@morscherlab/mint-sdk 1.4.0-beta.2 → 1.4.0-beta.20
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 +14 -3
- package/dist/{ActionMenu-CScINahU.js → AlertBox-CzLg0UaL.js} +40 -209
- package/dist/AlertBox-CzLg0UaL.js.map +1 -0
- package/dist/{AppSidebar-BmiiPfz9.js → AppSidebar-6oTT-gPO.js} +1249 -239
- package/dist/AppSidebar-6oTT-gPO.js.map +1 -0
- package/dist/{ConfirmDialog-CJ7hqYUP.js → ConfirmDialog-CSls2Nuv.js} +2 -2
- package/dist/{ConfirmDialog-CJ7hqYUP.js.map → ConfirmDialog-CSls2Nuv.js.map} +1 -1
- package/dist/ExperimentPopover-9l4QZlvQ.js +337 -0
- package/dist/ExperimentPopover-9l4QZlvQ.js.map +1 -0
- package/dist/{ExperimentSelectorModal-D-9z7cNx.js → ExperimentSelectorModal-pR5fK3pA.js} +244 -211
- package/dist/ExperimentSelectorModal-pR5fK3pA.js.map +1 -0
- package/dist/{SegmentedControl-DERBN-Xd.js → SegmentedControl-CJ7EAmOq.js} +2 -2
- package/dist/{SegmentedControl-DERBN-Xd.js.map → SegmentedControl-CJ7EAmOq.js.map} +1 -1
- package/dist/{SettingsModal-CSLE31yg.js → SettingsModal-Dyitgzfp.js} +28 -27
- package/dist/SettingsModal-Dyitgzfp.js.map +1 -0
- package/dist/__stories__/experiment-helpers.d.ts +10 -0
- package/dist/__tests__/components/AppTopBarOnboarding.test.d.ts +1 -0
- package/dist/__tests__/composables/useOnboarding.test.d.ts +1 -0
- package/dist/__tests__/styles/paletteTokens.test.d.ts +1 -0
- package/dist/__tests__/styles/v2AuditRules.test.d.ts +1 -0
- package/dist/components/AppSidebar.vue.d.ts +1 -1
- package/dist/components/AppTopBar.vue.d.ts +20 -5
- package/dist/components/ArtifactSaveDialog.vue.d.ts +9 -1
- package/dist/components/AuditTrail.vue.d.ts +1 -1
- package/dist/components/BaseButton.vue.d.ts +4 -2
- 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 +15 -5
- package/dist/components/FilePicker.vue.d.ts +1 -1
- package/dist/components/FileUploader.vue.d.ts +2 -2
- package/dist/components/JobsStatusTray.vue.d.ts +15 -4
- package/dist/components/PluginIcon.vue.d.ts +2 -2
- package/dist/components/PluginWorkspaceView.props.d.ts +3 -0
- package/dist/components/PluginWorkspaceView.vue.d.ts +3 -0
- package/dist/components/SampleSelector.vue.d.ts +6 -6
- package/dist/components/SequenceProgressBar.vue.d.ts +3 -0
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +1 -1
- package/dist/components/StepWizard.vue.d.ts +3 -0
- package/dist/components/internal/AppTopBarOnboardingInternal.vue.d.ts +7 -0
- package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -1
- package/dist/components/internal/AutoGroupModalInternal.vue.d.ts +1 -1
- package/dist/components/internal/DatePickerTimeInternal.vue.d.ts +1 -1
- package/dist/components/internal/OnboardingLayerInternal.vue.d.ts +7 -0
- package/dist/components/internal/ResourcePickerListInternal.vue.d.ts +2 -7
- package/dist/components/internal/SelectMultipleInternal.vue.d.ts +4 -0
- package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +8 -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/useJobCenter.d.ts +41 -3
- package/dist/composables/useOnboarding.d.ts +119 -0
- package/dist/composables/usePlatform.d.ts +1 -0
- package/dist/{controlSchemaModel-CP5-_nAj.js → controlSchemaModel-DCUOx8ll.js} +2 -2
- package/dist/{controlSchemaModel-CP5-_nAj.js.map → controlSchemaModel-DCUOx8ll.js.map} +1 -1
- package/dist/{data-C2PwI_dn.js → data-DBnmeBZX.js} +179 -125
- package/dist/data-DBnmeBZX.js.map +1 -0
- package/dist/data.js +8 -8
- package/dist/{experiment-43OJtH7R.js → experiment-DyO54FQB.js} +25 -61
- package/dist/experiment-DyO54FQB.js.map +1 -0
- package/dist/{experimentStatus-BZmU4czV.js → experimentStatus-BFrKpHAH.js} +3 -3
- package/dist/{experimentStatus-BZmU4czV.js.map → experimentStatus-BFrKpHAH.js.map} +1 -1
- package/dist/index.js +20 -20
- package/dist/{install-DAID6c2-.js → install-qjELyNwc.js} +15 -14
- package/dist/{install-DAID6c2-.js.map → install-qjELyNwc.js.map} +1 -1
- package/dist/install.js +1 -1
- package/dist/{lab-DLwRl_Ql.js → lab-UyTbokQC.js} +136 -148
- package/dist/lab-UyTbokQC.js.map +1 -0
- package/dist/lab.js +4 -3
- package/dist/{records-BzTcxekG.js → records-CR_pYzIP.js} +533 -335
- package/dist/records-CR_pYzIP.js.map +1 -0
- package/dist/{runtime-D6gVat6r.js → runtime-CoHhBP10.js} +417 -54
- package/dist/runtime-CoHhBP10.js.map +1 -0
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +7 -7
- package/dist/{shell-5ju97nOS.js → shell-BDuZf2zb.js} +10 -5
- package/dist/{shell-5ju97nOS.js.map → shell-BDuZf2zb.js.map} +1 -1
- package/dist/shell.d.ts +1 -0
- package/dist/shell.js +6 -6
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.js +2 -2
- package/dist/stores/settings.d.ts +4 -12
- package/dist/styles.css +2732 -2083
- package/dist/types/componentWorkflowTypes.d.ts +2 -0
- package/dist/types/components.d.ts +2 -0
- package/dist/types/generated/platformContext.d.ts +1 -0
- package/dist/types/generated-ui.d.ts +4 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/jobs.d.ts +9 -0
- package/dist/types/platform.d.ts +1 -1
- package/dist/{BaseModal-DfRIuVoj.js → useDropdownState-Bb2N4m40.js} +74 -4
- package/dist/useDropdownState-Bb2N4m40.js.map +1 -0
- package/dist/{useExperimentSamples-CxcnxZ8h.js → useExperimentSamples-Dno1fFMq.js} +4 -4
- package/dist/{useExperimentSamples-CxcnxZ8h.js.map → useExperimentSamples-Dno1fFMq.js.map} +1 -1
- package/dist/{useListReorder-CcbEYxX-.js → useListReorder-CQ9OCScc.js} +183 -351
- package/dist/useListReorder-CQ9OCScc.js.map +1 -0
- package/dist/{useRackEditor-BD5NIo5s.js → useRackEditor-wL3kPrRT.js} +73 -59
- package/dist/useRackEditor-wL3kPrRT.js.map +1 -0
- package/dist/useRealtime-C3whhVvb.js +508 -0
- package/dist/useRealtime-C3whhVvb.js.map +1 -0
- package/dist/useRequest-CDkrXNU7.js +244 -0
- package/dist/useRequest-CDkrXNU7.js.map +1 -0
- package/dist/utils/time.d.ts +7 -0
- package/package.json +1 -1
- package/src/__stories__/experiment-helpers.ts +3 -3
- package/src/__tests__/components/AppTopBar.test.ts +257 -3
- package/src/__tests__/components/AppTopBarOnboarding.test.ts +160 -0
- package/src/__tests__/components/AppTopBarPageSelector.test.ts +125 -9
- package/src/__tests__/components/AppTopBarPillNav.test.ts +35 -0
- package/src/__tests__/components/ArtifactSaveDialog.test.ts +78 -0
- package/src/__tests__/components/BaseButton.test.ts +19 -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 +153 -14
- package/src/__tests__/components/GeneratedPluginView.test.ts +23 -2
- package/src/__tests__/components/InstrumentStateBadge.test.ts +4 -4
- package/src/__tests__/components/JobsStatusTray.test.ts +373 -71
- package/src/__tests__/components/PluginWorkspaceView.test.ts +63 -1
- package/src/__tests__/components/ResourcePickerListInternal.test.ts +0 -20
- package/src/__tests__/components/SampleSelector.test.ts +33 -8
- package/src/__tests__/components/SequenceProgressBar.test.ts +12 -0
- package/src/__tests__/components/SettingsModal.test.ts +9 -2
- 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__/composables/useJobCenter.test.ts +262 -3
- package/src/__tests__/composables/useOnboarding.test.ts +317 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +4 -3
- package/src/__tests__/stores/settings.test.ts +21 -21
- 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 +6 -3
- package/src/__tests__/styles/menusShellRefresh.test.ts +22 -12
- package/src/__tests__/styles/paletteTokens.test.ts +44 -0
- package/src/__tests__/styles/v2AuditRules.test.ts +104 -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.onboarding.story.vue +69 -0
- package/src/components/AppTopBar.story.vue +105 -15
- package/src/components/AppTopBar.vue +248 -122
- 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/BaseButton.vue +16 -2
- 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 +73 -31
- package/src/components/ExperimentSelectorModal.vue +144 -111
- package/src/components/FormField.story.vue +8 -48
- package/src/components/GeneratedPluginView.vue +11 -10
- package/src/components/GeneratedResultRenderer.vue +3 -4
- package/src/components/InstrumentStateBadge.vue +1 -1
- package/src/components/JobsStatusTray.story.vue +97 -43
- package/src/components/JobsStatusTray.vue +287 -290
- package/src/components/LayoutResizeHandle.story.vue +65 -4
- 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.props.ts +3 -0
- package/src/components/PluginWorkspaceView.story.vue +1 -1
- package/src/components/PluginWorkspaceView.vue +17 -0
- package/src/components/RuntimeUpdateNotice.vue +1 -1
- package/src/components/SampleSelector.story.vue +22 -7
- package/src/components/SampleSelector.vue +34 -37
- package/src/components/SampleSelectorGroupNode.vue +1 -1
- package/src/components/SectionCard.story.vue +35 -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 +9 -14
- 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/AppTopBarOnboardingInternal.vue +172 -0
- package/src/components/internal/AppTopBarPageSelectorInternal.vue +140 -72
- 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/OnboardingLayerInternal.vue +173 -0
- 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/components/internal/WorkspaceShellInternal.vue +12 -0
- 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/useJobCenter.ts +188 -6
- package/src/composables/useOnboarding.ts +465 -0
- package/src/composables/usePluginWorkspace.ts +1 -1
- package/src/runtime.ts +2 -1
- package/src/shell.ts +17 -0
- package/src/stores/index.ts +0 -2
- package/src/stores/settings.ts +20 -50
- 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 +121 -44
- 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 +219 -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 +36 -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 +88 -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 +140 -296
- package/src/styles/components/layout-resize-handle.css +59 -16
- 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/onboarding.css +368 -0
- 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 +138 -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 +54 -49
- 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/index.css +1 -0
- package/src/styles/variables.css +241 -78
- package/src/types/componentWorkflowTypes.ts +2 -0
- package/src/types/components.ts +2 -0
- package/src/types/generated/platformContext.ts +1 -0
- package/src/types/generated-ui.ts +4 -0
- package/src/types/index.ts +1 -0
- package/src/types/jobs.ts +10 -0
- package/src/types/platform.ts +1 -1
- 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/experiment-43OJtH7R.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 +0 -696
- package/dist/useRealtime-PalKue84.js.map +0 -1
- package/dist/useRequest-D5JDfsgZ.js +0 -76
- package/dist/useRequest-D5JDfsgZ.js.map +0 -1
|
@@ -3,15 +3,20 @@ import { ref } from 'vue'
|
|
|
3
3
|
import LayoutResizeHandle from './LayoutResizeHandle.vue'
|
|
4
4
|
|
|
5
5
|
const width = ref(320)
|
|
6
|
+
const gapWidth = ref(320)
|
|
7
|
+
const edgeWidth = ref(280)
|
|
8
|
+
const height = ref(50)
|
|
9
|
+
|
|
10
|
+
const panel = 'background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--radius-lg); padding: 0.75rem;'
|
|
11
|
+
const caption = 'margin: 0 0 0.5rem; font: 0.75rem var(--font-mono); color: var(--text-secondary);'
|
|
6
12
|
</script>
|
|
7
13
|
|
|
8
14
|
<template>
|
|
9
15
|
<Story title="Layout/LayoutResizeHandle">
|
|
10
16
|
<Variant title="Keyboard splitter">
|
|
17
|
+
<!-- Directly between two panels, the handle is the gutter. -->
|
|
11
18
|
<div style="display: flex; height: 16rem; padding: 2rem;">
|
|
12
|
-
<div :style="{ width:
|
|
13
|
-
Panel width: {{ width }}px
|
|
14
|
-
</div>
|
|
19
|
+
<div :style="`${panel} width: ${width}px;`">Panel width: {{ width }}px</div>
|
|
15
20
|
<LayoutResizeHandle
|
|
16
21
|
v-model="width"
|
|
17
22
|
orientation="vertical"
|
|
@@ -19,7 +24,63 @@ const width = ref(320)
|
|
|
19
24
|
:min="240"
|
|
20
25
|
:max="480"
|
|
21
26
|
/>
|
|
22
|
-
<div style="flex: 1
|
|
27
|
+
<div :style="`${panel} flex: 1;`" />
|
|
28
|
+
</div>
|
|
29
|
+
</Variant>
|
|
30
|
+
|
|
31
|
+
<Variant title="Gaps and edge">
|
|
32
|
+
<div style="display: grid; gap: 1.5rem; padding: 2rem;">
|
|
33
|
+
<div data-gap="flex-8">
|
|
34
|
+
<p :style="caption">flex, 8px gutter (compact), handle between the panels</p>
|
|
35
|
+
<div style="display: flex; height: 8rem; --mint-gutter: 0.5rem;">
|
|
36
|
+
<div :style="`${panel} width: ${gapWidth}px;`">Left panel</div>
|
|
37
|
+
<LayoutResizeHandle v-model="gapWidth" orientation="vertical" label="Resize left panel (8px)" :min="200" :max="480" />
|
|
38
|
+
<div :style="`${panel} flex: 1;`">Right panel</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
<div data-gap="wrapper-12">
|
|
42
|
+
<p :style="caption">flex, 12px gutter, handle in a gutter-wide wrapper</p>
|
|
43
|
+
<div style="display: flex; height: 8rem; --mint-gutter: 0.75rem;">
|
|
44
|
+
<div :style="`${panel} width: ${gapWidth}px;`">Left panel</div>
|
|
45
|
+
<div style="display: flex; justify-content: center; flex-shrink: 0; width: var(--mint-gutter);">
|
|
46
|
+
<LayoutResizeHandle v-model="gapWidth" orientation="vertical" label="Resize left panel (12px)" :min="200" :max="480" />
|
|
47
|
+
</div>
|
|
48
|
+
<div :style="`${panel} flex: 1;`">Right panel</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
<div data-gap="grid-8">
|
|
52
|
+
<p :style="caption">grid, 8px track</p>
|
|
53
|
+
<div :style="`display: grid; grid-template-columns: ${gapWidth}px 0.5rem 1fr; height: 8rem;`">
|
|
54
|
+
<div :style="panel">Left panel</div>
|
|
55
|
+
<LayoutResizeHandle
|
|
56
|
+
v-model="gapWidth"
|
|
57
|
+
orientation="vertical"
|
|
58
|
+
label="Resize left panel (grid)"
|
|
59
|
+
:min="200"
|
|
60
|
+
:max="480"
|
|
61
|
+
style="--mint-layout-resize-gap: 0.5rem;"
|
|
62
|
+
/>
|
|
63
|
+
<div :style="panel">Right panel</div>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
<div data-gap="edge">
|
|
67
|
+
<p :style="caption">edge="right", 12px gutter</p>
|
|
68
|
+
<div style="display: flex; gap: var(--mint-gutter); height: 8rem; --mint-gutter: 0.75rem;">
|
|
69
|
+
<aside :style="`${panel} position: relative; width: ${edgeWidth}px;`">
|
|
70
|
+
Sidebar
|
|
71
|
+
<LayoutResizeHandle v-model="edgeWidth" orientation="vertical" edge="right" label="Resize sidebar" :min="200" :max="480" />
|
|
72
|
+
</aside>
|
|
73
|
+
<div :style="`${panel} flex: 1;`">Main</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
<div data-gap="horizontal">
|
|
77
|
+
<p :style="caption">horizontal, 8px gutter</p>
|
|
78
|
+
<div style="display: flex; flex-direction: column; height: 14rem; --mint-gutter: 0.5rem;">
|
|
79
|
+
<div :style="`${panel} flex: 0 0 ${height}%;`">Top panel</div>
|
|
80
|
+
<LayoutResizeHandle v-model="height" orientation="horizontal" label="Resize top panel" :min="20" :max="80" :step="1" />
|
|
81
|
+
<div :style="`${panel} flex: 1;`">Bottom panel</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
23
84
|
</div>
|
|
24
85
|
</Variant>
|
|
25
86
|
</Story>
|
|
@@ -40,7 +40,7 @@ withDefaults(defineProps<Props>(), {
|
|
|
40
40
|
<path
|
|
41
41
|
style="opacity: 0.75"
|
|
42
42
|
fill="currentColor"
|
|
43
|
-
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0
|
|
43
|
+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
|
|
44
44
|
/>
|
|
45
45
|
</svg>
|
|
46
46
|
<span class="mint-spinner__label">{{ label }}</span>
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
12
|
import { computed, onBeforeUnmount, useAttrs, type StyleValue } from 'vue'
|
|
13
|
+
import { ChevronDown, ChevronUp } from 'lucide-vue-next'
|
|
13
14
|
import type { UnitOption } from '../types'
|
|
14
15
|
import NumberUnitInputInternal from './internal/NumberUnitInputInternal.vue'
|
|
15
16
|
|
|
@@ -287,9 +288,7 @@ function handleScrubStart(event: PointerEvent) {
|
|
|
287
288
|
class="mint-number-input__stepper mint-number-input__stepper--down"
|
|
288
289
|
@click="decrement"
|
|
289
290
|
>
|
|
290
|
-
<
|
|
291
|
-
<path d="M2 5h6" />
|
|
292
|
-
</svg>
|
|
291
|
+
<ChevronDown :size="12" :stroke-width="2.25" />
|
|
293
292
|
</button>
|
|
294
293
|
<button
|
|
295
294
|
type="button"
|
|
@@ -299,9 +298,7 @@ function handleScrubStart(event: PointerEvent) {
|
|
|
299
298
|
class="mint-number-input__stepper mint-number-input__stepper--up"
|
|
300
299
|
@click="increment"
|
|
301
300
|
>
|
|
302
|
-
<
|
|
303
|
-
<path d="M5 2v6" /><path d="M2 5h6" />
|
|
304
|
-
</svg>
|
|
301
|
+
<ChevronUp :size="12" :stroke-width="2.25" />
|
|
305
302
|
</button>
|
|
306
303
|
</div>
|
|
307
304
|
</div>
|
|
@@ -52,8 +52,8 @@ function initState() {
|
|
|
52
52
|
<HstText v-model="state.icon" title="icon" />
|
|
53
53
|
<HstSelect v-model="state.size" title="size" :options="['sm', 'md', 'topbar', 'lg']" />
|
|
54
54
|
<HstSelect v-model="state.variant" title="variant" :options="['solid', 'tinted']" />
|
|
55
|
-
<HstSelect v-model="state.tone" title="tone" :options="['', 'neutral', 'primary', 'cta', 'success', 'warning', 'error', 'info']" />
|
|
56
|
-
<HstText v-model="state.color" title="color (
|
|
55
|
+
<HstSelect v-model="state.tone" title="tone (deprecated, no effect; removed in 1.5)" :options="['', 'neutral', 'primary', 'cta', 'success', 'warning', 'error', 'info']" />
|
|
56
|
+
<HstText v-model="state.color" title="color (deprecated, no effect; removed in 1.5)" />
|
|
57
57
|
</template>
|
|
58
58
|
</Variant>
|
|
59
59
|
|
|
@@ -94,13 +94,5 @@ function initState() {
|
|
|
94
94
|
<PluginIcon :icon="SAMPLE_STRUCTURED" size="lg" />
|
|
95
95
|
</div>
|
|
96
96
|
</Variant>
|
|
97
|
-
|
|
98
|
-
<Variant title="Tone overrides">
|
|
99
|
-
<div style="padding: 2rem; display: flex; gap: 1rem; align-items: center;">
|
|
100
|
-
<PluginIcon :icon="SAMPLE_PATH" size="lg" variant="solid" color="#0EA5E9" />
|
|
101
|
-
<PluginIcon :icon="SAMPLE_PATH" size="lg" variant="solid" color="#F97316" />
|
|
102
|
-
<PluginIcon :icon="SAMPLE_PATH" size="lg" variant="solid" color="#22C55E" />
|
|
103
|
-
</div>
|
|
104
|
-
</Variant>
|
|
105
97
|
</Story>
|
|
106
98
|
</template>
|
|
@@ -18,9 +18,9 @@ interface Props {
|
|
|
18
18
|
icon?: string
|
|
19
19
|
size?: 'sm' | 'md' | 'topbar' | 'lg'
|
|
20
20
|
variant?: 'solid' | 'tinted'
|
|
21
|
-
/**
|
|
21
|
+
/** @deprecated v2 design: the tile is always the neutral accent-soft tile, so the tone has no visible effect. Removed in 1.5. */
|
|
22
22
|
tone?: Tone
|
|
23
|
-
/**
|
|
23
|
+
/** @deprecated v2 design: the tile is always the neutral accent-soft tile, so the color has no visible effect. Removed in 1.5. */
|
|
24
24
|
color?: string
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
PillNavOption,
|
|
5
5
|
PluginWorkspaceViewSpec,
|
|
6
6
|
} from '../types'
|
|
7
|
+
import type { JobState } from '../types/jobs'
|
|
7
8
|
import type {
|
|
8
9
|
ControlComponentBinding,
|
|
9
10
|
ControlComponentBindingsById,
|
|
@@ -46,6 +47,8 @@ export interface PluginWorkspaceViewEmits {
|
|
|
46
47
|
'section-action': [sectionId: string, actionId: string]
|
|
47
48
|
'form-submit': [sectionId: string, values: Record<string, unknown>]
|
|
48
49
|
'form-cancel': [sectionId: string]
|
|
50
|
+
/** A job row in the jobs tray, or the just-completed job on the top-bar chip, was chosen. */
|
|
51
|
+
'job-select': [job: JobState]
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
/** Typed `emit` function shape produced by `defineEmits<PluginWorkspaceViewEmits>()`. */
|
|
@@ -274,7 +274,7 @@ async function saveDoseDesign() {
|
|
|
274
274
|
</PluginWorkspaceView>
|
|
275
275
|
<p
|
|
276
276
|
v-if="lastExperimentEvent"
|
|
277
|
-
style="padding: 0.75rem 1rem; margin: 0; font-family:
|
|
277
|
+
style="padding: 0.75rem 1rem; margin: 0; font-family: var(--font-mono); font-size: 0.75rem; color: var(--text-muted);"
|
|
278
278
|
>
|
|
279
279
|
Last shell event: {{ lastExperimentEvent }}
|
|
280
280
|
</p>
|
|
@@ -20,9 +20,12 @@ import type {
|
|
|
20
20
|
PillNavItem,
|
|
21
21
|
PillNavOption,
|
|
22
22
|
} from '../types'
|
|
23
|
+
import type { JobState } from '../types/jobs'
|
|
23
24
|
import { useAppExperiment } from '../composables/useAppExperiment'
|
|
25
|
+
import { useJobCenter } from '../composables/useJobCenter'
|
|
24
26
|
import { usePluginWorkspace } from '../composables/usePluginWorkspace'
|
|
25
27
|
import AppToastContainer from './AppToastContainer.vue'
|
|
28
|
+
import JobsStatusTray from './JobsStatusTray.vue'
|
|
26
29
|
import WorkspaceControlsInternal from './internal/WorkspaceControlsInternal.vue'
|
|
27
30
|
import WorkspaceShellInternal from './internal/WorkspaceShellInternal.vue'
|
|
28
31
|
import WorkspaceSidebarInternal from './internal/WorkspaceSidebarInternal.vue'
|
|
@@ -76,6 +79,14 @@ if (props.spec.experiment) {
|
|
|
76
79
|
})
|
|
77
80
|
}
|
|
78
81
|
|
|
82
|
+
// The job center is setup-time structure too: no `jobs`, no jobs control.
|
|
83
|
+
const jobs = props.spec.jobs
|
|
84
|
+
const jobCenter = jobs ? useJobCenter({ source: jobs }) : null
|
|
85
|
+
|
|
86
|
+
function handleJobSelect(job: JobState) {
|
|
87
|
+
emit('job-select', job)
|
|
88
|
+
}
|
|
89
|
+
|
|
79
90
|
const {
|
|
80
91
|
shell,
|
|
81
92
|
sidebar,
|
|
@@ -105,6 +116,11 @@ function handleFormCancel(sectionId: string) {
|
|
|
105
116
|
<template>
|
|
106
117
|
<WorkspaceShellInternal
|
|
107
118
|
:shell="shell"
|
|
119
|
+
:job="jobCenter ? jobCenter.topBarJob.value : undefined"
|
|
120
|
+
:jobs-done="jobCenter?.completedCount.value"
|
|
121
|
+
:jobs-open="jobCenter?.isOpen.value"
|
|
122
|
+
:jobs-panel-id="jobCenter?.panelId"
|
|
123
|
+
@job-click="jobCenter?.handleTopBarClick(handleJobSelect)"
|
|
108
124
|
@pill-select="handlePillSelect"
|
|
109
125
|
@pill-option-select="(option: PillNavOption, item: PillNavItem) => emit('pill-option-select', option, item)"
|
|
110
126
|
@settings-values-change="emit('settings-values-change', $event)"
|
|
@@ -158,6 +174,7 @@ function handleFormCancel(sectionId: string) {
|
|
|
158
174
|
</template>
|
|
159
175
|
</WorkspaceControlsInternal>
|
|
160
176
|
<AppToastContainer v-if="spec.toasts !== false" />
|
|
177
|
+
<JobsStatusTray v-if="jobCenter" :center="jobCenter" @select="handleJobSelect" />
|
|
161
178
|
</template>
|
|
162
179
|
</WorkspaceShellInternal>
|
|
163
180
|
</template>
|
|
@@ -21,6 +21,13 @@ const mockGroups: SampleGroup[] = [
|
|
|
21
21
|
{ name: 'Vehicle', color: '#F59E0B', samples: ['Vehicle_Rep1', 'Vehicle_Rep2', 'Vehicle_Rep3'] },
|
|
22
22
|
]
|
|
23
23
|
|
|
24
|
+
// 1024 selected runs in two groups: the long count must not push the actions out.
|
|
25
|
+
const manyRuns = Array.from({ length: 1024 }, (_, i) => `Run_${String(i + 1).padStart(4, '0')}`)
|
|
26
|
+
const manyGroups: SampleGroup[] = [
|
|
27
|
+
{ name: 'Batch A', color: '#3B82F6', samples: manyRuns.slice(0, 512) },
|
|
28
|
+
{ name: 'Batch B', color: '#10B981', samples: manyRuns.slice(512) },
|
|
29
|
+
]
|
|
30
|
+
|
|
24
31
|
const manualSamples = [
|
|
25
32
|
'Pt001_TumorA_d7_rep1',
|
|
26
33
|
'Pt001_TumorA_d7_rep1_reseq2024',
|
|
@@ -135,13 +142,21 @@ function handleSmartGroup(result: AutoGroupResult, state: { groups: SampleGroup[
|
|
|
135
142
|
</div>
|
|
136
143
|
</Variant>
|
|
137
144
|
|
|
138
|
-
<Variant title="Narrow
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
+
<Variant title="Narrow Header">
|
|
146
|
+
<!-- At 17.625rem of header content width and below, the grouping button shows only its icon and the count shortens. -->
|
|
147
|
+
<div style="display: flex; align-items: flex-start; gap: 2rem; padding: 2rem;">
|
|
148
|
+
<div v-for="width in [220, 300, 340]" :key="width" :data-width="width" :style="{ width: `${width}px` }">
|
|
149
|
+
<p style="margin: 0 0 0.5rem; font: 0.75rem var(--font-mono); color: var(--text-secondary);">{{ width }}px</p>
|
|
150
|
+
<SampleSelector
|
|
151
|
+
:model-value="['Control_Rep1']"
|
|
152
|
+
:samples="mockSamples"
|
|
153
|
+
:groups="mockGroups"
|
|
154
|
+
/>
|
|
155
|
+
</div>
|
|
156
|
+
<div data-width="320-long" style="width: 320px; height: 22rem;">
|
|
157
|
+
<p style="margin: 0 0 0.5rem; font: 0.75rem var(--font-mono); color: var(--text-secondary);">320px, 1024 selected</p>
|
|
158
|
+
<SampleSelector :model-value="manyRuns" :samples="manyRuns" :groups="manyGroups" />
|
|
159
|
+
</div>
|
|
145
160
|
</div>
|
|
146
161
|
</Variant>
|
|
147
162
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/** Interactive sample list with drag-and-drop group assignment, color labeling, and smart-group support. */
|
|
3
3
|
import { ref, computed } from 'vue'
|
|
4
|
+
import { Layers, RotateCcw, WandSparkles } from 'lucide-vue-next'
|
|
4
5
|
import BaseButton from './BaseButton.vue'
|
|
5
6
|
import BaseCheckbox from './BaseCheckbox.vue'
|
|
6
7
|
import BaseInput from './BaseInput.vue'
|
|
@@ -255,6 +256,8 @@ function addNewGroup() {
|
|
|
255
256
|
newGroupName.value = ''
|
|
256
257
|
}
|
|
257
258
|
|
|
259
|
+
const groupingLabel = computed(() => (props.enableSmartGroup ? 'Smart group' : 'Group'))
|
|
260
|
+
|
|
258
261
|
/** Selected samples among the resolved list, for the select-all header. */
|
|
259
262
|
const selectedCount = computed(() => resolvedSamples.value.filter(s => props.modelValue.includes(s)).length)
|
|
260
263
|
|
|
@@ -268,6 +271,36 @@ defineExpose({ handleSmartGroupApply })
|
|
|
268
271
|
|
|
269
272
|
<template>
|
|
270
273
|
<div class="mint-sample-selector">
|
|
274
|
+
<div class="mint-sample-selector__header">
|
|
275
|
+
<span class="mint-sample-selector__title">Samples</span>
|
|
276
|
+
<!-- A narrow selector shows "N sel."; screen readers keep "N selected". -->
|
|
277
|
+
<span class="mint-sample-selector__selected">
|
|
278
|
+
<span class="mint-sample-selector__selected-full">{{ selectedCount }} selected</span>
|
|
279
|
+
<span class="mint-sample-selector__selected-short" aria-hidden="true">{{ selectedCount }} sel.</span>
|
|
280
|
+
</span>
|
|
281
|
+
<div v-if="!isPlaceholderState && enableGrouping" class="mint-sample-selector__header-actions">
|
|
282
|
+
<BaseButton
|
|
283
|
+
variant="ghost"
|
|
284
|
+
size="sm"
|
|
285
|
+
:icon="enableSmartGroup ? WandSparkles : Layers"
|
|
286
|
+
:title="groupingLabel"
|
|
287
|
+
class="mint-sample-selector__action-btn mint-sample-selector__group-btn"
|
|
288
|
+
@click="openGroupingModal(groupingActionMode)"
|
|
289
|
+
>
|
|
290
|
+
{{ groupingLabel }}
|
|
291
|
+
</BaseButton>
|
|
292
|
+
<BaseButton
|
|
293
|
+
v-if="internalGroups.length > 0"
|
|
294
|
+
variant="ghost"
|
|
295
|
+
size="sm"
|
|
296
|
+
:icon="RotateCcw"
|
|
297
|
+
label="Clear all groups"
|
|
298
|
+
class="mint-sample-selector__action-btn"
|
|
299
|
+
@click="clearGroups"
|
|
300
|
+
/>
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
|
|
271
304
|
<div v-if="error" class="mint-sample-selector__state">
|
|
272
305
|
<slot name="error" :error="error">
|
|
273
306
|
<DataStateInternal state="error" size="sm" :title="error" />
|
|
@@ -302,43 +335,7 @@ defineExpose({ handleSmartGroupApply })
|
|
|
302
335
|
@update:model-value="toggleSelectAll"
|
|
303
336
|
/>
|
|
304
337
|
<span class="mint-sample-selector__select-all-label">All samples</span>
|
|
305
|
-
<span class="mint-sample-selector__select-all-count">{{ selectedCount }}
|
|
306
|
-
</div>
|
|
307
|
-
|
|
308
|
-
<!-- Action Buttons Row -->
|
|
309
|
-
<div v-if="!isPlaceholderState && enableGrouping" class="mint-sample-selector__actions">
|
|
310
|
-
<div class="mint-sample-selector__actions-row">
|
|
311
|
-
<!-- Grouping Button -->
|
|
312
|
-
<BaseButton
|
|
313
|
-
:variant="enableSmartGroup && groupingEnabled ? 'primary' : 'secondary'"
|
|
314
|
-
size="sm"
|
|
315
|
-
:disabled="resolvedSamples.length === 0"
|
|
316
|
-
class="mint-sample-selector__action-btn"
|
|
317
|
-
@click="openGroupingModal(groupingActionMode)"
|
|
318
|
-
>
|
|
319
|
-
<svg v-if="enableSmartGroup" class="mint-sample-selector__action-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
320
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
|
321
|
-
</svg>
|
|
322
|
-
<svg v-else class="mint-sample-selector__action-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
323
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3 3 7.5l9 4.5 9-4.5L12 3ZM3 12l9 4.5 9-4.5M3 16.5l9 4.5 9-4.5" />
|
|
324
|
-
</svg>
|
|
325
|
-
<span class="mint-sample-selector__action-label">Grouping</span>
|
|
326
|
-
</BaseButton>
|
|
327
|
-
|
|
328
|
-
<!-- Reset Button -->
|
|
329
|
-
<BaseButton
|
|
330
|
-
variant="ghost"
|
|
331
|
-
size="sm"
|
|
332
|
-
:disabled="internalGroups.length === 0"
|
|
333
|
-
class="mint-sample-selector__action-btn mint-sample-selector__action-btn--reset"
|
|
334
|
-
@click="clearGroups"
|
|
335
|
-
title="Clear all groups"
|
|
336
|
-
>
|
|
337
|
-
<svg class="mint-sample-selector__action-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
338
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
|
339
|
-
</svg>
|
|
340
|
-
</BaseButton>
|
|
341
|
-
</div>
|
|
338
|
+
<span class="mint-sample-selector__select-all-count">{{ selectedCount }}/{{ resolvedSamples.length }}</span>
|
|
342
339
|
</div>
|
|
343
340
|
|
|
344
341
|
<!-- Grouped View -->
|
|
@@ -153,7 +153,7 @@ function onHeaderKeydown(event: KeyboardEvent) {
|
|
|
153
153
|
:title="node.group?.name ?? node.label"
|
|
154
154
|
>{{ node.label }}</span>
|
|
155
155
|
|
|
156
|
-
<span class="mint-sample-selector__count-badge">{{ selectedCount }}
|
|
156
|
+
<span class="mint-sample-selector__count-badge">{{ selectedCount }}/{{ node.allSamples.length }}</span>
|
|
157
157
|
|
|
158
158
|
<button
|
|
159
159
|
type="button"
|
|
@@ -46,7 +46,7 @@ function initPlayground() {
|
|
|
46
46
|
>
|
|
47
47
|
<span style="flex: 1; min-width: 0">
|
|
48
48
|
<span style="display: block; font-size: 0.8125rem; font-weight: 500; color: var(--text-primary)">{{ e.name }}</span>
|
|
49
|
-
<span style="display: block; font-family:
|
|
49
|
+
<span style="display: block; font-family: var(--font-mono); font-size: 0.65625rem; color: var(--text-muted)">{{ e.code }}</span>
|
|
50
50
|
</span>
|
|
51
51
|
<span style="flex-shrink: 0; font-size: 0.71875rem; color: var(--text-muted)">{{ e.updated }}</span>
|
|
52
52
|
</a>
|
|
@@ -107,6 +107,39 @@ function initPlayground() {
|
|
|
107
107
|
</div>
|
|
108
108
|
</Variant>
|
|
109
109
|
|
|
110
|
+
<Variant title="Rows with lead">
|
|
111
|
+
<div style="padding: 2rem; max-width: 600px; display: grid; gap: 1rem;">
|
|
112
|
+
<SectionCard title="Experiments" count="3 total" :icon="flaskIcon" accent="experiment" uppercase>
|
|
113
|
+
<div class="mint-section-card__rows">
|
|
114
|
+
<a v-for="e in experiments" :key="e.code" href="#" class="mint-section-card__row">
|
|
115
|
+
<span class="mint-section-card__row-lead">
|
|
116
|
+
<span style="width: 0.375rem; height: 0.375rem; border-radius: 50%; background: var(--mint-success)" />
|
|
117
|
+
</span>
|
|
118
|
+
<span style="flex: 1; min-width: 0">
|
|
119
|
+
<span style="display: block; font-size: 0.8125rem; font-weight: 500; color: var(--text-primary)">{{ e.name }}</span>
|
|
120
|
+
<span style="display: block; font-family: var(--font-mono); font-size: 0.65625rem; color: var(--text-muted)">{{ e.code }}</span>
|
|
121
|
+
</span>
|
|
122
|
+
<span style="flex-shrink: 0; font-size: 0.71875rem; color: var(--text-muted)">{{ e.updated }}</span>
|
|
123
|
+
</a>
|
|
124
|
+
</div>
|
|
125
|
+
</SectionCard>
|
|
126
|
+
<SectionCard title="Projects" count="2 active" :icon="folderIcon" accent="project" uppercase>
|
|
127
|
+
<div class="mint-section-card__rows">
|
|
128
|
+
<a href="#" class="mint-section-card__row">
|
|
129
|
+
<span class="mint-section-card__row-lead" aria-hidden="true" />
|
|
130
|
+
<span style="flex: 1; font-size: 0.8125rem; font-weight: 500; color: var(--text-primary)">Hypoxia metabolic rewiring</span>
|
|
131
|
+
<span style="font-size: 0.71875rem; color: var(--text-muted)">12 experiments</span>
|
|
132
|
+
</a>
|
|
133
|
+
<a href="#" class="mint-section-card__row">
|
|
134
|
+
<span class="mint-section-card__row-lead" aria-hidden="true" />
|
|
135
|
+
<span style="flex: 1; font-size: 0.8125rem; font-weight: 500; color: var(--text-primary)">Serine one-carbon flux</span>
|
|
136
|
+
<span style="font-size: 0.71875rem; color: var(--text-muted)">7 experiments</span>
|
|
137
|
+
</a>
|
|
138
|
+
</div>
|
|
139
|
+
</SectionCard>
|
|
140
|
+
</div>
|
|
141
|
+
</Variant>
|
|
142
|
+
|
|
110
143
|
<Variant title="Detail card with footer">
|
|
111
144
|
<div style="padding: 2rem; max-width: 600px;">
|
|
112
145
|
<SectionCard title="Analysis artifacts" :count="4" divider="light">
|
|
@@ -139,7 +172,7 @@ function initPlayground() {
|
|
|
139
172
|
<div class="mint-section-card__rows">
|
|
140
173
|
<div v-for="n in 20" :key="n" class="mint-section-card__row">
|
|
141
174
|
<span style="flex: 1; font-size: 0.8125rem; color: var(--text-primary)">Row {{ n }}</span>
|
|
142
|
-
<span style="font-family:
|
|
175
|
+
<span style="font-family: var(--font-mono); font-size: 0.71875rem; color: var(--text-muted)">MM-2026-{{ String(n).padStart(3, '0') }}</span>
|
|
143
176
|
</div>
|
|
144
177
|
</div>
|
|
145
178
|
<template #footer>
|
|
@@ -40,6 +40,7 @@ function initState() {
|
|
|
40
40
|
showEta: true,
|
|
41
41
|
showRemaining: true,
|
|
42
42
|
label: 'samples',
|
|
43
|
+
failed: 0,
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
</script>
|
|
@@ -60,6 +61,7 @@ function initState() {
|
|
|
60
61
|
:label="state.label"
|
|
61
62
|
:show-eta="state.showEta"
|
|
62
63
|
:show-remaining="state.showRemaining"
|
|
64
|
+
:failed="state.failed"
|
|
63
65
|
/>
|
|
64
66
|
</div>
|
|
65
67
|
</template>
|
|
@@ -69,6 +71,7 @@ function initState() {
|
|
|
69
71
|
<HstNumber v-model="state.total" title="Total samples" />
|
|
70
72
|
<HstNumber v-model="state.remaining" title="Remaining (s)" />
|
|
71
73
|
<HstText v-model="state.label" title="Unit label" />
|
|
74
|
+
<HstNumber v-model="state.failed" title="Failed" />
|
|
72
75
|
<HstCheckbox v-model="state.compact" title="Compact" />
|
|
73
76
|
<HstCheckbox v-model="state.showEta" title="Show ETA" />
|
|
74
77
|
<HstCheckbox v-model="state.showRemaining" title="Show remaining" />
|
|
@@ -81,6 +84,12 @@ function initState() {
|
|
|
81
84
|
</div>
|
|
82
85
|
</Variant>
|
|
83
86
|
|
|
87
|
+
<Variant title="With failures">
|
|
88
|
+
<div style="padding: 2rem; max-width: 600px;">
|
|
89
|
+
<SequenceProgressBar :progress="running" :failed="1" />
|
|
90
|
+
</div>
|
|
91
|
+
</Variant>
|
|
92
|
+
|
|
84
93
|
<Variant title="Compact (no footer)">
|
|
85
94
|
<!-- Compact drops the remaining/ETA row for dense instrument tables. -->
|
|
86
95
|
<div style="padding: 2rem; max-width: 600px;">
|
|
@@ -15,6 +15,8 @@ interface Props {
|
|
|
15
15
|
label?: string
|
|
16
16
|
showEta?: boolean
|
|
17
17
|
showRemaining?: boolean
|
|
18
|
+
/** Failed injections so far; shown as "N failed" in the head when above 0. */
|
|
19
|
+
failed?: number
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
const props = withDefaults(defineProps<Props>(), {
|
|
@@ -22,6 +24,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
22
24
|
label: 'samples',
|
|
23
25
|
showEta: true,
|
|
24
26
|
showRemaining: true,
|
|
27
|
+
failed: 0,
|
|
25
28
|
})
|
|
26
29
|
|
|
27
30
|
const percent = computed(() => sequenceProgressPercent(props.progress))
|
|
@@ -37,8 +40,10 @@ const hasFooter = computed(() => {
|
|
|
37
40
|
<div class="mint-sequence-progress">
|
|
38
41
|
<div class="mint-sequence-progress__header">
|
|
39
42
|
<span class="mint-sequence-progress__label">
|
|
40
|
-
{{ progress.current_sample }} / {{ progress.total_samples }}
|
|
43
|
+
<span class="mint-sequence-progress__count">{{ progress.current_sample }} / {{ progress.total_samples }}</span>
|
|
44
|
+
{{ label }}
|
|
41
45
|
</span>
|
|
46
|
+
<span v-if="failed > 0" class="mint-sequence-progress__failed">{{ failed }} failed</span>
|
|
42
47
|
<span class="mint-sequence-progress__percent">{{ percent }}%</span>
|
|
43
48
|
</div>
|
|
44
49
|
|
|
@@ -17,7 +17,7 @@ export const APPEARANCE_TAB: SettingsTab = {
|
|
|
17
17
|
// Heroicons "swatch" — the built-in tab sits beside plugin tabs that all
|
|
18
18
|
// carry icons, so it needs one of its own to keep the rail consistent.
|
|
19
19
|
icon: '<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4.098 19.902a3.75 3.75 0 0 0 5.304 0l6.401-6.402M6.75 21A3.75 3.75 0 0 1 3 17.25V4.125C3 3.504 3.504 3 4.125 3h5.25c.621 0 1.125.504 1.125 1.125v4.072M6.75 21a3.75 3.75 0 0 0 3.75-3.75V8.197M6.75 21h13.125c.621 0 1.125-.504 1.125-1.125v-5.25c0-.621-.504-1.125-1.125-1.125h-4.072M10.5 8.197l2.88-2.88c.438-.439 1.15-.439 1.59 0l3.712 3.713c.44.44.44 1.152 0 1.59l-2.879 2.88M6.75 17.25h.008v.008H6.75v-.008Z"></path></svg>',
|
|
20
|
-
description: 'Theme, color palette, and
|
|
20
|
+
description: 'Theme, color palette, and density',
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
// Map settings groups onto the form-builder's flat-section shape.
|
|
@@ -358,13 +358,8 @@ const themeOptions: { value: ThemeMode; label: string; halves: ('light' | 'dark'
|
|
|
358
358
|
{ value: 'system', label: 'System', halves: ['light', 'dark'] },
|
|
359
359
|
]
|
|
360
360
|
|
|
361
|
-
/**
|
|
362
|
-
|
|
363
|
-
const [from, to] = colorPalettes[key].hues
|
|
364
|
-
const span = ((to - from + 540) % 360) - 180
|
|
365
|
-
const tone = key === 'pastel' ? '60% 72%' : '65% 48%'
|
|
366
|
-
return Array.from({ length: 5 }, (_, i) => `hsl(${Math.round(from + (span * i) / 4)} ${tone})`)
|
|
367
|
-
}
|
|
361
|
+
/** Accent tokens a palette swatch shows; `data-palette` on the strip resolves them per palette. */
|
|
362
|
+
const paletteSwatchTokens = ['--color-primary', '--color-primary-hover', '--color-primary-soft', '--color-primary-border']
|
|
368
363
|
|
|
369
364
|
const densityPreviewRows = [
|
|
370
365
|
['S-0012', '2.41', '12.5'],
|
|
@@ -562,7 +557,7 @@ function canShowForCurrentUser(item: AccessControlled): boolean {
|
|
|
562
557
|
<div class="mint-settings-modal__setting">
|
|
563
558
|
<div class="mint-settings-modal__setting-text">
|
|
564
559
|
<span class="mint-settings-modal__setting-label">Color palette</span>
|
|
565
|
-
<span class="mint-settings-modal__setting-hint">
|
|
560
|
+
<span class="mint-settings-modal__setting-hint">Accent colour across the interface</span>
|
|
566
561
|
</div>
|
|
567
562
|
<div class="mint-settings-modal__palettes">
|
|
568
563
|
<button
|
|
@@ -573,12 +568,12 @@ function canShowForCurrentUser(item: AccessControlled): boolean {
|
|
|
573
568
|
:class="['mint-settings-modal__palette', { 'mint-settings-modal__palette--active': settings.colorPalette === key }]"
|
|
574
569
|
@click="settings.colorPalette = key as ColorPalette"
|
|
575
570
|
>
|
|
576
|
-
<span class="mint-settings-modal__swatches" aria-hidden="true">
|
|
571
|
+
<span class="mint-settings-modal__swatches" :data-palette="key" aria-hidden="true">
|
|
577
572
|
<span
|
|
578
|
-
v-for="
|
|
579
|
-
:key="
|
|
573
|
+
v-for="token in paletteSwatchTokens"
|
|
574
|
+
:key="token"
|
|
580
575
|
class="mint-settings-modal__swatch"
|
|
581
|
-
:style="{ backgroundColor:
|
|
576
|
+
:style="{ backgroundColor: `var(${token})` }"
|
|
582
577
|
/>
|
|
583
578
|
</span>
|
|
584
579
|
<span class="mint-settings-modal__palette-name">{{ palette.name }}</span>
|
|
@@ -591,8 +586,8 @@ function canShowForCurrentUser(item: AccessControlled): boolean {
|
|
|
591
586
|
|
|
592
587
|
<div class="mint-settings-modal__setting mint-settings-modal__setting--inline">
|
|
593
588
|
<div class="mint-settings-modal__setting-text">
|
|
594
|
-
<span class="mint-settings-modal__setting-label">
|
|
595
|
-
<span class="mint-settings-modal__setting-hint">Adjusts
|
|
589
|
+
<span class="mint-settings-modal__setting-label">Density</span>
|
|
590
|
+
<span class="mint-settings-modal__setting-hint">Adjusts control and table row height</span>
|
|
596
591
|
</div>
|
|
597
592
|
<SegmentedControl
|
|
598
593
|
:model-value="settings.tableDensity"
|