{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ds-step-progress",
  "title": "Step Progress",
  "description": "A visual guide through a sequential multi-step process with horizontal and vertical orientations.",
  "dependencies": [
    "lucide-react",
    "class-variance-authority"
  ],
  "registryDependencies": [
    "@lema-ds/ui-i18n",
    "@lema-ds/ds-locale-provider"
  ],
  "files": [
    {
      "path": "components/ds/ds-step-progress.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Check } from \"lucide-react\"\nimport { cva } from \"class-variance-authority\"\nimport type { VariantProps } from \"class-variance-authority\"\nimport type { HTMLAttributes, ReactNode } from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport { UI_I18N, type UILocale } from \"@/lib/ui-i18n\"\nimport { useUILocale } from \"@/components/ui/ds-locale-provider\"\n\n// ── Types ──────────────────────────────────────────────────────────────────\n\nexport interface StepItem {\n  id: string\n  title: string\n  description?: string\n  icon?: ReactNode\n}\n\nexport interface StepProgressProps\n  extends\n    Omit<HTMLAttributes<HTMLOListElement>, \"onChange\">,\n    VariantProps<typeof stepProgressVariants> {\n  steps: StepItem[]\n  currentStepId: string\n  onStepClick?: (id: string) => void\n  size?: \"sm\" | \"md\" | \"lg\"\n  locale?: UILocale\n}\n\nexport interface StepProgressItemProps {\n  step: StepItem\n  index: number\n  isLast: boolean\n  status: \"complete\" | \"current\" | \"upcoming\"\n  connectorStatus: \"complete\" | \"current\" | \"upcoming\"\n  orientation: \"horizontal\" | \"vertical\"\n  size: \"sm\" | \"md\" | \"lg\"\n  onStepClick?: (id: string) => void\n}\n\n// ── Variants ───────────────────────────────────────────────────────────────\n\nexport const stepProgressVariants = cva(\"flex w-full\", {\n  variants: {\n    orientation: {\n      horizontal: \"flex-row items-start\",\n      vertical: \"flex-col\",\n    },\n  },\n  defaultVariants: { orientation: \"horizontal\" },\n})\n\nexport const stepCircleVariants = cva(\n  [\n    \"flex shrink-0 items-center justify-center rounded-full font-semibold transition-all duration-300 ease-out\",\n    \"ring-offset-background group-focus-visible:ring-2 group-focus-visible:ring-ring group-focus-visible:ring-offset-2\",\n  ],\n  {\n    variants: {\n      status: {\n        complete: [\n          \"border-2 border-primary bg-primary text-primary-foreground\",\n          \"shadow-[0_0_0_4px_theme(colors.primary.DEFAULT/15%)]\",\n          \"group-hover:scale-110 group-hover:shadow-[0_0_0_6px_theme(colors.primary.DEFAULT/20%)]\",\n        ],\n        current: [\n          \"border-2 border-primary bg-background text-primary\",\n          \"shadow-[0_0_0_4px_theme(colors.primary.DEFAULT/20%)]\",\n        ],\n        upcoming: [\n          \"border-2 border-border bg-background text-muted-foreground\",\n        ],\n      },\n      size: {\n        sm: \"h-7 min-h-[44px] w-7 min-w-[44px] text-xs\",\n        md: \"h-9 min-h-[44px] w-9 min-w-[44px] text-sm\",\n        lg: \"h-11 min-h-[44px] w-11 min-w-[44px] text-base\",\n      },\n    },\n    defaultVariants: { status: \"upcoming\", size: \"md\" },\n  }\n)\n\nexport const stepConnectorVariants = cva(\n  \"block shrink-0 transition-all duration-500 ease-in-out\",\n  {\n    variants: {\n      orientation: {\n        horizontal: \"mt-0 h-0.5 w-full\",\n        vertical: \"mx-auto mt-2 mb-2 min-h-6 w-0.5\",\n      },\n      status: {\n        complete: \"bg-primary\",\n        current: \"bg-gradient-to-r from-primary to-border\",\n        upcoming: \"bg-border\",\n      },\n    },\n    compoundVariants: [\n      {\n        orientation: \"vertical\",\n        status: \"current\",\n        className: \"bg-gradient-to-b from-primary to-border\",\n      },\n    ],\n    defaultVariants: { orientation: \"horizontal\", status: \"upcoming\" },\n  }\n)\n\nexport const stepTitleVariants = cva(\n  \"block leading-tight font-semibold transition-colors duration-200\",\n  {\n    variants: {\n      orientation: {\n        horizontal: \"mt-3 max-w-28 px-1 text-center text-xs\",\n        vertical: \"ml-4 pt-1 text-start text-sm\",\n      },\n      status: {\n        complete: \"text-foreground\",\n        current: \"text-primary\",\n        upcoming: \"text-muted-foreground\",\n      },\n    },\n    defaultVariants: { orientation: \"horizontal\", status: \"upcoming\" },\n  }\n)\n\nexport const stepDescriptionVariants = cva(\n  \"mt-0.5 block text-xs leading-snug text-muted-foreground\",\n  {\n    variants: {\n      orientation: {\n        horizontal: \"max-w-30 text-center\",\n        vertical: \"ml-4 text-start\",\n      },\n    },\n    defaultVariants: { orientation: \"horizontal\" },\n  }\n)\n\n// ── Private subcomponents ──────────────────────────────────────────────────\n\nconst StepConnector = ({\n  orientation,\n  status,\n}: {\n  orientation: \"horizontal\" | \"vertical\"\n  status: \"complete\" | \"current\" | \"upcoming\"\n}) => (\n  <span\n    className={cn(stepConnectorVariants({ orientation, status }))}\n    aria-hidden=\"true\"\n    data-slot=\"step-progress-step-connector\"\n  />\n)\n\nconst StepProgressItem = ({\n  step,\n  index,\n  isLast,\n  status,\n  connectorStatus,\n  orientation,\n  size,\n  onStepClick,\n}: StepProgressItemProps) => {\n  const isInteractive = !!onStepClick\n  const ItemWrapper = isInteractive ? \"button\" : \"div\"\n\n  const content = (\n    <div\n      className={cn(\n        \"flex\",\n        orientation === \"horizontal\"\n          ? \"flex-col items-center\"\n          : \"w-full flex-row items-start\"\n      )}\n    >\n      <div className={cn(\"relative flex shrink-0 flex-col items-center\")}>\n        <div\n          className={cn(stepCircleVariants({ status, size }), \"z-10\")}\n          data-slot=\"step-progress-step-circle\"\n        >\n          {status === \"complete\" && !step.icon ? (\n            <Check\n              className={cn(\n                size === \"sm\" ? \"size-3\" : size === \"lg\" ? \"size-5\" : \"size-4\"\n              )}\n            />\n          ) : step.icon ? (\n            <span className=\"text-current\">{step.icon}</span>\n          ) : (\n            <span className=\"tabular-nums\">{index + 1}</span>\n          )}\n        </div>\n      </div>\n\n      <div\n        className={cn(\n          \"flex flex-col\",\n          orientation === \"horizontal\" ? \"items-center\" : \"items-start\"\n        )}\n      >\n        <span\n          className={cn(stepTitleVariants({ orientation, status }))}\n          data-slot=\"step-progress-step-title\"\n        >\n          {step.title}\n        </span>\n        {step.description && (\n          <span\n            className={cn(stepDescriptionVariants({ orientation }))}\n            data-slot=\"step-progress-step-description\"\n          >\n            {step.description}\n          </span>\n        )}\n      </div>\n    </div>\n  )\n\n  return (\n    <>\n      <li\n        className={cn(\n          \"group relative flex\",\n          orientation === \"horizontal\"\n            ? \"flex-col items-center\"\n            : \"w-full flex-col\"\n        )}\n        data-slot=\"step-progress-step\"\n      >\n        <ItemWrapper\n          type={isInteractive ? \"button\" : undefined}\n          onClick={isInteractive ? () => onStepClick?.(step.id) : undefined}\n          className={cn(\n            \"rounded-lg transition-all outline-none\",\n            isInteractive &&\n              \"min-h-[44px] min-w-[44px] cursor-pointer hover:opacity-80 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n            orientation === \"vertical\" && \"w-full text-left\"\n          )}\n          aria-current={status === \"current\" ? \"step\" : undefined}\n        >\n          {content}\n        </ItemWrapper>\n\n        {orientation === \"vertical\" && !isLast && (\n          <div\n            className={cn(\n              \"flex py-1\",\n              size === \"sm\" ? \"ml-3.5\" : size === \"lg\" ? \"ml-5.5\" : \"ml-4.5\"\n            )}\n          >\n            <StepConnector orientation=\"vertical\" status={connectorStatus} />\n          </div>\n        )}\n      </li>\n\n      {orientation === \"horizontal\" && !isLast && (\n        <li\n          role=\"presentation\"\n          className={cn(\n            \"flex min-w-8 flex-1 items-start\",\n            size === \"sm\" ? \"pt-3.5\" : size === \"lg\" ? \"pt-5.5\" : \"pt-4.5\"\n          )}\n          aria-hidden=\"true\"\n        >\n          <StepConnector orientation=\"horizontal\" status={connectorStatus} />\n        </li>\n      )}\n    </>\n  )\n}\n\n// ── StepProgress ───────────────────────────────────────────────────────────\n\nexport const StepProgress = ({\n  steps,\n  currentStepId,\n  orientation = \"horizontal\",\n  size,\n  onStepClick,\n  locale: localeProp,\n  className,\n  ...props\n}: StepProgressProps) => {\n  const locale = useUILocale(localeProp)\n  const currentStepIndex = React.useMemo(() => {\n    const idx = steps.findIndex((s) => s.id === currentStepId)\n    return idx === -1 ? 0 : idx\n  }, [steps, currentStepId])\n\n  if (!steps || steps.length === 0) return null\n\n  return (\n    <ol\n      aria-label={UI_I18N[locale].stepProgress.label}\n      className={cn(stepProgressVariants({ orientation }), className)}\n      data-slot=\"step-progress\"\n      {...props}\n    >\n      {steps.map((step, index) => {\n        const status: \"complete\" | \"current\" | \"upcoming\" =\n          index < currentStepIndex\n            ? \"complete\"\n            : index === currentStepIndex\n              ? \"current\"\n              : \"upcoming\"\n\n        const connectorStatus: \"complete\" | \"current\" | \"upcoming\" =\n          index + 1 < currentStepIndex\n            ? \"complete\"\n            : index + 1 === currentStepIndex\n              ? \"current\"\n              : \"upcoming\"\n\n        return (\n          <StepProgressItem\n            key={step.id}\n            step={step}\n            index={index}\n            isLast={index === steps.length - 1}\n            status={status}\n            connectorStatus={connectorStatus}\n            orientation={orientation || \"horizontal\"}\n            size={size || \"md\"}\n            onStepClick={onStepClick}\n          />\n        )\n      })}\n    </ol>\n  )\n}\n\nStepProgress.displayName = \"StepProgress\"\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}
