1<script lang="ts">
2 import { Dialog as DialogPrimitive } from 'bits-ui';
3 import XIcon from '@lucide/svelte/icons/x';
4 import type { Snippet } from 'svelte';
5 import * as Dialog from './index.js';
6 import { cn, type WithoutChildrenOrChild } from '$lib/components/ui/utils';
7
8 let {
9 ref = $bindable(null),
10 class: className,
11 portalProps,
12 children,
13 showCloseButton = true,
14 ...restProps
15 }: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
16 portalProps?: DialogPrimitive.PortalProps;
17 children: Snippet;
18 showCloseButton?: boolean;
19 } = $props();
20</script>
21
22<Dialog.Portal {...portalProps}>
23 <Dialog.Overlay />
24 <DialogPrimitive.Content
25 bind:ref
26 data-slot="dialog-content"
27 class={cn(
28 `fixed top-[50%] left-[50%] z-50 grid max-h-[100dvh] w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 overflow-y-auto rounded-lg border border-border/30 bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg md:max-h-[100vh]`,
29 className
30 )}
31 {...restProps}
32 >
33 {@render children?.()}
34 {#if showCloseButton}
35 <DialogPrimitive.Close
36 class="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
37 >
38 <XIcon />
39 <span class="sr-only">Close</span>
40 </DialogPrimitive.Close>
41 {/if}
42 </DialogPrimitive.Content>
43</Dialog.Portal>