@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,233 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * Render native Plotly data with MINT loading, empty, theme, and error states.
4
+ *
5
+ * Plotly is loaded only when the component is mounted, so importing the SDK does
6
+ * not add Plotly to the application's initial bundle.
7
+ *
8
+ * @example
9
+ * ```vue
10
+ * <PlotlyChart
11
+ * title="QC overview"
12
+ * :data="traces"
13
+ * :layout="{ xaxis: { title: { text: 'Sample' } } }"
14
+ * :config="{ toImageButtonOptions: { filename: 'qc-overview' } }"
15
+ * />
16
+ * ```
17
+ */
18
+ import type * as PlotlyType from 'plotly.js'
19
+ import { nextTick, onBeforeUnmount, onMounted, ref, toRaw, watch } from 'vue'
20
+
21
+ import ChartContainer from './ChartContainer.vue'
22
+
23
+ interface Props {
24
+ data: PlotlyType.Data[]
25
+ layout?: Partial<PlotlyType.Layout>
26
+ config?: Partial<PlotlyType.Config>
27
+ title?: string
28
+ description?: string
29
+ loading?: boolean
30
+ empty?: boolean
31
+ emptyMessage?: string
32
+ ariaLabel?: string
33
+ }
34
+
35
+ const props = withDefaults(defineProps<Props>(), {
36
+ layout: () => ({}),
37
+ config: () => ({}),
38
+ loading: false,
39
+ empty: false,
40
+ emptyMessage: 'No data available',
41
+ ariaLabel: 'Interactive Plotly chart',
42
+ })
43
+
44
+ const chartElement = ref<HTMLDivElement | null>(null)
45
+ const failed = ref(false)
46
+ let plotly: typeof PlotlyType | null = null
47
+ let resizeObserver: ResizeObserver | null = null
48
+ let themeObserver: MutationObserver | null = null
49
+ let renderedElement: HTMLDivElement | null = null
50
+ let rendering = false
51
+ let disposed = false
52
+ let revision = 0
53
+
54
+ async function loadPlotly(): Promise<typeof PlotlyType> {
55
+ const module = await import('plotly.js-dist-min')
56
+ return ('default' in module ? module.default : module) as unknown as typeof PlotlyType
57
+ }
58
+
59
+ function cssValue(name: string, fallback: string): string {
60
+ const value = getComputedStyle(chartElement.value ?? document.documentElement).getPropertyValue(name).trim()
61
+ return value || getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback
62
+ }
63
+
64
+ // Unwrap nested Vue proxies while copying Plotly's mutable input tree. Keep
65
+ // native dates/typed arrays and callbacks instead of round-tripping through JSON.
66
+ function clonePlotlyInput<T>(value: T): T {
67
+ const raw = toRaw(value)
68
+ if (Array.isArray(raw)) return raw.map(clonePlotlyInput) as T
69
+ if (raw !== null && typeof raw === 'object') {
70
+ if (Object.getPrototypeOf(raw) === Object.prototype) {
71
+ return Object.fromEntries(Object.entries(raw).map(([key, item]) => [key, clonePlotlyInput(item)])) as T
72
+ }
73
+ return structuredClone(raw)
74
+ }
75
+ return raw
76
+ }
77
+
78
+ function themedLayout(): Partial<PlotlyType.Layout> {
79
+ const textColor = cssValue('--text-primary', '#1E293B')
80
+ const gridColor = cssValue('--border-color', '#E5E7EB')
81
+ const layout = clonePlotlyInput(props.layout)
82
+ return {
83
+ autosize: true,
84
+ paper_bgcolor: 'rgba(0,0,0,0)',
85
+ plot_bgcolor: 'rgba(0,0,0,0)',
86
+ ...layout,
87
+ font: { color: textColor, family: cssValue('--font-sans', 'Arial, sans-serif'), ...layout.font },
88
+ xaxis: { gridcolor: gridColor, ...layout.xaxis },
89
+ yaxis: { gridcolor: gridColor, ...layout.yaxis },
90
+ }
91
+ }
92
+
93
+ function purgeChart(): void {
94
+ resizeObserver?.disconnect()
95
+ if (renderedElement) plotly?.purge(renderedElement)
96
+ renderedElement = null
97
+ }
98
+
99
+ async function renderChart(): Promise<void> {
100
+ revision++
101
+ if (rendering || disposed || props.loading || props.empty) return
102
+ rendering = true
103
+ try {
104
+ while (!disposed && !props.loading && !props.empty) {
105
+ const currentRevision = revision
106
+ failed.value = false
107
+ await nextTick()
108
+ if (disposed || props.loading || props.empty) break
109
+ try {
110
+ plotly ??= await loadPlotly()
111
+ if (disposed || props.loading || props.empty) break
112
+ if (currentRevision !== revision) continue
113
+ const element = chartElement.value
114
+ if (!element) break
115
+ renderedElement = element
116
+ // Plotly mutates traces and nested layout fields; keep caller-owned values intact.
117
+ await plotly.react(
118
+ element,
119
+ clonePlotlyInput(props.data),
120
+ themedLayout(),
121
+ { responsive: true, displaylogo: false, ...props.config },
122
+ )
123
+ if (disposed || props.loading || props.empty || element !== chartElement.value) {
124
+ purgeChart()
125
+ } else {
126
+ resizeObserver?.observe(element)
127
+ }
128
+ } catch {
129
+ purgeChart()
130
+ if (!disposed && currentRevision === revision) failed.value = true
131
+ }
132
+ if (currentRevision === revision) break
133
+ }
134
+ } finally {
135
+ rendering = false
136
+ if (disposed || props.loading || props.empty) purgeChart()
137
+ }
138
+ }
139
+
140
+ onMounted(() => {
141
+ if (typeof ResizeObserver !== 'undefined') {
142
+ resizeObserver = new ResizeObserver(() => {
143
+ if (rendering || !plotly || !renderedElement) return
144
+ // A tab can become hidden or unmount before Plotly's async resize finishes.
145
+ void Promise.resolve(plotly.Plots.resize(renderedElement)).catch(() => {})
146
+ })
147
+ }
148
+
149
+ if (typeof MutationObserver !== 'undefined') {
150
+ themeObserver = new MutationObserver(() => void renderChart())
151
+ themeObserver.observe(document.documentElement, {
152
+ attributes: true,
153
+ attributeFilter: ['class', 'style'],
154
+ })
155
+ }
156
+ void renderChart()
157
+ })
158
+
159
+ watch(
160
+ [() => props.data, () => props.layout, () => props.config, () => props.loading, () => props.empty],
161
+ () => {
162
+ if (props.loading || props.empty) {
163
+ resizeObserver?.disconnect()
164
+ if (!rendering) purgeChart()
165
+ }
166
+ void renderChart()
167
+ },
168
+ )
169
+
170
+ onBeforeUnmount(() => {
171
+ disposed = true
172
+ resizeObserver?.disconnect()
173
+ themeObserver?.disconnect()
174
+ // An in-flight react must finish before its resources can be purged completely.
175
+ if (!rendering) purgeChart()
176
+ })
177
+ </script>
178
+
179
+ <template>
180
+ <ChartContainer
181
+ :title="title"
182
+ :description="description"
183
+ :loading="loading"
184
+ :empty="empty"
185
+ :empty-message="emptyMessage"
186
+ >
187
+ <template v-if="$slots.toolbar" #toolbar>
188
+ <slot name="toolbar" />
189
+ </template>
190
+ <template v-if="$slots.empty" #empty>
191
+ <slot name="empty" />
192
+ </template>
193
+
194
+ <template v-if="failed">
195
+ <slot name="error">
196
+ <div class="mint-plotly-chart__error">
197
+ <p role="alert">Unable to display this chart.</p>
198
+ </div>
199
+ </slot>
200
+ </template>
201
+ <div
202
+ ref="chartElement"
203
+ v-show="!failed"
204
+ class="mint-plotly-chart__plot"
205
+ role="group"
206
+ :aria-label="ariaLabel"
207
+ />
208
+
209
+ <template v-if="$slots.legend" #legend>
210
+ <slot name="legend" />
211
+ </template>
212
+ </ChartContainer>
213
+ </template>
214
+
215
+ <style scoped>
216
+ .mint-plotly-chart__plot {
217
+ width: 100%;
218
+ min-height: 24rem;
219
+ }
220
+
221
+ .mint-plotly-chart__error {
222
+ margin: 0;
223
+ padding: 1rem;
224
+ border: 1px solid var(--mint-error-border);
225
+ border-radius: 0.75rem;
226
+ background: var(--mint-error-bg);
227
+ color: var(--mint-error-hover);
228
+ }
229
+
230
+ .mint-plotly-chart__error :deep(p) {
231
+ margin: 0;
232
+ }
233
+ </style>
@@ -152,7 +152,3 @@ const rootStyle = computed(() =>
152
152
  />
153
153
  </span>
154
154
  </template>
155
-
156
- <style>
157
- @import '../styles/components/plugin-icon.css';
158
- </style>
@@ -111,7 +111,3 @@ const segmentCount = computed(() => props.steps.length || 0)
111
111
  </div>
112
112
  </div>
113
113
  </template>
114
-
115
- <style>
116
- @import '../styles/components/progress-bar.css';
117
- </style>
@@ -53,6 +53,7 @@ const selectedTemplateId = ref<string | null>(null)
53
53
  const {
54
54
  isOpen: templateDropdownOpen,
55
55
  rootRef: templateDropdownRef,
56
+ triggerRef: templateTriggerRef,
56
57
  close: closeTemplateDropdown,
57
58
  toggle: toggleTemplateDropdown,
58
59
  } = useDropdownState()
@@ -204,6 +205,7 @@ watch(
204
205
  <label class="mint-protocol-editor__template-label">Template</label>
205
206
  <div ref="templateDropdownRef" class="mint-protocol-editor__template-dropdown">
206
207
  <button
208
+ ref="templateTriggerRef"
207
209
  type="button"
208
210
  class="mint-protocol-editor__template-btn"
209
211
  @click="toggleTemplateDropdown"
@@ -376,7 +378,3 @@ watch(
376
378
  </div>
377
379
  </div>
378
380
  </template>
379
-
380
- <style>
381
- @import '../styles/components/protocol-step-editor.css';
382
- </style>
@@ -1,7 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  /** Multi-rack editor for managing collections of well-plate racks with add/remove/reorder controls and per-well editing. */
3
- import { ref, computed, watch } from 'vue'
3
+ import { computed, watch, type ComponentPublicInstance } from 'vue'
4
+ import { SLOT_COLORS, SLOT_ORDER } from '../utils/color'
4
5
  import type { Rack, SlotPosition, WellPlateFormat, WellPlateSize, WellEditData, Well, WellEditField, WellSampleDropData, RackSampleDropMapper } from '../types'
6
+ import { useListReorder } from '../composables/useListReorder'
5
7
  import { useRackEditor } from '../composables/useRackEditor'
6
8
  import WellPlate from './WellPlate.vue'
7
9
 
@@ -104,23 +106,48 @@ watch(
104
106
  },
105
107
  )
106
108
 
107
- const SLOT_COLORS: Record<SlotPosition, string> = {
108
- R: '#ef4444',
109
- G: '#22c55e',
110
- B: '#3b82f6',
111
- Y: '#eab308',
112
- }
113
-
114
- const SLOT_OPTIONS: SlotPosition[] = ['R', 'G', 'B', 'Y']
109
+ const SLOT_OPTIONS: readonly SlotPosition[] = SLOT_ORDER
115
110
 
116
111
  const FORMAT_OPTIONS: { value: WellPlateFormat; label: string }[] = [
117
112
  { value: 54, label: '54' },
118
113
  { value: 96, label: '96' },
119
114
  ]
120
115
 
121
- // Drag state for rack reordering
122
- const draggingRackId = ref<string | null>(null)
123
- const dragOverRackId = ref<string | null>(null)
116
+ // Rack tab reordering: HTML5 drag for pointers, Alt+Arrow for the keyboard,
117
+ // both owned by the shared reorder composable.
118
+ const tabRefs = new Map<string, HTMLElement>()
119
+
120
+ const {
121
+ draggingId: draggingRackId,
122
+ dragOverId: dragOverRackId,
123
+ announcement: reorderAnnouncement,
124
+ announcerStyle,
125
+ onDragStart: onRackDragStart,
126
+ onDragOver: onRackDragOver,
127
+ onDragLeave: onRackDragLeave,
128
+ onDrop: onRackDrop,
129
+ onDragEnd: onRackDragEnd,
130
+ onKeydown: onRackReorderKeydown,
131
+ } = useListReorder<Rack>({
132
+ items: () => editor.racks.value,
133
+ getId: (rack) => rack.id,
134
+ getLabel: (rack) => rack.name,
135
+ disabled: () => !props.allowReorder || props.readonly,
136
+ getElement: (id) => tabRefs.get(id),
137
+ itemNoun: 'Rack',
138
+ onReorder: ({ fromIndex, toIndex }) => {
139
+ editor.reorderRacks(fromIndex, toIndex)
140
+ emit('rack-reorder', editor.racks.value.map(r => r.id))
141
+ },
142
+ })
143
+
144
+ function setTabRef(id: string, el: Element | ComponentPublicInstance | null) {
145
+ if (el instanceof HTMLElement) {
146
+ tabRefs.set(id, el)
147
+ } else {
148
+ tabRefs.delete(id)
149
+ }
150
+ }
124
151
 
125
152
  function handleAddRack() {
126
153
  const rack = editor.addRack()
@@ -136,54 +163,6 @@ function handleTabClick(rackId: string) {
136
163
  editor.setActiveRack(rackId)
137
164
  }
138
165
 
139
- // Rack drag handlers
140
- function handleRackDragStart(event: DragEvent, rackId: string) {
141
- if (!props.allowReorder) return
142
- draggingRackId.value = rackId
143
- if (event.dataTransfer) {
144
- event.dataTransfer.effectAllowed = 'move'
145
- event.dataTransfer.setData('text/plain', rackId)
146
- }
147
- }
148
-
149
- function handleRackDragOver(event: DragEvent, rackId: string) {
150
- event.preventDefault()
151
- if (draggingRackId.value && draggingRackId.value !== rackId) {
152
- dragOverRackId.value = rackId
153
- }
154
- }
155
-
156
- function handleRackDragLeave() {
157
- dragOverRackId.value = null
158
- }
159
-
160
- function handleRackDrop(event: DragEvent, targetRackId: string) {
161
- event.preventDefault()
162
- if (!draggingRackId.value || draggingRackId.value === targetRackId) {
163
- clearDragState()
164
- return
165
- }
166
-
167
- const fromIndex = editor.racks.value.findIndex(r => r.id === draggingRackId.value)
168
- const toIndex = editor.racks.value.findIndex(r => r.id === targetRackId)
169
-
170
- if (fromIndex !== -1 && toIndex !== -1) {
171
- editor.reorderRacks(fromIndex, toIndex)
172
- emit('rack-reorder', editor.racks.value.map(r => r.id))
173
- }
174
-
175
- clearDragState()
176
- }
177
-
178
- function handleRackDragEnd() {
179
- clearDragState()
180
- }
181
-
182
- function clearDragState() {
183
- draggingRackId.value = null
184
- dragOverRackId.value = null
185
- }
186
-
187
166
  // Toolbar actions
188
167
  function handleFormatChange(format: WellPlateFormat) {
189
168
  if (!editor.activeRack.value) return
@@ -281,9 +260,11 @@ const activeRackWells = computed(() => editor.activeRack.value?.wells ?? {})
281
260
  <div class="mint-rack-editor__tabs">
282
261
  <div class="mint-rack-editor__tabs-inner">
283
262
  <button
284
- v-for="rack in editor.racks.value"
263
+ v-for="(rack, rackIndex) in editor.racks.value"
285
264
  :key="rack.id"
265
+ :ref="(el) => setTabRef(rack.id, el)"
286
266
  :draggable="allowReorder && !readonly"
267
+ :title="allowReorder && !readonly ? `${rack.name} — press Alt with the arrow keys to reorder` : undefined"
287
268
  :class="[
288
269
  'mint-rack-editor__tab',
289
270
  {
@@ -293,11 +274,12 @@ const activeRackWells = computed(() => editor.activeRack.value?.wells ?? {})
293
274
  },
294
275
  ]"
295
276
  @click="handleTabClick(rack.id)"
296
- @dragstart="handleRackDragStart($event, rack.id)"
297
- @dragover="handleRackDragOver($event, rack.id)"
298
- @dragleave="handleRackDragLeave"
299
- @drop="handleRackDrop($event, rack.id)"
300
- @dragend="handleRackDragEnd"
277
+ @keydown="onRackReorderKeydown($event, rack, rackIndex)"
278
+ @dragstart="onRackDragStart($event, rack, rackIndex)"
279
+ @dragover="onRackDragOver($event, rack, rackIndex)"
280
+ @dragleave="onRackDragLeave"
281
+ @drop="onRackDrop($event, rack, rackIndex)"
282
+ @dragend="onRackDragEnd"
301
283
  >
302
284
  <span
303
285
  class="mint-rack-editor__slot-dot"
@@ -434,9 +416,8 @@ const activeRackWells = computed(() => editor.activeRack.value?.wells ?? {})
434
416
  </template>
435
417
  </WellPlate>
436
418
  </div>
419
+
420
+ <!-- Reorder announcements for screen readers -->
421
+ <div role="status" aria-live="polite" :style="announcerStyle">{{ reorderAnnouncement }}</div>
437
422
  </div>
438
423
  </template>
439
-
440
- <style>
441
- @import '../styles/components/rack-editor.css';
442
- </style>
@@ -412,7 +412,3 @@ function formatLevel(value: number): string {
412
412
  </div>
413
413
  </div>
414
414
  </template>
415
-
416
- <style>
417
- @import '../styles/components/reagent-editor.css';
418
- </style>
@@ -76,6 +76,8 @@ const mockReagents: Reagent[] = [
76
76
 
77
77
  function initState() {
78
78
  return {
79
+ loading: false,
80
+ error: '',
79
81
  modelValue: mockReagents,
80
82
  readonly: false,
81
83
  showStockLevel: true,
@@ -92,6 +94,8 @@ function initState() {
92
94
  <template #default="{ state }">
93
95
  <div style="padding: 2rem;">
94
96
  <ReagentList
97
+ :loading="state.loading"
98
+ :error="state.error || null"
95
99
  v-model="state.modelValue"
96
100
  :readonly="state.readonly"
97
101
  :show-stock-level="state.showStockLevel"
@@ -102,6 +106,8 @@ function initState() {
102
106
  </div>
103
107
  </template>
104
108
  <template #controls="{ state }">
109
+ <HstCheckbox v-model="state.loading" title="Loading" />
110
+ <HstText v-model="state.error" title="Error Message" />
105
111
  <HstCheckbox v-model="state.readonly" title="Readonly" />
106
112
  <HstCheckbox v-model="state.showStockLevel" title="Show Stock Level" />
107
113
  <HstSlider v-model="state.lowStockThreshold" title="Low Stock Threshold (%)" :min="0" :max="50" />
@@ -133,5 +139,17 @@ function initState() {
133
139
  <ReagentList :model-value="[]" />
134
140
  </div>
135
141
  </Variant>
142
+
143
+ <Variant title="Loading">
144
+ <div style="padding: 2rem;">
145
+ <ReagentList :model-value="[]" loading />
146
+ </div>
147
+ </Variant>
148
+
149
+ <Variant title="Error">
150
+ <div style="padding: 2rem;">
151
+ <ReagentList :model-value="[]" error="Could not load reagents." />
152
+ </div>
153
+ </Variant>
136
154
  </Story>
137
155
  </template>