@morscherlab/mint-sdk 1.1.25 → 1.2.0-beta.10
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 +44 -12
- package/dist/{ExperimentPopover-tLwJ7XF4.js → ExperimentPopover-oL0fg_A0.js} +6 -4
- package/dist/ExperimentPopover-oL0fg_A0.js.map +1 -0
- package/dist/{ExperimentSelectorModal-B6P2msT4.js → ExperimentSelectorModal-BeEOomw_.js} +5 -5
- package/dist/ExperimentSelectorModal-BeEOomw_.js.map +1 -0
- package/dist/{SettingsModal-BW3Ar-uy.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/useEventStream.test.d.ts +1 -0
- package/dist/__tests__/composables/useListReorder.test.d.ts +1 -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/BatchProgressList.vue.d.ts +17 -0
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +1 -1
- 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/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/SampleSelector.drag.d.ts +13 -0
- package/dist/components/SampleSelector.tree.d.ts +2 -0
- package/dist/components/SampleSelector.vue.d.ts +34 -1
- package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
- package/dist/components/SecretInput.vue.d.ts +28 -0
- 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-DQt0tcpY.js → components-CgAUzF8F.js} +2491 -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 +8 -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 +52 -0
- package/dist/composables/useFocusTrap.d.ts +21 -0
- package/dist/composables/useJobsStatusTray.d.ts +1 -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 +4 -17
- package/dist/composables/usePluginConfig.d.ts +3 -1
- 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-CkXDe7nm.js → composables-B_pia3hO.js} +105 -254
- package/dist/composables-B_pia3hO.js.map +1 -0
- package/dist/{useApi-CDBq6z23.js → errors-_W0-LbA6.js} +102 -3
- package/dist/errors-_W0-LbA6.js.map +1 -0
- package/dist/{experiment-Y9Iz7KYi.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/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-CovvRZ-9.js → templates-Qq113pyZ.js} +303 -106
- package/dist/templates-Qq113pyZ.js.map +1 -0
- package/dist/types/form-builder.d.ts +1 -1
- package/dist/{useControlSchema-BhoJzWzx.js → useControlSchema-aMZlb4Sc.js} +684 -1216
- 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-D0pjj9WH.js → useExperimentSelector-I8HC8hUu.js} +4 -4
- package/dist/{useExperimentSelector-D0pjj9WH.js.map → useExperimentSelector-I8HC8hUu.js.map} +1 -1
- package/dist/{useFormBuilder-DiEcDis2.js → useFormBuilder-TCxNnqeb.js} +2 -2
- package/dist/{useFormBuilder-DiEcDis2.js.map → useFormBuilder-TCxNnqeb.js.map} +1 -1
- package/dist/{useProtocolTemplates-DHwSveE6.js → useProtocolTemplates-BmX_iVBR.js} +660 -197
- 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/GeneratedPluginView.test.ts +0 -5
- package/src/__tests__/components/GroupAssigner.test.ts +53 -0
- package/src/__tests__/components/JobsStatusTray.test.ts +20 -18
- 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 +25 -0
- package/src/__tests__/composables/useDropdownState.test.ts +58 -1
- package/src/__tests__/composables/useEventStream.test.ts +140 -0
- package/src/__tests__/composables/useGeneratedAnalysis.test.ts +103 -0
- package/src/__tests__/composables/useJobsStatusTray.test.ts +25 -161
- package/src/__tests__/composables/useListReorder.test.ts +145 -0
- package/src/__tests__/composables/usePluginClient.test.ts +148 -13
- package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +55 -2
- 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.story.vue +6 -10
- package/src/components/JobsStatusTray.vue +0 -4
- 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 +41 -5
- package/src/composables/pluginWorkspaceModel.ts +182 -0
- package/src/composables/useAsync.ts +5 -1
- 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 +326 -0
- package/src/composables/useFileImport.ts +2 -7
- package/src/composables/useFocusTrap.ts +91 -0
- package/src/composables/useGeneratedAnalysis.ts +46 -103
- package/src/composables/useJobsStatusTray.ts +1 -1
- 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 +91 -252
- package/src/composables/usePluginConfig.ts +3 -1
- 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/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/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-B6P2msT4.js.map +0 -1
- package/dist/SettingsModal-BW3Ar-uy.js.map +0 -1
- package/dist/components-DQt0tcpY.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-CkXDe7nm.js.map +0 -1
- package/dist/experiment-Y9Iz7KYi.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-CovvRZ-9.js.map +0 -1
- package/dist/useApi-CDBq6z23.js.map +0 -1
- package/dist/useControlSchema-BhoJzWzx.js.map +0 -1
- package/dist/useDropdownState-DSb3BC3N.js.map +0 -1
- package/dist/useProtocolTemplates-DHwSveE6.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
|
@@ -1,10 +1,114 @@
|
|
|
1
|
-
import { d as resolveExperimentCode } from "./experiment-utils-
|
|
2
|
-
import {
|
|
3
|
-
import { A as useConcentrationUnits, H as parseExperimentId, J as isActiveJobStatus, Q as normalizeJobState, U as resolveCurrentExperimentId, V as getInjectedPlatformContext, u as useControlWorkspace } from "./useControlSchema-
|
|
4
|
-
import {
|
|
5
|
-
import { t as useExperimentStore } from "./experiment-
|
|
6
|
-
import { B as toBioTemplateComponentProps, F as getBioTemplateComponentProps$1, H as toBioTemplateComponentPropsById, Jt as getBioTemplatePresetInfo, L as toBioTemplateComponentBindings, P as getBioTemplateComponentBindings, Qt as getBioTemplatePackInfo, R as toBioTemplateComponentBindingsById, U as toBioTemplateComponentSnippets, V as toBioTemplateComponentPropsByComponent$1, W as toBioTemplateComponentUsage, d as createBioTemplatePresetCollectionFromControls, dn as extractTemplateCollection, i as createBioTemplateControlToolkit, p as createBioTemplatePackCollection, sn as createTemplateCollection, u as createBioTemplatePresetCollection, un as ensureTemplateFromCollection, z as toBioTemplateComponentImports } from "./templates-
|
|
7
|
-
import { computed, effectScope, getCurrentScope, inject, onMounted, onScopeDispose, onUnmounted, provide, reactive, readonly, ref, shallowRef, toRaw, toValue, unref, watch } from "vue";
|
|
1
|
+
import { d as resolveExperimentCode } from "./experiment-utils-DV3DrvE_.js";
|
|
2
|
+
import { n as useRequestSyncState } from "./Skeleton-DxtwJ5gt.js";
|
|
3
|
+
import { A as useConcentrationUnits, H as parseExperimentId, J as isActiveJobStatus, Q as normalizeJobState, T as getDefaultControlView, U as resolveCurrentExperimentId, V as getInjectedPlatformContext, f as resolveControlModel, g as mergeControlWorkspaceOptions, h as controlValuesToComponentProps, m as controlValuesToComponentBindingsById, p as controlValuesToComponentBindings, r as getControlDefaults, rt as isRecord, u as useControlWorkspace, w as controlsToViewItems } from "./useControlSchema-aMZlb4Sc.js";
|
|
4
|
+
import { d as useSettingsStore, i as useApi, t as readErrorMessage } from "./errors-_W0-LbA6.js";
|
|
5
|
+
import { t as useExperimentStore } from "./experiment-Cwl9AYxw.js";
|
|
6
|
+
import { B as toBioTemplateComponentProps, F as getBioTemplateComponentProps$1, H as toBioTemplateComponentPropsById, Jt as getBioTemplatePresetInfo, L as toBioTemplateComponentBindings, P as getBioTemplateComponentBindings, Qt as getBioTemplatePackInfo, R as toBioTemplateComponentBindingsById, U as toBioTemplateComponentSnippets, V as toBioTemplateComponentPropsByComponent$1, W as toBioTemplateComponentUsage, bn as rowLabel, d as createBioTemplatePresetCollectionFromControls, dn as extractTemplateCollection, i as createBioTemplateControlToolkit, p as createBioTemplatePackCollection, pn as PLATE_CONFIGS, sn as createTemplateCollection, u as createBioTemplatePresetCollection, un as ensureTemplateFromCollection, wn as deriveShade, xn as SAMPLE_COLOR_SCALE, z as toBioTemplateComponentImports } from "./templates-Qq113pyZ.js";
|
|
7
|
+
import { computed, effectScope, getCurrentScope, inject, nextTick, onMounted, onScopeDispose, onUnmounted, provide, reactive, readonly, ref, shallowRef, toRaw, toValue, unref, watch } from "vue";
|
|
8
|
+
//#region src/composables/useRovingFocus.ts
|
|
9
|
+
/**
|
|
10
|
+
* WAI-ARIA roving-tabindex navigation with automatic activation (the tabs pattern):
|
|
11
|
+
* Left/Right (or Up/Down when `orientation` is `'vertical'`) move to the adjacent item
|
|
12
|
+
* and activate it immediately, wrapping past the ends; Home/End jump to the first/last
|
|
13
|
+
* item. Only the active item should carry `tabindex="0"`; give every other item
|
|
14
|
+
* `tabindex="-1"`. Used by BaseTabs.
|
|
15
|
+
*/
|
|
16
|
+
function useRovingFocus(options) {
|
|
17
|
+
const orientation = options.orientation ?? "horizontal";
|
|
18
|
+
const prevKey = orientation === "vertical" ? "ArrowUp" : "ArrowLeft";
|
|
19
|
+
const nextKey = orientation === "vertical" ? "ArrowDown" : "ArrowRight";
|
|
20
|
+
function moveTo(id) {
|
|
21
|
+
if (id === void 0) return;
|
|
22
|
+
options.activate(id);
|
|
23
|
+
nextTick(() => options.getElement(id)?.focus());
|
|
24
|
+
}
|
|
25
|
+
function handleKeydown(event) {
|
|
26
|
+
const ids = options.ids();
|
|
27
|
+
if (ids.length === 0) return;
|
|
28
|
+
const currentIndex = ids.indexOf(options.activeId() ?? "");
|
|
29
|
+
if (event.key === "Home") {
|
|
30
|
+
event.preventDefault();
|
|
31
|
+
moveTo(ids[0]);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (event.key === "End") {
|
|
35
|
+
event.preventDefault();
|
|
36
|
+
moveTo(ids[ids.length - 1]);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (event.key === prevKey) {
|
|
40
|
+
event.preventDefault();
|
|
41
|
+
moveTo(ids[currentIndex <= 0 ? ids.length - 1 : currentIndex - 1]);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (event.key === nextKey) {
|
|
45
|
+
event.preventDefault();
|
|
46
|
+
moveTo(ids[currentIndex === -1 || currentIndex >= ids.length - 1 ? 0 : currentIndex + 1]);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { handleKeydown };
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/composables/useMenuKeyboard.ts
|
|
53
|
+
/**
|
|
54
|
+
* Shared keyboard contract for menu- and listbox-style disclosure panels (the
|
|
55
|
+
* WAI-ARIA menu button pattern). Used by ActionMenu, AppAvatarMenu and DropdownButton,
|
|
56
|
+
* each pairing it with `useDropdownState` for the disclosure state itself.
|
|
57
|
+
*/
|
|
58
|
+
function useMenuKeyboard(options) {
|
|
59
|
+
function focusItem(position) {
|
|
60
|
+
nextTick(() => {
|
|
61
|
+
const items = options.items();
|
|
62
|
+
(position === "first" ? items[0] : items[items.length - 1])?.focus();
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function handleTriggerKeydown(event) {
|
|
66
|
+
if (options.isOpen()) return;
|
|
67
|
+
if (event.key === "ArrowDown" || event.key === "Enter" || event.key === " ") {
|
|
68
|
+
event.preventDefault();
|
|
69
|
+
options.open();
|
|
70
|
+
focusItem("first");
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (event.key === "ArrowUp") {
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
options.open();
|
|
76
|
+
focusItem("last");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function handlePanelKeydown(event) {
|
|
80
|
+
const items = options.items();
|
|
81
|
+
const currentIndex = items.indexOf(document.activeElement);
|
|
82
|
+
if (event.key === "Escape") {
|
|
83
|
+
event.preventDefault();
|
|
84
|
+
options.close(true);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (event.key === "Tab") {
|
|
88
|
+
options.close();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (event.key === "Home") {
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
items[0]?.focus();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (event.key === "End") {
|
|
97
|
+
event.preventDefault();
|
|
98
|
+
items[items.length - 1]?.focus();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (event.key !== "ArrowDown" && event.key !== "ArrowUp") return;
|
|
102
|
+
event.preventDefault();
|
|
103
|
+
const direction = event.key === "ArrowDown" ? 1 : -1;
|
|
104
|
+
items[(Math.max(currentIndex, 0) + direction + items.length) % items.length]?.focus();
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
handleTriggerKeydown,
|
|
108
|
+
handlePanelKeydown
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
8
112
|
//#region src/composables/useSortedItems.ts
|
|
9
113
|
/** Shared sorting for SDK tables and lists with stable empty-value handling. */
|
|
10
114
|
function useSortedItems(options) {
|
|
@@ -528,6 +632,310 @@ function useMobileSupportGate(options = {}) {
|
|
|
528
632
|
};
|
|
529
633
|
}
|
|
530
634
|
//#endregion
|
|
635
|
+
//#region src/components/PluginWorkspaceView.controls.ts
|
|
636
|
+
function usePluginWorkspaceControls(options) {
|
|
637
|
+
const resolvedModel = computed(() => resolveControlModel(options.model()));
|
|
638
|
+
const resolvedControls = computed(() => options.controls() ?? resolvedModel.value?.controls);
|
|
639
|
+
const resolvedControlOptions = computed(() => mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, options.controlOptions()));
|
|
640
|
+
const externalControlValues = computed(() => options.modelValue() ?? options.values());
|
|
641
|
+
const internalControlValues = reactive({});
|
|
642
|
+
let syncingControlValues = false;
|
|
643
|
+
const generatedControlDefaults = computed(() => {
|
|
644
|
+
if (!resolvedControls.value) return {};
|
|
645
|
+
return {
|
|
646
|
+
...getControlDefaults(resolvedControls.value),
|
|
647
|
+
...resolvedControlOptions.value.initialValues ?? {}
|
|
648
|
+
};
|
|
649
|
+
});
|
|
650
|
+
function replaceControlValues(values) {
|
|
651
|
+
for (const key of Object.keys(internalControlValues)) if (!(key in values)) delete internalControlValues[key];
|
|
652
|
+
Object.assign(internalControlValues, values);
|
|
653
|
+
}
|
|
654
|
+
function emitControlValues() {
|
|
655
|
+
options.emitValues({ ...internalControlValues });
|
|
656
|
+
}
|
|
657
|
+
function syncResolvedControlValues() {
|
|
658
|
+
syncingControlValues = true;
|
|
659
|
+
replaceControlValues({
|
|
660
|
+
...generatedControlDefaults.value,
|
|
661
|
+
...externalControlValues.value === void 0 ? internalControlValues : externalControlValues.value
|
|
662
|
+
});
|
|
663
|
+
syncingControlValues = false;
|
|
664
|
+
}
|
|
665
|
+
function handleControlValuesUpdate(values) {
|
|
666
|
+
syncingControlValues = true;
|
|
667
|
+
replaceControlValues({
|
|
668
|
+
...generatedControlDefaults.value,
|
|
669
|
+
...values
|
|
670
|
+
});
|
|
671
|
+
syncingControlValues = false;
|
|
672
|
+
emitControlValues();
|
|
673
|
+
}
|
|
674
|
+
const resolvedComponentBindings = computed(() => controlValuesToComponentBindings(internalControlValues, options.componentBindings() ?? resolvedModel.value?.componentBindings));
|
|
675
|
+
const resolvedComponentBindingsById = computed(() => controlValuesToComponentBindingsById(internalControlValues, options.componentBindings() ?? resolvedModel.value?.componentBindings));
|
|
676
|
+
const resolvedComponentProps = computed(() => {
|
|
677
|
+
const mapping = options.componentProps() ?? resolvedModel.value?.componentProps;
|
|
678
|
+
return mapping === void 0 ? {} : controlValuesToComponentProps(internalControlValues, mapping);
|
|
679
|
+
});
|
|
680
|
+
const resolvedComponentPropsById = computed(() => {
|
|
681
|
+
const mappings = options.componentPropsById() ?? resolvedModel.value?.componentPropsById;
|
|
682
|
+
if (mappings === void 0) return {};
|
|
683
|
+
return Object.fromEntries(Object.entries(mappings).map(([id, mapping]) => [id, controlValuesToComponentProps(internalControlValues, mapping)]));
|
|
684
|
+
});
|
|
685
|
+
const generatedPillNav = computed(() => {
|
|
686
|
+
if (!resolvedControls.value) return [];
|
|
687
|
+
return controlsToViewItems(resolvedControls.value, resolvedControlOptions.value);
|
|
688
|
+
});
|
|
689
|
+
const generatedDefaultView = computed(() => {
|
|
690
|
+
if (!resolvedControls.value) return "";
|
|
691
|
+
return getDefaultControlView(resolvedControls.value, resolvedControlOptions.value);
|
|
692
|
+
});
|
|
693
|
+
syncResolvedControlValues();
|
|
694
|
+
watch([generatedControlDefaults, externalControlValues], syncResolvedControlValues, { deep: true });
|
|
695
|
+
watch(internalControlValues, () => {
|
|
696
|
+
if (syncingControlValues) return;
|
|
697
|
+
emitControlValues();
|
|
698
|
+
}, {
|
|
699
|
+
deep: true,
|
|
700
|
+
flush: "sync"
|
|
701
|
+
});
|
|
702
|
+
return {
|
|
703
|
+
resolvedModel,
|
|
704
|
+
resolvedControls,
|
|
705
|
+
resolvedControlOptions,
|
|
706
|
+
generatedPillNav,
|
|
707
|
+
generatedDefaultView,
|
|
708
|
+
internalControlValues,
|
|
709
|
+
resolvedComponentBindings,
|
|
710
|
+
resolvedComponentBindingsById,
|
|
711
|
+
resolvedComponentProps,
|
|
712
|
+
resolvedComponentPropsById,
|
|
713
|
+
handleControlValuesUpdate
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
//#endregion
|
|
717
|
+
//#region src/components/PluginWorkspaceView.navigation.ts
|
|
718
|
+
function usePluginWorkspaceNavigation(options) {
|
|
719
|
+
const internalActiveView = ref(options.defaultActiveView());
|
|
720
|
+
const resolvedPillNav = computed(() => {
|
|
721
|
+
if (options.pillNav() !== void 0) return options.pillNav();
|
|
722
|
+
return options.generatedPillNav.value.length > 0 ? [...options.generatedPillNav.value] : void 0;
|
|
723
|
+
});
|
|
724
|
+
const firstConfiguredViewId = computed(() => options.defaultActiveView() ?? firstItemId(options.pillNav()) ?? options.generatedDefaultView.value ?? firstItemId(options.pageSelector()) ?? options.panelIds()[0] ?? "");
|
|
725
|
+
const resolvedActiveView = computed({
|
|
726
|
+
get: () => options.activeView() ?? options.currentPillId() ?? options.currentPageSelectorId() ?? internalActiveView.value ?? firstConfiguredViewId.value,
|
|
727
|
+
set: (value) => {
|
|
728
|
+
internalActiveView.value = value;
|
|
729
|
+
options.emitActiveView(value);
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
const resolvedCurrentPillId = computed(() => options.currentPillId() ?? resolvedActiveView.value);
|
|
733
|
+
const resolvedCurrentPageSelectorId = computed(() => options.currentPageSelectorId() ?? resolvedActiveView.value);
|
|
734
|
+
function setActiveView(viewId) {
|
|
735
|
+
resolvedActiveView.value = viewId;
|
|
736
|
+
}
|
|
737
|
+
function handlePageSelectorSelect(page) {
|
|
738
|
+
setActiveView(page.id);
|
|
739
|
+
options.emitPageSelectorSelect(page);
|
|
740
|
+
}
|
|
741
|
+
function handlePillSelect(item) {
|
|
742
|
+
setActiveView(item.id);
|
|
743
|
+
options.emitPillSelect(item);
|
|
744
|
+
}
|
|
745
|
+
return {
|
|
746
|
+
resolvedPillNav,
|
|
747
|
+
firstConfiguredViewId,
|
|
748
|
+
resolvedActiveView,
|
|
749
|
+
resolvedCurrentPillId,
|
|
750
|
+
resolvedCurrentPageSelectorId,
|
|
751
|
+
setActiveView,
|
|
752
|
+
handlePageSelectorSelect,
|
|
753
|
+
handlePillSelect
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
function firstItemId(items) {
|
|
757
|
+
const item = items?.[0];
|
|
758
|
+
if (item === void 0) return void 0;
|
|
759
|
+
return typeof item === "string" ? item : item.id;
|
|
760
|
+
}
|
|
761
|
+
//#endregion
|
|
762
|
+
//#region src/components/PluginWorkspaceView.shell.ts
|
|
763
|
+
var topBarForwardedSlots = new Set([
|
|
764
|
+
"icon",
|
|
765
|
+
"logo",
|
|
766
|
+
"page-selector-icon",
|
|
767
|
+
"page-selector-item-icon",
|
|
768
|
+
"nav",
|
|
769
|
+
"center",
|
|
770
|
+
"actions",
|
|
771
|
+
"account-menu-items",
|
|
772
|
+
"account-menu-item-icon",
|
|
773
|
+
"settings-appearance"
|
|
774
|
+
]);
|
|
775
|
+
var sidebarForwardedSlots = new Set([
|
|
776
|
+
"header",
|
|
777
|
+
"collapsed",
|
|
778
|
+
"collapsed-footer",
|
|
779
|
+
"footer"
|
|
780
|
+
]);
|
|
781
|
+
function getPluginWorkspaceTopBarSlotNames(slots) {
|
|
782
|
+
return Object.keys(slots).filter((name) => topBarForwardedSlots.has(name) || name.startsWith("settings-tab-"));
|
|
783
|
+
}
|
|
784
|
+
function getPluginWorkspaceSidebarSlotNames(slots) {
|
|
785
|
+
return Object.keys(slots).filter((name) => sidebarForwardedSlots.has(name) || name.startsWith("section-"));
|
|
786
|
+
}
|
|
787
|
+
function hasPluginWorkspaceSidebarSurface(options) {
|
|
788
|
+
if (!options.showSidebar) return false;
|
|
789
|
+
return Object.keys(options.panels).length > 0 || Object.keys(options.forms).length > 0 || options.model !== void 0 || options.controls !== void 0 || options.showSidebarWhenEmpty || options.sidebarContentId !== void 0 || options.sidebarTitle !== void 0 || options.sidebarSubtitle !== void 0 || options.sidebarBadge !== void 0 || options.hasSidebarSlot || options.sidebarSlotCount > 0;
|
|
790
|
+
}
|
|
791
|
+
//#endregion
|
|
792
|
+
//#region src/composables/usePluginWorkspace.ts
|
|
793
|
+
/**
|
|
794
|
+
* Maps PluginWorkspaceView's flat 72-prop surface into the three typed model objects
|
|
795
|
+
* (`shell`, `sidebar`, `controls`) rendered by its internal pieces
|
|
796
|
+
* (WorkspaceShellInternal, WorkspaceSidebarInternal, WorkspaceControlsInternal). Reuses the
|
|
797
|
+
* existing `usePluginWorkspaceControls` / `usePluginWorkspaceNavigation` composables and the
|
|
798
|
+
* PluginWorkspaceView.shell slot-detection helpers, so it changes only how that state is
|
|
799
|
+
* assembled and exposed, not the underlying behavior.
|
|
800
|
+
*
|
|
801
|
+
* @example Recommended
|
|
802
|
+
* ```ts
|
|
803
|
+
* const props = withDefaults(defineProps<PluginWorkspaceViewProps>(), { ... })
|
|
804
|
+
* const emit = defineEmits<PluginWorkspaceViewEmits>()
|
|
805
|
+
* const slots = useSlots()
|
|
806
|
+
* const { shell, sidebar, controls } = usePluginWorkspace({ props, slots, emit })
|
|
807
|
+
* ```
|
|
808
|
+
*/
|
|
809
|
+
function usePluginWorkspace(options) {
|
|
810
|
+
const { props, slots, emit } = options;
|
|
811
|
+
const controlsState = usePluginWorkspaceControls({
|
|
812
|
+
model: () => props.model,
|
|
813
|
+
controls: () => props.controls,
|
|
814
|
+
controlOptions: () => props.controlOptions ?? {},
|
|
815
|
+
modelValue: () => props.modelValue,
|
|
816
|
+
values: () => props.values,
|
|
817
|
+
componentBindings: () => props.componentBindings,
|
|
818
|
+
componentProps: () => props.componentProps,
|
|
819
|
+
componentPropsById: () => props.componentPropsById,
|
|
820
|
+
emitValues: (values) => {
|
|
821
|
+
emit("update:modelValue", values);
|
|
822
|
+
emit("update:values", values);
|
|
823
|
+
}
|
|
824
|
+
});
|
|
825
|
+
const navigationState = usePluginWorkspaceNavigation({
|
|
826
|
+
activeView: () => props.activeView,
|
|
827
|
+
defaultActiveView: () => props.defaultActiveView,
|
|
828
|
+
currentPillId: () => props.currentPillId,
|
|
829
|
+
currentPageSelectorId: () => props.currentPageSelectorId,
|
|
830
|
+
pillNav: () => props.pillNav,
|
|
831
|
+
pageSelector: () => props.pageSelector,
|
|
832
|
+
panelIds: () => Object.keys(props.panels ?? {}),
|
|
833
|
+
generatedPillNav: controlsState.generatedPillNav,
|
|
834
|
+
generatedDefaultView: controlsState.generatedDefaultView,
|
|
835
|
+
emitActiveView: (viewId) => emit("update:activeView", viewId),
|
|
836
|
+
emitPageSelectorSelect: (page) => emit("page-selector-select", page),
|
|
837
|
+
emitPillSelect: (item) => emit("pill-select", item)
|
|
838
|
+
});
|
|
839
|
+
const topBarSlotNames = computed(() => getPluginWorkspaceTopBarSlotNames(slots));
|
|
840
|
+
const sidebarSlotNames = computed(() => getPluginWorkspaceSidebarSlotNames(slots));
|
|
841
|
+
const hasSidebarSurface = computed(() => hasPluginWorkspaceSidebarSurface({
|
|
842
|
+
showSidebar: props.showSidebar ?? true,
|
|
843
|
+
panels: props.panels ?? {},
|
|
844
|
+
forms: props.forms ?? {},
|
|
845
|
+
model: props.model,
|
|
846
|
+
controls: props.controls,
|
|
847
|
+
showSidebarWhenEmpty: props.showSidebarWhenEmpty ?? false,
|
|
848
|
+
sidebarContentId: props.sidebarContentId,
|
|
849
|
+
sidebarTitle: props.sidebarTitle,
|
|
850
|
+
sidebarSubtitle: props.sidebarSubtitle,
|
|
851
|
+
sidebarBadge: props.sidebarBadge,
|
|
852
|
+
hasSidebarSlot: Boolean(slots.sidebar),
|
|
853
|
+
sidebarSlotCount: sidebarSlotNames.value.length
|
|
854
|
+
}));
|
|
855
|
+
const controls = computed(() => ({
|
|
856
|
+
activeView: navigationState.resolvedActiveView.value,
|
|
857
|
+
setActiveView: navigationState.setActiveView,
|
|
858
|
+
values: controlsState.internalControlValues,
|
|
859
|
+
componentBindings: controlsState.resolvedComponentBindings.value,
|
|
860
|
+
componentBindingsById: controlsState.resolvedComponentBindingsById.value,
|
|
861
|
+
componentProps: controlsState.resolvedComponentProps.value,
|
|
862
|
+
componentPropsById: controlsState.resolvedComponentPropsById.value
|
|
863
|
+
}));
|
|
864
|
+
return {
|
|
865
|
+
shell: computed(() => ({
|
|
866
|
+
sidebarPosition: props.sidebarPosition ?? "left",
|
|
867
|
+
sidebarWidth: props.sidebarWidth,
|
|
868
|
+
floating: props.floating ?? true,
|
|
869
|
+
responsiveSidebar: props.responsiveSidebar ?? true,
|
|
870
|
+
sidebarToggleLabel: props.sidebarToggleLabel ?? "Open workspace sidebar",
|
|
871
|
+
sidebarCloseLabel: props.sidebarCloseLabel ?? "Close workspace sidebar",
|
|
872
|
+
hasSidebarSurface: hasSidebarSurface.value,
|
|
873
|
+
title: props.title ?? "Workspace",
|
|
874
|
+
subtitle: props.subtitle,
|
|
875
|
+
topBarVariant: props.topBarVariant ?? "card",
|
|
876
|
+
homePath: props.homePath ?? "/",
|
|
877
|
+
showLogo: props.showLogo ?? true,
|
|
878
|
+
pageSelector: props.pageSelector,
|
|
879
|
+
currentPageSelectorId: navigationState.resolvedCurrentPageSelectorId.value,
|
|
880
|
+
pluginSwitcher: props.pluginSwitcher,
|
|
881
|
+
pillNav: navigationState.resolvedPillNav.value,
|
|
882
|
+
currentPillId: navigationState.resolvedCurrentPillId.value,
|
|
883
|
+
showThemeToggle: props.showThemeToggle ?? true,
|
|
884
|
+
showSettings: props.showSettings ?? true,
|
|
885
|
+
settingsConfig: props.settingsConfig,
|
|
886
|
+
showStandaloneLabel: props.showStandaloneLabel ?? false,
|
|
887
|
+
standaloneLabel: props.standaloneLabel ?? "Standalone",
|
|
888
|
+
accountMenu: props.accountMenu,
|
|
889
|
+
showNotifications: props.showNotifications ?? false,
|
|
890
|
+
hasNotificationDot: props.hasNotificationDot ?? false,
|
|
891
|
+
showAdmin: props.showAdmin ?? false,
|
|
892
|
+
adminPath: props.adminPath ?? "/admin",
|
|
893
|
+
userName: props.userName,
|
|
894
|
+
userInitial: props.userInitial,
|
|
895
|
+
userEmail: props.userEmail,
|
|
896
|
+
topBarSlotNames: topBarSlotNames.value,
|
|
897
|
+
controls: controls.value
|
|
898
|
+
})),
|
|
899
|
+
sidebar: computed(() => ({
|
|
900
|
+
title: props.sidebarTitle,
|
|
901
|
+
subtitle: props.sidebarSubtitle,
|
|
902
|
+
badge: props.sidebarBadge,
|
|
903
|
+
variant: props.sidebarVariant ?? "analysis",
|
|
904
|
+
panels: props.panels ?? {},
|
|
905
|
+
activeView: navigationState.resolvedActiveView.value,
|
|
906
|
+
floating: false,
|
|
907
|
+
dense: props.dense ?? true,
|
|
908
|
+
width: props.sidebarWidth,
|
|
909
|
+
side: props.sidebarPosition ?? "left",
|
|
910
|
+
forms: props.forms ?? {},
|
|
911
|
+
contentId: props.sidebarContentId,
|
|
912
|
+
showWhenEmpty: (props.showSidebarWhenEmpty ?? false) || props.sidebarContentId !== void 0,
|
|
913
|
+
model: props.model,
|
|
914
|
+
controlSchema: props.controls,
|
|
915
|
+
controlOptions: props.controlOptions ?? {},
|
|
916
|
+
values: controlsState.internalControlValues,
|
|
917
|
+
formEnhancements: props.formEnhancements,
|
|
918
|
+
showFormActions: props.showFormActions ?? false,
|
|
919
|
+
formLoading: props.formLoading ?? false,
|
|
920
|
+
formDisabled: props.formDisabled ?? false,
|
|
921
|
+
formReadonly: props.formReadonly ?? false,
|
|
922
|
+
formSize: props.formSize ?? "sm",
|
|
923
|
+
collapsible: props.sidebarCollapsible,
|
|
924
|
+
collapsed: props.sidebarCollapsed,
|
|
925
|
+
defaultCollapsed: props.defaultSidebarCollapsed ?? false,
|
|
926
|
+
collapsedWidth: props.sidebarCollapsedWidth ?? "3rem",
|
|
927
|
+
collapseButtonLabel: props.sidebarCollapseButtonLabel ?? "Collapse sidebar",
|
|
928
|
+
expandButtonLabel: props.sidebarExpandButtonLabel ?? "Expand sidebar",
|
|
929
|
+
slotNames: sidebarSlotNames.value
|
|
930
|
+
})),
|
|
931
|
+
controls,
|
|
932
|
+
hasSidebarSurface,
|
|
933
|
+
handleControlValuesUpdate: controlsState.handleControlValuesUpdate,
|
|
934
|
+
handlePageSelectorSelect: navigationState.handlePageSelectorSelect,
|
|
935
|
+
handlePillSelect: navigationState.handlePillSelect
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
//#endregion
|
|
531
939
|
//#region src/composables/useJobsStatusTray.ts
|
|
532
940
|
/**
|
|
533
941
|
* Combines independent job runtimes without copying their reactive state.
|
|
@@ -823,7 +1231,7 @@ function usePluginJobCenter(options = {}) {
|
|
|
823
1231
|
isPending: (job) => pendingJobIds.value.has(job.job_id)
|
|
824
1232
|
};
|
|
825
1233
|
}
|
|
826
|
-
/**
|
|
1234
|
+
/** @deprecated Use `usePluginJobCenter()` for the plugin job-center controller. */
|
|
827
1235
|
function useJobsStatusTray(options = {}) {
|
|
828
1236
|
return usePluginJobCenter(options);
|
|
829
1237
|
}
|
|
@@ -1074,18 +1482,153 @@ function useDoseCalculator() {
|
|
|
1074
1482
|
};
|
|
1075
1483
|
}
|
|
1076
1484
|
//#endregion
|
|
1485
|
+
//#region src/composables/useListReorder.ts
|
|
1486
|
+
/** Inline style for a visually hidden `aria-live` region (no global utility class in the SDK). */
|
|
1487
|
+
var REORDER_ANNOUNCER_STYLE = Object.freeze({
|
|
1488
|
+
position: "absolute",
|
|
1489
|
+
width: "1px",
|
|
1490
|
+
height: "1px",
|
|
1491
|
+
padding: "0",
|
|
1492
|
+
margin: "-1px",
|
|
1493
|
+
overflow: "hidden",
|
|
1494
|
+
clip: "rect(0, 0, 0, 0)",
|
|
1495
|
+
whiteSpace: "nowrap",
|
|
1496
|
+
border: "0"
|
|
1497
|
+
});
|
|
1498
|
+
/**
|
|
1499
|
+
* Screen-reader announcements for drag/keyboard move interactions. Bind
|
|
1500
|
+
* `announcement` to a `role="status" aria-live="polite"` element styled with
|
|
1501
|
+
* `announcerStyle`.
|
|
1502
|
+
*/
|
|
1503
|
+
function useReorderAnnouncer() {
|
|
1504
|
+
const announcement = ref("");
|
|
1505
|
+
function announce(message) {
|
|
1506
|
+
if (announcement.value === message) announcement.value = "";
|
|
1507
|
+
nextTick(() => {
|
|
1508
|
+
announcement.value = message;
|
|
1509
|
+
});
|
|
1510
|
+
}
|
|
1511
|
+
return {
|
|
1512
|
+
announcement,
|
|
1513
|
+
announce,
|
|
1514
|
+
announcerStyle: REORDER_ANNOUNCER_STYLE
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
/** Pure helper: a copy of `items` with the entry at `from` moved to `to`. */
|
|
1518
|
+
function reorderList(items, from, to) {
|
|
1519
|
+
const next = [...items];
|
|
1520
|
+
const [moved] = next.splice(from, 1);
|
|
1521
|
+
next.splice(to, 0, moved);
|
|
1522
|
+
return next;
|
|
1523
|
+
}
|
|
1524
|
+
/**
|
|
1525
|
+
* Keyboard-accessible list reordering shared by the SDK's drag-to-reorder lists.
|
|
1526
|
+
* It owns the HTML5 drag state, the drop-index maths, and an Alt+Arrow keyboard
|
|
1527
|
+
* alternative that announces every move through a polite live region — so a
|
|
1528
|
+
* reorder never depends on a pointer.
|
|
1529
|
+
*/
|
|
1530
|
+
function useListReorder(options) {
|
|
1531
|
+
const draggingId = ref(null);
|
|
1532
|
+
const dragOverId = ref(null);
|
|
1533
|
+
const { announcement, announce, announcerStyle } = useReorderAnnouncer();
|
|
1534
|
+
const noun = options.itemNoun ?? "Item";
|
|
1535
|
+
function isDisabled() {
|
|
1536
|
+
return options.disabled?.() === true;
|
|
1537
|
+
}
|
|
1538
|
+
function idFor(item, index) {
|
|
1539
|
+
return options.getId(item, index);
|
|
1540
|
+
}
|
|
1541
|
+
/** Index within `items()`, resolved by id so filtered/sorted renders still map back. */
|
|
1542
|
+
function indexOf(item, renderIndex) {
|
|
1543
|
+
const id = idFor(item, renderIndex);
|
|
1544
|
+
const found = options.items().findIndex((candidate, index) => idFor(candidate, index) === id);
|
|
1545
|
+
return found === -1 ? renderIndex : found;
|
|
1546
|
+
}
|
|
1547
|
+
function labelFor(index) {
|
|
1548
|
+
const item = options.items()[index];
|
|
1549
|
+
if (item === void 0) return noun;
|
|
1550
|
+
return options.getLabel?.(item, index) ?? idFor(item, index);
|
|
1551
|
+
}
|
|
1552
|
+
function clearDragState() {
|
|
1553
|
+
draggingId.value = null;
|
|
1554
|
+
dragOverId.value = null;
|
|
1555
|
+
}
|
|
1556
|
+
function move(fromIndex, toIndex, source = "keyboard") {
|
|
1557
|
+
if (isDisabled()) return;
|
|
1558
|
+
const items = options.items();
|
|
1559
|
+
if (fromIndex === toIndex || fromIndex < 0 || toIndex < 0 || fromIndex >= items.length || toIndex >= items.length) return;
|
|
1560
|
+
const movedId = idFor(items[fromIndex], fromIndex);
|
|
1561
|
+
const label = labelFor(fromIndex);
|
|
1562
|
+
options.onReorder({
|
|
1563
|
+
fromIndex,
|
|
1564
|
+
toIndex,
|
|
1565
|
+
items: reorderList(items, fromIndex, toIndex),
|
|
1566
|
+
source
|
|
1567
|
+
});
|
|
1568
|
+
announce(`${label} moved to position ${toIndex + 1} of ${items.length}.`);
|
|
1569
|
+
nextTick(() => options.getElement?.(movedId)?.focus());
|
|
1570
|
+
}
|
|
1571
|
+
function onDragStart(event, item, index) {
|
|
1572
|
+
if (isDisabled()) return;
|
|
1573
|
+
const id = idFor(item, index);
|
|
1574
|
+
draggingId.value = id;
|
|
1575
|
+
if (event.dataTransfer) {
|
|
1576
|
+
event.dataTransfer.effectAllowed = "move";
|
|
1577
|
+
event.dataTransfer.setData("text/plain", id);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
function onDragOver(event, item, index) {
|
|
1581
|
+
if (isDisabled() || draggingId.value === null) return;
|
|
1582
|
+
event.preventDefault();
|
|
1583
|
+
if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
|
|
1584
|
+
const id = idFor(item, index);
|
|
1585
|
+
dragOverId.value = id === draggingId.value ? null : id;
|
|
1586
|
+
}
|
|
1587
|
+
function onDragLeave() {
|
|
1588
|
+
dragOverId.value = null;
|
|
1589
|
+
}
|
|
1590
|
+
function onDrop(event, item, index) {
|
|
1591
|
+
if (isDisabled() || draggingId.value === null) {
|
|
1592
|
+
clearDragState();
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
event.preventDefault();
|
|
1596
|
+
const fromIndex = options.items().findIndex((candidate, i) => idFor(candidate, i) === draggingId.value);
|
|
1597
|
+
const toIndex = indexOf(item, index);
|
|
1598
|
+
clearDragState();
|
|
1599
|
+
if (fromIndex === -1) return;
|
|
1600
|
+
move(fromIndex, toIndex, "drag");
|
|
1601
|
+
}
|
|
1602
|
+
function onDragEnd() {
|
|
1603
|
+
clearDragState();
|
|
1604
|
+
}
|
|
1605
|
+
function onKeydown(event, item, index) {
|
|
1606
|
+
if (isDisabled() || !event.altKey) return;
|
|
1607
|
+
const direction = event.key === "ArrowUp" || event.key === "ArrowLeft" ? -1 : event.key === "ArrowDown" || event.key === "ArrowRight" ? 1 : 0;
|
|
1608
|
+
if (direction === 0) return;
|
|
1609
|
+
event.preventDefault();
|
|
1610
|
+
const fromIndex = indexOf(item, index);
|
|
1611
|
+
move(fromIndex, fromIndex + direction, "keyboard");
|
|
1612
|
+
}
|
|
1613
|
+
return {
|
|
1614
|
+
draggingId,
|
|
1615
|
+
dragOverId,
|
|
1616
|
+
isDragging: (id) => draggingId.value === id,
|
|
1617
|
+
isDragOver: (id) => dragOverId.value === id,
|
|
1618
|
+
announcement,
|
|
1619
|
+
announcerStyle,
|
|
1620
|
+
announce,
|
|
1621
|
+
onDragStart,
|
|
1622
|
+
onDragOver,
|
|
1623
|
+
onDragLeave,
|
|
1624
|
+
onDrop,
|
|
1625
|
+
onDragEnd,
|
|
1626
|
+
onKeydown,
|
|
1627
|
+
move
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1630
|
+
//#endregion
|
|
1077
1631
|
//#region src/composables/useWellPlateEditor.ts
|
|
1078
|
-
var DEFAULT_PALETTE = [
|
|
1079
|
-
"#3B82F6",
|
|
1080
|
-
"#10B981",
|
|
1081
|
-
"#EF4444",
|
|
1082
|
-
"#F59E0B",
|
|
1083
|
-
"#8B5CF6",
|
|
1084
|
-
"#F97316",
|
|
1085
|
-
"#06B6D4",
|
|
1086
|
-
"#14B8A6",
|
|
1087
|
-
"#6B7280"
|
|
1088
|
-
];
|
|
1089
1632
|
var MAX_HISTORY = 50;
|
|
1090
1633
|
function createEmptyPlate(name, format, id) {
|
|
1091
1634
|
return {
|
|
@@ -1169,7 +1712,7 @@ function useWellPlateEditor(initialState, options = {}) {
|
|
|
1169
1712
|
const sample = {
|
|
1170
1713
|
id: generateSampleId(),
|
|
1171
1714
|
name,
|
|
1172
|
-
color: color ||
|
|
1715
|
+
color: color || SAMPLE_COLOR_SCALE[internalState.value.samples.length % SAMPLE_COLOR_SCALE.length],
|
|
1173
1716
|
count: 0
|
|
1174
1717
|
};
|
|
1175
1718
|
internalState.value.samples.push(sample);
|
|
@@ -1277,7 +1820,7 @@ function useWellPlateEditor(initialState, options = {}) {
|
|
|
1277
1820
|
if (sampleId && !sampleMap.has(sampleId)) sampleMap.set(sampleId, {
|
|
1278
1821
|
id: sampleId,
|
|
1279
1822
|
name: sampleName || sampleId,
|
|
1280
|
-
color:
|
|
1823
|
+
color: SAMPLE_COLOR_SCALE[sampleMap.size % SAMPLE_COLOR_SCALE.length],
|
|
1281
1824
|
count: 0
|
|
1282
1825
|
});
|
|
1283
1826
|
const plate = plateMap.get(plateName);
|
|
@@ -2270,9 +2813,6 @@ function splitByTokenLength(classes, tokenized) {
|
|
|
2270
2813
|
}
|
|
2271
2814
|
//#endregion
|
|
2272
2815
|
//#region src/composables/experimentDesignData.ts
|
|
2273
|
-
function isRecord(value) {
|
|
2274
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2275
|
-
}
|
|
2276
2816
|
function isPlatformDesignDataResponse(value) {
|
|
2277
2817
|
return "data" in value && ("experiment_id" in value || "plugin_id" in value || "schema_version" in value || "updated_at" in value);
|
|
2278
2818
|
}
|
|
@@ -2986,7 +3526,7 @@ function useFileImport(options = {}) {
|
|
|
2986
3526
|
result.value = parsed;
|
|
2987
3527
|
return parsed;
|
|
2988
3528
|
} catch (err) {
|
|
2989
|
-
error.value = readErrorMessage(err);
|
|
3529
|
+
error.value = readErrorMessage(err, "Failed to import file.");
|
|
2990
3530
|
throw err;
|
|
2991
3531
|
} finally {
|
|
2992
3532
|
loading.value = false;
|
|
@@ -3096,108 +3636,6 @@ function formatBytes(bytes) {
|
|
|
3096
3636
|
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
3097
3637
|
return `${Math.round(bytes / (1024 * 1024))} MB`;
|
|
3098
3638
|
}
|
|
3099
|
-
function readErrorMessage(value) {
|
|
3100
|
-
if (value instanceof Error && value.message) return value.message;
|
|
3101
|
-
if (typeof value === "string" && value.trim()) return value;
|
|
3102
|
-
return "Failed to import file.";
|
|
3103
|
-
}
|
|
3104
|
-
//#endregion
|
|
3105
|
-
//#region src/utils/color.ts
|
|
3106
|
-
var HEX_RE = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i;
|
|
3107
|
-
function clamp(n, min, max) {
|
|
3108
|
-
return Math.min(max, Math.max(min, n));
|
|
3109
|
-
}
|
|
3110
|
-
function hexToHsl(hex) {
|
|
3111
|
-
const match = HEX_RE.exec(hex.trim());
|
|
3112
|
-
if (!match) return {
|
|
3113
|
-
h: 0,
|
|
3114
|
-
s: 0,
|
|
3115
|
-
l: 50
|
|
3116
|
-
};
|
|
3117
|
-
let raw = match[1];
|
|
3118
|
-
if (raw.length === 3) raw = raw.split("").map((c) => c + c).join("");
|
|
3119
|
-
const r = parseInt(raw.slice(0, 2), 16) / 255;
|
|
3120
|
-
const g = parseInt(raw.slice(2, 4), 16) / 255;
|
|
3121
|
-
const b = parseInt(raw.slice(4, 6), 16) / 255;
|
|
3122
|
-
const max = Math.max(r, g, b);
|
|
3123
|
-
const min = Math.min(r, g, b);
|
|
3124
|
-
const delta = max - min;
|
|
3125
|
-
let h = 0;
|
|
3126
|
-
if (delta !== 0) if (max === r) h = (g - b) / delta % 6;
|
|
3127
|
-
else if (max === g) h = (b - r) / delta + 2;
|
|
3128
|
-
else h = (r - g) / delta + 4;
|
|
3129
|
-
h = (h * 60 + 360) % 360;
|
|
3130
|
-
const l = (max + min) / 2;
|
|
3131
|
-
const s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
|
|
3132
|
-
return {
|
|
3133
|
-
h,
|
|
3134
|
-
s: s * 100,
|
|
3135
|
-
l: l * 100
|
|
3136
|
-
};
|
|
3137
|
-
}
|
|
3138
|
-
function hslToHex(h, s, l) {
|
|
3139
|
-
const sNorm = clamp(s, 0, 100) / 100;
|
|
3140
|
-
const lNorm = clamp(l, 0, 100) / 100;
|
|
3141
|
-
const hNorm = (h % 360 + 360) % 360;
|
|
3142
|
-
const c = (1 - Math.abs(2 * lNorm - 1)) * sNorm;
|
|
3143
|
-
const x = c * (1 - Math.abs(hNorm / 60 % 2 - 1));
|
|
3144
|
-
const m = lNorm - c / 2;
|
|
3145
|
-
let r = 0, g = 0, b = 0;
|
|
3146
|
-
if (hNorm < 60) [r, g, b] = [
|
|
3147
|
-
c,
|
|
3148
|
-
x,
|
|
3149
|
-
0
|
|
3150
|
-
];
|
|
3151
|
-
else if (hNorm < 120) [r, g, b] = [
|
|
3152
|
-
x,
|
|
3153
|
-
c,
|
|
3154
|
-
0
|
|
3155
|
-
];
|
|
3156
|
-
else if (hNorm < 180) [r, g, b] = [
|
|
3157
|
-
0,
|
|
3158
|
-
c,
|
|
3159
|
-
x
|
|
3160
|
-
];
|
|
3161
|
-
else if (hNorm < 240) [r, g, b] = [
|
|
3162
|
-
0,
|
|
3163
|
-
x,
|
|
3164
|
-
c
|
|
3165
|
-
];
|
|
3166
|
-
else if (hNorm < 300) [r, g, b] = [
|
|
3167
|
-
x,
|
|
3168
|
-
0,
|
|
3169
|
-
c
|
|
3170
|
-
];
|
|
3171
|
-
else [r, g, b] = [
|
|
3172
|
-
c,
|
|
3173
|
-
0,
|
|
3174
|
-
x
|
|
3175
|
-
];
|
|
3176
|
-
const toHex = (n) => Math.round((n + m) * 255).toString(16).padStart(2, "0");
|
|
3177
|
-
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
3178
|
-
}
|
|
3179
|
-
/**
|
|
3180
|
-
* Derive a same-hue-family shade of `parentHex` for child at `index` of `total`.
|
|
3181
|
-
*
|
|
3182
|
-
* Lightness is distributed evenly within [35, 75] so all children remain
|
|
3183
|
-
* readable on light/dark backgrounds. Hue and saturation are inherited from
|
|
3184
|
-
* the parent. With `total <= 1`, returns the parent unchanged.
|
|
3185
|
-
*
|
|
3186
|
-
* Children are ordered light → dark by index, so index 0 is the brightest
|
|
3187
|
-
* sibling and index `total - 1` is the darkest.
|
|
3188
|
-
*/
|
|
3189
|
-
function deriveShade(parentHex, index, total) {
|
|
3190
|
-
if (total <= 1) return parentHex;
|
|
3191
|
-
const { h, s, l } = hexToHsl(parentHex);
|
|
3192
|
-
const L_MIN = 35;
|
|
3193
|
-
const L_MAX = 75;
|
|
3194
|
-
const spread = Math.min(L_MAX - L_MIN, 40);
|
|
3195
|
-
const center = clamp(l, L_MIN + spread / 2, L_MAX - spread / 2);
|
|
3196
|
-
const top = center + spread / 2;
|
|
3197
|
-
const bot = center - spread / 2;
|
|
3198
|
-
const childL = top - (total === 1 ? .5 : index / (total - 1)) * (top - bot);
|
|
3199
|
-
return hslToHex(h, clamp(s, 35, 100), childL);
|
|
3200
|
-
}
|
|
3201
3639
|
//#endregion
|
|
3202
3640
|
//#region src/utils/sampleGroupPath.ts
|
|
3203
3641
|
/** Split a group name into normalized hierarchy segments. */
|
|
@@ -3657,6 +4095,30 @@ function useScheduleDrag(options) {
|
|
|
3657
4095
|
else if ((state.type === "resize-top" || state.type === "resize-bottom") && state.event && options.onResizeComplete) options.onResizeComplete(state.event, g.start, g.end);
|
|
3658
4096
|
cleanup();
|
|
3659
4097
|
}
|
|
4098
|
+
/**
|
|
4099
|
+
* Keyboard alternative to the pointer drag: shifts an event by one slot
|
|
4100
|
+
* (`mode: 'move'`) or grows/shrinks its end by one slot (`mode: 'resize'`),
|
|
4101
|
+
* staying inside the visible day. Returns whether the nudge was applied.
|
|
4102
|
+
*/
|
|
4103
|
+
function nudgeEvent(event, direction, mode = "move") {
|
|
4104
|
+
if (options.readonly.value) return false;
|
|
4105
|
+
if (mode === "move" && event.draggable === false) return false;
|
|
4106
|
+
if (mode === "resize" && event.resizable === false) return false;
|
|
4107
|
+
const slotMin = options.slotDuration.value;
|
|
4108
|
+
const dayStart = options.dayStartHour.value * 60;
|
|
4109
|
+
const dayEnd = options.dayEndHour.value * 60;
|
|
4110
|
+
const start = dateToMinutes(new Date(event.start));
|
|
4111
|
+
const end = dateToMinutes(new Date(event.end));
|
|
4112
|
+
const nextStart = mode === "move" ? start + direction * slotMin : start;
|
|
4113
|
+
const nextEnd = mode === "move" ? end + direction * slotMin : Math.max(start + slotMin, end + direction * slotMin);
|
|
4114
|
+
if (nextStart < dayStart || nextEnd > dayEnd || nextEnd <= nextStart) return false;
|
|
4115
|
+
const base = new Date(event.start);
|
|
4116
|
+
const newStart = minutesToDate(base, nextStart);
|
|
4117
|
+
const newEnd = minutesToDate(base, nextEnd);
|
|
4118
|
+
if (mode === "move") options.onMoveComplete?.(event, newStart, newEnd);
|
|
4119
|
+
else options.onResizeComplete?.(event, newStart, newEnd);
|
|
4120
|
+
return true;
|
|
4121
|
+
}
|
|
3660
4122
|
function addListeners() {
|
|
3661
4123
|
document.addEventListener("pointermove", onPointerMove);
|
|
3662
4124
|
document.addEventListener("pointerup", onPointerUp);
|
|
@@ -3674,7 +4136,8 @@ function useScheduleDrag(options) {
|
|
|
3674
4136
|
ghost,
|
|
3675
4137
|
startCreate,
|
|
3676
4138
|
startMove,
|
|
3677
|
-
startResize
|
|
4139
|
+
startResize,
|
|
4140
|
+
nudgeEvent
|
|
3678
4141
|
};
|
|
3679
4142
|
}
|
|
3680
4143
|
function snapMinutes(minutes, step) {
|
|
@@ -4031,6 +4494,57 @@ function useBioTemplateComponents(target) {
|
|
|
4031
4494
|
};
|
|
4032
4495
|
}
|
|
4033
4496
|
//#endregion
|
|
4497
|
+
//#region src/composables/flattenWorkspaceBindings.ts
|
|
4498
|
+
/**
|
|
4499
|
+
* Pick the shared template-component binding keys off a resolved bio-template workspace
|
|
4500
|
+
* (or its `components` source directly), so composables that build on `useBioTemplateWorkspace`
|
|
4501
|
+
* spread one object instead of re-listing all 9 keys by hand.
|
|
4502
|
+
*
|
|
4503
|
+
* @example Recommended
|
|
4504
|
+
* ```ts
|
|
4505
|
+
* const bindings = { renderer, ...flattenWorkspaceComponentBindings(components) }
|
|
4506
|
+
* ```
|
|
4507
|
+
*/
|
|
4508
|
+
function flattenWorkspaceComponentBindings(source) {
|
|
4509
|
+
return {
|
|
4510
|
+
componentBindings: source.componentBindings,
|
|
4511
|
+
componentBindingsById: source.componentBindingsById,
|
|
4512
|
+
componentImports: source.componentImports,
|
|
4513
|
+
componentProps: source.componentProps,
|
|
4514
|
+
componentPropsById: source.componentPropsById,
|
|
4515
|
+
componentPropsByComponent: source.componentPropsByComponent,
|
|
4516
|
+
componentSnippets: source.componentSnippets,
|
|
4517
|
+
componentUsage: source.componentUsage,
|
|
4518
|
+
getComponentProps: source.getComponentProps
|
|
4519
|
+
};
|
|
4520
|
+
}
|
|
4521
|
+
/**
|
|
4522
|
+
* `computed()`-lifted version of {@link flattenWorkspaceComponentBindings} for composables
|
|
4523
|
+
* that hold their resolved workspace behind a `ComputedRef` (e.g. a regenerated workspace
|
|
4524
|
+
* swapped in via `shallowRef`/`effectScope`), so each key stays independently reactive
|
|
4525
|
+
* instead of forcing consumers to unwrap the whole workspace to read one field.
|
|
4526
|
+
* `getComponentProps` stays a plain callable function, matching the un-lifted composables.
|
|
4527
|
+
*
|
|
4528
|
+
* @example Recommended
|
|
4529
|
+
* ```ts
|
|
4530
|
+
* const workspace = computed(() => workspaceRef.value)
|
|
4531
|
+
* const { componentBindings, componentProps, getComponentProps } = liftWorkspaceComponentBindings(workspace)
|
|
4532
|
+
* ```
|
|
4533
|
+
*/
|
|
4534
|
+
function liftWorkspaceComponentBindings(workspace) {
|
|
4535
|
+
return {
|
|
4536
|
+
componentBindings: computed(() => workspace.value.componentBindings),
|
|
4537
|
+
componentBindingsById: computed(() => workspace.value.componentBindingsById),
|
|
4538
|
+
componentImports: computed(() => workspace.value.componentImports),
|
|
4539
|
+
componentProps: computed(() => workspace.value.componentProps),
|
|
4540
|
+
componentPropsById: computed(() => workspace.value.componentPropsById),
|
|
4541
|
+
componentPropsByComponent: computed(() => workspace.value.componentPropsByComponent),
|
|
4542
|
+
componentSnippets: computed(() => workspace.value.componentSnippets),
|
|
4543
|
+
componentUsage: computed(() => workspace.value.componentUsage),
|
|
4544
|
+
getComponentProps: (component, options) => workspace.value.getComponentProps(component, options)
|
|
4545
|
+
};
|
|
4546
|
+
}
|
|
4547
|
+
//#endregion
|
|
4034
4548
|
//#region src/composables/useBioTemplateWorkspace.ts
|
|
4035
4549
|
/** One-stop wiring for BioTemplateRenderer, FormBuilder, AppSidebar, and template-aware SDK components. */
|
|
4036
4550
|
function useBioTemplateWorkspace(target, options = {}) {
|
|
@@ -4038,21 +4552,25 @@ function useBioTemplateWorkspace(target, options = {}) {
|
|
|
4038
4552
|
const workspace = useControlWorkspace(controls.controls, options);
|
|
4039
4553
|
const components = useBioTemplateComponents(target);
|
|
4040
4554
|
const renderer = isTemplateObjectTarget(target) ? { target } : null;
|
|
4041
|
-
const
|
|
4042
|
-
renderer,
|
|
4043
|
-
form: workspace.bindings.form,
|
|
4044
|
-
sidebar: workspace.bindings.sidebar,
|
|
4045
|
-
topBar: workspace.bindings.topBar,
|
|
4046
|
-
topBarSettings: workspace.bindings.topBarSettings,
|
|
4047
|
-
pillNav: workspace.bindings.pillNav,
|
|
4555
|
+
const componentBindings = flattenWorkspaceComponentBindings({
|
|
4048
4556
|
componentBindings: components.bindings,
|
|
4049
4557
|
componentBindingsById: components.componentBindingsById,
|
|
4558
|
+
componentImports: components.imports,
|
|
4050
4559
|
componentProps: components.componentProps,
|
|
4051
4560
|
componentPropsById: components.componentPropsById,
|
|
4052
4561
|
componentPropsByComponent: components.componentPropsByComponent,
|
|
4053
4562
|
componentSnippets: components.snippets,
|
|
4054
4563
|
componentUsage: components.usage,
|
|
4055
4564
|
getComponentProps: components.getComponentProps
|
|
4565
|
+
});
|
|
4566
|
+
const bindings = {
|
|
4567
|
+
renderer,
|
|
4568
|
+
form: workspace.bindings.form,
|
|
4569
|
+
sidebar: workspace.bindings.sidebar,
|
|
4570
|
+
topBar: workspace.bindings.topBar,
|
|
4571
|
+
topBarSettings: workspace.bindings.topBarSettings,
|
|
4572
|
+
pillNav: workspace.bindings.pillNav,
|
|
4573
|
+
...componentBindings
|
|
4056
4574
|
};
|
|
4057
4575
|
return {
|
|
4058
4576
|
target,
|
|
@@ -4069,15 +4587,7 @@ function useBioTemplateWorkspace(target, options = {}) {
|
|
|
4069
4587
|
topBarSettings: workspace.topBarSettings,
|
|
4070
4588
|
bindings,
|
|
4071
4589
|
renderer,
|
|
4072
|
-
componentBindings
|
|
4073
|
-
componentBindingsById: components.componentBindingsById,
|
|
4074
|
-
componentImports: components.imports,
|
|
4075
|
-
componentProps: components.componentProps,
|
|
4076
|
-
componentPropsById: components.componentPropsById,
|
|
4077
|
-
componentPropsByComponent: components.componentPropsByComponent,
|
|
4078
|
-
componentSnippets: components.snippets,
|
|
4079
|
-
componentUsage: components.usage,
|
|
4080
|
-
getComponentProps: components.getComponentProps
|
|
4590
|
+
...componentBindings
|
|
4081
4591
|
};
|
|
4082
4592
|
}
|
|
4083
4593
|
function isTemplateObjectTarget(target) {
|
|
@@ -4118,14 +4628,7 @@ function useBioTemplatePackWorkspace(packId, options = {}) {
|
|
|
4118
4628
|
const pillNav = computed(() => workspace.value.pillNav);
|
|
4119
4629
|
const topBarSettings = computed(() => workspace.value.topBarSettings);
|
|
4120
4630
|
const bindings = computed(() => workspace.value.bindings);
|
|
4121
|
-
const componentBindings =
|
|
4122
|
-
const componentBindingsById = computed(() => workspace.value.componentBindingsById);
|
|
4123
|
-
const componentImports = computed(() => workspace.value.componentImports);
|
|
4124
|
-
const componentProps = computed(() => workspace.value.componentProps);
|
|
4125
|
-
const componentPropsById = computed(() => workspace.value.componentPropsById);
|
|
4126
|
-
const componentPropsByComponent = computed(() => workspace.value.componentPropsByComponent);
|
|
4127
|
-
const componentSnippets = computed(() => workspace.value.componentSnippets);
|
|
4128
|
-
const componentUsage = computed(() => workspace.value.componentUsage);
|
|
4631
|
+
const { componentBindings, componentBindingsById, componentImports, componentProps, componentPropsById, componentPropsByComponent, componentSnippets, componentUsage, getComponentProps: getWorkspaceComponentProps } = liftWorkspaceComponentBindings(workspace);
|
|
4129
4632
|
watch(collection, (value) => {
|
|
4130
4633
|
workspaceRef.value = createWorkspace(value);
|
|
4131
4634
|
});
|
|
@@ -4168,7 +4671,7 @@ function useBioTemplatePackWorkspace(packId, options = {}) {
|
|
|
4168
4671
|
componentPropsByComponent,
|
|
4169
4672
|
componentSnippets,
|
|
4170
4673
|
componentUsage,
|
|
4171
|
-
getComponentProps:
|
|
4674
|
+
getComponentProps: getWorkspaceComponentProps,
|
|
4172
4675
|
applyCollection,
|
|
4173
4676
|
resetToDefaultCollection,
|
|
4174
4677
|
save: templateCollection.save,
|
|
@@ -4199,14 +4702,7 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
|
|
|
4199
4702
|
const collection = templateCollection.templateCollection;
|
|
4200
4703
|
const workspace = computed(() => useBioTemplateWorkspace(collection.value, resolvedControlOptions));
|
|
4201
4704
|
const renderer = computed(() => ({ target: collection.value }));
|
|
4202
|
-
const componentBindings =
|
|
4203
|
-
const componentBindingsById = computed(() => workspace.value.componentBindingsById);
|
|
4204
|
-
const componentImports = computed(() => workspace.value.componentImports);
|
|
4205
|
-
const componentProps = computed(() => workspace.value.componentProps);
|
|
4206
|
-
const componentPropsById = computed(() => workspace.value.componentPropsById);
|
|
4207
|
-
const componentPropsByComponent = computed(() => workspace.value.componentPropsByComponent);
|
|
4208
|
-
const componentSnippets = computed(() => workspace.value.componentSnippets);
|
|
4209
|
-
const componentUsage = computed(() => workspace.value.componentUsage);
|
|
4705
|
+
const { componentBindings, componentBindingsById, componentImports, componentProps, componentPropsById, componentPropsByComponent, componentSnippets, componentUsage, getComponentProps } = liftWorkspaceComponentBindings(workspace);
|
|
4210
4706
|
const form = reactive({
|
|
4211
4707
|
...controls.form,
|
|
4212
4708
|
modelValue: controlValues.value,
|
|
@@ -4239,9 +4735,6 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
|
|
|
4239
4735
|
onPillSelect: pillNav.onSelect,
|
|
4240
4736
|
...topBarSettings
|
|
4241
4737
|
}));
|
|
4242
|
-
function getComponentProps(component, options) {
|
|
4243
|
-
return workspace.value.getComponentProps(component, options);
|
|
4244
|
-
}
|
|
4245
4738
|
const bindings = {
|
|
4246
4739
|
renderer,
|
|
4247
4740
|
form,
|
|
@@ -4367,36 +4860,6 @@ var SLOT_CYCLE = [
|
|
|
4367
4860
|
"B",
|
|
4368
4861
|
"Y"
|
|
4369
4862
|
];
|
|
4370
|
-
var PLATE_CONFIGS = {
|
|
4371
|
-
6: {
|
|
4372
|
-
rows: 2,
|
|
4373
|
-
cols: 3
|
|
4374
|
-
},
|
|
4375
|
-
12: {
|
|
4376
|
-
rows: 3,
|
|
4377
|
-
cols: 4
|
|
4378
|
-
},
|
|
4379
|
-
24: {
|
|
4380
|
-
rows: 4,
|
|
4381
|
-
cols: 6
|
|
4382
|
-
},
|
|
4383
|
-
48: {
|
|
4384
|
-
rows: 6,
|
|
4385
|
-
cols: 8
|
|
4386
|
-
},
|
|
4387
|
-
54: {
|
|
4388
|
-
rows: 6,
|
|
4389
|
-
cols: 9
|
|
4390
|
-
},
|
|
4391
|
-
96: {
|
|
4392
|
-
rows: 8,
|
|
4393
|
-
cols: 12
|
|
4394
|
-
},
|
|
4395
|
-
384: {
|
|
4396
|
-
rows: 16,
|
|
4397
|
-
cols: 24
|
|
4398
|
-
}
|
|
4399
|
-
};
|
|
4400
4863
|
var globalIdCounter = 0;
|
|
4401
4864
|
function generateId() {
|
|
4402
4865
|
globalIdCounter++;
|
|
@@ -4480,7 +4943,7 @@ function useRackEditor(initialRacks, options) {
|
|
|
4480
4943
|
if (!config) return;
|
|
4481
4944
|
let counter = 1;
|
|
4482
4945
|
for (let row = 0; row < config.rows; row++) for (let col = 0; col < config.cols; col++) {
|
|
4483
|
-
const wellId = `${
|
|
4946
|
+
const wellId = `${rowLabel(row)}${col + 1}`;
|
|
4484
4947
|
if (!rack.wells[wellId]?.sampleType) {
|
|
4485
4948
|
const paddedNum = String(counter).padStart(3, "0");
|
|
4486
4949
|
rack.wells[wellId] = {
|
|
@@ -5144,6 +5607,6 @@ function useProtocolTemplates() {
|
|
|
5144
5607
|
};
|
|
5145
5608
|
}
|
|
5146
5609
|
//#endregion
|
|
5147
|
-
export {
|
|
5610
|
+
export { usePresenceHeartbeat as $, useAutoGroup as A, useReorderAnnouncer as B, getSampleGroupParentPath as C, useFileImport as D, readFileAsText as E, DEFAULT_COLORS as F, usePluginWorkspace as G, combinePluginJobSources as H, useWellPlateEditor as I, APP_EXPERIMENT_KEY as J, DEFAULT_MOBILE_VIEWPORT_QUERY as K, REORDER_ANNOUNCER_STYLE as L, extractSampleNamesFromDesignData as M, extractSampleOptionsFromDesignData as N, validateImportFile as O, unwrapExperimentDesignData as P, getPresenceClientId as Q, reorderList as R, getSampleGroupMajorPrefix as S, parseDelimitedText as T, useJobsStatusTray as U, useDoseCalculator as V, usePluginJobCenter as W, getInjectedFrontendRevision as X, useAppExperiment as Y, useRuntimeAlignment as Z, useScheduleDrag as _, useReagentSeries as a, compareSortValues as at, useExpansionSet as b, useBioTemplatePresetWorkspace as c, useRovingFocus as ct, getBioTemplateComponentProps as d, useTheme as et, toBioTemplateComponentPropsByComponent as f, useExperimentSave as g, useTemplateCollection as h, generateDilutionSeries as i, useTextSearch as it, parseCSV as j, extractSamplesFromDesignData as k, useBioTemplatePackWorkspace as l, useBioTemplateControls as m, DEFAULT_PRESETS as n, candidateMatchesSearch as nt, useGroupAssignment as o, useSortedItems as ot, useBioTemplateComponents as p, useMobileSupportGate as q, DEFAULT_UNITS as r, normalizeSearchQuery as rt, useRackEditor as s, useMenuKeyboard as st, useProtocolTemplates as t, useToast as tt, useBioTemplateWorkspace as u, useExperimentSamples as v, detectDelimiter as w, useSampleGroups as x, useExperimentData as y, useListReorder as z };
|
|
5148
5611
|
|
|
5149
|
-
//# sourceMappingURL=useProtocolTemplates-
|
|
5612
|
+
//# sourceMappingURL=useProtocolTemplates-BmX_iVBR.js.map
|