@morscherlab/mint-sdk 1.0.0-rc.2 → 1.0.0-rc.5

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 (443) 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/AppTopBar.navigation.d.ts +11 -0
  41. package/dist/components/BaseButton.vue.d.ts +1 -1
  42. package/dist/components/BaseCheckbox.vue.d.ts +1 -1
  43. package/dist/components/BaseInput.vue.d.ts +2 -2
  44. package/dist/components/BasePill.vue.d.ts +1 -1
  45. package/dist/components/BaseRadioGroup.vue.d.ts +1 -1
  46. package/dist/components/BaseSelect.vue.d.ts +1 -1
  47. package/dist/components/BaseSlider.vue.d.ts +2 -2
  48. package/dist/components/BaseTextarea.vue.d.ts +2 -2
  49. package/dist/components/BaseToggle.vue.d.ts +1 -1
  50. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
  51. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +1 -1
  52. package/dist/components/ColorSlider.vue.d.ts +2 -2
  53. package/dist/components/ConcentrationInput.vue.d.ts +2 -2
  54. package/dist/components/DatePicker.vue.d.ts +1 -1
  55. package/dist/components/DateTimePicker.vue.d.ts +2 -2
  56. package/dist/components/DoseCalculatorVolumeField.vue.d.ts +15 -0
  57. package/dist/components/DropdownButton.vue.d.ts +1 -1
  58. package/dist/components/FileUploader.vue.d.ts +2 -2
  59. package/dist/components/FormulaInput.vue.d.ts +2 -2
  60. package/dist/components/IconButton.vue.d.ts +1 -1
  61. package/dist/components/LoadingSpinner.vue.d.ts +1 -1
  62. package/dist/components/MoleculeInput.vue.d.ts +2 -2
  63. package/dist/components/MultiSelect.vue.d.ts +1 -1
  64. package/dist/components/NumberInput.vue.d.ts +1 -1
  65. package/dist/components/PlateMapEditor.vue.d.ts +6 -6
  66. package/dist/components/PluginWorkspaceView.controls.d.ts +28 -0
  67. package/dist/components/PluginWorkspaceView.navigation.d.ts +29 -0
  68. package/dist/components/PluginWorkspaceView.props.d.ts +151 -0
  69. package/dist/components/PluginWorkspaceView.shell.d.ts +19 -0
  70. package/dist/components/PluginWorkspaceView.vue.d.ts +46 -195
  71. package/dist/components/ProgressBar.vue.d.ts +1 -1
  72. package/dist/components/ProtocolStep.presentation.d.ts +4 -0
  73. package/dist/components/ProtocolStepEditor.state.d.ts +18 -0
  74. package/dist/components/ProtocolStepParameterField.vue.d.ts +12 -0
  75. package/dist/components/ReagentList.presentation.d.ts +16 -0
  76. package/dist/components/ResourceCard.vue.d.ts +1 -1
  77. package/dist/components/SampleSelector.colors.d.ts +13 -0
  78. package/dist/components/SampleSelector.drag.d.ts +24 -0
  79. package/dist/components/SampleSelector.groups.d.ts +15 -0
  80. package/dist/components/SampleSelector.selection.d.ts +26 -0
  81. package/dist/components/SampleSelector.vue.d.ts +4 -1
  82. package/dist/components/SampleSelectorSampleRow.vue.d.ts +21 -0
  83. package/dist/components/SegmentedControl.vue.d.ts +1 -1
  84. package/dist/components/SequenceInput.vue.d.ts +2 -2
  85. package/dist/components/SequenceProgressBar.vue.d.ts +1 -1
  86. package/dist/components/SettingsModal.schema.d.ts +9 -0
  87. package/dist/components/StatusIndicator.vue.d.ts +1 -1
  88. package/dist/components/TagsInput.vue.d.ts +2 -2
  89. package/dist/components/TimePicker.vue.d.ts +2 -2
  90. package/dist/components/TimeRangeInput.vue.d.ts +1 -1
  91. package/dist/components/UnitInput.vue.d.ts +2 -2
  92. package/dist/components/WellPlate.colors.d.ts +9 -0
  93. package/dist/components/WellPlate.conditions.d.ts +26 -0
  94. package/dist/components/WellPlate.geometry.d.ts +23 -0
  95. package/dist/components/WellPlate.interaction.d.ts +71 -0
  96. package/dist/components/WellPlate.legend.d.ts +2 -0
  97. package/dist/components/WellPlate.rendering.d.ts +24 -0
  98. package/dist/components/WellPlate.sampleDrop.d.ts +8 -0
  99. package/dist/components/WellPlate.vue.d.ts +1 -1
  100. package/dist/components/index.js +2 -2
  101. package/dist/components/internal/ActionItemInternal.vue.d.ts +1 -1
  102. package/dist/components/internal/PlateMapEditorToolbarInternal.vue.d.ts +28 -0
  103. package/dist/{components-BhK-dW99.js → components-DtHA2bgp.js} +3754 -2991
  104. package/dist/components-DtHA2bgp.js.map +1 -0
  105. package/dist/composables/autoGroup/classKey.d.ts +4 -0
  106. package/dist/composables/autoGroup/classify.d.ts +28 -0
  107. package/dist/composables/autoGroup/colors.d.ts +2 -0
  108. package/dist/composables/autoGroup/columns.d.ts +10 -0
  109. package/dist/composables/autoGroup/compose.d.ts +8 -0
  110. package/dist/composables/autoGroup/cooccurrence.d.ts +2 -0
  111. package/dist/composables/autoGroup/csv-shim.d.ts +2 -0
  112. package/dist/composables/autoGroup/fingerprint.d.ts +3 -0
  113. package/dist/composables/autoGroup/index.d.ts +16 -0
  114. package/dist/composables/autoGroup/replicatePreGroup.d.ts +38 -0
  115. package/dist/composables/autoGroup/template.d.ts +15 -0
  116. package/dist/composables/autoGroup/tokenize.d.ts +8 -0
  117. package/dist/composables/autoGroupConstants.d.ts +1 -0
  118. package/dist/composables/autoGroupGrouping.d.ts +3 -0
  119. package/dist/composables/controlComponentBindings.d.ts +7 -0
  120. package/dist/composables/controlSchemaAdapters.d.ts +20 -0
  121. package/dist/composables/controlSchemaDoseDesign.d.ts +11 -0
  122. package/dist/composables/controlSchemaFormFields.d.ts +3 -0
  123. package/dist/composables/controlSchemaLayout.d.ts +7 -0
  124. package/dist/composables/controlSchemaModel.d.ts +5 -0
  125. package/dist/composables/controlSchemaNormalize.d.ts +15 -0
  126. package/dist/composables/controlSchemaTypes.d.ts +305 -0
  127. package/dist/composables/controlSchemaUtils.d.ts +9 -0
  128. package/dist/composables/controlWorkspaceOptions.d.ts +2 -0
  129. package/dist/composables/formBuilderSchema.d.ts +18 -0
  130. package/dist/composables/index.js +3 -3
  131. package/dist/composables/pluginEndpointBuilder.d.ts +13 -0
  132. package/dist/composables/protocolTemplateCatalog.d.ts +26 -0
  133. package/dist/composables/useAutoGroup.d.ts +61 -74
  134. package/dist/composables/useAutoGroupInputSources.d.ts +32 -0
  135. package/dist/composables/useBioTemplateControls.d.ts +1 -1
  136. package/dist/composables/useBioTemplatePresetWorkspace.d.ts +1 -1
  137. package/dist/composables/useBioTemplateWorkspace.d.ts +1 -1
  138. package/dist/composables/useControlSchema.d.ts +8 -346
  139. package/dist/composables/useControlWorkspace.d.ts +5 -0
  140. package/dist/composables/useForm.d.ts +2 -33
  141. package/dist/composables/useFormBuilder.d.ts +2 -9
  142. package/dist/composables/useFormValidation.d.ts +34 -0
  143. package/dist/composables/usePluginClient.d.ts +1 -4
  144. package/dist/composables/useProtocolTemplates.d.ts +2 -24
  145. package/dist/composables/useScheduleCalendarLayout.d.ts +49 -0
  146. package/dist/{composables-Bg7CFuNz.js → composables-Dlg8jenH.js} +33 -31
  147. package/dist/composables-Dlg8jenH.js.map +1 -0
  148. package/dist/index.js +4 -4
  149. package/dist/install.js +2 -2
  150. package/dist/styles.css +547 -516
  151. package/dist/templates/adapters.d.ts +14 -47
  152. package/dist/templates/assayLookups.d.ts +3 -0
  153. package/dist/templates/assayMatrixAdapters.d.ts +6 -0
  154. package/dist/templates/assayMatrixBuilder.d.ts +2 -0
  155. package/dist/templates/assayNormalizers.d.ts +4 -0
  156. package/dist/templates/builderDefaults.d.ts +1 -0
  157. package/dist/templates/builderIdUtils.d.ts +4 -0
  158. package/dist/templates/builderPresetControls.d.ts +10 -0
  159. package/dist/templates/builderReadUtils.d.ts +8 -0
  160. package/dist/templates/builders.d.ts +26 -67
  161. package/dist/templates/calibrationCurveAdapters.d.ts +4 -0
  162. package/dist/templates/calibrationCurveBuilder.d.ts +2 -0
  163. package/dist/templates/calibrationNormalizers.d.ts +5 -0
  164. package/dist/templates/componentBindingCatalog.d.ts +25 -0
  165. package/dist/templates/componentBindingHelpers.d.ts +17 -0
  166. package/dist/templates/componentDoseResponseProps.d.ts +3 -0
  167. package/dist/templates/componentGenericProps.d.ts +8 -0
  168. package/dist/templates/componentPlateHelpers.d.ts +5 -0
  169. package/dist/templates/componentPlateMapProps.d.ts +3 -0
  170. package/dist/templates/componentPropsFactory.d.ts +3 -0
  171. package/dist/templates/componentQpcrPlateProps.d.ts +3 -0
  172. package/dist/templates/componentTargetResolvers.d.ts +5 -0
  173. package/dist/templates/componentTemplateProps.d.ts +3 -0
  174. package/dist/templates/controlSchemaClone.d.ts +4 -0
  175. package/dist/templates/controlSchemaConstants.d.ts +10 -0
  176. package/dist/templates/controlSchemaMerge.d.ts +3 -0
  177. package/dist/templates/controlSchemaTargets.d.ts +17 -0
  178. package/dist/templates/controlSchemaTypes.d.ts +4 -0
  179. package/dist/templates/controlSchemas.d.ts +4 -4
  180. package/dist/templates/defaultBioTemplateBuilder.d.ts +2 -0
  181. package/dist/templates/doseResponseAdapters.d.ts +4 -0
  182. package/dist/templates/doseResponseBuilder.d.ts +2 -0
  183. package/dist/templates/elisaAssayCollectionBuilder.d.ts +2 -0
  184. package/dist/templates/flowCytometryAssayCollectionBuilder.d.ts +2 -0
  185. package/dist/templates/flowCytometryPanelBuilder.d.ts +2 -0
  186. package/dist/templates/flowNormalizers.d.ts +8 -0
  187. package/dist/templates/flowPanelAdapters.d.ts +4 -0
  188. package/dist/templates/index.js +1 -1
  189. package/dist/templates/instrumentRunAdapterHelpers.d.ts +8 -0
  190. package/dist/templates/instrumentRunAdapters.d.ts +8 -0
  191. package/dist/templates/instrumentRunBuilder.d.ts +2 -0
  192. package/dist/templates/lcmsBatchCollectionBuilder.d.ts +2 -0
  193. package/dist/templates/plateGeometry.d.ts +4 -0
  194. package/dist/templates/plateMapAdapters.d.ts +3 -0
  195. package/dist/templates/plateMapBuilder.d.ts +2 -0
  196. package/dist/templates/presetControlSchemas.d.ts +534 -0
  197. package/dist/templates/protocolAdapters.d.ts +5 -0
  198. package/dist/templates/protocolNormalizers.d.ts +6 -0
  199. package/dist/templates/protocolStepsBuilder.d.ts +2 -0
  200. package/dist/templates/qpcrAdapters.d.ts +5 -0
  201. package/dist/templates/qpcrExpressionCollectionBuilder.d.ts +2 -0
  202. package/dist/templates/qpcrPlateBuilder.d.ts +2 -0
  203. package/dist/templates/reagentAdapters.d.ts +5 -0
  204. package/dist/templates/reagentListBuilder.d.ts +2 -0
  205. package/dist/templates/runNormalizers.d.ts +10 -0
  206. package/dist/templates/sampleNormalizers.d.ts +4 -0
  207. package/dist/templates/samplePrepAdapters.d.ts +4 -0
  208. package/dist/templates/samplePrepBuilder.d.ts +2 -0
  209. package/dist/templates/sampleSheetAdapters.d.ts +5 -0
  210. package/dist/templates/sampleSheetBuilder.d.ts +2 -0
  211. package/dist/templates/targetedMetabolomicsCollectionBuilder.d.ts +2 -0
  212. package/dist/templates/targetedMetabolomicsHelpers.d.ts +5 -0
  213. package/dist/templates/templateAdapterTypes.d.ts +48 -0
  214. package/dist/templates/templateControlSchemas.d.ts +400 -0
  215. package/dist/templates/templateCreateOptions.d.ts +165 -0
  216. package/dist/templates/templateEnvelopes.d.ts +9 -0
  217. package/dist/templates/templatePackCollectionBuilder.d.ts +2 -0
  218. package/dist/templates/templatePresetCollectionBuilder.d.ts +18 -0
  219. package/dist/templates/templateQpcrTypes.d.ts +42 -0
  220. package/dist/templates/templateValidators.d.ts +13 -0
  221. package/dist/templates/timeCourseAdapters.d.ts +5 -0
  222. package/dist/templates/timeCourseBuilder.d.ts +2 -0
  223. package/dist/templates/types.d.ts +5 -250
  224. package/dist/templates/wellPlateScreenCollectionBuilder.d.ts +2 -0
  225. package/dist/templates/westernBlotAssayCollectionBuilder.d.ts +2 -0
  226. package/dist/{templates-BorLR_7p.js → templates-DtdUvJ4c.js} +3565 -3411
  227. package/dist/templates-DtdUvJ4c.js.map +1 -0
  228. package/dist/types/auto-group.d.ts +79 -9
  229. package/dist/types/componentLabTypes.d.ts +161 -0
  230. package/dist/types/componentWorkflowTypes.d.ts +150 -0
  231. package/dist/types/components.d.ts +2 -311
  232. package/dist/{useProtocolTemplates-n6AJqSqv.js → useProtocolTemplates-Bm5vyH4_.js} +1220 -454
  233. package/dist/useProtocolTemplates-Bm5vyH4_.js.map +1 -0
  234. package/package.json +1 -1
  235. package/src/__tests__/components/AppTopBar.navigation.test.ts +70 -0
  236. package/src/__tests__/components/DoseCalculatorVolumeField.test.ts +53 -0
  237. package/src/__tests__/components/PlateMapEditorToolbarInternal.test.ts +54 -0
  238. package/src/__tests__/components/PluginWorkspaceView.controls.test.ts +156 -0
  239. package/src/__tests__/components/PluginWorkspaceView.navigation.test.ts +102 -0
  240. package/src/__tests__/components/PluginWorkspaceView.shell.test.ts +41 -0
  241. package/src/__tests__/components/ProtocolStep.presentation.test.ts +31 -0
  242. package/src/__tests__/components/ProtocolStepEditor.state.test.ts +165 -0
  243. package/src/__tests__/components/ProtocolStepParameterField.test.ts +44 -0
  244. package/src/__tests__/components/ReagentList.presentation.test.ts +68 -0
  245. package/src/__tests__/components/SampleSelector.colors.test.ts +49 -0
  246. package/src/__tests__/components/SampleSelector.drag.test.ts +100 -0
  247. package/src/__tests__/components/SampleSelector.groups.test.ts +81 -0
  248. package/src/__tests__/components/SampleSelector.selection.test.ts +70 -0
  249. package/src/__tests__/components/SampleSelector.test.ts +32 -0
  250. package/src/__tests__/components/SampleSelectorSampleRow.test.ts +37 -0
  251. package/src/__tests__/components/ScheduleCalendar.test.ts +44 -0
  252. package/src/__tests__/components/SettingsModal.schema.test.ts +97 -0
  253. package/src/__tests__/components/WellPlate.colors.test.ts +28 -0
  254. package/src/__tests__/components/WellPlate.conditions.test.ts +68 -0
  255. package/src/__tests__/components/WellPlate.geometry.test.ts +54 -0
  256. package/src/__tests__/components/WellPlate.interaction.test.ts +171 -0
  257. package/src/__tests__/components/WellPlate.legend.test.ts +13 -0
  258. package/src/__tests__/components/WellPlate.rendering.test.ts +122 -0
  259. package/src/__tests__/components/WellPlate.sampleDrop.test.ts +70 -0
  260. package/src/__tests__/composables/autoGroup/classify.test.ts +107 -0
  261. package/src/__tests__/composables/autoGroup/columns.test.ts +135 -0
  262. package/src/__tests__/composables/autoGroup/compose.test.ts +227 -0
  263. package/src/__tests__/composables/autoGroup/cooccurrence.test.ts +91 -0
  264. package/src/__tests__/composables/autoGroup/fingerprint.test.ts +50 -0
  265. package/src/__tests__/composables/autoGroup/integration.test.ts +79 -0
  266. package/src/__tests__/composables/autoGroup/template.test.ts +70 -0
  267. package/src/__tests__/composables/autoGroup/tokenize.test.ts +33 -0
  268. package/src/__tests__/composables/useAutoGroup.test.ts +129 -625
  269. package/src/__tests__/composables/useAutoGroupInputSources.test.ts +107 -0
  270. package/src/__tests__/composables/useControlSchema.test.ts +23 -0
  271. package/src/__tests__/composables/useScheduleCalendarLayout.test.ts +89 -0
  272. package/src/__tests__/docs/extractDocsComponents.test.ts +142 -0
  273. package/src/__tests__/docs/extractDocsExports.test.ts +77 -0
  274. package/src/__tests__/docs/extractDocsParsing.test.ts +69 -0
  275. package/src/__tests__/docs/extractDocsTemplates.test.ts +54 -0
  276. package/src/__tests__/docs/extractDocsTheme.test.ts +89 -0
  277. package/src/__tests__/docs/frontendDocsCatalog.test.ts +1 -1
  278. package/src/__tests__/fixtures/auto-group/mixed-lc-ms-batch.txt +187 -0
  279. package/src/components/AppSidebar.vue +2 -6
  280. package/src/components/AppTopBar.navigation.ts +62 -0
  281. package/src/components/AppTopBar.vue +17 -44
  282. package/src/components/AutoGroupModal.story.vue +50 -0
  283. package/src/components/AutoGroupModal.vue +441 -158
  284. package/src/components/ControlWorkspaceView.vue +2 -6
  285. package/src/components/DoseCalculator.vue +13 -73
  286. package/src/components/DoseCalculatorVolumeField.vue +61 -0
  287. package/src/components/ExperimentTimeline.vue +6 -31
  288. package/src/components/FormBuilder.vue +2 -7
  289. package/src/components/PlateMapEditor.vue +32 -106
  290. package/src/components/PluginWorkspaceView.controls.ts +182 -0
  291. package/src/components/PluginWorkspaceView.navigation.ts +106 -0
  292. package/src/components/PluginWorkspaceView.props.ts +174 -0
  293. package/src/components/PluginWorkspaceView.shell.ts +66 -0
  294. package/src/components/PluginWorkspaceView.vue +85 -404
  295. package/src/components/ProtocolStep.presentation.ts +31 -0
  296. package/src/components/ProtocolStepEditor.state.ts +104 -0
  297. package/src/components/ProtocolStepEditor.vue +48 -179
  298. package/src/components/ProtocolStepParameterField.vue +134 -0
  299. package/src/components/ReagentList.presentation.ts +105 -0
  300. package/src/components/ReagentList.vue +16 -79
  301. package/src/components/SampleSelector.colors.ts +43 -0
  302. package/src/components/SampleSelector.drag.ts +164 -0
  303. package/src/components/SampleSelector.groups.ts +109 -0
  304. package/src/components/SampleSelector.selection.ts +103 -0
  305. package/src/components/SampleSelector.vue +82 -349
  306. package/src/components/SampleSelectorSampleRow.vue +64 -0
  307. package/src/components/ScheduleCalendar.vue +44 -199
  308. package/src/components/SettingsModal.schema.ts +71 -0
  309. package/src/components/SettingsModal.vue +16 -46
  310. package/src/components/WellPlate.colors.ts +56 -0
  311. package/src/components/WellPlate.conditions.ts +100 -0
  312. package/src/components/WellPlate.geometry.ts +91 -0
  313. package/src/components/WellPlate.interaction.ts +272 -0
  314. package/src/components/WellPlate.legend.ts +8 -0
  315. package/src/components/WellPlate.rendering.ts +105 -0
  316. package/src/components/WellPlate.sampleDrop.ts +73 -0
  317. package/src/components/WellPlate.vue +102 -550
  318. package/src/components/internal/PlateMapEditorToolbarInternal.vue +128 -0
  319. package/src/composables/autoGroup/classKey.ts +5 -0
  320. package/src/composables/autoGroup/classify.ts +205 -0
  321. package/src/composables/autoGroup/colors.ts +6 -0
  322. package/src/composables/autoGroup/columns.ts +226 -0
  323. package/src/composables/autoGroup/compose.ts +156 -0
  324. package/src/composables/autoGroup/cooccurrence.ts +46 -0
  325. package/src/composables/autoGroup/csv-shim.ts +44 -0
  326. package/src/composables/autoGroup/fingerprint.ts +49 -0
  327. package/src/composables/autoGroup/index.ts +20 -0
  328. package/src/composables/autoGroup/replicatePreGroup.ts +90 -0
  329. package/src/composables/autoGroup/template.ts +126 -0
  330. package/src/composables/autoGroup/tokenize.ts +41 -0
  331. package/src/composables/autoGroup/vocab.json +67 -0
  332. package/src/composables/autoGroupConstants.ts +4 -0
  333. package/src/composables/autoGroupGrouping.ts +148 -0
  334. package/src/composables/controlComponentBindings.ts +80 -0
  335. package/src/composables/controlSchemaAdapters.ts +196 -0
  336. package/src/composables/controlSchemaDoseDesign.ts +215 -0
  337. package/src/composables/controlSchemaFormFields.ts +61 -0
  338. package/src/composables/controlSchemaLayout.ts +59 -0
  339. package/src/composables/controlSchemaModel.ts +163 -0
  340. package/src/composables/controlSchemaNormalize.ts +101 -0
  341. package/src/composables/controlSchemaTypes.ts +364 -0
  342. package/src/composables/controlSchemaUtils.ts +36 -0
  343. package/src/composables/controlWorkspaceOptions.ts +21 -0
  344. package/src/composables/formBuilderSchema.ts +153 -0
  345. package/src/composables/pluginEndpointBuilder.ts +203 -0
  346. package/src/composables/protocolTemplateCatalog.ts +325 -0
  347. package/src/composables/useAutoGroup.ts +395 -549
  348. package/src/composables/useAutoGroupInputSources.ts +147 -0
  349. package/src/composables/useBioTemplateControls.ts +1 -1
  350. package/src/composables/useBioTemplatePresetWorkspace.ts +1 -1
  351. package/src/composables/useBioTemplateWorkspace.ts +1 -1
  352. package/src/composables/useControlSchema.ts +64 -1312
  353. package/src/composables/useControlWorkspace.ts +201 -0
  354. package/src/composables/useForm.ts +5 -187
  355. package/src/composables/useFormBuilder.ts +11 -153
  356. package/src/composables/useFormValidation.ts +154 -0
  357. package/src/composables/usePluginClient.ts +10 -193
  358. package/src/composables/useProtocolTemplates.ts +10 -328
  359. package/src/composables/useScheduleCalendarLayout.ts +287 -0
  360. package/src/styles/components/auto-group-modal.css +248 -310
  361. package/src/templates/adapters.ts +89 -930
  362. package/src/templates/assayLookups.ts +33 -0
  363. package/src/templates/assayMatrixAdapters.ts +78 -0
  364. package/src/templates/assayMatrixBuilder.ts +59 -0
  365. package/src/templates/assayNormalizers.ts +34 -0
  366. package/src/templates/builderDefaults.ts +11 -0
  367. package/src/templates/builderIdUtils.ts +20 -0
  368. package/src/templates/builderPresetControls.ts +165 -0
  369. package/src/templates/builderReadUtils.ts +57 -0
  370. package/src/templates/builders.ts +122 -2350
  371. package/src/templates/calibrationCurveAdapters.ts +59 -0
  372. package/src/templates/calibrationCurveBuilder.ts +99 -0
  373. package/src/templates/calibrationNormalizers.ts +60 -0
  374. package/src/templates/componentBindingCatalog.ts +90 -0
  375. package/src/templates/componentBindingHelpers.ts +93 -0
  376. package/src/templates/componentBindings.ts +12 -461
  377. package/src/templates/componentDoseResponseProps.ts +42 -0
  378. package/src/templates/componentGenericProps.ts +77 -0
  379. package/src/templates/componentPlateHelpers.ts +29 -0
  380. package/src/templates/componentPlateMapProps.ts +32 -0
  381. package/src/templates/componentPropsFactory.ts +21 -0
  382. package/src/templates/componentQpcrPlateProps.ts +28 -0
  383. package/src/templates/componentTargetResolvers.ts +69 -0
  384. package/src/templates/componentTemplateProps.ts +78 -0
  385. package/src/templates/controlSchemaClone.ts +32 -0
  386. package/src/templates/controlSchemaConstants.ts +11 -0
  387. package/src/templates/controlSchemaMerge.ts +40 -0
  388. package/src/templates/controlSchemaTargets.ts +87 -0
  389. package/src/templates/controlSchemaTypes.ts +20 -0
  390. package/src/templates/controlSchemas.ts +22 -704
  391. package/src/templates/defaultBioTemplateBuilder.ts +124 -0
  392. package/src/templates/doseResponseAdapters.ts +45 -0
  393. package/src/templates/doseResponseBuilder.ts +44 -0
  394. package/src/templates/elisaAssayCollectionBuilder.ts +62 -0
  395. package/src/templates/flowCytometryAssayCollectionBuilder.ts +41 -0
  396. package/src/templates/flowCytometryPanelBuilder.ts +53 -0
  397. package/src/templates/flowNormalizers.ts +58 -0
  398. package/src/templates/flowPanelAdapters.ts +58 -0
  399. package/src/templates/instrumentRunAdapterHelpers.ts +94 -0
  400. package/src/templates/instrumentRunAdapters.ts +163 -0
  401. package/src/templates/instrumentRunBuilder.ts +97 -0
  402. package/src/templates/lcmsBatchCollectionBuilder.ts +38 -0
  403. package/src/templates/plateGeometry.ts +62 -0
  404. package/src/templates/plateMapAdapters.ts +36 -0
  405. package/src/templates/plateMapBuilder.ts +43 -0
  406. package/src/templates/presetControlSchemas.ts +258 -0
  407. package/src/templates/protocolAdapters.ts +69 -0
  408. package/src/templates/protocolNormalizers.ts +37 -0
  409. package/src/templates/protocolStepsBuilder.ts +36 -0
  410. package/src/templates/qpcrAdapters.ts +104 -0
  411. package/src/templates/qpcrExpressionCollectionBuilder.ts +33 -0
  412. package/src/templates/qpcrPlateBuilder.ts +96 -0
  413. package/src/templates/reagentAdapters.ts +77 -0
  414. package/src/templates/reagentListBuilder.ts +30 -0
  415. package/src/templates/runNormalizers.ts +63 -0
  416. package/src/templates/sampleNormalizers.ts +58 -0
  417. package/src/templates/samplePrepAdapters.ts +63 -0
  418. package/src/templates/samplePrepBuilder.ts +51 -0
  419. package/src/templates/sampleSheetAdapters.ts +75 -0
  420. package/src/templates/sampleSheetBuilder.ts +23 -0
  421. package/src/templates/targetedMetabolomicsCollectionBuilder.ts +79 -0
  422. package/src/templates/targetedMetabolomicsHelpers.ts +102 -0
  423. package/src/templates/templateAdapterTypes.ts +58 -0
  424. package/src/templates/templateControlSchemas.ts +320 -0
  425. package/src/templates/templateCreateOptions.ts +208 -0
  426. package/src/templates/templateEnvelopes.ts +137 -0
  427. package/src/templates/templatePackCollectionBuilder.ts +23 -0
  428. package/src/templates/templatePresetCollectionBuilder.ts +139 -0
  429. package/src/templates/templateQpcrTypes.ts +48 -0
  430. package/src/templates/templateValidators.ts +414 -0
  431. package/src/templates/timeCourseAdapters.ts +73 -0
  432. package/src/templates/timeCourseBuilder.ts +64 -0
  433. package/src/templates/types.ts +79 -275
  434. package/src/templates/wellPlateScreenCollectionBuilder.ts +36 -0
  435. package/src/templates/westernBlotAssayCollectionBuilder.ts +68 -0
  436. package/src/types/auto-group.ts +107 -9
  437. package/src/types/componentLabTypes.ts +235 -0
  438. package/src/types/componentWorkflowTypes.ts +190 -0
  439. package/src/types/components.ts +74 -424
  440. package/dist/components-BhK-dW99.js.map +0 -1
  441. package/dist/composables-Bg7CFuNz.js.map +0 -1
  442. package/dist/templates-BorLR_7p.js.map +0 -1
  443. package/dist/useProtocolTemplates-n6AJqSqv.js.map +0 -1
@@ -13,7 +13,7 @@ import type {
13
13
  ControlWorkspaceOptions,
14
14
  UseControlWorkspaceReturn,
15
15
  } from '../composables/useControlSchema'
16
- import { defineControlModel, mergeControlWorkspaceOptions, useControlWorkspace } from '../composables/useControlSchema'
16
+ import { mergeControlWorkspaceOptions, resolveControlModel, useControlWorkspace } from '../composables/useControlSchema'
17
17
  import AppLayout from './AppLayout.vue'
18
18
  import AppSidebar from './AppSidebar.vue'
19
19
  import AppTopBar from './AppTopBar.vue'
@@ -156,8 +156,7 @@ const props = withDefaults(defineProps<Props>(), {
156
156
 
157
157
  const externalValues = computed(() => props.modelValue ?? props.values)
158
158
  const resolvedModel = computed<ControlModelBinding | undefined>(() => {
159
- if (props.model === undefined) return undefined
160
- return isControlModelBinding(props.model) ? props.model : defineControlModel(props.model)
159
+ return resolveControlModel(props.model)
161
160
  })
162
161
  const resolvedControls = computed<ControlSchema>(() => props.controls ?? resolvedModel.value?.controls ?? {})
163
162
  const baseControlOptions = computed<ControlWorkspaceOptions>(() =>
@@ -282,9 +281,6 @@ function isPlainRecord(value: unknown): value is Record<string, unknown> {
282
281
  return typeof value === 'object' && value !== null && !Array.isArray(value)
283
282
  }
284
283
 
285
- function isControlModelBinding(model: ControlModel | ControlModelBinding): model is ControlModelBinding {
286
- return 'controlOptions' in model
287
- }
288
284
  </script>
289
285
 
290
286
  <template>
@@ -9,11 +9,11 @@ import {
9
9
  import {
10
10
  useDoseCalculator,
11
11
  type VolumeValue,
12
- type VolumeUnit,
13
12
  type DilutionResult,
14
13
  type SerialDilutionResult,
15
14
  type WellConcentration,
16
15
  } from '../composables/useDoseCalculator'
16
+ import DoseCalculatorVolumeField from './DoseCalculatorVolumeField.vue'
17
17
 
18
18
  type CalculatorMode = 'dilution' | 'serial' | 'conversion'
19
19
 
@@ -140,30 +140,6 @@ function handleApplyToWells() {
140
140
  }
141
141
  }
142
142
 
143
- // Volume unit change handler
144
- function handleVolumeChange(event: Event, target: 'final' | 'serial') {
145
- const input = event.target as HTMLInputElement
146
- const value = parseFloat(input.value)
147
- if (isNaN(value)) return
148
-
149
- if (target === 'final') {
150
- finalVolume.value = { ...finalVolume.value, value }
151
- } else {
152
- serialVolumePerWell.value = { ...serialVolumePerWell.value, value }
153
- }
154
- }
155
-
156
- function handleVolumeUnitChange(event: Event, target: 'final' | 'serial') {
157
- const select = event.target as HTMLSelectElement
158
- const unit = select.value as VolumeUnit
159
-
160
- if (target === 'final') {
161
- finalVolume.value = { ...finalVolume.value, unit }
162
- } else {
163
- serialVolumePerWell.value = { ...serialVolumePerWell.value, unit }
164
- }
165
- }
166
-
167
143
  // Watch for changes and recalculate
168
144
  watch(
169
145
  [stockConcentration, finalConcentration, finalVolume],
@@ -267,30 +243,12 @@ watch(activeMode, (mode) => {
267
243
  />
268
244
  </div>
269
245
 
270
- <div class="mint-dose-calculator__field">
271
- <label class="mint-dose-calculator__field-label">Final Volume</label>
272
- <div class="mint-dose-calculator__field-row">
273
- <input
274
- type="number"
275
- :value="finalVolume.value"
276
- :disabled="disabled"
277
- class="mint-dose-calculator__input"
278
- min="0"
279
- step="any"
280
- @input="handleVolumeChange($event, 'final')"
281
- />
282
- <select
283
- :value="finalVolume.unit"
284
- :disabled="disabled"
285
- class="mint-dose-calculator__select"
286
- @change="handleVolumeUnitChange($event, 'final')"
287
- >
288
- <option v-for="unit in volumeUnits" :key="unit" :value="unit">
289
- {{ unit }}
290
- </option>
291
- </select>
292
- </div>
293
- </div>
246
+ <DoseCalculatorVolumeField
247
+ v-model="finalVolume"
248
+ label="Final Volume"
249
+ :units="volumeUnits"
250
+ :disabled="disabled"
251
+ />
294
252
 
295
253
  <div class="mint-dose-calculator__divider" />
296
254
 
@@ -367,30 +325,12 @@ watch(activeMode, (mode) => {
367
325
  </div>
368
326
  </div>
369
327
 
370
- <div class="mint-dose-calculator__field">
371
- <label class="mint-dose-calculator__field-label">Volume per Well</label>
372
- <div class="mint-dose-calculator__field-row">
373
- <input
374
- type="number"
375
- :value="serialVolumePerWell.value"
376
- :disabled="disabled"
377
- class="mint-dose-calculator__input"
378
- min="0"
379
- step="any"
380
- @input="handleVolumeChange($event, 'serial')"
381
- />
382
- <select
383
- :value="serialVolumePerWell.unit"
384
- :disabled="disabled"
385
- class="mint-dose-calculator__select"
386
- @change="handleVolumeUnitChange($event, 'serial')"
387
- >
388
- <option v-for="unit in volumeUnits" :key="unit" :value="unit">
389
- {{ unit }}
390
- </option>
391
- </select>
392
- </div>
393
- </div>
328
+ <DoseCalculatorVolumeField
329
+ v-model="serialVolumePerWell"
330
+ label="Volume per Well"
331
+ :units="volumeUnits"
332
+ :disabled="disabled"
333
+ />
394
334
 
395
335
  <div class="mint-dose-calculator__divider" />
396
336
 
@@ -0,0 +1,61 @@
1
+ <script setup lang="ts">
2
+ /** Number + unit control used by DoseCalculator volume fields. */
3
+ import type { VolumeUnit, VolumeValue } from '../composables/useDoseCalculator'
4
+
5
+ interface Props {
6
+ label: string
7
+ modelValue: VolumeValue
8
+ units: VolumeUnit[]
9
+ disabled?: boolean
10
+ }
11
+
12
+ const props = withDefaults(defineProps<Props>(), {
13
+ disabled: false,
14
+ })
15
+
16
+ const emit = defineEmits<{
17
+ 'update:modelValue': [value: VolumeValue]
18
+ }>()
19
+
20
+ function handleValueInput(event: Event) {
21
+ const input = event.target as HTMLInputElement
22
+ const value = parseFloat(input.value)
23
+ if (Number.isNaN(value)) return
24
+ emit('update:modelValue', { ...props.modelValue, value })
25
+ }
26
+
27
+ function handleUnitChange(event: Event) {
28
+ const select = event.target as HTMLSelectElement
29
+ emit('update:modelValue', {
30
+ ...props.modelValue,
31
+ unit: select.value as VolumeUnit,
32
+ })
33
+ }
34
+ </script>
35
+
36
+ <template>
37
+ <div class="mint-dose-calculator__field">
38
+ <label class="mint-dose-calculator__field-label">{{ label }}</label>
39
+ <div class="mint-dose-calculator__field-row">
40
+ <input
41
+ type="number"
42
+ :value="modelValue.value"
43
+ :disabled="disabled"
44
+ class="mint-dose-calculator__input"
45
+ min="0"
46
+ step="any"
47
+ @input="handleValueInput"
48
+ />
49
+ <select
50
+ :value="modelValue.unit"
51
+ :disabled="disabled"
52
+ class="mint-dose-calculator__select"
53
+ @change="handleUnitChange"
54
+ >
55
+ <option v-for="unit in units" :key="unit" :value="unit">
56
+ {{ unit }}
57
+ </option>
58
+ </select>
59
+ </div>
60
+ </div>
61
+ </template>
@@ -1,7 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  /** Horizontal or vertical timeline of ordered protocol steps with status indicators, drag-to-reorder, and step-type iconography. */
3
3
  import { ref, computed } from 'vue'
4
- import type { ProtocolStep, ProtocolStepType, ProtocolStepStatus } from '../types'
4
+ import type { ProtocolStep, ProtocolStepStatus } from '../types'
5
+ import {
6
+ PROTOCOL_STEP_TYPE_COLORS as stepTypeColors,
7
+ PROTOCOL_STEP_TYPE_ICONS as stepTypeIcons,
8
+ formatProtocolDuration as formatDuration,
9
+ } from './ProtocolStep.presentation'
5
10
 
6
11
  interface Props {
7
12
  modelValue?: ProtocolStep[]
@@ -59,28 +64,6 @@ const sortedSteps = computed(() => {
59
64
  return [...props.modelValue].sort((a, b) => a.order - b.order)
60
65
  })
61
66
 
62
- const stepTypeIcons: Record<ProtocolStepType, string> = {
63
- 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',
64
- 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',
65
- addition: 'M12 9v3m0 0v3m0-3h3m-3 0H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z',
66
- 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',
67
- transfer: 'M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4',
68
- 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',
69
- 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',
70
- 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',
71
- }
72
-
73
- const stepTypeColors: Record<ProtocolStepType, string> = {
74
- incubation: '#F59E0B',
75
- wash: '#06B6D4',
76
- addition: '#10B981',
77
- measurement: '#8B5CF6',
78
- transfer: '#3B82F6',
79
- centrifuge: '#6B7280',
80
- mix: '#F97316',
81
- custom: '#EC4899',
82
- }
83
-
84
67
  const statusClasses: Record<ProtocolStepStatus, string> = {
85
68
  pending: 'mint-timeline__card--pending',
86
69
  in_progress: 'mint-timeline__card--in-progress',
@@ -97,14 +80,6 @@ const iconStatusClasses: Record<ProtocolStepStatus, string> = {
97
80
  skipped: 'mint-timeline__icon--skipped',
98
81
  }
99
82
 
100
- function formatDuration(minutes: number | undefined): string {
101
- if (minutes === undefined) return ''
102
- if (minutes < 60) return `${minutes}m`
103
- const hours = Math.floor(minutes / 60)
104
- const mins = minutes % 60
105
- return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`
106
- }
107
-
108
83
  function getStepColor(step: ProtocolStep): string {
109
84
  return props.colorByType && !props.colorByStatus ? stepTypeColors[step.type] : ''
110
85
  }
@@ -27,9 +27,9 @@ import type { FormSchema, FormEnhancements, UseFormBuilderReturn } from '../type
27
27
  import type { WizardStep } from '../types'
28
28
  import {
29
29
  controlsToFormSchema,
30
- defineControlModel,
31
30
  getControlDefaults,
32
31
  mergeControlWorkspaceOptions,
32
+ resolveControlModel,
33
33
  type ControlModel,
34
34
  type ControlModelBinding,
35
35
  type ControlSchema,
@@ -80,8 +80,7 @@ const emit = defineEmits<{
80
80
  }>()
81
81
 
82
82
  const resolvedModel = computed<ControlModelBinding | undefined>(() => {
83
- if (props.model === undefined) return undefined
84
- return isControlModelBinding(props.model) ? props.model : defineControlModel(props.model)
83
+ return resolveControlModel(props.model)
85
84
  })
86
85
 
87
86
  const resolvedControls = computed<ControlSchema | undefined>(() =>
@@ -197,10 +196,6 @@ function builderFieldNames(): string[] {
197
196
  return builder.fields.map(field => field.name)
198
197
  }
199
198
 
200
- function isControlModelBinding(model: ControlModel | ControlModelBinding): model is ControlModelBinding {
201
- return 'controls' in model && 'controlOptions' in model
202
- }
203
-
204
199
  defineExpose({
205
200
  form: builder.form,
206
201
  validate: builder.validate,
@@ -1,11 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  /** Full plate-map design environment for 96/384-well plates with sample assignment, slot-color coding, undo/redo, and CSV/JSON import-export. */
3
3
  import { ref, computed, watch } from 'vue'
4
- import type { PlateMapEditorState, WellPlateFormat, SampleType, Well } from '../types'
4
+ import type { PlateMapEditorState, WellPlateFormat, SampleType, Well, PlateMap } from '../types'
5
5
  import { useWellPlateEditor } from '../composables/useWellPlateEditor'
6
6
  import { useEventListener } from '../composables/useEventListener'
7
7
  import WellPlate from './WellPlate.vue'
8
8
  import SampleLegend from './SampleLegend.vue'
9
+ import PlateMapEditorToolbarInternal from './internal/PlateMapEditorToolbarInternal.vue'
9
10
 
10
11
  // Slot colors matching MSExpDesigner
11
12
  type SlotPosition = 'R' | 'G' | 'B' | 'Y'
@@ -73,6 +74,10 @@ function getPlateSlot(plateId: string, plateIndex: number): SlotPosition {
73
74
  return plateSlots.value.get(plateId)!
74
75
  }
75
76
 
77
+ function getPlateSlotColor(plateId: string, plateIndex: number): string {
78
+ return SLOT_COLORS[getPlateSlot(plateId, plateIndex)]
79
+ }
80
+
76
81
  const sampleColors = computed(() => {
77
82
  const colors: Record<string, string> = {}
78
83
  for (const sample of editor.samples.value) {
@@ -98,13 +103,18 @@ const wellsData = computed(() => {
98
103
  return wells
99
104
  })
100
105
 
101
- // Count samples in a plate
102
- function getPlateWellCount(plateId: string): number {
103
- const plate = editor.plates.value.find(p => p.id === plateId)
104
- if (!plate) return 0
106
+ function countPlateAssignedWells(plate: PlateMap): number {
105
107
  return Object.values(plate.wells).filter(w => w.sampleType).length
106
108
  }
107
109
 
110
+ const plateWellCounts = computed<Record<string, number>>(() => {
111
+ const counts: Record<string, number> = {}
112
+ for (const plate of editor.plates.value) {
113
+ counts[plate.id] = countPlateAssignedWells(plate)
114
+ }
115
+ return counts
116
+ })
117
+
108
118
  watch(
109
119
  () => editor.state.value,
110
120
  (newState) => emit('update:modelValue', { ...newState }),
@@ -230,107 +240,23 @@ useEventListener(() => document, 'keydown', handleKeyDown)
230
240
  <!-- Main plate area -->
231
241
  <div class="mint-plate-editor__main">
232
242
  <!-- Toolbar -->
233
- <div v-if="showToolbar" class="mint-plate-editor__toolbar">
234
- <!-- Plate tabs -->
235
- <div class="mint-plate-editor__tabs">
236
- <button
237
- v-for="(plate, index) in editor.plates.value"
238
- :key="plate.id"
239
- type="button"
240
- :class="['mint-plate-editor__tab', { 'mint-plate-editor__tab--active': plate.id === editor.activePlate.value?.id }]"
241
- @click="editor.setActivePlate(plate.id)"
242
- >
243
- <span
244
- class="mint-plate-editor__tab-slot"
245
- :style="{ backgroundColor: SLOT_COLORS[getPlateSlot(plate.id, index)] }"
246
- />
247
- <span class="mint-plate-editor__tab-name">{{ plate.name }}</span>
248
- <span
249
- v-if="getPlateWellCount(plate.id) > 0"
250
- class="mint-plate-editor__tab-count"
251
- >
252
- {{ getPlateWellCount(plate.id) }}
253
- </span>
254
- <button
255
- v-if="editor.plates.value.length > 1"
256
- type="button"
257
- class="mint-plate-editor__tab-remove"
258
- :aria-label="`Remove ${plate.name}`"
259
- @click.stop="handleRemovePlate(plate.id)"
260
- >
261
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
262
- <path d="M18 6 6 18" /><path d="m6 6 12 12" />
263
- </svg>
264
- </button>
265
- </button>
266
-
267
- <button
268
- v-if="allowAddPlates && editor.plates.value.length < maxPlates"
269
- type="button"
270
- class="mint-plate-editor__add-plate"
271
- aria-label="Add plate"
272
- @click="handleAddPlate"
273
- >
274
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
275
- <path d="M5 12h14" /><path d="M12 5v14" />
276
- </svg>
277
- <span>Add</span>
278
- </button>
279
- </div>
280
-
281
- <div class="mint-plate-editor__spacer" />
282
-
283
- <!-- Actions -->
284
- <div class="mint-plate-editor__actions">
285
- <button
286
- type="button"
287
- :disabled="!editor.canUndo.value"
288
- class="mint-plate-editor__action-btn"
289
- title="Undo (Ctrl+Z)"
290
- @click="handleUndo"
291
- >
292
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
293
- <path d="M9 14 4 9l5-5" /><path d="M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11" />
294
- </svg>
295
- </button>
296
-
297
- <button
298
- type="button"
299
- :disabled="!editor.canRedo.value"
300
- class="mint-plate-editor__action-btn"
301
- title="Redo (Ctrl+Shift+Z)"
302
- @click="handleRedo"
303
- >
304
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
305
- <path d="m15 14 5-5-5-5" /><path d="M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13" />
306
- </svg>
307
- </button>
308
-
309
- <div class="mint-plate-editor__divider" />
310
-
311
- <button
312
- type="button"
313
- class="mint-plate-editor__action-btn"
314
- title="Import"
315
- @click="showImportModal = true"
316
- >
317
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
318
- <path d="M12 3v12" /><path d="m17 8-5-5-5 5" /><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
319
- </svg>
320
- </button>
321
-
322
- <button
323
- type="button"
324
- class="mint-plate-editor__action-btn"
325
- title="Export JSON"
326
- @click="handleExport('json')"
327
- >
328
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
329
- <path d="M12 15V3" /><path d="m7 10 5 5 5-5" /><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
330
- </svg>
331
- </button>
332
- </div>
333
- </div>
243
+ <PlateMapEditorToolbarInternal
244
+ v-if="showToolbar"
245
+ :plates="editor.plates.value"
246
+ :active-plate-id="editor.activePlate.value?.id"
247
+ :plate-well-counts="plateWellCounts"
248
+ :can-add-plate="allowAddPlates && editor.plates.value.length < maxPlates"
249
+ :can-undo="editor.canUndo.value"
250
+ :can-redo="editor.canRedo.value"
251
+ :slot-color-for-plate="getPlateSlotColor"
252
+ @select-plate="editor.setActivePlate"
253
+ @remove-plate="handleRemovePlate"
254
+ @add-plate="handleAddPlate"
255
+ @undo="handleUndo"
256
+ @redo="handleRedo"
257
+ @import="showImportModal = true"
258
+ @export-json="handleExport('json')"
259
+ />
334
260
 
335
261
  <!-- Well plate -->
336
262
  <WellPlate
@@ -0,0 +1,182 @@
1
+ import { computed, reactive, watch } from 'vue'
2
+ import type { ComputedRef } from 'vue'
3
+ import type { PillNavItem } from '../types'
4
+ import type {
5
+ ControlComponentBinding,
6
+ ControlComponentBindingsById,
7
+ ControlComponentBindingsConfig,
8
+ ControlComponentPropsByIdMap,
9
+ ControlComponentPropsMap,
10
+ ControlModel,
11
+ ControlModelBinding,
12
+ ControlSchema,
13
+ ControlWorkspaceOptions,
14
+ } from '../composables/useControlSchema'
15
+ import {
16
+ controlValuesToComponentBindings,
17
+ controlValuesToComponentBindingsById,
18
+ controlValuesToComponentProps,
19
+ controlsToViewItems,
20
+ getControlDefaults,
21
+ getDefaultControlView,
22
+ mergeControlWorkspaceOptions,
23
+ resolveControlModel,
24
+ } from '../composables/useControlSchema'
25
+
26
+ export interface PluginWorkspaceControlsOptions {
27
+ model: () => ControlModel | ControlModelBinding | undefined
28
+ controls: () => ControlSchema | undefined
29
+ controlOptions: () => ControlWorkspaceOptions
30
+ modelValue: () => Record<string, unknown> | undefined
31
+ values: () => Record<string, unknown> | undefined
32
+ componentBindings: () => ControlComponentBindingsConfig | undefined
33
+ componentProps: () => ControlComponentPropsMap | undefined
34
+ componentPropsById: () => ControlComponentPropsByIdMap | undefined
35
+ emitValues: (values: Record<string, unknown>) => void
36
+ }
37
+
38
+ export interface PluginWorkspaceControls {
39
+ resolvedModel: ComputedRef<ControlModelBinding | undefined>
40
+ resolvedControls: ComputedRef<ControlSchema | undefined>
41
+ resolvedControlOptions: ComputedRef<ControlWorkspaceOptions>
42
+ generatedPillNav: ComputedRef<PillNavItem[]>
43
+ generatedDefaultView: ComputedRef<string>
44
+ internalControlValues: Record<string, unknown>
45
+ resolvedComponentBindings: ComputedRef<ControlComponentBinding[]>
46
+ resolvedComponentBindingsById: ComputedRef<ControlComponentBindingsById>
47
+ resolvedComponentProps: ComputedRef<Record<string, unknown>>
48
+ resolvedComponentPropsById: ComputedRef<Record<string, Record<string, unknown>>>
49
+ handleControlValuesUpdate: (values: Record<string, unknown>) => void
50
+ }
51
+
52
+ export function usePluginWorkspaceControls(
53
+ options: PluginWorkspaceControlsOptions,
54
+ ): PluginWorkspaceControls {
55
+ const resolvedModel = computed<ControlModelBinding | undefined>(() =>
56
+ resolveControlModel(options.model()),
57
+ )
58
+
59
+ const resolvedControls = computed<ControlSchema | undefined>(() =>
60
+ options.controls() ?? resolvedModel.value?.controls,
61
+ )
62
+
63
+ const resolvedControlOptions = computed<ControlWorkspaceOptions>(() =>
64
+ mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, options.controlOptions()),
65
+ )
66
+
67
+ const externalControlValues = computed(() => options.modelValue() ?? options.values())
68
+ const internalControlValues = reactive<Record<string, unknown>>({})
69
+ let syncingControlValues = false
70
+
71
+ const generatedControlDefaults = computed<Record<string, unknown>>(() => {
72
+ if (!resolvedControls.value) return {}
73
+ return {
74
+ ...getControlDefaults(resolvedControls.value),
75
+ ...(resolvedControlOptions.value.initialValues ?? {}),
76
+ }
77
+ })
78
+
79
+ function replaceControlValues(values: Record<string, unknown>) {
80
+ for (const key of Object.keys(internalControlValues)) {
81
+ if (!(key in values)) {
82
+ delete internalControlValues[key]
83
+ }
84
+ }
85
+ Object.assign(internalControlValues, values)
86
+ }
87
+
88
+ function emitControlValues() {
89
+ options.emitValues({ ...internalControlValues })
90
+ }
91
+
92
+ function syncResolvedControlValues() {
93
+ syncingControlValues = true
94
+ replaceControlValues({
95
+ ...generatedControlDefaults.value,
96
+ ...(externalControlValues.value === undefined ? internalControlValues : externalControlValues.value),
97
+ })
98
+ syncingControlValues = false
99
+ }
100
+
101
+ function handleControlValuesUpdate(values: Record<string, unknown>) {
102
+ syncingControlValues = true
103
+ replaceControlValues({
104
+ ...generatedControlDefaults.value,
105
+ ...values,
106
+ })
107
+ syncingControlValues = false
108
+ emitControlValues()
109
+ }
110
+
111
+ const resolvedComponentBindings = computed(() =>
112
+ controlValuesToComponentBindings(
113
+ internalControlValues,
114
+ options.componentBindings() ?? resolvedModel.value?.componentBindings,
115
+ ),
116
+ )
117
+
118
+ const resolvedComponentBindingsById = computed(() =>
119
+ controlValuesToComponentBindingsById(
120
+ internalControlValues,
121
+ options.componentBindings() ?? resolvedModel.value?.componentBindings,
122
+ ),
123
+ )
124
+
125
+ const resolvedComponentProps = computed(() => {
126
+ const mapping = options.componentProps() ?? resolvedModel.value?.componentProps
127
+ return mapping === undefined ? {} : controlValuesToComponentProps(internalControlValues, mapping)
128
+ })
129
+
130
+ const resolvedComponentPropsById = computed(() => {
131
+ const mappings = options.componentPropsById() ?? resolvedModel.value?.componentPropsById
132
+ if (mappings === undefined) return {}
133
+
134
+ return Object.fromEntries(
135
+ Object.entries(mappings).map(([id, mapping]) => [
136
+ id,
137
+ controlValuesToComponentProps(internalControlValues, mapping),
138
+ ]),
139
+ )
140
+ })
141
+
142
+ const generatedPillNav = computed<PillNavItem[]>(() => {
143
+ if (!resolvedControls.value) return []
144
+ return controlsToViewItems(resolvedControls.value, resolvedControlOptions.value)
145
+ })
146
+
147
+ const generatedDefaultView = computed(() => {
148
+ if (!resolvedControls.value) return ''
149
+ return getDefaultControlView(resolvedControls.value, resolvedControlOptions.value)
150
+ })
151
+
152
+ syncResolvedControlValues()
153
+
154
+ watch(
155
+ [generatedControlDefaults, externalControlValues],
156
+ syncResolvedControlValues,
157
+ { deep: true },
158
+ )
159
+
160
+ watch(
161
+ internalControlValues,
162
+ () => {
163
+ if (syncingControlValues) return
164
+ emitControlValues()
165
+ },
166
+ { deep: true, flush: 'sync' },
167
+ )
168
+
169
+ return {
170
+ resolvedModel,
171
+ resolvedControls,
172
+ resolvedControlOptions,
173
+ generatedPillNav,
174
+ generatedDefaultView,
175
+ internalControlValues,
176
+ resolvedComponentBindings,
177
+ resolvedComponentBindingsById,
178
+ resolvedComponentProps,
179
+ resolvedComponentPropsById,
180
+ handleControlValuesUpdate,
181
+ }
182
+ }