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

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,4 +1,5 @@
1
1
  import { computed, ref, shallowRef, type ComputedRef, type Ref, type ShallowRef } from 'vue'
2
+ import { readErrorMessage } from '../utils/errors'
2
3
 
3
4
  export type ResourceKey = string | number
4
5
 
@@ -38,7 +39,11 @@ export interface UseResourceCrudReturn<TItem, TCreate, TUpdate, TKey extends Res
38
39
  clearError: () => void
39
40
  }
40
41
 
41
- /** Common list/create/update/delete state wrapper for generated plugin clients. */
42
+ /**
43
+ * Common list/create/update/delete state wrapper for generated plugin clients.
44
+ *
45
+ * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useGeneratedPluginClient()` instead.
46
+ */
42
47
  export function useResourceCrud<
43
48
  TItem,
44
49
  TCreate = Partial<TItem>,
@@ -228,18 +233,3 @@ function resolveKey<TItem, TKey extends ResourceKey>(
228
233
  }
229
234
  return getKey(keyOrItem as TItem)
230
235
  }
231
-
232
- function readErrorMessage(value: unknown): string {
233
- if (value instanceof Error && value.message) return value.message
234
- if (typeof value === 'string' && value.trim()) return value
235
- if (
236
- typeof value === 'object'
237
- && value !== null
238
- && 'message' in value
239
- && typeof (value as { message?: unknown }).message === 'string'
240
- && (value as { message: string }).message.trim()
241
- ) {
242
- return (value as { message: string }).message
243
- }
244
- return 'Request failed.'
245
- }
@@ -0,0 +1,66 @@
1
+ import { nextTick } from 'vue'
2
+
3
+ export interface UseRovingFocusOptions {
4
+ /** Selectable item ids, in DOM order. Already excludes items skipped entirely (e.g. disabled tabs). */
5
+ ids: () => string[]
6
+ /** The id that is currently active/selected. */
7
+ activeId: () => string | undefined
8
+ /** Activates an id (e.g. emit `update:modelValue`). The composable focuses the matching element afterward. */
9
+ activate: (id: string) => void
10
+ /** Returns the focusable element for an id, queried lazily so it reflects the post-activation DOM. */
11
+ getElement: (id: string) => HTMLElement | null | undefined
12
+ /** Arrow-key axis: `'horizontal'` (Left/Right, default) or `'vertical'` (Up/Down). */
13
+ orientation?: 'horizontal' | 'vertical'
14
+ }
15
+
16
+ export interface UseRovingFocusReturn {
17
+ /** Bind to each item's `@keydown`. */
18
+ handleKeydown: (event: KeyboardEvent) => void
19
+ }
20
+
21
+ /**
22
+ * WAI-ARIA roving-tabindex navigation with automatic activation (the tabs pattern):
23
+ * Left/Right (or Up/Down when `orientation` is `'vertical'`) move to the adjacent item
24
+ * and activate it immediately, wrapping past the ends; Home/End jump to the first/last
25
+ * item. Only the active item should carry `tabindex="0"`; give every other item
26
+ * `tabindex="-1"`. Used by BaseTabs.
27
+ */
28
+ export function useRovingFocus(options: UseRovingFocusOptions): UseRovingFocusReturn {
29
+ const orientation = options.orientation ?? 'horizontal'
30
+ const prevKey = orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft'
31
+ const nextKey = orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight'
32
+
33
+ function moveTo(id: string | undefined) {
34
+ if (id === undefined) return
35
+ options.activate(id)
36
+ void nextTick(() => options.getElement(id)?.focus())
37
+ }
38
+
39
+ function handleKeydown(event: KeyboardEvent) {
40
+ const ids = options.ids()
41
+ if (ids.length === 0) return
42
+ const currentIndex = ids.indexOf(options.activeId() ?? '')
43
+
44
+ if (event.key === 'Home') {
45
+ event.preventDefault()
46
+ moveTo(ids[0])
47
+ return
48
+ }
49
+ if (event.key === 'End') {
50
+ event.preventDefault()
51
+ moveTo(ids[ids.length - 1])
52
+ return
53
+ }
54
+ if (event.key === prevKey) {
55
+ event.preventDefault()
56
+ moveTo(ids[currentIndex <= 0 ? ids.length - 1 : currentIndex - 1])
57
+ return
58
+ }
59
+ if (event.key === nextKey) {
60
+ event.preventDefault()
61
+ moveTo(ids[currentIndex === -1 || currentIndex >= ids.length - 1 ? 0 : currentIndex + 1])
62
+ }
63
+ }
64
+
65
+ return { handleKeydown }
66
+ }
@@ -200,6 +200,42 @@ export function useScheduleDrag(options: UseScheduleDragOptions) {
200
200
  cleanup()
201
201
  }
202
202
 
203
+ /**
204
+ * Keyboard alternative to the pointer drag: shifts an event by one slot
205
+ * (`mode: 'move'`) or grows/shrinks its end by one slot (`mode: 'resize'`),
206
+ * staying inside the visible day. Returns whether the nudge was applied.
207
+ */
208
+ function nudgeEvent(
209
+ event: ScheduleEvent,
210
+ direction: -1 | 1,
211
+ mode: 'move' | 'resize' = 'move',
212
+ ): boolean {
213
+ if (options.readonly.value) return false
214
+ if (mode === 'move' && event.draggable === false) return false
215
+ if (mode === 'resize' && event.resizable === false) return false
216
+
217
+ const slotMin = options.slotDuration.value
218
+ const dayStart = options.dayStartHour.value * 60
219
+ const dayEnd = options.dayEndHour.value * 60
220
+ const start = dateToMinutes(new Date(event.start))
221
+ const end = dateToMinutes(new Date(event.end))
222
+
223
+ const nextStart = mode === 'move' ? start + direction * slotMin : start
224
+ const nextEnd = mode === 'move'
225
+ ? end + direction * slotMin
226
+ : Math.max(start + slotMin, end + direction * slotMin)
227
+
228
+ if (nextStart < dayStart || nextEnd > dayEnd || nextEnd <= nextStart) return false
229
+
230
+ const base = new Date(event.start)
231
+ const newStart = minutesToDate(base, nextStart)
232
+ const newEnd = minutesToDate(base, nextEnd)
233
+
234
+ if (mode === 'move') options.onMoveComplete?.(event, newStart, newEnd)
235
+ else options.onResizeComplete?.(event, newStart, newEnd)
236
+ return true
237
+ }
238
+
203
239
  function addListeners() {
204
240
  document.addEventListener('pointermove', onPointerMove)
205
241
  document.addEventListener('pointerup', onPointerUp)
@@ -221,6 +257,7 @@ export function useScheduleDrag(options: UseScheduleDragOptions) {
221
257
  startCreate,
222
258
  startMove,
223
259
  startResize,
260
+ nudgeEvent,
224
261
  }
225
262
  }
226
263
 
@@ -1,5 +1,10 @@
1
1
  import { computed, ref, toValue, type ComputedRef, type Ref } from 'vue'
2
2
  import type { WellPlateFormat } from '../types'
3
+ import {
4
+ PLATE_CONFIGS as PLATE_DIMENSIONS,
5
+ rowIndex as rowLabelToIndex,
6
+ rowLabel as indexToRowLabel,
7
+ } from '../components/WellPlate.geometry'
3
8
 
4
9
  export type WellPlateSource<T> = T | Ref<T> | ComputedRef<T> | (() => T)
5
10
 
@@ -34,19 +39,12 @@ export interface UseWellPaintingReturn<TMode extends string = string, TPayload =
34
39
  cancel: () => void
35
40
  }
36
41
 
37
- const ROW_LABELS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
38
42
 
39
- const PLATE_DIMENSIONS: Record<WellPlateFormat, { rows: number; cols: number }> = {
40
- 6: { rows: 2, cols: 3 },
41
- 12: { rows: 3, cols: 4 },
42
- 24: { rows: 4, cols: 6 },
43
- 48: { rows: 6, cols: 8 },
44
- 54: { rows: 6, cols: 9 },
45
- 96: { rows: 8, cols: 12 },
46
- 384: { rows: 16, cols: 24 },
47
- }
48
-
49
- /** Pointer painting/rectangle selection state for WellPlate-based editors. */
43
+ /**
44
+ * Pointer painting/rectangle selection state for WellPlate-based editors.
45
+ *
46
+ * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useWellPlateEditor()` instead.
47
+ */
50
48
  export function useWellPainting<TMode extends string = string, TPayload = unknown>(
51
49
  options: UseWellPaintingOptions<TMode, TPayload>,
52
50
  ): UseWellPaintingReturn<TMode, TPayload> {
@@ -166,22 +164,4 @@ export function wellIdsInRectangle(
166
164
  return ids
167
165
  }
168
166
 
169
- function rowLabelToIndex(label: string): number {
170
- let result = 0
171
- for (const char of label) {
172
- result = result * 26 + (char.charCodeAt(0) - 64)
173
- }
174
- return result - 1
175
- }
176
167
 
177
- function indexToRowLabel(index: number): string {
178
- if (index < ROW_LABELS.length) return ROW_LABELS[index]
179
- let value = index + 1
180
- let label = ''
181
- while (value > 0) {
182
- value--
183
- label = ROW_LABELS[value % 26] + label
184
- value = Math.floor(value / 26)
185
- }
186
- return label
187
- }
@@ -28,7 +28,11 @@ export interface UseWellPlateAdapterReturn {
28
28
  wells: ComputedRef<Record<string, Partial<Well>>>
29
29
  }
30
30
 
31
- /** Convert domain rows into WellPlate's wells prop without hand-written adapters. */
31
+ /**
32
+ * Convert domain rows into WellPlate's wells prop without hand-written adapters.
33
+ *
34
+ * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useWellPlateEditor()` instead.
35
+ */
32
36
  export function useWellPlateAdapter<TEntry>(
33
37
  options: WellPlateAdapterOptions<TEntry>,
34
38
  ): UseWellPlateAdapterReturn {
@@ -5,18 +5,8 @@ import type {
5
5
  SampleType,
6
6
  WellPlateFormat,
7
7
  } from '../types'
8
+ import { SAMPLE_COLOR_SCALE as DEFAULT_PALETTE } from '../utils/color'
8
9
 
9
- const DEFAULT_PALETTE = [
10
- '#3B82F6', // blue
11
- '#10B981', // green
12
- '#EF4444', // red
13
- '#F59E0B', // amber
14
- '#8B5CF6', // purple
15
- '#F97316', // orange
16
- '#06B6D4', // cyan
17
- '#14B8A6', // teal
18
- '#6B7280', // gray
19
- ]
20
10
 
21
11
  const MAX_HISTORY = 50
22
12
 
@@ -33,7 +33,11 @@ export interface UseWellPlateValidationReturn<TType extends string = string> {
33
33
  errorCount: ComputedRef<number>
34
34
  }
35
35
 
36
- /** Rule-driven validation state for WellPlate layout/design screens. */
36
+ /**
37
+ * Rule-driven validation state for WellPlate layout/design screens.
38
+ *
39
+ * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useWellPlateEditor()` instead.
40
+ */
37
41
  export function useWellPlateValidation<TContext, TType extends string = string>(
38
42
  options: UseWellPlateValidationOptions<TContext, TType>,
39
43
  ): UseWellPlateValidationReturn<TType> {
@@ -0,0 +1,267 @@
1
+ import type { TopBarVariant } from '../types'
2
+ import type { FormEnhancements } from '../types/form-builder'
3
+ import type {
4
+ ControlModel,
5
+ ControlModelBinding,
6
+ ControlSchema,
7
+ ControlWorkspaceOptions,
8
+ UseControlWorkspaceReturn,
9
+ } from './useControlSchema'
10
+ import { mergeControlWorkspaceOptions, resolveControlModel } from './useControlSchema'
11
+
12
+ /**
13
+ * Merges `initialValues`/external `modelValue`/`values` on top of a base
14
+ * `ControlWorkspaceOptions.initialValues`, matching the layering FormBuilder expects: base
15
+ * defaults, then caller-supplied initial values, then live external values win last. Shared by
16
+ * {@link controlWorkspaceProps} and {@link bioTemplatePresetWorkspaceProps} so both "generate a
17
+ * workspace from options, initialValues, and v-model" views merge options identically.
18
+ */
19
+ export function resolveControlOptionsWithExternalValues<TOptions extends ControlWorkspaceOptions>(
20
+ base: TOptions,
21
+ initialValues: Record<string, unknown> | undefined,
22
+ externalValues: Record<string, unknown> | undefined,
23
+ ): TOptions {
24
+ if (initialValues === undefined && externalValues === undefined) return base
25
+
26
+ return {
27
+ ...base,
28
+ initialValues: {
29
+ ...(base.initialValues ?? {}),
30
+ ...(initialValues ?? {}),
31
+ ...(externalValues ?? {}),
32
+ },
33
+ }
34
+ }
35
+
36
+ export interface ControlWorkspaceModelProps {
37
+ model?: ControlModel | ControlModelBinding
38
+ controls?: ControlSchema
39
+ controlOptions?: ControlWorkspaceOptions
40
+ initialValues?: Record<string, unknown>
41
+ modelValue?: Record<string, unknown>
42
+ values?: Record<string, unknown>
43
+ }
44
+
45
+ export interface ResolvedControlWorkspaceModel {
46
+ /** `modelValue` if provided, else `values` — the single external v-model source of truth. */
47
+ externalValues: Record<string, unknown> | undefined
48
+ /** `model` resolved through `resolveControlModel()`, or undefined for a raw `controls` schema. */
49
+ resolvedModel: ControlModelBinding | undefined
50
+ /** `controls` if provided, else the resolved model's controls, else `{}`. */
51
+ resolvedControls: ControlSchema
52
+ /** `controlOptions` merged over the resolved model's own options, with initialValues/external values layered on top. */
53
+ resolvedControlOptions: ControlWorkspaceOptions
54
+ }
55
+
56
+ /**
57
+ * Resolves ControlWorkspaceView's `model`/`controls`/`controlOptions`/`initialValues`/
58
+ * `modelValue`/`values` props into the schema + options pair `useControlWorkspace()` needs.
59
+ * Pure and framework-free so callers wrap each field in their own `computed()`.
60
+ *
61
+ * @example Recommended
62
+ * ```ts
63
+ * const resolved = computed(() => controlWorkspaceProps(props))
64
+ * const resolvedControls = computed(() => resolved.value.resolvedControls)
65
+ * ```
66
+ */
67
+ export function controlWorkspaceProps(props: ControlWorkspaceModelProps): ResolvedControlWorkspaceModel {
68
+ const externalValues = props.modelValue ?? props.values
69
+ const resolvedModel = resolveControlModel(props.model)
70
+ const resolvedControls: ControlSchema = props.controls ?? resolvedModel?.controls ?? {}
71
+ const baseControlOptions = mergeControlWorkspaceOptions(resolvedModel?.controlOptions, props.controlOptions)
72
+ const resolvedControlOptions = resolveControlOptionsWithExternalValues(
73
+ baseControlOptions,
74
+ props.initialValues,
75
+ externalValues,
76
+ )
77
+
78
+ return { externalValues, resolvedModel, resolvedControls, resolvedControlOptions }
79
+ }
80
+
81
+ export interface DoseDesignWorkspacePassthroughProps {
82
+ workspace?: UseControlWorkspaceReturn<ControlSchema>
83
+ controlOptions?: ControlWorkspaceOptions
84
+ initialValues?: Record<string, unknown>
85
+ modelValue?: Record<string, unknown>
86
+ values?: Record<string, unknown>
87
+ title?: string
88
+ subtitle?: string
89
+ topBarVariant?: TopBarVariant
90
+ sidebarWidth?: string
91
+ sidebarVariant?: 'default' | 'analysis'
92
+ responsiveSidebar?: boolean
93
+ sidebarPosition?: 'left' | 'right'
94
+ sidebarTitle?: string
95
+ sidebarSubtitle?: string
96
+ sidebarBadge?: string | number
97
+ floating?: boolean
98
+ dense?: boolean
99
+ showSettings?: boolean
100
+ showFormActions?: boolean
101
+ formEnhancements?: FormEnhancements<Record<string, unknown>>
102
+ formLoading?: boolean
103
+ formDisabled?: boolean
104
+ formReadonly?: boolean
105
+ formSize?: 'sm' | 'md' | 'lg'
106
+ }
107
+
108
+ /**
109
+ * Maps DoseDesignWorkspaceView's props straight through to the identically-named
110
+ * ControlWorkspaceView props it wraps — the ~25-key pass-through list that used to be spelled
111
+ * out attribute-by-attribute in the template. `model` is the caller's already-resolved dose
112
+ * design model, not the raw (possibly absent) `props.model`.
113
+ *
114
+ * @example Recommended
115
+ * ```vue
116
+ * <ControlWorkspaceView v-bind="doseDesignWorkspaceProps(props, resolvedModel)" />
117
+ * ```
118
+ */
119
+ export function doseDesignWorkspaceProps(
120
+ props: DoseDesignWorkspacePassthroughProps,
121
+ model: ControlModel | ControlModelBinding,
122
+ ) {
123
+ return {
124
+ model,
125
+ workspace: props.workspace,
126
+ controlOptions: props.controlOptions,
127
+ initialValues: props.initialValues,
128
+ modelValue: props.modelValue,
129
+ values: props.values,
130
+ title: props.title,
131
+ subtitle: props.subtitle,
132
+ topBarVariant: props.topBarVariant,
133
+ sidebarWidth: props.sidebarWidth,
134
+ sidebarVariant: props.sidebarVariant,
135
+ responsiveSidebar: props.responsiveSidebar,
136
+ sidebarPosition: props.sidebarPosition,
137
+ sidebarTitle: props.sidebarTitle,
138
+ sidebarSubtitle: props.sidebarSubtitle,
139
+ sidebarBadge: props.sidebarBadge,
140
+ floating: props.floating,
141
+ dense: props.dense,
142
+ showSettings: props.showSettings,
143
+ showFormActions: props.showFormActions,
144
+ formEnhancements: props.formEnhancements,
145
+ formLoading: props.formLoading,
146
+ formDisabled: props.formDisabled,
147
+ formReadonly: props.formReadonly,
148
+ formSize: props.formSize,
149
+ }
150
+ }
151
+
152
+ export interface BioTemplateExperimentWorkspaceStatusProps {
153
+ status?: {
154
+ loading?: boolean
155
+ saving?: boolean
156
+ error?: string | null
157
+ hasExperiment?: boolean
158
+ currentExperimentId?: number
159
+ lastLoadedAt?: Date | null
160
+ lastSavedAt?: Date | null
161
+ }
162
+ loading?: boolean
163
+ error?: string | null
164
+ hasExperiment?: boolean
165
+ currentExperimentId?: number
166
+ lastLoadedAt?: Date | null
167
+ lastSavedAt?: Date | null
168
+ }
169
+
170
+ export interface ResolvedBioTemplateExperimentStatus {
171
+ loading: boolean
172
+ error: string | null | undefined
173
+ hasExperiment: boolean
174
+ currentExperimentId: number | undefined
175
+ lastLoadedAt: Date | null | undefined
176
+ lastSavedAt: Date | null | undefined
177
+ }
178
+
179
+ /**
180
+ * Merges BioTemplateExperimentWorkspaceView's grouped `status` prop over its individual
181
+ * `loading`/`error`/`hasExperiment`/... props: `status` wins whenever the corresponding field
182
+ * on it is set, otherwise the flat prop (or its default) is used. Centralizes the six
183
+ * independent fallback rules generated plugin pages rely on when they pass a request/experiment
184
+ * `status` object instead of wiring each field by hand.
185
+ */
186
+ export function bioTemplateExperimentWorkspaceProps(
187
+ props: BioTemplateExperimentWorkspaceStatusProps,
188
+ ): ResolvedBioTemplateExperimentStatus {
189
+ const status = props.status
190
+ return {
191
+ loading: status?.loading !== undefined || status?.saving !== undefined
192
+ ? Boolean(status?.loading) || Boolean(status?.saving)
193
+ : Boolean(props.loading),
194
+ error: status?.error !== undefined ? status.error : props.error,
195
+ hasExperiment: status?.hasExperiment ?? props.hasExperiment ?? false,
196
+ currentExperimentId: status?.currentExperimentId ?? props.currentExperimentId,
197
+ lastLoadedAt: status?.lastLoadedAt !== undefined ? status.lastLoadedAt : props.lastLoadedAt,
198
+ lastSavedAt: status?.lastSavedAt !== undefined ? status.lastSavedAt : props.lastSavedAt,
199
+ }
200
+ }
201
+
202
+ export interface BioTemplatePackWorkspacePassthroughProps {
203
+ message?: string
204
+ dense?: boolean
205
+ readonly?: boolean
206
+ showStatus?: boolean
207
+ showTemplateSummary?: boolean
208
+ loadLabel?: string
209
+ resetLabel?: string
210
+ saveLabel?: string
211
+ }
212
+
213
+ /**
214
+ * Assembles the prop object BioTemplatePackWorkspaceView binds onto the
215
+ * BioTemplateExperimentWorkspaceView it wraps: its own display props passed straight through,
216
+ * plus the pack-derived `target`/`label`/`status`/`actions` computed by the caller.
217
+ */
218
+ export function bioTemplatePackWorkspaceProps<TTarget, TStatus, TActions>(
219
+ props: BioTemplatePackWorkspacePassthroughProps,
220
+ derived: {
221
+ target: TTarget
222
+ label: string
223
+ status: TStatus
224
+ actions: TActions
225
+ },
226
+ ) {
227
+ return {
228
+ target: derived.target,
229
+ kind: 'collection' as const,
230
+ label: derived.label,
231
+ message: props.message,
232
+ status: derived.status,
233
+ actions: derived.actions,
234
+ dense: props.dense,
235
+ readonly: props.readonly,
236
+ showStatus: props.showStatus,
237
+ showTemplateSummary: props.showTemplateSummary,
238
+ loadLabel: props.loadLabel,
239
+ resetLabel: props.resetLabel,
240
+ saveLabel: props.saveLabel,
241
+ }
242
+ }
243
+
244
+ export interface BioTemplatePresetWorkspaceOptionsProps<TOptions extends ControlWorkspaceOptions> {
245
+ workspaceOptions?: TOptions
246
+ initialValues?: Record<string, unknown>
247
+ modelValue?: Record<string, unknown>
248
+ values?: Record<string, unknown>
249
+ }
250
+
251
+ /**
252
+ * Resolves BioTemplatePresetWorkspaceView's `workspaceOptions`/`initialValues`/`modelValue`/
253
+ * `values` props into the single options object `useBioTemplatePresetWorkspace()` needs,
254
+ * reusing the same base/initialValues/external-values layering as {@link controlWorkspaceProps}.
255
+ */
256
+ export function bioTemplatePresetWorkspaceProps<TOptions extends ControlWorkspaceOptions>(
257
+ props: BioTemplatePresetWorkspaceOptionsProps<TOptions>,
258
+ ): { externalValues: Record<string, unknown> | undefined; resolvedWorkspaceOptions: TOptions } {
259
+ const externalValues = props.modelValue ?? props.values
260
+ const resolvedWorkspaceOptions = resolveControlOptionsWithExternalValues(
261
+ (props.workspaceOptions ?? {}) as TOptions,
262
+ props.initialValues,
263
+ externalValues,
264
+ )
265
+
266
+ return { externalValues, resolvedWorkspaceOptions }
267
+ }
package/src/index.ts CHANGED
@@ -41,6 +41,22 @@ export {
41
41
  deriveShade,
42
42
  type Hsl,
43
43
  } from './utils/color'
44
+ export {
45
+ PLUGIN_SECRET_FORMAT_KEY,
46
+ PLUGIN_SECRET_FORMAT_REF,
47
+ PLUGIN_SECRET_REF_KEY,
48
+ clearPluginSecret,
49
+ isPluginSecretLocked,
50
+ isPluginSecretRef,
51
+ keepPluginSecret,
52
+ pluginSecretId,
53
+ pluginSecretLabel,
54
+ pluginSecretState,
55
+ setPluginSecret,
56
+ usesPluginSecretReferences,
57
+ type PluginSecretRef,
58
+ type PluginSecretState,
59
+ } from './utils/pluginSecrets'
44
60
  export {
45
61
  LCMS_DEFAULT_CONTROL_POSITIONS,
46
62
  createLcmsControlWellEditData,
@@ -2,7 +2,6 @@ export const ADMIN_ROLE = 'admin'
2
2
 
3
3
  export const ADMIN_PANEL_PERMISSIONS = [
4
4
  'users.view',
5
- 'users.invite',
6
5
  'users.manage',
7
6
  'platform.configure',
8
7
  'platform.view_logs',
@@ -41,11 +40,36 @@ export interface AccessPolicy {
41
40
  plugin?: string
42
41
  }
43
42
 
43
+ /**
44
+ * An object that carries an access rule.
45
+ *
46
+ * The nested `access` policy is the supported shape. The four flat fields are
47
+ * the pre-1.2 spelling of the same four `AccessPolicy` fields; they still work
48
+ * but are deprecated, and `normalizeAccessPolicy()` lets the nested policy win
49
+ * wherever both are given.
50
+ */
44
51
  export interface AccessControlled {
52
+ /** The access policy. Preferred over the flat fields below. */
45
53
  access?: AccessPolicy
54
+ /**
55
+ * @deprecated Since MINT 1.2; use `access.visibleFor` instead. The flat
56
+ * duplicate is removed in 1.3.
57
+ */
46
58
  visibleFor?: AccessAudienceInput
59
+ /**
60
+ * @deprecated Since MINT 1.2; use `access.requiresAdmin` instead. The flat
61
+ * duplicate is removed in 1.3.
62
+ */
47
63
  requiresAdmin?: boolean
64
+ /**
65
+ * @deprecated Since MINT 1.2; use `access.permissions` instead. The flat
66
+ * duplicate is removed in 1.3.
67
+ */
48
68
  permissions?: readonly string[]
69
+ /**
70
+ * @deprecated Since MINT 1.2; use `access.anyPermissions` instead. The flat
71
+ * duplicate is removed in 1.3.
72
+ */
49
73
  anyPermissions?: readonly string[]
50
74
  }
51
75
 
@@ -105,17 +129,32 @@ export function canAccessPlugin(
105
129
  return Array.isArray(access) && access.includes(pluginName)
106
130
  }
107
131
 
132
+ /**
133
+ * Flatten an access rule — either shape, or a mix of both — into one policy.
134
+ *
135
+ * ## Precedence
136
+ *
137
+ * 1. A defined field on the nested `access` policy wins. It is the supported
138
+ * spelling, so an object that carries both shapes is read as "the nested
139
+ * policy, with the deprecated flat fields as leftovers".
140
+ * 2. Otherwise the flat field on the rule itself is used.
141
+ * 3. A field set to `undefined` on either side counts as unset and never
142
+ * masks the other side.
143
+ *
144
+ * Only `AccessPolicy` fields the flat shape never had (`audience`,
145
+ * `requiresAuth`, `plugin`) can come from the nested policy alone; the four
146
+ * duplicated fields are the ones this ordering exists for.
147
+ */
108
148
  export function normalizeAccessPolicy(rule: AccessControlled | AccessPolicy | undefined): AccessPolicy {
109
149
  if (!rule) return {}
110
- const { access: nested, ...direct } = rule as AccessPolicy & { access?: AccessPolicy }
111
- return {
112
- ...(nested ?? {}),
113
- ...direct,
114
- ...('visibleFor' in rule && rule.visibleFor !== undefined ? { visibleFor: rule.visibleFor } : {}),
115
- ...('requiresAdmin' in rule && rule.requiresAdmin !== undefined ? { requiresAdmin: rule.requiresAdmin } : {}),
116
- ...('permissions' in rule && rule.permissions !== undefined ? { permissions: rule.permissions } : {}),
117
- ...('anyPermissions' in rule && rule.anyPermissions !== undefined ? { anyPermissions: rule.anyPermissions } : {}),
150
+ const { access: nested, ...flat } = rule as AccessPolicy & { access?: AccessPolicy }
151
+ const policy = { ...flat } as Record<string, unknown>
152
+
153
+ for (const [field, value] of Object.entries(nested ?? {})) {
154
+ if (value !== undefined) policy[field] = value
118
155
  }
156
+
157
+ return policy as AccessPolicy
119
158
  }
120
159
 
121
160
  export function canAccessByPolicy(
@@ -58,6 +58,7 @@ export const useAuthStore = defineStore('mint-auth', () => {
58
58
  passkeyEnabled: false,
59
59
  passkeyRegistered: false,
60
60
  registrationEnabled: false,
61
+ databaseMode: 'none',
61
62
  experimentVisibilityMode: 'open',
62
63
  })
63
64
  const isInitialized = ref(false)
@@ -1,6 +1,7 @@
1
1
  import { defineStore } from 'pinia'
2
2
  import { ref } from 'vue'
3
3
  import { useApi } from '../composables/useApi'
4
+ import { readErrorMessage } from '../utils/errors'
4
5
  import type { ExperimentSummary, PlatformContext } from '../types'
5
6
 
6
7
  function getPlatformApiUrl(): string | undefined {
@@ -9,12 +10,6 @@ function getPlatformApiUrl(): string | undefined {
9
10
  ?.platformApiUrl
10
11
  }
11
12
 
12
- function readErrorMessage(value: unknown): string {
13
- if (value instanceof Error && value.message) return value.message
14
- if (typeof value === 'string' && value.trim()) return value
15
- return 'Failed to load experiment'
16
- }
17
-
18
13
  /**
19
14
  * The single source of truth for the experiment a plugin is currently working on.
20
15
  *
@@ -89,7 +84,7 @@ export const useExperimentStore = defineStore('mint-experiment', () => {
89
84
  } catch (err) {
90
85
  if (token !== selectionToken) return null
91
86
  current.value = null
92
- error.value = readErrorMessage(err)
87
+ error.value = readErrorMessage(err, 'Failed to load experiment')
93
88
  return null
94
89
  } finally {
95
90
  // Only the newest request owns the loading flag; otherwise a superseded