{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "waterfall",
  "title": "Waterfall",
  "description": "Request bars grow from their start time one row after another, and nested spans cascade in.",
  "dependencies": [
    "@ui-sdk/core@0.1.0-beta.2",
    "@ui-sdk/react@0.1.0-beta.2"
  ],
  "registryDependencies": [
    "@keyframery/motion"
  ],
  "files": [
    {
      "path": "registry/components/keyframery/primitives/waterfall.tsx",
      "content": "\"use client\"\n\n/* Animated drop-in for `@ui-sdk/react/waterfall`: same parts, same props. Swap the import and keep your\n   code. This file adds motion only. Colours, radii, shadows and spacing stay yours. */\n\nimport {\n  WaterfallAxis as WaterfallAxisPart,\n  WaterfallBar as WaterfallBarPart,\n  WaterfallIndicator as WaterfallIndicatorPart,\n  WaterfallMark as WaterfallMarkPart,\n  WaterfallRow as WaterfallRowPart,\n  WaterfallTick as WaterfallTickPart,\n} from \"@ui-sdk/react/waterfall\"\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport * from \"@ui-sdk/react/waterfall\"\n\n/* UI SDK accepts a class name or a function of state; keep both working. */\nfunction withClass<S>(base: string, className: string | ((state: S) => string | undefined) | undefined) {\n  return typeof className === \"function\" ? (state: S) => cn(base, className(state)) : cn(base, className)\n}\n\n/* Keyframes rather than transitions: a row has no earlier state when it mounts, or when a collapsed\n   span opens and its hidden rows show again. Both replay the animation. */\nconst keyframes = [\n  \"@keyframes kf-waterfall-row{from{opacity:0;translate:0 6px;filter:blur(3px)}}\",\n  \"@keyframes kf-waterfall-bar{from{scale:0 1}}\",\n  \"@keyframes kf-waterfall-mark{from{opacity:0;clip-path:inset(0 0 100% 0)}}\",\n].join(\"\")\n\n/* Cascade: each row rises in a little after the one before it among its siblings, so opening a\n   span cascades its children from the first one. The place comes from the row's own\n   `aria-posinset`; where a browser can't read it, every row simply arrives at once. */\nfunction WaterfallRow({ className, ...props }: React.ComponentProps<typeof WaterfallRowPart>) {\n  return (\n    <>\n      <style href=\"kf-waterfall\" precedence=\"default\">\n        {keyframes}\n      </style>\n      <WaterfallRowPart\n        className={withClass(\n          cn(\n            \"[--kf-wf-i:attr(aria-posinset_type(<integer>),1)]\",\n            \"[--kf-wf-delay:calc((min(var(--kf-wf-i),10)-1)*calc(36ms*var(--kf-speed,1)))]\",\n            \"animate-[kf-waterfall-row_calc(420ms*var(--kf-speed,1))_var(--ease-spring)_backwards] [animation-delay:var(--kf-wf-delay)]\",\n            \"motion-reduce:animate-none!\",\n          ),\n          className,\n        )}\n        {...props}\n      />\n    </>\n  )\n}\n\n/* The bar grows left to right from where its span starts, on a spring, just after its row arrives.\n   When the range changes (a zoom, or new timings) it glides to its new place and length. It is\n   drawn by `::before`, placed by `--waterfall-start` and `--waterfall-size`, with a neutral\n   default surface you can restyle with `before:` classes. */\nfunction WaterfallBar({ className, ...props }: React.ComponentProps<typeof WaterfallBarPart>) {\n  return (\n    <WaterfallBarPart\n      className={withClass(\n        cn(\n          \"relative\",\n          \"before:absolute before:inset-y-2 before:start-(--waterfall-start) before:w-(--waterfall-size) before:min-w-0.5 before:content-['']\",\n          \"before:bg-[color-mix(in_oklch,currentColor_40%,transparent)]\",\n          \"before:origin-left rtl:before:origin-right\",\n          \"before:animate-[kf-waterfall-bar_calc(620ms*var(--kf-speed,1))_var(--ease-spring)_backwards]\",\n          \"before:[animation-delay:calc(var(--kf-wf-delay,0ms)+calc(90ms*var(--kf-speed,1)))]\",\n          \"before:transition-[inset-inline-start,width] before:duration-[calc(560ms*var(--kf-speed,1))] before:ease-spring\",\n          \"motion-reduce:before:animate-none! motion-reduce:before:transition-none!\",\n        ),\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* The chevron turns on a spring as its span opens. */\nfunction WaterfallIndicator({ className, ...props }: React.ComponentProps<typeof WaterfallIndicatorPart>) {\n  return (\n    <WaterfallIndicatorPart\n      className={withClass(\n        cn(\n          \"transition-[rotate] duration-[calc(380ms*var(--kf-speed,1))] ease-spring data-expanded:rotate-90 rtl:data-expanded:-rotate-90\",\n          \"motion-reduce:transition-none!\",\n        ),\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* The mark glides to its new moment when the time changes or the range moves, draws down when it\n   first appears, and fades while its moment is outside the range. */\nfunction WaterfallMark({ className, ...props }: React.ComponentProps<typeof WaterfallMarkPart>) {\n  return (\n    <WaterfallMarkPart\n      className={withClass(\n        cn(\n          \"absolute start-(--waterfall-mark)\",\n          \"transition-[inset-inline-start,opacity] duration-[calc(560ms*var(--kf-speed,1))] ease-spring data-outside:opacity-0\",\n          \"animate-[kf-waterfall-mark_calc(520ms*var(--kf-speed,1))_var(--ease-house)_calc(240ms*var(--kf-speed,1))_backwards]\",\n          \"motion-reduce:animate-none! motion-reduce:transition-none!\",\n        ),\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* Ticks sit at their time on the axis and glide when the range moves. */\nfunction WaterfallTick({ className, ...props }: React.ComponentProps<typeof WaterfallTickPart>) {\n  return (\n    <WaterfallTickPart\n      className={withClass(\n        cn(\n          \"absolute start-(--waterfall-tick)\",\n          \"transition-[inset-inline-start] duration-[calc(560ms*var(--kf-speed,1))] ease-spring motion-reduce:transition-none!\",\n        ),\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* Same as UI SDK's axis, but its default ticks are the gliding ones above. */\nfunction WaterfallAxis({ children, ...props }: React.ComponentProps<typeof WaterfallAxisPart>) {\n  return (\n    <WaterfallAxisPart {...props}>\n      {children ?? ((state) => state.ticks.map((tick) => <WaterfallTick key={tick.time} time={tick.time} />))}\n    </WaterfallAxisPart>\n  )\n}\n\nexport { WaterfallAxis, WaterfallBar, WaterfallIndicator, WaterfallMark, WaterfallRow, WaterfallTick }\n",
      "type": "registry:component",
      "target": "components/keyframery/primitives/waterfall.tsx"
    },
    {
      "path": "registry/components/keyframery/waterfall.tsx",
      "content": "\"use client\"\n\n/* Styled waterfall: the animated primitive plus the Keyframery look. */\n\nimport * as React from \"react\"\n\nimport {\n  Waterfall as WaterfallRoot,\n  WaterfallAxis as WaterfallAxisPrimitive,\n  WaterfallBar as WaterfallBarPrimitive,\n  WaterfallCell as WaterfallCellPrimitive,\n  WaterfallColumnHeader as WaterfallColumnHeaderPrimitive,\n  WaterfallHeaderRow as WaterfallHeaderRowPrimitive,\n  WaterfallIndicator as WaterfallIndicatorPrimitive,\n  WaterfallMark as WaterfallMarkPrimitive,\n  WaterfallRow as WaterfallRowPrimitive,\n  WaterfallRowHeader as WaterfallRowHeaderPrimitive,\n  WaterfallTick as WaterfallTickPrimitive,\n} from \"@/components/keyframery/primitives/waterfall\"\nimport { cn } from \"@/lib/utils\"\n\nexport { createWaterfallController, visibleWaterfallRows, type WaterfallData } from \"@/components/keyframery/primitives/waterfall\"\n\nconst focusRing = \"outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset\"\n\n/* A sheet laid out as a grid; every row is a subgrid, so columns line up. Set the columns with\n   a `grid-cols-[…]` class: the default is a name column and a timeline. */\nfunction Waterfall({ className, ...props }: React.ComponentProps<typeof WaterfallRoot>) {\n  return (\n    <WaterfallRoot\n      className={cn(\n        \"relative grid grid-cols-[minmax(8rem,auto)_minmax(0,1fr)] overflow-hidden rounded-[14px] bg-card py-1 text-[12.5px] text-card-foreground\",\n        \"shadow-[0_0_0_1px_rgb(0_0_0/0.06),0_2px_6px_-2px_rgb(0_0_0/0.08),0_12px_32px_-8px_rgb(0_0_0/0.12)]\",\n        \"dark:shadow-[0_0_0_1px_rgb(255_255_255/0.08),0_12px_32px_-8px_rgb(0_0_0/0.7)]\",\n        className as string,\n      )}\n      {...props}\n    />\n  )\n}\n\nconst rowGrid = \"col-span-full grid grid-cols-subgrid items-center gap-x-3 px-3\"\n\nfunction WaterfallHeaderRow({ className, ...props }: React.ComponentProps<typeof WaterfallHeaderRowPrimitive>) {\n  return (\n    <WaterfallHeaderRowPrimitive\n      className={cn(rowGrid, \"mb-1 h-12 border-b border-border text-[11px] font-medium text-muted-foreground\", className as string)}\n      {...props}\n    />\n  )\n}\n\nfunction WaterfallColumnHeader({ className, ...props }: React.ComponentProps<typeof WaterfallColumnHeaderPrimitive>) {\n  return <WaterfallColumnHeaderPrimitive className={cn(\"relative flex h-full items-center\", className as string)} {...props} />\n}\n\n/* Round times along the top of the timeline. */\nfunction WaterfallAxis({ className, ...props }: React.ComponentProps<typeof WaterfallAxisPrimitive>) {\n  return <WaterfallAxisPrimitive className={cn(\"relative h-full flex-1\", className as string)} {...props} />\n}\n\nfunction WaterfallTick({ className, ...props }: React.ComponentProps<typeof WaterfallTickPrimitive>) {\n  return (\n    <WaterfallTickPrimitive\n      className={cn(\n        \"top-2 -translate-x-1/2 text-[10.5px] leading-none font-normal whitespace-nowrap tabular-nums first:translate-x-0 last:-translate-x-full\",\n        className as string,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* A moment across every row: a label in the header and a hairline running down the rows. */\nfunction WaterfallMark({ className, ...props }: React.ComponentProps<typeof WaterfallMarkPrimitive>) {\n  return (\n    <WaterfallMarkPrimitive\n      className={cn(\n        \"pointer-events-none bottom-1.5 z-10 -translate-x-1/2 rounded-full bg-ring/12 px-1.5 py-[3px] text-[10.5px] leading-none font-medium whitespace-nowrap text-ring\",\n        \"after:absolute after:top-full after:left-1/2 after:h-[999px] after:w-px after:bg-ring/50 after:content-['']\",\n        className as string,\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction WaterfallRow({ className, ...props }: React.ComponentProps<typeof WaterfallRowPrimitive>) {\n  return (\n    <WaterfallRowPrimitive\n      className={cn(\n        rowGrid,\n        \"h-8 cursor-default\",\n        \"hover:bg-foreground/[0.03] data-selected:bg-accent dark:data-selected:bg-accent/70\",\n        focusRing,\n        className as string,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* The span's name, indented by its depth. Leaves line up with the names of spans beside a chevron. */\nfunction WaterfallRowHeader({ className, ...props }: React.ComponentProps<typeof WaterfallRowHeaderPrimitive>) {\n  return (\n    <WaterfallRowHeaderPrimitive\n      className={cn(\n        \"flex h-full min-w-0 items-center gap-1 truncate font-medium\",\n        \"ps-[calc((var(--waterfall-level)-1)*14px)] not-data-branch:ps-[calc((var(--waterfall-level)-1)*14px+20px)]\",\n        \"data-[level=2]:font-normal data-[level=2]:text-muted-foreground data-[level=2]:data-selected:text-foreground\",\n        focusRing,\n        className as string,\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction WaterfallIndicator({ className, children, ...props }: React.ComponentProps<typeof WaterfallIndicatorPrimitive>) {\n  return (\n    <WaterfallIndicatorPrimitive\n      className={cn(\n        \"grid size-4 shrink-0 cursor-pointer place-items-center rounded-[5px] text-muted-foreground hover:bg-foreground/[0.06] hover:text-foreground\",\n        className as string,\n      )}\n      {...props}\n    >\n      {children ?? (\n        <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden className=\"size-3.5\">\n          <path d=\"m6 4 4 4-4 4\" />\n        </svg>\n      )}\n    </WaterfallIndicatorPrimitive>\n  )\n}\n\nfunction WaterfallCell({ className, ...props }: React.ComponentProps<typeof WaterfallCellPrimitive>) {\n  return (\n    <WaterfallCellPrimitive\n      className={cn(\"flex h-full items-center whitespace-nowrap text-muted-foreground tabular-nums\", focusRing, className as string)}\n      {...props}\n    />\n  )\n}\n\n/* Top-level spans in the primary colour, nested ones quieter; the selected span takes the ring colour. */\nfunction WaterfallBar({ className, ...props }: React.ComponentProps<typeof WaterfallBarPrimitive>) {\n  return (\n    <WaterfallBarPrimitive\n      className={cn(\n        \"h-full\",\n        \"before:inset-y-[10px] before:rounded-[3px] before:bg-primary/75\",\n        \"data-[level=2]:before:bg-muted-foreground/40 data-[level=3]:before:bg-muted-foreground/30\",\n        \"data-selected:before:bg-ring\",\n        focusRing,\n        className as string,\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Waterfall,\n  WaterfallAxis,\n  WaterfallBar,\n  WaterfallCell,\n  WaterfallColumnHeader,\n  WaterfallHeaderRow,\n  WaterfallIndicator,\n  WaterfallMark,\n  WaterfallRow,\n  WaterfallRowHeader,\n  WaterfallTick,\n}\n",
      "type": "registry:component",
      "target": "components/keyframery/waterfall.tsx"
    }
  ],
  "type": "registry:component"
}