File: //usr/share/opensearch-dashboards/node_modules/react-focus-lock/README.md
<div align="left">
<h1 align="center">REACT FOCUS LOCK</h1>
<img src="./assets/ackbar.png" alt="it-is-a-trap" width="200" height="200" align="right">
- browser friendly focus lock<br/>
- matching all your use cases<br/>
- trusted by best UI frameworks<br/>
- the thing Admiral Ackbar was talking about<br/>
<br/>
[](https://circleci.com/gh/theKashey/react-focus-lock/tree/master)
[](https://www.npmjs.com/package/react-focus-lock)
[](https://bundlephobia.com/result?p=react-focus-lock)
[](https://www.npmtrends.com/react-focus-lock)
<hr/>
</div>
It is a trap! We got your focus and will not let him out!
- Modal dialogs. You can not leave it with "Tab", ie do a "tab-out".
- Focused tasks. It will aways brings you back, as you can "lock" user inside a component.
- Any any other case, when you have to lock user _intention_ and _focus_, if that's what `a11y` is asking for.
### Trusted
Trusted by
[Atlassian AtlasKit](https://atlaskit.atlassian.com),
[ReachUI](https://ui.reach.tech/),
[SmoothUI](https://smooth-ui.smooth-code.com/),
[Storybook](https://storybook.js.org/)
and we will do our best to earn your trust too!
# Features
- no keyboard control, everything is done watching a __focus behavior__, not emulating it. Thus works always and everywhere.
- React __Portals__ support. Even if some data is in outer space - it is [still in lock](https://github.com/theKashey/react-focus-lock/issues/19).
- _Scattered_ locks, or focus lock groups - you can setup different isolated locks, and _tab_ from one to another.
- Controllable isolation level.
- variable size bundle. Uses sidecar to trim UI part to 1.5kb.
> 💡 __focus__ locks is only the first part, there are also __scroll lock__ and __text-to-speech__ lock
you have to use to really "lock" the user.
Try [react-focus-on](https://github.com/theKashey/react-focus-on) to archive everything above, assembled in the right order.
# How to use
Just wrap something with focus lock, and focus will be `moved inside` on mount.
```js
import FocusLock from 'react-focus-lock';
const JailForAFocus = ({onClose}) => (
<FocusLock>
You can not leave this form
<button onClick={onClose} />
</FocusLock>
);
```
Demo - https://codesandbox.io/s/5wmrwlvxv4.
# WHY?
From [MDN Article about accessible dialogs](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_dialog_role):
- The dialog must be properly labeled
- Keyboard __focus must be managed__ correctly
This one is about managing the focus.
I've got a good [article about focus management, dialogs and WAI-ARIA](https://medium.com/@antonkorzunov/its-a-focus-trap-699a04d66fb5).
# API
> FocusLock would work perfectly even with no props set.
FocusLock has few props to tune behavior, all props are optional:
- `disabled`, to disable(enable) behavior without altering the tree.
- `className`, to set the `className` of the internal wrapper.
- `returnFocus`, to return focus into initial position on unmount(not disable).
> By default `returnFocus` is disabled, so FocusLock will __not__ restore original focus on deactivation.
This is expected behavior for Modals, but it is better to implement it by your self. See [unmounting and focus management](https://github.com/theKashey/react-focus-lock#unmounting-and-focus-management) for details
- `persistentFocus=false`, requires any element to be focused. This also disables text selections inside, and __outside__ focus lock.
- `autoFocus=true`, enables or disables focusing into on Lock activation. If disabled Lock will blur an active focus.
- `noFocusGuards=false` disabled _focus guards_ - virtual inputs which secure tab index.
- `group='''` named focus group for focus scattering aka [combined lock targets](https://github.com/theKashey/vue-focus-lock/issues/2)
- `shards=[]` an array of `ref` pointing to the nodes, which focus lock should consider and a part of it. This is another way focus scattering.
- `whiteList=fn` you could _whitelist_ locations FocusLock should carry about. Everything outside it will ignore. For example - any modals.
- `as='div'` if you need to change internal `div` element, to any other. Use ref forwarding to give FocusLock the node to work with.
- `lockProps={}` to pass any extra props (except className) to the internal wrapper.
- `hasPositiveIndices=false` to support a focus lock behavior when any elements tabIndex greater than 0.
### Focusing in OSX (Safari/Firefox) is strange!
By default `tabbing` in OSX `sees` only controls, but not links or anything else `tabbable`. This is system settings, and Safari/Firefox obey.
Press Option+Tab in Safari to loop across all tabbables, or change the Safari settings. There is no way to _fix_ Firefox, unless change system settings (Control+F7). See [this issue](https://github.com/theKashey/react-focus-lock/issues/24) for more information.
## Set up
### Requirements
- version 1x is React 15/16 compatible
- version 2+ requires React 16.8+ (hooks)
### Import
`react-focus-lock` exposed __3 entry points__: for the classical usage, and a _sidecar_ one.
#### Default usage
- 4kb, `import FocusLock from 'react-focus-lock` would give you component you are looking for.
#### Separated usage
Meanwhile - you dont need any focus related logic until it's needed.
Thus - you may defer that logic till Lock activation and move all related code to a _sidecar_.
- UI, __1.5kb__, `import FocusLockUI from 'react-focus-lock/UI` - a DOM part of a lock.
- Sidecar, 3.5kb, `import Sidecar from 'react-focus-lock/sidecar` - which is the real focus lock.
```js
import FocusLockUI from "react-focus-lock/UI";
import {sidecar} from "use-sidecar";
// prefetch sidecar. data would be loaded, but js would not be executed
const FocusLockSidecar = sidecar(
() => import(/* webpackPrefetch: true */ "react-focus-lock/sidecar")
);
<FocusLockUI
disabled={this.state.disabled}
sideCar={FocusLockSidecar}
>
{content}
</FocusLockUI>
```
That would split FocusLock into two pieces, reducing app size and improving the first load.
The cost of focus-lock is just 1.5kb!
> Saved 3.5kb?! 🤷♂️ 3.5kb here and 3.5kb here, and your 20mb bundle is ready.
# Autofocus
Use when you cannot use the native `autoFocus` prop - because you only want to autofocus once the Trap has been activated
- prop `data-autofocus` on the element.
- prop `data-autofocus-inside` on the element to focus on something inside.
- `AutoFocusInside` component, as named export of this library.
```js
import FocusLock, { AutoFocusInside } from 'react-focus-lock';
<FocusLock>
<button>Click</button>
<AutoFocusInside>
<button>will be focused</button>
</AutoFocusInside>
</FocusLock>
// is the same as
<FocusLock>
<button>Click</button>
<button data-autofocus>will be focused</button>
</FocusLock>
```
If there is more than one auto-focusable target - the first will be selected.
If it is a part of radio group, and __rest of radio group element are also autofocusable__(just put them into AutoFocusInside) -
checked one fill be selected.
`AutoFocusInside` will work only on Lock activation, and does nothing, then used outside of the lock.
You can use `MoveFocusInside` to move focus inside with or without lock.
```js
import { MoveFocusInside } from 'react-focus-lock';
<MoveFocusInside>
<button>will be focused</button>
</MoveFocusInside>
```
# Portals
Use focus scattering to handle portals
- using `groups`. Just create a few locks (only one could be active) with a same group name
```js
const PortaledElement = () => (
<FocusLock group="group42" disabled={true}>
// "discoverable" portaled content
</FocusLock>
);
<FocusLock group="group42">
// main content
</FocusLock>
```
- using `shards`. Just pass all the pieces to the "shards" prop.
```js
const PortaledElement = () => (
<div ref={ref}>
// "discoverable" portaled content
</div>
);
<FocusLock shards={[ref]}>
// main content
</FocusLock>
```
- without anything. FocusLock will not prevent focusing portaled element, but will not include them in to tab order
```js
const PortaledElement = () => (
<div>
// NON-"discoverable" portaled content
</div>
);
<FocusLock shards={[ref]}>
// main content
<PortaledElement />
</FocusLock>
```
### Using your own `Components`
You may use `as` prop to change _what_ Focus-Lock will render around `children`.
```js
<FocusLock as="section">
<button>Click</button>
<button data-autofocus>will be focused</button>
</FocusLock>
<FocusLock as={AnotherComponent} lockProps={{anyAnotherComponentProp: 4}}>
<button>Click</button>
<span>Hello there!</span>
</FocusLock>
```
### Guarding
As you may know - FocusLock is adding `Focus Guards` before and after lock to remove some side effects, like page scrolling.
But `shards` will not have such guards, and it might be not so cool to use them - for example if no `tabbable` would be
defined after shard - you will tab to the browser chrome.
You may wrap shard with `InFocusGuard` or just drop `InFocusGuard` here and there - that would solve the problem.
```js
import {InFocusGuard} from 'react-focus-lock';
// wrap with
<InFocusGuard>
<button />
</InFocusGuard>
// place before and after
<InFocusGuard />
<button />
<InFocusGuard />
```
InFocusGuards would be active(tabbable) only when tabble, it protecting, is focused.
#### Removing Tailing Guard
If only your modal is the last tabble element on the body - you might remove the Tailing Guard,
to allow user _tab_ into address bar.
```js
<InFocusGuard/>
<button />
// there is no "tailing" guard :)
```
# Unmounting and focus management
- In case FocusLock has `returnFocus` enabled, and it's going to be unmounted - focus will be returned after zero-timeout.
- In case `returnFocus` is set to `false`, and you are going to control focus change on your own - keep in mind
>> React will first call Parent.componentWillUnmount, and next Child.componentWillUnmount
This means - Trap will be still active by the time you _may_ want move(return) focus on componentWillUnmount. Please deffer this action with a zero-timeout.
Similarly, if you are using the `disabled` prop to control FocusLock, you will need a zero-timeout to correctly restore focus.
```
<FocusLock
disabled={isFocusLockDisabled}
onDeactivation={() => {
// Without the zero-timeout, focus will likely remain on the button/control
// you used to set isFocusLockDisabled = true
window.setTimeout(() => myRef.current.focus(), 0);
}
>
```
## Return focus with no scroll
> read more at the [issue #83](https://github.com/theKashey/react-focus-lock/issues/83) or
[mdn article](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus).
To return focus, but without _jumpy_ page scroll returning a focus you might specify a focus option
```js
<FocusLock
returnFocus={{ preventScroll: false }} // working not in all browsers
>
```
Not supported by Edge and Safari.
# Not only for React
Uses [focus-lock](https://github.com/theKashey/focus-lock/) under the hood. It does also provide support for Vue.js and Vanilla DOM solutions
# Warning!
Two different _focus-lock-managers_ or even different version of a single one, active
simultaneously will FIGHT!
__Focus-lock will surrender__, as long any other focus management library will not.
## Focus fighting
You may wrap some render branch with `FreeFocusInside`, and react-focus-lock __will ignore__
any focus inside marked node, thus landing a peace.
```js
import { FreeFocusInside } from 'react-focus-lock';
<FreeFocusInside>
<div id="portal-for-modals">
in this div i am going to portal my modals, dont fight with them please
</div>
</FreeFocusInside>
```
Even the better is to `whiteList` FocusLock areas - for example "you should handle only React Stuff in React Root"
```js
<FocusLock whiteList={node => document.getElementById('root').contains(node)}>
...
</FocusLock>
```
PS: __please use webpack or yarn resolution for force one version of react-focus-lock used__
> webpack.conf
```js
resolve: {
alias: {
'react-focus-lock': path.resolve(path.join(__dirname, './node_modules/react-focus-lock'))
...
```
# More
To create a "right" modal dialog you have to:
- manage a focus. Use this library
- block document scroll. Use [react-scroll-locky](https://github.com/theKashey/react-scroll-locky).
- hide everything else from screen readers. Use [aria-hidden](https://github.com/theKashey/aria-hidden)
You may use [react-focus-on](https://github.com/theKashey/react-focus-on) to achieve everything above, assembled in the right order.
# Licence
MIT