{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "timeline",
  "title": "Timeline",
  "author": "@fma-ui/ui",
  "description": "A vertical or horizontal timeline rendered as an ordered list. `value` is the current step: items with `step <= value` get `data-completed` (filled indicator and separator) and the current one gets `aria-current=\"step\"`. Compose each `TimelineItem` from `TimelineHeader` (`TimelineDate`, `TimelineTitle`, `TimelineIndicator`), `TimelineSeparator` and `TimelineContent`.",
  "dependencies": [
    "cn@^0.4.0"
  ],
  "files": [
    {
      "path": "src/core/timeline/timeline.tsx",
      "content": "\"use client\";\n\nimport { cn } from \"cn\";\nimport * as React from \"react\";\n\nconst TimelineContext = React.createContext<number | null>(null);\n\nfunction useActiveStep() {\n  const activeStep = React.useContext(TimelineContext);\n  if (activeStep === null) throw new Error(\"TimelineItem must be used within a Timeline\");\n  return activeStep;\n}\n\ntype TimelineProps = React.ComponentProps<\"ol\"> & {\n  /** The current step: items with `step <= value` are marked completed. */\n  value?: number;\n  orientation?: \"horizontal\" | \"vertical\";\n};\n\nfunction Timeline({ value = 1, orientation = \"vertical\", className, ...props }: TimelineProps) {\n  return (\n    <TimelineContext.Provider value={value}>\n      <ol\n        data-slot=\"timeline\"\n        data-orientation={orientation}\n        className={cn(\n          \"group/timeline flex data-[orientation=horizontal]:w-full data-[orientation=horizontal]:flex-row data-[orientation=vertical]:flex-col\",\n          className,\n        )}\n        {...props}\n      />\n    </TimelineContext.Provider>\n  );\n}\n\ntype TimelineItemProps = React.ComponentProps<\"li\"> & { step: number };\n\nfunction TimelineItem({ step, className, ...props }: TimelineItemProps) {\n  const activeStep = useActiveStep();\n  return (\n    <li\n      data-slot=\"timeline-item\"\n      data-completed={step <= activeStep || undefined}\n      aria-current={step === activeStep ? \"step\" : undefined}\n      className={cn(\n        \"group/timeline-item relative flex flex-1 flex-col gap-0.5 group-data-[orientation=horizontal]/timeline:mt-8 group-data-[orientation=vertical]/timeline:ms-8 group-data-[orientation=horizontal]/timeline:not-last:pe-8 group-data-[orientation=vertical]/timeline:not-last:pb-6 has-[+[data-completed]]:**:data-[slot=timeline-separator]:bg-primary\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction TimelineHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n  return <div data-slot=\"timeline-header\" className={className} {...props} />;\n}\n\nfunction TimelineTitle({ className, ...props }: React.ComponentProps<\"h3\">) {\n  return (\n    <h3 data-slot=\"timeline-title\" className={cn(\"text-sm font-medium\", className)} {...props} />\n  );\n}\n\nfunction TimelineDate({ className, ...props }: React.ComponentProps<\"time\">) {\n  return (\n    <time\n      data-slot=\"timeline-date\"\n      className={cn(\n        \"mb-1 block text-xs font-medium text-muted-foreground group-data-[orientation=vertical]/timeline:max-sm:h-4\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction TimelineContent({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"timeline-content\"\n      className={cn(\"text-sm text-muted-foreground\", className)}\n      {...props}\n    />\n  );\n}\n\nfunction TimelineIndicator({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      aria-hidden=\"true\"\n      data-slot=\"timeline-indicator\"\n      className={cn(\n        \"absolute size-4 rounded-full border-2 border-primary/20 group-data-completed/timeline-item:border-primary group-data-[orientation=horizontal]/timeline:-top-6 group-data-[orientation=horizontal]/timeline:left-0 group-data-[orientation=horizontal]/timeline:-translate-y-1/2 group-data-[orientation=vertical]/timeline:top-0 group-data-[orientation=vertical]/timeline:-left-6 group-data-[orientation=vertical]/timeline:-translate-x-1/2\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction TimelineSeparator({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      aria-hidden=\"true\"\n      data-slot=\"timeline-separator\"\n      className={cn(\n        \"absolute self-start bg-primary/10 group-last/timeline-item:hidden group-data-[orientation=horizontal]/timeline:-top-6 group-data-[orientation=horizontal]/timeline:h-0.5 group-data-[orientation=horizontal]/timeline:w-[calc(100%-1rem-0.25rem)] group-data-[orientation=horizontal]/timeline:translate-x-4.5 group-data-[orientation=horizontal]/timeline:-translate-y-1/2 group-data-[orientation=vertical]/timeline:-left-6 group-data-[orientation=vertical]/timeline:h-[calc(100%-1rem-0.25rem)] group-data-[orientation=vertical]/timeline:w-0.5 group-data-[orientation=vertical]/timeline:-translate-x-1/2 group-data-[orientation=vertical]/timeline:translate-y-4.5\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport type { TimelineItemProps, TimelineProps };\nexport {\n  Timeline,\n  TimelineContent,\n  TimelineDate,\n  TimelineHeader,\n  TimelineIndicator,\n  TimelineItem,\n  TimelineSeparator,\n  TimelineTitle,\n};\n",
      "type": "registry:component",
      "target": "components/fma-ui/timeline.tsx"
    }
  ],
  "meta": {
    "status": "stable",
    "source": "third-party",
    "origin": "reui.io (https://reui.io/docs/components/base/timeline, MIT), via EMITTE",
    "tags": [
      "data-display",
      "timeline",
      "steps",
      "progress"
    ]
  },
  "categories": [
    "data-display"
  ],
  "type": "registry:ui"
}