@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
|
@@ -2,43 +2,75 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Schema-driven form component that renders flat or multi-step wizard forms.
|
|
4
4
|
*
|
|
5
|
-
* Pass a `FormSchema` with either `sections` (flat) or `steps` (wizard)
|
|
5
|
+
* Pass a `FormSchema` with either `sections` (flat) or `steps` (wizard), or
|
|
6
|
+
* pass a compact `controls` schema for standard generated forms.
|
|
6
7
|
* Use `v-model` for two-way binding of the form data; the `submit` event
|
|
7
8
|
* carries only the data for currently-visible fields. Supply `enhancements`
|
|
8
9
|
* for dynamic options, custom validators, a submit handler, and field-change
|
|
9
10
|
* callbacks that cannot be expressed in JSON.
|
|
11
|
+
* Compact control schemas can be bound directly:
|
|
12
|
+
* `<FormBuilder :controls="controls" v-model="values" />`.
|
|
13
|
+
* Complete control models can also be bound directly:
|
|
14
|
+
* `<FormBuilder :model="workspaceModel" v-model="values" />`.
|
|
10
15
|
*
|
|
11
|
-
* Exposes `form`, `validate`, `reset`, `
|
|
12
|
-
* `builder` for imperative control via template refs.
|
|
16
|
+
* Exposes `form`, `validate`, `reset`, `updateSchema`, `goNext`, `goBack`,
|
|
17
|
+
* `goToStep`, and `builder` for imperative control via template refs.
|
|
13
18
|
*
|
|
14
19
|
* Slots:
|
|
15
20
|
* - `field:<name>` — override a single field's input component
|
|
16
21
|
* - `section:<id>` — replace an entire section body
|
|
17
22
|
* - `section:<id>:after` — inject content after a section
|
|
18
|
-
* - `actions` — replace the default FormActions bar
|
|
23
|
+
* - `actions` — replace the default FormActions bar when `showActions` is true
|
|
19
24
|
*/
|
|
20
25
|
import { ref, computed, watch } from 'vue'
|
|
21
26
|
import type { FormSchema, FormEnhancements, UseFormBuilderReturn } from '../types/form-builder'
|
|
22
27
|
import type { WizardStep } from '../types'
|
|
28
|
+
import {
|
|
29
|
+
controlsToFormSchema,
|
|
30
|
+
defineControlModel,
|
|
31
|
+
getControlDefaults,
|
|
32
|
+
mergeControlWorkspaceOptions,
|
|
33
|
+
type ControlModel,
|
|
34
|
+
type ControlModelBinding,
|
|
35
|
+
type ControlSchema,
|
|
36
|
+
type ControlWorkspaceOptions,
|
|
37
|
+
} from '../composables/useControlSchema'
|
|
23
38
|
import { useFormBuilder } from '../composables/useFormBuilder'
|
|
39
|
+
import {
|
|
40
|
+
formSchemaFieldNames,
|
|
41
|
+
pickExistingRecordKeys,
|
|
42
|
+
recordValuesEqualForKeys,
|
|
43
|
+
} from '../utils/formModelSync'
|
|
24
44
|
import StepWizard from './StepWizard.vue'
|
|
25
|
-
import
|
|
45
|
+
import FormSectionRenderer from './internal/FormSectionRenderer.vue'
|
|
26
46
|
import FormActions from './FormActions.vue'
|
|
27
47
|
|
|
28
48
|
interface Props {
|
|
29
|
-
schema
|
|
49
|
+
/** Full form or wizard schema. Takes precedence when `controls` is also provided. */
|
|
50
|
+
schema?: FormSchema
|
|
51
|
+
/** Model returned by defineControlModel(), or a raw nested ControlModel for one-step form generation. */
|
|
52
|
+
model?: ControlModel | ControlModelBinding
|
|
53
|
+
/** Compact control schema used to generate a flat FormSchema. */
|
|
54
|
+
controls?: ControlSchema
|
|
55
|
+
/** Options passed to compact control schema generation, including shared initialValues. */
|
|
56
|
+
controlOptions?: ControlWorkspaceOptions
|
|
30
57
|
modelValue?: Record<string, unknown>
|
|
31
58
|
enhancements?: FormEnhancements<Record<string, unknown>>
|
|
32
59
|
loading?: boolean
|
|
33
60
|
disabled?: boolean
|
|
34
61
|
size?: 'sm' | 'md' | 'lg'
|
|
35
62
|
readonly?: boolean
|
|
63
|
+
/** Show the default or slotted form actions. */
|
|
64
|
+
showActions?: boolean
|
|
36
65
|
}
|
|
37
66
|
|
|
38
67
|
const props = withDefaults(defineProps<Props>(), {
|
|
68
|
+
model: undefined,
|
|
69
|
+
controlOptions: () => ({}),
|
|
39
70
|
loading: false,
|
|
40
71
|
disabled: false,
|
|
41
72
|
readonly: false,
|
|
73
|
+
showActions: true,
|
|
42
74
|
})
|
|
43
75
|
|
|
44
76
|
const emit = defineEmits<{
|
|
@@ -47,12 +79,68 @@ const emit = defineEmits<{
|
|
|
47
79
|
cancel: []
|
|
48
80
|
}>()
|
|
49
81
|
|
|
82
|
+
const resolvedModel = computed<ControlModelBinding | undefined>(() => {
|
|
83
|
+
if (props.model === undefined) return undefined
|
|
84
|
+
return isControlModelBinding(props.model) ? props.model : defineControlModel(props.model)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
const resolvedControls = computed<ControlSchema | undefined>(() =>
|
|
88
|
+
props.controls ?? resolvedModel.value?.controls,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
const resolvedControlOptions = computed<ControlWorkspaceOptions>(() =>
|
|
92
|
+
mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, props.controlOptions)
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
const resolvedSchema = computed<FormSchema>(() => {
|
|
96
|
+
if (props.schema) return props.schema
|
|
97
|
+
if (resolvedControls.value) return controlsToFormSchema(resolvedControls.value, resolvedControlOptions.value)
|
|
98
|
+
return { sections: [] }
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
const resolvedModelValue = computed<Record<string, unknown>>(() => ({
|
|
102
|
+
...(resolvedControls.value ? getControlDefaults(resolvedControls.value) : {}),
|
|
103
|
+
...(resolvedControlOptions.value.initialValues ?? {}),
|
|
104
|
+
...(props.modelValue ?? {}),
|
|
105
|
+
}))
|
|
106
|
+
|
|
50
107
|
const builder = useFormBuilder(
|
|
51
|
-
|
|
52
|
-
|
|
108
|
+
resolvedSchema.value,
|
|
109
|
+
resolvedModelValue.value,
|
|
53
110
|
props.enhancements,
|
|
54
111
|
)
|
|
55
112
|
|
|
113
|
+
// Sync schema/control changes into the internal builder so generated forms stay coherent.
|
|
114
|
+
watch(
|
|
115
|
+
resolvedSchema,
|
|
116
|
+
(schema) => {
|
|
117
|
+
const fieldNames = formSchemaFieldNames(schema)
|
|
118
|
+
const schemaValues = pickExistingRecordKeys(resolvedModelValue.value, fieldNames)
|
|
119
|
+
const existingValues = pickExistingRecordKeys(
|
|
120
|
+
builder.form.data as Record<string, unknown>,
|
|
121
|
+
fieldNames,
|
|
122
|
+
)
|
|
123
|
+
const nextValues = props.modelValue === undefined
|
|
124
|
+
? { ...schemaValues, ...existingValues }
|
|
125
|
+
: schemaValues
|
|
126
|
+
|
|
127
|
+
builder.updateSchema(schema, nextValues)
|
|
128
|
+
},
|
|
129
|
+
{ deep: true },
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
// Sync external modelValue changes into the internal form without resetting on no-op echo updates.
|
|
133
|
+
watch(
|
|
134
|
+
() => props.modelValue,
|
|
135
|
+
() => {
|
|
136
|
+
const data = resolvedModelValue.value
|
|
137
|
+
const fieldNames = builderFieldNames()
|
|
138
|
+
if (recordValuesEqualForKeys(data, builder.form.data as Record<string, unknown>, fieldNames)) return
|
|
139
|
+
builder.reset(pickExistingRecordKeys(data, fieldNames))
|
|
140
|
+
},
|
|
141
|
+
{ deep: true },
|
|
142
|
+
)
|
|
143
|
+
|
|
56
144
|
// Sync modelValue changes back to parent
|
|
57
145
|
watch(
|
|
58
146
|
() => ({ ...builder.form.data }),
|
|
@@ -61,12 +149,12 @@ watch(
|
|
|
61
149
|
)
|
|
62
150
|
|
|
63
151
|
// Wizard support
|
|
64
|
-
const isWizard = computed(() => !!
|
|
152
|
+
const isWizard = computed(() => !!resolvedSchema.value.steps)
|
|
65
153
|
const wizardRef = ref<InstanceType<typeof StepWizard> | null>(null)
|
|
66
154
|
|
|
67
155
|
const wizardSteps = computed<WizardStep[]>(() => {
|
|
68
|
-
if (!
|
|
69
|
-
return
|
|
156
|
+
if (!resolvedSchema.value.steps) return []
|
|
157
|
+
return resolvedSchema.value.steps.map((step) => ({
|
|
70
158
|
id: step.id,
|
|
71
159
|
label: step.label,
|
|
72
160
|
description: step.description,
|
|
@@ -105,10 +193,19 @@ function handleCancel() {
|
|
|
105
193
|
emit('cancel')
|
|
106
194
|
}
|
|
107
195
|
|
|
196
|
+
function builderFieldNames(): string[] {
|
|
197
|
+
return builder.fields.map(field => field.name)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function isControlModelBinding(model: ControlModel | ControlModelBinding): model is ControlModelBinding {
|
|
201
|
+
return 'controls' in model && 'controlOptions' in model
|
|
202
|
+
}
|
|
203
|
+
|
|
108
204
|
defineExpose({
|
|
109
205
|
form: builder.form,
|
|
110
206
|
validate: builder.validate,
|
|
111
207
|
reset: builder.reset,
|
|
208
|
+
updateSchema: builder.updateSchema,
|
|
112
209
|
goNext: builder.goNext,
|
|
113
210
|
goBack: builder.goBack,
|
|
114
211
|
goToStep: builder.goToStep,
|
|
@@ -119,17 +216,17 @@ defineExpose({
|
|
|
119
216
|
<template>
|
|
120
217
|
<div :class="['mint-form-builder', size ? `mint-form-builder--${size}` : '']">
|
|
121
218
|
<!-- Wizard mode -->
|
|
122
|
-
<template v-if="isWizard &&
|
|
219
|
+
<template v-if="isWizard && resolvedSchema.steps">
|
|
123
220
|
<StepWizard
|
|
124
221
|
ref="wizardRef"
|
|
125
222
|
:steps="wizardSteps"
|
|
126
223
|
:model-value="builder.currentStep.value"
|
|
127
224
|
@update:model-value="builder.goToStep($event)"
|
|
128
225
|
>
|
|
129
|
-
<template v-for="step in
|
|
226
|
+
<template v-for="step in resolvedSchema.steps" :key="step.id" #[`step-${step.id}`]>
|
|
130
227
|
<div class="mint-form-builder__step">
|
|
131
228
|
<template v-for="section in step.sections" :key="section.id">
|
|
132
|
-
<
|
|
229
|
+
<FormSectionRenderer
|
|
133
230
|
v-if="builder.isSectionVisible(section.id)"
|
|
134
231
|
:section="section"
|
|
135
232
|
:builder="(builder as UseFormBuilderReturn<Record<string, unknown>>)"
|
|
@@ -145,12 +242,12 @@ defineExpose({
|
|
|
145
242
|
<template #[`section:${section.id}:after`]="slotProps">
|
|
146
243
|
<slot :name="`section:${section.id}:after`" v-bind="slotProps" />
|
|
147
244
|
</template>
|
|
148
|
-
</
|
|
245
|
+
</FormSectionRenderer>
|
|
149
246
|
</template>
|
|
150
247
|
</div>
|
|
151
248
|
</template>
|
|
152
249
|
|
|
153
|
-
<template #navigation="{ isFirst, isLast }">
|
|
250
|
+
<template v-if="showActions" #navigation="{ isFirst, isLast }">
|
|
154
251
|
<slot name="actions" :form="builder.form" :builder="builder">
|
|
155
252
|
<FormActions
|
|
156
253
|
is-wizard
|
|
@@ -159,9 +256,9 @@ defineExpose({
|
|
|
159
256
|
:can-proceed="builder.isCurrentStepValid.value"
|
|
160
257
|
:loading="loading || builder.form.isSubmitting.value"
|
|
161
258
|
:disabled="disabled"
|
|
162
|
-
:submit-label="
|
|
163
|
-
:cancel-label="
|
|
164
|
-
:show-cancel="
|
|
259
|
+
:submit-label="resolvedSchema.submitLabel ?? 'Submit'"
|
|
260
|
+
:cancel-label="resolvedSchema.cancelLabel ?? 'Cancel'"
|
|
261
|
+
:show-cancel="resolvedSchema.showCancel ?? false"
|
|
165
262
|
@next="handleNext"
|
|
166
263
|
@back="builder.goBack"
|
|
167
264
|
@submit="handleSubmit"
|
|
@@ -173,9 +270,9 @@ defineExpose({
|
|
|
173
270
|
</template>
|
|
174
271
|
|
|
175
272
|
<!-- Flat mode -->
|
|
176
|
-
<template v-else-if="
|
|
177
|
-
<template v-for="section in
|
|
178
|
-
<
|
|
273
|
+
<template v-else-if="resolvedSchema.sections">
|
|
274
|
+
<template v-for="section in resolvedSchema.sections" :key="section.id">
|
|
275
|
+
<FormSectionRenderer
|
|
179
276
|
v-if="builder.isSectionVisible(section.id)"
|
|
180
277
|
:section="section"
|
|
181
278
|
:builder="(builder as UseFormBuilderReturn<Record<string, unknown>>)"
|
|
@@ -191,16 +288,16 @@ defineExpose({
|
|
|
191
288
|
<template #[`section:${section.id}:after`]="slotProps">
|
|
192
289
|
<slot :name="`section:${section.id}:after`" v-bind="slotProps" />
|
|
193
290
|
</template>
|
|
194
|
-
</
|
|
291
|
+
</FormSectionRenderer>
|
|
195
292
|
</template>
|
|
196
293
|
|
|
197
|
-
<slot name="actions" :form="builder.form" :builder="builder">
|
|
294
|
+
<slot v-if="showActions" name="actions" :form="builder.form" :builder="builder">
|
|
198
295
|
<FormActions
|
|
199
296
|
:loading="loading || builder.form.isSubmitting.value"
|
|
200
297
|
:disabled="disabled"
|
|
201
|
-
:submit-label="
|
|
202
|
-
:cancel-label="
|
|
203
|
-
:show-cancel="
|
|
298
|
+
:submit-label="resolvedSchema.submitLabel ?? 'Submit'"
|
|
299
|
+
:cancel-label="resolvedSchema.cancelLabel ?? 'Cancel'"
|
|
300
|
+
:show-cancel="resolvedSchema.showCancel ?? false"
|
|
204
301
|
@submit="handleSubmit"
|
|
205
302
|
@cancel="handleCancel"
|
|
206
303
|
/>
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* @deprecated Use FormBuilder with schema/controls and field slots instead.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* validation errors only after the field has been touched, and handles the
|
|
7
|
-
* FileUploader's event-based upload pattern via `handleUpload`. Consumers can
|
|
8
|
-
* override rendering via the `field:<name>` slot.
|
|
5
|
+
* Compatibility wrapper around the internal FormBuilder field renderer.
|
|
9
6
|
*/
|
|
10
|
-
import { computed } from 'vue'
|
|
11
7
|
import type { FormFieldSchema } from '../types/form-builder'
|
|
12
8
|
import type { UseFormReturn } from '../composables/useForm'
|
|
13
|
-
import
|
|
14
|
-
import FormField from './FormField.vue'
|
|
9
|
+
import FormFieldRendererInternal from './internal/FormFieldRendererInternal.vue'
|
|
15
10
|
|
|
16
11
|
interface Props {
|
|
17
12
|
field: FormFieldSchema
|
|
@@ -21,38 +16,20 @@ interface Props {
|
|
|
21
16
|
|
|
22
17
|
const props = defineProps<Props>()
|
|
23
18
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return props.form.touched[name] ? props.form.errors[name] : null
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
function handleUpload(files: File[]) {
|
|
32
|
-
props.form.setFieldValue(props.field.name, files)
|
|
33
|
-
}
|
|
19
|
+
defineSlots<{
|
|
20
|
+
'`field:${field.name}`'?: (props: Record<string, unknown>) => unknown
|
|
21
|
+
[name: string]: ((props: Record<string, unknown>) => unknown) | undefined
|
|
22
|
+
}>()
|
|
34
23
|
</script>
|
|
35
24
|
|
|
36
25
|
<template>
|
|
37
|
-
<
|
|
38
|
-
:
|
|
39
|
-
:
|
|
40
|
-
:
|
|
41
|
-
:required="!!field.validation?.required"
|
|
42
|
-
:html-for="field.name"
|
|
26
|
+
<FormFieldRendererInternal
|
|
27
|
+
:field="props.field"
|
|
28
|
+
:resolved-props="props.resolvedProps"
|
|
29
|
+
:form="props.form"
|
|
43
30
|
>
|
|
44
|
-
<
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
v-bind="resolvedProps"
|
|
49
|
-
/>
|
|
50
|
-
<component
|
|
51
|
-
:is="entry.component"
|
|
52
|
-
v-else
|
|
53
|
-
v-bind="resolvedProps"
|
|
54
|
-
@upload="handleUpload"
|
|
55
|
-
/>
|
|
56
|
-
</slot>
|
|
57
|
-
</FormField>
|
|
31
|
+
<template #[`field:${props.field.name}`]="slotProps">
|
|
32
|
+
<slot :name="`field:${props.field.name}`" v-bind="slotProps" />
|
|
33
|
+
</template>
|
|
34
|
+
</FormFieldRendererInternal>
|
|
58
35
|
</template>
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* @deprecated Use FormBuilder with schema/controls and section slots instead.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* grid and per-field `colSpan`, and switches between a collapsible
|
|
7
|
-
* (`CollapsibleCard`) and a static layout based on `section.collapsible`.
|
|
8
|
-
* The entire section is hidden when all its fields are hidden. Consumers can
|
|
9
|
-
* replace the section body via `section:<id>` or inject content after it via
|
|
10
|
-
* `section:<id>:after`, and override individual fields via `field:<name>`.
|
|
5
|
+
* Compatibility wrapper around the internal FormBuilder section renderer.
|
|
11
6
|
*/
|
|
12
|
-
import { computed } from 'vue'
|
|
13
7
|
import type { FormSectionSchema, UseFormBuilderReturn } from '../types/form-builder'
|
|
14
|
-
import
|
|
15
|
-
import FormFieldRenderer from './FormFieldRenderer.vue'
|
|
8
|
+
import FormSectionRenderer from './internal/FormSectionRenderer.vue'
|
|
16
9
|
|
|
17
10
|
interface Props {
|
|
18
11
|
section: FormSectionSchema
|
|
@@ -21,70 +14,24 @@ interface Props {
|
|
|
21
14
|
|
|
22
15
|
const props = defineProps<Props>()
|
|
23
16
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}))
|
|
17
|
+
defineSlots<{
|
|
18
|
+
'`section:${section.id}`'?: (props: Record<string, unknown>) => unknown
|
|
19
|
+
'`field:${field.name}`'?: (props: Record<string, unknown>) => unknown
|
|
20
|
+
'`section:${section.id}:after`'?: (props: Record<string, unknown>) => unknown
|
|
21
|
+
[name: string]: ((props: Record<string, unknown>) => unknown) | undefined
|
|
22
|
+
}>()
|
|
31
23
|
</script>
|
|
32
24
|
|
|
33
25
|
<template>
|
|
34
|
-
<
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
v-for="field in visibleFields"
|
|
46
|
-
:key="field.name"
|
|
47
|
-
:style="field.colSpan ? { gridColumn: `span ${field.colSpan}` } : undefined"
|
|
48
|
-
>
|
|
49
|
-
<slot :name="`field:${field.name}`" :field="field" :form="builder.form" :field-props="builder.form.getFieldProps(field.name)">
|
|
50
|
-
<FormFieldRenderer
|
|
51
|
-
:field="field"
|
|
52
|
-
:resolved-props="builder.getResolvedFieldProps(field)"
|
|
53
|
-
:form="builder.form"
|
|
54
|
-
/>
|
|
55
|
-
</slot>
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
</CollapsibleCard>
|
|
59
|
-
|
|
60
|
-
<!-- Static variant -->
|
|
61
|
-
<div v-else class="mint-form-section--static">
|
|
62
|
-
<div v-if="section.title || section.description" class="mint-form-section__header">
|
|
63
|
-
<h3 v-if="section.title" class="mint-form-section__title">{{ section.title }}</h3>
|
|
64
|
-
<p v-if="section.description" class="mint-form-section__description">{{ section.description }}</p>
|
|
65
|
-
</div>
|
|
66
|
-
<div class="mint-form-section__grid" :style="gridStyle">
|
|
67
|
-
<div
|
|
68
|
-
v-for="field in visibleFields"
|
|
69
|
-
:key="field.name"
|
|
70
|
-
:style="field.colSpan ? { gridColumn: `span ${field.colSpan}` } : undefined"
|
|
71
|
-
>
|
|
72
|
-
<slot :name="`field:${field.name}`" :field="field" :form="builder.form" :field-props="builder.form.getFieldProps(field.name)">
|
|
73
|
-
<FormFieldRenderer
|
|
74
|
-
:field="field"
|
|
75
|
-
:resolved-props="builder.getResolvedFieldProps(field)"
|
|
76
|
-
:form="builder.form"
|
|
77
|
-
/>
|
|
78
|
-
</slot>
|
|
79
|
-
</div>
|
|
80
|
-
</div>
|
|
81
|
-
</div>
|
|
82
|
-
</slot>
|
|
83
|
-
|
|
84
|
-
<slot :name="`section:${section.id}:after`" :form="builder.form" />
|
|
85
|
-
</div>
|
|
26
|
+
<FormSectionRenderer :section="props.section" :builder="props.builder">
|
|
27
|
+
<template #[`section:${props.section.id}`]="slotProps">
|
|
28
|
+
<slot :name="`section:${props.section.id}`" v-bind="slotProps" />
|
|
29
|
+
</template>
|
|
30
|
+
<template v-for="field in props.section.fields" :key="field.name" #[`field:${field.name}`]="slotProps">
|
|
31
|
+
<slot :name="`field:${field.name}`" v-bind="slotProps" />
|
|
32
|
+
</template>
|
|
33
|
+
<template #[`section:${props.section.id}:after`]="slotProps">
|
|
34
|
+
<slot :name="`section:${props.section.id}:after`" v-bind="slotProps" />
|
|
35
|
+
</template>
|
|
36
|
+
</FormSectionRenderer>
|
|
86
37
|
</template>
|
|
87
|
-
|
|
88
|
-
<style>
|
|
89
|
-
@import '../styles/components/form-builder.css';
|
|
90
|
-
</style>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/** Drag-and-drop two-zone assigner for splitting sample groups into control and treatment arms. */
|
|
3
|
-
import {
|
|
3
|
+
import { ref } from 'vue'
|
|
4
4
|
import type { GroupItem } from '../types'
|
|
5
|
+
import { useGroupAssignment, type GroupAssignmentState, type GroupAssignmentZone } from '../composables/useGroupAssignment'
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
7
8
|
groups: GroupItem[]
|
|
@@ -30,42 +31,15 @@ const emit = defineEmits<{
|
|
|
30
31
|
const dragOverZone = ref<'zone1' | 'zone2' | null>(null)
|
|
31
32
|
const draggingGroup = ref<string | null>(null)
|
|
32
33
|
|
|
33
|
-
const
|
|
34
|
-
props.groups
|
|
35
|
-
|
|
36
|
-
)
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
props.groups.filter(g => props.group1.includes(g.name))
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
const zone2Groups = computed(() =>
|
|
44
|
-
props.groups.filter(g => props.group2.includes(g.name))
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
const zone1Count = computed(() =>
|
|
48
|
-
zone1Groups.value.reduce((sum, g) => sum + g.count, 0)
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
const zone2Count = computed(() =>
|
|
52
|
-
zone2Groups.value.reduce((sum, g) => sum + g.count, 0)
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
const isValid = computed(() =>
|
|
56
|
-
props.group1.length >= props.minPerGroup &&
|
|
57
|
-
props.group2.length >= props.minPerGroup
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
const validationMessage = computed(() => {
|
|
61
|
-
if (isValid.value) return null
|
|
62
|
-
const missing1 = Math.max(0, props.minPerGroup - props.group1.length)
|
|
63
|
-
const missing2 = Math.max(0, props.minPerGroup - props.group2.length)
|
|
64
|
-
const parts: string[] = []
|
|
65
|
-
if (missing1 > 0) parts.push(`${missing1} more to ${props.label1}`)
|
|
66
|
-
if (missing2 > 0) parts.push(`${missing2} more to ${props.label2}`)
|
|
67
|
-
return `Add ${parts.join(' and ')}`
|
|
34
|
+
const assignment = useGroupAssignment({
|
|
35
|
+
groups: () => props.groups,
|
|
36
|
+
group1: () => props.group1,
|
|
37
|
+
group2: () => props.group2,
|
|
38
|
+
label1: () => props.label1,
|
|
39
|
+
label2: () => props.label2,
|
|
40
|
+
minPerGroup: () => props.minPerGroup,
|
|
68
41
|
})
|
|
42
|
+
const { unassignedGroups, zone1Groups, zone2Groups, zone1Count, zone2Count, validationMessage } = assignment
|
|
69
43
|
|
|
70
44
|
function handleDragStart(event: DragEvent, groupName: string) {
|
|
71
45
|
draggingGroup.value = groupName
|
|
@@ -78,7 +52,7 @@ function handleDragEnd() {
|
|
|
78
52
|
dragOverZone.value = null
|
|
79
53
|
}
|
|
80
54
|
|
|
81
|
-
function handleDragOver(event: DragEvent, zone:
|
|
55
|
+
function handleDragOver(event: DragEvent, zone: GroupAssignmentZone) {
|
|
82
56
|
event.preventDefault()
|
|
83
57
|
event.dataTransfer!.dropEffect = 'move'
|
|
84
58
|
dragOverZone.value = zone
|
|
@@ -88,7 +62,7 @@ function handleDragLeave() {
|
|
|
88
62
|
dragOverZone.value = null
|
|
89
63
|
}
|
|
90
64
|
|
|
91
|
-
function handleDrop(event: DragEvent, zone:
|
|
65
|
+
function handleDrop(event: DragEvent, zone: GroupAssignmentZone) {
|
|
92
66
|
event.preventDefault()
|
|
93
67
|
dragOverZone.value = null
|
|
94
68
|
|
|
@@ -98,32 +72,26 @@ function handleDrop(event: DragEvent, zone: 'zone1' | 'zone2') {
|
|
|
98
72
|
assignToZone(groupName, zone)
|
|
99
73
|
}
|
|
100
74
|
|
|
101
|
-
function assignToZone(groupName: string, zone:
|
|
102
|
-
|
|
103
|
-
const newGroup1 = props.group1.filter(n => n !== groupName)
|
|
104
|
-
const newGroup2 = props.group2.filter(n => n !== groupName)
|
|
105
|
-
|
|
106
|
-
// Add to target zone
|
|
107
|
-
if (zone === 'zone1') {
|
|
108
|
-
emit('update:group1', [...newGroup1, groupName])
|
|
109
|
-
emit('update:group2', newGroup2)
|
|
110
|
-
} else {
|
|
111
|
-
emit('update:group1', newGroup1)
|
|
112
|
-
emit('update:group2', [...newGroup2, groupName])
|
|
113
|
-
}
|
|
75
|
+
function assignToZone(groupName: string, zone: GroupAssignmentZone) {
|
|
76
|
+
emitAssignment(assignment.assignToZone(groupName, zone))
|
|
114
77
|
}
|
|
115
78
|
|
|
116
|
-
function removeFromZone(groupName: string, zone:
|
|
79
|
+
function removeFromZone(groupName: string, zone: GroupAssignmentZone) {
|
|
80
|
+
const state = assignment.removeFromZone(groupName, zone)
|
|
117
81
|
if (zone === 'zone1') {
|
|
118
|
-
emit('update:group1',
|
|
82
|
+
emit('update:group1', state.group1)
|
|
119
83
|
} else {
|
|
120
|
-
emit('update:group2',
|
|
84
|
+
emit('update:group2', state.group2)
|
|
121
85
|
}
|
|
122
86
|
}
|
|
123
87
|
|
|
124
88
|
function clearAll() {
|
|
125
|
-
|
|
126
|
-
|
|
89
|
+
emitAssignment(assignment.clearAll())
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function emitAssignment(state: GroupAssignmentState) {
|
|
93
|
+
emit('update:group1', state.group1)
|
|
94
|
+
emit('update:group2', state.group2)
|
|
127
95
|
}
|
|
128
96
|
</script>
|
|
129
97
|
|
|
@@ -12,8 +12,8 @@ const isOpen = ref(false)
|
|
|
12
12
|
</script>
|
|
13
13
|
|
|
14
14
|
<template>
|
|
15
|
-
<Story title="Lab/GroupingModal">
|
|
16
|
-
<Variant title="
|
|
15
|
+
<Story title="Lab/Deprecated/GroupingModal">
|
|
16
|
+
<Variant title="Compatibility Preview">
|
|
17
17
|
<div style="padding: 2rem;">
|
|
18
18
|
<button
|
|
19
19
|
type="button"
|
|
@@ -27,7 +27,7 @@ const isOpen = ref(false)
|
|
|
27
27
|
"
|
|
28
28
|
@click="isOpen = true"
|
|
29
29
|
>
|
|
30
|
-
Open Grouping Modal
|
|
30
|
+
Open Legacy Grouping Modal
|
|
31
31
|
</button>
|
|
32
32
|
<GroupingModal
|
|
33
33
|
:open="isOpen"
|