@morscherlab/mint-sdk 1.2.0-beta.7 → 1.2.0-beta.9

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 (307) hide show
  1. package/README.md +30 -0
  2. package/dist/{ExperimentPopover-CfOdh5Rm.js → ExperimentPopover-oL0fg_A0.js} +5 -3
  3. package/dist/ExperimentPopover-oL0fg_A0.js.map +1 -0
  4. package/dist/{ExperimentSelectorModal-DvIagrxY.js → ExperimentSelectorModal-BeEOomw_.js} +4 -4
  5. package/dist/ExperimentSelectorModal-BeEOomw_.js.map +1 -0
  6. package/dist/{SettingsModal-W3TYfnP9.js → SettingsModal-Dphh3RrI.js} +4 -4
  7. package/dist/SettingsModal-Dphh3RrI.js.map +1 -0
  8. package/dist/{EmptyState-NBqf2_8z.js → Skeleton-DxtwJ5gt.js} +110 -92
  9. package/dist/Skeleton-DxtwJ5gt.js.map +1 -0
  10. package/dist/__tests__/components/ExperimentTimeline.test.d.ts +1 -0
  11. package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
  12. package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
  13. package/dist/components/ActionMenu.vue.d.ts +1 -1
  14. package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
  15. package/dist/components/AuditTrail.vue.d.ts +13 -0
  16. package/dist/components/BatchProgressList.vue.d.ts +17 -0
  17. package/dist/components/DataFrame.vue.d.ts +14 -2
  18. package/dist/components/DatePicker.vue.d.ts +1 -1
  19. package/dist/components/DateTimePicker.vue.d.ts +2 -0
  20. package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
  21. package/dist/components/ExperimentPopover.vue.d.ts +1 -0
  22. package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
  23. package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
  24. package/dist/components/ProgressBar.vue.d.ts +1 -1
  25. package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
  26. package/dist/components/ReagentList.vue.d.ts +29 -1
  27. package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
  28. package/dist/components/SampleSelector.drag.d.ts +13 -0
  29. package/dist/components/SampleSelector.tree.d.ts +2 -0
  30. package/dist/components/SampleSelector.vue.d.ts +34 -1
  31. package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
  32. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +1 -0
  33. package/dist/components/TimePicker.vue.d.ts +1 -0
  34. package/dist/components/WellPlate.geometry.d.ts +15 -0
  35. package/dist/components/WellPlate.interaction.d.ts +13 -0
  36. package/dist/components/WellPlate.vue.d.ts +29 -0
  37. package/dist/components/index.js +6 -6
  38. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
  39. package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
  40. package/dist/{components-B80gV0P6.js → components-CgAUzF8F.js} +1930 -1688
  41. package/dist/components-CgAUzF8F.js.map +1 -0
  42. package/dist/composables/controlSchemaTypes.d.ts +34 -0
  43. package/dist/composables/index.d.ts +1 -0
  44. package/dist/composables/index.js +9 -9
  45. package/dist/composables/useDropdownState.d.ts +18 -2
  46. package/dist/composables/useEventStream.d.ts +9 -0
  47. package/dist/composables/useListReorder.d.ts +90 -0
  48. package/dist/composables/useMenuKeyboard.d.ts +2 -2
  49. package/dist/composables/usePluginConfig.d.ts +3 -1
  50. package/dist/composables/useRequestSyncState.d.ts +42 -2
  51. package/dist/composables/useScheduleDrag.d.ts +1 -0
  52. package/dist/{composables-C8mmD5ta.js → composables-B_pia3hO.js} +13 -69
  53. package/dist/composables-B_pia3hO.js.map +1 -0
  54. package/dist/{useApi-CDBq6z23.js → errors-_W0-LbA6.js} +102 -3
  55. package/dist/errors-_W0-LbA6.js.map +1 -0
  56. package/dist/{experiment-Y9Iz7KYi.js → experiment-Cwl9AYxw.js} +3 -8
  57. package/dist/experiment-Cwl9AYxw.js.map +1 -0
  58. package/dist/experiment-utils-DV3DrvE_.js.map +1 -1
  59. package/dist/index.js +14 -14
  60. package/dist/install.js +2 -7
  61. package/dist/install.js.map +1 -1
  62. package/dist/permissions.d.ts +42 -1
  63. package/dist/permissions.js +20 -10
  64. package/dist/permissions.js.map +1 -1
  65. package/dist/stores/index.d.ts +1 -1
  66. package/dist/stores/index.js +3 -3
  67. package/dist/stores/settings.d.ts +31 -1
  68. package/dist/styles.css +9572 -27877
  69. package/dist/templates/index.js +2 -4
  70. package/dist/{templates-CK72aKO1.js → templates-Qq113pyZ.js} +291 -85
  71. package/dist/templates-Qq113pyZ.js.map +1 -0
  72. package/dist/{useControlSchema-_OVhavKq.js → useControlSchema-aMZlb4Sc.js} +197 -1089
  73. package/dist/useControlSchema-aMZlb4Sc.js.map +1 -0
  74. package/dist/{useDropdownState-D5G4UvWd.js → useDropdownState-DitCtrTT.js} +21 -5
  75. package/dist/useDropdownState-DitCtrTT.js.map +1 -0
  76. package/dist/{useExperimentSelector-DSEckf_g.js → useExperimentSelector-I8HC8hUu.js} +3 -3
  77. package/dist/{useExperimentSelector-DSEckf_g.js.map → useExperimentSelector-I8HC8hUu.js.map} +1 -1
  78. package/dist/{useFormBuilder-Bd714C7y.js → useFormBuilder-TCxNnqeb.js} +2 -2
  79. package/dist/{useFormBuilder-Bd714C7y.js.map → useFormBuilder-TCxNnqeb.js.map} +1 -1
  80. package/dist/{useProtocolTemplates-Dq5Pzwyd.js → useProtocolTemplates-BmX_iVBR.js} +185 -157
  81. package/dist/useProtocolTemplates-BmX_iVBR.js.map +1 -0
  82. package/dist/utils/color.d.ts +13 -0
  83. package/dist/utils/errors.d.ts +9 -0
  84. package/package.json +1 -1
  85. package/src/__tests__/components/ActionMenu.test.ts +94 -0
  86. package/src/__tests__/components/DataFrame.test.ts +183 -11
  87. package/src/__tests__/components/DataStates.test.ts +176 -0
  88. package/src/__tests__/components/DatePicker.test.ts +76 -0
  89. package/src/__tests__/components/DateTimePicker.test.ts +36 -0
  90. package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
  91. package/src/__tests__/components/GroupAssigner.test.ts +53 -0
  92. package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
  93. package/src/__tests__/components/RackEditor.test.ts +35 -0
  94. package/src/__tests__/components/ReagentList.test.ts +64 -2
  95. package/src/__tests__/components/RetiredStyles.test.ts +31 -0
  96. package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
  97. package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
  98. package/src/__tests__/components/SegmentedControl.test.ts +88 -0
  99. package/src/__tests__/components/TimePicker.test.ts +61 -0
  100. package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
  101. package/src/__tests__/composables/useDropdownState.test.ts +58 -1
  102. package/src/__tests__/composables/useListReorder.test.ts +145 -0
  103. package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
  104. package/src/__tests__/stores/settings.test.ts +71 -1
  105. package/src/__tests__/styles/cssTokens.test.ts +131 -0
  106. package/src/__tests__/utils/permissions.test.ts +68 -0
  107. package/src/components/ActionMenu.vue +45 -88
  108. package/src/components/AlertBox.vue +0 -4
  109. package/src/components/AppAvatarMenu.vue +2 -14
  110. package/src/components/AppLayout.vue +0 -4
  111. package/src/components/AppPluginSwitcher.story.vue +87 -0
  112. package/src/components/AppPluginSwitcher.vue +2 -5
  113. package/src/components/AppSidebar.vue +0 -4
  114. package/src/components/AppToastContainer.vue +6 -8
  115. package/src/components/AppTopBar.vue +0 -4
  116. package/src/components/ArtifactSaveDialog.vue +0 -4
  117. package/src/components/ArtifactSelectorModal.vue +0 -4
  118. package/src/components/AuditTrail.story.vue +18 -0
  119. package/src/components/AuditTrail.vue +27 -7
  120. package/src/components/AutoGroupModal.vue +0 -4
  121. package/src/components/Avatar.vue +0 -4
  122. package/src/components/BaseButton.vue +0 -4
  123. package/src/components/BaseCheckbox.vue +0 -4
  124. package/src/components/BaseInput.vue +0 -4
  125. package/src/components/BaseModal.vue +0 -4
  126. package/src/components/BasePill.vue +0 -4
  127. package/src/components/BaseRadioGroup.vue +0 -4
  128. package/src/components/BaseSelect.vue +0 -4
  129. package/src/components/BaseSlider.vue +0 -4
  130. package/src/components/BaseTabs.vue +0 -4
  131. package/src/components/BaseTextarea.vue +0 -4
  132. package/src/components/BaseToggle.vue +0 -4
  133. package/src/components/BatchProgressList.story.vue +18 -0
  134. package/src/components/BatchProgressList.vue +32 -4
  135. package/src/components/Breadcrumb.vue +0 -4
  136. package/src/components/Calendar.vue +0 -4
  137. package/src/components/ChartContainer.story.vue +1 -1
  138. package/src/components/ChartContainer.vue +0 -4
  139. package/src/components/ChemicalFormula.vue +0 -4
  140. package/src/components/CollapsibleCard.vue +0 -4
  141. package/src/components/ColorSlider.vue +0 -4
  142. package/src/components/ConcentrationInput.vue +0 -4
  143. package/src/components/ConfirmDialog.vue +0 -4
  144. package/src/components/DataFrame.story.vue +14 -0
  145. package/src/components/DataFrame.vue +97 -23
  146. package/src/components/DatePicker.vue +73 -27
  147. package/src/components/DateTimePicker.vue +45 -17
  148. package/src/components/Divider.vue +0 -4
  149. package/src/components/DoseCalculator.vue +0 -4
  150. package/src/components/DropdownButton.vue +2 -14
  151. package/src/components/EmptyState.vue +0 -4
  152. package/src/components/ExperimentCodeBadge.vue +0 -4
  153. package/src/components/ExperimentDataViewer.story.vue +3 -0
  154. package/src/components/ExperimentDataViewer.vue +33 -13
  155. package/src/components/ExperimentPopover.vue +2 -5
  156. package/src/components/ExperimentSelectorModal.vue +0 -4
  157. package/src/components/ExperimentTimeline.story.vue +18 -0
  158. package/src/components/ExperimentTimeline.vue +81 -75
  159. package/src/components/FileUploader.vue +0 -4
  160. package/src/components/FitPanel.vue +0 -4
  161. package/src/components/FormActions.story.vue +96 -0
  162. package/src/components/FormActions.vue +0 -4
  163. package/src/components/FormBuilder.vue +0 -4
  164. package/src/components/FormField.vue +0 -4
  165. package/src/components/FormulaInput.vue +0 -4
  166. package/src/components/GeneratedPathInput.story.vue +68 -0
  167. package/src/components/GeneratedPlotlyResult.story.vue +96 -0
  168. package/src/components/GeneratedPlotlyResult.vue +3 -3
  169. package/src/components/GeneratedPluginView.story.vue +145 -0
  170. package/src/components/GeneratedPluginView.vue +10 -10
  171. package/src/components/GeneratedResultRenderer.story.vue +117 -0
  172. package/src/components/GeneratedResultRenderer.vue +4 -4
  173. package/src/components/GroupAssigner.vue +67 -5
  174. package/src/components/IconButton.vue +0 -4
  175. package/src/components/InstrumentAlertLog.vue +0 -4
  176. package/src/components/InstrumentStateBadge.vue +0 -4
  177. package/src/components/InstrumentStatusCard.vue +0 -4
  178. package/src/components/JobsStatusTray.vue +0 -4
  179. package/src/components/LcmsSequenceTable.vue +81 -50
  180. package/src/components/LoadingSpinner.vue +0 -4
  181. package/src/components/MobileSupportGate.vue +0 -4
  182. package/src/components/MoleculeInput.vue +0 -4
  183. package/src/components/MultiSelect.vue +0 -4
  184. package/src/components/NumberInput.vue +0 -4
  185. package/src/components/PlateMapEditor.vue +3 -14
  186. package/src/components/PluginIcon.vue +0 -4
  187. package/src/components/ProgressBar.vue +0 -4
  188. package/src/components/ProtocolStepEditor.vue +2 -4
  189. package/src/components/RackEditor.vue +51 -70
  190. package/src/components/ReagentEditor.vue +0 -4
  191. package/src/components/ReagentList.story.vue +18 -0
  192. package/src/components/ReagentList.vue +127 -82
  193. package/src/components/ResourceCard.vue +0 -4
  194. package/src/components/RuntimeUpdateNotice.story.vue +49 -0
  195. package/src/components/RuntimeUpdateNotice.vue +4 -4
  196. package/src/components/SampleHierarchyTree.story.vue +18 -0
  197. package/src/components/SampleHierarchyTree.vue +32 -9
  198. package/src/components/SampleLegend.vue +2 -8
  199. package/src/components/SampleSelector.drag.ts +51 -0
  200. package/src/components/SampleSelector.story.vue +6 -0
  201. package/src/components/SampleSelector.tree.ts +2 -0
  202. package/src/components/SampleSelector.vue +49 -10
  203. package/src/components/SampleSelectorGroupNode.vue +19 -0
  204. package/src/components/ScheduleCalendar.story.vue +6 -0
  205. package/src/components/ScheduleCalendar.vue +82 -7
  206. package/src/components/ScientificNumber.vue +0 -4
  207. package/src/components/SectionCard.vue +0 -4
  208. package/src/components/SegmentedControl.vue +48 -5
  209. package/src/components/SequenceInput.vue +0 -4
  210. package/src/components/SequenceProgressBar.story.vue +110 -0
  211. package/src/components/SequenceProgressBar.vue +0 -4
  212. package/src/components/SettingsModal.vue +0 -4
  213. package/src/components/Skeleton.vue +0 -4
  214. package/src/components/SmartGroupFieldRecipe.vue +8 -6
  215. package/src/components/SmartGroupManual.vue +0 -4
  216. package/src/components/StatusIndicator.vue +0 -4
  217. package/src/components/StepWizard.vue +0 -4
  218. package/src/components/TagsInput.vue +4 -6
  219. package/src/components/ThemeToggle.vue +0 -4
  220. package/src/components/TimePicker.vue +36 -7
  221. package/src/components/TimeRangeInput.vue +0 -4
  222. package/src/components/Tooltip.story.vue +3 -3
  223. package/src/components/Tooltip.vue +0 -4
  224. package/src/components/UnitInput.vue +0 -4
  225. package/src/components/WellPlate.geometry.ts +60 -1
  226. package/src/components/WellPlate.interaction.ts +44 -0
  227. package/src/components/WellPlate.story.vue +8 -0
  228. package/src/components/WellPlate.vue +53 -7
  229. package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
  230. package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
  231. package/src/components/internal/DataStateInternal.vue +74 -0
  232. package/src/components/internal/FormSectionRenderer.vue +0 -4
  233. package/src/components/internal/WellEditPopupInternal.vue +0 -4
  234. package/src/composables/controlSchemaTypes.ts +34 -0
  235. package/src/composables/index.ts +10 -0
  236. package/src/composables/useDropdownState.ts +35 -5
  237. package/src/composables/useEventStream.ts +14 -2
  238. package/src/composables/useFileImport.ts +2 -7
  239. package/src/composables/useGeneratedAnalysis.ts +8 -9
  240. package/src/composables/useListReorder.story.vue +143 -0
  241. package/src/composables/useListReorder.ts +242 -0
  242. package/src/composables/useMenuKeyboard.ts +2 -2
  243. package/src/composables/useOptimisticMutation.ts +1 -15
  244. package/src/composables/usePluginConfig.ts +3 -1
  245. package/src/composables/useRackEditor.ts +2 -11
  246. package/src/composables/useRequestSyncState.ts +98 -28
  247. package/src/composables/useResourceCrud.ts +1 -15
  248. package/src/composables/useScheduleDrag.ts +37 -0
  249. package/src/composables/useWellPainting.ts +5 -29
  250. package/src/composables/useWellPlateEditor.ts +1 -11
  251. package/src/permissions.ts +48 -9
  252. package/src/stores/experiment.ts +2 -7
  253. package/src/stores/index.ts +9 -1
  254. package/src/stores/settings.ts +93 -1
  255. package/src/styles/components/audit-trail.css +5 -5
  256. package/src/styles/components/batch-progress-list.css +7 -0
  257. package/src/styles/components/color-slider.css +2 -2
  258. package/src/styles/components/data-state.css +30 -0
  259. package/src/styles/components/dataframe.css +29 -35
  260. package/src/styles/components/experiment-data-viewer.css +4 -4
  261. package/src/styles/components/experiment-timeline.css +3 -30
  262. package/src/styles/components/form-builder.css +5 -5
  263. package/src/styles/components/lcms-sequence-table.css +16 -1
  264. package/src/styles/components/multi-select.css +1 -1
  265. package/src/styles/components/reagent-list.css +38 -31
  266. package/src/styles/components/sample-hierarchy-tree.css +5 -19
  267. package/src/styles/components/sample-selector.css +9 -2
  268. package/src/styles/components/schedule-calendar.css +8 -0
  269. package/src/styles/components/scientific-number.css +1 -1
  270. package/src/styles/components/well-plate.css +8 -0
  271. package/src/styles/index.css +8 -0
  272. package/src/styles/variables.css +29 -0
  273. package/src/templates/builderPresetControls.ts +1 -1
  274. package/src/templates/componentPlateHelpers.ts +3 -1
  275. package/src/templates/doseResponseAdapters.ts +2 -13
  276. package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
  277. package/src/templates/plateMapBuilder.ts +2 -2
  278. package/src/templates/qpcrPlateBuilder.ts +1 -1
  279. package/src/templates/templateValidators.ts +1 -1
  280. package/src/templates/timeCourseBuilder.ts +2 -2
  281. package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
  282. package/src/utils/color.ts +51 -0
  283. package/src/utils/errors.ts +29 -0
  284. package/dist/EmptyState-NBqf2_8z.js.map +0 -1
  285. package/dist/ExperimentPopover-CfOdh5Rm.js.map +0 -1
  286. package/dist/ExperimentSelectorModal-DvIagrxY.js.map +0 -1
  287. package/dist/SettingsModal-W3TYfnP9.js.map +0 -1
  288. package/dist/components-B80gV0P6.js.map +0 -1
  289. package/dist/composables/autoGroupConstants.d.ts +0 -1
  290. package/dist/composables/autoGroupGrouping.d.ts +0 -3
  291. package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
  292. package/dist/composables-C8mmD5ta.js.map +0 -1
  293. package/dist/experiment-Y9Iz7KYi.js.map +0 -1
  294. package/dist/templates/builderDefaults.d.ts +0 -1
  295. package/dist/templates/plateGeometry.d.ts +0 -4
  296. package/dist/templates-CK72aKO1.js.map +0 -1
  297. package/dist/useApi-CDBq6z23.js.map +0 -1
  298. package/dist/useControlSchema-_OVhavKq.js.map +0 -1
  299. package/dist/useDropdownState-D5G4UvWd.js.map +0 -1
  300. package/dist/useProtocolTemplates-Dq5Pzwyd.js.map +0 -1
  301. package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
  302. package/src/composables/autoGroupConstants.ts +0 -4
  303. package/src/composables/autoGroupGrouping.ts +0 -148
  304. package/src/composables/useAutoGroupInputSources.ts +0 -147
  305. package/src/templates/builderDefaults.ts +0 -11
  306. package/src/templates/plateGeometry.ts +0 -62
  307. /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → components/DataStates.test.d.ts} +0 -0
@@ -0,0 +1,30 @@
1
+ /* DataStateInternal — shared loading / error / empty presentation for data components */
2
+
3
+ .mint-data-state {
4
+ display: flex;
5
+ flex-direction: column;
6
+ align-items: center;
7
+ justify-content: center;
8
+ background-color: var(--bg-primary);
9
+ }
10
+
11
+ .mint-data-state--loading {
12
+ gap: 0.75rem;
13
+ padding: 2.5rem 2rem;
14
+ color: var(--text-muted);
15
+ }
16
+
17
+ .mint-data-state--loading.mint-data-state--sm {
18
+ padding: 1.25rem 1rem;
19
+ }
20
+
21
+ .mint-data-state--loading.mint-data-state--lg {
22
+ padding: 3.5rem 2rem;
23
+ }
24
+
25
+ .mint-data-state__loading-text {
26
+ font-size: 0.875rem;
27
+ color: var(--text-muted);
28
+ margin: 0 !important;
29
+ padding: 0 !important;
30
+ }
@@ -187,6 +187,23 @@
187
187
  text-align: center;
188
188
  }
189
189
 
190
+ /* Sortable headers are real buttons; strip the native chrome so the cell keeps
191
+ its table-header appearance while staying keyboard-operable. */
192
+ .mint-dataframe__th-button {
193
+ display: block;
194
+ width: 100%;
195
+ margin: 0;
196
+ padding: 0;
197
+ border: 0;
198
+ background: none;
199
+ color: inherit;
200
+ font: inherit;
201
+ letter-spacing: inherit;
202
+ text-transform: inherit;
203
+ text-align: inherit;
204
+ cursor: inherit;
205
+ }
206
+
190
207
  .mint-dataframe__th-content {
191
208
  display: inline-flex;
192
209
  align-items: center;
@@ -308,7 +325,7 @@
308
325
  }
309
326
 
310
327
  .mint-dataframe__row--clickable:focus-visible {
311
- outline: 2px solid var(--focus-ring-color, var(--color-primary));
328
+ outline: 2px solid var(--color-primary);
312
329
  outline-offset: -2px;
313
330
  }
314
331
 
@@ -352,32 +369,15 @@ html.dark .mint-dataframe__row--selected > .mint-dataframe__td {
352
369
  border-bottom: none;
353
370
  }
354
371
 
355
- /* Empty state */
356
- .mint-dataframe__empty {
372
+ /* Empty / error placeholder host (content comes from EmptyState) */
373
+ .mint-dataframe__state {
357
374
  display: flex;
358
- flex-direction: column;
359
375
  align-items: center;
360
376
  justify-content: center;
361
377
  min-height: 12rem;
362
- padding: 2.5rem 2rem;
363
- color: var(--text-muted);
364
378
  background-color: var(--bg-primary);
365
379
  }
366
380
 
367
- .mint-dataframe__empty-icon {
368
- width: 2.5rem;
369
- height: 2.5rem;
370
- opacity: 0.5;
371
- margin-bottom: 0.5rem;
372
- }
373
-
374
- .mint-dataframe__empty-text {
375
- font-size: 0.875rem;
376
- margin-top: 0 !important;
377
- margin-bottom: 0 !important;
378
- padding: 0 !important;
379
- }
380
-
381
381
  /* Loading overlay */
382
382
  .mint-dataframe__loading {
383
383
  position: absolute;
@@ -395,18 +395,6 @@ html.dark .mint-dataframe__loading {
395
395
  background-color: rgba(0, 0, 0, 0.4);
396
396
  }
397
397
 
398
- .mint-dataframe__loading-spinner {
399
- width: 1.5rem;
400
- height: 1.5rem;
401
- color: var(--color-primary);
402
- animation: mint-dataframe-spin 1s linear infinite;
403
- }
404
-
405
- @keyframes mint-dataframe-spin {
406
- from { transform: rotate(0deg); }
407
- to { transform: rotate(360deg); }
408
- }
409
-
410
398
  /* Footer / Pagination */
411
399
  .mint-dataframe__footer {
412
400
  display: flex;
@@ -502,11 +490,17 @@ html.dark .mint-dataframe__loading {
502
490
  transition: background-color 0.15s ease;
503
491
  }
504
492
 
505
- .mint-dataframe__resize-handle:hover::after {
493
+ .mint-dataframe__resize-handle:hover::after,
494
+ .mint-dataframe__resize-handle:focus-visible::after {
506
495
  width: 2px;
507
496
  background-color: var(--color-primary);
508
497
  }
509
498
 
499
+ .mint-dataframe__resize-handle:focus-visible {
500
+ outline: none;
501
+ box-shadow: var(--focus-ring);
502
+ }
503
+
510
504
  /* Row delete action column */
511
505
  .mint-dataframe__th--actions,
512
506
  .mint-dataframe__td--actions {
@@ -539,8 +533,8 @@ html.dark .mint-dataframe__loading {
539
533
  }
540
534
 
541
535
  .mint-dataframe__delete-btn:hover {
542
- background-color: color-mix(in srgb, var(--color-error, #ef4444) 14%, transparent);
543
- color: var(--color-error, #ef4444);
536
+ background-color: color-mix(in srgb, var(--mint-error) 14%, transparent);
537
+ color: var(--mint-error);
544
538
  }
545
539
 
546
540
  .mint-dataframe__delete-btn:focus-visible {
@@ -27,10 +27,10 @@
27
27
  flex-direction: column;
28
28
  gap: 12px;
29
29
  }
30
- .mint-data-viewer__empty {
31
- text-align: center;
32
- padding: 32px;
33
- color: var(--text-muted);
30
+ .mint-data-viewer__state {
31
+ display: flex;
32
+ align-items: center;
33
+ justify-content: center;
34
34
  }
35
35
 
36
36
  /* Summary view */
@@ -291,7 +291,7 @@
291
291
  .mint-timeline__expanded {
292
292
  margin-top: 0.75rem;
293
293
  padding-top: 0.75rem;
294
- border-top: 1px solid rgba(var(--border-color-rgb, 0, 0, 0), 0.5);
294
+ border-top: 1px solid color-mix(in srgb, var(--border-color) 50%, transparent);
295
295
  }
296
296
 
297
297
  .mint-timeline__description {
@@ -434,42 +434,15 @@
434
434
  width: 2rem;
435
435
  }
436
436
 
437
- /* Empty state */
438
- .mint-timeline__empty {
437
+ /* Empty / loading / error placeholder host (content comes from EmptyState) */
438
+ .mint-timeline__state {
439
439
  display: flex;
440
440
  align-items: center;
441
441
  justify-content: center;
442
- padding: 2rem;
443
442
  border: 2px dashed var(--border-color);
444
443
  border-radius: var(--radius-md);
445
444
  }
446
445
 
447
- .mint-timeline__empty-content {
448
- text-align: center;
449
- }
450
-
451
- .mint-timeline__empty-text {
452
- color: var(--text-muted);
453
- margin-top: 0 !important;
454
- margin-bottom: 0.5rem !important;
455
- padding: 0 !important;
456
- }
457
-
458
- .mint-timeline__empty-btn {
459
- padding: 0.375rem 0.75rem;
460
- font-size: 0.875rem;
461
- background-color: var(--color-primary);
462
- color: white;
463
- border: none;
464
- border-radius: var(--radius-md);
465
- cursor: pointer;
466
- transition: background-color 0.15s ease;
467
- }
468
-
469
- .mint-timeline__empty-btn:hover {
470
- opacity: 0.9;
471
- }
472
-
473
446
  /* Add step button (end) */
474
447
  .mint-timeline__add-end {
475
448
  display: flex;
@@ -40,16 +40,16 @@
40
40
  }
41
41
 
42
42
  .mint-form-section__title {
43
- font-size: var(--font-size-base, 0.9375rem);
43
+ font-size: 0.9375rem;
44
44
  font-weight: 600;
45
- color: var(--color-text, #1a1a2e);
45
+ color: var(--text-primary);
46
46
  margin: 0;
47
47
  line-height: 1.4;
48
48
  }
49
49
 
50
50
  .mint-form-section__description {
51
- font-size: var(--font-size-sm, 0.8125rem);
52
- color: var(--color-text-secondary, #6b7280);
51
+ font-size: 0.8125rem;
52
+ color: var(--text-secondary);
53
53
  margin: 0;
54
54
  line-height: 1.5;
55
55
  }
@@ -65,5 +65,5 @@
65
65
  align-items: center;
66
66
  gap: 0.75rem;
67
67
  padding-top: 1rem;
68
- border-top: 1px solid var(--color-border, #e5e7eb);
68
+ border-top: 1px solid var(--border-color);
69
69
  }
@@ -64,7 +64,11 @@
64
64
  padding-right: 0.25rem;
65
65
  }
66
66
 
67
+ /* The handle is a button so it can also take Alt+Arrow keyboard reordering. */
67
68
  .mint-lcms-sequence-table__drag-handle {
69
+ padding: 0;
70
+ border: 0;
71
+ background: none;
68
72
  color: var(--text-muted, #64748b);
69
73
  cursor: grab;
70
74
  font-family: var(--font-mono, 'Fira Code', monospace);
@@ -72,6 +76,11 @@
72
76
  letter-spacing: -0.08em;
73
77
  }
74
78
 
79
+ .mint-lcms-sequence-table__drag-handle:focus-visible {
80
+ outline: none;
81
+ box-shadow: var(--focus-ring);
82
+ }
83
+
75
84
  .mint-lcms-sequence-table__td {
76
85
  min-width: 0;
77
86
  color: var(--text-primary, #0f172a);
@@ -168,7 +177,6 @@
168
177
  background: color-mix(in srgb, var(--mint-error, #ef4444) 10%, transparent);
169
178
  }
170
179
 
171
- .mint-lcms-sequence-table__empty,
172
180
  .mint-lcms-sequence-table__more {
173
181
  color: var(--text-muted, #64748b);
174
182
  font-size: 0.875rem;
@@ -176,6 +184,13 @@
176
184
  text-align: center;
177
185
  }
178
186
 
187
+ /* Empty / loading / error placeholder host (content comes from EmptyState) */
188
+ .mint-lcms-sequence-table__state {
189
+ display: flex;
190
+ align-items: center;
191
+ justify-content: center;
192
+ }
193
+
179
194
  .mint-lcms-sequence-table__more {
180
195
  border-top: 1px solid var(--border-color, #e2e8f0);
181
196
  padding: 0.625rem 1rem;
@@ -64,7 +64,7 @@
64
64
  }
65
65
 
66
66
  .mint-multi-select__chip--active:hover {
67
- background-color: var(--color-primary-dark, #4338ca);
67
+ background-color: var(--color-primary-hover);
68
68
  }
69
69
 
70
70
  .mint-multi-select__chip--disabled {
@@ -138,6 +138,24 @@
138
138
  color: var(--text-secondary);
139
139
  }
140
140
 
141
+ /* Sortable headers are real buttons; strip the native chrome so the cell keeps
142
+ its table-header look while staying keyboard-operable. */
143
+ .mint-reagent-list__sort-btn {
144
+ display: inline-flex;
145
+ align-items: center;
146
+ width: 100%;
147
+ margin: 0;
148
+ padding: 0;
149
+ border: 0;
150
+ background: none;
151
+ color: inherit;
152
+ font: inherit;
153
+ letter-spacing: inherit;
154
+ text-transform: inherit;
155
+ text-align: inherit;
156
+ cursor: inherit;
157
+ }
158
+
141
159
  .mint-reagent-list__sort-icon {
142
160
  display: inline-block;
143
161
  width: 0.75rem;
@@ -332,45 +350,34 @@
332
350
  height: 1rem;
333
351
  }
334
352
 
335
- /* Empty state */
336
- .mint-reagent-list__empty {
337
- padding: 2rem;
338
- text-align: center;
339
- }
340
-
341
- .mint-reagent-list__empty-icon {
342
- width: 2.5rem;
343
- height: 2.5rem;
344
- margin: 0 auto 0.75rem;
345
- color: var(--text-muted);
346
- opacity: 0.5;
353
+ /* Empty / loading / error placeholder host (content comes from EmptyState) */
354
+ .mint-reagent-list__state {
355
+ display: flex;
356
+ align-items: center;
357
+ justify-content: center;
347
358
  }
348
359
 
349
- .mint-reagent-list__empty-text {
350
- font-size: 0.875rem;
351
- color: var(--text-muted);
352
- margin-top: 0 !important;
353
- margin-bottom: 0.75rem !important;
354
- padding: 0 !important;
360
+ /* Drag handle */
361
+ /* The drag handle doubles as the keyboard reorder target (Alt+Arrow). */
362
+ .mint-reagent-list__drag-handle-btn {
363
+ display: inline-flex;
364
+ align-items: center;
365
+ padding: 0;
366
+ border: 0;
367
+ background: none;
368
+ color: inherit;
369
+ cursor: grab;
355
370
  }
356
371
 
357
- .mint-reagent-list__empty-btn {
358
- padding: 0.375rem 0.75rem;
359
- font-size: 0.875rem;
360
- font-weight: 500;
361
- color: white;
362
- background-color: var(--color-primary);
363
- border: none;
364
- border-radius: var(--radius);
365
- cursor: pointer;
366
- transition: background-color 0.15s ease;
372
+ .mint-reagent-list__drag-handle-btn:focus-visible {
373
+ outline: none;
374
+ box-shadow: var(--focus-ring);
367
375
  }
368
376
 
369
- .mint-reagent-list__empty-btn:hover {
370
- background-color: var(--color-primary-hover);
377
+ .mint-reagent-list__drag-handle-btn:focus-visible .mint-reagent-list__drag-handle {
378
+ opacity: 1;
371
379
  }
372
380
 
373
- /* Drag handle */
374
381
  .mint-reagent-list__drag-handle {
375
382
  width: 1rem;
376
383
  color: var(--text-muted);
@@ -288,23 +288,9 @@
288
288
  }
289
289
  }
290
290
 
291
- /* Empty state */
292
- .mint-sample-tree__empty {
293
- padding: 1rem;
294
- text-align: center;
295
- color: var(--text-muted);
296
- }
297
-
298
- .mint-sample-tree__empty-icon {
299
- width: 2rem;
300
- height: 2rem;
301
- margin: 0 auto 0.5rem;
302
- opacity: 0.5;
303
- }
304
-
305
- .mint-sample-tree__empty-text {
306
- font-size: 0.875rem;
307
- margin-top: 0 !important;
308
- margin-bottom: 0 !important;
309
- padding: 0 !important;
291
+ /* Empty / loading / error placeholder host (content comes from EmptyState) */
292
+ .mint-sample-tree__state {
293
+ display: flex;
294
+ align-items: center;
295
+ justify-content: center;
310
296
  }
@@ -468,14 +468,21 @@
468
468
  height: 0.625rem;
469
469
  }
470
470
 
471
- /* Empty State */
472
- .mint-sample-selector__empty {
471
+ /* Inline hint shown inside the grouped/flat sub-lists */
472
+ .mint-sample-selector__hint {
473
473
  text-align: center;
474
474
  padding: 1rem;
475
475
  font-size: 0.875rem;
476
476
  color: var(--text-muted);
477
477
  }
478
478
 
479
+ /* Empty / loading / error placeholder host (content comes from EmptyState) */
480
+ .mint-sample-selector__state {
481
+ display: flex;
482
+ align-items: center;
483
+ justify-content: center;
484
+ }
485
+
479
486
  /* Ungrouped Section */
480
487
  .mint-sample-selector__ungrouped {
481
488
  margin-top: 0.75rem;
@@ -470,3 +470,11 @@
470
470
  .mint-schedule__month-more:hover {
471
471
  text-decoration: underline;
472
472
  }
473
+
474
+ /* Empty / loading / error placeholder host (content comes from EmptyState) */
475
+ .mint-schedule__state {
476
+ display: flex;
477
+ align-items: center;
478
+ justify-content: center;
479
+ min-height: 12rem;
480
+ }
@@ -59,5 +59,5 @@
59
59
  }
60
60
 
61
61
  .mint-sci-number__copy-btn--copied {
62
- color: var(--color-success, #10b981);
62
+ color: var(--mint-success);
63
63
  }
@@ -284,3 +284,11 @@
284
284
  font-size: 0.75rem;
285
285
  color: var(--text-muted);
286
286
  }
287
+
288
+ /* Empty / loading / error placeholder host (content comes from EmptyState) */
289
+ .mint-well-plate__state {
290
+ display: flex;
291
+ align-items: center;
292
+ justify-content: center;
293
+ min-height: 12rem;
294
+ }
@@ -57,6 +57,7 @@
57
57
  @import './components/dropdown-button.css';
58
58
  @import './components/calendar.css';
59
59
  @import './components/dataframe.css';
60
+ @import './components/data-state.css';
60
61
  @import './components/well-edit-popup.css';
61
62
  @import './components/rack-editor.css';
62
63
  @import './components/loading-spinner.css';
@@ -92,3 +93,10 @@
92
93
  @import './components/artifact-save-dialog.css';
93
94
  @import './components/experiment-popover.css';
94
95
  @import './components/fit-panel.css';
96
+ @import './components/app-avatar-menu.css';
97
+ @import './components/app-page-selector.css';
98
+ @import './components/app-pill-nav.css';
99
+ @import './components/app-plugin-switcher.css';
100
+ @import './components/mobile-support-gate.css';
101
+ @import './components/plugin-icon.css';
102
+ @import './components/reagent-editor.css';
@@ -66,6 +66,32 @@
66
66
  /* The MINT 1.1 card system uses exactly one shadow for every card. */
67
67
  --card-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.04), 0 1px 3px 0 rgb(0 0 0 / 0.06);
68
68
 
69
+ /* Categorical sample scale — mirrored by SAMPLE_COLOR_SCALE in
70
+ src/utils/color.ts. The JS constant carries the same hexes as a
71
+ canvas/SVG/persistence-safe fallback; change both together. */
72
+ --mint-sample-1: #3B82F6;
73
+ --mint-sample-2: #10B981;
74
+ --mint-sample-3: #EF4444;
75
+ --mint-sample-4: #F59E0B;
76
+ --mint-sample-5: #8B5CF6;
77
+ --mint-sample-6: #F97316;
78
+ --mint-sample-7: #06B6D4;
79
+ --mint-sample-8: #14B8A6;
80
+ --mint-sample-9: #6B7280;
81
+
82
+ /* Rack / plate slot positions — mirrored by SLOT_COLORS in
83
+ src/utils/color.ts. */
84
+ --mint-slot-r: #ef4444;
85
+ --mint-slot-g: #22c55e;
86
+ --mint-slot-b: #3b82f6;
87
+ --mint-slot-y: #eab308;
88
+
89
+ /* Motion — the SDK's standard easing curve. */
90
+ --mint-ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
91
+
92
+ /* Typography — Fira Code for data, code and routes. */
93
+ --font-mono: 'Fira Code', ui-monospace, SFMono-Regular, Menlo, monospace;
94
+
69
95
  /* Border radius */
70
96
  --radius-sm: 0.25rem;
71
97
  --radius: 0.375rem;
@@ -90,6 +116,8 @@
90
116
  --mint-warning-hover: #D97706;
91
117
  --mint-warning-bg: rgba(245, 158, 11, 0.1);
92
118
  --mint-warning-border: rgba(245, 158, 11, 0.3);
119
+ /* Readable warning label on --mint-warning-bg (amber-700, 5.9:1). */
120
+ --mint-warning-text: #B45309;
93
121
  --mint-info: #3B82F6;
94
122
  --mint-info-bg: rgba(59, 130, 246, 0.1);
95
123
  --mint-info-border: rgba(59, 130, 246, 0.3);
@@ -178,6 +206,7 @@ html.dark {
178
206
  --mint-success-bg: rgba(16, 185, 129, 0.15);
179
207
  --mint-error-bg: rgba(239, 68, 68, 0.15);
180
208
  --mint-warning-bg: rgba(245, 158, 11, 0.15);
209
+ --mint-warning-text: #FCD34D;
181
210
  --mint-info-bg: rgba(59, 130, 246, 0.15);
182
211
 
183
212
  /* Focus ring - dark mode offset uses bg-primary instead of white */
@@ -7,7 +7,7 @@ import {
7
7
  readString,
8
8
  readStringList,
9
9
  } from './builderReadUtils'
10
- import { readPlateFormat } from './plateGeometry'
10
+ import { readPlateFormat } from '../components/WellPlate.geometry'
11
11
  import { getBioTemplatePresetInfo } from './presets'
12
12
  import type {
13
13
  CreateElisaAssayCollectionOptions,
@@ -2,6 +2,7 @@ import type {
2
2
  PlateMapEditorState,
3
3
  WellLegendItem,
4
4
  } from '../types'
5
+ import { SAMPLE_COLOR_SCALE } from '../utils/color'
5
6
 
6
7
  export function activePlateFromState(state: PlateMapEditorState) {
7
8
  return state.plates.find(plate => plate.id === state.activePlateId) ?? state.plates[0]
@@ -24,6 +25,7 @@ export function legendItemsFromPlateState(state: PlateMapEditorState): WellLegen
24
25
  }
25
26
 
26
27
  export function colorForIndex(index: number): string {
27
- const colors = ['#3B82F6', '#10B981', '#EF4444', '#F59E0B', '#8B5CF6', '#F97316', '#06B6D4', '#14B8A6']
28
+ // The gray tail of the scale is reserved for "other"; component plates cycle the eight hues.
29
+ const colors = SAMPLE_COLOR_SCALE.slice(0, 8)
28
30
  return colors[index % colors.length]
29
31
  }
@@ -2,6 +2,7 @@ import type {
2
2
  PlateCondition,
3
3
  PlateMapEditorState,
4
4
  } from '../types'
5
+ import { SAMPLE_COLOR_SCALE } from '../utils/color'
5
6
  import { toPlateMapEditorState } from './plateMapAdapters'
6
7
  import { getTemplateData } from './templateEnvelopes'
7
8
  import { validateDoseResponseData } from './templateValidators'
@@ -11,18 +12,6 @@ import type {
11
12
  DoseResponseTemplateData,
12
13
  } from './types'
13
14
 
14
- const CONDITION_COLORS = [
15
- '#3B82F6',
16
- '#10B981',
17
- '#EF4444',
18
- '#F59E0B',
19
- '#8B5CF6',
20
- '#F97316',
21
- '#06B6D4',
22
- '#14B8A6',
23
- '#6B7280',
24
- ]
25
-
26
15
  export function toDoseConditions(
27
16
  template: DoseResponseTemplate | DoseResponseTemplateData
28
17
  ): DoseConditionsAdapterResult {
@@ -30,7 +19,7 @@ export function toDoseConditions(
30
19
  validateDoseResponseData(data)
31
20
  return data.compounds.map((compound, index): PlateCondition => ({
32
21
  label: compound.name,
33
- color: String(compound.metadata?.color ?? CONDITION_COLORS[index % CONDITION_COLORS.length]),
22
+ color: String(compound.metadata?.color ?? SAMPLE_COLOR_SCALE[index % SAMPLE_COLOR_SCALE.length]),
34
23
  concentrations: compound.concentrations,
35
24
  unit: data.unit,
36
25
  }))
@@ -1,5 +1,5 @@
1
1
  import { createAssayMatrixTemplate } from './assayMatrixBuilder'
2
- import { DEFAULT_SAMPLE_COLORS } from './builderDefaults'
2
+ import { SAMPLE_COLOR_SCALE } from '../utils/color'
3
3
  import { idFromName } from './builderIdUtils'
4
4
  import { createCalibrationCurveTemplate } from './calibrationCurveBuilder'
5
5
  import { createPlateMapTemplate } from './plateMapBuilder'
@@ -27,7 +27,7 @@ export function createElisaAssayCollection(
27
27
  ...sampleRecords.map((sample, index) => ({
28
28
  id: sample.sampleId,
29
29
  name: sample.name ?? sample.sampleId,
30
- color: DEFAULT_SAMPLE_COLORS[index % DEFAULT_SAMPLE_COLORS.length],
30
+ color: SAMPLE_COLOR_SCALE[index % SAMPLE_COLOR_SCALE.length],
31
31
  })),
32
32
  ],
33
33
  })
@@ -1,4 +1,4 @@
1
- import { DEFAULT_SAMPLE_COLORS } from './builderDefaults'
1
+ import { SAMPLE_COLOR_SCALE } from '../utils/color'
2
2
  import { sampleIdFromName } from './builderIdUtils'
3
3
  import { createTemplateEnvelope } from './templateEnvelopes'
4
4
  import type {
@@ -23,7 +23,7 @@ export function createPlateMapTemplate(
23
23
  return {
24
24
  id: sampleIdFromName(sample, index),
25
25
  name: sample,
26
- color: DEFAULT_SAMPLE_COLORS[index % DEFAULT_SAMPLE_COLORS.length],
26
+ color: SAMPLE_COLOR_SCALE[index % SAMPLE_COLOR_SCALE.length],
27
27
  }
28
28
  })
29
29
 
@@ -1,5 +1,5 @@
1
1
  import { idFromName } from './builderIdUtils'
2
- import { wellIdsForFormat } from './plateGeometry'
2
+ import { wellIdsForFormat } from '../components/WellPlate.geometry'
3
3
  import {
4
4
  normalizeQpcrSample,
5
5
  normalizeQpcrTarget,
@@ -12,7 +12,7 @@ import type {
12
12
  SampleSheetTemplateData,
13
13
  TimeCourseTemplateData,
14
14
  } from './types'
15
- import { assertWellInFormat } from './plateGeometry'
15
+ import { assertWellInFormat } from '../components/WellPlate.geometry'
16
16
 
17
17
  export function validatePlateMapData(data: PlateMapTemplateData): void {
18
18
  if (!Array.isArray(data.plates) || data.plates.length === 0) {
@@ -1,4 +1,4 @@
1
- import { DEFAULT_SAMPLE_COLORS } from './builderDefaults'
1
+ import { SAMPLE_COLOR_SCALE } from '../utils/color'
2
2
  import {
3
3
  idFromName,
4
4
  timepointId,
@@ -36,7 +36,7 @@ export function createTimeCourseTemplate(
36
36
  return {
37
37
  id: idFromName(condition, `condition-${index + 1}`),
38
38
  name: condition,
39
- color: DEFAULT_SAMPLE_COLORS[index % DEFAULT_SAMPLE_COLORS.length],
39
+ color: SAMPLE_COLOR_SCALE[index % SAMPLE_COLOR_SCALE.length],
40
40
  metadata: {},
41
41
  }
42
42
  })