focus-trap-react 5.0.0 → 7.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,8 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## 7.0.1
4
+
5
+ - Fix: PropTypes definition now supports server-side rendering. #83
6
+
7
+ ## 7.0.0
8
+
9
+ - Add: Prop types for `<FocusTrap>`.
10
+ - 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
11
+ - **BREAKING** Update: Only React 16.0+ is supported going forward. #55
12
+ - **BREAKING** Update: All dependencies updated to their latest versions.
13
+ - Fix: `children`'s type is `React.ReactNode`, not `React.ReactElement`. #66
14
+ - Fix: Allow mutable object refs to be used for FocusTrap child. #72
15
+ - Fix: `specifiedFocusTrapOptions.includes(optionName)` statement in `componentDidMount()` was causing an exception because `includes()` is not a function defined on `Object`.
16
+
17
+ ## 6.0.0
18
+
19
+ - 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).
20
+
21
+ ## 5.0.1
22
+
23
+ - Fix TypeScript declarations.
24
+
3
25
  ## 5.0.0
4
26
 
5
- - **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>`.
27
+ - **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>`.
6
28
 
7
29
  ## 4.0.1
8
30
 
package/README.md CHANGED
@@ -1,5 +1,12 @@
1
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)
2
2
 
3
+ ---
4
+
5
+ **SEEKING CO-MAINTAINERS!** Continued development of this project is going to require the work of one or more dedicated co-maintainers (or forkers). If you're interested, please comment in [this issue](https://github.com/davidtheclark/focus-trap-react/issues/48).
6
+
7
+ ---
8
+
9
+
3
10
  A React component that traps focus.
4
11
 
5
12
  This component is a light wrapper around [focus-trap](https://github.com/davidtheclark/focus-trap),
@@ -7,12 +14,6 @@ tailored to your React-specific needs.
7
14
 
8
15
  You might want it for, say, building [an accessible modal](https://github.com/davidtheclark/react-aria-modal)?
9
16
 
10
- ---
11
-
12
- **Looking for co-maintainers!** If you'd like to help maintain this project, please let me know.
13
-
14
- ---
15
-
16
17
  ## What it does
17
18
 
18
19
  [Check out the demo](http://davidtheclark.github.io/focus-trap-react/demo/).
@@ -167,8 +168,12 @@ If you would like to pause or unpause the focus trap (see [`focus-trap`'s docume
167
168
 
168
169
  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
 
171
+ Format with `npm run format`.
172
+
170
173
  Lint with `npm run lint`.
171
174
 
172
175
  Run the demos with `npm start`.
173
176
 
174
- Test with `npm run test`.
177
+ Test with `npm run test` (checks formatting, checks lint, runs tests).
178
+
179
+ Unit test (only) with `npm run test-unit`.
@@ -1,37 +1,67 @@
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 createFocusTrap = require('focus-trap'); // TODO: These issues are related to older React features which we'll likely need
34
+ // to fix in order to move the code forward to the next major version of React.
35
+ // @see https://github.com/davidtheclark/focus-trap-react/issues/77
36
+
37
+ /* eslint-disable react/no-find-dom-node */
38
+
39
+
40
+ var FocusTrap = /*#__PURE__*/function (_React$Component) {
16
41
  _inherits(FocusTrap, _React$Component);
17
42
 
43
+ var _super = _createSuper(FocusTrap);
44
+
18
45
  function FocusTrap(props) {
46
+ var _this;
47
+
19
48
  _classCallCheck(this, FocusTrap);
20
49
 
21
- var _this = _possibleConstructorReturn(this, (FocusTrap.__proto__ || Object.getPrototypeOf(FocusTrap)).call(this, props));
50
+ _this = _super.call(this, props);
22
51
 
23
- _this.setFocusTrapElement = function (element) {
52
+ _defineProperty(_assertThisInitialized(_this), "setFocusTrapElement", function (element) {
24
53
  _this.focusTrapElement = element;
25
- };
54
+ });
26
55
 
27
56
  if (typeof document !== 'undefined') {
28
57
  _this.previouslyFocusedElement = document.activeElement;
29
58
  }
59
+
30
60
  return _this;
31
61
  }
32
62
 
33
63
  _createClass(FocusTrap, [{
34
- key: 'componentDidMount',
64
+ key: "componentDidMount",
35
65
  value: function componentDidMount() {
36
66
  // We need to hijack the returnFocusOnDeactivate option,
37
67
  // because React can move focus into the element before we arrived at
@@ -42,30 +72,40 @@ var FocusTrap = function (_React$Component) {
42
72
  var tailoredFocusTrapOptions = {
43
73
  returnFocusOnDeactivate: false
44
74
  };
75
+
45
76
  for (var optionName in specifiedFocusTrapOptions) {
46
- if (!specifiedFocusTrapOptions.hasOwnProperty(optionName)) continue;
47
- if (optionName === 'returnFocusOnDeactivate') continue;
77
+ if (!Object.prototype.hasOwnProperty.call(specifiedFocusTrapOptions, optionName)) {
78
+ continue;
79
+ }
80
+
81
+ if (optionName === 'returnFocusOnDeactivate') {
82
+ continue;
83
+ }
84
+
48
85
  tailoredFocusTrapOptions[optionName] = specifiedFocusTrapOptions[optionName];
49
86
  }
50
87
 
51
- var focusTrapElementDOMNode = ReactDOM.findDOMNode(this.focusTrapElement);
88
+ var focusTrapElementDOMNode = ReactDOM.findDOMNode(this.focusTrapElement); // eslint-disable-next-line react/prop-types -- _createFocusTrap is an internal prop
52
89
 
53
90
  this.focusTrap = this.props._createFocusTrap(focusTrapElementDOMNode, tailoredFocusTrapOptions);
91
+
54
92
  if (this.props.active) {
55
93
  this.focusTrap.activate();
56
94
  }
95
+
57
96
  if (this.props.paused) {
58
97
  this.focusTrap.pause();
59
98
  }
60
99
  }
61
100
  }, {
62
- key: 'componentDidUpdate',
101
+ key: "componentDidUpdate",
63
102
  value: function componentDidUpdate(prevProps) {
64
103
  if (prevProps.active && !this.props.active) {
65
104
  var returnFocusOnDeactivate = this.props.focusTrapOptions.returnFocusOnDeactivate;
66
-
67
105
  var returnFocus = returnFocusOnDeactivate || false;
68
- var config = { returnFocus: returnFocus };
106
+ var config = {
107
+ returnFocus: returnFocus
108
+ };
69
109
  this.focusTrap.deactivate(config);
70
110
  } else if (!prevProps.active && this.props.active) {
71
111
  this.focusTrap.activate();
@@ -78,15 +118,16 @@ var FocusTrap = function (_React$Component) {
78
118
  }
79
119
  }
80
120
  }, {
81
- key: 'componentWillUnmount',
121
+ key: "componentWillUnmount",
82
122
  value: function componentWillUnmount() {
83
123
  this.focusTrap.deactivate();
124
+
84
125
  if (this.props.focusTrapOptions.returnFocusOnDeactivate !== false && this.previouslyFocusedElement && this.previouslyFocusedElement.focus) {
85
126
  this.previouslyFocusedElement.focus();
86
127
  }
87
128
  }
88
129
  }, {
89
- key: 'render',
130
+ key: "render",
90
131
  value: function render() {
91
132
  var _this2 = this;
92
133
 
@@ -94,25 +135,52 @@ var FocusTrap = function (_React$Component) {
94
135
 
95
136
  var composedRefCallback = function composedRefCallback(element) {
96
137
  _this2.setFocusTrapElement(element);
138
+
97
139
  if (typeof child.ref === 'function') {
98
140
  child.ref(element);
141
+ } else if (child.ref) {
142
+ child.ref.current = element;
99
143
  }
100
144
  };
101
145
 
102
- var childWithRef = React.cloneElement(child, { ref: composedRefCallback });
103
-
146
+ var childWithRef = React.cloneElement(child, {
147
+ ref: composedRefCallback
148
+ });
104
149
  return childWithRef;
105
150
  }
106
151
  }]);
107
152
 
108
153
  return FocusTrap;
109
- }(React.Component);
154
+ }(React.Component); // support server-side rendering where `Element` will not be defined
155
+
156
+
157
+ var ElementType = typeof Element === 'undefined' ? Function : Element;
158
+ FocusTrap.propTypes = {
159
+ active: PropTypes.bool,
160
+ paused: PropTypes.bool,
161
+ focusTrapOptions: PropTypes.shape({
162
+ onActivate: PropTypes.func,
163
+ onDeactivate: PropTypes.func,
164
+ initialFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.func]),
165
+ fallbackFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.func]),
166
+ escapeDeactivates: PropTypes.bool,
167
+ clickOutsideDeactivates: PropTypes.bool,
168
+ returnFocusOnDeactivate: PropTypes.bool,
169
+ setReturnFocus: PropTypes.oneOfType([PropTypes.instanceOf(ElementType), PropTypes.string, PropTypes.func]),
170
+ allowOutsideClick: PropTypes.func,
171
+ preventScroll: PropTypes.bool
172
+ }),
173
+ children: PropTypes.oneOfType([PropTypes.element, // React element
174
+ PropTypes.instanceOf(ElementType) // DOM element
175
+ ]) // NOTE: _createFocusTrap is internal, for testing purposes only, so we don't
176
+ // specify it here. It's expected to be set to the function returned from
177
+ // require('focus-trap'), or one with a compatible interface.
110
178
 
179
+ };
111
180
  FocusTrap.defaultProps = {
112
181
  active: true,
113
182
  paused: false,
114
183
  focusTrapOptions: {},
115
184
  _createFocusTrap: createFocusTrap
116
185
  };
117
-
118
186
  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;
8
+ children: React.ReactNode;
9
9
  active?: boolean;
10
10
  paused?: boolean;
11
11
  focusTrapOptions?: FocusTrapOptions;
package/package.json CHANGED
@@ -1,25 +1,29 @@
1
1
  {
2
2
  "name": "focus-trap-react",
3
- "version": "5.0.0",
3
+ "version": "7.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",
7
7
  "scripts": {
8
8
  "demo-bundle": "browserify demo/js -t babelify --extension=.jsx -o demo/demo-bundle.js",
9
+ "prestart": "yarn build",
9
10
  "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",
11
+ "lint": "eslint \"src/**/*.js\" \"test/**/*.js\" \"demo/**/*.js\"",
12
+ "format": "prettier --write \"src/**/*.js\" \"test/**/*.js\" \"demo/js/**/*.js\"",
13
+ "format-check": "prettier --check \"src/**/*.js\" \"test/**/*.js\" \"demo/js/**/*.js\"",
12
14
  "build": "babel src -d dist",
13
- "jest": "jest",
14
- "pretest": "npm run lint && npm run build",
15
- "test": "jest",
16
- "prepublishOnly": "npm run build"
15
+ "test-unit": "jest",
16
+ "test": "yarn format-check && yarn lint && jest",
17
+ "prepublishOnly": "yarn test && yarn build"
17
18
  },
18
19
  "repository": {
19
20
  "type": "git",
20
21
  "url": "git+https://github.com/davidtheclark/focus-trap-react.git"
21
22
  },
22
23
  "files": [
24
+ "README.md",
25
+ "LICENSE",
26
+ "CHANGELOG.md",
23
27
  "dist",
24
28
  "src",
25
29
  "index.d.ts"
@@ -36,48 +40,51 @@
36
40
  "keyboard"
37
41
  ],
38
42
  "author": "David Clark",
43
+ "contributors": [
44
+ {
45
+ "name": "David Clark",
46
+ "url": "http://davidtheclark.com/"
47
+ },
48
+ {
49
+ "name": "Stefan Cameron",
50
+ "url": "https://stefancameron.com/"
51
+ },
52
+ {
53
+ "name": "Marais Rossouw",
54
+ "url": "https://marais.io/"
55
+ }
56
+ ],
39
57
  "license": "MIT",
40
58
  "bugs": {
41
59
  "url": "https://github.com/davidtheclark/focus-trap-react/issues"
42
60
  },
43
61
  "homepage": "https://github.com/davidtheclark/focus-trap-react#readme",
44
62
  "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"
63
+ "@babel/cli": "^7.10.3",
64
+ "@babel/core": "^7.10.3",
65
+ "@babel/plugin-proposal-class-properties": "^7.10.1",
66
+ "@babel/preset-env": "^7.10.2",
67
+ "@babel/preset-react": "^7.10.1",
68
+ "babel-eslint": "^10.1.0",
69
+ "babel-jest": "^26.0.1",
70
+ "babelify": "^10.0.0",
71
+ "browserify": "^16.5.1",
72
+ "budo": "^11.6.3",
73
+ "eslint": "^7.3.0",
74
+ "eslint-config-prettier": "^6.11.0",
75
+ "eslint-plugin-react": "^7.20.0",
76
+ "jest": "^26.0.1",
77
+ "prettier": "^2.0.5",
78
+ "prop-types": "^15.7.2",
79
+ "react": "^16.13.1",
80
+ "react-dom": "^16.13.1"
59
81
  },
60
82
  "dependencies": {
61
- "focus-trap": "^3.0.0"
83
+ "focus-trap": "^5.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
+ "react": "^16.0.0",
87
+ "react-dom": "^16.0.0",
88
+ "prop-types": "^15.7.2"
82
89
  }
83
90
  }
@@ -1,10 +1,16 @@
1
1
  const React = require('react');
2
2
  const ReactDOM = require('react-dom');
3
+ const PropTypes = require('prop-types');
3
4
  const createFocusTrap = require('focus-trap');
4
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 */
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;
@@ -21,15 +27,28 @@ class FocusTrap extends React.Component {
21
27
  const tailoredFocusTrapOptions = {
22
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,26 +89,70 @@ 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.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,