{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ai-02",
  "type": "registry:block",
  "title": "AI Chat with Model Selection",
  "description": "A ai chat with model selection block.",
  "author": "ephraim duncan <https://ephraimduncan.com>",
  "registryDependencies": [
    "button",
    "select",
    "textarea"
  ],
  "dependencies": [
    "@tabler/icons-react"
  ],
  "files": [
    {
      "path": "content/components/ai/ai-02.tsx",
      "type": "registry:component",
      "target": "components/ai-02.tsx",
      "content": "\"use client\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"@/components/ui/select\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  IconAlertTriangle,\n  IconArrowUp,\n  IconCloud,\n  IconFileSpark,\n  IconGauge,\n  IconPhotoScan,\n} from \"@tabler/icons-react\";\nimport { useRef, useState } from \"react\";\n\nconst PROMPTS = [\n  {\n    icon: IconFileSpark,\n    text: \"Write documentation\",\n    prompt:\n      \"Write comprehensive documentation for this codebase, including setup instructions, API references, and usage examples.\",\n  },\n  {\n    icon: IconGauge,\n    text: \"Optimize performance\",\n    prompt:\n      \"Analyze the codebase for performance bottlenecks and suggest optimizations to improve loading times and runtime efficiency.\",\n  },\n  {\n    icon: IconAlertTriangle,\n    text: \"Find and fix 3 bugs\",\n    prompt:\n      \"Scan through the codebase to identify and fix 3 critical bugs, providing detailed explanations for each fix.\",\n  },\n];\n\nconst MODELS = [\n  {\n    value: \"gpt-5\",\n    name: \"GPT-5\",\n    description: \"Most advanced model\",\n    max: true,\n  },\n  {\n    value: \"gpt-4o\",\n    name: \"GPT-4o\",\n    description: \"Fast and capable\",\n  },\n  {\n    value: \"gpt-4\",\n    name: \"GPT-4\",\n    description: \"Reliable and accurate\",\n  },\n  {\n    value: \"claude-3.5\",\n    name: \"Claude 3.5 Sonnet\",\n    description: \"Great for coding tasks\",\n  },\n];\n\nexport default function Ai02() {\n  const [inputValue, setInputValue] = useState(\"\");\n  const [selectedModel, setSelectedModel] = useState(MODELS[0]);\n  const inputRef = useRef<HTMLTextAreaElement>(null);\n\n  const handlePromptClick = (prompt: string) => {\n    if (inputRef.current) {\n      inputRef.current.value = prompt;\n      setInputValue(prompt);\n      inputRef.current.focus();\n    }\n  };\n\n  const handleModelChange = (value: string) => {\n    const model = MODELS.find((m) => m.value === value);\n    if (model) {\n      setSelectedModel(model);\n    }\n  };\n\n  const renderMaxBadge = () => (\n    <div className=\"flex h-[14px] items-center gap-1.5 rounded border border-border px-1 py-0\">\n      <span\n        className=\"text-[9px] font-bold uppercase\"\n        style={{\n          background:\n            \"linear-gradient(to right, rgb(129, 161, 193), rgb(125, 124, 155))\",\n          WebkitBackgroundClip: \"text\",\n          WebkitTextFillColor: \"transparent\",\n        }}\n      >\n        MAX\n      </span>\n    </div>\n  );\n\n  return (\n    <div className=\"flex flex-col gap-4 w-[calc(42rem-5rem)]\">\n      <div className=\"flex min-h-[120px] flex-col rounded-2xl cursor-text bg-card border border-border shadow-lg\">\n        <div className=\"flex-1 relative overflow-y-auto max-h-[258px]\">\n          <Textarea\n            ref={inputRef}\n            value={inputValue}\n            onChange={(e) => setInputValue(e.target.value)}\n            placeholder=\"Ask anything\"\n            className=\"w-full border-0 p-3 transition-[padding] duration-200 ease-in-out min-h-[48.4px] outline-none text-[16px] text-foreground resize-none shadow-none focus-visible:ring-0 focus-visible:ring-offset-0 bg-transparent! whitespace-pre-wrap break-words\"\n          />\n        </div>\n\n        <div className=\"flex min-h-[40px] items-center gap-2 p-2 pb-1\">\n          <div className=\"flex aspect-1 items-center gap-1 rounded-full bg-muted p-1.5 text-xs\">\n            <IconCloud className=\"h-4 w-4 text-muted-foreground\" />\n          </div>\n\n          <div className=\"relative flex items-center\">\n            <Select\n              value={selectedModel.value}\n              onValueChange={handleModelChange}\n            >\n              <SelectTrigger className=\"w-fit border-none bg-transparent! p-0 text-sm text-muted-foreground hover:text-foreground focus:ring-0 shadow-none\">\n                <SelectValue>\n                  {selectedModel.max ? (\n                    <div className=\"flex items-center gap-1\">\n                      <span>{selectedModel.name}</span>\n                      {renderMaxBadge()}\n                    </div>\n                  ) : (\n                    <span>{selectedModel.name}</span>\n                  )}\n                </SelectValue>\n              </SelectTrigger>\n              <SelectContent>\n                {MODELS.map((model) => (\n                  <SelectItem key={model.value} value={model.value}>\n                    {model.max ? (\n                      <div className=\"flex items-center gap-1\">\n                        <span>{model.name}</span>\n                        {renderMaxBadge()}\n                      </div>\n                    ) : (\n                      <span>{model.name}</span>\n                    )}\n                    <span className=\"text-muted-foreground block text-xs\">\n                      {model.description}\n                    </span>\n                  </SelectItem>\n                ))}\n              </SelectContent>\n            </Select>\n          </div>\n\n          <div className=\"ml-auto flex items-center gap-3\">\n            <Button\n              variant=\"ghost\"\n              size=\"icon-sm\"\n              className=\"text-muted-foreground hover:text-foreground transition-colors duration-100 ease-out\"\n              title=\"Attach images\"\n              aria-label=\"Attach images\"\n            >\n              <IconPhotoScan className=\"h-5 w-5\" />\n            </Button>\n\n            <Button\n              variant=\"ghost\"\n              size=\"icon-sm\"\n              className={cn(\n                \"rounded-full transition-colors duration-100 ease-out cursor-pointer bg-primary\",\n                inputValue && \"bg-primary hover:bg-primary/90!\"\n              )}\n              disabled={!inputValue}\n              aria-label=\"Send message\"\n            >\n              <IconArrowUp className=\"h-4 w-4 text-primary-foreground\" />\n            </Button>\n          </div>\n        </div>\n      </div>\n\n      <div className=\"flex flex-wrap justify-center gap-2\">\n        {PROMPTS.map((button) => {\n          const IconComponent = button.icon;\n          return (\n            <Button\n              key={button.text}\n              variant=\"ghost\"\n              className=\"group flex items-center gap-2 rounded-full border px-3 py-2 text-sm text-foreground transition-colors duration-200 ease-out hover:bg-muted/30 h-auto bg-transparent dark:bg-muted\"\n              onClick={() => handlePromptClick(button.prompt)}\n            >\n              <IconComponent className=\"h-4 w-4 text-muted-foreground transition-colors group-hover:text-foreground\" />\n              <span>{button.text}</span>\n            </Button>\n          );\n        })}\n      </div>\n    </div>\n  );\n}\n"
    }
  ],
  "categories": [
    "ai"
  ]
}