Skip to content

Commit 420e678

Browse files
committed
more
1 parent b988fca commit 420e678

File tree

12 files changed

+319
-1200
lines changed

12 files changed

+319
-1200
lines changed

packages/vaul-svelte/src/lib/components/drawer/drawer-content.svelte

+22-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script lang="ts">
2-
import { Dialog as DialogPrimitive, useId } from "bits-ui";
3-
import { box, mergeProps } from "svelte-toolbelt";
2+
import { Dialog as DialogPrimitive, type WithoutChildrenOrChild, useId } from "bits-ui";
3+
import { type WithChildren, box, mergeProps } from "svelte-toolbelt";
4+
import Mounted from "../utils/mounted.svelte";
45
import type { DrawerContentProps } from "./types.js";
56
import { useDrawerContent } from "$lib/vaul.svelte.js";
67
import { noop } from "$lib/internal/helpers/noop.js";
@@ -12,8 +13,9 @@
1213
onEscapeKeydown = noop,
1314
onInteractOutside = noop,
1415
onFocusOutside = noop,
16+
children,
1517
...restProps
16-
}: DrawerContentProps = $props();
18+
}: WithChildren<WithoutChildrenOrChild<DrawerContentProps>> = $props();
1719
1820
const contentState = useDrawerContent({
1921
id: box.with(() => id),
@@ -29,6 +31,7 @@
2931
<DialogPrimitive.Content
3032
bind:ref
3133
{...mergedProps}
34+
preventScroll={false}
3235
onMountAutoFocus={(e) => {
3336
onMountAutoFocus(e);
3437
if (e.defaultPrevented) return;
@@ -37,20 +40,29 @@
3740
onEscapeKeydown={(e) => {
3841
onEscapeKeydown(e);
3942
if (e.defaultPrevented) return;
40-
if (!contentState.root.modal.current) {
41-
e.preventDefault();
42-
}
43+
e.preventDefault();
44+
if (!contentState.root.modal.current) return;
45+
contentState.root.closeDrawer();
4346
}}
4447
onFocusOutside={(e) => {
4548
onFocusOutside(e);
4649
if (e.defaultPrevented) return;
47-
if (!contentState.root.modal.current) {
48-
e.preventDefault();
49-
}
50+
contentState.onFocusOutside(e);
5051
}}
5152
onInteractOutside={(e) => {
5253
onInteractOutside(e);
5354
if (e.defaultPrevented) return;
5455
contentState.onInteractOutside(e);
5556
}}
56-
/>
57+
>
58+
<Mounted
59+
onMounted={(mounted) => {
60+
if (mounted) {
61+
contentState.root.visible = true;
62+
} else {
63+
contentState.root.drawerNode = null;
64+
}
65+
}}
66+
/>
67+
{@render children?.()}
68+
</DialogPrimitive.Content>

packages/vaul-svelte/src/lib/components/drawer/drawer-overlay.svelte

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
<script lang="ts">
2-
import { Dialog as DialogPrimitive, useId } from "bits-ui";
3-
import { box, mergeProps } from "svelte-toolbelt";
2+
import { Dialog as DialogPrimitive, type WithoutChildrenOrChild, useId } from "bits-ui";
3+
import { type WithChildren, box, mergeProps } from "svelte-toolbelt";
4+
import Mounted from "../utils/mounted.svelte";
45
import type { DrawerOverlayProps } from "./types.js";
56
import { useDrawerOverlay } from "$lib/vaul.svelte.js";
67
7-
let { id = useId(), ref = $bindable(null), ...restProps }: DrawerOverlayProps = $props();
8+
let {
9+
id = useId(),
10+
ref = $bindable(null),
11+
children,
12+
...restProps
13+
}: WithChildren<WithoutChildrenOrChild<DrawerOverlayProps>> = $props();
814
915
const overlayState = useDrawerOverlay({
1016
id: box.with(() => id),
@@ -17,4 +23,13 @@
1723
const mergedProps = $derived(mergeProps(restProps, overlayState.props));
1824
</script>
1925

20-
<DialogPrimitive.Overlay bind:ref {...mergedProps} />
26+
<DialogPrimitive.Overlay bind:ref {...mergedProps}>
27+
<Mounted
28+
onMounted={(mounted) => {
29+
if (!mounted) {
30+
overlayState.root.overlayNode = null;
31+
}
32+
}}
33+
/>
34+
{@render children?.()}
35+
</DialogPrimitive.Overlay>

packages/vaul-svelte/src/lib/components/drawer/drawer.svelte

+35-29
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
noBodyStyles = false,
3232
preventScrollRestoration = true,
3333
setBackgroundColorOnScale = true,
34+
disablePreventScroll = false,
3435
...restProps
3536
}: DrawerRootProps = $props();
3637
@@ -67,25 +68,23 @@
6768
noBodyStyles: box.with(() => noBodyStyles),
6869
preventScrollRestoration: box.with(() => preventScrollRestoration),
6970
setBackgroundColorOnScale: box.with(() => setBackgroundColorOnScale),
71+
disablePreventScroll: box.with(() => disablePreventScroll),
7072
});
7173
</script>
7274

7375
<DialogPrimitive.Root
7476
bind:open
7577
onOpenChange={(o) => {
7678
onOpenChange(o);
77-
if (!o) {
78-
rootState.closeDrawer();
79-
} else if (o) {
80-
rootState.openDrawer();
81-
}
79+
rootState.onOpenChange(o);
8280
}}
8381
{...restProps}
8482
/>
8583

86-
<style>
84+
<style global>
8785
:global([data-vaul-drawer]) {
8886
touch-action: none;
87+
will-change: transform;
8988
transition: transform 0.5s cubic-bezier(0.32, 0.72, 0, 1);
9089
}
9190
@@ -105,18 +104,18 @@
105104
transform: translate3d(100%, 0, 0);
106105
}
107106
108-
:global(.vaul-dragging .vaul-scrollable [data-vaul-drawer-direction="top"]) {
107+
:global(.vaul-dragging .vaul-scrollable [data-vault-drawer-direction="top"]) {
109108
overflow-y: hidden !important;
110109
}
111-
112-
:global(.vaul-dragging .vaul-scrollable [data-vaul-drawer-direction="bottom"]) {
110+
:global(.vaul-dragging .vaul-scrollable [data-vault-drawer-direction="bottom"]) {
113111
overflow-y: hidden !important;
114112
}
115113
116-
:global(.vaul-dragging .vaul-scrollable [data-vaul-drawer-direction="left"]) {
114+
:global(.vaul-dragging .vaul-scrollable [data-vault-drawer-direction="left"]) {
117115
overflow-x: hidden !important;
118116
}
119-
:global(.vaul-dragging .vaul-scrollable [data-vaul-drawer-direction="right"]) {
117+
118+
:global(.vaul-dragging .vaul-scrollable [data-vault-drawer-direction="right"]) {
120119
overflow-x: hidden !important;
121120
}
122121
@@ -190,22 +189,6 @@
190189
width: 200%;
191190
}
192191
193-
:global(
194-
[data-vaul-overlay][data-vaul-snap-points="true"]:not(
195-
[data-vaul-snap-points-overlay="true"]
196-
):not([data-state="closed"])
197-
) {
198-
opacity: 0;
199-
}
200-
201-
:global(
202-
[data-vaul-overlay][data-vaul-snap-points-overlay="true"]:not(
203-
[data-vaul-drawer-visible="false"]
204-
)
205-
) {
206-
opacity: 1;
207-
}
208-
209192
:global([data-vaul-handle]) {
210193
display: block;
211194
position: relative;
@@ -237,8 +220,24 @@
237220
touch-action: inherit;
238221
}
239222
240-
/* This will allow us to not animate via animation, but still benefit from delaying
241-
unmount via Bits */
223+
:global(
224+
[data-vaul-overlay][data-vaul-snap-points="true"]:not(
225+
[data-vaul-snap-points-overlay="true"]
226+
):not([data-state="closed"])
227+
) {
228+
opacity: 0;
229+
}
230+
231+
:global(
232+
[data-vaul-overlay][data-vaul-snap-points-overlay="true"]:not(
233+
[data-vaul-drawer-visible="false"]
234+
)
235+
) {
236+
opacity: 1;
237+
}
238+
239+
/* This will allow us to not animate via animation, but still benefit from delaying unmount via Radix. */
240+
242241
@keyframes -global-fake-animation {
243242
from {
244243
}
@@ -251,4 +250,11 @@
251250
user-select: none;
252251
}
253252
}
253+
254+
@media (pointer: fine) {
255+
:global([data-vaul-handle-hitarea]) {
256+
width: 100%;
257+
height: 100%;
258+
}
259+
}
254260
</style>

packages/vaul-svelte/src/lib/components/drawer/types.ts

+7
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,13 @@ type BaseDrawerRootPropsWithoutHTML = WithChildren<{
159159
* @default true
160160
*/
161161
setBackgroundColorOnScale?: boolean;
162+
163+
/**
164+
* When `true` scroll will not be prevented outside the drawer.
165+
*
166+
* @default false
167+
*/
168+
disablePreventScroll?: boolean;
162169
}>;
163170

164171
export type DrawerRootPropsWithoutHTML = BaseDrawerRootPropsWithoutHTML &
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script lang="ts">
2+
import { onMount } from "svelte";
3+
4+
let { onMounted }: { onMounted: (bool: boolean) => void } = $props();
5+
6+
onMount(() => {
7+
onMounted(true);
8+
9+
return () => {
10+
onMounted(false);
11+
};
12+
});
13+
</script>

packages/vaul-svelte/src/lib/internal/helpers/is.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,16 @@ export function isInput(target: Element) {
2929
}
3030

3131
export function isVertical(direction: DrawerDirection) {
32-
if (direction === "top" || direction === "bottom") return true;
33-
return false;
32+
switch (direction) {
33+
case "top":
34+
case "bottom":
35+
return true;
36+
case "left":
37+
case "right":
38+
return false;
39+
default:
40+
return direction satisfies never;
41+
}
3442
}
3543

3644
export function isBottomOrRight(direction: DrawerDirection) {

packages/vaul-svelte/src/lib/internal/helpers/style.ts

+7-10
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ interface Style {
77

88
const cache = new WeakMap();
99

10-
export function setStyles(el?: Element | HTMLElement | null, styles?: Style, ignoreCache = false) {
11-
if (!el || !(el instanceof HTMLElement) || !styles) return;
12-
10+
export function setStyles(
11+
el: Element | HTMLElement | null | undefined,
12+
styles: Style,
13+
ignoreCache = false
14+
) {
15+
if (!el || !(el instanceof HTMLElement)) return;
1316
const originalStyles: Style = {};
1417

1518
Object.entries(styles).forEach(([key, value]: [string, string]) => {
@@ -49,6 +52,7 @@ export function resetStyles(el: Element | HTMLElement | null, prop?: string) {
4952
}
5053

5154
export function getTranslate(element: HTMLElement, direction: DrawerDirection): number | null {
55+
if (!element) return null;
5256
const style = window.getComputedStyle(element);
5357
const transform =
5458
// @ts-expect-error - vendor prefix
@@ -62,10 +66,3 @@ export function getTranslate(element: HTMLElement, direction: DrawerDirection):
6266
mat = transform.match(/^matrix\((.+)\)$/);
6367
return mat ? Number.parseFloat(mat[1].split(", ")[isVertical(direction) ? 5 : 4]) : null;
6468
}
65-
66-
export function styleToString(style: Record<string, number | string | undefined>): string {
67-
return Object.keys(style).reduce((str, key) => {
68-
if (style[key] === undefined) return str;
69-
return `${str}${key}:${style[key]};`;
70-
}, "");
71-
}

0 commit comments

Comments
 (0)