@morscherlab/mint-sdk 1.1.25 → 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 (403) hide show
  1. package/README.md +44 -12
  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-B6P2msT4.js → ExperimentSelectorModal-BeEOomw_.js} +5 -5
  5. package/dist/ExperimentSelectorModal-BeEOomw_.js.map +1 -0
  6. package/dist/{SettingsModal-BW3Ar-uy.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/useEventStream.test.d.ts +1 -0
  15. package/dist/__tests__/composables/useListReorder.test.d.ts +1 -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/BatchProgressList.vue.d.ts +17 -0
  23. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +1 -1
  24. package/dist/components/DataFrame.vue.d.ts +14 -2
  25. package/dist/components/DatePicker.vue.d.ts +1 -1
  26. package/dist/components/DateTimePicker.vue.d.ts +2 -0
  27. package/dist/components/DropdownButton.vue.d.ts +2 -0
  28. package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
  29. package/dist/components/ExperimentPopover.vue.d.ts +1 -0
  30. package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
  31. package/dist/components/FitPanel.vue.d.ts +1 -1
  32. package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
  33. package/dist/components/PluginWorkspaceView.props.d.ts +29 -1
  34. package/dist/components/PluginWorkspaceView.vue.d.ts +5 -5
  35. package/dist/components/ProgressBar.vue.d.ts +1 -1
  36. package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
  37. package/dist/components/ReagentList.vue.d.ts +29 -1
  38. package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
  39. package/dist/components/SampleSelector.drag.d.ts +13 -0
  40. package/dist/components/SampleSelector.tree.d.ts +2 -0
  41. package/dist/components/SampleSelector.vue.d.ts +34 -1
  42. package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
  43. package/dist/components/SecretInput.vue.d.ts +28 -0
  44. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -1
  45. package/dist/components/TimePicker.vue.d.ts +1 -0
  46. package/dist/components/WellPlate.geometry.d.ts +15 -0
  47. package/dist/components/WellPlate.interaction.d.ts +13 -0
  48. package/dist/components/WellPlate.vue.d.ts +29 -0
  49. package/dist/components/index.d.ts +9 -0
  50. package/dist/components/index.js +8 -8
  51. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
  52. package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
  53. package/dist/components/internal/WellEditPopupInternal.vue.d.ts +3 -1
  54. package/dist/components/internal/WorkspaceControlsInternal.vue.d.ts +23 -0
  55. package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +70 -0
  56. package/dist/components/internal/WorkspaceSidebarInternal.vue.d.ts +43 -0
  57. package/dist/{components-DQt0tcpY.js → components-CgAUzF8F.js} +2491 -2235
  58. package/dist/components-CgAUzF8F.js.map +1 -0
  59. package/dist/composables/controlSchemaTypes.d.ts +34 -0
  60. package/dist/composables/flattenWorkspaceBindings.d.ts +61 -0
  61. package/dist/composables/index.d.ts +8 -2
  62. package/dist/composables/index.js +10 -10
  63. package/dist/composables/pluginWorkspaceModel.d.ts +164 -0
  64. package/dist/composables/useAsync.d.ts +5 -1
  65. package/dist/composables/useBioTemplateWorkspace.d.ts +4 -20
  66. package/dist/composables/useCommandHistory.d.ts +5 -1
  67. package/dist/composables/useDropdownState.d.ts +18 -2
  68. package/dist/composables/useEventStream.d.ts +52 -0
  69. package/dist/composables/useFocusTrap.d.ts +21 -0
  70. package/dist/composables/useJobsStatusTray.d.ts +1 -1
  71. package/dist/composables/useListReorder.d.ts +90 -0
  72. package/dist/composables/useMenuKeyboard.d.ts +29 -0
  73. package/dist/composables/useOptimisticMutation.d.ts +5 -1
  74. package/dist/composables/usePluginClient.d.ts +4 -17
  75. package/dist/composables/usePluginConfig.d.ts +3 -1
  76. package/dist/composables/usePluginWorkspace.d.ts +51 -0
  77. package/dist/composables/useRequestSyncState.d.ts +42 -2
  78. package/dist/composables/useResourceCrud.d.ts +5 -1
  79. package/dist/composables/useRovingFocus.d.ts +24 -0
  80. package/dist/composables/useScheduleDrag.d.ts +1 -0
  81. package/dist/composables/useWellPainting.d.ts +5 -1
  82. package/dist/composables/useWellPlateAdapter.d.ts +5 -1
  83. package/dist/composables/useWellPlateValidation.d.ts +5 -1
  84. package/dist/composables/workspaceRecipes.d.ts +188 -0
  85. package/dist/{composables-CkXDe7nm.js → composables-B_pia3hO.js} +105 -254
  86. package/dist/composables-B_pia3hO.js.map +1 -0
  87. package/dist/{useApi-CDBq6z23.js → errors-_W0-LbA6.js} +102 -3
  88. package/dist/errors-_W0-LbA6.js.map +1 -0
  89. package/dist/{experiment-Y9Iz7KYi.js → experiment-Cwl9AYxw.js} +3 -8
  90. package/dist/experiment-Cwl9AYxw.js.map +1 -0
  91. package/dist/{experiment-utils-CLnzPPq5.js → experiment-utils-DV3DrvE_.js} +70 -51
  92. package/dist/experiment-utils-DV3DrvE_.js.map +1 -0
  93. package/dist/index.d.ts +1 -0
  94. package/dist/index.js +15 -15
  95. package/dist/install.js +2 -7
  96. package/dist/install.js.map +1 -1
  97. package/dist/permissions.d.ts +42 -1
  98. package/dist/permissions.js +20 -10
  99. package/dist/permissions.js.map +1 -1
  100. package/dist/stores/index.d.ts +1 -1
  101. package/dist/stores/index.js +3 -3
  102. package/dist/stores/settings.d.ts +31 -1
  103. package/dist/styles.css +11247 -29501
  104. package/dist/templates/builderReadUtils.d.ts +1 -1
  105. package/dist/templates/index.js +2 -4
  106. package/dist/{templates-CovvRZ-9.js → templates-Qq113pyZ.js} +303 -106
  107. package/dist/templates-Qq113pyZ.js.map +1 -0
  108. package/dist/types/form-builder.d.ts +1 -1
  109. package/dist/{useControlSchema-BhoJzWzx.js → useControlSchema-aMZlb4Sc.js} +684 -1216
  110. package/dist/useControlSchema-aMZlb4Sc.js.map +1 -0
  111. package/dist/{useDropdownState-DSb3BC3N.js → useDropdownState-DitCtrTT.js} +22 -6
  112. package/dist/useDropdownState-DitCtrTT.js.map +1 -0
  113. package/dist/{useExperimentSelector-D0pjj9WH.js → useExperimentSelector-I8HC8hUu.js} +4 -4
  114. package/dist/{useExperimentSelector-D0pjj9WH.js.map → useExperimentSelector-I8HC8hUu.js.map} +1 -1
  115. package/dist/{useFormBuilder-DiEcDis2.js → useFormBuilder-TCxNnqeb.js} +2 -2
  116. package/dist/{useFormBuilder-DiEcDis2.js.map → useFormBuilder-TCxNnqeb.js.map} +1 -1
  117. package/dist/{useProtocolTemplates-DHwSveE6.js → useProtocolTemplates-BmX_iVBR.js} +660 -197
  118. package/dist/useProtocolTemplates-BmX_iVBR.js.map +1 -0
  119. package/dist/utils/color.d.ts +13 -0
  120. package/dist/utils/errors.d.ts +9 -0
  121. package/dist/utils/pluginSecrets.d.ts +53 -0
  122. package/dist/utils/records.d.ts +4 -0
  123. package/package.json +1 -1
  124. package/src/__tests__/components/ActionMenu.test.ts +94 -0
  125. package/src/__tests__/components/AppAvatarMenu.test.ts +123 -0
  126. package/src/__tests__/components/BaseTabs.test.ts +67 -0
  127. package/src/__tests__/components/DataFrame.test.ts +183 -11
  128. package/src/__tests__/components/DataStates.test.ts +176 -0
  129. package/src/__tests__/components/DatePicker.test.ts +76 -0
  130. package/src/__tests__/components/DateTimePicker.test.ts +36 -0
  131. package/src/__tests__/components/DropdownButton.test.ts +134 -0
  132. package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
  133. package/src/__tests__/components/GeneratedPluginView.test.ts +0 -5
  134. package/src/__tests__/components/GroupAssigner.test.ts +53 -0
  135. package/src/__tests__/components/JobsStatusTray.test.ts +20 -18
  136. package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
  137. package/src/__tests__/components/PluginWorkspaceView.internal.test.ts +230 -0
  138. package/src/__tests__/components/RackEditor.test.ts +35 -0
  139. package/src/__tests__/components/ReagentList.test.ts +64 -2
  140. package/src/__tests__/components/RetiredStyles.test.ts +31 -0
  141. package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
  142. package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
  143. package/src/__tests__/components/SecretInput.test.ts +87 -0
  144. package/src/__tests__/components/SegmentedControl.test.ts +88 -0
  145. package/src/__tests__/components/TimePicker.test.ts +61 -0
  146. package/src/__tests__/components/WellEditPopupInternal.test.ts +108 -0
  147. package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
  148. package/src/__tests__/composables/useAuth.test.ts +25 -0
  149. package/src/__tests__/composables/useDropdownState.test.ts +58 -1
  150. package/src/__tests__/composables/useEventStream.test.ts +140 -0
  151. package/src/__tests__/composables/useGeneratedAnalysis.test.ts +103 -0
  152. package/src/__tests__/composables/useJobsStatusTray.test.ts +25 -161
  153. package/src/__tests__/composables/useListReorder.test.ts +145 -0
  154. package/src/__tests__/composables/usePluginClient.test.ts +148 -13
  155. package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
  156. package/src/__tests__/docs/frontendDocsCatalog.test.ts +55 -2
  157. package/src/__tests__/stores/settings.test.ts +71 -1
  158. package/src/__tests__/styles/cssTokens.test.ts +131 -0
  159. package/src/__tests__/utils/permissions.test.ts +68 -0
  160. package/src/components/ActionMenu.vue +45 -88
  161. package/src/components/AlertBox.vue +0 -4
  162. package/src/components/AppAvatarMenu.vue +26 -7
  163. package/src/components/AppLayout.vue +0 -4
  164. package/src/components/AppPluginSwitcher.story.vue +87 -0
  165. package/src/components/AppPluginSwitcher.vue +2 -5
  166. package/src/components/AppSidebar.vue +0 -4
  167. package/src/components/AppToastContainer.vue +6 -8
  168. package/src/components/AppTopBar.vue +0 -4
  169. package/src/components/ArtifactSaveDialog.vue +0 -4
  170. package/src/components/ArtifactSelectorModal.vue +0 -4
  171. package/src/components/AuditTrail.story.vue +18 -0
  172. package/src/components/AuditTrail.vue +27 -7
  173. package/src/components/AutoGroupModal.vue +0 -4
  174. package/src/components/Avatar.vue +0 -4
  175. package/src/components/BaseButton.vue +0 -4
  176. package/src/components/BaseCheckbox.vue +0 -4
  177. package/src/components/BaseInput.vue +0 -4
  178. package/src/components/BaseModal.vue +8 -60
  179. package/src/components/BasePill.vue +0 -4
  180. package/src/components/BaseRadioGroup.vue +0 -4
  181. package/src/components/BaseSelect.vue +0 -4
  182. package/src/components/BaseSlider.vue +0 -4
  183. package/src/components/BaseTabs.vue +26 -5
  184. package/src/components/BaseTextarea.vue +0 -4
  185. package/src/components/BaseToggle.vue +0 -4
  186. package/src/components/BatchProgressList.story.vue +18 -0
  187. package/src/components/BatchProgressList.vue +32 -4
  188. package/src/components/BioTemplateExperimentWorkspaceView.vue +10 -21
  189. package/src/components/BioTemplatePackWorkspaceView.vue +11 -15
  190. package/src/components/BioTemplatePresetWorkspaceView.vue +8 -13
  191. package/src/components/Breadcrumb.vue +0 -4
  192. package/src/components/Calendar.vue +0 -4
  193. package/src/components/ChartContainer.story.vue +1 -1
  194. package/src/components/ChartContainer.vue +0 -4
  195. package/src/components/ChemicalFormula.vue +0 -4
  196. package/src/components/CollapsibleCard.vue +0 -4
  197. package/src/components/ColorSlider.vue +0 -4
  198. package/src/components/ComponentBindingRenderer.vue +1 -3
  199. package/src/components/ConcentrationInput.vue +0 -4
  200. package/src/components/ConfirmDialog.vue +0 -4
  201. package/src/components/ControlWorkspaceView.vue +11 -22
  202. package/src/components/DataFrame.story.vue +14 -0
  203. package/src/components/DataFrame.vue +97 -23
  204. package/src/components/DatePicker.vue +73 -27
  205. package/src/components/DateTimePicker.vue +45 -17
  206. package/src/components/Divider.vue +0 -4
  207. package/src/components/DoseCalculator.vue +0 -4
  208. package/src/components/DoseDesignWorkspaceView.vue +6 -25
  209. package/src/components/DropdownButton.vue +24 -6
  210. package/src/components/EmptyState.vue +0 -4
  211. package/src/components/ExperimentCodeBadge.vue +0 -4
  212. package/src/components/ExperimentDataViewer.story.vue +3 -0
  213. package/src/components/ExperimentDataViewer.vue +33 -13
  214. package/src/components/ExperimentPopover.vue +2 -5
  215. package/src/components/ExperimentSelectorModal.vue +0 -4
  216. package/src/components/ExperimentTimeline.story.vue +18 -0
  217. package/src/components/ExperimentTimeline.vue +81 -75
  218. package/src/components/FileUploader.vue +0 -4
  219. package/src/components/FitPanel.vue +0 -4
  220. package/src/components/FormActions.story.vue +96 -0
  221. package/src/components/FormActions.vue +0 -4
  222. package/src/components/FormBuilder.vue +0 -4
  223. package/src/components/FormField.vue +0 -4
  224. package/src/components/FormulaInput.vue +0 -4
  225. package/src/components/GeneratedPathInput.story.vue +68 -0
  226. package/src/components/GeneratedPlotlyResult.story.vue +96 -0
  227. package/src/components/GeneratedPlotlyResult.vue +3 -3
  228. package/src/components/GeneratedPluginView.story.vue +145 -0
  229. package/src/components/GeneratedPluginView.vue +10 -10
  230. package/src/components/GeneratedResultRenderer.story.vue +117 -0
  231. package/src/components/GeneratedResultRenderer.vue +4 -4
  232. package/src/components/GroupAssigner.vue +67 -5
  233. package/src/components/IconButton.vue +0 -4
  234. package/src/components/InstrumentAlertLog.vue +0 -4
  235. package/src/components/InstrumentStateBadge.vue +0 -4
  236. package/src/components/InstrumentStatusCard.vue +0 -4
  237. package/src/components/JobsStatusTray.story.vue +6 -10
  238. package/src/components/JobsStatusTray.vue +0 -4
  239. package/src/components/LcmsSequenceTable.vue +81 -50
  240. package/src/components/LoadingSpinner.vue +0 -4
  241. package/src/components/MobileSupportGate.vue +0 -4
  242. package/src/components/MoleculeInput.vue +0 -4
  243. package/src/components/MultiSelect.vue +0 -4
  244. package/src/components/NumberInput.vue +0 -4
  245. package/src/components/PlateMapEditor.vue +3 -14
  246. package/src/components/PluginIcon.vue +0 -4
  247. package/src/components/PluginWorkspaceView.props.ts +38 -0
  248. package/src/components/PluginWorkspaceView.vue +53 -224
  249. package/src/components/ProgressBar.vue +0 -4
  250. package/src/components/ProtocolStepEditor.vue +2 -4
  251. package/src/components/RackEditor.vue +51 -70
  252. package/src/components/ReagentEditor.vue +0 -4
  253. package/src/components/ReagentList.story.vue +18 -0
  254. package/src/components/ReagentList.vue +127 -82
  255. package/src/components/ResourceCard.vue +0 -4
  256. package/src/components/RuntimeUpdateNotice.story.vue +49 -0
  257. package/src/components/RuntimeUpdateNotice.vue +4 -4
  258. package/src/components/SampleHierarchyTree.story.vue +18 -0
  259. package/src/components/SampleHierarchyTree.vue +32 -9
  260. package/src/components/SampleLegend.vue +2 -8
  261. package/src/components/SampleSelector.drag.ts +51 -0
  262. package/src/components/SampleSelector.story.vue +6 -0
  263. package/src/components/SampleSelector.tree.ts +2 -0
  264. package/src/components/SampleSelector.vue +49 -10
  265. package/src/components/SampleSelectorGroupNode.vue +19 -0
  266. package/src/components/ScheduleCalendar.story.vue +6 -0
  267. package/src/components/ScheduleCalendar.vue +82 -7
  268. package/src/components/ScientificNumber.vue +0 -4
  269. package/src/components/SecretInput.story.vue +79 -0
  270. package/src/components/SecretInput.vue +150 -0
  271. package/src/components/SectionCard.vue +0 -4
  272. package/src/components/SegmentedControl.vue +48 -5
  273. package/src/components/SequenceInput.vue +0 -4
  274. package/src/components/SequenceProgressBar.story.vue +110 -0
  275. package/src/components/SequenceProgressBar.vue +0 -4
  276. package/src/components/SettingsModal.vue +0 -4
  277. package/src/components/Skeleton.vue +0 -4
  278. package/src/components/SmartGroupFieldRecipe.vue +8 -6
  279. package/src/components/SmartGroupManual.vue +0 -4
  280. package/src/components/StatusIndicator.vue +0 -4
  281. package/src/components/StepWizard.vue +0 -4
  282. package/src/components/TagsInput.vue +4 -6
  283. package/src/components/ThemeToggle.vue +0 -4
  284. package/src/components/TimePicker.vue +36 -7
  285. package/src/components/TimeRangeInput.vue +0 -4
  286. package/src/components/Tooltip.story.vue +3 -3
  287. package/src/components/Tooltip.vue +0 -4
  288. package/src/components/UnitInput.vue +0 -4
  289. package/src/components/WellPlate.geometry.ts +60 -1
  290. package/src/components/WellPlate.interaction.ts +44 -0
  291. package/src/components/WellPlate.story.vue +8 -0
  292. package/src/components/WellPlate.vue +53 -7
  293. package/src/components/index.ts +9 -0
  294. package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
  295. package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
  296. package/src/components/internal/DataStateInternal.vue +74 -0
  297. package/src/components/internal/FormSectionRenderer.vue +0 -4
  298. package/src/components/internal/WellEditPopupInternal.vue +20 -5
  299. package/src/components/internal/WorkspaceControlsInternal.vue +20 -0
  300. package/src/components/internal/WorkspaceShellInternal.vue +125 -0
  301. package/src/components/internal/WorkspaceSidebarInternal.vue +82 -0
  302. package/src/composables/controlSchemaTypes.ts +34 -0
  303. package/src/composables/experimentDesignData.ts +1 -3
  304. package/src/composables/flattenWorkspaceBindings.ts +104 -0
  305. package/src/composables/formBuilderRegistry.ts +5 -0
  306. package/src/composables/index.ts +41 -5
  307. package/src/composables/pluginWorkspaceModel.ts +182 -0
  308. package/src/composables/useAsync.ts +5 -1
  309. package/src/composables/useBioTemplatePackWorkspace.ts +15 -9
  310. package/src/composables/useBioTemplatePresetWorkspace.ts +14 -15
  311. package/src/composables/useBioTemplateWorkspace.ts +18 -43
  312. package/src/composables/useCommandHistory.ts +5 -1
  313. package/src/composables/useDropdownState.ts +35 -5
  314. package/src/composables/useEventStream.ts +326 -0
  315. package/src/composables/useFileImport.ts +2 -7
  316. package/src/composables/useFocusTrap.ts +91 -0
  317. package/src/composables/useGeneratedAnalysis.ts +46 -103
  318. package/src/composables/useJobsStatusTray.ts +1 -1
  319. package/src/composables/useListReorder.story.vue +143 -0
  320. package/src/composables/useListReorder.ts +242 -0
  321. package/src/composables/useMenuKeyboard.ts +90 -0
  322. package/src/composables/useOptimisticMutation.ts +6 -16
  323. package/src/composables/usePluginClient.ts +91 -252
  324. package/src/composables/usePluginConfig.ts +3 -1
  325. package/src/composables/usePluginWorkspace.ts +208 -0
  326. package/src/composables/useRackEditor.ts +2 -11
  327. package/src/composables/useRequestSyncState.ts +98 -28
  328. package/src/composables/useResourceCrud.ts +6 -16
  329. package/src/composables/useRovingFocus.ts +66 -0
  330. package/src/composables/useScheduleDrag.ts +37 -0
  331. package/src/composables/useWellPainting.ts +10 -30
  332. package/src/composables/useWellPlateAdapter.ts +5 -1
  333. package/src/composables/useWellPlateEditor.ts +1 -11
  334. package/src/composables/useWellPlateValidation.ts +5 -1
  335. package/src/composables/workspaceRecipes.ts +267 -0
  336. package/src/index.ts +16 -0
  337. package/src/permissions.ts +48 -9
  338. package/src/stores/experiment.ts +2 -7
  339. package/src/stores/index.ts +9 -1
  340. package/src/stores/settings.ts +93 -1
  341. package/src/styles/components/audit-trail.css +5 -5
  342. package/src/styles/components/batch-progress-list.css +7 -0
  343. package/src/styles/components/color-slider.css +2 -2
  344. package/src/styles/components/data-state.css +30 -0
  345. package/src/styles/components/dataframe.css +29 -35
  346. package/src/styles/components/experiment-data-viewer.css +4 -4
  347. package/src/styles/components/experiment-timeline.css +3 -30
  348. package/src/styles/components/form-builder.css +5 -5
  349. package/src/styles/components/lcms-sequence-table.css +16 -1
  350. package/src/styles/components/multi-select.css +1 -1
  351. package/src/styles/components/reagent-list.css +38 -31
  352. package/src/styles/components/sample-hierarchy-tree.css +5 -19
  353. package/src/styles/components/sample-selector.css +9 -2
  354. package/src/styles/components/schedule-calendar.css +8 -0
  355. package/src/styles/components/scientific-number.css +1 -1
  356. package/src/styles/components/secret-input.css +60 -0
  357. package/src/styles/components/well-plate.css +8 -0
  358. package/src/styles/index.css +9 -0
  359. package/src/styles/variables.css +29 -0
  360. package/src/templates/builderPresetControls.ts +1 -1
  361. package/src/templates/builderReadUtils.ts +1 -3
  362. package/src/templates/componentPlateHelpers.ts +3 -1
  363. package/src/templates/componentTargetResolvers.ts +1 -3
  364. package/src/templates/controlSchemaTargets.ts +1 -3
  365. package/src/templates/doseResponseAdapters.ts +2 -13
  366. package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
  367. package/src/templates/plateMapBuilder.ts +2 -2
  368. package/src/templates/qpcrPlateBuilder.ts +1 -1
  369. package/src/templates/templateValidators.ts +1 -1
  370. package/src/templates/timeCourseBuilder.ts +2 -2
  371. package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
  372. package/src/types/form-builder.ts +1 -0
  373. package/src/utils/color.ts +51 -0
  374. package/src/utils/errors.ts +29 -0
  375. package/src/utils/formModelSync.ts +1 -3
  376. package/src/utils/pluginIcon.ts +1 -3
  377. package/src/utils/pluginSecrets.ts +102 -0
  378. package/src/utils/records.ts +9 -0
  379. package/dist/EmptyState-p90quq8Z.js.map +0 -1
  380. package/dist/ExperimentPopover-tLwJ7XF4.js.map +0 -1
  381. package/dist/ExperimentSelectorModal-B6P2msT4.js.map +0 -1
  382. package/dist/SettingsModal-BW3Ar-uy.js.map +0 -1
  383. package/dist/components-DQt0tcpY.js.map +0 -1
  384. package/dist/composables/autoGroupConstants.d.ts +0 -1
  385. package/dist/composables/autoGroupGrouping.d.ts +0 -3
  386. package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
  387. package/dist/composables-CkXDe7nm.js.map +0 -1
  388. package/dist/experiment-Y9Iz7KYi.js.map +0 -1
  389. package/dist/experiment-utils-CLnzPPq5.js.map +0 -1
  390. package/dist/templates/builderDefaults.d.ts +0 -1
  391. package/dist/templates/plateGeometry.d.ts +0 -4
  392. package/dist/templates-CovvRZ-9.js.map +0 -1
  393. package/dist/useApi-CDBq6z23.js.map +0 -1
  394. package/dist/useControlSchema-BhoJzWzx.js.map +0 -1
  395. package/dist/useDropdownState-DSb3BC3N.js.map +0 -1
  396. package/dist/useProtocolTemplates-DHwSveE6.js.map +0 -1
  397. package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
  398. package/src/composables/autoGroupConstants.ts +0 -4
  399. package/src/composables/autoGroupGrouping.ts +0 -148
  400. package/src/composables/useAutoGroupInputSources.ts +0 -147
  401. package/src/templates/builderDefaults.ts +0 -11
  402. package/src/templates/plateGeometry.ts +0 -62
  403. /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → components/DataStates.test.d.ts} +0 -0
@@ -1,10 +1,114 @@
1
- import { d as resolveExperimentCode } from "./experiment-utils-CLnzPPq5.js";
2
- import { r as useRequestSyncState } from "./EmptyState-p90quq8Z.js";
3
- import { A as useConcentrationUnits, H as parseExperimentId, J as isActiveJobStatus, Q as normalizeJobState, U as resolveCurrentExperimentId, V as getInjectedPlatformContext, u as useControlWorkspace } from "./useControlSchema-BhoJzWzx.js";
4
- import { o as useSettingsStore, r as useApi } from "./useApi-CDBq6z23.js";
5
- import { t as useExperimentStore } from "./experiment-Y9Iz7KYi.js";
6
- import { B as toBioTemplateComponentProps, F as getBioTemplateComponentProps$1, H as toBioTemplateComponentPropsById, Jt as getBioTemplatePresetInfo, L as toBioTemplateComponentBindings, P as getBioTemplateComponentBindings, Qt as getBioTemplatePackInfo, R as toBioTemplateComponentBindingsById, U as toBioTemplateComponentSnippets, V as toBioTemplateComponentPropsByComponent$1, W as toBioTemplateComponentUsage, d as createBioTemplatePresetCollectionFromControls, dn as extractTemplateCollection, i as createBioTemplateControlToolkit, p as createBioTemplatePackCollection, sn as createTemplateCollection, u as createBioTemplatePresetCollection, un as ensureTemplateFromCollection, z as toBioTemplateComponentImports } from "./templates-CovvRZ-9.js";
7
- import { computed, effectScope, getCurrentScope, inject, onMounted, onScopeDispose, onUnmounted, provide, reactive, readonly, ref, shallowRef, toRaw, toValue, unref, watch } from "vue";
1
+ import { d as resolveExperimentCode } from "./experiment-utils-DV3DrvE_.js";
2
+ import { n as useRequestSyncState } from "./Skeleton-DxtwJ5gt.js";
3
+ import { A as useConcentrationUnits, H as parseExperimentId, J as isActiveJobStatus, Q as normalizeJobState, T as getDefaultControlView, U as resolveCurrentExperimentId, V as getInjectedPlatformContext, f as resolveControlModel, g as mergeControlWorkspaceOptions, h as controlValuesToComponentProps, m as controlValuesToComponentBindingsById, p as controlValuesToComponentBindings, r as getControlDefaults, rt as isRecord, u as useControlWorkspace, w as controlsToViewItems } from "./useControlSchema-aMZlb4Sc.js";
4
+ import { d as useSettingsStore, i as useApi, t as readErrorMessage } from "./errors-_W0-LbA6.js";
5
+ import { t as useExperimentStore } from "./experiment-Cwl9AYxw.js";
6
+ import { B as toBioTemplateComponentProps, F as getBioTemplateComponentProps$1, H as toBioTemplateComponentPropsById, Jt as getBioTemplatePresetInfo, L as toBioTemplateComponentBindings, P as getBioTemplateComponentBindings, Qt as getBioTemplatePackInfo, R as toBioTemplateComponentBindingsById, U as toBioTemplateComponentSnippets, V as toBioTemplateComponentPropsByComponent$1, W as toBioTemplateComponentUsage, bn as rowLabel, d as createBioTemplatePresetCollectionFromControls, dn as extractTemplateCollection, i as createBioTemplateControlToolkit, p as createBioTemplatePackCollection, pn as PLATE_CONFIGS, sn as createTemplateCollection, u as createBioTemplatePresetCollection, un as ensureTemplateFromCollection, wn as deriveShade, xn as SAMPLE_COLOR_SCALE, z as toBioTemplateComponentImports } from "./templates-Qq113pyZ.js";
7
+ import { computed, effectScope, getCurrentScope, inject, nextTick, onMounted, onScopeDispose, onUnmounted, provide, reactive, readonly, ref, shallowRef, toRaw, toValue, unref, watch } from "vue";
8
+ //#region src/composables/useRovingFocus.ts
9
+ /**
10
+ * WAI-ARIA roving-tabindex navigation with automatic activation (the tabs pattern):
11
+ * Left/Right (or Up/Down when `orientation` is `'vertical'`) move to the adjacent item
12
+ * and activate it immediately, wrapping past the ends; Home/End jump to the first/last
13
+ * item. Only the active item should carry `tabindex="0"`; give every other item
14
+ * `tabindex="-1"`. Used by BaseTabs.
15
+ */
16
+ function useRovingFocus(options) {
17
+ const orientation = options.orientation ?? "horizontal";
18
+ const prevKey = orientation === "vertical" ? "ArrowUp" : "ArrowLeft";
19
+ const nextKey = orientation === "vertical" ? "ArrowDown" : "ArrowRight";
20
+ function moveTo(id) {
21
+ if (id === void 0) return;
22
+ options.activate(id);
23
+ nextTick(() => options.getElement(id)?.focus());
24
+ }
25
+ function handleKeydown(event) {
26
+ const ids = options.ids();
27
+ if (ids.length === 0) return;
28
+ const currentIndex = ids.indexOf(options.activeId() ?? "");
29
+ if (event.key === "Home") {
30
+ event.preventDefault();
31
+ moveTo(ids[0]);
32
+ return;
33
+ }
34
+ if (event.key === "End") {
35
+ event.preventDefault();
36
+ moveTo(ids[ids.length - 1]);
37
+ return;
38
+ }
39
+ if (event.key === prevKey) {
40
+ event.preventDefault();
41
+ moveTo(ids[currentIndex <= 0 ? ids.length - 1 : currentIndex - 1]);
42
+ return;
43
+ }
44
+ if (event.key === nextKey) {
45
+ event.preventDefault();
46
+ moveTo(ids[currentIndex === -1 || currentIndex >= ids.length - 1 ? 0 : currentIndex + 1]);
47
+ }
48
+ }
49
+ return { handleKeydown };
50
+ }
51
+ //#endregion
52
+ //#region src/composables/useMenuKeyboard.ts
53
+ /**
54
+ * Shared keyboard contract for menu- and listbox-style disclosure panels (the
55
+ * WAI-ARIA menu button pattern). Used by ActionMenu, AppAvatarMenu and DropdownButton,
56
+ * each pairing it with `useDropdownState` for the disclosure state itself.
57
+ */
58
+ function useMenuKeyboard(options) {
59
+ function focusItem(position) {
60
+ nextTick(() => {
61
+ const items = options.items();
62
+ (position === "first" ? items[0] : items[items.length - 1])?.focus();
63
+ });
64
+ }
65
+ function handleTriggerKeydown(event) {
66
+ if (options.isOpen()) return;
67
+ if (event.key === "ArrowDown" || event.key === "Enter" || event.key === " ") {
68
+ event.preventDefault();
69
+ options.open();
70
+ focusItem("first");
71
+ return;
72
+ }
73
+ if (event.key === "ArrowUp") {
74
+ event.preventDefault();
75
+ options.open();
76
+ focusItem("last");
77
+ }
78
+ }
79
+ function handlePanelKeydown(event) {
80
+ const items = options.items();
81
+ const currentIndex = items.indexOf(document.activeElement);
82
+ if (event.key === "Escape") {
83
+ event.preventDefault();
84
+ options.close(true);
85
+ return;
86
+ }
87
+ if (event.key === "Tab") {
88
+ options.close();
89
+ return;
90
+ }
91
+ if (event.key === "Home") {
92
+ event.preventDefault();
93
+ items[0]?.focus();
94
+ return;
95
+ }
96
+ if (event.key === "End") {
97
+ event.preventDefault();
98
+ items[items.length - 1]?.focus();
99
+ return;
100
+ }
101
+ if (event.key !== "ArrowDown" && event.key !== "ArrowUp") return;
102
+ event.preventDefault();
103
+ const direction = event.key === "ArrowDown" ? 1 : -1;
104
+ items[(Math.max(currentIndex, 0) + direction + items.length) % items.length]?.focus();
105
+ }
106
+ return {
107
+ handleTriggerKeydown,
108
+ handlePanelKeydown
109
+ };
110
+ }
111
+ //#endregion
8
112
  //#region src/composables/useSortedItems.ts
9
113
  /** Shared sorting for SDK tables and lists with stable empty-value handling. */
10
114
  function useSortedItems(options) {
@@ -528,6 +632,310 @@ function useMobileSupportGate(options = {}) {
528
632
  };
529
633
  }
530
634
  //#endregion
635
+ //#region src/components/PluginWorkspaceView.controls.ts
636
+ function usePluginWorkspaceControls(options) {
637
+ const resolvedModel = computed(() => resolveControlModel(options.model()));
638
+ const resolvedControls = computed(() => options.controls() ?? resolvedModel.value?.controls);
639
+ const resolvedControlOptions = computed(() => mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, options.controlOptions()));
640
+ const externalControlValues = computed(() => options.modelValue() ?? options.values());
641
+ const internalControlValues = reactive({});
642
+ let syncingControlValues = false;
643
+ const generatedControlDefaults = computed(() => {
644
+ if (!resolvedControls.value) return {};
645
+ return {
646
+ ...getControlDefaults(resolvedControls.value),
647
+ ...resolvedControlOptions.value.initialValues ?? {}
648
+ };
649
+ });
650
+ function replaceControlValues(values) {
651
+ for (const key of Object.keys(internalControlValues)) if (!(key in values)) delete internalControlValues[key];
652
+ Object.assign(internalControlValues, values);
653
+ }
654
+ function emitControlValues() {
655
+ options.emitValues({ ...internalControlValues });
656
+ }
657
+ function syncResolvedControlValues() {
658
+ syncingControlValues = true;
659
+ replaceControlValues({
660
+ ...generatedControlDefaults.value,
661
+ ...externalControlValues.value === void 0 ? internalControlValues : externalControlValues.value
662
+ });
663
+ syncingControlValues = false;
664
+ }
665
+ function handleControlValuesUpdate(values) {
666
+ syncingControlValues = true;
667
+ replaceControlValues({
668
+ ...generatedControlDefaults.value,
669
+ ...values
670
+ });
671
+ syncingControlValues = false;
672
+ emitControlValues();
673
+ }
674
+ const resolvedComponentBindings = computed(() => controlValuesToComponentBindings(internalControlValues, options.componentBindings() ?? resolvedModel.value?.componentBindings));
675
+ const resolvedComponentBindingsById = computed(() => controlValuesToComponentBindingsById(internalControlValues, options.componentBindings() ?? resolvedModel.value?.componentBindings));
676
+ const resolvedComponentProps = computed(() => {
677
+ const mapping = options.componentProps() ?? resolvedModel.value?.componentProps;
678
+ return mapping === void 0 ? {} : controlValuesToComponentProps(internalControlValues, mapping);
679
+ });
680
+ const resolvedComponentPropsById = computed(() => {
681
+ const mappings = options.componentPropsById() ?? resolvedModel.value?.componentPropsById;
682
+ if (mappings === void 0) return {};
683
+ return Object.fromEntries(Object.entries(mappings).map(([id, mapping]) => [id, controlValuesToComponentProps(internalControlValues, mapping)]));
684
+ });
685
+ const generatedPillNav = computed(() => {
686
+ if (!resolvedControls.value) return [];
687
+ return controlsToViewItems(resolvedControls.value, resolvedControlOptions.value);
688
+ });
689
+ const generatedDefaultView = computed(() => {
690
+ if (!resolvedControls.value) return "";
691
+ return getDefaultControlView(resolvedControls.value, resolvedControlOptions.value);
692
+ });
693
+ syncResolvedControlValues();
694
+ watch([generatedControlDefaults, externalControlValues], syncResolvedControlValues, { deep: true });
695
+ watch(internalControlValues, () => {
696
+ if (syncingControlValues) return;
697
+ emitControlValues();
698
+ }, {
699
+ deep: true,
700
+ flush: "sync"
701
+ });
702
+ return {
703
+ resolvedModel,
704
+ resolvedControls,
705
+ resolvedControlOptions,
706
+ generatedPillNav,
707
+ generatedDefaultView,
708
+ internalControlValues,
709
+ resolvedComponentBindings,
710
+ resolvedComponentBindingsById,
711
+ resolvedComponentProps,
712
+ resolvedComponentPropsById,
713
+ handleControlValuesUpdate
714
+ };
715
+ }
716
+ //#endregion
717
+ //#region src/components/PluginWorkspaceView.navigation.ts
718
+ function usePluginWorkspaceNavigation(options) {
719
+ const internalActiveView = ref(options.defaultActiveView());
720
+ const resolvedPillNav = computed(() => {
721
+ if (options.pillNav() !== void 0) return options.pillNav();
722
+ return options.generatedPillNav.value.length > 0 ? [...options.generatedPillNav.value] : void 0;
723
+ });
724
+ const firstConfiguredViewId = computed(() => options.defaultActiveView() ?? firstItemId(options.pillNav()) ?? options.generatedDefaultView.value ?? firstItemId(options.pageSelector()) ?? options.panelIds()[0] ?? "");
725
+ const resolvedActiveView = computed({
726
+ get: () => options.activeView() ?? options.currentPillId() ?? options.currentPageSelectorId() ?? internalActiveView.value ?? firstConfiguredViewId.value,
727
+ set: (value) => {
728
+ internalActiveView.value = value;
729
+ options.emitActiveView(value);
730
+ }
731
+ });
732
+ const resolvedCurrentPillId = computed(() => options.currentPillId() ?? resolvedActiveView.value);
733
+ const resolvedCurrentPageSelectorId = computed(() => options.currentPageSelectorId() ?? resolvedActiveView.value);
734
+ function setActiveView(viewId) {
735
+ resolvedActiveView.value = viewId;
736
+ }
737
+ function handlePageSelectorSelect(page) {
738
+ setActiveView(page.id);
739
+ options.emitPageSelectorSelect(page);
740
+ }
741
+ function handlePillSelect(item) {
742
+ setActiveView(item.id);
743
+ options.emitPillSelect(item);
744
+ }
745
+ return {
746
+ resolvedPillNav,
747
+ firstConfiguredViewId,
748
+ resolvedActiveView,
749
+ resolvedCurrentPillId,
750
+ resolvedCurrentPageSelectorId,
751
+ setActiveView,
752
+ handlePageSelectorSelect,
753
+ handlePillSelect
754
+ };
755
+ }
756
+ function firstItemId(items) {
757
+ const item = items?.[0];
758
+ if (item === void 0) return void 0;
759
+ return typeof item === "string" ? item : item.id;
760
+ }
761
+ //#endregion
762
+ //#region src/components/PluginWorkspaceView.shell.ts
763
+ var topBarForwardedSlots = new Set([
764
+ "icon",
765
+ "logo",
766
+ "page-selector-icon",
767
+ "page-selector-item-icon",
768
+ "nav",
769
+ "center",
770
+ "actions",
771
+ "account-menu-items",
772
+ "account-menu-item-icon",
773
+ "settings-appearance"
774
+ ]);
775
+ var sidebarForwardedSlots = new Set([
776
+ "header",
777
+ "collapsed",
778
+ "collapsed-footer",
779
+ "footer"
780
+ ]);
781
+ function getPluginWorkspaceTopBarSlotNames(slots) {
782
+ return Object.keys(slots).filter((name) => topBarForwardedSlots.has(name) || name.startsWith("settings-tab-"));
783
+ }
784
+ function getPluginWorkspaceSidebarSlotNames(slots) {
785
+ return Object.keys(slots).filter((name) => sidebarForwardedSlots.has(name) || name.startsWith("section-"));
786
+ }
787
+ function hasPluginWorkspaceSidebarSurface(options) {
788
+ if (!options.showSidebar) return false;
789
+ return Object.keys(options.panels).length > 0 || Object.keys(options.forms).length > 0 || options.model !== void 0 || options.controls !== void 0 || options.showSidebarWhenEmpty || options.sidebarContentId !== void 0 || options.sidebarTitle !== void 0 || options.sidebarSubtitle !== void 0 || options.sidebarBadge !== void 0 || options.hasSidebarSlot || options.sidebarSlotCount > 0;
790
+ }
791
+ //#endregion
792
+ //#region src/composables/usePluginWorkspace.ts
793
+ /**
794
+ * Maps PluginWorkspaceView's flat 72-prop surface into the three typed model objects
795
+ * (`shell`, `sidebar`, `controls`) rendered by its internal pieces
796
+ * (WorkspaceShellInternal, WorkspaceSidebarInternal, WorkspaceControlsInternal). Reuses the
797
+ * existing `usePluginWorkspaceControls` / `usePluginWorkspaceNavigation` composables and the
798
+ * PluginWorkspaceView.shell slot-detection helpers, so it changes only how that state is
799
+ * assembled and exposed, not the underlying behavior.
800
+ *
801
+ * @example Recommended
802
+ * ```ts
803
+ * const props = withDefaults(defineProps<PluginWorkspaceViewProps>(), { ... })
804
+ * const emit = defineEmits<PluginWorkspaceViewEmits>()
805
+ * const slots = useSlots()
806
+ * const { shell, sidebar, controls } = usePluginWorkspace({ props, slots, emit })
807
+ * ```
808
+ */
809
+ function usePluginWorkspace(options) {
810
+ const { props, slots, emit } = options;
811
+ const controlsState = usePluginWorkspaceControls({
812
+ model: () => props.model,
813
+ controls: () => props.controls,
814
+ controlOptions: () => props.controlOptions ?? {},
815
+ modelValue: () => props.modelValue,
816
+ values: () => props.values,
817
+ componentBindings: () => props.componentBindings,
818
+ componentProps: () => props.componentProps,
819
+ componentPropsById: () => props.componentPropsById,
820
+ emitValues: (values) => {
821
+ emit("update:modelValue", values);
822
+ emit("update:values", values);
823
+ }
824
+ });
825
+ const navigationState = usePluginWorkspaceNavigation({
826
+ activeView: () => props.activeView,
827
+ defaultActiveView: () => props.defaultActiveView,
828
+ currentPillId: () => props.currentPillId,
829
+ currentPageSelectorId: () => props.currentPageSelectorId,
830
+ pillNav: () => props.pillNav,
831
+ pageSelector: () => props.pageSelector,
832
+ panelIds: () => Object.keys(props.panels ?? {}),
833
+ generatedPillNav: controlsState.generatedPillNav,
834
+ generatedDefaultView: controlsState.generatedDefaultView,
835
+ emitActiveView: (viewId) => emit("update:activeView", viewId),
836
+ emitPageSelectorSelect: (page) => emit("page-selector-select", page),
837
+ emitPillSelect: (item) => emit("pill-select", item)
838
+ });
839
+ const topBarSlotNames = computed(() => getPluginWorkspaceTopBarSlotNames(slots));
840
+ const sidebarSlotNames = computed(() => getPluginWorkspaceSidebarSlotNames(slots));
841
+ const hasSidebarSurface = computed(() => hasPluginWorkspaceSidebarSurface({
842
+ showSidebar: props.showSidebar ?? true,
843
+ panels: props.panels ?? {},
844
+ forms: props.forms ?? {},
845
+ model: props.model,
846
+ controls: props.controls,
847
+ showSidebarWhenEmpty: props.showSidebarWhenEmpty ?? false,
848
+ sidebarContentId: props.sidebarContentId,
849
+ sidebarTitle: props.sidebarTitle,
850
+ sidebarSubtitle: props.sidebarSubtitle,
851
+ sidebarBadge: props.sidebarBadge,
852
+ hasSidebarSlot: Boolean(slots.sidebar),
853
+ sidebarSlotCount: sidebarSlotNames.value.length
854
+ }));
855
+ const controls = computed(() => ({
856
+ activeView: navigationState.resolvedActiveView.value,
857
+ setActiveView: navigationState.setActiveView,
858
+ values: controlsState.internalControlValues,
859
+ componentBindings: controlsState.resolvedComponentBindings.value,
860
+ componentBindingsById: controlsState.resolvedComponentBindingsById.value,
861
+ componentProps: controlsState.resolvedComponentProps.value,
862
+ componentPropsById: controlsState.resolvedComponentPropsById.value
863
+ }));
864
+ return {
865
+ shell: computed(() => ({
866
+ sidebarPosition: props.sidebarPosition ?? "left",
867
+ sidebarWidth: props.sidebarWidth,
868
+ floating: props.floating ?? true,
869
+ responsiveSidebar: props.responsiveSidebar ?? true,
870
+ sidebarToggleLabel: props.sidebarToggleLabel ?? "Open workspace sidebar",
871
+ sidebarCloseLabel: props.sidebarCloseLabel ?? "Close workspace sidebar",
872
+ hasSidebarSurface: hasSidebarSurface.value,
873
+ title: props.title ?? "Workspace",
874
+ subtitle: props.subtitle,
875
+ topBarVariant: props.topBarVariant ?? "card",
876
+ homePath: props.homePath ?? "/",
877
+ showLogo: props.showLogo ?? true,
878
+ pageSelector: props.pageSelector,
879
+ currentPageSelectorId: navigationState.resolvedCurrentPageSelectorId.value,
880
+ pluginSwitcher: props.pluginSwitcher,
881
+ pillNav: navigationState.resolvedPillNav.value,
882
+ currentPillId: navigationState.resolvedCurrentPillId.value,
883
+ showThemeToggle: props.showThemeToggle ?? true,
884
+ showSettings: props.showSettings ?? true,
885
+ settingsConfig: props.settingsConfig,
886
+ showStandaloneLabel: props.showStandaloneLabel ?? false,
887
+ standaloneLabel: props.standaloneLabel ?? "Standalone",
888
+ accountMenu: props.accountMenu,
889
+ showNotifications: props.showNotifications ?? false,
890
+ hasNotificationDot: props.hasNotificationDot ?? false,
891
+ showAdmin: props.showAdmin ?? false,
892
+ adminPath: props.adminPath ?? "/admin",
893
+ userName: props.userName,
894
+ userInitial: props.userInitial,
895
+ userEmail: props.userEmail,
896
+ topBarSlotNames: topBarSlotNames.value,
897
+ controls: controls.value
898
+ })),
899
+ sidebar: computed(() => ({
900
+ title: props.sidebarTitle,
901
+ subtitle: props.sidebarSubtitle,
902
+ badge: props.sidebarBadge,
903
+ variant: props.sidebarVariant ?? "analysis",
904
+ panels: props.panels ?? {},
905
+ activeView: navigationState.resolvedActiveView.value,
906
+ floating: false,
907
+ dense: props.dense ?? true,
908
+ width: props.sidebarWidth,
909
+ side: props.sidebarPosition ?? "left",
910
+ forms: props.forms ?? {},
911
+ contentId: props.sidebarContentId,
912
+ showWhenEmpty: (props.showSidebarWhenEmpty ?? false) || props.sidebarContentId !== void 0,
913
+ model: props.model,
914
+ controlSchema: props.controls,
915
+ controlOptions: props.controlOptions ?? {},
916
+ values: controlsState.internalControlValues,
917
+ formEnhancements: props.formEnhancements,
918
+ showFormActions: props.showFormActions ?? false,
919
+ formLoading: props.formLoading ?? false,
920
+ formDisabled: props.formDisabled ?? false,
921
+ formReadonly: props.formReadonly ?? false,
922
+ formSize: props.formSize ?? "sm",
923
+ collapsible: props.sidebarCollapsible,
924
+ collapsed: props.sidebarCollapsed,
925
+ defaultCollapsed: props.defaultSidebarCollapsed ?? false,
926
+ collapsedWidth: props.sidebarCollapsedWidth ?? "3rem",
927
+ collapseButtonLabel: props.sidebarCollapseButtonLabel ?? "Collapse sidebar",
928
+ expandButtonLabel: props.sidebarExpandButtonLabel ?? "Expand sidebar",
929
+ slotNames: sidebarSlotNames.value
930
+ })),
931
+ controls,
932
+ hasSidebarSurface,
933
+ handleControlValuesUpdate: controlsState.handleControlValuesUpdate,
934
+ handlePageSelectorSelect: navigationState.handlePageSelectorSelect,
935
+ handlePillSelect: navigationState.handlePillSelect
936
+ };
937
+ }
938
+ //#endregion
531
939
  //#region src/composables/useJobsStatusTray.ts
532
940
  /**
533
941
  * Combines independent job runtimes without copying their reactive state.
@@ -823,7 +1231,7 @@ function usePluginJobCenter(options = {}) {
823
1231
  isPending: (job) => pendingJobIds.value.has(job.job_id)
824
1232
  };
825
1233
  }
826
- /** Backward-compatible name for the plugin job-center controller. */
1234
+ /** @deprecated Use `usePluginJobCenter()` for the plugin job-center controller. */
827
1235
  function useJobsStatusTray(options = {}) {
828
1236
  return usePluginJobCenter(options);
829
1237
  }
@@ -1074,18 +1482,153 @@ function useDoseCalculator() {
1074
1482
  };
1075
1483
  }
1076
1484
  //#endregion
1485
+ //#region src/composables/useListReorder.ts
1486
+ /** Inline style for a visually hidden `aria-live` region (no global utility class in the SDK). */
1487
+ var REORDER_ANNOUNCER_STYLE = Object.freeze({
1488
+ position: "absolute",
1489
+ width: "1px",
1490
+ height: "1px",
1491
+ padding: "0",
1492
+ margin: "-1px",
1493
+ overflow: "hidden",
1494
+ clip: "rect(0, 0, 0, 0)",
1495
+ whiteSpace: "nowrap",
1496
+ border: "0"
1497
+ });
1498
+ /**
1499
+ * Screen-reader announcements for drag/keyboard move interactions. Bind
1500
+ * `announcement` to a `role="status" aria-live="polite"` element styled with
1501
+ * `announcerStyle`.
1502
+ */
1503
+ function useReorderAnnouncer() {
1504
+ const announcement = ref("");
1505
+ function announce(message) {
1506
+ if (announcement.value === message) announcement.value = "";
1507
+ nextTick(() => {
1508
+ announcement.value = message;
1509
+ });
1510
+ }
1511
+ return {
1512
+ announcement,
1513
+ announce,
1514
+ announcerStyle: REORDER_ANNOUNCER_STYLE
1515
+ };
1516
+ }
1517
+ /** Pure helper: a copy of `items` with the entry at `from` moved to `to`. */
1518
+ function reorderList(items, from, to) {
1519
+ const next = [...items];
1520
+ const [moved] = next.splice(from, 1);
1521
+ next.splice(to, 0, moved);
1522
+ return next;
1523
+ }
1524
+ /**
1525
+ * Keyboard-accessible list reordering shared by the SDK's drag-to-reorder lists.
1526
+ * It owns the HTML5 drag state, the drop-index maths, and an Alt+Arrow keyboard
1527
+ * alternative that announces every move through a polite live region — so a
1528
+ * reorder never depends on a pointer.
1529
+ */
1530
+ function useListReorder(options) {
1531
+ const draggingId = ref(null);
1532
+ const dragOverId = ref(null);
1533
+ const { announcement, announce, announcerStyle } = useReorderAnnouncer();
1534
+ const noun = options.itemNoun ?? "Item";
1535
+ function isDisabled() {
1536
+ return options.disabled?.() === true;
1537
+ }
1538
+ function idFor(item, index) {
1539
+ return options.getId(item, index);
1540
+ }
1541
+ /** Index within `items()`, resolved by id so filtered/sorted renders still map back. */
1542
+ function indexOf(item, renderIndex) {
1543
+ const id = idFor(item, renderIndex);
1544
+ const found = options.items().findIndex((candidate, index) => idFor(candidate, index) === id);
1545
+ return found === -1 ? renderIndex : found;
1546
+ }
1547
+ function labelFor(index) {
1548
+ const item = options.items()[index];
1549
+ if (item === void 0) return noun;
1550
+ return options.getLabel?.(item, index) ?? idFor(item, index);
1551
+ }
1552
+ function clearDragState() {
1553
+ draggingId.value = null;
1554
+ dragOverId.value = null;
1555
+ }
1556
+ function move(fromIndex, toIndex, source = "keyboard") {
1557
+ if (isDisabled()) return;
1558
+ const items = options.items();
1559
+ if (fromIndex === toIndex || fromIndex < 0 || toIndex < 0 || fromIndex >= items.length || toIndex >= items.length) return;
1560
+ const movedId = idFor(items[fromIndex], fromIndex);
1561
+ const label = labelFor(fromIndex);
1562
+ options.onReorder({
1563
+ fromIndex,
1564
+ toIndex,
1565
+ items: reorderList(items, fromIndex, toIndex),
1566
+ source
1567
+ });
1568
+ announce(`${label} moved to position ${toIndex + 1} of ${items.length}.`);
1569
+ nextTick(() => options.getElement?.(movedId)?.focus());
1570
+ }
1571
+ function onDragStart(event, item, index) {
1572
+ if (isDisabled()) return;
1573
+ const id = idFor(item, index);
1574
+ draggingId.value = id;
1575
+ if (event.dataTransfer) {
1576
+ event.dataTransfer.effectAllowed = "move";
1577
+ event.dataTransfer.setData("text/plain", id);
1578
+ }
1579
+ }
1580
+ function onDragOver(event, item, index) {
1581
+ if (isDisabled() || draggingId.value === null) return;
1582
+ event.preventDefault();
1583
+ if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
1584
+ const id = idFor(item, index);
1585
+ dragOverId.value = id === draggingId.value ? null : id;
1586
+ }
1587
+ function onDragLeave() {
1588
+ dragOverId.value = null;
1589
+ }
1590
+ function onDrop(event, item, index) {
1591
+ if (isDisabled() || draggingId.value === null) {
1592
+ clearDragState();
1593
+ return;
1594
+ }
1595
+ event.preventDefault();
1596
+ const fromIndex = options.items().findIndex((candidate, i) => idFor(candidate, i) === draggingId.value);
1597
+ const toIndex = indexOf(item, index);
1598
+ clearDragState();
1599
+ if (fromIndex === -1) return;
1600
+ move(fromIndex, toIndex, "drag");
1601
+ }
1602
+ function onDragEnd() {
1603
+ clearDragState();
1604
+ }
1605
+ function onKeydown(event, item, index) {
1606
+ if (isDisabled() || !event.altKey) return;
1607
+ const direction = event.key === "ArrowUp" || event.key === "ArrowLeft" ? -1 : event.key === "ArrowDown" || event.key === "ArrowRight" ? 1 : 0;
1608
+ if (direction === 0) return;
1609
+ event.preventDefault();
1610
+ const fromIndex = indexOf(item, index);
1611
+ move(fromIndex, fromIndex + direction, "keyboard");
1612
+ }
1613
+ return {
1614
+ draggingId,
1615
+ dragOverId,
1616
+ isDragging: (id) => draggingId.value === id,
1617
+ isDragOver: (id) => dragOverId.value === id,
1618
+ announcement,
1619
+ announcerStyle,
1620
+ announce,
1621
+ onDragStart,
1622
+ onDragOver,
1623
+ onDragLeave,
1624
+ onDrop,
1625
+ onDragEnd,
1626
+ onKeydown,
1627
+ move
1628
+ };
1629
+ }
1630
+ //#endregion
1077
1631
  //#region src/composables/useWellPlateEditor.ts
1078
- var DEFAULT_PALETTE = [
1079
- "#3B82F6",
1080
- "#10B981",
1081
- "#EF4444",
1082
- "#F59E0B",
1083
- "#8B5CF6",
1084
- "#F97316",
1085
- "#06B6D4",
1086
- "#14B8A6",
1087
- "#6B7280"
1088
- ];
1089
1632
  var MAX_HISTORY = 50;
1090
1633
  function createEmptyPlate(name, format, id) {
1091
1634
  return {
@@ -1169,7 +1712,7 @@ function useWellPlateEditor(initialState, options = {}) {
1169
1712
  const sample = {
1170
1713
  id: generateSampleId(),
1171
1714
  name,
1172
- color: color || DEFAULT_PALETTE[internalState.value.samples.length % DEFAULT_PALETTE.length],
1715
+ color: color || SAMPLE_COLOR_SCALE[internalState.value.samples.length % SAMPLE_COLOR_SCALE.length],
1173
1716
  count: 0
1174
1717
  };
1175
1718
  internalState.value.samples.push(sample);
@@ -1277,7 +1820,7 @@ function useWellPlateEditor(initialState, options = {}) {
1277
1820
  if (sampleId && !sampleMap.has(sampleId)) sampleMap.set(sampleId, {
1278
1821
  id: sampleId,
1279
1822
  name: sampleName || sampleId,
1280
- color: DEFAULT_PALETTE[sampleMap.size % DEFAULT_PALETTE.length],
1823
+ color: SAMPLE_COLOR_SCALE[sampleMap.size % SAMPLE_COLOR_SCALE.length],
1281
1824
  count: 0
1282
1825
  });
1283
1826
  const plate = plateMap.get(plateName);
@@ -2270,9 +2813,6 @@ function splitByTokenLength(classes, tokenized) {
2270
2813
  }
2271
2814
  //#endregion
2272
2815
  //#region src/composables/experimentDesignData.ts
2273
- function isRecord(value) {
2274
- return value !== null && typeof value === "object" && !Array.isArray(value);
2275
- }
2276
2816
  function isPlatformDesignDataResponse(value) {
2277
2817
  return "data" in value && ("experiment_id" in value || "plugin_id" in value || "schema_version" in value || "updated_at" in value);
2278
2818
  }
@@ -2986,7 +3526,7 @@ function useFileImport(options = {}) {
2986
3526
  result.value = parsed;
2987
3527
  return parsed;
2988
3528
  } catch (err) {
2989
- error.value = readErrorMessage(err);
3529
+ error.value = readErrorMessage(err, "Failed to import file.");
2990
3530
  throw err;
2991
3531
  } finally {
2992
3532
  loading.value = false;
@@ -3096,108 +3636,6 @@ function formatBytes(bytes) {
3096
3636
  if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
3097
3637
  return `${Math.round(bytes / (1024 * 1024))} MB`;
3098
3638
  }
3099
- function readErrorMessage(value) {
3100
- if (value instanceof Error && value.message) return value.message;
3101
- if (typeof value === "string" && value.trim()) return value;
3102
- return "Failed to import file.";
3103
- }
3104
- //#endregion
3105
- //#region src/utils/color.ts
3106
- var HEX_RE = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i;
3107
- function clamp(n, min, max) {
3108
- return Math.min(max, Math.max(min, n));
3109
- }
3110
- function hexToHsl(hex) {
3111
- const match = HEX_RE.exec(hex.trim());
3112
- if (!match) return {
3113
- h: 0,
3114
- s: 0,
3115
- l: 50
3116
- };
3117
- let raw = match[1];
3118
- if (raw.length === 3) raw = raw.split("").map((c) => c + c).join("");
3119
- const r = parseInt(raw.slice(0, 2), 16) / 255;
3120
- const g = parseInt(raw.slice(2, 4), 16) / 255;
3121
- const b = parseInt(raw.slice(4, 6), 16) / 255;
3122
- const max = Math.max(r, g, b);
3123
- const min = Math.min(r, g, b);
3124
- const delta = max - min;
3125
- let h = 0;
3126
- if (delta !== 0) if (max === r) h = (g - b) / delta % 6;
3127
- else if (max === g) h = (b - r) / delta + 2;
3128
- else h = (r - g) / delta + 4;
3129
- h = (h * 60 + 360) % 360;
3130
- const l = (max + min) / 2;
3131
- const s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
3132
- return {
3133
- h,
3134
- s: s * 100,
3135
- l: l * 100
3136
- };
3137
- }
3138
- function hslToHex(h, s, l) {
3139
- const sNorm = clamp(s, 0, 100) / 100;
3140
- const lNorm = clamp(l, 0, 100) / 100;
3141
- const hNorm = (h % 360 + 360) % 360;
3142
- const c = (1 - Math.abs(2 * lNorm - 1)) * sNorm;
3143
- const x = c * (1 - Math.abs(hNorm / 60 % 2 - 1));
3144
- const m = lNorm - c / 2;
3145
- let r = 0, g = 0, b = 0;
3146
- if (hNorm < 60) [r, g, b] = [
3147
- c,
3148
- x,
3149
- 0
3150
- ];
3151
- else if (hNorm < 120) [r, g, b] = [
3152
- x,
3153
- c,
3154
- 0
3155
- ];
3156
- else if (hNorm < 180) [r, g, b] = [
3157
- 0,
3158
- c,
3159
- x
3160
- ];
3161
- else if (hNorm < 240) [r, g, b] = [
3162
- 0,
3163
- x,
3164
- c
3165
- ];
3166
- else if (hNorm < 300) [r, g, b] = [
3167
- x,
3168
- 0,
3169
- c
3170
- ];
3171
- else [r, g, b] = [
3172
- c,
3173
- 0,
3174
- x
3175
- ];
3176
- const toHex = (n) => Math.round((n + m) * 255).toString(16).padStart(2, "0");
3177
- return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
3178
- }
3179
- /**
3180
- * Derive a same-hue-family shade of `parentHex` for child at `index` of `total`.
3181
- *
3182
- * Lightness is distributed evenly within [35, 75] so all children remain
3183
- * readable on light/dark backgrounds. Hue and saturation are inherited from
3184
- * the parent. With `total <= 1`, returns the parent unchanged.
3185
- *
3186
- * Children are ordered light → dark by index, so index 0 is the brightest
3187
- * sibling and index `total - 1` is the darkest.
3188
- */
3189
- function deriveShade(parentHex, index, total) {
3190
- if (total <= 1) return parentHex;
3191
- const { h, s, l } = hexToHsl(parentHex);
3192
- const L_MIN = 35;
3193
- const L_MAX = 75;
3194
- const spread = Math.min(L_MAX - L_MIN, 40);
3195
- const center = clamp(l, L_MIN + spread / 2, L_MAX - spread / 2);
3196
- const top = center + spread / 2;
3197
- const bot = center - spread / 2;
3198
- const childL = top - (total === 1 ? .5 : index / (total - 1)) * (top - bot);
3199
- return hslToHex(h, clamp(s, 35, 100), childL);
3200
- }
3201
3639
  //#endregion
3202
3640
  //#region src/utils/sampleGroupPath.ts
3203
3641
  /** Split a group name into normalized hierarchy segments. */
@@ -3657,6 +4095,30 @@ function useScheduleDrag(options) {
3657
4095
  else if ((state.type === "resize-top" || state.type === "resize-bottom") && state.event && options.onResizeComplete) options.onResizeComplete(state.event, g.start, g.end);
3658
4096
  cleanup();
3659
4097
  }
4098
+ /**
4099
+ * Keyboard alternative to the pointer drag: shifts an event by one slot
4100
+ * (`mode: 'move'`) or grows/shrinks its end by one slot (`mode: 'resize'`),
4101
+ * staying inside the visible day. Returns whether the nudge was applied.
4102
+ */
4103
+ function nudgeEvent(event, direction, mode = "move") {
4104
+ if (options.readonly.value) return false;
4105
+ if (mode === "move" && event.draggable === false) return false;
4106
+ if (mode === "resize" && event.resizable === false) return false;
4107
+ const slotMin = options.slotDuration.value;
4108
+ const dayStart = options.dayStartHour.value * 60;
4109
+ const dayEnd = options.dayEndHour.value * 60;
4110
+ const start = dateToMinutes(new Date(event.start));
4111
+ const end = dateToMinutes(new Date(event.end));
4112
+ const nextStart = mode === "move" ? start + direction * slotMin : start;
4113
+ const nextEnd = mode === "move" ? end + direction * slotMin : Math.max(start + slotMin, end + direction * slotMin);
4114
+ if (nextStart < dayStart || nextEnd > dayEnd || nextEnd <= nextStart) return false;
4115
+ const base = new Date(event.start);
4116
+ const newStart = minutesToDate(base, nextStart);
4117
+ const newEnd = minutesToDate(base, nextEnd);
4118
+ if (mode === "move") options.onMoveComplete?.(event, newStart, newEnd);
4119
+ else options.onResizeComplete?.(event, newStart, newEnd);
4120
+ return true;
4121
+ }
3660
4122
  function addListeners() {
3661
4123
  document.addEventListener("pointermove", onPointerMove);
3662
4124
  document.addEventListener("pointerup", onPointerUp);
@@ -3674,7 +4136,8 @@ function useScheduleDrag(options) {
3674
4136
  ghost,
3675
4137
  startCreate,
3676
4138
  startMove,
3677
- startResize
4139
+ startResize,
4140
+ nudgeEvent
3678
4141
  };
3679
4142
  }
3680
4143
  function snapMinutes(minutes, step) {
@@ -4031,6 +4494,57 @@ function useBioTemplateComponents(target) {
4031
4494
  };
4032
4495
  }
4033
4496
  //#endregion
4497
+ //#region src/composables/flattenWorkspaceBindings.ts
4498
+ /**
4499
+ * Pick the shared template-component binding keys off a resolved bio-template workspace
4500
+ * (or its `components` source directly), so composables that build on `useBioTemplateWorkspace`
4501
+ * spread one object instead of re-listing all 9 keys by hand.
4502
+ *
4503
+ * @example Recommended
4504
+ * ```ts
4505
+ * const bindings = { renderer, ...flattenWorkspaceComponentBindings(components) }
4506
+ * ```
4507
+ */
4508
+ function flattenWorkspaceComponentBindings(source) {
4509
+ return {
4510
+ componentBindings: source.componentBindings,
4511
+ componentBindingsById: source.componentBindingsById,
4512
+ componentImports: source.componentImports,
4513
+ componentProps: source.componentProps,
4514
+ componentPropsById: source.componentPropsById,
4515
+ componentPropsByComponent: source.componentPropsByComponent,
4516
+ componentSnippets: source.componentSnippets,
4517
+ componentUsage: source.componentUsage,
4518
+ getComponentProps: source.getComponentProps
4519
+ };
4520
+ }
4521
+ /**
4522
+ * `computed()`-lifted version of {@link flattenWorkspaceComponentBindings} for composables
4523
+ * that hold their resolved workspace behind a `ComputedRef` (e.g. a regenerated workspace
4524
+ * swapped in via `shallowRef`/`effectScope`), so each key stays independently reactive
4525
+ * instead of forcing consumers to unwrap the whole workspace to read one field.
4526
+ * `getComponentProps` stays a plain callable function, matching the un-lifted composables.
4527
+ *
4528
+ * @example Recommended
4529
+ * ```ts
4530
+ * const workspace = computed(() => workspaceRef.value)
4531
+ * const { componentBindings, componentProps, getComponentProps } = liftWorkspaceComponentBindings(workspace)
4532
+ * ```
4533
+ */
4534
+ function liftWorkspaceComponentBindings(workspace) {
4535
+ return {
4536
+ componentBindings: computed(() => workspace.value.componentBindings),
4537
+ componentBindingsById: computed(() => workspace.value.componentBindingsById),
4538
+ componentImports: computed(() => workspace.value.componentImports),
4539
+ componentProps: computed(() => workspace.value.componentProps),
4540
+ componentPropsById: computed(() => workspace.value.componentPropsById),
4541
+ componentPropsByComponent: computed(() => workspace.value.componentPropsByComponent),
4542
+ componentSnippets: computed(() => workspace.value.componentSnippets),
4543
+ componentUsage: computed(() => workspace.value.componentUsage),
4544
+ getComponentProps: (component, options) => workspace.value.getComponentProps(component, options)
4545
+ };
4546
+ }
4547
+ //#endregion
4034
4548
  //#region src/composables/useBioTemplateWorkspace.ts
4035
4549
  /** One-stop wiring for BioTemplateRenderer, FormBuilder, AppSidebar, and template-aware SDK components. */
4036
4550
  function useBioTemplateWorkspace(target, options = {}) {
@@ -4038,21 +4552,25 @@ function useBioTemplateWorkspace(target, options = {}) {
4038
4552
  const workspace = useControlWorkspace(controls.controls, options);
4039
4553
  const components = useBioTemplateComponents(target);
4040
4554
  const renderer = isTemplateObjectTarget(target) ? { target } : null;
4041
- const bindings = {
4042
- renderer,
4043
- form: workspace.bindings.form,
4044
- sidebar: workspace.bindings.sidebar,
4045
- topBar: workspace.bindings.topBar,
4046
- topBarSettings: workspace.bindings.topBarSettings,
4047
- pillNav: workspace.bindings.pillNav,
4555
+ const componentBindings = flattenWorkspaceComponentBindings({
4048
4556
  componentBindings: components.bindings,
4049
4557
  componentBindingsById: components.componentBindingsById,
4558
+ componentImports: components.imports,
4050
4559
  componentProps: components.componentProps,
4051
4560
  componentPropsById: components.componentPropsById,
4052
4561
  componentPropsByComponent: components.componentPropsByComponent,
4053
4562
  componentSnippets: components.snippets,
4054
4563
  componentUsage: components.usage,
4055
4564
  getComponentProps: components.getComponentProps
4565
+ });
4566
+ const bindings = {
4567
+ renderer,
4568
+ form: workspace.bindings.form,
4569
+ sidebar: workspace.bindings.sidebar,
4570
+ topBar: workspace.bindings.topBar,
4571
+ topBarSettings: workspace.bindings.topBarSettings,
4572
+ pillNav: workspace.bindings.pillNav,
4573
+ ...componentBindings
4056
4574
  };
4057
4575
  return {
4058
4576
  target,
@@ -4069,15 +4587,7 @@ function useBioTemplateWorkspace(target, options = {}) {
4069
4587
  topBarSettings: workspace.topBarSettings,
4070
4588
  bindings,
4071
4589
  renderer,
4072
- componentBindings: components.bindings,
4073
- componentBindingsById: components.componentBindingsById,
4074
- componentImports: components.imports,
4075
- componentProps: components.componentProps,
4076
- componentPropsById: components.componentPropsById,
4077
- componentPropsByComponent: components.componentPropsByComponent,
4078
- componentSnippets: components.snippets,
4079
- componentUsage: components.usage,
4080
- getComponentProps: components.getComponentProps
4590
+ ...componentBindings
4081
4591
  };
4082
4592
  }
4083
4593
  function isTemplateObjectTarget(target) {
@@ -4118,14 +4628,7 @@ function useBioTemplatePackWorkspace(packId, options = {}) {
4118
4628
  const pillNav = computed(() => workspace.value.pillNav);
4119
4629
  const topBarSettings = computed(() => workspace.value.topBarSettings);
4120
4630
  const bindings = computed(() => workspace.value.bindings);
4121
- const componentBindings = computed(() => workspace.value.componentBindings);
4122
- const componentBindingsById = computed(() => workspace.value.componentBindingsById);
4123
- const componentImports = computed(() => workspace.value.componentImports);
4124
- const componentProps = computed(() => workspace.value.componentProps);
4125
- const componentPropsById = computed(() => workspace.value.componentPropsById);
4126
- const componentPropsByComponent = computed(() => workspace.value.componentPropsByComponent);
4127
- const componentSnippets = computed(() => workspace.value.componentSnippets);
4128
- const componentUsage = computed(() => workspace.value.componentUsage);
4631
+ const { componentBindings, componentBindingsById, componentImports, componentProps, componentPropsById, componentPropsByComponent, componentSnippets, componentUsage, getComponentProps: getWorkspaceComponentProps } = liftWorkspaceComponentBindings(workspace);
4129
4632
  watch(collection, (value) => {
4130
4633
  workspaceRef.value = createWorkspace(value);
4131
4634
  });
@@ -4168,7 +4671,7 @@ function useBioTemplatePackWorkspace(packId, options = {}) {
4168
4671
  componentPropsByComponent,
4169
4672
  componentSnippets,
4170
4673
  componentUsage,
4171
- getComponentProps: (component, options) => workspace.value.getComponentProps(component, options),
4674
+ getComponentProps: getWorkspaceComponentProps,
4172
4675
  applyCollection,
4173
4676
  resetToDefaultCollection,
4174
4677
  save: templateCollection.save,
@@ -4199,14 +4702,7 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
4199
4702
  const collection = templateCollection.templateCollection;
4200
4703
  const workspace = computed(() => useBioTemplateWorkspace(collection.value, resolvedControlOptions));
4201
4704
  const renderer = computed(() => ({ target: collection.value }));
4202
- const componentBindings = computed(() => workspace.value.componentBindings);
4203
- const componentBindingsById = computed(() => workspace.value.componentBindingsById);
4204
- const componentImports = computed(() => workspace.value.componentImports);
4205
- const componentProps = computed(() => workspace.value.componentProps);
4206
- const componentPropsById = computed(() => workspace.value.componentPropsById);
4207
- const componentPropsByComponent = computed(() => workspace.value.componentPropsByComponent);
4208
- const componentSnippets = computed(() => workspace.value.componentSnippets);
4209
- const componentUsage = computed(() => workspace.value.componentUsage);
4705
+ const { componentBindings, componentBindingsById, componentImports, componentProps, componentPropsById, componentPropsByComponent, componentSnippets, componentUsage, getComponentProps } = liftWorkspaceComponentBindings(workspace);
4210
4706
  const form = reactive({
4211
4707
  ...controls.form,
4212
4708
  modelValue: controlValues.value,
@@ -4239,9 +4735,6 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
4239
4735
  onPillSelect: pillNav.onSelect,
4240
4736
  ...topBarSettings
4241
4737
  }));
4242
- function getComponentProps(component, options) {
4243
- return workspace.value.getComponentProps(component, options);
4244
- }
4245
4738
  const bindings = {
4246
4739
  renderer,
4247
4740
  form,
@@ -4367,36 +4860,6 @@ var SLOT_CYCLE = [
4367
4860
  "B",
4368
4861
  "Y"
4369
4862
  ];
4370
- var PLATE_CONFIGS = {
4371
- 6: {
4372
- rows: 2,
4373
- cols: 3
4374
- },
4375
- 12: {
4376
- rows: 3,
4377
- cols: 4
4378
- },
4379
- 24: {
4380
- rows: 4,
4381
- cols: 6
4382
- },
4383
- 48: {
4384
- rows: 6,
4385
- cols: 8
4386
- },
4387
- 54: {
4388
- rows: 6,
4389
- cols: 9
4390
- },
4391
- 96: {
4392
- rows: 8,
4393
- cols: 12
4394
- },
4395
- 384: {
4396
- rows: 16,
4397
- cols: 24
4398
- }
4399
- };
4400
4863
  var globalIdCounter = 0;
4401
4864
  function generateId() {
4402
4865
  globalIdCounter++;
@@ -4480,7 +4943,7 @@ function useRackEditor(initialRacks, options) {
4480
4943
  if (!config) return;
4481
4944
  let counter = 1;
4482
4945
  for (let row = 0; row < config.rows; row++) for (let col = 0; col < config.cols; col++) {
4483
- const wellId = `${String.fromCharCode(65 + row)}${col + 1}`;
4946
+ const wellId = `${rowLabel(row)}${col + 1}`;
4484
4947
  if (!rack.wells[wellId]?.sampleType) {
4485
4948
  const paddedNum = String(counter).padStart(3, "0");
4486
4949
  rack.wells[wellId] = {
@@ -5144,6 +5607,6 @@ function useProtocolTemplates() {
5144
5607
  };
5145
5608
  }
5146
5609
  //#endregion
5147
- export { useToast as $, useFileImport as A, useDoseCalculator as B, getSampleGroupParentPath as C, detectDelimiter as D, hslToHex as E, extractSampleNamesFromDesignData as F, useMobileSupportGate as G, useJobsStatusTray as H, extractSampleOptionsFromDesignData as I, getInjectedFrontendRevision as J, APP_EXPERIMENT_KEY as K, unwrapExperimentDesignData as L, extractSamplesFromDesignData as M, useAutoGroup as N, parseDelimitedText as O, parseCSV as P, useTheme as Q, DEFAULT_COLORS as R, getSampleGroupMajorPrefix as S, hexToHsl as T, usePluginJobCenter as U, combinePluginJobSources as V, DEFAULT_MOBILE_VIEWPORT_QUERY as W, getPresenceClientId as X, useRuntimeAlignment as Y, usePresenceHeartbeat as Z, useScheduleDrag as _, useReagentSeries as a, useExpansionSet as b, useBioTemplatePresetWorkspace as c, getBioTemplateComponentProps as d, candidateMatchesSearch as et, toBioTemplateComponentPropsByComponent as f, useExperimentSave as g, useTemplateCollection as h, generateDilutionSeries as i, useSortedItems as it, validateImportFile as j, readFileAsText as k, useBioTemplatePackWorkspace as l, useBioTemplateControls as m, DEFAULT_PRESETS as n, useTextSearch as nt, useGroupAssignment as o, useBioTemplateComponents as p, useAppExperiment as q, DEFAULT_UNITS as r, compareSortValues as rt, useRackEditor as s, useProtocolTemplates as t, normalizeSearchQuery as tt, useBioTemplateWorkspace as u, useExperimentSamples as v, deriveShade as w, useSampleGroups as x, useExperimentData as y, useWellPlateEditor as z };
5610
+ export { usePresenceHeartbeat as $, useAutoGroup as A, useReorderAnnouncer as B, getSampleGroupParentPath as C, useFileImport as D, readFileAsText as E, DEFAULT_COLORS as F, usePluginWorkspace as G, combinePluginJobSources as H, useWellPlateEditor as I, APP_EXPERIMENT_KEY as J, DEFAULT_MOBILE_VIEWPORT_QUERY as K, REORDER_ANNOUNCER_STYLE as L, extractSampleNamesFromDesignData as M, extractSampleOptionsFromDesignData as N, validateImportFile as O, unwrapExperimentDesignData as P, getPresenceClientId as Q, reorderList as R, getSampleGroupMajorPrefix as S, parseDelimitedText as T, useJobsStatusTray as U, useDoseCalculator as V, usePluginJobCenter as W, getInjectedFrontendRevision as X, useAppExperiment as Y, useRuntimeAlignment as Z, useScheduleDrag as _, useReagentSeries as a, compareSortValues as at, useExpansionSet as b, useBioTemplatePresetWorkspace as c, useRovingFocus as ct, getBioTemplateComponentProps as d, useTheme as et, toBioTemplateComponentPropsByComponent as f, useExperimentSave as g, useTemplateCollection as h, generateDilutionSeries as i, useTextSearch as it, parseCSV as j, extractSamplesFromDesignData as k, useBioTemplatePackWorkspace as l, useBioTemplateControls as m, DEFAULT_PRESETS as n, candidateMatchesSearch as nt, useGroupAssignment as o, useSortedItems as ot, useBioTemplateComponents as p, useMobileSupportGate as q, DEFAULT_UNITS as r, normalizeSearchQuery as rt, useRackEditor as s, useMenuKeyboard as st, useProtocolTemplates as t, useToast as tt, useBioTemplateWorkspace as u, useExperimentSamples as v, detectDelimiter as w, useSampleGroups as x, useExperimentData as y, useListReorder as z };
5148
5611
 
5149
- //# sourceMappingURL=useProtocolTemplates-DHwSveE6.js.map
5612
+ //# sourceMappingURL=useProtocolTemplates-BmX_iVBR.js.map