@tamagui/dismissable 2.7.7 → 3.0.0-beta.637.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/cjs/Dismissable.cjs +282 -330
  2. package/dist/cjs/Dismissable.native.cjs +61 -0
  3. package/dist/cjs/Dismissable.native.js +33 -37
  4. package/dist/cjs/Dismissable.native.js.map +1 -1
  5. package/dist/cjs/DismissableProps.cjs +10 -11
  6. package/dist/cjs/DismissableProps.native.cjs +19 -0
  7. package/dist/cjs/DismissableProps.native.js +10 -10
  8. package/dist/cjs/DismissableProps.native.js.map +1 -1
  9. package/dist/cjs/index.cjs +10 -11
  10. package/dist/cjs/index.native.cjs +21 -0
  11. package/dist/cjs/index.native.js +10 -10
  12. package/dist/cjs/index.native.js.map +1 -1
  13. package/dist/esm/Dismissable.mjs +261 -301
  14. package/dist/esm/Dismissable.mjs.map +1 -1
  15. package/dist/esm/Dismissable.native.js +12 -9
  16. package/dist/esm/Dismissable.native.js.map +1 -1
  17. package/dist/esm/DismissableProps.mjs +0 -2
  18. package/dist/esm/DismissableProps.native.js +0 -2
  19. package/dist/esm/index.js +1 -2
  20. package/dist/esm/index.mjs +1 -2
  21. package/dist/esm/index.native.js +1 -2
  22. package/dist/jsx/Dismissable.mjs +261 -301
  23. package/dist/jsx/Dismissable.mjs.map +1 -1
  24. package/dist/jsx/Dismissable.native.cjs +61 -0
  25. package/dist/jsx/Dismissable.native.js +33 -37
  26. package/dist/jsx/Dismissable.native.js.map +1 -1
  27. package/dist/jsx/DismissableProps.mjs +0 -2
  28. package/dist/jsx/DismissableProps.native.cjs +19 -0
  29. package/dist/jsx/DismissableProps.native.js +10 -10
  30. package/dist/jsx/DismissableProps.native.js.map +1 -1
  31. package/dist/jsx/index.js +1 -2
  32. package/dist/jsx/index.mjs +1 -2
  33. package/dist/jsx/index.native.cjs +21 -0
  34. package/dist/jsx/index.native.js +10 -10
  35. package/dist/jsx/index.native.js.map +1 -1
  36. package/package.json +7 -7
  37. package/src/Dismissable.native.tsx +3 -2
  38. package/src/Dismissable.tsx +90 -92
  39. package/src/DismissableProps.tsx +31 -10
  40. package/types/Dismissable.d.ts +3 -9
  41. package/types/Dismissable.d.ts.map +1 -1
  42. package/types/Dismissable.native.d.ts +2 -2
  43. package/types/Dismissable.native.d.ts.map +1 -1
  44. package/types/DismissableProps.d.ts +22 -10
  45. package/types/DismissableProps.d.ts.map +1 -1
  46. package/dist/esm/DismissableProps.mjs.map +0 -1
  47. package/dist/esm/DismissableProps.native.js.map +0 -1
  48. package/dist/esm/index.js.map +0 -1
  49. package/dist/esm/index.mjs.map +0 -1
  50. package/dist/esm/index.native.js.map +0 -1
  51. package/dist/jsx/DismissableProps.mjs.map +0 -1
  52. package/dist/jsx/index.js.map +0 -1
  53. package/dist/jsx/index.mjs.map +0 -1
@@ -1,340 +1,300 @@
1
1
  import { useComposedRefs } from "@tamagui/compose-refs";
2
- import { Slot, View, composeEventHandlers } from "@tamagui/core";
2
+ import { Slot, View, composeEventHandlers, createChangeEventDetails, createRefComponent } from "@tamagui/core";
3
3
  import { useEscapeKeydown } from "@tamagui/use-escape-keydown";
4
4
  import { useEvent } from "@tamagui/use-event";
5
5
  import * as React from "react";
6
6
  import * as ReactDOM from "react-dom";
7
7
  import { jsx } from "react/jsx-runtime";
8
+
8
9
  function dispatchDiscreteCustomEvent(target, event) {
9
- if (target) ReactDOM.flushSync(() => target.dispatchEvent(event));
10
+ if (target) ReactDOM.flushSync(() => target.dispatchEvent(event));
10
11
  }
11
12
  const DISMISSABLE_LAYER_NAME = "Dismissable";
12
13
  const CONTEXT_UPDATE = "dismissable.update";
13
- const POINTER_DOWN_OUTSIDE = "dismissable.pointerDownOutside";
14
- const FOCUS_OUTSIDE = "dismissable.focusOutside";
15
14
  let originalBodyPointerEvents;
16
- const globalLayers = /* @__PURE__ */new Set();
17
- const layerChangeListeners = /* @__PURE__ */new Set();
15
+ const globalLayers = /* @__PURE__ */ new Set();
16
+ const layerChangeListeners = /* @__PURE__ */ new Set();
18
17
  let layersWithPointerEventsDisabledCount = 0;
19
18
  function notifyLayerChange() {
20
- for (const listener of layerChangeListeners) {
21
- listener();
22
- }
19
+ for (const listener of layerChangeListeners) {
20
+ listener();
21
+ }
23
22
  }
24
23
  function getDismissableLayerCount() {
25
- return globalLayers.size;
24
+ return globalLayers.size;
26
25
  }
27
26
  function debugDismissableLayers() {
28
- const layers = Array.from(globalLayers);
29
- console.log("[Dismissable] Active layers:", layers.length, layers);
30
- return layers;
27
+ const layers = Array.from(globalLayers);
28
+ console.log("[Dismissable] Active layers:", layers.length, layers);
29
+ return layers;
31
30
  }
32
31
  function useHasDismissableLayers() {
33
- const [count, setCount] = React.useState(() => globalLayers.size);
34
- React.useEffect(() => {
35
- setCount(globalLayers.size);
36
- const update = () => setCount(globalLayers.size);
37
- layerChangeListeners.add(update);
38
- return () => {
39
- layerChangeListeners.delete(update);
40
- };
41
- }, []);
42
- return count > 0;
32
+ const [count, setCount] = React.useState(() => globalLayers.size);
33
+ React.useEffect(() => {
34
+ setCount(globalLayers.size);
35
+ const update = () => setCount(globalLayers.size);
36
+ layerChangeListeners.add(update);
37
+ return () => {
38
+ layerChangeListeners.delete(update);
39
+ };
40
+ }, []);
41
+ return count > 0;
43
42
  }
44
43
  const DismissableContext = React.createContext({
45
- layers: /* @__PURE__ */new Set(),
46
- layersWithOutsidePointerEventsDisabled: /* @__PURE__ */new Set(),
47
- branches: /* @__PURE__ */new Set()
44
+ layers: /* @__PURE__ */ new Set(),
45
+ layersWithOutsidePointerEventsDisabled: /* @__PURE__ */ new Set(),
46
+ branches: /* @__PURE__ */ new Set()
48
47
  });
49
48
  function useIsInsideDismissable(ref) {
50
- const context = React.useContext(DismissableContext);
51
- const [isInside, setIsInside] = React.useState(false);
52
- React.useEffect(() => {
53
- const check = () => {
54
- const el = ref.current;
55
- if (!el) {
56
- setIsInside(false);
57
- return;
58
- }
59
- for (const layer of context.layers) {
60
- if (layer.contains(el)) {
61
- setIsInside(true);
62
- return;
63
- }
64
- }
65
- setIsInside(false);
66
- };
67
- check();
68
- document.addEventListener(CONTEXT_UPDATE, check);
69
- return () => document.removeEventListener(CONTEXT_UPDATE, check);
70
- }, [context.layers, ref]);
71
- return isInside;
49
+ const context = React.useContext(DismissableContext);
50
+ const [isInside, setIsInside] = React.useState(false);
51
+ React.useEffect(() => {
52
+ const check = () => {
53
+ const el = ref.current;
54
+ if (!el) {
55
+ setIsInside(false);
56
+ return;
57
+ }
58
+ for (const layer of context.layers) {
59
+ if (layer.contains(el)) {
60
+ setIsInside(true);
61
+ return;
62
+ }
63
+ }
64
+ setIsInside(false);
65
+ };
66
+ check();
67
+ document.addEventListener(CONTEXT_UPDATE, check);
68
+ return () => document.removeEventListener(CONTEXT_UPDATE, check);
69
+ }, [context.layers, ref]);
70
+ return isInside;
72
71
  }
73
72
  function useDismissableLayersAbove(ref) {
74
- const context = React.useContext(DismissableContext);
75
- const [count, setCount] = React.useState(0);
76
- React.useEffect(() => {
77
- const check = () => {
78
- const el = ref.current;
79
- if (!el) {
80
- setCount(0);
81
- return;
82
- }
83
- let above = 0;
84
- for (const layer of context.layers) {
85
- if (layer.contains(el)) {
86
- above++;
87
- }
88
- }
89
- setCount(above);
90
- };
91
- check();
92
- document.addEventListener(CONTEXT_UPDATE, check);
93
- return () => document.removeEventListener(CONTEXT_UPDATE, check);
94
- }, [context.layers, ref]);
95
- return count;
73
+ const context = React.useContext(DismissableContext);
74
+ const [count, setCount] = React.useState(0);
75
+ React.useEffect(() => {
76
+ const check = () => {
77
+ const el = ref.current;
78
+ if (!el) {
79
+ setCount(0);
80
+ return;
81
+ }
82
+ let above = 0;
83
+ for (const layer of context.layers) {
84
+ if (layer.contains(el)) {
85
+ above++;
86
+ }
87
+ }
88
+ setCount(above);
89
+ };
90
+ check();
91
+ document.addEventListener(CONTEXT_UPDATE, check);
92
+ return () => document.removeEventListener(CONTEXT_UPDATE, check);
93
+ }, [context.layers, ref]);
94
+ return count;
96
95
  }
97
- const Dismissable = React.forwardRef((props, forwardedRef) => {
98
- const {
99
- disableOutsidePointerEvents = false,
100
- forceUnmount,
101
- onEscapeKeyDown,
102
- onPointerDownOutside,
103
- onFocusOutside,
104
- onInteractOutside,
105
- onDismiss,
106
- asChild,
107
- children,
108
- branches: branchesProp,
109
- ...layerProps
110
- } = props;
111
- const Comp = asChild ? Slot : View;
112
- const context = React.useContext(DismissableContext);
113
- const [node, setNode] = React.useState(null);
114
- const [, force] = React.useState({});
115
- const composedRefs = useComposedRefs(forwardedRef, node2 => setNode(node2));
116
- const layers = Array.from(context.layers);
117
- const [highestLayerWithOutsidePointerEventsDisabled] = [...context.layersWithOutsidePointerEventsDisabled].slice(-1);
118
- const highestLayerWithOutsidePointerEventsDisabledIndex = layers.indexOf(highestLayerWithOutsidePointerEventsDisabled);
119
- const index = node ? layers.indexOf(node) : -1;
120
- const isBodyPointerEventsDisabled = context.layersWithOutsidePointerEventsDisabled.size > 0;
121
- const isPointerEventsEnabled = index >= highestLayerWithOutsidePointerEventsDisabledIndex;
122
- const pointerDownOutside = usePointerDownOutside(event => {
123
- const target = event.target;
124
- const branches = branchesProp || context.branches;
125
- const isPointerDownOnBranch = [...branches].some(branch => branch.contains(target));
126
- if (!isPointerEventsEnabled || isPointerDownOnBranch) return;
127
- onPointerDownOutside?.(event);
128
- onInteractOutside?.(event);
129
- if (!event.defaultPrevented) onDismiss?.();
130
- });
131
- const focusOutside = useFocusOutside(event => {
132
- const target = event.target;
133
- const branches = branchesProp || context.branches;
134
- const isFocusInBranch = [...branches].some(branch => branch.contains(target));
135
- if (isFocusInBranch) return;
136
- onFocusOutside?.(event);
137
- onInteractOutside?.(event);
138
- if (!event.defaultPrevented) onDismiss?.();
139
- });
140
- const forceUnmountRef = React.useRef(forceUnmount);
141
- React.useEffect(() => {
142
- forceUnmountRef.current = forceUnmount;
143
- }, [forceUnmount]);
144
- useEscapeKeydown(event => {
145
- if (forceUnmountRef.current) return;
146
- const currentLayers = Array.from(context.layers);
147
- const currentIndex = node ? currentLayers.indexOf(node) : -1;
148
- const isHighestLayer = currentIndex === currentLayers.length - 1;
149
- if (!isHighestLayer) return;
150
- onEscapeKeyDown?.(event);
151
- if (!event.defaultPrevented && onDismiss) {
152
- event.preventDefault();
153
- onDismiss();
154
- }
155
- });
156
- React.useEffect(() => {
157
- if (!node) return;
158
- if (forceUnmount) return;
159
- if (disableOutsidePointerEvents) {
160
- if (context.layersWithOutsidePointerEventsDisabled.size === 0) {
161
- originalBodyPointerEvents = document.body.style.pointerEvents;
162
- document.body.style.pointerEvents = "none";
163
- }
164
- context.layersWithOutsidePointerEventsDisabled.add(node);
165
- layersWithPointerEventsDisabledCount++;
166
- }
167
- context.layers.add(node);
168
- globalLayers.add(node);
169
- if (disableOutsidePointerEvents || layersWithPointerEventsDisabledCount > 0) {
170
- dispatchUpdate();
171
- }
172
- notifyLayerChange();
173
- return () => {
174
- if (disableOutsidePointerEvents) {
175
- if (context.layersWithOutsidePointerEventsDisabled.size === 1) {
176
- document.body.style.pointerEvents = originalBodyPointerEvents;
177
- }
178
- }
179
- };
180
- }, [node, disableOutsidePointerEvents, forceUnmount, context]);
181
- React.useEffect(() => {
182
- if (forceUnmount) return;
183
- return () => {
184
- if (!node) return;
185
- const hadPointerEventsDisabled = context.layersWithOutsidePointerEventsDisabled.has(node);
186
- context.layers.delete(node);
187
- context.layersWithOutsidePointerEventsDisabled.delete(node);
188
- globalLayers.delete(node);
189
- if (layersWithPointerEventsDisabledCount > 0) {
190
- dispatchUpdate();
191
- }
192
- notifyLayerChange();
193
- if (hadPointerEventsDisabled) {
194
- layersWithPointerEventsDisabledCount--;
195
- }
196
- };
197
- }, [node, context, forceUnmount]);
198
- React.useEffect(() => {
199
- const handleUpdate = () => {
200
- if (layersWithPointerEventsDisabledCount > 0) {
201
- force({});
202
- }
203
- };
204
- document.addEventListener(CONTEXT_UPDATE, handleUpdate);
205
- return () => document.removeEventListener(CONTEXT_UPDATE, handleUpdate);
206
- }, []);
207
- return /* @__PURE__ */jsx(Comp, {
208
- ...layerProps,
209
- ref: composedRefs,
210
- ...(!asChild && {
211
- display: "contents"
212
- }),
213
- pointerEvents: isBodyPointerEventsDisabled ? isPointerEventsEnabled ? "auto" : "none" : void 0,
214
- onFocusCapture: composeEventHandlers(props.onFocusCapture, focusOutside.onFocusCapture),
215
- onBlurCapture: composeEventHandlers(props.onBlurCapture, focusOutside.onBlurCapture),
216
- onPointerDownCapture: composeEventHandlers(props.onPointerDownCapture, pointerDownOutside.onPointerDownCapture),
217
- children
218
- });
96
+ const Dismissable = createRefComponent((props, forwardedRef) => {
97
+ const { disableOutsidePointerEvents = false, forceUnmount, onEscapeKeyDown, onPointerDownOutside, onFocusOutside, onInteractOutside, onDismiss, asChild, children, branches: branchesProp, ...layerProps } = props;
98
+ const Comp = asChild ? Slot : View;
99
+ const context = React.useContext(DismissableContext);
100
+ const [node, setNode] = React.useState(null);
101
+ const [, force] = React.useState({});
102
+ const composedRefs = useComposedRefs(forwardedRef, (node2) => setNode(node2));
103
+ const layers = Array.from(context.layers);
104
+ const [highestLayerWithOutsidePointerEventsDisabled] = [...context.layersWithOutsidePointerEventsDisabled].slice(-1);
105
+ const highestLayerWithOutsidePointerEventsDisabledIndex = layers.indexOf(highestLayerWithOutsidePointerEventsDisabled);
106
+ const index = node ? layers.indexOf(node) : -1;
107
+ const isBodyPointerEventsDisabled = context.layersWithOutsidePointerEventsDisabled.size > 0;
108
+ const isPointerEventsEnabled = index >= highestLayerWithOutsidePointerEventsDisabledIndex;
109
+ const pointerDownOutside = usePointerDownOutside((event) => {
110
+ const target = event.target;
111
+ const branches = branchesProp || context.branches;
112
+ const isPointerDownOnBranch = [...branches].some((branch) => branch.contains(target));
113
+ if (!isPointerEventsEnabled || isPointerDownOnBranch) return;
114
+ const details = createChangeEventDetails("outside-press", event, event.target, { interaction: "pointer" });
115
+ onPointerDownOutside?.(details);
116
+ onInteractOutside?.(details);
117
+ if (!details.isCanceled) onDismiss?.(details);
118
+ });
119
+ const focusOutside = useFocusOutside((event) => {
120
+ const target = event.target;
121
+ const branches = branchesProp || context.branches;
122
+ const isFocusInBranch = [...branches].some((branch) => branch.contains(target));
123
+ if (isFocusInBranch) return;
124
+ if (node && target.contains(node)) return;
125
+ const details = createChangeEventDetails("focus-out", event, event.target, { interaction: "focus" });
126
+ onFocusOutside?.(details);
127
+ onInteractOutside?.(details);
128
+ if (!details.isCanceled) onDismiss?.(details);
129
+ });
130
+ const forceUnmountRef = React.useRef(forceUnmount);
131
+ React.useEffect(() => {
132
+ forceUnmountRef.current = forceUnmount;
133
+ }, [forceUnmount]);
134
+ useEscapeKeydown((event) => {
135
+ if (event.defaultPrevented) return;
136
+ if (forceUnmountRef.current) return;
137
+ const currentLayers = Array.from(context.layers);
138
+ const currentIndex = node ? currentLayers.indexOf(node) : -1;
139
+ const isHighestLayer = currentIndex === currentLayers.length - 1;
140
+ if (!isHighestLayer) return;
141
+ const details = createChangeEventDetails("escape-key", event, event.target);
142
+ onEscapeKeyDown?.(details);
143
+ if (!details.isCanceled && onDismiss) {
144
+ event.preventDefault();
145
+ onDismiss(details);
146
+ }
147
+ });
148
+ React.useEffect(() => {
149
+ if (!node) return;
150
+ if (forceUnmount) return;
151
+ context.layers.add(node);
152
+ globalLayers.add(node);
153
+ dispatchUpdate();
154
+ notifyLayerChange();
155
+ return () => {
156
+ context.layers.delete(node);
157
+ globalLayers.delete(node);
158
+ dispatchUpdate();
159
+ notifyLayerChange();
160
+ };
161
+ }, [
162
+ node,
163
+ forceUnmount,
164
+ context
165
+ ]);
166
+ React.useEffect(() => {
167
+ if (!node) return;
168
+ if (forceUnmount) return;
169
+ if (!disableOutsidePointerEvents) return;
170
+ if (context.layersWithOutsidePointerEventsDisabled.size === 0) {
171
+ originalBodyPointerEvents = document.body.style.pointerEvents;
172
+ document.body.style.pointerEvents = "none";
173
+ }
174
+ context.layersWithOutsidePointerEventsDisabled.add(node);
175
+ layersWithPointerEventsDisabledCount++;
176
+ dispatchUpdate();
177
+ notifyLayerChange();
178
+ return () => {
179
+ context.layersWithOutsidePointerEventsDisabled.delete(node);
180
+ if (context.layersWithOutsidePointerEventsDisabled.size === 0) {
181
+ document.body.style.pointerEvents = originalBodyPointerEvents;
182
+ }
183
+ dispatchUpdate();
184
+ notifyLayerChange();
185
+ layersWithPointerEventsDisabledCount--;
186
+ };
187
+ }, [
188
+ node,
189
+ disableOutsidePointerEvents,
190
+ forceUnmount,
191
+ context
192
+ ]);
193
+ React.useEffect(() => {
194
+ const handleUpdate = () => {
195
+ if (layersWithPointerEventsDisabledCount > 0) {
196
+ force({});
197
+ }
198
+ };
199
+ document.addEventListener(CONTEXT_UPDATE, handleUpdate);
200
+ return () => document.removeEventListener(CONTEXT_UPDATE, handleUpdate);
201
+ }, []);
202
+ return /* @__PURE__ */ jsx(Comp, {
203
+ ...layerProps,
204
+ ref: composedRefs,
205
+ ...!asChild && { display: "contents" },
206
+ pointerEvents: isBodyPointerEventsDisabled ? isPointerEventsEnabled ? "auto" : "none" : void 0,
207
+ onFocusCapture: composeEventHandlers(props.onFocusCapture, focusOutside.onFocusCapture),
208
+ onBlurCapture: composeEventHandlers(props.onBlurCapture, focusOutside.onBlurCapture),
209
+ onPointerDownCapture: composeEventHandlers(props.onPointerDownCapture, pointerDownOutside.onPointerDownCapture),
210
+ children
211
+ });
219
212
  });
220
213
  Dismissable.displayName = DISMISSABLE_LAYER_NAME;
221
214
  const BRANCH_NAME = "DismissableBranch";
222
- const DismissableBranch = React.forwardRef((props, forwardedRef) => {
223
- const {
224
- branches: branchesProp,
225
- ...rest
226
- } = props;
227
- const context = React.useContext(DismissableContext);
228
- const ref = React.useRef(null);
229
- const composedRefs = useComposedRefs(forwardedRef, ref);
230
- React.useEffect(() => {
231
- const node = ref.current;
232
- if (!(node instanceof HTMLElement)) return;
233
- const branches = branchesProp || context.branches;
234
- if (node && branches) {
235
- branches.add(node);
236
- return () => {
237
- branches.delete(node);
238
- };
239
- }
240
- }, [branchesProp, context.branches]);
241
- return /* @__PURE__ */jsx(View, {
242
- asChild: "except-style",
243
- ...rest,
244
- ref: composedRefs
245
- });
215
+ const DismissableBranch = createRefComponent((props, forwardedRef) => {
216
+ const { branches: branchesProp, ...rest } = props;
217
+ const context = React.useContext(DismissableContext);
218
+ const ref = React.useRef(null);
219
+ const composedRefs = useComposedRefs(forwardedRef, ref);
220
+ React.useEffect(() => {
221
+ const node = ref.current;
222
+ if (!(node instanceof HTMLElement)) return;
223
+ const branches = branchesProp || context.branches;
224
+ if (node && branches) {
225
+ branches.add(node);
226
+ return () => {
227
+ branches.delete(node);
228
+ };
229
+ }
230
+ }, [branchesProp, context.branches]);
231
+ return /* @__PURE__ */ jsx(View, {
232
+ asChild: "except-style",
233
+ ...rest,
234
+ ref: composedRefs
235
+ });
246
236
  });
247
237
  DismissableBranch.displayName = BRANCH_NAME;
248
238
  function usePointerDownOutside(onPointerDownOutside) {
249
- const handlePointerDownOutside = useEvent(onPointerDownOutside);
250
- const isPointerInsideReactTreeRef = React.useRef(false);
251
- const handleClickRef = React.useRef(() => {});
252
- React.useEffect(() => {
253
- const handlePointerDown = event => {
254
- if (event.target && !isPointerInsideReactTreeRef.current) {
255
- let handleAndDispatchPointerDownOutsideEvent = function () {
256
- handleAndDispatchCustomEvent(POINTER_DOWN_OUTSIDE, handlePointerDownOutside, eventDetail, {
257
- discrete: true
258
- });
259
- };
260
- const eventDetail = {
261
- originalEvent: event
262
- };
263
- if (event.pointerType === "touch") {
264
- document.removeEventListener("click", handleClickRef.current);
265
- handleClickRef.current = handleAndDispatchPointerDownOutsideEvent;
266
- document.addEventListener("click", handleClickRef.current, {
267
- once: true
268
- });
269
- } else {
270
- handleAndDispatchPointerDownOutsideEvent();
271
- }
272
- }
273
- isPointerInsideReactTreeRef.current = false;
274
- };
275
- const timerId = setTimeout(() => {
276
- document.addEventListener("pointerdown", handlePointerDown);
277
- }, 0);
278
- return () => {
279
- window.clearTimeout(timerId);
280
- document.removeEventListener("pointerdown", handlePointerDown);
281
- document.removeEventListener("click", handleClickRef.current);
282
- };
283
- }, [handlePointerDownOutside]);
284
- return {
285
- // ensures we check React component tree (not just DOM tree)
286
- onPointerDownCapture: () => {
287
- isPointerInsideReactTreeRef.current = true;
288
- }
289
- };
239
+ const handlePointerDownOutside = useEvent(onPointerDownOutside);
240
+ const isPointerInsideReactTreeRef = React.useRef(false);
241
+ const handleClickRef = React.useRef(() => {});
242
+ React.useEffect(() => {
243
+ const handlePointerDown = (event) => {
244
+ if (event.target && !isPointerInsideReactTreeRef.current) {
245
+ let handlePointerDownOutsideEvent = function() {
246
+ if (handlePointerDownOutside) {
247
+ ReactDOM.flushSync(() => handlePointerDownOutside(event));
248
+ }
249
+ };
250
+ if (event.pointerType === "touch") {
251
+ document.removeEventListener("click", handleClickRef.current);
252
+ handleClickRef.current = handlePointerDownOutsideEvent;
253
+ document.addEventListener("click", handleClickRef.current, { once: true });
254
+ } else {
255
+ handlePointerDownOutsideEvent();
256
+ }
257
+ }
258
+ isPointerInsideReactTreeRef.current = false;
259
+ };
260
+ const timerId = setTimeout(() => {
261
+ document.addEventListener("pointerdown", handlePointerDown);
262
+ }, 0);
263
+ return () => {
264
+ window.clearTimeout(timerId);
265
+ document.removeEventListener("pointerdown", handlePointerDown);
266
+ document.removeEventListener("click", handleClickRef.current);
267
+ };
268
+ }, [handlePointerDownOutside]);
269
+ return { onPointerDownCapture: () => {
270
+ isPointerInsideReactTreeRef.current = true;
271
+ } };
290
272
  }
291
273
  function useFocusOutside(onFocusOutside) {
292
- const handleFocusOutside = useEvent(onFocusOutside);
293
- const isFocusInsideReactTreeRef = React.useRef(false);
294
- React.useEffect(() => {
295
- const handleFocus = event => {
296
- if (event.target && !isFocusInsideReactTreeRef.current) {
297
- const eventDetail = {
298
- originalEvent: event
299
- };
300
- handleAndDispatchCustomEvent(FOCUS_OUTSIDE, handleFocusOutside, eventDetail, {
301
- discrete: false
302
- });
303
- }
304
- };
305
- document.addEventListener("focusin", handleFocus);
306
- return () => document.removeEventListener("focusin", handleFocus);
307
- }, [handleFocusOutside]);
308
- return {
309
- onFocusCapture: () => {
310
- isFocusInsideReactTreeRef.current = true;
311
- },
312
- onBlurCapture: () => {
313
- isFocusInsideReactTreeRef.current = false;
314
- }
315
- };
274
+ const handleFocusOutside = useEvent(onFocusOutside);
275
+ const isFocusInsideReactTreeRef = React.useRef(false);
276
+ React.useEffect(() => {
277
+ const handleFocus = (event) => {
278
+ if (event.target && !isFocusInsideReactTreeRef.current) {
279
+ handleFocusOutside?.(event);
280
+ }
281
+ };
282
+ document.addEventListener("focusin", handleFocus);
283
+ return () => document.removeEventListener("focusin", handleFocus);
284
+ }, [handleFocusOutside]);
285
+ return {
286
+ onFocusCapture: () => {
287
+ isFocusInsideReactTreeRef.current = true;
288
+ },
289
+ onBlurCapture: () => {
290
+ isFocusInsideReactTreeRef.current = false;
291
+ }
292
+ };
316
293
  }
317
294
  function dispatchUpdate() {
318
- const event = new CustomEvent(CONTEXT_UPDATE);
319
- document.dispatchEvent(event);
320
- }
321
- function handleAndDispatchCustomEvent(name, handler, detail, {
322
- discrete
323
- }) {
324
- const target = detail.originalEvent.target;
325
- const event = new CustomEvent(name, {
326
- bubbles: false,
327
- cancelable: true,
328
- detail
329
- });
330
- if (handler) target.addEventListener(name, handler, {
331
- once: true
332
- });
333
- if (discrete) {
334
- dispatchDiscreteCustomEvent(target, event);
335
- } else {
336
- target.dispatchEvent(event);
337
- }
295
+ const event = new CustomEvent(CONTEXT_UPDATE);
296
+ document.dispatchEvent(event);
338
297
  }
298
+
339
299
  export { Dismissable, DismissableBranch, debugDismissableLayers, dispatchDiscreteCustomEvent, getDismissableLayerCount, useDismissableLayersAbove, useHasDismissableLayers, useIsInsideDismissable };
340
300
  //# sourceMappingURL=Dismissable.mjs.map