<script lang="ts">
    import type { Snippet } from 'svelte';
    import Modal from './Modal.svelte';
    import Sheet from './Sheet.svelte';

    // One overlay that adapts to the form factor: a bottom Sheet on phones,
    // a centered Modal on desktop. Both share the same chrome contract
    // (open / title / onClose / children / testid), so callers stay agnostic
    // and the page-action editors present consistently with the rest of the
    // mobile UI (long-press → action sheet → editor sheet, no Modal hop).
    let {
        open,
        title,
        onClose,
        children,
        size = 'md',
        testid
    }: {
        open: boolean;
        title: string;
        onClose: () => void;
        children: Snippet;
        /** Desktop modal width; ignored by the mobile sheet. */
        size?: 'sm' | 'md' | 'lg';
        testid?: string;
    } = $props();

    // Bottom sheet under the 640px breakpoint. Guarded on matchMedia rather
    // than $app/environment so it's SSR-safe (no window) and unit-testable
    // (stub matchMedia). First paint defaults to the modal; the effect
    // corrects to a sheet on phones before the dialog is opened.
    let isMobile = $state(false);
    $effect(() => {
        if (typeof window === 'undefined' || !window.matchMedia) return;
        const mql = window.matchMedia('(max-width: 640px)');
        isMobile = mql.matches;
        const onChange = (e: MediaQueryListEvent) => {
            isMobile = e.matches;
        };
        mql.addEventListener('change', onChange);
        return () => mql.removeEventListener('change', onChange);
    });
</script>

{#if isMobile}
    <Sheet {open} {title} {onClose} {testid}>
        {@render children()}
    </Sheet>
{:else}
    <Modal {open} {title} {onClose} {size} {testid}>
        {@render children()}
    </Modal>
{/if}
