1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', { value: true });
|
4 |
|
5 | function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
6 |
|
7 | var React = require('react');
|
8 | var React__default = _interopDefault(React);
|
9 | var ReactDom = _interopDefault(require('react-dom'));
|
10 | var cx = _interopDefault(require('classnames'));
|
11 | var noScroll = _interopDefault(require('no-scroll'));
|
12 |
|
13 | function _extends() {
|
14 | _extends = Object.assign || function (target) {
|
15 | for (var i = 1; i < arguments.length; i++) {
|
16 | var source = arguments[i];
|
17 |
|
18 | for (var key in source) {
|
19 | if (Object.prototype.hasOwnProperty.call(source, key)) {
|
20 | target[key] = source[key];
|
21 | }
|
22 | }
|
23 | }
|
24 |
|
25 | return target;
|
26 | };
|
27 |
|
28 | return _extends.apply(this, arguments);
|
29 | }
|
30 |
|
31 | var CloseIcon = function CloseIcon(_ref) {
|
32 | var classes = _ref.classes,
|
33 | classNames = _ref.classNames,
|
34 | styles = _ref.styles,
|
35 | id = _ref.id,
|
36 | closeIcon = _ref.closeIcon,
|
37 | onClickCloseIcon = _ref.onClickCloseIcon;
|
38 | return React__default.createElement("button", {
|
39 | id: id,
|
40 | className: cx(classes.closeButton, classNames === null || classNames === void 0 ? void 0 : classNames.closeButton),
|
41 | style: styles === null || styles === void 0 ? void 0 : styles.closeButton,
|
42 | onClick: onClickCloseIcon,
|
43 | "data-testid": "close-button"
|
44 | }, closeIcon ? closeIcon : React__default.createElement("svg", {
|
45 | className: classNames === null || classNames === void 0 ? void 0 : classNames.closeIcon,
|
46 | style: styles === null || styles === void 0 ? void 0 : styles.closeIcon,
|
47 | xmlns: "http://www.w3.org/2000/svg",
|
48 | width: 28,
|
49 | height: 28,
|
50 | viewBox: "0 0 36 36",
|
51 | "data-testid": "close-icon"
|
52 | }, React__default.createElement("path", {
|
53 | d: "M28.5 9.62L26.38 7.5 18 15.88 9.62 7.5 7.5 9.62 15.88 18 7.5 26.38l2.12 2.12L18 20.12l8.38 8.38 2.12-2.12L20.12 18z"
|
54 | })));
|
55 | };
|
56 |
|
57 | var _modals = [];
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 | var modalManager = {
|
64 | |
65 |
|
66 |
|
67 | modals: function modals() {
|
68 | return _modals;
|
69 | },
|
70 |
|
71 | |
72 |
|
73 |
|
74 | add: function add(newModal, blockScroll) {
|
75 | if (_modals.findIndex(function (modal) {
|
76 | return modal.element === newModal;
|
77 | }) === -1) {
|
78 | _modals.push({
|
79 | element: newModal,
|
80 | blockScroll: blockScroll
|
81 | });
|
82 | }
|
83 | },
|
84 |
|
85 | |
86 |
|
87 |
|
88 | remove: function remove(oldModal) {
|
89 | var index = _modals.findIndex(function (modal) {
|
90 | return modal.element === oldModal;
|
91 | });
|
92 |
|
93 | if (index !== -1) {
|
94 | _modals.splice(index, 1);
|
95 | }
|
96 | },
|
97 |
|
98 | |
99 |
|
100 |
|
101 | isTopModal: function isTopModal(modal) {
|
102 | var _modals2;
|
103 |
|
104 | return !!_modals.length && ((_modals2 = _modals[_modals.length - 1]) === null || _modals2 === void 0 ? void 0 : _modals2.element) === modal;
|
105 | }
|
106 | };
|
107 |
|
108 | var isBrowser = typeof window !== 'undefined';
|
109 | var blockNoScroll = function blockNoScroll() {
|
110 | noScroll.on();
|
111 | };
|
112 | var unblockNoScroll = function unblockNoScroll() {
|
113 |
|
114 |
|
115 | var modals = modalManager.modals().filter(function (modal) {
|
116 | return modal.blockScroll;
|
117 | });
|
118 |
|
119 | if (modals.length === 0) {
|
120 | noScroll.off();
|
121 | }
|
122 | };
|
123 |
|
124 |
|
125 | var candidateSelectors = ['input', 'select', 'textarea', 'a[href]', 'button', '[tabindex]', 'audio[controls]', 'video[controls]', '[contenteditable]:not([contenteditable="false"])'];
|
126 |
|
127 | function isHidden(node) {
|
128 |
|
129 |
|
130 | return node.offsetParent === null || getComputedStyle(node).visibility === 'hidden';
|
131 | }
|
132 |
|
133 | function getAllTabbingElements(parentElem) {
|
134 | var tabbableNodes = parentElem.querySelectorAll(candidateSelectors.join(','));
|
135 | var onlyTabbable = [];
|
136 |
|
137 | for (var i = 0; i < tabbableNodes.length; i++) {
|
138 | var node = tabbableNodes[i];
|
139 |
|
140 | if (!node.disabled && getTabindex(node) > -1 && !isHidden(node)) {
|
141 | onlyTabbable.push(node);
|
142 | }
|
143 | }
|
144 |
|
145 | return onlyTabbable;
|
146 | }
|
147 | function tabTrappingKey(event, parentElem) {
|
148 |
|
149 | if (!event || event.key !== 'Tab') return;
|
150 |
|
151 | if (!parentElem || !parentElem.contains) {
|
152 | if (process && "development" === 'development') {
|
153 | console.warn('focus-trap-js: parent element is not defined');
|
154 | }
|
155 |
|
156 | return false;
|
157 | }
|
158 |
|
159 | if (!parentElem.contains(event.target)) {
|
160 | return false;
|
161 | }
|
162 |
|
163 | var allTabbingElements = getAllTabbingElements(parentElem);
|
164 | var firstFocusableElement = allTabbingElements[0];
|
165 | var lastFocusableElement = allTabbingElements[allTabbingElements.length - 1];
|
166 |
|
167 | if (event.shiftKey && event.target === firstFocusableElement) {
|
168 | lastFocusableElement.focus();
|
169 | event.preventDefault();
|
170 | return true;
|
171 | } else if (!event.shiftKey && event.target === lastFocusableElement) {
|
172 | firstFocusableElement.focus();
|
173 | event.preventDefault();
|
174 | return true;
|
175 | }
|
176 |
|
177 | return false;
|
178 | }
|
179 |
|
180 | function getTabindex(node) {
|
181 | var tabindexAttr = parseInt(node.getAttribute('tabindex'), 10);
|
182 | if (!isNaN(tabindexAttr)) return tabindexAttr;
|
183 |
|
184 |
|
185 | if (isContentEditable(node)) return 0;
|
186 | return node.tabIndex;
|
187 | }
|
188 |
|
189 | function isContentEditable(node) {
|
190 | return node.getAttribute('contentEditable');
|
191 | }
|
192 |
|
193 | var FocusTrap = function FocusTrap(_ref) {
|
194 | var container = _ref.container;
|
195 | var refLastFocus = React.useRef();
|
196 | |
197 |
|
198 |
|
199 |
|
200 | React.useEffect(function () {
|
201 | var handleKeyEvent = function handleKeyEvent(event) {
|
202 | if (container === null || container === void 0 ? void 0 : container.current) {
|
203 | tabTrappingKey(event, container.current);
|
204 | }
|
205 | };
|
206 |
|
207 | if (isBrowser) {
|
208 | document.addEventListener('keydown', handleKeyEvent);
|
209 | }
|
210 |
|
211 |
|
212 | if (isBrowser && (container === null || container === void 0 ? void 0 : container.current)) {
|
213 | var allTabbingElements = getAllTabbingElements(container.current);
|
214 |
|
215 | if (allTabbingElements[0]) {
|
216 |
|
217 |
|
218 | if (candidateSelectors.findIndex(function (selector) {
|
219 | var _document$activeEleme;
|
220 |
|
221 | return (_document$activeEleme = document.activeElement) === null || _document$activeEleme === void 0 ? void 0 : _document$activeEleme.matches(selector);
|
222 | }) !== -1) {
|
223 | refLastFocus.current = document.activeElement;
|
224 | }
|
225 |
|
226 | allTabbingElements[0].focus();
|
227 | }
|
228 | }
|
229 |
|
230 | return function () {
|
231 | if (isBrowser) {
|
232 | var _refLastFocus$current;
|
233 |
|
234 | document.removeEventListener('keydown', handleKeyEvent);
|
235 |
|
236 | (_refLastFocus$current = refLastFocus.current) === null || _refLastFocus$current === void 0 ? void 0 : _refLastFocus$current.focus();
|
237 | }
|
238 | };
|
239 | }, [container]);
|
240 | return null;
|
241 | };
|
242 |
|
243 | var classes = {
|
244 | overlay: 'react-responsive-modal-overlay',
|
245 | modal: 'react-responsive-modal-modal',
|
246 | modalCenter: 'react-responsive-modal-modalCenter',
|
247 | closeButton: 'react-responsive-modal-closeButton',
|
248 | animationIn: 'react-responsive-modal-fadeIn',
|
249 | animationOut: 'react-responsive-modal-fadeOut'
|
250 | };
|
251 | var Modal = function Modal(_ref) {
|
252 | var _classNames$animation, _classNames$animation2;
|
253 |
|
254 | var open = _ref.open,
|
255 | center = _ref.center,
|
256 | _ref$blockScroll = _ref.blockScroll,
|
257 | blockScroll = _ref$blockScroll === void 0 ? true : _ref$blockScroll,
|
258 | _ref$closeOnEsc = _ref.closeOnEsc,
|
259 | closeOnEsc = _ref$closeOnEsc === void 0 ? true : _ref$closeOnEsc,
|
260 | _ref$closeOnOverlayCl = _ref.closeOnOverlayClick,
|
261 | closeOnOverlayClick = _ref$closeOnOverlayCl === void 0 ? true : _ref$closeOnOverlayCl,
|
262 | container = _ref.container,
|
263 | _ref$showCloseIcon = _ref.showCloseIcon,
|
264 | showCloseIcon = _ref$showCloseIcon === void 0 ? true : _ref$showCloseIcon,
|
265 | closeIconId = _ref.closeIconId,
|
266 | closeIcon = _ref.closeIcon,
|
267 | _ref$focusTrapped = _ref.focusTrapped,
|
268 | focusTrapped = _ref$focusTrapped === void 0 ? true : _ref$focusTrapped,
|
269 | _ref$animationDuratio = _ref.animationDuration,
|
270 | animationDuration = _ref$animationDuratio === void 0 ? 500 : _ref$animationDuratio,
|
271 | classNames = _ref.classNames,
|
272 | styles = _ref.styles,
|
273 | _ref$role = _ref.role,
|
274 | role = _ref$role === void 0 ? 'dialog' : _ref$role,
|
275 | ariaDescribedby = _ref.ariaDescribedby,
|
276 | ariaLabelledby = _ref.ariaLabelledby,
|
277 | modalId = _ref.modalId,
|
278 | onClose = _ref.onClose,
|
279 | onEscKeyDown = _ref.onEscKeyDown,
|
280 | onOverlayClick = _ref.onOverlayClick,
|
281 | onAnimationEnd = _ref.onAnimationEnd,
|
282 | children = _ref.children;
|
283 | var refModal = React.useRef(null);
|
284 | var refShouldClose = React.useRef(null);
|
285 | var refContainer = React.useRef(null);
|
286 |
|
287 |
|
288 | if (refContainer.current === null && isBrowser) {
|
289 | refContainer.current = document.createElement('div');
|
290 | }
|
291 |
|
292 | var _useState = React.useState(open),
|
293 | showPortal = _useState[0],
|
294 | setShowPortal = _useState[1];
|
295 |
|
296 | var handleOpen = function handleOpen() {
|
297 | modalManager.add(refContainer.current, blockScroll);
|
298 |
|
299 | if (blockScroll) {
|
300 | blockNoScroll();
|
301 | }
|
302 |
|
303 | if (refContainer.current && !container && !document.body.contains(refContainer.current)) {
|
304 | document.body.appendChild(refContainer.current);
|
305 | }
|
306 |
|
307 | document.addEventListener('keydown', handleKeydown);
|
308 | };
|
309 |
|
310 | var handleClose = function handleClose() {
|
311 | modalManager.remove(refContainer.current);
|
312 |
|
313 | if (blockScroll) {
|
314 | unblockNoScroll();
|
315 | }
|
316 |
|
317 | if (refContainer.current && !container && document.body.contains(refContainer.current)) {
|
318 | document.body.removeChild(refContainer.current);
|
319 | }
|
320 |
|
321 | document.removeEventListener('keydown', handleKeydown);
|
322 | };
|
323 |
|
324 | var handleKeydown = function handleKeydown(event) {
|
325 |
|
326 | if (event.keyCode !== 27 || !modalManager.isTopModal(refContainer.current)) {
|
327 | return;
|
328 | }
|
329 |
|
330 | if (onEscKeyDown) {
|
331 | onEscKeyDown(event);
|
332 | }
|
333 |
|
334 | if (closeOnEsc) {
|
335 | onClose();
|
336 | }
|
337 | };
|
338 |
|
339 | React.useEffect(function () {
|
340 |
|
341 | if (open) {
|
342 | handleOpen();
|
343 | }
|
344 |
|
345 | return function () {
|
346 |
|
347 | if (showPortal) {
|
348 | handleClose();
|
349 | }
|
350 | };
|
351 | }, []);
|
352 | React.useEffect(function () {
|
353 |
|
354 | if (open && !showPortal) {
|
355 | setShowPortal(true);
|
356 | handleOpen();
|
357 | }
|
358 | }, [open]);
|
359 |
|
360 | var handleClickOverlay = function handleClickOverlay(event) {
|
361 | if (refShouldClose.current === null) {
|
362 | refShouldClose.current = true;
|
363 | }
|
364 |
|
365 | if (!refShouldClose.current) {
|
366 | refShouldClose.current = null;
|
367 | return;
|
368 | }
|
369 |
|
370 | if (onOverlayClick) {
|
371 | onOverlayClick(event);
|
372 | }
|
373 |
|
374 | if (closeOnOverlayClick) {
|
375 | onClose();
|
376 | }
|
377 |
|
378 | refShouldClose.current = null;
|
379 | };
|
380 |
|
381 | var handleModalEvent = function handleModalEvent() {
|
382 | refShouldClose.current = false;
|
383 | };
|
384 |
|
385 | var handleClickCloseIcon = function handleClickCloseIcon() {
|
386 | onClose();
|
387 | };
|
388 |
|
389 | var handleAnimationEnd = function handleAnimationEnd() {
|
390 | if (!open) {
|
391 | setShowPortal(false);
|
392 | handleClose();
|
393 | }
|
394 |
|
395 | if (blockScroll) {
|
396 | unblockNoScroll();
|
397 | }
|
398 |
|
399 | if (onAnimationEnd) {
|
400 | onAnimationEnd();
|
401 | }
|
402 | };
|
403 |
|
404 | return showPortal ? ReactDom.createPortal(React__default.createElement("div", {
|
405 | style: _extends({
|
406 | animation: (open ? (_classNames$animation = classNames === null || classNames === void 0 ? void 0 : classNames.animationIn) !== null && _classNames$animation !== void 0 ? _classNames$animation : classes.animationIn : (_classNames$animation2 = classNames === null || classNames === void 0 ? void 0 : classNames.animationOut) !== null && _classNames$animation2 !== void 0 ? _classNames$animation2 : classes.animationOut) + " " + animationDuration + "ms"
|
407 | }, styles === null || styles === void 0 ? void 0 : styles.overlay),
|
408 | className: cx(classes.overlay, classNames === null || classNames === void 0 ? void 0 : classNames.overlay),
|
409 | onClick: handleClickOverlay,
|
410 | onAnimationEnd: handleAnimationEnd,
|
411 | "data-testid": "overlay"
|
412 | }, React__default.createElement("div", {
|
413 | ref: refModal,
|
414 | className: cx(classes.modal, center && classes.modalCenter, classNames === null || classNames === void 0 ? void 0 : classNames.modal),
|
415 | style: styles === null || styles === void 0 ? void 0 : styles.modal,
|
416 | onMouseDown: handleModalEvent,
|
417 | onMouseUp: handleModalEvent,
|
418 | onClick: handleModalEvent,
|
419 | id: modalId,
|
420 | role: role,
|
421 | "aria-modal": "true",
|
422 | "aria-labelledby": ariaLabelledby,
|
423 | "aria-describedby": ariaDescribedby,
|
424 | "data-testid": "modal"
|
425 | }, focusTrapped && React__default.createElement(FocusTrap, {
|
426 | container: refModal
|
427 | }), children, showCloseIcon && React__default.createElement(CloseIcon, {
|
428 | classes: classes,
|
429 | classNames: classNames,
|
430 | styles: styles,
|
431 | closeIcon: closeIcon,
|
432 | onClickCloseIcon: handleClickCloseIcon,
|
433 | id: closeIconId
|
434 | }))), container || refContainer.current) : null;
|
435 | };
|
436 |
|
437 | exports.Modal = Modal;
|
438 | exports.default = Modal;
|
439 |
|