focus-trap-react 8.8.0 → 8.9.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 +28 -0
- package/README.md +8 -3
- package/dist/focus-trap-react.js +52 -12
- package/package.json +25 -25
- package/src/focus-trap-react.js +46 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 8.9.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 3eb9421: Bump focus-trap to v6.7.2 for bug fix.
|
|
8
|
+
|
|
9
|
+
## 8.9.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 83097a5: Delay trap creation until it should be active. This is a change in behavior, however it should not break existing behavior. The delay now allows you to set `active=false` until you have the `focusTrapOptions` set correctly. [#539](https://github.com/focus-trap/focus-trap-react/issues/539)
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 16d1ae1: Fix bug where global document was being accessed instead of first checking for `focusTrapOptions.document` option. [#539](https://github.com/focus-trap/focus-trap-react/issues/539)
|
|
18
|
+
|
|
19
|
+
## 8.8.2
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- 08a9449: Use `preventScroll` option on deactivation if returning focus.
|
|
24
|
+
|
|
25
|
+
## 8.8.1
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- a2806a0: Fix SSR issues when accessing `document` object (#482)
|
|
30
|
+
|
|
3
31
|
## 8.8.0
|
|
4
32
|
|
|
5
33
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# focus-trap-react [](https://github.com/focus-trap/focus-trap-react/actions?query=workflow:CI+branch:master) [](https://codecov.io/gh/focus-trap/focus-trap-react) [](./LICENSE)
|
|
2
2
|
|
|
3
3
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
4
|
-
[](#contributors)
|
|
5
5
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
6
6
|
|
|
7
7
|
A React component that traps focus.
|
|
@@ -191,21 +191,26 @@ In alphabetical order:
|
|
|
191
191
|
<td align="center"><a href="https://github.com/features/security"><img src="https://avatars1.githubusercontent.com/u/27347476?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dependabot</b></sub></a><br /><a href="#maintenance-dependabot" title="Maintenance">🚧</a></td>
|
|
192
192
|
</tr>
|
|
193
193
|
<tr>
|
|
194
|
+
<td align="center"><a href="https://github.com/jhnns"><img src="https://avatars.githubusercontent.com/u/781746?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Johannes Ewald</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/commits?author=jhnns" title="Code">💻</a></td>
|
|
194
195
|
<td align="center"><a href="http://josuzuki.me"><img src="https://avatars1.githubusercontent.com/u/9583920?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonathan Suzuki</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/issues?q=author%3AJoSuzuki" title="Bug reports">🐛</a></td>
|
|
195
196
|
<td align="center"><a href="http://kathleenmcmahon.dev/"><img src="https://avatars1.githubusercontent.com/u/11621935?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kathleen McMahon</b></sub></a><br /><a href="#maintenance-resource11" title="Maintenance">🚧</a></td>
|
|
197
|
+
<td align="center"><a href="https://github.com/LoganDark"><img src="https://avatars.githubusercontent.com/u/4723091?v=4?s=100" width="100px;" alt=""/><br /><sub><b>LoganDark</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/issues?q=author%3ALoganDark" title="Bug reports">🐛</a></td>
|
|
196
198
|
<td align="center"><a href="https://marais.io/"><img src="https://avatars2.githubusercontent.com/u/599459?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Marais Rossouw</b></sub></a><br /><a href="#infra-maraisr" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
|
197
199
|
<td align="center"><a href="https://github.com/liunate"><img src="https://avatars2.githubusercontent.com/u/38996291?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nate Liu</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/commits?author=liunate" title="Tests">⚠️</a></td>
|
|
198
200
|
<td align="center"><a href="https://www.linkedin.com/in/rivajunior/"><img src="https://avatars1.githubusercontent.com/u/11370172?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rivaldo Junior</b></sub></a><br /><a href="#maintenance-rivajunior" title="Maintenance">🚧</a></td>
|
|
199
|
-
<td align="center"><a href="https://scottrippey.github.io/"><img src="https://avatars3.githubusercontent.com/u/430608?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Scott Rippey</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/commits?author=scottrippey" title="Code">💻</a> <a href="https://github.com/focus-trap/focus-trap-react/issues?q=author%3Ascottrippey" title="Bug reports">🐛</a></td>
|
|
200
|
-
<td align="center"><a href="https://seanmcp.com/"><img src="https://avatars1.githubusercontent.com/u/6360367?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sean McPherson</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/commits?author=SeanMcP" title="Code">💻</a></td>
|
|
201
201
|
</tr>
|
|
202
202
|
<tr>
|
|
203
|
+
<td align="center"><a href="https://scottrippey.github.io/"><img src="https://avatars3.githubusercontent.com/u/430608?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Scott Rippey</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/commits?author=scottrippey" title="Code">💻</a> <a href="https://github.com/focus-trap/focus-trap-react/issues?q=author%3Ascottrippey" title="Bug reports">🐛</a></td>
|
|
204
|
+
<td align="center"><a href="https://seanmcp.com/"><img src="https://avatars1.githubusercontent.com/u/6360367?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sean McPherson</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/commits?author=SeanMcP" title="Code">💻</a></td>
|
|
203
205
|
<td align="center"><a href="https://recollectr.io"><img src="https://avatars2.githubusercontent.com/u/6835891?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Slapbox</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/commits?author=Slapbox" title="Documentation">📖</a></td>
|
|
204
206
|
<td align="center"><a href="https://stefancameron.com/"><img src="https://avatars3.githubusercontent.com/u/2855350?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stefan Cameron</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/commits?author=stefcameron" title="Code">💻</a> <a href="https://github.com/focus-trap/focus-trap-react/issues?q=author%3Astefcameron" title="Bug reports">🐛</a> <a href="#infra-stefcameron" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/focus-trap/focus-trap-react/commits?author=stefcameron" title="Tests">⚠️</a> <a href="https://github.com/focus-trap/focus-trap-react/commits?author=stefcameron" title="Documentation">📖</a> <a href="#maintenance-stefcameron" title="Maintenance">🚧</a></td>
|
|
205
207
|
<td align="center"><a href="http://tylerhawkins.info/201R/"><img src="https://avatars0.githubusercontent.com/u/13806458?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tyler Hawkins</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/commits?author=thawkin3" title="Documentation">📖</a> <a href="#example-thawkin3" title="Examples">💡</a> <a href="https://github.com/focus-trap/focus-trap-react/commits?author=thawkin3" title="Tests">⚠️</a> <a href="#tool-thawkin3" title="Tools">🔧</a></td>
|
|
206
208
|
<td align="center"><a href="https://github.com/wandroll"><img src="https://avatars.githubusercontent.com/u/4492317?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Wandrille Verlut</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/commits?author=wandroll" title="Code">💻</a> <a href="https://github.com/focus-trap/focus-trap-react/commits?author=wandroll" title="Tests">⚠️</a></td>
|
|
207
209
|
<td align="center"><a href="https://github.com/krikienoid"><img src="https://avatars3.githubusercontent.com/u/8528227?v=4?s=100" width="100px;" alt=""/><br /><sub><b>krikienoid</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/issues?q=author%3Akrikienoid" title="Bug reports">🐛</a></td>
|
|
208
210
|
</tr>
|
|
211
|
+
<tr>
|
|
212
|
+
<td align="center"><a href="https://github.com/syntactic-salt"><img src="https://avatars.githubusercontent.com/u/9385662?v=4?s=100" width="100px;" alt=""/><br /><sub><b>syntactic-salt</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/issues?q=author%3Asyntactic-salt" title="Bug reports">🐛</a></td>
|
|
213
|
+
</tr>
|
|
209
214
|
</table>
|
|
210
215
|
|
|
211
216
|
<!-- markdownlint-restore -->
|
package/dist/focus-trap-react.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function _typeof(obj) { "@babel/helpers - typeof";
|
|
3
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
4
4
|
|
|
5
5
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
6
6
|
|
|
7
7
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
8
8
|
|
|
9
|
-
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
9
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
10
10
|
|
|
11
|
-
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
11
|
+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
12
12
|
|
|
13
13
|
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
14
14
|
|
|
@@ -86,10 +86,23 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
|
|
|
86
86
|
_this.updatePreviousElement();
|
|
87
87
|
|
|
88
88
|
return _this;
|
|
89
|
-
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Gets the configured document.
|
|
92
|
+
* @returns {Document|undefined} Configured document, falling back to the main
|
|
93
|
+
* document, if it exists. During SSR, `undefined` is returned since the
|
|
94
|
+
* document doesn't exist.
|
|
95
|
+
*/
|
|
90
96
|
|
|
91
97
|
|
|
92
98
|
_createClass(FocusTrap, [{
|
|
99
|
+
key: "getDocument",
|
|
100
|
+
value: function getDocument() {
|
|
101
|
+
// SSR: careful to check if `document` exists before accessing it as a variable
|
|
102
|
+
return this.props.focusTrapOptions.document || (typeof document !== 'undefined' ? document : undefined);
|
|
103
|
+
} // TODO: Need more test coverage for this function
|
|
104
|
+
|
|
105
|
+
}, {
|
|
93
106
|
key: "getNodeForOption",
|
|
94
107
|
value: function getNodeForOption(optionName) {
|
|
95
108
|
var optionValue = this.tailoredFocusTrapOptions[optionName];
|
|
@@ -101,7 +114,9 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
|
|
|
101
114
|
var node = optionValue;
|
|
102
115
|
|
|
103
116
|
if (typeof optionValue === 'string') {
|
|
104
|
-
|
|
117
|
+
var _this$getDocument;
|
|
118
|
+
|
|
119
|
+
node = (_this$getDocument = this.getDocument()) === null || _this$getDocument === void 0 ? void 0 : _this$getDocument.querySelector(optionValue);
|
|
105
120
|
|
|
106
121
|
if (!node) {
|
|
107
122
|
throw new Error("`".concat(optionName, "` refers to no known node"));
|
|
@@ -129,7 +144,7 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
|
|
|
129
144
|
}, {
|
|
130
145
|
key: "updatePreviousElement",
|
|
131
146
|
value: function updatePreviousElement() {
|
|
132
|
-
var currentDocument = this.
|
|
147
|
+
var currentDocument = this.getDocument();
|
|
133
148
|
|
|
134
149
|
if (currentDocument) {
|
|
135
150
|
this.previouslyFocusedElement = currentDocument.activeElement;
|
|
@@ -140,7 +155,10 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
|
|
|
140
155
|
value: function deactivateTrap() {
|
|
141
156
|
var _this2 = this;
|
|
142
157
|
|
|
143
|
-
var
|
|
158
|
+
var _this$tailoredFocusTr = this.tailoredFocusTrapOptions,
|
|
159
|
+
checkCanReturnFocus = _this$tailoredFocusTr.checkCanReturnFocus,
|
|
160
|
+
_this$tailoredFocusTr2 = _this$tailoredFocusTr.preventScroll,
|
|
161
|
+
preventScroll = _this$tailoredFocusTr2 === void 0 ? false : _this$tailoredFocusTr2;
|
|
144
162
|
|
|
145
163
|
if (this.focusTrap) {
|
|
146
164
|
// NOTE: we never let the trap return the focus since we do that ourselves
|
|
@@ -156,7 +174,9 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
|
|
|
156
174
|
|
|
157
175
|
if (canReturnFocus) {
|
|
158
176
|
/** Returns focus to the element that had focus when the trap was activated. */
|
|
159
|
-
returnFocusNode.focus(
|
|
177
|
+
returnFocusNode.focus({
|
|
178
|
+
preventScroll: preventScroll
|
|
179
|
+
});
|
|
160
180
|
}
|
|
161
181
|
|
|
162
182
|
if (_this2.onPostDeactivate) {
|
|
@@ -198,7 +218,14 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
|
|
|
198
218
|
}, {
|
|
199
219
|
key: "componentDidMount",
|
|
200
220
|
value: function componentDidMount() {
|
|
201
|
-
this.
|
|
221
|
+
if (this.props.active) {
|
|
222
|
+
this.setupFocusTrap();
|
|
223
|
+
} // else, wait for later activation in case the `focusTrapOptions` will be updated
|
|
224
|
+
// again before the trap is activated (e.g. if waiting to know what the document
|
|
225
|
+
// object will be, so the Trap must be rendered, but the consumer is waiting to
|
|
226
|
+
// activate until they have obtained the document from a ref)
|
|
227
|
+
// @see https://github.com/focus-trap/focus-trap-react/issues/539
|
|
228
|
+
|
|
202
229
|
}
|
|
203
230
|
}, {
|
|
204
231
|
key: "componentDidUpdate",
|
|
@@ -230,9 +257,22 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
|
|
|
230
257
|
if (hasUnpaused) {
|
|
231
258
|
this.focusTrap.unpause();
|
|
232
259
|
}
|
|
233
|
-
} else
|
|
234
|
-
|
|
235
|
-
|
|
260
|
+
} else {
|
|
261
|
+
// NOTE: if we're in `componentDidUpdate` and we don't have a trap yet,
|
|
262
|
+
// it either means it shouldn't be active, or it should be but none of
|
|
263
|
+
// of given `containerElements` were present in the DOM the last time
|
|
264
|
+
// we tried to create the trap
|
|
265
|
+
if (prevProps.containerElements !== this.props.containerElements) {
|
|
266
|
+
this.focusTrapElements = this.props.containerElements;
|
|
267
|
+
} // don't create the trap unless it should be active in case the consumer
|
|
268
|
+
// is still updating `focusTrapOptions`
|
|
269
|
+
// @see https://github.com/focus-trap/focus-trap-react/issues/539
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
if (this.props.active) {
|
|
273
|
+
this.updatePreviousElement();
|
|
274
|
+
this.setupFocusTrap();
|
|
275
|
+
}
|
|
236
276
|
}
|
|
237
277
|
}
|
|
238
278
|
}, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "focus-trap-react",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.9.1",
|
|
4
4
|
"description": "A React component that traps focus.",
|
|
5
5
|
"main": "dist/focus-trap-react.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -55,46 +55,46 @@
|
|
|
55
55
|
},
|
|
56
56
|
"homepage": "https://github.com/focus-trap/focus-trap-react#readme",
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@babel/cli": "^7.
|
|
59
|
-
"@babel/core": "^7.
|
|
60
|
-
"@babel/
|
|
61
|
-
"@babel/
|
|
62
|
-
"@babel/preset-
|
|
63
|
-
"@
|
|
64
|
-
"@
|
|
65
|
-
"@testing-library/
|
|
66
|
-
"@testing-library/
|
|
67
|
-
"@testing-library/
|
|
68
|
-
"@testing-library/
|
|
69
|
-
"@
|
|
58
|
+
"@babel/cli": "^7.16.8",
|
|
59
|
+
"@babel/core": "^7.16.7",
|
|
60
|
+
"@babel/eslint-parser": "^7.16.5",
|
|
61
|
+
"@babel/plugin-proposal-class-properties": "^7.16.5",
|
|
62
|
+
"@babel/preset-env": "^7.16.8",
|
|
63
|
+
"@babel/preset-react": "^7.16.7",
|
|
64
|
+
"@changesets/cli": "^2.19.0",
|
|
65
|
+
"@testing-library/cypress": "^8.0.2",
|
|
66
|
+
"@testing-library/dom": "^8.11.1",
|
|
67
|
+
"@testing-library/jest-dom": "^5.16.1",
|
|
68
|
+
"@testing-library/react": "^12.1.2",
|
|
69
|
+
"@testing-library/user-event": "^13.5.0",
|
|
70
|
+
"@types/jquery": "^3.5.13",
|
|
70
71
|
"all-contributors-cli": "^6.20.0",
|
|
71
|
-
"babel-
|
|
72
|
-
"babel-jest": "^27.2.1",
|
|
72
|
+
"babel-jest": "^27.4.6",
|
|
73
73
|
"babelify": "^10.0.0",
|
|
74
74
|
"browserify": "^17.0.0",
|
|
75
75
|
"budo": "^11.6.4",
|
|
76
|
-
"cypress": "^
|
|
76
|
+
"cypress": "^9.2.1",
|
|
77
77
|
"cypress-plugin-tab": "^1.0.5",
|
|
78
|
-
"eslint": "^
|
|
78
|
+
"eslint": "^8.6.0",
|
|
79
79
|
"eslint-config-prettier": "^8.3.0",
|
|
80
80
|
"eslint-plugin-cypress": "^2.12.1",
|
|
81
|
-
"eslint-plugin-react": "^7.
|
|
82
|
-
"jest": "^27.
|
|
83
|
-
"jest-watch-typeahead": "^0.
|
|
81
|
+
"eslint-plugin-react": "^7.28.0",
|
|
82
|
+
"jest": "^27.4.7",
|
|
83
|
+
"jest-watch-typeahead": "^1.0.0",
|
|
84
84
|
"onchange": "^7.1.0",
|
|
85
|
-
"prettier": "^2.
|
|
86
|
-
"prop-types": "^15.
|
|
85
|
+
"prettier": "^2.5.1",
|
|
86
|
+
"prop-types": "^15.8.1",
|
|
87
87
|
"react": "^17.0.2",
|
|
88
88
|
"react-dom": "^17.0.2",
|
|
89
89
|
"regenerator-runtime": "^0.13.9",
|
|
90
90
|
"start-server-and-test": "^1.14.0",
|
|
91
|
-
"typescript": "^4.4
|
|
91
|
+
"typescript": "^4.5.4"
|
|
92
92
|
},
|
|
93
93
|
"dependencies": {
|
|
94
|
-
"focus-trap": "^6.7.
|
|
94
|
+
"focus-trap": "^6.7.2"
|
|
95
95
|
},
|
|
96
96
|
"peerDependencies": {
|
|
97
|
-
"prop-types": "^15.
|
|
97
|
+
"prop-types": "^15.8.1",
|
|
98
98
|
"react": ">=16.0.0",
|
|
99
99
|
"react-dom": ">=16.0.0"
|
|
100
100
|
}
|
package/src/focus-trap-react.js
CHANGED
|
@@ -53,6 +53,20 @@ class FocusTrap extends React.Component {
|
|
|
53
53
|
this.updatePreviousElement();
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Gets the configured document.
|
|
58
|
+
* @returns {Document|undefined} Configured document, falling back to the main
|
|
59
|
+
* document, if it exists. During SSR, `undefined` is returned since the
|
|
60
|
+
* document doesn't exist.
|
|
61
|
+
*/
|
|
62
|
+
getDocument() {
|
|
63
|
+
// SSR: careful to check if `document` exists before accessing it as a variable
|
|
64
|
+
return (
|
|
65
|
+
this.props.focusTrapOptions.document ||
|
|
66
|
+
(typeof document !== 'undefined' ? document : undefined)
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
56
70
|
// TODO: Need more test coverage for this function
|
|
57
71
|
getNodeForOption(optionName) {
|
|
58
72
|
const optionValue = this.tailoredFocusTrapOptions[optionName];
|
|
@@ -63,7 +77,7 @@ class FocusTrap extends React.Component {
|
|
|
63
77
|
let node = optionValue;
|
|
64
78
|
|
|
65
79
|
if (typeof optionValue === 'string') {
|
|
66
|
-
node =
|
|
80
|
+
node = this.getDocument()?.querySelector(optionValue);
|
|
67
81
|
if (!node) {
|
|
68
82
|
throw new Error(`\`${optionName}\` refers to no known node`);
|
|
69
83
|
}
|
|
@@ -87,14 +101,15 @@ class FocusTrap extends React.Component {
|
|
|
87
101
|
|
|
88
102
|
/** Update the previously focused element with the currently focused element. */
|
|
89
103
|
updatePreviousElement() {
|
|
90
|
-
const currentDocument = this.
|
|
104
|
+
const currentDocument = this.getDocument();
|
|
91
105
|
if (currentDocument) {
|
|
92
106
|
this.previouslyFocusedElement = currentDocument.activeElement;
|
|
93
107
|
}
|
|
94
108
|
}
|
|
95
109
|
|
|
96
110
|
deactivateTrap() {
|
|
97
|
-
const { checkCanReturnFocus } =
|
|
111
|
+
const { checkCanReturnFocus, preventScroll = false } =
|
|
112
|
+
this.tailoredFocusTrapOptions;
|
|
98
113
|
|
|
99
114
|
if (this.focusTrap) {
|
|
100
115
|
// NOTE: we never let the trap return the focus since we do that ourselves
|
|
@@ -108,7 +123,9 @@ class FocusTrap extends React.Component {
|
|
|
108
123
|
|
|
109
124
|
if (canReturnFocus) {
|
|
110
125
|
/** Returns focus to the element that had focus when the trap was activated. */
|
|
111
|
-
returnFocusNode.focus(
|
|
126
|
+
returnFocusNode.focus({
|
|
127
|
+
preventScroll,
|
|
128
|
+
});
|
|
112
129
|
}
|
|
113
130
|
|
|
114
131
|
if (this.onPostDeactivate) {
|
|
@@ -155,7 +172,14 @@ class FocusTrap extends React.Component {
|
|
|
155
172
|
}
|
|
156
173
|
|
|
157
174
|
componentDidMount() {
|
|
158
|
-
this.
|
|
175
|
+
if (this.props.active) {
|
|
176
|
+
this.setupFocusTrap();
|
|
177
|
+
}
|
|
178
|
+
// else, wait for later activation in case the `focusTrapOptions` will be updated
|
|
179
|
+
// again before the trap is activated (e.g. if waiting to know what the document
|
|
180
|
+
// object will be, so the Trap must be rendered, but the consumer is waiting to
|
|
181
|
+
// activate until they have obtained the document from a ref)
|
|
182
|
+
// @see https://github.com/focus-trap/focus-trap-react/issues/539
|
|
159
183
|
}
|
|
160
184
|
|
|
161
185
|
componentDidUpdate(prevProps) {
|
|
@@ -186,9 +210,23 @@ class FocusTrap extends React.Component {
|
|
|
186
210
|
if (hasUnpaused) {
|
|
187
211
|
this.focusTrap.unpause();
|
|
188
212
|
}
|
|
189
|
-
} else
|
|
190
|
-
|
|
191
|
-
|
|
213
|
+
} else {
|
|
214
|
+
// NOTE: if we're in `componentDidUpdate` and we don't have a trap yet,
|
|
215
|
+
// it either means it shouldn't be active, or it should be but none of
|
|
216
|
+
// of given `containerElements` were present in the DOM the last time
|
|
217
|
+
// we tried to create the trap
|
|
218
|
+
|
|
219
|
+
if (prevProps.containerElements !== this.props.containerElements) {
|
|
220
|
+
this.focusTrapElements = this.props.containerElements;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// don't create the trap unless it should be active in case the consumer
|
|
224
|
+
// is still updating `focusTrapOptions`
|
|
225
|
+
// @see https://github.com/focus-trap/focus-trap-react/issues/539
|
|
226
|
+
if (this.props.active) {
|
|
227
|
+
this.updatePreviousElement();
|
|
228
|
+
this.setupFocusTrap();
|
|
229
|
+
}
|
|
192
230
|
}
|
|
193
231
|
}
|
|
194
232
|
|