@morscherlab/mint-sdk 1.2.0-beta.1 → 1.2.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/README.md +35 -5
- package/dist/{ExperimentPopover-tLwJ7XF4.js → ExperimentPopover-oL0fg_A0.js} +6 -4
- package/dist/ExperimentPopover-oL0fg_A0.js.map +1 -0
- package/dist/{ExperimentSelectorModal-DyPAUCLw.js → ExperimentSelectorModal-BeEOomw_.js} +5 -5
- package/dist/ExperimentSelectorModal-BeEOomw_.js.map +1 -0
- package/dist/{SettingsModal-BgKY93zh.js → SettingsModal-Dphh3RrI.js} +5 -8
- package/dist/SettingsModal-Dphh3RrI.js.map +1 -0
- package/dist/{EmptyState-p90quq8Z.js → Skeleton-DxtwJ5gt.js} +111 -93
- package/dist/Skeleton-DxtwJ5gt.js.map +1 -0
- package/dist/__tests__/components/ExperimentTimeline.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.internal.test.d.ts +1 -0
- package/dist/__tests__/components/SecretInput.test.d.ts +1 -0
- package/dist/__tests__/components/WellEditPopupInternal.test.d.ts +1 -0
- package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
- package/dist/__tests__/composables/usePluginConfig.test.d.ts +15 -0
- package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
- package/dist/components/ActionMenu.vue.d.ts +1 -1
- package/dist/components/AppAvatarMenu.vue.d.ts +4 -0
- package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
- package/dist/components/AppSidebar.vue.d.ts +1 -1
- package/dist/components/AuditTrail.vue.d.ts +13 -0
- package/dist/components/AutoGroupModal.vue.d.ts +1 -1
- package/dist/components/BatchProgressList.vue.d.ts +17 -0
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
- package/dist/components/DataFrame.vue.d.ts +14 -2
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/DateTimePicker.vue.d.ts +2 -0
- package/dist/components/DropdownButton.vue.d.ts +2 -0
- package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
- package/dist/components/ExperimentPopover.vue.d.ts +1 -0
- package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
- package/dist/components/FitPanel.vue.d.ts +1 -1
- package/dist/components/JobsStatusTray.vue.d.ts +9 -2
- package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
- package/dist/components/PluginWorkspaceView.props.d.ts +29 -1
- package/dist/components/PluginWorkspaceView.vue.d.ts +5 -5
- package/dist/components/ProgressBar.vue.d.ts +1 -1
- package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
- package/dist/components/ReagentList.vue.d.ts +29 -1
- package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
- package/dist/components/SampleLegend.vue.d.ts +1 -1
- package/dist/components/SampleSelector.drag.d.ts +13 -0
- package/dist/components/SampleSelector.tree.d.ts +2 -0
- package/dist/components/SampleSelector.vue.d.ts +35 -2
- package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
- package/dist/components/SecretInput.vue.d.ts +28 -0
- package/dist/components/SettingsModal.vue.d.ts +1 -1
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -1
- package/dist/components/TimePicker.vue.d.ts +1 -0
- package/dist/components/WellPlate.geometry.d.ts +15 -0
- package/dist/components/WellPlate.interaction.d.ts +13 -0
- package/dist/components/WellPlate.vue.d.ts +29 -0
- package/dist/components/index.d.ts +9 -0
- package/dist/components/index.js +8 -8
- package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
- package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
- package/dist/components/internal/WellEditPopupInternal.vue.d.ts +3 -1
- package/dist/components/internal/WorkspaceControlsInternal.vue.d.ts +23 -0
- package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +70 -0
- package/dist/components/internal/WorkspaceSidebarInternal.vue.d.ts +43 -0
- package/dist/{components-DkHddRMl.js → components-CgAUzF8F.js} +2497 -2235
- package/dist/components-CgAUzF8F.js.map +1 -0
- package/dist/composables/controlSchemaTypes.d.ts +34 -0
- package/dist/composables/flattenWorkspaceBindings.d.ts +61 -0
- package/dist/composables/index.d.ts +9 -2
- package/dist/composables/index.js +10 -10
- package/dist/composables/pluginWorkspaceModel.d.ts +164 -0
- package/dist/composables/useAsync.d.ts +5 -1
- package/dist/composables/useBioTemplateWorkspace.d.ts +4 -20
- package/dist/composables/useCommandHistory.d.ts +5 -1
- package/dist/composables/useDropdownState.d.ts +18 -2
- package/dist/composables/useEventStream.d.ts +9 -0
- package/dist/composables/useFocusTrap.d.ts +21 -0
- package/dist/composables/useGeneratedAnalysis.d.ts +3 -1
- package/dist/composables/useJobsStatusTray.d.ts +25 -1
- package/dist/composables/useListReorder.d.ts +90 -0
- package/dist/composables/useMenuKeyboard.d.ts +29 -0
- package/dist/composables/useOptimisticMutation.d.ts +5 -1
- package/dist/composables/usePluginClient.d.ts +2 -0
- package/dist/composables/usePluginConfig.d.ts +27 -0
- package/dist/composables/usePluginWorkspace.d.ts +51 -0
- package/dist/composables/useRequestSyncState.d.ts +42 -2
- package/dist/composables/useResourceCrud.d.ts +5 -1
- package/dist/composables/useRovingFocus.d.ts +24 -0
- package/dist/composables/useScheduleDrag.d.ts +1 -0
- package/dist/composables/useWellPainting.d.ts +5 -1
- package/dist/composables/useWellPlateAdapter.d.ts +5 -1
- package/dist/composables/useWellPlateValidation.d.ts +5 -1
- package/dist/composables/workspaceRecipes.d.ts +188 -0
- package/dist/{composables-C_i90sGS.js → composables-B_pia3hO.js} +209 -82
- package/dist/composables-B_pia3hO.js.map +1 -0
- package/dist/{useApi-J6zFkHmn.js → errors-_W0-LbA6.js} +103 -3
- package/dist/errors-_W0-LbA6.js.map +1 -0
- package/dist/{experiment-Cq145oEW.js → experiment-Cwl9AYxw.js} +3 -8
- package/dist/experiment-Cwl9AYxw.js.map +1 -0
- package/dist/{experiment-utils-CLnzPPq5.js → experiment-utils-DV3DrvE_.js} +70 -51
- package/dist/experiment-utils-DV3DrvE_.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -15
- package/dist/install.js +2 -7
- package/dist/install.js.map +1 -1
- package/dist/permissions.d.ts +42 -1
- package/dist/permissions.js +20 -10
- package/dist/permissions.js.map +1 -1
- package/dist/stores/auth.d.ts +6 -0
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.js +3 -3
- package/dist/stores/settings.d.ts +31 -1
- package/dist/styles.css +11247 -29501
- package/dist/templates/builderReadUtils.d.ts +1 -1
- package/dist/templates/index.js +2 -4
- package/dist/{templates-DsP51i-S.js → templates-Qq113pyZ.js} +303 -106
- package/dist/templates-Qq113pyZ.js.map +1 -0
- package/dist/types/auth.d.ts +1 -0
- package/dist/types/form-builder.d.ts +1 -1
- package/dist/{useControlSchema-BDx2Olha.js → useControlSchema-aMZlb4Sc.js} +462 -1130
- package/dist/useControlSchema-aMZlb4Sc.js.map +1 -0
- package/dist/{useDropdownState-DSb3BC3N.js → useDropdownState-DitCtrTT.js} +22 -6
- package/dist/useDropdownState-DitCtrTT.js.map +1 -0
- package/dist/{useExperimentSelector-CV4iNfMS.js → useExperimentSelector-I8HC8hUu.js} +4 -4
- package/dist/{useExperimentSelector-CV4iNfMS.js.map → useExperimentSelector-I8HC8hUu.js.map} +1 -1
- package/dist/{useFormBuilder-BLxG3BOX.js → useFormBuilder-TCxNnqeb.js} +2 -2
- package/dist/{useFormBuilder-BLxG3BOX.js.map → useFormBuilder-TCxNnqeb.js.map} +1 -1
- package/dist/{useProtocolTemplates-CS_SQl6U.js → useProtocolTemplates-BmX_iVBR.js} +766 -212
- package/dist/useProtocolTemplates-BmX_iVBR.js.map +1 -0
- package/dist/utils/color.d.ts +13 -0
- package/dist/utils/errors.d.ts +9 -0
- package/dist/utils/pluginSecrets.d.ts +53 -0
- package/dist/utils/records.d.ts +4 -0
- package/package.json +1 -1
- package/src/__tests__/components/ActionMenu.test.ts +94 -0
- package/src/__tests__/components/AppAvatarMenu.test.ts +123 -0
- package/src/__tests__/components/BaseTabs.test.ts +67 -0
- package/src/__tests__/components/DataFrame.test.ts +183 -11
- package/src/__tests__/components/DataStates.test.ts +176 -0
- package/src/__tests__/components/DatePicker.test.ts +76 -0
- package/src/__tests__/components/DateTimePicker.test.ts +36 -0
- package/src/__tests__/components/DropdownButton.test.ts +134 -0
- package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
- package/src/__tests__/components/GroupAssigner.test.ts +53 -0
- package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
- package/src/__tests__/components/PluginWorkspaceView.internal.test.ts +230 -0
- package/src/__tests__/components/RackEditor.test.ts +35 -0
- package/src/__tests__/components/ReagentList.test.ts +64 -2
- package/src/__tests__/components/RetiredStyles.test.ts +31 -0
- package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
- package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
- package/src/__tests__/components/SecretInput.test.ts +87 -0
- package/src/__tests__/components/SegmentedControl.test.ts +88 -0
- package/src/__tests__/components/TimePicker.test.ts +61 -0
- package/src/__tests__/components/WellEditPopupInternal.test.ts +108 -0
- package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
- package/src/__tests__/composables/useAuth.test.ts +2 -0
- package/src/__tests__/composables/useDropdownState.test.ts +58 -1
- package/src/__tests__/composables/useListReorder.test.ts +145 -0
- package/src/__tests__/composables/usePluginClient.test.ts +140 -0
- package/src/__tests__/composables/usePluginConfig.test.ts +497 -0
- package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +39 -7
- package/src/__tests__/stores/settings.test.ts +71 -1
- package/src/__tests__/styles/cssTokens.test.ts +131 -0
- package/src/__tests__/utils/permissions.test.ts +68 -0
- package/src/components/ActionMenu.vue +45 -88
- package/src/components/AlertBox.vue +0 -4
- package/src/components/AppAvatarMenu.vue +26 -7
- package/src/components/AppLayout.vue +0 -4
- package/src/components/AppPluginSwitcher.story.vue +87 -0
- package/src/components/AppPluginSwitcher.vue +2 -5
- package/src/components/AppSidebar.vue +0 -4
- package/src/components/AppToastContainer.vue +6 -8
- package/src/components/AppTopBar.vue +0 -4
- package/src/components/ArtifactSaveDialog.vue +0 -4
- package/src/components/ArtifactSelectorModal.vue +0 -4
- package/src/components/AuditTrail.story.vue +18 -0
- package/src/components/AuditTrail.vue +27 -7
- package/src/components/AutoGroupModal.vue +0 -4
- package/src/components/Avatar.vue +0 -4
- package/src/components/BaseButton.vue +0 -4
- package/src/components/BaseCheckbox.vue +0 -4
- package/src/components/BaseInput.vue +0 -4
- package/src/components/BaseModal.vue +8 -60
- package/src/components/BasePill.vue +0 -4
- package/src/components/BaseRadioGroup.vue +0 -4
- package/src/components/BaseSelect.vue +0 -4
- package/src/components/BaseSlider.vue +0 -4
- package/src/components/BaseTabs.vue +26 -5
- package/src/components/BaseTextarea.vue +0 -4
- package/src/components/BaseToggle.vue +0 -4
- package/src/components/BatchProgressList.story.vue +18 -0
- package/src/components/BatchProgressList.vue +32 -4
- package/src/components/BioTemplateExperimentWorkspaceView.vue +10 -21
- package/src/components/BioTemplatePackWorkspaceView.vue +11 -15
- package/src/components/BioTemplatePresetWorkspaceView.vue +8 -13
- package/src/components/Breadcrumb.vue +0 -4
- package/src/components/Calendar.vue +0 -4
- package/src/components/ChartContainer.story.vue +1 -1
- package/src/components/ChartContainer.vue +0 -4
- package/src/components/ChemicalFormula.vue +0 -4
- package/src/components/CollapsibleCard.vue +0 -4
- package/src/components/ColorSlider.vue +0 -4
- package/src/components/ComponentBindingRenderer.vue +1 -3
- package/src/components/ConcentrationInput.vue +0 -4
- package/src/components/ConfirmDialog.vue +0 -4
- package/src/components/ControlWorkspaceView.vue +11 -22
- package/src/components/DataFrame.story.vue +14 -0
- package/src/components/DataFrame.vue +97 -23
- package/src/components/DatePicker.vue +73 -27
- package/src/components/DateTimePicker.vue +45 -17
- package/src/components/Divider.vue +0 -4
- package/src/components/DoseCalculator.vue +0 -4
- package/src/components/DoseDesignWorkspaceView.vue +6 -25
- package/src/components/DropdownButton.vue +24 -6
- package/src/components/EmptyState.vue +0 -4
- package/src/components/ExperimentCodeBadge.vue +0 -4
- package/src/components/ExperimentDataViewer.story.vue +3 -0
- package/src/components/ExperimentDataViewer.vue +33 -13
- package/src/components/ExperimentPopover.vue +2 -5
- package/src/components/ExperimentSelectorModal.vue +0 -4
- package/src/components/ExperimentTimeline.story.vue +18 -0
- package/src/components/ExperimentTimeline.vue +81 -75
- package/src/components/FileUploader.vue +0 -4
- package/src/components/FitPanel.vue +0 -4
- package/src/components/FormActions.story.vue +96 -0
- package/src/components/FormActions.vue +0 -4
- package/src/components/FormBuilder.vue +0 -4
- package/src/components/FormField.vue +0 -4
- package/src/components/FormulaInput.vue +0 -4
- package/src/components/GeneratedPathInput.story.vue +68 -0
- package/src/components/GeneratedPlotlyResult.story.vue +96 -0
- package/src/components/GeneratedPlotlyResult.vue +3 -3
- package/src/components/GeneratedPluginView.story.vue +145 -0
- package/src/components/GeneratedPluginView.vue +10 -10
- package/src/components/GeneratedResultRenderer.story.vue +117 -0
- package/src/components/GeneratedResultRenderer.vue +4 -4
- package/src/components/GroupAssigner.vue +67 -5
- package/src/components/IconButton.vue +0 -4
- package/src/components/InstrumentAlertLog.vue +0 -4
- package/src/components/InstrumentStateBadge.vue +0 -4
- package/src/components/InstrumentStatusCard.vue +0 -4
- package/src/components/JobsStatusTray.vue +16 -5
- package/src/components/LcmsSequenceTable.vue +81 -50
- package/src/components/LoadingSpinner.vue +0 -4
- package/src/components/MobileSupportGate.vue +0 -4
- package/src/components/MoleculeInput.vue +0 -4
- package/src/components/MultiSelect.vue +0 -4
- package/src/components/NumberInput.vue +0 -4
- package/src/components/PlateMapEditor.vue +3 -14
- package/src/components/PluginIcon.vue +0 -4
- package/src/components/PluginWorkspaceView.props.ts +38 -0
- package/src/components/PluginWorkspaceView.vue +53 -224
- package/src/components/ProgressBar.vue +0 -4
- package/src/components/ProtocolStepEditor.vue +2 -4
- package/src/components/RackEditor.vue +51 -70
- package/src/components/ReagentEditor.vue +0 -4
- package/src/components/ReagentList.story.vue +18 -0
- package/src/components/ReagentList.vue +127 -82
- package/src/components/ResourceCard.vue +0 -4
- package/src/components/RuntimeUpdateNotice.story.vue +49 -0
- package/src/components/RuntimeUpdateNotice.vue +4 -4
- package/src/components/SampleHierarchyTree.story.vue +18 -0
- package/src/components/SampleHierarchyTree.vue +32 -9
- package/src/components/SampleLegend.vue +2 -8
- package/src/components/SampleSelector.drag.ts +51 -0
- package/src/components/SampleSelector.story.vue +6 -0
- package/src/components/SampleSelector.tree.ts +2 -0
- package/src/components/SampleSelector.vue +49 -10
- package/src/components/SampleSelectorGroupNode.vue +19 -0
- package/src/components/ScheduleCalendar.story.vue +6 -0
- package/src/components/ScheduleCalendar.vue +82 -7
- package/src/components/ScientificNumber.vue +0 -4
- package/src/components/SecretInput.story.vue +79 -0
- package/src/components/SecretInput.vue +150 -0
- package/src/components/SectionCard.vue +0 -4
- package/src/components/SegmentedControl.vue +48 -5
- package/src/components/SequenceInput.vue +0 -4
- package/src/components/SequenceProgressBar.story.vue +110 -0
- package/src/components/SequenceProgressBar.vue +0 -4
- package/src/components/SettingsModal.vue +0 -4
- package/src/components/Skeleton.vue +0 -4
- package/src/components/SmartGroupFieldRecipe.vue +8 -6
- package/src/components/SmartGroupManual.vue +0 -4
- package/src/components/StatusIndicator.vue +0 -4
- package/src/components/StepWizard.vue +0 -4
- package/src/components/TagsInput.vue +4 -6
- package/src/components/ThemeToggle.vue +0 -4
- package/src/components/TimePicker.vue +36 -7
- package/src/components/TimeRangeInput.vue +0 -4
- package/src/components/Tooltip.story.vue +3 -3
- package/src/components/Tooltip.vue +0 -4
- package/src/components/UnitInput.vue +0 -4
- package/src/components/WellPlate.geometry.ts +60 -1
- package/src/components/WellPlate.interaction.ts +44 -0
- package/src/components/WellPlate.story.vue +8 -0
- package/src/components/WellPlate.vue +53 -7
- package/src/components/index.ts +9 -0
- package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
- package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
- package/src/components/internal/DataStateInternal.vue +74 -0
- package/src/components/internal/FormSectionRenderer.vue +0 -4
- package/src/components/internal/WellEditPopupInternal.vue +20 -5
- package/src/components/internal/WorkspaceControlsInternal.vue +20 -0
- package/src/components/internal/WorkspaceShellInternal.vue +125 -0
- package/src/components/internal/WorkspaceSidebarInternal.vue +82 -0
- package/src/composables/controlSchemaTypes.ts +34 -0
- package/src/composables/experimentDesignData.ts +1 -3
- package/src/composables/flattenWorkspaceBindings.ts +104 -0
- package/src/composables/formBuilderRegistry.ts +5 -0
- package/src/composables/index.ts +43 -0
- package/src/composables/pluginWorkspaceModel.ts +182 -0
- package/src/composables/useAsync.ts +5 -1
- package/src/composables/useAuth.ts +3 -0
- package/src/composables/useBioTemplatePackWorkspace.ts +15 -9
- package/src/composables/useBioTemplatePresetWorkspace.ts +14 -15
- package/src/composables/useBioTemplateWorkspace.ts +18 -43
- package/src/composables/useCommandHistory.ts +5 -1
- package/src/composables/useDropdownState.ts +35 -5
- package/src/composables/useEventStream.ts +14 -2
- package/src/composables/useFileImport.ts +2 -7
- package/src/composables/useFocusTrap.ts +91 -0
- package/src/composables/useGeneratedAnalysis.ts +22 -10
- package/src/composables/useJobsStatusTray.ts +184 -17
- package/src/composables/useListReorder.story.vue +143 -0
- package/src/composables/useListReorder.ts +242 -0
- package/src/composables/useMenuKeyboard.ts +90 -0
- package/src/composables/useOptimisticMutation.ts +6 -16
- package/src/composables/usePluginClient.ts +47 -4
- package/src/composables/usePluginConfig.ts +252 -0
- package/src/composables/usePluginWorkspace.ts +208 -0
- package/src/composables/useRackEditor.ts +2 -11
- package/src/composables/useRequestSyncState.ts +98 -28
- package/src/composables/useResourceCrud.ts +6 -16
- package/src/composables/useRovingFocus.ts +66 -0
- package/src/composables/useScheduleDrag.ts +37 -0
- package/src/composables/useWellPainting.ts +10 -30
- package/src/composables/useWellPlateAdapter.ts +5 -1
- package/src/composables/useWellPlateEditor.ts +1 -11
- package/src/composables/useWellPlateValidation.ts +5 -1
- package/src/composables/workspaceRecipes.ts +267 -0
- package/src/index.ts +16 -0
- package/src/permissions.ts +48 -9
- package/src/stores/auth.ts +1 -0
- package/src/stores/experiment.ts +2 -7
- package/src/stores/index.ts +9 -1
- package/src/stores/settings.ts +93 -1
- package/src/styles/components/audit-trail.css +5 -5
- package/src/styles/components/batch-progress-list.css +7 -0
- package/src/styles/components/color-slider.css +2 -2
- package/src/styles/components/data-state.css +30 -0
- package/src/styles/components/dataframe.css +29 -35
- package/src/styles/components/experiment-data-viewer.css +4 -4
- package/src/styles/components/experiment-timeline.css +3 -30
- package/src/styles/components/form-builder.css +5 -5
- package/src/styles/components/lcms-sequence-table.css +16 -1
- package/src/styles/components/multi-select.css +1 -1
- package/src/styles/components/reagent-list.css +38 -31
- package/src/styles/components/sample-hierarchy-tree.css +5 -19
- package/src/styles/components/sample-selector.css +9 -2
- package/src/styles/components/schedule-calendar.css +8 -0
- package/src/styles/components/scientific-number.css +1 -1
- package/src/styles/components/secret-input.css +60 -0
- package/src/styles/components/well-plate.css +8 -0
- package/src/styles/index.css +9 -0
- package/src/styles/variables.css +29 -0
- package/src/templates/builderPresetControls.ts +1 -1
- package/src/templates/builderReadUtils.ts +1 -3
- package/src/templates/componentPlateHelpers.ts +3 -1
- package/src/templates/componentTargetResolvers.ts +1 -3
- package/src/templates/controlSchemaTargets.ts +1 -3
- package/src/templates/doseResponseAdapters.ts +2 -13
- package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
- package/src/templates/plateMapBuilder.ts +2 -2
- package/src/templates/qpcrPlateBuilder.ts +1 -1
- package/src/templates/templateValidators.ts +1 -1
- package/src/templates/timeCourseBuilder.ts +2 -2
- package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
- package/src/types/auth.ts +1 -0
- package/src/types/form-builder.ts +1 -0
- package/src/utils/color.ts +51 -0
- package/src/utils/errors.ts +29 -0
- package/src/utils/formModelSync.ts +1 -3
- package/src/utils/pluginIcon.ts +1 -3
- package/src/utils/pluginSecrets.ts +102 -0
- package/src/utils/records.ts +9 -0
- package/dist/EmptyState-p90quq8Z.js.map +0 -1
- package/dist/ExperimentPopover-tLwJ7XF4.js.map +0 -1
- package/dist/ExperimentSelectorModal-DyPAUCLw.js.map +0 -1
- package/dist/SettingsModal-BgKY93zh.js.map +0 -1
- package/dist/components-DkHddRMl.js.map +0 -1
- package/dist/composables/autoGroupConstants.d.ts +0 -1
- package/dist/composables/autoGroupGrouping.d.ts +0 -3
- package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
- package/dist/composables-C_i90sGS.js.map +0 -1
- package/dist/experiment-Cq145oEW.js.map +0 -1
- package/dist/experiment-utils-CLnzPPq5.js.map +0 -1
- package/dist/templates/builderDefaults.d.ts +0 -1
- package/dist/templates/plateGeometry.d.ts +0 -4
- package/dist/templates-DsP51i-S.js.map +0 -1
- package/dist/useApi-J6zFkHmn.js.map +0 -1
- package/dist/useControlSchema-BDx2Olha.js.map +0 -1
- package/dist/useDropdownState-DSb3BC3N.js.map +0 -1
- package/dist/useProtocolTemplates-CS_SQl6U.js.map +0 -1
- package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
- package/src/composables/autoGroupConstants.ts +0 -4
- package/src/composables/autoGroupGrouping.ts +0 -148
- package/src/composables/useAutoGroupInputSources.ts +0 -147
- package/src/templates/builderDefaults.ts +0 -11
- package/src/templates/plateGeometry.ts +0 -62
- /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → components/DataStates.test.d.ts} +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import GeneratedPlotlyResult from './GeneratedPlotlyResult.vue'
|
|
3
|
+
|
|
4
|
+
const scatterSpec: Record<string, unknown> = {
|
|
5
|
+
data: [
|
|
6
|
+
{
|
|
7
|
+
type: 'scatter',
|
|
8
|
+
mode: 'markers',
|
|
9
|
+
name: 'Control',
|
|
10
|
+
x: [1.2, 2.4, 3.1, 4.8, 5.5, 6.9],
|
|
11
|
+
y: [0.9, 1.8, 2.6, 3.9, 4.4, 5.8],
|
|
12
|
+
marker: { size: 9 },
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
type: 'scatter',
|
|
16
|
+
mode: 'markers',
|
|
17
|
+
name: 'Treated',
|
|
18
|
+
x: [1.1, 2.2, 3.4, 4.5, 5.9, 6.4],
|
|
19
|
+
y: [2.1, 3.4, 3.9, 5.2, 6.4, 7.1],
|
|
20
|
+
marker: { size: 9 },
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
layout: {
|
|
24
|
+
margin: { t: 24, r: 16, b: 40, l: 48 },
|
|
25
|
+
xaxis: { title: 'log2 intensity (control)' },
|
|
26
|
+
yaxis: { title: 'log2 intensity (treated)' },
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const barSpec: Record<string, unknown> = {
|
|
31
|
+
data: [
|
|
32
|
+
{
|
|
33
|
+
type: 'bar',
|
|
34
|
+
x: ['Glycolysis', 'TCA', 'PPP', 'Urea cycle'],
|
|
35
|
+
y: [12, 27, 8, 4],
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
layout: { margin: { t: 24, r: 16, b: 40, l: 48 } },
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Not a valid Plotly spec — exercises the static-image fallback branch.
|
|
42
|
+
const brokenSpec: Record<string, unknown> = { data: 'not-an-array' }
|
|
43
|
+
|
|
44
|
+
const PIXEL_PNG
|
|
45
|
+
= 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=='
|
|
46
|
+
|
|
47
|
+
function initState() {
|
|
48
|
+
return { chart: 'scatter' as 'scatter' | 'bar' }
|
|
49
|
+
}
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<template>
|
|
53
|
+
<Story title="Workflow/GeneratedPlotlyResult">
|
|
54
|
+
<Variant title="Playground" :init-state="initState">
|
|
55
|
+
<template #default="{ state }">
|
|
56
|
+
<div style="padding: 2rem; max-width: 720px;">
|
|
57
|
+
<GeneratedPlotlyResult :spec="state.chart === 'bar' ? barSpec : scatterSpec" />
|
|
58
|
+
</div>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
|
+
<template #controls="{ state }">
|
|
62
|
+
<HstSelect
|
|
63
|
+
v-model="state.chart"
|
|
64
|
+
title="Chart"
|
|
65
|
+
:options="[
|
|
66
|
+
{ label: 'scatter', value: 'scatter' },
|
|
67
|
+
{ label: 'bar', value: 'bar' },
|
|
68
|
+
]"
|
|
69
|
+
/>
|
|
70
|
+
</template>
|
|
71
|
+
</Variant>
|
|
72
|
+
|
|
73
|
+
<Variant title="Scatter">
|
|
74
|
+
<div style="padding: 2rem; max-width: 720px;">
|
|
75
|
+
<GeneratedPlotlyResult :spec="scatterSpec" />
|
|
76
|
+
</div>
|
|
77
|
+
</Variant>
|
|
78
|
+
|
|
79
|
+
<Variant title="Bar">
|
|
80
|
+
<div style="padding: 2rem; max-width: 720px;">
|
|
81
|
+
<GeneratedPlotlyResult :spec="barSpec" />
|
|
82
|
+
</div>
|
|
83
|
+
</Variant>
|
|
84
|
+
|
|
85
|
+
<Variant title="Render failure → PNG fallback">
|
|
86
|
+
<!-- When Plotly cannot render the spec the component swaps in the
|
|
87
|
+
server-rendered static image, if the job supplied one. -->
|
|
88
|
+
<div style="padding: 2rem; max-width: 720px;">
|
|
89
|
+
<GeneratedPlotlyResult
|
|
90
|
+
:spec="brokenSpec"
|
|
91
|
+
:fallback="{ media_type: 'image/png', data: PIXEL_PNG }"
|
|
92
|
+
/>
|
|
93
|
+
</div>
|
|
94
|
+
</Variant>
|
|
95
|
+
</Story>
|
|
96
|
+
</template>
|
|
@@ -79,9 +79,9 @@ onBeforeUnmount(() => {
|
|
|
79
79
|
.mint-generated-result__plotly-error {
|
|
80
80
|
margin: 0;
|
|
81
81
|
padding: 1rem;
|
|
82
|
-
border: 1px solid var(--
|
|
82
|
+
border: 1px solid var(--mint-error-border);
|
|
83
83
|
border-radius: 0.75rem;
|
|
84
|
-
background: var(--
|
|
85
|
-
color: var(--
|
|
84
|
+
background: var(--mint-error-bg);
|
|
85
|
+
color: var(--mint-error);
|
|
86
86
|
}
|
|
87
87
|
</style>
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import GeneratedPluginView from './GeneratedPluginView.vue'
|
|
3
|
+
import type { GeneratedAnalysisTransport } from '../composables/useGeneratedAnalysis'
|
|
4
|
+
import type { GeneratedAnalysisManifest } from '../types/generated-ui'
|
|
5
|
+
|
|
6
|
+
const manifest: GeneratedAnalysisManifest = {
|
|
7
|
+
schema_version: '1',
|
|
8
|
+
plugin: {
|
|
9
|
+
name: 'peak-qc',
|
|
10
|
+
version: '1.2.0',
|
|
11
|
+
description: 'Peak-picking quality control',
|
|
12
|
+
routes_prefix: '/api/peak-qc',
|
|
13
|
+
},
|
|
14
|
+
ui: {
|
|
15
|
+
title: 'Peak QC',
|
|
16
|
+
description: 'Score peak-picking output and flag features that need review.',
|
|
17
|
+
},
|
|
18
|
+
jobs: [
|
|
19
|
+
{
|
|
20
|
+
id: 'score-features',
|
|
21
|
+
title: 'Score features',
|
|
22
|
+
description: 'Compute RSD, blank ratio and detection rate for every feature.',
|
|
23
|
+
cpu: 4,
|
|
24
|
+
input_schema: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
title: 'Scoring parameters',
|
|
27
|
+
properties: {
|
|
28
|
+
rsd_threshold: {
|
|
29
|
+
type: 'number',
|
|
30
|
+
title: 'QC RSD threshold',
|
|
31
|
+
description: 'Features above this relative standard deviation are flagged.',
|
|
32
|
+
default: 0.3,
|
|
33
|
+
minimum: 0,
|
|
34
|
+
maximum: 1,
|
|
35
|
+
},
|
|
36
|
+
blank_ratio: {
|
|
37
|
+
type: 'number',
|
|
38
|
+
title: 'Minimum blank ratio',
|
|
39
|
+
default: 3,
|
|
40
|
+
minimum: 1,
|
|
41
|
+
},
|
|
42
|
+
drop_flagged: {
|
|
43
|
+
type: 'boolean',
|
|
44
|
+
title: 'Drop flagged features',
|
|
45
|
+
default: false,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
required: ['rsd_threshold'],
|
|
49
|
+
},
|
|
50
|
+
output_schema: { type: 'object' },
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: 'align-batches',
|
|
54
|
+
title: 'Align batches',
|
|
55
|
+
description: 'Retention-time align acquisition batches before merging.',
|
|
56
|
+
cpu: 8,
|
|
57
|
+
input_schema: {
|
|
58
|
+
type: 'object',
|
|
59
|
+
properties: {
|
|
60
|
+
tolerance_seconds: { type: 'number', title: 'RT tolerance (s)', default: 6 },
|
|
61
|
+
reference_batch: { type: 'string', title: 'Reference batch', default: 'batch-1' },
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
output_schema: { type: 'object' },
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const session = {
|
|
70
|
+
id: 'sess_story',
|
|
71
|
+
tab_id: 'tab_story',
|
|
72
|
+
created_at: new Date().toISOString(),
|
|
73
|
+
last_seen_at: new Date().toISOString(),
|
|
74
|
+
active_job_ids: [],
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function json(body: unknown): Response {
|
|
78
|
+
return new Response(JSON.stringify(body), {
|
|
79
|
+
status: 200,
|
|
80
|
+
headers: { 'Content-Type': 'application/json' },
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Serves the manifest, one session and an empty job list — no network. */
|
|
85
|
+
const readyTransport: GeneratedAnalysisTransport = async (input) => {
|
|
86
|
+
const url = String(input)
|
|
87
|
+
if (url.includes('/generated/manifest')) return json(manifest)
|
|
88
|
+
if (url.includes('/jobs/sessions')) return json({ sessions: [session] })
|
|
89
|
+
if (url.includes('/jobs')) return json({ jobs: [] })
|
|
90
|
+
return json({})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Never settles, so the workspace stays in its loading state. */
|
|
94
|
+
const loadingTransport: GeneratedAnalysisTransport = () => new Promise<Response>(() => {})
|
|
95
|
+
|
|
96
|
+
/** Fails the manifest request, so the workspace surfaces its error banner. */
|
|
97
|
+
const failingTransport: GeneratedAnalysisTransport = async () => (
|
|
98
|
+
new Response(JSON.stringify({ detail: 'Plugin runtime is not reachable' }), {
|
|
99
|
+
status: 503,
|
|
100
|
+
headers: { 'Content-Type': 'application/json' },
|
|
101
|
+
})
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
function initState() {
|
|
105
|
+
return { showStandaloneLabel: false }
|
|
106
|
+
}
|
|
107
|
+
</script>
|
|
108
|
+
|
|
109
|
+
<template>
|
|
110
|
+
<Story title="Workflow/GeneratedPluginView">
|
|
111
|
+
<Variant title="Playground" :init-state="initState">
|
|
112
|
+
<template #default="{ state }">
|
|
113
|
+
<div style="height: 42rem;">
|
|
114
|
+
<GeneratedPluginView
|
|
115
|
+
base-url="/story/peak-qc"
|
|
116
|
+
:transport="readyTransport"
|
|
117
|
+
:show-standalone-label="state.showStandaloneLabel"
|
|
118
|
+
/>
|
|
119
|
+
</div>
|
|
120
|
+
</template>
|
|
121
|
+
|
|
122
|
+
<template #controls="{ state }">
|
|
123
|
+
<HstCheckbox v-model="state.showStandaloneLabel" title="Standalone label" />
|
|
124
|
+
</template>
|
|
125
|
+
</Variant>
|
|
126
|
+
|
|
127
|
+
<Variant title="Ready — two job definitions">
|
|
128
|
+
<div style="height: 42rem;">
|
|
129
|
+
<GeneratedPluginView base-url="/story/peak-qc" :transport="readyTransport" />
|
|
130
|
+
</div>
|
|
131
|
+
</Variant>
|
|
132
|
+
|
|
133
|
+
<Variant title="Loading">
|
|
134
|
+
<div style="height: 42rem;">
|
|
135
|
+
<GeneratedPluginView base-url="/story/loading" :transport="loadingTransport" />
|
|
136
|
+
</div>
|
|
137
|
+
</Variant>
|
|
138
|
+
|
|
139
|
+
<Variant title="Runtime unreachable">
|
|
140
|
+
<div style="height: 42rem;">
|
|
141
|
+
<GeneratedPluginView base-url="/story/failing" :transport="failingTransport" />
|
|
142
|
+
</div>
|
|
143
|
+
</Variant>
|
|
144
|
+
</Story>
|
|
145
|
+
</template>
|
|
@@ -207,7 +207,7 @@ onMounted(() => {
|
|
|
207
207
|
min-width: 0;
|
|
208
208
|
min-height: calc(100vh - 5rem);
|
|
209
209
|
padding: clamp(1rem, 2.5vw, 2.5rem);
|
|
210
|
-
background: var(--
|
|
210
|
+
background: var(--bg-primary);
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
.mint-generated-workspace__loading {
|
|
@@ -216,7 +216,7 @@ onMounted(() => {
|
|
|
216
216
|
align-items: center;
|
|
217
217
|
justify-content: center;
|
|
218
218
|
gap: 0.75rem;
|
|
219
|
-
color: var(--
|
|
219
|
+
color: var(--text-secondary);
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
.mint-generated-workspace__header {
|
|
@@ -230,19 +230,19 @@ onMounted(() => {
|
|
|
230
230
|
|
|
231
231
|
.mint-generated-workspace__header h1 {
|
|
232
232
|
margin: 0;
|
|
233
|
-
color: var(--
|
|
233
|
+
color: var(--text-primary);
|
|
234
234
|
font-size: clamp(1.35rem, 2vw, 1.8rem);
|
|
235
235
|
line-height: 1.2;
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
.mint-generated-workspace__header p:not(.mint-generated-workspace__eyebrow) {
|
|
239
239
|
margin: 0.4rem 0 0;
|
|
240
|
-
color: var(--
|
|
240
|
+
color: var(--text-secondary);
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
.mint-generated-workspace__eyebrow {
|
|
244
244
|
margin: 0 0 0.35rem;
|
|
245
|
-
color: var(--
|
|
245
|
+
color: var(--text-muted);
|
|
246
246
|
font-size: 0.72rem;
|
|
247
247
|
font-weight: 700;
|
|
248
248
|
letter-spacing: 0.08em;
|
|
@@ -258,10 +258,10 @@ onMounted(() => {
|
|
|
258
258
|
|
|
259
259
|
.mint-generated-workspace__resources span {
|
|
260
260
|
padding: 0.3rem 0.55rem;
|
|
261
|
-
border: 1px solid var(--color
|
|
261
|
+
border: 1px solid var(--border-color);
|
|
262
262
|
border-radius: 999px;
|
|
263
|
-
background: var(--
|
|
264
|
-
color: var(--
|
|
263
|
+
background: var(--bg-secondary);
|
|
264
|
+
color: var(--text-secondary);
|
|
265
265
|
font-size: 0.75rem;
|
|
266
266
|
font-weight: 600;
|
|
267
267
|
}
|
|
@@ -271,9 +271,9 @@ onMounted(() => {
|
|
|
271
271
|
min-height: 24rem;
|
|
272
272
|
margin: 0 auto;
|
|
273
273
|
padding: clamp(1rem, 2vw, 1.75rem);
|
|
274
|
-
border: 1px solid var(--color
|
|
274
|
+
border: 1px solid var(--border-color);
|
|
275
275
|
border-radius: 1rem;
|
|
276
|
-
background: var(--
|
|
276
|
+
background: var(--bg-secondary);
|
|
277
277
|
box-shadow: var(--shadow-sm);
|
|
278
278
|
}
|
|
279
279
|
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import GeneratedResultRenderer from './GeneratedResultRenderer.vue'
|
|
3
|
+
import type { GeneratedAnalysisResult } from '../types/generated-ui'
|
|
4
|
+
|
|
5
|
+
const textResult: GeneratedAnalysisResult = {
|
|
6
|
+
kind: 'text',
|
|
7
|
+
text: 'Peak integration finished: 1,284 features across 96 samples, 12 flagged for manual review.',
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const jsonResult: GeneratedAnalysisResult = {
|
|
11
|
+
kind: 'json',
|
|
12
|
+
value: {
|
|
13
|
+
method: 'HILIC_neg_12min',
|
|
14
|
+
features: 1284,
|
|
15
|
+
qc: { rsd_median: 0.041, blanks_removed: 37 },
|
|
16
|
+
flagged: ['M241T118', 'M317T204'],
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const tableResult: GeneratedAnalysisResult = {
|
|
21
|
+
kind: 'table',
|
|
22
|
+
columns: ['feature_id', 'mz', 'retention_time', 'fold_change', 'p_value'],
|
|
23
|
+
rows: [
|
|
24
|
+
{ feature_id: 'M180T204', mz: 180.0634, retention_time: 3.42, fold_change: 2.14, p_value: 0.0012 },
|
|
25
|
+
{ feature_id: 'M241T118', mz: 241.0311, retention_time: 1.97, fold_change: -1.83, p_value: 0.0044 },
|
|
26
|
+
{ feature_id: 'M317T204', mz: 317.0521, retention_time: 3.41, fold_change: 1.07, p_value: 0.2310 },
|
|
27
|
+
{ feature_id: 'M146T092', mz: 146.0453, retention_time: 1.53, fold_change: -3.02, p_value: 0.0001 },
|
|
28
|
+
],
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 1x1 transparent PNG — enough to exercise the image branch without a fixture.
|
|
32
|
+
const PIXEL_PNG
|
|
33
|
+
= 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=='
|
|
34
|
+
|
|
35
|
+
const imageResult: GeneratedAnalysisResult = {
|
|
36
|
+
kind: 'image',
|
|
37
|
+
media_type: 'image/png',
|
|
38
|
+
data: PIXEL_PNG,
|
|
39
|
+
alt: 'Static QC overview rendered by the plugin',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const artifactResult: GeneratedAnalysisResult = {
|
|
43
|
+
kind: 'artifact',
|
|
44
|
+
id: 'art_01J9',
|
|
45
|
+
name: 'peak_table.parquet',
|
|
46
|
+
media_type: 'application/vnd.apache.parquet',
|
|
47
|
+
size: 4_812_390,
|
|
48
|
+
download_url: '#download',
|
|
49
|
+
managed: true,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type ResultKind = 'text' | 'json' | 'table' | 'image' | 'artifact'
|
|
53
|
+
|
|
54
|
+
const kinds: ResultKind[] = ['text', 'json', 'table', 'image', 'artifact']
|
|
55
|
+
|
|
56
|
+
const byKind: Record<ResultKind, GeneratedAnalysisResult> = {
|
|
57
|
+
text: textResult,
|
|
58
|
+
json: jsonResult,
|
|
59
|
+
table: tableResult,
|
|
60
|
+
image: imageResult,
|
|
61
|
+
artifact: artifactResult,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function initState() {
|
|
65
|
+
return { kind: 'table' as ResultKind }
|
|
66
|
+
}
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<template>
|
|
70
|
+
<Story title="Workflow/GeneratedResultRenderer">
|
|
71
|
+
<Variant title="Playground" :init-state="initState">
|
|
72
|
+
<template #default="{ state }">
|
|
73
|
+
<div style="padding: 2rem; max-width: 720px;">
|
|
74
|
+
<GeneratedResultRenderer :result="byKind[state.kind as ResultKind]" />
|
|
75
|
+
</div>
|
|
76
|
+
</template>
|
|
77
|
+
|
|
78
|
+
<template #controls="{ state }">
|
|
79
|
+
<HstSelect
|
|
80
|
+
v-model="state.kind"
|
|
81
|
+
title="Result kind"
|
|
82
|
+
:options="kinds.map(k => ({ label: k, value: k }))"
|
|
83
|
+
/>
|
|
84
|
+
</template>
|
|
85
|
+
</Variant>
|
|
86
|
+
|
|
87
|
+
<Variant title="Text">
|
|
88
|
+
<div style="padding: 2rem; max-width: 720px;">
|
|
89
|
+
<GeneratedResultRenderer :result="textResult" />
|
|
90
|
+
</div>
|
|
91
|
+
</Variant>
|
|
92
|
+
|
|
93
|
+
<Variant title="Table">
|
|
94
|
+
<div style="padding: 2rem; max-width: 720px;">
|
|
95
|
+
<GeneratedResultRenderer :result="tableResult" />
|
|
96
|
+
</div>
|
|
97
|
+
</Variant>
|
|
98
|
+
|
|
99
|
+
<Variant title="JSON">
|
|
100
|
+
<div style="padding: 2rem; max-width: 720px;">
|
|
101
|
+
<GeneratedResultRenderer :result="jsonResult" />
|
|
102
|
+
</div>
|
|
103
|
+
</Variant>
|
|
104
|
+
|
|
105
|
+
<Variant title="Image">
|
|
106
|
+
<div style="padding: 2rem; max-width: 720px;">
|
|
107
|
+
<GeneratedResultRenderer :result="imageResult" />
|
|
108
|
+
</div>
|
|
109
|
+
</Variant>
|
|
110
|
+
|
|
111
|
+
<Variant title="Artifact download">
|
|
112
|
+
<div style="padding: 2rem; max-width: 720px;">
|
|
113
|
+
<GeneratedResultRenderer :result="artifactResult" />
|
|
114
|
+
</div>
|
|
115
|
+
</Variant>
|
|
116
|
+
</Story>
|
|
117
|
+
</template>
|
|
@@ -101,7 +101,7 @@ function humanize(value: string): string {
|
|
|
101
101
|
.mint-generated-result__text,
|
|
102
102
|
.mint-generated-result__json {
|
|
103
103
|
margin: 0;
|
|
104
|
-
color: var(--
|
|
104
|
+
color: var(--text-primary);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
.mint-generated-result__text {
|
|
@@ -113,9 +113,9 @@ function humanize(value: string): string {
|
|
|
113
113
|
.mint-generated-result__json {
|
|
114
114
|
overflow: auto;
|
|
115
115
|
padding: 1rem;
|
|
116
|
-
border: 1px solid var(--color
|
|
116
|
+
border: 1px solid var(--border-color);
|
|
117
117
|
border-radius: 0.75rem;
|
|
118
|
-
background: var(--
|
|
118
|
+
background: var(--bg-secondary);
|
|
119
119
|
font-size: 0.8125rem;
|
|
120
120
|
line-height: 1.55;
|
|
121
121
|
white-space: pre-wrap;
|
|
@@ -139,7 +139,7 @@ function humanize(value: string): string {
|
|
|
139
139
|
justify-content: space-between;
|
|
140
140
|
gap: 1rem;
|
|
141
141
|
padding: 1rem;
|
|
142
|
-
border: 1px solid var(--color
|
|
142
|
+
border: 1px solid var(--border-color);
|
|
143
143
|
border-radius: 0.75rem;
|
|
144
144
|
color: var(--color-primary);
|
|
145
145
|
text-decoration: none;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/** Drag-and-drop two-zone assigner for splitting sample groups into control and treatment arms. */
|
|
3
|
-
import { ref } from 'vue'
|
|
3
|
+
import { nextTick, ref, type ComponentPublicInstance } from 'vue'
|
|
4
4
|
import type { GroupItem } from '../types'
|
|
5
5
|
import { useGroupAssignment, type GroupAssignmentState, type GroupAssignmentZone } from '../composables/useGroupAssignment'
|
|
6
|
+
import { useReorderAnnouncer } from '../composables/useListReorder'
|
|
6
7
|
|
|
7
8
|
interface Props {
|
|
8
9
|
groups: GroupItem[]
|
|
@@ -98,6 +99,56 @@ function emitAssignment(state: GroupAssignmentState) {
|
|
|
98
99
|
emit('update:group1', state.group1)
|
|
99
100
|
emit('update:group2', state.group2)
|
|
100
101
|
}
|
|
102
|
+
|
|
103
|
+
// Keyboard alternative to the pointer drag. GroupAssigner moves items between
|
|
104
|
+
// zones rather than reordering one list, so it shares the announcer (and the
|
|
105
|
+
// Alt+Arrow idiom) with useListReorder without its index maths.
|
|
106
|
+
const { announcement, announce, announcerStyle } = useReorderAnnouncer()
|
|
107
|
+
const pillRefs = new Map<string, HTMLElement>()
|
|
108
|
+
|
|
109
|
+
function setPillRef(name: string, el: Element | ComponentPublicInstance | null) {
|
|
110
|
+
if (el instanceof HTMLElement) {
|
|
111
|
+
pillRefs.set(name, el)
|
|
112
|
+
} else {
|
|
113
|
+
pillRefs.delete(name)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function zoneLabel(zone: GroupAssignmentZone | null): string {
|
|
118
|
+
if (zone === 'zone1') return props.label1
|
|
119
|
+
if (zone === 'zone2') return props.label2
|
|
120
|
+
return 'Available Groups'
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Alt+Left / Alt+Right walk a group through Control → unassigned → Treatment. */
|
|
124
|
+
function handlePillKeydown(event: KeyboardEvent, groupName: string) {
|
|
125
|
+
if (!event.altKey) return
|
|
126
|
+
const direction =
|
|
127
|
+
event.key === 'ArrowLeft' ? -1 : event.key === 'ArrowRight' ? 1 : 0
|
|
128
|
+
if (direction === 0) return
|
|
129
|
+
|
|
130
|
+
event.preventDefault()
|
|
131
|
+
const order: Array<GroupAssignmentZone | null> = ['zone1', null, 'zone2']
|
|
132
|
+
const current = order.indexOf(assignment.getZoneForGroup(groupName))
|
|
133
|
+
const next = order[current + direction]
|
|
134
|
+
if (current === -1 || next === undefined) return
|
|
135
|
+
|
|
136
|
+
if (next === null) {
|
|
137
|
+
const from = assignment.getZoneForGroup(groupName)
|
|
138
|
+
if (from) removeFromZone(groupName, from)
|
|
139
|
+
} else {
|
|
140
|
+
assignToZone(groupName, next)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
announce(`${groupName} moved to ${zoneLabel(next)}.`)
|
|
144
|
+
void nextTick(() => pillRefs.get(groupName)?.focus())
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Instructions read out with each pill. */
|
|
148
|
+
function pillLabel(group: GroupItem): string {
|
|
149
|
+
const zone = assignment.getZoneForGroup(group.name)
|
|
150
|
+
return `${group.name}, ${zoneLabel(zone)}. Press Alt with the left or right arrow keys to move it.`
|
|
151
|
+
}
|
|
101
152
|
</script>
|
|
102
153
|
|
|
103
154
|
<template>
|
|
@@ -125,10 +176,14 @@ function emitAssignment(state: GroupAssignmentState) {
|
|
|
125
176
|
<div
|
|
126
177
|
v-for="group in zone1Groups"
|
|
127
178
|
:key="group.name"
|
|
179
|
+
:ref="(el) => setPillRef(group.name, el)"
|
|
128
180
|
class="mint-group-assigner__pill"
|
|
129
181
|
draggable="true"
|
|
182
|
+
tabindex="0"
|
|
183
|
+
:aria-label="pillLabel(group)"
|
|
130
184
|
@dragstart="handleDragStart($event, group.name)"
|
|
131
185
|
@dragend="handleDragEnd"
|
|
186
|
+
@keydown="handlePillKeydown($event, group.name)"
|
|
132
187
|
>
|
|
133
188
|
<span
|
|
134
189
|
class="mint-group-assigner__pill-color"
|
|
@@ -174,10 +229,14 @@ function emitAssignment(state: GroupAssignmentState) {
|
|
|
174
229
|
<div
|
|
175
230
|
v-for="group in zone2Groups"
|
|
176
231
|
:key="group.name"
|
|
232
|
+
:ref="(el) => setPillRef(group.name, el)"
|
|
177
233
|
class="mint-group-assigner__pill"
|
|
178
234
|
draggable="true"
|
|
235
|
+
tabindex="0"
|
|
236
|
+
:aria-label="pillLabel(group)"
|
|
179
237
|
@dragstart="handleDragStart($event, group.name)"
|
|
180
238
|
@dragend="handleDragEnd"
|
|
239
|
+
@keydown="handlePillKeydown($event, group.name)"
|
|
181
240
|
>
|
|
182
241
|
<span
|
|
183
242
|
class="mint-group-assigner__pill-color"
|
|
@@ -221,14 +280,18 @@ function emitAssignment(state: GroupAssignmentState) {
|
|
|
221
280
|
<div
|
|
222
281
|
v-for="group in unassignedGroups"
|
|
223
282
|
:key="group.name"
|
|
283
|
+
:ref="(el) => setPillRef(group.name, el)"
|
|
224
284
|
:class="[
|
|
225
285
|
'mint-group-assigner__pill',
|
|
226
286
|
'mint-group-assigner__pill--unassigned',
|
|
227
287
|
draggingGroup === group.name ? 'mint-group-assigner__pill--dragging' : '',
|
|
228
288
|
]"
|
|
229
289
|
draggable="true"
|
|
290
|
+
tabindex="0"
|
|
291
|
+
:aria-label="pillLabel(group)"
|
|
230
292
|
@dragstart="handleDragStart($event, group.name)"
|
|
231
293
|
@dragend="handleDragEnd"
|
|
294
|
+
@keydown="handlePillKeydown($event, group.name)"
|
|
232
295
|
>
|
|
233
296
|
<span
|
|
234
297
|
class="mint-group-assigner__pill-color"
|
|
@@ -240,6 +303,9 @@ function emitAssignment(state: GroupAssignmentState) {
|
|
|
240
303
|
</div>
|
|
241
304
|
</div>
|
|
242
305
|
|
|
306
|
+
<!-- Assignment announcements for screen readers -->
|
|
307
|
+
<div role="status" aria-live="polite" :style="announcerStyle">{{ announcement }}</div>
|
|
308
|
+
|
|
243
309
|
<!-- Validation message -->
|
|
244
310
|
<div v-if="validationMessage" class="mint-group-assigner__validation">
|
|
245
311
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
@@ -251,7 +317,3 @@ function emitAssignment(state: GroupAssignmentState) {
|
|
|
251
317
|
</div>
|
|
252
318
|
</div>
|
|
253
319
|
</template>
|
|
254
|
-
|
|
255
|
-
<style>
|
|
256
|
-
@import '../styles/components/group-assigner.css';
|
|
257
|
-
</style>
|
|
@@ -15,12 +15,24 @@ import {
|
|
|
15
15
|
} from '../jobs'
|
|
16
16
|
import {
|
|
17
17
|
usePluginJobCenter,
|
|
18
|
+
type JobsStatusTrayAdapter,
|
|
18
19
|
type PluginJobCenterSource,
|
|
19
20
|
} from '../composables/useJobsStatusTray'
|
|
20
|
-
import type {
|
|
21
|
+
import type { UsePluginEventStreamReturn } from '../composables/usePluginClient'
|
|
22
|
+
import type {
|
|
23
|
+
JobState,
|
|
24
|
+
JobStateInput,
|
|
25
|
+
JobStreamData,
|
|
26
|
+
} from '../types/jobs'
|
|
21
27
|
|
|
22
28
|
interface Props {
|
|
23
29
|
source?: PluginJobCenterSource
|
|
30
|
+
/** @deprecated Pass a source instead. */
|
|
31
|
+
jobs?: readonly JobStateInput[]
|
|
32
|
+
/** @deprecated Pass source actions instead. */
|
|
33
|
+
adapter?: JobsStatusTrayAdapter
|
|
34
|
+
/** @deprecated Event streams belong to the source runtime. */
|
|
35
|
+
eventStream?: UsePluginEventStreamReturn<JobStreamData>
|
|
24
36
|
loadOnMount?: boolean
|
|
25
37
|
title?: string
|
|
26
38
|
teleportTo?: string | HTMLElement | false
|
|
@@ -49,6 +61,9 @@ const panelRef = ref<HTMLElement | null>(null)
|
|
|
49
61
|
const teleportTarget = computed(() => props.teleportTo || 'body')
|
|
50
62
|
const tray = usePluginJobCenter({
|
|
51
63
|
source: toRef(props, 'source'),
|
|
64
|
+
jobs: toRef(props, 'jobs'),
|
|
65
|
+
adapter: toRef(props, 'adapter'),
|
|
66
|
+
eventStream: toRef(props, 'eventStream'),
|
|
52
67
|
loadOnMount: props.loadOnMount,
|
|
53
68
|
})
|
|
54
69
|
const canClear = computed(() => (
|
|
@@ -386,7 +401,3 @@ async function clearFinished(): Promise<void> {
|
|
|
386
401
|
</div>
|
|
387
402
|
</Teleport>
|
|
388
403
|
</template>
|
|
389
|
-
|
|
390
|
-
<style>
|
|
391
|
-
@import '../styles/components/jobs-status-tray.css';
|
|
392
|
-
</style>
|