@morscherlab/mint-sdk 1.0.0-rc.1 → 1.0.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/__tests__/components/LcmsSequenceTable.test.d.ts +1 -0
- package/dist/__tests__/components/ProgressBar.test.d.ts +1 -0
- package/dist/__tests__/components/RackEditor.test.d.ts +1 -0
- package/dist/__tests__/components/SequenceProgressBar.test.d.ts +1 -0
- package/dist/__tests__/composables/useExperimentSamples.test.d.ts +1 -0
- package/dist/__tests__/utils/instrument.test.d.ts +1 -0
- package/dist/__tests__/utils/lcms.test.d.ts +1 -0
- package/dist/__tests__/utils/permissions.test.d.ts +1 -0
- package/dist/__tests__/utils/rack.test.d.ts +1 -0
- package/dist/{auth-CBG3bWEc.js → auth-B7g4J4ZF.js} +99 -5
- package/dist/auth-B7g4J4ZF.js.map +1 -0
- package/dist/components/AppSidebar.vue.d.ts +3 -3
- package/dist/components/AutoGroupModal.vue.d.ts +1 -1
- package/dist/components/BaseCheckbox.vue.d.ts +1 -1
- package/dist/components/BaseToggle.vue.d.ts +2 -2
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +1 -1
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +1 -1
- package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +1 -1
- package/dist/components/ControlWorkspaceView.vue.d.ts +3 -3
- package/dist/components/DoseDesignWorkspaceView.vue.d.ts +2 -2
- package/dist/components/FormulaInput.vue.d.ts +1 -1
- package/dist/components/InstrumentAlertLog.vue.d.ts +22 -0
- package/dist/components/InstrumentStateBadge.vue.d.ts +11 -0
- package/dist/components/InstrumentStatusCard.vue.d.ts +13 -0
- package/dist/components/LcmsSequenceTable.vue.d.ts +26 -0
- package/dist/components/PluginWorkspaceView.vue.d.ts +3 -3
- package/dist/components/ProgressBar.vue.d.ts +1 -0
- package/dist/components/RackEditor.vue.d.ts +41 -3
- package/dist/components/ReagentList.vue.d.ts +1 -1
- package/dist/components/SampleSelector.vue.d.ts +5 -2
- package/dist/components/SegmentedControl.vue.d.ts +2 -0
- package/dist/components/SequenceInput.vue.d.ts +1 -1
- package/dist/components/SequenceProgressBar.vue.d.ts +15 -0
- package/dist/components/SettingsModal.vue.d.ts +3 -1
- package/dist/components/TagsInput.vue.d.ts +1 -1
- package/dist/components/WellPlate.vue.d.ts +42 -3
- package/dist/components/index.d.ts +5 -0
- package/dist/components/index.js +3 -3
- package/dist/{components-5KSfsVqf.js → components-DafPc4rM.js} +2091 -1051
- package/dist/components-DafPc4rM.js.map +1 -0
- package/dist/composables/controlComponentBindings.d.ts +7 -0
- package/dist/composables/controlSchemaAdapters.d.ts +20 -0
- package/dist/composables/controlSchemaFormFields.d.ts +3 -0
- package/dist/composables/controlSchemaLayout.d.ts +7 -0
- package/dist/composables/controlSchemaNormalize.d.ts +15 -0
- package/dist/composables/controlSchemaUtils.d.ts +9 -0
- package/dist/composables/controlWorkspaceOptions.d.ts +2 -0
- package/dist/composables/experimentDesignData.d.ts +17 -0
- package/dist/composables/index.d.ts +2 -0
- package/dist/composables/index.js +4 -4
- package/dist/composables/useControlSchema.d.ts +15 -30
- package/dist/composables/useControlWorkspace.d.ts +5 -0
- package/dist/composables/useExperimentData.d.ts +11 -3
- package/dist/composables/useExperimentSamples.d.ts +42 -0
- package/dist/composables/usePlatformContext.d.ts +54 -0
- package/dist/{composables-D4Myb30a.js → composables-BMkPQhVK.js} +5 -3
- package/dist/composables-BMkPQhVK.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +168 -6
- package/dist/index.js.map +1 -0
- package/dist/install.js +2 -2
- package/dist/instrument.d.ts +7 -0
- package/dist/lcms.d.ts +27 -0
- package/dist/permissions.d.ts +46 -0
- package/dist/stores/auth.d.ts +74 -2
- package/dist/stores/index.js +1 -1
- package/dist/styles.css +3316 -1216
- package/dist/templates/adapters.d.ts +14 -47
- package/dist/templates/assayLookups.d.ts +3 -0
- package/dist/templates/assayMatrixAdapters.d.ts +6 -0
- package/dist/templates/assayMatrixBuilder.d.ts +2 -0
- package/dist/templates/assayNormalizers.d.ts +4 -0
- package/dist/templates/builderDefaults.d.ts +1 -0
- package/dist/templates/builderIdUtils.d.ts +4 -0
- package/dist/templates/builderPresetControls.d.ts +10 -0
- package/dist/templates/builderReadUtils.d.ts +8 -0
- package/dist/templates/builders.d.ts +26 -63
- package/dist/templates/calibrationCurveAdapters.d.ts +4 -0
- package/dist/templates/calibrationCurveBuilder.d.ts +2 -0
- package/dist/templates/calibrationNormalizers.d.ts +5 -0
- package/dist/templates/componentBindingCatalog.d.ts +25 -0
- package/dist/templates/componentBindingHelpers.d.ts +17 -0
- package/dist/templates/componentDoseResponseProps.d.ts +3 -0
- package/dist/templates/componentGenericProps.d.ts +8 -0
- package/dist/templates/componentPlateHelpers.d.ts +5 -0
- package/dist/templates/componentPlateMapProps.d.ts +3 -0
- package/dist/templates/componentPropsFactory.d.ts +3 -0
- package/dist/templates/componentQpcrPlateProps.d.ts +3 -0
- package/dist/templates/componentTargetResolvers.d.ts +5 -0
- package/dist/templates/componentTemplateProps.d.ts +3 -0
- package/dist/templates/controlSchemaClone.d.ts +4 -0
- package/dist/templates/controlSchemaConstants.d.ts +10 -0
- package/dist/templates/controlSchemaMerge.d.ts +3 -0
- package/dist/templates/controlSchemaTargets.d.ts +17 -0
- package/dist/templates/controlSchemaTypes.d.ts +4 -0
- package/dist/templates/controlSchemas.d.ts +4 -4
- package/dist/templates/defaultBioTemplateBuilder.d.ts +2 -0
- package/dist/templates/doseResponseAdapters.d.ts +4 -0
- package/dist/templates/doseResponseBuilder.d.ts +2 -0
- package/dist/templates/elisaAssayCollectionBuilder.d.ts +2 -0
- package/dist/templates/flowCytometryAssayCollectionBuilder.d.ts +2 -0
- package/dist/templates/flowCytometryPanelBuilder.d.ts +2 -0
- package/dist/templates/flowNormalizers.d.ts +8 -0
- package/dist/templates/flowPanelAdapters.d.ts +4 -0
- package/dist/templates/index.d.ts +2 -2
- package/dist/templates/index.js +2 -2
- package/dist/templates/instrumentRunAdapterHelpers.d.ts +8 -0
- package/dist/templates/instrumentRunAdapters.d.ts +8 -0
- package/dist/templates/instrumentRunBuilder.d.ts +2 -0
- package/dist/templates/lcmsBatchCollectionBuilder.d.ts +2 -0
- package/dist/templates/plateGeometry.d.ts +4 -0
- package/dist/templates/plateMapAdapters.d.ts +3 -0
- package/dist/templates/plateMapBuilder.d.ts +2 -0
- package/dist/templates/presetControlSchemas.d.ts +534 -0
- package/dist/templates/presets.d.ts +12 -0
- package/dist/templates/protocolAdapters.d.ts +5 -0
- package/dist/templates/protocolNormalizers.d.ts +6 -0
- package/dist/templates/protocolStepsBuilder.d.ts +2 -0
- package/dist/templates/qpcrAdapters.d.ts +5 -0
- package/dist/templates/qpcrExpressionCollectionBuilder.d.ts +2 -0
- package/dist/templates/qpcrPlateBuilder.d.ts +2 -0
- package/dist/templates/reagentAdapters.d.ts +5 -0
- package/dist/templates/reagentListBuilder.d.ts +2 -0
- package/dist/templates/runNormalizers.d.ts +10 -0
- package/dist/templates/sampleNormalizers.d.ts +4 -0
- package/dist/templates/samplePrepAdapters.d.ts +4 -0
- package/dist/templates/samplePrepBuilder.d.ts +2 -0
- package/dist/templates/sampleSheetAdapters.d.ts +5 -0
- package/dist/templates/sampleSheetBuilder.d.ts +2 -0
- package/dist/templates/targetedMetabolomicsCollectionBuilder.d.ts +2 -0
- package/dist/templates/targetedMetabolomicsHelpers.d.ts +5 -0
- package/dist/templates/templateControlSchemas.d.ts +400 -0
- package/dist/templates/templateEnvelopes.d.ts +9 -0
- package/dist/templates/templatePackCollectionBuilder.d.ts +2 -0
- package/dist/templates/templatePresetCollectionBuilder.d.ts +18 -0
- package/dist/templates/templateValidators.d.ts +13 -0
- package/dist/templates/timeCourseAdapters.d.ts +5 -0
- package/dist/templates/timeCourseBuilder.d.ts +2 -0
- package/dist/templates/types.d.ts +16 -1
- package/dist/templates/wellPlateScreenCollectionBuilder.d.ts +2 -0
- package/dist/templates/westernBlotAssayCollectionBuilder.d.ts +2 -0
- package/dist/{templates-BSlxwV2c.js → templates-bUAWMn5L.js} +3610 -3154
- package/dist/templates-bUAWMn5L.js.map +1 -0
- package/dist/types/auth.d.ts +2 -0
- package/dist/types/components.d.ts +32 -3
- package/dist/types/form-builder.d.ts +2 -1
- package/dist/types/index.d.ts +4 -1
- package/dist/types/instrument.d.ts +56 -0
- package/dist/types/platform.d.ts +3 -0
- package/dist/{useExperimentData-BbbdI5xT.js → useProtocolTemplates-QZtHFFH2.js} +534 -359
- package/dist/useProtocolTemplates-QZtHFFH2.js.map +1 -0
- package/dist/utils/rack.d.ts +47 -0
- package/package.json +1 -1
- package/src/__tests__/components/AppTopBar.test.ts +15 -0
- package/src/__tests__/components/BaseTabs.test.ts +15 -0
- package/src/__tests__/components/LcmsSequenceTable.test.ts +57 -0
- package/src/__tests__/components/ProgressBar.test.ts +18 -0
- package/src/__tests__/components/RackEditor.test.ts +125 -0
- package/src/__tests__/components/SampleSelector.test.ts +25 -0
- package/src/__tests__/components/SegmentedControl.test.ts +45 -0
- package/src/__tests__/components/SequenceProgressBar.test.ts +39 -0
- package/src/__tests__/components/SettingsModal.test.ts +83 -2
- package/src/__tests__/composables/useControlSchema.test.ts +4 -0
- package/src/__tests__/composables/useExperimentData.test.ts +23 -0
- package/src/__tests__/composables/useExperimentSamples.test.ts +91 -0
- package/src/__tests__/templates/templates.test.ts +86 -0
- package/src/__tests__/utils/instrument.test.ts +47 -0
- package/src/__tests__/utils/lcms.test.ts +73 -0
- package/src/__tests__/utils/permissions.test.ts +50 -0
- package/src/__tests__/utils/rack.test.ts +120 -0
- package/src/components/AppTopBar.vue +1 -0
- package/src/components/BaseTabs.vue +22 -1
- package/src/components/InstrumentAlertLog.vue +191 -0
- package/src/components/InstrumentStateBadge.vue +50 -0
- package/src/components/InstrumentStatusCard.vue +188 -0
- package/src/components/LcmsSequenceTable.vue +191 -0
- package/src/components/ProgressBar.vue +3 -0
- package/src/components/RackEditor.vue +73 -2
- package/src/components/SampleSelector.vue +28 -9
- package/src/components/SegmentedControl.story.vue +17 -0
- package/src/components/SegmentedControl.vue +14 -3
- package/src/components/SequenceProgressBar.vue +71 -0
- package/src/components/SettingsModal.vue +42 -2
- package/src/components/WellPlate.vue +142 -21
- package/src/components/index.ts +5 -0
- package/src/components/internal/WellEditPopupInternal.vue +1 -0
- package/src/composables/controlComponentBindings.ts +80 -0
- package/src/composables/controlSchemaAdapters.ts +196 -0
- package/src/composables/controlSchemaFormFields.ts +61 -0
- package/src/composables/controlSchemaLayout.ts +59 -0
- package/src/composables/controlSchemaNormalize.ts +101 -0
- package/src/composables/controlSchemaUtils.ts +36 -0
- package/src/composables/controlWorkspaceOptions.ts +21 -0
- package/src/composables/experimentDesignData.ts +182 -0
- package/src/composables/index.ts +14 -0
- package/src/composables/useAuth.ts +4 -0
- package/src/composables/useAutoGroup.ts +5 -1
- package/src/composables/useControlSchema.ts +62 -618
- package/src/composables/useControlWorkspace.ts +207 -0
- package/src/composables/useExperimentData.ts +57 -16
- package/src/composables/useExperimentSamples.ts +142 -0
- package/src/index.ts +27 -0
- package/src/instrument.ts +90 -0
- package/src/lcms.ts +108 -0
- package/src/permissions.ts +143 -0
- package/src/stores/auth.ts +31 -3
- package/src/styles/components/instrument-monitor.css +478 -0
- package/src/styles/components/lcms-sequence-table.css +189 -0
- package/src/styles/components/sequence-progress-bar.css +63 -0
- package/src/styles/components/tabs.css +9 -0
- package/src/styles/components/well-edit-popup.css +7 -1
- package/src/styles/components/well-plate.css +5 -0
- package/src/styles/index.css +3 -0
- package/src/templates/adapters.ts +89 -930
- package/src/templates/assayLookups.ts +33 -0
- package/src/templates/assayMatrixAdapters.ts +78 -0
- package/src/templates/assayMatrixBuilder.ts +59 -0
- package/src/templates/assayNormalizers.ts +34 -0
- package/src/templates/builderDefaults.ts +11 -0
- package/src/templates/builderIdUtils.ts +20 -0
- package/src/templates/builderPresetControls.ts +165 -0
- package/src/templates/builderReadUtils.ts +57 -0
- package/src/templates/builders.ts +122 -2149
- package/src/templates/calibrationCurveAdapters.ts +59 -0
- package/src/templates/calibrationCurveBuilder.ts +99 -0
- package/src/templates/calibrationNormalizers.ts +60 -0
- package/src/templates/componentBindingCatalog.ts +90 -0
- package/src/templates/componentBindingHelpers.ts +93 -0
- package/src/templates/componentBindings.ts +12 -461
- package/src/templates/componentDoseResponseProps.ts +42 -0
- package/src/templates/componentGenericProps.ts +77 -0
- package/src/templates/componentPlateHelpers.ts +29 -0
- package/src/templates/componentPlateMapProps.ts +32 -0
- package/src/templates/componentPropsFactory.ts +21 -0
- package/src/templates/componentQpcrPlateProps.ts +28 -0
- package/src/templates/componentTargetResolvers.ts +69 -0
- package/src/templates/componentTemplateProps.ts +78 -0
- package/src/templates/controlSchemaClone.ts +32 -0
- package/src/templates/controlSchemaConstants.ts +11 -0
- package/src/templates/controlSchemaMerge.ts +40 -0
- package/src/templates/controlSchemaTargets.ts +87 -0
- package/src/templates/controlSchemaTypes.ts +20 -0
- package/src/templates/controlSchemas.ts +22 -636
- package/src/templates/defaultBioTemplateBuilder.ts +124 -0
- package/src/templates/doseResponseAdapters.ts +45 -0
- package/src/templates/doseResponseBuilder.ts +44 -0
- package/src/templates/elisaAssayCollectionBuilder.ts +62 -0
- package/src/templates/flowCytometryAssayCollectionBuilder.ts +41 -0
- package/src/templates/flowCytometryPanelBuilder.ts +53 -0
- package/src/templates/flowNormalizers.ts +58 -0
- package/src/templates/flowPanelAdapters.ts +58 -0
- package/src/templates/index.ts +2 -0
- package/src/templates/instrumentRunAdapterHelpers.ts +94 -0
- package/src/templates/instrumentRunAdapters.ts +163 -0
- package/src/templates/instrumentRunBuilder.ts +97 -0
- package/src/templates/lcmsBatchCollectionBuilder.ts +38 -0
- package/src/templates/plateGeometry.ts +62 -0
- package/src/templates/plateMapAdapters.ts +36 -0
- package/src/templates/plateMapBuilder.ts +43 -0
- package/src/templates/presetControlSchemas.ts +258 -0
- package/src/templates/presets.ts +23 -0
- package/src/templates/protocolAdapters.ts +69 -0
- package/src/templates/protocolNormalizers.ts +37 -0
- package/src/templates/protocolStepsBuilder.ts +36 -0
- package/src/templates/qpcrAdapters.ts +104 -0
- package/src/templates/qpcrExpressionCollectionBuilder.ts +33 -0
- package/src/templates/qpcrPlateBuilder.ts +96 -0
- package/src/templates/reagentAdapters.ts +77 -0
- package/src/templates/reagentListBuilder.ts +30 -0
- package/src/templates/runNormalizers.ts +63 -0
- package/src/templates/sampleNormalizers.ts +58 -0
- package/src/templates/samplePrepAdapters.ts +63 -0
- package/src/templates/samplePrepBuilder.ts +51 -0
- package/src/templates/sampleSheetAdapters.ts +75 -0
- package/src/templates/sampleSheetBuilder.ts +23 -0
- package/src/templates/targetedMetabolomicsCollectionBuilder.ts +79 -0
- package/src/templates/targetedMetabolomicsHelpers.ts +102 -0
- package/src/templates/templateControlSchemas.ts +320 -0
- package/src/templates/templateEnvelopes.ts +137 -0
- package/src/templates/templatePackCollectionBuilder.ts +23 -0
- package/src/templates/templatePresetCollectionBuilder.ts +139 -0
- package/src/templates/templateValidators.ts +414 -0
- package/src/templates/timeCourseAdapters.ts +73 -0
- package/src/templates/timeCourseBuilder.ts +64 -0
- package/src/templates/types.ts +17 -0
- package/src/templates/wellPlateScreenCollectionBuilder.ts +36 -0
- package/src/templates/westernBlotAssayCollectionBuilder.ts +68 -0
- package/src/types/auth.ts +3 -0
- package/src/types/components.ts +45 -3
- package/src/types/form-builder.ts +2 -1
- package/src/types/index.ts +35 -0
- package/src/types/instrument.ts +61 -0
- package/src/types/platform.ts +4 -0
- package/src/utils/rack.ts +209 -0
- package/dist/auth-CBG3bWEc.js.map +0 -1
- package/dist/components-5KSfsVqf.js.map +0 -1
- package/dist/composables-D4Myb30a.js.map +0 -1
- package/dist/templates-BSlxwV2c.js.map +0 -1
- package/dist/useExperimentData-BbbdI5xT.js.map +0 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type {
|
|
2
|
+
ComputedRef,
|
|
3
|
+
Ref,
|
|
4
|
+
} from 'vue'
|
|
2
5
|
import type {
|
|
3
6
|
PillNavItem,
|
|
4
7
|
SidebarToolSection,
|
|
@@ -6,6 +9,7 @@ import type {
|
|
|
6
9
|
SettingsModalSchema,
|
|
7
10
|
TopBarSettingsConfig,
|
|
8
11
|
} from '../types'
|
|
12
|
+
import type { AccessPolicy, AccessAudienceInput } from '../permissions'
|
|
9
13
|
import type {
|
|
10
14
|
FieldCondition,
|
|
11
15
|
FieldValidation,
|
|
@@ -14,9 +18,55 @@ import type {
|
|
|
14
18
|
FormSchema,
|
|
15
19
|
FormSectionSchema,
|
|
16
20
|
} from '../types/form-builder'
|
|
17
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
defaultValueForControl,
|
|
23
|
+
normalizeControls,
|
|
24
|
+
normalizeControlDefinition,
|
|
25
|
+
} from './controlSchemaNormalize'
|
|
26
|
+
import {
|
|
27
|
+
controlToFormField,
|
|
28
|
+
} from './controlSchemaFormFields'
|
|
29
|
+
import {
|
|
30
|
+
controlsToFormSchema,
|
|
31
|
+
controlsToSectionFormSchema,
|
|
32
|
+
controlsToSectionFormSchemas,
|
|
33
|
+
controlsToSettingsSchema,
|
|
34
|
+
controlsToSidebarPanels,
|
|
35
|
+
controlsToTopBarSettingsConfig,
|
|
36
|
+
controlsToViewItems,
|
|
37
|
+
} from './controlSchemaAdapters'
|
|
38
|
+
import {
|
|
39
|
+
omitUndefined,
|
|
40
|
+
recordValue,
|
|
41
|
+
} from './controlSchemaUtils'
|
|
18
42
|
import type { WellConcentration } from './useDoseCalculator'
|
|
19
43
|
|
|
44
|
+
export {
|
|
45
|
+
mergeControlWorkspaceOptions,
|
|
46
|
+
} from './controlWorkspaceOptions'
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
useControlWorkspace,
|
|
50
|
+
} from './useControlWorkspace'
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
controlValuesToComponentBindings,
|
|
54
|
+
controlValuesToComponentBindingsById,
|
|
55
|
+
controlValuesToComponentProps,
|
|
56
|
+
} from './controlComponentBindings'
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
controlsToFormSchema,
|
|
60
|
+
controlsToSectionFormSchema,
|
|
61
|
+
controlsToSectionFormSchemas,
|
|
62
|
+
controlsToSettingsSchema,
|
|
63
|
+
controlsToSidebarPanels,
|
|
64
|
+
controlsToTopBarSettingsConfig,
|
|
65
|
+
controlsToViewIds,
|
|
66
|
+
controlsToViewItems,
|
|
67
|
+
getDefaultControlView,
|
|
68
|
+
} from './controlSchemaAdapters'
|
|
69
|
+
|
|
20
70
|
export type ControlOptionValue = string | number | boolean
|
|
21
71
|
export type ControlOption = ControlOptionValue | SelectOption<unknown>
|
|
22
72
|
export type ControlPrimitive = string | number | boolean
|
|
@@ -34,6 +84,11 @@ export interface ControlSectionConfig {
|
|
|
34
84
|
iconBg?: string
|
|
35
85
|
columns?: 1 | 2 | 3
|
|
36
86
|
condition?: FieldCondition
|
|
87
|
+
access?: AccessPolicy
|
|
88
|
+
visibleFor?: AccessAudienceInput
|
|
89
|
+
requiresAdmin?: boolean
|
|
90
|
+
permissions?: readonly string[]
|
|
91
|
+
anyPermissions?: readonly string[]
|
|
37
92
|
defaultOpen?: boolean
|
|
38
93
|
showToggle?: boolean
|
|
39
94
|
}
|
|
@@ -70,6 +125,11 @@ export interface ControlDefinition {
|
|
|
70
125
|
pattern?: string | { value: string; message: string }
|
|
71
126
|
validation?: FieldValidation
|
|
72
127
|
condition?: FieldCondition
|
|
128
|
+
access?: AccessPolicy
|
|
129
|
+
visibleFor?: AccessAudienceInput
|
|
130
|
+
requiresAdmin?: boolean
|
|
131
|
+
permissions?: readonly string[]
|
|
132
|
+
anyPermissions?: readonly string[]
|
|
73
133
|
options?: readonly ControlOption[]
|
|
74
134
|
section?: string
|
|
75
135
|
sectionLabel?: string
|
|
@@ -350,15 +410,6 @@ type ControlValue<TControl> =
|
|
|
350
410
|
|
|
351
411
|
type OptionValue<TOption> = TOption extends SelectOption<infer TValue> ? TValue : TOption
|
|
352
412
|
|
|
353
|
-
interface NormalizedControl {
|
|
354
|
-
name: string
|
|
355
|
-
definition: ControlDefinition
|
|
356
|
-
type: FormFieldType
|
|
357
|
-
sectionId: string
|
|
358
|
-
viewId: string
|
|
359
|
-
order: number
|
|
360
|
-
}
|
|
361
|
-
|
|
362
413
|
/** Preserve literal control keys while marking an object as a MINT control schema. */
|
|
363
414
|
export function defineControls<TControls extends ControlSchema>(controls: TControls): TControls {
|
|
364
415
|
return controls
|
|
@@ -470,52 +521,6 @@ export function getControlDefaults<TControls extends ControlSchema>(
|
|
|
470
521
|
return values as ControlValues<TControls>
|
|
471
522
|
}
|
|
472
523
|
|
|
473
|
-
/** Map control workspace values into component props for direct `v-bind` usage. */
|
|
474
|
-
export function controlValuesToComponentProps<TValues extends Record<string, unknown>>(
|
|
475
|
-
values: TValues,
|
|
476
|
-
mapping?: ControlComponentPropsMap<TValues>,
|
|
477
|
-
): Record<string, unknown> {
|
|
478
|
-
if (mapping === undefined) return { ...values }
|
|
479
|
-
|
|
480
|
-
if (Array.isArray(mapping)) {
|
|
481
|
-
const props: Record<string, unknown> = {}
|
|
482
|
-
for (const key of mapping) {
|
|
483
|
-
props[key] = values[key]
|
|
484
|
-
}
|
|
485
|
-
return props
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
const props: Record<string, unknown> = {}
|
|
489
|
-
for (const [prop, source] of Object.entries(mapping) as Array<[string, ControlComponentPropSource<TValues>]>) {
|
|
490
|
-
props[prop] = typeof source === 'function' ? source(values) : values[source]
|
|
491
|
-
}
|
|
492
|
-
return props
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
/** Map control workspace values into named SDK component bindings for direct slot rendering. */
|
|
496
|
-
export function controlValuesToComponentBindings<TValues extends Record<string, unknown>>(
|
|
497
|
-
values: TValues,
|
|
498
|
-
bindings?: ControlComponentBindingsConfig<TValues>,
|
|
499
|
-
): ControlComponentBinding[] {
|
|
500
|
-
if (bindings === undefined) return []
|
|
501
|
-
|
|
502
|
-
return normalizeControlComponentBindingConfigs(bindings).map(binding => ({
|
|
503
|
-
id: binding.id,
|
|
504
|
-
component: binding.component,
|
|
505
|
-
props: controlValuesToComponentProps(values, binding.props),
|
|
506
|
-
}))
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
/** Map control workspace values into SDK component bindings keyed by binding id. */
|
|
510
|
-
export function controlValuesToComponentBindingsById<TValues extends Record<string, unknown>>(
|
|
511
|
-
values: TValues,
|
|
512
|
-
bindings?: ControlComponentBindingsConfig<TValues>,
|
|
513
|
-
): ControlComponentBindingsById {
|
|
514
|
-
return Object.fromEntries(
|
|
515
|
-
controlValuesToComponentBindings(values, bindings).map(binding => [binding.id, binding]),
|
|
516
|
-
)
|
|
517
|
-
}
|
|
518
|
-
|
|
519
524
|
/** Return a default WellPlate prop mapping for generated control workspaces. */
|
|
520
525
|
export function defineWellPlateControlProps<TValues extends Record<string, unknown> = Record<string, unknown>>(
|
|
521
526
|
options: WellPlateControlPropsOptions<TValues> = {},
|
|
@@ -649,196 +654,6 @@ export function defineDoseDesignControlModel(
|
|
|
649
654
|
})
|
|
650
655
|
}
|
|
651
656
|
|
|
652
|
-
function isControlModelBindingInput<TControls extends ControlSchema>(
|
|
653
|
-
value: TControls | (ControlModelBinding & { controls: TControls }),
|
|
654
|
-
): value is ControlModelBinding & { controls: TControls } {
|
|
655
|
-
return (
|
|
656
|
-
typeof value === 'object'
|
|
657
|
-
&& value !== null
|
|
658
|
-
&& 'controls' in value
|
|
659
|
-
&& 'controlOptions' in value
|
|
660
|
-
)
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
export function mergeControlWorkspaceOptions(
|
|
664
|
-
base?: ControlWorkspaceOptions,
|
|
665
|
-
override?: ControlWorkspaceOptions,
|
|
666
|
-
): ControlWorkspaceOptions {
|
|
667
|
-
return {
|
|
668
|
-
...(base ?? {}),
|
|
669
|
-
...(override ?? {}),
|
|
670
|
-
initialValues: {
|
|
671
|
-
...(base?.initialValues ?? {}),
|
|
672
|
-
...(override?.initialValues ?? {}),
|
|
673
|
-
},
|
|
674
|
-
topBarSettings: {
|
|
675
|
-
...(base?.topBarSettings ?? {}),
|
|
676
|
-
...(override?.topBarSettings ?? {}),
|
|
677
|
-
},
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
/** Convert a compact control schema into a FormBuilder schema. */
|
|
682
|
-
export function controlsToFormSchema(
|
|
683
|
-
controls: ControlSchema,
|
|
684
|
-
options: ControlSchemaOptions = {},
|
|
685
|
-
): ControlFormSchema {
|
|
686
|
-
const normalized = normalizeControls(controls, options)
|
|
687
|
-
const sectionIds = orderedUnique(normalized.map(control => control.sectionId))
|
|
688
|
-
const sections = sectionIds.map((sectionId): FormSectionSchema => {
|
|
689
|
-
const sectionControls = normalized.filter(control => control.sectionId === sectionId)
|
|
690
|
-
const config = sectionConfig(sectionId, sectionControls, options)
|
|
691
|
-
return {
|
|
692
|
-
id: sectionId,
|
|
693
|
-
title: config.title ?? config.label ?? humanize(sectionId),
|
|
694
|
-
description: config.description,
|
|
695
|
-
columns: config.columns ?? options.columns ?? 1,
|
|
696
|
-
defaultOpen: config.defaultOpen,
|
|
697
|
-
condition: config.condition,
|
|
698
|
-
fields: sectionControls.map(controlToFormField),
|
|
699
|
-
}
|
|
700
|
-
})
|
|
701
|
-
|
|
702
|
-
return {
|
|
703
|
-
sections,
|
|
704
|
-
submitLabel: options.submitLabel,
|
|
705
|
-
cancelLabel: options.cancelLabel,
|
|
706
|
-
showCancel: options.showCancel,
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
/** Convert controls into AppSidebar panels grouped by view and section. */
|
|
711
|
-
export function controlsToSidebarPanels(
|
|
712
|
-
controls: ControlSchema,
|
|
713
|
-
options: ControlSchemaOptions = {},
|
|
714
|
-
): Record<string, SidebarToolSection[]> {
|
|
715
|
-
const normalized = normalizeControls(controls, options)
|
|
716
|
-
.filter(control => isSidebarEnabled(control.definition.sidebar))
|
|
717
|
-
const viewIds = orderedUnique(normalized.map(control => control.viewId))
|
|
718
|
-
const panels: Record<string, SidebarToolSection[]> = {}
|
|
719
|
-
|
|
720
|
-
for (const viewId of viewIds) {
|
|
721
|
-
const viewControls = normalized.filter(control => control.viewId === viewId)
|
|
722
|
-
const sectionIds = orderedUnique(viewControls.map(control => control.sectionId))
|
|
723
|
-
panels[viewId] = sectionIds.map((sectionId): SidebarToolSection => {
|
|
724
|
-
const sectionControls = viewControls.filter(control => control.sectionId === sectionId)
|
|
725
|
-
const config = sectionConfig(sectionId, sectionControls, options)
|
|
726
|
-
const sidebarConfig = firstSidebarConfig(sectionControls)
|
|
727
|
-
return {
|
|
728
|
-
id: sectionId,
|
|
729
|
-
label: sidebarConfig?.label ?? config.label ?? config.title ?? humanize(sectionId),
|
|
730
|
-
subtitle: sidebarConfig?.subtitle ?? config.subtitle,
|
|
731
|
-
icon: sidebarConfig?.icon ?? config.icon,
|
|
732
|
-
iconColor: sidebarConfig?.iconColor ?? config.iconColor,
|
|
733
|
-
iconBg: sidebarConfig?.iconBg ?? config.iconBg,
|
|
734
|
-
defaultOpen: sidebarConfig?.defaultOpen ?? config.defaultOpen,
|
|
735
|
-
showToggle: sidebarConfig?.showToggle ?? config.showToggle,
|
|
736
|
-
}
|
|
737
|
-
})
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
return panels
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
/** Convert controls into a SettingsModal schema grouped by the same sections. */
|
|
744
|
-
export function controlsToSettingsSchema(
|
|
745
|
-
controls: ControlSchema,
|
|
746
|
-
options: ControlSchemaOptions = {},
|
|
747
|
-
): SettingsModalSchema {
|
|
748
|
-
const normalized = normalizeControls(controls, options)
|
|
749
|
-
const sectionIds = orderedUnique(normalized.map(control => control.sectionId))
|
|
750
|
-
|
|
751
|
-
return {
|
|
752
|
-
groups: sectionIds.map((sectionId) => {
|
|
753
|
-
const sectionControls = normalized.filter(control => control.sectionId === sectionId)
|
|
754
|
-
const config = sectionConfig(sectionId, sectionControls, options)
|
|
755
|
-
return {
|
|
756
|
-
id: sectionId,
|
|
757
|
-
label: config.label ?? config.title ?? humanize(sectionId),
|
|
758
|
-
description: config.description ?? config.subtitle,
|
|
759
|
-
icon: typeof config.icon === 'string' ? config.icon : undefined,
|
|
760
|
-
fields: sectionControls.map(controlToFormField),
|
|
761
|
-
columns: config.columns ?? options.columns ?? 1,
|
|
762
|
-
condition: config.condition,
|
|
763
|
-
}
|
|
764
|
-
}),
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
/** Convert controls into an AppTopBar settingsConfig object that passes compact controls through to SettingsModal. */
|
|
769
|
-
export function controlsToTopBarSettingsConfig(
|
|
770
|
-
controls: ControlSchema,
|
|
771
|
-
options: ControlSchemaOptions = {},
|
|
772
|
-
config: Omit<TopBarSettingsConfig, 'schema' | 'controls' | 'controlOptions'> = {},
|
|
773
|
-
): TopBarSettingsConfig {
|
|
774
|
-
return {
|
|
775
|
-
...config,
|
|
776
|
-
controls,
|
|
777
|
-
controlOptions: options,
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
/** Return generated control view IDs that have at least one sidebar panel. */
|
|
782
|
-
export function controlsToViewIds(
|
|
783
|
-
controls: ControlSchema,
|
|
784
|
-
options: ControlSchemaOptions = {},
|
|
785
|
-
): string[] {
|
|
786
|
-
return controlsToViewItems(controls, options).map(item => item.id)
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
/** Return AppTopBar pillNav-compatible view items for switching generated control sidebars. */
|
|
790
|
-
export function controlsToViewItems(
|
|
791
|
-
controls: ControlSchema,
|
|
792
|
-
options: ControlSchemaOptions = {},
|
|
793
|
-
): PillNavItem[] {
|
|
794
|
-
return Object.entries(controlsToSidebarPanels(controls, options))
|
|
795
|
-
.filter(([, sections]) => sections.length > 0)
|
|
796
|
-
.map(([id]) => controlViewItem(id, options))
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
/** Return the first generated sidebar view ID, or an empty string when controls render no sidebar panels. */
|
|
800
|
-
export function getDefaultControlView(
|
|
801
|
-
controls: ControlSchema,
|
|
802
|
-
options: ControlSchemaOptions = {},
|
|
803
|
-
): string {
|
|
804
|
-
return controlsToViewIds(controls, options)[0] ?? ''
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
/** Return a headerless single-section FormBuilder schema for rendering inside an AppSidebar section slot. */
|
|
808
|
-
export function controlsToSectionFormSchema(
|
|
809
|
-
controls: ControlSchema,
|
|
810
|
-
sectionId: string,
|
|
811
|
-
options: ControlSchemaOptions = {},
|
|
812
|
-
): ControlFormSchema {
|
|
813
|
-
const schema = controlsToFormSchema(controls, options)
|
|
814
|
-
return {
|
|
815
|
-
sections: schema.sections
|
|
816
|
-
.filter(section => section.id === sectionId)
|
|
817
|
-
.map(section => ({ ...section, title: '', description: undefined })),
|
|
818
|
-
submitLabel: schema.submitLabel,
|
|
819
|
-
cancelLabel: schema.cancelLabel,
|
|
820
|
-
showCancel: schema.showCancel,
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
/** Return headerless FormBuilder schemas keyed by section ID for AppSidebar auto-rendering. */
|
|
825
|
-
export function controlsToSectionFormSchemas(
|
|
826
|
-
controls: ControlSchema,
|
|
827
|
-
options: ControlSchemaOptions = {},
|
|
828
|
-
): Record<string, ControlFormSchema> {
|
|
829
|
-
const schema = controlsToFormSchema(controls, options)
|
|
830
|
-
const schemas: Record<string, ControlFormSchema> = {}
|
|
831
|
-
for (const section of schema.sections) {
|
|
832
|
-
schemas[section.id] = {
|
|
833
|
-
sections: [{ ...section, title: '', description: undefined }],
|
|
834
|
-
submitLabel: schema.submitLabel,
|
|
835
|
-
cancelLabel: schema.cancelLabel,
|
|
836
|
-
showCancel: schema.showCancel,
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
return schemas
|
|
840
|
-
}
|
|
841
|
-
|
|
842
657
|
/** Prepare FormBuilder, SettingsModal, AppTopBar settings, AppSidebar, and initial values from one compact control model. */
|
|
843
658
|
export function useControlSchema<TControls extends ControlSchema>(
|
|
844
659
|
controls: TControls,
|
|
@@ -886,195 +701,6 @@ export function useControlSchema<TControls extends ControlSchema>(
|
|
|
886
701
|
}
|
|
887
702
|
}
|
|
888
703
|
|
|
889
|
-
/** Prepare shared reactive values plus AppTopBar/AppSidebar/FormBuilder bindings from one simple controls data model. */
|
|
890
|
-
export function useControlWorkspace<TControls extends ControlSchema>(
|
|
891
|
-
controlsOrModel: TControls | (ControlModelBinding & { controls: TControls }),
|
|
892
|
-
options: ControlWorkspaceOptions = {},
|
|
893
|
-
): UseControlWorkspaceReturn<TControls> {
|
|
894
|
-
const model = isControlModelBindingInput<TControls>(controlsOrModel) ? controlsOrModel : undefined
|
|
895
|
-
const controls: TControls = model ? model.controls : controlsOrModel as TControls
|
|
896
|
-
const workspaceOptions = model
|
|
897
|
-
? mergeControlWorkspaceOptions(model.controlOptions, options)
|
|
898
|
-
: options
|
|
899
|
-
const { initialValues, topBarSettings, ...schemaOptions } = workspaceOptions
|
|
900
|
-
const schema = useControlSchema(controls, schemaOptions)
|
|
901
|
-
const activeView = ref(schema.defaultView)
|
|
902
|
-
const values = reactive({
|
|
903
|
-
...schema.initialValues,
|
|
904
|
-
...(initialValues ?? {}),
|
|
905
|
-
}) as ControlValues<TControls> & Record<string, unknown>
|
|
906
|
-
|
|
907
|
-
function setActiveView(viewId: string) {
|
|
908
|
-
syncActiveView(viewId)
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
function syncActiveView(viewId: string) {
|
|
912
|
-
if (!schema.viewIds.includes(viewId)) return
|
|
913
|
-
if (activeView.value !== viewId) activeView.value = viewId
|
|
914
|
-
if (sidebar.activeView !== viewId) sidebar.activeView = viewId
|
|
915
|
-
if (pillNav.currentItemId !== viewId) pillNav.currentItemId = viewId
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
function setValues(nextValues: Record<string, unknown>) {
|
|
919
|
-
Object.assign(values, nextValues)
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
function resetValues(nextValues: Record<string, unknown> = {}) {
|
|
923
|
-
replaceRecord(values, {
|
|
924
|
-
...schema.initialValues,
|
|
925
|
-
...nextValues,
|
|
926
|
-
})
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
function getComponentProps(
|
|
930
|
-
mapping?: ControlComponentPropsMap<ControlValues<TControls> & Record<string, unknown>>,
|
|
931
|
-
): Record<string, unknown> {
|
|
932
|
-
return controlValuesToComponentProps(values, mapping)
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
function getComponentPropsById(
|
|
936
|
-
mappings?: ControlComponentPropsByIdMap<ControlValues<TControls> & Record<string, unknown>>,
|
|
937
|
-
): Record<string, Record<string, unknown>> {
|
|
938
|
-
if (mappings === undefined) return {}
|
|
939
|
-
|
|
940
|
-
return Object.fromEntries(
|
|
941
|
-
Object.entries(mappings).map(([id, mapping]) => [
|
|
942
|
-
id,
|
|
943
|
-
controlValuesToComponentProps(values, mapping),
|
|
944
|
-
]),
|
|
945
|
-
)
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
function getComponentBindings(
|
|
949
|
-
bindings?: ControlComponentBindingsConfig<ControlValues<TControls> & Record<string, unknown>>,
|
|
950
|
-
): ControlComponentBinding[] {
|
|
951
|
-
return controlValuesToComponentBindings(values, bindings)
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
function getComponentBindingsById(
|
|
955
|
-
bindings?: ControlComponentBindingsConfig<ControlValues<TControls> & Record<string, unknown>>,
|
|
956
|
-
): ControlComponentBindingsById {
|
|
957
|
-
return controlValuesToComponentBindingsById(values, bindings)
|
|
958
|
-
}
|
|
959
|
-
const componentProps = computed(() => (
|
|
960
|
-
model?.componentProps === undefined ? {} : getComponentProps(model.componentProps)
|
|
961
|
-
))
|
|
962
|
-
const componentPropsById = computed(() => getComponentPropsById(model?.componentPropsById))
|
|
963
|
-
const componentBindings = computed(() => getComponentBindings(model?.componentBindings))
|
|
964
|
-
const componentBindingsById = computed(() => getComponentBindingsById(model?.componentBindings))
|
|
965
|
-
const form = {
|
|
966
|
-
...schema.form,
|
|
967
|
-
modelValue: values,
|
|
968
|
-
'onUpdate:modelValue': setValues,
|
|
969
|
-
} as ControlWorkspaceFormBinding
|
|
970
|
-
|
|
971
|
-
const topBarSettingsConfig: TopBarSettingsConfig = {
|
|
972
|
-
...schema.topBarSettingsConfig,
|
|
973
|
-
...(topBarSettings ?? {}),
|
|
974
|
-
values,
|
|
975
|
-
}
|
|
976
|
-
const sidebar = reactive({
|
|
977
|
-
...schema.sidebar,
|
|
978
|
-
activeView: activeView.value,
|
|
979
|
-
modelValue: values,
|
|
980
|
-
'onUpdate:modelValue': setValues,
|
|
981
|
-
values,
|
|
982
|
-
'onUpdate:values': setValues,
|
|
983
|
-
}) as ControlWorkspaceSidebarBinding
|
|
984
|
-
const pillNav = reactive({
|
|
985
|
-
items: schema.viewItems,
|
|
986
|
-
currentItemId: activeView.value,
|
|
987
|
-
onSelect: (item: PillNavItem) => setActiveView(item.id),
|
|
988
|
-
}) as ControlWorkspacePillNavBinding
|
|
989
|
-
const topBarSettingsBinding = {
|
|
990
|
-
showSettings: true,
|
|
991
|
-
settingsConfig: topBarSettingsConfig,
|
|
992
|
-
onSettingsValuesChange: setValues,
|
|
993
|
-
} as ControlWorkspaceTopBarSettingsBinding
|
|
994
|
-
const topBarProps = computed<ControlWorkspaceTopBarBinding>(() => ({
|
|
995
|
-
pillNav: pillNav.items,
|
|
996
|
-
currentPillId: pillNav.currentItemId,
|
|
997
|
-
onPillSelect: pillNav.onSelect,
|
|
998
|
-
...topBarSettingsBinding,
|
|
999
|
-
}))
|
|
1000
|
-
const bindings: ControlWorkspaceComponentBindings = {
|
|
1001
|
-
form,
|
|
1002
|
-
sidebar,
|
|
1003
|
-
topBar: topBarProps,
|
|
1004
|
-
topBarSettings: topBarSettingsBinding,
|
|
1005
|
-
pillNav,
|
|
1006
|
-
componentBindings,
|
|
1007
|
-
componentBindingsById,
|
|
1008
|
-
componentProps,
|
|
1009
|
-
componentPropsById,
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
watch(activeView, syncActiveView, { flush: 'sync' })
|
|
1013
|
-
watch(() => sidebar.activeView, syncActiveView, { flush: 'sync' })
|
|
1014
|
-
watch(() => pillNav.currentItemId, syncActiveView, { flush: 'sync' })
|
|
1015
|
-
|
|
1016
|
-
return {
|
|
1017
|
-
...schema,
|
|
1018
|
-
schema,
|
|
1019
|
-
values,
|
|
1020
|
-
activeView,
|
|
1021
|
-
topBarSettingsConfig,
|
|
1022
|
-
form,
|
|
1023
|
-
sidebar,
|
|
1024
|
-
topBar: topBarProps,
|
|
1025
|
-
pillNav,
|
|
1026
|
-
topBarSettings: topBarSettingsBinding,
|
|
1027
|
-
bindings,
|
|
1028
|
-
componentBindings,
|
|
1029
|
-
componentBindingsById,
|
|
1030
|
-
componentProps,
|
|
1031
|
-
componentPropsById,
|
|
1032
|
-
setActiveView,
|
|
1033
|
-
setValues,
|
|
1034
|
-
resetValues,
|
|
1035
|
-
getComponentProps,
|
|
1036
|
-
getComponentPropsById,
|
|
1037
|
-
getComponentBindings,
|
|
1038
|
-
getComponentBindingsById,
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
function normalizeControls(
|
|
1043
|
-
controls: ControlSchema,
|
|
1044
|
-
options: ControlSchemaOptions = {},
|
|
1045
|
-
): NormalizedControl[] {
|
|
1046
|
-
return Object.entries(controls)
|
|
1047
|
-
.map(([name, input], index): NormalizedControl => {
|
|
1048
|
-
const definition = normalizeControlDefinition(input)
|
|
1049
|
-
const type = definition.type ?? inferControlType(definition)
|
|
1050
|
-
return {
|
|
1051
|
-
name,
|
|
1052
|
-
definition,
|
|
1053
|
-
type,
|
|
1054
|
-
sectionId: definition.section ?? options.section ?? 'controls',
|
|
1055
|
-
viewId: definition.view ?? options.view ?? 'default',
|
|
1056
|
-
order: definition.order ?? index,
|
|
1057
|
-
}
|
|
1058
|
-
})
|
|
1059
|
-
.sort((a, b) => a.order - b.order)
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
function normalizeControlDefinition(input: ControlInput): ControlDefinition {
|
|
1063
|
-
if (isControlOptionArray(input)) {
|
|
1064
|
-
if (input.length === 0) return { type: 'tags', default: [] }
|
|
1065
|
-
return {
|
|
1066
|
-
default: optionValue(input[0]),
|
|
1067
|
-
options: input,
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
if (typeof input === 'string' || typeof input === 'number' || typeof input === 'boolean') {
|
|
1072
|
-
return { default: input }
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
return input
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
704
|
function appendModelControls(
|
|
1079
705
|
target: ControlSchema,
|
|
1080
706
|
source: ControlSchema,
|
|
@@ -1116,113 +742,6 @@ function registerSectionOptions(
|
|
|
1116
742
|
})
|
|
1117
743
|
}
|
|
1118
744
|
|
|
1119
|
-
function isControlOptionArray(input: ControlInput): input is readonly ControlOption[] {
|
|
1120
|
-
return Array.isArray(input)
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
function inferControlType(definition: ControlDefinition): FormFieldType {
|
|
1124
|
-
const value = definition.default ?? definition.defaultValue
|
|
1125
|
-
if (definition.options?.length) return Array.isArray(value) ? 'multiselect' : 'select'
|
|
1126
|
-
if (typeof value === 'boolean') return 'toggle'
|
|
1127
|
-
if (typeof value === 'number') return 'number'
|
|
1128
|
-
if (Array.isArray(value)) return 'tags'
|
|
1129
|
-
return 'text'
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
|
-
function defaultValueForControl(definition: ControlDefinition, type: FormFieldType): unknown {
|
|
1133
|
-
if (definition.default !== undefined) return definition.default
|
|
1134
|
-
if (definition.defaultValue !== undefined) return definition.defaultValue
|
|
1135
|
-
return getTypeDefault(type)
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
function controlToFormField(control: NormalizedControl): FormFieldSchema {
|
|
1139
|
-
const { name, definition, type } = control
|
|
1140
|
-
const props = fieldProps(definition)
|
|
1141
|
-
return {
|
|
1142
|
-
name,
|
|
1143
|
-
label: definition.label ?? humanize(name),
|
|
1144
|
-
type,
|
|
1145
|
-
defaultValue: defaultValueForControl(definition, type),
|
|
1146
|
-
placeholder: definition.placeholder,
|
|
1147
|
-
hint: definition.hint,
|
|
1148
|
-
size: definition.size,
|
|
1149
|
-
disabled: definition.disabled,
|
|
1150
|
-
readonly: definition.readonly,
|
|
1151
|
-
validation: validationForControl(definition),
|
|
1152
|
-
condition: definition.condition,
|
|
1153
|
-
colSpan: definition.colSpan,
|
|
1154
|
-
props,
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
function fieldProps(definition: ControlDefinition): Record<string, unknown> {
|
|
1159
|
-
const props: Record<string, unknown> = {}
|
|
1160
|
-
if (definition.min !== undefined) props.min = numericValue(definition.min)
|
|
1161
|
-
if (definition.max !== undefined) props.max = numericValue(definition.max)
|
|
1162
|
-
if (definition.options) props.options = definition.options.map(normalizeOption)
|
|
1163
|
-
return { ...props, ...(definition.props ?? {}) }
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
function validationForControl(definition: ControlDefinition): FieldValidation | undefined {
|
|
1167
|
-
const validation: FieldValidation = { ...(definition.validation ?? {}) }
|
|
1168
|
-
if (definition.required !== undefined) validation.required = definition.required
|
|
1169
|
-
if (definition.min !== undefined) validation.min = definition.min
|
|
1170
|
-
if (definition.max !== undefined) validation.max = definition.max
|
|
1171
|
-
if (definition.minLength !== undefined) validation.minLength = definition.minLength
|
|
1172
|
-
if (definition.maxLength !== undefined) validation.maxLength = definition.maxLength
|
|
1173
|
-
if (definition.email !== undefined) validation.email = definition.email
|
|
1174
|
-
if (definition.pattern !== undefined) validation.pattern = definition.pattern
|
|
1175
|
-
return Object.keys(validation).length > 0 ? validation : undefined
|
|
1176
|
-
}
|
|
1177
|
-
|
|
1178
|
-
function sectionConfig(
|
|
1179
|
-
sectionId: string,
|
|
1180
|
-
controls: NormalizedControl[],
|
|
1181
|
-
options: ControlSchemaOptions,
|
|
1182
|
-
): ControlSectionConfig {
|
|
1183
|
-
const configured = options.sections?.[sectionId]
|
|
1184
|
-
const first = controls[0]?.definition
|
|
1185
|
-
return {
|
|
1186
|
-
...configured,
|
|
1187
|
-
id: sectionId,
|
|
1188
|
-
label: configured?.label ?? first?.sectionLabel,
|
|
1189
|
-
title: configured?.title ?? first?.sectionLabel,
|
|
1190
|
-
description: configured?.description ?? first?.sectionDescription,
|
|
1191
|
-
subtitle: configured?.subtitle ?? first?.sectionSubtitle,
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
|
|
1195
|
-
function firstSidebarConfig(controls: NormalizedControl[]): ControlSidebarConfig | undefined {
|
|
1196
|
-
for (const control of controls) {
|
|
1197
|
-
const sidebar = control.definition.sidebar
|
|
1198
|
-
if (sidebar && typeof sidebar === 'object' && sidebar.enabled !== false) return sidebar
|
|
1199
|
-
}
|
|
1200
|
-
return undefined
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
function isSidebarEnabled(sidebar: ControlDefinition['sidebar']): boolean {
|
|
1204
|
-
if (sidebar === false) return false
|
|
1205
|
-
if (sidebar && typeof sidebar === 'object') return sidebar.enabled !== false
|
|
1206
|
-
return true
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
function normalizeOption(option: ControlOption): SelectOption<unknown> {
|
|
1210
|
-
if (typeof option === 'object' && option !== null && 'label' in option) {
|
|
1211
|
-
return option
|
|
1212
|
-
}
|
|
1213
|
-
return {
|
|
1214
|
-
value: option,
|
|
1215
|
-
label: humanize(String(option)),
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
|
|
1219
|
-
function optionValue(option: ControlOption): ControlOptionValue | unknown {
|
|
1220
|
-
if (typeof option === 'object' && option !== null && 'value' in option) {
|
|
1221
|
-
return option.value
|
|
1222
|
-
}
|
|
1223
|
-
return option
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
745
|
function compactComponentPropsMap<TValues extends Record<string, unknown>>(
|
|
1227
746
|
mapping: Record<string, ControlComponentPropSource<TValues> | undefined>,
|
|
1228
747
|
): ControlComponentPropsMap<TValues> {
|
|
@@ -1233,31 +752,6 @@ function compactComponentPropsMap<TValues extends Record<string, unknown>>(
|
|
|
1233
752
|
)
|
|
1234
753
|
}
|
|
1235
754
|
|
|
1236
|
-
function normalizeControlComponentBindingConfigs<TValues extends Record<string, unknown>>(
|
|
1237
|
-
bindings: ControlComponentBindingsConfig<TValues>,
|
|
1238
|
-
): Array<Required<Pick<ControlComponentBindingConfig<TValues>, 'id' | 'component'>> & Pick<ControlComponentBindingConfig<TValues>, 'props'>> {
|
|
1239
|
-
if (Array.isArray(bindings)) {
|
|
1240
|
-
const usedIds = new Map<string, number>()
|
|
1241
|
-
return bindings.map(binding => ({
|
|
1242
|
-
id: uniqueComponentBindingId(binding.id ?? binding.component, usedIds),
|
|
1243
|
-
component: binding.component,
|
|
1244
|
-
props: binding.props,
|
|
1245
|
-
}))
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
return Object.entries(bindings).map(([id, binding]) => ({
|
|
1249
|
-
id,
|
|
1250
|
-
component: binding.component,
|
|
1251
|
-
props: binding.props,
|
|
1252
|
-
}))
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
function uniqueComponentBindingId(id: string, usedIds: Map<string, number>): string {
|
|
1256
|
-
const count = usedIds.get(id) ?? 0
|
|
1257
|
-
usedIds.set(id, count + 1)
|
|
1258
|
-
return count === 0 ? id : `${id}-${count + 1}`
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
755
|
function sourceKey<TValues extends Record<string, unknown>>(key: string): keyof TValues & string {
|
|
1262
756
|
return key as keyof TValues & string
|
|
1263
757
|
}
|
|
@@ -1310,53 +804,3 @@ function updateWellsFromDoseResults<TValues extends Record<string, unknown>>(
|
|
|
1310
804
|
writableValues[source] = nextWells
|
|
1311
805
|
}
|
|
1312
806
|
}
|
|
1313
|
-
|
|
1314
|
-
function recordValue(value: unknown): Record<string, unknown> {
|
|
1315
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
1316
|
-
? value as Record<string, unknown>
|
|
1317
|
-
: {}
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
function numericValue(value: number | { value: number; message: string }): number {
|
|
1321
|
-
return typeof value === 'number' ? value : value.value
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
function orderedUnique(values: string[]): string[] {
|
|
1325
|
-
return [...new Set(values)]
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
function controlViewItem(viewId: string, options: ControlSchemaOptions): PillNavItem {
|
|
1329
|
-
const config = options.views?.[viewId]
|
|
1330
|
-
return {
|
|
1331
|
-
id: viewId,
|
|
1332
|
-
label: config?.label ?? humanize(viewId),
|
|
1333
|
-
...(config?.icon !== undefined ? { icon: config.icon } : {}),
|
|
1334
|
-
...(config?.to !== undefined ? { to: config.to } : {}),
|
|
1335
|
-
...(config?.href !== undefined ? { href: config.href } : {}),
|
|
1336
|
-
...(config?.disabled !== undefined ? { disabled: config.disabled } : {}),
|
|
1337
|
-
...(config?.children !== undefined ? { children: config.children } : {}),
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
function replaceRecord(target: Record<string, unknown>, values: Record<string, unknown>) {
|
|
1342
|
-
for (const key of Object.keys(target)) {
|
|
1343
|
-
delete target[key]
|
|
1344
|
-
}
|
|
1345
|
-
Object.assign(target, values)
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
function omitUndefined<T extends object>(record: T): T {
|
|
1349
|
-
const next: Record<string, unknown> = {}
|
|
1350
|
-
for (const [key, value] of Object.entries(record as Record<string, unknown>)) {
|
|
1351
|
-
if (value !== undefined) next[key] = value
|
|
1352
|
-
}
|
|
1353
|
-
return next as T
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
function humanize(value: string): string {
|
|
1357
|
-
return value
|
|
1358
|
-
.replace(/[_-]+/g, ' ')
|
|
1359
|
-
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
1360
|
-
.trim()
|
|
1361
|
-
.replace(/\w\S*/g, word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
1362
|
-
}
|