@morscherlab/mint-sdk 1.0.0-rc.4 → 1.0.0-rc.6
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/dist/__tests__/components/AppTopBar.navigation.test.d.ts +1 -0
- package/dist/__tests__/components/DoseCalculatorVolumeField.test.d.ts +1 -0
- package/dist/__tests__/components/PlateMapEditorToolbarInternal.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.controls.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.navigation.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.shell.test.d.ts +1 -0
- package/dist/__tests__/components/ProtocolStep.presentation.test.d.ts +1 -0
- package/dist/__tests__/components/ProtocolStepEditor.state.test.d.ts +1 -0
- package/dist/__tests__/components/ProtocolStepParameterField.test.d.ts +1 -0
- package/dist/__tests__/components/ReagentList.presentation.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.colors.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.drag.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.groups.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.selection.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelectorSampleRow.test.d.ts +1 -0
- package/dist/__tests__/components/ScheduleCalendar.test.d.ts +1 -0
- package/dist/__tests__/components/SettingsModal.schema.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.colors.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.conditions.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.geometry.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.interaction.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.legend.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.rendering.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.sampleDrop.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/classify.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/columns.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/compose.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/cooccurrence.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/fingerprint.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/integration.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/template.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/tokenize.test.d.ts +1 -0
- package/dist/__tests__/composables/useAutoGroupInputSources.test.d.ts +1 -0
- package/dist/__tests__/composables/useScheduleCalendarLayout.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsComponents.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsExports.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsParsing.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsTemplates.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsTheme.test.d.ts +1 -0
- package/dist/components/AppSidebar.vue.d.ts +9 -6
- package/dist/components/AppTopBar.navigation.d.ts +11 -0
- package/dist/components/BaseButton.vue.d.ts +1 -1
- package/dist/components/BaseCheckbox.vue.d.ts +7 -2
- 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 +2 -2
- package/dist/components/BaseSelect.vue.d.ts +1 -1
- package/dist/components/BaseSlider.vue.d.ts +2 -2
- package/dist/components/BaseTextarea.vue.d.ts +2 -2
- package/dist/components/BaseToggle.vue.d.ts +7 -2
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +1 -1
- package/dist/components/CollapsibleCard.vue.d.ts +9 -0
- package/dist/components/ColorSlider.vue.d.ts +2 -2
- package/dist/components/ConcentrationInput.vue.d.ts +2 -2
- package/dist/components/ControlWorkspaceView.vue.d.ts +4 -4
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/DateTimePicker.vue.d.ts +2 -2
- package/dist/components/DoseCalculatorVolumeField.vue.d.ts +15 -0
- package/dist/components/DoseDesignWorkspaceView.vue.d.ts +2 -2
- package/dist/components/DropdownButton.vue.d.ts +1 -1
- package/dist/components/FileUploader.vue.d.ts +2 -2
- package/dist/components/FormulaInput.vue.d.ts +2 -2
- package/dist/components/IconButton.vue.d.ts +1 -1
- package/dist/components/LoadingSpinner.vue.d.ts +1 -1
- package/dist/components/MoleculeInput.vue.d.ts +2 -2
- package/dist/components/MultiSelect.vue.d.ts +1 -1
- package/dist/components/NumberInput.vue.d.ts +1 -1
- package/dist/components/PlateMapEditor.vue.d.ts +6 -6
- package/dist/components/PluginWorkspaceView.controls.d.ts +28 -0
- package/dist/components/PluginWorkspaceView.navigation.d.ts +29 -0
- package/dist/components/PluginWorkspaceView.props.d.ts +151 -0
- package/dist/components/PluginWorkspaceView.shell.d.ts +19 -0
- package/dist/components/PluginWorkspaceView.vue.d.ts +51 -196
- package/dist/components/ProgressBar.vue.d.ts +1 -1
- package/dist/components/ProtocolStep.presentation.d.ts +4 -0
- package/dist/components/ProtocolStepEditor.state.d.ts +18 -0
- package/dist/components/ProtocolStepParameterField.vue.d.ts +12 -0
- package/dist/components/ReagentList.presentation.d.ts +16 -0
- package/dist/components/ResourceCard.vue.d.ts +1 -1
- package/dist/components/SampleSelector.colors.d.ts +13 -0
- package/dist/components/SampleSelector.drag.d.ts +24 -0
- package/dist/components/SampleSelector.groups.d.ts +15 -0
- package/dist/components/SampleSelector.selection.d.ts +26 -0
- package/dist/components/SampleSelector.vue.d.ts +4 -1
- package/dist/components/SampleSelectorSampleRow.vue.d.ts +21 -0
- package/dist/components/SegmentedControl.vue.d.ts +1 -1
- package/dist/components/SequenceInput.vue.d.ts +2 -2
- package/dist/components/SequenceProgressBar.vue.d.ts +1 -1
- package/dist/components/SettingsModal.schema.d.ts +9 -0
- package/dist/components/StatusIndicator.vue.d.ts +1 -1
- package/dist/components/TagsInput.vue.d.ts +2 -2
- package/dist/components/TimePicker.vue.d.ts +2 -2
- package/dist/components/TimeRangeInput.vue.d.ts +1 -1
- package/dist/components/UnitInput.vue.d.ts +2 -2
- package/dist/components/WellPlate.colors.d.ts +9 -0
- package/dist/components/WellPlate.conditions.d.ts +26 -0
- package/dist/components/WellPlate.geometry.d.ts +23 -0
- package/dist/components/WellPlate.interaction.d.ts +71 -0
- package/dist/components/WellPlate.legend.d.ts +2 -0
- package/dist/components/WellPlate.rendering.d.ts +24 -0
- package/dist/components/WellPlate.sampleDrop.d.ts +8 -0
- package/dist/components/WellPlate.vue.d.ts +1 -1
- package/dist/components/index.js +2 -2
- package/dist/components/internal/ActionItemInternal.vue.d.ts +1 -1
- package/dist/components/internal/PlateMapEditorToolbarInternal.vue.d.ts +28 -0
- package/dist/{components-DafPc4rM.js → components-Blx4MG--.js} +4073 -4222
- package/dist/components-Blx4MG--.js.map +1 -0
- package/dist/composables/autoGroup/classKey.d.ts +4 -0
- package/dist/composables/autoGroup/classify.d.ts +28 -0
- package/dist/composables/autoGroup/colors.d.ts +2 -0
- package/dist/composables/autoGroup/columns.d.ts +10 -0
- package/dist/composables/autoGroup/compose.d.ts +8 -0
- package/dist/composables/autoGroup/cooccurrence.d.ts +2 -0
- package/dist/composables/autoGroup/csv-shim.d.ts +2 -0
- package/dist/composables/autoGroup/fingerprint.d.ts +3 -0
- package/dist/composables/autoGroup/index.d.ts +16 -0
- package/dist/composables/autoGroup/replicatePreGroup.d.ts +38 -0
- package/dist/composables/autoGroup/template.d.ts +15 -0
- package/dist/composables/autoGroup/tokenize.d.ts +8 -0
- package/dist/composables/autoGroupConstants.d.ts +1 -0
- package/dist/composables/autoGroupGrouping.d.ts +3 -0
- package/dist/composables/controlComponentBindings.d.ts +1 -1
- package/dist/composables/controlSchemaAdapters.d.ts +1 -1
- package/dist/composables/controlSchemaDoseDesign.d.ts +11 -0
- package/dist/composables/controlSchemaLayout.d.ts +1 -1
- package/dist/composables/controlSchemaModel.d.ts +5 -0
- package/dist/composables/controlSchemaNormalize.d.ts +1 -1
- package/dist/composables/controlSchemaTypes.d.ts +311 -0
- package/dist/composables/controlWorkspaceOptions.d.ts +1 -1
- package/dist/composables/formBuilderSchema.d.ts +18 -0
- package/dist/composables/index.js +3 -3
- package/dist/composables/pluginEndpointBuilder.d.ts +13 -0
- package/dist/composables/protocolTemplateCatalog.d.ts +26 -0
- package/dist/composables/useAutoGroup.d.ts +61 -74
- package/dist/composables/useAutoGroupInputSources.d.ts +32 -0
- package/dist/composables/useBioTemplateControls.d.ts +1 -1
- package/dist/composables/useBioTemplatePresetWorkspace.d.ts +1 -1
- package/dist/composables/useBioTemplateWorkspace.d.ts +1 -1
- package/dist/composables/useControlSchema.d.ts +4 -316
- package/dist/composables/useControlWorkspace.d.ts +1 -1
- package/dist/composables/useForm.d.ts +2 -33
- package/dist/composables/useFormBuilder.d.ts +2 -9
- package/dist/composables/useFormValidation.d.ts +34 -0
- package/dist/composables/usePluginClient.d.ts +1 -4
- package/dist/composables/useProtocolTemplates.d.ts +2 -24
- package/dist/composables/useScheduleCalendarLayout.d.ts +49 -0
- package/dist/{composables-BMkPQhVK.js → composables-CHDjDIQT.js} +33 -31
- package/dist/composables-CHDjDIQT.js.map +1 -0
- package/dist/index.js +4 -4
- package/dist/install.js +2 -2
- package/dist/styles.css +1432 -660
- package/dist/templates/controlSchemaTypes.d.ts +1 -1
- package/dist/templates/index.js +1 -1
- package/dist/templates/templateAdapterTypes.d.ts +48 -0
- package/dist/templates/templateCreateOptions.d.ts +165 -0
- package/dist/templates/templateQpcrTypes.d.ts +42 -0
- package/dist/templates/types.d.ts +5 -250
- package/dist/{templates-bUAWMn5L.js → templates-DSbHJC4v.js} +1536 -297
- package/dist/templates-DSbHJC4v.js.map +1 -0
- package/dist/types/auto-group.d.ts +79 -9
- package/dist/types/componentLabTypes.d.ts +161 -0
- package/dist/types/componentWorkflowTypes.d.ts +150 -0
- package/dist/types/components.d.ts +14 -311
- package/dist/types/form-builder.d.ts +3 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/{useProtocolTemplates-QZtHFFH2.js → useProtocolTemplates-BbPOYPzO.js} +1220 -454
- package/dist/useProtocolTemplates-BbPOYPzO.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/components/AppSidebar.test.ts +67 -0
- package/src/__tests__/components/AppTopBar.navigation.test.ts +70 -0
- package/src/__tests__/components/CollapsibleCard.test.ts +47 -0
- package/src/__tests__/components/DoseCalculatorVolumeField.test.ts +53 -0
- package/src/__tests__/components/FormBuilder.test.ts +57 -0
- package/src/__tests__/components/PlateMapEditorToolbarInternal.test.ts +54 -0
- package/src/__tests__/components/PluginWorkspaceView.controls.test.ts +156 -0
- package/src/__tests__/components/PluginWorkspaceView.navigation.test.ts +102 -0
- package/src/__tests__/components/PluginWorkspaceView.shell.test.ts +43 -0
- package/src/__tests__/components/ProtocolStep.presentation.test.ts +31 -0
- package/src/__tests__/components/ProtocolStepEditor.state.test.ts +165 -0
- package/src/__tests__/components/ProtocolStepParameterField.test.ts +44 -0
- package/src/__tests__/components/ReagentList.presentation.test.ts +68 -0
- package/src/__tests__/components/SampleSelector.colors.test.ts +49 -0
- package/src/__tests__/components/SampleSelector.drag.test.ts +100 -0
- package/src/__tests__/components/SampleSelector.groups.test.ts +81 -0
- package/src/__tests__/components/SampleSelector.selection.test.ts +70 -0
- package/src/__tests__/components/SampleSelector.test.ts +32 -0
- package/src/__tests__/components/SampleSelectorSampleRow.test.ts +37 -0
- package/src/__tests__/components/ScheduleCalendar.test.ts +44 -0
- package/src/__tests__/components/SettingsModal.schema.test.ts +97 -0
- package/src/__tests__/components/WellPlate.colors.test.ts +28 -0
- package/src/__tests__/components/WellPlate.conditions.test.ts +68 -0
- package/src/__tests__/components/WellPlate.geometry.test.ts +54 -0
- package/src/__tests__/components/WellPlate.interaction.test.ts +171 -0
- package/src/__tests__/components/WellPlate.legend.test.ts +13 -0
- package/src/__tests__/components/WellPlate.rendering.test.ts +122 -0
- package/src/__tests__/components/WellPlate.sampleDrop.test.ts +70 -0
- package/src/__tests__/composables/autoGroup/classify.test.ts +107 -0
- package/src/__tests__/composables/autoGroup/columns.test.ts +135 -0
- package/src/__tests__/composables/autoGroup/compose.test.ts +227 -0
- package/src/__tests__/composables/autoGroup/cooccurrence.test.ts +91 -0
- package/src/__tests__/composables/autoGroup/fingerprint.test.ts +50 -0
- package/src/__tests__/composables/autoGroup/integration.test.ts +79 -0
- package/src/__tests__/composables/autoGroup/template.test.ts +70 -0
- package/src/__tests__/composables/autoGroup/tokenize.test.ts +33 -0
- package/src/__tests__/composables/useAutoGroup.test.ts +129 -625
- package/src/__tests__/composables/useAutoGroupInputSources.test.ts +107 -0
- package/src/__tests__/composables/useControlSchema.test.ts +23 -0
- package/src/__tests__/composables/useScheduleCalendarLayout.test.ts +89 -0
- package/src/__tests__/docs/extractDocsComponents.test.ts +142 -0
- package/src/__tests__/docs/extractDocsExports.test.ts +77 -0
- package/src/__tests__/docs/extractDocsParsing.test.ts +69 -0
- package/src/__tests__/docs/extractDocsTemplates.test.ts +54 -0
- package/src/__tests__/docs/extractDocsTheme.test.ts +89 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +1 -1
- package/src/__tests__/fixtures/auto-group/mixed-lc-ms-batch.txt +187 -0
- package/src/components/AppSidebar.story.vue +79 -6
- package/src/components/AppSidebar.vue +74 -6
- package/src/components/AppTopBar.navigation.ts +62 -0
- package/src/components/AppTopBar.vue +17 -44
- package/src/components/AutoGroupModal.story.vue +50 -0
- package/src/components/AutoGroupModal.vue +441 -158
- package/src/components/BaseCheckbox.story.vue +27 -0
- package/src/components/BaseCheckbox.vue +63 -1
- package/src/components/BaseToggle.story.vue +27 -0
- package/src/components/BaseToggle.vue +66 -1
- package/src/components/CollapsibleCard.vue +123 -45
- package/src/components/ControlWorkspaceView.vue +2 -6
- package/src/components/DoseCalculator.vue +13 -73
- package/src/components/DoseCalculatorVolumeField.vue +61 -0
- package/src/components/ExperimentTimeline.vue +6 -31
- package/src/components/FormBuilder.story.vue +13 -0
- package/src/components/FormBuilder.vue +2 -7
- package/src/components/PlateMapEditor.vue +32 -106
- package/src/components/PluginWorkspaceView.controls.ts +182 -0
- package/src/components/PluginWorkspaceView.navigation.ts +106 -0
- package/src/components/PluginWorkspaceView.props.ts +174 -0
- package/src/components/PluginWorkspaceView.shell.ts +67 -0
- package/src/components/PluginWorkspaceView.vue +88 -404
- package/src/components/ProtocolStep.presentation.ts +31 -0
- package/src/components/ProtocolStepEditor.state.ts +104 -0
- package/src/components/ProtocolStepEditor.vue +48 -179
- package/src/components/ProtocolStepParameterField.vue +134 -0
- package/src/components/ReagentList.presentation.ts +105 -0
- package/src/components/ReagentList.vue +16 -79
- package/src/components/SampleSelector.colors.ts +43 -0
- package/src/components/SampleSelector.drag.ts +164 -0
- package/src/components/SampleSelector.groups.ts +109 -0
- package/src/components/SampleSelector.selection.ts +103 -0
- package/src/components/SampleSelector.vue +82 -349
- package/src/components/SampleSelectorSampleRow.vue +64 -0
- package/src/components/ScheduleCalendar.vue +44 -199
- package/src/components/SettingsModal.schema.ts +71 -0
- package/src/components/SettingsModal.vue +16 -46
- package/src/components/WellPlate.colors.ts +56 -0
- package/src/components/WellPlate.conditions.ts +100 -0
- package/src/components/WellPlate.geometry.ts +91 -0
- package/src/components/WellPlate.interaction.ts +272 -0
- package/src/components/WellPlate.legend.ts +8 -0
- package/src/components/WellPlate.rendering.ts +105 -0
- package/src/components/WellPlate.sampleDrop.ts +73 -0
- package/src/components/WellPlate.vue +102 -550
- package/src/components/internal/FormFieldRendererInternal.vue +23 -5
- package/src/components/internal/PlateMapEditorToolbarInternal.vue +128 -0
- package/src/composables/autoGroup/classKey.ts +5 -0
- package/src/composables/autoGroup/classify.ts +205 -0
- package/src/composables/autoGroup/colors.ts +6 -0
- package/src/composables/autoGroup/columns.ts +226 -0
- package/src/composables/autoGroup/compose.ts +156 -0
- package/src/composables/autoGroup/cooccurrence.ts +46 -0
- package/src/composables/autoGroup/csv-shim.ts +44 -0
- package/src/composables/autoGroup/fingerprint.ts +49 -0
- package/src/composables/autoGroup/index.ts +20 -0
- package/src/composables/autoGroup/replicatePreGroup.ts +90 -0
- package/src/composables/autoGroup/template.ts +126 -0
- package/src/composables/autoGroup/tokenize.ts +41 -0
- package/src/composables/autoGroup/vocab.json +67 -0
- package/src/composables/autoGroupConstants.ts +4 -0
- package/src/composables/autoGroupGrouping.ts +148 -0
- package/src/composables/controlComponentBindings.ts +1 -1
- package/src/composables/controlSchemaAdapters.ts +4 -1
- package/src/composables/controlSchemaDoseDesign.ts +215 -0
- package/src/composables/controlSchemaFormFields.ts +4 -1
- package/src/composables/controlSchemaLayout.ts +1 -1
- package/src/composables/controlSchemaModel.ts +163 -0
- package/src/composables/controlSchemaNormalize.ts +1 -1
- package/src/composables/controlSchemaTypes.ts +372 -0
- package/src/composables/controlWorkspaceOptions.ts +1 -1
- package/src/composables/formBuilderSchema.ts +153 -0
- package/src/composables/pluginEndpointBuilder.ts +203 -0
- package/src/composables/protocolTemplateCatalog.ts +325 -0
- package/src/composables/useAutoGroup.ts +395 -549
- package/src/composables/useAutoGroupInputSources.ts +147 -0
- package/src/composables/useBioTemplateControls.ts +1 -1
- package/src/composables/useBioTemplatePresetWorkspace.ts +1 -1
- package/src/composables/useBioTemplateWorkspace.ts +1 -1
- package/src/composables/useControlSchema.ts +21 -692
- package/src/composables/useControlWorkspace.ts +7 -13
- package/src/composables/useForm.ts +5 -187
- package/src/composables/useFormBuilder.ts +11 -153
- package/src/composables/useFormValidation.ts +154 -0
- package/src/composables/usePluginClient.ts +10 -193
- package/src/composables/useProtocolTemplates.ts +10 -328
- package/src/composables/useScheduleCalendarLayout.ts +287 -0
- package/src/styles/components/app-sidebar.css +134 -6
- package/src/styles/components/auto-group-modal.css +248 -310
- package/src/styles/components/checkbox.css +87 -0
- package/src/styles/components/collapsible-card.css +154 -14
- package/src/styles/components/toggle.css +80 -0
- package/src/templates/controlSchemaTypes.ts +1 -1
- package/src/templates/templateAdapterTypes.ts +58 -0
- package/src/templates/templateCreateOptions.ts +208 -0
- package/src/templates/templateQpcrTypes.ts +48 -0
- package/src/templates/types.ts +79 -275
- package/src/types/auto-group.ts +107 -9
- package/src/types/componentLabTypes.ts +235 -0
- package/src/types/componentWorkflowTypes.ts +190 -0
- package/src/types/components.ts +95 -424
- package/src/types/form-builder.ts +3 -0
- package/src/types/index.ts +2 -0
- package/dist/components-DafPc4rM.js.map +0 -1
- package/dist/composables-BMkPQhVK.js.map +0 -1
- package/dist/templates-bUAWMn5L.js.map +0 -1
- package/dist/useProtocolTemplates-QZtHFFH2.js.map +0 -1
|
@@ -19,6 +19,9 @@ import {
|
|
|
19
19
|
controlValuesToComponentBindingsById,
|
|
20
20
|
controlValuesToComponentProps,
|
|
21
21
|
} from './controlComponentBindings'
|
|
22
|
+
import {
|
|
23
|
+
isControlModelBinding,
|
|
24
|
+
} from './controlSchemaModel'
|
|
22
25
|
import {
|
|
23
26
|
useControlSchema,
|
|
24
27
|
} from './useControlSchema'
|
|
@@ -39,14 +42,16 @@ import type {
|
|
|
39
42
|
ControlWorkspaceTopBarBinding,
|
|
40
43
|
ControlWorkspaceTopBarSettingsBinding,
|
|
41
44
|
UseControlWorkspaceReturn,
|
|
42
|
-
} from './
|
|
45
|
+
} from './controlSchemaTypes'
|
|
43
46
|
|
|
44
47
|
/** Prepare shared reactive values plus AppTopBar/AppSidebar/FormBuilder bindings from one simple controls data model. */
|
|
45
48
|
export function useControlWorkspace<TControls extends ControlSchema>(
|
|
46
49
|
controlsOrModel: TControls | (ControlModelBinding & { controls: TControls }),
|
|
47
50
|
options: ControlWorkspaceOptions = {},
|
|
48
51
|
): UseControlWorkspaceReturn<TControls> {
|
|
49
|
-
const model =
|
|
52
|
+
const model = isControlModelBinding<ControlModelBinding & { controls: TControls }>(controlsOrModel)
|
|
53
|
+
? controlsOrModel
|
|
54
|
+
: undefined
|
|
50
55
|
const controls: TControls = model ? model.controls : controlsOrModel as TControls
|
|
51
56
|
const workspaceOptions = model
|
|
52
57
|
? mergeControlWorkspaceOptions(model.controlOptions, options)
|
|
@@ -194,14 +199,3 @@ export function useControlWorkspace<TControls extends ControlSchema>(
|
|
|
194
199
|
getComponentBindingsById,
|
|
195
200
|
}
|
|
196
201
|
}
|
|
197
|
-
|
|
198
|
-
function isControlModelBindingInput<TControls extends ControlSchema>(
|
|
199
|
-
value: TControls | (ControlModelBinding & { controls: TControls }),
|
|
200
|
-
): value is ControlModelBinding & { controls: TControls } {
|
|
201
|
-
return (
|
|
202
|
-
typeof value === 'object'
|
|
203
|
-
&& value !== null
|
|
204
|
-
&& 'controls' in value
|
|
205
|
-
&& 'controlOptions' in value
|
|
206
|
-
)
|
|
207
|
-
}
|
|
@@ -1,24 +1,7 @@
|
|
|
1
1
|
import { ref, reactive, computed, toRaw, watch, type Ref } from 'vue'
|
|
2
|
+
import { validateFieldValue, type FieldRules } from './useFormValidation'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
* Validation rule function type.
|
|
5
|
-
* Returns error message string if invalid, undefined/null if valid.
|
|
6
|
-
*/
|
|
7
|
-
export type ValidationRule<T = unknown> = (value: T, formData: Record<string, unknown>) => string | undefined | null
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Field validation rules configuration.
|
|
11
|
-
*/
|
|
12
|
-
export interface FieldRules<T = unknown> {
|
|
13
|
-
required?: boolean | string
|
|
14
|
-
minLength?: number | { value: number; message: string }
|
|
15
|
-
maxLength?: number | { value: number; message: string }
|
|
16
|
-
min?: number | { value: number; message: string }
|
|
17
|
-
max?: number | { value: number; message: string }
|
|
18
|
-
pattern?: RegExp | { value: RegExp; message: string }
|
|
19
|
-
email?: boolean | string
|
|
20
|
-
custom?: ValidationRule<T> | ValidationRule<T>[]
|
|
21
|
-
}
|
|
4
|
+
export type { FieldRules, ValidationRule } from './useFormValidation'
|
|
22
5
|
|
|
23
6
|
/**
|
|
24
7
|
* Field validation rules configuration.
|
|
@@ -69,68 +52,6 @@ export interface UseFormReturn<T extends Record<string, unknown>> {
|
|
|
69
52
|
}
|
|
70
53
|
}
|
|
71
54
|
|
|
72
|
-
// Built-in validators
|
|
73
|
-
const validators = {
|
|
74
|
-
required: (value: unknown, message = 'This field is required'): string | null => {
|
|
75
|
-
if (value === null || value === undefined || value === '') {
|
|
76
|
-
return message
|
|
77
|
-
}
|
|
78
|
-
if (Array.isArray(value) && value.length === 0) {
|
|
79
|
-
return message
|
|
80
|
-
}
|
|
81
|
-
return null
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
minLength: (value: unknown, min: number, message?: string): string | null => {
|
|
85
|
-
if (typeof value !== 'string') return null
|
|
86
|
-
if (value.length < min) {
|
|
87
|
-
return message || `Must be at least ${min} characters`
|
|
88
|
-
}
|
|
89
|
-
return null
|
|
90
|
-
},
|
|
91
|
-
|
|
92
|
-
maxLength: (value: unknown, max: number, message?: string): string | null => {
|
|
93
|
-
if (typeof value !== 'string') return null
|
|
94
|
-
if (value.length > max) {
|
|
95
|
-
return message || `Must be at most ${max} characters`
|
|
96
|
-
}
|
|
97
|
-
return null
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
min: (value: unknown, min: number, message?: string): string | null => {
|
|
101
|
-
if (typeof value !== 'number') return null
|
|
102
|
-
if (value < min) {
|
|
103
|
-
return message || `Must be at least ${min}`
|
|
104
|
-
}
|
|
105
|
-
return null
|
|
106
|
-
},
|
|
107
|
-
|
|
108
|
-
max: (value: unknown, max: number, message?: string): string | null => {
|
|
109
|
-
if (typeof value !== 'number') return null
|
|
110
|
-
if (value > max) {
|
|
111
|
-
return message || `Must be at most ${max}`
|
|
112
|
-
}
|
|
113
|
-
return null
|
|
114
|
-
},
|
|
115
|
-
|
|
116
|
-
pattern: (value: unknown, pattern: RegExp, message?: string): string | null => {
|
|
117
|
-
if (typeof value !== 'string') return null
|
|
118
|
-
if (!pattern.test(value)) {
|
|
119
|
-
return message || 'Invalid format'
|
|
120
|
-
}
|
|
121
|
-
return null
|
|
122
|
-
},
|
|
123
|
-
|
|
124
|
-
email: (value: unknown, message = 'Invalid email address'): string | null => {
|
|
125
|
-
if (typeof value !== 'string' || !value) return null
|
|
126
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
127
|
-
if (!emailRegex.test(value)) {
|
|
128
|
-
return message
|
|
129
|
-
}
|
|
130
|
-
return null
|
|
131
|
-
},
|
|
132
|
-
}
|
|
133
|
-
|
|
134
55
|
/**
|
|
135
56
|
* Form state management composable with validation.
|
|
136
57
|
*
|
|
@@ -205,112 +126,9 @@ export function useForm<T extends Record<string, unknown>>(
|
|
|
205
126
|
function validateField(field: string): boolean {
|
|
206
127
|
const value = data[field as keyof T]
|
|
207
128
|
const fieldRules = rules[field as keyof T]
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return true
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Check required
|
|
215
|
-
if (fieldRules.required) {
|
|
216
|
-
const message = typeof fieldRules.required === 'string' ? fieldRules.required : undefined
|
|
217
|
-
const error = validators.required(value, message)
|
|
218
|
-
if (error) {
|
|
219
|
-
errors[field] = error
|
|
220
|
-
return false
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// Skip other validations if empty and not required
|
|
225
|
-
if (value === null || value === undefined || value === '') {
|
|
226
|
-
errors[field] = null
|
|
227
|
-
return true
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Check minLength
|
|
231
|
-
if (fieldRules.minLength !== undefined) {
|
|
232
|
-
const config = typeof fieldRules.minLength === 'number'
|
|
233
|
-
? { value: fieldRules.minLength, message: undefined }
|
|
234
|
-
: fieldRules.minLength
|
|
235
|
-
const error = validators.minLength(value, config.value, config.message)
|
|
236
|
-
if (error) {
|
|
237
|
-
errors[field] = error
|
|
238
|
-
return false
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Check maxLength
|
|
243
|
-
if (fieldRules.maxLength !== undefined) {
|
|
244
|
-
const config = typeof fieldRules.maxLength === 'number'
|
|
245
|
-
? { value: fieldRules.maxLength, message: undefined }
|
|
246
|
-
: fieldRules.maxLength
|
|
247
|
-
const error = validators.maxLength(value, config.value, config.message)
|
|
248
|
-
if (error) {
|
|
249
|
-
errors[field] = error
|
|
250
|
-
return false
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Check min
|
|
255
|
-
if (fieldRules.min !== undefined) {
|
|
256
|
-
const config = typeof fieldRules.min === 'number'
|
|
257
|
-
? { value: fieldRules.min, message: undefined }
|
|
258
|
-
: fieldRules.min
|
|
259
|
-
const error = validators.min(value, config.value, config.message)
|
|
260
|
-
if (error) {
|
|
261
|
-
errors[field] = error
|
|
262
|
-
return false
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Check max
|
|
267
|
-
if (fieldRules.max !== undefined) {
|
|
268
|
-
const config = typeof fieldRules.max === 'number'
|
|
269
|
-
? { value: fieldRules.max, message: undefined }
|
|
270
|
-
: fieldRules.max
|
|
271
|
-
const error = validators.max(value, config.value, config.message)
|
|
272
|
-
if (error) {
|
|
273
|
-
errors[field] = error
|
|
274
|
-
return false
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// Check pattern
|
|
279
|
-
if (fieldRules.pattern !== undefined) {
|
|
280
|
-
const config = fieldRules.pattern instanceof RegExp
|
|
281
|
-
? { value: fieldRules.pattern, message: undefined }
|
|
282
|
-
: fieldRules.pattern
|
|
283
|
-
const error = validators.pattern(value, config.value, config.message)
|
|
284
|
-
if (error) {
|
|
285
|
-
errors[field] = error
|
|
286
|
-
return false
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// Check email
|
|
291
|
-
if (fieldRules.email) {
|
|
292
|
-
const message = typeof fieldRules.email === 'string' ? fieldRules.email : undefined
|
|
293
|
-
const error = validators.email(value, message)
|
|
294
|
-
if (error) {
|
|
295
|
-
errors[field] = error
|
|
296
|
-
return false
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// Check custom validators
|
|
301
|
-
if (fieldRules.custom) {
|
|
302
|
-
const customRules = Array.isArray(fieldRules.custom) ? fieldRules.custom : [fieldRules.custom]
|
|
303
|
-
for (const rule of customRules) {
|
|
304
|
-
const error = rule(value, data as Record<string, unknown>)
|
|
305
|
-
if (error) {
|
|
306
|
-
errors[field] = error
|
|
307
|
-
return false
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
errors[field] = null
|
|
313
|
-
return true
|
|
129
|
+
const error = validateFieldValue(value, fieldRules, data as Record<string, unknown>)
|
|
130
|
+
errors[field] = error
|
|
131
|
+
return error === null
|
|
314
132
|
}
|
|
315
133
|
|
|
316
134
|
// Validate all fields
|
|
@@ -1,167 +1,25 @@
|
|
|
1
1
|
import { reactive, ref, computed, shallowRef, watch } from 'vue'
|
|
2
2
|
import { useForm, type FieldRules, type UseFormReturn } from './useForm'
|
|
3
|
-
import { getFieldRegistryEntry
|
|
3
|
+
import { getFieldRegistryEntry } from './formBuilderRegistry'
|
|
4
|
+
import {
|
|
5
|
+
buildInitialValues,
|
|
6
|
+
buildRules,
|
|
7
|
+
collectSections,
|
|
8
|
+
evaluateCondition,
|
|
9
|
+
flattenFields,
|
|
10
|
+
replaceArray,
|
|
11
|
+
replaceRecord,
|
|
12
|
+
} from './formBuilderSchema'
|
|
4
13
|
import type {
|
|
5
14
|
FormSchema,
|
|
6
15
|
FormFieldSchema,
|
|
7
16
|
FormSectionSchema,
|
|
8
|
-
FieldCondition,
|
|
9
|
-
FieldValidation,
|
|
10
17
|
FormOptionInput,
|
|
11
18
|
FormEnhancements,
|
|
12
19
|
UseFormBuilderReturn,
|
|
13
20
|
} from '../types/form-builder'
|
|
14
21
|
|
|
15
|
-
|
|
16
|
-
// Condition evaluator
|
|
17
|
-
// ---------------------------------------------------------------------------
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Evaluate a JSON-serializable field condition against the current form data.
|
|
21
|
-
*
|
|
22
|
-
* Supports logical operators (`and`, `or`, `not`) and comparison operators
|
|
23
|
-
* (`eq`, `neq`, `gt`, `lt`, `gte`, `lte`, `in`, `notIn`, `truthy`, `falsy`,
|
|
24
|
-
* `contains`). Returns `true` if the condition passes.
|
|
25
|
-
*/
|
|
26
|
-
export function evaluateCondition(
|
|
27
|
-
condition: FieldCondition,
|
|
28
|
-
data: Record<string, unknown>,
|
|
29
|
-
): boolean {
|
|
30
|
-
if ('and' in condition) {
|
|
31
|
-
return condition.and.every((c) => evaluateCondition(c, data))
|
|
32
|
-
}
|
|
33
|
-
if ('or' in condition) {
|
|
34
|
-
return condition.or.some((c) => evaluateCondition(c, data))
|
|
35
|
-
}
|
|
36
|
-
if ('not' in condition) {
|
|
37
|
-
return !evaluateCondition(condition.not, data)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const value = data[condition.field]
|
|
41
|
-
|
|
42
|
-
if ('eq' in condition) return value === condition.eq
|
|
43
|
-
if ('neq' in condition) return value !== condition.neq
|
|
44
|
-
if ('gt' in condition) return typeof value === 'number' && value > condition.gt
|
|
45
|
-
if ('lt' in condition) return typeof value === 'number' && value < condition.lt
|
|
46
|
-
if ('gte' in condition) return typeof value === 'number' && value >= condition.gte
|
|
47
|
-
if ('lte' in condition) return typeof value === 'number' && value <= condition.lte
|
|
48
|
-
if ('in' in condition) return condition.in.includes(value)
|
|
49
|
-
if ('notIn' in condition) return !condition.notIn.includes(value)
|
|
50
|
-
if ('truthy' in condition) return !!value
|
|
51
|
-
if ('falsy' in condition) return !value
|
|
52
|
-
if ('contains' in condition) {
|
|
53
|
-
if (typeof value === 'string') return value.includes(condition.contains)
|
|
54
|
-
if (Array.isArray(value)) return value.includes(condition.contains)
|
|
55
|
-
return false
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return true
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// ---------------------------------------------------------------------------
|
|
62
|
-
// Schema helpers
|
|
63
|
-
// ---------------------------------------------------------------------------
|
|
64
|
-
|
|
65
|
-
/** Return all sections across steps (wizard) or directly from a flat schema. */
|
|
66
|
-
function collectSections(schema: FormSchema): FormSectionSchema[] {
|
|
67
|
-
return schema.steps ? schema.steps.flatMap((step) => step.sections) : schema.sections
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** Return all field schemas in schema order, flattening sections and steps. */
|
|
71
|
-
function flattenFields(schema: FormSchema): FormFieldSchema[] {
|
|
72
|
-
return collectSections(schema).flatMap((section) => section.fields)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** Convert a JSON-safe `FieldValidation` descriptor to a runtime `FieldRules` object. */
|
|
76
|
-
function convertValidation(v: FieldValidation): FieldRules {
|
|
77
|
-
const rules: FieldRules = {}
|
|
78
|
-
|
|
79
|
-
if (v.required !== undefined) rules.required = v.required
|
|
80
|
-
if (v.minLength !== undefined) rules.minLength = v.minLength
|
|
81
|
-
if (v.maxLength !== undefined) rules.maxLength = v.maxLength
|
|
82
|
-
if (v.min !== undefined) rules.min = v.min
|
|
83
|
-
if (v.max !== undefined) rules.max = v.max
|
|
84
|
-
if (v.email !== undefined) rules.email = v.email
|
|
85
|
-
|
|
86
|
-
if (v.pattern !== undefined) {
|
|
87
|
-
rules.pattern =
|
|
88
|
-
typeof v.pattern === 'string'
|
|
89
|
-
? new RegExp(v.pattern)
|
|
90
|
-
: { value: new RegExp(v.pattern.value), message: v.pattern.message }
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return rules
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function buildInitialValues<T extends Record<string, unknown>>(
|
|
97
|
-
fields: readonly FormFieldSchema[],
|
|
98
|
-
initialData?: Partial<T>,
|
|
99
|
-
): Record<string, unknown> {
|
|
100
|
-
const initialValues = {} as Record<string, unknown>
|
|
101
|
-
|
|
102
|
-
for (const field of fields) {
|
|
103
|
-
const key = field.name
|
|
104
|
-
if (initialData && hasOwnKey(initialData, key)) {
|
|
105
|
-
initialValues[key] = (initialData as Record<string, unknown>)[key]
|
|
106
|
-
} else if (field.defaultValue !== undefined) {
|
|
107
|
-
initialValues[key] = field.defaultValue
|
|
108
|
-
} else {
|
|
109
|
-
initialValues[key] = getTypeDefault(field.type)
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return initialValues
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function buildRules<T extends Record<string, unknown>>(
|
|
117
|
-
fields: readonly FormFieldSchema[],
|
|
118
|
-
enhancements?: FormEnhancements<T>,
|
|
119
|
-
): Partial<Record<string, FieldRules>> {
|
|
120
|
-
const rules: Partial<Record<string, FieldRules>> = {}
|
|
121
|
-
|
|
122
|
-
for (const field of fields) {
|
|
123
|
-
const base: FieldRules = field.validation ? convertValidation(field.validation) : {}
|
|
124
|
-
const enhancement = enhancements?.fields?.[field.name as keyof T]
|
|
125
|
-
|
|
126
|
-
const customValidators: Array<(
|
|
127
|
-
value: unknown,
|
|
128
|
-
formData: Record<string, unknown>,
|
|
129
|
-
) => string | undefined | null> = []
|
|
130
|
-
|
|
131
|
-
if (enhancement?.validate) {
|
|
132
|
-
const fn = enhancement.validate
|
|
133
|
-
customValidators.push((value, formData) => fn(value, formData as T))
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (customValidators.length > 0) {
|
|
137
|
-
base.custom = customValidators
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (Object.keys(base).length > 0) {
|
|
141
|
-
rules[field.name] = base
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return rules
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function replaceArray<T>(target: T[], values: readonly T[]): void {
|
|
149
|
-
target.splice(0, target.length, ...values)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function replaceRecord<TValue>(
|
|
153
|
-
target: Partial<Record<string, TValue>>,
|
|
154
|
-
source: Partial<Record<string, TValue>>,
|
|
155
|
-
): void {
|
|
156
|
-
for (const key of Object.keys(target)) {
|
|
157
|
-
delete target[key]
|
|
158
|
-
}
|
|
159
|
-
Object.assign(target, source)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function hasOwnKey(source: object, key: string): boolean {
|
|
163
|
-
return Object.prototype.hasOwnProperty.call(source, key)
|
|
164
|
-
}
|
|
22
|
+
export { evaluateCondition } from './formBuilderSchema'
|
|
165
23
|
|
|
166
24
|
// ---------------------------------------------------------------------------
|
|
167
25
|
// useFormBuilder
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation rule function type.
|
|
3
|
+
* Returns error message string if invalid, undefined/null if valid.
|
|
4
|
+
*/
|
|
5
|
+
export type ValidationRule<T = unknown> = (value: T, formData: Record<string, unknown>) => string | undefined | null
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Field validation rules configuration.
|
|
9
|
+
*/
|
|
10
|
+
export interface FieldRules<T = unknown> {
|
|
11
|
+
required?: boolean | string
|
|
12
|
+
minLength?: number | { value: number; message: string }
|
|
13
|
+
maxLength?: number | { value: number; message: string }
|
|
14
|
+
min?: number | { value: number; message: string }
|
|
15
|
+
max?: number | { value: number; message: string }
|
|
16
|
+
pattern?: RegExp | { value: RegExp; message: string }
|
|
17
|
+
email?: boolean | string
|
|
18
|
+
custom?: ValidationRule<T> | ValidationRule<T>[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const validators = {
|
|
22
|
+
required: (value: unknown, message = 'This field is required'): string | null => {
|
|
23
|
+
if (value === null || value === undefined || value === '') {
|
|
24
|
+
return message
|
|
25
|
+
}
|
|
26
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
27
|
+
return message
|
|
28
|
+
}
|
|
29
|
+
return null
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
minLength: (value: unknown, min: number, message?: string): string | null => {
|
|
33
|
+
if (typeof value !== 'string') return null
|
|
34
|
+
if (value.length < min) {
|
|
35
|
+
return message || `Must be at least ${min} characters`
|
|
36
|
+
}
|
|
37
|
+
return null
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
maxLength: (value: unknown, max: number, message?: string): string | null => {
|
|
41
|
+
if (typeof value !== 'string') return null
|
|
42
|
+
if (value.length > max) {
|
|
43
|
+
return message || `Must be at most ${max} characters`
|
|
44
|
+
}
|
|
45
|
+
return null
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
min: (value: unknown, min: number, message?: string): string | null => {
|
|
49
|
+
if (typeof value !== 'number') return null
|
|
50
|
+
if (value < min) {
|
|
51
|
+
return message || `Must be at least ${min}`
|
|
52
|
+
}
|
|
53
|
+
return null
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
max: (value: unknown, max: number, message?: string): string | null => {
|
|
57
|
+
if (typeof value !== 'number') return null
|
|
58
|
+
if (value > max) {
|
|
59
|
+
return message || `Must be at most ${max}`
|
|
60
|
+
}
|
|
61
|
+
return null
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
pattern: (value: unknown, pattern: RegExp, message?: string): string | null => {
|
|
65
|
+
if (typeof value !== 'string') return null
|
|
66
|
+
if (!pattern.test(value)) {
|
|
67
|
+
return message || 'Invalid format'
|
|
68
|
+
}
|
|
69
|
+
return null
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
email: (value: unknown, message = 'Invalid email address'): string | null => {
|
|
73
|
+
if (typeof value !== 'string' || !value) return null
|
|
74
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
75
|
+
if (!emailRegex.test(value)) {
|
|
76
|
+
return message
|
|
77
|
+
}
|
|
78
|
+
return null
|
|
79
|
+
},
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function validateFieldValue(
|
|
83
|
+
value: unknown,
|
|
84
|
+
fieldRules: FieldRules | undefined,
|
|
85
|
+
formData: Record<string, unknown>,
|
|
86
|
+
): string | null {
|
|
87
|
+
if (!fieldRules) return null
|
|
88
|
+
|
|
89
|
+
if (fieldRules.required) {
|
|
90
|
+
const message = typeof fieldRules.required === 'string' ? fieldRules.required : undefined
|
|
91
|
+
const error = validators.required(value, message)
|
|
92
|
+
if (error) return error
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (value === null || value === undefined || value === '') {
|
|
96
|
+
return null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (fieldRules.minLength !== undefined) {
|
|
100
|
+
const config = typeof fieldRules.minLength === 'number'
|
|
101
|
+
? { value: fieldRules.minLength, message: undefined }
|
|
102
|
+
: fieldRules.minLength
|
|
103
|
+
const error = validators.minLength(value, config.value, config.message)
|
|
104
|
+
if (error) return error
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (fieldRules.maxLength !== undefined) {
|
|
108
|
+
const config = typeof fieldRules.maxLength === 'number'
|
|
109
|
+
? { value: fieldRules.maxLength, message: undefined }
|
|
110
|
+
: fieldRules.maxLength
|
|
111
|
+
const error = validators.maxLength(value, config.value, config.message)
|
|
112
|
+
if (error) return error
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (fieldRules.min !== undefined) {
|
|
116
|
+
const config = typeof fieldRules.min === 'number'
|
|
117
|
+
? { value: fieldRules.min, message: undefined }
|
|
118
|
+
: fieldRules.min
|
|
119
|
+
const error = validators.min(value, config.value, config.message)
|
|
120
|
+
if (error) return error
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (fieldRules.max !== undefined) {
|
|
124
|
+
const config = typeof fieldRules.max === 'number'
|
|
125
|
+
? { value: fieldRules.max, message: undefined }
|
|
126
|
+
: fieldRules.max
|
|
127
|
+
const error = validators.max(value, config.value, config.message)
|
|
128
|
+
if (error) return error
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (fieldRules.pattern !== undefined) {
|
|
132
|
+
const config = fieldRules.pattern instanceof RegExp
|
|
133
|
+
? { value: fieldRules.pattern, message: undefined }
|
|
134
|
+
: fieldRules.pattern
|
|
135
|
+
const error = validators.pattern(value, config.value, config.message)
|
|
136
|
+
if (error) return error
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (fieldRules.email) {
|
|
140
|
+
const message = typeof fieldRules.email === 'string' ? fieldRules.email : undefined
|
|
141
|
+
const error = validators.email(value, message)
|
|
142
|
+
if (error) return error
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (fieldRules.custom) {
|
|
146
|
+
const customRules = Array.isArray(fieldRules.custom) ? fieldRules.custom : [fieldRules.custom]
|
|
147
|
+
for (const rule of customRules) {
|
|
148
|
+
const error = rule(value, formData)
|
|
149
|
+
if (error) return error
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return null
|
|
154
|
+
}
|