{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ai-chat",
  "type": "registry:item",
  "title": "AI Chat",
  "description": "An AI chat input component with mode selector and action buttons.",
  "registryDependencies": [
    "https://roiui.com/r/button.json",
    "https://roiui.com/r/card.json",
    "https://roiui.com/r/field.json",
    "https://roiui.com/r/form.json",
    "https://roiui.com/r/select.json"
  ],
  "files": [
    {
      "path": "registry/brook/blocks/ai-chat/components/ai-chat.tsx",
      "content": "\"use client\";\n\nimport { ArrowUp, AudioLines, Paperclip } from \"lucide-react\";\nimport { useActionState, useState } from \"react\";\nimport { Button } from \"@/registry/brook/ui/button/button\";\nimport { Card, CardContent, CardFooter } from \"@/registry/brook/ui/card/card\";\nimport { Field, FieldControl } from \"@/registry/brook/ui/field/field\";\nimport { Form } from \"@/registry/brook/ui/form/form\";\nimport {\n  Select,\n  SelectIcon,\n  SelectItem,\n  SelectItemIndicator,\n  SelectItemText,\n  SelectList,\n  SelectPopup,\n  SelectPortal,\n  SelectPositioner,\n  SelectSpacer,\n  SelectTrigger,\n  SelectValue,\n} from \"@/registry/brook/ui/select/select\";\nimport styles from \"./ai-chat.module.css\";\n\nconst aiModes = [\n  { value: \"creative\", label: \"Creative\" },\n  { value: \"fast\", label: \"Fast\" },\n  { value: \"reasoning\", label: \"Reason\" },\n  { value: \"teach\", label: \"Teach\" },\n];\n\ntype FormState =\n  | { status: \"idle\" }\n  | { status: \"success\"; data: { message: string; mode: string } }\n  | { status: \"error\"; error: string; submittedData: { message: string; mode: string } };\n\nconst initialFormState: FormState = { status: \"idle\" };\n\nasync function chatAction(_prevState: FormState, formData: FormData): Promise<FormState> {\n  await new Promise((resolve) => setTimeout(resolve, 500));\n\n  const message = formData.get(\"message\") as string;\n  const mode = formData.get(\"mode\") as string;\n\n  return { status: \"success\", data: { message, mode } };\n}\n\nexport function AiChat() {\n  const [formState, submitAction, isPending] = useActionState(chatAction, initialFormState);\n  const [hasContent, setHasContent] = useState(false);\n\n  const defaultMessage = formState.status === \"error\" ? formState.submittedData.message : \"\";\n  const defaultMode = formState.status === \"error\" ? formState.submittedData.mode : aiModes[0].value;\n\n  return (\n    <Form action={submitAction} className={styles.form}>\n      <Card className={styles.aiChatCard}>\n        <CardContent>\n          <Field className={styles.field}>\n            <FieldControl\n              placeholder=\"How can I help…\"\n              render={\n                <textarea\n                  className={styles.textarea}\n                  defaultValue={defaultMessage}\n                  disabled={isPending}\n                  name=\"message\"\n                  onChange={(e) => setHasContent(e.target.value.trim().length > 0)}\n                />\n              }\n            />\n          </Field>\n        </CardContent>\n        <CardFooter className={styles.footer}>\n          <Button aria-label=\"Attach file\" className={styles.attachButton} size=\"icon\" type=\"button\" variant=\"ghost\">\n            <Paperclip size={14} />\n          </Button>\n\n          <div className={styles.footerActions}>\n            <Select defaultValue={defaultMode} items={aiModes} name=\"mode\">\n              <SelectTrigger\n                className={styles.selectTrigger}\n                render={<Button className={styles.selectButton} size=\"sm\" variant=\"ghost\" />}\n              >\n                <SelectValue>\n                  {(value) => {\n                    const selectedMode = aiModes.find((mode) => mode.value === value);\n                    return <span className={styles.selectValue}>{selectedMode?.label}</span>;\n                  }}\n                </SelectValue>\n                <SelectIcon className={styles.selectIcon} />\n              </SelectTrigger>\n              <SelectPortal>\n                <SelectPositioner align=\"start\" alignItemWithTrigger={false} side=\"top\" sideOffset={8}>\n                  <SelectPopup className={styles.popup} data-slot=\"select-popup\">\n                    <SelectSpacer />\n                    <SelectList>\n                      {aiModes.map(({ label, value }) => (\n                        <SelectItem data-slot=\"select-item\" key={value} value={value}>\n                          <SelectItemText>{label}</SelectItemText>\n                          <SelectItemIndicator className={styles.selectIndicator} />\n                        </SelectItem>\n                      ))}\n                    </SelectList>\n                    <SelectSpacer />\n                  </SelectPopup>\n                </SelectPositioner>\n              </SelectPortal>\n            </Select>\n\n            <Button\n              aria-label={hasContent ? \"Send message\" : \"Start voice input\"}\n              className={styles.submitButton}\n              disabled={isPending}\n              size=\"icon\"\n              type=\"submit\"\n              variant=\"ghost\"\n            >\n              {hasContent ? (\n                <ArrowUp className={styles.submitIcon} size={16} />\n              ) : (\n                <AudioLines className={styles.submitIcon} size={16} />\n              )}\n            </Button>\n          </div>\n        </CardFooter>\n      </Card>\n    </Form>\n  );\n}\n",
      "type": "registry:file",
      "target": "~/components/blocks/ai-chat/ai-chat.tsx"
    },
    {
      "path": "registry/brook/blocks/ai-chat/components/ai-chat.module.css",
      "content": ".aiChatCard[data-slot=\"card\"] {\n  padding: 0.75rem;\n  gap: 0.75rem;\n  width: 100%;\n  height: auto;\n  max-width: 600px;\n  min-width: 0;\n  margin: 0 auto;\n  border-radius: var(--radius-lg);\n  border-color: oklch(from var(--border) l c h / 0.25);\n  background-color: var(--mix-card-50-bg);\n  transition: border-color 0.2s ease;\n\n  &:hover,\n  &:focus-within {\n    border-color: oklch(from var(--border) l c h / 0.5);\n  }\n}\n\n.form {\n  width: 100%;\n}\n\n.textarea {\n  background-color: transparent;\n  border: none;\n  padding: 0.25rem;\n  resize: none;\n  min-height: 2.5rem;\n  height: auto;\n  line-height: 1.5;\n\n  &:focus {\n    outline: none;\n  }\n}\n\n.attachButton[data-slot=\"button\"] {\n  width: 32px;\n  height: 32px;\n  padding: 8px;\n  border-radius: 50%;\n  flex-shrink: 0;\n\n  & svg {\n    color: var(--muted-foreground);\n    flex-shrink: 0;\n    transform: rotate(-45deg);\n  }\n}\n\n.footerActions {\n  display: flex;\n  gap: 0.5rem;\n  align-items: center;\n}\n\n.selectButton[data-slot=\"button\"] {\n  border-radius: var(--radius);\n}\n\n.selectValue {\n  color: var(--muted-foreground);\n}\n\n.selectIcon {\n  margin-left: 0.25rem;\n}\n\n.selectIndicator {\n  color: var(--muted-foreground);\n}\n\n.submitButton[data-slot=\"button\"] {\n  width: 36px;\n  height: 36px;\n  border-radius: 50%;\n  background-color: var(--primary);\n  flex-shrink: 0;\n}\n\n.submitButton[data-slot=\"button\"]:hover:not([data-disabled]) {\n  background-color: oklch(from var(--primary) calc(l * 0.8) c h);\n}\n\n.submitIcon {\n  color: var(--primary-foreground);\n}\n\n.footer[data-slot=\"card-footer\"] {\n  gap: 0.5rem;\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n}\n\n.selectButton:hover,\n.selectButton[data-popup-open] {\n  background-color: var(--accent) !important;\n}\n\n.popup[data-slot=\"select-popup\"] {\n  box-sizing: border-box;\n  min-width: 140px;\n}\n\n@media (max-width: 768px) {\n  .popup[data-slot=\"select-popup\"] {\n    width: 120px !important;\n    min-width: 120px !important;\n    max-width: 120px !important;\n  }\n\n  .selectValue {\n    font-size: 0.875rem;\n  }\n\n  .selectIcon {\n    display: none;\n  }\n}\n\n@media (max-width: 1280px) {\n  .textarea {\n    min-height: 4rem;\n    padding: 0.5rem;\n  }\n}\n\n@media (max-width: 640px) {\n  .aiChatCard[data-slot=\"card\"] {\n    min-width: 230px;\n  }\n\n  .form {\n    display: flex;\n    justify-content: center;\n    align-items: center;\n  }\n}\n",
      "type": "registry:file",
      "target": "~/components/blocks/ai-chat/ai-chat.module.css"
    }
  ]
}