{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "wizard",
  "title": "Wizard",
  "author": "AlgorizeTech",
  "description": "A multi-step form flow with context-driven navigation, progress bar and completion callback. Reach for it when a form is long enough to need splitting across steps.",
  "dependencies": [],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/custom/blocks/WizardBlock.tsx",
      "content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport React, { forwardRef, useEffect, useRef, useState } from \"react\";\nimport { WizardContext, useWizard } from \"./wizard-context\";\n\n// ==========================================\n// MOTION\n// ==========================================\n/** GSAP's power3.out, sampled into a CSS `linear()` curve. */\nconst EASE_POWER3_OUT =\n  \"linear(0, .0963, .1855, .2679, .3439, .4138, .478, .5367, .5904, .6392, .6836, .7237, .7599, .7924, .8215, .8474, .8704, .8907, .9085, .924, .9375, .9491, .959, .9674, .9744, .9802, .985, .9888, .9919, .9943, .9961, .9974, .9984, .9991, .9995, .9998, .9999, 1, 1, 1, 1)\";\n\n/**\n * Settle an element's current style before its first change, so that change\n * transitions from where the element was painted.\n */\nconst settle = (el: HTMLElement, done: { current: boolean }) => {\n  if (done.current) return;\n  void el.offsetWidth;\n  done.current = true;\n};\n\n// ==========================================\n// COMPONENTS\n// ==========================================\n\nexport type WizardColor =\n  | \"primary\"\n  | \"indigo\"\n  | \"blue\"\n  | \"rose\"\n  | \"emerald\"\n  | \"zinc\"\n  | (string & {});\n\nexport interface WizardProps extends React.HTMLAttributes<HTMLDivElement> {\n  initialStep?: number;\n  color?: WizardColor;\n  onComplete?: () => void;\n}\n\nexport const Wizard = forwardRef<HTMLDivElement, WizardProps>(\n  (\n    {\n      children,\n      initialStep = 0,\n      color = \"primary\",\n      onComplete,\n      className,\n      ...props\n    },\n    ref,\n  ) => {\n    const [currentStep, setCurrentStep] = useState(initialStep);\n    const [totalSteps, setTotalSteps] = useState(0);\n\n    const nextStep = () => {\n      if (currentStep < totalSteps - 1) {\n        setCurrentStep((prev) => prev + 1);\n      } else if (onComplete) {\n        onComplete();\n      }\n    };\n\n    const prevStep = () => {\n      if (currentStep > 0) {\n        setCurrentStep((prev) => prev - 1);\n      }\n    };\n\n    return (\n      <WizardContext.Provider\n        value={{\n          currentStep,\n          totalSteps,\n          nextStep,\n          prevStep,\n          setTotalSteps,\n          color,\n        }}\n      >\n        <div\n          ref={ref}\n          className={cn(\"relative w-full flex flex-col\", className)}\n          {...props}\n        >\n          {children}\n        </div>\n      </WizardContext.Provider>\n    );\n  },\n);\nWizard.displayName = \"Wizard\";\n\nexport const WizardProgress = forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n  const { currentStep, totalSteps, color } = useWizard();\n  const progressRef = useRef<HTMLDivElement>(null);\n  const progressSettled = useRef(false);\n\n  // Calculate percentage (avoid division by zero)\n  const progress = totalSteps > 1 ? (currentStep / (totalSteps - 1)) * 100 : 0;\n\n  useEffect(() => {\n    const el = progressRef.current;\n    if (!el) return;\n    settle(el, progressSettled);\n    el.style.transition = `width 0.6s ${EASE_POWER3_OUT}`;\n    el.style.width = `${progress}%`;\n  }, [progress]);\n\n  // Tailwind color mapping\n  const isHex = color && color.startsWith(\"#\");\n  const colorMap: Record<string, string> = {\n    primary: \"bg-primary\",\n    indigo: \"bg-indigo-600 dark:bg-indigo-500\",\n    blue: \"bg-blue-600 dark:bg-blue-500\",\n    rose: \"bg-rose-600 dark:bg-rose-500\",\n    emerald: \"bg-emerald-600 dark:bg-emerald-500\",\n    zinc: \"bg-zinc-900 dark:bg-zinc-100\",\n  };\n\n  return (\n    <div\n      ref={ref}\n      className={cn(\"w-full h-1.5 bg-transparent overflow-hidden\", className)}\n      {...props}\n    >\n      <div\n        ref={progressRef}\n        className={cn(\"h-full w-0\", !isHex && (colorMap[color] || colorMap.primary))}\n        style={isHex ? { backgroundColor: color } : undefined}\n      />\n    </div>\n  );\n});\nWizardProgress.displayName = \"WizardProgress\";\n\nexport const WizardContainer = forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ children, className, ...props }, ref) => {\n  const { setTotalSteps } = useWizard();\n\n  useEffect(() => {\n    // Automatically count the number of WizardStep children\n    const stepCount = React.Children.toArray(children).filter(\n      (child) =>\n        React.isValidElement(child) &&\n        (child.type as { displayName?: string }).displayName === \"WizardStep\",\n    ).length;\n    setTotalSteps(stepCount);\n  }, [children, setTotalSteps]);\n\n  return (\n    <div\n      ref={ref}\n      className={cn(\n        \"relative w-full h-[500px] overflow-hidden bg-background\",\n        className,\n      )}\n      {...props}\n    >\n      {children}\n    </div>\n  );\n});\nWizardContainer.displayName = \"WizardContainer\";\n\nexport interface WizardStepProps extends React.HTMLAttributes<HTMLDivElement> {\n  index: number;\n}\n\nexport const WizardStep = forwardRef<HTMLDivElement, WizardStepProps>(\n  ({ children, index, className, ...props }, ref) => {\n    const { currentStep } = useWizard();\n    const stepRef = useRef<HTMLDivElement>(null);\n    const stepSettled = useRef(false);\n\n    React.useImperativeHandle(ref, () => stepRef.current as HTMLDivElement);\n\n    useEffect(() => {\n      const el = stepRef.current;\n      if (!el) return;\n\n      const isActive = index === currentStep;\n      const isPast = index < currentStep;\n\n      // Typeform style vertical scroll logic\n      let yOffset = 0;\n      if (isPast)\n        yOffset = -150; // Scrolled up\n      else if (index > currentStep) yOffset = 150; // Waiting below\n\n      // Slides and fades from wherever it is; pointer-events flips at once.\n      settle(el, stepSettled);\n      el.style.transition = `transform 0.7s ${EASE_POWER3_OUT}, opacity 0.7s ${EASE_POWER3_OUT}`;\n      el.style.transform = `translateY(${yOffset}px)`;\n      el.style.opacity = isActive ? \"1\" : \"0\";\n      el.style.pointerEvents = isActive ? \"auto\" : \"none\";\n    }, [currentStep, index]);\n\n    return (\n      <div\n        ref={stepRef}\n        className={cn(\n          \"absolute inset-0 w-full h-full flex flex-col justify-center px-6 md:px-12 lg:px-24 opacity-0 pointer-events-none\",\n          className,\n        )}\n        {...props}\n      >\n        <div className=\"w-full max-w-3xl mx-auto flex flex-col gap-6\">\n          {children}\n        </div>\n      </div>\n    );\n  },\n);\nWizardStep.displayName = \"WizardStep\";\n\nexport const WizardTitle = forwardRef<\n  HTMLHeadingElement,\n  React.HTMLAttributes<HTMLHeadingElement>\n>(({ children, className, ...props }, ref) => {\n  return (\n    <h2\n      ref={ref}\n      className={cn(\n        \"text-3xl sm:text-4xl md:text-5xl font-semibold tracking-tight text-foreground\",\n        className,\n      )}\n      {...props}\n    >\n      {children}\n    </h2>\n  );\n});\nWizardTitle.displayName = \"WizardTitle\";\n\nexport const WizardDescription = forwardRef<\n  HTMLParagraphElement,\n  React.HTMLAttributes<HTMLParagraphElement>\n>(({ children, className, ...props }, ref) => {\n  return (\n    <p\n      ref={ref}\n      className={cn(\n        \"text-lg sm:text-xl text-muted-foreground mt-2\",\n        className,\n      )}\n      {...props}\n    >\n      {children}\n    </p>\n  );\n});\nWizardDescription.displayName = \"WizardDescription\";\n\nexport const WizardInput = forwardRef<\n  HTMLInputElement,\n  React.InputHTMLAttributes<HTMLInputElement>\n>(({ className, ...props }, ref) => {\n  const { color } = useWizard();\n\n  const isHex = color && color.startsWith(\"#\");\n  const focusColors: Record<string, string> = {\n    primary: \"focus:border-primary/30\",\n    indigo: \"focus:border-indigo-500\",\n    blue: \"focus:border-blue-500\",\n    rose: \"focus:border-rose-500\",\n    emerald: \"focus:border-emerald-500\",\n    zinc: \"focus:border-zinc-500 dark:focus:border-zinc-400\",\n  };\n\n  return (\n    <input\n      ref={ref}\n      className={cn(\n        \"w-full bg-transparent border-b-2 border-border py-4 text-2xl sm:text-3xl text-foreground placeholder:text-muted-foreground/50 focus:outline-none transition-colors\",\n        !isHex && (focusColors[color] || focusColors.primary),\n        className,\n      )}\n      style={isHex ? { borderColor: color } : undefined}\n      {...props}\n    />\n  );\n});\nWizardInput.displayName = \"WizardInput\";\n\nexport const WizardNavigation = forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n  const { currentStep, nextStep, prevStep, color } = useWizard();\n\n  const isHex = color && color.startsWith(\"#\");\n  const btnColors: Record<string, string> = {\n    primary: \"bg-primary text-primary-foreground hover:opacity-90\",\n    indigo: \"bg-indigo-600 hover:bg-indigo-700 text-white\",\n    blue: \"bg-blue-600 hover:bg-blue-700 text-white\",\n    rose: \"bg-rose-600 hover:bg-rose-700 text-white\",\n    emerald: \"bg-emerald-600 hover:bg-emerald-700 text-white\",\n    zinc: \"bg-primary hover:bg-primary text-primary-foreground\",\n  };\n\n  return (\n    <div\n      ref={ref}\n      className={cn(\"flex items-center gap-4 mt-8\", className)}\n      {...props}\n    >\n      <button\n        type=\"button\"\n        onClick={nextStep}\n        className={cn(\n          \"px-6 py-3 rounded-xl font-semibold text-sm sm:text-base flex items-center gap-2 transition-all active:scale-95 shadow-sm\",\n          !isHex && (btnColors[color] || btnColors.primary),\n        )}\n        style={isHex ? { backgroundColor: color, color: \"#ffffff\" } : undefined}\n      >\n        OK{\" \"}\n        <span className=\"font-normal opacity-70 ml-2 hidden sm:inline\">\n          press Enter ↵\n        </span>\n      </button>\n      {currentStep > 0 && (\n        <button\n          type=\"button\"\n          onClick={prevStep}\n          className=\"px-4 py-3 rounded-xl text-sm font-semibold text-muted-foreground hover:bg-muted transition-colors\"\n        >\n          Back\n        </button>\n      )}\n    </div>\n  );\n});\nWizardNavigation.displayName = \"WizardNavigation\";\n",
      "type": "registry:component",
      "target": "components/custom/blocks/WizardBlock.tsx"
    },
    {
      "path": "src/components/custom/blocks/wizard-context.ts",
      "content": "\"use client\";\n\nimport { createContext, useContext } from \"react\";\n\ninterface WizardContextType {\n  currentStep: number;\n  totalSteps: number;\n  nextStep: () => void;\n  prevStep: () => void;\n  setTotalSteps: (steps: number) => void;\n  color: string;\n}\n\nexport const WizardContext = createContext<WizardContextType | null>(null);\n\nexport function useWizard() {\n  const context = useContext(WizardContext);\n  if (!context) {\n    throw new Error(\"Wizard components must be used within a Wizard root.\");\n  }\n  return context;\n}\n",
      "type": "registry:component",
      "target": "components/custom/blocks/wizard-context.ts"
    }
  ],
  "docs": "Named exports: Wizard, WizardProgress, WizardContainer, WizardStep, WizardTitle, WizardDescription, useWizard. Wizard owns the step state; children read `currentStep`, `nextStep` and `prevStep` from the useWizard hook. `onComplete` fires on the final step. Unlike `stepper`, this manages navigation for you.",
  "categories": [
    "forms",
    "navigation"
  ],
  "type": "registry:component"
}
