1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | import * as React from "react";
|
16 | import { Portal } from "@reach/portal";
|
17 | import {
|
18 | composeEventHandlers,
|
19 | createContext,
|
20 | getOwnerDocument,
|
21 | noop,
|
22 | useComposedRefs
|
23 | } from "@reach/utils";
|
24 | import FocusLock from "react-focus-lock";
|
25 | import { RemoveScroll } from "react-remove-scroll";
|
26 | var [DialogContextProvider, useDialogContext] = createContext("DialogContext", {
|
27 | isOpen: false
|
28 | });
|
29 | function DialogWrapper({
|
30 | isOpen = true,
|
31 | children,
|
32 | ...props
|
33 | }) {
|
34 | React.useEffect(() => {
|
35 | if (isOpen) {
|
36 | window.__REACH_DISABLE_TOOLTIPS = true;
|
37 | } else {
|
38 | window.requestAnimationFrame(() => {
|
39 | window.__REACH_DISABLE_TOOLTIPS = false;
|
40 | });
|
41 | }
|
42 | }, [isOpen]);
|
43 | return React.createElement(Portal, {
|
44 | "data-reach-dialog-wrapper": "",
|
45 | "data-state": isOpen ? "open" : "closed" ,
|
46 | ...props
|
47 | }, React.createElement(DialogContextProvider, {
|
48 | isOpen
|
49 | }, children));
|
50 | }
|
51 | DialogWrapper.displayName = "unstable_DialogWrapper";
|
52 | var DialogInner = React.forwardRef(function DialogInner2({
|
53 | allowPinchZoom,
|
54 | as: Comp = "div",
|
55 | dangerouslyBypassFocusLock,
|
56 | dangerouslyBypassScrollLock,
|
57 | initialFocusRef,
|
58 | onClick,
|
59 | onDismiss = noop,
|
60 | onKeyDown,
|
61 | onMouseDown,
|
62 | unstable_lockFocusAcrossFrames,
|
63 | ...props
|
64 | }, forwardedRef) {
|
65 | let { isOpen } = useDialogContext("DialogInner");
|
66 | let lockFocusAcrossFramesIsDefined = unstable_lockFocusAcrossFrames !== void 0;
|
67 | if (true) {
|
68 | React.useEffect(() => {
|
69 | if (lockFocusAcrossFramesIsDefined) {
|
70 | console.warn(`The unstable_lockFocusAcrossFrames in @reach/dialog is deprecated. It will be removed in the next minor release.`);
|
71 | }
|
72 | }, [lockFocusAcrossFramesIsDefined]);
|
73 | }
|
74 | const mouseDownTarget = React.useRef(null);
|
75 | const overlayNode = React.useRef(null);
|
76 | const ref = useComposedRefs(overlayNode, forwardedRef);
|
77 | const activateFocusLock = React.useCallback(() => {
|
78 | if (initialFocusRef && initialFocusRef.current) {
|
79 | initialFocusRef.current.focus();
|
80 | }
|
81 | }, [initialFocusRef]);
|
82 | function handleClick(event) {
|
83 | if (mouseDownTarget.current === event.target) {
|
84 | event.stopPropagation();
|
85 | onDismiss(event);
|
86 | }
|
87 | }
|
88 | function handleKeyDown(event) {
|
89 | if (event.key === "Escape") {
|
90 | event.stopPropagation();
|
91 | onDismiss(event);
|
92 | }
|
93 | }
|
94 | function handleMouseDown(event) {
|
95 | mouseDownTarget.current = event.target;
|
96 | }
|
97 | React.useEffect(() => {
|
98 | return overlayNode.current ? createAriaHider(overlayNode.current) : void 0;
|
99 | }, []);
|
100 | return React.createElement(FocusLock, {
|
101 | autoFocus: true,
|
102 | returnFocus: true,
|
103 | onActivation: activateFocusLock,
|
104 | disabled: dangerouslyBypassFocusLock != null ? dangerouslyBypassFocusLock : !isOpen,
|
105 | crossFrame: unstable_lockFocusAcrossFrames ?? true
|
106 | }, React.createElement(RemoveScroll, {
|
107 | allowPinchZoom,
|
108 | enabled: dangerouslyBypassScrollLock != null ? !dangerouslyBypassScrollLock : isOpen
|
109 | }, React.createElement(Comp, {
|
110 | ...props,
|
111 | ref,
|
112 | "data-reach-dialog-inner": "",
|
113 | "data-state": isOpen ? "open" : "closed" ,
|
114 | onClick: composeEventHandlers(onClick, handleClick),
|
115 | onKeyDown: composeEventHandlers(onKeyDown, handleKeyDown),
|
116 | onMouseDown: composeEventHandlers(onMouseDown, handleMouseDown)
|
117 | })));
|
118 | });
|
119 | DialogInner.displayName = "DialogInner";
|
120 | var DialogOverlay = React.forwardRef(function DialogOverlay2({ as: Comp = "div", isOpen = true, ...props }, forwardedRef) {
|
121 | return isOpen ? React.createElement(DialogWrapper, {
|
122 | isOpen
|
123 | }, React.createElement(DialogInner, {
|
124 | "data-reach-dialog-overlay": "",
|
125 | ref: forwardedRef,
|
126 | as: Comp,
|
127 | ...props
|
128 | })) : null;
|
129 | });
|
130 | DialogOverlay.displayName = "DialogOverlay";
|
131 | var DialogContent = React.forwardRef(function DialogContent2({ as: Comp = "div", onClick, onKeyDown, ...props }, forwardedRef) {
|
132 | let { isOpen } = useDialogContext("DialogContent");
|
133 | return React.createElement(Comp, {
|
134 | "aria-modal": "true",
|
135 | role: "dialog",
|
136 | tabIndex: -1,
|
137 | ...props,
|
138 | ref: forwardedRef,
|
139 | "data-reach-dialog-content": "",
|
140 | "data-state": isOpen ? "open" : "closed" ,
|
141 | onClick: composeEventHandlers(onClick, (event) => {
|
142 | event.stopPropagation();
|
143 | })
|
144 | });
|
145 | });
|
146 | DialogContent.displayName = "DialogContent";
|
147 | var Dialog = React.forwardRef(function Dialog2({
|
148 | allowPinchZoom = false,
|
149 | initialFocusRef,
|
150 | isOpen,
|
151 | onDismiss = noop,
|
152 | ...props
|
153 | }, forwardedRef) {
|
154 | return React.createElement(DialogOverlay, {
|
155 | allowPinchZoom,
|
156 | initialFocusRef,
|
157 | isOpen,
|
158 | onDismiss
|
159 | }, React.createElement(DialogContent, {
|
160 | ref: forwardedRef,
|
161 | ...props
|
162 | }));
|
163 | });
|
164 | Dialog.displayName = "Dialog";
|
165 | function createAriaHider(dialogNode) {
|
166 | let originalValues = [];
|
167 | let rootNodes = [];
|
168 | let ownerDocument = getOwnerDocument(dialogNode);
|
169 | if (!dialogNode) {
|
170 | if (true) {
|
171 | console.warn("A ref has not yet been attached to a dialog node when attempting to call `createAriaHider`.");
|
172 | }
|
173 | return noop;
|
174 | }
|
175 | Array.prototype.forEach.call(ownerDocument.querySelectorAll("body > *"), (node) => {
|
176 | const portalNode = dialogNode.parentNode?.parentNode?.parentNode;
|
177 | if (node === portalNode) {
|
178 | return;
|
179 | }
|
180 | let attr = node.getAttribute("aria-hidden");
|
181 | let alreadyHidden = attr !== null && attr !== "false";
|
182 | if (alreadyHidden) {
|
183 | return;
|
184 | }
|
185 | originalValues.push(attr);
|
186 | rootNodes.push(node);
|
187 | node.setAttribute("aria-hidden", "true");
|
188 | });
|
189 | return () => {
|
190 | rootNodes.forEach((node, index) => {
|
191 | let originalValue = originalValues[index];
|
192 | if (originalValue === null) {
|
193 | node.removeAttribute("aria-hidden");
|
194 | } else {
|
195 | node.setAttribute("aria-hidden", originalValue);
|
196 | }
|
197 | });
|
198 | };
|
199 | }
|
200 | export {
|
201 | Dialog,
|
202 | DialogContent,
|
203 | DialogInner,
|
204 | DialogOverlay,
|
205 | DialogWrapper as unstable_DialogWrapper
|
206 | };
|