PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.18.0
GiveWP – Donation Plugin and Fundraising Platform v4.18.0
4.18.0 4.17.0 4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 All 257 releases
give / src / Campaigns / Blocks / shared / components / ModalForm / index.tsx

index.tsx in GiveWP – Donation Plugin and Fundraising Platform 4.18.0, at src/Campaigns/Blocks/shared/components/ModalForm/index.tsx

163 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import {useEffect, useState} from '@wordpress/element';
2 import {__} from '@wordpress/i18n';
3 import {Button, Dialog, Modal, ModalOverlay} from 'react-aria-components';
4 import ModalCloseIcon from './ModalClose';
5 import EmbedFrame from '@givewp/forms/shared/EmbedFrame';
6 import './styles.scss';
7 import '../EntitySelector/styles/index.scss';
8 import {FocusScope} from 'react-aria';
9
10 /**
11 * @since 4.17.0 add formUrl, where the fallback link points when the form is slow to load.
12 * @since 4.3.0
13 */
14 type ModalFormProps = {
15 dataSrc: string;
16 embedId: string;
17 buttonText: string;
18 isFormRedirect: boolean;
19 formViewUrl: string;
20 formUrl?: string;
21 };
22
23 /**
24 * @since 4.17.0 render the iframe through EmbedFrame; a form that is slow to load also offers a link.
25 * @since 4.17.0 Share the launcher's pending state markup and styles with the external embed.
26 * @since 4.3.0
27 */
28 export default function ModalForm({
29 dataSrc,
30 embedId,
31 buttonText,
32 isFormRedirect,
33 formViewUrl,
34 formUrl,
35 }: ModalFormProps) {
36 const [dataSrcUrl, setDataSrcUrl] = useState(dataSrc);
37 const [isOpen, setIsOpen] = useState<boolean>(isFormRedirect);
38 const [isLoading, setLoading] = useState<boolean>(false);
39 const [isEntering, setEntering] = useState<boolean>(false);
40
41 useEffect(() => {
42 const handleEscape = (event: KeyboardEvent) => {
43 if (event.key === 'Escape' && isOpen) {
44 closeModal();
45 }
46 };
47
48 document.addEventListener('keydown', handleEscape);
49 return () => {
50 document.removeEventListener('keydown', handleEscape);
51 };
52 }, [isOpen]);
53
54 // Preload the iframe document
55 useEffect(() => {
56 const selector = `link[rel="preload"][href="${dataSrcUrl}"][as="document"]`;
57
58 const existingLink = document.querySelector(selector);
59
60 if (!existingLink) {
61 const link = document.createElement('link');
62 link.rel = 'preload';
63 link.href = dataSrcUrl;
64 link.as = 'document';
65 document.head.appendChild(link);
66 }
67
68 return () => {
69 const addedLink = document.querySelector(selector);
70 if (addedLink) {
71 document.head.removeChild(addedLink);
72 }
73 };
74 }, [dataSrcUrl]);
75
76 useEffect(() => {
77 if (isEntering && !isLoading) {
78 resetEntering();
79 }
80 }, [isEntering, isLoading]);
81
82 // Offline gateways like Stripe refresh the page and need to programmatically
83 // open the confirmation page from the modal.
84 const resetDataSrcUrl = () => {
85 if (!isOpen && isFormRedirect) {
86 setDataSrcUrl(formViewUrl);
87 }
88 };
89
90 const openModal = () => {
91 setEntering(true);
92 setIsOpen(true);
93 setLoading(true);
94 resetDataSrcUrl();
95 };
96
97 const closeModal = () => {
98 setIsOpen(false);
99 setLoading(false);
100 resetDataSrcUrl();
101 };
102
103 const resetEntering = () => {
104 setTimeout(() => {
105 setEntering(false);
106 }, 2000);
107 };
108
109 return (
110 <>
111 <Button
112 type="button"
113 className="givewp-donation-form-modal__open"
114 onPress={openModal}
115 isPending={isLoading}
116 aria-label={isLoading ? __('Loading donation form', 'give') : undefined}
117 >
118 {isLoading && <span className="givewp-donation-form-modal__open__spinner" aria-hidden="true" />}
119 <span className="givewp-donation-form-modal__open__label">{buttonText}</span>
120 </Button>
121
122 <ModalOverlay
123 className="givewp-donation-form-modal__overlay"
124 data-loading={isLoading}
125 isOpen={isOpen}
126 onOpenChange={setIsOpen}
127 isDismissable
128 isEntering={isEntering}
129 >
130 <Modal className="givewp-donation-form-modal" data-loading={isLoading}>
131 <FocusScope contain restoreFocus autoFocus>
132 <Dialog
133 className="givewp-donation-form-modal__dialog"
134 aria-label={__('Donation Form', 'give')}
135 role="dialog"
136 aria-modal="true"
137 >
138 <button
139 aria-label={__('Close donation form', 'give')}
140 type="button"
141 className="givewp-donation-form-modal__close"
142 onClick={closeModal}
143 tabIndex={0}
144 >
145 <ModalCloseIcon />
146 </button>
147 <div className="givewp-donation-form-modal__dialog__content">
148 <EmbedFrame
149 src={dataSrcUrl}
150 embedId={embedId}
151 fallbackUrl={formUrl || dataSrcUrl}
152 onReady={() => setLoading(false)}
153 onSlow={() => setLoading(false)}
154 />
155 </div>
156 </Dialog>
157 </FocusScope>
158 </Modal>
159 </ModalOverlay>
160 </>
161 );
162 }
163