@gravity-ui/dynamic-forms 3.1.0 → 3.3.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.
Files changed (57) hide show
  1. package/build/cjs/lib/core/components/Form/Controller/Controller.js +120 -0
  2. package/build/cjs/lib/core/components/Form/Controller/index.js +4 -0
  3. package/build/cjs/lib/core/components/Form/Controller/types.js +2 -0
  4. package/build/cjs/lib/core/components/Form/Controller/utils.js +305 -0
  5. package/build/cjs/lib/core/components/Form/DynamicField.js +6 -4
  6. package/build/cjs/lib/core/components/Form/constants.js +2 -1
  7. package/build/cjs/lib/core/components/Form/hooks/index.js +3 -4
  8. package/build/cjs/lib/core/components/Form/hooks/useMutateDFState.js +6 -0
  9. package/build/cjs/lib/core/components/Form/hooks/useMutators.js +43 -0
  10. package/build/cjs/lib/core/components/Form/hooks/useStoreValue.js +6 -0
  11. package/build/cjs/lib/core/components/Form/index.js +4 -0
  12. package/build/cjs/lib/core/components/Form/types/index.js +1 -0
  13. package/build/cjs/lib/core/components/Form/types/mutators.js +2 -0
  14. package/build/esm/lib/core/components/Form/Controller/Controller.d.ts +10 -0
  15. package/build/esm/lib/core/components/Form/Controller/Controller.js +115 -0
  16. package/build/esm/lib/core/components/Form/Controller/index.d.ts +1 -0
  17. package/build/esm/lib/core/components/Form/Controller/index.js +1 -0
  18. package/build/esm/lib/core/components/Form/Controller/types.d.ts +98 -0
  19. package/build/esm/lib/core/components/Form/Controller/types.js +1 -0
  20. package/build/esm/lib/core/components/Form/Controller/utils.d.ts +26 -0
  21. package/build/esm/lib/core/components/Form/Controller/utils.js +291 -0
  22. package/build/esm/lib/core/components/Form/DynamicField.d.ts +2 -2
  23. package/build/esm/lib/core/components/Form/DynamicField.js +7 -5
  24. package/build/esm/lib/core/components/Form/constants.d.ts +1 -0
  25. package/build/esm/lib/core/components/Form/constants.js +1 -0
  26. package/build/esm/lib/core/components/Form/hooks/index.d.ts +3 -4
  27. package/build/esm/lib/core/components/Form/hooks/index.js +3 -4
  28. package/build/esm/lib/core/components/Form/hooks/useMutateDFState.d.ts +1 -0
  29. package/build/esm/lib/core/components/Form/hooks/useMutateDFState.js +2 -0
  30. package/build/esm/lib/core/components/Form/hooks/useMutators.d.ts +5 -0
  31. package/build/esm/lib/core/components/Form/hooks/useMutators.js +38 -0
  32. package/build/esm/lib/core/components/Form/hooks/useStoreValue.d.ts +1 -0
  33. package/build/esm/lib/core/components/Form/hooks/useStoreValue.js +2 -0
  34. package/build/esm/lib/core/components/Form/index.d.ts +1 -0
  35. package/build/esm/lib/core/components/Form/index.js +1 -0
  36. package/build/esm/lib/core/components/Form/types/context.d.ts +4 -2
  37. package/build/esm/lib/core/components/Form/types/index.d.ts +1 -0
  38. package/build/esm/lib/core/components/Form/types/index.js +1 -0
  39. package/build/esm/lib/core/components/Form/types/mirror.d.ts +3 -5
  40. package/build/esm/lib/core/components/Form/types/mutators.d.ts +18 -0
  41. package/build/esm/lib/core/components/Form/types/mutators.js +1 -0
  42. package/package.json +1 -1
  43. package/build/cjs/lib/core/components/Form/Controller.js +0 -33
  44. package/build/cjs/lib/core/components/Form/hooks/useComponents.js +0 -40
  45. package/build/cjs/lib/core/components/Form/hooks/useField.js +0 -167
  46. package/build/cjs/lib/core/components/Form/hooks/useRender.js +0 -28
  47. package/build/cjs/lib/core/components/Form/hooks/useValidate.js +0 -32
  48. package/build/esm/lib/core/components/Form/Controller.d.ts +0 -10
  49. package/build/esm/lib/core/components/Form/Controller.js +0 -28
  50. package/build/esm/lib/core/components/Form/hooks/useComponents.d.ts +0 -6
  51. package/build/esm/lib/core/components/Form/hooks/useComponents.js +0 -35
  52. package/build/esm/lib/core/components/Form/hooks/useField.d.ts +0 -14
  53. package/build/esm/lib/core/components/Form/hooks/useField.js +0 -162
  54. package/build/esm/lib/core/components/Form/hooks/useRender.d.ts +0 -9
  55. package/build/esm/lib/core/components/Form/hooks/useRender.js +0 -23
  56. package/build/esm/lib/core/components/Form/hooks/useValidate.d.ts +0 -3
  57. package/build/esm/lib/core/components/Form/hooks/useValidate.js +0 -27
@@ -0,0 +1,115 @@
1
+ import React from 'react';
2
+ import _ from 'lodash';
3
+ import { useControllerMirror, useDynamicFormsCtx, useSearch } from '../hooks';
4
+ import { callUnmout, getFieldMethods, initializeStore, updateStore } from './utils';
5
+ export const Controller = ({ spec: _spec, name, value: valueFromParent, parentOnChange, parentOnUnmount, }) => {
6
+ const { config, tools, mutators, __mirror } = useDynamicFormsCtx();
7
+ const firstRenderRef = React.useRef(true);
8
+ const [store, setStore] = React.useState(initializeStore({
9
+ name,
10
+ spec: _spec,
11
+ mutators,
12
+ config,
13
+ valueFromParent,
14
+ tools,
15
+ parentOnChange,
16
+ parentOnUnmount,
17
+ }));
18
+ const { methods, fieldMethods } = React.useMemo(() => {
19
+ const fieldMethods = getFieldMethods();
20
+ const onChange = (valOrSetter, childErrors, errorMutator) => {
21
+ setStore((store) => fieldMethods.onChange(store, { valOrSetter, childErrors, errorMutator }));
22
+ };
23
+ const onDrop = () => {
24
+ setStore((store) => fieldMethods.onDrop(store, undefined));
25
+ };
26
+ const onBlur = () => {
27
+ setStore((store) => fieldMethods.onBlur(store, undefined));
28
+ };
29
+ const onFocus = () => {
30
+ setStore((store) => fieldMethods.onFocus(store, undefined));
31
+ };
32
+ const parentOnUnmount = (childName) => {
33
+ setStore((store) => fieldMethods.parentOnUnmount(store, childName));
34
+ };
35
+ const onItemAdd = (value) => {
36
+ setStore((store) => fieldMethods.onItemAdd(store, value));
37
+ };
38
+ const onItemRemove = (idx) => {
39
+ setStore((store) => fieldMethods.onItemRemove(store, idx));
40
+ };
41
+ return {
42
+ methods: {
43
+ onChange,
44
+ onDrop,
45
+ onBlur,
46
+ onFocus,
47
+ parentOnUnmount,
48
+ onItemAdd,
49
+ onItemRemove,
50
+ },
51
+ fieldMethods,
52
+ };
53
+ }, [setStore]);
54
+ const renderProps = React.useMemo(() => ({
55
+ input: {
56
+ name: store.name,
57
+ value: store.state.value,
58
+ onChange: methods.onChange,
59
+ onBlur: methods.onBlur,
60
+ onFocus: methods.onFocus,
61
+ onDrop: methods.onDrop,
62
+ parentOnUnmount: methods.parentOnUnmount,
63
+ },
64
+ arrayInput: {
65
+ name: store.name,
66
+ value: store.state.value,
67
+ onItemAdd: methods.onItemAdd,
68
+ onItemRemove: methods.onItemRemove,
69
+ onDrop: methods.onDrop,
70
+ },
71
+ meta: Object.assign(Object.assign({}, _.omit(store.state, 'value')), { submitFailed: store.tools.submitFailed }),
72
+ }), [methods, store.name, store.state, store.tools.submitFailed]);
73
+ const withSearch = useSearch(store.spec, store.state.value, store.name);
74
+ useControllerMirror(store.name, {
75
+ useField: renderProps,
76
+ useSearch: withSearch,
77
+ }, __mirror);
78
+ React.useEffect(() => {
79
+ var _a;
80
+ (_a = store.afterStoreUpdateCB) === null || _a === void 0 ? void 0 : _a.call(store);
81
+ }, [store.afterStoreUpdateCB]);
82
+ React.useEffect(() => {
83
+ if (!firstRenderRef.current) {
84
+ updateStore({
85
+ store,
86
+ setStore,
87
+ spec: _spec,
88
+ name,
89
+ parentOnChange,
90
+ parentOnUnmount,
91
+ mutators,
92
+ config,
93
+ tools,
94
+ methodOnChange: fieldMethods.onChange,
95
+ valueFromParent,
96
+ });
97
+ }
98
+ }, [
99
+ _spec,
100
+ name,
101
+ parentOnChange,
102
+ parentOnUnmount,
103
+ mutators,
104
+ config,
105
+ tools.onChange,
106
+ tools.onUnmount,
107
+ ]);
108
+ React.useEffect(() => {
109
+ firstRenderRef.current = false;
110
+ return () => {
111
+ callUnmout(store);
112
+ };
113
+ }, []);
114
+ return withSearch(store.render(renderProps));
115
+ };
@@ -0,0 +1 @@
1
+ export * from './Controller';
@@ -0,0 +1 @@
1
+ export * from './Controller';
@@ -0,0 +1,98 @@
1
+ /// <reference types="react" />
2
+ import { FormValue, Spec } from '../../../types';
3
+ import { DynamicFormConfig, DynamicFormMutators, DynamicFormsContext, FieldRenderProps, FieldValue, IndependentInputEntity, InputEntity, LayoutType, ValidateError } from '../types';
4
+ export interface GetSpecParams<SpecType extends Spec> {
5
+ name: string;
6
+ spec: SpecType;
7
+ mutators: DynamicFormMutators;
8
+ }
9
+ export interface GetComponentsParams<SpecType extends Spec> {
10
+ spec: SpecType;
11
+ config: DynamicFormConfig;
12
+ }
13
+ export interface GetComponentsReturn<DirtyValue extends FieldValue, SpecType extends Spec> {
14
+ inputEntity?: InputEntity<DirtyValue, SpecType> | IndependentInputEntity<DirtyValue, SpecType>;
15
+ Layout?: LayoutType<DirtyValue, SpecType>;
16
+ }
17
+ export interface GetRenderParams<DirtyValue extends FieldValue, SpecType extends Spec> {
18
+ name: string;
19
+ spec: SpecType;
20
+ inputEntity?: InputEntity<DirtyValue, SpecType> | IndependentInputEntity<DirtyValue, SpecType>;
21
+ Layout?: LayoutType<DirtyValue, SpecType>;
22
+ }
23
+ export interface GetValidateParams<SpecType extends Spec> {
24
+ spec: SpecType;
25
+ config: DynamicFormConfig;
26
+ }
27
+ export interface GetFieldInitialsParams<DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec> {
28
+ name: string;
29
+ spec: SpecType;
30
+ valueFromParent: DirtyValue;
31
+ initialValue: DirtyValue;
32
+ validate: (value?: Value) => ValidateError;
33
+ mutators: DynamicFormMutators;
34
+ }
35
+ export type FieldMethod<DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec, Params extends any = undefined> = (store: ControllerStore<DirtyValue, Value, SpecType>, params: Params) => ControllerStore<DirtyValue, Value, SpecType>;
36
+ export interface GetFieldMethodsReturn<DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec> {
37
+ onChange: FieldMethod<DirtyValue, Value, SpecType, {
38
+ valOrSetter: DirtyValue | ((currentValue: DirtyValue) => DirtyValue);
39
+ childErrors?: Record<string, ValidateError>;
40
+ errorMutator?: ValidateError;
41
+ }>;
42
+ onDrop: FieldMethod<DirtyValue, Value, SpecType>;
43
+ onBlur: FieldMethod<DirtyValue, Value, SpecType>;
44
+ onFocus: FieldMethod<DirtyValue, Value, SpecType>;
45
+ parentOnUnmount: FieldMethod<DirtyValue, Value, SpecType, string>;
46
+ onItemAdd: FieldMethod<DirtyValue, Value, SpecType, FieldValue>;
47
+ onItemRemove: FieldMethod<DirtyValue, Value, SpecType, number | string>;
48
+ }
49
+ export interface InitializeStoreParams<DirtyValue extends FieldValue, SpecType extends Spec> {
50
+ name: string;
51
+ spec: SpecType;
52
+ mutators: DynamicFormMutators;
53
+ config: DynamicFormConfig;
54
+ valueFromParent: DirtyValue;
55
+ tools: DynamicFormsContext['tools'];
56
+ parentOnChange: ((childName: string, childValue: FieldValue, childErrors: Record<string, ValidateError>) => void) | null;
57
+ parentOnUnmount: ((childName: string) => void) | null;
58
+ }
59
+ export interface ControllerStore<DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec> {
60
+ name: string;
61
+ spec: SpecType;
62
+ initialSpec: SpecType;
63
+ config: DynamicFormConfig;
64
+ tools: DynamicFormsContext['tools'];
65
+ mutators: DynamicFormMutators;
66
+ render: (props: FieldRenderProps<DirtyValue>) => JSX.Element | null;
67
+ validate: (value?: Value) => ValidateError;
68
+ parentOnChange: ((childName: string, childValue: FieldValue, childErrors: Record<string, ValidateError>) => void) | null;
69
+ parentOnUnmount: ((childName: string) => void) | null;
70
+ state: {
71
+ initialValue: DirtyValue;
72
+ active: boolean;
73
+ dirty: boolean;
74
+ error: ValidateError;
75
+ invalid: boolean;
76
+ modified: boolean;
77
+ pristine: boolean;
78
+ touched: boolean;
79
+ valid: boolean;
80
+ value: DirtyValue;
81
+ visited: boolean;
82
+ childErrors: Record<string, ValidateError>;
83
+ };
84
+ afterStoreUpdateCB?: () => void;
85
+ }
86
+ export interface UpdateStoreParams<DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec> {
87
+ store: ControllerStore<DirtyValue, Value, SpecType>;
88
+ setStore: (store: ControllerStore<DirtyValue, Value, SpecType>) => void;
89
+ spec: SpecType;
90
+ name: string;
91
+ parentOnChange: ((childName: string, childValue: FieldValue, childErrors: Record<string, ValidateError>) => void) | null;
92
+ parentOnUnmount: ((childName: string) => void) | null;
93
+ mutators: DynamicFormMutators;
94
+ valueFromParent: DirtyValue;
95
+ config: DynamicFormConfig;
96
+ tools: DynamicFormsContext['tools'];
97
+ methodOnChange: GetFieldMethodsReturn<DirtyValue, Value, SpecType>['onChange'];
98
+ }
@@ -0,0 +1,26 @@
1
+ import { FormValue, Spec } from '../../../types';
2
+ import { FieldRenderProps, FieldValue, ValidateError } from '../types';
3
+ import { ControllerStore, GetComponentsParams, GetComponentsReturn, GetFieldInitialsParams, GetFieldMethodsReturn, GetRenderParams, GetSpecParams, GetValidateParams, InitializeStoreParams, UpdateStoreParams } from './types';
4
+ export declare const updateParentStore: <DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec>(store: ControllerStore<DirtyValue, Value, SpecType>) => void;
5
+ export declare const callUnmout: <DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec>(store: ControllerStore<DirtyValue, Value, SpecType>) => void;
6
+ export declare const getSpec: <SpecType extends Spec>({ name, spec, mutators, }: GetSpecParams<SpecType>) => SpecType;
7
+ export declare const getComponents: <DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec>({ spec, config, }: GetComponentsParams<SpecType>) => GetComponentsReturn<DirtyValue, SpecType>;
8
+ export declare const getRender: <DirtyValue extends FieldValue, SpecType extends Spec>({ name, spec, inputEntity, Layout, }: GetRenderParams<DirtyValue, SpecType>) => (props: FieldRenderProps<DirtyValue>) => JSX.Element | null;
9
+ export declare const getValidate: <DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec>({ spec, config, }: GetValidateParams<SpecType>) => (value?: Value | undefined) => ValidateError;
10
+ export declare const getFieldInitials: <DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec>({ name, spec, valueFromParent, initialValue, validate, mutators, }: GetFieldInitialsParams<DirtyValue, Value, SpecType>) => {
11
+ initialValue: DirtyValue;
12
+ active: boolean;
13
+ dirty: boolean;
14
+ error: string | boolean | import("../types").AsyncValidateError | undefined;
15
+ invalid: boolean;
16
+ modified: boolean;
17
+ pristine: boolean;
18
+ touched: boolean;
19
+ valid: boolean;
20
+ value: DirtyValue;
21
+ visited: boolean;
22
+ childErrors: {};
23
+ };
24
+ export declare const getFieldMethods: <DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec>() => GetFieldMethodsReturn<DirtyValue, Value, SpecType>;
25
+ export declare const initializeStore: <DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec>({ name, spec: _spec, mutators, config, valueFromParent, tools, parentOnChange, parentOnUnmount, }: InitializeStoreParams<DirtyValue, SpecType>) => ControllerStore<DirtyValue, Value, SpecType>;
26
+ export declare const updateStore: <DirtyValue extends FieldValue, Value extends FormValue, SpecType extends Spec>({ store, setStore, spec: _spec, name, parentOnChange, parentOnUnmount, mutators, valueFromParent, config, tools, methodOnChange, }: UpdateStoreParams<DirtyValue, Value, SpecType>) => void;
@@ -0,0 +1,291 @@
1
+ import React from 'react';
2
+ import _ from 'lodash';
3
+ import { isValidElementType } from 'react-is';
4
+ import { SpecTypes } from '../../../constants';
5
+ import { isArraySpec, isCorrectSpec, isNumberSpec, isObjectSpec } from '../../../helpers';
6
+ import { EMPTY_MUTATOR, OBJECT_ARRAY_CNT, OBJECT_ARRAY_FLAG } from '../constants';
7
+ import { isArrayItem, isCorrectConfig, transformArrIn, transformArrOut } from '../utils';
8
+ const isErrorMutatorCorrect = (errorMutator) => errorMutator !== EMPTY_MUTATOR && (_.isString(errorMutator) || _.isBoolean(errorMutator));
9
+ const isValueMutatorCorrect = (valueMutator, spec) => valueMutator !== EMPTY_MUTATOR &&
10
+ (typeof valueMutator === spec.type ||
11
+ (_.isArray(valueMutator) && spec.type === SpecTypes.Array));
12
+ export const updateParentStore = (store) => {
13
+ (store.parentOnChange ? store.parentOnChange : store.tools.onChange)(store.name, store.state.value, Object.assign(Object.assign({}, store.state.childErrors), { [store.name]: store.state.error }));
14
+ };
15
+ export const callUnmout = (store) => {
16
+ (store.parentOnUnmount ? store.parentOnUnmount : store.tools.onUnmount)(store.name);
17
+ };
18
+ export const getSpec = ({ name, spec, mutators, }) => {
19
+ const mutator = _.get(mutators.spec, name, EMPTY_MUTATOR);
20
+ if (mutator !== EMPTY_MUTATOR) {
21
+ const mutatedSpec = _.merge(_.cloneDeep(spec), mutator);
22
+ if (isCorrectSpec(mutatedSpec)) {
23
+ return mutatedSpec;
24
+ }
25
+ }
26
+ return spec;
27
+ };
28
+ export const getComponents = ({ spec, config, }) => {
29
+ const result = {};
30
+ if (isCorrectConfig(config) && isCorrectSpec(spec)) {
31
+ const { inputs, layouts } = config[spec.type];
32
+ if (inputs) {
33
+ const entity = inputs[spec.viewSpec.type];
34
+ if (isValidElementType(entity === null || entity === void 0 ? void 0 : entity.Component)) {
35
+ result.inputEntity = entity;
36
+ }
37
+ }
38
+ if (layouts && _.isString(spec.viewSpec.layout)) {
39
+ const Component = layouts[spec.viewSpec.layout];
40
+ if (isValidElementType(Component)) {
41
+ result.Layout = Component;
42
+ }
43
+ }
44
+ }
45
+ return result;
46
+ };
47
+ export const getRender = ({ name, spec, inputEntity, Layout, }) => {
48
+ const render = (props) => {
49
+ if (inputEntity && isCorrectSpec(spec) && _.isString(name)) {
50
+ if (!spec.viewSpec.hidden) {
51
+ if (inputEntity.independent) {
52
+ const InputComponent = inputEntity.Component;
53
+ return React.createElement(InputComponent, Object.assign({ spec: spec, name: name, Layout: Layout }, props));
54
+ }
55
+ const InputComponent = inputEntity.Component;
56
+ const input = React.createElement(InputComponent, Object.assign({ spec: spec, name: name }, props));
57
+ if (Layout) {
58
+ return (React.createElement(Layout, Object.assign({ spec: spec, name: name }, props), input));
59
+ }
60
+ return input;
61
+ }
62
+ }
63
+ return null;
64
+ };
65
+ return render;
66
+ };
67
+ export const getValidate = ({ spec, config, }) => {
68
+ let validate = () => undefined;
69
+ if (isCorrectConfig(config) && isCorrectSpec(spec)) {
70
+ const { validators } = config[spec.type];
71
+ if (validators) {
72
+ if ((!_.isString(spec.validator) || !spec.validator.length) &&
73
+ _.isFunction(validators.base)) {
74
+ validate = (value) => validators.base(spec, value);
75
+ }
76
+ if (_.isString(spec.validator) && _.isFunction(validators[spec.validator])) {
77
+ validate = (value) => validators[spec.validator](spec, value);
78
+ }
79
+ }
80
+ }
81
+ return validate;
82
+ };
83
+ export const getFieldInitials = ({ name, spec, valueFromParent, initialValue, validate, mutators, }) => {
84
+ const valueMutator = transformArrIn(_.get(mutators.values, name, EMPTY_MUTATOR));
85
+ let value = _.cloneDeep(valueFromParent);
86
+ if (isValueMutatorCorrect(valueMutator, spec)) {
87
+ value = valueMutator;
88
+ }
89
+ if (_.isNil(value)) {
90
+ if (spec.defaultValue) {
91
+ value = transformArrIn(spec.defaultValue);
92
+ }
93
+ // if the spec with type array or object, and this spec has "required === true",
94
+ // we immediately exclude empty value
95
+ else if (spec.required) {
96
+ if (isArraySpec(spec)) {
97
+ value = { [OBJECT_ARRAY_FLAG]: true, [OBJECT_ARRAY_CNT]: 0 };
98
+ }
99
+ else if (isObjectSpec(spec)) {
100
+ value = {};
101
+ }
102
+ }
103
+ }
104
+ let errorMutator = _.get(mutators.errors, name, EMPTY_MUTATOR);
105
+ if (!isErrorMutatorCorrect(errorMutator)) {
106
+ errorMutator = undefined;
107
+ }
108
+ const error = (validate === null || validate === void 0 ? void 0 : validate(transformArrOut(value))) || errorMutator;
109
+ const dirty = !_.isEqual(value, initialValue);
110
+ return {
111
+ initialValue,
112
+ active: false,
113
+ dirty,
114
+ error,
115
+ invalid: Boolean(error),
116
+ modified: dirty,
117
+ pristine: true,
118
+ touched: false,
119
+ valid: !error,
120
+ value,
121
+ visited: false,
122
+ childErrors: {},
123
+ };
124
+ };
125
+ export const getFieldMethods = () => {
126
+ const onChange = (store, { valOrSetter, childErrors, errorMutator }) => {
127
+ const { state, validate, spec } = store;
128
+ const _value = _.isFunction(valOrSetter) ? valOrSetter(state.value) : valOrSetter;
129
+ const error = (validate === null || validate === void 0 ? void 0 : validate(transformArrOut(_value))) || errorMutator;
130
+ let value = transformArrIn(_value);
131
+ if (isNumberSpec(spec) && !error) {
132
+ value = (value ? Number(value) : undefined);
133
+ }
134
+ let newChildErrors = Object.assign({}, state.childErrors);
135
+ if (childErrors) {
136
+ const nearestChildName = _.keys(childErrors).sort((a, b) => a.length - b.length)[0];
137
+ if (nearestChildName) {
138
+ const existingСhildNames = _.keys(newChildErrors).filter((childName) => childName.startsWith(nearestChildName));
139
+ newChildErrors = Object.assign(Object.assign({}, _.omit(newChildErrors, existingСhildNames)), childErrors);
140
+ }
141
+ }
142
+ const nextStore = Object.assign(Object.assign({}, store), { state: Object.assign(Object.assign({}, store.state), { dirty: !_.isEqual(value, state.initialValue), error, invalid: Boolean(error), modified: true, pristine: value === state.initialValue, touched: true, valid: !error, value, visited: true, childErrors: newChildErrors }) });
143
+ nextStore.afterStoreUpdateCB = () => updateParentStore(nextStore);
144
+ return nextStore;
145
+ };
146
+ const onDrop = (store) => {
147
+ const { name } = store;
148
+ if (isArrayItem(name)) {
149
+ const afterStoreUpdateCB = () => callUnmout(store);
150
+ return Object.assign(Object.assign({}, store), { afterStoreUpdateCB });
151
+ }
152
+ return onChange(store, {
153
+ valOrSetter: undefined,
154
+ childErrors: { [name]: false },
155
+ });
156
+ };
157
+ const onBlur = (store) => {
158
+ return Object.assign(Object.assign({}, store), { state: Object.assign(Object.assign({}, store.state), { active: false, touched: true }) });
159
+ };
160
+ const onFocus = (store) => {
161
+ return Object.assign(Object.assign({}, store), { state: Object.assign(Object.assign({}, store.state), { active: true, visited: true }) });
162
+ };
163
+ const parentOnUnmount = (store, childName) => {
164
+ const { name, spec } = store;
165
+ if (isArraySpec(spec) || isObjectSpec(spec)) {
166
+ return onChange(store, {
167
+ valOrSetter: (currentValue) => currentValue
168
+ ? _.omit(currentValue, childName.split(`${name}.`)[1])
169
+ : currentValue,
170
+ childErrors: { [childName]: false },
171
+ });
172
+ }
173
+ return store;
174
+ };
175
+ const onItemAdd = (store, _value) => {
176
+ const { validate, state } = store;
177
+ const stateValue = (state.value || {
178
+ [OBJECT_ARRAY_FLAG]: true,
179
+ [OBJECT_ARRAY_CNT]: 0,
180
+ });
181
+ const value = Object.assign(Object.assign({}, stateValue), { [`<${stateValue[OBJECT_ARRAY_CNT]}>`]: transformArrIn(_value), [OBJECT_ARRAY_CNT]: stateValue[OBJECT_ARRAY_CNT] + 1 });
182
+ const error = validate === null || validate === void 0 ? void 0 : validate(transformArrOut(value));
183
+ const nextStore = Object.assign(Object.assign({}, store), { state: Object.assign(Object.assign({}, store.state), { dirty: !_.isEqual(value, store.state.initialValue), error, invalid: Boolean(error), modified: true, pristine: value === store.state.initialValue, touched: true, valid: !error, value, visited: true }) });
184
+ nextStore.afterStoreUpdateCB = () => updateParentStore(nextStore);
185
+ return nextStore;
186
+ };
187
+ const onItemRemove = (store, idx) => {
188
+ return parentOnUnmount(store, `${store.name}.<${idx}>`);
189
+ };
190
+ return {
191
+ onChange,
192
+ onDrop,
193
+ onBlur,
194
+ onFocus,
195
+ parentOnUnmount,
196
+ onItemAdd,
197
+ onItemRemove,
198
+ };
199
+ };
200
+ export const initializeStore = ({ name, spec: _spec, mutators, config, valueFromParent, tools, parentOnChange, parentOnUnmount, }) => {
201
+ const spec = getSpec({ name, spec: _spec, mutators });
202
+ const components = getComponents({ spec, config });
203
+ const render = getRender(Object.assign({ name, spec }, components));
204
+ const validate = getValidate({ spec, config });
205
+ const state = getFieldInitials({
206
+ name,
207
+ spec,
208
+ valueFromParent,
209
+ validate,
210
+ mutators,
211
+ initialValue: _.get(tools.initialValue, name),
212
+ });
213
+ const initialsStore = {
214
+ name,
215
+ spec,
216
+ initialSpec: _spec,
217
+ config,
218
+ tools,
219
+ mutators,
220
+ render,
221
+ validate,
222
+ parentOnChange,
223
+ parentOnUnmount,
224
+ state,
225
+ };
226
+ if (!_.isEqual(valueFromParent, state.value) || state.error) {
227
+ initialsStore.afterStoreUpdateCB = () => updateParentStore(initialsStore);
228
+ }
229
+ return initialsStore;
230
+ };
231
+ export const updateStore = ({ store, setStore, spec: _spec, name, parentOnChange, parentOnUnmount, mutators, valueFromParent, config, tools, methodOnChange, }) => {
232
+ const storeSpecMutator = _.get(store.mutators.spec, store.name, EMPTY_MUTATOR);
233
+ const storeValueMutator = _.get(store.mutators.values, store.name, EMPTY_MUTATOR);
234
+ const storeErrorMutator = _.get(store.mutators.errors, store.name, EMPTY_MUTATOR);
235
+ const specMutator = _.get(mutators.errors, name, EMPTY_MUTATOR);
236
+ const valueMutator = _.get(mutators.values, name, EMPTY_MUTATOR);
237
+ const errorMutator = _.get(mutators.errors, name, EMPTY_MUTATOR);
238
+ const valueMutatorUpdated = isValueMutatorCorrect(valueMutator, getSpec({ name, spec: _spec, mutators })) &&
239
+ valueMutator !== storeValueMutator;
240
+ const errorMutatorUpdated = isErrorMutatorCorrect(errorMutator) && errorMutator !== storeErrorMutator;
241
+ const updateState = valueMutatorUpdated || errorMutatorUpdated;
242
+ const updateNonCritical = parentOnChange !== store.parentOnChange ||
243
+ parentOnUnmount !== store.parentOnUnmount ||
244
+ tools.onChange !== store.tools.onChange ||
245
+ tools.onUnmount !== store.tools.onUnmount;
246
+ const updateAllStore = !_.isEqual(_spec, store.initialSpec) ||
247
+ config !== store.config ||
248
+ (specMutator !== EMPTY_MUTATOR && specMutator !== storeSpecMutator);
249
+ const updateAllStoreAndClearParentValues = name !== store.name;
250
+ if (updateAllStoreAndClearParentValues) {
251
+ callUnmout(store);
252
+ setStore(initializeStore({
253
+ name,
254
+ spec: _spec,
255
+ mutators,
256
+ config,
257
+ valueFromParent,
258
+ tools,
259
+ parentOnChange,
260
+ parentOnUnmount,
261
+ }));
262
+ }
263
+ else if (updateAllStore) {
264
+ let nextStore = Object.assign(Object.assign({}, initializeStore({
265
+ name,
266
+ spec: _spec,
267
+ mutators,
268
+ config,
269
+ valueFromParent,
270
+ tools,
271
+ parentOnChange,
272
+ parentOnUnmount,
273
+ })), { state: store.state });
274
+ if (updateState) {
275
+ nextStore = methodOnChange(nextStore, Object.assign({ valOrSetter: (value) => valueMutatorUpdated ? valueMutator : value }, (errorMutatorUpdated ? { errorMutator } : {})));
276
+ }
277
+ setStore(nextStore);
278
+ }
279
+ else if (updateNonCritical) {
280
+ let nextStore = Object.assign(Object.assign({}, store), { parentOnChange,
281
+ parentOnUnmount,
282
+ tools });
283
+ if (updateState) {
284
+ nextStore = methodOnChange(nextStore, Object.assign({ valOrSetter: (value) => valueMutatorUpdated ? valueMutator : value }, (errorMutatorUpdated ? { errorMutator } : {})));
285
+ }
286
+ setStore(nextStore);
287
+ }
288
+ else if (updateState) {
289
+ setStore(methodOnChange(store, Object.assign({ valOrSetter: (value) => valueMutatorUpdated ? valueMutator : value }, (errorMutatorUpdated ? { errorMutator } : {}))));
290
+ }
291
+ };
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import type { MonacoEditorProps } from 'react-monaco-editor/lib/types';
3
3
  import { Spec, StringSpec } from '../../types';
4
- import { BaseValidateError, DynamicFormConfig, FieldValue, WonderMirror } from './types';
4
+ import { DynamicFormConfig, DynamicFormMutators, FieldValue, WonderMirror } from './types';
5
5
  export interface DynamicFieldProps {
6
6
  name: string;
7
7
  spec: Spec;
@@ -10,7 +10,7 @@ export interface DynamicFieldProps {
10
10
  search?: string | ((spec: Spec, input: FieldValue, name: string) => boolean);
11
11
  generateRandomValue?: (spec: StringSpec) => string;
12
12
  withoutInsertFFDebounce?: boolean;
13
- errors?: Record<string, BaseValidateError>;
13
+ mutators?: DynamicFormMutators;
14
14
  __mirror?: WonderMirror;
15
15
  }
16
16
  export declare const DynamicField: React.FC<DynamicFieldProps>;
@@ -3,22 +3,24 @@ import _ from 'lodash';
3
3
  import { isValidElementType } from 'react-is';
4
4
  import { isCorrectSpec } from '../../helpers';
5
5
  import { Controller } from './Controller';
6
- import { useCreateContext, useCreateSearchContext, useDynamicFieldMirror, useIntegrationFF, useSearchStore, useStore, } from './hooks';
6
+ import { useCreateContext, useCreateSearchContext, useDynamicFieldMirror, useIntegrationFF, useMutators, useSearchStore, useStore, } from './hooks';
7
7
  import { getDefaultSearchFunction, isCorrectConfig } from './utils';
8
- export const DynamicField = ({ name, spec, config, Monaco, generateRandomValue, search, withoutInsertFFDebounce, errors: externalErrors, __mirror, }) => {
8
+ export const DynamicField = ({ name, spec, config, Monaco, generateRandomValue, search, withoutInsertFFDebounce, mutators: externalMutators, __mirror, }) => {
9
9
  const DynamicFormsCtx = useCreateContext();
10
10
  const SearchContext = useCreateSearchContext();
11
11
  const { tools, store } = useStore(name);
12
12
  const watcher = useIntegrationFF(store, withoutInsertFFDebounce);
13
+ const { mutators, mutateDFState } = useMutators(externalMutators);
13
14
  const { store: searchStore, setField, removeField, isHiddenField } = useSearchStore();
14
15
  const context = React.useMemo(() => ({
15
16
  config,
16
17
  Monaco: isValidElementType(Monaco) ? Monaco : undefined,
17
18
  generateRandomValue,
18
- tools,
19
- externalErrors,
19
+ tools: Object.assign(Object.assign({}, tools), { mutateDFState }),
20
+ store,
21
+ mutators,
20
22
  __mirror,
21
- }), [tools, config, Monaco, __mirror, generateRandomValue, externalErrors]);
23
+ }), [tools, config, Monaco, __mirror, generateRandomValue, mutators, mutateDFState, store]);
22
24
  const searchContext = React.useMemo(() => ({
23
25
  setField,
24
26
  removeField,
@@ -1,3 +1,4 @@
1
1
  export declare const OBJECT_ARRAY_FLAG = "____arr-obj";
2
2
  export declare const OBJECT_ARRAY_CNT = "____arr-obj-cnt";
3
3
  export declare const SPEC_TYPE_FOR_GENERATE_BUTTON: string[];
4
+ export declare const EMPTY_MUTATOR = "____empty-mutator";
@@ -1,3 +1,4 @@
1
1
  export const OBJECT_ARRAY_FLAG = '____arr-obj';
2
2
  export const OBJECT_ARRAY_CNT = '____arr-obj-cnt';
3
3
  export const SPEC_TYPE_FOR_GENERATE_BUTTON = ['base', 'password', 'textarea'];
4
+ export const EMPTY_MUTATOR = '____empty-mutator';
@@ -1,14 +1,13 @@
1
- export * from './useComponents';
2
1
  export * from './useControllerMirror';
3
2
  export * from './useCreateContext';
4
3
  export * from './useDynamicFieldMirror';
5
4
  export * from './useDynamicFormsCtx';
6
- export * from './useField';
7
5
  export * from './useGenerateRandomValue';
8
6
  export * from './useIntegrationFF';
9
- export * from './useRender';
7
+ export * from './useMutateDFState';
8
+ export * from './useMutators';
10
9
  export * from './useStore';
11
- export * from './useValidate';
10
+ export * from './useStoreValue';
12
11
  export * from './useMonaco';
13
12
  export * from './useSearchStore';
14
13
  export * from './useSearchContext';
@@ -1,14 +1,13 @@
1
- export * from './useComponents';
2
1
  export * from './useControllerMirror';
3
2
  export * from './useCreateContext';
4
3
  export * from './useDynamicFieldMirror';
5
4
  export * from './useDynamicFormsCtx';
6
- export * from './useField';
7
5
  export * from './useGenerateRandomValue';
8
6
  export * from './useIntegrationFF';
9
- export * from './useRender';
7
+ export * from './useMutateDFState';
8
+ export * from './useMutators';
10
9
  export * from './useStore';
11
- export * from './useValidate';
10
+ export * from './useStoreValue';
12
11
  export * from './useMonaco';
13
12
  export * from './useSearchStore';
14
13
  export * from './useSearchContext';
@@ -0,0 +1 @@
1
+ export declare const useMutateDFState: () => (mutators: import("..").DynamicFormMutators) => void;
@@ -0,0 +1,2 @@
1
+ import { useDynamicFormsCtx } from './useDynamicFormsCtx';
2
+ export const useMutateDFState = () => useDynamicFormsCtx().tools.mutateDFState;
@@ -0,0 +1,5 @@
1
+ import { DynamicFormMutators } from '../types';
2
+ export declare const useMutators: (externalMutators?: DynamicFormMutators) => {
3
+ mutators: DynamicFormMutators;
4
+ mutateDFState: (mutators: DynamicFormMutators) => void;
5
+ };