<script lang="ts">
  import type { Snippet } from 'svelte';
  // A press-and-hold control: a short tap opens a popover (the consumer renders its
  // buttons), a ~holdMs hold runs `onhold` immediately. Reused by MakeMove and the
  // game tab-bar confirmations. The popover snippet receives a `close` callback.
  let {
    onhold,
    holdMs = 700,
    disabled = false,
    triggerClass = '',
    trigger,
    popover,
  }: {
    onhold: () => void;
    holdMs?: number;
    disabled?: boolean;
    triggerClass?: string;
    trigger: Snippet;
    popover: Snippet<[() => void]>;
  } = $props();

  let open = $state(false);
  let timer: ReturnType<typeof setTimeout> | null = null;
  let held = false;

  function clear() {
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }
  }
  function down() {
    if (disabled) return;
    held = false;
    clear();
    timer = setTimeout(() => {
      held = true;
      open = false;
      onhold();
    }, holdMs);
  }
  function up() {
    clear();
    if (!held && !disabled) open = true;
  }
  function leave() {
    clear();
  }
  const close = () => (open = false);
</script>

<div class="hc">
  <button
    class="trigger {triggerClass}"
    {disabled}
    onpointerdown={down}
    onpointerup={up}
    onpointerleave={leave}
    onpointercancel={leave}
  >
    {@render trigger()}
  </button>

  {#if open}
    <!-- svelte-ignore a11y_click_events_have_key_events -->
    <!-- svelte-ignore a11y_no_static_element_interactions -->
    <div class="backdrop" onclick={close}></div>
    <div class="popover">{@render popover(close)}</div>
  {/if}
</div>

<style>
  .hc {
    position: relative;
    display: flex;
  }
  .trigger {
    width: 100%;
    background: none;
    border: none;
    padding: 0;
    color: inherit;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
  }
  .backdrop {
    position: fixed;
    inset: 0;
    z-index: 18;
  }
  .popover {
    position: absolute;
    bottom: calc(100% + 6px);
    right: 0;
    z-index: 19;
    display: flex;
    flex-direction: column;
    gap: 2px;
    white-space: nowrap;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow);
    padding: 4px;
    min-width: 132px;
  }
</style>
