@morscherlab/mint-sdk 1.0.0-rc.4 → 1.0.0-rc.6

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 (324) hide show
  1. package/dist/__tests__/components/AppTopBar.navigation.test.d.ts +1 -0
  2. package/dist/__tests__/components/DoseCalculatorVolumeField.test.d.ts +1 -0
  3. package/dist/__tests__/components/PlateMapEditorToolbarInternal.test.d.ts +1 -0
  4. package/dist/__tests__/components/PluginWorkspaceView.controls.test.d.ts +1 -0
  5. package/dist/__tests__/components/PluginWorkspaceView.navigation.test.d.ts +1 -0
  6. package/dist/__tests__/components/PluginWorkspaceView.shell.test.d.ts +1 -0
  7. package/dist/__tests__/components/ProtocolStep.presentation.test.d.ts +1 -0
  8. package/dist/__tests__/components/ProtocolStepEditor.state.test.d.ts +1 -0
  9. package/dist/__tests__/components/ProtocolStepParameterField.test.d.ts +1 -0
  10. package/dist/__tests__/components/ReagentList.presentation.test.d.ts +1 -0
  11. package/dist/__tests__/components/SampleSelector.colors.test.d.ts +1 -0
  12. package/dist/__tests__/components/SampleSelector.drag.test.d.ts +1 -0
  13. package/dist/__tests__/components/SampleSelector.groups.test.d.ts +1 -0
  14. package/dist/__tests__/components/SampleSelector.selection.test.d.ts +1 -0
  15. package/dist/__tests__/components/SampleSelectorSampleRow.test.d.ts +1 -0
  16. package/dist/__tests__/components/ScheduleCalendar.test.d.ts +1 -0
  17. package/dist/__tests__/components/SettingsModal.schema.test.d.ts +1 -0
  18. package/dist/__tests__/components/WellPlate.colors.test.d.ts +1 -0
  19. package/dist/__tests__/components/WellPlate.conditions.test.d.ts +1 -0
  20. package/dist/__tests__/components/WellPlate.geometry.test.d.ts +1 -0
  21. package/dist/__tests__/components/WellPlate.interaction.test.d.ts +1 -0
  22. package/dist/__tests__/components/WellPlate.legend.test.d.ts +1 -0
  23. package/dist/__tests__/components/WellPlate.rendering.test.d.ts +1 -0
  24. package/dist/__tests__/components/WellPlate.sampleDrop.test.d.ts +1 -0
  25. package/dist/__tests__/composables/autoGroup/classify.test.d.ts +1 -0
  26. package/dist/__tests__/composables/autoGroup/columns.test.d.ts +1 -0
  27. package/dist/__tests__/composables/autoGroup/compose.test.d.ts +1 -0
  28. package/dist/__tests__/composables/autoGroup/cooccurrence.test.d.ts +1 -0
  29. package/dist/__tests__/composables/autoGroup/fingerprint.test.d.ts +1 -0
  30. package/dist/__tests__/composables/autoGroup/integration.test.d.ts +1 -0
  31. package/dist/__tests__/composables/autoGroup/template.test.d.ts +1 -0
  32. package/dist/__tests__/composables/autoGroup/tokenize.test.d.ts +1 -0
  33. package/dist/__tests__/composables/useAutoGroupInputSources.test.d.ts +1 -0
  34. package/dist/__tests__/composables/useScheduleCalendarLayout.test.d.ts +1 -0
  35. package/dist/__tests__/docs/extractDocsComponents.test.d.ts +1 -0
  36. package/dist/__tests__/docs/extractDocsExports.test.d.ts +1 -0
  37. package/dist/__tests__/docs/extractDocsParsing.test.d.ts +1 -0
  38. package/dist/__tests__/docs/extractDocsTemplates.test.d.ts +1 -0
  39. package/dist/__tests__/docs/extractDocsTheme.test.d.ts +1 -0
  40. package/dist/components/AppSidebar.vue.d.ts +9 -6
  41. package/dist/components/AppTopBar.navigation.d.ts +11 -0
  42. package/dist/components/BaseButton.vue.d.ts +1 -1
  43. package/dist/components/BaseCheckbox.vue.d.ts +7 -2
  44. package/dist/components/BaseInput.vue.d.ts +2 -2
  45. package/dist/components/BasePill.vue.d.ts +2 -2
  46. package/dist/components/BaseRadioGroup.vue.d.ts +2 -2
  47. package/dist/components/BaseSelect.vue.d.ts +1 -1
  48. package/dist/components/BaseSlider.vue.d.ts +2 -2
  49. package/dist/components/BaseTextarea.vue.d.ts +2 -2
  50. package/dist/components/BaseToggle.vue.d.ts +7 -2
  51. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
  52. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +1 -1
  53. package/dist/components/CollapsibleCard.vue.d.ts +9 -0
  54. package/dist/components/ColorSlider.vue.d.ts +2 -2
  55. package/dist/components/ConcentrationInput.vue.d.ts +2 -2
  56. package/dist/components/ControlWorkspaceView.vue.d.ts +4 -4
  57. package/dist/components/DatePicker.vue.d.ts +1 -1
  58. package/dist/components/DateTimePicker.vue.d.ts +2 -2
  59. package/dist/components/DoseCalculatorVolumeField.vue.d.ts +15 -0
  60. package/dist/components/DoseDesignWorkspaceView.vue.d.ts +2 -2
  61. package/dist/components/DropdownButton.vue.d.ts +1 -1
  62. package/dist/components/FileUploader.vue.d.ts +2 -2
  63. package/dist/components/FormulaInput.vue.d.ts +2 -2
  64. package/dist/components/IconButton.vue.d.ts +1 -1
  65. package/dist/components/LoadingSpinner.vue.d.ts +1 -1
  66. package/dist/components/MoleculeInput.vue.d.ts +2 -2
  67. package/dist/components/MultiSelect.vue.d.ts +1 -1
  68. package/dist/components/NumberInput.vue.d.ts +1 -1
  69. package/dist/components/PlateMapEditor.vue.d.ts +6 -6
  70. package/dist/components/PluginWorkspaceView.controls.d.ts +28 -0
  71. package/dist/components/PluginWorkspaceView.navigation.d.ts +29 -0
  72. package/dist/components/PluginWorkspaceView.props.d.ts +151 -0
  73. package/dist/components/PluginWorkspaceView.shell.d.ts +19 -0
  74. package/dist/components/PluginWorkspaceView.vue.d.ts +51 -196
  75. package/dist/components/ProgressBar.vue.d.ts +1 -1
  76. package/dist/components/ProtocolStep.presentation.d.ts +4 -0
  77. package/dist/components/ProtocolStepEditor.state.d.ts +18 -0
  78. package/dist/components/ProtocolStepParameterField.vue.d.ts +12 -0
  79. package/dist/components/ReagentList.presentation.d.ts +16 -0
  80. package/dist/components/ResourceCard.vue.d.ts +1 -1
  81. package/dist/components/SampleSelector.colors.d.ts +13 -0
  82. package/dist/components/SampleSelector.drag.d.ts +24 -0
  83. package/dist/components/SampleSelector.groups.d.ts +15 -0
  84. package/dist/components/SampleSelector.selection.d.ts +26 -0
  85. package/dist/components/SampleSelector.vue.d.ts +4 -1
  86. package/dist/components/SampleSelectorSampleRow.vue.d.ts +21 -0
  87. package/dist/components/SegmentedControl.vue.d.ts +1 -1
  88. package/dist/components/SequenceInput.vue.d.ts +2 -2
  89. package/dist/components/SequenceProgressBar.vue.d.ts +1 -1
  90. package/dist/components/SettingsModal.schema.d.ts +9 -0
  91. package/dist/components/StatusIndicator.vue.d.ts +1 -1
  92. package/dist/components/TagsInput.vue.d.ts +2 -2
  93. package/dist/components/TimePicker.vue.d.ts +2 -2
  94. package/dist/components/TimeRangeInput.vue.d.ts +1 -1
  95. package/dist/components/UnitInput.vue.d.ts +2 -2
  96. package/dist/components/WellPlate.colors.d.ts +9 -0
  97. package/dist/components/WellPlate.conditions.d.ts +26 -0
  98. package/dist/components/WellPlate.geometry.d.ts +23 -0
  99. package/dist/components/WellPlate.interaction.d.ts +71 -0
  100. package/dist/components/WellPlate.legend.d.ts +2 -0
  101. package/dist/components/WellPlate.rendering.d.ts +24 -0
  102. package/dist/components/WellPlate.sampleDrop.d.ts +8 -0
  103. package/dist/components/WellPlate.vue.d.ts +1 -1
  104. package/dist/components/index.js +2 -2
  105. package/dist/components/internal/ActionItemInternal.vue.d.ts +1 -1
  106. package/dist/components/internal/PlateMapEditorToolbarInternal.vue.d.ts +28 -0
  107. package/dist/{components-DafPc4rM.js → components-Blx4MG--.js} +4073 -4222
  108. package/dist/components-Blx4MG--.js.map +1 -0
  109. package/dist/composables/autoGroup/classKey.d.ts +4 -0
  110. package/dist/composables/autoGroup/classify.d.ts +28 -0
  111. package/dist/composables/autoGroup/colors.d.ts +2 -0
  112. package/dist/composables/autoGroup/columns.d.ts +10 -0
  113. package/dist/composables/autoGroup/compose.d.ts +8 -0
  114. package/dist/composables/autoGroup/cooccurrence.d.ts +2 -0
  115. package/dist/composables/autoGroup/csv-shim.d.ts +2 -0
  116. package/dist/composables/autoGroup/fingerprint.d.ts +3 -0
  117. package/dist/composables/autoGroup/index.d.ts +16 -0
  118. package/dist/composables/autoGroup/replicatePreGroup.d.ts +38 -0
  119. package/dist/composables/autoGroup/template.d.ts +15 -0
  120. package/dist/composables/autoGroup/tokenize.d.ts +8 -0
  121. package/dist/composables/autoGroupConstants.d.ts +1 -0
  122. package/dist/composables/autoGroupGrouping.d.ts +3 -0
  123. package/dist/composables/controlComponentBindings.d.ts +1 -1
  124. package/dist/composables/controlSchemaAdapters.d.ts +1 -1
  125. package/dist/composables/controlSchemaDoseDesign.d.ts +11 -0
  126. package/dist/composables/controlSchemaLayout.d.ts +1 -1
  127. package/dist/composables/controlSchemaModel.d.ts +5 -0
  128. package/dist/composables/controlSchemaNormalize.d.ts +1 -1
  129. package/dist/composables/controlSchemaTypes.d.ts +311 -0
  130. package/dist/composables/controlWorkspaceOptions.d.ts +1 -1
  131. package/dist/composables/formBuilderSchema.d.ts +18 -0
  132. package/dist/composables/index.js +3 -3
  133. package/dist/composables/pluginEndpointBuilder.d.ts +13 -0
  134. package/dist/composables/protocolTemplateCatalog.d.ts +26 -0
  135. package/dist/composables/useAutoGroup.d.ts +61 -74
  136. package/dist/composables/useAutoGroupInputSources.d.ts +32 -0
  137. package/dist/composables/useBioTemplateControls.d.ts +1 -1
  138. package/dist/composables/useBioTemplatePresetWorkspace.d.ts +1 -1
  139. package/dist/composables/useBioTemplateWorkspace.d.ts +1 -1
  140. package/dist/composables/useControlSchema.d.ts +4 -316
  141. package/dist/composables/useControlWorkspace.d.ts +1 -1
  142. package/dist/composables/useForm.d.ts +2 -33
  143. package/dist/composables/useFormBuilder.d.ts +2 -9
  144. package/dist/composables/useFormValidation.d.ts +34 -0
  145. package/dist/composables/usePluginClient.d.ts +1 -4
  146. package/dist/composables/useProtocolTemplates.d.ts +2 -24
  147. package/dist/composables/useScheduleCalendarLayout.d.ts +49 -0
  148. package/dist/{composables-BMkPQhVK.js → composables-CHDjDIQT.js} +33 -31
  149. package/dist/composables-CHDjDIQT.js.map +1 -0
  150. package/dist/index.js +4 -4
  151. package/dist/install.js +2 -2
  152. package/dist/styles.css +1432 -660
  153. package/dist/templates/controlSchemaTypes.d.ts +1 -1
  154. package/dist/templates/index.js +1 -1
  155. package/dist/templates/templateAdapterTypes.d.ts +48 -0
  156. package/dist/templates/templateCreateOptions.d.ts +165 -0
  157. package/dist/templates/templateQpcrTypes.d.ts +42 -0
  158. package/dist/templates/types.d.ts +5 -250
  159. package/dist/{templates-bUAWMn5L.js → templates-DSbHJC4v.js} +1536 -297
  160. package/dist/templates-DSbHJC4v.js.map +1 -0
  161. package/dist/types/auto-group.d.ts +79 -9
  162. package/dist/types/componentLabTypes.d.ts +161 -0
  163. package/dist/types/componentWorkflowTypes.d.ts +150 -0
  164. package/dist/types/components.d.ts +14 -311
  165. package/dist/types/form-builder.d.ts +3 -0
  166. package/dist/types/index.d.ts +1 -1
  167. package/dist/{useProtocolTemplates-QZtHFFH2.js → useProtocolTemplates-BbPOYPzO.js} +1220 -454
  168. package/dist/useProtocolTemplates-BbPOYPzO.js.map +1 -0
  169. package/package.json +1 -1
  170. package/src/__tests__/components/AppSidebar.test.ts +67 -0
  171. package/src/__tests__/components/AppTopBar.navigation.test.ts +70 -0
  172. package/src/__tests__/components/CollapsibleCard.test.ts +47 -0
  173. package/src/__tests__/components/DoseCalculatorVolumeField.test.ts +53 -0
  174. package/src/__tests__/components/FormBuilder.test.ts +57 -0
  175. package/src/__tests__/components/PlateMapEditorToolbarInternal.test.ts +54 -0
  176. package/src/__tests__/components/PluginWorkspaceView.controls.test.ts +156 -0
  177. package/src/__tests__/components/PluginWorkspaceView.navigation.test.ts +102 -0
  178. package/src/__tests__/components/PluginWorkspaceView.shell.test.ts +43 -0
  179. package/src/__tests__/components/ProtocolStep.presentation.test.ts +31 -0
  180. package/src/__tests__/components/ProtocolStepEditor.state.test.ts +165 -0
  181. package/src/__tests__/components/ProtocolStepParameterField.test.ts +44 -0
  182. package/src/__tests__/components/ReagentList.presentation.test.ts +68 -0
  183. package/src/__tests__/components/SampleSelector.colors.test.ts +49 -0
  184. package/src/__tests__/components/SampleSelector.drag.test.ts +100 -0
  185. package/src/__tests__/components/SampleSelector.groups.test.ts +81 -0
  186. package/src/__tests__/components/SampleSelector.selection.test.ts +70 -0
  187. package/src/__tests__/components/SampleSelector.test.ts +32 -0
  188. package/src/__tests__/components/SampleSelectorSampleRow.test.ts +37 -0
  189. package/src/__tests__/components/ScheduleCalendar.test.ts +44 -0
  190. package/src/__tests__/components/SettingsModal.schema.test.ts +97 -0
  191. package/src/__tests__/components/WellPlate.colors.test.ts +28 -0
  192. package/src/__tests__/components/WellPlate.conditions.test.ts +68 -0
  193. package/src/__tests__/components/WellPlate.geometry.test.ts +54 -0
  194. package/src/__tests__/components/WellPlate.interaction.test.ts +171 -0
  195. package/src/__tests__/components/WellPlate.legend.test.ts +13 -0
  196. package/src/__tests__/components/WellPlate.rendering.test.ts +122 -0
  197. package/src/__tests__/components/WellPlate.sampleDrop.test.ts +70 -0
  198. package/src/__tests__/composables/autoGroup/classify.test.ts +107 -0
  199. package/src/__tests__/composables/autoGroup/columns.test.ts +135 -0
  200. package/src/__tests__/composables/autoGroup/compose.test.ts +227 -0
  201. package/src/__tests__/composables/autoGroup/cooccurrence.test.ts +91 -0
  202. package/src/__tests__/composables/autoGroup/fingerprint.test.ts +50 -0
  203. package/src/__tests__/composables/autoGroup/integration.test.ts +79 -0
  204. package/src/__tests__/composables/autoGroup/template.test.ts +70 -0
  205. package/src/__tests__/composables/autoGroup/tokenize.test.ts +33 -0
  206. package/src/__tests__/composables/useAutoGroup.test.ts +129 -625
  207. package/src/__tests__/composables/useAutoGroupInputSources.test.ts +107 -0
  208. package/src/__tests__/composables/useControlSchema.test.ts +23 -0
  209. package/src/__tests__/composables/useScheduleCalendarLayout.test.ts +89 -0
  210. package/src/__tests__/docs/extractDocsComponents.test.ts +142 -0
  211. package/src/__tests__/docs/extractDocsExports.test.ts +77 -0
  212. package/src/__tests__/docs/extractDocsParsing.test.ts +69 -0
  213. package/src/__tests__/docs/extractDocsTemplates.test.ts +54 -0
  214. package/src/__tests__/docs/extractDocsTheme.test.ts +89 -0
  215. package/src/__tests__/docs/frontendDocsCatalog.test.ts +1 -1
  216. package/src/__tests__/fixtures/auto-group/mixed-lc-ms-batch.txt +187 -0
  217. package/src/components/AppSidebar.story.vue +79 -6
  218. package/src/components/AppSidebar.vue +74 -6
  219. package/src/components/AppTopBar.navigation.ts +62 -0
  220. package/src/components/AppTopBar.vue +17 -44
  221. package/src/components/AutoGroupModal.story.vue +50 -0
  222. package/src/components/AutoGroupModal.vue +441 -158
  223. package/src/components/BaseCheckbox.story.vue +27 -0
  224. package/src/components/BaseCheckbox.vue +63 -1
  225. package/src/components/BaseToggle.story.vue +27 -0
  226. package/src/components/BaseToggle.vue +66 -1
  227. package/src/components/CollapsibleCard.vue +123 -45
  228. package/src/components/ControlWorkspaceView.vue +2 -6
  229. package/src/components/DoseCalculator.vue +13 -73
  230. package/src/components/DoseCalculatorVolumeField.vue +61 -0
  231. package/src/components/ExperimentTimeline.vue +6 -31
  232. package/src/components/FormBuilder.story.vue +13 -0
  233. package/src/components/FormBuilder.vue +2 -7
  234. package/src/components/PlateMapEditor.vue +32 -106
  235. package/src/components/PluginWorkspaceView.controls.ts +182 -0
  236. package/src/components/PluginWorkspaceView.navigation.ts +106 -0
  237. package/src/components/PluginWorkspaceView.props.ts +174 -0
  238. package/src/components/PluginWorkspaceView.shell.ts +67 -0
  239. package/src/components/PluginWorkspaceView.vue +88 -404
  240. package/src/components/ProtocolStep.presentation.ts +31 -0
  241. package/src/components/ProtocolStepEditor.state.ts +104 -0
  242. package/src/components/ProtocolStepEditor.vue +48 -179
  243. package/src/components/ProtocolStepParameterField.vue +134 -0
  244. package/src/components/ReagentList.presentation.ts +105 -0
  245. package/src/components/ReagentList.vue +16 -79
  246. package/src/components/SampleSelector.colors.ts +43 -0
  247. package/src/components/SampleSelector.drag.ts +164 -0
  248. package/src/components/SampleSelector.groups.ts +109 -0
  249. package/src/components/SampleSelector.selection.ts +103 -0
  250. package/src/components/SampleSelector.vue +82 -349
  251. package/src/components/SampleSelectorSampleRow.vue +64 -0
  252. package/src/components/ScheduleCalendar.vue +44 -199
  253. package/src/components/SettingsModal.schema.ts +71 -0
  254. package/src/components/SettingsModal.vue +16 -46
  255. package/src/components/WellPlate.colors.ts +56 -0
  256. package/src/components/WellPlate.conditions.ts +100 -0
  257. package/src/components/WellPlate.geometry.ts +91 -0
  258. package/src/components/WellPlate.interaction.ts +272 -0
  259. package/src/components/WellPlate.legend.ts +8 -0
  260. package/src/components/WellPlate.rendering.ts +105 -0
  261. package/src/components/WellPlate.sampleDrop.ts +73 -0
  262. package/src/components/WellPlate.vue +102 -550
  263. package/src/components/internal/FormFieldRendererInternal.vue +23 -5
  264. package/src/components/internal/PlateMapEditorToolbarInternal.vue +128 -0
  265. package/src/composables/autoGroup/classKey.ts +5 -0
  266. package/src/composables/autoGroup/classify.ts +205 -0
  267. package/src/composables/autoGroup/colors.ts +6 -0
  268. package/src/composables/autoGroup/columns.ts +226 -0
  269. package/src/composables/autoGroup/compose.ts +156 -0
  270. package/src/composables/autoGroup/cooccurrence.ts +46 -0
  271. package/src/composables/autoGroup/csv-shim.ts +44 -0
  272. package/src/composables/autoGroup/fingerprint.ts +49 -0
  273. package/src/composables/autoGroup/index.ts +20 -0
  274. package/src/composables/autoGroup/replicatePreGroup.ts +90 -0
  275. package/src/composables/autoGroup/template.ts +126 -0
  276. package/src/composables/autoGroup/tokenize.ts +41 -0
  277. package/src/composables/autoGroup/vocab.json +67 -0
  278. package/src/composables/autoGroupConstants.ts +4 -0
  279. package/src/composables/autoGroupGrouping.ts +148 -0
  280. package/src/composables/controlComponentBindings.ts +1 -1
  281. package/src/composables/controlSchemaAdapters.ts +4 -1
  282. package/src/composables/controlSchemaDoseDesign.ts +215 -0
  283. package/src/composables/controlSchemaFormFields.ts +4 -1
  284. package/src/composables/controlSchemaLayout.ts +1 -1
  285. package/src/composables/controlSchemaModel.ts +163 -0
  286. package/src/composables/controlSchemaNormalize.ts +1 -1
  287. package/src/composables/controlSchemaTypes.ts +372 -0
  288. package/src/composables/controlWorkspaceOptions.ts +1 -1
  289. package/src/composables/formBuilderSchema.ts +153 -0
  290. package/src/composables/pluginEndpointBuilder.ts +203 -0
  291. package/src/composables/protocolTemplateCatalog.ts +325 -0
  292. package/src/composables/useAutoGroup.ts +395 -549
  293. package/src/composables/useAutoGroupInputSources.ts +147 -0
  294. package/src/composables/useBioTemplateControls.ts +1 -1
  295. package/src/composables/useBioTemplatePresetWorkspace.ts +1 -1
  296. package/src/composables/useBioTemplateWorkspace.ts +1 -1
  297. package/src/composables/useControlSchema.ts +21 -692
  298. package/src/composables/useControlWorkspace.ts +7 -13
  299. package/src/composables/useForm.ts +5 -187
  300. package/src/composables/useFormBuilder.ts +11 -153
  301. package/src/composables/useFormValidation.ts +154 -0
  302. package/src/composables/usePluginClient.ts +10 -193
  303. package/src/composables/useProtocolTemplates.ts +10 -328
  304. package/src/composables/useScheduleCalendarLayout.ts +287 -0
  305. package/src/styles/components/app-sidebar.css +134 -6
  306. package/src/styles/components/auto-group-modal.css +248 -310
  307. package/src/styles/components/checkbox.css +87 -0
  308. package/src/styles/components/collapsible-card.css +154 -14
  309. package/src/styles/components/toggle.css +80 -0
  310. package/src/templates/controlSchemaTypes.ts +1 -1
  311. package/src/templates/templateAdapterTypes.ts +58 -0
  312. package/src/templates/templateCreateOptions.ts +208 -0
  313. package/src/templates/templateQpcrTypes.ts +48 -0
  314. package/src/templates/types.ts +79 -275
  315. package/src/types/auto-group.ts +107 -9
  316. package/src/types/componentLabTypes.ts +235 -0
  317. package/src/types/componentWorkflowTypes.ts +190 -0
  318. package/src/types/components.ts +95 -424
  319. package/src/types/form-builder.ts +3 -0
  320. package/src/types/index.ts +2 -0
  321. package/dist/components-DafPc4rM.js.map +0 -1
  322. package/dist/composables-BMkPQhVK.js.map +0 -1
  323. package/dist/templates-bUAWMn5L.js.map +0 -1
  324. package/dist/useProtocolTemplates-QZtHFFH2.js.map +0 -1
@@ -1,191 +1,32 @@
1
1
  <script setup lang="ts">
2
2
  /** Standard plugin workspace shell that combines AppLayout, AppTopBar, and AppSidebar with LEAF-style defaults. */
3
- import { computed, reactive, ref, useSlots, watch } from 'vue'
3
+ import { computed, useSlots } from 'vue'
4
4
  import type {
5
5
  AccountMenuItem,
6
6
  ExperimentSummary,
7
7
  PageSelectorItem,
8
- PageSelectorItemInput,
9
8
  PillNavItem,
10
- PillNavItemInput,
11
- PluginSwitcherInfo,
12
9
  PluginSwitcherPlugin,
13
- SidebarToolSection,
14
- TopBarSettingsConfig,
15
10
  PillNavOption,
16
- TopBarVariant,
17
11
  } from '../types'
18
- import type { FormEnhancements, FormSchema } from '../types/form-builder'
19
- import type {
20
- ControlComponentBinding,
21
- ControlComponentBindingsById,
22
- ControlComponentBindingsConfig,
23
- ControlComponentPropsByIdMap,
24
- ControlComponentPropsMap,
25
- ControlModel,
26
- ControlModelBinding,
27
- ControlSchema,
28
- ControlWorkspaceOptions,
29
- } from '../composables/useControlSchema'
30
- import {
31
- controlValuesToComponentBindings,
32
- controlValuesToComponentBindingsById,
33
- controlValuesToComponentProps,
34
- controlsToViewItems,
35
- defineControlModel,
36
- getDefaultControlView,
37
- getControlDefaults,
38
- mergeControlWorkspaceOptions,
39
- } from '../composables/useControlSchema'
40
- import {
41
- useAppExperiment,
42
- type AppExperimentRecord,
43
- } from '../composables/useAppExperiment'
12
+ import { useAppExperiment } from '../composables/useAppExperiment'
44
13
  import AppLayout from './AppLayout.vue'
45
14
  import AppSidebar from './AppSidebar.vue'
46
15
  import AppTopBar from './AppTopBar.vue'
16
+ import { usePluginWorkspaceControls } from './PluginWorkspaceView.controls'
17
+ import { usePluginWorkspaceNavigation } from './PluginWorkspaceView.navigation'
18
+ import {
19
+ getPluginWorkspaceSidebarSlotNames,
20
+ getPluginWorkspaceTopBarSlotNames,
21
+ hasPluginWorkspaceSidebarSurface,
22
+ } from './PluginWorkspaceView.shell'
23
+ import type {
24
+ PluginWorkspaceForwardedSlotProps,
25
+ PluginWorkspaceSlotProps,
26
+ PluginWorkspaceViewProps,
27
+ } from './PluginWorkspaceView.props'
47
28
 
48
- type SidebarVariant = 'default' | 'analysis'
49
-
50
- interface Props {
51
- /** App or plugin title shown in the top bar. */
52
- title?: string
53
- /** Secondary copy shown under the title. */
54
- subtitle?: string
55
- /** Top bar visual treatment. */
56
- topBarVariant?: TopBarVariant
57
- /** Home link used by the top bar brand icon. */
58
- homePath?: string
59
- /** Show the default MINT logo when no icon/logo slot is provided. */
60
- showLogo?: boolean
61
- /** Preferred route-level page selector entries. */
62
- pageSelector?: PageSelectorItemInput[]
63
- /** Active page selector id. Defaults to activeView. */
64
- currentPageSelectorId?: string
65
- /** Optional plugin switcher shown in the left navigation position. */
66
- pluginSwitcher?: PluginSwitcherInfo
67
- /** Preferred centered navigation for local modes inside the current route. */
68
- pillNav?: PillNavItemInput[]
69
- /** Active centered pill id. Defaults to activeView. */
70
- currentPillId?: string
71
- /** Show the theme toggle button. */
72
- showThemeToggle?: boolean
73
- /** Show the settings button and modal. */
74
- showSettings?: boolean
75
- /** Built-in settings modal configuration. */
76
- settingsConfig?: TopBarSettingsConfig
77
- /** Show the standalone badge when not integrated into the platform. */
78
- showStandaloneLabel?: boolean
79
- /** Custom standalone badge label. */
80
- standaloneLabel?: string
81
- /** Account dropdown entries. */
82
- accountMenu?: AccountMenuItem[]
83
- /** Show the notifications icon button. */
84
- showNotifications?: boolean
85
- /** Draw a notification dot on the notifications icon. */
86
- hasNotificationDot?: boolean
87
- /** Show the classic admin shortcut. */
88
- showAdmin?: boolean
89
- /** Route used by the classic admin shortcut. */
90
- adminPath?: string
91
- /** Show the classic profile button when accountMenu is not provided. */
92
- showProfile?: boolean
93
- /** Classic profile display name. */
94
- userName?: string
95
- /** Explicit classic profile initial. */
96
- userInitial?: string
97
- /** Classic profile email. */
98
- userEmail?: string
99
- /** Enable the built-in AppTopBar experiment popover and selector flow. */
100
- experimentShell?: boolean
101
- /** Current experiment mirrored into the AppTopBar experiment chip when experimentShell is enabled. */
102
- experiment?: AppExperimentRecord | null
103
- /** Save handler used by the AppTopBar experiment chip. Return a message to flash success. */
104
- experimentSave?: () => string | null | Promise<string | null>
105
- /** Disable the experiment save action. */
106
- experimentSaveDisabled?: boolean
107
- /** Tooltip shown when the experiment save action is disabled. */
108
- experimentSaveDisabledMessage?: string
109
-
110
- /** Active workspace view used by top bar navigation and sidebar panels. */
111
- activeView?: string
112
- /** Initial active view when activeView is uncontrolled. */
113
- defaultActiveView?: string
114
- /** Map of view IDs to sidebar tool sections. */
115
- panels?: Record<string, SidebarToolSection[]>
116
- /** Optional FormBuilder schemas keyed by section ID. */
117
- forms?: Record<string, FormSchema>
118
- /** Sidebar chrome title. */
119
- sidebarTitle?: string
120
- /** Sidebar chrome subtitle. */
121
- sidebarSubtitle?: string
122
- /** Optional compact badge/count rendered in the sidebar header. */
123
- sidebarBadge?: string | number
124
- /** AppSidebar visual preset. `analysis` matches the LEAF-style MINT analysis sidebar language. */
125
- sidebarVariant?: SidebarVariant
126
- /** Sidebar CSS width. Defaults to AppSidebar's variant width. */
127
- sidebarWidth?: string
128
- /** Sidebar position in AppLayout. */
129
- sidebarPosition?: 'left' | 'right'
130
- /** Convert the sidebar into an SDK-owned mobile overlay below the AppLayout breakpoint. */
131
- responsiveSidebar?: boolean
132
- /** Render the sidebar shell even when no panel matches the active view. */
133
- showSidebarWhenEmpty?: boolean
134
- /** Disable the built-in sidebar surface entirely. */
135
- showSidebar?: boolean
136
- /** DOM id for the AppSidebar scrollable content area. Use with route/tab-owned Teleport sidebars. */
137
- sidebarContentId?: string
138
- /** Compact AppSidebar density. */
139
- dense?: boolean
140
- /** Show a built-in collapse/expand button in the sidebar chrome. Defaults to AppSidebar's variant behavior. */
141
- sidebarCollapsible?: boolean
142
- /** Sidebar width when collapsed. */
143
- sidebarCollapsedWidth?: string
144
- /** Accessible label for the sidebar collapse action. */
145
- sidebarCollapseButtonLabel?: string
146
- /** Accessible label for the sidebar expand action. */
147
- sidebarExpandButtonLabel?: string
148
- /** Floating AppLayout style. */
149
- floating?: boolean
150
- /** Optional compact control model for generated sidebar forms. */
151
- model?: ControlModel | ControlModelBinding
152
- /** Compact control schema for generated sidebar forms. */
153
- controls?: ControlSchema
154
- /** Options passed to compact control schema generation. */
155
- controlOptions?: ControlWorkspaceOptions
156
- /** Optional SDK component bindings exposed to the default slot with resolved props. */
157
- componentBindings?: ControlComponentBindingsConfig
158
- /** Optional mapping from workspace values to component props exposed to the default slot. */
159
- componentProps?: ControlComponentPropsMap
160
- /** Optional named mappings from workspace values to component props exposed to the default slot. */
161
- componentPropsById?: ControlComponentPropsByIdMap
162
- /** Shared values for auto-rendered sidebar forms. Supports default v-model. */
163
- modelValue?: Record<string, unknown>
164
- /** Shared values for auto-rendered sidebar forms. */
165
- values?: Record<string, unknown>
166
- /** Runtime FormBuilder enhancements for auto-rendered sidebar forms. */
167
- formEnhancements?: FormEnhancements<Record<string, unknown>>
168
- /** Show submit/cancel actions inside auto-rendered sidebar forms. */
169
- showFormActions?: boolean
170
- /** Loading/saving state for auto-rendered sidebar forms. */
171
- formLoading?: boolean
172
- /** Disabled state for auto-rendered sidebar forms. */
173
- formDisabled?: boolean
174
- /** Readonly state for auto-rendered sidebar forms. */
175
- formReadonly?: boolean
176
- /** Size passed to auto-rendered sidebar forms. */
177
- formSize?: 'sm' | 'md' | 'lg'
178
- /** Controlled sidebar collapsed state. */
179
- sidebarCollapsed?: boolean
180
- /** Initial sidebar collapsed state when uncontrolled. */
181
- defaultSidebarCollapsed?: boolean
182
- /** Accessible label for the mobile sidebar toggle. */
183
- sidebarToggleLabel?: string
184
- /** Accessible label used when the mobile sidebar is open. */
185
- sidebarCloseLabel?: string
186
- }
187
-
188
- const props = withDefaults(defineProps<Props>(), {
29
+ const props = withDefaults(defineProps<PluginWorkspaceViewProps>(), {
189
30
  title: 'Workspace',
190
31
  subtitle: undefined,
191
32
  topBarVariant: 'card',
@@ -274,62 +115,32 @@ const emit = defineEmits<{
274
115
  'update:values': [values: Record<string, unknown>]
275
116
  'update:sidebarCollapsed': [value: boolean]
276
117
  'update:toggle': [sectionId: string, value: boolean]
118
+ 'section-action': [sectionId: string, actionId: string]
277
119
  'form-submit': [sectionId: string, values: Record<string, unknown>]
278
120
  'form-cancel': [sectionId: string]
279
121
  }>()
280
122
 
281
- interface PluginWorkspaceSlotProps {
282
- activeView: string
283
- setActiveView: (viewId: string) => void
284
- values: Record<string, unknown>
285
- componentBindings: ControlComponentBinding[]
286
- componentBindingsById: ControlComponentBindingsById
287
- componentProps: Record<string, unknown>
288
- componentPropsById: Record<string, Record<string, unknown>>
289
- }
290
-
291
- type ForwardedSlotProps = Record<string, unknown>
292
-
293
123
  defineSlots<{
294
124
  default?: (props: PluginWorkspaceSlotProps) => unknown
295
125
  topbar?: (props: PluginWorkspaceSlotProps) => unknown
296
126
  sidebar?: (props: PluginWorkspaceSlotProps) => unknown
297
- icon?: (props: ForwardedSlotProps) => unknown
298
- logo?: (props: ForwardedSlotProps) => unknown
299
- 'page-selector-icon'?: (props: ForwardedSlotProps) => unknown
300
- 'page-selector-item-icon'?: (props: ForwardedSlotProps) => unknown
301
- nav?: (props: ForwardedSlotProps) => unknown
302
- center?: (props: ForwardedSlotProps) => unknown
303
- actions?: (props: ForwardedSlotProps) => unknown
304
- 'account-menu-items'?: (props: ForwardedSlotProps) => unknown
305
- 'account-menu-item-icon'?: (props: ForwardedSlotProps) => unknown
306
- 'settings-appearance'?: (props: ForwardedSlotProps) => unknown
307
- header?: (props: ForwardedSlotProps) => unknown
308
- collapsed?: (props: ForwardedSlotProps) => unknown
309
- footer?: (props: ForwardedSlotProps) => unknown
127
+ icon?: (props: PluginWorkspaceForwardedSlotProps) => unknown
128
+ logo?: (props: PluginWorkspaceForwardedSlotProps) => unknown
129
+ 'page-selector-icon'?: (props: PluginWorkspaceForwardedSlotProps) => unknown
130
+ 'page-selector-item-icon'?: (props: PluginWorkspaceForwardedSlotProps) => unknown
131
+ nav?: (props: PluginWorkspaceForwardedSlotProps) => unknown
132
+ center?: (props: PluginWorkspaceForwardedSlotProps) => unknown
133
+ actions?: (props: PluginWorkspaceForwardedSlotProps) => unknown
134
+ 'account-menu-items'?: (props: PluginWorkspaceForwardedSlotProps) => unknown
135
+ 'account-menu-item-icon'?: (props: PluginWorkspaceForwardedSlotProps) => unknown
136
+ 'settings-appearance'?: (props: PluginWorkspaceForwardedSlotProps) => unknown
137
+ header?: (props: PluginWorkspaceForwardedSlotProps) => unknown
138
+ collapsed?: (props: PluginWorkspaceForwardedSlotProps) => unknown
139
+ 'collapsed-footer'?: (props: PluginWorkspaceForwardedSlotProps) => unknown
140
+ footer?: (props: PluginWorkspaceForwardedSlotProps) => unknown
310
141
  }>()
311
142
 
312
- const topBarForwardedSlots = new Set([
313
- 'icon',
314
- 'logo',
315
- 'page-selector-icon',
316
- 'page-selector-item-icon',
317
- 'nav',
318
- 'center',
319
- 'actions',
320
- 'account-menu-items',
321
- 'account-menu-item-icon',
322
- 'settings-appearance',
323
- ])
324
-
325
- const sidebarForwardedSlots = new Set([
326
- 'header',
327
- 'collapsed',
328
- 'footer',
329
- ])
330
-
331
143
  const slots = useSlots()
332
- const internalActiveView = ref(props.defaultActiveView)
333
144
 
334
145
  if (props.experimentShell) {
335
146
  useAppExperiment({
@@ -343,171 +154,77 @@ if (props.experimentShell) {
343
154
  }
344
155
 
345
156
  const topBarSlotNames = computed<string[]>(() =>
346
- Object.keys(slots).filter(name =>
347
- topBarForwardedSlots.has(name) || name.startsWith('settings-tab-'),
348
- ),
157
+ getPluginWorkspaceTopBarSlotNames(slots),
349
158
  )
350
159
 
351
160
  const sidebarSlotNames = computed<string[]>(() =>
352
- Object.keys(slots).filter(name =>
353
- sidebarForwardedSlots.has(name) || name.startsWith('section-'),
354
- ),
161
+ getPluginWorkspaceSidebarSlotNames(slots),
355
162
  )
356
163
 
357
- const resolvedModel = computed<ControlModelBinding | undefined>(() => {
358
- if (props.model === undefined) return undefined
359
- return isControlModelBinding(props.model) ? props.model : defineControlModel(props.model)
360
- })
361
-
362
- const resolvedControls = computed<ControlSchema | undefined>(() =>
363
- props.controls ?? resolvedModel.value?.controls,
364
- )
365
-
366
- const resolvedControlOptions = computed<ControlWorkspaceOptions>(() =>
367
- mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, props.controlOptions),
368
- )
369
-
370
- const externalControlValues = computed(() => props.modelValue ?? props.values)
371
- const internalControlValues = reactive<Record<string, unknown>>({})
372
- let syncingControlValues = false
373
-
374
- const generatedControlDefaults = computed<Record<string, unknown>>(() => {
375
- if (!resolvedControls.value) return {}
376
- return {
377
- ...getControlDefaults(resolvedControls.value),
378
- ...(resolvedControlOptions.value.initialValues ?? {}),
379
- }
380
- })
381
-
382
- syncResolvedControlValues()
383
-
384
- watch(
385
- [generatedControlDefaults, externalControlValues],
386
- syncResolvedControlValues,
387
- { deep: true },
388
- )
389
-
390
- watch(
164
+ const {
165
+ generatedPillNav,
166
+ generatedDefaultView,
391
167
  internalControlValues,
392
- () => {
393
- if (syncingControlValues) return
394
- emitControlValues()
168
+ resolvedComponentBindings,
169
+ resolvedComponentBindingsById,
170
+ resolvedComponentProps,
171
+ resolvedComponentPropsById,
172
+ handleControlValuesUpdate,
173
+ } = usePluginWorkspaceControls({
174
+ model: () => props.model,
175
+ controls: () => props.controls,
176
+ controlOptions: () => props.controlOptions,
177
+ modelValue: () => props.modelValue,
178
+ values: () => props.values,
179
+ componentBindings: () => props.componentBindings,
180
+ componentProps: () => props.componentProps,
181
+ componentPropsById: () => props.componentPropsById,
182
+ emitValues: (values) => {
183
+ emit('update:modelValue', values)
184
+ emit('update:values', values)
395
185
  },
396
- { deep: true, flush: 'sync' },
397
- )
398
-
399
- const resolvedComponentBindings = computed(() =>
400
- controlValuesToComponentBindings(
401
- internalControlValues,
402
- props.componentBindings ?? resolvedModel.value?.componentBindings,
403
- ),
404
- )
405
-
406
- const resolvedComponentBindingsById = computed(() =>
407
- controlValuesToComponentBindingsById(
408
- internalControlValues,
409
- props.componentBindings ?? resolvedModel.value?.componentBindings,
410
- ),
411
- )
412
-
413
- const resolvedComponentProps = computed(() => {
414
- const mapping = props.componentProps ?? resolvedModel.value?.componentProps
415
- return mapping === undefined ? {} : controlValuesToComponentProps(internalControlValues, mapping)
416
- })
417
-
418
- const resolvedComponentPropsById = computed(() => {
419
- const mappings = props.componentPropsById ?? resolvedModel.value?.componentPropsById
420
- if (mappings === undefined) return {}
421
-
422
- return Object.fromEntries(
423
- Object.entries(mappings).map(([id, mapping]) => [
424
- id,
425
- controlValuesToComponentProps(internalControlValues, mapping),
426
- ]),
427
- )
428
186
  })
429
187
 
430
- const generatedPillNav = computed<PillNavItem[]>(() => {
431
- if (!resolvedControls.value) return []
432
- return controlsToViewItems(resolvedControls.value, resolvedControlOptions.value)
188
+ const {
189
+ resolvedPillNav,
190
+ resolvedActiveView,
191
+ resolvedCurrentPillId,
192
+ resolvedCurrentPageSelectorId,
193
+ setActiveView,
194
+ handlePageSelectorSelect,
195
+ handlePillSelect,
196
+ } = usePluginWorkspaceNavigation({
197
+ activeView: () => props.activeView,
198
+ defaultActiveView: () => props.defaultActiveView,
199
+ currentPillId: () => props.currentPillId,
200
+ currentPageSelectorId: () => props.currentPageSelectorId,
201
+ pillNav: () => props.pillNav,
202
+ pageSelector: () => props.pageSelector,
203
+ panelIds: () => Object.keys(props.panels),
204
+ generatedPillNav,
205
+ generatedDefaultView,
206
+ emitActiveView: (viewId) => emit('update:activeView', viewId),
207
+ emitPageSelectorSelect: (page) => emit('page-selector-select', page),
208
+ emitPillSelect: (item) => emit('pill-select', item),
433
209
  })
434
210
 
435
- const generatedDefaultView = computed(() => {
436
- if (!resolvedControls.value) return ''
437
- return getDefaultControlView(resolvedControls.value, resolvedControlOptions.value)
438
- })
439
-
440
- const resolvedPillNav = computed<PillNavItemInput[] | undefined>(() => {
441
- if (props.pillNav !== undefined) return props.pillNav
442
- return generatedPillNav.value.length > 0 ? generatedPillNav.value : undefined
443
- })
444
-
445
- const firstConfiguredViewId = computed(() =>
446
- props.defaultActiveView
447
- ?? firstItemId(props.pillNav)
448
- ?? generatedDefaultView.value
449
- ?? firstItemId(props.pageSelector)
450
- ?? Object.keys(props.panels)[0]
451
- ?? '',
452
- )
453
-
454
- const resolvedActiveView = computed({
455
- get: () =>
456
- props.activeView
457
- ?? props.currentPillId
458
- ?? props.currentPageSelectorId
459
- ?? internalActiveView.value
460
- ?? firstConfiguredViewId.value,
461
- set: (value: string) => {
462
- internalActiveView.value = value
463
- emit('update:activeView', value)
464
- },
465
- })
466
-
467
- const resolvedCurrentPillId = computed(() => props.currentPillId ?? resolvedActiveView.value)
468
- const resolvedCurrentPageSelectorId = computed(() => props.currentPageSelectorId ?? resolvedActiveView.value)
469
-
470
211
  const hasSidebarSurface = computed(() => {
471
- if (!props.showSidebar) return false
472
- return (
473
- Object.keys(props.panels).length > 0
474
- || Object.keys(props.forms).length > 0
475
- || props.model !== undefined
476
- || props.controls !== undefined
477
- || props.showSidebarWhenEmpty
478
- || props.sidebarContentId !== undefined
479
- || props.sidebarTitle !== undefined
480
- || props.sidebarSubtitle !== undefined
481
- || props.sidebarBadge !== undefined
482
- || Boolean(slots.sidebar)
483
- || sidebarSlotNames.value.length > 0
484
- )
212
+ return hasPluginWorkspaceSidebarSurface({
213
+ showSidebar: props.showSidebar,
214
+ panels: props.panels,
215
+ forms: props.forms,
216
+ model: props.model,
217
+ controls: props.controls,
218
+ showSidebarWhenEmpty: props.showSidebarWhenEmpty,
219
+ sidebarContentId: props.sidebarContentId,
220
+ sidebarTitle: props.sidebarTitle,
221
+ sidebarSubtitle: props.sidebarSubtitle,
222
+ sidebarBadge: props.sidebarBadge,
223
+ hasSidebarSlot: Boolean(slots.sidebar),
224
+ sidebarSlotCount: sidebarSlotNames.value.length,
225
+ })
485
226
  })
486
227
 
487
- function firstItemId(items?: readonly (string | { id: string })[]): string | undefined {
488
- const item = items?.[0]
489
- if (item === undefined) return undefined
490
- return typeof item === 'string' ? item : item.id
491
- }
492
-
493
- function isControlModelBinding(model: ControlModel | ControlModelBinding): model is ControlModelBinding {
494
- return 'controls' in model && 'controlOptions' in model
495
- }
496
-
497
- function setActiveView(viewId: string) {
498
- resolvedActiveView.value = viewId
499
- }
500
-
501
- function handlePageSelectorSelect(page: PageSelectorItem) {
502
- setActiveView(page.id)
503
- emit('page-selector-select', page)
504
- }
505
-
506
- function handlePillSelect(item: PillNavItem) {
507
- setActiveView(item.id)
508
- emit('pill-select', item)
509
- }
510
-
511
228
  function handlePillOptionSelect(option: PillNavOption, item: PillNavItem) {
512
229
  emit('pill-option-select', option, item)
513
230
  }
@@ -516,16 +233,6 @@ function handleToggle(sectionId: string, value: boolean) {
516
233
  emit('update:toggle', sectionId, value)
517
234
  }
518
235
 
519
- function handleControlValuesUpdate(values: Record<string, unknown>) {
520
- syncingControlValues = true
521
- replaceControlValues({
522
- ...generatedControlDefaults.value,
523
- ...values,
524
- })
525
- syncingControlValues = false
526
- emitControlValues()
527
- }
528
-
529
236
  function handleFormSubmit(sectionId: string, values: Record<string, unknown>) {
530
237
  emit('form-submit', sectionId, values)
531
238
  }
@@ -534,30 +241,6 @@ function handleFormCancel(sectionId: string) {
534
241
  emit('form-cancel', sectionId)
535
242
  }
536
243
 
537
- function syncResolvedControlValues() {
538
- syncingControlValues = true
539
- replaceControlValues({
540
- ...generatedControlDefaults.value,
541
- ...(externalControlValues.value === undefined ? internalControlValues : externalControlValues.value),
542
- })
543
- syncingControlValues = false
544
- }
545
-
546
- function replaceControlValues(values: Record<string, unknown>) {
547
- for (const key of Object.keys(internalControlValues)) {
548
- if (!(key in values)) {
549
- delete internalControlValues[key]
550
- }
551
- }
552
- Object.assign(internalControlValues, values)
553
- }
554
-
555
- function emitControlValues() {
556
- const nextValues = { ...internalControlValues }
557
- emit('update:modelValue', nextValues)
558
- emit('update:values', nextValues)
559
- }
560
-
561
244
  </script>
562
245
 
563
246
  <template>
@@ -677,6 +360,7 @@ function emitControlValues() {
677
360
  @update:model-value="handleControlValuesUpdate"
678
361
  @update:collapsed="emit('update:sidebarCollapsed', $event)"
679
362
  @update:toggle="handleToggle"
363
+ @section-action="(sectionId, actionId) => emit('section-action', sectionId, actionId)"
680
364
  @form-submit="handleFormSubmit"
681
365
  @form-cancel="handleFormCancel"
682
366
  >
@@ -0,0 +1,31 @@
1
+ import type { ProtocolStepType } from '../types'
2
+
3
+ export const PROTOCOL_STEP_TYPE_ICONS: Record<ProtocolStepType, string> = {
4
+ incubation: 'M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z',
5
+ wash: 'M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z',
6
+ addition: 'M12 9v3m0 0v3m0-3h3m-3 0H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z',
7
+ measurement: 'M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z',
8
+ transfer: 'M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4',
9
+ centrifuge: 'M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15',
10
+ mix: 'M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z',
11
+ custom: 'M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z',
12
+ }
13
+
14
+ export const PROTOCOL_STEP_TYPE_COLORS: Record<ProtocolStepType, string> = {
15
+ incubation: '#F59E0B',
16
+ wash: '#06B6D4',
17
+ addition: '#10B981',
18
+ measurement: '#8B5CF6',
19
+ transfer: '#3B82F6',
20
+ centrifuge: '#6B7280',
21
+ mix: '#F97316',
22
+ custom: '#EC4899',
23
+ }
24
+
25
+ export function formatProtocolDuration(minutes: number | undefined): string {
26
+ if (minutes === undefined) return ''
27
+ if (minutes < 60) return `${minutes}m`
28
+ const hours = Math.floor(minutes / 60)
29
+ const mins = minutes % 60
30
+ return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`
31
+ }