@morscherlab/mint-sdk 1.0.0-alpha.2
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 +326 -0
- package/dist/__stories__/experiment-helpers.d.ts +25 -0
- package/dist/__tests__/components/AppLayout.test.d.ts +1 -0
- package/dist/__tests__/components/AppSidebar.test.d.ts +1 -0
- package/dist/__tests__/components/AppTopBar.test.d.ts +1 -0
- package/dist/__tests__/components/BaseInput.test.d.ts +1 -0
- package/dist/__tests__/components/BasePill.test.d.ts +1 -0
- package/dist/__tests__/components/Calendar.test.d.ts +1 -0
- package/dist/__tests__/components/CollapsibleCard.test.d.ts +1 -0
- package/dist/__tests__/components/DataFrame.test.d.ts +1 -0
- package/dist/__tests__/components/DropdownButton.test.d.ts +1 -0
- package/dist/__tests__/composables/formBuilderRegistry.test.d.ts +1 -0
- package/dist/__tests__/composables/useAppExperiment.test.d.ts +1 -0
- package/dist/__tests__/composables/useAuth.test.d.ts +1 -0
- package/dist/__tests__/composables/useAutoGroup.test.d.ts +1 -0
- package/dist/__tests__/composables/useExperimentData.test.d.ts +13 -0
- package/dist/__tests__/composables/useExperimentSave.test.d.ts +1 -0
- package/dist/__tests__/composables/useForm.test.d.ts +1 -0
- package/dist/__tests__/composables/useFormBuilder.test.d.ts +1 -0
- package/dist/__tests__/composables/usePlatformContext.test.d.ts +1 -0
- package/dist/__tests__/composables/usePluginApi.test.d.ts +13 -0
- package/dist/__tests__/composables/usePluginConfig.test.d.ts +14 -0
- package/dist/__tests__/utils/color.test.d.ts +1 -0
- package/dist/auth-BYmxZdJl.js +297 -0
- package/dist/auth-BYmxZdJl.js.map +1 -0
- package/dist/components/AlertBox.vue.d.ts +34 -0
- package/dist/components/AppAvatarMenu.vue.d.ts +58 -0
- package/dist/components/AppContainer.vue.d.ts +28 -0
- package/dist/components/AppLayout.vue.d.ts +31 -0
- package/dist/components/AppPageSelector.vue.d.ts +43 -0
- package/dist/components/AppPillNav.vue.d.ts +11 -0
- package/dist/components/AppPluginSwitcher.vue.d.ts +38 -0
- package/dist/components/AppSidebar.vue.d.ts +47 -0
- package/dist/components/AppTopBar.vue.d.ts +111 -0
- package/dist/components/AuditTrail.vue.d.ts +38 -0
- package/dist/components/AutoGroupModal.vue.d.ts +124 -0
- package/dist/components/Avatar.vue.d.ts +14 -0
- package/dist/components/BaseButton.vue.d.ts +37 -0
- package/dist/components/BaseCheckbox.vue.d.ts +17 -0
- package/dist/components/BaseInput.vue.d.ts +34 -0
- package/dist/components/BaseModal.vue.d.ts +46 -0
- package/dist/components/BasePill.vue.d.ts +57 -0
- package/dist/components/BaseRadioGroup.vue.d.ts +21 -0
- package/dist/components/BaseSelect.vue.d.ts +20 -0
- package/dist/components/BaseSlider.vue.d.ts +22 -0
- package/dist/components/BaseTabs.vue.d.ts +14 -0
- package/dist/components/BaseTextarea.vue.d.ts +30 -0
- package/dist/components/BaseToggle.vue.d.ts +19 -0
- package/dist/components/BatchProgressList.vue.d.ts +43 -0
- package/dist/components/Breadcrumb.vue.d.ts +33 -0
- package/dist/components/Calendar.vue.d.ts +107 -0
- package/dist/components/ChartContainer.vue.d.ts +31 -0
- package/dist/components/ChemicalFormula.vue.d.ts +8 -0
- package/dist/components/CollapsibleCard.vue.d.ts +41 -0
- package/dist/components/ColorSlider.vue.d.ts +34 -0
- package/dist/components/ConcentrationInput.vue.d.ts +25 -0
- package/dist/components/ConfirmDialog.vue.d.ts +42 -0
- package/dist/components/DataFrame.vue.d.ts +107 -0
- package/dist/components/DatePicker.vue.d.ts +25 -0
- package/dist/components/DateTimePicker.vue.d.ts +30 -0
- package/dist/components/Divider.vue.d.ts +14 -0
- package/dist/components/DoseCalculator.vue.d.ts +19 -0
- package/dist/components/DropdownButton.vue.d.ts +47 -0
- package/dist/components/EmptyState.vue.d.ts +36 -0
- package/dist/components/ExperimentCodeBadge.vue.d.ts +14 -0
- package/dist/components/ExperimentDataViewer.vue.d.ts +29 -0
- package/dist/components/ExperimentPopover.vue.d.ts +32 -0
- package/dist/components/ExperimentSelectorModal.vue.d.ts +28 -0
- package/dist/components/ExperimentTimeline.vue.d.ts +44 -0
- package/dist/components/FileUploader.vue.d.ts +40 -0
- package/dist/components/FitPanel.vue.d.ts +46 -0
- package/dist/components/FormActions.vue.d.ts +33 -0
- package/dist/components/FormBuilder.vue.d.ts +287 -0
- package/dist/components/FormField.vue.d.ts +28 -0
- package/dist/components/FormFieldRenderer.vue.d.ts +31 -0
- package/dist/components/FormSection.vue.d.ts +43 -0
- package/dist/components/FormulaInput.vue.d.ts +25 -0
- package/dist/components/GroupAssigner.vue.d.ts +25 -0
- package/dist/components/GroupingModal.vue.d.ts +12 -0
- package/dist/components/IconButton.vue.d.ts +34 -0
- package/dist/components/LoadingSpinner.vue.d.ts +12 -0
- package/dist/components/MoleculeInput.vue.d.ts +27 -0
- package/dist/components/MultiSelect.vue.d.ts +19 -0
- package/dist/components/NumberInput.vue.d.ts +22 -0
- package/dist/components/PlateMapEditor.vue.d.ts +50 -0
- package/dist/components/ProgressBar.vue.d.ts +23 -0
- package/dist/components/ProtocolStepEditor.vue.d.ts +24 -0
- package/dist/components/RackEditor.vue.d.ts +40 -0
- package/dist/components/ReagentEditor.vue.d.ts +30 -0
- package/dist/components/ReagentList.vue.d.ts +32 -0
- package/dist/components/ResourceCard.vue.d.ts +50 -0
- package/dist/components/SampleHierarchyTree.vue.d.ts +26 -0
- package/dist/components/SampleLegend.vue.d.ts +32 -0
- package/dist/components/SampleSelector.vue.d.ts +29 -0
- package/dist/components/ScheduleCalendar.vue.d.ts +110 -0
- package/dist/components/ScientificNumber.vue.d.ts +14 -0
- package/dist/components/SegmentedControl.vue.d.ts +20 -0
- package/dist/components/SequenceInput.vue.d.ts +54 -0
- package/dist/components/SettingsButton.vue.d.ts +30 -0
- package/dist/components/SettingsModal.vue.d.ts +36 -0
- package/dist/components/Skeleton.vue.d.ts +11 -0
- package/dist/components/StatusIndicator.vue.d.ts +13 -0
- package/dist/components/StepWizard.vue.d.ts +65 -0
- package/dist/components/TagsInput.vue.d.ts +39 -0
- package/dist/components/ThemeToggle.vue.d.ts +7 -0
- package/dist/components/TimePicker.vue.d.ts +29 -0
- package/dist/components/TimeRangeInput.vue.d.ts +27 -0
- package/dist/components/ToastNotification.vue.d.ts +2 -0
- package/dist/components/Tooltip.vue.d.ts +35 -0
- package/dist/components/UnitInput.vue.d.ts +39 -0
- package/dist/components/WellEditPopup.vue.d.ts +25 -0
- package/dist/components/WellPlate.vue.d.ts +73 -0
- package/dist/components/index.d.ts +87 -0
- package/dist/components/index.js +3 -0
- package/dist/components-CKf-UpGi.js +15089 -0
- package/dist/components-CKf-UpGi.js.map +1 -0
- package/dist/composables/experiment-utils.d.ts +8 -0
- package/dist/composables/formBuilderRegistry.d.ts +13 -0
- package/dist/composables/index.d.ts +28 -0
- package/dist/composables/index.js +3 -0
- package/dist/composables/useApi.d.ts +20 -0
- package/dist/composables/useAppExperiment.d.ts +37 -0
- package/dist/composables/useAsync.d.ts +128 -0
- package/dist/composables/useAuth.d.ts +47 -0
- package/dist/composables/useAutoGroup.d.ts +106 -0
- package/dist/composables/useChemicalFormula.d.ts +21 -0
- package/dist/composables/useConcentrationUnits.d.ts +29 -0
- package/dist/composables/useDoseCalculator.d.ts +58 -0
- package/dist/composables/useExperimentData.d.ts +18 -0
- package/dist/composables/useExperimentSave.d.ts +36 -0
- package/dist/composables/useExperimentSelector.d.ts +30 -0
- package/dist/composables/useForm.d.ts +92 -0
- package/dist/composables/useFormBuilder.d.ts +24 -0
- package/dist/composables/usePasskey.d.ts +10 -0
- package/dist/composables/usePlatformContext.d.ts +131 -0
- package/dist/composables/usePluginApi.d.ts +29 -0
- package/dist/composables/usePluginConfig.d.ts +13 -0
- package/dist/composables/useProtocolTemplates.d.ts +44 -0
- package/dist/composables/useRackEditor.d.ts +31 -0
- package/dist/composables/useReagentSeries.d.ts +23 -0
- package/dist/composables/useScheduleDrag.d.ts +78 -0
- package/dist/composables/useSequenceUtils.d.ts +14 -0
- package/dist/composables/useTheme.d.ts +8 -0
- package/dist/composables/useTimeUtils.d.ts +29 -0
- package/dist/composables/useToast.d.ts +22 -0
- package/dist/composables/useWellPlateEditor.d.ts +33 -0
- package/dist/composables-D0QfFzq1.js +805 -0
- package/dist/composables-D0QfFzq1.js.map +1 -0
- package/dist/histoire.setup.d.ts +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/install.d.ts +16 -0
- package/dist/install.js +23 -0
- package/dist/install.js.map +1 -0
- package/dist/stores/auth.d.ts +146 -0
- package/dist/stores/index.d.ts +2 -0
- package/dist/stores/index.js +2 -0
- package/dist/stores/settings.d.ts +75 -0
- package/dist/styles.css +29728 -0
- package/dist/tailwind.preset.d.ts +58 -0
- package/dist/tailwind.preset.js +66 -0
- package/dist/tailwind.preset.js.map +1 -0
- package/dist/types/auth.d.ts +42 -0
- package/dist/types/auto-group.d.ts +34 -0
- package/dist/types/components.d.ts +528 -0
- package/dist/types/form-builder.d.ts +167 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js +0 -0
- package/dist/types/platform.d.ts +75 -0
- package/dist/useScheduleDrag-DAJueTbK.js +7181 -0
- package/dist/useScheduleDrag-DAJueTbK.js.map +1 -0
- package/dist/utils/color.d.ts +24 -0
- package/package.json +114 -0
- package/src/__stories__/experiment-helpers.ts +83 -0
- package/src/__tests__/components/AppLayout.test.ts +163 -0
- package/src/__tests__/components/AppSidebar.test.ts +292 -0
- package/src/__tests__/components/AppTopBar.test.ts +683 -0
- package/src/__tests__/components/BaseInput.test.ts +99 -0
- package/src/__tests__/components/BasePill.test.ts +291 -0
- package/src/__tests__/components/Calendar.test.ts +566 -0
- package/src/__tests__/components/CollapsibleCard.test.ts +524 -0
- package/src/__tests__/components/DataFrame.test.ts +767 -0
- package/src/__tests__/components/DropdownButton.test.ts +471 -0
- package/src/__tests__/composables/formBuilderRegistry.test.ts +187 -0
- package/src/__tests__/composables/useAppExperiment.test.ts +560 -0
- package/src/__tests__/composables/useAuth.test.ts +188 -0
- package/src/__tests__/composables/useAutoGroup.test.ts +860 -0
- package/src/__tests__/composables/useExperimentData.test.ts +127 -0
- package/src/__tests__/composables/useExperimentSave.test.ts +347 -0
- package/src/__tests__/composables/useForm.test.ts +205 -0
- package/src/__tests__/composables/useFormBuilder.test.ts +917 -0
- package/src/__tests__/composables/usePlatformContext.test.ts +116 -0
- package/src/__tests__/composables/usePluginApi.test.ts +81 -0
- package/src/__tests__/composables/usePluginConfig.test.ts +176 -0
- package/src/__tests__/utils/color.test.ts +96 -0
- package/src/components/AlertBox.story.vue +204 -0
- package/src/components/AlertBox.vue +88 -0
- package/src/components/AppAvatarMenu.story.vue +155 -0
- package/src/components/AppAvatarMenu.vue +184 -0
- package/src/components/AppContainer.story.vue +104 -0
- package/src/components/AppContainer.vue +34 -0
- package/src/components/AppLayout.story.vue +292 -0
- package/src/components/AppLayout.vue +75 -0
- package/src/components/AppPageSelector.vue +159 -0
- package/src/components/AppPillNav.vue +66 -0
- package/src/components/AppPluginSwitcher.vue +241 -0
- package/src/components/AppSidebar.story.vue +309 -0
- package/src/components/AppSidebar.vue +119 -0
- package/src/components/AppTopBar.story.vue +304 -0
- package/src/components/AppTopBar.vue +661 -0
- package/src/components/AuditTrail.story.vue +163 -0
- package/src/components/AuditTrail.vue +151 -0
- package/src/components/AutoGroupModal.story.vue +273 -0
- package/src/components/AutoGroupModal.vue +566 -0
- package/src/components/Avatar.story.vue +115 -0
- package/src/components/Avatar.vue +79 -0
- package/src/components/BaseButton.story.vue +96 -0
- package/src/components/BaseButton.vue +73 -0
- package/src/components/BaseCheckbox.story.vue +73 -0
- package/src/components/BaseCheckbox.vue +69 -0
- package/src/components/BaseInput.story.vue +98 -0
- package/src/components/BaseInput.vue +74 -0
- package/src/components/BaseModal.story.vue +237 -0
- package/src/components/BaseModal.vue +182 -0
- package/src/components/BasePill.story.vue +142 -0
- package/src/components/BasePill.vue +89 -0
- package/src/components/BaseRadioGroup.story.vue +145 -0
- package/src/components/BaseRadioGroup.vue +124 -0
- package/src/components/BaseSelect.story.vue +120 -0
- package/src/components/BaseSelect.vue +71 -0
- package/src/components/BaseSlider.story.vue +122 -0
- package/src/components/BaseSlider.vue +126 -0
- package/src/components/BaseTabs.story.vue +127 -0
- package/src/components/BaseTabs.vue +59 -0
- package/src/components/BaseTextarea.story.vue +91 -0
- package/src/components/BaseTextarea.vue +62 -0
- package/src/components/BaseToggle.story.vue +81 -0
- package/src/components/BaseToggle.vue +76 -0
- package/src/components/BatchProgressList.story.vue +92 -0
- package/src/components/BatchProgressList.vue +184 -0
- package/src/components/Breadcrumb.story.vue +106 -0
- package/src/components/Breadcrumb.vue +75 -0
- package/src/components/Calendar.story.vue +106 -0
- package/src/components/Calendar.vue +363 -0
- package/src/components/ChartContainer.story.vue +113 -0
- package/src/components/ChartContainer.vue +64 -0
- package/src/components/ChemicalFormula.story.vue +102 -0
- package/src/components/ChemicalFormula.vue +39 -0
- package/src/components/CollapsibleCard.story.vue +135 -0
- package/src/components/CollapsibleCard.vue +167 -0
- package/src/components/ColorSlider.story.vue +120 -0
- package/src/components/ColorSlider.vue +164 -0
- package/src/components/ConcentrationInput.story.vue +77 -0
- package/src/components/ConcentrationInput.vue +185 -0
- package/src/components/ConfirmDialog.story.vue +248 -0
- package/src/components/ConfirmDialog.vue +93 -0
- package/src/components/DataFrame.story.vue +148 -0
- package/src/components/DataFrame.vue +419 -0
- package/src/components/DatePicker.story.vue +119 -0
- package/src/components/DatePicker.vue +330 -0
- package/src/components/DateTimePicker.story.vue +112 -0
- package/src/components/DateTimePicker.vue +392 -0
- package/src/components/Divider.story.vue +80 -0
- package/src/components/Divider.vue +49 -0
- package/src/components/DoseCalculator.story.vue +68 -0
- package/src/components/DoseCalculator.vue +476 -0
- package/src/components/DropdownButton.story.vue +102 -0
- package/src/components/DropdownButton.vue +181 -0
- package/src/components/EmptyState.story.vue +135 -0
- package/src/components/EmptyState.vue +69 -0
- package/src/components/ExperimentCodeBadge.story.vue +77 -0
- package/src/components/ExperimentCodeBadge.vue +64 -0
- package/src/components/ExperimentDataViewer.story.vue +174 -0
- package/src/components/ExperimentDataViewer.vue +288 -0
- package/src/components/ExperimentPopover.story.vue +384 -0
- package/src/components/ExperimentPopover.vue +241 -0
- package/src/components/ExperimentSelectorModal.story.vue +391 -0
- package/src/components/ExperimentSelectorModal.vue +387 -0
- package/src/components/ExperimentTimeline.story.vue +161 -0
- package/src/components/ExperimentTimeline.vue +382 -0
- package/src/components/FileUploader.story.vue +107 -0
- package/src/components/FileUploader.vue +386 -0
- package/src/components/FitPanel.story.vue +125 -0
- package/src/components/FitPanel.vue +120 -0
- package/src/components/FormActions.vue +92 -0
- package/src/components/FormBuilder.vue +214 -0
- package/src/components/FormField.story.vue +132 -0
- package/src/components/FormField.vue +59 -0
- package/src/components/FormFieldRenderer.vue +58 -0
- package/src/components/FormSection.vue +90 -0
- package/src/components/FormulaInput.story.vue +96 -0
- package/src/components/FormulaInput.vue +125 -0
- package/src/components/GroupAssigner.story.vue +83 -0
- package/src/components/GroupAssigner.vue +284 -0
- package/src/components/GroupingModal.story.vue +52 -0
- package/src/components/GroupingModal.vue +422 -0
- package/src/components/IconButton.story.vue +135 -0
- package/src/components/IconButton.vue +73 -0
- package/src/components/LoadingSpinner.story.vue +70 -0
- package/src/components/LoadingSpinner.vue +50 -0
- package/src/components/MoleculeInput.story.vue +66 -0
- package/src/components/MoleculeInput.vue +426 -0
- package/src/components/MultiSelect.story.vue +132 -0
- package/src/components/MultiSelect.vue +118 -0
- package/src/components/NumberInput.story.vue +122 -0
- package/src/components/NumberInput.vue +160 -0
- package/src/components/PlateMapEditor.story.vue +92 -0
- package/src/components/PlateMapEditor.vue +513 -0
- package/src/components/ProgressBar.story.vue +148 -0
- package/src/components/ProgressBar.vue +114 -0
- package/src/components/ProtocolStepEditor.story.vue +69 -0
- package/src/components/ProtocolStepEditor.vue +522 -0
- package/src/components/RackEditor.story.vue +100 -0
- package/src/components/RackEditor.vue +371 -0
- package/src/components/ReagentEditor.story.vue +153 -0
- package/src/components/ReagentEditor.vue +418 -0
- package/src/components/ReagentList.story.vue +137 -0
- package/src/components/ReagentList.vue +463 -0
- package/src/components/ResourceCard.story.vue +150 -0
- package/src/components/ResourceCard.vue +161 -0
- package/src/components/SampleHierarchyTree.story.vue +161 -0
- package/src/components/SampleHierarchyTree.vue +256 -0
- package/src/components/SampleLegend.story.vue +91 -0
- package/src/components/SampleLegend.vue +119 -0
- package/src/components/SampleSelector.story.vue +111 -0
- package/src/components/SampleSelector.vue +1033 -0
- package/src/components/ScheduleCalendar.story.vue +195 -0
- package/src/components/ScheduleCalendar.vue +569 -0
- package/src/components/ScientificNumber.story.vue +127 -0
- package/src/components/ScientificNumber.vue +197 -0
- package/src/components/SegmentedControl.story.vue +132 -0
- package/src/components/SegmentedControl.vue +79 -0
- package/src/components/SequenceInput.story.vue +119 -0
- package/src/components/SequenceInput.vue +209 -0
- package/src/components/SettingsButton.story.vue +58 -0
- package/src/components/SettingsButton.vue +76 -0
- package/src/components/SettingsModal.story.vue +145 -0
- package/src/components/SettingsModal.vue +146 -0
- package/src/components/Skeleton.story.vue +141 -0
- package/src/components/Skeleton.vue +74 -0
- package/src/components/StatusIndicator.story.vue +99 -0
- package/src/components/StatusIndicator.vue +40 -0
- package/src/components/StepWizard.story.vue +155 -0
- package/src/components/StepWizard.vue +223 -0
- package/src/components/TagsInput.story.vue +155 -0
- package/src/components/TagsInput.vue +265 -0
- package/src/components/ThemeToggle.story.vue +36 -0
- package/src/components/ThemeToggle.vue +54 -0
- package/src/components/TimePicker.story.vue +96 -0
- package/src/components/TimePicker.vue +273 -0
- package/src/components/TimeRangeInput.story.vue +104 -0
- package/src/components/TimeRangeInput.vue +122 -0
- package/src/components/ToastNotification.story.vue +157 -0
- package/src/components/ToastNotification.vue +62 -0
- package/src/components/Tooltip.story.vue +138 -0
- package/src/components/Tooltip.vue +119 -0
- package/src/components/UnitInput.story.vue +194 -0
- package/src/components/UnitInput.vue +213 -0
- package/src/components/WellEditPopup.vue +234 -0
- package/src/components/WellPlate.story.vue +282 -0
- package/src/components/WellPlate.vue +830 -0
- package/src/components/index.ts +118 -0
- package/src/composables/experiment-utils.ts +57 -0
- package/src/composables/formBuilderRegistry.ts +79 -0
- package/src/composables/index.ts +140 -0
- package/src/composables/useApi.ts +167 -0
- package/src/composables/useAppExperiment.ts +159 -0
- package/src/composables/useAsync.ts +323 -0
- package/src/composables/useAuth.ts +445 -0
- package/src/composables/useAutoGroup.ts +641 -0
- package/src/composables/useChemicalFormula.ts +275 -0
- package/src/composables/useConcentrationUnits.ts +246 -0
- package/src/composables/useDoseCalculator.ts +370 -0
- package/src/composables/useExperimentData.ts +86 -0
- package/src/composables/useExperimentSave.ts +192 -0
- package/src/composables/useExperimentSelector.ts +292 -0
- package/src/composables/useForm.ts +416 -0
- package/src/composables/useFormBuilder.ts +383 -0
- package/src/composables/usePasskey.ts +216 -0
- package/src/composables/usePlatformContext.ts +299 -0
- package/src/composables/usePluginApi.ts +39 -0
- package/src/composables/usePluginConfig.ts +93 -0
- package/src/composables/useProtocolTemplates.ts +518 -0
- package/src/composables/useRackEditor.ts +222 -0
- package/src/composables/useReagentSeries.ts +91 -0
- package/src/composables/useScheduleDrag.ts +245 -0
- package/src/composables/useSequenceUtils.ts +105 -0
- package/src/composables/useTheme.ts +58 -0
- package/src/composables/useTimeUtils.ts +131 -0
- package/src/composables/useToast.ts +40 -0
- package/src/composables/useWellPlateEditor.ts +421 -0
- package/src/histoire.setup.ts +17 -0
- package/src/index.ts +367 -0
- package/src/install.ts +32 -0
- package/src/stores/auth.ts +152 -0
- package/src/stores/index.ts +2 -0
- package/src/stores/settings.ts +218 -0
- package/src/styles/components/alert-box.css +150 -0
- package/src/styles/components/app-avatar-menu.css +155 -0
- package/src/styles/components/app-container.css +33 -0
- package/src/styles/components/app-layout.css +98 -0
- package/src/styles/components/app-page-selector.css +191 -0
- package/src/styles/components/app-pill-nav.css +57 -0
- package/src/styles/components/app-plugin-switcher.css +209 -0
- package/src/styles/components/app-sidebar.css +145 -0
- package/src/styles/components/app-top-bar.css +492 -0
- package/src/styles/components/audit-trail.css +143 -0
- package/src/styles/components/auto-group-modal.css +644 -0
- package/src/styles/components/avatar.css +73 -0
- package/src/styles/components/batch-progress-list.css +196 -0
- package/src/styles/components/breadcrumb.css +64 -0
- package/src/styles/components/button.css +188 -0
- package/src/styles/components/calendar.css +192 -0
- package/src/styles/components/chart-container.css +69 -0
- package/src/styles/components/checkbox.css +123 -0
- package/src/styles/components/chemical-formula.css +46 -0
- package/src/styles/components/collapsible-card.css +253 -0
- package/src/styles/components/color-slider.css +110 -0
- package/src/styles/components/concentration-input.css +156 -0
- package/src/styles/components/confirm-dialog.css +183 -0
- package/src/styles/components/dataframe.css +382 -0
- package/src/styles/components/date-picker.css +243 -0
- package/src/styles/components/datetime-picker.css +229 -0
- package/src/styles/components/divider.css +63 -0
- package/src/styles/components/dose-calculator.css +301 -0
- package/src/styles/components/dropdown-button.css +280 -0
- package/src/styles/components/empty-state.css +151 -0
- package/src/styles/components/experiment-code-badge.css +33 -0
- package/src/styles/components/experiment-data-viewer.css +138 -0
- package/src/styles/components/experiment-popover.css +562 -0
- package/src/styles/components/experiment-selector-modal.css +285 -0
- package/src/styles/components/experiment-timeline.css +529 -0
- package/src/styles/components/file-uploader.css +310 -0
- package/src/styles/components/fit-panel.css +67 -0
- package/src/styles/components/form-builder.css +69 -0
- package/src/styles/components/form-field.css +48 -0
- package/src/styles/components/formula-input.css +103 -0
- package/src/styles/components/group-assigner.css +200 -0
- package/src/styles/components/grouping-modal.css +323 -0
- package/src/styles/components/icon-button.css +192 -0
- package/src/styles/components/input.css +66 -0
- package/src/styles/components/loading-spinner.css +67 -0
- package/src/styles/components/modal.css +350 -0
- package/src/styles/components/molecule-input.css +186 -0
- package/src/styles/components/multi-select.css +131 -0
- package/src/styles/components/number-input.css +199 -0
- package/src/styles/components/pill.css +188 -0
- package/src/styles/components/plate-map-editor.css +464 -0
- package/src/styles/components/progress-bar.css +133 -0
- package/src/styles/components/protocol-step-editor.css +449 -0
- package/src/styles/components/rack-editor.css +265 -0
- package/src/styles/components/radio-group.css +240 -0
- package/src/styles/components/reagent-editor.css +510 -0
- package/src/styles/components/reagent-list.css +407 -0
- package/src/styles/components/resource-card.css +360 -0
- package/src/styles/components/sample-hierarchy-tree.css +314 -0
- package/src/styles/components/sample-legend.css +201 -0
- package/src/styles/components/sample-selector.css +751 -0
- package/src/styles/components/schedule-calendar.css +478 -0
- package/src/styles/components/scientific-number.css +63 -0
- package/src/styles/components/segmented-control.css +197 -0
- package/src/styles/components/select.css +77 -0
- package/src/styles/components/sequence-input.css +184 -0
- package/src/styles/components/settings-button.css +94 -0
- package/src/styles/components/settings-modal.css +95 -0
- package/src/styles/components/skeleton.css +49 -0
- package/src/styles/components/slider.css +74 -0
- package/src/styles/components/status-indicator.css +66 -0
- package/src/styles/components/step-wizard.css +192 -0
- package/src/styles/components/tabs.css +95 -0
- package/src/styles/components/tags-input.css +195 -0
- package/src/styles/components/textarea.css +82 -0
- package/src/styles/components/theme-toggle.css +69 -0
- package/src/styles/components/time-picker.css +171 -0
- package/src/styles/components/time-range-input.css +42 -0
- package/src/styles/components/toast.css +91 -0
- package/src/styles/components/toggle.css +146 -0
- package/src/styles/components/tooltip.css +91 -0
- package/src/styles/components/unit-input.css +123 -0
- package/src/styles/components/well-edit-popup.css +252 -0
- package/src/styles/components/well-plate.css +307 -0
- package/src/styles/index.css +87 -0
- package/src/styles/variables.css +1117 -0
- package/src/tailwind.preset.ts +61 -0
- package/src/types/auth.ts +55 -0
- package/src/types/auto-group.ts +40 -0
- package/src/types/components.ts +710 -0
- package/src/types/form-builder.ts +197 -0
- package/src/types/index.ts +207 -0
- package/src/types/platform.ts +116 -0
- package/src/utils/color.ts +96 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
|
2
|
+
import type { PlatformContext, PlatformContextOptions, PlatformEvent } from '../types'
|
|
3
|
+
|
|
4
|
+
const DEFAULT_CONTEXT: PlatformContext = {
|
|
5
|
+
isIntegrated: false,
|
|
6
|
+
theme: 'system',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const platformContext = ref<PlatformContext>({ ...DEFAULT_CONTEXT })
|
|
10
|
+
|
|
11
|
+
// Track allowed origins for postMessage security.
|
|
12
|
+
// Inferred origins come from platform injection and URL params.
|
|
13
|
+
// Consumer origins and allowAnyOrigin are tracked per composable instance.
|
|
14
|
+
let inferredOrigins: Set<string> = new Set()
|
|
15
|
+
let allowedOrigins: Set<string> = new Set()
|
|
16
|
+
let allowAnyOrigin = false
|
|
17
|
+
let initialized = false
|
|
18
|
+
let listenerCount = 0
|
|
19
|
+
let nextConsumerId = 0
|
|
20
|
+
let currentHandler: ((event: MessageEvent) => void) | null = null
|
|
21
|
+
const consumerOrigins: Map<number, Set<string>> = new Map()
|
|
22
|
+
const allowAnyOriginConsumers: Set<number> = new Set()
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Derive origin from URL (protocol + host)
|
|
26
|
+
*/
|
|
27
|
+
function getOriginFromUrl(url: string): string | null {
|
|
28
|
+
try {
|
|
29
|
+
const parsed = new URL(url)
|
|
30
|
+
return parsed.origin
|
|
31
|
+
} catch {
|
|
32
|
+
return null
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizeAllowedOrigins(origins: string[] | undefined): Set<string> {
|
|
37
|
+
const normalized = new Set<string>()
|
|
38
|
+
if (!origins) {
|
|
39
|
+
return normalized
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (const origin of origins) {
|
|
43
|
+
normalized.add(getOriginFromUrl(origin) || origin)
|
|
44
|
+
}
|
|
45
|
+
return normalized
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function recomputeOriginPolicy(): void {
|
|
49
|
+
allowedOrigins = new Set(inferredOrigins)
|
|
50
|
+
for (const origins of consumerOrigins.values()) {
|
|
51
|
+
for (const origin of origins) {
|
|
52
|
+
allowedOrigins.add(origin)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
allowAnyOrigin = allowAnyOriginConsumers.size > 0
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function resetPlatformContextState(): void {
|
|
59
|
+
inferredOrigins = new Set()
|
|
60
|
+
allowedOrigins = new Set()
|
|
61
|
+
allowAnyOrigin = false
|
|
62
|
+
initialized = false
|
|
63
|
+
listenerCount = 0
|
|
64
|
+
currentHandler = null
|
|
65
|
+
consumerOrigins.clear()
|
|
66
|
+
allowAnyOriginConsumers.clear()
|
|
67
|
+
platformContext.value = { ...DEFAULT_CONTEXT }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Check if an origin is allowed for postMessage communication
|
|
72
|
+
*/
|
|
73
|
+
function isOriginAllowed(origin: string): boolean {
|
|
74
|
+
// Development mode: allow any origin (must be explicitly enabled)
|
|
75
|
+
if (allowAnyOrigin) {
|
|
76
|
+
console.warn('[MLD SDK] postMessage origin validation disabled - only use in development')
|
|
77
|
+
return true
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Same origin is always allowed
|
|
81
|
+
if (origin === window.location.origin) {
|
|
82
|
+
return true
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Check against allowed origins list
|
|
86
|
+
return allowedOrigins.has(origin)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Platform context composable for plugin integration with MLD Platform.
|
|
91
|
+
*
|
|
92
|
+
* Provides secure communication with the parent platform via postMessage.
|
|
93
|
+
*
|
|
94
|
+
* @param options - Configuration options
|
|
95
|
+
* @param options.allowedOrigins - List of allowed origins for postMessage
|
|
96
|
+
* @param options.allowAnyOrigin - Allow any origin (UNSAFE, development only)
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* // Basic usage - derives origin from platform injection
|
|
101
|
+
* const { isIntegrated, user, theme } = usePlatformContext()
|
|
102
|
+
*
|
|
103
|
+
* // With explicit allowed origins
|
|
104
|
+
* const { isIntegrated } = usePlatformContext({
|
|
105
|
+
* allowedOrigins: ['https://mld.example.com']
|
|
106
|
+
* })
|
|
107
|
+
*
|
|
108
|
+
* // Development mode (UNSAFE)
|
|
109
|
+
* const { isIntegrated } = usePlatformContext({
|
|
110
|
+
* allowAnyOrigin: import.meta.env.DEV
|
|
111
|
+
* })
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
/** Connects a plugin to the MLD platform via postMessage, exposing user, theme, and experiment context. */
|
|
115
|
+
export function usePlatformContext(options: PlatformContextOptions = {}) {
|
|
116
|
+
const consumerId = ++nextConsumerId
|
|
117
|
+
const instanceOrigins = normalizeAllowedOrigins(options.allowedOrigins)
|
|
118
|
+
const instanceAllowAnyOrigin = options.allowAnyOrigin === true
|
|
119
|
+
|
|
120
|
+
function detectPlatform(): void {
|
|
121
|
+
const detectedOrigins = new Set<string>()
|
|
122
|
+
|
|
123
|
+
// Check if running under MLD Platform by looking for platform-injected global
|
|
124
|
+
const platformData = (window as unknown as { __MINT_PLATFORM__?: PlatformContext }).__MINT_PLATFORM__
|
|
125
|
+
|
|
126
|
+
if (platformData) {
|
|
127
|
+
platformContext.value = {
|
|
128
|
+
...platformData,
|
|
129
|
+
isIntegrated: true,
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Derive platform origin from injected data
|
|
133
|
+
if (platformData.platformOrigin) {
|
|
134
|
+
detectedOrigins.add(platformData.platformOrigin)
|
|
135
|
+
} else if (platformData.platformApiUrl) {
|
|
136
|
+
const origin = getOriginFromUrl(platformData.platformApiUrl)
|
|
137
|
+
if (origin) {
|
|
138
|
+
detectedOrigins.add(origin)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
// Check for platform indicator in URL or localStorage
|
|
143
|
+
const urlParams = new URLSearchParams(window.location.search)
|
|
144
|
+
const hasPluginParam = urlParams.has('mld-plugin')
|
|
145
|
+
|
|
146
|
+
// Try to get platform origin from URL parameter
|
|
147
|
+
const platformOrigin = urlParams.get('mld-origin')
|
|
148
|
+
if (platformOrigin) {
|
|
149
|
+
const origin = getOriginFromUrl(platformOrigin)
|
|
150
|
+
if (origin) {
|
|
151
|
+
detectedOrigins.add(origin)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
platformContext.value = {
|
|
156
|
+
isIntegrated: hasPluginParam,
|
|
157
|
+
theme: (() => {
|
|
158
|
+
try {
|
|
159
|
+
const s = localStorage.getItem('mld-settings')
|
|
160
|
+
if (s) return (JSON.parse(s).theme as 'light' | 'dark' | 'system') || 'system'
|
|
161
|
+
} catch { /* ignore */ }
|
|
162
|
+
return 'system'
|
|
163
|
+
})(),
|
|
164
|
+
platformOrigin: platformOrigin || undefined,
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
inferredOrigins = detectedOrigins
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function handlePlatformMessage(event: MessageEvent): void {
|
|
172
|
+
// Only accept messages from parent window (platform)
|
|
173
|
+
if (event.source !== window.parent) return
|
|
174
|
+
|
|
175
|
+
// Validate origin for security
|
|
176
|
+
if (!isOriginAllowed(event.origin)) {
|
|
177
|
+
console.warn(`[MLD SDK] Rejected postMessage from untrusted origin: ${event.origin}`)
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
const platformEvent = event.data as PlatformEvent
|
|
183
|
+
if (!platformEvent.type?.startsWith('mld:')) return
|
|
184
|
+
|
|
185
|
+
switch (platformEvent.type) {
|
|
186
|
+
case 'mld:theme-changed':
|
|
187
|
+
platformContext.value.theme = platformEvent.payload as 'light' | 'dark' | 'system'
|
|
188
|
+
break
|
|
189
|
+
case 'mld:user-changed':
|
|
190
|
+
platformContext.value.user = platformEvent.payload as PlatformContext['user']
|
|
191
|
+
break
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
// Ignore invalid messages
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Send a message to the parent platform.
|
|
200
|
+
* Uses validated target origin for security.
|
|
201
|
+
*/
|
|
202
|
+
function sendToPlatform(event: PlatformEvent): void {
|
|
203
|
+
if (!platformContext.value.isIntegrated || window.parent === window) {
|
|
204
|
+
return
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Determine target origin
|
|
208
|
+
let targetOrigin: string
|
|
209
|
+
|
|
210
|
+
if (platformContext.value.platformOrigin) {
|
|
211
|
+
// Use explicitly configured platform origin
|
|
212
|
+
targetOrigin = platformContext.value.platformOrigin
|
|
213
|
+
} else if (allowedOrigins.size > 0) {
|
|
214
|
+
// Use first allowed origin (typically the platform)
|
|
215
|
+
targetOrigin = allowedOrigins.values().next().value as string
|
|
216
|
+
} else if (allowAnyOrigin) {
|
|
217
|
+
// Development mode fallback
|
|
218
|
+
targetOrigin = '*'
|
|
219
|
+
console.warn('[MLD SDK] Using wildcard origin for postMessage - only use in development')
|
|
220
|
+
} else {
|
|
221
|
+
// Safety: if no origin is configured, log warning and don't send
|
|
222
|
+
console.warn('[MLD SDK] Cannot send postMessage: no platform origin configured')
|
|
223
|
+
return
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
window.parent.postMessage(event, targetOrigin)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Request navigation to a path in the platform.
|
|
231
|
+
*/
|
|
232
|
+
function navigate(path: string): void {
|
|
233
|
+
sendToPlatform({
|
|
234
|
+
type: 'mld:navigate',
|
|
235
|
+
payload: path,
|
|
236
|
+
})
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Show a notification in the platform.
|
|
241
|
+
*/
|
|
242
|
+
function notify(message: string, type: 'success' | 'error' | 'warning' | 'info' = 'info'): void {
|
|
243
|
+
sendToPlatform({
|
|
244
|
+
type: 'mld:notification',
|
|
245
|
+
payload: { message, type },
|
|
246
|
+
})
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
onMounted(() => {
|
|
250
|
+
consumerOrigins.set(consumerId, instanceOrigins)
|
|
251
|
+
if (instanceAllowAnyOrigin) {
|
|
252
|
+
allowAnyOriginConsumers.add(consumerId)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (!initialized) {
|
|
256
|
+
detectPlatform()
|
|
257
|
+
currentHandler = handlePlatformMessage
|
|
258
|
+
window.addEventListener('message', handlePlatformMessage)
|
|
259
|
+
initialized = true
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
listenerCount++
|
|
263
|
+
recomputeOriginPolicy()
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
onUnmounted(() => {
|
|
267
|
+
consumerOrigins.delete(consumerId)
|
|
268
|
+
allowAnyOriginConsumers.delete(consumerId)
|
|
269
|
+
|
|
270
|
+
listenerCount = Math.max(0, listenerCount - 1)
|
|
271
|
+
if (listenerCount === 0) {
|
|
272
|
+
if (currentHandler) {
|
|
273
|
+
window.removeEventListener('message', currentHandler)
|
|
274
|
+
}
|
|
275
|
+
resetPlatformContextState()
|
|
276
|
+
return
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
recomputeOriginPolicy()
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
const isIntegrated = computed(() => platformContext.value.isIntegrated)
|
|
283
|
+
const plugin = computed(() => platformContext.value.plugin)
|
|
284
|
+
const user = computed(() => platformContext.value.user)
|
|
285
|
+
const theme = computed(() => platformContext.value.theme)
|
|
286
|
+
const features = computed(() => platformContext.value.features)
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
context: platformContext,
|
|
290
|
+
isIntegrated,
|
|
291
|
+
plugin,
|
|
292
|
+
user,
|
|
293
|
+
theme,
|
|
294
|
+
features,
|
|
295
|
+
navigate,
|
|
296
|
+
notify,
|
|
297
|
+
sendToPlatform,
|
|
298
|
+
}
|
|
299
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useApi } from './useApi'
|
|
2
|
+
|
|
3
|
+
export interface UsePluginApiOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Fallback API prefix when `VITE_API_PREFIX` is not set.
|
|
6
|
+
* Typically your plugin's route prefix, e.g. `'/api/drp'`.
|
|
7
|
+
*/
|
|
8
|
+
fallbackPrefix?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Pre-configured API client for plugins.
|
|
13
|
+
*
|
|
14
|
+
* Resolves the base URL in priority order:
|
|
15
|
+
* 1. `import.meta.env.VITE_API_PREFIX` (build-time env override)
|
|
16
|
+
* 2. `fallbackPrefix` option (plugin's route prefix)
|
|
17
|
+
* 3. `'/api'` (default)
|
|
18
|
+
*
|
|
19
|
+
* Eliminates the repeated pattern across plugins:
|
|
20
|
+
* ```ts
|
|
21
|
+
* const API_BASE = import.meta.env.VITE_API_PREFIX || '/api/my-plugin'
|
|
22
|
+
* const api = useApi({ baseUrl: API_BASE })
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* const api = usePluginApi({ fallbackPrefix: '/api/drp' })
|
|
28
|
+
* const data = await api.get('/sessions')
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
/** Pre-configured API client resolving the plugin base URL from VITE_API_PREFIX or a fallback prefix. */
|
|
32
|
+
export function usePluginApi(options: UsePluginApiOptions = {}) {
|
|
33
|
+
const baseUrl =
|
|
34
|
+
(import.meta.env?.VITE_API_PREFIX as string | undefined) ||
|
|
35
|
+
options.fallbackPrefix ||
|
|
36
|
+
'/api'
|
|
37
|
+
|
|
38
|
+
return useApi({ baseUrl })
|
|
39
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { ref, computed, onMounted, type Ref, type ComputedRef } from 'vue'
|
|
2
|
+
import { useApi } from './useApi'
|
|
3
|
+
import { usePlatformContext } from './usePlatformContext'
|
|
4
|
+
|
|
5
|
+
export interface UsePluginConfigReturn {
|
|
6
|
+
config: Ref<Record<string, unknown>>
|
|
7
|
+
isLoading: Ref<boolean>
|
|
8
|
+
isSaving: Ref<boolean>
|
|
9
|
+
error: Ref<string | null>
|
|
10
|
+
isDirty: ComputedRef<boolean>
|
|
11
|
+
load: () => Promise<void>
|
|
12
|
+
save: () => Promise<boolean>
|
|
13
|
+
reset: () => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Loads, saves, and tracks dirty state for a plugin's persistent configuration via the platform API. */
|
|
17
|
+
export function usePluginConfig(pluginName?: string): UsePluginConfigReturn {
|
|
18
|
+
const api = useApi()
|
|
19
|
+
const { plugin } = usePlatformContext()
|
|
20
|
+
|
|
21
|
+
const resolvedName = computed(() => pluginName ?? plugin.value?.name ?? '')
|
|
22
|
+
|
|
23
|
+
const config = ref<Record<string, unknown>>({})
|
|
24
|
+
const savedConfig = ref<Record<string, unknown>>({})
|
|
25
|
+
const isLoading = ref(false)
|
|
26
|
+
const isSaving = ref(false)
|
|
27
|
+
const error = ref<string | null>(null)
|
|
28
|
+
|
|
29
|
+
const isDirty = computed(() => {
|
|
30
|
+
return JSON.stringify(config.value) !== JSON.stringify(savedConfig.value)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
async function load(): Promise<void> {
|
|
34
|
+
const name = resolvedName.value
|
|
35
|
+
if (!name) return
|
|
36
|
+
|
|
37
|
+
isLoading.value = true
|
|
38
|
+
error.value = null
|
|
39
|
+
try {
|
|
40
|
+
const response = await api.get<{ plugin_name: string; config: Record<string, unknown> }>(
|
|
41
|
+
`/plugins/${encodeURIComponent(name)}/config`,
|
|
42
|
+
)
|
|
43
|
+
config.value = { ...response.config }
|
|
44
|
+
savedConfig.value = { ...response.config }
|
|
45
|
+
} catch (e) {
|
|
46
|
+
error.value = e instanceof Error ? e.message : 'Failed to load plugin config'
|
|
47
|
+
} finally {
|
|
48
|
+
isLoading.value = false
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function save(): Promise<boolean> {
|
|
53
|
+
const name = resolvedName.value
|
|
54
|
+
if (!name) return false
|
|
55
|
+
|
|
56
|
+
isSaving.value = true
|
|
57
|
+
error.value = null
|
|
58
|
+
try {
|
|
59
|
+
const response = await api.patch<{ plugin_name: string; config: Record<string, unknown> }>(
|
|
60
|
+
`/plugins/${encodeURIComponent(name)}/config`,
|
|
61
|
+
{ config: config.value },
|
|
62
|
+
)
|
|
63
|
+
config.value = { ...response.config }
|
|
64
|
+
savedConfig.value = { ...response.config }
|
|
65
|
+
return true
|
|
66
|
+
} catch (e) {
|
|
67
|
+
error.value = e instanceof Error ? e.message : 'Failed to save plugin config'
|
|
68
|
+
return false
|
|
69
|
+
} finally {
|
|
70
|
+
isSaving.value = false
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function reset(): void {
|
|
75
|
+
config.value = { ...savedConfig.value }
|
|
76
|
+
error.value = null
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
onMounted(() => {
|
|
80
|
+
load()
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
config,
|
|
85
|
+
isLoading,
|
|
86
|
+
isSaving,
|
|
87
|
+
error,
|
|
88
|
+
isDirty,
|
|
89
|
+
load,
|
|
90
|
+
save,
|
|
91
|
+
reset,
|
|
92
|
+
}
|
|
93
|
+
}
|