@morscherlab/mint-sdk 1.0.0-beta.2 → 1.0.0-beta.3
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 +218 -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/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/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/FormCompatibility.test.d.ts +1 -0
- package/dist/__tests__/components/GroupAssigner.test.d.ts +1 -0
- package/dist/__tests__/components/GroupingModal.test.d.ts +1 -0
- package/dist/__tests__/components/MultiSelect.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/SettingsButton.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/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/ActionItem.vue.d.ts +32 -0
- package/dist/components/AppAvatarMenu.vue.d.ts +2 -7
- package/dist/components/AppPageSelector.vue.d.ts +3 -6
- package/dist/components/AppPillNav.vue.d.ts +2 -2
- package/dist/components/AppSidebar.vue.d.ts +56 -3
- package/dist/components/AppToastContainer.vue.d.ts +2 -0
- package/dist/components/AppTopBar.vue.d.ts +41 -10
- 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 +117 -0
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +92 -0
- package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +82 -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/CalendarGridPanel.vue.d.ts +25 -0
- package/dist/components/CollapsibleCard.vue.d.ts +1 -1
- 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 +130 -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/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 +22 -8
- package/dist/components/FormFieldRenderer.vue.d.ts +7 -10
- package/dist/components/FormSection.vue.d.ts +11 -24
- 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/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/SettingsButton.vue.d.ts +2 -2
- package/dist/components/SettingsModal.vue.d.ts +13 -5
- 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 +8 -8
- package/dist/components/index.d.ts +11 -1
- package/dist/components/index.js +3 -3
- package/dist/components/internal/FormFieldRendererInternal.vue.d.ts +31 -0
- package/dist/components/internal/FormSectionRenderer.vue.d.ts +43 -0
- package/dist/{components-_XqPEhP9.js → components-D_Sr0adg.js} +7290 -6518
- package/dist/components-D_Sr0adg.js.map +1 -0
- package/dist/composables/index.d.ts +21 -2
- package/dist/composables/index.js +4 -3
- package/dist/composables/platformContextHelpers.d.ts +14 -0
- package/dist/composables/useBioTemplateComponents.d.ts +20 -0
- package/dist/composables/useBioTemplateControls.d.ts +6 -0
- package/dist/composables/useBioTemplatePackWorkspace.d.ts +45 -0
- package/dist/composables/useBioTemplatePresetWorkspace.d.ts +74 -0
- package/dist/composables/useBioTemplateWorkspace.d.ts +50 -0
- package/dist/composables/useCalendarGrid.d.ts +26 -0
- package/dist/composables/useControlSchema.d.ts +321 -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/usePluginApi.d.ts +7 -14
- package/dist/composables/usePluginClient.d.ts +109 -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-C3dpXQN5.js} +228 -146
- package/dist/composables-C3dpXQN5.js.map +1 -0
- package/dist/index.d.ts +12 -3
- 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 +5235 -5977
- 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 +58 -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-50NPjaxL.js +9333 -0
- package/dist/templates-50NPjaxL.js.map +1 -0
- package/dist/types/components.d.ts +26 -4
- 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-D4oWdh41.js +4371 -0
- package/dist/useScheduleDrag-D4oWdh41.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/AppPageSelector.test.ts +134 -0
- package/src/__tests__/components/AppPillNav.test.ts +78 -0
- package/src/__tests__/components/AppPluginSwitcher.test.ts +44 -0
- package/src/__tests__/components/AppSidebar.test.ts +370 -0
- package/src/__tests__/components/AppToastContainer.test.ts +48 -0
- package/src/__tests__/components/AppTopBar.test.ts +383 -0
- 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 +153 -0
- package/src/__tests__/components/BioTemplatePackWorkspaceView.test.ts +161 -0
- package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +281 -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/ConcentrationInput.test.ts +45 -0
- package/src/__tests__/components/ControlWorkspaceView.test.ts +1031 -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/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/FormCompatibility.test.ts +94 -0
- package/src/__tests__/components/GroupAssigner.test.ts +30 -0
- package/src/__tests__/components/GroupingModal.test.ts +73 -0
- package/src/__tests__/components/MultiSelect.test.ts +48 -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/SettingsButton.test.ts +44 -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/useBioTemplatePackWorkspace.test.ts +122 -0
- package/src/__tests__/composables/useBioTemplatePresetWorkspace.test.ts +199 -0
- package/src/__tests__/composables/useBioTemplateWorkspace.test.ts +99 -0
- package/src/__tests__/composables/useCalendarGrid.test.ts +38 -0
- package/src/__tests__/composables/useControlSchema.test.ts +919 -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 +444 -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 +229 -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 +1043 -0
- package/src/components/ActionItem.vue +82 -0
- package/src/components/AppAvatarMenu.vue +15 -69
- package/src/components/AppLayout.story.vue +25 -25
- package/src/components/AppPageSelector.vue +63 -94
- package/src/components/AppPillNav.vue +44 -39
- package/src/components/AppPluginSwitcher.vue +41 -145
- package/src/components/AppSidebar.story.vue +94 -0
- package/src/components/AppSidebar.vue +187 -12
- package/src/components/{ToastNotification.story.vue → AppToastContainer.story.vue} +6 -6
- package/src/components/AppToastContainer.vue +62 -0
- package/src/components/AppTopBar.story.vue +7 -30
- package/src/components/AppTopBar.vue +251 -57
- 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 +337 -0
- package/src/components/BioTemplatePackWorkspaceView.story.vue +107 -0
- package/src/components/BioTemplatePackWorkspaceView.vue +176 -0
- package/src/components/BioTemplatePresetWorkspaceView.story.vue +151 -0
- package/src/components/BioTemplatePresetWorkspaceView.vue +392 -0
- package/src/components/BioTemplateRenderer.story.vue +57 -0
- package/src/components/BioTemplateRenderer.vue +269 -0
- package/src/components/Breadcrumb.vue +14 -8
- package/src/components/CalendarGridPanel.vue +120 -0
- package/src/components/ConcentrationInput.vue +27 -64
- package/src/components/ControlWorkspaceView.story.vue +336 -0
- package/src/components/ControlWorkspaceView.vue +347 -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/DropdownButton.vue +14 -32
- package/src/components/EmptyState.vue +4 -2
- package/src/components/ExperimentPopover.vue +5 -22
- package/src/components/FormBuilder.vue +124 -27
- package/src/components/FormFieldRenderer.vue +15 -38
- package/src/components/FormSection.vue +20 -73
- package/src/components/GroupAssigner.vue +24 -56
- package/src/components/GroupingModal.story.vue +3 -3
- package/src/components/GroupingModal.vue +30 -391
- package/src/components/MultiSelect.vue +17 -12
- package/src/components/PlateMapEditor.vue +3 -8
- package/src/components/PluginIcon.vue +2 -22
- 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/SettingsButton.story.vue +1 -1
- package/src/components/SettingsButton.vue +15 -27
- package/src/components/SettingsModal.story.vue +1 -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/ToastNotification.vue +4 -57
- package/src/components/Tooltip.vue +7 -12
- package/src/components/WellEditPopup.vue +3 -8
- package/src/components/WellPlate.vue +4 -10
- package/src/components/index.ts +11 -1
- package/src/components/internal/FormFieldRendererInternal.vue +50 -0
- package/src/components/internal/FormSectionRenderer.vue +78 -0
- package/src/composables/index.ts +212 -0
- package/src/composables/platformContextHelpers.ts +74 -0
- package/src/composables/useBioTemplateComponents.ts +93 -0
- package/src/composables/useBioTemplateControls.ts +41 -0
- package/src/composables/useBioTemplatePackWorkspace.ts +181 -0
- package/src/composables/useBioTemplatePresetWorkspace.ts +337 -0
- package/src/composables/useBioTemplateWorkspace.ts +139 -0
- package/src/composables/useCalendarGrid.ts +140 -0
- package/src/composables/useControlSchema.ts +1274 -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/usePluginApi.ts +7 -14
- package/src/composables/usePluginClient.ts +425 -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 +224 -4
- package/src/install.ts +11 -4
- package/src/stores/settings.ts +13 -9
- package/src/styles/components/app-page-selector.css +23 -0
- package/src/styles/components/app-pill-nav.css +7 -0
- package/src/styles/components/app-top-bar.css +34 -0
- package/src/styles/components/concentration-input.css +3 -142
- package/src/styles/components/empty-state.css +0 -16
- package/src/styles/components/settings-button.css +3 -66
- package/src/styles/components/theme-toggle.css +3 -66
- package/src/styles/index.css +0 -1
- 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 +615 -0
- package/src/templates/controlSchemas.ts +718 -0
- package/src/templates/index.ts +314 -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 +41 -4
- package/src/types/form-builder.ts +7 -2
- package/src/types/index.ts +14 -0
- 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/auth-DsI0rQ7_.js.map +0 -1
- package/dist/components-_XqPEhP9.js.map +0 -1
- 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/styles/components/grouping-modal.css +0 -323
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/** Preferred toast container driven by useToast, with auto-dismiss progress bar and click-to-close on each notification. */
|
|
3
|
+
import { useToast } from '../composables/useToast'
|
|
4
|
+
import type { Toast } from '../types'
|
|
5
|
+
|
|
6
|
+
const { toasts, dismiss } = useToast()
|
|
7
|
+
|
|
8
|
+
const accentColors: Record<Toast['type'], string> = {
|
|
9
|
+
success: '#10B981',
|
|
10
|
+
error: '#EF4444',
|
|
11
|
+
warning: '#F59E0B',
|
|
12
|
+
info: '#3B82F6',
|
|
13
|
+
}
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<template>
|
|
17
|
+
<Teleport to="body">
|
|
18
|
+
<div class="mint-toast__container">
|
|
19
|
+
<TransitionGroup name="toast">
|
|
20
|
+
<div
|
|
21
|
+
v-for="toast in toasts"
|
|
22
|
+
:key="toast.id"
|
|
23
|
+
:class="['mint-toast__item', `mint-toast__item--${toast.type}`]"
|
|
24
|
+
:style="{
|
|
25
|
+
borderLeftColor: accentColors[toast.type],
|
|
26
|
+
}"
|
|
27
|
+
role="alert"
|
|
28
|
+
@click="dismiss(toast.id)"
|
|
29
|
+
>
|
|
30
|
+
<!-- Lucide circle-check -->
|
|
31
|
+
<svg v-if="toast.type === 'success'" class="mint-toast__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" :style="{ color: accentColors[toast.type] }">
|
|
32
|
+
<circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" />
|
|
33
|
+
</svg>
|
|
34
|
+
<!-- Lucide circle-x -->
|
|
35
|
+
<svg v-else-if="toast.type === 'error'" class="mint-toast__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" :style="{ color: accentColors[toast.type] }">
|
|
36
|
+
<circle cx="12" cy="12" r="10" /><path d="m15 9-6 6" /><path d="m9 9 6 6" />
|
|
37
|
+
</svg>
|
|
38
|
+
<!-- Lucide triangle-alert -->
|
|
39
|
+
<svg v-else-if="toast.type === 'warning'" class="mint-toast__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" :style="{ color: accentColors[toast.type] }">
|
|
40
|
+
<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /><path d="M12 9v4" /><path d="M12 17h.01" />
|
|
41
|
+
</svg>
|
|
42
|
+
<!-- Lucide info -->
|
|
43
|
+
<svg v-else class="mint-toast__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" :style="{ color: accentColors[toast.type] }">
|
|
44
|
+
<circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" />
|
|
45
|
+
</svg>
|
|
46
|
+
<span class="mint-toast__message">{{ toast.message }}</span>
|
|
47
|
+
<span
|
|
48
|
+
class="mint-toast__progress"
|
|
49
|
+
:style="{
|
|
50
|
+
backgroundColor: accentColors[toast.type],
|
|
51
|
+
animationDuration: `${toast.duration ?? 3500}ms`,
|
|
52
|
+
}"
|
|
53
|
+
/>
|
|
54
|
+
</div>
|
|
55
|
+
</TransitionGroup>
|
|
56
|
+
</div>
|
|
57
|
+
</Teleport>
|
|
58
|
+
</template>
|
|
59
|
+
|
|
60
|
+
<style>
|
|
61
|
+
@import '../styles/components/toast.css';
|
|
62
|
+
</style>
|
|
@@ -3,8 +3,6 @@ import AppTopBar from './AppTopBar.vue'
|
|
|
3
3
|
import { ExperimentProvider } from '../__stories__/experiment-helpers'
|
|
4
4
|
import type {
|
|
5
5
|
TopBarVariant,
|
|
6
|
-
TopBarPage,
|
|
7
|
-
TopBarTab,
|
|
8
6
|
PillNavItem,
|
|
9
7
|
PageSelectorItem,
|
|
10
8
|
AccountMenuItem,
|
|
@@ -35,27 +33,6 @@ const sampleAccountMenu: AccountMenuItem[] = [
|
|
|
35
33
|
{ id: 'admin', label: 'Admin', to: '/admin' },
|
|
36
34
|
]
|
|
37
35
|
|
|
38
|
-
const samplePages: TopBarPage[] = [
|
|
39
|
-
{ id: 'dashboard', label: 'Dashboard', description: 'Overview and statistics' },
|
|
40
|
-
{ id: 'experiments', label: 'Experiments', description: 'Manage experiments' },
|
|
41
|
-
{ id: 'analysis', label: 'Analysis', description: 'Run analysis pipelines' },
|
|
42
|
-
{ id: 'settings', label: 'Settings', disabled: true },
|
|
43
|
-
]
|
|
44
|
-
|
|
45
|
-
const sampleTabs: TopBarTab[] = [
|
|
46
|
-
{ id: 'overview', label: 'Overview' },
|
|
47
|
-
{ id: 'results', label: 'Results' },
|
|
48
|
-
{
|
|
49
|
-
id: 'export',
|
|
50
|
-
label: 'Export',
|
|
51
|
-
children: [
|
|
52
|
-
{ id: 'export-csv', label: 'CSV', description: 'Comma-separated values' },
|
|
53
|
-
{ id: 'export-xlsx', label: 'Excel', description: 'Microsoft Excel format' },
|
|
54
|
-
{ id: 'export-pdf', label: 'PDF', description: 'Portable Document Format' },
|
|
55
|
-
],
|
|
56
|
-
},
|
|
57
|
-
]
|
|
58
|
-
|
|
59
36
|
</script>
|
|
60
37
|
|
|
61
38
|
<template>
|
|
@@ -214,7 +191,7 @@ const sampleTabs: TopBarTab[] = [
|
|
|
214
191
|
</div>
|
|
215
192
|
</Variant>
|
|
216
193
|
|
|
217
|
-
<!-- ─────────────── CLASSIC VARIANTS
|
|
194
|
+
<!-- ─────────────── CLASSIC VARIANTS ─────────────── -->
|
|
218
195
|
|
|
219
196
|
<Variant title="Classic · Playground">
|
|
220
197
|
<template #default="{ state }">
|
|
@@ -254,13 +231,13 @@ const sampleTabs: TopBarTab[] = [
|
|
|
254
231
|
</div>
|
|
255
232
|
</Variant>
|
|
256
233
|
|
|
257
|
-
<Variant title="Classic ·
|
|
234
|
+
<Variant title="Classic · Page selector">
|
|
258
235
|
<div style="padding: 2rem;">
|
|
259
236
|
<AppTopBar
|
|
260
237
|
plugin-name="IC50 Calculator"
|
|
261
238
|
title="Results"
|
|
262
|
-
:
|
|
263
|
-
current-page-id="
|
|
239
|
+
:page-selector="samplePageSelector"
|
|
240
|
+
current-page-selector-id="plugins"
|
|
264
241
|
variant="card"
|
|
265
242
|
:show-theme-toggle="true"
|
|
266
243
|
home-path=""
|
|
@@ -268,13 +245,13 @@ const sampleTabs: TopBarTab[] = [
|
|
|
268
245
|
</div>
|
|
269
246
|
</Variant>
|
|
270
247
|
|
|
271
|
-
<Variant title="Classic ·
|
|
248
|
+
<Variant title="Classic · Pill nav">
|
|
272
249
|
<div style="padding: 2rem;">
|
|
273
250
|
<AppTopBar
|
|
274
251
|
plugin-name="Plate Analyzer"
|
|
275
252
|
title="Experiment View"
|
|
276
|
-
:
|
|
277
|
-
current-
|
|
253
|
+
:pill-nav="samplePillNav.slice(0, 3)"
|
|
254
|
+
current-pill-id="workspace"
|
|
278
255
|
variant="card"
|
|
279
256
|
home-path=""
|
|
280
257
|
/>
|
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/** Full application top bar with brand logo, page selector or plugin switcher, centered pill nav, experiment popover, and avatar menu. */
|
|
3
|
-
import { ref, computed, inject
|
|
3
|
+
import { ref, computed, inject } from 'vue'
|
|
4
4
|
import type {
|
|
5
5
|
TopBarPage,
|
|
6
|
+
TopBarPageInput,
|
|
6
7
|
TopBarTab,
|
|
8
|
+
TopBarTabInput,
|
|
7
9
|
TopBarTabOption,
|
|
10
|
+
TopBarTabOptionInput,
|
|
8
11
|
TopBarSettingsConfig,
|
|
9
12
|
TopBarVariant,
|
|
10
13
|
PillNavItem,
|
|
14
|
+
PillNavItemInput,
|
|
11
15
|
PageSelectorItem,
|
|
16
|
+
PageSelectorItemInput,
|
|
12
17
|
PluginSwitcherInfo,
|
|
13
18
|
PluginSwitcherPlugin,
|
|
14
19
|
AccountMenuItem,
|
|
20
|
+
SettingsTab,
|
|
15
21
|
} from '../types/components'
|
|
22
|
+
import type { PluginNavItem } from '../types/platform'
|
|
23
|
+
import { normalizeItemInput } from '../utils/items'
|
|
24
|
+
import { isPluginIconFormat } from '../utils/pluginIcon'
|
|
16
25
|
import ThemeToggle from './ThemeToggle.vue'
|
|
17
26
|
import SettingsModal from './SettingsModal.vue'
|
|
18
27
|
import ExperimentPopover from './ExperimentPopover.vue'
|
|
@@ -24,45 +33,72 @@ import AppPluginSwitcher from './AppPluginSwitcher.vue'
|
|
|
24
33
|
import PluginIcon from './PluginIcon.vue'
|
|
25
34
|
import { usePlatformContext } from '../composables/usePlatformContext'
|
|
26
35
|
import { APP_EXPERIMENT_KEY } from '../composables/useAppExperiment'
|
|
36
|
+
import { useEventListener } from '../composables/useEventListener'
|
|
37
|
+
import { useDropdownState } from '../composables/useDropdownState'
|
|
27
38
|
|
|
28
39
|
interface Props {
|
|
29
|
-
|
|
40
|
+
/** App or plugin title shown in the left title group when no page selector is present. */
|
|
30
41
|
title?: string
|
|
42
|
+
/** Secondary title copy shown under the title in title-group layouts. */
|
|
31
43
|
subtitle?: string
|
|
44
|
+
/** Show the default MINT logo when the icon/logo slot is not provided. */
|
|
32
45
|
showLogo?: boolean
|
|
46
|
+
/** Top bar visual treatment. */
|
|
33
47
|
variant?: TopBarVariant
|
|
34
|
-
|
|
35
|
-
pages?: TopBarPage[]
|
|
36
|
-
currentPageId?: string
|
|
37
|
-
tabs?: TopBarTab[]
|
|
38
|
-
currentTabId?: string
|
|
48
|
+
/** Home link used by classic breadcrumb layouts. */
|
|
39
49
|
homePath?: string
|
|
40
50
|
|
|
41
|
-
|
|
42
|
-
pageSelector?:
|
|
51
|
+
/** Preferred route-level page switch entries for plugin and platform pages. */
|
|
52
|
+
pageSelector?: PageSelectorItemInput[]
|
|
53
|
+
/** Active id for the preferred page selector. */
|
|
43
54
|
currentPageSelectorId?: string
|
|
55
|
+
/** Optional plugin switcher shown in the left navigation position instead of pageSelector. */
|
|
44
56
|
pluginSwitcher?: PluginSwitcherInfo
|
|
45
57
|
|
|
46
|
-
|
|
47
|
-
pillNav?:
|
|
58
|
+
/** Preferred centered navigation for local modes inside the current route. */
|
|
59
|
+
pillNav?: PillNavItemInput[]
|
|
60
|
+
/** Active id for the preferred centered pill navigation. */
|
|
48
61
|
currentPillId?: string
|
|
49
62
|
|
|
50
|
-
|
|
63
|
+
/** Account dropdown entries. Takes precedence over the classic profile button. */
|
|
51
64
|
accountMenu?: AccountMenuItem[]
|
|
65
|
+
/** Show the notifications icon button. */
|
|
52
66
|
showNotifications?: boolean
|
|
67
|
+
/** Draw a notification dot on the notifications icon. */
|
|
53
68
|
hasNotificationDot?: boolean
|
|
54
69
|
|
|
55
|
-
|
|
70
|
+
/** Compatibility breadcrumb plugin name. Prefer pageSelector for route-level pages. */
|
|
71
|
+
pluginName?: string
|
|
72
|
+
/** Compatibility page dropdown items. Prefer pageSelector for new route-level navigation. */
|
|
73
|
+
pages?: TopBarPageInput[]
|
|
74
|
+
/** Active id for the compatibility page dropdown. */
|
|
75
|
+
currentPageId?: string
|
|
76
|
+
/** Compatibility center tabs. Prefer pillNav for new in-page modes. */
|
|
77
|
+
tabs?: TopBarTabInput[]
|
|
78
|
+
/** Active id for compatibility center tabs. */
|
|
79
|
+
currentTabId?: string
|
|
80
|
+
|
|
81
|
+
/** Show the theme toggle button. */
|
|
56
82
|
showThemeToggle?: boolean
|
|
83
|
+
/** Show the settings button and modal. */
|
|
57
84
|
showSettings?: boolean
|
|
85
|
+
/** Built-in SettingsModal configuration. */
|
|
58
86
|
settingsConfig?: TopBarSettingsConfig
|
|
87
|
+
/** Show the standalone badge when the plugin is not integrated into the platform. */
|
|
59
88
|
showStandaloneLabel?: boolean
|
|
89
|
+
/** Custom standalone badge label. */
|
|
60
90
|
standaloneLabel?: string
|
|
91
|
+
/** Show the classic admin shortcut. */
|
|
61
92
|
showAdmin?: boolean
|
|
93
|
+
/** Route used by the classic admin shortcut. */
|
|
62
94
|
adminPath?: string
|
|
95
|
+
/** Show the classic profile button when accountMenu is not provided. */
|
|
63
96
|
showProfile?: boolean
|
|
97
|
+
/** Classic profile display name. */
|
|
64
98
|
userName?: string
|
|
99
|
+
/** Explicit classic profile initial. */
|
|
65
100
|
userInitial?: string
|
|
101
|
+
/** Classic profile email, used by avatar/account layouts. */
|
|
66
102
|
userEmail?: string
|
|
67
103
|
}
|
|
68
104
|
|
|
@@ -111,21 +147,22 @@ const profileInitial = computed(() => {
|
|
|
111
147
|
return 'U'
|
|
112
148
|
})
|
|
113
149
|
|
|
150
|
+
const hasPlatformPages = computed(() => props.pages === undefined && !!plugin.value?.nav_items?.length)
|
|
151
|
+
const effectivePluginName = computed(() => props.pluginName ?? (hasPlatformPages.value ? plugin.value?.name : '') ?? '')
|
|
114
152
|
const hasPageSelector = computed(() => !!props.pageSelector?.length)
|
|
115
153
|
const hasPluginSwitcher = computed(() => !!props.pluginSwitcher)
|
|
116
154
|
const hasPillNav = computed(() => !!props.pillNav?.length)
|
|
117
155
|
const hasAccountMenu = computed(() => !!props.accountMenu?.length)
|
|
118
156
|
const hasLegacyBreadcrumb = computed(
|
|
119
|
-
() => !hasPageSelector.value && !hasPluginSwitcher.value && (!!
|
|
157
|
+
() => !hasPageSelector.value && !hasPluginSwitcher.value && (!!effectivePluginName.value || normalizedPages.value.length > 0),
|
|
120
158
|
)
|
|
121
159
|
const hasTitleGroup = computed(
|
|
122
160
|
() =>
|
|
123
161
|
!hasPageSelector.value &&
|
|
124
162
|
!hasPluginSwitcher.value &&
|
|
163
|
+
!hasLegacyBreadcrumb.value &&
|
|
125
164
|
!!props.title &&
|
|
126
|
-
!!props.subtitle
|
|
127
|
-
!props.pluginName &&
|
|
128
|
-
!props.pages?.length,
|
|
165
|
+
!!props.subtitle
|
|
129
166
|
)
|
|
130
167
|
const hasTitleOnly = computed(
|
|
131
168
|
() =>
|
|
@@ -135,25 +172,104 @@ const hasTitleOnly = computed(
|
|
|
135
172
|
!hasLegacyBreadcrumb.value &&
|
|
136
173
|
!!props.title,
|
|
137
174
|
)
|
|
175
|
+
const normalizedPages = computed<TopBarPage[]>(() =>
|
|
176
|
+
props.pages !== undefined
|
|
177
|
+
? props.pages.map(normalizeItemInput)
|
|
178
|
+
: plugin.value?.nav_items?.map(pluginNavItemToPage) ?? [],
|
|
179
|
+
)
|
|
180
|
+
const normalizedTabs = computed<TopBarTab[]>(() => props.tabs?.map(normalizeTopBarTabInput) ?? [])
|
|
181
|
+
const normalizedPageSelector = computed<PageSelectorItem[]>(() => props.pageSelector?.map(normalizeItemInput) ?? [])
|
|
182
|
+
const normalizedPillNav = computed<PillNavItem[]>(() => props.pillNav?.map(normalizeItemInput) ?? [])
|
|
183
|
+
const normalizedSettingsTabs = computed<SettingsTab[]>(() =>
|
|
184
|
+
props.settingsConfig?.tabs?.map(normalizeItemInput) ?? [],
|
|
185
|
+
)
|
|
186
|
+
const effectiveCurrentPageId = computed(() =>
|
|
187
|
+
props.currentPageId
|
|
188
|
+
?? (hasPlatformPages.value ? currentPageIdFromLocation(normalizedPages.value) : undefined)
|
|
189
|
+
?? (hasPlatformPages.value ? normalizedPages.value[0]?.id : undefined),
|
|
190
|
+
)
|
|
191
|
+
const currentLegacyPage = computed(() =>
|
|
192
|
+
normalizedPages.value.find((page) => page.id === effectiveCurrentPageId.value),
|
|
193
|
+
)
|
|
194
|
+
const effectiveTitle = computed(() =>
|
|
195
|
+
props.title ?? (hasPlatformPages.value ? currentLegacyPage.value?.label : undefined),
|
|
196
|
+
)
|
|
138
197
|
|
|
139
|
-
const
|
|
140
|
-
|
|
198
|
+
const {
|
|
199
|
+
isOpen: showPagesDropdown,
|
|
200
|
+
rootRef: dropdownRef,
|
|
201
|
+
close: closePagesDropdown,
|
|
202
|
+
toggle: togglePagesDropdownBase,
|
|
203
|
+
} = useDropdownState()
|
|
141
204
|
const openTabDropdown = ref<string | null>(null)
|
|
142
205
|
const tabDropdownRefs = ref<Map<string, HTMLElement>>(new Map())
|
|
143
206
|
|
|
144
207
|
function togglePagesDropdown() {
|
|
145
|
-
|
|
208
|
+
togglePagesDropdownBase()
|
|
146
209
|
openTabDropdown.value = null
|
|
147
210
|
}
|
|
148
211
|
|
|
212
|
+
function normalizeTopBarTabInput(tab: TopBarTabInput): TopBarTab {
|
|
213
|
+
const normalized = normalizeItemInput<Omit<TopBarTab, 'children'> & { children?: TopBarTabOptionInput[] }>(tab)
|
|
214
|
+
return {
|
|
215
|
+
...normalized,
|
|
216
|
+
children: normalized.children?.map(normalizeItemInput),
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function isSvgTabIcon(icon?: string): icon is string {
|
|
221
|
+
return !!icon && (icon.startsWith('M') || icon.startsWith('m'))
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function normalizeNavPath(path?: string): string {
|
|
225
|
+
const raw = path?.trim() || '/'
|
|
226
|
+
const prefixed = raw.startsWith('/') ? raw : `/${raw}`
|
|
227
|
+
return prefixed.replace(/\/+$/, '') || '/'
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function pageIdFromPath(path: string, fallback: string): string {
|
|
231
|
+
const normalized = normalizeNavPath(path)
|
|
232
|
+
if (normalized === '/') return 'dashboard'
|
|
233
|
+
return normalized.replace(/^\/+/, '').replace(/\/+/g, '-') || fallback
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function pluginNavItemToPage(item: PluginNavItem, index: number): TopBarPage {
|
|
237
|
+
const path = normalizeNavPath(item.path)
|
|
238
|
+
return {
|
|
239
|
+
id: item.id || pageIdFromPath(path, `page-${index + 1}`),
|
|
240
|
+
label: item.label,
|
|
241
|
+
to: path,
|
|
242
|
+
icon: item.icon || plugin.value?.icon,
|
|
243
|
+
description: item.description,
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function currentPagePath(): string | undefined {
|
|
248
|
+
if (typeof window === 'undefined') return undefined
|
|
249
|
+
const pathname = normalizeNavPath(window.location.pathname)
|
|
250
|
+
const routePrefix = normalizeNavPath(plugin.value?.route_prefix)
|
|
251
|
+
|
|
252
|
+
if (pathname === routePrefix) return '/'
|
|
253
|
+
if (routePrefix !== '/' && pathname.startsWith(`${routePrefix}/`)) {
|
|
254
|
+
return normalizeNavPath(pathname.slice(routePrefix.length))
|
|
255
|
+
}
|
|
256
|
+
return pathname
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function currentPageIdFromLocation(pages: TopBarPage[]): string | undefined {
|
|
260
|
+
const path = currentPagePath()
|
|
261
|
+
if (!path) return undefined
|
|
262
|
+
return pages.find((page) => normalizeNavPath(page.to || page.href) === path)?.id
|
|
263
|
+
}
|
|
264
|
+
|
|
149
265
|
function handlePageClick(page: TopBarPage) {
|
|
150
266
|
if (page.disabled) return
|
|
151
267
|
emit('page-select', page)
|
|
152
|
-
|
|
268
|
+
closePagesDropdown()
|
|
153
269
|
}
|
|
154
270
|
|
|
155
271
|
function toggleTabDropdown(tabId: string) {
|
|
156
|
-
|
|
272
|
+
closePagesDropdown()
|
|
157
273
|
openTabDropdown.value = openTabDropdown.value === tabId ? null : tabId
|
|
158
274
|
}
|
|
159
275
|
|
|
@@ -184,10 +300,6 @@ function setTabDropdownRef(el: HTMLElement | null, tabId: string) {
|
|
|
184
300
|
function handleClickOutside(event: MouseEvent) {
|
|
185
301
|
const target = event.target as Node
|
|
186
302
|
|
|
187
|
-
if (showPagesDropdown.value && dropdownRef.value && !dropdownRef.value.contains(target)) {
|
|
188
|
-
showPagesDropdown.value = false
|
|
189
|
-
}
|
|
190
|
-
|
|
191
303
|
if (openTabDropdown.value !== null) {
|
|
192
304
|
const clickedInside = Array.from(tabDropdownRefs.value.values()).some((el) => el.contains(target))
|
|
193
305
|
if (!clickedInside) {
|
|
@@ -196,13 +308,7 @@ function handleClickOutside(event: MouseEvent) {
|
|
|
196
308
|
}
|
|
197
309
|
}
|
|
198
310
|
|
|
199
|
-
|
|
200
|
-
document.addEventListener('click', handleClickOutside)
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
onUnmounted(() => {
|
|
204
|
-
document.removeEventListener('click', handleClickOutside)
|
|
205
|
-
})
|
|
311
|
+
useEventListener(() => document, 'click', handleClickOutside)
|
|
206
312
|
</script>
|
|
207
313
|
|
|
208
314
|
<template>
|
|
@@ -293,8 +399,8 @@ onUnmounted(() => {
|
|
|
293
399
|
@install-click="emit('plugin-switcher-install')"
|
|
294
400
|
/>
|
|
295
401
|
<AppPageSelector
|
|
296
|
-
v-else-if="hasPageSelector
|
|
297
|
-
:pages="
|
|
402
|
+
v-else-if="hasPageSelector"
|
|
403
|
+
:pages="normalizedPageSelector"
|
|
298
404
|
:current-page-id="currentPageSelectorId"
|
|
299
405
|
@select="emit('page-selector-select', $event)"
|
|
300
406
|
>
|
|
@@ -314,12 +420,12 @@ onUnmounted(() => {
|
|
|
314
420
|
|
|
315
421
|
<div v-else-if="hasLegacyBreadcrumb" ref="dropdownRef" class="mint-topbar-breadcrumb">
|
|
316
422
|
<button
|
|
317
|
-
v-if="
|
|
423
|
+
v-if="normalizedPages.length"
|
|
318
424
|
type="button"
|
|
319
425
|
class="mint-topbar-plugin-name"
|
|
320
426
|
@click.stop="togglePagesDropdown"
|
|
321
427
|
>
|
|
322
|
-
{{
|
|
428
|
+
{{ effectivePluginName }}
|
|
323
429
|
<svg
|
|
324
430
|
class="mint-topbar-chevron"
|
|
325
431
|
:class="{ 'mint-topbar-chevron--open': showPagesDropdown }"
|
|
@@ -335,10 +441,10 @@ onUnmounted(() => {
|
|
|
335
441
|
<path d="m6 9 6 6 6-6" />
|
|
336
442
|
</svg>
|
|
337
443
|
</button>
|
|
338
|
-
<span v-else class="mint-topbar-plugin-name--static">{{
|
|
444
|
+
<span v-else class="mint-topbar-plugin-name--static">{{ effectivePluginName }}</span>
|
|
339
445
|
|
|
340
446
|
<svg
|
|
341
|
-
v-if="
|
|
447
|
+
v-if="effectiveTitle"
|
|
342
448
|
class="mint-topbar-separator"
|
|
343
449
|
width="16"
|
|
344
450
|
height="16"
|
|
@@ -351,36 +457,69 @@ onUnmounted(() => {
|
|
|
351
457
|
>
|
|
352
458
|
<path d="m9 18 6-6-6-6" />
|
|
353
459
|
</svg>
|
|
354
|
-
<span v-if="
|
|
460
|
+
<span v-if="effectiveTitle" class="mint-topbar-current-page">{{ effectiveTitle }}</span>
|
|
355
461
|
|
|
356
462
|
<div v-show="showPagesDropdown" class="mint-topbar-dropdown">
|
|
357
|
-
<template v-for="page in
|
|
463
|
+
<template v-for="page in normalizedPages" :key="page.id">
|
|
358
464
|
<a
|
|
359
465
|
v-if="page.href"
|
|
360
466
|
:href="page.href"
|
|
361
|
-
:class="['mint-topbar-dropdown-item', { 'mint-topbar-dropdown-item--active': page.id ===
|
|
362
|
-
@click="
|
|
467
|
+
:class="['mint-topbar-dropdown-item', { 'mint-topbar-dropdown-item--active': page.id === effectiveCurrentPageId, 'mint-topbar-dropdown-item--disabled': page.disabled }]"
|
|
468
|
+
@click="closePagesDropdown"
|
|
363
469
|
>
|
|
364
|
-
<span class="mint-topbar-dropdown-
|
|
365
|
-
|
|
470
|
+
<span class="mint-topbar-dropdown-item__page">
|
|
471
|
+
<PluginIcon
|
|
472
|
+
v-if="isPluginIconFormat(page.icon)"
|
|
473
|
+
class="mint-topbar-dropdown-item__icon"
|
|
474
|
+
:icon="page.icon"
|
|
475
|
+
size="sm"
|
|
476
|
+
variant="tinted"
|
|
477
|
+
/>
|
|
478
|
+
<span class="mint-topbar-dropdown-item__copy">
|
|
479
|
+
<span class="mint-topbar-dropdown-item__label">{{ page.label }}</span>
|
|
480
|
+
<span v-if="page.description" class="mint-topbar-dropdown-item__description">{{ page.description }}</span>
|
|
481
|
+
</span>
|
|
482
|
+
</span>
|
|
366
483
|
</a>
|
|
367
484
|
<router-link
|
|
368
485
|
v-else-if="page.to"
|
|
369
486
|
:to="page.to"
|
|
370
|
-
:class="['mint-topbar-dropdown-item', { 'mint-topbar-dropdown-item--active': page.id ===
|
|
371
|
-
@click="
|
|
487
|
+
:class="['mint-topbar-dropdown-item', { 'mint-topbar-dropdown-item--active': page.id === effectiveCurrentPageId, 'mint-topbar-dropdown-item--disabled': page.disabled }]"
|
|
488
|
+
@click="closePagesDropdown"
|
|
372
489
|
>
|
|
373
|
-
<span class="mint-topbar-dropdown-
|
|
374
|
-
|
|
490
|
+
<span class="mint-topbar-dropdown-item__page">
|
|
491
|
+
<PluginIcon
|
|
492
|
+
v-if="isPluginIconFormat(page.icon)"
|
|
493
|
+
class="mint-topbar-dropdown-item__icon"
|
|
494
|
+
:icon="page.icon"
|
|
495
|
+
size="sm"
|
|
496
|
+
variant="tinted"
|
|
497
|
+
/>
|
|
498
|
+
<span class="mint-topbar-dropdown-item__copy">
|
|
499
|
+
<span class="mint-topbar-dropdown-item__label">{{ page.label }}</span>
|
|
500
|
+
<span v-if="page.description" class="mint-topbar-dropdown-item__description">{{ page.description }}</span>
|
|
501
|
+
</span>
|
|
502
|
+
</span>
|
|
375
503
|
</router-link>
|
|
376
504
|
<button
|
|
377
505
|
v-else
|
|
378
506
|
type="button"
|
|
379
|
-
:class="['mint-topbar-dropdown-item', { 'mint-topbar-dropdown-item--active': page.id ===
|
|
507
|
+
:class="['mint-topbar-dropdown-item', { 'mint-topbar-dropdown-item--active': page.id === effectiveCurrentPageId, 'mint-topbar-dropdown-item--disabled': page.disabled }]"
|
|
380
508
|
@click="handlePageClick(page)"
|
|
381
509
|
>
|
|
382
|
-
<span class="mint-topbar-dropdown-
|
|
383
|
-
|
|
510
|
+
<span class="mint-topbar-dropdown-item__page">
|
|
511
|
+
<PluginIcon
|
|
512
|
+
v-if="isPluginIconFormat(page.icon)"
|
|
513
|
+
class="mint-topbar-dropdown-item__icon"
|
|
514
|
+
:icon="page.icon"
|
|
515
|
+
size="sm"
|
|
516
|
+
variant="tinted"
|
|
517
|
+
/>
|
|
518
|
+
<span class="mint-topbar-dropdown-item__copy">
|
|
519
|
+
<span class="mint-topbar-dropdown-item__label">{{ page.label }}</span>
|
|
520
|
+
<span v-if="page.description" class="mint-topbar-dropdown-item__description">{{ page.description }}</span>
|
|
521
|
+
</span>
|
|
522
|
+
</span>
|
|
384
523
|
</button>
|
|
385
524
|
</template>
|
|
386
525
|
</div>
|
|
@@ -396,7 +535,7 @@ onUnmounted(() => {
|
|
|
396
535
|
<slot name="center">
|
|
397
536
|
<AppPillNav
|
|
398
537
|
v-if="hasPillNav && pillNav"
|
|
399
|
-
:items="
|
|
538
|
+
:items="normalizedPillNav"
|
|
400
539
|
:current-item-id="currentPillId"
|
|
401
540
|
@select="emit('pill-select', $event)"
|
|
402
541
|
/>
|
|
@@ -406,9 +545,9 @@ onUnmounted(() => {
|
|
|
406
545
|
<!-- Center: classic tabs (when no pillNav) — wrapped in the same centered
|
|
407
546
|
container as AppPillNav so classic :tabs consumers get centered pill
|
|
408
547
|
layout without migrating to :pill-nav. -->
|
|
409
|
-
<div v-if="!hasPillNav &&
|
|
548
|
+
<div v-if="!hasPillNav && normalizedTabs.length" class="mint-topbar__center">
|
|
410
549
|
<div class="mint-topbar__tabs">
|
|
411
|
-
<template v-for="tab in
|
|
550
|
+
<template v-for="tab in normalizedTabs" :key="tab.id">
|
|
412
551
|
<div
|
|
413
552
|
:ref="(el) => tab.children?.length ? setTabDropdownRef(el as HTMLElement, tab.id) : null"
|
|
414
553
|
class="mint-topbar-tab-wrapper"
|
|
@@ -423,6 +562,19 @@ onUnmounted(() => {
|
|
|
423
562
|
]"
|
|
424
563
|
@click.stop="handleTabClick(tab)"
|
|
425
564
|
>
|
|
565
|
+
<svg
|
|
566
|
+
v-if="isSvgTabIcon(tab.icon)"
|
|
567
|
+
class="mint-topbar-tab-icon"
|
|
568
|
+
viewBox="0 0 24 24"
|
|
569
|
+
fill="none"
|
|
570
|
+
stroke="currentColor"
|
|
571
|
+
stroke-width="2"
|
|
572
|
+
stroke-linecap="round"
|
|
573
|
+
stroke-linejoin="round"
|
|
574
|
+
aria-hidden="true"
|
|
575
|
+
>
|
|
576
|
+
<path :d="tab.icon" />
|
|
577
|
+
</svg>
|
|
426
578
|
{{ tab.label }}
|
|
427
579
|
<svg
|
|
428
580
|
class="mint-topbar-tab-chevron"
|
|
@@ -449,6 +601,19 @@ onUnmounted(() => {
|
|
|
449
601
|
{ 'mint-topbar-tab--disabled': tab.disabled }
|
|
450
602
|
]"
|
|
451
603
|
>
|
|
604
|
+
<svg
|
|
605
|
+
v-if="isSvgTabIcon(tab.icon)"
|
|
606
|
+
class="mint-topbar-tab-icon"
|
|
607
|
+
viewBox="0 0 24 24"
|
|
608
|
+
fill="none"
|
|
609
|
+
stroke="currentColor"
|
|
610
|
+
stroke-width="2"
|
|
611
|
+
stroke-linecap="round"
|
|
612
|
+
stroke-linejoin="round"
|
|
613
|
+
aria-hidden="true"
|
|
614
|
+
>
|
|
615
|
+
<path :d="tab.icon" />
|
|
616
|
+
</svg>
|
|
452
617
|
{{ tab.label }}
|
|
453
618
|
</a>
|
|
454
619
|
<router-link
|
|
@@ -460,6 +625,19 @@ onUnmounted(() => {
|
|
|
460
625
|
{ 'mint-topbar-tab--disabled': tab.disabled }
|
|
461
626
|
]"
|
|
462
627
|
>
|
|
628
|
+
<svg
|
|
629
|
+
v-if="isSvgTabIcon(tab.icon)"
|
|
630
|
+
class="mint-topbar-tab-icon"
|
|
631
|
+
viewBox="0 0 24 24"
|
|
632
|
+
fill="none"
|
|
633
|
+
stroke="currentColor"
|
|
634
|
+
stroke-width="2"
|
|
635
|
+
stroke-linecap="round"
|
|
636
|
+
stroke-linejoin="round"
|
|
637
|
+
aria-hidden="true"
|
|
638
|
+
>
|
|
639
|
+
<path :d="tab.icon" />
|
|
640
|
+
</svg>
|
|
463
641
|
{{ tab.label }}
|
|
464
642
|
</router-link>
|
|
465
643
|
<button
|
|
@@ -472,6 +650,19 @@ onUnmounted(() => {
|
|
|
472
650
|
]"
|
|
473
651
|
@click="handleTabClick(tab)"
|
|
474
652
|
>
|
|
653
|
+
<svg
|
|
654
|
+
v-if="isSvgTabIcon(tab.icon)"
|
|
655
|
+
class="mint-topbar-tab-icon"
|
|
656
|
+
viewBox="0 0 24 24"
|
|
657
|
+
fill="none"
|
|
658
|
+
stroke="currentColor"
|
|
659
|
+
stroke-width="2"
|
|
660
|
+
stroke-linecap="round"
|
|
661
|
+
stroke-linejoin="round"
|
|
662
|
+
aria-hidden="true"
|
|
663
|
+
>
|
|
664
|
+
<path :d="tab.icon" />
|
|
665
|
+
</svg>
|
|
475
666
|
{{ tab.label }}
|
|
476
667
|
</button>
|
|
477
668
|
|
|
@@ -634,16 +825,19 @@ onUnmounted(() => {
|
|
|
634
825
|
v-if="showSettings"
|
|
635
826
|
v-model="settingsOpen"
|
|
636
827
|
:title="settingsConfig?.title"
|
|
637
|
-
:tabs="
|
|
828
|
+
:tabs="normalizedSettingsTabs"
|
|
638
829
|
:show-appearance="settingsConfig?.showAppearance ?? true"
|
|
639
830
|
:size="settingsConfig?.size"
|
|
640
831
|
:layout="settingsConfig?.layout"
|
|
641
832
|
:schema="settingsConfig?.schema"
|
|
833
|
+
:model="settingsConfig?.model"
|
|
834
|
+
:controls="settingsConfig?.controls"
|
|
835
|
+
:control-options="settingsConfig?.controlOptions"
|
|
642
836
|
:values="settingsConfig?.values"
|
|
643
837
|
:enhancements="settingsConfig?.enhancements"
|
|
644
838
|
@update:values="emit('settings-values-change', $event)"
|
|
645
839
|
>
|
|
646
|
-
<template v-for="tab in
|
|
840
|
+
<template v-for="tab in normalizedSettingsTabs" :key="tab.id" #[`tab-${tab.id}`]>
|
|
647
841
|
<slot :name="`settings-tab-${tab.id}`" />
|
|
648
842
|
</template>
|
|
649
843
|
<template #appearance>
|