@morscherlab/mint-sdk 1.0.0-beta.2 → 1.0.0-beta.3

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 (399) hide show
  1. package/README.md +218 -6
  2. package/dist/__tests__/components/ActionItem.test.d.ts +1 -0
  3. package/dist/__tests__/components/AppAvatarMenu.test.d.ts +1 -0
  4. package/dist/__tests__/components/AppPageSelector.test.d.ts +1 -0
  5. package/dist/__tests__/components/AppPillNav.test.d.ts +1 -0
  6. package/dist/__tests__/components/AppPluginSwitcher.test.d.ts +1 -0
  7. package/dist/__tests__/components/AppToastContainer.test.d.ts +1 -0
  8. package/dist/__tests__/components/BaseRadioGroup.test.d.ts +1 -0
  9. package/dist/__tests__/components/BaseSelect.test.d.ts +1 -0
  10. package/dist/__tests__/components/BaseTabs.test.d.ts +1 -0
  11. package/dist/__tests__/components/BatchProgressList.test.d.ts +1 -0
  12. package/dist/__tests__/components/BioTemplateExperimentWorkspaceView.test.d.ts +1 -0
  13. package/dist/__tests__/components/BioTemplatePackWorkspaceView.test.d.ts +1 -0
  14. package/dist/__tests__/components/BioTemplatePresetWorkspaceView.test.d.ts +1 -0
  15. package/dist/__tests__/components/BioTemplateRenderer.test.d.ts +1 -0
  16. package/dist/__tests__/components/Breadcrumb.test.d.ts +1 -0
  17. package/dist/__tests__/components/CalendarGridPanel.test.d.ts +1 -0
  18. package/dist/__tests__/components/ConcentrationInput.test.d.ts +1 -0
  19. package/dist/__tests__/components/ControlWorkspaceView.test.d.ts +1 -0
  20. package/dist/__tests__/components/DatePicker.test.d.ts +1 -0
  21. package/dist/__tests__/components/DateTimePicker.test.d.ts +1 -0
  22. package/dist/__tests__/components/EmptyState.test.d.ts +1 -0
  23. package/dist/__tests__/components/ExperimentPopover.test.d.ts +1 -0
  24. package/dist/__tests__/components/FormBuilder.test.d.ts +1 -0
  25. package/dist/__tests__/components/FormCompatibility.test.d.ts +1 -0
  26. package/dist/__tests__/components/GroupAssigner.test.d.ts +1 -0
  27. package/dist/__tests__/components/GroupingModal.test.d.ts +1 -0
  28. package/dist/__tests__/components/MultiSelect.test.d.ts +1 -0
  29. package/dist/__tests__/components/ProtocolStepEditor.test.d.ts +1 -0
  30. package/dist/__tests__/components/ReagentList.test.d.ts +1 -0
  31. package/dist/__tests__/components/SampleHierarchyTree.test.d.ts +1 -0
  32. package/dist/__tests__/components/SampleSelector.test.d.ts +1 -0
  33. package/dist/__tests__/components/SegmentedControl.test.d.ts +1 -0
  34. package/dist/__tests__/components/SettingsButton.test.d.ts +1 -0
  35. package/dist/__tests__/components/SettingsModal.test.d.ts +1 -0
  36. package/dist/__tests__/components/TagsInput.test.d.ts +1 -0
  37. package/dist/__tests__/components/ThemeToggle.test.d.ts +1 -0
  38. package/dist/__tests__/components/TimePicker.test.d.ts +1 -0
  39. package/dist/__tests__/composables/useBioTemplatePackWorkspace.test.d.ts +1 -0
  40. package/dist/__tests__/composables/useBioTemplatePresetWorkspace.test.d.ts +1 -0
  41. package/dist/__tests__/composables/useBioTemplateWorkspace.test.d.ts +1 -0
  42. package/dist/__tests__/composables/useCalendarGrid.test.d.ts +1 -0
  43. package/dist/__tests__/composables/useControlSchema.test.d.ts +1 -0
  44. package/dist/__tests__/composables/useDebouncedWatch.test.d.ts +1 -0
  45. package/dist/__tests__/composables/useDropdownState.test.d.ts +1 -0
  46. package/dist/__tests__/composables/useEventListener.test.d.ts +1 -0
  47. package/dist/__tests__/composables/useExpansionSet.test.d.ts +1 -0
  48. package/dist/__tests__/composables/useExperimentData.test.d.ts +1 -0
  49. package/dist/__tests__/composables/useExperimentSelector.test.d.ts +1 -0
  50. package/dist/__tests__/composables/useGroupAssignment.test.d.ts +1 -0
  51. package/dist/__tests__/composables/useListSelection.test.d.ts +1 -0
  52. package/dist/__tests__/composables/usePluginClient.test.d.ts +1 -0
  53. package/dist/__tests__/composables/usePluginConfig.test.d.ts +1 -0
  54. package/dist/__tests__/composables/useRequestSyncState.test.d.ts +1 -0
  55. package/dist/__tests__/composables/useSampleGroups.test.d.ts +1 -0
  56. package/dist/__tests__/composables/useSelectionLimit.test.d.ts +1 -0
  57. package/dist/__tests__/composables/useSortedItems.test.d.ts +1 -0
  58. package/dist/__tests__/composables/useTemplateCollection.test.d.ts +1 -0
  59. package/dist/__tests__/composables/useTextSearch.test.d.ts +1 -0
  60. package/dist/__tests__/composables/useTheme.test.d.ts +1 -0
  61. package/dist/__tests__/composables/useTimeUtils.test.d.ts +1 -0
  62. package/dist/__tests__/docs/frontendDocsCatalog.test.d.ts +1 -0
  63. package/dist/__tests__/templates/templates.test.d.ts +1 -0
  64. package/dist/{auth-DsI0rQ7_.js → auth-QQj2kkze.js} +12 -5
  65. package/dist/auth-QQj2kkze.js.map +1 -0
  66. package/dist/components/ActionItem.vue.d.ts +32 -0
  67. package/dist/components/AppAvatarMenu.vue.d.ts +2 -7
  68. package/dist/components/AppPageSelector.vue.d.ts +3 -6
  69. package/dist/components/AppPillNav.vue.d.ts +2 -2
  70. package/dist/components/AppSidebar.vue.d.ts +56 -3
  71. package/dist/components/AppToastContainer.vue.d.ts +2 -0
  72. package/dist/components/AppTopBar.vue.d.ts +41 -10
  73. package/dist/components/BaseButton.vue.d.ts +1 -1
  74. package/dist/components/BaseCheckbox.vue.d.ts +1 -1
  75. package/dist/components/BaseInput.vue.d.ts +2 -2
  76. package/dist/components/BasePill.vue.d.ts +2 -2
  77. package/dist/components/BaseRadioGroup.vue.d.ts +3 -3
  78. package/dist/components/BaseSelect.vue.d.ts +3 -3
  79. package/dist/components/BaseTabs.vue.d.ts +2 -2
  80. package/dist/components/BaseTextarea.vue.d.ts +1 -1
  81. package/dist/components/BaseToggle.vue.d.ts +1 -1
  82. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +117 -0
  83. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +92 -0
  84. package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +82 -0
  85. package/dist/components/BioTemplateRenderer.vue.d.ts +29 -0
  86. package/dist/components/Breadcrumb.vue.d.ts +2 -2
  87. package/dist/components/Calendar.vue.d.ts +1 -1
  88. package/dist/components/CalendarGridPanel.vue.d.ts +25 -0
  89. package/dist/components/CollapsibleCard.vue.d.ts +1 -1
  90. package/dist/components/ConcentrationInput.vue.d.ts +2 -2
  91. package/dist/components/ConfirmDialog.vue.d.ts +2 -2
  92. package/dist/components/ControlWorkspaceView.vue.d.ts +130 -0
  93. package/dist/components/DatePicker.vue.d.ts +1 -1
  94. package/dist/components/DateTimePicker.vue.d.ts +3 -3
  95. package/dist/components/Divider.vue.d.ts +1 -1
  96. package/dist/components/DropdownButton.vue.d.ts +3 -3
  97. package/dist/components/EmptyState.vue.d.ts +1 -2
  98. package/dist/components/ExperimentDataViewer.vue.d.ts +1 -1
  99. package/dist/components/ExperimentTimeline.vue.d.ts +2 -2
  100. package/dist/components/FileUploader.vue.d.ts +1 -1
  101. package/dist/components/FitPanel.vue.d.ts +1 -1
  102. package/dist/components/FormActions.vue.d.ts +4 -4
  103. package/dist/components/FormBuilder.vue.d.ts +22 -8
  104. package/dist/components/FormFieldRenderer.vue.d.ts +7 -10
  105. package/dist/components/FormSection.vue.d.ts +11 -24
  106. package/dist/components/FormulaInput.vue.d.ts +2 -2
  107. package/dist/components/MoleculeInput.vue.d.ts +2 -2
  108. package/dist/components/MultiSelect.vue.d.ts +3 -3
  109. package/dist/components/NumberInput.vue.d.ts +1 -1
  110. package/dist/components/ProgressBar.vue.d.ts +1 -1
  111. package/dist/components/ProtocolStepEditor.vue.d.ts +3 -1
  112. package/dist/components/RackEditor.vue.d.ts +2 -2
  113. package/dist/components/SampleLegend.vue.d.ts +2 -2
  114. package/dist/components/ScheduleCalendar.vue.d.ts +2 -2
  115. package/dist/components/SegmentedControl.vue.d.ts +2 -2
  116. package/dist/components/SequenceInput.vue.d.ts +3 -3
  117. package/dist/components/SettingsButton.vue.d.ts +2 -2
  118. package/dist/components/SettingsModal.vue.d.ts +13 -5
  119. package/dist/components/StatusIndicator.vue.d.ts +1 -1
  120. package/dist/components/TagsInput.vue.d.ts +3 -2
  121. package/dist/components/TimePicker.vue.d.ts +3 -3
  122. package/dist/components/TimeRangeInput.vue.d.ts +1 -1
  123. package/dist/components/UnitInput.vue.d.ts +2 -2
  124. package/dist/components/WellPlate.vue.d.ts +8 -8
  125. package/dist/components/index.d.ts +11 -1
  126. package/dist/components/index.js +3 -3
  127. package/dist/components/internal/FormFieldRendererInternal.vue.d.ts +31 -0
  128. package/dist/components/internal/FormSectionRenderer.vue.d.ts +43 -0
  129. package/dist/{components-_XqPEhP9.js → components-D_Sr0adg.js} +7290 -6518
  130. package/dist/components-D_Sr0adg.js.map +1 -0
  131. package/dist/composables/index.d.ts +21 -2
  132. package/dist/composables/index.js +4 -3
  133. package/dist/composables/platformContextHelpers.d.ts +14 -0
  134. package/dist/composables/useBioTemplateComponents.d.ts +20 -0
  135. package/dist/composables/useBioTemplateControls.d.ts +6 -0
  136. package/dist/composables/useBioTemplatePackWorkspace.d.ts +45 -0
  137. package/dist/composables/useBioTemplatePresetWorkspace.d.ts +74 -0
  138. package/dist/composables/useBioTemplateWorkspace.d.ts +50 -0
  139. package/dist/composables/useCalendarGrid.d.ts +26 -0
  140. package/dist/composables/useControlSchema.d.ts +321 -0
  141. package/dist/composables/useDebouncedWatch.d.ts +20 -0
  142. package/dist/composables/useDropdownState.d.ts +19 -0
  143. package/dist/composables/useEventListener.d.ts +13 -0
  144. package/dist/composables/useExpansionSet.d.ts +21 -0
  145. package/dist/composables/useExperimentData.d.ts +10 -0
  146. package/dist/composables/useExperimentSave.d.ts +31 -2
  147. package/dist/composables/useExperimentSelector.d.ts +20 -0
  148. package/dist/composables/useForm.d.ts +2 -0
  149. package/dist/composables/useGroupAssignment.d.ts +31 -0
  150. package/dist/composables/useListSelection.d.ts +35 -0
  151. package/dist/composables/usePlatformContext.d.ts +21 -3
  152. package/dist/composables/usePluginApi.d.ts +7 -14
  153. package/dist/composables/usePluginClient.d.ts +109 -0
  154. package/dist/composables/usePluginConfig.d.ts +12 -0
  155. package/dist/composables/useRequestSyncState.d.ts +34 -0
  156. package/dist/composables/useSampleGroups.d.ts +32 -0
  157. package/dist/composables/useSelectionLimit.d.ts +17 -0
  158. package/dist/composables/useSortedItems.d.ts +32 -0
  159. package/dist/composables/useTemplateCollection.d.ts +58 -0
  160. package/dist/composables/useTextSearch.d.ts +18 -0
  161. package/dist/composables/useTimeUtils.d.ts +8 -0
  162. package/dist/{composables-tiZqLu1M.js → composables-C3dpXQN5.js} +228 -146
  163. package/dist/composables-C3dpXQN5.js.map +1 -0
  164. package/dist/index.d.ts +12 -3
  165. package/dist/index.js +6 -5
  166. package/dist/install.d.ts +7 -2
  167. package/dist/install.js +2 -2
  168. package/dist/install.js.map +1 -1
  169. package/dist/stores/index.js +1 -1
  170. package/dist/stores/settings.d.ts +4 -1
  171. package/dist/styles.css +5235 -5977
  172. package/dist/templates/adapters.d.ts +43 -0
  173. package/dist/templates/builders.d.ts +63 -0
  174. package/dist/templates/catalog.d.ts +188 -0
  175. package/dist/templates/componentBindings.d.ts +58 -0
  176. package/dist/templates/controlSchemas.d.ts +25 -0
  177. package/dist/templates/index.d.ts +15 -0
  178. package/dist/templates/index.js +2 -0
  179. package/dist/templates/lookup.d.ts +4 -0
  180. package/dist/templates/packs.d.ts +18 -0
  181. package/dist/templates/presets.d.ts +90 -0
  182. package/dist/templates/types.d.ts +531 -0
  183. package/dist/templates-50NPjaxL.js +9333 -0
  184. package/dist/templates-50NPjaxL.js.map +1 -0
  185. package/dist/types/components.d.ts +26 -4
  186. package/dist/types/form-builder.d.ts +6 -8
  187. package/dist/types/index.d.ts +2 -2
  188. package/dist/types/platform.d.ts +7 -1
  189. package/dist/useScheduleDrag-D4oWdh41.js +4371 -0
  190. package/dist/useScheduleDrag-D4oWdh41.js.map +1 -0
  191. package/dist/utils/formModelSync.d.ts +5 -0
  192. package/dist/utils/items.d.ts +8 -0
  193. package/dist/utils/options.d.ts +6 -0
  194. package/dist/utils/pluginIcon.d.ts +9 -0
  195. package/package.json +7 -2
  196. package/src/__tests__/components/ActionItem.test.ts +99 -0
  197. package/src/__tests__/components/AppAvatarMenu.test.ts +27 -0
  198. package/src/__tests__/components/AppPageSelector.test.ts +134 -0
  199. package/src/__tests__/components/AppPillNav.test.ts +78 -0
  200. package/src/__tests__/components/AppPluginSwitcher.test.ts +44 -0
  201. package/src/__tests__/components/AppSidebar.test.ts +370 -0
  202. package/src/__tests__/components/AppToastContainer.test.ts +48 -0
  203. package/src/__tests__/components/AppTopBar.test.ts +383 -0
  204. package/src/__tests__/components/BaseRadioGroup.test.ts +25 -0
  205. package/src/__tests__/components/BaseSelect.test.ts +21 -0
  206. package/src/__tests__/components/BaseTabs.test.ts +25 -0
  207. package/src/__tests__/components/BatchProgressList.test.ts +52 -0
  208. package/src/__tests__/components/BioTemplateExperimentWorkspaceView.test.ts +153 -0
  209. package/src/__tests__/components/BioTemplatePackWorkspaceView.test.ts +161 -0
  210. package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +281 -0
  211. package/src/__tests__/components/BioTemplateRenderer.test.ts +71 -0
  212. package/src/__tests__/components/Breadcrumb.test.ts +23 -0
  213. package/src/__tests__/components/CalendarGridPanel.test.ts +36 -0
  214. package/src/__tests__/components/ConcentrationInput.test.ts +45 -0
  215. package/src/__tests__/components/ControlWorkspaceView.test.ts +1031 -0
  216. package/src/__tests__/components/DataFrame.test.ts +11 -0
  217. package/src/__tests__/components/DatePicker.test.ts +45 -0
  218. package/src/__tests__/components/DateTimePicker.test.ts +48 -0
  219. package/src/__tests__/components/DropdownButton.test.ts +23 -0
  220. package/src/__tests__/components/EmptyState.test.ts +23 -0
  221. package/src/__tests__/components/ExperimentPopover.test.ts +56 -0
  222. package/src/__tests__/components/FormBuilder.test.ts +296 -0
  223. package/src/__tests__/components/FormCompatibility.test.ts +94 -0
  224. package/src/__tests__/components/GroupAssigner.test.ts +30 -0
  225. package/src/__tests__/components/GroupingModal.test.ts +73 -0
  226. package/src/__tests__/components/MultiSelect.test.ts +48 -0
  227. package/src/__tests__/components/ProtocolStepEditor.test.ts +33 -0
  228. package/src/__tests__/components/ReagentList.test.ts +82 -0
  229. package/src/__tests__/components/SampleHierarchyTree.test.ts +53 -0
  230. package/src/__tests__/components/SampleSelector.test.ts +60 -0
  231. package/src/__tests__/components/SegmentedControl.test.ts +24 -0
  232. package/src/__tests__/components/SettingsButton.test.ts +44 -0
  233. package/src/__tests__/components/SettingsModal.test.ts +296 -0
  234. package/src/__tests__/components/TagsInput.test.ts +75 -0
  235. package/src/__tests__/components/ThemeToggle.test.ts +47 -0
  236. package/src/__tests__/components/TimePicker.test.ts +38 -0
  237. package/src/__tests__/composables/useBioTemplatePackWorkspace.test.ts +122 -0
  238. package/src/__tests__/composables/useBioTemplatePresetWorkspace.test.ts +199 -0
  239. package/src/__tests__/composables/useBioTemplateWorkspace.test.ts +99 -0
  240. package/src/__tests__/composables/useCalendarGrid.test.ts +38 -0
  241. package/src/__tests__/composables/useControlSchema.test.ts +919 -0
  242. package/src/__tests__/composables/useDebouncedWatch.test.ts +93 -0
  243. package/src/__tests__/composables/useDropdownState.test.ts +95 -0
  244. package/src/__tests__/composables/useEventListener.test.ts +116 -0
  245. package/src/__tests__/composables/useExpansionSet.test.ts +62 -0
  246. package/src/__tests__/composables/useExperimentData.test.ts +4 -0
  247. package/src/__tests__/composables/useExperimentSave.test.ts +203 -8
  248. package/src/__tests__/composables/useExperimentSelector.test.ts +164 -0
  249. package/src/__tests__/composables/useForm.test.ts +58 -0
  250. package/src/__tests__/composables/useFormBuilder.test.ts +77 -0
  251. package/src/__tests__/composables/useGroupAssignment.test.ts +73 -0
  252. package/src/__tests__/composables/useListSelection.test.ts +66 -0
  253. package/src/__tests__/composables/usePluginClient.test.ts +444 -0
  254. package/src/__tests__/composables/usePluginConfig.test.ts +5 -0
  255. package/src/__tests__/composables/useRequestSyncState.test.ts +92 -0
  256. package/src/__tests__/composables/useSampleGroups.test.ts +66 -0
  257. package/src/__tests__/composables/useSelectionLimit.test.ts +41 -0
  258. package/src/__tests__/composables/useSortedItems.test.ts +87 -0
  259. package/src/__tests__/composables/useTemplateCollection.test.ts +147 -0
  260. package/src/__tests__/composables/useTextSearch.test.ts +55 -0
  261. package/src/__tests__/composables/useTheme.test.ts +91 -0
  262. package/src/__tests__/composables/useTimeUtils.test.ts +35 -0
  263. package/src/__tests__/docs/frontendDocsCatalog.test.ts +229 -0
  264. package/src/__tests__/fixtures/templates/dose-response.json +81 -0
  265. package/src/__tests__/fixtures/templates/plate-map.json +54 -0
  266. package/src/__tests__/fixtures/templates/qpcr-plate.json +96 -0
  267. package/src/__tests__/fixtures/templates/sample-sheet.json +71 -0
  268. package/src/__tests__/templates/templates.test.ts +1043 -0
  269. package/src/components/ActionItem.vue +82 -0
  270. package/src/components/AppAvatarMenu.vue +15 -69
  271. package/src/components/AppLayout.story.vue +25 -25
  272. package/src/components/AppPageSelector.vue +63 -94
  273. package/src/components/AppPillNav.vue +44 -39
  274. package/src/components/AppPluginSwitcher.vue +41 -145
  275. package/src/components/AppSidebar.story.vue +94 -0
  276. package/src/components/AppSidebar.vue +187 -12
  277. package/src/components/{ToastNotification.story.vue → AppToastContainer.story.vue} +6 -6
  278. package/src/components/AppToastContainer.vue +62 -0
  279. package/src/components/AppTopBar.story.vue +7 -30
  280. package/src/components/AppTopBar.vue +251 -57
  281. package/src/components/BaseModal.vue +3 -5
  282. package/src/components/BaseRadioGroup.vue +7 -3
  283. package/src/components/BaseSelect.vue +11 -7
  284. package/src/components/BaseTabs.vue +6 -4
  285. package/src/components/BatchProgressList.vue +5 -8
  286. package/src/components/BioTemplateExperimentWorkspaceView.story.vue +123 -0
  287. package/src/components/BioTemplateExperimentWorkspaceView.vue +337 -0
  288. package/src/components/BioTemplatePackWorkspaceView.story.vue +107 -0
  289. package/src/components/BioTemplatePackWorkspaceView.vue +176 -0
  290. package/src/components/BioTemplatePresetWorkspaceView.story.vue +151 -0
  291. package/src/components/BioTemplatePresetWorkspaceView.vue +392 -0
  292. package/src/components/BioTemplateRenderer.story.vue +57 -0
  293. package/src/components/BioTemplateRenderer.vue +269 -0
  294. package/src/components/Breadcrumb.vue +14 -8
  295. package/src/components/CalendarGridPanel.vue +120 -0
  296. package/src/components/ConcentrationInput.vue +27 -64
  297. package/src/components/ControlWorkspaceView.story.vue +336 -0
  298. package/src/components/ControlWorkspaceView.vue +347 -0
  299. package/src/components/DataFrame.vue +34 -50
  300. package/src/components/DatePicker.vue +59 -192
  301. package/src/components/DateTimePicker.vue +50 -171
  302. package/src/components/DropdownButton.vue +14 -32
  303. package/src/components/EmptyState.vue +4 -2
  304. package/src/components/ExperimentPopover.vue +5 -22
  305. package/src/components/FormBuilder.vue +124 -27
  306. package/src/components/FormFieldRenderer.vue +15 -38
  307. package/src/components/FormSection.vue +20 -73
  308. package/src/components/GroupAssigner.vue +24 -56
  309. package/src/components/GroupingModal.story.vue +3 -3
  310. package/src/components/GroupingModal.vue +30 -391
  311. package/src/components/MultiSelect.vue +17 -12
  312. package/src/components/PlateMapEditor.vue +3 -8
  313. package/src/components/PluginIcon.vue +2 -22
  314. package/src/components/ProtocolStepEditor.vue +13 -22
  315. package/src/components/ReagentList.vue +25 -33
  316. package/src/components/SampleHierarchyTree.vue +12 -23
  317. package/src/components/SampleSelector.vue +42 -122
  318. package/src/components/SegmentedControl.vue +7 -3
  319. package/src/components/SettingsButton.story.vue +1 -1
  320. package/src/components/SettingsButton.vue +15 -27
  321. package/src/components/SettingsModal.story.vue +1 -1
  322. package/src/components/SettingsModal.vue +120 -29
  323. package/src/components/TagsInput.vue +29 -14
  324. package/src/components/ThemeToggle.vue +9 -7
  325. package/src/components/TimePicker.vue +19 -41
  326. package/src/components/ToastNotification.vue +4 -57
  327. package/src/components/Tooltip.vue +7 -12
  328. package/src/components/WellEditPopup.vue +3 -8
  329. package/src/components/WellPlate.vue +4 -10
  330. package/src/components/index.ts +11 -1
  331. package/src/components/internal/FormFieldRendererInternal.vue +50 -0
  332. package/src/components/internal/FormSectionRenderer.vue +78 -0
  333. package/src/composables/index.ts +212 -0
  334. package/src/composables/platformContextHelpers.ts +74 -0
  335. package/src/composables/useBioTemplateComponents.ts +93 -0
  336. package/src/composables/useBioTemplateControls.ts +41 -0
  337. package/src/composables/useBioTemplatePackWorkspace.ts +181 -0
  338. package/src/composables/useBioTemplatePresetWorkspace.ts +337 -0
  339. package/src/composables/useBioTemplateWorkspace.ts +139 -0
  340. package/src/composables/useCalendarGrid.ts +140 -0
  341. package/src/composables/useControlSchema.ts +1274 -0
  342. package/src/composables/useDebouncedWatch.ts +119 -0
  343. package/src/composables/useDropdownState.ts +83 -0
  344. package/src/composables/useEventListener.ts +111 -0
  345. package/src/composables/useExpansionSet.ts +117 -0
  346. package/src/composables/useExperimentData.ts +20 -11
  347. package/src/composables/useExperimentSave.ts +202 -50
  348. package/src/composables/useExperimentSelector.ts +86 -72
  349. package/src/composables/useForm.ts +49 -4
  350. package/src/composables/useFormBuilder.ts +93 -42
  351. package/src/composables/useGroupAssignment.ts +148 -0
  352. package/src/composables/useListSelection.ts +158 -0
  353. package/src/composables/usePluginApi.ts +7 -14
  354. package/src/composables/usePluginClient.ts +425 -0
  355. package/src/composables/usePluginConfig.ts +34 -13
  356. package/src/composables/useRequestSyncState.ts +126 -0
  357. package/src/composables/useSampleGroups.ts +126 -0
  358. package/src/composables/useSelectionLimit.ts +57 -0
  359. package/src/composables/useSortedItems.ts +118 -0
  360. package/src/composables/useTemplateCollection.ts +229 -0
  361. package/src/composables/useTextSearch.ts +60 -0
  362. package/src/composables/useTheme.ts +2 -28
  363. package/src/composables/useTimeUtils.ts +26 -2
  364. package/src/composables/useWellPlateEditor.ts +13 -9
  365. package/src/index.ts +224 -4
  366. package/src/install.ts +11 -4
  367. package/src/stores/settings.ts +13 -9
  368. package/src/styles/components/app-page-selector.css +23 -0
  369. package/src/styles/components/app-pill-nav.css +7 -0
  370. package/src/styles/components/app-top-bar.css +34 -0
  371. package/src/styles/components/concentration-input.css +3 -142
  372. package/src/styles/components/empty-state.css +0 -16
  373. package/src/styles/components/settings-button.css +3 -66
  374. package/src/styles/components/theme-toggle.css +3 -66
  375. package/src/styles/index.css +0 -1
  376. package/src/templates/adapters.ts +785 -0
  377. package/src/templates/builders.ts +2149 -0
  378. package/src/templates/catalog.ts +245 -0
  379. package/src/templates/componentBindings.ts +615 -0
  380. package/src/templates/controlSchemas.ts +718 -0
  381. package/src/templates/index.ts +314 -0
  382. package/src/templates/lookup.ts +18 -0
  383. package/src/templates/packs.ts +156 -0
  384. package/src/templates/presets.ts +146 -0
  385. package/src/templates/types.ts +668 -0
  386. package/src/types/components.ts +41 -4
  387. package/src/types/form-builder.ts +7 -2
  388. package/src/types/index.ts +14 -0
  389. package/src/types/platform.ts +7 -1
  390. package/src/utils/formModelSync.ts +52 -0
  391. package/src/utils/items.ts +28 -0
  392. package/src/utils/options.ts +23 -0
  393. package/src/utils/pluginIcon.ts +30 -0
  394. package/dist/auth-DsI0rQ7_.js.map +0 -1
  395. package/dist/components-_XqPEhP9.js.map +0 -1
  396. package/dist/composables-tiZqLu1M.js.map +0 -1
  397. package/dist/useScheduleDrag-CA9sGNJG.js +0 -7181
  398. package/dist/useScheduleDrag-CA9sGNJG.js.map +0 -1
  399. package/src/styles/components/grouping-modal.css +0 -323
@@ -1,7 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  /** Modal dialog with backdrop, focus trap, Escape-to-close, and configurable size/variant. */
3
- import { ref, watch, nextTick, onMounted, onUnmounted } from 'vue'
3
+ import { ref, watch, nextTick, onUnmounted } from 'vue'
4
4
  import type { ModalSize, ModalVariant } from '../types'
5
+ import { useEventListener } from '../composables/useEventListener'
5
6
 
6
7
  interface Props {
7
8
  modelValue: boolean
@@ -101,12 +102,9 @@ watch(() => props.modelValue, async (isOpen) => {
101
102
  }
102
103
  })
103
104
 
104
- onMounted(() => {
105
- document.addEventListener('keydown', handleKeydown)
106
- })
105
+ useEventListener(() => document, 'keydown', handleKeydown)
107
106
 
108
107
  onUnmounted(() => {
109
- document.removeEventListener('keydown', handleKeydown)
110
108
  document.body.style.overflow = ''
111
109
  })
112
110
  </script>
@@ -1,10 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  /** Renders a group of radio buttons in list or tile layout, horizontal or vertical. */
3
- import type { RadioOption } from '../types'
3
+ import { computed } from 'vue'
4
+ import type { RadioOption, RadioOptionInput } from '../types'
5
+ import { normalizeOptionInput } from '../utils/options'
4
6
 
5
7
  interface Props {
6
8
  modelValue?: string | number
7
- options: RadioOption[]
9
+ options: RadioOptionInput[]
8
10
  name: string
9
11
  disabled?: boolean
10
12
  direction?: 'horizontal' | 'vertical'
@@ -23,6 +25,8 @@ const emit = defineEmits<{
23
25
  'update:modelValue': [value: string | number]
24
26
  }>()
25
27
 
28
+ const normalizedOptions = computed<RadioOption[]>(() => props.options.map(normalizeOptionInput))
29
+
26
30
  function handleChange(value: string | number) {
27
31
  emit('update:modelValue', value)
28
32
  }
@@ -34,7 +38,7 @@ function handleChange(value: string | number) {
34
38
  role="radiogroup"
35
39
  >
36
40
  <label
37
- v-for="option in props.options"
41
+ v-for="option in normalizedOptions"
38
42
  :key="String(option.value)"
39
43
  :class="[
40
44
  'mint-radio-option',
@@ -1,10 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  /** Renders a native `<select>` element with size, error, and disabled states. */
3
- import type { SelectOption } from '../types'
3
+ import { computed } from 'vue'
4
+ import type { SelectOption, SelectOptionInput } from '../types'
5
+ import { findOptionByDomValue, normalizeOptionInput } from '../utils/options'
4
6
 
5
7
  interface Props {
6
8
  modelValue?: string | number
7
- options: SelectOption<string | number>[]
9
+ options: SelectOptionInput<string | number>[]
8
10
  placeholder?: string
9
11
  disabled?: boolean
10
12
  error?: boolean
@@ -22,12 +24,14 @@ const emit = defineEmits<{
22
24
  'update:modelValue': [value: string | number]
23
25
  }>()
24
26
 
27
+ const normalizedOptions = computed<SelectOption<string | number>[]>(() =>
28
+ props.options.map(normalizeOptionInput)
29
+ )
30
+
25
31
  function handleChange(event: Event) {
26
32
  const target = event.target as HTMLSelectElement
27
- const value = typeof props.modelValue === 'number'
28
- ? Number(target.value)
29
- : target.value
30
- emit('update:modelValue', value)
33
+ const option = findOptionByDomValue(normalizedOptions.value, target.value)
34
+ emit('update:modelValue', option?.value ?? target.value)
31
35
  }
32
36
  </script>
33
37
 
@@ -50,7 +54,7 @@ function handleChange(event: Event) {
50
54
  {{ placeholder }}
51
55
  </option>
52
56
  <option
53
- v-for="option in options"
57
+ v-for="option in normalizedOptions"
54
58
  :key="String(option.value)"
55
59
  :value="option.value"
56
60
  :disabled="option.disabled"
@@ -1,11 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  /** Renders a tab bar with underline or pills variant, badges, icons, and disabled tab support. */
3
3
  import { computed } from 'vue'
4
- import type { TabItem } from '../types'
4
+ import type { TabItem, TabItemInput } from '../types'
5
+ import { normalizeItemInput } from '../utils/items'
5
6
 
6
7
  interface Props {
7
8
  modelValue: string
8
- tabs: TabItem[]
9
+ tabs: TabItemInput[]
9
10
  variant?: 'underline' | 'pills'
10
11
  }
11
12
 
@@ -18,9 +19,10 @@ const emit = defineEmits<{
18
19
  }>()
19
20
 
20
21
  const activeTab = computed(() => props.modelValue)
22
+ const normalizedTabs = computed<TabItem[]>(() => props.tabs.map(normalizeItemInput))
21
23
 
22
24
  function selectTab(tabId: string) {
23
- const tab = props.tabs.find(t => t.id === tabId)
25
+ const tab = normalizedTabs.value.find(t => t.id === tabId)
24
26
  if (tab && !tab.disabled) {
25
27
  emit('update:modelValue', tabId)
26
28
  }
@@ -30,7 +32,7 @@ function selectTab(tabId: string) {
30
32
  <template>
31
33
  <div :class="['mint-tabs', `mint-tabs--${variant}`]" role="tablist">
32
34
  <button
33
- v-for="tab in tabs"
35
+ v-for="tab in normalizedTabs"
34
36
  :key="tab.id"
35
37
  type="button"
36
38
  role="tab"
@@ -2,6 +2,7 @@
2
2
  /** Scrollable list tracking per-item status for a batch operation with overall progress summary. */
3
3
  import { computed, ref, watch, nextTick } from 'vue'
4
4
  import type { BatchItem, BatchSummary } from '../types'
5
+ import { useExpansionSet } from '../composables/useExpansionSet'
5
6
 
6
7
  interface Props {
7
8
  items: BatchItem[]
@@ -22,7 +23,7 @@ const emit = defineEmits<{
22
23
  }>()
23
24
 
24
25
  const listRef = ref<HTMLElement | null>(null)
25
- const expandedErrors = ref<Set<string>>(new Set())
26
+ const errorExpansion = useExpansionSet()
26
27
 
27
28
  const summary = computed<BatchSummary>(() => {
28
29
  const total = props.items.length
@@ -36,11 +37,7 @@ const summary = computed<BatchSummary>(() => {
36
37
  })
37
38
 
38
39
  function toggleError(id: string) {
39
- if (expandedErrors.value.has(id)) {
40
- expandedErrors.value.delete(id)
41
- } else {
42
- expandedErrors.value.add(id)
43
- }
40
+ errorExpansion.toggle(id)
44
41
  }
45
42
 
46
43
  watch(
@@ -167,9 +164,9 @@ watch(
167
164
  class="mint-batch-progress__error-toggle"
168
165
  @click.stop="toggleError(item.id)"
169
166
  >
170
- {{ expandedErrors.has(item.id) ? 'Hide error' : 'Show error' }}
167
+ {{ errorExpansion.isExpanded(item.id) ? 'Hide error' : 'Show error' }}
171
168
  </button>
172
- <div v-if="expandedErrors.has(item.id)" class="mint-batch-progress__item-message">
169
+ <div v-if="errorExpansion.isExpanded(item.id)" class="mint-batch-progress__item-message">
173
170
  {{ item.message }}
174
171
  </div>
175
172
  </div>
@@ -0,0 +1,123 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ import BioTemplateExperimentWorkspaceView from './BioTemplateExperimentWorkspaceView.vue'
4
+ import DoseCalculator from './DoseCalculator.vue'
5
+ import WellPlate from './WellPlate.vue'
6
+ import {
7
+ createWellPlateScreenCollection,
8
+ createPlateMapTemplate,
9
+ } from '../templates'
10
+
11
+ const collection = createWellPlateScreenCollection()
12
+ const template = createPlateMapTemplate()
13
+ const error = ref<string | null>(null)
14
+
15
+ function initState() {
16
+ return {
17
+ target: 'collection',
18
+ hasExperiment: true,
19
+ showTemplateSummary: true,
20
+ dense: true,
21
+ }
22
+ }
23
+ </script>
24
+
25
+ <template>
26
+ <Story title="Templates/BioTemplateExperimentWorkspaceView" :init-state="initState">
27
+ <Variant title="Playground">
28
+ <template #default="{ state }">
29
+ <div style="padding: 2rem; min-height: 680px; background: var(--bg-primary, #f8fafc);">
30
+ <BioTemplateExperimentWorkspaceView
31
+ :target="state.target === 'template' ? template : collection"
32
+ :kind="state.target === 'template' ? 'template' : 'collection'"
33
+ :label="state.target === 'template' ? 'Plate Map' : 'Wellplate Screen'"
34
+ :has-experiment="state.hasExperiment"
35
+ :current-experiment-id="state.hasExperiment ? 42 : undefined"
36
+ :error="error"
37
+ :show-template-summary="state.showTemplateSummary"
38
+ :dense="state.dense"
39
+ />
40
+ </div>
41
+ </template>
42
+
43
+ <template #controls="{ state }">
44
+ <HstSelect
45
+ v-model="state.target"
46
+ title="Target"
47
+ :options="[
48
+ { label: 'Collection', value: 'collection' },
49
+ { label: 'Template', value: 'template' },
50
+ ]"
51
+ />
52
+ <HstCheckbox v-model="state.hasExperiment" title="Has experiment" />
53
+ <HstCheckbox v-model="state.showTemplateSummary" title="Template summary" />
54
+ <HstCheckbox v-model="state.dense" title="Dense" />
55
+ </template>
56
+ </Variant>
57
+
58
+ <Variant title="Component Props">
59
+ <div style="padding: 2rem; min-height: 680px; background: var(--bg-primary, #f8fafc);">
60
+ <BioTemplateExperimentWorkspaceView
61
+ :target="collection"
62
+ kind="collection"
63
+ label="Wellplate Screen"
64
+ :has-experiment="true"
65
+ :current-experiment-id="42"
66
+ :show-template-summary="false"
67
+ v-slot="{ bindings }"
68
+ >
69
+ <div class="experiment-component-layout">
70
+ <div class="experiment-component-panel experiment-component-panel--plate">
71
+ <WellPlate
72
+ v-bind="bindings.componentPropsById['plate-map:WellPlate']"
73
+ size="sm"
74
+ readonly
75
+ />
76
+ </div>
77
+ <div class="experiment-component-panel experiment-component-panel--dose">
78
+ <DoseCalculator
79
+ v-bind="bindings.componentPropsById['dose-response:DoseCalculator']"
80
+ />
81
+ </div>
82
+ </div>
83
+ </BioTemplateExperimentWorkspaceView>
84
+ </div>
85
+ </Variant>
86
+ </Story>
87
+ </template>
88
+
89
+ <style scoped>
90
+ .experiment-component-layout {
91
+ display: grid;
92
+ grid-template-columns: minmax(0, 1.35fr) minmax(18rem, 0.65fr);
93
+ gap: 1rem;
94
+ align-items: start;
95
+ min-width: 0;
96
+ }
97
+
98
+ .experiment-component-panel {
99
+ min-width: 0;
100
+ padding: 1rem;
101
+ border: 1px solid var(--border-color);
102
+ border-radius: var(--radius-lg, 0.75rem);
103
+ background: var(--bg-primary);
104
+ }
105
+
106
+ .experiment-component-panel--plate {
107
+ overflow-x: auto;
108
+ }
109
+
110
+ .experiment-component-panel--dose {
111
+ max-width: 24rem;
112
+ }
113
+
114
+ @media (max-width: 960px) {
115
+ .experiment-component-layout {
116
+ grid-template-columns: 1fr;
117
+ }
118
+
119
+ .experiment-component-panel--dose {
120
+ max-width: none;
121
+ }
122
+ }
123
+ </style>
@@ -0,0 +1,337 @@
1
+ <script setup lang="ts">
2
+ /** Current-experiment template workspace with load/save/reset controls and WellPlate/DataFrame/DoseCalculator previews. */
3
+ import { computed } from 'vue'
4
+ import {
5
+ extractTemplateCollection,
6
+ getBioTemplateComponentProps,
7
+ toBioTemplateComponentProps,
8
+ toBioTemplateComponentPropsByComponent,
9
+ toBioTemplateComponentPropsById,
10
+ type BioTemplateEnvelope,
11
+ type BioTemplateComponentPropsLookupOptions,
12
+ type TemplateCollectionEnvelope,
13
+ } from '../templates'
14
+ import AlertBox from './AlertBox.vue'
15
+ import BaseButton from './BaseButton.vue'
16
+ import BioTemplateRenderer from './BioTemplateRenderer.vue'
17
+
18
+ type BioTemplateWorkspaceTarget = BioTemplateEnvelope<unknown> | TemplateCollectionEnvelope
19
+ type WorkspaceKind = 'template' | 'collection'
20
+
21
+ interface TemplateWorkspaceStatus {
22
+ loading?: boolean
23
+ saving?: boolean
24
+ error?: string | null
25
+ hasExperiment?: boolean
26
+ currentExperimentId?: number
27
+ lastLoadedAt?: Date | null
28
+ lastSavedAt?: Date | null
29
+ }
30
+
31
+ interface TemplateWorkspaceActions {
32
+ load?: () => unknown
33
+ reset?: () => unknown
34
+ save?: () => unknown
35
+ }
36
+
37
+ interface Props {
38
+ /** Template envelope or template collection shown in BioTemplateRenderer. */
39
+ target: BioTemplateWorkspaceTarget
40
+ /** Human-readable workspace label. */
41
+ label: string
42
+ /** Grouped request and current-experiment state for generated plugin pages. */
43
+ status?: TemplateWorkspaceStatus
44
+ /** Grouped load/reset/save handlers for generated plugin pages. */
45
+ actions?: TemplateWorkspaceActions
46
+ /** Copy shown in the status banner. */
47
+ message?: string
48
+ /** Whether the load/save request is active. */
49
+ loading?: boolean
50
+ /** Current request error. */
51
+ error?: string | null
52
+ /** Whether a current experiment id is available. */
53
+ hasExperiment?: boolean
54
+ /** Current experiment id displayed in the footer. */
55
+ currentExperimentId?: number
56
+ /** Last successful load timestamp. */
57
+ lastLoadedAt?: Date | null
58
+ /** Last successful save timestamp. */
59
+ lastSavedAt?: Date | null
60
+ /** Template vs collection copy defaults. */
61
+ kind?: WorkspaceKind
62
+ /** Compact preview layout. */
63
+ dense?: boolean
64
+ /** Render preview components in read-only mode. */
65
+ readonly?: boolean
66
+ /** Show load/save timestamps. */
67
+ showStatus?: boolean
68
+ /** Show template id/version cards for collection targets. */
69
+ showTemplateSummary?: boolean
70
+ loadLabel?: string
71
+ resetLabel?: string
72
+ saveLabel?: string
73
+ }
74
+
75
+ const props = withDefaults(defineProps<Props>(), {
76
+ status: undefined,
77
+ actions: undefined,
78
+ message: undefined,
79
+ loading: false,
80
+ error: null,
81
+ hasExperiment: false,
82
+ currentExperimentId: undefined,
83
+ lastLoadedAt: null,
84
+ lastSavedAt: null,
85
+ kind: 'template',
86
+ dense: true,
87
+ readonly: true,
88
+ showStatus: true,
89
+ showTemplateSummary: false,
90
+ loadLabel: 'Load',
91
+ resetLabel: 'Reset defaults',
92
+ saveLabel: 'Save',
93
+ })
94
+
95
+ const emit = defineEmits<{
96
+ load: []
97
+ reset: []
98
+ save: []
99
+ }>()
100
+
101
+ const statusMessage = computed(() => {
102
+ if (props.message) return props.message
103
+ if (props.kind === 'collection') {
104
+ return `${props.label} saves the full template collection to the current experiment.`
105
+ }
106
+ return `${props.label} template data saves to experiment design_data.`
107
+ })
108
+
109
+ const resolvedLoading = computed(() => {
110
+ if (props.status?.loading !== undefined || props.status?.saving !== undefined) {
111
+ return Boolean(props.status.loading) || Boolean(props.status.saving)
112
+ }
113
+ return props.loading
114
+ })
115
+ const resolvedError = computed(() =>
116
+ props.status?.error !== undefined ? props.status.error : props.error,
117
+ )
118
+ const resolvedHasExperiment = computed(() =>
119
+ props.status?.hasExperiment ?? props.hasExperiment,
120
+ )
121
+ const resolvedCurrentExperimentId = computed(() =>
122
+ props.status?.currentExperimentId ?? props.currentExperimentId,
123
+ )
124
+ const resolvedLastLoadedAt = computed(() =>
125
+ props.status?.lastLoadedAt !== undefined ? props.status.lastLoadedAt : props.lastLoadedAt,
126
+ )
127
+ const resolvedLastSavedAt = computed(() =>
128
+ props.status?.lastSavedAt !== undefined ? props.status.lastSavedAt : props.lastSavedAt,
129
+ )
130
+
131
+ const templateSummaries = computed(() =>
132
+ Object.values(extractTemplateCollection(props.target)).map(template => ({
133
+ id: String(template.template_id),
134
+ version: String(template.template_version ?? 'unknown'),
135
+ }))
136
+ )
137
+ const componentProps = computed(() => toBioTemplateComponentProps(props.target))
138
+ const componentPropsById = computed(() => toBioTemplateComponentPropsById(props.target))
139
+ const componentPropsByComponent = computed(() => toBioTemplateComponentPropsByComponent(props.target))
140
+ const renderer = computed(() => ({ target: props.target }))
141
+
142
+ function getComponentProps(component: string, options?: BioTemplateComponentPropsLookupOptions) {
143
+ return getBioTemplateComponentProps(props.target, component, options)
144
+ }
145
+
146
+ interface BioTemplateExperimentWorkspaceBindings {
147
+ renderer: { target: BioTemplateWorkspaceTarget }
148
+ componentProps: ReturnType<typeof toBioTemplateComponentProps>
149
+ componentPropsById: ReturnType<typeof toBioTemplateComponentPropsById>
150
+ componentPropsByComponent: ReturnType<typeof toBioTemplateComponentPropsByComponent>
151
+ getComponentProps: typeof getComponentProps
152
+ }
153
+
154
+ const bindings = computed<BioTemplateExperimentWorkspaceBindings>(() => ({
155
+ renderer: renderer.value,
156
+ componentProps: componentProps.value,
157
+ componentPropsById: componentPropsById.value,
158
+ componentPropsByComponent: componentPropsByComponent.value,
159
+ getComponentProps,
160
+ }))
161
+
162
+ interface BioTemplateExperimentWorkspaceSlotProps {
163
+ target: BioTemplateWorkspaceTarget
164
+ bindings: BioTemplateExperimentWorkspaceBindings
165
+ componentProps: ReturnType<typeof toBioTemplateComponentProps>
166
+ componentPropsById: ReturnType<typeof toBioTemplateComponentPropsById>
167
+ componentPropsByComponent: ReturnType<typeof toBioTemplateComponentPropsByComponent>
168
+ getComponentProps: typeof getComponentProps
169
+ }
170
+
171
+ defineSlots<{
172
+ default?: (props: BioTemplateExperimentWorkspaceSlotProps) => unknown
173
+ }>()
174
+
175
+ function handleLoad() {
176
+ if (props.actions?.load) {
177
+ return props.actions.load()
178
+ }
179
+ emit('load')
180
+ }
181
+
182
+ function handleReset() {
183
+ if (props.actions?.reset) {
184
+ return props.actions.reset()
185
+ }
186
+ emit('reset')
187
+ }
188
+
189
+ function handleSave() {
190
+ if (props.actions?.save) {
191
+ return props.actions.save()
192
+ }
193
+ emit('save')
194
+ }
195
+ </script>
196
+
197
+ <template>
198
+ <div class="mint-bio-template-experiment-workspace">
199
+ <div class="mint-bio-template-experiment-workspace__toolbar">
200
+ <AlertBox type="info" class="mint-bio-template-experiment-workspace__status">
201
+ {{ statusMessage }}
202
+ </AlertBox>
203
+
204
+ <div class="mint-bio-template-experiment-workspace__actions">
205
+ <BaseButton
206
+ variant="secondary"
207
+ :loading="resolvedLoading"
208
+ :disabled="!resolvedHasExperiment"
209
+ @click="handleLoad"
210
+ >
211
+ {{ loadLabel }}
212
+ </BaseButton>
213
+ <BaseButton variant="secondary" :loading="resolvedLoading" @click="handleReset">
214
+ {{ resetLabel }}
215
+ </BaseButton>
216
+ <BaseButton
217
+ variant="primary"
218
+ :loading="resolvedLoading"
219
+ :disabled="!resolvedHasExperiment"
220
+ @click="handleSave"
221
+ >
222
+ {{ saveLabel }}
223
+ </BaseButton>
224
+ </div>
225
+ </div>
226
+
227
+ <AlertBox v-if="resolvedError" type="error">
228
+ {{ resolvedError }}
229
+ </AlertBox>
230
+
231
+ <p v-if="showStatus" class="mint-bio-template-experiment-workspace__meta">
232
+ loaded: {{ resolvedLastLoadedAt?.toLocaleString() ?? 'not loaded' }} -
233
+ saved: {{ resolvedLastSavedAt?.toLocaleString() ?? 'not saved' }}
234
+ </p>
235
+
236
+ <div
237
+ v-if="showTemplateSummary"
238
+ class="mint-bio-template-experiment-workspace__templates"
239
+ >
240
+ <div
241
+ v-for="template in templateSummaries"
242
+ :key="template.id"
243
+ class="mint-bio-template-experiment-workspace__template"
244
+ >
245
+ <p class="mint-bio-template-experiment-workspace__template-id">
246
+ {{ template.id }}
247
+ </p>
248
+ <p class="mint-bio-template-experiment-workspace__template-version">
249
+ v{{ template.version }}
250
+ </p>
251
+ </div>
252
+ </div>
253
+
254
+ <slot
255
+ :target="target"
256
+ :bindings="bindings"
257
+ :component-props="componentProps"
258
+ :component-props-by-id="componentPropsById"
259
+ :component-props-by-component="componentPropsByComponent"
260
+ :get-component-props="getComponentProps"
261
+ >
262
+ <BioTemplateRenderer
263
+ :target="target"
264
+ :dense="dense"
265
+ :readonly="readonly"
266
+ />
267
+ </slot>
268
+
269
+ <p class="mint-bio-template-experiment-workspace__meta">
270
+ experiment: {{ resolvedCurrentExperimentId ?? 'not selected' }}
271
+ </p>
272
+ </div>
273
+ </template>
274
+
275
+ <style scoped>
276
+ .mint-bio-template-experiment-workspace {
277
+ display: flex;
278
+ flex-direction: column;
279
+ gap: 1rem;
280
+ min-width: 0;
281
+ }
282
+
283
+ .mint-bio-template-experiment-workspace__toolbar {
284
+ display: flex;
285
+ align-items: center;
286
+ justify-content: space-between;
287
+ gap: 0.75rem;
288
+ }
289
+
290
+ .mint-bio-template-experiment-workspace__status {
291
+ flex: 1 1 auto;
292
+ min-width: 0;
293
+ }
294
+
295
+ .mint-bio-template-experiment-workspace__actions {
296
+ display: flex;
297
+ flex: 0 0 auto;
298
+ gap: 0.5rem;
299
+ }
300
+
301
+ .mint-bio-template-experiment-workspace__meta,
302
+ .mint-bio-template-experiment-workspace__template-version {
303
+ margin: 0;
304
+ color: var(--text-secondary, #64748b);
305
+ font-family: var(--font-mono, 'Fira Code', monospace);
306
+ font-size: 0.75rem;
307
+ }
308
+
309
+ .mint-bio-template-experiment-workspace__templates {
310
+ display: grid;
311
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
312
+ gap: 0.75rem;
313
+ }
314
+
315
+ .mint-bio-template-experiment-workspace__template {
316
+ min-width: 0;
317
+ padding: 1rem;
318
+ border: 1px solid var(--border-color, #e5e7eb);
319
+ border-radius: 0.5rem;
320
+ background: var(--bg-primary, #ffffff);
321
+ }
322
+
323
+ .mint-bio-template-experiment-workspace__template-id {
324
+ margin: 0;
325
+ color: var(--text-primary, #0f172a);
326
+ font-family: var(--font-mono, 'Fira Code', monospace);
327
+ font-size: 0.875rem;
328
+ }
329
+
330
+ @media (max-width: 48rem) {
331
+ .mint-bio-template-experiment-workspace__toolbar,
332
+ .mint-bio-template-experiment-workspace__actions {
333
+ align-items: stretch;
334
+ flex-direction: column;
335
+ }
336
+ }
337
+ </style>