{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ai-composer",
  "type": "registry:ui",
  "title": "Ai composer",
  "description": "Chat input for AI apps with a multiline textarea, Enter to send, suggestion chips, attach button, model picker and a stop button while a response streams.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "https://ui.minidev.pro/r/icon-button.json",
    "https://ui.minidev.pro/r/model-picker.json",
    "https://ui.minidev.pro/r/suggestion-chips.json",
    "utils"
  ],
  "files": [
    {
      "path": "registry/ui/ai-composer.tsx",
      "type": "registry:ui",
      "target": "components/ui/ai-composer.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { ArrowUpIcon, PaperclipIcon, SquareIcon } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\nimport { IconButton } from \"@/components/ui/icon-button\"\nimport { ModelPicker } from \"@/components/ui/model-picker\"\nimport { SuggestionChips } from \"@/components/ui/suggestion-chips\"\n\nconst DEFAULT_MODELS = [\n  { id: \"gpt\", label: \"GPT\" },\n  { id: \"claude\", label: \"Claude\" },\n  { id: \"gemini\", label: \"Gemini\" },\n]\n\nfunction AiComposer({\n  value,\n  onChange,\n  onSubmit,\n  onStop,\n  streaming,\n  suggestions,\n  models = DEFAULT_MODELS,\n  model,\n  onModelChange,\n  className,\n}: {\n  value?: string\n  onChange?: (v: string) => void\n  onSubmit?: () => void\n  onStop?: () => void\n  streaming?: boolean\n  suggestions?: string[]\n  models?: { id: string; label: string }[]\n  model?: string\n  onModelChange?: (v: string) => void\n  className?: string\n}) {\n  return (\n    <div data-slot=\"ai-composer\" className={cn(\"space-y-2 rounded-2xl border border-border bg-surface p-3 shadow-highlight\", className)}>\n      {suggestions?.length ? (\n        <SuggestionChips items={suggestions} onSelect={(s) => onChange?.(s)} />\n      ) : null}\n      <textarea\n        aria-label=\"Message\"\n        rows={3}\n        value={value}\n        placeholder=\"Ask anything…\"\n        className=\"w-full resize-none bg-transparent text-sm text-fg outline-none placeholder:text-fg-muted\"\n        onChange={(e) => onChange?.(e.target.value)}\n        onKeyDown={(e) => {\n          if (e.key === \"Enter\" && !e.shiftKey) {\n            e.preventDefault()\n            onSubmit?.()\n          }\n        }}\n      />\n      <div className=\"flex items-center justify-between gap-2\">\n        <div className=\"flex items-center gap-1\">\n          <IconButton type=\"button\" size=\"icon-sm\" variant=\"ghost\" aria-label=\"Attach\"><PaperclipIcon /></IconButton>\n          <ModelPicker models={models} value={model} onChange={onModelChange} className=\"w-36\" />\n        </div>\n        {streaming ? (\n          <IconButton type=\"button\" size=\"icon\" variant=\"outline\" aria-label=\"Stop\" onClick={onStop}><SquareIcon /></IconButton>\n        ) : (\n          <IconButton type=\"button\" size=\"icon\" aria-label=\"Send\" onClick={onSubmit} disabled={!value?.trim()}><ArrowUpIcon /></IconButton>\n        )}\n      </div>\n    </div>\n  )\n}\nexport { AiComposer }\n"
    }
  ]
}
