@humain/ui 2.4.1 → 2.4.3

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.
Files changed (157) hide show
  1. package/dist/index150.js +1 -1
  2. package/dist/index150.js.map +1 -1
  3. package/dist/index194.js +6 -8
  4. package/dist/index194.js.map +1 -1
  5. package/dist/index24.js +1 -1
  6. package/dist/index24.js.map +1 -1
  7. package/dist/styles.css +1 -1
  8. package/dist/wc/AIClarificationCard.js +1 -1
  9. package/dist/wc/AIContainer.js +1 -1
  10. package/dist/wc/AIForm.js +17 -17
  11. package/dist/wc/AIInput.js +32 -32
  12. package/dist/wc/AIInput.js.map +1 -1
  13. package/dist/wc/AIMermaidDiagram.js +1 -1
  14. package/dist/wc/AIMessage.js +1 -1
  15. package/dist/wc/AIScrollButton.js +4 -4
  16. package/dist/wc/AIToolCall.js +5 -5
  17. package/dist/wc/AppSidebar.constants.js +1 -1
  18. package/dist/wc/AvatarFallback.js +5 -5
  19. package/dist/wc/CheckboxIndicator.js +7 -7
  20. package/dist/wc/CollapsiblePanel.js +1 -1
  21. package/dist/wc/DialogTrigger.js +9 -9
  22. package/dist/wc/DropdownMenu.js +16 -16
  23. package/dist/wc/MenuSubmenuTrigger.js +31 -31
  24. package/dist/wc/PopoverDescription.js +30 -30
  25. package/dist/wc/PrehydrationScript.js +1 -1
  26. package/dist/wc/Select.js +18 -18
  27. package/dist/wc/SelectSeparator.js +72 -72
  28. package/dist/wc/SelectSeparator.js.map +1 -1
  29. package/dist/wc/Tabs.js +18 -18
  30. package/dist/wc/TooltipProvider.js +9 -9
  31. package/dist/wc/chart.js +1 -1
  32. package/dist/wc/chunk-75Z2AOVW.js +39 -39
  33. package/dist/wc/chunk-OSK3NFVY.js +32 -32
  34. package/dist/wc/command.js +4 -4
  35. package/dist/wc/form-field.js +1 -1
  36. package/dist/wc/form-fieldset.js +5 -5
  37. package/dist/wc/hf-accordion-card.js +4 -4
  38. package/dist/wc/hf-accordion.js +6 -6
  39. package/dist/wc/hf-ai-feedback-bar.js +5 -5
  40. package/dist/wc/hf-ai-reasoning-block.js +6 -6
  41. package/dist/wc/hf-ai-system-message.js +1 -1
  42. package/dist/wc/hf-ai-tool-run.js +1 -1
  43. package/dist/wc/hf-area-chart.js +15 -15
  44. package/dist/wc/hf-autocomplete.js +36 -36
  45. package/dist/wc/hf-bar-chart.js +4 -4
  46. package/dist/wc/hf-calendar.js +4 -4
  47. package/dist/wc/hf-carousel.js +1 -1
  48. package/dist/wc/hf-context-menu.js +8 -8
  49. package/dist/wc/hf-donut-chart.js +10 -10
  50. package/dist/wc/hf-empty-state.js +87 -88
  51. package/dist/wc/hf-empty-state.js.map +1 -1
  52. package/dist/wc/hf-history.js +4 -4
  53. package/dist/wc/hf-horizontal-bar-chart.js +7 -7
  54. package/dist/wc/hf-hover-card.js +6 -6
  55. package/dist/wc/hf-line-chart.js +4 -4
  56. package/dist/wc/hf-metric-card.js +5 -5
  57. package/dist/wc/hf-metric-item.js +8 -8
  58. package/dist/wc/hf-metric-item.js.map +1 -1
  59. package/dist/wc/hf-nav-account-menu.js +4 -4
  60. package/dist/wc/hf-notification-panel.js +2 -2
  61. package/dist/wc/hf-pie-chart.js +17 -17
  62. package/dist/wc/hf-radar-chart.js +16 -16
  63. package/dist/wc/hf-section-header.js +6 -6
  64. package/dist/wc/hf-sheet.js +1 -1
  65. package/dist/wc/hf-sparkline-chart.js +5 -5
  66. package/dist/wc/hf-steps.js +6 -6
  67. package/dist/wc/journeyDiagram-3NMN7TZE.js +10 -10
  68. package/dist/wc/pieDiagram-E7YTZNPT.js +16 -16
  69. package/dist/wc/popupStateMapping.js +53 -53
  70. package/dist/wc/popupStateMapping.js.map +1 -1
  71. package/dist/wc/selection-group.js +1 -1
  72. package/dist/wc/selection-group.js.map +1 -1
  73. package/dist/wc/{useOpenChangeComplete.js → stateAttributesMapping.js} +21 -21
  74. package/dist/wc/stateAttributesMapping.js.map +1 -0
  75. package/dist/wc/stateDiagram-D77RDMKH.js +3 -3
  76. package/dist/wc/timeline-definition-24CTP7MA.js +19 -19
  77. package/dist/wc/useCollapsiblePanel.js +3 -3
  78. package/dist/wc/usePopupHandleStore.js +4 -4
  79. package/dist/wc/useScrollLock.js +1 -1
  80. package/dist/wc/vendor/recharts.js +525 -524
  81. package/dist/wc/vendor/recharts.js.map +1 -1
  82. package/dist/wc/xychartDiagram-S5SC5T6Z.js +6 -6
  83. package/dist/wc-react/AIClarificationCard.js +1 -1
  84. package/dist/wc-react/AIContainer.js +1 -1
  85. package/dist/wc-react/AIForm.js +17 -17
  86. package/dist/wc-react/AIInput.js +2 -2
  87. package/dist/wc-react/AIInput.js.map +1 -1
  88. package/dist/wc-react/AIMermaidDiagram.js +1 -1
  89. package/dist/wc-react/AIMessage.js +1 -1
  90. package/dist/wc-react/AIScrollButton.js +4 -4
  91. package/dist/wc-react/AIToolCall.js +5 -5
  92. package/dist/wc-react/AppSidebar.constants.js +1 -1
  93. package/dist/wc-react/AvatarFallback.js +5 -5
  94. package/dist/wc-react/CheckboxIndicator.js +7 -7
  95. package/dist/wc-react/CollapsiblePanel.js +1 -1
  96. package/dist/wc-react/DialogTrigger.js +9 -9
  97. package/dist/wc-react/DropdownMenu.js +16 -16
  98. package/dist/wc-react/FloatingPortalLite.js +3 -3
  99. package/dist/wc-react/MenuSubmenuTrigger.js +31 -31
  100. package/dist/wc-react/PopoverDescription.js +31 -31
  101. package/dist/wc-react/PrehydrationScript.js +1 -1
  102. package/dist/wc-react/Select.js +18 -18
  103. package/dist/wc-react/SelectSeparator.js +71 -70
  104. package/dist/wc-react/SelectSeparator.js.map +1 -1
  105. package/dist/wc-react/Tabs.js +18 -18
  106. package/dist/wc-react/TooltipProvider.js +9 -9
  107. package/dist/wc-react/chart.js +1 -1
  108. package/dist/wc-react/chunk-75Z2AOVW.js +39 -39
  109. package/dist/wc-react/chunk-OSK3NFVY.js +32 -32
  110. package/dist/wc-react/command.js +4 -4
  111. package/dist/wc-react/form-field.js +1 -1
  112. package/dist/wc-react/form-fieldset.js +77 -77
  113. package/dist/wc-react/hf-accordion-card.js +4 -4
  114. package/dist/wc-react/hf-accordion.js +6 -6
  115. package/dist/wc-react/hf-ai-feedback-bar.js +5 -5
  116. package/dist/wc-react/hf-ai-reasoning-block.js +6 -6
  117. package/dist/wc-react/hf-ai-system-message.js +1 -1
  118. package/dist/wc-react/hf-ai-tool-run.js +1 -1
  119. package/dist/wc-react/hf-autocomplete.js +37 -37
  120. package/dist/wc-react/hf-calendar.js +4 -4
  121. package/dist/wc-react/hf-carousel.js +1 -1
  122. package/dist/wc-react/hf-context-menu.js +8 -8
  123. package/dist/wc-react/hf-data-table.js +1 -1
  124. package/dist/wc-react/hf-empty-state.js +87 -88
  125. package/dist/wc-react/hf-empty-state.js.map +1 -1
  126. package/dist/wc-react/hf-history.js +4 -4
  127. package/dist/wc-react/hf-hover-card.js +6 -6
  128. package/dist/wc-react/hf-metric-item.js +6 -6
  129. package/dist/wc-react/hf-metric-item.js.map +1 -1
  130. package/dist/wc-react/hf-nav-account-menu.js +4 -4
  131. package/dist/wc-react/hf-notification-panel.js +2 -2
  132. package/dist/wc-react/hf-section-header.js +6 -6
  133. package/dist/wc-react/hf-sheet.js +1 -1
  134. package/dist/wc-react/hf-steps.js +5 -5
  135. package/dist/wc-react/journeyDiagram-3NMN7TZE.js +10 -10
  136. package/dist/wc-react/pieDiagram-E7YTZNPT.js +16 -16
  137. package/dist/wc-react/popupStateMapping.js +54 -54
  138. package/dist/wc-react/popupStateMapping.js.map +1 -1
  139. package/dist/wc-react/selection-group.js +1 -1
  140. package/dist/wc-react/selection-group.js.map +1 -1
  141. package/dist/wc-react/{useOpenChangeComplete.js → stateAttributesMapping.js} +19 -19
  142. package/dist/wc-react/stateAttributesMapping.js.map +1 -0
  143. package/dist/wc-react/stateDiagram-D77RDMKH.js +3 -3
  144. package/dist/wc-react/timeline-definition-24CTP7MA.js +19 -19
  145. package/dist/wc-react/useCollapsiblePanel.js +3 -3
  146. package/dist/wc-react/usePopupHandleStore.js +3 -3
  147. package/dist/wc-react/useScrollLock.js +1 -1
  148. package/dist/wc-react/vendor/recharts.js +525 -524
  149. package/dist/wc-react/vendor/recharts.js.map +1 -1
  150. package/dist/wc-react/xychartDiagram-S5SC5T6Z.js +6 -6
  151. package/package.json +1 -1
  152. package/skills/humain-ui/SKILL.md +1 -1
  153. package/skills/humain-ui-wc/SKILL.md +1 -1
  154. package/skills/humain-ui-wc.skill +0 -0
  155. package/skills/humain-ui.skill +0 -0
  156. package/dist/wc/useOpenChangeComplete.js.map +0 -1
  157. package/dist/wc-react/useOpenChangeComplete.js.map +0 -1
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":"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"}
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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"}
package/dist/index194.js CHANGED
@@ -47,12 +47,6 @@ var iconGlyphSizeClass = {
47
47
  md: "size-4",
48
48
  lg: "size-5"
49
49
  };
50
- var illustrationIconCenterClass = {
51
- cloud: "top-[58%]",
52
- box: "top-[58%]",
53
- documents: "top-[60%]",
54
- "credit-card": "top-[60%]"
55
- };
56
50
  var illustrationCircleSizeClass = {
57
51
  sm: "size-[104px]",
58
52
  md: "size-32",
@@ -191,6 +185,7 @@ function DecorativeDots({ tone }) {
191
185
  }
192
186
  function CloudShape({ accentId, shadeId, tone }) {
193
187
  return /* @__PURE__ */ jsxs("g", {
188
+ transform: "translate(10.5 14.5)",
194
189
  className: "drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]",
195
190
  children: [/* @__PURE__ */ jsx("path", {
196
191
  d: "M54 110c-21 0-38-14-38-32 0-16 14-30 33-32 8-19 27-31 49-31 27 0 50 19 55 43 17 3 30 16 30 32 0 19-18 34-40 34H55c-1 0-1-14-1-14Z",
@@ -204,6 +199,7 @@ function CloudShape({ accentId, shadeId, tone }) {
204
199
  }
205
200
  function BoxShape({ accentId, shadeId }) {
206
201
  return /* @__PURE__ */ jsxs("g", {
202
+ transform: "translate(-19.5)",
207
203
  className: "drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]",
208
204
  children: [
209
205
  /* @__PURE__ */ jsx("path", {
@@ -233,6 +229,7 @@ function BoxShape({ accentId, shadeId }) {
233
229
  }
234
230
  function DocumentsShape({ accentId, shadeId }) {
235
231
  return /* @__PURE__ */ jsxs("g", {
232
+ transform: "translate(0 -0.5)",
236
233
  className: "drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]",
237
234
  children: [
238
235
  /* @__PURE__ */ jsxs("g", {
@@ -282,6 +279,7 @@ function DocumentsShape({ accentId, shadeId }) {
282
279
  }
283
280
  function CreditCardShape({ accentId, shadeId }) {
284
281
  return /* @__PURE__ */ jsxs("g", {
282
+ transform: "translate(0 -5)",
285
283
  className: "drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]",
286
284
  children: [
287
285
  /* @__PURE__ */ jsx("rect", {
@@ -355,7 +353,7 @@ var EmptyStateIllustration = React$1.forwardRef(({ className, size = "sm", varia
355
353
  "data-slot": "empty-state-illustration-background",
356
354
  "data-testid": "empty-state-illustration-background",
357
355
  "data-centered": "true",
358
- className: cn("absolute left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full", isPrimary ? "bg-primary/20" : "bg-muted/80", illustrationCircleSizeClass[size], illustrationIconCenterClass[variant])
356
+ className: cn("absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full", isPrimary ? "bg-primary/20" : "bg-muted/80", illustrationCircleSizeClass[size])
359
357
  }),
360
358
  /* @__PURE__ */ jsx(DecorativeDots, { tone }),
361
359
  /* @__PURE__ */ jsxs("svg", {
@@ -411,7 +409,7 @@ var EmptyStateIllustration = React$1.forwardRef(({ className, size = "sm", varia
411
409
  "data-slot": "empty-state-illustration-icon",
412
410
  "data-testid": "empty-state-illustration-icon",
413
411
  "data-centered": "true",
414
- className: cn("absolute left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-xl bg-primary/10 text-primary shadow-xs backdrop-blur-md supports-backdrop-filter:backdrop-blur-md [&>svg]:shrink-0", !isPrimary && "bg-muted text-muted-foreground", illustrationIconSizeClass[size], illustrationIconCenterClass[variant]),
412
+ className: cn("absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-xl bg-primary/10 text-primary shadow-xs backdrop-blur-md supports-backdrop-filter:backdrop-blur-md [&>svg]:shrink-0", !isPrimary && "bg-muted text-muted-foreground", illustrationIconSizeClass[size]),
415
413
  children: /* @__PURE__ */ jsx(EmptyStateIconGlyph, {
416
414
  icon,
417
415
  size
@@ -1 +1 @@
1
- {"version":3,"file":"index194.js","names":[],"sources":["../src/components/organisms/content/EmptyState/EmptyState.tsx"],"sourcesContent":["import { cva } from 'class-variance-authority';\nimport { Heart, Search } from 'lucide-react';\nimport * as React from 'react';\nimport { Button } from '@/components/atoms/buttons/Button';\nimport { FeaturedIcon } from '@/components/molecules/data/FeaturedIcon';\nimport {\n type FileExtension,\n FileTypeIcon,\n type SimpleFileType,\n} from '@/components/molecules/files/FileTypeIcon';\nimport { cn } from '@/lib/utils';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type EmptyStateSize = 'sm' | 'md' | 'lg';\nexport type EmptyStateMedia =\n | 'featured-icon'\n | 'illustration'\n | 'file-type-icon'\n | 'none';\nexport type EmptyStateBackgroundPatternVariant =\n | 'circles'\n | 'grid'\n | 'grid-dot'\n | 'squares'\n | 'none';\nexport type EmptyStateIllustrationVariant =\n | 'cloud'\n | 'box'\n | 'documents'\n | 'credit-card';\nexport type EmptyStateTone = 'primary' | 'gray';\n\nexport interface EmptyStateActionConfig {\n label: React.ReactNode;\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n startIcon?: React.ReactNode;\n disabled?: boolean;\n loading?: boolean;\n 'aria-label'?: string;\n}\n\n// ============================================================================\n// Shared maps\n// ============================================================================\n\nconst patternSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-[336px]',\n md: 'size-[480px]',\n lg: 'size-[768px]',\n};\n\nconst patternGridSize: Record<EmptyStateSize, string> = {\n sm: '24px 24px',\n md: '32px 32px',\n lg: '48px 48px',\n};\n\nconst illustrationSizeClass: Record<\n EmptyStateSize,\n Record<EmptyStateIllustrationVariant, string>\n> = {\n sm: {\n cloud: 'h-[118px] w-[152px]',\n box: 'h-[124px] w-[152px]',\n documents: 'h-[118px] w-[152px]',\n 'credit-card': 'h-[118px] w-[152px]',\n },\n md: {\n cloud: 'h-32 w-[172px]',\n box: 'h-[136px] w-[172px]',\n documents: 'h-32 w-[172px]',\n 'credit-card': 'h-[134px] w-[172px]',\n },\n lg: {\n cloud: 'h-40 w-[220px]',\n box: 'h-[168px] w-[220px]',\n documents: 'h-40 w-[220px]',\n 'credit-card': 'h-40 w-[220px]',\n },\n};\n\nconst illustrationIconSizeClass: Record<EmptyStateSize, string> = {\n sm: 'p-2',\n md: 'p-2.5',\n lg: 'p-2.5',\n};\n\nconst iconGlyphSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-4',\n md: 'size-4',\n lg: 'size-5',\n};\n\nconst illustrationIconCenterClass: Record<\n EmptyStateIllustrationVariant,\n string\n> = {\n cloud: 'top-[58%]',\n box: 'top-[58%]',\n documents: 'top-[60%]',\n 'credit-card': 'top-[60%]',\n};\n\nconst illustrationCircleSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-[104px]',\n md: 'size-32',\n lg: 'size-40',\n};\n\nconst fileIconWrapSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-20',\n md: 'size-24',\n lg: 'size-28',\n};\n\nconst textGapClass: Record<EmptyStateSize, string> = {\n sm: 'gap-1',\n md: 'gap-2',\n lg: 'gap-2',\n};\n\nconst mediaGapClass: Record<EmptyStateSize, string> = {\n sm: 'gap-4',\n md: 'gap-5',\n lg: 'gap-5',\n};\n\nconst contentGapClass: Record<EmptyStateSize, string> = {\n sm: 'gap-6',\n md: 'gap-8',\n lg: 'gap-8',\n};\n\nconst featuredIconSize: Record<EmptyStateSize, 'sm' | 'md' | 'lg'> = {\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n};\n\nconst fileIconSize: Record<EmptyStateSize, 'sm' | 'md' | 'lg'> = {\n sm: 'md',\n md: 'md',\n lg: 'md',\n};\n\nconst headingTag = {\n 2: 'h2',\n 3: 'h3',\n 4: 'h4',\n} as const;\n\nfunction EmptyStateIconGlyph({\n icon,\n size,\n}: {\n icon: React.ReactNode;\n size: EmptyStateSize;\n}) {\n return (\n <span\n data-slot=\"empty-state-icon-glyph\"\n data-testid=\"empty-state-icon-glyph\"\n data-centered=\"true\"\n aria-hidden=\"true\"\n className={cn(\n 'inline-flex shrink-0 items-center justify-center leading-none [line-height:0] [&>svg]:block [&>svg]:size-full [&>svg]:shrink-0',\n iconGlyphSizeClass[size],\n )}\n >\n {icon}\n </span>\n );\n}\n\n// ============================================================================\n// Background Pattern\n// ============================================================================\n\nexport interface EmptyStateBackgroundPatternProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n size?: EmptyStateSize;\n variant?: EmptyStateBackgroundPatternVariant;\n}\n\nconst gridPatternStyle = (\n size: EmptyStateSize,\n dot = false,\n): React.CSSProperties => ({\n backgroundImage: dot\n ? 'radial-gradient(circle, color-mix(in oklch, var(--border) 70%, transparent) 1px, transparent 1px)'\n : [\n 'linear-gradient(to right, color-mix(in oklch, var(--border) 54%, transparent) 1px, transparent 1px)',\n 'linear-gradient(to bottom, color-mix(in oklch, var(--border) 54%, transparent) 1px, transparent 1px)',\n ].join(', '),\n backgroundSize: patternGridSize[size],\n});\n\nconst squaresBySize: Record<EmptyStateSize, number[]> = {\n sm: [96, 144, 192, 240, 288, 336],\n md: [96, 160, 224, 288, 352, 416, 480],\n lg: [96, 192, 288, 384, 480, 576, 672, 768],\n};\n\nexport const EmptyStateBackgroundPattern = React.forwardRef<\n HTMLDivElement,\n EmptyStateBackgroundPatternProps\n>(({ className, size = 'sm', variant = 'circles', style, ...props }, ref) => {\n if (variant === 'none') {\n return null;\n }\n\n return (\n <div\n ref={ref}\n data-slot=\"empty-state-background-pattern\"\n data-testid=\"empty-state-pattern\"\n data-size={size}\n data-variant={variant}\n aria-hidden=\"true\"\n className={cn(\n 'pointer-events-none absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 overflow-hidden opacity-75',\n patternSizeClass[size],\n className,\n )}\n style={style}\n {...props}\n >\n <div className=\"absolute inset-0 bg-[radial-gradient(circle_at_center,var(--background)_0%,transparent_68%)]\" />\n\n {variant === 'circles' && (\n <div className=\"absolute inset-0\">\n {Array.from({ length: 7 }, (_, index) => (\n <span\n key={index}\n className=\"absolute left-1/2 top-1/2 rounded-full border border-border/60\"\n style={{\n width: `${(index + 1) * 14}%`,\n height: `${(index + 1) * 14}%`,\n transform: 'translate(-50%, -50%)',\n }}\n />\n ))}\n </div>\n )}\n\n {(variant === 'grid' || variant === 'grid-dot') && (\n <div\n className=\"absolute inset-0 opacity-70 [mask-image:radial-gradient(circle_at_center,black_0%,black_48%,transparent_76%)]\"\n style={gridPatternStyle(size, variant === 'grid-dot')}\n />\n )}\n\n {variant === 'squares' && (\n <div className=\"absolute inset-0\">\n {squaresBySize[size].map((squareSize) => (\n <span\n key={squareSize}\n className=\"absolute left-1/2 top-1/2 rounded-xl border border-border/55\"\n style={{\n width: squareSize,\n height: squareSize,\n transform: 'translate(-50%, -50%) rotate(-12.5deg)',\n }}\n />\n ))}\n </div>\n )}\n </div>\n );\n});\n\nEmptyStateBackgroundPattern.displayName = 'EmptyStateBackgroundPattern';\n\n// ============================================================================\n// Illustration\n// ============================================================================\n\nexport interface EmptyStateIllustrationProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n size?: EmptyStateSize;\n variant?: EmptyStateIllustrationVariant;\n tone?: EmptyStateTone;\n icon?: React.ReactNode;\n}\n\nfunction DecorativeDots({ tone }: { tone: EmptyStateTone }) {\n const dotClassName =\n tone === 'primary' ? 'bg-primary/70' : 'bg-muted-foreground/10';\n\n return (\n <>\n <span\n className={cn(\n 'absolute left-[7%] top-[8%] size-2 rounded-full',\n dotClassName,\n )}\n />\n <span\n className={cn(\n 'absolute right-[6%] top-[18%] size-3 rounded-full',\n dotClassName,\n )}\n />\n <span\n className={cn(\n 'absolute bottom-[10%] left-[8%] size-3 rounded-full',\n dotClassName,\n )}\n />\n <span\n className={cn(\n 'absolute bottom-[18%] right-[13%] size-2 rounded-full',\n dotClassName,\n )}\n />\n </>\n );\n}\n\nfunction CloudShape({\n accentId,\n shadeId,\n tone,\n}: {\n accentId: string;\n shadeId: string;\n tone: EmptyStateTone;\n}) {\n return (\n <g className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\">\n <path\n d=\"M54 110c-21 0-38-14-38-32 0-16 14-30 33-32 8-19 27-31 49-31 27 0 50 19 55 43 17 3 30 16 30 32 0 19-18 34-40 34H55c-1 0-1-14-1-14Z\"\n fill={`url(#${shadeId})`}\n />\n <path\n d=\"M68 106c-18 0-32-12-32-27 0-13 11-24 27-26 7-16 23-26 42-26 23 0 42 16 46 36 15 3 26 14 26 28 0 16-15 29-34 29H68v-14Z\"\n fill={`url(#${accentId})`}\n opacity={tone === 'primary' ? 0.78 : 0.36}\n />\n </g>\n );\n}\n\nfunction BoxShape({\n accentId,\n shadeId,\n}: {\n accentId: string;\n shadeId: string;\n}) {\n return (\n <g className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\">\n <path d=\"M72 42 132 20l55 31-62 24-53-33Z\" fill={`url(#${accentId})`} />\n <path d=\"M72 42v72l53 34V75L72 42Z\" fill={`url(#${shadeId})`} />\n <path d=\"M125 75v73l62-35V51l-62 24Z\" fill=\"var(--card)\" />\n <path\n d=\"M132 20v33l24 14V34l-24-14Z\"\n fill=\"currentColor\"\n opacity=\"0.34\"\n />\n <path\n d=\"M72 42 132 20l55 31-62 24-53-33Z\"\n fill=\"none\"\n stroke=\"var(--border)\"\n />\n </g>\n );\n}\n\nfunction DocumentsShape({\n accentId,\n shadeId,\n}: {\n accentId: string;\n shadeId: string;\n}) {\n return (\n <g className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\">\n <g transform=\"translate(44 48) rotate(-18)\">\n <rect\n width=\"58\"\n height=\"78\"\n rx=\"7\"\n fill={`url(#${shadeId})`}\n stroke=\"var(--border)\"\n />\n <path\n d=\"M15 21h28M15 35h21M15 49h28\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.28\"\n />\n </g>\n <g transform=\"translate(83 32)\">\n <rect\n width=\"58\"\n height=\"88\"\n rx=\"7\"\n fill=\"var(--card)\"\n stroke=\"var(--border)\"\n />\n <path\n d=\"M16 26h28M16 41h22M16 56h28\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.32\"\n />\n </g>\n <g transform=\"translate(121 47) rotate(18)\">\n <rect\n width=\"58\"\n height=\"78\"\n rx=\"7\"\n fill={`url(#${accentId})`}\n stroke=\"var(--border)\"\n />\n <path\n d=\"M15 21h28M15 35h21M15 49h28\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.32\"\n />\n </g>\n </g>\n );\n}\n\nfunction CreditCardShape({\n accentId,\n shadeId,\n}: {\n accentId: string;\n shadeId: string;\n}) {\n return (\n <g className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\">\n <rect\n x=\"42\"\n y=\"48\"\n width=\"136\"\n height=\"82\"\n rx=\"12\"\n fill={`url(#${shadeId})`}\n stroke=\"var(--border)\"\n />\n <rect\n x=\"42\"\n y=\"70\"\n width=\"136\"\n height=\"16\"\n fill={`url(#${accentId})`}\n opacity=\"0.72\"\n />\n <rect\n x=\"58\"\n y=\"104\"\n width=\"28\"\n height=\"8\"\n rx=\"2\"\n fill=\"currentColor\"\n opacity=\"0.28\"\n />\n <rect\n x=\"58\"\n y=\"116\"\n width=\"58\"\n height=\"5\"\n rx=\"2.5\"\n fill=\"currentColor\"\n opacity=\"0.18\"\n />\n <circle cx=\"146\" cy=\"112\" r=\"10\" fill=\"currentColor\" opacity=\"0.24\" />\n <circle cx=\"158\" cy=\"112\" r=\"10\" fill=\"currentColor\" opacity=\"0.38\" />\n </g>\n );\n}\n\nexport const EmptyStateIllustration = React.forwardRef<\n HTMLDivElement,\n EmptyStateIllustrationProps\n>(\n (\n {\n className,\n size = 'sm',\n variant = 'cloud',\n tone = 'primary',\n icon = <Heart aria-hidden=\"true\" />,\n ...props\n },\n ref,\n ) => {\n const accentId = React.useId();\n const shadeId = React.useId();\n const isPrimary = tone === 'primary';\n\n return (\n <div\n ref={ref}\n data-slot=\"empty-state-illustration\"\n data-testid=\"empty-state-illustration\"\n data-size={size}\n data-variant={variant}\n data-tone={tone}\n aria-hidden=\"true\"\n className={cn(\n 'relative shrink-0 text-primary',\n !isPrimary && 'text-muted-foreground',\n illustrationSizeClass[size][variant],\n className,\n )}\n {...props}\n >\n <div\n data-slot=\"empty-state-illustration-background\"\n data-testid=\"empty-state-illustration-background\"\n data-centered=\"true\"\n className={cn(\n 'absolute left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full',\n isPrimary ? 'bg-primary/20' : 'bg-muted/80',\n illustrationCircleSizeClass[size],\n illustrationIconCenterClass[variant],\n )}\n />\n <DecorativeDots tone={tone} />\n <svg\n viewBox=\"0 0 220 168\"\n className=\"absolute inset-0 size-full overflow-visible\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <defs>\n <linearGradient id={accentId} x1=\"25\" y1=\"12\" x2=\"190\" y2=\"148\">\n <stop\n stopColor={isPrimary ? 'var(--primary)' : 'var(--muted)'}\n stopOpacity={isPrimary ? 0.34 : 0.74}\n />\n <stop stopColor=\"var(--card)\" stopOpacity={0.95} />\n </linearGradient>\n <linearGradient id={shadeId} x1=\"54\" y1=\"18\" x2=\"165\" y2=\"140\">\n <stop stopColor=\"var(--card)\" />\n <stop\n stopColor={\n isPrimary ? 'var(--primary)' : 'var(--muted-foreground)'\n }\n stopOpacity={isPrimary ? 0.18 : 0.14}\n />\n </linearGradient>\n </defs>\n\n {variant === 'cloud' && (\n <CloudShape accentId={accentId} shadeId={shadeId} tone={tone} />\n )}\n {variant === 'box' && (\n <BoxShape accentId={accentId} shadeId={shadeId} />\n )}\n {variant === 'documents' && (\n <DocumentsShape accentId={accentId} shadeId={shadeId} />\n )}\n {variant === 'credit-card' && (\n <CreditCardShape accentId={accentId} shadeId={shadeId} />\n )}\n </svg>\n <div\n data-slot=\"empty-state-illustration-icon\"\n data-testid=\"empty-state-illustration-icon\"\n data-centered=\"true\"\n className={cn(\n 'absolute left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-xl bg-primary/10 text-primary shadow-xs backdrop-blur-md supports-backdrop-filter:backdrop-blur-md [&>svg]:shrink-0',\n !isPrimary && 'bg-muted text-muted-foreground',\n illustrationIconSizeClass[size],\n illustrationIconCenterClass[variant],\n )}\n >\n <EmptyStateIconGlyph icon={icon} size={size} />\n </div>\n </div>\n );\n },\n);\n\nEmptyStateIllustration.displayName = 'EmptyStateIllustration';\n\n// ============================================================================\n// EmptyState\n// ============================================================================\n\nconst emptyStateVariants = cva(\n 'relative isolate mx-auto flex w-full max-w-[512px] items-center justify-center overflow-visible py-8 text-center',\n {\n variants: {\n size: {\n sm: 'min-h-[212px]',\n md: 'min-h-[280px]',\n lg: 'min-h-[360px]',\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n },\n);\n\nexport interface EmptyStateProps\n extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {\n title: React.ReactNode;\n description?: React.ReactNode;\n size?: EmptyStateSize;\n media?: EmptyStateMedia;\n pattern?: EmptyStateBackgroundPatternVariant | 'auto';\n icon?: React.ReactNode;\n iconLabel?: string;\n illustrationVariant?: EmptyStateIllustrationVariant;\n illustrationTone?: EmptyStateTone;\n fileExtension?: FileExtension;\n fileType?: SimpleFileType;\n primaryAction?: EmptyStateActionConfig;\n secondaryAction?: EmptyStateActionConfig;\n actions?: React.ReactNode;\n headingLevel?: 2 | 3 | 4;\n}\n\nfunction resolvePattern(\n pattern: EmptyStateProps['pattern'],\n media: EmptyStateMedia,\n): EmptyStateBackgroundPatternVariant {\n if (!pattern || pattern === 'auto') {\n if (media === 'illustration') return 'grid';\n if (media === 'none') return 'none';\n return 'circles';\n }\n return pattern;\n}\n\nfunction renderEmptyStateAction(\n action: EmptyStateActionConfig,\n intent: 'primary' | 'secondary',\n) {\n const {\n label,\n onClick,\n startIcon,\n disabled,\n loading,\n 'aria-label': ariaLabel,\n } = action;\n\n return (\n <Button\n appearance={intent === 'primary' ? 'solid' : 'outline'}\n variant={intent === 'primary' ? 'primary' : 'secondary'}\n size=\"sm\"\n shape=\"rounded\"\n onClick={onClick}\n disabled={disabled}\n loading={loading}\n startIcon={startIcon}\n aria-label={ariaLabel}\n type=\"button\"\n >\n {label}\n </Button>\n );\n}\n\nexport const EmptyState = React.forwardRef<HTMLElement, EmptyStateProps>(\n (\n {\n className,\n title,\n description,\n size = 'sm',\n media = 'featured-icon',\n pattern = 'auto',\n icon,\n iconLabel,\n illustrationVariant = 'cloud',\n illustrationTone = 'gray',\n fileExtension,\n fileType = 'document',\n primaryAction,\n secondaryAction,\n actions,\n headingLevel = 3,\n ...props\n },\n ref,\n ) => {\n const Heading = headingTag[headingLevel];\n const resolvedPattern = resolvePattern(pattern, media);\n const defaultIcon = icon ?? <Search aria-hidden=\"true\" />;\n const hasActions = actions || primaryAction || secondaryAction;\n\n return (\n <section\n ref={ref}\n data-slot=\"empty-state\"\n aria-label={typeof title === 'string' ? title : 'Empty state'}\n className={cn(emptyStateVariants({ size }), className)}\n {...props}\n >\n <div\n data-slot=\"empty-state-content\"\n className={cn(\n 'relative z-10 flex min-w-0 flex-1 flex-col items-center',\n contentGapClass[size],\n )}\n >\n <div\n data-slot=\"empty-state-body\"\n className={cn(\n 'flex w-full flex-col items-center',\n mediaGapClass[size],\n )}\n >\n {media !== 'none' && (\n <div\n data-slot=\"empty-state-media\"\n data-testid=\"empty-state-media\"\n data-media={media}\n data-centered=\"true\"\n className=\"relative flex w-full min-w-0 justify-center\"\n >\n <EmptyStateBackgroundPattern\n size={size}\n variant={resolvedPattern}\n data-centered=\"true\"\n className=\"z-0\"\n />\n\n {media === 'featured-icon' && (\n <FeaturedIcon\n data-slot=\"empty-state-featured-icon\"\n size={featuredIconSize[size]}\n shape=\"rounded\"\n intent=\"default\"\n icon={\n <EmptyStateIconGlyph icon={defaultIcon} size={size} />\n }\n aria-label={iconLabel}\n className=\"relative z-10 delight-stagger motion-reduce:animate-none\"\n />\n )}\n\n {media === 'illustration' && (\n <EmptyStateIllustration\n size={size}\n variant={illustrationVariant}\n tone={illustrationTone}\n icon={defaultIcon}\n className=\"relative z-10 delight-stagger motion-reduce:animate-none\"\n />\n )}\n\n {media === 'file-type-icon' && (\n <div\n data-slot=\"empty-state-file-icon-wrap\"\n data-testid=\"empty-state-file-icon-wrap\"\n data-centered=\"true\"\n className={cn(\n 'relative z-10 flex items-center justify-center rounded-full bg-linear-[104deg,color-mix(in_oklch,var(--card)_60%,transparent),color-mix(in_oklch,var(--muted)_55%,transparent)] delight-stagger motion-reduce:animate-none',\n fileIconWrapSizeClass[size],\n )}\n >\n <div\n data-slot=\"empty-state-file-icon-optical-center\"\n data-testid=\"empty-state-file-icon-optical-center\"\n data-centered=\"true\"\n >\n <FileTypeIcon\n extension={fileExtension}\n fileType={fileExtension ? undefined : fileType}\n size={fileIconSize[size]}\n className=\"drop-shadow-[0_1px_2px_var(--shadow-xs-1-color)]\"\n />\n </div>\n </div>\n )}\n </div>\n )}\n\n <div\n data-slot=\"empty-state-text\"\n className={cn(\n 'flex w-full max-w-[352px] flex-col items-center text-center',\n textGapClass[size],\n )}\n >\n <Heading className=\"w-full text-base font-semibold leading-6 text-foreground\">\n {title}\n </Heading>\n {description && (\n <p className=\"w-full text-sm leading-5 text-secondary-foreground\">\n {description}\n </p>\n )}\n </div>\n </div>\n\n {hasActions && (\n <div\n data-slot=\"empty-state-actions\"\n className=\"flex flex-wrap items-center justify-center gap-3\"\n >\n {actions ?? (\n <>\n {secondaryAction &&\n renderEmptyStateAction(secondaryAction, 'secondary')}\n {primaryAction &&\n renderEmptyStateAction(primaryAction, 'primary')}\n </>\n )}\n </div>\n )}\n </div>\n </section>\n );\n },\n);\n\nEmptyState.displayName = 'EmptyState';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index194.js","names":[],"sources":["../src/components/organisms/content/EmptyState/EmptyState.tsx"],"sourcesContent":["import { cva } from 'class-variance-authority';\nimport { Heart, Search } from 'lucide-react';\nimport * as React from 'react';\nimport { Button } from '@/components/atoms/buttons/Button';\nimport { FeaturedIcon } from '@/components/molecules/data/FeaturedIcon';\nimport {\n type FileExtension,\n FileTypeIcon,\n type SimpleFileType,\n} from '@/components/molecules/files/FileTypeIcon';\nimport { cn } from '@/lib/utils';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type EmptyStateSize = 'sm' | 'md' | 'lg';\nexport type EmptyStateMedia =\n | 'featured-icon'\n | 'illustration'\n | 'file-type-icon'\n | 'none';\nexport type EmptyStateBackgroundPatternVariant =\n | 'circles'\n | 'grid'\n | 'grid-dot'\n | 'squares'\n | 'none';\nexport type EmptyStateIllustrationVariant =\n | 'cloud'\n | 'box'\n | 'documents'\n | 'credit-card';\nexport type EmptyStateTone = 'primary' | 'gray';\n\nexport interface EmptyStateActionConfig {\n label: React.ReactNode;\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n startIcon?: React.ReactNode;\n disabled?: boolean;\n loading?: boolean;\n 'aria-label'?: string;\n}\n\n// ============================================================================\n// Shared maps\n// ============================================================================\n\nconst patternSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-[336px]',\n md: 'size-[480px]',\n lg: 'size-[768px]',\n};\n\nconst patternGridSize: Record<EmptyStateSize, string> = {\n sm: '24px 24px',\n md: '32px 32px',\n lg: '48px 48px',\n};\n\nconst illustrationSizeClass: Record<\n EmptyStateSize,\n Record<EmptyStateIllustrationVariant, string>\n> = {\n sm: {\n cloud: 'h-[118px] w-[152px]',\n box: 'h-[124px] w-[152px]',\n documents: 'h-[118px] w-[152px]',\n 'credit-card': 'h-[118px] w-[152px]',\n },\n md: {\n cloud: 'h-32 w-[172px]',\n box: 'h-[136px] w-[172px]',\n documents: 'h-32 w-[172px]',\n 'credit-card': 'h-[134px] w-[172px]',\n },\n lg: {\n cloud: 'h-40 w-[220px]',\n box: 'h-[168px] w-[220px]',\n documents: 'h-40 w-[220px]',\n 'credit-card': 'h-40 w-[220px]',\n },\n};\n\nconst illustrationIconSizeClass: Record<EmptyStateSize, string> = {\n sm: 'p-2',\n md: 'p-2.5',\n lg: 'p-2.5',\n};\n\nconst iconGlyphSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-4',\n md: 'size-4',\n lg: 'size-5',\n};\n\nconst illustrationCircleSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-[104px]',\n md: 'size-32',\n lg: 'size-40',\n};\n\nconst fileIconWrapSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-20',\n md: 'size-24',\n lg: 'size-28',\n};\n\nconst textGapClass: Record<EmptyStateSize, string> = {\n sm: 'gap-1',\n md: 'gap-2',\n lg: 'gap-2',\n};\n\nconst mediaGapClass: Record<EmptyStateSize, string> = {\n sm: 'gap-4',\n md: 'gap-5',\n lg: 'gap-5',\n};\n\nconst contentGapClass: Record<EmptyStateSize, string> = {\n sm: 'gap-6',\n md: 'gap-8',\n lg: 'gap-8',\n};\n\nconst featuredIconSize: Record<EmptyStateSize, 'sm' | 'md' | 'lg'> = {\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n};\n\nconst fileIconSize: Record<EmptyStateSize, 'sm' | 'md' | 'lg'> = {\n sm: 'md',\n md: 'md',\n lg: 'md',\n};\n\nconst headingTag = {\n 2: 'h2',\n 3: 'h3',\n 4: 'h4',\n} as const;\n\nfunction EmptyStateIconGlyph({\n icon,\n size,\n}: {\n icon: React.ReactNode;\n size: EmptyStateSize;\n}) {\n return (\n <span\n data-slot=\"empty-state-icon-glyph\"\n data-testid=\"empty-state-icon-glyph\"\n data-centered=\"true\"\n aria-hidden=\"true\"\n className={cn(\n 'inline-flex shrink-0 items-center justify-center leading-none [line-height:0] [&>svg]:block [&>svg]:size-full [&>svg]:shrink-0',\n iconGlyphSizeClass[size],\n )}\n >\n {icon}\n </span>\n );\n}\n\n// ============================================================================\n// Background Pattern\n// ============================================================================\n\nexport interface EmptyStateBackgroundPatternProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n size?: EmptyStateSize;\n variant?: EmptyStateBackgroundPatternVariant;\n}\n\nconst gridPatternStyle = (\n size: EmptyStateSize,\n dot = false,\n): React.CSSProperties => ({\n backgroundImage: dot\n ? 'radial-gradient(circle, color-mix(in oklch, var(--border) 70%, transparent) 1px, transparent 1px)'\n : [\n 'linear-gradient(to right, color-mix(in oklch, var(--border) 54%, transparent) 1px, transparent 1px)',\n 'linear-gradient(to bottom, color-mix(in oklch, var(--border) 54%, transparent) 1px, transparent 1px)',\n ].join(', '),\n backgroundSize: patternGridSize[size],\n});\n\nconst squaresBySize: Record<EmptyStateSize, number[]> = {\n sm: [96, 144, 192, 240, 288, 336],\n md: [96, 160, 224, 288, 352, 416, 480],\n lg: [96, 192, 288, 384, 480, 576, 672, 768],\n};\n\nexport const EmptyStateBackgroundPattern = React.forwardRef<\n HTMLDivElement,\n EmptyStateBackgroundPatternProps\n>(({ className, size = 'sm', variant = 'circles', style, ...props }, ref) => {\n if (variant === 'none') {\n return null;\n }\n\n return (\n <div\n ref={ref}\n data-slot=\"empty-state-background-pattern\"\n data-testid=\"empty-state-pattern\"\n data-size={size}\n data-variant={variant}\n aria-hidden=\"true\"\n className={cn(\n 'pointer-events-none absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 overflow-hidden opacity-75',\n patternSizeClass[size],\n className,\n )}\n style={style}\n {...props}\n >\n <div className=\"absolute inset-0 bg-[radial-gradient(circle_at_center,var(--background)_0%,transparent_68%)]\" />\n\n {variant === 'circles' && (\n <div className=\"absolute inset-0\">\n {Array.from({ length: 7 }, (_, index) => (\n <span\n key={index}\n className=\"absolute left-1/2 top-1/2 rounded-full border border-border/60\"\n style={{\n width: `${(index + 1) * 14}%`,\n height: `${(index + 1) * 14}%`,\n transform: 'translate(-50%, -50%)',\n }}\n />\n ))}\n </div>\n )}\n\n {(variant === 'grid' || variant === 'grid-dot') && (\n <div\n className=\"absolute inset-0 opacity-70 [mask-image:radial-gradient(circle_at_center,black_0%,black_48%,transparent_76%)]\"\n style={gridPatternStyle(size, variant === 'grid-dot')}\n />\n )}\n\n {variant === 'squares' && (\n <div className=\"absolute inset-0\">\n {squaresBySize[size].map((squareSize) => (\n <span\n key={squareSize}\n className=\"absolute left-1/2 top-1/2 rounded-xl border border-border/55\"\n style={{\n width: squareSize,\n height: squareSize,\n transform: 'translate(-50%, -50%) rotate(-12.5deg)',\n }}\n />\n ))}\n </div>\n )}\n </div>\n );\n});\n\nEmptyStateBackgroundPattern.displayName = 'EmptyStateBackgroundPattern';\n\n// ============================================================================\n// Illustration\n// ============================================================================\n\nexport interface EmptyStateIllustrationProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n size?: EmptyStateSize;\n variant?: EmptyStateIllustrationVariant;\n tone?: EmptyStateTone;\n icon?: React.ReactNode;\n}\n\nfunction DecorativeDots({ tone }: { tone: EmptyStateTone }) {\n const dotClassName =\n tone === 'primary' ? 'bg-primary/70' : 'bg-muted-foreground/10';\n\n return (\n <>\n <span\n className={cn(\n 'absolute left-[7%] top-[8%] size-2 rounded-full',\n dotClassName,\n )}\n />\n <span\n className={cn(\n 'absolute right-[6%] top-[18%] size-3 rounded-full',\n dotClassName,\n )}\n />\n <span\n className={cn(\n 'absolute bottom-[10%] left-[8%] size-3 rounded-full',\n dotClassName,\n )}\n />\n <span\n className={cn(\n 'absolute bottom-[18%] right-[13%] size-2 rounded-full',\n dotClassName,\n )}\n />\n </>\n );\n}\n\n// Keep every artwork bbox centered on the shared 220 × 168 viewBox center (110, 84).\nfunction CloudShape({\n accentId,\n shadeId,\n tone,\n}: {\n accentId: string;\n shadeId: string;\n tone: EmptyStateTone;\n}) {\n return (\n <g\n transform=\"translate(10.5 14.5)\"\n className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\"\n >\n <path\n d=\"M54 110c-21 0-38-14-38-32 0-16 14-30 33-32 8-19 27-31 49-31 27 0 50 19 55 43 17 3 30 16 30 32 0 19-18 34-40 34H55c-1 0-1-14-1-14Z\"\n fill={`url(#${shadeId})`}\n />\n <path\n d=\"M68 106c-18 0-32-12-32-27 0-13 11-24 27-26 7-16 23-26 42-26 23 0 42 16 46 36 15 3 26 14 26 28 0 16-15 29-34 29H68v-14Z\"\n fill={`url(#${accentId})`}\n opacity={tone === 'primary' ? 0.78 : 0.36}\n />\n </g>\n );\n}\n\nfunction BoxShape({\n accentId,\n shadeId,\n}: {\n accentId: string;\n shadeId: string;\n}) {\n return (\n <g\n transform=\"translate(-19.5)\"\n className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\"\n >\n <path d=\"M72 42 132 20l55 31-62 24-53-33Z\" fill={`url(#${accentId})`} />\n <path d=\"M72 42v72l53 34V75L72 42Z\" fill={`url(#${shadeId})`} />\n <path d=\"M125 75v73l62-35V51l-62 24Z\" fill=\"var(--card)\" />\n <path\n d=\"M132 20v33l24 14V34l-24-14Z\"\n fill=\"currentColor\"\n opacity=\"0.34\"\n />\n <path\n d=\"M72 42 132 20l55 31-62 24-53-33Z\"\n fill=\"none\"\n stroke=\"var(--border)\"\n />\n </g>\n );\n}\n\nfunction DocumentsShape({\n accentId,\n shadeId,\n}: {\n accentId: string;\n shadeId: string;\n}) {\n return (\n <g\n transform=\"translate(0 -0.5)\"\n className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\"\n >\n <g transform=\"translate(44 48) rotate(-18)\">\n <rect\n width=\"58\"\n height=\"78\"\n rx=\"7\"\n fill={`url(#${shadeId})`}\n stroke=\"var(--border)\"\n />\n <path\n d=\"M15 21h28M15 35h21M15 49h28\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.28\"\n />\n </g>\n <g transform=\"translate(83 32)\">\n <rect\n width=\"58\"\n height=\"88\"\n rx=\"7\"\n fill=\"var(--card)\"\n stroke=\"var(--border)\"\n />\n <path\n d=\"M16 26h28M16 41h22M16 56h28\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.32\"\n />\n </g>\n <g transform=\"translate(121 47) rotate(18)\">\n <rect\n width=\"58\"\n height=\"78\"\n rx=\"7\"\n fill={`url(#${accentId})`}\n stroke=\"var(--border)\"\n />\n <path\n d=\"M15 21h28M15 35h21M15 49h28\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.32\"\n />\n </g>\n </g>\n );\n}\n\nfunction CreditCardShape({\n accentId,\n shadeId,\n}: {\n accentId: string;\n shadeId: string;\n}) {\n return (\n <g\n transform=\"translate(0 -5)\"\n className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\"\n >\n <rect\n x=\"42\"\n y=\"48\"\n width=\"136\"\n height=\"82\"\n rx=\"12\"\n fill={`url(#${shadeId})`}\n stroke=\"var(--border)\"\n />\n <rect\n x=\"42\"\n y=\"70\"\n width=\"136\"\n height=\"16\"\n fill={`url(#${accentId})`}\n opacity=\"0.72\"\n />\n <rect\n x=\"58\"\n y=\"104\"\n width=\"28\"\n height=\"8\"\n rx=\"2\"\n fill=\"currentColor\"\n opacity=\"0.28\"\n />\n <rect\n x=\"58\"\n y=\"116\"\n width=\"58\"\n height=\"5\"\n rx=\"2.5\"\n fill=\"currentColor\"\n opacity=\"0.18\"\n />\n <circle cx=\"146\" cy=\"112\" r=\"10\" fill=\"currentColor\" opacity=\"0.24\" />\n <circle cx=\"158\" cy=\"112\" r=\"10\" fill=\"currentColor\" opacity=\"0.38\" />\n </g>\n );\n}\n\nexport const EmptyStateIllustration = React.forwardRef<\n HTMLDivElement,\n EmptyStateIllustrationProps\n>(\n (\n {\n className,\n size = 'sm',\n variant = 'cloud',\n tone = 'primary',\n icon = <Heart aria-hidden=\"true\" />,\n ...props\n },\n ref,\n ) => {\n const accentId = React.useId();\n const shadeId = React.useId();\n const isPrimary = tone === 'primary';\n\n return (\n <div\n ref={ref}\n data-slot=\"empty-state-illustration\"\n data-testid=\"empty-state-illustration\"\n data-size={size}\n data-variant={variant}\n data-tone={tone}\n aria-hidden=\"true\"\n className={cn(\n 'relative shrink-0 text-primary',\n !isPrimary && 'text-muted-foreground',\n illustrationSizeClass[size][variant],\n className,\n )}\n {...props}\n >\n <div\n data-slot=\"empty-state-illustration-background\"\n data-testid=\"empty-state-illustration-background\"\n data-centered=\"true\"\n className={cn(\n 'absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full',\n isPrimary ? 'bg-primary/20' : 'bg-muted/80',\n illustrationCircleSizeClass[size],\n )}\n />\n <DecorativeDots tone={tone} />\n <svg\n viewBox=\"0 0 220 168\"\n className=\"absolute inset-0 size-full overflow-visible\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <defs>\n <linearGradient id={accentId} x1=\"25\" y1=\"12\" x2=\"190\" y2=\"148\">\n <stop\n stopColor={isPrimary ? 'var(--primary)' : 'var(--muted)'}\n stopOpacity={isPrimary ? 0.34 : 0.74}\n />\n <stop stopColor=\"var(--card)\" stopOpacity={0.95} />\n </linearGradient>\n <linearGradient id={shadeId} x1=\"54\" y1=\"18\" x2=\"165\" y2=\"140\">\n <stop stopColor=\"var(--card)\" />\n <stop\n stopColor={\n isPrimary ? 'var(--primary)' : 'var(--muted-foreground)'\n }\n stopOpacity={isPrimary ? 0.18 : 0.14}\n />\n </linearGradient>\n </defs>\n\n {variant === 'cloud' && (\n <CloudShape accentId={accentId} shadeId={shadeId} tone={tone} />\n )}\n {variant === 'box' && (\n <BoxShape accentId={accentId} shadeId={shadeId} />\n )}\n {variant === 'documents' && (\n <DocumentsShape accentId={accentId} shadeId={shadeId} />\n )}\n {variant === 'credit-card' && (\n <CreditCardShape accentId={accentId} shadeId={shadeId} />\n )}\n </svg>\n <div\n data-slot=\"empty-state-illustration-icon\"\n data-testid=\"empty-state-illustration-icon\"\n data-centered=\"true\"\n className={cn(\n 'absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-xl bg-primary/10 text-primary shadow-xs backdrop-blur-md supports-backdrop-filter:backdrop-blur-md [&>svg]:shrink-0',\n !isPrimary && 'bg-muted text-muted-foreground',\n illustrationIconSizeClass[size],\n )}\n >\n <EmptyStateIconGlyph icon={icon} size={size} />\n </div>\n </div>\n );\n },\n);\n\nEmptyStateIllustration.displayName = 'EmptyStateIllustration';\n\n// ============================================================================\n// EmptyState\n// ============================================================================\n\nconst emptyStateVariants = cva(\n 'relative isolate mx-auto flex w-full max-w-[512px] items-center justify-center overflow-visible py-8 text-center',\n {\n variants: {\n size: {\n sm: 'min-h-[212px]',\n md: 'min-h-[280px]',\n lg: 'min-h-[360px]',\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n },\n);\n\nexport interface EmptyStateProps\n extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {\n title: React.ReactNode;\n description?: React.ReactNode;\n size?: EmptyStateSize;\n media?: EmptyStateMedia;\n pattern?: EmptyStateBackgroundPatternVariant | 'auto';\n icon?: React.ReactNode;\n iconLabel?: string;\n illustrationVariant?: EmptyStateIllustrationVariant;\n illustrationTone?: EmptyStateTone;\n fileExtension?: FileExtension;\n fileType?: SimpleFileType;\n primaryAction?: EmptyStateActionConfig;\n secondaryAction?: EmptyStateActionConfig;\n actions?: React.ReactNode;\n headingLevel?: 2 | 3 | 4;\n}\n\nfunction resolvePattern(\n pattern: EmptyStateProps['pattern'],\n media: EmptyStateMedia,\n): EmptyStateBackgroundPatternVariant {\n if (!pattern || pattern === 'auto') {\n if (media === 'illustration') return 'grid';\n if (media === 'none') return 'none';\n return 'circles';\n }\n return pattern;\n}\n\nfunction renderEmptyStateAction(\n action: EmptyStateActionConfig,\n intent: 'primary' | 'secondary',\n) {\n const {\n label,\n onClick,\n startIcon,\n disabled,\n loading,\n 'aria-label': ariaLabel,\n } = action;\n\n return (\n <Button\n appearance={intent === 'primary' ? 'solid' : 'outline'}\n variant={intent === 'primary' ? 'primary' : 'secondary'}\n size=\"sm\"\n shape=\"rounded\"\n onClick={onClick}\n disabled={disabled}\n loading={loading}\n startIcon={startIcon}\n aria-label={ariaLabel}\n type=\"button\"\n >\n {label}\n </Button>\n );\n}\n\nexport const EmptyState = React.forwardRef<HTMLElement, EmptyStateProps>(\n (\n {\n className,\n title,\n description,\n size = 'sm',\n media = 'featured-icon',\n pattern = 'auto',\n icon,\n iconLabel,\n illustrationVariant = 'cloud',\n illustrationTone = 'gray',\n fileExtension,\n fileType = 'document',\n primaryAction,\n secondaryAction,\n actions,\n headingLevel = 3,\n ...props\n },\n ref,\n ) => {\n const Heading = headingTag[headingLevel];\n const resolvedPattern = resolvePattern(pattern, media);\n const defaultIcon = icon ?? <Search aria-hidden=\"true\" />;\n const hasActions = actions || primaryAction || secondaryAction;\n\n return (\n <section\n ref={ref}\n data-slot=\"empty-state\"\n aria-label={typeof title === 'string' ? title : 'Empty state'}\n className={cn(emptyStateVariants({ size }), className)}\n {...props}\n >\n <div\n data-slot=\"empty-state-content\"\n className={cn(\n 'relative z-10 flex min-w-0 flex-1 flex-col items-center',\n contentGapClass[size],\n )}\n >\n <div\n data-slot=\"empty-state-body\"\n className={cn(\n 'flex w-full flex-col items-center',\n mediaGapClass[size],\n )}\n >\n {media !== 'none' && (\n <div\n data-slot=\"empty-state-media\"\n data-testid=\"empty-state-media\"\n data-media={media}\n data-centered=\"true\"\n className=\"relative flex w-full min-w-0 justify-center\"\n >\n <EmptyStateBackgroundPattern\n size={size}\n variant={resolvedPattern}\n data-centered=\"true\"\n className=\"z-0\"\n />\n\n {media === 'featured-icon' && (\n <FeaturedIcon\n data-slot=\"empty-state-featured-icon\"\n size={featuredIconSize[size]}\n shape=\"rounded\"\n intent=\"default\"\n icon={\n <EmptyStateIconGlyph icon={defaultIcon} size={size} />\n }\n aria-label={iconLabel}\n className=\"relative z-10 delight-stagger motion-reduce:animate-none\"\n />\n )}\n\n {media === 'illustration' && (\n <EmptyStateIllustration\n size={size}\n variant={illustrationVariant}\n tone={illustrationTone}\n icon={defaultIcon}\n className=\"relative z-10 delight-stagger motion-reduce:animate-none\"\n />\n )}\n\n {media === 'file-type-icon' && (\n <div\n data-slot=\"empty-state-file-icon-wrap\"\n data-testid=\"empty-state-file-icon-wrap\"\n data-centered=\"true\"\n className={cn(\n 'relative z-10 flex items-center justify-center rounded-full bg-linear-[104deg,color-mix(in_oklch,var(--card)_60%,transparent),color-mix(in_oklch,var(--muted)_55%,transparent)] delight-stagger motion-reduce:animate-none',\n fileIconWrapSizeClass[size],\n )}\n >\n <div\n data-slot=\"empty-state-file-icon-optical-center\"\n data-testid=\"empty-state-file-icon-optical-center\"\n data-centered=\"true\"\n >\n <FileTypeIcon\n extension={fileExtension}\n fileType={fileExtension ? undefined : fileType}\n size={fileIconSize[size]}\n className=\"drop-shadow-[0_1px_2px_var(--shadow-xs-1-color)]\"\n />\n </div>\n </div>\n )}\n </div>\n )}\n\n <div\n data-slot=\"empty-state-text\"\n className={cn(\n 'flex w-full max-w-[352px] flex-col items-center text-center',\n textGapClass[size],\n )}\n >\n <Heading className=\"w-full text-base font-semibold leading-6 text-foreground\">\n {title}\n </Heading>\n {description && (\n <p className=\"w-full text-sm leading-5 text-secondary-foreground\">\n {description}\n </p>\n )}\n </div>\n </div>\n\n {hasActions && (\n <div\n data-slot=\"empty-state-actions\"\n className=\"flex flex-wrap items-center justify-center gap-3\"\n >\n {actions ?? (\n <>\n {secondaryAction &&\n renderEmptyStateAction(secondaryAction, 'secondary')}\n {primaryAction &&\n renderEmptyStateAction(primaryAction, 'primary')}\n </>\n )}\n </div>\n )}\n </div>\n </section>\n );\n },\n);\n\nEmptyState.displayName = 'EmptyState';\n"],"mappings":";;;;;;;;;AAgDA,IAAM,mBAAmD;CACvD,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,kBAAkD;CACtD,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,wBAGF;CACF,IAAI;EACF,OAAO;EACP,KAAK;EACL,WAAW;EACX,eAAe;CACjB;CACA,IAAI;EACF,OAAO;EACP,KAAK;EACL,WAAW;EACX,eAAe;CACjB;CACA,IAAI;EACF,OAAO;EACP,KAAK;EACL,WAAW;EACX,eAAe;CACjB;AACF;AAEA,IAAM,4BAA4D;CAChE,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,qBAAqD;CACzD,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,8BAA8D;CAClE,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,wBAAwD;CAC5D,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,eAA+C;CACnD,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,gBAAgD;CACpD,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,kBAAkD;CACtD,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,mBAA+D;CACnE,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,eAA2D;CAC/D,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,aAAa;CACjB,GAAG;CACH,GAAG;CACH,GAAG;AACL;AAEA,SAAS,oBAAoB,EAC3B,MACA,QAIC;CACD,OACE,oBAAC,QAAD;EACE,aAAU;EACV,eAAY;EACZ,iBAAc;EACd,eAAY;EACZ,WAAW,GACT,kIACA,mBAAmB,KACrB;EAEC,UAAA;CACG,CAAA;AAEV;AAYA,IAAM,oBACJ,MACA,MAAM,WACmB;CACzB,iBAAiB,MACb,sGACA,CACE,uGACA,sGACF,CAAC,CAAC,KAAK,IAAI;CACf,gBAAgB,gBAAgB;AAClC;AAEA,IAAM,gBAAkD;CACtD,IAAI;EAAC;EAAI;EAAK;EAAK;EAAK;EAAK;CAAG;CAChC,IAAI;EAAC;EAAI;EAAK;EAAK;EAAK;EAAK;EAAK;CAAG;CACrC,IAAI;EAAC;EAAI;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;CAAG;AAC5C;AAEA,IAAa,8BAA8B,QAAM,YAG9C,EAAE,WAAW,OAAO,MAAM,UAAU,WAAW,OAAO,GAAG,SAAS,QAAQ;CAC3E,IAAI,YAAY,QACd,OAAO;CAGT,OACE,qBAAC,OAAD;EACO;EACL,aAAU;EACV,eAAY;EACZ,aAAW;EACX,gBAAc;EACd,eAAY;EACZ,WAAW,GACT,8GACA,iBAAiB,OACjB,SACF;EACO;EACP,GAAI;EAbN,UAAA;GAeE,oBAAC,OAAD,EAAK,WAAU,+FAAgG,CAAA;GAE9G,YAAY,aACX,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,MAAM,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAG,UAC7B,oBAAC,QAAD;KAEE,WAAU;KACV,OAAO;MACL,OAAO,IAAI,QAAQ,KAAK,GAAG;MAC3B,QAAQ,IAAI,QAAQ,KAAK,GAAG;MAC5B,WAAW;KACb;IACD,GAPM,KAON,CACF;GACE,CAAA;IAGL,YAAY,UAAU,YAAY,eAClC,oBAAC,OAAD;IACE,WAAU;IACV,OAAO,iBAAiB,MAAM,YAAY,UAAU;GACrD,CAAA;GAGF,YAAY,aACX,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,cAAc,KAAK,CAAC,KAAK,eACxB,oBAAC,QAAD;KAEE,WAAU;KACV,OAAO;MACL,OAAO;MACP,QAAQ;MACR,WAAW;KACb;IACD,GAPM,UAON,CACF;GACE,CAAA;EAEJ;;AAET,CAAC;AAED,4BAA4B,cAAc;AAc1C,SAAS,eAAe,EAAE,QAAkC;CAC1D,MAAM,eACJ,SAAS,YAAY,kBAAkB;CAEzC,OACE,qBAAA,UAAA,EAAA,UAAA;EACE,oBAAC,QAAD,EACE,WAAW,GACT,mDACA,YACF,EACD,CAAA;EACD,oBAAC,QAAD,EACE,WAAW,GACT,qDACA,YACF,EACD,CAAA;EACD,oBAAC,QAAD,EACE,WAAW,GACT,uDACA,YACF,EACD,CAAA;EACD,oBAAC,QAAD,EACE,WAAW,GACT,yDACA,YACF,EACD,CAAA;CACD,EAAA,CAAA;AAEN;AAGA,SAAS,WAAW,EAClB,UACA,SACA,QAKC;CACD,OACE,qBAAC,KAAD;EACE,WAAU;EACV,WAAU;EAFZ,UAAA,CAIE,oBAAC,QAAD;GACE,GAAE;GACF,MAAM,QAAQ,QAAQ;EACvB,CAAA,GACD,oBAAC,QAAD;GACE,GAAE;GACF,MAAM,QAAQ,SAAS;GACvB,SAAS,SAAS,YAAY,MAAO;EACtC,CAAA,CACA;;AAEP;AAEA,SAAS,SAAS,EAChB,UACA,WAIC;CACD,OACE,qBAAC,KAAD;EACE,WAAU;EACV,WAAU;EAFZ,UAAA;GAIE,oBAAC,QAAD;IAAM,GAAE;IAAmC,MAAM,QAAQ,SAAS;GAAK,CAAA;GACvE,oBAAC,QAAD;IAAM,GAAE;IAA4B,MAAM,QAAQ,QAAQ;GAAK,CAAA;GAC/D,oBAAC,QAAD;IAAM,GAAE;IAA8B,MAAK;GAAe,CAAA;GAC1D,oBAAC,QAAD;IACE,GAAE;IACF,MAAK;IACL,SAAQ;GACT,CAAA;GACD,oBAAC,QAAD;IACE,GAAE;IACF,MAAK;IACL,QAAO;GACR,CAAA;EACA;;AAEP;AAEA,SAAS,eAAe,EACtB,UACA,WAIC;CACD,OACE,qBAAC,KAAD;EACE,WAAU;EACV,WAAU;EAFZ,UAAA;GAIE,qBAAC,KAAD;IAAG,WAAU;IAAb,UAAA,CACE,oBAAC,QAAD;KACE,OAAM;KACN,QAAO;KACP,IAAG;KACH,MAAM,QAAQ,QAAQ;KACtB,QAAO;IACR,CAAA,GACD,oBAAC,QAAD;KACE,GAAE;KACF,QAAO;KACP,eAAc;IACf,CAAA,CACA;;GACH,qBAAC,KAAD;IAAG,WAAU;IAAb,UAAA,CACE,oBAAC,QAAD;KACE,OAAM;KACN,QAAO;KACP,IAAG;KACH,MAAK;KACL,QAAO;IACR,CAAA,GACD,oBAAC,QAAD;KACE,GAAE;KACF,QAAO;KACP,eAAc;IACf,CAAA,CACA;;GACH,qBAAC,KAAD;IAAG,WAAU;IAAb,UAAA,CACE,oBAAC,QAAD;KACE,OAAM;KACN,QAAO;KACP,IAAG;KACH,MAAM,QAAQ,SAAS;KACvB,QAAO;IACR,CAAA,GACD,oBAAC,QAAD;KACE,GAAE;KACF,QAAO;KACP,eAAc;IACf,CAAA,CACA;;EACF;;AAEP;AAEA,SAAS,gBAAgB,EACvB,UACA,WAIC;CACD,OACE,qBAAC,KAAD;EACE,WAAU;EACV,WAAU;EAFZ,UAAA;GAIE,oBAAC,QAAD;IACE,GAAE;IACF,GAAE;IACF,OAAM;IACN,QAAO;IACP,IAAG;IACH,MAAM,QAAQ,QAAQ;IACtB,QAAO;GACR,CAAA;GACD,oBAAC,QAAD;IACE,GAAE;IACF,GAAE;IACF,OAAM;IACN,QAAO;IACP,MAAM,QAAQ,SAAS;IACvB,SAAQ;GACT,CAAA;GACD,oBAAC,QAAD;IACE,GAAE;IACF,GAAE;IACF,OAAM;IACN,QAAO;IACP,IAAG;IACH,MAAK;IACL,SAAQ;GACT,CAAA;GACD,oBAAC,QAAD;IACE,GAAE;IACF,GAAE;IACF,OAAM;IACN,QAAO;IACP,IAAG;IACH,MAAK;IACL,SAAQ;GACT,CAAA;GACD,oBAAC,UAAD;IAAQ,IAAG;IAAM,IAAG;IAAM,GAAE;IAAK,MAAK;IAAe,SAAQ;GAAQ,CAAA;GACrE,oBAAC,UAAD;IAAQ,IAAG;IAAM,IAAG;IAAM,GAAE;IAAK,MAAK;IAAe,SAAQ;GAAQ,CAAA;EACpE;;AAEP;AAEA,IAAa,yBAAyB,QAAM,YAKxC,EACE,WACA,OAAO,MACP,UAAU,SACV,OAAO,WACP,OAAO,oBAAC,OAAD,EAAO,eAAY,OAAQ,CAAA,GAClC,GAAG,SAEL,QACG;CACH,MAAM,WAAW,QAAM,MAAM;CAC7B,MAAM,UAAU,QAAM,MAAM;CAC5B,MAAM,YAAY,SAAS;CAE3B,OACE,qBAAC,OAAD;EACO;EACL,aAAU;EACV,eAAY;EACZ,aAAW;EACX,gBAAc;EACd,aAAW;EACX,eAAY;EACZ,WAAW,GACT,kCACA,CAAC,aAAa,yBACd,sBAAsB,KAAK,CAAC,UAC5B,SACF;EACA,GAAI;EAdN,UAAA;GAgBE,oBAAC,OAAD;IACE,aAAU;IACV,eAAY;IACZ,iBAAc;IACd,WAAW,GACT,4EACA,YAAY,kBAAkB,eAC9B,4BAA4B,KAC9B;GACD,CAAA;GACD,oBAAC,gBAAD,EAAsB,KAAO,CAAA;GAC7B,qBAAC,OAAD;IACE,SAAQ;IACR,WAAU;IACV,MAAK;IACL,eAAY;IAJd,UAAA;KAME,qBAAC,QAAD,EAAA,UAAA,CACE,qBAAC,kBAAD;MAAgB,IAAI;MAAU,IAAG;MAAK,IAAG;MAAK,IAAG;MAAM,IAAG;MAA1D,UAAA,CACE,oBAAC,QAAD;OACE,WAAW,YAAY,mBAAmB;OAC1C,aAAa,YAAY,MAAO;MACjC,CAAA,GACD,oBAAC,QAAD;OAAM,WAAU;OAAc,aAAa;MAAO,CAAA,CACpC;KAChB,CAAA,GAAA,qBAAC,kBAAD;MAAgB,IAAI;MAAS,IAAG;MAAK,IAAG;MAAK,IAAG;MAAM,IAAG;MAAzD,UAAA,CACE,oBAAC,QAAD,EAAM,WAAU,cAAe,CAAA,GAC/B,oBAAC,QAAD;OACE,WACE,YAAY,mBAAmB;OAEjC,aAAa,YAAY,MAAO;MACjC,CAAA,CACa;KACZ,CAAA,CAAA,EAAA,CAAA;KAEL,YAAY,WACX,oBAAC,YAAD;MAAsB;MAAmB;MAAe;KAAO,CAAA;KAEhE,YAAY,SACX,oBAAC,UAAD;MAAoB;MAAmB;KAAU,CAAA;KAElD,YAAY,eACX,oBAAC,gBAAD;MAA0B;MAAmB;KAAU,CAAA;KAExD,YAAY,iBACX,oBAAC,iBAAD;MAA2B;MAAmB;KAAU,CAAA;IAEvD;;GACL,oBAAC,OAAD;IACE,aAAU;IACV,eAAY;IACZ,iBAAc;IACd,WAAW,GACT,4NACA,CAAC,aAAa,kCACd,0BAA0B,KAC5B;IAEA,UAAA,oBAAC,qBAAD;KAA2B;KAAY;IAAO,CAAA;GAC3C,CAAA;EACF;;AAET,CACF;AAEA,uBAAuB,cAAc;AAMrC,IAAM,qBAAqB,IACzB,oHACA;CACE,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;CACN,EACF;CACA,iBAAiB,EACf,MAAM,KACR;AACF,CACF;AAqBA,SAAS,eACP,SACA,OACoC;CACpC,IAAI,CAAC,WAAW,YAAY,QAAQ;EAClC,IAAI,UAAU,gBAAgB,OAAO;EACrC,IAAI,UAAU,QAAQ,OAAO;EAC7B,OAAO;CACT;CACA,OAAO;AACT;AAEA,SAAS,uBACP,QACA,QACA;CACA,MAAM,EACJ,OACA,SACA,WACA,UACA,SACA,cAAc,cACZ;CAEJ,OACE,oBAAC,QAAD;EACE,YAAY,WAAW,YAAY,UAAU;EAC7C,SAAS,WAAW,YAAY,YAAY;EAC5C,MAAK;EACL,OAAM;EACG;EACC;EACD;EACE;EACX,cAAY;EACZ,MAAK;EAEJ,UAAA;CACK,CAAA;AAEZ;AAEA,IAAa,aAAa,QAAM,YAE5B,EACE,WACA,OACA,aACA,OAAO,MACP,QAAQ,iBACR,UAAU,QACV,MACA,WACA,sBAAsB,SACtB,mBAAmB,QACnB,eACA,WAAW,YACX,eACA,iBACA,SACA,eAAe,GACf,GAAG,SAEL,QACG;CACH,MAAM,UAAU,WAAW;CAC3B,MAAM,kBAAkB,eAAe,SAAS,KAAK;CACrD,MAAM,cAAc,QAAQ,oBAAC,QAAD,EAAQ,eAAY,OAAQ,CAAA;CACxD,MAAM,aAAa,WAAW,iBAAiB;CAE/C,OACE,oBAAC,WAAD;EACO;EACL,aAAU;EACV,cAAY,OAAO,UAAU,WAAW,QAAQ;EAChD,WAAW,GAAG,mBAAmB,EAAE,KAAK,CAAC,GAAG,SAAS;EACrD,GAAI;EAEJ,UAAA,qBAAC,OAAD;GACE,aAAU;GACV,WAAW,GACT,2DACA,gBAAgB,KAClB;GALF,UAAA,CAOE,qBAAC,OAAD;IACE,aAAU;IACV,WAAW,GACT,qCACA,cAAc,KAChB;IALF,UAAA,CAOG,UAAU,UACT,qBAAC,OAAD;KACE,aAAU;KACV,eAAY;KACZ,cAAY;KACZ,iBAAc;KACd,WAAU;KALZ,UAAA;MAOE,oBAAC,6BAAD;OACQ;OACN,SAAS;OACT,iBAAc;OACd,WAAU;MACX,CAAA;MAEA,UAAU,mBACT,oBAAC,cAAD;OACE,aAAU;OACV,MAAM,iBAAiB;OACvB,OAAM;OACN,QAAO;OACP,MACE,oBAAC,qBAAD;QAAqB,MAAM;QAAmB;OAAO,CAAA;OAEvD,cAAY;OACZ,WAAU;MACX,CAAA;MAGF,UAAU,kBACT,oBAAC,wBAAD;OACQ;OACN,SAAS;OACT,MAAM;OACN,MAAM;OACN,WAAU;MACX,CAAA;MAGF,UAAU,oBACT,oBAAC,OAAD;OACE,aAAU;OACV,eAAY;OACZ,iBAAc;OACd,WAAW,GACT,8NACA,sBAAsB,KACxB;OAEA,UAAA,oBAAC,OAAD;QACE,aAAU;QACV,eAAY;QACZ,iBAAc;QAEd,UAAA,oBAAC,cAAD;SACE,WAAW;SACX,UAAU,gBAAgB,KAAA,IAAY;SACtC,MAAM,aAAa;SACnB,WAAU;QACX,CAAA;OACE,CAAA;MACF,CAAA;KAEJ;IAGP,CAAA,GAAA,qBAAC,OAAD;KACE,aAAU;KACV,WAAW,GACT,+DACA,aAAa,KACf;KALF,UAAA,CAOE,oBAAC,SAAD;MAAS,WAAU;MAChB,UAAA;KACM,CAAA,GACR,eACC,oBAAC,KAAD;MAAG,WAAU;MACV,UAAA;KACA,CAAA,CAEF;IACF,CAAA,CAAA;GAEJ,CAAA,GAAA,cACC,oBAAC,OAAD;IACE,aAAU;IACV,WAAU;IAET,UAAA,WACC,qBAAA,UAAA,EAAA,UAAA,CACG,mBACC,uBAAuB,iBAAiB,WAAW,GACpD,iBACC,uBAAuB,eAAe,SAAS,CACjD,EAAA,CAAA;GAED,CAAA,CAEJ;;CACE,CAAA;AAEb,CACF;AAEA,WAAW,cAAc"}
package/dist/index24.js CHANGED
@@ -216,7 +216,7 @@ var FeaturedIcon = React$1.forwardRef(({ children, size = "sm", className }, ref
216
216
  className: cn("shrink-0 rounded-md border border-border bg-card/60", "flex items-center justify-center", "dark:border-border", containerSize, className),
217
217
  style: { boxShadow: "var(--shadow-inset-ring)" },
218
218
  children: /* @__PURE__ */ jsx("div", {
219
- className: cn("text-secondary-foreground", innerSize),
219
+ className: cn("text-secondary-foreground [&>svg]:block [&>svg]:size-full", innerSize),
220
220
  children
221
221
  })
222
222
  });