PluginProbe
ElasticPress / 4.2.2
ElasticPress v4.2.2
5.3.5 5.3.4 3.6.5 3.6.6 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.7.0 4.7.1 4.7.2 5.0.0 5.0.1 5.0.2 All 108 releases
elasticpress / assets / js / instant-results / components / common / modal.js

modal.js in ElasticPress 4.2.2, at assets/js/instant-results/components/common/modal.js

107 lines 2.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * External dependencies.
3 */
4 import FocusTrap from 'focus-trap-react';
5
6 /**
7 * WordPress dependencies.
8 */
9 import { forwardRef, useCallback, useEffect, useRef, WPElement } from '@wordpress/element';
10 import { closeSmall, Icon } from '@wordpress/icons';
11 import { __ } from '@wordpress/i18n';
12
13 /**
14 * Modal components.
15 *
16 * @param {object} props Component props.
17 * @param {WPElement} props.children Component children.
18 * @param {boolean} props.isOpen Whether the modal is open.
19 * @param {Function} props.onClose Callback to run when modal is closed.
20 * @param {object} ref Ref.
21 * @returns {WPElement} React element.
22 */
23 const Modal = ({ children, isOpen, onClose, ...props }, ref) => {
24 /**
25 * Reference to close button element.
26 */
27 const closeRef = useRef(null);
28
29 /**
30 * Handle key down.
31 *
32 * @param {Event} event Keydown event.
33 */
34 const onKeyDown = useCallback(
35 (event) => {
36 if (event.key === 'Escape' || event.key === 'Esc') {
37 onClose();
38 }
39 },
40 [onClose],
41 );
42
43 /**
44 * Handle binding events to outside DOM elements.
45 *
46 * @returns {Function} Clean up function that removes events.
47 */
48 const handleEvents = () => {
49 const { current: modalEl } = ref;
50
51 modalEl.ownerDocument.body.addEventListener('keydown', onKeyDown);
52
53 return () => {
54 modalEl.ownerDocument.body.removeEventListener('keydown', onKeyDown);
55 };
56 };
57
58 /**
59 * Handle the model being opened or closed.
60 *
61 * Adds a class to the body element to allow controlling scrolling.
62 */
63 const handleOpen = () => {
64 const { current: modalEl } = ref;
65
66 if (isOpen) {
67 modalEl.ownerDocument.body.classList.add('has-ep-search-modal');
68 closeRef.current.focus();
69 } else {
70 modalEl.ownerDocument.body.classList.remove('has-ep-search-modal');
71 }
72 };
73
74 useEffect(handleEvents, [onKeyDown, ref]);
75 useEffect(handleOpen, [isOpen, ref]);
76
77 return (
78 <div
79 aria-hidden={!isOpen}
80 aria-modal="true"
81 className="ep-search-modal"
82 ref={ref}
83 role="dialog"
84 {...props}
85 >
86 {isOpen && (
87 <FocusTrap focusTrapOptions={{ allowOutsideClick: true }}>
88 <div className="ep-search-modal__content">
89 <button
90 className="ep-search-modal__close ep-search-reset-button ep-search-icon-button"
91 type="button"
92 onClick={onClose}
93 ref={closeRef}
94 >
95 <Icon icon={closeSmall} />
96 {__('Close', 'elasticpress')}
97 </button>
98 {children}
99 </div>
100 </FocusTrap>
101 )}
102 </div>
103 );
104 };
105
106 export default forwardRef(Modal);
107