{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ai-input",
  "type": "registry:ui",
  "description": "AI chat input component with advanced features",
  "files": [
    {
      "path": "packages/ai/input.tsx",
      "content": "'use client';\n\nimport { Loader2Icon, Send, SquareIcon, X } from 'lucide-react';\nimport type {\n  ComponentProps,\n  HTMLAttributes,\n  KeyboardEventHandler,\n} from 'react';\nimport { Children, useCallback, useEffect, useRef } from 'react';\nimport { Button } from '@repo/shadcn-ui/components/ui/button';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@repo/shadcn-ui/components/ui/select';\nimport { Textarea } from '@repo/shadcn-ui/components/ui/textarea';\nimport { cn } from '@repo/shadcn-ui/lib/utils';\n\ntype UseAutoResizeTextareaProps = {\n  minHeight: number;\n  maxHeight?: number;\n};\n\nconst useAutoResizeTextarea = ({\n  minHeight,\n  maxHeight,\n}: UseAutoResizeTextareaProps) => {\n  const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n  const adjustHeight = useCallback(\n    (reset?: boolean) => {\n      const textarea = textareaRef.current;\n      if (!textarea) {\n        return;\n      }\n\n      if (reset) {\n        textarea.style.height = `${minHeight}px`;\n        return;\n      }\n\n      // Temporarily shrink to get the right scrollHeight\n      textarea.style.height = `${minHeight}px`;\n\n      // Calculate new height\n      const newHeight = Math.max(\n        minHeight,\n        Math.min(textarea.scrollHeight, maxHeight ?? Number.POSITIVE_INFINITY)\n      );\n\n      textarea.style.height = `${newHeight}px`;\n    },\n    [minHeight, maxHeight]\n  );\n\n  useEffect(() => {\n    // Set initial height\n    const textarea = textareaRef.current;\n    if (textarea) {\n      textarea.style.height = `${minHeight}px`;\n    }\n  }, [minHeight]);\n\n  // Adjust height on window resize\n  useEffect(() => {\n    const handleResize = () => adjustHeight();\n    window.addEventListener('resize', handleResize);\n    return () => window.removeEventListener('resize', handleResize);\n  }, [adjustHeight]);\n\n  return { textareaRef, adjustHeight };\n};\n\nexport type AIInputProps = HTMLAttributes<HTMLFormElement>;\n\nexport const AIInput = ({ className, ...props }: AIInputProps) => (\n  <form\n    className={cn(\n      'w-full divide-y overflow-hidden rounded-xl border bg-background shadow-sm',\n      className\n    )}\n    {...props}\n  />\n);\n\nexport type AIInputTextareaProps = ComponentProps<typeof Textarea> & {\n  minHeight?: number;\n  maxHeight?: number;\n};\n\nexport const AIInputTextarea = ({\n  onChange,\n  className,\n  placeholder = 'What would you like to know?',\n  minHeight = 48,\n  maxHeight = 164,\n  ...props\n}: AIInputTextareaProps) => {\n  const { textareaRef, adjustHeight } = useAutoResizeTextarea({\n    minHeight,\n    maxHeight,\n  });\n\n  const handleKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (e) => {\n    if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n      e.preventDefault();\n      const form = e.currentTarget.form;\n      if (form) {\n        form.requestSubmit();\n      }\n    }\n  };\n\n  return (\n    <Textarea\n      className={cn(\n        'w-full resize-none rounded-none border-none p-3 shadow-none outline-none ring-0',\n        'bg-transparent dark:bg-transparent',\n        'focus-visible:ring-0',\n        className\n      )}\n      name=\"message\"\n      onChange={(e) => {\n        adjustHeight();\n        onChange?.(e);\n      }}\n      onKeyDown={handleKeyDown}\n      placeholder={placeholder}\n      ref={textareaRef}\n      {...props}\n    />\n  );\n};\n\nexport type AIInputToolbarProps = HTMLAttributes<HTMLDivElement>;\n\nexport const AIInputToolbar = ({\n  className,\n  ...props\n}: AIInputToolbarProps) => (\n  <div\n    className={cn('flex items-center justify-between p-1', className)}\n    {...props}\n  />\n);\n\nexport type AIInputToolsProps = HTMLAttributes<HTMLDivElement>;\n\nexport const AIInputTools = ({ className, ...props }: AIInputToolsProps) => (\n  <div\n    className={cn(\n      'flex items-center gap-1',\n      '[&_button:first-child]:rounded-bl-xl',\n      className\n    )}\n    {...props}\n  />\n);\n\nexport type AIInputButtonProps = ComponentProps<typeof Button>;\n\nexport const AIInputButton = ({\n  variant = 'ghost',\n  className,\n  size,\n  ...props\n}: AIInputButtonProps) => {\n  const newSize =\n    (size ?? Children.count(props.children) > 1) ? 'default' : 'icon';\n\n  return (\n    <Button\n      className={cn(\n        'shrink-0 gap-1.5 rounded-lg',\n        variant === 'ghost' && 'text-muted-foreground',\n        newSize === 'default' && 'px-3',\n        className\n      )}\n      size={newSize}\n      type=\"button\"\n      variant={variant}\n      {...props}\n    />\n  );\n};\n\nexport type AIInputSubmitProps = ComponentProps<typeof Button> & {\n  status?: 'submitted' | 'streaming' | 'ready' | 'error';\n};\n\nexport const AIInputSubmit = ({\n  className,\n  variant = 'default',\n  size = 'icon',\n  status,\n  children,\n  ...props\n}: AIInputSubmitProps) => {\n  let Icon = <Send />;\n\n  if (status === 'submitted') {\n    Icon = <Loader2Icon className=\"animate-spin\" />;\n  } else if (status === 'streaming') {\n    Icon = <SquareIcon />;\n  } else if (status === 'error') {\n    Icon = <X />;\n  }\n\n  return (\n    <Button\n      className={cn('gap-1.5 rounded-lg rounded-br-xl', className)}\n      size={size}\n      type=\"submit\"\n      variant={variant}\n      {...props}\n    >\n      {children ?? Icon}\n    </Button>\n  );\n};\n\nexport type AIInputModelSelectProps = ComponentProps<typeof Select>;\n\nexport const AIInputModelSelect = (props: AIInputModelSelectProps) => (\n  <Select {...props} />\n);\n\nexport type AIInputModelSelectTriggerProps = ComponentProps<\n  typeof SelectTrigger\n>;\n\nexport const AIInputModelSelectTrigger = ({\n  className,\n  ...props\n}: AIInputModelSelectTriggerProps) => (\n  <SelectTrigger\n    className={cn(\n      'border-none bg-transparent font-medium text-muted-foreground shadow-none transition-colors',\n      'hover:bg-accent hover:text-foreground [&[aria-expanded=\"true\"]]:bg-accent [&[aria-expanded=\"true\"]]:text-foreground',\n      className\n    )}\n    {...props}\n  />\n);\n\nexport type AIInputModelSelectContentProps = ComponentProps<\n  typeof SelectContent\n>;\n\nexport const AIInputModelSelectContent = ({\n  className,\n  ...props\n}: AIInputModelSelectContentProps) => (\n  <SelectContent className={cn(className)} {...props} />\n);\n\nexport type AIInputModelSelectItemProps = ComponentProps<typeof SelectItem>;\n\nexport const AIInputModelSelectItem = ({\n  className,\n  ...props\n}: AIInputModelSelectItemProps) => (\n  <SelectItem className={cn(className)} {...props} />\n);\n\nexport type AIInputModelSelectValueProps = ComponentProps<typeof SelectValue>;\n\nexport const AIInputModelSelectValue = ({\n  className,\n  ...props\n}: AIInputModelSelectValueProps) => (\n  <SelectValue className={cn(className)} {...props} />\n);\n",
      "type": "registry:component"
    }
  ]
}