@morscherlab/mint-sdk 1.2.0-beta.9 → 1.2.0
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/README.md +30 -0
- package/dist/{ExperimentPopover-oL0fg_A0.js → ExperimentPopover-CJdNlCZb.js} +21 -14
- package/dist/ExperimentPopover-CJdNlCZb.js.map +1 -0
- package/dist/{ExperimentSelectorModal-BeEOomw_.js → ExperimentSelectorModal-DCXmwKNS.js} +5 -5
- package/dist/{ExperimentSelectorModal-BeEOomw_.js.map → ExperimentSelectorModal-DCXmwKNS.js.map} +1 -1
- package/dist/{SettingsModal-Dphh3RrI.js → SettingsModal-BYR20I4c.js} +5 -5
- package/dist/{SettingsModal-Dphh3RrI.js.map → SettingsModal-BYR20I4c.js.map} +1 -1
- package/dist/{Skeleton-DxtwJ5gt.js → Skeleton-BAF3CKY7.js} +3 -3
- package/dist/{Skeleton-DxtwJ5gt.js.map → Skeleton-BAF3CKY7.js.map} +1 -1
- package/dist/__tests__/apiErrors.test.d.ts +1 -0
- package/dist/__tests__/components/FileBrowserModal.test.d.ts +1 -0
- package/dist/__tests__/components/FilePicker.state.test.d.ts +1 -0
- package/dist/__tests__/components/FilePicker.test.d.ts +1 -0
- package/dist/__tests__/components/PlotlyChart.test.d.ts +1 -0
- package/dist/__tests__/components/iconButtonIconSizing.test.d.ts +1 -0
- package/dist/__tests__/composables/useFileBrowser.test.d.ts +1 -0
- package/dist/__tests__/composables/usePlatformFilePickerAdapter.test.d.ts +1 -0
- package/dist/apiErrors.d.ts +26 -0
- package/dist/components/BaseInput.vue.d.ts +1 -1
- package/dist/components/BaseSelect.vue.d.ts +1 -1
- package/dist/components/BaseTextarea.vue.d.ts +1 -1
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +2 -2
- package/dist/components/ConcentrationInput.vue.d.ts +1 -1
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/DateTimePicker.vue.d.ts +1 -1
- package/dist/components/FileBrowserModal.vue.d.ts +99 -0
- package/dist/components/FilePicker.vue.d.ts +32 -0
- package/dist/components/FileUploader.vue.d.ts +5 -2
- package/dist/components/FormulaInput.vue.d.ts +1 -1
- package/dist/components/GeneratedPlotlyResult.vue.d.ts +1 -3
- package/dist/components/MobileSupportGate.vue.d.ts +1 -1
- package/dist/components/MoleculeInput.vue.d.ts +1 -1
- package/dist/components/NumberInput.vue.d.ts +1 -1
- package/dist/components/PlotlyChart.vue.d.ts +59 -0
- package/dist/components/ResourceCard.vue.d.ts +1 -1
- package/dist/components/SecretInput.vue.d.ts +1 -1
- package/dist/components/SequenceInput.vue.d.ts +1 -1
- package/dist/components/StatusIndicator.vue.d.ts +1 -1
- package/dist/components/TagsInput.vue.d.ts +1 -1
- package/dist/components/TimePicker.vue.d.ts +1 -1
- package/dist/components/TimeRangeInput.vue.d.ts +1 -1
- package/dist/components/UnitInput.vue.d.ts +1 -1
- package/dist/components/WellPlate.vue.d.ts +1 -1
- package/dist/components/fileBrowserPresentation.d.ts +10 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +8 -8
- package/dist/components/internal/FileBrowserDialogInternal.vue.d.ts +34 -0
- package/dist/components/internal/FileBrowserListingInternal.vue.d.ts +25 -0
- package/dist/components/internal/FileBrowserToolbarInternal.vue.d.ts +26 -0
- package/dist/components/internal/FilePickerPreviewInternal.vue.d.ts +18 -0
- package/dist/components/internal/FilePickerTreeInternal.vue.d.ts +31 -0
- package/dist/{components-CgAUzF8F.js → components-DIum5hkx.js} +4286 -1866
- package/dist/components-DIum5hkx.js.map +1 -0
- package/dist/composables/filePicker/localFiles.d.ts +3 -0
- package/dist/composables/filePicker/usePickerNavigation.d.ts +96 -0
- package/dist/composables/filePicker/usePickerSelection.d.ts +31 -0
- package/dist/composables/filePicker/validation.d.ts +5 -0
- package/dist/composables/index.d.ts +2 -0
- package/dist/composables/index.js +10 -10
- package/dist/composables/useApi.d.ts +14 -7
- package/dist/composables/useFileBrowser.d.ts +55 -0
- package/dist/composables/useFilePicker.d.ts +189 -0
- package/dist/composables/usePlatformFilePickerAdapter.d.ts +11 -0
- package/dist/{composables-B_pia3hO.js → composables-mFXsTA4g.js} +300 -11
- package/dist/composables-mFXsTA4g.js.map +1 -0
- package/dist/{errors-_W0-LbA6.js → errors-BLuqMee5.js} +78 -15
- package/dist/errors-BLuqMee5.js.map +1 -0
- package/dist/{experiment-Cwl9AYxw.js → experiment-CVDRAnqp.js} +2 -2
- package/dist/{experiment-Cwl9AYxw.js.map → experiment-CVDRAnqp.js.map} +1 -1
- package/dist/{experiment-utils-DV3DrvE_.js → experiment-utils-CV2Wza3z.js} +1 -1
- package/dist/{experiment-utils-DV3DrvE_.js.map → experiment-utils-CV2Wza3z.js.map} +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -15
- package/dist/install.js +2 -2
- package/dist/stores/index.js +2 -2
- package/dist/styles.css +2369 -1377
- package/dist/templates/index.js +2 -2
- package/dist/{templates-Qq113pyZ.js → templates-CmGfmBRA.js} +2 -2
- package/dist/{templates-Qq113pyZ.js.map → templates-CmGfmBRA.js.map} +1 -1
- package/dist/types/fileBrowserTypes.d.ts +77 -0
- package/dist/types/filePicker.d.ts +77 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/{useControlSchema-aMZlb4Sc.js → useControlSchema-DldpxNOP.js} +42 -37
- package/dist/useControlSchema-DldpxNOP.js.map +1 -0
- package/dist/{useDropdownState-DitCtrTT.js → useDropdownState-C7hRiVQf.js} +2 -2
- package/dist/{useDropdownState-DitCtrTT.js.map → useDropdownState-C7hRiVQf.js.map} +1 -1
- package/dist/{useExperimentSelector-I8HC8hUu.js → useExperimentSelector-CEcIaueJ.js} +4 -4
- package/dist/{useExperimentSelector-I8HC8hUu.js.map → useExperimentSelector-CEcIaueJ.js.map} +1 -1
- package/dist/{useFormBuilder-TCxNnqeb.js → useFormBuilder-z5L_dUIy.js} +2 -2
- package/dist/{useFormBuilder-TCxNnqeb.js.map → useFormBuilder-z5L_dUIy.js.map} +1 -1
- package/dist/{useProtocolTemplates-BmX_iVBR.js → validation-uwoJGEb6.js} +53 -8
- package/dist/validation-uwoJGEb6.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/apiErrors.test.ts +81 -0
- package/src/__tests__/components/ExperimentPopover.test.ts +30 -0
- package/src/__tests__/components/FileBrowserModal.test.ts +460 -0
- package/src/__tests__/components/FilePicker.state.test.ts +287 -0
- package/src/__tests__/components/FilePicker.test.ts +487 -0
- package/src/__tests__/components/GeneratedPlotlyResult.test.ts +52 -5
- package/src/__tests__/components/PlotlyChart.test.ts +305 -0
- package/src/__tests__/components/SegmentedControl.test.ts +19 -0
- package/src/__tests__/components/iconButtonIconSizing.test.ts +18 -0
- package/src/__tests__/composables/useApi.test.ts +92 -9
- package/src/__tests__/composables/useFileBrowser.test.ts +305 -0
- package/src/__tests__/composables/useGeneratedAnalysis.test.ts +7 -2
- package/src/__tests__/composables/usePlatformFilePickerAdapter.test.ts +67 -0
- package/src/__tests__/composables/usePluginClient.test.ts +3 -0
- package/src/apiErrors.ts +85 -0
- package/src/components/ExperimentPopover.vue +10 -2
- package/src/components/FileBrowserModal.story.vue +203 -0
- package/src/components/FileBrowserModal.vue +384 -0
- package/src/components/FilePicker.story.vue +44 -0
- package/src/components/FilePicker.vue +284 -0
- package/src/components/FileUploader.vue +32 -14
- package/src/components/GeneratedPlotlyResult.vue +34 -69
- package/src/components/GeneratedResultRenderer.vue +0 -5
- package/src/components/PlotlyChart.story.vue +61 -0
- package/src/components/PlotlyChart.vue +233 -0
- package/src/components/SegmentedControl.vue +2 -2
- package/src/components/fileBrowserPresentation.ts +39 -0
- package/src/components/index.ts +5 -0
- package/src/components/internal/FileBrowserDialogInternal.vue +75 -0
- package/src/components/internal/FileBrowserListingInternal.vue +197 -0
- package/src/components/internal/FileBrowserToolbarInternal.vue +136 -0
- package/src/components/internal/FilePickerPreviewInternal.vue +100 -0
- package/src/components/internal/FilePickerTreeInternal.vue +238 -0
- package/src/composables/filePicker/localFiles.ts +58 -0
- package/src/composables/filePicker/usePickerNavigation.ts +220 -0
- package/src/composables/filePicker/usePickerSelection.ts +259 -0
- package/src/composables/filePicker/validation.ts +41 -0
- package/src/composables/index.ts +7 -0
- package/src/composables/useApi.ts +57 -13
- package/src/composables/useFileBrowser.ts +314 -0
- package/src/composables/useFilePicker.ts +366 -0
- package/src/composables/useGeneratedAnalysis.ts +10 -17
- package/src/composables/usePlatformFilePickerAdapter.ts +104 -0
- package/src/composables/usePluginClient.ts +3 -0
- package/src/index.ts +3 -0
- package/src/styles/components/file-browser-modal.css +489 -0
- package/src/styles/components/file-picker.css +502 -0
- package/src/styles/components/icon-button.css +9 -0
- package/src/styles/index.css +3 -0
- package/src/types/fileBrowserTypes.ts +85 -0
- package/src/types/filePicker.ts +72 -0
- package/src/types/index.ts +14 -0
- package/dist/ExperimentPopover-oL0fg_A0.js.map +0 -1
- package/dist/components-CgAUzF8F.js.map +0 -1
- package/dist/composables-B_pia3hO.js.map +0 -1
- package/dist/errors-_W0-LbA6.js.map +0 -1
- package/dist/useControlSchema-aMZlb4Sc.js.map +0 -1
- package/dist/useProtocolTemplates-BmX_iVBR.js.map +0 -1
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
/* Unified picker: search-first header, Finder tree, metadata preview and receipt. */
|
|
2
|
+
.mint-picker-dialog {
|
|
3
|
+
width: 800px;
|
|
4
|
+
}
|
|
5
|
+
.mint-picker-dialog .mint-file-browser-dialog__header {
|
|
6
|
+
padding: 15px 18px;
|
|
7
|
+
gap: 12px;
|
|
8
|
+
}
|
|
9
|
+
.mint-picker-dialog .mint-file-browser-dialog__footer {
|
|
10
|
+
padding: 12px 18px;
|
|
11
|
+
background: var(--bg-primary);
|
|
12
|
+
}
|
|
13
|
+
.mint-picker__search {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
position: relative;
|
|
17
|
+
flex: 1;
|
|
18
|
+
min-width: 0;
|
|
19
|
+
}
|
|
20
|
+
.mint-picker__search > svg {
|
|
21
|
+
position: absolute;
|
|
22
|
+
left: 12px;
|
|
23
|
+
width: 16px;
|
|
24
|
+
height: 16px;
|
|
25
|
+
color: var(--text-muted);
|
|
26
|
+
pointer-events: none;
|
|
27
|
+
}
|
|
28
|
+
.mint-picker__search .mint-input {
|
|
29
|
+
width: 100%;
|
|
30
|
+
padding-left: 36px;
|
|
31
|
+
padding-right: 36px;
|
|
32
|
+
background: var(--bg-primary);
|
|
33
|
+
font-size: 13px;
|
|
34
|
+
}
|
|
35
|
+
.mint-picker__search > kbd {
|
|
36
|
+
position: absolute;
|
|
37
|
+
right: 12px;
|
|
38
|
+
font-family: var(--font-mono);
|
|
39
|
+
font-size: 11px;
|
|
40
|
+
border: 1px solid var(--border-color);
|
|
41
|
+
border-radius: var(--radius-sm);
|
|
42
|
+
padding: 1px 5px;
|
|
43
|
+
color: var(--text-secondary);
|
|
44
|
+
background: var(--bg-secondary);
|
|
45
|
+
}
|
|
46
|
+
.mint-picker__sources {
|
|
47
|
+
position: relative;
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
gap: 2px;
|
|
51
|
+
background: var(--bg-primary);
|
|
52
|
+
padding: 2px;
|
|
53
|
+
border-radius: var(--radius-md);
|
|
54
|
+
flex-shrink: 0;
|
|
55
|
+
}
|
|
56
|
+
.mint-picker {
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-direction: column;
|
|
59
|
+
min-height: 0;
|
|
60
|
+
}
|
|
61
|
+
.mint-picker__pathbar {
|
|
62
|
+
display: flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
gap: 6px;
|
|
65
|
+
padding: 7px 18px;
|
|
66
|
+
border-block: 1px solid var(--border-color);
|
|
67
|
+
background: var(--bg-primary);
|
|
68
|
+
flex-shrink: 0;
|
|
69
|
+
}
|
|
70
|
+
.mint-picker__breadcrumbs {
|
|
71
|
+
display: flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
min-width: 0;
|
|
74
|
+
flex: 1;
|
|
75
|
+
overflow-x: auto;
|
|
76
|
+
color: var(--text-muted);
|
|
77
|
+
}
|
|
78
|
+
.mint-picker__breadcrumbs .mint-button {
|
|
79
|
+
font-family: var(--font-mono);
|
|
80
|
+
font-size: 11px;
|
|
81
|
+
padding-inline: 5px;
|
|
82
|
+
flex-shrink: 0;
|
|
83
|
+
}
|
|
84
|
+
.mint-picker__scope {
|
|
85
|
+
font-size: 11px;
|
|
86
|
+
flex-shrink: 0;
|
|
87
|
+
}
|
|
88
|
+
.mint-picker__scope[aria-pressed='true'] {
|
|
89
|
+
color: var(--color-primary);
|
|
90
|
+
background: var(--color-primary-soft);
|
|
91
|
+
}
|
|
92
|
+
.mint-picker__workspace {
|
|
93
|
+
display: grid;
|
|
94
|
+
grid-template-columns: minmax(0, 1fr) 208px;
|
|
95
|
+
height: 344px;
|
|
96
|
+
min-height: 0;
|
|
97
|
+
}
|
|
98
|
+
.mint-picker__tree {
|
|
99
|
+
padding: 7px;
|
|
100
|
+
background: var(--bg-primary);
|
|
101
|
+
overflow-y: auto;
|
|
102
|
+
min-height: 0;
|
|
103
|
+
min-width: 0;
|
|
104
|
+
}
|
|
105
|
+
.mint-picker__row {
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
gap: 6px;
|
|
109
|
+
min-height: 40px;
|
|
110
|
+
padding: 5px 10px 5px calc(2px + var(--picker-depth, 0) * 14px);
|
|
111
|
+
border-radius: var(--radius-md);
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
margin-bottom: 2px;
|
|
114
|
+
border: 1px solid transparent;
|
|
115
|
+
}
|
|
116
|
+
.mint-picker__row:hover {
|
|
117
|
+
background: var(--bg-hover);
|
|
118
|
+
}
|
|
119
|
+
.mint-picker__row--selected,
|
|
120
|
+
.mint-picker__row--selected:hover {
|
|
121
|
+
background: var(--color-primary-soft);
|
|
122
|
+
border-color: color-mix(in srgb, var(--color-primary) 40%, transparent);
|
|
123
|
+
color: var(--text-primary);
|
|
124
|
+
}
|
|
125
|
+
.mint-picker__row:focus-visible {
|
|
126
|
+
outline: none;
|
|
127
|
+
box-shadow: inset 0 0 0 2px var(--color-primary);
|
|
128
|
+
}
|
|
129
|
+
.mint-picker__row--child {
|
|
130
|
+
min-height: 30px;
|
|
131
|
+
padding-block: 1px;
|
|
132
|
+
}
|
|
133
|
+
.mint-picker__disclosure {
|
|
134
|
+
flex-shrink: 0;
|
|
135
|
+
}
|
|
136
|
+
.mint-picker__disclosure-spacer {
|
|
137
|
+
width: var(--form-height-sm);
|
|
138
|
+
flex-shrink: 0;
|
|
139
|
+
}
|
|
140
|
+
.mint-picker__disclosure svg {
|
|
141
|
+
width: 10px;
|
|
142
|
+
height: 10px;
|
|
143
|
+
transition: transform 120ms;
|
|
144
|
+
}
|
|
145
|
+
.mint-picker__chevron--open {
|
|
146
|
+
transform: rotate(90deg);
|
|
147
|
+
}
|
|
148
|
+
.mint-picker__node-icon {
|
|
149
|
+
width: 16px;
|
|
150
|
+
height: 16px;
|
|
151
|
+
flex-shrink: 0;
|
|
152
|
+
color: var(--text-muted);
|
|
153
|
+
}
|
|
154
|
+
.mint-picker__row--selected .mint-picker__node-icon {
|
|
155
|
+
color: var(--color-primary);
|
|
156
|
+
}
|
|
157
|
+
.mint-picker__row-name {
|
|
158
|
+
flex: 1;
|
|
159
|
+
min-width: 0;
|
|
160
|
+
display: flex;
|
|
161
|
+
flex-direction: column;
|
|
162
|
+
gap: 3px;
|
|
163
|
+
}
|
|
164
|
+
.mint-picker__name {
|
|
165
|
+
overflow: hidden;
|
|
166
|
+
text-overflow: ellipsis;
|
|
167
|
+
white-space: nowrap;
|
|
168
|
+
font-size: 13px;
|
|
169
|
+
}
|
|
170
|
+
.mint-picker__row--selected .mint-picker__name {
|
|
171
|
+
font-weight: 600;
|
|
172
|
+
}
|
|
173
|
+
.mint-picker__name mark {
|
|
174
|
+
background: color-mix(in srgb, var(--mint-warning) 32%, transparent);
|
|
175
|
+
color: inherit;
|
|
176
|
+
border-radius: 2px;
|
|
177
|
+
}
|
|
178
|
+
.mint-picker__formats {
|
|
179
|
+
display: flex;
|
|
180
|
+
flex-wrap: wrap;
|
|
181
|
+
gap: 4px;
|
|
182
|
+
}
|
|
183
|
+
.mint-picker__formats > span {
|
|
184
|
+
color: var(--text-secondary);
|
|
185
|
+
background: var(--bg-secondary);
|
|
186
|
+
padding: 1px 4px;
|
|
187
|
+
border: 1px solid var(--border-color);
|
|
188
|
+
border-radius: var(--radius-sm);
|
|
189
|
+
font: 10px var(--font-mono);
|
|
190
|
+
}
|
|
191
|
+
.mint-picker__row-meta {
|
|
192
|
+
display: flex;
|
|
193
|
+
align-items: flex-end;
|
|
194
|
+
flex-direction: column;
|
|
195
|
+
gap: 3px;
|
|
196
|
+
flex-shrink: 0;
|
|
197
|
+
font: 10px var(--font-mono);
|
|
198
|
+
color: var(--text-muted);
|
|
199
|
+
}
|
|
200
|
+
.mint-picker__partial {
|
|
201
|
+
background: var(--mint-warning-bg);
|
|
202
|
+
color: var(--mint-warning-text);
|
|
203
|
+
padding: 2px 5px;
|
|
204
|
+
border-radius: var(--radius-sm);
|
|
205
|
+
}
|
|
206
|
+
.mint-picker__parent-name {
|
|
207
|
+
font: 10px var(--font-mono);
|
|
208
|
+
color: var(--text-muted);
|
|
209
|
+
overflow: hidden;
|
|
210
|
+
text-overflow: ellipsis;
|
|
211
|
+
white-space: nowrap;
|
|
212
|
+
}
|
|
213
|
+
.mint-picker__row--unreadable,
|
|
214
|
+
.mint-picker__row--unreadable:hover {
|
|
215
|
+
cursor: not-allowed;
|
|
216
|
+
color: var(--text-muted);
|
|
217
|
+
background: repeating-linear-gradient(
|
|
218
|
+
135deg,
|
|
219
|
+
transparent,
|
|
220
|
+
transparent 5px,
|
|
221
|
+
color-mix(in srgb, var(--text-muted) 6%, transparent) 5px,
|
|
222
|
+
color-mix(in srgb, var(--text-muted) 6%, transparent) 10px
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
.mint-picker__row--unreadable .mint-picker__name {
|
|
226
|
+
text-decoration: line-through;
|
|
227
|
+
}
|
|
228
|
+
.mint-picker__branch-error {
|
|
229
|
+
padding: 6px 12px;
|
|
230
|
+
color: var(--mint-error);
|
|
231
|
+
font-size: 12px;
|
|
232
|
+
}
|
|
233
|
+
.mint-picker__skeleton {
|
|
234
|
+
display: flex;
|
|
235
|
+
flex-direction: column;
|
|
236
|
+
gap: 8px;
|
|
237
|
+
padding: 8px;
|
|
238
|
+
}
|
|
239
|
+
.mint-picker__empty {
|
|
240
|
+
display: flex;
|
|
241
|
+
flex-direction: column;
|
|
242
|
+
justify-content: center;
|
|
243
|
+
align-items: center;
|
|
244
|
+
gap: 12px;
|
|
245
|
+
min-height: 180px;
|
|
246
|
+
padding: 24px;
|
|
247
|
+
font-size: 12px;
|
|
248
|
+
color: var(--text-secondary);
|
|
249
|
+
text-align: center;
|
|
250
|
+
}
|
|
251
|
+
.mint-picker__preview {
|
|
252
|
+
border-left: 1px solid var(--border-color);
|
|
253
|
+
display: flex;
|
|
254
|
+
flex-direction: column;
|
|
255
|
+
min-height: 0;
|
|
256
|
+
background: var(--bg-secondary);
|
|
257
|
+
}
|
|
258
|
+
.mint-picker__preview-heading {
|
|
259
|
+
padding: 10px 13px;
|
|
260
|
+
border-bottom: 1px solid var(--border-color);
|
|
261
|
+
font-size: 10px;
|
|
262
|
+
font-weight: 600;
|
|
263
|
+
text-transform: uppercase;
|
|
264
|
+
letter-spacing: 0.1em;
|
|
265
|
+
color: var(--text-muted);
|
|
266
|
+
}
|
|
267
|
+
.mint-picker__preview-content {
|
|
268
|
+
display: flex;
|
|
269
|
+
flex-direction: column;
|
|
270
|
+
gap: 10px;
|
|
271
|
+
padding: 14px 13px;
|
|
272
|
+
overflow-y: auto;
|
|
273
|
+
min-height: 0;
|
|
274
|
+
flex: 1;
|
|
275
|
+
}
|
|
276
|
+
.mint-picker__preview-icon {
|
|
277
|
+
display: grid;
|
|
278
|
+
place-items: center;
|
|
279
|
+
width: 52px;
|
|
280
|
+
height: 52px;
|
|
281
|
+
flex-shrink: 0;
|
|
282
|
+
border-radius: 13px;
|
|
283
|
+
background: linear-gradient(135deg, var(--color-primary), var(--color-purple));
|
|
284
|
+
color: white;
|
|
285
|
+
margin: 0 auto;
|
|
286
|
+
}
|
|
287
|
+
.mint-picker__preview-icon svg {
|
|
288
|
+
width: 26px;
|
|
289
|
+
height: 26px;
|
|
290
|
+
}
|
|
291
|
+
.mint-picker__preview-name {
|
|
292
|
+
font-size: 12px;
|
|
293
|
+
text-align: center;
|
|
294
|
+
overflow-wrap: anywhere;
|
|
295
|
+
}
|
|
296
|
+
.mint-picker__metadata {
|
|
297
|
+
display: flex;
|
|
298
|
+
flex-direction: column;
|
|
299
|
+
gap: 7px;
|
|
300
|
+
margin: 0;
|
|
301
|
+
font-size: 11px;
|
|
302
|
+
}
|
|
303
|
+
.mint-picker__metadata > div {
|
|
304
|
+
display: grid;
|
|
305
|
+
grid-template-columns: 44px minmax(0, 1fr);
|
|
306
|
+
gap: 5px;
|
|
307
|
+
}
|
|
308
|
+
.mint-picker__metadata dt {
|
|
309
|
+
color: var(--text-muted);
|
|
310
|
+
}
|
|
311
|
+
.mint-picker__metadata dd {
|
|
312
|
+
margin: 0;
|
|
313
|
+
font: 10px/1.5 var(--font-mono);
|
|
314
|
+
overflow-wrap: anywhere;
|
|
315
|
+
}
|
|
316
|
+
.mint-picker__ready {
|
|
317
|
+
margin-top: auto;
|
|
318
|
+
border: 1px solid var(--mint-success);
|
|
319
|
+
border-radius: 999px;
|
|
320
|
+
background: var(--mint-success-bg);
|
|
321
|
+
color: var(--mint-success-hover);
|
|
322
|
+
text-align: center;
|
|
323
|
+
padding: 4px;
|
|
324
|
+
font-size: 10px;
|
|
325
|
+
}
|
|
326
|
+
.mint-picker__preview-empty {
|
|
327
|
+
color: var(--text-muted);
|
|
328
|
+
font-size: 12px;
|
|
329
|
+
text-align: center;
|
|
330
|
+
padding: 32px 16px;
|
|
331
|
+
}
|
|
332
|
+
.mint-picker__skipped {
|
|
333
|
+
background: var(--mint-warning-bg);
|
|
334
|
+
color: var(--mint-warning-text);
|
|
335
|
+
white-space: normal;
|
|
336
|
+
}
|
|
337
|
+
.mint-picker__exclusion {
|
|
338
|
+
display: flex;
|
|
339
|
+
flex-direction: column;
|
|
340
|
+
gap: 4px;
|
|
341
|
+
font-size: 11px;
|
|
342
|
+
overflow-wrap: anywhere;
|
|
343
|
+
padding-bottom: 8px;
|
|
344
|
+
border-bottom: 1px solid var(--border-color);
|
|
345
|
+
}
|
|
346
|
+
.mint-picker__exclusion span {
|
|
347
|
+
color: var(--text-muted);
|
|
348
|
+
}
|
|
349
|
+
.mint-picker__preview-error {
|
|
350
|
+
display: flex;
|
|
351
|
+
flex-direction: column;
|
|
352
|
+
gap: 8px;
|
|
353
|
+
font-size: 11px;
|
|
354
|
+
color: var(--mint-error);
|
|
355
|
+
}
|
|
356
|
+
.mint-picker__footer {
|
|
357
|
+
display: flex;
|
|
358
|
+
align-items: center;
|
|
359
|
+
gap: 12px;
|
|
360
|
+
width: 100%;
|
|
361
|
+
}
|
|
362
|
+
.mint-picker__receipt {
|
|
363
|
+
display: flex;
|
|
364
|
+
align-items: center;
|
|
365
|
+
gap: 6px;
|
|
366
|
+
flex: 1;
|
|
367
|
+
min-width: 0;
|
|
368
|
+
flex-wrap: wrap;
|
|
369
|
+
font-size: 11px;
|
|
370
|
+
color: var(--text-secondary);
|
|
371
|
+
}
|
|
372
|
+
.mint-picker__receipt > span {
|
|
373
|
+
overflow-wrap: anywhere;
|
|
374
|
+
}
|
|
375
|
+
.mint-picker__badge {
|
|
376
|
+
padding: 3px 7px;
|
|
377
|
+
border-radius: var(--radius-sm);
|
|
378
|
+
color: var(--color-primary);
|
|
379
|
+
border: 1px solid color-mix(in srgb, var(--color-primary) 40%, transparent);
|
|
380
|
+
background: var(--color-primary-soft);
|
|
381
|
+
font: 10px var(--font-mono);
|
|
382
|
+
}
|
|
383
|
+
.mint-picker__actions {
|
|
384
|
+
display: flex;
|
|
385
|
+
align-items: center;
|
|
386
|
+
gap: 8px;
|
|
387
|
+
flex-shrink: 0;
|
|
388
|
+
}
|
|
389
|
+
.mint-picker__local-upload {
|
|
390
|
+
display: flex;
|
|
391
|
+
flex-direction: column;
|
|
392
|
+
gap: 8px;
|
|
393
|
+
padding: 12px 18px;
|
|
394
|
+
flex-shrink: 0;
|
|
395
|
+
color: var(--text-muted);
|
|
396
|
+
font-size: 11px;
|
|
397
|
+
}
|
|
398
|
+
.mint-picker__local-title {
|
|
399
|
+
flex: 1;
|
|
400
|
+
}
|
|
401
|
+
@media (max-width: 600px) {
|
|
402
|
+
.mint-picker-dialog .mint-file-browser-dialog__header {
|
|
403
|
+
padding: 10px;
|
|
404
|
+
gap: 6px;
|
|
405
|
+
flex-wrap: nowrap;
|
|
406
|
+
}
|
|
407
|
+
.mint-picker__search .mint-input {
|
|
408
|
+
font-size: 12px;
|
|
409
|
+
padding-right: 8px;
|
|
410
|
+
}
|
|
411
|
+
.mint-picker__search > kbd {
|
|
412
|
+
display: none;
|
|
413
|
+
}
|
|
414
|
+
.mint-picker__pathbar {
|
|
415
|
+
padding-inline: 8px;
|
|
416
|
+
gap: 2px;
|
|
417
|
+
}
|
|
418
|
+
.mint-picker__workspace {
|
|
419
|
+
grid-template-columns: minmax(0, 1fr);
|
|
420
|
+
height: 390px;
|
|
421
|
+
}
|
|
422
|
+
.mint-picker__preview {
|
|
423
|
+
display: none;
|
|
424
|
+
}
|
|
425
|
+
.mint-picker__workspace:has(.mint-picker__exclusion) {
|
|
426
|
+
grid-template-columns: minmax(0, 1fr) 160px;
|
|
427
|
+
}
|
|
428
|
+
.mint-picker__workspace:has(.mint-picker__exclusion) .mint-picker__preview {
|
|
429
|
+
display: flex;
|
|
430
|
+
}
|
|
431
|
+
.mint-picker__row {
|
|
432
|
+
gap: 4px;
|
|
433
|
+
padding-right: 5px;
|
|
434
|
+
}
|
|
435
|
+
.mint-picker__name {
|
|
436
|
+
font-size: 12px;
|
|
437
|
+
}
|
|
438
|
+
.mint-picker__footer {
|
|
439
|
+
align-items: stretch;
|
|
440
|
+
flex-direction: column;
|
|
441
|
+
gap: 8px;
|
|
442
|
+
}
|
|
443
|
+
.mint-picker__actions {
|
|
444
|
+
justify-content: flex-end;
|
|
445
|
+
}
|
|
446
|
+
.mint-picker__receipt {
|
|
447
|
+
min-height: 24px;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
@media (max-height: 600px) {
|
|
451
|
+
.mint-picker {
|
|
452
|
+
overflow-y: auto;
|
|
453
|
+
}
|
|
454
|
+
.mint-picker__workspace {
|
|
455
|
+
min-height: 220px;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/* The source highlight slides between fixed-size SDK icon buttons. */
|
|
460
|
+
.mint-picker__source-indicator {
|
|
461
|
+
box-sizing: border-box;
|
|
462
|
+
position: absolute;
|
|
463
|
+
inset: 2px auto 2px 2px;
|
|
464
|
+
width: 32px;
|
|
465
|
+
border: 1px solid var(--border-color);
|
|
466
|
+
border-radius: var(--radius-md);
|
|
467
|
+
background: var(--bg-secondary);
|
|
468
|
+
box-shadow: var(--shadow-sm);
|
|
469
|
+
pointer-events: none;
|
|
470
|
+
transform: translateX(calc(var(--picker-source-index, 0) * 34px));
|
|
471
|
+
transition: transform 180ms ease-out;
|
|
472
|
+
}
|
|
473
|
+
.mint-picker__sources .mint-icon-button {
|
|
474
|
+
position: relative;
|
|
475
|
+
width: 32px;
|
|
476
|
+
height: 32px;
|
|
477
|
+
}
|
|
478
|
+
.mint-picker__sources .mint-icon-button[aria-pressed='true'] {
|
|
479
|
+
color: var(--text-primary);
|
|
480
|
+
background: transparent;
|
|
481
|
+
}
|
|
482
|
+
.mint-picker__source-panel {
|
|
483
|
+
animation: mint-picker-source-in 180ms ease-out;
|
|
484
|
+
}
|
|
485
|
+
@keyframes mint-picker-source-in {
|
|
486
|
+
from {
|
|
487
|
+
opacity: 0;
|
|
488
|
+
transform: translateY(4px);
|
|
489
|
+
}
|
|
490
|
+
to {
|
|
491
|
+
opacity: 1;
|
|
492
|
+
transform: translateY(0);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
@media (prefers-reduced-motion: reduce) {
|
|
496
|
+
.mint-picker__source-indicator {
|
|
497
|
+
transition: none;
|
|
498
|
+
}
|
|
499
|
+
.mint-picker__source-panel {
|
|
500
|
+
animation: none;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
@@ -167,6 +167,15 @@
|
|
|
167
167
|
height: 1.5rem;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
+
/* A bare <svg> in the slot has no intrinsic size and collapses to 0 width as a
|
|
171
|
+
flex item; fill the sized icon box so callers need not size their icon. */
|
|
172
|
+
.mint-icon-button__icon--sm > svg,
|
|
173
|
+
.mint-icon-button__icon--md > svg,
|
|
174
|
+
.mint-icon-button__icon--lg > svg {
|
|
175
|
+
width: 100%;
|
|
176
|
+
height: 100%;
|
|
177
|
+
}
|
|
178
|
+
|
|
170
179
|
/* Spinner */
|
|
171
180
|
.mint-icon-button__spinner {
|
|
172
181
|
animation: mint-spin 1s linear infinite;
|
package/src/styles/index.css
CHANGED
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
@import './components/experiment-code-badge.css';
|
|
91
91
|
@import './components/experiment-selector-modal.css';
|
|
92
92
|
@import './components/artifact-selector-modal.css';
|
|
93
|
+
@import './components/file-browser-modal.css';
|
|
93
94
|
@import './components/artifact-save-dialog.css';
|
|
94
95
|
@import './components/experiment-popover.css';
|
|
95
96
|
@import './components/fit-panel.css';
|
|
@@ -100,3 +101,5 @@
|
|
|
100
101
|
@import './components/mobile-support-gate.css';
|
|
101
102
|
@import './components/plugin-icon.css';
|
|
102
103
|
@import './components/reagent-editor.css';
|
|
104
|
+
|
|
105
|
+
@import './components/file-picker.css';
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for browsing read-only server mounts.
|
|
3
|
+
*
|
|
4
|
+
* These mirror the `mint_sdk.filesystem` wire models. MINT records the path of
|
|
5
|
+
* data that already sits on a mount; it never copies it.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** What a listing row is. */
|
|
9
|
+
export type FileEntryKind = 'file' | 'directory'
|
|
10
|
+
|
|
11
|
+
/** Field a listing is ordered by, after directories are grouped first. */
|
|
12
|
+
export type FileBrowserSortKey = 'name' | 'size' | 'modified'
|
|
13
|
+
|
|
14
|
+
/** One read-only directory tree exposed by the server. */
|
|
15
|
+
export interface ServerMount {
|
|
16
|
+
id: string
|
|
17
|
+
label: string
|
|
18
|
+
read_only?: boolean
|
|
19
|
+
/** False when the mount is configured but currently unreachable. */
|
|
20
|
+
available?: boolean
|
|
21
|
+
/** Child mounts, used to render the sidebar tree. */
|
|
22
|
+
children?: ServerMount[]
|
|
23
|
+
/** Item count shown beside the mount; free-form so callers can send "1.2k". */
|
|
24
|
+
count?: string | number
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** One step of the trail from a mount root to the current directory. */
|
|
28
|
+
export interface FilePathCrumb {
|
|
29
|
+
label: string
|
|
30
|
+
path: string
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** A single file or directory inside a mount. */
|
|
34
|
+
export interface FileEntry {
|
|
35
|
+
name: string
|
|
36
|
+
/** Mount-relative POSIX path. */
|
|
37
|
+
path: string
|
|
38
|
+
kind: FileEntryKind
|
|
39
|
+
/** Null for directories. */
|
|
40
|
+
size_bytes?: number | null
|
|
41
|
+
modified_at?: string | null
|
|
42
|
+
extension?: string
|
|
43
|
+
/**
|
|
44
|
+
* False when the entry fails the active type rules. Non-matching entries are
|
|
45
|
+
* still listed — they dim rather than vanish.
|
|
46
|
+
*/
|
|
47
|
+
matches_type_rules?: boolean
|
|
48
|
+
/** Directories only. */
|
|
49
|
+
child_count?: number | null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** The contents of one directory inside a mount. */
|
|
53
|
+
export interface FileDirectoryListing {
|
|
54
|
+
mount_id: string
|
|
55
|
+
path: string
|
|
56
|
+
/** Null at the mount root. */
|
|
57
|
+
parent?: string | null
|
|
58
|
+
breadcrumbs?: FilePathCrumb[]
|
|
59
|
+
entries?: FileEntry[]
|
|
60
|
+
/** Directory size before any search filter. */
|
|
61
|
+
total_count?: number
|
|
62
|
+
/** How many entries satisfy the type rules. */
|
|
63
|
+
match_count?: number
|
|
64
|
+
/** How many entries this response carries, after search and any cap. */
|
|
65
|
+
shown_count?: number
|
|
66
|
+
/** True when the directory held more entries than the server will return. */
|
|
67
|
+
truncated?: boolean
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** One item the user has picked. */
|
|
71
|
+
export interface FileSelection {
|
|
72
|
+
mount_id: string
|
|
73
|
+
path: string
|
|
74
|
+
name: string
|
|
75
|
+
kind: FileEntryKind
|
|
76
|
+
/** For a directory pick, how many files it contains. */
|
|
77
|
+
child_count?: number | null
|
|
78
|
+
size_bytes?: number | null
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Where the user is standing in the browser. */
|
|
82
|
+
export interface FileBrowserLocation {
|
|
83
|
+
mount_id: string
|
|
84
|
+
path: string
|
|
85
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** Sources are supplied by the host; the SDK never infers a host filesystem path. */
|
|
2
|
+
export type PickerSource = 'server' | 'localFile'
|
|
3
|
+
export type PickerSelectionMode = 'single-file' | 'multi-file' | 'folder' | 'folder+files'
|
|
4
|
+
|
|
5
|
+
interface PickerNodeBase {
|
|
6
|
+
path: string
|
|
7
|
+
name: string
|
|
8
|
+
parentPath?: string | null
|
|
9
|
+
parentName?: string
|
|
10
|
+
bytes?: number | null
|
|
11
|
+
/** An explicit adapter failure makes a row inert, including its disclosure. */
|
|
12
|
+
unavailableReason?: string
|
|
13
|
+
}
|
|
14
|
+
export interface PickerFolder extends PickerNodeBase {
|
|
15
|
+
kind: 'folder'
|
|
16
|
+
fileCount?: number | null
|
|
17
|
+
formats?: Record<string, number>
|
|
18
|
+
hasChildren?: boolean
|
|
19
|
+
}
|
|
20
|
+
export interface PickerFile extends PickerNodeBase {
|
|
21
|
+
kind: 'file'
|
|
22
|
+
format: string
|
|
23
|
+
/** Present only for browser-selected files. The picker does not read its bytes. */
|
|
24
|
+
file?: File
|
|
25
|
+
}
|
|
26
|
+
export type PickerNode = PickerFolder | PickerFile
|
|
27
|
+
export interface PickerRequest {
|
|
28
|
+
signal?: AbortSignal
|
|
29
|
+
source?: PickerSource
|
|
30
|
+
/**
|
|
31
|
+
* Set only when the user pressed Refresh. Adapters that cache listings (or
|
|
32
|
+
* ask a server to bypass its own cache) should re-read the location then and
|
|
33
|
+
* serve cached data otherwise; the picker keeps folder contents while it is
|
|
34
|
+
* open and re-reads the current location on each open.
|
|
35
|
+
*/
|
|
36
|
+
refresh?: true
|
|
37
|
+
}
|
|
38
|
+
export interface PickerAdapter {
|
|
39
|
+
listRoot(request?: PickerRequest): Promise<PickerNode[]>
|
|
40
|
+
listChildren(path: string, request?: PickerRequest): Promise<PickerNode[]>
|
|
41
|
+
search(
|
|
42
|
+
query: string,
|
|
43
|
+
scope: { path: string; recursive: boolean },
|
|
44
|
+
request?: PickerRequest,
|
|
45
|
+
): Promise<PickerNode[]>
|
|
46
|
+
}
|
|
47
|
+
export interface PickerCapability {
|
|
48
|
+
/** Case-insensitive suffixes, including compound extensions such as mzML.gz. */
|
|
49
|
+
formats: string[]
|
|
50
|
+
maxBytes?: number
|
|
51
|
+
/** Optional host-owned blank classification; no filename heuristics in the SDK. */
|
|
52
|
+
isBlank?: (node: PickerNode) => boolean
|
|
53
|
+
}
|
|
54
|
+
export type PickerCapabilities = Partial<Record<PickerSource, PickerCapability>>
|
|
55
|
+
export type PickerExclusionReason =
|
|
56
|
+
'deselected' | 'unsupported' | 'tooLarge' | 'blank' | 'unreadable' | 'forbidden'
|
|
57
|
+
export interface PickerExcluded {
|
|
58
|
+
/** Opaque identity prevents collisions between equal filenames in different folders. */
|
|
59
|
+
path: string
|
|
60
|
+
name: string
|
|
61
|
+
reason: PickerExclusionReason
|
|
62
|
+
}
|
|
63
|
+
export type PickerSelection =
|
|
64
|
+
| { source: 'server'; folders: string[]; files: PickerFile[]; excluded: PickerExcluded[] }
|
|
65
|
+
| { source: 'localFile'; files: File[]; relativePaths?: string[] }
|
|
66
|
+
export interface PickerTreeRow {
|
|
67
|
+
node: PickerNode
|
|
68
|
+
depth: number
|
|
69
|
+
expanded: boolean
|
|
70
|
+
loading: boolean
|
|
71
|
+
error?: string
|
|
72
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -208,6 +208,18 @@ export type {
|
|
|
208
208
|
} from './analysisArtifactTypes'
|
|
209
209
|
export { ANALYSIS_FILE_ARTIFACT_SCHEMA } from './analysisArtifactTypes'
|
|
210
210
|
|
|
211
|
+
// File browser types
|
|
212
|
+
export type {
|
|
213
|
+
FileBrowserLocation,
|
|
214
|
+
FileBrowserSortKey,
|
|
215
|
+
FileDirectoryListing,
|
|
216
|
+
FileEntry,
|
|
217
|
+
FileEntryKind,
|
|
218
|
+
FilePathCrumb,
|
|
219
|
+
FileSelection,
|
|
220
|
+
ServerMount,
|
|
221
|
+
} from './fileBrowserTypes'
|
|
222
|
+
|
|
211
223
|
export type {
|
|
212
224
|
JobListPayload,
|
|
213
225
|
JobProgress,
|
|
@@ -297,3 +309,5 @@ export type {
|
|
|
297
309
|
TableDensity,
|
|
298
310
|
UserSummary,
|
|
299
311
|
} from './platform'
|
|
312
|
+
|
|
313
|
+
export type * from './filePicker'
|