{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ai-05",
  "type": "registry:block",
  "title": "AI Elements Chat",
  "description": "A ai elements chat block.",
  "author": "ephraim duncan <https://ephraimduncan.com>",
  "registryDependencies": [
    "badge",
    "button"
  ],
  "dependencies": [
    "@tabler/icons-react",
    "ai"
  ],
  "files": [
    {
      "path": "content/components/ai/ai-05.tsx",
      "type": "registry:component",
      "target": "components/ai-05.tsx",
      "content": "'use client';\n\n// Install AI Elements components:\n// npx ai-elements@latest add conversation message prompt-input\n\nimport {\n  IconAdjustmentsHorizontal,\n  IconBolt,\n  IconMessageCircle,\n  IconPaperclip,\n  IconRefresh,\n  IconSparkles,\n} from '@tabler/icons-react';\nimport type { ChatStatus } from 'ai';\nimport { useEffect, useRef, useState } from 'react';\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from '@/components/ai-elements/conversation';\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from '@/components/ai-elements/message';\nimport {\n  PromptInput,\n  PromptInputButton,\n  PromptInputFooter,\n  PromptInputSubmit,\n  PromptInputTextarea,\n  PromptInputTools,\n} from '@/components/ai-elements/prompt-input';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/lib/utils';\n\ninterface DemoMessage {\n  id: string;\n  role: 'user' | 'assistant';\n  content: string;\n}\n\nconst INITIAL_MESSAGES: DemoMessage[] = [\n  {\n    id: 'intro',\n    role: 'assistant',\n    content:\n      '**Welcome back.** I can help you explore this chat block.\\n\\n- Draft UI copy\\n- Summarize docs\\n- Turn notes into tasks\\n\\nAsk me anything and I will respond with a demo reply.',\n  },\n  {\n    id: 'question',\n    role: 'user',\n    content: 'What makes this chat block reusable?',\n  },\n  {\n    id: 'answer',\n    role: 'assistant',\n    content:\n      'It is built with **AI Elements** for conversation layout and input, plus shadcn/ui for the chrome. That means you can drop it into other screens and wire it up to a real AI backend later.',\n  },\n];\n\nconst RESPONSES = [\n  'Here is a quick outline you can reuse:\\n\\n1. Swap the mock response with a real API call.\\n2. Stream tokens into `MessageResponse`.\\n3. Keep the layout exactly as-is for a consistent UI.',\n  'If you want multi-model support, add a small model selector next to the status badge and pass the selection to your backend.',\n  'You can also inject tools like file upload or voice input by adding buttons to the prompt footer.',\n];\n\nconst pickResponse = (index: number) => RESPONSES[index % RESPONSES.length];\n\nexport default function Ai05() {\n  const [messages, setMessages] = useState<DemoMessage[]>(INITIAL_MESSAGES);\n  const [inputValue, setInputValue] = useState('');\n  const [status, setStatus] = useState<ChatStatus>('ready');\n  const replyTimeoutRef = useRef<number | null>(null);\n\n  useEffect(() => {\n    return () => {\n      if (replyTimeoutRef.current) {\n        window.clearTimeout(replyTimeoutRef.current);\n      }\n    };\n  }, []);\n\n  const handleSend = (text: string) => {\n    const trimmed = text.trim();\n    if (!trimmed) {\n      return;\n    }\n\n    const newMessage: DemoMessage = {\n      id: `user-${Date.now()}`,\n      role: 'user',\n      content: trimmed,\n    };\n\n    setMessages((prev) => [...prev, newMessage]);\n    setInputValue('');\n    setStatus('submitted');\n\n    replyTimeoutRef.current = window.setTimeout(() => {\n      const response: DemoMessage = {\n        id: `assistant-${Date.now()}`,\n        role: 'assistant',\n        content: pickResponse(messages.length),\n      };\n\n      setMessages((prev) => [...prev, response]);\n      setStatus('ready');\n    }, 900);\n  };\n\n  return (\n    <div className=\"w-full px-4\">\n      <div className=\"mx-auto flex h-96 w-full max-w-2xl flex-col overflow-hidden rounded-2xl border border-border bg-card shadow-lg sm:w-3/5\">\n        <header className=\"flex items-center justify-between gap-4 border-border/80 border-b px-4 py-3\">\n          <div className=\"flex items-center gap-3\">\n            <div className=\"space-y-1\">\n              <div className=\"flex items-center gap-2 text-balance font-semibold text-sm\">\n                Documenso Chat\n              </div>\n              <div className=\"flex items-center gap-2 text-pretty text-muted-foreground text-xs\">\n                <span className=\"inline-flex items-center gap-1\">\n                  <span className=\"size-1.5 rounded-full bg-emerald-500\" />\n                  Live preview\n                </span>\n                <span className=\"hidden sm:inline\">- Powered by shadcn/ui</span>\n              </div>\n            </div>\n          </div>\n          <div className=\"flex items-center gap-1\">\n            <Button\n              aria-label=\"Refresh\"\n              className=\"size-8\"\n              size=\"icon\"\n              title=\"Refresh\"\n              variant=\"ghost\"\n            >\n              <IconRefresh className=\"size-4\" />\n            </Button>\n            <Button\n              aria-label=\"Settings\"\n              className=\"size-8\"\n              size=\"icon\"\n              title=\"Settings\"\n              variant=\"ghost\"\n            >\n              <IconAdjustmentsHorizontal className=\"size-4\" />\n            </Button>\n          </div>\n        </header>\n\n        <Conversation className=\"bg-muted/30\">\n          <ConversationContent className=\"gap-6 pl-1\">\n            {messages.map((message) => (\n              <Message from={message.role} key={message.id}>\n                <MessageContent\n                  className={cn(\n                    'leading-relaxed',\n                    message.role === 'assistant' && 'max-w-prose'\n                  )}\n                >\n                  {message.role === 'assistant' ? (\n                    <MessageResponse>{message.content}</MessageResponse>\n                  ) : (\n                    <p className=\"whitespace-pre-wrap text-pretty\">\n                      {message.content}\n                    </p>\n                  )}\n                </MessageContent>\n              </Message>\n            ))}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n\n        <div className=\"bg-background\">\n          <PromptInput\n            className=\"w-full [&>[data-slot=input-group]]:rounded-none [&>[data-slot=input-group]]:border-border/80 [&>[data-slot=input-group]]:border-x-0 [&>[data-slot=input-group]]:border-t [&>[data-slot=input-group]]:border-b-0 [&>[data-slot=input-group]]:shadow-none [&>[data-slot=input-group]]:focus-within:border-border/80 [&>[data-slot=input-group]]:focus-within:outline-none [&>[data-slot=input-group]]:focus-within:ring-0 [&>[data-slot=input-group]]:focus-within:ring-transparent [&>[data-slot=input-group]]:focus-within:ring-offset-0\"\n            onSubmit={(message) => handleSend(message.text)}\n          >\n            <PromptInputTextarea\n              onChange={(event) => setInputValue(event.currentTarget.value)}\n              placeholder=\"Ask about the block, UI patterns, or an AI workflow\"\n              value={inputValue}\n            />\n            <PromptInputFooter>\n              <PromptInputTools>\n                <PromptInputButton aria-label=\"Attach\">\n                  <IconPaperclip className=\"size-4\" />\n                </PromptInputButton>\n                <PromptInputButton aria-label=\"Quick prompt\">\n                  <IconBolt className=\"size-4\" />\n                </PromptInputButton>\n                <PromptInputButton aria-label=\"New chat\">\n                  <IconMessageCircle className=\"size-4\" />\n                </PromptInputButton>\n              </PromptInputTools>\n              <PromptInputSubmit\n                disabled={!inputValue.trim() || status !== 'ready'}\n                status={status}\n              />\n            </PromptInputFooter>\n          </PromptInput>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
    }
  ],
  "categories": [
    "ai"
  ]
}