@flowgram-vue/node 0.2.0
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/LICENSE +22 -0
- package/dist/index.cjs +0 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +0 -0
- package/dist/index.js.map +1 -0
- package/package.json +70 -0
- package/src/NodeFormRender.vue +35 -0
- package/src/env.d.ts +10 -0
- package/src/form-model-v2.ts +575 -0
- package/src/form-plugin.ts +129 -0
- package/src/form-render.ts +13 -0
- package/src/get-node-form.ts +109 -0
- package/src/helpers.ts +29 -0
- package/src/hooks.ts +98 -0
- package/src/index.ts +11 -0
- package/src/types.ts +153 -0
- package/src/utils.ts +86 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { h, type VNode } from 'vue';
|
|
7
|
+
|
|
8
|
+
import { Disposable, Event } from '@flowgram-vue/utils';
|
|
9
|
+
import { FlowNodeFormData, NodeRender, OnFormValuesChangePayload } from '@flowgram-vue/form-core';
|
|
10
|
+
import { FieldName, FieldValue, FormState } from '@flowgram-vue/form';
|
|
11
|
+
import { FlowNodeEntity } from '@flowgram-vue/document';
|
|
12
|
+
|
|
13
|
+
import { onFormValueChangeInPayload } from './types';
|
|
14
|
+
import { FormModelV2 } from './form-model-v2';
|
|
15
|
+
|
|
16
|
+
export interface NodeFormProps<TValues> {
|
|
17
|
+
/**
|
|
18
|
+
* The initialValues of the form.
|
|
19
|
+
*/
|
|
20
|
+
initialValues: TValues;
|
|
21
|
+
/**
|
|
22
|
+
* Form values. Returns a deep copy of the data in the store.
|
|
23
|
+
*/
|
|
24
|
+
values: TValues;
|
|
25
|
+
/**
|
|
26
|
+
* Form state
|
|
27
|
+
*/
|
|
28
|
+
state: FormState;
|
|
29
|
+
/**
|
|
30
|
+
* Get value in certain path
|
|
31
|
+
* @param name path
|
|
32
|
+
*/
|
|
33
|
+
getValueIn<TValue = FieldValue>(name: FieldName): TValue;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Set value in certain path.
|
|
37
|
+
* It will trigger the re-rendering of the Field Component if a Field is related to this path
|
|
38
|
+
* @param name path
|
|
39
|
+
*/
|
|
40
|
+
setValueIn<TValue>(name: FieldName, value: TValue): void;
|
|
41
|
+
/**
|
|
42
|
+
* set form values
|
|
43
|
+
*/
|
|
44
|
+
updateFormValues(values: any): void;
|
|
45
|
+
/**
|
|
46
|
+
* Render form
|
|
47
|
+
*/
|
|
48
|
+
render: () => VNode;
|
|
49
|
+
/**
|
|
50
|
+
* Form value change event
|
|
51
|
+
*/
|
|
52
|
+
onFormValuesChange: Event<OnFormValuesChangePayload>;
|
|
53
|
+
/**
|
|
54
|
+
* Trigger form validate
|
|
55
|
+
*/
|
|
56
|
+
validate: () => Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Form validate event
|
|
59
|
+
*/
|
|
60
|
+
onValidate: Event<FormState>;
|
|
61
|
+
/**
|
|
62
|
+
* Form field value change event
|
|
63
|
+
*/
|
|
64
|
+
onFormValueChangeIn<TValue = FieldValue, TFormValue = FieldValue>(
|
|
65
|
+
name: FieldName,
|
|
66
|
+
callback: (payload: onFormValueChangeInPayload<TValue, TFormValue>) => void
|
|
67
|
+
): Disposable;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Use `node.form` instead
|
|
72
|
+
* @deprecated
|
|
73
|
+
* @param node
|
|
74
|
+
*/
|
|
75
|
+
export function getNodeForm<TValues = FieldValue>(
|
|
76
|
+
node: FlowNodeEntity
|
|
77
|
+
): NodeFormProps<TValues> | undefined {
|
|
78
|
+
const formModel = node.getData<FlowNodeFormData>(FlowNodeFormData)?.getFormModel<FormModelV2>();
|
|
79
|
+
const nativeFormModel = formModel?.nativeFormModel;
|
|
80
|
+
|
|
81
|
+
if (!formModel || !nativeFormModel) return undefined;
|
|
82
|
+
|
|
83
|
+
const result: NodeFormProps<TValues> = {
|
|
84
|
+
initialValues: nativeFormModel.initialValues,
|
|
85
|
+
get values() {
|
|
86
|
+
return nativeFormModel.values;
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
state: nativeFormModel.state,
|
|
90
|
+
getValueIn: (name: FieldName) => nativeFormModel.getValueIn(name),
|
|
91
|
+
setValueIn: (name: FieldName, value: any) => nativeFormModel.setValueIn(name, value),
|
|
92
|
+
updateFormValues: (values: any) => {
|
|
93
|
+
formModel.updateFormValues(values);
|
|
94
|
+
},
|
|
95
|
+
render: () => h(NodeRender, { node }),
|
|
96
|
+
onFormValuesChange: formModel.onFormValuesChange.bind(formModel),
|
|
97
|
+
onFormValueChangeIn: formModel.onFormValueChangeIn.bind(formModel),
|
|
98
|
+
onValidate: formModel.nativeFormModel.onValidate,
|
|
99
|
+
validate: formModel.validate.bind(formModel),
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
Object.defineProperty(result, '_formModel', {
|
|
103
|
+
enumerable: false,
|
|
104
|
+
get() {
|
|
105
|
+
return formModel;
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
return result;
|
|
109
|
+
}
|
package/src/helpers.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FlowNodeFormData } from '@flowgram-vue/form-core';
|
|
7
|
+
import { FlowNodeEntity } from '@flowgram-vue/document';
|
|
8
|
+
|
|
9
|
+
import { DataEvent } from './types';
|
|
10
|
+
import { FormModelV2 } from './form-model-v2';
|
|
11
|
+
|
|
12
|
+
export function getFormModel(node: FlowNodeEntity) {
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
return node.getData<FlowNodeFormData>(FlowNodeFormData)?.formModel as FormModelV2;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isFormV2(node: FlowNodeEntity) {
|
|
18
|
+
return !!node.getNodeRegistry().formMeta?.render;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function createEffectOptions<T>(
|
|
22
|
+
event: DataEvent,
|
|
23
|
+
effect: T
|
|
24
|
+
): { effect: T; event: DataEvent } {
|
|
25
|
+
return {
|
|
26
|
+
event,
|
|
27
|
+
effect,
|
|
28
|
+
};
|
|
29
|
+
}
|
package/src/hooks.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { onBeforeUnmount } from 'vue';
|
|
7
|
+
|
|
8
|
+
import { useRefresh } from '@flowgram-vue/utils';
|
|
9
|
+
import { FlowNodeFormData } from '@flowgram-vue/form-core';
|
|
10
|
+
import { Errors, Warnings } from '@flowgram-vue/form';
|
|
11
|
+
import { FormState, useFormErrors, useFormState, useFormWarnings } from '@flowgram-vue/form';
|
|
12
|
+
import { FlowNodeEntity } from '@flowgram-vue/document';
|
|
13
|
+
|
|
14
|
+
import { FormModelV2 } from './form-model-v2';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Listen to Form's values and refresh the Vue component.
|
|
18
|
+
* By providing related node, you can use this hook outside the Form Component.
|
|
19
|
+
* @param node
|
|
20
|
+
*/
|
|
21
|
+
export function useWatchFormValues<T = any>(node: FlowNodeEntity): T | undefined {
|
|
22
|
+
const formModel = node.getData(FlowNodeFormData).getFormModel<FormModelV2>();
|
|
23
|
+
const refresh = useRefresh();
|
|
24
|
+
|
|
25
|
+
const disposable = formModel.nativeFormModel?.onFormValuesChange(() => {
|
|
26
|
+
refresh();
|
|
27
|
+
});
|
|
28
|
+
onBeforeUnmount(() => disposable?.dispose());
|
|
29
|
+
|
|
30
|
+
return formModel.getValues<T>();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Listen to Form's value in a certain path and refresh the Vue component.
|
|
35
|
+
* By providing related node, you can use this hook outside the Form Component.
|
|
36
|
+
* @param node
|
|
37
|
+
*/
|
|
38
|
+
export function useWatchFormValueIn<T = any>(node: FlowNodeEntity, name: string): T | undefined {
|
|
39
|
+
const formModel = node.getData(FlowNodeFormData).getFormModel<FormModelV2>();
|
|
40
|
+
const refresh = useRefresh();
|
|
41
|
+
|
|
42
|
+
const disposable = formModel.nativeFormModel?.onFormValuesChange(({ name: changedName }) => {
|
|
43
|
+
if (name === changedName) {
|
|
44
|
+
refresh();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
onBeforeUnmount(() => disposable?.dispose());
|
|
49
|
+
|
|
50
|
+
return formModel.getValueIn<T>(name);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Listen to FormModel's initialization and refresh Vue component.
|
|
55
|
+
* By providing related node, you can use this hook outside the Form Component.
|
|
56
|
+
* @param node
|
|
57
|
+
*/
|
|
58
|
+
export function useInitializedFormModel(node: FlowNodeEntity) {
|
|
59
|
+
const formModel = node.getData(FlowNodeFormData).getFormModel<FormModelV2>();
|
|
60
|
+
const refresh = useRefresh();
|
|
61
|
+
|
|
62
|
+
const disposable = formModel.onInitialized(() => {
|
|
63
|
+
refresh();
|
|
64
|
+
});
|
|
65
|
+
onBeforeUnmount(() => disposable.dispose());
|
|
66
|
+
|
|
67
|
+
return formModel;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get Form's state, Form State is a proxy, it will refresh the Vue component when the value you accessed changed
|
|
72
|
+
* By providing related node, you can use this hook outside the Form Component.
|
|
73
|
+
* @param node
|
|
74
|
+
*/
|
|
75
|
+
export function useWatchFormState(node: FlowNodeEntity): FormState | undefined {
|
|
76
|
+
const formModel = useInitializedFormModel(node);
|
|
77
|
+
return useFormState(formModel.formControl);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get Form's errors, Form errors is a proxy, it will refresh the Vue component when the value you accessed changed
|
|
82
|
+
* By providing related node, you can use this hook outside the Form Component.
|
|
83
|
+
* @param node
|
|
84
|
+
*/
|
|
85
|
+
export function useWatchFormErrors(node: FlowNodeEntity): Errors | undefined {
|
|
86
|
+
const formModel = useInitializedFormModel(node);
|
|
87
|
+
return useFormErrors(formModel.formControl);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Get Form's warnings, Form warnings is a proxy, it will refresh the Vue component when the value you accessed changed
|
|
92
|
+
* By providing related node, you can use this hook outside the Form Component.
|
|
93
|
+
* @param node
|
|
94
|
+
*/
|
|
95
|
+
export function useWatchFormWarnings(node: FlowNodeEntity): Warnings | undefined {
|
|
96
|
+
const formModel = useInitializedFormModel(node);
|
|
97
|
+
return useFormWarnings(formModel.formControl);
|
|
98
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export * from './types';
|
|
7
|
+
export * from './form-model-v2';
|
|
8
|
+
export { isFormV2, createEffectOptions } from './helpers';
|
|
9
|
+
export * from './hooks';
|
|
10
|
+
export * from './form-plugin';
|
|
11
|
+
export { type NodeFormProps, getNodeForm } from './get-node-form';
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { VNode } from 'vue';
|
|
7
|
+
|
|
8
|
+
import { FormModel, IFormMeta, NodeContext } from '@flowgram-vue/form-core';
|
|
9
|
+
import { FieldName, FieldValue } from '@flowgram-vue/form';
|
|
10
|
+
import {
|
|
11
|
+
FormRenderProps,
|
|
12
|
+
IForm,
|
|
13
|
+
Validate as FormValidate,
|
|
14
|
+
ValidateTrigger,
|
|
15
|
+
} from '@flowgram-vue/form';
|
|
16
|
+
|
|
17
|
+
import { FormPlugin } from './form-plugin';
|
|
18
|
+
import { FormModelV2 } from './form-model-v2';
|
|
19
|
+
|
|
20
|
+
export interface Node {}
|
|
21
|
+
|
|
22
|
+
export interface Flow {}
|
|
23
|
+
|
|
24
|
+
export type Validate<TFieldValue = any, TFormValues = any> = (props: {
|
|
25
|
+
value: TFieldValue;
|
|
26
|
+
formValues: TFormValues;
|
|
27
|
+
context: NodeContext;
|
|
28
|
+
name: FieldName;
|
|
29
|
+
}) => ReturnType<FormValidate<TFieldValue, TFormValues>>;
|
|
30
|
+
|
|
31
|
+
export enum DataEvent {
|
|
32
|
+
/* When value change */
|
|
33
|
+
onValueChange = 'onValueChange',
|
|
34
|
+
/**
|
|
35
|
+
* When value Init,it triggers when
|
|
36
|
+
* - defaultValue is configured in formMeta, it will trigger when form is initializing.
|
|
37
|
+
* - defaultValue is configured in Field, it will trigger when this Field is initializing if no initial value is set to this field.
|
|
38
|
+
*/
|
|
39
|
+
onValueInit = 'onValueInit',
|
|
40
|
+
/**
|
|
41
|
+
* When Value Init or change
|
|
42
|
+
*/
|
|
43
|
+
onValueInitOrChange = 'onValueInitOrChange',
|
|
44
|
+
/* It will trigger when ArrayField.append is called. It relies on ArrayField's rendering. If ArrayField is possibly not rendered in your case, please avoid using this event */
|
|
45
|
+
onArrayAppend = 'onArrayAppend',
|
|
46
|
+
/* It will trigger when ArrayField.delete is called. It relies on ArrayField's rendering. If ArrayField is possibly not rendered in your case, please avoid using this event */
|
|
47
|
+
onArrayDelete = 'onArrayDelete',
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type EffectReturn = () => void;
|
|
51
|
+
|
|
52
|
+
export interface EffectFuncProps<TFieldValue = any, TFormValues = any> {
|
|
53
|
+
name: FieldName;
|
|
54
|
+
value: TFieldValue;
|
|
55
|
+
prevValue?: TFieldValue;
|
|
56
|
+
formValues: TFormValues;
|
|
57
|
+
form: IForm;
|
|
58
|
+
context: NodeContext;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type Effect<TFieldValue = any, TFormValues = any> = (
|
|
62
|
+
props: EffectFuncProps<TFieldValue, TFormValues>
|
|
63
|
+
) => void | EffectReturn;
|
|
64
|
+
|
|
65
|
+
export type ArrayAppendEffect<TFieldValue = any, TFormValues = any> = (props: {
|
|
66
|
+
index: number;
|
|
67
|
+
value: TFieldValue;
|
|
68
|
+
arrayValues: Array<TFieldValue>;
|
|
69
|
+
formValues: TFormValues;
|
|
70
|
+
form: IForm;
|
|
71
|
+
context: NodeContext;
|
|
72
|
+
}) => void | EffectReturn;
|
|
73
|
+
|
|
74
|
+
export type ArrayDeleteEffect<TFieldValue = any, TFormValues = any> = (props: {
|
|
75
|
+
index: number;
|
|
76
|
+
arrayValue: Array<TFieldValue>;
|
|
77
|
+
formValues: TFormValues;
|
|
78
|
+
form: IForm;
|
|
79
|
+
context: NodeContext;
|
|
80
|
+
}) => void | EffectReturn;
|
|
81
|
+
|
|
82
|
+
export type EffectOptions =
|
|
83
|
+
| { effect: Effect; event: DataEvent }
|
|
84
|
+
| { effect: ArrayAppendEffect; event: DataEvent }
|
|
85
|
+
| { effect: ArrayDeleteEffect; event: DataEvent };
|
|
86
|
+
|
|
87
|
+
export interface FormMeta<TValues = any> {
|
|
88
|
+
/**
|
|
89
|
+
* The render method of the node form content. <Form /> is already integrated, so you don't need to wrap your components with <Form />
|
|
90
|
+
* @param props
|
|
91
|
+
*/
|
|
92
|
+
render: (props: FormRenderProps<any>) => VNode;
|
|
93
|
+
/**
|
|
94
|
+
* When to trigger the validation.
|
|
95
|
+
*/
|
|
96
|
+
validateTrigger?: ValidateTrigger;
|
|
97
|
+
/**
|
|
98
|
+
* Form data's validation rules. It's a key value map, where the key is a pattern of data's path (or field name), the value is a validate function.
|
|
99
|
+
*/
|
|
100
|
+
validate?:
|
|
101
|
+
| Record<FieldName, Validate>
|
|
102
|
+
| ((values: TValues, ctx: NodeContext) => Record<FieldName, Validate>);
|
|
103
|
+
/**
|
|
104
|
+
* Form data's effects. It's a key value map, where the key is a pattern of data's path (or field name), the value is an array of effect configuration.
|
|
105
|
+
*/
|
|
106
|
+
effect?: Record<FieldName, EffectOptions[]>;
|
|
107
|
+
/**
|
|
108
|
+
* Form data's complete default value. it will not be sent to formatOnInit, but used directly as form's value when needed.
|
|
109
|
+
*/
|
|
110
|
+
defaultValues?: TValues | ((context: NodeContext) => TValues);
|
|
111
|
+
/**
|
|
112
|
+
* This function is to format the value when initiate the form, the returned value will be used as the initial value of the form.
|
|
113
|
+
* @param value value input to node as initialValue.
|
|
114
|
+
* @param context
|
|
115
|
+
*/
|
|
116
|
+
formatOnInit?: (value: any, context: NodeContext) => any;
|
|
117
|
+
/**
|
|
118
|
+
* This function is to format the value when FormModel.toJSON is called, the returned value will be used as the final value to be saved .
|
|
119
|
+
* @param value value sent by form before format.
|
|
120
|
+
* @param context
|
|
121
|
+
*/
|
|
122
|
+
formatOnSubmit?: (value: any, context: NodeContext) => any;
|
|
123
|
+
/**
|
|
124
|
+
* Form's plugins
|
|
125
|
+
*/
|
|
126
|
+
plugins?: FormPlugin[];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function isFormModelV2(fm: FormModel | FormModelV2): fm is FormModelV2 {
|
|
130
|
+
return 'onFormValuesChange' in fm;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function isFormMetaV2(formMeta: IFormMeta | FormMeta) {
|
|
134
|
+
return 'render' in formMeta;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export type FormPluginCtx = {
|
|
138
|
+
formModel: FormModelV2;
|
|
139
|
+
} & NodeContext;
|
|
140
|
+
|
|
141
|
+
export type FormPluginSetupMetaCtx = {
|
|
142
|
+
mergeEffect: (effect: Record<string, EffectOptions[]>) => void;
|
|
143
|
+
mergeValidate: (validate: Record<FieldName, Validate>) => void;
|
|
144
|
+
addFormatOnInit: (formatOnInit: FormMeta['formatOnInit']) => void;
|
|
145
|
+
addFormatOnSubmit: (formatOnSubmit: FormMeta['formatOnSubmit']) => void;
|
|
146
|
+
} & NodeContext;
|
|
147
|
+
|
|
148
|
+
export interface onFormValueChangeInPayload<TValue = FieldValue, TFormValues = FieldValue> {
|
|
149
|
+
value: TValue;
|
|
150
|
+
prevValue: TValue;
|
|
151
|
+
formValues: TFormValues;
|
|
152
|
+
prevFormValues: TFormValues;
|
|
153
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { find, mergeWith } from 'lodash-es';
|
|
7
|
+
import { FormFeedback, FormPathService } from '@flowgram-vue/form-core';
|
|
8
|
+
import type { FieldError, FieldWarning, FormValidateReturn } from '@flowgram-vue/form';
|
|
9
|
+
import { type FieldModel, FieldName } from '@flowgram-vue/form';
|
|
10
|
+
|
|
11
|
+
import { DataEvent, EffectOptions, EffectReturn } from './types';
|
|
12
|
+
|
|
13
|
+
export function findMatchedInMap<T = any>(
|
|
14
|
+
field: FieldModel<any>,
|
|
15
|
+
validateMap: Record<FieldName, T> | undefined
|
|
16
|
+
): T | undefined {
|
|
17
|
+
if (!validateMap) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (validateMap[field.name]) {
|
|
21
|
+
return validateMap[field.name];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const found = find(Object.keys(validateMap), (key) => {
|
|
25
|
+
if (key.startsWith('regex:')) {
|
|
26
|
+
const regex = RegExp(key.split(':')[1]);
|
|
27
|
+
return regex.test(field.name);
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (found) {
|
|
33
|
+
return validateMap[found];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function formFeedbacksToNodeCoreFormFeedbacks(
|
|
38
|
+
formFeedbacks: FormValidateReturn
|
|
39
|
+
): FormFeedback[] {
|
|
40
|
+
return formFeedbacks.map(
|
|
41
|
+
(f: FieldError | FieldWarning) =>
|
|
42
|
+
({
|
|
43
|
+
feedbackStatus: f.level,
|
|
44
|
+
feedbackText: f.message,
|
|
45
|
+
path: f.name,
|
|
46
|
+
} as FormFeedback)
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function convertGlobPath(path: string) {
|
|
51
|
+
if (path.startsWith('/')) {
|
|
52
|
+
const parts = FormPathService.normalize(path).slice(1).split('/');
|
|
53
|
+
return parts.join('.');
|
|
54
|
+
}
|
|
55
|
+
return path;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function mergeEffectMap(
|
|
59
|
+
origin: Record<string, EffectOptions[]>,
|
|
60
|
+
source: Record<string, EffectOptions[]>
|
|
61
|
+
) {
|
|
62
|
+
return mergeWith(origin, source, function (objValue: EffectOptions[], srcValue: EffectOptions[]) {
|
|
63
|
+
return (objValue || []).concat(srcValue);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function mergeEffectReturn(origin?: EffectReturn, source?: EffectReturn): EffectReturn {
|
|
68
|
+
return () => {
|
|
69
|
+
origin?.();
|
|
70
|
+
source?.();
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function runAndDeleteEffectReturn(
|
|
75
|
+
effectReturnMap: Map<DataEvent, Record<string, EffectReturn>>,
|
|
76
|
+
name: string,
|
|
77
|
+
events: DataEvent[]
|
|
78
|
+
) {
|
|
79
|
+
events.forEach((event) => {
|
|
80
|
+
const eventMap = effectReturnMap.get(event);
|
|
81
|
+
if (eventMap?.[name]) {
|
|
82
|
+
eventMap[name]();
|
|
83
|
+
delete eventMap[name];
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|