focus-trap-react 10.3.1 → 11.0.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,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 11.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - cd75caa: Fix missing default export in typings; props no longer extend `React.AllHTMLAttributes<any>` to allow things like `className` (those extra props have always been ignored anyway); deprecate default export; add named export in code ([#1396](https://github.com/focus-trap/focus-trap-react/issues/1396))
8
+
9
+ ## 11.0.0
10
+
11
+ ### Major Changes
12
+
13
+ - 4a37dae: Dropping `propTypes` and `defaultProps` no longer supported by React 19 and long deprecated in React 18 (going forward, use TypeScript for prop typings, and if necessary, a runtime library to validate props); Increasing minimum supported React version up to >=18; Bumping `focus-trap` dependency to v7.6.2
14
+
3
15
  ## 10.3.1
4
16
 
5
17
  ### Patch 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-28-orange.svg?style=flat-square)](#contributors)
4
+ [![All Contributors](https://img.shields.io/badge/all_contributors-29-orange.svg?style=flat-square)](#contributors)
5
5
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
6
6
 
7
7
  A React component that traps focus.
@@ -33,14 +33,23 @@ npm install focus-trap-react
33
33
 
34
34
  ### React dependency
35
35
 
36
- React `>= 16.3.0`
36
+ React `>= 18.0.0`
37
37
 
38
- ## Browser Support
38
+ > Note that while React 18.x still supported `propTypes` and `defaultProps`, they had long-since been deprecated, and are completely dropped in React 19.
39
+
40
+ Therefore, this library no longer assigns these properties to the `<FocusTrap>` element for runtime validation and initialization. The same techniques you would now use in React 19 are backward-compatible with React 18:
41
+
42
+ - Use TypeScript for static prop type validation
43
+ - Use a runtime validation library such as [RTV.js](https://rtvjs.stefcameron.com/), [JSON Schema](https://json-schema.org/), or [yup](https://github.com/jquense/yup) for runtime prop validation to replace `prop-types`)
39
44
 
40
- As old and as broad as _reasonably_ possible, excluding browsers that are out of support or have nearly no user base.
45
+ > This library aims to support one major version of React _behind_ the current major version, since React major releases are typically years apart -- to the extent that the feature drift is not too great and remains reasonably surmountable.
46
+
47
+ ## Browser Support
41
48
 
42
49
  Focused on desktop browsers, particularly Chrome, Edge, FireFox, Safari, and Opera.
43
50
 
51
+ Gated by what React [supports](https://legacy.reactjs.org/docs/javascript-environment-requirements.html) in the version [currently](#react-dependency) supported.
52
+
44
53
  Focus-trap-react is not officially tested on any mobile browsers or devices.
45
54
 
46
55
  > ⚠️ 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.
@@ -75,10 +84,9 @@ You can read further code examples in `demo/` (it's very simple), and [see how i
75
84
  Here's one more simple example:
76
85
 
77
86
  ```jsx
78
- const React = require('react');
79
- const ReactDOM = require('react-dom'); // React 16-17
80
- const { createRoot } = require('react-dom/client'); // React 18
81
- const FocusTrap = require('focus-trap-react');
87
+ import React from 'react';
88
+ import { createRoot } from 'react-dom/client';
89
+ import { FocusTrap } from 'focus-trap-react';
82
90
 
83
91
  class Demo extends React.Component {
84
92
  constructor(props) {
@@ -141,7 +149,6 @@ class Demo extends React.Component {
141
149
  }
142
150
  }
143
151
 
144
- ReactDOM.render(<Demo />, document.getElementById('root')); // React 16-17
145
152
  createRoot(document.getElementById('root')).render(<Demo />); // React 18
146
153
  ```
147
154
 
@@ -183,14 +190,13 @@ The result can be that (depending on how you render the trap) in Strict Mode, th
183
190
  Example:
184
191
 
185
192
  ```jsx
186
- const React = require('react');
187
- const { createRoot } = require('react-dom/client');
188
- const propTypes = require('prop-types');
189
- const FocusTrap = require('../../dist/focus-trap-react');
193
+ import { forwardRef, Component } from 'react';
194
+ import { createRoot } from 'react-dom/client';
195
+ import { FocusTrap } from 'focus-trap-react';
190
196
 
191
197
  const container = document.getElementById('demo-function-child');
192
198
 
193
- const TrapChild = React.forwardRef(function ({ onDeactivate }, ref) {
199
+ const TrapChild = forwardRef(function ({ onDeactivate }, ref) {
194
200
  return (
195
201
  <div ref={ref}>
196
202
  <p>
@@ -214,7 +220,7 @@ TrapChild.propTypes = {
214
220
  onDeactivate: propTypes.func,
215
221
  };
216
222
 
217
- class DemoFunctionChild extends React.Component {
223
+ class DemoFunctionChild extends Component {
218
224
  constructor(props) {
219
225
  super(props);
220
226
 
@@ -350,21 +356,24 @@ In alphabetical order:
350
356
  <td align="center" valign="top" width="14.28%"><a href="https://marais.io/"><img src="https://avatars2.githubusercontent.com/u/599459?v=4?s=100" width="100px;" alt="Marais Rossouw"/><br /><sub><b>Marais Rossouw</b></sub></a><br /><a href="#infra-maraisr" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
351
357
  </tr>
352
358
  <tr>
359
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Mathias-S"><img src="https://avatars.githubusercontent.com/u/225531?v=4?s=100" width="100px;" alt="Mathias Stang"/><br /><sub><b>Mathias Stang</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/issues?q=author%3AMathias-S" title="Bug reports">🐛</a> <a href="https://github.com/focus-trap/focus-trap-react/pulls?q=is%3Apr+reviewed-by%3AMathias-S" title="Reviewed Pull Requests">👀</a></td>
353
360
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/StackOverflowIsBetterThanAnyAI"><img src="https://avatars.githubusercontent.com/u/140268904?v=4?s=100" width="100px;" alt="Michael"/><br /><sub><b>Michael</b></sub></a><br /><a href="#example-StackOverflowIsBetterThanAnyAI" title="Examples">💡</a></td>
354
361
  <td align="center" valign="top" width="14.28%"><a href="https://www.moroshko.me"><img src="https://avatars.githubusercontent.com/u/259753?v=4?s=100" width="100px;" alt="Misha Moroshko"/><br /><sub><b>Misha Moroshko</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/issues?q=author%3Amoroshko" title="Bug reports">🐛</a></td>
355
362
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/liunate"><img src="https://avatars2.githubusercontent.com/u/38996291?v=4?s=100" width="100px;" alt="Nate Liu"/><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>
356
363
  <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/rivajunior/"><img src="https://avatars1.githubusercontent.com/u/11370172?v=4?s=100" width="100px;" alt="Rivaldo Junior"/><br /><sub><b>Rivaldo Junior</b></sub></a><br /><a href="#maintenance-rivajunior" title="Maintenance">🚧</a></td>
357
364
  <td align="center" valign="top" width="14.28%"><a href="https://scottrippey.github.io/"><img src="https://avatars3.githubusercontent.com/u/430608?v=4?s=100" width="100px;" alt="Scott Rippey"/><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>
358
365
  <td align="center" valign="top" width="14.28%"><a href="https://seanmcp.com/"><img src="https://avatars1.githubusercontent.com/u/6360367?v=4?s=100" width="100px;" alt="Sean McPherson"/><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>
359
- <td align="center" valign="top" width="14.28%"><a href="http://smoores.dev"><img src="https://avatars.githubusercontent.com/u/5354254?v=4?s=100" width="100px;" alt="Shane Moore"/><br /><sub><b>Shane Moore</b></sub></a><br /><a href="#platform-SMores" title="Packaging/porting to new platform">📦</a></td>
360
366
  </tr>
361
367
  <tr>
368
+ <td align="center" valign="top" width="14.28%"><a href="http://smoores.dev"><img src="https://avatars.githubusercontent.com/u/5354254?v=4?s=100" width="100px;" alt="Shane Moore"/><br /><sub><b>Shane Moore</b></sub></a><br /><a href="#platform-SMores" title="Packaging/porting to new platform">📦</a></td>
362
369
  <td align="center" valign="top" width="14.28%"><a href="https://recollectr.io"><img src="https://avatars2.githubusercontent.com/u/6835891?v=4?s=100" width="100px;" alt="Slapbox"/><br /><sub><b>Slapbox</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/commits?author=Slapbox" title="Documentation">📖</a> <a href="https://github.com/focus-trap/focus-trap-react/issues?q=author%3ASlapbox" title="Bug reports">🐛</a></td>
363
370
  <td align="center" valign="top" width="14.28%"><a href="https://stefancameron.com/"><img src="https://avatars3.githubusercontent.com/u/2855350?v=4?s=100" width="100px;" alt="Stefan Cameron"/><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>
364
371
  <td align="center" valign="top" width="14.28%"><a href="http://tylerhawkins.info/201R/"><img src="https://avatars0.githubusercontent.com/u/13806458?v=4?s=100" width="100px;" alt="Tyler Hawkins"/><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>
365
372
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/wandroll"><img src="https://avatars.githubusercontent.com/u/4492317?v=4?s=100" width="100px;" alt="Wandrille Verlut"/><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>
366
373
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/krikienoid"><img src="https://avatars3.githubusercontent.com/u/8528227?v=4?s=100" width="100px;" alt="krikienoid"/><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>
367
374
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/robert-westenberger"><img src="https://avatars.githubusercontent.com/u/44252092?v=4?s=100" width="100px;" alt="robert-westenberger"/><br /><sub><b>robert-westenberger</b></sub></a><br /><a href="https://github.com/focus-trap/focus-trap-react/commits?author=robert-westenberger" title="Documentation">📖</a> <a href="https://github.com/focus-trap/focus-trap-react/issues?q=author%3Arobert-westenberger" title="Bug reports">🐛</a></td>
375
+ </tr>
376
+ <tr>
368
377
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/syntactic-salt"><img src="https://avatars.githubusercontent.com/u/9385662?v=4?s=100" width="100px;" alt="syntactic-salt"/><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>
369
378
  </tr>
370
379
  </tbody>
@@ -15,11 +15,14 @@ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object
15
15
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
16
16
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
17
17
  var React = require('react');
18
- var PropTypes = require('prop-types');
19
18
  var _require = require('focus-trap'),
20
19
  createFocusTrap = _require.createFocusTrap;
21
20
  var _require2 = require('tabbable'),
22
21
  isFocusable = _require2.isFocusable;
22
+
23
+ /**
24
+ * @type {import('../index.d.ts').FocusTrap}
25
+ */
23
26
  var FocusTrap = /*#__PURE__*/function (_React$Component) {
24
27
  function FocusTrap(props) {
25
28
  var _this;
@@ -386,56 +389,19 @@ var FocusTrap = /*#__PURE__*/function (_React$Component) {
386
389
  return null;
387
390
  }
388
391
  }]);
389
- }(React.Component); // support server-side rendering where `Element` will not be defined
390
- var ElementType = typeof Element === 'undefined' ? Function : Element;
391
- FocusTrap.propTypes = {
392
- active: PropTypes.bool,
393
- paused: PropTypes.bool,
394
- focusTrapOptions: PropTypes.shape({
395
- document: PropTypes.object,
396
- onActivate: PropTypes.func,
397
- onPostActivate: PropTypes.func,
398
- checkCanFocusTrap: PropTypes.func,
399
- onPause: PropTypes.func,
400
- onPostPause: PropTypes.func,
401
- onUnpause: PropTypes.func,
402
- onPostUnpause: PropTypes.func,
403
- onDeactivate: PropTypes.func,
404
- onPostDeactivate: PropTypes.func,
405
- checkCanReturnFocus: PropTypes.func,
406
- initialFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.bool, PropTypes.func]),
407
- fallbackFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string,
408
- // NOTE: does not support `false` as value (or return value from function)
409
- PropTypes.func]),
410
- escapeDeactivates: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
411
- clickOutsideDeactivates: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
412
- returnFocusOnDeactivate: PropTypes.bool,
413
- setReturnFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.bool, PropTypes.func]),
414
- allowOutsideClick: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
415
- preventScroll: PropTypes.bool,
416
- tabbableOptions: PropTypes.shape({
417
- displayCheck: PropTypes.oneOf(['full', 'legacy-full', 'non-zero-area', 'none']),
418
- getShadowRoot: PropTypes.oneOfType([PropTypes.bool, PropTypes.func])
419
- }),
420
- trapStack: PropTypes.array,
421
- isKeyForward: PropTypes.func,
422
- isKeyBackward: PropTypes.func
423
- }),
424
- containerElements: PropTypes.arrayOf(PropTypes.instanceOf(ElementType)),
425
- // DOM element ONLY
426
- children: PropTypes.oneOfType([PropTypes.element,
427
- // React element
428
- PropTypes.instanceOf(ElementType) // DOM element
429
- ])
430
-
431
- // NOTE: _createFocusTrap is internal, for testing purposes only, so we don't
432
- // specify it here. It's expected to be set to the function returned from
433
- // require('focus-trap'), or one with a compatible interface.
434
- };
392
+ }(React.Component); // NOTE: While React 19 REMOVED support for `propTypes`, support for `defaultProps`
393
+ // __for class components ONLY__ remains: "Class components will continue to support
394
+ // defaultProps since there is no ES6 alternative."
395
+ // @see https://react.dev/blog/2024/04/25/react-19-upgrade-guide#removed-proptypes-and-defaultprops
435
396
  FocusTrap.defaultProps = {
436
397
  active: true,
437
398
  paused: false,
438
399
  focusTrapOptions: {},
439
400
  _createFocusTrap: createFocusTrap
440
401
  };
441
- module.exports = FocusTrap;
402
+
403
+ // 🔺 DEPRECATED: default export
404
+ module.exports = FocusTrap;
405
+
406
+ // named export
407
+ module.exports.FocusTrap = FocusTrap;
package/index.d.ts CHANGED
@@ -1,16 +1,56 @@
1
1
  import { Options as FocusTrapOptions } from 'focus-trap';
2
2
  import * as React from 'react';
3
3
 
4
- export = FocusTrap;
4
+ export interface FocusTrapProps {
5
+ /**
6
+ * __Single container child__ for the trap. Use `containerElements` instead
7
+ * if you need a trap with multiple containers.
8
+ */
9
+ children?: React.ReactNode;
5
10
 
11
+ /**
12
+ * By default, the trap will be active when it mounts, so it's activated by
13
+ * mounting, and deactivated by unmounting. Use this prop to control when
14
+ * it's active while it's mounted, or if it's initially inactive.
15
+ */
16
+ active?: boolean;
17
+
18
+ /**
19
+ * To pause or unpause the trap while it's `active`. Primarily for use when
20
+ * you need to manage multiple traps in the same view. When paused, the trap
21
+ * retains its various event listeners, but ignores all events.
22
+ */
23
+ paused?: boolean;
24
+
25
+ /**
26
+ * See Focus-trap's [createOptions](https://github.com/focus-trap/focus-trap?tab=readme-ov-file#createoptions)
27
+ * for more details on available options.
28
+ */
29
+ focusTrapOptions?: FocusTrapOptions;
30
+
31
+ /**
32
+ * If specified, these elements will be used as the boundaries for the
33
+ * trap, __instead of the child__ specified in `children` (though
34
+ * `children` will still be rendered).
35
+ */
36
+ containerElements?: Array<HTMLElement>;
37
+ }
38
+
39
+ export declare class FocusTrap extends React.Component<FocusTrapProps> { }
40
+
41
+ /**
42
+ * Default export of the FocusTrap component.
43
+ * @deprecated 🔺 Use the named import `{ FocusTrap }` instead.
44
+ * @description 🔺 The default export will be removed in a future release. Migrate to the named
45
+ * import `{ FocusTrap }` today to ensure future compatibility.
46
+ */
6
47
  declare namespace FocusTrap {
7
- export interface Props extends React.AllHTMLAttributes<any> {
8
- children?: React.ReactNode;
9
- active?: boolean;
10
- paused?: boolean;
11
- focusTrapOptions?: FocusTrapOptions;
12
- containerElements?: Array<HTMLElement>;
13
- }
48
+ export type Props = FocusTrapProps;
14
49
  }
15
50
 
16
- declare class FocusTrap extends React.Component<FocusTrap.Props> { }
51
+ /**
52
+ * @deprecated 🔺 Use the named import `{ FocusTrap }` instead.
53
+ * @description 🔺 The default export will be removed in a future release. Migrate to the named
54
+ * import `{ FocusTrap }` today to ensure future compatibility.
55
+ */
56
+ export default FocusTrap;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "focus-trap-react",
3
- "version": "10.3.1",
3
+ "version": "11.0.1",
4
4
  "description": "A React component that traps focus.",
5
5
  "main": "dist/focus-trap-react.js",
6
6
  "types": "index.d.ts",
@@ -57,25 +57,27 @@
57
57
  },
58
58
  "homepage": "https://github.com/focus-trap/focus-trap-react#readme",
59
59
  "devDependencies": {
60
- "@babel/cli": "^7.25.9",
60
+ "@babel/cli": "^7.26.4",
61
61
  "@babel/core": "^7.26.0",
62
62
  "@babel/eslint-parser": "^7.25.9",
63
63
  "@babel/plugin-proposal-class-properties": "^7.18.6",
64
64
  "@babel/preset-env": "^7.26.0",
65
- "@babel/preset-react": "^7.25.9",
66
- "@changesets/cli": "^2.27.9",
65
+ "@babel/preset-react": "^7.26.3",
66
+ "@changesets/cli": "^2.27.10",
67
67
  "@testing-library/cypress": "^10.0.2",
68
68
  "@testing-library/dom": "^10.4.0",
69
69
  "@testing-library/jest-dom": "^6.6.3",
70
- "@testing-library/react": "^16.0.1",
70
+ "@testing-library/react": "^16.1.0",
71
71
  "@testing-library/user-event": "^14.5.2",
72
72
  "@types/jquery": "^3.5.32",
73
+ "@types/react": "^18.3.1",
74
+ "@types/react-dom": "^18.3.0",
73
75
  "all-contributors-cli": "^6.26.1",
74
76
  "babel-jest": "^29.7.0",
75
77
  "babelify": "^10.0.0",
76
78
  "browserify": "^17.0.1",
77
79
  "budo": "^11.8.4",
78
- "cypress": "^13.15.2",
80
+ "cypress": "^13.16.1",
79
81
  "cypress-plugin-tab": "^1.0.5",
80
82
  "eslint": "^8.57.0",
81
83
  "eslint-config-prettier": "^9.1.0",
@@ -86,21 +88,21 @@
86
88
  "jest-environment-jsdom": "^29.7.0",
87
89
  "jest-watch-typeahead": "^2.2.2",
88
90
  "onchange": "^7.1.0",
89
- "prettier": "^3.3.3",
90
- "prop-types": "^15.8.1",
91
+ "prettier": "^3.4.2",
91
92
  "react": "^18.3.1",
92
93
  "react-dom": "^18.3.1",
93
94
  "regenerator-runtime": "^0.14.1",
94
- "start-server-and-test": "^2.0.8",
95
- "typescript": "^5.6.3"
95
+ "start-server-and-test": "^2.0.9",
96
+ "typescript": "^5.7.2"
96
97
  },
97
98
  "dependencies": {
98
- "focus-trap": "^7.6.1",
99
+ "focus-trap": "^7.6.2",
99
100
  "tabbable": "^6.2.0"
100
101
  },
101
102
  "peerDependencies": {
102
- "prop-types": "^15.8.1",
103
- "react": ">=16.3.0",
104
- "react-dom": ">=16.3.0"
103
+ "@types/react": "^18.0.0 || ^19.0.0",
104
+ "@types/react-dom": "^18.0.0 || ^19.0.0",
105
+ "react": "^18.0.0 || ^19.0.0",
106
+ "react-dom": "^18.0.0 || ^19.0.0"
105
107
  }
106
108
  }
@@ -1,8 +1,10 @@
1
1
  const React = require('react');
2
- const PropTypes = require('prop-types');
3
2
  const { createFocusTrap } = require('focus-trap');
4
3
  const { isFocusable } = require('tabbable');
5
4
 
5
+ /**
6
+ * @type {import('../index.d.ts').FocusTrap}
7
+ */
6
8
  class FocusTrap extends React.Component {
7
9
  constructor(props) {
8
10
  super(props);
@@ -412,74 +414,10 @@ class FocusTrap extends React.Component {
412
414
  }
413
415
  }
414
416
 
415
- // support server-side rendering where `Element` will not be defined
416
- const ElementType = typeof Element === 'undefined' ? Function : Element;
417
-
418
- FocusTrap.propTypes = {
419
- active: PropTypes.bool,
420
- paused: PropTypes.bool,
421
- focusTrapOptions: PropTypes.shape({
422
- document: PropTypes.object,
423
- onActivate: PropTypes.func,
424
- onPostActivate: PropTypes.func,
425
- checkCanFocusTrap: PropTypes.func,
426
- onPause: PropTypes.func,
427
- onPostPause: PropTypes.func,
428
- onUnpause: PropTypes.func,
429
- onPostUnpause: PropTypes.func,
430
- onDeactivate: PropTypes.func,
431
- onPostDeactivate: PropTypes.func,
432
- checkCanReturnFocus: PropTypes.func,
433
- initialFocus: PropTypes.oneOfType([
434
- PropTypes.instanceOf(ElementType),
435
- PropTypes.string,
436
- PropTypes.bool,
437
- PropTypes.func,
438
- ]),
439
- fallbackFocus: PropTypes.oneOfType([
440
- PropTypes.instanceOf(ElementType),
441
- PropTypes.string,
442
- // NOTE: does not support `false` as value (or return value from function)
443
- PropTypes.func,
444
- ]),
445
- escapeDeactivates: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
446
- clickOutsideDeactivates: PropTypes.oneOfType([
447
- PropTypes.bool,
448
- PropTypes.func,
449
- ]),
450
- returnFocusOnDeactivate: PropTypes.bool,
451
- setReturnFocus: PropTypes.oneOfType([
452
- PropTypes.instanceOf(ElementType),
453
- PropTypes.string,
454
- PropTypes.bool,
455
- PropTypes.func,
456
- ]),
457
- allowOutsideClick: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
458
- preventScroll: PropTypes.bool,
459
- tabbableOptions: PropTypes.shape({
460
- displayCheck: PropTypes.oneOf([
461
- 'full',
462
- 'legacy-full',
463
- 'non-zero-area',
464
- 'none',
465
- ]),
466
- getShadowRoot: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
467
- }),
468
- trapStack: PropTypes.array,
469
- isKeyForward: PropTypes.func,
470
- isKeyBackward: PropTypes.func,
471
- }),
472
- containerElements: PropTypes.arrayOf(PropTypes.instanceOf(ElementType)), // DOM element ONLY
473
- children: PropTypes.oneOfType([
474
- PropTypes.element, // React element
475
- PropTypes.instanceOf(ElementType), // DOM element
476
- ]),
477
-
478
- // NOTE: _createFocusTrap is internal, for testing purposes only, so we don't
479
- // specify it here. It's expected to be set to the function returned from
480
- // require('focus-trap'), or one with a compatible interface.
481
- };
482
-
417
+ // NOTE: While React 19 REMOVED support for `propTypes`, support for `defaultProps`
418
+ // __for class components ONLY__ remains: "Class components will continue to support
419
+ // defaultProps since there is no ES6 alternative."
420
+ // @see https://react.dev/blog/2024/04/25/react-19-upgrade-guide#removed-proptypes-and-defaultprops
483
421
  FocusTrap.defaultProps = {
484
422
  active: true,
485
423
  paused: false,
@@ -487,4 +425,8 @@ FocusTrap.defaultProps = {
487
425
  _createFocusTrap: createFocusTrap,
488
426
  };
489
427
 
428
+ // 🔺 DEPRECATED: default export
490
429
  module.exports = FocusTrap;
430
+
431
+ // named export
432
+ module.exports.FocusTrap = FocusTrap;