@morscherlab/mint-sdk 1.4.0-beta.1 → 1.4.0-beta.11
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/{ActionMenu-CScINahU.js → AlertBox-B2Bgr3ei.js} +40 -209
- package/dist/AlertBox-B2Bgr3ei.js.map +1 -0
- package/dist/{AppSidebar-BmiiPfz9.js → AppSidebar-mvm--GxN.js} +161 -110
- package/dist/AppSidebar-mvm--GxN.js.map +1 -0
- package/dist/{ConfirmDialog-CJ7hqYUP.js → ConfirmDialog-nbJj51is.js} +2 -2
- package/dist/{ConfirmDialog-CJ7hqYUP.js.map → ConfirmDialog-nbJj51is.js.map} +1 -1
- package/dist/ExperimentPopover-5T1fAq2L.js +337 -0
- package/dist/ExperimentPopover-5T1fAq2L.js.map +1 -0
- package/dist/{ExperimentSelectorModal-D-9z7cNx.js → ExperimentSelectorModal-65peG4Up.js} +198 -181
- package/dist/ExperimentSelectorModal-65peG4Up.js.map +1 -0
- package/dist/{SegmentedControl-DERBN-Xd.js → SegmentedControl-BtnnjWzs.js} +2 -2
- package/dist/{SegmentedControl-DERBN-Xd.js.map → SegmentedControl-BtnnjWzs.js.map} +1 -1
- package/dist/{SettingsModal-CSLE31yg.js → SettingsModal-DO3IZ7qz.js} +9 -9
- package/dist/SettingsModal-DO3IZ7qz.js.map +1 -0
- package/dist/__tests__/styles/v2AuditRules.test.d.ts +1 -0
- package/dist/components/AppSidebar.vue.d.ts +1 -1
- package/dist/components/ArtifactSaveDialog.vue.d.ts +9 -1
- package/dist/components/AuditTrail.vue.d.ts +1 -1
- package/dist/components/BaseSelect.vue.d.ts +2 -2
- package/dist/components/ChartContainer.vue.d.ts +2 -0
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/ExperimentPopover.vue.d.ts +18 -0
- package/dist/components/ExperimentSelectorModal.vue.d.ts +0 -4
- package/dist/components/FilePicker.vue.d.ts +1 -1
- package/dist/components/FileUploader.vue.d.ts +2 -2
- package/dist/components/PluginIcon.vue.d.ts +2 -2
- package/dist/components/SampleSelector.vue.d.ts +6 -6
- package/dist/components/SequenceProgressBar.vue.d.ts +3 -0
- package/dist/components/StepWizard.vue.d.ts +3 -0
- package/dist/components/internal/AutoGroupModalInternal.vue.d.ts +1 -1
- package/dist/components/internal/DatePickerTimeInternal.vue.d.ts +1 -1
- package/dist/components/internal/ResourcePickerListInternal.vue.d.ts +2 -7
- package/dist/components/internal/SelectMultipleInternal.vue.d.ts +4 -0
- package/dist/composables/createClient.d.ts +2 -0
- package/dist/composables/index.d.ts +1 -0
- package/dist/composables/pluginIdentity.d.ts +24 -0
- package/dist/composables/pluginWorkspaceModel.d.ts +2 -2
- package/dist/composables/useAppExperiment.d.ts +8 -0
- package/dist/composables/useCalendarGrid.d.ts +1 -1
- package/dist/composables/useExperimentSelector.d.ts +6 -2
- package/dist/composables/usePlatform.d.ts +1 -0
- package/dist/{controlSchemaModel-CP5-_nAj.js → controlSchemaModel-B8CTXagP.js} +2 -2
- package/dist/{controlSchemaModel-CP5-_nAj.js.map → controlSchemaModel-B8CTXagP.js.map} +1 -1
- package/dist/{data-C2PwI_dn.js → data-CgILxDLW.js} +178 -124
- package/dist/data-CgILxDLW.js.map +1 -0
- package/dist/data.js +8 -8
- package/dist/{experimentStatus-BZmU4czV.js → experimentStatus-Cqp6qNrR.js} +3 -3
- package/dist/{experimentStatus-BZmU4czV.js.map → experimentStatus-Cqp6qNrR.js.map} +1 -1
- package/dist/index.js +19 -19
- package/dist/{install-DAID6c2-.js → install-mB8-IyvO.js} +15 -14
- package/dist/{install-DAID6c2-.js.map → install-mB8-IyvO.js.map} +1 -1
- package/dist/install.js +1 -1
- package/dist/{lab-DLwRl_Ql.js → lab-D5bIX426.js} +128 -147
- package/dist/lab-D5bIX426.js.map +1 -0
- package/dist/lab.js +4 -3
- package/dist/{records-BzTcxekG.js → records-B6gpM_3e.js} +472 -274
- package/dist/records-B6gpM_3e.js.map +1 -0
- package/dist/{runtime-D6gVat6r.js → runtime-D7vKpfbF.js} +27 -31
- package/dist/runtime-D7vKpfbF.js.map +1 -0
- package/dist/runtime.js +6 -6
- package/dist/{shell-5ju97nOS.js → shell-CywENwBT.js} +5 -5
- package/dist/{shell-5ju97nOS.js.map → shell-CywENwBT.js.map} +1 -1
- package/dist/shell.js +5 -5
- package/dist/styles.css +1644 -1688
- package/dist/types/componentWorkflowTypes.d.ts +2 -0
- package/dist/types/generated/platformContext.d.ts +1 -0
- package/dist/types/generated-ui.d.ts +4 -0
- package/dist/{BaseModal-DfRIuVoj.js → useDropdownState-8yWMu-7_.js} +60 -2
- package/dist/useDropdownState-8yWMu-7_.js.map +1 -0
- package/dist/{useExperimentSamples-CxcnxZ8h.js → useExperimentSamples-DHnxKFAF.js} +3 -3
- package/dist/{useExperimentSamples-CxcnxZ8h.js.map → useExperimentSamples-DHnxKFAF.js.map} +1 -1
- package/dist/{useListReorder-CcbEYxX-.js → useListReorder-BitdUhxn.js} +109 -277
- package/dist/useListReorder-BitdUhxn.js.map +1 -0
- package/dist/{useRackEditor-BD5NIo5s.js → useRackEditor-Q8xO-cCy.js} +72 -58
- package/dist/useRackEditor-Q8xO-cCy.js.map +1 -0
- package/dist/{useRealtime-PalKue84.js → useRealtime-C3iy9QkU.js} +7 -4
- package/dist/useRealtime-C3iy9QkU.js.map +1 -0
- package/dist/useRequest-D506eHi8.js +244 -0
- package/dist/useRequest-D506eHi8.js.map +1 -0
- package/dist/utils/time.d.ts +7 -0
- package/package.json +1 -1
- package/src/__tests__/components/AppTopBar.test.ts +51 -2
- package/src/__tests__/components/AppTopBarPillNav.test.ts +35 -0
- package/src/__tests__/components/ArtifactSaveDialog.test.ts +78 -0
- package/src/__tests__/components/BaseSelect.multiple.test.ts +87 -32
- package/src/__tests__/components/BaseSelect.test.ts +2 -1
- package/src/__tests__/components/BatchProgressList.test.ts +16 -0
- package/src/__tests__/components/CalendarGridPanel.test.ts +2 -2
- package/src/__tests__/components/ChartContainer.test.ts +11 -0
- package/src/__tests__/components/ChemicalFormula.test.ts +6 -3
- package/src/__tests__/components/DatePicker.datetime.test.ts +6 -0
- package/src/__tests__/components/DatePicker.test.ts +21 -0
- package/src/__tests__/components/DatePicker.time.test.ts +2 -2
- package/src/__tests__/components/EmptyState.test.ts +1 -1
- package/src/__tests__/components/ExperimentPopover.test.ts +125 -16
- package/src/__tests__/components/ExperimentSelectorModal.test.ts +119 -13
- package/src/__tests__/components/GeneratedPluginView.test.ts +22 -1
- package/src/__tests__/components/InstrumentStateBadge.test.ts +4 -4
- package/src/__tests__/components/PluginWorkspaceView.test.ts +7 -0
- package/src/__tests__/components/ResourcePickerListInternal.test.ts +0 -20
- package/src/__tests__/components/SampleSelector.test.ts +13 -8
- package/src/__tests__/components/SequenceProgressBar.test.ts +12 -0
- package/src/__tests__/components/StepWizard.test.ts +11 -0
- package/src/__tests__/components/WellPlate.decoration.test.ts +11 -4
- package/src/__tests__/components/deprecationTags.test.ts +1 -1
- package/src/__tests__/composables/useAppExperiment.test.ts +27 -1
- package/src/__tests__/composables/useCalendarGrid.test.ts +4 -2
- package/src/__tests__/composables/useExperimentSelector.test.ts +111 -0
- package/src/__tests__/styles/baseControlsRules.test.ts +6 -2
- package/src/__tests__/styles/controlRefreshRules.test.ts +0 -6
- package/src/__tests__/styles/cssTokens.test.ts +2 -2
- package/src/__tests__/styles/menusShellRefresh.test.ts +14 -10
- package/src/__tests__/styles/v2AuditRules.test.ts +96 -0
- package/src/__tests__/utils/plotlyTemplate.test.ts +4 -4
- package/src/__tests__/utils/time.test.ts +18 -1
- package/src/components/AdductText.story.vue +7 -0
- package/src/components/AdductText.vue +1 -1
- package/src/components/AlertBox.story.vue +2 -2
- package/src/components/AlertBox.vue +18 -16
- package/src/components/AppSidebar.story.vue +0 -28
- package/src/components/AppTopBar.story.vue +47 -12
- package/src/components/AppTopBar.vue +118 -114
- package/src/components/ArtifactSaveDialog.story.vue +23 -0
- package/src/components/ArtifactSaveDialog.vue +102 -12
- package/src/components/AuditTrail.story.vue +2 -1
- package/src/components/AuditTrail.vue +2 -21
- package/src/components/Avatar.vue +10 -14
- package/src/components/BaseSelect.multiple.story.vue +13 -2
- package/src/components/BaseSelect.vue +4 -3
- package/src/components/BatchProgressList.vue +35 -25
- package/src/components/ChartContainer.story.vue +2 -1
- package/src/components/ChartContainer.vue +8 -6
- package/src/components/ConfirmDialog.story.vue +1 -1
- package/src/components/EmptyState.vue +1 -1
- package/src/components/ExperimentPopover.story.vue +165 -53
- package/src/components/ExperimentPopover.vue +169 -187
- package/src/components/ExperimentSelectorModal.story.vue +40 -36
- package/src/components/ExperimentSelectorModal.vue +124 -110
- package/src/components/FormField.story.vue +8 -48
- package/src/components/GeneratedPluginView.vue +7 -1
- package/src/components/GeneratedResultRenderer.vue +3 -4
- package/src/components/InstrumentStateBadge.vue +1 -1
- package/src/components/JobsStatusTray.vue +1 -1
- package/src/components/LoadingSpinner.vue +1 -1
- package/src/components/NumberInput.vue +3 -6
- package/src/components/PluginIcon.story.vue +2 -10
- package/src/components/PluginIcon.vue +2 -2
- package/src/components/PluginWorkspaceView.story.vue +1 -1
- package/src/components/RuntimeUpdateNotice.vue +1 -1
- package/src/components/SampleSelector.story.vue +1 -1
- package/src/components/SampleSelector.vue +27 -37
- package/src/components/SampleSelectorGroupNode.vue +1 -1
- package/src/components/SectionCard.story.vue +2 -2
- package/src/components/SequenceProgressBar.story.vue +9 -0
- package/src/components/SequenceProgressBar.vue +6 -1
- package/src/components/SettingsModal.schema.ts +1 -1
- package/src/components/SettingsModal.vue +2 -2
- package/src/components/SmartGroupFieldRecipe.story.vue +1 -1
- package/src/components/SmartGroupManual.story.vue +1 -1
- package/src/components/StepWizard.story.vue +33 -0
- package/src/components/StepWizard.vue +8 -1
- package/src/components/WellPlate.story.vue +3 -1
- package/src/components/WellPlate.vue +7 -0
- package/src/components/internal/AppTopBarPillNavInternal.vue +33 -2
- package/src/components/internal/DatePickerDateInternal.vue +16 -40
- package/src/components/internal/DatePickerDateTimeInternal.vue +3 -13
- package/src/components/internal/DatePickerTimeInternal.vue +5 -8
- package/src/components/internal/ResourcePickerListInternal.vue +45 -85
- package/src/components/internal/SelectMultipleInternal.vue +182 -65
- package/src/components/internal/SelectSearchableInternal.vue +2 -3
- package/src/composables/createClient.ts +2 -0
- package/src/composables/index.ts +1 -0
- package/src/composables/pluginIdentity.ts +31 -0
- package/src/composables/pluginWorkspaceModel.ts +2 -2
- package/src/composables/useAppExperiment.ts +20 -0
- package/src/composables/useCalendarGrid.ts +4 -3
- package/src/composables/useExperimentSelector.ts +77 -31
- package/src/composables/usePluginWorkspace.ts +1 -1
- package/src/styles/components/adduct-text.css +13 -5
- package/src/styles/components/alert-box.css +39 -58
- package/src/styles/components/app-layout.css +7 -5
- package/src/styles/components/app-page-selector.css +3 -1
- package/src/styles/components/app-pill-nav.css +11 -12
- package/src/styles/components/app-sidebar.css +9 -18
- package/src/styles/components/app-top-bar.css +57 -55
- package/src/styles/components/artifact-save-dialog.css +153 -2
- package/src/styles/components/audit-trail.css +16 -19
- package/src/styles/components/avatar.css +6 -4
- package/src/styles/components/batch-progress-list.css +38 -36
- package/src/styles/components/button.css +28 -59
- package/src/styles/components/calendar.css +12 -12
- package/src/styles/components/chart-container.css +34 -23
- package/src/styles/components/checkbox.css +2 -12
- package/src/styles/components/collapsible-card.css +27 -29
- package/src/styles/components/confirm-dialog.css +13 -14
- package/src/styles/components/dataframe.css +13 -5
- package/src/styles/components/date-picker.css +80 -92
- package/src/styles/components/datetime-picker.css +31 -43
- package/src/styles/components/divider.css +20 -20
- package/src/styles/components/dose-calculator.css +3 -3
- package/src/styles/components/empty-state.css +20 -17
- package/src/styles/components/experiment-code-badge.css +2 -0
- package/src/styles/components/experiment-popover.css +174 -329
- package/src/styles/components/experiment-selector-modal.css +75 -56
- package/src/styles/components/file-picker.css +3 -3
- package/src/styles/components/file-uploader.css +38 -49
- package/src/styles/components/form-builder.css +3 -3
- package/src/styles/components/formula-input.css +1 -1
- package/src/styles/components/icon-button.css +18 -24
- package/src/styles/components/input.css +5 -4
- package/src/styles/components/instrument-monitor.css +13 -15
- package/src/styles/components/jobs-status-tray.css +31 -25
- package/src/styles/components/modal.css +4 -6
- package/src/styles/components/molecule-input.css +2 -2
- package/src/styles/components/multi-select.css +65 -117
- package/src/styles/components/number-input.css +26 -19
- package/src/styles/components/pill.css +3 -2
- package/src/styles/components/plate-editor.css +0 -1
- package/src/styles/components/plugin-icon.css +26 -23
- package/src/styles/components/popover.css +2 -2
- package/src/styles/components/presence-avatars.css +1 -1
- package/src/styles/components/progress-bar.css +3 -3
- package/src/styles/components/protocol-step-editor.css +1 -3
- package/src/styles/components/resource-card.css +2 -2
- package/src/styles/components/resource-picker-list.css +6 -57
- package/src/styles/components/sample-hierarchy-tree.css +4 -4
- package/src/styles/components/sample-selector.css +95 -79
- package/src/styles/components/schedule-calendar.css +8 -8
- package/src/styles/components/searchable-select.css +12 -12
- package/src/styles/components/section-card.css +30 -47
- package/src/styles/components/segmented-control.css +18 -15
- package/src/styles/components/select.css +3 -3
- package/src/styles/components/sequence-input.css +2 -2
- package/src/styles/components/sequence-progress-bar.css +17 -8
- package/src/styles/components/settings-modal.css +7 -2
- package/src/styles/components/smart-group.css +18 -18
- package/src/styles/components/step-wizard.css +52 -16
- package/src/styles/components/tabs.css +2 -2
- package/src/styles/components/textarea.css +3 -3
- package/src/styles/components/time-picker.css +36 -21
- package/src/styles/components/toast.css +12 -10
- package/src/styles/components/toggle.css +1 -11
- package/src/styles/components/tooltip.css +10 -9
- package/src/styles/components/unit-input.css +8 -7
- package/src/styles/components/well-plate.css +9 -2
- package/src/styles/variables.css +118 -77
- package/src/types/componentWorkflowTypes.ts +2 -0
- package/src/types/generated/platformContext.ts +1 -0
- package/src/types/generated-ui.ts +4 -0
- package/src/utils/time.ts +21 -0
- package/dist/ActionMenu-CScINahU.js.map +0 -1
- package/dist/AppSidebar-BmiiPfz9.js.map +0 -1
- package/dist/BaseModal-DfRIuVoj.js.map +0 -1
- package/dist/ExperimentPopover-C4sGw-is.js +0 -359
- package/dist/ExperimentPopover-C4sGw-is.js.map +0 -1
- package/dist/ExperimentSelectorModal-D-9z7cNx.js.map +0 -1
- package/dist/SettingsModal-CSLE31yg.js.map +0 -1
- package/dist/data-C2PwI_dn.js.map +0 -1
- package/dist/lab-DLwRl_Ql.js.map +0 -1
- package/dist/records-BzTcxekG.js.map +0 -1
- package/dist/runtime-D6gVat6r.js.map +0 -1
- package/dist/useListReorder-CcbEYxX-.js.map +0 -1
- package/dist/useRackEditor-BD5NIo5s.js.map +0 -1
- package/dist/useRealtime-PalKue84.js.map +0 -1
- package/dist/useRequest-D5JDfsgZ.js +0 -76
- package/dist/useRequest-D5JDfsgZ.js.map +0 -1
|
@@ -29,11 +29,11 @@ describe('SDK control refresh base-control rules', () => {
|
|
|
29
29
|
})
|
|
30
30
|
|
|
31
31
|
it('should find no soft or plain focus ring when scanning pressable controls (1a)', () => {
|
|
32
|
-
const pressables = ['checkbox.css', 'radio-group.css', 'toggle.css', 'icon-button.css'
|
|
32
|
+
const pressables = ['checkbox.css', 'radio-group.css', 'toggle.css', 'icon-button.css']
|
|
33
33
|
expect(offenders(pressables, (l) => /var\(--focus-ring(-soft)?\)/.test(l))).toEqual([])
|
|
34
34
|
})
|
|
35
35
|
|
|
36
|
-
it.each(['input.css', 'select.css', 'textarea.css'])(
|
|
36
|
+
it.each(['input.css', 'select.css', 'textarea.css', 'multi-select.css'])(
|
|
37
37
|
'should use the shared field hover border when scanning %s (1e)',
|
|
38
38
|
(file) => {
|
|
39
39
|
expect(css(file)).toContain('border-color: var(--_field-border-hover)')
|
|
@@ -77,6 +77,10 @@ describe('SDK control refresh base-control rules', () => {
|
|
|
77
77
|
expect(offenders(['alert-box.css'], (l) => /\.mint-alert--\w+ \.mint-alert__title/.test(l))).toEqual([])
|
|
78
78
|
})
|
|
79
79
|
|
|
80
|
+
it('should find no tone fill on the alert surface when scanning alert-box.css (v2 callout)', () => {
|
|
81
|
+
expect(offenders(['alert-box.css'], (l) => /^\.mint-alert--\w+\s*\{/.test(l))).toEqual([])
|
|
82
|
+
})
|
|
83
|
+
|
|
80
84
|
it('should find no pill radius on the chip when scanning multi-select.css (1i)', () => {
|
|
81
85
|
expect(offenders(['multi-select.css'], (l) => /9999px|999px/.test(l))).toEqual([])
|
|
82
86
|
})
|
|
@@ -197,12 +197,6 @@ describe('SDK control refresh style rules', () => {
|
|
|
197
197
|
expect(rule).toMatch(/padding:\s*0/)
|
|
198
198
|
})
|
|
199
199
|
|
|
200
|
-
it('should pad resource picker group bars to the modal gutter when scanning resource-picker-list.css', () => {
|
|
201
|
-
const css = stripComments(readFileSync(component('resource-picker-list.css'), 'utf-8'))
|
|
202
|
-
const rule = /\.mint-resource-picker__group\s*\{([^}]*)\}/.exec(css)?.[1] ?? ''
|
|
203
|
-
expect(rule).toMatch(/padding:\s*0 1\.25rem/)
|
|
204
|
-
})
|
|
205
|
-
|
|
206
200
|
// The list sat in a bordered card inside the modal card.
|
|
207
201
|
it('should draw no frame around the resource picker list when scanning resource-picker-list.css', () => {
|
|
208
202
|
const css = stripComments(readFileSync(component('resource-picker-list.css'), 'utf-8'))
|
|
@@ -93,8 +93,8 @@ describe('CSS custom properties', () => {
|
|
|
93
93
|
|
|
94
94
|
// 9a: PlotlyChart reads it through getComputedStyle('--font-sans'), which the
|
|
95
95
|
// scan above counts as a declaration, so it slipped through as undefined.
|
|
96
|
-
it('should declare --font-sans as
|
|
97
|
-
expect(variablesCss).toMatch(/--font-sans:\s*'
|
|
96
|
+
it('should declare --font-sans as Geist when charts read the sans font token (9a)', () => {
|
|
97
|
+
expect(variablesCss).toMatch(/--font-sans:\s*'Geist'/)
|
|
98
98
|
})
|
|
99
99
|
|
|
100
100
|
it('does not use the platform-only --color-bg-*/--color-text-*/--color-border aliases', () => {
|
|
@@ -25,9 +25,9 @@ describe('menus and app shell styles', () => {
|
|
|
25
25
|
expect(css('app-top-bar.css')).toMatch(/\.mint-topbar\s*\{[^}]*padding:\s*0\.75rem 1rem;/)
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
-
//
|
|
29
|
-
it('should size pill nav items so the track matches the
|
|
30
|
-
expect(css('app-pill-nav.css')).toMatch(/\.mint-pill-nav__item\s*\{[^}]*height:\s*1\.
|
|
28
|
+
// 26px items + 2px track padding + 1px border on each side = the 32px top-bar control height.
|
|
29
|
+
it('should size pill nav items so the track matches the 32px top-bar controls', () => {
|
|
30
|
+
expect(css('app-pill-nav.css')).toMatch(/\.mint-pill-nav__item\s*\{[^}]*height:\s*1\.625rem;/)
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
it('should size the page selector trigger to the 36px identity tile', () => {
|
|
@@ -44,17 +44,21 @@ describe('menus and app shell styles', () => {
|
|
|
44
44
|
expect(css('app-top-bar.css')).toMatch(/\.mint-topbar__identity > \*\s*\{[^}]*max-width:\s*100%;[^}]*max-height:\s*100%;/)
|
|
45
45
|
})
|
|
46
46
|
|
|
47
|
-
//
|
|
48
|
-
it('should fit the top-bar title and subtitle
|
|
49
|
-
|
|
47
|
+
// 18px name + 15px subtitle lines, spread over the 36px identity tile height (top and bottom aligned).
|
|
48
|
+
it('should fit the top-bar title and subtitle to the 36px identity tile (5a)', () => {
|
|
49
|
+
const topBar = css('app-top-bar.css')
|
|
50
|
+
expect(topBar).toMatch(/\.mint-topbar-title-group\s*\{[^}]*justify-content:\s*space-between;[^}]*height:\s*2\.25rem;/)
|
|
51
|
+
expect(topBar).toMatch(/\.mint-topbar-title\s*\{[^}]*font-size:\s*0\.9375rem;[^}]*line-height:\s*1\.125rem;/)
|
|
52
|
+
expect(topBar).toMatch(/\.mint-topbar-subtitle\s*\{[^}]*font-size:\s*0\.75rem;[^}]*line-height:\s*0\.9375rem;/)
|
|
50
53
|
})
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
// Design v2: the joined [trigger | Save] group is 30px inside its 1px border.
|
|
56
|
+
it('should size the top-bar experiment trigger to the 30px v2 control height (5a)', () => {
|
|
57
|
+
expect(css('experiment-popover.css')).toMatch(/\.mint-experiment-popover__trigger\s*\{[^}]*height:\s*30px;/)
|
|
54
58
|
})
|
|
55
59
|
|
|
56
|
-
it('should size the top-bar experiment save
|
|
57
|
-
expect(css('experiment-popover.css')).toMatch(/\.mint-experiment-popover__save
|
|
60
|
+
it('should size the top-bar experiment save button to the 30px v2 control height (5a)', () => {
|
|
61
|
+
expect(css('experiment-popover.css')).toMatch(/\.mint-experiment-popover__save\s*\{[^}]*height:\s*30px;/)
|
|
58
62
|
})
|
|
59
63
|
|
|
60
64
|
it('should give settings number rows a 120px control (5d)', () => {
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { dirname, join, resolve } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { describe, expect, it } from 'vitest'
|
|
5
|
+
|
|
6
|
+
// v2 design audit (2026-10-28) fixes in the SDK stylesheets.
|
|
7
|
+
|
|
8
|
+
const srcRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../..')
|
|
9
|
+
const stylesDir = join(srcRoot, 'styles')
|
|
10
|
+
|
|
11
|
+
function css(path: string): string {
|
|
12
|
+
return readFileSync(join(stylesDir, path), 'utf-8').replace(/\/\*[\s\S]*?\*\//g, '')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function rule(text: string, selector: string): string {
|
|
16
|
+
const escaped = selector.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
17
|
+
return new RegExp(`(?:^|\\})\\s*${escaped}\\s*\\{([^}]*)\\}`).exec(text)?.[1] ?? ''
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const rem = (value: string): number => Number(value.replace('rem', '')) * 16
|
|
21
|
+
|
|
22
|
+
describe('v2 audit style rules', () => {
|
|
23
|
+
it('should keep the outermost cards at least 16px from the window edge', () => {
|
|
24
|
+
const inset = /--mint-page-inset:\s*([\d.]+rem)/.exec(css('variables.css'))?.[1] ?? '0rem'
|
|
25
|
+
expect(rem(inset)).toBeGreaterThanOrEqual(16)
|
|
26
|
+
expect(rule(css('components/app-layout.css'), '.mint-layout--floating')).toMatch(/padding:\s*var\(--mint-page-inset\)/)
|
|
27
|
+
const topBarCard = rule(css('components/app-top-bar.css'), '.mint-topbar--card')
|
|
28
|
+
expect(topBarCard).toMatch(/width:\s*calc\(100% - 2 \* var\(--mint-page-inset\)\)/)
|
|
29
|
+
expect(topBarCard).toMatch(/margin:\s*var\(--mint-page-inset\) var\(--mint-page-inset\) 0/)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should put the SDK utility classes in the utilities layer so host variants beat them', () => {
|
|
33
|
+
const vars = css('variables.css')
|
|
34
|
+
const order = vars.indexOf('@layer theme, base, components, utilities;')
|
|
35
|
+
const layer = vars.indexOf('@layer utilities {')
|
|
36
|
+
expect(order).toBeGreaterThan(-1)
|
|
37
|
+
expect(order).toBeLessThan(vars.indexOf('@layer base {'))
|
|
38
|
+
const utilities = vars.slice(layer, vars.indexOf('@media (prefers-reduced-motion'))
|
|
39
|
+
expect(layer).toBeGreaterThan(-1)
|
|
40
|
+
for (const selector of ['.flex-col {', '.text-text-muted {', '.truncate {', '.max-w-sm {']) {
|
|
41
|
+
expect(utilities).toContain(selector)
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('should drop the last DataFrame row rule over the !important cell border', () => {
|
|
46
|
+
const body = rule(css('components/dataframe.css'), '.mint-dataframe__row:last-child .mint-dataframe__td')
|
|
47
|
+
expect(body).toMatch(/border-bottom:\s*none\s*!important/)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('should round the modal close button with --radius-md', () => {
|
|
51
|
+
expect(rule(css('components/modal.css'), '.mint-modal__close')).toMatch(/border-radius:\s*var\(--radius-md\)/)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('should draw no capsule on the progress rail or the sheet grab hint', () => {
|
|
55
|
+
expect(css('components/progress-bar.css')).not.toMatch(/9999px/)
|
|
56
|
+
expect(rule(css('components/modal.css'), '.mint-modal__grab-hint')).not.toMatch(/9999px/)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should keep a 28px header control inside the section card header strip', () => {
|
|
60
|
+
const text = css('components/section-card.css')
|
|
61
|
+
const cases: Array<[string, number]> = [
|
|
62
|
+
['.mint-section-card__header', 28],
|
|
63
|
+
['[data-density="comfortable"] .mint-section-card__header', 32],
|
|
64
|
+
]
|
|
65
|
+
for (const [selector, control] of cases) {
|
|
66
|
+
const body = rule(text, selector)
|
|
67
|
+
const minHeight = rem(/min-height:\s*([\d.]+rem)/.exec(body)?.[1] ?? '0rem')
|
|
68
|
+
const padTop = rem(/padding:\s*([\d.]+rem)/.exec(body)?.[1] ?? '0rem')
|
|
69
|
+
expect(control + 2 * padTop + 1, selector).toBeLessThanOrEqual(minHeight)
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('should end the settings pane without a closing row hairline and draw no box around the density preview', () => {
|
|
74
|
+
const text = css('components/settings-modal.css')
|
|
75
|
+
const last = rule(
|
|
76
|
+
text,
|
|
77
|
+
'.mint-settings-modal__group:last-of-type > .mint-settings-modal__group-grid > .mint-settings-modal__row:last-child',
|
|
78
|
+
)
|
|
79
|
+
expect(last).toMatch(/border-bottom:\s*none/)
|
|
80
|
+
expect(rule(text, '.mint-settings-modal__density-preview')).not.toMatch(/(^|;)\s*border(-radius)?:/)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('should set the md number input text no smaller than the sm one', () => {
|
|
84
|
+
const text = css('components/number-input.css')
|
|
85
|
+
const size = (variant: string) =>
|
|
86
|
+
rem(/font-size:\s*([\d.]+rem)/.exec(rule(text, `.mint-number-input__input--${variant}`))?.[1] ?? '0rem')
|
|
87
|
+
expect(size('md')).toBeGreaterThan(size('sm'))
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('should give the generated JSON block a token radius and no frame', () => {
|
|
91
|
+
const sfc = readFileSync(join(srcRoot, 'components/GeneratedResultRenderer.vue'), 'utf-8')
|
|
92
|
+
const body = /\.mint-generated-result__json\s*\{([^}]*overflow:[^}]*)\}/.exec(sfc)?.[1] ?? ''
|
|
93
|
+
expect(body).toMatch(/border-radius:\s*var\(--radius-md\)/)
|
|
94
|
+
expect(body).not.toMatch(/(^|;)\s*border:/)
|
|
95
|
+
})
|
|
96
|
+
})
|
|
@@ -10,8 +10,8 @@ const tokens: Record<string, string> = {
|
|
|
10
10
|
'--mint-sample-6': '#666666',
|
|
11
11
|
'--mint-sample-7': '#777777',
|
|
12
12
|
'--mint-sample-8': '#888888',
|
|
13
|
-
'--font-sans': '
|
|
14
|
-
'--font-mono': '
|
|
13
|
+
'--font-sans': 'Geist',
|
|
14
|
+
'--font-mono': 'Geist Mono',
|
|
15
15
|
'--text-primary': '#1E293B',
|
|
16
16
|
'--text-secondary': '#64748B',
|
|
17
17
|
'--border-light': '#F3F4F6',
|
|
@@ -35,11 +35,11 @@ describe('mintPlotlyTemplate', () => {
|
|
|
35
35
|
})
|
|
36
36
|
|
|
37
37
|
it('should set 12px sans body text in the primary text color when tokens are defined', () => {
|
|
38
|
-
expect(mintPlotlyTemplate().layout?.font).toEqual({ family: '
|
|
38
|
+
expect(mintPlotlyTemplate().layout?.font).toEqual({ family: 'Geist', size: 12, color: '#1E293B' })
|
|
39
39
|
})
|
|
40
40
|
|
|
41
41
|
it('should set 11px mono ticks in the secondary text color when tokens are defined', () => {
|
|
42
|
-
expect(mintPlotlyTemplate().layout?.yaxis?.tickfont).toEqual({ family: '
|
|
42
|
+
expect(mintPlotlyTemplate().layout?.yaxis?.tickfont).toEqual({ family: 'Geist Mono', size: 11, color: '#64748B' })
|
|
43
43
|
})
|
|
44
44
|
|
|
45
45
|
it('should draw the grid with --border-light when tokens are defined', () => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
2
2
|
import {
|
|
3
3
|
findNearestTimeSlotIndex,
|
|
4
|
+
formatRelativeTime,
|
|
4
5
|
formatTimeSlot,
|
|
5
6
|
fromMinutes,
|
|
6
7
|
generateTimeSlots,
|
|
@@ -25,4 +26,20 @@ describe('time', () => {
|
|
|
25
26
|
expect(findNearestTimeSlotIndex('08:00', [])).toBe(-1)
|
|
26
27
|
})
|
|
27
28
|
|
|
29
|
+
describe('formatRelativeTime', () => {
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
vi.useRealTimers()
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it.each([
|
|
35
|
+
[{ weeks: true }, '2 weeks ago'],
|
|
36
|
+
[{}, new Date('2026-10-14T12:00:00Z').toLocaleDateString()],
|
|
37
|
+
])('should format a 14-day-old time as a week count only when weeks is on (%o)', (options, expected) => {
|
|
38
|
+
vi.useFakeTimers({ toFake: ['Date'] })
|
|
39
|
+
vi.setSystemTime(new Date('2026-10-28T12:00:00Z'))
|
|
40
|
+
|
|
41
|
+
expect(formatRelativeTime('2026-10-14T12:00:00Z', options)).toBe(expected)
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
28
45
|
})
|
|
@@ -12,6 +12,13 @@ import AdductText from './AdductText.vue'
|
|
|
12
12
|
</div>
|
|
13
13
|
</Variant>
|
|
14
14
|
|
|
15
|
+
<Variant title="Badges">
|
|
16
|
+
<div style="display: flex; align-items: center; gap: 0.5rem; padding: 2rem;">
|
|
17
|
+
<AdductText v-for="v in ['[M+H]+', '[M-H]-', '[M+Na]+', '[M-H2O+H]+', '[M+2H]2+']" :key="v" :value="v" variant="badge" />
|
|
18
|
+
<AdductText value="[M+H]+" variant="badge" font="mono" />
|
|
19
|
+
</div>
|
|
20
|
+
</Variant>
|
|
21
|
+
|
|
15
22
|
<Variant title="Tones and inherited size">
|
|
16
23
|
<div style="display: flex; flex-direction: column; gap: 0.75rem; padding: 2rem; max-width: 600px; color: var(--text-primary); font-size: 0.875rem;">
|
|
17
24
|
<div style="display: flex; align-items: center; gap: 1rem;">
|
|
@@ -35,7 +35,7 @@ function handleAction(label: string) {
|
|
|
35
35
|
</AlertBox>
|
|
36
36
|
<p
|
|
37
37
|
v-if="actionFired"
|
|
38
|
-
style="margin-top: 0.75rem; font-size: 0.8rem; color: var(--mint-success, #10B981); font-family:
|
|
38
|
+
style="margin-top: 0.75rem; font-size: 0.8rem; color: var(--mint-success, #10B981); font-family: var(--font-mono);"
|
|
39
39
|
>
|
|
40
40
|
Action fired: "{{ actionFired }}"
|
|
41
41
|
</p>
|
|
@@ -111,7 +111,7 @@ function handleAction(label: string) {
|
|
|
111
111
|
|
|
112
112
|
<p
|
|
113
113
|
v-if="actionFired"
|
|
114
|
-
style="font-size: 0.8rem; color: var(--mint-success, #10B981); font-family:
|
|
114
|
+
style="font-size: 0.8rem; color: var(--mint-success, #10B981); font-family: var(--font-mono);"
|
|
115
115
|
>
|
|
116
116
|
Action fired: "{{ actionFired }}"
|
|
117
117
|
</p>
|
|
@@ -31,22 +31,24 @@ const hasActions = () => !!props.actionLabel || !!slots.actions
|
|
|
31
31
|
:class="`mint-alert--${props.tone}`"
|
|
32
32
|
role="alert"
|
|
33
33
|
>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
<
|
|
49
|
-
|
|
34
|
+
<span :class="['mint-alert__icon', `mint-alert__icon--${props.tone}`]">
|
|
35
|
+
<!-- Lucide circle-check -->
|
|
36
|
+
<svg v-if="props.tone === 'success'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round">
|
|
37
|
+
<circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" />
|
|
38
|
+
</svg>
|
|
39
|
+
<!-- Lucide circle-x -->
|
|
40
|
+
<svg v-else-if="props.tone === 'error'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round">
|
|
41
|
+
<circle cx="12" cy="12" r="10" /><path d="m15 9-6 6" /><path d="m9 9 6 6" />
|
|
42
|
+
</svg>
|
|
43
|
+
<!-- Lucide triangle-alert -->
|
|
44
|
+
<svg v-else-if="props.tone === 'warning'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round">
|
|
45
|
+
<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /><path d="M12 9v4" /><path d="M12 17h.01" />
|
|
46
|
+
</svg>
|
|
47
|
+
<!-- Lucide info -->
|
|
48
|
+
<svg v-else viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round">
|
|
49
|
+
<circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" />
|
|
50
|
+
</svg>
|
|
51
|
+
</span>
|
|
50
52
|
|
|
51
53
|
<div class="mint-alert__content">
|
|
52
54
|
<h4 v-if="props.title" class="mint-alert__title">
|
|
@@ -36,16 +36,12 @@ const sequencePanels: Record<string, SidebarToolSection[]> = {
|
|
|
36
36
|
label: 'Import Layout',
|
|
37
37
|
subtitle: 'Upload from Excel',
|
|
38
38
|
icon: icons.upload,
|
|
39
|
-
iconColor: '#3b82f6',
|
|
40
|
-
iconBg: '#dbeafe',
|
|
41
39
|
},
|
|
42
40
|
{
|
|
43
41
|
id: 'naming',
|
|
44
42
|
label: 'Experiment & Naming',
|
|
45
43
|
subtitle: 'exp001_260210_XP_M...',
|
|
46
44
|
icon: icons.fileText,
|
|
47
|
-
iconColor: '#6366f1',
|
|
48
|
-
iconBg: '#e0e7ff',
|
|
49
45
|
showToggle: true,
|
|
50
46
|
badge: 'on',
|
|
51
47
|
badgeTone: 'success',
|
|
@@ -55,8 +51,6 @@ const sequencePanels: Record<string, SidebarToolSection[]> = {
|
|
|
55
51
|
label: 'Randomize Samples',
|
|
56
52
|
subtitle: 'Sequential order',
|
|
57
53
|
icon: icons.shuffle,
|
|
58
|
-
iconColor: '#6366f1',
|
|
59
|
-
iconBg: '#e0e7ff',
|
|
60
54
|
showToggle: true,
|
|
61
55
|
badge: 3,
|
|
62
56
|
badgeTone: 'cta',
|
|
@@ -70,16 +64,12 @@ const sequencePanels: Record<string, SidebarToolSection[]> = {
|
|
|
70
64
|
label: 'Acquisition',
|
|
71
65
|
subtitle: 'NEG, VIAL',
|
|
72
66
|
icon: icons.zap,
|
|
73
|
-
iconColor: '#ef4444',
|
|
74
|
-
iconBg: '#fee2e2',
|
|
75
67
|
},
|
|
76
68
|
{
|
|
77
69
|
id: 'method',
|
|
78
70
|
label: 'Method & Path',
|
|
79
71
|
subtitle: 'Select method',
|
|
80
72
|
icon: icons.route,
|
|
81
|
-
iconColor: '#8b5cf6',
|
|
82
|
-
iconBg: '#ede9fe',
|
|
83
73
|
defaultOpen: false,
|
|
84
74
|
},
|
|
85
75
|
],
|
|
@@ -93,16 +83,12 @@ const simplePanels: Record<string, SidebarToolSection[]> = {
|
|
|
93
83
|
label: 'Parameters',
|
|
94
84
|
subtitle: 'Analysis settings',
|
|
95
85
|
icon: ['M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z', 'M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8z'],
|
|
96
|
-
iconColor: '#6366f1',
|
|
97
|
-
iconBg: '#e0e7ff',
|
|
98
86
|
},
|
|
99
87
|
{
|
|
100
88
|
id: 'filters',
|
|
101
89
|
label: 'Filters',
|
|
102
90
|
subtitle: 'Refine results',
|
|
103
91
|
icon: ['M22 3H2l8 9.46V19l4 2v-8.54L22 3'],
|
|
104
|
-
iconColor: '#0ea5e9',
|
|
105
|
-
iconBg: '#e0f2fe',
|
|
106
92
|
defaultOpen: false,
|
|
107
93
|
},
|
|
108
94
|
],
|
|
@@ -112,16 +98,12 @@ const simplePanels: Record<string, SidebarToolSection[]> = {
|
|
|
112
98
|
label: 'Display Options',
|
|
113
99
|
subtitle: 'Chart and table settings',
|
|
114
100
|
icon: ['M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z', 'M12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6z'],
|
|
115
|
-
iconColor: '#8b5cf6',
|
|
116
|
-
iconBg: '#ede9fe',
|
|
117
101
|
},
|
|
118
102
|
{
|
|
119
103
|
id: 'export',
|
|
120
104
|
label: 'Export',
|
|
121
105
|
subtitle: 'Download data',
|
|
122
106
|
icon: ['M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4', 'M7 10l5 5 5-5', 'M12 15V3'],
|
|
123
|
-
iconColor: '#10b981',
|
|
124
|
-
iconBg: '#d1fae5',
|
|
125
107
|
defaultOpen: false,
|
|
126
108
|
},
|
|
127
109
|
],
|
|
@@ -163,8 +145,6 @@ const schemaControls = defineControls({
|
|
|
163
145
|
view: 'analysis',
|
|
164
146
|
sidebar: {
|
|
165
147
|
icon: icons.settings,
|
|
166
|
-
iconColor: '#6366f1',
|
|
167
|
-
iconBg: '#e0e7ff',
|
|
168
148
|
},
|
|
169
149
|
},
|
|
170
150
|
method: {
|
|
@@ -180,16 +160,12 @@ const schemaControls = defineControls({
|
|
|
180
160
|
default: true,
|
|
181
161
|
hint: 'Keep flagged points visible',
|
|
182
162
|
icon: icons.eye,
|
|
183
|
-
iconColor: '#0ea5e9',
|
|
184
|
-
iconBg: '#e0f2fe',
|
|
185
163
|
section: 'display',
|
|
186
164
|
sectionLabel: 'Display',
|
|
187
165
|
sectionSubtitle: 'Result filters',
|
|
188
166
|
view: 'analysis',
|
|
189
167
|
sidebar: {
|
|
190
168
|
icon: icons.zap,
|
|
191
|
-
iconColor: '#0ea5e9',
|
|
192
|
-
iconBg: '#e0f2fe',
|
|
193
169
|
defaultOpen: false,
|
|
194
170
|
},
|
|
195
171
|
},
|
|
@@ -215,8 +191,6 @@ const modelDrivenSidebarModel = defineControlModel({
|
|
|
215
191
|
description: 'Result cleanup',
|
|
216
192
|
sidebar: {
|
|
217
193
|
icon: icons.zap,
|
|
218
|
-
iconColor: '#0ea5e9',
|
|
219
|
-
iconBg: '#e0f2fe',
|
|
220
194
|
defaultOpen: false,
|
|
221
195
|
},
|
|
222
196
|
controls: {
|
|
@@ -225,8 +199,6 @@ const modelDrivenSidebarModel = defineControlModel({
|
|
|
225
199
|
default: true,
|
|
226
200
|
hint: 'Keep flagged points visible',
|
|
227
201
|
icon: icons.eye,
|
|
228
|
-
iconColor: '#0ea5e9',
|
|
229
|
-
iconBg: '#e0f2fe',
|
|
230
202
|
},
|
|
231
203
|
minPeakArea: { type: 'number', default: 1000, min: 0 },
|
|
232
204
|
},
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import AppTopBar from './AppTopBar.vue'
|
|
3
3
|
import Avatar from './Avatar.vue'
|
|
4
|
+
import PluginIcon from './PluginIcon.vue'
|
|
4
5
|
import { ExperimentProvider } from '../__stories__/experiment-helpers'
|
|
6
|
+
import { providePluginIdentity } from '../composables/pluginIdentity'
|
|
7
|
+
import type { App } from 'vue'
|
|
5
8
|
import type {
|
|
6
9
|
TopBarVariant,
|
|
7
10
|
PillNavItem,
|
|
@@ -59,6 +62,25 @@ const samplePlugin: PluginInfo = {
|
|
|
59
62
|
settings_api: 'platform',
|
|
60
63
|
}
|
|
61
64
|
|
|
65
|
+
const samplePluginWithSubtitle: PluginInfo = {
|
|
66
|
+
...samplePlugin,
|
|
67
|
+
id: 'ms-planner',
|
|
68
|
+
name: 'ms-planner',
|
|
69
|
+
display_name: 'MS Planner',
|
|
70
|
+
subtitle: 'Experiment Scheduler',
|
|
71
|
+
icon: 'calendar',
|
|
72
|
+
route_prefix: '/ms-planner',
|
|
73
|
+
api_prefix: '/api/ms-planner',
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// The seed is module state: clear it when the variant unmounts.
|
|
77
|
+
function seedIdentity({ app }: { app: App }) {
|
|
78
|
+
providePluginIdentity({
|
|
79
|
+
plugin: { name: 'ms-planner', displayName: 'MS Planner', subtitle: 'Experiment Scheduler', icon: 'calendar' },
|
|
80
|
+
})
|
|
81
|
+
app.onUnmount(() => providePluginIdentity({ plugin: { name: '' } }))
|
|
82
|
+
}
|
|
83
|
+
|
|
62
84
|
</script>
|
|
63
85
|
|
|
64
86
|
<template>
|
|
@@ -82,18 +104,7 @@ const samplePlugin: PluginInfo = {
|
|
|
82
104
|
pill="experiments"
|
|
83
105
|
>
|
|
84
106
|
<template #icon>
|
|
85
|
-
<
|
|
86
|
-
style="width: 2.25rem; height: 2.25rem; border-radius: 0.5rem; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #F97316 0%, #FB923C 100%);"
|
|
87
|
-
>
|
|
88
|
-
<svg
|
|
89
|
-
style="width: 1.25rem; height: 1.25rem; color: white;"
|
|
90
|
-
fill="none"
|
|
91
|
-
stroke="currentColor"
|
|
92
|
-
viewBox="0 0 24 24"
|
|
93
|
-
>
|
|
94
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" />
|
|
95
|
-
</svg>
|
|
96
|
-
</div>
|
|
107
|
+
<PluginIcon size="topbar" />
|
|
97
108
|
</template>
|
|
98
109
|
</AppTopBar>
|
|
99
110
|
</div>
|
|
@@ -223,6 +234,20 @@ const samplePlugin: PluginInfo = {
|
|
|
223
234
|
</div>
|
|
224
235
|
</Variant>
|
|
225
236
|
|
|
237
|
+
<Variant title="Identity · Integrated with subtitle">
|
|
238
|
+
<div style="padding: 2rem; background: var(--bg-primary); min-height: 12rem;">
|
|
239
|
+
<ExperimentProvider :plugin="samplePluginWithSubtitle">
|
|
240
|
+
<AppTopBar :spec="{ pills: samplePillNav, homePath: '' }" pill="workspace" />
|
|
241
|
+
</ExperimentProvider>
|
|
242
|
+
</div>
|
|
243
|
+
</Variant>
|
|
244
|
+
|
|
245
|
+
<Variant title="Identity · Standalone seeded" :setup-app="seedIdentity">
|
|
246
|
+
<div style="padding: 2rem;">
|
|
247
|
+
<AppTopBar :spec="{ pills: samplePillNav, homePath: '' }" pill="workspace" />
|
|
248
|
+
</div>
|
|
249
|
+
</Variant>
|
|
250
|
+
|
|
226
251
|
<Variant title="Navigation · Page selector">
|
|
227
252
|
<div style="padding: 2rem;">
|
|
228
253
|
<AppTopBar
|
|
@@ -244,6 +269,16 @@ const samplePlugin: PluginInfo = {
|
|
|
244
269
|
</div>
|
|
245
270
|
</Variant>
|
|
246
271
|
|
|
272
|
+
<Variant title="Navigation · Pill nav overflow (More)">
|
|
273
|
+
<div style="padding: 2rem; min-height: 14rem;">
|
|
274
|
+
<AppTopBar
|
|
275
|
+
:spec="{ pills: ['Queue', 'Calendar', 'Utilization', 'Instruments', 'Reports', 'Settings', 'Logs'], homePath: '' }"
|
|
276
|
+
title="MS Planner"
|
|
277
|
+
pill="Reports"
|
|
278
|
+
/>
|
|
279
|
+
</div>
|
|
280
|
+
</Variant>
|
|
281
|
+
|
|
247
282
|
<Variant title="Navigation · Pill nav with dropdown and dot">
|
|
248
283
|
<div style="padding: 2rem;">
|
|
249
284
|
<AppTopBar
|