@morscherlab/mint-sdk 1.2.0-beta.1 → 1.2.0-beta.10

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 (408) hide show
  1. package/README.md +35 -5
  2. package/dist/{ExperimentPopover-tLwJ7XF4.js → ExperimentPopover-oL0fg_A0.js} +6 -4
  3. package/dist/ExperimentPopover-oL0fg_A0.js.map +1 -0
  4. package/dist/{ExperimentSelectorModal-DyPAUCLw.js → ExperimentSelectorModal-BeEOomw_.js} +5 -5
  5. package/dist/ExperimentSelectorModal-BeEOomw_.js.map +1 -0
  6. package/dist/{SettingsModal-BgKY93zh.js → SettingsModal-Dphh3RrI.js} +5 -8
  7. package/dist/SettingsModal-Dphh3RrI.js.map +1 -0
  8. package/dist/{EmptyState-p90quq8Z.js → Skeleton-DxtwJ5gt.js} +111 -93
  9. package/dist/Skeleton-DxtwJ5gt.js.map +1 -0
  10. package/dist/__tests__/components/ExperimentTimeline.test.d.ts +1 -0
  11. package/dist/__tests__/components/PluginWorkspaceView.internal.test.d.ts +1 -0
  12. package/dist/__tests__/components/SecretInput.test.d.ts +1 -0
  13. package/dist/__tests__/components/WellEditPopupInternal.test.d.ts +1 -0
  14. package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
  15. package/dist/__tests__/composables/usePluginConfig.test.d.ts +15 -0
  16. package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
  17. package/dist/components/ActionMenu.vue.d.ts +1 -1
  18. package/dist/components/AppAvatarMenu.vue.d.ts +4 -0
  19. package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
  20. package/dist/components/AppSidebar.vue.d.ts +1 -1
  21. package/dist/components/AuditTrail.vue.d.ts +13 -0
  22. package/dist/components/AutoGroupModal.vue.d.ts +1 -1
  23. package/dist/components/BatchProgressList.vue.d.ts +17 -0
  24. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
  25. package/dist/components/DataFrame.vue.d.ts +14 -2
  26. package/dist/components/DatePicker.vue.d.ts +1 -1
  27. package/dist/components/DateTimePicker.vue.d.ts +2 -0
  28. package/dist/components/DropdownButton.vue.d.ts +2 -0
  29. package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
  30. package/dist/components/ExperimentPopover.vue.d.ts +1 -0
  31. package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
  32. package/dist/components/FitPanel.vue.d.ts +1 -1
  33. package/dist/components/JobsStatusTray.vue.d.ts +9 -2
  34. package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
  35. package/dist/components/PluginWorkspaceView.props.d.ts +29 -1
  36. package/dist/components/PluginWorkspaceView.vue.d.ts +5 -5
  37. package/dist/components/ProgressBar.vue.d.ts +1 -1
  38. package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
  39. package/dist/components/ReagentList.vue.d.ts +29 -1
  40. package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
  41. package/dist/components/SampleLegend.vue.d.ts +1 -1
  42. package/dist/components/SampleSelector.drag.d.ts +13 -0
  43. package/dist/components/SampleSelector.tree.d.ts +2 -0
  44. package/dist/components/SampleSelector.vue.d.ts +35 -2
  45. package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
  46. package/dist/components/SecretInput.vue.d.ts +28 -0
  47. package/dist/components/SettingsModal.vue.d.ts +1 -1
  48. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -1
  49. package/dist/components/TimePicker.vue.d.ts +1 -0
  50. package/dist/components/WellPlate.geometry.d.ts +15 -0
  51. package/dist/components/WellPlate.interaction.d.ts +13 -0
  52. package/dist/components/WellPlate.vue.d.ts +29 -0
  53. package/dist/components/index.d.ts +9 -0
  54. package/dist/components/index.js +8 -8
  55. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
  56. package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
  57. package/dist/components/internal/WellEditPopupInternal.vue.d.ts +3 -1
  58. package/dist/components/internal/WorkspaceControlsInternal.vue.d.ts +23 -0
  59. package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +70 -0
  60. package/dist/components/internal/WorkspaceSidebarInternal.vue.d.ts +43 -0
  61. package/dist/{components-DkHddRMl.js → components-CgAUzF8F.js} +2497 -2235
  62. package/dist/components-CgAUzF8F.js.map +1 -0
  63. package/dist/composables/controlSchemaTypes.d.ts +34 -0
  64. package/dist/composables/flattenWorkspaceBindings.d.ts +61 -0
  65. package/dist/composables/index.d.ts +9 -2
  66. package/dist/composables/index.js +10 -10
  67. package/dist/composables/pluginWorkspaceModel.d.ts +164 -0
  68. package/dist/composables/useAsync.d.ts +5 -1
  69. package/dist/composables/useBioTemplateWorkspace.d.ts +4 -20
  70. package/dist/composables/useCommandHistory.d.ts +5 -1
  71. package/dist/composables/useDropdownState.d.ts +18 -2
  72. package/dist/composables/useEventStream.d.ts +9 -0
  73. package/dist/composables/useFocusTrap.d.ts +21 -0
  74. package/dist/composables/useGeneratedAnalysis.d.ts +3 -1
  75. package/dist/composables/useJobsStatusTray.d.ts +25 -1
  76. package/dist/composables/useListReorder.d.ts +90 -0
  77. package/dist/composables/useMenuKeyboard.d.ts +29 -0
  78. package/dist/composables/useOptimisticMutation.d.ts +5 -1
  79. package/dist/composables/usePluginClient.d.ts +2 -0
  80. package/dist/composables/usePluginConfig.d.ts +27 -0
  81. package/dist/composables/usePluginWorkspace.d.ts +51 -0
  82. package/dist/composables/useRequestSyncState.d.ts +42 -2
  83. package/dist/composables/useResourceCrud.d.ts +5 -1
  84. package/dist/composables/useRovingFocus.d.ts +24 -0
  85. package/dist/composables/useScheduleDrag.d.ts +1 -0
  86. package/dist/composables/useWellPainting.d.ts +5 -1
  87. package/dist/composables/useWellPlateAdapter.d.ts +5 -1
  88. package/dist/composables/useWellPlateValidation.d.ts +5 -1
  89. package/dist/composables/workspaceRecipes.d.ts +188 -0
  90. package/dist/{composables-C_i90sGS.js → composables-B_pia3hO.js} +209 -82
  91. package/dist/composables-B_pia3hO.js.map +1 -0
  92. package/dist/{useApi-J6zFkHmn.js → errors-_W0-LbA6.js} +103 -3
  93. package/dist/errors-_W0-LbA6.js.map +1 -0
  94. package/dist/{experiment-Cq145oEW.js → experiment-Cwl9AYxw.js} +3 -8
  95. package/dist/experiment-Cwl9AYxw.js.map +1 -0
  96. package/dist/{experiment-utils-CLnzPPq5.js → experiment-utils-DV3DrvE_.js} +70 -51
  97. package/dist/experiment-utils-DV3DrvE_.js.map +1 -0
  98. package/dist/index.d.ts +1 -0
  99. package/dist/index.js +15 -15
  100. package/dist/install.js +2 -7
  101. package/dist/install.js.map +1 -1
  102. package/dist/permissions.d.ts +42 -1
  103. package/dist/permissions.js +20 -10
  104. package/dist/permissions.js.map +1 -1
  105. package/dist/stores/auth.d.ts +6 -0
  106. package/dist/stores/index.d.ts +1 -1
  107. package/dist/stores/index.js +3 -3
  108. package/dist/stores/settings.d.ts +31 -1
  109. package/dist/styles.css +11247 -29501
  110. package/dist/templates/builderReadUtils.d.ts +1 -1
  111. package/dist/templates/index.js +2 -4
  112. package/dist/{templates-DsP51i-S.js → templates-Qq113pyZ.js} +303 -106
  113. package/dist/templates-Qq113pyZ.js.map +1 -0
  114. package/dist/types/auth.d.ts +1 -0
  115. package/dist/types/form-builder.d.ts +1 -1
  116. package/dist/{useControlSchema-BDx2Olha.js → useControlSchema-aMZlb4Sc.js} +462 -1130
  117. package/dist/useControlSchema-aMZlb4Sc.js.map +1 -0
  118. package/dist/{useDropdownState-DSb3BC3N.js → useDropdownState-DitCtrTT.js} +22 -6
  119. package/dist/useDropdownState-DitCtrTT.js.map +1 -0
  120. package/dist/{useExperimentSelector-CV4iNfMS.js → useExperimentSelector-I8HC8hUu.js} +4 -4
  121. package/dist/{useExperimentSelector-CV4iNfMS.js.map → useExperimentSelector-I8HC8hUu.js.map} +1 -1
  122. package/dist/{useFormBuilder-BLxG3BOX.js → useFormBuilder-TCxNnqeb.js} +2 -2
  123. package/dist/{useFormBuilder-BLxG3BOX.js.map → useFormBuilder-TCxNnqeb.js.map} +1 -1
  124. package/dist/{useProtocolTemplates-CS_SQl6U.js → useProtocolTemplates-BmX_iVBR.js} +766 -212
  125. package/dist/useProtocolTemplates-BmX_iVBR.js.map +1 -0
  126. package/dist/utils/color.d.ts +13 -0
  127. package/dist/utils/errors.d.ts +9 -0
  128. package/dist/utils/pluginSecrets.d.ts +53 -0
  129. package/dist/utils/records.d.ts +4 -0
  130. package/package.json +1 -1
  131. package/src/__tests__/components/ActionMenu.test.ts +94 -0
  132. package/src/__tests__/components/AppAvatarMenu.test.ts +123 -0
  133. package/src/__tests__/components/BaseTabs.test.ts +67 -0
  134. package/src/__tests__/components/DataFrame.test.ts +183 -11
  135. package/src/__tests__/components/DataStates.test.ts +176 -0
  136. package/src/__tests__/components/DatePicker.test.ts +76 -0
  137. package/src/__tests__/components/DateTimePicker.test.ts +36 -0
  138. package/src/__tests__/components/DropdownButton.test.ts +134 -0
  139. package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
  140. package/src/__tests__/components/GroupAssigner.test.ts +53 -0
  141. package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
  142. package/src/__tests__/components/PluginWorkspaceView.internal.test.ts +230 -0
  143. package/src/__tests__/components/RackEditor.test.ts +35 -0
  144. package/src/__tests__/components/ReagentList.test.ts +64 -2
  145. package/src/__tests__/components/RetiredStyles.test.ts +31 -0
  146. package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
  147. package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
  148. package/src/__tests__/components/SecretInput.test.ts +87 -0
  149. package/src/__tests__/components/SegmentedControl.test.ts +88 -0
  150. package/src/__tests__/components/TimePicker.test.ts +61 -0
  151. package/src/__tests__/components/WellEditPopupInternal.test.ts +108 -0
  152. package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
  153. package/src/__tests__/composables/useAuth.test.ts +2 -0
  154. package/src/__tests__/composables/useDropdownState.test.ts +58 -1
  155. package/src/__tests__/composables/useListReorder.test.ts +145 -0
  156. package/src/__tests__/composables/usePluginClient.test.ts +140 -0
  157. package/src/__tests__/composables/usePluginConfig.test.ts +497 -0
  158. package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
  159. package/src/__tests__/docs/frontendDocsCatalog.test.ts +39 -7
  160. package/src/__tests__/stores/settings.test.ts +71 -1
  161. package/src/__tests__/styles/cssTokens.test.ts +131 -0
  162. package/src/__tests__/utils/permissions.test.ts +68 -0
  163. package/src/components/ActionMenu.vue +45 -88
  164. package/src/components/AlertBox.vue +0 -4
  165. package/src/components/AppAvatarMenu.vue +26 -7
  166. package/src/components/AppLayout.vue +0 -4
  167. package/src/components/AppPluginSwitcher.story.vue +87 -0
  168. package/src/components/AppPluginSwitcher.vue +2 -5
  169. package/src/components/AppSidebar.vue +0 -4
  170. package/src/components/AppToastContainer.vue +6 -8
  171. package/src/components/AppTopBar.vue +0 -4
  172. package/src/components/ArtifactSaveDialog.vue +0 -4
  173. package/src/components/ArtifactSelectorModal.vue +0 -4
  174. package/src/components/AuditTrail.story.vue +18 -0
  175. package/src/components/AuditTrail.vue +27 -7
  176. package/src/components/AutoGroupModal.vue +0 -4
  177. package/src/components/Avatar.vue +0 -4
  178. package/src/components/BaseButton.vue +0 -4
  179. package/src/components/BaseCheckbox.vue +0 -4
  180. package/src/components/BaseInput.vue +0 -4
  181. package/src/components/BaseModal.vue +8 -60
  182. package/src/components/BasePill.vue +0 -4
  183. package/src/components/BaseRadioGroup.vue +0 -4
  184. package/src/components/BaseSelect.vue +0 -4
  185. package/src/components/BaseSlider.vue +0 -4
  186. package/src/components/BaseTabs.vue +26 -5
  187. package/src/components/BaseTextarea.vue +0 -4
  188. package/src/components/BaseToggle.vue +0 -4
  189. package/src/components/BatchProgressList.story.vue +18 -0
  190. package/src/components/BatchProgressList.vue +32 -4
  191. package/src/components/BioTemplateExperimentWorkspaceView.vue +10 -21
  192. package/src/components/BioTemplatePackWorkspaceView.vue +11 -15
  193. package/src/components/BioTemplatePresetWorkspaceView.vue +8 -13
  194. package/src/components/Breadcrumb.vue +0 -4
  195. package/src/components/Calendar.vue +0 -4
  196. package/src/components/ChartContainer.story.vue +1 -1
  197. package/src/components/ChartContainer.vue +0 -4
  198. package/src/components/ChemicalFormula.vue +0 -4
  199. package/src/components/CollapsibleCard.vue +0 -4
  200. package/src/components/ColorSlider.vue +0 -4
  201. package/src/components/ComponentBindingRenderer.vue +1 -3
  202. package/src/components/ConcentrationInput.vue +0 -4
  203. package/src/components/ConfirmDialog.vue +0 -4
  204. package/src/components/ControlWorkspaceView.vue +11 -22
  205. package/src/components/DataFrame.story.vue +14 -0
  206. package/src/components/DataFrame.vue +97 -23
  207. package/src/components/DatePicker.vue +73 -27
  208. package/src/components/DateTimePicker.vue +45 -17
  209. package/src/components/Divider.vue +0 -4
  210. package/src/components/DoseCalculator.vue +0 -4
  211. package/src/components/DoseDesignWorkspaceView.vue +6 -25
  212. package/src/components/DropdownButton.vue +24 -6
  213. package/src/components/EmptyState.vue +0 -4
  214. package/src/components/ExperimentCodeBadge.vue +0 -4
  215. package/src/components/ExperimentDataViewer.story.vue +3 -0
  216. package/src/components/ExperimentDataViewer.vue +33 -13
  217. package/src/components/ExperimentPopover.vue +2 -5
  218. package/src/components/ExperimentSelectorModal.vue +0 -4
  219. package/src/components/ExperimentTimeline.story.vue +18 -0
  220. package/src/components/ExperimentTimeline.vue +81 -75
  221. package/src/components/FileUploader.vue +0 -4
  222. package/src/components/FitPanel.vue +0 -4
  223. package/src/components/FormActions.story.vue +96 -0
  224. package/src/components/FormActions.vue +0 -4
  225. package/src/components/FormBuilder.vue +0 -4
  226. package/src/components/FormField.vue +0 -4
  227. package/src/components/FormulaInput.vue +0 -4
  228. package/src/components/GeneratedPathInput.story.vue +68 -0
  229. package/src/components/GeneratedPlotlyResult.story.vue +96 -0
  230. package/src/components/GeneratedPlotlyResult.vue +3 -3
  231. package/src/components/GeneratedPluginView.story.vue +145 -0
  232. package/src/components/GeneratedPluginView.vue +10 -10
  233. package/src/components/GeneratedResultRenderer.story.vue +117 -0
  234. package/src/components/GeneratedResultRenderer.vue +4 -4
  235. package/src/components/GroupAssigner.vue +67 -5
  236. package/src/components/IconButton.vue +0 -4
  237. package/src/components/InstrumentAlertLog.vue +0 -4
  238. package/src/components/InstrumentStateBadge.vue +0 -4
  239. package/src/components/InstrumentStatusCard.vue +0 -4
  240. package/src/components/JobsStatusTray.vue +16 -5
  241. package/src/components/LcmsSequenceTable.vue +81 -50
  242. package/src/components/LoadingSpinner.vue +0 -4
  243. package/src/components/MobileSupportGate.vue +0 -4
  244. package/src/components/MoleculeInput.vue +0 -4
  245. package/src/components/MultiSelect.vue +0 -4
  246. package/src/components/NumberInput.vue +0 -4
  247. package/src/components/PlateMapEditor.vue +3 -14
  248. package/src/components/PluginIcon.vue +0 -4
  249. package/src/components/PluginWorkspaceView.props.ts +38 -0
  250. package/src/components/PluginWorkspaceView.vue +53 -224
  251. package/src/components/ProgressBar.vue +0 -4
  252. package/src/components/ProtocolStepEditor.vue +2 -4
  253. package/src/components/RackEditor.vue +51 -70
  254. package/src/components/ReagentEditor.vue +0 -4
  255. package/src/components/ReagentList.story.vue +18 -0
  256. package/src/components/ReagentList.vue +127 -82
  257. package/src/components/ResourceCard.vue +0 -4
  258. package/src/components/RuntimeUpdateNotice.story.vue +49 -0
  259. package/src/components/RuntimeUpdateNotice.vue +4 -4
  260. package/src/components/SampleHierarchyTree.story.vue +18 -0
  261. package/src/components/SampleHierarchyTree.vue +32 -9
  262. package/src/components/SampleLegend.vue +2 -8
  263. package/src/components/SampleSelector.drag.ts +51 -0
  264. package/src/components/SampleSelector.story.vue +6 -0
  265. package/src/components/SampleSelector.tree.ts +2 -0
  266. package/src/components/SampleSelector.vue +49 -10
  267. package/src/components/SampleSelectorGroupNode.vue +19 -0
  268. package/src/components/ScheduleCalendar.story.vue +6 -0
  269. package/src/components/ScheduleCalendar.vue +82 -7
  270. package/src/components/ScientificNumber.vue +0 -4
  271. package/src/components/SecretInput.story.vue +79 -0
  272. package/src/components/SecretInput.vue +150 -0
  273. package/src/components/SectionCard.vue +0 -4
  274. package/src/components/SegmentedControl.vue +48 -5
  275. package/src/components/SequenceInput.vue +0 -4
  276. package/src/components/SequenceProgressBar.story.vue +110 -0
  277. package/src/components/SequenceProgressBar.vue +0 -4
  278. package/src/components/SettingsModal.vue +0 -4
  279. package/src/components/Skeleton.vue +0 -4
  280. package/src/components/SmartGroupFieldRecipe.vue +8 -6
  281. package/src/components/SmartGroupManual.vue +0 -4
  282. package/src/components/StatusIndicator.vue +0 -4
  283. package/src/components/StepWizard.vue +0 -4
  284. package/src/components/TagsInput.vue +4 -6
  285. package/src/components/ThemeToggle.vue +0 -4
  286. package/src/components/TimePicker.vue +36 -7
  287. package/src/components/TimeRangeInput.vue +0 -4
  288. package/src/components/Tooltip.story.vue +3 -3
  289. package/src/components/Tooltip.vue +0 -4
  290. package/src/components/UnitInput.vue +0 -4
  291. package/src/components/WellPlate.geometry.ts +60 -1
  292. package/src/components/WellPlate.interaction.ts +44 -0
  293. package/src/components/WellPlate.story.vue +8 -0
  294. package/src/components/WellPlate.vue +53 -7
  295. package/src/components/index.ts +9 -0
  296. package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
  297. package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
  298. package/src/components/internal/DataStateInternal.vue +74 -0
  299. package/src/components/internal/FormSectionRenderer.vue +0 -4
  300. package/src/components/internal/WellEditPopupInternal.vue +20 -5
  301. package/src/components/internal/WorkspaceControlsInternal.vue +20 -0
  302. package/src/components/internal/WorkspaceShellInternal.vue +125 -0
  303. package/src/components/internal/WorkspaceSidebarInternal.vue +82 -0
  304. package/src/composables/controlSchemaTypes.ts +34 -0
  305. package/src/composables/experimentDesignData.ts +1 -3
  306. package/src/composables/flattenWorkspaceBindings.ts +104 -0
  307. package/src/composables/formBuilderRegistry.ts +5 -0
  308. package/src/composables/index.ts +43 -0
  309. package/src/composables/pluginWorkspaceModel.ts +182 -0
  310. package/src/composables/useAsync.ts +5 -1
  311. package/src/composables/useAuth.ts +3 -0
  312. package/src/composables/useBioTemplatePackWorkspace.ts +15 -9
  313. package/src/composables/useBioTemplatePresetWorkspace.ts +14 -15
  314. package/src/composables/useBioTemplateWorkspace.ts +18 -43
  315. package/src/composables/useCommandHistory.ts +5 -1
  316. package/src/composables/useDropdownState.ts +35 -5
  317. package/src/composables/useEventStream.ts +14 -2
  318. package/src/composables/useFileImport.ts +2 -7
  319. package/src/composables/useFocusTrap.ts +91 -0
  320. package/src/composables/useGeneratedAnalysis.ts +22 -10
  321. package/src/composables/useJobsStatusTray.ts +184 -17
  322. package/src/composables/useListReorder.story.vue +143 -0
  323. package/src/composables/useListReorder.ts +242 -0
  324. package/src/composables/useMenuKeyboard.ts +90 -0
  325. package/src/composables/useOptimisticMutation.ts +6 -16
  326. package/src/composables/usePluginClient.ts +47 -4
  327. package/src/composables/usePluginConfig.ts +252 -0
  328. package/src/composables/usePluginWorkspace.ts +208 -0
  329. package/src/composables/useRackEditor.ts +2 -11
  330. package/src/composables/useRequestSyncState.ts +98 -28
  331. package/src/composables/useResourceCrud.ts +6 -16
  332. package/src/composables/useRovingFocus.ts +66 -0
  333. package/src/composables/useScheduleDrag.ts +37 -0
  334. package/src/composables/useWellPainting.ts +10 -30
  335. package/src/composables/useWellPlateAdapter.ts +5 -1
  336. package/src/composables/useWellPlateEditor.ts +1 -11
  337. package/src/composables/useWellPlateValidation.ts +5 -1
  338. package/src/composables/workspaceRecipes.ts +267 -0
  339. package/src/index.ts +16 -0
  340. package/src/permissions.ts +48 -9
  341. package/src/stores/auth.ts +1 -0
  342. package/src/stores/experiment.ts +2 -7
  343. package/src/stores/index.ts +9 -1
  344. package/src/stores/settings.ts +93 -1
  345. package/src/styles/components/audit-trail.css +5 -5
  346. package/src/styles/components/batch-progress-list.css +7 -0
  347. package/src/styles/components/color-slider.css +2 -2
  348. package/src/styles/components/data-state.css +30 -0
  349. package/src/styles/components/dataframe.css +29 -35
  350. package/src/styles/components/experiment-data-viewer.css +4 -4
  351. package/src/styles/components/experiment-timeline.css +3 -30
  352. package/src/styles/components/form-builder.css +5 -5
  353. package/src/styles/components/lcms-sequence-table.css +16 -1
  354. package/src/styles/components/multi-select.css +1 -1
  355. package/src/styles/components/reagent-list.css +38 -31
  356. package/src/styles/components/sample-hierarchy-tree.css +5 -19
  357. package/src/styles/components/sample-selector.css +9 -2
  358. package/src/styles/components/schedule-calendar.css +8 -0
  359. package/src/styles/components/scientific-number.css +1 -1
  360. package/src/styles/components/secret-input.css +60 -0
  361. package/src/styles/components/well-plate.css +8 -0
  362. package/src/styles/index.css +9 -0
  363. package/src/styles/variables.css +29 -0
  364. package/src/templates/builderPresetControls.ts +1 -1
  365. package/src/templates/builderReadUtils.ts +1 -3
  366. package/src/templates/componentPlateHelpers.ts +3 -1
  367. package/src/templates/componentTargetResolvers.ts +1 -3
  368. package/src/templates/controlSchemaTargets.ts +1 -3
  369. package/src/templates/doseResponseAdapters.ts +2 -13
  370. package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
  371. package/src/templates/plateMapBuilder.ts +2 -2
  372. package/src/templates/qpcrPlateBuilder.ts +1 -1
  373. package/src/templates/templateValidators.ts +1 -1
  374. package/src/templates/timeCourseBuilder.ts +2 -2
  375. package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
  376. package/src/types/auth.ts +1 -0
  377. package/src/types/form-builder.ts +1 -0
  378. package/src/utils/color.ts +51 -0
  379. package/src/utils/errors.ts +29 -0
  380. package/src/utils/formModelSync.ts +1 -3
  381. package/src/utils/pluginIcon.ts +1 -3
  382. package/src/utils/pluginSecrets.ts +102 -0
  383. package/src/utils/records.ts +9 -0
  384. package/dist/EmptyState-p90quq8Z.js.map +0 -1
  385. package/dist/ExperimentPopover-tLwJ7XF4.js.map +0 -1
  386. package/dist/ExperimentSelectorModal-DyPAUCLw.js.map +0 -1
  387. package/dist/SettingsModal-BgKY93zh.js.map +0 -1
  388. package/dist/components-DkHddRMl.js.map +0 -1
  389. package/dist/composables/autoGroupConstants.d.ts +0 -1
  390. package/dist/composables/autoGroupGrouping.d.ts +0 -3
  391. package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
  392. package/dist/composables-C_i90sGS.js.map +0 -1
  393. package/dist/experiment-Cq145oEW.js.map +0 -1
  394. package/dist/experiment-utils-CLnzPPq5.js.map +0 -1
  395. package/dist/templates/builderDefaults.d.ts +0 -1
  396. package/dist/templates/plateGeometry.d.ts +0 -4
  397. package/dist/templates-DsP51i-S.js.map +0 -1
  398. package/dist/useApi-J6zFkHmn.js.map +0 -1
  399. package/dist/useControlSchema-BDx2Olha.js.map +0 -1
  400. package/dist/useDropdownState-DSb3BC3N.js.map +0 -1
  401. package/dist/useProtocolTemplates-CS_SQl6U.js.map +0 -1
  402. package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
  403. package/src/composables/autoGroupConstants.ts +0 -4
  404. package/src/composables/autoGroupGrouping.ts +0 -148
  405. package/src/composables/useAutoGroupInputSources.ts +0 -147
  406. package/src/templates/builderDefaults.ts +0 -11
  407. package/src/templates/plateGeometry.ts +0 -62
  408. /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → components/DataStates.test.d.ts} +0 -0
@@ -1,8 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  /** Modal dialog with backdrop, focus trap, Escape-to-close, and configurable size/variant/layout. */
3
- import { computed, ref, watch, nextTick, onUnmounted, type ComponentPublicInstance } from 'vue'
3
+ import { computed, ref, toRef, watch, onUnmounted, type ComponentPublicInstance } from 'vue'
4
4
  import type { ModalLayout, ModalSize, ModalTab, ModalVariant } from '../types'
5
5
  import { useEventListener } from '../composables/useEventListener'
6
+ import { useFocusTrap } from '../composables/useFocusTrap'
6
7
 
7
8
  interface Props {
8
9
  modelValue: boolean
@@ -75,47 +76,16 @@ function isPathIcon(icon: ModalTab['icon']): icon is string | string[] {
75
76
  }
76
77
 
77
78
  const containerRef = ref<HTMLElement | null>(null)
78
- let previouslyFocused: HTMLElement | null = null
79
79
 
80
- const FOCUSABLE_SELECTOR = [
81
- 'a[href]',
82
- 'button:not([disabled])',
83
- 'input:not([disabled])',
84
- 'select:not([disabled])',
85
- 'textarea:not([disabled])',
86
- '[tabindex]:not([tabindex="-1"])',
87
- ].join(', ')
80
+ useFocusTrap({ containerRef, active: toRef(props, 'modelValue') })
88
81
 
89
- function getFocusableElements(): HTMLElement[] {
90
- if (!containerRef.value) return []
91
- return Array.from(containerRef.value.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR))
92
- // Roving tabindex (inactive tabs/rail items) stays out of the Tab cycle.
93
- .filter((el) => el.tabIndex !== -1)
94
- }
82
+ watch(() => props.modelValue, (isOpen) => {
83
+ document.body.style.overflow = isOpen ? 'hidden' : ''
84
+ })
95
85
 
96
- function handleKeydown(event: KeyboardEvent) {
86
+ function handleEscapeKeydown(event: KeyboardEvent) {
97
87
  if (event.key === 'Escape' && props.closeOnEscape && props.modelValue) {
98
88
  close()
99
- return
100
- }
101
-
102
- if (event.key !== 'Tab' || !containerRef.value) return
103
-
104
- const focusable = getFocusableElements()
105
- if (focusable.length === 0) {
106
- event.preventDefault()
107
- return
108
- }
109
-
110
- const first = focusable[0]
111
- const last = focusable[focusable.length - 1]
112
-
113
- if (event.shiftKey && document.activeElement === first) {
114
- event.preventDefault()
115
- last.focus()
116
- } else if (!event.shiftKey && document.activeElement === last) {
117
- event.preventDefault()
118
- first.focus()
119
89
  }
120
90
  }
121
91
 
@@ -132,25 +102,7 @@ function handleOverlayClick(event: MouseEvent) {
132
102
  }
133
103
  }
134
104
 
135
- watch(() => props.modelValue, async (isOpen) => {
136
- if (isOpen) {
137
- previouslyFocused = document.activeElement as HTMLElement | null
138
- document.body.style.overflow = 'hidden'
139
- await nextTick()
140
- const focusable = getFocusableElements()
141
- if (focusable.length > 0) {
142
- focusable[0].focus()
143
- } else {
144
- containerRef.value?.focus()
145
- }
146
- } else {
147
- document.body.style.overflow = ''
148
- previouslyFocused?.focus()
149
- previouslyFocused = null
150
- }
151
- })
152
-
153
- useEventListener(() => document, 'keydown', handleKeydown)
105
+ useEventListener(() => document, 'keydown', handleEscapeKeydown)
154
106
 
155
107
  onUnmounted(() => {
156
108
  document.body.style.overflow = ''
@@ -322,7 +274,3 @@ onUnmounted(() => {
322
274
  </Transition>
323
275
  </Teleport>
324
276
  </template>
325
-
326
- <style>
327
- @import '../styles/components/modal.css';
328
- </style>
@@ -83,7 +83,3 @@ function handleRemove(event: MouseEvent) {
83
83
  </button>
84
84
  </span>
85
85
  </template>
86
-
87
- <style>
88
- @import '../styles/components/pill.css';
89
- </style>
@@ -122,7 +122,3 @@ function handleChange(value: string | number) {
122
122
  </label>
123
123
  </div>
124
124
  </template>
125
-
126
- <style>
127
- @import '../styles/components/radio-group.css';
128
- </style>
@@ -83,7 +83,3 @@ function handleChange(event: Event) {
83
83
  </div>
84
84
  </div>
85
85
  </template>
86
-
87
- <style>
88
- @import '../styles/components/select.css';
89
- </style>
@@ -120,7 +120,3 @@ function handleInput(event: Event) {
120
120
  </span>
121
121
  </div>
122
122
  </template>
123
-
124
- <style>
125
- @import '../styles/components/slider.css';
126
- </style>
@@ -1,8 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  /** Renders a tab bar with underline or pills variant, badges, icons, and disabled tab support. */
3
- import { computed } from 'vue'
3
+ import { computed, type ComponentPublicInstance } from 'vue'
4
4
  import type { TabItem, TabItemInput } from '../types'
5
5
  import { normalizeItemInput } from '../utils/items'
6
+ import { useRovingFocus } from '../composables/useRovingFocus'
6
7
 
7
8
  interface Props {
8
9
  modelValue: string
@@ -32,23 +33,47 @@ function selectTab(tabId: string) {
32
33
  emit('update:modelValue', tabId)
33
34
  }
34
35
  }
36
+
37
+ const tabButtonRefs = new Map<string, HTMLElement>()
38
+
39
+ function setTabButtonRef(id: string, el: Element | ComponentPublicInstance | null) {
40
+ if (el instanceof HTMLElement) {
41
+ tabButtonRefs.set(id, el)
42
+ } else {
43
+ tabButtonRefs.delete(id)
44
+ }
45
+ }
46
+
47
+ // Left/Right only — BaseTabs renders a single horizontal strip with no vertical
48
+ // variant, so there is no Up/Down axis to support.
49
+ const { handleKeydown } = useRovingFocus({
50
+ ids: () => normalizedTabs.value.filter(tab => !tab.disabled).map(tab => tab.id),
51
+ activeId: () => activeTab.value,
52
+ activate: selectTab,
53
+ getElement: (id) => tabButtonRefs.get(id),
54
+ })
35
55
  </script>
36
56
 
37
57
  <template>
38
58
  <div :class="['mint-tabs', `mint-tabs--${variant}`]" role="tablist">
39
59
  <button
40
60
  v-for="tab in normalizedTabs"
61
+ :id="`mint-tab-${tab.id}`"
41
62
  :key="tab.id"
63
+ :ref="(el) => setTabButtonRef(tab.id, el)"
42
64
  type="button"
43
65
  role="tab"
44
66
  :aria-selected="activeTab === tab.id"
45
67
  :aria-disabled="tab.disabled"
68
+ :aria-controls="`mint-tabpanel-${tab.id}`"
69
+ :tabindex="activeTab === tab.id ? 0 : -1"
46
70
  :class="[
47
71
  'mint-tab',
48
72
  activeTab === tab.id ? 'mint-tab--active' : '',
49
73
  tab.disabled ? 'mint-tab--disabled' : '',
50
74
  ]"
51
75
  @click="selectTab(tab.id)"
76
+ @keydown="handleKeydown"
52
77
  >
53
78
  <span class="mint-tab__content">
54
79
  <svg
@@ -76,7 +101,3 @@ function selectTab(tabId: string) {
76
101
  </button>
77
102
  </div>
78
103
  </template>
79
-
80
- <style>
81
- @import '../styles/components/tabs.css';
82
- </style>
@@ -56,7 +56,3 @@ function handleInput(event: Event) {
56
56
  @blur="emit('blur', $event)"
57
57
  />
58
58
  </template>
59
-
60
- <style>
61
- @import '../styles/components/textarea.css';
62
- </style>
@@ -137,7 +137,3 @@ function iconStyle(): Record<string, string> {
137
137
  </span>
138
138
  </div>
139
139
  </template>
140
-
141
- <style>
142
- @import '../styles/components/toggle.css';
143
- </style>
@@ -21,6 +21,8 @@ const allCompleted = [
21
21
 
22
22
  function initState() {
23
23
  return {
24
+ loading: false,
25
+ error: '',
24
26
  items: mixedItems,
25
27
  showSummary: true,
26
28
  title: 'Processing Raw Data Files',
@@ -35,6 +37,8 @@ function initState() {
35
37
  <template #default="{ state }">
36
38
  <div style="padding: 2rem; max-width: 500px;">
37
39
  <BatchProgressList
40
+ :loading="state.loading"
41
+ :error="state.error || null"
38
42
  :items="state.items"
39
43
  :show-summary="state.showSummary"
40
44
  :title="state.title"
@@ -45,6 +49,8 @@ function initState() {
45
49
  </div>
46
50
  </template>
47
51
  <template #controls="{ state }">
52
+ <HstCheckbox v-model="state.loading" title="Loading" />
53
+ <HstText v-model="state.error" title="Error Message" />
48
54
  <HstCheckbox v-model="state.showSummary" title="Show Summary" />
49
55
  <HstText v-model="state.title" title="Title" />
50
56
  <HstCheckbox v-model="state.autoScroll" title="Auto Scroll" />
@@ -88,5 +94,17 @@ function initState() {
88
94
  />
89
95
  </div>
90
96
  </Variant>
97
+
98
+ <Variant title="Loading">
99
+ <div style="padding: 2rem; max-width: 600px;">
100
+ <BatchProgressList :items="[]" loading />
101
+ </div>
102
+ </Variant>
103
+
104
+ <Variant title="Error">
105
+ <div style="padding: 2rem; max-width: 600px;">
106
+ <BatchProgressList :items="[]" error="Could not load the batch." />
107
+ </div>
108
+ </Variant>
91
109
  </Story>
92
110
  </template>
@@ -3,6 +3,7 @@
3
3
  import { computed, ref, watch, nextTick } from 'vue'
4
4
  import type { BatchItem, BatchSummary } from '../types'
5
5
  import { useExpansionSet } from '../composables/useExpansionSet'
6
+ import DataStateInternal from './internal/DataStateInternal.vue'
6
7
 
7
8
  interface Props {
8
9
  items: BatchItem[]
@@ -10,11 +11,23 @@ interface Props {
10
11
  title?: string
11
12
  maxHeight?: string
12
13
  autoScroll?: boolean
14
+ /** Replace the item list with a loading placeholder. */
15
+ loading?: boolean
16
+ /**
17
+ * Error message. When set, the item list is replaced by an error state.
18
+ * `null`/`undefined` renders normally.
19
+ */
20
+ error?: string | null
21
+ /** Empty-state headline shown when there are no batch items. */
22
+ emptyMessage?: string
13
23
  }
14
24
 
15
25
  const props = withDefaults(defineProps<Props>(), {
16
26
  showSummary: true,
17
27
  autoScroll: true,
28
+ loading: false,
29
+ error: null,
30
+ emptyMessage: 'No items in this batch',
18
31
  })
19
32
 
20
33
  const emit = defineEmits<{
@@ -91,7 +104,26 @@ watch(
91
104
  </div>
92
105
  </slot>
93
106
 
107
+ <div v-if="error" class="mint-batch-progress__state">
108
+ <slot name="error" :error="error">
109
+ <DataStateInternal state="error" size="sm" :title="error" />
110
+ </slot>
111
+ </div>
112
+
113
+ <div v-else-if="loading" class="mint-batch-progress__state">
114
+ <slot name="loading">
115
+ <DataStateInternal state="loading" size="sm" loading-label="Loading batch" />
116
+ </slot>
117
+ </div>
118
+
119
+ <div v-else-if="items.length === 0" class="mint-batch-progress__state">
120
+ <slot name="empty">
121
+ <DataStateInternal state="empty" size="sm" :title="emptyMessage" />
122
+ </slot>
123
+ </div>
124
+
94
125
  <div
126
+ v-else
95
127
  ref="listRef"
96
128
  class="mint-batch-progress__list"
97
129
  :style="maxHeight ? { maxHeight, overflowY: 'auto' } : {}"
@@ -175,7 +207,3 @@ watch(
175
207
  </div>
176
208
  </div>
177
209
  </template>
178
-
179
- <style>
180
- @import '../styles/components/batch-progress-list.css';
181
- </style>
@@ -19,6 +19,7 @@ import {
19
19
  type BioTemplateComponentPropsLookupOptions,
20
20
  type TemplateCollectionEnvelope,
21
21
  } from '../templates'
22
+ import { bioTemplateExperimentWorkspaceProps } from '../composables/workspaceRecipes'
22
23
  import AlertBox from './AlertBox.vue'
23
24
  import BaseButton from './BaseButton.vue'
24
25
  import BioTemplateRenderer from './BioTemplateRenderer.vue'
@@ -114,27 +115,15 @@ const statusMessage = computed(() => {
114
115
  return `${props.label} template data saves to experiment design_data.`
115
116
  })
116
117
 
117
- const resolvedLoading = computed(() => {
118
- if (props.status?.loading !== undefined || props.status?.saving !== undefined) {
119
- return Boolean(props.status.loading) || Boolean(props.status.saving)
120
- }
121
- return props.loading
122
- })
123
- const resolvedError = computed(() =>
124
- props.status?.error !== undefined ? props.status.error : props.error,
125
- )
126
- const resolvedHasExperiment = computed(() =>
127
- props.status?.hasExperiment ?? props.hasExperiment,
128
- )
129
- const resolvedCurrentExperimentId = computed(() =>
130
- props.status?.currentExperimentId ?? props.currentExperimentId,
131
- )
132
- const resolvedLastLoadedAt = computed(() =>
133
- props.status?.lastLoadedAt !== undefined ? props.status.lastLoadedAt : props.lastLoadedAt,
134
- )
135
- const resolvedLastSavedAt = computed(() =>
136
- props.status?.lastSavedAt !== undefined ? props.status.lastSavedAt : props.lastSavedAt,
137
- )
118
+ // Thin recipe over bioTemplateExperimentWorkspaceProps(): merges the grouped `status` prop
119
+ // over the individual loading/error/experiment props (see workspaceRecipes.ts).
120
+ const resolvedStatus = computed(() => bioTemplateExperimentWorkspaceProps(props))
121
+ const resolvedLoading = computed(() => resolvedStatus.value.loading)
122
+ const resolvedError = computed(() => resolvedStatus.value.error)
123
+ const resolvedHasExperiment = computed(() => resolvedStatus.value.hasExperiment)
124
+ const resolvedCurrentExperimentId = computed(() => resolvedStatus.value.currentExperimentId)
125
+ const resolvedLastLoadedAt = computed(() => resolvedStatus.value.lastLoadedAt)
126
+ const resolvedLastSavedAt = computed(() => resolvedStatus.value.lastSavedAt)
138
127
 
139
128
  const templateSummaries = computed(() =>
140
129
  Object.values(extractTemplateCollection(props.target)).map(template => ({
@@ -14,6 +14,7 @@ import type {
14
14
  UseBioTemplatePackWorkspaceReturn,
15
15
  } from '../composables/useBioTemplatePackWorkspace'
16
16
  import { useBioTemplatePackWorkspace } from '../composables/useBioTemplatePackWorkspace'
17
+ import { bioTemplatePackWorkspaceProps } from '../composables/workspaceRecipes'
17
18
  import BioTemplateExperimentWorkspaceView from './BioTemplateExperimentWorkspaceView.vue'
18
19
 
19
20
  interface BioTemplatePackWorkspaceSlotProps {
@@ -140,6 +141,15 @@ const resolvedActions = computed<PackWorkspaceActions>(() => ({
140
141
  save: props.actions?.save ?? (() => resolvedWorkspace.value.saveCurrent()),
141
142
  }))
142
143
 
144
+ // Thin recipe over bioTemplatePackWorkspaceProps(): forwards this view's own display props
145
+ // plus the pack-derived target/label/status/actions to BioTemplateExperimentWorkspaceView.
146
+ const experimentWorkspaceRecipe = computed(() => bioTemplatePackWorkspaceProps(props, {
147
+ target: target.value,
148
+ label: label.value,
149
+ status: resolvedStatus.value,
150
+ actions: resolvedActions.value,
151
+ }))
152
+
143
153
  watch(
144
154
  [() => props.pack, () => props.workspaceOptions],
145
155
  () => {
@@ -152,21 +162,7 @@ onScopeDispose(() => generatedWorkspaceScope?.stop())
152
162
  </script>
153
163
 
154
164
  <template>
155
- <BioTemplateExperimentWorkspaceView
156
- :target="target"
157
- kind="collection"
158
- :label="label"
159
- :message="message"
160
- :status="resolvedStatus"
161
- :actions="resolvedActions"
162
- :dense="dense"
163
- :readonly="readonly"
164
- :show-status="showStatus"
165
- :show-template-summary="showTemplateSummary"
166
- :load-label="loadLabel"
167
- :reset-label="resetLabel"
168
- :save-label="saveLabel"
169
- >
165
+ <BioTemplateExperimentWorkspaceView v-bind="experimentWorkspaceRecipe">
170
166
  <template v-if="hasDefaultSlot" #default="slotProps">
171
167
  <slot
172
168
  v-bind="slotProps"
@@ -14,6 +14,7 @@ import type {
14
14
  UseBioTemplatePresetWorkspaceReturn,
15
15
  } from '../composables/useBioTemplatePresetWorkspace'
16
16
  import { useBioTemplatePresetWorkspace } from '../composables/useBioTemplatePresetWorkspace'
17
+ import { bioTemplatePresetWorkspaceProps } from '../composables/workspaceRecipes'
17
18
  import AlertBox from './AlertBox.vue'
18
19
  import AppSidebar from './AppSidebar.vue'
19
20
  import BaseButton from './BaseButton.vue'
@@ -96,19 +97,13 @@ const props = withDefaults(defineProps<Props>(), {
96
97
  resetLabel: 'Reset defaults',
97
98
  })
98
99
 
99
- const externalValues = computed(() => props.modelValue ?? props.values)
100
- const resolvedWorkspaceOptions = computed<UseBioTemplatePresetWorkspaceOptions>(() => {
101
- if (props.initialValues === undefined && externalValues.value === undefined) return props.workspaceOptions
102
-
103
- return {
104
- ...props.workspaceOptions,
105
- initialValues: {
106
- ...(props.workspaceOptions.initialValues ?? {}),
107
- ...(props.initialValues ?? {}),
108
- ...(externalValues.value ?? {}),
109
- },
110
- }
111
- })
100
+ // Thin recipe over bioTemplatePresetWorkspaceProps(): merges workspaceOptions/initialValues/
101
+ // v-model into the options useBioTemplatePresetWorkspace() consumes (see workspaceRecipes.ts).
102
+ const resolvedPresetProps = computed(() => bioTemplatePresetWorkspaceProps(props))
103
+ const externalValues = computed(() => resolvedPresetProps.value.externalValues)
104
+ const resolvedWorkspaceOptions = computed<UseBioTemplatePresetWorkspaceOptions>(() =>
105
+ resolvedPresetProps.value.resolvedWorkspaceOptions
106
+ )
112
107
 
113
108
  let generatedWorkspaceScope: EffectScope | undefined
114
109
 
@@ -75,7 +75,3 @@ function handleClick(item: BreadcrumbItem) {
75
75
  </ol>
76
76
  </nav>
77
77
  </template>
78
-
79
- <style>
80
- @import '../styles/components/breadcrumb.css';
81
- </style>
@@ -361,7 +361,3 @@ function nextMonth() {
361
361
  </div>
362
362
  </div>
363
363
  </template>
364
-
365
- <style>
366
- @import '../styles/components/calendar.css';
367
- </style>
@@ -75,7 +75,7 @@ import ChartContainer from './ChartContainer.vue'
75
75
  <button type="button" style="padding: 0.25rem 0.75rem; font-size: 0.8125rem; border: 1px solid var(--border-color, #e2e8f0); border-radius: 0.375rem; background: var(--bg-card, #fff); color: var(--text-primary, #1e293b); cursor: pointer;">
76
76
  Linear
77
77
  </button>
78
- <button type="button" style="padding: 0.25rem 0.75rem; font-size: 0.8125rem; border: 1px solid var(--mint-primary, #3B82F6); border-radius: 0.375rem; background: var(--mint-primary, #3B82F6); color: #fff; cursor: pointer;">
78
+ <button type="button" style="padding: 0.25rem 0.75rem; font-size: 0.8125rem; border: 1px solid var(--color-primary); border-radius: 0.375rem; background: var(--color-primary); color: #fff; cursor: pointer;">
79
79
  Log
80
80
  </button>
81
81
  </div>
@@ -58,7 +58,3 @@ withDefaults(defineProps<Props>(), {
58
58
  </div>
59
59
  </div>
60
60
  </template>
61
-
62
- <style>
63
- @import '../styles/components/chart-container.css';
64
- </style>
@@ -33,7 +33,3 @@ function getParts(f: string): FormulaPart[] {
33
33
  </template>
34
34
  </component>
35
35
  </template>
36
-
37
- <style>
38
- @import '../styles/components/chemical-formula.css';
39
- </style>
@@ -239,7 +239,3 @@ function handleActionClick(action: SidebarToolSectionAction) {
239
239
  </Transition>
240
240
  </div>
241
241
  </template>
242
-
243
- <style>
244
- @import '../styles/components/collapsible-card.css';
245
- </style>
@@ -158,7 +158,3 @@ function handleInput(event: Event) {
158
158
  </div>
159
159
  </div>
160
160
  </template>
161
-
162
- <style>
163
- @import '../styles/components/color-slider.css';
164
- </style>
@@ -16,6 +16,7 @@ import ReagentList from './ReagentList.vue'
16
16
  import SampleSelector from './SampleSelector.vue'
17
17
  import ScheduleCalendar from './ScheduleCalendar.vue'
18
18
  import WellPlate from './WellPlate.vue'
19
+ import { isRecord } from '../utils/records'
19
20
 
20
21
  export interface ComponentBindingRendererBinding {
21
22
  id?: string
@@ -173,9 +174,6 @@ function normalizeProps(binding: ComponentBindingRendererBinding): Record<string
173
174
  }
174
175
  }
175
176
 
176
- function isRecord(value: unknown): value is Record<string, unknown> {
177
- return typeof value === 'object' && value !== null && !Array.isArray(value)
178
- }
179
177
  </script>
180
178
 
181
179
  <template>
@@ -143,7 +143,3 @@ watch(availableUnits, (units) => {
143
143
  </div>
144
144
  </div>
145
145
  </template>
146
-
147
- <style>
148
- @import '../styles/components/concentration-input.css';
149
- </style>
@@ -94,7 +94,3 @@ const confirmVariant = computed<ButtonVariant>(() => {
94
94
  </template>
95
95
  </BaseModal>
96
96
  </template>
97
-
98
- <style>
99
- @import '../styles/components/confirm-dialog.css';
100
- </style>
@@ -20,7 +20,8 @@ import type {
20
20
  ControlWorkspaceOptions,
21
21
  UseControlWorkspaceReturn,
22
22
  } from '../composables/useControlSchema'
23
- import { mergeControlWorkspaceOptions, resolveControlModel, useControlWorkspace } from '../composables/useControlSchema'
23
+ import { useControlWorkspace } from '../composables/useControlSchema'
24
+ import { controlWorkspaceProps } from '../composables/workspaceRecipes'
24
25
  import AppLayout from './AppLayout.vue'
25
26
  import AppSidebar from './AppSidebar.vue'
26
27
  import AppTopBar from './AppTopBar.vue'
@@ -161,27 +162,15 @@ const props = withDefaults(defineProps<Props>(), {
161
162
  formSize: 'md',
162
163
  })
163
164
 
164
- const externalValues = computed(() => props.modelValue ?? props.values)
165
- const resolvedModel = computed<ControlModelBinding | undefined>(() => {
166
- return resolveControlModel(props.model)
167
- })
168
- const resolvedControls = computed<ControlSchema>(() => props.controls ?? resolvedModel.value?.controls ?? {})
169
- const baseControlOptions = computed<ControlWorkspaceOptions>(() =>
170
- mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, props.controlOptions)
171
- )
172
-
173
- const resolvedControlOptions = computed<ControlWorkspaceOptions>(() => {
174
- if (props.initialValues === undefined && externalValues.value === undefined) return baseControlOptions.value
175
-
176
- return {
177
- ...baseControlOptions.value,
178
- initialValues: {
179
- ...(baseControlOptions.value.initialValues ?? {}),
180
- ...(props.initialValues ?? {}),
181
- ...(externalValues.value ?? {}),
182
- },
183
- }
184
- })
165
+ // Thin recipe over controlWorkspaceProps(): resolves model/controls/controlOptions/v-model
166
+ // into the schema + options pair useControlWorkspace() consumes, shared with
167
+ // DoseDesignWorkspaceView (which forwards its own props here) and
168
+ // BioTemplatePresetWorkspaceView's equivalent options merge.
169
+ const resolvedWorkspaceModel = computed(() => controlWorkspaceProps(props))
170
+ const externalValues = computed(() => resolvedWorkspaceModel.value.externalValues)
171
+ const resolvedModel = computed(() => resolvedWorkspaceModel.value.resolvedModel)
172
+ const resolvedControls = computed(() => resolvedWorkspaceModel.value.resolvedControls)
173
+ const resolvedControlOptions = computed(() => resolvedWorkspaceModel.value.resolvedControlOptions)
185
174
 
186
175
  let generatedWorkspaceScope: EffectScope | undefined
187
176
 
@@ -37,6 +37,7 @@ const pagination = ref<PaginationState>({ page: 1, pageSize: 5, total: data.leng
37
37
  <template #default="{ state }">
38
38
  <div style="padding: 2rem; max-width: 900px; margin: 0 auto;">
39
39
  <DataFrame
40
+ :error="state.error || null"
40
41
  :data="data"
41
42
  :columns="columns"
42
43
  row-key="id"
@@ -55,6 +56,8 @@ const pagination = ref<PaginationState>({ page: 1, pageSize: 5, total: data.leng
55
56
  </template>
56
57
 
57
58
  <template #controls="{ state }">
59
+
60
+ <HstText v-model="state.error" title="Error Message" />
58
61
  <HstSelect
59
62
  v-model="state.size"
60
63
  title="Size"
@@ -144,5 +147,16 @@ const pagination = ref<PaginationState>({ page: 1, pageSize: 5, total: data.leng
144
147
  />
145
148
  </div>
146
149
  </Variant>
150
+
151
+ <Variant title="Error">
152
+ <div style="padding: 2rem; max-width: 900px; margin: 0 auto;">
153
+ <DataFrame
154
+ :data="data"
155
+ :columns="columns"
156
+ row-key="id"
157
+ error="Could not load the result table."
158
+ />
159
+ </div>
160
+ </Variant>
147
161
  </Story>
148
162
  </template>