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 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 [![CI](https://github.com/focus-trap/focus-trap-react/workflows/CI/badge.svg?branch=master&event=push)](https://github.com/focus-trap/focus-trap-react/actions?query=workflow:CI+branch:master) [![Codecov](https://img.shields.io/codecov/c/github/focus-trap/focus-trap-react)](https://codecov.io/gh/focus-trap/focus-trap-react) [![license](https://badgen.now.sh/badge/license/MIT)](./LICENSE)
2
2
 
3
3
  <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
4
- [![All Contributors](https://img.shields.io/badge/all_contributors-19-orange.svg?style=flat-square)](#contributors)
4
+ [![All Contributors](https://img.shields.io/badge/all_contributors-22-orange.svg?style=flat-square)](#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 -->
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
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
- } // TODO: Need more test coverage for this function
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
- node = document.querySelector(optionValue);
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.props.focusTrapOptions.document || document;
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 checkCanReturnFocus = this.tailoredFocusTrapOptions.checkCanReturnFocus;
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.setupFocusTrap();
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 if (prevProps.containerElements !== this.props.containerElements) {
234
- this.focusTrapElements = this.props.containerElements;
235
- this.setupFocusTrap();
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.8.0",
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.15.7",
59
- "@babel/core": "^7.15.5",
60
- "@babel/plugin-proposal-class-properties": "^7.12.13",
61
- "@babel/preset-env": "^7.15.6",
62
- "@babel/preset-react": "^7.14.5",
63
- "@changesets/cli": "^2.17.0",
64
- "@testing-library/cypress": "^8.0.1",
65
- "@testing-library/dom": "^8.5.0",
66
- "@testing-library/jest-dom": "^5.14.1",
67
- "@testing-library/react": "^12.1.0",
68
- "@testing-library/user-event": "^13.2.1",
69
- "@types/jquery": "^3.5.6",
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-eslint": "^10.1.0",
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": "^8.4.1",
76
+ "cypress": "^9.2.1",
77
77
  "cypress-plugin-tab": "^1.0.5",
78
- "eslint": "^7.32.0",
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.26.0",
82
- "jest": "^27.2.1",
83
- "jest-watch-typeahead": "^0.6.4",
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.4.1",
86
- "prop-types": "^15.7.2",
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.3"
91
+ "typescript": "^4.5.4"
92
92
  },
93
93
  "dependencies": {
94
- "focus-trap": "^6.7.1"
94
+ "focus-trap": "^6.7.2"
95
95
  },
96
96
  "peerDependencies": {
97
- "prop-types": "^15.7.2",
97
+ "prop-types": "^15.8.1",
98
98
  "react": ">=16.0.0",
99
99
  "react-dom": ">=16.0.0"
100
100
  }
@@ -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 = document.querySelector(optionValue);
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.props.focusTrapOptions.document || document;
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 } = this.tailoredFocusTrapOptions;
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.setupFocusTrap();
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 if (prevProps.containerElements !== this.props.containerElements) {
190
- this.focusTrapElements = this.props.containerElements;
191
- this.setupFocusTrap();
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