@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
@@ -0,0 +1,68 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import type { ColumnCondition, RowCondition } from '../../types'
3
+ import {
4
+ createColumnConditionMap,
5
+ createColumnConditionSpans,
6
+ createRowConditionMap,
7
+ createRowConditionSpanByRow,
8
+ createRowConditionSpans,
9
+ } from '../../components/WellPlate.conditions'
10
+
11
+ const columnCondition: ColumnCondition = {
12
+ label: 'Drug A',
13
+ color: '#10b981',
14
+ concentrations: [1, 10],
15
+ cols: [2, 3],
16
+ unit: 'uM',
17
+ }
18
+
19
+ const rowCondition: RowCondition = {
20
+ label: 'Drug B',
21
+ color: '#6366f1',
22
+ concentrations: [0.1, 1],
23
+ rows: ['B', 'C'],
24
+ }
25
+
26
+ describe('WellPlate condition helpers', () => {
27
+ it('maps column and row labels to their condition index', () => {
28
+ expect(createColumnConditionMap([columnCondition]).get(3)).toEqual({
29
+ condition: columnCondition,
30
+ indexInGroup: 1,
31
+ })
32
+ expect(createRowConditionMap([rowCondition]).get('C')).toEqual({
33
+ condition: rowCondition,
34
+ indexInGroup: 1,
35
+ })
36
+ })
37
+
38
+ it('creates column spans with gaps around condition groups', () => {
39
+ const spans = createColumnConditionSpans(
40
+ [1, 2, 3, 4],
41
+ createColumnConditionMap([columnCondition]),
42
+ )
43
+
44
+ expect(spans).toEqual([
45
+ { gap: true, colspan: 1 },
46
+ { condition: columnCondition, colspan: 2 },
47
+ { gap: true, colspan: 1 },
48
+ ])
49
+ })
50
+
51
+ it('creates row spans and indexes them by starting row', () => {
52
+ const spans = createRowConditionSpans(
53
+ ['A', 'B', 'C', 'D'],
54
+ createRowConditionMap([rowCondition]),
55
+ )
56
+
57
+ expect(spans).toEqual([
58
+ { gap: true, rowspan: 1, startRow: 0 },
59
+ { condition: rowCondition, rowspan: 2, startRow: 1 },
60
+ { gap: true, rowspan: 1, startRow: 3 },
61
+ ])
62
+ expect(createRowConditionSpanByRow(spans).get(1)).toEqual({
63
+ condition: rowCondition,
64
+ rowspan: 2,
65
+ startRow: 1,
66
+ })
67
+ })
68
+ })
@@ -0,0 +1,54 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import {
3
+ createPlateColumnLabels,
4
+ createPlateRowLabels,
5
+ createWellGrid,
6
+ getRectangleWellIds,
7
+ PLATE_CONFIGS,
8
+ WELL_PLATE_SIZE_CONFIGS,
9
+ } from '../../components/WellPlate.geometry'
10
+
11
+ describe('WellPlate geometry helpers', () => {
12
+ it('exposes supported plate dimensions and size presets', () => {
13
+ expect(PLATE_CONFIGS[96]).toEqual({ rows: 8, cols: 12 })
14
+ expect(PLATE_CONFIGS[384]).toEqual({ rows: 16, cols: 24 })
15
+ expect(WELL_PLATE_SIZE_CONFIGS.fill.cellWidth).toBe('100%')
16
+ })
17
+
18
+ it('creates row and column labels from a plate config', () => {
19
+ const config = PLATE_CONFIGS[24]
20
+
21
+ expect(createPlateRowLabels(config)).toEqual(['A', 'B', 'C', 'D'])
22
+ expect(createPlateColumnLabels(config)).toEqual([1, 2, 3, 4, 5, 6])
23
+ })
24
+
25
+ it('creates a well grid with partial well data merged into defaults', () => {
26
+ const config = PLATE_CONFIGS[6]
27
+ const rows = createPlateRowLabels(config)
28
+ const grid = createWellGrid(config, rows, {
29
+ A1: { state: 'filled', sampleType: 'qc', value: 42, metadata: { label: 'QC 1' } },
30
+ })
31
+
32
+ expect(grid[0][0]).toEqual({
33
+ id: 'A1',
34
+ row: 0,
35
+ col: 0,
36
+ state: 'filled',
37
+ sampleType: 'qc',
38
+ value: 42,
39
+ metadata: { label: 'QC 1' },
40
+ })
41
+ expect(grid[1][2]).toMatchObject({ id: 'B3', row: 1, col: 2, state: 'empty' })
42
+ })
43
+
44
+ it('creates rectangle well ids independent of drag direction', () => {
45
+ expect(Array.from(getRectangleWellIds({ row: 1, col: 2 }, { row: 0, col: 0 }, ['A', 'B']))).toEqual([
46
+ 'A1',
47
+ 'A2',
48
+ 'A3',
49
+ 'B1',
50
+ 'B2',
51
+ 'B3',
52
+ ])
53
+ })
54
+ })
@@ -0,0 +1,171 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+ import {
3
+ nextClickedWellSelection,
4
+ useWellPlateInteraction,
5
+ } from '../../components/WellPlate.interaction'
6
+ import type { Well, WellPlateSelectionMode } from '../../types'
7
+
8
+ function well(overrides: Partial<Well> = {}): Well {
9
+ return {
10
+ id: 'A1',
11
+ row: 0,
12
+ col: 0,
13
+ state: 'empty',
14
+ ...overrides,
15
+ }
16
+ }
17
+
18
+ function mouseEvent(overrides: Partial<MouseEvent> = {}): MouseEvent {
19
+ return {
20
+ preventDefault: vi.fn(),
21
+ button: 0,
22
+ shiftKey: false,
23
+ metaKey: false,
24
+ ctrlKey: false,
25
+ currentTarget: {
26
+ getBoundingClientRect: () => ({ right: 10, top: 20 }),
27
+ },
28
+ ...overrides,
29
+ } as unknown as MouseEvent
30
+ }
31
+
32
+ function dragEvent(data: Record<string, string> = {}): DragEvent {
33
+ return {
34
+ preventDefault: vi.fn(),
35
+ dataTransfer: {
36
+ effectAllowed: '',
37
+ dropEffect: '',
38
+ getData: (format: string) => data[format] ?? '',
39
+ setData: vi.fn(),
40
+ },
41
+ } as unknown as DragEvent
42
+ }
43
+
44
+ function createInteraction(overrides: Partial<Parameters<typeof useWellPlateInteraction>[0]> = {}) {
45
+ const emitted: Record<string, unknown[]> = {}
46
+ const selected = { value: [] as string[] }
47
+ const selectionMode = { value: 'multiple' as WellPlateSelectionMode }
48
+ const rows = ['A', 'B']
49
+ const grid = [
50
+ [well({ id: 'A1', row: 0, col: 0 }), well({ id: 'A2', row: 0, col: 1 })],
51
+ [well({ id: 'B1', row: 1, col: 0 }), well({ id: 'B2', row: 1, col: 1 })],
52
+ ]
53
+
54
+ const interaction = useWellPlateInteraction({
55
+ modelValue: () => selected.value,
56
+ selectionMode: () => selectionMode.value,
57
+ disabled: () => false,
58
+ readonly: () => false,
59
+ editable: () => false,
60
+ allowSampleDrop: () => false,
61
+ sampleDropParser: () => undefined,
62
+ rowLabels: () => rows,
63
+ wellGrid: () => grid,
64
+ emitSelected: (wellIds) => {
65
+ emitted.selected = [...(emitted.selected ?? []), wellIds]
66
+ selected.value = wellIds
67
+ },
68
+ emitWellClick: (wellId, event) => {
69
+ emitted.click = [...(emitted.click ?? []), [wellId, event]]
70
+ },
71
+ emitWellHover: (wellId, event) => {
72
+ emitted.hover = [...(emitted.hover ?? []), [wellId, event]]
73
+ },
74
+ emitContextMenu: (wellId, event) => {
75
+ emitted.context = [...(emitted.context ?? []), [wellId, event]]
76
+ },
77
+ emitWellMove: (sourceWellId, targetWellId) => {
78
+ emitted.move = [...(emitted.move ?? []), [sourceWellId, targetWellId]]
79
+ },
80
+ emitWellEdit: (wellId, data) => {
81
+ emitted.edit = [...(emitted.edit ?? []), [wellId, data]]
82
+ },
83
+ emitWellClear: (wellId) => {
84
+ emitted.clear = [...(emitted.clear ?? []), wellId]
85
+ },
86
+ emitSampleDrop: (wellId, data, event) => {
87
+ emitted.drop = [...(emitted.drop ?? []), [wellId, data, event]]
88
+ },
89
+ ...overrides,
90
+ })
91
+
92
+ return { emitted, grid, interaction, selected, selectionMode }
93
+ }
94
+
95
+ describe('WellPlate interaction helpers', () => {
96
+ it('calculates clicked well selection for single and multi-select modes', () => {
97
+ expect(nextClickedWellSelection([], 'A1', 'single', mouseEvent())).toEqual(['A1'])
98
+ expect(nextClickedWellSelection(['A1'], 'A1', 'single', mouseEvent())).toEqual([])
99
+ expect(nextClickedWellSelection(['A1'], 'A2', 'multiple', mouseEvent({ shiftKey: true }))).toEqual(['A1', 'A2'])
100
+ expect(nextClickedWellSelection(['A1', 'A2'], 'A1', 'multiple', mouseEvent({ ctrlKey: true }))).toEqual(['A2'])
101
+ expect(nextClickedWellSelection(['A1'], 'A1', 'multiple', mouseEvent())).toEqual([])
102
+ })
103
+
104
+ it('emits click selection changes and opens editor instead when editable', () => {
105
+ const { emitted, grid, interaction } = createInteraction()
106
+
107
+ interaction.handleWellClick(grid[0][0], mouseEvent())
108
+
109
+ expect(emitted.click?.[0]).toEqual(['A1', expect.anything()])
110
+ expect(emitted.selected?.[0]).toEqual(['A1'])
111
+
112
+ const editable = createInteraction({ editable: () => true })
113
+ editable.interaction.handleWellClick(grid[0][1], mouseEvent())
114
+
115
+ expect(editable.interaction.editingWellId.value).toBe('A2')
116
+ expect(editable.interaction.editPopupPosition.value).toEqual({ x: 18, y: 20 })
117
+ expect(editable.emitted.selected).toBeUndefined()
118
+ })
119
+
120
+ it('tracks rectangle drag selection and emits on mouseup', () => {
121
+ const { emitted, grid, interaction, selectionMode } = createInteraction()
122
+ selectionMode.value = 'rectangle'
123
+
124
+ interaction.handleWellMouseDown(grid[0][0], mouseEvent())
125
+ interaction.handleWellMouseEnter(grid[1][1], mouseEvent())
126
+
127
+ expect(Array.from(interaction.dragSelectedWells.value)).toEqual(['A1', 'A2', 'B1', 'B2'])
128
+
129
+ interaction.handleMouseUp()
130
+
131
+ expect(emitted.selected?.[0]).toEqual(['A1', 'A2', 'B1', 'B2'])
132
+ expect(interaction.isDragging.value).toBe(false)
133
+ })
134
+
135
+ it('moves wells in drag mode and resets drag state', () => {
136
+ const { emitted, grid, interaction, selectionMode } = createInteraction()
137
+ selectionMode.value = 'drag'
138
+
139
+ interaction.handleDragStart({ ...grid[0][0], sampleType: 'sample' }, dragEvent())
140
+ interaction.handleDrop(grid[1][1], dragEvent())
141
+
142
+ expect(emitted.move?.[0]).toEqual(['A1', 'B2'])
143
+ expect(interaction.dragSourceWell.value).toBeNull()
144
+ expect(interaction.dragTargetWell.value).toBeNull()
145
+ })
146
+
147
+ it('parses dropped samples when sample drop is enabled', () => {
148
+ const { emitted, grid, interaction } = createInteraction({ allowSampleDrop: () => true })
149
+
150
+ interaction.handleDrop(grid[0][0], dragEvent({ 'text/plain': 'Sample A' }))
151
+
152
+ expect(emitted.drop?.[0]).toEqual([
153
+ 'A1',
154
+ { sampleName: 'Sample A', label: 'Sample A', raw: 'Sample A' },
155
+ expect.anything(),
156
+ ])
157
+ })
158
+
159
+ it('handles keyboard clear and select all shortcuts', () => {
160
+ const { emitted, interaction, selected } = createInteraction()
161
+ selected.value = ['A1']
162
+
163
+ interaction.handleKeyDown(new KeyboardEvent('keydown', { key: 'Escape' }))
164
+ interaction.handleKeyDown(new KeyboardEvent('keydown', { key: 'a', metaKey: true }))
165
+
166
+ expect(emitted.selected).toEqual([
167
+ [],
168
+ ['A1', 'A2', 'B1', 'B2'],
169
+ ])
170
+ })
171
+ })
@@ -0,0 +1,13 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { DEFAULT_WELL_LEGEND_ITEMS } from '../../components/WellPlate.legend'
3
+
4
+ describe('WellPlate legend helpers', () => {
5
+ it('keeps default sample legend item order stable', () => {
6
+ expect(DEFAULT_WELL_LEGEND_ITEMS.map(item => item.type)).toEqual([
7
+ 'sample',
8
+ 'blank',
9
+ 'qc',
10
+ 'iqc',
11
+ ])
12
+ })
13
+ })
@@ -0,0 +1,122 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import {
3
+ sampleTypeIndicator,
4
+ wellBadge,
5
+ wellClasses,
6
+ wellLabel,
7
+ wellStyle,
8
+ } from '../../components/WellPlate.rendering'
9
+ import type { Well } from '../../types'
10
+
11
+ function well(overrides: Partial<Well> = {}): Well {
12
+ return {
13
+ id: 'A1',
14
+ row: 0,
15
+ col: 0,
16
+ state: 'empty',
17
+ ...overrides,
18
+ }
19
+ }
20
+
21
+ describe('WellPlate rendering helpers', () => {
22
+ it('derives well classes from selection and drag priority', () => {
23
+ expect(wellClasses(well({ sampleType: 'sample' }), {
24
+ wellShape: 'circle',
25
+ selectionMode: 'drag',
26
+ selected: true,
27
+ dragOver: false,
28
+ hovered: false,
29
+ disabled: false,
30
+ readonly: false,
31
+ dragSource: false,
32
+ dragTarget: true,
33
+ })).toEqual([
34
+ 'mint-well-plate__well',
35
+ 'mint-well-plate__well--circle',
36
+ 'mint-well-plate__well--draggable',
37
+ 'mint-well-plate__well--drag-target',
38
+ ])
39
+ })
40
+
41
+ it('suppresses hover styling when readonly and includes disabled/filled states', () => {
42
+ expect(wellClasses(well({ state: 'filled' }), {
43
+ wellShape: 'rounded',
44
+ selectionMode: 'multiple',
45
+ selected: false,
46
+ dragOver: false,
47
+ hovered: true,
48
+ disabled: true,
49
+ readonly: true,
50
+ dragSource: false,
51
+ dragTarget: false,
52
+ })).toEqual([
53
+ 'mint-well-plate__well',
54
+ 'mint-well-plate__well--rounded',
55
+ 'mint-well-plate__well--disabled',
56
+ 'mint-well-plate__well--filled',
57
+ ])
58
+ })
59
+
60
+ it('prefers heatmap and custom sample colors before defaults', () => {
61
+ expect(wellStyle(well({ value: 0.5 }), {
62
+ heatmap: { enabled: true, colorScale: 'viridis', min: 0, max: 1 },
63
+ sampleColors: {},
64
+ })).toEqual({
65
+ backgroundColor: expect.any(String),
66
+ border: '1px solid transparent',
67
+ })
68
+
69
+ expect(wellStyle(well({ sampleType: 'treated' }), {
70
+ heatmap: { enabled: false },
71
+ sampleColors: { treated: '#123456' },
72
+ })).toEqual({
73
+ backgroundColor: '#12345626',
74
+ border: '1px solid #12345666',
75
+ })
76
+
77
+ expect(wellStyle(well({ sampleType: 'qc' }), {
78
+ heatmap: { enabled: false },
79
+ sampleColors: {},
80
+ })).toEqual({
81
+ backgroundColor: 'rgba(139, 92, 246, 0.15)',
82
+ border: '1px solid rgba(139, 92, 246, 0.4)',
83
+ })
84
+ })
85
+
86
+ it('falls back to empty or filled well styles', () => {
87
+ expect(wellStyle(well(), {
88
+ heatmap: { enabled: false },
89
+ sampleColors: {},
90
+ })).toEqual({
91
+ backgroundColor: 'var(--bg-tertiary)',
92
+ border: '1px dashed var(--border-color)',
93
+ })
94
+
95
+ expect(wellStyle(well({ state: 'filled' }), {
96
+ heatmap: { enabled: false },
97
+ sampleColors: {},
98
+ })).toEqual({
99
+ backgroundColor: 'var(--bg-tertiary)',
100
+ border: '1px solid var(--border-color)',
101
+ })
102
+ })
103
+
104
+ it('formats indicators, labels, and badges for optional overlays', () => {
105
+ expect(sampleTypeIndicator(well({ sampleType: 'qc' }), true)).toBe('Q')
106
+ expect(sampleTypeIndicator(well({ sampleType: 'treated' }), true)).toBe('T')
107
+ expect(sampleTypeIndicator(well({ sampleType: 'treated' }), false)).toBeNull()
108
+
109
+ expect(wellLabel(well({ metadata: { label: 'Dose A' } }), true)).toBe('Dose A')
110
+ expect(wellLabel(well({ metadata: { label: 'Dose A' } }), false)).toBeUndefined()
111
+
112
+ expect(wellBadge(well({ metadata: { injectionCount: 3 } }), true)).toEqual({
113
+ text: '3',
114
+ color: '#6366f1',
115
+ })
116
+ expect(wellBadge(well({ metadata: { customMethod: 'LCMS-2' } }), true)).toEqual({
117
+ text: '+',
118
+ color: '#ec4899',
119
+ })
120
+ expect(wellBadge(well({ metadata: { injectionCount: 1 } }), true)).toBeNull()
121
+ })
122
+ })
@@ -0,0 +1,70 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import {
3
+ createTextDroppedSample,
4
+ normalizeDroppedSample,
5
+ parseDroppedSampleTransfer,
6
+ } from '../../components/WellPlate.sampleDrop'
7
+
8
+ function createTransfer(data: Record<string, string>) {
9
+ return {
10
+ getData(format: string) {
11
+ return data[format] ?? ''
12
+ },
13
+ }
14
+ }
15
+
16
+ describe('WellPlate sample drop helpers', () => {
17
+ it('normalizes JSON sample payloads', () => {
18
+ const raw = {
19
+ id: 'sample-1',
20
+ sample_name: 'Sample 1',
21
+ sample_type: 'qc',
22
+ injection_volume: 5,
23
+ injection_count: 2,
24
+ custom_method: 'fast',
25
+ metadata: { batch: 'A' },
26
+ }
27
+
28
+ expect(normalizeDroppedSample(raw)).toEqual({
29
+ id: 'sample-1',
30
+ sampleName: 'Sample 1',
31
+ label: 'Sample 1',
32
+ sampleType: 'qc',
33
+ injectionVolume: 5,
34
+ injectionCount: 2,
35
+ customMethod: 'fast',
36
+ metadata: { batch: 'A' },
37
+ raw,
38
+ })
39
+ })
40
+
41
+ it('parses JSON payloads before text fallback', () => {
42
+ const transfer = createTransfer({
43
+ 'application/json': JSON.stringify({ name: 'From JSON' }),
44
+ 'text/plain': 'From Text',
45
+ })
46
+
47
+ expect(parseDroppedSampleTransfer(transfer)).toMatchObject({
48
+ sampleName: 'From JSON',
49
+ label: 'From JSON',
50
+ })
51
+ })
52
+
53
+ it('creates a text sample when no JSON payload exists', () => {
54
+ expect(createTextDroppedSample(' Sample A ')).toEqual({
55
+ sampleName: 'Sample A',
56
+ label: 'Sample A',
57
+ raw: 'Sample A',
58
+ })
59
+ expect(parseDroppedSampleTransfer(createTransfer({ 'text/plain': 'Sample B' }))).toMatchObject({
60
+ sampleName: 'Sample B',
61
+ label: 'Sample B',
62
+ })
63
+ })
64
+
65
+ it('rejects invalid or empty payloads', () => {
66
+ expect(normalizeDroppedSample({ metadata: { batch: 'A' } })).toBeNull()
67
+ expect(createTextDroppedSample(' ')).toBeNull()
68
+ expect(parseDroppedSampleTransfer(createTransfer({ 'application/json': '{' }))).toBeNull()
69
+ })
70
+ })
@@ -0,0 +1,107 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { detectClass } from '../../../composables/autoGroup/classify'
3
+
4
+ describe('detectClass', () => {
5
+ it('detects IQC and EQC by exact vocab match', () => {
6
+ const result = detectClass(
7
+ [
8
+ ['exp281', 'SAM_SAH', 'Tissues', 'IQC', '003'],
9
+ ['exp281', 'SAM_SAH', 'Tissues', 'IQC', '056'],
10
+ ['exp280', 'Experiment', 'EQC', '002'],
11
+ ],
12
+ {},
13
+ )
14
+ const iqc = result.find(c => c.kind === 'iqc')
15
+ const eqc = result.find(c => c.kind === 'eqc')
16
+ expect(iqc?.members).toEqual([0, 1])
17
+ expect(eqc?.members).toEqual([2])
18
+ })
19
+
20
+ it('detects Biological with subKind from matrix vocab', () => {
21
+ const result = detectClass(
22
+ [
23
+ ['exp281', 'SAM_SAH', 'Tissues', 'Kidney', 'M10', '085'],
24
+ ['exp281', 'SAM_SAH', 'Tissues', 'Liver', 'M10', '047'],
25
+ ['exp280', 'Experiment', 'Plasma', 'M10', '031'],
26
+ ],
27
+ {},
28
+ )
29
+ const tissues = result.find(c => c.kind === 'biological' && c.subKind === 'Tissues')
30
+ const plasma = result.find(c => c.kind === 'biological' && c.subKind === 'Plasma')
31
+ expect(tissues?.members).toEqual([0, 1])
32
+ expect(plasma?.members).toEqual([2])
33
+ })
34
+
35
+ it('classifies SAHStandard, SAMstandard, ExtractionS, STD1 as Standard (not Biological)', () => {
36
+ const result = detectClass(
37
+ [
38
+ ['exp281', 'SAM_SAH', 'SAHStandard', '5nM', '002'],
39
+ ['exp281', 'SAM_SAH', 'SAMstandard', '5nM', '001'],
40
+ ['exp281', 'SAM_SAH', 'Tissues', 'ExtractionS', '00B'],
41
+ ['exp', 'STD1', 'inject'],
42
+ ],
43
+ {},
44
+ )
45
+ const std = result.find(c => c.kind === 'standard')
46
+ expect(std?.members.sort()).toEqual([0, 1, 2, 3])
47
+ })
48
+
49
+ it('classifies SpikeIn and Stock', () => {
50
+ const result = detectClass(
51
+ [
52
+ ['exp280', 'SK', 'ESwithSpikeIn', '02'],
53
+ ['exp280', 'SK', 'ESwithSpikeIn', '1to100', 'Stock', '05'],
54
+ ],
55
+ {},
56
+ )
57
+ // SpikeIn matches first, so both go to spike-in (first match wins).
58
+ const spike = result.find(c => c.kind === 'spike-in')
59
+ expect(spike?.members.sort()).toEqual([0, 1])
60
+ })
61
+
62
+ it('classifies samples with no recognized vocab as Unknown', () => {
63
+ const result = detectClass([['foo', 'bar', 'baz']], {})
64
+ expect(result[0].kind).toBe('unknown')
65
+ expect(result[0].members).toEqual([0])
66
+ })
67
+
68
+ it('records classTagPositions for the position(s) that matched vocab', () => {
69
+ const result = detectClass(
70
+ [['exp281', 'SAM_SAH', 'Tissues', 'Kidney', 'M10', '085']],
71
+ {},
72
+ )
73
+ const tissues = result.find(c => c.kind === 'biological')
74
+ // Tissues at position 2 (class tag) and Kidney at position 3 (matrix tag).
75
+ expect(tissues?.classTagPositions).toContain(2)
76
+ expect(tissues?.classTagPositions).toContain(3)
77
+ })
78
+
79
+ it('honors sample_type hint short-circuit', () => {
80
+ const result = detectClass(
81
+ [['weird', 'name', 'with', 'no', 'vocab']],
82
+ { sampleTypeHints: ['qc'] },
83
+ )
84
+ expect(result[0].kind).toBe('iqc')
85
+ })
86
+
87
+ it('does not classify bare A1/M10/QC1/STD1 as Biological', () => {
88
+ // Names that only contain a `[A-Z]+\d+` token without matrix vocab must fall to Unknown,
89
+ // not Biological — prevents misclassifying calibration/QC labels.
90
+ const result = detectClass([['exp', 'foo', 'A1']], {})
91
+ expect(result[0].kind).toBe('unknown')
92
+ })
93
+
94
+ it('Biological requires an accompanying matrix vocab token', () => {
95
+ const result = detectClass([['exp', 'Plasma', 'M10']], {})
96
+ expect(result[0].kind).toBe('biological')
97
+ expect(result[0].subKind).toBe('Plasma')
98
+ })
99
+
100
+ it('first-match-wins between SpikeIn and Stock when both tokens appear', () => {
101
+ const result = detectClass(
102
+ [['exp', 'SK', 'ESwithSpikeIn', '1to100', 'Stock', '05']],
103
+ {},
104
+ )
105
+ expect(result[0].kind).toBe('spike-in')
106
+ })
107
+ })