@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
@@ -9,8 +9,14 @@ import BaseInput from './BaseInput.vue'
9
9
  import NumberInput from './NumberInput.vue'
10
10
  import FileUploader from './FileUploader.vue'
11
11
  import FormField from './FormField.vue'
12
+ import WellPlate from './WellPlate.vue'
13
+ import { defineControlModel, defineControls, getControlDefaults } from '../composables/useControlSchema'
14
+ import { useBioTemplateWorkspace } from '../composables/useBioTemplateWorkspace'
15
+ import { createWellPlateScreenCollection } from '../templates'
12
16
  import type { SidebarToolSection } from '../types'
13
17
 
18
+ type SidebarVariant = 'analysis' | 'default'
19
+
14
20
  /* --- Icon paths (Lucide-style) --- */
15
21
  const icons = {
16
22
  upload: ['M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4', 'M17 8l-5-5-5 5', 'M12 3v12'],
@@ -126,7 +132,98 @@ const polarity = ref('negative')
126
132
  const container = ref('vial')
127
133
  const expNumber = ref(1)
128
134
  const initials = ref('XP')
135
+ const sequencePrefix = ref('exp001_260210_XP')
136
+ const runMode = ref('balanced')
137
+ const runModeOptions = [
138
+ { value: 'fast', label: 'Fast' },
139
+ { value: 'balanced', label: 'Balanced' },
140
+ { value: 'qc', label: 'QC focused' },
141
+ ]
129
142
  const toggleState = reactive<Record<string, boolean>>({ naming: true, randomize: false })
143
+ const schemaControls = defineControls({
144
+ threshold: {
145
+ type: 'slider',
146
+ label: 'Threshold',
147
+ default: 0.05,
148
+ min: 0,
149
+ max: 1,
150
+ props: { step: 0.01 },
151
+ section: 'parameters',
152
+ sectionLabel: 'Parameters',
153
+ sectionSubtitle: 'Analysis controls',
154
+ view: 'analysis',
155
+ sidebar: {
156
+ icon: icons.settings,
157
+ iconColor: '#6366f1',
158
+ iconBg: '#e0e7ff',
159
+ },
160
+ },
161
+ method: {
162
+ label: 'Model',
163
+ default: 'linear',
164
+ options: ['linear', 'logistic', 'quadratic'],
165
+ required: true,
166
+ section: 'parameters',
167
+ view: 'analysis',
168
+ },
169
+ showOutliers: {
170
+ label: 'Show outliers',
171
+ default: true,
172
+ section: 'display',
173
+ sectionLabel: 'Display',
174
+ sectionSubtitle: 'Result filters',
175
+ view: 'analysis',
176
+ sidebar: {
177
+ icon: icons.zap,
178
+ iconColor: '#0ea5e9',
179
+ iconBg: '#e0f2fe',
180
+ defaultOpen: false,
181
+ },
182
+ },
183
+ })
184
+ const controlValues = ref<Record<string, unknown>>({ ...getControlDefaults(schemaControls) })
185
+ const modelDrivenSidebarModel = defineControlModel({
186
+ views: {
187
+ analysis: {
188
+ label: 'Analysis',
189
+ sections: {
190
+ parameters: {
191
+ label: 'Parameters',
192
+ description: 'Thresholds and scoring',
193
+ icon: icons.settings,
194
+ controls: {
195
+ threshold: { type: 'number', default: 0.05, min: 0, max: 1 },
196
+ method: ['linear', 'logistic', 'spline'],
197
+ },
198
+ },
199
+ filters: {
200
+ label: 'Filters',
201
+ description: 'Result cleanup',
202
+ sidebar: {
203
+ icon: icons.zap,
204
+ iconColor: '#0ea5e9',
205
+ iconBg: '#e0f2fe',
206
+ defaultOpen: false,
207
+ },
208
+ controls: {
209
+ showOutliers: true,
210
+ minPeakArea: { type: 'number', default: 1000, min: 0 },
211
+ },
212
+ },
213
+ },
214
+ },
215
+ },
216
+ })
217
+ const modelDrivenValues = ref<Record<string, unknown>>({})
218
+ const templateCollection = createWellPlateScreenCollection({
219
+ samples: ['Control', 'Treatment'],
220
+ compounds: { 'Drug A': [10, 1, 0.1] },
221
+ })
222
+ const templateWorkspace = useBioTemplateWorkspace(templateCollection)
223
+ const templateValues = ref<Record<string, unknown>>({ ...templateWorkspace.controls.initialValues })
224
+ const templateWellPlateProps = templateWorkspace.componentProps
225
+ .find(binding => binding.component === 'WellPlate')
226
+ ?.propsObject ?? {}
130
227
 
131
228
  function handleToggle(id: string, value: boolean) {
132
229
  toggleState[id] = value
@@ -135,8 +232,9 @@ function handleToggle(id: string, value: boolean) {
135
232
  function initSimpleToolkit() {
136
233
  return {
137
234
  activeView: 'analysis',
235
+ variant: 'analysis' as SidebarVariant,
138
236
  floating: false,
139
- width: '260px',
237
+ width: '20rem',
140
238
  side: 'left' as const,
141
239
  }
142
240
  }
@@ -218,6 +316,101 @@ function initSimpleToolkit() {
218
316
  </div>
219
317
  </Variant>
220
318
 
319
+ <Variant title="Schema Driven Controls">
320
+ <div style="padding: 2rem; height: 520px; position: relative; background: var(--bg-primary, #f1f5f9);">
321
+ <AppSidebar
322
+ variant="analysis"
323
+ title="Peak Picking"
324
+ subtitle="Current experiment"
325
+ :controls="schemaControls"
326
+ active-view="analysis"
327
+ v-model="controlValues"
328
+ />
329
+ </div>
330
+ </Variant>
331
+
332
+ <Variant title="Model Driven Analysis">
333
+ <div style="padding: 2rem; height: 560px; position: relative; background: var(--bg-primary, #f1f5f9);">
334
+ <AppSidebar
335
+ v-model="modelDrivenValues"
336
+ variant="analysis"
337
+ title="Peak Picking"
338
+ subtitle="Current experiment"
339
+ :model="modelDrivenSidebarModel"
340
+ />
341
+ </div>
342
+ </Variant>
343
+
344
+ <Variant title="Route Owned Shell">
345
+ <div style="padding: 2rem; height: 560px; display: flex; gap: 1rem; background: var(--bg-primary, #f1f5f9);">
346
+ <AppSidebar
347
+ variant="analysis"
348
+ title="Sequence"
349
+ subtitle="Acquisition run"
350
+ content-id="seqgen-sidebar"
351
+ show-when-empty
352
+ >
353
+ <div style="display: flex; flex-direction: column; gap: 0.75rem;">
354
+ <FormField label="File Prefix">
355
+ <BaseInput v-model="sequencePrefix" size="sm" />
356
+ </FormField>
357
+ <FormField label="Run Mode">
358
+ <BaseSelect v-model="runMode" :options="runModeOptions" size="sm" />
359
+ </FormField>
360
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem;">
361
+ <BaseButton size="sm" variant="secondary">NEG</BaseButton>
362
+ <BaseButton size="sm" variant="secondary">VIAL</BaseButton>
363
+ </div>
364
+ </div>
365
+
366
+ <template #footer>
367
+ <div style="display: flex; flex-direction: column; gap: 0.5rem;">
368
+ <BaseButton variant="cta" style="width: 100%;">Generate Sequence</BaseButton>
369
+ <BaseButton variant="ghost" size="sm" style="width: 100%;">Clear Draft</BaseButton>
370
+ </div>
371
+ </template>
372
+ </AppSidebar>
373
+
374
+ <div style="flex: 1; min-width: 0; border: 1px solid var(--border-color, #e5e7eb); border-radius: 0.5rem; background: var(--bg-card, #fff); padding: 1rem;">
375
+ <div style="display: flex; justify-content: space-between; gap: 1rem; align-items: center;">
376
+ <div>
377
+ <div style="font-size: 0.875rem; font-weight: 650; color: var(--text-primary, #111827);">MS queue</div>
378
+ <div style="font-size: 0.75rem; color: var(--text-muted, #6b7280);">{{ sequencePrefix }} · {{ runMode }}</div>
379
+ </div>
380
+ <BaseButton size="sm" variant="secondary">Preview CSV</BaseButton>
381
+ </div>
382
+ </div>
383
+ </div>
384
+ </Variant>
385
+
386
+ <Variant title="Template Driven Controls">
387
+ <div style="padding: 2rem; min-height: 560px; display: flex; gap: 1rem; background: var(--bg-primary, #f1f5f9);">
388
+ <AppSidebar
389
+ v-bind="templateWorkspace.sidebar"
390
+ active-view="design"
391
+ v-model="templateValues"
392
+ width="300px"
393
+ />
394
+
395
+ <div style="flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.75rem;">
396
+ <div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
397
+ <span
398
+ v-for="binding in templateWorkspace.componentBindings"
399
+ :key="binding.id"
400
+ style="font-size: 0.75rem; padding: 0.25rem 0.5rem; border: 1px solid var(--border-color, #e5e7eb); border-radius: 0.375rem; background: var(--bg-card, #fff); color: var(--text-secondary, #4b5563);"
401
+ >
402
+ {{ binding.component }}
403
+ </span>
404
+ </div>
405
+ <WellPlate
406
+ v-bind="templateWellPlateProps"
407
+ size="fill"
408
+ readonly
409
+ />
410
+ </div>
411
+ </div>
412
+ </Variant>
413
+
221
414
  <Variant title="Simple Toolkit" :init-state="initSimpleToolkit">
222
415
  <template #default="{ state }">
223
416
  <div style="padding: 2rem; height: 500px; position: relative; background: var(--bg-primary, #f1f5f9);">
@@ -241,6 +434,7 @@ function initSimpleToolkit() {
241
434
  </div>
242
435
  <AppSidebar
243
436
  :panels="simplePanels"
437
+ :variant="state.variant"
244
438
  :active-view="state.activeView"
245
439
  :floating="state.floating"
246
440
  :width="state.width"
@@ -271,6 +465,14 @@ function initSimpleToolkit() {
271
465
  title="Active View"
272
466
  :options="['analysis', 'results', 'settings'].map(v => ({ label: v, value: v }))"
273
467
  />
468
+ <HstSelect
469
+ v-model="state.variant"
470
+ title="Variant"
471
+ :options="[
472
+ { label: 'Analysis', value: 'analysis' },
473
+ { label: 'Default', value: 'default' },
474
+ ]"
475
+ />
274
476
  <HstCheckbox v-model="state.floating" title="Floating" />
275
477
  <HstText v-model="state.width" title="Width" />
276
478
  <HstSelect
@@ -2,10 +2,9 @@
2
2
  /**
3
3
  * AppSidebar - Context-sensitive toolkit panel
4
4
  *
5
- * Shows tool sections relevant to the active view. Sections are defined
6
- * via the `panels` config (mapping view IDs to section arrays) and rendered
7
- * as CollapsibleCards. Actual controls are provided through named slots:
8
- * `#section-{sectionId}`.
5
+ * Shows tool sections relevant to the active view. Sections are defined via
6
+ * the `panels` config and rendered as CollapsibleCards. Controls can be
7
+ * provided through named slots or auto-rendered from FormBuilder schemas.
9
8
  *
10
9
  * When the active view has no matching panels, the sidebar hides entirely.
11
10
  *
@@ -20,61 +19,287 @@
20
19
  * </template>
21
20
  * <template #header>Plugin Tools</template>
22
21
  * </AppSidebar>
22
+ *
23
+ * <!-- Direct schema-driven controls -->
24
+ * <AppSidebar :controls="controls" :active-view="activeTab" v-model="values" />
23
25
  * ```
24
26
  */
25
- import { computed } from 'vue'
26
- import type { SidebarToolSection } from '../types'
27
+ import { computed, ref, useSlots, type Slots } from 'vue'
28
+ import type { PillNavItem, SidebarToolSection } from '../types'
29
+ import type { FormEnhancements, FormSchema } from '../types/form-builder'
30
+ import {
31
+ controlsToSectionFormSchemas,
32
+ controlsToSidebarPanels,
33
+ defineControlModel,
34
+ getControlDefaults,
35
+ mergeControlWorkspaceOptions,
36
+ type ControlModel,
37
+ type ControlModelBinding,
38
+ type ControlSchema,
39
+ type ControlWorkspaceOptions,
40
+ } from '../composables/useControlSchema'
27
41
  import CollapsibleCard from './CollapsibleCard.vue'
42
+ import FormBuilder from './FormBuilder.vue'
28
43
 
29
44
  interface Props {
45
+ /** Optional chrome title rendered above generated sections. */
46
+ title?: string
47
+ /** Optional secondary chrome copy rendered below title. */
48
+ subtitle?: string
49
+ /** Optional compact badge/count rendered in the chrome header. */
50
+ badge?: string | number
51
+ /** Visual preset for common plugin sidebars. `analysis` preserves the LEAF-style MINT analysis sidebar design language. */
52
+ variant?: 'default' | 'analysis'
30
53
  /** Map of view IDs to their tool sections */
31
54
  panels?: Record<string, SidebarToolSection[]>
32
55
  /** Which view's panels to display */
33
56
  activeView?: string
34
- /** Floating variant with absolute positioning */
57
+ /** Floating variant with absolute positioning. Defaults to false for analysis variant. */
35
58
  floating?: boolean
36
59
  /** Compact layout: smaller headers, tighter spacing, no icon backgrounds */
37
60
  dense?: boolean
38
- /** Width when visible */
61
+ /** Width when visible. Defaults to 20rem for analysis variant, otherwise 280px. */
39
62
  width?: string
40
63
  /** Position sidebar on left or right side */
41
64
  side?: 'left' | 'right'
42
65
  /** Toggle state map: sectionId → boolean */
43
66
  toggleState?: Record<string, boolean>
67
+ /** Optional FormBuilder schemas keyed by section ID. Used when no section slot is provided. */
68
+ forms?: Record<string, FormSchema>
69
+ /** Generated view IDs from useControlSchema(). Consumed for clean v-bind ergonomics. */
70
+ viewIds?: string[]
71
+ /** Generated AppTopBar pillNav-compatible view items from useControlSchema(). Consumed for clean v-bind ergonomics. */
72
+ viewItems?: PillNavItem[]
73
+ /** Default view ID used when activeView is omitted. */
74
+ defaultView?: string
75
+ /** Model returned by defineControlModel(), or a raw nested ControlModel for one-step sidebar/form generation. */
76
+ model?: ControlModel | ControlModelBinding
77
+ /** Compact control schema. When provided, AppSidebar generates panels, section forms, and default values. */
78
+ controls?: ControlSchema
79
+ /** Options passed to compact control schema generation, including shared initialValues. */
80
+ controlOptions?: ControlWorkspaceOptions
81
+ /** DOM id for the scrollable content area. Use with Teleport when route/tab children own sidebar controls. */
82
+ contentId?: string
83
+ /** Render the sidebar shell even when no panel matches the active view. Useful for default-slot or Teleport-driven sidebars. */
84
+ showWhenEmpty?: boolean
85
+ /** Shared values for auto-rendered section forms. Supports default v-model. */
86
+ modelValue?: Record<string, unknown>
87
+ /** Shared values for auto-rendered section forms */
88
+ values?: Record<string, unknown>
89
+ /** Runtime FormBuilder enhancements for auto-rendered section forms */
90
+ formEnhancements?: FormEnhancements<Record<string, unknown>>
91
+ /** Show submit/cancel actions inside auto-rendered section forms */
92
+ showFormActions?: boolean
93
+ /** Loading/saving state for auto-rendered section forms */
94
+ formLoading?: boolean
95
+ /** Disabled state for auto-rendered section forms */
96
+ formDisabled?: boolean
97
+ /** Readonly state for auto-rendered section forms */
98
+ formReadonly?: boolean
99
+ /** Size passed to auto-rendered section forms */
100
+ formSize?: 'sm' | 'md' | 'lg'
101
+ /** Show a built-in collapse/expand button in the sidebar chrome. Defaults to true for analysis variant. */
102
+ collapsible?: boolean
103
+ /** Controlled collapsed state. */
104
+ collapsed?: boolean
105
+ /** Initial collapsed state when collapsed is uncontrolled. */
106
+ defaultCollapsed?: boolean
107
+ /** Width when collapsed. */
108
+ collapsedWidth?: string
109
+ /** Accessible label for the collapse action. */
110
+ collapseButtonLabel?: string
111
+ /** Accessible label for the expand action. */
112
+ expandButtonLabel?: string
44
113
  }
45
114
 
46
115
  const props = withDefaults(defineProps<Props>(), {
116
+ title: undefined,
117
+ subtitle: undefined,
118
+ badge: undefined,
119
+ variant: 'default',
47
120
  panels: () => ({}),
48
121
  activeView: '',
49
- floating: true,
122
+ floating: undefined,
50
123
  dense: false,
51
- width: '280px',
124
+ width: undefined,
52
125
  side: 'left',
53
126
  toggleState: () => ({}),
127
+ forms: () => ({}),
128
+ viewIds: () => [],
129
+ viewItems: () => [],
130
+ defaultView: '',
131
+ model: undefined,
132
+ controlOptions: () => ({}),
133
+ contentId: undefined,
134
+ showWhenEmpty: false,
135
+ modelValue: undefined,
136
+ values: () => ({}),
137
+ showFormActions: false,
138
+ formLoading: false,
139
+ formDisabled: false,
140
+ formReadonly: false,
141
+ formSize: 'sm',
142
+ collapsible: undefined,
143
+ collapsed: undefined,
144
+ defaultCollapsed: false,
145
+ collapsedWidth: '3rem',
146
+ collapseButtonLabel: 'Collapse sidebar',
147
+ expandButtonLabel: 'Expand sidebar',
54
148
  })
55
149
 
56
- defineEmits<{
150
+ const emit = defineEmits<{
57
151
  'update:toggle': [sectionId: string, value: boolean]
152
+ 'update:modelValue': [values: Record<string, unknown>]
153
+ 'update:values': [values: Record<string, unknown>]
154
+ 'update:collapsed': [value: boolean]
155
+ 'form-submit': [sectionId: string, values: Record<string, unknown>]
156
+ 'form-cancel': [sectionId: string]
58
157
  }>()
59
158
 
159
+ const slots: Slots = useSlots()
160
+ const internalCollapsed = ref(props.defaultCollapsed)
161
+ const collapsedModel = computed({
162
+ get: () => props.collapsed ?? internalCollapsed.value,
163
+ set: (value: boolean) => {
164
+ internalCollapsed.value = value
165
+ emit('update:collapsed', value)
166
+ },
167
+ })
168
+
169
+ const isAnalysisVariant = computed(() => props.variant === 'analysis')
170
+ const resolvedFloating = computed(() => props.floating ?? !isAnalysisVariant.value)
171
+ const resolvedWidth = computed(() => props.width ?? (isAnalysisVariant.value ? '20rem' : '280px'))
172
+ const resolvedCollapsible = computed(() => props.collapsible ?? isAnalysisVariant.value)
173
+
174
+ const resolvedModel = computed<ControlModelBinding | undefined>(() => {
175
+ if (props.model === undefined) return undefined
176
+ return isControlModelBinding(props.model) ? props.model : defineControlModel(props.model)
177
+ })
178
+
179
+ const resolvedControls = computed<ControlSchema | undefined>(() =>
180
+ props.controls ?? resolvedModel.value?.controls,
181
+ )
182
+
183
+ const resolvedControlOptions = computed<ControlWorkspaceOptions>(() =>
184
+ mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, props.controlOptions)
185
+ )
186
+
187
+ const generatedPanels = computed<Record<string, SidebarToolSection[]>>(() => {
188
+ if (!resolvedControls.value) return {}
189
+ return controlsToSidebarPanels(resolvedControls.value, resolvedControlOptions.value)
190
+ })
191
+
192
+ const generatedForms = computed<Record<string, FormSchema>>(() => {
193
+ if (!resolvedControls.value) return {}
194
+ return controlsToSectionFormSchemas(resolvedControls.value, resolvedControlOptions.value)
195
+ })
196
+
197
+ const generatedDefaults = computed<Record<string, unknown>>(() => {
198
+ if (!resolvedControls.value) return {}
199
+ return {
200
+ ...getControlDefaults(resolvedControls.value),
201
+ ...(resolvedControlOptions.value.initialValues ?? {}),
202
+ }
203
+ })
204
+
205
+ const resolvedPanels = computed<Record<string, SidebarToolSection[]>>(() =>
206
+ mergeSidebarPanels(generatedPanels.value, props.panels),
207
+ )
208
+
209
+ const resolvedForms = computed<Record<string, FormSchema>>(() => ({
210
+ ...generatedForms.value,
211
+ ...props.forms,
212
+ }))
213
+
214
+ const resolvedValues = computed<Record<string, unknown>>(() => ({
215
+ ...generatedDefaults.value,
216
+ ...(props.modelValue ?? props.values),
217
+ }))
218
+
219
+ const resolvedActiveView = computed(() => {
220
+ if (props.activeView) return props.activeView
221
+ if (props.defaultView) return props.defaultView
222
+ if (!resolvedControls.value) return ''
223
+ return firstVisibleViewId(resolvedPanels.value)
224
+ })
225
+
60
226
  const activeSections = computed<SidebarToolSection[]>(() => {
61
- if (!props.activeView || !props.panels[props.activeView]) return []
62
- return props.panels[props.activeView]
227
+ if (!resolvedActiveView.value || !resolvedPanels.value[resolvedActiveView.value]) return []
228
+ return resolvedPanels.value[resolvedActiveView.value]
63
229
  })
64
230
 
65
- const isVisible = computed(() => activeSections.value.length > 0)
231
+ const isVisible = computed<boolean>(() =>
232
+ activeSections.value.length > 0 || props.showWhenEmpty || Boolean(slots.default),
233
+ )
66
234
 
67
- const sidebarClasses = computed(() => [
235
+ const sidebarClasses = computed<string[]>(() => [
68
236
  'mint-sidebar',
69
237
  `mint-sidebar--${props.side}`,
70
- props.floating ? 'mint-sidebar--floating' : 'mint-sidebar--static',
238
+ `mint-sidebar--${props.variant}`,
239
+ resolvedFloating.value ? 'mint-sidebar--floating' : 'mint-sidebar--static',
71
240
  props.dense ? 'mint-sidebar--dense' : '',
241
+ resolvedCollapsible.value ? 'mint-sidebar--collapsible' : '',
242
+ collapsedModel.value ? 'mint-sidebar--collapsed' : '',
72
243
  !isVisible.value ? 'mint-sidebar--hidden' : '',
73
244
  ])
74
245
 
75
- const sidebarStyle = computed(() => ({
76
- width: props.width,
246
+ const sidebarStyle = computed<Record<string, string>>(() => ({
247
+ width: collapsedModel.value ? props.collapsedWidth : resolvedWidth.value,
77
248
  }))
249
+
250
+ function handleFormUpdate(values: Record<string, unknown>) {
251
+ const nextValues = { ...resolvedValues.value, ...values }
252
+ emit('update:modelValue', nextValues)
253
+ emit('update:values', nextValues)
254
+ }
255
+
256
+ function handleFormSubmit(sectionId: string, values: Record<string, unknown>) {
257
+ emit('form-submit', sectionId, values)
258
+ }
259
+
260
+ function handleFormCancel(sectionId: string) {
261
+ emit('form-cancel', sectionId)
262
+ }
263
+
264
+ function toggleCollapsed() {
265
+ collapsedModel.value = !collapsedModel.value
266
+ }
267
+
268
+ function expandCollapsed() {
269
+ collapsedModel.value = false
270
+ }
271
+
272
+ function mergeSidebarPanels(
273
+ generated: Record<string, SidebarToolSection[]>,
274
+ explicit: Record<string, SidebarToolSection[]>,
275
+ ): Record<string, SidebarToolSection[]> {
276
+ const merged: Record<string, SidebarToolSection[]> = {}
277
+ const viewIds = new Set([...Object.keys(generated), ...Object.keys(explicit)])
278
+
279
+ for (const viewId of viewIds) {
280
+ const sectionsById = new Map<string, SidebarToolSection>()
281
+ for (const section of generated[viewId] ?? []) {
282
+ sectionsById.set(section.id, section)
283
+ }
284
+ for (const section of explicit[viewId] ?? []) {
285
+ sectionsById.set(section.id, section)
286
+ }
287
+ merged[viewId] = [...sectionsById.values()]
288
+ }
289
+
290
+ return merged
291
+ }
292
+
293
+ function firstVisibleViewId(panels: Record<string, SidebarToolSection[]>): string {
294
+ for (const [viewId, sections] of Object.entries(panels)) {
295
+ if (sections.length > 0) return viewId
296
+ }
297
+ return ''
298
+ }
299
+
300
+ function isControlModelBinding(model: ControlModel | ControlModelBinding): model is ControlModelBinding {
301
+ return 'controls' in model && 'controlOptions' in model
302
+ }
78
303
  </script>
79
304
 
80
305
  <template>
@@ -82,13 +307,54 @@ const sidebarStyle = computed(() => ({
82
307
  :class="sidebarClasses"
83
308
  :style="sidebarStyle"
84
309
  >
85
- <!-- Header slot -->
86
- <div v-if="$slots.header" class="mint-sidebar__header">
87
- <slot name="header" />
310
+ <!-- Header slot / built-in chrome -->
311
+ <div
312
+ v-if="$slots.header || title || subtitle || badge !== undefined || resolvedCollapsible"
313
+ class="mint-sidebar__header"
314
+ >
315
+ <slot
316
+ name="header"
317
+ :collapsed="collapsedModel"
318
+ :toggle-collapsed="toggleCollapsed"
319
+ >
320
+ <div v-if="!collapsedModel" class="mint-sidebar__heading">
321
+ <div class="mint-sidebar__heading-copy">
322
+ <h2 v-if="title" class="mint-sidebar__title">{{ title }}</h2>
323
+ <p v-if="subtitle" class="mint-sidebar__subtitle">{{ subtitle }}</p>
324
+ </div>
325
+ <span v-if="badge !== undefined" class="mint-sidebar__badge">{{ badge }}</span>
326
+ </div>
327
+ <button
328
+ v-if="resolvedCollapsible"
329
+ type="button"
330
+ class="mint-sidebar__collapse-button"
331
+ :aria-label="collapsedModel ? expandButtonLabel : collapseButtonLabel"
332
+ :aria-expanded="!collapsedModel"
333
+ @click="toggleCollapsed"
334
+ >
335
+ <svg
336
+ class="mint-sidebar__collapse-icon"
337
+ :class="{ 'mint-sidebar__collapse-icon--collapsed': collapsedModel }"
338
+ viewBox="0 0 24 24"
339
+ fill="none"
340
+ stroke="currentColor"
341
+ stroke-width="2"
342
+ stroke-linecap="round"
343
+ stroke-linejoin="round"
344
+ aria-hidden="true"
345
+ >
346
+ <path d="M11 19l-7-7 7-7m8 14l-7-7 7-7" />
347
+ </svg>
348
+ </button>
349
+ </slot>
88
350
  </div>
89
351
 
90
352
  <!-- Tool sections -->
91
- <div class="mint-sidebar__sections">
353
+ <div
354
+ v-if="!collapsedModel"
355
+ :id="contentId"
356
+ class="mint-sidebar__sections"
357
+ >
92
358
  <CollapsibleCard
93
359
  v-for="section in activeSections"
94
360
  :key="section.id"
@@ -101,14 +367,43 @@ const sidebarStyle = computed(() => ({
101
367
  :default-open="section.defaultOpen !== false"
102
368
  :show-toggle="section.showToggle"
103
369
  :toggle-value="toggleState[section.id] ?? false"
104
- @update:toggle-value="$emit('update:toggle', section.id, $event)"
370
+ @update:toggle-value="emit('update:toggle', section.id, $event)"
105
371
  >
106
- <slot :name="`section-${section.id}`" />
372
+ <slot :name="`section-${section.id}`">
373
+ <FormBuilder
374
+ v-if="resolvedForms[section.id]"
375
+ :model-value="resolvedValues"
376
+ :schema="resolvedForms[section.id]"
377
+ :enhancements="formEnhancements"
378
+ :loading="formLoading"
379
+ :disabled="formDisabled"
380
+ :readonly="formReadonly"
381
+ :size="formSize"
382
+ :show-actions="showFormActions"
383
+ @update:model-value="handleFormUpdate"
384
+ @submit="handleFormSubmit(section.id, $event)"
385
+ @cancel="handleFormCancel(section.id)"
386
+ />
387
+ </slot>
107
388
  </CollapsibleCard>
389
+
390
+ <slot
391
+ :sections="activeSections"
392
+ :active-view="resolvedActiveView"
393
+ :values="resolvedValues"
394
+ />
395
+ </div>
396
+
397
+ <div v-else-if="$slots.collapsed" class="mint-sidebar__collapsed">
398
+ <slot
399
+ name="collapsed"
400
+ :sections="activeSections"
401
+ :expand="expandCollapsed"
402
+ />
108
403
  </div>
109
404
 
110
405
  <!-- Footer slot -->
111
- <div v-if="$slots.footer" class="mint-sidebar__footer">
406
+ <div v-if="!collapsedModel && $slots.footer" class="mint-sidebar__footer">
112
407
  <slot name="footer" />
113
408
  </div>
114
409
  </aside>