{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "timescale",
  "title": "Timescale",
  "author": "ncdai <dai@chanhdai.com>",
  "description": "Ruler-style timeline for plotting milestones along a horizontal or vertical axis.",
  "files": [
    {
      "path": "src/registry/components/timescale/timescale.tsx",
      "content": "\"use client\"\n\n// Inspired by Evil Rabbit's Lifeline: https://lifeline.evilrabbit.com\nimport { useEffect, useRef } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport type TimescaleRootProps = React.ComponentProps<\"div\"> & {\n  orientation?: \"horizontal\" | \"vertical\"\n}\n\nexport function TimescaleRoot({\n  className,\n  orientation = \"horizontal\",\n  ...props\n}: TimescaleRootProps) {\n  return (\n    <div\n      data-slot=\"timescale-root\"\n      data-orientation={orientation}\n      className={cn(\n        \"group/timescale relative flex w-full [--timescale-rail:--spacing(14)]\",\n        \"data-[orientation=vertical]:flex-col\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport type TimescaleViewportProps = React.ComponentProps<\"div\">\n\nexport function TimescaleViewport({\n  className,\n  ...props\n}: TimescaleViewportProps) {\n  return (\n    <div\n      data-slot=\"timescale-viewport\"\n      className={cn(\n        \"no-scrollbar w-full\",\n        \"group-data-[orientation=horizontal]/timescale:flex group-data-[orientation=horizontal]/timescale:flex-1 group-data-[orientation=horizontal]/timescale:scroll-fade-x group-data-[orientation=horizontal]/timescale:overflow-x-auto group-data-[orientation=horizontal]/timescale:overscroll-x-contain group-data-[orientation=horizontal]/timescale:pl-20 group-data-[orientation=horizontal]/timescale:scroll-fade-s-40\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport type TimescaleHeaderProps = React.ComponentProps<\"div\">\n\nexport function TimescaleHeader({ className, ...props }: TimescaleHeaderProps) {\n  return (\n    <div\n      data-slot=\"timescale-header\"\n      aria-hidden=\"true\"\n      className={cn(\n        \"z-10\",\n        \"group-data-[orientation=horizontal]/timescale:absolute group-data-[orientation=horizontal]/timescale:top-0 group-data-[orientation=horizontal]/timescale:left-0 group-data-[orientation=horizontal]/timescale:w-20 group-data-[orientation=horizontal]/timescale:shrink-0 group-data-[orientation=horizontal]/timescale:bg-linear-to-r group-data-[orientation=horizontal]/timescale:from-background group-data-[orientation=horizontal]/timescale:from-75% group-data-[orientation=horizontal]/timescale:to-transparent group-data-[orientation=horizontal]/timescale:pr-4 group-data-[orientation=horizontal]/timescale:text-right\",\n        \"group-data-[orientation=vertical]/timescale:grid group-data-[orientation=vertical]/timescale:w-full group-data-[orientation=vertical]/timescale:grid-cols-[var(--timescale-rail)_1fr] group-data-[orientation=vertical]/timescale:gap-x-4 group-data-[orientation=vertical]/timescale:bg-background\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport type TimescaleTrackProps = React.ComponentProps<\"div\">\n\nexport function TimescaleTrack({ className, ...props }: TimescaleTrackProps) {\n  return (\n    <div\n      data-slot=\"timescale-track\"\n      className={cn(\n        \"relative flex\",\n        \"group-data-[orientation=horizontal]/timescale:w-max group-data-[orientation=horizontal]/timescale:items-start\",\n        \"group-data-[orientation=vertical]/timescale:w-full group-data-[orientation=vertical]/timescale:flex-col group-data-[orientation=vertical]/timescale:pt-4\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport type TimescaleRailProps = React.ComponentProps<\"div\">\n\nexport function TimescaleRail({ className, ...props }: TimescaleRailProps) {\n  return (\n    <div\n      data-slot=\"timescale-rail\"\n      aria-hidden=\"true\"\n      className={cn(\n        \"pointer-events-none absolute border-dashed\",\n        \"group-data-[orientation=horizontal]/timescale:inset-x-0 group-data-[orientation=horizontal]/timescale:top-(--timescale-rail) group-data-[orientation=horizontal]/timescale:h-px group-data-[orientation=horizontal]/timescale:border-t\",\n        \"group-data-[orientation=vertical]/timescale:inset-y-0 group-data-[orientation=vertical]/timescale:left-(--timescale-rail) group-data-[orientation=vertical]/timescale:w-px group-data-[orientation=vertical]/timescale:border-l\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport type TimescaleItemProps = React.ComponentProps<\"div\">\n\nexport function TimescaleItem({ className, ...props }: TimescaleItemProps) {\n  return (\n    <div\n      data-slot=\"timescale-item\"\n      className={cn(\n        \"relative\",\n        \"group-data-[orientation=horizontal]/timescale:w-20 group-data-[orientation=horizontal]/timescale:shrink-0 group-data-[orientation=horizontal]/timescale:not-last:pr-4 group-data-[orientation=horizontal]/timescale:has-data-[slot=timescale-content]:w-80\",\n        \"group-data-[orientation=vertical]/timescale:grid group-data-[orientation=vertical]/timescale:w-full group-data-[orientation=vertical]/timescale:grid-cols-[var(--timescale-rail)_1fr] group-data-[orientation=vertical]/timescale:gap-x-4 group-data-[orientation=vertical]/timescale:not-last:pb-4\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport type TimescaleTickProps = React.ComponentProps<\"span\">\n\nexport function TimescaleTick({ className, ...props }: TimescaleTickProps) {\n  return (\n    <span\n      data-slot=\"timescale-tick\"\n      aria-hidden=\"true\"\n      className={cn(\n        \"absolute z-10 bg-border\",\n        \"group-data-[orientation=horizontal]/timescale:top-(--timescale-rail) group-data-[orientation=horizontal]/timescale:left-0 group-data-[orientation=horizontal]/timescale:h-3 group-data-[orientation=horizontal]/timescale:w-px group-data-[orientation=horizontal]/timescale:-translate-y-1/2\",\n        \"group-data-[orientation=vertical]/timescale:top-2.5 group-data-[orientation=vertical]/timescale:left-(--timescale-rail) group-data-[orientation=vertical]/timescale:h-px group-data-[orientation=vertical]/timescale:w-3 group-data-[orientation=vertical]/timescale:-translate-x-1/2\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport type TimescaleAgeProps = React.ComponentProps<\"p\">\n\nexport function TimescaleAge({ className, ...props }: TimescaleAgeProps) {\n  return (\n    <p\n      data-slot=\"timescale-age\"\n      className={cn(\n        \"text-xs leading-5 font-medium text-muted-foreground tabular-nums\",\n        \"in-data-[slot=timescale-header]:tracking-widest in-data-[slot=timescale-header]:uppercase\",\n        \"group-data-[orientation=vertical]/timescale:col-start-1 group-data-[orientation=vertical]/timescale:row-start-1 group-data-[orientation=vertical]/timescale:pr-4 group-data-[orientation=vertical]/timescale:text-right\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport type TimescaleYearProps = React.ComponentProps<\"p\">\n\nexport function TimescaleYear({ className, ...props }: TimescaleYearProps) {\n  return (\n    <p\n      data-slot=\"timescale-year\"\n      className={cn(\n        \"text-xs leading-5 font-medium text-muted-foreground tabular-nums\",\n        \"in-data-[slot=timescale-header]:tracking-widest in-data-[slot=timescale-header]:uppercase\",\n        \"group-data-[orientation=vertical]/timescale:col-start-2 group-data-[orientation=vertical]/timescale:row-start-1\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport type TimescaleContentProps = React.ComponentProps<\"div\">\n\nexport function TimescaleContent({\n  className,\n  ...props\n}: TimescaleContentProps) {\n  return (\n    <div\n      data-slot=\"timescale-content\"\n      className={cn(\n        \"w-full py-4 text-left\",\n        \"group-data-[orientation=horizontal]/timescale:mt-4\",\n        \"group-data-[orientation=vertical]/timescale:col-start-2 group-data-[orientation=vertical]/timescale:row-start-2\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nconst INTRO_SCROLL_START_HOLD = 200 // ms resting on the first item before scrolling\n\n// Sweeps a horizontal Timescale to its most recent item on mount using native\n// smooth scroll, so `scroll-fade` stays in sync and there is no scroll stepping.\nexport function TimescaleIntroScroll({\n  children,\n}: {\n  children: React.ReactNode\n}) {\n  const ref = useRef<HTMLDivElement>(null)\n\n  useEffect(() => {\n    const viewport = ref.current?.querySelector<HTMLElement>(\n      '[data-slot=\"timescale-viewport\"]'\n    )\n    if (!viewport) return\n\n    const distance = viewport.scrollWidth - viewport.clientWidth\n    if (distance <= 0) return\n\n    // Respect users who opt out of motion: land at the end without the sweep.\n    if (window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches) {\n      viewport.scrollLeft = distance\n      return\n    }\n\n    // A user gesture cancels the native smooth scroll, so no manual interruption\n    // handling is needed.\n    const timer = window.setTimeout(() => {\n      viewport.scrollTo({ left: distance, behavior: \"smooth\" })\n    }, INTRO_SCROLL_START_HOLD)\n\n    return () => window.clearTimeout(timer)\n  }, [])\n\n  return (\n    <div ref={ref} className=\"contents\">\n      {children}\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/timescale.tsx"
    }
  ],
  "docs": "https://chanhdai.com/components/timescale",
  "categories": [
    "data-display"
  ],
  "type": "registry:component"
}