@morscherlab/mint-sdk 1.2.0-beta.1 → 1.2.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -5
- package/dist/{ExperimentPopover-tLwJ7XF4.js → ExperimentPopover-oL0fg_A0.js} +6 -4
- package/dist/ExperimentPopover-oL0fg_A0.js.map +1 -0
- package/dist/{ExperimentSelectorModal-DyPAUCLw.js → ExperimentSelectorModal-BeEOomw_.js} +5 -5
- package/dist/ExperimentSelectorModal-BeEOomw_.js.map +1 -0
- package/dist/{SettingsModal-BgKY93zh.js → SettingsModal-Dphh3RrI.js} +5 -8
- package/dist/SettingsModal-Dphh3RrI.js.map +1 -0
- package/dist/{EmptyState-p90quq8Z.js → Skeleton-DxtwJ5gt.js} +111 -93
- package/dist/Skeleton-DxtwJ5gt.js.map +1 -0
- package/dist/__tests__/components/ExperimentTimeline.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.internal.test.d.ts +1 -0
- package/dist/__tests__/components/SecretInput.test.d.ts +1 -0
- package/dist/__tests__/components/WellEditPopupInternal.test.d.ts +1 -0
- package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
- package/dist/__tests__/composables/usePluginConfig.test.d.ts +15 -0
- package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
- package/dist/components/ActionMenu.vue.d.ts +1 -1
- package/dist/components/AppAvatarMenu.vue.d.ts +4 -0
- package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
- package/dist/components/AppSidebar.vue.d.ts +1 -1
- package/dist/components/AuditTrail.vue.d.ts +13 -0
- package/dist/components/AutoGroupModal.vue.d.ts +1 -1
- package/dist/components/BatchProgressList.vue.d.ts +17 -0
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
- package/dist/components/DataFrame.vue.d.ts +14 -2
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/DateTimePicker.vue.d.ts +2 -0
- package/dist/components/DropdownButton.vue.d.ts +2 -0
- package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
- package/dist/components/ExperimentPopover.vue.d.ts +1 -0
- package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
- package/dist/components/FitPanel.vue.d.ts +1 -1
- package/dist/components/JobsStatusTray.vue.d.ts +9 -2
- package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
- package/dist/components/PluginWorkspaceView.props.d.ts +29 -1
- package/dist/components/PluginWorkspaceView.vue.d.ts +5 -5
- package/dist/components/ProgressBar.vue.d.ts +1 -1
- package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
- package/dist/components/ReagentList.vue.d.ts +29 -1
- package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
- package/dist/components/SampleLegend.vue.d.ts +1 -1
- package/dist/components/SampleSelector.drag.d.ts +13 -0
- package/dist/components/SampleSelector.tree.d.ts +2 -0
- package/dist/components/SampleSelector.vue.d.ts +35 -2
- package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
- package/dist/components/SecretInput.vue.d.ts +28 -0
- package/dist/components/SettingsModal.vue.d.ts +1 -1
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -1
- package/dist/components/TimePicker.vue.d.ts +1 -0
- package/dist/components/WellPlate.geometry.d.ts +15 -0
- package/dist/components/WellPlate.interaction.d.ts +13 -0
- package/dist/components/WellPlate.vue.d.ts +29 -0
- package/dist/components/index.d.ts +9 -0
- package/dist/components/index.js +8 -8
- package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
- package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
- package/dist/components/internal/WellEditPopupInternal.vue.d.ts +3 -1
- package/dist/components/internal/WorkspaceControlsInternal.vue.d.ts +23 -0
- package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +70 -0
- package/dist/components/internal/WorkspaceSidebarInternal.vue.d.ts +43 -0
- package/dist/{components-DkHddRMl.js → components-CgAUzF8F.js} +2497 -2235
- package/dist/components-CgAUzF8F.js.map +1 -0
- package/dist/composables/controlSchemaTypes.d.ts +34 -0
- package/dist/composables/flattenWorkspaceBindings.d.ts +61 -0
- package/dist/composables/index.d.ts +9 -2
- package/dist/composables/index.js +10 -10
- package/dist/composables/pluginWorkspaceModel.d.ts +164 -0
- package/dist/composables/useAsync.d.ts +5 -1
- package/dist/composables/useBioTemplateWorkspace.d.ts +4 -20
- package/dist/composables/useCommandHistory.d.ts +5 -1
- package/dist/composables/useDropdownState.d.ts +18 -2
- package/dist/composables/useEventStream.d.ts +9 -0
- package/dist/composables/useFocusTrap.d.ts +21 -0
- package/dist/composables/useGeneratedAnalysis.d.ts +3 -1
- package/dist/composables/useJobsStatusTray.d.ts +25 -1
- package/dist/composables/useListReorder.d.ts +90 -0
- package/dist/composables/useMenuKeyboard.d.ts +29 -0
- package/dist/composables/useOptimisticMutation.d.ts +5 -1
- package/dist/composables/usePluginClient.d.ts +2 -0
- package/dist/composables/usePluginConfig.d.ts +27 -0
- package/dist/composables/usePluginWorkspace.d.ts +51 -0
- package/dist/composables/useRequestSyncState.d.ts +42 -2
- package/dist/composables/useResourceCrud.d.ts +5 -1
- package/dist/composables/useRovingFocus.d.ts +24 -0
- package/dist/composables/useScheduleDrag.d.ts +1 -0
- package/dist/composables/useWellPainting.d.ts +5 -1
- package/dist/composables/useWellPlateAdapter.d.ts +5 -1
- package/dist/composables/useWellPlateValidation.d.ts +5 -1
- package/dist/composables/workspaceRecipes.d.ts +188 -0
- package/dist/{composables-C_i90sGS.js → composables-B_pia3hO.js} +209 -82
- package/dist/composables-B_pia3hO.js.map +1 -0
- package/dist/{useApi-J6zFkHmn.js → errors-_W0-LbA6.js} +103 -3
- package/dist/errors-_W0-LbA6.js.map +1 -0
- package/dist/{experiment-Cq145oEW.js → experiment-Cwl9AYxw.js} +3 -8
- package/dist/experiment-Cwl9AYxw.js.map +1 -0
- package/dist/{experiment-utils-CLnzPPq5.js → experiment-utils-DV3DrvE_.js} +70 -51
- package/dist/experiment-utils-DV3DrvE_.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -15
- package/dist/install.js +2 -7
- package/dist/install.js.map +1 -1
- package/dist/permissions.d.ts +42 -1
- package/dist/permissions.js +20 -10
- package/dist/permissions.js.map +1 -1
- package/dist/stores/auth.d.ts +6 -0
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.js +3 -3
- package/dist/stores/settings.d.ts +31 -1
- package/dist/styles.css +11247 -29501
- package/dist/templates/builderReadUtils.d.ts +1 -1
- package/dist/templates/index.js +2 -4
- package/dist/{templates-DsP51i-S.js → templates-Qq113pyZ.js} +303 -106
- package/dist/templates-Qq113pyZ.js.map +1 -0
- package/dist/types/auth.d.ts +1 -0
- package/dist/types/form-builder.d.ts +1 -1
- package/dist/{useControlSchema-BDx2Olha.js → useControlSchema-aMZlb4Sc.js} +462 -1130
- package/dist/useControlSchema-aMZlb4Sc.js.map +1 -0
- package/dist/{useDropdownState-DSb3BC3N.js → useDropdownState-DitCtrTT.js} +22 -6
- package/dist/useDropdownState-DitCtrTT.js.map +1 -0
- package/dist/{useExperimentSelector-CV4iNfMS.js → useExperimentSelector-I8HC8hUu.js} +4 -4
- package/dist/{useExperimentSelector-CV4iNfMS.js.map → useExperimentSelector-I8HC8hUu.js.map} +1 -1
- package/dist/{useFormBuilder-BLxG3BOX.js → useFormBuilder-TCxNnqeb.js} +2 -2
- package/dist/{useFormBuilder-BLxG3BOX.js.map → useFormBuilder-TCxNnqeb.js.map} +1 -1
- package/dist/{useProtocolTemplates-CS_SQl6U.js → useProtocolTemplates-BmX_iVBR.js} +766 -212
- package/dist/useProtocolTemplates-BmX_iVBR.js.map +1 -0
- package/dist/utils/color.d.ts +13 -0
- package/dist/utils/errors.d.ts +9 -0
- package/dist/utils/pluginSecrets.d.ts +53 -0
- package/dist/utils/records.d.ts +4 -0
- package/package.json +1 -1
- package/src/__tests__/components/ActionMenu.test.ts +94 -0
- package/src/__tests__/components/AppAvatarMenu.test.ts +123 -0
- package/src/__tests__/components/BaseTabs.test.ts +67 -0
- package/src/__tests__/components/DataFrame.test.ts +183 -11
- package/src/__tests__/components/DataStates.test.ts +176 -0
- package/src/__tests__/components/DatePicker.test.ts +76 -0
- package/src/__tests__/components/DateTimePicker.test.ts +36 -0
- package/src/__tests__/components/DropdownButton.test.ts +134 -0
- package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
- package/src/__tests__/components/GroupAssigner.test.ts +53 -0
- package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
- package/src/__tests__/components/PluginWorkspaceView.internal.test.ts +230 -0
- package/src/__tests__/components/RackEditor.test.ts +35 -0
- package/src/__tests__/components/ReagentList.test.ts +64 -2
- package/src/__tests__/components/RetiredStyles.test.ts +31 -0
- package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
- package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
- package/src/__tests__/components/SecretInput.test.ts +87 -0
- package/src/__tests__/components/SegmentedControl.test.ts +88 -0
- package/src/__tests__/components/TimePicker.test.ts +61 -0
- package/src/__tests__/components/WellEditPopupInternal.test.ts +108 -0
- package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
- package/src/__tests__/composables/useAuth.test.ts +2 -0
- package/src/__tests__/composables/useDropdownState.test.ts +58 -1
- package/src/__tests__/composables/useListReorder.test.ts +145 -0
- package/src/__tests__/composables/usePluginClient.test.ts +140 -0
- package/src/__tests__/composables/usePluginConfig.test.ts +497 -0
- package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +39 -7
- package/src/__tests__/stores/settings.test.ts +71 -1
- package/src/__tests__/styles/cssTokens.test.ts +131 -0
- package/src/__tests__/utils/permissions.test.ts +68 -0
- package/src/components/ActionMenu.vue +45 -88
- package/src/components/AlertBox.vue +0 -4
- package/src/components/AppAvatarMenu.vue +26 -7
- package/src/components/AppLayout.vue +0 -4
- package/src/components/AppPluginSwitcher.story.vue +87 -0
- package/src/components/AppPluginSwitcher.vue +2 -5
- package/src/components/AppSidebar.vue +0 -4
- package/src/components/AppToastContainer.vue +6 -8
- package/src/components/AppTopBar.vue +0 -4
- package/src/components/ArtifactSaveDialog.vue +0 -4
- package/src/components/ArtifactSelectorModal.vue +0 -4
- package/src/components/AuditTrail.story.vue +18 -0
- package/src/components/AuditTrail.vue +27 -7
- package/src/components/AutoGroupModal.vue +0 -4
- package/src/components/Avatar.vue +0 -4
- package/src/components/BaseButton.vue +0 -4
- package/src/components/BaseCheckbox.vue +0 -4
- package/src/components/BaseInput.vue +0 -4
- package/src/components/BaseModal.vue +8 -60
- package/src/components/BasePill.vue +0 -4
- package/src/components/BaseRadioGroup.vue +0 -4
- package/src/components/BaseSelect.vue +0 -4
- package/src/components/BaseSlider.vue +0 -4
- package/src/components/BaseTabs.vue +26 -5
- package/src/components/BaseTextarea.vue +0 -4
- package/src/components/BaseToggle.vue +0 -4
- package/src/components/BatchProgressList.story.vue +18 -0
- package/src/components/BatchProgressList.vue +32 -4
- package/src/components/BioTemplateExperimentWorkspaceView.vue +10 -21
- package/src/components/BioTemplatePackWorkspaceView.vue +11 -15
- package/src/components/BioTemplatePresetWorkspaceView.vue +8 -13
- package/src/components/Breadcrumb.vue +0 -4
- package/src/components/Calendar.vue +0 -4
- package/src/components/ChartContainer.story.vue +1 -1
- package/src/components/ChartContainer.vue +0 -4
- package/src/components/ChemicalFormula.vue +0 -4
- package/src/components/CollapsibleCard.vue +0 -4
- package/src/components/ColorSlider.vue +0 -4
- package/src/components/ComponentBindingRenderer.vue +1 -3
- package/src/components/ConcentrationInput.vue +0 -4
- package/src/components/ConfirmDialog.vue +0 -4
- package/src/components/ControlWorkspaceView.vue +11 -22
- package/src/components/DataFrame.story.vue +14 -0
- package/src/components/DataFrame.vue +97 -23
- package/src/components/DatePicker.vue +73 -27
- package/src/components/DateTimePicker.vue +45 -17
- package/src/components/Divider.vue +0 -4
- package/src/components/DoseCalculator.vue +0 -4
- package/src/components/DoseDesignWorkspaceView.vue +6 -25
- package/src/components/DropdownButton.vue +24 -6
- package/src/components/EmptyState.vue +0 -4
- package/src/components/ExperimentCodeBadge.vue +0 -4
- package/src/components/ExperimentDataViewer.story.vue +3 -0
- package/src/components/ExperimentDataViewer.vue +33 -13
- package/src/components/ExperimentPopover.vue +2 -5
- package/src/components/ExperimentSelectorModal.vue +0 -4
- package/src/components/ExperimentTimeline.story.vue +18 -0
- package/src/components/ExperimentTimeline.vue +81 -75
- package/src/components/FileUploader.vue +0 -4
- package/src/components/FitPanel.vue +0 -4
- package/src/components/FormActions.story.vue +96 -0
- package/src/components/FormActions.vue +0 -4
- package/src/components/FormBuilder.vue +0 -4
- package/src/components/FormField.vue +0 -4
- package/src/components/FormulaInput.vue +0 -4
- package/src/components/GeneratedPathInput.story.vue +68 -0
- package/src/components/GeneratedPlotlyResult.story.vue +96 -0
- package/src/components/GeneratedPlotlyResult.vue +3 -3
- package/src/components/GeneratedPluginView.story.vue +145 -0
- package/src/components/GeneratedPluginView.vue +10 -10
- package/src/components/GeneratedResultRenderer.story.vue +117 -0
- package/src/components/GeneratedResultRenderer.vue +4 -4
- package/src/components/GroupAssigner.vue +67 -5
- package/src/components/IconButton.vue +0 -4
- package/src/components/InstrumentAlertLog.vue +0 -4
- package/src/components/InstrumentStateBadge.vue +0 -4
- package/src/components/InstrumentStatusCard.vue +0 -4
- package/src/components/JobsStatusTray.vue +16 -5
- package/src/components/LcmsSequenceTable.vue +81 -50
- package/src/components/LoadingSpinner.vue +0 -4
- package/src/components/MobileSupportGate.vue +0 -4
- package/src/components/MoleculeInput.vue +0 -4
- package/src/components/MultiSelect.vue +0 -4
- package/src/components/NumberInput.vue +0 -4
- package/src/components/PlateMapEditor.vue +3 -14
- package/src/components/PluginIcon.vue +0 -4
- package/src/components/PluginWorkspaceView.props.ts +38 -0
- package/src/components/PluginWorkspaceView.vue +53 -224
- package/src/components/ProgressBar.vue +0 -4
- package/src/components/ProtocolStepEditor.vue +2 -4
- package/src/components/RackEditor.vue +51 -70
- package/src/components/ReagentEditor.vue +0 -4
- package/src/components/ReagentList.story.vue +18 -0
- package/src/components/ReagentList.vue +127 -82
- package/src/components/ResourceCard.vue +0 -4
- package/src/components/RuntimeUpdateNotice.story.vue +49 -0
- package/src/components/RuntimeUpdateNotice.vue +4 -4
- package/src/components/SampleHierarchyTree.story.vue +18 -0
- package/src/components/SampleHierarchyTree.vue +32 -9
- package/src/components/SampleLegend.vue +2 -8
- package/src/components/SampleSelector.drag.ts +51 -0
- package/src/components/SampleSelector.story.vue +6 -0
- package/src/components/SampleSelector.tree.ts +2 -0
- package/src/components/SampleSelector.vue +49 -10
- package/src/components/SampleSelectorGroupNode.vue +19 -0
- package/src/components/ScheduleCalendar.story.vue +6 -0
- package/src/components/ScheduleCalendar.vue +82 -7
- package/src/components/ScientificNumber.vue +0 -4
- package/src/components/SecretInput.story.vue +79 -0
- package/src/components/SecretInput.vue +150 -0
- package/src/components/SectionCard.vue +0 -4
- package/src/components/SegmentedControl.vue +48 -5
- package/src/components/SequenceInput.vue +0 -4
- package/src/components/SequenceProgressBar.story.vue +110 -0
- package/src/components/SequenceProgressBar.vue +0 -4
- package/src/components/SettingsModal.vue +0 -4
- package/src/components/Skeleton.vue +0 -4
- package/src/components/SmartGroupFieldRecipe.vue +8 -6
- package/src/components/SmartGroupManual.vue +0 -4
- package/src/components/StatusIndicator.vue +0 -4
- package/src/components/StepWizard.vue +0 -4
- package/src/components/TagsInput.vue +4 -6
- package/src/components/ThemeToggle.vue +0 -4
- package/src/components/TimePicker.vue +36 -7
- package/src/components/TimeRangeInput.vue +0 -4
- package/src/components/Tooltip.story.vue +3 -3
- package/src/components/Tooltip.vue +0 -4
- package/src/components/UnitInput.vue +0 -4
- package/src/components/WellPlate.geometry.ts +60 -1
- package/src/components/WellPlate.interaction.ts +44 -0
- package/src/components/WellPlate.story.vue +8 -0
- package/src/components/WellPlate.vue +53 -7
- package/src/components/index.ts +9 -0
- package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
- package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
- package/src/components/internal/DataStateInternal.vue +74 -0
- package/src/components/internal/FormSectionRenderer.vue +0 -4
- package/src/components/internal/WellEditPopupInternal.vue +20 -5
- package/src/components/internal/WorkspaceControlsInternal.vue +20 -0
- package/src/components/internal/WorkspaceShellInternal.vue +125 -0
- package/src/components/internal/WorkspaceSidebarInternal.vue +82 -0
- package/src/composables/controlSchemaTypes.ts +34 -0
- package/src/composables/experimentDesignData.ts +1 -3
- package/src/composables/flattenWorkspaceBindings.ts +104 -0
- package/src/composables/formBuilderRegistry.ts +5 -0
- package/src/composables/index.ts +43 -0
- package/src/composables/pluginWorkspaceModel.ts +182 -0
- package/src/composables/useAsync.ts +5 -1
- package/src/composables/useAuth.ts +3 -0
- package/src/composables/useBioTemplatePackWorkspace.ts +15 -9
- package/src/composables/useBioTemplatePresetWorkspace.ts +14 -15
- package/src/composables/useBioTemplateWorkspace.ts +18 -43
- package/src/composables/useCommandHistory.ts +5 -1
- package/src/composables/useDropdownState.ts +35 -5
- package/src/composables/useEventStream.ts +14 -2
- package/src/composables/useFileImport.ts +2 -7
- package/src/composables/useFocusTrap.ts +91 -0
- package/src/composables/useGeneratedAnalysis.ts +22 -10
- package/src/composables/useJobsStatusTray.ts +184 -17
- package/src/composables/useListReorder.story.vue +143 -0
- package/src/composables/useListReorder.ts +242 -0
- package/src/composables/useMenuKeyboard.ts +90 -0
- package/src/composables/useOptimisticMutation.ts +6 -16
- package/src/composables/usePluginClient.ts +47 -4
- package/src/composables/usePluginConfig.ts +252 -0
- package/src/composables/usePluginWorkspace.ts +208 -0
- package/src/composables/useRackEditor.ts +2 -11
- package/src/composables/useRequestSyncState.ts +98 -28
- package/src/composables/useResourceCrud.ts +6 -16
- package/src/composables/useRovingFocus.ts +66 -0
- package/src/composables/useScheduleDrag.ts +37 -0
- package/src/composables/useWellPainting.ts +10 -30
- package/src/composables/useWellPlateAdapter.ts +5 -1
- package/src/composables/useWellPlateEditor.ts +1 -11
- package/src/composables/useWellPlateValidation.ts +5 -1
- package/src/composables/workspaceRecipes.ts +267 -0
- package/src/index.ts +16 -0
- package/src/permissions.ts +48 -9
- package/src/stores/auth.ts +1 -0
- package/src/stores/experiment.ts +2 -7
- package/src/stores/index.ts +9 -1
- package/src/stores/settings.ts +93 -1
- package/src/styles/components/audit-trail.css +5 -5
- package/src/styles/components/batch-progress-list.css +7 -0
- package/src/styles/components/color-slider.css +2 -2
- package/src/styles/components/data-state.css +30 -0
- package/src/styles/components/dataframe.css +29 -35
- package/src/styles/components/experiment-data-viewer.css +4 -4
- package/src/styles/components/experiment-timeline.css +3 -30
- package/src/styles/components/form-builder.css +5 -5
- package/src/styles/components/lcms-sequence-table.css +16 -1
- package/src/styles/components/multi-select.css +1 -1
- package/src/styles/components/reagent-list.css +38 -31
- package/src/styles/components/sample-hierarchy-tree.css +5 -19
- package/src/styles/components/sample-selector.css +9 -2
- package/src/styles/components/schedule-calendar.css +8 -0
- package/src/styles/components/scientific-number.css +1 -1
- package/src/styles/components/secret-input.css +60 -0
- package/src/styles/components/well-plate.css +8 -0
- package/src/styles/index.css +9 -0
- package/src/styles/variables.css +29 -0
- package/src/templates/builderPresetControls.ts +1 -1
- package/src/templates/builderReadUtils.ts +1 -3
- package/src/templates/componentPlateHelpers.ts +3 -1
- package/src/templates/componentTargetResolvers.ts +1 -3
- package/src/templates/controlSchemaTargets.ts +1 -3
- package/src/templates/doseResponseAdapters.ts +2 -13
- package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
- package/src/templates/plateMapBuilder.ts +2 -2
- package/src/templates/qpcrPlateBuilder.ts +1 -1
- package/src/templates/templateValidators.ts +1 -1
- package/src/templates/timeCourseBuilder.ts +2 -2
- package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
- package/src/types/auth.ts +1 -0
- package/src/types/form-builder.ts +1 -0
- package/src/utils/color.ts +51 -0
- package/src/utils/errors.ts +29 -0
- package/src/utils/formModelSync.ts +1 -3
- package/src/utils/pluginIcon.ts +1 -3
- package/src/utils/pluginSecrets.ts +102 -0
- package/src/utils/records.ts +9 -0
- package/dist/EmptyState-p90quq8Z.js.map +0 -1
- package/dist/ExperimentPopover-tLwJ7XF4.js.map +0 -1
- package/dist/ExperimentSelectorModal-DyPAUCLw.js.map +0 -1
- package/dist/SettingsModal-BgKY93zh.js.map +0 -1
- package/dist/components-DkHddRMl.js.map +0 -1
- package/dist/composables/autoGroupConstants.d.ts +0 -1
- package/dist/composables/autoGroupGrouping.d.ts +0 -3
- package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
- package/dist/composables-C_i90sGS.js.map +0 -1
- package/dist/experiment-Cq145oEW.js.map +0 -1
- package/dist/experiment-utils-CLnzPPq5.js.map +0 -1
- package/dist/templates/builderDefaults.d.ts +0 -1
- package/dist/templates/plateGeometry.d.ts +0 -4
- package/dist/templates-DsP51i-S.js.map +0 -1
- package/dist/useApi-J6zFkHmn.js.map +0 -1
- package/dist/useControlSchema-BDx2Olha.js.map +0 -1
- package/dist/useDropdownState-DSb3BC3N.js.map +0 -1
- package/dist/useProtocolTemplates-CS_SQl6U.js.map +0 -1
- package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
- package/src/composables/autoGroupConstants.ts +0 -4
- package/src/composables/autoGroupGrouping.ts +0 -148
- package/src/composables/useAutoGroupInputSources.ts +0 -147
- package/src/templates/builderDefaults.ts +0 -11
- package/src/templates/plateGeometry.ts +0 -62
- /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → components/DataStates.test.d.ts} +0 -0
|
@@ -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.
|
|
@@ -601,6 +1009,12 @@ var PluginJobSourceDisposeError = class extends Error {
|
|
|
601
1009
|
function duplicatePluginJobId(jobId) {
|
|
602
1010
|
return /* @__PURE__ */ new Error(`Duplicate plugin job id across combined sources: ${jobId}`);
|
|
603
1011
|
}
|
|
1012
|
+
function responseJobs(response) {
|
|
1013
|
+
return "jobs" in response ? response.jobs : response;
|
|
1014
|
+
}
|
|
1015
|
+
function isSnapshotPayload(data) {
|
|
1016
|
+
return "jobs" in data && Array.isArray(data.jobs);
|
|
1017
|
+
}
|
|
604
1018
|
function errorMessage(error, fallback) {
|
|
605
1019
|
return error instanceof Error ? error.message : fallback;
|
|
606
1020
|
}
|
|
@@ -611,38 +1025,94 @@ function errorMessage(error, fallback) {
|
|
|
611
1025
|
* source. The controller never mirrors source jobs into another ref.
|
|
612
1026
|
*/
|
|
613
1027
|
function usePluginJobCenter(options = {}) {
|
|
1028
|
+
const legacyOverride = shallowRef(null);
|
|
614
1029
|
const isOpen = ref(false);
|
|
615
1030
|
const activeTab = ref("active");
|
|
616
1031
|
const isLoading = ref(false);
|
|
617
1032
|
const error = shallowRef(null);
|
|
618
1033
|
const pendingJobIds = ref(/* @__PURE__ */ new Set());
|
|
1034
|
+
const jobRevisions = /* @__PURE__ */ new Map();
|
|
1035
|
+
let stateRevision = 0;
|
|
619
1036
|
let requestGeneration = 0;
|
|
620
1037
|
let active = true;
|
|
621
1038
|
const source = computed(() => toValue(options.source));
|
|
622
|
-
const
|
|
1039
|
+
const adapter = computed(() => toValue(options.adapter));
|
|
1040
|
+
const jobs = computed(() => {
|
|
1041
|
+
const currentSource = source.value;
|
|
1042
|
+
if (currentSource) return [...toValue(currentSource.jobs)].map(normalizeJobState);
|
|
1043
|
+
const input = toValue(options.jobs);
|
|
1044
|
+
const override = legacyOverride.value;
|
|
1045
|
+
if (override && override.input === input) return override.jobs;
|
|
1046
|
+
return input ? [...input].map(normalizeJobState) : [];
|
|
1047
|
+
});
|
|
623
1048
|
const activeJobs = computed(() => jobs.value.filter((job) => isActiveJobStatus(job.status)));
|
|
624
1049
|
const historyJobs = computed(() => jobs.value.filter((job) => !isActiveJobStatus(job.status)));
|
|
625
1050
|
const deletableJobs = computed(() => historyJobs.value.filter((job) => job.can_delete));
|
|
626
1051
|
const featuredJob = computed(() => activeJobs.value[0] ?? historyJobs.value[0] ?? null);
|
|
627
|
-
const canRefresh = computed(() => Boolean(source.value?.refreshJobs));
|
|
628
|
-
const canCancel = computed(() => Boolean(source.value?.cancelJob));
|
|
629
|
-
const canDelete = computed(() => Boolean(source.value?.deleteJob));
|
|
630
|
-
const canClearFinished = computed(() => Boolean(source.value?.clearFinishedJobs || source.value?.deleteJob));
|
|
1052
|
+
const canRefresh = computed(() => Boolean(source.value?.refreshJobs || adapter.value?.listJobs));
|
|
1053
|
+
const canCancel = computed(() => Boolean(source.value?.cancelJob || adapter.value?.cancelJob));
|
|
1054
|
+
const canDelete = computed(() => Boolean(source.value?.deleteJob || adapter.value?.deleteJob));
|
|
1055
|
+
const canClearFinished = computed(() => Boolean(source.value?.clearFinishedJobs || source.value?.deleteJob || adapter.value?.clearFinishedJobs || adapter.value?.deleteJob));
|
|
1056
|
+
function bumpJobRevision(jobId) {
|
|
1057
|
+
jobRevisions.set(jobId, (jobRevisions.get(jobId) ?? 0) + 1);
|
|
1058
|
+
}
|
|
1059
|
+
function replaceLegacyJobs(nextJobs) {
|
|
1060
|
+
const normalized = nextJobs.map(normalizeJobState);
|
|
1061
|
+
new Set([...jobs.value.map((job) => job.job_id), ...normalized.map((job) => job.job_id)]).forEach(bumpJobRevision);
|
|
1062
|
+
legacyOverride.value = {
|
|
1063
|
+
input: toValue(options.jobs),
|
|
1064
|
+
jobs: normalized
|
|
1065
|
+
};
|
|
1066
|
+
stateRevision += 1;
|
|
1067
|
+
}
|
|
1068
|
+
function upsertLegacyJob(nextJob) {
|
|
1069
|
+
const normalized = normalizeJobState(nextJob);
|
|
1070
|
+
const existingIndex = jobs.value.findIndex((job) => job.job_id === normalized.job_id);
|
|
1071
|
+
const nextJobs = [...jobs.value];
|
|
1072
|
+
if (existingIndex === -1) nextJobs.unshift(normalized);
|
|
1073
|
+
else nextJobs[existingIndex] = normalized;
|
|
1074
|
+
legacyOverride.value = {
|
|
1075
|
+
input: toValue(options.jobs),
|
|
1076
|
+
jobs: nextJobs
|
|
1077
|
+
};
|
|
1078
|
+
bumpJobRevision(normalized.job_id);
|
|
1079
|
+
stateRevision += 1;
|
|
1080
|
+
}
|
|
1081
|
+
function removeLegacyJobs(jobIds) {
|
|
1082
|
+
legacyOverride.value = {
|
|
1083
|
+
input: toValue(options.jobs),
|
|
1084
|
+
jobs: jobs.value.filter((job) => !jobIds.has(job.job_id))
|
|
1085
|
+
};
|
|
1086
|
+
jobIds.forEach(bumpJobRevision);
|
|
1087
|
+
stateRevision += 1;
|
|
1088
|
+
}
|
|
631
1089
|
function setPending(jobId, pending) {
|
|
632
1090
|
const next = new Set(pendingJobIds.value);
|
|
633
1091
|
if (pending) next.add(jobId);
|
|
634
1092
|
else next.delete(jobId);
|
|
635
1093
|
pendingJobIds.value = next;
|
|
636
1094
|
}
|
|
1095
|
+
function applyStreamMessage(message) {
|
|
1096
|
+
if (!active || source.value) return;
|
|
1097
|
+
if (message.event === "snapshot" && isSnapshotPayload(message.data)) {
|
|
1098
|
+
replaceLegacyJobs(message.data.jobs);
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1101
|
+
if ((message.event === "job" || message.event === "terminal") && !isSnapshotPayload(message.data)) upsertLegacyJob(message.data);
|
|
1102
|
+
}
|
|
637
1103
|
async function refresh() {
|
|
638
|
-
const
|
|
639
|
-
|
|
1104
|
+
const currentSource = source.value;
|
|
1105
|
+
const listJobs = currentSource?.refreshJobs ?? adapter.value?.listJobs;
|
|
1106
|
+
if (!listJobs) return false;
|
|
640
1107
|
const generation = ++requestGeneration;
|
|
1108
|
+
const revision = stateRevision;
|
|
641
1109
|
isLoading.value = true;
|
|
642
1110
|
error.value = null;
|
|
643
1111
|
try {
|
|
644
|
-
await
|
|
645
|
-
|
|
1112
|
+
const response = await listJobs();
|
|
1113
|
+
if (!active || generation !== requestGeneration || revision !== stateRevision) return false;
|
|
1114
|
+
if (!currentSource && response) replaceLegacyJobs(responseJobs(response));
|
|
1115
|
+
return true;
|
|
646
1116
|
} catch (cause) {
|
|
647
1117
|
if (active && generation === requestGeneration) error.value = errorMessage(cause, "Failed to load jobs");
|
|
648
1118
|
return false;
|
|
@@ -652,12 +1122,17 @@ function usePluginJobCenter(options = {}) {
|
|
|
652
1122
|
}
|
|
653
1123
|
async function cancelJob(job) {
|
|
654
1124
|
const sourceCancel = source.value?.cancelJob;
|
|
655
|
-
|
|
1125
|
+
const adapterCancel = adapter.value?.cancelJob;
|
|
1126
|
+
if (!job.can_cancel || !sourceCancel && !adapterCancel || pendingJobIds.value.has(job.job_id)) return false;
|
|
1127
|
+
const revision = jobRevisions.get(job.job_id) ?? 0;
|
|
656
1128
|
setPending(job.job_id, true);
|
|
657
1129
|
error.value = null;
|
|
658
1130
|
try {
|
|
659
|
-
await sourceCancel(job.job_id);
|
|
660
|
-
return
|
|
1131
|
+
const updated = sourceCancel ? await sourceCancel(job.job_id) : await adapterCancel(job);
|
|
1132
|
+
if (!active) return false;
|
|
1133
|
+
if (!sourceCancel && revision === (jobRevisions.get(job.job_id) ?? 0)) if (updated) upsertLegacyJob(updated);
|
|
1134
|
+
else await refresh();
|
|
1135
|
+
return true;
|
|
661
1136
|
} catch (cause) {
|
|
662
1137
|
if (active) error.value = errorMessage(cause, "Failed to cancel job");
|
|
663
1138
|
return false;
|
|
@@ -667,12 +1142,16 @@ function usePluginJobCenter(options = {}) {
|
|
|
667
1142
|
}
|
|
668
1143
|
async function deleteJob(job) {
|
|
669
1144
|
const sourceDelete = source.value?.deleteJob;
|
|
670
|
-
|
|
1145
|
+
const adapterDelete = adapter.value?.deleteJob;
|
|
1146
|
+
if (!job.can_delete || !sourceDelete && !adapterDelete || pendingJobIds.value.has(job.job_id)) return false;
|
|
671
1147
|
setPending(job.job_id, true);
|
|
672
1148
|
error.value = null;
|
|
673
1149
|
try {
|
|
674
|
-
const deleted = await sourceDelete(job.job_id);
|
|
675
|
-
|
|
1150
|
+
const deleted = sourceDelete ? await sourceDelete(job.job_id) : await adapterDelete(job);
|
|
1151
|
+
if (!active) return false;
|
|
1152
|
+
if (!sourceDelete) if (deleted === false) await refresh();
|
|
1153
|
+
else removeLegacyJobs(new Set([job.job_id]));
|
|
1154
|
+
return deleted !== false;
|
|
676
1155
|
} catch (cause) {
|
|
677
1156
|
if (active) error.value = errorMessage(cause, "Failed to delete job");
|
|
678
1157
|
return false;
|
|
@@ -692,12 +1171,27 @@ function usePluginJobCenter(options = {}) {
|
|
|
692
1171
|
return typeof deleted !== "number" || deleted === targets.length;
|
|
693
1172
|
}
|
|
694
1173
|
if (currentSource?.deleteJob) return (await Promise.all(targets.map((job) => deleteJob(job)))).every(Boolean);
|
|
695
|
-
|
|
1174
|
+
const currentAdapter = adapter.value;
|
|
1175
|
+
if (currentAdapter?.clearFinishedJobs) {
|
|
1176
|
+
const deleted = await currentAdapter.clearFinishedJobs(targets);
|
|
1177
|
+
if (!active) return false;
|
|
1178
|
+
if (typeof deleted === "number" && deleted !== targets.length) {
|
|
1179
|
+
await refresh();
|
|
1180
|
+
return false;
|
|
1181
|
+
}
|
|
1182
|
+
removeLegacyJobs(new Set(targets.map((job) => job.job_id)));
|
|
1183
|
+
return true;
|
|
1184
|
+
}
|
|
1185
|
+
if (!currentAdapter?.deleteJob) return false;
|
|
1186
|
+
return (await Promise.all(targets.map((job) => deleteJob(job)))).every(Boolean);
|
|
696
1187
|
} catch (cause) {
|
|
697
1188
|
if (active) error.value = errorMessage(cause, "Failed to clear jobs");
|
|
698
1189
|
return false;
|
|
699
1190
|
}
|
|
700
1191
|
}
|
|
1192
|
+
if (options.eventStream !== void 0) watch(() => toValue(options.eventStream)?.lastMessage.value ?? null, (message) => {
|
|
1193
|
+
if (message) applyStreamMessage(message);
|
|
1194
|
+
}, { immediate: true });
|
|
701
1195
|
onMounted(() => {
|
|
702
1196
|
if (options.loadOnMount !== false) refresh();
|
|
703
1197
|
});
|
|
@@ -730,12 +1224,17 @@ function usePluginJobCenter(options = {}) {
|
|
|
730
1224
|
isOpen.value = !isOpen.value;
|
|
731
1225
|
},
|
|
732
1226
|
refresh,
|
|
1227
|
+
applyStreamMessage,
|
|
733
1228
|
cancelJob,
|
|
734
1229
|
deleteJob,
|
|
735
1230
|
clearFinished,
|
|
736
1231
|
isPending: (job) => pendingJobIds.value.has(job.job_id)
|
|
737
1232
|
};
|
|
738
1233
|
}
|
|
1234
|
+
/** @deprecated Use `usePluginJobCenter()` for the plugin job-center controller. */
|
|
1235
|
+
function useJobsStatusTray(options = {}) {
|
|
1236
|
+
return usePluginJobCenter(options);
|
|
1237
|
+
}
|
|
739
1238
|
//#endregion
|
|
740
1239
|
//#region src/composables/useDoseCalculator.ts
|
|
741
1240
|
var VOLUME_UNITS = [
|
|
@@ -983,18 +1482,153 @@ function useDoseCalculator() {
|
|
|
983
1482
|
};
|
|
984
1483
|
}
|
|
985
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
|
|
986
1631
|
//#region src/composables/useWellPlateEditor.ts
|
|
987
|
-
var DEFAULT_PALETTE = [
|
|
988
|
-
"#3B82F6",
|
|
989
|
-
"#10B981",
|
|
990
|
-
"#EF4444",
|
|
991
|
-
"#F59E0B",
|
|
992
|
-
"#8B5CF6",
|
|
993
|
-
"#F97316",
|
|
994
|
-
"#06B6D4",
|
|
995
|
-
"#14B8A6",
|
|
996
|
-
"#6B7280"
|
|
997
|
-
];
|
|
998
1632
|
var MAX_HISTORY = 50;
|
|
999
1633
|
function createEmptyPlate(name, format, id) {
|
|
1000
1634
|
return {
|
|
@@ -1078,7 +1712,7 @@ function useWellPlateEditor(initialState, options = {}) {
|
|
|
1078
1712
|
const sample = {
|
|
1079
1713
|
id: generateSampleId(),
|
|
1080
1714
|
name,
|
|
1081
|
-
color: color ||
|
|
1715
|
+
color: color || SAMPLE_COLOR_SCALE[internalState.value.samples.length % SAMPLE_COLOR_SCALE.length],
|
|
1082
1716
|
count: 0
|
|
1083
1717
|
};
|
|
1084
1718
|
internalState.value.samples.push(sample);
|
|
@@ -1186,7 +1820,7 @@ function useWellPlateEditor(initialState, options = {}) {
|
|
|
1186
1820
|
if (sampleId && !sampleMap.has(sampleId)) sampleMap.set(sampleId, {
|
|
1187
1821
|
id: sampleId,
|
|
1188
1822
|
name: sampleName || sampleId,
|
|
1189
|
-
color:
|
|
1823
|
+
color: SAMPLE_COLOR_SCALE[sampleMap.size % SAMPLE_COLOR_SCALE.length],
|
|
1190
1824
|
count: 0
|
|
1191
1825
|
});
|
|
1192
1826
|
const plate = plateMap.get(plateName);
|
|
@@ -2179,9 +2813,6 @@ function splitByTokenLength(classes, tokenized) {
|
|
|
2179
2813
|
}
|
|
2180
2814
|
//#endregion
|
|
2181
2815
|
//#region src/composables/experimentDesignData.ts
|
|
2182
|
-
function isRecord(value) {
|
|
2183
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2184
|
-
}
|
|
2185
2816
|
function isPlatformDesignDataResponse(value) {
|
|
2186
2817
|
return "data" in value && ("experiment_id" in value || "plugin_id" in value || "schema_version" in value || "updated_at" in value);
|
|
2187
2818
|
}
|
|
@@ -2895,7 +3526,7 @@ function useFileImport(options = {}) {
|
|
|
2895
3526
|
result.value = parsed;
|
|
2896
3527
|
return parsed;
|
|
2897
3528
|
} catch (err) {
|
|
2898
|
-
error.value = readErrorMessage(err);
|
|
3529
|
+
error.value = readErrorMessage(err, "Failed to import file.");
|
|
2899
3530
|
throw err;
|
|
2900
3531
|
} finally {
|
|
2901
3532
|
loading.value = false;
|
|
@@ -3005,108 +3636,6 @@ function formatBytes(bytes) {
|
|
|
3005
3636
|
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
3006
3637
|
return `${Math.round(bytes / (1024 * 1024))} MB`;
|
|
3007
3638
|
}
|
|
3008
|
-
function readErrorMessage(value) {
|
|
3009
|
-
if (value instanceof Error && value.message) return value.message;
|
|
3010
|
-
if (typeof value === "string" && value.trim()) return value;
|
|
3011
|
-
return "Failed to import file.";
|
|
3012
|
-
}
|
|
3013
|
-
//#endregion
|
|
3014
|
-
//#region src/utils/color.ts
|
|
3015
|
-
var HEX_RE = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i;
|
|
3016
|
-
function clamp(n, min, max) {
|
|
3017
|
-
return Math.min(max, Math.max(min, n));
|
|
3018
|
-
}
|
|
3019
|
-
function hexToHsl(hex) {
|
|
3020
|
-
const match = HEX_RE.exec(hex.trim());
|
|
3021
|
-
if (!match) return {
|
|
3022
|
-
h: 0,
|
|
3023
|
-
s: 0,
|
|
3024
|
-
l: 50
|
|
3025
|
-
};
|
|
3026
|
-
let raw = match[1];
|
|
3027
|
-
if (raw.length === 3) raw = raw.split("").map((c) => c + c).join("");
|
|
3028
|
-
const r = parseInt(raw.slice(0, 2), 16) / 255;
|
|
3029
|
-
const g = parseInt(raw.slice(2, 4), 16) / 255;
|
|
3030
|
-
const b = parseInt(raw.slice(4, 6), 16) / 255;
|
|
3031
|
-
const max = Math.max(r, g, b);
|
|
3032
|
-
const min = Math.min(r, g, b);
|
|
3033
|
-
const delta = max - min;
|
|
3034
|
-
let h = 0;
|
|
3035
|
-
if (delta !== 0) if (max === r) h = (g - b) / delta % 6;
|
|
3036
|
-
else if (max === g) h = (b - r) / delta + 2;
|
|
3037
|
-
else h = (r - g) / delta + 4;
|
|
3038
|
-
h = (h * 60 + 360) % 360;
|
|
3039
|
-
const l = (max + min) / 2;
|
|
3040
|
-
const s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
|
|
3041
|
-
return {
|
|
3042
|
-
h,
|
|
3043
|
-
s: s * 100,
|
|
3044
|
-
l: l * 100
|
|
3045
|
-
};
|
|
3046
|
-
}
|
|
3047
|
-
function hslToHex(h, s, l) {
|
|
3048
|
-
const sNorm = clamp(s, 0, 100) / 100;
|
|
3049
|
-
const lNorm = clamp(l, 0, 100) / 100;
|
|
3050
|
-
const hNorm = (h % 360 + 360) % 360;
|
|
3051
|
-
const c = (1 - Math.abs(2 * lNorm - 1)) * sNorm;
|
|
3052
|
-
const x = c * (1 - Math.abs(hNorm / 60 % 2 - 1));
|
|
3053
|
-
const m = lNorm - c / 2;
|
|
3054
|
-
let r = 0, g = 0, b = 0;
|
|
3055
|
-
if (hNorm < 60) [r, g, b] = [
|
|
3056
|
-
c,
|
|
3057
|
-
x,
|
|
3058
|
-
0
|
|
3059
|
-
];
|
|
3060
|
-
else if (hNorm < 120) [r, g, b] = [
|
|
3061
|
-
x,
|
|
3062
|
-
c,
|
|
3063
|
-
0
|
|
3064
|
-
];
|
|
3065
|
-
else if (hNorm < 180) [r, g, b] = [
|
|
3066
|
-
0,
|
|
3067
|
-
c,
|
|
3068
|
-
x
|
|
3069
|
-
];
|
|
3070
|
-
else if (hNorm < 240) [r, g, b] = [
|
|
3071
|
-
0,
|
|
3072
|
-
x,
|
|
3073
|
-
c
|
|
3074
|
-
];
|
|
3075
|
-
else if (hNorm < 300) [r, g, b] = [
|
|
3076
|
-
x,
|
|
3077
|
-
0,
|
|
3078
|
-
c
|
|
3079
|
-
];
|
|
3080
|
-
else [r, g, b] = [
|
|
3081
|
-
c,
|
|
3082
|
-
0,
|
|
3083
|
-
x
|
|
3084
|
-
];
|
|
3085
|
-
const toHex = (n) => Math.round((n + m) * 255).toString(16).padStart(2, "0");
|
|
3086
|
-
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
3087
|
-
}
|
|
3088
|
-
/**
|
|
3089
|
-
* Derive a same-hue-family shade of `parentHex` for child at `index` of `total`.
|
|
3090
|
-
*
|
|
3091
|
-
* Lightness is distributed evenly within [35, 75] so all children remain
|
|
3092
|
-
* readable on light/dark backgrounds. Hue and saturation are inherited from
|
|
3093
|
-
* the parent. With `total <= 1`, returns the parent unchanged.
|
|
3094
|
-
*
|
|
3095
|
-
* Children are ordered light → dark by index, so index 0 is the brightest
|
|
3096
|
-
* sibling and index `total - 1` is the darkest.
|
|
3097
|
-
*/
|
|
3098
|
-
function deriveShade(parentHex, index, total) {
|
|
3099
|
-
if (total <= 1) return parentHex;
|
|
3100
|
-
const { h, s, l } = hexToHsl(parentHex);
|
|
3101
|
-
const L_MIN = 35;
|
|
3102
|
-
const L_MAX = 75;
|
|
3103
|
-
const spread = Math.min(L_MAX - L_MIN, 40);
|
|
3104
|
-
const center = clamp(l, L_MIN + spread / 2, L_MAX - spread / 2);
|
|
3105
|
-
const top = center + spread / 2;
|
|
3106
|
-
const bot = center - spread / 2;
|
|
3107
|
-
const childL = top - (total === 1 ? .5 : index / (total - 1)) * (top - bot);
|
|
3108
|
-
return hslToHex(h, clamp(s, 35, 100), childL);
|
|
3109
|
-
}
|
|
3110
3639
|
//#endregion
|
|
3111
3640
|
//#region src/utils/sampleGroupPath.ts
|
|
3112
3641
|
/** Split a group name into normalized hierarchy segments. */
|
|
@@ -3566,6 +4095,30 @@ function useScheduleDrag(options) {
|
|
|
3566
4095
|
else if ((state.type === "resize-top" || state.type === "resize-bottom") && state.event && options.onResizeComplete) options.onResizeComplete(state.event, g.start, g.end);
|
|
3567
4096
|
cleanup();
|
|
3568
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
|
+
}
|
|
3569
4122
|
function addListeners() {
|
|
3570
4123
|
document.addEventListener("pointermove", onPointerMove);
|
|
3571
4124
|
document.addEventListener("pointerup", onPointerUp);
|
|
@@ -3583,7 +4136,8 @@ function useScheduleDrag(options) {
|
|
|
3583
4136
|
ghost,
|
|
3584
4137
|
startCreate,
|
|
3585
4138
|
startMove,
|
|
3586
|
-
startResize
|
|
4139
|
+
startResize,
|
|
4140
|
+
nudgeEvent
|
|
3587
4141
|
};
|
|
3588
4142
|
}
|
|
3589
4143
|
function snapMinutes(minutes, step) {
|
|
@@ -3940,6 +4494,57 @@ function useBioTemplateComponents(target) {
|
|
|
3940
4494
|
};
|
|
3941
4495
|
}
|
|
3942
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
|
|
3943
4548
|
//#region src/composables/useBioTemplateWorkspace.ts
|
|
3944
4549
|
/** One-stop wiring for BioTemplateRenderer, FormBuilder, AppSidebar, and template-aware SDK components. */
|
|
3945
4550
|
function useBioTemplateWorkspace(target, options = {}) {
|
|
@@ -3947,21 +4552,25 @@ function useBioTemplateWorkspace(target, options = {}) {
|
|
|
3947
4552
|
const workspace = useControlWorkspace(controls.controls, options);
|
|
3948
4553
|
const components = useBioTemplateComponents(target);
|
|
3949
4554
|
const renderer = isTemplateObjectTarget(target) ? { target } : null;
|
|
3950
|
-
const
|
|
3951
|
-
renderer,
|
|
3952
|
-
form: workspace.bindings.form,
|
|
3953
|
-
sidebar: workspace.bindings.sidebar,
|
|
3954
|
-
topBar: workspace.bindings.topBar,
|
|
3955
|
-
topBarSettings: workspace.bindings.topBarSettings,
|
|
3956
|
-
pillNav: workspace.bindings.pillNav,
|
|
4555
|
+
const componentBindings = flattenWorkspaceComponentBindings({
|
|
3957
4556
|
componentBindings: components.bindings,
|
|
3958
4557
|
componentBindingsById: components.componentBindingsById,
|
|
4558
|
+
componentImports: components.imports,
|
|
3959
4559
|
componentProps: components.componentProps,
|
|
3960
4560
|
componentPropsById: components.componentPropsById,
|
|
3961
4561
|
componentPropsByComponent: components.componentPropsByComponent,
|
|
3962
4562
|
componentSnippets: components.snippets,
|
|
3963
4563
|
componentUsage: components.usage,
|
|
3964
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
|
|
3965
4574
|
};
|
|
3966
4575
|
return {
|
|
3967
4576
|
target,
|
|
@@ -3978,15 +4587,7 @@ function useBioTemplateWorkspace(target, options = {}) {
|
|
|
3978
4587
|
topBarSettings: workspace.topBarSettings,
|
|
3979
4588
|
bindings,
|
|
3980
4589
|
renderer,
|
|
3981
|
-
componentBindings
|
|
3982
|
-
componentBindingsById: components.componentBindingsById,
|
|
3983
|
-
componentImports: components.imports,
|
|
3984
|
-
componentProps: components.componentProps,
|
|
3985
|
-
componentPropsById: components.componentPropsById,
|
|
3986
|
-
componentPropsByComponent: components.componentPropsByComponent,
|
|
3987
|
-
componentSnippets: components.snippets,
|
|
3988
|
-
componentUsage: components.usage,
|
|
3989
|
-
getComponentProps: components.getComponentProps
|
|
4590
|
+
...componentBindings
|
|
3990
4591
|
};
|
|
3991
4592
|
}
|
|
3992
4593
|
function isTemplateObjectTarget(target) {
|
|
@@ -4027,14 +4628,7 @@ function useBioTemplatePackWorkspace(packId, options = {}) {
|
|
|
4027
4628
|
const pillNav = computed(() => workspace.value.pillNav);
|
|
4028
4629
|
const topBarSettings = computed(() => workspace.value.topBarSettings);
|
|
4029
4630
|
const bindings = computed(() => workspace.value.bindings);
|
|
4030
|
-
const componentBindings =
|
|
4031
|
-
const componentBindingsById = computed(() => workspace.value.componentBindingsById);
|
|
4032
|
-
const componentImports = computed(() => workspace.value.componentImports);
|
|
4033
|
-
const componentProps = computed(() => workspace.value.componentProps);
|
|
4034
|
-
const componentPropsById = computed(() => workspace.value.componentPropsById);
|
|
4035
|
-
const componentPropsByComponent = computed(() => workspace.value.componentPropsByComponent);
|
|
4036
|
-
const componentSnippets = computed(() => workspace.value.componentSnippets);
|
|
4037
|
-
const componentUsage = computed(() => workspace.value.componentUsage);
|
|
4631
|
+
const { componentBindings, componentBindingsById, componentImports, componentProps, componentPropsById, componentPropsByComponent, componentSnippets, componentUsage, getComponentProps: getWorkspaceComponentProps } = liftWorkspaceComponentBindings(workspace);
|
|
4038
4632
|
watch(collection, (value) => {
|
|
4039
4633
|
workspaceRef.value = createWorkspace(value);
|
|
4040
4634
|
});
|
|
@@ -4077,7 +4671,7 @@ function useBioTemplatePackWorkspace(packId, options = {}) {
|
|
|
4077
4671
|
componentPropsByComponent,
|
|
4078
4672
|
componentSnippets,
|
|
4079
4673
|
componentUsage,
|
|
4080
|
-
getComponentProps:
|
|
4674
|
+
getComponentProps: getWorkspaceComponentProps,
|
|
4081
4675
|
applyCollection,
|
|
4082
4676
|
resetToDefaultCollection,
|
|
4083
4677
|
save: templateCollection.save,
|
|
@@ -4108,14 +4702,7 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
|
|
|
4108
4702
|
const collection = templateCollection.templateCollection;
|
|
4109
4703
|
const workspace = computed(() => useBioTemplateWorkspace(collection.value, resolvedControlOptions));
|
|
4110
4704
|
const renderer = computed(() => ({ target: collection.value }));
|
|
4111
|
-
const componentBindings =
|
|
4112
|
-
const componentBindingsById = computed(() => workspace.value.componentBindingsById);
|
|
4113
|
-
const componentImports = computed(() => workspace.value.componentImports);
|
|
4114
|
-
const componentProps = computed(() => workspace.value.componentProps);
|
|
4115
|
-
const componentPropsById = computed(() => workspace.value.componentPropsById);
|
|
4116
|
-
const componentPropsByComponent = computed(() => workspace.value.componentPropsByComponent);
|
|
4117
|
-
const componentSnippets = computed(() => workspace.value.componentSnippets);
|
|
4118
|
-
const componentUsage = computed(() => workspace.value.componentUsage);
|
|
4705
|
+
const { componentBindings, componentBindingsById, componentImports, componentProps, componentPropsById, componentPropsByComponent, componentSnippets, componentUsage, getComponentProps } = liftWorkspaceComponentBindings(workspace);
|
|
4119
4706
|
const form = reactive({
|
|
4120
4707
|
...controls.form,
|
|
4121
4708
|
modelValue: controlValues.value,
|
|
@@ -4148,9 +4735,6 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
|
|
|
4148
4735
|
onPillSelect: pillNav.onSelect,
|
|
4149
4736
|
...topBarSettings
|
|
4150
4737
|
}));
|
|
4151
|
-
function getComponentProps(component, options) {
|
|
4152
|
-
return workspace.value.getComponentProps(component, options);
|
|
4153
|
-
}
|
|
4154
4738
|
const bindings = {
|
|
4155
4739
|
renderer,
|
|
4156
4740
|
form,
|
|
@@ -4276,36 +4860,6 @@ var SLOT_CYCLE = [
|
|
|
4276
4860
|
"B",
|
|
4277
4861
|
"Y"
|
|
4278
4862
|
];
|
|
4279
|
-
var PLATE_CONFIGS = {
|
|
4280
|
-
6: {
|
|
4281
|
-
rows: 2,
|
|
4282
|
-
cols: 3
|
|
4283
|
-
},
|
|
4284
|
-
12: {
|
|
4285
|
-
rows: 3,
|
|
4286
|
-
cols: 4
|
|
4287
|
-
},
|
|
4288
|
-
24: {
|
|
4289
|
-
rows: 4,
|
|
4290
|
-
cols: 6
|
|
4291
|
-
},
|
|
4292
|
-
48: {
|
|
4293
|
-
rows: 6,
|
|
4294
|
-
cols: 8
|
|
4295
|
-
},
|
|
4296
|
-
54: {
|
|
4297
|
-
rows: 6,
|
|
4298
|
-
cols: 9
|
|
4299
|
-
},
|
|
4300
|
-
96: {
|
|
4301
|
-
rows: 8,
|
|
4302
|
-
cols: 12
|
|
4303
|
-
},
|
|
4304
|
-
384: {
|
|
4305
|
-
rows: 16,
|
|
4306
|
-
cols: 24
|
|
4307
|
-
}
|
|
4308
|
-
};
|
|
4309
4863
|
var globalIdCounter = 0;
|
|
4310
4864
|
function generateId() {
|
|
4311
4865
|
globalIdCounter++;
|
|
@@ -4389,7 +4943,7 @@ function useRackEditor(initialRacks, options) {
|
|
|
4389
4943
|
if (!config) return;
|
|
4390
4944
|
let counter = 1;
|
|
4391
4945
|
for (let row = 0; row < config.rows; row++) for (let col = 0; col < config.cols; col++) {
|
|
4392
|
-
const wellId = `${
|
|
4946
|
+
const wellId = `${rowLabel(row)}${col + 1}`;
|
|
4393
4947
|
if (!rack.wells[wellId]?.sampleType) {
|
|
4394
4948
|
const paddedNum = String(counter).padStart(3, "0");
|
|
4395
4949
|
rack.wells[wellId] = {
|
|
@@ -5053,6 +5607,6 @@ function useProtocolTemplates() {
|
|
|
5053
5607
|
};
|
|
5054
5608
|
}
|
|
5055
5609
|
//#endregion
|
|
5056
|
-
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 };
|
|
5057
5611
|
|
|
5058
|
-
//# sourceMappingURL=useProtocolTemplates-
|
|
5612
|
+
//# sourceMappingURL=useProtocolTemplates-BmX_iVBR.js.map
|