@parallelworks/ui 0.18.0 → 0.19.1

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 (349) hide show
  1. package/README.md +86 -6
  2. package/dist/ai/adapter/memoryStore.d.ts +8 -0
  3. package/dist/ai/adapter/memoryStore.js +152 -0
  4. package/dist/ai/adapter/mock/index.d.ts +2 -0
  5. package/dist/ai/adapter/mock/index.js +3 -0
  6. package/dist/ai/adapter/mock/mockAdapter.d.ts +4 -0
  7. package/dist/ai/adapter/mock/mockAdapter.js +81 -0
  8. package/dist/ai/adapter/openai/createOpenAIStream.d.ts +9 -0
  9. package/dist/ai/adapter/openai/createOpenAIStream.js +33 -0
  10. package/dist/ai/adapter/openai/errors.d.ts +3 -0
  11. package/dist/ai/adapter/openai/errors.js +37 -0
  12. package/dist/ai/adapter/openai/index.d.ts +6 -0
  13. package/dist/ai/adapter/openai/index.js +6 -0
  14. package/dist/ai/adapter/openai/openaiAdapter.d.ts +9 -0
  15. package/dist/ai/adapter/openai/openaiAdapter.js +54 -0
  16. package/dist/ai/adapter/openai/responses.d.ts +4 -0
  17. package/dist/ai/adapter/openai/responses.js +108 -0
  18. package/dist/ai/adapter/openai/sse.d.ts +24 -0
  19. package/dist/ai/adapter/openai/sse.js +112 -0
  20. package/dist/ai/adapter/openai/wire.d.ts +40 -0
  21. package/dist/ai/adapter/types.d.ts +131 -0
  22. package/dist/ai/adapter/types.js +11 -0
  23. package/dist/ai/agent/classifier.d.ts +2 -0
  24. package/dist/ai/agent/classifier.js +12 -0
  25. package/dist/ai/agent/diff.d.ts +35 -0
  26. package/dist/ai/agent/diff.js +223 -0
  27. package/dist/ai/agent/diffHighlight.d.ts +6 -0
  28. package/dist/ai/agent/diffHighlight.js +101 -0
  29. package/dist/ai/agent/index.d.ts +6 -0
  30. package/dist/ai/agent/permissions.d.ts +11 -0
  31. package/dist/ai/agent/permissions.js +29 -0
  32. package/dist/ai/agent/toolfmt.d.ts +18 -0
  33. package/dist/ai/agent/toolfmt.js +383 -0
  34. package/dist/ai/agent/transcript.d.ts +38 -0
  35. package/dist/ai/agent/transcript.js +127 -0
  36. package/dist/ai/ai.css +325 -0
  37. package/dist/ai/components/AllocationSelector.d.ts +4 -0
  38. package/dist/ai/components/AllocationSelector.js +56 -0
  39. package/dist/ai/components/AttachmentManager.d.ts +1 -0
  40. package/dist/ai/components/AttachmentManager.js +144 -0
  41. package/dist/ai/components/AttachmentUpload.d.ts +24 -0
  42. package/dist/ai/components/AttachmentUpload.js +179 -0
  43. package/dist/ai/components/BlockedGroupBanner.d.ts +1 -0
  44. package/dist/ai/components/BlockedGroupBanner.js +29 -0
  45. package/dist/ai/components/BranchNavigator.d.ts +8 -0
  46. package/dist/ai/components/BranchNavigator.js +57 -0
  47. package/dist/ai/components/ChatEmptyState.d.ts +3 -0
  48. package/dist/ai/components/ChatEmptyState.js +171 -0
  49. package/dist/ai/components/ChatInput.d.ts +45 -0
  50. package/dist/ai/components/ChatInput.js +265 -0
  51. package/dist/ai/components/ChatLayout.d.ts +5 -0
  52. package/dist/ai/components/ChatLayout.js +15 -0
  53. package/dist/ai/components/ChatMessage.d.ts +24 -0
  54. package/dist/ai/components/ChatMessage.js +338 -0
  55. package/dist/ai/components/ChatMessageList.d.ts +35 -0
  56. package/dist/ai/components/ChatMessageList.js +301 -0
  57. package/dist/ai/components/ChatSidebar.d.ts +5 -0
  58. package/dist/ai/components/ChatSidebar.js +345 -0
  59. package/dist/ai/components/ChatThread.d.ts +3 -0
  60. package/dist/ai/components/ChatThread.js +198 -0
  61. package/dist/ai/components/ComposerChrome.d.ts +18 -0
  62. package/dist/ai/components/ComposerChrome.js +50 -0
  63. package/dist/ai/components/ComposerFrame.d.ts +16 -0
  64. package/dist/ai/components/ComposerFrame.js +33 -0
  65. package/dist/ai/components/DragOverlay.d.ts +5 -0
  66. package/dist/ai/components/DragOverlay.js +20 -0
  67. package/dist/ai/components/ModelSelector.d.ts +6 -0
  68. package/dist/ai/components/ModelSelector.js +343 -0
  69. package/dist/ai/components/ShareDialog.d.ts +11 -0
  70. package/dist/ai/components/ShareDialog.js +260 -0
  71. package/dist/ai/components/SlashMenu.d.ts +28 -0
  72. package/dist/ai/components/SlashMenu.js +91 -0
  73. package/dist/ai/components/agent/ActivityLine.d.ts +21 -0
  74. package/dist/ai/components/agent/ActivityLine.js +151 -0
  75. package/dist/ai/components/agent/AgentMessageParts.d.ts +54 -0
  76. package/dist/ai/components/agent/AgentMessageParts.js +721 -0
  77. package/dist/ai/components/agent/PermissionPicker.d.ts +11 -0
  78. package/dist/ai/components/agent/PermissionPicker.js +38 -0
  79. package/dist/ai/components/attachmentKeys.d.ts +4 -0
  80. package/dist/ai/components/attachmentKeys.js +10 -0
  81. package/dist/ai/core/ChatProvider.d.ts +66 -0
  82. package/dist/ai/core/ChatProvider.js +848 -0
  83. package/dist/ai/core/KeyboardShortcutsProvider.d.ts +5 -0
  84. package/dist/ai/core/KeyboardShortcutsProvider.js +9 -0
  85. package/dist/ai/core/chatReducer.d.ts +114 -0
  86. package/dist/ai/core/chatReducer.js +223 -0
  87. package/dist/ai/core/config.d.ts +47 -0
  88. package/dist/ai/core/config.js +45 -0
  89. package/dist/ai/core/events.d.ts +1 -0
  90. package/dist/ai/core/events.js +4 -0
  91. package/dist/ai/core/exportConversation.d.ts +4 -0
  92. package/dist/ai/core/exportConversation.js +42 -0
  93. package/dist/ai/core/greeting.d.ts +3 -0
  94. package/dist/ai/core/greeting.js +38 -0
  95. package/dist/ai/core/parts.d.ts +11 -0
  96. package/dist/ai/core/parts.js +84 -0
  97. package/dist/ai/core/useDragDrop.d.ts +14 -0
  98. package/dist/ai/core/useDragDrop.js +36 -0
  99. package/dist/ai/core/useKeyboardShortcuts.d.ts +12 -0
  100. package/dist/ai/core/useKeyboardShortcuts.js +77 -0
  101. package/dist/ai/core/useSSEStream.d.ts +34 -0
  102. package/dist/ai/core/useSSEStream.js +98 -0
  103. package/dist/ai/index.d.ts +40 -0
  104. package/dist/ai/index.js +44 -0
  105. package/dist/ai/strings.d.ts +167 -0
  106. package/dist/ai/strings.js +175 -0
  107. package/dist/ai/types.d.ts +236 -0
  108. package/dist/ai/ui/Avatar.d.ts +8 -0
  109. package/dist/ai/ui/Avatar.js +35 -0
  110. package/dist/ai/ui/Dropdown.d.ts +31 -0
  111. package/dist/ai/ui/Dropdown.js +110 -0
  112. package/dist/ai/ui/Markdown.d.ts +8 -0
  113. package/dist/ai/ui/Markdown.js +79 -0
  114. package/dist/ai/ui/Notice.d.ts +21 -0
  115. package/dist/ai/ui/Notice.js +77 -0
  116. package/dist/ai/ui/buttons.d.ts +1 -0
  117. package/dist/ai/ui/codeBreaks.d.ts +16 -0
  118. package/dist/ai/ui/codeBreaks.js +36 -0
  119. package/dist/ai/ui/prose.d.ts +1 -0
  120. package/dist/ai/ui/prose.js +13 -0
  121. package/dist/ai/ui/sidebar.d.ts +81 -0
  122. package/dist/ai/ui/sidebar.js +148 -0
  123. package/dist/ai/utils.d.ts +4 -0
  124. package/dist/ai/utils.js +23 -0
  125. package/dist/assets/{editor.worker-CuBRIwi-.js → editor.worker-BmHUIVG4.js} +194 -163
  126. package/dist/assets/{json.worker-8ytS02vz.js → json.worker-D8bJ92nw.js} +384 -338
  127. package/dist/assets/{yaml.worker-DJC-VUcv.js → yaml.worker-C4gyGAko.js} +15657 -13823
  128. package/dist/components/AddMenu.js +46 -0
  129. package/dist/components/Avatar.d.ts +1 -1
  130. package/dist/components/Avatar.js +46 -0
  131. package/dist/{chunks/BareModal-BtRiQezg.js → components/BareModal.js} +1 -1
  132. package/dist/components/Breadcrumbs.d.ts +1 -1
  133. package/dist/components/Breadcrumbs.js +83 -0
  134. package/dist/components/Button.js +83 -0
  135. package/dist/components/Callout.js +23 -0
  136. package/dist/components/Card.js +31 -0
  137. package/dist/components/CollapsiblePanel.js +77 -0
  138. package/dist/components/ConfirmModal.js +74 -0
  139. package/dist/components/CopyToClipboard.js +81 -0
  140. package/dist/{chunks/CreateModal-BY6DLmur.js → components/CreateModal.js} +10 -189
  141. package/dist/components/DescriptionList.js +42 -0
  142. package/dist/components/Dropdown.d.ts +1 -1
  143. package/dist/components/Dropdown.js +349 -0
  144. package/dist/components/EmptyState.d.ts +1 -1
  145. package/dist/components/EmptyState.js +27 -0
  146. package/dist/components/Filter.js +32 -0
  147. package/dist/components/FilterPill.js +13 -0
  148. package/dist/components/IconButton.js +34 -0
  149. package/dist/components/Indicator.d.ts +2 -2
  150. package/dist/{chunks/Indicator-hBSIxOPK.js → components/Indicator.js} +1 -1
  151. package/dist/components/Input.d.ts +1 -1
  152. package/dist/components/Input.js +88 -0
  153. package/dist/components/LetterBadge.d.ts +1 -1
  154. package/dist/components/LetterBadge.js +13 -0
  155. package/dist/components/Listbox.js +123 -0
  156. package/dist/{chunks/Loader-BXoXTZGc.js → components/Loader.js} +1 -1
  157. package/dist/components/Markdown.js +15 -0
  158. package/dist/components/MarkdownImpl.d.ts +1 -1
  159. package/dist/components/MultiSelect.js +171 -0
  160. package/dist/components/Overview.js +39 -0
  161. package/dist/components/PageHeader.js +194 -0
  162. package/dist/components/Pagination.js +35 -0
  163. package/dist/components/Provider.d.ts +16 -65
  164. package/dist/{chunks/Provider-Ghua9PkN.js → components/Provider.js} +54 -20
  165. package/dist/{chunks/RequiredMark-DfLdYbYZ.js → components/RequiredMark.js} +1 -1
  166. package/dist/components/SectionHeader.js +11 -0
  167. package/dist/components/SettingModeOption.js +30 -0
  168. package/dist/components/SettingRow.d.ts +1 -1
  169. package/dist/components/SettingRow.js +35 -0
  170. package/dist/components/SettingsCard.js +31 -0
  171. package/dist/components/SettingsGroup.d.ts +1 -1
  172. package/dist/components/SettingsGroup.js +17 -0
  173. package/dist/components/Sort.js +42 -0
  174. package/dist/components/StatusBadge.js +63 -0
  175. package/dist/components/SwitchToggle.js +59 -0
  176. package/dist/{chunks/SwitchToggleSmall-FcsaYSTs.js → components/SwitchToggleSmall.js} +1 -1
  177. package/dist/{chunks/Table-4OHjdKdO.js → components/Table.js} +7 -5
  178. package/dist/components/Toggle.js +20 -0
  179. package/dist/{chunks/Tooltip-Crxo_eU_.js → components/Tooltip.js} +6 -4
  180. package/dist/{chunks/StatusBadge-C1Blx_cW.js → components/dropdownUtils.js} +2 -63
  181. package/dist/components/focus.d.ts +2 -0
  182. package/dist/components/focus.js +7 -0
  183. package/dist/components/ghostButton.js +7 -0
  184. package/dist/components/inputClasses.js +4 -0
  185. package/dist/components/keys.d.ts +12 -0
  186. package/dist/components/keys.js +27 -0
  187. package/dist/components/relativeTime.js +32 -0
  188. package/dist/{chunks/useCssIsDark-DHr05dG2.js → components/useCssIsDark.js} +1 -1
  189. package/dist/duration.d.ts +3 -0
  190. package/dist/duration.js +17 -0
  191. package/dist/editor/Editor.js +13 -0
  192. package/dist/editor/EditorField.js +53 -0
  193. package/dist/editor/FormCodePanel.js +173 -0
  194. package/dist/editor/Monaco.d.ts +1 -20
  195. package/dist/editor/Monaco.js +112 -0
  196. package/dist/editor/index.d.ts +2 -1
  197. package/dist/editor/index.js +7 -2
  198. package/dist/editor/themes.js +91 -0
  199. package/dist/editor/workers.js +29 -0
  200. package/dist/editor/yaml.d.ts +5 -0
  201. package/dist/editor/yaml.js +15 -0
  202. package/dist/engine.d.ts +98 -0
  203. package/dist/file-explorer/FileExplorer.d.ts +11 -2
  204. package/dist/file-explorer/FileExplorer.js +1402 -0
  205. package/dist/file-explorer/FileExplorerContext.d.ts +1 -1
  206. package/dist/file-explorer/FileExplorerContext.js +370 -0
  207. package/dist/file-explorer/FilePreview/CodePreviewEditor.d.ts +1 -1
  208. package/dist/{chunks/CodePreviewEditor-4lx3kE-w.js → file-explorer/FilePreview/CodePreviewEditor.js} +3 -2
  209. package/dist/file-explorer/FilePreview/Inline.js +45 -0
  210. package/dist/file-explorer/FilePreview/StreamedBadge.js +16 -0
  211. package/dist/file-explorer/FilePreview/Viewer.js +526 -0
  212. package/dist/file-explorer/FilePreview/index.js +266 -0
  213. package/dist/file-explorer/FilePreview/parse.js +63 -0
  214. package/dist/file-explorer/FilePreview/previewCache.js +98 -0
  215. package/dist/file-explorer/FilePreview/previewType.d.ts +1 -1
  216. package/dist/file-explorer/FilePreview/previewType.js +151 -0
  217. package/dist/file-explorer/FilePreview/readCappedBytes.js +196 -0
  218. package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +95 -0
  219. package/dist/file-explorer/FilePreview/useObjectText.js +109 -0
  220. package/dist/file-explorer/FilePreview/usePresignedUrl.js +73 -0
  221. package/dist/file-explorer/FileRow.d.ts +1 -1
  222. package/dist/file-explorer/FileRow.js +165 -0
  223. package/dist/file-explorer/FileRowsWindow.js +92 -0
  224. package/dist/file-explorer/FileTable.js +172 -0
  225. package/dist/file-explorer/FileTableHeaders.js +49 -0
  226. package/dist/file-explorer/LoadMoreRow.js +46 -0
  227. package/dist/file-explorer/TreeView.js +376 -0
  228. package/dist/file-explorer/helpers.d.ts +4 -4
  229. package/dist/file-explorer/helpers.js +537 -0
  230. package/dist/file-explorer/index.d.ts +3 -3
  231. package/dist/file-explorer/index.js +7 -5705
  232. package/dist/file-explorer/lib/batch.js +39 -0
  233. package/dist/file-explorer/lib/errors.js +9 -0
  234. package/dist/file-explorer/lib/paging.js +124 -0
  235. package/dist/file-explorer/lib/types.d.ts +6 -1
  236. package/dist/file-explorer/lib/utils.d.ts +1 -3
  237. package/dist/file-explorer/lib/utils.js +322 -0
  238. package/dist/file-explorer/toasts.js +400 -0
  239. package/dist/file-explorer/treeRows.js +73 -0
  240. package/dist/file-explorer/useNearEnd.d.ts +1 -1
  241. package/dist/file-explorer/useNearEnd.js +27 -0
  242. package/dist/form/FieldWrapper.d.ts +2 -2
  243. package/dist/form/FieldWrapper.js +54 -0
  244. package/dist/form/Fields/BooleanField.js +51 -0
  245. package/dist/form/Fields/CheckboxGroupField.js +72 -0
  246. package/dist/form/Fields/ColorField.js +33 -0
  247. package/dist/form/Fields/DropdownField.js +49 -0
  248. package/dist/form/Fields/DurationField.js +130 -0
  249. package/dist/form/Fields/LabelField.js +19 -0
  250. package/dist/form/Fields/MultiDropdownField.js +40 -0
  251. package/dist/form/Fields/NumberField.js +51 -0
  252. package/dist/form/Fields/ObjectField.js +54 -0
  253. package/dist/form/Fields/RadioField.js +49 -0
  254. package/dist/form/Fields/RangeField.js +58 -0
  255. package/dist/form/Fields/ResourceOptionIcon.d.ts +1 -1
  256. package/dist/form/Fields/ResourceOptionIcon.js +21 -0
  257. package/dist/form/Fields/StepField.js +6 -0
  258. package/dist/form/Fields/StringField.js +37 -0
  259. package/dist/form/Fields/TextAreaField.js +31 -0
  260. package/dist/form/Fields/durationValidity.js +11 -0
  261. package/dist/form/Form.d.ts +4 -21
  262. package/dist/form/Form.js +643 -0
  263. package/dist/form/SpecialTypes/DropdownWrapper.js +30 -0
  264. package/dist/form/SpecialTypes/FormikCustomDropdown.js +122 -0
  265. package/dist/form/SpecialTypes/FormikCustomInput.js +111 -0
  266. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +31 -0
  267. package/dist/form/SpecialTypes/FormikNumericInput.js +60 -0
  268. package/dist/form/Wizard/WizardContainer.js +138 -0
  269. package/dist/form/Wizard/WizardNavigation.js +92 -0
  270. package/dist/form/Wizard/WizardStepContent.js +35 -0
  271. package/dist/form/Wizard/WizardStepIndicator.js +108 -0
  272. package/dist/form/Wizard/useWizardState.js +118 -0
  273. package/dist/form/Wizard/utils.js +34 -0
  274. package/dist/form/fieldContext.js +26 -0
  275. package/dist/form/fieldRegistry.js +50 -0
  276. package/dist/form/index.d.ts +11 -12
  277. package/dist/form/index.js +18 -2445
  278. package/dist/form/lib.d.ts +6 -1
  279. package/dist/{chunks/FieldWrapper-Bef01EWO.js → form/lib.js} +5 -104
  280. package/dist/form/types/fieldComponentTypes.d.ts +3 -2
  281. package/dist/form/types/fieldTypes.d.ts +6 -20
  282. package/dist/form/useParsedOpts.d.ts +1 -1
  283. package/dist/form/useParsedOpts.js +62 -0
  284. package/dist/form/usePrevious.js +11 -0
  285. package/dist/form/utils/checkShowIfObject.js +14 -0
  286. package/dist/form/utils/{slurmDuration.d.ts → duration.d.ts} +2 -2
  287. package/dist/form/utils/duration.js +69 -0
  288. package/dist/form/utils/getParentValue.js +23 -0
  289. package/dist/form/utils/getPlaceholder.js +9 -0
  290. package/dist/form/utils/getValueUsingPath.js +23 -0
  291. package/dist/form/utils/secondaryField.js +22 -0
  292. package/dist/graph/AnnotationBanner.js +141 -0
  293. package/dist/graph/Collapse.js +41 -0
  294. package/dist/{workflow/index.js → graph/DependencyGraph.js} +76 -1163
  295. package/dist/graph/JobSummary.js +104 -0
  296. package/dist/{workflow → graph}/MatrixGroup.d.ts +2 -2
  297. package/dist/graph/MatrixGroup.js +107 -0
  298. package/dist/graph/Reveal.js +57 -0
  299. package/dist/graph/TreeView.js +711 -0
  300. package/dist/{workflow → graph}/index.d.ts +1 -1
  301. package/dist/graph/index.js +2 -0
  302. package/dist/{workflow → graph}/types.d.ts +3 -3
  303. package/dist/graph/types.js +6 -0
  304. package/dist/icons.d.ts +20 -21
  305. package/dist/index.d.ts +38 -40
  306. package/dist/index.js +47 -599
  307. package/dist/list/ActionToolbar.js +184 -0
  308. package/dist/list/HoverCard.js +73 -0
  309. package/dist/list/ListPage.js +145 -0
  310. package/dist/list/ListPager.js +59 -0
  311. package/dist/list/ListTable.d.ts +1 -1
  312. package/dist/list/ListTable.js +163 -0
  313. package/dist/list/ListViewControls.d.ts +2 -2
  314. package/dist/list/ListViewControls.js +372 -0
  315. package/dist/list/RowContextMenu.js +350 -0
  316. package/dist/list/UserHoverCard.js +117 -0
  317. package/dist/list/index.d.ts +9 -9
  318. package/dist/list/index.js +11 -2
  319. package/dist/list/listSearch.js +137 -0
  320. package/dist/list/listView.js +210 -0
  321. package/dist/list/textEntry.js +10 -0
  322. package/dist/logviewer/LogViewer.d.ts +1 -1
  323. package/dist/logviewer/LogViewer.js +750 -0
  324. package/dist/logviewer/index.d.ts +1 -0
  325. package/dist/logviewer/index.js +3 -742
  326. package/dist/logviewer/segments.d.ts +9 -0
  327. package/dist/logviewer/segments.js +80 -0
  328. package/dist/styles/fonts.css +4 -4
  329. package/dist/styles/theme.css +6 -4
  330. package/dist/styles.css +1 -1
  331. package/dist/theme/index.js +2 -2
  332. package/package.json +38 -14
  333. package/LICENSE +0 -202
  334. package/dist/chunks/Monaco-C1POOdVv.js +0 -1046
  335. package/dist/chunks/PageHeader-l49p1nM9.js +0 -690
  336. package/dist/chunks/SwitchToggle-CHPP8uZQ.js +0 -755
  337. package/dist/chunks/editor-9_uVtUyy.js +0 -347
  338. package/dist/chunks/list-qrojZZNv.js +0 -1411
  339. package/dist/editor/usesGitlab.d.ts +0 -97
  340. package/dist/form/Fields/BucketReadOnlyField.d.ts +0 -7
  341. package/dist/form/types/workflow-schema.d.ts +0 -1145
  342. package/dist/form/utils/pwResolver.d.ts +0 -18
  343. package/dist/{chunks/MarkdownImpl-Bq4QhrtA.js → components/MarkdownImpl.js} +1 -1
  344. /package/dist/{workflow → graph}/AnnotationBanner.d.ts +0 -0
  345. /package/dist/{workflow → graph}/Collapse.d.ts +0 -0
  346. /package/dist/{workflow → graph}/DependencyGraph.d.ts +0 -0
  347. /package/dist/{workflow → graph}/JobSummary.d.ts +0 -0
  348. /package/dist/{workflow → graph}/Reveal.d.ts +0 -0
  349. /package/dist/{workflow → graph}/TreeView.d.ts +0 -0
@@ -0,0 +1,343 @@
1
+ import { CheckIcon, ChevronDownIcon, CloudIcon, CogIcon, RetryIcon, RobotIcon } from "../../icons.js";
2
+ import { useChatConfig } from "../core/config.js";
3
+ import { useChat } from "../core/ChatProvider.js";
4
+ import cx from "classnames";
5
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
6
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
+ import { createPortal } from "react-dom";
8
+ //#region src/ai/components/ModelSelector.tsx
9
+ /** The search field plus the list's max-h-80, so the flip decision matches
10
+ * what renders. */
11
+ var MAX_PANEL_HEIGHT_PX = 380;
12
+ function CspIcon({ cspKind, className }) {
13
+ const { slots } = useChatConfig();
14
+ const custom = slots.providerIcon?.(cspKind, className);
15
+ if (custom) return /* @__PURE__ */ jsx(Fragment$1, { children: custom });
16
+ return /* @__PURE__ */ jsx(CloudIcon, { className: cx("text-purple-500", className) });
17
+ }
18
+ function getProviderKeyFromModelId(modelId) {
19
+ const idx = modelId.indexOf("/");
20
+ return idx > 0 ? modelId.substring(0, idx) : modelId;
21
+ }
22
+ function getModelNameFromId(modelId) {
23
+ const idx = modelId.indexOf("/");
24
+ return idx > 0 ? modelId.substring(idx + 1) : modelId;
25
+ }
26
+ function getModelLabel(model) {
27
+ const idName = getModelNameFromId(model.id);
28
+ const name = model.name?.trim();
29
+ if (!name || name === `${model.provider} (${idName})`) return idName;
30
+ return name;
31
+ }
32
+ function groupModelsByProvider(models) {
33
+ const groups = /* @__PURE__ */ new Map();
34
+ for (const model of models) {
35
+ const key = model.id.includes("/") ? getProviderKeyFromModelId(model.id) : model.provider ?? model.owned_by;
36
+ if (!groups.has(key)) groups.set(key, []);
37
+ groups.get(key).push(model);
38
+ }
39
+ return groups;
40
+ }
41
+ function ModelSelector({ targetSession, variant = "default" }) {
42
+ const bare = variant === "bare";
43
+ const { providers, models, unreachableSessions, selectedProvider, setSelectedProvider, isLoadingModels, hasLoadedModels, modelsError, refreshModels, currentUser } = useChat();
44
+ const { extraLinks, LinkComponent } = useChatConfig();
45
+ const [isOpen, setIsOpen] = useState(false);
46
+ const [searchQuery, setSearchQuery] = useState("");
47
+ const [dropdownPosition, setDropdownPosition] = useState({
48
+ top: 0,
49
+ bottom: 0,
50
+ left: 0,
51
+ width: 0,
52
+ flipped: false
53
+ });
54
+ const containerRef = useRef(null);
55
+ const dropdownRef = useRef(null);
56
+ const buttonRef = useRef(null);
57
+ const inputRef = useRef(null);
58
+ const [mounted, setMounted] = useState(false);
59
+ useEffect(() => {
60
+ setMounted(true);
61
+ }, []);
62
+ const updateDropdownPosition = useCallback(() => {
63
+ if (!buttonRef.current) return;
64
+ const rect = buttonRef.current.getBoundingClientRect();
65
+ const below = window.innerHeight - rect.bottom;
66
+ setDropdownPosition({
67
+ top: rect.bottom + 4,
68
+ bottom: window.innerHeight - rect.top + 4,
69
+ left: rect.left,
70
+ width: Math.max(rect.width, 320),
71
+ flipped: below < MAX_PANEL_HEIGHT_PX && rect.top > below
72
+ });
73
+ }, []);
74
+ useEffect(() => {
75
+ if (!isOpen) return;
76
+ function handleClickOutside(event) {
77
+ const target = event.target;
78
+ const clickedInsideButton = containerRef.current?.contains(target);
79
+ const clickedInsideDropdown = dropdownRef.current?.contains(target);
80
+ if (!clickedInsideButton && !clickedInsideDropdown) setIsOpen(false);
81
+ }
82
+ const timeoutId = setTimeout(() => {
83
+ document.addEventListener("mousedown", handleClickOutside);
84
+ }, 0);
85
+ return () => {
86
+ clearTimeout(timeoutId);
87
+ document.removeEventListener("mousedown", handleClickOutside);
88
+ };
89
+ }, [isOpen]);
90
+ useEffect(() => {
91
+ if (!isOpen) return;
92
+ updateDropdownPosition();
93
+ window.addEventListener("scroll", updateDropdownPosition, true);
94
+ window.addEventListener("resize", updateDropdownPosition);
95
+ return () => {
96
+ window.removeEventListener("scroll", updateDropdownPosition, true);
97
+ window.removeEventListener("resize", updateDropdownPosition);
98
+ };
99
+ }, [isOpen, updateDropdownPosition]);
100
+ useEffect(() => {
101
+ if (isOpen && inputRef.current) inputRef.current.focus();
102
+ }, [isOpen]);
103
+ const filteredModels = useMemo(() => {
104
+ if (!searchQuery.trim()) return models;
105
+ const query = searchQuery.toLowerCase();
106
+ return models.filter((model) => getModelNameFromId(model.id).toLowerCase().includes(query) || (model.provider || "").toLowerCase().includes(query) || (model.name || "").toLowerCase().includes(query));
107
+ }, [models, searchQuery]);
108
+ const groupedModels = useMemo(() => groupModelsByProvider(filteredModels), [filteredModels]);
109
+ const selectedModelInfo = models.find((m) => m.id === selectedProvider);
110
+ const selectedModelName = selectedModelInfo ? getModelLabel(selectedModelInfo) : null;
111
+ const selectedProviderName = selectedModelInfo?.provider || null;
112
+ const handleSelect = (modelId) => {
113
+ setSelectedProvider(modelId);
114
+ setIsOpen(false);
115
+ setSearchQuery("");
116
+ };
117
+ const targetSessionDisplayName = targetSession?.split(":").pop();
118
+ const targetSessionFound = targetSession && models.length > 0 ? models.some((m) => m.id.startsWith(`session:${targetSession}/`)) : false;
119
+ const targetSessionStatus = targetSession ? isLoadingModels ? "connecting" : hasLoadedModels && !targetSessionFound ? "offline" : null : null;
120
+ const boxClass = bare ? "flex items-center gap-1 rounded-md px-1.5 py-0.5 max-w-[280px]" : "flex items-center gap-2 px-3 h-8 rounded-lg min-w-[180px] max-w-[280px]";
121
+ const textClass = bare ? "text-[11px]" : "text-sm";
122
+ if (isLoadingModels && models.length === 0 && !targetSession) return /* @__PURE__ */ jsx("div", {
123
+ ref: containerRef,
124
+ className: "relative",
125
+ children: /* @__PURE__ */ jsxs("div", {
126
+ className: boxClass,
127
+ children: [!bare && /* @__PURE__ */ jsx(RobotIcon, { className: "h-4 w-4 text-purple-500 flex-shrink-0 animate-pulse" }), /* @__PURE__ */ jsx("span", {
128
+ className: cx(textClass, "theme-muted-text"),
129
+ children: "Loading models..."
130
+ })]
131
+ })
132
+ });
133
+ if (modelsError && models.length === 0) return /* @__PURE__ */ jsx("div", {
134
+ ref: containerRef,
135
+ className: "relative",
136
+ children: /* @__PURE__ */ jsxs("div", {
137
+ className: boxClass,
138
+ children: [
139
+ !bare && /* @__PURE__ */ jsx(RobotIcon, { className: "h-4 w-4 text-red-500 flex-shrink-0" }),
140
+ /* @__PURE__ */ jsx("span", {
141
+ className: cx(textClass, "text-red-600"),
142
+ children: "Failed to load models"
143
+ }),
144
+ /* @__PURE__ */ jsxs("button", {
145
+ type: "button",
146
+ onClick: () => refreshModels(),
147
+ className: cx("flex items-center gap-1 text-blue-600 hover:underline ml-1", bare ? "text-[11px]" : "text-xs"),
148
+ children: [/* @__PURE__ */ jsx(RetryIcon, { className: "h-2.5 w-2.5" }), "Retry"]
149
+ })
150
+ ]
151
+ })
152
+ });
153
+ if (hasLoadedModels && models.length === 0 && !targetSessionStatus && unreachableSessions.length === 0) return /* @__PURE__ */ jsx("div", {
154
+ ref: containerRef,
155
+ className: "relative",
156
+ children: /* @__PURE__ */ jsxs("div", {
157
+ className: boxClass,
158
+ children: [!bare && /* @__PURE__ */ jsx(RobotIcon, { className: "h-4 w-4 theme-muted-text flex-shrink-0" }), /* @__PURE__ */ jsx("span", {
159
+ className: cx(textClass, "theme-muted-text"),
160
+ children: "No models available"
161
+ })]
162
+ })
163
+ });
164
+ const triggerText = selectedModelName ? null : targetSessionStatus === "connecting" ? "Connecting..." : models.length === 0 && isLoadingModels ? "Loading models..." : "Select a model";
165
+ return /* @__PURE__ */ jsxs("div", {
166
+ ref: containerRef,
167
+ className: "relative",
168
+ children: [/* @__PURE__ */ jsxs("button", {
169
+ ref: buttonRef,
170
+ type: "button",
171
+ onClick: () => setIsOpen(!isOpen),
172
+ disabled: models.length === 0 && !targetSessionStatus && unreachableSessions.length === 0,
173
+ className: cx(boxClass, "transition-all cursor-pointer bg-transparent", "focus:outline-none", "disabled:opacity-50 disabled:cursor-not-allowed", bare ? "hover:theme-muted-panel" : "border theme-border hover:theme-hover"),
174
+ children: [
175
+ !bare && /* @__PURE__ */ jsx(RobotIcon, { className: cx("h-4 w-4 flex-shrink-0", targetSessionStatus === "connecting" ? "text-amber-500 animate-pulse" : "text-purple-500") }),
176
+ /* @__PURE__ */ jsx("div", {
177
+ className: "flex-1 min-w-0 text-left",
178
+ children: selectedModelName ? /* @__PURE__ */ jsxs("div", {
179
+ className: "flex items-baseline gap-1.5 min-w-0",
180
+ children: [/* @__PURE__ */ jsx("span", {
181
+ title: selectedModelName,
182
+ className: cx("truncate", bare ? "text-[11px] theme-muted-text" : "text-sm font-medium text-(--theme-panel)"),
183
+ children: selectedModelName
184
+ }), selectedProviderName && /* @__PURE__ */ jsx("span", {
185
+ title: selectedProviderName,
186
+ className: cx("theme-muted-text truncate flex-shrink-0 max-w-[45%]", bare ? "text-[10px]" : "text-xs"),
187
+ children: selectedProviderName
188
+ })]
189
+ }) : /* @__PURE__ */ jsx("span", {
190
+ className: cx(bare ? "text-[11px]" : "text-sm", targetSessionStatus === "connecting" ? "text-amber-600" : "theme-muted-text"),
191
+ children: triggerText
192
+ })
193
+ }),
194
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: cx("h-3 w-3 theme-muted-text transition-transform flex-shrink-0", !bare && "ml-auto", isOpen && "rotate-180") })
195
+ ]
196
+ }), isOpen && mounted && createPortal(/* @__PURE__ */ jsxs("div", {
197
+ ref: dropdownRef,
198
+ role: "none",
199
+ onClick: (e) => e.stopPropagation(),
200
+ onKeyDown: (e) => {
201
+ if (e.key === "Escape") {
202
+ e.preventDefault();
203
+ setIsOpen(false);
204
+ buttonRef.current?.focus();
205
+ }
206
+ },
207
+ style: {
208
+ position: "fixed",
209
+ ...dropdownPosition.flipped ? { bottom: dropdownPosition.bottom } : { top: dropdownPosition.top },
210
+ left: dropdownPosition.left,
211
+ width: dropdownPosition.width,
212
+ zIndex: 9999
213
+ },
214
+ className: cx("theme-panel rounded-lg shadow-lg", "border theme-border", "overflow-hidden"),
215
+ children: [/* @__PURE__ */ jsx("div", {
216
+ className: "p-2 border-b theme-border",
217
+ children: /* @__PURE__ */ jsx("input", {
218
+ ref: inputRef,
219
+ type: "text",
220
+ value: searchQuery,
221
+ onChange: (e) => setSearchQuery(e.target.value),
222
+ placeholder: "Search models...",
223
+ className: cx("w-full px-3 py-2 text-sm rounded-md", "theme-muted-panel", "border theme-border", "focus:outline-none focus:ring-2 focus:ring-blue-500", "placeholder:theme-muted-text")
224
+ })
225
+ }), /* @__PURE__ */ jsxs("div", {
226
+ className: "max-h-80 overflow-y-auto",
227
+ children: [
228
+ targetSessionStatus && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
229
+ className: "px-3 py-1.5 bg-amber-500/5 sticky top-0",
230
+ children: /* @__PURE__ */ jsxs("div", {
231
+ className: "flex items-center gap-2",
232
+ children: [
233
+ /* @__PURE__ */ jsx(CloudIcon, { className: "h-3 w-3 text-amber-500" }),
234
+ /* @__PURE__ */ jsx("span", {
235
+ className: "text-xs font-semibold text-amber-600 uppercase tracking-wide flex-1",
236
+ children: targetSessionDisplayName
237
+ }),
238
+ /* @__PURE__ */ jsx("span", {
239
+ className: cx("text-[10px] px-1.5 py-0.5 rounded-full", targetSessionStatus === "connecting" ? "text-amber-600 bg-amber-500/10 animate-pulse" : "text-amber-500 bg-amber-500/10"),
240
+ children: targetSessionStatus === "connecting" ? "Connecting..." : "Not responding"
241
+ })
242
+ ]
243
+ })
244
+ }), /* @__PURE__ */ jsx("div", {
245
+ className: "px-4 py-2 flex items-center gap-2",
246
+ children: /* @__PURE__ */ jsx("span", {
247
+ className: "text-sm theme-muted-text italic",
248
+ children: targetSessionStatus === "connecting" ? "Loading session models..." : "Service not responding — ensure it is running on the remote host"
249
+ })
250
+ })] }),
251
+ unreachableSessions.filter((s) => !targetSession || `${s.owner}:${s.name}` !== targetSession).map((s) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
252
+ className: "px-3 py-1.5 bg-amber-500/5 sticky top-0",
253
+ children: /* @__PURE__ */ jsxs("div", {
254
+ className: "flex items-center gap-2",
255
+ children: [
256
+ /* @__PURE__ */ jsx(CloudIcon, { className: "h-3 w-3 text-amber-500" }),
257
+ /* @__PURE__ */ jsx("span", {
258
+ className: "text-xs font-semibold text-amber-600 uppercase tracking-wide flex-1",
259
+ children: s.name
260
+ }),
261
+ /* @__PURE__ */ jsx("span", {
262
+ className: "text-[10px] text-amber-500 bg-amber-500/10 px-1.5 py-0.5 rounded-full",
263
+ children: "Not responding"
264
+ })
265
+ ]
266
+ })
267
+ }), /* @__PURE__ */ jsx("div", {
268
+ className: "px-4 py-2 flex items-center gap-2",
269
+ children: /* @__PURE__ */ jsx("span", {
270
+ className: "text-sm theme-muted-text italic",
271
+ children: "Service not responding — ensure it is running on the remote host"
272
+ })
273
+ })] }, `${s.owner}:${s.name}`)),
274
+ groupedModels.size === 0 && !targetSessionStatus && unreachableSessions.length === 0 ? /* @__PURE__ */ jsx("div", {
275
+ className: "p-4 text-center theme-muted-text text-sm",
276
+ children: "No models found"
277
+ }) : Array.from(groupedModels.entries()).map(([providerKey, providerModels]) => {
278
+ const providerInfo = providers.find((p) => `${p.user}:${p.name}` === providerKey);
279
+ const providerName = providerModels[0]?.provider || providerInfo?.name || "Unknown Provider";
280
+ const platform = providerInfo?.platformLabel;
281
+ const platformSuffix = providerInfo && platform && platform.toLowerCase() !== providerName.toLowerCase() ? platform : null;
282
+ const isOwner = providerInfo?.user === currentUser.username;
283
+ const settingsHref = providerInfo && extraLinks.providerSettings ? extraLinks.providerSettings(providerInfo.user, providerInfo.name) : null;
284
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
285
+ className: "px-3 py-1.5 theme-muted-panel sticky top-0",
286
+ children: /* @__PURE__ */ jsxs("div", {
287
+ className: "flex items-center gap-2",
288
+ children: [
289
+ /* @__PURE__ */ jsx(CspIcon, {
290
+ cspKind: providerInfo?.cspKind ?? "other",
291
+ className: "h-3 w-3"
292
+ }),
293
+ /* @__PURE__ */ jsx("span", {
294
+ className: "text-xs font-semibold theme-muted-text uppercase tracking-wide",
295
+ children: providerName
296
+ }),
297
+ /* @__PURE__ */ jsx("span", {
298
+ className: "min-w-0 flex-1 truncate text-xs theme-muted-text",
299
+ children: platformSuffix ? `· ${platformSuffix}` : ""
300
+ }),
301
+ /* @__PURE__ */ jsxs("span", {
302
+ className: "text-xs theme-muted-text",
303
+ children: [
304
+ "(",
305
+ providerModels.length,
306
+ ")"
307
+ ]
308
+ }),
309
+ isOwner && settingsHref && /* @__PURE__ */ jsx(LinkComponent, {
310
+ target: {
311
+ kind: "external",
312
+ href: settingsHref
313
+ },
314
+ onClick: (e) => e.stopPropagation(),
315
+ className: "p-0.5 rounded hover:theme-hover theme-muted-text hover:text-blue-600 transition-colors",
316
+ title: "Manage provider",
317
+ children: /* @__PURE__ */ jsx(CogIcon, { className: "h-3 w-3" })
318
+ })
319
+ ]
320
+ })
321
+ }), providerModels.map((model) => {
322
+ const modelName = getModelLabel(model);
323
+ const isSelected = model.id === selectedProvider;
324
+ return /* @__PURE__ */ jsxs("button", {
325
+ type: "button",
326
+ onClick: () => handleSelect(model.id),
327
+ className: cx("w-full flex items-center gap-3 px-4 py-2 text-left cursor-pointer", "hover:bg-blue-500/5 transition-colors", isSelected && "bg-blue-500/10"),
328
+ children: [/* @__PURE__ */ jsx("span", {
329
+ title: modelName,
330
+ className: cx("flex-1 min-w-0 text-sm truncate", isSelected ? "text-blue-600 font-medium" : ""),
331
+ style: !isSelected ? { color: "var(--theme-panel, #1f2937)" } : void 0,
332
+ children: modelName
333
+ }), isSelected && /* @__PURE__ */ jsx(CheckIcon, { className: "h-3.5 w-3.5 text-blue-600 flex-shrink-0" })]
334
+ }, model.id);
335
+ })] }, providerKey);
336
+ })
337
+ ]
338
+ })]
339
+ }), document.body)]
340
+ });
341
+ }
342
+ //#endregion
343
+ export { ModelSelector as default, getProviderKeyFromModelId };
@@ -0,0 +1,11 @@
1
+ interface ShareDialogProps {
2
+ conversationId: string;
3
+ isOpen: boolean;
4
+ onClose: () => void;
5
+ }
6
+ export default function ShareDialog({ conversationId, isOpen, onClose }: ShareDialogProps): import("react").JSX.Element | null;
7
+ export declare function ShareButton({ conversationId, disabled, }: {
8
+ conversationId: string;
9
+ disabled?: boolean;
10
+ }): import("react").JSX.Element | null;
11
+ export {};
@@ -0,0 +1,260 @@
1
+ import { ShareIcon, TrashIcon } from "../../icons.js";
2
+ import { ConfirmModal } from "../../components/ConfirmModal.js";
3
+ import Loader from "../../components/Loader.js";
4
+ import { useChatConfig } from "../core/config.js";
5
+ import { useChat } from "../core/ChatProvider.js";
6
+ import Dropdown from "../ui/Dropdown.js";
7
+ import { useCallback, useEffect, useState, useTransition } from "react";
8
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
+ //#region src/ai/components/ShareDialog.tsx
10
+ function ShareDialog({ conversationId, isOpen, onClose }) {
11
+ const { strings } = useChatConfig();
12
+ const t = strings.shareConversation;
13
+ const { adapter, notify } = useChat();
14
+ const sharing = adapter.sharing;
15
+ const [permissions, setPermissions] = useState([]);
16
+ const [teams, setTeams] = useState([]);
17
+ const [loading, setLoading] = useState(false);
18
+ const [saving, startSaveTransition] = useTransition();
19
+ const [orgViewAccess, setOrgViewAccess] = useState(false);
20
+ const [orgCollaborateAccess, setOrgCollaborateAccess] = useState(false);
21
+ const [originalPermissions, setOriginalPermissions] = useState([]);
22
+ const [originalOrgCollaborateAccess, setOriginalOrgCollaborateAccess] = useState(false);
23
+ useEffect(() => {
24
+ if (!isOpen || !sharing) return;
25
+ const loadData = async () => {
26
+ setLoading(true);
27
+ try {
28
+ const perms = await sharing.listPermissions(conversationId);
29
+ setPermissions(perms);
30
+ setOriginalPermissions([...perms]);
31
+ const orgPerm = perms.find((p) => p.entireOrganization);
32
+ if (orgPerm) {
33
+ setOrgViewAccess(true);
34
+ setOrgCollaborateAccess(orgPerm.permission === "collaborate");
35
+ setOriginalOrgCollaborateAccess(orgPerm.permission === "collaborate");
36
+ } else {
37
+ setOrgViewAccess(false);
38
+ setOrgCollaborateAccess(false);
39
+ setOriginalOrgCollaborateAccess(false);
40
+ }
41
+ setTeams(await sharing.listGroups());
42
+ } catch (error) {
43
+ console.error("Failed to load sharing data:", error);
44
+ notify.error(t.loadError);
45
+ } finally {
46
+ setLoading(false);
47
+ }
48
+ };
49
+ loadData();
50
+ }, [
51
+ isOpen,
52
+ conversationId,
53
+ sharing,
54
+ notify,
55
+ t.loadError
56
+ ]);
57
+ const handleSave = useCallback(() => {
58
+ if (!sharing) return;
59
+ startSaveTransition(async () => {
60
+ try {
61
+ const hadOrgPerm = originalPermissions.find((p) => p.entireOrganization);
62
+ const wantOrgPerm = orgViewAccess;
63
+ if (wantOrgPerm && !hadOrgPerm) await sharing.addPermission(conversationId, {
64
+ permission: orgCollaborateAccess ? "collaborate" : "view",
65
+ entireOrganization: true
66
+ });
67
+ else if (!wantOrgPerm && hadOrgPerm?.id) await sharing.removePermission(conversationId, hadOrgPerm.id);
68
+ else if (wantOrgPerm && hadOrgPerm?.id && (originalOrgCollaborateAccess !== orgCollaborateAccess || hadOrgPerm.permission === "collaborate" !== orgCollaborateAccess)) await sharing.updatePermission(conversationId, hadOrgPerm.id, orgCollaborateAccess ? "collaborate" : "view");
69
+ const originalTeamPerms = originalPermissions.filter((p) => p.team && !p.entireOrganization);
70
+ const currentTeamPerms = permissions.filter((p) => p.team && !p.entireOrganization);
71
+ for (const perm of currentTeamPerms) {
72
+ const original = originalTeamPerms.find((p) => p.team === perm.team);
73
+ if (!original) await sharing.addPermission(conversationId, {
74
+ permission: perm.permission,
75
+ team: perm.team,
76
+ entireOrganization: false
77
+ });
78
+ else if (original.permission !== perm.permission && original.id) await sharing.updatePermission(conversationId, original.id, perm.permission);
79
+ }
80
+ for (const original of originalTeamPerms) if (!currentTeamPerms.find((p) => p.team === original.team) && original.id) await sharing.removePermission(conversationId, original.id);
81
+ } catch (error) {
82
+ notify.error(error instanceof Error ? error.message : String(error));
83
+ return;
84
+ }
85
+ notify.success(t.saveSuccess);
86
+ onClose();
87
+ });
88
+ }, [
89
+ sharing,
90
+ conversationId,
91
+ permissions,
92
+ originalPermissions,
93
+ orgViewAccess,
94
+ orgCollaborateAccess,
95
+ originalOrgCollaborateAccess,
96
+ onClose,
97
+ notify,
98
+ t.saveSuccess
99
+ ]);
100
+ const handleAddTeam = useCallback((teamId) => {
101
+ if (permissions.some((p) => p.team === teamId)) return;
102
+ const team = teams.find((candidate) => candidate.id === teamId);
103
+ if (team) setPermissions((prev) => [...prev, {
104
+ team: teamId,
105
+ teamName: team.name,
106
+ permission: "view",
107
+ entireOrganization: false
108
+ }]);
109
+ }, [teams, permissions]);
110
+ const handleRemoveTeam = useCallback((teamId) => {
111
+ setPermissions((prev) => prev.filter((p) => p.team !== teamId));
112
+ }, []);
113
+ const handleTeamPermissionChange = useCallback((teamId, permission) => {
114
+ setPermissions((prev) => prev.map((p) => p.team === teamId ? {
115
+ ...p,
116
+ permission
117
+ } : p));
118
+ }, []);
119
+ if (!sharing) return null;
120
+ const teamPermissions = permissions.filter((p) => p.team && !p.entireOrganization);
121
+ const availableTeams = teams.filter((team) => !permissions.some((p) => p.team === team.id));
122
+ return /* @__PURE__ */ jsx(ConfirmModal, {
123
+ open: isOpen,
124
+ onClose,
125
+ align: "center",
126
+ title: t.title,
127
+ confirmLabel: strings.modal.save,
128
+ cancelLabel: strings.modal.cancel,
129
+ onConfirm: handleSave,
130
+ confirmDisabled: saving,
131
+ children: /* @__PURE__ */ jsx("div", {
132
+ className: "space-y-4",
133
+ children: loading ? /* @__PURE__ */ jsx("div", {
134
+ className: "py-4",
135
+ children: /* @__PURE__ */ jsx(Loader, {
136
+ size: 24,
137
+ text: strings.modal.loading
138
+ })
139
+ }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
140
+ /* @__PURE__ */ jsxs("div", {
141
+ className: "border theme-border rounded-lg p-3",
142
+ children: [/* @__PURE__ */ jsx("h3", {
143
+ className: "font-medium text-sm mb-2",
144
+ children: t.orgAccess
145
+ }), /* @__PURE__ */ jsxs("div", {
146
+ className: "space-y-2",
147
+ children: [/* @__PURE__ */ jsxs("label", {
148
+ className: "flex items-center gap-2",
149
+ children: [/* @__PURE__ */ jsx("input", {
150
+ type: "checkbox",
151
+ checked: orgViewAccess,
152
+ onChange: (e) => {
153
+ setOrgViewAccess(e.target.checked);
154
+ if (!e.target.checked) setOrgCollaborateAccess(false);
155
+ },
156
+ className: "rounded"
157
+ }), /* @__PURE__ */ jsx("span", {
158
+ className: "text-sm",
159
+ children: t.orgCanView
160
+ })]
161
+ }), /* @__PURE__ */ jsxs("label", {
162
+ className: "flex items-center gap-2 ml-4",
163
+ children: [/* @__PURE__ */ jsx("input", {
164
+ type: "checkbox",
165
+ checked: orgCollaborateAccess,
166
+ onChange: (e) => setOrgCollaborateAccess(e.target.checked),
167
+ disabled: !orgViewAccess,
168
+ className: "rounded"
169
+ }), /* @__PURE__ */ jsx("span", {
170
+ className: "text-sm",
171
+ children: t.allowCollaboration
172
+ })]
173
+ })]
174
+ })]
175
+ }),
176
+ /* @__PURE__ */ jsxs("div", {
177
+ className: "border theme-border rounded-lg p-3",
178
+ children: [
179
+ /* @__PURE__ */ jsx("h3", {
180
+ className: "font-medium text-sm mb-2",
181
+ children: t.groupAccess
182
+ }),
183
+ teamPermissions.length > 0 ? /* @__PURE__ */ jsx("ul", {
184
+ className: "space-y-2 mb-3 max-h-[200px] overflow-y-auto",
185
+ children: teamPermissions.map((perm) => /* @__PURE__ */ jsxs("li", {
186
+ className: "flex items-center justify-between theme-muted-panel rounded px-2 py-1.5",
187
+ children: [/* @__PURE__ */ jsx("span", {
188
+ className: "text-sm theme-text",
189
+ children: perm.teamName || perm.team
190
+ }), /* @__PURE__ */ jsxs("div", {
191
+ className: "flex items-center gap-2",
192
+ children: [/* @__PURE__ */ jsx(Dropdown, {
193
+ options: [{
194
+ label: t.viewOnly,
195
+ value: "view"
196
+ }, {
197
+ label: t.canCollaborate,
198
+ value: "collaborate"
199
+ }],
200
+ value: perm.permission,
201
+ onChange: (val) => handleTeamPermissionChange(perm.team, val),
202
+ wrapperClassName: "w-40",
203
+ textBoxClassName: "text-xs border theme-border rounded px-2 py-1"
204
+ }), /* @__PURE__ */ jsx("button", {
205
+ type: "button",
206
+ onClick: () => handleRemoveTeam(perm.team),
207
+ className: "p-1 rounded hover:bg-red-500/10",
208
+ title: t.remove,
209
+ children: /* @__PURE__ */ jsx(TrashIcon, { className: "w-3 h-3 text-red-500" })
210
+ })]
211
+ })]
212
+ }, perm.team))
213
+ }) : /* @__PURE__ */ jsx("p", {
214
+ className: "text-sm theme-muted-text mb-3",
215
+ children: t.noGroups
216
+ }),
217
+ availableTeams.length > 0 && /* @__PURE__ */ jsx("div", {
218
+ className: "flex items-center gap-2",
219
+ children: /* @__PURE__ */ jsx(Dropdown, {
220
+ options: availableTeams.map((team) => ({
221
+ label: team.name,
222
+ value: team.id
223
+ })),
224
+ value: "",
225
+ onChange: (val) => handleAddTeam(val),
226
+ placeholder: t.addGroups,
227
+ wrapperClassName: "flex-1",
228
+ textBoxClassName: "text-sm border theme-border rounded px-2 py-1.5 w-full"
229
+ })
230
+ })
231
+ ]
232
+ }),
233
+ /* @__PURE__ */ jsx("p", {
234
+ className: "text-xs theme-muted-text",
235
+ children: t.info
236
+ })
237
+ ] })
238
+ })
239
+ });
240
+ }
241
+ function ShareButton({ conversationId, disabled = false }) {
242
+ const { strings } = useChatConfig();
243
+ const { adapter } = useChat();
244
+ const [isOpen, setIsOpen] = useState(false);
245
+ if (!adapter.sharing) return null;
246
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("button", {
247
+ type: "button",
248
+ onClick: () => setIsOpen(true),
249
+ disabled,
250
+ className: "flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[11px] theme-muted-text transition-colors hover:theme-muted-panel hover:theme-text disabled:opacity-50",
251
+ title: strings.shareConversation.shareButton,
252
+ children: [/* @__PURE__ */ jsx(ShareIcon, { className: "h-3 w-3" }), strings.shareConversation.shareButton]
253
+ }), /* @__PURE__ */ jsx(ShareDialog, {
254
+ conversationId,
255
+ isOpen,
256
+ onClose: () => setIsOpen(false)
257
+ })] });
258
+ }
259
+ //#endregion
260
+ export { ShareButton, ShareDialog as default };
@@ -0,0 +1,28 @@
1
+ import { type KeyboardEvent } from 'react';
2
+ export interface SlashCommandOption {
3
+ name: string;
4
+ description?: string | undefined;
5
+ usage?: string | undefined;
6
+ }
7
+ export interface SlashMenuConfig {
8
+ commands: SlashCommandOption[];
9
+ /** Names the listbox for assistive tech. */
10
+ label: string;
11
+ /** Called when the input first reads as a command, so a host can load the list lazily. */
12
+ onOpen?: (() => void) | undefined;
13
+ }
14
+ export declare function slashMatches(input: string, commands: SlashCommandOption[]): SlashCommandOption[];
15
+ /** The palette's open state and keys; the caller owns the input. */
16
+ export declare function useSlashMenu(input: string, config: SlashMenuConfig | undefined, setInput: (value: string) => void): {
17
+ open: boolean;
18
+ matches: SlashCommandOption[];
19
+ active: number;
20
+ choose: (name: string) => void;
21
+ handleKey: (e: KeyboardEvent<HTMLTextAreaElement>) => boolean;
22
+ };
23
+ export declare function SlashMenu({ label, matches, active, onChoose, }: {
24
+ label: string;
25
+ matches: SlashCommandOption[];
26
+ active: number;
27
+ onChoose: (name: string) => void;
28
+ }): import("react").JSX.Element;