import type { ReactNode } from 'react';
import { cn } from '@/lib/utils';

/**
 * The sanctioned extension seam.
 *
 * A demo that needs something the shell does not have has two options: fork the
 * shell, or drop it into a slot. This is the second one. Slots are named and
 * finite, so `check-demos` can see what a demo added and reviewers can see it
 * in a diff — which is the whole reason this exists rather than letting demos
 * pass arbitrary children into arbitrary components.
 *
 * A slot with nothing in it renders NOTHING, not an empty box: the layout must
 * not shift depending on whether a demo opted in.
 */
export type SlotId =
  | 'hero-aside'
  | 'below-board'
  | 'beside-reward'
  | 'below-timeline'
  | 'before-limits'
  | 'after-receipts';

export interface SlotRegionProps {
  id: SlotId;
  /**
   * Announced to assistive tech when the slot has content. Omit for purely
   * decorative additions; a region with no label is not exposed as a landmark.
   */
  label?: string;
  children?: ReactNode;
  className?: string;
}

export function SlotRegion({ id, label, children, className }: SlotRegionProps) {
  // `children` can be `false`/`null` from a demo's own conditional. Treat those
  // as "no slot content" rather than rendering a labelled empty region.
  if (children === null || children === undefined || children === false) return null;

  if (!label) {
    return (
      <div data-slot={id} className={className}>
        {children}
      </div>
    );
  }

  return (
    <section data-slot={id} aria-label={label} className={cn('contents', className)}>
      {children}
    </section>
  );
}
