@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
@@ -1,8 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  /** Drag-and-drop two-zone assigner for splitting sample groups into control and treatment arms. */
3
- import { ref } from 'vue'
3
+ import { nextTick, ref, type ComponentPublicInstance } from 'vue'
4
4
  import type { GroupItem } from '../types'
5
5
  import { useGroupAssignment, type GroupAssignmentState, type GroupAssignmentZone } from '../composables/useGroupAssignment'
6
+ import { useReorderAnnouncer } from '../composables/useListReorder'
6
7
 
7
8
  interface Props {
8
9
  groups: GroupItem[]
@@ -98,6 +99,56 @@ function emitAssignment(state: GroupAssignmentState) {
98
99
  emit('update:group1', state.group1)
99
100
  emit('update:group2', state.group2)
100
101
  }
102
+
103
+ // Keyboard alternative to the pointer drag. GroupAssigner moves items between
104
+ // zones rather than reordering one list, so it shares the announcer (and the
105
+ // Alt+Arrow idiom) with useListReorder without its index maths.
106
+ const { announcement, announce, announcerStyle } = useReorderAnnouncer()
107
+ const pillRefs = new Map<string, HTMLElement>()
108
+
109
+ function setPillRef(name: string, el: Element | ComponentPublicInstance | null) {
110
+ if (el instanceof HTMLElement) {
111
+ pillRefs.set(name, el)
112
+ } else {
113
+ pillRefs.delete(name)
114
+ }
115
+ }
116
+
117
+ function zoneLabel(zone: GroupAssignmentZone | null): string {
118
+ if (zone === 'zone1') return props.label1
119
+ if (zone === 'zone2') return props.label2
120
+ return 'Available Groups'
121
+ }
122
+
123
+ /** Alt+Left / Alt+Right walk a group through Control → unassigned → Treatment. */
124
+ function handlePillKeydown(event: KeyboardEvent, groupName: string) {
125
+ if (!event.altKey) return
126
+ const direction =
127
+ event.key === 'ArrowLeft' ? -1 : event.key === 'ArrowRight' ? 1 : 0
128
+ if (direction === 0) return
129
+
130
+ event.preventDefault()
131
+ const order: Array<GroupAssignmentZone | null> = ['zone1', null, 'zone2']
132
+ const current = order.indexOf(assignment.getZoneForGroup(groupName))
133
+ const next = order[current + direction]
134
+ if (current === -1 || next === undefined) return
135
+
136
+ if (next === null) {
137
+ const from = assignment.getZoneForGroup(groupName)
138
+ if (from) removeFromZone(groupName, from)
139
+ } else {
140
+ assignToZone(groupName, next)
141
+ }
142
+
143
+ announce(`${groupName} moved to ${zoneLabel(next)}.`)
144
+ void nextTick(() => pillRefs.get(groupName)?.focus())
145
+ }
146
+
147
+ /** Instructions read out with each pill. */
148
+ function pillLabel(group: GroupItem): string {
149
+ const zone = assignment.getZoneForGroup(group.name)
150
+ return `${group.name}, ${zoneLabel(zone)}. Press Alt with the left or right arrow keys to move it.`
151
+ }
101
152
  </script>
102
153
 
103
154
  <template>
@@ -125,10 +176,14 @@ function emitAssignment(state: GroupAssignmentState) {
125
176
  <div
126
177
  v-for="group in zone1Groups"
127
178
  :key="group.name"
179
+ :ref="(el) => setPillRef(group.name, el)"
128
180
  class="mint-group-assigner__pill"
129
181
  draggable="true"
182
+ tabindex="0"
183
+ :aria-label="pillLabel(group)"
130
184
  @dragstart="handleDragStart($event, group.name)"
131
185
  @dragend="handleDragEnd"
186
+ @keydown="handlePillKeydown($event, group.name)"
132
187
  >
133
188
  <span
134
189
  class="mint-group-assigner__pill-color"
@@ -174,10 +229,14 @@ function emitAssignment(state: GroupAssignmentState) {
174
229
  <div
175
230
  v-for="group in zone2Groups"
176
231
  :key="group.name"
232
+ :ref="(el) => setPillRef(group.name, el)"
177
233
  class="mint-group-assigner__pill"
178
234
  draggable="true"
235
+ tabindex="0"
236
+ :aria-label="pillLabel(group)"
179
237
  @dragstart="handleDragStart($event, group.name)"
180
238
  @dragend="handleDragEnd"
239
+ @keydown="handlePillKeydown($event, group.name)"
181
240
  >
182
241
  <span
183
242
  class="mint-group-assigner__pill-color"
@@ -221,14 +280,18 @@ function emitAssignment(state: GroupAssignmentState) {
221
280
  <div
222
281
  v-for="group in unassignedGroups"
223
282
  :key="group.name"
283
+ :ref="(el) => setPillRef(group.name, el)"
224
284
  :class="[
225
285
  'mint-group-assigner__pill',
226
286
  'mint-group-assigner__pill--unassigned',
227
287
  draggingGroup === group.name ? 'mint-group-assigner__pill--dragging' : '',
228
288
  ]"
229
289
  draggable="true"
290
+ tabindex="0"
291
+ :aria-label="pillLabel(group)"
230
292
  @dragstart="handleDragStart($event, group.name)"
231
293
  @dragend="handleDragEnd"
294
+ @keydown="handlePillKeydown($event, group.name)"
232
295
  >
233
296
  <span
234
297
  class="mint-group-assigner__pill-color"
@@ -240,6 +303,9 @@ function emitAssignment(state: GroupAssignmentState) {
240
303
  </div>
241
304
  </div>
242
305
 
306
+ <!-- Assignment announcements for screen readers -->
307
+ <div role="status" aria-live="polite" :style="announcerStyle">{{ announcement }}</div>
308
+
243
309
  <!-- Validation message -->
244
310
  <div v-if="validationMessage" class="mint-group-assigner__validation">
245
311
  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -251,7 +317,3 @@ function emitAssignment(state: GroupAssignmentState) {
251
317
  </div>
252
318
  </div>
253
319
  </template>
254
-
255
- <style>
256
- @import '../styles/components/group-assigner.css';
257
- </style>
@@ -67,7 +67,3 @@ function handleClick(event: MouseEvent) {
67
67
  </span>
68
68
  </button>
69
69
  </template>
70
-
71
- <style>
72
- @import '../styles/components/icon-button.css';
73
- </style>
@@ -185,7 +185,3 @@ function alertDetail(alert: InstrumentAlert): string {
185
185
  </TransitionGroup>
186
186
  </div>
187
187
  </template>
188
-
189
- <style>
190
- @import '../styles/components/instrument-monitor.css';
191
- </style>
@@ -44,7 +44,3 @@ const shouldPulse = computed(() => props.pulseWhenRunning && normalizedState.val
44
44
  {{ label ?? config.label }}
45
45
  </span>
46
46
  </template>
47
-
48
- <style>
49
- @import '../styles/components/instrument-monitor.css';
50
- </style>
@@ -182,7 +182,3 @@ function hasRemaining(progress: SequenceProgress | null | undefined): boolean {
182
182
  </template>
183
183
  </div>
184
184
  </template>
185
-
186
- <style>
187
- @import '../styles/components/instrument-monitor.css';
188
- </style>
@@ -401,7 +401,3 @@ async function clearFinished(): Promise<void> {
401
401
  </div>
402
402
  </Teleport>
403
403
  </template>
404
-
405
- <style>
406
- @import '../styles/components/jobs-status-tray.css';
407
- </style>
@@ -1,12 +1,14 @@
1
1
  <script setup lang="ts">
2
2
  /** Table for Xcalibur-compatible LCMS sequence rows with optional reorder/remove/duplicate controls. */
3
- import { computed, ref } from 'vue'
3
+ import { computed, type ComponentPublicInstance } from 'vue'
4
+ import { useListReorder } from '../composables/useListReorder'
4
5
  import {
5
6
  basenameFromWindowsPath,
6
7
  DEFAULT_LCMS_SEQUENCE_COLUMNS,
7
8
  type LcmsSequenceItem,
8
9
  type LcmsSequenceTableColumn,
9
10
  } from '../lcms'
11
+ import DataStateInternal from './internal/DataStateInternal.vue'
10
12
 
11
13
  interface Props {
12
14
  items?: LcmsSequenceItem[]
@@ -15,6 +17,13 @@ interface Props {
15
17
  maxRows?: number
16
18
  showMoreLabel?: boolean
17
19
  emptyMessage?: string
20
+ /** Replace the table with a loading placeholder. */
21
+ loading?: boolean
22
+ /**
23
+ * Error message. When set, the table is replaced by an error state.
24
+ * `null`/`undefined` renders normally.
25
+ */
26
+ error?: string | null
18
27
  }
19
28
 
20
29
  const props = withDefaults(defineProps<Props>(), {
@@ -24,6 +33,8 @@ const props = withDefaults(defineProps<Props>(), {
24
33
  maxRows: undefined,
25
34
  showMoreLabel: true,
26
35
  emptyMessage: 'No sequence items to display',
36
+ loading: false,
37
+ error: null,
27
38
  })
28
39
 
29
40
  const emit = defineEmits<{
@@ -32,8 +43,38 @@ const emit = defineEmits<{
32
43
  duplicate: [index: number]
33
44
  }>()
34
45
 
35
- const dragIndex = ref<number | null>(null)
36
- const dropTargetIndex = ref<number | null>(null)
46
+ // Rows are a plain ordered list: pointer drag plus an Alt+Arrow keyboard
47
+ // alternative, both from the shared reorder composable.
48
+ const handleRefs = new Map<string, HTMLElement>()
49
+
50
+ const {
51
+ draggingId,
52
+ dragOverId,
53
+ announcement: reorderAnnouncement,
54
+ announcerStyle,
55
+ onDragStart,
56
+ onDragOver,
57
+ onDragLeave,
58
+ onDrop,
59
+ onDragEnd,
60
+ onKeydown: onReorderKeydown,
61
+ } = useListReorder<LcmsSequenceItem>({
62
+ items: () => props.items,
63
+ getId: (_item, index) => String(index),
64
+ getLabel: (item) => item.file_name,
65
+ disabled: () => !props.editable,
66
+ getElement: (id) => handleRefs.get(id),
67
+ itemNoun: 'Row',
68
+ onReorder: ({ fromIndex, toIndex }) => emit('reorder', fromIndex, toIndex),
69
+ })
70
+
71
+ function setHandleRef(index: number, el: Element | ComponentPublicInstance | null) {
72
+ if (el instanceof HTMLElement) {
73
+ handleRefs.set(String(index), el)
74
+ } else {
75
+ handleRefs.delete(String(index))
76
+ }
77
+ }
37
78
 
38
79
  const displayItems = computed(() => {
39
80
  if (!props.maxRows) return props.items
@@ -60,42 +101,11 @@ function cellValue(item: LcmsSequenceItem, column: LcmsSequenceTableColumn, inde
60
101
  return item[column.key] ?? ''
61
102
  }
62
103
 
63
- function onDragStart(event: DragEvent, index: number) {
64
- if (!props.editable) return
65
- dragIndex.value = index
66
- if (event.dataTransfer) {
67
- event.dataTransfer.effectAllowed = 'move'
68
- event.dataTransfer.setData('text/plain', String(index))
69
- }
70
- }
71
-
72
- function onDragOver(event: DragEvent, index: number) {
73
- if (!props.editable) return
74
- event.preventDefault()
75
- if (event.dataTransfer) event.dataTransfer.dropEffect = 'move'
76
- if (dragIndex.value !== null && dragIndex.value !== index) {
77
- dropTargetIndex.value = index
78
- }
79
- }
80
-
81
- function clearDragState() {
82
- dragIndex.value = null
83
- dropTargetIndex.value = null
84
- }
85
-
86
- function onDrop(event: DragEvent, toIndex: number) {
87
- if (!props.editable) return
88
- event.preventDefault()
89
- if (dragIndex.value !== null && dragIndex.value !== toIndex) {
90
- emit('reorder', dragIndex.value, toIndex)
91
- }
92
- clearDragState()
93
- }
94
104
  </script>
95
105
 
96
106
  <template>
97
107
  <div class="mint-lcms-sequence-table">
98
- <div class="mint-lcms-sequence-table__scroller">
108
+ <div v-if="!loading && !error && items.length > 0" class="mint-lcms-sequence-table__scroller">
99
109
  <table class="mint-lcms-sequence-table__table">
100
110
  <thead>
101
111
  <tr>
@@ -120,19 +130,27 @@ function onDrop(event: DragEvent, toIndex: number) {
120
130
  :draggable="editable"
121
131
  class="mint-lcms-sequence-table__row"
122
132
  :class="{
123
- 'mint-lcms-sequence-table__row--dragging': dragIndex === index,
124
- 'mint-lcms-sequence-table__row--drop-above': dropTargetIndex === index && dragIndex !== null && dragIndex > index,
125
- 'mint-lcms-sequence-table__row--drop-below': dropTargetIndex === index && dragIndex !== null && dragIndex < index,
133
+ 'mint-lcms-sequence-table__row--dragging': draggingId === String(index),
134
+ 'mint-lcms-sequence-table__row--drop-above': dragOverId === String(index) && draggingId !== null && Number(draggingId) > index,
135
+ 'mint-lcms-sequence-table__row--drop-below': dragOverId === String(index) && draggingId !== null && Number(draggingId) < index,
126
136
  }"
127
- @dragstart="onDragStart($event, index)"
137
+ @dragstart="onDragStart($event, item, index)"
128
138
  @dragenter.prevent
129
- @dragover="onDragOver($event, index)"
130
- @dragleave="dropTargetIndex = null"
131
- @drop="onDrop($event, index)"
132
- @dragend="clearDragState"
139
+ @dragover="onDragOver($event, item, index)"
140
+ @dragleave="onDragLeave"
141
+ @drop="onDrop($event, item, index)"
142
+ @dragend="onDragEnd"
133
143
  >
134
144
  <td v-if="editable" class="mint-lcms-sequence-table__drag-cell">
135
- <span class="mint-lcms-sequence-table__drag-handle" aria-hidden="true">::</span>
145
+ <button
146
+ :ref="(el) => setHandleRef(index, el)"
147
+ type="button"
148
+ class="mint-lcms-sequence-table__drag-handle"
149
+ :aria-label="`Reorder ${item.file_name}. Press Alt with the arrow keys to move it.`"
150
+ @keydown="onReorderKeydown($event, item, index)"
151
+ >
152
+ ::
153
+ </button>
136
154
  </td>
137
155
  <td
138
156
  v-for="column in columns"
@@ -176,16 +194,29 @@ function onDrop(event: DragEvent, toIndex: number) {
176
194
  </table>
177
195
  </div>
178
196
 
179
- <div v-if="items.length === 0" class="mint-lcms-sequence-table__empty">
180
- {{ emptyMessage }}
197
+ <div v-else-if="error" class="mint-lcms-sequence-table__state">
198
+ <slot name="error" :error="error">
199
+ <DataStateInternal state="error" size="sm" :title="error" />
200
+ </slot>
201
+ </div>
202
+
203
+ <div v-else-if="loading" class="mint-lcms-sequence-table__state">
204
+ <slot name="loading">
205
+ <DataStateInternal state="loading" size="sm" loading-label="Loading sequence" />
206
+ </slot>
207
+ </div>
208
+
209
+ <div v-else class="mint-lcms-sequence-table__state">
210
+ <slot name="empty">
211
+ <DataStateInternal state="empty" size="sm" :title="emptyMessage" />
212
+ </slot>
181
213
  </div>
182
214
 
183
215
  <div v-if="hasMore && showMoreLabel" class="mint-lcms-sequence-table__more">
184
216
  Showing first {{ maxRows }} of {{ items.length }} items
185
217
  </div>
218
+
219
+ <!-- Reorder announcements for screen readers -->
220
+ <div role="status" aria-live="polite" :style="announcerStyle">{{ reorderAnnouncement }}</div>
186
221
  </div>
187
222
  </template>
188
-
189
- <style>
190
- @import '../styles/components/lcms-sequence-table.css';
191
- </style>
@@ -44,7 +44,3 @@ withDefaults(defineProps<Props>(), {
44
44
  <span class="mint-spinner__label">{{ label }}</span>
45
45
  </div>
46
46
  </template>
47
-
48
- <style>
49
- @import '../styles/components/loading-spinner.css';
50
- </style>
@@ -109,7 +109,3 @@ const {
109
109
  :is-supported="isSupported"
110
110
  />
111
111
  </template>
112
-
113
- <style>
114
- @import '../styles/components/mobile-support-gate.css';
115
- </style>
@@ -420,7 +420,3 @@ onUnmounted(() => {
420
420
  </div>
421
421
  </div>
422
422
  </template>
423
-
424
- <style>
425
- @import '../styles/components/molecule-input.css';
426
- </style>
@@ -117,7 +117,3 @@ const selectedLabels = computed(() => {
117
117
  </div>
118
118
  </div>
119
119
  </template>
120
-
121
- <style>
122
- @import '../styles/components/multi-select.css';
123
- </style>
@@ -156,7 +156,3 @@ function increment() {
156
156
  />
157
157
  </div>
158
158
  </template>
159
-
160
- <style>
161
- @import '../styles/components/number-input.css';
162
- </style>
@@ -1,22 +1,15 @@
1
1
  <script setup lang="ts">
2
2
  /** Full plate-map design environment for 96/384-well plates with sample assignment, slot-color coding, undo/redo, and CSV/JSON import-export. */
3
3
  import { ref, computed, watch } from 'vue'
4
- import type { PlateMapEditorState, WellPlateFormat, SampleType, Well, PlateMap } from '../types'
4
+ import type { PlateMapEditorState, WellPlateFormat, SampleType, Well, PlateMap, SlotPosition } from '../types'
5
+ // Slot colors matching MSExpDesigner — shared with RackEditor.
6
+ import { SLOT_COLORS, SLOT_ORDER } from '../utils/color'
5
7
  import { useWellPlateEditor } from '../composables/useWellPlateEditor'
6
8
  import { useEventListener } from '../composables/useEventListener'
7
9
  import WellPlate from './WellPlate.vue'
8
10
  import SampleLegend from './SampleLegend.vue'
9
11
  import PlateMapEditorToolbarInternal from './internal/PlateMapEditorToolbarInternal.vue'
10
12
 
11
- // Slot colors matching MSExpDesigner
12
- type SlotPosition = 'R' | 'G' | 'B' | 'Y'
13
- const SLOT_COLORS: Record<SlotPosition, string> = {
14
- R: '#ef4444', // red
15
- G: '#22c55e', // green
16
- B: '#3b82f6', // blue
17
- Y: '#eab308', // yellow
18
- }
19
- const SLOT_ORDER: SlotPosition[] = ['R', 'G', 'B', 'Y']
20
13
 
21
14
  interface Props {
22
15
  modelValue?: PlateMapEditorState
@@ -428,7 +421,3 @@ useEventListener(() => document, 'keydown', handleKeyDown)
428
421
  </Teleport>
429
422
  </div>
430
423
  </template>
431
-
432
- <style>
433
- @import '../styles/components/plate-map-editor.css';
434
- </style>
@@ -0,0 +1,61 @@
1
+ <script setup lang="ts">
2
+ import type * as Plotly from 'plotly.js'
3
+
4
+ import PlotlyChart from './PlotlyChart.vue'
5
+
6
+ const data: Plotly.Data[] = [
7
+ {
8
+ type: 'scatter',
9
+ mode: 'lines+markers',
10
+ name: 'Control',
11
+ x: ['0 h', '6 h', '12 h', '24 h'],
12
+ y: [1, 1.3, 1.8, 2.1],
13
+ },
14
+ {
15
+ type: 'scatter',
16
+ mode: 'lines+markers',
17
+ name: 'Treatment',
18
+ x: ['0 h', '6 h', '12 h', '24 h'],
19
+ y: [1, 1.8, 3.1, 4.4],
20
+ },
21
+ ]
22
+
23
+ const layout: Partial<Plotly.Layout> = {
24
+ margin: { t: 24, r: 24, b: 56, l: 56 },
25
+ xaxis: { title: { text: 'Time' } },
26
+ yaxis: { title: { text: 'Relative abundance' } },
27
+ }
28
+ </script>
29
+
30
+ <template>
31
+ <Story title="Data Display/PlotlyChart">
32
+ <Variant title="Native Plotly">
33
+ <div style="max-width: 760px; margin: 0 auto; padding: 2rem;">
34
+ <PlotlyChart
35
+ title="Metabolite response"
36
+ description="Native Plotly traces with MINT theme and resize handling"
37
+ :data="data"
38
+ :layout="layout"
39
+ :config="{ toImageButtonOptions: { filename: 'metabolite-response' } }"
40
+ />
41
+ </div>
42
+ </Variant>
43
+
44
+ <Variant title="Empty">
45
+ <div style="max-width: 760px; margin: 0 auto; padding: 2rem;">
46
+ <PlotlyChart
47
+ title="Metabolite response"
48
+ :data="[]"
49
+ empty
50
+ empty-message="No measurements are available."
51
+ />
52
+ </div>
53
+ </Variant>
54
+
55
+ <Variant title="Loading">
56
+ <div style="max-width: 760px; margin: 0 auto; padding: 2rem;">
57
+ <PlotlyChart title="Loading measurements" :data="[]" loading />
58
+ </div>
59
+ </Variant>
60
+ </Story>
61
+ </template>