File size: 1,956 Bytes
84f775e |
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 |
<script lang="ts">
import { clickOutside } from "$lib/actions/click-outside.js";
import type { Snippet } from "svelte";
import type { EventHandler } from "svelte/elements";
import IconCross from "~icons/carbon/close";
interface Props {
title: string | Snippet;
children: Snippet;
footer?: Snippet;
onClose?: () => void;
open: boolean;
onSubmit?: EventHandler<SubmitEvent>;
}
let { children, onClose, open, title, footer, onSubmit }: Props = $props();
let dialog: HTMLDialogElement | undefined = $state();
$effect(() => {
if (open) {
dialog?.showModal();
} else {
dialog?.close();
}
});
</script>
<dialog bind:this={dialog} onclose={onClose}>
{#if open}
<form class="fixed inset-0 z-50 flex items-center justify-center overflow-hidden bg-black/85" onsubmit={onSubmit}>
<div class="relative w-xl rounded-xl bg-white shadow-sm dark:bg-gray-900" use:clickOutside={() => onClose?.()}>
<div class="flex items-center justify-between rounded-t border-b p-4 md:px-5 md:py-4 dark:border-gray-800">
{#if typeof title === "string"}
<h3 class="flex items-center gap-2.5 text-lg font-semibold text-gray-900 dark:text-white">
{title}
</h3>
{:else}
{@render title()}
{/if}
<button
type="button"
class="ms-auto inline-flex h-8 w-8 items-center justify-center rounded-lg bg-transparent text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900 dark:hover:bg-gray-600 dark:hover:text-white"
onclick={onClose}
>
<div class="text-xl">
<IconCross />
</div>
<span class="sr-only">Close modal</span>
</button>
</div>
<!-- Modal body -->
<div class="p-4 md:p-5">
{@render children()}
</div>
{#if footer}
<!-- Modal footer -->
<div class="flex rounded-b border-t border-gray-200 p-4 md:p-5 dark:border-gray-800">
{@render footer()}
</div>
{/if}
</div>
</form>
{/if}
</dialog>
|