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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (399) hide show
  1. package/README.md +218 -6
  2. package/dist/__tests__/components/ActionItem.test.d.ts +1 -0
  3. package/dist/__tests__/components/AppAvatarMenu.test.d.ts +1 -0
  4. package/dist/__tests__/components/AppPageSelector.test.d.ts +1 -0
  5. package/dist/__tests__/components/AppPillNav.test.d.ts +1 -0
  6. package/dist/__tests__/components/AppPluginSwitcher.test.d.ts +1 -0
  7. package/dist/__tests__/components/AppToastContainer.test.d.ts +1 -0
  8. package/dist/__tests__/components/BaseRadioGroup.test.d.ts +1 -0
  9. package/dist/__tests__/components/BaseSelect.test.d.ts +1 -0
  10. package/dist/__tests__/components/BaseTabs.test.d.ts +1 -0
  11. package/dist/__tests__/components/BatchProgressList.test.d.ts +1 -0
  12. package/dist/__tests__/components/BioTemplateExperimentWorkspaceView.test.d.ts +1 -0
  13. package/dist/__tests__/components/BioTemplatePackWorkspaceView.test.d.ts +1 -0
  14. package/dist/__tests__/components/BioTemplatePresetWorkspaceView.test.d.ts +1 -0
  15. package/dist/__tests__/components/BioTemplateRenderer.test.d.ts +1 -0
  16. package/dist/__tests__/components/Breadcrumb.test.d.ts +1 -0
  17. package/dist/__tests__/components/CalendarGridPanel.test.d.ts +1 -0
  18. package/dist/__tests__/components/ConcentrationInput.test.d.ts +1 -0
  19. package/dist/__tests__/components/ControlWorkspaceView.test.d.ts +1 -0
  20. package/dist/__tests__/components/DatePicker.test.d.ts +1 -0
  21. package/dist/__tests__/components/DateTimePicker.test.d.ts +1 -0
  22. package/dist/__tests__/components/EmptyState.test.d.ts +1 -0
  23. package/dist/__tests__/components/ExperimentPopover.test.d.ts +1 -0
  24. package/dist/__tests__/components/FormBuilder.test.d.ts +1 -0
  25. package/dist/__tests__/components/FormCompatibility.test.d.ts +1 -0
  26. package/dist/__tests__/components/GroupAssigner.test.d.ts +1 -0
  27. package/dist/__tests__/components/GroupingModal.test.d.ts +1 -0
  28. package/dist/__tests__/components/MultiSelect.test.d.ts +1 -0
  29. package/dist/__tests__/components/ProtocolStepEditor.test.d.ts +1 -0
  30. package/dist/__tests__/components/ReagentList.test.d.ts +1 -0
  31. package/dist/__tests__/components/SampleHierarchyTree.test.d.ts +1 -0
  32. package/dist/__tests__/components/SampleSelector.test.d.ts +1 -0
  33. package/dist/__tests__/components/SegmentedControl.test.d.ts +1 -0
  34. package/dist/__tests__/components/SettingsButton.test.d.ts +1 -0
  35. package/dist/__tests__/components/SettingsModal.test.d.ts +1 -0
  36. package/dist/__tests__/components/TagsInput.test.d.ts +1 -0
  37. package/dist/__tests__/components/ThemeToggle.test.d.ts +1 -0
  38. package/dist/__tests__/components/TimePicker.test.d.ts +1 -0
  39. package/dist/__tests__/composables/useBioTemplatePackWorkspace.test.d.ts +1 -0
  40. package/dist/__tests__/composables/useBioTemplatePresetWorkspace.test.d.ts +1 -0
  41. package/dist/__tests__/composables/useBioTemplateWorkspace.test.d.ts +1 -0
  42. package/dist/__tests__/composables/useCalendarGrid.test.d.ts +1 -0
  43. package/dist/__tests__/composables/useControlSchema.test.d.ts +1 -0
  44. package/dist/__tests__/composables/useDebouncedWatch.test.d.ts +1 -0
  45. package/dist/__tests__/composables/useDropdownState.test.d.ts +1 -0
  46. package/dist/__tests__/composables/useEventListener.test.d.ts +1 -0
  47. package/dist/__tests__/composables/useExpansionSet.test.d.ts +1 -0
  48. package/dist/__tests__/composables/useExperimentData.test.d.ts +1 -0
  49. package/dist/__tests__/composables/useExperimentSelector.test.d.ts +1 -0
  50. package/dist/__tests__/composables/useGroupAssignment.test.d.ts +1 -0
  51. package/dist/__tests__/composables/useListSelection.test.d.ts +1 -0
  52. package/dist/__tests__/composables/usePluginClient.test.d.ts +1 -0
  53. package/dist/__tests__/composables/usePluginConfig.test.d.ts +1 -0
  54. package/dist/__tests__/composables/useRequestSyncState.test.d.ts +1 -0
  55. package/dist/__tests__/composables/useSampleGroups.test.d.ts +1 -0
  56. package/dist/__tests__/composables/useSelectionLimit.test.d.ts +1 -0
  57. package/dist/__tests__/composables/useSortedItems.test.d.ts +1 -0
  58. package/dist/__tests__/composables/useTemplateCollection.test.d.ts +1 -0
  59. package/dist/__tests__/composables/useTextSearch.test.d.ts +1 -0
  60. package/dist/__tests__/composables/useTheme.test.d.ts +1 -0
  61. package/dist/__tests__/composables/useTimeUtils.test.d.ts +1 -0
  62. package/dist/__tests__/docs/frontendDocsCatalog.test.d.ts +1 -0
  63. package/dist/__tests__/templates/templates.test.d.ts +1 -0
  64. package/dist/{auth-DsI0rQ7_.js → auth-QQj2kkze.js} +12 -5
  65. package/dist/auth-QQj2kkze.js.map +1 -0
  66. package/dist/components/ActionItem.vue.d.ts +32 -0
  67. package/dist/components/AppAvatarMenu.vue.d.ts +2 -7
  68. package/dist/components/AppPageSelector.vue.d.ts +3 -6
  69. package/dist/components/AppPillNav.vue.d.ts +2 -2
  70. package/dist/components/AppSidebar.vue.d.ts +56 -3
  71. package/dist/components/AppToastContainer.vue.d.ts +2 -0
  72. package/dist/components/AppTopBar.vue.d.ts +41 -10
  73. package/dist/components/BaseButton.vue.d.ts +1 -1
  74. package/dist/components/BaseCheckbox.vue.d.ts +1 -1
  75. package/dist/components/BaseInput.vue.d.ts +2 -2
  76. package/dist/components/BasePill.vue.d.ts +2 -2
  77. package/dist/components/BaseRadioGroup.vue.d.ts +3 -3
  78. package/dist/components/BaseSelect.vue.d.ts +3 -3
  79. package/dist/components/BaseTabs.vue.d.ts +2 -2
  80. package/dist/components/BaseTextarea.vue.d.ts +1 -1
  81. package/dist/components/BaseToggle.vue.d.ts +1 -1
  82. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +117 -0
  83. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +92 -0
  84. package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +82 -0
  85. package/dist/components/BioTemplateRenderer.vue.d.ts +29 -0
  86. package/dist/components/Breadcrumb.vue.d.ts +2 -2
  87. package/dist/components/Calendar.vue.d.ts +1 -1
  88. package/dist/components/CalendarGridPanel.vue.d.ts +25 -0
  89. package/dist/components/CollapsibleCard.vue.d.ts +1 -1
  90. package/dist/components/ConcentrationInput.vue.d.ts +2 -2
  91. package/dist/components/ConfirmDialog.vue.d.ts +2 -2
  92. package/dist/components/ControlWorkspaceView.vue.d.ts +130 -0
  93. package/dist/components/DatePicker.vue.d.ts +1 -1
  94. package/dist/components/DateTimePicker.vue.d.ts +3 -3
  95. package/dist/components/Divider.vue.d.ts +1 -1
  96. package/dist/components/DropdownButton.vue.d.ts +3 -3
  97. package/dist/components/EmptyState.vue.d.ts +1 -2
  98. package/dist/components/ExperimentDataViewer.vue.d.ts +1 -1
  99. package/dist/components/ExperimentTimeline.vue.d.ts +2 -2
  100. package/dist/components/FileUploader.vue.d.ts +1 -1
  101. package/dist/components/FitPanel.vue.d.ts +1 -1
  102. package/dist/components/FormActions.vue.d.ts +4 -4
  103. package/dist/components/FormBuilder.vue.d.ts +22 -8
  104. package/dist/components/FormFieldRenderer.vue.d.ts +7 -10
  105. package/dist/components/FormSection.vue.d.ts +11 -24
  106. package/dist/components/FormulaInput.vue.d.ts +2 -2
  107. package/dist/components/MoleculeInput.vue.d.ts +2 -2
  108. package/dist/components/MultiSelect.vue.d.ts +3 -3
  109. package/dist/components/NumberInput.vue.d.ts +1 -1
  110. package/dist/components/ProgressBar.vue.d.ts +1 -1
  111. package/dist/components/ProtocolStepEditor.vue.d.ts +3 -1
  112. package/dist/components/RackEditor.vue.d.ts +2 -2
  113. package/dist/components/SampleLegend.vue.d.ts +2 -2
  114. package/dist/components/ScheduleCalendar.vue.d.ts +2 -2
  115. package/dist/components/SegmentedControl.vue.d.ts +2 -2
  116. package/dist/components/SequenceInput.vue.d.ts +3 -3
  117. package/dist/components/SettingsButton.vue.d.ts +2 -2
  118. package/dist/components/SettingsModal.vue.d.ts +13 -5
  119. package/dist/components/StatusIndicator.vue.d.ts +1 -1
  120. package/dist/components/TagsInput.vue.d.ts +3 -2
  121. package/dist/components/TimePicker.vue.d.ts +3 -3
  122. package/dist/components/TimeRangeInput.vue.d.ts +1 -1
  123. package/dist/components/UnitInput.vue.d.ts +2 -2
  124. package/dist/components/WellPlate.vue.d.ts +8 -8
  125. package/dist/components/index.d.ts +11 -1
  126. package/dist/components/index.js +3 -3
  127. package/dist/components/internal/FormFieldRendererInternal.vue.d.ts +31 -0
  128. package/dist/components/internal/FormSectionRenderer.vue.d.ts +43 -0
  129. package/dist/{components-_XqPEhP9.js → components-D_Sr0adg.js} +7290 -6518
  130. package/dist/components-D_Sr0adg.js.map +1 -0
  131. package/dist/composables/index.d.ts +21 -2
  132. package/dist/composables/index.js +4 -3
  133. package/dist/composables/platformContextHelpers.d.ts +14 -0
  134. package/dist/composables/useBioTemplateComponents.d.ts +20 -0
  135. package/dist/composables/useBioTemplateControls.d.ts +6 -0
  136. package/dist/composables/useBioTemplatePackWorkspace.d.ts +45 -0
  137. package/dist/composables/useBioTemplatePresetWorkspace.d.ts +74 -0
  138. package/dist/composables/useBioTemplateWorkspace.d.ts +50 -0
  139. package/dist/composables/useCalendarGrid.d.ts +26 -0
  140. package/dist/composables/useControlSchema.d.ts +321 -0
  141. package/dist/composables/useDebouncedWatch.d.ts +20 -0
  142. package/dist/composables/useDropdownState.d.ts +19 -0
  143. package/dist/composables/useEventListener.d.ts +13 -0
  144. package/dist/composables/useExpansionSet.d.ts +21 -0
  145. package/dist/composables/useExperimentData.d.ts +10 -0
  146. package/dist/composables/useExperimentSave.d.ts +31 -2
  147. package/dist/composables/useExperimentSelector.d.ts +20 -0
  148. package/dist/composables/useForm.d.ts +2 -0
  149. package/dist/composables/useGroupAssignment.d.ts +31 -0
  150. package/dist/composables/useListSelection.d.ts +35 -0
  151. package/dist/composables/usePlatformContext.d.ts +21 -3
  152. package/dist/composables/usePluginApi.d.ts +7 -14
  153. package/dist/composables/usePluginClient.d.ts +109 -0
  154. package/dist/composables/usePluginConfig.d.ts +12 -0
  155. package/dist/composables/useRequestSyncState.d.ts +34 -0
  156. package/dist/composables/useSampleGroups.d.ts +32 -0
  157. package/dist/composables/useSelectionLimit.d.ts +17 -0
  158. package/dist/composables/useSortedItems.d.ts +32 -0
  159. package/dist/composables/useTemplateCollection.d.ts +58 -0
  160. package/dist/composables/useTextSearch.d.ts +18 -0
  161. package/dist/composables/useTimeUtils.d.ts +8 -0
  162. package/dist/{composables-tiZqLu1M.js → composables-C3dpXQN5.js} +228 -146
  163. package/dist/composables-C3dpXQN5.js.map +1 -0
  164. package/dist/index.d.ts +12 -3
  165. package/dist/index.js +6 -5
  166. package/dist/install.d.ts +7 -2
  167. package/dist/install.js +2 -2
  168. package/dist/install.js.map +1 -1
  169. package/dist/stores/index.js +1 -1
  170. package/dist/stores/settings.d.ts +4 -1
  171. package/dist/styles.css +5235 -5977
  172. package/dist/templates/adapters.d.ts +43 -0
  173. package/dist/templates/builders.d.ts +63 -0
  174. package/dist/templates/catalog.d.ts +188 -0
  175. package/dist/templates/componentBindings.d.ts +58 -0
  176. package/dist/templates/controlSchemas.d.ts +25 -0
  177. package/dist/templates/index.d.ts +15 -0
  178. package/dist/templates/index.js +2 -0
  179. package/dist/templates/lookup.d.ts +4 -0
  180. package/dist/templates/packs.d.ts +18 -0
  181. package/dist/templates/presets.d.ts +90 -0
  182. package/dist/templates/types.d.ts +531 -0
  183. package/dist/templates-50NPjaxL.js +9333 -0
  184. package/dist/templates-50NPjaxL.js.map +1 -0
  185. package/dist/types/components.d.ts +26 -4
  186. package/dist/types/form-builder.d.ts +6 -8
  187. package/dist/types/index.d.ts +2 -2
  188. package/dist/types/platform.d.ts +7 -1
  189. package/dist/useScheduleDrag-D4oWdh41.js +4371 -0
  190. package/dist/useScheduleDrag-D4oWdh41.js.map +1 -0
  191. package/dist/utils/formModelSync.d.ts +5 -0
  192. package/dist/utils/items.d.ts +8 -0
  193. package/dist/utils/options.d.ts +6 -0
  194. package/dist/utils/pluginIcon.d.ts +9 -0
  195. package/package.json +7 -2
  196. package/src/__tests__/components/ActionItem.test.ts +99 -0
  197. package/src/__tests__/components/AppAvatarMenu.test.ts +27 -0
  198. package/src/__tests__/components/AppPageSelector.test.ts +134 -0
  199. package/src/__tests__/components/AppPillNav.test.ts +78 -0
  200. package/src/__tests__/components/AppPluginSwitcher.test.ts +44 -0
  201. package/src/__tests__/components/AppSidebar.test.ts +370 -0
  202. package/src/__tests__/components/AppToastContainer.test.ts +48 -0
  203. package/src/__tests__/components/AppTopBar.test.ts +383 -0
  204. package/src/__tests__/components/BaseRadioGroup.test.ts +25 -0
  205. package/src/__tests__/components/BaseSelect.test.ts +21 -0
  206. package/src/__tests__/components/BaseTabs.test.ts +25 -0
  207. package/src/__tests__/components/BatchProgressList.test.ts +52 -0
  208. package/src/__tests__/components/BioTemplateExperimentWorkspaceView.test.ts +153 -0
  209. package/src/__tests__/components/BioTemplatePackWorkspaceView.test.ts +161 -0
  210. package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +281 -0
  211. package/src/__tests__/components/BioTemplateRenderer.test.ts +71 -0
  212. package/src/__tests__/components/Breadcrumb.test.ts +23 -0
  213. package/src/__tests__/components/CalendarGridPanel.test.ts +36 -0
  214. package/src/__tests__/components/ConcentrationInput.test.ts +45 -0
  215. package/src/__tests__/components/ControlWorkspaceView.test.ts +1031 -0
  216. package/src/__tests__/components/DataFrame.test.ts +11 -0
  217. package/src/__tests__/components/DatePicker.test.ts +45 -0
  218. package/src/__tests__/components/DateTimePicker.test.ts +48 -0
  219. package/src/__tests__/components/DropdownButton.test.ts +23 -0
  220. package/src/__tests__/components/EmptyState.test.ts +23 -0
  221. package/src/__tests__/components/ExperimentPopover.test.ts +56 -0
  222. package/src/__tests__/components/FormBuilder.test.ts +296 -0
  223. package/src/__tests__/components/FormCompatibility.test.ts +94 -0
  224. package/src/__tests__/components/GroupAssigner.test.ts +30 -0
  225. package/src/__tests__/components/GroupingModal.test.ts +73 -0
  226. package/src/__tests__/components/MultiSelect.test.ts +48 -0
  227. package/src/__tests__/components/ProtocolStepEditor.test.ts +33 -0
  228. package/src/__tests__/components/ReagentList.test.ts +82 -0
  229. package/src/__tests__/components/SampleHierarchyTree.test.ts +53 -0
  230. package/src/__tests__/components/SampleSelector.test.ts +60 -0
  231. package/src/__tests__/components/SegmentedControl.test.ts +24 -0
  232. package/src/__tests__/components/SettingsButton.test.ts +44 -0
  233. package/src/__tests__/components/SettingsModal.test.ts +296 -0
  234. package/src/__tests__/components/TagsInput.test.ts +75 -0
  235. package/src/__tests__/components/ThemeToggle.test.ts +47 -0
  236. package/src/__tests__/components/TimePicker.test.ts +38 -0
  237. package/src/__tests__/composables/useBioTemplatePackWorkspace.test.ts +122 -0
  238. package/src/__tests__/composables/useBioTemplatePresetWorkspace.test.ts +199 -0
  239. package/src/__tests__/composables/useBioTemplateWorkspace.test.ts +99 -0
  240. package/src/__tests__/composables/useCalendarGrid.test.ts +38 -0
  241. package/src/__tests__/composables/useControlSchema.test.ts +919 -0
  242. package/src/__tests__/composables/useDebouncedWatch.test.ts +93 -0
  243. package/src/__tests__/composables/useDropdownState.test.ts +95 -0
  244. package/src/__tests__/composables/useEventListener.test.ts +116 -0
  245. package/src/__tests__/composables/useExpansionSet.test.ts +62 -0
  246. package/src/__tests__/composables/useExperimentData.test.ts +4 -0
  247. package/src/__tests__/composables/useExperimentSave.test.ts +203 -8
  248. package/src/__tests__/composables/useExperimentSelector.test.ts +164 -0
  249. package/src/__tests__/composables/useForm.test.ts +58 -0
  250. package/src/__tests__/composables/useFormBuilder.test.ts +77 -0
  251. package/src/__tests__/composables/useGroupAssignment.test.ts +73 -0
  252. package/src/__tests__/composables/useListSelection.test.ts +66 -0
  253. package/src/__tests__/composables/usePluginClient.test.ts +444 -0
  254. package/src/__tests__/composables/usePluginConfig.test.ts +5 -0
  255. package/src/__tests__/composables/useRequestSyncState.test.ts +92 -0
  256. package/src/__tests__/composables/useSampleGroups.test.ts +66 -0
  257. package/src/__tests__/composables/useSelectionLimit.test.ts +41 -0
  258. package/src/__tests__/composables/useSortedItems.test.ts +87 -0
  259. package/src/__tests__/composables/useTemplateCollection.test.ts +147 -0
  260. package/src/__tests__/composables/useTextSearch.test.ts +55 -0
  261. package/src/__tests__/composables/useTheme.test.ts +91 -0
  262. package/src/__tests__/composables/useTimeUtils.test.ts +35 -0
  263. package/src/__tests__/docs/frontendDocsCatalog.test.ts +229 -0
  264. package/src/__tests__/fixtures/templates/dose-response.json +81 -0
  265. package/src/__tests__/fixtures/templates/plate-map.json +54 -0
  266. package/src/__tests__/fixtures/templates/qpcr-plate.json +96 -0
  267. package/src/__tests__/fixtures/templates/sample-sheet.json +71 -0
  268. package/src/__tests__/templates/templates.test.ts +1043 -0
  269. package/src/components/ActionItem.vue +82 -0
  270. package/src/components/AppAvatarMenu.vue +15 -69
  271. package/src/components/AppLayout.story.vue +25 -25
  272. package/src/components/AppPageSelector.vue +63 -94
  273. package/src/components/AppPillNav.vue +44 -39
  274. package/src/components/AppPluginSwitcher.vue +41 -145
  275. package/src/components/AppSidebar.story.vue +94 -0
  276. package/src/components/AppSidebar.vue +187 -12
  277. package/src/components/{ToastNotification.story.vue → AppToastContainer.story.vue} +6 -6
  278. package/src/components/AppToastContainer.vue +62 -0
  279. package/src/components/AppTopBar.story.vue +7 -30
  280. package/src/components/AppTopBar.vue +251 -57
  281. package/src/components/BaseModal.vue +3 -5
  282. package/src/components/BaseRadioGroup.vue +7 -3
  283. package/src/components/BaseSelect.vue +11 -7
  284. package/src/components/BaseTabs.vue +6 -4
  285. package/src/components/BatchProgressList.vue +5 -8
  286. package/src/components/BioTemplateExperimentWorkspaceView.story.vue +123 -0
  287. package/src/components/BioTemplateExperimentWorkspaceView.vue +337 -0
  288. package/src/components/BioTemplatePackWorkspaceView.story.vue +107 -0
  289. package/src/components/BioTemplatePackWorkspaceView.vue +176 -0
  290. package/src/components/BioTemplatePresetWorkspaceView.story.vue +151 -0
  291. package/src/components/BioTemplatePresetWorkspaceView.vue +392 -0
  292. package/src/components/BioTemplateRenderer.story.vue +57 -0
  293. package/src/components/BioTemplateRenderer.vue +269 -0
  294. package/src/components/Breadcrumb.vue +14 -8
  295. package/src/components/CalendarGridPanel.vue +120 -0
  296. package/src/components/ConcentrationInput.vue +27 -64
  297. package/src/components/ControlWorkspaceView.story.vue +336 -0
  298. package/src/components/ControlWorkspaceView.vue +347 -0
  299. package/src/components/DataFrame.vue +34 -50
  300. package/src/components/DatePicker.vue +59 -192
  301. package/src/components/DateTimePicker.vue +50 -171
  302. package/src/components/DropdownButton.vue +14 -32
  303. package/src/components/EmptyState.vue +4 -2
  304. package/src/components/ExperimentPopover.vue +5 -22
  305. package/src/components/FormBuilder.vue +124 -27
  306. package/src/components/FormFieldRenderer.vue +15 -38
  307. package/src/components/FormSection.vue +20 -73
  308. package/src/components/GroupAssigner.vue +24 -56
  309. package/src/components/GroupingModal.story.vue +3 -3
  310. package/src/components/GroupingModal.vue +30 -391
  311. package/src/components/MultiSelect.vue +17 -12
  312. package/src/components/PlateMapEditor.vue +3 -8
  313. package/src/components/PluginIcon.vue +2 -22
  314. package/src/components/ProtocolStepEditor.vue +13 -22
  315. package/src/components/ReagentList.vue +25 -33
  316. package/src/components/SampleHierarchyTree.vue +12 -23
  317. package/src/components/SampleSelector.vue +42 -122
  318. package/src/components/SegmentedControl.vue +7 -3
  319. package/src/components/SettingsButton.story.vue +1 -1
  320. package/src/components/SettingsButton.vue +15 -27
  321. package/src/components/SettingsModal.story.vue +1 -1
  322. package/src/components/SettingsModal.vue +120 -29
  323. package/src/components/TagsInput.vue +29 -14
  324. package/src/components/ThemeToggle.vue +9 -7
  325. package/src/components/TimePicker.vue +19 -41
  326. package/src/components/ToastNotification.vue +4 -57
  327. package/src/components/Tooltip.vue +7 -12
  328. package/src/components/WellEditPopup.vue +3 -8
  329. package/src/components/WellPlate.vue +4 -10
  330. package/src/components/index.ts +11 -1
  331. package/src/components/internal/FormFieldRendererInternal.vue +50 -0
  332. package/src/components/internal/FormSectionRenderer.vue +78 -0
  333. package/src/composables/index.ts +212 -0
  334. package/src/composables/platformContextHelpers.ts +74 -0
  335. package/src/composables/useBioTemplateComponents.ts +93 -0
  336. package/src/composables/useBioTemplateControls.ts +41 -0
  337. package/src/composables/useBioTemplatePackWorkspace.ts +181 -0
  338. package/src/composables/useBioTemplatePresetWorkspace.ts +337 -0
  339. package/src/composables/useBioTemplateWorkspace.ts +139 -0
  340. package/src/composables/useCalendarGrid.ts +140 -0
  341. package/src/composables/useControlSchema.ts +1274 -0
  342. package/src/composables/useDebouncedWatch.ts +119 -0
  343. package/src/composables/useDropdownState.ts +83 -0
  344. package/src/composables/useEventListener.ts +111 -0
  345. package/src/composables/useExpansionSet.ts +117 -0
  346. package/src/composables/useExperimentData.ts +20 -11
  347. package/src/composables/useExperimentSave.ts +202 -50
  348. package/src/composables/useExperimentSelector.ts +86 -72
  349. package/src/composables/useForm.ts +49 -4
  350. package/src/composables/useFormBuilder.ts +93 -42
  351. package/src/composables/useGroupAssignment.ts +148 -0
  352. package/src/composables/useListSelection.ts +158 -0
  353. package/src/composables/usePluginApi.ts +7 -14
  354. package/src/composables/usePluginClient.ts +425 -0
  355. package/src/composables/usePluginConfig.ts +34 -13
  356. package/src/composables/useRequestSyncState.ts +126 -0
  357. package/src/composables/useSampleGroups.ts +126 -0
  358. package/src/composables/useSelectionLimit.ts +57 -0
  359. package/src/composables/useSortedItems.ts +118 -0
  360. package/src/composables/useTemplateCollection.ts +229 -0
  361. package/src/composables/useTextSearch.ts +60 -0
  362. package/src/composables/useTheme.ts +2 -28
  363. package/src/composables/useTimeUtils.ts +26 -2
  364. package/src/composables/useWellPlateEditor.ts +13 -9
  365. package/src/index.ts +224 -4
  366. package/src/install.ts +11 -4
  367. package/src/stores/settings.ts +13 -9
  368. package/src/styles/components/app-page-selector.css +23 -0
  369. package/src/styles/components/app-pill-nav.css +7 -0
  370. package/src/styles/components/app-top-bar.css +34 -0
  371. package/src/styles/components/concentration-input.css +3 -142
  372. package/src/styles/components/empty-state.css +0 -16
  373. package/src/styles/components/settings-button.css +3 -66
  374. package/src/styles/components/theme-toggle.css +3 -66
  375. package/src/styles/index.css +0 -1
  376. package/src/templates/adapters.ts +785 -0
  377. package/src/templates/builders.ts +2149 -0
  378. package/src/templates/catalog.ts +245 -0
  379. package/src/templates/componentBindings.ts +615 -0
  380. package/src/templates/controlSchemas.ts +718 -0
  381. package/src/templates/index.ts +314 -0
  382. package/src/templates/lookup.ts +18 -0
  383. package/src/templates/packs.ts +156 -0
  384. package/src/templates/presets.ts +146 -0
  385. package/src/templates/types.ts +668 -0
  386. package/src/types/components.ts +41 -4
  387. package/src/types/form-builder.ts +7 -2
  388. package/src/types/index.ts +14 -0
  389. package/src/types/platform.ts +7 -1
  390. package/src/utils/formModelSync.ts +52 -0
  391. package/src/utils/items.ts +28 -0
  392. package/src/utils/options.ts +23 -0
  393. package/src/utils/pluginIcon.ts +30 -0
  394. package/dist/auth-DsI0rQ7_.js.map +0 -1
  395. package/dist/components-_XqPEhP9.js.map +0 -1
  396. package/dist/composables-tiZqLu1M.js.map +0 -1
  397. package/dist/useScheduleDrag-CA9sGNJG.js +0 -7181
  398. package/dist/useScheduleDrag-CA9sGNJG.js.map +0 -1
  399. package/src/styles/components/grouping-modal.css +0 -323
@@ -1,7 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  /** Dropdown menu for switching between installed plugins with color swatches, version badges, and an install link. */
3
- import { ref, onMounted, onUnmounted } from 'vue'
3
+ import { useDropdownState } from '../composables/useDropdownState'
4
4
  import type { PluginSwitcherPlugin } from '../types/components'
5
+ import ActionItem from './ActionItem.vue'
5
6
 
6
7
  interface Props {
7
8
  current: PluginSwitcherPlugin
@@ -21,55 +22,26 @@ const emit = defineEmits<{
21
22
  'install-click': []
22
23
  }>()
23
24
 
24
- const isOpen = ref(false)
25
- const rootRef = ref<HTMLElement | null>(null)
25
+ const { isOpen, rootRef, close, toggle } = useDropdownState()
26
26
 
27
27
  function initialsOf(plugin: PluginSwitcherPlugin) {
28
28
  const label = plugin.label || plugin.id
29
29
  return label.slice(0, 2).toUpperCase()
30
30
  }
31
31
 
32
- function toggle() {
33
- isOpen.value = !isOpen.value
34
- }
35
-
36
32
  function handleSelect(plugin: PluginSwitcherPlugin) {
37
33
  if (plugin.id === props.current.id) {
38
- isOpen.value = false
34
+ close()
39
35
  return
40
36
  }
41
37
  emit('select', plugin)
42
- isOpen.value = false
38
+ close()
43
39
  }
44
40
 
45
41
  function handleInstall() {
46
42
  emit('install-click')
47
- isOpen.value = false
48
- }
49
-
50
- function handleClickOutside(event: MouseEvent) {
51
- if (!isOpen.value) return
52
- const target = event.target as Node
53
- if (rootRef.value && !rootRef.value.contains(target)) {
54
- isOpen.value = false
55
- }
43
+ close()
56
44
  }
57
-
58
- function handleKeydown(event: KeyboardEvent) {
59
- if (event.key === 'Escape' && isOpen.value) {
60
- isOpen.value = false
61
- }
62
- }
63
-
64
- onMounted(() => {
65
- document.addEventListener('click', handleClickOutside)
66
- document.addEventListener('keydown', handleKeydown)
67
- })
68
-
69
- onUnmounted(() => {
70
- document.removeEventListener('click', handleClickOutside)
71
- document.removeEventListener('keydown', handleKeydown)
72
- })
73
45
  </script>
74
46
 
75
47
  <template>
@@ -102,124 +74,48 @@ onUnmounted(() => {
102
74
 
103
75
  <div v-if="isOpen" class="mint-plugin-switcher__menu" role="menu">
104
76
  <div class="mint-plugin-switcher__menu-title">Switch plugin</div>
105
- <template v-for="plugin in plugins" :key="plugin.id">
106
- <a
107
- v-if="plugin.href"
108
- :href="plugin.href"
109
- :class="[
110
- 'mint-plugin-switcher__item',
111
- { 'mint-plugin-switcher__item--active': plugin.id === current.id },
112
- ]"
113
- role="menuitem"
114
- @click="handleSelect(plugin)"
77
+ <ActionItem
78
+ v-for="plugin in plugins"
79
+ :key="plugin.id"
80
+ :href="plugin.href"
81
+ :to="plugin.to"
82
+ :class="[
83
+ 'mint-plugin-switcher__item',
84
+ { 'mint-plugin-switcher__item--active': plugin.id === current.id },
85
+ ]"
86
+ role="menuitem"
87
+ @click="handleSelect(plugin)"
88
+ >
89
+ <span
90
+ class="mint-plugin-switcher__item-swatch"
91
+ :style="{ background: plugin.color ?? 'var(--color-primary)' }"
115
92
  >
116
- <span
117
- class="mint-plugin-switcher__item-swatch"
118
- :style="{ background: plugin.color ?? 'var(--color-primary)' }"
119
- >
120
- {{ initialsOf(plugin) }}
121
- </span>
122
- <span class="mint-plugin-switcher__item-label">{{ plugin.label }}</span>
123
- <span v-if="plugin.version" class="mint-plugin-switcher__item-version">v{{ plugin.version }}</span>
124
- <svg
125
- v-if="plugin.id === current.id"
126
- class="mint-plugin-switcher__item-check"
127
- viewBox="0 0 24 24"
128
- fill="none"
129
- stroke="currentColor"
130
- stroke-width="2.5"
131
- stroke-linecap="round"
132
- stroke-linejoin="round"
133
- aria-hidden="true"
134
- >
135
- <path d="M5 13l4 4L19 7" />
136
- </svg>
137
- </a>
138
- <router-link
139
- v-else-if="plugin.to"
140
- :to="plugin.to"
141
- :class="[
142
- 'mint-plugin-switcher__item',
143
- { 'mint-plugin-switcher__item--active': plugin.id === current.id },
144
- ]"
145
- role="menuitem"
146
- @click="handleSelect(plugin)"
147
- >
148
- <span
149
- class="mint-plugin-switcher__item-swatch"
150
- :style="{ background: plugin.color ?? 'var(--color-primary)' }"
151
- >
152
- {{ initialsOf(plugin) }}
153
- </span>
154
- <span class="mint-plugin-switcher__item-label">{{ plugin.label }}</span>
155
- <span v-if="plugin.version" class="mint-plugin-switcher__item-version">v{{ plugin.version }}</span>
156
- <svg
157
- v-if="plugin.id === current.id"
158
- class="mint-plugin-switcher__item-check"
159
- viewBox="0 0 24 24"
160
- fill="none"
161
- stroke="currentColor"
162
- stroke-width="2.5"
163
- stroke-linecap="round"
164
- stroke-linejoin="round"
165
- aria-hidden="true"
166
- >
167
- <path d="M5 13l4 4L19 7" />
168
- </svg>
169
- </router-link>
170
- <button
171
- v-else
172
- type="button"
173
- :class="[
174
- 'mint-plugin-switcher__item',
175
- { 'mint-plugin-switcher__item--active': plugin.id === current.id },
176
- ]"
177
- role="menuitem"
178
- @click="handleSelect(plugin)"
93
+ {{ initialsOf(plugin) }}
94
+ </span>
95
+ <span class="mint-plugin-switcher__item-label">{{ plugin.label }}</span>
96
+ <span v-if="plugin.version" class="mint-plugin-switcher__item-version">v{{ plugin.version }}</span>
97
+ <svg
98
+ v-if="plugin.id === current.id"
99
+ class="mint-plugin-switcher__item-check"
100
+ viewBox="0 0 24 24"
101
+ fill="none"
102
+ stroke="currentColor"
103
+ stroke-width="2.5"
104
+ stroke-linecap="round"
105
+ stroke-linejoin="round"
106
+ aria-hidden="true"
179
107
  >
180
- <span
181
- class="mint-plugin-switcher__item-swatch"
182
- :style="{ background: plugin.color ?? 'var(--color-primary)' }"
183
- >
184
- {{ initialsOf(plugin) }}
185
- </span>
186
- <span class="mint-plugin-switcher__item-label">{{ plugin.label }}</span>
187
- <span v-if="plugin.version" class="mint-plugin-switcher__item-version">v{{ plugin.version }}</span>
188
- <svg
189
- v-if="plugin.id === current.id"
190
- class="mint-plugin-switcher__item-check"
191
- viewBox="0 0 24 24"
192
- fill="none"
193
- stroke="currentColor"
194
- stroke-width="2.5"
195
- stroke-linecap="round"
196
- stroke-linejoin="round"
197
- aria-hidden="true"
198
- >
199
- <path d="M5 13l4 4L19 7" />
200
- </svg>
201
- </button>
202
- </template>
108
+ <path d="M5 13l4 4L19 7" />
109
+ </svg>
110
+ </ActionItem>
203
111
 
204
112
  <template v-if="plugins.length && (installHref || installTo || $slots.install)">
205
113
  <div class="mint-plugin-switcher__divider" role="separator" />
206
114
  </template>
207
115
  <slot name="install">
208
- <a
209
- v-if="installHref"
116
+ <ActionItem
117
+ v-if="installHref || installTo"
210
118
  :href="installHref"
211
- class="mint-plugin-switcher__install"
212
- role="menuitem"
213
- @click="handleInstall"
214
- >
215
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
216
- <line x1="12" y1="5" x2="12" y2="19" />
217
- <line x1="5" y1="12" x2="19" y2="12" />
218
- </svg>
219
- <span>{{ installLabel }}</span>
220
- </a>
221
- <router-link
222
- v-else-if="installTo"
223
119
  :to="installTo"
224
120
  class="mint-plugin-switcher__install"
225
121
  role="menuitem"
@@ -230,7 +126,7 @@ onUnmounted(() => {
230
126
  <line x1="5" y1="12" x2="19" y2="12" />
231
127
  </svg>
232
128
  <span>{{ installLabel }}</span>
233
- </router-link>
129
+ </ActionItem>
234
130
  </slot>
235
131
  </div>
236
132
  </div>
@@ -9,6 +9,10 @@ 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 { 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
 
14
18
  /* --- Icon paths (Lucide-style) --- */
@@ -127,6 +131,57 @@ const container = ref('vial')
127
131
  const expNumber = ref(1)
128
132
  const initials = ref('XP')
129
133
  const toggleState = reactive<Record<string, boolean>>({ naming: true, randomize: false })
134
+ const schemaControls = defineControls({
135
+ threshold: {
136
+ type: 'slider',
137
+ label: 'Threshold',
138
+ default: 0.05,
139
+ min: 0,
140
+ max: 1,
141
+ props: { step: 0.01 },
142
+ section: 'parameters',
143
+ sectionLabel: 'Parameters',
144
+ sectionSubtitle: 'Analysis controls',
145
+ view: 'analysis',
146
+ sidebar: {
147
+ icon: icons.settings,
148
+ iconColor: '#6366f1',
149
+ iconBg: '#e0e7ff',
150
+ },
151
+ },
152
+ method: {
153
+ label: 'Model',
154
+ default: 'linear',
155
+ options: ['linear', 'logistic', 'quadratic'],
156
+ required: true,
157
+ section: 'parameters',
158
+ view: 'analysis',
159
+ },
160
+ showOutliers: {
161
+ label: 'Show outliers',
162
+ default: true,
163
+ section: 'display',
164
+ sectionLabel: 'Display',
165
+ sectionSubtitle: 'Result filters',
166
+ view: 'analysis',
167
+ sidebar: {
168
+ icon: icons.zap,
169
+ iconColor: '#0ea5e9',
170
+ iconBg: '#e0f2fe',
171
+ defaultOpen: false,
172
+ },
173
+ },
174
+ })
175
+ const controlValues = reactive<Record<string, unknown>>({ ...getControlDefaults(schemaControls) })
176
+ const templateCollection = createWellPlateScreenCollection({
177
+ samples: ['Control', 'Treatment'],
178
+ compounds: { 'Drug A': [10, 1, 0.1] },
179
+ })
180
+ const templateWorkspace = useBioTemplateWorkspace(templateCollection)
181
+ const templateValues = reactive<Record<string, unknown>>({ ...templateWorkspace.controls.initialValues })
182
+ const templateWellPlateProps = templateWorkspace.componentProps
183
+ .find(binding => binding.component === 'WellPlate')
184
+ ?.propsObject ?? {}
130
185
 
131
186
  function handleToggle(id: string, value: boolean) {
132
187
  toggleState[id] = value
@@ -218,6 +273,45 @@ function initSimpleToolkit() {
218
273
  </div>
219
274
  </Variant>
220
275
 
276
+ <Variant title="Schema Driven Controls">
277
+ <div style="padding: 2rem; height: 520px; position: relative; background: var(--bg-primary, #f1f5f9);">
278
+ <AppSidebar
279
+ :controls="schemaControls"
280
+ active-view="analysis"
281
+ v-model="controlValues"
282
+ width="300px"
283
+ />
284
+ </div>
285
+ </Variant>
286
+
287
+ <Variant title="Template Driven Controls">
288
+ <div style="padding: 2rem; min-height: 560px; display: flex; gap: 1rem; background: var(--bg-primary, #f1f5f9);">
289
+ <AppSidebar
290
+ v-bind="templateWorkspace.sidebar"
291
+ active-view="design"
292
+ v-model="templateValues"
293
+ width="300px"
294
+ />
295
+
296
+ <div style="flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.75rem;">
297
+ <div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
298
+ <span
299
+ v-for="binding in templateWorkspace.componentBindings"
300
+ :key="binding.id"
301
+ 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);"
302
+ >
303
+ {{ binding.component }}
304
+ </span>
305
+ </div>
306
+ <WellPlate
307
+ v-bind="templateWellPlateProps"
308
+ size="fill"
309
+ readonly
310
+ />
311
+ </div>
312
+ </div>
313
+ </Variant>
314
+
221
315
  <Variant title="Simple Toolkit" :init-state="initSimpleToolkit">
222
316
  <template #default="{ state }">
223
317
  <div style="padding: 2rem; height: 500px; position: relative; background: var(--bg-primary, #f1f5f9);">
@@ -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,11 +19,27 @@
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
27
  import { computed } from 'vue'
26
- import type { SidebarToolSection } from '../types'
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 {
30
45
  /** Map of view IDs to their tool sections */
@@ -41,6 +56,36 @@ interface Props {
41
56
  side?: 'left' | 'right'
42
57
  /** Toggle state map: sectionId → boolean */
43
58
  toggleState?: Record<string, boolean>
59
+ /** Optional FormBuilder schemas keyed by section ID. Used when no section slot is provided. */
60
+ forms?: Record<string, FormSchema>
61
+ /** Generated view IDs from useControlSchema(). Consumed for clean v-bind ergonomics. */
62
+ viewIds?: string[]
63
+ /** Generated AppPillNav-compatible view items from useControlSchema(). Consumed for clean v-bind ergonomics. */
64
+ viewItems?: PillNavItem[]
65
+ /** Default view ID used when activeView is omitted. */
66
+ defaultView?: string
67
+ /** Model returned by defineControlModel(), or a raw nested ControlModel for one-step sidebar/form generation. */
68
+ model?: ControlModel | ControlModelBinding
69
+ /** Compact control schema. When provided, AppSidebar generates panels, section forms, and default values. */
70
+ controls?: ControlSchema
71
+ /** Options passed to compact control schema generation, including shared initialValues. */
72
+ controlOptions?: ControlWorkspaceOptions
73
+ /** Shared values for auto-rendered section forms. Supports default v-model. */
74
+ modelValue?: Record<string, unknown>
75
+ /** Shared values for auto-rendered section forms */
76
+ values?: Record<string, unknown>
77
+ /** Runtime FormBuilder enhancements for auto-rendered section forms */
78
+ formEnhancements?: FormEnhancements<Record<string, unknown>>
79
+ /** Show submit/cancel actions inside auto-rendered section forms */
80
+ showFormActions?: boolean
81
+ /** Loading/saving state for auto-rendered section forms */
82
+ formLoading?: boolean
83
+ /** Disabled state for auto-rendered section forms */
84
+ formDisabled?: boolean
85
+ /** Readonly state for auto-rendered section forms */
86
+ formReadonly?: boolean
87
+ /** Size passed to auto-rendered section forms */
88
+ formSize?: 'sm' | 'md' | 'lg'
44
89
  }
45
90
 
46
91
  const props = withDefaults(defineProps<Props>(), {
@@ -51,15 +96,76 @@ const props = withDefaults(defineProps<Props>(), {
51
96
  width: '280px',
52
97
  side: 'left',
53
98
  toggleState: () => ({}),
99
+ forms: () => ({}),
100
+ viewIds: () => [],
101
+ viewItems: () => [],
102
+ defaultView: '',
103
+ model: undefined,
104
+ controlOptions: () => ({}),
105
+ modelValue: undefined,
106
+ values: () => ({}),
107
+ showFormActions: false,
108
+ formLoading: false,
109
+ formDisabled: false,
110
+ formReadonly: false,
111
+ formSize: 'sm',
54
112
  })
55
113
 
56
- defineEmits<{
57
- 'update:toggle': [sectionId: string, value: boolean]
58
- }>()
114
+ const resolvedModel = computed<ControlModelBinding | undefined>(() => {
115
+ if (props.model === undefined) return undefined
116
+ return isControlModelBinding(props.model) ? props.model : defineControlModel(props.model)
117
+ })
118
+
119
+ const resolvedControls = computed<ControlSchema | undefined>(() =>
120
+ props.controls ?? resolvedModel.value?.controls,
121
+ )
122
+
123
+ const resolvedControlOptions = computed<ControlWorkspaceOptions>(() =>
124
+ mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, props.controlOptions)
125
+ )
126
+
127
+ const generatedPanels = computed<Record<string, SidebarToolSection[]>>(() => {
128
+ if (!resolvedControls.value) return {}
129
+ return controlsToSidebarPanels(resolvedControls.value, resolvedControlOptions.value)
130
+ })
131
+
132
+ const generatedForms = computed<Record<string, FormSchema>>(() => {
133
+ if (!resolvedControls.value) return {}
134
+ return controlsToSectionFormSchemas(resolvedControls.value, resolvedControlOptions.value)
135
+ })
136
+
137
+ const generatedDefaults = computed<Record<string, unknown>>(() => {
138
+ if (!resolvedControls.value) return {}
139
+ return {
140
+ ...getControlDefaults(resolvedControls.value),
141
+ ...(resolvedControlOptions.value.initialValues ?? {}),
142
+ }
143
+ })
144
+
145
+ const resolvedPanels = computed<Record<string, SidebarToolSection[]>>(() =>
146
+ mergeSidebarPanels(generatedPanels.value, props.panels),
147
+ )
148
+
149
+ const resolvedForms = computed<Record<string, FormSchema>>(() => ({
150
+ ...generatedForms.value,
151
+ ...props.forms,
152
+ }))
153
+
154
+ const resolvedValues = computed<Record<string, unknown>>(() => ({
155
+ ...generatedDefaults.value,
156
+ ...(props.modelValue ?? props.values),
157
+ }))
158
+
159
+ const resolvedActiveView = computed(() => {
160
+ if (props.activeView) return props.activeView
161
+ if (props.defaultView) return props.defaultView
162
+ if (!resolvedControls.value) return ''
163
+ return firstVisibleViewId(resolvedPanels.value)
164
+ })
59
165
 
60
166
  const activeSections = computed<SidebarToolSection[]>(() => {
61
- if (!props.activeView || !props.panels[props.activeView]) return []
62
- return props.panels[props.activeView]
167
+ if (!resolvedActiveView.value || !resolvedPanels.value[resolvedActiveView.value]) return []
168
+ return resolvedPanels.value[resolvedActiveView.value]
63
169
  })
64
170
 
65
171
  const isVisible = computed(() => activeSections.value.length > 0)
@@ -75,6 +181,60 @@ const sidebarClasses = computed(() => [
75
181
  const sidebarStyle = computed(() => ({
76
182
  width: props.width,
77
183
  }))
184
+
185
+ const emit = defineEmits<{
186
+ 'update:toggle': [sectionId: string, value: boolean]
187
+ 'update:modelValue': [values: Record<string, unknown>]
188
+ 'update:values': [values: Record<string, unknown>]
189
+ 'form-submit': [sectionId: string, values: Record<string, unknown>]
190
+ 'form-cancel': [sectionId: string]
191
+ }>()
192
+
193
+ function handleFormUpdate(values: Record<string, unknown>) {
194
+ const nextValues = { ...resolvedValues.value, ...values }
195
+ emit('update:modelValue', nextValues)
196
+ emit('update:values', nextValues)
197
+ }
198
+
199
+ function handleFormSubmit(sectionId: string, values: Record<string, unknown>) {
200
+ emit('form-submit', sectionId, values)
201
+ }
202
+
203
+ function handleFormCancel(sectionId: string) {
204
+ emit('form-cancel', sectionId)
205
+ }
206
+
207
+ function mergeSidebarPanels(
208
+ generated: Record<string, SidebarToolSection[]>,
209
+ explicit: Record<string, SidebarToolSection[]>,
210
+ ): Record<string, SidebarToolSection[]> {
211
+ const merged: Record<string, SidebarToolSection[]> = {}
212
+ const viewIds = new Set([...Object.keys(generated), ...Object.keys(explicit)])
213
+
214
+ for (const viewId of viewIds) {
215
+ const sectionsById = new Map<string, SidebarToolSection>()
216
+ for (const section of generated[viewId] ?? []) {
217
+ sectionsById.set(section.id, section)
218
+ }
219
+ for (const section of explicit[viewId] ?? []) {
220
+ sectionsById.set(section.id, section)
221
+ }
222
+ merged[viewId] = [...sectionsById.values()]
223
+ }
224
+
225
+ return merged
226
+ }
227
+
228
+ function firstVisibleViewId(panels: Record<string, SidebarToolSection[]>): string {
229
+ for (const [viewId, sections] of Object.entries(panels)) {
230
+ if (sections.length > 0) return viewId
231
+ }
232
+ return ''
233
+ }
234
+
235
+ function isControlModelBinding(model: ControlModel | ControlModelBinding): model is ControlModelBinding {
236
+ return 'controls' in model && 'controlOptions' in model
237
+ }
78
238
  </script>
79
239
 
80
240
  <template>
@@ -101,9 +261,24 @@ const sidebarStyle = computed(() => ({
101
261
  :default-open="section.defaultOpen !== false"
102
262
  :show-toggle="section.showToggle"
103
263
  :toggle-value="toggleState[section.id] ?? false"
104
- @update:toggle-value="$emit('update:toggle', section.id, $event)"
264
+ @update:toggle-value="emit('update:toggle', section.id, $event)"
105
265
  >
106
- <slot :name="`section-${section.id}`" />
266
+ <slot :name="`section-${section.id}`">
267
+ <FormBuilder
268
+ v-if="resolvedForms[section.id]"
269
+ :model-value="resolvedValues"
270
+ :schema="resolvedForms[section.id]"
271
+ :enhancements="formEnhancements"
272
+ :loading="formLoading"
273
+ :disabled="formDisabled"
274
+ :readonly="formReadonly"
275
+ :size="formSize"
276
+ :show-actions="showFormActions"
277
+ @update:model-value="handleFormUpdate"
278
+ @submit="handleFormSubmit(section.id, $event)"
279
+ @cancel="handleFormCancel(section.id)"
280
+ />
281
+ </slot>
107
282
  </CollapsibleCard>
108
283
  </div>
109
284
 
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import ToastNotification from './ToastNotification.vue'
2
+ import AppToastContainer from './AppToastContainer.vue'
3
3
  import { useToast } from '../composables/useToast'
4
4
 
5
5
  const toast = useToast()
@@ -34,7 +34,7 @@ function triggerLongToast(type: 'success' | 'error') {
34
34
  </script>
35
35
 
36
36
  <template>
37
- <Story title="Feedback/ToastNotification">
37
+ <Story title="Feedback/AppToastContainer">
38
38
  <Variant title="Playground">
39
39
  <template #default="{ state }">
40
40
  <div style="padding: 2rem; display: flex; flex-direction: column; align-items: center; gap: 1rem;">
@@ -71,7 +71,7 @@ function triggerLongToast(type: 'success' | 'error') {
71
71
  Info
72
72
  </button>
73
73
  </div>
74
- <ToastNotification />
74
+ <AppToastContainer />
75
75
  </div>
76
76
  </template>
77
77
 
@@ -112,7 +112,7 @@ function triggerLongToast(type: 'success' | 'error') {
112
112
  Info Toast
113
113
  </button>
114
114
  </div>
115
- <ToastNotification />
115
+ <AppToastContainer />
116
116
  </div>
117
117
  </Variant>
118
118
 
@@ -128,7 +128,7 @@ function triggerLongToast(type: 'success' | 'error') {
128
128
  <p style="margin: 0; color: var(--text-muted, #94a3b8); font-size: 0.75rem;">
129
129
  Click to see multiple toasts stacked. Click any toast to dismiss it.
130
130
  </p>
131
- <ToastNotification />
131
+ <AppToastContainer />
132
132
  </div>
133
133
  </Variant>
134
134
  <Variant title="Progress bar — 4s / 6s TTL">
@@ -150,7 +150,7 @@ function triggerLongToast(type: 'success' | 'error') {
150
150
  <p style="margin: 0; font-size: 0.8125rem; color: var(--text-muted);">
151
151
  Watch the bottom progress bar shrink over the toast's TTL.
152
152
  </p>
153
- <ToastNotification />
153
+ <AppToastContainer />
154
154
  </div>
155
155
  </Variant>
156
156
  </Story>