focus-trap-react 6.0.0 → 8.1.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,40 @@
1
1
  # Changelog
2
2
 
3
+ ## 8.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 5994a8c: Bump focus-trap from 6.0.1 to 6.1.0. This new version of focus-trap provides a new `delayInitialFocus` flag that can be used to further customize trap behavior.
8
+
9
+ ### Patch Changes
10
+
11
+ - 0562ef0: Change `prepublishOnly` script to `prepare` script so that it also runs if someone installs the package directly from the git repo (e.g. from your work in which you fixed a bug or added a feature you're waiting to get merged to master and published to NPM).
12
+
13
+ ## 8.0.0
14
+
15
+ ### Major Changes
16
+
17
+ - 513a2d3: **BREAKING**: Updated [focus-trap](https://github.com/focus-trap/focus-trap/blob/master/CHANGELOG.md#600) dependency to new 6.0.1 release, which contains breaking changes. This update means it's also now using the latest version of [tabbable](https://github.com/focus-trap/tabbable/blob/master/CHANGELOG.md#500), which also has breaking changes. See respective CHANGELOGs for details.
18
+
19
+ ### Patch Changes
20
+
21
+ - 35040fa: Remove call for maintainers. @stefcameron and @maraisr hope to take up the charge. Additional help and contributors are most welcome for anyone interested!
22
+ - 513a2d3: Changed code formatting to use dangling commas where ES5 supports them.
23
+
24
+ ## 7.0.1
25
+
26
+ - Fix: PropTypes definition now supports server-side rendering. [#83](https://github.com/davidtheclark/focus-trap-react/issues/83)
27
+
28
+ ## 7.0.0
29
+
30
+ - Add: Prop types for `<FocusTrap>`.
31
+ - Update: `focus-trap` dependency from 4.0.2 to [5.1.0](https://github.com/davidtheclark/focus-trap/blob/master/CHANGELOG.md#510) for the latest features/fixes it provides. [#71](https://github.com/davidtheclark/focus-trap-react/issues/71)
32
+ - **BREAKING** Update: Only React 16.0+ is supported going forward. [#55](https://github.com/davidtheclark/focus-trap-react/issues/55)
33
+ - **BREAKING** Update: All dependencies updated to their latest versions.
34
+ - Fix: `children`'s type is `React.ReactNode`, not `React.ReactElement`. [#66](https://github.com/davidtheclark/focus-trap-react/issues/66)
35
+ - Fix: Allow mutable object refs to be used for FocusTrap child. [#72](https://github.com/davidtheclark/focus-trap-react/issues/72)
36
+ - Fix: `specifiedFocusTrapOptions.includes(optionName)` statement in `componentDidMount()` was causing an exception because `includes()` is not a function defined on `Object`.
37
+
3
38
  ## 6.0.0
4
39
 
5
40
  - Update focus-trap to 4.0.2, which includes [a queue of traps](https://github.com/davidtheclark/focus-trap/blob/master/CHANGELOG.md#400), so when a trap is paused because another trap activates, it will be unpaused when that other trap deactivates. If Trap A was automatically paused because Trap B activated (existing behavior), when Trap B is deactivated Trap A will be automatically unpaused (new behavior).
@@ -10,7 +45,7 @@
10
45
 
11
46
  ## 5.0.0
12
47
 
13
- - **Breaking change:** `<FocusTrap>` now expects exactly one child element which can be any HTML element or other React component that contains focusable elements. The `tag` prop has been removed, as has support for additional props that are passed through to the `tag`, because it is no longer necessary: you should provide your own element, with whatever props you want, as a child of `<FocusTrap>`.
48
+ - **BREAKING:** `<FocusTrap>` now expects exactly one child element which can be any HTML element or other React component that contains focusable elements. The `tag` prop has been removed, as has support for additional props that are passed through to the `tag`, because it is no longer necessary: you should provide your own element, with whatever props you want, as a child of `<FocusTrap>`.
14
49
 
15
50
  ## 4.0.1
16
51
 
@@ -19,7 +54,7 @@
19
54
  ## 4.0.0
20
55
 
21
56
  - Update focus-trap to 3.0.0, which includes [a couple of behavior changes](https://github.com/davidtheclark/focus-trap/blob/master/CHANGELOG.md#300). The key change is that focus management has been changed so that you can include tricky focusable elements like radio groups, iframes, and shadow DOM components in your trap — as long as the first and last focusable elements in the trap can still be detected by [Tabbable](https://github.com/davidtheclark/tabbable).
22
- - An effect of this change is that *positive tabindexes are no longer guaranteed to work as expected*. You should avoid these.
57
+ - An effect of this change is that _positive tabindexes are no longer guaranteed to work as expected_. You should avoid these.
23
58
 
24
59
  ## 3.1.4
25
60
 
@@ -51,8 +86,7 @@
51
86
 
52
87
  ## 3.0.3
53
88
 
54
- - Introduce `dist/focus-trap-react.js`, where `src/` now compiles to, since React 15.5+ demands `class`es, so Babel-compilation.
55
- Which is actually a huge overhaul, though in semver it's just a patch.
89
+ - Introduce `dist/focus-trap-react.js`, where `src/` now compiles to, since React 15.5+ demands `class`es, so Babel-compilation. Which is actually a huge overhaul, though in semver it's just a patch.
56
90
 
57
91
  ## 3.0.2
58
92
 
package/README.md CHANGED
@@ -1,23 +1,21 @@
1
- # focus-trap-react [![Build Status](https://travis-ci.org/davidtheclark/focus-trap-react.svg?branch=master)](https://travis-ci.org/davidtheclark/focus-trap-react)
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) [![license](https://badgen.now.sh/badge/license/MIT)](./LICENSE)
2
+
3
+ <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
4
+ [![All Contributors](https://img.shields.io/badge/all_contributors-12-orange.svg?style=flat-square)](#contributors)
5
+ <!-- ALL-CONTRIBUTORS-BADGE:END -->
2
6
 
3
7
  A React component that traps focus.
4
8
 
5
- This component is a light wrapper around [focus-trap](https://github.com/davidtheclark/focus-trap),
9
+ This component is a light wrapper around [focus-trap](https://github.com/focus-trap/focus-trap),
6
10
  tailored to your React-specific needs.
7
11
 
8
12
  You might want it for, say, building [an accessible modal](https://github.com/davidtheclark/react-aria-modal)?
9
13
 
10
- ---
11
-
12
- **Looking for co-maintainers!** If you'd like to help maintain this project, please let me know.
13
-
14
- ---
15
-
16
14
  ## What it does
17
15
 
18
- [Check out the demo](http://davidtheclark.github.io/focus-trap-react/demo/).
16
+ [Check out the demo](http://focus-trap.github.io/focus-trap-react/demo/).
19
17
 
20
- Please read [the focus-trap documentation](https://github.com/davidtheclark/focus-trap) to understand what a focus trap is, what happens when a focus trap is activated, and what happens when one is deactivated.
18
+ Please read [the focus-trap documentation](https://github.com/focus-trap/focus-trap) to understand what a focus trap is, what happens when a focus trap is activated, and what happens when one is deactivated.
21
19
 
22
20
  This module simply provides a React component that creates and manages a focus trap.
23
21
 
@@ -66,7 +64,7 @@ For example:
66
64
  </FocusTrap>
67
65
  ```
68
66
 
69
- You can read further code examples in `demo/` (it's very simple), and [see how it works](http://davidtheclark.github.io/focus-trap-react/demo/).
67
+ You can read further code examples in `demo/` (it's very simple), and [see how it works](http://focus-trap.github.io/focus-trap-react/demo/).
70
68
 
71
69
  Here's one more simple example:
72
70
 
@@ -147,7 +145,7 @@ ReactDOM.render(<DemoOne />, container);
147
145
 
148
146
  Type: `Object`, optional
149
147
 
150
- Pass any of the options available in [`focus-trap`'s `createOptions`](https://github.com/davidtheclark/focus-trap#focustrap--createfocustrapelement-createoptions).
148
+ Pass any of the options available in [`focus-trap`'s `createOptions`](https://github.com/focus-trap/focus-trap#focustrap--createfocustrapelement-createoptions).
151
149
 
152
150
  #### active
153
151
 
@@ -161,14 +159,39 @@ See `demo/demo-three.jsx`.
161
159
 
162
160
  Type: `Boolean`, optional
163
161
 
164
- If you would like to pause or unpause the focus trap (see [`focus-trap`'s documentation](https://github.com/davidtheclark/focus-trap#focustrappause)), toggle this prop.
165
-
166
- ## Contributing & Development
167
-
168
- Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
169
-
170
- Lint with `npm run lint`.
171
-
172
- Run the demos with `npm start`.
173
-
174
- Test with `npm run test`.
162
+ If you would like to pause or unpause the focus trap (see [`focus-trap`'s documentation](https://github.com/focus-trap/focus-trap#focustrappause)), toggle this prop.
163
+
164
+ ## Contributing
165
+
166
+ See [CONTRIBUTING](CONTRIBUTING.md).
167
+
168
+ ## Contributors
169
+
170
+ In alphabetical order:
171
+
172
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
173
+ <!-- prettier-ignore-start -->
174
+ <!-- markdownlint-disable -->
175
+ <table>
176
+ <tr>
177
+ <td align="center"><a href="https://github.com/Ayc0"><img src="https://avatars3.githubusercontent.com/u/22725671?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Benjamin Koltes</b></sub></a><br /><a href="https://github.com/stefcameron/focus-trap-react/issues?q=author%3AAyc0" title="Bug reports">🐛</a></td>
178
+ <td align="center"><a href="https://ofcr.se/"><img src="https://avatars1.githubusercontent.com/u/813865?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Benjamin Tan</b></sub></a><br /><a href="https://github.com/stefcameron/focus-trap-react/commits?author=bnjmnt4n" title="Documentation">📖</a></td>
179
+ <td align="center"><a href="https://github.com/DSil"><img src="https://avatars1.githubusercontent.com/u/6265045?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel</b></sub></a><br /><a href="#maintenance-DSil" title="Maintenance">🚧</a> <a href="https://github.com/stefcameron/focus-trap-react/commits?author=DSil" title="Tests">⚠️</a></td>
180
+ <td align="center"><a href="http://davidtheclark.com/"><img src="https://avatars2.githubusercontent.com/u/628431?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Clark</b></sub></a><br /><a href="https://github.com/stefcameron/focus-trap-react/commits?author=davidtheclark" title="Code">💻</a> <a href="https://github.com/stefcameron/focus-trap-react/issues?q=author%3Adavidtheclark" title="Bug reports">🐛</a> <a href="#infra-davidtheclark" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/stefcameron/focus-trap-react/commits?author=davidtheclark" title="Tests">⚠️</a> <a href="https://github.com/stefcameron/focus-trap-react/commits?author=davidtheclark" title="Documentation">📖</a> <a href="#maintenance-davidtheclark" title="Maintenance">🚧</a></td>
181
+ <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>
182
+ <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>
183
+ <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>
184
+ </tr>
185
+ <tr>
186
+ <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/stefcameron/focus-trap-react/commits?author=liunate" title="Tests">⚠️</a></td>
187
+ <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>
188
+ <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/stefcameron/focus-trap-react/commits?author=scottrippey" title="Code">💻</a> <a href="https://github.com/stefcameron/focus-trap-react/issues?q=author%3Ascottrippey" title="Bug reports">🐛</a></td>
189
+ <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/stefcameron/focus-trap-react/commits?author=SeanMcP" title="Code">💻</a></td>
190
+ <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/stefcameron/focus-trap-react/commits?author=stefcameron" title="Code">💻</a> <a href="https://github.com/stefcameron/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/stefcameron/focus-trap-react/commits?author=stefcameron" title="Tests">⚠️</a> <a href="https://github.com/stefcameron/focus-trap-react/commits?author=stefcameron" title="Documentation">📖</a> <a href="#maintenance-stefcameron" title="Maintenance">🚧</a></td>
191
+ </tr>
192
+ </table>
193
+
194
+ <!-- markdownlint-restore -->
195
+ <!-- prettier-ignore-end -->
196
+
197
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
@@ -1,37 +1,68 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
- var _createClass = function () { 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
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); }
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
- function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
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 _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
9
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
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); }
12
+
13
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
14
+
15
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
16
+
17
+ function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
18
+
19
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
20
+
21
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
22
+
23
+ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
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; }
10
26
 
11
27
  var React = require('react');
28
+
12
29
  var ReactDOM = require('react-dom');
13
- var createFocusTrap = require('focus-trap');
14
30
 
15
- var FocusTrap = function (_React$Component) {
31
+ var PropTypes = require('prop-types');
32
+
33
+ var _require = require('focus-trap'),
34
+ createFocusTrap = _require.createFocusTrap; // TODO: These issues are related to older React features which we'll likely need
35
+ // to fix in order to move the code forward to the next major version of React.
36
+ // @see https://github.com/davidtheclark/focus-trap-react/issues/77
37
+
38
+ /* eslint-disable react/no-find-dom-node */
39
+
40
+
41
+ var FocusTrap = /*#__PURE__*/function (_React$Component) {
16
42
  _inherits(FocusTrap, _React$Component);
17
43
 
44
+ var _super = _createSuper(FocusTrap);
45
+
18
46
  function FocusTrap(props) {
47
+ var _this;
48
+
19
49
  _classCallCheck(this, FocusTrap);
20
50
 
21
- var _this = _possibleConstructorReturn(this, (FocusTrap.__proto__ || Object.getPrototypeOf(FocusTrap)).call(this, props));
51
+ _this = _super.call(this, props);
22
52
 
23
- _this.setFocusTrapElement = function (element) {
53
+ _defineProperty(_assertThisInitialized(_this), "setFocusTrapElement", function (element) {
24
54
  _this.focusTrapElement = element;
25
- };
55
+ });
26
56
 
27
57
  if (typeof document !== 'undefined') {
28
58
  _this.previouslyFocusedElement = document.activeElement;
29
59
  }
60
+
30
61
  return _this;
31
62
  }
32
63
 
33
64
  _createClass(FocusTrap, [{
34
- key: 'componentDidMount',
65
+ key: "componentDidMount",
35
66
  value: function componentDidMount() {
36
67
  // We need to hijack the returnFocusOnDeactivate option,
37
68
  // because React can move focus into the element before we arrived at
@@ -42,30 +73,40 @@ var FocusTrap = function (_React$Component) {
42
73
  var tailoredFocusTrapOptions = {
43
74
  returnFocusOnDeactivate: false
44
75
  };
76
+
45
77
  for (var optionName in specifiedFocusTrapOptions) {
46
- if (!specifiedFocusTrapOptions.hasOwnProperty(optionName)) continue;
47
- if (optionName === 'returnFocusOnDeactivate') continue;
78
+ if (!Object.prototype.hasOwnProperty.call(specifiedFocusTrapOptions, optionName)) {
79
+ continue;
80
+ }
81
+
82
+ if (optionName === 'returnFocusOnDeactivate') {
83
+ continue;
84
+ }
85
+
48
86
  tailoredFocusTrapOptions[optionName] = specifiedFocusTrapOptions[optionName];
49
87
  }
50
88
 
51
- var focusTrapElementDOMNode = ReactDOM.findDOMNode(this.focusTrapElement);
89
+ var focusTrapElementDOMNode = ReactDOM.findDOMNode(this.focusTrapElement); // eslint-disable-next-line react/prop-types -- _createFocusTrap is an internal prop
52
90
 
53
91
  this.focusTrap = this.props._createFocusTrap(focusTrapElementDOMNode, tailoredFocusTrapOptions);
92
+
54
93
  if (this.props.active) {
55
94
  this.focusTrap.activate();
56
95
  }
96
+
57
97
  if (this.props.paused) {
58
98
  this.focusTrap.pause();
59
99
  }
60
100
  }
61
101
  }, {
62
- key: 'componentDidUpdate',
102
+ key: "componentDidUpdate",
63
103
  value: function componentDidUpdate(prevProps) {
64
104
  if (prevProps.active && !this.props.active) {
65
105
  var returnFocusOnDeactivate = this.props.focusTrapOptions.returnFocusOnDeactivate;
66
-
67
106
  var returnFocus = returnFocusOnDeactivate || false;
68
- var config = { returnFocus: returnFocus };
107
+ var config = {
108
+ returnFocus: returnFocus
109
+ };
69
110
  this.focusTrap.deactivate(config);
70
111
  } else if (!prevProps.active && this.props.active) {
71
112
  this.focusTrap.activate();
@@ -78,15 +119,16 @@ var FocusTrap = function (_React$Component) {
78
119
  }
79
120
  }
80
121
  }, {
81
- key: 'componentWillUnmount',
122
+ key: "componentWillUnmount",
82
123
  value: function componentWillUnmount() {
83
124
  this.focusTrap.deactivate();
125
+
84
126
  if (this.props.focusTrapOptions.returnFocusOnDeactivate !== false && this.previouslyFocusedElement && this.previouslyFocusedElement.focus) {
85
127
  this.previouslyFocusedElement.focus();
86
128
  }
87
129
  }
88
130
  }, {
89
- key: 'render',
131
+ key: "render",
90
132
  value: function render() {
91
133
  var _this2 = this;
92
134
 
@@ -94,25 +136,52 @@ var FocusTrap = function (_React$Component) {
94
136
 
95
137
  var composedRefCallback = function composedRefCallback(element) {
96
138
  _this2.setFocusTrapElement(element);
139
+
97
140
  if (typeof child.ref === 'function') {
98
141
  child.ref(element);
142
+ } else if (child.ref) {
143
+ child.ref.current = element;
99
144
  }
100
145
  };
101
146
 
102
- var childWithRef = React.cloneElement(child, { ref: composedRefCallback });
103
-
147
+ var childWithRef = React.cloneElement(child, {
148
+ ref: composedRefCallback
149
+ });
104
150
  return childWithRef;
105
151
  }
106
152
  }]);
107
153
 
108
154
  return FocusTrap;
109
- }(React.Component);
155
+ }(React.Component); // support server-side rendering where `Element` will not be defined
156
+
157
+
158
+ var ElementType = typeof Element === 'undefined' ? Function : Element;
159
+ FocusTrap.propTypes = {
160
+ active: PropTypes.bool,
161
+ paused: PropTypes.bool,
162
+ focusTrapOptions: PropTypes.shape({
163
+ onActivate: PropTypes.func,
164
+ onDeactivate: PropTypes.func,
165
+ initialFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.func]),
166
+ fallbackFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.func]),
167
+ escapeDeactivates: PropTypes.bool,
168
+ clickOutsideDeactivates: PropTypes.bool,
169
+ returnFocusOnDeactivate: PropTypes.bool,
170
+ setReturnFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.func]),
171
+ allowOutsideClick: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
172
+ preventScroll: PropTypes.bool
173
+ }),
174
+ children: PropTypes.oneOfType([PropTypes.element, // React element
175
+ PropTypes.instanceOf(ElementType) // DOM element
176
+ ]) // NOTE: _createFocusTrap is internal, for testing purposes only, so we don't
177
+ // specify it here. It's expected to be set to the function returned from
178
+ // require('focus-trap'), or one with a compatible interface.
110
179
 
180
+ };
111
181
  FocusTrap.defaultProps = {
112
182
  active: true,
113
183
  paused: false,
114
184
  focusTrapOptions: {},
115
185
  _createFocusTrap: createFocusTrap
116
186
  };
117
-
118
187
  module.exports = FocusTrap;
package/index.d.ts CHANGED
@@ -5,7 +5,7 @@ export = FocusTrap;
5
5
 
6
6
  declare namespace FocusTrap {
7
7
  export interface Props extends React.AllHTMLAttributes<any> {
8
- children: React.ReactElement<any>;
8
+ children: React.ReactNode;
9
9
  active?: boolean;
10
10
  paused?: boolean;
11
11
  focusTrapOptions?: FocusTrapOptions;
package/package.json CHANGED
@@ -1,29 +1,36 @@
1
1
  {
2
2
  "name": "focus-trap-react",
3
- "version": "6.0.0",
3
+ "version": "8.1.0",
4
4
  "description": "A React component that traps focus.",
5
5
  "main": "dist/focus-trap-react.js",
6
6
  "types": "index.d.ts",
7
+ "files": [
8
+ "README.md",
9
+ "LICENSE",
10
+ "CHANGELOG.md",
11
+ "dist",
12
+ "src",
13
+ "index.d.ts"
14
+ ],
7
15
  "scripts": {
8
16
  "demo-bundle": "browserify demo/js -t babelify --extension=.jsx -o demo/demo-bundle.js",
9
- "start": "budo demo/js/index.js:demo-bundle.js --dir demo --live -- -t babelify --extension=.jsx",
10
- "lint": "eslint .",
11
- "format": "prettier --single-quote --write src/*.js test/*.js demo/js/*.js",
17
+ "start": "yarn build && budo demo/js/index.js:demo-bundle.js --dir demo --live -- -t babelify --extension=.jsx",
18
+ "lint": "eslint \"*.js\" \"src/**/*.js\" \"test/**/*.js\" \"demo/**/*.js\"",
19
+ "format": "prettier --write \"{*,src/**/*,test/**/*,demo/js/**/*,.github/workflows/*,cypress/**/*}.+(js|yml)\"",
20
+ "format-check": "prettier --check \"{*,src/**/*,test/**/*,demo/js/**/*,.github/workflows/*,cypress/**/*}.+(js|yml)\"",
12
21
  "build": "babel src -d dist",
13
- "jest": "jest",
14
- "pretest": "npm run lint && npm run build",
15
- "test": "jest",
16
- "prepublishOnly": "npm run build"
22
+ "test-types": "tsc index.d.ts",
23
+ "test-unit": "jest",
24
+ "test-cypress": "start-server-and-test start 9966 'cypress open'",
25
+ "test-cypress-ci": "start-server-and-test start 9966 'cypress run --browser $CYPRESS_BROWSER --headless'",
26
+ "test": "yarn format-check && yarn lint && yarn test-unit && yarn test-types && CYPRESS_BROWSER=chrome yarn test-cypress-ci",
27
+ "prepare": "yarn build",
28
+ "release": "yarn build && changeset publish"
17
29
  },
18
30
  "repository": {
19
31
  "type": "git",
20
- "url": "git+https://github.com/davidtheclark/focus-trap-react.git"
32
+ "url": "git+https://github.com/focus-trap/focus-trap-react.git"
21
33
  },
22
- "files": [
23
- "dist",
24
- "src",
25
- "index.d.ts"
26
- ],
27
34
  "keywords": [
28
35
  "react",
29
36
  "reactjs",
@@ -35,49 +42,49 @@
35
42
  "focus",
36
43
  "keyboard"
37
44
  ],
38
- "author": "David Clark",
45
+ "author": {
46
+ "name": "David Clark",
47
+ "url": "http://davidtheclark.com/"
48
+ },
39
49
  "license": "MIT",
40
50
  "bugs": {
41
- "url": "https://github.com/davidtheclark/focus-trap-react/issues"
51
+ "url": "https://github.com/focus-trap/focus-trap-react/issues"
42
52
  },
43
- "homepage": "https://github.com/davidtheclark/focus-trap-react#readme",
53
+ "homepage": "https://github.com/focus-trap/focus-trap-react#readme",
44
54
  "devDependencies": {
45
- "babel-cli": "^6.24.1",
46
- "babel-eslint": "^7.2.3",
47
- "babel-plugin-transform-class-properties": "^6.24.1",
48
- "babel-preset-es2015": "^6.24.1",
49
- "babel-preset-react": "^6.24.1",
50
- "babelify": "^7.3.0",
51
- "browserify": "^14.3.0",
52
- "budo": "^9.4.1",
53
- "eslint": "^3.13.1",
54
- "eslint-plugin-react": "^6.10.3",
55
- "jest": "^23.4.0",
56
- "prettier": "^1.2.2",
57
- "react": "^16.0.0",
58
- "react-dom": "^16.0.0"
55
+ "@babel/cli": "^7.11.6",
56
+ "@babel/core": "^7.11.6",
57
+ "@babel/plugin-proposal-class-properties": "^7.10.4",
58
+ "@babel/preset-env": "^7.11.5",
59
+ "@babel/preset-react": "^7.10.4",
60
+ "@changesets/cli": "^2.10.3",
61
+ "@testing-library/cypress": "^7.0.1",
62
+ "@types/jquery": "^3.5.1",
63
+ "all-contributors-cli": "^6.17.4",
64
+ "babel-eslint": "^10.1.0",
65
+ "babel-jest": "^26.3.0",
66
+ "babelify": "^10.0.0",
67
+ "browserify": "^16.5.2",
68
+ "budo": "^11.6.4",
69
+ "cypress": "^5.2.0",
70
+ "cypress-plugin-tab": "^1.0.5",
71
+ "eslint": "^7.9.0",
72
+ "eslint-config-prettier": "^6.11.0",
73
+ "eslint-plugin-react": "^7.21.0",
74
+ "jest": "^26.4.2",
75
+ "prettier": "^2.1.2",
76
+ "prop-types": "^15.7.2",
77
+ "react": "^16.13.1",
78
+ "react-dom": "^16.13.1",
79
+ "start-server-and-test": "^1.11.4",
80
+ "typescript": "^4.0.3"
59
81
  },
60
82
  "dependencies": {
61
- "focus-trap": "^4.0.2"
83
+ "focus-trap": "^6.1.0"
62
84
  },
63
85
  "peerDependencies": {
64
- "react": "0.14.x || ^15.0.0 || ^16.0.0",
65
- "react-dom": "0.14.x || ^15.0.0 || ^16.0.0"
66
- },
67
- "babel": {
68
- "presets": [
69
- "react",
70
- "es2015"
71
- ],
72
- "plugins": [
73
- "transform-class-properties"
74
- ]
75
- },
76
- "jest": {
77
- "setupFiles": [
78
- "<rootDir>/test/jest-setup.js"
79
- ],
80
- "clearMocks": true,
81
- "testURL": "http://localhost"
86
+ "prop-types": "^15.7.2",
87
+ "react": "^16.0.0",
88
+ "react-dom": "^16.0.0"
82
89
  }
83
90
  }
@@ -1,10 +1,16 @@
1
1
  const React = require('react');
2
2
  const ReactDOM = require('react-dom');
3
- const createFocusTrap = require('focus-trap');
3
+ const PropTypes = require('prop-types');
4
+ const { createFocusTrap } = require('focus-trap');
5
+
6
+ // TODO: These issues are related to older React features which we'll likely need
7
+ // to fix in order to move the code forward to the next major version of React.
8
+ // @see https://github.com/davidtheclark/focus-trap-react/issues/77
9
+ /* eslint-disable react/no-find-dom-node */
4
10
 
5
11
  class FocusTrap extends React.Component {
6
12
  constructor(props) {
7
- super(props)
13
+ super(props);
8
14
 
9
15
  if (typeof document !== 'undefined') {
10
16
  this.previouslyFocusedElement = document.activeElement;
@@ -19,17 +25,30 @@ class FocusTrap extends React.Component {
19
25
  // then (optionally) returns focus to it in componentWillUnmount.
20
26
  const specifiedFocusTrapOptions = this.props.focusTrapOptions;
21
27
  const tailoredFocusTrapOptions = {
22
- returnFocusOnDeactivate: false
28
+ returnFocusOnDeactivate: false,
23
29
  };
30
+
24
31
  for (const optionName in specifiedFocusTrapOptions) {
25
- if (!specifiedFocusTrapOptions.hasOwnProperty(optionName)) continue;
26
- if (optionName === 'returnFocusOnDeactivate') continue;
32
+ if (
33
+ !Object.prototype.hasOwnProperty.call(
34
+ specifiedFocusTrapOptions,
35
+ optionName
36
+ )
37
+ ) {
38
+ continue;
39
+ }
40
+
41
+ if (optionName === 'returnFocusOnDeactivate') {
42
+ continue;
43
+ }
44
+
27
45
  tailoredFocusTrapOptions[optionName] =
28
46
  specifiedFocusTrapOptions[optionName];
29
47
  }
30
48
 
31
49
  const focusTrapElementDOMNode = ReactDOM.findDOMNode(this.focusTrapElement);
32
50
 
51
+ // eslint-disable-next-line react/prop-types -- _createFocusTrap is an internal prop
33
52
  this.focusTrap = this.props._createFocusTrap(
34
53
  focusTrapElementDOMNode,
35
54
  tailoredFocusTrapOptions
@@ -70,31 +89,75 @@ class FocusTrap extends React.Component {
70
89
  }
71
90
  }
72
91
 
73
- setFocusTrapElement = element => {
92
+ setFocusTrapElement = (element) => {
74
93
  this.focusTrapElement = element;
75
94
  };
76
95
 
77
96
  render() {
78
97
  const child = React.Children.only(this.props.children);
79
98
 
80
- const composedRefCallback = element => {
99
+ const composedRefCallback = (element) => {
81
100
  this.setFocusTrapElement(element);
82
101
  if (typeof child.ref === 'function') {
83
102
  child.ref(element);
103
+ } else if (child.ref) {
104
+ child.ref.current = element;
84
105
  }
85
- }
106
+ };
86
107
 
87
- const childWithRef = React.cloneElement(child, { ref: composedRefCallback });
108
+ const childWithRef = React.cloneElement(child, {
109
+ ref: composedRefCallback,
110
+ });
88
111
 
89
112
  return childWithRef;
90
113
  }
91
114
  }
92
115
 
116
+ // support server-side rendering where `Element` will not be defined
117
+ const ElementType = typeof Element === 'undefined' ? Function : Element;
118
+
119
+ FocusTrap.propTypes = {
120
+ active: PropTypes.bool,
121
+ paused: PropTypes.bool,
122
+ focusTrapOptions: PropTypes.shape({
123
+ onActivate: PropTypes.func,
124
+ onDeactivate: PropTypes.func,
125
+ initialFocus: PropTypes.oneOfType([
126
+ PropTypes.instanceOf(ElementType),
127
+ PropTypes.string,
128
+ PropTypes.func,
129
+ ]),
130
+ fallbackFocus: PropTypes.oneOfType([
131
+ PropTypes.instanceOf(ElementType),
132
+ PropTypes.string,
133
+ PropTypes.func,
134
+ ]),
135
+ escapeDeactivates: PropTypes.bool,
136
+ clickOutsideDeactivates: PropTypes.bool,
137
+ returnFocusOnDeactivate: PropTypes.bool,
138
+ setReturnFocus: PropTypes.oneOfType([
139
+ PropTypes.instanceOf(ElementType),
140
+ PropTypes.string,
141
+ PropTypes.func,
142
+ ]),
143
+ allowOutsideClick: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
144
+ preventScroll: PropTypes.bool,
145
+ }),
146
+ children: PropTypes.oneOfType([
147
+ PropTypes.element, // React element
148
+ PropTypes.instanceOf(ElementType), // DOM element
149
+ ]),
150
+
151
+ // NOTE: _createFocusTrap is internal, for testing purposes only, so we don't
152
+ // specify it here. It's expected to be set to the function returned from
153
+ // require('focus-trap'), or one with a compatible interface.
154
+ };
155
+
93
156
  FocusTrap.defaultProps = {
94
157
  active: true,
95
158
  paused: false,
96
159
  focusTrapOptions: {},
97
- _createFocusTrap: createFocusTrap
160
+ _createFocusTrap: createFocusTrap,
98
161
  };
99
162
 
100
163
  module.exports = FocusTrap;