{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "timeline",
  "description": "A visual representation of events in chronological order.",
  "dependencies": [
    "@base-ui/react"
  ],
  "registryDependencies": [
    "@ondo-ui/utils"
  ],
  "files": [
    {
      "path": "components/ui/timeline.tsx",
      "content": "\"use client\"\n\nimport { createContext, useCallback, useContext, useState } from \"react\"\nimport { mergeProps } from \"@base-ui/react/merge-props\"\nimport { useRender } from \"@base-ui/react/use-render\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst timelineVariants = cva(\n  \"group/timeline flex [--timeline-rail:1rem] data-[orientation=horizontal]:w-full data-[orientation=horizontal]:flex-row data-[orientation=vertical]:flex-col\",\n  {\n    variants: {\n      size: {\n        sm: \"[--timeline-icon:0.5rem] [--timeline-indicator:0.75rem]\",\n        default: \"[--timeline-icon:0.625rem] [--timeline-indicator:1rem]\",\n        lg: \"[--timeline-icon:0.875rem] [--timeline-indicator:1.5rem]\",\n      },\n    },\n    defaultVariants: {\n      size: \"default\",\n    },\n  }\n)\n\ntype TimelineContextValue = {\n  activeStep: number\n  setActiveStep: (step: number) => void\n}\n\nconst TimelineContext = createContext<TimelineContextValue | undefined>(\n  undefined\n)\n\nconst useTimeline = () => {\n  const context = useContext(TimelineContext)\n  if (!context) {\n    throw new Error(\"useTimeline must be used within a Timeline\")\n  }\n  return context\n}\n\ninterface TimelineProps\n  extends\n    useRender.ComponentProps<\"div\">,\n    VariantProps<typeof timelineVariants> {\n  defaultValue?: number\n  value?: number\n  onValueChange?: (value: number) => void\n  orientation?: \"horizontal\" | \"vertical\"\n}\n\nfunction Timeline({\n  defaultValue = 1,\n  value,\n  onValueChange,\n  orientation = \"vertical\",\n  size = \"default\",\n  className,\n  render,\n  children,\n  ...props\n}: TimelineProps) {\n  const [activeStep, setInternalStep] = useState(defaultValue)\n\n  const setActiveStep = useCallback(\n    (step: number) => {\n      if (value === undefined) {\n        setInternalStep(step)\n      }\n      onValueChange?.(step)\n    },\n    [value, onValueChange]\n  )\n\n  const currentStep = value ?? activeStep\n\n  const defaultProps = {\n    className: cn(timelineVariants({ size }), className),\n    \"data-orientation\": orientation,\n    \"data-size\": size,\n    \"data-slot\": \"timeline\",\n    children,\n  }\n\n  return (\n    <TimelineContext.Provider\n      value={{ activeStep: currentStep, setActiveStep }}\n    >\n      {useRender({\n        defaultTagName: \"div\",\n        render,\n        props: mergeProps<\"div\">(defaultProps, props),\n      })}\n    </TimelineContext.Provider>\n  )\n}\n\nfunction TimelineContent({\n  className,\n  render,\n  children,\n  ...props\n}: useRender.ComponentProps<\"div\">) {\n  const defaultProps = {\n    className: cn(\"text-sm text-muted-foreground\", className),\n    \"data-slot\": \"timeline-content\",\n    children,\n  }\n\n  return useRender({\n    defaultTagName: \"div\",\n    render,\n    props: mergeProps<\"div\">(defaultProps, props),\n  })\n}\n\ntype TimelineDateProps = useRender.ComponentProps<\"time\">\n\nfunction TimelineDate({\n  className,\n  render,\n  children,\n  ...props\n}: TimelineDateProps) {\n  const defaultProps = {\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    \"data-slot\": \"timeline-date\",\n    children,\n  }\n\n  return useRender({\n    defaultTagName: \"time\",\n    render,\n    props: mergeProps<\"time\">(defaultProps, props),\n  })\n}\n\nfunction TimelineHeader({\n  className,\n  render,\n  children,\n  ...props\n}: useRender.ComponentProps<\"div\">) {\n  const defaultProps = {\n    className: cn(className),\n    \"data-slot\": \"timeline-header\",\n    children,\n  }\n\n  return useRender({\n    defaultTagName: \"div\",\n    render,\n    props: mergeProps<\"div\">(defaultProps, props),\n  })\n}\n\nconst timelineIndicatorVariants = cva(\n  [\n    \"absolute flex size-(--timeline-indicator) items-center justify-center rounded-full\",\n    \"group-data-[orientation=horizontal]/timeline:top-[calc((var(--timeline-indicator)/2+var(--timeline-rail))*-1)] group-data-[orientation=horizontal]/timeline:left-0 group-data-[orientation=horizontal]/timeline:-translate-y-1/2\",\n    \"group-data-[orientation=vertical]/timeline:top-0 group-data-[orientation=vertical]/timeline:left-[calc((var(--timeline-indicator)/2+var(--timeline-rail))*-1)] group-data-[orientation=vertical]/timeline:-translate-x-1/2\",\n    \"[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-(--timeline-icon)\",\n    \"before:absolute before:inset-0 before:-z-1 before:hidden before:rounded-full before:bg-(--timeline-accent) before:opacity-75\",\n    \"group-data-completed/timeline-item:before:bg-(--timeline-accent-done)\",\n  ],\n  {\n    variants: {\n      variant: {\n        default:\n          \"[--timeline-accent-done:var(--color-primary)] [--timeline-accent-fg:var(--color-primary-foreground)] [--timeline-accent:var(--color-primary)]\",\n        muted:\n          \"[--timeline-accent-done:var(--color-primary)] [--timeline-accent-fg:var(--color-primary-foreground)] [--timeline-accent:var(--color-muted-foreground)]\",\n        info: \"[--timeline-accent-done:var(--color-info)] [--timeline-accent-fg:var(--color-background)] [--timeline-accent:var(--color-info)]\",\n        success:\n          \"[--timeline-accent-done:var(--color-success)] [--timeline-accent-fg:var(--color-background)] [--timeline-accent:var(--color-success)]\",\n        warning:\n          \"[--timeline-accent-done:var(--color-warning)] [--timeline-accent-fg:var(--color-background)] [--timeline-accent:var(--color-warning)]\",\n        destructive:\n          \"[--timeline-accent-done:var(--color-destructive)] [--timeline-accent-fg:var(--color-background)] [--timeline-accent:var(--color-destructive)]\",\n      },\n      fill: {\n        outline:\n          \"border-2 border-(--timeline-accent)/20 text-(--timeline-accent) group-data-completed/timeline-item:border-(--timeline-accent-done)\",\n        solid:\n          \"bg-(--timeline-accent)/10 text-(--timeline-accent) group-data-completed/timeline-item:bg-(--timeline-accent-done) group-data-completed/timeline-item:text-(--timeline-accent-fg)\",\n      },\n      animate: {\n        ping: \"group-data-current/timeline-item:before:motion-safe:block group-data-current/timeline-item:before:motion-safe:animate-ping\",\n        pulse: \"group-data-current/timeline-item:motion-safe:animate-pulse\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n      fill: \"outline\",\n    },\n  }\n)\n\ninterface TimelineIndicatorProps\n  extends\n    useRender.ComponentProps<\"div\">,\n    VariantProps<typeof timelineIndicatorVariants> {}\n\nfunction TimelineIndicator({\n  className,\n  variant = \"default\",\n  fill = \"outline\",\n  animate,\n  children,\n  render,\n  ...props\n}: TimelineIndicatorProps) {\n  const defaultProps = {\n    \"aria-hidden\": true,\n    className: cn(\n      timelineIndicatorVariants({ variant, fill, animate }),\n      className\n    ),\n    \"data-slot\": \"timeline-indicator\",\n    \"data-variant\": variant,\n    \"data-fill\": fill,\n    children,\n  }\n\n  return useRender({\n    defaultTagName: \"div\",\n    render,\n    props: mergeProps<\"div\">(defaultProps, props),\n  })\n}\n\ninterface TimelineItemProps extends useRender.ComponentProps<\"div\"> {\n  step: number\n}\n\nfunction TimelineItem({\n  step,\n  className,\n  render,\n  children,\n  ...props\n}: TimelineItemProps) {\n  const { activeStep } = useTimeline()\n\n  const defaultProps = {\n    className: cn(\n      \"group/timeline-item relative flex flex-1 flex-col gap-0.5 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      \"group-data-[orientation=horizontal]/timeline:mt-[calc(var(--timeline-indicator)+var(--timeline-rail))] group-data-[orientation=vertical]/timeline:ms-[calc(var(--timeline-indicator)+var(--timeline-rail))]\",\n      className\n    ),\n    \"data-completed\": step <= activeStep || undefined,\n    \"data-current\": step === activeStep || undefined,\n    \"data-slot\": \"timeline-item\",\n    children,\n  }\n\n  return useRender({\n    defaultTagName: \"div\",\n    render,\n    props: mergeProps<\"div\">(defaultProps, props),\n  })\n}\n\nfunction TimelineSeparator({\n  className,\n  render,\n  children,\n  ...props\n}: useRender.ComponentProps<\"div\">) {\n  const defaultProps = {\n    \"aria-hidden\": true,\n    className: cn(\n      \"absolute self-start bg-primary/10 group-last/timeline-item:hidden\",\n      \"group-data-[orientation=horizontal]/timeline:top-[calc((var(--timeline-indicator)/2+var(--timeline-rail))*-1)] group-data-[orientation=horizontal]/timeline:h-0.5 group-data-[orientation=horizontal]/timeline:w-[calc(100%-var(--timeline-indicator)-0.25rem)] group-data-[orientation=horizontal]/timeline:translate-x-[calc(var(--timeline-indicator)+0.125rem)] group-data-[orientation=horizontal]/timeline:-translate-y-1/2\",\n      \"group-data-[orientation=vertical]/timeline:left-[calc((var(--timeline-indicator)/2+var(--timeline-rail))*-1)] group-data-[orientation=vertical]/timeline:h-[calc(100%-var(--timeline-indicator)-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-[calc(var(--timeline-indicator)+0.125rem)]\",\n      className\n    ),\n    \"data-slot\": \"timeline-separator\",\n    children,\n  }\n\n  return useRender({\n    defaultTagName: \"div\",\n    render,\n    props: mergeProps<\"div\">(defaultProps, props),\n  })\n}\n\nfunction TimelineTitle({\n  className,\n  render,\n  children,\n  ...props\n}: useRender.ComponentProps<\"h3\">) {\n  const defaultProps = {\n    className: cn(\"text-sm font-medium\", className),\n    \"data-slot\": \"timeline-title\",\n    children,\n  }\n\n  return useRender({\n    defaultTagName: \"h3\",\n    render,\n    props: mergeProps<\"h3\">(defaultProps, props),\n  })\n}\n\nexport {\n  Timeline,\n  TimelineContent,\n  TimelineDate,\n  TimelineHeader,\n  TimelineIndicator,\n  TimelineItem,\n  TimelineSeparator,\n  TimelineTitle,\n  timelineVariants,\n  timelineIndicatorVariants,\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}