@morscherlab/mint-sdk 1.3.0-beta.1 → 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 (134) hide show
  1. package/README.md +23 -140
  2. package/dist/{ResourcePickerListInternal-c3IT8PIu.js → ResourcePickerListInternal-CFAw4vTZ.js} +26 -19
  3. package/dist/ResourcePickerListInternal-CFAw4vTZ.js.map +1 -0
  4. package/dist/components/FilePicker.vue.d.ts +4 -1
  5. package/dist/components/SettingsModal.schema.d.ts +1 -1
  6. package/dist/components/SettingsModal.vue.d.ts +2 -0
  7. package/dist/components/WellPlate.colors.d.ts +1 -5
  8. package/dist/components/WellPlate.rendering.d.ts +5 -2
  9. package/dist/components/index.d.ts +32 -17
  10. package/dist/components/index.js +3 -3
  11. package/dist/components/internal/FilePickerListInternal.vue.d.ts +2 -0
  12. package/dist/components/internal/ResourcePickerListInternal.vue.d.ts +9 -3
  13. package/dist/{components-CvY105kJ.js → components-GDDvof8D.js} +414 -368
  14. package/dist/components-GDDvof8D.js.map +1 -0
  15. package/dist/composables/createFilePickerAdapter.d.ts +5 -1
  16. package/dist/composables/filePicker/usePickerNavigation.d.ts +3 -2
  17. package/dist/composables/index.d.ts +0 -3
  18. package/dist/composables/index.js +4 -4
  19. package/dist/composables/useAutoGroup.d.ts +1 -1
  20. package/dist/composables/useBioTemplateComponents.d.ts +15 -3
  21. package/dist/composables/useBioTemplateControls.d.ts +5 -1
  22. package/dist/composables/useBioTemplatePackWorkspace.d.ts +2 -0
  23. package/dist/composables/useBioTemplatePresetWorkspace.d.ts +5 -1
  24. package/dist/composables/useBioTemplateWorkspace.d.ts +5 -1
  25. package/dist/composables/useExperimentSave.d.ts +5 -1
  26. package/dist/composables/useFilePicker.d.ts +4 -1
  27. package/dist/composables/useGroupAssignment.d.ts +5 -1
  28. package/dist/composables/usePlatformContext.d.ts +3 -0
  29. package/dist/composables/useTemplateCollection.d.ts +5 -1
  30. package/dist/composables-D6uqp0UF.js +591 -0
  31. package/dist/composables-D6uqp0UF.js.map +1 -0
  32. package/dist/index.js +24 -24
  33. package/dist/index.js.map +1 -1
  34. package/dist/install.js +1 -1
  35. package/dist/lcms.d.ts +11 -11
  36. package/dist/styles.css +170 -200
  37. package/dist/templates/index.js +1 -1
  38. package/dist/{templates-Bj9hZ7iV.js → templates-BU1pet28.js} +31 -44
  39. package/dist/templates-BU1pet28.js.map +1 -0
  40. package/dist/types/auth.d.ts +0 -27
  41. package/dist/types/components.d.ts +8 -0
  42. package/dist/types/fileBrowserTypes.d.ts +13 -0
  43. package/dist/types/filePicker.d.ts +8 -1
  44. package/dist/types/index.d.ts +2 -2
  45. package/dist/types/platform.d.ts +2 -0
  46. package/dist/utils/rack.d.ts +16 -16
  47. package/dist/{validation-B4Y8_eEe.js → validation-Dmp9Q5W0.js} +50 -12
  48. package/dist/validation-Dmp9Q5W0.js.map +1 -0
  49. package/package.json +1 -6
  50. package/src/__tests__/components/ActionMenu.test.ts +10 -0
  51. package/src/__tests__/components/AppTopBar.test.ts +24 -8
  52. package/src/__tests__/components/EmptyState.test.ts +15 -0
  53. package/src/__tests__/components/ExperimentSelectorModal.test.ts +12 -5
  54. package/src/__tests__/components/FilePicker.test.ts +65 -1
  55. package/src/__tests__/components/FileUploader.test.ts +6 -9
  56. package/src/__tests__/components/ResourcePickerListInternal.test.ts +23 -4
  57. package/src/__tests__/components/SettingsModal.test.ts +22 -0
  58. package/src/__tests__/components/WellPlate.decoration.test.ts +4 -28
  59. package/src/__tests__/components/WellPlate.rendering.test.ts +20 -33
  60. package/src/__tests__/components/WellPlate.sampleTypeIndicator.test.ts +7 -7
  61. package/src/__tests__/composables/createFilePickerAdapter.test.ts +92 -1
  62. package/src/__tests__/composables/usePickerNavigation.test.ts +61 -1
  63. package/src/__tests__/composables/usePlatformFilePickerAdapter.test.ts +18 -6
  64. package/src/__tests__/docs/frontendDocsCatalog.test.ts +2 -2
  65. package/src/__tests__/styles/controlRefreshRules.test.ts +21 -8
  66. package/src/__tests__/styles/menusShellRefresh.test.ts +20 -5
  67. package/src/__tests__/templates/templatesDeprecation.test.ts +58 -11
  68. package/src/components/ActionMenu.vue +10 -2
  69. package/src/components/AppTopBar.vue +6 -4
  70. package/src/components/EmptyState.vue +3 -1
  71. package/src/components/ExperimentSelectorModal.vue +4 -1
  72. package/src/components/FilePicker.vue +42 -0
  73. package/src/components/FileUploader.vue +30 -46
  74. package/src/components/SettingsModal.schema.ts +4 -2
  75. package/src/components/SettingsModal.vue +4 -2
  76. package/src/components/WellPlate.colors.ts +6 -10
  77. package/src/components/WellPlate.legend.ts +4 -4
  78. package/src/components/WellPlate.rendering.ts +9 -8
  79. package/src/components/WellPlate.vue +5 -22
  80. package/src/components/index.ts +32 -17
  81. package/src/components/internal/FilePickerListInternal.vue +11 -2
  82. package/src/components/internal/ResourcePickerListInternal.vue +21 -27
  83. package/src/composables/autoGroup/index.ts +1 -1
  84. package/src/composables/createFilePickerAdapter.ts +82 -22
  85. package/src/composables/filePicker/usePickerNavigation.ts +29 -2
  86. package/src/composables/index.ts +0 -7
  87. package/src/composables/useAutoGroup.ts +1 -1
  88. package/src/composables/useBioTemplateComponents.ts +15 -3
  89. package/src/composables/useBioTemplateControls.ts +5 -1
  90. package/src/composables/useBioTemplatePackWorkspace.ts +2 -0
  91. package/src/composables/useBioTemplatePresetWorkspace.ts +5 -1
  92. package/src/composables/useBioTemplateWorkspace.ts +5 -1
  93. package/src/composables/useExperimentSave.ts +5 -1
  94. package/src/composables/useFilePicker.ts +8 -1
  95. package/src/composables/useGroupAssignment.ts +5 -1
  96. package/src/composables/usePlatformFilePickerAdapter.ts +26 -4
  97. package/src/composables/useTemplateCollection.ts +5 -1
  98. package/src/index.ts +1 -1
  99. package/src/lcms.ts +11 -11
  100. package/src/styles/components/action-menu.css +10 -0
  101. package/src/styles/components/app-page-selector.css +3 -3
  102. package/src/styles/components/app-pill-nav.css +1 -1
  103. package/src/styles/components/app-top-bar.css +18 -38
  104. package/src/styles/components/empty-state.css +3 -2
  105. package/src/styles/components/experiment-selector-modal.css +3 -9
  106. package/src/styles/components/file-picker.css +23 -1
  107. package/src/styles/components/file-uploader.css +22 -55
  108. package/src/styles/components/resource-picker-list.css +70 -36
  109. package/src/styles/components/well-plate.css +18 -55
  110. package/src/types/auth.ts +0 -37
  111. package/src/types/components.ts +8 -0
  112. package/src/types/fileBrowserTypes.ts +15 -0
  113. package/src/types/filePicker.ts +8 -1
  114. package/src/types/index.ts +2 -5
  115. package/src/types/platform.ts +2 -0
  116. package/src/utils/rack.ts +16 -16
  117. package/dist/ResourcePickerListInternal-c3IT8PIu.js.map +0 -1
  118. package/dist/__tests__/composables/useAuth.test.d.ts +0 -1
  119. package/dist/__tests__/composables/usePasskey.test.d.ts +0 -1
  120. package/dist/components-CvY105kJ.js.map +0 -1
  121. package/dist/composables/useAuth.d.ts +0 -47
  122. package/dist/composables/usePasskey.d.ts +0 -10
  123. package/dist/composables/useWellPlateEditor.d.ts +0 -33
  124. package/dist/composables-DL4Vca7L.js +0 -1193
  125. package/dist/composables-DL4Vca7L.js.map +0 -1
  126. package/dist/plotly.min-D6Ge6qgX.js +0 -168582
  127. package/dist/plotly.min-D6Ge6qgX.js.map +0 -1
  128. package/dist/templates-Bj9hZ7iV.js.map +0 -1
  129. package/dist/validation-B4Y8_eEe.js.map +0 -1
  130. package/src/__tests__/composables/useAuth.test.ts +0 -290
  131. package/src/__tests__/composables/usePasskey.test.ts +0 -38
  132. package/src/composables/useAuth.ts +0 -470
  133. package/src/composables/usePasskey.ts +0 -216
  134. package/src/composables/useWellPlateEditor.ts +0 -415
@@ -67,14 +67,22 @@ export interface UseBioTemplateComponentsReturn {
67
67
  ) => Record<string, unknown> | undefined
68
68
  }
69
69
 
70
- /** Return component props grouped by SDK component name for direct WellPlate/DoseCalculator binding. */
70
+ /**
71
+ * Return component props grouped by SDK component name for direct WellPlate/DoseCalculator binding.
72
+ *
73
+ * @deprecated Scheduled for removal in MINT 1.4; no SDK replacement.
74
+ */
71
75
  export function toBioTemplateComponentPropsByComponent(
72
76
  target: BioTemplateEnvelope<unknown> | TemplateCollectionEnvelope,
73
77
  ): BioTemplateComponentPropsByComponent {
74
78
  return toTemplateComponentPropsByComponent(target)
75
79
  }
76
80
 
77
- /** Return the first props object for an SDK component, optionally restricted by template id or binding id. */
81
+ /**
82
+ * Return the first props object for an SDK component, optionally restricted by template id or binding id.
83
+ *
84
+ * @deprecated Scheduled for removal in MINT 1.4; no SDK replacement.
85
+ */
78
86
  export function getBioTemplateComponentProps(
79
87
  target: BioTemplateEnvelope<unknown> | TemplateCollectionEnvelope,
80
88
  component: string,
@@ -83,7 +91,11 @@ export function getBioTemplateComponentProps(
83
91
  return getTemplateComponentProps(target, component, options)
84
92
  }
85
93
 
86
- /** Map built-in biology templates to SDK components such as WellPlate, DataFrame, DoseCalculator, and PlateEditor. */
94
+ /**
95
+ * Map built-in biology templates to SDK components such as WellPlate, DataFrame, DoseCalculator, and PlateEditor.
96
+ *
97
+ * @deprecated Scheduled for removal in MINT 1.4; no SDK replacement.
98
+ */
87
99
  export function useBioTemplateComponents(
88
100
  target: BioTemplateComponentTarget
89
101
  ): UseBioTemplateComponentsReturn {
@@ -21,7 +21,11 @@ export type {
21
21
  BioTemplateControlTarget,
22
22
  }
23
23
 
24
- /** Build FormBuilder schema, AppSidebar panels, and defaults for a built-in biology template or preset. */
24
+ /**
25
+ * Build FormBuilder schema, AppSidebar panels, and defaults for a built-in biology template or preset.
26
+ *
27
+ * @deprecated Scheduled for removal in MINT 1.4; no SDK replacement.
28
+ */
25
29
  export function useBioTemplateControls(
26
30
  target: BioTemplateControlTarget,
27
31
  options: ControlWorkspaceOptions = {},
@@ -90,6 +90,8 @@ export interface UseBioTemplatePackWorkspaceReturn {
90
90
  * const pack = useBioTemplatePackWorkspace('cell-culture-screen')
91
91
  * await pack.loadCurrent()
92
92
  * ```
93
+ *
94
+ * @deprecated Scheduled for removal in MINT 1.4; no SDK replacement.
93
95
  */
94
96
  export function useBioTemplatePackWorkspace(
95
97
  packId: TemplatePackId | string,
@@ -119,7 +119,11 @@ export interface BioTemplatePresetWorkspaceBindings {
119
119
  getComponentProps: UseBioTemplateWorkspaceReturn['getComponentProps']
120
120
  }
121
121
 
122
- /** Create a complete editable WellPlate/DoseCalculator workspace for dose design from a built-in biology template preset with current-experiment save wiring. */
122
+ /**
123
+ * Create a complete editable WellPlate/DoseCalculator workspace for dose design from a built-in biology template preset with current-experiment save wiring.
124
+ *
125
+ * @deprecated Scheduled for removal in MINT 1.4; no SDK replacement.
126
+ */
123
127
  export function useBioTemplatePresetWorkspace(
124
128
  presetId: TemplatePresetId,
125
129
  options: UseBioTemplatePresetWorkspaceOptions = {},
@@ -60,7 +60,11 @@ export interface UseBioTemplateWorkspaceReturn extends BioTemplateWorkspaceCompo
60
60
  renderer: BioTemplateRendererBinding | null
61
61
  }
62
62
 
63
- /** One-stop wiring for BioTemplateRenderer, FormBuilder, AppSidebar, and template-aware SDK components. */
63
+ /**
64
+ * One-stop wiring for BioTemplateRenderer, FormBuilder, AppSidebar, and template-aware SDK components.
65
+ *
66
+ * @deprecated Scheduled for removal in MINT 1.4; no SDK replacement.
67
+ */
64
68
  export function useBioTemplateWorkspace(
65
69
  target: BioTemplateWorkspaceTarget,
66
70
  options: ControlWorkspaceOptions = {}
@@ -86,7 +86,11 @@ export interface UseExperimentSaveReturn {
86
86
  requireCurrentExperimentId: () => number
87
87
  }
88
88
 
89
- /** Persists experiment design, analysis, and built-in template preset data through the platform API. */
89
+ /**
90
+ * Persists experiment design, analysis, and built-in template preset data through the platform API.
91
+ *
92
+ * @deprecated Scheduled for removal in MINT 1.4; no SDK replacement.
93
+ */
90
94
  export function useExperimentSave(
91
95
  options: UseExperimentSaveOptions = {},
92
96
  ): UseExperimentSaveReturn {
@@ -5,6 +5,7 @@ import type {
5
5
  PickerNode,
6
6
  PickerSelection,
7
7
  PickerSelectionMode,
8
+ PickerSort,
8
9
  PickerSource,
9
10
  } from '../types/filePicker'
10
11
  import type { SegmentedOption } from '../types'
@@ -20,6 +21,7 @@ interface PickerStateProps {
20
21
  capabilities: PickerCapabilities
21
22
  initialPath: string
22
23
  initialSelection: PickerSelection | null
24
+ defaultSort: PickerSort
23
25
  systemFilter?: (node: PickerNode, source: PickerSource) => boolean
24
26
  }
25
27
  type PickerEmit = {
@@ -50,6 +52,7 @@ export function useFilePicker(
50
52
  )
51
53
  const query = shallowRef('')
52
54
  const recursive = shallowRef(false)
55
+ const sort = shallowRef<PickerSort>(props.defaultSort)
53
56
  const skipBlanks = shallowRef(false)
54
57
  const reviewing = shallowRef(false)
55
58
  const localFiles = shallowRef<File[]>([])
@@ -61,6 +64,7 @@ export function useFilePicker(
61
64
  () => (source.value === 'localFile' ? localAdapter.value : props.adapter),
62
65
  () => ({ source: source.value }),
63
66
  (node) => props.systemFilter?.(node, source.value) !== false,
67
+ () => sort.value,
64
68
  )
65
69
  const capability = computed(() => props.capabilities[source.value])
66
70
  const selection = usePickerSelection(
@@ -182,6 +186,7 @@ export function useFilePicker(
182
186
  (open) => {
183
187
  clearTimeout(timer)
184
188
  if (open) {
189
+ sort.value = props.defaultSort
185
190
  if (!initialized) {
186
191
  path.value = props.initialPath
187
192
  if (path.value) trail.value = [{ path: path.value, label: 'Current folder' }]
@@ -348,9 +353,10 @@ export function useFilePicker(
348
353
  }
349
354
  async function selectLocalFiles() {
350
355
  const token = openGeneration
351
- const items = props.selectionMode === 'single-file' || props.selectionMode === 'multi-file'
356
+ const found = props.selectionMode === 'single-file' || props.selectionMode === 'multi-file'
352
357
  ? await localAdapter.value.search('', { path: '', recursive: true })
353
358
  : nav.entries.value
359
+ const items = Array.isArray(found) ? found : found.nodes
354
360
  if (token !== openGeneration || !props.open || source.value !== 'localFile') return
355
361
  nav.register(items)
356
362
  const candidates = items.filter((node) => selection.selectable(node))
@@ -411,6 +417,7 @@ export function useFilePicker(
411
417
  source,
412
418
  query,
413
419
  recursive,
420
+ sort,
414
421
  skipBlanks,
415
422
  reviewing,
416
423
  nav,
@@ -37,7 +37,11 @@ export interface UseGroupAssignmentReturn {
37
37
  clearAll: () => GroupAssignmentState
38
38
  }
39
39
 
40
- /** Shared two-zone group assignment model for control/treatment style workflows. */
40
+ /**
41
+ * Shared two-zone group assignment model for control/treatment style workflows.
42
+ *
43
+ * @deprecated Scheduled for removal in MINT 1.4; no SDK replacement.
44
+ */
41
45
  export function useGroupAssignment(options: UseGroupAssignmentOptions): UseGroupAssignmentReturn {
42
46
  const groups = computed(() => [...toValue(options.groups)])
43
47
  const group1 = computed(() => [...toValue(options.group1)])
@@ -1,11 +1,24 @@
1
1
  import type { PickerAdapter } from '../types/filePicker'
2
- import type { FileDirectoryListing, ServerMount } from '../types/fileBrowserTypes'
2
+ import type {
3
+ FileBrowserLocation,
4
+ FileDirectoryListing,
5
+ FileDirectoryTree,
6
+ FileSearchResult,
7
+ ServerMount,
8
+ } from '../types/fileBrowserTypes'
9
+ import type { PickerRequest } from '../types/filePicker'
3
10
  import { useApi } from './useApi'
4
11
  import { getInjectedPlatformContext } from './platformContextHelpers'
5
12
  import { createFilePickerAdapter, type FilePickerAdapterOptions } from './createFilePickerAdapter'
6
13
 
7
14
  export { encodePlatformPickerPath, decodePlatformPickerPath } from './createFilePickerAdapter'
8
15
 
16
+ function query(location: FileBrowserLocation, request?: PickerRequest): URLSearchParams {
17
+ const params = new URLSearchParams({ mount_id: location.mount_id, path: location.path })
18
+ if (request?.refresh) params.set('refresh', 'true')
19
+ return params
20
+ }
21
+
9
22
  /** Adapt the authenticated MINT mount API without exposing absolute host paths. */
10
23
  export function usePlatformFilePickerAdapter(
11
24
  options: FilePickerAdapterOptions & { apiBaseUrl?: string } = {},
@@ -27,11 +40,20 @@ export function usePlatformFilePickerAdapter(
27
40
  }
28
41
  },
29
42
  browse(location, request) {
30
- const query = new URLSearchParams({ mount_id: location.mount_id, path: location.path })
31
- if (request?.refresh) query.set('refresh', 'true')
32
- return api.get<FileDirectoryListing>(`/filesystem/browse?${query}`, {
43
+ return api.get<FileDirectoryListing>(`/filesystem/browse?${query(location, request)}`, {
44
+ signal: request?.signal,
45
+ })
46
+ },
47
+ tree(location, request) {
48
+ return api.get<FileDirectoryTree>(`/filesystem/tree?${query(location, request)}`, {
33
49
  signal: request?.signal,
34
50
  })
35
51
  },
52
+ search(location, text, recursive, request) {
53
+ const params = query(location, request)
54
+ params.set('q', text)
55
+ params.set('recursive', String(recursive))
56
+ return api.get<FileSearchResult>(`/filesystem/search?${params}`, { signal: request?.signal })
57
+ },
36
58
  }, options)
37
59
  }
@@ -72,7 +72,11 @@ export interface UseTemplateCollectionReturn {
72
72
  requireCurrentExperimentId: () => number
73
73
  }
74
74
 
75
- /** Manages a biology template collection in the current experiment's design_data. */
75
+ /**
76
+ * Manages a biology template collection in the current experiment's design_data.
77
+ *
78
+ * @deprecated Scheduled for removal in MINT 1.4; no SDK replacement.
79
+ */
76
80
  export function useTemplateCollection(
77
81
  options: UseTemplateCollectionOptions = {},
78
82
  ): UseTemplateCollectionReturn {
package/src/index.ts CHANGED
@@ -34,7 +34,7 @@ export * from './jobs'
34
34
  // Experimental generated analysis workspace
35
35
  export * from './generated/schema'
36
36
 
37
- // LCMS sequence helpers. Deprecated: scheduled for removal in MINT 1.4 (moves to the mld-ms plugins).
37
+ // LCMS sequence helpers. Deprecated: scheduled for removal in MINT 1.4, no SDK replacement.
38
38
  export * from './lcms'
39
39
 
40
40
  // Utils
package/src/lcms.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import type { LcmsPlateCell, LcmsPlateType } from './utils/rack'
2
2
 
3
- /** @deprecated Scheduled for removal in MINT 1.4; LC-MS helpers move to the mld-ms plugins. */
3
+ /** @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
4
4
  export type LcmsPolarity = 'POS' | 'NEG' | 'BOTH'
5
- /** @deprecated Scheduled for removal in MINT 1.4; LC-MS helpers move to the mld-ms plugins. */
5
+ /** @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
6
6
  export type LcmsContainerType = 'VIAL' | 'PLATE'
7
7
 
8
- /** @deprecated Scheduled for removal in MINT 1.4; LC-MS helpers move to the mld-ms plugins. */
8
+ /** @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
9
9
  export interface LcmsSequenceItem {
10
10
  sample_type: string
11
11
  file_name: string
@@ -16,14 +16,14 @@ export interface LcmsSequenceItem {
16
16
  injection_volume: number
17
17
  }
18
18
 
19
- /** @deprecated Scheduled for removal in MINT 1.4; LC-MS helpers move to the mld-ms plugins. */
19
+ /** @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
20
20
  export interface LcmsSequenceTableColumn {
21
21
  key: keyof LcmsSequenceItem | 'index' | 'actions'
22
22
  label: string
23
23
  align?: 'left' | 'right'
24
24
  }
25
25
 
26
- /** @deprecated Scheduled for removal in MINT 1.4; LC-MS helpers move to the mld-ms plugins. */
26
+ /** @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
27
27
  export const DEFAULT_LCMS_SEQUENCE_COLUMNS: LcmsSequenceTableColumn[] = [
28
28
  { key: 'index', label: '#' },
29
29
  { key: 'sample_type', label: 'Type' },
@@ -33,7 +33,7 @@ export const DEFAULT_LCMS_SEQUENCE_COLUMNS: LcmsSequenceTableColumn[] = [
33
33
  { key: 'injection_volume', label: 'Inj Vol', align: 'right' },
34
34
  ]
35
35
 
36
- /** @deprecated Scheduled for removal in MINT 1.4; LC-MS helpers move to the mld-ms plugins. */
36
+ /** @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
37
37
  export function extractLcmsCommonPrefix(fileNames: readonly string[]): string {
38
38
  if (fileNames.length === 0) return ''
39
39
  const stripped = fileNames.map(fileName => fileName.replace(/_\d{3}$/, ''))
@@ -52,7 +52,7 @@ export function extractLcmsCommonPrefix(fileNames: readonly string[]): string {
52
52
  return common
53
53
  }
54
54
 
55
- /** @deprecated Scheduled for removal in MINT 1.4; LC-MS helpers move to the mld-ms plugins. */
55
+ /** @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
56
56
  export function extractLcmsSampleName(fileName: string, prefix = ''): string {
57
57
  let name = fileName.replace(/_\d{3}$/, '')
58
58
  if (prefix && name.startsWith(prefix)) {
@@ -62,12 +62,12 @@ export function extractLcmsSampleName(fileName: string, prefix = ''): string {
62
62
  return name || fileName
63
63
  }
64
64
 
65
- /** @deprecated Scheduled for removal in MINT 1.4; LC-MS helpers move to the mld-ms plugins. */
65
+ /** @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
66
66
  export function lcmsWellIdFromPosition(position: string): string {
67
67
  return position.includes(':') ? position.split(':').pop() ?? position : position
68
68
  }
69
69
 
70
- /** @deprecated Scheduled for removal in MINT 1.4; LC-MS helpers move to the mld-ms plugins. */
70
+ /** @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
71
71
  export function inferLcmsPlateTypeFromWellIds(wellIds: readonly string[]): LcmsPlateType | null {
72
72
  let maxCol = 0
73
73
  let maxRow = 0
@@ -81,7 +81,7 @@ export function inferLcmsPlateTypeFromWellIds(wellIds: readonly string[]): LcmsP
81
81
  return maxCol <= 9 && maxRow <= 6 ? '54vial' : '96well'
82
82
  }
83
83
 
84
- /** @deprecated Scheduled for removal in MINT 1.4; LC-MS helpers move to the mld-ms plugins. */
84
+ /** @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
85
85
  export function reconstructLcmsPlateCellsFromSequenceItems(
86
86
  items: readonly LcmsSequenceItem[],
87
87
  ): { cells: LcmsPlateCell[]; plateType: LcmsPlateType } | null {
@@ -112,7 +112,7 @@ export function reconstructLcmsPlateCellsFromSequenceItems(
112
112
  return { cells, plateType }
113
113
  }
114
114
 
115
- /** @deprecated Scheduled for removal in MINT 1.4; LC-MS helpers move to the mld-ms plugins. */
115
+ /** @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
116
116
  export function basenameFromWindowsPath(path: string | null | undefined): string {
117
117
  if (!path) return ''
118
118
  return path.split(/[\\/]/).pop() ?? path
@@ -18,3 +18,13 @@
18
18
  min-width: 10rem;
19
19
  max-width: min(18rem, calc(100vw - 1rem));
20
20
  }
21
+
22
+ .mint-action-menu__check {
23
+ flex-shrink: 0;
24
+ color: var(--color-primary);
25
+ }
26
+
27
+ /* Unchecked radio rows keep the check's width so labels stay aligned. */
28
+ .mint-action-menu__check--off {
29
+ visibility: hidden;
30
+ }
@@ -1,5 +1,5 @@
1
1
  /* AppTopBar page selector — left-side route/page dropdown.
2
- Trigger speaks the field language (5a): 32px, hover changes the background
2
+ Trigger speaks the field language (5a): 36px (the identity tile height), hover changes the background
3
3
  only, open = field focus, inline 12px chevron. Menu = .mint-popover +
4
4
  .mint-menu-item (2d); __menu / __item stay as aliases. */
5
5
 
@@ -13,8 +13,8 @@
13
13
  align-items: center;
14
14
  gap: 0.5rem;
15
15
  width: 100%;
16
- height: 2rem;
17
- padding: 0 0.5rem 0 0.3125rem;
16
+ height: 2.25rem;
17
+ padding: 0 0.5rem 0 0.4375rem;
18
18
  border: 1px solid var(--border-color);
19
19
  background: var(--bg-card);
20
20
  color: var(--text-primary);
@@ -21,7 +21,7 @@
21
21
  display: inline-flex;
22
22
  align-items: center;
23
23
  gap: 0.375rem;
24
- height: 1.625rem;
24
+ height: 1.75rem;
25
25
  border: 0;
26
26
  padding: 0 0.875rem;
27
27
  border-radius: 9999px;
@@ -9,7 +9,7 @@
9
9
  .mint-topbar {
10
10
  display: block;
11
11
  width: 100%;
12
- padding: 0.625rem 0.75rem;
12
+ padding: 0.75rem 1rem;
13
13
  background-color: var(--bg-secondary);
14
14
  box-sizing: border-box;
15
15
  }
@@ -19,7 +19,7 @@
19
19
  display: flex;
20
20
  align-items: center;
21
21
  gap: 0.5rem;
22
- min-height: 2rem;
22
+ min-height: 2.375rem;
23
23
  position: relative;
24
24
  }
25
25
 
@@ -31,35 +31,28 @@
31
31
  }
32
32
 
33
33
  .mint-topbar__identity {
34
- width: 2rem;
35
- height: 2rem;
34
+ width: 2.25rem;
35
+ height: 2.25rem;
36
36
  display: inline-flex;
37
37
  align-items: center;
38
38
  justify-content: center;
39
39
  flex-shrink: 0;
40
40
  }
41
41
 
42
- /* The 36px plugin tile would push the bar past 52px; the bar uses the 32px control height. */
43
- .mint-topbar__identity .mint-plugin-icon--topbar {
44
- width: 2rem;
45
- height: 2rem;
42
+ /* Slotted logos sized above 36px shrink to fit instead of stretching the tile. */
43
+ .mint-topbar__identity > * {
44
+ max-width: 100%;
45
+ max-height: 100%;
46
46
  }
47
47
 
48
- /* Integrated: the tile joins the static identity as a 20px mark (icon + name + version). */
49
- .mint-topbar__brand:has(+ .mint-topbar__plugin-identity) .mint-topbar__identity {
50
- width: auto;
51
- padding-left: 0.125rem;
48
+ /* Left and right fields share the 36px identity tile height. */
49
+ .mint-topbar .mint-experiment-popover__trigger,
50
+ .mint-topbar .mint-experiment-popover__save-trigger {
51
+ height: 2.25rem;
52
52
  }
53
53
 
54
- .mint-topbar__brand:has(+ .mint-topbar__plugin-identity) .mint-plugin-icon--topbar {
55
- width: 1.25rem;
56
- height: 1.25rem;
57
- border-radius: var(--radius-sm);
58
- }
59
-
60
- .mint-topbar__brand:has(+ .mint-topbar__plugin-identity) .mint-plugin-icon--topbar :is(.mint-plugin-icon__svg, .mint-plugin-icon__img) {
61
- width: 0.75rem;
62
- height: 0.75rem;
54
+ .mint-topbar .mint-experiment-popover__save-trigger {
55
+ width: 2.25rem;
63
56
  }
64
57
 
65
58
  /* Centered section — absolute so asymmetric left/right weight never shifts the
@@ -98,8 +91,8 @@
98
91
  }
99
92
 
100
93
  .mint-topbar__logo-icon {
101
- width: 2rem;
102
- height: 2rem;
94
+ width: 2.25rem;
95
+ height: 2.25rem;
103
96
  background-color: var(--color-primary);
104
97
  border-radius: var(--radius-md);
105
98
  display: flex;
@@ -118,7 +111,7 @@
118
111
  color: var(--text-primary);
119
112
  }
120
113
 
121
- /* Static plugin identity: name + mono version, not a control (5a) */
114
+ /* Static plugin identity: name only, not a control (5a) */
122
115
  .mint-topbar__plugin-identity {
123
116
  display: inline-flex;
124
117
  align-items: baseline;
@@ -136,19 +129,6 @@
136
129
  text-overflow: ellipsis;
137
130
  }
138
131
 
139
- .mint-topbar__plugin-version {
140
- font-family: var(--font-mono);
141
- font-size: 0.6875rem;
142
- color: var(--text-secondary);
143
- }
144
-
145
- .mint-topbar__divider {
146
- width: 1px;
147
- height: 1.25rem;
148
- flex-shrink: 0;
149
- background-color: var(--border-color);
150
- }
151
-
152
132
  /* Variant: card - inline card with margins and rounded corners */
153
133
  .mint-topbar--card {
154
134
  width: calc(100% - 2rem);
@@ -175,7 +155,7 @@
175
155
  opacity: 0.8;
176
156
  }
177
157
 
178
- /* Title + subtitle stay inside the 32px control row (5a: 52px bar). */
158
+ /* Title + subtitle stay inside the 36px control row. */
179
159
  .mint-topbar-title-group {
180
160
  display: flex;
181
161
  flex-direction: column;
@@ -115,8 +115,9 @@
115
115
  color: var(--text-muted);
116
116
  }
117
117
 
118
- /* Action */
119
- .mint-empty-state--illustrated .mint-empty-state__action {
118
+ /* Action — slotted content sits in a block so a child's own larger top margin collapses into this one. */
119
+ .mint-empty-state--illustrated .mint-empty-state__action,
120
+ .mint-empty-state--illustrated .mint-empty-state__content {
120
121
  margin-top: 0.625rem;
121
122
  }
122
123
 
@@ -5,6 +5,7 @@
5
5
  align-items: center;
6
6
  gap: 0.5rem;
7
7
  flex-wrap: wrap;
8
+ padding: 0 1.25rem;
8
9
  }
9
10
 
10
11
  .mint-experiment-selector__filter-select {
@@ -65,14 +66,6 @@ html.dark .mint-experiment-selector__filters-toggle--active {
65
66
  flex-shrink: 0;
66
67
  }
67
68
 
68
- /* Advanced filters row */
69
- .mint-experiment-selector__filters-advanced {
70
- padding: 0.625rem;
71
- border: 1px solid var(--border-light);
72
- border-radius: var(--radius-md);
73
- background-color: color-mix(in srgb, var(--bg-secondary) 72%, transparent);
74
- }
75
-
76
69
  /* Group toggle checkbox label */
77
70
  .mint-experiment-selector__group-toggle {
78
71
  display: inline-flex;
@@ -103,7 +96,8 @@ html.dark .mint-experiment-selector__filters-toggle--active {
103
96
  .mint-experiment-selector__footer {
104
97
  display: flex;
105
98
  justify-content: flex-start;
106
- padding-top: 0.25rem;
99
+ padding: 0.5rem 1.25rem 0.75rem;
100
+ border-top: 1px solid var(--border-light);
107
101
  }
108
102
 
109
103
  .mint-experiment-selector__clear-btn {
@@ -106,6 +106,7 @@
106
106
  white-space: nowrap;
107
107
  }
108
108
  .mint-picker__scope,
109
+ .mint-picker__sort,
109
110
  .mint-picker__link {
110
111
  padding: 2px 6px;
111
112
  border: 0;
@@ -116,10 +117,20 @@
116
117
  cursor: pointer;
117
118
  transition: background-color 150ms ease;
118
119
  }
119
- .mint-picker__scope {
120
+ .mint-picker__scope,
121
+ .mint-picker__sort {
120
122
  flex-shrink: 0;
121
123
  color: var(--text-secondary-strong);
122
124
  }
125
+ .mint-picker__sort {
126
+ display: inline-flex;
127
+ align-items: center;
128
+ gap: 2px;
129
+ }
130
+ .mint-picker__sort svg {
131
+ width: 12px;
132
+ height: 12px;
133
+ }
123
134
  .mint-picker__link {
124
135
  color: var(--_ink-primary);
125
136
  }
@@ -138,10 +149,13 @@
138
149
  cursor: not-allowed;
139
150
  }
140
151
  .mint-picker__scope:hover,
152
+ .mint-picker__sort:hover,
153
+ .mint-picker__sort[aria-expanded='true'],
141
154
  .mint-picker__link:hover {
142
155
  background: var(--bg-hover);
143
156
  }
144
157
  .mint-picker__scope:focus-visible,
158
+ .mint-picker__sort:focus-visible,
145
159
  .mint-picker__link:focus-visible {
146
160
  outline: none;
147
161
  box-shadow: var(--focus-ring-offset);
@@ -185,6 +199,14 @@
185
199
  .mint-picker__list-head > span:nth-child(n + 3) {
186
200
  text-align: right;
187
201
  }
202
+ .mint-picker__truncated {
203
+ margin: 0;
204
+ padding: 6px 12px;
205
+ border-bottom: 1px solid var(--border-light);
206
+ background: var(--bg-secondary);
207
+ font-size: 12px;
208
+ color: var(--text-secondary);
209
+ }
188
210
  .mint-picker__row {
189
211
  box-sizing: border-box;
190
212
  height: 34px;