focus-trap-react 9.0.2 → 10.0.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 CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 10.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - af69c14: 🚨 **Breaking:** Underlying `tabbable` dependency has been updated to v6.0.0 and contains a breaking change related to detached nodes with its default `displayCheck` setting. See tabbable's [changelog](https://github.com/focus-trap/tabbable/blob/master/CHANGELOG.md#600) for more information.
8
+ - The `focus-trap` dependency has also be updated to v7.0.0 but only contains the underlying `tabbable` changes.
9
+ - The `tabbableOptions.displayCheck` prop type has been updated to include the new "legacy-full" option.
10
+ - 018732c: 🚨 **Breaking:** Dropped support of IE browsers, all versions.
11
+ - IE11 was [officially retired](https://blogs.windows.com/windowsexperience/2022/06/15/internet-explorer-11-has-retired-and-is-officially-out-of-support-what-you-need-to-know/) on June 15, 2022 (6 weeks ago). There are no longer any versions of IE that are still maintained or even supported by Microsoft.
12
+ - 018732c: Revised and clarified official browser support (still as broad and deep as _reasonably_ possible).
13
+
14
+ ### Patch Changes
15
+
16
+ - b0bbbd4: Update README with a note about the `children` prop stating that the trap requires a single child, and that if a component is used, it must be a **functional** component that forwards refs.
17
+
3
18
  ## 9.0.2
4
19
 
5
20
  ### Patch Changes
package/README.md CHANGED
@@ -33,13 +33,21 @@ npm install focus-trap-react
33
33
 
34
34
  ### React dependency
35
35
 
36
- React `>= 16.0.0`.
36
+ React `>= 16.3.0`
37
37
 
38
38
  ## Browser Support
39
39
 
40
- Basically IE9+.
40
+ As old and as broad as _reasonably_ possible, excluding browsers that are out of support or have nearly no user base.
41
41
 
42
- Why? Because this module's core functionality comes from focus-trap, which uses [a couple of IE9+ functions](https://github.com/davidtheclark/tabbable#browser-support).
42
+ Focused on desktop browsers, particularly Chrome, Edge, FireFox, Safari, and Opera.
43
+
44
+ Focus-trap-react is not officially tested on any mobile browsers or devices.
45
+
46
+ > ⚠️ Microsoft [no longer supports](https://blogs.windows.com/windowsexperience/2022/06/15/internet-explorer-11-has-retired-and-is-officially-out-of-support-what-you-need-to-know/) any version of IE, so IE is no longer supported by this library.
47
+
48
+ > 💬 Focus-trap-react relies on focus-trap so its browser support is at least [what focus-trap supports](https://github.com/focus-trap/focus-trap#browser-support).
49
+
50
+ > 💬 Keep in mind that performance optimization and old browser support are often at odds, so tabbable may not always be able to use the most optimal (typically modern) APIs in all cases.
43
51
 
44
52
  ## Usage
45
53
 
@@ -66,7 +74,7 @@ You can read further code examples in `demo/` (it's very simple), and [see how i
66
74
 
67
75
  Here's one more simple example:
68
76
 
69
- ```js
77
+ ```jsx
70
78
  const React = require('react');
71
79
  const ReactDOM = require('react-dom'); // React 16-17
72
80
  const { createRoot } = require('react-dom/client'); // React 18
@@ -139,6 +147,96 @@ createRoot(document.getElementById('root')).render(<Demo />); // React 18
139
147
 
140
148
  ### Props
141
149
 
150
+ #### children
151
+
152
+ > ⚠️ The `<FocusTrap>` component requires a __single__ child, and this child must __forward refs__ onto the element which will ultimately be considered the trap's container. Since React does not provide for a way to forward refs to class-based components, this means the child must be a __functional__ component that uses the `React.forwardRef()` API.
153
+ >
154
+ > If you must use a __class__-based component as the trap's container, then you will need to get your own ref to it upon render, and use the `containerElements` prop (initially set to an empty array `[]`) in order to provide the ref's element to it once updated by React (hint: use a [callback ref](https://reactjs.org/docs/refs-and-the-dom.html#callback-refs)).
155
+
156
+ > 💬 The child is ignored (but still rendered) if the `containerElements` prop is used to imperatively provide trap container elements.
157
+
158
+ Example:
159
+
160
+ ```jsx
161
+ const React = require('react');
162
+ const { createRoot } = require('react-dom/client');
163
+ const propTypes = require('prop-types');
164
+ const FocusTrap = require('../../dist/focus-trap-react');
165
+
166
+ const container = document.getElementById('demo-function-child');
167
+
168
+ const TrapChild = React.forwardRef(function ({ onDeactivate }, ref) {
169
+ return (
170
+ <div ref={ref}>
171
+ <p>
172
+ Here is a focus trap <a href="#">with</a> <a href="#">some</a>{' '}
173
+ <a href="#">focusable</a> parts.
174
+ </p>
175
+ <p>
176
+ <button
177
+ onClick={onDeactivate}
178
+ aria-describedby="class-child-heading"
179
+ >
180
+ deactivate trap
181
+ </button>
182
+ </p>
183
+ </div>
184
+ );
185
+ });
186
+
187
+ TrapChild.displayName = 'TrapChild';
188
+ TrapChild.propTypes = {
189
+ onDeactivate: propTypes.func,
190
+ };
191
+
192
+ class DemoFunctionChild extends React.Component {
193
+ constructor(props) {
194
+ super(props);
195
+
196
+ this.state = {
197
+ activeTrap: false,
198
+ };
199
+
200
+ this.mountTrap = this.mountTrap.bind(this);
201
+ this.unmountTrap = this.unmountTrap.bind(this);
202
+ }
203
+
204
+ mountTrap() {
205
+ this.setState({ activeTrap: true });
206
+ }
207
+
208
+ unmountTrap() {
209
+ this.setState({ activeTrap: false });
210
+ }
211
+
212
+ render() {
213
+ const trap = this.state.activeTrap && (
214
+ <FocusTrap
215
+ focusTrapOptions={{
216
+ onDeactivate: this.unmountTrap,
217
+ }}
218
+ >
219
+ <TrapChild />
220
+ </FocusTrap>
221
+ );
222
+
223
+ return (
224
+ <div>
225
+ <p>
226
+ <button onClick={this.mountTrap} aria-describedby="function-child-heading">
227
+ activate trap
228
+ </button>
229
+ </p>
230
+ {trap}
231
+ </div>
232
+ );
233
+ }
234
+ }
235
+
236
+ const root = createRoot(container);
237
+ root.render(<DemoFunctionChild />);
238
+ ```
239
+
142
240
  #### focusTrapOptions
143
241
 
144
242
  Type: `Object`, optional
@@ -165,9 +263,11 @@ If you would like to pause or unpause the focus trap (see [`focus-trap`'s docume
165
263
 
166
264
  Type: `Array of HTMLElement`, optional
167
265
 
168
- If passed in, these elements will be used as the boundaries for the focus-trap, __instead of the child__. These get passed as arguments to `focus-trap`'s `updateContainerElements()` method.
266
+ If specified, these elements will be used as the boundaries for the focus-trap, __instead of the child__. These get passed as arguments to `focus-trap`'s `updateContainerElements()` method.
169
267
 
170
- > Note that when you use `containerElements`, the need for a child is eliminated as the child is __always__ ignored when the prop is specified, even if the prop is `[]` (an empty array). Also note that if the refs you're putting into the array like `containerElements={[ref1.current, ref2.current]}` and one or both refs aren't resolved yet, resulting in `[null, null]` for example, the trap will not get created. The array must contain at least one `HTMLElement` in order for the trap to get updated.
268
+ > 💬 Note that when you use `containerElements`, the need for a child is eliminated as the child is __always__ ignored (though still rendered) when the prop is specified, even if this prop is `[]` (an empty array).
269
+ >
270
+ > Also note that if the refs you're putting into the array, like `containerElements={[ref1.current, ref2.current]}`, aren't resolved yet, resulting in `[null, null]` for example, the trap will not get created. The array must contain at least one valid `HTMLElement` in order for the trap to get created/updated.
171
271
 
172
272
  If `containerElements` is subsequently updated (i.e. after the trap has been created) to an empty array (or an array of falsy values like `[null, null]`), the trap will still be active, but the TAB key will do nothing because the trap will not contain any tabbable groups of nodes. At this point, the trap can either be deactivated manually or by unmounting, or an updated set of elements can be given to `containerElements` to resume use of the TAB key.
173
273
 
@@ -464,7 +464,7 @@ FocusTrap.propTypes = {
464
464
  allowOutsideClick: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
465
465
  preventScroll: PropTypes.bool,
466
466
  tabbableOptions: PropTypes.shape({
467
- displayCheck: PropTypes.oneOf(['full', 'non-zero-area', 'none']),
467
+ displayCheck: PropTypes.oneOf(['full', 'legacy-full', 'non-zero-area', 'none']),
468
468
  getShadowRoot: PropTypes.oneOfType([PropTypes.bool, PropTypes.func])
469
469
  })
470
470
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "focus-trap-react",
3
- "version": "9.0.2",
3
+ "version": "10.0.0",
4
4
  "description": "A React component that traps focus.",
5
5
  "main": "dist/focus-trap-react.js",
6
6
  "types": "index.d.ts",
@@ -57,46 +57,46 @@
57
57
  },
58
58
  "homepage": "https://github.com/focus-trap/focus-trap-react#readme",
59
59
  "devDependencies": {
60
- "@babel/cli": "^7.17.10",
61
- "@babel/core": "^7.18.5",
62
- "@babel/eslint-parser": "^7.18.2",
63
- "@babel/plugin-proposal-class-properties": "^7.17.12",
64
- "@babel/preset-env": "^7.18.2",
65
- "@babel/preset-react": "^7.17.12",
66
- "@changesets/cli": "^2.23.0",
60
+ "@babel/cli": "^7.18.10",
61
+ "@babel/core": "^7.18.13",
62
+ "@babel/eslint-parser": "^7.18.9",
63
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
64
+ "@babel/preset-env": "^7.18.10",
65
+ "@babel/preset-react": "^7.18.6",
66
+ "@changesets/cli": "^2.24.3",
67
67
  "@testing-library/cypress": "^8.0.3",
68
- "@testing-library/dom": "^8.13.0",
69
- "@testing-library/jest-dom": "^5.16.4",
68
+ "@testing-library/dom": "^8.17.1",
69
+ "@testing-library/jest-dom": "^5.16.5",
70
70
  "@testing-library/react": "^13.3.0",
71
- "@testing-library/user-event": "^14.2.0",
71
+ "@testing-library/user-event": "^14.4.3",
72
72
  "@types/jquery": "^3.5.14",
73
73
  "all-contributors-cli": "^6.20.0",
74
- "babel-jest": "^28.1.1",
74
+ "babel-jest": "^28.1.3",
75
75
  "babelify": "^10.0.0",
76
76
  "browserify": "^17.0.0",
77
77
  "budo": "^11.7.0",
78
- "cypress": "^10.1.0",
78
+ "cypress": "^10.6.0",
79
79
  "cypress-plugin-tab": "^1.0.5",
80
- "eslint": "^8.17.0",
80
+ "eslint": "^8.22.0",
81
81
  "eslint-config-prettier": "^8.5.0",
82
82
  "eslint-plugin-cypress": "^2.12.1",
83
- "eslint-plugin-jest": "^26.5.3",
84
- "eslint-plugin-react": "^7.30.0",
85
- "jest": "^28.1.1",
86
- "jest-environment-jsdom": "^28.1.1",
87
- "jest-watch-typeahead": "^1.1.0",
83
+ "eslint-plugin-jest": "^26.8.7",
84
+ "eslint-plugin-react": "^7.30.1",
85
+ "jest": "^28.1.3",
86
+ "jest-environment-jsdom": "^28.1.3",
87
+ "jest-watch-typeahead": "^2.0.0",
88
88
  "onchange": "^7.1.0",
89
- "prettier": "^2.7.0",
89
+ "prettier": "^2.7.1",
90
90
  "prop-types": "^15.8.1",
91
91
  "react": "^18.2.0",
92
92
  "react-dom": "^18.2.0",
93
93
  "regenerator-runtime": "^0.13.9",
94
94
  "start-server-and-test": "^1.14.0",
95
- "typescript": "^4.7.3"
95
+ "typescript": "^4.7.4"
96
96
  },
97
97
  "dependencies": {
98
- "focus-trap": "^6.9.4",
99
- "tabbable": "^5.3.3"
98
+ "focus-trap": "^7.0.0",
99
+ "tabbable": "^6.0.0"
100
100
  },
101
101
  "peerDependencies": {
102
102
  "prop-types": "^15.8.1",
@@ -453,7 +453,12 @@ FocusTrap.propTypes = {
453
453
  allowOutsideClick: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
454
454
  preventScroll: PropTypes.bool,
455
455
  tabbableOptions: PropTypes.shape({
456
- displayCheck: PropTypes.oneOf(['full', 'non-zero-area', 'none']),
456
+ displayCheck: PropTypes.oneOf([
457
+ 'full',
458
+ 'legacy-full',
459
+ 'non-zero-area',
460
+ 'none',
461
+ ]),
457
462
  getShadowRoot: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
458
463
  }),
459
464
  }),