@morscherlab/mint-sdk 1.3.0-beta.5 → 1.3.0-beta.6
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.
- package/dist/components/index.d.ts +3 -3
- package/dist/components/index.js +2 -2
- package/dist/{components-BTzcqrJp.js → components-C-CAD2Ma.js} +4 -4
- package/dist/components-C-CAD2Ma.js.map +1 -0
- package/dist/composables/index.js +3 -3
- package/dist/composables/usePlatformContext.d.ts +3 -0
- package/dist/{composables-Doqb7g1z.js → composables-BKhsoONv.js} +3 -3
- package/dist/{composables-Doqb7g1z.js.map → composables-BKhsoONv.js.map} +1 -1
- package/dist/index.js +4 -4
- package/dist/install.js +1 -1
- package/dist/styles.css +22 -55
- package/dist/templates/index.js +1 -1
- package/dist/{templates-DgAG5kMq.js → templates-DcxyATPT.js} +30 -43
- package/dist/templates-DcxyATPT.js.map +1 -0
- package/dist/types/platform.d.ts +2 -0
- package/dist/{validation-DILksa0c.js → validation-kbTxfKYD.js} +2 -2
- package/dist/{validation-DILksa0c.js.map → validation-kbTxfKYD.js.map} +1 -1
- package/package.json +1 -1
- package/src/__tests__/components/AppTopBar.test.ts +8 -0
- package/src/__tests__/components/FileUploader.test.ts +6 -9
- package/src/__tests__/templates/templatesDeprecation.test.ts +8 -1
- package/src/components/AppTopBar.vue +4 -1
- package/src/components/FileUploader.vue +30 -46
- package/src/components/index.ts +3 -3
- package/src/styles/components/file-uploader.css +22 -55
- package/src/types/platform.ts +2 -0
- package/dist/components-BTzcqrJp.js.map +0 -1
- package/dist/templates-DgAG5kMq.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morscherlab/mint-sdk",
|
|
3
|
-
"version": "1.3.0-beta.
|
|
3
|
+
"version": "1.3.0-beta.6",
|
|
4
4
|
"description": "MINT Platform SDK — Vue 3 components, composables, and types for plugin development. MINT = Mass-spec INtegrated Toolkit.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -1211,6 +1211,14 @@ describe('AppTopBar', () => {
|
|
|
1211
1211
|
expect(wrapper.get('.mint-topbar__plugin-name').text()).toBe('LC-MS Analysis')
|
|
1212
1212
|
})
|
|
1213
1213
|
|
|
1214
|
+
it('should render the platform display name when integrated', () => {
|
|
1215
|
+
mockPlatformCtx({ isIntegrated: true, plugin: { ...integratedPlugin, display_name: 'LC-MS Peak Review' } })
|
|
1216
|
+
|
|
1217
|
+
const wrapper = createWrapper()
|
|
1218
|
+
|
|
1219
|
+
expect(wrapper.get('.mint-topbar__plugin-name').text()).toBe('LC-MS Peak Review')
|
|
1220
|
+
})
|
|
1221
|
+
|
|
1214
1222
|
it('should not render the plugin version when integrated', () => {
|
|
1215
1223
|
mockPlatformCtx({ isIntegrated: true, plugin: integratedPlugin })
|
|
1216
1224
|
|
|
@@ -3,16 +3,13 @@ import { describe, expect, it } from 'vitest'
|
|
|
3
3
|
import FileUploader from '../../components/FileUploader.vue'
|
|
4
4
|
|
|
5
5
|
describe('FileUploader', () => {
|
|
6
|
-
it('should
|
|
7
|
-
const wrapper = mount(FileUploader, { props: {
|
|
8
|
-
|
|
9
|
-
dataTransfer: { items: { length: 3 } },
|
|
10
|
-
})
|
|
11
|
-
expect(wrapper.get('.mint-file-uploader__text').text()).toBe('Release to add 3 files')
|
|
6
|
+
it('should name the accepted formats in the prompt when accept is set', () => {
|
|
7
|
+
const wrapper = mount(FileUploader, { props: { accept: '.raw, .mzML' } })
|
|
8
|
+
expect(wrapper.get('.mint-file-uploader__text').text()).toBe('Drop RAW, MZML or click')
|
|
12
9
|
})
|
|
13
10
|
|
|
14
|
-
it('should
|
|
15
|
-
const wrapper = mount(FileUploader
|
|
16
|
-
expect(wrapper.get('.mint-file-
|
|
11
|
+
it('should prompt for any file when accept is not set', () => {
|
|
12
|
+
const wrapper = mount(FileUploader)
|
|
13
|
+
expect(wrapper.get('.mint-file-uploader__text').text()).toBe('Drop any file or click')
|
|
17
14
|
})
|
|
18
15
|
})
|
|
@@ -53,12 +53,19 @@ function undeprecatedValueExports(file: string): string[] {
|
|
|
53
53
|
|
|
54
54
|
describe('templates deprecation', () => {
|
|
55
55
|
it('should expose deprecated component tags to TypeScript consumers', () => {
|
|
56
|
-
const names = ['BioTemplateRenderer', 'SmartGroupModal', '
|
|
56
|
+
const names = ['BioTemplateRenderer', 'SmartGroupModal', 'DoseDesignWorkspaceView']
|
|
57
57
|
const tagged = exportsOf(COMPONENTS_INDEX).filter(isDeprecated).map(symbol => symbol.getName())
|
|
58
58
|
|
|
59
59
|
expect(names.filter(name => !tagged.includes(name))).toEqual([])
|
|
60
60
|
})
|
|
61
61
|
|
|
62
|
+
it('should not tag components that stay public in MINT 1.4', () => {
|
|
63
|
+
const names = ['SampleSelector', 'SequenceProgressBar', 'InstrumentStateBadge']
|
|
64
|
+
const tagged = exportsOf(COMPONENTS_INDEX).filter(isDeprecated).map(symbol => symbol.getName())
|
|
65
|
+
|
|
66
|
+
expect(names.filter(name => tagged.includes(name))).toEqual([])
|
|
67
|
+
})
|
|
68
|
+
|
|
62
69
|
it('should tag every template value export when the templates move out in MINT 1.4', () => {
|
|
63
70
|
expect(undeprecatedValueExports(TEMPLATES_INDEX)).toEqual([])
|
|
64
71
|
})
|
|
@@ -145,7 +145,10 @@ const hasPlatformPageSelector = computed(() =>
|
|
|
145
145
|
)
|
|
146
146
|
const hasPageSelector = computed(() => (props.pageSelector?.length ?? 0) > 1 || hasPlatformPageSelector.value)
|
|
147
147
|
/** Integrated plugins show their name as a static identity in place of the title; the page selector replaces it. */
|
|
148
|
-
|
|
148
|
+
// Platforms before 1.3 send no display_name.
|
|
149
|
+
const identityName = computed(() =>
|
|
150
|
+
isIntegrated.value && !hasPageSelector.value ? plugin.value?.display_name || plugin.value?.name : undefined,
|
|
151
|
+
)
|
|
149
152
|
const hasPillNav = computed(() => !!props.pillNav?.length)
|
|
150
153
|
const hasAccountMenu = computed(() => !!props.accountMenu?.length)
|
|
151
154
|
const hasTitleGroup = computed(
|
|
@@ -31,7 +31,6 @@ const emit = defineEmits<{
|
|
|
31
31
|
}>()
|
|
32
32
|
|
|
33
33
|
const isDragOver = ref(false)
|
|
34
|
-
const dragCount = ref(0)
|
|
35
34
|
const inputRef = ref<HTMLInputElement>()
|
|
36
35
|
const selectedFiles = ref<File[]>([])
|
|
37
36
|
const folderName = ref<string | null>(null)
|
|
@@ -45,14 +44,9 @@ watch(() => [props.files, props.rootName] as const, ([files, rootName]) => {
|
|
|
45
44
|
const isFolder = computed(() => props.mode === 'folder')
|
|
46
45
|
const isMixed = computed(() => props.mode === 'file+folder')
|
|
47
46
|
|
|
48
|
-
const
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
return `Release to add ${dragCount.value} file${dragCount.value === 1 ? '' : 's'}`
|
|
52
|
-
}
|
|
53
|
-
if (isMixed.value) return 'Drop files or a folder, or click to choose files'
|
|
54
|
-
if (isFolder.value) return 'Drop a folder, or click to choose'
|
|
55
|
-
return props.multiple ? 'Drop files, or click to choose' : 'Drop a file, or click to choose'
|
|
47
|
+
const acceptLabel = computed(() => {
|
|
48
|
+
if (!props.accept) return isFolder.value ? 'a folder' : 'any file'
|
|
49
|
+
return props.accept.split(',').map(a => a.trim().replace('.', '').toUpperCase()).join(', ')
|
|
56
50
|
})
|
|
57
51
|
|
|
58
52
|
const maxSizeLabel = computed(() => {
|
|
@@ -69,12 +63,6 @@ const maxSizeLabel = computed(() => {
|
|
|
69
63
|
return `${props.maxSize} bytes`
|
|
70
64
|
})
|
|
71
65
|
|
|
72
|
-
/** Accepted formats exactly as the caller wrote them, plus the size cap. */
|
|
73
|
-
const formatsLabel = computed(() => [
|
|
74
|
-
props.accept?.split(',').map(a => a.trim()).filter(Boolean).join(' '),
|
|
75
|
-
maxSizeLabel.value && `max ${maxSizeLabel.value}`,
|
|
76
|
-
].filter(Boolean).join(' · '))
|
|
77
|
-
|
|
78
66
|
const fileTypeMap: Record<string, { color: string; label: string }> = {
|
|
79
67
|
csv: { color: '#10B981', label: 'CSV' },
|
|
80
68
|
tsv: { color: '#10B981', label: 'TSV' },
|
|
@@ -272,7 +260,6 @@ function handleDragOver(event: DragEvent) {
|
|
|
272
260
|
event.preventDefault()
|
|
273
261
|
if (!props.disabled) {
|
|
274
262
|
isDragOver.value = true
|
|
275
|
-
dragCount.value = event.dataTransfer?.items?.length ?? 0
|
|
276
263
|
}
|
|
277
264
|
}
|
|
278
265
|
|
|
@@ -359,37 +346,34 @@ function formatFileSize(bytes: number): string {
|
|
|
359
346
|
/>
|
|
360
347
|
|
|
361
348
|
<div class="mint-file-uploader__content">
|
|
362
|
-
<
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
</svg>
|
|
387
|
-
</span>
|
|
349
|
+
<svg
|
|
350
|
+
v-if="isFolder"
|
|
351
|
+
class="mint-file-uploader__icon"
|
|
352
|
+
fill="none"
|
|
353
|
+
stroke="currentColor"
|
|
354
|
+
stroke-width="1.5"
|
|
355
|
+
stroke-linecap="round"
|
|
356
|
+
stroke-linejoin="round"
|
|
357
|
+
viewBox="0 0 24 24"
|
|
358
|
+
>
|
|
359
|
+
<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" />
|
|
360
|
+
</svg>
|
|
361
|
+
<svg
|
|
362
|
+
v-else
|
|
363
|
+
class="mint-file-uploader__icon"
|
|
364
|
+
fill="none"
|
|
365
|
+
stroke="currentColor"
|
|
366
|
+
stroke-width="1.5"
|
|
367
|
+
stroke-linecap="round"
|
|
368
|
+
stroke-linejoin="round"
|
|
369
|
+
viewBox="0 0 24 24"
|
|
370
|
+
>
|
|
371
|
+
<path d="M20.39 18.39A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.3" /><path d="m16 16-4-4-4 4" /><path d="M12 12v9" />
|
|
372
|
+
</svg>
|
|
388
373
|
|
|
389
|
-
<
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
</div>
|
|
374
|
+
<p class="mint-file-uploader__text">
|
|
375
|
+
{{ isMixed ? 'Drop files or a folder, or click to choose files' : `Drop ${acceptLabel} or click` }}
|
|
376
|
+
</p>
|
|
393
377
|
</div>
|
|
394
378
|
</div>
|
|
395
379
|
|
package/src/components/index.ts
CHANGED
|
@@ -86,8 +86,8 @@ export { /** @deprecated Removed in MINT 1.4. */ default as SampleLegend } from
|
|
|
86
86
|
export { /** @deprecated Removed in MINT 1.4. */ default as ExperimentTimeline } from './ExperimentTimeline.vue'
|
|
87
87
|
|
|
88
88
|
// Sample management components
|
|
89
|
-
/** Interactive sample list with drag-and-drop group assignment, color labeling, and smart-group support.
|
|
90
|
-
export {
|
|
89
|
+
/** Interactive sample list with drag-and-drop group assignment, color labeling, and smart-group support. */
|
|
90
|
+
export { default as SampleSelector } from './SampleSelector.vue'
|
|
91
91
|
/** Smart Group modal wired to the `useAutoGroup` engine. @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
|
|
92
92
|
export { /** @deprecated Removed in MINT 1.4. */ default as AutoGroupModal } from './AutoGroupModal.vue'
|
|
93
93
|
/** Drag-and-drop two-zone assigner for splitting sample groups into control and treatment arms. @deprecated Scheduled for removal in MINT 1.4; no SDK replacement. */
|
|
@@ -114,7 +114,7 @@ export { default as ProtocolStepEditor } from './ProtocolStepEditor.vue'
|
|
|
114
114
|
export { default as PlotlyChart } from './PlotlyChart.vue'
|
|
115
115
|
export { default as ScientificNumber } from './ScientificNumber.vue'
|
|
116
116
|
export { default as ChemicalFormula } from './ChemicalFormula.vue'
|
|
117
|
-
/** Displays LC/MS or GC/MS acquisition sequence progress with ETA and remaining-time labels.
|
|
117
|
+
/** Displays LC/MS or GC/MS acquisition sequence progress with ETA and remaining-time labels. */
|
|
118
118
|
export { default as SequenceProgressBar } from './SequenceProgressBar.vue'
|
|
119
119
|
/** Status badge for instrument states: a tone dot (or dash / hollow shape for offline, never-reported and inactive) plus a label. */
|
|
120
120
|
export { default as InstrumentStateBadge } from './InstrumentStateBadge.vue'
|
|
@@ -14,113 +14,80 @@
|
|
|
14
14
|
|
|
15
15
|
.mint-file-uploader__dropzone {
|
|
16
16
|
position: relative;
|
|
17
|
-
border:
|
|
17
|
+
border: 2px dashed var(--border-color);
|
|
18
18
|
border-radius: var(--radius-lg);
|
|
19
19
|
cursor: pointer;
|
|
20
20
|
background: var(--bg-secondary);
|
|
21
21
|
transition: border-color 0.15s ease, background-color 0.15s ease;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/* 2g: hover only changes the surface; the border change is reserved for dragover. */
|
|
25
24
|
.mint-file-uploader__dropzone:hover {
|
|
26
|
-
|
|
25
|
+
border-color: var(--color-primary);
|
|
26
|
+
background: color-mix(in srgb, var(--color-primary) 3%, var(--bg-secondary));
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
.mint-file-uploader__dropzone:focus-visible {
|
|
30
|
-
outline:
|
|
31
|
-
|
|
30
|
+
outline: 2px solid var(--color-primary);
|
|
31
|
+
outline-offset: 2px;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
.mint-file-uploader__dropzone--dragover
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
background: var(--color-primary-soft);
|
|
34
|
+
.mint-file-uploader__dropzone--dragover {
|
|
35
|
+
border-color: var(--color-primary);
|
|
36
|
+
background: color-mix(in srgb, var(--color-primary) 5%, var(--bg-secondary));
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
.mint-file-uploader__dropzone--disabled
|
|
41
|
-
.mint-file-uploader__dropzone--disabled:hover {
|
|
42
|
-
background: var(--bg-tertiary);
|
|
39
|
+
.mint-file-uploader__dropzone--disabled {
|
|
43
40
|
opacity: var(--mint-disabled-opacity);
|
|
44
41
|
cursor: not-allowed;
|
|
45
42
|
}
|
|
46
43
|
|
|
47
44
|
.mint-file-uploader__dropzone--sm {
|
|
48
|
-
padding:
|
|
45
|
+
padding: 1.25rem;
|
|
49
46
|
}
|
|
50
47
|
|
|
51
48
|
.mint-file-uploader__dropzone--md {
|
|
52
|
-
padding: 1.
|
|
49
|
+
padding: 1.5rem;
|
|
53
50
|
}
|
|
54
51
|
|
|
55
52
|
.mint-file-uploader__dropzone--lg {
|
|
56
|
-
padding:
|
|
53
|
+
padding: 2rem;
|
|
57
54
|
}
|
|
58
55
|
|
|
59
56
|
/* ==========================================================================
|
|
60
|
-
Content area
|
|
57
|
+
Content area
|
|
61
58
|
========================================================================== */
|
|
62
59
|
|
|
63
60
|
.mint-file-uploader__content {
|
|
64
61
|
display: flex;
|
|
62
|
+
flex-direction: column;
|
|
65
63
|
align-items: center;
|
|
66
|
-
|
|
64
|
+
text-align: center;
|
|
67
65
|
}
|
|
68
66
|
|
|
69
67
|
.mint-file-uploader__input {
|
|
70
68
|
display: none;
|
|
71
69
|
}
|
|
72
70
|
|
|
73
|
-
.mint-file-uploader__icon
|
|
74
|
-
display: flex;
|
|
75
|
-
align-items: center;
|
|
76
|
-
justify-content: center;
|
|
77
|
-
flex-shrink: 0;
|
|
71
|
+
.mint-file-uploader__icon {
|
|
78
72
|
width: 2rem;
|
|
79
73
|
height: 2rem;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
color: var(--text-secondary);
|
|
83
|
-
transition: background-color 0.15s ease, color 0.15s ease;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.mint-file-uploader__dropzone--dragover .mint-file-uploader__icon-tile {
|
|
87
|
-
background: var(--color-primary);
|
|
88
|
-
color: white;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
.mint-file-uploader__icon {
|
|
92
|
-
width: 1rem;
|
|
93
|
-
height: 1rem;
|
|
94
|
-
stroke-width: 1.8;
|
|
74
|
+
color: var(--text-muted);
|
|
75
|
+
margin-bottom: 0.5rem;
|
|
95
76
|
}
|
|
96
77
|
|
|
97
|
-
.mint-file-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
gap: 0.125rem;
|
|
101
|
-
min-width: 0;
|
|
78
|
+
.mint-file-uploader__dropzone:hover .mint-file-uploader__icon,
|
|
79
|
+
.mint-file-uploader__dropzone--dragover .mint-file-uploader__icon {
|
|
80
|
+
color: var(--color-primary);
|
|
102
81
|
}
|
|
103
82
|
|
|
104
83
|
.mint-file-uploader__text {
|
|
105
|
-
color: var(--text-
|
|
84
|
+
color: var(--text-secondary);
|
|
106
85
|
font-size: 0.8125rem;
|
|
107
86
|
font-weight: 500;
|
|
108
87
|
margin: 0;
|
|
109
88
|
padding: 0;
|
|
110
89
|
}
|
|
111
90
|
|
|
112
|
-
.mint-file-uploader__dropzone--dragover .mint-file-uploader__text {
|
|
113
|
-
color: var(--_ink-primary);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.mint-file-uploader__formats {
|
|
117
|
-
color: var(--text-secondary);
|
|
118
|
-
font-family: var(--font-mono);
|
|
119
|
-
font-size: 0.6875rem;
|
|
120
|
-
margin: 0;
|
|
121
|
-
padding: 0;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
91
|
/* ==========================================================================
|
|
125
92
|
Actions slot
|
|
126
93
|
========================================================================== */
|
package/src/types/platform.ts
CHANGED
|
@@ -4,6 +4,8 @@ import type { RoleInfo } from '../permissions'
|
|
|
4
4
|
export interface PluginInfo {
|
|
5
5
|
id: string
|
|
6
6
|
name: string
|
|
7
|
+
/** Name to show in the UI; the platform falls back to the plugin ID. Absent before MINT 1.3. */
|
|
8
|
+
display_name?: string
|
|
7
9
|
version: string
|
|
8
10
|
plugin_type?: string
|
|
9
11
|
description?: string
|