@morscherlab/mint-sdk 1.2.0-beta.8 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (402) hide show
  1. package/README.md +60 -0
  2. package/dist/{ExperimentPopover-CfOdh5Rm.js → ExperimentPopover-CJdNlCZb.js} +24 -15
  3. package/dist/ExperimentPopover-CJdNlCZb.js.map +1 -0
  4. package/dist/{ExperimentSelectorModal-DvIagrxY.js → ExperimentSelectorModal-DCXmwKNS.js} +5 -5
  5. package/dist/ExperimentSelectorModal-DCXmwKNS.js.map +1 -0
  6. package/dist/{SettingsModal-W3TYfnP9.js → SettingsModal-BYR20I4c.js} +5 -5
  7. package/dist/SettingsModal-BYR20I4c.js.map +1 -0
  8. package/dist/{EmptyState-NBqf2_8z.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/iconButtonIconSizing.test.d.ts +1 -0
  17. package/dist/__tests__/composables/useFileBrowser.test.d.ts +1 -0
  18. package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
  19. package/dist/__tests__/composables/usePlatformFilePickerAdapter.test.d.ts +1 -0
  20. package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
  21. package/dist/apiErrors.d.ts +26 -0
  22. package/dist/components/ActionMenu.vue.d.ts +1 -1
  23. package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
  24. package/dist/components/AuditTrail.vue.d.ts +13 -0
  25. package/dist/components/BaseInput.vue.d.ts +1 -1
  26. package/dist/components/BaseSelect.vue.d.ts +1 -1
  27. package/dist/components/BaseTextarea.vue.d.ts +1 -1
  28. package/dist/components/BatchProgressList.vue.d.ts +17 -0
  29. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
  30. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +2 -2
  31. package/dist/components/ConcentrationInput.vue.d.ts +1 -1
  32. package/dist/components/DataFrame.vue.d.ts +14 -2
  33. package/dist/components/DatePicker.vue.d.ts +2 -2
  34. package/dist/components/DateTimePicker.vue.d.ts +3 -1
  35. package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
  36. package/dist/components/ExperimentPopover.vue.d.ts +1 -0
  37. package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
  38. package/dist/components/FileBrowserModal.vue.d.ts +99 -0
  39. package/dist/components/FilePicker.vue.d.ts +32 -0
  40. package/dist/components/FileUploader.vue.d.ts +5 -2
  41. package/dist/components/FormulaInput.vue.d.ts +1 -1
  42. package/dist/components/GeneratedPlotlyResult.vue.d.ts +1 -3
  43. package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
  44. package/dist/components/MobileSupportGate.vue.d.ts +1 -1
  45. package/dist/components/MoleculeInput.vue.d.ts +1 -1
  46. package/dist/components/NumberInput.vue.d.ts +1 -1
  47. package/dist/components/PlotlyChart.vue.d.ts +59 -0
  48. package/dist/components/ProgressBar.vue.d.ts +1 -1
  49. package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
  50. package/dist/components/ReagentList.vue.d.ts +29 -1
  51. package/dist/components/ResourceCard.vue.d.ts +1 -1
  52. package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
  53. package/dist/components/SampleSelector.drag.d.ts +13 -0
  54. package/dist/components/SampleSelector.tree.d.ts +2 -0
  55. package/dist/components/SampleSelector.vue.d.ts +34 -1
  56. package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
  57. package/dist/components/SecretInput.vue.d.ts +1 -1
  58. package/dist/components/SequenceInput.vue.d.ts +1 -1
  59. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +1 -0
  60. package/dist/components/StatusIndicator.vue.d.ts +1 -1
  61. package/dist/components/TagsInput.vue.d.ts +1 -1
  62. package/dist/components/TimePicker.vue.d.ts +2 -1
  63. package/dist/components/TimeRangeInput.vue.d.ts +1 -1
  64. package/dist/components/UnitInput.vue.d.ts +1 -1
  65. package/dist/components/WellPlate.geometry.d.ts +15 -0
  66. package/dist/components/WellPlate.interaction.d.ts +13 -0
  67. package/dist/components/WellPlate.vue.d.ts +30 -1
  68. package/dist/components/fileBrowserPresentation.d.ts +10 -0
  69. package/dist/components/index.d.ts +4 -0
  70. package/dist/components/index.js +8 -8
  71. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
  72. package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
  73. package/dist/components/internal/FileBrowserDialogInternal.vue.d.ts +34 -0
  74. package/dist/components/internal/FileBrowserListingInternal.vue.d.ts +25 -0
  75. package/dist/components/internal/FileBrowserToolbarInternal.vue.d.ts +26 -0
  76. package/dist/components/internal/FilePickerPreviewInternal.vue.d.ts +18 -0
  77. package/dist/components/internal/FilePickerTreeInternal.vue.d.ts +31 -0
  78. package/dist/{components-B80gV0P6.js → components-DIum5hkx.js} +5415 -2753
  79. package/dist/components-DIum5hkx.js.map +1 -0
  80. package/dist/composables/controlSchemaTypes.d.ts +34 -0
  81. package/dist/composables/filePicker/localFiles.d.ts +3 -0
  82. package/dist/composables/filePicker/usePickerNavigation.d.ts +96 -0
  83. package/dist/composables/filePicker/usePickerSelection.d.ts +31 -0
  84. package/dist/composables/filePicker/validation.d.ts +5 -0
  85. package/dist/composables/index.d.ts +3 -0
  86. package/dist/composables/index.js +10 -10
  87. package/dist/composables/useApi.d.ts +14 -7
  88. package/dist/composables/useDropdownState.d.ts +18 -2
  89. package/dist/composables/useEventStream.d.ts +9 -0
  90. package/dist/composables/useFileBrowser.d.ts +55 -0
  91. package/dist/composables/useFilePicker.d.ts +189 -0
  92. package/dist/composables/useListReorder.d.ts +90 -0
  93. package/dist/composables/useMenuKeyboard.d.ts +2 -2
  94. package/dist/composables/usePlatformFilePickerAdapter.d.ts +11 -0
  95. package/dist/composables/usePluginConfig.d.ts +3 -1
  96. package/dist/composables/useRequestSyncState.d.ts +42 -2
  97. package/dist/composables/useScheduleDrag.d.ts +1 -0
  98. package/dist/{composables-C8mmD5ta.js → composables-mFXsTA4g.js} +307 -74
  99. package/dist/composables-mFXsTA4g.js.map +1 -0
  100. package/dist/{useApi-CDBq6z23.js → errors-BLuqMee5.js} +178 -16
  101. package/dist/errors-BLuqMee5.js.map +1 -0
  102. package/dist/{experiment-Y9Iz7KYi.js → experiment-CVDRAnqp.js} +3 -8
  103. package/dist/experiment-CVDRAnqp.js.map +1 -0
  104. package/dist/{experiment-utils-DV3DrvE_.js → experiment-utils-CV2Wza3z.js} +1 -1
  105. package/dist/experiment-utils-CV2Wza3z.js.map +1 -0
  106. package/dist/index.d.ts +1 -0
  107. package/dist/index.js +15 -15
  108. package/dist/install.js +2 -7
  109. package/dist/install.js.map +1 -1
  110. package/dist/permissions.d.ts +42 -1
  111. package/dist/permissions.js +20 -10
  112. package/dist/permissions.js.map +1 -1
  113. package/dist/stores/index.d.ts +1 -1
  114. package/dist/stores/index.js +3 -3
  115. package/dist/stores/settings.d.ts +31 -1
  116. package/dist/styles.css +15162 -32475
  117. package/dist/templates/index.js +2 -4
  118. package/dist/{templates-CK72aKO1.js → templates-CmGfmBRA.js} +291 -85
  119. package/dist/templates-CmGfmBRA.js.map +1 -0
  120. package/dist/types/fileBrowserTypes.d.ts +77 -0
  121. package/dist/types/filePicker.d.ts +77 -0
  122. package/dist/types/index.d.ts +2 -0
  123. package/dist/{useControlSchema-_OVhavKq.js → useControlSchema-DldpxNOP.js} +234 -1121
  124. package/dist/useControlSchema-DldpxNOP.js.map +1 -0
  125. package/dist/{useDropdownState-D5G4UvWd.js → useDropdownState-C7hRiVQf.js} +22 -6
  126. package/dist/useDropdownState-C7hRiVQf.js.map +1 -0
  127. package/dist/{useExperimentSelector-DSEckf_g.js → useExperimentSelector-CEcIaueJ.js} +4 -4
  128. package/dist/{useExperimentSelector-DSEckf_g.js.map → useExperimentSelector-CEcIaueJ.js.map} +1 -1
  129. package/dist/{useFormBuilder-Bd714C7y.js → useFormBuilder-z5L_dUIy.js} +2 -2
  130. package/dist/{useFormBuilder-Bd714C7y.js.map → useFormBuilder-z5L_dUIy.js.map} +1 -1
  131. package/dist/utils/color.d.ts +13 -0
  132. package/dist/utils/errors.d.ts +9 -0
  133. package/dist/{useProtocolTemplates-Dq5Pzwyd.js → validation-uwoJGEb6.js} +231 -158
  134. package/dist/validation-uwoJGEb6.js.map +1 -0
  135. package/package.json +1 -1
  136. package/src/__tests__/apiErrors.test.ts +81 -0
  137. package/src/__tests__/components/ActionMenu.test.ts +94 -0
  138. package/src/__tests__/components/DataFrame.test.ts +183 -11
  139. package/src/__tests__/components/DataStates.test.ts +176 -0
  140. package/src/__tests__/components/DatePicker.test.ts +76 -0
  141. package/src/__tests__/components/DateTimePicker.test.ts +36 -0
  142. package/src/__tests__/components/ExperimentPopover.test.ts +30 -0
  143. package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
  144. package/src/__tests__/components/FileBrowserModal.test.ts +460 -0
  145. package/src/__tests__/components/FilePicker.state.test.ts +287 -0
  146. package/src/__tests__/components/FilePicker.test.ts +487 -0
  147. package/src/__tests__/components/GeneratedPlotlyResult.test.ts +52 -5
  148. package/src/__tests__/components/GroupAssigner.test.ts +53 -0
  149. package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
  150. package/src/__tests__/components/PlotlyChart.test.ts +305 -0
  151. package/src/__tests__/components/RackEditor.test.ts +35 -0
  152. package/src/__tests__/components/ReagentList.test.ts +64 -2
  153. package/src/__tests__/components/RetiredStyles.test.ts +31 -0
  154. package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
  155. package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
  156. package/src/__tests__/components/SegmentedControl.test.ts +107 -0
  157. package/src/__tests__/components/TimePicker.test.ts +61 -0
  158. package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
  159. package/src/__tests__/components/iconButtonIconSizing.test.ts +18 -0
  160. package/src/__tests__/composables/useApi.test.ts +92 -9
  161. package/src/__tests__/composables/useDropdownState.test.ts +58 -1
  162. package/src/__tests__/composables/useFileBrowser.test.ts +305 -0
  163. package/src/__tests__/composables/useGeneratedAnalysis.test.ts +7 -2
  164. package/src/__tests__/composables/useListReorder.test.ts +145 -0
  165. package/src/__tests__/composables/usePlatformFilePickerAdapter.test.ts +67 -0
  166. package/src/__tests__/composables/usePluginClient.test.ts +3 -0
  167. package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
  168. package/src/__tests__/stores/settings.test.ts +71 -1
  169. package/src/__tests__/styles/cssTokens.test.ts +131 -0
  170. package/src/__tests__/utils/permissions.test.ts +68 -0
  171. package/src/apiErrors.ts +85 -0
  172. package/src/components/ActionMenu.vue +45 -88
  173. package/src/components/AlertBox.vue +0 -4
  174. package/src/components/AppAvatarMenu.vue +2 -14
  175. package/src/components/AppLayout.vue +0 -4
  176. package/src/components/AppPluginSwitcher.story.vue +87 -0
  177. package/src/components/AppPluginSwitcher.vue +2 -5
  178. package/src/components/AppSidebar.vue +0 -4
  179. package/src/components/AppToastContainer.vue +6 -8
  180. package/src/components/AppTopBar.vue +0 -4
  181. package/src/components/ArtifactSaveDialog.vue +0 -4
  182. package/src/components/ArtifactSelectorModal.vue +0 -4
  183. package/src/components/AuditTrail.story.vue +18 -0
  184. package/src/components/AuditTrail.vue +27 -7
  185. package/src/components/AutoGroupModal.vue +0 -4
  186. package/src/components/Avatar.vue +0 -4
  187. package/src/components/BaseButton.vue +0 -4
  188. package/src/components/BaseCheckbox.vue +0 -4
  189. package/src/components/BaseInput.vue +0 -4
  190. package/src/components/BaseModal.vue +0 -4
  191. package/src/components/BasePill.vue +0 -4
  192. package/src/components/BaseRadioGroup.vue +0 -4
  193. package/src/components/BaseSelect.vue +0 -4
  194. package/src/components/BaseSlider.vue +0 -4
  195. package/src/components/BaseTabs.vue +0 -4
  196. package/src/components/BaseTextarea.vue +0 -4
  197. package/src/components/BaseToggle.vue +0 -4
  198. package/src/components/BatchProgressList.story.vue +18 -0
  199. package/src/components/BatchProgressList.vue +32 -4
  200. package/src/components/Breadcrumb.vue +0 -4
  201. package/src/components/Calendar.vue +0 -4
  202. package/src/components/ChartContainer.story.vue +1 -1
  203. package/src/components/ChartContainer.vue +0 -4
  204. package/src/components/ChemicalFormula.vue +0 -4
  205. package/src/components/CollapsibleCard.vue +0 -4
  206. package/src/components/ColorSlider.vue +0 -4
  207. package/src/components/ConcentrationInput.vue +0 -4
  208. package/src/components/ConfirmDialog.vue +0 -4
  209. package/src/components/DataFrame.story.vue +14 -0
  210. package/src/components/DataFrame.vue +97 -23
  211. package/src/components/DatePicker.vue +73 -27
  212. package/src/components/DateTimePicker.vue +45 -17
  213. package/src/components/Divider.vue +0 -4
  214. package/src/components/DoseCalculator.vue +0 -4
  215. package/src/components/DropdownButton.vue +2 -14
  216. package/src/components/EmptyState.vue +0 -4
  217. package/src/components/ExperimentCodeBadge.vue +0 -4
  218. package/src/components/ExperimentDataViewer.story.vue +3 -0
  219. package/src/components/ExperimentDataViewer.vue +33 -13
  220. package/src/components/ExperimentPopover.vue +12 -7
  221. package/src/components/ExperimentSelectorModal.vue +0 -4
  222. package/src/components/ExperimentTimeline.story.vue +18 -0
  223. package/src/components/ExperimentTimeline.vue +81 -75
  224. package/src/components/FileBrowserModal.story.vue +203 -0
  225. package/src/components/FileBrowserModal.vue +384 -0
  226. package/src/components/FilePicker.story.vue +44 -0
  227. package/src/components/FilePicker.vue +284 -0
  228. package/src/components/FileUploader.vue +32 -18
  229. package/src/components/FitPanel.vue +0 -4
  230. package/src/components/FormActions.story.vue +96 -0
  231. package/src/components/FormActions.vue +0 -4
  232. package/src/components/FormBuilder.vue +0 -4
  233. package/src/components/FormField.vue +0 -4
  234. package/src/components/FormulaInput.vue +0 -4
  235. package/src/components/GeneratedPathInput.story.vue +68 -0
  236. package/src/components/GeneratedPlotlyResult.story.vue +96 -0
  237. package/src/components/GeneratedPlotlyResult.vue +34 -69
  238. package/src/components/GeneratedPluginView.story.vue +145 -0
  239. package/src/components/GeneratedPluginView.vue +10 -10
  240. package/src/components/GeneratedResultRenderer.story.vue +117 -0
  241. package/src/components/GeneratedResultRenderer.vue +4 -9
  242. package/src/components/GroupAssigner.vue +67 -5
  243. package/src/components/IconButton.vue +0 -4
  244. package/src/components/InstrumentAlertLog.vue +0 -4
  245. package/src/components/InstrumentStateBadge.vue +0 -4
  246. package/src/components/InstrumentStatusCard.vue +0 -4
  247. package/src/components/JobsStatusTray.vue +0 -4
  248. package/src/components/LcmsSequenceTable.vue +81 -50
  249. package/src/components/LoadingSpinner.vue +0 -4
  250. package/src/components/MobileSupportGate.vue +0 -4
  251. package/src/components/MoleculeInput.vue +0 -4
  252. package/src/components/MultiSelect.vue +0 -4
  253. package/src/components/NumberInput.vue +0 -4
  254. package/src/components/PlateMapEditor.vue +3 -14
  255. package/src/components/PlotlyChart.story.vue +61 -0
  256. package/src/components/PlotlyChart.vue +233 -0
  257. package/src/components/PluginIcon.vue +0 -4
  258. package/src/components/ProgressBar.vue +0 -4
  259. package/src/components/ProtocolStepEditor.vue +2 -4
  260. package/src/components/RackEditor.vue +51 -70
  261. package/src/components/ReagentEditor.vue +0 -4
  262. package/src/components/ReagentList.story.vue +18 -0
  263. package/src/components/ReagentList.vue +127 -82
  264. package/src/components/ResourceCard.vue +0 -4
  265. package/src/components/RuntimeUpdateNotice.story.vue +49 -0
  266. package/src/components/RuntimeUpdateNotice.vue +4 -4
  267. package/src/components/SampleHierarchyTree.story.vue +18 -0
  268. package/src/components/SampleHierarchyTree.vue +32 -9
  269. package/src/components/SampleLegend.vue +2 -8
  270. package/src/components/SampleSelector.drag.ts +51 -0
  271. package/src/components/SampleSelector.story.vue +6 -0
  272. package/src/components/SampleSelector.tree.ts +2 -0
  273. package/src/components/SampleSelector.vue +49 -10
  274. package/src/components/SampleSelectorGroupNode.vue +19 -0
  275. package/src/components/ScheduleCalendar.story.vue +6 -0
  276. package/src/components/ScheduleCalendar.vue +82 -7
  277. package/src/components/ScientificNumber.vue +0 -4
  278. package/src/components/SectionCard.vue +0 -4
  279. package/src/components/SegmentedControl.vue +50 -7
  280. package/src/components/SequenceInput.vue +0 -4
  281. package/src/components/SequenceProgressBar.story.vue +110 -0
  282. package/src/components/SequenceProgressBar.vue +0 -4
  283. package/src/components/SettingsModal.vue +0 -4
  284. package/src/components/Skeleton.vue +0 -4
  285. package/src/components/SmartGroupFieldRecipe.vue +8 -6
  286. package/src/components/SmartGroupManual.vue +0 -4
  287. package/src/components/StatusIndicator.vue +0 -4
  288. package/src/components/StepWizard.vue +0 -4
  289. package/src/components/TagsInput.vue +4 -6
  290. package/src/components/ThemeToggle.vue +0 -4
  291. package/src/components/TimePicker.vue +36 -7
  292. package/src/components/TimeRangeInput.vue +0 -4
  293. package/src/components/Tooltip.story.vue +3 -3
  294. package/src/components/Tooltip.vue +0 -4
  295. package/src/components/UnitInput.vue +0 -4
  296. package/src/components/WellPlate.geometry.ts +60 -1
  297. package/src/components/WellPlate.interaction.ts +44 -0
  298. package/src/components/WellPlate.story.vue +8 -0
  299. package/src/components/WellPlate.vue +53 -7
  300. package/src/components/fileBrowserPresentation.ts +39 -0
  301. package/src/components/index.ts +5 -0
  302. package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
  303. package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
  304. package/src/components/internal/DataStateInternal.vue +74 -0
  305. package/src/components/internal/FileBrowserDialogInternal.vue +75 -0
  306. package/src/components/internal/FileBrowserListingInternal.vue +197 -0
  307. package/src/components/internal/FileBrowserToolbarInternal.vue +136 -0
  308. package/src/components/internal/FilePickerPreviewInternal.vue +100 -0
  309. package/src/components/internal/FilePickerTreeInternal.vue +238 -0
  310. package/src/components/internal/FormSectionRenderer.vue +0 -4
  311. package/src/components/internal/WellEditPopupInternal.vue +0 -4
  312. package/src/composables/controlSchemaTypes.ts +34 -0
  313. package/src/composables/filePicker/localFiles.ts +58 -0
  314. package/src/composables/filePicker/usePickerNavigation.ts +220 -0
  315. package/src/composables/filePicker/usePickerSelection.ts +259 -0
  316. package/src/composables/filePicker/validation.ts +41 -0
  317. package/src/composables/index.ts +17 -0
  318. package/src/composables/useApi.ts +57 -13
  319. package/src/composables/useDropdownState.ts +35 -5
  320. package/src/composables/useEventStream.ts +14 -2
  321. package/src/composables/useFileBrowser.ts +314 -0
  322. package/src/composables/useFileImport.ts +2 -7
  323. package/src/composables/useFilePicker.ts +366 -0
  324. package/src/composables/useGeneratedAnalysis.ts +18 -26
  325. package/src/composables/useListReorder.story.vue +143 -0
  326. package/src/composables/useListReorder.ts +242 -0
  327. package/src/composables/useMenuKeyboard.ts +2 -2
  328. package/src/composables/useOptimisticMutation.ts +1 -15
  329. package/src/composables/usePlatformFilePickerAdapter.ts +104 -0
  330. package/src/composables/usePluginClient.ts +3 -0
  331. package/src/composables/usePluginConfig.ts +3 -1
  332. package/src/composables/useRackEditor.ts +2 -11
  333. package/src/composables/useRequestSyncState.ts +98 -28
  334. package/src/composables/useResourceCrud.ts +1 -15
  335. package/src/composables/useScheduleDrag.ts +37 -0
  336. package/src/composables/useWellPainting.ts +5 -29
  337. package/src/composables/useWellPlateEditor.ts +1 -11
  338. package/src/index.ts +3 -0
  339. package/src/permissions.ts +48 -9
  340. package/src/stores/experiment.ts +2 -7
  341. package/src/stores/index.ts +9 -1
  342. package/src/stores/settings.ts +93 -1
  343. package/src/styles/components/audit-trail.css +5 -5
  344. package/src/styles/components/batch-progress-list.css +7 -0
  345. package/src/styles/components/color-slider.css +2 -2
  346. package/src/styles/components/data-state.css +30 -0
  347. package/src/styles/components/dataframe.css +29 -35
  348. package/src/styles/components/experiment-data-viewer.css +4 -4
  349. package/src/styles/components/experiment-timeline.css +3 -30
  350. package/src/styles/components/file-browser-modal.css +489 -0
  351. package/src/styles/components/file-picker.css +502 -0
  352. package/src/styles/components/form-builder.css +5 -5
  353. package/src/styles/components/icon-button.css +9 -0
  354. package/src/styles/components/lcms-sequence-table.css +16 -1
  355. package/src/styles/components/multi-select.css +1 -1
  356. package/src/styles/components/reagent-list.css +38 -31
  357. package/src/styles/components/sample-hierarchy-tree.css +5 -19
  358. package/src/styles/components/sample-selector.css +9 -2
  359. package/src/styles/components/schedule-calendar.css +8 -0
  360. package/src/styles/components/scientific-number.css +1 -1
  361. package/src/styles/components/well-plate.css +8 -0
  362. package/src/styles/index.css +11 -0
  363. package/src/styles/variables.css +29 -0
  364. package/src/templates/builderPresetControls.ts +1 -1
  365. package/src/templates/componentPlateHelpers.ts +3 -1
  366. package/src/templates/doseResponseAdapters.ts +2 -13
  367. package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
  368. package/src/templates/plateMapBuilder.ts +2 -2
  369. package/src/templates/qpcrPlateBuilder.ts +1 -1
  370. package/src/templates/templateValidators.ts +1 -1
  371. package/src/templates/timeCourseBuilder.ts +2 -2
  372. package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
  373. package/src/types/fileBrowserTypes.ts +85 -0
  374. package/src/types/filePicker.ts +72 -0
  375. package/src/types/index.ts +14 -0
  376. package/src/utils/color.ts +51 -0
  377. package/src/utils/errors.ts +29 -0
  378. package/dist/EmptyState-NBqf2_8z.js.map +0 -1
  379. package/dist/ExperimentPopover-CfOdh5Rm.js.map +0 -1
  380. package/dist/ExperimentSelectorModal-DvIagrxY.js.map +0 -1
  381. package/dist/SettingsModal-W3TYfnP9.js.map +0 -1
  382. package/dist/components-B80gV0P6.js.map +0 -1
  383. package/dist/composables/autoGroupConstants.d.ts +0 -1
  384. package/dist/composables/autoGroupGrouping.d.ts +0 -3
  385. package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
  386. package/dist/composables-C8mmD5ta.js.map +0 -1
  387. package/dist/experiment-Y9Iz7KYi.js.map +0 -1
  388. package/dist/experiment-utils-DV3DrvE_.js.map +0 -1
  389. package/dist/templates/builderDefaults.d.ts +0 -1
  390. package/dist/templates/plateGeometry.d.ts +0 -4
  391. package/dist/templates-CK72aKO1.js.map +0 -1
  392. package/dist/useApi-CDBq6z23.js.map +0 -1
  393. package/dist/useControlSchema-_OVhavKq.js.map +0 -1
  394. package/dist/useDropdownState-D5G4UvWd.js.map +0 -1
  395. package/dist/useProtocolTemplates-Dq5Pzwyd.js.map +0 -1
  396. package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
  397. package/src/composables/autoGroupConstants.ts +0 -4
  398. package/src/composables/autoGroupGrouping.ts +0 -148
  399. package/src/composables/useAutoGroupInputSources.ts +0 -147
  400. package/src/templates/builderDefaults.ts +0 -11
  401. package/src/templates/plateGeometry.ts +0 -62
  402. /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → apiErrors.test.d.ts} +0 -0
@@ -0,0 +1,90 @@
1
+ import { Ref } from 'vue';
2
+ /** Inline style for a visually hidden `aria-live` region (no global utility class in the SDK). */
3
+ export declare const REORDER_ANNOUNCER_STYLE: Readonly<{
4
+ position: "absolute";
5
+ width: "1px";
6
+ height: "1px";
7
+ padding: "0";
8
+ margin: "-1px";
9
+ overflow: "hidden";
10
+ clip: "rect(0, 0, 0, 0)";
11
+ whiteSpace: "nowrap";
12
+ border: "0";
13
+ }>;
14
+ export interface UseReorderAnnouncerReturn {
15
+ /** Bind to a polite live region's text content. */
16
+ announcement: Ref<string>;
17
+ /** Publishes a message to the live region. */
18
+ announce: (message: string) => void;
19
+ /** Bind to the live region's `style` so it stays visually hidden. */
20
+ announcerStyle: typeof REORDER_ANNOUNCER_STYLE;
21
+ }
22
+ /**
23
+ * Screen-reader announcements for drag/keyboard move interactions. Bind
24
+ * `announcement` to a `role="status" aria-live="polite"` element styled with
25
+ * `announcerStyle`.
26
+ */
27
+ export declare function useReorderAnnouncer(): UseReorderAnnouncerReturn;
28
+ export interface ListReorderMove<T> {
29
+ /** Index the item moved from, within `items()`. */
30
+ fromIndex: number;
31
+ /** Index the item moved to, within `items()`. */
32
+ toIndex: number;
33
+ /** The reordered array (a copy — `items()` is never mutated). */
34
+ items: T[];
35
+ /** Whether the move came from the keyboard or a pointer drag. */
36
+ source: 'keyboard' | 'drag';
37
+ }
38
+ export interface UseListReorderOptions<T> {
39
+ /** The list being reordered, in its canonical (not merely rendered) order. */
40
+ items: () => T[];
41
+ /** Stable id for an item; falls back to the render index when ids repeat. */
42
+ getId: (item: T, index: number) => string;
43
+ /** Applies the move. The composable never mutates the source array. */
44
+ onReorder: (move: ListReorderMove<T>) => void;
45
+ /** Human-readable name used in announcements. Defaults to the item's id. */
46
+ getLabel?: (item: T, index: number) => string;
47
+ /** Blocks every reorder while it returns `true` (readonly / non-sortable lists). */
48
+ disabled?: () => boolean;
49
+ /** Resolves the focusable element for an id so keyboard moves keep focus on the item. */
50
+ getElement?: (id: string) => HTMLElement | null | undefined;
51
+ /** Noun used in announcements, e.g. `'Reagent'`. Default `'Item'`. */
52
+ itemNoun?: string;
53
+ }
54
+ export interface UseListReorderReturn<T> {
55
+ /** Id of the item currently being dragged, or `null`. */
56
+ draggingId: Ref<string | null>;
57
+ /** Id of the item the pointer is hovering as a drop target, or `null`. */
58
+ dragOverId: Ref<string | null>;
59
+ isDragging: (id: string) => boolean;
60
+ isDragOver: (id: string) => boolean;
61
+ announcement: Ref<string>;
62
+ announcerStyle: typeof REORDER_ANNOUNCER_STYLE;
63
+ announce: (message: string) => void;
64
+ /** Bind to the draggable element's `@dragstart`. */
65
+ onDragStart: (event: DragEvent, item: T, index: number) => void;
66
+ /** Bind to `@dragover` — calls `preventDefault()` so the drop is accepted. */
67
+ onDragOver: (event: DragEvent, item: T, index: number) => void;
68
+ /** Bind to `@dragleave`. */
69
+ onDragLeave: () => void;
70
+ /** Bind to `@drop`. */
71
+ onDrop: (event: DragEvent, item: T, index: number) => void;
72
+ /** Bind to `@dragend`. */
73
+ onDragEnd: () => void;
74
+ /**
75
+ * Bind to the item's (or its drag handle's) `@keydown`: Alt+ArrowUp / Alt+ArrowLeft
76
+ * moves the item one position earlier, Alt+ArrowDown / Alt+ArrowRight one later.
77
+ */
78
+ onKeydown: (event: KeyboardEvent, item: T, index: number) => void;
79
+ /** Moves an item between two indices of `items()` programmatically. */
80
+ move: (fromIndex: number, toIndex: number, source?: 'keyboard' | 'drag') => void;
81
+ }
82
+ /** Pure helper: a copy of `items` with the entry at `from` moved to `to`. */
83
+ export declare function reorderList<T>(items: T[], from: number, to: number): T[];
84
+ /**
85
+ * Keyboard-accessible list reordering shared by the SDK's drag-to-reorder lists.
86
+ * It owns the HTML5 drag state, the drop-index maths, and an Alt+Arrow keyboard
87
+ * alternative that announces every move through a polite live region — so a
88
+ * reorder never depends on a pointer.
89
+ */
90
+ export declare function useListReorder<T>(options: UseListReorderOptions<T>): UseListReorderReturn<T>;
@@ -23,7 +23,7 @@ export interface UseMenuKeyboardReturn {
23
23
  }
24
24
  /**
25
25
  * Shared keyboard contract for menu- and listbox-style disclosure panels (the
26
- * WAI-ARIA menu button pattern). Used by AppAvatarMenu and DropdownButton; ActionMenu
27
- * implements the same contract inline.
26
+ * WAI-ARIA menu button pattern). Used by ActionMenu, AppAvatarMenu and DropdownButton,
27
+ * each pairing it with `useDropdownState` for the disclosure state itself.
28
28
  */
29
29
  export declare function useMenuKeyboard(options: UseMenuKeyboardOptions): UseMenuKeyboardReturn;
@@ -0,0 +1,11 @@
1
+ import { PickerAdapter } from '../types/filePicker';
2
+ /** Opaque picker identity; decode before passing a selection to a mount-scoped API. */
3
+ export declare function encodePlatformPickerPath(mountId: string, path?: string): string;
4
+ export declare function decodePlatformPickerPath(path: string): {
5
+ mountId: string;
6
+ path: string;
7
+ };
8
+ /** Adapt the authenticated MINT mount API without exposing absolute host paths. */
9
+ export declare function usePlatformFilePickerAdapter(options?: {
10
+ apiBaseUrl?: string;
11
+ }): PickerAdapter;
@@ -21,5 +21,7 @@ export interface UsePluginConfigReturn {
21
21
  /** Restore the last loaded or saved configuration snapshot. */
22
22
  reset: () => void;
23
23
  }
24
- /** @deprecated Use `usePluginSettings()` for typed plugin settings. */
24
+ /**
25
+ * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `usePluginSettings()` for typed plugin settings.
26
+ */
25
27
  export declare function usePluginConfig(pluginName?: string): UsePluginConfigReturn;
@@ -1,8 +1,24 @@
1
1
  import { Ref } from 'vue';
2
2
  export type RequestSyncSuccessKind = 'load' | 'save' | 'run';
3
+ /**
4
+ * The unit of work `run()` drives.
5
+ *
6
+ * It receives an `AbortSignal` that fires when the run is superseded by a
7
+ * newer `run()` or by `cancel()`. Zero-argument operations stay valid and
8
+ * simply ignore it.
9
+ */
10
+ export type RequestSyncOperation<T> = (signal: AbortSignal) => Promise<T>;
3
11
  export interface RequestSyncRunOptions {
4
12
  success?: RequestSyncSuccessKind;
5
13
  errorMessage?: string;
14
+ /**
15
+ * Abort the previously started run when this one starts. Default `true`;
16
+ * pass `false` to let overlapping runs finish their own work (the stale
17
+ * guard on shared state still applies either way).
18
+ */
19
+ abortPrevious?: boolean;
20
+ /** Caller-owned signal; aborting it aborts this run's signal too. */
21
+ signal?: AbortSignal;
6
22
  }
7
23
  export interface UseRequestSyncStateReturn {
8
24
  /** Whether a request is in progress. */
@@ -27,8 +43,32 @@ export interface UseRequestSyncStateReturn {
27
43
  markSaved: (date?: Date) => void;
28
44
  /** Mark the operation as successfully run. */
29
45
  markRun: (date?: Date) => void;
30
- /** Run a request with shared loading/error handling and optional sync marking. */
31
- run: <T>(operation: () => Promise<T>, options?: RequestSyncRunOptions) => Promise<T>;
46
+ /**
47
+ * Run a request with shared loading/error handling and optional sync marking.
48
+ *
49
+ * ## Stale-response semantics
50
+ *
51
+ * Every call takes a monotonically increasing token. Starting a run
52
+ * supersedes any run started before it, and a superseded run writes **no**
53
+ * shared state when it finally settles: it does not clear `loading`, does not
54
+ * set `error`, and does not move `lastLoadedAt` / `lastSavedAt` / `lastRunAt`.
55
+ * Only the newest run owns those.
56
+ *
57
+ * The caller's own promise is untouched by the guard — a superseded run still
58
+ * resolves with its value or rejects with its own error, exactly as the
59
+ * operation did. The guard never invents a rejection, so a caller awaiting
60
+ * `run()` never sees a "superseded" error it did not cause.
61
+ *
62
+ * The operation additionally receives an `AbortSignal` that fires when its
63
+ * run is superseded or `cancel()` is called, so an operation that forwards
64
+ * the signal (`fetch(url, { signal })`) stops work instead of racing.
65
+ */
66
+ run: <T>(operation: RequestSyncOperation<T>, options?: RequestSyncRunOptions) => Promise<T>;
67
+ /**
68
+ * Abort the in-flight run and drop `loading`. The aborted run's completion
69
+ * is treated as stale and writes no state.
70
+ */
71
+ cancel: () => void;
32
72
  }
33
73
  /** Shared loading/error/timestamp state for generated plugin request helpers. */
34
74
  export declare function useRequestSyncState(defaultErrorMessage?: string): UseRequestSyncStateReturn;
@@ -75,4 +75,5 @@ export declare function useScheduleDrag(options: UseScheduleDragOptions): {
75
75
  startCreate: (date: Date, y: number, dayIndex: number) => void;
76
76
  startMove: (event: ScheduleEvent, y: number, dayIndex: number) => void;
77
77
  startResize: (event: ScheduleEvent, edge: "top" | "bottom", y: number, dayIndex: number) => void;
78
+ nudgeEvent: (event: ScheduleEvent, direction: -1 | 1, mode?: "move" | "resize") => boolean;
78
79
  };
@@ -1,8 +1,10 @@
1
- import { r as useRequestSyncState } from "./EmptyState-NBqf2_8z.js";
2
- import { B as currentExperimentFromContext, U as resolveCurrentExperimentId, V as getInjectedPlatformContext, et as useEventStream, lt as PLUGIN_SECRET_FORMAT_KEY } from "./useControlSchema-_OVhavKq.js";
3
- import { i as useAuthStore, n as authenticationRequiredError, o as useSettingsStore, r as useApi, t as AuthenticationRequiredError } from "./useApi-CDBq6z23.js";
4
- import { i as usePlatformContext } from "./useFormBuilder-Bd714C7y.js";
5
- import { computed, getCurrentInstance, onMounted, onUnmounted, ref, shallowRef, toValue, watch } from "vue";
1
+ import { a as useAuthStore, d as useSettingsStore, i as useApi, n as AuthenticationRequiredError, r as authenticationRequiredError, t as readErrorMessage } from "./errors-BLuqMee5.js";
2
+ import { n as useRequestSyncState } from "./Skeleton-BAF3CKY7.js";
3
+ import { B as currentExperimentFromContext, U as resolveCurrentExperimentId, V as getInjectedPlatformContext, et as useEventStream, lt as PLUGIN_SECRET_FORMAT_KEY } from "./useControlSchema-DldpxNOP.js";
4
+ import { n as pickerFormat } from "./validation-uwoJGEb6.js";
5
+ import { i as usePlatformContext } from "./useFormBuilder-z5L_dUIy.js";
6
+ import { bn as rowLabel, pn as PLATE_CONFIGS, yn as rowIndex } from "./templates-CmGfmBRA.js";
7
+ import { computed, getCurrentInstance, getCurrentScope, onMounted, onScopeDispose, onUnmounted, ref, shallowRef, toValue, watch } from "vue";
6
8
  import axios from "axios";
7
9
  //#region src/composables/useAuth.ts
8
10
  var TOKEN_REFRESH_MARGIN_MS = 300 * 1e3;
@@ -637,7 +639,9 @@ function platformOwnedConfigPatch(config) {
637
639
  function responseConfigPayload(response) {
638
640
  return response.config ?? response.settings ?? {};
639
641
  }
640
- /** @deprecated Use `usePluginSettings()` for typed plugin settings. */
642
+ /**
643
+ * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `usePluginSettings()` for typed plugin settings.
644
+ */
641
645
  function usePluginConfig(pluginName) {
642
646
  const injectedContext = getInjectedPlatformContext();
643
647
  const { plugin } = usePlatformContext();
@@ -746,6 +750,212 @@ function usePluginConfig(pluginName) {
746
750
  };
747
751
  }
748
752
  //#endregion
753
+ //#region src/composables/useFileBrowser.ts
754
+ /**
755
+ * Drives FileBrowserModal against the platform's `/api/filesystem` routes.
756
+ *
757
+ * Requires the `filesystem.browse` permission and a deployment that declares
758
+ * mounts; with none configured the routes are absent and `mounts` stays empty.
759
+ */
760
+ function useFileBrowser(options = {}) {
761
+ const injectedContext = getInjectedPlatformContext();
762
+ const api = useApi({ baseUrl: options.apiBaseUrl ?? injectedContext?.platformApiUrl });
763
+ const sync = useRequestSyncState("Could not read the server mounts.");
764
+ const mounts = ref([]);
765
+ const mountId = shallowRef("");
766
+ const path = shallowRef("");
767
+ const parent = ref(null);
768
+ const entries = ref([]);
769
+ const breadcrumbs = ref([]);
770
+ const totalCount = ref(null);
771
+ const matchCount = ref(null);
772
+ const shownCount = ref(null);
773
+ const truncated = ref(false);
774
+ const search = shallowRef("");
775
+ const sort = shallowRef("name");
776
+ const selected = ref([]);
777
+ const mountsLoading = shallowRef(false);
778
+ const listingLoading = shallowRef(false);
779
+ const listingReady = shallowRef(false);
780
+ const isLoading = computed(() => mountsLoading.value || listingLoading.value);
781
+ let listToken = 0;
782
+ let mountsToken = 0;
783
+ let disposed = false;
784
+ let listingController;
785
+ let mountsController;
786
+ let searchTimer;
787
+ function resetListing() {
788
+ listingReady.value = false;
789
+ entries.value = [];
790
+ breadcrumbs.value = [];
791
+ parent.value = null;
792
+ totalCount.value = null;
793
+ matchCount.value = null;
794
+ shownCount.value = null;
795
+ truncated.value = false;
796
+ }
797
+ function typeRuleParams() {
798
+ return (toValue(options.typeRules) ?? []).map((rule) => `&type_rules=${encodeURIComponent(rule)}`).join("");
799
+ }
800
+ /** Prefer the API's own `detail` over axios's "Request failed with status N". */
801
+ function describe(cause, fallback) {
802
+ const detail = cause?.response?.data?.detail;
803
+ return typeof detail === "string" && detail ? detail : sync.readErrorMessage(cause, fallback);
804
+ }
805
+ function fail(cause, fallback) {
806
+ sync.setError(new Error(describe(cause, fallback)), fallback);
807
+ }
808
+ function statusOf(cause) {
809
+ return cause?.response?.status;
810
+ }
811
+ async function loadMounts() {
812
+ const token = ++mountsToken;
813
+ mountsController?.abort();
814
+ mountsController = new AbortController();
815
+ mountsLoading.value = true;
816
+ try {
817
+ const data = await api.get("/filesystem/mounts", { signal: mountsController.signal });
818
+ if (disposed || token !== mountsToken) return false;
819
+ mounts.value = data.mounts ?? [];
820
+ sync.clearError();
821
+ sync.markLoaded();
822
+ return true;
823
+ } catch (cause) {
824
+ if (disposed || token !== mountsToken) return false;
825
+ if (statusOf(cause) === 404) {
826
+ mounts.value = [];
827
+ sync.clearError();
828
+ sync.markLoaded();
829
+ return true;
830
+ }
831
+ mounts.value = [];
832
+ fail(cause, "Could not read the server mounts.");
833
+ return false;
834
+ } finally {
835
+ if (token === mountsToken) mountsLoading.value = false;
836
+ }
837
+ }
838
+ async function navigate(location) {
839
+ if (disposed || !location.mount_id) return;
840
+ clearTimeout(searchTimer);
841
+ const token = ++listToken;
842
+ listingController?.abort();
843
+ listingController = new AbortController();
844
+ listingLoading.value = true;
845
+ mountId.value = location.mount_id;
846
+ path.value = location.path;
847
+ resetListing();
848
+ sync.clearError();
849
+ try {
850
+ const query = `mount_id=${encodeURIComponent(location.mount_id)}&path=${encodeURIComponent(location.path)}&sort=${sort.value}` + (search.value ? `&search=${encodeURIComponent(search.value)}` : "") + typeRuleParams();
851
+ const listing = await api.get(`/filesystem/browse?${query}`, { signal: listingController.signal });
852
+ if (disposed || token !== listToken) return;
853
+ mountId.value = listing.mount_id;
854
+ path.value = listing.path;
855
+ parent.value = listing.parent ?? null;
856
+ entries.value = listing.entries ?? [];
857
+ breadcrumbs.value = listing.breadcrumbs ?? [];
858
+ totalCount.value = listing.total_count ?? null;
859
+ matchCount.value = listing.match_count ?? null;
860
+ shownCount.value = listing.shown_count ?? listing.entries?.length ?? null;
861
+ truncated.value = listing.truncated ?? false;
862
+ listingReady.value = true;
863
+ sync.clearError();
864
+ sync.markLoaded();
865
+ } catch (cause) {
866
+ if (disposed || token !== listToken) return;
867
+ entries.value = [];
868
+ fail(cause, "Could not read that folder.");
869
+ } finally {
870
+ if (token === listToken) listingLoading.value = false;
871
+ }
872
+ }
873
+ async function init() {
874
+ if (disposed) return;
875
+ const navigationToken = listToken;
876
+ if (!await loadMounts() || disposed || navigationToken !== listToken) return;
877
+ const preferred = toValue(options.initialMountId);
878
+ const reachable = (mount) => mount.available !== false;
879
+ const target = mounts.value.find((mount) => mount.id === preferred && reachable(mount)) ?? mounts.value.find(reachable);
880
+ if (target) await navigate({
881
+ mount_id: target.id,
882
+ path: ""
883
+ });
884
+ else {
885
+ mountId.value = "";
886
+ path.value = "";
887
+ resetListing();
888
+ }
889
+ }
890
+ async function refresh() {
891
+ if (disposed) return;
892
+ if (mountId.value) await navigate({
893
+ mount_id: mountId.value,
894
+ path: path.value
895
+ });
896
+ else await init();
897
+ }
898
+ function selectCurrentFolder() {
899
+ if (!mountId.value || !listingReady.value || isLoading.value || sync.error.value) return;
900
+ const crumb = breadcrumbs.value[breadcrumbs.value.length - 1];
901
+ const key = JSON.stringify([mountId.value, path.value]);
902
+ if (selected.value.some((item) => JSON.stringify([item.mount_id, item.path]) === key)) return;
903
+ selected.value = [...selected.value, {
904
+ mount_id: mountId.value,
905
+ path: path.value,
906
+ name: crumb?.label ?? path.value,
907
+ kind: "directory",
908
+ child_count: totalCount.value
909
+ }];
910
+ }
911
+ function clear() {
912
+ selected.value = [];
913
+ }
914
+ watch(search, () => {
915
+ if (!mountId.value) return;
916
+ clearTimeout(searchTimer);
917
+ searchTimer = setTimeout(() => {
918
+ refresh();
919
+ }, 250);
920
+ });
921
+ watch(sort, () => {
922
+ if (mountId.value) refresh();
923
+ });
924
+ watch(() => toValue(options.typeRules), () => {
925
+ if (mountId.value) refresh();
926
+ }, { deep: true });
927
+ if (getCurrentScope()) onScopeDispose(() => {
928
+ disposed = true;
929
+ ++listToken;
930
+ ++mountsToken;
931
+ clearTimeout(searchTimer);
932
+ listingController?.abort();
933
+ mountsController?.abort();
934
+ });
935
+ return {
936
+ mounts,
937
+ mountId,
938
+ path,
939
+ parent,
940
+ entries,
941
+ breadcrumbs,
942
+ totalCount,
943
+ matchCount,
944
+ shownCount,
945
+ truncated,
946
+ search,
947
+ sort,
948
+ selected,
949
+ isLoading,
950
+ error: sync.error,
951
+ init,
952
+ navigate,
953
+ refresh,
954
+ selectCurrentFolder,
955
+ clear
956
+ };
957
+ }
958
+ //#endregion
749
959
  //#region src/composables/analysisArtifactTarget.ts
750
960
  var EXPERIMENT_ID = "experiment_id";
751
961
  var ARTIFACT_PLUGIN_ID = "artifact_plugin_id";
@@ -887,7 +1097,7 @@ function useOptimisticMutation(options) {
887
1097
  return result;
888
1098
  } catch (err) {
889
1099
  options.rollback?.(snapshot, variables, err);
890
- error.value = options.readErrorMessage?.(err) ?? readErrorMessage$1(err);
1100
+ error.value = options.readErrorMessage?.(err) ?? readErrorMessage(err);
891
1101
  options.onError?.(err, context);
892
1102
  throw err;
893
1103
  } finally {
@@ -906,12 +1116,6 @@ function useOptimisticMutation(options) {
906
1116
  reset
907
1117
  };
908
1118
  }
909
- function readErrorMessage$1(value) {
910
- if (value instanceof Error && value.message) return value.message;
911
- if (typeof value === "string" && value.trim()) return value;
912
- if (typeof value === "object" && value !== null && "message" in value && typeof value.message === "string" && value.message.trim()) return value.message;
913
- return "Request failed.";
914
- }
915
1119
  //#endregion
916
1120
  //#region src/composables/useResourceCrud.ts
917
1121
  /**
@@ -1046,45 +1250,8 @@ function resolveKey(keyOrItem, getKey) {
1046
1250
  if (typeof keyOrItem === "string" || typeof keyOrItem === "number") return keyOrItem;
1047
1251
  return getKey(keyOrItem);
1048
1252
  }
1049
- function readErrorMessage(value) {
1050
- if (value instanceof Error && value.message) return value.message;
1051
- if (typeof value === "string" && value.trim()) return value;
1052
- if (typeof value === "object" && value !== null && "message" in value && typeof value.message === "string" && value.message.trim()) return value.message;
1053
- return "Request failed.";
1054
- }
1055
1253
  //#endregion
1056
1254
  //#region src/composables/useWellPainting.ts
1057
- var ROW_LABELS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1058
- var PLATE_DIMENSIONS = {
1059
- 6: {
1060
- rows: 2,
1061
- cols: 3
1062
- },
1063
- 12: {
1064
- rows: 3,
1065
- cols: 4
1066
- },
1067
- 24: {
1068
- rows: 4,
1069
- cols: 6
1070
- },
1071
- 48: {
1072
- rows: 6,
1073
- cols: 8
1074
- },
1075
- 54: {
1076
- rows: 6,
1077
- cols: 9
1078
- },
1079
- 96: {
1080
- rows: 8,
1081
- cols: 12
1082
- },
1083
- 384: {
1084
- rows: 16,
1085
- cols: 24
1086
- }
1087
- };
1088
1255
  /**
1089
1256
  * Pointer painting/rectangle selection state for WellPlate-based editors.
1090
1257
  *
@@ -1164,15 +1331,15 @@ function wellIdToCoordinate(wellId) {
1164
1331
  const match = /^([A-Z]+)(\d+)$/i.exec(wellId.trim());
1165
1332
  if (!match) return null;
1166
1333
  return {
1167
- row: rowLabelToIndex$1(match[1].toUpperCase()),
1334
+ row: rowIndex(match[1].toUpperCase()),
1168
1335
  col: Number(match[2]) - 1
1169
1336
  };
1170
1337
  }
1171
1338
  function coordinateToWellId(coord) {
1172
- return `${indexToRowLabel$1(coord.row)}${coord.col + 1}`;
1339
+ return `${rowLabel(coord.row)}${coord.col + 1}`;
1173
1340
  }
1174
1341
  function wellIdsInRectangle(start, end, format) {
1175
- const dimensions = PLATE_DIMENSIONS[format];
1342
+ const dimensions = PLATE_CONFIGS[format];
1176
1343
  const minRow = Math.max(0, Math.min(start.row, end.row));
1177
1344
  const maxRow = Math.min(dimensions.rows - 1, Math.max(start.row, end.row));
1178
1345
  const minCol = Math.max(0, Math.min(start.col, end.col));
@@ -1184,22 +1351,6 @@ function wellIdsInRectangle(start, end, format) {
1184
1351
  }));
1185
1352
  return ids;
1186
1353
  }
1187
- function rowLabelToIndex$1(label) {
1188
- let result = 0;
1189
- for (const char of label) result = result * 26 + (char.charCodeAt(0) - 64);
1190
- return result - 1;
1191
- }
1192
- function indexToRowLabel$1(index) {
1193
- if (index < 26) return ROW_LABELS[index];
1194
- let value = index + 1;
1195
- let label = "";
1196
- while (value > 0) {
1197
- value--;
1198
- label = ROW_LABELS[value % 26] + label;
1199
- value = Math.floor(value / 26);
1200
- }
1201
- return label;
1202
- }
1203
1354
  //#endregion
1204
1355
  //#region src/composables/useWellPlateAdapter.ts
1205
1356
  /**
@@ -1578,7 +1729,8 @@ function createPluginClient(contract, options) {
1578
1729
  const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl);
1579
1730
  const api = useApi({
1580
1731
  baseUrl: parts.baseUrl,
1581
- withAuth: endpoint.requiresAuth !== false
1732
+ withAuth: endpoint.requiresAuth !== false,
1733
+ typedErrors: true
1582
1734
  });
1583
1735
  const config = endpointRequestConfig(endpoint, parts.query, callOptions);
1584
1736
  if (endpoint.method === "get") return api.get(parts.path, config);
@@ -1609,7 +1761,8 @@ async function uploadPluginEndpoint(contract, endpoint, payload, options = {}) {
1609
1761
  const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl);
1610
1762
  const api = useApi({
1611
1763
  baseUrl: parts.baseUrl,
1612
- withAuth: endpoint.requiresAuth !== false
1764
+ withAuth: endpoint.requiresAuth !== false,
1765
+ typedErrors: true
1613
1766
  });
1614
1767
  const body = endpoint.hasBody ? requestBodyFromPayload(payload, parts.requestPayload, endpoint) : payload;
1615
1768
  if (endpoint.requestContentType === OCTET_STREAM) {
@@ -1634,7 +1787,8 @@ async function downloadPluginEndpoint(contract, endpoint, payload, options = {})
1634
1787
  const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl);
1635
1788
  const api = useApi({
1636
1789
  baseUrl: parts.baseUrl,
1637
- withAuth: endpoint.requiresAuth !== false
1790
+ withAuth: endpoint.requiresAuth !== false,
1791
+ typedErrors: true
1638
1792
  });
1639
1793
  const config = {
1640
1794
  ...endpointRequestConfig(endpoint, parts.query, { signal: options.signal }) ?? {},
@@ -1946,6 +2100,85 @@ function useCurrentExperiment(options = {}) {
1946
2100
  };
1947
2101
  }
1948
2102
  //#endregion
1949
- export { useAsync as A, createPluginResourceClient as C, buildAnalysisArtifactTargetQuery as D, useCommandHistory as E, resolvePluginFrontendBase as M, usePasskey as N, parseAnalysisArtifactTarget as O, useAuth as P, wellIdsInRectangle as S, useOptimisticMutation as T, createWellPlateWells as _, pluginFormDataFromPayload as a, useWellPainting as b, usePluginClient as c, buildPluginEndpointUrl as d, resolvePluginBaseUrl as f, createRowConditions as g, createColumnConditions as h, getPluginPageSelectorItems as i, useAsyncBatch as j, usePluginConfig as k, usePluginEventStream as l, useWellPlateValidation as m, downloadBlob as n, uploadPluginEndpoint as o, runWellPlateValidation as p, downloadPluginEndpoint as r, useCurrentExperiment as s, createPluginClient as t, usePluginSettings as u, useWellPlateAdapter as v, useResourceCrud as w, wellIdToCoordinate as x, coordinateToWellId as y };
2103
+ //#region src/composables/usePlatformFilePickerAdapter.ts
2104
+ /** Opaque picker identity; decode before passing a selection to a mount-scoped API. */
2105
+ function encodePlatformPickerPath(mountId, path = "") {
2106
+ return JSON.stringify([mountId, path]);
2107
+ }
2108
+ function decodePlatformPickerPath(path) {
2109
+ const decoded = JSON.parse(path);
2110
+ if (!Array.isArray(decoded) || decoded.length !== 2 || !decoded.every((item) => typeof item === "string") || !decoded[0]) throw new Error("Invalid platform picker path.");
2111
+ return {
2112
+ mountId: decoded[0],
2113
+ path: decoded[1]
2114
+ };
2115
+ }
2116
+ /** Adapt the authenticated MINT mount API without exposing absolute host paths. */
2117
+ function usePlatformFilePickerAdapter(options = {}) {
2118
+ const api = useApi({ baseUrl: options.apiBaseUrl ?? getInjectedPlatformContext()?.platformApiUrl });
2119
+ const mountLabels = /* @__PURE__ */ new Map();
2120
+ async function listRoot(request) {
2121
+ try {
2122
+ const { mounts } = await api.get("/filesystem/mounts", { signal: request?.signal });
2123
+ return mounts.map((mount) => {
2124
+ mountLabels.set(mount.id, mount.label);
2125
+ return {
2126
+ kind: "folder",
2127
+ path: encodePlatformPickerPath(mount.id),
2128
+ name: mount.label,
2129
+ parentPath: null,
2130
+ parentName: "Server mounts",
2131
+ unavailableReason: mount.available === false ? "This mount is offline." : void 0
2132
+ };
2133
+ });
2134
+ } catch (cause) {
2135
+ if (cause.response?.status === 404) return [];
2136
+ throw cause;
2137
+ }
2138
+ }
2139
+ async function listChildren(path, request) {
2140
+ const location = decodePlatformPickerPath(path);
2141
+ const query = new URLSearchParams({
2142
+ mount_id: location.mountId,
2143
+ path: location.path
2144
+ });
2145
+ const listing = await api.get(`/filesystem/browse?${query}`, { signal: request?.signal });
2146
+ if (listing.truncated) throw new Error("This directory exceeds the server listing limit. Choose a smaller data directory.");
2147
+ return (listing.entries ?? []).map((entry) => ({
2148
+ kind: entry.kind === "directory" ? "folder" : "file",
2149
+ path: encodePlatformPickerPath(location.mountId, entry.path),
2150
+ parentPath: path,
2151
+ parentName: `${mountLabels.get(location.mountId) ?? location.mountId}${location.path ? ` / ${location.path}` : ""}`,
2152
+ name: entry.name,
2153
+ bytes: entry.size_bytes,
2154
+ ...entry.kind === "directory" ? { hasChildren: entry.child_count !== 0 } : { format: pickerFormat(entry.name) }
2155
+ }));
2156
+ }
2157
+ return {
2158
+ listRoot,
2159
+ listChildren,
2160
+ async search(query, scope, request) {
2161
+ const matches = [];
2162
+ const queue = [scope.path];
2163
+ const visited = /* @__PURE__ */ new Set();
2164
+ while (queue.length) {
2165
+ request?.signal?.throwIfAborted();
2166
+ const path = queue.shift();
2167
+ if (visited.has(path)) continue;
2168
+ visited.add(path);
2169
+ if (visited.size > 500) throw new Error("Search reached its folder limit. Search a smaller location or turn off Subfolders.");
2170
+ const nodes = path ? await listChildren(path, request) : await listRoot(request);
2171
+ for (const node of nodes) {
2172
+ if (node.name.toLowerCase().includes(query.toLowerCase())) matches.push(node);
2173
+ if (scope.recursive && node.kind === "folder" && !node.unavailableReason) queue.push(node.path);
2174
+ }
2175
+ if (matches.length > 1e4) throw new Error("Too many search results. Use a more specific search.");
2176
+ }
2177
+ return matches;
2178
+ }
2179
+ };
2180
+ }
2181
+ //#endregion
2182
+ export { buildAnalysisArtifactTargetQuery as A, useWellPainting as C, useResourceCrud as D, createPluginResourceClient as E, useAsyncBatch as F, resolvePluginFrontendBase as I, usePasskey as L, useFileBrowser as M, usePluginConfig as N, useOptimisticMutation as O, useAsync as P, useAuth as R, coordinateToWellId as S, wellIdsInRectangle as T, useWellPlateValidation as _, downloadBlob as a, createWellPlateWells as b, pluginFormDataFromPayload as c, usePluginClient as d, usePluginEventStream as f, runWellPlateValidation as g, resolvePluginBaseUrl as h, createPluginClient as i, parseAnalysisArtifactTarget as j, useCommandHistory as k, uploadPluginEndpoint as l, buildPluginEndpointUrl as m, encodePlatformPickerPath as n, downloadPluginEndpoint as o, usePluginSettings as p, usePlatformFilePickerAdapter as r, getPluginPageSelectorItems as s, decodePlatformPickerPath as t, useCurrentExperiment as u, createColumnConditions as v, wellIdToCoordinate as w, useWellPlateAdapter as x, createRowConditions as y };
1950
2183
 
1951
- //# sourceMappingURL=composables-C8mmD5ta.js.map
2184
+ //# sourceMappingURL=composables-mFXsTA4g.js.map