{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ai-chat-input",
  "title": "AI Chat Input",
  "description": "Prompt composer for conversational interfaces with helper text, toolbar actions, and submit states.",
  "dependencies": [
    "@vllnt/ui@^0.3.0",
    "lucide-react"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/ai-chat-input/ai-chat-input.tsx",
      "content": "import { cva } from \"class-variance-authority\";\nimport { LoaderCircle, SendHorizontal } from \"lucide-react\";\n\nimport { cn } from \"@vllnt/ui\";\nimport { Button } from \"@vllnt/ui\";\nimport { Textarea } from \"@vllnt/ui\";\n\nconst formShellVariants = cva(\n  \"rounded-2xl border border-border/70 bg-background shadow-sm\",\n);\n\nfunction AIChatInputFooter({\n  currentLength,\n  helperText,\n  isSubmitDisabled,\n  isSubmitting,\n  maxLength,\n  status,\n  submitLabel,\n}: {\n  currentLength: number;\n  helperText?: string;\n  isSubmitDisabled: boolean;\n  isSubmitting: boolean;\n  maxLength?: number;\n  status?: string;\n  submitLabel: string;\n}) {\n  return (\n    <div className=\"flex flex-col gap-3 border-t border-border/60 pt-3 sm:flex-row sm:items-end sm:justify-between\">\n      <div className=\"space-y-1 text-xs text-muted-foreground\">\n        {helperText ? <p>{helperText}</p> : null}\n        <div className=\"flex flex-wrap items-center gap-2\">\n          {status ? <span>{status}</span> : null}\n          {typeof maxLength === \"number\" ? (\n            <span>\n              {currentLength}/{maxLength}\n            </span>\n          ) : null}\n        </div>\n      </div>\n\n      <Button\n        className=\"self-start rounded-full px-4 sm:self-auto\"\n        disabled={isSubmitDisabled}\n        type=\"submit\"\n      >\n        {isSubmitting ? (\n          <LoaderCircle className=\"mr-2 size-4 animate-spin\" />\n        ) : (\n          <SendHorizontal className=\"mr-2 size-4\" />\n        )}\n        {submitLabel}\n      </Button>\n    </div>\n  );\n}\n\nexport type AIChatInputProps = React.ComponentPropsWithoutRef<\"form\"> & {\n  /** Disables editing and submit actions. */\n  disabled?: boolean;\n  /** Optional helper text shown below the prompt field. */\n  helperText?: string;\n  /**\n   * Accessible name for the message textarea. Defaults to `\"Chat message\"`.\n   * Override `textareaProps.aria-label` / `aria-labelledby` for finer control.\n   */\n  inputLabel?: string;\n  /** Whether the submit action is in progress. */\n  isSubmitting?: boolean;\n  /** Called whenever the textarea value changes. */\n  onValueChange?: (value: string) => void;\n  /** Optional status text shown beside helper copy. */\n  status?: string;\n  /** Label for the submit button. */\n  submitLabel?: string;\n  /** Props forwarded to the textarea primitive. */\n  textareaProps?: React.TextareaHTMLAttributes<HTMLTextAreaElement>;\n  /** Optional controls rendered above the footer row. */\n  toolbar?: React.ReactNode;\n  /** Controlled textarea value. */\n  value?: string;\n};\n\nconst AIChatInput = ({\n  className,\n  disabled = false,\n  helperText,\n  inputLabel = \"Chat message\",\n  isSubmitting = false,\n  onSubmit,\n  onValueChange,\n  ref,\n  status,\n  submitLabel = \"Send\",\n  textareaProps,\n  toolbar,\n  value,\n  ...props\n}: AIChatInputProps & { ref?: React.Ref<HTMLFormElement> }) => {\n  const currentValue = value ?? \"\";\n  const maxLength = textareaProps?.maxLength;\n  const isSubmitDisabled =\n    disabled || isSubmitting || currentValue.trim().length === 0;\n\n  return (\n    <form\n      className={cn(formShellVariants(), \"w-full p-3\", className)}\n      onSubmit={onSubmit}\n      ref={ref}\n      {...props}\n    >\n      <div className=\"space-y-3\">\n        <Textarea\n          aria-label={inputLabel}\n          className=\"min-h-[120px] resize-none rounded-xl border-0 bg-transparent p-1 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0\"\n          disabled={disabled}\n          onChange={(event) => {\n            textareaProps?.onChange?.(event);\n            onValueChange?.(event.target.value);\n          }}\n          placeholder=\"Ask a follow-up question, paste context, or describe what you need...\"\n          value={value}\n          {...textareaProps}\n        />\n\n        {toolbar ? <div className=\"flex flex-wrap gap-2\">{toolbar}</div> : null}\n\n        <AIChatInputFooter\n          currentLength={currentValue.length}\n          helperText={helperText}\n          isSubmitDisabled={isSubmitDisabled}\n          isSubmitting={isSubmitting}\n          maxLength={maxLength}\n          status={status}\n          submitLabel={submitLabel}\n        />\n      </div>\n    </form>\n  );\n};\n\nAIChatInput.displayName = \"AIChatInput\";\n\nexport { AIChatInput };\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component",
  "version": "0.3.0",
  "stability": "stable"
}
