@parallelworks/ui 0.41.0 → 0.42.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 (280) hide show
  1. package/README.md +25 -0
  2. package/dist/ai/components/AllocationSelector.d.ts +3 -4
  3. package/dist/ai/components/AllocationSelector.js +37 -33
  4. package/dist/ai/components/AttachmentManager.js +7 -7
  5. package/dist/ai/components/AttachmentUpload.js +5 -5
  6. package/dist/ai/components/BranchNavigator.js +1 -1
  7. package/dist/ai/components/ChatEmptyState.js +2 -2
  8. package/dist/ai/components/ChatInput.js +10 -8
  9. package/dist/ai/components/ChatLayout.js +4 -5
  10. package/dist/ai/components/ChatMessage.js +12 -12
  11. package/dist/ai/components/ChatMessageList.js +9 -9
  12. package/dist/ai/components/ChatSidebar.js +8 -9
  13. package/dist/ai/components/ChatThread.js +4 -4
  14. package/dist/ai/components/ComposerChrome.d.ts +2 -2
  15. package/dist/ai/components/ComposerChrome.js +3 -6
  16. package/dist/ai/components/DragOverlay.js +2 -2
  17. package/dist/ai/components/ModelSelector.d.ts +5 -3
  18. package/dist/ai/components/ModelSelector.js +102 -339
  19. package/dist/ai/components/PastedText.js +11 -11
  20. package/dist/ai/components/ProviderIssueBanner.d.ts +2 -0
  21. package/dist/ai/components/ProviderIssueBanner.js +34 -16
  22. package/dist/ai/components/Reasoning.js +4 -4
  23. package/dist/ai/components/ShareDialog.js +43 -35
  24. package/dist/ai/components/SlashMenu.d.ts +12 -2
  25. package/dist/ai/components/SlashMenu.js +29 -13
  26. package/dist/ai/components/agent/ActivityLine.js +3 -3
  27. package/dist/ai/components/agent/AgentMessageParts.js +20 -20
  28. package/dist/ai/components/agent/PermissionPicker.js +13 -11
  29. package/dist/ai/components/conversationActions.d.ts +4 -6
  30. package/dist/ai/components/conversationActions.js +9 -13
  31. package/dist/ai/core/ChatProvider.js +1 -1
  32. package/dist/ai/core/config.js +1 -1
  33. package/dist/ai/core/providerIssues.d.ts +7 -0
  34. package/dist/ai/core/providerIssues.js +9 -1
  35. package/dist/ai/core/useKeyboardShortcuts.d.ts +4 -0
  36. package/dist/ai/core/useKeyboardShortcuts.js +8 -2
  37. package/dist/ai/index.d.ts +0 -1
  38. package/dist/ai/index.js +1 -2
  39. package/dist/ai/strings.d.ts +19 -0
  40. package/dist/ai/strings.js +18 -1
  41. package/dist/ai/ui/Avatar.js +5 -5
  42. package/dist/ai/ui/ConversationSidebar.d.ts +0 -1
  43. package/dist/ai/ui/ConversationSidebar.js +6 -7
  44. package/dist/ai/ui/Markdown.js +3 -3
  45. package/dist/ai/ui/Notice.js +6 -6
  46. package/dist/ai/ui/chip.d.ts +4 -0
  47. package/dist/ai/ui/chip.js +8 -0
  48. package/dist/ai/ui/sidebar.d.ts +6 -5
  49. package/dist/ai/ui/sidebar.js +39 -43
  50. package/dist/components/ActionMenu.d.ts +13 -0
  51. package/dist/components/ActionMenu.js +30 -0
  52. package/dist/components/Avatar.js +6 -6
  53. package/dist/components/Breadcrumbs.js +1 -1
  54. package/dist/components/Button.js +10 -10
  55. package/dist/components/Callout.js +2 -2
  56. package/dist/components/Card.js +3 -3
  57. package/dist/components/Combobox.d.ts +66 -0
  58. package/dist/components/Combobox.js +393 -0
  59. package/dist/components/ConfirmModal.js +11 -11
  60. package/dist/components/ContextMenu.d.ts +23 -0
  61. package/dist/components/ContextMenu.js +89 -0
  62. package/dist/components/CopyToClipboard.js +2 -2
  63. package/dist/components/CreateModal.d.ts +17 -36
  64. package/dist/components/CreateModal.js +97 -259
  65. package/dist/components/DescriptionList.js +8 -8
  66. package/dist/components/Filter.js +2 -2
  67. package/dist/components/FilterPill.js +2 -2
  68. package/dist/components/HoverCard.d.ts +14 -0
  69. package/dist/components/HoverCard.js +33 -0
  70. package/dist/components/IconButton.d.ts +5 -5
  71. package/dist/components/IconButton.js +18 -22
  72. package/dist/components/InfoTip.d.ts +15 -0
  73. package/dist/components/InfoTip.js +60 -0
  74. package/dist/components/Input.js +5 -5
  75. package/dist/components/LetterBadge.js +2 -2
  76. package/dist/components/Loader.js +3 -3
  77. package/dist/components/Markdown.js +1 -1
  78. package/dist/components/MarkdownImpl.js +2 -2
  79. package/dist/components/Menu.d.ts +33 -0
  80. package/dist/components/Menu.js +86 -0
  81. package/dist/components/MenuEntries.d.ts +56 -0
  82. package/dist/components/MenuEntries.js +123 -0
  83. package/dist/components/Modal.d.ts +29 -0
  84. package/dist/components/Modal.js +47 -0
  85. package/dist/components/Overview.js +11 -10
  86. package/dist/components/PageHeader.d.ts +10 -16
  87. package/dist/components/PageHeader.js +69 -95
  88. package/dist/components/Pagination.js +5 -5
  89. package/dist/components/Provider.d.ts +5 -11
  90. package/dist/components/Provider.js +11 -14
  91. package/dist/components/Radio.d.ts +8 -0
  92. package/dist/components/Radio.js +16 -0
  93. package/dist/components/SectionHeader.js +2 -2
  94. package/dist/components/SegmentedControl.d.ts +6 -5
  95. package/dist/components/SegmentedControl.js +34 -30
  96. package/dist/components/Select.d.ts +27 -0
  97. package/dist/components/Select.js +78 -0
  98. package/dist/components/SettingModeOption.d.ts +5 -8
  99. package/dist/components/SettingModeOption.js +10 -12
  100. package/dist/components/SettingRow.js +4 -4
  101. package/dist/components/SettingsCard.js +4 -4
  102. package/dist/components/SettingsGroup.js +2 -2
  103. package/dist/components/Sort.js +1 -1
  104. package/dist/components/StatusBadge.js +7 -7
  105. package/dist/components/StatusIcons.js +4 -4
  106. package/dist/components/Switch.d.ts +22 -0
  107. package/dist/components/Switch.js +28 -0
  108. package/dist/components/Table.js +11 -11
  109. package/dist/components/Tooltip.d.ts +24 -20
  110. package/dist/components/Tooltip.js +58 -76
  111. package/dist/components/floating.d.ts +14 -0
  112. package/dist/components/floating.js +21 -0
  113. package/dist/components/search.d.ts +2 -0
  114. package/dist/components/search.js +14 -0
  115. package/dist/editor/Editor.js +1 -1
  116. package/dist/editor/EditorField.js +16 -21
  117. package/dist/editor/FormCodePanel.js +19 -19
  118. package/dist/editor/Monaco.js +3 -3
  119. package/dist/file-explorer/FileExplorer.js +77 -81
  120. package/dist/file-explorer/FileExplorerContext.js +2 -2
  121. package/dist/file-explorer/FilePreview/CodePreviewEditor.js +1 -1
  122. package/dist/file-explorer/FilePreview/Inline.js +1 -1
  123. package/dist/file-explorer/FilePreview/StreamedBadge.js +5 -6
  124. package/dist/file-explorer/FilePreview/Viewer.js +8 -8
  125. package/dist/file-explorer/FilePreview/index.d.ts +1 -1
  126. package/dist/file-explorer/FilePreview/index.js +49 -83
  127. package/dist/file-explorer/FileRow.d.ts +4 -3
  128. package/dist/file-explorer/FileRow.js +32 -38
  129. package/dist/file-explorer/FileRowsWindow.d.ts +3 -2
  130. package/dist/file-explorer/FileRowsWindow.js +4 -4
  131. package/dist/file-explorer/FileTable.d.ts +3 -2
  132. package/dist/file-explorer/FileTable.js +3 -3
  133. package/dist/file-explorer/LoadMoreRow.js +1 -1
  134. package/dist/file-explorer/TreeView.js +11 -16
  135. package/dist/file-explorer/helpers.js +11 -12
  136. package/dist/file-explorer/toasts.js +11 -11
  137. package/dist/form/FieldGroup.d.ts +11 -0
  138. package/dist/form/FieldGroup.js +36 -0
  139. package/dist/form/FieldWrapper.js +4 -4
  140. package/dist/form/Fields/BooleanField.js +23 -33
  141. package/dist/form/Fields/CheckboxGroupField.d.ts +1 -1
  142. package/dist/form/Fields/CheckboxGroupField.js +9 -13
  143. package/dist/form/Fields/ColorField.d.ts +1 -2
  144. package/dist/form/Fields/ColorField.js +6 -11
  145. package/dist/form/Fields/DropdownField.d.ts +3 -13
  146. package/dist/form/Fields/DropdownField.js +40 -27
  147. package/dist/form/Fields/DurationField.d.ts +1 -2
  148. package/dist/form/Fields/DurationField.js +25 -32
  149. package/dist/form/Fields/LabelField.js +2 -2
  150. package/dist/form/Fields/MultiDropdownField.d.ts +6 -12
  151. package/dist/form/Fields/MultiDropdownField.js +31 -22
  152. package/dist/form/Fields/NumberField.d.ts +1 -1
  153. package/dist/form/Fields/NumberField.js +65 -35
  154. package/dist/form/Fields/ObjectField.d.ts +1 -1
  155. package/dist/form/Fields/ObjectField.js +12 -43
  156. package/dist/form/Fields/RadioField.d.ts +1 -1
  157. package/dist/form/Fields/RadioField.js +30 -41
  158. package/dist/form/Fields/RangeField.d.ts +1 -2
  159. package/dist/form/Fields/RangeField.js +23 -16
  160. package/dist/form/Fields/StringField.d.ts +1 -2
  161. package/dist/form/Fields/StringField.js +58 -26
  162. package/dist/form/Fields/TextAreaField.js +12 -10
  163. package/dist/form/Form.d.ts +30 -48
  164. package/dist/form/Form.js +306 -412
  165. package/dist/form/FormLayout.js +9 -9
  166. package/dist/form/Wizard/WizardContainer.d.ts +1 -4
  167. package/dist/form/Wizard/WizardContainer.js +40 -56
  168. package/dist/form/Wizard/WizardNavigation.js +1 -1
  169. package/dist/form/Wizard/WizardStepContent.d.ts +1 -5
  170. package/dist/form/Wizard/WizardStepContent.js +11 -16
  171. package/dist/form/Wizard/WizardStepIndicator.js +6 -6
  172. package/dist/form/Wizard/types.d.ts +0 -14
  173. package/dist/form/fieldRegistry.d.ts +1 -1
  174. package/dist/form/fieldRegistry.js +6 -6
  175. package/dist/form/formEditing.js +1 -1
  176. package/dist/form/index.d.ts +5 -4
  177. package/dist/form/index.js +6 -7
  178. package/dist/form/types/fieldComponentTypes.d.ts +8 -10
  179. package/dist/form/useChoiceField.d.ts +20 -0
  180. package/dist/form/useChoiceField.js +49 -0
  181. package/dist/form/useFieldValue.d.ts +7 -0
  182. package/dist/form/useFieldValue.js +20 -0
  183. package/dist/form/useParsedOpts.d.ts +3 -1
  184. package/dist/form/useParsedOpts.js +12 -17
  185. package/dist/form/utils/dependentOptions.d.ts +8 -4
  186. package/dist/form/utils/dependentOptions.js +25 -17
  187. package/dist/form/utils/fieldItems.d.ts +10 -0
  188. package/dist/form/utils/fieldItems.js +11 -0
  189. package/dist/form/utils/fieldPath.d.ts +10 -0
  190. package/dist/form/utils/fieldPath.js +20 -0
  191. package/dist/form/utils/shareEqual.d.ts +6 -0
  192. package/dist/form/utils/shareEqual.js +38 -0
  193. package/dist/graph/AnnotationBanner.js +8 -8
  194. package/dist/graph/Collapse.d.ts +1 -0
  195. package/dist/graph/Collapse.js +6 -27
  196. package/dist/graph/Connectors.js +5 -5
  197. package/dist/graph/DependencyGraph.js +20 -19
  198. package/dist/graph/GraphEditor.js +30 -41
  199. package/dist/graph/GraphEditorDialogs.js +17 -17
  200. package/dist/graph/GraphNode.js +1 -1
  201. package/dist/graph/InputDialog.js +19 -22
  202. package/dist/graph/InputsEditor.js +58 -66
  203. package/dist/graph/JobSummary.js +42 -39
  204. package/dist/graph/MatrixGroup.js +1 -1
  205. package/dist/graph/ProblemsButton.js +18 -19
  206. package/dist/graph/Reveal.js +1 -1
  207. package/dist/graph/ShortcutsButton.js +15 -18
  208. package/dist/graph/SuggestionInput.d.ts +5 -10
  209. package/dist/graph/SuggestionInput.js +14 -18
  210. package/dist/graph/ToolbarPopover.d.ts +11 -6
  211. package/dist/graph/ToolbarPopover.js +35 -67
  212. package/dist/graph/TreeView.js +24 -37
  213. package/dist/graph/WorkflowSettingsDialog.js +4 -4
  214. package/dist/graph/editorChrome.js +13 -12
  215. package/dist/graph/editorFields.js +29 -29
  216. package/dist/graph/editorPrimitives.d.ts +1 -1
  217. package/dist/graph/editorPrimitives.js +10 -7
  218. package/dist/graph/editorRows.js +103 -97
  219. package/dist/graph/fieldProblems.js +2 -2
  220. package/dist/graph/graphEditorState.d.ts +4 -3
  221. package/dist/graph/inputRefs.js +9 -9
  222. package/dist/graph/settingsViews.js +6 -7
  223. package/dist/graph/stepWith.js +6 -6
  224. package/dist/index.d.ts +14 -15
  225. package/dist/index.js +15 -14
  226. package/dist/list/ActionToolbar.d.ts +6 -14
  227. package/dist/list/ActionToolbar.js +48 -96
  228. package/dist/list/ListPage.d.ts +6 -12
  229. package/dist/list/ListPage.js +46 -29
  230. package/dist/list/ListPager.js +4 -4
  231. package/dist/list/ListTable.js +5 -5
  232. package/dist/list/ListViewControls.d.ts +5 -4
  233. package/dist/list/ListViewControls.js +177 -267
  234. package/dist/list/UserHoverCard.d.ts +3 -17
  235. package/dist/list/UserHoverCard.js +21 -45
  236. package/dist/list/index.d.ts +3 -4
  237. package/dist/list/index.js +3 -4
  238. package/dist/list/listSearch.js +12 -11
  239. package/dist/list/rowMenu.d.ts +63 -0
  240. package/dist/list/rowMenu.js +134 -0
  241. package/dist/logviewer/LogViewer.js +26 -26
  242. package/dist/styles.css +1 -1
  243. package/package.json +7 -13
  244. package/dist/ai/ui/Dropdown.d.ts +0 -31
  245. package/dist/ai/ui/Dropdown.js +0 -110
  246. package/dist/components/AddMenu.d.ts +0 -18
  247. package/dist/components/AddMenu.js +0 -46
  248. package/dist/components/BareModal.d.ts +0 -17
  249. package/dist/components/BareModal.js +0 -77
  250. package/dist/components/CollapsiblePanel.d.ts +0 -27
  251. package/dist/components/CollapsiblePanel.js +0 -77
  252. package/dist/components/Dropdown.d.ts +0 -28
  253. package/dist/components/Dropdown.js +0 -355
  254. package/dist/components/Listbox.d.ts +0 -21
  255. package/dist/components/Listbox.js +0 -119
  256. package/dist/components/MultiSelect.d.ts +0 -22
  257. package/dist/components/MultiSelect.js +0 -168
  258. package/dist/components/SwitchToggle.d.ts +0 -15
  259. package/dist/components/SwitchToggle.js +0 -57
  260. package/dist/components/SwitchToggleSmall.d.ts +0 -6
  261. package/dist/components/SwitchToggleSmall.js +0 -14
  262. package/dist/components/Toggle.d.ts +0 -6
  263. package/dist/components/Toggle.js +0 -20
  264. package/dist/components/dropdownUtils.d.ts +0 -37
  265. package/dist/components/dropdownUtils.js +0 -99
  266. package/dist/form/SpecialTypes/DropdownWrapper.d.ts +0 -25
  267. package/dist/form/SpecialTypes/DropdownWrapper.js +0 -28
  268. package/dist/form/SpecialTypes/FormikCustomDropdown.d.ts +0 -51
  269. package/dist/form/SpecialTypes/FormikCustomDropdown.js +0 -119
  270. package/dist/form/SpecialTypes/FormikCustomInput.d.ts +0 -19
  271. package/dist/form/SpecialTypes/FormikCustomInput.js +0 -121
  272. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.d.ts +0 -13
  273. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +0 -31
  274. package/dist/form/SpecialTypes/FormikNumericInput.d.ts +0 -9
  275. package/dist/form/SpecialTypes/FormikNumericInput.js +0 -60
  276. package/dist/form/SpecialTypes/index.d.ts +0 -3
  277. package/dist/list/HoverCard.d.ts +0 -24
  278. package/dist/list/HoverCard.js +0 -73
  279. package/dist/list/RowContextMenu.d.ts +0 -127
  280. package/dist/list/RowContextMenu.js +0 -515
package/README.md CHANGED
@@ -176,6 +176,31 @@ animations) and streamdown's classes next to the theme contract:
176
176
 
177
177
  The prebuilt `@parallelworks/ui/styles.css` already includes both.
178
178
 
179
+ ## Form state
180
+
181
+ `DynamicForm` keeps its values in react-hook-form, a peer dependency, so the
182
+ host and the library share one instance. A host that reads or drives the form
183
+ creates it and passes it in:
184
+
185
+ ```tsx
186
+ const form = useForm()
187
+ const { isDirty } = useFormState({ control: form.control })
188
+
189
+ <DynamicForm form={form} formJSONs={inputs} initialValues={saved} />
190
+ ```
191
+
192
+ `form.getValues()`, `form.reset()` and `formState.isDirty` then work as
193
+ react-hook-form documents them. Without `form`, the form keeps its own;
194
+ `onValuesChange` reports each change either way. `missingFields` marks fields
195
+ as `required` errors.
196
+
197
+ Each field subscribes only to what it reads, so typing renders the edited
198
+ field and whatever reads it, not the whole form. A host field component,
199
+ passed through `fields` or `slots.formFields`, binds the same way: its own
200
+ value with `useFieldValue(field.name)` (or `useController`), another input's
201
+ with `useFieldAt(path)` or `useWatch`, and a pick from a list with
202
+ `useChoiceField`, which applies `autoselect` and `secondaryField`.
203
+
179
204
  ## Form layouts
180
205
 
181
206
  `DynamicForm` accepts an optional `$meta.layout` in `formJSONs`. A layout arranges
@@ -1,4 +1,3 @@
1
- export default function AllocationSelector({ variant, }?: {
2
- /** 'bare' drops the border, for a toolbar that reads as text. */
3
- variant?: 'default' | 'bare';
4
- }): import("react").JSX.Element | null;
1
+ /** Which allocation an organization model bills, with its spend so far. Shows
2
+ * only for an organization model, and picks the first allocation for it. */
3
+ export default function AllocationSelector(): import("react").JSX.Element | null;
@@ -1,55 +1,59 @@
1
+ import { FaAngleDown } from "../../icons/fa/FaAngleDown.js";
2
+ import { Select } from "../../components/Select.js";
3
+ import { useChatConfig } from "../core/config.js";
1
4
  import { useChat } from "../core/ChatProvider.js";
2
- import Dropdown from "../ui/Dropdown.js";
5
+ import { chipClassName } from "../ui/chip.js";
3
6
  import { isOrgModel } from "../utils.js";
4
- import { useEffect } from "react";
5
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { useEffect } from "react";
6
9
  import useSWR from "swr";
7
10
  //#region src/ai/components/AllocationSelector.tsx
8
- function AllocationSelector({ variant = "default" } = {}) {
9
- const bare = variant === "bare";
11
+ var money = (amount) => `$${amount.toFixed(2)}`;
12
+ /** Which allocation an organization model bills, with its spend so far. Shows
13
+ * only for an organization model, and picks the first allocation for it. */
14
+ function AllocationSelector() {
10
15
  const { adapter, selectedProvider, selectedAllocation, setSelectedAllocation } = useChat();
16
+ const t = useChatConfig().strings.allocationPicker;
11
17
  const isOrgProvider = isOrgModel(selectedProvider);
12
18
  const allocationsAdapter = adapter.allocations;
13
19
  const { data: allocations } = useSWR(isOrgProvider && allocationsAdapter ? ["ai-chat-allocations"] : null, () => allocationsAdapter?.list());
20
+ const first = allocations?.[0];
14
21
  useEffect(() => {
15
- const first = allocations?.[0];
16
- if (isOrgProvider && first && !selectedAllocation) setSelectedAllocation(first.name);
17
- }, [
18
- isOrgProvider,
19
- allocations,
20
- selectedAllocation,
21
- setSelectedAllocation
22
- ]);
23
- useEffect(() => {
24
- if (!isOrgProvider && selectedAllocation) setSelectedAllocation(null);
22
+ if (!isOrgProvider) {
23
+ if (selectedAllocation) setSelectedAllocation(null);
24
+ } else if (first && !selectedAllocation) setSelectedAllocation(first.name);
25
25
  }, [
26
26
  isOrgProvider,
27
+ first,
27
28
  selectedAllocation,
28
29
  setSelectedAllocation
29
30
  ]);
30
31
  if (!isOrgProvider || !allocations?.length) return null;
31
- const options = allocations.map((alloc) => ({
32
- label: alloc.name,
33
- value: alloc.name
34
- }));
35
32
  const selected = allocations.find((a) => a.name === selectedAllocation);
36
33
  return /* @__PURE__ */ jsxs("div", {
37
- className: "flex items-center gap-2",
38
- children: [/* @__PURE__ */ jsx(Dropdown, {
39
- options,
40
- value: selectedAllocation ?? "",
41
- onChange: (v) => setSelectedAllocation(v || null),
42
- variant,
43
- textBoxClassName: bare ? "rounded-full h-8 px-2.5 text-[13px] hover:chat-tint" : "h-8 rounded-lg border theme-border text-xs px-2",
44
- placeholder: "Select allocation"
45
- }), selected && /* @__PURE__ */ jsxs("span", {
34
+ className: "flex min-w-0 items-center gap-2",
35
+ children: [/* @__PURE__ */ jsx(Select, {
36
+ "aria-label": t.choose,
37
+ items: allocations.map((a) => ({
38
+ value: a.name,
39
+ label: a.name
40
+ })),
41
+ value: selectedAllocation,
42
+ onValueChange: setSelectedAllocation,
43
+ trigger: /* @__PURE__ */ jsxs("button", {
44
+ type: "button",
45
+ className: chipClassName,
46
+ children: [/* @__PURE__ */ jsx("span", {
47
+ className: "truncate",
48
+ children: selected?.name ?? t.placeholder
49
+ }), /* @__PURE__ */ jsx(FaAngleDown, {
50
+ className: "h-3 w-3 shrink-0",
51
+ "aria-hidden": "true"
52
+ })]
53
+ })
54
+ }), selected && /* @__PURE__ */ jsx("span", {
46
55
  className: "text-xs tabular-nums theme-muted-text whitespace-nowrap",
47
- children: [
48
- "$",
49
- (selected.used ?? 0).toFixed(2),
50
- " / $",
51
- selected.total.toFixed(2)
52
- ]
56
+ children: t.usage(money(selected.used ?? 0), money(selected.total))
53
57
  })]
54
58
  });
55
59
  }
@@ -1,14 +1,14 @@
1
- import { safeUrl } from "../../safeUrl.js";
2
1
  import { BiSolidTrashAlt } from "../../icons/bi/BiSolidTrashAlt.js";
3
2
  import { FiDownload } from "../../icons/fi/FiDownload.js";
4
3
  import { FiFile } from "../../icons/fi/FiFile.js";
4
+ import { safeUrl } from "../../safeUrl.js";
5
5
  import { useChatConfig } from "../core/config.js";
6
6
  import { useChat } from "../core/ChatProvider.js";
7
7
  import { formatFileSize } from "../utils.js";
8
8
  import { attachmentsPageKey } from "./attachmentKeys.js";
9
- import cx from "classnames";
9
+ import { clsx } from "clsx";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
11
  import { useCallback, useMemo, useState } from "react";
11
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
12
12
  import { DateTime } from "luxon";
13
13
  import useSWRInfinite from "swr/infinite";
14
14
  //#region src/ai/components/AttachmentManager.tsx
@@ -74,7 +74,7 @@ function AttachmentManager() {
74
74
  }) : attachments.length === 0 ? /* @__PURE__ */ jsx("p", {
75
75
  className: "text-center theme-muted-text py-12 text-sm",
76
76
  children: t.empty
77
- }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
77
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
78
78
  className: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4",
79
79
  children: attachments.map((att) => {
80
80
  const downloadUrl = attachmentsAdapter.downloadUrl(att.id);
@@ -87,14 +87,14 @@ function AttachmentManager() {
87
87
  style: { cursor: "pointer" }
88
88
  } : {};
89
89
  return /* @__PURE__ */ jsxs("div", {
90
- className: cx("rounded-lg border theme-border overflow-hidden", isDeleting && "opacity-50 pointer-events-none"),
90
+ className: clsx("rounded-lg border theme-border overflow-hidden", isDeleting && "opacity-50 pointer-events-none"),
91
91
  children: [/* @__PURE__ */ jsxs("div", {
92
92
  className: "relative aspect-square bg-(--theme-muted-panel-bg) flex items-center justify-center",
93
93
  ...openProps,
94
94
  children: [/* @__PURE__ */ jsx(FiFile, { className: "w-8 h-8 theme-muted-text" }), showThumbnail && /* @__PURE__ */ jsx("img", {
95
95
  src: downloadUrl,
96
96
  alt: att.filename || "Image",
97
- className: cx("absolute inset-0 w-full h-full object-cover", thumbnail !== "loaded" && "opacity-0"),
97
+ className: clsx("absolute inset-0 w-full h-full object-cover", thumbnail !== "loaded" && "opacity-0"),
98
98
  loading: "lazy",
99
99
  onLoad: () => markThumbnail(att.id, "loaded"),
100
100
  onError: () => markThumbnail(att.id, "broken")
@@ -108,7 +108,7 @@ function AttachmentManager() {
108
108
  children: att.filename || "File"
109
109
  }), /* @__PURE__ */ jsxs("p", {
110
110
  className: "truncate theme-muted-text",
111
- children: [att.size ? formatFileSize(att.size) : "", att.uploadedAt && /* @__PURE__ */ jsxs(Fragment$1, { children: [att.size ? " · " : "", DateTime.fromISO(att.uploadedAt).toRelative()] })]
111
+ children: [att.size ? formatFileSize(att.size) : "", att.uploadedAt && /* @__PURE__ */ jsxs(Fragment, { children: [att.size ? " · " : "", DateTime.fromISO(att.uploadedAt).toRelative()] })]
112
112
  })]
113
113
  }), /* @__PURE__ */ jsxs("div", {
114
114
  className: "flex items-center gap-0.5 flex-shrink-0",
@@ -7,9 +7,9 @@ import { useChatConfig } from "../core/config.js";
7
7
  import { useChat } from "../core/ChatProvider.js";
8
8
  import { formatFileSize } from "../utils.js";
9
9
  import { ATTACHMENTS_INFINITE_KEY } from "./attachmentKeys.js";
10
- import cx from "classnames";
10
+ import { clsx } from "clsx";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
12
  import { forwardRef, useCallback, useImperativeHandle, useRef, useState } from "react";
12
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
13
13
  import { mutate } from "swr";
14
14
  //#region src/ai/components/AttachmentUpload.tsx
15
15
  var DEFAULT_MAX_FILE_SIZE = 26214400;
@@ -112,7 +112,7 @@ var AttachmentUpload = forwardRef(function AttachmentUpload({ conversationId, at
112
112
  const handleClick = () => {
113
113
  fileInputRef.current?.click();
114
114
  };
115
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("input", {
115
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
116
116
  ref: fileInputRef,
117
117
  type: "file",
118
118
  multiple: true,
@@ -127,7 +127,7 @@ var AttachmentUpload = forwardRef(function AttachmentUpload({ conversationId, at
127
127
  children: attachments.map((attachment, index) => {
128
128
  const Icon = getFileIcon(attachment.mimeType);
129
129
  return /* @__PURE__ */ jsxs("div", {
130
- className: cx("flex items-center gap-2 px-2 py-1 rounded border theme-border theme-muted-panel", attachment.error && "border-red-500"),
130
+ className: clsx("flex items-center gap-2 px-2 py-1 rounded border theme-border theme-muted-panel", attachment.error && "border-red-500"),
131
131
  children: [
132
132
  /* @__PURE__ */ jsx(Icon, { className: "w-4 h-4 theme-muted-text" }),
133
133
  /* @__PURE__ */ jsx("span", {
@@ -163,7 +163,7 @@ var AttachmentUpload = forwardRef(function AttachmentUpload({ conversationId, at
163
163
  onDragOver: handleDragOver,
164
164
  onDragLeave: handleDragLeave,
165
165
  onDrop: handleDrop,
166
- className: cx("relative block w-full border-2 border-dashed rounded-lg p-3 text-center transition-colors", isDragging ? "border-blue-500 bg-blue-500/10" : "theme-border hover:theme-border", disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"),
166
+ className: clsx("relative block w-full border-2 border-dashed rounded-lg p-3 text-center transition-colors", isDragging ? "border-blue-500 bg-blue-500/10" : "theme-border hover:theme-border", disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"),
167
167
  onClick: disabled ? void 0 : handleClick,
168
168
  children: [/* @__PURE__ */ jsxs("span", {
169
169
  className: "flex items-center justify-center gap-2 text-sm theme-muted-text",
@@ -1,8 +1,8 @@
1
1
  import { FaAngleLeft } from "../../icons/fa/FaAngleLeft.js";
2
2
  import { FaAngleRight } from "../../icons/fa/FaAngleRight.js";
3
3
  import { useChatConfig } from "../core/config.js";
4
- import { useMemo } from "react";
5
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { useMemo } from "react";
6
6
  //#region src/ai/components/BranchNavigator.tsx
7
7
  function findSiblings(messages, messageId) {
8
8
  const message = messages.find((m) => m.id === messageId);
@@ -12,8 +12,8 @@ import DragOverlay from "./DragOverlay.js";
12
12
  import ChatInput from "./ChatInput.js";
13
13
  import ChatStage from "./ChatStage.js";
14
14
  import ProviderIssueBanner from "./ProviderIssueBanner.js";
15
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
15
16
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
16
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
17
17
  //#region src/ai/components/ChatEmptyState.tsx
18
18
  function pickRandom(arr, count) {
19
19
  return [...arr].sort(() => Math.random() - .5).slice(0, count);
@@ -138,7 +138,7 @@ function ChatEmptyState({ targetSession }) {
138
138
  disabled: isLoading || isLoadingModels || models.length === 0,
139
139
  placeholder: isLoadingModels ? tInput.placeholderLoading : hasLoadedModels && models.length === 0 ? tInput.placeholderNoProviders : tInput.placeholder,
140
140
  settingsLeft: /* @__PURE__ */ jsx(ConnectToolsLink, {}),
141
- settingsRight: /* @__PURE__ */ jsxs(Fragment$1, { children: [slots.composerUsage, /* @__PURE__ */ jsx(ComposerControls, { targetSession })] })
141
+ settingsRight: /* @__PURE__ */ jsxs(Fragment, { children: [slots.composerUsage, /* @__PURE__ */ jsx(ComposerControls, { targetSession })] })
142
142
  }),
143
143
  prompts.length > 0 && !(hasLoadedModels && models.length === 0) && /* @__PURE__ */ jsx("ul", {
144
144
  className: "mx-auto max-w-[var(--chat-column,50rem)] px-8",
@@ -11,9 +11,9 @@ import DragOverlay from "./DragOverlay.js";
11
11
  import { PasteFileCard } from "./PastedText.js";
12
12
  import { SlashMenu, useSlashMenu } from "./SlashMenu.js";
13
13
  import { usePasteCards } from "./usePasteCards.js";
14
- import cx from "classnames";
14
+ import { clsx } from "clsx";
15
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
15
16
  import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
16
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
17
17
  //#region src/ai/components/ChatInput.tsx
18
18
  /** An optional box that is still empty should not wear the filled look of
19
19
  * one waiting to send something. */
@@ -35,10 +35,10 @@ function AttachButton({ open, disabled, label, onClick }) {
35
35
  onClick,
36
36
  disabled,
37
37
  "aria-expanded": open,
38
- className: cx("flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full transition-colors", open ? "theme-text chat-tint-strong" : "theme-muted-text hover:theme-text hover:chat-tint", "disabled:opacity-50 disabled:cursor-not-allowed"),
38
+ className: clsx("flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full transition-colors", open ? "theme-text chat-tint-strong" : "theme-muted-text hover:theme-text hover:chat-tint", "disabled:opacity-50 disabled:cursor-not-allowed"),
39
39
  "aria-label": label,
40
40
  title: label,
41
- children: /* @__PURE__ */ jsx(GoPlus, { className: cx("h-5 w-5 transition-transform duration-200", open && "rotate-45") })
41
+ children: /* @__PURE__ */ jsx(GoPlus, { className: clsx("h-5 w-5 transition-transform duration-200", open && "rotate-45") })
42
42
  });
43
43
  }
44
44
  function SendButton({ onClick, enabled, emphasised, label, testId }) {
@@ -47,7 +47,7 @@ function SendButton({ onClick, enabled, emphasised, label, testId }) {
47
47
  onClick,
48
48
  disabled: !enabled,
49
49
  "data-testid": testId,
50
- className: cx("flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full transition-[background-color,color,transform] duration-150 active:scale-95", emphasised ? "theme-element hover:opacity-90" : "chat-send-idle", !enabled && "cursor-not-allowed active:scale-100"),
50
+ className: clsx("flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full transition-[background-color,color,transform] duration-150 active:scale-95", emphasised ? "theme-element hover:opacity-90" : "chat-send-idle", !enabled && "cursor-not-allowed active:scale-100"),
51
51
  "aria-label": label,
52
52
  title: label,
53
53
  children: /* @__PURE__ */ jsx(FaArrowUp, { className: "h-4 w-4" })
@@ -228,6 +228,7 @@ var ChatInput = forwardRef(function ChatInput({ onSend, disabled = false, placeh
228
228
  className: "relative",
229
229
  children: [slash && slashMenu.open && /* @__PURE__ */ jsx(SlashMenu, {
230
230
  label: slash.label,
231
+ listId: slashMenu.listId,
231
232
  matches: slashMenu.matches,
232
233
  active: slashMenu.active,
233
234
  onChoose: (name) => {
@@ -248,7 +249,7 @@ var ChatInput = forwardRef(function ChatInput({ onSend, disabled = false, placeh
248
249
  })
249
250
  }),
250
251
  /* @__PURE__ */ jsxs("div", {
251
- className: cx(!toolbar && "flex items-end gap-2 pr-2 pb-2"),
252
+ className: clsx(!toolbar && "flex items-end gap-2 pr-2 pb-2"),
252
253
  children: [/* @__PURE__ */ jsx("div", {
253
254
  className: "max-h-[200px] min-w-0 flex-1 overflow-y-auto",
254
255
  children: /* @__PURE__ */ jsx("textarea", {
@@ -257,11 +258,12 @@ var ChatInput = forwardRef(function ChatInput({ onSend, disabled = false, placeh
257
258
  onChange: (e) => setInputAndPersist(e.target.value),
258
259
  onKeyDown: handleKeyDown,
259
260
  onPaste: handlePaste,
261
+ ...slashMenu.inputProps,
260
262
  placeholder: effectivePlaceholder,
261
263
  "aria-label": inputLabel ?? effectivePlaceholder,
262
264
  disabled,
263
265
  rows: 1,
264
- className: cx("theme-text block w-full resize-none overflow-hidden", "bg-transparent border-0 px-4", toolbar ? "pt-3.5 pb-1" : "pt-3 pb-1", "placeholder:theme-muted-text", "focus:outline-none focus:ring-0", "disabled:opacity-50 disabled:cursor-not-allowed", "text-[1rem] leading-relaxed")
266
+ className: clsx("theme-text block w-full resize-none overflow-hidden", "bg-transparent border-0 px-4", toolbar ? "pt-3.5 pb-1" : "pt-3 pb-1", "placeholder:theme-muted-text", "focus:outline-none focus:ring-0", "disabled:opacity-50 disabled:cursor-not-allowed", "text-[1rem] leading-relaxed")
265
267
  })
266
268
  }), !toolbar && action]
267
269
  }),
@@ -286,7 +288,7 @@ var ChatInput = forwardRef(function ChatInput({ onSend, disabled = false, placeh
286
288
  ]
287
289
  })]
288
290
  }),
289
- (settingsLeft || uploadedCount > 0) && /* @__PURE__ */ jsx(ComposerSettings, { left: /* @__PURE__ */ jsxs(Fragment$1, { children: [settingsLeft, uploadedCount > 0 && /* @__PURE__ */ jsx("span", {
291
+ (settingsLeft || uploadedCount > 0) && /* @__PURE__ */ jsx(ComposerSettings, { left: /* @__PURE__ */ jsxs(Fragment, { children: [settingsLeft, uploadedCount > 0 && /* @__PURE__ */ jsx("span", {
290
292
  className: "text-[11px] theme-muted-text",
291
293
  children: t.filesAttached(uploadedCount)
292
294
  })] }) }),
@@ -4,9 +4,9 @@ import { useChat } from "../core/ChatProvider.js";
4
4
  import { KeyboardShortcutsProvider } from "../core/KeyboardShortcutsProvider.js";
5
5
  import { SidebarToggle } from "../ui/sidebar.js";
6
6
  import ChatSidebar from "./ChatSidebar.js";
7
- import cx from "classnames";
8
- import { useLayoutEffect, useRef, useState } from "react";
7
+ import { clsx } from "clsx";
9
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { useLayoutEffect, useRef, useState } from "react";
10
10
  //#region src/ai/components/ChatLayout.tsx
11
11
  /** The list at its default width beside the narrowest thread that still
12
12
  * reads comfortably; narrower than that, 'auto' moves the list to a drawer. */
@@ -51,10 +51,9 @@ function ConversationLayout({ sidebar, children, sidebarMode = "inline", drawerB
51
51
  const { strings } = useChatConfig();
52
52
  return /* @__PURE__ */ jsxs("div", {
53
53
  ref,
54
- className: cx("flex h-full", drawer && "relative overflow-hidden"),
54
+ className: clsx("flex h-full", drawer && "relative overflow-hidden"),
55
55
  children: [sidebar, /* @__PURE__ */ jsxs("main", {
56
- inert: drawer && drawerOpen,
57
- className: cx("flex min-w-0 flex-1 flex-col", CHAT_COLUMN_SCOPE),
56
+ className: clsx("flex min-w-0 flex-1 flex-col", CHAT_COLUMN_SCOPE),
58
57
  children: [drawer && (drawerToggle || drawerBar) && /* @__PURE__ */ jsxs("div", {
59
58
  className: "flex shrink-0 items-center gap-2 bg-(--theme-panel-bg) px-2 pt-2",
60
59
  children: [drawerToggle && /* @__PURE__ */ jsx(SidebarToggle, {
@@ -1,4 +1,3 @@
1
- import { safeUrl } from "../../safeUrl.js";
2
1
  import { BiError } from "../../icons/bi/BiError.js";
3
2
  import { FaCheck } from "../../icons/fa/FaCheck.js";
4
3
  import { FaEdit } from "../../icons/fa/FaEdit.js";
@@ -7,6 +6,7 @@ import { FiCopy } from "../../icons/fi/FiCopy.js";
7
6
  import { FiDownload } from "../../icons/fi/FiDownload.js";
8
7
  import { FiFile } from "../../icons/fi/FiFile.js";
9
8
  import { MdRefresh } from "../../icons/md/MdRefresh.js";
9
+ import { safeUrl } from "../../safeUrl.js";
10
10
  import { durationToAbsHumanDuration } from "../../duration.js";
11
11
  import { useChatConfig } from "../core/config.js";
12
12
  import { formatFileSize } from "../utils.js";
@@ -17,9 +17,9 @@ import AgentMessageParts from "./agent/AgentMessageParts.js";
17
17
  import BranchNavigator from "./BranchNavigator.js";
18
18
  import { UserMessageText } from "./PastedText.js";
19
19
  import { Avatar } from "../ui/Avatar.js";
20
- import cx from "classnames";
21
- import { memo, useEffect, useRef, useState } from "react";
20
+ import { clsx } from "clsx";
22
21
  import { jsx, jsxs } from "react/jsx-runtime";
22
+ import { memo, useEffect, useRef, useState } from "react";
23
23
  import { DateTime, Duration } from "luxon";
24
24
  //#region src/ai/components/ChatMessage.tsx
25
25
  function formatDuration(ms) {
@@ -102,7 +102,7 @@ function ChatMessage({ message, allMessages, isStreaming = false, latest = false
102
102
  };
103
103
  const hasParts = !!message.parts?.length;
104
104
  if (hasParts && !message.content) return /* @__PURE__ */ jsx("div", {
105
- className: cx("group py-3 w-full", !flush && "px-4"),
105
+ className: clsx("group py-3 w-full", !flush && "px-4"),
106
106
  children: /* @__PURE__ */ jsx(AgentMessageParts, {
107
107
  message,
108
108
  isStreaming,
@@ -123,7 +123,7 @@ function ChatMessage({ message, allMessages, isStreaming = false, latest = false
123
123
  };
124
124
  return /* @__PURE__ */ jsx("div", {
125
125
  role: "none",
126
- className: cx("group w-full", isUser ? "pt-8 pb-5" : "py-3", !flush && "px-4"),
126
+ className: clsx("group w-full", isUser ? "pt-8 pb-5" : "py-3", !flush && "px-4"),
127
127
  onMouseEnter: () => setShowActions(true),
128
128
  onMouseLeave: () => setShowActions(false),
129
129
  onFocus: () => setShowActions(true),
@@ -153,9 +153,9 @@ function ChatMessage({ message, allMessages, isStreaming = false, latest = false
153
153
  })]
154
154
  })]
155
155
  }) : /* @__PURE__ */ jsx("div", {
156
- className: cx("flex gap-3 w-full", isRightAligned ? "flex-row-reverse" : "flex-row"),
156
+ className: clsx("flex gap-3 w-full", isRightAligned ? "flex-row-reverse" : "flex-row"),
157
157
  children: /* @__PURE__ */ jsxs("div", {
158
- className: cx("flex-1 min-w-0 space-y-1", isRightAligned && "relative flex flex-col items-end"),
158
+ className: clsx("flex-1 min-w-0 space-y-1", isRightAligned && "relative flex flex-col items-end"),
159
159
  children: [
160
160
  showReasoningButton && /* @__PURE__ */ jsxs("div", {
161
161
  className: "mb-2",
@@ -191,21 +191,21 @@ function ChatMessage({ message, allMessages, isStreaming = false, latest = false
191
191
  name: otherAuthor.name || otherAuthor.username,
192
192
  className: "flex-shrink-0 mb-0.5"
193
193
  }), /* @__PURE__ */ jsx("div", {
194
- className: cx("px-4 py-2.5 chat-ink rounded-[1.25rem] max-w-[80%] inline-block whitespace-pre-wrap wrap-break-word text-[1rem] leading-6 chat-tint", hasPastes && "chat-bubble-roomy"),
194
+ className: clsx("px-4 py-2.5 chat-ink rounded-[1.25rem] max-w-[80%] inline-block whitespace-pre-wrap wrap-break-word text-[1rem] leading-6 chat-tint", hasPastes && "chat-bubble-roomy"),
195
195
  children: /* @__PURE__ */ jsx(UserMessageText, {
196
196
  content: message.content,
197
197
  pastes: message.pastes
198
198
  })
199
199
  })]
200
200
  }) : isUser ? /* @__PURE__ */ jsx("div", {
201
- className: cx("px-4 py-2.5 chat-ink rounded-[1.25rem] max-w-[80%] inline-block whitespace-pre-wrap wrap-break-word text-[1rem] leading-6 chat-bubble-user", hasPastes && "chat-bubble-roomy"),
201
+ className: clsx("px-4 py-2.5 chat-ink rounded-[1.25rem] max-w-[80%] inline-block whitespace-pre-wrap wrap-break-word text-[1rem] leading-6 chat-bubble-user", hasPastes && "chat-bubble-roomy"),
202
202
  children: /* @__PURE__ */ jsx(UserMessageText, {
203
203
  content: message.content,
204
204
  pastes: message.pastes
205
205
  })
206
206
  }) : /* @__PURE__ */ jsx("div", {
207
207
  ref: contentRef,
208
- className: cx(chatProseClasses, collapsed && "chat-message-clamp"),
208
+ className: clsx(chatProseClasses, collapsed && "chat-message-clamp"),
209
209
  children: /* @__PURE__ */ jsx(Markdown, {
210
210
  isStreaming,
211
211
  children: message.content
@@ -303,7 +303,7 @@ function ChatMessage({ message, allMessages, isStreaming = false, latest = false
303
303
  })
304
304
  }),
305
305
  !isStreaming && !isEditing && /* @__PURE__ */ jsxs("div", {
306
- className: cx("chat-actions flex items-center gap-0.5 transition-opacity duration-150", isRightAligned ? "absolute right-0 top-full -mr-1.5 mt-0.5" : "-ml-1.5 mt-2", isRightAligned && (showActions ? "opacity-100" : "opacity-0 pointer-events-none")),
306
+ className: clsx("chat-actions flex items-center gap-0.5 transition-opacity duration-150", isRightAligned ? "absolute right-0 top-full -mr-1.5 mt-0.5" : "-ml-1.5 mt-2", isRightAligned && (showActions ? "opacity-100" : "opacity-0 pointer-events-none")),
307
307
  children: [
308
308
  /* @__PURE__ */ jsx("button", {
309
309
  type: "button",
@@ -332,7 +332,7 @@ function ChatMessage({ message, allMessages, isStreaming = false, latest = false
332
332
  onNavigate: onNavigateBranch
333
333
  }),
334
334
  (timestamp || !isUser && (message.model || totalTokens)) && /* @__PURE__ */ jsxs("span", {
335
- className: cx("chat-meta flex items-center gap-2 ml-2 text-xs tabular-nums theme-muted-text transition-opacity duration-150 select-none", showActions ? "opacity-100" : "opacity-0"),
335
+ className: clsx("chat-meta flex items-center gap-2 ml-2 text-xs tabular-nums theme-muted-text transition-opacity duration-150 select-none", showActions ? "opacity-100" : "opacity-0"),
336
336
  children: [
337
337
  timestamp && /* @__PURE__ */ jsx("span", {
338
338
  title: timestamp.toLocaleString(DateTime.DATETIME_MED_WITH_SECONDS),
@@ -7,9 +7,9 @@ import Markdown from "../ui/Markdown.js";
7
7
  import { ReasoningBody, ReasoningToggle } from "./Reasoning.js";
8
8
  import AgentMessageParts from "./agent/AgentMessageParts.js";
9
9
  import ChatMessage_default from "./ChatMessage.js";
10
- import cx from "classnames";
10
+ import { clsx } from "clsx";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
12
  import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
12
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
13
13
  import { Duration } from "luxon";
14
14
  //#region src/ai/components/ChatMessageList.tsx
15
15
  function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessages, onRemoveQueued, canRemoveQueued, queueDelivery = "afterReply", editingMessageId, showAuthor, currentUsername, onNavigateBranch, onEditMessage, onSaveEdit, onCancelEdit, onRegenerateMessage, onRetryMessage, onOpenReasoning, onApprovalAnswer, inputElement, isStreaming: isStreamingProp, flush, label, footer, workingIndicator = true }) {
@@ -151,7 +151,7 @@ function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessag
151
151
  children: [
152
152
  /* @__PURE__ */ jsx("div", { className: "flex-1" }),
153
153
  footer && /* @__PURE__ */ jsx("div", {
154
- className: cx("w-full max-w-[var(--chat-column,50rem)] mx-auto", !flush && "px-4"),
154
+ className: clsx("w-full max-w-[var(--chat-column,50rem)] mx-auto", !flush && "px-4"),
155
155
  children: footer
156
156
  }),
157
157
  inputElement && /* @__PURE__ */ jsx("div", {
@@ -202,7 +202,7 @@ function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessag
202
202
  isStreaming && streamingReasoning && /* @__PURE__ */ jsx("div", {
203
203
  className: "animate-chat-enter",
204
204
  children: /* @__PURE__ */ jsxs("div", {
205
- className: cx("pt-3", !flush && "px-4"),
205
+ className: clsx("pt-3", !flush && "px-4"),
206
206
  children: [/* @__PURE__ */ jsx(ReasoningToggle, {
207
207
  open: reasoningOpen,
208
208
  shimmer: isThinking,
@@ -225,7 +225,7 @@ function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessag
225
225
  })
226
226
  }, "thinking"),
227
227
  isStreaming && streamingParts.length > 0 && /* @__PURE__ */ jsx("div", {
228
- className: cx("animate-chat-enter py-1", !flush && "px-4"),
228
+ className: clsx("animate-chat-enter py-1", !flush && "px-4"),
229
229
  children: /* @__PURE__ */ jsx(AgentMessageParts, {
230
230
  message: {
231
231
  id: "streaming-parts",
@@ -238,7 +238,7 @@ function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessag
238
238
  showWorkingIndicator && /* @__PURE__ */ jsx("div", {
239
239
  className: "animate-chat-enter",
240
240
  children: /* @__PURE__ */ jsx("div", {
241
- className: cx("py-3", !flush && "px-4"),
241
+ className: clsx("py-3", !flush && "px-4"),
242
242
  children: /* @__PURE__ */ jsx("div", {
243
243
  className: "animate-shimmer text-shimmer text-sm",
244
244
  children: tThinking.ellipsis
@@ -261,7 +261,7 @@ function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessag
261
261
  const removable = canRemoveQueued?.(msg.id) ?? true;
262
262
  const status = !removable ? strings.queue.handedOver : queueDelivery === "nextStep" ? strings.queue.waitingNextStep : strings.queue.waiting;
263
263
  return /* @__PURE__ */ jsxs("div", {
264
- className: cx("animate-chat-enter", removable && "chat-queued"),
264
+ className: clsx("animate-chat-enter", removable && "chat-queued"),
265
265
  children: [/* @__PURE__ */ jsx(ChatMessage_default, {
266
266
  message: msg,
267
267
  allMessages,
@@ -270,11 +270,11 @@ function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessag
270
270
  onOpenAttachment
271
271
  }), /* @__PURE__ */ jsxs("div", {
272
272
  "data-testid": "queued-status",
273
- className: cx("-mt-4 mb-2 flex items-center justify-end gap-2 text-xs theme-muted-text", !flush && "px-4"),
273
+ className: clsx("-mt-4 mb-2 flex items-center justify-end gap-2 text-xs theme-muted-text", !flush && "px-4"),
274
274
  children: [
275
275
  removable ? /* @__PURE__ */ jsx(FiClock, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(FaCheck, { className: "h-3 w-3" }),
276
276
  /* @__PURE__ */ jsx("span", { children: status }),
277
- onRemoveQueued && removable && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
277
+ onRemoveQueued && removable && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
278
278
  "aria-hidden": "true",
279
279
  children: "·"
280
280
  }), /* @__PURE__ */ jsx("button", {
@@ -10,9 +10,9 @@ import { FOCUS_SIDEBAR_SEARCH_EVENT } from "../core/events.js";
10
10
  import { SidebarPlaceholder, SidebarRow, SidebarRowTitle } from "../ui/sidebar.js";
11
11
  import { ConversationSidebar } from "../ui/ConversationSidebar.js";
12
12
  import { groupConversationsByDate, useConversationActions } from "./conversationActions.js";
13
- import cx from "classnames";
13
+ import { clsx } from "clsx";
14
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
15
  import { useEffect, useMemo, useRef, useState } from "react";
15
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
16
16
  //#region src/ai/components/ChatSidebar.tsx
17
17
  function ConversationRow({ conv, isCurrent, updated, menuItems, openMenu, onOpen }) {
18
18
  const { LinkComponent, strings } = useChatConfig();
@@ -91,8 +91,7 @@ function ChatSidebar({ actions = true, top }) {
91
91
  drawer: drawer ? {
92
92
  open: drawerOpen,
93
93
  onClose: closeDrawer,
94
- label: tSidebar.drawerLabel,
95
- closeLabel: tSidebar.closeSidebar
94
+ label: tSidebar.drawerLabel
96
95
  } : void 0,
97
96
  onToggle: toggleSidebar,
98
97
  toggleLabels: {
@@ -119,15 +118,15 @@ function ChatSidebar({ actions = true, top }) {
119
118
  current: filteredConversations.find((conv) => conv.id === activeConversationId),
120
119
  onSelect: (conv) => navigation.toConversation(conv.id)
121
120
  },
122
- top: (top || actions) && /* @__PURE__ */ jsxs(Fragment$1, { children: [top?.({ collapsed: sidebarCollapsed }), actions && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
121
+ top: (top || actions) && /* @__PURE__ */ jsxs(Fragment, { children: [top?.({ collapsed: sidebarCollapsed }), actions && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
123
122
  className: "flex flex-col gap-0.5 px-2 pt-2 pb-1",
124
123
  children: [/* @__PURE__ */ jsxs("button", {
125
124
  type: "button",
126
125
  onClick: handleNewChat,
127
126
  className: "flex items-center h-9 px-2 gap-3 rounded-lg font-medium transition-colors hover:chat-tint",
128
127
  title: tSidebar.newChat,
129
- children: [/* @__PURE__ */ jsx(TbEdit, { className: cx("flex-shrink-0", "w-4 h-4") }), /* @__PURE__ */ jsx("span", {
130
- className: cx("text-sm transition-opacity duration-200", sidebarCollapsed ? "opacity-0 w-0 overflow-hidden" : "opacity-100"),
128
+ children: [/* @__PURE__ */ jsx(TbEdit, { className: clsx("flex-shrink-0", "w-4 h-4") }), /* @__PURE__ */ jsx("span", {
129
+ className: clsx("text-sm transition-opacity duration-200", sidebarCollapsed ? "opacity-0 w-0 overflow-hidden" : "opacity-100"),
131
130
  children: tSidebar.newChat
132
131
  })]
133
132
  }), attachmentsAvailable && /* @__PURE__ */ jsxs(LinkComponent, {
@@ -136,7 +135,7 @@ function ChatSidebar({ actions = true, top }) {
136
135
  title: tSidebar.attachments,
137
136
  onClick: closeDrawer,
138
137
  children: [/* @__PURE__ */ jsx(FaRegFileImage, { className: "flex-shrink-0 w-4 h-4" }), /* @__PURE__ */ jsx("span", {
139
- className: cx("text-sm transition-opacity duration-200", sidebarCollapsed ? "opacity-0 w-0 overflow-hidden" : "opacity-100"),
138
+ className: clsx("text-sm transition-opacity duration-200", sidebarCollapsed ? "opacity-0 w-0 overflow-hidden" : "opacity-100"),
140
139
  children: tSidebar.attachments
141
140
  })]
142
141
  })]
@@ -163,7 +162,7 @@ function ChatSidebar({ actions = true, top }) {
163
162
  })] })] }),
164
163
  footer: /* @__PURE__ */ jsx(ManageProvidersLink, {})
165
164
  });
166
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [(drawer || sidebar !== "hidden") && list, overlays] });
165
+ return /* @__PURE__ */ jsxs(Fragment, { children: [(drawer || sidebar !== "hidden") && list, overlays] });
167
166
  }
168
167
  //#endregion
169
168
  export { ChatSidebar as default };
@@ -8,8 +8,8 @@ import ChatInput from "./ChatInput.js";
8
8
  import ProviderIssueBanner from "./ProviderIssueBanner.js";
9
9
  import { ShareButton } from "./ShareDialog.js";
10
10
  import ChatMessageList from "./ChatMessageList.js";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
12
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
12
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
13
13
  //#region src/ai/components/ChatThread.tsx
14
14
  function ChatThread({ conversationId }) {
15
15
  const chatInputRef = useRef(null);
@@ -92,7 +92,7 @@ function ChatThread({ conversationId }) {
92
92
  disabled: true,
93
93
  conversationId,
94
94
  settingsLeft: /* @__PURE__ */ jsx(ConnectToolsLink, {}),
95
- settingsRight: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ComposerUsage, { children: slots.composerUsage }), /* @__PURE__ */ jsx(ComposerControls, {})] })
95
+ settingsRight: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ComposerUsage, { children: slots.composerUsage }), /* @__PURE__ */ jsx(ComposerControls, {})] })
96
96
  })]
97
97
  });
98
98
  return /* @__PURE__ */ jsx("div", {
@@ -126,8 +126,8 @@ function ChatThread({ conversationId }) {
126
126
  placeholder: currentConversation?.canCollaborate === false ? strings.thread.viewOnly : void 0,
127
127
  conversationId,
128
128
  onEditLastMessage: handleEditLastMessage,
129
- settingsLeft: /* @__PURE__ */ jsxs(Fragment$1, { children: [currentConversation?.isOwner !== false && /* @__PURE__ */ jsx(ShareButton, { conversationId }), /* @__PURE__ */ jsx(ConnectToolsLink, {})] }),
130
- settingsRight: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ComposerUsage, { children: slots.composerUsage }), /* @__PURE__ */ jsx(ComposerControls, {})] })
129
+ settingsLeft: /* @__PURE__ */ jsxs(Fragment, { children: [currentConversation?.isOwner !== false && /* @__PURE__ */ jsx(ShareButton, { conversationId }), /* @__PURE__ */ jsx(ConnectToolsLink, {})] }),
130
+ settingsRight: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ComposerUsage, { children: slots.composerUsage }), /* @__PURE__ */ jsx(ComposerControls, {})] })
131
131
  })
132
132
  })
133
133
  ]
@@ -17,8 +17,8 @@ export declare function ComposerSettings({ left, children }: {
17
17
  export declare function ComposerUsage({ children }: {
18
18
  children: ReactNode;
19
19
  }): import("react").JSX.Element | null;
20
- /** The two selectors every surface carries, bare so they read as text beside
21
- * whatever the surface puts next to them. */
20
+ /** The two selectors every surface carries, reading as text beside whatever
21
+ * the surface puts next to them. */
22
22
  export declare function ComposerControls({ targetSession }: {
23
23
  targetSession?: string | null | undefined;
24
24
  }): import("react").JSX.Element;