<script lang="ts">
  // Renders an invisible sentinel element near the bottom of a paged list.
  // When the sentinel enters the viewport (within `rootMargin`), onIntersect
  // fires — typically calling TanStack Query's fetchNextPage. The caller is
  // responsible for setting `enabled = hasNextPage && !isFetchingNextPage`
  // so the observer stays disconnected while a fetch is in flight; otherwise
  // a tall list could fire onIntersect repeatedly during a single scroll.

  let {
    onIntersect,
    enabled = true,
    rootMargin = '800px'
  }: {
    onIntersect: () => void;
    enabled?: boolean;
    /** Distance below the viewport at which the sentinel triggers. Larger
        values fire earlier so the next page is fetched well before the
        user scrolls into empty space. Default 800px ≈ 3-4 rows of
        cards on a typical library grid. */
    rootMargin?: string;
  } = $props();

  let sentinel: HTMLElement | undefined = $state();

  $effect(() => {
    if (!enabled || !sentinel) return;
    if (typeof IntersectionObserver === 'undefined') return;
    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0]?.isIntersecting) onIntersect();
      },
      { rootMargin }
    );
    observer.observe(sentinel);
    return () => observer.disconnect();
  });
</script>

<div bind:this={sentinel} aria-hidden="true" class="h-px"></div>
