@morscherlab/mint-sdk 1.2.0-beta.2 → 1.2.0-beta.20

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 (493) hide show
  1. package/README.md +65 -5
  2. package/dist/{ExperimentPopover-tLwJ7XF4.js → ExperimentPopover-CJdNlCZb.js} +24 -15
  3. package/dist/ExperimentPopover-CJdNlCZb.js.map +1 -0
  4. package/dist/{ExperimentSelectorModal-DyPAUCLw.js → ExperimentSelectorModal-DCXmwKNS.js} +5 -5
  5. package/dist/ExperimentSelectorModal-DCXmwKNS.js.map +1 -0
  6. package/dist/{SettingsModal-BgKY93zh.js → SettingsModal-BYR20I4c.js} +5 -8
  7. package/dist/SettingsModal-BYR20I4c.js.map +1 -0
  8. package/dist/{EmptyState-p90quq8Z.js → Skeleton-BAF3CKY7.js} +111 -93
  9. package/dist/Skeleton-BAF3CKY7.js.map +1 -0
  10. package/dist/__tests__/components/DataStates.test.d.ts +1 -0
  11. package/dist/__tests__/components/ExperimentTimeline.test.d.ts +1 -0
  12. package/dist/__tests__/components/FileBrowserModal.test.d.ts +1 -0
  13. package/dist/__tests__/components/FilePicker.state.test.d.ts +1 -0
  14. package/dist/__tests__/components/FilePicker.test.d.ts +1 -0
  15. package/dist/__tests__/components/PlotlyChart.test.d.ts +1 -0
  16. package/dist/__tests__/components/PluginWorkspaceView.internal.test.d.ts +1 -0
  17. package/dist/__tests__/components/SecretInput.test.d.ts +1 -0
  18. package/dist/__tests__/components/WellEditPopupInternal.test.d.ts +1 -0
  19. package/dist/__tests__/components/iconButtonIconSizing.test.d.ts +1 -0
  20. package/dist/__tests__/composables/useFileBrowser.test.d.ts +1 -0
  21. package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
  22. package/dist/__tests__/composables/usePlatformFilePickerAdapter.test.d.ts +1 -0
  23. package/dist/__tests__/composables/usePluginConfig.test.d.ts +15 -0
  24. package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
  25. package/dist/apiErrors.d.ts +26 -0
  26. package/dist/components/ActionMenu.vue.d.ts +1 -1
  27. package/dist/components/AppAvatarMenu.vue.d.ts +4 -0
  28. package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
  29. package/dist/components/AppSidebar.vue.d.ts +1 -1
  30. package/dist/components/AuditTrail.vue.d.ts +13 -0
  31. package/dist/components/AutoGroupModal.vue.d.ts +1 -1
  32. package/dist/components/BaseInput.vue.d.ts +1 -1
  33. package/dist/components/BaseSelect.vue.d.ts +1 -1
  34. package/dist/components/BaseTextarea.vue.d.ts +1 -1
  35. package/dist/components/BatchProgressList.vue.d.ts +17 -0
  36. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +4 -4
  37. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +2 -2
  38. package/dist/components/ConcentrationInput.vue.d.ts +1 -1
  39. package/dist/components/DataFrame.vue.d.ts +14 -2
  40. package/dist/components/DatePicker.vue.d.ts +2 -2
  41. package/dist/components/DateTimePicker.vue.d.ts +3 -1
  42. package/dist/components/DropdownButton.vue.d.ts +2 -0
  43. package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
  44. package/dist/components/ExperimentPopover.vue.d.ts +1 -0
  45. package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
  46. package/dist/components/FileBrowserModal.vue.d.ts +99 -0
  47. package/dist/components/FilePicker.vue.d.ts +32 -0
  48. package/dist/components/FileUploader.vue.d.ts +5 -2
  49. package/dist/components/FitPanel.vue.d.ts +1 -1
  50. package/dist/components/FormulaInput.vue.d.ts +1 -1
  51. package/dist/components/GeneratedPlotlyResult.vue.d.ts +1 -3
  52. package/dist/components/JobsStatusTray.vue.d.ts +9 -2
  53. package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
  54. package/dist/components/MobileSupportGate.vue.d.ts +1 -1
  55. package/dist/components/MoleculeInput.vue.d.ts +1 -1
  56. package/dist/components/NumberInput.vue.d.ts +1 -1
  57. package/dist/components/PlotlyChart.vue.d.ts +59 -0
  58. package/dist/components/PluginWorkspaceView.props.d.ts +29 -1
  59. package/dist/components/PluginWorkspaceView.vue.d.ts +5 -5
  60. package/dist/components/ProgressBar.vue.d.ts +1 -1
  61. package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
  62. package/dist/components/ReagentList.vue.d.ts +29 -1
  63. package/dist/components/ResourceCard.vue.d.ts +1 -1
  64. package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
  65. package/dist/components/SampleLegend.vue.d.ts +1 -1
  66. package/dist/components/SampleSelector.drag.d.ts +13 -0
  67. package/dist/components/SampleSelector.tree.d.ts +2 -0
  68. package/dist/components/SampleSelector.vue.d.ts +35 -2
  69. package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
  70. package/dist/components/SecretInput.vue.d.ts +28 -0
  71. package/dist/components/SequenceInput.vue.d.ts +1 -1
  72. package/dist/components/SettingsModal.vue.d.ts +1 -1
  73. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -1
  74. package/dist/components/StatusIndicator.vue.d.ts +1 -1
  75. package/dist/components/TagsInput.vue.d.ts +1 -1
  76. package/dist/components/TimePicker.vue.d.ts +2 -1
  77. package/dist/components/TimeRangeInput.vue.d.ts +1 -1
  78. package/dist/components/UnitInput.vue.d.ts +1 -1
  79. package/dist/components/WellPlate.geometry.d.ts +15 -0
  80. package/dist/components/WellPlate.interaction.d.ts +13 -0
  81. package/dist/components/WellPlate.vue.d.ts +30 -1
  82. package/dist/components/fileBrowserPresentation.d.ts +10 -0
  83. package/dist/components/index.d.ts +13 -0
  84. package/dist/components/index.js +8 -8
  85. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
  86. package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
  87. package/dist/components/internal/FileBrowserDialogInternal.vue.d.ts +34 -0
  88. package/dist/components/internal/FileBrowserListingInternal.vue.d.ts +25 -0
  89. package/dist/components/internal/FileBrowserToolbarInternal.vue.d.ts +26 -0
  90. package/dist/components/internal/FilePickerPreviewInternal.vue.d.ts +18 -0
  91. package/dist/components/internal/FilePickerTreeInternal.vue.d.ts +31 -0
  92. package/dist/components/internal/WellEditPopupInternal.vue.d.ts +3 -1
  93. package/dist/components/internal/WorkspaceControlsInternal.vue.d.ts +23 -0
  94. package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +70 -0
  95. package/dist/components/internal/WorkspaceSidebarInternal.vue.d.ts +43 -0
  96. package/dist/{components-DkHddRMl.js → components-DIum5hkx.js} +5882 -3200
  97. package/dist/components-DIum5hkx.js.map +1 -0
  98. package/dist/composables/controlSchemaTypes.d.ts +34 -0
  99. package/dist/composables/filePicker/localFiles.d.ts +3 -0
  100. package/dist/composables/filePicker/usePickerNavigation.d.ts +96 -0
  101. package/dist/composables/filePicker/usePickerSelection.d.ts +31 -0
  102. package/dist/composables/filePicker/validation.d.ts +5 -0
  103. package/dist/composables/flattenWorkspaceBindings.d.ts +61 -0
  104. package/dist/composables/index.d.ts +11 -2
  105. package/dist/composables/index.js +10 -10
  106. package/dist/composables/pluginWorkspaceModel.d.ts +164 -0
  107. package/dist/composables/useApi.d.ts +14 -7
  108. package/dist/composables/useAsync.d.ts +5 -1
  109. package/dist/composables/useBioTemplateWorkspace.d.ts +4 -20
  110. package/dist/composables/useCommandHistory.d.ts +5 -1
  111. package/dist/composables/useDropdownState.d.ts +18 -2
  112. package/dist/composables/useEventStream.d.ts +9 -0
  113. package/dist/composables/useFileBrowser.d.ts +55 -0
  114. package/dist/composables/useFilePicker.d.ts +189 -0
  115. package/dist/composables/useFocusTrap.d.ts +21 -0
  116. package/dist/composables/useGeneratedAnalysis.d.ts +3 -1
  117. package/dist/composables/useJobsStatusTray.d.ts +25 -1
  118. package/dist/composables/useListReorder.d.ts +90 -0
  119. package/dist/composables/useMenuKeyboard.d.ts +29 -0
  120. package/dist/composables/useOptimisticMutation.d.ts +5 -1
  121. package/dist/composables/usePlatformFilePickerAdapter.d.ts +11 -0
  122. package/dist/composables/usePluginClient.d.ts +2 -0
  123. package/dist/composables/usePluginConfig.d.ts +27 -0
  124. package/dist/composables/usePluginWorkspace.d.ts +51 -0
  125. package/dist/composables/useRequestSyncState.d.ts +42 -2
  126. package/dist/composables/useResourceCrud.d.ts +5 -1
  127. package/dist/composables/useRovingFocus.d.ts +24 -0
  128. package/dist/composables/useScheduleDrag.d.ts +1 -0
  129. package/dist/composables/useWellPainting.d.ts +5 -1
  130. package/dist/composables/useWellPlateAdapter.d.ts +5 -1
  131. package/dist/composables/useWellPlateValidation.d.ts +5 -1
  132. package/dist/composables/workspaceRecipes.d.ts +188 -0
  133. package/dist/{composables-C_i90sGS.js → composables-mFXsTA4g.js} +502 -86
  134. package/dist/composables-mFXsTA4g.js.map +1 -0
  135. package/dist/{useApi-J6zFkHmn.js → errors-BLuqMee5.js} +179 -16
  136. package/dist/errors-BLuqMee5.js.map +1 -0
  137. package/dist/{experiment-Cq145oEW.js → experiment-CVDRAnqp.js} +3 -8
  138. package/dist/experiment-CVDRAnqp.js.map +1 -0
  139. package/dist/{experiment-utils-CLnzPPq5.js → experiment-utils-CV2Wza3z.js} +70 -51
  140. package/dist/experiment-utils-CV2Wza3z.js.map +1 -0
  141. package/dist/index.d.ts +2 -0
  142. package/dist/index.js +15 -15
  143. package/dist/install.js +2 -7
  144. package/dist/install.js.map +1 -1
  145. package/dist/permissions.d.ts +42 -1
  146. package/dist/permissions.js +20 -10
  147. package/dist/permissions.js.map +1 -1
  148. package/dist/stores/auth.d.ts +6 -0
  149. package/dist/stores/index.d.ts +1 -1
  150. package/dist/stores/index.js +3 -3
  151. package/dist/stores/settings.d.ts +31 -1
  152. package/dist/styles.css +15135 -32397
  153. package/dist/templates/builderReadUtils.d.ts +1 -1
  154. package/dist/templates/index.js +2 -4
  155. package/dist/{templates-DsP51i-S.js → templates-CmGfmBRA.js} +303 -106
  156. package/dist/templates-CmGfmBRA.js.map +1 -0
  157. package/dist/types/auth.d.ts +1 -0
  158. package/dist/types/fileBrowserTypes.d.ts +77 -0
  159. package/dist/types/filePicker.d.ts +77 -0
  160. package/dist/types/form-builder.d.ts +1 -1
  161. package/dist/types/index.d.ts +2 -0
  162. package/dist/{useControlSchema-BDx2Olha.js → useControlSchema-DldpxNOP.js} +499 -1162
  163. package/dist/useControlSchema-DldpxNOP.js.map +1 -0
  164. package/dist/{useDropdownState-DSb3BC3N.js → useDropdownState-C7hRiVQf.js} +22 -6
  165. package/dist/useDropdownState-C7hRiVQf.js.map +1 -0
  166. package/dist/{useExperimentSelector-CV4iNfMS.js → useExperimentSelector-CEcIaueJ.js} +4 -4
  167. package/dist/{useExperimentSelector-CV4iNfMS.js.map → useExperimentSelector-CEcIaueJ.js.map} +1 -1
  168. package/dist/{useFormBuilder-BLxG3BOX.js → useFormBuilder-z5L_dUIy.js} +2 -2
  169. package/dist/{useFormBuilder-BLxG3BOX.js.map → useFormBuilder-z5L_dUIy.js.map} +1 -1
  170. package/dist/utils/color.d.ts +13 -0
  171. package/dist/utils/errors.d.ts +9 -0
  172. package/dist/utils/pluginSecrets.d.ts +53 -0
  173. package/dist/utils/records.d.ts +4 -0
  174. package/dist/{useProtocolTemplates-CS_SQl6U.js → validation-uwoJGEb6.js} +811 -212
  175. package/dist/validation-uwoJGEb6.js.map +1 -0
  176. package/package.json +1 -1
  177. package/src/__tests__/apiErrors.test.ts +81 -0
  178. package/src/__tests__/components/ActionMenu.test.ts +94 -0
  179. package/src/__tests__/components/AppAvatarMenu.test.ts +123 -0
  180. package/src/__tests__/components/BaseTabs.test.ts +67 -0
  181. package/src/__tests__/components/DataFrame.test.ts +183 -11
  182. package/src/__tests__/components/DataStates.test.ts +176 -0
  183. package/src/__tests__/components/DatePicker.test.ts +76 -0
  184. package/src/__tests__/components/DateTimePicker.test.ts +36 -0
  185. package/src/__tests__/components/DropdownButton.test.ts +134 -0
  186. package/src/__tests__/components/ExperimentPopover.test.ts +30 -0
  187. package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
  188. package/src/__tests__/components/FileBrowserModal.test.ts +460 -0
  189. package/src/__tests__/components/FilePicker.state.test.ts +287 -0
  190. package/src/__tests__/components/FilePicker.test.ts +487 -0
  191. package/src/__tests__/components/GeneratedPlotlyResult.test.ts +52 -5
  192. package/src/__tests__/components/GroupAssigner.test.ts +53 -0
  193. package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
  194. package/src/__tests__/components/PlotlyChart.test.ts +305 -0
  195. package/src/__tests__/components/PluginWorkspaceView.internal.test.ts +230 -0
  196. package/src/__tests__/components/RackEditor.test.ts +35 -0
  197. package/src/__tests__/components/ReagentList.test.ts +64 -2
  198. package/src/__tests__/components/RetiredStyles.test.ts +31 -0
  199. package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
  200. package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
  201. package/src/__tests__/components/SecretInput.test.ts +87 -0
  202. package/src/__tests__/components/SegmentedControl.test.ts +107 -0
  203. package/src/__tests__/components/TimePicker.test.ts +61 -0
  204. package/src/__tests__/components/WellEditPopupInternal.test.ts +108 -0
  205. package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
  206. package/src/__tests__/components/iconButtonIconSizing.test.ts +18 -0
  207. package/src/__tests__/composables/useApi.test.ts +92 -9
  208. package/src/__tests__/composables/useAuth.test.ts +2 -0
  209. package/src/__tests__/composables/useDropdownState.test.ts +58 -1
  210. package/src/__tests__/composables/useFileBrowser.test.ts +305 -0
  211. package/src/__tests__/composables/useGeneratedAnalysis.test.ts +7 -2
  212. package/src/__tests__/composables/useListReorder.test.ts +145 -0
  213. package/src/__tests__/composables/usePlatformFilePickerAdapter.test.ts +67 -0
  214. package/src/__tests__/composables/usePluginClient.test.ts +143 -0
  215. package/src/__tests__/composables/usePluginConfig.test.ts +497 -0
  216. package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
  217. package/src/__tests__/docs/frontendDocsCatalog.test.ts +39 -7
  218. package/src/__tests__/stores/settings.test.ts +71 -1
  219. package/src/__tests__/styles/cssTokens.test.ts +131 -0
  220. package/src/__tests__/utils/permissions.test.ts +68 -0
  221. package/src/apiErrors.ts +85 -0
  222. package/src/components/ActionMenu.vue +45 -88
  223. package/src/components/AlertBox.vue +0 -4
  224. package/src/components/AppAvatarMenu.vue +26 -7
  225. package/src/components/AppLayout.vue +0 -4
  226. package/src/components/AppPluginSwitcher.story.vue +87 -0
  227. package/src/components/AppPluginSwitcher.vue +2 -5
  228. package/src/components/AppSidebar.vue +0 -4
  229. package/src/components/AppToastContainer.vue +6 -8
  230. package/src/components/AppTopBar.vue +0 -4
  231. package/src/components/ArtifactSaveDialog.vue +0 -4
  232. package/src/components/ArtifactSelectorModal.vue +0 -4
  233. package/src/components/AuditTrail.story.vue +18 -0
  234. package/src/components/AuditTrail.vue +27 -7
  235. package/src/components/AutoGroupModal.vue +0 -4
  236. package/src/components/Avatar.vue +0 -4
  237. package/src/components/BaseButton.vue +0 -4
  238. package/src/components/BaseCheckbox.vue +0 -4
  239. package/src/components/BaseInput.vue +0 -4
  240. package/src/components/BaseModal.vue +8 -60
  241. package/src/components/BasePill.vue +0 -4
  242. package/src/components/BaseRadioGroup.vue +0 -4
  243. package/src/components/BaseSelect.vue +0 -4
  244. package/src/components/BaseSlider.vue +0 -4
  245. package/src/components/BaseTabs.vue +26 -5
  246. package/src/components/BaseTextarea.vue +0 -4
  247. package/src/components/BaseToggle.vue +0 -4
  248. package/src/components/BatchProgressList.story.vue +18 -0
  249. package/src/components/BatchProgressList.vue +32 -4
  250. package/src/components/BioTemplateExperimentWorkspaceView.vue +10 -21
  251. package/src/components/BioTemplatePackWorkspaceView.vue +11 -15
  252. package/src/components/BioTemplatePresetWorkspaceView.vue +8 -13
  253. package/src/components/Breadcrumb.vue +0 -4
  254. package/src/components/Calendar.vue +0 -4
  255. package/src/components/ChartContainer.story.vue +1 -1
  256. package/src/components/ChartContainer.vue +0 -4
  257. package/src/components/ChemicalFormula.vue +0 -4
  258. package/src/components/CollapsibleCard.vue +0 -4
  259. package/src/components/ColorSlider.vue +0 -4
  260. package/src/components/ComponentBindingRenderer.vue +1 -3
  261. package/src/components/ConcentrationInput.vue +0 -4
  262. package/src/components/ConfirmDialog.vue +0 -4
  263. package/src/components/ControlWorkspaceView.vue +11 -22
  264. package/src/components/DataFrame.story.vue +14 -0
  265. package/src/components/DataFrame.vue +97 -23
  266. package/src/components/DatePicker.vue +73 -27
  267. package/src/components/DateTimePicker.vue +45 -17
  268. package/src/components/Divider.vue +0 -4
  269. package/src/components/DoseCalculator.vue +0 -4
  270. package/src/components/DoseDesignWorkspaceView.vue +6 -25
  271. package/src/components/DropdownButton.vue +24 -6
  272. package/src/components/EmptyState.vue +0 -4
  273. package/src/components/ExperimentCodeBadge.vue +0 -4
  274. package/src/components/ExperimentDataViewer.story.vue +3 -0
  275. package/src/components/ExperimentDataViewer.vue +33 -13
  276. package/src/components/ExperimentPopover.vue +12 -7
  277. package/src/components/ExperimentSelectorModal.vue +0 -4
  278. package/src/components/ExperimentTimeline.story.vue +18 -0
  279. package/src/components/ExperimentTimeline.vue +81 -75
  280. package/src/components/FileBrowserModal.story.vue +203 -0
  281. package/src/components/FileBrowserModal.vue +384 -0
  282. package/src/components/FilePicker.story.vue +44 -0
  283. package/src/components/FilePicker.vue +284 -0
  284. package/src/components/FileUploader.vue +32 -18
  285. package/src/components/FitPanel.vue +0 -4
  286. package/src/components/FormActions.story.vue +96 -0
  287. package/src/components/FormActions.vue +0 -4
  288. package/src/components/FormBuilder.vue +0 -4
  289. package/src/components/FormField.vue +0 -4
  290. package/src/components/FormulaInput.vue +0 -4
  291. package/src/components/GeneratedPathInput.story.vue +68 -0
  292. package/src/components/GeneratedPlotlyResult.story.vue +96 -0
  293. package/src/components/GeneratedPlotlyResult.vue +34 -69
  294. package/src/components/GeneratedPluginView.story.vue +145 -0
  295. package/src/components/GeneratedPluginView.vue +10 -10
  296. package/src/components/GeneratedResultRenderer.story.vue +117 -0
  297. package/src/components/GeneratedResultRenderer.vue +4 -9
  298. package/src/components/GroupAssigner.vue +67 -5
  299. package/src/components/IconButton.vue +0 -4
  300. package/src/components/InstrumentAlertLog.vue +0 -4
  301. package/src/components/InstrumentStateBadge.vue +0 -4
  302. package/src/components/InstrumentStatusCard.vue +0 -4
  303. package/src/components/JobsStatusTray.vue +16 -5
  304. package/src/components/LcmsSequenceTable.vue +81 -50
  305. package/src/components/LoadingSpinner.vue +0 -4
  306. package/src/components/MobileSupportGate.vue +0 -4
  307. package/src/components/MoleculeInput.vue +0 -4
  308. package/src/components/MultiSelect.vue +0 -4
  309. package/src/components/NumberInput.vue +0 -4
  310. package/src/components/PlateMapEditor.vue +3 -14
  311. package/src/components/PlotlyChart.story.vue +61 -0
  312. package/src/components/PlotlyChart.vue +233 -0
  313. package/src/components/PluginIcon.vue +0 -4
  314. package/src/components/PluginWorkspaceView.props.ts +38 -0
  315. package/src/components/PluginWorkspaceView.vue +53 -224
  316. package/src/components/ProgressBar.vue +0 -4
  317. package/src/components/ProtocolStepEditor.vue +2 -4
  318. package/src/components/RackEditor.vue +51 -70
  319. package/src/components/ReagentEditor.vue +0 -4
  320. package/src/components/ReagentList.story.vue +18 -0
  321. package/src/components/ReagentList.vue +127 -82
  322. package/src/components/ResourceCard.vue +0 -4
  323. package/src/components/RuntimeUpdateNotice.story.vue +49 -0
  324. package/src/components/RuntimeUpdateNotice.vue +4 -4
  325. package/src/components/SampleHierarchyTree.story.vue +18 -0
  326. package/src/components/SampleHierarchyTree.vue +32 -9
  327. package/src/components/SampleLegend.vue +2 -8
  328. package/src/components/SampleSelector.drag.ts +51 -0
  329. package/src/components/SampleSelector.story.vue +6 -0
  330. package/src/components/SampleSelector.tree.ts +2 -0
  331. package/src/components/SampleSelector.vue +49 -10
  332. package/src/components/SampleSelectorGroupNode.vue +19 -0
  333. package/src/components/ScheduleCalendar.story.vue +6 -0
  334. package/src/components/ScheduleCalendar.vue +82 -7
  335. package/src/components/ScientificNumber.vue +0 -4
  336. package/src/components/SecretInput.story.vue +79 -0
  337. package/src/components/SecretInput.vue +150 -0
  338. package/src/components/SectionCard.vue +0 -4
  339. package/src/components/SegmentedControl.vue +50 -7
  340. package/src/components/SequenceInput.vue +0 -4
  341. package/src/components/SequenceProgressBar.story.vue +110 -0
  342. package/src/components/SequenceProgressBar.vue +0 -4
  343. package/src/components/SettingsModal.vue +0 -4
  344. package/src/components/Skeleton.vue +0 -4
  345. package/src/components/SmartGroupFieldRecipe.vue +8 -6
  346. package/src/components/SmartGroupManual.vue +0 -4
  347. package/src/components/StatusIndicator.vue +0 -4
  348. package/src/components/StepWizard.vue +0 -4
  349. package/src/components/TagsInput.vue +4 -6
  350. package/src/components/ThemeToggle.vue +0 -4
  351. package/src/components/TimePicker.vue +36 -7
  352. package/src/components/TimeRangeInput.vue +0 -4
  353. package/src/components/Tooltip.story.vue +3 -3
  354. package/src/components/Tooltip.vue +0 -4
  355. package/src/components/UnitInput.vue +0 -4
  356. package/src/components/WellPlate.geometry.ts +60 -1
  357. package/src/components/WellPlate.interaction.ts +44 -0
  358. package/src/components/WellPlate.story.vue +8 -0
  359. package/src/components/WellPlate.vue +53 -7
  360. package/src/components/fileBrowserPresentation.ts +39 -0
  361. package/src/components/index.ts +14 -0
  362. package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
  363. package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
  364. package/src/components/internal/DataStateInternal.vue +74 -0
  365. package/src/components/internal/FileBrowserDialogInternal.vue +75 -0
  366. package/src/components/internal/FileBrowserListingInternal.vue +197 -0
  367. package/src/components/internal/FileBrowserToolbarInternal.vue +136 -0
  368. package/src/components/internal/FilePickerPreviewInternal.vue +100 -0
  369. package/src/components/internal/FilePickerTreeInternal.vue +238 -0
  370. package/src/components/internal/FormSectionRenderer.vue +0 -4
  371. package/src/components/internal/WellEditPopupInternal.vue +20 -5
  372. package/src/components/internal/WorkspaceControlsInternal.vue +20 -0
  373. package/src/components/internal/WorkspaceShellInternal.vue +125 -0
  374. package/src/components/internal/WorkspaceSidebarInternal.vue +82 -0
  375. package/src/composables/controlSchemaTypes.ts +34 -0
  376. package/src/composables/experimentDesignData.ts +1 -3
  377. package/src/composables/filePicker/localFiles.ts +58 -0
  378. package/src/composables/filePicker/usePickerNavigation.ts +220 -0
  379. package/src/composables/filePicker/usePickerSelection.ts +259 -0
  380. package/src/composables/filePicker/validation.ts +41 -0
  381. package/src/composables/flattenWorkspaceBindings.ts +104 -0
  382. package/src/composables/formBuilderRegistry.ts +5 -0
  383. package/src/composables/index.ts +50 -0
  384. package/src/composables/pluginWorkspaceModel.ts +182 -0
  385. package/src/composables/useApi.ts +57 -13
  386. package/src/composables/useAsync.ts +5 -1
  387. package/src/composables/useAuth.ts +3 -0
  388. package/src/composables/useBioTemplatePackWorkspace.ts +15 -9
  389. package/src/composables/useBioTemplatePresetWorkspace.ts +14 -15
  390. package/src/composables/useBioTemplateWorkspace.ts +18 -43
  391. package/src/composables/useCommandHistory.ts +5 -1
  392. package/src/composables/useDropdownState.ts +35 -5
  393. package/src/composables/useEventStream.ts +14 -2
  394. package/src/composables/useFileBrowser.ts +314 -0
  395. package/src/composables/useFileImport.ts +2 -7
  396. package/src/composables/useFilePicker.ts +366 -0
  397. package/src/composables/useFocusTrap.ts +91 -0
  398. package/src/composables/useGeneratedAnalysis.ts +32 -27
  399. package/src/composables/useJobsStatusTray.ts +184 -17
  400. package/src/composables/useListReorder.story.vue +143 -0
  401. package/src/composables/useListReorder.ts +242 -0
  402. package/src/composables/useMenuKeyboard.ts +90 -0
  403. package/src/composables/useOptimisticMutation.ts +6 -16
  404. package/src/composables/usePlatformFilePickerAdapter.ts +104 -0
  405. package/src/composables/usePluginClient.ts +50 -4
  406. package/src/composables/usePluginConfig.ts +252 -0
  407. package/src/composables/usePluginWorkspace.ts +208 -0
  408. package/src/composables/useRackEditor.ts +2 -11
  409. package/src/composables/useRequestSyncState.ts +98 -28
  410. package/src/composables/useResourceCrud.ts +6 -16
  411. package/src/composables/useRovingFocus.ts +66 -0
  412. package/src/composables/useScheduleDrag.ts +37 -0
  413. package/src/composables/useWellPainting.ts +10 -30
  414. package/src/composables/useWellPlateAdapter.ts +5 -1
  415. package/src/composables/useWellPlateEditor.ts +1 -11
  416. package/src/composables/useWellPlateValidation.ts +5 -1
  417. package/src/composables/workspaceRecipes.ts +267 -0
  418. package/src/index.ts +19 -0
  419. package/src/permissions.ts +48 -9
  420. package/src/stores/auth.ts +1 -0
  421. package/src/stores/experiment.ts +2 -7
  422. package/src/stores/index.ts +9 -1
  423. package/src/stores/settings.ts +93 -1
  424. package/src/styles/components/audit-trail.css +5 -5
  425. package/src/styles/components/batch-progress-list.css +7 -0
  426. package/src/styles/components/color-slider.css +2 -2
  427. package/src/styles/components/data-state.css +30 -0
  428. package/src/styles/components/dataframe.css +29 -35
  429. package/src/styles/components/experiment-data-viewer.css +4 -4
  430. package/src/styles/components/experiment-timeline.css +3 -30
  431. package/src/styles/components/file-browser-modal.css +489 -0
  432. package/src/styles/components/file-picker.css +502 -0
  433. package/src/styles/components/form-builder.css +5 -5
  434. package/src/styles/components/icon-button.css +9 -0
  435. package/src/styles/components/lcms-sequence-table.css +16 -1
  436. package/src/styles/components/multi-select.css +1 -1
  437. package/src/styles/components/reagent-list.css +38 -31
  438. package/src/styles/components/sample-hierarchy-tree.css +5 -19
  439. package/src/styles/components/sample-selector.css +9 -2
  440. package/src/styles/components/schedule-calendar.css +8 -0
  441. package/src/styles/components/scientific-number.css +1 -1
  442. package/src/styles/components/secret-input.css +60 -0
  443. package/src/styles/components/well-plate.css +8 -0
  444. package/src/styles/index.css +12 -0
  445. package/src/styles/variables.css +29 -0
  446. package/src/templates/builderPresetControls.ts +1 -1
  447. package/src/templates/builderReadUtils.ts +1 -3
  448. package/src/templates/componentPlateHelpers.ts +3 -1
  449. package/src/templates/componentTargetResolvers.ts +1 -3
  450. package/src/templates/controlSchemaTargets.ts +1 -3
  451. package/src/templates/doseResponseAdapters.ts +2 -13
  452. package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
  453. package/src/templates/plateMapBuilder.ts +2 -2
  454. package/src/templates/qpcrPlateBuilder.ts +1 -1
  455. package/src/templates/templateValidators.ts +1 -1
  456. package/src/templates/timeCourseBuilder.ts +2 -2
  457. package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
  458. package/src/types/auth.ts +1 -0
  459. package/src/types/fileBrowserTypes.ts +85 -0
  460. package/src/types/filePicker.ts +72 -0
  461. package/src/types/form-builder.ts +1 -0
  462. package/src/types/index.ts +14 -0
  463. package/src/utils/color.ts +51 -0
  464. package/src/utils/errors.ts +29 -0
  465. package/src/utils/formModelSync.ts +1 -3
  466. package/src/utils/pluginIcon.ts +1 -3
  467. package/src/utils/pluginSecrets.ts +102 -0
  468. package/src/utils/records.ts +9 -0
  469. package/dist/EmptyState-p90quq8Z.js.map +0 -1
  470. package/dist/ExperimentPopover-tLwJ7XF4.js.map +0 -1
  471. package/dist/ExperimentSelectorModal-DyPAUCLw.js.map +0 -1
  472. package/dist/SettingsModal-BgKY93zh.js.map +0 -1
  473. package/dist/components-DkHddRMl.js.map +0 -1
  474. package/dist/composables/autoGroupConstants.d.ts +0 -1
  475. package/dist/composables/autoGroupGrouping.d.ts +0 -3
  476. package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
  477. package/dist/composables-C_i90sGS.js.map +0 -1
  478. package/dist/experiment-Cq145oEW.js.map +0 -1
  479. package/dist/experiment-utils-CLnzPPq5.js.map +0 -1
  480. package/dist/templates/builderDefaults.d.ts +0 -1
  481. package/dist/templates/plateGeometry.d.ts +0 -4
  482. package/dist/templates-DsP51i-S.js.map +0 -1
  483. package/dist/useApi-J6zFkHmn.js.map +0 -1
  484. package/dist/useControlSchema-BDx2Olha.js.map +0 -1
  485. package/dist/useDropdownState-DSb3BC3N.js.map +0 -1
  486. package/dist/useProtocolTemplates-CS_SQl6U.js.map +0 -1
  487. package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
  488. package/src/composables/autoGroupConstants.ts +0 -4
  489. package/src/composables/autoGroupGrouping.ts +0 -148
  490. package/src/composables/useAutoGroupInputSources.ts +0 -147
  491. package/src/templates/builderDefaults.ts +0 -11
  492. package/src/templates/plateGeometry.ts +0 -62
  493. /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → apiErrors.test.d.ts} +0 -0
@@ -0,0 +1,143 @@
1
+ <script setup lang="ts">
2
+ /** Demonstrates `useListReorder`: drag a row, or focus a handle and press Alt with the arrow keys. */
3
+ import { ref } from 'vue'
4
+ import { useListReorder } from './useListReorder'
5
+
6
+ interface Step { id: string; name: string }
7
+
8
+ const steps = ref<Step[]>([
9
+ { id: 's1', name: 'Thaw samples' },
10
+ { id: 's2', name: 'Quench metabolism' },
11
+ { id: 's3', name: 'Extract metabolites' },
12
+ { id: 's4', name: 'Dry down' },
13
+ ])
14
+
15
+ const handles = new Map<string, HTMLElement>()
16
+
17
+ function setHandle(id: string, el: Element | null) {
18
+ if (el instanceof HTMLElement) handles.set(id, el)
19
+ else handles.delete(id)
20
+ }
21
+
22
+ const {
23
+ draggingId,
24
+ dragOverId,
25
+ announcement,
26
+ announcerStyle,
27
+ onDragStart,
28
+ onDragOver,
29
+ onDragLeave,
30
+ onDrop,
31
+ onDragEnd,
32
+ onKeydown,
33
+ } = useListReorder<Step>({
34
+ items: () => steps.value,
35
+ getId: (step) => step.id,
36
+ getLabel: (step) => step.name,
37
+ getElement: (id) => handles.get(id),
38
+ itemNoun: 'Step',
39
+ onReorder: ({ items }) => {
40
+ steps.value = items
41
+ },
42
+ })
43
+
44
+ function initState() {
45
+ return { showAnnouncement: true }
46
+ }
47
+ </script>
48
+
49
+ <template>
50
+ <Story title="Composables/useListReorder">
51
+ <Variant title="Playground" :init-state="initState">
52
+ <template #default="{ state }">
53
+ <div style="padding: 2rem; max-width: 600px;">
54
+ <p class="mint-story-hint">
55
+ Drag a row, or focus its handle and press Alt with the up/down arrow keys.
56
+ </p>
57
+ <ul class="mint-story-list">
58
+ <li
59
+ v-for="(step, index) in steps"
60
+ :key="step.id"
61
+ class="mint-story-row"
62
+ :class="{
63
+ 'mint-story-row--dragging': draggingId === step.id,
64
+ 'mint-story-row--over': dragOverId === step.id,
65
+ }"
66
+ draggable="true"
67
+ @dragstart="onDragStart($event, step, index)"
68
+ @dragover="onDragOver($event, step, index)"
69
+ @dragleave="onDragLeave"
70
+ @drop="onDrop($event, step, index)"
71
+ @dragend="onDragEnd"
72
+ >
73
+ <button
74
+ :ref="(el) => setHandle(step.id, el as Element | null)"
75
+ type="button"
76
+ class="mint-story-handle"
77
+ :aria-label="`Reorder ${step.name}. Press Alt with the arrow keys to move it.`"
78
+ @keydown="onKeydown($event, step, index)"
79
+ >
80
+ ⠿
81
+ </button>
82
+ <span>{{ index + 1 }}. {{ step.name }}</span>
83
+ </li>
84
+ </ul>
85
+
86
+ <p v-if="state.showAnnouncement" class="mint-story-hint">
87
+ Live region: <em>{{ announcement || '—' }}</em>
88
+ </p>
89
+ <div role="status" aria-live="polite" :style="announcerStyle">{{ announcement }}</div>
90
+ </div>
91
+ </template>
92
+
93
+ <template #controls="{ state }">
94
+ <HstCheckbox v-model="state.showAnnouncement" title="Show live-region text" />
95
+ </template>
96
+ </Variant>
97
+ </Story>
98
+ </template>
99
+
100
+ <style scoped>
101
+ .mint-story-list {
102
+ list-style: none;
103
+ margin: 0;
104
+ padding: 0;
105
+ display: flex;
106
+ flex-direction: column;
107
+ gap: 0.25rem;
108
+ }
109
+
110
+ .mint-story-row {
111
+ display: flex;
112
+ align-items: center;
113
+ gap: 0.5rem;
114
+ padding: 0.5rem 0.75rem;
115
+ border: 1px solid var(--border-color);
116
+ border-radius: 0.5rem;
117
+ background: var(--bg-primary);
118
+ color: var(--text-primary);
119
+ }
120
+
121
+ .mint-story-row--dragging {
122
+ opacity: 0.5;
123
+ }
124
+
125
+ .mint-story-row--over {
126
+ border-color: var(--color-primary);
127
+ }
128
+
129
+ .mint-story-handle {
130
+ padding: 0;
131
+ border: 0;
132
+ background: none;
133
+ color: var(--text-muted);
134
+ cursor: grab;
135
+ font-size: 1rem;
136
+ }
137
+
138
+ .mint-story-hint {
139
+ margin: 0 0 0.75rem;
140
+ color: var(--text-secondary);
141
+ font-size: 0.8125rem;
142
+ }
143
+ </style>
@@ -0,0 +1,242 @@
1
+ import { nextTick, ref, type Ref } from 'vue'
2
+
3
+ /** Inline style for a visually hidden `aria-live` region (no global utility class in the SDK). */
4
+ export const REORDER_ANNOUNCER_STYLE = Object.freeze({
5
+ position: 'absolute',
6
+ width: '1px',
7
+ height: '1px',
8
+ padding: '0',
9
+ margin: '-1px',
10
+ overflow: 'hidden',
11
+ clip: 'rect(0, 0, 0, 0)',
12
+ whiteSpace: 'nowrap',
13
+ border: '0',
14
+ })
15
+
16
+ export interface UseReorderAnnouncerReturn {
17
+ /** Bind to a polite live region's text content. */
18
+ announcement: Ref<string>
19
+ /** Publishes a message to the live region. */
20
+ announce: (message: string) => void
21
+ /** Bind to the live region's `style` so it stays visually hidden. */
22
+ announcerStyle: typeof REORDER_ANNOUNCER_STYLE
23
+ }
24
+
25
+ /**
26
+ * Screen-reader announcements for drag/keyboard move interactions. Bind
27
+ * `announcement` to a `role="status" aria-live="polite"` element styled with
28
+ * `announcerStyle`.
29
+ */
30
+ export function useReorderAnnouncer(): UseReorderAnnouncerReturn {
31
+ const announcement = ref('')
32
+
33
+ function announce(message: string) {
34
+ // Re-announce identical consecutive messages by clearing first.
35
+ if (announcement.value === message) announcement.value = ''
36
+ void nextTick(() => {
37
+ announcement.value = message
38
+ })
39
+ }
40
+
41
+ return { announcement, announce, announcerStyle: REORDER_ANNOUNCER_STYLE }
42
+ }
43
+
44
+ export interface ListReorderMove<T> {
45
+ /** Index the item moved from, within `items()`. */
46
+ fromIndex: number
47
+ /** Index the item moved to, within `items()`. */
48
+ toIndex: number
49
+ /** The reordered array (a copy — `items()` is never mutated). */
50
+ items: T[]
51
+ /** Whether the move came from the keyboard or a pointer drag. */
52
+ source: 'keyboard' | 'drag'
53
+ }
54
+
55
+ export interface UseListReorderOptions<T> {
56
+ /** The list being reordered, in its canonical (not merely rendered) order. */
57
+ items: () => T[]
58
+ /** Stable id for an item; falls back to the render index when ids repeat. */
59
+ getId: (item: T, index: number) => string
60
+ /** Applies the move. The composable never mutates the source array. */
61
+ onReorder: (move: ListReorderMove<T>) => void
62
+ /** Human-readable name used in announcements. Defaults to the item's id. */
63
+ getLabel?: (item: T, index: number) => string
64
+ /** Blocks every reorder while it returns `true` (readonly / non-sortable lists). */
65
+ disabled?: () => boolean
66
+ /** Resolves the focusable element for an id so keyboard moves keep focus on the item. */
67
+ getElement?: (id: string) => HTMLElement | null | undefined
68
+ /** Noun used in announcements, e.g. `'Reagent'`. Default `'Item'`. */
69
+ itemNoun?: string
70
+ }
71
+
72
+ export interface UseListReorderReturn<T> {
73
+ /** Id of the item currently being dragged, or `null`. */
74
+ draggingId: Ref<string | null>
75
+ /** Id of the item the pointer is hovering as a drop target, or `null`. */
76
+ dragOverId: Ref<string | null>
77
+ isDragging: (id: string) => boolean
78
+ isDragOver: (id: string) => boolean
79
+ announcement: Ref<string>
80
+ announcerStyle: typeof REORDER_ANNOUNCER_STYLE
81
+ announce: (message: string) => void
82
+ /** Bind to the draggable element's `@dragstart`. */
83
+ onDragStart: (event: DragEvent, item: T, index: number) => void
84
+ /** Bind to `@dragover` — calls `preventDefault()` so the drop is accepted. */
85
+ onDragOver: (event: DragEvent, item: T, index: number) => void
86
+ /** Bind to `@dragleave`. */
87
+ onDragLeave: () => void
88
+ /** Bind to `@drop`. */
89
+ onDrop: (event: DragEvent, item: T, index: number) => void
90
+ /** Bind to `@dragend`. */
91
+ onDragEnd: () => void
92
+ /**
93
+ * Bind to the item's (or its drag handle's) `@keydown`: Alt+ArrowUp / Alt+ArrowLeft
94
+ * moves the item one position earlier, Alt+ArrowDown / Alt+ArrowRight one later.
95
+ */
96
+ onKeydown: (event: KeyboardEvent, item: T, index: number) => void
97
+ /** Moves an item between two indices of `items()` programmatically. */
98
+ move: (fromIndex: number, toIndex: number, source?: 'keyboard' | 'drag') => void
99
+ }
100
+
101
+ /** Pure helper: a copy of `items` with the entry at `from` moved to `to`. */
102
+ export function reorderList<T>(items: T[], from: number, to: number): T[] {
103
+ const next = [...items]
104
+ const [moved] = next.splice(from, 1)
105
+ next.splice(to, 0, moved)
106
+ return next
107
+ }
108
+
109
+ /**
110
+ * Keyboard-accessible list reordering shared by the SDK's drag-to-reorder lists.
111
+ * It owns the HTML5 drag state, the drop-index maths, and an Alt+Arrow keyboard
112
+ * alternative that announces every move through a polite live region — so a
113
+ * reorder never depends on a pointer.
114
+ */
115
+ export function useListReorder<T>(options: UseListReorderOptions<T>): UseListReorderReturn<T> {
116
+ const draggingId = ref<string | null>(null)
117
+ const dragOverId = ref<string | null>(null)
118
+ const { announcement, announce, announcerStyle } = useReorderAnnouncer()
119
+ const noun = options.itemNoun ?? 'Item'
120
+
121
+ function isDisabled(): boolean {
122
+ return options.disabled?.() === true
123
+ }
124
+
125
+ function idFor(item: T, index: number): string {
126
+ return options.getId(item, index)
127
+ }
128
+
129
+ /** Index within `items()`, resolved by id so filtered/sorted renders still map back. */
130
+ function indexOf(item: T, renderIndex: number): number {
131
+ const id = idFor(item, renderIndex)
132
+ const found = options.items().findIndex((candidate, index) => idFor(candidate, index) === id)
133
+ return found === -1 ? renderIndex : found
134
+ }
135
+
136
+ function labelFor(index: number): string {
137
+ const item = options.items()[index]
138
+ if (item === undefined) return noun
139
+ return options.getLabel?.(item, index) ?? idFor(item, index)
140
+ }
141
+
142
+ function clearDragState() {
143
+ draggingId.value = null
144
+ dragOverId.value = null
145
+ }
146
+
147
+ function move(fromIndex: number, toIndex: number, source: 'keyboard' | 'drag' = 'keyboard') {
148
+ if (isDisabled()) return
149
+ const items = options.items()
150
+ if (
151
+ fromIndex === toIndex ||
152
+ fromIndex < 0 ||
153
+ toIndex < 0 ||
154
+ fromIndex >= items.length ||
155
+ toIndex >= items.length
156
+ ) return
157
+
158
+ const movedId = idFor(items[fromIndex], fromIndex)
159
+ const label = labelFor(fromIndex)
160
+ options.onReorder({
161
+ fromIndex,
162
+ toIndex,
163
+ items: reorderList(items, fromIndex, toIndex),
164
+ source,
165
+ })
166
+ announce(`${label} moved to position ${toIndex + 1} of ${items.length}.`)
167
+ void nextTick(() => options.getElement?.(movedId)?.focus())
168
+ }
169
+
170
+ function onDragStart(event: DragEvent, item: T, index: number) {
171
+ if (isDisabled()) return
172
+ const id = idFor(item, index)
173
+ draggingId.value = id
174
+ if (event.dataTransfer) {
175
+ event.dataTransfer.effectAllowed = 'move'
176
+ event.dataTransfer.setData('text/plain', id)
177
+ }
178
+ }
179
+
180
+ function onDragOver(event: DragEvent, item: T, index: number) {
181
+ if (isDisabled() || draggingId.value === null) return
182
+ event.preventDefault()
183
+ if (event.dataTransfer) event.dataTransfer.dropEffect = 'move'
184
+ const id = idFor(item, index)
185
+ dragOverId.value = id === draggingId.value ? null : id
186
+ }
187
+
188
+ function onDragLeave() {
189
+ dragOverId.value = null
190
+ }
191
+
192
+ function onDrop(event: DragEvent, item: T, index: number) {
193
+ if (isDisabled() || draggingId.value === null) {
194
+ clearDragState()
195
+ return
196
+ }
197
+ event.preventDefault()
198
+
199
+ const items = options.items()
200
+ const fromIndex = items.findIndex((candidate, i) => idFor(candidate, i) === draggingId.value)
201
+ const toIndex = indexOf(item, index)
202
+ clearDragState()
203
+ if (fromIndex === -1) return
204
+ move(fromIndex, toIndex, 'drag')
205
+ }
206
+
207
+ function onDragEnd() {
208
+ clearDragState()
209
+ }
210
+
211
+ function onKeydown(event: KeyboardEvent, item: T, index: number) {
212
+ if (isDisabled() || !event.altKey) return
213
+ const direction =
214
+ event.key === 'ArrowUp' || event.key === 'ArrowLeft'
215
+ ? -1
216
+ : event.key === 'ArrowDown' || event.key === 'ArrowRight'
217
+ ? 1
218
+ : 0
219
+ if (direction === 0) return
220
+
221
+ event.preventDefault()
222
+ const fromIndex = indexOf(item, index)
223
+ move(fromIndex, fromIndex + direction, 'keyboard')
224
+ }
225
+
226
+ return {
227
+ draggingId,
228
+ dragOverId,
229
+ isDragging: (id: string) => draggingId.value === id,
230
+ isDragOver: (id: string) => dragOverId.value === id,
231
+ announcement,
232
+ announcerStyle,
233
+ announce,
234
+ onDragStart,
235
+ onDragOver,
236
+ onDragLeave,
237
+ onDrop,
238
+ onDragEnd,
239
+ onKeydown,
240
+ move,
241
+ }
242
+ }
@@ -0,0 +1,90 @@
1
+ import { nextTick } from 'vue'
2
+
3
+ export interface UseMenuKeyboardOptions {
4
+ /** Returns the currently navigable items inside the open panel, in DOM order. */
5
+ items: () => HTMLElement[]
6
+ /** True while the panel is open. */
7
+ isOpen: () => boolean
8
+ /** Opens the panel. */
9
+ open: () => void
10
+ /** Closes the panel. When `returnFocus` is true, focus should return to the trigger. */
11
+ close: (returnFocus?: boolean) => void
12
+ }
13
+
14
+ export interface UseMenuKeyboardReturn {
15
+ /**
16
+ * Bind to the trigger's `@keydown`. ArrowDown/Enter/Space open the panel (when
17
+ * closed) and focus its first item; ArrowUp opens it focused on the last item.
18
+ */
19
+ handleTriggerKeydown: (event: KeyboardEvent) => void
20
+ /**
21
+ * Bind to the open panel's `@keydown`. ArrowUp/ArrowDown cycle focus with
22
+ * wraparound, Home/End jump to the first/last item, Escape closes and returns
23
+ * focus to the trigger, and Tab closes without moving focus.
24
+ */
25
+ handlePanelKeydown: (event: KeyboardEvent) => void
26
+ }
27
+
28
+ /**
29
+ * Shared keyboard contract for menu- and listbox-style disclosure panels (the
30
+ * WAI-ARIA menu button pattern). Used by ActionMenu, AppAvatarMenu and DropdownButton,
31
+ * each pairing it with `useDropdownState` for the disclosure state itself.
32
+ */
33
+ export function useMenuKeyboard(options: UseMenuKeyboardOptions): UseMenuKeyboardReturn {
34
+ function focusItem(position: 'first' | 'last') {
35
+ void nextTick(() => {
36
+ const items = options.items()
37
+ const target = position === 'first' ? items[0] : items[items.length - 1]
38
+ target?.focus()
39
+ })
40
+ }
41
+
42
+ function handleTriggerKeydown(event: KeyboardEvent) {
43
+ if (options.isOpen()) return
44
+
45
+ if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {
46
+ event.preventDefault()
47
+ options.open()
48
+ focusItem('first')
49
+ return
50
+ }
51
+ if (event.key === 'ArrowUp') {
52
+ event.preventDefault()
53
+ options.open()
54
+ focusItem('last')
55
+ }
56
+ }
57
+
58
+ function handlePanelKeydown(event: KeyboardEvent) {
59
+ const items = options.items()
60
+ const currentIndex = items.indexOf(document.activeElement as HTMLElement)
61
+
62
+ if (event.key === 'Escape') {
63
+ event.preventDefault()
64
+ options.close(true)
65
+ return
66
+ }
67
+ if (event.key === 'Tab') {
68
+ options.close()
69
+ return
70
+ }
71
+ if (event.key === 'Home') {
72
+ event.preventDefault()
73
+ items[0]?.focus()
74
+ return
75
+ }
76
+ if (event.key === 'End') {
77
+ event.preventDefault()
78
+ items[items.length - 1]?.focus()
79
+ return
80
+ }
81
+ if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return
82
+
83
+ event.preventDefault()
84
+ const direction = event.key === 'ArrowDown' ? 1 : -1
85
+ const nextIndex = (Math.max(currentIndex, 0) + direction + items.length) % items.length
86
+ items[nextIndex]?.focus()
87
+ }
88
+
89
+ return { handleTriggerKeydown, handlePanelKeydown }
90
+ }
@@ -1,4 +1,5 @@
1
1
  import { computed, ref, shallowRef, type ComputedRef, type Ref, type ShallowRef } from 'vue'
2
+ import { readErrorMessage } from '../utils/errors'
2
3
 
3
4
  export interface OptimisticMutationContext<TVariables, TSnapshot> {
4
5
  variables: TVariables
@@ -32,7 +33,11 @@ export interface UseOptimisticMutationReturn<TVariables, TData, TSnapshot = unkn
32
33
  reset: () => void
33
34
  }
34
35
 
35
- /** Run async mutations with optional optimistic local updates and rollback. */
36
+ /**
37
+ * Run async mutations with optional optimistic local updates and rollback.
38
+ *
39
+ * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useRequestSyncState()` instead.
40
+ */
36
41
  export function useOptimisticMutation<TVariables, TData, TSnapshot = unknown>(
37
42
  options: UseOptimisticMutationOptions<TVariables, TData, TSnapshot>,
38
43
  ): UseOptimisticMutationReturn<TVariables, TData, TSnapshot> {
@@ -90,18 +95,3 @@ export function useOptimisticMutation<TVariables, TData, TSnapshot = unknown>(
90
95
  reset,
91
96
  }
92
97
  }
93
-
94
- function readErrorMessage(value: unknown): string {
95
- if (value instanceof Error && value.message) return value.message
96
- if (typeof value === 'string' && value.trim()) return value
97
- if (
98
- typeof value === 'object'
99
- && value !== null
100
- && 'message' in value
101
- && typeof (value as { message?: unknown }).message === 'string'
102
- && (value as { message: string }).message.trim()
103
- ) {
104
- return (value as { message: string }).message
105
- }
106
- return 'Request failed.'
107
- }
@@ -0,0 +1,104 @@
1
+ import type { PickerAdapter, PickerNode, PickerRequest } from '../types/filePicker'
2
+ import type { FileDirectoryListing, ServerMount } from '../types/fileBrowserTypes'
3
+ import { useApi } from './useApi'
4
+ import { getInjectedPlatformContext } from './platformContextHelpers'
5
+ import { pickerFormat } from './filePicker/validation'
6
+
7
+ /** Opaque picker identity; decode before passing a selection to a mount-scoped API. */
8
+ export function encodePlatformPickerPath(mountId: string, path = ''): string {
9
+ return JSON.stringify([mountId, path])
10
+ }
11
+ export function decodePlatformPickerPath(path: string): { mountId: string; path: string } {
12
+ const decoded: unknown = JSON.parse(path)
13
+ if (
14
+ !Array.isArray(decoded) ||
15
+ decoded.length !== 2 ||
16
+ !decoded.every((item) => typeof item === 'string') ||
17
+ !decoded[0]
18
+ ) {
19
+ throw new Error('Invalid platform picker path.')
20
+ }
21
+ return { mountId: decoded[0], path: decoded[1] }
22
+ }
23
+
24
+ /** Adapt the authenticated MINT mount API without exposing absolute host paths. */
25
+ export function usePlatformFilePickerAdapter(options: { apiBaseUrl?: string } = {}): PickerAdapter {
26
+ const api = useApi({
27
+ baseUrl: options.apiBaseUrl ?? getInjectedPlatformContext()?.platformApiUrl,
28
+ })
29
+ const mountLabels = new Map<string, string>()
30
+ async function listRoot(request?: PickerRequest): Promise<PickerNode[]> {
31
+ try {
32
+ const { mounts } = await api.get<{ mounts: ServerMount[] }>('/filesystem/mounts', {
33
+ signal: request?.signal,
34
+ })
35
+ return mounts.map((mount) => {
36
+ mountLabels.set(mount.id, mount.label)
37
+ return {
38
+ kind: 'folder',
39
+ path: encodePlatformPickerPath(mount.id),
40
+ name: mount.label,
41
+ parentPath: null,
42
+ parentName: 'Server mounts',
43
+ unavailableReason: mount.available === false ? 'This mount is offline.' : undefined,
44
+ }
45
+ })
46
+ } catch (cause) {
47
+ if ((cause as { response?: { status?: number } }).response?.status === 404) return []
48
+ throw cause
49
+ }
50
+ }
51
+ async function listChildren(path: string, request?: PickerRequest): Promise<PickerNode[]> {
52
+ const location = decodePlatformPickerPath(path)
53
+ const query = new URLSearchParams({ mount_id: location.mountId, path: location.path })
54
+ const listing = await api.get<FileDirectoryListing>(`/filesystem/browse?${query}`, {
55
+ signal: request?.signal,
56
+ })
57
+ if (listing.truncated)
58
+ throw new Error(
59
+ 'This directory exceeds the server listing limit. Choose a smaller data directory.',
60
+ )
61
+ return (listing.entries ?? []).map(
62
+ (entry) =>
63
+ ({
64
+ kind: entry.kind === 'directory' ? 'folder' : 'file',
65
+ path: encodePlatformPickerPath(location.mountId, entry.path),
66
+ parentPath: path,
67
+ parentName: `${mountLabels.get(location.mountId) ?? location.mountId}${location.path ? ` / ${location.path}` : ''}`,
68
+ name: entry.name,
69
+ bytes: entry.size_bytes,
70
+ ...(entry.kind === 'directory'
71
+ ? { hasChildren: entry.child_count !== 0 }
72
+ : { format: pickerFormat(entry.name) }),
73
+ }) as PickerNode,
74
+ )
75
+ }
76
+ return {
77
+ listRoot,
78
+ listChildren,
79
+ async search(query, scope, request) {
80
+ const matches: PickerNode[] = []
81
+ const queue = [scope.path]
82
+ const visited = new Set<string>()
83
+ while (queue.length) {
84
+ request?.signal?.throwIfAborted()
85
+ const path = queue.shift()!
86
+ if (visited.has(path)) continue
87
+ visited.add(path)
88
+ if (visited.size > 500)
89
+ throw new Error(
90
+ 'Search reached its folder limit. Search a smaller location or turn off Subfolders.',
91
+ )
92
+ const nodes = path ? await listChildren(path, request) : await listRoot(request)
93
+ for (const node of nodes) {
94
+ if (node.name.toLowerCase().includes(query.toLowerCase())) matches.push(node)
95
+ if (scope.recursive && node.kind === 'folder' && !node.unavailableReason)
96
+ queue.push(node.path)
97
+ }
98
+ if (matches.length > 10000)
99
+ throw new Error('Too many search results. Use a more specific search.')
100
+ }
101
+ return matches
102
+ },
103
+ }
104
+ }