{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "vanish-input",
  "title": "Vanish Input",
  "description": "Search field whose placeholder cycles while empty.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/velora/vanish-input.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\n\nimport { cn } from \"@/lib/utils\";\n\ninterface VanishInputProps {\n  /** Cycled through while the field is empty */\n  placeholders: string[];\n  /** Seconds each placeholder is held */\n  interval?: number;\n  /** Accessible name for the input */\n  label?: string;\n  onSubmit?: (value: string) => void;\n  className?: string;\n}\n\n/**\n * Search or prompt field whose placeholder cycles while empty. Built on a real\n * `form` and `input`, so Enter, autofill and screen readers behave normally.\n * The cycling pauses on hover and focus, and stays on the first placeholder\n * under `prefers-reduced-motion`.\n */\nexport function VanishInput({\n  placeholders,\n  interval = 3,\n  label = \"Search\",\n  onSubmit,\n  className,\n}: VanishInputProps) {\n  const [index, setIndex] = useState(0);\n  const [value, setValue] = useState(\"\");\n  const [hovered, setHovered] = useState(false);\n  const [focused, setFocused] = useState(false);\n  const inputRef = useRef<HTMLInputElement>(null);\n  const reducedMotion = useReducedMotion();\n\n  useEffect(() => {\n    if (placeholders.length < 2 || value || reducedMotion || hovered || focused)\n      return;\n    const id = window.setInterval(\n      () => setIndex((i) => (i + 1) % placeholders.length),\n      interval * 1000\n    );\n    return () => window.clearInterval(id);\n  }, [placeholders.length, interval, value, reducedMotion, hovered, focused]);\n\n  const handleSubmit = (event: React.FormEvent) => {\n    event.preventDefault();\n    if (!value.trim()) return;\n    onSubmit?.(value);\n    setValue(\"\");\n    // Clearing disables the submit button, so keep focus in the field.\n    inputRef.current?.focus();\n  };\n\n  return (\n    <form\n      onSubmit={handleSubmit}\n      onMouseEnter={() => setHovered(true)}\n      onMouseLeave={() => setHovered(false)}\n      onFocus={() => setFocused(true)}\n      onBlur={(event) => {\n        if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {\n          setFocused(false);\n        }\n      }}\n      data-slot=\"vanish-input\"\n      className={cn(\n        \"relative flex h-12 w-full max-w-lg items-center rounded-full border bg-background pr-1.5 pl-5 transition-shadow focus-within:ring-2 focus-within:ring-ring\",\n        className\n      )}\n    >\n      <input\n        ref={inputRef}\n        value={value}\n        onChange={(event) => setValue(event.target.value)}\n        aria-label={label}\n        className=\"peer h-full flex-1 bg-transparent text-sm outline-none\"\n      />\n\n      {/* Visual only — the input keeps its own accessible label. */}\n      {!value && (\n        <span\n          aria-hidden\n          className=\"pointer-events-none absolute left-5 flex h-full items-center overflow-hidden text-sm text-muted-foreground\"\n        >\n          <AnimatePresence mode=\"wait\" initial={false}>\n            <motion.span\n              key={index}\n              initial={{ opacity: 0, y: 8 }}\n              animate={{ opacity: 1, y: 0 }}\n              exit={{ opacity: 0, y: -8 }}\n              transition={{ duration: reducedMotion ? 0 : 0.25 }}\n              className=\"block\"\n            >\n              {placeholders[index]}\n            </motion.span>\n          </AnimatePresence>\n        </span>\n      )}\n\n      <button\n        type=\"submit\"\n        aria-label=\"Submit\"\n        disabled={!value.trim()}\n        className=\"grid size-9 shrink-0 place-items-center rounded-full bg-primary text-primary-foreground transition-opacity disabled:opacity-40\"\n      >\n        <svg\n          width=\"16\"\n          height=\"16\"\n          viewBox=\"0 0 16 16\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          strokeWidth=\"1.75\"\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n          aria-hidden\n        >\n          <path d=\"M3 8h9M8.5 4l4 4-4 4\" />\n        </svg>\n      </button>\n    </form>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/velora/vanish-input.tsx"
    }
  ],
  "type": "registry:ui"
}