<script lang="ts">
  /**
   * A bordered box with a caption bar — the unit every page is assembled from.
   *
   * `variant` picks the era-correct chrome:
   *   panel  blue caption bar (left rail)
   *   band   peach caption bar (main column)
   *   plain  no chrome, just the heading
  */
  import type { Snippet } from 'svelte'
  import type { CustomEmoji } from '$lib/api/types'
  import EmojiText from './EmojiText.svelte'

  interface Props {
    title?: string
    /** Custom emoji available to user-derived titles. */
    titleEmojis?: CustomEmoji[]
    variant?: 'panel' | 'band' | 'plain'
    /** Right-aligned link in the caption bar, e.g. "[view all]". */
    action?: Snippet
    /** Remove body padding, for tables that should meet the border. */
    flush?: boolean
    /** Extra classes, so callers can add their own styling hook. */
    class?: string
    children: Snippet
  }

  let {
    title,
    titleEmojis,
    variant = 'panel',
    action,
    flush = false,
    class: extraClass = '',
    children,
  }: Props = $props()

  const variantClass = $derived(
    variant === 'band' ? 'module--band' : variant === 'plain' ? 'module--plain' : '',
  )
</script>

<section class="module {variantClass} {extraClass}" data-variant={variant}>
  {#if title}
    <h2 class="module-header">
      <EmojiText class="module-header-title" text={title} emojis={titleEmojis} />
      {#if action}
        <span class="module-header-action">{@render action()}</span>
      {/if}
    </h2>
  {/if}
  <div class="module-body" class:module-body--flush={flush}>
    {@render children()}
  </div>
</section>
