{"id":18368769,"url":"https://github.com/greena13/react-ref-manager","last_synced_at":"2025-04-06T17:31:52.433Z","repository":{"id":57343402,"uuid":"118424043","full_name":"greena13/react-ref-manager","owner":"greena13","description":"Manage, focus and scroll to Elements or React components (refs)","archived":false,"fork":false,"pushed_at":"2018-02-11T09:04:40.000Z","size":84,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-06T08:35:48.918Z","etag":null,"topics":["dom","focus","react","react-components","reactjs","scrolling"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/greena13.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-22T07:49:53.000Z","updated_at":"2023-08-26T16:38:25.000Z","dependencies_parsed_at":"2022-09-16T03:01:50.443Z","dependency_job_id":null,"html_url":"https://github.com/greena13/react-ref-manager","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greena13%2Freact-ref-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greena13%2Freact-ref-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greena13%2Freact-ref-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greena13%2Freact-ref-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/greena13","download_url":"https://codeload.github.com/greena13/react-ref-manager/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247522428,"owners_count":20952546,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dom","focus","react","react-components","reactjs","scrolling"],"created_at":"2024-11-05T23:27:22.621Z","updated_at":"2025-04-06T17:31:52.092Z","avatar_url":"https://github.com/greena13.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Ref Manager\n\n[![npm](https://img.shields.io/npm/dm/react-ref-manager.svg)]()\n[![GitHub license](https://img.shields.io/github/license/greena13/react-ref-manager.svg)](https://github.com/greena13/react-ref-manager/blob/master/LICENSE)\n\nManage, focus and scroll to `Element`s or React `Component`s (refs) in a standard manner.\n\n## Overview\n\n`react-ref-manager` is a standard way of storing references to elements created by React applications and cuts down on boilerplate code for focusing and scrolling to those refs.\n\n`react-ref-manager` is *not* a replacement for React's ref generation or DOM management, nor is it a replacement for the normal focus management provided by the browser.\n\nReact renders to the DOM and generates refs, which `react-ref-manager` stores and provides a high-level API for focusing and scrolling, which wrap the browser's API.\n\n## Basic Usage\n\n```javascript\nimport RefManager, { FocusDirection } from 'react-ref-manager';\n\nclass MyComponent extends Component {\n    constructor(props, context) {\n        super(props, context);\n\n        this.handleKeyPress = this.handleKeyPress.bind(this);\n\n        /**\n          * Create a new Ref Manager instance\n          */\n\n        this.refManager = new RefManager();\n      }\n\n    render() {\n        const { items } = this.props;\n\n        return (\n          \u003cdiv onKeyPress={ this.handleKeyPress }\u003e\n\n                /**\n                  * Assign refs to important document elements\n                  */\n\n                \u003cdiv ref={ (c) =\u003e this.refManager.set('toolbar', c) } tabIndex={-1} /\u003e\n\n                {\n                    items.map( ({ name }, index) =\u003e {\n                        return(\n\n                            /**\n                              * Assign refs to iterable document elements\n                              */\n\n                            \u003cdiv ref={ (c) =\u003e this.refManager.set('items', index, c) tabIndex={-1}\u003e\n                                { name }\n                            \u003c/div\u003e\n                        )\n                    }\n                }\n\n                \u003cdiv ref={ (c) =\u003e this.refManager.set('footer') } tabIndex={-1} /\u003e\n          \u003c/div\u003e\n        );\n      }\n\n    handleKeyPress({ key }) {\n        const refManager = this.refManager;\n\n        if (key = 't') {\n\n            /**\n              * Focus elements in the DOM\n              */\n\n            refManager.focusById('toolbar');\n\n        } else if (key = 'b') {\n\n            /**\n              * Scroll to elements\n              */\n\n            refManager.scrollToById('toolbar');\n\n        } else if (parseInt(key) {\n\n            /**\n              * Jump to the start of iterable collections, and continue to move\n              * through them by repeated key presses\n              */\n\n            refManager.focusNextById('items', { direction: FocusDirection.DOWN });\n\n        } else if (key = 'ArrowDown') {\n\n            /**\n              * Iterate through collections\n              */\n\n            refManager.focusNextById('items', { direction: FocusDirection.DOWN });\n\n        } else if (key = 'ArrowUp') {\n            refManager.focusNextById('items', { direction: FocusDirection.UP } );\n        }\n    }\n}\n\n```\n\n## Installation\n\n```bash\nnpm install react-ref-manager --save\n```\n\n## API\n\n#### set()\n\nStores a ref for later use.\n\nThis method should generally be called in React's `render` method, using React `Component`'s `ref` attribute.\n\nYou can pass either a single id, or an optional second item id for collections, followed by the ref to store:\n\n```javascript\n// Using a single id\nthis.refManager.set('toolbar', ref)\n\n// Using a collection and item id\nthis.refManager.set('items', index, ref)\n```\n\n`react-ref-manager` does not support any deeper referencing than a collection and item id. If you have elements that resemble a grid, store them as a flat list and use `focusNext`'s options to correctly move focus between them.\n\n#### get()\n\nRetrieves a ref previously stored using `set()`.\n\nYou can pass either a single id, or an optional second item id for collections:\n\n```javascript\n// Using a single id\nthis.refManager.get('toolbar')\n\n// Using a collection and item id\nthis.refManager.get('items', index)\n```\n\n### Focusing a ref\n\n#### FocusDirection\n\nA class of constants exported from `react-ref-manager` used to denote directions to iterate through collections. Available values are:\n\n* `FocusDirection.LEFT`\n* `FocusDirection.RIGHT`\n* `FocusDirection.DOWN`\n* `FocusDirection.UP`\n\n```javascript\nimport { FocusDirection } from 'react-ref-manager';\n```\n\n#### Focus objects\n\nFocus objects are returned by all of the `focus*()` methods. A focus object has the following attributes:\n\n* `ref` - The ref that was last focused. `null` when the ref cannot be found in the `RefManager` instance.\n* `DOMRef` - The ref pointing to the actual element in the DOM that was focused. For standard React elements (`\u003cdiv\u003e`, `\u003cspan\u003e`, `\u003cinput\u003e` etc), this is the same as `ref`. For custom React components that don't define a focus() method, this is the ref to the backing elements in the DOM. `null` when the ref was not found in the DOM.\n* `id` - The `itemId` option passed when a ref was last focused.\n* `collectionId` - The `collectionId` option passed when a ref was last focused.\n* `context` - The value of `context` at the time the ref was last focused. You can store any information about when the ref was focused that you later want to access, in here.\n* `applied` - Boolean that is `true` if the focus attempt was successful. If `false`, see the `ref` and `DOMRef` values to determine whether the failure was because the ref could not be found in the `RefManager` instance, or in the DOM.\n\n### Storing and retrieving refs\n\n#### focus()\n\nFocuses a ref passed as the first argument. Accepts a hash of options as the second argument.\n\nSupported options are:\n\n* `id`: The string item `id` of the ref to be focused. This will appear in the focus object returned by this method and `getCurrentFocus()`.\n* `collectionId`: (Optional) The string `collectionId` of the ref to be focused, when it is an item in a collection of refs.\n* `context`: (Optional) Any contextual information that you want to record about the ref being focused, that will be useful later.\n\nReturns a focus object.\n\n```javascript\nconst toolbarRef = refManager.get('toolbar');\nrefManager.focus(toolbarRef, { id: 'toolbar' });\n```\n\n#### focusById()\n\nFocuses a ref in the browser identified by an `id` and (optionally) `collectionId`, and updates the currently focused ref in the `RefManager` instance it's called on.\n\nAn hash of options can be passed as the final argument, but is not required.\n\n`focusById()` supports all options available in `focus()`, but `id` and `collectionId` are automatically set for you.\n\nReturns a focus object.\n\n```javascript\n// Using a single id\nrefManager.focusById('toolbar');\n\n// Using a collection and item id\nrefManager.focusById('items', index);\n\n// Using options\nrefManager.focusById('items', { context: { firstFocus: true } });\nrefManager.focusById('items', index, { context: { firstFocus: true } });\n```\n\n#### focusNext()\n\nFocuses the next item in a collection of refs passed as the first argument. Accepts an options hash as the second argument.\n\nIf no item in a collection of refs is currently focused, the first item is focused. If the last item in the collection is already focused, the behaviour depends on the `yWrap` and `xWrap` options.\n\nAccepted options:\n\n* `direction`: (Default: `FocusDirection.RIGHT`) One of the `FocusDirection` values that determines in what direction the collection should be iterated over.\n* `indexes`: An array of the collection keys that should be used to iterate over the collection items. The default value is the full set of keys in the collection pointed to by the provided `collectionId`, in the order that those items were added to the collection.\n* `context`: Any contextual information that you want to record about the ref being focused.\n* `collectionWidth`: (Default: 1) number of items in each row of the collection. Used for iterating over 2 dimensional lists (grids of items).\n* `yWrap`: (Default: `false`) whether to allow wrapping of the focused item when the iteration reaches the top or bottom of the collection. i.e. If the `yWrap` is `false` and the user iterates to the bottom of a grid and presses down once more, the focus will not move. If `yWrap` is `true`, the same situation will focus the item in the top row, in that same column.\n* `xWrap`: (Default: `false`) whether to allow wrapping of the focused item when the iteration reaches the start or end of a row in the collection. i.e. If the `xWrap` is `false` and the user iterates to the right of a grid and presses right once more, the focus will not move. If `xWrap` is `true`, the same situation will focus the first item in the same row.\n\nReturns a focus object.\n\n```javascript\nconst usersRef = this.refManager.get('users');\n\nthis.refManager.focusNext(usersRef, {\n    direction: FocusDirection.RIGHT,\n    xWrap: true\n});\n```\n\n#### focusNextById()\n\nFocuses the next ref in a collection pointed to by the provided `collectionId`. Accepts a hash of options as the second argument.\n\n`focusNextById()` accepts all the options that `focusNext()` does, except `collectionId` is automatically set for you.\n\nReturns a focus object.\n\n```javascript\nthis.refManager.focusNextById('users', {\n    direction: FocusDirection.RIGHT,\n    xWrap: true\n});\n```\n\n### Working with the current focus\n\n#### isFocusedRefInDOM()\n\nReturns whether the ref currently considered focused by `react-ref-manager` is mounted in the DOM and the equal to `document.activeElement`.\n\n#### RefManager.refIsFocused()\n\nThis is a class method.\n\nReturns whether the ref passed as its only argument is currently in the DOM and is equal to`document.activeElement`.\n\nThe ref does not have to have been focused using an instance of `RefManager`.\n\n#### getCurrentFocus()\n\nReturns the current focus object. The focus object is updated every time one of the `focus*` methods is used. The focus object is an empty object (`{}`) before any `focus*` methods are called.\n\n#### setCurrentFocus()\n\nSets the current focus object *without* actually focusing the ref in the DOM. Useful if you need to focus a ref externally for whatever reason and need to update `react-ref-manager`.\n\nThis method still calls any change listeners that may have been added using `addFocusChangeListener()`.\n\n\n#### RefManager.focus()\n\nThis is a class method.\n\nFocuses the ref passed as it first argument. This method does *not* update any `RefManager` instance's focus object.\n\nReturns the ref pointing to the actual element in the DOM that was focused. For standard React elements (`\u003cdiv\u003e`, `\u003cspan\u003e`, `\u003cinput\u003e` etc), this is the same as the `ref` passed as the first argument. For custom React components thad don't define a focus() method, this is the ref to the backing elements in the DOM. Alternatively, it returns `null` when the `ref` was `undefined` or was not found in the DOM.\n\n### Listening to changes in focus\n\n#### addFocusChangeListener()\n\nAccepts a function that is called every time the current focus is changed through the  `RefManager` instance it is called on. The function is called with the previous focus object and the current focus object as its first and second arguments.\n\n`addFocusChangeListener()` returns the function it is passed, so that it may be easily unbound, later on.\n\n```javascript\ncomponentDidMount(){\n    this.focusListener = this.refManager.addFocusChangeListener((prevFocus, nextFocus) =\u003e {\n        if (nextFocus.context === 'users') {\n              this.setState({\n                    focusedUserId: nextFocus.id\n              });\n        } else {\n              this.setState({\n                    focusedUserId: null\n              });\n        }\n    });\n}\n```\n\n#### removeFocusChangeListener()\n\nRemoves a focus change listener that has been previously registered with `addFocusChangeListener()`. It accepts the listener to remove as the first argument.\n\n```javascript\ncomponentWillUnmount(){\n    this.refManager.removeFocusChangeListener(this.focusListener);\n}\n```\n\n### Scrolling\n\n#### Scroll objects\n\nScroll objects are returned by all of the `scroll*()` methods. A scroll object has the following attributes:\n\n* `ref` - The ref that was scrolled to or `null` when the ref cannot be found in the `RefManager` instance.\n* `DOMRef` - The ref pointing to the actual element in the DOM that was scrolled to. For standard React elements (`\u003cdiv\u003e`, `\u003cspan\u003e`, `\u003cinput\u003e` etc), this is the same as `ref`. For custom React components that don't define a focus() method, this is the ref to the backing elements in the DOM. `null` is returned instead when the ref was not found in the DOM.\n* `id` - The `id` of the ref that was scrolled to.\n* `collectionId` - The `collectionId` value passed as an argument when scrolling to the ref.\n* `applied` - Boolean that is true if the scroll attempt was successful. If `false`, see the `ref` and `DOMRef` values to determine whether the failure was because the ref could not be found in the `RefManager` instance, or in the DOM.\n\n#### RefManager.scrollTo()\n\nThis is a class method.\n\nScrolls to the ref passed to it as its first argument.\n\nIt accepts an options hash as the second argument that is passed straight to [scrollIntoView](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView).\n\nReturns the ref that was scrolled to (which may be different to the ref passed as an argument in the case of custom React elements that don't define a scrollIntoView() method), or `null` if the ref could not be located in the DOM.\n\n#### scrollToById()\n\nScrolls to a ref by the `id` and (optionally) `collectionId` that was used when it was registered using `set()`.\n\nAn options hash may be passed as the final argument. These options are passed straight to [scrollIntoView](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView).\n\nWhen the ref is a custom React component that doesn't define a scrollIntoView() method, it's backing DOM element ref will be located, and that will be used to scroll to.\n\nReturns a scroll object.\n\n```javascript\nrefManager.scrollToById('toolbar');\n```\n\n#### scrollToFocused()\n\nScrolls to the ref that was last focused, if there is one.\n\nIt accepts an options hash as its only argument that is passed straight to [scrollIntoView](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView).\n\nReturns a scroll object.\n\n## Contributions\n\nAll contributions are welcome and encouraged.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgreena13%2Freact-ref-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgreena13%2Freact-ref-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgreena13%2Freact-ref-manager/lists"}