{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "progressive-input-stack",
  "type": "registry:component",
  "title": "Progressive Input Stack",
  "description": "An animated input stack that progressively layers form fields as users complete each step.",
  "dependencies": [
    "lucide-react",
    "motion",
    "react-icons"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "components/watermelon/progressive-input-stack.tsx",
      "type": "registry:component",
      "content": "import React, { useState } from 'react';\nimport { motion, AnimatePresence } from 'motion/react';\nimport { ArrowRight, ArrowLeft } from 'lucide-react';\nimport { FaCheck } from 'react-icons/fa6';\nimport { cn } from '@/lib/utils';\n\nexport interface StepData {\n  id: string;\n  label: string;\n  type: 'text' | 'toggle';\n  placeholder?: string;\n}\n\ninterface ProgressiveInputStackProps {\n  steps: StepData[];\n  initialData?: Record<string, string | boolean>;\n  onSubmit?: (data: Record<string, string | boolean>) => void;\n}\n\nexport const ProgressiveInputStack: React.FC<ProgressiveInputStackProps> = ({\n  steps,\n  initialData,\n  onSubmit,\n}) => {\n  const [currentStep, setCurrentStep] = useState(0);\n\n  const [formData, setFormData] = useState<Record<string, string | boolean>>(\n    initialData ||\n      steps.reduce(\n        (acc, step) => ({\n          ...acc,\n          [step.id]: step.type === 'toggle' ? false : '',\n        }),\n        {},\n      ),\n  );\n\n  const springTransition = {\n    type: 'spring' as const,\n    stiffness: 800,\n    damping: 45,\n    mass: 2,\n  };\n\n  const handleNext = () => {\n    if (currentStep < steps.length - 1) {\n      setCurrentStep((prev) => prev + 1);\n    } else {\n      onSubmit?.(formData);\n    }\n  };\n\n  const handleBack = () => {\n    if (currentStep > 0) {\n      setCurrentStep((prev) => prev - 1);\n    }\n  };\n\n  const updateField = (id: string, value: string | boolean) => {\n    setFormData((prev) => ({ ...prev, [id]: value }));\n  };\n\n  return (\n    <div className=\"relative flex w-xs flex-col gap-8 sm:w-sm\">\n      <div className=\"relative h-[60px] w-full\">\n        <AnimatePresence mode=\"popLayout\" initial={false}>\n          {steps.map((step, index) => {\n            if (index > currentStep) return null;\n\n            const position = currentStep - index;\n            const isTop = index === currentStep;\n\n            return (\n              <motion.div\n                key={step.id}\n                initial={{ opacity: 0, scale: 1.2, y: 15, z: steps.length }}\n                animate={{\n                  opacity: 1,\n                  scale: 1 - position * 0.05,\n                  y: -position * 12,\n                  z: steps.length - position,\n                }}\n                exit={{\n                  opacity: 0,\n                  scale: 1.2,\n                  y: 15,\n                }}\n                transition={springTransition}\n                className={cn(\n                  'absolute inset-0 flex h-[60px] items-center rounded-2xl border border-[#E9E8EE] bg-white px-4 shadow-sm transition-colors dark:border-zinc-700 dark:bg-zinc-900',\n                  !isTop && 'pointer-events-none opacity-50',\n                )}\n              >\n                {step.type === 'text' && (\n                  <input\n                    autoFocus={isTop}\n                    type=\"text\"\n                    value={formData[step.id] as string}\n                    onChange={(e) => updateField(step.id, e.target.value)}\n                    placeholder={step.placeholder}\n                    className=\"w-full bg-transparent text-lg font-semibold text-[#242426] outline-none placeholder:text-[#85858B]/70 dark:text-zinc-200 dark:placeholder:text-zinc-500\"\n                  />\n                )}\n\n                {step.type === 'toggle' && (\n                  <div className=\"flex w-full items-center gap-4\">\n                    <span className=\"min-w-0 flex-1 truncate text-lg font-semibold text-[#85858B] dark:text-zinc-400\">\n                      {step.label}\n                    </span>\n\n                    <button\n                      onClick={() => updateField(step.id, !formData[step.id])}\n                      className={cn(\n                        'relative flex h-7 w-12 shrink-0 items-center rounded-full p-1 transition-colors',\n                        formData[step.id]\n                          ? 'bg-black dark:bg-zinc-200'\n                          : 'bg-zinc-200 dark:bg-zinc-800',\n                      )}\n                    >\n                      <motion.div\n                        animate={{\n                          x: formData[step.id] ? 20 : 0,\n                        }}\n                        transition={springTransition}\n                        className=\"h-5 w-5 rounded-full bg-white shadow\"\n                      />\n                    </button>\n                  </div>\n                )}\n              </motion.div>\n            );\n          })}\n        </AnimatePresence>\n      </div>\n\n      <div className=\"flex items-center\">\n        <AnimatePresence>\n          {currentStep > 0 && (\n            <motion.button\n              initial={{ opacity: 0, scale: 0.9 }}\n              animate={{ opacity: 1, scale: 1 }}\n              exit={{ opacity: 0, scale: 0.9 }}\n              onClick={handleBack}\n              transition={{\n                duration: 0.2,\n                ease: 'easeOut',\n              }}\n              className=\"flex items-center justify-center rounded-full bg-zinc-200 p-4 transition hover:bg-zinc-300 dark:bg-zinc-800 dark:hover:bg-zinc-700\"\n            >\n              <ArrowLeft size={24} />\n            </motion.button>\n          )}\n        </AnimatePresence>\n\n        <motion.button\n          onClick={handleNext}\n          className=\"ml-auto flex h-12 items-center gap-2 overflow-hidden rounded-full bg-black px-5 font-semibold text-white transition hover:opacity-90 dark:bg-zinc-200 dark:text-black\"\n        >\n          <AnimatePresence mode=\"popLayout\" initial={false}>\n            {currentStep === steps.length - 1 ? (\n              <motion.div\n                key=\"done\"\n                initial={{ y: 20, opacity: 0, filter: 'blur(4px)' }}\n                animate={{ y: 0, opacity: 1, filter: 'blur(0px)' }}\n                exit={{ y: -20, opacity: 0, filter: 'blur(4px)' }}\n                transition={{\n                  duration: 0.2,\n                  ease: 'easeOut',\n                }}\n                className=\"flex items-center gap-2\"\n              >\n                <FaCheck size={18} />\n                Done\n              </motion.div>\n            ) : (\n              <motion.div\n                key=\"next\"\n                initial={{ y: 20, opacity: 0, filter: 'blur(4px)' }}\n                animate={{ y: 0, opacity: 1, filter: 'blur(0px)' }}\n                exit={{ y: -20, opacity: 0, filter: 'blur(4px)' }}\n                transition={{\n                  duration: 0.2,\n                  ease: 'easeOut',\n                }}\n                className=\"flex items-center gap-2\"\n              >\n                Next\n                <ArrowRight size={18} />\n              </motion.div>\n            )}\n          </AnimatePresence>\n        </motion.button>\n      </div>\n    </div>\n  );\n};\n"
    }
  ]
}
