UNPKG

5.54 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
7var React = require('react');
8var React__default = _interopDefault(React);
9require('./_commonjsHelpers-72d386ba.js');
10var index = require('./index-b0606964.js');
11var defineProperty = require('./defineProperty-0921a47c.js');
12var getPrototypeOf = require('./getPrototypeOf-2a661a20.js');
13
14function _createSuper(Derived) { return function () { var Super = getPrototypeOf._getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = getPrototypeOf._getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return getPrototypeOf._possibleConstructorReturn(this, result); }; }
15
16function _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; } }
17// supporting it yet.
18//
19// It follows the Chrome implementation, checking for a pointer device rather
20// than a keyboard event.
21//
22// Resources:
23// - https://caniuse.com/#search=%3Afocus-visible
24// - https://github.com/WICG/focus-visible/issues/88#issuecomment-363227219
25// - https://chromium-review.googlesource.com/c/chromium/src/+/897002<Paste>
26//
27
28var FocusVisible = /*#__PURE__*/function (_React$Component) {
29 getPrototypeOf._inherits(FocusVisible, _React$Component);
30
31 var _super = _createSuper(FocusVisible);
32
33 function FocusVisible() {
34 var _this;
35
36 getPrototypeOf._classCallCheck(this, FocusVisible);
37
38 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
39 args[_key] = arguments[_key];
40 }
41
42 _this = _super.call.apply(_super, [this].concat(args));
43
44 defineProperty._defineProperty(getPrototypeOf._assertThisInitialized(_this), "_element", React__default.createRef());
45
46 defineProperty._defineProperty(getPrototypeOf._assertThisInitialized(_this), "_document", null);
47
48 defineProperty._defineProperty(getPrototypeOf._assertThisInitialized(_this), "state", {
49 focusVisible: false
50 });
51
52 defineProperty._defineProperty(getPrototypeOf._assertThisInitialized(_this), "handlePointerEvent", function (e) {
53 _this._pointerActive = true;
54 _this._timer = setTimeout(function () {
55 _this._pointerActive = false;
56 }, 0);
57
58 if (_this.state.focusVisible) {
59 _this.setState({
60 focusVisible: false
61 });
62 }
63 });
64
65 defineProperty._defineProperty(getPrototypeOf._assertThisInitialized(_this), "handleFocus", function () {
66 _this.setState({
67 focusVisible: !_this._pointerActive
68 });
69 });
70
71 return _this;
72 }
73
74 getPrototypeOf._createClass(FocusVisible, [{
75 key: "componentDidMount",
76 value: function componentDidMount() {
77 // `document` was previously set as a state entry, which was having the
78 // advantages of keeping track of it, and also triggering a rerender to
79 // remove the injected span.
80 //
81 // The issue with this approach is that the component can get unmounted
82 // before the state gets updated (e.g. in case of an error in the tree),
83 // preventing to remove the event listeners.
84 //
85 // this._document is now set on the instance directly, and
86 // this.forceUpdate() is used to trigger the second render needed to remove
87 // the injected span.
88 this._document = this._element.current.ownerDocument;
89
90 this._document.addEventListener('mousedown', this.handlePointerEvent);
91
92 this._document.addEventListener('mouseup', this.handlePointerEvent);
93
94 this._document.addEventListener('touchstart', this.handlePointerEvent);
95
96 this._document.addEventListener('touchend', this.handlePointerEvent);
97
98 this.forceUpdate();
99 }
100 }, {
101 key: "componentWillUnmount",
102 value: function componentWillUnmount() {
103 if (this._document) {
104 this._document.removeEventListener('mousedown', this.handlePointerEvent);
105
106 this._document.removeEventListener('mouseup', this.handlePointerEvent);
107
108 this._document.removeEventListener('touchstart', this.handlePointerEvent);
109
110 this._document.removeEventListener('touchend', this.handlePointerEvent);
111 }
112 } // It doesn’t seem to be specified, but pointer-related events happen before
113 // the focus-related events on every modern browser.
114
115 }, {
116 key: "render",
117 value: function render() {
118 var focusVisible = this.state.focusVisible;
119 return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, this.props.children({
120 focusVisible: focusVisible,
121 onFocus: this.handleFocus
122 }), !this._document && /*#__PURE__*/React__default.createElement("span", {
123 ref: this._element
124 }));
125 }
126 }]);
127
128 return FocusVisible;
129}(React__default.Component);
130
131defineProperty._defineProperty(FocusVisible, "propTypes", {
132 // children is called with an object containing two entries:
133 // - focusVisible represents the visibility of the focus (boolean).
134 // - onFocus() need to be called when the target element is focused.
135 children: index.PropTypes.func.isRequired
136});
137
138exports.default = FocusVisible;
139//# sourceMappingURL=FocusVisible.js.map