@gravity-ui/dynamic-forms 5.29.2 → 5.32.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 (63) hide show
  1. package/build/cjs/lib/unstable/core/constants.d.ts +1 -0
  2. package/build/cjs/lib/unstable/core/constants.js +1 -0
  3. package/build/cjs/lib/unstable/core/useSchemaRenderer/types/state.d.ts +1 -0
  4. package/build/cjs/lib/unstable/core/useSchemaRenderer/useSchemaRenderer.js +17 -0
  5. package/build/cjs/lib/unstable/kit/components/EntityContainer/EntityContainer.d.ts +1 -0
  6. package/build/cjs/lib/unstable/kit/constants/config.d.ts +4 -2
  7. package/build/cjs/lib/unstable/kit/constants/config.js +4 -4
  8. package/build/cjs/lib/unstable/kit/entities/FewOfNested/FewOfNested.d.ts +1 -0
  9. package/build/cjs/lib/unstable/kit/entities/FewOfNested/FewOfNested.js +8 -3
  10. package/build/cjs/lib/unstable/kit/entities/ObjectEntity/ObjectEntity.js +8 -5
  11. package/build/cjs/lib/unstable/kit/entities/ObjectInline/ObjectInline.js +1 -1
  12. package/build/cjs/lib/unstable/kit/entities/OneOfNested/OneOfNested.d.ts +1 -0
  13. package/build/cjs/lib/unstable/kit/entities/OneOfNested/OneOfNested.js +9 -4
  14. package/build/cjs/lib/unstable/kit/form-entities/NumberWithScaleInput/NumberWithScaleInput.js +1 -1
  15. package/build/cjs/lib/unstable/kit/form-entities/RangeInput/RangeInput.js +2 -2
  16. package/build/cjs/lib/unstable/kit/form-entities/SegmentedRadioGroupInput/SegmentedRadioGroupInput.css +9 -4
  17. package/build/cjs/lib/unstable/kit/form-entities/SegmentedRadioGroupInput/SegmentedRadioGroupInput.js +14 -15
  18. package/build/cjs/lib/unstable/kit/form-entities/StringNumberWithScaleInput/StringNumberWithScaleInput.js +1 -1
  19. package/build/cjs/lib/unstable/kit/form-entities/TextAreaInput/TextAreaInput.js +1 -1
  20. package/build/cjs/lib/unstable/kit/form-layouts/FormColumn/FormColumn.js +1 -1
  21. package/build/cjs/lib/unstable/kit/form-layouts/FormRow/FormRow.js +1 -1
  22. package/build/cjs/lib/unstable/kit/hooks/index.d.ts +1 -0
  23. package/build/cjs/lib/unstable/kit/hooks/index.js +5 -0
  24. package/build/cjs/lib/unstable/kit/hooks/useExpanded.d.ts +11 -0
  25. package/build/cjs/lib/unstable/kit/hooks/useExpanded.js +25 -0
  26. package/build/cjs/lib/unstable/kit/index.d.ts +1 -0
  27. package/build/cjs/lib/unstable/kit/index.js +1 -0
  28. package/build/cjs/lib/unstable/kit/layouts/Accordeon/Accordeon.js +4 -2
  29. package/build/cjs/lib/unstable/kit/layouts/Card/Card.js +11 -9
  30. package/build/cjs/lib/unstable/kit/layouts/Section/Section.js +1 -1
  31. package/build/cjs/lib/unstable/kit/utils/transformer.js +18 -3
  32. package/build/esm/lib/unstable/core/constants.d.ts +1 -0
  33. package/build/esm/lib/unstable/core/constants.js +1 -0
  34. package/build/esm/lib/unstable/core/useSchemaRenderer/types/state.d.ts +1 -0
  35. package/build/esm/lib/unstable/core/useSchemaRenderer/useSchemaRenderer.js +17 -0
  36. package/build/esm/lib/unstable/kit/components/EntityContainer/EntityContainer.d.ts +1 -0
  37. package/build/esm/lib/unstable/kit/constants/config.d.ts +4 -2
  38. package/build/esm/lib/unstable/kit/constants/config.js +4 -4
  39. package/build/esm/lib/unstable/kit/entities/FewOfNested/FewOfNested.d.ts +1 -0
  40. package/build/esm/lib/unstable/kit/entities/FewOfNested/FewOfNested.js +8 -3
  41. package/build/esm/lib/unstable/kit/entities/ObjectEntity/ObjectEntity.js +10 -7
  42. package/build/esm/lib/unstable/kit/entities/ObjectInline/ObjectInline.js +1 -1
  43. package/build/esm/lib/unstable/kit/entities/OneOfNested/OneOfNested.d.ts +1 -0
  44. package/build/esm/lib/unstable/kit/entities/OneOfNested/OneOfNested.js +9 -4
  45. package/build/esm/lib/unstable/kit/form-entities/NumberWithScaleInput/NumberWithScaleInput.js +1 -1
  46. package/build/esm/lib/unstable/kit/form-entities/RangeInput/RangeInput.js +2 -2
  47. package/build/esm/lib/unstable/kit/form-entities/SegmentedRadioGroupInput/SegmentedRadioGroupInput.css +9 -4
  48. package/build/esm/lib/unstable/kit/form-entities/SegmentedRadioGroupInput/SegmentedRadioGroupInput.js +14 -15
  49. package/build/esm/lib/unstable/kit/form-entities/StringNumberWithScaleInput/StringNumberWithScaleInput.js +1 -1
  50. package/build/esm/lib/unstable/kit/form-entities/TextAreaInput/TextAreaInput.js +1 -1
  51. package/build/esm/lib/unstable/kit/form-layouts/FormColumn/FormColumn.js +1 -1
  52. package/build/esm/lib/unstable/kit/form-layouts/FormRow/FormRow.js +1 -1
  53. package/build/esm/lib/unstable/kit/hooks/index.d.ts +1 -0
  54. package/build/esm/lib/unstable/kit/hooks/index.js +1 -0
  55. package/build/esm/lib/unstable/kit/hooks/useExpanded.d.ts +11 -0
  56. package/build/esm/lib/unstable/kit/hooks/useExpanded.js +20 -0
  57. package/build/esm/lib/unstable/kit/index.d.ts +1 -0
  58. package/build/esm/lib/unstable/kit/index.js +1 -0
  59. package/build/esm/lib/unstable/kit/layouts/Accordeon/Accordeon.js +4 -2
  60. package/build/esm/lib/unstable/kit/layouts/Card/Card.js +11 -9
  61. package/build/esm/lib/unstable/kit/layouts/Section/Section.js +1 -1
  62. package/build/esm/lib/unstable/kit/utils/transformer.js +18 -3
  63. package/package.json +1 -1
@@ -11,6 +11,7 @@ export declare enum SchemaRendererEventType {
11
11
  Patch = "patch",
12
12
  Settings = "settings",
13
13
  Schema = "schema",
14
+ Submit = "submit",
14
15
  UserContext = "userContext"
15
16
  }
16
17
  export declare enum JsonSchemaType {
@@ -16,6 +16,7 @@ var SchemaRendererEventType;
16
16
  SchemaRendererEventType["Patch"] = "patch";
17
17
  SchemaRendererEventType["Settings"] = "settings";
18
18
  SchemaRendererEventType["Schema"] = "schema";
19
+ SchemaRendererEventType["Submit"] = "submit";
19
20
  SchemaRendererEventType["UserContext"] = "userContext";
20
21
  })(SchemaRendererEventType || (exports.SchemaRendererEventType = SchemaRendererEventType = {}));
21
22
  var JsonSchemaType;
@@ -21,6 +21,7 @@ export interface SchemaRendererState<UserContext extends Record<string, unknown>
21
21
  coerceInitialValues: boolean;
22
22
  jsonDefaultValues: boolean;
23
23
  };
24
+ submitCount: number;
24
25
  subscribe: (subscriber: SchemaRendererSubscriber) => string;
25
26
  subscribers: {
26
27
  byId: Record<string, SchemaRendererSubscriber>;
@@ -49,6 +49,7 @@ const useSchemaRenderer = ({ coerceInitialValues = true, config, connectValidate
49
49
  runValidate,
50
50
  settings: { coerceInitialValues, jsonDefaultValues },
51
51
  schema: nameUpdated || schemaUpdated ? (0, cloneDeep_1.default)(originalSchema) : (prevState === null || prevState === void 0 ? void 0 : prevState.schema) || {},
52
+ submitCount: nameUpdated || schemaUpdated || !prevState ? 0 : prevState.submitCount,
52
53
  subscribe,
53
54
  subscribers: (prevState === null || prevState === void 0 ? void 0 : prevState.subscribers) || { byId: {}, byName: new Map(), byPath: new Map() },
54
55
  unsubscribe,
@@ -118,6 +119,22 @@ const useSchemaRenderer = ({ coerceInitialValues = true, config, connectValidate
118
119
  initialState.dispatchEvent(initialEvents);
119
120
  }
120
121
  }, [initialEvents, initialState]);
122
+ react_1.default.useEffect(() => {
123
+ const originalSubmit = form.submit;
124
+ form.submit = () => {
125
+ var _a;
126
+ const srField = form.getFieldState((0, utils_1.getServiceFieldName)(constants_2.SCHEMA_RENDERER_SERVICE_FIELD, headName));
127
+ const srState = (_a = srField === null || srField === void 0 ? void 0 : srField.data) === null || _a === void 0 ? void 0 : _a.state;
128
+ if (srState) {
129
+ srState.submitCount += 1;
130
+ srState.dispatchEvent([{ type: constants_1.SchemaRendererEventType.Submit, all: true }]);
131
+ }
132
+ return originalSubmit.call(form);
133
+ };
134
+ return () => {
135
+ form.submit = originalSubmit;
136
+ };
137
+ }, [form]);
121
138
  react_1.default.useEffect(() => {
122
139
  const strictChecker = strictCheckerRef.current;
123
140
  return () => {
@@ -3,6 +3,7 @@ import { type FlexProps } from '@gravity-ui/uikit';
3
3
  export interface EntityContainerProps extends FlexProps {
4
4
  children: React.ReactNode;
5
5
  fill?: 'populated' | 'empty' | 'by-child';
6
+ ref?: React.ComponentPropsWithRef<'div'>['ref'];
6
7
  stretch: 'max' | 'fit' | 'by-child';
7
8
  }
8
9
  export declare const EntityContainer: React.FC<EntityContainerProps>;
@@ -288,6 +288,7 @@ export declare const untypedConfig: {
288
288
  readonly formEntities: {
289
289
  readonly base: {
290
290
  readonly Component: import("../../core").NodeEntity<import("../../core").JsonSchemaObject, import("../entities").ObjectEntityProps>;
291
+ readonly independent: true;
291
292
  };
292
293
  readonly dot_value: {
293
294
  readonly Component: import("../../core").NodeEntity<import("../../core").JsonSchemaObject, import("../entities").DotValueProps>;
@@ -336,6 +337,7 @@ export declare const untypedConfig: {
336
337
  readonly overviewEntities: {
337
338
  readonly base: {
338
339
  readonly Component: import("../../core").NodeEntity<import("../../core").JsonSchemaObject, import("../entities").ObjectEntityProps>;
340
+ readonly independent: true;
339
341
  };
340
342
  readonly dot_value: {
341
343
  readonly Component: import("../../core").NodeEntity<import("../../core").JsonSchemaObject, import("../entities").DotValueProps>;
@@ -397,7 +399,7 @@ export declare const untypedConfig: {
397
399
  readonly color_picker: {
398
400
  readonly Component: import("../../core").NodeEntity<import("../../core").JsonSchemaString, import("../form-entities").ColorPickerInputProps>;
399
401
  };
400
- readonly file: {
402
+ readonly file_input: {
401
403
  readonly Component: import("../../core").NodeEntity<import("../../core").JsonSchemaString, import("../form-entities").FileInputProps>;
402
404
  };
403
405
  readonly label: {
@@ -461,7 +463,7 @@ export declare const untypedConfig: {
461
463
  readonly color_picker: {
462
464
  readonly Component: import("../../core").NodeEntity<import("../../core").JsonSchemaString, import("../overview-entities").ColorPickerValueProps>;
463
465
  };
464
- readonly file: {
466
+ readonly file_input: {
465
467
  readonly Component: import("../../core").NodeEntity<import("../../core").JsonSchemaString, import("../overview-entities").StringValueProps>;
466
468
  };
467
469
  readonly label: {
@@ -131,7 +131,7 @@ exports.untypedConfig = {
131
131
  },
132
132
  [core_1.NodeType.Object]: {
133
133
  formEntities: {
134
- base: { Component: entities_1.ObjectEntity },
134
+ base: { Component: entities_1.ObjectEntity, independent: true },
135
135
  dot_value: { Component: entities_1.DotValue },
136
136
  few_of_nested: { Component: entities_1.FewOfNested, independent: true },
137
137
  inline: { Component: entities_1.ObjectInline },
@@ -149,7 +149,7 @@ exports.untypedConfig = {
149
149
  transparent: { Component: layouts_1.Transparent },
150
150
  },
151
151
  overviewEntities: {
152
- base: { Component: entities_1.ObjectEntity },
152
+ base: { Component: entities_1.ObjectEntity, independent: true },
153
153
  dot_value: { Component: entities_1.DotValue },
154
154
  few_of_nested: { Component: entities_1.FewOfNested, independent: true },
155
155
  inline: { Component: entities_1.ObjectInline },
@@ -173,7 +173,7 @@ exports.untypedConfig = {
173
173
  alert: { Component: entities_1.Alert },
174
174
  base: { Component: form_entities_1.StringInput },
175
175
  color_picker: { Component: form_entities_1.ColorPickerInput },
176
- file: { Component: form_entities_1.FileInput },
176
+ file_input: { Component: form_entities_1.FileInput },
177
177
  label: { Component: entities_1.Label },
178
178
  monaco_input: { Component: entities_1.Monaco },
179
179
  password: { Component: form_entities_1.PasswordInput },
@@ -197,7 +197,7 @@ exports.untypedConfig = {
197
197
  alert: { Component: entities_1.Alert },
198
198
  base: { Component: overview_entities_1.StringValue },
199
199
  color_picker: { Component: overview_entities_1.ColorPickerValue },
200
- file: { Component: overview_entities_1.StringValue },
200
+ file_input: { Component: overview_entities_1.StringValue },
201
201
  label: { Component: entities_1.Label },
202
202
  monaco_input: { Component: entities_1.Monaco },
203
203
  password: { Component: overview_entities_1.StringValue },
@@ -3,5 +3,6 @@ export interface FewOfNestedProps {
3
3
  toggler: JsonSchema;
4
4
  withIndent?: boolean;
5
5
  togglerArrayRemoveButton?: boolean;
6
+ order?: string[];
6
7
  }
7
8
  export declare const FewOfNested: NodeEntity<JsonSchemaObject, FewOfNestedProps>;
@@ -10,7 +10,7 @@ const utils_1 = require("../../utils");
10
10
  const b = (0, utils_1.block)('few-of-nested');
11
11
  const FewOfNested = ({ Layout, headName, input, layoutProps, meta, mode, props, schema, schemaPath, }) => {
12
12
  const { name, value } = input;
13
- const { togglerArrayRemoveButton = false, toggler: togglerSchema = {}, withIndent = false, } = props;
13
+ const { togglerArrayRemoveButton = false, toggler: togglerSchema = {}, withIndent = false, order, } = props;
14
14
  const overviewFlag = mode === core_1.SchemaRendererMode.Overview;
15
15
  const srState = (0, core_1.useSchemaRendererState)({
16
16
  headName,
@@ -20,8 +20,13 @@ const FewOfNested = ({ Layout, headName, input, layoutProps, meta, mode, props,
20
20
  if (value && Object.keys(value).length) {
21
21
  return Object.keys(value);
22
22
  }
23
- if (!overviewFlag && schema.properties && Object.keys(schema.properties).length) {
24
- return [Object.keys(schema.properties)[0]];
23
+ if (!overviewFlag) {
24
+ if ((order === null || order === void 0 ? void 0 : order[0]) !== undefined) {
25
+ return [order[0]];
26
+ }
27
+ if (schema.properties && Object.keys(schema.properties).length) {
28
+ return [Object.keys(schema.properties)[0]];
29
+ }
25
30
  }
26
31
  return [];
27
32
  });
@@ -5,12 +5,15 @@ const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const core_1 = require("../../../core");
7
7
  const components_1 = require("../../components");
8
- const ObjectEntity = ({ headName, mode, input, props, schema, schemaPath, }) => {
8
+ const ObjectEntity = ({ Layout, headName, input, layoutProps, meta, mode, props, schema, schemaPath, }) => {
9
9
  const { name } = input;
10
- const overviewFlag = mode === core_1.SchemaRendererMode.Overview;
11
- if (overviewFlag && !Object.keys(schema.properties || {}).length) {
12
- return react_1.default.createElement(components_1.EmptyEntityValue, null);
10
+ if (!Object.keys(schema.properties || {}).length) {
11
+ return null;
13
12
  }
14
- return (react_1.default.createElement(components_1.EntityContainer, { stretch: "by-child", fill: "by-child" }, (props.order || Object.keys(schema.properties || {})).map((property) => (react_1.default.createElement(core_1.SchemaRendererNode, { headName: headName, name: `${name ? name + '.' : ''}${property}`, schemaPath: `${schemaPath}/properties/${property}`, key: property })))));
13
+ let content = (react_1.default.createElement(components_1.EntityContainer, { stretch: "by-child", fill: "by-child" }, (props.order || Object.keys(schema.properties || {})).map((property) => (react_1.default.createElement(core_1.SchemaRendererNode, { headName: headName, name: `${name ? name + '.' : ''}${property}`, schemaPath: `${schemaPath}/properties/${property}`, key: property })))));
14
+ if (Layout) {
15
+ content = (react_1.default.createElement(Layout, { headName: headName, input: input, meta: meta, mode: mode, schema: schema, schemaPath: schemaPath, props: layoutProps || {} }, content));
16
+ }
17
+ return content;
15
18
  };
16
19
  exports.ObjectEntity = ObjectEntity;
@@ -19,7 +19,7 @@ const ObjectInline = ({ headName, input, mode, props, schema, schemaPath, }) =>
19
19
  }
20
20
  return (react_1.default.createElement(components_1.EntityContainer, { stretch: overviewFlag ? 'by-child' : 'max', className: b(), fill: "by-child" },
21
21
  react_1.default.createElement(uikit_1.Flex, { className: b('items', { overview: overviewFlag }), direction: "row", alignItems: "flex-start", gap: overviewFlag ? 1 : 2 }, (order || Object.keys(schema.properties || {})).map((property, index, array) => (react_1.default.createElement(react_1.default.Fragment, { key: property },
22
- react_1.default.createElement(core_1.SchemaRendererNode, { headName: headName, name: `${name ? name + '.' : ''}${property}`, schemaPath: `${schemaPath}/properties/${property}` }),
22
+ react_1.default.createElement(core_1.SchemaRendererNode, { headName: headName, name: `${name ? name + '.' : ''}${property}`, schemaPath: `${schemaPath}/properties/${property}`, key: property }),
23
23
  (0, isString_1.default)(delimiter) && index + 1 !== array.length ? (react_1.default.createElement(uikit_1.Text, { className: b('delimiter') }, delimiter)) : null,
24
24
  (0, isObject_1.default)(delimiter) && delimiter[property] ? (react_1.default.createElement(uikit_1.Text, { className: b('delimiter') }, delimiter[property])) : null))))));
25
25
  };
@@ -7,5 +7,6 @@ export interface OneOfNestedProps {
7
7
  };
8
8
  withIndent?: boolean;
9
9
  togglerArrayRemoveButton?: boolean;
10
+ order?: string[];
10
11
  }
11
12
  export declare const OneOfNested: NodeEntity<JsonSchemaObject, OneOfNestedProps>;
@@ -9,7 +9,7 @@ const utils_1 = require("../../utils");
9
9
  const b = (0, utils_1.block)('one-of-nested');
10
10
  const OneOfNested = ({ Layout, headName, input, layoutProps, meta, mode, props, schema, schemaPath, }) => {
11
11
  const { name, value } = input;
12
- const { booleanToKey, togglerArrayRemoveButton = false, toggler: togglerSchema = {}, withIndent = false, } = props;
12
+ const { booleanToKey, togglerArrayRemoveButton = false, toggler: togglerSchema = {}, withIndent = false, order, } = props;
13
13
  const overviewFlag = mode === core_1.SchemaRendererMode.Overview;
14
14
  const srState = (0, core_1.useSchemaRendererState)({
15
15
  headName,
@@ -19,8 +19,13 @@ const OneOfNested = ({ Layout, headName, input, layoutProps, meta, mode, props,
19
19
  if (value && Object.keys(value).length) {
20
20
  return Object.keys(value)[0];
21
21
  }
22
- if (!overviewFlag && schema.properties) {
23
- return Object.keys(schema.properties)[0];
22
+ if (!overviewFlag) {
23
+ if ((order === null || order === void 0 ? void 0 : order[0]) !== undefined) {
24
+ return order[0];
25
+ }
26
+ if (schema.properties) {
27
+ return Object.keys(schema.properties)[0];
28
+ }
24
29
  }
25
30
  return undefined;
26
31
  });
@@ -67,7 +72,7 @@ const OneOfNested = ({ Layout, headName, input, layoutProps, meta, mode, props,
67
72
  }, [name, input, togglerArrayRemoveButton]);
68
73
  let content = (react_1.default.createElement(components_1.EntityContainer, { direction: "column-reverse", stretch: "by-child", fill: "populated" },
69
74
  togglerValue === undefined ? null : (react_1.default.createElement(components_1.LayoutContainer, { className: b('content', { 'with-indent': withIndent }), hideEmpty: overviewFlag },
70
- react_1.default.createElement(core_1.SchemaRendererNode, { headName: headName, name: `${name ? name + '.' : ''}${togglerValue}`, schemaPath: `${schemaPath}/properties/${togglerValue}` }))),
75
+ react_1.default.createElement(core_1.SchemaRendererNode, { headName: headName, name: `${name ? name + '.' : ''}${togglerValue}`, schemaPath: `${schemaPath}/properties/${togglerValue}`, key: togglerValue }))),
71
76
  toggler));
72
77
  if (overviewFlag && Object.values(value || {}).length === 0) {
73
78
  content = react_1.default.createElement(react_1.default.Fragment, null, toggler);
@@ -30,7 +30,7 @@ const NumberWithScaleInput = ({ input, meta, props, schema, }) => {
30
30
  scale: preparedScale,
31
31
  defaultType,
32
32
  viewType: viewType && preparedScale[viewType] ? [viewType] : [defaultType],
33
- minScaleLength: `${minScaleLength + 42}px`,
33
+ minScaleLength: `${minScaleLength + 60}px`,
34
34
  };
35
35
  }
36
36
  }
@@ -64,8 +64,8 @@ const RangeInput = ({ headName, input, props, schemaPath, }) => {
64
64
  }, [inputValue === null || inputValue === void 0 ? void 0 : inputValue[fromKey], inputValue === null || inputValue === void 0 ? void 0 : inputValue[toKey]]);
65
65
  return (react_1.default.createElement(components_1.EntityContainer, { stretch: "max", className: b() },
66
66
  react_1.default.createElement(uikit_1.Flex, { className: b('items'), direction: "row", alignItems: "flex-start", gap: 2 },
67
- react_1.default.createElement(core_1.SchemaRendererNode, { headName: headName, name: fromName, schemaPath: `${schemaPath}/properties/${fromKey}` }),
67
+ react_1.default.createElement(core_1.SchemaRendererNode, { headName: headName, name: fromName, schemaPath: `${schemaPath}/properties/${fromKey}`, key: fromKey }),
68
68
  react_1.default.createElement(uikit_1.Text, { className: b('delimiter') }, separator),
69
- react_1.default.createElement(core_1.SchemaRendererNode, { headName: headName, name: toName, schemaPath: `${schemaPath}/properties/${toKey}` }))));
69
+ react_1.default.createElement(core_1.SchemaRendererNode, { headName: headName, name: toName, schemaPath: `${schemaPath}/properties/${toKey}`, key: toKey }))));
70
70
  };
71
71
  exports.RangeInput = RangeInput;
@@ -1,11 +1,16 @@
1
+ .sr-segmented-radio-group-input {
2
+ position: relative;
3
+ }
1
4
  .sr-segmented-radio-group-input_error .g-segmented-radio-group .g-segmented-radio-group__option_checked:hover::after {
2
5
  border: 1px solid var(--g-color-text-danger);
3
6
  }
4
7
  .sr-segmented-radio-group-input_error .g-segmented-radio-group .g-segmented-radio-group__option_checked::after {
5
8
  border: 1px solid var(--g-color-text-danger);
6
9
  }
7
- .sr-segmented-radio-group-input_overflowed {
8
- height: 0;
9
- opacity: 0;
10
- overflow: hidden;
10
+ .sr-segmented-radio-group-input__checker {
11
+ position: absolute;
12
+ left: 0;
13
+ top: 0;
14
+ width: max-content;
15
+ visibility: hidden;
11
16
  }
@@ -14,7 +14,8 @@ const SegmentedRadioGroupInput = (_a) => {
14
14
  const { name, onBlur, onChange, onFocus, value } = input;
15
15
  const { enumDescriptions, optionsDisabled } = props, restEntityProps = tslib_1.__rest(props, ["enumDescriptions", "optionsDisabled"]);
16
16
  const { disabled } = ((_b = schema.nodeParameters) === null || _b === void 0 ? void 0 : _b.flags) || {};
17
- const ref = react_1.default.useRef(null);
17
+ const containerRef = react_1.default.useRef(null);
18
+ const controlRef = react_1.default.useRef(null);
18
19
  const [overflowed, setOverflowed] = react_1.default.useState(false);
19
20
  const options = react_1.default.useMemo(() => {
20
21
  var _a;
@@ -30,27 +31,25 @@ const SegmentedRadioGroupInput = (_a) => {
30
31
  onBlur();
31
32
  }, [onBlur, onChange, onFocus]);
32
33
  react_1.default.useLayoutEffect(() => {
33
- const root = ref.current;
34
- if (!root) {
34
+ const container = containerRef.current;
35
+ const control = controlRef.current;
36
+ if (!container || !control) {
35
37
  return;
36
38
  }
37
39
  const measure = () => {
38
- const texts = root.querySelectorAll('.g-segmented-radio-group__option-text');
39
- setOverflowed(Array.from(texts).some((node) => {
40
- if (node.offsetWidth === 0 && node.scrollWidth === 0) {
41
- return false;
42
- }
43
- return node.scrollWidth > node.clientWidth;
44
- }));
40
+ const GAP = 48; // little bit more than potential remove button width + spacing
41
+ const containerWidth = container.offsetWidth - GAP;
42
+ const controlWidth = control.offsetWidth;
43
+ setOverflowed(controlWidth > containerWidth);
45
44
  };
46
45
  measure();
47
46
  const observer = new ResizeObserver(measure);
48
- observer.observe(root);
47
+ observer.observe(container);
49
48
  return () => observer.disconnect();
50
49
  }, [options]);
51
- return (react_1.default.createElement(components_1.EntityContainer, { stretch: "max" },
52
- overflowed ? (react_1.default.createElement(SelectInput_1.SelectInput, Object.assign({ input: input, meta: meta, props: props, schema: schema }, restProps))) : null,
53
- react_1.default.createElement(components_1.EntityContainer, { stretch: "max", className: b({ error: (0, utils_1.getBooleanValidationState)(meta), overflowed }) },
54
- react_1.default.createElement(uikit_1.SegmentedRadioGroup, Object.assign({ ref: ref, width: "max", disabled: disabled || schema.readOnly, options: options }, restEntityProps, { value: value, onFocus: onFocus, onBlur: onBlur, onUpdate: onUpdate, qa: name })))));
50
+ return (react_1.default.createElement(components_1.EntityContainer, { ref: containerRef, className: b({ error: (0, utils_1.getBooleanValidationState)(meta) }), stretch: "max" },
51
+ overflowed ? (react_1.default.createElement(SelectInput_1.SelectInput, Object.assign({ input: input, meta: meta, props: props, schema: schema }, restProps))) : (react_1.default.createElement(uikit_1.SegmentedRadioGroup, Object.assign({ width: "max", disabled: disabled || schema.readOnly, options: options }, restEntityProps, { value: value, onFocus: onFocus, onBlur: onBlur, onUpdate: onUpdate, qa: name }))),
52
+ react_1.default.createElement("div", { className: b('checker') },
53
+ react_1.default.createElement(uikit_1.SegmentedRadioGroup, Object.assign({ ref: controlRef, width: "max", disabled: disabled || schema.readOnly, options: options }, restEntityProps)))));
55
54
  };
56
55
  exports.SegmentedRadioGroupInput = SegmentedRadioGroupInput;
@@ -31,7 +31,7 @@ const StringNumberWithScaleInput = ({ input, meta, props, schema }) => {
31
31
  scale: preparedScale,
32
32
  defaultType,
33
33
  viewType: viewType && preparedScale[viewType] ? [viewType] : [defaultType],
34
- minScaleLength: `${minScaleLength + 42}px`,
34
+ minScaleLength: `${minScaleLength + 60}px`,
35
35
  };
36
36
  }
37
37
  }
@@ -11,6 +11,6 @@ const TextAreaInput = ({ input, meta, props, schema, }) => {
11
11
  var _a, _b, _c;
12
12
  const { disabled } = ((_a = schema.nodeParameters) === null || _a === void 0 ? void 0 : _a.flags) || {};
13
13
  return (react_1.default.createElement(components_1.EntityContainer, { stretch: "max", className: b({ error: (0, utils_1.getBooleanValidationState)(meta) }) },
14
- react_1.default.createElement(uikit_1.TextArea, Object.assign({ maxRows: 20, minRows: 0, placeholder: (_b = schema.examples) === null || _b === void 0 ? void 0 : _b[0], disabled: disabled || schema.readOnly, hasClear: true }, props, { value: (_c = input.value) !== null && _c !== void 0 ? _c : '', onFocus: input.onFocus, onBlur: input.onBlur, onUpdate: input.onChange, errorMessage: undefined, validationState: (0, utils_1.getValidationState)(meta), qa: input.name }))));
14
+ react_1.default.createElement(uikit_1.TextArea, Object.assign({ maxRows: 20, minRows: 8, placeholder: (_b = schema.examples) === null || _b === void 0 ? void 0 : _b[0], disabled: disabled || schema.readOnly, hasClear: true }, props, { value: (_c = input.value) !== null && _c !== void 0 ? _c : '', onFocus: input.onFocus, onBlur: input.onBlur, onUpdate: input.onChange, errorMessage: undefined, validationState: (0, utils_1.getValidationState)(meta), qa: input.name }))));
15
15
  };
16
16
  exports.TextAreaInput = TextAreaInput;
@@ -26,7 +26,7 @@ const FormColumn = ({ children, headName, input, meta, schema, props, }) => {
26
26
  return (react_1.default.createElement(components_1.LayoutContainer, { className: b(), gap: 2, hidden: hidden },
27
27
  react_1.default.createElement(uikit_1.Flex, { direction: "column", gap: 0.5 },
28
28
  react_1.default.createElement("div", { className: b('top') },
29
- react_1.default.createElement(uikit_1.Text, { className: b('title', { required }), wordBreak: "break-word" }, schema.title),
29
+ react_1.default.createElement(uikit_1.Text, { className: b('title', { required }), variant: "subheader-1", color: "complementary", wordBreak: "break-word" }, schema.title),
30
30
  tooltip,
31
31
  react_1.default.createElement(components_1.ArrayRemoveButton, { name: input.name, headName: headName })),
32
32
  bottomDescription),
@@ -25,7 +25,7 @@ const FormRow = ({ children, headName, input, meta, schema, props, }) => {
25
25
  }, [headName, schema.description, props.descriptionType]);
26
26
  return (react_1.default.createElement(components_1.LayoutContainer, { className: b(), direction: "row", alignItems: "flex-start", gap: 2, hidden: hidden },
27
27
  react_1.default.createElement("div", { className: b('left') },
28
- react_1.default.createElement(uikit_1.Text, { className: b('title', { required }), wordBreak: "break-word" }, schema.title),
28
+ react_1.default.createElement(uikit_1.Text, { className: b('title', { required }), variant: "subheader-1", color: "complementary", wordBreak: "break-word" }, schema.title),
29
29
  tooltip),
30
30
  react_1.default.createElement(uikit_1.Flex, { className: b('right'), direction: "column", gap: 0.5, grow: 1 },
31
31
  react_1.default.createElement(uikit_1.Flex, { grow: 1, gap: 2 },
@@ -0,0 +1 @@
1
+ export { type UseExpandedParams, useExpanded } from './useExpanded';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useExpanded = void 0;
4
+ var useExpanded_1 = require("./useExpanded");
5
+ Object.defineProperty(exports, "useExpanded", { enumerable: true, get: function () { return useExpanded_1.useExpanded; } });
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ export interface UseExpandedParams {
3
+ headName: string;
4
+ name: string;
5
+ open?: boolean;
6
+ }
7
+ export declare const useExpanded: ({ headName, name, open }: UseExpandedParams) => {
8
+ expanded: boolean;
9
+ setExpanded: React.Dispatch<React.SetStateAction<boolean>>;
10
+ toggleExpanded: () => void;
11
+ };
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useExpanded = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const core_1 = require("../../core");
7
+ const useExpanded = ({ headName, name, open = true }) => {
8
+ const srState = (0, core_1.useSchemaRendererState)({
9
+ headName,
10
+ subscriptions: [core_1.SchemaRendererEventType.Submit],
11
+ });
12
+ const [expanded, setExpanded] = react_1.default.useState(open);
13
+ const toggleExpanded = react_1.default.useCallback(() => {
14
+ setExpanded((f) => !f);
15
+ }, []);
16
+ react_1.default.useEffect(() => {
17
+ if (srState &&
18
+ srState.submitCount > 0 &&
19
+ Object.keys(srState.errors).some((key) => key.startsWith(name))) {
20
+ setExpanded(true);
21
+ }
22
+ }, [srState]);
23
+ return { expanded, setExpanded, toggleExpanded };
24
+ };
25
+ exports.useExpanded = useExpanded;
@@ -1,6 +1,7 @@
1
1
  export * from './components';
2
2
  export * from './constants';
3
3
  export * from './entities';
4
+ export * from './hooks';
4
5
  export * from './form-entities';
5
6
  export * from './form-layouts';
6
7
  export * from './layouts';
@@ -4,6 +4,7 @@ const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./components"), exports);
5
5
  tslib_1.__exportStar(require("./constants"), exports);
6
6
  tslib_1.__exportStar(require("./entities"), exports);
7
+ tslib_1.__exportStar(require("./hooks"), exports);
7
8
  tslib_1.__exportStar(require("./form-entities"), exports);
8
9
  tslib_1.__exportStar(require("./form-layouts"), exports);
9
10
  tslib_1.__exportStar(require("./layouts"), exports);
@@ -7,14 +7,16 @@ const icons_1 = require("@gravity-ui/icons");
7
7
  const uikit_1 = require("@gravity-ui/uikit");
8
8
  const core_1 = require("../../../core");
9
9
  const components_1 = require("../../components");
10
+ const hooks_1 = require("../../hooks");
10
11
  const utils_1 = require("../../utils");
11
12
  const b = (0, utils_1.block)('accordeon');
12
13
  const Accordeon = ({ children, headName, input, meta, mode, schema, props, }) => {
13
14
  var _a;
14
15
  const { titleProps, togglerProps, withIndent = false, withDefaultSummary = false } = props, restLayoutProps = tslib_1.__rest(props, ["titleProps", "togglerProps", "withIndent", "withDefaultSummary"]);
15
16
  const { copy, required, hidden, open } = ((_a = schema.nodeParameters) === null || _a === void 0 ? void 0 : _a.flags) || {};
17
+ const { expanded, setExpanded } = (0, hooks_1.useExpanded)({ headName, name: input.name, open });
16
18
  const overviewFlag = mode === core_1.SchemaRendererMode.Overview;
17
- const summary = react_1.default.useMemo(() => (react_1.default.createElement(uikit_1.Text, Object.assign({}, titleProps, { className: b('title', { required: required && !overviewFlag }, titleProps === null || titleProps === void 0 ? void 0 : titleProps.className) }), schema.title)), [overviewFlag, required, schema.title, titleProps]);
19
+ const summary = react_1.default.useMemo(() => (react_1.default.createElement(uikit_1.Text, Object.assign({ variant: "subheader-1", color: "complementary" }, titleProps, { className: b('title', { required: required && !overviewFlag }, titleProps === null || titleProps === void 0 ? void 0 : titleProps.className) }), schema.title)), [overviewFlag, required, schema.title, titleProps]);
18
20
  const helpMark = react_1.default.useMemo(() => {
19
21
  if (schema.description) {
20
22
  return (react_1.default.createElement(uikit_1.HelpMark, null,
@@ -35,7 +37,7 @@ const Accordeon = ({ children, headName, input, meta, mode, schema, props, }) =>
35
37
  return react_1.default.createElement(components_1.ArrayRemoveButton, { name: input.name, headName: headName });
36
38
  }, [overviewFlag, input.name, headName]);
37
39
  return (react_1.default.createElement(components_1.LayoutContainer, { className: b({ 'without-default-summary': !withDefaultSummary }), hideEmpty: overviewFlag, hidden: hidden },
38
- react_1.default.createElement(uikit_1.Disclosure, Object.assign({ defaultExpanded: open, summary: summary }, restLayoutProps),
40
+ react_1.default.createElement(uikit_1.Disclosure, Object.assign({ summary: summary, expanded: expanded, onUpdate: setExpanded }, restLayoutProps),
39
41
  react_1.default.createElement(uikit_1.Disclosure.Summary, null, ({ expanded, onClick }, defaultSummary) => (react_1.default.createElement(uikit_1.Flex, { minHeight: "28px", alignItems: "center", gap: 2 },
40
42
  withDefaultSummary ? (defaultSummary) : (react_1.default.createElement(uikit_1.Button, Object.assign({}, togglerProps, { onClick: onClick, className: b('toggler', togglerProps === null || togglerProps === void 0 ? void 0 : togglerProps.className) }),
41
43
  react_1.default.createElement(uikit_1.Flex, { alignItems: "center", gap: 2, height: "100%" },
@@ -7,6 +7,7 @@ const icons_1 = require("@gravity-ui/icons");
7
7
  const uikit_1 = require("@gravity-ui/uikit");
8
8
  const core_1 = require("../../../core");
9
9
  const components_1 = require("../../components");
10
+ const hooks_1 = require("../../hooks");
10
11
  const utils_1 = require("../../utils");
11
12
  const b = (0, utils_1.block)('card');
12
13
  const Card = ({ children, headName, input, meta, mode, schema, props, }) => {
@@ -14,10 +15,11 @@ const Card = ({ children, headName, input, meta, mode, schema, props, }) => {
14
15
  const { descriptionType = 'tooltip', likeAccordeon = true } = props, restLayoutProps = tslib_1.__rest(props, ["descriptionType", "likeAccordeon"]);
15
16
  const { copy, required, hidden, open = true } = ((_a = schema.nodeParameters) === null || _a === void 0 ? void 0 : _a.flags) || {};
16
17
  const overviewFlag = mode === core_1.SchemaRendererMode.Overview;
17
- const [visible, setVisible] = react_1.default.useState(likeAccordeon ? open : true);
18
- const toggleVisible = react_1.default.useCallback(() => {
19
- setVisible((f) => !f);
20
- }, []);
18
+ const { expanded, toggleExpanded } = (0, hooks_1.useExpanded)({
19
+ headName,
20
+ name: input.name,
21
+ open: likeAccordeon ? open : true,
22
+ });
21
23
  const tooltip = react_1.default.useMemo(() => {
22
24
  if (!schema.description || descriptionType === 'bottom') {
23
25
  return null;
@@ -33,20 +35,20 @@ const Card = ({ children, headName, input, meta, mode, schema, props, }) => {
33
35
  }, [headName, schema.description, descriptionType, overviewFlag]);
34
36
  return (react_1.default.createElement(components_1.LayoutContainer, { className: b(), hideEmpty: overviewFlag, hidden: hidden },
35
37
  react_1.default.createElement(uikit_1.Card, Object.assign({}, restLayoutProps, { className: b('card') }),
36
- react_1.default.createElement("div", { className: b('inner', { hidden: !visible }) },
38
+ react_1.default.createElement("div", { className: b('inner', { hidden: !expanded }) },
37
39
  react_1.default.createElement(uikit_1.Flex, { className: b('header'), direction: "column", justifyContent: "center" },
38
40
  react_1.default.createElement(uikit_1.Flex, { justifyContent: "space-between", alignItems: "center" },
39
41
  react_1.default.createElement(uikit_1.Flex, { alignItems: "center", gap: 2 },
40
- react_1.default.createElement(uikit_1.Text, { variant: "subheader-1", className: b('title', { required: required && !overviewFlag }) }, schema.title),
42
+ react_1.default.createElement(uikit_1.Text, { variant: "subheader-1", color: "complementary", className: b('title', { required: required && !overviewFlag }) }, schema.title),
41
43
  tooltip),
42
44
  react_1.default.createElement(uikit_1.Flex, { className: b('header-actions'), alignItems: "center", gap: 2 },
43
45
  overviewFlag ? (react_1.default.createElement(components_1.CopyButton, { className: b('copy-button'), copy: copy, value: input.value })) : null,
44
46
  overviewFlag ? null : (react_1.default.createElement(components_1.ArrayRemoveButton, { name: input.name, headName: headName })),
45
47
  likeAccordeon ? (react_1.default.createElement(uikit_1.Flex, { width: "28px", justifyContent: "center" },
46
- react_1.default.createElement(uikit_1.Button, { onClick: toggleVisible, size: "s", view: "flat-secondary" },
47
- react_1.default.createElement(uikit_1.Icon, { data: visible ? icons_1.ChevronUp : icons_1.ChevronDown, size: 16 })))) : null)),
48
+ react_1.default.createElement(uikit_1.Button, { onClick: toggleExpanded, size: "s", view: "flat-secondary" },
49
+ react_1.default.createElement(uikit_1.Icon, { data: expanded ? icons_1.ChevronUp : icons_1.ChevronDown, size: 16 })))) : null)),
48
50
  bottomDescription),
49
- react_1.default.createElement("div", { className: b('content', { hidden: !visible }) }, children)),
51
+ react_1.default.createElement("div", { className: b('content', { hidden: !expanded }) }, children)),
50
52
  overviewFlag ? null : (react_1.default.createElement(components_1.EntityError, { errorMessage: meta.error, validationState: (0, utils_1.getValidationState)(meta) })))));
51
53
  };
52
54
  exports.Card = Card;
@@ -30,7 +30,7 @@ const Section = ({ children, headName, input, meta, mode, schema, props, }) => {
30
30
  react_1.default.createElement(uikit_1.Flex, { direction: "column", gap: 4 },
31
31
  react_1.default.createElement(uikit_1.Flex, { direction: "column" },
32
32
  react_1.default.createElement(uikit_1.Flex, { className: b('header'), gap: 2, alignItems: "center" },
33
- react_1.default.createElement(uikit_1.Text, Object.assign({ variant: "subheader-1" }, restLayoutProps, { className: b('title', { required: required && !overviewFlag }, restLayoutProps === null || restLayoutProps === void 0 ? void 0 : restLayoutProps.className) }), schema.title),
33
+ react_1.default.createElement(uikit_1.Text, Object.assign({ variant: "subheader-1", color: "complementary" }, restLayoutProps, { className: b('title', { required: required && !overviewFlag }, restLayoutProps === null || restLayoutProps === void 0 ? void 0 : restLayoutProps.className) }), schema.title),
34
34
  tooltip,
35
35
  overviewFlag ? (react_1.default.createElement(components_1.CopyButton, { className: b('copy-button'), copy: copy, value: input.value })) : null,
36
36
  overviewFlag ? null : (react_1.default.createElement(components_1.ArrayRemoveButton, { name: input.name, headName: headName }))),