<script lang="ts">
	import { Dialog } from 'bits-ui';
	import X from '@lucide/svelte/icons/x';
	import type { Snippet } from 'svelte';
	import { m } from '$lib/paraglide/messages';

	type Props = {
		open?: boolean;
		/** For callers whose open state is derived from something else (an
		 *  "editing this row" object, say) and cannot be two-way bound. */
		onOpenChange?: (open: boolean) => void;
		title: string;
		description?: string;
		children: Snippet;
		contentClass?: string;
		'data-testid'?: string;
	};

	let {
		open = $bindable(false),
		onOpenChange,
		title,
		description,
		children,
		contentClass = '',
		'data-testid': testId
	}: Props = $props();
</script>

<Dialog.Root bind:open {onOpenChange}>
	<Dialog.Portal>
		<Dialog.Overlay class="fixed inset-0 z-50 bg-surface-sunken/70 backdrop-blur-sm" />
		<Dialog.Content
			class="fixed top-1/2 left-1/2 z-50 w-[min(28rem,calc(100vw-2rem))] -translate-x-1/2 -translate-y-1/2 rounded-xl border border-border bg-surface-raised p-6 shadow-lg {contentClass}"
			data-testid={testId}
		>
			<div class="mb-4 flex items-start justify-between gap-4">
				<div>
					<Dialog.Title class="text-lg font-semibold">{title}</Dialog.Title>
					{#if description}
						<Dialog.Description class="mt-1 text-sm text-ink-muted">
							{description}
						</Dialog.Description>
					{/if}
				</div>
				<Dialog.Close
					class="cursor-pointer rounded-md p-1 text-ink-muted transition-colors hover:bg-surface-sunken hover:text-ink focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
					aria-label={m.common_close()}
				>
					<X size={18} />
				</Dialog.Close>
			</div>
			{@render children()}
		</Dialog.Content>
	</Dialog.Portal>
</Dialog.Root>
