@gravity-ui/dynamic-forms 5.26.0 → 5.27.1

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 (55) hide show
  1. package/build/cjs/lib/unstable/core/SchemaRendererNode/SchemaRendererNode.js +67 -14
  2. package/build/cjs/lib/unstable/core/SchemaRendererNode/utils.d.ts +6 -3
  3. package/build/cjs/lib/unstable/core/SchemaRendererNode/utils.js +63 -14
  4. package/build/cjs/lib/unstable/core/index.d.ts +1 -1
  5. package/build/cjs/lib/unstable/core/index.js +4 -1
  6. package/build/cjs/lib/unstable/core/useSchemaRenderer/types/state.d.ts +1 -0
  7. package/build/cjs/lib/unstable/core/useSchemaRenderer/useSchemaRenderer.d.ts +2 -1
  8. package/build/cjs/lib/unstable/core/useSchemaRenderer/useSchemaRenderer.js +39 -22
  9. package/build/cjs/lib/unstable/core/useSchemaRenderer/utils/get-validate.js +6 -1
  10. package/build/cjs/lib/unstable/core/useSchemaRendererState/useSchemaRendererState.js +14 -0
  11. package/build/cjs/lib/unstable/core/utils/common.d.ts +3 -0
  12. package/build/cjs/lib/unstable/core/utils/common.js +7 -1
  13. package/build/cjs/lib/unstable/core/utils/index.d.ts +1 -0
  14. package/build/cjs/lib/unstable/core/utils/index.js +1 -0
  15. package/build/cjs/lib/unstable/core/utils/strict-mode.d.ts +6 -0
  16. package/build/cjs/lib/unstable/core/utils/strict-mode.js +30 -0
  17. package/build/cjs/lib/unstable/kit/components/EntityError/EntityError.js +1 -1
  18. package/build/cjs/lib/unstable/kit/entities/OneOfNested/OneOfNested.js +9 -1
  19. package/build/cjs/lib/unstable/kit/form-entities/StringNumberWithScaleInput/StringNumberWithScaleInput.d.ts +1 -1
  20. package/build/cjs/lib/unstable/kit/form-entities/StringNumberWithScaleInput/StringNumberWithScaleInput.js +8 -7
  21. package/build/cjs/lib/unstable/kit/overview-entities/StringNumberWithScaleValue/StringNumberWithScaleValue.d.ts +1 -1
  22. package/build/cjs/lib/unstable/kit/overview-entities/StringNumberWithScaleValue/StringNumberWithScaleValue.js +5 -5
  23. package/build/cjs/lib/unstable/kit/utils/common.d.ts +0 -3
  24. package/build/cjs/lib/unstable/kit/utils/common.js +1 -7
  25. package/build/cjs/lib/unstable/kit/utils/index.d.ts +1 -1
  26. package/build/cjs/lib/unstable/kit/utils/index.js +1 -4
  27. package/build/cjs/lib/unstable/kit/utils/transformer.js +10 -2
  28. package/build/esm/lib/unstable/core/SchemaRendererNode/SchemaRendererNode.js +70 -17
  29. package/build/esm/lib/unstable/core/SchemaRendererNode/utils.d.ts +6 -3
  30. package/build/esm/lib/unstable/core/SchemaRendererNode/utils.js +63 -14
  31. package/build/esm/lib/unstable/core/index.d.ts +1 -1
  32. package/build/esm/lib/unstable/core/index.js +1 -1
  33. package/build/esm/lib/unstable/core/useSchemaRenderer/types/state.d.ts +1 -0
  34. package/build/esm/lib/unstable/core/useSchemaRenderer/useSchemaRenderer.d.ts +2 -1
  35. package/build/esm/lib/unstable/core/useSchemaRenderer/useSchemaRenderer.js +40 -23
  36. package/build/esm/lib/unstable/core/useSchemaRenderer/utils/get-validate.js +6 -1
  37. package/build/esm/lib/unstable/core/useSchemaRendererState/useSchemaRendererState.js +15 -1
  38. package/build/esm/lib/unstable/core/utils/common.d.ts +3 -0
  39. package/build/esm/lib/unstable/core/utils/common.js +3 -0
  40. package/build/esm/lib/unstable/core/utils/index.d.ts +1 -0
  41. package/build/esm/lib/unstable/core/utils/index.js +1 -0
  42. package/build/esm/lib/unstable/core/utils/strict-mode.d.ts +6 -0
  43. package/build/esm/lib/unstable/core/utils/strict-mode.js +26 -0
  44. package/build/esm/lib/unstable/kit/components/EntityError/EntityError.js +1 -1
  45. package/build/esm/lib/unstable/kit/entities/OneOfNested/OneOfNested.js +9 -1
  46. package/build/esm/lib/unstable/kit/form-entities/StringNumberWithScaleInput/StringNumberWithScaleInput.d.ts +1 -1
  47. package/build/esm/lib/unstable/kit/form-entities/StringNumberWithScaleInput/StringNumberWithScaleInput.js +2 -1
  48. package/build/esm/lib/unstable/kit/overview-entities/StringNumberWithScaleValue/StringNumberWithScaleValue.d.ts +1 -1
  49. package/build/esm/lib/unstable/kit/overview-entities/StringNumberWithScaleValue/StringNumberWithScaleValue.js +1 -1
  50. package/build/esm/lib/unstable/kit/utils/common.d.ts +0 -3
  51. package/build/esm/lib/unstable/kit/utils/common.js +0 -3
  52. package/build/esm/lib/unstable/kit/utils/index.d.ts +1 -1
  53. package/build/esm/lib/unstable/kit/utils/index.js +1 -1
  54. package/build/esm/lib/unstable/kit/utils/transformer.js +10 -2
  55. package/package.json +1 -1
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const uikit_1 = require("@gravity-ui/uikit");
7
7
  const decimal_js_1 = tslib_1.__importDefault(require("decimal.js"));
8
+ const core_1 = require("../../../core");
8
9
  const components_1 = require("../../components");
9
10
  const utils_1 = require("../../utils");
10
11
  const b = (0, utils_1.block)('string-number-with-scale-input');
@@ -18,7 +19,7 @@ const StringNumberWithScaleInput = ({ input, meta, props, schema }) => {
18
19
  const preparedScale = {};
19
20
  let minScaleLength = 0;
20
21
  Object.entries(scale).forEach(([key, value]) => {
21
- if ((0, utils_1.isStringNumber)(value.factor)) {
22
+ if ((0, core_1.isStringNumber)(value.factor)) {
22
23
  preparedScale[key] = value;
23
24
  if ((value.title || key).length * 12 > minScaleLength) {
24
25
  minScaleLength = (value.title || key).length * 12;
@@ -47,16 +48,16 @@ const StringNumberWithScaleInput = ({ input, meta, props, schema }) => {
47
48
  var _a, _b, _c, _d, _e, _f, _g, _h;
48
49
  const factor = (_b = (_a = scaleKit === null || scaleKit === void 0 ? void 0 : scaleKit.scale) === null || _a === void 0 ? void 0 : _a[scaleValue[0]]) === null || _b === void 0 ? void 0 : _b.factor;
49
50
  const result = {
50
- max: (0, utils_1.isStringNumber)((_c = schema.stringNumber) === null || _c === void 0 ? void 0 : _c.maximum)
51
+ max: (0, core_1.isStringNumber)((_c = schema.stringNumber) === null || _c === void 0 ? void 0 : _c.maximum)
51
52
  ? (_d = schema.stringNumber) === null || _d === void 0 ? void 0 : _d.maximum
52
53
  : undefined,
53
- min: (0, utils_1.isStringNumber)((_e = schema.stringNumber) === null || _e === void 0 ? void 0 : _e.minimum)
54
+ min: (0, core_1.isStringNumber)((_e = schema.stringNumber) === null || _e === void 0 ? void 0 : _e.minimum)
54
55
  ? (_f = schema.stringNumber) === null || _f === void 0 ? void 0 : _f.minimum
55
56
  : undefined,
56
- step: (0, utils_1.isStringNumber)((_g = schema.stringNumber) === null || _g === void 0 ? void 0 : _g.multipleOf)
57
+ step: (0, core_1.isStringNumber)((_g = schema.stringNumber) === null || _g === void 0 ? void 0 : _g.multipleOf)
57
58
  ? (_h = schema.stringNumber) === null || _h === void 0 ? void 0 : _h.multipleOf
58
59
  : '1',
59
- defaultValue: (0, utils_1.isStringNumber)(schema.default) ? schema.default : undefined,
60
+ defaultValue: (0, core_1.isStringNumber)(schema.default) ? schema.default : undefined,
60
61
  value: inputValue || '',
61
62
  onUpdate: onChange,
62
63
  };
@@ -65,10 +66,10 @@ const StringNumberWithScaleInput = ({ input, meta, props, schema }) => {
65
66
  max: result.max ? new decimal_js_1.default(result.max).div(factor).toString() : undefined,
66
67
  min: result.min ? new decimal_js_1.default(result.min).div(factor).toString() : undefined,
67
68
  step: new decimal_js_1.default(result.step).div(factor).toString(),
68
- value: (0, utils_1.isStringNumber)(result.value)
69
+ value: (0, core_1.isStringNumber)(result.value)
69
70
  ? new decimal_js_1.default(result.value).div(factor).toString()
70
71
  : result.value,
71
- onUpdate: (value) => onChange((0, utils_1.isStringNumber)(value) ? new decimal_js_1.default(value).mul(factor).toString() : value),
72
+ onUpdate: (value) => onChange((0, core_1.isStringNumber)(value) ? new decimal_js_1.default(value).mul(factor).toString() : value),
72
73
  };
73
74
  }
74
75
  return result;
@@ -1,4 +1,4 @@
1
- import type { JsonSchemaString, NodeEntity } from '../../../core';
1
+ import { type JsonSchemaString, type NodeEntity } from '../../../core';
2
2
  import { type LongValueProps } from '../../components';
3
3
  export interface StringNumberWithScaleValueProps extends Omit<LongValueProps, 'qa' | 'value'> {
4
4
  scale?: Record<string, {
@@ -6,18 +6,18 @@ const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const uikit_1 = require("@gravity-ui/uikit");
7
7
  const decimal_js_1 = tslib_1.__importDefault(require("decimal.js"));
8
8
  const get_1 = tslib_1.__importDefault(require("lodash/get"));
9
+ const core_1 = require("../../../core");
9
10
  const components_1 = require("../../components");
10
- const utils_1 = require("../../utils");
11
11
  const StringNumberWithScaleValue = ({ input, props }) => {
12
12
  const { scale, viewType } = props, restProps = tslib_1.__rest(props, ["scale", "viewType"]);
13
13
  const level = react_1.default.useMemo(() => {
14
14
  const determined = viewType ? (0, get_1.default)(scale, viewType) : undefined;
15
- let suggested = (0, utils_1.isStringNumber)(determined === null || determined === void 0 ? void 0 : determined.factor)
15
+ let suggested = (0, core_1.isStringNumber)(determined === null || determined === void 0 ? void 0 : determined.factor)
16
16
  ? determined
17
17
  : undefined;
18
18
  Object.values(scale || {}).forEach((item) => {
19
- if ((0, utils_1.isStringNumber)(input.value) &&
20
- (0, utils_1.isStringNumber)(item.factor) &&
19
+ if ((0, core_1.isStringNumber)(input.value) &&
20
+ (0, core_1.isStringNumber)(item.factor) &&
21
21
  new decimal_js_1.default(input.value).div(item.factor).abs().gte(1) &&
22
22
  (!suggested || new decimal_js_1.default(item.factor).gt(suggested.factor))) {
23
23
  suggested = item;
@@ -25,7 +25,7 @@ const StringNumberWithScaleValue = ({ input, props }) => {
25
25
  });
26
26
  return suggested;
27
27
  }, [input.value, scale, viewType]);
28
- if (!(0, utils_1.isStringNumber)(input.value)) {
28
+ if (!(0, core_1.isStringNumber)(input.value)) {
29
29
  return react_1.default.createElement(components_1.EmptyEntityValue, null);
30
30
  }
31
31
  return (react_1.default.createElement(components_1.EntityContainer, { stretch: "fit", fill: "populated", direction: "row", gap: 0.5 },
@@ -6,6 +6,3 @@ export declare const getArrayItemParentName: (name: string) => string;
6
6
  export declare const getArrayItemIndex: (name: string) => string;
7
7
  export declare const isArrayItem: (name: string) => boolean;
8
8
  export declare const isTupleItem: (name: string, headName: string, form: FormApi) => boolean | undefined;
9
- export declare const isStringInt: (v: unknown) => v is string;
10
- export declare const isStringFloat: (v: unknown) => v is string;
11
- export declare const isStringNumber: (v: unknown) => v is string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isStringNumber = exports.isStringFloat = exports.isStringInt = exports.isTupleItem = exports.isArrayItem = exports.getArrayItemIndex = exports.getArrayItemParentName = exports.getBooleanValidationState = exports.getValidationState = void 0;
3
+ exports.isTupleItem = exports.isArrayItem = exports.getArrayItemIndex = exports.getArrayItemParentName = exports.getBooleanValidationState = exports.getValidationState = void 0;
4
4
  const core_1 = require("../../core");
5
5
  const getValidationState = (meta) => {
6
6
  if ((meta.touched || meta.submitFailed) && meta.error) {
@@ -37,9 +37,3 @@ const isTupleItem = (name, headName, form) => {
37
37
  return parentSchema && 'items' in parentSchema && Array.isArray(parentSchema.items);
38
38
  };
39
39
  exports.isTupleItem = isTupleItem;
40
- const isStringInt = (v) => /^-?(0|[1-9][0-9]*)$/.test(`${v}`);
41
- exports.isStringInt = isStringInt;
42
- const isStringFloat = (v) => /^-?(0|[1-9][0-9]*)(\.[0-9]+)?$/.test(`${v}`);
43
- exports.isStringFloat = isStringFloat;
44
- const isStringNumber = (v) => (0, exports.isStringInt)(v) || (0, exports.isStringFloat)(v);
45
- exports.isStringNumber = isStringNumber;
@@ -1,4 +1,4 @@
1
1
  export { block } from './cn';
2
- export { getArrayItemIndex, getArrayItemParentName, getBooleanValidationState, getValidationState, isArrayItem, isStringInt, isStringFloat, isStringNumber, isTupleItem, } from './common';
2
+ export { getArrayItemIndex, getArrayItemParentName, getBooleanValidationState, getValidationState, isArrayItem, isTupleItem, } from './common';
3
3
  export { parseDate } from './date';
4
4
  export { specToJsonSchema } from './transformer';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.specToJsonSchema = exports.parseDate = exports.isTupleItem = exports.isStringNumber = exports.isStringFloat = exports.isStringInt = exports.isArrayItem = exports.getValidationState = exports.getBooleanValidationState = exports.getArrayItemParentName = exports.getArrayItemIndex = exports.block = void 0;
3
+ exports.specToJsonSchema = exports.parseDate = exports.isTupleItem = exports.isArrayItem = exports.getValidationState = exports.getBooleanValidationState = exports.getArrayItemParentName = exports.getArrayItemIndex = exports.block = void 0;
4
4
  var cn_1 = require("./cn");
5
5
  Object.defineProperty(exports, "block", { enumerable: true, get: function () { return cn_1.block; } });
6
6
  var common_1 = require("./common");
@@ -9,9 +9,6 @@ Object.defineProperty(exports, "getArrayItemParentName", { enumerable: true, get
9
9
  Object.defineProperty(exports, "getBooleanValidationState", { enumerable: true, get: function () { return common_1.getBooleanValidationState; } });
10
10
  Object.defineProperty(exports, "getValidationState", { enumerable: true, get: function () { return common_1.getValidationState; } });
11
11
  Object.defineProperty(exports, "isArrayItem", { enumerable: true, get: function () { return common_1.isArrayItem; } });
12
- Object.defineProperty(exports, "isStringInt", { enumerable: true, get: function () { return common_1.isStringInt; } });
13
- Object.defineProperty(exports, "isStringFloat", { enumerable: true, get: function () { return common_1.isStringFloat; } });
14
- Object.defineProperty(exports, "isStringNumber", { enumerable: true, get: function () { return common_1.isStringNumber; } });
15
12
  Object.defineProperty(exports, "isTupleItem", { enumerable: true, get: function () { return common_1.isTupleItem; } });
16
13
  var date_1 = require("./date");
17
14
  Object.defineProperty(exports, "parseDate", { enumerable: true, get: function () { return date_1.parseDate; } });
@@ -7,7 +7,6 @@ const isObject_1 = tslib_1.__importDefault(require("lodash/isObject"));
7
7
  const set_1 = tslib_1.__importDefault(require("lodash/set"));
8
8
  const core_1 = require("../../../core");
9
9
  const core_2 = require("../../core");
10
- const constants_1 = require("../constants");
11
10
  const viewSpecRules = {
12
11
  disabled: (spec, mutableSchema) => {
13
12
  if (spec.viewSpec.disabled) {
@@ -664,6 +663,15 @@ const specRules = {
664
663
  Object.entries(spec.properties).forEach(([key, childSpec]) => {
665
664
  const childSchema = specToJsonSchema(childSpec, Object.assign({}, ((0, get_1.default)(mutableSchema, ['properties', key]) || {})), rules, errorMessages);
666
665
  (0, set_1.default)(mutableSchema, ['properties', key], childSchema);
666
+ if (childSpec.required &&
667
+ !(spec.viewSpec.type === 'oneof' ||
668
+ spec.viewSpec.type === 'oneof_flat' ||
669
+ spec.viewSpec.type === 'card_oneof' ||
670
+ spec.viewSpec.type === 'multi_oneof' ||
671
+ spec.viewSpec.type === 'multi_oneof_flat')) {
672
+ (0, set_1.default)(mutableSchema, ['required'], [...((0, get_1.default)(mutableSchema, 'required') || []), key]);
673
+ (0, set_1.default)(mutableSchema, 'nodeParameters.errorMessages.required', errorMessages.required);
674
+ }
667
675
  });
668
676
  }
669
677
  },
@@ -681,7 +689,7 @@ const specRules = {
681
689
  Object.values(rules.viewSpecRules).forEach((rule) => rule(spec, mutableSchema, rules, errorMessages));
682
690
  },
683
691
  };
684
- function specToJsonSchema(spec, mutableSchema = {}, rules, errorMessages = constants_1.errorMessages) {
692
+ function specToJsonSchema(spec, mutableSchema = {}, rules, errorMessages = {}) {
685
693
  const mergedSpecRules = Object.assign(Object.assign({}, specRules), rules === null || rules === void 0 ? void 0 : rules.specRules);
686
694
  const mergedViewSpecRules = Object.assign(Object.assign({}, viewSpecRules), rules === null || rules === void 0 ? void 0 : rules.viewSpecRules);
687
695
  Object.values(mergedSpecRules).forEach((rule) => rule(spec, mutableSchema, { specRules: mergedSpecRules, viewSpecRules: mergedViewSpecRules }, errorMessages));
@@ -1,15 +1,16 @@
1
1
  import React from 'react';
2
+ import get from 'lodash/get';
2
3
  import noop from 'lodash/noop';
3
4
  import { useForm } from 'react-final-form';
4
- import { SchemaRendererEventType, SchemaRendererMode } from '../constants';
5
+ import { JsonSchemaType, SchemaRendererEventType, SchemaRendererMode } from '../constants';
5
6
  import { SCHEMA_RENDERER_SERVICE_FIELD } from '../useSchemaRenderer';
6
7
  import { useSchemaRendererState } from '../useSchemaRendererState';
7
- import { getServiceFieldName } from '../utils';
8
- import { getAccumulatedSchema, getCompareValues, getRenderKit, scheduleFlush } from './utils';
8
+ import { getServiceFieldName, getStrictModeChecker } from '../utils';
9
+ import { coerceToJsonSchemaType, getAccumulatedSchema, getRenderKit, scheduleFlush } from './utils';
9
10
  const SchemaRendererNodeComponent = ({ headName, modeOverride, name, schemaOverride, schemaPath, }) => {
10
- var _a;
11
+ var _a, _b, _c, _d, _e, _f;
11
12
  const form = useForm();
12
- const compareValuesRef = React.useRef(getCompareValues());
13
+ const strictCheckerRef = React.useRef(getStrictModeChecker());
13
14
  const fieldRef = React.useRef(null);
14
15
  const unsubscribeRef = React.useRef(null);
15
16
  const [ticks, setTicks] = React.useState({ input: 0, meta: 0 });
@@ -30,13 +31,15 @@ const SchemaRendererNodeComponent = ({ headName, modeOverride, name, schemaOverr
30
31
  const schema = React.useMemo(() => getAccumulatedSchema(schemaPath, srState === null || srState === void 0 ? void 0 : srState.schema, schemaOverride), [schemaOverride, schemaPath, srState === null || srState === void 0 ? void 0 : srState.schema]);
31
32
  const error = srState === null || srState === void 0 ? void 0 : srState.errors[name];
32
33
  const mode = modeOverride || (srState === null || srState === void 0 ? void 0 : srState.mode);
33
- const jsonDefaultValues = ((_a = srState === null || srState === void 0 ? void 0 : srState.settings) === null || _a === void 0 ? void 0 : _a.jsonDefaultValues) || false;
34
+ // todo: check parent
35
+ const required = (_b = (_a = schema === null || schema === void 0 ? void 0 : schema.nodeParameters) === null || _a === void 0 ? void 0 : _a.flags) === null || _b === void 0 ? void 0 : _b.required;
36
+ const coerceInitialValues = (_d = (_c = srState === null || srState === void 0 ? void 0 : srState.settings) === null || _c === void 0 ? void 0 : _c.coerceInitialValues) !== null && _d !== void 0 ? _d : true;
37
+ const jsonDefaultValues = (_f = (_e = srState === null || srState === void 0 ? void 0 : srState.settings) === null || _e === void 0 ? void 0 : _e.jsonDefaultValues) !== null && _f !== void 0 ? _f : false;
34
38
  const kit = React.useMemo(() => getRenderKit({ config: srState === null || srState === void 0 ? void 0 : srState.config, schema }), [schema, srState === null || srState === void 0 ? void 0 : srState.config]);
35
39
  React.useMemo(() => {
36
40
  var _a;
37
- if (compareValuesRef.current({
41
+ if (!strictCheckerRef.current.checkDiff({
38
42
  form,
39
- jsonDefaultValues,
40
43
  headName,
41
44
  name,
42
45
  default: schema === null || schema === void 0 ? void 0 : schema.default,
@@ -47,13 +50,35 @@ const SchemaRendererNodeComponent = ({ headName, modeOverride, name, schemaOverr
47
50
  }
48
51
  (_a = unsubscribeRef.current) === null || _a === void 0 ? void 0 : _a.call(unsubscribeRef);
49
52
  const initialState = { schemaPath };
50
- let defaultValue = schema === null || schema === void 0 ? void 0 : schema.default;
51
- if (jsonDefaultValues && typeof defaultValue === 'string') {
52
- try {
53
- defaultValue = JSON.parse(defaultValue);
53
+ const defaultValue = (() => {
54
+ let result = schema === null || schema === void 0 ? void 0 : schema.default;
55
+ if (jsonDefaultValues) {
56
+ try {
57
+ result = JSON.parse(result);
58
+ }
59
+ catch (_a) {
60
+ result = undefined;
61
+ }
54
62
  }
55
- catch (_b) { }
56
- }
63
+ if (result === undefined && required) {
64
+ if ((Array.isArray(schema.type) &&
65
+ schema.type.length &&
66
+ !schema.type.filter((t) => t !== JsonSchemaType.Array).length) ||
67
+ schema.type === JsonSchemaType.Array) {
68
+ result = [];
69
+ }
70
+ else if ((Array.isArray(schema.type) &&
71
+ schema.type.length &&
72
+ !schema.type.filter((t) => t !== JsonSchemaType.Object).length) ||
73
+ schema.type === JsonSchemaType.Object) {
74
+ result = {};
75
+ }
76
+ }
77
+ if (coerceInitialValues) {
78
+ result = coerceToJsonSchemaType(result, schema === null || schema === void 0 ? void 0 : schema.type);
79
+ }
80
+ return result;
81
+ })();
57
82
  const unsubscribe = form.registerField(name, (f) => {
58
83
  const prevF = fieldRef.current;
59
84
  if (prevF) {
@@ -81,12 +106,36 @@ const SchemaRendererNodeComponent = ({ headName, modeOverride, name, schemaOverr
81
106
  silent: true,
82
107
  validateFields: [getServiceFieldName(SCHEMA_RENDERER_SERVICE_FIELD, headName)],
83
108
  });
84
- scheduleFlush(form);
109
+ const castParams = (() => {
110
+ if (!coerceInitialValues) {
111
+ return undefined;
112
+ }
113
+ const formValues = form.getState().values;
114
+ const currentValue = name ? get(formValues, name) : formValues;
115
+ if (currentValue === undefined) {
116
+ return undefined;
117
+ }
118
+ const coercedCurrentValue = coerceToJsonSchemaType(currentValue, schema === null || schema === void 0 ? void 0 : schema.type);
119
+ if (coercedCurrentValue !== undefined) {
120
+ if (coercedCurrentValue === currentValue) {
121
+ return undefined;
122
+ }
123
+ return { name, value: coercedCurrentValue };
124
+ }
125
+ if (defaultValue !== undefined) {
126
+ if (defaultValue === currentValue) {
127
+ return undefined;
128
+ }
129
+ return { name, value: defaultValue };
130
+ }
131
+ return undefined;
132
+ })();
133
+ scheduleFlush(form, headName, castParams);
85
134
  unsubscribeRef.current = () => {
86
135
  unsubscribe();
87
- scheduleFlush(form);
136
+ scheduleFlush(form, headName);
88
137
  };
89
- }, [form, jsonDefaultValues, headName, name, schema === null || schema === void 0 ? void 0 : schema.default, schema === null || schema === void 0 ? void 0 : schema.type, schemaPath]);
138
+ }, [form, headName, name, schema === null || schema === void 0 ? void 0 : schema.default, schema === null || schema === void 0 ? void 0 : schema.type, schemaPath]);
90
139
  const input = React.useMemo(() => {
91
140
  var _a;
92
141
  const fieldState = form.getFieldState(name);
@@ -110,8 +159,12 @@ const SchemaRendererNodeComponent = ({ headName, modeOverride, name, schemaOverr
110
159
  };
111
160
  }, [error, form, name, ticks.meta]);
112
161
  React.useEffect(() => {
162
+ const strictChecker = strictCheckerRef.current;
113
163
  return () => {
114
164
  var _a;
165
+ if (strictChecker.isStrict()) {
166
+ return;
167
+ }
115
168
  (_a = unsubscribeRef.current) === null || _a === void 0 ? void 0 : _a.call(unsubscribeRef);
116
169
  };
117
170
  }, []);
@@ -1,6 +1,6 @@
1
1
  import type { FormApi } from 'final-form';
2
2
  import { SchemaRendererMode } from '../constants';
3
- import type { JsonSchema, NodeEntity, NodeLayout, NodesConfig } from '../types';
3
+ import type { FieldValue, JsonSchema, NodeEntity, NodeLayout, NodesConfig } from '../types';
4
4
  type GetRenderKitParams<Schema extends JsonSchema> = {
5
5
  config?: NodesConfig;
6
6
  schema?: Schema;
@@ -23,6 +23,9 @@ type GetRenderKitReturn<Schema extends JsonSchema> = {
23
23
  };
24
24
  export declare const getRenderKit: <Schema extends JsonSchema>({ config, schema, }: GetRenderKitParams<Schema>) => GetRenderKitReturn<Schema>;
25
25
  export declare const getAccumulatedSchema: (schemaPath: string, rootSchema?: JsonSchema, override?: JsonSchema, collectedPaths?: Set<string>) => JsonSchema;
26
- export declare const scheduleFlush: (form: FormApi) => void;
27
- export declare const getCompareValues: () => (currentValues: Record<string, unknown>) => boolean;
26
+ export declare const scheduleFlush: (form: FormApi, headName: string, change?: {
27
+ name: string;
28
+ value: FieldValue;
29
+ }) => void;
30
+ export declare const coerceToJsonSchemaType: (value: FieldValue, type?: JsonSchema["type"]) => FieldValue;
28
31
  export {};
@@ -1,8 +1,10 @@
1
1
  import get from 'lodash/get';
2
+ import isObjectLike from 'lodash/isObjectLike';
2
3
  import isString from 'lodash/isString';
3
4
  import set from 'lodash/set';
4
- import { EMPTY_OBJECT, SchemaRendererMode } from '../constants';
5
- import { getSchemaByPointer, getValuePaths } from '../utils';
5
+ import { EMPTY_OBJECT, JsonSchemaType, SchemaRendererMode } from '../constants';
6
+ import { SCHEMA_RENDERER_SERVICE_FIELD } from '../useSchemaRenderer';
7
+ import { getSchemaByPointer, getServiceFieldName, getValuePaths, isStringNumber } from '../utils';
6
8
  const fixType = (value) => value;
7
9
  const mergeValues = (first, second) => {
8
10
  const result = {};
@@ -155,24 +157,71 @@ export const getAccumulatedSchema = (schemaPath, rootSchema, override, collected
155
157
  return accumulatedSchema;
156
158
  };
157
159
  const flushes = new WeakMap();
158
- export const scheduleFlush = (form) => {
159
- if (flushes.get(form)) {
160
+ export const scheduleFlush = (form, headName, change) => {
161
+ const scheduled = flushes.get(form);
162
+ if (scheduled) {
163
+ scheduled.headNames.add(headName);
164
+ if (change) {
165
+ scheduled.changes.set(change.name, change.value);
166
+ }
160
167
  return;
161
168
  }
162
- flushes.set(form, true);
169
+ const changes = new Map();
170
+ const headNames = new Set([headName]);
171
+ if (change) {
172
+ changes.set(change.name, change.value);
173
+ }
174
+ flushes.set(form, { changes, headNames });
163
175
  queueMicrotask(() => {
164
176
  flushes.delete(form);
165
- form.batch(() => { });
177
+ form.batch(() => {
178
+ changes.forEach((value, name) => {
179
+ form.change(name, value);
180
+ });
181
+ });
182
+ headNames.forEach((name) => {
183
+ var _a;
184
+ const srName = getServiceFieldName(SCHEMA_RENDERER_SERVICE_FIELD, name);
185
+ const srField = form.getFieldState(srName);
186
+ const srState = (_a = srField === null || srField === void 0 ? void 0 : srField.data) === null || _a === void 0 ? void 0 : _a.state;
187
+ srState === null || srState === void 0 ? void 0 : srState.runValidate();
188
+ });
166
189
  });
167
190
  };
168
- export const getCompareValues = () => {
169
- let cachedValues;
170
- return (currentValues) => {
171
- if (!cachedValues ||
172
- [...Object.keys(cachedValues), ...Object.keys(currentValues)].some((key) => cachedValues[key] !== currentValues[key])) {
173
- cachedValues = Object.assign({}, currentValues);
191
+ // eslint-disable-next-line complexity
192
+ export const coerceToJsonSchemaType = (value, type) => {
193
+ if (value === undefined || value === null || !type) {
194
+ return value;
195
+ }
196
+ const typeArray = Array.isArray(type) ? type : [type];
197
+ if (typeArray.length &&
198
+ typeArray.some((t) => t === JsonSchemaType.Number || t === JsonSchemaType.Integer) &&
199
+ !typeArray.filter((t) => t !== JsonSchemaType.Number &&
200
+ t !== JsonSchemaType.Integer &&
201
+ t !== JsonSchemaType.Null).length) {
202
+ if (isStringNumber(value)) {
203
+ return Number(value);
204
+ }
205
+ return value;
206
+ }
207
+ if (typeArray.length &&
208
+ typeArray.some((t) => t === JsonSchemaType.Boolean) &&
209
+ !typeArray.filter((t) => t !== JsonSchemaType.Boolean && t !== JsonSchemaType.Null).length) {
210
+ if (value === 'true' || value === 1) {
211
+ return true;
212
+ }
213
+ if (value === 'false' || value === 0) {
174
214
  return false;
175
215
  }
176
- return true;
177
- };
216
+ return value;
217
+ }
218
+ if (typeArray.length &&
219
+ typeArray.some((t) => t === JsonSchemaType.String) &&
220
+ !typeArray.filter((t) => t !== JsonSchemaType.String && t !== JsonSchemaType.Null).length) {
221
+ if (!(typeof value === 'string' || isObjectLike(value))) {
222
+ return String(value);
223
+ }
224
+ return value;
225
+ }
226
+ return value;
178
227
  };
@@ -5,4 +5,4 @@ export type * from './types';
5
5
  export { SCHEMA_RENDERER_SERVICE_FIELD, type SchemaRendererState, type SchemaPatch, type SchemaPatchRemover, type UseSchemaRendererParams, useSchemaRenderer, } from './useSchemaRenderer';
6
6
  export { type UseSchemaRendererStateParams, useSchemaRendererState } from './useSchemaRendererState';
7
7
  export { useSchemaRendererTools } from './useSchemaRendererTools';
8
- export { createNodeParametersDefiner, defineNodeEntityConfig, defineNodeLayoutConfig, getServiceFieldName, getSchemaByPointer, } from './utils';
8
+ export { createNodeParametersDefiner, defineNodeEntityConfig, defineNodeLayoutConfig, getServiceFieldName, getSchemaByPointer, isStringFloat, isStringInt, isStringNumber, } from './utils';
@@ -4,4 +4,4 @@ export { NodeType, JsonSchemaType, SchemaRendererEventType, SchemaRendererMode }
4
4
  export { SCHEMA_RENDERER_SERVICE_FIELD, useSchemaRenderer, } from './useSchemaRenderer';
5
5
  export { useSchemaRendererState } from './useSchemaRendererState';
6
6
  export { useSchemaRendererTools } from './useSchemaRendererTools';
7
- export { createNodeParametersDefiner, defineNodeEntityConfig, defineNodeLayoutConfig, getServiceFieldName, getSchemaByPointer, } from './utils';
7
+ export { createNodeParametersDefiner, defineNodeEntityConfig, defineNodeLayoutConfig, getServiceFieldName, getSchemaByPointer, isStringFloat, isStringInt, isStringNumber, } from './utils';
@@ -18,6 +18,7 @@ export interface SchemaRendererState<UserContext extends Record<string, unknown>
18
18
  runValidate: () => void;
19
19
  schema: JsonSchema;
20
20
  settings: {
21
+ coerceInitialValues: boolean;
21
22
  jsonDefaultValues: boolean;
22
23
  };
23
24
  subscribe: (subscriber: SchemaRendererSubscriber) => string;
@@ -3,6 +3,7 @@ import { type SchemaRendererMode } from '../constants';
3
3
  import type { ErrorMessages, FieldValue, JsonSchema, NodesConfig } from '../types';
4
4
  import type { SchemaRendererState } from './types';
5
5
  export interface UseSchemaRendererParams {
6
+ coerceInitialValues?: boolean;
6
7
  config?: NodesConfig;
7
8
  connectValidate?: boolean;
8
9
  errorMessages?: ErrorMessages;
@@ -13,4 +14,4 @@ export interface UseSchemaRendererParams {
13
14
  validateOnBlur: boolean;
14
15
  userContext?: SchemaRendererState['userContext'];
15
16
  }
16
- export declare const useSchemaRenderer: ({ config, connectValidate, errorMessages, jsonDefaultValues, mode, name: headName, schema: originalSchema, validateOnBlur, userContext, }: UseSchemaRendererParams) => FieldValidator<FieldValue>;
17
+ export declare const useSchemaRenderer: ({ coerceInitialValues, config, connectValidate, errorMessages, jsonDefaultValues, mode, name: headName, schema: originalSchema, validateOnBlur, userContext, }: UseSchemaRendererParams) => FieldValidator<FieldValue>;
@@ -3,11 +3,12 @@ import React from 'react';
3
3
  import cloneDeep from 'lodash/cloneDeep';
4
4
  import { useForm } from 'react-final-form';
5
5
  import { SchemaRendererEventType } from '../constants';
6
- import { getServiceFieldName } from '../utils';
6
+ import { getServiceFieldName, getStrictModeChecker } from '../utils';
7
7
  import { SCHEMA_RENDERER_SERVICE_FIELD } from './constants';
8
8
  import { getDispatch, getRunValidate, getSubscribe, getValidate } from './utils';
9
- export const useSchemaRenderer = ({ config, connectValidate = true, errorMessages, jsonDefaultValues = false, mode, name: headName, schema: originalSchema, validateOnBlur, userContext, }) => {
9
+ export const useSchemaRenderer = ({ coerceInitialValues = true, config, connectValidate = true, errorMessages, jsonDefaultValues = false, mode, name: headName, schema: originalSchema, validateOnBlur, userContext, }) => {
10
10
  const form = useForm();
11
+ const strictCheckerRef = React.useRef(getStrictModeChecker());
11
12
  const stateRef = React.useRef(null);
12
13
  const prevParamsRef = React.useRef(null);
13
14
  const unsubscribeRef = React.useRef(null);
@@ -15,9 +16,7 @@ export const useSchemaRenderer = ({ config, connectValidate = true, errorMessage
15
16
  const dispatchEvent = React.useMemo(() => getDispatch(form, headName), [form, headName]);
16
17
  const runValidate = React.useMemo(() => getRunValidate(form, headName, validateOnBlur), [form, headName, validateOnBlur]);
17
18
  const validate = React.useMemo(() => getValidate(form, headName), [form, headName]);
18
- const unsubscribeField = React.useMemo(() => {
19
- var _a;
20
- (_a = unsubscribeRef.current) === null || _a === void 0 ? void 0 : _a.call(unsubscribeRef);
19
+ const { initialEvents, initialState } = React.useMemo(() => {
21
20
  const prevParams = prevParamsRef.current;
22
21
  const prevState = stateRef.current;
23
22
  const configUpdated = config !== (prevParams === null || prevParams === void 0 ? void 0 : prevParams.config);
@@ -26,7 +25,8 @@ export const useSchemaRenderer = ({ config, connectValidate = true, errorMessage
26
25
  const modeUpdated = mode !== (prevParams === null || prevParams === void 0 ? void 0 : prevParams.mode);
27
26
  const schemaUpdated = originalSchema !== (prevParams === null || prevParams === void 0 ? void 0 : prevParams.schema);
28
27
  const userContextUpdated = userContext !== (prevParams === null || prevParams === void 0 ? void 0 : prevParams.userContext);
29
- const settingsUpdated = jsonDefaultValues !== (prevParams === null || prevParams === void 0 ? void 0 : prevParams.jsonDefaultValues);
28
+ const settingsUpdated = coerceInitialValues !== (prevParams === null || prevParams === void 0 ? void 0 : prevParams.coerceInitialValues) ||
29
+ jsonDefaultValues !== (prevParams === null || prevParams === void 0 ? void 0 : prevParams.jsonDefaultValues);
30
30
  const initialState = {
31
31
  cache: nameUpdated || schemaUpdated || !(prevState === null || prevState === void 0 ? void 0 : prevState.cache) ? {} : prevState.cache,
32
32
  config: config || {},
@@ -43,7 +43,7 @@ export const useSchemaRenderer = ({ config, connectValidate = true, errorMessage
43
43
  ? {}
44
44
  : prevState.regularErrors,
45
45
  runValidate,
46
- settings: { jsonDefaultValues },
46
+ settings: { coerceInitialValues, jsonDefaultValues },
47
47
  schema: nameUpdated || schemaUpdated ? cloneDeep(originalSchema) : (prevState === null || prevState === void 0 ? void 0 : prevState.schema) || {},
48
48
  subscribe,
49
49
  subscribers: (prevState === null || prevState === void 0 ? void 0 : prevState.subscribers) || { byId: {}, byName: new Map(), byPath: new Map() },
@@ -51,8 +51,7 @@ export const useSchemaRenderer = ({ config, connectValidate = true, errorMessage
51
51
  userContext: userContextUpdated ? userContext || {} : (prevState === null || prevState === void 0 ? void 0 : prevState.userContext) || {},
52
52
  waiters: nameUpdated || schemaUpdated || !(prevState === null || prevState === void 0 ? void 0 : prevState.waiters) ? {} : prevState.waiters,
53
53
  };
54
- const getValidator = connectValidate ? () => validate : undefined;
55
- let initialEvents = [
54
+ const initialEvents = [
56
55
  ...(configUpdated ? [SchemaRendererEventType.Config] : []),
57
56
  ...(errorMessagesUpdated ? [SchemaRendererEventType.ErrorMessages] : []),
58
57
  ...(nameUpdated ? [SchemaRendererEventType.Name] : []),
@@ -61,15 +60,8 @@ export const useSchemaRenderer = ({ config, connectValidate = true, errorMessage
61
60
  ...(userContextUpdated ? [SchemaRendererEventType.UserContext] : []),
62
61
  ...(settingsUpdated ? [SchemaRendererEventType.Settings] : []),
63
62
  ].map((type) => ({ type, all: true }));
64
- unsubscribeRef.current = form.registerField(getServiceFieldName(SCHEMA_RENDERER_SERVICE_FIELD, headName), (f) => {
65
- var _a;
66
- const state = (_a = f.data) === null || _a === void 0 ? void 0 : _a.state;
67
- if (state && initialEvents.length) {
68
- state.dispatchEvent(initialEvents);
69
- initialEvents = [];
70
- }
71
- }, { data: true }, { data: { state: initialState }, getValidator, silent: true, validateFields: [headName] });
72
63
  prevParamsRef.current = {
64
+ coerceInitialValues,
73
65
  config,
74
66
  errorMessages,
75
67
  jsonDefaultValues,
@@ -80,13 +72,12 @@ export const useSchemaRenderer = ({ config, connectValidate = true, errorMessage
80
72
  validateOnBlur,
81
73
  };
82
74
  stateRef.current = initialState;
83
- return unsubscribeRef.current;
75
+ return { initialEvents, initialState };
84
76
  }, [
77
+ coerceInitialValues,
85
78
  config,
86
- connectValidate,
87
79
  dispatchEvent,
88
80
  errorMessages,
89
- form,
90
81
  jsonDefaultValues,
91
82
  headName,
92
83
  mode,
@@ -94,16 +85,42 @@ export const useSchemaRenderer = ({ config, connectValidate = true, errorMessage
94
85
  runValidate,
95
86
  subscribe,
96
87
  unsubscribe,
97
- validate,
98
88
  validateOnBlur,
99
89
  userContext,
100
90
  ]);
91
+ React.useMemo(() => {
92
+ var _a;
93
+ if (!strictCheckerRef.current.checkDiff({
94
+ connectValidate,
95
+ form,
96
+ headName,
97
+ validate,
98
+ })) {
99
+ return;
100
+ }
101
+ const getValidator = connectValidate ? () => validate : undefined;
102
+ (_a = unsubscribeRef.current) === null || _a === void 0 ? void 0 : _a.call(unsubscribeRef);
103
+ unsubscribeRef.current = form.registerField(getServiceFieldName(SCHEMA_RENDERER_SERVICE_FIELD, headName), () => { }, { data: true }, {
104
+ data: { state: stateRef.current },
105
+ getValidator,
106
+ silent: true,
107
+ validateFields: [headName],
108
+ });
109
+ }, [connectValidate, form, headName, validate]);
101
110
  React.useEffect(() => {
102
- runValidate();
103
- }, [unsubscribeField]);
111
+ const srField = form.getFieldState(getServiceFieldName(SCHEMA_RENDERER_SERVICE_FIELD, headName));
112
+ if (srField === null || srField === void 0 ? void 0 : srField.data) {
113
+ srField.data.state = initialState;
114
+ initialState.dispatchEvent(initialEvents);
115
+ }
116
+ }, [initialEvents, initialState]);
104
117
  React.useEffect(() => {
118
+ const strictChecker = strictCheckerRef.current;
105
119
  return () => {
106
120
  var _a;
121
+ if (strictChecker.isStrict()) {
122
+ return;
123
+ }
107
124
  (_a = unsubscribeRef.current) === null || _a === void 0 ? void 0 : _a.call(unsubscribeRef);
108
125
  };
109
126
  }, []);
@@ -66,7 +66,12 @@ export const getValidate = (form, headName) => {
66
66
  Object.keys(Object.assign(Object.assign({}, srState.errors), allErrors)).forEach((key) => {
67
67
  if (srState.errors[key] !== allErrors[key]) {
68
68
  newErrors[key] = allErrors[key];
69
- srState.errors[key] = allErrors[key];
69
+ if (allErrors[key] === undefined) {
70
+ delete srState.errors[key];
71
+ }
72
+ else {
73
+ srState.errors[key] = allErrors[key];
74
+ }
70
75
  }
71
76
  });
72
77
  srState.waiters = Object.assign(Object.assign({}, srState.waiters), waiters);