@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
@@ -5,10 +5,13 @@ import type {
5
5
  ScheduleView,
6
6
  ScheduleEvent,
7
7
  ScheduleBlockedSlot,
8
- ScheduleEventStatus,
9
8
  } from '../types/components'
10
- import { formatTime } from '../composables/useTimeUtils'
11
9
  import { useScheduleDrag } from '../composables/useScheduleDrag'
10
+ import {
11
+ SCHEDULE_SLOT_HEIGHT,
12
+ parseScheduleModelDate,
13
+ useScheduleCalendarLayout,
14
+ } from '../composables/useScheduleCalendarLayout'
12
15
 
13
16
  interface Props {
14
17
  modelValue?: Date | string
@@ -52,21 +55,26 @@ const emit = defineEmits<{
52
55
  'navigate': [context: { direction: string; date: Date }]
53
56
  }>()
54
57
 
55
- const SLOT_HEIGHT = 40
58
+ const SLOT_HEIGHT = SCHEDULE_SLOT_HEIGHT
56
59
  const currentView = ref<ScheduleView>(props.view)
57
- const currentDate = ref<Date>(parseModelDate(props.modelValue))
60
+ const currentDate = ref<Date>(parseScheduleModelDate(props.modelValue))
58
61
  const nowTimer = ref<ReturnType<typeof setInterval>>()
59
62
  const now = ref(new Date())
60
63
  const bodyRef = ref<HTMLDivElement>()
61
64
 
62
65
  watch(() => props.view, (v) => { currentView.value = v })
63
- watch(() => props.modelValue, (v) => { if (v) currentDate.value = parseModelDate(v) })
66
+ watch(() => props.modelValue, (v) => { if (v) currentDate.value = parseScheduleModelDate(v) })
64
67
 
65
68
  const slotHeightRef = computed(() => SLOT_HEIGHT)
66
69
  const slotDurationRef = computed(() => props.slotDuration)
67
70
  const dayStartRef = computed(() => props.dayStartHour)
68
71
  const dayEndRef = computed(() => props.dayEndHour)
69
72
  const readonlyRef = computed(() => props.readonly)
73
+ const eventsRef = computed(() => props.events)
74
+ const blockedSlotsRef = computed(() => props.blockedSlots)
75
+ const weekStartsOnRef = computed(() => props.weekStartsOn)
76
+ const localeRef = computed(() => props.locale)
77
+ const showNowIndicatorRef = computed(() => props.showNowIndicator)
70
78
 
71
79
  const { isDragging, ghost, startCreate, startMove, startResize } = useScheduleDrag({
72
80
  slotDuration: slotDurationRef,
@@ -85,124 +93,39 @@ const { isDragging, ghost, startCreate, startMove, startResize } = useScheduleDr
85
93
  },
86
94
  })
87
95
 
88
- const totalSlots = computed(() => {
89
- return ((props.dayEndHour - props.dayStartHour) * 60) / props.slotDuration
90
- })
91
-
92
- const timeLabels = computed(() => {
93
- const labels: string[] = []
94
- for (let i = 0; i <= totalSlots.value; i++) {
95
- const totalMinutes = props.dayStartHour * 60 + i * props.slotDuration
96
- const hour = Math.floor(totalMinutes / 60)
97
- const minute = totalMinutes % 60
98
- labels.push(formatTime(hour, minute, '24h'))
99
- }
100
- return labels
101
- })
102
-
103
- const weekDays = computed(() => {
104
- const days: Date[] = []
105
- const start = getWeekStart(currentDate.value)
106
- for (let i = 0; i < 7; i++) {
107
- const d = new Date(start)
108
- d.setDate(d.getDate() + i)
109
- days.push(d)
110
- }
111
- return days
112
- })
113
-
114
- const visibleDays = computed(() => {
115
- if (currentView.value === 'day') return [currentDate.value]
116
- if (currentView.value === 'week') return weekDays.value
117
- return []
118
- })
119
-
120
- const headerTitle = computed(() => {
121
- if (currentView.value === 'day') {
122
- return currentDate.value.toLocaleDateString(props.locale, {
123
- weekday: 'long',
124
- year: 'numeric',
125
- month: 'long',
126
- day: 'numeric',
127
- })
128
- }
129
- if (currentView.value === 'week') {
130
- const days = weekDays.value
131
- const first = days[0]
132
- const last = days[6]
133
- const sameMonth = first.getMonth() === last.getMonth()
134
- if (sameMonth) {
135
- return `${first.toLocaleDateString(props.locale, { month: 'short', day: 'numeric' })} - ${last.getDate()}, ${last.getFullYear()}`
136
- }
137
- return `${first.toLocaleDateString(props.locale, { month: 'short', day: 'numeric' })} - ${last.toLocaleDateString(props.locale, { month: 'short', day: 'numeric' })}, ${last.getFullYear()}`
138
- }
139
- return currentDate.value.toLocaleDateString(props.locale, { year: 'numeric', month: 'long' })
140
- })
141
-
142
- // Month view computations
143
- const monthDays = computed(() => {
144
- const year = currentDate.value.getFullYear()
145
- const month = currentDate.value.getMonth()
146
- const firstDay = new Date(year, month, 1)
147
- const lastDay = new Date(year, month + 1, 0)
148
-
149
- const days: { date: Date; isCurrentMonth: boolean }[] = []
150
-
151
- // Adjust for weekStartsOn
152
- let startPadding = firstDay.getDay() - props.weekStartsOn
153
- if (startPadding < 0) startPadding += 7
154
-
155
- for (let i = startPadding - 1; i >= 0; i--) {
156
- const date = new Date(year, month, -i)
157
- days.push({ date, isCurrentMonth: false })
158
- }
159
-
160
- for (let i = 1; i <= lastDay.getDate(); i++) {
161
- days.push({ date: new Date(year, month, i), isCurrentMonth: true })
162
- }
163
-
164
- const remaining = 42 - days.length
165
- for (let i = 1; i <= remaining; i++) {
166
- days.push({ date: new Date(year, month + 1, i), isCurrentMonth: false })
167
- }
168
-
169
- return days
170
- })
171
-
172
- const monthWeekdayLabels = computed(() => {
173
- const labels: string[] = []
174
- const base = new Date(2024, 0, props.weekStartsOn === 1 ? 1 : 7) // A known Monday or Sunday
175
- for (let i = 0; i < 7; i++) {
176
- const d = new Date(base)
177
- d.setDate(d.getDate() + i)
178
- labels.push(d.toLocaleDateString(props.locale, { weekday: 'short' }))
179
- }
180
- return labels
96
+ const {
97
+ totalSlots,
98
+ timeLabels,
99
+ visibleDays,
100
+ headerTitle,
101
+ monthDays,
102
+ monthWeekdayLabels,
103
+ isToday,
104
+ isSameDay,
105
+ getEventStyle,
106
+ getEventsForDay,
107
+ getEventsForDate,
108
+ getBlockedForDay,
109
+ getBlockedStyle,
110
+ getNowIndicatorStyle,
111
+ getStatusClass,
112
+ getMonthStatusClass,
113
+ formatEventTime,
114
+ } = useScheduleCalendarLayout({
115
+ currentView,
116
+ currentDate,
117
+ now,
118
+ events: eventsRef,
119
+ blockedSlots: blockedSlotsRef,
120
+ dayStartHour: dayStartRef,
121
+ dayEndHour: dayEndRef,
122
+ slotDuration: slotDurationRef,
123
+ weekStartsOn: weekStartsOnRef,
124
+ locale: localeRef,
125
+ showNowIndicator: showNowIndicatorRef,
126
+ slotHeight: slotHeightRef,
181
127
  })
182
128
 
183
- function parseModelDate(value?: Date | string): Date {
184
- if (!value) return new Date()
185
- if (value instanceof Date) return value
186
- const d = new Date(value)
187
- return isNaN(d.getTime()) ? new Date() : d
188
- }
189
-
190
- function getWeekStart(date: Date): Date {
191
- const d = new Date(date)
192
- const day = d.getDay()
193
- const diff = (day - props.weekStartsOn + 7) % 7
194
- d.setDate(d.getDate() - diff)
195
- return d
196
- }
197
-
198
- function isToday(date: Date): boolean {
199
- return date.toDateString() === now.value.toDateString()
200
- }
201
-
202
- function isSameDay(a: Date, b: Date): boolean {
203
- return a.toDateString() === b.toDateString()
204
- }
205
-
206
129
  function navigate(direction: 'prev' | 'next' | 'today') {
207
130
  const d = new Date(currentDate.value)
208
131
  if (direction === 'today') {
@@ -223,78 +146,6 @@ function setView(view: ScheduleView) {
223
146
  emit('update:view', view)
224
147
  }
225
148
 
226
- function getEventStyle(event: ScheduleEvent, dayDate: Date) {
227
- const eventStart = new Date(event.start)
228
- const eventEnd = new Date(event.end)
229
- if (!isSameDay(eventStart, dayDate) && !isSameDay(eventEnd, dayDate)) return null
230
-
231
- const dayStartMin = props.dayStartHour * 60
232
- const startMin = Math.max(eventStart.getHours() * 60 + eventStart.getMinutes(), dayStartMin) - dayStartMin
233
- const endMin = Math.min(eventEnd.getHours() * 60 + eventEnd.getMinutes(), props.dayEndHour * 60) - dayStartMin
234
-
235
- const pixelsPerMin = SLOT_HEIGHT / props.slotDuration
236
- return {
237
- top: `${startMin * pixelsPerMin}px`,
238
- height: `${Math.max((endMin - startMin) * pixelsPerMin, SLOT_HEIGHT / 2)}px`,
239
- }
240
- }
241
-
242
- function getEventsForDay(day: Date): ScheduleEvent[] {
243
- return props.events.filter((e) => {
244
- const start = new Date(e.start)
245
- return isSameDay(start, day)
246
- })
247
- }
248
-
249
- function getEventsForDate(date: Date): ScheduleEvent[] {
250
- return props.events.filter((e) => {
251
- const start = new Date(e.start)
252
- return isSameDay(start, date)
253
- })
254
- }
255
-
256
- function getBlockedForDay(day: Date): ScheduleBlockedSlot[] {
257
- return props.blockedSlots.filter((b) => {
258
- const start = new Date(b.start)
259
- return isSameDay(start, day)
260
- })
261
- }
262
-
263
- function getBlockedStyle(slot: ScheduleBlockedSlot) {
264
- const start = new Date(slot.start)
265
- const end = new Date(slot.end)
266
- const dayStartMin = props.dayStartHour * 60
267
- const startMin = Math.max(start.getHours() * 60 + start.getMinutes(), dayStartMin) - dayStartMin
268
- const endMin = Math.min(end.getHours() * 60 + end.getMinutes(), props.dayEndHour * 60) - dayStartMin
269
-
270
- const pixelsPerMin = SLOT_HEIGHT / props.slotDuration
271
- return {
272
- top: `${startMin * pixelsPerMin}px`,
273
- height: `${(endMin - startMin) * pixelsPerMin}px`,
274
- }
275
- }
276
-
277
- function getNowIndicatorStyle(): Record<string, string> | null {
278
- if (!props.showNowIndicator) return null
279
- const nowMin = now.value.getHours() * 60 + now.value.getMinutes()
280
- const dayStartMin = props.dayStartHour * 60
281
- const dayEndMin = props.dayEndHour * 60
282
- if (nowMin < dayStartMin || nowMin > dayEndMin) return null
283
-
284
- const pixelsPerMin = SLOT_HEIGHT / props.slotDuration
285
- return { top: `${(nowMin - dayStartMin) * pixelsPerMin}px` }
286
- }
287
-
288
- function getStatusClass(status?: ScheduleEventStatus): string {
289
- if (!status) return 'mint-schedule__event--confirmed'
290
- return `mint-schedule__event--${status}`
291
- }
292
-
293
- function getMonthStatusClass(status?: ScheduleEventStatus): string {
294
- if (!status) return 'mint-schedule__month-event--confirmed'
295
- return `mint-schedule__month-event--${status}`
296
- }
297
-
298
149
  function onEventClick(event: ScheduleEvent, e: MouseEvent) {
299
150
  e.stopPropagation()
300
151
  emit('event-click', event)
@@ -335,12 +186,6 @@ function onMonthDayClick(date: Date) {
335
186
  setView('day')
336
187
  }
337
188
 
338
- function formatEventTime(event: ScheduleEvent): string {
339
- const start = new Date(event.start)
340
- const end = new Date(event.end)
341
- return `${formatTime(start.getHours(), start.getMinutes())} - ${formatTime(end.getHours(), end.getMinutes())}`
342
- }
343
-
344
189
  onMounted(() => {
345
190
  nowTimer.value = setInterval(() => { now.value = new Date() }, 60000)
346
191
 
@@ -0,0 +1,71 @@
1
+ import type {
2
+ FormSchema,
3
+ FormSectionSchema,
4
+ SettingsGroup,
5
+ SettingsModalSchema,
6
+ SettingsTab,
7
+ SettingsTabInput,
8
+ } from '../types'
9
+ import type { AccessControlled } from '../permissions'
10
+ import { normalizeItemInput } from '../utils/items'
11
+
12
+ export const APPEARANCE_TAB_ID = 'appearance'
13
+
14
+ export const APPEARANCE_TAB: SettingsTab = {
15
+ id: APPEARANCE_TAB_ID,
16
+ label: 'Appearance',
17
+ description: 'Theme, color palette, and table density',
18
+ }
19
+
20
+ // Map settings groups onto the form-builder's flat-section shape.
21
+ // `title: ''` because the rail/pane header already shows the group name.
22
+ export function buildFlatSettingsSchema(schema: SettingsModalSchema): FormSchema {
23
+ return {
24
+ sections: schema.groups.map<FormSectionSchema>((group) => ({
25
+ id: group.id,
26
+ title: '',
27
+ fields: group.fields,
28
+ columns: group.columns,
29
+ condition: group.condition,
30
+ })),
31
+ }
32
+ }
33
+
34
+ export function filterSettingsSchemaByAccess(
35
+ schema: SettingsModalSchema,
36
+ canShow: (item: AccessControlled) => boolean
37
+ ): SettingsModalSchema {
38
+ const groups = schema.groups.flatMap((group) => {
39
+ if (!canShow(group)) return []
40
+
41
+ const fields = group.fields.filter(canShow)
42
+ if (fields.length === 0) return []
43
+
44
+ return [{ ...group, fields }]
45
+ })
46
+
47
+ return { groups }
48
+ }
49
+
50
+ export function settingsGroupToTab(group: SettingsGroup): SettingsTab {
51
+ return {
52
+ id: group.id,
53
+ label: group.label,
54
+ icon: group.icon,
55
+ description: group.description,
56
+ }
57
+ }
58
+
59
+ export function normalizeVisibleSettingsTabs(
60
+ tabs: SettingsTabInput[],
61
+ canShow: (item: AccessControlled) => boolean
62
+ ): SettingsTab[] {
63
+ return tabs.map(normalizeItemInput).filter(canShow)
64
+ }
65
+
66
+ export function buildSettingsTabs(
67
+ baseTabs: SettingsTab[],
68
+ showAppearance: boolean
69
+ ): SettingsTab[] {
70
+ return showAppearance ? [...baseTabs, APPEARANCE_TAB] : baseTabs
71
+ }
@@ -24,8 +24,8 @@ import FormFieldRendererInternal from './internal/FormFieldRendererInternal.vue'
24
24
  import { useFormBuilder } from '../composables/useFormBuilder'
25
25
  import {
26
26
  controlsToSettingsSchema,
27
- defineControlModel,
28
27
  mergeControlWorkspaceOptions,
28
+ resolveControlModel,
29
29
  type ControlModel,
30
30
  type ControlModelBinding,
31
31
  type ControlSchema,
@@ -50,26 +50,17 @@ import type {
50
50
  SettingsModalLayout,
51
51
  SettingsModalSchema,
52
52
  SettingsUserType,
53
- FormSchema,
54
- FormSectionSchema,
55
53
  FormEnhancements,
56
54
  } from '../types'
57
55
  import type { AccessControlled, PermissionUser } from '../permissions'
58
- import { normalizeItemInput } from '../utils/items'
59
-
60
- // Map our settings groups onto the form-builder's flat-section shape.
61
- // `title: ''` because the rail/pane header already shows the group name.
62
- function buildFlatSchema(schema: SettingsModalSchema): FormSchema {
63
- return {
64
- sections: schema.groups.map<FormSectionSchema>((g) => ({
65
- id: g.id,
66
- title: '',
67
- fields: g.fields,
68
- columns: g.columns,
69
- condition: g.condition,
70
- })),
71
- }
72
- }
56
+ import {
57
+ APPEARANCE_TAB_ID,
58
+ buildFlatSettingsSchema,
59
+ buildSettingsTabs,
60
+ filterSettingsSchemaByAccess,
61
+ normalizeVisibleSettingsTabs,
62
+ settingsGroupToTab,
63
+ } from './SettingsModal.schema'
73
64
 
74
65
  interface Props {
75
66
  modelValue: boolean
@@ -114,14 +105,6 @@ const settings = useSettingsStore()
114
105
  const auth = useAuthStore()
115
106
  const { user: platformUser } = usePlatformContext()
116
107
 
117
- const APPEARANCE_TAB_ID = 'appearance'
118
-
119
- const APPEARANCE_TAB: SettingsTab = {
120
- id: APPEARANCE_TAB_ID,
121
- label: 'Appearance',
122
- description: 'Theme, color palette, and table density',
123
- }
124
-
125
108
  const isVertical = computed(() => props.layout === 'vertical')
126
109
 
127
110
  // Per-instance prefix for ARIA tab/tabpanel id wiring. Stable across renders.
@@ -130,8 +113,7 @@ const tabId = (id: string) => `${uid}-tab-${id}`
130
113
  const panelId = (id: string) => `${uid}-panel-${id}`
131
114
 
132
115
  const resolvedModel = computed<ControlModelBinding | undefined>(() => {
133
- if (props.model === undefined) return undefined
134
- return isControlModelBinding(props.model) ? props.model : defineControlModel(props.model)
116
+ return resolveControlModel(props.model)
135
117
  })
136
118
  const resolvedControls = computed<ControlSchema | undefined>(() =>
137
119
  props.controls ?? resolvedModel.value?.controls,
@@ -157,15 +139,7 @@ const isAccessUserAuthenticated = computed(() =>
157
139
  )
158
140
  const settingsSchema = computed<SettingsModalSchema | undefined>(() => {
159
141
  if (!sourceSettingsSchema.value) return undefined
160
- const groups = sourceSettingsSchema.value.groups.flatMap((group) => {
161
- if (!canShowForCurrentUser(group)) return []
162
-
163
- const fields = group.fields.filter(canShowForCurrentUser)
164
- if (fields.length === 0) return []
165
-
166
- return [{ ...group, fields }]
167
- })
168
- return { groups }
142
+ return filterSettingsSchemaByAccess(sourceSettingsSchema.value, canShowForCurrentUser)
169
143
  })
170
144
  const isSchemaDriven = computed(() => !!settingsSchema.value)
171
145
  const resolvedValues = computed<Record<string, unknown>>(() => ({
@@ -176,7 +150,7 @@ const resolvedValues = computed<Record<string, unknown>>(() => ({
176
150
  // Schema-driven mode keeps one form-builder instance and syncs schema changes
177
151
  // into it, so callers can swap groups/fields without remounting the modal.
178
152
  const builder = useFormBuilder(
179
- settingsSchema.value ? buildFlatSchema(settingsSchema.value) : { sections: [] },
153
+ settingsSchema.value ? buildFlatSettingsSchema(settingsSchema.value) : { sections: [] },
180
154
  resolvedValues.value,
181
155
  props.enhancements,
182
156
  )
@@ -189,7 +163,7 @@ watch(
189
163
  return
190
164
  }
191
165
 
192
- const flatSchema = buildFlatSchema(schema)
166
+ const flatSchema = buildFlatSettingsSchema(schema)
193
167
  const fieldNames = formSchemaFieldNames(flatSchema)
194
168
  const sourceValues = props.values === undefined
195
169
  ? {
@@ -232,14 +206,14 @@ const visibleSchemaGroups = computed(() =>
232
206
  )
233
207
 
234
208
  const manualTabs = computed<SettingsTab[]>(() =>
235
- props.tabs.map(normalizeItemInput).filter(canShowForCurrentUser)
209
+ normalizeVisibleSettingsTabs(props.tabs, canShowForCurrentUser)
236
210
  )
237
211
 
238
212
  const allTabs = computed<SettingsTab[]>(() => {
239
213
  const base: SettingsTab[] = settingsSchema.value
240
- ? visibleSchemaGroups.value.map((g) => ({ id: g.id, label: g.label, icon: g.icon, description: g.description }))
214
+ ? visibleSchemaGroups.value.map(settingsGroupToTab)
241
215
  : manualTabs.value
242
- return props.showAppearance ? [...base, APPEARANCE_TAB] : base
216
+ return buildSettingsTabs(base, props.showAppearance)
243
217
  })
244
218
 
245
219
  const activeTab = ref(allTabs.value[0]?.id || APPEARANCE_TAB_ID)
@@ -285,10 +259,6 @@ function builderFieldNames(): string[] {
285
259
  return builder.fields.map(field => field.name)
286
260
  }
287
261
 
288
- function isControlModelBinding(model: ControlModel | ControlModelBinding): model is ControlModelBinding {
289
- return 'controls' in model && 'controlOptions' in model
290
- }
291
-
292
262
  function canShowForCurrentUser(item: AccessControlled): boolean {
293
263
  return canAccessByPolicy(
294
264
  currentAccessUser.value,
@@ -0,0 +1,56 @@
1
+ import type { HeatmapConfig } from '../types'
2
+
3
+ export const DEFAULT_SAMPLE_TYPE_COLORS: Record<string, { bg: string; border: string }> = {
4
+ sample: { bg: 'rgba(16, 185, 129, 0.15)', border: 'rgba(16, 185, 129, 0.4)' },
5
+ control: { bg: 'rgba(59, 130, 246, 0.15)', border: 'rgba(59, 130, 246, 0.4)' },
6
+ blank: { bg: 'rgba(249, 115, 22, 0.15)', border: 'rgba(249, 115, 22, 0.4)' },
7
+ qc: { bg: 'rgba(139, 92, 246, 0.15)', border: 'rgba(139, 92, 246, 0.4)' },
8
+ iqc: { bg: 'rgba(236, 72, 153, 0.15)', border: 'rgba(236, 72, 153, 0.4)' },
9
+ }
10
+
11
+ export const HEATMAP_COLORS: Record<string, string[]> = {
12
+ viridis: ['#440154', '#482878', '#3e4989', '#31688e', '#26828e', '#1f9e89', '#35b779', '#6ece58', '#b5de2b', '#fde725'],
13
+ plasma: ['#0d0887', '#46039f', '#7201a8', '#9c179e', '#bd3786', '#d8576b', '#ed7953', '#fb9f3a', '#fdca26', '#f0f921'],
14
+ turbo: ['#30123b', '#4145ab', '#4675ed', '#39a2fc', '#1bcfd4', '#24e79e', '#71f05f', '#c1f034', '#f1c83c', '#f99538', '#e45a31', '#ba2512', '#7a0403'],
15
+ }
16
+
17
+ export function conditionGradientStyle(
18
+ color: string,
19
+ concentration: number,
20
+ concentrations: number[],
21
+ ): Record<string, string> {
22
+ const min = Math.min(...concentrations)
23
+ const max = Math.max(...concentrations)
24
+ const t = max <= min ? 1 : (concentration - min) / (max - min)
25
+ const opacity = 0.25 + t * 0.50
26
+ const r = parseInt(color.slice(1, 3), 16)
27
+ const g = parseInt(color.slice(3, 5), 16)
28
+ const b = parseInt(color.slice(5, 7), 16)
29
+ const er = 255 * (1 - opacity) + r * opacity
30
+ const eg = 255 * (1 - opacity) + g * opacity
31
+ const eb = 255 * (1 - opacity) + b * opacity
32
+ const luminance = (0.299 * er + 0.587 * eg + 0.114 * eb) / 255
33
+ return {
34
+ backgroundColor: `rgba(${r}, ${g}, ${b}, ${opacity})`,
35
+ color: luminance > 0.55 ? '#1e293b' : '#ffffff',
36
+ }
37
+ }
38
+
39
+ export function formatConcentration(value: number): string {
40
+ if (value >= 1000) return `${value / 1000}k`
41
+ if (value < 0.01) return value.toExponential(0)
42
+ return String(value)
43
+ }
44
+
45
+ export function getHeatmapColor(config: HeatmapConfig | undefined, value: number | undefined): string | null {
46
+ if (!config?.enabled || value === undefined) return null
47
+
48
+ const min = config.min ?? 0
49
+ const max = config.max ?? 1
50
+ const normalized = Math.max(0, Math.min(1, (value - min) / (max - min)))
51
+ const colors = config.colorScale === 'custom' && config.customColors?.length
52
+ ? config.customColors
53
+ : HEATMAP_COLORS[config.colorScale || 'viridis']
54
+ const index = Math.min(Math.floor(normalized * (colors.length - 1)), colors.length - 1)
55
+ return colors[index]
56
+ }
@@ -0,0 +1,100 @@
1
+ import type { ColumnCondition, RowCondition } from '../types'
2
+
3
+ export interface ConditionEntry<TCondition> {
4
+ condition: TCondition
5
+ indexInGroup: number
6
+ }
7
+
8
+ export type ColumnConditionSpan =
9
+ | { condition: ColumnCondition; colspan: number }
10
+ | { gap: true; colspan: number }
11
+
12
+ export type RowConditionSpan =
13
+ | { condition: RowCondition; rowspan: number; startRow: number }
14
+ | { gap: true; rowspan: number; startRow: number }
15
+
16
+ export function createColumnConditionMap(
17
+ conditions: ColumnCondition[],
18
+ ): Map<number, ConditionEntry<ColumnCondition>> {
19
+ const map = new Map<number, ConditionEntry<ColumnCondition>>()
20
+ for (const condition of conditions) {
21
+ condition.cols.forEach((col, indexInGroup) => {
22
+ map.set(col, { condition, indexInGroup })
23
+ })
24
+ }
25
+ return map
26
+ }
27
+
28
+ export function createRowConditionMap(
29
+ conditions: RowCondition[],
30
+ ): Map<string, ConditionEntry<RowCondition>> {
31
+ const map = new Map<string, ConditionEntry<RowCondition>>()
32
+ for (const condition of conditions) {
33
+ condition.rows.forEach((row, indexInGroup) => {
34
+ map.set(row, { condition, indexInGroup })
35
+ })
36
+ }
37
+ return map
38
+ }
39
+
40
+ export function createColumnConditionSpans(
41
+ cols: number[],
42
+ conditionMap: ReadonlyMap<number, ConditionEntry<ColumnCondition>>,
43
+ ): ColumnConditionSpan[] {
44
+ const spans: ColumnConditionSpan[] = []
45
+ let index = 0
46
+
47
+ while (index < cols.length) {
48
+ const entry = conditionMap.get(cols[index])
49
+ if (entry?.indexInGroup === 0) {
50
+ spans.push({ condition: entry.condition, colspan: entry.condition.cols.length })
51
+ index += entry.condition.cols.length
52
+ continue
53
+ }
54
+
55
+ let gapCount = 0
56
+ while (index + gapCount < cols.length && !conditionMap.has(cols[index + gapCount])) {
57
+ gapCount++
58
+ }
59
+ spans.push({ gap: true, colspan: gapCount || 1 })
60
+ index += gapCount || 1
61
+ }
62
+
63
+ return spans
64
+ }
65
+
66
+ export function createRowConditionSpans(
67
+ rows: string[],
68
+ conditionMap: ReadonlyMap<string, ConditionEntry<RowCondition>>,
69
+ ): RowConditionSpan[] {
70
+ const spans: RowConditionSpan[] = []
71
+ let index = 0
72
+
73
+ while (index < rows.length) {
74
+ const entry = conditionMap.get(rows[index])
75
+ if (entry?.indexInGroup === 0) {
76
+ spans.push({ condition: entry.condition, rowspan: entry.condition.rows.length, startRow: index })
77
+ index += entry.condition.rows.length
78
+ continue
79
+ }
80
+
81
+ let gapCount = 0
82
+ while (index + gapCount < rows.length && !conditionMap.has(rows[index + gapCount])) {
83
+ gapCount++
84
+ }
85
+ spans.push({ gap: true, rowspan: gapCount || 1, startRow: index })
86
+ index += gapCount || 1
87
+ }
88
+
89
+ return spans
90
+ }
91
+
92
+ export function createRowConditionSpanByRow(
93
+ spans: RowConditionSpan[],
94
+ ): Map<number, RowConditionSpan> {
95
+ const map = new Map<number, RowConditionSpan>()
96
+ for (const span of spans) {
97
+ map.set(span.startRow, span)
98
+ }
99
+ return map
100
+ }