@morscherlab/mint-sdk 1.0.0-beta.2 → 1.0.0-beta.4
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 +225 -6
- package/dist/__tests__/components/ActionItem.test.d.ts +1 -0
- package/dist/__tests__/components/AppAvatarMenu.test.d.ts +1 -0
- package/dist/__tests__/components/AppPageSelector.test.d.ts +1 -0
- package/dist/__tests__/components/AppPillNav.test.d.ts +1 -0
- package/dist/__tests__/components/AppPluginSwitcher.test.d.ts +1 -0
- package/dist/__tests__/components/AppToastContainer.test.d.ts +1 -0
- package/dist/__tests__/components/BaseRadioGroup.test.d.ts +1 -0
- package/dist/__tests__/components/BaseSelect.test.d.ts +1 -0
- package/dist/__tests__/components/BaseTabs.test.d.ts +1 -0
- package/dist/__tests__/components/BatchProgressList.test.d.ts +1 -0
- package/dist/__tests__/components/BioTemplateExperimentWorkspaceView.test.d.ts +1 -0
- package/dist/__tests__/components/BioTemplatePackWorkspaceView.test.d.ts +1 -0
- package/dist/__tests__/components/BioTemplatePresetWorkspaceView.test.d.ts +1 -0
- package/dist/__tests__/components/BioTemplateRenderer.test.d.ts +1 -0
- package/dist/__tests__/components/Breadcrumb.test.d.ts +1 -0
- package/dist/__tests__/components/CalendarGridPanel.test.d.ts +1 -0
- package/dist/__tests__/components/ComponentBindingRenderer.test.d.ts +1 -0
- package/dist/__tests__/components/ConcentrationInput.test.d.ts +1 -0
- package/dist/__tests__/components/ControlWorkspaceView.test.d.ts +1 -0
- package/dist/__tests__/components/DatePicker.test.d.ts +1 -0
- package/dist/__tests__/components/DateTimePicker.test.d.ts +1 -0
- package/dist/__tests__/components/DoseDesignWorkspaceView.test.d.ts +1 -0
- package/dist/__tests__/components/EmptyState.test.d.ts +1 -0
- package/dist/__tests__/components/ExperimentPopover.test.d.ts +1 -0
- package/dist/__tests__/components/FormBuilder.test.d.ts +1 -0
- package/dist/__tests__/components/GroupAssigner.test.d.ts +1 -0
- package/dist/__tests__/components/MultiSelect.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.test.d.ts +1 -0
- package/dist/__tests__/components/ProtocolStepEditor.test.d.ts +1 -0
- package/dist/__tests__/components/ReagentList.test.d.ts +1 -0
- package/dist/__tests__/components/SampleHierarchyTree.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.test.d.ts +1 -0
- package/dist/__tests__/components/SegmentedControl.test.d.ts +1 -0
- package/dist/__tests__/components/SettingsModal.test.d.ts +1 -0
- package/dist/__tests__/components/TagsInput.test.d.ts +1 -0
- package/dist/__tests__/components/ThemeToggle.test.d.ts +1 -0
- package/dist/__tests__/components/TimePicker.test.d.ts +1 -0
- package/dist/__tests__/composables/experiment-utils.test.d.ts +1 -0
- package/dist/__tests__/composables/useApi.test.d.ts +1 -0
- package/dist/__tests__/composables/useBioTemplatePackWorkspace.test.d.ts +1 -0
- package/dist/__tests__/composables/useBioTemplatePresetWorkspace.test.d.ts +1 -0
- package/dist/__tests__/composables/useBioTemplateWorkspace.test.d.ts +1 -0
- package/dist/__tests__/composables/useCalendarGrid.test.d.ts +1 -0
- package/dist/__tests__/composables/useControlSchema.test.d.ts +1 -0
- package/dist/__tests__/composables/useDebouncedWatch.test.d.ts +1 -0
- package/dist/__tests__/composables/useDropdownState.test.d.ts +1 -0
- package/dist/__tests__/composables/useEventListener.test.d.ts +1 -0
- package/dist/__tests__/composables/useExpansionSet.test.d.ts +1 -0
- package/dist/__tests__/composables/useExperimentData.test.d.ts +1 -0
- package/dist/__tests__/composables/useExperimentSelector.test.d.ts +1 -0
- package/dist/__tests__/composables/useGroupAssignment.test.d.ts +1 -0
- package/dist/__tests__/composables/useListSelection.test.d.ts +1 -0
- package/dist/__tests__/composables/usePluginClient.test.d.ts +1 -0
- package/dist/__tests__/composables/usePluginConfig.test.d.ts +1 -0
- package/dist/__tests__/composables/useRequestSyncState.test.d.ts +1 -0
- package/dist/__tests__/composables/useSampleGroups.test.d.ts +1 -0
- package/dist/__tests__/composables/useSelectionLimit.test.d.ts +1 -0
- package/dist/__tests__/composables/useSortedItems.test.d.ts +1 -0
- package/dist/__tests__/composables/useTemplateCollection.test.d.ts +1 -0
- package/dist/__tests__/composables/useTextSearch.test.d.ts +1 -0
- package/dist/__tests__/composables/useTheme.test.d.ts +1 -0
- package/dist/__tests__/composables/useTimeUtils.test.d.ts +1 -0
- package/dist/__tests__/docs/frontendDocsCatalog.test.d.ts +1 -0
- package/dist/__tests__/templates/templates.test.d.ts +1 -0
- package/dist/{auth-DsI0rQ7_.js → auth-QQj2kkze.js} +12 -5
- package/dist/auth-QQj2kkze.js.map +1 -0
- package/dist/components/AppAvatarMenu.vue.d.ts +2 -7
- package/dist/components/AppContainer.vue.d.ts +1 -1
- package/dist/components/AppLayout.vue.d.ts +20 -1
- package/dist/components/AppSidebar.vue.d.ts +111 -6
- package/dist/components/AppTopBar.vue.d.ts +35 -22
- package/dist/components/BaseButton.vue.d.ts +1 -1
- package/dist/components/BaseCheckbox.vue.d.ts +1 -1
- package/dist/components/BaseInput.vue.d.ts +2 -2
- package/dist/components/BasePill.vue.d.ts +2 -2
- package/dist/components/BaseRadioGroup.vue.d.ts +3 -3
- package/dist/components/BaseSelect.vue.d.ts +3 -3
- package/dist/components/BaseTabs.vue.d.ts +2 -2
- package/dist/components/BaseTextarea.vue.d.ts +1 -1
- package/dist/components/BaseToggle.vue.d.ts +1 -1
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +119 -0
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +93 -0
- package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +87 -0
- package/dist/components/BioTemplateRenderer.vue.d.ts +29 -0
- package/dist/components/Breadcrumb.vue.d.ts +2 -2
- package/dist/components/Calendar.vue.d.ts +1 -1
- package/dist/components/CollapsibleCard.vue.d.ts +1 -1
- package/dist/components/ComponentBindingRenderer.vue.d.ts +44 -0
- package/dist/components/ConcentrationInput.vue.d.ts +2 -2
- package/dist/components/ConfirmDialog.vue.d.ts +2 -2
- package/dist/components/ControlWorkspaceView.vue.d.ts +147 -0
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/DateTimePicker.vue.d.ts +3 -3
- package/dist/components/Divider.vue.d.ts +1 -1
- package/dist/components/DoseDesignWorkspaceView.vue.d.ts +149 -0
- package/dist/components/DropdownButton.vue.d.ts +3 -3
- package/dist/components/EmptyState.vue.d.ts +1 -2
- package/dist/components/ExperimentDataViewer.vue.d.ts +1 -1
- package/dist/components/ExperimentTimeline.vue.d.ts +2 -2
- package/dist/components/FileUploader.vue.d.ts +1 -1
- package/dist/components/FitPanel.vue.d.ts +1 -1
- package/dist/components/FormActions.vue.d.ts +4 -4
- package/dist/components/FormBuilder.vue.d.ts +31 -17
- package/dist/components/FormulaInput.vue.d.ts +2 -2
- package/dist/components/MoleculeInput.vue.d.ts +2 -2
- package/dist/components/MultiSelect.vue.d.ts +3 -3
- package/dist/components/NumberInput.vue.d.ts +1 -1
- package/dist/components/PlateMapEditor.vue.d.ts +1 -1
- package/dist/components/PluginWorkspaceView.vue.d.ts +310 -0
- package/dist/components/ProgressBar.vue.d.ts +1 -1
- package/dist/components/ProtocolStepEditor.vue.d.ts +3 -1
- package/dist/components/RackEditor.vue.d.ts +2 -2
- package/dist/components/SampleLegend.vue.d.ts +2 -2
- package/dist/components/ScheduleCalendar.vue.d.ts +2 -2
- package/dist/components/SegmentedControl.vue.d.ts +2 -2
- package/dist/components/SequenceInput.vue.d.ts +3 -3
- package/dist/components/SettingsModal.vue.d.ts +14 -6
- package/dist/components/StatusIndicator.vue.d.ts +1 -1
- package/dist/components/TagsInput.vue.d.ts +3 -2
- package/dist/components/TimePicker.vue.d.ts +3 -3
- package/dist/components/TimeRangeInput.vue.d.ts +1 -1
- package/dist/components/UnitInput.vue.d.ts +2 -2
- package/dist/components/WellPlate.vue.d.ts +6 -6
- package/dist/components/index.d.ts +9 -8
- package/dist/components/index.js +3 -3
- package/dist/components/{SettingsButton.vue.d.ts → internal/ActionItemInternal.vue.d.ts} +11 -9
- package/dist/components/{AppPageSelector.vue.d.ts → internal/AppPageSelectorInternal.vue.d.ts} +3 -6
- package/dist/components/{AppPillNav.vue.d.ts → internal/AppPillNavInternal.vue.d.ts} +4 -2
- package/dist/components/internal/CalendarGridPanelInternal.vue.d.ts +25 -0
- package/dist/components/{FormFieldRenderer.vue.d.ts → internal/FormFieldRendererInternal.vue.d.ts} +2 -2
- package/dist/components/{FormSection.vue.d.ts → internal/FormSectionRenderer.vue.d.ts} +7 -7
- package/dist/components/{WellEditPopup.vue.d.ts → internal/WellEditPopupInternal.vue.d.ts} +1 -1
- package/dist/{components-_XqPEhP9.js → components-BkGF4B4y.js} +9760 -8471
- package/dist/components-BkGF4B4y.js.map +1 -0
- package/dist/composables/experiment-utils.d.ts +8 -0
- package/dist/composables/index.d.ts +22 -5
- package/dist/composables/index.js +4 -3
- package/dist/composables/platformContextHelpers.d.ts +14 -0
- package/dist/composables/useAppExperiment.d.ts +31 -2
- package/dist/composables/useBioTemplateComponents.d.ts +22 -0
- package/dist/composables/useBioTemplateControls.d.ts +6 -0
- package/dist/composables/useBioTemplatePackWorkspace.d.ts +46 -0
- package/dist/composables/useBioTemplatePresetWorkspace.d.ts +75 -0
- package/dist/composables/useBioTemplateWorkspace.d.ts +51 -0
- package/dist/composables/useCalendarGrid.d.ts +26 -0
- package/dist/composables/useControlSchema.d.ts +343 -0
- package/dist/composables/useDebouncedWatch.d.ts +20 -0
- package/dist/composables/useDropdownState.d.ts +19 -0
- package/dist/composables/useEventListener.d.ts +13 -0
- package/dist/composables/useExpansionSet.d.ts +21 -0
- package/dist/composables/useExperimentData.d.ts +10 -0
- package/dist/composables/useExperimentSave.d.ts +31 -2
- package/dist/composables/useExperimentSelector.d.ts +20 -0
- package/dist/composables/useForm.d.ts +2 -0
- package/dist/composables/useGroupAssignment.d.ts +31 -0
- package/dist/composables/useListSelection.d.ts +35 -0
- package/dist/composables/usePlatformContext.d.ts +21 -3
- package/dist/composables/usePluginClient.d.ts +112 -0
- package/dist/composables/usePluginConfig.d.ts +12 -0
- package/dist/composables/useRequestSyncState.d.ts +34 -0
- package/dist/composables/useSampleGroups.d.ts +32 -0
- package/dist/composables/useSelectionLimit.d.ts +17 -0
- package/dist/composables/useSortedItems.d.ts +32 -0
- package/dist/composables/useTemplateCollection.d.ts +58 -0
- package/dist/composables/useTextSearch.d.ts +18 -0
- package/dist/composables/useTimeUtils.d.ts +8 -0
- package/dist/{composables-tiZqLu1M.js → composables-CHsME9H1.js} +240 -146
- package/dist/composables-CHsME9H1.js.map +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +6 -5
- package/dist/install.d.ts +7 -2
- package/dist/install.js +2 -2
- package/dist/install.js.map +1 -1
- package/dist/stores/index.js +1 -1
- package/dist/stores/settings.d.ts +4 -1
- package/dist/styles.css +4746 -5514
- package/dist/templates/adapters.d.ts +43 -0
- package/dist/templates/builders.d.ts +63 -0
- package/dist/templates/catalog.d.ts +188 -0
- package/dist/templates/componentBindings.d.ts +71 -0
- package/dist/templates/controlSchemas.d.ts +25 -0
- package/dist/templates/index.d.ts +15 -0
- package/dist/templates/index.js +2 -0
- package/dist/templates/lookup.d.ts +4 -0
- package/dist/templates/packs.d.ts +18 -0
- package/dist/templates/presets.d.ts +90 -0
- package/dist/templates/types.d.ts +531 -0
- package/dist/templates-B5jmTWuk.js +9388 -0
- package/dist/templates-B5jmTWuk.js.map +1 -0
- package/dist/types/components.d.ts +26 -23
- package/dist/types/form-builder.d.ts +6 -8
- package/dist/types/index.d.ts +2 -2
- package/dist/types/platform.d.ts +7 -1
- package/dist/useScheduleDrag-BgzpQT53.js +4414 -0
- package/dist/useScheduleDrag-BgzpQT53.js.map +1 -0
- package/dist/utils/formModelSync.d.ts +5 -0
- package/dist/utils/items.d.ts +8 -0
- package/dist/utils/options.d.ts +6 -0
- package/dist/utils/pluginIcon.d.ts +9 -0
- package/package.json +7 -2
- package/src/__tests__/components/ActionItem.test.ts +99 -0
- package/src/__tests__/components/AppAvatarMenu.test.ts +27 -0
- package/src/__tests__/components/AppLayout.test.ts +44 -0
- package/src/__tests__/components/AppPageSelector.test.ts +134 -0
- package/src/__tests__/components/AppPillNav.test.ts +125 -0
- package/src/__tests__/components/AppPluginSwitcher.test.ts +44 -0
- package/src/__tests__/components/AppSidebar.test.ts +496 -0
- package/src/__tests__/components/AppToastContainer.test.ts +37 -0
- package/src/__tests__/components/AppTopBar.test.ts +455 -9
- package/src/__tests__/components/BaseRadioGroup.test.ts +25 -0
- package/src/__tests__/components/BaseSelect.test.ts +21 -0
- package/src/__tests__/components/BaseTabs.test.ts +25 -0
- package/src/__tests__/components/BatchProgressList.test.ts +52 -0
- package/src/__tests__/components/BioTemplateExperimentWorkspaceView.test.ts +159 -0
- package/src/__tests__/components/BioTemplatePackWorkspaceView.test.ts +175 -0
- package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +306 -0
- package/src/__tests__/components/BioTemplateRenderer.test.ts +71 -0
- package/src/__tests__/components/Breadcrumb.test.ts +23 -0
- package/src/__tests__/components/CalendarGridPanel.test.ts +36 -0
- package/src/__tests__/components/ComponentBindingRenderer.test.ts +161 -0
- package/src/__tests__/components/ConcentrationInput.test.ts +45 -0
- package/src/__tests__/components/ControlWorkspaceView.test.ts +1102 -0
- package/src/__tests__/components/DataFrame.test.ts +11 -0
- package/src/__tests__/components/DatePicker.test.ts +45 -0
- package/src/__tests__/components/DateTimePicker.test.ts +48 -0
- package/src/__tests__/components/DoseDesignWorkspaceView.test.ts +185 -0
- package/src/__tests__/components/DropdownButton.test.ts +23 -0
- package/src/__tests__/components/EmptyState.test.ts +23 -0
- package/src/__tests__/components/ExperimentPopover.test.ts +56 -0
- package/src/__tests__/components/FormBuilder.test.ts +296 -0
- package/src/__tests__/components/GroupAssigner.test.ts +30 -0
- package/src/__tests__/components/MultiSelect.test.ts +48 -0
- package/src/__tests__/components/PluginWorkspaceView.test.ts +548 -0
- package/src/__tests__/components/ProtocolStepEditor.test.ts +33 -0
- package/src/__tests__/components/ReagentList.test.ts +82 -0
- package/src/__tests__/components/SampleHierarchyTree.test.ts +53 -0
- package/src/__tests__/components/SampleSelector.test.ts +60 -0
- package/src/__tests__/components/SegmentedControl.test.ts +24 -0
- package/src/__tests__/components/SettingsModal.test.ts +296 -0
- package/src/__tests__/components/TagsInput.test.ts +75 -0
- package/src/__tests__/components/ThemeToggle.test.ts +47 -0
- package/src/__tests__/components/TimePicker.test.ts +38 -0
- package/src/__tests__/composables/experiment-utils.test.ts +30 -0
- package/src/__tests__/composables/useApi.test.ts +30 -0
- package/src/__tests__/composables/useAppExperiment.test.ts +100 -1
- package/src/__tests__/composables/useBioTemplatePackWorkspace.test.ts +125 -0
- package/src/__tests__/composables/useBioTemplatePresetWorkspace.test.ts +199 -0
- package/src/__tests__/composables/useBioTemplateWorkspace.test.ts +104 -0
- package/src/__tests__/composables/useCalendarGrid.test.ts +38 -0
- package/src/__tests__/composables/useControlSchema.test.ts +1033 -0
- package/src/__tests__/composables/useDebouncedWatch.test.ts +93 -0
- package/src/__tests__/composables/useDropdownState.test.ts +95 -0
- package/src/__tests__/composables/useEventListener.test.ts +116 -0
- package/src/__tests__/composables/useExpansionSet.test.ts +62 -0
- package/src/__tests__/composables/useExperimentData.test.ts +4 -0
- package/src/__tests__/composables/useExperimentSave.test.ts +203 -8
- package/src/__tests__/composables/useExperimentSelector.test.ts +164 -0
- package/src/__tests__/composables/useForm.test.ts +58 -0
- package/src/__tests__/composables/useFormBuilder.test.ts +77 -0
- package/src/__tests__/composables/useGroupAssignment.test.ts +73 -0
- package/src/__tests__/composables/useListSelection.test.ts +66 -0
- package/src/__tests__/composables/usePluginClient.test.ts +541 -0
- package/src/__tests__/composables/usePluginConfig.test.ts +5 -0
- package/src/__tests__/composables/useRequestSyncState.test.ts +92 -0
- package/src/__tests__/composables/useSampleGroups.test.ts +66 -0
- package/src/__tests__/composables/useSelectionLimit.test.ts +41 -0
- package/src/__tests__/composables/useSortedItems.test.ts +87 -0
- package/src/__tests__/composables/useTemplateCollection.test.ts +147 -0
- package/src/__tests__/composables/useTextSearch.test.ts +55 -0
- package/src/__tests__/composables/useTheme.test.ts +91 -0
- package/src/__tests__/composables/useTimeUtils.test.ts +35 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +324 -0
- package/src/__tests__/fixtures/templates/dose-response.json +81 -0
- package/src/__tests__/fixtures/templates/plate-map.json +54 -0
- package/src/__tests__/fixtures/templates/qpcr-plate.json +96 -0
- package/src/__tests__/fixtures/templates/sample-sheet.json +71 -0
- package/src/__tests__/templates/templates.test.ts +1055 -0
- package/src/components/AppAvatarMenu.vue +15 -69
- package/src/components/AppLayout.story.vue +64 -25
- package/src/components/AppLayout.vue +83 -2
- package/src/components/AppPluginSwitcher.vue +41 -145
- package/src/components/AppSidebar.story.vue +203 -1
- package/src/components/AppSidebar.vue +320 -25
- package/src/components/{ToastNotification.story.vue → AppToastContainer.story.vue} +6 -6
- package/src/components/{ToastNotification.vue → AppToastContainer.vue} +1 -1
- package/src/components/AppTopBar.story.vue +7 -33
- package/src/components/AppTopBar.vue +104 -300
- package/src/components/BaseModal.vue +3 -5
- package/src/components/BaseRadioGroup.vue +7 -3
- package/src/components/BaseSelect.vue +11 -7
- package/src/components/BaseTabs.vue +6 -4
- package/src/components/BatchProgressList.vue +5 -8
- package/src/components/BioTemplateExperimentWorkspaceView.story.vue +123 -0
- package/src/components/BioTemplateExperimentWorkspaceView.vue +343 -0
- package/src/components/BioTemplatePackWorkspaceView.story.vue +107 -0
- package/src/components/BioTemplatePackWorkspaceView.vue +177 -0
- package/src/components/BioTemplatePresetWorkspaceView.story.vue +163 -0
- package/src/components/BioTemplatePresetWorkspaceView.vue +401 -0
- package/src/components/BioTemplateRenderer.story.vue +57 -0
- package/src/components/BioTemplateRenderer.vue +57 -0
- package/src/components/Breadcrumb.vue +14 -8
- package/src/components/ComponentBindingRenderer.story.vue +57 -0
- package/src/components/ComponentBindingRenderer.vue +308 -0
- package/src/components/ConcentrationInput.vue +27 -64
- package/src/components/ControlWorkspaceView.story.vue +347 -0
- package/src/components/ControlWorkspaceView.vue +378 -0
- package/src/components/DataFrame.vue +34 -50
- package/src/components/DatePicker.vue +59 -192
- package/src/components/DateTimePicker.vue +50 -171
- package/src/components/DoseDesignWorkspaceView.story.vue +77 -0
- package/src/components/DoseDesignWorkspaceView.vue +255 -0
- package/src/components/DropdownButton.vue +14 -32
- package/src/components/EmptyState.vue +4 -2
- package/src/components/ExperimentPopover.vue +7 -28
- package/src/components/ExperimentSelectorModal.vue +6 -5
- package/src/components/FormBuilder.story.vue +190 -0
- package/src/components/FormBuilder.vue +124 -27
- package/src/components/GroupAssigner.vue +24 -56
- package/src/components/MultiSelect.vue +17 -12
- package/src/components/PlateMapEditor.vue +3 -8
- package/src/components/PluginIcon.vue +2 -22
- package/src/components/PluginWorkspaceView.story.vue +334 -0
- package/src/components/PluginWorkspaceView.vue +708 -0
- package/src/components/ProtocolStepEditor.vue +13 -22
- package/src/components/ReagentList.vue +25 -33
- package/src/components/SampleHierarchyTree.vue +12 -23
- package/src/components/SampleSelector.vue +42 -122
- package/src/components/SegmentedControl.vue +7 -3
- package/src/components/SettingsModal.story.vue +88 -1
- package/src/components/SettingsModal.vue +120 -29
- package/src/components/TagsInput.vue +29 -14
- package/src/components/ThemeToggle.vue +9 -7
- package/src/components/TimePicker.vue +19 -41
- package/src/components/Tooltip.vue +7 -12
- package/src/components/WellPlate.vue +6 -12
- package/src/components/index.ts +9 -8
- package/src/components/internal/ActionItemInternal.vue +82 -0
- package/src/components/internal/AppPageSelectorInternal.vue +128 -0
- package/src/components/internal/AppPillNavInternal.vue +194 -0
- package/src/components/internal/CalendarGridPanelInternal.vue +120 -0
- package/src/components/{FormFieldRenderer.vue → internal/FormFieldRendererInternal.vue} +4 -12
- package/src/components/{FormSection.vue → internal/FormSectionRenderer.vue} +6 -18
- package/src/components/{WellEditPopup.vue → internal/WellEditPopupInternal.vue} +5 -10
- package/src/composables/experiment-utils.ts +26 -0
- package/src/composables/index.ts +229 -3
- package/src/composables/platformContextHelpers.ts +74 -0
- package/src/composables/useApi.ts +9 -2
- package/src/composables/useAppExperiment.ts +85 -13
- package/src/composables/useBioTemplateComponents.ts +105 -0
- package/src/composables/useBioTemplateControls.ts +41 -0
- package/src/composables/useBioTemplatePackWorkspace.ts +185 -0
- package/src/composables/useBioTemplatePresetWorkspace.ts +326 -0
- package/src/composables/useBioTemplateWorkspace.ts +141 -0
- package/src/composables/useCalendarGrid.ts +140 -0
- package/src/composables/useControlSchema.ts +1362 -0
- package/src/composables/useDebouncedWatch.ts +119 -0
- package/src/composables/useDropdownState.ts +83 -0
- package/src/composables/useEventListener.ts +111 -0
- package/src/composables/useExpansionSet.ts +117 -0
- package/src/composables/useExperimentData.ts +20 -11
- package/src/composables/useExperimentSave.ts +202 -50
- package/src/composables/useExperimentSelector.ts +86 -72
- package/src/composables/useForm.ts +49 -4
- package/src/composables/useFormBuilder.ts +93 -42
- package/src/composables/useGroupAssignment.ts +148 -0
- package/src/composables/useListSelection.ts +158 -0
- package/src/composables/usePluginClient.ts +466 -0
- package/src/composables/usePluginConfig.ts +34 -13
- package/src/composables/useRequestSyncState.ts +126 -0
- package/src/composables/useSampleGroups.ts +126 -0
- package/src/composables/useSelectionLimit.ts +57 -0
- package/src/composables/useSortedItems.ts +118 -0
- package/src/composables/useTemplateCollection.ts +229 -0
- package/src/composables/useTextSearch.ts +60 -0
- package/src/composables/useTheme.ts +2 -28
- package/src/composables/useTimeUtils.ts +26 -2
- package/src/composables/useWellPlateEditor.ts +13 -9
- package/src/index.ts +11 -348
- package/src/install.ts +11 -4
- package/src/stores/settings.ts +13 -9
- package/src/styles/components/app-layout.css +82 -0
- package/src/styles/components/app-page-selector.css +23 -0
- package/src/styles/components/app-pill-nav.css +77 -0
- package/src/styles/components/app-sidebar.css +119 -0
- package/src/styles/components/app-top-bar.css +0 -201
- package/src/styles/components/concentration-input.css +3 -142
- package/src/styles/components/empty-state.css +0 -16
- package/src/styles/components/theme-toggle.css +3 -66
- package/src/styles/index.css +0 -2
- package/src/templates/adapters.ts +785 -0
- package/src/templates/builders.ts +2149 -0
- package/src/templates/catalog.ts +245 -0
- package/src/templates/componentBindings.ts +653 -0
- package/src/templates/controlSchemas.ts +718 -0
- package/src/templates/index.ts +318 -0
- package/src/templates/lookup.ts +18 -0
- package/src/templates/packs.ts +156 -0
- package/src/templates/presets.ts +146 -0
- package/src/templates/types.ts +668 -0
- package/src/types/components.ts +39 -27
- package/src/types/form-builder.ts +7 -2
- package/src/types/index.ts +13 -3
- package/src/types/platform.ts +7 -1
- package/src/utils/formModelSync.ts +52 -0
- package/src/utils/items.ts +28 -0
- package/src/utils/options.ts +23 -0
- package/src/utils/pluginIcon.ts +30 -0
- package/dist/__tests__/composables/usePluginApi.test.d.ts +0 -13
- package/dist/auth-DsI0rQ7_.js.map +0 -1
- package/dist/components/GroupingModal.vue.d.ts +0 -12
- package/dist/components-_XqPEhP9.js.map +0 -1
- package/dist/composables/usePluginApi.d.ts +0 -29
- package/dist/composables-tiZqLu1M.js.map +0 -1
- package/dist/useScheduleDrag-CA9sGNJG.js +0 -7181
- package/dist/useScheduleDrag-CA9sGNJG.js.map +0 -1
- package/src/__tests__/composables/usePluginApi.test.ts +0 -81
- package/src/components/AppPageSelector.vue +0 -159
- package/src/components/AppPillNav.vue +0 -66
- package/src/components/GroupingModal.story.vue +0 -52
- package/src/components/GroupingModal.vue +0 -422
- package/src/components/SettingsButton.story.vue +0 -58
- package/src/components/SettingsButton.vue +0 -76
- package/src/composables/usePluginApi.ts +0 -39
- package/src/styles/components/grouping-modal.css +0 -323
- package/src/styles/components/settings-button.css +0 -94
- /package/dist/components/{ToastNotification.vue.d.ts → AppToastContainer.vue.d.ts} +0 -0
|
@@ -9,8 +9,14 @@ import BaseInput from './BaseInput.vue'
|
|
|
9
9
|
import NumberInput from './NumberInput.vue'
|
|
10
10
|
import FileUploader from './FileUploader.vue'
|
|
11
11
|
import FormField from './FormField.vue'
|
|
12
|
+
import WellPlate from './WellPlate.vue'
|
|
13
|
+
import { defineControlModel, defineControls, getControlDefaults } from '../composables/useControlSchema'
|
|
14
|
+
import { useBioTemplateWorkspace } from '../composables/useBioTemplateWorkspace'
|
|
15
|
+
import { createWellPlateScreenCollection } from '../templates'
|
|
12
16
|
import type { SidebarToolSection } from '../types'
|
|
13
17
|
|
|
18
|
+
type SidebarVariant = 'analysis' | 'default'
|
|
19
|
+
|
|
14
20
|
/* --- Icon paths (Lucide-style) --- */
|
|
15
21
|
const icons = {
|
|
16
22
|
upload: ['M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4', 'M17 8l-5-5-5 5', 'M12 3v12'],
|
|
@@ -126,7 +132,98 @@ const polarity = ref('negative')
|
|
|
126
132
|
const container = ref('vial')
|
|
127
133
|
const expNumber = ref(1)
|
|
128
134
|
const initials = ref('XP')
|
|
135
|
+
const sequencePrefix = ref('exp001_260210_XP')
|
|
136
|
+
const runMode = ref('balanced')
|
|
137
|
+
const runModeOptions = [
|
|
138
|
+
{ value: 'fast', label: 'Fast' },
|
|
139
|
+
{ value: 'balanced', label: 'Balanced' },
|
|
140
|
+
{ value: 'qc', label: 'QC focused' },
|
|
141
|
+
]
|
|
129
142
|
const toggleState = reactive<Record<string, boolean>>({ naming: true, randomize: false })
|
|
143
|
+
const schemaControls = defineControls({
|
|
144
|
+
threshold: {
|
|
145
|
+
type: 'slider',
|
|
146
|
+
label: 'Threshold',
|
|
147
|
+
default: 0.05,
|
|
148
|
+
min: 0,
|
|
149
|
+
max: 1,
|
|
150
|
+
props: { step: 0.01 },
|
|
151
|
+
section: 'parameters',
|
|
152
|
+
sectionLabel: 'Parameters',
|
|
153
|
+
sectionSubtitle: 'Analysis controls',
|
|
154
|
+
view: 'analysis',
|
|
155
|
+
sidebar: {
|
|
156
|
+
icon: icons.settings,
|
|
157
|
+
iconColor: '#6366f1',
|
|
158
|
+
iconBg: '#e0e7ff',
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
method: {
|
|
162
|
+
label: 'Model',
|
|
163
|
+
default: 'linear',
|
|
164
|
+
options: ['linear', 'logistic', 'quadratic'],
|
|
165
|
+
required: true,
|
|
166
|
+
section: 'parameters',
|
|
167
|
+
view: 'analysis',
|
|
168
|
+
},
|
|
169
|
+
showOutliers: {
|
|
170
|
+
label: 'Show outliers',
|
|
171
|
+
default: true,
|
|
172
|
+
section: 'display',
|
|
173
|
+
sectionLabel: 'Display',
|
|
174
|
+
sectionSubtitle: 'Result filters',
|
|
175
|
+
view: 'analysis',
|
|
176
|
+
sidebar: {
|
|
177
|
+
icon: icons.zap,
|
|
178
|
+
iconColor: '#0ea5e9',
|
|
179
|
+
iconBg: '#e0f2fe',
|
|
180
|
+
defaultOpen: false,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
})
|
|
184
|
+
const controlValues = ref<Record<string, unknown>>({ ...getControlDefaults(schemaControls) })
|
|
185
|
+
const modelDrivenSidebarModel = defineControlModel({
|
|
186
|
+
views: {
|
|
187
|
+
analysis: {
|
|
188
|
+
label: 'Analysis',
|
|
189
|
+
sections: {
|
|
190
|
+
parameters: {
|
|
191
|
+
label: 'Parameters',
|
|
192
|
+
description: 'Thresholds and scoring',
|
|
193
|
+
icon: icons.settings,
|
|
194
|
+
controls: {
|
|
195
|
+
threshold: { type: 'number', default: 0.05, min: 0, max: 1 },
|
|
196
|
+
method: ['linear', 'logistic', 'spline'],
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
filters: {
|
|
200
|
+
label: 'Filters',
|
|
201
|
+
description: 'Result cleanup',
|
|
202
|
+
sidebar: {
|
|
203
|
+
icon: icons.zap,
|
|
204
|
+
iconColor: '#0ea5e9',
|
|
205
|
+
iconBg: '#e0f2fe',
|
|
206
|
+
defaultOpen: false,
|
|
207
|
+
},
|
|
208
|
+
controls: {
|
|
209
|
+
showOutliers: true,
|
|
210
|
+
minPeakArea: { type: 'number', default: 1000, min: 0 },
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
})
|
|
217
|
+
const modelDrivenValues = ref<Record<string, unknown>>({})
|
|
218
|
+
const templateCollection = createWellPlateScreenCollection({
|
|
219
|
+
samples: ['Control', 'Treatment'],
|
|
220
|
+
compounds: { 'Drug A': [10, 1, 0.1] },
|
|
221
|
+
})
|
|
222
|
+
const templateWorkspace = useBioTemplateWorkspace(templateCollection)
|
|
223
|
+
const templateValues = ref<Record<string, unknown>>({ ...templateWorkspace.controls.initialValues })
|
|
224
|
+
const templateWellPlateProps = templateWorkspace.componentProps
|
|
225
|
+
.find(binding => binding.component === 'WellPlate')
|
|
226
|
+
?.propsObject ?? {}
|
|
130
227
|
|
|
131
228
|
function handleToggle(id: string, value: boolean) {
|
|
132
229
|
toggleState[id] = value
|
|
@@ -135,8 +232,9 @@ function handleToggle(id: string, value: boolean) {
|
|
|
135
232
|
function initSimpleToolkit() {
|
|
136
233
|
return {
|
|
137
234
|
activeView: 'analysis',
|
|
235
|
+
variant: 'analysis' as SidebarVariant,
|
|
138
236
|
floating: false,
|
|
139
|
-
width: '
|
|
237
|
+
width: '20rem',
|
|
140
238
|
side: 'left' as const,
|
|
141
239
|
}
|
|
142
240
|
}
|
|
@@ -218,6 +316,101 @@ function initSimpleToolkit() {
|
|
|
218
316
|
</div>
|
|
219
317
|
</Variant>
|
|
220
318
|
|
|
319
|
+
<Variant title="Schema Driven Controls">
|
|
320
|
+
<div style="padding: 2rem; height: 520px; position: relative; background: var(--bg-primary, #f1f5f9);">
|
|
321
|
+
<AppSidebar
|
|
322
|
+
variant="analysis"
|
|
323
|
+
title="Peak Picking"
|
|
324
|
+
subtitle="Current experiment"
|
|
325
|
+
:controls="schemaControls"
|
|
326
|
+
active-view="analysis"
|
|
327
|
+
v-model="controlValues"
|
|
328
|
+
/>
|
|
329
|
+
</div>
|
|
330
|
+
</Variant>
|
|
331
|
+
|
|
332
|
+
<Variant title="Model Driven Analysis">
|
|
333
|
+
<div style="padding: 2rem; height: 560px; position: relative; background: var(--bg-primary, #f1f5f9);">
|
|
334
|
+
<AppSidebar
|
|
335
|
+
v-model="modelDrivenValues"
|
|
336
|
+
variant="analysis"
|
|
337
|
+
title="Peak Picking"
|
|
338
|
+
subtitle="Current experiment"
|
|
339
|
+
:model="modelDrivenSidebarModel"
|
|
340
|
+
/>
|
|
341
|
+
</div>
|
|
342
|
+
</Variant>
|
|
343
|
+
|
|
344
|
+
<Variant title="Route Owned Shell">
|
|
345
|
+
<div style="padding: 2rem; height: 560px; display: flex; gap: 1rem; background: var(--bg-primary, #f1f5f9);">
|
|
346
|
+
<AppSidebar
|
|
347
|
+
variant="analysis"
|
|
348
|
+
title="Sequence"
|
|
349
|
+
subtitle="Acquisition run"
|
|
350
|
+
content-id="seqgen-sidebar"
|
|
351
|
+
show-when-empty
|
|
352
|
+
>
|
|
353
|
+
<div style="display: flex; flex-direction: column; gap: 0.75rem;">
|
|
354
|
+
<FormField label="File Prefix">
|
|
355
|
+
<BaseInput v-model="sequencePrefix" size="sm" />
|
|
356
|
+
</FormField>
|
|
357
|
+
<FormField label="Run Mode">
|
|
358
|
+
<BaseSelect v-model="runMode" :options="runModeOptions" size="sm" />
|
|
359
|
+
</FormField>
|
|
360
|
+
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem;">
|
|
361
|
+
<BaseButton size="sm" variant="secondary">NEG</BaseButton>
|
|
362
|
+
<BaseButton size="sm" variant="secondary">VIAL</BaseButton>
|
|
363
|
+
</div>
|
|
364
|
+
</div>
|
|
365
|
+
|
|
366
|
+
<template #footer>
|
|
367
|
+
<div style="display: flex; flex-direction: column; gap: 0.5rem;">
|
|
368
|
+
<BaseButton variant="cta" style="width: 100%;">Generate Sequence</BaseButton>
|
|
369
|
+
<BaseButton variant="ghost" size="sm" style="width: 100%;">Clear Draft</BaseButton>
|
|
370
|
+
</div>
|
|
371
|
+
</template>
|
|
372
|
+
</AppSidebar>
|
|
373
|
+
|
|
374
|
+
<div style="flex: 1; min-width: 0; border: 1px solid var(--border-color, #e5e7eb); border-radius: 0.5rem; background: var(--bg-card, #fff); padding: 1rem;">
|
|
375
|
+
<div style="display: flex; justify-content: space-between; gap: 1rem; align-items: center;">
|
|
376
|
+
<div>
|
|
377
|
+
<div style="font-size: 0.875rem; font-weight: 650; color: var(--text-primary, #111827);">MS queue</div>
|
|
378
|
+
<div style="font-size: 0.75rem; color: var(--text-muted, #6b7280);">{{ sequencePrefix }} · {{ runMode }}</div>
|
|
379
|
+
</div>
|
|
380
|
+
<BaseButton size="sm" variant="secondary">Preview CSV</BaseButton>
|
|
381
|
+
</div>
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
</Variant>
|
|
385
|
+
|
|
386
|
+
<Variant title="Template Driven Controls">
|
|
387
|
+
<div style="padding: 2rem; min-height: 560px; display: flex; gap: 1rem; background: var(--bg-primary, #f1f5f9);">
|
|
388
|
+
<AppSidebar
|
|
389
|
+
v-bind="templateWorkspace.sidebar"
|
|
390
|
+
active-view="design"
|
|
391
|
+
v-model="templateValues"
|
|
392
|
+
width="300px"
|
|
393
|
+
/>
|
|
394
|
+
|
|
395
|
+
<div style="flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.75rem;">
|
|
396
|
+
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
|
|
397
|
+
<span
|
|
398
|
+
v-for="binding in templateWorkspace.componentBindings"
|
|
399
|
+
:key="binding.id"
|
|
400
|
+
style="font-size: 0.75rem; padding: 0.25rem 0.5rem; border: 1px solid var(--border-color, #e5e7eb); border-radius: 0.375rem; background: var(--bg-card, #fff); color: var(--text-secondary, #4b5563);"
|
|
401
|
+
>
|
|
402
|
+
{{ binding.component }}
|
|
403
|
+
</span>
|
|
404
|
+
</div>
|
|
405
|
+
<WellPlate
|
|
406
|
+
v-bind="templateWellPlateProps"
|
|
407
|
+
size="fill"
|
|
408
|
+
readonly
|
|
409
|
+
/>
|
|
410
|
+
</div>
|
|
411
|
+
</div>
|
|
412
|
+
</Variant>
|
|
413
|
+
|
|
221
414
|
<Variant title="Simple Toolkit" :init-state="initSimpleToolkit">
|
|
222
415
|
<template #default="{ state }">
|
|
223
416
|
<div style="padding: 2rem; height: 500px; position: relative; background: var(--bg-primary, #f1f5f9);">
|
|
@@ -241,6 +434,7 @@ function initSimpleToolkit() {
|
|
|
241
434
|
</div>
|
|
242
435
|
<AppSidebar
|
|
243
436
|
:panels="simplePanels"
|
|
437
|
+
:variant="state.variant"
|
|
244
438
|
:active-view="state.activeView"
|
|
245
439
|
:floating="state.floating"
|
|
246
440
|
:width="state.width"
|
|
@@ -271,6 +465,14 @@ function initSimpleToolkit() {
|
|
|
271
465
|
title="Active View"
|
|
272
466
|
:options="['analysis', 'results', 'settings'].map(v => ({ label: v, value: v }))"
|
|
273
467
|
/>
|
|
468
|
+
<HstSelect
|
|
469
|
+
v-model="state.variant"
|
|
470
|
+
title="Variant"
|
|
471
|
+
:options="[
|
|
472
|
+
{ label: 'Analysis', value: 'analysis' },
|
|
473
|
+
{ label: 'Default', value: 'default' },
|
|
474
|
+
]"
|
|
475
|
+
/>
|
|
274
476
|
<HstCheckbox v-model="state.floating" title="Floating" />
|
|
275
477
|
<HstText v-model="state.width" title="Width" />
|
|
276
478
|
<HstSelect
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* AppSidebar - Context-sensitive toolkit panel
|
|
4
4
|
*
|
|
5
|
-
* Shows tool sections relevant to the active view. Sections are defined
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* `#section-{sectionId}`.
|
|
5
|
+
* Shows tool sections relevant to the active view. Sections are defined via
|
|
6
|
+
* the `panels` config and rendered as CollapsibleCards. Controls can be
|
|
7
|
+
* provided through named slots or auto-rendered from FormBuilder schemas.
|
|
9
8
|
*
|
|
10
9
|
* When the active view has no matching panels, the sidebar hides entirely.
|
|
11
10
|
*
|
|
@@ -20,61 +19,287 @@
|
|
|
20
19
|
* </template>
|
|
21
20
|
* <template #header>Plugin Tools</template>
|
|
22
21
|
* </AppSidebar>
|
|
22
|
+
*
|
|
23
|
+
* <!-- Direct schema-driven controls -->
|
|
24
|
+
* <AppSidebar :controls="controls" :active-view="activeTab" v-model="values" />
|
|
23
25
|
* ```
|
|
24
26
|
*/
|
|
25
|
-
import { computed } from 'vue'
|
|
26
|
-
import type { SidebarToolSection } from '../types'
|
|
27
|
+
import { computed, ref, useSlots, type Slots } from 'vue'
|
|
28
|
+
import type { PillNavItem, SidebarToolSection } from '../types'
|
|
29
|
+
import type { FormEnhancements, FormSchema } from '../types/form-builder'
|
|
30
|
+
import {
|
|
31
|
+
controlsToSectionFormSchemas,
|
|
32
|
+
controlsToSidebarPanels,
|
|
33
|
+
defineControlModel,
|
|
34
|
+
getControlDefaults,
|
|
35
|
+
mergeControlWorkspaceOptions,
|
|
36
|
+
type ControlModel,
|
|
37
|
+
type ControlModelBinding,
|
|
38
|
+
type ControlSchema,
|
|
39
|
+
type ControlWorkspaceOptions,
|
|
40
|
+
} from '../composables/useControlSchema'
|
|
27
41
|
import CollapsibleCard from './CollapsibleCard.vue'
|
|
42
|
+
import FormBuilder from './FormBuilder.vue'
|
|
28
43
|
|
|
29
44
|
interface Props {
|
|
45
|
+
/** Optional chrome title rendered above generated sections. */
|
|
46
|
+
title?: string
|
|
47
|
+
/** Optional secondary chrome copy rendered below title. */
|
|
48
|
+
subtitle?: string
|
|
49
|
+
/** Optional compact badge/count rendered in the chrome header. */
|
|
50
|
+
badge?: string | number
|
|
51
|
+
/** Visual preset for common plugin sidebars. `analysis` preserves the LEAF-style MINT analysis sidebar design language. */
|
|
52
|
+
variant?: 'default' | 'analysis'
|
|
30
53
|
/** Map of view IDs to their tool sections */
|
|
31
54
|
panels?: Record<string, SidebarToolSection[]>
|
|
32
55
|
/** Which view's panels to display */
|
|
33
56
|
activeView?: string
|
|
34
|
-
/** Floating variant with absolute positioning */
|
|
57
|
+
/** Floating variant with absolute positioning. Defaults to false for analysis variant. */
|
|
35
58
|
floating?: boolean
|
|
36
59
|
/** Compact layout: smaller headers, tighter spacing, no icon backgrounds */
|
|
37
60
|
dense?: boolean
|
|
38
|
-
/** Width when visible */
|
|
61
|
+
/** Width when visible. Defaults to 20rem for analysis variant, otherwise 280px. */
|
|
39
62
|
width?: string
|
|
40
63
|
/** Position sidebar on left or right side */
|
|
41
64
|
side?: 'left' | 'right'
|
|
42
65
|
/** Toggle state map: sectionId → boolean */
|
|
43
66
|
toggleState?: Record<string, boolean>
|
|
67
|
+
/** Optional FormBuilder schemas keyed by section ID. Used when no section slot is provided. */
|
|
68
|
+
forms?: Record<string, FormSchema>
|
|
69
|
+
/** Generated view IDs from useControlSchema(). Consumed for clean v-bind ergonomics. */
|
|
70
|
+
viewIds?: string[]
|
|
71
|
+
/** Generated AppTopBar pillNav-compatible view items from useControlSchema(). Consumed for clean v-bind ergonomics. */
|
|
72
|
+
viewItems?: PillNavItem[]
|
|
73
|
+
/** Default view ID used when activeView is omitted. */
|
|
74
|
+
defaultView?: string
|
|
75
|
+
/** Model returned by defineControlModel(), or a raw nested ControlModel for one-step sidebar/form generation. */
|
|
76
|
+
model?: ControlModel | ControlModelBinding
|
|
77
|
+
/** Compact control schema. When provided, AppSidebar generates panels, section forms, and default values. */
|
|
78
|
+
controls?: ControlSchema
|
|
79
|
+
/** Options passed to compact control schema generation, including shared initialValues. */
|
|
80
|
+
controlOptions?: ControlWorkspaceOptions
|
|
81
|
+
/** DOM id for the scrollable content area. Use with Teleport when route/tab children own sidebar controls. */
|
|
82
|
+
contentId?: string
|
|
83
|
+
/** Render the sidebar shell even when no panel matches the active view. Useful for default-slot or Teleport-driven sidebars. */
|
|
84
|
+
showWhenEmpty?: boolean
|
|
85
|
+
/** Shared values for auto-rendered section forms. Supports default v-model. */
|
|
86
|
+
modelValue?: Record<string, unknown>
|
|
87
|
+
/** Shared values for auto-rendered section forms */
|
|
88
|
+
values?: Record<string, unknown>
|
|
89
|
+
/** Runtime FormBuilder enhancements for auto-rendered section forms */
|
|
90
|
+
formEnhancements?: FormEnhancements<Record<string, unknown>>
|
|
91
|
+
/** Show submit/cancel actions inside auto-rendered section forms */
|
|
92
|
+
showFormActions?: boolean
|
|
93
|
+
/** Loading/saving state for auto-rendered section forms */
|
|
94
|
+
formLoading?: boolean
|
|
95
|
+
/** Disabled state for auto-rendered section forms */
|
|
96
|
+
formDisabled?: boolean
|
|
97
|
+
/** Readonly state for auto-rendered section forms */
|
|
98
|
+
formReadonly?: boolean
|
|
99
|
+
/** Size passed to auto-rendered section forms */
|
|
100
|
+
formSize?: 'sm' | 'md' | 'lg'
|
|
101
|
+
/** Show a built-in collapse/expand button in the sidebar chrome. Defaults to true for analysis variant. */
|
|
102
|
+
collapsible?: boolean
|
|
103
|
+
/** Controlled collapsed state. */
|
|
104
|
+
collapsed?: boolean
|
|
105
|
+
/** Initial collapsed state when collapsed is uncontrolled. */
|
|
106
|
+
defaultCollapsed?: boolean
|
|
107
|
+
/** Width when collapsed. */
|
|
108
|
+
collapsedWidth?: string
|
|
109
|
+
/** Accessible label for the collapse action. */
|
|
110
|
+
collapseButtonLabel?: string
|
|
111
|
+
/** Accessible label for the expand action. */
|
|
112
|
+
expandButtonLabel?: string
|
|
44
113
|
}
|
|
45
114
|
|
|
46
115
|
const props = withDefaults(defineProps<Props>(), {
|
|
116
|
+
title: undefined,
|
|
117
|
+
subtitle: undefined,
|
|
118
|
+
badge: undefined,
|
|
119
|
+
variant: 'default',
|
|
47
120
|
panels: () => ({}),
|
|
48
121
|
activeView: '',
|
|
49
|
-
floating:
|
|
122
|
+
floating: undefined,
|
|
50
123
|
dense: false,
|
|
51
|
-
width:
|
|
124
|
+
width: undefined,
|
|
52
125
|
side: 'left',
|
|
53
126
|
toggleState: () => ({}),
|
|
127
|
+
forms: () => ({}),
|
|
128
|
+
viewIds: () => [],
|
|
129
|
+
viewItems: () => [],
|
|
130
|
+
defaultView: '',
|
|
131
|
+
model: undefined,
|
|
132
|
+
controlOptions: () => ({}),
|
|
133
|
+
contentId: undefined,
|
|
134
|
+
showWhenEmpty: false,
|
|
135
|
+
modelValue: undefined,
|
|
136
|
+
values: () => ({}),
|
|
137
|
+
showFormActions: false,
|
|
138
|
+
formLoading: false,
|
|
139
|
+
formDisabled: false,
|
|
140
|
+
formReadonly: false,
|
|
141
|
+
formSize: 'sm',
|
|
142
|
+
collapsible: undefined,
|
|
143
|
+
collapsed: undefined,
|
|
144
|
+
defaultCollapsed: false,
|
|
145
|
+
collapsedWidth: '3rem',
|
|
146
|
+
collapseButtonLabel: 'Collapse sidebar',
|
|
147
|
+
expandButtonLabel: 'Expand sidebar',
|
|
54
148
|
})
|
|
55
149
|
|
|
56
|
-
defineEmits<{
|
|
150
|
+
const emit = defineEmits<{
|
|
57
151
|
'update:toggle': [sectionId: string, value: boolean]
|
|
152
|
+
'update:modelValue': [values: Record<string, unknown>]
|
|
153
|
+
'update:values': [values: Record<string, unknown>]
|
|
154
|
+
'update:collapsed': [value: boolean]
|
|
155
|
+
'form-submit': [sectionId: string, values: Record<string, unknown>]
|
|
156
|
+
'form-cancel': [sectionId: string]
|
|
58
157
|
}>()
|
|
59
158
|
|
|
159
|
+
const slots: Slots = useSlots()
|
|
160
|
+
const internalCollapsed = ref(props.defaultCollapsed)
|
|
161
|
+
const collapsedModel = computed({
|
|
162
|
+
get: () => props.collapsed ?? internalCollapsed.value,
|
|
163
|
+
set: (value: boolean) => {
|
|
164
|
+
internalCollapsed.value = value
|
|
165
|
+
emit('update:collapsed', value)
|
|
166
|
+
},
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
const isAnalysisVariant = computed(() => props.variant === 'analysis')
|
|
170
|
+
const resolvedFloating = computed(() => props.floating ?? !isAnalysisVariant.value)
|
|
171
|
+
const resolvedWidth = computed(() => props.width ?? (isAnalysisVariant.value ? '20rem' : '280px'))
|
|
172
|
+
const resolvedCollapsible = computed(() => props.collapsible ?? isAnalysisVariant.value)
|
|
173
|
+
|
|
174
|
+
const resolvedModel = computed<ControlModelBinding | undefined>(() => {
|
|
175
|
+
if (props.model === undefined) return undefined
|
|
176
|
+
return isControlModelBinding(props.model) ? props.model : defineControlModel(props.model)
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const resolvedControls = computed<ControlSchema | undefined>(() =>
|
|
180
|
+
props.controls ?? resolvedModel.value?.controls,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
const resolvedControlOptions = computed<ControlWorkspaceOptions>(() =>
|
|
184
|
+
mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, props.controlOptions)
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
const generatedPanels = computed<Record<string, SidebarToolSection[]>>(() => {
|
|
188
|
+
if (!resolvedControls.value) return {}
|
|
189
|
+
return controlsToSidebarPanels(resolvedControls.value, resolvedControlOptions.value)
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
const generatedForms = computed<Record<string, FormSchema>>(() => {
|
|
193
|
+
if (!resolvedControls.value) return {}
|
|
194
|
+
return controlsToSectionFormSchemas(resolvedControls.value, resolvedControlOptions.value)
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
const generatedDefaults = computed<Record<string, unknown>>(() => {
|
|
198
|
+
if (!resolvedControls.value) return {}
|
|
199
|
+
return {
|
|
200
|
+
...getControlDefaults(resolvedControls.value),
|
|
201
|
+
...(resolvedControlOptions.value.initialValues ?? {}),
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
const resolvedPanels = computed<Record<string, SidebarToolSection[]>>(() =>
|
|
206
|
+
mergeSidebarPanels(generatedPanels.value, props.panels),
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
const resolvedForms = computed<Record<string, FormSchema>>(() => ({
|
|
210
|
+
...generatedForms.value,
|
|
211
|
+
...props.forms,
|
|
212
|
+
}))
|
|
213
|
+
|
|
214
|
+
const resolvedValues = computed<Record<string, unknown>>(() => ({
|
|
215
|
+
...generatedDefaults.value,
|
|
216
|
+
...(props.modelValue ?? props.values),
|
|
217
|
+
}))
|
|
218
|
+
|
|
219
|
+
const resolvedActiveView = computed(() => {
|
|
220
|
+
if (props.activeView) return props.activeView
|
|
221
|
+
if (props.defaultView) return props.defaultView
|
|
222
|
+
if (!resolvedControls.value) return ''
|
|
223
|
+
return firstVisibleViewId(resolvedPanels.value)
|
|
224
|
+
})
|
|
225
|
+
|
|
60
226
|
const activeSections = computed<SidebarToolSection[]>(() => {
|
|
61
|
-
if (!
|
|
62
|
-
return
|
|
227
|
+
if (!resolvedActiveView.value || !resolvedPanels.value[resolvedActiveView.value]) return []
|
|
228
|
+
return resolvedPanels.value[resolvedActiveView.value]
|
|
63
229
|
})
|
|
64
230
|
|
|
65
|
-
const isVisible = computed(() =>
|
|
231
|
+
const isVisible = computed<boolean>(() =>
|
|
232
|
+
activeSections.value.length > 0 || props.showWhenEmpty || Boolean(slots.default),
|
|
233
|
+
)
|
|
66
234
|
|
|
67
|
-
const sidebarClasses = computed(() => [
|
|
235
|
+
const sidebarClasses = computed<string[]>(() => [
|
|
68
236
|
'mint-sidebar',
|
|
69
237
|
`mint-sidebar--${props.side}`,
|
|
70
|
-
|
|
238
|
+
`mint-sidebar--${props.variant}`,
|
|
239
|
+
resolvedFloating.value ? 'mint-sidebar--floating' : 'mint-sidebar--static',
|
|
71
240
|
props.dense ? 'mint-sidebar--dense' : '',
|
|
241
|
+
resolvedCollapsible.value ? 'mint-sidebar--collapsible' : '',
|
|
242
|
+
collapsedModel.value ? 'mint-sidebar--collapsed' : '',
|
|
72
243
|
!isVisible.value ? 'mint-sidebar--hidden' : '',
|
|
73
244
|
])
|
|
74
245
|
|
|
75
|
-
const sidebarStyle = computed(() => ({
|
|
76
|
-
width: props.
|
|
246
|
+
const sidebarStyle = computed<Record<string, string>>(() => ({
|
|
247
|
+
width: collapsedModel.value ? props.collapsedWidth : resolvedWidth.value,
|
|
77
248
|
}))
|
|
249
|
+
|
|
250
|
+
function handleFormUpdate(values: Record<string, unknown>) {
|
|
251
|
+
const nextValues = { ...resolvedValues.value, ...values }
|
|
252
|
+
emit('update:modelValue', nextValues)
|
|
253
|
+
emit('update:values', nextValues)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function handleFormSubmit(sectionId: string, values: Record<string, unknown>) {
|
|
257
|
+
emit('form-submit', sectionId, values)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function handleFormCancel(sectionId: string) {
|
|
261
|
+
emit('form-cancel', sectionId)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function toggleCollapsed() {
|
|
265
|
+
collapsedModel.value = !collapsedModel.value
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function expandCollapsed() {
|
|
269
|
+
collapsedModel.value = false
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function mergeSidebarPanels(
|
|
273
|
+
generated: Record<string, SidebarToolSection[]>,
|
|
274
|
+
explicit: Record<string, SidebarToolSection[]>,
|
|
275
|
+
): Record<string, SidebarToolSection[]> {
|
|
276
|
+
const merged: Record<string, SidebarToolSection[]> = {}
|
|
277
|
+
const viewIds = new Set([...Object.keys(generated), ...Object.keys(explicit)])
|
|
278
|
+
|
|
279
|
+
for (const viewId of viewIds) {
|
|
280
|
+
const sectionsById = new Map<string, SidebarToolSection>()
|
|
281
|
+
for (const section of generated[viewId] ?? []) {
|
|
282
|
+
sectionsById.set(section.id, section)
|
|
283
|
+
}
|
|
284
|
+
for (const section of explicit[viewId] ?? []) {
|
|
285
|
+
sectionsById.set(section.id, section)
|
|
286
|
+
}
|
|
287
|
+
merged[viewId] = [...sectionsById.values()]
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return merged
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function firstVisibleViewId(panels: Record<string, SidebarToolSection[]>): string {
|
|
294
|
+
for (const [viewId, sections] of Object.entries(panels)) {
|
|
295
|
+
if (sections.length > 0) return viewId
|
|
296
|
+
}
|
|
297
|
+
return ''
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function isControlModelBinding(model: ControlModel | ControlModelBinding): model is ControlModelBinding {
|
|
301
|
+
return 'controls' in model && 'controlOptions' in model
|
|
302
|
+
}
|
|
78
303
|
</script>
|
|
79
304
|
|
|
80
305
|
<template>
|
|
@@ -82,13 +307,54 @@ const sidebarStyle = computed(() => ({
|
|
|
82
307
|
:class="sidebarClasses"
|
|
83
308
|
:style="sidebarStyle"
|
|
84
309
|
>
|
|
85
|
-
<!-- Header slot -->
|
|
86
|
-
<div
|
|
87
|
-
|
|
310
|
+
<!-- Header slot / built-in chrome -->
|
|
311
|
+
<div
|
|
312
|
+
v-if="$slots.header || title || subtitle || badge !== undefined || resolvedCollapsible"
|
|
313
|
+
class="mint-sidebar__header"
|
|
314
|
+
>
|
|
315
|
+
<slot
|
|
316
|
+
name="header"
|
|
317
|
+
:collapsed="collapsedModel"
|
|
318
|
+
:toggle-collapsed="toggleCollapsed"
|
|
319
|
+
>
|
|
320
|
+
<div v-if="!collapsedModel" class="mint-sidebar__heading">
|
|
321
|
+
<div class="mint-sidebar__heading-copy">
|
|
322
|
+
<h2 v-if="title" class="mint-sidebar__title">{{ title }}</h2>
|
|
323
|
+
<p v-if="subtitle" class="mint-sidebar__subtitle">{{ subtitle }}</p>
|
|
324
|
+
</div>
|
|
325
|
+
<span v-if="badge !== undefined" class="mint-sidebar__badge">{{ badge }}</span>
|
|
326
|
+
</div>
|
|
327
|
+
<button
|
|
328
|
+
v-if="resolvedCollapsible"
|
|
329
|
+
type="button"
|
|
330
|
+
class="mint-sidebar__collapse-button"
|
|
331
|
+
:aria-label="collapsedModel ? expandButtonLabel : collapseButtonLabel"
|
|
332
|
+
:aria-expanded="!collapsedModel"
|
|
333
|
+
@click="toggleCollapsed"
|
|
334
|
+
>
|
|
335
|
+
<svg
|
|
336
|
+
class="mint-sidebar__collapse-icon"
|
|
337
|
+
:class="{ 'mint-sidebar__collapse-icon--collapsed': collapsedModel }"
|
|
338
|
+
viewBox="0 0 24 24"
|
|
339
|
+
fill="none"
|
|
340
|
+
stroke="currentColor"
|
|
341
|
+
stroke-width="2"
|
|
342
|
+
stroke-linecap="round"
|
|
343
|
+
stroke-linejoin="round"
|
|
344
|
+
aria-hidden="true"
|
|
345
|
+
>
|
|
346
|
+
<path d="M11 19l-7-7 7-7m8 14l-7-7 7-7" />
|
|
347
|
+
</svg>
|
|
348
|
+
</button>
|
|
349
|
+
</slot>
|
|
88
350
|
</div>
|
|
89
351
|
|
|
90
352
|
<!-- Tool sections -->
|
|
91
|
-
<div
|
|
353
|
+
<div
|
|
354
|
+
v-if="!collapsedModel"
|
|
355
|
+
:id="contentId"
|
|
356
|
+
class="mint-sidebar__sections"
|
|
357
|
+
>
|
|
92
358
|
<CollapsibleCard
|
|
93
359
|
v-for="section in activeSections"
|
|
94
360
|
:key="section.id"
|
|
@@ -101,14 +367,43 @@ const sidebarStyle = computed(() => ({
|
|
|
101
367
|
:default-open="section.defaultOpen !== false"
|
|
102
368
|
:show-toggle="section.showToggle"
|
|
103
369
|
:toggle-value="toggleState[section.id] ?? false"
|
|
104
|
-
@update:toggle-value="
|
|
370
|
+
@update:toggle-value="emit('update:toggle', section.id, $event)"
|
|
105
371
|
>
|
|
106
|
-
<slot :name="`section-${section.id}`"
|
|
372
|
+
<slot :name="`section-${section.id}`">
|
|
373
|
+
<FormBuilder
|
|
374
|
+
v-if="resolvedForms[section.id]"
|
|
375
|
+
:model-value="resolvedValues"
|
|
376
|
+
:schema="resolvedForms[section.id]"
|
|
377
|
+
:enhancements="formEnhancements"
|
|
378
|
+
:loading="formLoading"
|
|
379
|
+
:disabled="formDisabled"
|
|
380
|
+
:readonly="formReadonly"
|
|
381
|
+
:size="formSize"
|
|
382
|
+
:show-actions="showFormActions"
|
|
383
|
+
@update:model-value="handleFormUpdate"
|
|
384
|
+
@submit="handleFormSubmit(section.id, $event)"
|
|
385
|
+
@cancel="handleFormCancel(section.id)"
|
|
386
|
+
/>
|
|
387
|
+
</slot>
|
|
107
388
|
</CollapsibleCard>
|
|
389
|
+
|
|
390
|
+
<slot
|
|
391
|
+
:sections="activeSections"
|
|
392
|
+
:active-view="resolvedActiveView"
|
|
393
|
+
:values="resolvedValues"
|
|
394
|
+
/>
|
|
395
|
+
</div>
|
|
396
|
+
|
|
397
|
+
<div v-else-if="$slots.collapsed" class="mint-sidebar__collapsed">
|
|
398
|
+
<slot
|
|
399
|
+
name="collapsed"
|
|
400
|
+
:sections="activeSections"
|
|
401
|
+
:expand="expandCollapsed"
|
|
402
|
+
/>
|
|
108
403
|
</div>
|
|
109
404
|
|
|
110
405
|
<!-- Footer slot -->
|
|
111
|
-
<div v-if="$slots.footer" class="mint-sidebar__footer">
|
|
406
|
+
<div v-if="!collapsedModel && $slots.footer" class="mint-sidebar__footer">
|
|
112
407
|
<slot name="footer" />
|
|
113
408
|
</div>
|
|
114
409
|
</aside>
|