{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "progress",
  "title": "Progress",
  "description": "The bar fills on a spring, the percentage rolls and it turns green when complete.",
  "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/progress.tsx",
      "content": "\"use client\"\n\n/* Animated drop-in for `@ui-sdk/react/progress`: same parts, same props. Swap the import and keep your code.\n   This file adds motion only. Colours, radii, shadows and spacing stay yours. */\n\nimport {\n  ProgressIndicator as ProgressIndicatorPart,\n  ProgressTrack as ProgressTrackPart,\n  ProgressValue as ProgressValuePart,\n} from \"@ui-sdk/react/progress\"\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport * from \"@ui-sdk/react/progress\"\n\n/* Roll: every digit is a column of 0 to 9 that slides to its value on a spring; other characters\n   (%, spaces, units) stay put. Positions are keyed from the right, so 9% to 10% rolls the units\n   digit and adds a tens digit instead of shifting everything. Exported for other numbers. */\nfunction Roll({ text, className }: { text: string; className?: string }) {\n  const chars = text.split(\"\")\n  /* Screen readers get the plain value; the digit columns are only for the eye. */\n  return (\n    <>\n    <span className=\"sr-only\">{text}</span>\n    <span data-slot=\"roll\" aria-hidden className={cn(\"inline-flex h-[1lh] overflow-hidden whitespace-pre tabular-nums\", className)}>\n      {chars.map((c, i) => {\n        const key = chars.length - i\n        return /\\d/.test(c) ? (\n          <span\n            key={key}\n            style={{ \"--d\": Number(c) } as React.CSSProperties}\n            className=\"flex flex-col transition-[translate] duration-[calc(500ms*var(--kf-speed,1))] ease-spring [translate:0_calc(var(--d)*-1lh)] motion-reduce:transition-none!\"\n          >\n            {Array.from({ length: 10 }, (_, d) => (\n              <span key={d} className=\"h-[1lh]\">\n                {d}\n              </span>\n            ))}\n          </span>\n        ) : (\n          <span key={key}>{c}</span>\n        )\n      })}\n    </span>\n    </>\n  )\n}\n\n/* The value rolls to each new reading. Pass children to render your own. */\nfunction ProgressValue({ children, ...props }: React.ComponentProps<typeof ProgressValuePart>) {\n  return (\n    <ProgressValuePart {...props}>\n      {children ?? ((state) => <Roll text={state.text} />)}\n    </ProgressValuePart>\n  )\n}\n\n/* The track clips the fill, so its spring overshoot never shows outside. */\nfunction ProgressTrack({ className, ...props }: React.ComponentProps<typeof ProgressTrackPart>) {\n  return <ProgressTrackPart className={cn(\"overflow-hidden\", className)} {...props} />\n}\n\n/* The fill moves to each new width on a spring (it overshoots a little and settles). While the\n   amount is unknown, a 40% bar slides through the track; with reduced motion it rests full width. */\nfunction ProgressIndicator({ className, ...props }: React.ComponentProps<typeof ProgressIndicatorPart>) {\n  return (\n    <>\n      <style href=\"kf-progress-slide\" precedence=\"default\">\n        {\"@keyframes kf-progress-slide{from{translate:-100% 0}to{translate:250% 0}}\"}\n      </style>\n      <ProgressIndicatorPart\n        className={cn(\n          \"block h-full [transition:width_calc(700ms*var(--kf-speed,1))_var(--ease-spring),background-color_calc(300ms*var(--kf-speed,1))_var(--ease-house)]\",\n          \"data-indeterminate:w-2/5 data-indeterminate:animate-[kf-progress-slide_1.3s_cubic-bezier(0.65,0,0.35,1)_infinite]\",\n          \"motion-reduce:transition-none! motion-reduce:data-indeterminate:w-full motion-reduce:data-indeterminate:animate-none!\",\n          className,\n        )}\n        {...props}\n      />\n    </>\n  )\n}\n\nexport { ProgressIndicator, ProgressTrack, ProgressValue, Roll }\n",
      "type": "registry:component",
      "target": "components/keyframery/primitives/progress.tsx"
    },
    {
      "path": "registry/components/keyframery/progress.tsx",
      "content": "\"use client\"\n\n/* Styled progress: the animated primitive plus the Keyframery look. */\n\nimport {\n  Progress as ProgressRoot,\n  ProgressIndicator as ProgressIndicatorPart,\n  ProgressLabel as ProgressLabelPart,\n  ProgressTrack as ProgressTrackPart,\n  ProgressValue as ProgressValuePart,\n} from \"@/components/keyframery/primitives/progress\"\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Label and value share the first row; the track spans the row below. */\nfunction Progress({ className, ...props }: React.ComponentProps<typeof ProgressRoot>) {\n  return (\n    <ProgressRoot\n      className={cn(\n        \"group/progress grid w-full grid-cols-[minmax(0,1fr)_auto] items-baseline gap-x-3 gap-y-2\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction ProgressLabel({ className, ...props }: React.ComponentProps<typeof ProgressLabelPart>) {\n  return (\n    <ProgressLabelPart\n      className={cn(\"truncate text-[13px] leading-5 font-medium text-foreground\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction ProgressValue({ className, ...props }: React.ComponentProps<typeof ProgressValuePart>) {\n  return (\n    <ProgressValuePart\n      className={cn(\n        \"col-start-2 text-[13px] leading-5 text-muted-foreground tabular-nums\",\n        \"transition-colors duration-[calc(150ms*var(--kf-speed,1))] data-complete:text-foreground motion-reduce:transition-none!\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* The track is a thin pill well. */\nfunction ProgressTrack({ className, ...props }: React.ComponentProps<typeof ProgressTrackPart>) {\n  return (\n    <ProgressTrackPart\n      className={cn(\n        \"relative col-span-full h-1.5 w-full rounded-full bg-muted\",\n        \"shadow-[inset_0_1px_2px_rgb(0_0_0/0.07),inset_0_0_0_1px_rgb(0_0_0/0.035)]\",\n        \"dark:shadow-[inset_0_1px_2px_rgb(0_0_0/0.5),inset_0_0_0_1px_rgb(255_255_255/0.04)]\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* The fill springs to each new width and the indeterminate bar slides (from the primitive).\n   When the task finishes it turns green once. */\nfunction ProgressIndicator({\n  className,\n  ...props\n}: React.ComponentProps<typeof ProgressIndicatorPart>) {\n  return (\n    <ProgressIndicatorPart\n      className={cn(\n        \"rounded-full bg-primary\",\n        \"shadow-[inset_0_1px_0_rgb(255_255_255/0.14)]\",\n        \"data-complete:bg-[oklch(0.62_0.16_150)]\",\n        \"motion-reduce:data-indeterminate:opacity-30\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nexport { Progress, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue }\n",
      "type": "registry:component",
      "target": "components/keyframery/progress.tsx"
    }
  ],
  "type": "registry:component"
}