@seed-design/react-dismissible-layer 0.0.0-alpha-20260414104312

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.
@@ -0,0 +1,202 @@
1
+ 'use client';
2
+ import { useRef, useEffect } from 'react';
3
+ import { i as isTopMost, c as isBelowPointerBlockingLayer, a as isInBranch, b as isInNestedLayer } from './layer-stack-12s-DjRVp1_u.js';
4
+
5
+ /**
6
+ * Detects pointer-down events outside a React subtree.
7
+ * Uses `onPointerDownCapture` on the element to distinguish React-tree-inside
8
+ * from DOM-tree-inside (Portal support).
9
+ *
10
+ * Ported from Radix's usePointerDownOutside with layer stack integration.
11
+ */ function usePointerDownOutside(node, ctx, options) {
12
+ const callbackRef = useRef(options.onPressOutside);
13
+ callbackRef.current = options.onPressOutside;
14
+ const excludeRef = useRef(options.exclude);
15
+ excludeRef.current = options.exclude;
16
+ const pressBehaviorRef = useRef(options.pressBehavior);
17
+ pressBehaviorRef.current = options.pressBehavior;
18
+ const isPointerInsideReactTreeRef = useRef(false);
19
+ const handleClickRef = useRef(()=>{});
20
+ // Touch drag state (only used in "drag" mode)
21
+ const touchStateRef = useRef(null);
22
+ const suppressPointerRef = useRef(false);
23
+ const suppressTimerRef = useRef();
24
+ useEffect(()=>{
25
+ if (!node || !options.enabled) return;
26
+ const ownerDocument = node.ownerDocument ?? document;
27
+ function isOutsideLayer(target) {
28
+ if (!isTopMost(ctx, node)) return false;
29
+ if (isBelowPointerBlockingLayer(ctx, node)) return false;
30
+ if (isInBranch(ctx, target)) return false;
31
+ if (isInNestedLayer(ctx, node, target)) return false;
32
+ return true;
33
+ }
34
+ function isOutsideTarget(target) {
35
+ if (!isOutsideLayer(target)) return false;
36
+ if (excludeRef.current?.(target)) return false;
37
+ return true;
38
+ }
39
+ function deferToClick(handleAndDispatch) {
40
+ ownerDocument.removeEventListener("click", handleClickRef.current);
41
+ handleClickRef.current = handleAndDispatch;
42
+ ownerDocument.addEventListener("click", handleClickRef.current, {
43
+ once: true
44
+ });
45
+ }
46
+ const handlePointerDown = (event)=>{
47
+ const target = event.target;
48
+ if (target && !isPointerInsideReactTreeRef.current) {
49
+ if (!isOutsideTarget(target)) {
50
+ isPointerInsideReactTreeRef.current = false;
51
+ return;
52
+ }
53
+ // In drag mode, suppress synthetic pointerdown that follows a touch dismiss.
54
+ if (pressBehaviorRef.current === "drag" && suppressPointerRef.current) {
55
+ isPointerInsideReactTreeRef.current = false;
56
+ return;
57
+ }
58
+ function handleAndDispatch() {
59
+ callbackRef.current(event);
60
+ }
61
+ const behavior = pressBehaviorRef.current ?? "confirm";
62
+ if (behavior === "confirm") {
63
+ // Both mouse and touch defer to click
64
+ deferToClick(handleAndDispatch);
65
+ } else if (behavior === "drag") {
66
+ // Touch is handled by touchstart/move/end listeners.
67
+ // Only process non-touch pointerdown (mouse, pen).
68
+ if (event.pointerType === "touch") {
69
+ isPointerInsideReactTreeRef.current = false;
70
+ return;
71
+ }
72
+ handleAndDispatch();
73
+ } else {
74
+ // "eager" (default): mouse immediate, touch defers to click
75
+ if (event.pointerType === "touch") {
76
+ deferToClick(handleAndDispatch);
77
+ } else {
78
+ handleAndDispatch();
79
+ }
80
+ }
81
+ } else {
82
+ ownerDocument.removeEventListener("click", handleClickRef.current);
83
+ }
84
+ isPointerInsideReactTreeRef.current = false;
85
+ };
86
+ // -- Touch drag handlers (only active in "drag" mode) --
87
+ const isTouchInsideReactTreeRef = {
88
+ current: false
89
+ };
90
+ const handleTouchStartCapture = ()=>{
91
+ isTouchInsideReactTreeRef.current = true;
92
+ };
93
+ const handleTouchStart = (event)=>{
94
+ if (pressBehaviorRef.current !== "drag") return;
95
+ if (isTouchInsideReactTreeRef.current) {
96
+ isTouchInsideReactTreeRef.current = false;
97
+ return;
98
+ }
99
+ const target = event.target;
100
+ if (!target || !isOutsideLayer(target)) return;
101
+ const touch = event.touches[0];
102
+ if (!touch) return;
103
+ const startedOnExcluded = !!excludeRef.current?.(target);
104
+ touchStateRef.current = {
105
+ startX: touch.clientX,
106
+ startY: touch.clientY,
107
+ dismissOnTouchEnd: false,
108
+ startedOnExcluded
109
+ };
110
+ // Activate click-through guard
111
+ suppressPointerRef.current = true;
112
+ clearTimeout(suppressTimerRef.current);
113
+ suppressTimerRef.current = setTimeout(()=>{
114
+ suppressPointerRef.current = false;
115
+ if (touchStateRef.current) {
116
+ touchStateRef.current.dismissOnTouchEnd = false;
117
+ }
118
+ }, 1000);
119
+ };
120
+ const handleTouchMove = (event)=>{
121
+ if (pressBehaviorRef.current !== "drag" || !touchStateRef.current) return;
122
+ const target = event.target;
123
+ if (target && node.contains(target)) return;
124
+ const touch = event.touches[0];
125
+ if (!touch) return;
126
+ const deltaX = Math.abs(touch.clientX - touchStateRef.current.startX);
127
+ const deltaY = Math.abs(touch.clientY - touchStateRef.current.startY);
128
+ const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
129
+ if (distance > 5) {
130
+ touchStateRef.current.dismissOnTouchEnd = true;
131
+ }
132
+ if (distance > 10) {
133
+ callbackRef.current(event);
134
+ clearTimeout(suppressTimerRef.current);
135
+ suppressTimerRef.current = setTimeout(()=>{
136
+ suppressPointerRef.current = false;
137
+ }, 1000);
138
+ touchStateRef.current = null;
139
+ }
140
+ };
141
+ const handleTouchEnd = ()=>{
142
+ if (pressBehaviorRef.current !== "drag" || !touchStateRef.current) return;
143
+ if (touchStateRef.current.dismissOnTouchEnd) {
144
+ // Drag detected (>5px): dismiss immediately
145
+ callbackRef.current(new PointerEvent("pointerdown"));
146
+ clearTimeout(suppressTimerRef.current);
147
+ suppressTimerRef.current = setTimeout(()=>{
148
+ suppressPointerRef.current = false;
149
+ }, 1000);
150
+ } else if (!touchStateRef.current.startedOnExcluded) {
151
+ // Tap (no significant movement): defer to click, like "confirm" mode.
152
+ // Skip if tap started on an excluded target (e.g., trigger) — toggle handles it.
153
+ suppressPointerRef.current = false;
154
+ clearTimeout(suppressTimerRef.current);
155
+ deferToClick(()=>callbackRef.current(new PointerEvent("pointerdown")));
156
+ } else {
157
+ // Tap on excluded target — clean up guard without dismissing
158
+ suppressPointerRef.current = false;
159
+ clearTimeout(suppressTimerRef.current);
160
+ }
161
+ touchStateRef.current = null;
162
+ };
163
+ // Delay registration to prevent the mount-triggering pointerdown from
164
+ // being detected as "outside". This is a DOM behavior, not React-specific.
165
+ const timerId = window.setTimeout(()=>{
166
+ ownerDocument.addEventListener("pointerdown", handlePointerDown);
167
+ if (pressBehaviorRef.current === "drag") {
168
+ ownerDocument.addEventListener("touchstart", handleTouchStart);
169
+ ownerDocument.addEventListener("touchmove", handleTouchMove);
170
+ ownerDocument.addEventListener("touchend", handleTouchEnd);
171
+ }
172
+ }, 0);
173
+ // Register capture handler on node for React tree detection
174
+ if (pressBehaviorRef.current === "drag") {
175
+ node.addEventListener("touchstart", handleTouchStartCapture, true);
176
+ }
177
+ return ()=>{
178
+ window.clearTimeout(timerId);
179
+ clearTimeout(suppressTimerRef.current);
180
+ ownerDocument.removeEventListener("pointerdown", handlePointerDown);
181
+ ownerDocument.removeEventListener("click", handleClickRef.current);
182
+ ownerDocument.removeEventListener("touchstart", handleTouchStart);
183
+ ownerDocument.removeEventListener("touchmove", handleTouchMove);
184
+ ownerDocument.removeEventListener("touchend", handleTouchEnd);
185
+ node?.removeEventListener("touchstart", handleTouchStartCapture, true);
186
+ touchStateRef.current = null;
187
+ suppressPointerRef.current = false;
188
+ };
189
+ }, [
190
+ node,
191
+ ctx,
192
+ options.enabled
193
+ ]);
194
+ return {
195
+ // React synthetic event — fires for React-tree descendants (including Portals).
196
+ onPointerDownCapture: ()=>{
197
+ isPointerInsideReactTreeRef.current = true;
198
+ }
199
+ };
200
+ }
201
+
202
+ export { usePointerDownOutside as u };
@@ -0,0 +1,202 @@
1
+ 'use client';
2
+ var react = require('react');
3
+ var layerStack12s = require('./layer-stack-12s-Ctg3ipjW.cjs');
4
+
5
+ /**
6
+ * Detects pointer-down events outside a React subtree.
7
+ * Uses `onPointerDownCapture` on the element to distinguish React-tree-inside
8
+ * from DOM-tree-inside (Portal support).
9
+ *
10
+ * Ported from Radix's usePointerDownOutside with layer stack integration.
11
+ */ function usePointerDownOutside(node, ctx, options) {
12
+ const callbackRef = react.useRef(options.onPressOutside);
13
+ callbackRef.current = options.onPressOutside;
14
+ const excludeRef = react.useRef(options.exclude);
15
+ excludeRef.current = options.exclude;
16
+ const pressBehaviorRef = react.useRef(options.pressBehavior);
17
+ pressBehaviorRef.current = options.pressBehavior;
18
+ const isPointerInsideReactTreeRef = react.useRef(false);
19
+ const handleClickRef = react.useRef(()=>{});
20
+ // Touch drag state (only used in "drag" mode)
21
+ const touchStateRef = react.useRef(null);
22
+ const suppressPointerRef = react.useRef(false);
23
+ const suppressTimerRef = react.useRef();
24
+ react.useEffect(()=>{
25
+ if (!node || !options.enabled) return;
26
+ const ownerDocument = node.ownerDocument ?? document;
27
+ function isOutsideLayer(target) {
28
+ if (!layerStack12s.isTopMost(ctx, node)) return false;
29
+ if (layerStack12s.isBelowPointerBlockingLayer(ctx, node)) return false;
30
+ if (layerStack12s.isInBranch(ctx, target)) return false;
31
+ if (layerStack12s.isInNestedLayer(ctx, node, target)) return false;
32
+ return true;
33
+ }
34
+ function isOutsideTarget(target) {
35
+ if (!isOutsideLayer(target)) return false;
36
+ if (excludeRef.current?.(target)) return false;
37
+ return true;
38
+ }
39
+ function deferToClick(handleAndDispatch) {
40
+ ownerDocument.removeEventListener("click", handleClickRef.current);
41
+ handleClickRef.current = handleAndDispatch;
42
+ ownerDocument.addEventListener("click", handleClickRef.current, {
43
+ once: true
44
+ });
45
+ }
46
+ const handlePointerDown = (event)=>{
47
+ const target = event.target;
48
+ if (target && !isPointerInsideReactTreeRef.current) {
49
+ if (!isOutsideTarget(target)) {
50
+ isPointerInsideReactTreeRef.current = false;
51
+ return;
52
+ }
53
+ // In drag mode, suppress synthetic pointerdown that follows a touch dismiss.
54
+ if (pressBehaviorRef.current === "drag" && suppressPointerRef.current) {
55
+ isPointerInsideReactTreeRef.current = false;
56
+ return;
57
+ }
58
+ function handleAndDispatch() {
59
+ callbackRef.current(event);
60
+ }
61
+ const behavior = pressBehaviorRef.current ?? "confirm";
62
+ if (behavior === "confirm") {
63
+ // Both mouse and touch defer to click
64
+ deferToClick(handleAndDispatch);
65
+ } else if (behavior === "drag") {
66
+ // Touch is handled by touchstart/move/end listeners.
67
+ // Only process non-touch pointerdown (mouse, pen).
68
+ if (event.pointerType === "touch") {
69
+ isPointerInsideReactTreeRef.current = false;
70
+ return;
71
+ }
72
+ handleAndDispatch();
73
+ } else {
74
+ // "eager" (default): mouse immediate, touch defers to click
75
+ if (event.pointerType === "touch") {
76
+ deferToClick(handleAndDispatch);
77
+ } else {
78
+ handleAndDispatch();
79
+ }
80
+ }
81
+ } else {
82
+ ownerDocument.removeEventListener("click", handleClickRef.current);
83
+ }
84
+ isPointerInsideReactTreeRef.current = false;
85
+ };
86
+ // -- Touch drag handlers (only active in "drag" mode) --
87
+ const isTouchInsideReactTreeRef = {
88
+ current: false
89
+ };
90
+ const handleTouchStartCapture = ()=>{
91
+ isTouchInsideReactTreeRef.current = true;
92
+ };
93
+ const handleTouchStart = (event)=>{
94
+ if (pressBehaviorRef.current !== "drag") return;
95
+ if (isTouchInsideReactTreeRef.current) {
96
+ isTouchInsideReactTreeRef.current = false;
97
+ return;
98
+ }
99
+ const target = event.target;
100
+ if (!target || !isOutsideLayer(target)) return;
101
+ const touch = event.touches[0];
102
+ if (!touch) return;
103
+ const startedOnExcluded = !!excludeRef.current?.(target);
104
+ touchStateRef.current = {
105
+ startX: touch.clientX,
106
+ startY: touch.clientY,
107
+ dismissOnTouchEnd: false,
108
+ startedOnExcluded
109
+ };
110
+ // Activate click-through guard
111
+ suppressPointerRef.current = true;
112
+ clearTimeout(suppressTimerRef.current);
113
+ suppressTimerRef.current = setTimeout(()=>{
114
+ suppressPointerRef.current = false;
115
+ if (touchStateRef.current) {
116
+ touchStateRef.current.dismissOnTouchEnd = false;
117
+ }
118
+ }, 1000);
119
+ };
120
+ const handleTouchMove = (event)=>{
121
+ if (pressBehaviorRef.current !== "drag" || !touchStateRef.current) return;
122
+ const target = event.target;
123
+ if (target && node.contains(target)) return;
124
+ const touch = event.touches[0];
125
+ if (!touch) return;
126
+ const deltaX = Math.abs(touch.clientX - touchStateRef.current.startX);
127
+ const deltaY = Math.abs(touch.clientY - touchStateRef.current.startY);
128
+ const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
129
+ if (distance > 5) {
130
+ touchStateRef.current.dismissOnTouchEnd = true;
131
+ }
132
+ if (distance > 10) {
133
+ callbackRef.current(event);
134
+ clearTimeout(suppressTimerRef.current);
135
+ suppressTimerRef.current = setTimeout(()=>{
136
+ suppressPointerRef.current = false;
137
+ }, 1000);
138
+ touchStateRef.current = null;
139
+ }
140
+ };
141
+ const handleTouchEnd = ()=>{
142
+ if (pressBehaviorRef.current !== "drag" || !touchStateRef.current) return;
143
+ if (touchStateRef.current.dismissOnTouchEnd) {
144
+ // Drag detected (>5px): dismiss immediately
145
+ callbackRef.current(new PointerEvent("pointerdown"));
146
+ clearTimeout(suppressTimerRef.current);
147
+ suppressTimerRef.current = setTimeout(()=>{
148
+ suppressPointerRef.current = false;
149
+ }, 1000);
150
+ } else if (!touchStateRef.current.startedOnExcluded) {
151
+ // Tap (no significant movement): defer to click, like "confirm" mode.
152
+ // Skip if tap started on an excluded target (e.g., trigger) — toggle handles it.
153
+ suppressPointerRef.current = false;
154
+ clearTimeout(suppressTimerRef.current);
155
+ deferToClick(()=>callbackRef.current(new PointerEvent("pointerdown")));
156
+ } else {
157
+ // Tap on excluded target — clean up guard without dismissing
158
+ suppressPointerRef.current = false;
159
+ clearTimeout(suppressTimerRef.current);
160
+ }
161
+ touchStateRef.current = null;
162
+ };
163
+ // Delay registration to prevent the mount-triggering pointerdown from
164
+ // being detected as "outside". This is a DOM behavior, not React-specific.
165
+ const timerId = window.setTimeout(()=>{
166
+ ownerDocument.addEventListener("pointerdown", handlePointerDown);
167
+ if (pressBehaviorRef.current === "drag") {
168
+ ownerDocument.addEventListener("touchstart", handleTouchStart);
169
+ ownerDocument.addEventListener("touchmove", handleTouchMove);
170
+ ownerDocument.addEventListener("touchend", handleTouchEnd);
171
+ }
172
+ }, 0);
173
+ // Register capture handler on node for React tree detection
174
+ if (pressBehaviorRef.current === "drag") {
175
+ node.addEventListener("touchstart", handleTouchStartCapture, true);
176
+ }
177
+ return ()=>{
178
+ window.clearTimeout(timerId);
179
+ clearTimeout(suppressTimerRef.current);
180
+ ownerDocument.removeEventListener("pointerdown", handlePointerDown);
181
+ ownerDocument.removeEventListener("click", handleClickRef.current);
182
+ ownerDocument.removeEventListener("touchstart", handleTouchStart);
183
+ ownerDocument.removeEventListener("touchmove", handleTouchMove);
184
+ ownerDocument.removeEventListener("touchend", handleTouchEnd);
185
+ node?.removeEventListener("touchstart", handleTouchStartCapture, true);
186
+ touchStateRef.current = null;
187
+ suppressPointerRef.current = false;
188
+ };
189
+ }, [
190
+ node,
191
+ ctx,
192
+ options.enabled
193
+ ]);
194
+ return {
195
+ // React synthetic event — fires for React-tree descendants (including Portals).
196
+ onPointerDownCapture: ()=>{
197
+ isPointerInsideReactTreeRef.current = true;
198
+ }
199
+ };
200
+ }
201
+
202
+ exports.usePointerDownOutside = usePointerDownOutside;
@@ -0,0 +1,146 @@
1
+ 'use client';
2
+ import { useState, useCallback, useRef, useEffect } from 'react';
3
+ import { u as useLayerStackContext, d as useDismissibleParentNode, e as addLayer, r as removeLayer, L as LAYER_UPDATE_EVENT, g as getPointerEventsEnabled, i as isTopMost } from './layer-stack-12s-DjRVp1_u.js';
4
+ import { u as useEscapeKeydown } from './use-escape-keydown-12s-Bl_her-_.js';
5
+ import { u as usePointerDownOutside } from './use-pointer-down-outside-12s-BLctGw0m.js';
6
+ import { u as useFocusOutside } from './use-focus-outside-12s-LpFt7UjO.js';
7
+
8
+ const NOOP = ()=>{};
9
+ // Module-level storage for the original body pointer-events value.
10
+ // Follows Radix's pattern: save once when the first blocking layer mounts,
11
+ // restore when the last blocking layer unmounts. This decouples save/restore
12
+ // from React's bottom-up cleanup order.
13
+ let originalBodyPointerEvents;
14
+ function useDismissibleLayer(options) {
15
+ const { enabled, blockPointerEvents = false, onEscapeKeyDown, onPressOutside, onFocusOutside, onCascadeDismiss, exclude, pressBehavior } = options;
16
+ const ctx = useLayerStackContext();
17
+ const parentNode = useDismissibleParentNode();
18
+ const [node, setNode] = useState(null);
19
+ const [, forceRender] = useState({});
20
+ // Callback ref — fires when element mounts/unmounts.
21
+ // Drives `node` state which triggers registration and event listener setup.
22
+ const dismissibleRef = useCallback((el)=>{
23
+ setNode(el);
24
+ }, []);
25
+ // Stable callback refs
26
+ const onCascadeDismissRef = useRef(onCascadeDismiss);
27
+ onCascadeDismissRef.current = onCascadeDismiss;
28
+ const onEscapeKeyDownRef = useRef(onEscapeKeyDown);
29
+ onEscapeKeyDownRef.current = onEscapeKeyDown;
30
+ // -- Layer registration --
31
+ useEffect(()=>{
32
+ if (!node || !enabled) return;
33
+ const layer = {
34
+ node,
35
+ dismiss: (detail)=>onCascadeDismissRef.current?.(detail),
36
+ blockPointerEvents,
37
+ parentNode
38
+ };
39
+ addLayer(ctx, layer);
40
+ return ()=>{
41
+ removeLayer(ctx, node);
42
+ };
43
+ }, [
44
+ node,
45
+ enabled,
46
+ blockPointerEvents,
47
+ ctx,
48
+ parentNode
49
+ ]);
50
+ // -- Pointer event blocking --
51
+ // Follows Radix's pattern: save original value once when the first blocking
52
+ // layer mounts, restore when the last unmounts. The module-level variable
53
+ // decouples save/restore from React's bottom-up cleanup order.
54
+ useEffect(()=>{
55
+ if (!node || !enabled || !blockPointerEvents) return;
56
+ const ownerDocument = node.ownerDocument ?? document;
57
+ const blockingLayers = ctx.layers.filter((l)=>l.blockPointerEvents);
58
+ if (blockingLayers.length === 1) {
59
+ // First blocking layer — save the original value and block
60
+ originalBodyPointerEvents = ownerDocument.body.style.pointerEvents;
61
+ ownerDocument.body.style.pointerEvents = "none";
62
+ }
63
+ return ()=>{
64
+ // Check count BEFORE this layer is removed from ctx.layers.
65
+ // At cleanup time, this layer is still in the array.
66
+ const remainingBlocking = ctx.layers.filter((l)=>l.blockPointerEvents && l.node !== node);
67
+ if (remainingBlocking.length === 0) {
68
+ ownerDocument.body.style.pointerEvents = originalBodyPointerEvents;
69
+ }
70
+ };
71
+ }, [
72
+ node,
73
+ enabled,
74
+ blockPointerEvents,
75
+ ctx
76
+ ]);
77
+ // -- Subscribe to layer changes for style updates --
78
+ useEffect(()=>{
79
+ if (!enabled) return;
80
+ const handler = ()=>forceRender({});
81
+ document.addEventListener(LAYER_UPDATE_EVENT, handler);
82
+ return ()=>document.removeEventListener(LAYER_UPDATE_EVENT, handler);
83
+ }, [
84
+ enabled
85
+ ]);
86
+ // -- Escape keydown --
87
+ const handleEscapeKeyDown = useCallback((event)=>{
88
+ onEscapeKeyDownRef.current?.(event);
89
+ }, []);
90
+ useEscapeKeydown(enabled ? node : null, ctx, handleEscapeKeyDown);
91
+ // -- Press outside --
92
+ const handlePressOutside = useCallback((event)=>{
93
+ onPressOutside(event);
94
+ }, [
95
+ onPressOutside
96
+ ]);
97
+ const pressOutsideProps = usePointerDownOutside(enabled ? node : null, ctx, {
98
+ enabled,
99
+ exclude,
100
+ onPressOutside: handlePressOutside,
101
+ pressBehavior
102
+ });
103
+ // -- Focus outside --
104
+ const handleFocusOutside = useCallback((event)=>{
105
+ onFocusOutside(event);
106
+ }, [
107
+ onFocusOutside
108
+ ]);
109
+ const focusOutsideProps = useFocusOutside(enabled ? node : null, ctx, {
110
+ enabled,
111
+ exclude,
112
+ onFocusOutside: handleFocusOutside
113
+ });
114
+ // -- Compute pointer-events style --
115
+ const hasBlocking = ctx.layers.some((l)=>l.blockPointerEvents);
116
+ const pointerEventsEnabled = node ? getPointerEventsEnabled(ctx, node) : true;
117
+ const style = hasBlocking ? {
118
+ pointerEvents: pointerEventsEnabled ? "auto" : "none"
119
+ } : {};
120
+ const topLayer = node ? isTopMost(ctx, node) : true;
121
+ if (!enabled) {
122
+ return {
123
+ dismissibleRef,
124
+ dismissibleProps: {
125
+ onPointerDownCapture: NOOP,
126
+ onFocusCapture: NOOP,
127
+ onBlurCapture: NOOP
128
+ },
129
+ isTopLayer: true,
130
+ /** The current layer node, for providing DismissibleParentContext to children. */ layerNode: node
131
+ };
132
+ }
133
+ return {
134
+ dismissibleRef,
135
+ dismissibleProps: {
136
+ onPointerDownCapture: pressOutsideProps.onPointerDownCapture,
137
+ onFocusCapture: focusOutsideProps.onFocusCapture,
138
+ onBlurCapture: focusOutsideProps.onBlurCapture,
139
+ style
140
+ },
141
+ isTopLayer: topLayer,
142
+ /** The current layer node, for providing DismissibleParentContext to children. */ layerNode: node
143
+ };
144
+ }
145
+
146
+ export { useDismissibleLayer as u };