focus-trap-react 8.11.2 → 8.11.3

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,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 8.11.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 9947461: Bump focus-trap dependency to v6.9.4 to get typings fix.
8
+ - 519e5a5: Fix setReturnFocus option as function not being passed node focused prior to activation.
9
+
3
10
  ## 8.11.2
4
11
 
5
12
  ### Patch Changes
@@ -22,6 +22,8 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re
22
22
 
23
23
  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
24
24
 
25
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
26
+
25
27
  var React = require('react');
26
28
 
27
29
  var ReactDOM = require('react-dom');
@@ -50,6 +52,49 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
50
52
  _classCallCheck(this, FocusTrap);
51
53
 
52
54
  _this = _super.call(this, props);
55
+
56
+ _defineProperty(_assertThisInitialized(_this), "getNodeForOption", function (optionName) {
57
+ var _this$internalOptions;
58
+
59
+ // use internal options first, falling back to original options
60
+ var optionValue = (_this$internalOptions = this.internalOptions[optionName]) !== null && _this$internalOptions !== void 0 ? _this$internalOptions : this.originalOptions[optionName];
61
+
62
+ if (typeof optionValue === 'function') {
63
+ for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
64
+ params[_key - 1] = arguments[_key];
65
+ }
66
+
67
+ optionValue = optionValue.apply(void 0, params);
68
+ }
69
+
70
+ if (optionValue === true) {
71
+ optionValue = undefined; // use default value
72
+ }
73
+
74
+ if (!optionValue) {
75
+ if (optionValue === undefined || optionValue === false) {
76
+ return optionValue;
77
+ } // else, empty string (invalid), null (invalid), 0 (invalid)
78
+
79
+
80
+ throw new Error("`".concat(optionName, "` was specified but was not a node, or did not return a node"));
81
+ }
82
+
83
+ var node = optionValue; // could be HTMLElement, SVGElement, or non-empty string at this point
84
+
85
+ if (typeof optionValue === 'string') {
86
+ var _this$getDocument;
87
+
88
+ node = (_this$getDocument = this.getDocument()) === null || _this$getDocument === void 0 ? void 0 : _this$getDocument.querySelector(optionValue); // resolve to node, or null if fails
89
+
90
+ if (!node) {
91
+ throw new Error("`".concat(optionName, "` as selector refers to no known node"));
92
+ }
93
+ }
94
+
95
+ return node;
96
+ });
97
+
53
98
  _this.handleDeactivate = _this.handleDeactivate.bind(_assertThisInitialized(_this));
54
99
  _this.handlePostDeactivate = _this.handlePostDeactivate.bind(_assertThisInitialized(_this));
55
100
  _this.handleClickOutsideDeactivates = _this.handleClickOutsideDeactivates.bind(_assertThisInitialized(_this)); // focus-trap options used internally when creating the trap
@@ -74,10 +119,10 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
74
119
  }; // original options provided by the consumer
75
120
 
76
121
  _this.originalOptions = {
77
- // because of the above `tailoredFocusTrapOptions`, we maintain our own flag for
122
+ // because of the above `internalOptions`, we maintain our own flag for
78
123
  // this option, and default it to `true` because that's focus-trap's default
79
124
  returnFocusOnDeactivate: true,
80
- // because of the above `tailoredFocusTrapOptions`, we keep these separate since
125
+ // because of the above `internalOptions`, we keep these separate since
81
126
  // they're part of the deactivation process which we configure (internally) to
82
127
  // be shared between focus-trap and focus-trap-react
83
128
  onDeactivate: null,
@@ -95,7 +140,7 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
95
140
 
96
141
  if (optionName === 'returnFocusOnDeactivate' || optionName === 'onDeactivate' || optionName === 'onPostDeactivate' || optionName === 'checkCanReturnFocus' || optionName === 'clickOutsideDeactivates') {
97
142
  _this.originalOptions[optionName] = focusTrapOptions[optionName];
98
- continue; // exclude from tailoredFocusTrapOptions
143
+ continue; // exclude from internalOptions
99
144
  }
100
145
 
101
146
  _this.internalOptions[optionName] = focusTrapOptions[optionName];
@@ -128,44 +173,26 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
128
173
  value: function getDocument() {
129
174
  // SSR: careful to check if `document` exists before accessing it as a variable
130
175
  return this.props.focusTrapOptions.document || (typeof document !== 'undefined' ? document : undefined);
131
- } // TODO: Need more test coverage for this function
132
-
133
- }, {
134
- key: "getNodeForOption",
135
- value: function getNodeForOption(optionName) {
136
- var optionValue = this.internalOptions[optionName];
137
-
138
- if (!optionValue) {
139
- return null;
140
- }
141
-
142
- var node = optionValue;
143
-
144
- if (typeof optionValue === 'string') {
145
- var _this$getDocument;
146
-
147
- node = (_this$getDocument = this.getDocument()) === null || _this$getDocument === void 0 ? void 0 : _this$getDocument.querySelector(optionValue);
148
-
149
- if (!node) {
150
- throw new Error("`".concat(optionName, "` refers to no known node"));
151
- }
152
- }
153
-
154
- if (typeof optionValue === 'function') {
155
- node = optionValue();
156
-
157
- if (!node) {
158
- throw new Error("`".concat(optionName, "` did not return a node"));
159
- }
160
- }
161
-
162
- return node;
163
176
  }
177
+ /**
178
+ * Gets the node for the given option, which is expected to be an option that
179
+ * can be either a DOM node, a string that is a selector to get a node, `false`
180
+ * (if a node is explicitly NOT given), or a function that returns any of these
181
+ * values.
182
+ * @param {string} optionName
183
+ * @returns {undefined | false | HTMLElement | SVGElement} Returns
184
+ * `undefined` if the option is not specified; `false` if the option
185
+ * resolved to `false` (node explicitly not given); otherwise, the resolved
186
+ * DOM node.
187
+ * @throws {Error} If the option is set, not `false`, and is not, or does not
188
+ * resolve to a node.
189
+ */
190
+
164
191
  }, {
165
192
  key: "getReturnFocusNode",
166
193
  value: function getReturnFocusNode() {
167
- var node = this.getNodeForOption('setReturnFocus');
168
- return node ? node : this.previouslyFocusedElement;
194
+ var node = this.getNodeForOption('setReturnFocus', this.previouslyFocusedElement);
195
+ return node ? node : node === false ? false : this.previouslyFocusedElement;
169
196
  }
170
197
  /** Update the previously focused element with the currently focused element. */
171
198
 
@@ -417,12 +444,13 @@ FocusTrap.propTypes = {
417
444
  onDeactivate: PropTypes.func,
418
445
  onPostDeactivate: PropTypes.func,
419
446
  checkCanReturnFocus: PropTypes.func,
420
- initialFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.func, PropTypes.bool]),
421
- fallbackFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.func]),
447
+ initialFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.bool, PropTypes.func]),
448
+ fallbackFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, // NOTE: does not support `false` as value (or return value from function)
449
+ PropTypes.func]),
422
450
  escapeDeactivates: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
423
451
  clickOutsideDeactivates: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
424
452
  returnFocusOnDeactivate: PropTypes.bool,
425
- setReturnFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.func]),
453
+ setReturnFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.bool, PropTypes.func]),
426
454
  allowOutsideClick: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
427
455
  preventScroll: PropTypes.bool,
428
456
  tabbableOptions: PropTypes.shape({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "focus-trap-react",
3
- "version": "8.11.2",
3
+ "version": "8.11.3",
4
4
  "description": "A React component that traps focus.",
5
5
  "main": "dist/focus-trap-react.js",
6
6
  "types": "index.d.ts",
@@ -59,31 +59,31 @@
59
59
  "devDependencies": {
60
60
  "@babel/cli": "^7.17.10",
61
61
  "@babel/core": "^7.18.2",
62
- "@babel/eslint-parser": "^7.17.0",
62
+ "@babel/eslint-parser": "^7.18.2",
63
63
  "@babel/plugin-proposal-class-properties": "^7.17.12",
64
- "@babel/preset-env": "^7.18.0",
64
+ "@babel/preset-env": "^7.18.2",
65
65
  "@babel/preset-react": "^7.17.12",
66
66
  "@changesets/cli": "^2.22.0",
67
- "@testing-library/cypress": "^8.0.2",
67
+ "@testing-library/cypress": "^8.0.3",
68
68
  "@testing-library/dom": "^8.13.0",
69
69
  "@testing-library/jest-dom": "^5.16.4",
70
- "@testing-library/react": "^13.2.0",
70
+ "@testing-library/react": "^13.3.0",
71
71
  "@testing-library/user-event": "^14.2.0",
72
72
  "@types/jquery": "^3.5.14",
73
73
  "all-contributors-cli": "^6.20.0",
74
- "babel-jest": "^28.1.0",
74
+ "babel-jest": "^28.1.1",
75
75
  "babelify": "^10.0.0",
76
76
  "browserify": "^17.0.0",
77
77
  "budo": "^11.7.0",
78
78
  "cypress": "^9.7.0",
79
79
  "cypress-plugin-tab": "^1.0.5",
80
- "eslint": "^8.16.0",
80
+ "eslint": "^8.17.0",
81
81
  "eslint-config-prettier": "^8.5.0",
82
82
  "eslint-plugin-cypress": "^2.12.1",
83
- "eslint-plugin-jest": "^26.2.2",
83
+ "eslint-plugin-jest": "^26.5.3",
84
84
  "eslint-plugin-react": "^7.30.0",
85
- "jest": "^28.1.0",
86
- "jest-environment-jsdom": "^28.1.0",
85
+ "jest": "^28.1.1",
86
+ "jest-environment-jsdom": "^28.1.1",
87
87
  "jest-watch-typeahead": "^1.1.0",
88
88
  "onchange": "^7.1.0",
89
89
  "prettier": "^2.6.2",
@@ -92,10 +92,10 @@
92
92
  "react-dom": "^18.1.0",
93
93
  "regenerator-runtime": "^0.13.9",
94
94
  "start-server-and-test": "^1.14.0",
95
- "typescript": "^4.7.2"
95
+ "typescript": "^4.7.3"
96
96
  },
97
97
  "dependencies": {
98
- "focus-trap": "^6.9.3"
98
+ "focus-trap": "^6.9.4"
99
99
  },
100
100
  "peerDependencies": {
101
101
  "prop-types": "^15.8.1",
@@ -42,11 +42,11 @@ class FocusTrap extends React.Component {
42
42
 
43
43
  // original options provided by the consumer
44
44
  this.originalOptions = {
45
- // because of the above `tailoredFocusTrapOptions`, we maintain our own flag for
45
+ // because of the above `internalOptions`, we maintain our own flag for
46
46
  // this option, and default it to `true` because that's focus-trap's default
47
47
  returnFocusOnDeactivate: true,
48
48
 
49
- // because of the above `tailoredFocusTrapOptions`, we keep these separate since
49
+ // because of the above `internalOptions`, we keep these separate since
50
50
  // they're part of the deactivation process which we configure (internally) to
51
51
  // be shared between focus-trap and focus-trap-react
52
52
  onDeactivate: null,
@@ -71,7 +71,7 @@ class FocusTrap extends React.Component {
71
71
  optionName === 'clickOutsideDeactivates'
72
72
  ) {
73
73
  this.originalOptions[optionName] = focusTrapOptions[optionName];
74
- continue; // exclude from tailoredFocusTrapOptions
74
+ continue; // exclude from internalOptions
75
75
  }
76
76
 
77
77
  this.internalOptions[optionName] = focusTrapOptions[optionName];
@@ -106,36 +106,63 @@ class FocusTrap extends React.Component {
106
106
  );
107
107
  }
108
108
 
109
- // TODO: Need more test coverage for this function
110
- getNodeForOption(optionName) {
111
- const optionValue = this.internalOptions[optionName];
112
- if (!optionValue) {
113
- return null;
109
+ /**
110
+ * Gets the node for the given option, which is expected to be an option that
111
+ * can be either a DOM node, a string that is a selector to get a node, `false`
112
+ * (if a node is explicitly NOT given), or a function that returns any of these
113
+ * values.
114
+ * @param {string} optionName
115
+ * @returns {undefined | false | HTMLElement | SVGElement} Returns
116
+ * `undefined` if the option is not specified; `false` if the option
117
+ * resolved to `false` (node explicitly not given); otherwise, the resolved
118
+ * DOM node.
119
+ * @throws {Error} If the option is set, not `false`, and is not, or does not
120
+ * resolve to a node.
121
+ */
122
+ getNodeForOption = function (optionName, ...params) {
123
+ // use internal options first, falling back to original options
124
+ let optionValue =
125
+ this.internalOptions[optionName] ?? this.originalOptions[optionName];
126
+
127
+ if (typeof optionValue === 'function') {
128
+ optionValue = optionValue(...params);
114
129
  }
115
130
 
116
- let node = optionValue;
131
+ if (optionValue === true) {
132
+ optionValue = undefined; // use default value
133
+ }
117
134
 
118
- if (typeof optionValue === 'string') {
119
- node = this.getDocument()?.querySelector(optionValue);
120
- if (!node) {
121
- throw new Error(`\`${optionName}\` refers to no known node`);
135
+ if (!optionValue) {
136
+ if (optionValue === undefined || optionValue === false) {
137
+ return optionValue;
122
138
  }
139
+ // else, empty string (invalid), null (invalid), 0 (invalid)
140
+
141
+ throw new Error(
142
+ `\`${optionName}\` was specified but was not a node, or did not return a node`
143
+ );
123
144
  }
124
145
 
125
- if (typeof optionValue === 'function') {
126
- node = optionValue();
146
+ let node = optionValue; // could be HTMLElement, SVGElement, or non-empty string at this point
147
+
148
+ if (typeof optionValue === 'string') {
149
+ node = this.getDocument()?.querySelector(optionValue); // resolve to node, or null if fails
127
150
  if (!node) {
128
- throw new Error(`\`${optionName}\` did not return a node`);
151
+ throw new Error(
152
+ `\`${optionName}\` as selector refers to no known node`
153
+ );
129
154
  }
130
155
  }
131
156
 
132
157
  return node;
133
- }
158
+ };
134
159
 
135
160
  getReturnFocusNode() {
136
- const node = this.getNodeForOption('setReturnFocus');
137
-
138
- return node ? node : this.previouslyFocusedElement;
161
+ const node = this.getNodeForOption(
162
+ 'setReturnFocus',
163
+ this.previouslyFocusedElement
164
+ );
165
+ return node ? node : node === false ? false : this.previouslyFocusedElement;
139
166
  }
140
167
 
141
168
  /** Update the previously focused element with the currently focused element. */
@@ -395,12 +422,13 @@ FocusTrap.propTypes = {
395
422
  initialFocus: PropTypes.oneOfType([
396
423
  PropTypes.instanceOf(ElementType),
397
424
  PropTypes.string,
398
- PropTypes.func,
399
425
  PropTypes.bool,
426
+ PropTypes.func,
400
427
  ]),
401
428
  fallbackFocus: PropTypes.oneOfType([
402
429
  PropTypes.instanceOf(ElementType),
403
430
  PropTypes.string,
431
+ // NOTE: does not support `false` as value (or return value from function)
404
432
  PropTypes.func,
405
433
  ]),
406
434
  escapeDeactivates: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
@@ -412,6 +440,7 @@ FocusTrap.propTypes = {
412
440
  setReturnFocus: PropTypes.oneOfType([
413
441
  PropTypes.instanceOf(ElementType),
414
442
  PropTypes.string,
443
+ PropTypes.bool,
415
444
  PropTypes.func,
416
445
  ]),
417
446
  allowOutsideClick: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),