@morscherlab/mint-sdk 1.2.10 → 1.3.0-beta.10

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 (841) hide show
  1. package/README.md +45 -137
  2. package/dist/ResourcePickerListInternal-CFAw4vTZ.js +605 -0
  3. package/dist/ResourcePickerListInternal-CFAw4vTZ.js.map +1 -0
  4. package/dist/__stories__/experiment-helpers.d.ts +12 -1
  5. package/dist/__tests__/components/ScientificNumber.test.d.ts +1 -0
  6. package/dist/__tests__/components/SequenceInput.test.d.ts +1 -0
  7. package/dist/__tests__/components/Skeleton.test.d.ts +1 -0
  8. package/dist/__tests__/components/SmartGroupFieldRecipe.test.d.ts +1 -0
  9. package/dist/__tests__/components/SmartGroupModal.test.d.ts +1 -0
  10. package/dist/__tests__/components/StepWizard.test.d.ts +1 -0
  11. package/dist/__tests__/components/TimeRangeInput.test.d.ts +1 -0
  12. package/dist/__tests__/components/UnitInput.test.d.ts +1 -0
  13. package/dist/__tests__/components/WellPlate.keyboard.test.d.ts +1 -0
  14. package/dist/__tests__/components/WellPlate.sampleTypeIndicator.test.d.ts +1 -0
  15. package/dist/__tests__/composables/useChemicalFormula.test.d.ts +1 -0
  16. package/dist/__tests__/composables/useRackEditor.test.d.ts +1 -0
  17. package/dist/__tests__/composables/useSequenceUtils.test.d.ts +1 -0
  18. package/dist/__tests__/styles/baseControlsRules.test.d.ts +1 -0
  19. package/dist/__tests__/styles/controlRefreshRules.test.d.ts +1 -0
  20. package/dist/__tests__/styles/darkModeRules.test.d.ts +1 -0
  21. package/dist/__tests__/styles/menusShellRefresh.test.d.ts +1 -0
  22. package/dist/__tests__/templates/templatesDeprecation.test.d.ts +1 -0
  23. package/dist/__tests__/utils/plotlyTemplate.test.d.ts +1 -0
  24. package/dist/__tests__/utils/sampleTypeMarker.test.d.ts +1 -0
  25. package/dist/{analysisArtifactTypes-DQ0MjwHZ.js → analysisArtifactTypes-Cy3D0Ipg.js} +1 -1
  26. package/dist/{analysisArtifactTypes-DQ0MjwHZ.js.map → analysisArtifactTypes-Cy3D0Ipg.js.map} +1 -1
  27. package/dist/components/ActionMenu.vue.d.ts +17 -5
  28. package/dist/components/AdductText.vue.d.ts +3 -2
  29. package/dist/components/AlertBox.vue.d.ts +11 -14
  30. package/dist/components/AppAvatarMenu.vue.d.ts +18 -28
  31. package/dist/components/AppContainer.vue.d.ts +7 -11
  32. package/dist/components/AppLayout.vue.d.ts +11 -13
  33. package/dist/components/AppSidebar.vue.d.ts +30 -28
  34. package/dist/components/AppToastContainer.vue.d.ts +2 -1
  35. package/dist/components/AppTopBar.vue.d.ts +45 -44
  36. package/dist/components/ArtifactSaveDialog.vue.d.ts +3 -2
  37. package/dist/components/ArtifactSelectorModal.vue.d.ts +5 -6
  38. package/dist/components/AuditTrail.vue.d.ts +17 -18
  39. package/dist/components/AutoGroupModal.vue.d.ts +4 -3
  40. package/dist/components/Avatar.vue.d.ts +2 -1
  41. package/dist/components/BaseButton.vue.d.ts +11 -13
  42. package/dist/components/BaseCheckbox.vue.d.ts +7 -1
  43. package/dist/components/BaseInput.vue.d.ts +15 -2
  44. package/dist/components/BaseModal.vue.d.ts +20 -23
  45. package/dist/components/BasePill.vue.d.ts +10 -13
  46. package/dist/components/BaseRadioGroup.vue.d.ts +2 -1
  47. package/dist/components/BaseSelect.vue.d.ts +3 -2
  48. package/dist/components/BaseSlider.vue.d.ts +18 -1
  49. package/dist/components/BaseTabs.vue.d.ts +2 -1
  50. package/dist/components/BaseTextarea.vue.d.ts +2 -1
  51. package/dist/components/BaseToggle.vue.d.ts +2 -1
  52. package/dist/components/BatchProgressList.vue.d.ts +22 -26
  53. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +7 -14
  54. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +6 -13
  55. package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +7 -14
  56. package/dist/components/BioTemplateRenderer.vue.d.ts +2 -1
  57. package/dist/components/Breadcrumb.vue.d.ts +13 -16
  58. package/dist/components/Calendar.vue.d.ts +21 -23
  59. package/dist/components/ChartContainer.vue.d.ts +19 -25
  60. package/dist/components/ChemicalFormula.vue.d.ts +7 -11
  61. package/dist/components/CollapsibleCard.vue.d.ts +7 -11
  62. package/dist/components/ComponentBindingRenderer.vue.d.ts +2 -1
  63. package/dist/components/ConcentrationInput.vue.d.ts +2 -1
  64. package/dist/components/ConfirmDialog.vue.d.ts +10 -13
  65. package/dist/components/ControlWorkspaceView.vue.d.ts +9 -18
  66. package/dist/components/DataFrame.vue.d.ts +27 -24
  67. package/dist/components/DatePicker.vue.d.ts +3 -6
  68. package/dist/components/DateTimePicker.vue.d.ts +3 -6
  69. package/dist/components/Divider.vue.d.ts +3 -2
  70. package/dist/components/DoseCalculator.vue.d.ts +2 -1
  71. package/dist/components/DoseCalculatorVolumeField.vue.d.ts +2 -1
  72. package/dist/components/DoseDesignWorkspaceView.vue.d.ts +9 -18
  73. package/dist/components/EmptyState.vue.d.ts +9 -12
  74. package/dist/components/ExperimentCodeBadge.vue.d.ts +2 -1
  75. package/dist/components/ExperimentDataViewer.vue.d.ts +13 -15
  76. package/dist/components/ExperimentPopover.vue.d.ts +3 -5
  77. package/dist/components/ExperimentSelectorModal.vue.d.ts +3 -4
  78. package/dist/components/ExperimentTimeline.vue.d.ts +13 -15
  79. package/dist/components/FilePicker.vue.d.ts +10 -5
  80. package/dist/components/FileUploader.vue.d.ts +8 -16
  81. package/dist/components/FitPanel.vue.d.ts +26 -16
  82. package/dist/components/FormActions.vue.d.ts +2 -1
  83. package/dist/components/FormBuilder.vue.d.ts +54 -250
  84. package/dist/components/FormField.vue.d.ts +14 -16
  85. package/dist/components/FormulaInput.vue.d.ts +2 -1
  86. package/dist/components/GeneratedPathInput.vue.d.ts +6 -5
  87. package/dist/components/GeneratedPlotlyResult.vue.d.ts +2 -1
  88. package/dist/components/GeneratedPluginView.vue.d.ts +2 -1
  89. package/dist/components/GeneratedResultRenderer.vue.d.ts +2 -1
  90. package/dist/components/GroupAssigner.vue.d.ts +2 -1
  91. package/dist/components/IconButton.vue.d.ts +7 -11
  92. package/dist/components/InstrumentStateBadge.vue.d.ts +4 -3
  93. package/dist/components/JobsStatusTray.vue.d.ts +13 -29
  94. package/dist/components/LayoutResizeHandle.vue.d.ts +2 -1
  95. package/dist/components/LoadingSpinner.vue.d.ts +2 -1
  96. package/dist/components/MobileSupportGate.vue.d.ts +5 -13
  97. package/dist/components/MoleculeInput.vue.d.ts +3 -4
  98. package/dist/components/MultiSelect.vue.d.ts +2 -1
  99. package/dist/components/NumberInput.vue.d.ts +2 -1
  100. package/dist/components/PlateEditor.vue.d.ts +147 -0
  101. package/dist/components/PlotlyChart.vue.d.ts +21 -31
  102. package/dist/components/PluginIcon.vue.d.ts +2 -1
  103. package/dist/components/PluginWorkspaceView.props.d.ts +2 -6
  104. package/dist/components/PluginWorkspaceView.vue.d.ts +23 -51
  105. package/dist/components/ProgressBar.vue.d.ts +4 -9
  106. package/dist/components/ProtocolStepEditor.vue.d.ts +7 -5
  107. package/dist/components/ProtocolStepParameterField.vue.d.ts +2 -1
  108. package/dist/components/ReagentEditor.vue.d.ts +2 -1
  109. package/dist/components/ReagentList.presentation.d.ts +2 -1
  110. package/dist/components/ReagentList.vue.d.ts +15 -17
  111. package/dist/components/ResourceCard.vue.d.ts +18 -17
  112. package/dist/components/RuntimeUpdateNotice.vue.d.ts +3 -2
  113. package/dist/components/SampleHierarchyTree.vue.d.ts +21 -15
  114. package/dist/components/SampleLegend.vue.d.ts +2 -1
  115. package/dist/components/SampleSelector.vue.d.ts +15 -21
  116. package/dist/components/SampleSelectorGroupNode.vue.d.ts +2 -1
  117. package/dist/components/SampleSelectorSampleRow.vue.d.ts +2 -5
  118. package/dist/components/ScheduleCalendar.vue.d.ts +34 -36
  119. package/dist/components/ScientificNumber.vue.d.ts +3 -2
  120. package/dist/components/SearchableSelect.vue.d.ts +14 -32
  121. package/dist/components/SecretInput.vue.d.ts +2 -1
  122. package/dist/components/SectionCard.vue.d.ts +13 -14
  123. package/dist/components/SegmentedControl.vue.d.ts +2 -1
  124. package/dist/components/SequenceInput.vue.d.ts +10 -21
  125. package/dist/components/SequenceProgressBar.vue.d.ts +2 -1
  126. package/dist/components/SettingsModal.schema.d.ts +1 -1
  127. package/dist/components/SettingsModal.vue.d.ts +28 -25
  128. package/dist/components/Skeleton.vue.d.ts +2 -1
  129. package/dist/components/SmartGroup.types.d.ts +2 -2
  130. package/dist/components/SmartGroupFieldRecipe.groups.d.ts +2 -0
  131. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +4 -7
  132. package/dist/components/SmartGroupManual.vue.d.ts +3 -2
  133. package/dist/components/SmartGroupModal.vue.d.ts +6 -4
  134. package/dist/components/StatusIndicator.vue.d.ts +2 -1
  135. package/dist/components/StepWizard.vue.d.ts +26 -27
  136. package/dist/components/TagsInput.vue.d.ts +3 -5
  137. package/dist/components/ThemeToggle.vue.d.ts +2 -1
  138. package/dist/components/TimePicker.vue.d.ts +6 -6
  139. package/dist/components/TimeRangeInput.vue.d.ts +9 -2
  140. package/dist/components/Tooltip.vue.d.ts +8 -18
  141. package/dist/components/UnitInput.vue.d.ts +2 -1
  142. package/dist/components/WellPlate.colors.d.ts +2 -4
  143. package/dist/components/WellPlate.rendering.d.ts +7 -1
  144. package/dist/components/WellPlate.sampleDrop.d.ts +2 -0
  145. package/dist/components/WellPlate.vue.d.ts +22 -39
  146. package/dist/components/index.d.ts +34 -31
  147. package/dist/components/index.js +5 -8
  148. package/dist/components/internal/ActionItemInternal.vue.d.ts +11 -13
  149. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +14 -23
  150. package/dist/components/internal/AppTopBarPillNavInternal.vue.d.ts +2 -1
  151. package/dist/components/internal/CalendarGridPanelInternal.vue.d.ts +2 -1
  152. package/dist/components/internal/DataStateInternal.vue.d.ts +7 -11
  153. package/dist/components/internal/{FilePickerTreeInternal.vue.d.ts → FilePickerListInternal.vue.d.ts} +9 -6
  154. package/dist/components/internal/FilePickerPreviewInternal.vue.d.ts +4 -3
  155. package/dist/components/internal/FormFieldRendererInternal.vue.d.ts +16 -18
  156. package/dist/components/internal/FormSectionRenderer.vue.d.ts +36 -32
  157. package/dist/components/internal/PlateEditorBindingInternal.vue.d.ts +8 -0
  158. package/dist/components/internal/ResourcePickerListInternal.vue.d.ts +65 -0
  159. package/dist/components/internal/SettingsPaneHeadInternal.vue.d.ts +15 -0
  160. package/dist/components/internal/WellEditPopupInternal.vue.d.ts +12 -4
  161. package/dist/components/internal/WorkspaceControlsInternal.vue.d.ts +6 -13
  162. package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +19 -42
  163. package/dist/components/internal/WorkspaceSidebarInternal.vue.d.ts +9 -19
  164. package/dist/components/internal/filePickerPresentation.d.ts +8 -0
  165. package/dist/components/internal/generatedJobsApi.d.ts +9 -0
  166. package/dist/{components-Bbg_gtzF.js → components-GDDvof8D.js} +7088 -5955
  167. package/dist/components-GDDvof8D.js.map +1 -0
  168. package/dist/composables/controlSchemaTypes.d.ts +4 -43
  169. package/dist/composables/createFilePickerAdapter.d.ts +5 -1
  170. package/dist/composables/filePicker/usePickerNavigation.d.ts +7 -2
  171. package/dist/composables/index.d.ts +2 -13
  172. package/dist/composables/index.js +7 -11
  173. package/dist/composables/pluginWorkspaceModel.d.ts +1 -3
  174. package/dist/composables/useAutoGroup.d.ts +10 -0
  175. package/dist/composables/useBioTemplateComponents.d.ts +15 -3
  176. package/dist/composables/useBioTemplateControls.d.ts +5 -1
  177. package/dist/composables/useBioTemplatePackWorkspace.d.ts +2 -0
  178. package/dist/composables/useBioTemplatePresetWorkspace.d.ts +5 -1
  179. package/dist/composables/useBioTemplateWorkspace.d.ts +5 -1
  180. package/dist/composables/useChemicalFormula.d.ts +2 -1
  181. package/dist/composables/useDropdownState.d.ts +5 -0
  182. package/dist/composables/useExperimentSave.d.ts +5 -1
  183. package/dist/composables/useFileBrowser.d.ts +3 -2
  184. package/dist/composables/useFilePicker.d.ts +25 -13
  185. package/dist/composables/useFocusTrap.d.ts +2 -1
  186. package/dist/composables/useGroupAssignment.d.ts +5 -1
  187. package/dist/composables/useJobsStatusTray.d.ts +5 -5
  188. package/dist/composables/useMenuKeyboard.d.ts +3 -3
  189. package/dist/composables/usePlatformContext.d.ts +3 -0
  190. package/dist/composables/usePluginClient.d.ts +1 -1
  191. package/dist/composables/useRackEditor.d.ts +36 -1
  192. package/dist/composables/useSequenceUtils.d.ts +8 -0
  193. package/dist/composables/useTemplateCollection.d.ts +5 -1
  194. package/dist/composables/workspaceRecipes.d.ts +1 -0
  195. package/dist/composables-D6uqp0UF.js +591 -0
  196. package/dist/composables-D6uqp0UF.js.map +1 -0
  197. package/dist/{errors-BLuqMee5.js → experiment-DgllIc3I.js} +89 -333
  198. package/dist/experiment-DgllIc3I.js.map +1 -0
  199. package/dist/{experiment-utils-CV2Wza3z.js → experiment-utils-DTANyVKV.js} +68 -37
  200. package/dist/experiment-utils-DTANyVKV.js.map +1 -0
  201. package/dist/index.d.ts +2 -0
  202. package/dist/index.js +122 -17
  203. package/dist/index.js.map +1 -1
  204. package/dist/install.js +1 -2
  205. package/dist/install.js.map +1 -1
  206. package/dist/instrument.d.ts +6 -0
  207. package/dist/lcms.d.ts +11 -0
  208. package/dist/permissions.d.ts +2 -47
  209. package/dist/permissions.js +2 -26
  210. package/dist/permissions.js.map +1 -1
  211. package/dist/settings-BLr8lzw6.js +341 -0
  212. package/dist/settings-BLr8lzw6.js.map +1 -0
  213. package/dist/stores/auth.d.ts +2 -150
  214. package/dist/stores/experiment.d.ts +2 -106
  215. package/dist/stores/index.js +2 -2
  216. package/dist/stores/settings.d.ts +2 -44
  217. package/dist/styles.css +8608 -6950
  218. package/dist/tailwind.preset.js.map +1 -1
  219. package/dist/templates/adapters.d.ts +3 -0
  220. package/dist/templates/assayMatrixAdapters.d.ts +8 -1
  221. package/dist/templates/assayMatrixBuilder.d.ts +1 -0
  222. package/dist/templates/builderPresetControls.d.ts +1 -0
  223. package/dist/templates/calibrationCurveAdapters.d.ts +3 -0
  224. package/dist/templates/calibrationCurveBuilder.d.ts +1 -0
  225. package/dist/templates/catalog.d.ts +6 -2
  226. package/dist/templates/componentBindings.d.ts +31 -5
  227. package/dist/templates/componentPlateHelpers.d.ts +7 -1
  228. package/dist/templates/controlSchemas.d.ts +9 -0
  229. package/dist/templates/defaultBioTemplateBuilder.d.ts +1 -0
  230. package/dist/templates/doseResponseAdapters.d.ts +2 -0
  231. package/dist/templates/doseResponseBuilder.d.ts +1 -0
  232. package/dist/templates/elisaAssayCollectionBuilder.d.ts +1 -0
  233. package/dist/templates/flowCytometryAssayCollectionBuilder.d.ts +1 -0
  234. package/dist/templates/flowCytometryPanelBuilder.d.ts +1 -0
  235. package/dist/templates/flowPanelAdapters.d.ts +3 -0
  236. package/dist/templates/index.d.ts +1 -1
  237. package/dist/templates/index.js +2 -3
  238. package/dist/templates/instrumentRunAdapters.d.ts +13 -2
  239. package/dist/templates/instrumentRunBuilder.d.ts +1 -0
  240. package/dist/templates/lcmsBatchCollectionBuilder.d.ts +1 -0
  241. package/dist/templates/packs.d.ts +4 -0
  242. package/dist/templates/plateMapAdapters.d.ts +2 -0
  243. package/dist/templates/plateMapBuilder.d.ts +1 -0
  244. package/dist/templates/presets.d.ts +6 -2
  245. package/dist/templates/protocolAdapters.d.ts +4 -0
  246. package/dist/templates/protocolStepsBuilder.d.ts +1 -0
  247. package/dist/templates/qpcrAdapters.d.ts +4 -0
  248. package/dist/templates/qpcrExpressionCollectionBuilder.d.ts +1 -0
  249. package/dist/templates/qpcrPlateBuilder.d.ts +1 -0
  250. package/dist/templates/reagentAdapters.d.ts +4 -0
  251. package/dist/templates/reagentListBuilder.d.ts +1 -0
  252. package/dist/templates/samplePrepAdapters.d.ts +3 -0
  253. package/dist/templates/samplePrepBuilder.d.ts +1 -0
  254. package/dist/templates/sampleSheetAdapters.d.ts +4 -0
  255. package/dist/templates/sampleSheetBuilder.d.ts +1 -0
  256. package/dist/templates/targetedMetabolomicsCollectionBuilder.d.ts +1 -0
  257. package/dist/templates/templateEnvelopes.d.ts +8 -0
  258. package/dist/templates/templatePackCollectionBuilder.d.ts +1 -0
  259. package/dist/templates/templatePresetCollectionBuilder.d.ts +2 -0
  260. package/dist/templates/templateValidators.d.ts +12 -0
  261. package/dist/templates/timeCourseAdapters.d.ts +4 -0
  262. package/dist/templates/timeCourseBuilder.d.ts +1 -0
  263. package/dist/templates/wellPlateScreenCollectionBuilder.d.ts +1 -0
  264. package/dist/templates/westernBlotAssayCollectionBuilder.d.ts +1 -0
  265. package/dist/templates-BU1pet28.js +12304 -0
  266. package/dist/templates-BU1pet28.js.map +1 -0
  267. package/dist/types/auth.d.ts +0 -27
  268. package/dist/types/componentLabTypes.d.ts +14 -7
  269. package/dist/types/componentWorkflowTypes.d.ts +26 -0
  270. package/dist/types/components.d.ts +40 -17
  271. package/dist/types/fileBrowserTypes.d.ts +13 -0
  272. package/dist/types/filePicker.d.ts +19 -1
  273. package/dist/types/generated-ui.d.ts +13 -0
  274. package/dist/types/index.d.ts +4 -4
  275. package/dist/types/index.js +1 -1
  276. package/dist/types/instrument.d.ts +43 -15
  277. package/dist/types/platform.d.ts +2 -0
  278. package/dist/utils/color.d.ts +6 -1
  279. package/dist/utils/formModelSync.d.ts +1 -0
  280. package/dist/utils/plotlyTemplate.d.ts +3 -0
  281. package/dist/utils/rack.d.ts +16 -0
  282. package/dist/utils/sampleTypeMarker.d.ts +23 -0
  283. package/dist/{validation-ChMyixAf.js → validation-Dmp9Q5W0.js} +3032 -838
  284. package/dist/validation-Dmp9Q5W0.js.map +1 -0
  285. package/package.json +17 -23
  286. package/src/__stories__/experiment-helpers.ts +8 -4
  287. package/src/__tests__/components/ActionMenu.test.ts +66 -0
  288. package/src/__tests__/components/AlertBox.test.ts +21 -0
  289. package/src/__tests__/components/AppAvatarMenu.test.ts +25 -0
  290. package/src/__tests__/components/AppTopBar.test.ts +79 -0
  291. package/src/__tests__/components/AppTopBarPageSelector.test.ts +20 -0
  292. package/src/__tests__/components/AppTopBarPillNav.test.ts +74 -0
  293. package/src/__tests__/components/ArtifactSelectorModal.test.ts +20 -6
  294. package/src/__tests__/components/AuditTrail.test.ts +38 -0
  295. package/src/__tests__/components/BaseCheckbox.test.ts +43 -0
  296. package/src/__tests__/components/BaseInput.test.ts +43 -0
  297. package/src/__tests__/components/BaseModal.test.ts +90 -0
  298. package/src/__tests__/components/BaseRadioGroup.test.ts +8 -0
  299. package/src/__tests__/components/BaseSlider.test.ts +116 -0
  300. package/src/__tests__/components/BaseToggle.test.ts +7 -0
  301. package/src/__tests__/components/BatchProgressList.test.ts +22 -14
  302. package/src/__tests__/components/BioTemplateExperimentWorkspaceView.test.ts +4 -4
  303. package/src/__tests__/components/BioTemplatePackWorkspaceView.test.ts +1 -1
  304. package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +8 -8
  305. package/src/__tests__/components/BioTemplateRenderer.test.ts +2 -2
  306. package/src/__tests__/components/Breadcrumb.test.ts +45 -0
  307. package/src/__tests__/components/CalendarGridPanel.test.ts +14 -0
  308. package/src/__tests__/components/ChartContainer.test.ts +23 -0
  309. package/src/__tests__/components/ChemicalFormula.test.ts +15 -0
  310. package/src/__tests__/components/CollapsibleCard.test.ts +12 -9
  311. package/src/__tests__/components/ComponentBindingRenderer.test.ts +45 -17
  312. package/src/__tests__/components/ConcentrationInput.test.ts +17 -2
  313. package/src/__tests__/components/DataFrame.test.ts +107 -4
  314. package/src/__tests__/components/DataStates.test.ts +0 -16
  315. package/src/__tests__/components/DatePicker.test.ts +10 -0
  316. package/src/__tests__/components/DoseCalculator.test.ts +47 -0
  317. package/src/__tests__/components/DoseCalculatorVolumeField.test.ts +37 -34
  318. package/src/__tests__/components/EmptyState.test.ts +16 -1
  319. package/src/__tests__/components/ExperimentSelectorModal.test.ts +31 -3
  320. package/src/__tests__/components/ExperimentTimeline.test.ts +45 -0
  321. package/src/__tests__/components/FilePicker.state.test.ts +2 -2
  322. package/src/__tests__/components/FilePicker.test.ts +360 -13
  323. package/src/__tests__/components/FileUploader.test.ts +15 -0
  324. package/src/__tests__/components/FitPanel.test.ts +96 -0
  325. package/src/__tests__/components/FormulaInput.test.ts +97 -0
  326. package/src/__tests__/components/GeneratedPathInput.test.ts +168 -41
  327. package/src/__tests__/components/GeneratedPlotlyResult.test.ts +1 -1
  328. package/src/__tests__/components/GeneratedResultRenderer.test.ts +47 -2
  329. package/src/__tests__/components/InstrumentStateBadge.test.ts +50 -0
  330. package/src/__tests__/components/JobsStatusTray.test.ts +27 -0
  331. package/src/__tests__/components/MoleculeInput.test.ts +78 -0
  332. package/src/__tests__/components/MultiSelect.test.ts +6 -0
  333. package/src/__tests__/components/PlateEditor.test.ts +1134 -0
  334. package/src/__tests__/components/PlateEditorBindingInternal.test.ts +64 -0
  335. package/src/__tests__/components/PlotlyChart.test.ts +147 -1
  336. package/src/__tests__/components/ProgressBar.test.ts +18 -0
  337. package/src/__tests__/components/ProtocolStepEditor.test.ts +106 -18
  338. package/src/__tests__/components/ProtocolStepParameterField.test.ts +74 -29
  339. package/src/__tests__/components/ReagentList.presentation.test.ts +10 -5
  340. package/src/__tests__/components/ReagentList.test.ts +23 -0
  341. package/src/__tests__/components/ResourcePickerListInternal.test.ts +141 -0
  342. package/src/__tests__/components/RetiredStyles.test.ts +0 -6
  343. package/src/__tests__/components/SampleHierarchyTree.test.ts +102 -0
  344. package/src/__tests__/components/SampleLegend.test.ts +18 -0
  345. package/src/__tests__/components/SampleSelector.test.ts +92 -1
  346. package/src/__tests__/components/SampleSelectorSampleRow.test.ts +5 -2
  347. package/src/__tests__/components/ScheduleCalendar.test.ts +32 -0
  348. package/src/__tests__/components/ScientificNumber.test.ts +113 -0
  349. package/src/__tests__/components/SearchableSelect.test.ts +21 -0
  350. package/src/__tests__/components/SecretInput.test.ts +6 -0
  351. package/src/__tests__/components/SegmentedControl.test.ts +14 -0
  352. package/src/__tests__/components/SequenceInput.test.ts +81 -0
  353. package/src/__tests__/components/SettingsModal.schema.test.ts +5 -5
  354. package/src/__tests__/components/SettingsModal.test.ts +371 -23
  355. package/src/__tests__/components/Skeleton.test.ts +23 -0
  356. package/src/__tests__/components/SmartGroupFieldRecipe.test.ts +12 -0
  357. package/src/__tests__/components/SmartGroupModal.test.ts +69 -0
  358. package/src/__tests__/components/StepWizard.test.ts +75 -0
  359. package/src/__tests__/components/TagsInput.test.ts +16 -0
  360. package/src/__tests__/components/TimePicker.test.ts +66 -0
  361. package/src/__tests__/components/TimeRangeInput.test.ts +83 -0
  362. package/src/__tests__/components/UnitInput.test.ts +147 -0
  363. package/src/__tests__/components/WellEditPopupInternal.test.ts +434 -2
  364. package/src/__tests__/components/WellPlate.decoration.test.ts +18 -0
  365. package/src/__tests__/components/WellPlate.geometry.test.ts +13 -0
  366. package/src/__tests__/components/WellPlate.interaction.test.ts +213 -0
  367. package/src/__tests__/components/WellPlate.keyboard.test.ts +24 -0
  368. package/src/__tests__/components/WellPlate.rendering.test.ts +38 -19
  369. package/src/__tests__/components/WellPlate.sampleDrop.test.ts +19 -0
  370. package/src/__tests__/components/WellPlate.sampleTypeIndicator.test.ts +58 -0
  371. package/src/__tests__/composables/createFilePickerAdapter.test.ts +114 -1
  372. package/src/__tests__/composables/useBioTemplatePackWorkspace.test.ts +1 -1
  373. package/src/__tests__/composables/useBioTemplateWorkspace.test.ts +1 -1
  374. package/src/__tests__/composables/useChemicalFormula.test.ts +60 -0
  375. package/src/__tests__/composables/useControlSchema.test.ts +15 -5
  376. package/src/__tests__/composables/useDropdownState.test.ts +20 -1
  377. package/src/__tests__/composables/useGeneratedAnalysis.test.ts +52 -0
  378. package/src/__tests__/composables/usePickerNavigation.test.ts +61 -1
  379. package/src/__tests__/composables/usePlatformFilePickerAdapter.test.ts +18 -6
  380. package/src/__tests__/composables/useRackEditor.test.ts +270 -0
  381. package/src/__tests__/composables/useSequenceUtils.test.ts +28 -0
  382. package/src/__tests__/docs/frontendDocsCatalog.test.ts +44 -9
  383. package/src/__tests__/styles/baseControlsRules.test.ts +115 -0
  384. package/src/__tests__/styles/controlRefreshRules.test.ts +218 -0
  385. package/src/__tests__/styles/cssTokens.test.ts +7 -5
  386. package/src/__tests__/styles/darkModeRules.test.ts +47 -0
  387. package/src/__tests__/styles/menusShellRefresh.test.ts +75 -0
  388. package/src/__tests__/templates/templates.test.ts +65 -15
  389. package/src/__tests__/templates/templatesDeprecation.test.ts +78 -0
  390. package/src/__tests__/utils/permissions.test.ts +0 -68
  391. package/src/__tests__/utils/plotlyTemplate.test.ts +69 -0
  392. package/src/__tests__/utils/sampleTypeMarker.test.ts +54 -0
  393. package/src/components/ActionMenu.vue +44 -23
  394. package/src/components/AdductText.story.vue +18 -0
  395. package/src/components/AdductText.vue +7 -1
  396. package/src/components/AlertBox.vue +3 -7
  397. package/src/components/AppAvatarMenu.vue +12 -10
  398. package/src/components/AppSidebar.vue +1 -1
  399. package/src/components/AppTopBar.story.vue +47 -4
  400. package/src/components/AppTopBar.vue +16 -22
  401. package/src/components/ArtifactSelectorModal.story.vue +1 -1
  402. package/src/components/ArtifactSelectorModal.vue +48 -160
  403. package/src/components/AuditTrail.vue +26 -12
  404. package/src/components/AutoGroupModal.vue +1 -1
  405. package/src/components/BaseCheckbox.story.vue +58 -2
  406. package/src/components/BaseCheckbox.vue +21 -3
  407. package/src/components/BaseInput.story.vue +51 -0
  408. package/src/components/BaseInput.vue +62 -1
  409. package/src/components/BaseModal.story.vue +55 -0
  410. package/src/components/BaseModal.vue +83 -50
  411. package/src/components/BaseRadioGroup.vue +1 -1
  412. package/src/components/BaseSlider.story.vue +36 -0
  413. package/src/components/BaseSlider.vue +56 -8
  414. package/src/components/BaseToggle.vue +1 -7
  415. package/src/components/BatchProgressList.vue +50 -52
  416. package/src/components/BioTemplatePresetWorkspaceView.vue +1 -1
  417. package/src/components/Breadcrumb.story.vue +1 -1
  418. package/src/components/Breadcrumb.vue +50 -15
  419. package/src/components/ChartContainer.story.vue +42 -0
  420. package/src/components/ChartContainer.vue +22 -1
  421. package/src/components/ChemicalFormula.story.vue +11 -11
  422. package/src/components/ChemicalFormula.vue +1 -0
  423. package/src/components/CollapsibleCard.vue +12 -32
  424. package/src/components/ComponentBindingRenderer.vue +6 -8
  425. package/src/components/ConcentrationInput.story.vue +1 -1
  426. package/src/components/ConcentrationInput.vue +8 -14
  427. package/src/components/ControlWorkspaceView.vue +1 -1
  428. package/src/components/DataFrame.story.vue +45 -2
  429. package/src/components/DataFrame.vue +28 -13
  430. package/src/components/DatePicker.story.vue +11 -0
  431. package/src/components/DatePicker.vue +5 -5
  432. package/src/components/DateTimePicker.story.vue +1 -1
  433. package/src/components/DateTimePicker.vue +8 -5
  434. package/src/components/Divider.story.vue +1 -1
  435. package/src/components/DoseCalculator.vue +44 -51
  436. package/src/components/DoseCalculatorVolumeField.vue +22 -35
  437. package/src/components/DoseDesignWorkspaceView.vue +1 -1
  438. package/src/components/EmptyState.story.vue +4 -4
  439. package/src/components/EmptyState.vue +4 -2
  440. package/src/components/ExperimentPopover.story.vue +2 -2
  441. package/src/components/ExperimentPopover.vue +6 -4
  442. package/src/components/ExperimentSelectorModal.story.vue +2 -1
  443. package/src/components/ExperimentSelectorModal.vue +91 -261
  444. package/src/components/ExperimentTimeline.story.vue +29 -0
  445. package/src/components/ExperimentTimeline.vue +20 -0
  446. package/src/components/FilePicker.story.vue +65 -10
  447. package/src/components/FilePicker.vue +203 -121
  448. package/src/components/FitPanel.story.vue +72 -6
  449. package/src/components/FitPanel.vue +70 -18
  450. package/src/components/FormField.vue +2 -0
  451. package/src/components/FormulaInput.story.vue +6 -0
  452. package/src/components/FormulaInput.vue +49 -70
  453. package/src/components/GeneratedPathInput.story.vue +121 -8
  454. package/src/components/GeneratedPathInput.vue +155 -86
  455. package/src/components/GeneratedPlotlyResult.vue +1 -1
  456. package/src/components/GeneratedPluginView.vue +4 -4
  457. package/src/components/GeneratedResultRenderer.vue +19 -0
  458. package/src/components/InstrumentStateBadge.story.vue +41 -0
  459. package/src/components/InstrumentStateBadge.vue +24 -14
  460. package/src/components/JobsStatusTray.vue +30 -8
  461. package/src/components/MoleculeInput.vue +12 -7
  462. package/src/components/MultiSelect.vue +3 -3
  463. package/src/components/PlateEditor.story.vue +333 -0
  464. package/src/components/PlateEditor.vue +793 -0
  465. package/src/components/PlotlyChart.story.vue +37 -1
  466. package/src/components/PlotlyChart.vue +86 -16
  467. package/src/components/PluginWorkspaceView.props.ts +1 -7
  468. package/src/components/PluginWorkspaceView.vue +0 -4
  469. package/src/components/ProgressBar.story.vue +0 -30
  470. package/src/components/ProgressBar.vue +3 -53
  471. package/src/components/ProtocolStepEditor.story.vue +8 -0
  472. package/src/components/ProtocolStepEditor.vue +55 -145
  473. package/src/components/ProtocolStepParameterField.vue +55 -93
  474. package/src/components/ReagentList.presentation.ts +7 -6
  475. package/src/components/ReagentList.vue +18 -17
  476. package/src/components/SampleHierarchyTree.story.vue +19 -0
  477. package/src/components/SampleHierarchyTree.vue +47 -14
  478. package/src/components/SampleLegend.vue +12 -4
  479. package/src/components/SampleSelector.story.vue +5 -1
  480. package/src/components/SampleSelector.vue +25 -15
  481. package/src/components/SampleSelectorGroupNode.vue +10 -20
  482. package/src/components/SampleSelectorSampleRow.vue +7 -18
  483. package/src/components/ScheduleCalendar.story.vue +14 -0
  484. package/src/components/ScheduleCalendar.vue +13 -1
  485. package/src/components/ScientificNumber.story.vue +15 -2
  486. package/src/components/ScientificNumber.vue +22 -26
  487. package/src/components/SearchableSelect.vue +14 -9
  488. package/src/components/SecretInput.vue +1 -1
  489. package/src/components/SegmentedControl.story.vue +23 -0
  490. package/src/components/SegmentedControl.vue +6 -1
  491. package/src/components/SequenceInput.story.vue +27 -5
  492. package/src/components/SequenceInput.vue +74 -29
  493. package/src/components/SequenceProgressBar.vue +0 -1
  494. package/src/components/SettingsModal.schema.ts +4 -2
  495. package/src/components/SettingsModal.story.vue +83 -22
  496. package/src/components/SettingsModal.vue +338 -79
  497. package/src/components/Skeleton.vue +6 -35
  498. package/src/components/SmartGroup.types.ts +2 -2
  499. package/src/components/SmartGroupFieldRecipe.groups.ts +4 -1
  500. package/src/components/SmartGroupFieldRecipe.vue +14 -8
  501. package/src/components/SmartGroupManual.vue +14 -11
  502. package/src/components/StepWizard.vue +16 -19
  503. package/src/components/TagsInput.story.vue +16 -11
  504. package/src/components/TagsInput.vue +20 -3
  505. package/src/components/TimePicker.story.vue +38 -3
  506. package/src/components/TimePicker.vue +26 -11
  507. package/src/components/TimeRangeInput.story.vue +50 -1
  508. package/src/components/TimeRangeInput.vue +36 -17
  509. package/src/components/UnitInput.story.vue +1 -1
  510. package/src/components/UnitInput.vue +173 -107
  511. package/src/components/WellPlate.colors.ts +7 -6
  512. package/src/components/WellPlate.geometry.ts +3 -0
  513. package/src/components/WellPlate.interaction.ts +39 -5
  514. package/src/components/WellPlate.rendering.ts +21 -27
  515. package/src/components/WellPlate.sampleDrop.ts +20 -12
  516. package/src/components/WellPlate.story.vue +18 -7
  517. package/src/components/WellPlate.vue +28 -22
  518. package/src/components/index.ts +34 -31
  519. package/src/components/internal/AppTopBarPageSelectorInternal.vue +13 -7
  520. package/src/components/internal/AppTopBarPillNavInternal.vue +12 -7
  521. package/src/components/internal/CalendarGridPanelInternal.vue +1 -1
  522. package/src/components/internal/FilePickerListInternal.vue +318 -0
  523. package/src/components/internal/FilePickerPreviewInternal.vue +54 -52
  524. package/src/components/internal/PlateEditorBindingInternal.vue +37 -0
  525. package/src/components/internal/ResourcePickerListInternal.vue +237 -0
  526. package/src/components/internal/SettingsPaneHeadInternal.vue +41 -0
  527. package/src/components/internal/WellEditPopupInternal.vue +219 -146
  528. package/src/components/internal/WorkspaceShellInternal.vue +0 -6
  529. package/src/components/internal/filePickerPresentation.ts +30 -0
  530. package/src/components/internal/generatedJobsApi.ts +12 -0
  531. package/src/composables/autoGroup/index.ts +3 -0
  532. package/src/composables/controlSchemaAdapters.ts +0 -4
  533. package/src/composables/controlSchemaFormFields.ts +0 -4
  534. package/src/composables/controlSchemaTypes.ts +4 -43
  535. package/src/composables/createFilePickerAdapter.ts +90 -22
  536. package/src/composables/filePicker/localFiles.ts +1 -0
  537. package/src/composables/filePicker/usePickerNavigation.ts +29 -2
  538. package/src/composables/index.ts +2 -71
  539. package/src/composables/pluginWorkspaceModel.ts +0 -3
  540. package/src/composables/useAutoGroup.ts +10 -0
  541. package/src/composables/useBioTemplateComponents.ts +15 -3
  542. package/src/composables/useBioTemplateControls.ts +5 -1
  543. package/src/composables/useBioTemplatePackWorkspace.ts +2 -0
  544. package/src/composables/useBioTemplatePresetWorkspace.ts +5 -1
  545. package/src/composables/useBioTemplateWorkspace.ts +5 -1
  546. package/src/composables/useChemicalFormula.ts +39 -13
  547. package/src/composables/useDropdownState.ts +6 -1
  548. package/src/composables/useExperimentSave.ts +5 -1
  549. package/src/composables/useFileBrowser.ts +3 -2
  550. package/src/composables/useFilePicker.ts +98 -13
  551. package/src/composables/useFocusTrap.ts +9 -6
  552. package/src/composables/useGeneratedAnalysis.ts +38 -0
  553. package/src/composables/useGroupAssignment.ts +5 -1
  554. package/src/composables/useJobsStatusTray.ts +5 -5
  555. package/src/composables/useMenuKeyboard.ts +5 -3
  556. package/src/composables/usePlatformFilePickerAdapter.ts +26 -4
  557. package/src/composables/usePluginClient.ts +1 -1
  558. package/src/composables/usePluginWorkspace.ts +0 -1
  559. package/src/composables/useRackEditor.ts +202 -12
  560. package/src/composables/useSequenceUtils.ts +20 -2
  561. package/src/composables/useTemplateCollection.ts +5 -1
  562. package/src/composables/workspaceRecipes.ts +1 -0
  563. package/src/index.ts +9 -3
  564. package/src/instrument.ts +6 -0
  565. package/src/lcms.ts +11 -0
  566. package/src/permissions.ts +2 -59
  567. package/src/styles/components/action-menu.css +9 -38
  568. package/src/styles/components/adduct-text.css +15 -3
  569. package/src/styles/components/alert-box.css +19 -70
  570. package/src/styles/components/app-avatar-menu.css +22 -57
  571. package/src/styles/components/app-container.css +4 -4
  572. package/src/styles/components/app-layout.css +18 -18
  573. package/src/styles/components/app-page-selector.css +50 -105
  574. package/src/styles/components/app-pill-nav.css +24 -42
  575. package/src/styles/components/app-sidebar.css +2 -2
  576. package/src/styles/components/app-top-bar.css +78 -55
  577. package/src/styles/components/artifact-selector-modal.css +1 -211
  578. package/src/styles/components/audit-trail.css +45 -38
  579. package/src/styles/components/avatar.css +1 -1
  580. package/src/styles/components/batch-progress-list.css +179 -95
  581. package/src/styles/components/breadcrumb.css +34 -15
  582. package/src/styles/components/calendar.css +2 -8
  583. package/src/styles/components/chart-container.css +81 -38
  584. package/src/styles/components/checkbox.css +8 -6
  585. package/src/styles/components/chemical-formula.css +8 -6
  586. package/src/styles/components/collapsible-card.css +6 -46
  587. package/src/styles/components/concentration-input.css +1 -10
  588. package/src/styles/components/dataframe.css +48 -67
  589. package/src/styles/components/date-picker.css +124 -62
  590. package/src/styles/components/datetime-picker.css +81 -47
  591. package/src/styles/components/divider.css +2 -4
  592. package/src/styles/components/dose-calculator.css +9 -135
  593. package/src/styles/components/empty-state.css +26 -35
  594. package/src/styles/components/experiment-code-badge.css +1 -1
  595. package/src/styles/components/experiment-popover.css +16 -83
  596. package/src/styles/components/experiment-selector-modal.css +9 -226
  597. package/src/styles/components/experiment-timeline.css +120 -50
  598. package/src/styles/components/file-picker.css +323 -299
  599. package/src/styles/components/file-uploader.css +4 -6
  600. package/src/styles/components/fit-panel.css +108 -22
  601. package/src/styles/components/form-field.css +6 -4
  602. package/src/styles/components/formula-input.css +121 -48
  603. package/src/styles/components/group-assigner.css +1 -3
  604. package/src/styles/components/icon-button.css +15 -37
  605. package/src/styles/components/input.css +91 -2
  606. package/src/styles/components/instrument-monitor.css +37 -447
  607. package/src/styles/components/jobs-status-tray.css +82 -61
  608. package/src/styles/components/loading-spinner.css +18 -0
  609. package/src/styles/components/mobile-support-gate.css +15 -17
  610. package/src/styles/components/modal.css +44 -33
  611. package/src/styles/components/molecule-input.css +31 -16
  612. package/src/styles/components/multi-select.css +33 -29
  613. package/src/styles/components/number-input.css +1 -1
  614. package/src/styles/components/plate-editor.css +497 -0
  615. package/src/styles/components/popover.css +162 -0
  616. package/src/styles/components/progress-bar.css +1 -70
  617. package/src/styles/components/protocol-step-editor.css +21 -333
  618. package/src/styles/components/radio-group.css +9 -18
  619. package/src/styles/components/reagent-editor.css +3 -7
  620. package/src/styles/components/reagent-list.css +63 -69
  621. package/src/styles/components/resource-card.css +4 -6
  622. package/src/styles/components/resource-picker-list.css +212 -0
  623. package/src/styles/components/sample-hierarchy-tree.css +83 -65
  624. package/src/styles/components/sample-legend.css +18 -7
  625. package/src/styles/components/sample-selector.css +41 -68
  626. package/src/styles/components/schedule-calendar.css +59 -54
  627. package/src/styles/components/scientific-number.css +72 -18
  628. package/src/styles/components/searchable-select.css +17 -26
  629. package/src/styles/components/secret-input.css +20 -23
  630. package/src/styles/components/section-card.css +3 -5
  631. package/src/styles/components/segmented-control.css +14 -1
  632. package/src/styles/components/select.css +19 -8
  633. package/src/styles/components/sequence-input.css +85 -37
  634. package/src/styles/components/sequence-progress-bar.css +18 -37
  635. package/src/styles/components/settings-modal.css +683 -34
  636. package/src/styles/components/skeleton.css +24 -23
  637. package/src/styles/components/slider.css +74 -8
  638. package/src/styles/components/smart-group.css +27 -39
  639. package/src/styles/components/status-indicator.css +1 -1
  640. package/src/styles/components/step-wizard.css +62 -99
  641. package/src/styles/components/tabs.css +2 -6
  642. package/src/styles/components/tags-input.css +64 -54
  643. package/src/styles/components/textarea.css +2 -2
  644. package/src/styles/components/time-picker.css +67 -38
  645. package/src/styles/components/time-range-input.css +16 -18
  646. package/src/styles/components/toast.css +1 -1
  647. package/src/styles/components/toggle.css +21 -31
  648. package/src/styles/components/tooltip.css +13 -15
  649. package/src/styles/components/unit-input.css +86 -36
  650. package/src/styles/components/well-edit-popup.css +111 -189
  651. package/src/styles/components/well-plate.css +7 -7
  652. package/src/styles/index.css +5 -7
  653. package/src/styles/variables.css +35 -7
  654. package/src/templates/adapters.ts +4 -0
  655. package/src/templates/assayMatrixAdapters.ts +8 -1
  656. package/src/templates/assayMatrixBuilder.ts +1 -0
  657. package/src/templates/builderPresetControls.ts +1 -0
  658. package/src/templates/calibrationCurveAdapters.ts +3 -0
  659. package/src/templates/calibrationCurveBuilder.ts +1 -0
  660. package/src/templates/catalog.ts +6 -2
  661. package/src/templates/componentBindingCatalog.ts +1 -1
  662. package/src/templates/componentBindings.ts +31 -5
  663. package/src/templates/componentDoseResponseProps.ts +0 -1
  664. package/src/templates/componentPlateHelpers.ts +22 -1
  665. package/src/templates/componentPlateMapProps.ts +7 -5
  666. package/src/templates/componentQpcrPlateProps.ts +0 -1
  667. package/src/templates/controlSchemas.ts +9 -0
  668. package/src/templates/defaultBioTemplateBuilder.ts +1 -0
  669. package/src/templates/doseResponseAdapters.ts +2 -0
  670. package/src/templates/doseResponseBuilder.ts +1 -0
  671. package/src/templates/elisaAssayCollectionBuilder.ts +1 -0
  672. package/src/templates/flowCytometryAssayCollectionBuilder.ts +1 -0
  673. package/src/templates/flowCytometryPanelBuilder.ts +1 -0
  674. package/src/templates/flowPanelAdapters.ts +3 -0
  675. package/src/templates/index.ts +4 -0
  676. package/src/templates/instrumentRunAdapters.ts +13 -2
  677. package/src/templates/instrumentRunBuilder.ts +1 -0
  678. package/src/templates/lcmsBatchCollectionBuilder.ts +1 -0
  679. package/src/templates/packs.ts +4 -0
  680. package/src/templates/plateMapAdapters.ts +2 -0
  681. package/src/templates/plateMapBuilder.ts +1 -0
  682. package/src/templates/presets.ts +6 -2
  683. package/src/templates/protocolAdapters.ts +4 -0
  684. package/src/templates/protocolStepsBuilder.ts +1 -0
  685. package/src/templates/qpcrAdapters.ts +4 -0
  686. package/src/templates/qpcrExpressionCollectionBuilder.ts +1 -0
  687. package/src/templates/qpcrPlateBuilder.ts +1 -0
  688. package/src/templates/reagentAdapters.ts +4 -0
  689. package/src/templates/reagentListBuilder.ts +1 -0
  690. package/src/templates/samplePrepAdapters.ts +3 -0
  691. package/src/templates/samplePrepBuilder.ts +1 -0
  692. package/src/templates/sampleSheetAdapters.ts +4 -0
  693. package/src/templates/sampleSheetBuilder.ts +1 -0
  694. package/src/templates/targetedMetabolomicsCollectionBuilder.ts +1 -0
  695. package/src/templates/templateEnvelopes.ts +8 -0
  696. package/src/templates/templatePackCollectionBuilder.ts +1 -0
  697. package/src/templates/templatePresetCollectionBuilder.ts +2 -0
  698. package/src/templates/templateValidators.ts +12 -0
  699. package/src/templates/timeCourseAdapters.ts +4 -0
  700. package/src/templates/timeCourseBuilder.ts +1 -0
  701. package/src/templates/wellPlateScreenCollectionBuilder.ts +1 -0
  702. package/src/templates/westernBlotAssayCollectionBuilder.ts +1 -0
  703. package/src/types/auth.ts +0 -37
  704. package/src/types/componentLabTypes.ts +16 -13
  705. package/src/types/componentWorkflowTypes.ts +29 -0
  706. package/src/types/components.ts +43 -20
  707. package/src/types/fileBrowserTypes.ts +15 -0
  708. package/src/types/filePicker.ts +19 -1
  709. package/src/types/generated-ui.ts +15 -0
  710. package/src/types/index.ts +12 -11
  711. package/src/types/instrument.ts +47 -15
  712. package/src/types/platform.ts +2 -0
  713. package/src/utils/color.ts +16 -1
  714. package/src/utils/formModelSync.ts +1 -1
  715. package/src/utils/plotlyTemplate.ts +39 -0
  716. package/src/utils/rack.ts +16 -0
  717. package/src/utils/sampleTypeMarker.ts +44 -0
  718. package/dist/ExperimentPopover-CJdNlCZb.js +0 -451
  719. package/dist/ExperimentPopover-CJdNlCZb.js.map +0 -1
  720. package/dist/ExperimentSelectorModal-DHE9k8TP.js +0 -507
  721. package/dist/ExperimentSelectorModal-DHE9k8TP.js.map +0 -1
  722. package/dist/SettingsModal-DELMkUFR.js +0 -492
  723. package/dist/SettingsModal-DELMkUFR.js.map +0 -1
  724. package/dist/Skeleton-jhF9wUkU.js +0 -485
  725. package/dist/Skeleton-jhF9wUkU.js.map +0 -1
  726. package/dist/__tests__/composables/usePluginConfig.test.d.ts +0 -15
  727. package/dist/chunk-BoAXSpZd.js +0 -33
  728. package/dist/components/AppPluginSwitcher.vue.d.ts +0 -40
  729. package/dist/components/ColorSlider.vue.d.ts +0 -34
  730. package/dist/components/DropdownButton.vue.d.ts +0 -49
  731. package/dist/components/FileBrowserModal.vue.d.ts +0 -99
  732. package/dist/components/InstrumentAlertLog.vue.d.ts +0 -22
  733. package/dist/components/InstrumentStatusCard.vue.d.ts +0 -13
  734. package/dist/components/LcmsSequenceTable.vue.d.ts +0 -54
  735. package/dist/components/PlateMapEditor.vue.d.ts +0 -50
  736. package/dist/components/RackEditor.vue.d.ts +0 -78
  737. package/dist/components/fileBrowserPresentation.d.ts +0 -10
  738. package/dist/components/internal/FileBrowserDialogInternal.vue.d.ts +0 -34
  739. package/dist/components/internal/FileBrowserListingInternal.vue.d.ts +0 -25
  740. package/dist/components/internal/FileBrowserToolbarInternal.vue.d.ts +0 -26
  741. package/dist/components/internal/PlateMapEditorToolbarInternal.vue.d.ts +0 -28
  742. package/dist/components-Bbg_gtzF.js.map +0 -1
  743. package/dist/composables/useAsync.d.ts +0 -132
  744. package/dist/composables/useAuth.d.ts +0 -47
  745. package/dist/composables/useCommandHistory.d.ts +0 -33
  746. package/dist/composables/useOptimisticMutation.d.ts +0 -32
  747. package/dist/composables/usePasskey.d.ts +0 -10
  748. package/dist/composables/usePluginConfig.d.ts +0 -27
  749. package/dist/composables/useResourceCrud.d.ts +0 -44
  750. package/dist/composables/useWellPainting.d.ts +0 -39
  751. package/dist/composables/useWellPlateAdapter.d.ts +0 -40
  752. package/dist/composables/useWellPlateEditor.d.ts +0 -33
  753. package/dist/composables/useWellPlateValidation.d.ts +0 -31
  754. package/dist/composables-BCbYb2lA.js +0 -2356
  755. package/dist/composables-BCbYb2lA.js.map +0 -1
  756. package/dist/errors-BLuqMee5.js.map +0 -1
  757. package/dist/experiment-CVDRAnqp.js +0 -90
  758. package/dist/experiment-CVDRAnqp.js.map +0 -1
  759. package/dist/experiment-utils-CV2Wza3z.js.map +0 -1
  760. package/dist/plotly.min-c2Sez60c.js +0 -180634
  761. package/dist/plotly.min-c2Sez60c.js.map +0 -1
  762. package/dist/templates-NuaNHohp.js +0 -5260
  763. package/dist/templates-NuaNHohp.js.map +0 -1
  764. package/dist/useControlSchema-vLiRPUmj.js +0 -7301
  765. package/dist/useControlSchema-vLiRPUmj.js.map +0 -1
  766. package/dist/useDropdownState-C7hRiVQf.js +0 -63
  767. package/dist/useDropdownState-C7hRiVQf.js.map +0 -1
  768. package/dist/useExperimentSelector-G_CAOFTX.js +0 -328
  769. package/dist/useExperimentSelector-G_CAOFTX.js.map +0 -1
  770. package/dist/useFormBuilder-D37ajgS8.js +0 -729
  771. package/dist/useFormBuilder-D37ajgS8.js.map +0 -1
  772. package/dist/validation-ChMyixAf.js.map +0 -1
  773. package/src/__tests__/components/AppPluginSwitcher.test.ts +0 -44
  774. package/src/__tests__/components/DropdownButton.test.ts +0 -628
  775. package/src/__tests__/components/FileBrowserModal.test.ts +0 -460
  776. package/src/__tests__/components/InstrumentAlertLog.test.ts +0 -59
  777. package/src/__tests__/components/LcmsSequenceTable.test.ts +0 -79
  778. package/src/__tests__/components/PlateMapEditorToolbarInternal.test.ts +0 -54
  779. package/src/__tests__/components/RackEditor.test.ts +0 -169
  780. package/src/__tests__/composables/useAuth.test.ts +0 -233
  781. package/src/__tests__/composables/useCommandHistory.test.ts +0 -43
  782. package/src/__tests__/composables/useOptimisticMutation.test.ts +0 -40
  783. package/src/__tests__/composables/usePluginConfig.test.ts +0 -497
  784. package/src/__tests__/composables/useResourceCrud.test.ts +0 -56
  785. package/src/__tests__/composables/useWellPainting.test.ts +0 -52
  786. package/src/__tests__/composables/useWellPlateAdapter.test.ts +0 -50
  787. package/src/__tests__/composables/useWellPlateValidation.test.ts +0 -42
  788. package/src/components/AppPluginSwitcher.story.vue +0 -87
  789. package/src/components/AppPluginSwitcher.vue +0 -134
  790. package/src/components/ColorSlider.story.vue +0 -120
  791. package/src/components/ColorSlider.vue +0 -160
  792. package/src/components/DropdownButton.story.vue +0 -102
  793. package/src/components/DropdownButton.vue +0 -181
  794. package/src/components/FileBrowserModal.story.vue +0 -203
  795. package/src/components/FileBrowserModal.vue +0 -384
  796. package/src/components/InstrumentAlertLog.vue +0 -187
  797. package/src/components/InstrumentStatusCard.vue +0 -184
  798. package/src/components/LcmsSequenceTable.vue +0 -222
  799. package/src/components/PlateMapEditor.story.vue +0 -92
  800. package/src/components/PlateMapEditor.vue +0 -423
  801. package/src/components/RackEditor.story.vue +0 -100
  802. package/src/components/RackEditor.vue +0 -429
  803. package/src/components/fileBrowserPresentation.ts +0 -39
  804. package/src/components/internal/FileBrowserDialogInternal.vue +0 -75
  805. package/src/components/internal/FileBrowserListingInternal.vue +0 -197
  806. package/src/components/internal/FileBrowserToolbarInternal.vue +0 -136
  807. package/src/components/internal/FilePickerTreeInternal.vue +0 -238
  808. package/src/components/internal/PlateMapEditorToolbarInternal.vue +0 -128
  809. package/src/composables/useAsync.ts +0 -327
  810. package/src/composables/useAuth.ts +0 -458
  811. package/src/composables/useCommandHistory.ts +0 -117
  812. package/src/composables/useOptimisticMutation.ts +0 -97
  813. package/src/composables/usePasskey.ts +0 -216
  814. package/src/composables/usePluginConfig.ts +0 -252
  815. package/src/composables/useResourceCrud.ts +0 -235
  816. package/src/composables/useWellPainting.ts +0 -167
  817. package/src/composables/useWellPlateAdapter.ts +0 -151
  818. package/src/composables/useWellPlateEditor.ts +0 -415
  819. package/src/composables/useWellPlateValidation.ts +0 -89
  820. package/src/plotly-dist.d.ts +0 -3
  821. package/src/styles/components/app-plugin-switcher.css +0 -196
  822. package/src/styles/components/color-slider.css +0 -110
  823. package/src/styles/components/dropdown-button.css +0 -280
  824. package/src/styles/components/file-browser-modal.css +0 -489
  825. package/src/styles/components/lcms-sequence-table.css +0 -204
  826. package/src/styles/components/plate-map-editor.css +0 -464
  827. package/src/styles/components/rack-editor.css +0 -287
  828. /package/dist/__tests__/components/{AppPluginSwitcher.test.d.ts → AlertBox.test.d.ts} +0 -0
  829. /package/dist/__tests__/components/{DropdownButton.test.d.ts → AuditTrail.test.d.ts} +0 -0
  830. /package/dist/__tests__/components/{FileBrowserModal.test.d.ts → BaseCheckbox.test.d.ts} +0 -0
  831. /package/dist/__tests__/components/{InstrumentAlertLog.test.d.ts → BaseSlider.test.d.ts} +0 -0
  832. /package/dist/__tests__/components/{LcmsSequenceTable.test.d.ts → DoseCalculator.test.d.ts} +0 -0
  833. /package/dist/__tests__/components/{PlateMapEditorToolbarInternal.test.d.ts → FileUploader.test.d.ts} +0 -0
  834. /package/dist/__tests__/components/{RackEditor.test.d.ts → FitPanel.test.d.ts} +0 -0
  835. /package/dist/__tests__/{composables/useAuth.test.d.ts → components/FormulaInput.test.d.ts} +0 -0
  836. /package/dist/__tests__/{composables/useCommandHistory.test.d.ts → components/InstrumentStateBadge.test.d.ts} +0 -0
  837. /package/dist/__tests__/{composables/useOptimisticMutation.test.d.ts → components/MoleculeInput.test.d.ts} +0 -0
  838. /package/dist/__tests__/{composables/useResourceCrud.test.d.ts → components/PlateEditor.test.d.ts} +0 -0
  839. /package/dist/__tests__/{composables/useWellPainting.test.d.ts → components/PlateEditorBindingInternal.test.d.ts} +0 -0
  840. /package/dist/__tests__/{composables/useWellPlateAdapter.test.d.ts → components/ResourcePickerListInternal.test.d.ts} +0 -0
  841. /package/dist/__tests__/{composables/useWellPlateValidation.test.d.ts → components/SampleLegend.test.d.ts} +0 -0
@@ -0,0 +1,115 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import { dirname, join, resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { describe, expect, it } from 'vitest'
5
+
6
+ // SDK control refresh, phase 1 base controls (rounds 1 and 10). One rule per
7
+ // test; a failure lists the offending `file:line`.
8
+
9
+ const here = dirname(fileURLToPath(import.meta.url))
10
+ const componentsDir = resolve(here, '../../styles/components')
11
+
12
+ /** Lines of a component sheet with block comments blanked (line numbers kept). */
13
+ function lines(file: string): string[] {
14
+ const text = readFileSync(join(componentsDir, file), 'utf-8')
15
+ return text.replace(/\/\*[\s\S]*?\*\//g, (c) => c.replace(/[^\n]/g, ' ')).split('\n')
16
+ }
17
+
18
+ function offenders(files: string[], test: (line: string) => boolean): string[] {
19
+ return files.flatMap((file) =>
20
+ lines(file).flatMap((line, i) => (test(line) ? [`${file}:${i + 1}: ${line.trim()}`] : [])),
21
+ )
22
+ }
23
+
24
+ const css = (file: string) => lines(file).join('\n')
25
+
26
+ describe('SDK control refresh base-control rules', () => {
27
+ it('should find no transparent-border focus when scanning select.css (1a)', () => {
28
+ expect(offenders(['select.css'], (l) => /border-color:\s*transparent/.test(l))).toEqual([])
29
+ })
30
+
31
+ it('should find no soft or plain focus ring when scanning pressable controls (1a)', () => {
32
+ const pressables = ['checkbox.css', 'radio-group.css', 'toggle.css', 'icon-button.css', 'multi-select.css']
33
+ expect(offenders(pressables, (l) => /var\(--focus-ring(-soft)?\)/.test(l))).toEqual([])
34
+ })
35
+
36
+ it.each(['input.css', 'select.css', 'textarea.css'])(
37
+ 'should use the shared field hover border when scanning %s (1e)',
38
+ (file) => {
39
+ expect(css(file)).toContain('border-color: var(--_field-border-hover)')
40
+ },
41
+ )
42
+
43
+ it('should disable select without opacity when scanning select.css (1e)', () => {
44
+ expect(css('select.css')).not.toContain('--mint-disabled-opacity')
45
+ })
46
+
47
+ it.each(['checkbox.css', 'radio-group.css'])(
48
+ 'should draw the unchecked control with the strong border when scanning %s (1b)',
49
+ (file) => {
50
+ expect(css(file)).toContain('border: 1.5px solid var(--_control-border-strong)')
51
+ },
52
+ )
53
+
54
+ it('should paint the off track with the strong border color when scanning toggle.css (1b)', () => {
55
+ expect(css('toggle.css')).toMatch(/\.mint-toggle__track--off \{\s*background-color: var\(--_control-border-strong\);/)
56
+ })
57
+
58
+ it('should move the toggle knob with transform only when scanning toggle.css (1b)', () => {
59
+ expect(offenders(['toggle.css'], (l) => /__knob--on-|transition:\s*left/.test(l))).toEqual([])
60
+ })
61
+
62
+ it('should find no radio input-wrapper size modifiers when scanning radio-group.css (1b)', () => {
63
+ expect(offenders(['radio-group.css'], (l) => /__input-wrapper--|margin-left:\s*-/.test(l))).toEqual([])
64
+ })
65
+
66
+ it('should find no translateY lift when scanning icon-button.css (1d)', () => {
67
+ expect(offenders(['icon-button.css'], (l) => /translateY/.test(l))).toEqual([])
68
+ })
69
+
70
+ it('should ring the slider thumb when the native input has keyboard focus (1f)', () => {
71
+ expect(css('slider.css')).toMatch(
72
+ /\.mint-slider__input:focus-visible ~ \.mint-slider__thumb \{[^}]*box-shadow: var\(--focus-ring-offset\);/,
73
+ )
74
+ })
75
+
76
+ it('should find no semantic title color when scanning alert-box.css (1h)', () => {
77
+ expect(offenders(['alert-box.css'], (l) => /\.mint-alert--\w+ \.mint-alert__title/.test(l))).toEqual([])
78
+ })
79
+
80
+ it('should find no pill radius on the chip when scanning multi-select.css (1i)', () => {
81
+ expect(offenders(['multi-select.css'], (l) => /9999px|999px/.test(l))).toEqual([])
82
+ })
83
+
84
+ it('should find no literal radius or hand-written shadow when scanning modal.css (1i drift)', () => {
85
+ expect(offenders(['modal.css'], (l) => /0\.875rem 0|radius:\s*0\.875rem|rgba\(15, 23, 42, 0\.(4|2|08)\)/.test(l))).toEqual([])
86
+ })
87
+
88
+ it('should find no Fira font literal when scanning drift files (1i drift, 10c)', () => {
89
+ const files = ['modal.css', 'tooltip.css', 'slider.css', 'experiment-code-badge.css']
90
+ expect(offenders(files, (l) => /'Fira/.test(l))).toEqual([])
91
+ })
92
+
93
+ it('should find no literal var() fallback when scanning drift files (1i drift, 10c)', () => {
94
+ const files = ['checkbox.css', 'toggle.css', 'slider.css', 'app-layout.css', 'app-container.css', 'mobile-support-gate.css']
95
+ expect(offenders(files, (l) => /var\(--[\w-]+,\s*[^v\s]/.test(l))).toEqual([])
96
+ })
97
+
98
+ it('should keep the collapsible-card header actions still on hover (10a)', () => {
99
+ expect(offenders(['collapsible-card.css'], (l) => /translateY/.test(l))).toEqual([])
100
+ })
101
+
102
+ it('should keep the resource-card hover shadow at --shadow-sm (10a)', () => {
103
+ expect(css('resource-card.css')).not.toMatch(/\.mint-resource-card:hover \{[^}]*box-shadow/)
104
+ })
105
+
106
+ it('should replace the spinner rotation under reduced motion (10c)', () => {
107
+ expect(css('loading-spinner.css')).toMatch(
108
+ /@media \(prefers-reduced-motion: reduce\) \{\s*\.mint-spinner__svg \{\s*animation: mint-spinner-pulse [^;]*!important;/,
109
+ )
110
+ })
111
+
112
+ it('should size the card segmented control border-box so full-width fits its container (3b)', () => {
113
+ expect(css('segmented-control.css')).toMatch(/\.mint-segmented-control--card \{[^}]*box-sizing: border-box;/)
114
+ })
115
+ })
@@ -0,0 +1,218 @@
1
+ import { readdirSync, readFileSync, statSync } from 'node:fs'
2
+ import { dirname, join, relative, resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { describe, expect, it } from 'vitest'
5
+
6
+ // SDK control refresh (decisions/2026-09-25-sdk-control-refresh) style rules.
7
+ // Each failure message lists every offending `file:line`, so it doubles as the
8
+ // migration work-list.
9
+
10
+ const here = dirname(fileURLToPath(import.meta.url))
11
+ const pkgRoot = resolve(here, '../../..')
12
+ const srcRoot = join(pkgRoot, 'src')
13
+ const stylesDir = join(srcRoot, 'styles')
14
+ const componentsDir = join(stylesDir, 'components')
15
+
16
+ const IGNORED_DIRS = new Set(['__tests__', 'generated-ui', 'node_modules'])
17
+
18
+ function walk(dir: string, exts: string[], out: string[] = []): string[] {
19
+ for (const entry of readdirSync(dir)) {
20
+ const full = join(dir, entry)
21
+ if (statSync(full).isDirectory()) {
22
+ if (!IGNORED_DIRS.has(entry)) walk(full, exts, out)
23
+ } else if (exts.some((ext) => entry.endsWith(ext))) {
24
+ out.push(full)
25
+ }
26
+ }
27
+ return out
28
+ }
29
+
30
+ /** Block comments blanked out, newlines kept so line numbers stay true. */
31
+ function stripComments(text: string): string {
32
+ return text.replace(/\/\*[\s\S]*?\*\//g, (c) => c.replace(/[^\n]/g, ' '))
33
+ }
34
+
35
+ function offenders(files: string[], test: (line: string) => boolean): string[] {
36
+ const hits: string[] = []
37
+ for (const file of files) {
38
+ const lines = stripComments(readFileSync(file, 'utf-8')).split('\n')
39
+ lines.forEach((line, i) => {
40
+ if (test(line)) hits.push(`${relative(pkgRoot, file)}:${i + 1}: ${line.trim()}`)
41
+ })
42
+ }
43
+ return hits
44
+ }
45
+
46
+ function expectNone(hits: string[]): void {
47
+ expect(hits, `${hits.length} offenders\n${hits.join('\n')}`).toEqual([])
48
+ }
49
+
50
+ const componentCss = walk(componentsDir, ['.css'])
51
+ const allStyleCss = walk(stylesDir, ['.css'])
52
+ const allSrcCssAndVue = walk(srcRoot, ['.css', '.vue'])
53
+ const component = (name: string) => join(componentsDir, name)
54
+
55
+ // 8d: UI text >= 11px (0.6875rem). In-graphic well labels are exempt.
56
+ const MIN_FONT_PX = 11
57
+ const FONT_SIZE_WHITELIST = new Set(['well-plate.css'])
58
+
59
+ function hasTooSmallFont(line: string): boolean {
60
+ // Several declarations can share a line (`font: inherit; font-size: …`).
61
+ for (const decl of line.matchAll(/\bfont(?:-size)?\s*:\s*([^;]*)/g)) {
62
+ // The first length in `font-size:` or the `font:` shorthand is the size.
63
+ const size = decl[1].match(/(\d*\.?\d+)(px|rem)\b/)
64
+ if (!size) continue
65
+ const px = size[2] === 'rem' ? Number(size[1]) * 16 : Number(size[1])
66
+ if (px < MIN_FONT_PX) return true
67
+ }
68
+ return false
69
+ }
70
+
71
+ describe('SDK control refresh style rules', () => {
72
+ it('should find no uppercase text-transform when scanning styles (2a)', () => {
73
+ expectNone(offenders(allStyleCss, (l) => /text-transform\s*:\s*uppercase/i.test(l)))
74
+ })
75
+
76
+ it('should find no font size below 11px when scanning component styles (8d)', () => {
77
+ const files = componentCss.filter((f) => !FONT_SIZE_WHITELIST.has(relative(componentsDir, f)))
78
+ expectNone(offenders(files, hasTooSmallFont))
79
+ })
80
+
81
+ it('should find no var(--token, #hex) fallback when scanning styles (4f)', () => {
82
+ expectNone(offenders(allStyleCss, (l) => /var\(--[\w-]+,\s*#/.test(l)))
83
+ })
84
+
85
+ it('should find no legacy --mint-border/bg-/text- reference when scanning styles (4f)', () => {
86
+ // Usages only: variables.css still declares the aliases, and
87
+ // --mint-border-focus is a real token, not part of the legacy chain.
88
+ expectNone(offenders(allStyleCss, (l) => /var\(--mint-(?:border(?![\w-])|bg-|text-)/.test(l)))
89
+ })
90
+
91
+ it('should find no pre-rebrand blue literal when scanning source CSS and Vue files (6d)', () => {
92
+ // The --mint-info-* token declarations are the genuine info blue (the
93
+ // replacement target for info intent), not a legacy use.
94
+ expectNone(
95
+ offenders(
96
+ allSrcCssAndVue,
97
+ (l) => /rgba\(\s*59\s*,\s*130\s*,\s*246/.test(l) && !/^\s*--mint-info-[\w-]+\s*:/.test(l),
98
+ ),
99
+ )
100
+ })
101
+
102
+ it('should find no linear-gradient when scanning flat-surface components (1d, 2f, 2g, 3e)', () => {
103
+ const files = ['icon-button.css', 'empty-state.css', 'jobs-status-tray.css', 'file-picker.css', 'skeleton.css'].map(component)
104
+ expectNone(offenders(files, (l) => /linear-gradient/.test(l)))
105
+ })
106
+
107
+ it('should find no hex color literal when scanning token-only graphics (1g, 2b, 3b, 7a)', () => {
108
+ const files = ['well-plate.css', 'tooltip.css', 'well-edit-popup.css', 'plate-editor.css'].map(component)
109
+ expectNone(offenders(files, (l) => /#[0-9a-fA-F]{3,8}\b/.test(l)))
110
+ })
111
+
112
+ it('should ring the focused editor root when scanning plate-editor.css (7a)', () => {
113
+ const css = stripComments(readFileSync(component('plate-editor.css'), 'utf-8'))
114
+ expect(/\.mint-plate-editor:focus-visible\s*\{[^}]*box-shadow:\s*var\(--focus-ring\)/.test(css)).toBe(true)
115
+ })
116
+
117
+ it('should fill progress with the primary color only when scanning progress-bar.css (6b)', () => {
118
+ // --mint-info is reserved for the "running" status dot.
119
+ expectNone(offenders([component('progress-bar.css')], (l) => /--mint-info/.test(l)))
120
+ })
121
+
122
+ it('should keep sequence progress text off --mint-info when scanning sequence-progress-bar.css (6b)', () => {
123
+ expectNone(offenders([component('sequence-progress-bar.css')], (l) => /--mint-info/.test(l)))
124
+ })
125
+
126
+ it('should fill primary and info progress with --color-primary when scanning progress-bar.css (6b)', () => {
127
+ // The rail bar, for primary and info.
128
+ const fills = stripComments(readFileSync(component('progress-bar.css'), 'utf-8'))
129
+ .split('\n')
130
+ .filter((l) => /\.mint-progress__[\w.-]*--(primary|info)\s*\{/.test(l))
131
+ .map((l) => /background-color:\s*([^;]+);/.exec(l)?.[1])
132
+ expect(fills).toEqual(Array(2).fill('var(--color-primary)'))
133
+ })
134
+
135
+ it('should compose SDK fields instead of private field styles when scanning protocol-step-editor.css and dose-calculator.css (6c)', () => {
136
+ const files = [component('protocol-step-editor.css'), component('dose-calculator.css')]
137
+ expectNone(offenders(files, (l) => /__(input|select|textarea|unit-suffix|template-|mode-badge|btn|apply-btn)/.test(l)))
138
+ })
139
+
140
+ it('should wrap FormField rows so a row error sits on its own line (6c)', () => {
141
+ expect(readFileSync(component('form-field.css'), 'utf-8')).toMatch(/\.mint-form-field--row\s*\{[^}]*flex-wrap:\s*wrap;/)
142
+ })
143
+
144
+ it('should set FormField row labels in 13px text-secondary-strong (3b, 6c)', () => {
145
+ expect(readFileSync(component('form-field.css'), 'utf-8')).toMatch(/\.mint-form-field--row \.mint-form-field__label\s*\{[^}]*font-size:\s*0\.8125rem;[^}]*color:\s*var\(--text-secondary-strong\);/)
146
+ })
147
+
148
+ it('should draw no checkbox glyph as a data URI when scanning sample-selector.css (7c)', () => {
149
+ expectNone(offenders([component('sample-selector.css')], (l) => /data:image/.test(l)))
150
+ })
151
+
152
+ it('should generate no label text in CSS when scanning scientific inputs (4b)', () => {
153
+ // "MW" and "≈" live in templates so they can be translated, selected and read aloud.
154
+ const files = ['formula-input.css', 'concentration-input.css', 'unit-input.css'].map(component)
155
+ expectNone(offenders(files, (l) => /(^|[^-\w])content\s*:/.test(l)))
156
+ })
157
+
158
+ it('should find no italic conversion hint when scanning scientific inputs (4b)', () => {
159
+ const files = ['concentration-input.css', 'unit-input.css'].map(component)
160
+ expectNone(offenders(files, (l) => /font-style\s*:\s*italic/.test(l)))
161
+ })
162
+
163
+ it('should set the unit at the number size when scanning scientific-number.css (4b)', () => {
164
+ const css = stripComments(readFileSync(component('scientific-number.css'), 'utf-8'))
165
+ const rule = /\.mint-sci-number__unit\s*\{([^}]*)\}/.exec(css)?.[1] ?? ''
166
+ expect(rule).not.toMatch(/font-size/)
167
+ })
168
+
169
+ it('should give numeric DataFrame cells tabular figures when scanning dataframe.css (2a)', () => {
170
+ const css = stripComments(readFileSync(component('dataframe.css'), 'utf-8'))
171
+ const rule = /\.mint-dataframe__td--number\s*\{([^}]*)\}/.exec(css)?.[1] ?? ''
172
+ expect(rule).toMatch(/font-variant-numeric:\s*tabular-nums/)
173
+ })
174
+
175
+ it('should center the select-all checkbox over the row checkboxes when .mint-dataframe__th forces left (2a)', () => {
176
+ const css = stripComments(readFileSync(component('dataframe.css'), 'utf-8'))
177
+ const rule = /\.mint-dataframe__th--checkbox\s*\{([^}]*)\}/.exec(css)?.[1] ?? ''
178
+ expect(rule).toMatch(/text-align:\s*center\s*!important/)
179
+ })
180
+
181
+ it('should wrap a row FormField so its hint drops below the control when scanning form-field.css (3b)', () => {
182
+ const css = stripComments(readFileSync(component('form-field.css'), 'utf-8'))
183
+ const rule = /\.mint-form-field--row\s*\{([^}]*)\}/.exec(css)?.[1] ?? ''
184
+ expect(rule).toMatch(/flex-wrap:\s*wrap/)
185
+ })
186
+
187
+ it('should pad resource picker rows to the roomier two-column layout when scanning resource-picker-list.css', () => {
188
+ const css = stripComments(readFileSync(component('resource-picker-list.css'), 'utf-8'))
189
+ const rule = /\.mint-resource-picker__row\s*\{([^}]*)\}/.exec(css)?.[1] ?? ''
190
+ expect(rule).toMatch(/padding:\s*10px 12px/)
191
+ })
192
+
193
+ // Group bars and the list frame were inset by the modal body padding; the list now runs edge to edge.
194
+ it('should drop the modal body padding around the resource picker when scanning resource-picker-list.css', () => {
195
+ const css = stripComments(readFileSync(component('resource-picker-list.css'), 'utf-8'))
196
+ const rule = /\.mint-modal__body:has\(> \.mint-resource-picker\)\s*\{([^}]*)\}/.exec(css)?.[1] ?? ''
197
+ expect(rule).toMatch(/padding:\s*0/)
198
+ })
199
+
200
+ it('should pad resource picker group bars to the modal gutter when scanning resource-picker-list.css', () => {
201
+ const css = stripComments(readFileSync(component('resource-picker-list.css'), 'utf-8'))
202
+ const rule = /\.mint-resource-picker__group\s*\{([^}]*)\}/.exec(css)?.[1] ?? ''
203
+ expect(rule).toMatch(/padding:\s*0 1\.25rem/)
204
+ })
205
+
206
+ // The list sat in a bordered card inside the modal card.
207
+ it('should draw no frame around the resource picker list when scanning resource-picker-list.css', () => {
208
+ const css = stripComments(readFileSync(component('resource-picker-list.css'), 'utf-8'))
209
+ const rule = /\.mint-resource-picker__frame\s*\{([^}]*)\}/.exec(css)?.[1] ?? ''
210
+ expect(rule).not.toMatch(/(^|;)\s*border:/)
211
+ })
212
+
213
+ it('should paint the clear-selection link with primary ink when scanning experiment-selector-modal.css (8b)', () => {
214
+ const css = stripComments(readFileSync(component('experiment-selector-modal.css'), 'utf-8'))
215
+ const rule = /\.mint-experiment-selector__clear-btn\s*\{([^}]*)\}/.exec(css)?.[1] ?? ''
216
+ expect(rule).toMatch(/color:\s*var\(--_ink-primary\)/)
217
+ })
218
+ })
@@ -14,11 +14,7 @@ const variablesCss = readFileSync(join(stylesDir, 'variables.css'), 'utf-8')
14
14
  * component-local knobs declared in the same stylesheet that consumes them.
15
15
  * Anything else must be a canonical token from variables.css.
16
16
  */
17
- const RUNTIME_PROPERTY_ALLOWLIST = new Set<string>([
18
- // Names assembled in JS (`--grp-${i}`) — the literal prefix is what the
19
- // scanner sees in a template string.
20
- '--grp-',
21
- ])
17
+ const RUNTIME_PROPERTY_ALLOWLIST = new Set<string>([])
22
18
 
23
19
  const SOURCE_EXTENSIONS = ['.vue', '.css', '.ts']
24
20
  const IGNORED_DIRS = new Set(['__tests__', 'generated-ui', 'node_modules'])
@@ -95,6 +91,12 @@ describe('CSS custom properties', () => {
95
91
  expect(report).toEqual([])
96
92
  })
97
93
 
94
+ // 9a: PlotlyChart reads it through getComputedStyle('--font-sans'), which the
95
+ // scan above counts as a declaration, so it slipped through as undefined.
96
+ it('should declare --font-sans as Fira Sans when charts read the sans font token (9a)', () => {
97
+ expect(variablesCss).toMatch(/--font-sans:\s*'Fira Sans'/)
98
+ })
99
+
98
100
  it('does not use the platform-only --color-bg-*/--color-text-*/--color-border aliases', () => {
99
101
  const platformOnly = /^--color-(bg|text)-|^--color-border$/
100
102
  const offenders = [
@@ -0,0 +1,47 @@
1
+ import { readdirSync, readFileSync } from 'node:fs'
2
+ import { dirname, join, resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { describe, expect, it } from 'vitest'
5
+
6
+ // SDK control refresh phase 1, fix round 1: dark-mode ink, hairlines and sizing.
7
+ const stylesDir = resolve(dirname(fileURLToPath(import.meta.url)), '../../styles')
8
+ const componentsDir = join(stylesDir, 'components')
9
+ const css = (name: string) => readFileSync(join(componentsDir, name), 'utf-8')
10
+
11
+ describe('dark-mode ink and hairline rules', () => {
12
+ it('should find no light-only ink text color when scanning component styles', () => {
13
+ const offenders = readdirSync(componentsDir)
14
+ .filter(f => f.endsWith('.css'))
15
+ .flatMap(f => css(f).split('\n').map((l, i) => ({ l, at: `${f}:${i + 1}` })))
16
+ .filter(({ l }) => /(^|[\s;{])color:\s*var\(--(color-primary-hover|mint-error-hover)\)/.test(l))
17
+ .map(({ at }) => at)
18
+ expect(offenders).toEqual([])
19
+ })
20
+
21
+ it('should lift the ink aliases toward --text-primary when the theme is dark', () => {
22
+ const dark = readFileSync(join(stylesDir, 'variables.css'), 'utf-8').match(/html\.dark \{[^}]*\}/)?.[0] ?? ''
23
+ expect(dark).toMatch(/--_ink-primary: color-mix\(in srgb, var\(--color-primary\) 50%, var\(--text-primary\)\);[\s\S]*--_ink-error: color-mix\(in srgb, var\(--mint-error\) 50%, var\(--text-primary\)\);/)
24
+ })
25
+
26
+ it.each([
27
+ ['batch-progress-list.css', 'mint-batch-progress'],
28
+ ['dataframe.css', 'mint-dataframe'],
29
+ ['fit-panel.css', 'mint-fit-panel'],
30
+ ['jobs-status-tray.css', 'mint-jobs-tray'],
31
+ ['molecule-input.css', 'mint-molecule-input'],
32
+ ['reagent-list.css', 'mint-reagent-list'],
33
+ ['sample-hierarchy-tree.css', 'mint-sample-tree'],
34
+ ['sequence-input.css', 'mint-sequence-input'],
35
+ ['step-wizard.css', 'mint-wizard'],
36
+ ])('should draw %s hairlines with --border-color when the theme is dark', (file, root) => {
37
+ expect(css(file)).toContain(`:where(html.dark) .${root} {\n --border-light: var(--border-color);\n}`)
38
+ })
39
+
40
+ it('should stripe DataFrame rows with a tint that differs from the --bg-card surface', () => {
41
+ expect(css('dataframe.css')).not.toMatch(/\.mint-dataframe__row--striped[^{]*\{[^}]*--bg-secondary/)
42
+ })
43
+
44
+ it('should size timeline icons border-box so the dashed skipped ring keeps the nominal size', () => {
45
+ expect(css('experiment-timeline.css')).toMatch(/\.mint-timeline__icon \{[^}]*box-sizing: border-box;/)
46
+ })
47
+ })
@@ -0,0 +1,75 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import { dirname, join, resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { describe, expect, it } from 'vitest'
5
+
6
+ // SDK control refresh phase 1 (2c, 5a, 5d): CSS-only cards, locked by value.
7
+ const componentsDir = resolve(dirname(fileURLToPath(import.meta.url)), '../../styles/components')
8
+ const css = (name: string) => readFileSync(join(componentsDir, name), 'utf-8')
9
+
10
+ describe('menus and app shell styles', () => {
11
+ it('should fill completed StepWizard connectors with the primary hue (2c)', () => {
12
+ expect(css('step-wizard.css')).toMatch(/\.mint-wizard__step-connector--completed\s*\{[^}]*background-color:\s*var\(--color-primary\);/)
13
+ })
14
+
15
+ it('should draw the StepWizard connector 1px tall (2c)', () => {
16
+ expect(css('step-wizard.css')).toMatch(/\.mint-wizard__step-connector\s*\{[^}]*height:\s*1px;/)
17
+ })
18
+
19
+ // Phase 3: the nav renders BaseButton (Finish = primary, see StepWizard.test.ts), so no private button rules remain.
20
+ it('should leave StepWizard nav buttons to BaseButton (2c)', () => {
21
+ expect(css('step-wizard.css')).not.toMatch(/\.mint-wizard__nav-btn/)
22
+ })
23
+
24
+ it('should pad the top bar to the 1.2 height (62px)', () => {
25
+ expect(css('app-top-bar.css')).toMatch(/\.mint-topbar\s*\{[^}]*padding:\s*0\.75rem 1rem;/)
26
+ })
27
+
28
+ // 28px items + 3px track padding + 1px border on each side = the 36px top-bar control height.
29
+ it('should size pill nav items so the track matches the 36px top-bar controls', () => {
30
+ expect(css('app-pill-nav.css')).toMatch(/\.mint-pill-nav__item\s*\{[^}]*height:\s*1\.75rem;/)
31
+ })
32
+
33
+ it('should size the page selector trigger to the 36px identity tile', () => {
34
+ expect(css('app-page-selector.css')).toMatch(/\.mint-page-selector__trigger\s*\{[^}]*height:\s*2\.25rem;/)
35
+ })
36
+
37
+ // Shrinking the tile beside the identity also shrank structured icons inside their solid chip, drawing a ring.
38
+ it('should keep the plugin tile beside the static plugin identity (5a)', () => {
39
+ expect(css('app-top-bar.css')).not.toMatch(/:has\(\+ \.mint-topbar__plugin-identity\)/)
40
+ })
41
+
42
+ // A slotted 36px logo shrank to 32px wide but kept its height, drawing a 32x36 tile.
43
+ it('should fit slotted identity content inside the identity tile (5a)', () => {
44
+ expect(css('app-top-bar.css')).toMatch(/\.mint-topbar__identity > \*\s*\{[^}]*max-width:\s*100%;[^}]*max-height:\s*100%;/)
45
+ })
46
+
47
+ // 15px x 1.15 + 12px x 1.2 = 31.7px, so the title group fits the 32px control row.
48
+ it('should fit the top-bar title and subtitle inside the control row (5a)', () => {
49
+ expect(css('app-top-bar.css')).toMatch(/\.mint-topbar-title\s*\{[^}]*line-height:\s*1\.15;/)
50
+ })
51
+
52
+ it('should size the top-bar experiment trigger to the 32px control height (5a)', () => {
53
+ expect(css('experiment-popover.css')).toMatch(/\.mint-experiment-popover__trigger\s*\{[^}]*height:\s*var\(--form-height-sm\);/)
54
+ })
55
+
56
+ it('should size the top-bar experiment save trigger to the 32px control height (5a)', () => {
57
+ expect(css('experiment-popover.css')).toMatch(/\.mint-experiment-popover__save-trigger\s*\{[^}]*height:\s*var\(--form-height-sm\);/)
58
+ })
59
+
60
+ it('should give settings number rows a 120px control (5d)', () => {
61
+ expect(css('settings-modal.css')).toMatch(/> \.mint-number-input\s*\{\s*width:\s*7\.5rem;/)
62
+ })
63
+
64
+ it('should give settings select rows a 220px control (5d)', () => {
65
+ expect(css('settings-modal.css')).toMatch(/> \.mint-select\s*\{\s*width:\s*13\.75rem;/)
66
+ })
67
+
68
+ it('should keep full-width menu items inside the popover when rendered as <a> or <li> (2d)', () => {
69
+ expect(css('popover.css')).toMatch(/\.mint-menu-item\s*\{[^}]*box-sizing:\s*border-box;/)
70
+ })
71
+
72
+ it('should size the popover border-box so trigger-width panels do not overhang (2d)', () => {
73
+ expect(css('popover.css')).toMatch(/\.mint-popover\s*\{[^}]*box-sizing:\s*border-box;/)
74
+ })
75
+ })
@@ -66,6 +66,7 @@ import {
66
66
  toInstrumentRunRows,
67
67
  toInstrumentRunScheduleEvents,
68
68
  toInstrumentRunSteps,
69
+ racksFromPlateState,
69
70
  toPlateMapEditorState,
70
71
  toProtocolDataFrame,
71
72
  toProtocolSteps,
@@ -251,6 +252,12 @@ describe('bio data templates', () => {
251
252
  expect(listBioTemplatePresets()).toEqual(bioTemplatePresetsContract)
252
253
  })
253
254
 
255
+ it('should not recommend AutoGroupModal when it is scheduled for removal', () => {
256
+ const components = listBioTemplateCatalog().flatMap(entry => entry.components)
257
+
258
+ expect(components).not.toContain('AutoGroupModal')
259
+ })
260
+
254
261
  it('prefers generic dataframe adapters in catalog entries', () => {
255
262
  const dataframeTemplates = listBioTemplateCatalog().filter(entry =>
256
263
  entry.components.includes('DataFrame')
@@ -311,12 +318,12 @@ describe('bio data templates', () => {
311
318
  const westernBindings = getBioTemplateComponentBindings('western-blot-assay')
312
319
  const wellplateImports = toBioTemplateComponentImports('wellplate-screen')
313
320
 
314
- expect(bindings['plate-map'].map(binding => binding.component)).toEqual(['PlateMapEditor', 'WellPlate'])
321
+ expect(bindings['plate-map'].map(binding => binding.component)).toEqual(['PlateEditor', 'WellPlate'])
315
322
  expect(wellplateBindings.map(binding => binding.component)).toContain('DoseCalculator')
316
323
  expect(wellplateBindings.map(binding => binding.component)).toContain('WellPlate')
317
324
  expect(qpcrBindings.map(binding => binding.component)).toContain('WellPlate')
318
325
  expect(qpcrBindings.map(binding => binding.component)).toContain('DataFrame')
319
- expect(elisaBindings.map(binding => binding.component)).toContain('PlateMapEditor')
326
+ expect(elisaBindings.map(binding => binding.component)).toContain('PlateEditor')
320
327
  expect(elisaBindings.map(binding => binding.component)).toContain('DataFrame')
321
328
  expect(lcmsBindings.map(binding => binding.component)).toContain('ScheduleCalendar')
322
329
  expect(lcmsBindings.map(binding => binding.component)).toContain('ExperimentTimeline')
@@ -335,8 +342,8 @@ describe('bio data templates', () => {
335
342
  expect(wellplateImports).toEqual([
336
343
  {
337
344
  importPath: '@morscherlab/mint-sdk',
338
- components: ['PlateMapEditor', 'WellPlate', 'DataFrame', 'SampleSelector', 'DoseCalculator'],
339
- statement: "import { PlateMapEditor, WellPlate, DataFrame, SampleSelector, DoseCalculator } from '@morscherlab/mint-sdk'",
345
+ components: ['PlateEditor', 'WellPlate', 'DataFrame', 'SampleSelector', 'DoseCalculator'],
346
+ statement: "import { PlateEditor, WellPlate, DataFrame, SampleSelector, DoseCalculator } from '@morscherlab/mint-sdk'",
340
347
  },
341
348
  ])
342
349
  })
@@ -354,6 +361,12 @@ describe('bio data templates', () => {
354
361
  expect(state.samples[1].id).toBe('drug-a')
355
362
  })
356
363
 
364
+ it('should convert plate-map state into PlateEditor racks', () => {
365
+ const state = toPlateMapEditorState(createPlateMapTemplate({ samples: ['DMSO'] }))
366
+
367
+ expect(racksFromPlateState(state)[0]).toMatchObject({ id: 'plate-1', format: 96, slot: 'R' })
368
+ })
369
+
357
370
  it('loads the shared plate-map fixture', () => {
358
371
  const state = toPlateMapEditorState(plateMapFixture as PlateMapTemplate)
359
372
  const wells = toWellPlateWells(plateMapFixture as PlateMapTemplate)
@@ -390,7 +403,7 @@ describe('bio data templates', () => {
390
403
  })
391
404
 
392
405
  expect(Object.keys(propsById)).toEqual([
393
- 'plate-map:PlateMapEditor',
406
+ 'plate-map:PlateEditor',
394
407
  'plate-map:WellPlate',
395
408
  'sample-sheet:DataFrame',
396
409
  'sample-sheet:SampleSelector',
@@ -446,13 +459,13 @@ describe('bio data templates', () => {
446
459
  propsVariable: 'bindings',
447
460
  })
448
461
 
449
- expect(snippets.map(snippet => snippet.component)).toEqual(['PlateMapEditor', 'WellPlate'])
462
+ expect(snippets.map(snippet => snippet.component)).toEqual(['PlateEditor', 'WellPlate'])
450
463
  expect(snippets.map(snippet => snippet.propsName)).toEqual([
451
- 'plateMapPlateMapEditorProps',
464
+ 'plateMapPlateEditorProps',
452
465
  'plateMapWellPlateProps',
453
466
  ])
454
467
  expect(snippets[0].propsExpression).toBe('bindings[0].propsObject')
455
- expect(snippets[0].template).toBe('<PlateMapEditor v-bind="bindings[0].propsObject" />')
468
+ expect(snippets[0].template).toBe('<PlateEditor v-bind="bindings[0].propsObject" />')
456
469
  expect(snippets[1].template).toBe('<WellPlate v-bind="bindings[1].propsObject" />')
457
470
  })
458
471
 
@@ -463,20 +476,20 @@ describe('bio data templates', () => {
463
476
  })
464
477
 
465
478
  expect(usage.imports[0].statement).toBe(
466
- "import { PlateMapEditor, WellPlate } from '@morscherlab/mint-sdk'"
479
+ "import { PlateEditor, WellPlate } from '@morscherlab/mint-sdk'"
467
480
  )
468
481
  expect(usage.componentProps).toHaveLength(2)
469
482
  expect(usage.propsDeclarations).toEqual([
470
- 'const plateMapPlateMapEditorProps = bindings[0].propsObject',
483
+ 'const plateMapPlateEditorProps = bindings[0].propsObject',
471
484
  'const plateMapWellPlateProps = bindings[1].propsObject',
472
485
  ])
473
486
  expect(usage.scriptSetup).toBe([
474
487
  'const bindings = toBioTemplateComponentProps(plateMap)',
475
- 'const plateMapPlateMapEditorProps = bindings[0].propsObject',
488
+ 'const plateMapPlateEditorProps = bindings[0].propsObject',
476
489
  'const plateMapWellPlateProps = bindings[1].propsObject',
477
490
  ].join('\n'))
478
491
  expect(usage.template).toBe([
479
- '<PlateMapEditor v-bind="plateMapPlateMapEditorProps" />',
492
+ '<PlateEditor v-bind="plateMapPlateEditorProps" />',
480
493
  '<WellPlate v-bind="plateMapWellPlateProps" />',
481
494
  ].join('\n'))
482
495
  })
@@ -487,10 +500,10 @@ describe('bio data templates', () => {
487
500
  expect(usage.scriptSetup).toContain(
488
501
  'const props = defineProps<{ templateCollection: BioTemplateEnvelope<unknown> | TemplateCollectionEnvelope }>()'
489
502
  )
490
- expect(usage.sfc).toContain("import { PlateMapEditor, WellPlate } from '@morscherlab/mint-sdk'")
503
+ expect(usage.sfc).toContain("import { PlateEditor, WellPlate } from '@morscherlab/mint-sdk'")
491
504
  expect(usage.sfc).toContain("import { toBioTemplateComponentProps } from '@morscherlab/mint-sdk/templates'")
492
505
  expect(usage.sfc).toContain('defineProps<{ templateCollection: BioTemplateEnvelope<unknown> | TemplateCollectionEnvelope }>()')
493
- expect(usage.sfc).toContain('<PlateMapEditor v-bind="plateMapPlateMapEditorProps" />')
506
+ expect(usage.sfc).toContain('<PlateEditor v-bind="plateMapPlateEditorProps" />')
494
507
  expect(usage.sfc).toContain('<WellPlate v-bind="plateMapWellPlateProps" />')
495
508
  expect(usage.sfc).toMatch(/^<script setup lang="ts">[\s\S]*<\/template>$/)
496
509
  })
@@ -583,7 +596,7 @@ describe('bio data templates', () => {
583
596
  expect(wellplate.metadata?.preset).toBe('wellplate-screen')
584
597
  expect(toPlateMapEditorState(wellplateTemplates['plate-map'] as PlateMapTemplate).samples[1].id).toBe('treatment')
585
598
  expect(toDoseConditions(wellplateTemplates['dose-response'] as DoseResponseTemplate)[0].label).toBe('Drug A')
586
- expect(wellplateComponentProps.map(binding => binding.component)).toContain('PlateMapEditor')
599
+ expect(wellplateComponentProps.map(binding => binding.component)).toContain('PlateEditor')
587
600
  expect(wellplateComponentProps.map(binding => binding.component)).toContain('DoseCalculator')
588
601
  expect(Object.keys(qpcrTemplates)).toEqual(['sample-sheet', 'qpcr-plate'])
589
602
  expect(toQpcrRows(qpcrTemplates['qpcr-plate'] as QpcrPlateTemplate)[0].sampleId).toBe('S001')
@@ -1183,3 +1196,40 @@ describe('bio data templates', () => {
1183
1196
  expect(template.data.measurements[0].featureId).toBe('lactate')
1184
1197
  })
1185
1198
  })
1199
+
1200
+ describe('plate-map PlateEditor binding (7a)', () => {
1201
+ const editorProps = () =>
1202
+ toBioTemplateComponentProps(plateMapFixture as PlateMapTemplate)
1203
+ .find(binding => binding.component === 'PlateEditor')?.propsObject as Record<string, unknown>
1204
+
1205
+ it('should pass the plates as racks with sequential slots', () => {
1206
+ expect((editorProps().modelValue as Array<{ slot: string }>)[0].slot).toBe('R')
1207
+ })
1208
+
1209
+ it('should move the sample id of a well to its group', () => {
1210
+ const racks = editorProps().modelValue as Array<{ wells: Record<string, { group?: string }> }>
1211
+
1212
+ expect(racks[0].wells.A2.group).toBe('drug-a')
1213
+ })
1214
+
1215
+ it('should make a well with a sample id a sample', () => {
1216
+ const racks = editorProps().modelValue as Array<{ wells: Record<string, { sampleType?: string }> }>
1217
+
1218
+ expect(racks[0].wells.A2.sampleType).toBe('sample')
1219
+ })
1220
+
1221
+ it('should leave the stored plate-map wells unchanged', () => {
1222
+ const template = structuredClone(plateMapFixture) as PlateMapTemplate
1223
+ toBioTemplateComponentProps(template)
1224
+
1225
+ expect(template).toEqual(plateMapFixture)
1226
+ })
1227
+
1228
+ it('should offer the template samples as groups', () => {
1229
+ expect((editorProps().groups as Array<{ id: string }>).map(group => group.id)).toContain('drug-a')
1230
+ })
1231
+
1232
+ it('should pin the format to the plate format', () => {
1233
+ expect(editorProps().formats).toEqual([96])
1234
+ })
1235
+ })