{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "sf-stepper", "title": "SF Stepper", "description": "Vertical multi-step flow with SFProgress connectors and per-step error state", "dependencies": [ "gsap", "lucide-react" ], "registryDependencies": [], "files": [ { "path": "components/sf/sf-stepper.tsx", "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Check, AlertCircle } from \"lucide-react\";\nimport { SFProgress } from \"./sf-progress\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * SFStepper -- SIGNAL layer vertical multi-step flow component.\n *\n * Renders a vertical sequence of steps with SFProgress connectors\n * between them. Each step has a status indicator (square, not circle)\n * and optional label/description. Connectors use actual SFProgress\n * instances for GSAP-driven fill animation.\n *\n * @param activeStep - Zero-based index of the current active step\n * @param children - SFStep elements\n * @param className - Additional classes on root container\n *\n * @example\n * \n * \n * \n * \n * \n *\n * \n * \n * \n * \n * \n */\n\ntype StepStatus = \"pending\" | \"active\" | \"complete\" | \"error\";\n\ninterface SFStepperProps {\n activeStep: number;\n children: React.ReactNode;\n className?: string;\n}\n\ninterface SFStepProps {\n status?: StepStatus;\n label?: string;\n description?: string;\n children?: React.ReactNode;\n className?: string;\n}\n\nfunction getConnectorValue(status: StepStatus): number {\n switch (status) {\n case \"complete\":\n return 100;\n case \"active\":\n return 50;\n case \"error\":\n return 100;\n case \"pending\":\n default:\n return 0;\n }\n}\n\nfunction SFStepper({ activeStep: _activeStep, children, className }: SFStepperProps) {\n const steps = React.Children.toArray(children);\n\n return (\n \n {steps.map((step, index) => {\n const isLast = index === steps.length - 1;\n const stepElement = step as React.ReactElement;\n const status = stepElement.props?.status ?? \"pending\";\n\n return (\n \n {step}\n {!isLast && (\n
\n \n
\n )}\n
\n );\n })}\n \n );\n}\n\nfunction SFStep({\n status = \"pending\",\n label,\n description,\n children,\n className,\n}: SFStepProps) {\n return (\n \n {/* Step indicator -- square, not circle */}\n \n {status === \"complete\" && }\n {status === \"error\" && }\n {(status === \"active\" || status === \"pending\") && null}\n \n\n {/* Step content */}\n
\n {label && (\n \n {label}\n \n )}\n {description && (\n \n {description}\n \n )}\n {children}\n
\n \n );\n}\n\nexport { SFStepper, SFStep };\nexport type { StepStatus, SFStepperProps, SFStepProps };\n", "type": "registry:ui" } ], "meta": { "layer": "signal", "pattern": "C" }, "type": "registry:ui" }