PluginProbe
Elementor Website Builder – more than just a page builder / 3.8.0-beta1
Elementor Website Builder – more than just a page builder v3.8.0-beta1
4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 All 457 releases
elementor / app / assets / js / ui / modal / modal.js

modal.js in Elementor Website Builder – more than just a page builder 3.8.0-beta1, at app/assets/js/ui/modal/modal.js

149 lines 3.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useState, useRef, useEffect } from 'react';
2 import { arrayToClassName } from 'elementor-app/utils/utils.js';
3
4 import Button from 'elementor-app/ui/molecules/button';
5 import Grid from 'elementor-app/ui/grid/grid';
6 import Icon from 'elementor-app/ui/atoms/icon';
7 import Text from 'elementor-app/ui/atoms/text';
8
9 import ModalSection from './modal-section';
10 import ModalTip from './modal-tip';
11
12 import './modal.scss';
13
14 export default function ModalProvider( props ) {
15 const [ show, setShow ] = useState( props.show ),
16 hideModal = () => {
17 setShow( false );
18
19 // The purpose of the props.setShow is to sync an external state with the component inner state.
20 if ( props.setShow ) {
21 props.setShow( false );
22 }
23 },
24 showModal = () => {
25 setShow( true );
26
27 // The purpose of the props.setShow is to sync an external state with the component inner state.
28 if ( props.setShow ) {
29 props.setShow( true );
30 }
31 },
32 modalAttrs = {
33 ...props,
34 show,
35 hideModal,
36 showModal,
37 };
38
39 useEffect( () => {
40 // Sync with external state.
41 setShow( props.show );
42 }, [ props.show ] );
43
44 return (
45 <>
46 {
47 props.toggleButtonProps &&
48 <Button { ...props.toggleButtonProps } onClick={ showModal } />
49 }
50
51 <Modal { ...modalAttrs }>
52 { props.children }
53 </Modal>
54 </>
55 );
56 }
57
58 ModalProvider.propTypes = {
59 children: PropTypes.node.isRequired,
60 toggleButtonProps: PropTypes.object,
61 title: PropTypes.string,
62 icon: PropTypes.string,
63 show: PropTypes.bool,
64 setShow: PropTypes.func,
65 onOpen: PropTypes.func,
66 onClose: PropTypes.func,
67 };
68
69 ModalProvider.defaultProps = {
70 show: false,
71 };
72
73 ModalProvider.Section = ModalSection;
74 ModalProvider.Tip = ModalTip;
75
76 export const Modal = ( props ) => {
77 const modalRef = useRef( null ),
78 closeRef = useRef( null ),
79 closeModal = ( e ) => {
80 const node = modalRef.current,
81 closeNode = closeRef.current,
82 isInCloseNode = closeNode && closeNode.contains( e.target );
83
84 // Ignore if click is inside the modal
85 if ( node && node.contains( e.target ) && ! isInCloseNode ) {
86 return;
87 }
88
89 props.hideModal();
90
91 if ( props.onClose ) {
92 props.onClose( e );
93 }
94 };
95
96 useEffect( () => {
97 if ( props.show ) {
98 document.addEventListener( 'mousedown', closeModal, false );
99 props.onOpen?.();
100 }
101
102 return () => document.removeEventListener( 'mousedown', closeModal, false );
103 }, [ props.show ] );
104
105 if ( ! props.show ) {
106 return null;
107 }
108
109 return (
110 // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
111 <div className="eps-modal__overlay" onClick={ closeModal }>
112 <div className={ arrayToClassName( [ 'eps-modal', props.className ] ) } ref={ modalRef } >
113 <Grid container className="eps-modal__header" justify="space-between" alignItems="center">
114 <Grid item>
115 <Icon className={ `eps-modal__icon ${ props.icon }` } />
116 <Text className="title" tag="span">{ props.title }</Text>
117 </Grid>
118 <Grid item>
119 <div className="eps-modal__close-wrapper" ref={ closeRef }>
120 <Button text={ __( 'Close', 'elementor' ) } hideText icon="eicon-close" onClick={ props.closeModal } />
121 </div>
122 </Grid>
123 </Grid>
124 <div className="eps-modal__body">
125 { props.children }
126 </div>
127 </div>
128 </div>
129 );
130 };
131
132 Modal.propTypes = {
133 className: PropTypes.string,
134 children: PropTypes.any.isRequired,
135 title: PropTypes.string.isRequired,
136 icon: PropTypes.string,
137 show: PropTypes.bool,
138 setShow: PropTypes.func,
139 hideModal: PropTypes.func,
140 showModal: PropTypes.func,
141 closeModal: PropTypes.func,
142 onOpen: PropTypes.func,
143 onClose: PropTypes.func,
144 };
145
146 Modal.defaultProps = {
147 className: '',
148 };
149