{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "progressive-input-stack-base",
  "type": "registry:component",
  "title": "Progressive Input Stack (base)",
  "description": "Theme-ready base variant of 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                  'border-border bg-card absolute inset-0 flex h-[60px] items-center rounded-lg border px-4 shadow-sm transition-colors',\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=\"text-foreground placeholder:text-muted-foreground/70 w-full bg-transparent text-lg font-semibold outline-none\"\n                  />\n                )}\n\n                {step.type === 'toggle' && (\n                  <div className=\"flex w-full items-center gap-4\">\n                    <span className=\"text-muted-foreground min-w-0 flex-1 truncate text-lg font-semibold\">\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-lg p-1 transition-colors',\n                        formData[step.id]\n                          ? 'bg-foreground'\n                          : 'bg-foreground/50',\n                      )}\n                    >\n                      <motion.div\n                        animate={{\n                          x: formData[step.id] ? 20 : 0,\n                        }}\n                        transition={springTransition}\n                        className=\"bg-background h-5 w-5 rounded-lg 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=\"bg-muted hover:bg-accent flex items-center justify-center rounded-lg p-4 transition\"\n            >\n              <ArrowLeft size={24} />\n            </motion.button>\n          )}\n        </AnimatePresence>\n\n        <motion.button\n          onClick={handleNext}\n          className=\"bg-primary text-primary-foreground ml-auto flex h-12 items-center gap-2 overflow-hidden rounded-lg px-5 font-semibold transition hover:opacity-90\"\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"
    }
  ]
}
