focus-trap 7.6.5 → 7.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -1
- package/README.md +225 -48
- package/dist/focus-trap.esm.js +1 -1
- package/dist/focus-trap.esm.js.map +1 -1
- package/dist/focus-trap.esm.min.js +1 -1
- package/dist/focus-trap.esm.min.js.map +1 -1
- package/dist/focus-trap.js +1 -1
- package/dist/focus-trap.js.map +1 -1
- package/dist/focus-trap.min.js +1 -1
- package/dist/focus-trap.min.js.map +1 -1
- package/dist/focus-trap.umd.js +1 -1
- package/dist/focus-trap.umd.js.map +1 -1
- package/dist/focus-trap.umd.min.js +1 -1
- package/dist/focus-trap.umd.min.js.map +1 -1
- package/package.json +29 -29
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 7.6.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- dcd4ae9: Update `tabbable` dependency to [6.3.0](https://github.com/focus-trap/tabbable/blob/master/CHANGELOG.md#630) for new `displayCheck` option.
|
|
8
|
+
|
|
3
9
|
## 7.6.5
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
|
@@ -245,7 +251,6 @@
|
|
|
245
251
|
There may be cases where we don't want to focus the first tabbable element when a focus trap activates.
|
|
246
252
|
|
|
247
253
|
Examples use-cases:
|
|
248
|
-
|
|
249
254
|
- Modals/dialogs
|
|
250
255
|
- On mobile devices where "tabbing" doesn't make sense without a connected Bluetooth keyboard
|
|
251
256
|
|
package/README.md
CHANGED
|
@@ -89,54 +89,231 @@ Returns a new focus trap on `element` (one or more "containers" of tabbable node
|
|
|
89
89
|
|
|
90
90
|
> A focus trap must have at least one container with at least one tabbable/focusable node in it to be considered valid. While nodes can be added/removed at runtime, with the trap adjusting to added/removed tabbable nodes, **an error will be thrown** if the trap ever gets into a state where it determines none of its containers have any tabbable nodes in them *and* the `fallbackFocus` option does not resolve to an alternate node where focus can go.
|
|
91
91
|
|
|
92
|
-
####
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
92
|
+
#### Trap Configuration Options
|
|
93
|
+
|
|
94
|
+
##### onActivate
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
() => void
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
A function that will be called **before** sending focus to the target element upon activation.
|
|
101
|
+
|
|
102
|
+
##### onPostActivate
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
() => void
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
A function that will be called **after** sending focus to the target element upon activation **unless** initial focus is delayed because the [delayInitialFocus](#delayinitialfocus) is true (default).
|
|
109
|
+
|
|
110
|
+
##### onPause
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
() => void
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
A function that will be called immediately after the trap's state is updated to be paused.
|
|
117
|
+
|
|
118
|
+
##### onPostPause
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
() => void
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
A function that will be called after the trap has been completely paused and is no longer managing/trapping focus.
|
|
125
|
+
|
|
126
|
+
##### onUnpause
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
() => void
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
A function that will be called immediately after the trap's state is updated to be active again, but prior to updating its knowledge of what nodes are tabbable within its containers, and prior to actively managing/trapping focus.
|
|
133
|
+
|
|
134
|
+
##### onPostUnpause
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
() => void
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
A function that will be called after the trap has been completely unpaused and is once again managing/trapping focus.
|
|
141
|
+
|
|
142
|
+
Note that if [delayInitialFocus](#delayinitialfocus) is true, this handler will be called **before** focus is re-set on the initial focused node.
|
|
143
|
+
|
|
144
|
+
##### checkCanFocusTrap
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
(containers: Array<HTMLElement | SVGElement>) => Promise<void>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Animated dialogs have a small delay between when `onActivate` is called and when the focus trap is focusable. `checkCanFocusTrap` expects a promise to be returned. When that promise settles (resolves or rejects), focus will be sent to the first tabbable node (in tab order) in the focus trap (or the node configured in the `initialFocus` option).
|
|
151
|
+
|
|
152
|
+
##### onDeactivate
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
() => void
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
A function that will be called **before** returning focus to the node that had focus prior to activation (or configured with the `setReturnFocus` option) upon deactivation.
|
|
159
|
+
|
|
160
|
+
##### onPostDeactivate
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
() => void
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
A function that will be called after the trap is deactivated, after `onDeactivate`. If the `returnFocus` deactivation option was set, it will be called **after** returning focus to the node that had focus prior to activation (or configured with the `setReturnFocus` option) upon deactivation; otherwise, it will be called after deactivation completes.
|
|
167
|
+
|
|
168
|
+
##### checkCanReturnFocus
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
(trigger: HTMLElement | SVGElement) => Promise<void>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
An animated trigger button will have a small delay between when `onDeactivate` is called and when the focus is able to be sent back to the trigger. `checkCanReturnFocus` expects a promise to be returned. When that promise settles (resolves or rejects), focus will be sent to to the node that had focus prior to the activation of the trap (or the node configured in the `setReturnFocus` option).
|
|
175
|
+
|
|
176
|
+
##### initialFocus
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
HTMLElement | SVGElement | string | false | undefined | (() => HTMLElement | SVGElement | string | false | undefined)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
By default (when `undefined` or the function returns `undefined`), when a focus trap is activated, the active element will receive focus if it's in the trap, otherwise, the first element in the focus trap's tab order will receive focus. With this option you can specify a different element to receive that initial focus. Can be a DOM node, or a selector string (which will be passed to `document.querySelector()` to find the DOM node), or a function that returns any of these. You can also set this option to `false` (or to a function that returns `false`) to prevent any initial focus at all when the trap activates.
|
|
183
|
+
|
|
184
|
+
- Setting this option to `false` (or a function that returns `false`) will prevent the `fallbackFocus` option from being used.
|
|
185
|
+
- If the option resolves to a non-focusable node (e.g. one that exists, but is hidden), the default behavior will be used (as though the option weren't set at all).
|
|
186
|
+
- If the option resolves to a non-existent node, an exception will be thrown.
|
|
187
|
+
- If the option resolves to a valid selector string (directly set, or returned from a function), but the selector doesn't match a node, the trap will fall back to the `fallbackFocus` node option. If that option also fails to yield a node, an exception will be thrown.
|
|
188
|
+
- If the option resolves to `undefined` (i.e. not set or function returns `undefined`), the default behavior will be used.
|
|
189
|
+
- ⚠️ See warning below about **[Shadow DOM](#shadow-dom)** and selector strings.
|
|
190
|
+
|
|
191
|
+
##### fallbackFocus
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
HTMLElement | SVGElement | string | () => HTMLElement | SVGElement | string
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
By default, an error will be thrown if the focus trap contains no elements in its tab order. With this option you can specify a fallback element to programmatically receive focus if no other tabbable elements are found. For example, you may want a popover's `<div>` to receive focus if the popover's content includes no tabbable elements. *Make sure the fallback element has a negative `tabindex` so it can be programmatically focused.* The option value can be a DOM node, a selector string (which will be passed to `document.querySelector()` to find the DOM node), or a function that returns any of these.
|
|
198
|
+
|
|
199
|
+
- If `initialFocus` is `false` (or a function that returns `false`), this function will not be called when the trap is activated, and no element will be initially focused. This function may still be called while the trap is active if things change such that there are no longer any tabbable nodes in the trap.
|
|
200
|
+
- ⚠️ See warning below about **[Shadow DOM](#shadow-dom)** and selector strings.
|
|
201
|
+
|
|
202
|
+
##### escapeDeactivates
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
boolean | (e: KeyboardEvent) => boolean
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Default: `true`. If `false` or returns `false`, the `Escape` key will not trigger deactivation of the focus trap. This can be useful if you want to force the user to make a decision instead of allowing an easy way out. Note that if a function is given, it's only called if the ESC key was pressed.
|
|
209
|
+
|
|
210
|
+
##### clickOutsideDeactivates
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
boolean | (e: MouseEvent | TouchEvent) => boolean
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
If `true` or returns `true`, a click outside the focus trap will immediately deactivate the focus trap and allow the click event to do its thing (i.e. to pass-through to the element that was clicked). This option **takes precedence** over `allowOutsideClick` when it's set to `true`. Default: `false`.
|
|
217
|
+
|
|
218
|
+
- If a function is provided, it will be called up to **twice** (but only if the click occurs *outside* the trap's containers): First on the `mousedown` (or `touchstart` on mobile) event and, if `true` was returned, again on the `click` event. It will get the same node each time, and it's recommended that the returned value is also the same each time. Be sure to check the event type if the double call is an issue in your code.
|
|
219
|
+
- ⚠️ If you're using a password manager such as 1Password, where the app adds a clickable icon to all fillable fields, you should avoid using this option, and instead use the `allowOutsideClick` option to better control exactly when the focus trap can be deactivated. The clickable icons are usually positioned absolutely, floating on top of the fields, and therefore *not* part of the container the trap is managing. When using the `clickOutsideDeactivates` option, clicking on a field's 1Password icon will likely cause the trap to be unintentionally deactivated.
|
|
220
|
+
|
|
221
|
+
##### allowOutsideClick
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
boolean | (e: MouseEvent | TouchEvent) => boolean
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
If set and is or returns `true`, a click outside the focus trap will not be prevented (letting focus temporarily escape the trap, without deactivating it), even if `clickOutsideDeactivates=false`. Default: `false`.
|
|
228
|
+
|
|
229
|
+
- If this is a function, it will be called up to **twice** on every click (but only if the click occurs *outside* the trap's containers): First on `mousedown` (or `touchstart` on mobile), and then on the actual `click` if the function returned `true` on the first event. Be sure to check the event type if the double call is an issue in your code.
|
|
230
|
+
- 💡 When `clickOutsideDeactivates=true`, this option is **ignored** (i.e. if it's a function, it will not be called).
|
|
231
|
+
- Use this option to control if (and even which) clicks are allowed outside the trap in conjunction with `clickOutsideDeactivates=false`.
|
|
232
|
+
|
|
233
|
+
##### returnFocusOnDeactivate
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
boolean
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Default: `true`. If `false`, when the trap is deactivated, focus will *not* return to the element that had focus before activation.
|
|
240
|
+
|
|
241
|
+
- 💬 When using this option in conjunction with `clickOutsideDeactivates=true`:
|
|
242
|
+
- If `returnFocusOnDeactivate=true` and the outside click causing deactivation is on a focusable element, focus will __not__ return to that element; instead, it will return to the node focused just before activation.
|
|
243
|
+
- If `returnFocusOnDeactivate=false` and the outside click is on a focusable node, focus will __remain__ on that node instead of the node focused just before activation. If the outside click is on a non-focusable node, then "nothing" will have focus post-deactivation.
|
|
244
|
+
|
|
245
|
+
##### setReturnFocus
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
HTMLElement | SVGElement | string | (previousActiveElement: HTMLElement | SVGElement) => HTMLElement | SVGElement | string | false
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
By default, on **deactivation**, if `returnFocusOnDeactivate=true` (or if `returnFocus=true` in the [deactivation options](#trapdeactivate)), focus will be returned to the element that was focused just before activation. With this option, you can specify another element to programmatically receive focus after deactivation. It can be a DOM node, a selector string (which will be passed to `document.querySelector()` to find the DOM node **upon deactivation**), or a function that returns any of these to call **upon deactivation** (i.e. the selector and function options are only executed at the time the trap is deactivated). Can also be `false` (or return `false`) to leave focus where it is at the time of deactivation.
|
|
252
|
+
|
|
253
|
+
- 💬 Using the selector or function options is a good way to return focus to a DOM node that may not exist at the time the trap is activated.
|
|
254
|
+
- ⚠️ See warning below about **[Shadow DOM](#shadow-dom)** and selector strings.
|
|
255
|
+
|
|
256
|
+
##### preventScroll
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
boolean
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
By default, focus() will scroll to the element if not in viewport. It can produce unintended effects like scrolling back to the top of a modal. If set to `true`, no scroll will happen.
|
|
263
|
+
|
|
264
|
+
##### delayInitialFocus
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
boolean
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Default: `true`. Delays the autofocus to the next execution frame when the focus trap is activated. This prevents elements within the focusable element from capturing the event that triggered the focus trap activation.
|
|
271
|
+
|
|
272
|
+
🔺 Note that when this option is `true` (default), it means the initial element to be focused will not be focused until **after** [onPostActivate](#onpostactivate) or [onPostUnpause](#onpostunpause) are called.
|
|
273
|
+
|
|
274
|
+
##### document
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
Document
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Default: `window.document`. Document where the focus trap will be active. This enables the use of FocusTrap [inside an iFrame](https://focus-trap.github.io/focus-trap/#demo-in-iframe).
|
|
281
|
+
|
|
282
|
+
- ⚠️ Note that FocusTrap will be unable to trap focus outside the iFrame if you configure this option to be the iFrame's document. It will only trap focus _inside_ of it (as the demo shows). If you want to trap focus _outside_ as well, then your FocusTrap must be configured on an element that [contains the iFrame](https://focus-trap.github.io/focus-trap/#demo-iframe).
|
|
283
|
+
|
|
284
|
+
##### tabbableOptions
|
|
285
|
+
|
|
286
|
+
[Tabbable options](https://github.com/focus-trap/tabbable#common-options) configurable on FocusTrap (all the *common options*).
|
|
287
|
+
|
|
288
|
+
- ⚠️ See notes about **[testing in JSDom](#testing-in-jsdom)** (e.g. using Jest).
|
|
289
|
+
|
|
290
|
+
##### trapStack
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
Array<FocusTrap>
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Define the global trap stack. This makes it possible to share the same stack in multiple instances of `focus-trap` in the same page such that auto-activation/pausing of traps is properly coordinated among all instances as activating a trap when another is already active should result in the other being auto-paused. By default, each instance will have its own internal stack, leading to conflicts if they each try to trap the focus at the same time.
|
|
297
|
+
|
|
298
|
+
##### isKeyForward
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
(event: KeyboardEvent) => boolean
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Determines if the given keyboard event is a "tab forward" event that will move the focus to the next trapped element in tab order. Defaults to the `TAB` key. Use this to override the trap's behavior if you want to use arrow keys to control keyboard navigation within the trap, for example. Also see `isKeyBackward()` option.
|
|
305
|
+
|
|
306
|
+
- ⚠️ Using this option will not automatically prevent use of the `TAB` key as the browser will continue to respond to it by moving focus forward because that's what using the `TAB` key does in a browser, but it will no longer respect the trap's container edges as it normally would. You will need to add your own `keydown` handler to call `preventDefault()` on a `TAB` key event if you want to completely suppress the use of the `TAB` key.
|
|
307
|
+
|
|
308
|
+
##### isKeyBackward
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
(event: KeyboardEvent) => boolean
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Determines if the given keyboard event is a "tab backward" event that will move the focus to the previous trapped element in tab order. Defaults to the `SHIFT+TAB` key. Use this to override the trap's behavior if you want to use arrow keys to control keyboard navigation within the trap, for example. Also see `isKeyForward()` option.
|
|
315
|
+
|
|
316
|
+
- ⚠️ Using this option will not automatically prevent use of the `SHIFT+TAB` key as the browser will continue to respond to it by moving focus backward because that's what using the `SHIFT+TAB` key sequence does in a browser, but it will no longer respect the trap's container edges as it normally would. You will need to add your own `keydown` handler to call `preventDefault()` on a `TAB` key event if you want to completely suppress the use of the `SHIFT+TAB` key sequence.
|
|
140
317
|
|
|
141
318
|
#### Shadow DOM
|
|
142
319
|
|
package/dist/focus-trap.esm.js
CHANGED