@johly/vaul-svelte 1.0.0-next.11 → 1.0.0-next.13
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.
- package/dist/components/drawer/drawer.svelte +47 -16
- package/dist/components/drawer/drawer.svelte.d.ts +1 -7
- package/dist/drawer-registry.d.ts +15 -0
- package/dist/drawer-registry.js +32 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/use-drawer-content.svelte.js +8 -0
- package/package.json +1 -1
|
@@ -6,11 +6,14 @@
|
|
|
6
6
|
import { CLOSE_THRESHOLD, SCROLL_LOCK_TIMEOUT } from "../../internal/constants.js";
|
|
7
7
|
import { useDrawerRoot } from "../../use-drawer-root.svelte.js";
|
|
8
8
|
import type { ParentDrawerState } from "../../types.js";
|
|
9
|
+
import {
|
|
10
|
+
registerDrawer,
|
|
11
|
+
unregisterDrawer,
|
|
12
|
+
getCurrentParentDrawer,
|
|
13
|
+
} from "../../drawer-registry.js";
|
|
9
14
|
|
|
10
15
|
let {
|
|
11
16
|
open = $bindable(false),
|
|
12
|
-
drawerState = $bindable(),
|
|
13
|
-
parentDrawer,
|
|
14
17
|
onOpenChange = noop,
|
|
15
18
|
onDrag: onDragProp = noop,
|
|
16
19
|
onRelease: onReleaseProp = noop,
|
|
@@ -38,35 +41,47 @@
|
|
|
38
41
|
autoFocus = false,
|
|
39
42
|
disablePreventScroll = true,
|
|
40
43
|
...restProps
|
|
41
|
-
}: RootProps
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
}: RootProps = $props();
|
|
45
|
+
|
|
46
|
+
// Track the auto-detected parent drawer
|
|
47
|
+
// If drawer starts open, try to auto-detect immediately
|
|
48
|
+
const initialParent = open && !nested ? getCurrentParentDrawer() : undefined;
|
|
49
|
+
let resolvedParentDrawer = $state<ParentDrawerState | undefined>(initialParent);
|
|
50
|
+
|
|
51
|
+
// Auto-detect parent when opening (for drawers that open after mount)
|
|
52
|
+
let wasOpen = open;
|
|
53
|
+
$effect.pre(() => {
|
|
54
|
+
// Detect parent on open transition (false -> true)
|
|
55
|
+
if (open && !wasOpen && !nested) {
|
|
56
|
+
resolvedParentDrawer = getCurrentParentDrawer();
|
|
57
|
+
}
|
|
58
|
+
wasOpen = open;
|
|
59
|
+
});
|
|
45
60
|
|
|
46
|
-
// When parentDrawer is provided, this drawer behaves as nested
|
|
47
|
-
const isNestedViaParent = $derived(!!
|
|
61
|
+
// When parentDrawer is provided or auto-detected, this drawer behaves as nested
|
|
62
|
+
const isNestedViaParent = $derived(!!resolvedParentDrawer);
|
|
48
63
|
const effectiveNested = $derived(nested || isNestedViaParent);
|
|
49
64
|
|
|
50
65
|
// Wrap onDrag to also notify parent drawer
|
|
51
66
|
function onDrag(event: PointerEvent, percentageDragged: number) {
|
|
52
67
|
onDragProp(event, percentageDragged);
|
|
53
|
-
if (
|
|
54
|
-
|
|
68
|
+
if (resolvedParentDrawer) {
|
|
69
|
+
resolvedParentDrawer.onNestedDrag(event, percentageDragged);
|
|
55
70
|
}
|
|
56
71
|
}
|
|
57
72
|
|
|
58
73
|
// Wrap onRelease to also notify parent drawer
|
|
59
74
|
function onRelease(event: PointerEvent, isOpen: boolean) {
|
|
60
75
|
onReleaseProp(event, isOpen);
|
|
61
|
-
if (
|
|
62
|
-
|
|
76
|
+
if (resolvedParentDrawer) {
|
|
77
|
+
resolvedParentDrawer.onNestedRelease(event, isOpen);
|
|
63
78
|
}
|
|
64
79
|
}
|
|
65
80
|
|
|
66
81
|
// Watch open state to notify parent drawer
|
|
67
82
|
$effect(() => {
|
|
68
|
-
if (
|
|
69
|
-
|
|
83
|
+
if (resolvedParentDrawer) {
|
|
84
|
+
resolvedParentDrawer.onNestedOpenChange(open);
|
|
70
85
|
}
|
|
71
86
|
});
|
|
72
87
|
|
|
@@ -111,9 +126,25 @@
|
|
|
111
126
|
onAnimationEnd: box.with(() => onAnimationEnd),
|
|
112
127
|
});
|
|
113
128
|
|
|
114
|
-
//
|
|
129
|
+
// Get stable reference to drawer state for registry
|
|
130
|
+
const stableDrawerState = rootState.parentDrawerState;
|
|
131
|
+
|
|
132
|
+
// Register/unregister with global drawer registry
|
|
133
|
+
$effect(() => {
|
|
134
|
+
if (open) {
|
|
135
|
+
registerDrawer(stableDrawerState);
|
|
136
|
+
return () => unregisterDrawer(stableDrawerState);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Clear auto-detected parent after drawer closes (separate effect to avoid loops)
|
|
115
141
|
$effect(() => {
|
|
116
|
-
|
|
142
|
+
if (!open && resolvedParentDrawer) {
|
|
143
|
+
// Use queueMicrotask to avoid triggering other effects synchronously
|
|
144
|
+
queueMicrotask(() => {
|
|
145
|
+
resolvedParentDrawer = undefined;
|
|
146
|
+
});
|
|
147
|
+
}
|
|
117
148
|
});
|
|
118
149
|
</script>
|
|
119
150
|
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
import type { ParentDrawerState } from "../../types.js";
|
|
3
|
-
type $$ComponentProps = RootProps & {
|
|
4
|
-
drawerState?: ParentDrawerState;
|
|
5
|
-
parentDrawer?: ParentDrawerState;
|
|
6
|
-
};
|
|
7
|
-
declare const Drawer: import("svelte").Component<$$ComponentProps, {}, "open" | "activeSnapPoint" | "drawerState">;
|
|
1
|
+
declare const Drawer: import("svelte").Component<import("../../types.js").DrawerRootPropsWithoutHTML, {}, "open" | "activeSnapPoint">;
|
|
8
2
|
type Drawer = ReturnType<typeof Drawer>;
|
|
9
3
|
export default Drawer;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ParentDrawerState } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Register a drawer as open.
|
|
4
|
+
*/
|
|
5
|
+
export declare function registerDrawer(state: ParentDrawerState): void;
|
|
6
|
+
/**
|
|
7
|
+
* Unregister a drawer when it closes.
|
|
8
|
+
*/
|
|
9
|
+
export declare function unregisterDrawer(state: ParentDrawerState): void;
|
|
10
|
+
/**
|
|
11
|
+
* Get the current topmost drawer state (if any).
|
|
12
|
+
* Used to auto-detect parent drawer when a new drawer opens.
|
|
13
|
+
* Returns the most recently opened drawer, which becomes the parent of the new drawer.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getCurrentParentDrawer(): ParentDrawerState | undefined;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global registry for tracking open drawers.
|
|
3
|
+
* Enables automatic parent-child relationships without manual prop passing.
|
|
4
|
+
*
|
|
5
|
+
* NOTE: This is intentionally NOT using $state to avoid creating reactive
|
|
6
|
+
* dependencies that would cause infinite effect loops.
|
|
7
|
+
*/
|
|
8
|
+
// Stack of open drawers (most recent last) - intentionally non-reactive
|
|
9
|
+
let openDrawers = [];
|
|
10
|
+
/**
|
|
11
|
+
* Register a drawer as open.
|
|
12
|
+
*/
|
|
13
|
+
export function registerDrawer(state) {
|
|
14
|
+
openDrawers.push(state);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Unregister a drawer when it closes.
|
|
18
|
+
*/
|
|
19
|
+
export function unregisterDrawer(state) {
|
|
20
|
+
const index = openDrawers.indexOf(state);
|
|
21
|
+
if (index !== -1) {
|
|
22
|
+
openDrawers.splice(index, 1);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get the current topmost drawer state (if any).
|
|
27
|
+
* Used to auto-detect parent drawer when a new drawer opens.
|
|
28
|
+
* Returns the most recently opened drawer, which becomes the parent of the new drawer.
|
|
29
|
+
*/
|
|
30
|
+
export function getCurrentParentDrawer() {
|
|
31
|
+
return openDrawers.at(-1);
|
|
32
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -109,6 +109,10 @@ export function useDrawerContent(opts) {
|
|
|
109
109
|
const delta = { x: xPosition, y: yPosition };
|
|
110
110
|
const isAllowedToSwipe = isDeltaInDirection(delta, ctx.direction.current, swipeStartThreshold);
|
|
111
111
|
if (isAllowedToSwipe) {
|
|
112
|
+
// Prevent scrollable content from scrolling while dragging the drawer
|
|
113
|
+
if (ctx.isDragging) {
|
|
114
|
+
e.preventDefault();
|
|
115
|
+
}
|
|
112
116
|
ctx.onDrag(e);
|
|
113
117
|
// Prevent parent drawer from receiving the drag event
|
|
114
118
|
if (ctx.nested.current) {
|
|
@@ -163,6 +167,10 @@ export function useDrawerContent(opts) {
|
|
|
163
167
|
const delta = { x: xPosition, y: yPosition };
|
|
164
168
|
const isAllowedToSwipe = isDeltaInDirection(delta, ctx.direction.current, swipeStartThreshold);
|
|
165
169
|
if (isAllowedToSwipe) {
|
|
170
|
+
// Prevent scrollable content from scrolling while dragging the drawer
|
|
171
|
+
if (ctx.isDragging) {
|
|
172
|
+
e.preventDefault();
|
|
173
|
+
}
|
|
166
174
|
ctx.onDrag(syntheticEvent);
|
|
167
175
|
// Prevent parent drawer from receiving the touch drag event
|
|
168
176
|
if (ctx.nested.current) {
|