focus-trap-react 8.8.2 → 8.9.0
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 +10 -0
- package/dist/focus-trap-react.js +42 -8
- package/package.json +20 -20
- package/src/focus-trap-react.js +41 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 8.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 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)
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 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)
|
|
12
|
+
|
|
3
13
|
## 8.8.2
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/dist/focus-trap-react.js
CHANGED
|
@@ -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,8 +144,7 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
|
|
|
129
144
|
}, {
|
|
130
145
|
key: "updatePreviousElement",
|
|
131
146
|
value: function updatePreviousElement() {
|
|
132
|
-
|
|
133
|
-
var currentDocument = this.props.focusTrapOptions.document || (typeof document !== 'undefined' ? document : undefined);
|
|
147
|
+
var currentDocument = this.getDocument();
|
|
134
148
|
|
|
135
149
|
if (currentDocument) {
|
|
136
150
|
this.previouslyFocusedElement = currentDocument.activeElement;
|
|
@@ -204,7 +218,14 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
|
|
|
204
218
|
}, {
|
|
205
219
|
key: "componentDidMount",
|
|
206
220
|
value: function componentDidMount() {
|
|
207
|
-
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
|
+
|
|
208
229
|
}
|
|
209
230
|
}, {
|
|
210
231
|
key: "componentDidUpdate",
|
|
@@ -236,9 +257,22 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
|
|
|
236
257
|
if (hasUnpaused) {
|
|
237
258
|
this.focusTrap.unpause();
|
|
238
259
|
}
|
|
239
|
-
} else
|
|
240
|
-
|
|
241
|
-
|
|
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
|
+
}
|
|
242
276
|
}
|
|
243
277
|
}
|
|
244
278
|
}, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "focus-trap-react",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.9.0",
|
|
4
4
|
"description": "A React component that traps focus.",
|
|
5
5
|
"main": "dist/focus-trap-react.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -55,40 +55,40 @@
|
|
|
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/
|
|
58
|
+
"@babel/cli": "^7.16.0",
|
|
59
|
+
"@babel/core": "^7.16.0",
|
|
60
|
+
"@babel/eslint-parser": "^7.16.3",
|
|
61
|
+
"@babel/plugin-proposal-class-properties": "^7.16.0",
|
|
62
|
+
"@babel/preset-env": "^7.16.4",
|
|
63
|
+
"@babel/preset-react": "^7.16.0",
|
|
64
|
+
"@changesets/cli": "^2.18.1",
|
|
65
|
+
"@testing-library/cypress": "^8.0.2",
|
|
66
|
+
"@testing-library/dom": "^8.11.1",
|
|
67
|
+
"@testing-library/jest-dom": "^5.16.1",
|
|
67
68
|
"@testing-library/react": "^12.1.2",
|
|
68
|
-
"@testing-library/user-event": "^13.
|
|
69
|
-
"@types/jquery": "^3.5.
|
|
69
|
+
"@testing-library/user-event": "^13.5.0",
|
|
70
|
+
"@types/jquery": "^3.5.9",
|
|
70
71
|
"all-contributors-cli": "^6.20.0",
|
|
71
|
-
"babel-
|
|
72
|
-
"babel-jest": "^27.2.5",
|
|
72
|
+
"babel-jest": "^27.4.2",
|
|
73
73
|
"babelify": "^10.0.0",
|
|
74
74
|
"browserify": "^17.0.0",
|
|
75
75
|
"budo": "^11.6.4",
|
|
76
|
-
"cypress": "^
|
|
76
|
+
"cypress": "^9.1.1",
|
|
77
77
|
"cypress-plugin-tab": "^1.0.5",
|
|
78
|
-
"eslint": "^
|
|
78
|
+
"eslint": "^8.4.1",
|
|
79
79
|
"eslint-config-prettier": "^8.3.0",
|
|
80
80
|
"eslint-plugin-cypress": "^2.12.1",
|
|
81
|
-
"eslint-plugin-react": "^7.
|
|
82
|
-
"jest": "^27.
|
|
81
|
+
"eslint-plugin-react": "^7.27.1",
|
|
82
|
+
"jest": "^27.4.3",
|
|
83
83
|
"jest-watch-typeahead": "^1.0.0",
|
|
84
84
|
"onchange": "^7.1.0",
|
|
85
|
-
"prettier": "^2.
|
|
85
|
+
"prettier": "^2.5.1",
|
|
86
86
|
"prop-types": "^15.7.2",
|
|
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.
|
|
91
|
+
"typescript": "^4.5.2"
|
|
92
92
|
},
|
|
93
93
|
"dependencies": {
|
|
94
94
|
"focus-trap": "^6.7.1"
|
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,10 +101,7 @@ class FocusTrap extends React.Component {
|
|
|
87
101
|
|
|
88
102
|
/** Update the previously focused element with the currently focused element. */
|
|
89
103
|
updatePreviousElement() {
|
|
90
|
-
|
|
91
|
-
const currentDocument =
|
|
92
|
-
this.props.focusTrapOptions.document ||
|
|
93
|
-
(typeof document !== 'undefined' ? document : undefined);
|
|
104
|
+
const currentDocument = this.getDocument();
|
|
94
105
|
if (currentDocument) {
|
|
95
106
|
this.previouslyFocusedElement = currentDocument.activeElement;
|
|
96
107
|
}
|
|
@@ -161,7 +172,14 @@ class FocusTrap extends React.Component {
|
|
|
161
172
|
}
|
|
162
173
|
|
|
163
174
|
componentDidMount() {
|
|
164
|
-
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
|
|
165
183
|
}
|
|
166
184
|
|
|
167
185
|
componentDidUpdate(prevProps) {
|
|
@@ -192,9 +210,23 @@ class FocusTrap extends React.Component {
|
|
|
192
210
|
if (hasUnpaused) {
|
|
193
211
|
this.focusTrap.unpause();
|
|
194
212
|
}
|
|
195
|
-
} else
|
|
196
|
-
|
|
197
|
-
|
|
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
|
+
}
|
|
198
230
|
}
|
|
199
231
|
}
|
|
200
232
|
|