|
|
@@ -0,0 +1,62 @@
|
|
|
+<script lang="ts">
|
|
|
+ import type { Snippet } from 'svelte';
|
|
|
+
|
|
|
+ import * as AlertDialog from '$lib/components/controls/alert-dialog';
|
|
|
+
|
|
|
+ type Props = {
|
|
|
+ open: boolean;
|
|
|
+ title: string;
|
|
|
+ description: Snippet;
|
|
|
+ confirmLabel?: string;
|
|
|
+ confirmingLabel?: string;
|
|
|
+ variant?: 'destructive' | 'default';
|
|
|
+ onconfirm: () => Promise<void>;
|
|
|
+ };
|
|
|
+
|
|
|
+ let {
|
|
|
+ open = $bindable(),
|
|
|
+ title,
|
|
|
+ description,
|
|
|
+ confirmLabel = 'Confirm',
|
|
|
+ confirmingLabel = 'Confirming…',
|
|
|
+ variant = 'default',
|
|
|
+ onconfirm,
|
|
|
+ }: Props = $props();
|
|
|
+
|
|
|
+ let confirming = $state(false);
|
|
|
+
|
|
|
+ const handleConfirm = async () => {
|
|
|
+ confirming = true;
|
|
|
+ try {
|
|
|
+ await onconfirm();
|
|
|
+ } finally {
|
|
|
+ confirming = false;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const actionClass = $derived(
|
|
|
+ variant === 'destructive'
|
|
|
+ ? 'bg-red-500 text-white hover:bg-red-600 disabled:opacity-50'
|
|
|
+ : undefined,
|
|
|
+ );
|
|
|
+</script>
|
|
|
+
|
|
|
+<AlertDialog.Root bind:open>
|
|
|
+ <AlertDialog.Portal>
|
|
|
+ <AlertDialog.Overlay />
|
|
|
+ <AlertDialog.Content>
|
|
|
+ <AlertDialog.Header>
|
|
|
+ <AlertDialog.Title>{title}</AlertDialog.Title>
|
|
|
+ <AlertDialog.Description>
|
|
|
+ {@render description()}
|
|
|
+ </AlertDialog.Description>
|
|
|
+ </AlertDialog.Header>
|
|
|
+ <AlertDialog.Footer>
|
|
|
+ <AlertDialog.Cancel>Cancel</AlertDialog.Cancel>
|
|
|
+ <AlertDialog.Action class={actionClass} disabled={confirming} onclick={handleConfirm}>
|
|
|
+ {confirming ? confirmingLabel : confirmLabel}
|
|
|
+ </AlertDialog.Action>
|
|
|
+ </AlertDialog.Footer>
|
|
|
+ </AlertDialog.Content>
|
|
|
+ </AlertDialog.Portal>
|
|
|
+</AlertDialog.Root>
|