@neuronection/assistant-ui 0.5.0 → 0.7.0

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 (73) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +4 -0
  3. package/dist/ai-magic-fill.d.ts +20 -0
  4. package/dist/ai-magic-fill.js +3 -0
  5. package/dist/ai-magic-fill.js.map +1 -0
  6. package/dist/{chunk-BUPMDOVL.js → chunk-2EPZAT3X.js} +2 -2
  7. package/dist/{chunk-BUPMDOVL.js.map → chunk-2EPZAT3X.js.map} +1 -1
  8. package/dist/chunk-AHLNXCP2.js +74 -0
  9. package/dist/chunk-AHLNXCP2.js.map +1 -0
  10. package/dist/chunk-C74WWM23.js +38 -0
  11. package/dist/chunk-C74WWM23.js.map +1 -0
  12. package/dist/chunk-FE26R5RN.js +63 -0
  13. package/dist/chunk-FE26R5RN.js.map +1 -0
  14. package/dist/chunk-HTXTVWVG.js +3 -0
  15. package/dist/chunk-HTXTVWVG.js.map +1 -0
  16. package/dist/chunk-I2RXO6ZU.js +74 -0
  17. package/dist/chunk-I2RXO6ZU.js.map +1 -0
  18. package/dist/chunk-IQKP2BWE.js +78 -0
  19. package/dist/chunk-IQKP2BWE.js.map +1 -0
  20. package/dist/chunk-J4OELYDR.js +125 -0
  21. package/dist/chunk-J4OELYDR.js.map +1 -0
  22. package/dist/{chunk-COPPAHR5.js → chunk-M4V7XHL7.js} +2 -2
  23. package/dist/chunk-M4V7XHL7.js.map +1 -0
  24. package/dist/chunk-PSAJSOXL.js +3 -0
  25. package/dist/chunk-PSAJSOXL.js.map +1 -0
  26. package/dist/chunk-RJSN4TVT.js +89 -0
  27. package/dist/chunk-RJSN4TVT.js.map +1 -0
  28. package/dist/chunk-RLFND34I.js +3 -0
  29. package/dist/chunk-RLFND34I.js.map +1 -0
  30. package/dist/chunk-UWHUCQC6.js +73 -0
  31. package/dist/chunk-UWHUCQC6.js.map +1 -0
  32. package/dist/chunk-VKV464ZF.js +3 -0
  33. package/dist/chunk-VKV464ZF.js.map +1 -0
  34. package/dist/chunk-W2HORE44.js +92 -0
  35. package/dist/chunk-W2HORE44.js.map +1 -0
  36. package/dist/{chunk-W5WDGME5.js → chunk-XHHEAJHN.js} +8 -5
  37. package/dist/chunk-XHHEAJHN.js.map +1 -0
  38. package/dist/combobox.d.ts +1 -0
  39. package/dist/combobox.js +1 -1
  40. package/dist/connection-test-row.d.ts +23 -0
  41. package/dist/connection-test-row.js +3 -0
  42. package/dist/connection-test-row.js.map +1 -0
  43. package/dist/file-card.d.ts +25 -0
  44. package/dist/file-card.js +3 -0
  45. package/dist/file-card.js.map +1 -0
  46. package/dist/file-queue.d.ts +32 -0
  47. package/dist/file-queue.js +3 -0
  48. package/dist/file-queue.js.map +1 -0
  49. package/dist/form-modal.js +1 -1
  50. package/dist/index.d.ts +31 -2
  51. package/dist/index.js +151 -12
  52. package/dist/index.js.map +1 -1
  53. package/dist/input.d.ts +2 -2
  54. package/dist/input.js +1 -1
  55. package/dist/model-picker.d.ts +38 -0
  56. package/dist/model-picker.js +3 -0
  57. package/dist/model-picker.js.map +1 -0
  58. package/dist/provider-form.d.ts +31 -0
  59. package/dist/provider-form.js +3 -0
  60. package/dist/provider-form.js.map +1 -0
  61. package/dist/settings-shell.d.ts +24 -0
  62. package/dist/settings-shell.js +3 -0
  63. package/dist/settings-shell.js.map +1 -0
  64. package/dist/styles.css +1 -1
  65. package/dist/task-assignment-picker.d.ts +27 -0
  66. package/dist/task-assignment-picker.js +3 -0
  67. package/dist/task-assignment-picker.js.map +1 -0
  68. package/dist/textarea.d.ts +10 -0
  69. package/dist/textarea.js +3 -0
  70. package/dist/textarea.js.map +1 -0
  71. package/package.json +38 -2
  72. package/dist/chunk-COPPAHR5.js.map +0 -1
  73. package/dist/chunk-W5WDGME5.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
  # @neuronection/assistant-ui
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`8022462`](https://github.com/neuronection/assistant-ui/commit/80224625682e6f59b1d40e2622f4935a50494063) Thanks [@constLiakos](https://github.com/constLiakos)! - Phase-4 file-attachment surface (presentational; upload controllers stay
8
+ app-side): `UploadDropzone` (block/row variants, drag events + file-picker
9
+ results out via `onFiles`, optional folder picker, uploading state),
10
+ `FileCard` (name/size/status/thumbnail, remove, include-in-processing
11
+ toggle) and `FileQueue` (aggregate summary, drag-to-reorder intent via
12
+ `onReorder(fromId, toId)`).
13
+
14
+ - [`58445ab`](https://github.com/neuronection/assistant-ui/commit/58445ab109ec5c9dce8073b04b9f780f11d8ad50) Thanks [@constLiakos](https://github.com/constLiakos)! - Phase-4 settings-trio blocks (part 2): `ModelPicker` (grouped, searchable
15
+ provider → model combobox with capability chips) and
16
+ `TaskAssignmentPicker` (task → model mapping rows with inline pickers and
17
+ clear buttons). `ComboboxOption` gains an optional `badge` chip.
18
+
19
+ ### Patch Changes
20
+
21
+ - [`6202ef0`](https://github.com/neuronection/assistant-ui/commit/6202ef0957e2edaaecdd9dce8aa8d25ca5d65344) Thanks [@constLiakos](https://github.com/constLiakos)! - Fix the package-root re-exports for `SettingsShell`, `ProviderForm` and
22
+ `ConnectionTestRow` (missing from `index.d.ts` in 0.6.0 — the per-module
23
+ entry points `/settings-shell`, `/provider-form`, `/connection-test-row`
24
+ were unaffected).
25
+
26
+ ## 0.6.0
27
+
28
+ ### Minor Changes
29
+
30
+ - [`fc350c6`](https://github.com/neuronection/assistant-ui/commit/fc350c6a684eb85dd5ef18a73af5c0d1a368b315) Thanks [@constLiakos](https://github.com/constLiakos)! - New `AiMagicFill` (describe-in-words prompt modal over `FormModal`, with
31
+ busy/error states — the app applies the extracted data) and a `Textarea`
32
+ primitive with the same label/hint/error wiring as `Input`.
33
+
34
+ - [`048e70a`](https://github.com/neuronection/assistant-ui/commit/048e70abfcaa349b8e61193ac85961ca834ca8b1) Thanks [@constLiakos](https://github.com/constLiakos)! - Phase-4 settings-trio blocks (part 1): `SettingsShell` (controlled two-pane
35
+ nav — router/store stay app-side), `ProviderForm` (name/base URL plus a
36
+ **write-only** masked API-key field; keyring stays app-side, ADR-006) and
37
+ `ConnectionTestRow` (idle/testing/ok/fail + latency presentation; the ping is
38
+ app-side). `Input`'s `label`/`hint` now accept ReactNode.
39
+
3
40
  ## 0.5.0
4
41
 
5
42
  ### Minor Changes
package/README.md CHANGED
@@ -88,8 +88,12 @@ files in the package's `dist/`. Visual reference:
88
88
  | `check-indicator` / `selection-bar` / `view-toggle` | `CheckIndicator` (tri-state) · `SelectionBar` (bulk-select bar) · `ViewToggle` (grid/list) |
89
89
  | `error-banner` / `undo-notice` / `empty-state` / `spinner` | presentational feedback: alert banner with `action` slot · undo toast · `EmptyState` · `Spinner` |
90
90
  | `info-button` / `field-label` | `InfoButton` (info popover) · `FieldLabel` (label + info affordance) |
91
+ | `model-picker` / `task-assignment-picker` | `ModelPicker` (grouped provider→model combobox, capability chips) · `TaskAssignmentPicker` (task → model mapping rows) |
92
+ | `settings-shell` / `provider-form` / `connection-test-row` | `SettingsShell` (controlled two-pane nav) · `ProviderForm` (write-only key field) · `ConnectionTestRow` (idle/testing/ok/fail) |
91
93
  | `copy-button` / `breadcrumbs` | `CopyButton` (clipboard + copied state) · `Breadcrumbs` (SPA links via `linkComponent`) |
94
+ | `ai-magic-fill` | `AiMagicFill` (describe-in-words → structured data prompt modal; app applies the data) |
92
95
  | `ai-button` / `ai-actions-dropdown` | `AiButton` (suggestions + prompt + response slot) · `AiActionsDropdown` (action list + custom prompt) |
96
+ | `upload-dropzone` / `file-card` / `file-queue` | file attachment surface: dropzone (block/row) · card (status, include toggle) · queue (summary + reorder) |
93
97
  | `marquee` | `useMarquee`, `MarqueeSurface`, `MarqueeBand` (rubber-band selection) |
94
98
  | `portal` / `theme-scope` / `tokens` | `Portal` · `ThemeScope` · token name lists + types |
95
99
 
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+
3
+ interface AiMagicFillProps {
4
+ open: boolean;
5
+ onOpenChange: (open: boolean) => void;
6
+ onSubmit: (prompt: string) => void;
7
+ busy?: boolean;
8
+ error?: string | null;
9
+ title?: string;
10
+ subtitle?: string;
11
+ description?: string;
12
+ promptLabel?: string;
13
+ placeholder?: string;
14
+ submitLabel?: string;
15
+ cancelLabel?: string;
16
+ className?: string;
17
+ }
18
+ declare function AiMagicFill({ open, onOpenChange, onSubmit, busy, error, title, subtitle, description, promptLabel, placeholder, submitLabel, cancelLabel, className, }: AiMagicFillProps): React.JSX.Element;
19
+
20
+ export { AiMagicFill, type AiMagicFillProps };
@@ -0,0 +1,3 @@
1
+ export { AiMagicFill } from './chunk-I2RXO6ZU.js';
2
+ //# sourceMappingURL=ai-magic-fill.js.map
3
+ //# sourceMappingURL=ai-magic-fill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"ai-magic-fill.js"}
@@ -76,5 +76,5 @@ function FormModal({
76
76
  }
77
77
 
78
78
  export { FormModal };
79
- //# sourceMappingURL=chunk-BUPMDOVL.js.map
80
- //# sourceMappingURL=chunk-BUPMDOVL.js.map
79
+ //# sourceMappingURL=chunk-2EPZAT3X.js.map
80
+ //# sourceMappingURL=chunk-2EPZAT3X.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/form-modal/FormModal.tsx"],"names":[],"mappings":"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","file":"chunk-BUPMDOVL.js","sourcesContent":["import * as React from 'react'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Button } from '../button/Button'\nimport {\n Modal,\n ModalContent,\n ModalDescription,\n ModalFooter,\n ModalHeader,\n ModalTitle,\n} from '../modal/Modal'\n\nexport interface FormModalProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n title: React.ReactNode\n description?: React.ReactNode\n icon?: LucideIcon\n headerActions?: React.ReactNode\n children: React.ReactNode\n onSubmit?: () => void\n submitting?: boolean\n submitDisabled?: boolean\n submitLabel?: string\n cancelLabel?: string\n closeLabel?: string\n size?: 'sm' | 'md' | 'lg' | 'xl'\n contentClassName?: string\n bodyClassName?: string\n footer?: React.ReactNode\n hideFooter?: boolean\n onReject?: () => void\n rejectLabel?: string\n}\n\nexport function FormModal({\n open,\n onOpenChange,\n title,\n description,\n icon: Icon,\n headerActions,\n children,\n onSubmit,\n submitting = false,\n submitDisabled = false,\n submitLabel = 'Save',\n cancelLabel = 'Cancel',\n closeLabel = 'Close',\n size = 'md',\n contentClassName,\n bodyClassName,\n footer,\n hideFooter = false,\n onReject,\n rejectLabel = 'Reject',\n}: FormModalProps) {\n return (\n <Modal open={open} onOpenChange={onOpenChange}>\n <ModalContent size={size} closeLabel={closeLabel} aria-describedby={undefined}>\n <form\n data-as=\"form-modal\"\n className={cn('contents', contentClassName)}\n onSubmit={(event) => {\n event.preventDefault()\n if (!submitting && !submitDisabled) {\n onSubmit?.()\n }\n }}\n >\n <ModalHeader>\n <div className=\"flex items-center gap-3\">\n {Icon ? (\n <span className=\"rounded-[var(--as-radius)] bg-[var(--as-secondary)] p-2 text-[var(--as-fg)]\">\n <Icon aria-hidden=\"true\" className=\"size-5\" />\n </span>\n ) : null}\n <ModalTitle>{title}</ModalTitle>\n {headerActions ? (\n <span className=\"ml-auto flex items-center gap-1.5\">{headerActions}</span>\n ) : null}\n </div>\n {description ? <ModalDescription>{description}</ModalDescription> : null}\n </ModalHeader>\n <div className={cn('px-6 pb-2', bodyClassName)}>{children}</div>\n {footer ?? (hideFooter ? null : (\n <ModalFooter>\n {onReject ? (\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={onReject}\n disabled={submitting}\n className=\"sm:mr-auto\"\n >\n {rejectLabel}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={submitting}\n >\n {cancelLabel}\n </Button>\n {onSubmit ? (\n <Button type=\"submit\" disabled={submitDisabled || submitting} loading={submitting}>\n {submitLabel}\n </Button>\n ) : null}\n </ModalFooter>\n ))}\n </form>\n </ModalContent>\n </Modal>\n )\n}\n"]}
1
+ {"version":3,"sources":["../src/components/form-modal/FormModal.tsx"],"names":[],"mappings":"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","file":"chunk-2EPZAT3X.js","sourcesContent":["import * as React from 'react'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Button } from '../button/Button'\nimport {\n Modal,\n ModalContent,\n ModalDescription,\n ModalFooter,\n ModalHeader,\n ModalTitle,\n} from '../modal/Modal'\n\nexport interface FormModalProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n title: React.ReactNode\n description?: React.ReactNode\n icon?: LucideIcon\n headerActions?: React.ReactNode\n children: React.ReactNode\n onSubmit?: () => void\n submitting?: boolean\n submitDisabled?: boolean\n submitLabel?: string\n cancelLabel?: string\n closeLabel?: string\n size?: 'sm' | 'md' | 'lg' | 'xl'\n contentClassName?: string\n bodyClassName?: string\n footer?: React.ReactNode\n hideFooter?: boolean\n onReject?: () => void\n rejectLabel?: string\n}\n\nexport function FormModal({\n open,\n onOpenChange,\n title,\n description,\n icon: Icon,\n headerActions,\n children,\n onSubmit,\n submitting = false,\n submitDisabled = false,\n submitLabel = 'Save',\n cancelLabel = 'Cancel',\n closeLabel = 'Close',\n size = 'md',\n contentClassName,\n bodyClassName,\n footer,\n hideFooter = false,\n onReject,\n rejectLabel = 'Reject',\n}: FormModalProps) {\n return (\n <Modal open={open} onOpenChange={onOpenChange}>\n <ModalContent size={size} closeLabel={closeLabel} aria-describedby={undefined}>\n <form\n data-as=\"form-modal\"\n className={cn('contents', contentClassName)}\n onSubmit={(event) => {\n event.preventDefault()\n if (!submitting && !submitDisabled) {\n onSubmit?.()\n }\n }}\n >\n <ModalHeader>\n <div className=\"flex items-center gap-3\">\n {Icon ? (\n <span className=\"rounded-[var(--as-radius)] bg-[var(--as-secondary)] p-2 text-[var(--as-fg)]\">\n <Icon aria-hidden=\"true\" className=\"size-5\" />\n </span>\n ) : null}\n <ModalTitle>{title}</ModalTitle>\n {headerActions ? (\n <span className=\"ml-auto flex items-center gap-1.5\">{headerActions}</span>\n ) : null}\n </div>\n {description ? <ModalDescription>{description}</ModalDescription> : null}\n </ModalHeader>\n <div className={cn('px-6 pb-2', bodyClassName)}>{children}</div>\n {footer ?? (hideFooter ? null : (\n <ModalFooter>\n {onReject ? (\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={onReject}\n disabled={submitting}\n className=\"sm:mr-auto\"\n >\n {rejectLabel}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={submitting}\n >\n {cancelLabel}\n </Button>\n {onSubmit ? (\n <Button type=\"submit\" disabled={submitDisabled || submitting} loading={submitting}>\n {submitLabel}\n </Button>\n ) : null}\n </ModalFooter>\n ))}\n </form>\n </ModalContent>\n </Modal>\n )\n}\n"]}
@@ -0,0 +1,74 @@
1
+ import { cn } from './chunk-BLJWR4ZV.js';
2
+ import * as React from 'react';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+
5
+ var SettingsShell = React.forwardRef(
6
+ function SettingsShell2({ nav, active, onNavigate, header, children, className, navClassName }, ref) {
7
+ const HeaderIcon = header?.icon;
8
+ return /* @__PURE__ */ jsxs(
9
+ "div",
10
+ {
11
+ ref,
12
+ "data-as": "settings-shell",
13
+ className: cn("grid grid-cols-1 gap-8 lg:grid-cols-4", className),
14
+ children: [
15
+ /* @__PURE__ */ jsx("nav", { className: "lg:col-span-1", "aria-label": "Settings sections", children: /* @__PURE__ */ jsxs(
16
+ "div",
17
+ {
18
+ className: cn(
19
+ "space-y-1 rounded-[var(--as-radius-lg)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] p-3 lg:sticky lg:top-24",
20
+ navClassName
21
+ ),
22
+ children: [
23
+ header ? /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2.5 border-b border-[var(--as-border)] px-3 py-2", children: [
24
+ HeaderIcon ? /* @__PURE__ */ jsx(
25
+ HeaderIcon,
26
+ {
27
+ className: "size-5 shrink-0 text-[var(--as-primary)]",
28
+ "aria-hidden": true
29
+ }
30
+ ) : null,
31
+ /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-bold text-[var(--as-fg)]", children: header.title })
32
+ ] }) : null,
33
+ nav.map(({ id, label, description, icon: Icon }) => {
34
+ const isActive = id === active;
35
+ return /* @__PURE__ */ jsxs(
36
+ "button",
37
+ {
38
+ type: "button",
39
+ "aria-current": isActive ? "page" : void 0,
40
+ onClick: () => onNavigate(id),
41
+ className: cn(
42
+ "flex w-full cursor-pointer items-start rounded-[var(--as-radius)] px-3 py-2.5 text-left text-sm transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
43
+ isActive ? "bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] font-bold text-[var(--as-primary)]" : "font-medium text-[var(--as-fg)] hover:bg-[var(--as-muted)]"
44
+ ),
45
+ children: [
46
+ Icon ? /* @__PURE__ */ jsx(
47
+ Icon,
48
+ {
49
+ className: "mr-3 mt-0.5 size-4 shrink-0",
50
+ "aria-hidden": true
51
+ }
52
+ ) : null,
53
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col", children: [
54
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: label }),
55
+ description ? /* @__PURE__ */ jsx("span", { className: "text-[11px] font-normal text-[var(--as-muted-fg)]", children: description }) : null
56
+ ] })
57
+ ]
58
+ },
59
+ id
60
+ );
61
+ })
62
+ ]
63
+ }
64
+ ) }),
65
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 lg:col-span-3", children })
66
+ ]
67
+ }
68
+ );
69
+ }
70
+ );
71
+
72
+ export { SettingsShell };
73
+ //# sourceMappingURL=chunk-AHLNXCP2.js.map
74
+ //# sourceMappingURL=chunk-AHLNXCP2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/settings-shell/SettingsShell.tsx"],"names":["SettingsShell"],"mappings":";;;;AAqBO,IAAM,aAAA,GAAsB,KAAA,CAAA,UAAA;AAAA,EACjC,SAASA,cAAAA,CACP,EAAE,GAAA,EAAK,MAAA,EAAQ,UAAA,EAAY,MAAA,EAAQ,QAAA,EAAU,SAAA,EAAW,YAAA,EAAa,EACrE,GAAA,EACA;AACA,IAAA,MAAM,aAAa,MAAA,EAAQ,IAAA;AAC3B,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAQ,gBAAA;AAAA,QACR,SAAA,EAAW,EAAA,CAAG,uCAAA,EAAyC,SAAS,CAAA;AAAA,QAEhE,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,eAAA,EAAgB,YAAA,EAAW,mBAAA,EACxC,QAAA,kBAAA,IAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,EAAA;AAAA,gBACT,gIAAA;AAAA,gBACA;AAAA,eACF;AAAA,cAEC,QAAA,EAAA;AAAA,gBAAA,MAAA,mBACC,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6EAAA,EACZ,QAAA,EAAA;AAAA,kBAAA,UAAA,mBACC,GAAA;AAAA,oBAAC,UAAA;AAAA,oBAAA;AAAA,sBACC,SAAA,EAAU,0CAAA;AAAA,sBACV,aAAA,EAAW;AAAA;AAAA,mBACb,GACE,IAAA;AAAA,kCACJ,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gDAAA,EACb,iBAAO,KAAA,EACV;AAAA,iBAAA,EACF,CAAA,GACE,IAAA;AAAA,gBACH,GAAA,CAAI,IAAI,CAAC,EAAE,IAAI,KAAA,EAAO,WAAA,EAAa,IAAA,EAAM,IAAA,EAAK,KAAM;AACnD,kBAAA,MAAM,WAAW,EAAA,KAAO,MAAA;AACxB,kBAAA,uBACE,IAAA;AAAA,oBAAC,QAAA;AAAA,oBAAA;AAAA,sBAEC,IAAA,EAAK,QAAA;AAAA,sBACL,cAAA,EAAc,WAAW,MAAA,GAAS,MAAA;AAAA,sBAClC,OAAA,EAAS,MAAM,UAAA,CAAW,EAAE,CAAA;AAAA,sBAC5B,SAAA,EAAW,EAAA;AAAA,wBACT,uNAAA;AAAA,wBACA,WACI,8FAAA,GACA;AAAA,uBACN;AAAA,sBAEC,QAAA,EAAA;AAAA,wBAAA,IAAA,mBACC,GAAA;AAAA,0BAAC,IAAA;AAAA,0BAAA;AAAA,4BACC,SAAA,EAAU,6BAAA;AAAA,4BACV,aAAA,EAAW;AAAA;AAAA,yBACb,GACE,IAAA;AAAA,wCACJ,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uBAAA,EACd,QAAA,EAAA;AAAA,0CAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,UAAA,EAAY,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,0BACjC,8BACC,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,mDAAA,EACb,uBACH,CAAA,GACE;AAAA,yBAAA,EACN;AAAA;AAAA,qBAAA;AAAA,oBAxBK;AAAA,mBAyBP;AAAA,gBAEJ,CAAC;AAAA;AAAA;AAAA,WACH,EACF,CAAA;AAAA,0BACA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uBAAA,EAAyB,QAAA,EAAS;AAAA;AAAA;AAAA,KACnD;AAAA,EAEJ;AACF","file":"chunk-AHLNXCP2.js","sourcesContent":["import * as React from 'react'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '../../lib/utils'\n\nexport interface SettingsNavItem {\n id: string\n label: string\n description?: string\n icon?: LucideIcon\n}\n\nexport interface SettingsShellProps {\n nav: SettingsNavItem[]\n active: string\n onNavigate: (id: string) => void\n header?: { icon?: LucideIcon; title: string }\n children: React.ReactNode\n className?: string\n navClassName?: string\n}\n\nexport const SettingsShell = React.forwardRef<HTMLDivElement, SettingsShellProps>(\n function SettingsShell(\n { nav, active, onNavigate, header, children, className, navClassName },\n ref,\n ) {\n const HeaderIcon = header?.icon\n return (\n <div\n ref={ref}\n data-as=\"settings-shell\"\n className={cn('grid grid-cols-1 gap-8 lg:grid-cols-4', className)}\n >\n <nav className=\"lg:col-span-1\" aria-label=\"Settings sections\">\n <div\n className={cn(\n 'space-y-1 rounded-[var(--as-radius-lg)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] p-3 lg:sticky lg:top-24',\n navClassName,\n )}\n >\n {header ? (\n <div className=\"mb-2 flex items-center gap-2.5 border-b border-[var(--as-border)] px-3 py-2\">\n {HeaderIcon ? (\n <HeaderIcon\n className=\"size-5 shrink-0 text-[var(--as-primary)]\"\n aria-hidden\n />\n ) : null}\n <span className=\"truncate text-sm font-bold text-[var(--as-fg)]\">\n {header.title}\n </span>\n </div>\n ) : null}\n {nav.map(({ id, label, description, icon: Icon }) => {\n const isActive = id === active\n return (\n <button\n key={id}\n type=\"button\"\n aria-current={isActive ? 'page' : undefined}\n onClick={() => onNavigate(id)}\n className={cn(\n 'flex w-full cursor-pointer items-start rounded-[var(--as-radius)] px-3 py-2.5 text-left text-sm transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]',\n isActive\n ? 'bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] font-bold text-[var(--as-primary)]'\n : 'font-medium text-[var(--as-fg)] hover:bg-[var(--as-muted)]',\n )}\n >\n {Icon ? (\n <Icon\n className=\"mr-3 mt-0.5 size-4 shrink-0\"\n aria-hidden\n />\n ) : null}\n <span className=\"flex min-w-0 flex-col\">\n <span className=\"truncate\">{label}</span>\n {description ? (\n <span className=\"text-[11px] font-normal text-[var(--as-muted-fg)]\">\n {description}\n </span>\n ) : null}\n </span>\n </button>\n )\n })}\n </div>\n </nav>\n <div className=\"min-w-0 lg:col-span-3\">{children}</div>\n </div>\n )\n },\n)\n"]}
@@ -0,0 +1,38 @@
1
+ import { cn } from './chunk-BLJWR4ZV.js';
2
+ import * as React from 'react';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ var Textarea = React.forwardRef(
6
+ function Textarea2({ className, label, hint, error, id: idProp, ...props }, ref) {
7
+ const autoId = React.useId();
8
+ const id = idProp ?? (label || hint || error ? autoId : void 0);
9
+ const describedBy = error ? `${id}-error` : hint ? `${id}-hint` : void 0;
10
+ const textarea = /* @__PURE__ */ jsx(
11
+ "textarea",
12
+ {
13
+ ref,
14
+ id,
15
+ "data-as": "textarea",
16
+ "aria-invalid": error ? true : void 0,
17
+ "aria-describedby": describedBy,
18
+ className: cn(
19
+ "flex min-h-16 w-full rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] px-3 py-2 text-sm text-[var(--as-fg)] transition-colors placeholder:text-[var(--as-muted-fg)] focus-visible:border-[var(--as-focus-ring)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50",
20
+ error && "border-[var(--as-danger)] focus-visible:border-[var(--as-danger)] focus-visible:ring-[var(--as-danger)]",
21
+ className
22
+ ),
23
+ ...props
24
+ }
25
+ );
26
+ if (!label && !hint && !error) return textarea;
27
+ return /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col gap-1.5", children: [
28
+ label ? /* @__PURE__ */ jsx("label", { htmlFor: id, className: "text-sm font-medium leading-none text-[var(--as-fg)]", children: label }) : null,
29
+ textarea,
30
+ hint && !error ? /* @__PURE__ */ jsx("p", { id: `${id}-hint`, className: "text-xs text-[var(--as-muted-fg)]", children: hint }) : null,
31
+ error ? /* @__PURE__ */ jsx("p", { id: `${id}-error`, role: "alert", className: "text-xs font-medium text-[var(--as-danger)]", children: error }) : null
32
+ ] });
33
+ }
34
+ );
35
+
36
+ export { Textarea };
37
+ //# sourceMappingURL=chunk-C74WWM23.js.map
38
+ //# sourceMappingURL=chunk-C74WWM23.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/textarea/Textarea.tsx"],"names":["Textarea"],"mappings":";;;;AASO,IAAM,QAAA,GAAiB,KAAA,CAAA,UAAA;AAAA,EAC5B,SAASA,SAAAA,CAAS,EAAE,SAAA,EAAW,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,GAAG,KAAA,EAAM,EAAG,GAAA,EAAK;AAC9E,IAAA,MAAM,SAAe,KAAA,CAAA,KAAA,EAAM;AAC3B,IAAA,MAAM,EAAA,GAAK,MAAA,KAAW,KAAA,IAAS,IAAA,IAAQ,QAAQ,MAAA,GAAS,MAAA,CAAA;AACxD,IAAA,MAAM,WAAA,GAAc,QAAQ,CAAA,EAAG,EAAE,WAAW,IAAA,GAAO,CAAA,EAAG,EAAE,CAAA,KAAA,CAAA,GAAU,MAAA;AAElE,IAAA,MAAM,QAAA,mBACJ,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,EAAA;AAAA,QACA,SAAA,EAAQ,UAAA;AAAA,QACR,cAAA,EAAc,QAAQ,IAAA,GAAO,MAAA;AAAA,QAC7B,kBAAA,EAAkB,WAAA;AAAA,QAClB,SAAA,EAAW,EAAA;AAAA,UACT,6XAAA;AAAA,UACA,KAAA,IACE,yGAAA;AAAA,UACF;AAAA,SACF;AAAA,QACC,GAAG;AAAA;AAAA,KACN;AAGF,IAAA,IAAI,CAAC,KAAA,IAAS,CAAC,IAAA,IAAQ,CAAC,OAAO,OAAO,QAAA;AAEtC,IAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8BAAA,EACZ,QAAA,EAAA;AAAA,MAAA,KAAA,uBACE,OAAA,EAAA,EAAM,OAAA,EAAS,IAAI,SAAA,EAAU,sDAAA,EAC3B,iBACH,CAAA,GACE,IAAA;AAAA,MACH,QAAA;AAAA,MACA,IAAA,IAAQ,CAAC,KAAA,mBACR,GAAA,CAAC,GAAA,EAAA,EAAE,EAAA,EAAI,CAAA,EAAG,EAAE,CAAA,KAAA,CAAA,EAAS,SAAA,EAAU,mCAAA,EAC5B,QAAA,EAAA,IAAA,EACH,CAAA,GACE,IAAA;AAAA,MACH,KAAA,mBACC,GAAA,CAAC,GAAA,EAAA,EAAE,EAAA,EAAI,CAAA,EAAG,EAAE,CAAA,MAAA,CAAA,EAAU,IAAA,EAAK,OAAA,EAAQ,SAAA,EAAU,6CAAA,EAC1C,QAAA,EAAA,KAAA,EACH,CAAA,GACE;AAAA,KAAA,EACN,CAAA;AAAA,EAEJ;AACF","file":"chunk-C74WWM23.js","sourcesContent":["import * as React from 'react'\nimport { cn } from '../../lib/utils'\n\nexport interface TextareaProps extends React.ComponentProps<'textarea'> {\n label?: string\n hint?: string\n error?: string\n}\n\nexport const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n function Textarea({ className, label, hint, error, id: idProp, ...props }, ref) {\n const autoId = React.useId()\n const id = idProp ?? (label || hint || error ? autoId : undefined)\n const describedBy = error ? `${id}-error` : hint ? `${id}-hint` : undefined\n\n const textarea = (\n <textarea\n ref={ref}\n id={id}\n data-as=\"textarea\"\n aria-invalid={error ? true : undefined}\n aria-describedby={describedBy}\n className={cn(\n 'flex min-h-16 w-full rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] px-3 py-2 text-sm text-[var(--as-fg)] transition-colors placeholder:text-[var(--as-muted-fg)] focus-visible:border-[var(--as-focus-ring)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50',\n error &&\n 'border-[var(--as-danger)] focus-visible:border-[var(--as-danger)] focus-visible:ring-[var(--as-danger)]',\n className,\n )}\n {...props}\n />\n )\n\n if (!label && !hint && !error) return textarea\n\n return (\n <div className=\"flex w-full flex-col gap-1.5\">\n {label ? (\n <label htmlFor={id} className=\"text-sm font-medium leading-none text-[var(--as-fg)]\">\n {label}\n </label>\n ) : null}\n {textarea}\n {hint && !error ? (\n <p id={`${id}-hint`} className=\"text-xs text-[var(--as-muted-fg)]\">\n {hint}\n </p>\n ) : null}\n {error ? (\n <p id={`${id}-error`} role=\"alert\" className=\"text-xs font-medium text-[var(--as-danger)]\">\n {error}\n </p>\n ) : null}\n </div>\n )\n },\n)\n"]}
@@ -0,0 +1,63 @@
1
+ import { Combobox } from './chunk-XHHEAJHN.js';
2
+ import { cn } from './chunk-BLJWR4ZV.js';
3
+ import * as React from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ var ModelPicker = React.forwardRef(
7
+ function ModelPicker2({
8
+ providers,
9
+ value,
10
+ onChange,
11
+ placeholder = "Select a model\u2026",
12
+ searchPlaceholder = "Search models\u2026",
13
+ searchLabel,
14
+ emptyLabel,
15
+ loading = false,
16
+ disabled = false,
17
+ clearable = false,
18
+ clearLabel,
19
+ label,
20
+ error,
21
+ id,
22
+ className,
23
+ panelClassName
24
+ }, ref) {
25
+ const options = React.useMemo(
26
+ () => providers.flatMap(
27
+ (provider) => provider.models.map((model) => ({
28
+ value: model.id,
29
+ label: model.name,
30
+ group: provider.name,
31
+ badge: model.capability
32
+ }))
33
+ ),
34
+ [providers]
35
+ );
36
+ return /* @__PURE__ */ jsx(
37
+ Combobox,
38
+ {
39
+ ref,
40
+ options,
41
+ value,
42
+ onChange,
43
+ placeholder,
44
+ searchPlaceholder,
45
+ searchLabel,
46
+ emptyLabel,
47
+ loading,
48
+ disabled,
49
+ clearable,
50
+ clearLabel,
51
+ label,
52
+ error,
53
+ id,
54
+ className: cn("w-full", className),
55
+ panelClassName
56
+ }
57
+ );
58
+ }
59
+ );
60
+
61
+ export { ModelPicker };
62
+ //# sourceMappingURL=chunk-FE26R5RN.js.map
63
+ //# sourceMappingURL=chunk-FE26R5RN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/model-picker/ModelPicker.tsx"],"names":["ModelPicker"],"mappings":";;;;;AA2CO,IAAM,WAAA,GAAoB,KAAA,CAAA,UAAA;AAAA,EAC/B,SAASA,YAAAA,CACP;AAAA,IACE,SAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA,GAAc,sBAAA;AAAA,IACd,iBAAA,GAAoB,qBAAA;AAAA,IACpB,WAAA;AAAA,IACA,UAAA;AAAA,IACA,OAAA,GAAU,KAAA;AAAA,IACV,QAAA,GAAW,KAAA;AAAA,IACX,SAAA,GAAY,KAAA;AAAA,IACZ,UAAA;AAAA,IACA,KAAA;AAAA,IACA,KAAA;AAAA,IACA,EAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,KAEF,GAAA,EACA;AACA,IAAA,MAAM,OAAA,GAAkC,KAAA,CAAA,OAAA;AAAA,MACtC,MACE,SAAA,CAAU,OAAA;AAAA,QAAQ,CAAC,QAAA,KACjB,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,UAC9B,OAAO,KAAA,CAAM,EAAA;AAAA,UACb,OAAO,KAAA,CAAM,IAAA;AAAA,UACb,OAAO,QAAA,CAAS,IAAA;AAAA,UAChB,OAAO,KAAA,CAAM;AAAA,SACf,CAAE;AAAA,OACJ;AAAA,MACF,CAAC,SAAS;AAAA,KACZ;AAEA,IAAA,uBACE,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,OAAA;AAAA,QACA,KAAA;AAAA,QACA,QAAA;AAAA,QACA,WAAA;AAAA,QACA,iBAAA;AAAA,QACA,WAAA;AAAA,QACA,UAAA;AAAA,QACA,OAAA;AAAA,QACA,QAAA;AAAA,QACA,SAAA;AAAA,QACA,UAAA;AAAA,QACA,KAAA;AAAA,QACA,KAAA;AAAA,QACA,EAAA;AAAA,QACA,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,SAAS,CAAA;AAAA,QACjC;AAAA;AAAA,KACF;AAAA,EAEJ;AACF","file":"chunk-FE26R5RN.js","sourcesContent":["import * as React from 'react'\nimport { cn } from '../../lib/utils'\nimport {\n Combobox,\n type ComboboxOption,\n} from '../combobox'\n\nexport interface ModelPickerModel {\n id: string\n name: string\n /** Short capability chip, e.g. `vision` or `tools`. */\n capability?: string\n}\n\nexport interface ModelPickerProvider {\n id: string\n name: string\n models: ModelPickerModel[]\n}\n\nexport interface ModelPickerProps {\n providers: ModelPickerProvider[]\n value?: string\n onChange: (modelId: string) => void\n placeholder?: string\n searchPlaceholder?: string\n searchLabel?: string\n emptyLabel?: string\n loading?: boolean\n disabled?: boolean\n clearable?: boolean\n clearLabel?: string\n label?: string\n error?: string\n id?: string\n className?: string\n panelClassName?: string\n}\n\n/**\n * Grouped, searchable provider → model picker. Presentational: the model\n * list comes in via props, selection goes out via `onChange`.\n */\nexport const ModelPicker = React.forwardRef<HTMLButtonElement, ModelPickerProps>(\n function ModelPicker(\n {\n providers,\n value,\n onChange,\n placeholder = 'Select a model…',\n searchPlaceholder = 'Search models…',\n searchLabel,\n emptyLabel,\n loading = false,\n disabled = false,\n clearable = false,\n clearLabel,\n label,\n error,\n id,\n className,\n panelClassName,\n },\n ref,\n ) {\n const options: ComboboxOption[] = React.useMemo(\n () =>\n providers.flatMap((provider) =>\n provider.models.map((model) => ({\n value: model.id,\n label: model.name,\n group: provider.name,\n badge: model.capability,\n })),\n ),\n [providers],\n )\n\n return (\n <Combobox\n ref={ref}\n options={options}\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n searchPlaceholder={searchPlaceholder}\n searchLabel={searchLabel}\n emptyLabel={emptyLabel}\n loading={loading}\n disabled={disabled}\n clearable={clearable}\n clearLabel={clearLabel}\n label={label}\n error={error}\n id={id}\n className={cn('w-full', className)}\n panelClassName={panelClassName}\n />\n )\n },\n)\n"]}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-HTXTVWVG.js.map
3
+ //# sourceMappingURL=chunk-HTXTVWVG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-HTXTVWVG.js"}
@@ -0,0 +1,74 @@
1
+ import { FormModal } from './chunk-2EPZAT3X.js';
2
+ import { Textarea } from './chunk-C74WWM23.js';
3
+ import * as React from 'react';
4
+ import { Sparkles } from 'lucide-react';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ function AiMagicFill({
8
+ open,
9
+ onOpenChange,
10
+ onSubmit,
11
+ busy = false,
12
+ error,
13
+ title = "Magic Fill",
14
+ subtitle = "AI-powered data extraction",
15
+ description,
16
+ promptLabel = "Describe details",
17
+ placeholder = "Describe the data here\u2026",
18
+ submitLabel,
19
+ cancelLabel = "Cancel",
20
+ className
21
+ }) {
22
+ const [prompt, setPrompt] = React.useState("");
23
+ const submit = () => {
24
+ const trimmed = prompt.trim();
25
+ if (!trimmed || busy) return;
26
+ onSubmit(trimmed);
27
+ setPrompt("");
28
+ };
29
+ return /* @__PURE__ */ jsx(
30
+ FormModal,
31
+ {
32
+ open,
33
+ onOpenChange,
34
+ title,
35
+ description: subtitle,
36
+ icon: Sparkles,
37
+ submitLabel: submitLabel ?? `Apply ${title}`,
38
+ cancelLabel,
39
+ submitting: busy,
40
+ submitDisabled: !prompt.trim(),
41
+ onSubmit: submit,
42
+ contentClassName: className,
43
+ children: /* @__PURE__ */ jsxs("div", { "data-as": "ai-magic-fill", className: "flex flex-col gap-4", children: [
44
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
45
+ /* @__PURE__ */ jsx(
46
+ "label",
47
+ {
48
+ htmlFor: "ai-magic-fill-prompt",
49
+ className: "text-[11px] font-bold uppercase tracking-[0.18em] text-[var(--as-muted-fg)]",
50
+ children: promptLabel
51
+ }
52
+ ),
53
+ /* @__PURE__ */ jsx(
54
+ Textarea,
55
+ {
56
+ id: "ai-magic-fill-prompt",
57
+ rows: 5,
58
+ value: prompt,
59
+ onChange: (event) => setPrompt(event.target.value),
60
+ placeholder,
61
+ className: "resize-none leading-relaxed"
62
+ }
63
+ )
64
+ ] }),
65
+ description ? /* @__PURE__ */ jsx("p", { className: "rounded-[var(--as-radius)] border border-[color-mix(in_srgb,var(--as-ai)_25%,transparent)] bg-[color-mix(in_srgb,var(--as-ai)_8%,transparent)] p-3 text-xs font-medium leading-relaxed text-[var(--as-fg)]", children: description }) : null,
66
+ error ? /* @__PURE__ */ jsx("p", { role: "alert", className: "text-xs font-semibold text-[var(--as-danger)]", children: error }) : null
67
+ ] })
68
+ }
69
+ );
70
+ }
71
+
72
+ export { AiMagicFill };
73
+ //# sourceMappingURL=chunk-I2RXO6ZU.js.map
74
+ //# sourceMappingURL=chunk-I2RXO6ZU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ai-magic-fill/AiMagicFill.tsx"],"names":[],"mappings":";;;;;;AAqBO,SAAS,WAAA,CAAY;AAAA,EAC1B,IAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,IAAA,GAAO,KAAA;AAAA,EACP,KAAA;AAAA,EACA,KAAA,GAAQ,YAAA;AAAA,EACR,QAAA,GAAW,4BAAA;AAAA,EACX,WAAA;AAAA,EACA,WAAA,GAAc,kBAAA;AAAA,EACd,WAAA,GAAc,8BAAA;AAAA,EACd,WAAA;AAAA,EACA,WAAA,GAAc,QAAA;AAAA,EACd;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAU,eAAS,EAAE,CAAA;AAE7C,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,MAAM,OAAA,GAAU,OAAO,IAAA,EAAK;AAC5B,IAAA,IAAI,CAAC,WAAW,IAAA,EAAM;AACtB,IAAA,QAAA,CAAS,OAAO,CAAA;AAChB,IAAA,SAAA,CAAU,EAAE,CAAA;AAAA,EACd,CAAA;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,YAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA,EAAa,QAAA;AAAA,MACb,IAAA,EAAM,QAAA;AAAA,MACN,WAAA,EAAa,WAAA,IAAe,CAAA,MAAA,EAAS,KAAK,CAAA,CAAA;AAAA,MAC1C,WAAA;AAAA,MACA,UAAA,EAAY,IAAA;AAAA,MACZ,cAAA,EAAgB,CAAC,MAAA,CAAO,IAAA,EAAK;AAAA,MAC7B,QAAA,EAAU,MAAA;AAAA,MACV,gBAAA,EAAkB,SAAA;AAAA,MAElB,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAQ,eAAA,EAAgB,WAAU,qBAAA,EACrC,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,uBAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,sBAAA;AAAA,cACR,SAAA,EAAU,6EAAA;AAAA,cAET,QAAA,EAAA;AAAA;AAAA,WACH;AAAA,0BACA,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,EAAA,EAAG,sBAAA;AAAA,cACH,IAAA,EAAM,CAAA;AAAA,cACN,KAAA,EAAO,MAAA;AAAA,cACP,UAAU,CAAC,KAAA,KACT,SAAA,CAAU,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,cAE9B,WAAA;AAAA,cACA,SAAA,EAAU;AAAA;AAAA;AACZ,SAAA,EACF,CAAA;AAAA,QACC,8BACC,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,4MAAA,EACV,uBACH,CAAA,GACE,IAAA;AAAA,QACH,KAAA,uBACE,GAAA,EAAA,EAAE,IAAA,EAAK,SAAQ,SAAA,EAAU,+CAAA,EACvB,iBACH,CAAA,GACE;AAAA,OAAA,EACN;AAAA;AAAA,GACF;AAEJ","file":"chunk-I2RXO6ZU.js","sourcesContent":["import * as React from 'react'\nimport { Sparkles } from 'lucide-react'\nimport { FormModal } from '../form-modal/FormModal'\nimport { Textarea } from '../textarea/Textarea'\n\nexport interface AiMagicFillProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n onSubmit: (prompt: string) => void\n busy?: boolean\n error?: string | null\n title?: string\n subtitle?: string\n description?: string\n promptLabel?: string\n placeholder?: string\n submitLabel?: string\n cancelLabel?: string\n className?: string\n}\n\nexport function AiMagicFill({\n open,\n onOpenChange,\n onSubmit,\n busy = false,\n error,\n title = 'Magic Fill',\n subtitle = 'AI-powered data extraction',\n description,\n promptLabel = 'Describe details',\n placeholder = 'Describe the data here…',\n submitLabel,\n cancelLabel = 'Cancel',\n className,\n}: AiMagicFillProps) {\n const [prompt, setPrompt] = React.useState('')\n\n const submit = () => {\n const trimmed = prompt.trim()\n if (!trimmed || busy) return\n onSubmit(trimmed)\n setPrompt('')\n }\n\n return (\n <FormModal\n open={open}\n onOpenChange={onOpenChange}\n title={title}\n description={subtitle}\n icon={Sparkles}\n submitLabel={submitLabel ?? `Apply ${title}`}\n cancelLabel={cancelLabel}\n submitting={busy}\n submitDisabled={!prompt.trim()}\n onSubmit={submit}\n contentClassName={className}\n >\n <div data-as=\"ai-magic-fill\" className=\"flex flex-col gap-4\">\n <div className=\"flex flex-col gap-1.5\">\n <label\n htmlFor=\"ai-magic-fill-prompt\"\n className=\"text-[11px] font-bold uppercase tracking-[0.18em] text-[var(--as-muted-fg)]\"\n >\n {promptLabel}\n </label>\n <Textarea\n id=\"ai-magic-fill-prompt\"\n rows={5}\n value={prompt}\n onChange={(event: React.ChangeEvent<HTMLTextAreaElement>) =>\n setPrompt(event.target.value)\n }\n placeholder={placeholder}\n className=\"resize-none leading-relaxed\"\n />\n </div>\n {description ? (\n <p className=\"rounded-[var(--as-radius)] border border-[color-mix(in_srgb,var(--as-ai)_25%,transparent)] bg-[color-mix(in_srgb,var(--as-ai)_8%,transparent)] p-3 text-xs font-medium leading-relaxed text-[var(--as-fg)]\">\n {description}\n </p>\n ) : null}\n {error ? (\n <p role=\"alert\" className=\"text-xs font-semibold text-[var(--as-danger)]\">\n {error}\n </p>\n ) : null}\n </div>\n </FormModal>\n )\n}\n"]}
@@ -0,0 +1,78 @@
1
+ import { formatBytes, FileCard } from './chunk-J4OELYDR.js';
2
+ import { cn } from './chunk-BLJWR4ZV.js';
3
+ import * as React from 'react';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+
6
+ var FileQueue = React.forwardRef(
7
+ function FileQueue2({
8
+ files,
9
+ onRemove,
10
+ onToggleInclude,
11
+ onOpen,
12
+ onReorder,
13
+ reorderable = Boolean(onReorder),
14
+ emptyText,
15
+ summary,
16
+ removeLabel = "Remove file",
17
+ includeLabel = "Include in processing",
18
+ className
19
+ }, ref) {
20
+ const dragId = React.useRef(null);
21
+ const [dropTarget, setDropTarget] = React.useState(null);
22
+ if (files.length === 0 && emptyText) {
23
+ return /* @__PURE__ */ jsx("p", { ref, className: cn("text-sm text-[var(--as-muted-fg)]", className), children: emptyText });
24
+ }
25
+ return /* @__PURE__ */ jsxs("div", { ref, "data-as": "file-queue", className: cn("flex w-full flex-col gap-2", className), children: [
26
+ files.length > 0 ? /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--as-muted-fg)]", children: summary ?? `${files.length} ${files.length === 1 ? "file" : "files"}${files.some((f) => f.sizeBytes != null) ? ` \xB7 ${formatBytes(files.reduce((total, f) => total + (f.sizeBytes ?? 0), 0))}` : ""}` }) : null,
27
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: files.map((file) => /* @__PURE__ */ jsx(
28
+ "div",
29
+ {
30
+ onDragOver: reorderable ? (event) => {
31
+ event.preventDefault();
32
+ if (dragId.current && dragId.current !== file.id) setDropTarget(file.id);
33
+ } : void 0,
34
+ onDrop: reorderable ? (event) => {
35
+ event.preventDefault();
36
+ if (dragId.current && dragId.current !== file.id) {
37
+ onReorder?.(dragId.current, file.id);
38
+ }
39
+ dragId.current = null;
40
+ setDropTarget(null);
41
+ } : void 0,
42
+ className: cn(
43
+ dropTarget === file.id && "ring-2 ring-[var(--as-focus-ring)] ring-offset-2"
44
+ ),
45
+ children: /* @__PURE__ */ jsx(
46
+ FileCard,
47
+ {
48
+ name: file.name,
49
+ sizeBytes: file.sizeBytes,
50
+ status: file.status,
51
+ error: file.error,
52
+ thumbnailUrl: file.thumbnailUrl,
53
+ included: file.included,
54
+ onToggleInclude: onToggleInclude ? () => onToggleInclude(file.id) : void 0,
55
+ onRemove: onRemove ? () => onRemove(file.id) : void 0,
56
+ onOpen: onOpen ? () => onOpen(file.id) : void 0,
57
+ draggable: reorderable,
58
+ onDragStart: () => {
59
+ dragId.current = file.id;
60
+ },
61
+ onDragEnd: () => {
62
+ dragId.current = null;
63
+ setDropTarget(null);
64
+ },
65
+ removeLabel,
66
+ includeLabel
67
+ }
68
+ )
69
+ },
70
+ file.id
71
+ )) })
72
+ ] });
73
+ }
74
+ );
75
+
76
+ export { FileQueue };
77
+ //# sourceMappingURL=chunk-IQKP2BWE.js.map
78
+ //# sourceMappingURL=chunk-IQKP2BWE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/file-queue/FileQueue.tsx"],"names":["FileQueue"],"mappings":"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","file":"chunk-IQKP2BWE.js","sourcesContent":["import * as React from 'react'\nimport { cn } from '../../lib/utils'\nimport {\n FileCard,\n formatBytes,\n type FileCardStatus,\n} from '../file-card/FileCard'\n\nexport interface FileQueueItem {\n id: string\n name: string\n sizeBytes?: number\n status?: FileCardStatus\n error?: string | null\n thumbnailUrl?: string | null\n included?: boolean\n}\n\nexport interface FileQueueProps {\n files: FileQueueItem[]\n onRemove?: (id: string) => void\n onToggleInclude?: (id: string) => void\n onOpen?: (id: string) => void\n onReorder?: (fromId: string, toId: string) => void\n reorderable?: boolean\n emptyText?: string\n summary?: React.ReactNode\n removeLabel?: string\n includeLabel?: string\n className?: string\n}\n\n/**\n * FileCard grid with aggregate summary and optional drag-to-reorder\n * (reports intent via `onReorder(fromId, toId)` — the app owns ordering).\n */\nexport const FileQueue = React.forwardRef<HTMLDivElement, FileQueueProps>(\n function FileQueue(\n {\n files,\n onRemove,\n onToggleInclude,\n onOpen,\n onReorder,\n reorderable = Boolean(onReorder),\n emptyText,\n summary,\n removeLabel = 'Remove file',\n includeLabel = 'Include in processing',\n className,\n },\n ref,\n ) {\n const dragId = React.useRef<string | null>(null)\n const [dropTarget, setDropTarget] = React.useState<string | null>(null)\n\n if (files.length === 0 && emptyText) {\n return (\n <p ref={ref} className={cn('text-sm text-[var(--as-muted-fg)]', className)}>\n {emptyText}\n </p>\n )\n }\n\n return (\n <div ref={ref} data-as=\"file-queue\" className={cn('flex w-full flex-col gap-2', className)}>\n {files.length > 0 ? (\n <p className=\"text-xs text-[var(--as-muted-fg)]\">\n {summary ??\n `${files.length} ${files.length === 1 ? 'file' : 'files'}${\n files.some((f) => f.sizeBytes != null)\n ? ` · ${formatBytes(files.reduce((total, f) => total + (f.sizeBytes ?? 0), 0))}`\n : ''\n }`}\n </p>\n ) : null}\n <div className=\"flex flex-wrap gap-2\">\n {files.map((file) => (\n <div\n key={file.id}\n onDragOver={reorderable ? (event) => {\n event.preventDefault()\n if (dragId.current && dragId.current !== file.id) setDropTarget(file.id)\n } : undefined}\n onDrop={reorderable ? (event) => {\n event.preventDefault()\n if (dragId.current && dragId.current !== file.id) {\n onReorder?.(dragId.current, file.id)\n }\n dragId.current = null\n setDropTarget(null)\n } : undefined}\n className={cn(\n dropTarget === file.id && 'ring-2 ring-[var(--as-focus-ring)] ring-offset-2',\n )}\n >\n <FileCard\n name={file.name}\n sizeBytes={file.sizeBytes}\n status={file.status}\n error={file.error}\n thumbnailUrl={file.thumbnailUrl}\n included={file.included}\n onToggleInclude={onToggleInclude ? () => onToggleInclude(file.id) : undefined}\n onRemove={onRemove ? () => onRemove(file.id) : undefined}\n onOpen={onOpen ? () => onOpen(file.id) : undefined}\n draggable={reorderable}\n onDragStart={() => {\n dragId.current = file.id\n }}\n onDragEnd={() => {\n dragId.current = null\n setDropTarget(null)\n }}\n removeLabel={removeLabel}\n includeLabel={includeLabel}\n />\n </div>\n ))}\n </div>\n </div>\n )\n },\n)\n"]}