{
  "name": "ai-input-search",
  "type": "registry:component",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "textarea"
  ],
  "files": [
    {
      "type": "registry:component",
      "content": "\"use client\";\n\n/**\n * @author: @kokonutui\n * @description: AI Input Search\n * @version: 1.0.0\n * @date: 2025-06-26\n * @license: MIT\n * @website: https://kokonutui.com\n * @github: https://github.com/kokonut-labs/kokonutui\n */\n\nimport { Globe, Paperclip, Send } from \"lucide-react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { useState } from \"react\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { useAutoResizeTextarea } from \"@/hooks/use-auto-resize-textarea\";\nimport { cn } from \"@/lib/utils\";\n\ninterface AIInputSearchProps {\n  placeholder?: string;\n  searchLabel?: string;\n  onSubmit?: (value: string) => void;\n  className?: string;\n}\n\nexport default function AI_Input_Search({\n  placeholder = \"Search the web...\",\n  searchLabel = \"Search\",\n  onSubmit,\n  className,\n}: AIInputSearchProps) {\n  const [value, setValue] = useState(\"\");\n  const { textareaRef, adjustHeight } = useAutoResizeTextarea({\n    minHeight: 52,\n    maxHeight: 200,\n  });\n  const [showSearch, setShowSearch] = useState(true);\n  const [isFocused, setIsFocused] = useState(false);\n\n  const handleSubmit = () => {\n    onSubmit?.(value);\n    setValue(\"\");\n    adjustHeight(true);\n  };\n\n  const handleFocus = () => {\n    setIsFocused(true);\n  };\n\n  const handleBlur = () => {\n    setIsFocused(false);\n  };\n\n  const handleContainerClick = () => {\n    if (textareaRef.current) {\n      textareaRef.current.focus();\n    }\n  };\n\n  return (\n    <div className={cn(\"w-full py-4\", className)}>\n      <div className=\"relative mx-auto w-full max-w-xl\">\n        <div\n          aria-label=\"Search input container\"\n          className={cn(\n            \"relative flex w-full cursor-text flex-col rounded-xl text-left transition-all duration-200\",\n            \"ring-1 ring-black/10 dark:ring-white/10\",\n            isFocused && \"ring-black/20 dark:ring-white/20\"\n          )}\n          onClick={handleContainerClick}\n          onKeyDown={(e) => {\n            if (e.key === \"Enter\" || e.key === \" \") {\n              handleContainerClick();\n            }\n          }}\n          role=\"textbox\"\n          tabIndex={0}\n        >\n          <div className=\"max-h-[200px] overflow-y-auto\">\n            <Textarea\n              className=\"w-full resize-none rounded-xl rounded-b-none border-none bg-black/5 px-4 py-3 leading-[1.2] placeholder:text-black/70 focus-visible:ring-0 dark:bg-white/5 dark:text-white dark:placeholder:text-white/70\"\n              id=\"ai-input-04\"\n              onBlur={handleBlur}\n              onChange={(e) => {\n                setValue(e.target.value);\n                adjustHeight();\n              }}\n              onFocus={handleFocus}\n              onKeyDown={(e) => {\n                if (e.key === \"Enter\" && !e.shiftKey) {\n                  e.preventDefault();\n                  handleSubmit();\n                }\n              }}\n              placeholder={placeholder}\n              ref={textareaRef}\n              value={value}\n            />\n          </div>\n\n          <div className=\"h-12 rounded-b-xl bg-black/5 dark:bg-white/5\">\n            <div className=\"absolute bottom-3 left-3 flex items-center gap-2\">\n              <label className=\"cursor-pointer rounded-lg bg-black/5 p-2 dark:bg-white/5\">\n                <input className=\"hidden\" type=\"file\" />\n                <Paperclip className=\"h-4 w-4 text-black/40 transition-colors hover:text-black dark:text-white/40 dark:hover:text-white\" />\n              </label>\n              <button\n                className={cn(\n                  \"flex h-8 cursor-pointer items-center gap-2 rounded-full border px-1.5 py-1 transition-all\",\n                  showSearch\n                    ? \"border-sky-400 bg-sky-500/15 text-sky-500\"\n                    : \"border-transparent bg-black/5 text-black/40 hover:text-black dark:bg-white/5 dark:text-white/40 dark:hover:text-white\"\n                )}\n                onClick={() => {\n                  setShowSearch(!showSearch);\n                }}\n                type=\"button\"\n              >\n                <div className=\"flex h-4 w-4 shrink-0 items-center justify-center\">\n                  <motion.div\n                    animate={{\n                      rotate: showSearch ? 180 : 0,\n                      scale: showSearch ? 1.1 : 1,\n                    }}\n                    transition={{\n                      type: \"spring\",\n                      stiffness: 260,\n                      damping: 25,\n                    }}\n                    whileHover={{\n                      rotate: showSearch ? 180 : 15,\n                      scale: 1.1,\n                      transition: {\n                        type: \"spring\",\n                        stiffness: 300,\n                        damping: 10,\n                      },\n                    }}\n                  >\n                    <Globe\n                      className={cn(\n                        \"h-4 w-4\",\n                        showSearch ? \"text-sky-500\" : \"text-inherit\"\n                      )}\n                    />\n                  </motion.div>\n                </div>\n                <AnimatePresence>\n                  {showSearch && (\n                    <motion.span\n                      animate={{\n                        width: \"auto\",\n                        opacity: 1,\n                      }}\n                      className=\"shrink-0 overflow-hidden whitespace-nowrap text-sky-500 text-sm\"\n                      exit={{ width: 0, opacity: 0 }}\n                      initial={{ width: 0, opacity: 0 }}\n                      transition={{ duration: 0.2 }}\n                    >\n                      {searchLabel}\n                    </motion.span>\n                  )}\n                </AnimatePresence>\n              </button>\n            </div>\n            <div className=\"absolute right-3 bottom-3\">\n              <button\n                className={cn(\n                  \"rounded-lg p-2 transition-colors\",\n                  value\n                    ? \"bg-sky-500/15 text-sky-500\"\n                    : \"cursor-pointer bg-black/5 text-black/40 hover:text-black dark:bg-white/5 dark:text-white/40 dark:hover:text-white\"\n                )}\n                onClick={handleSubmit}\n                type=\"button\"\n              >\n                <Send className=\"h-4 w-4\" />\n              </button>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n",
      "path": "/components/kokonutui/ai-input-search.tsx",
      "target": "components/kokonutui/ai-input-search.tsx"
    },
    {
      "type": "registry:hook",
      "content": "import { useCallback, useEffect, useRef } from \"react\";\n\ninterface UseAutoResizeTextareaProps {\n  minHeight: number;\n  maxHeight?: number;\n}\n\nexport function useAutoResizeTextarea({\n  minHeight,\n  maxHeight,\n}: UseAutoResizeTextareaProps) {\n  const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n  const adjustHeight = useCallback(\n    (reset?: boolean) => {\n      const textarea = textareaRef.current;\n      if (!textarea) return;\n\n      if (reset) {\n        textarea.style.height = `${minHeight}px`;\n        return;\n      }\n\n      // Temporarily shrink to get the right scrollHeight\n      textarea.style.height = `${minHeight}px`;\n\n      // Calculate new height\n      const newHeight = Math.max(\n        minHeight,\n        Math.min(textarea.scrollHeight, maxHeight ?? Number.POSITIVE_INFINITY)\n      );\n\n      textarea.style.height = `${newHeight}px`;\n    },\n    [minHeight, maxHeight]\n  );\n\n  useEffect(() => {\n    // Set initial height\n    const textarea = textareaRef.current;\n    if (textarea) {\n      textarea.style.height = `${minHeight}px`;\n    }\n  }, [minHeight]);\n\n  // Adjust height on window resize\n  useEffect(() => {\n    const handleResize = () => adjustHeight();\n    window.addEventListener(\"resize\", handleResize);\n    return () => window.removeEventListener(\"resize\", handleResize);\n  }, [adjustHeight]);\n\n  return { textareaRef, adjustHeight };\n}\n",
      "path": "/hooks/use-auto-resize-textarea.ts",
      "target": "hooks/use-auto-resize-textarea.ts"
    }
  ]
}