@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
@@ -1,29 +1,47 @@
1
1
  import { FaExclamationTriangle } from "../../icons/fa/FaExclamationTriangle.js";
2
+ import { IoSettingsOutline } from "../../icons/io5/IoSettingsOutline.js";
2
3
  import { useChatConfig } from "../core/config.js";
3
- import { providerIssueFor } from "../core/providerIssues.js";
4
+ import { issueDetail, providerIssueFor } from "../core/providerIssues.js";
4
5
  import { useChat } from "../core/ChatProvider.js";
6
+ import { getProviderKeyFromModelId } from "./ModelSelector.js";
5
7
  import { jsx, jsxs } from "react/jsx-runtime";
6
8
  //#region src/ai/components/ProviderIssueBanner.tsx
9
+ /** Why the selected model can't answer, with a way to fix it for the
10
+ * provider's owner, who alone can change its key or endpoint. */
7
11
  function ProviderIssueBanner() {
8
- const { strings } = useChatConfig();
9
- const { models, providerIssues, selectedProvider } = useChat();
12
+ const { strings, extraLinks, LinkComponent } = useChatConfig();
13
+ const { models, providers, providerIssues, selectedProvider, currentUser } = useChat();
10
14
  const selectedModel = models.find((m) => m.id === selectedProvider);
11
15
  const issue = providerIssueFor(providerIssues, selectedModel);
12
- if (!issue) return null;
13
- const title = issue.status === "unauthorized" ? strings.providerIssue.bannerKeyRejected(issue.provider) : strings.providerIssue.bannerUnreachable(issue.provider);
14
- const detail = issue.message || (issue.status === "unauthorized" ? strings.providerIssue.keyRejectedHint : strings.providerIssue.unreachableHint);
16
+ if (!selectedModel || !issue) return null;
17
+ const t = strings.providerIssue;
18
+ const title = issue.status === "unauthorized" ? t.bannerKeyRejected(issue.provider) : t.bannerUnreachable(issue.provider);
19
+ const providerKey = getProviderKeyFromModelId(selectedModel.id);
20
+ const provider = providers.find((p) => `${p.user}:${p.name}` === providerKey);
21
+ const settingsHref = provider?.user === currentUser.username ? extraLinks.providerSettings?.(provider.user, provider.name) : void 0;
15
22
  return /* @__PURE__ */ jsxs("div", {
16
23
  className: "mx-4 mt-2 flex items-start gap-3 p-3 rounded-lg bg-amber-500/10 border border-amber-500/20",
17
- children: [/* @__PURE__ */ jsx(FaExclamationTriangle, { className: "w-4 h-4 text-amber-500 shrink-0 mt-0.5" }), /* @__PURE__ */ jsxs("div", {
18
- className: "flex-1 min-w-0",
19
- children: [/* @__PURE__ */ jsx("p", {
20
- className: "text-sm font-medium text-amber-700",
21
- children: title
22
- }), /* @__PURE__ */ jsx("p", {
23
- className: "text-xs text-amber-600/80 mt-0.5",
24
- children: detail
25
- })]
26
- })]
24
+ children: [
25
+ /* @__PURE__ */ jsx(FaExclamationTriangle, { className: "w-4 h-4 text-amber-500 shrink-0 mt-0.5" }),
26
+ /* @__PURE__ */ jsxs("div", {
27
+ className: "flex-1 min-w-0",
28
+ children: [/* @__PURE__ */ jsx("p", {
29
+ className: "text-sm font-medium text-amber-700",
30
+ children: title
31
+ }), /* @__PURE__ */ jsx("p", {
32
+ className: "text-xs text-amber-600/80 mt-0.5",
33
+ children: issueDetail(t, issue)
34
+ })]
35
+ }),
36
+ settingsHref && /* @__PURE__ */ jsxs(LinkComponent, {
37
+ target: {
38
+ kind: "external",
39
+ href: settingsHref
40
+ },
41
+ className: "flex shrink-0 items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-amber-700 transition-colors hover:bg-amber-500/10",
42
+ children: [/* @__PURE__ */ jsx(IoSettingsOutline, { className: "h-3.5 w-3.5" }), strings.modelPicker.manageProvider]
43
+ })
44
+ ]
27
45
  });
28
46
  }
29
47
  //#endregion
@@ -1,5 +1,5 @@
1
1
  import { LuChevronRight } from "../../icons/lu/LuChevronRight.js";
2
- import cx from "classnames";
2
+ import { clsx } from "clsx";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  //#region src/ai/components/Reasoning.tsx
5
5
  /** The line a turn's reasoning folds under. It opens the reasoning in place,
@@ -12,16 +12,16 @@ function ReasoningToggle({ open, onToggle, shimmer = false, children }) {
12
12
  "aria-expanded": open,
13
13
  className: "group/reasoning -ml-1 flex items-center gap-x-1 rounded-md px-1 py-0.5 text-sm theme-muted-text transition-colors hover:theme-text",
14
14
  children: [/* @__PURE__ */ jsx("span", {
15
- className: cx(shimmer && "animate-shimmer text-shimmer"),
15
+ className: clsx(shimmer && "animate-shimmer text-shimmer"),
16
16
  children
17
- }), /* @__PURE__ */ jsx(LuChevronRight, { className: cx("h-3.5 w-3.5 transition-transform duration-200 motion-reduce:transition-none", open && "rotate-90") })]
17
+ }), /* @__PURE__ */ jsx(LuChevronRight, { className: clsx("h-3.5 w-3.5 transition-transform duration-200 motion-reduce:transition-none", open && "rotate-90") })]
18
18
  });
19
19
  }
20
20
  /** The reasoning itself: smaller and quieter than the answer, hung off a
21
21
  * hairline of the accent so it reads as the assistant's aside. */
22
22
  function ReasoningBody({ className, children }) {
23
23
  return /* @__PURE__ */ jsx("div", {
24
- className: cx("chat-reasoning-body ml-1 mt-1.5 mb-3 pl-4 text-sm leading-relaxed theme-muted-text", className),
24
+ className: clsx("chat-reasoning-body ml-1 mt-1.5 mb-3 pl-4 text-sm leading-relaxed theme-muted-text", className),
25
25
  children
26
26
  });
27
27
  }
@@ -1,12 +1,14 @@
1
1
  import { BiSolidTrashAlt } from "../../icons/bi/BiSolidTrashAlt.js";
2
2
  import { PiShareBold } from "../../icons/pi/PiShareBold.js";
3
+ import { Tooltip } from "../../components/Tooltip.js";
4
+ import { Combobox } from "../../components/Combobox.js";
3
5
  import { ConfirmModal } from "../../components/ConfirmModal.js";
4
6
  import Loader from "../../components/Loader.js";
7
+ import { Select } from "../../components/Select.js";
5
8
  import { useChatConfig } from "../core/config.js";
6
9
  import { useChat } from "../core/ChatProvider.js";
7
- import Dropdown from "../ui/Dropdown.js";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
11
  import { useCallback, useEffect, useState, useTransition } from "react";
9
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
12
  //#region src/ai/components/ShareDialog.tsx
11
13
  function isTeamPermission(p) {
12
14
  return !!p.team && !p.entireOrganization;
@@ -122,6 +124,13 @@ function ShareDialog({ conversationId, isOpen, onClose }) {
122
124
  }, []);
123
125
  if (!sharing) return null;
124
126
  const teamPermissions = permissions.filter(isTeamPermission);
127
+ const permissionItems = [{
128
+ label: t.viewOnly,
129
+ value: "view"
130
+ }, {
131
+ label: t.canCollaborate,
132
+ value: "collaborate"
133
+ }];
125
134
  const availableTeams = teams.filter((team) => !permissions.some((p) => p.team === team.id));
126
135
  return /* @__PURE__ */ jsx(ConfirmModal, {
127
136
  open: isOpen,
@@ -140,7 +149,7 @@ function ShareDialog({ conversationId, isOpen, onClose }) {
140
149
  size: 24,
141
150
  text: strings.modal.loading
142
151
  })
143
- }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
152
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [
144
153
  /* @__PURE__ */ jsxs("div", {
145
154
  className: "border theme-border rounded-lg p-3",
146
155
  children: [/* @__PURE__ */ jsx("h3", {
@@ -193,24 +202,25 @@ function ShareDialog({ conversationId, isOpen, onClose }) {
193
202
  children: perm.teamName || perm.team
194
203
  }), /* @__PURE__ */ jsxs("div", {
195
204
  className: "flex items-center gap-2",
196
- children: [/* @__PURE__ */ jsx(Dropdown, {
197
- options: [{
198
- label: t.viewOnly,
199
- value: "view"
200
- }, {
201
- label: t.canCollaborate,
202
- value: "collaborate"
203
- }],
204
- value: perm.permission,
205
- onChange: (val) => handleTeamPermissionChange(perm.team, val),
206
- wrapperClassName: "w-40",
207
- textBoxClassName: "text-xs border theme-border rounded px-2 py-1"
208
- }), /* @__PURE__ */ jsx("button", {
209
- type: "button",
210
- onClick: () => handleRemoveTeam(perm.team),
211
- className: "p-1 rounded hover:bg-red-500/10",
212
- title: t.remove,
213
- children: /* @__PURE__ */ jsx(BiSolidTrashAlt, { className: "w-3 h-3 text-red-500" })
205
+ children: [/* @__PURE__ */ jsx("div", {
206
+ className: "w-40",
207
+ children: /* @__PURE__ */ jsx(Select, {
208
+ items: permissionItems,
209
+ value: perm.permission,
210
+ onValueChange: (level) => {
211
+ if (level !== null) handleTeamPermissionChange(perm.team, level);
212
+ },
213
+ "aria-label": perm.teamName || perm.team
214
+ })
215
+ }), /* @__PURE__ */ jsx(Tooltip, {
216
+ content: t.remove,
217
+ children: /* @__PURE__ */ jsx("button", {
218
+ type: "button",
219
+ onClick: () => handleRemoveTeam(perm.team),
220
+ className: "p-1 rounded hover:bg-red-500/10",
221
+ "aria-label": `${t.remove} ${perm.teamName || perm.team}`,
222
+ children: /* @__PURE__ */ jsx(BiSolidTrashAlt, { className: "w-3 h-3 text-red-500" })
223
+ })
214
224
  })]
215
225
  })]
216
226
  }, perm.team))
@@ -218,19 +228,17 @@ function ShareDialog({ conversationId, isOpen, onClose }) {
218
228
  className: "text-sm theme-muted-text mb-3",
219
229
  children: t.noGroups
220
230
  }),
221
- availableTeams.length > 0 && /* @__PURE__ */ jsx("div", {
222
- className: "flex items-center gap-2",
223
- children: /* @__PURE__ */ jsx(Dropdown, {
224
- options: availableTeams.map((team) => ({
225
- label: team.name,
226
- value: team.id
227
- })),
228
- value: "",
229
- onChange: (val) => handleAddTeam(val),
230
- placeholder: t.addGroups,
231
- wrapperClassName: "flex-1",
232
- textBoxClassName: "text-sm border theme-border rounded px-2 py-1.5 w-full"
233
- })
231
+ availableTeams.length > 0 && /* @__PURE__ */ jsx(Combobox, {
232
+ items: availableTeams.map((team) => ({
233
+ label: team.name,
234
+ value: team.id
235
+ })),
236
+ value: null,
237
+ onValueChange: (teamId) => {
238
+ if (teamId !== null) handleAddTeam(teamId);
239
+ },
240
+ placeholder: t.addGroups,
241
+ "aria-label": t.addGroups
234
242
  })
235
243
  ]
236
244
  }),
@@ -247,7 +255,7 @@ function ShareButton({ conversationId, disabled = false }) {
247
255
  const { adapter } = useChat();
248
256
  const [isOpen, setIsOpen] = useState(false);
249
257
  if (!adapter.sharing) return null;
250
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("button", {
258
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("button", {
251
259
  type: "button",
252
260
  onClick: () => setIsOpen(true),
253
261
  disabled,
@@ -11,16 +11,26 @@ export interface SlashMenuConfig {
11
11
  onOpen?: (() => void) | undefined;
12
12
  }
13
13
  export declare function slashMatches(input: string, commands: SlashCommandOption[]): SlashCommandOption[];
14
- /** The palette's open state and keys; the caller owns the input. */
14
+ /** The palette's open state and keys; the caller owns the input.
15
+ * Base UI's Autocomplete drives a single-line input, and its arrow keys would take the caret
16
+ * from a multi-line composer, so the textarea stays a textbox that points at the list:
17
+ * spread `inputProps` on it. */
15
18
  export declare function useSlashMenu(input: string, config: SlashMenuConfig | undefined, setInput: (value: string) => void): {
16
19
  open: boolean;
17
20
  matches: SlashCommandOption[];
18
21
  active: number;
19
22
  choose: (name: string) => void;
20
23
  handleKey: (e: KeyboardEvent<HTMLTextAreaElement>) => boolean;
24
+ listId: string;
25
+ inputProps: {
26
+ 'aria-autocomplete': 'list';
27
+ 'aria-controls': string | undefined;
28
+ 'aria-activedescendant': string | undefined;
29
+ };
21
30
  };
22
- export declare function SlashMenu({ label, matches, active, onChoose, }: {
31
+ export declare function SlashMenu({ label, listId, matches, active, onChoose, }: {
23
32
  label: string;
33
+ listId: string;
24
34
  matches: SlashCommandOption[];
25
35
  active: number;
26
36
  onChoose: (name: string) => void;
@@ -1,6 +1,7 @@
1
- import cx from "classnames";
2
- import { useEffect, useState } from "react";
1
+ import { panelClassName, panelItemClassName } from "../../components/floating.js";
2
+ import { clsx } from "clsx";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { useEffect, useId, useState } from "react";
4
5
  //#region src/ai/components/SlashMenu.tsx
5
6
  var MAX_SHOWN = 8;
6
7
  var TYPING_NAME = /^\/([\w:-]*)$/;
@@ -10,8 +11,12 @@ function slashMatches(input, commands) {
10
11
  const query = (typed[1] ?? "").toLowerCase();
11
12
  return commands.filter((c) => c.name.toLowerCase().startsWith(query)).slice(0, MAX_SHOWN);
12
13
  }
13
- /** The palette's open state and keys; the caller owns the input. */
14
+ /** The palette's open state and keys; the caller owns the input.
15
+ * Base UI's Autocomplete drives a single-line input, and its arrow keys would take the caret
16
+ * from a multi-line composer, so the textarea stays a textbox that points at the list:
17
+ * spread `inputProps` on it. */
14
18
  function useSlashMenu(input, config, setInput) {
19
+ const listId = useId();
15
20
  const [active, setActive] = useState(0);
16
21
  const [dismissed, setDismissed] = useState(false);
17
22
  const matches = config ? slashMatches(input, config.commands) : [];
@@ -30,6 +35,7 @@ function useSlashMenu(input, config, setInput) {
30
35
  setDismissed(false);
31
36
  }
32
37
  const choose = (name) => setInput(`/${name} `);
38
+ const shown = Math.min(active, matches.length - 1);
33
39
  /** True when the key belonged to the menu. */
34
40
  const handleKey = (e) => {
35
41
  if (!open) return false;
@@ -43,7 +49,7 @@ function useSlashMenu(input, config, setInput) {
43
49
  case "Tab":
44
50
  case "Enter": {
45
51
  if (e.shiftKey) return false;
46
- const pick = matches[Math.min(active, matches.length - 1)];
52
+ const pick = matches[shown];
47
53
  if (!pick) return false;
48
54
  choose(pick.name);
49
55
  break;
@@ -59,29 +65,39 @@ function useSlashMenu(input, config, setInput) {
59
65
  return {
60
66
  open,
61
67
  matches,
62
- active,
68
+ active: shown,
63
69
  choose,
64
- handleKey
70
+ handleKey,
71
+ listId,
72
+ inputProps: {
73
+ "aria-autocomplete": "list",
74
+ "aria-controls": open ? listId : void 0,
75
+ "aria-activedescendant": open ? optionId(listId, shown) : void 0
76
+ }
65
77
  };
66
78
  }
67
- function SlashMenu({ label, matches, active, onChoose }) {
79
+ var optionId = (listId, index) => `${listId}-${index}`;
80
+ function SlashMenu({ label, listId, matches, active, onChoose }) {
68
81
  return /* @__PURE__ */ jsx("div", {
82
+ id: listId,
69
83
  role: "listbox",
70
84
  "aria-label": label,
71
85
  "data-testid": "slash-menu",
72
- className: "absolute bottom-full left-0 right-0 mb-2 z-20 overflow-hidden rounded-xl border theme-border bg-(--theme-panel-bg) shadow-lg",
73
- children: matches.map((c, i) => /* @__PURE__ */ jsxs("button", {
74
- type: "button",
86
+ className: clsx("absolute bottom-full left-0 right-0 z-20 mb-2 overflow-hidden py-1", panelClassName),
87
+ children: matches.map((c, i) => /* @__PURE__ */ jsxs("div", {
88
+ id: optionId(listId, i),
75
89
  role: "option",
90
+ tabIndex: -1,
76
91
  "aria-selected": i === active,
92
+ "data-highlighted": i === active || void 0,
77
93
  onMouseDown: (e) => e.preventDefault(),
78
94
  onClick: () => onChoose(c.name),
79
- className: cx("flex w-full items-baseline gap-3 px-3 py-1.5 text-left text-sm", i === active ? "theme-hover" : "hover:theme-hover"),
95
+ className: clsx("items-baseline gap-3", panelItemClassName),
80
96
  children: [/* @__PURE__ */ jsxs("span", {
81
- className: "font-mono theme-text",
97
+ className: "font-mono",
82
98
  children: ["/", c.name]
83
99
  }), c.description && /* @__PURE__ */ jsx("span", {
84
- className: "truncate text-xs theme-muted-text",
100
+ className: "truncate text-xs text-(--theme-muted-text-color)",
85
101
  children: c.description
86
102
  })]
87
103
  }, c.name))
@@ -1,9 +1,9 @@
1
1
  import { FaStop } from "../../../icons/fa/FaStop.js";
2
2
  import { LoaderIcon } from "../../../components/StatusIcons.js";
3
3
  import { useChatConfig } from "../../core/config.js";
4
- import cx from "classnames";
5
- import { useEffect, useRef, useState } from "react";
4
+ import { clsx } from "clsx";
6
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { useEffect, useRef, useState } from "react";
7
7
  import { DateTime } from "luxon";
8
8
  //#region src/ai/components/agent/ActivityLine.tsx
9
9
  /** The agent status words: one is picked per turn and held until it ends. */
@@ -142,7 +142,7 @@ function ActivityLine({ startedAt, inputTokens, outputTokens, onStop, stopping =
142
142
  disabled: stopping,
143
143
  "aria-label": strings.input.stopGenerating,
144
144
  title: strings.input.stopGenerating,
145
- className: cx("ml-auto inline-flex h-7 items-center gap-1.5 rounded-md px-2 text-xs theme-muted-text transition-colors", "hover:theme-hover hover:theme-text disabled:cursor-not-allowed disabled:opacity-50"),
145
+ className: clsx("ml-auto inline-flex h-7 items-center gap-1.5 rounded-md px-2 text-xs theme-muted-text transition-colors", "hover:theme-hover hover:theme-text disabled:cursor-not-allowed disabled:opacity-50"),
146
146
  children: [/* @__PURE__ */ jsx(FaStop, { className: "h-3 w-3" }), strings.activity.stop]
147
147
  })
148
148
  ]
@@ -11,14 +11,14 @@ import { useChatConfig } from "../../core/config.js";
11
11
  import Markdown from "../../ui/Markdown.js";
12
12
  import { chatProseClasses } from "../../ui/prose.js";
13
13
  import { ReasoningBody, ReasoningToggle } from "../Reasoning.js";
14
- import cx from "classnames";
14
+ import { clsx } from "clsx";
15
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
15
16
  import { useEffect, useMemo, useState } from "react";
16
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
17
17
  //#region src/ai/components/agent/AgentMessageParts.tsx
18
18
  var COLLAPSED_RESULT_LINES = 12;
19
19
  function LineSpans({ text, tokens, emphasis }) {
20
20
  const pieces = tokens ?? [{ content: text }];
21
- if (!emphasis || emphasis.length === 0) return /* @__PURE__ */ jsx(Fragment$1, { children: pieces.map((t, i) => /* @__PURE__ */ jsx("span", {
21
+ if (!emphasis || emphasis.length === 0) return /* @__PURE__ */ jsx(Fragment, { children: pieces.map((t, i) => /* @__PURE__ */ jsx("span", {
22
22
  style: t.color ? { color: t.color } : void 0,
23
23
  children: t.content
24
24
  }, i)) });
@@ -41,7 +41,7 @@ function LineSpans({ text, tokens, emphasis }) {
41
41
  }
42
42
  offset += t.content.length;
43
43
  }
44
- return /* @__PURE__ */ jsx(Fragment$1, { children: out });
44
+ return /* @__PURE__ */ jsx(Fragment, { children: out });
45
45
  }
46
46
  function DiffRows({ rows, lang }) {
47
47
  const isDark = useCssIsDark();
@@ -68,7 +68,7 @@ function DiffRows({ rows, lang }) {
68
68
  return /* @__PURE__ */ jsx("div", {
69
69
  className: "overflow-x-auto rounded-md border theme-border font-mono text-xs leading-5",
70
70
  children: rows.map((row, i) => /* @__PURE__ */ jsxs("div", {
71
- className: cx("flex whitespace-pre", row.kind === "add" && "bg-green-500/15", row.kind === "del" && "bg-red-500/15", row.kind === "gap" && "theme-muted-text"),
71
+ className: clsx("flex whitespace-pre", row.kind === "add" && "bg-green-500/15", row.kind === "del" && "bg-red-500/15", row.kind === "gap" && "theme-muted-text"),
72
72
  children: [
73
73
  numbered && /* @__PURE__ */ jsx("span", {
74
74
  className: "w-10 shrink-0 select-none text-right pr-2 theme-muted-text",
@@ -207,11 +207,11 @@ function ToolCallBlock({ part }) {
207
207
  ]
208
208
  })]
209
209
  }),
210
- /* @__PURE__ */ jsx(LuChevronRight, { className: cx("w-3.5 h-3.5 mt-1 shrink-0 theme-muted-text transition-transform", expanded && "rotate-90") })
210
+ /* @__PURE__ */ jsx(LuChevronRight, { className: clsx("w-3.5 h-3.5 mt-1 shrink-0 theme-muted-text transition-transform", expanded && "rotate-90") })
211
211
  ]
212
212
  }),
213
213
  !isDiff && /* @__PURE__ */ jsx("div", {
214
- className: cx("ml-5 mt-0.5 text-[13px]", part.status === "error" ? "text-red-600" : "theme-muted-text"),
214
+ className: clsx("ml-5 mt-0.5 text-[13px]", part.status === "error" ? "text-red-600" : "theme-muted-text"),
215
215
  children: expanded ? null : summary
216
216
  }),
217
217
  expanded && !isDiff && /* @__PURE__ */ jsxs("div", {
@@ -251,7 +251,7 @@ function SubagentCard({ part }) {
251
251
  className: "flex min-h-6 items-start gap-2 w-full text-left",
252
252
  children: [
253
253
  part.status === "running" ? /* @__PURE__ */ jsx(LoaderIcon, { className: "w-3.5 h-3.5 mt-[3px] animate-spin theme-muted-text" }) : /* @__PURE__ */ jsx("span", {
254
- className: cx("leading-none", part.status === "failed" ? "text-red-500" : "text-green-600"),
254
+ className: clsx("leading-none", part.status === "failed" ? "text-red-500" : "text-green-600"),
255
255
  style: color && part.status !== "failed" ? { color } : void 0,
256
256
  children: "●"
257
257
  }),
@@ -269,10 +269,10 @@ function SubagentCard({ part }) {
269
269
  ]
270
270
  })]
271
271
  }),
272
- canExpand && /* @__PURE__ */ jsx(LuChevronRight, { className: cx("w-3.5 h-3.5 mt-1 shrink-0 theme-muted-text transition-transform", expanded && "rotate-90") })
272
+ canExpand && /* @__PURE__ */ jsx(LuChevronRight, { className: clsx("w-3.5 h-3.5 mt-1 shrink-0 theme-muted-text transition-transform", expanded && "rotate-90") })
273
273
  ]
274
274
  }), /* @__PURE__ */ jsx("div", {
275
- className: cx("ml-5 mt-0.5 text-[13px]", part.status === "failed" ? "text-red-600" : "theme-muted-text"),
275
+ className: clsx("ml-5 mt-0.5 text-[13px]", part.status === "failed" ? "text-red-600" : "theme-muted-text"),
276
276
  children: expanded ? /* @__PURE__ */ jsxs("div", {
277
277
  className: "space-y-1",
278
278
  children: [actions.length > 0 && /* @__PURE__ */ jsxs("ul", {
@@ -297,7 +297,7 @@ function ConfirmApproval({ part, onAnswer }) {
297
297
  path: [t.allowPath, t.denyPath],
298
298
  call: [t.allowCall, t.denyCall]
299
299
  }[part.subject ?? "command"];
300
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
300
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
301
301
  part.command && /* @__PURE__ */ jsx("pre", {
302
302
  className: "overflow-x-auto rounded-md bg-(--theme-muted-panel-bg) p-2 font-mono text-xs whitespace-pre-wrap",
303
303
  children: part.command
@@ -376,7 +376,7 @@ function AskApproval({ part, onAnswer }) {
376
376
  kind: "ask",
377
377
  text
378
378
  });
379
- if (!onAnswer) return /* @__PURE__ */ jsxs(Fragment$1, { children: [
379
+ if (!onAnswer) return /* @__PURE__ */ jsxs(Fragment, { children: [
380
380
  part.question && /* @__PURE__ */ jsx("div", {
381
381
  className: "text-sm",
382
382
  children: part.question
@@ -393,7 +393,7 @@ function AskApproval({ part, onAnswer }) {
393
393
  children: t.approvalPending
394
394
  })
395
395
  ] });
396
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [part.question && /* @__PURE__ */ jsx("div", {
396
+ return /* @__PURE__ */ jsxs(Fragment, { children: [part.question && /* @__PURE__ */ jsx("div", {
397
397
  className: "text-sm",
398
398
  children: part.question
399
399
  }), own === null ? /* @__PURE__ */ jsxs("div", {
@@ -457,7 +457,7 @@ function ApprovalBlock({ part, onApprovalAnswer }) {
457
457
  function PlanApproval({ part }) {
458
458
  const { strings } = useChatConfig();
459
459
  const t = strings.agentTranscript;
460
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
460
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
461
461
  className: "text-xs theme-muted-text",
462
462
  children: t.planPending
463
463
  }), part.plan && /* @__PURE__ */ jsx("div", {
@@ -480,7 +480,7 @@ function TodoSnapshotBlock({ part }) {
480
480
  }), /* @__PURE__ */ jsx("ul", {
481
481
  className: "space-y-0.5 text-sm",
482
482
  children: part.todos.map((todo) => /* @__PURE__ */ jsxs("li", {
483
- className: cx("flex items-start gap-2", todo.status === "completed" && "line-through theme-muted-text", todo.status === "in_progress" && "font-semibold"),
483
+ className: clsx("flex items-start gap-2", todo.status === "completed" && "line-through theme-muted-text", todo.status === "in_progress" && "font-semibold"),
484
484
  children: [/* @__PURE__ */ jsx("span", {
485
485
  className: "select-none font-mono",
486
486
  children: todo.status === "completed" ? "✔" : todo.status === "in_progress" ? "■" : "□"
@@ -508,7 +508,7 @@ function NoticeBlock({ part }) {
508
508
  children: [/* @__PURE__ */ jsx("span", {
509
509
  className: "min-w-0 flex-1 whitespace-pre-wrap",
510
510
  children: part.text
511
- }), /* @__PURE__ */ jsx(LuChevronRight, { className: cx("mt-0.5 h-3.5 w-3.5 shrink-0 transition-transform", expanded && "rotate-90") })]
511
+ }), /* @__PURE__ */ jsx(LuChevronRight, { className: clsx("mt-0.5 h-3.5 w-3.5 shrink-0 transition-transform", expanded && "rotate-90") })]
512
512
  }), expanded && /* @__PURE__ */ jsx("div", {
513
513
  className: "ml-4 mt-1 border-l-2 theme-border pl-3 text-sm theme-muted-text",
514
514
  children: /* @__PURE__ */ jsx(Markdown, { children: part.detail })
@@ -516,7 +516,7 @@ function NoticeBlock({ part }) {
516
516
  });
517
517
  }
518
518
  return /* @__PURE__ */ jsx("div", {
519
- className: cx("my-1 text-xs rounded-md px-2.5 py-1.5", part.kind === "error" ? "bg-red-500/10 text-red-700" : "bg-yellow-500/10 text-yellow-700"),
519
+ className: clsx("my-1 text-xs rounded-md px-2.5 py-1.5", part.kind === "error" ? "bg-red-500/10 text-red-700" : "bg-yellow-500/10 text-yellow-700"),
520
520
  "data-testid": `${part.kind}-part`,
521
521
  children: part.text
522
522
  });
@@ -575,7 +575,7 @@ function ReasoningBlock({ part, isStreaming }) {
575
575
  }
576
576
  function TextBlock({ part, isStreaming }) {
577
577
  return /* @__PURE__ */ jsx("div", {
578
- className: cx(chatProseClasses, "[&:not(:first-child)]:mt-4"),
578
+ className: clsx(chatProseClasses, "[&:not(:first-child)]:mt-4"),
579
579
  children: /* @__PURE__ */ jsx(Markdown, {
580
580
  isStreaming: isStreaming ?? false,
581
581
  children: part.text
@@ -702,10 +702,10 @@ function RollupGroup({ members, message }) {
702
702
  className: "font-mono text-[13px] theme-muted-text min-w-0 truncate",
703
703
  children: sentence
704
704
  }),
705
- /* @__PURE__ */ jsx(LuChevronRight, { className: cx("w-3.5 h-3.5 shrink-0 theme-muted-text transition-transform", expanded && "rotate-90") })
705
+ /* @__PURE__ */ jsx(LuChevronRight, { className: clsx("w-3.5 h-3.5 shrink-0 theme-muted-text transition-transform", expanded && "rotate-90") })
706
706
  ]
707
707
  }), /* @__PURE__ */ jsx("div", {
708
- className: cx("ml-1.5 mt-0.5 rounded-md", expanded ? "bg-(--theme-muted-panel-bg)/40 px-2" : "hidden"),
708
+ className: clsx("ml-1.5 mt-0.5 rounded-md", expanded ? "bg-(--theme-muted-panel-bg)/40 px-2" : "hidden"),
709
709
  children: members.map((m) => /* @__PURE__ */ jsx(PartDispatch, {
710
710
  part: m.part,
711
711
  message
@@ -1,6 +1,7 @@
1
+ import { Select } from "../../../components/Select.js";
1
2
  import { isNamedPermissionMode, permissionModesUpTo } from "../../agent/permissions.js";
2
3
  import { useChatConfig } from "../../core/config.js";
3
- import Dropdown from "../../ui/Dropdown.js";
4
+ import { smallChipClassName } from "../../ui/chip.js";
4
5
  import { jsx } from "react/jsx-runtime";
5
6
  //#region src/ai/components/agent/PermissionPicker.tsx
6
7
  var LABEL_KEY = {
@@ -17,22 +18,23 @@ function PermissionPicker({ mode, onPick, ceiling, accepted, disabled = false })
17
18
  const t = useChatConfig().strings.permissions;
18
19
  const current = mode ?? "accept-edits";
19
20
  const named = isNamedPermissionMode(current) ? current : void 0;
20
- const options = permissionModesUpTo(ceiling, accepted).map((m) => ({
21
+ const items = permissionModesUpTo(ceiling, accepted).map((m) => ({
21
22
  value: m,
22
23
  label: t[LABEL_KEY[m]],
23
24
  description: t[`${LABEL_KEY[m]}Hint`]
24
25
  }));
25
- return /* @__PURE__ */ jsx(Dropdown, {
26
- options,
26
+ return /* @__PURE__ */ jsx(Select, {
27
+ "aria-label": t.choose,
28
+ items,
27
29
  value: current,
28
- onChange: (value) => onPick(value),
30
+ onValueChange: (value) => value && onPick(value),
29
31
  disabled,
30
- variant: "bare",
31
- ariaLabel: t.choose,
32
- ...named ? { hint: t[`${LABEL_KEY[named]}Hint`] } : {},
33
- ...options.some((o) => o.value === current) ? {} : { valueLabel: named ? t[LABEL_KEY[named]] : current },
34
- textBoxClassName: "rounded-md px-1.5 py-0.5 text-[11px] theme-muted-text transition-colors hover:theme-muted-panel hover:theme-text",
35
- listClassName: "w-64"
32
+ triggerTooltip: named ? t[`${LABEL_KEY[named]}Hint`] : void 0,
33
+ trigger: /* @__PURE__ */ jsx("button", {
34
+ type: "button",
35
+ className: smallChipClassName,
36
+ children: named ? t[LABEL_KEY[named]] : current
37
+ })
36
38
  });
37
39
  }
38
40
  //#endregion
@@ -1,5 +1,6 @@
1
1
  import { type ReactNode } from 'react';
2
- import { type OpenMenu, type RowMenuItem } from '../../list/index.js';
2
+ import { type OpenMenu } from '../../components/ContextMenu.js';
3
+ import type { MenuEntry } from '../../components/MenuEntries.js';
3
4
  import type { ConversationSummary } from '../types.js';
4
5
  export type ConversationGroupKey = 'groupToday' | 'groupYesterday' | 'groupThisWeek' | 'groupThisMonth' | 'groupOlder';
5
6
  /** Conversations by how long ago they started, newest group first, leaving
@@ -13,11 +14,8 @@ export declare function groupConversationsByDate<T extends {
13
14
  /** What a conversation row offers behind its menu (rename, share, download,
14
15
  * delete) and the menu and dialogs that carry them out, for any list of
15
16
  * conversations. Render `overlays` once beside the list. */
16
- export declare function useConversationActions({ menuZClassName, }?: {
17
- /** The menu's stacking class, for a list inside a layer above the page. */
18
- menuZClassName?: string;
19
- }): {
20
- menuItems: (conv: ConversationSummary) => RowMenuItem[];
17
+ export declare function useConversationActions(): {
18
+ menuItems: (conv: ConversationSummary) => MenuEntry[];
21
19
  openMenu: OpenMenu;
22
20
  overlays: ReactNode;
23
21
  };