{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "era-comparison",
  "title": "Era Comparison",
  "description": "Side-by-side comparison of historical eras with domain rows, color-themed columns, highlights, and figure chips.",
  "dependencies": [
    "@vllnt/ui@^0.3.0"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/era-comparison/era-comparison.tsx",
      "content": "\"use client\";\n\nimport {\n  type AnchorHTMLAttributes,\n  type ComponentPropsWithoutRef,\n  createContext,\n  type ReactNode,\n  type Ref,\n  use,\n  useMemo,\n} from \"react\";\n\nimport { cn } from \"@vllnt/ui\";\n\nfunction assignRef<T>(ref: Ref<T> | undefined, node: null | T): void {\n  if (typeof ref === \"function\") {\n    ref(node);\n  } else if (ref) {\n    ref.current = node;\n  }\n}\n\n/**\n * Color theme for an {@link EraColumn} accent strip.\n *\n * @public\n */\nexport type EraColor =\n  | \"amber\"\n  | \"blue\"\n  | \"emerald\"\n  | \"neutral\"\n  | \"purple\"\n  | \"red\"\n  | \"rose\";\n\nconst ERA_PALETTE: Record<EraColor, { accent: string; chip: string }> = {\n  amber: {\n    accent: \"bg-amber-500\",\n    chip: \"bg-amber-500/15 text-amber-700 dark:text-amber-300\",\n  },\n  blue: {\n    accent: \"bg-blue-500\",\n    chip: \"bg-blue-500/15 text-blue-700 dark:text-blue-300\",\n  },\n  emerald: {\n    accent: \"bg-emerald-500\",\n    chip: \"bg-emerald-500/15 text-emerald-700 dark:text-emerald-300\",\n  },\n  neutral: {\n    accent: \"bg-muted-foreground/40\",\n    chip: \"bg-muted text-muted-foreground\",\n  },\n  purple: {\n    accent: \"bg-purple-500\",\n    chip: \"bg-purple-500/15 text-purple-700 dark:text-purple-300\",\n  },\n  red: {\n    accent: \"bg-red-500\",\n    chip: \"bg-red-500/15 text-red-700 dark:text-red-300\",\n  },\n  rose: {\n    accent: \"bg-rose-500\",\n    chip: \"bg-rose-500/15 text-rose-700 dark:text-rose-300\",\n  },\n};\n\ntype EraColumnContextValue = {\n  color: EraColor;\n};\n\nconst EraColumnContext = createContext<EraColumnContextValue>({\n  color: \"neutral\",\n});\n\n/**\n * Hook for reading the surrounding {@link EraColumn}'s color theme. Useful\n * for custom children that want to match the column accent.\n *\n * @public\n */\nexport function useEraColumnColor(): EraColor {\n  return use(EraColumnContext).color;\n}\n\n/**\n * Props for {@link EraComparison}.\n *\n * @public\n */\nexport type EraComparisonProps = ComponentPropsWithoutRef<\"section\">;\n\n/**\n * Side-by-side comparison of historical eras. Lays out {@link EraColumn}\n * children in a responsive grid (1 col on mobile → 2 col on `md` → 3 col\n * on `xl`). Composes {@link Badge}.\n *\n * @example\n * ```tsx\n * <EraComparison>\n *   <EraColumn name=\"Renaissance\" period=\"1400–1600\" color=\"amber\">\n *     <EraDomain name=\"Art\">\n *       <EraHighlight>Perspective painting, humanism</EraHighlight>\n *       <EraFigure name=\"Leonardo da Vinci\" />\n *     </EraDomain>\n *   </EraColumn>\n *   <EraColumn name=\"Islamic Golden Age\" period=\"800–1400\" color=\"emerald\">\n *     <EraDomain name=\"Science\">\n *       <EraHighlight>Algebra, optics, astronomy</EraHighlight>\n *       <EraFigure name=\"Al-Khwarizmi\" />\n *     </EraDomain>\n *   </EraColumn>\n * </EraComparison>\n * ```\n *\n * @public\n */\nexport const EraComparison = ({\n  children,\n  className,\n  ref,\n  ...rest\n}: EraComparisonProps & { ref?: React.Ref<HTMLElement> }) => (\n  <section\n    className={cn(\n      \"grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3\",\n      className,\n    )}\n    ref={ref}\n    {...rest}\n  >\n    {children}\n  </section>\n);\nEraComparison.displayName = \"EraComparison\";\n\n/**\n * Props for {@link EraColumn}.\n *\n * @public\n */\nexport type EraColumnProps = {\n  /** Color theme. Drives the top accent strip + chip. Defaults to `\"neutral\"`. */\n  color?: EraColor;\n  /** Era display name. */\n  name: ReactNode;\n  /** Period label (e.g. `\"1400–1600\"`). */\n  period?: ReactNode;\n  /** Optional region label (e.g. `\"Europe\"`). */\n  region?: ReactNode;\n} & ComponentPropsWithoutRef<\"article\">;\n\ntype ColumnHeaderProps = {\n  color: EraColor;\n  name: ReactNode;\n  period?: ReactNode;\n  region?: ReactNode;\n};\n\nfunction ColumnHeader({\n  color,\n  name,\n  period,\n  region,\n}: ColumnHeaderProps): ReactNode {\n  const palette = ERA_PALETTE[color];\n  return (\n    <header className=\"flex flex-col gap-2\">\n      <span\n        aria-hidden=\"true\"\n        className={cn(\"h-1 w-12 rounded-full\", palette.accent)}\n      />\n      <div className=\"flex items-baseline justify-between gap-2\">\n        <h3 className=\"text-base font-semibold tracking-tight text-foreground\">\n          {name}\n        </h3>\n        {period ? (\n          <span\n            className={cn(\n              \"rounded-full px-2 py-0.5 text-xs font-mono\",\n              palette.chip,\n            )}\n          >\n            {period}\n          </span>\n        ) : null}\n      </div>\n      {region ? (\n        <p className=\"text-xs text-muted-foreground\">{region}</p>\n      ) : null}\n    </header>\n  );\n}\n\n/**\n * Single era column inside an {@link EraComparison}. Wraps a header (name,\n * period, region) and the column body — typically a series of\n * {@link EraDomain} sections.\n *\n * @public\n */\nexport const EraColumn = ({\n  ref,\n  ...props\n}: EraColumnProps & { ref?: React.Ref<HTMLElement> }) => {\n  const {\n    children,\n    className,\n    color = \"neutral\",\n    name,\n    period,\n    region,\n    ...rest\n  } = props;\n  const contextValue = useMemo<EraColumnContextValue>(\n    () => ({ color }),\n    [color],\n  );\n  return (\n    <EraColumnContext.Provider value={contextValue}>\n      <article\n        className={cn(\n          \"flex flex-col gap-3 rounded-2xl border border-border bg-background p-4 shadow-sm\",\n          className,\n        )}\n        data-color={color}\n        ref={ref}\n        {...rest}\n      >\n        <ColumnHeader\n          color={color}\n          name={name}\n          period={period}\n          region={region}\n        />\n        <div className=\"flex flex-col gap-3\">{children}</div>\n      </article>\n    </EraColumnContext.Provider>\n  );\n};\nEraColumn.displayName = \"EraColumn\";\n\n/**\n * Props for {@link EraDomain}.\n *\n * @public\n */\nexport type EraDomainProps = {\n  /** Domain display name (e.g. `\"Art\"`, `\"Science\"`). */\n  name: ReactNode;\n} & ComponentPropsWithoutRef<\"section\">;\n\n/**\n * Domain row inside an {@link EraColumn}. Aligns across columns by\n * convention — pass the same `name` in each column for parallel rows.\n *\n * @public\n */\nexport const EraDomain = ({\n  children,\n  className,\n  name,\n  ref,\n  ...rest\n}: EraDomainProps & { ref?: React.Ref<HTMLElement> }) => (\n  <section\n    className={cn(\"flex flex-col gap-2\", className)}\n    data-domain={typeof name === \"string\" ? name : undefined}\n    ref={ref}\n    {...rest}\n  >\n    <h4 className=\"text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n      {name}\n    </h4>\n    {children}\n  </section>\n);\nEraDomain.displayName = \"EraDomain\";\n\n/**\n * Props for {@link EraHighlight}.\n *\n * @public\n */\nexport type EraHighlightProps = ComponentPropsWithoutRef<\"p\">;\n\n/**\n * Single-line achievement note inside an {@link EraDomain}. Picks up the\n * surrounding column's color theme automatically.\n *\n * @public\n */\nexport const EraHighlight = ({\n  children,\n  className,\n  ref,\n  ...rest\n}: EraHighlightProps & { ref?: React.Ref<HTMLParagraphElement> }) => {\n  const color = useEraColumnColor();\n  const palette = ERA_PALETTE[color];\n  return (\n    <p\n      className={cn(\"rounded-md px-2 py-1 text-sm\", palette.chip, className)}\n      ref={ref}\n      {...rest}\n    >\n      {children}\n    </p>\n  );\n};\nEraHighlight.displayName = \"EraHighlight\";\n\ntype AnchorPassthroughProps = Omit<\n  AnchorHTMLAttributes<HTMLAnchorElement>,\n  \"children\"\n>;\n\n/**\n * Props for {@link EraFigure}.\n *\n * @public\n */\nexport type EraFigureProps = {\n  /** Anchor passthrough (e.g. `target`, `rel`). Forwarded with `href`. */\n  anchorProps?: AnchorPassthroughProps;\n  /** Optional anchor href. With this prop the chip renders as an `<a>`. */\n  href?: string;\n  /** Display name for the figure. */\n  name: ReactNode;\n} & Omit<ComponentPropsWithoutRef<\"span\">, \"children\">;\n\n/**\n * Pill-shaped reference to a notable figure. With an `href`, the chip\n * renders as a link.\n *\n * @public\n */\nexport const EraFigure = ({\n  ref,\n  ...props\n}: EraFigureProps & {\n  ref?: React.Ref<HTMLAnchorElement | HTMLSpanElement>;\n}) => {\n  const { anchorProps, className, href, name, ...rest } = props;\n  const color = useEraColumnColor();\n  const palette = ERA_PALETTE[color];\n  const baseClass = cn(\n    \"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium\",\n    palette.chip,\n    className,\n  );\n  if (href) {\n    return (\n      <a\n        className={cn(baseClass, \"underline-offset-4 hover:underline\")}\n        href={href}\n        ref={(node) => {\n          assignRef(ref, node);\n        }}\n        {...anchorProps}\n      >\n        {name}\n      </a>\n    );\n  }\n  return (\n    <span\n      className={baseClass}\n      ref={(node) => {\n        assignRef(ref, node);\n      }}\n      {...rest}\n    >\n      {name}\n    </span>\n  );\n};\nEraFigure.displayName = \"EraFigure\";\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component",
  "version": "0.3.0",
  "stability": "stable"
}
