Spaces:
Running
Running
File size: 2,919 Bytes
336b102 c6afb12 336b102 c6afb12 336b102 c6afb12 336b102 c6afb12 336b102 c6afb12 336b102 c6afb12 336b102 c6afb12 336b102 74473f3 336b102 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | <script lang="ts" module>
import type { Snippet } from 'svelte';
export type SheetSide = 'top' | 'right' | 'bottom' | 'left';
export type SheetProps = {
open?: boolean;
titleText?: string;
description?: string;
side?: SheetSide;
lockScroll?: boolean;
contentClass?: string;
headerClass?: string;
titleClass?: string;
header?: Snippet;
title?: Snippet;
children?: Snippet;
};
</script>
<script lang="ts">
import * as UISheet from '$lib/components/ui/sheet';
import { cn } from '$lib/utils.js';
let {
open = $bindable(false),
titleText = '',
description,
side = 'right',
lockScroll = true,
contentClass,
headerClass,
titleClass,
header,
title,
children
}: SheetProps = $props();
let contentElement = $state<HTMLElement | null>(null);
let restoreFocusTo: HTMLElement | null = null;
$effect.pre(() => {
if (typeof document === 'undefined' || !open) return;
const activeElement = document.activeElement;
if (activeElement instanceof HTMLElement) restoreFocusTo = activeElement;
});
$effect(() => {
if (typeof document === 'undefined' || !open || !lockScroll) return;
function preventOutsideScroll(event: WheelEvent | TouchEvent) {
const target = event.target;
if (target instanceof Node && contentElement?.contains(target)) return;
event.preventDefault();
}
document.addEventListener('wheel', preventOutsideScroll, { passive: false });
document.addEventListener('touchmove', preventOutsideScroll, { passive: false });
return () => {
document.removeEventListener('wheel', preventOutsideScroll);
document.removeEventListener('touchmove', preventOutsideScroll);
};
});
function handleCloseAutoFocus(event: Event) {
event.preventDefault();
if (restoreFocusTo && document.contains(restoreFocusTo)) {
restoreFocusTo.focus({ preventScroll: true });
}
restoreFocusTo = null;
}
</script>
<UISheet.Root bind:open>
<UISheet.Content
bind:ref={contentElement}
{side}
preventScroll={false}
onCloseAutoFocus={handleCloseAutoFocus}
class={cn(
'w-screen max-w-none overflow-y-auto overscroll-contain p-0 data-[side=right]:w-screen! data-[side=right]:max-w-none! sm:data-[side=right]:w-[90vw]! sm:data-[side=right]:max-w-none! lg:data-[side=right]:w-1/2!',
contentClass
)}
>
{#if header}
{@render header()}
{:else}
<UISheet.Header class={cn('border-b p-4 pr-14 sm:p-5 sm:pr-16', headerClass)}>
<UISheet.Title
class={cn('min-w-0 font-mono text-lg font-semibold tracking-normal', titleClass)}
>
{#if title}
{@render title()}
{:else}
<span class="block truncate">{titleText}</span>
{/if}
</UISheet.Title>
{#if description}
<UISheet.Description class="text-sm leading-6 text-muted-foreground">
{description}
</UISheet.Description>
{/if}
</UISheet.Header>
{/if}
{@render children?.()}
</UISheet.Content>
</UISheet.Root>
|