{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "quick-switcher",
  "type": "registry:component",
  "title": "Quick Switcher",
  "description": "A premium, dual-mode action bar that enables fast switching between two distinct modes with fluid animations and spring physics.",
  "dependencies": [
    "lucide-react",
    "motion"
  ],
  "files": [
    {
      "path": "components/watermelon/quick-switcher.tsx",
      "type": "registry:component",
      "content": "'use client';\n\nimport React, { useState, type ChangeEvent } from 'react';\nimport { motion, AnimatePresence, type Transition } from 'motion/react';\nimport { ArrowRight, ChevronUp, ChevronDown } from 'lucide-react';\n\nexport type QuickSwitcherMode = 'ask' | 'generate';\n\nexport interface QuickSwitcherProps {\n  defaultMode?: QuickSwitcherMode;\n  askIcon: React.ReactNode;\n  generateIcon: React.ReactNode;\n  askLabel?: string;\n  generateLabel?: string;\n  onActionClick?: (mode: QuickSwitcherMode) => void;\n}\n\nconst transition: Transition = {\n  type: 'spring',\n  stiffness: 300,\n  damping: 30,\n  mass: 0.8,\n};\n\nexport const QuickSwitcher: React.FC<QuickSwitcherProps> = ({\n  defaultMode = 'ask',\n  askIcon,\n  generateIcon,\n  askLabel = 'Ask Anything',\n  generateLabel = 'Generate Image',\n  onActionClick,\n}) => {\n  const [mode, setMode] = useState<QuickSwitcherMode>(defaultMode);\n  const [value, setValue] = useState<string>('');\n\n  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n    setValue(e.target.value);\n  };\n\n  const onSubmit = () => {\n    onActionClick?.(mode);\n  };\n  const toggleMode = () => {\n    setMode((prev) => (prev === 'ask' ? 'generate' : 'ask'));\n  };\n\n  return (\n    <motion.div\n      layout\n      className=\"flex h-[68px] min-w-[320px] items-center rounded-full border border-gray-200/50 bg-[#F2F2F2] p-1.5 shadow-sm sm:min-w-[380px] dark:border-neutral-800/50 dark:bg-neutral-900\"\n    >\n      <button\n        onClick={toggleMode}\n        className=\"group flex h-full items-center rounded-full bg-white pr-4 pl-2 shadow-sm transition-colors hover:bg-neutral-100 active:scale-95 dark:bg-neutral-800 dark:hover:bg-neutral-700\"\n      >\n        <div className=\"relative flex h-12 w-12 items-center justify-center overflow-hidden\">\n          <AnimatePresence mode=\"popLayout\" initial={false}>\n            <motion.div\n              key={mode}\n              initial={{ opacity: 0, filter: 'blur(4px)', scale: 0.5 }}\n              animate={{ opacity: 1, filter: 'blur(0px)', scale: 1 }}\n              exit={{ opacity: 0, filter: 'blur(4px)', scale: 0.5 }}\n              transition={transition}\n              className=\"flex items-center justify-center text-neutral-900 dark:text-neutral-100\"\n            >\n              {mode === 'ask' ? askIcon : generateIcon}\n            </motion.div>\n          </AnimatePresence>\n        </div>\n\n        <div className=\"ml-1 flex flex-col\">\n          <ChevronUp\n            size={14}\n            strokeWidth={4}\n            className={`transition-colors ${'text-neutral-300 dark:text-neutral-500'}`}\n          />\n          <ChevronDown\n            size={14}\n            strokeWidth={4}\n            className={`transition-colors ${'text-neutral-300 dark:text-neutral-500'}`}\n          />\n        </div>\n      </button>\n\n      <div className=\"relative flex h-full flex-grow items-center overflow-hidden px-4\">\n        <AnimatePresence mode=\"popLayout\" initial={false}>\n          {value.length <= 0 && (\n            <AnimatedText\n              text={mode === 'ask' ? askLabel : generateLabel}\n              className=\"pointer-events-none absolute top-1/2 left-4 z-10 -translate-y-1/2 truncate text-[18px] font-semibold whitespace-nowrap text-neutral-400 sm:text-[20px] dark:text-neutral-500\"\n            />\n          )}\n        </AnimatePresence>\n\n        <input\n          type=\"text\"\n          value={value}\n          onChange={handleChange}\n          className=\"w-full flex-1 border-none bg-transparent text-[18px] font-semibold text-neutral-900 placeholder-transparent ring-0 outline-none focus:ring-0 focus:outline-none sm:text-[20px] dark:text-neutral-100\"\n        />\n      </div>\n\n      <motion.button\n        whileHover={{ x: 2 }}\n        whileTap={{ scale: 0.9 }}\n        className=\"flex h-12 w-12 shrink-0 items-center justify-center rounded-full border border-gray-100 bg-white text-neutral-900 shadow-sm transition-colors hover:bg-neutral-100 active:bg-neutral-50 dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-100 dark:hover:bg-neutral-700 dark:active:bg-neutral-800\"\n        onClick={onSubmit}\n      >\n        <ArrowRight size={22} strokeWidth={2.5} />\n      </motion.button>\n    </motion.div>\n  );\n};\n\nfunction AnimatedText({\n  text,\n  className,\n  delayStep = 0.014,\n}: {\n  text: string;\n  className?: string;\n  delayStep?: number;\n}) {\n  const chars = text.split('');\n\n  return (\n    <span className={className} style={{ display: 'inline-flex' }}>\n      <AnimatePresence mode=\"popLayout\">\n        <motion.span\n          key={text}\n          style={{ display: 'inline-flex', willChange: 'transform' }}\n        >\n          {chars.map((char, i) => (\n            <motion.span\n              key={i}\n              initial={{\n                y: 10,\n                opacity: 0,\n                scale: 0.5,\n                filter: 'blur(2px)',\n              }}\n              animate={{\n                y: 0,\n                opacity: 1,\n                scale: 1,\n                filter: 'blur(0px)',\n              }}\n              exit={{\n                y: -10,\n                opacity: 0,\n                scale: 0.5,\n                filter: 'blur(2px)',\n              }}\n              transition={{\n                type: 'spring',\n                stiffness: 240,\n                damping: 16,\n                mass: 1.2,\n                delay: i * delayStep,\n              }}\n              style={{\n                display: 'inline-block',\n                whiteSpace: char === ' ' ? 'pre' : undefined,\n              }}\n            >\n              {char}\n            </motion.span>\n          ))}\n        </motion.span>\n      </AnimatePresence>\n    </span>\n  );\n}\n"
    }
  ]
}
