@morscherlab/mint-sdk 1.2.0-beta.2 → 1.2.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 +65 -5
- package/dist/{ExperimentPopover-tLwJ7XF4.js → ExperimentPopover-CJdNlCZb.js} +24 -15
- package/dist/ExperimentPopover-CJdNlCZb.js.map +1 -0
- package/dist/{ExperimentSelectorModal-DyPAUCLw.js → ExperimentSelectorModal-DCXmwKNS.js} +5 -5
- package/dist/ExperimentSelectorModal-DCXmwKNS.js.map +1 -0
- package/dist/{SettingsModal-BgKY93zh.js → SettingsModal-BYR20I4c.js} +5 -8
- package/dist/SettingsModal-BYR20I4c.js.map +1 -0
- package/dist/{EmptyState-p90quq8Z.js → Skeleton-BAF3CKY7.js} +111 -93
- package/dist/Skeleton-BAF3CKY7.js.map +1 -0
- package/dist/__tests__/components/DataStates.test.d.ts +1 -0
- package/dist/__tests__/components/ExperimentTimeline.test.d.ts +1 -0
- package/dist/__tests__/components/FileBrowserModal.test.d.ts +1 -0
- package/dist/__tests__/components/FilePicker.state.test.d.ts +1 -0
- package/dist/__tests__/components/FilePicker.test.d.ts +1 -0
- package/dist/__tests__/components/PlotlyChart.test.d.ts +1 -0
- package/dist/__tests__/components/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__/components/iconButtonIconSizing.test.d.ts +1 -0
- package/dist/__tests__/composables/useFileBrowser.test.d.ts +1 -0
- package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
- package/dist/__tests__/composables/usePlatformFilePickerAdapter.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/apiErrors.d.ts +26 -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/BaseInput.vue.d.ts +1 -1
- package/dist/components/BaseSelect.vue.d.ts +1 -1
- package/dist/components/BaseTextarea.vue.d.ts +1 -1
- package/dist/components/BatchProgressList.vue.d.ts +17 -0
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +4 -4
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +2 -2
- package/dist/components/ConcentrationInput.vue.d.ts +1 -1
- package/dist/components/DataFrame.vue.d.ts +14 -2
- package/dist/components/DatePicker.vue.d.ts +2 -2
- package/dist/components/DateTimePicker.vue.d.ts +3 -1
- 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/FileBrowserModal.vue.d.ts +99 -0
- package/dist/components/FilePicker.vue.d.ts +32 -0
- package/dist/components/FileUploader.vue.d.ts +5 -2
- package/dist/components/FitPanel.vue.d.ts +1 -1
- package/dist/components/FormulaInput.vue.d.ts +1 -1
- package/dist/components/GeneratedPlotlyResult.vue.d.ts +1 -3
- package/dist/components/JobsStatusTray.vue.d.ts +9 -2
- package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
- package/dist/components/MobileSupportGate.vue.d.ts +1 -1
- package/dist/components/MoleculeInput.vue.d.ts +1 -1
- package/dist/components/NumberInput.vue.d.ts +1 -1
- package/dist/components/PlotlyChart.vue.d.ts +59 -0
- package/dist/components/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/ResourceCard.vue.d.ts +1 -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/SequenceInput.vue.d.ts +1 -1
- package/dist/components/SettingsModal.vue.d.ts +1 -1
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -1
- package/dist/components/StatusIndicator.vue.d.ts +1 -1
- package/dist/components/TagsInput.vue.d.ts +1 -1
- package/dist/components/TimePicker.vue.d.ts +2 -1
- package/dist/components/TimeRangeInput.vue.d.ts +1 -1
- package/dist/components/UnitInput.vue.d.ts +1 -1
- 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 +30 -1
- package/dist/components/fileBrowserPresentation.d.ts +10 -0
- package/dist/components/index.d.ts +13 -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/FileBrowserDialogInternal.vue.d.ts +34 -0
- package/dist/components/internal/FileBrowserListingInternal.vue.d.ts +25 -0
- package/dist/components/internal/FileBrowserToolbarInternal.vue.d.ts +26 -0
- package/dist/components/internal/FilePickerPreviewInternal.vue.d.ts +18 -0
- package/dist/components/internal/FilePickerTreeInternal.vue.d.ts +31 -0
- package/dist/components/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-DIum5hkx.js} +5882 -3200
- package/dist/components-DIum5hkx.js.map +1 -0
- package/dist/composables/controlSchemaTypes.d.ts +34 -0
- package/dist/composables/filePicker/localFiles.d.ts +3 -0
- package/dist/composables/filePicker/usePickerNavigation.d.ts +96 -0
- package/dist/composables/filePicker/usePickerSelection.d.ts +31 -0
- package/dist/composables/filePicker/validation.d.ts +5 -0
- package/dist/composables/flattenWorkspaceBindings.d.ts +61 -0
- package/dist/composables/index.d.ts +11 -2
- package/dist/composables/index.js +10 -10
- package/dist/composables/pluginWorkspaceModel.d.ts +164 -0
- package/dist/composables/useApi.d.ts +14 -7
- 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/useFileBrowser.d.ts +55 -0
- package/dist/composables/useFilePicker.d.ts +189 -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/usePlatformFilePickerAdapter.d.ts +11 -0
- 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-mFXsTA4g.js} +502 -86
- package/dist/composables-mFXsTA4g.js.map +1 -0
- package/dist/{useApi-J6zFkHmn.js → errors-BLuqMee5.js} +179 -16
- package/dist/errors-BLuqMee5.js.map +1 -0
- package/dist/{experiment-Cq145oEW.js → experiment-CVDRAnqp.js} +3 -8
- package/dist/experiment-CVDRAnqp.js.map +1 -0
- package/dist/{experiment-utils-CLnzPPq5.js → experiment-utils-CV2Wza3z.js} +70 -51
- package/dist/experiment-utils-CV2Wza3z.js.map +1 -0
- package/dist/index.d.ts +2 -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 +15135 -32397
- package/dist/templates/builderReadUtils.d.ts +1 -1
- package/dist/templates/index.js +2 -4
- package/dist/{templates-DsP51i-S.js → templates-CmGfmBRA.js} +303 -106
- package/dist/templates-CmGfmBRA.js.map +1 -0
- package/dist/types/auth.d.ts +1 -0
- package/dist/types/fileBrowserTypes.d.ts +77 -0
- package/dist/types/filePicker.d.ts +77 -0
- package/dist/types/form-builder.d.ts +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/{useControlSchema-BDx2Olha.js → useControlSchema-DldpxNOP.js} +499 -1162
- package/dist/useControlSchema-DldpxNOP.js.map +1 -0
- package/dist/{useDropdownState-DSb3BC3N.js → useDropdownState-C7hRiVQf.js} +22 -6
- package/dist/useDropdownState-C7hRiVQf.js.map +1 -0
- package/dist/{useExperimentSelector-CV4iNfMS.js → useExperimentSelector-CEcIaueJ.js} +4 -4
- package/dist/{useExperimentSelector-CV4iNfMS.js.map → useExperimentSelector-CEcIaueJ.js.map} +1 -1
- package/dist/{useFormBuilder-BLxG3BOX.js → useFormBuilder-z5L_dUIy.js} +2 -2
- package/dist/{useFormBuilder-BLxG3BOX.js.map → useFormBuilder-z5L_dUIy.js.map} +1 -1
- 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/dist/{useProtocolTemplates-CS_SQl6U.js → validation-uwoJGEb6.js} +811 -212
- package/dist/validation-uwoJGEb6.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/apiErrors.test.ts +81 -0
- package/src/__tests__/components/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/ExperimentPopover.test.ts +30 -0
- package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
- package/src/__tests__/components/FileBrowserModal.test.ts +460 -0
- package/src/__tests__/components/FilePicker.state.test.ts +287 -0
- package/src/__tests__/components/FilePicker.test.ts +487 -0
- package/src/__tests__/components/GeneratedPlotlyResult.test.ts +52 -5
- package/src/__tests__/components/GroupAssigner.test.ts +53 -0
- package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
- package/src/__tests__/components/PlotlyChart.test.ts +305 -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 +107 -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__/components/iconButtonIconSizing.test.ts +18 -0
- package/src/__tests__/composables/useApi.test.ts +92 -9
- package/src/__tests__/composables/useAuth.test.ts +2 -0
- package/src/__tests__/composables/useDropdownState.test.ts +58 -1
- package/src/__tests__/composables/useFileBrowser.test.ts +305 -0
- package/src/__tests__/composables/useGeneratedAnalysis.test.ts +7 -2
- package/src/__tests__/composables/useListReorder.test.ts +145 -0
- package/src/__tests__/composables/usePlatformFilePickerAdapter.test.ts +67 -0
- package/src/__tests__/composables/usePluginClient.test.ts +143 -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/apiErrors.ts +85 -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 +12 -7
- 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/FileBrowserModal.story.vue +203 -0
- package/src/components/FileBrowserModal.vue +384 -0
- package/src/components/FilePicker.story.vue +44 -0
- package/src/components/FilePicker.vue +284 -0
- package/src/components/FileUploader.vue +32 -18
- 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 +34 -69
- 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 -9
- 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/PlotlyChart.story.vue +61 -0
- package/src/components/PlotlyChart.vue +233 -0
- 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 +50 -7
- 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/fileBrowserPresentation.ts +39 -0
- package/src/components/index.ts +14 -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/FileBrowserDialogInternal.vue +75 -0
- package/src/components/internal/FileBrowserListingInternal.vue +197 -0
- package/src/components/internal/FileBrowserToolbarInternal.vue +136 -0
- package/src/components/internal/FilePickerPreviewInternal.vue +100 -0
- package/src/components/internal/FilePickerTreeInternal.vue +238 -0
- package/src/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/filePicker/localFiles.ts +58 -0
- package/src/composables/filePicker/usePickerNavigation.ts +220 -0
- package/src/composables/filePicker/usePickerSelection.ts +259 -0
- package/src/composables/filePicker/validation.ts +41 -0
- package/src/composables/flattenWorkspaceBindings.ts +104 -0
- package/src/composables/formBuilderRegistry.ts +5 -0
- package/src/composables/index.ts +50 -0
- package/src/composables/pluginWorkspaceModel.ts +182 -0
- package/src/composables/useApi.ts +57 -13
- 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/useFileBrowser.ts +314 -0
- package/src/composables/useFileImport.ts +2 -7
- package/src/composables/useFilePicker.ts +366 -0
- package/src/composables/useFocusTrap.ts +91 -0
- package/src/composables/useGeneratedAnalysis.ts +32 -27
- 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/usePlatformFilePickerAdapter.ts +104 -0
- package/src/composables/usePluginClient.ts +50 -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 +19 -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/file-browser-modal.css +489 -0
- package/src/styles/components/file-picker.css +502 -0
- package/src/styles/components/form-builder.css +5 -5
- package/src/styles/components/icon-button.css +9 -0
- 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 +12 -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/fileBrowserTypes.ts +85 -0
- package/src/types/filePicker.ts +72 -0
- package/src/types/form-builder.ts +1 -0
- package/src/types/index.ts +14 -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 → apiErrors.test.d.ts} +0 -0
|
@@ -21,6 +21,8 @@ const allCompleted = [
|
|
|
21
21
|
|
|
22
22
|
function initState() {
|
|
23
23
|
return {
|
|
24
|
+
loading: false,
|
|
25
|
+
error: '',
|
|
24
26
|
items: mixedItems,
|
|
25
27
|
showSummary: true,
|
|
26
28
|
title: 'Processing Raw Data Files',
|
|
@@ -35,6 +37,8 @@ function initState() {
|
|
|
35
37
|
<template #default="{ state }">
|
|
36
38
|
<div style="padding: 2rem; max-width: 500px;">
|
|
37
39
|
<BatchProgressList
|
|
40
|
+
:loading="state.loading"
|
|
41
|
+
:error="state.error || null"
|
|
38
42
|
:items="state.items"
|
|
39
43
|
:show-summary="state.showSummary"
|
|
40
44
|
:title="state.title"
|
|
@@ -45,6 +49,8 @@ function initState() {
|
|
|
45
49
|
</div>
|
|
46
50
|
</template>
|
|
47
51
|
<template #controls="{ state }">
|
|
52
|
+
<HstCheckbox v-model="state.loading" title="Loading" />
|
|
53
|
+
<HstText v-model="state.error" title="Error Message" />
|
|
48
54
|
<HstCheckbox v-model="state.showSummary" title="Show Summary" />
|
|
49
55
|
<HstText v-model="state.title" title="Title" />
|
|
50
56
|
<HstCheckbox v-model="state.autoScroll" title="Auto Scroll" />
|
|
@@ -88,5 +94,17 @@ function initState() {
|
|
|
88
94
|
/>
|
|
89
95
|
</div>
|
|
90
96
|
</Variant>
|
|
97
|
+
|
|
98
|
+
<Variant title="Loading">
|
|
99
|
+
<div style="padding: 2rem; max-width: 600px;">
|
|
100
|
+
<BatchProgressList :items="[]" loading />
|
|
101
|
+
</div>
|
|
102
|
+
</Variant>
|
|
103
|
+
|
|
104
|
+
<Variant title="Error">
|
|
105
|
+
<div style="padding: 2rem; max-width: 600px;">
|
|
106
|
+
<BatchProgressList :items="[]" error="Could not load the batch." />
|
|
107
|
+
</div>
|
|
108
|
+
</Variant>
|
|
91
109
|
</Story>
|
|
92
110
|
</template>
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { computed, ref, watch, nextTick } from 'vue'
|
|
4
4
|
import type { BatchItem, BatchSummary } from '../types'
|
|
5
5
|
import { useExpansionSet } from '../composables/useExpansionSet'
|
|
6
|
+
import DataStateInternal from './internal/DataStateInternal.vue'
|
|
6
7
|
|
|
7
8
|
interface Props {
|
|
8
9
|
items: BatchItem[]
|
|
@@ -10,11 +11,23 @@ interface Props {
|
|
|
10
11
|
title?: string
|
|
11
12
|
maxHeight?: string
|
|
12
13
|
autoScroll?: boolean
|
|
14
|
+
/** Replace the item list with a loading placeholder. */
|
|
15
|
+
loading?: boolean
|
|
16
|
+
/**
|
|
17
|
+
* Error message. When set, the item list is replaced by an error state.
|
|
18
|
+
* `null`/`undefined` renders normally.
|
|
19
|
+
*/
|
|
20
|
+
error?: string | null
|
|
21
|
+
/** Empty-state headline shown when there are no batch items. */
|
|
22
|
+
emptyMessage?: string
|
|
13
23
|
}
|
|
14
24
|
|
|
15
25
|
const props = withDefaults(defineProps<Props>(), {
|
|
16
26
|
showSummary: true,
|
|
17
27
|
autoScroll: true,
|
|
28
|
+
loading: false,
|
|
29
|
+
error: null,
|
|
30
|
+
emptyMessage: 'No items in this batch',
|
|
18
31
|
})
|
|
19
32
|
|
|
20
33
|
const emit = defineEmits<{
|
|
@@ -91,7 +104,26 @@ watch(
|
|
|
91
104
|
</div>
|
|
92
105
|
</slot>
|
|
93
106
|
|
|
107
|
+
<div v-if="error" class="mint-batch-progress__state">
|
|
108
|
+
<slot name="error" :error="error">
|
|
109
|
+
<DataStateInternal state="error" size="sm" :title="error" />
|
|
110
|
+
</slot>
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<div v-else-if="loading" class="mint-batch-progress__state">
|
|
114
|
+
<slot name="loading">
|
|
115
|
+
<DataStateInternal state="loading" size="sm" loading-label="Loading batch" />
|
|
116
|
+
</slot>
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
<div v-else-if="items.length === 0" class="mint-batch-progress__state">
|
|
120
|
+
<slot name="empty">
|
|
121
|
+
<DataStateInternal state="empty" size="sm" :title="emptyMessage" />
|
|
122
|
+
</slot>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
94
125
|
<div
|
|
126
|
+
v-else
|
|
95
127
|
ref="listRef"
|
|
96
128
|
class="mint-batch-progress__list"
|
|
97
129
|
:style="maxHeight ? { maxHeight, overflowY: 'auto' } : {}"
|
|
@@ -175,7 +207,3 @@ watch(
|
|
|
175
207
|
</div>
|
|
176
208
|
</div>
|
|
177
209
|
</template>
|
|
178
|
-
|
|
179
|
-
<style>
|
|
180
|
-
@import '../styles/components/batch-progress-list.css';
|
|
181
|
-
</style>
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
type BioTemplateComponentPropsLookupOptions,
|
|
20
20
|
type TemplateCollectionEnvelope,
|
|
21
21
|
} from '../templates'
|
|
22
|
+
import { bioTemplateExperimentWorkspaceProps } from '../composables/workspaceRecipes'
|
|
22
23
|
import AlertBox from './AlertBox.vue'
|
|
23
24
|
import BaseButton from './BaseButton.vue'
|
|
24
25
|
import BioTemplateRenderer from './BioTemplateRenderer.vue'
|
|
@@ -114,27 +115,15 @@ const statusMessage = computed(() => {
|
|
|
114
115
|
return `${props.label} template data saves to experiment design_data.`
|
|
115
116
|
})
|
|
116
117
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
)
|
|
126
|
-
const resolvedHasExperiment = computed(() =>
|
|
127
|
-
props.status?.hasExperiment ?? props.hasExperiment,
|
|
128
|
-
)
|
|
129
|
-
const resolvedCurrentExperimentId = computed(() =>
|
|
130
|
-
props.status?.currentExperimentId ?? props.currentExperimentId,
|
|
131
|
-
)
|
|
132
|
-
const resolvedLastLoadedAt = computed(() =>
|
|
133
|
-
props.status?.lastLoadedAt !== undefined ? props.status.lastLoadedAt : props.lastLoadedAt,
|
|
134
|
-
)
|
|
135
|
-
const resolvedLastSavedAt = computed(() =>
|
|
136
|
-
props.status?.lastSavedAt !== undefined ? props.status.lastSavedAt : props.lastSavedAt,
|
|
137
|
-
)
|
|
118
|
+
// Thin recipe over bioTemplateExperimentWorkspaceProps(): merges the grouped `status` prop
|
|
119
|
+
// over the individual loading/error/experiment props (see workspaceRecipes.ts).
|
|
120
|
+
const resolvedStatus = computed(() => bioTemplateExperimentWorkspaceProps(props))
|
|
121
|
+
const resolvedLoading = computed(() => resolvedStatus.value.loading)
|
|
122
|
+
const resolvedError = computed(() => resolvedStatus.value.error)
|
|
123
|
+
const resolvedHasExperiment = computed(() => resolvedStatus.value.hasExperiment)
|
|
124
|
+
const resolvedCurrentExperimentId = computed(() => resolvedStatus.value.currentExperimentId)
|
|
125
|
+
const resolvedLastLoadedAt = computed(() => resolvedStatus.value.lastLoadedAt)
|
|
126
|
+
const resolvedLastSavedAt = computed(() => resolvedStatus.value.lastSavedAt)
|
|
138
127
|
|
|
139
128
|
const templateSummaries = computed(() =>
|
|
140
129
|
Object.values(extractTemplateCollection(props.target)).map(template => ({
|
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
UseBioTemplatePackWorkspaceReturn,
|
|
15
15
|
} from '../composables/useBioTemplatePackWorkspace'
|
|
16
16
|
import { useBioTemplatePackWorkspace } from '../composables/useBioTemplatePackWorkspace'
|
|
17
|
+
import { bioTemplatePackWorkspaceProps } from '../composables/workspaceRecipes'
|
|
17
18
|
import BioTemplateExperimentWorkspaceView from './BioTemplateExperimentWorkspaceView.vue'
|
|
18
19
|
|
|
19
20
|
interface BioTemplatePackWorkspaceSlotProps {
|
|
@@ -140,6 +141,15 @@ const resolvedActions = computed<PackWorkspaceActions>(() => ({
|
|
|
140
141
|
save: props.actions?.save ?? (() => resolvedWorkspace.value.saveCurrent()),
|
|
141
142
|
}))
|
|
142
143
|
|
|
144
|
+
// Thin recipe over bioTemplatePackWorkspaceProps(): forwards this view's own display props
|
|
145
|
+
// plus the pack-derived target/label/status/actions to BioTemplateExperimentWorkspaceView.
|
|
146
|
+
const experimentWorkspaceRecipe = computed(() => bioTemplatePackWorkspaceProps(props, {
|
|
147
|
+
target: target.value,
|
|
148
|
+
label: label.value,
|
|
149
|
+
status: resolvedStatus.value,
|
|
150
|
+
actions: resolvedActions.value,
|
|
151
|
+
}))
|
|
152
|
+
|
|
143
153
|
watch(
|
|
144
154
|
[() => props.pack, () => props.workspaceOptions],
|
|
145
155
|
() => {
|
|
@@ -152,21 +162,7 @@ onScopeDispose(() => generatedWorkspaceScope?.stop())
|
|
|
152
162
|
</script>
|
|
153
163
|
|
|
154
164
|
<template>
|
|
155
|
-
<BioTemplateExperimentWorkspaceView
|
|
156
|
-
:target="target"
|
|
157
|
-
kind="collection"
|
|
158
|
-
:label="label"
|
|
159
|
-
:message="message"
|
|
160
|
-
:status="resolvedStatus"
|
|
161
|
-
:actions="resolvedActions"
|
|
162
|
-
:dense="dense"
|
|
163
|
-
:readonly="readonly"
|
|
164
|
-
:show-status="showStatus"
|
|
165
|
-
:show-template-summary="showTemplateSummary"
|
|
166
|
-
:load-label="loadLabel"
|
|
167
|
-
:reset-label="resetLabel"
|
|
168
|
-
:save-label="saveLabel"
|
|
169
|
-
>
|
|
165
|
+
<BioTemplateExperimentWorkspaceView v-bind="experimentWorkspaceRecipe">
|
|
170
166
|
<template v-if="hasDefaultSlot" #default="slotProps">
|
|
171
167
|
<slot
|
|
172
168
|
v-bind="slotProps"
|
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
UseBioTemplatePresetWorkspaceReturn,
|
|
15
15
|
} from '../composables/useBioTemplatePresetWorkspace'
|
|
16
16
|
import { useBioTemplatePresetWorkspace } from '../composables/useBioTemplatePresetWorkspace'
|
|
17
|
+
import { bioTemplatePresetWorkspaceProps } from '../composables/workspaceRecipes'
|
|
17
18
|
import AlertBox from './AlertBox.vue'
|
|
18
19
|
import AppSidebar from './AppSidebar.vue'
|
|
19
20
|
import BaseButton from './BaseButton.vue'
|
|
@@ -96,19 +97,13 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
96
97
|
resetLabel: 'Reset defaults',
|
|
97
98
|
})
|
|
98
99
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
...(props.workspaceOptions.initialValues ?? {}),
|
|
107
|
-
...(props.initialValues ?? {}),
|
|
108
|
-
...(externalValues.value ?? {}),
|
|
109
|
-
},
|
|
110
|
-
}
|
|
111
|
-
})
|
|
100
|
+
// Thin recipe over bioTemplatePresetWorkspaceProps(): merges workspaceOptions/initialValues/
|
|
101
|
+
// v-model into the options useBioTemplatePresetWorkspace() consumes (see workspaceRecipes.ts).
|
|
102
|
+
const resolvedPresetProps = computed(() => bioTemplatePresetWorkspaceProps(props))
|
|
103
|
+
const externalValues = computed(() => resolvedPresetProps.value.externalValues)
|
|
104
|
+
const resolvedWorkspaceOptions = computed<UseBioTemplatePresetWorkspaceOptions>(() =>
|
|
105
|
+
resolvedPresetProps.value.resolvedWorkspaceOptions
|
|
106
|
+
)
|
|
112
107
|
|
|
113
108
|
let generatedWorkspaceScope: EffectScope | undefined
|
|
114
109
|
|
|
@@ -75,7 +75,7 @@ import ChartContainer from './ChartContainer.vue'
|
|
|
75
75
|
<button type="button" style="padding: 0.25rem 0.75rem; font-size: 0.8125rem; border: 1px solid var(--border-color, #e2e8f0); border-radius: 0.375rem; background: var(--bg-card, #fff); color: var(--text-primary, #1e293b); cursor: pointer;">
|
|
76
76
|
Linear
|
|
77
77
|
</button>
|
|
78
|
-
<button type="button" style="padding: 0.25rem 0.75rem; font-size: 0.8125rem; border: 1px solid var(--
|
|
78
|
+
<button type="button" style="padding: 0.25rem 0.75rem; font-size: 0.8125rem; border: 1px solid var(--color-primary); border-radius: 0.375rem; background: var(--color-primary); color: #fff; cursor: pointer;">
|
|
79
79
|
Log
|
|
80
80
|
</button>
|
|
81
81
|
</div>
|
|
@@ -16,6 +16,7 @@ import ReagentList from './ReagentList.vue'
|
|
|
16
16
|
import SampleSelector from './SampleSelector.vue'
|
|
17
17
|
import ScheduleCalendar from './ScheduleCalendar.vue'
|
|
18
18
|
import WellPlate from './WellPlate.vue'
|
|
19
|
+
import { isRecord } from '../utils/records'
|
|
19
20
|
|
|
20
21
|
export interface ComponentBindingRendererBinding {
|
|
21
22
|
id?: string
|
|
@@ -173,9 +174,6 @@ function normalizeProps(binding: ComponentBindingRendererBinding): Record<string
|
|
|
173
174
|
}
|
|
174
175
|
}
|
|
175
176
|
|
|
176
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
177
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
178
|
-
}
|
|
179
177
|
</script>
|
|
180
178
|
|
|
181
179
|
<template>
|
|
@@ -20,7 +20,8 @@ import type {
|
|
|
20
20
|
ControlWorkspaceOptions,
|
|
21
21
|
UseControlWorkspaceReturn,
|
|
22
22
|
} from '../composables/useControlSchema'
|
|
23
|
-
import {
|
|
23
|
+
import { useControlWorkspace } from '../composables/useControlSchema'
|
|
24
|
+
import { controlWorkspaceProps } from '../composables/workspaceRecipes'
|
|
24
25
|
import AppLayout from './AppLayout.vue'
|
|
25
26
|
import AppSidebar from './AppSidebar.vue'
|
|
26
27
|
import AppTopBar from './AppTopBar.vue'
|
|
@@ -161,27 +162,15 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
161
162
|
formSize: 'md',
|
|
162
163
|
})
|
|
163
164
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
const resolvedControlOptions = computed<ControlWorkspaceOptions>(() => {
|
|
174
|
-
if (props.initialValues === undefined && externalValues.value === undefined) return baseControlOptions.value
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
...baseControlOptions.value,
|
|
178
|
-
initialValues: {
|
|
179
|
-
...(baseControlOptions.value.initialValues ?? {}),
|
|
180
|
-
...(props.initialValues ?? {}),
|
|
181
|
-
...(externalValues.value ?? {}),
|
|
182
|
-
},
|
|
183
|
-
}
|
|
184
|
-
})
|
|
165
|
+
// Thin recipe over controlWorkspaceProps(): resolves model/controls/controlOptions/v-model
|
|
166
|
+
// into the schema + options pair useControlWorkspace() consumes, shared with
|
|
167
|
+
// DoseDesignWorkspaceView (which forwards its own props here) and
|
|
168
|
+
// BioTemplatePresetWorkspaceView's equivalent options merge.
|
|
169
|
+
const resolvedWorkspaceModel = computed(() => controlWorkspaceProps(props))
|
|
170
|
+
const externalValues = computed(() => resolvedWorkspaceModel.value.externalValues)
|
|
171
|
+
const resolvedModel = computed(() => resolvedWorkspaceModel.value.resolvedModel)
|
|
172
|
+
const resolvedControls = computed(() => resolvedWorkspaceModel.value.resolvedControls)
|
|
173
|
+
const resolvedControlOptions = computed(() => resolvedWorkspaceModel.value.resolvedControlOptions)
|
|
185
174
|
|
|
186
175
|
let generatedWorkspaceScope: EffectScope | undefined
|
|
187
176
|
|
|
@@ -37,6 +37,7 @@ const pagination = ref<PaginationState>({ page: 1, pageSize: 5, total: data.leng
|
|
|
37
37
|
<template #default="{ state }">
|
|
38
38
|
<div style="padding: 2rem; max-width: 900px; margin: 0 auto;">
|
|
39
39
|
<DataFrame
|
|
40
|
+
:error="state.error || null"
|
|
40
41
|
:data="data"
|
|
41
42
|
:columns="columns"
|
|
42
43
|
row-key="id"
|
|
@@ -55,6 +56,8 @@ const pagination = ref<PaginationState>({ page: 1, pageSize: 5, total: data.leng
|
|
|
55
56
|
</template>
|
|
56
57
|
|
|
57
58
|
<template #controls="{ state }">
|
|
59
|
+
|
|
60
|
+
<HstText v-model="state.error" title="Error Message" />
|
|
58
61
|
<HstSelect
|
|
59
62
|
v-model="state.size"
|
|
60
63
|
title="Size"
|
|
@@ -144,5 +147,16 @@ const pagination = ref<PaginationState>({ page: 1, pageSize: 5, total: data.leng
|
|
|
144
147
|
/>
|
|
145
148
|
</div>
|
|
146
149
|
</Variant>
|
|
150
|
+
|
|
151
|
+
<Variant title="Error">
|
|
152
|
+
<div style="padding: 2rem; max-width: 900px; margin: 0 auto;">
|
|
153
|
+
<DataFrame
|
|
154
|
+
:data="data"
|
|
155
|
+
:columns="columns"
|
|
156
|
+
row-key="id"
|
|
157
|
+
error="Could not load the result table."
|
|
158
|
+
/>
|
|
159
|
+
</div>
|
|
160
|
+
</Variant>
|
|
147
161
|
</Story>
|
|
148
162
|
</template>
|
|
@@ -5,6 +5,14 @@ import type { DataFrameColumn, SortState, PaginationState } from '../types'
|
|
|
5
5
|
import { useSortedItems } from '../composables/useSortedItems'
|
|
6
6
|
import { useTextSearch } from '../composables/useTextSearch'
|
|
7
7
|
import { useListSelection } from '../composables/useListSelection'
|
|
8
|
+
import DataStateInternal from './internal/DataStateInternal.vue'
|
|
9
|
+
import LoadingSpinner from './LoadingSpinner.vue'
|
|
10
|
+
import { tableDensityToSize, tryUseSettingsStore } from '../stores/settings'
|
|
11
|
+
|
|
12
|
+
/** Inbox glyph kept from the pre-1.2 hand-rolled empty state. */
|
|
13
|
+
const EMPTY_ICON_PATH
|
|
14
|
+
= 'M22 12L16 12L14 15L10 15L8 12L2 12'
|
|
15
|
+
+ 'M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z'
|
|
8
16
|
|
|
9
17
|
/**
|
|
10
18
|
* DataFrame - Data table with sorting, searching, pagination, and row selection.
|
|
@@ -34,7 +42,11 @@ interface Props {
|
|
|
34
42
|
striped?: boolean
|
|
35
43
|
/** Show table borders */
|
|
36
44
|
bordered?: boolean
|
|
37
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Table size. Left unset, it follows the platform's `tableDensity` setting
|
|
47
|
+
* (compact → `sm`, normal → `md`, comfortable → `lg`) and falls back to
|
|
48
|
+
* `md` when no settings store is installed.
|
|
49
|
+
*/
|
|
38
50
|
size?: 'sm' | 'md' | 'lg'
|
|
39
51
|
/** Make header sticky on scroll */
|
|
40
52
|
stickyHeader?: boolean
|
|
@@ -42,6 +54,11 @@ interface Props {
|
|
|
42
54
|
maxHeight?: string | number
|
|
43
55
|
/** Show loading overlay */
|
|
44
56
|
loading?: boolean
|
|
57
|
+
/**
|
|
58
|
+
* Error message. When set, the table body is replaced by an error state
|
|
59
|
+
* instead of the empty state. `null`/`undefined` renders normally.
|
|
60
|
+
*/
|
|
61
|
+
error?: string | null
|
|
45
62
|
/** Empty state message */
|
|
46
63
|
emptyText?: string
|
|
47
64
|
/** Enable column sorting */
|
|
@@ -75,9 +92,9 @@ interface Props {
|
|
|
75
92
|
const props = withDefaults(defineProps<Props>(), {
|
|
76
93
|
striped: true,
|
|
77
94
|
bordered: true,
|
|
78
|
-
size: 'md',
|
|
79
95
|
stickyHeader: false,
|
|
80
96
|
loading: false,
|
|
97
|
+
error: null,
|
|
81
98
|
emptyText: 'No data',
|
|
82
99
|
sortable: false,
|
|
83
100
|
pagination: false,
|
|
@@ -108,6 +125,13 @@ const emit = defineEmits<{
|
|
|
108
125
|
'delete-row': [row: Record<string, unknown>, index: number]
|
|
109
126
|
}>()
|
|
110
127
|
|
|
128
|
+
const settings = tryUseSettingsStore()
|
|
129
|
+
|
|
130
|
+
/** Explicit `size` wins; otherwise the user's table density, else `md`. */
|
|
131
|
+
const size = computed<'sm' | 'md' | 'lg'>(() =>
|
|
132
|
+
props.size ?? (settings ? tableDensityToSize(settings.tableDensity) : 'md'),
|
|
133
|
+
)
|
|
134
|
+
|
|
111
135
|
const searchQuery = ref('')
|
|
112
136
|
const internalSort = ref<SortState | null>(null)
|
|
113
137
|
|
|
@@ -219,6 +243,21 @@ function isColumnSortable(col: DataFrameColumn): boolean {
|
|
|
219
243
|
return col.sortable === true || (props.sortable && col.sortable !== false)
|
|
220
244
|
}
|
|
221
245
|
|
|
246
|
+
/** `aria-sort` for the header cell, omitted on columns that cannot be sorted. */
|
|
247
|
+
function columnAriaSort(col: DataFrameColumn): 'ascending' | 'descending' | 'none' | undefined {
|
|
248
|
+
if (!isColumnSortable(col)) return undefined
|
|
249
|
+
if (activeSort.value?.key !== col.key || !activeSort.value.direction) return 'none'
|
|
250
|
+
return activeSort.value.direction === 'asc' ? 'ascending' : 'descending'
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Native buttons activate on Enter/Space, but the default is prevented here so
|
|
254
|
+
// the header sorts exactly once per key press in every engine.
|
|
255
|
+
function handleSortKeydown(event: KeyboardEvent, col: DataFrameColumn) {
|
|
256
|
+
if (event.key !== 'Enter' && event.key !== ' ') return
|
|
257
|
+
event.preventDefault()
|
|
258
|
+
handleSort(col)
|
|
259
|
+
}
|
|
260
|
+
|
|
222
261
|
// Selection
|
|
223
262
|
const pageRowKeys = computed(() =>
|
|
224
263
|
paginatedData.value.map((row, i) => getRowKey(row, i))
|
|
@@ -264,6 +303,35 @@ function columnStyle(col: DataFrameColumn) {
|
|
|
264
303
|
}
|
|
265
304
|
}
|
|
266
305
|
|
|
306
|
+
const RESIZE_KEY_STEP = 16
|
|
307
|
+
|
|
308
|
+
function columnMinWidth(col: DataFrameColumn): number {
|
|
309
|
+
return Math.max(MIN_COL_WIDTH, typeof col.minWidth === 'number' ? col.minWidth : 0)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/** Current px width of a column when one is known (resized, or a numeric `width`). */
|
|
313
|
+
function columnWidthValue(col: DataFrameColumn): number | undefined {
|
|
314
|
+
const width = activeWidths.value[col.key] ?? col.width
|
|
315
|
+
return typeof width === 'number' ? width : undefined
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function applyColumnWidth(key: string, width: number) {
|
|
319
|
+
const widths = { ...activeWidths.value, [key]: width }
|
|
320
|
+
if (props.columnWidths === undefined) internalWidths.value = widths
|
|
321
|
+
emit('update:columnWidths', widths)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** Left/Right resize the column by a fixed step; the handle is a `role="slider"`. */
|
|
325
|
+
function handleResizeKeydown(event: KeyboardEvent, col: DataFrameColumn) {
|
|
326
|
+
if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return
|
|
327
|
+
event.preventDefault()
|
|
328
|
+
const th = (event.target as HTMLElement).closest('th')
|
|
329
|
+
const base =
|
|
330
|
+
columnWidthValue(col) ?? (th instanceof HTMLElement ? th.offsetWidth : MIN_COL_WIDTH)
|
|
331
|
+
const delta = event.key === 'ArrowRight' ? RESIZE_KEY_STEP : -RESIZE_KEY_STEP
|
|
332
|
+
applyColumnWidth(col.key, Math.max(columnMinWidth(col), base + delta))
|
|
333
|
+
}
|
|
334
|
+
|
|
267
335
|
let resizeState: { key: string; startX: number; startWidth: number; min: number } | null = null
|
|
268
336
|
|
|
269
337
|
function startResize(col: DataFrameColumn, event: MouseEvent) {
|
|
@@ -272,8 +340,7 @@ function startResize(col: DataFrameColumn, event: MouseEvent) {
|
|
|
272
340
|
const th = (event.target as HTMLElement).closest('th')
|
|
273
341
|
const startWidth =
|
|
274
342
|
th instanceof HTMLElement ? th.offsetWidth : (typeof col.width === 'number' ? col.width : MIN_COL_WIDTH)
|
|
275
|
-
|
|
276
|
-
resizeState = { key: col.key, startX: event.clientX, startWidth, min }
|
|
343
|
+
resizeState = { key: col.key, startX: event.clientX, startWidth, min: columnMinWidth(col) }
|
|
277
344
|
window.addEventListener('mousemove', onResizeMove)
|
|
278
345
|
window.addEventListener('mouseup', stopResize)
|
|
279
346
|
}
|
|
@@ -281,9 +348,7 @@ function startResize(col: DataFrameColumn, event: MouseEvent) {
|
|
|
281
348
|
function onResizeMove(event: MouseEvent) {
|
|
282
349
|
if (!resizeState) return
|
|
283
350
|
const next = Math.max(resizeState.min, resizeState.startWidth + (event.clientX - resizeState.startX))
|
|
284
|
-
|
|
285
|
-
if (props.columnWidths === undefined) internalWidths.value = widths
|
|
286
|
-
emit('update:columnWidths', widths)
|
|
351
|
+
applyColumnWidth(resizeState.key, next)
|
|
287
352
|
}
|
|
288
353
|
|
|
289
354
|
function stopResize() {
|
|
@@ -355,8 +420,15 @@ const wrapperStyle = computed(() => {
|
|
|
355
420
|
},
|
|
356
421
|
]"
|
|
357
422
|
:style="columnStyle(col)"
|
|
358
|
-
|
|
423
|
+
:aria-sort="columnAriaSort(col)"
|
|
359
424
|
>
|
|
425
|
+
<component
|
|
426
|
+
:is="isColumnSortable(col) ? 'button' : 'div'"
|
|
427
|
+
:type="isColumnSortable(col) ? 'button' : undefined"
|
|
428
|
+
class="mint-dataframe__th-button"
|
|
429
|
+
@click="isColumnSortable(col) ? handleSort(col) : undefined"
|
|
430
|
+
@keydown="isColumnSortable(col) ? handleSortKeydown($event, col) : undefined"
|
|
431
|
+
>
|
|
360
432
|
<slot :name="`header-${col.key}`" :column="col">
|
|
361
433
|
<div class="mint-dataframe__th-content">
|
|
362
434
|
<span>{{ col.label }}</span>
|
|
@@ -380,13 +452,18 @@ const wrapperStyle = computed(() => {
|
|
|
380
452
|
</svg>
|
|
381
453
|
</div>
|
|
382
454
|
</slot>
|
|
455
|
+
</component>
|
|
383
456
|
<span
|
|
384
457
|
v-if="resizable"
|
|
385
458
|
class="mint-dataframe__resize-handle"
|
|
386
|
-
role="
|
|
459
|
+
role="slider"
|
|
460
|
+
tabindex="0"
|
|
387
461
|
aria-orientation="vertical"
|
|
388
|
-
aria-label="Resize column"
|
|
462
|
+
:aria-label="`Resize ${col.label} column`"
|
|
463
|
+
:aria-valuemin="columnMinWidth(col)"
|
|
464
|
+
:aria-valuenow="columnWidthValue(col)"
|
|
389
465
|
@mousedown="startResize(col, $event)"
|
|
466
|
+
@keydown="handleResizeKeydown($event, col)"
|
|
390
467
|
@click.stop
|
|
391
468
|
/>
|
|
392
469
|
</th>
|
|
@@ -459,23 +536,24 @@ const wrapperStyle = computed(() => {
|
|
|
459
536
|
</tbody>
|
|
460
537
|
</table>
|
|
461
538
|
|
|
539
|
+
<!-- Error state -->
|
|
540
|
+
<div v-if="error" class="mint-dataframe__state">
|
|
541
|
+
<slot name="error" :error="error">
|
|
542
|
+
<DataStateInternal state="error" :title="error" />
|
|
543
|
+
</slot>
|
|
544
|
+
</div>
|
|
545
|
+
|
|
462
546
|
<!-- Empty state -->
|
|
463
|
-
<div v-if="paginatedData.length === 0 && !loading" class="mint-
|
|
547
|
+
<div v-else-if="paginatedData.length === 0 && !loading" class="mint-dataframe__state">
|
|
464
548
|
<slot name="empty">
|
|
465
|
-
<
|
|
466
|
-
<polyline points="22 12 16 12 14 15 10 15 8 12 2 12" /><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" />
|
|
467
|
-
</svg>
|
|
468
|
-
<p class="mint-dataframe__empty-text">{{ emptyText }}</p>
|
|
549
|
+
<DataStateInternal state="empty" :title="emptyText" :icon-path="EMPTY_ICON_PATH" />
|
|
469
550
|
</slot>
|
|
470
551
|
</div>
|
|
471
552
|
|
|
472
553
|
<!-- Loading overlay -->
|
|
473
554
|
<div v-if="loading" class="mint-dataframe__loading">
|
|
474
555
|
<slot name="loading">
|
|
475
|
-
<
|
|
476
|
-
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="3" opacity="0.25" />
|
|
477
|
-
<path d="M12 2a10 10 0 0 1 10 10" stroke="currentColor" stroke-width="3" stroke-linecap="round" />
|
|
478
|
-
</svg>
|
|
556
|
+
<LoadingSpinner size="lg" />
|
|
479
557
|
</slot>
|
|
480
558
|
</div>
|
|
481
559
|
</div>
|
|
@@ -514,7 +592,3 @@ const wrapperStyle = computed(() => {
|
|
|
514
592
|
</div>
|
|
515
593
|
</div>
|
|
516
594
|
</template>
|
|
517
|
-
|
|
518
|
-
<style>
|
|
519
|
-
@import '../styles/components/dataframe.css';
|
|
520
|
-
</style>
|