@humain/ui 2.4.1 → 2.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index150.js CHANGED
@@ -172,7 +172,7 @@ function AIInputDefaultButton({ customButton, disabled }) {
172
172
  if (customButton) return customButton(buttonProps);
173
173
  return /* @__PURE__ */ jsx(SubmitButton, {
174
174
  icon: ArrowUp,
175
- ...buttonProps
175
+ disabled: true
176
176
  });
177
177
  }
178
178
  function AIInputRoot({ children, variant = "default", value: controlledValue, defaultValue = "", onChange, onSubmit, uploadingFiles = [], onRemoveFile, onCancelUpload, onRetryUpload, onRemoveAllFiles, disabled = false, className, onFilesSelected, accept, multiple = true, dropText = "Drop files to attach", pasteAsFile }) {
@@ -1 +1 @@
1
- {"version":3,"file":"index150.js","names":[],"sources":["../src/components/organisms/ai/AIInput/AIInput.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { ArrowDown, ArrowUp, X } from 'lucide-react';\nimport * as React from 'react';\nimport { Button } from '@/components/atoms/buttons/Button';\nimport { FileUploadItem } from '@/components/molecules/files/FileUpload';\nimport {\n matchesAcceptToken,\n toFileList,\n useDropZone,\n} from '@/hooks/use-drop-zone';\nimport { createSafeContext } from '@/lib/create-safe-context';\nimport { cn } from '@/lib/utils';\nimport { analyzePaste, mapKindToFile, type PasteKind } from './paste-detection';\n\n// =============================================================================\n// Shared Styles\n// =============================================================================\n\nconst textareaClasses =\n 'flex-1 h-[40px] resize-none overflow-y-auto bg-transparent text-base text-foreground placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:text-muted-foreground';\n\nconst compactTextareaClasses =\n 'flex-1 h-[32px] resize-none overflow-y-auto bg-transparent text-base leading-6 text-foreground placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:text-muted-foreground';\n\n// =============================================================================\n// Variants\n// =============================================================================\n\nconst inputVariants = cva(\n 'flex items-center w-full transition-[color,background-color,border-color,box-shadow,opacity]',\n {\n variants: {\n state: {\n default: '',\n focused: '',\n withText: '',\n disabled: 'cursor-not-allowed',\n attachments: '',\n dragover: '',\n },\n variant: {\n default: 'flex-col gap-2 py-4 px-4 rounded-[inherit]',\n compact: 'flex-row gap-2 py-4 px-4 rounded-[inherit]',\n inline: 'flex-row gap-2 px-4 py-4 rounded-[inherit]',\n },\n },\n defaultVariants: {\n state: 'default',\n variant: 'default',\n },\n },\n);\n\nfunction getAIInputShellClassName({\n state,\n variant,\n className,\n}: {\n state: VariantProps<typeof inputVariants>['state'];\n variant: 'default' | 'compact' | 'inline';\n className?: string;\n}) {\n const isDefault = variant === 'default';\n const isDisabled = state === 'disabled';\n const isPrimaryState =\n state === 'focused' ||\n state === 'withText' ||\n state === 'attachments' ||\n state === 'dragover';\n const isStrongState =\n state === 'focused' || state === 'withText' || state === 'dragover';\n\n return cn(\n 'relative w-full overflow-hidden border bg-background shadow-[var(--shadow-ai-input)] transition-[color,background-color,border-color,box-shadow,opacity] duration-150 ease-out',\n isDefault ? 'rounded-3xl max-w-[772px]' : 'rounded-2xl',\n isDisabled\n ? 'border-border bg-muted'\n : isPrimaryState\n ? 'border-primary'\n : 'border-ring/50 hover:border-primary',\n isStrongState ? 'border-2' : 'border-[1.25px]',\n className,\n );\n}\n\n// =============================================================================\n// Drop Overlay (shared across all variants)\n// =============================================================================\n\nfunction DropOverlay({\n isDefault,\n dropText,\n}: {\n isDefault: boolean;\n dropText: string;\n}) {\n return (\n <div\n data-slot=\"ai-input-drop-overlay\"\n role=\"status\"\n aria-live=\"polite\"\n className={cn(\n 'delight-drop-enter absolute inset-1.5 border-2 border-dashed border-primary/50 dark:border-primary/60 pointer-events-none flex flex-col items-center justify-center gap-1.5 z-10',\n isDefault ? 'rounded-[calc(1.5rem-8px)]' : 'rounded-[calc(1rem-8px)]',\n )}\n >\n <ArrowDown className=\"size-4 text-primary/70 delight-drop-icon\" />\n <span className=\"text-sm text-muted-foreground font-medium\">\n {dropText}\n </span>\n </div>\n );\n}\n\nDropOverlay.displayName = 'AIInput.DropOverlay';\n\n// =============================================================================\n// File Attachment Types\n// =============================================================================\n\nexport interface UploadingFile {\n id: string;\n name: string;\n size: string;\n progress: number;\n status: 'uploading' | 'complete' | 'error';\n /** File extension for icon display (e.g., 'pdf', 'docx') */\n fileExtension?: string;\n}\n\n// =============================================================================\n// Paste-as-File public types\n// =============================================================================\n\nexport type { PasteKind } from './paste-detection';\n\nexport interface PasteAsFileConfig {\n /** Char count above which plain text always converts. Default: 500 */\n threshold?: number;\n /** Line count above which plain text always converts. Default: 10 */\n lineThreshold?: number;\n /** Run structured-content heuristics (JSON/XML/CSV/code/log). Default: true */\n detectStructured?: boolean;\n /**\n * Auto-fill textarea after conversion. Receives filename + detected kind.\n * Return string to set as textarea value (appended with leading space if textarea non-empty).\n * Empty/whitespace-only return is treated as no-op.\n * Default: undefined → textarea stays empty.\n */\n prefillTemplate?: (filename: string, kind: PasteKind) => string;\n /** Fired after onFilesSelected and prefill. */\n onConverted?: (filename: string, kind: PasteKind) => void;\n}\n\n/**\n * Accepts boolean for runtime toggling. `false` and `undefined` both disable.\n * `true` enables with defaults. Object enables with overrides.\n */\nexport type PasteAsFileProp = boolean | PasteAsFileConfig;\n\n// =============================================================================\n// usePasteAsFile — internal hook\n// =============================================================================\n\ninterface UsePasteAsFileOpts {\n pasteAsFile: PasteAsFileProp | undefined;\n onFilesSelected: ((files: FileList) => void) | undefined;\n accept: string | undefined;\n disabled: boolean;\n variant: 'default' | 'compact' | 'inline';\n value: string;\n setValue: (next: string) => void;\n}\n\nfunction usePasteAsFile(opts: UsePasteAsFileOpts): {\n onPaste?: React.ClipboardEventHandler<HTMLTextAreaElement>;\n} {\n const counterRef = React.useRef(0);\n const warnedRef = React.useRef(false);\n const optsRef = React.useRef(opts);\n\n // Keep the ref pointing at the latest opts each render. This pattern lets the\n // returned `onPaste` be referentially stable (empty-deps useCallback) while\n // still seeing the freshest pasteAsFile config and callbacks.\n React.useEffect(() => {\n optsRef.current = opts;\n });\n\n const onPaste = React.useCallback<\n React.ClipboardEventHandler<HTMLTextAreaElement>\n >((e) => {\n const { pasteAsFile, onFilesSelected, accept, disabled, value, setValue } =\n optsRef.current;\n\n if (!pasteAsFile || disabled) return;\n\n const text = e.clipboardData.getData('text/plain');\n if (!text) return;\n\n const config: PasteAsFileConfig = pasteAsFile === true ? {} : pasteAsFile;\n\n const detectionOpts = {\n charThreshold: config.threshold,\n lineThreshold: config.lineThreshold,\n detectStructured: config.detectStructured,\n };\n\n const { shouldConvert, kind } = analyzePaste(text, detectionOpts);\n if (!shouldConvert) return;\n\n if (!onFilesSelected) {\n if (process.env.NODE_ENV !== 'production' && !warnedRef.current) {\n console.warn(\n '[AIInput] pasteAsFile is set but onFilesSelected is missing. Paste-to-file is a no-op.',\n );\n warnedRef.current = true;\n }\n return;\n }\n\n const { ext, mime } = mapKindToFile(kind);\n const nProspective = counterRef.current + 1;\n const filename = `Pasted-${nProspective}.${ext}`;\n\n if (\n accept &&\n !accept\n .split(',')\n .some((token) =>\n matchesAcceptToken({ name: filename, type: mime }, token),\n )\n ) {\n return;\n }\n\n let fileList: FileList;\n try {\n const file = new File([text], filename, { type: mime });\n fileList = toFileList([file]);\n } catch {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n '[AIInput] DataTransfer unavailable; falling back to native paste.',\n );\n }\n return;\n }\n\n e.preventDefault();\n counterRef.current = nProspective;\n onFilesSelected(fileList);\n\n if (config.prefillTemplate) {\n const tpl = config.prefillTemplate(filename, kind);\n if (tpl?.trim()) {\n setValue(value ? `${value} ${tpl}` : tpl);\n }\n }\n\n config.onConverted?.(filename, kind);\n }, []);\n\n if (opts.variant === 'inline' || !opts.pasteAsFile) {\n return { onPaste: undefined };\n }\n\n return { onPaste };\n}\n\n// =============================================================================\n// Context\n// =============================================================================\n\ninterface AIInputContextValue {\n /** Current input value */\n value: string;\n /** Whether the input has text */\n hasText: boolean;\n /** Whether the input is focused */\n isFocused: boolean;\n /** Whether the input is disabled */\n disabled: boolean;\n /** Visual variant */\n variant: 'default' | 'compact' | 'inline';\n /** Files being uploaded */\n uploadingFiles: UploadingFile[];\n /** Has attachments */\n hasAttachments: boolean;\n /** Update input value */\n setValue: (value: string) => void;\n /** Set focus state */\n setIsFocused: (focused: boolean) => void;\n /** Handle submit */\n handleSubmit: () => void;\n /** Handle key down */\n handleKeyDown: (\n e: React.KeyboardEvent<HTMLTextAreaElement | HTMLInputElement>,\n ) => void;\n /** Handle clear */\n handleClear: () => void;\n /** Paste handler from usePasteAsFile (only set when paste-as-file is active). */\n onPaste?: React.ClipboardEventHandler<HTMLTextAreaElement>;\n /** Remove file */\n onRemoveFile?: (fileId: string) => void;\n /** Cancel upload */\n onCancelUpload?: (fileId: string) => void;\n /** Retry failed upload */\n onRetryUpload?: (fileId: string) => void;\n /** Remove all files */\n onRemoveAllFiles?: () => void;\n /** Whether files are being dragged over the input */\n isDragging: boolean;\n /** Open the native file picker */\n openFilePicker: () => void;\n /** Callback when files are selected (via drop or picker) */\n onFilesSelected?: (files: FileList) => void;\n /** Textarea ref (for default variant) */\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\n /** Input ref (for compact variant) */\n inputRef: React.RefObject<HTMLInputElement | null>;\n}\n\nconst [AIInputContext, useAIInputContext] =\n createSafeContext<AIInputContextValue>('AIInput');\n\n// =============================================================================\n// Compound Components - Building Blocks\n// =============================================================================\n\nexport interface ActionButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Icon component to render */\n icon: React.ComponentType<{ className?: string }>;\n /** Tooltip text */\n tooltip?: string;\n}\n\nfunction ActionButton({\n icon: Icon,\n onClick,\n disabled,\n tooltip,\n className,\n ...props\n}: ActionButtonProps) {\n return (\n <button\n type=\"button\"\n data-slot=\"action-button\"\n onClick={onClick}\n disabled={disabled}\n title={tooltip}\n aria-label={tooltip}\n className={cn(\n 'p-2 rounded-full text-secondary-foreground hover:bg-accent transition-colors disabled:opacity-50 disabled:cursor-not-allowed',\n className,\n )}\n {...props}\n >\n <Icon className=\"size-4\" />\n </button>\n );\n}\n\nActionButton.displayName = 'AIInput.ActionButton';\n\nexport interface SubmitButtonProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {\n /** Icon component to render (defaults to ArrowUp) */\n icon?: React.ComponentType<{ className?: string }>;\n}\n\nfunction SubmitButton({\n icon: Icon = ArrowUp,\n className,\n onClick,\n disabled,\n ...props\n}: SubmitButtonProps) {\n return (\n <Button\n type=\"button\"\n data-slot=\"submit-button\"\n size=\"icon-sm\"\n onClick={onClick}\n disabled={disabled}\n aria-label=\"Send message\"\n className={cn(\n 'rounded-full bg-primary hover:bg-primary/90 text-primary-foreground disabled:bg-accent disabled:text-muted-foreground transition-colors duration-150 ease-out',\n className,\n )}\n {...props}\n >\n <Icon className=\"size-4\" />\n </Button>\n );\n}\n\nSubmitButton.displayName = 'AIInput.SubmitButton';\n\nexport interface CompactActionButtonProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {\n /** Icon component to render */\n icon: React.ComponentType<{ className?: string }>;\n /** Accessible label for the icon-only button (required for a11y) */\n 'aria-label': string;\n}\n\n/**\n * @deprecated Use `ActionButton` instead. CompactActionButton will be removed in a future major version.\n */\nfunction CompactActionButton({\n icon: Icon,\n className,\n onClick,\n disabled,\n ...props\n}: CompactActionButtonProps) {\n return (\n <Button\n type=\"button\"\n data-slot=\"compact-action-button\"\n onClick={onClick}\n disabled={disabled}\n appearance=\"outline\"\n variant=\"secondary\"\n size=\"icon\"\n className={cn(\n 'rounded-full border-border text-foreground hover:bg-muted',\n className,\n )}\n {...props}\n >\n <Icon className=\"size-5\" />\n </Button>\n );\n}\n\nCompactActionButton.displayName = 'AIInput.CompactActionButton';\n\nfunction RemoveAllButton({ onClick }: { onClick?: () => void }) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label=\"Remove all attached files\"\n className=\"flex items-center gap-1.5 h-5 px-2 py-1 rounded-full bg-accent border border-border text-xs font-medium text-foreground hover:bg-accent/80 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring transition-colors\"\n >\n <X className=\"size-4\" />\n Remove all\n </button>\n );\n}\n\nRemoveAllButton.displayName = 'AIInput.RemoveAllButton';\n\n// =============================================================================\n// Render Function Types (for monolithic API)\n// =============================================================================\n\n/** Props passed to custom submit button render function */\nexport interface SubmitButtonRenderProps {\n onClick: () => void;\n disabled: boolean;\n}\n\n/** Render function type for custom submit button */\nexport type SubmitButtonRenderFn = (\n props: SubmitButtonRenderProps,\n) => React.ReactElement;\n\n/** Props passed to custom default button render function */\nexport interface DefaultButtonRenderProps {\n disabled: boolean;\n}\n\n/** Render function type for custom default button */\nexport type DefaultButtonRenderFn = (\n props: DefaultButtonRenderProps,\n) => React.ReactElement;\n\nfunction AIInputSubmitButton({\n customButton,\n onClick,\n disabled,\n}: {\n customButton?: SubmitButtonRenderFn;\n onClick: () => void;\n disabled: boolean;\n}) {\n const buttonProps: SubmitButtonRenderProps = {\n onClick,\n disabled,\n };\n\n if (customButton) {\n return customButton(buttonProps);\n }\n\n return <SubmitButton {...buttonProps} />;\n}\n\nfunction AIInputDefaultButton({\n customButton,\n disabled,\n}: {\n customButton?: DefaultButtonRenderFn;\n disabled: boolean;\n}) {\n const buttonProps: DefaultButtonRenderProps = {\n disabled,\n };\n\n if (customButton) {\n return customButton(buttonProps);\n }\n\n return <SubmitButton icon={ArrowUp} {...buttonProps} />;\n}\n\n// =============================================================================\n// Composable Subcomponents (for dual-API)\n// =============================================================================\n\nexport interface AIInputRootProps {\n /** Children (composable subcomponents) */\n children: React.ReactNode;\n /** Visual variant of the input */\n variant?: 'default' | 'compact' | 'inline';\n /** Current input value (controlled) */\n value?: string;\n /** Default input value (uncontrolled) */\n defaultValue?: string;\n /** Callback when value changes */\n onChange?: (value: string) => void;\n /** Callback when message is submitted */\n onSubmit?: (message: string) => void;\n /** Files being uploaded */\n uploadingFiles?: UploadingFile[];\n /** Callback when file is removed */\n onRemoveFile?: (fileId: string) => void;\n /** Callback when file upload is cancelled */\n onCancelUpload?: (fileId: string) => void;\n /** Callback to retry a failed upload */\n onRetryUpload?: (fileId: string) => void;\n /** Callback to remove all files */\n onRemoveAllFiles?: () => void;\n /** Whether the input is disabled */\n disabled?: boolean;\n /** Additional class name */\n className?: string;\n /** Callback when files are selected (via drag-drop or file picker) */\n onFilesSelected?: (files: FileList) => void;\n /** Accepted file types (e.g. 'image/*,.pdf') */\n accept?: string;\n /** Allow multiple file selection */\n multiple?: boolean;\n /** Text shown in the drop overlay */\n dropText?: string;\n /** Convert large/structured paste into a file attachment. Requires onFilesSelected. */\n pasteAsFile?: PasteAsFileProp;\n}\n\nfunction AIInputRoot({\n children,\n variant = 'default',\n value: controlledValue,\n defaultValue = '',\n onChange,\n onSubmit,\n uploadingFiles = [],\n onRemoveFile,\n onCancelUpload,\n onRetryUpload,\n onRemoveAllFiles,\n disabled = false,\n className,\n onFilesSelected,\n accept,\n multiple = true,\n dropText = 'Drop files to attach',\n pasteAsFile,\n}: AIInputRootProps) {\n const [internalValue, setInternalValue] = React.useState(defaultValue);\n const [isFocused, setIsFocused] = React.useState(false);\n const textareaRef = React.useRef<HTMLTextAreaElement>(null);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n\n const { isDragging, dropZoneProps, openFilePicker } = useDropZone({\n onFilesSelected,\n accept,\n multiple,\n disabled,\n containerRef: rootRef,\n });\n\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : internalValue;\n const hasText = value.trim().length > 0;\n const hasAttachments = uploadingFiles.length > 0;\n const setValue = React.useCallback(\n (newValue: string) => {\n if (onChange) {\n onChange(newValue);\n }\n if (!isControlled) {\n setInternalValue(newValue);\n }\n },\n [onChange, isControlled],\n );\n\n const { onPaste } = usePasteAsFile({\n pasteAsFile,\n onFilesSelected,\n accept,\n disabled,\n variant,\n value,\n setValue,\n });\n\n const handleSubmit = React.useCallback(() => {\n if (hasText && onSubmit) {\n onSubmit(value);\n if (!isControlled) {\n setInternalValue('');\n }\n }\n }, [hasText, onSubmit, value, isControlled]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement | HTMLInputElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n },\n [handleSubmit],\n );\n\n const handleClear = React.useCallback(() => {\n setValue('');\n if (variant === 'inline') {\n inputRef.current?.focus();\n } else {\n textareaRef.current?.focus();\n }\n }, [setValue, variant]);\n\n // Determine visual state\n const getState = (): VariantProps<typeof inputVariants>['state'] => {\n if (disabled) return 'disabled';\n if (isDragging) return 'dragover';\n if (hasAttachments) return 'attachments';\n if (hasText) return 'withText';\n if (isFocused) return 'focused';\n return 'default';\n };\n\n const contextValue = React.useMemo<AIInputContextValue>(\n () => ({\n value,\n hasText,\n isFocused,\n disabled,\n variant,\n uploadingFiles,\n hasAttachments,\n setValue,\n setIsFocused,\n handleSubmit,\n handleKeyDown,\n handleClear,\n onPaste,\n onRemoveFile,\n onCancelUpload,\n onRetryUpload,\n onRemoveAllFiles,\n isDragging,\n openFilePicker,\n onFilesSelected,\n textareaRef,\n inputRef,\n }),\n [\n value,\n hasText,\n isFocused,\n disabled,\n variant,\n uploadingFiles,\n hasAttachments,\n setValue,\n handleSubmit,\n handleKeyDown,\n handleClear,\n onPaste,\n onRemoveFile,\n onCancelUpload,\n onRetryUpload,\n onRemoveAllFiles,\n isDragging,\n openFilePicker,\n onFilesSelected,\n ],\n );\n\n const isDefault = variant === 'default';\n const state = getState();\n\n return (\n <AIInputContext.Provider value={contextValue}>\n <div\n ref={rootRef}\n data-slot=\"ai-input\"\n data-dragging={isDragging}\n {...dropZoneProps}\n {...(onFilesSelected\n ? { 'aria-label': 'Chat input with file drop zone' }\n : {})}\n className={getAIInputShellClassName({ state, variant, className })}\n >\n <div\n data-slot=\"ai-input-inner\"\n className={cn(\n inputVariants({ state, variant }),\n 'relative',\n !isDefault && hasAttachments && 'flex-col items-stretch py-3',\n disabled && !isDefault ? 'bg-muted' : 'bg-background',\n 'rounded-[inherit]',\n disabled && isDefault && 'bg-muted',\n )}\n >\n {isDragging && (\n <DropOverlay isDefault={isDefault} dropText={dropText} />\n )}\n {children}\n </div>\n </div>\n </AIInputContext.Provider>\n );\n}\n\nAIInputRoot.displayName = 'AIInput.Root';\n\n// =============================================================================\n// AIInput.TextArea - The text input area\n// =============================================================================\n\nexport interface AIInputTextAreaProps {\n /** Placeholder text */\n placeholder?: string;\n /** Additional class name */\n className?: string;\n /** Show clear button when text is present */\n showClearButton?: boolean;\n}\n\nfunction AIInputTextArea({\n placeholder = 'How can HUMAIN ONE help you today?',\n className,\n showClearButton = true,\n}: AIInputTextAreaProps) {\n const ctx = useAIInputContext();\n const isInline = ctx.variant === 'inline';\n\n const handleChange = (\n e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,\n ) => {\n ctx.setValue(e.target.value);\n };\n\n if (isInline) {\n return (\n <input\n ref={ctx.inputRef}\n data-slot=\"ai-input-text\"\n type=\"text\"\n value={ctx.value}\n onChange={handleChange}\n onFocus={() => ctx.setIsFocused(true)}\n onBlur={() => ctx.setIsFocused(false)}\n onKeyDown={ctx.handleKeyDown}\n placeholder={placeholder}\n aria-label={placeholder}\n disabled={ctx.disabled}\n className={cn(\n 'flex-1 min-w-0 bg-transparent text-sm leading-5 text-foreground placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:text-muted-foreground',\n className,\n )}\n />\n );\n }\n\n return (\n <div\n data-slot=\"ai-input-text-area\"\n className={cn(\n 'flex gap-2',\n ctx.variant === 'compact' && !ctx.hasAttachments\n ? 'min-w-0 flex-1 items-center'\n : 'w-full items-start',\n )}\n >\n <textarea\n ref={ctx.textareaRef}\n data-slot=\"ai-input-textarea\"\n value={ctx.value}\n onChange={handleChange}\n onPaste={ctx.onPaste}\n onFocus={() => ctx.setIsFocused(true)}\n onBlur={() => ctx.setIsFocused(false)}\n onKeyDown={ctx.handleKeyDown}\n placeholder={placeholder}\n aria-label={placeholder}\n disabled={ctx.disabled}\n rows={1}\n className={cn(\n ctx.variant === 'compact' ? compactTextareaClasses : textareaClasses,\n className,\n )}\n />\n {showClearButton &&\n ctx.variant !== 'compact' &&\n ctx.hasText &&\n !ctx.disabled && (\n <button\n type=\"button\"\n onClick={ctx.handleClear}\n aria-label=\"Clear input\"\n className=\"p-2 rounded-full hover:bg-accent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring transition-colors duration-150 ease-out shrink-0\"\n >\n <X className=\"size-5 text-muted-foreground\" />\n </button>\n )}\n </div>\n );\n}\n\nAIInputTextArea.displayName = 'AIInput.TextArea';\n\n// =============================================================================\n// AIInput.LeadingIcon - Leading icon for inline variant\n// =============================================================================\n\nexport interface AIInputLeadingIconProps {\n /** Icon content (brand icon, spinner, avatar) */\n children: React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIInputLeadingIcon({ children, className }: AIInputLeadingIconProps) {\n return (\n <div\n data-slot=\"ai-input-leading-icon\"\n aria-hidden=\"true\"\n className={cn(\n 'flex items-center justify-center shrink-0 size-9 rounded-xl bg-foreground/4 border border-border',\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nAIInputLeadingIcon.displayName = 'AIInput.LeadingIcon';\n\n// =============================================================================\n// AIInput.SendButton - The send/submit button\n// =============================================================================\n\nexport interface AIInputSendButtonProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {\n /** Icon component to render */\n icon?: React.ComponentType<{ className?: string }>;\n}\n\nfunction AIInputSendButton({\n icon,\n className,\n ...props\n}: AIInputSendButtonProps) {\n const ctx = useAIInputContext();\n const Icon = icon ?? ArrowUp;\n\n return (\n <Button\n type=\"button\"\n data-slot=\"ai-input-send-button\"\n size=\"icon-sm\"\n onClick={ctx.handleSubmit}\n disabled={ctx.disabled || !ctx.hasText}\n aria-label=\"Send message\"\n className={cn(\n 'rounded-full bg-primary hover:bg-primary/90 text-primary-foreground disabled:bg-accent disabled:text-muted-foreground',\n 'transition-all duration-150 ease-out active:scale-90 motion-reduce:active:scale-100',\n className,\n )}\n {...props}\n >\n <Icon className=\"size-4\" />\n </Button>\n );\n}\n\nAIInputSendButton.displayName = 'AIInput.SendButton';\n\n// =============================================================================\n// AIInput.AttachButton - Attach file button\n// =============================================================================\n\nexport interface AIInputAttachButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Icon component to render */\n icon: React.ComponentType<{ className?: string }>;\n /** Tooltip text */\n tooltip?: string;\n}\n\nfunction AIInputAttachButton({\n icon: Icon,\n tooltip,\n className,\n onClick,\n ...props\n}: AIInputAttachButtonProps) {\n const ctx = useAIInputContext();\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n if (onClick) {\n onClick(e);\n } else if (ctx.onFilesSelected) {\n ctx.openFilePicker();\n }\n },\n [onClick, ctx.onFilesSelected, ctx.openFilePicker],\n );\n\n return (\n <button\n type=\"button\"\n data-slot=\"ai-input-attach-button\"\n onClick={handleClick}\n disabled={ctx.disabled}\n title={tooltip}\n aria-label={tooltip ?? 'Attach file'}\n className={cn(\n 'p-2.5 min-h-11 min-w-11 flex items-center justify-center rounded-full text-secondary-foreground hover:bg-accent transition-colors disabled:opacity-50 disabled:cursor-not-allowed',\n className,\n )}\n {...props}\n >\n <Icon className=\"size-4\" />\n </button>\n );\n}\n\nAIInputAttachButton.displayName = 'AIInput.AttachButton';\n\n// =============================================================================\n// AIInput.Actions - Container for action buttons\n// =============================================================================\n\nexport interface AIInputActionsProps {\n /** Children (action buttons) */\n children?: React.ReactNode;\n /** Position of actions */\n position?: 'leading' | 'trailing';\n /** Additional class name */\n className?: string;\n}\n\nfunction AIInputActions({\n children,\n position = 'leading',\n className,\n}: AIInputActionsProps) {\n return (\n <div\n data-slot=\"ai-input-actions\"\n data-position={position}\n className={cn('flex items-center gap-2', className)}\n >\n {children}\n </div>\n );\n}\n\nAIInputActions.displayName = 'AIInput.Actions';\n\n// =============================================================================\n// AIInput.ActionBar - The bottom action bar (for default variant)\n// =============================================================================\n\nexport interface AIInputActionBarProps {\n /** Children (leading actions, trailing actions, send button) */\n children?: React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIInputActionBar({ children, className }: AIInputActionBarProps) {\n const ctx = useAIInputContext();\n const isCompactRow = ctx.variant === 'compact' && !ctx.hasAttachments;\n\n return (\n <div\n data-slot=\"ai-input-action-bar\"\n className={cn(\n 'flex items-center',\n isCompactRow ? 'shrink-0 gap-3' : 'justify-between w-full',\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nAIInputActionBar.displayName = 'AIInput.ActionBar';\n\n// =============================================================================\n// AIInput.FilePreview - File attachments section\n// =============================================================================\n\nexport interface AIInputFilePreviewProps {\n /** Additional class name */\n className?: string;\n}\n\nfunction AIInputFilePreview({ className }: AIInputFilePreviewProps) {\n const ctx = useAIInputContext();\n\n if (!ctx.hasAttachments) return null;\n\n const completedFiles = ctx.uploadingFiles.filter(\n (f) => f.status === 'complete' || f.progress >= 100,\n );\n\n // Compact/inline variants use the mobile file mini-card.\n if (ctx.variant !== 'default') {\n return (\n <div\n data-slot=\"ai-input-file-preview\"\n className={cn('w-full flex flex-col gap-2', className)}\n >\n <div className=\"flex gap-2 w-full overflow-x-auto\">\n {ctx.uploadingFiles.map((file, index) => (\n <FileUploadItem\n key={file.id}\n mobile\n fileName={file.name}\n fileExtension={file.fileExtension ?? file.name.split('.').pop()}\n progress={file.progress}\n status={file.status}\n className=\"shrink-0 delight-stagger\"\n style={\n {\n '--delight-delay': `${index * 60}ms`,\n } as React.CSSProperties\n }\n onRemove={() => ctx.onRemoveFile?.(file.id)}\n onCancel={() => ctx.onCancelUpload?.(file.id)}\n onRetry={() => ctx.onRetryUpload?.(file.id)}\n />\n ))}\n </div>\n <div className=\"flex items-center justify-between w-full\">\n <span className=\"text-xs text-card-foreground\">\n {completedFiles.length} file\n {completedFiles.length !== 1 ? 's' : ''} added\n </span>\n <RemoveAllButton onClick={ctx.onRemoveAllFiles} />\n </div>\n <div className=\"w-full h-px bg-border\" />\n </div>\n );\n }\n\n // Default variant uses the horizontal file mini-card.\n return (\n <div\n data-slot=\"ai-input-file-preview\"\n className={cn('w-full flex flex-col gap-2', className)}\n >\n <div className=\"flex items-start gap-2 w-full overflow-x-auto\">\n {ctx.uploadingFiles.map((file, index) => (\n <FileUploadItem\n key={file.id}\n fileName={file.name}\n fileSize={file.size}\n fileExtension={file.fileExtension ?? file.name.split('.').pop()}\n progress={file.progress}\n status={file.status}\n className=\"flex-1 min-w-0 delight-stagger\"\n style={\n { '--delight-delay': `${index * 60}ms` } as React.CSSProperties\n }\n onRemove={() => ctx.onRemoveFile?.(file.id)}\n onCancel={() => ctx.onCancelUpload?.(file.id)}\n onRetry={() => ctx.onRetryUpload?.(file.id)}\n />\n ))}\n </div>\n <div className=\"flex items-end justify-between w-full\">\n <span className=\"text-xs text-card-foreground\">\n {completedFiles.length} file\n {completedFiles.length !== 1 ? 's' : ''} added\n </span>\n <RemoveAllButton onClick={ctx.onRemoveAllFiles} />\n </div>\n <div className=\"w-full h-px bg-border\" />\n </div>\n );\n}\n\nAIInputFilePreview.displayName = 'AIInput.FilePreview';\n\n// =============================================================================\n// Monolithic AIInput Component (Batteries-Included)\n// =============================================================================\n\nexport interface AIInputProps extends VariantProps<typeof inputVariants> {\n /** Visual variant of the input */\n variant?: 'default' | 'compact' | 'inline';\n /** Placeholder text */\n placeholder?: string;\n /** Current input value */\n value?: string;\n /** Initial input value for uncontrolled usage */\n defaultValue?: string;\n /** Callback when value changes */\n onChange?: (value: string) => void;\n /** Callback when message is submitted */\n onSubmit?: (message: string) => void;\n /** Files being uploaded */\n uploadingFiles?: UploadingFile[];\n /** Callback when file is removed */\n onRemoveFile?: (fileId: string) => void;\n /** Callback when file upload is cancelled */\n onCancelUpload?: (fileId: string) => void;\n /** Callback to retry a failed upload */\n onRetryUpload?: (fileId: string) => void;\n /** Callback to remove all files */\n onRemoveAllFiles?: () => void;\n /** Callback when files are selected (via drag-drop or file picker) */\n onFilesSelected?: (files: FileList) => void;\n /** Accepted file types (e.g. 'image/*,.pdf') */\n accept?: string;\n /** Allow multiple file selection */\n multiple?: boolean;\n /** Text shown in the drop overlay */\n dropText?: string;\n /** Whether the input is disabled */\n disabled?: boolean;\n /** Additional class name */\n className?: string;\n\n // ==========================================================================\n // Slot Props (for customizing buttons)\n // ==========================================================================\n\n /** Actions rendered on the left side of the action bar, or before submit in inline mode */\n leadingActions?: React.ReactNode;\n /** Actions rendered on the right side, before submit button */\n trailingActions?: React.ReactNode;\n /** Custom submit button render function - receives onClick and disabled */\n submitButton?: SubmitButtonRenderFn;\n /** Custom default button render function (default variant only) - receives disabled */\n defaultButton?: DefaultButtonRenderFn;\n /** Leading icon for inline variant (brand icon, spinner, avatar). Required for inline, ignored for other variants. */\n leadingIcon?: React.ReactNode;\n /** Convert large/structured paste into a file attachment. */\n pasteAsFile?: PasteAsFileProp;\n}\n\nfunction AIInputDefault({\n variant = 'default',\n placeholder = 'How can HUMAIN ONE help you today?',\n value,\n defaultValue = '',\n onChange,\n onSubmit,\n uploadingFiles = [],\n onRemoveFile,\n onCancelUpload,\n onRetryUpload,\n onRemoveAllFiles,\n onFilesSelected,\n accept,\n multiple = true,\n dropText = 'Drop files to attach',\n disabled = false,\n className,\n // Slot props\n leadingActions,\n trailingActions,\n submitButton,\n defaultButton,\n leadingIcon,\n pasteAsFile,\n}: AIInputProps) {\n const [internalValue, setInternalValue] = React.useState(defaultValue);\n const [isFocused, setIsFocused] = React.useState(false);\n const textareaRef = React.useRef<HTMLTextAreaElement>(null);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n\n const { isDragging, dropZoneProps } = useDropZone({\n onFilesSelected,\n accept,\n multiple,\n disabled,\n containerRef: rootRef,\n });\n\n const inputValue = value !== undefined ? value : internalValue;\n const hasText = inputValue.trim().length > 0;\n const hasAttachments = uploadingFiles.length > 0;\n const isControlled = value !== undefined;\n\n const isInline = variant === 'inline';\n const isDefault = variant === 'default';\n\n // Determine visual state\n const getState = (): VariantProps<typeof inputVariants>['state'] => {\n if (disabled) return 'disabled';\n if (isDragging) return 'dragover';\n if (hasAttachments) return 'attachments';\n if (hasText) return 'withText';\n if (isFocused) return 'focused';\n return 'default';\n };\n\n const setValue = React.useCallback(\n (next: string) => {\n if (onChange) {\n onChange(next);\n }\n if (!isControlled) {\n setInternalValue(next);\n }\n },\n [onChange, isControlled],\n );\n\n const handleChange = (\n e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,\n ) => {\n setValue(e.target.value);\n };\n\n const { onPaste } = usePasteAsFile({\n pasteAsFile,\n onFilesSelected,\n accept,\n disabled,\n variant,\n value: inputValue,\n setValue,\n });\n\n const handleSubmit = () => {\n if (hasText && onSubmit) {\n onSubmit(inputValue);\n if (!isControlled) {\n setInternalValue('');\n }\n }\n };\n\n const handleKeyDown = (\n e: React.KeyboardEvent<HTMLTextAreaElement | HTMLInputElement>,\n ) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n const handleClear = () => {\n if (onChange) {\n onChange('');\n }\n if (!isControlled) {\n setInternalValue('');\n }\n if (variant === 'inline') {\n inputRef.current?.focus();\n } else {\n textareaRef.current?.focus();\n }\n };\n\n // Shared: completed file count for file preview sections\n const completedCount = uploadingFiles.filter(\n (f) => f.status === 'complete' || f.progress >= 100,\n ).length;\n\n // Compact file preview (shared by compact + inline variants, skipped for default)\n const compactFilePreview = !isDefault && hasAttachments && (\n <div\n data-slot=\"ai-input-file-preview\"\n className=\"w-full flex flex-col gap-2\"\n >\n <div className=\"flex gap-2 w-full overflow-x-auto\">\n {uploadingFiles.map((file, index) => (\n <FileUploadItem\n key={file.id}\n mobile\n fileName={file.name}\n fileExtension={file.fileExtension ?? file.name.split('.').pop()}\n progress={file.progress}\n status={file.status}\n className=\"shrink-0 delight-stagger\"\n style={\n { '--delight-delay': `${index * 60}ms` } as React.CSSProperties\n }\n onRemove={() => onRemoveFile?.(file.id)}\n onCancel={() => onCancelUpload?.(file.id)}\n onRetry={() => onRetryUpload?.(file.id)}\n />\n ))}\n </div>\n <div className=\"flex items-center justify-between w-full\">\n <span className=\"text-xs text-card-foreground\">\n {completedCount} file\n {completedCount !== 1 ? 's' : ''} added\n </span>\n <RemoveAllButton onClick={onRemoveAllFiles} />\n </div>\n <div className=\"w-full h-px bg-border\" />\n </div>\n );\n\n // Inline variant\n if (isInline) {\n return (\n <div\n ref={rootRef}\n data-slot=\"ai-input\"\n data-dragging={isDragging}\n {...dropZoneProps}\n {...(onFilesSelected\n ? { 'aria-label': 'Chat input with file drop zone' }\n : {})}\n className={getAIInputShellClassName({\n state: getState(),\n variant: 'inline',\n className,\n })}\n >\n <div\n data-slot=\"ai-input-inner\"\n className={cn(\n inputVariants({ state: getState(), variant: 'inline' }),\n 'relative bg-transparent',\n hasAttachments && 'flex-col items-stretch py-3',\n )}\n >\n {isDragging && (\n <DropOverlay isDefault={isDefault} dropText={dropText} />\n )}\n {compactFilePreview}\n\n <div className=\"flex items-center gap-2 w-full\">\n {leadingIcon ? (\n <AIInputLeadingIcon>{leadingIcon}</AIInputLeadingIcon>\n ) : null}\n\n <input\n ref={inputRef}\n data-slot=\"ai-input-text\"\n type=\"text\"\n value={inputValue}\n onChange={handleChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n aria-label={placeholder}\n disabled={disabled}\n className=\"flex-1 min-w-0 bg-transparent text-sm leading-5 text-foreground placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:text-muted-foreground\"\n />\n\n {leadingActions}\n {trailingActions}\n\n <AIInputSubmitButton\n customButton={submitButton}\n onClick={handleSubmit}\n disabled={disabled || !hasText}\n />\n </div>\n </div>\n </div>\n );\n }\n\n // Compact variant\n if (!isDefault) {\n return (\n <div\n ref={rootRef}\n data-slot=\"ai-input\"\n data-dragging={isDragging}\n {...dropZoneProps}\n {...(onFilesSelected\n ? { 'aria-label': 'Chat input with file drop zone' }\n : {})}\n className={getAIInputShellClassName({\n state: getState(),\n variant: 'compact',\n className,\n })}\n >\n <div\n data-slot=\"ai-input-inner\"\n className={cn(\n inputVariants({ state: getState(), variant: 'compact' }),\n 'relative bg-transparent',\n hasAttachments && 'flex-col items-stretch',\n )}\n >\n {isDragging && (\n <DropOverlay isDefault={isDefault} dropText={dropText} />\n )}\n {compactFilePreview}\n\n <div\n data-slot=\"ai-input-text-area\"\n className={cn(\n 'flex gap-2',\n hasAttachments\n ? 'w-full items-start'\n : 'min-w-0 flex-1 items-center',\n )}\n >\n <textarea\n ref={textareaRef}\n data-slot=\"ai-input-textarea\"\n value={inputValue}\n onChange={handleChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n onPaste={onPaste}\n placeholder={placeholder}\n aria-label={placeholder}\n disabled={disabled}\n rows={1}\n className={compactTextareaClasses}\n />\n </div>\n\n <div\n data-slot=\"ai-input-action-bar\"\n className={cn(\n 'flex items-center',\n hasAttachments ? 'justify-between w-full' : 'shrink-0 gap-3',\n )}\n >\n <div\n data-slot=\"ai-input-actions\"\n className=\"flex items-center gap-2\"\n >\n {leadingActions}\n </div>\n <div\n data-slot=\"ai-input-actions\"\n className=\"flex items-center gap-2\"\n >\n {trailingActions}\n {hasText ? (\n <AIInputSubmitButton\n customButton={submitButton}\n onClick={handleSubmit}\n disabled={disabled || !hasText}\n />\n ) : (\n <AIInputDefaultButton\n customButton={defaultButton}\n disabled={disabled}\n />\n )}\n </div>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div\n ref={rootRef}\n data-slot=\"ai-input\"\n data-dragging={isDragging}\n {...dropZoneProps}\n {...(onFilesSelected\n ? { 'aria-label': 'Chat input with file drop zone' }\n : {})}\n className={getAIInputShellClassName({\n state: getState(),\n variant: 'default',\n className,\n })}\n >\n <div\n data-slot=\"ai-input-inner\"\n className={cn(\n inputVariants({ state: getState(), variant: 'default' }),\n 'relative bg-transparent',\n )}\n >\n {isDragging && (\n <DropOverlay isDefault={isDefault} dropText={dropText} />\n )}\n {/* Attachments Section (above input, matching Figma layout) */}\n {hasAttachments && (\n <div\n data-slot=\"ai-input-file-preview\"\n className=\"w-full flex flex-col gap-2\"\n >\n <div className=\"flex items-start gap-2 w-full overflow-x-auto\">\n {uploadingFiles.map((file, index) => (\n <FileUploadItem\n key={file.id}\n fileName={file.name}\n fileSize={file.size}\n fileExtension={\n file.fileExtension ?? file.name.split('.').pop()\n }\n progress={file.progress}\n status={file.status}\n className=\"flex-1 min-w-0 delight-stagger\"\n style={\n {\n '--delight-delay': `${index * 60}ms`,\n } as React.CSSProperties\n }\n onRemove={() => onRemoveFile?.(file.id)}\n onCancel={() => onCancelUpload?.(file.id)}\n onRetry={() => onRetryUpload?.(file.id)}\n />\n ))}\n </div>\n\n <div className=\"flex items-end justify-between w-full\">\n <span className=\"text-xs text-card-foreground\">\n {completedCount} file\n {completedCount !== 1 ? 's' : ''} added\n </span>\n <RemoveAllButton onClick={onRemoveAllFiles} />\n </div>\n\n <div className=\"w-full h-px bg-border\" />\n </div>\n )}\n\n <div\n data-slot=\"ai-input-text-area\"\n className=\"flex items-start gap-2 w-full\"\n >\n <textarea\n ref={textareaRef}\n data-slot=\"ai-input-textarea\"\n value={inputValue}\n onChange={handleChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n onPaste={onPaste}\n placeholder={placeholder}\n aria-label={placeholder}\n disabled={disabled}\n rows={1}\n className={textareaClasses}\n />\n {hasText && !disabled && (\n <button\n type=\"button\"\n onClick={handleClear}\n aria-label=\"Clear input\"\n className=\"p-2 rounded-full hover:bg-accent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring transition-colors duration-150 ease-out shrink-0\"\n >\n <X className=\"size-5 text-muted-foreground\" />\n </button>\n )}\n </div>\n\n <div\n data-slot=\"ai-input-action-bar\"\n className=\"flex items-center justify-between w-full\"\n >\n <div data-slot=\"ai-input-actions\" className=\"flex items-center gap-2\">\n {leadingActions}\n </div>\n\n <div data-slot=\"ai-input-actions\" className=\"flex items-center gap-2\">\n {trailingActions}\n {hasText ? (\n <AIInputSubmitButton\n customButton={submitButton}\n onClick={handleSubmit}\n disabled={disabled || !hasText}\n />\n ) : (\n <AIInputDefaultButton\n customButton={defaultButton}\n disabled={disabled}\n />\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nAIInputDefault.displayName = 'AIInput';\n\n// =============================================================================\n// Export: Object.assign for dual-API\n// =============================================================================\n\n/**\n * AIInput - Dual-API component for AI chat input.\n *\n * Supports two usage patterns:\n *\n * 1. **Monolithic API (batteries-included)**:\n * ```tsx\n * <AIInput\n * placeholder=\"Ask anything...\"\n * onSubmit={handleSubmit}\n * leadingActions={<AIInput.ActionButton icon={Plus} />}\n * />\n * ```\n *\n * 2. **Composable API (full customization)**:\n * ```tsx\n * <AIInput.Root onSubmit={handleSubmit}>\n * <AIInput.TextArea placeholder=\"Ask anything...\" />\n * <AIInput.ActionBar>\n * <AIInput.Actions position=\"leading\">\n * <AIInput.AttachButton icon={Plus} tooltip=\"Add file\" />\n * </AIInput.Actions>\n * <AIInput.Actions position=\"trailing\">\n * <AIInput.SendButton />\n * </AIInput.Actions>\n * </AIInput.ActionBar>\n * <AIInput.FilePreview />\n * </AIInput.Root>\n * ```\n */\nconst AIInput = Object.assign(AIInputDefault, {\n Root: AIInputRoot,\n TextArea: AIInputTextArea,\n LeadingIcon: AIInputLeadingIcon,\n SendButton: AIInputSendButton,\n AttachButton: AIInputAttachButton,\n Actions: AIInputActions,\n ActionBar: AIInputActionBar,\n FilePreview: AIInputFilePreview,\n // Legacy compound components (also available on main export)\n ActionButton,\n SubmitButton,\n CompactActionButton,\n});\n\nexport {\n // Compound components (also available as AIInput.X)\n ActionButton,\n AIInput,\n AIInputActionBar,\n AIInputActions,\n AIInputAttachButton,\n AIInputFilePreview,\n AIInputLeadingIcon,\n // New composable components\n AIInputRoot,\n AIInputSendButton,\n AIInputTextArea,\n CompactActionButton,\n inputVariants,\n SubmitButton,\n // Context hook for custom subcomponents\n useAIInputContext,\n};\n\n// Note: SubmitButtonRenderProps, SubmitButtonRenderFn, DefaultButtonRenderProps,\n// and DefaultButtonRenderFn are exported at their definition sites above\n"],"mappings":";;;;;;;;;;;AAkBA,IAAM,kBACJ;AAEF,IAAM,yBACJ;AAMF,IAAM,gBAAgB,IACpB,gGACA;CACE,UAAU;EACR,OAAO;GACL,SAAS;GACT,SAAS;GACT,UAAU;GACV,UAAU;GACV,aAAa;GACb,UAAU;EACZ;EACA,SAAS;GACP,SAAS;GACT,SAAS;GACT,QAAQ;EACV;CACF;CACA,iBAAiB;EACf,OAAO;EACP,SAAS;CACX;AACF,CACF;AAEA,SAAS,yBAAyB,EAChC,OACA,SACA,aAKC;CAWD,OAAO,GACL,kLAXgB,YAAY,YAYhB,8BAA8B,eAXzB,UAAU,aAavB,2BAXJ,UAAU,aACV,UAAU,cACV,UAAU,iBACV,UAAU,aAUJ,mBACA,uCATN,UAAU,aAAa,UAAU,cAAc,UAAU,aAUzC,aAAa,mBAC7B,SACF;AACF;AAMA,SAAS,YAAY,EACnB,WACA,YAIC;CACD,OACE,qBAAC,OAAD;EACE,aAAU;EACV,MAAK;EACL,aAAU;EACV,WAAW,GACT,oLACA,YAAY,+BAA+B,0BAC7C;EAPF,UAAA,CASE,oBAAC,WAAD,EAAW,WAAU,2CAA4C,CAAA,GACjE,oBAAC,QAAD;GAAM,WAAU;GACb,UAAA;EACG,CAAA,CACH;;AAET;AAEA,YAAY,cAAc;AA4D1B,SAAS,eAAe,MAEtB;CACA,MAAM,aAAa,QAAM,OAAO,CAAC;CACjC,MAAM,YAAY,QAAM,OAAO,KAAK;CACpC,MAAM,UAAU,QAAM,OAAO,IAAI;CAKjC,QAAM,gBAAgB;EACpB,QAAQ,UAAU;CACpB,CAAC;CAED,MAAM,UAAU,QAAM,aAEnB,MAAM;EACP,MAAM,EAAE,aAAa,iBAAiB,QAAQ,UAAU,OAAO,aAC7D,QAAQ;EAEV,IAAI,CAAC,eAAe,UAAU;EAE9B,MAAM,OAAO,EAAE,cAAc,QAAQ,YAAY;EACjD,IAAI,CAAC,MAAM;EAEX,MAAM,SAA4B,gBAAgB,OAAO,CAAC,IAAI;EAE9D,MAAM,gBAAgB;GACpB,eAAe,OAAO;GACtB,eAAe,OAAO;GACtB,kBAAkB,OAAO;EAC3B;EAEA,MAAM,EAAE,eAAe,SAAS,aAAa,MAAM,aAAa;EAChE,IAAI,CAAC,eAAe;EAEpB,IAAI,CAAC,iBAAiB;GACpB,IAAA,QAAA,IAAA,aAA6B,gBAAgB,CAAC,UAAU,SAAS;IAC/D,QAAQ,KACN,wFACF;IACA,UAAU,UAAU;GACtB;GACA;EACF;EAEA,MAAM,EAAE,KAAK,SAAS,cAAc,IAAI;EACxC,MAAM,eAAe,WAAW,UAAU;EAC1C,MAAM,WAAW,UAAU,aAAa,GAAG;EAE3C,IACE,UACA,CAAC,OACE,MAAM,GAAG,CAAC,CACV,MAAM,UACL,mBAAmB;GAAE,MAAM;GAAU,MAAM;EAAK,GAAG,KAAK,CAC1D,GAEF;EAGF,IAAI;EACJ,IAAI;GACF,MAAM,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,UAAU,EAAE,MAAM,KAAK,CAAC;GACtD,WAAW,WAAW,CAAC,IAAI,CAAC;EAC9B,QAAQ;GACN,IAAA,QAAA,IAAA,aAA6B,cAC3B,QAAQ,KACN,mEACF;GAEF;EACF;EAEA,EAAE,eAAe;EACjB,WAAW,UAAU;EACrB,gBAAgB,QAAQ;EAExB,IAAI,OAAO,iBAAiB;GAC1B,MAAM,MAAM,OAAO,gBAAgB,UAAU,IAAI;GACjD,IAAI,KAAK,KAAK,GACZ,SAAS,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG;EAE5C;EAEA,OAAO,cAAc,UAAU,IAAI;CACrC,GAAG,CAAC,CAAC;CAEL,IAAI,KAAK,YAAY,YAAY,CAAC,KAAK,aACrC,OAAO,EAAE,SAAS,KAAA,EAAU;CAG9B,OAAO,EAAE,QAAQ;AACnB;AAuDA,IAAM,CAAC,gBAAgB,qBACrB,kBAAuC,SAAS;AAclD,SAAS,aAAa,EACpB,MAAM,MACN,SACA,UACA,SACA,WACA,GAAG,SACiB;CACpB,OACE,oBAAC,UAAD;EACE,MAAK;EACL,aAAU;EACD;EACC;EACV,OAAO;EACP,cAAY;EACZ,WAAW,GACT,gIACA,SACF;EACA,GAAI;EAEJ,UAAA,oBAAC,MAAD,EAAM,WAAU,SAAU,CAAA;CACpB,CAAA;AAEZ;AAEA,aAAa,cAAc;AAQ3B,SAAS,aAAa,EACpB,MAAM,OAAO,SACb,WACA,SACA,UACA,GAAG,SACiB;CACpB,OACE,oBAAC,QAAD;EACE,MAAK;EACL,aAAU;EACV,MAAK;EACI;EACC;EACV,cAAW;EACX,WAAW,GACT,iKACA,SACF;EACA,GAAI;EAEJ,UAAA,oBAAC,MAAD,EAAM,WAAU,SAAU,CAAA;CACpB,CAAA;AAEZ;AAEA,aAAa,cAAc;;;;AAa3B,SAAS,oBAAoB,EAC3B,MAAM,MACN,WACA,SACA,UACA,GAAG,SACwB;CAC3B,OACE,oBAAC,QAAD;EACE,MAAK;EACL,aAAU;EACD;EACC;EACV,YAAW;EACX,SAAQ;EACR,MAAK;EACL,WAAW,GACT,6DACA,SACF;EACA,GAAI;EAEJ,UAAA,oBAAC,MAAD,EAAM,WAAU,SAAU,CAAA;CACpB,CAAA;AAEZ;AAEA,oBAAoB,cAAc;AAElC,SAAS,gBAAgB,EAAE,WAAqC;CAC9D,OACE,qBAAC,UAAD;EACE,MAAK;EACI;EACT,cAAW;EACX,WAAU;EAJZ,UAAA,CAME,oBAAC,GAAD,EAAG,WAAU,SAAU,CAAA,GAAC,YAElB;;AAEZ;AAEA,gBAAgB,cAAc;AA2B9B,SAAS,oBAAoB,EAC3B,cACA,SACA,YAKC;CACD,MAAM,cAAuC;EAC3C;EACA;CACF;CAEA,IAAI,cACF,OAAO,aAAa,WAAW;CAGjC,OAAO,oBAAC,cAAD,EAAc,GAAI,YAAc,CAAA;AACzC;AAEA,SAAS,qBAAqB,EAC5B,cACA,YAIC;CACD,MAAM,cAAwC,EAC5C,SACF;CAEA,IAAI,cACF,OAAO,aAAa,WAAW;CAGjC,OAAO,oBAAC,cAAD;EAAc,MAAM;EAAS,GAAI;CAAc,CAAA;AACxD;AA6CA,SAAS,YAAY,EACnB,UACA,UAAU,WACV,OAAO,iBACP,eAAe,IACf,UACA,UACA,iBAAiB,CAAC,GAClB,cACA,gBACA,eACA,kBACA,WAAW,OACX,WACA,iBACA,QACA,WAAW,MACX,WAAW,wBACX,eACmB;CACnB,MAAM,CAAC,eAAe,oBAAoB,QAAM,SAAS,YAAY;CACrE,MAAM,CAAC,WAAW,gBAAgB,QAAM,SAAS,KAAK;CACtD,MAAM,cAAc,QAAM,OAA4B,IAAI;CAC1D,MAAM,WAAW,QAAM,OAAyB,IAAI;CACpD,MAAM,UAAU,QAAM,OAAuB,IAAI;CAEjD,MAAM,EAAE,YAAY,eAAe,mBAAmB,YAAY;EAChE;EACA;EACA;EACA;EACA,cAAc;CAChB,CAAC;CAED,MAAM,eAAe,oBAAoB,KAAA;CACzC,MAAM,QAAQ,eAAe,kBAAkB;CAC/C,MAAM,UAAU,MAAM,KAAK,CAAC,CAAC,SAAS;CACtC,MAAM,iBAAiB,eAAe,SAAS;CAC/C,MAAM,WAAW,QAAM,aACpB,aAAqB;EACpB,IAAI,UACF,SAAS,QAAQ;EAEnB,IAAI,CAAC,cACH,iBAAiB,QAAQ;CAE7B,GACA,CAAC,UAAU,YAAY,CACzB;CAEA,MAAM,EAAE,YAAY,eAAe;EACjC;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,eAAe,QAAM,kBAAkB;EAC3C,IAAI,WAAW,UAAU;GACvB,SAAS,KAAK;GACd,IAAI,CAAC,cACH,iBAAiB,EAAE;EAEvB;CACF,GAAG;EAAC;EAAS;EAAU;EAAO;CAAY,CAAC;CAE3C,MAAM,gBAAgB,QAAM,aACzB,MAAmE;EAClE,IAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;GACpC,EAAE,eAAe;GACjB,aAAa;EACf;CACF,GACA,CAAC,YAAY,CACf;CAEA,MAAM,cAAc,QAAM,kBAAkB;EAC1C,SAAS,EAAE;EACX,IAAI,YAAY,UACd,SAAS,SAAS,MAAM;OAExB,YAAY,SAAS,MAAM;CAE/B,GAAG,CAAC,UAAU,OAAO,CAAC;CAGtB,MAAM,iBAA8D;EAClE,IAAI,UAAU,OAAO;EACrB,IAAI,YAAY,OAAO;EACvB,IAAI,gBAAgB,OAAO;EAC3B,IAAI,SAAS,OAAO;EACpB,IAAI,WAAW,OAAO;EACtB,OAAO;CACT;CAEA,MAAM,eAAe,QAAM,eAClB;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,IACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CACF;CAEA,MAAM,YAAY,YAAY;CAC9B,MAAM,QAAQ,SAAS;CAEvB,OACE,oBAAC,eAAe,UAAhB;EAAyB,OAAO;EAC9B,UAAA,oBAAC,OAAD;GACE,KAAK;GACL,aAAU;GACV,iBAAe;GACf,GAAI;GACJ,GAAK,kBACD,EAAE,cAAc,iCAAiC,IACjD,CAAC;GACL,WAAW,yBAAyB;IAAE;IAAO;IAAS;GAAU,CAAC;GAEjE,UAAA,qBAAC,OAAD;IACE,aAAU;IACV,WAAW,GACT,cAAc;KAAE;KAAO;IAAQ,CAAC,GAChC,YACA,CAAC,aAAa,kBAAkB,+BAChC,YAAY,CAAC,YAAY,aAAa,iBACtC,qBACA,YAAY,aAAa,UAC3B;IATF,UAAA,CAWG,cACC,oBAAC,aAAD;KAAwB;KAAqB;IAAW,CAAA,GAEzD,QACE;;EACF,CAAA;CACkB,CAAA;AAE7B;AAEA,YAAY,cAAc;AAe1B,SAAS,gBAAgB,EACvB,cAAc,sCACd,WACA,kBAAkB,QACK;CACvB,MAAM,MAAM,kBAAkB;CAC9B,MAAM,WAAW,IAAI,YAAY;CAEjC,MAAM,gBACJ,MACG;EACH,IAAI,SAAS,EAAE,OAAO,KAAK;CAC7B;CAEA,IAAI,UACF,OACE,oBAAC,SAAD;EACE,KAAK,IAAI;EACT,aAAU;EACV,MAAK;EACL,OAAO,IAAI;EACX,UAAU;EACV,eAAe,IAAI,aAAa,IAAI;EACpC,cAAc,IAAI,aAAa,KAAK;EACpC,WAAW,IAAI;EACF;EACb,cAAY;EACZ,UAAU,IAAI;EACd,WAAW,GACT,2LACA,SACF;CACD,CAAA;CAIL,OACE,qBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,cACA,IAAI,YAAY,aAAa,CAAC,IAAI,iBAC9B,gCACA,oBACN;EAPF,UAAA,CASE,oBAAC,YAAD;GACE,KAAK,IAAI;GACT,aAAU;GACV,OAAO,IAAI;GACX,UAAU;GACV,SAAS,IAAI;GACb,eAAe,IAAI,aAAa,IAAI;GACpC,cAAc,IAAI,aAAa,KAAK;GACpC,WAAW,IAAI;GACF;GACb,cAAY;GACZ,UAAU,IAAI;GACd,MAAM;GACN,WAAW,GACT,IAAI,YAAY,YAAY,yBAAyB,iBACrD,SACF;EACD,CAAA,GACA,mBACC,IAAI,YAAY,aAChB,IAAI,WACJ,CAAC,IAAI,YACH,oBAAC,UAAD;GACE,MAAK;GACL,SAAS,IAAI;GACb,cAAW;GACX,WAAU;GAEV,UAAA,oBAAC,GAAD,EAAG,WAAU,+BAAgC,CAAA;EACvC,CAAA,CAET;;AAET;AAEA,gBAAgB,cAAc;AAa9B,SAAS,mBAAmB,EAAE,UAAU,aAAsC;CAC5E,OACE,oBAAC,OAAD;EACE,aAAU;EACV,eAAY;EACZ,WAAW,GACT,oGACA,SACF;EAEC;CACE,CAAA;AAET;AAEA,mBAAmB,cAAc;AAYjC,SAAS,kBAAkB,EACzB,MACA,WACA,GAAG,SACsB;CACzB,MAAM,MAAM,kBAAkB;CAC9B,MAAM,OAAO,QAAQ;CAErB,OACE,oBAAC,QAAD;EACE,MAAK;EACL,aAAU;EACV,MAAK;EACL,SAAS,IAAI;EACb,UAAU,IAAI,YAAY,CAAC,IAAI;EAC/B,cAAW;EACX,WAAW,GACT,yHACA,uFACA,SACF;EACA,GAAI;EAEJ,UAAA,oBAAC,MAAD,EAAM,WAAU,SAAU,CAAA;CACpB,CAAA;AAEZ;AAEA,kBAAkB,cAAc;AAchC,SAAS,oBAAoB,EAC3B,MAAM,MACN,SACA,WACA,SACA,GAAG,SACwB;CAC3B,MAAM,MAAM,kBAAkB;CAE9B,MAAM,cAAc,QAAM,aACvB,MAA2C;EAC1C,IAAI,SACF,QAAQ,CAAC;OACJ,IAAI,IAAI,iBACb,IAAI,eAAe;CAEvB,GACA;EAAC;EAAS,IAAI;EAAiB,IAAI;CAAc,CACnD;CAEA,OACE,oBAAC,UAAD;EACE,MAAK;EACL,aAAU;EACV,SAAS;EACT,UAAU,IAAI;EACd,OAAO;EACP,cAAY,WAAW;EACvB,WAAW,GACT,qLACA,SACF;EACA,GAAI;EAEJ,UAAA,oBAAC,MAAD,EAAM,WAAU,SAAU,CAAA;CACpB,CAAA;AAEZ;AAEA,oBAAoB,cAAc;AAelC,SAAS,eAAe,EACtB,UACA,WAAW,WACX,aACsB;CACtB,OACE,oBAAC,OAAD;EACE,aAAU;EACV,iBAAe;EACf,WAAW,GAAG,2BAA2B,SAAS;EAEjD;CACE,CAAA;AAET;AAEA,eAAe,cAAc;AAa7B,SAAS,iBAAiB,EAAE,UAAU,aAAoC;CACxE,MAAM,MAAM,kBAAkB;CAC9B,MAAM,eAAe,IAAI,YAAY,aAAa,CAAC,IAAI;CAEvD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,qBACA,eAAe,mBAAmB,0BAClC,SACF;EAEC;CACE,CAAA;AAET;AAEA,iBAAiB,cAAc;AAW/B,SAAS,mBAAmB,EAAE,aAAsC;CAClE,MAAM,MAAM,kBAAkB;CAE9B,IAAI,CAAC,IAAI,gBAAgB,OAAO;CAEhC,MAAM,iBAAiB,IAAI,eAAe,QACvC,MAAM,EAAE,WAAW,cAAc,EAAE,YAAY,GAClD;CAGA,IAAI,IAAI,YAAY,WAClB,OACE,qBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,8BAA8B,SAAS;EAFvD,UAAA;GAIE,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,IAAI,eAAe,KAAK,MAAM,UAC7B,oBAAC,gBAAD;KAEE,QAAA;KACA,UAAU,KAAK;KACf,eAAe,KAAK,iBAAiB,KAAK,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI;KAC9D,UAAU,KAAK;KACf,QAAQ,KAAK;KACb,WAAU;KACV,OACE,EACE,mBAAmB,GAAG,QAAQ,GAAG,IACnC;KAEF,gBAAgB,IAAI,eAAe,KAAK,EAAE;KAC1C,gBAAgB,IAAI,iBAAiB,KAAK,EAAE;KAC5C,eAAe,IAAI,gBAAgB,KAAK,EAAE;IAC3C,GAfM,KAAK,EAeX,CACF;GACE,CAAA;GACL,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA;MACG,eAAe;MAAO;MACtB,eAAe,WAAW,IAAI,MAAM;MAAG;KACpC;IACN,CAAA,GAAA,oBAAC,iBAAD,EAAiB,SAAS,IAAI,iBAAmB,CAAA,CAC9C;;GACL,oBAAC,OAAD,EAAK,WAAU,wBAAyB,CAAA;EACrC;;CAKT,OACE,qBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,8BAA8B,SAAS;EAFvD,UAAA;GAIE,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,IAAI,eAAe,KAAK,MAAM,UAC7B,oBAAC,gBAAD;KAEE,UAAU,KAAK;KACf,UAAU,KAAK;KACf,eAAe,KAAK,iBAAiB,KAAK,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI;KAC9D,UAAU,KAAK;KACf,QAAQ,KAAK;KACb,WAAU;KACV,OACE,EAAE,mBAAmB,GAAG,QAAQ,GAAG,IAAI;KAEzC,gBAAgB,IAAI,eAAe,KAAK,EAAE;KAC1C,gBAAgB,IAAI,iBAAiB,KAAK,EAAE;KAC5C,eAAe,IAAI,gBAAgB,KAAK,EAAE;IAC3C,GAbM,KAAK,EAaX,CACF;GACE,CAAA;GACL,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA;MACG,eAAe;MAAO;MACtB,eAAe,WAAW,IAAI,MAAM;MAAG;KACpC;IACN,CAAA,GAAA,oBAAC,iBAAD,EAAiB,SAAS,IAAI,iBAAmB,CAAA,CAC9C;;GACL,oBAAC,OAAD,EAAK,WAAU,wBAAyB,CAAA;EACrC;;AAET;AAEA,mBAAmB,cAAc;AA4DjC,SAAS,eAAe,EACtB,UAAU,WACV,cAAc,sCACd,OACA,eAAe,IACf,UACA,UACA,iBAAiB,CAAC,GAClB,cACA,gBACA,eACA,kBACA,iBACA,QACA,WAAW,MACX,WAAW,wBACX,WAAW,OACX,WAEA,gBACA,iBACA,cACA,eACA,aACA,eACe;CACf,MAAM,CAAC,eAAe,oBAAoB,QAAM,SAAS,YAAY;CACrE,MAAM,CAAC,WAAW,gBAAgB,QAAM,SAAS,KAAK;CACtD,MAAM,cAAc,QAAM,OAA4B,IAAI;CAC1D,MAAM,WAAW,QAAM,OAAyB,IAAI;CACpD,MAAM,UAAU,QAAM,OAAuB,IAAI;CAEjD,MAAM,EAAE,YAAY,kBAAkB,YAAY;EAChD;EACA;EACA;EACA;EACA,cAAc;CAChB,CAAC;CAED,MAAM,aAAa,UAAU,KAAA,IAAY,QAAQ;CACjD,MAAM,UAAU,WAAW,KAAK,CAAC,CAAC,SAAS;CAC3C,MAAM,iBAAiB,eAAe,SAAS;CAC/C,MAAM,eAAe,UAAU,KAAA;CAE/B,MAAM,WAAW,YAAY;CAC7B,MAAM,YAAY,YAAY;CAG9B,MAAM,iBAA8D;EAClE,IAAI,UAAU,OAAO;EACrB,IAAI,YAAY,OAAO;EACvB,IAAI,gBAAgB,OAAO;EAC3B,IAAI,SAAS,OAAO;EACpB,IAAI,WAAW,OAAO;EACtB,OAAO;CACT;CAEA,MAAM,WAAW,QAAM,aACpB,SAAiB;EAChB,IAAI,UACF,SAAS,IAAI;EAEf,IAAI,CAAC,cACH,iBAAiB,IAAI;CAEzB,GACA,CAAC,UAAU,YAAY,CACzB;CAEA,MAAM,gBACJ,MACG;EACH,SAAS,EAAE,OAAO,KAAK;CACzB;CAEA,MAAM,EAAE,YAAY,eAAe;EACjC;EACA;EACA;EACA;EACA;EACA,OAAO;EACP;CACF,CAAC;CAED,MAAM,qBAAqB;EACzB,IAAI,WAAW,UAAU;GACvB,SAAS,UAAU;GACnB,IAAI,CAAC,cACH,iBAAiB,EAAE;EAEvB;CACF;CAEA,MAAM,iBACJ,MACG;EACH,IAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;GACpC,EAAE,eAAe;GACjB,aAAa;EACf;CACF;CAEA,MAAM,oBAAoB;EACxB,IAAI,UACF,SAAS,EAAE;EAEb,IAAI,CAAC,cACH,iBAAiB,EAAE;EAErB,IAAI,YAAY,UACd,SAAS,SAAS,MAAM;OAExB,YAAY,SAAS,MAAM;CAE/B;CAGA,MAAM,iBAAiB,eAAe,QACnC,MAAM,EAAE,WAAW,cAAc,EAAE,YAAY,GAClD,CAAC,CAAC;CAGF,MAAM,qBAAqB,CAAC,aAAa,kBACvC,qBAAC,OAAD;EACE,aAAU;EACV,WAAU;EAFZ,UAAA;GAIE,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,eAAe,KAAK,MAAM,UACzB,oBAAC,gBAAD;KAEE,QAAA;KACA,UAAU,KAAK;KACf,eAAe,KAAK,iBAAiB,KAAK,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI;KAC9D,UAAU,KAAK;KACf,QAAQ,KAAK;KACb,WAAU;KACV,OACE,EAAE,mBAAmB,GAAG,QAAQ,GAAG,IAAI;KAEzC,gBAAgB,eAAe,KAAK,EAAE;KACtC,gBAAgB,iBAAiB,KAAK,EAAE;KACxC,eAAe,gBAAgB,KAAK,EAAE;IACvC,GAbM,KAAK,EAaX,CACF;GACE,CAAA;GACL,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA;MACG;MAAe;MACf,mBAAmB,IAAI,MAAM;MAAG;KAC7B;IACN,CAAA,GAAA,oBAAC,iBAAD,EAAiB,SAAS,iBAAmB,CAAA,CAC1C;;GACL,oBAAC,OAAD,EAAK,WAAU,wBAAyB,CAAA;EACrC;;CAIP,IAAI,UACF,OACE,oBAAC,OAAD;EACE,KAAK;EACL,aAAU;EACV,iBAAe;EACf,GAAI;EACJ,GAAK,kBACD,EAAE,cAAc,iCAAiC,IACjD,CAAC;EACL,WAAW,yBAAyB;GAClC,OAAO,SAAS;GAChB,SAAS;GACT;EACF,CAAC;EAED,UAAA,qBAAC,OAAD;GACE,aAAU;GACV,WAAW,GACT,cAAc;IAAE,OAAO,SAAS;IAAG,SAAS;GAAS,CAAC,GACtD,2BACA,kBAAkB,6BACpB;GANF,UAAA;IAQG,cACC,oBAAC,aAAD;KAAwB;KAAqB;IAAW,CAAA;IAEzD;IAED,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACG,cACC,oBAAC,oBAAD,EAAA,UAAqB,YAAgC,CAAA,IACnD;MAEJ,oBAAC,SAAD;OACE,KAAK;OACL,aAAU;OACV,MAAK;OACL,OAAO;OACP,UAAU;OACV,eAAe,aAAa,IAAI;OAChC,cAAc,aAAa,KAAK;OAChC,WAAW;OACE;OACb,cAAY;OACF;OACV,WAAU;MACX,CAAA;MAEA;MACA;MAED,oBAAC,qBAAD;OACE,cAAc;OACd,SAAS;OACT,UAAU,YAAY,CAAC;MACxB,CAAA;KACE;;GACF;;CACF,CAAA;CAKT,IAAI,CAAC,WACH,OACE,oBAAC,OAAD;EACE,KAAK;EACL,aAAU;EACV,iBAAe;EACf,GAAI;EACJ,GAAK,kBACD,EAAE,cAAc,iCAAiC,IACjD,CAAC;EACL,WAAW,yBAAyB;GAClC,OAAO,SAAS;GAChB,SAAS;GACT;EACF,CAAC;EAED,UAAA,qBAAC,OAAD;GACE,aAAU;GACV,WAAW,GACT,cAAc;IAAE,OAAO,SAAS;IAAG,SAAS;GAAU,CAAC,GACvD,2BACA,kBAAkB,wBACpB;GANF,UAAA;IAQG,cACC,oBAAC,aAAD;KAAwB;KAAqB;IAAW,CAAA;IAEzD;IAED,oBAAC,OAAD;KACE,aAAU;KACV,WAAW,GACT,cACA,iBACI,uBACA,6BACN;KAEA,UAAA,oBAAC,YAAD;MACE,KAAK;MACL,aAAU;MACV,OAAO;MACP,UAAU;MACV,eAAe,aAAa,IAAI;MAChC,cAAc,aAAa,KAAK;MAChC,WAAW;MACF;MACI;MACb,cAAY;MACF;MACV,MAAM;MACN,WAAW;KACZ,CAAA;IACE,CAAA;IAEL,qBAAC,OAAD;KACE,aAAU;KACV,WAAW,GACT,qBACA,iBAAiB,2BAA2B,gBAC9C;KALF,UAAA,CAOE,oBAAC,OAAD;MACE,aAAU;MACV,WAAU;MAET,UAAA;KACE,CAAA,GACL,qBAAC,OAAD;MACE,aAAU;MACV,WAAU;MAFZ,UAAA,CAIG,iBACA,UACC,oBAAC,qBAAD;OACE,cAAc;OACd,SAAS;OACT,UAAU,YAAY,CAAC;MACxB,CAAA,IAED,oBAAC,sBAAD;OACE,cAAc;OACJ;MACX,CAAA,CAEA;KACF,CAAA,CAAA;;GACF;;CACF,CAAA;CAIT,OACE,oBAAC,OAAD;EACE,KAAK;EACL,aAAU;EACV,iBAAe;EACf,GAAI;EACJ,GAAK,kBACD,EAAE,cAAc,iCAAiC,IACjD,CAAC;EACL,WAAW,yBAAyB;GAClC,OAAO,SAAS;GAChB,SAAS;GACT;EACF,CAAC;EAED,UAAA,qBAAC,OAAD;GACE,aAAU;GACV,WAAW,GACT,cAAc;IAAE,OAAO,SAAS;IAAG,SAAS;GAAU,CAAC,GACvD,yBACF;GALF,UAAA;IAOG,cACC,oBAAC,aAAD;KAAwB;KAAqB;IAAW,CAAA;IAGzD,kBACC,qBAAC,OAAD;KACE,aAAU;KACV,WAAU;KAFZ,UAAA;MAIE,oBAAC,OAAD;OAAK,WAAU;OACZ,UAAA,eAAe,KAAK,MAAM,UACzB,oBAAC,gBAAD;QAEE,UAAU,KAAK;QACf,UAAU,KAAK;QACf,eACE,KAAK,iBAAiB,KAAK,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI;QAEjD,UAAU,KAAK;QACf,QAAQ,KAAK;QACb,WAAU;QACV,OACE,EACE,mBAAmB,GAAG,QAAQ,GAAG,IACnC;QAEF,gBAAgB,eAAe,KAAK,EAAE;QACtC,gBAAgB,iBAAiB,KAAK,EAAE;QACxC,eAAe,gBAAgB,KAAK,EAAE;OACvC,GAjBM,KAAK,EAiBX,CACF;MACE,CAAA;MAEL,qBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,qBAAC,QAAD;QAAM,WAAU;QAAhB,UAAA;SACG;SAAe;SACf,mBAAmB,IAAI,MAAM;SAAG;QAC7B;OACN,CAAA,GAAA,oBAAC,iBAAD,EAAiB,SAAS,iBAAmB,CAAA,CAC1C;;MAEL,oBAAC,OAAD,EAAK,WAAU,wBAAyB,CAAA;KACrC;;IAGP,qBAAC,OAAD;KACE,aAAU;KACV,WAAU;KAFZ,UAAA,CAIE,oBAAC,YAAD;MACE,KAAK;MACL,aAAU;MACV,OAAO;MACP,UAAU;MACV,eAAe,aAAa,IAAI;MAChC,cAAc,aAAa,KAAK;MAChC,WAAW;MACF;MACI;MACb,cAAY;MACF;MACV,MAAM;MACN,WAAW;KACZ,CAAA,GACA,WAAW,CAAC,YACX,oBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,cAAW;MACX,WAAU;MAEV,UAAA,oBAAC,GAAD,EAAG,WAAU,+BAAgC,CAAA;KACvC,CAAA,CAEP;;IAEL,qBAAC,OAAD;KACE,aAAU;KACV,WAAU;KAFZ,UAAA,CAIE,oBAAC,OAAD;MAAK,aAAU;MAAmB,WAAU;MACzC,UAAA;KACE,CAAA,GAEL,qBAAC,OAAD;MAAK,aAAU;MAAmB,WAAU;MAA5C,UAAA,CACG,iBACA,UACC,oBAAC,qBAAD;OACE,cAAc;OACd,SAAS;OACT,UAAU,YAAY,CAAC;MACxB,CAAA,IAED,oBAAC,sBAAD;OACE,cAAc;OACJ;MACX,CAAA,CAEA;KACF,CAAA,CAAA;;GACF;;CACF,CAAA;AAET;AAEA,eAAe,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoC7B,IAAM,UAAU,OAAO,OAAO,gBAAgB;CAC5C,MAAM;CACN,UAAU;CACV,aAAa;CACb,YAAY;CACZ,cAAc;CACd,SAAS;CACT,WAAW;CACX,aAAa;CAEb;CACA;CACA;AACF,CAAC"}
1
+ {"version":3,"file":"index150.js","names":[],"sources":["../src/components/organisms/ai/AIInput/AIInput.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { ArrowDown, ArrowUp, X } from 'lucide-react';\nimport * as React from 'react';\nimport { Button } from '@/components/atoms/buttons/Button';\nimport { FileUploadItem } from '@/components/molecules/files/FileUpload';\nimport {\n matchesAcceptToken,\n toFileList,\n useDropZone,\n} from '@/hooks/use-drop-zone';\nimport { createSafeContext } from '@/lib/create-safe-context';\nimport { cn } from '@/lib/utils';\nimport { analyzePaste, mapKindToFile, type PasteKind } from './paste-detection';\n\n// =============================================================================\n// Shared Styles\n// =============================================================================\n\nconst textareaClasses =\n 'flex-1 h-[40px] resize-none overflow-y-auto bg-transparent text-base text-foreground placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:text-muted-foreground';\n\nconst compactTextareaClasses =\n 'flex-1 h-[32px] resize-none overflow-y-auto bg-transparent text-base leading-6 text-foreground placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:text-muted-foreground';\n\n// =============================================================================\n// Variants\n// =============================================================================\n\nconst inputVariants = cva(\n 'flex items-center w-full transition-[color,background-color,border-color,box-shadow,opacity]',\n {\n variants: {\n state: {\n default: '',\n focused: '',\n withText: '',\n disabled: 'cursor-not-allowed',\n attachments: '',\n dragover: '',\n },\n variant: {\n default: 'flex-col gap-2 py-4 px-4 rounded-[inherit]',\n compact: 'flex-row gap-2 py-4 px-4 rounded-[inherit]',\n inline: 'flex-row gap-2 px-4 py-4 rounded-[inherit]',\n },\n },\n defaultVariants: {\n state: 'default',\n variant: 'default',\n },\n },\n);\n\nfunction getAIInputShellClassName({\n state,\n variant,\n className,\n}: {\n state: VariantProps<typeof inputVariants>['state'];\n variant: 'default' | 'compact' | 'inline';\n className?: string;\n}) {\n const isDefault = variant === 'default';\n const isDisabled = state === 'disabled';\n const isPrimaryState =\n state === 'focused' ||\n state === 'withText' ||\n state === 'attachments' ||\n state === 'dragover';\n const isStrongState =\n state === 'focused' || state === 'withText' || state === 'dragover';\n\n return cn(\n 'relative w-full overflow-hidden border bg-background shadow-[var(--shadow-ai-input)] transition-[color,background-color,border-color,box-shadow,opacity] duration-150 ease-out',\n isDefault ? 'rounded-3xl max-w-[772px]' : 'rounded-2xl',\n isDisabled\n ? 'border-border bg-muted'\n : isPrimaryState\n ? 'border-primary'\n : 'border-ring/50 hover:border-primary',\n isStrongState ? 'border-2' : 'border-[1.25px]',\n className,\n );\n}\n\n// =============================================================================\n// Drop Overlay (shared across all variants)\n// =============================================================================\n\nfunction DropOverlay({\n isDefault,\n dropText,\n}: {\n isDefault: boolean;\n dropText: string;\n}) {\n return (\n <div\n data-slot=\"ai-input-drop-overlay\"\n role=\"status\"\n aria-live=\"polite\"\n className={cn(\n 'delight-drop-enter absolute inset-1.5 border-2 border-dashed border-primary/50 dark:border-primary/60 pointer-events-none flex flex-col items-center justify-center gap-1.5 z-10',\n isDefault ? 'rounded-[calc(1.5rem-8px)]' : 'rounded-[calc(1rem-8px)]',\n )}\n >\n <ArrowDown className=\"size-4 text-primary/70 delight-drop-icon\" />\n <span className=\"text-sm text-muted-foreground font-medium\">\n {dropText}\n </span>\n </div>\n );\n}\n\nDropOverlay.displayName = 'AIInput.DropOverlay';\n\n// =============================================================================\n// File Attachment Types\n// =============================================================================\n\nexport interface UploadingFile {\n id: string;\n name: string;\n size: string;\n progress: number;\n status: 'uploading' | 'complete' | 'error';\n /** File extension for icon display (e.g., 'pdf', 'docx') */\n fileExtension?: string;\n}\n\n// =============================================================================\n// Paste-as-File public types\n// =============================================================================\n\nexport type { PasteKind } from './paste-detection';\n\nexport interface PasteAsFileConfig {\n /** Char count above which plain text always converts. Default: 500 */\n threshold?: number;\n /** Line count above which plain text always converts. Default: 10 */\n lineThreshold?: number;\n /** Run structured-content heuristics (JSON/XML/CSV/code/log). Default: true */\n detectStructured?: boolean;\n /**\n * Auto-fill textarea after conversion. Receives filename + detected kind.\n * Return string to set as textarea value (appended with leading space if textarea non-empty).\n * Empty/whitespace-only return is treated as no-op.\n * Default: undefined → textarea stays empty.\n */\n prefillTemplate?: (filename: string, kind: PasteKind) => string;\n /** Fired after onFilesSelected and prefill. */\n onConverted?: (filename: string, kind: PasteKind) => void;\n}\n\n/**\n * Accepts boolean for runtime toggling. `false` and `undefined` both disable.\n * `true` enables with defaults. Object enables with overrides.\n */\nexport type PasteAsFileProp = boolean | PasteAsFileConfig;\n\n// =============================================================================\n// usePasteAsFile — internal hook\n// =============================================================================\n\ninterface UsePasteAsFileOpts {\n pasteAsFile: PasteAsFileProp | undefined;\n onFilesSelected: ((files: FileList) => void) | undefined;\n accept: string | undefined;\n disabled: boolean;\n variant: 'default' | 'compact' | 'inline';\n value: string;\n setValue: (next: string) => void;\n}\n\nfunction usePasteAsFile(opts: UsePasteAsFileOpts): {\n onPaste?: React.ClipboardEventHandler<HTMLTextAreaElement>;\n} {\n const counterRef = React.useRef(0);\n const warnedRef = React.useRef(false);\n const optsRef = React.useRef(opts);\n\n // Keep the ref pointing at the latest opts each render. This pattern lets the\n // returned `onPaste` be referentially stable (empty-deps useCallback) while\n // still seeing the freshest pasteAsFile config and callbacks.\n React.useEffect(() => {\n optsRef.current = opts;\n });\n\n const onPaste = React.useCallback<\n React.ClipboardEventHandler<HTMLTextAreaElement>\n >((e) => {\n const { pasteAsFile, onFilesSelected, accept, disabled, value, setValue } =\n optsRef.current;\n\n if (!pasteAsFile || disabled) return;\n\n const text = e.clipboardData.getData('text/plain');\n if (!text) return;\n\n const config: PasteAsFileConfig = pasteAsFile === true ? {} : pasteAsFile;\n\n const detectionOpts = {\n charThreshold: config.threshold,\n lineThreshold: config.lineThreshold,\n detectStructured: config.detectStructured,\n };\n\n const { shouldConvert, kind } = analyzePaste(text, detectionOpts);\n if (!shouldConvert) return;\n\n if (!onFilesSelected) {\n if (process.env.NODE_ENV !== 'production' && !warnedRef.current) {\n console.warn(\n '[AIInput] pasteAsFile is set but onFilesSelected is missing. Paste-to-file is a no-op.',\n );\n warnedRef.current = true;\n }\n return;\n }\n\n const { ext, mime } = mapKindToFile(kind);\n const nProspective = counterRef.current + 1;\n const filename = `Pasted-${nProspective}.${ext}`;\n\n if (\n accept &&\n !accept\n .split(',')\n .some((token) =>\n matchesAcceptToken({ name: filename, type: mime }, token),\n )\n ) {\n return;\n }\n\n let fileList: FileList;\n try {\n const file = new File([text], filename, { type: mime });\n fileList = toFileList([file]);\n } catch {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n '[AIInput] DataTransfer unavailable; falling back to native paste.',\n );\n }\n return;\n }\n\n e.preventDefault();\n counterRef.current = nProspective;\n onFilesSelected(fileList);\n\n if (config.prefillTemplate) {\n const tpl = config.prefillTemplate(filename, kind);\n if (tpl?.trim()) {\n setValue(value ? `${value} ${tpl}` : tpl);\n }\n }\n\n config.onConverted?.(filename, kind);\n }, []);\n\n if (opts.variant === 'inline' || !opts.pasteAsFile) {\n return { onPaste: undefined };\n }\n\n return { onPaste };\n}\n\n// =============================================================================\n// Context\n// =============================================================================\n\ninterface AIInputContextValue {\n /** Current input value */\n value: string;\n /** Whether the input has text */\n hasText: boolean;\n /** Whether the input is focused */\n isFocused: boolean;\n /** Whether the input is disabled */\n disabled: boolean;\n /** Visual variant */\n variant: 'default' | 'compact' | 'inline';\n /** Files being uploaded */\n uploadingFiles: UploadingFile[];\n /** Has attachments */\n hasAttachments: boolean;\n /** Update input value */\n setValue: (value: string) => void;\n /** Set focus state */\n setIsFocused: (focused: boolean) => void;\n /** Handle submit */\n handleSubmit: () => void;\n /** Handle key down */\n handleKeyDown: (\n e: React.KeyboardEvent<HTMLTextAreaElement | HTMLInputElement>,\n ) => void;\n /** Handle clear */\n handleClear: () => void;\n /** Paste handler from usePasteAsFile (only set when paste-as-file is active). */\n onPaste?: React.ClipboardEventHandler<HTMLTextAreaElement>;\n /** Remove file */\n onRemoveFile?: (fileId: string) => void;\n /** Cancel upload */\n onCancelUpload?: (fileId: string) => void;\n /** Retry failed upload */\n onRetryUpload?: (fileId: string) => void;\n /** Remove all files */\n onRemoveAllFiles?: () => void;\n /** Whether files are being dragged over the input */\n isDragging: boolean;\n /** Open the native file picker */\n openFilePicker: () => void;\n /** Callback when files are selected (via drop or picker) */\n onFilesSelected?: (files: FileList) => void;\n /** Textarea ref (for default variant) */\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\n /** Input ref (for compact variant) */\n inputRef: React.RefObject<HTMLInputElement | null>;\n}\n\nconst [AIInputContext, useAIInputContext] =\n createSafeContext<AIInputContextValue>('AIInput');\n\n// =============================================================================\n// Compound Components - Building Blocks\n// =============================================================================\n\nexport interface ActionButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Icon component to render */\n icon: React.ComponentType<{ className?: string }>;\n /** Tooltip text */\n tooltip?: string;\n}\n\nfunction ActionButton({\n icon: Icon,\n onClick,\n disabled,\n tooltip,\n className,\n ...props\n}: ActionButtonProps) {\n return (\n <button\n type=\"button\"\n data-slot=\"action-button\"\n onClick={onClick}\n disabled={disabled}\n title={tooltip}\n aria-label={tooltip}\n className={cn(\n 'p-2 rounded-full text-secondary-foreground hover:bg-accent transition-colors disabled:opacity-50 disabled:cursor-not-allowed',\n className,\n )}\n {...props}\n >\n <Icon className=\"size-4\" />\n </button>\n );\n}\n\nActionButton.displayName = 'AIInput.ActionButton';\n\nexport interface SubmitButtonProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {\n /** Icon component to render (defaults to ArrowUp) */\n icon?: React.ComponentType<{ className?: string }>;\n}\n\nfunction SubmitButton({\n icon: Icon = ArrowUp,\n className,\n onClick,\n disabled,\n ...props\n}: SubmitButtonProps) {\n return (\n <Button\n type=\"button\"\n data-slot=\"submit-button\"\n size=\"icon-sm\"\n onClick={onClick}\n disabled={disabled}\n aria-label=\"Send message\"\n className={cn(\n 'rounded-full bg-primary hover:bg-primary/90 text-primary-foreground disabled:bg-accent disabled:text-muted-foreground transition-colors duration-150 ease-out',\n className,\n )}\n {...props}\n >\n <Icon className=\"size-4\" />\n </Button>\n );\n}\n\nSubmitButton.displayName = 'AIInput.SubmitButton';\n\nexport interface CompactActionButtonProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {\n /** Icon component to render */\n icon: React.ComponentType<{ className?: string }>;\n /** Accessible label for the icon-only button (required for a11y) */\n 'aria-label': string;\n}\n\n/**\n * @deprecated Use `ActionButton` instead. CompactActionButton will be removed in a future major version.\n */\nfunction CompactActionButton({\n icon: Icon,\n className,\n onClick,\n disabled,\n ...props\n}: CompactActionButtonProps) {\n return (\n <Button\n type=\"button\"\n data-slot=\"compact-action-button\"\n onClick={onClick}\n disabled={disabled}\n appearance=\"outline\"\n variant=\"secondary\"\n size=\"icon\"\n className={cn(\n 'rounded-full border-border text-foreground hover:bg-muted',\n className,\n )}\n {...props}\n >\n <Icon className=\"size-5\" />\n </Button>\n );\n}\n\nCompactActionButton.displayName = 'AIInput.CompactActionButton';\n\nfunction RemoveAllButton({ onClick }: { onClick?: () => void }) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label=\"Remove all attached files\"\n className=\"flex items-center gap-1.5 h-5 px-2 py-1 rounded-full bg-accent border border-border text-xs font-medium text-foreground hover:bg-accent/80 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring transition-colors\"\n >\n <X className=\"size-4\" />\n Remove all\n </button>\n );\n}\n\nRemoveAllButton.displayName = 'AIInput.RemoveAllButton';\n\n// =============================================================================\n// Render Function Types (for monolithic API)\n// =============================================================================\n\n/** Props passed to custom submit button render function */\nexport interface SubmitButtonRenderProps {\n onClick: () => void;\n disabled: boolean;\n}\n\n/** Render function type for custom submit button */\nexport type SubmitButtonRenderFn = (\n props: SubmitButtonRenderProps,\n) => React.ReactElement;\n\n/** Props passed to custom default button render function */\nexport interface DefaultButtonRenderProps {\n disabled: boolean;\n}\n\n/** Render function type for custom default button */\nexport type DefaultButtonRenderFn = (\n props: DefaultButtonRenderProps,\n) => React.ReactElement;\n\nfunction AIInputSubmitButton({\n customButton,\n onClick,\n disabled,\n}: {\n customButton?: SubmitButtonRenderFn;\n onClick: () => void;\n disabled: boolean;\n}) {\n const buttonProps: SubmitButtonRenderProps = {\n onClick,\n disabled,\n };\n\n if (customButton) {\n return customButton(buttonProps);\n }\n\n return <SubmitButton {...buttonProps} />;\n}\n\nfunction AIInputDefaultButton({\n customButton,\n disabled,\n}: {\n customButton?: DefaultButtonRenderFn;\n disabled: boolean;\n}) {\n const buttonProps: DefaultButtonRenderProps = {\n disabled,\n };\n\n if (customButton) {\n return customButton(buttonProps);\n }\n\n return <SubmitButton icon={ArrowUp} disabled />;\n}\n\n// =============================================================================\n// Composable Subcomponents (for dual-API)\n// =============================================================================\n\nexport interface AIInputRootProps {\n /** Children (composable subcomponents) */\n children: React.ReactNode;\n /** Visual variant of the input */\n variant?: 'default' | 'compact' | 'inline';\n /** Current input value (controlled) */\n value?: string;\n /** Default input value (uncontrolled) */\n defaultValue?: string;\n /** Callback when value changes */\n onChange?: (value: string) => void;\n /** Callback when message is submitted */\n onSubmit?: (message: string) => void;\n /** Files being uploaded */\n uploadingFiles?: UploadingFile[];\n /** Callback when file is removed */\n onRemoveFile?: (fileId: string) => void;\n /** Callback when file upload is cancelled */\n onCancelUpload?: (fileId: string) => void;\n /** Callback to retry a failed upload */\n onRetryUpload?: (fileId: string) => void;\n /** Callback to remove all files */\n onRemoveAllFiles?: () => void;\n /** Whether the input is disabled */\n disabled?: boolean;\n /** Additional class name */\n className?: string;\n /** Callback when files are selected (via drag-drop or file picker) */\n onFilesSelected?: (files: FileList) => void;\n /** Accepted file types (e.g. 'image/*,.pdf') */\n accept?: string;\n /** Allow multiple file selection */\n multiple?: boolean;\n /** Text shown in the drop overlay */\n dropText?: string;\n /** Convert large/structured paste into a file attachment. Requires onFilesSelected. */\n pasteAsFile?: PasteAsFileProp;\n}\n\nfunction AIInputRoot({\n children,\n variant = 'default',\n value: controlledValue,\n defaultValue = '',\n onChange,\n onSubmit,\n uploadingFiles = [],\n onRemoveFile,\n onCancelUpload,\n onRetryUpload,\n onRemoveAllFiles,\n disabled = false,\n className,\n onFilesSelected,\n accept,\n multiple = true,\n dropText = 'Drop files to attach',\n pasteAsFile,\n}: AIInputRootProps) {\n const [internalValue, setInternalValue] = React.useState(defaultValue);\n const [isFocused, setIsFocused] = React.useState(false);\n const textareaRef = React.useRef<HTMLTextAreaElement>(null);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n\n const { isDragging, dropZoneProps, openFilePicker } = useDropZone({\n onFilesSelected,\n accept,\n multiple,\n disabled,\n containerRef: rootRef,\n });\n\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : internalValue;\n const hasText = value.trim().length > 0;\n const hasAttachments = uploadingFiles.length > 0;\n const setValue = React.useCallback(\n (newValue: string) => {\n if (onChange) {\n onChange(newValue);\n }\n if (!isControlled) {\n setInternalValue(newValue);\n }\n },\n [onChange, isControlled],\n );\n\n const { onPaste } = usePasteAsFile({\n pasteAsFile,\n onFilesSelected,\n accept,\n disabled,\n variant,\n value,\n setValue,\n });\n\n const handleSubmit = React.useCallback(() => {\n if (hasText && onSubmit) {\n onSubmit(value);\n if (!isControlled) {\n setInternalValue('');\n }\n }\n }, [hasText, onSubmit, value, isControlled]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement | HTMLInputElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n },\n [handleSubmit],\n );\n\n const handleClear = React.useCallback(() => {\n setValue('');\n if (variant === 'inline') {\n inputRef.current?.focus();\n } else {\n textareaRef.current?.focus();\n }\n }, [setValue, variant]);\n\n // Determine visual state\n const getState = (): VariantProps<typeof inputVariants>['state'] => {\n if (disabled) return 'disabled';\n if (isDragging) return 'dragover';\n if (hasAttachments) return 'attachments';\n if (hasText) return 'withText';\n if (isFocused) return 'focused';\n return 'default';\n };\n\n const contextValue = React.useMemo<AIInputContextValue>(\n () => ({\n value,\n hasText,\n isFocused,\n disabled,\n variant,\n uploadingFiles,\n hasAttachments,\n setValue,\n setIsFocused,\n handleSubmit,\n handleKeyDown,\n handleClear,\n onPaste,\n onRemoveFile,\n onCancelUpload,\n onRetryUpload,\n onRemoveAllFiles,\n isDragging,\n openFilePicker,\n onFilesSelected,\n textareaRef,\n inputRef,\n }),\n [\n value,\n hasText,\n isFocused,\n disabled,\n variant,\n uploadingFiles,\n hasAttachments,\n setValue,\n handleSubmit,\n handleKeyDown,\n handleClear,\n onPaste,\n onRemoveFile,\n onCancelUpload,\n onRetryUpload,\n onRemoveAllFiles,\n isDragging,\n openFilePicker,\n onFilesSelected,\n ],\n );\n\n const isDefault = variant === 'default';\n const state = getState();\n\n return (\n <AIInputContext.Provider value={contextValue}>\n <div\n ref={rootRef}\n data-slot=\"ai-input\"\n data-dragging={isDragging}\n {...dropZoneProps}\n {...(onFilesSelected\n ? { 'aria-label': 'Chat input with file drop zone' }\n : {})}\n className={getAIInputShellClassName({ state, variant, className })}\n >\n <div\n data-slot=\"ai-input-inner\"\n className={cn(\n inputVariants({ state, variant }),\n 'relative',\n !isDefault && hasAttachments && 'flex-col items-stretch py-3',\n disabled && !isDefault ? 'bg-muted' : 'bg-background',\n 'rounded-[inherit]',\n disabled && isDefault && 'bg-muted',\n )}\n >\n {isDragging && (\n <DropOverlay isDefault={isDefault} dropText={dropText} />\n )}\n {children}\n </div>\n </div>\n </AIInputContext.Provider>\n );\n}\n\nAIInputRoot.displayName = 'AIInput.Root';\n\n// =============================================================================\n// AIInput.TextArea - The text input area\n// =============================================================================\n\nexport interface AIInputTextAreaProps {\n /** Placeholder text */\n placeholder?: string;\n /** Additional class name */\n className?: string;\n /** Show clear button when text is present */\n showClearButton?: boolean;\n}\n\nfunction AIInputTextArea({\n placeholder = 'How can HUMAIN ONE help you today?',\n className,\n showClearButton = true,\n}: AIInputTextAreaProps) {\n const ctx = useAIInputContext();\n const isInline = ctx.variant === 'inline';\n\n const handleChange = (\n e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,\n ) => {\n ctx.setValue(e.target.value);\n };\n\n if (isInline) {\n return (\n <input\n ref={ctx.inputRef}\n data-slot=\"ai-input-text\"\n type=\"text\"\n value={ctx.value}\n onChange={handleChange}\n onFocus={() => ctx.setIsFocused(true)}\n onBlur={() => ctx.setIsFocused(false)}\n onKeyDown={ctx.handleKeyDown}\n placeholder={placeholder}\n aria-label={placeholder}\n disabled={ctx.disabled}\n className={cn(\n 'flex-1 min-w-0 bg-transparent text-sm leading-5 text-foreground placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:text-muted-foreground',\n className,\n )}\n />\n );\n }\n\n return (\n <div\n data-slot=\"ai-input-text-area\"\n className={cn(\n 'flex gap-2',\n ctx.variant === 'compact' && !ctx.hasAttachments\n ? 'min-w-0 flex-1 items-center'\n : 'w-full items-start',\n )}\n >\n <textarea\n ref={ctx.textareaRef}\n data-slot=\"ai-input-textarea\"\n value={ctx.value}\n onChange={handleChange}\n onPaste={ctx.onPaste}\n onFocus={() => ctx.setIsFocused(true)}\n onBlur={() => ctx.setIsFocused(false)}\n onKeyDown={ctx.handleKeyDown}\n placeholder={placeholder}\n aria-label={placeholder}\n disabled={ctx.disabled}\n rows={1}\n className={cn(\n ctx.variant === 'compact' ? compactTextareaClasses : textareaClasses,\n className,\n )}\n />\n {showClearButton &&\n ctx.variant !== 'compact' &&\n ctx.hasText &&\n !ctx.disabled && (\n <button\n type=\"button\"\n onClick={ctx.handleClear}\n aria-label=\"Clear input\"\n className=\"p-2 rounded-full hover:bg-accent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring transition-colors duration-150 ease-out shrink-0\"\n >\n <X className=\"size-5 text-muted-foreground\" />\n </button>\n )}\n </div>\n );\n}\n\nAIInputTextArea.displayName = 'AIInput.TextArea';\n\n// =============================================================================\n// AIInput.LeadingIcon - Leading icon for inline variant\n// =============================================================================\n\nexport interface AIInputLeadingIconProps {\n /** Icon content (brand icon, spinner, avatar) */\n children: React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIInputLeadingIcon({ children, className }: AIInputLeadingIconProps) {\n return (\n <div\n data-slot=\"ai-input-leading-icon\"\n aria-hidden=\"true\"\n className={cn(\n 'flex items-center justify-center shrink-0 size-9 rounded-xl bg-foreground/4 border border-border',\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nAIInputLeadingIcon.displayName = 'AIInput.LeadingIcon';\n\n// =============================================================================\n// AIInput.SendButton - The send/submit button\n// =============================================================================\n\nexport interface AIInputSendButtonProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {\n /** Icon component to render */\n icon?: React.ComponentType<{ className?: string }>;\n}\n\nfunction AIInputSendButton({\n icon,\n className,\n ...props\n}: AIInputSendButtonProps) {\n const ctx = useAIInputContext();\n const Icon = icon ?? ArrowUp;\n\n return (\n <Button\n type=\"button\"\n data-slot=\"ai-input-send-button\"\n size=\"icon-sm\"\n onClick={ctx.handleSubmit}\n disabled={ctx.disabled || !ctx.hasText}\n aria-label=\"Send message\"\n className={cn(\n 'rounded-full bg-primary hover:bg-primary/90 text-primary-foreground disabled:bg-accent disabled:text-muted-foreground',\n 'transition-all duration-150 ease-out active:scale-90 motion-reduce:active:scale-100',\n className,\n )}\n {...props}\n >\n <Icon className=\"size-4\" />\n </Button>\n );\n}\n\nAIInputSendButton.displayName = 'AIInput.SendButton';\n\n// =============================================================================\n// AIInput.AttachButton - Attach file button\n// =============================================================================\n\nexport interface AIInputAttachButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Icon component to render */\n icon: React.ComponentType<{ className?: string }>;\n /** Tooltip text */\n tooltip?: string;\n}\n\nfunction AIInputAttachButton({\n icon: Icon,\n tooltip,\n className,\n onClick,\n ...props\n}: AIInputAttachButtonProps) {\n const ctx = useAIInputContext();\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n if (onClick) {\n onClick(e);\n } else if (ctx.onFilesSelected) {\n ctx.openFilePicker();\n }\n },\n [onClick, ctx.onFilesSelected, ctx.openFilePicker],\n );\n\n return (\n <button\n type=\"button\"\n data-slot=\"ai-input-attach-button\"\n onClick={handleClick}\n disabled={ctx.disabled}\n title={tooltip}\n aria-label={tooltip ?? 'Attach file'}\n className={cn(\n 'p-2.5 min-h-11 min-w-11 flex items-center justify-center rounded-full text-secondary-foreground hover:bg-accent transition-colors disabled:opacity-50 disabled:cursor-not-allowed',\n className,\n )}\n {...props}\n >\n <Icon className=\"size-4\" />\n </button>\n );\n}\n\nAIInputAttachButton.displayName = 'AIInput.AttachButton';\n\n// =============================================================================\n// AIInput.Actions - Container for action buttons\n// =============================================================================\n\nexport interface AIInputActionsProps {\n /** Children (action buttons) */\n children?: React.ReactNode;\n /** Position of actions */\n position?: 'leading' | 'trailing';\n /** Additional class name */\n className?: string;\n}\n\nfunction AIInputActions({\n children,\n position = 'leading',\n className,\n}: AIInputActionsProps) {\n return (\n <div\n data-slot=\"ai-input-actions\"\n data-position={position}\n className={cn('flex items-center gap-2', className)}\n >\n {children}\n </div>\n );\n}\n\nAIInputActions.displayName = 'AIInput.Actions';\n\n// =============================================================================\n// AIInput.ActionBar - The bottom action bar (for default variant)\n// =============================================================================\n\nexport interface AIInputActionBarProps {\n /** Children (leading actions, trailing actions, send button) */\n children?: React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIInputActionBar({ children, className }: AIInputActionBarProps) {\n const ctx = useAIInputContext();\n const isCompactRow = ctx.variant === 'compact' && !ctx.hasAttachments;\n\n return (\n <div\n data-slot=\"ai-input-action-bar\"\n className={cn(\n 'flex items-center',\n isCompactRow ? 'shrink-0 gap-3' : 'justify-between w-full',\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nAIInputActionBar.displayName = 'AIInput.ActionBar';\n\n// =============================================================================\n// AIInput.FilePreview - File attachments section\n// =============================================================================\n\nexport interface AIInputFilePreviewProps {\n /** Additional class name */\n className?: string;\n}\n\nfunction AIInputFilePreview({ className }: AIInputFilePreviewProps) {\n const ctx = useAIInputContext();\n\n if (!ctx.hasAttachments) return null;\n\n const completedFiles = ctx.uploadingFiles.filter(\n (f) => f.status === 'complete' || f.progress >= 100,\n );\n\n // Compact/inline variants use the mobile file mini-card.\n if (ctx.variant !== 'default') {\n return (\n <div\n data-slot=\"ai-input-file-preview\"\n className={cn('w-full flex flex-col gap-2', className)}\n >\n <div className=\"flex gap-2 w-full overflow-x-auto\">\n {ctx.uploadingFiles.map((file, index) => (\n <FileUploadItem\n key={file.id}\n mobile\n fileName={file.name}\n fileExtension={file.fileExtension ?? file.name.split('.').pop()}\n progress={file.progress}\n status={file.status}\n className=\"shrink-0 delight-stagger\"\n style={\n {\n '--delight-delay': `${index * 60}ms`,\n } as React.CSSProperties\n }\n onRemove={() => ctx.onRemoveFile?.(file.id)}\n onCancel={() => ctx.onCancelUpload?.(file.id)}\n onRetry={() => ctx.onRetryUpload?.(file.id)}\n />\n ))}\n </div>\n <div className=\"flex items-center justify-between w-full\">\n <span className=\"text-xs text-card-foreground\">\n {completedFiles.length} file\n {completedFiles.length !== 1 ? 's' : ''} added\n </span>\n <RemoveAllButton onClick={ctx.onRemoveAllFiles} />\n </div>\n <div className=\"w-full h-px bg-border\" />\n </div>\n );\n }\n\n // Default variant uses the horizontal file mini-card.\n return (\n <div\n data-slot=\"ai-input-file-preview\"\n className={cn('w-full flex flex-col gap-2', className)}\n >\n <div className=\"flex items-start gap-2 w-full overflow-x-auto\">\n {ctx.uploadingFiles.map((file, index) => (\n <FileUploadItem\n key={file.id}\n fileName={file.name}\n fileSize={file.size}\n fileExtension={file.fileExtension ?? file.name.split('.').pop()}\n progress={file.progress}\n status={file.status}\n className=\"flex-1 min-w-0 delight-stagger\"\n style={\n { '--delight-delay': `${index * 60}ms` } as React.CSSProperties\n }\n onRemove={() => ctx.onRemoveFile?.(file.id)}\n onCancel={() => ctx.onCancelUpload?.(file.id)}\n onRetry={() => ctx.onRetryUpload?.(file.id)}\n />\n ))}\n </div>\n <div className=\"flex items-end justify-between w-full\">\n <span className=\"text-xs text-card-foreground\">\n {completedFiles.length} file\n {completedFiles.length !== 1 ? 's' : ''} added\n </span>\n <RemoveAllButton onClick={ctx.onRemoveAllFiles} />\n </div>\n <div className=\"w-full h-px bg-border\" />\n </div>\n );\n}\n\nAIInputFilePreview.displayName = 'AIInput.FilePreview';\n\n// =============================================================================\n// Monolithic AIInput Component (Batteries-Included)\n// =============================================================================\n\nexport interface AIInputProps extends VariantProps<typeof inputVariants> {\n /** Visual variant of the input */\n variant?: 'default' | 'compact' | 'inline';\n /** Placeholder text */\n placeholder?: string;\n /** Current input value */\n value?: string;\n /** Initial input value for uncontrolled usage */\n defaultValue?: string;\n /** Callback when value changes */\n onChange?: (value: string) => void;\n /** Callback when message is submitted */\n onSubmit?: (message: string) => void;\n /** Files being uploaded */\n uploadingFiles?: UploadingFile[];\n /** Callback when file is removed */\n onRemoveFile?: (fileId: string) => void;\n /** Callback when file upload is cancelled */\n onCancelUpload?: (fileId: string) => void;\n /** Callback to retry a failed upload */\n onRetryUpload?: (fileId: string) => void;\n /** Callback to remove all files */\n onRemoveAllFiles?: () => void;\n /** Callback when files are selected (via drag-drop or file picker) */\n onFilesSelected?: (files: FileList) => void;\n /** Accepted file types (e.g. 'image/*,.pdf') */\n accept?: string;\n /** Allow multiple file selection */\n multiple?: boolean;\n /** Text shown in the drop overlay */\n dropText?: string;\n /** Whether the input is disabled */\n disabled?: boolean;\n /** Additional class name */\n className?: string;\n\n // ==========================================================================\n // Slot Props (for customizing buttons)\n // ==========================================================================\n\n /** Actions rendered on the left side of the action bar, or before submit in inline mode */\n leadingActions?: React.ReactNode;\n /** Actions rendered on the right side, before submit button */\n trailingActions?: React.ReactNode;\n /** Custom submit button render function - receives onClick and disabled */\n submitButton?: SubmitButtonRenderFn;\n /** Custom default button render function (default variant only) - receives disabled */\n defaultButton?: DefaultButtonRenderFn;\n /** Leading icon for inline variant (brand icon, spinner, avatar). Required for inline, ignored for other variants. */\n leadingIcon?: React.ReactNode;\n /** Convert large/structured paste into a file attachment. */\n pasteAsFile?: PasteAsFileProp;\n}\n\nfunction AIInputDefault({\n variant = 'default',\n placeholder = 'How can HUMAIN ONE help you today?',\n value,\n defaultValue = '',\n onChange,\n onSubmit,\n uploadingFiles = [],\n onRemoveFile,\n onCancelUpload,\n onRetryUpload,\n onRemoveAllFiles,\n onFilesSelected,\n accept,\n multiple = true,\n dropText = 'Drop files to attach',\n disabled = false,\n className,\n // Slot props\n leadingActions,\n trailingActions,\n submitButton,\n defaultButton,\n leadingIcon,\n pasteAsFile,\n}: AIInputProps) {\n const [internalValue, setInternalValue] = React.useState(defaultValue);\n const [isFocused, setIsFocused] = React.useState(false);\n const textareaRef = React.useRef<HTMLTextAreaElement>(null);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n\n const { isDragging, dropZoneProps } = useDropZone({\n onFilesSelected,\n accept,\n multiple,\n disabled,\n containerRef: rootRef,\n });\n\n const inputValue = value !== undefined ? value : internalValue;\n const hasText = inputValue.trim().length > 0;\n const hasAttachments = uploadingFiles.length > 0;\n const isControlled = value !== undefined;\n\n const isInline = variant === 'inline';\n const isDefault = variant === 'default';\n\n // Determine visual state\n const getState = (): VariantProps<typeof inputVariants>['state'] => {\n if (disabled) return 'disabled';\n if (isDragging) return 'dragover';\n if (hasAttachments) return 'attachments';\n if (hasText) return 'withText';\n if (isFocused) return 'focused';\n return 'default';\n };\n\n const setValue = React.useCallback(\n (next: string) => {\n if (onChange) {\n onChange(next);\n }\n if (!isControlled) {\n setInternalValue(next);\n }\n },\n [onChange, isControlled],\n );\n\n const handleChange = (\n e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,\n ) => {\n setValue(e.target.value);\n };\n\n const { onPaste } = usePasteAsFile({\n pasteAsFile,\n onFilesSelected,\n accept,\n disabled,\n variant,\n value: inputValue,\n setValue,\n });\n\n const handleSubmit = () => {\n if (hasText && onSubmit) {\n onSubmit(inputValue);\n if (!isControlled) {\n setInternalValue('');\n }\n }\n };\n\n const handleKeyDown = (\n e: React.KeyboardEvent<HTMLTextAreaElement | HTMLInputElement>,\n ) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n const handleClear = () => {\n if (onChange) {\n onChange('');\n }\n if (!isControlled) {\n setInternalValue('');\n }\n if (variant === 'inline') {\n inputRef.current?.focus();\n } else {\n textareaRef.current?.focus();\n }\n };\n\n // Shared: completed file count for file preview sections\n const completedCount = uploadingFiles.filter(\n (f) => f.status === 'complete' || f.progress >= 100,\n ).length;\n\n // Compact file preview (shared by compact + inline variants, skipped for default)\n const compactFilePreview = !isDefault && hasAttachments && (\n <div\n data-slot=\"ai-input-file-preview\"\n className=\"w-full flex flex-col gap-2\"\n >\n <div className=\"flex gap-2 w-full overflow-x-auto\">\n {uploadingFiles.map((file, index) => (\n <FileUploadItem\n key={file.id}\n mobile\n fileName={file.name}\n fileExtension={file.fileExtension ?? file.name.split('.').pop()}\n progress={file.progress}\n status={file.status}\n className=\"shrink-0 delight-stagger\"\n style={\n { '--delight-delay': `${index * 60}ms` } as React.CSSProperties\n }\n onRemove={() => onRemoveFile?.(file.id)}\n onCancel={() => onCancelUpload?.(file.id)}\n onRetry={() => onRetryUpload?.(file.id)}\n />\n ))}\n </div>\n <div className=\"flex items-center justify-between w-full\">\n <span className=\"text-xs text-card-foreground\">\n {completedCount} file\n {completedCount !== 1 ? 's' : ''} added\n </span>\n <RemoveAllButton onClick={onRemoveAllFiles} />\n </div>\n <div className=\"w-full h-px bg-border\" />\n </div>\n );\n\n // Inline variant\n if (isInline) {\n return (\n <div\n ref={rootRef}\n data-slot=\"ai-input\"\n data-dragging={isDragging}\n {...dropZoneProps}\n {...(onFilesSelected\n ? { 'aria-label': 'Chat input with file drop zone' }\n : {})}\n className={getAIInputShellClassName({\n state: getState(),\n variant: 'inline',\n className,\n })}\n >\n <div\n data-slot=\"ai-input-inner\"\n className={cn(\n inputVariants({ state: getState(), variant: 'inline' }),\n 'relative bg-transparent',\n hasAttachments && 'flex-col items-stretch py-3',\n )}\n >\n {isDragging && (\n <DropOverlay isDefault={isDefault} dropText={dropText} />\n )}\n {compactFilePreview}\n\n <div className=\"flex items-center gap-2 w-full\">\n {leadingIcon ? (\n <AIInputLeadingIcon>{leadingIcon}</AIInputLeadingIcon>\n ) : null}\n\n <input\n ref={inputRef}\n data-slot=\"ai-input-text\"\n type=\"text\"\n value={inputValue}\n onChange={handleChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n aria-label={placeholder}\n disabled={disabled}\n className=\"flex-1 min-w-0 bg-transparent text-sm leading-5 text-foreground placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:text-muted-foreground\"\n />\n\n {leadingActions}\n {trailingActions}\n\n <AIInputSubmitButton\n customButton={submitButton}\n onClick={handleSubmit}\n disabled={disabled || !hasText}\n />\n </div>\n </div>\n </div>\n );\n }\n\n // Compact variant\n if (!isDefault) {\n return (\n <div\n ref={rootRef}\n data-slot=\"ai-input\"\n data-dragging={isDragging}\n {...dropZoneProps}\n {...(onFilesSelected\n ? { 'aria-label': 'Chat input with file drop zone' }\n : {})}\n className={getAIInputShellClassName({\n state: getState(),\n variant: 'compact',\n className,\n })}\n >\n <div\n data-slot=\"ai-input-inner\"\n className={cn(\n inputVariants({ state: getState(), variant: 'compact' }),\n 'relative bg-transparent',\n hasAttachments && 'flex-col items-stretch',\n )}\n >\n {isDragging && (\n <DropOverlay isDefault={isDefault} dropText={dropText} />\n )}\n {compactFilePreview}\n\n <div\n data-slot=\"ai-input-text-area\"\n className={cn(\n 'flex gap-2',\n hasAttachments\n ? 'w-full items-start'\n : 'min-w-0 flex-1 items-center',\n )}\n >\n <textarea\n ref={textareaRef}\n data-slot=\"ai-input-textarea\"\n value={inputValue}\n onChange={handleChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n onPaste={onPaste}\n placeholder={placeholder}\n aria-label={placeholder}\n disabled={disabled}\n rows={1}\n className={compactTextareaClasses}\n />\n </div>\n\n <div\n data-slot=\"ai-input-action-bar\"\n className={cn(\n 'flex items-center',\n hasAttachments ? 'justify-between w-full' : 'shrink-0 gap-3',\n )}\n >\n <div\n data-slot=\"ai-input-actions\"\n className=\"flex items-center gap-2\"\n >\n {leadingActions}\n </div>\n <div\n data-slot=\"ai-input-actions\"\n className=\"flex items-center gap-2\"\n >\n {trailingActions}\n {hasText ? (\n <AIInputSubmitButton\n customButton={submitButton}\n onClick={handleSubmit}\n disabled={disabled || !hasText}\n />\n ) : (\n <AIInputDefaultButton\n customButton={defaultButton}\n disabled={disabled}\n />\n )}\n </div>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div\n ref={rootRef}\n data-slot=\"ai-input\"\n data-dragging={isDragging}\n {...dropZoneProps}\n {...(onFilesSelected\n ? { 'aria-label': 'Chat input with file drop zone' }\n : {})}\n className={getAIInputShellClassName({\n state: getState(),\n variant: 'default',\n className,\n })}\n >\n <div\n data-slot=\"ai-input-inner\"\n className={cn(\n inputVariants({ state: getState(), variant: 'default' }),\n 'relative bg-transparent',\n )}\n >\n {isDragging && (\n <DropOverlay isDefault={isDefault} dropText={dropText} />\n )}\n {/* Attachments Section (above input, matching Figma layout) */}\n {hasAttachments && (\n <div\n data-slot=\"ai-input-file-preview\"\n className=\"w-full flex flex-col gap-2\"\n >\n <div className=\"flex items-start gap-2 w-full overflow-x-auto\">\n {uploadingFiles.map((file, index) => (\n <FileUploadItem\n key={file.id}\n fileName={file.name}\n fileSize={file.size}\n fileExtension={\n file.fileExtension ?? file.name.split('.').pop()\n }\n progress={file.progress}\n status={file.status}\n className=\"flex-1 min-w-0 delight-stagger\"\n style={\n {\n '--delight-delay': `${index * 60}ms`,\n } as React.CSSProperties\n }\n onRemove={() => onRemoveFile?.(file.id)}\n onCancel={() => onCancelUpload?.(file.id)}\n onRetry={() => onRetryUpload?.(file.id)}\n />\n ))}\n </div>\n\n <div className=\"flex items-end justify-between w-full\">\n <span className=\"text-xs text-card-foreground\">\n {completedCount} file\n {completedCount !== 1 ? 's' : ''} added\n </span>\n <RemoveAllButton onClick={onRemoveAllFiles} />\n </div>\n\n <div className=\"w-full h-px bg-border\" />\n </div>\n )}\n\n <div\n data-slot=\"ai-input-text-area\"\n className=\"flex items-start gap-2 w-full\"\n >\n <textarea\n ref={textareaRef}\n data-slot=\"ai-input-textarea\"\n value={inputValue}\n onChange={handleChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n onPaste={onPaste}\n placeholder={placeholder}\n aria-label={placeholder}\n disabled={disabled}\n rows={1}\n className={textareaClasses}\n />\n {hasText && !disabled && (\n <button\n type=\"button\"\n onClick={handleClear}\n aria-label=\"Clear input\"\n className=\"p-2 rounded-full hover:bg-accent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring transition-colors duration-150 ease-out shrink-0\"\n >\n <X className=\"size-5 text-muted-foreground\" />\n </button>\n )}\n </div>\n\n <div\n data-slot=\"ai-input-action-bar\"\n className=\"flex items-center justify-between w-full\"\n >\n <div data-slot=\"ai-input-actions\" className=\"flex items-center gap-2\">\n {leadingActions}\n </div>\n\n <div data-slot=\"ai-input-actions\" className=\"flex items-center gap-2\">\n {trailingActions}\n {hasText ? (\n <AIInputSubmitButton\n customButton={submitButton}\n onClick={handleSubmit}\n disabled={disabled || !hasText}\n />\n ) : (\n <AIInputDefaultButton\n customButton={defaultButton}\n disabled={disabled}\n />\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nAIInputDefault.displayName = 'AIInput';\n\n// =============================================================================\n// Export: Object.assign for dual-API\n// =============================================================================\n\n/**\n * AIInput - Dual-API component for AI chat input.\n *\n * Supports two usage patterns:\n *\n * 1. **Monolithic API (batteries-included)**:\n * ```tsx\n * <AIInput\n * placeholder=\"Ask anything...\"\n * onSubmit={handleSubmit}\n * leadingActions={<AIInput.ActionButton icon={Plus} />}\n * />\n * ```\n *\n * 2. **Composable API (full customization)**:\n * ```tsx\n * <AIInput.Root onSubmit={handleSubmit}>\n * <AIInput.TextArea placeholder=\"Ask anything...\" />\n * <AIInput.ActionBar>\n * <AIInput.Actions position=\"leading\">\n * <AIInput.AttachButton icon={Plus} tooltip=\"Add file\" />\n * </AIInput.Actions>\n * <AIInput.Actions position=\"trailing\">\n * <AIInput.SendButton />\n * </AIInput.Actions>\n * </AIInput.ActionBar>\n * <AIInput.FilePreview />\n * </AIInput.Root>\n * ```\n */\nconst AIInput = Object.assign(AIInputDefault, {\n Root: AIInputRoot,\n TextArea: AIInputTextArea,\n LeadingIcon: AIInputLeadingIcon,\n SendButton: AIInputSendButton,\n AttachButton: AIInputAttachButton,\n Actions: AIInputActions,\n ActionBar: AIInputActionBar,\n FilePreview: AIInputFilePreview,\n // Legacy compound components (also available on main export)\n ActionButton,\n SubmitButton,\n CompactActionButton,\n});\n\nexport {\n // Compound components (also available as AIInput.X)\n ActionButton,\n AIInput,\n AIInputActionBar,\n AIInputActions,\n AIInputAttachButton,\n AIInputFilePreview,\n AIInputLeadingIcon,\n // New composable components\n AIInputRoot,\n AIInputSendButton,\n AIInputTextArea,\n CompactActionButton,\n inputVariants,\n SubmitButton,\n // Context hook for custom subcomponents\n useAIInputContext,\n};\n\n// Note: SubmitButtonRenderProps, SubmitButtonRenderFn, DefaultButtonRenderProps,\n// and DefaultButtonRenderFn are exported at their definition sites above\n"],"mappings":"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"}
@@ -128,10 +128,10 @@ function me(s) {
128
128
  if (!i || N) return;
129
129
  const f = r.clipboardData.getData("text/plain");
130
130
  if (!f) return;
131
- const b = i === !0 ? {} : i, I = {
132
- charThreshold: b.threshold,
133
- lineThreshold: b.lineThreshold,
134
- detectStructured: b.detectStructured
131
+ const v = i === !0 ? {} : i, I = {
132
+ charThreshold: v.threshold,
133
+ lineThreshold: v.lineThreshold,
134
+ detectStructured: v.detectStructured
135
135
  }, { shouldConvert: R, kind: d } = He(f, I);
136
136
  if (!R || !c) return;
137
137
  const { ext: B, mime: T } = Le(d), k = t.current + 1, j = `Pasted-${k}.${B}`;
@@ -146,11 +146,11 @@ function me(s) {
146
146
  } catch {
147
147
  return;
148
148
  }
149
- if (r.preventDefault(), t.current = k, c(A), b.prefillTemplate) {
150
- const h = b.prefillTemplate(j, d);
149
+ if (r.preventDefault(), t.current = k, c(A), v.prefillTemplate) {
150
+ const h = v.prefillTemplate(j, d);
151
151
  h?.trim() && S(m ? `${m} ${h}` : h);
152
152
  }
153
- b.onConverted?.(j, d);
153
+ v.onConverted?.(j, d);
154
154
  }, []);
155
155
  return s.variant === "inline" || !s.pasteAsFile ? { onPaste: void 0 } : { onPaste: a };
156
156
  }
@@ -219,10 +219,10 @@ function ue({ customButton: s, disabled: t }) {
219
219
  const n = { disabled: t };
220
220
  return s ? s(n) : /* @__PURE__ */ (0, e.jsx)(ee, {
221
221
  icon: ne,
222
- ...n
222
+ disabled: !0
223
223
  });
224
224
  }
225
- function he({ children: s, variant: t = "default", value: n, defaultValue: a = "", onChange: r, onSubmit: i, uploadingFiles: c = [], onRemoveFile: x, onCancelUpload: N, onRetryUpload: m, onRemoveAllFiles: S, disabled: f = !1, className: b, onFilesSelected: I, accept: R, multiple: d = !0, dropText: B = "Drop files to attach", pasteAsFile: T }) {
225
+ function he({ children: s, variant: t = "default", value: n, defaultValue: a = "", onChange: r, onSubmit: i, uploadingFiles: c = [], onRemoveFile: x, onCancelUpload: N, onRetryUpload: m, onRemoveAllFiles: S, disabled: f = !1, className: v, onFilesSelected: I, accept: R, multiple: d = !0, dropText: B = "Drop files to attach", pasteAsFile: T }) {
226
226
  const [k, j] = l.useState(a), [A, h] = l.useState(!1), X = l.useRef(null), W = l.useRef(null), L = l.useRef(null), { isDragging: F, dropZoneProps: D, openFilePicker: H } = ce({
227
227
  onFilesSelected: I,
228
228
  accept: R,
@@ -239,7 +239,7 @@ function he({ children: s, variant: t = "default", value: n, defaultValue: a = "
239
239
  variant: t,
240
240
  value: y,
241
241
  setValue: g
242
- }), v = l.useCallback(() => {
242
+ }), b = l.useCallback(() => {
243
243
  p && i && (i(y), E || j(""));
244
244
  }, [
245
245
  p,
@@ -247,8 +247,8 @@ function he({ children: s, variant: t = "default", value: n, defaultValue: a = "
247
247
  y,
248
248
  E
249
249
  ]), _ = l.useCallback((C) => {
250
- C.key === "Enter" && !C.shiftKey && (C.preventDefault(), v());
251
- }, [v]), Z = l.useCallback(() => {
250
+ C.key === "Enter" && !C.shiftKey && (C.preventDefault(), b());
251
+ }, [b]), Z = l.useCallback(() => {
252
252
  g(""), t === "inline" ? W.current?.focus() : X.current?.focus();
253
253
  }, [g, t]), O = () => f ? "disabled" : F ? "dragover" : z ? "attachments" : p ? "withText" : A ? "focused" : "default", P = l.useMemo(() => ({
254
254
  value: y,
@@ -260,7 +260,7 @@ function he({ children: s, variant: t = "default", value: n, defaultValue: a = "
260
260
  hasAttachments: z,
261
261
  setValue: g,
262
262
  setIsFocused: h,
263
- handleSubmit: v,
263
+ handleSubmit: b,
264
264
  handleKeyDown: _,
265
265
  handleClear: Z,
266
266
  onPaste: w,
@@ -282,7 +282,7 @@ function he({ children: s, variant: t = "default", value: n, defaultValue: a = "
282
282
  c,
283
283
  z,
284
284
  g,
285
- v,
285
+ b,
286
286
  _,
287
287
  Z,
288
288
  w,
@@ -305,7 +305,7 @@ function he({ children: s, variant: t = "default", value: n, defaultValue: a = "
305
305
  className: Q({
306
306
  state: V,
307
307
  variant: t,
308
- className: b
308
+ className: v
309
309
  }),
310
310
  children: /* @__PURE__ */ (0, e.jsxs)("div", {
311
311
  "data-slot": "ai-input-inner",
@@ -375,7 +375,7 @@ function ie({ children: s, className: t }) {
375
375
  });
376
376
  }
377
377
  ie.displayName = "AIInput.LeadingIcon";
378
- function ve({ icon: s, className: t, ...n }) {
378
+ function be({ icon: s, className: t, ...n }) {
379
379
  const a = U(), r = s ?? ne;
380
380
  return /* @__PURE__ */ (0, e.jsx)(oe, {
381
381
  type: "button",
@@ -389,8 +389,8 @@ function ve({ icon: s, className: t, ...n }) {
389
389
  children: /* @__PURE__ */ (0, e.jsx)(r, { className: "size-4" })
390
390
  });
391
391
  }
392
- ve.displayName = "AIInput.SendButton";
393
- function be({ icon: s, tooltip: t, className: n, onClick: a, ...r }) {
392
+ be.displayName = "AIInput.SendButton";
393
+ function ve({ icon: s, tooltip: t, className: n, onClick: a, ...r }) {
394
394
  const i = U(), c = l.useCallback((x) => {
395
395
  a ? a(x) : i.onFilesSelected && i.openFilePicker();
396
396
  }, [
@@ -410,7 +410,7 @@ function be({ icon: s, tooltip: t, className: n, onClick: a, ...r }) {
410
410
  children: /* @__PURE__ */ (0, e.jsx)(s, { className: "size-4" })
411
411
  });
412
412
  }
413
- be.displayName = "AIInput.AttachButton";
413
+ ve.displayName = "AIInput.AttachButton";
414
414
  function je({ children: s, position: t = "leading", className: n }) {
415
415
  return /* @__PURE__ */ (0, e.jsx)("div", {
416
416
  "data-slot": "ai-input-actions",
@@ -502,21 +502,21 @@ function we({ className: s }) {
502
502
  });
503
503
  }
504
504
  we.displayName = "AIInput.FilePreview";
505
- function Ne({ variant: s = "default", placeholder: t = "How can HUMAIN ONE help you today?", value: n, defaultValue: a = "", onChange: r, onSubmit: i, uploadingFiles: c = [], onRemoveFile: x, onCancelUpload: N, onRetryUpload: m, onRemoveAllFiles: S, onFilesSelected: f, accept: b, multiple: I = !0, dropText: R = "Drop files to attach", disabled: d = !1, className: B, leadingActions: T, trailingActions: k, submitButton: j, defaultButton: A, leadingIcon: h, pasteAsFile: X }) {
505
+ function Ne({ variant: s = "default", placeholder: t = "How can HUMAIN ONE help you today?", value: n, defaultValue: a = "", onChange: r, onSubmit: i, uploadingFiles: c = [], onRemoveFile: x, onCancelUpload: N, onRetryUpload: m, onRemoveAllFiles: S, onFilesSelected: f, accept: v, multiple: I = !0, dropText: R = "Drop files to attach", disabled: d = !1, className: B, leadingActions: T, trailingActions: k, submitButton: j, defaultButton: A, leadingIcon: h, pasteAsFile: X }) {
506
506
  const [W, L] = l.useState(a), [F, D] = l.useState(!1), H = l.useRef(null), E = l.useRef(null), y = l.useRef(null), { isDragging: p, dropZoneProps: z } = ce({
507
507
  onFilesSelected: f,
508
- accept: b,
508
+ accept: v,
509
509
  multiple: I,
510
510
  disabled: d,
511
511
  containerRef: y
512
- }), g = n !== void 0 ? n : W, w = g.trim().length > 0, v = c.length > 0, _ = n !== void 0, Z = s === "inline", O = s === "default", P = () => d ? "disabled" : p ? "dragover" : v ? "attachments" : w ? "withText" : F ? "focused" : "default", K = l.useCallback((o) => {
512
+ }), g = n !== void 0 ? n : W, w = g.trim().length > 0, b = c.length > 0, _ = n !== void 0, Z = s === "inline", O = s === "default", P = () => d ? "disabled" : p ? "dragover" : b ? "attachments" : w ? "withText" : F ? "focused" : "default", K = l.useCallback((o) => {
513
513
  r && r(o), _ || L(o);
514
514
  }, [r, _]), V = (o) => {
515
515
  K(o.target.value);
516
516
  }, { onPaste: C } = me({
517
517
  pasteAsFile: X,
518
518
  onFilesSelected: f,
519
- accept: b,
519
+ accept: v,
520
520
  disabled: d,
521
521
  variant: s,
522
522
  value: g,
@@ -527,7 +527,7 @@ function Ne({ variant: s = "default", placeholder: t = "How can HUMAIN ONE help
527
527
  o.key === "Enter" && !o.shiftKey && (o.preventDefault(), q());
528
528
  }, Ie = () => {
529
529
  r && r(""), _ || L(""), s === "inline" ? E.current?.focus() : H.current?.focus();
530
- }, G = c.filter((o) => o.status === "complete" || o.progress >= 100).length, le = !O && v && /* @__PURE__ */ (0, e.jsxs)("div", {
530
+ }, G = c.filter((o) => o.status === "complete" || o.progress >= 100).length, le = !O && b && /* @__PURE__ */ (0, e.jsxs)("div", {
531
531
  "data-slot": "ai-input-file-preview",
532
532
  className: "w-full flex flex-col gap-2",
533
533
  children: [
@@ -577,7 +577,7 @@ function Ne({ variant: s = "default", placeholder: t = "How can HUMAIN ONE help
577
577
  className: u(J({
578
578
  state: P(),
579
579
  variant: "inline"
580
- }), "relative bg-transparent", v && "flex-col items-stretch py-3"),
580
+ }), "relative bg-transparent", b && "flex-col items-stretch py-3"),
581
581
  children: [
582
582
  p && /* @__PURE__ */ (0, e.jsx)($, {
583
583
  isDefault: O,
@@ -635,7 +635,7 @@ function Ne({ variant: s = "default", placeholder: t = "How can HUMAIN ONE help
635
635
  isDefault: O,
636
636
  dropText: R
637
637
  }),
638
- v && /* @__PURE__ */ (0, e.jsxs)("div", {
638
+ b && /* @__PURE__ */ (0, e.jsxs)("div", {
639
639
  "data-slot": "ai-input-file-preview",
640
640
  className: "w-full flex flex-col gap-2",
641
641
  children: [
@@ -732,7 +732,7 @@ function Ne({ variant: s = "default", placeholder: t = "How can HUMAIN ONE help
732
732
  className: u(J({
733
733
  state: P(),
734
734
  variant: "compact"
735
- }), "relative bg-transparent", v && "flex-col items-stretch"),
735
+ }), "relative bg-transparent", b && "flex-col items-stretch"),
736
736
  children: [
737
737
  p && /* @__PURE__ */ (0, e.jsx)($, {
738
738
  isDefault: O,
@@ -741,7 +741,7 @@ function Ne({ variant: s = "default", placeholder: t = "How can HUMAIN ONE help
741
741
  le,
742
742
  /* @__PURE__ */ (0, e.jsx)("div", {
743
743
  "data-slot": "ai-input-text-area",
744
- className: u("flex gap-2", v ? "w-full items-start" : "min-w-0 flex-1 items-center"),
744
+ className: u("flex gap-2", b ? "w-full items-start" : "min-w-0 flex-1 items-center"),
745
745
  children: /* @__PURE__ */ (0, e.jsx)("textarea", {
746
746
  ref: H,
747
747
  "data-slot": "ai-input-textarea",
@@ -760,7 +760,7 @@ function Ne({ variant: s = "default", placeholder: t = "How can HUMAIN ONE help
760
760
  }),
761
761
  /* @__PURE__ */ (0, e.jsxs)("div", {
762
762
  "data-slot": "ai-input-action-bar",
763
- className: u("flex items-center", v ? "justify-between w-full" : "shrink-0 gap-3"),
763
+ className: u("flex items-center", b ? "justify-between w-full" : "shrink-0 gap-3"),
764
764
  children: [/* @__PURE__ */ (0, e.jsx)("div", {
765
765
  "data-slot": "ai-input-actions",
766
766
  className: "flex items-center gap-2",
@@ -787,8 +787,8 @@ var nt = Object.assign(Ne, {
787
787
  Root: he,
788
788
  TextArea: ge,
789
789
  LeadingIcon: ie,
790
- SendButton: ve,
791
- AttachButton: be,
790
+ SendButton: be,
791
+ AttachButton: ve,
792
792
  Actions: je,
793
793
  ActionBar: ye,
794
794
  FilePreview: we,