UNPKG

5.29 kBJavaScriptView Raw
1"use strict";
2
3var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
5Object.defineProperty(exports, "__esModule", {
6 value: true
7});
8exports.default = void 0;
9
10var _react = _interopRequireDefault(require("react"));
11
12var _reactDom = _interopRequireDefault(require("react-dom"));
13
14var _propTypes = _interopRequireDefault(require("prop-types"));
15
16var _ownerDocument = _interopRequireDefault(require("../utils/ownerDocument"));
17
18var _useForkRef = _interopRequireDefault(require("../utils/useForkRef"));
19
20var _setRef = _interopRequireDefault(require("../utils/setRef"));
21
22var _useEventCallback = _interopRequireDefault(require("../utils/useEventCallback"));
23
24var _utils = require("@material-ui/utils");
25
26function mapEventPropToEvent(eventProp) {
27 return eventProp.substring(2).toLowerCase();
28}
29/**
30 * Listen for click events that occur somewhere in the document, outside of the element itself.
31 * For instance, if you need to hide a menu when people click anywhere else on your page.
32 */
33
34
35var ClickAwayListener = _react.default.forwardRef(function ClickAwayListener(props, ref) {
36 var children = props.children,
37 _props$mouseEvent = props.mouseEvent,
38 mouseEvent = _props$mouseEvent === void 0 ? 'onClick' : _props$mouseEvent,
39 _props$touchEvent = props.touchEvent,
40 touchEvent = _props$touchEvent === void 0 ? 'onTouchEnd' : _props$touchEvent,
41 onClickAway = props.onClickAway;
42
43 var movedRef = _react.default.useRef(false);
44
45 var nodeRef = _react.default.useRef(null);
46
47 var mountedRef = _react.default.useRef(false);
48
49 _react.default.useEffect(function () {
50 mountedRef.current = true;
51 return function () {
52 mountedRef.current = false;
53 };
54 }, []);
55
56 var handleNodeRef = (0, _useForkRef.default)(nodeRef, ref); // can be removed once we drop support for non ref forwarding class components
57
58 var handleOwnRef = _react.default.useCallback(function (instance) {
59 // #StrictMode ready
60 (0, _setRef.default)(handleNodeRef, _reactDom.default.findDOMNode(instance));
61 }, [handleNodeRef]);
62
63 var handleRef = (0, _useForkRef.default)(children.ref, handleOwnRef);
64 var handleClickAway = (0, _useEventCallback.default)(function (event) {
65 // The handler doesn't take event.defaultPrevented into account:
66 //
67 // event.preventDefault() is meant to stop default behaviours like
68 // clicking a checkbox to check it, hitting a button to submit a form,
69 // and hitting left arrow to move the cursor in a text input etc.
70 // Only special HTML elements have these default behaviors.
71 // IE 11 support, which trigger the handleClickAway even after the unbind
72 if (!mountedRef.current) {
73 return;
74 } // Do not act if user performed touchmove
75
76
77 if (movedRef.current) {
78 movedRef.current = false;
79 return;
80 } // The child might render null.
81
82
83 if (!nodeRef.current) {
84 return;
85 } // Multi window support
86
87
88 var doc = (0, _ownerDocument.default)(nodeRef.current);
89
90 if (doc.documentElement && doc.documentElement.contains(event.target) && !nodeRef.current.contains(event.target)) {
91 onClickAway(event);
92 }
93 });
94
95 var handleTouchMove = _react.default.useCallback(function () {
96 movedRef.current = true;
97 }, []);
98
99 _react.default.useEffect(function () {
100 if (touchEvent !== false) {
101 var mappedTouchEvent = mapEventPropToEvent(touchEvent);
102 var doc = (0, _ownerDocument.default)(nodeRef.current);
103 doc.addEventListener(mappedTouchEvent, handleClickAway);
104 doc.addEventListener('touchmove', handleTouchMove);
105 return function () {
106 doc.removeEventListener(mappedTouchEvent, handleClickAway);
107 doc.removeEventListener('touchmove', handleTouchMove);
108 };
109 }
110
111 return undefined;
112 }, [handleClickAway, handleTouchMove, touchEvent]);
113
114 _react.default.useEffect(function () {
115 if (mouseEvent !== false) {
116 var mappedMouseEvent = mapEventPropToEvent(mouseEvent);
117 var doc = (0, _ownerDocument.default)(nodeRef.current);
118 doc.addEventListener(mappedMouseEvent, handleClickAway);
119 return function () {
120 doc.removeEventListener(mappedMouseEvent, handleClickAway);
121 };
122 }
123
124 return undefined;
125 }, [handleClickAway, mouseEvent]);
126
127 return _react.default.createElement(_react.default.Fragment, null, _react.default.cloneElement(children, {
128 ref: handleRef
129 }));
130});
131
132process.env.NODE_ENV !== "production" ? ClickAwayListener.propTypes = {
133 /**
134 * The wrapped element.
135 */
136 children: _utils.elementAcceptingRef.isRequired,
137
138 /**
139 * The mouse event to listen to. You can disable the listener by providing `false`.
140 */
141 mouseEvent: _propTypes.default.oneOf(['onClick', 'onMouseDown', 'onMouseUp', false]),
142
143 /**
144 * Callback fired when a "click away" event is detected.
145 */
146 onClickAway: _propTypes.default.func.isRequired,
147
148 /**
149 * The touch event to listen to. You can disable the listener by providing `false`.
150 */
151 touchEvent: _propTypes.default.oneOf(['onTouchStart', 'onTouchEnd', false])
152} : void 0;
153
154if (process.env.NODE_ENV !== 'production') {
155 // eslint-disable-next-line
156 ClickAwayListener['propTypes' + ''] = (0, _utils.exactProp)(ClickAwayListener.propTypes);
157}
158
159var _default = ClickAwayListener;
160exports.default = _default;
\No newline at end of file