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

  let {
    title = '',
    onclose,
    overlayKeyboard = false,
    children,
  }: { title?: string; onclose?: () => void; overlayKeyboard?: boolean; children?: Snippet } = $props();

  // Track the visual viewport so the backdrop covers only the area above an open
  // mobile keyboard: dvh alone shrinks the sheet but the fixed, layout-viewport
  // backdrop still centres it behind the keyboard. Sizing the backdrop to
  // visualViewport keeps the sheet (and the start of a chat) fully on screen.
  // overlayKeyboard opts out: the sheet is small and top-anchored, so the keyboard
  // simply overlays the empty lower area — no resize, no relayout jank (e.g. check word).
  let vh = $state(0);
  let top = $state(0);
  $effect(() => {
    const vv = typeof window !== 'undefined' ? window.visualViewport : null;
    if (!vv || overlayKeyboard) return;
    const update = () => {
      vh = vv.height;
      top = vv.offsetTop;
    };
    update();
    vv.addEventListener('resize', update);
    vv.addEventListener('scroll', update);
    return () => {
      vv.removeEventListener('resize', update);
      vv.removeEventListener('scroll', update);
    };
  });
</script>

<!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
  class="backdrop"
  class:overlay={overlayKeyboard}
  style:height={vh ? `${vh}px` : null}
  style:top={vh ? `${top}px` : null}
  onclick={() => onclose?.()}
>
  <div class="sheet" role="dialog" aria-modal="true" tabindex="-1" onclick={(e) => e.stopPropagation()}>
    {#if title}<h2>{title}</h2>{/if}
    {@render children?.()}
  </div>
</div>

<style>
  .backdrop {
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    /* Base fallback; overridden inline to the visual-viewport height/top so the
       backdrop (and the centred sheet) stay above an open mobile keyboard. */
    height: 100dvh;
    box-sizing: border-box;
    background: rgba(0, 0, 0, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    z-index: 40;
  }
  /* Overlay mode: top-anchor the (small) sheet and don't track the keyboard, so the
     soft keyboard overlays the empty lower area without resizing/relaying out. */
  .backdrop.overlay {
    align-items: flex-start;
    padding-top: 12vh;
  }
  .sheet {
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: var(--pad);
    width: min(94vw, 420px);
    /* dvh tracks the dynamic viewport, so the sheet shrinks above an open mobile
       keyboard instead of being scrolled off the top (vh fallback first). */
    max-height: 86vh;
    max-height: 86dvh;
    overflow: auto;
  }
  h2 {
    margin: 0 0 10px;
    font-size: 1.05rem;
  }
</style>
