@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,259 @@
1
+ import { computed, ref, shallowRef, watch } from 'vue'
2
+ import type {
3
+ PickerCapability,
4
+ PickerExcluded,
5
+ PickerFile,
6
+ PickerNode,
7
+ PickerSelection,
8
+ PickerSelectionMode,
9
+ } from '../../types/filePicker'
10
+ import type { usePickerNavigation } from './usePickerNavigation'
11
+ import { pickerExclusion } from './validation'
12
+
13
+ type Navigation = ReturnType<typeof usePickerNavigation>
14
+ export function usePickerSelection(
15
+ nav: Navigation,
16
+ mode: () => PickerSelectionMode,
17
+ capability: () => PickerCapability | undefined,
18
+ skipBlanks: () => boolean,
19
+ ) {
20
+ const keys = ref(new Set<string>())
21
+ const dropped = ref(new Set<string>())
22
+ const focusPath = shallowRef('')
23
+ const resolving = shallowRef(false)
24
+ const resolutionError = shallowRef('')
25
+ let anchor = ''
26
+ let generation = 0
27
+
28
+ function ancestorSelected(node: PickerNode, candidates = keys.value): boolean {
29
+ const seen = new Set<string>()
30
+ let parent = node.parentPath
31
+ while (parent && !seen.has(parent)) {
32
+ if (candidates.has(parent)) return true
33
+ seen.add(parent)
34
+ parent = nav.nodes.value.get(parent)?.parentPath
35
+ }
36
+ return false
37
+ }
38
+ function exclusion(node: PickerNode) {
39
+ if (!nav.isAllowed(node))
40
+ return { path: node.path, name: node.name, reason: 'forbidden' as const }
41
+ const own = pickerExclusion(node, capability(), skipBlanks())
42
+ if (own) return own
43
+ const seen = new Set<string>()
44
+ let parent = node.parentPath
45
+ while (parent && !seen.has(parent)) {
46
+ seen.add(parent)
47
+ const folder = nav.nodes.value.get(parent)
48
+ if (!folder) break
49
+ const inherited = pickerExclusion(folder, capability(), skipBlanks())
50
+ if (inherited) return { ...inherited, path: node.path, name: node.name }
51
+ parent = folder.parentPath
52
+ }
53
+ return null
54
+ }
55
+ function selected(node: PickerNode): boolean {
56
+ return (
57
+ !exclusion(node) &&
58
+ !dropped.value.has(node.path) &&
59
+ !ancestorSelected(node, dropped.value) &&
60
+ (keys.value.has(node.path) || (mode() === 'folder+files' && ancestorSelected(node)))
61
+ )
62
+ }
63
+ function selectable(node: PickerNode): boolean {
64
+ if (exclusion(node)) return false
65
+ return node.kind === 'folder'
66
+ ? mode() === 'folder' || mode() === 'folder+files'
67
+ : mode() !== 'folder'
68
+ }
69
+ function select(
70
+ node: PickerNode,
71
+ modifiers: { metaKey?: boolean; ctrlKey?: boolean; shiftKey?: boolean; toggle?: boolean } = {},
72
+ ) {
73
+ if (exclusion(node)) return
74
+ focusPath.value = node.path
75
+ if (!selectable(node)) return
76
+ const multi = mode() === 'multi-file' || mode() === 'folder+files'
77
+ // Multi modes behave like a checklist: a plain click (or Space) adds or
78
+ // removes one row, Shift extends a range, Ctrl/Cmd is accepted for habit.
79
+ const additive = multi && (modifiers.metaKey || modifiers.ctrlKey || modifiers.toggle)
80
+ if (multi && modifiers.shiftKey && anchor) {
81
+ const rows = nav.rows.value.map((row) => row.node)
82
+ const from = rows.findIndex((item) => item.path === anchor)
83
+ const to = rows.findIndex((item) => item.path === node.path)
84
+ if (from >= 0 && to >= 0) {
85
+ keys.value = new Set([
86
+ ...(additive ? keys.value : []),
87
+ ...rows
88
+ .slice(Math.min(from, to), Math.max(from, to) + 1)
89
+ .filter(selectable)
90
+ .map((item) => item.path),
91
+ ])
92
+ dropped.value.clear()
93
+ return
94
+ }
95
+ }
96
+ if (additive || (modifiers.toggle && (selected(node) || dropped.value.has(node.path)))) {
97
+ if (mode() === 'folder+files' && ancestorSelected(node)) {
98
+ if (dropped.value.has(node.path)) dropped.value.delete(node.path)
99
+ else dropped.value.add(node.path)
100
+ } else if (keys.value.has(node.path)) keys.value.delete(node.path)
101
+ else {
102
+ keys.value.add(node.path)
103
+ dropped.value.delete(node.path)
104
+ }
105
+ } else {
106
+ keys.value = new Set([node.path])
107
+ dropped.value.clear()
108
+ }
109
+ anchor = node.path
110
+ }
111
+ function reset(selection?: PickerSelection | null) {
112
+ ++generation
113
+ keys.value.clear()
114
+ dropped.value.clear()
115
+ resolving.value = false
116
+ resolutionError.value = ''
117
+ focusPath.value = ''
118
+ if (selection?.source === 'server') {
119
+ const files =
120
+ mode() === 'folder'
121
+ ? []
122
+ : mode() === 'single-file'
123
+ ? selection.files.slice(0, 1)
124
+ : selection.files
125
+ const folders =
126
+ mode() === 'folder'
127
+ ? selection.folders.slice(0, 1)
128
+ : mode() === 'folder+files'
129
+ ? selection.folders
130
+ : []
131
+ nav.register(files)
132
+ folders.forEach((path) => {
133
+ if (!nav.nodes.value.has(path))
134
+ nav.register([
135
+ { kind: 'folder', path, name: 'Selected folder', parentName: 'Selected location' },
136
+ ])
137
+ keys.value.add(path)
138
+ })
139
+ files.forEach((file) => keys.value.add(file.path))
140
+ selection.excluded
141
+ .filter((item) => item.reason === 'deselected')
142
+ .forEach((item) => dropped.value.add(item.path))
143
+ }
144
+ }
145
+ const roots = computed(() =>
146
+ [...keys.value]
147
+ .map((key) => nav.nodes.value.get(key))
148
+ .filter((node): node is PickerNode => !!node && !ancestorSelected(node) && nav.isAllowed(node)),
149
+ )
150
+ const chosen = computed(() => {
151
+ const files: PickerFile[] = []
152
+ const excluded: PickerExcluded[] = []
153
+ for (const node of nav.nodes.value.values()) {
154
+ if (!nav.isAllowed(node)) continue
155
+ if (!keys.value.has(node.path) && !ancestorSelected(node)) continue
156
+ const reason =
157
+ exclusion(node) ??
158
+ (dropped.value.has(node.path)
159
+ ? { path: node.path, name: node.name, reason: 'deselected' as const }
160
+ : null)
161
+ // A dropped folder excludes its descendants as well.
162
+ const droppedByParent = ancestorSelected(node, dropped.value)
163
+ if (reason || droppedByParent) {
164
+ if (node.kind === 'file' || reason?.reason === 'unreadable')
165
+ excluded.push(reason ?? { path: node.path, name: node.name, reason: 'deselected' })
166
+ } else if (node.kind === 'file') files.push(node)
167
+ }
168
+ return { files, excluded, bytes: files.reduce((total, node) => total + (node.bytes ?? 0), 0) }
169
+ })
170
+ async function resolve() {
171
+ const token = ++generation
172
+ resolving.value = true
173
+ resolutionError.value = ''
174
+ let count = 0
175
+ const seen = new Set<string>()
176
+ async function walk(node: PickerNode, ancestors: string[] = []): Promise<PickerFile[]> {
177
+ if (token !== generation) throw new DOMException('Cancelled', 'AbortError')
178
+ if (!nav.isAllowed(node)) return []
179
+ if (node.kind === 'file') return [node]
180
+ if (node.unavailableReason) return []
181
+ if (ancestors.includes(node.path))
182
+ throw new Error('The adapter returned a circular folder tree.')
183
+ if (seen.has(node.path)) return []
184
+ seen.add(node.path)
185
+ if (++count > 500 || ancestors.length > 30)
186
+ throw new Error('This selection is too large to validate. Choose a smaller folder.')
187
+ const children = await nav.loadChildren(node.path, ancestors)
188
+ const files: PickerFile[] = []
189
+ for (const child of children) files.push(...(await walk(child, [...ancestors, node.path])))
190
+ if (token !== generation) throw new DOMException('Cancelled', 'AbortError')
191
+ const formats: Record<string, number> = {}
192
+ files.forEach((file) => {
193
+ formats[file.format] = (formats[file.format] ?? 0) + 1
194
+ })
195
+ nav.register([
196
+ {
197
+ ...node,
198
+ fileCount: files.length,
199
+ bytes: files.reduce((sum, file) => sum + (file.bytes ?? 0), 0),
200
+ formats,
201
+ },
202
+ ])
203
+ return files
204
+ }
205
+ try {
206
+ for (const node of roots.value) await walk(node)
207
+ if (token === generation) {
208
+ // Resolved descendants inherit their folder, including restored selections.
209
+ for (const key of [...keys.value]) {
210
+ const node = nav.nodes.value.get(key)
211
+ if (node && ancestorSelected(node)) keys.value.delete(key)
212
+ }
213
+ }
214
+ } catch (cause) {
215
+ if (token === generation)
216
+ resolutionError.value =
217
+ cause instanceof Error ? cause.message : 'Could not validate the selection.'
218
+ } finally {
219
+ if (token === generation) resolving.value = false
220
+ }
221
+ }
222
+ const focused = computed(() => {
223
+ const node = nav.nodes.value.get(focusPath.value)
224
+ return node && nav.isAllowed(node) ? node : roots.value[roots.value.length - 1] ?? null
225
+ })
226
+ watch(
227
+ () => new Map([...nav.nodes.value].map(([path, node]) => [path, nav.isAllowed(node)])),
228
+ (allowed, previous) => {
229
+ if (keys.value.size && [...allowed].some(([path, value]) =>
230
+ previous.has(path) && value !== previous.get(path),
231
+ )) void resolve()
232
+ },
233
+ )
234
+ function folderProgress(node: PickerNode): string {
235
+ if (node.kind !== 'folder' || node.fileCount == null) return ''
236
+ const allowed = chosen.value.files.filter((file) =>
237
+ ancestorSelected(file, new Set([node.path])),
238
+ ).length
239
+ return `${selected(node) ? allowed : 0} / ${node.fileCount}`
240
+ }
241
+ return {
242
+ keys,
243
+ dropped,
244
+ focusPath,
245
+ resolving,
246
+ resolutionError,
247
+ roots,
248
+ chosen,
249
+ focused,
250
+ select,
251
+ selected,
252
+ selectable,
253
+ exclusion,
254
+ reset,
255
+ resolve,
256
+ folderProgress,
257
+ ancestorSelected,
258
+ }
259
+ }
@@ -0,0 +1,41 @@
1
+ import type { PickerCapability, PickerExcluded, PickerNode } from '../../types/filePicker'
2
+
3
+ export function normalizePickerFormat(format: string): string {
4
+ return format.trim().replace(/^\./, '').toLowerCase()
5
+ }
6
+
7
+ export function pickerExclusion(
8
+ node: PickerNode,
9
+ capability?: PickerCapability,
10
+ skipBlanks = false,
11
+ ): PickerExcluded | null {
12
+ const base = { path: node.path, name: node.name }
13
+ if (node.unavailableReason) return { ...base, reason: 'unreadable' }
14
+ if (skipBlanks && capability?.isBlank?.(node)) return { ...base, reason: 'blank' }
15
+ if (node.kind === 'folder') return null
16
+ const formats = capability?.formats.map(normalizePickerFormat) ?? []
17
+ if (formats.length && !formats.some((format) => node.name.toLowerCase().endsWith(`.${format}`))) {
18
+ return { ...base, reason: 'unsupported' }
19
+ }
20
+ if (capability?.maxBytes != null && node.bytes != null && node.bytes > capability.maxBytes) {
21
+ return { ...base, reason: 'tooLarge' }
22
+ }
23
+ return null
24
+ }
25
+
26
+ export function pickerReason(excluded: PickerExcluded | null, node?: PickerNode): string {
27
+ if (!excluded) return ''
28
+ return {
29
+ unsupported: 'This format is not supported by this source.',
30
+ tooLarge: 'This file exceeds the size limit for this source.',
31
+ blank: 'Skipped by the blank-file rule.',
32
+ unreadable: node?.unavailableReason || 'This item cannot be read.',
33
+ deselected: 'Removed from the selection.',
34
+ forbidden: 'This item is not permitted by the system filter.',
35
+ }[excluded.reason]
36
+ }
37
+
38
+ export function pickerFormat(name: string): string {
39
+ const compound = /\.(mzml|mzxml)\.gz$/i.exec(name)
40
+ return compound ? `${compound[1]}.gz` : name.includes('.') ? name.split('.').pop()! : ''
41
+ }
@@ -0,0 +1,104 @@
1
+ import { computed } from 'vue'
2
+ import type { ComputedRef } from 'vue'
3
+ import type {
4
+ BioTemplateComponentBinding,
5
+ BioTemplateComponentBindingsById,
6
+ BioTemplateComponentImport,
7
+ BioTemplateComponentPropsByComponent,
8
+ BioTemplateComponentPropsBinding,
9
+ BioTemplateComponentPropsById,
10
+ BioTemplateComponentPropsLookupOptions,
11
+ BioTemplateComponentSnippet,
12
+ BioTemplateComponentUsage,
13
+ } from './useBioTemplateComponents'
14
+
15
+ /**
16
+ * The template-component slice of `UseBioTemplateWorkspaceReturn`: the ~9 keys every
17
+ * bio-template workspace composable (`useBioTemplateWorkspace`, `useBioTemplatePackWorkspace`,
18
+ * `useBioTemplatePresetWorkspace`) re-exposes verbatim from `useBioTemplateComponents()`.
19
+ */
20
+ export interface BioTemplateWorkspaceComponentBindings {
21
+ componentBindings: BioTemplateComponentBinding[]
22
+ componentBindingsById: BioTemplateComponentBindingsById
23
+ componentImports: BioTemplateComponentImport[]
24
+ componentProps: BioTemplateComponentPropsBinding[]
25
+ componentPropsById: BioTemplateComponentPropsById
26
+ componentPropsByComponent: BioTemplateComponentPropsByComponent
27
+ componentSnippets: BioTemplateComponentSnippet[]
28
+ componentUsage: BioTemplateComponentUsage | null
29
+ getComponentProps: (component: string, options?: BioTemplateComponentPropsLookupOptions) => Record<string, unknown> | undefined
30
+ }
31
+
32
+ /** Structural source shape accepted by {@link flattenWorkspaceComponentBindings}. */
33
+ export interface BioTemplateWorkspaceComponentSource {
34
+ componentBindings: BioTemplateComponentBinding[]
35
+ componentBindingsById: BioTemplateComponentBindingsById
36
+ componentImports: BioTemplateComponentImport[]
37
+ componentProps: BioTemplateComponentPropsBinding[]
38
+ componentPropsById: BioTemplateComponentPropsById
39
+ componentPropsByComponent: BioTemplateComponentPropsByComponent
40
+ componentSnippets: BioTemplateComponentSnippet[]
41
+ componentUsage: BioTemplateComponentUsage | null
42
+ getComponentProps: (component: string, options?: BioTemplateComponentPropsLookupOptions) => Record<string, unknown> | undefined
43
+ }
44
+
45
+ /**
46
+ * Pick the shared template-component binding keys off a resolved bio-template workspace
47
+ * (or its `components` source directly), so composables that build on `useBioTemplateWorkspace`
48
+ * spread one object instead of re-listing all 9 keys by hand.
49
+ *
50
+ * @example Recommended
51
+ * ```ts
52
+ * const bindings = { renderer, ...flattenWorkspaceComponentBindings(components) }
53
+ * ```
54
+ */
55
+ export function flattenWorkspaceComponentBindings(
56
+ source: BioTemplateWorkspaceComponentSource,
57
+ ): BioTemplateWorkspaceComponentBindings {
58
+ return {
59
+ componentBindings: source.componentBindings,
60
+ componentBindingsById: source.componentBindingsById,
61
+ componentImports: source.componentImports,
62
+ componentProps: source.componentProps,
63
+ componentPropsById: source.componentPropsById,
64
+ componentPropsByComponent: source.componentPropsByComponent,
65
+ componentSnippets: source.componentSnippets,
66
+ componentUsage: source.componentUsage,
67
+ getComponentProps: source.getComponentProps,
68
+ }
69
+ }
70
+
71
+ /** Keys of {@link BioTemplateWorkspaceComponentBindings} that are plain (non-reactive) values, lifted to `ComputedRef`s by {@link liftWorkspaceComponentBindings}. */
72
+ export type LiftedBioTemplateWorkspaceComponentBindings =
73
+ { [K in Exclude<keyof BioTemplateWorkspaceComponentBindings, 'getComponentProps'>]: ComputedRef<BioTemplateWorkspaceComponentBindings[K]> }
74
+ & { getComponentProps: BioTemplateWorkspaceComponentBindings['getComponentProps'] }
75
+
76
+ /**
77
+ * `computed()`-lifted version of {@link flattenWorkspaceComponentBindings} for composables
78
+ * that hold their resolved workspace behind a `ComputedRef` (e.g. a regenerated workspace
79
+ * swapped in via `shallowRef`/`effectScope`), so each key stays independently reactive
80
+ * instead of forcing consumers to unwrap the whole workspace to read one field.
81
+ * `getComponentProps` stays a plain callable function, matching the un-lifted composables.
82
+ *
83
+ * @example Recommended
84
+ * ```ts
85
+ * const workspace = computed(() => workspaceRef.value)
86
+ * const { componentBindings, componentProps, getComponentProps } = liftWorkspaceComponentBindings(workspace)
87
+ * ```
88
+ */
89
+ export function liftWorkspaceComponentBindings<TSource extends BioTemplateWorkspaceComponentSource>(
90
+ workspace: ComputedRef<TSource>,
91
+ ): LiftedBioTemplateWorkspaceComponentBindings {
92
+ return {
93
+ componentBindings: computed(() => workspace.value.componentBindings),
94
+ componentBindingsById: computed(() => workspace.value.componentBindingsById),
95
+ componentImports: computed(() => workspace.value.componentImports),
96
+ componentProps: computed(() => workspace.value.componentProps),
97
+ componentPropsById: computed(() => workspace.value.componentPropsById),
98
+ componentPropsByComponent: computed(() => workspace.value.componentPropsByComponent),
99
+ componentSnippets: computed(() => workspace.value.componentSnippets),
100
+ componentUsage: computed(() => workspace.value.componentUsage),
101
+ getComponentProps: (component: string, options?: BioTemplateComponentPropsLookupOptions) =>
102
+ workspace.value.getComponentProps(component, options),
103
+ }
104
+ }
@@ -2,6 +2,7 @@ import type { Component } from 'vue'
2
2
  import type { FormFieldType } from '../types/form-builder'
3
3
 
4
4
  import BaseInput from '../components/BaseInput.vue'
5
+ import SecretInput from '../components/SecretInput.vue'
5
6
  import BaseTextarea from '../components/BaseTextarea.vue'
6
7
  import BaseSelect from '../components/BaseSelect.vue'
7
8
  import MultiSelect from '../components/MultiSelect.vue'
@@ -34,6 +35,7 @@ const registry: Record<FormFieldType, RegistryEntry> = {
34
35
  text: { component: BaseInput, defaults: { type: 'text' }, vModel: true },
35
36
  email: { component: BaseInput, defaults: { type: 'email' }, vModel: true },
36
37
  password: { component: BaseInput, defaults: { type: 'password' }, vModel: true },
38
+ secret: { component: SecretInput, defaults: {}, vModel: true },
37
39
  tel: { component: BaseInput, defaults: { type: 'tel' }, vModel: true },
38
40
  url: { component: BaseInput, defaults: { type: 'url' }, vModel: true },
39
41
  search: { component: BaseInput, defaults: { type: 'search' }, vModel: true },
@@ -75,6 +77,9 @@ export function getTypeDefault(type: FormFieldType): unknown {
75
77
  case 'multiselect':
76
78
  case 'tags':
77
79
  return []
80
+ case 'secret':
81
+ // A secret field has no empty string state: `null` means "not stored".
82
+ return null
78
83
  default:
79
84
  return ''
80
85
  }
@@ -153,6 +153,7 @@ export {
153
153
  type UseGeneratedAnalysisReturn,
154
154
  } from './useGeneratedAnalysis'
155
155
  export { useAutoGroup, DEFAULT_COLORS, extractSamplesFromDesignData } from './useAutoGroup'
156
+ export { usePluginConfig, type UsePluginConfigReturn } from './usePluginConfig'
156
157
  export {
157
158
  useReagentSeries,
158
159
  generateDilutionSeries,
@@ -173,6 +174,11 @@ export {
173
174
  type UseAnalysisArtifactsOptions,
174
175
  type UseAnalysisArtifactsReturn,
175
176
  } from './useAnalysisArtifacts'
177
+ export {
178
+ useFileBrowser,
179
+ type UseFileBrowserOptions,
180
+ type UseFileBrowserReturn,
181
+ } from './useFileBrowser'
176
182
  export {
177
183
  buildAnalysisArtifactTargetQuery,
178
184
  parseAnalysisArtifactTarget,
@@ -487,6 +493,7 @@ export {
487
493
  pluginFormDataFromPayload,
488
494
  resolvePluginBaseUrl,
489
495
  uploadPluginEndpoint,
496
+ usePluginClient,
490
497
  usePluginEventStream,
491
498
  usePluginSettings,
492
499
  useCurrentExperiment,
@@ -515,9 +522,52 @@ export {
515
522
  export {
516
523
  combinePluginJobSources,
517
524
  usePluginJobCenter,
525
+ useJobsStatusTray,
518
526
  type CombinedPluginJobCenterSource,
527
+ type JobsStatusTrayAdapter,
528
+ type JobStreamMessage,
519
529
  type PluginJobCenterSource,
520
530
  type JobsStatusTrayTab,
531
+ type UseJobsStatusTrayOptions,
532
+ type UseJobsStatusTrayReturn,
521
533
  type UsePluginJobCenterOptions,
522
534
  type UsePluginJobCenterReturn,
523
535
  } from './useJobsStatusTray'
536
+ export {
537
+ usePluginWorkspace,
538
+ type PluginWorkspaceSlotsLike,
539
+ type UsePluginWorkspaceOptions,
540
+ type UsePluginWorkspaceReturn,
541
+ } from './usePluginWorkspace'
542
+ export {
543
+ type PluginWorkspaceControlsModel,
544
+ type PluginWorkspaceShellModel,
545
+ type PluginWorkspaceSidebarModel,
546
+ } from './pluginWorkspaceModel'
547
+ export {
548
+ useFocusTrap,
549
+ type UseFocusTrapOptions,
550
+ type UseFocusTrapReturn,
551
+ } from './useFocusTrap'
552
+ export {
553
+ useRovingFocus,
554
+ type UseRovingFocusOptions,
555
+ type UseRovingFocusReturn,
556
+ } from './useRovingFocus'
557
+ export {
558
+ reorderList,
559
+ useListReorder,
560
+ useReorderAnnouncer,
561
+ REORDER_ANNOUNCER_STYLE,
562
+ type ListReorderMove,
563
+ type UseListReorderOptions,
564
+ type UseListReorderReturn,
565
+ type UseReorderAnnouncerReturn,
566
+ } from './useListReorder'
567
+ export {
568
+ useMenuKeyboard,
569
+ type UseMenuKeyboardOptions,
570
+ type UseMenuKeyboardReturn,
571
+ } from './useMenuKeyboard'
572
+
573
+ export { usePlatformFilePickerAdapter, encodePlatformPickerPath, decodePlatformPickerPath } from './usePlatformFilePickerAdapter'
@@ -0,0 +1,182 @@
1
+ import type {
2
+ AccountMenuItem,
3
+ PageSelectorItemInput,
4
+ PillNavItemInput,
5
+ PluginSwitcherInfo,
6
+ SidebarToolSection,
7
+ TopBarSettingsConfig,
8
+ TopBarVariant,
9
+ } from '../types'
10
+ import type { FormEnhancements, FormSchema } from '../types/form-builder'
11
+ import type {
12
+ ControlComponentBinding,
13
+ ControlComponentBindingsById,
14
+ ControlModel,
15
+ ControlModelBinding,
16
+ ControlSchema,
17
+ ControlWorkspaceOptions,
18
+ } from './useControlSchema'
19
+ import type { PluginWorkspaceSidebarVariant } from '../components/PluginWorkspaceView.props'
20
+
21
+ /**
22
+ * Scoped-slot payload shared by PluginWorkspaceView's `default`, `topbar`, and `sidebar`
23
+ * slots: the resolved active view plus the values and component bindings/props derived
24
+ * from the compact control schema. WorkspaceControlsInternal renders a component's default
25
+ * slot bound to exactly this shape.
26
+ */
27
+ export interface PluginWorkspaceControlsModel {
28
+ /** Currently resolved workspace view id. */
29
+ activeView: string
30
+ /** Sets the active view, updating any uncontrolled state and emitting `update:activeView`. */
31
+ setActiveView: (viewId: string) => void
32
+ /** Current control values, shared between the auto-rendered sidebar form and the default slot. */
33
+ values: Record<string, unknown>
34
+ /** Ordered SDK component bindings resolved from the current control values. */
35
+ componentBindings: ControlComponentBinding[]
36
+ /** SDK component bindings resolved from the current control values, keyed by binding id. */
37
+ componentBindingsById: ControlComponentBindingsById
38
+ /** Flat component props resolved from the current control values. */
39
+ componentProps: Record<string, unknown>
40
+ /** Named component prop mappings resolved from the current control values. */
41
+ componentPropsById: Record<string, Record<string, unknown>>
42
+ }
43
+
44
+ /**
45
+ * Resolved AppLayout + AppTopBar configuration consumed by WorkspaceShellInternal: top bar
46
+ * chrome and navigation, plus the AppLayout layout/collapse props that own the responsive
47
+ * mobile sidebar toggle.
48
+ */
49
+ export interface PluginWorkspaceShellModel {
50
+ /** AppLayout sidebar position. */
51
+ sidebarPosition: 'left' | 'right'
52
+ /** AppLayout sidebar width, forwarded so the layout can reserve space before AppSidebar mounts. */
53
+ sidebarWidth?: string
54
+ /** AppLayout floating style. */
55
+ floating: boolean
56
+ /** Convert the sidebar into an SDK-owned mobile overlay below the AppLayout breakpoint. */
57
+ responsiveSidebar: boolean
58
+ /** Accessible label for the mobile sidebar toggle. */
59
+ sidebarToggleLabel: string
60
+ /** Accessible label used when the mobile sidebar is open. */
61
+ sidebarCloseLabel: string
62
+ /** Whether AppLayout should render a `#sidebar` template at all. */
63
+ hasSidebarSurface: boolean
64
+ /** App or plugin title shown in the top bar. */
65
+ title: string
66
+ /** Secondary copy shown under the title. */
67
+ subtitle?: string
68
+ /** Top bar visual treatment. */
69
+ topBarVariant: TopBarVariant
70
+ /** Home link used by the top bar brand icon. */
71
+ homePath: string
72
+ /** Show the default MINT logo when no icon/logo slot is provided. */
73
+ showLogo: boolean
74
+ /** Preferred route-level page selector entries. */
75
+ pageSelector?: PageSelectorItemInput[]
76
+ /** Resolved active page selector id. */
77
+ currentPageSelectorId: string
78
+ /** Optional plugin switcher shown in the left navigation position. */
79
+ pluginSwitcher?: PluginSwitcherInfo
80
+ /** Resolved centered pill navigation, generated from the control schema when omitted. */
81
+ pillNav?: PillNavItemInput[]
82
+ /** Resolved active centered pill id. */
83
+ currentPillId: string
84
+ /** Show the theme toggle button. */
85
+ showThemeToggle: boolean
86
+ /** Show the settings button and modal. */
87
+ showSettings: boolean
88
+ /** Built-in settings modal configuration. */
89
+ settingsConfig?: TopBarSettingsConfig
90
+ /** Show the standalone badge when not integrated into the platform. */
91
+ showStandaloneLabel: boolean
92
+ /** Custom standalone badge label. */
93
+ standaloneLabel: string
94
+ /** Account dropdown entries. */
95
+ accountMenu?: AccountMenuItem[]
96
+ /** Show the notifications icon button. */
97
+ showNotifications: boolean
98
+ /** Draw a notification dot on the notifications icon. */
99
+ hasNotificationDot: boolean
100
+ /** Show the admin shortcut. */
101
+ showAdmin: boolean
102
+ /** Route used by the admin shortcut. */
103
+ adminPath: string
104
+ /** Account display name. */
105
+ userName?: string
106
+ /** Explicit account avatar initial. */
107
+ userInitial?: string
108
+ /** Account email shown in the avatar menu. */
109
+ userEmail?: string
110
+ /** Names of AppTopBar passthrough slots the caller actually provided. */
111
+ topBarSlotNames: string[]
112
+ /** Scoped-slot payload exposed to the `topbar` override slot. */
113
+ controls: PluginWorkspaceControlsModel
114
+ }
115
+
116
+ /**
117
+ * Resolved AppSidebar configuration consumed by WorkspaceSidebarInternal: sidebar chrome,
118
+ * panels/forms, collapse behavior, and the compact control-schema props that drive
119
+ * AppSidebar's auto-generated form.
120
+ */
121
+ export interface PluginWorkspaceSidebarModel {
122
+ /** Sidebar chrome title. */
123
+ title?: string
124
+ /** Sidebar chrome subtitle. */
125
+ subtitle?: string
126
+ /** Optional compact badge/count rendered in the sidebar header. */
127
+ badge?: string | number
128
+ /** AppSidebar visual preset. */
129
+ variant: PluginWorkspaceSidebarVariant
130
+ /** Map of view IDs to sidebar tool sections. */
131
+ panels: Record<string, SidebarToolSection[]>
132
+ /** Resolved active view, used to pick which panels/forms render. */
133
+ activeView: string
134
+ /** AppSidebar floating style (always false: PluginWorkspaceView docks the sidebar inside AppLayout). */
135
+ floating: boolean
136
+ /** Compact AppSidebar density. */
137
+ dense: boolean
138
+ /** Sidebar CSS width. */
139
+ width?: string
140
+ /** Sidebar position, mirrors the shell's `sidebarPosition`. */
141
+ side: 'left' | 'right'
142
+ /** Optional FormBuilder schemas keyed by section ID. */
143
+ forms: Record<string, FormSchema>
144
+ /** DOM id for the AppSidebar scrollable content area. */
145
+ contentId?: string
146
+ /** Render the sidebar shell even when no panel matches the active view. */
147
+ showWhenEmpty: boolean
148
+ /** Optional compact control model for the generated sidebar form. */
149
+ model?: ControlModel | ControlModelBinding
150
+ /** Compact control schema for the generated sidebar form. */
151
+ controlSchema?: ControlSchema
152
+ /** Options passed to compact control schema generation. */
153
+ controlOptions: ControlWorkspaceOptions
154
+ /** Shared values for the auto-rendered sidebar form. */
155
+ values: Record<string, unknown>
156
+ /** Runtime FormBuilder enhancements for the auto-rendered sidebar form. */
157
+ formEnhancements?: FormEnhancements<Record<string, unknown>>
158
+ /** Show submit/cancel actions inside the auto-rendered sidebar form. */
159
+ showFormActions: boolean
160
+ /** Loading/saving state for the auto-rendered sidebar form. */
161
+ formLoading: boolean
162
+ /** Disabled state for the auto-rendered sidebar form. */
163
+ formDisabled: boolean
164
+ /** Readonly state for the auto-rendered sidebar form. */
165
+ formReadonly: boolean
166
+ /** Size passed to the auto-rendered sidebar form. */
167
+ formSize: 'sm' | 'md' | 'lg'
168
+ /** Show a built-in collapse/expand button in the sidebar chrome. */
169
+ collapsible?: boolean
170
+ /** Controlled sidebar collapsed state. */
171
+ collapsed?: boolean
172
+ /** Initial sidebar collapsed state when uncontrolled. */
173
+ defaultCollapsed: boolean
174
+ /** Sidebar width when collapsed. */
175
+ collapsedWidth: string
176
+ /** Accessible label for the sidebar collapse action. */
177
+ collapseButtonLabel: string
178
+ /** Accessible label for the sidebar expand action. */
179
+ expandButtonLabel: string
180
+ /** Names of AppSidebar passthrough slots the caller actually provided. */
181
+ slotNames: string[]
182
+ }