focus-trap 6.4.0 → 6.6.1
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 +53 -0
- package/README.md +53 -47
- package/dist/focus-trap.esm.js +88 -32
- package/dist/focus-trap.esm.js.map +1 -1
- package/dist/focus-trap.esm.min.js +2 -2
- package/dist/focus-trap.esm.min.js.map +1 -1
- package/dist/focus-trap.js +88 -32
- package/dist/focus-trap.js.map +1 -1
- package/dist/focus-trap.min.js +2 -2
- package/dist/focus-trap.min.js.map +1 -1
- package/dist/focus-trap.umd.js +88 -32
- package/dist/focus-trap.umd.js.map +1 -1
- package/dist/focus-trap.umd.min.js +2 -2
- package/dist/focus-trap.umd.min.js.map +1 -1
- package/index.d.ts +62 -13
- package/index.js +82 -22
- package/package.json +27 -26
package/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { tabbable, isFocusable } from 'tabbable';
|
|
2
2
|
|
|
3
|
-
let activeFocusDelay;
|
|
4
|
-
|
|
5
3
|
const activeFocusTraps = (function () {
|
|
6
4
|
const trapQueue = [];
|
|
7
5
|
return {
|
|
@@ -111,10 +109,21 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
111
109
|
mostRecentlyFocusedNode: null,
|
|
112
110
|
active: false,
|
|
113
111
|
paused: false,
|
|
112
|
+
|
|
113
|
+
// timer ID for when delayInitialFocus is true and initial focus in this trap
|
|
114
|
+
// has been delayed during activation
|
|
115
|
+
delayInitialFocusTimer: undefined,
|
|
114
116
|
};
|
|
115
117
|
|
|
116
118
|
let trap; // eslint-disable-line prefer-const -- some private functions reference it, and its methods reference private functions, so we must declare here and define later
|
|
117
119
|
|
|
120
|
+
const getOption = (configOverrideOptions, optionName, configOptionName) => {
|
|
121
|
+
return configOverrideOptions &&
|
|
122
|
+
configOverrideOptions[optionName] !== undefined
|
|
123
|
+
? configOverrideOptions[optionName]
|
|
124
|
+
: config[configOptionName || optionName];
|
|
125
|
+
};
|
|
126
|
+
|
|
118
127
|
const containersContain = function (element) {
|
|
119
128
|
return state.containers.some((container) => container.contains(element));
|
|
120
129
|
};
|
|
@@ -147,6 +156,11 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
147
156
|
const getInitialFocusNode = function () {
|
|
148
157
|
let node;
|
|
149
158
|
|
|
159
|
+
// false indicates we want no initialFocus at all
|
|
160
|
+
if (getOption({}, 'initialFocus') === false) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
150
164
|
if (getNodeForOption('initialFocus') !== null) {
|
|
151
165
|
node = getNodeForOption('initialFocus');
|
|
152
166
|
} else if (containersContain(doc.activeElement)) {
|
|
@@ -196,9 +210,14 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
196
210
|
};
|
|
197
211
|
|
|
198
212
|
const tryFocus = function (node) {
|
|
213
|
+
if (node === false) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
199
217
|
if (node === doc.activeElement) {
|
|
200
218
|
return;
|
|
201
219
|
}
|
|
220
|
+
|
|
202
221
|
if (!node || !node.focus) {
|
|
203
222
|
tryFocus(getInitialFocusNode());
|
|
204
223
|
return;
|
|
@@ -376,7 +395,10 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
376
395
|
};
|
|
377
396
|
|
|
378
397
|
const checkKey = function (e) {
|
|
379
|
-
if (
|
|
398
|
+
if (
|
|
399
|
+
isEscapeEvent(e) &&
|
|
400
|
+
valueOrHandler(config.escapeDeactivates) !== false
|
|
401
|
+
) {
|
|
380
402
|
e.preventDefault();
|
|
381
403
|
trap.deactivate();
|
|
382
404
|
return;
|
|
@@ -419,7 +441,7 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
419
441
|
|
|
420
442
|
// Delay ensures that the focused element doesn't capture the event
|
|
421
443
|
// that caused the focus trap activation.
|
|
422
|
-
|
|
444
|
+
state.delayInitialFocusTimer = config.delayInitialFocus
|
|
423
445
|
? delay(function () {
|
|
424
446
|
tryFocus(getInitialFocusNode());
|
|
425
447
|
})
|
|
@@ -470,21 +492,41 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
470
492
|
return this;
|
|
471
493
|
}
|
|
472
494
|
|
|
473
|
-
|
|
495
|
+
const onActivate = getOption(activateOptions, 'onActivate');
|
|
496
|
+
const onPostActivate = getOption(activateOptions, 'onPostActivate');
|
|
497
|
+
const checkCanFocusTrap = getOption(activateOptions, 'checkCanFocusTrap');
|
|
498
|
+
|
|
499
|
+
if (!checkCanFocusTrap) {
|
|
500
|
+
updateTabbableNodes();
|
|
501
|
+
}
|
|
474
502
|
|
|
475
503
|
state.active = true;
|
|
476
504
|
state.paused = false;
|
|
477
505
|
state.nodeFocusedBeforeActivation = doc.activeElement;
|
|
478
506
|
|
|
479
|
-
const onActivate =
|
|
480
|
-
activateOptions && activateOptions.onActivate
|
|
481
|
-
? activateOptions.onActivate
|
|
482
|
-
: config.onActivate;
|
|
483
507
|
if (onActivate) {
|
|
484
508
|
onActivate();
|
|
485
509
|
}
|
|
486
510
|
|
|
487
|
-
|
|
511
|
+
const finishActivation = () => {
|
|
512
|
+
if (checkCanFocusTrap) {
|
|
513
|
+
updateTabbableNodes();
|
|
514
|
+
}
|
|
515
|
+
addListeners();
|
|
516
|
+
if (onPostActivate) {
|
|
517
|
+
onPostActivate();
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
if (checkCanFocusTrap) {
|
|
522
|
+
checkCanFocusTrap(state.containers.concat()).then(
|
|
523
|
+
finishActivation,
|
|
524
|
+
finishActivation
|
|
525
|
+
);
|
|
526
|
+
return this;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
finishActivation();
|
|
488
530
|
return this;
|
|
489
531
|
},
|
|
490
532
|
|
|
@@ -493,7 +535,8 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
493
535
|
return this;
|
|
494
536
|
}
|
|
495
537
|
|
|
496
|
-
clearTimeout(
|
|
538
|
+
clearTimeout(state.delayInitialFocusTimer); // noop if undefined
|
|
539
|
+
state.delayInitialFocusTimer = undefined;
|
|
497
540
|
|
|
498
541
|
removeListeners();
|
|
499
542
|
state.active = false;
|
|
@@ -501,25 +544,42 @@ const createFocusTrap = function (elements, userOptions) {
|
|
|
501
544
|
|
|
502
545
|
activeFocusTraps.deactivateTrap(trap);
|
|
503
546
|
|
|
504
|
-
const onDeactivate =
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
547
|
+
const onDeactivate = getOption(deactivateOptions, 'onDeactivate');
|
|
548
|
+
const onPostDeactivate = getOption(deactivateOptions, 'onPostDeactivate');
|
|
549
|
+
const checkCanReturnFocus = getOption(
|
|
550
|
+
deactivateOptions,
|
|
551
|
+
'checkCanReturnFocus'
|
|
552
|
+
);
|
|
553
|
+
|
|
508
554
|
if (onDeactivate) {
|
|
509
555
|
onDeactivate();
|
|
510
556
|
}
|
|
511
557
|
|
|
512
|
-
const returnFocus =
|
|
513
|
-
deactivateOptions
|
|
514
|
-
|
|
515
|
-
|
|
558
|
+
const returnFocus = getOption(
|
|
559
|
+
deactivateOptions,
|
|
560
|
+
'returnFocus',
|
|
561
|
+
'returnFocusOnDeactivate'
|
|
562
|
+
);
|
|
516
563
|
|
|
517
|
-
|
|
518
|
-
delay(
|
|
519
|
-
|
|
564
|
+
const finishDeactivation = () => {
|
|
565
|
+
delay(() => {
|
|
566
|
+
if (returnFocus) {
|
|
567
|
+
tryFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation));
|
|
568
|
+
}
|
|
569
|
+
if (onPostDeactivate) {
|
|
570
|
+
onPostDeactivate();
|
|
571
|
+
}
|
|
520
572
|
});
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
if (returnFocus && checkCanReturnFocus) {
|
|
576
|
+
checkCanReturnFocus(
|
|
577
|
+
getReturnFocusNode(state.nodeFocusedBeforeActivation)
|
|
578
|
+
).then(finishDeactivation, finishDeactivation);
|
|
579
|
+
return this;
|
|
521
580
|
}
|
|
522
581
|
|
|
582
|
+
finishDeactivation();
|
|
523
583
|
return this;
|
|
524
584
|
},
|
|
525
585
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "focus-trap",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.6.1",
|
|
4
4
|
"description": "Trap focus within a DOM node.",
|
|
5
5
|
"main": "dist/focus-trap.js",
|
|
6
6
|
"module": "dist/focus-trap.esm.js",
|
|
@@ -17,18 +17,18 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
|
-
"demo-bundle": "browserify
|
|
21
|
-
"format": "prettier --write \"{*,src/**/*,test/**/*,
|
|
22
|
-
"format:check": "prettier --check \"{*,src/**/*,test/**/*,
|
|
23
|
-
"format:watch": "onchange \"{*,src/**/*,test/**/*,
|
|
24
|
-
"lint": "eslint \"*.js\" \"
|
|
20
|
+
"demo-bundle": "browserify docs/js/index.js -o docs/demo-bundle.js",
|
|
21
|
+
"format": "prettier --write \"{*,src/**/*,test/**/*,docs/js/**/*,.github/workflows/*,cypress/**/*}.+(js|yml)\"",
|
|
22
|
+
"format:check": "prettier --check \"{*,src/**/*,test/**/*,docs/js/**/*,.github/workflows/*,cypress/**/*}.+(js|yml)\"",
|
|
23
|
+
"format:watch": "onchange \"{*,src/**/*,test/**/*,docs/js/**/*,.github/workflows/*,cypress/**/*}.+(js|yml)\" -- prettier --write {{changed}}",
|
|
24
|
+
"lint": "eslint \"*.js\" \"docs/js/**/*.js\" \"cypress/**/*.js\"",
|
|
25
25
|
"clean": "rm -rf ./dist",
|
|
26
|
-
"compile:esm": "BUILD_ENV=esm BABEL_ENV=esm rollup -c",
|
|
27
|
-
"compile:cjs": "BUILD_ENV=cjs BABEL_ENV=es5 rollup -c",
|
|
28
|
-
"compile:umd": "BUILD_ENV=umd BABEL_ENV=es5 rollup -c",
|
|
26
|
+
"compile:esm": "cross-env BUILD_ENV=esm BABEL_ENV=esm rollup -c",
|
|
27
|
+
"compile:cjs": "cross-env BUILD_ENV=cjs BABEL_ENV=es5 rollup -c",
|
|
28
|
+
"compile:umd": "cross-env BUILD_ENV=umd BABEL_ENV=es5 rollup -c",
|
|
29
29
|
"compile": "yarn compile:esm && yarn compile:cjs && yarn compile:umd",
|
|
30
30
|
"build": "yarn clean && yarn compile",
|
|
31
|
-
"start": "yarn compile:cjs && budo
|
|
31
|
+
"start": "yarn compile:cjs && budo docs/js/index.js:demo-bundle.js --dir docs --live -- -t babelify",
|
|
32
32
|
"test:types": "tsc index.d.ts",
|
|
33
33
|
"test:unit": "echo \"No unit tests to run!\"",
|
|
34
34
|
"test:cypress": "start-server-and-test start 9966 'cypress open'",
|
|
@@ -60,35 +60,36 @@
|
|
|
60
60
|
},
|
|
61
61
|
"homepage": "https://github.com/focus-trap/focus-trap#readme",
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"tabbable": "^5.2.
|
|
63
|
+
"tabbable": "^5.2.1"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@babel/cli": "^7.
|
|
67
|
-
"@babel/core": "^7.
|
|
68
|
-
"@babel/preset-env": "^7.
|
|
66
|
+
"@babel/cli": "^7.14.8",
|
|
67
|
+
"@babel/core": "^7.15.0",
|
|
68
|
+
"@babel/preset-env": "^7.15.0",
|
|
69
69
|
"@changesets/cli": "^2.16.0",
|
|
70
70
|
"@rollup/plugin-babel": "^5.3.0",
|
|
71
|
-
"@rollup/plugin-commonjs": "^
|
|
72
|
-
"@rollup/plugin-node-resolve": "^
|
|
73
|
-
"@testing-library/cypress": "^
|
|
74
|
-
"@types/jquery": "^3.5.
|
|
71
|
+
"@rollup/plugin-commonjs": "^20.0.0",
|
|
72
|
+
"@rollup/plugin-node-resolve": "^13.0.4",
|
|
73
|
+
"@testing-library/cypress": "^8.0.0",
|
|
74
|
+
"@types/jquery": "^3.5.6",
|
|
75
75
|
"all-contributors-cli": "^6.20.0",
|
|
76
76
|
"babel-eslint": "^10.1.0",
|
|
77
77
|
"babel-loader": "^8.2.2",
|
|
78
78
|
"babelify": "^10.0.0",
|
|
79
79
|
"browserify": "^17.0.0",
|
|
80
80
|
"budo": "^11.6.4",
|
|
81
|
-
"
|
|
81
|
+
"cross-env": "^7.0.3",
|
|
82
|
+
"cypress": "^8.2.0",
|
|
82
83
|
"cypress-plugin-tab": "^1.0.5",
|
|
83
|
-
"eslint": "^7.
|
|
84
|
-
"eslint-config-prettier": "^8.
|
|
85
|
-
"eslint-plugin-cypress": "^2.11.
|
|
84
|
+
"eslint": "^7.32.0",
|
|
85
|
+
"eslint-config-prettier": "^8.3.0",
|
|
86
|
+
"eslint-plugin-cypress": "^2.11.3",
|
|
86
87
|
"onchange": "^7.1.0",
|
|
87
|
-
"prettier": "^2.2
|
|
88
|
-
"rollup": "^2.
|
|
88
|
+
"prettier": "^2.3.2",
|
|
89
|
+
"rollup": "^2.56.2",
|
|
89
90
|
"rollup-plugin-sourcemaps": "^0.6.3",
|
|
90
91
|
"rollup-plugin-terser": "^7.0.1",
|
|
91
|
-
"start-server-and-test": "^1.
|
|
92
|
-
"typescript": "^4.
|
|
92
|
+
"start-server-and-test": "^1.13.1",
|
|
93
|
+
"typescript": "^4.3.5"
|
|
93
94
|
}
|
|
94
95
|
}
|