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

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 (427) hide show
  1. package/README.md +225 -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/ComponentBindingRenderer.test.d.ts +1 -0
  19. package/dist/__tests__/components/ConcentrationInput.test.d.ts +1 -0
  20. package/dist/__tests__/components/ControlWorkspaceView.test.d.ts +1 -0
  21. package/dist/__tests__/components/DatePicker.test.d.ts +1 -0
  22. package/dist/__tests__/components/DateTimePicker.test.d.ts +1 -0
  23. package/dist/__tests__/components/DoseDesignWorkspaceView.test.d.ts +1 -0
  24. package/dist/__tests__/components/EmptyState.test.d.ts +1 -0
  25. package/dist/__tests__/components/ExperimentPopover.test.d.ts +1 -0
  26. package/dist/__tests__/components/FormBuilder.test.d.ts +1 -0
  27. package/dist/__tests__/components/GroupAssigner.test.d.ts +1 -0
  28. package/dist/__tests__/components/MultiSelect.test.d.ts +1 -0
  29. package/dist/__tests__/components/PluginWorkspaceView.test.d.ts +1 -0
  30. package/dist/__tests__/components/ProtocolStepEditor.test.d.ts +1 -0
  31. package/dist/__tests__/components/ReagentList.test.d.ts +1 -0
  32. package/dist/__tests__/components/SampleHierarchyTree.test.d.ts +1 -0
  33. package/dist/__tests__/components/SampleSelector.test.d.ts +1 -0
  34. package/dist/__tests__/components/SegmentedControl.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/experiment-utils.test.d.ts +1 -0
  40. package/dist/__tests__/composables/useApi.test.d.ts +1 -0
  41. package/dist/__tests__/composables/useBioTemplatePackWorkspace.test.d.ts +1 -0
  42. package/dist/__tests__/composables/useBioTemplatePresetWorkspace.test.d.ts +1 -0
  43. package/dist/__tests__/composables/useBioTemplateWorkspace.test.d.ts +1 -0
  44. package/dist/__tests__/composables/useCalendarGrid.test.d.ts +1 -0
  45. package/dist/__tests__/composables/useControlSchema.test.d.ts +1 -0
  46. package/dist/__tests__/composables/useDebouncedWatch.test.d.ts +1 -0
  47. package/dist/__tests__/composables/useDropdownState.test.d.ts +1 -0
  48. package/dist/__tests__/composables/useEventListener.test.d.ts +1 -0
  49. package/dist/__tests__/composables/useExpansionSet.test.d.ts +1 -0
  50. package/dist/__tests__/composables/useExperimentData.test.d.ts +1 -0
  51. package/dist/__tests__/composables/useExperimentSelector.test.d.ts +1 -0
  52. package/dist/__tests__/composables/useGroupAssignment.test.d.ts +1 -0
  53. package/dist/__tests__/composables/useListSelection.test.d.ts +1 -0
  54. package/dist/__tests__/composables/usePluginClient.test.d.ts +1 -0
  55. package/dist/__tests__/composables/usePluginConfig.test.d.ts +1 -0
  56. package/dist/__tests__/composables/useRequestSyncState.test.d.ts +1 -0
  57. package/dist/__tests__/composables/useSampleGroups.test.d.ts +1 -0
  58. package/dist/__tests__/composables/useSelectionLimit.test.d.ts +1 -0
  59. package/dist/__tests__/composables/useSortedItems.test.d.ts +1 -0
  60. package/dist/__tests__/composables/useTemplateCollection.test.d.ts +1 -0
  61. package/dist/__tests__/composables/useTextSearch.test.d.ts +1 -0
  62. package/dist/__tests__/composables/useTheme.test.d.ts +1 -0
  63. package/dist/__tests__/composables/useTimeUtils.test.d.ts +1 -0
  64. package/dist/__tests__/docs/frontendDocsCatalog.test.d.ts +1 -0
  65. package/dist/__tests__/templates/templates.test.d.ts +1 -0
  66. package/dist/{auth-DsI0rQ7_.js → auth-QQj2kkze.js} +12 -5
  67. package/dist/auth-QQj2kkze.js.map +1 -0
  68. package/dist/components/AppAvatarMenu.vue.d.ts +2 -7
  69. package/dist/components/AppContainer.vue.d.ts +1 -1
  70. package/dist/components/AppLayout.vue.d.ts +20 -1
  71. package/dist/components/AppSidebar.vue.d.ts +111 -6
  72. package/dist/components/AppTopBar.vue.d.ts +35 -22
  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 +119 -0
  83. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +93 -0
  84. package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +87 -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/CollapsibleCard.vue.d.ts +1 -1
  89. package/dist/components/ComponentBindingRenderer.vue.d.ts +44 -0
  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 +147 -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/DoseDesignWorkspaceView.vue.d.ts +149 -0
  97. package/dist/components/DropdownButton.vue.d.ts +3 -3
  98. package/dist/components/EmptyState.vue.d.ts +1 -2
  99. package/dist/components/ExperimentDataViewer.vue.d.ts +1 -1
  100. package/dist/components/ExperimentTimeline.vue.d.ts +2 -2
  101. package/dist/components/FileUploader.vue.d.ts +1 -1
  102. package/dist/components/FitPanel.vue.d.ts +1 -1
  103. package/dist/components/FormActions.vue.d.ts +4 -4
  104. package/dist/components/FormBuilder.vue.d.ts +31 -17
  105. package/dist/components/FormulaInput.vue.d.ts +2 -2
  106. package/dist/components/MoleculeInput.vue.d.ts +2 -2
  107. package/dist/components/MultiSelect.vue.d.ts +3 -3
  108. package/dist/components/NumberInput.vue.d.ts +1 -1
  109. package/dist/components/PlateMapEditor.vue.d.ts +1 -1
  110. package/dist/components/PluginWorkspaceView.vue.d.ts +310 -0
  111. package/dist/components/ProgressBar.vue.d.ts +1 -1
  112. package/dist/components/ProtocolStepEditor.vue.d.ts +3 -1
  113. package/dist/components/RackEditor.vue.d.ts +2 -2
  114. package/dist/components/SampleLegend.vue.d.ts +2 -2
  115. package/dist/components/ScheduleCalendar.vue.d.ts +2 -2
  116. package/dist/components/SegmentedControl.vue.d.ts +2 -2
  117. package/dist/components/SequenceInput.vue.d.ts +3 -3
  118. package/dist/components/SettingsModal.vue.d.ts +14 -6
  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 +6 -6
  125. package/dist/components/index.d.ts +9 -8
  126. package/dist/components/index.js +3 -3
  127. package/dist/components/{SettingsButton.vue.d.ts → internal/ActionItemInternal.vue.d.ts} +11 -9
  128. package/dist/components/{AppPageSelector.vue.d.ts → internal/AppPageSelectorInternal.vue.d.ts} +3 -6
  129. package/dist/components/{AppPillNav.vue.d.ts → internal/AppPillNavInternal.vue.d.ts} +4 -2
  130. package/dist/components/internal/CalendarGridPanelInternal.vue.d.ts +25 -0
  131. package/dist/components/{FormFieldRenderer.vue.d.ts → internal/FormFieldRendererInternal.vue.d.ts} +2 -2
  132. package/dist/components/{FormSection.vue.d.ts → internal/FormSectionRenderer.vue.d.ts} +7 -7
  133. package/dist/components/{WellEditPopup.vue.d.ts → internal/WellEditPopupInternal.vue.d.ts} +1 -1
  134. package/dist/{components-_XqPEhP9.js → components-BkGF4B4y.js} +9760 -8471
  135. package/dist/components-BkGF4B4y.js.map +1 -0
  136. package/dist/composables/experiment-utils.d.ts +8 -0
  137. package/dist/composables/index.d.ts +22 -5
  138. package/dist/composables/index.js +4 -3
  139. package/dist/composables/platformContextHelpers.d.ts +14 -0
  140. package/dist/composables/useAppExperiment.d.ts +31 -2
  141. package/dist/composables/useBioTemplateComponents.d.ts +22 -0
  142. package/dist/composables/useBioTemplateControls.d.ts +6 -0
  143. package/dist/composables/useBioTemplatePackWorkspace.d.ts +46 -0
  144. package/dist/composables/useBioTemplatePresetWorkspace.d.ts +75 -0
  145. package/dist/composables/useBioTemplateWorkspace.d.ts +51 -0
  146. package/dist/composables/useCalendarGrid.d.ts +26 -0
  147. package/dist/composables/useControlSchema.d.ts +343 -0
  148. package/dist/composables/useDebouncedWatch.d.ts +20 -0
  149. package/dist/composables/useDropdownState.d.ts +19 -0
  150. package/dist/composables/useEventListener.d.ts +13 -0
  151. package/dist/composables/useExpansionSet.d.ts +21 -0
  152. package/dist/composables/useExperimentData.d.ts +10 -0
  153. package/dist/composables/useExperimentSave.d.ts +31 -2
  154. package/dist/composables/useExperimentSelector.d.ts +20 -0
  155. package/dist/composables/useForm.d.ts +2 -0
  156. package/dist/composables/useGroupAssignment.d.ts +31 -0
  157. package/dist/composables/useListSelection.d.ts +35 -0
  158. package/dist/composables/usePlatformContext.d.ts +21 -3
  159. package/dist/composables/usePluginClient.d.ts +112 -0
  160. package/dist/composables/usePluginConfig.d.ts +12 -0
  161. package/dist/composables/useRequestSyncState.d.ts +34 -0
  162. package/dist/composables/useSampleGroups.d.ts +32 -0
  163. package/dist/composables/useSelectionLimit.d.ts +17 -0
  164. package/dist/composables/useSortedItems.d.ts +32 -0
  165. package/dist/composables/useTemplateCollection.d.ts +58 -0
  166. package/dist/composables/useTextSearch.d.ts +18 -0
  167. package/dist/composables/useTimeUtils.d.ts +8 -0
  168. package/dist/{composables-tiZqLu1M.js → composables-CHsME9H1.js} +240 -146
  169. package/dist/composables-CHsME9H1.js.map +1 -0
  170. package/dist/index.d.ts +6 -4
  171. package/dist/index.js +6 -5
  172. package/dist/install.d.ts +7 -2
  173. package/dist/install.js +2 -2
  174. package/dist/install.js.map +1 -1
  175. package/dist/stores/index.js +1 -1
  176. package/dist/stores/settings.d.ts +4 -1
  177. package/dist/styles.css +4746 -5514
  178. package/dist/templates/adapters.d.ts +43 -0
  179. package/dist/templates/builders.d.ts +63 -0
  180. package/dist/templates/catalog.d.ts +188 -0
  181. package/dist/templates/componentBindings.d.ts +71 -0
  182. package/dist/templates/controlSchemas.d.ts +25 -0
  183. package/dist/templates/index.d.ts +15 -0
  184. package/dist/templates/index.js +2 -0
  185. package/dist/templates/lookup.d.ts +4 -0
  186. package/dist/templates/packs.d.ts +18 -0
  187. package/dist/templates/presets.d.ts +90 -0
  188. package/dist/templates/types.d.ts +531 -0
  189. package/dist/templates-B5jmTWuk.js +9388 -0
  190. package/dist/templates-B5jmTWuk.js.map +1 -0
  191. package/dist/types/components.d.ts +26 -23
  192. package/dist/types/form-builder.d.ts +6 -8
  193. package/dist/types/index.d.ts +2 -2
  194. package/dist/types/platform.d.ts +7 -1
  195. package/dist/useScheduleDrag-BgzpQT53.js +4414 -0
  196. package/dist/useScheduleDrag-BgzpQT53.js.map +1 -0
  197. package/dist/utils/formModelSync.d.ts +5 -0
  198. package/dist/utils/items.d.ts +8 -0
  199. package/dist/utils/options.d.ts +6 -0
  200. package/dist/utils/pluginIcon.d.ts +9 -0
  201. package/package.json +7 -2
  202. package/src/__tests__/components/ActionItem.test.ts +99 -0
  203. package/src/__tests__/components/AppAvatarMenu.test.ts +27 -0
  204. package/src/__tests__/components/AppLayout.test.ts +44 -0
  205. package/src/__tests__/components/AppPageSelector.test.ts +134 -0
  206. package/src/__tests__/components/AppPillNav.test.ts +125 -0
  207. package/src/__tests__/components/AppPluginSwitcher.test.ts +44 -0
  208. package/src/__tests__/components/AppSidebar.test.ts +496 -0
  209. package/src/__tests__/components/AppToastContainer.test.ts +37 -0
  210. package/src/__tests__/components/AppTopBar.test.ts +455 -9
  211. package/src/__tests__/components/BaseRadioGroup.test.ts +25 -0
  212. package/src/__tests__/components/BaseSelect.test.ts +21 -0
  213. package/src/__tests__/components/BaseTabs.test.ts +25 -0
  214. package/src/__tests__/components/BatchProgressList.test.ts +52 -0
  215. package/src/__tests__/components/BioTemplateExperimentWorkspaceView.test.ts +159 -0
  216. package/src/__tests__/components/BioTemplatePackWorkspaceView.test.ts +175 -0
  217. package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +306 -0
  218. package/src/__tests__/components/BioTemplateRenderer.test.ts +71 -0
  219. package/src/__tests__/components/Breadcrumb.test.ts +23 -0
  220. package/src/__tests__/components/CalendarGridPanel.test.ts +36 -0
  221. package/src/__tests__/components/ComponentBindingRenderer.test.ts +161 -0
  222. package/src/__tests__/components/ConcentrationInput.test.ts +45 -0
  223. package/src/__tests__/components/ControlWorkspaceView.test.ts +1102 -0
  224. package/src/__tests__/components/DataFrame.test.ts +11 -0
  225. package/src/__tests__/components/DatePicker.test.ts +45 -0
  226. package/src/__tests__/components/DateTimePicker.test.ts +48 -0
  227. package/src/__tests__/components/DoseDesignWorkspaceView.test.ts +185 -0
  228. package/src/__tests__/components/DropdownButton.test.ts +23 -0
  229. package/src/__tests__/components/EmptyState.test.ts +23 -0
  230. package/src/__tests__/components/ExperimentPopover.test.ts +56 -0
  231. package/src/__tests__/components/FormBuilder.test.ts +296 -0
  232. package/src/__tests__/components/GroupAssigner.test.ts +30 -0
  233. package/src/__tests__/components/MultiSelect.test.ts +48 -0
  234. package/src/__tests__/components/PluginWorkspaceView.test.ts +548 -0
  235. package/src/__tests__/components/ProtocolStepEditor.test.ts +33 -0
  236. package/src/__tests__/components/ReagentList.test.ts +82 -0
  237. package/src/__tests__/components/SampleHierarchyTree.test.ts +53 -0
  238. package/src/__tests__/components/SampleSelector.test.ts +60 -0
  239. package/src/__tests__/components/SegmentedControl.test.ts +24 -0
  240. package/src/__tests__/components/SettingsModal.test.ts +296 -0
  241. package/src/__tests__/components/TagsInput.test.ts +75 -0
  242. package/src/__tests__/components/ThemeToggle.test.ts +47 -0
  243. package/src/__tests__/components/TimePicker.test.ts +38 -0
  244. package/src/__tests__/composables/experiment-utils.test.ts +30 -0
  245. package/src/__tests__/composables/useApi.test.ts +30 -0
  246. package/src/__tests__/composables/useAppExperiment.test.ts +100 -1
  247. package/src/__tests__/composables/useBioTemplatePackWorkspace.test.ts +125 -0
  248. package/src/__tests__/composables/useBioTemplatePresetWorkspace.test.ts +199 -0
  249. package/src/__tests__/composables/useBioTemplateWorkspace.test.ts +104 -0
  250. package/src/__tests__/composables/useCalendarGrid.test.ts +38 -0
  251. package/src/__tests__/composables/useControlSchema.test.ts +1033 -0
  252. package/src/__tests__/composables/useDebouncedWatch.test.ts +93 -0
  253. package/src/__tests__/composables/useDropdownState.test.ts +95 -0
  254. package/src/__tests__/composables/useEventListener.test.ts +116 -0
  255. package/src/__tests__/composables/useExpansionSet.test.ts +62 -0
  256. package/src/__tests__/composables/useExperimentData.test.ts +4 -0
  257. package/src/__tests__/composables/useExperimentSave.test.ts +203 -8
  258. package/src/__tests__/composables/useExperimentSelector.test.ts +164 -0
  259. package/src/__tests__/composables/useForm.test.ts +58 -0
  260. package/src/__tests__/composables/useFormBuilder.test.ts +77 -0
  261. package/src/__tests__/composables/useGroupAssignment.test.ts +73 -0
  262. package/src/__tests__/composables/useListSelection.test.ts +66 -0
  263. package/src/__tests__/composables/usePluginClient.test.ts +541 -0
  264. package/src/__tests__/composables/usePluginConfig.test.ts +5 -0
  265. package/src/__tests__/composables/useRequestSyncState.test.ts +92 -0
  266. package/src/__tests__/composables/useSampleGroups.test.ts +66 -0
  267. package/src/__tests__/composables/useSelectionLimit.test.ts +41 -0
  268. package/src/__tests__/composables/useSortedItems.test.ts +87 -0
  269. package/src/__tests__/composables/useTemplateCollection.test.ts +147 -0
  270. package/src/__tests__/composables/useTextSearch.test.ts +55 -0
  271. package/src/__tests__/composables/useTheme.test.ts +91 -0
  272. package/src/__tests__/composables/useTimeUtils.test.ts +35 -0
  273. package/src/__tests__/docs/frontendDocsCatalog.test.ts +324 -0
  274. package/src/__tests__/fixtures/templates/dose-response.json +81 -0
  275. package/src/__tests__/fixtures/templates/plate-map.json +54 -0
  276. package/src/__tests__/fixtures/templates/qpcr-plate.json +96 -0
  277. package/src/__tests__/fixtures/templates/sample-sheet.json +71 -0
  278. package/src/__tests__/templates/templates.test.ts +1055 -0
  279. package/src/components/AppAvatarMenu.vue +15 -69
  280. package/src/components/AppLayout.story.vue +64 -25
  281. package/src/components/AppLayout.vue +83 -2
  282. package/src/components/AppPluginSwitcher.vue +41 -145
  283. package/src/components/AppSidebar.story.vue +203 -1
  284. package/src/components/AppSidebar.vue +320 -25
  285. package/src/components/{ToastNotification.story.vue → AppToastContainer.story.vue} +6 -6
  286. package/src/components/{ToastNotification.vue → AppToastContainer.vue} +1 -1
  287. package/src/components/AppTopBar.story.vue +7 -33
  288. package/src/components/AppTopBar.vue +104 -300
  289. package/src/components/BaseModal.vue +3 -5
  290. package/src/components/BaseRadioGroup.vue +7 -3
  291. package/src/components/BaseSelect.vue +11 -7
  292. package/src/components/BaseTabs.vue +6 -4
  293. package/src/components/BatchProgressList.vue +5 -8
  294. package/src/components/BioTemplateExperimentWorkspaceView.story.vue +123 -0
  295. package/src/components/BioTemplateExperimentWorkspaceView.vue +343 -0
  296. package/src/components/BioTemplatePackWorkspaceView.story.vue +107 -0
  297. package/src/components/BioTemplatePackWorkspaceView.vue +177 -0
  298. package/src/components/BioTemplatePresetWorkspaceView.story.vue +163 -0
  299. package/src/components/BioTemplatePresetWorkspaceView.vue +401 -0
  300. package/src/components/BioTemplateRenderer.story.vue +57 -0
  301. package/src/components/BioTemplateRenderer.vue +57 -0
  302. package/src/components/Breadcrumb.vue +14 -8
  303. package/src/components/ComponentBindingRenderer.story.vue +57 -0
  304. package/src/components/ComponentBindingRenderer.vue +308 -0
  305. package/src/components/ConcentrationInput.vue +27 -64
  306. package/src/components/ControlWorkspaceView.story.vue +347 -0
  307. package/src/components/ControlWorkspaceView.vue +378 -0
  308. package/src/components/DataFrame.vue +34 -50
  309. package/src/components/DatePicker.vue +59 -192
  310. package/src/components/DateTimePicker.vue +50 -171
  311. package/src/components/DoseDesignWorkspaceView.story.vue +77 -0
  312. package/src/components/DoseDesignWorkspaceView.vue +255 -0
  313. package/src/components/DropdownButton.vue +14 -32
  314. package/src/components/EmptyState.vue +4 -2
  315. package/src/components/ExperimentPopover.vue +7 -28
  316. package/src/components/ExperimentSelectorModal.vue +6 -5
  317. package/src/components/FormBuilder.story.vue +190 -0
  318. package/src/components/FormBuilder.vue +124 -27
  319. package/src/components/GroupAssigner.vue +24 -56
  320. package/src/components/MultiSelect.vue +17 -12
  321. package/src/components/PlateMapEditor.vue +3 -8
  322. package/src/components/PluginIcon.vue +2 -22
  323. package/src/components/PluginWorkspaceView.story.vue +334 -0
  324. package/src/components/PluginWorkspaceView.vue +708 -0
  325. package/src/components/ProtocolStepEditor.vue +13 -22
  326. package/src/components/ReagentList.vue +25 -33
  327. package/src/components/SampleHierarchyTree.vue +12 -23
  328. package/src/components/SampleSelector.vue +42 -122
  329. package/src/components/SegmentedControl.vue +7 -3
  330. package/src/components/SettingsModal.story.vue +88 -1
  331. package/src/components/SettingsModal.vue +120 -29
  332. package/src/components/TagsInput.vue +29 -14
  333. package/src/components/ThemeToggle.vue +9 -7
  334. package/src/components/TimePicker.vue +19 -41
  335. package/src/components/Tooltip.vue +7 -12
  336. package/src/components/WellPlate.vue +6 -12
  337. package/src/components/index.ts +9 -8
  338. package/src/components/internal/ActionItemInternal.vue +82 -0
  339. package/src/components/internal/AppPageSelectorInternal.vue +128 -0
  340. package/src/components/internal/AppPillNavInternal.vue +194 -0
  341. package/src/components/internal/CalendarGridPanelInternal.vue +120 -0
  342. package/src/components/{FormFieldRenderer.vue → internal/FormFieldRendererInternal.vue} +4 -12
  343. package/src/components/{FormSection.vue → internal/FormSectionRenderer.vue} +6 -18
  344. package/src/components/{WellEditPopup.vue → internal/WellEditPopupInternal.vue} +5 -10
  345. package/src/composables/experiment-utils.ts +26 -0
  346. package/src/composables/index.ts +229 -3
  347. package/src/composables/platformContextHelpers.ts +74 -0
  348. package/src/composables/useApi.ts +9 -2
  349. package/src/composables/useAppExperiment.ts +85 -13
  350. package/src/composables/useBioTemplateComponents.ts +105 -0
  351. package/src/composables/useBioTemplateControls.ts +41 -0
  352. package/src/composables/useBioTemplatePackWorkspace.ts +185 -0
  353. package/src/composables/useBioTemplatePresetWorkspace.ts +326 -0
  354. package/src/composables/useBioTemplateWorkspace.ts +141 -0
  355. package/src/composables/useCalendarGrid.ts +140 -0
  356. package/src/composables/useControlSchema.ts +1362 -0
  357. package/src/composables/useDebouncedWatch.ts +119 -0
  358. package/src/composables/useDropdownState.ts +83 -0
  359. package/src/composables/useEventListener.ts +111 -0
  360. package/src/composables/useExpansionSet.ts +117 -0
  361. package/src/composables/useExperimentData.ts +20 -11
  362. package/src/composables/useExperimentSave.ts +202 -50
  363. package/src/composables/useExperimentSelector.ts +86 -72
  364. package/src/composables/useForm.ts +49 -4
  365. package/src/composables/useFormBuilder.ts +93 -42
  366. package/src/composables/useGroupAssignment.ts +148 -0
  367. package/src/composables/useListSelection.ts +158 -0
  368. package/src/composables/usePluginClient.ts +466 -0
  369. package/src/composables/usePluginConfig.ts +34 -13
  370. package/src/composables/useRequestSyncState.ts +126 -0
  371. package/src/composables/useSampleGroups.ts +126 -0
  372. package/src/composables/useSelectionLimit.ts +57 -0
  373. package/src/composables/useSortedItems.ts +118 -0
  374. package/src/composables/useTemplateCollection.ts +229 -0
  375. package/src/composables/useTextSearch.ts +60 -0
  376. package/src/composables/useTheme.ts +2 -28
  377. package/src/composables/useTimeUtils.ts +26 -2
  378. package/src/composables/useWellPlateEditor.ts +13 -9
  379. package/src/index.ts +11 -348
  380. package/src/install.ts +11 -4
  381. package/src/stores/settings.ts +13 -9
  382. package/src/styles/components/app-layout.css +82 -0
  383. package/src/styles/components/app-page-selector.css +23 -0
  384. package/src/styles/components/app-pill-nav.css +77 -0
  385. package/src/styles/components/app-sidebar.css +119 -0
  386. package/src/styles/components/app-top-bar.css +0 -201
  387. package/src/styles/components/concentration-input.css +3 -142
  388. package/src/styles/components/empty-state.css +0 -16
  389. package/src/styles/components/theme-toggle.css +3 -66
  390. package/src/styles/index.css +0 -2
  391. package/src/templates/adapters.ts +785 -0
  392. package/src/templates/builders.ts +2149 -0
  393. package/src/templates/catalog.ts +245 -0
  394. package/src/templates/componentBindings.ts +653 -0
  395. package/src/templates/controlSchemas.ts +718 -0
  396. package/src/templates/index.ts +318 -0
  397. package/src/templates/lookup.ts +18 -0
  398. package/src/templates/packs.ts +156 -0
  399. package/src/templates/presets.ts +146 -0
  400. package/src/templates/types.ts +668 -0
  401. package/src/types/components.ts +39 -27
  402. package/src/types/form-builder.ts +7 -2
  403. package/src/types/index.ts +13 -3
  404. package/src/types/platform.ts +7 -1
  405. package/src/utils/formModelSync.ts +52 -0
  406. package/src/utils/items.ts +28 -0
  407. package/src/utils/options.ts +23 -0
  408. package/src/utils/pluginIcon.ts +30 -0
  409. package/dist/__tests__/composables/usePluginApi.test.d.ts +0 -13
  410. package/dist/auth-DsI0rQ7_.js.map +0 -1
  411. package/dist/components/GroupingModal.vue.d.ts +0 -12
  412. package/dist/components-_XqPEhP9.js.map +0 -1
  413. package/dist/composables/usePluginApi.d.ts +0 -29
  414. package/dist/composables-tiZqLu1M.js.map +0 -1
  415. package/dist/useScheduleDrag-CA9sGNJG.js +0 -7181
  416. package/dist/useScheduleDrag-CA9sGNJG.js.map +0 -1
  417. package/src/__tests__/composables/usePluginApi.test.ts +0 -81
  418. package/src/components/AppPageSelector.vue +0 -159
  419. package/src/components/AppPillNav.vue +0 -66
  420. package/src/components/GroupingModal.story.vue +0 -52
  421. package/src/components/GroupingModal.vue +0 -422
  422. package/src/components/SettingsButton.story.vue +0 -58
  423. package/src/components/SettingsButton.vue +0 -76
  424. package/src/composables/usePluginApi.ts +0 -39
  425. package/src/styles/components/grouping-modal.css +0 -323
  426. package/src/styles/components/settings-button.css +0 -94
  427. /package/dist/components/{ToastNotification.vue.d.ts → AppToastContainer.vue.d.ts} +0 -0
@@ -0,0 +1,401 @@
1
+ <script setup lang="ts">
2
+ /** Complete editable WellPlate/DoseCalculator workspace for dose design that rebuilds generated AppSidebar preset wiring when preset props load late. */
3
+ import { computed, effectScope, onScopeDispose, shallowRef, toRaw, unref, watch, type EffectScope } from 'vue'
4
+ import type { BioTemplateControlValues, TemplatePresetId } from '../templates'
5
+ import type {
6
+ UseBioTemplatePresetWorkspaceOptions,
7
+ UseBioTemplatePresetWorkspaceReturn,
8
+ } from '../composables/useBioTemplatePresetWorkspace'
9
+ import { useBioTemplatePresetWorkspace } from '../composables/useBioTemplatePresetWorkspace'
10
+ import AlertBox from './AlertBox.vue'
11
+ import AppSidebar from './AppSidebar.vue'
12
+ import BaseButton from './BaseButton.vue'
13
+ import BioTemplateRenderer from './BioTemplateRenderer.vue'
14
+ import AppPillNavInternal from './internal/AppPillNavInternal.vue'
15
+
16
+ type BioTemplatePresetSidebarVariant = 'default' | 'analysis'
17
+
18
+ interface BioTemplatePresetWorkspaceSlotProps {
19
+ workspace: UseBioTemplatePresetWorkspaceReturn
20
+ bindings: UseBioTemplatePresetWorkspaceReturn['bindings']
21
+ collection: UseBioTemplatePresetWorkspaceReturn['collection']['value']
22
+ renderer: UseBioTemplatePresetWorkspaceReturn['renderer']['value']
23
+ componentBindingsById: UseBioTemplatePresetWorkspaceReturn['componentBindingsById']['value']
24
+ componentProps: UseBioTemplatePresetWorkspaceReturn['componentProps']['value']
25
+ componentPropsById: UseBioTemplatePresetWorkspaceReturn['componentPropsById']['value']
26
+ componentPropsByComponent: UseBioTemplatePresetWorkspaceReturn['componentPropsByComponent']['value']
27
+ getComponentProps: UseBioTemplatePresetWorkspaceReturn['getComponentProps']
28
+ }
29
+
30
+ interface Props {
31
+ /** Workspace returned by useBioTemplatePresetWorkspace(). Use for full manual control. */
32
+ workspace?: UseBioTemplatePresetWorkspaceReturn
33
+ /** Built-in preset id used to create the workspace when workspace is not provided. */
34
+ preset?: TemplatePresetId
35
+ /** Options passed to the internally generated useBioTemplatePresetWorkspace() call. */
36
+ workspaceOptions?: UseBioTemplatePresetWorkspaceOptions
37
+ /** Initial control values for the internally generated preset workspace. */
38
+ initialValues?: BioTemplateControlValues
39
+ /** External control values for the internally generated preset workspace. Supports default v-model. */
40
+ modelValue?: BioTemplateControlValues
41
+ /** External control values for the internally generated preset workspace. Supports v-model:values. */
42
+ values?: BioTemplateControlValues
43
+ /** Label shown in the status banner. Defaults to the humanized preset id. */
44
+ label?: string
45
+ /** Sidebar CSS width. */
46
+ sidebarWidth?: string
47
+ /** AppSidebar visual preset. `analysis` matches the LEAF-style MINT analysis sidebar design language. */
48
+ sidebarVariant?: BioTemplatePresetSidebarVariant
49
+ /** Compact sidebar and preview layout. */
50
+ dense?: boolean
51
+ /** Render preview components in read-only mode. */
52
+ readonly?: boolean
53
+ /** Show save timestamp. */
54
+ showStatus?: boolean
55
+ /** Show cards for templates included in the preset collection. */
56
+ showTemplateSummary?: boolean
57
+ /** Show component binding count. */
58
+ showComponentSummary?: boolean
59
+ saveLabel?: string
60
+ resetLabel?: string
61
+ }
62
+
63
+ const emit = defineEmits<{
64
+ /** Emitted when generated preset controls change through the embedded sidebar or reset action. */
65
+ 'update:modelValue': [values: BioTemplateControlValues]
66
+ /** Emitted when generated preset controls change through the embedded sidebar or reset action. */
67
+ 'update:values': [values: BioTemplateControlValues]
68
+ }>()
69
+
70
+ defineSlots<{
71
+ default?: (props: BioTemplatePresetWorkspaceSlotProps) => unknown
72
+ }>()
73
+
74
+ const props = withDefaults(defineProps<Props>(), {
75
+ workspace: undefined,
76
+ preset: 'wellplate-screen',
77
+ workspaceOptions: () => ({}),
78
+ initialValues: undefined,
79
+ modelValue: undefined,
80
+ values: undefined,
81
+ sidebarWidth: '320px',
82
+ sidebarVariant: 'analysis',
83
+ dense: true,
84
+ readonly: true,
85
+ showStatus: true,
86
+ showTemplateSummary: true,
87
+ showComponentSummary: false,
88
+ saveLabel: 'Save',
89
+ resetLabel: 'Reset defaults',
90
+ })
91
+
92
+ const externalValues = computed(() => props.modelValue ?? props.values)
93
+ const resolvedWorkspaceOptions = computed<UseBioTemplatePresetWorkspaceOptions>(() => {
94
+ if (props.initialValues === undefined && externalValues.value === undefined) return props.workspaceOptions
95
+
96
+ return {
97
+ ...props.workspaceOptions,
98
+ initialValues: {
99
+ ...(props.workspaceOptions.initialValues ?? {}),
100
+ ...(props.initialValues ?? {}),
101
+ ...(externalValues.value ?? {}),
102
+ },
103
+ }
104
+ })
105
+
106
+ let generatedWorkspaceScope: EffectScope | undefined
107
+
108
+ function createGeneratedWorkspace(): UseBioTemplatePresetWorkspaceReturn {
109
+ generatedWorkspaceScope?.stop()
110
+ generatedWorkspaceScope = effectScope()
111
+ return generatedWorkspaceScope.run(() => useBioTemplatePresetWorkspace(props.preset, resolvedWorkspaceOptions.value))!
112
+ }
113
+
114
+ const generatedWorkspace = shallowRef<UseBioTemplatePresetWorkspaceReturn>(createGeneratedWorkspace())
115
+ const resolvedWorkspace = computed(() => props.workspace ?? generatedWorkspace.value)
116
+
117
+ watch(
118
+ [() => props.preset, () => props.workspaceOptions, () => props.initialValues],
119
+ () => {
120
+ generatedWorkspace.value = createGeneratedWorkspace()
121
+ },
122
+ { deep: true },
123
+ )
124
+
125
+ onScopeDispose(() => generatedWorkspaceScope?.stop())
126
+
127
+ watch(
128
+ externalValues,
129
+ (values) => {
130
+ if (values === undefined || props.workspace !== undefined) return
131
+ if (recordsEqual(toPlainRecord(generatedWorkspace.value.controlValues.value), values)) return
132
+ generatedWorkspace.value.setControlValues(values)
133
+ },
134
+ { deep: true },
135
+ )
136
+
137
+ watch(
138
+ () => generatedWorkspace.value.controlValues.value,
139
+ (values) => {
140
+ if (props.workspace !== undefined) return
141
+ const nextValues = toPlainRecord(values)
142
+ if (externalValues.value !== undefined && recordsEqual(nextValues, externalValues.value)) return
143
+ emit('update:modelValue', nextValues)
144
+ emit('update:values', nextValues)
145
+ },
146
+ { deep: true },
147
+ )
148
+
149
+ const presetId = computed(() => resolvedWorkspace.value.presetId)
150
+ const label = computed(() => props.label ?? unref(resolvedWorkspace.value.presetLabel))
151
+ const collection = computed(() => unref(resolvedWorkspace.value.collection))
152
+ const templateIds = computed(() => unref(resolvedWorkspace.value.templateIds))
153
+ const currentExperimentId = computed(() => unref(resolvedWorkspace.value.currentExperimentId))
154
+ const hasCurrentExperiment = computed(() => unref(resolvedWorkspace.value.hasCurrentExperiment))
155
+ const isSaving = computed(() => unref(resolvedWorkspace.value.saving))
156
+ const error = computed(() => unref(resolvedWorkspace.value.error))
157
+ const lastSavedAt = computed(() => unref(resolvedWorkspace.value.lastSavedAt))
158
+ const renderer = computed(() => unref(resolvedWorkspace.value.renderer))
159
+ const componentBindingsById = computed(() => unref(resolvedWorkspace.value.componentBindingsById))
160
+ const componentProps = computed(() => unref(resolvedWorkspace.value.componentProps))
161
+ const componentPropsById = computed(() => unref(resolvedWorkspace.value.componentPropsById))
162
+ const componentPropsByComponent = computed(() => unref(resolvedWorkspace.value.componentPropsByComponent))
163
+ const componentPropsCount = computed(() => unref(resolvedWorkspace.value.componentProps).length)
164
+ const bindings = computed(() => resolvedWorkspace.value.bindings)
165
+
166
+ function toPlainRecord(value: Record<string, unknown>): Record<string, unknown> {
167
+ return toPlain(value) as Record<string, unknown>
168
+ }
169
+
170
+ function toPlain(value: unknown): unknown {
171
+ const raw = toRaw(value)
172
+ if (Array.isArray(raw)) return raw.map(item => toPlain(item))
173
+ if (raw && typeof raw === 'object') {
174
+ return Object.fromEntries(
175
+ Object.entries(raw as Record<string, unknown>).map(([key, item]) => [key, toPlain(item)])
176
+ )
177
+ }
178
+ return raw
179
+ }
180
+
181
+ function recordsEqual(left: Record<string, unknown>, right: Record<string, unknown>): boolean {
182
+ const leftKeys = Object.keys(left)
183
+ const rightKeys = Object.keys(right)
184
+ if (leftKeys.length !== rightKeys.length) return false
185
+ return leftKeys.every(key => valuesEqual(left[key], right[key]))
186
+ }
187
+
188
+ function valuesEqual(left: unknown, right: unknown): boolean {
189
+ const leftRaw = toRaw(left)
190
+ const rightRaw = toRaw(right)
191
+
192
+ if (Object.is(leftRaw, rightRaw)) return true
193
+
194
+ if (Array.isArray(leftRaw) || Array.isArray(rightRaw)) {
195
+ if (!Array.isArray(leftRaw) || !Array.isArray(rightRaw)) return false
196
+ if (leftRaw.length !== rightRaw.length) return false
197
+ return leftRaw.every((item, index) => valuesEqual(item, rightRaw[index]))
198
+ }
199
+
200
+ if (isPlainRecord(leftRaw) || isPlainRecord(rightRaw)) {
201
+ if (!isPlainRecord(leftRaw) || !isPlainRecord(rightRaw)) return false
202
+ return recordsEqual(leftRaw, rightRaw)
203
+ }
204
+
205
+ return false
206
+ }
207
+
208
+ function isPlainRecord(value: unknown): value is Record<string, unknown> {
209
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
210
+ }
211
+ </script>
212
+
213
+ <template>
214
+ <div class="mint-bio-template-preset-workspace">
215
+ <div class="mint-bio-template-preset-workspace__toolbar">
216
+ <AlertBox type="info" class="mint-bio-template-preset-workspace__status">
217
+ {{ label }} preset saves to the current experiment design_data.
218
+ </AlertBox>
219
+
220
+ <div class="mint-bio-template-preset-workspace__actions">
221
+ <BaseButton
222
+ variant="secondary"
223
+ :disabled="isSaving"
224
+ @click="resolvedWorkspace.resetToDefaultCollection()"
225
+ >
226
+ {{ resetLabel }}
227
+ </BaseButton>
228
+ <BaseButton
229
+ variant="primary"
230
+ :loading="isSaving"
231
+ :disabled="!hasCurrentExperiment"
232
+ @click="resolvedWorkspace.saveCurrent()"
233
+ >
234
+ {{ saveLabel }}
235
+ </BaseButton>
236
+ </div>
237
+ </div>
238
+
239
+ <AlertBox v-if="error" type="error">
240
+ {{ error }}
241
+ </AlertBox>
242
+
243
+ <p v-if="showStatus" class="mint-bio-template-preset-workspace__meta">
244
+ saved: {{ lastSavedAt?.toLocaleString() ?? 'not saved' }}
245
+ </p>
246
+
247
+ <div class="mint-bio-template-preset-workspace__main">
248
+ <AppSidebar
249
+ v-bind="resolvedWorkspace.sidebar"
250
+ :variant="sidebarVariant"
251
+ :floating="false"
252
+ :width="sidebarWidth"
253
+ :dense="dense"
254
+ >
255
+ <template #header>
256
+ <p class="mint-bio-template-preset-workspace__sidebar-title">
257
+ Controls
258
+ </p>
259
+ <AppPillNavInternal
260
+ v-if="resolvedWorkspace.pillNav.items.length > 1"
261
+ class="mint-bio-template-preset-workspace__view-nav"
262
+ :items="resolvedWorkspace.pillNav.items"
263
+ :current-item-id="resolvedWorkspace.pillNav.currentItemId"
264
+ @select="resolvedWorkspace.pillNav.onSelect"
265
+ />
266
+ <p class="mint-bio-template-preset-workspace__sidebar-subtitle">
267
+ {{ presetId }}
268
+ </p>
269
+ </template>
270
+ </AppSidebar>
271
+
272
+ <slot
273
+ :workspace="resolvedWorkspace"
274
+ :bindings="bindings"
275
+ :collection="collection"
276
+ :renderer="renderer"
277
+ :component-bindings-by-id="componentBindingsById"
278
+ :component-props="componentProps"
279
+ :component-props-by-id="componentPropsById"
280
+ :component-props-by-component="componentPropsByComponent"
281
+ :get-component-props="resolvedWorkspace.getComponentProps"
282
+ >
283
+ <BioTemplateRenderer
284
+ v-bind="renderer"
285
+ :dense="dense"
286
+ :readonly="readonly"
287
+ />
288
+ </slot>
289
+ </div>
290
+
291
+ <div
292
+ v-if="showTemplateSummary"
293
+ class="mint-bio-template-preset-workspace__templates"
294
+ >
295
+ <div
296
+ v-for="templateId in templateIds"
297
+ :key="templateId"
298
+ class="mint-bio-template-preset-workspace__template"
299
+ >
300
+ <p class="mint-bio-template-preset-workspace__template-id">
301
+ {{ templateId }}
302
+ </p>
303
+ <p class="mint-bio-template-preset-workspace__template-meta">
304
+ {{ presetId }} - Experiment {{ currentExperimentId ?? 'not selected' }}
305
+ </p>
306
+ </div>
307
+ </div>
308
+
309
+ <p v-if="showComponentSummary" class="mint-bio-template-preset-workspace__meta">
310
+ component prop bindings: {{ componentPropsCount }}
311
+ </p>
312
+ </div>
313
+ </template>
314
+
315
+ <style scoped>
316
+ .mint-bio-template-preset-workspace {
317
+ display: flex;
318
+ flex-direction: column;
319
+ gap: 1rem;
320
+ min-width: 0;
321
+ }
322
+
323
+ .mint-bio-template-preset-workspace__toolbar {
324
+ display: flex;
325
+ align-items: center;
326
+ justify-content: space-between;
327
+ gap: 0.75rem;
328
+ }
329
+
330
+ .mint-bio-template-preset-workspace__status {
331
+ flex: 1 1 auto;
332
+ min-width: 0;
333
+ }
334
+
335
+ .mint-bio-template-preset-workspace__actions {
336
+ display: flex;
337
+ flex: 0 0 auto;
338
+ gap: 0.5rem;
339
+ }
340
+
341
+ .mint-bio-template-preset-workspace__meta,
342
+ .mint-bio-template-preset-workspace__sidebar-subtitle,
343
+ .mint-bio-template-preset-workspace__template-meta {
344
+ margin: 0;
345
+ color: var(--text-secondary, #64748b);
346
+ font-family: var(--font-mono, 'Fira Code', monospace);
347
+ font-size: 0.75rem;
348
+ }
349
+
350
+ .mint-bio-template-preset-workspace__main {
351
+ display: grid;
352
+ grid-template-columns: minmax(16rem, max-content) minmax(0, 1fr);
353
+ gap: 1rem;
354
+ align-items: start;
355
+ min-width: 0;
356
+ }
357
+
358
+ .mint-bio-template-preset-workspace__sidebar-title {
359
+ margin: 0;
360
+ color: var(--text-primary, #0f172a);
361
+ font-size: 0.875rem;
362
+ font-weight: 600;
363
+ }
364
+
365
+ .mint-bio-template-preset-workspace__view-nav {
366
+ margin-top: 0.5rem;
367
+ }
368
+
369
+ .mint-bio-template-preset-workspace__templates {
370
+ display: grid;
371
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
372
+ gap: 0.75rem;
373
+ }
374
+
375
+ .mint-bio-template-preset-workspace__template {
376
+ min-width: 0;
377
+ padding: 1rem;
378
+ border: 1px solid var(--border-color, #e5e7eb);
379
+ border-radius: 0.5rem;
380
+ background: var(--bg-primary, #ffffff);
381
+ }
382
+
383
+ .mint-bio-template-preset-workspace__template-id {
384
+ margin: 0;
385
+ color: var(--text-primary, #0f172a);
386
+ font-family: var(--font-mono, 'Fira Code', monospace);
387
+ font-size: 0.875rem;
388
+ }
389
+
390
+ @media (max-width: 48rem) {
391
+ .mint-bio-template-preset-workspace__toolbar,
392
+ .mint-bio-template-preset-workspace__actions {
393
+ align-items: stretch;
394
+ flex-direction: column;
395
+ }
396
+
397
+ .mint-bio-template-preset-workspace__main {
398
+ grid-template-columns: minmax(0, 1fr);
399
+ }
400
+ }
401
+ </style>
@@ -0,0 +1,57 @@
1
+ <script setup lang="ts">
2
+ import BioTemplateRenderer from './BioTemplateRenderer.vue'
3
+ import {
4
+ createLcmsBatchCollection,
5
+ createQpcrExpressionCollection,
6
+ createWellPlateScreenCollection,
7
+ } from '../templates'
8
+
9
+ const wellplateScreen = createWellPlateScreenCollection({
10
+ samples: ['Control', 'Treatment'],
11
+ compounds: {
12
+ 'Drug A': [10, 1, 0.1],
13
+ },
14
+ unit: 'uM',
15
+ })
16
+
17
+ const qpcrExpression = createQpcrExpressionCollection({
18
+ samples: ['Control', 'Treatment'],
19
+ targets: ['ACTB', 'GAPDH'],
20
+ replicates: 2,
21
+ })
22
+
23
+ const lcmsBatch = createLcmsBatchCollection({
24
+ samples: ['S001', 'S002', 'S003'],
25
+ features: ['Glucose', 'Lactate', 'Citrate'],
26
+ })
27
+ </script>
28
+
29
+ <template>
30
+ <Story title="Templates/BioTemplateRenderer">
31
+ <Variant title="Wellplate Screen">
32
+ <div style="padding: 2rem; background: var(--bg-primary, #f8fafc);">
33
+ <BioTemplateRenderer :target="wellplateScreen" />
34
+ </div>
35
+ </Variant>
36
+
37
+ <Variant title="qPCR Expression">
38
+ <div style="padding: 2rem; background: var(--bg-primary, #f8fafc);">
39
+ <BioTemplateRenderer
40
+ :target="qpcrExpression"
41
+ :include="['WellPlate', 'DataFrame']"
42
+ dense
43
+ />
44
+ </div>
45
+ </Variant>
46
+
47
+ <Variant title="LCMS Batch Tables">
48
+ <div style="padding: 2rem; background: var(--bg-primary, #f8fafc);">
49
+ <BioTemplateRenderer
50
+ :target="lcmsBatch"
51
+ :include="['DataFrame']"
52
+ dense
53
+ />
54
+ </div>
55
+ </Variant>
56
+ </Story>
57
+ </template>
@@ -0,0 +1,57 @@
1
+ <script setup lang="ts">
2
+ /** Render biology template envelopes with matching SDK components such as WellPlate, DoseCalculator, and DataFrame. */
3
+ import { computed } from 'vue'
4
+ import {
5
+ toBioTemplateComponentBindings,
6
+ } from '../templates/componentBindings'
7
+ import type {
8
+ BioTemplateEnvelope,
9
+ TemplateCollectionEnvelope,
10
+ } from '../templates/types'
11
+ import ComponentBindingRenderer from './ComponentBindingRenderer.vue'
12
+
13
+ interface Props {
14
+ /** Template envelope or template collection to render. */
15
+ target: BioTemplateEnvelope<unknown> | TemplateCollectionEnvelope
16
+ /** Optional allow-list of component names, for example ['WellPlate', 'DataFrame']. */
17
+ include?: string[]
18
+ /** Optional deny-list of component names. */
19
+ exclude?: string[]
20
+ /** Compact child component sizing. */
21
+ dense?: boolean
22
+ /** Prefer preview-safe props for editable components. */
23
+ readonly?: boolean
24
+ /** Show component/template labels above each rendered component. */
25
+ showHeaders?: boolean
26
+ /** Show binding descriptions in each header. */
27
+ showDescriptions?: boolean
28
+ /** Message shown when the target has no renderable bindings. */
29
+ emptyText?: string
30
+ }
31
+
32
+ const props = withDefaults(defineProps<Props>(), {
33
+ include: () => [],
34
+ exclude: () => [],
35
+ dense: false,
36
+ readonly: true,
37
+ showHeaders: true,
38
+ showDescriptions: true,
39
+ emptyText: 'No renderable biology template components.',
40
+ })
41
+
42
+ const componentBindings = computed(() => toBioTemplateComponentBindings(props.target))
43
+ </script>
44
+
45
+ <template>
46
+ <ComponentBindingRenderer
47
+ class="mint-bio-template-renderer"
48
+ :bindings="componentBindings"
49
+ :include="include"
50
+ :exclude="exclude"
51
+ :dense="dense"
52
+ :readonly="readonly"
53
+ :show-headers="showHeaders"
54
+ :show-descriptions="showDescriptions"
55
+ :empty-text="emptyText"
56
+ />
57
+ </template>
@@ -1,13 +1,15 @@
1
1
  <script setup lang="ts">
2
2
  /** Renders a breadcrumb trail where ancestors are links or emit-based buttons and the last item is the current page. */
3
- import type { BreadcrumbItem } from '../types'
3
+ import { computed } from 'vue'
4
+ import type { BreadcrumbItem, BreadcrumbItemInput } from '../types'
5
+ import { normalizeLabelItemInput } from '../utils/items'
4
6
 
5
7
  interface Props {
6
- items: BreadcrumbItem[]
8
+ items: BreadcrumbItemInput[]
7
9
  separator?: string
8
10
  }
9
11
 
10
- withDefaults(defineProps<Props>(), {
12
+ const props = withDefaults(defineProps<Props>(), {
11
13
  separator: '/',
12
14
  })
13
15
 
@@ -15,6 +17,10 @@ const emit = defineEmits<{
15
17
  navigate: [item: BreadcrumbItem]
16
18
  }>()
17
19
 
20
+ const normalizedItems = computed<BreadcrumbItem[]>(() =>
21
+ props.items.map(normalizeLabelItemInput)
22
+ )
23
+
18
24
  function handleClick(item: BreadcrumbItem) {
19
25
  if (!item.href) {
20
26
  emit('navigate', item)
@@ -26,20 +32,20 @@ function handleClick(item: BreadcrumbItem) {
26
32
  <nav class="mint-breadcrumb" aria-label="Breadcrumb">
27
33
  <ol class="mint-breadcrumb__list">
28
34
  <li
29
- v-for="(item, index) in items"
35
+ v-for="(item, index) in normalizedItems"
30
36
  :key="index"
31
37
  class="mint-breadcrumb__item"
32
38
  >
33
- <slot name="item" :item="item" :index="index" :is-last="index === items.length - 1">
39
+ <slot name="item" :item="item" :index="index" :is-last="index === normalizedItems.length - 1">
34
40
  <a
35
- v-if="item.href && index !== items.length - 1"
41
+ v-if="item.href && index !== normalizedItems.length - 1"
36
42
  :href="item.href"
37
43
  class="mint-breadcrumb__link"
38
44
  >
39
45
  {{ item.label }}
40
46
  </a>
41
47
  <button
42
- v-else-if="index !== items.length - 1"
48
+ v-else-if="index !== normalizedItems.length - 1"
43
49
  class="mint-breadcrumb__link"
44
50
  @click="handleClick(item)"
45
51
  >
@@ -54,7 +60,7 @@ function handleClick(item: BreadcrumbItem) {
54
60
  </span>
55
61
  </slot>
56
62
  <span
57
- v-if="index !== items.length - 1"
63
+ v-if="index !== normalizedItems.length - 1"
58
64
  class="mint-breadcrumb__separator"
59
65
  aria-hidden="true"
60
66
  >
@@ -0,0 +1,57 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref } from 'vue'
3
+ import ComponentBindingRenderer from './ComponentBindingRenderer.vue'
4
+ import {
5
+ defineDoseDesignControlModel,
6
+ useControlWorkspace,
7
+ } from '../composables/useControlSchema'
8
+
9
+ const model = defineDoseDesignControlModel({
10
+ selectedWells: ['A1', 'A2', 'B1'],
11
+ plateFormat: 96,
12
+ includeMolecularWeight: true,
13
+ })
14
+ const workspace = useControlWorkspace(model)
15
+
16
+ const state = ref({
17
+ dense: false,
18
+ readonly: true,
19
+ showHeaders: true,
20
+ showDescriptions: true,
21
+ layout: 'grid' as 'grid' | 'stack',
22
+ })
23
+
24
+ const bindings = computed(() => workspace.componentBindings.value)
25
+ </script>
26
+
27
+ <template>
28
+ <Story title="Layout/ComponentBindingRenderer">
29
+ <Variant title="Dose Design Bindings">
30
+ <div style="padding: 2rem; min-height: 640px; background: var(--bg-secondary, #f8fafc);">
31
+ <ComponentBindingRenderer
32
+ :bindings="bindings"
33
+ :dense="state.dense"
34
+ :readonly="state.readonly"
35
+ :show-headers="state.showHeaders"
36
+ :show-descriptions="state.showDescriptions"
37
+ :layout="state.layout"
38
+ />
39
+ </div>
40
+ </Variant>
41
+
42
+ <template #controls>
43
+ <HstCheckbox v-model="state.dense" title="Dense" />
44
+ <HstCheckbox v-model="state.readonly" title="Readonly" />
45
+ <HstCheckbox v-model="state.showHeaders" title="Headers" />
46
+ <HstCheckbox v-model="state.showDescriptions" title="Descriptions" />
47
+ <HstSelect
48
+ v-model="state.layout"
49
+ title="Layout"
50
+ :options="[
51
+ { label: 'Grid', value: 'grid' },
52
+ { label: 'Stack', value: 'stack' },
53
+ ]"
54
+ />
55
+ </template>
56
+ </Story>
57
+ </template>