@gravity-ui/dynamic-forms 5.25.0 → 5.27.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 (59) hide show
  1. package/build/cjs/lib/unstable/core/SchemaRendererNode/SchemaRendererNode.js +61 -16
  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 +40 -19
  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/Alert/Alert.js +3 -3
  19. package/build/cjs/lib/unstable/kit/entities/FewOfNested/FewOfNested.js +6 -1
  20. package/build/cjs/lib/unstable/kit/entities/OneOfNested/OneOfNested.js +12 -2
  21. package/build/cjs/lib/unstable/kit/form-entities/StringNumberWithScaleInput/StringNumberWithScaleInput.d.ts +1 -1
  22. package/build/cjs/lib/unstable/kit/form-entities/StringNumberWithScaleInput/StringNumberWithScaleInput.js +8 -7
  23. package/build/cjs/lib/unstable/kit/overview-entities/StringNumberWithScaleValue/StringNumberWithScaleValue.d.ts +1 -1
  24. package/build/cjs/lib/unstable/kit/overview-entities/StringNumberWithScaleValue/StringNumberWithScaleValue.js +5 -5
  25. package/build/cjs/lib/unstable/kit/utils/common.d.ts +0 -3
  26. package/build/cjs/lib/unstable/kit/utils/common.js +1 -7
  27. package/build/cjs/lib/unstable/kit/utils/index.d.ts +1 -1
  28. package/build/cjs/lib/unstable/kit/utils/index.js +1 -4
  29. package/build/cjs/lib/unstable/kit/utils/transformer.js +10 -2
  30. package/build/esm/lib/unstable/core/SchemaRendererNode/SchemaRendererNode.js +64 -19
  31. package/build/esm/lib/unstable/core/SchemaRendererNode/utils.d.ts +6 -3
  32. package/build/esm/lib/unstable/core/SchemaRendererNode/utils.js +63 -14
  33. package/build/esm/lib/unstable/core/index.d.ts +1 -1
  34. package/build/esm/lib/unstable/core/index.js +1 -1
  35. package/build/esm/lib/unstable/core/useSchemaRenderer/types/state.d.ts +1 -0
  36. package/build/esm/lib/unstable/core/useSchemaRenderer/useSchemaRenderer.d.ts +2 -1
  37. package/build/esm/lib/unstable/core/useSchemaRenderer/useSchemaRenderer.js +41 -20
  38. package/build/esm/lib/unstable/core/useSchemaRenderer/utils/get-validate.js +6 -1
  39. package/build/esm/lib/unstable/core/useSchemaRendererState/useSchemaRendererState.js +15 -1
  40. package/build/esm/lib/unstable/core/utils/common.d.ts +3 -0
  41. package/build/esm/lib/unstable/core/utils/common.js +3 -0
  42. package/build/esm/lib/unstable/core/utils/index.d.ts +1 -0
  43. package/build/esm/lib/unstable/core/utils/index.js +1 -0
  44. package/build/esm/lib/unstable/core/utils/strict-mode.d.ts +6 -0
  45. package/build/esm/lib/unstable/core/utils/strict-mode.js +26 -0
  46. package/build/esm/lib/unstable/kit/components/EntityError/EntityError.js +1 -1
  47. package/build/esm/lib/unstable/kit/entities/Alert/Alert.js +3 -3
  48. package/build/esm/lib/unstable/kit/entities/FewOfNested/FewOfNested.js +6 -1
  49. package/build/esm/lib/unstable/kit/entities/OneOfNested/OneOfNested.js +12 -2
  50. package/build/esm/lib/unstable/kit/form-entities/StringNumberWithScaleInput/StringNumberWithScaleInput.d.ts +1 -1
  51. package/build/esm/lib/unstable/kit/form-entities/StringNumberWithScaleInput/StringNumberWithScaleInput.js +2 -1
  52. package/build/esm/lib/unstable/kit/overview-entities/StringNumberWithScaleValue/StringNumberWithScaleValue.d.ts +1 -1
  53. package/build/esm/lib/unstable/kit/overview-entities/StringNumberWithScaleValue/StringNumberWithScaleValue.js +1 -1
  54. package/build/esm/lib/unstable/kit/utils/common.d.ts +0 -3
  55. package/build/esm/lib/unstable/kit/utils/common.js +0 -3
  56. package/build/esm/lib/unstable/kit/utils/index.d.ts +1 -1
  57. package/build/esm/lib/unstable/kit/utils/index.js +1 -1
  58. package/build/esm/lib/unstable/kit/utils/transformer.js +10 -2
  59. package/package.json +1 -1
@@ -2,14 +2,24 @@ import React from 'react';
2
2
  import { useForm } from 'react-final-form';
3
3
  import { SchemaRendererEventType } from '../constants';
4
4
  import { SCHEMA_RENDERER_SERVICE_FIELD } from '../useSchemaRenderer';
5
- import { getSchemaByPointer, getServiceFieldName } from '../utils';
5
+ import { getSchemaByPointer, getServiceFieldName, getStrictModeChecker } from '../utils';
6
6
  export const useSchemaRendererState = ({ headName, name, schemaPath, subscriptions = Object.values(SchemaRendererEventType), }) => {
7
7
  const form = useForm();
8
+ const strictCheckerRef = React.useRef(getStrictModeChecker());
8
9
  const uuidRef = React.useRef(null);
9
10
  const [tick, setTick] = React.useState(0);
10
11
  const srName = React.useMemo(() => getServiceFieldName(SCHEMA_RENDERER_SERVICE_FIELD, headName), [headName]);
11
12
  React.useMemo(() => {
12
13
  var _a;
14
+ if (!strictCheckerRef.current.checkDiff({
15
+ form,
16
+ headName,
17
+ name,
18
+ schemaPath,
19
+ subscriptions: subscriptions.join(','),
20
+ })) {
21
+ return;
22
+ }
13
23
  const srField = form.getFieldState(srName);
14
24
  const srState = (_a = srField === null || srField === void 0 ? void 0 : srField.data) === null || _a === void 0 ? void 0 : _a.state;
15
25
  if (srState) {
@@ -44,8 +54,12 @@ export const useSchemaRendererState = ({ headName, name, schemaPath, subscriptio
44
54
  return undefined;
45
55
  }, [form, srName, tick]);
46
56
  React.useEffect(() => {
57
+ const strictChecker = strictCheckerRef.current;
47
58
  return () => {
48
59
  var _a;
60
+ if (strictChecker.isStrict()) {
61
+ return;
62
+ }
49
63
  const srField = form.getFieldState(srName);
50
64
  const srState = (_a = srField === null || srField === void 0 ? void 0 : srField.data) === null || _a === void 0 ? void 0 : _a.state;
51
65
  if (srState && uuidRef.current) {
@@ -58,3 +58,6 @@ export declare const arrayPathToDotBracket: (arrayPath: string[]) => string;
58
58
  export declare const getSchemaByPointer: (schema: JsonSchema, pointer: string | string[]) => JsonSchema | undefined;
59
59
  export declare const getValuePaths: (value: unknown, path?: string[]) => string[][];
60
60
  export declare const getServiceFieldName: (serviceFieldName: string, headName: string) => string;
61
+ export declare const isStringInt: (v: unknown) => v is string;
62
+ export declare const isStringFloat: (v: unknown) => v is string;
63
+ export declare const isStringNumber: (v: unknown) => v is string;
@@ -106,3 +106,6 @@ export const getValuePaths = (value, path = []) => {
106
106
  return result;
107
107
  };
108
108
  export const getServiceFieldName = (serviceFieldName, headName) => headName ? `${serviceFieldName}.${headName}` : serviceFieldName;
109
+ export const isStringInt = (v) => /^-?(0|[1-9][0-9]*)$/.test(`${v}`);
110
+ export const isStringFloat = (v) => /^-?(0|[1-9][0-9]*)(\.[0-9]+)?$/.test(`${v}`);
111
+ export const isStringNumber = (v) => isStringInt(v) || isStringFloat(v);
@@ -1,2 +1,3 @@
1
1
  export * from './common';
2
2
  export * from './definers';
3
+ export * from './strict-mode';
@@ -1,2 +1,3 @@
1
1
  export * from './common';
2
2
  export * from './definers';
3
+ export * from './strict-mode';
@@ -0,0 +1,6 @@
1
+ export declare const getStrictModeChecker: () => {
2
+ cachedValues: Record<string, unknown> | undefined;
3
+ hasDiff: boolean | undefined;
4
+ checkDiff: (currentValues: Record<string, unknown>) => boolean;
5
+ isStrict: () => boolean | undefined;
6
+ };
@@ -0,0 +1,26 @@
1
+ export const getStrictModeChecker = () => {
2
+ const checker = {
3
+ cachedValues: undefined,
4
+ hasDiff: undefined,
5
+ checkDiff: (currentValues) => {
6
+ const cachedValues = checker.cachedValues;
7
+ if (!cachedValues ||
8
+ [...Object.keys(cachedValues), ...Object.keys(currentValues)].some((key) => cachedValues[key] !== currentValues[key])) {
9
+ checker.cachedValues = Object.assign({}, currentValues);
10
+ checker.hasDiff = true;
11
+ return true;
12
+ }
13
+ checker.hasDiff = false;
14
+ return false;
15
+ },
16
+ isStrict: () => {
17
+ if (checker.hasDiff === undefined) {
18
+ return undefined;
19
+ }
20
+ const hasDiff = checker.hasDiff;
21
+ checker.hasDiff = undefined;
22
+ return !hasDiff;
23
+ },
24
+ };
25
+ return checker;
26
+ };
@@ -5,7 +5,7 @@ import './EntityError.css';
5
5
  const b = block('entity-error');
6
6
  export const EntityError = ({ errorMessage, validationState }) => {
7
7
  if (validationState === 'invalid' && errorMessage) {
8
- return (React.createElement(Text, { className: b(), color: "danger" }, errorMessage));
8
+ return (React.createElement(Text, { className: b(), color: "danger", wordBreak: "break-word", "data-sr-error": "true" }, errorMessage));
9
9
  }
10
10
  return null;
11
11
  };
@@ -27,17 +27,17 @@ export const Alert = ({ headName, props, schema }) => {
27
27
  const msg = React.useMemo(() => {
28
28
  if (message) {
29
29
  if (typeof message === 'string') {
30
- return (React.createElement("div", { className: b('message', { expanded }) },
30
+ return (React.createElement("div", { className: b('message', { expanded: expanded || !title }) },
31
31
  React.createElement(HTMLContent, { content: message, headName: headName })));
32
32
  }
33
33
  return message;
34
34
  }
35
35
  if (schema.description) {
36
- return (React.createElement("div", { className: b('message', { expanded }) },
36
+ return (React.createElement("div", { className: b('message', { expanded: expanded || !title }) },
37
37
  React.createElement(HTMLContent, { content: schema.description, headName: headName })));
38
38
  }
39
39
  return undefined;
40
- }, [expanded, headName, message, schema.description]);
40
+ }, [expanded, headName, message, schema.description, title]);
41
41
  return (React.createElement(EntityContainer, { className: b({ expanded }), stretch: "fit", fill: "populated" },
42
42
  React.createElement(UIKitAlert, Object.assign({ icon: icon, message: msg, title: title }, entityRestProps))));
43
43
  };
@@ -28,7 +28,12 @@ export const FewOfNested = ({ Layout, headName, input, layoutProps, meta, mode,
28
28
  const { Entity, Layout, entityProps, independent, layoutProps } = renderKit[mode];
29
29
  const togglerInput = Object.assign(Object.assign({}, input), { name: togglerArrayRemoveButton ? name : `${name}._____toggler`, value: togglerValues, onChange: (value) => {
30
30
  if (Array.isArray(value)) {
31
- setTogglerValues(value.filter(isString));
31
+ const nextTogglerValues = value.filter(isString);
32
+ setTogglerValues(nextTogglerValues);
33
+ input.onChange(nextTogglerValues.reduce((acc, togglerValue) => {
34
+ var _a;
35
+ return (Object.assign(Object.assign({}, acc), { [togglerValue]: (_a = input.value) === null || _a === void 0 ? void 0 : _a[togglerValue] }));
36
+ }, {}));
32
37
  }
33
38
  } });
34
39
  const togglerMeta = Object.assign(Object.assign({}, meta), { error: undefined });
@@ -12,7 +12,15 @@ export const OneOfNested = ({ Layout, headName, input, layoutProps, meta, mode,
12
12
  headName,
13
13
  subscriptions: [SchemaRendererEventType.Config],
14
14
  });
15
- const [togglerValue, setTogglerValue] = React.useState(Object.keys(value || (overviewFlag ? undefined : schema.properties) || {})[0]);
15
+ const [togglerValue, setTogglerValue] = React.useState(() => {
16
+ if (value && Object.keys(value).length) {
17
+ return Object.keys(value)[0];
18
+ }
19
+ if (!overviewFlag && schema.properties) {
20
+ return Object.keys(schema.properties)[0];
21
+ }
22
+ return undefined;
23
+ });
16
24
  const toggler = React.useMemo(() => {
17
25
  var _a;
18
26
  let result = null;
@@ -24,7 +32,9 @@ export const OneOfNested = ({ Layout, headName, input, layoutProps, meta, mode,
24
32
  ? booleanToKey.true === togglerValue
25
33
  : togglerValue, onChange: (value) => {
26
34
  const nextValue = `${value}`;
27
- setTogglerValue((booleanToKey === null || booleanToKey === void 0 ? void 0 : booleanToKey[nextValue]) || nextValue);
35
+ const nextTogglerValue = (booleanToKey === null || booleanToKey === void 0 ? void 0 : booleanToKey[nextValue]) || nextValue;
36
+ setTogglerValue(nextTogglerValue);
37
+ input.onChange({ [nextTogglerValue]: undefined });
28
38
  } });
29
39
  const togglerMeta = Object.assign(Object.assign({}, meta), { error: undefined });
30
40
  if (Entity) {
@@ -1,5 +1,5 @@
1
1
  import { type TextInputProps } from '@gravity-ui/uikit';
2
- import type { JsonSchemaString, NodeEntity } from '../../../core';
2
+ import { type JsonSchemaString, type NodeEntity } from '../../../core';
3
3
  import './StringNumberWithScaleInput.css';
4
4
  export interface StringNumberWithScaleInputProps extends Omit<TextInputProps, 'defaultValue' | 'value' | 'onFocus' | 'onBlur' | 'onChange' | 'onUpdate' | 'errorMessage' | 'validationState' | 'qa'> {
5
5
  defaultType?: string;
@@ -2,8 +2,9 @@ import { __rest } from "tslib";
2
2
  import React from 'react';
3
3
  import { Select, TextInput } from '@gravity-ui/uikit';
4
4
  import Decimal from 'decimal.js';
5
+ import { isStringNumber } from '../../../core';
5
6
  import { EntityContainer } from '../../components';
6
- import { block, getBooleanValidationState, getValidationState, isStringNumber } from '../../utils';
7
+ import { block, getBooleanValidationState, getValidationState } from '../../utils';
7
8
  import './StringNumberWithScaleInput.css';
8
9
  const b = block('string-number-with-scale-input');
9
10
  export const StringNumberWithScaleInput = ({ input, meta, props, schema }) => {
@@ -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, {
@@ -3,8 +3,8 @@ import React from 'react';
3
3
  import { Text } from '@gravity-ui/uikit';
4
4
  import Decimal from 'decimal.js';
5
5
  import get from 'lodash/get';
6
+ import { isStringNumber } from '../../../core';
6
7
  import { EmptyEntityValue, EntityContainer, LongValue } from '../../components';
7
- import { isStringNumber } from '../../utils';
8
8
  export const StringNumberWithScaleValue = ({ input, props }) => {
9
9
  const { scale, viewType } = props, restProps = __rest(props, ["scale", "viewType"]);
10
10
  const level = React.useMemo(() => {
@@ -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;
@@ -28,6 +28,3 @@ export const isTupleItem = (name, headName, form) => {
28
28
  const parentSchema = getSchemaByPointer(srState.schema, parentState.schemaPath);
29
29
  return parentSchema && 'items' in parentSchema && Array.isArray(parentSchema.items);
30
30
  };
31
- export const isStringInt = (v) => /^-?(0|[1-9][0-9]*)$/.test(`${v}`);
32
- export const isStringFloat = (v) => /^-?(0|[1-9][0-9]*)(\.[0-9]+)?$/.test(`${v}`);
33
- export const isStringNumber = (v) => isStringInt(v) || isStringFloat(v);
@@ -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,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';
@@ -3,7 +3,6 @@ import isObject from 'lodash/isObject';
3
3
  import set from 'lodash/set';
4
4
  import { SpecTypes } from '../../../core';
5
5
  import { JsonSchemaType, NodeType } from '../../core';
6
- import { errorMessages as defaultErrorMessages } from '../constants';
7
6
  const viewSpecRules = {
8
7
  disabled: (spec, mutableSchema) => {
9
8
  if (spec.viewSpec.disabled) {
@@ -660,6 +659,15 @@ const specRules = {
660
659
  Object.entries(spec.properties).forEach(([key, childSpec]) => {
661
660
  const childSchema = specToJsonSchema(childSpec, Object.assign({}, (get(mutableSchema, ['properties', key]) || {})), rules, errorMessages);
662
661
  set(mutableSchema, ['properties', key], childSchema);
662
+ if (childSpec.required &&
663
+ !(spec.viewSpec.type === 'oneof' ||
664
+ spec.viewSpec.type === 'oneof_flat' ||
665
+ spec.viewSpec.type === 'card_oneof' ||
666
+ spec.viewSpec.type === 'multi_oneof' ||
667
+ spec.viewSpec.type === 'multi_oneof_flat')) {
668
+ set(mutableSchema, ['required'], [...(get(mutableSchema, 'required') || []), key]);
669
+ set(mutableSchema, 'nodeParameters.errorMessages.required', errorMessages.required);
670
+ }
663
671
  });
664
672
  }
665
673
  },
@@ -677,7 +685,7 @@ const specRules = {
677
685
  Object.values(rules.viewSpecRules).forEach((rule) => rule(spec, mutableSchema, rules, errorMessages));
678
686
  },
679
687
  };
680
- export function specToJsonSchema(spec, mutableSchema = {}, rules, errorMessages = defaultErrorMessages) {
688
+ export function specToJsonSchema(spec, mutableSchema = {}, rules, errorMessages = {}) {
681
689
  const mergedSpecRules = Object.assign(Object.assign({}, specRules), rules === null || rules === void 0 ? void 0 : rules.specRules);
682
690
  const mergedViewSpecRules = Object.assign(Object.assign({}, viewSpecRules), rules === null || rules === void 0 ? void 0 : rules.viewSpecRules);
683
691
  Object.values(mergedSpecRules).forEach((rule) => rule(spec, mutableSchema, { specRules: mergedSpecRules, viewSpecRules: mergedViewSpecRules }, errorMessages));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dynamic-forms",
3
- "version": "5.25.0",
3
+ "version": "5.27.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "main": "build/cjs/index.js",