@gravity-ui/dynamic-forms 1.6.2 → 1.7.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 (53) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/build/cjs/lib/core/components/Form/Controller.js +3 -2
  3. package/build/cjs/lib/core/components/Form/DynamicField.js +1 -1
  4. package/build/cjs/lib/core/components/Form/hooks/useField.js +10 -11
  5. package/build/cjs/lib/core/components/Form/hooks/useStore.js +12 -12
  6. package/build/cjs/lib/core/helpers.js +1 -4
  7. package/build/cjs/lib/kit/components/Card/Card.css +2 -1
  8. package/build/cjs/lib/kit/components/Inputs/ArrayBase/ArrayBase.js +1 -1
  9. package/build/cjs/lib/kit/components/Inputs/CardOneOf/CardOneOf.js +1 -1
  10. package/build/cjs/lib/kit/components/Inputs/ObjectBase/ObjectBase.js +1 -1
  11. package/build/cjs/lib/kit/components/Inputs/ObjectValueInput/ObjectValueInput.js +1 -1
  12. package/build/cjs/lib/kit/components/Inputs/OneOf/OneOf.css +16 -5
  13. package/build/cjs/lib/kit/components/Inputs/OneOf/OneOf.js +10 -5
  14. package/build/cjs/lib/kit/components/Inputs/OneOfCard/OneOfCard.js +1 -1
  15. package/build/cjs/lib/kit/components/Inputs/Secret/Secret.js +1 -1
  16. package/build/cjs/lib/kit/components/Inputs/TableArrayInput/TableArrayInput.js +1 -1
  17. package/build/cjs/lib/kit/components/Inputs/TextLink/TextLink.js +1 -1
  18. package/build/cjs/lib/kit/components/Views/OneOfView/OneOfView.css +8 -0
  19. package/build/cjs/lib/kit/components/Views/{OneOfView.js → OneOfView/OneOfView.js} +10 -6
  20. package/build/cjs/lib/kit/components/Views/OneOfView/index.js +4 -0
  21. package/build/cjs/lib/kit/constants/config.js +2 -0
  22. package/build/cjs/lib/kit/hooks/useOneOf.js +7 -3
  23. package/build/esm/lib/core/components/Form/Controller.d.ts +2 -2
  24. package/build/esm/lib/core/components/Form/Controller.js +3 -2
  25. package/build/esm/lib/core/components/Form/DynamicField.js +1 -1
  26. package/build/esm/lib/core/components/Form/hooks/useField.d.ts +2 -1
  27. package/build/esm/lib/core/components/Form/hooks/useField.js +11 -12
  28. package/build/esm/lib/core/components/Form/hooks/useStore.js +12 -12
  29. package/build/esm/lib/core/components/Form/types/context.d.ts +2 -2
  30. package/build/esm/lib/core/helpers.d.ts +0 -1
  31. package/build/esm/lib/core/helpers.js +0 -2
  32. package/build/esm/lib/core/types/specs.d.ts +3 -0
  33. package/build/esm/lib/kit/components/Card/Card.css +2 -1
  34. package/build/esm/lib/kit/components/Inputs/ArrayBase/ArrayBase.js +1 -1
  35. package/build/esm/lib/kit/components/Inputs/CardOneOf/CardOneOf.js +1 -1
  36. package/build/esm/lib/kit/components/Inputs/ObjectBase/ObjectBase.js +1 -1
  37. package/build/esm/lib/kit/components/Inputs/ObjectValueInput/ObjectValueInput.js +1 -1
  38. package/build/esm/lib/kit/components/Inputs/OneOf/OneOf.css +16 -5
  39. package/build/esm/lib/kit/components/Inputs/OneOf/OneOf.d.ts +7 -2
  40. package/build/esm/lib/kit/components/Inputs/OneOf/OneOf.js +9 -4
  41. package/build/esm/lib/kit/components/Inputs/OneOfCard/OneOfCard.js +1 -1
  42. package/build/esm/lib/kit/components/Inputs/Secret/Secret.js +1 -1
  43. package/build/esm/lib/kit/components/Inputs/TableArrayInput/TableArrayInput.js +1 -1
  44. package/build/esm/lib/kit/components/Inputs/TextLink/TextLink.js +1 -1
  45. package/build/esm/lib/kit/components/Views/OneOfView/OneOfView.css +8 -0
  46. package/build/esm/lib/kit/components/Views/OneOfView/OneOfView.d.ts +8 -0
  47. package/build/esm/lib/kit/components/Views/{OneOfView.js → OneOfView/OneOfView.js} +9 -4
  48. package/build/esm/lib/kit/components/Views/OneOfView/index.d.ts +1 -0
  49. package/build/esm/lib/kit/components/Views/OneOfView/index.js +1 -0
  50. package/build/esm/lib/kit/constants/config.js +3 -1
  51. package/build/esm/lib/kit/hooks/useOneOf.js +7 -3
  52. package/package.json +1 -1
  53. package/build/esm/lib/kit/components/Views/OneOfView.d.ts +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.7.0](https://github.com/gravity-ui/dynamic-forms/compare/v1.6.2...v1.7.0) (2023-05-22)
4
+
5
+
6
+ ### Features
7
+
8
+ * add flat oneof input, add oneof params to object spec ([#44](https://github.com/gravity-ui/dynamic-forms/issues/44)) ([25e9a35](https://github.com/gravity-ui/dynamic-forms/commit/25e9a3588b359cc251e5fdc19a1b51c5a614abb8))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * initial value ([#39](https://github.com/gravity-ui/dynamic-forms/issues/39)) ([ce52d65](https://github.com/gravity-ui/dynamic-forms/commit/ce52d6531b8dbabd3462dfd430b947b99e00b433))
14
+
15
+
16
+ ### Performance Improvements
17
+
18
+ * remove strict mode wrapper and react version check ([#43](https://github.com/gravity-ui/dynamic-forms/issues/43)) ([ec823bf](https://github.com/gravity-ui/dynamic-forms/commit/ec823bf56d4bec192649b8cd2c3da16def094bfb))
19
+
3
20
  ## [1.6.2](https://github.com/gravity-ui/dynamic-forms/compare/v1.6.1...v1.6.2) (2023-05-16)
4
21
 
5
22
 
@@ -5,14 +5,15 @@ const tslib_1 = require("tslib");
5
5
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
6
6
  const helpers_1 = require("../../helpers");
7
7
  const hooks_1 = require("./hooks");
8
- const Controller = ({ spec, name, initialValue, parentOnChange, parentOnUnmount, }) => {
8
+ const Controller = ({ spec, name, value, parentOnChange, parentOnUnmount, }) => {
9
9
  const { tools, __mirror } = (0, hooks_1.useDynamicFormsCtx)();
10
10
  const { inputEntity, Layout } = (0, hooks_1.useComponents)(spec);
11
11
  const render = (0, hooks_1.useRender)({ name, spec, inputEntity, Layout });
12
12
  const validate = (0, hooks_1.useValidate)(spec);
13
13
  const renderProps = (0, hooks_1.useField)({
14
14
  name,
15
- initialValue,
15
+ initialValue: lodash_1.default.get(tools.initialValue, name),
16
+ value,
16
17
  spec,
17
18
  validate,
18
19
  tools,
@@ -36,7 +36,7 @@ const DynamicField = ({ name, spec, config, Monaco, search, __mirror, }) => {
36
36
  if (correctParams) {
37
37
  return (react_1.default.createElement(DynamicFormsCtx.Provider, { value: context },
38
38
  react_1.default.createElement(SearchContext.Provider, { value: searchContext },
39
- react_1.default.createElement(Controller_1.Controller, { spec: spec, name: name, parentOnChange: null, parentOnUnmount: null, initialValue: lodash_1.default.get(tools.initialValue, name) }),
39
+ react_1.default.createElement(Controller_1.Controller, { spec: spec, name: name, parentOnChange: null, parentOnUnmount: null, value: lodash_1.default.get(store.values, name) }),
40
40
  watcher)));
41
41
  }
42
42
  return null;
@@ -7,7 +7,7 @@ const lodash_1 = tslib_1.__importDefault(require("lodash"));
7
7
  const helpers_1 = require("../../../helpers");
8
8
  const constants_1 = require("../constants");
9
9
  const utils_1 = require("../utils");
10
- const useField = ({ name, spec, initialValue, validate: propsValidate, tools, parentOnChange, parentOnUnmount, }) => {
10
+ const useField = ({ name, spec, initialValue, value: externalValue, validate: propsValidate, tools, parentOnChange, parentOnUnmount, }) => {
11
11
  const firstRenderRef = react_1.default.useRef(true);
12
12
  const validate = react_1.default.useCallback((value) => {
13
13
  if (value === constants_1.REMOVED_ITEM) {
@@ -16,7 +16,7 @@ const useField = ({ name, spec, initialValue, validate: propsValidate, tools, pa
16
16
  return propsValidate === null || propsValidate === void 0 ? void 0 : propsValidate((0, utils_1.transformArrOut)(value));
17
17
  }, [propsValidate]);
18
18
  const [state, setState] = react_1.default.useState(() => {
19
- let value = lodash_1.default.cloneDeep(initialValue);
19
+ let value = lodash_1.default.cloneDeep(externalValue);
20
20
  if (lodash_1.default.isNil(value)) {
21
21
  if (spec.defaultValue) {
22
22
  value = (0, utils_1.transformArrIn)(spec.defaultValue);
@@ -33,17 +33,19 @@ const useField = ({ name, spec, initialValue, validate: propsValidate, tools, pa
33
33
  }
34
34
  }
35
35
  const error = validate === null || validate === void 0 ? void 0 : validate(value);
36
+ const dirty = !lodash_1.default.isEqual(value, initialValue);
37
+ const pristine = value === initialValue;
36
38
  return {
37
39
  active: false,
38
- dirty: false,
40
+ dirty,
39
41
  error,
40
42
  invalid: Boolean(error),
41
- modified: false,
42
- pristine: false,
43
- touched: false,
43
+ modified: dirty || !pristine,
44
+ pristine,
45
+ touched: dirty || !pristine,
44
46
  valid: !error,
45
47
  value,
46
- visited: false,
48
+ visited: dirty || !pristine,
47
49
  childErrors: {},
48
50
  };
49
51
  });
@@ -129,16 +131,13 @@ const useField = ({ name, spec, initialValue, validate: propsValidate, tools, pa
129
131
  onDrop,
130
132
  ]);
131
133
  react_1.default.useEffect(() => {
132
- if (!firstRenderRef.current || !lodash_1.default.isEqual(initialValue, state.value) || state.error) {
134
+ if (!firstRenderRef.current || !lodash_1.default.isEqual(externalValue, state.value) || state.error) {
133
135
  (parentOnChange ? parentOnChange : tools.onChange)(name, state.value, Object.assign(Object.assign({}, state.childErrors), { [name]: state.error }));
134
136
  }
135
137
  }, [state.value]);
136
138
  react_1.default.useEffect(() => {
137
139
  firstRenderRef.current = false;
138
140
  return () => {
139
- if ((0, helpers_1.isReact18OrMore)()) {
140
- firstRenderRef.current = true;
141
- }
142
141
  (parentOnUnmount ? parentOnUnmount : tools.onUnmount)(name);
143
142
  };
144
143
  }, []);
@@ -5,19 +5,21 @@ const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
7
7
  const react_final_form_1 = require("react-final-form");
8
- const helpers_1 = require("../../../helpers");
9
8
  const utils_1 = require("../utils");
10
9
  const useStore = (name) => {
11
10
  const form = (0, react_final_form_1.useForm)();
12
11
  const firstRenderRef = react_1.default.useRef(true);
13
12
  const [store, setStore] = react_1.default.useState(() => {
14
- const initialValue = (0, utils_1.transformArrIn)({
13
+ const values = (0, utils_1.transformArrIn)({
15
14
  [name]: lodash_1.default.get(form.getState().values, name),
16
15
  });
16
+ const initialValue = (0, utils_1.transformArrIn)({
17
+ [name]: lodash_1.default.get(form.getState().initialValues, name),
18
+ });
17
19
  return {
18
20
  name,
19
- initialValue,
20
- values: lodash_1.default.cloneDeep(initialValue),
21
+ initialValue: lodash_1.default.cloneDeep(initialValue),
22
+ values: lodash_1.default.cloneDeep(values),
21
23
  errors: {},
22
24
  };
23
25
  });
@@ -30,24 +32,22 @@ const useStore = (name) => {
30
32
  }), [store.initialValue, setStore, submitFailed]);
31
33
  react_1.default.useEffect(() => {
32
34
  if (!firstRenderRef.current) {
33
- const initialValue = (0, utils_1.transformArrIn)({
35
+ const values = (0, utils_1.transformArrIn)({
34
36
  [name]: lodash_1.default.get(form.getState().values, name),
35
37
  });
38
+ const initialValue = (0, utils_1.transformArrIn)({
39
+ [name]: lodash_1.default.get(form.getState().initialValues, name),
40
+ });
36
41
  setStore({
37
42
  name: name,
38
- initialValue,
39
- values: lodash_1.default.cloneDeep(initialValue),
43
+ initialValue: lodash_1.default.cloneDeep(initialValue),
44
+ values: lodash_1.default.cloneDeep(values),
40
45
  errors: {},
41
46
  });
42
47
  }
43
48
  }, [name]);
44
49
  react_1.default.useEffect(() => {
45
50
  firstRenderRef.current = false;
46
- return () => {
47
- if ((0, helpers_1.isReact18OrMore)()) {
48
- firstRenderRef.current = true;
49
- }
50
- };
51
51
  }, []);
52
52
  return { tools, store };
53
53
  };
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isReact18OrMore = exports.isStringSpec = exports.isObjectSpec = exports.isNumberSpec = exports.isBooleanSpec = exports.isArraySpec = exports.isCorrectSpec = void 0;
3
+ exports.isStringSpec = exports.isObjectSpec = exports.isNumberSpec = exports.isBooleanSpec = exports.isArraySpec = exports.isCorrectSpec = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const react_1 = tslib_1.__importDefault(require("react"));
6
5
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
7
6
  const constants_1 = require("./constants");
8
7
  const isCorrectSpec = (candidate) => lodash_1.default.isObjectLike(candidate) &&
@@ -24,5 +23,3 @@ const isObjectSpec = (candidate) => (candidate === null || candidate === void 0
24
23
  exports.isObjectSpec = isObjectSpec;
25
24
  const isStringSpec = (candidate) => (candidate === null || candidate === void 0 ? void 0 : candidate.type) === constants_1.SpecTypes.String;
26
25
  exports.isStringSpec = isStringSpec;
27
- const isReact18OrMore = () => Number(react_1.default.version.split('.')[0]) >= 18;
28
- exports.isReact18OrMore = isReact18OrMore;
@@ -38,13 +38,14 @@
38
38
  .df-card__header-left {
39
39
  display: flex;
40
40
  align-items: center;
41
+ flex-grow: 1;
41
42
  }
42
43
  .df-card__header-right {
43
44
  display: flex;
44
45
  align-items: center;
45
46
  }
46
47
  .df-card__header-right > * {
47
- margin-left: 5px;
48
+ margin-left: 10px;
48
49
  }
49
50
  .df-card__title {
50
51
  font-size: var(--yc-text-subheader-2-font-size);
@@ -46,7 +46,7 @@ const ArrayBase = ({ spec, name, arrayInput, input }) => {
46
46
  if (!itemSpec) {
47
47
  return null;
48
48
  }
49
- return (react_1.default.createElement(core_1.Controller, { initialValue: (_a = input.value) === null || _a === void 0 ? void 0 : _a[`<${key}>`], parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, spec: itemSpec, name: `${name}.<${key}>`, key: `${name}.<${key}>` }));
49
+ return (react_1.default.createElement(core_1.Controller, { value: (_a = input.value) === null || _a === void 0 ? void 0 : _a[`<${key}>`], parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, spec: itemSpec, name: `${name}.<${key}>`, key: `${name}.<${key}>` }));
50
50
  }), [keys.join(''), name, getItemSpec, parentOnChange, parentOnUnmount, input.value]);
51
51
  if (!itemSpecCorrect) {
52
52
  return null;
@@ -32,6 +32,6 @@ const CardOneOf = (props) => {
32
32
  }, [input.onChange, input.name]);
33
33
  const parentOnUnmount = react_1.default.useCallback((childName) => input.onChange((currentValue) => currentValue, { [childName]: false }), [input.onChange]);
34
34
  (0, hooks_1.useErrorChecker)({ name, meta, open, setOpen });
35
- return (react_1.default.createElement(__1.Card, { name: name, title: toggler, description: spec.viewSpec.layoutDescription, actions: actions, open: open, onToggle: onToggle, disableHeaderToggle: true }, specProperties[oneOfValue] ? (react_1.default.createElement(core_1.Controller, { initialValue: (_a = input.value) === null || _a === void 0 ? void 0 : _a[oneOfValue], spec: specProperties[oneOfValue], name: `${name}.${oneOfValue}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name}.${oneOfValue}` })) : null));
35
+ return (react_1.default.createElement(__1.Card, { name: name, title: toggler, description: spec.viewSpec.layoutDescription, actions: actions, open: open, onToggle: onToggle, disableHeaderToggle: true }, specProperties[oneOfValue] ? (react_1.default.createElement(core_1.Controller, { value: (_a = input.value) === null || _a === void 0 ? void 0 : _a[oneOfValue], spec: specProperties[oneOfValue], name: `${name}.${oneOfValue}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name}.${oneOfValue}` })) : null));
36
36
  };
37
37
  exports.CardOneOf = CardOneOf;
@@ -27,7 +27,7 @@ const ObjectBase = (_a) => {
27
27
  const specProperties = Object.assign({}, spec.properties);
28
28
  return (react_1.default.createElement(react_1.default.Fragment, null, (spec.viewSpec.order || Object.keys(specProperties)).map((property) => {
29
29
  var _a;
30
- return specProperties[property] ? (react_1.default.createElement(core_1.Controller, { initialValue: (_a = restProps.input.value) === null || _a === void 0 ? void 0 : _a[property], spec: specProperties[property], name: `${name ? name + '.' : ''}${property}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name ? name + '.' : ''}${property}` })) : null;
30
+ return specProperties[property] ? (react_1.default.createElement(core_1.Controller, { value: (_a = restProps.input.value) === null || _a === void 0 ? void 0 : _a[property], spec: specProperties[property], name: `${name ? name + '.' : ''}${property}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name ? name + '.' : ''}${property}` })) : null;
31
31
  })));
32
32
  }, [
33
33
  spec.properties,
@@ -23,7 +23,7 @@ const ObjectValueInput = (props) => {
23
23
  if (!childSpec) {
24
24
  return null;
25
25
  }
26
- const content = (react_1.default.createElement(core_1.Controller, { initialValue: (_a = input.value) === null || _a === void 0 ? void 0 : _a[OBJECT_VALUE_PROPERTY_NAME], spec: childSpec, name: `${name}.${OBJECT_VALUE_PROPERTY_NAME}`, key: `${name}.${OBJECT_VALUE_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount }));
26
+ const content = (react_1.default.createElement(core_1.Controller, { value: (_a = input.value) === null || _a === void 0 ? void 0 : _a[OBJECT_VALUE_PROPERTY_NAME], spec: childSpec, name: `${name}.${OBJECT_VALUE_PROPERTY_NAME}`, key: `${name}.${OBJECT_VALUE_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount }));
27
27
  if (Layout) {
28
28
  return react_1.default.createElement(Layout, Object.assign({}, props), content);
29
29
  }
@@ -5,10 +5,10 @@
5
5
  .df-oneof:last-child > .df-group-indent {
6
6
  margin-bottom: 0;
7
7
  }
8
- .df-oneof .df-group-indent {
8
+ .df-oneof_base .df-group-indent {
9
9
  all: unset;
10
10
  }
11
- .df-oneof .df-group-indent > .df-use-search {
11
+ .df-oneof_base .df-group-indent > .df-use-search {
12
12
  padding-top: 11px;
13
13
  padding-left: 20px;
14
14
  margin-top: 4px;
@@ -16,12 +16,23 @@
16
16
  margin-left: 5px;
17
17
  border-left: 1px solid var(--yc-color-line-generic-accent);
18
18
  }
19
- .df-oneof .df-group-indent > .df-use-search:empty {
19
+ .df-oneof_base .df-group-indent > .df-use-search:empty {
20
20
  display: none;
21
21
  }
22
- .df-oneof .df-group-indent > .df-use-search:last-child {
22
+ .df-oneof_base .df-group-indent > .df-use-search:last-child {
23
23
  margin-bottom: 0;
24
24
  }
25
- .df-oneof .df-group-indent > .df-use-search > .df-simple-vertical-accordeon_view {
25
+ .df-oneof_base .df-group-indent > .df-use-search > .df-simple-vertical-accordeon_view {
26
26
  margin-top: -10px;
27
+ }
28
+ .df-oneof_flat > .df-group-indent {
29
+ margin: 0;
30
+ border-left: none;
31
+ padding: 0;
32
+ }
33
+ .df-oneof_flat > .df-group-indent > .df-use-search {
34
+ margin-top: 15px;
35
+ }
36
+ .df-oneof_flat > .df-group-indent > .df-use-search:empty {
37
+ display: none;
27
38
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OneOf = void 0;
3
+ exports.OneOfFlat = exports.OneOf = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
@@ -9,7 +9,7 @@ const core_1 = require("../../../../core");
9
9
  const hooks_1 = require("../../../hooks");
10
10
  const utils_1 = require("../../../utils");
11
11
  const b = (0, utils_1.block)('oneof');
12
- const OneOf = (props) => {
12
+ const OneOfComponent = (props) => {
13
13
  var _a;
14
14
  const { oneOfValue, specProperties, toggler } = (0, hooks_1.useOneOf)({ props });
15
15
  const parentOnChange = react_1.default.useCallback((childName, childValue, childErrors) => {
@@ -17,9 +17,14 @@ const OneOf = (props) => {
17
17
  props.input.onChange(value, childErrors);
18
18
  }, [props.input.onChange, props.input.name]);
19
19
  const parentOnUnmount = react_1.default.useCallback((childName) => props.input.onChange((currentValue) => currentValue, { [childName]: false }), [props.input.onChange]);
20
- return (react_1.default.createElement("div", { className: b() },
20
+ return (react_1.default.createElement("div", { className: b({
21
+ base: !props.withoutIndent,
22
+ flat: props.withoutIndent,
23
+ }) },
21
24
  react_1.default.createElement("div", null, toggler),
22
25
  specProperties[oneOfValue] ? (react_1.default.createElement(__1.GroupIndent, null,
23
- react_1.default.createElement(core_1.Controller, { initialValue: (_a = props.input.value) === null || _a === void 0 ? void 0 : _a[oneOfValue], spec: specProperties[oneOfValue], name: `${props.name}.${oneOfValue}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${props.name}.${oneOfValue}` }))) : null));
26
+ react_1.default.createElement(core_1.Controller, { value: (_a = props.input.value) === null || _a === void 0 ? void 0 : _a[oneOfValue], spec: specProperties[oneOfValue], name: `${props.name}.${oneOfValue}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${props.name}.${oneOfValue}` }))) : null));
24
27
  };
25
- exports.OneOf = OneOf;
28
+ exports.OneOf = OneOfComponent;
29
+ const OneOfFlat = (props) => (react_1.default.createElement(OneOfComponent, Object.assign({}, props, { withoutIndent: true })));
30
+ exports.OneOfFlat = OneOfFlat;
@@ -39,6 +39,6 @@ const OneOfCard = (props) => {
39
39
  }, [input.onChange, input.name]);
40
40
  const parentOnUnmount = react_1.default.useCallback((childName) => input.onChange((currentValue) => currentValue, { [childName]: false }), [input.onChange]);
41
41
  (0, hooks_1.useErrorChecker)({ name, meta, open, setOpen });
42
- return (react_1.default.createElement(__1.AccordeonCard, { className: b(), name: name, header: toggler, description: spec.viewSpec.layoutDescription || '', open: open, onToggle: onToggle, ignoreHeaderToggle: true, headerActionsTemplate: headerActionsTemplate }, specProperties[oneOfValue] ? (react_1.default.createElement(core_1.Controller, { initialValue: (_a = props.input.value) === null || _a === void 0 ? void 0 : _a[oneOfValue], spec: specProperties[oneOfValue], name: `${name}.${oneOfValue}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name}.${oneOfValue}` })) : null));
42
+ return (react_1.default.createElement(__1.AccordeonCard, { className: b(), name: name, header: toggler, description: spec.viewSpec.layoutDescription || '', open: open, onToggle: onToggle, ignoreHeaderToggle: true, headerActionsTemplate: headerActionsTemplate }, specProperties[oneOfValue] ? (react_1.default.createElement(core_1.Controller, { value: (_a = props.input.value) === null || _a === void 0 ? void 0 : _a[oneOfValue], spec: specProperties[oneOfValue], name: `${name}.${oneOfValue}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name}.${oneOfValue}` })) : null));
43
43
  };
44
44
  exports.OneOfCard = OneOfCard;
@@ -23,7 +23,7 @@ const Secret = (props) => {
23
23
  if (!childSpec) {
24
24
  return null;
25
25
  }
26
- const content = (react_1.default.createElement(core_1.Controller, { initialValue: (_a = input.value) === null || _a === void 0 ? void 0 : _a[SECRET_PROPERTY_NAME], spec: childSpec, name: `${name}.${SECRET_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name}.${SECRET_PROPERTY_NAME}` }));
26
+ const content = (react_1.default.createElement(core_1.Controller, { value: (_a = input.value) === null || _a === void 0 ? void 0 : _a[SECRET_PROPERTY_NAME], spec: childSpec, name: `${name}.${SECRET_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name}.${SECRET_PROPERTY_NAME}` }));
27
27
  if (Layout) {
28
28
  return react_1.default.createElement(Layout, Object.assign({}, props), content);
29
29
  }
@@ -62,7 +62,7 @@ const TableArrayInput = ({ spec, name, arrayInput, input }) => {
62
62
  arr: (0, core_1.isArraySpec)(preparedEntitySpec),
63
63
  obj: (0, core_1.isObjectSpec)(preparedEntitySpec),
64
64
  }), key: `${name}.<${key}>.${property}` },
65
- react_1.default.createElement(core_1.Controller, { initialValue: (_c = (_b = input.value) === null || _b === void 0 ? void 0 : _b[`<${key}>`]) === null || _c === void 0 ? void 0 : _c[property], spec: preparedEntitySpec, name: `${name}.<${key}>.${property}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount })));
65
+ react_1.default.createElement(core_1.Controller, { value: (_c = (_b = input.value) === null || _b === void 0 ? void 0 : _b[`<${key}>`]) === null || _c === void 0 ? void 0 : _c[property], spec: preparedEntitySpec, name: `${name}.<${key}>.${property}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount })));
66
66
  },
67
67
  }));
68
68
  return [idxColumn, ...columns, removeColumn];
@@ -24,7 +24,7 @@ const TextLink = (props) => {
24
24
  if (!childSpec) {
25
25
  return null;
26
26
  }
27
- const content = (react_1.default.createElement(core_1.Controller, { initialValue: (_a = input.value) === null || _a === void 0 ? void 0 : _a[TEXT_LINK_PROPERTY_NAME], spec: childSpec, name: `${name}.${TEXT_LINK_PROPERTY_NAME}`, key: `${name}.${TEXT_LINK_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount }));
27
+ const content = (react_1.default.createElement(core_1.Controller, { value: (_a = input.value) === null || _a === void 0 ? void 0 : _a[TEXT_LINK_PROPERTY_NAME], spec: childSpec, name: `${name}.${TEXT_LINK_PROPERTY_NAME}`, key: `${name}.${TEXT_LINK_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount }));
28
28
  if (Layout) {
29
29
  return react_1.default.createElement(Layout, Object.assign({}, props), content);
30
30
  }
@@ -0,0 +1,8 @@
1
+ .df-oneof-view .df-group-indent {
2
+ margin-bottom: 20px;
3
+ }
4
+ .df-oneof-view_flat > .df-group-indent {
5
+ margin: 0 0 20px;
6
+ border-left: none;
7
+ padding: 0;
8
+ }
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OneOfView = void 0;
3
+ exports.OneOfFlatView = exports.OneOfView = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
7
- const __1 = require("../");
8
- const core_1 = require("../../../core");
9
- const OneOfView = (props) => {
7
+ const __1 = require("../../");
8
+ const core_1 = require("../../../../core");
9
+ const utils_1 = require("../../../utils");
10
+ const b = (0, utils_1.block)('oneof-view');
11
+ const OneOfViewComponent = (props) => {
10
12
  const { value = {}, spec, Layout, name } = props;
11
13
  const specProperties = react_1.default.useMemo(() => (lodash_1.default.isObjectLike(spec.properties) ? spec.properties : {}), [spec.properties]);
12
14
  const valueKey = react_1.default.useMemo(() => Object.keys(value)[0], [value]);
@@ -26,9 +28,11 @@ const OneOfView = (props) => {
26
28
  if (!value || !Object.keys(value).length) {
27
29
  return null;
28
30
  }
29
- return (react_1.default.createElement(react_1.default.Fragment, null,
31
+ return (react_1.default.createElement("div", { className: b({ flat: props.withoutIndent }) },
30
32
  wrappedValue,
31
33
  specProperties[valueKey] ? (react_1.default.createElement(__1.GroupIndent, null,
32
34
  react_1.default.createElement(core_1.ViewController, { spec: specProperties[valueKey], name: `${name}.${valueKey}`, key: `${name}.${valueKey}` }))) : null));
33
35
  };
34
- exports.OneOfView = OneOfView;
36
+ exports.OneOfView = OneOfViewComponent;
37
+ const OneOfFlatView = (props) => (react_1.default.createElement(OneOfViewComponent, Object.assign({}, props, { withoutIndent: true })));
38
+ exports.OneOfFlatView = OneOfFlatView;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./OneOfView"), exports);
@@ -57,6 +57,7 @@ exports.dynamicConfig = {
57
57
  object: {
58
58
  inputs: {
59
59
  oneof: { Component: components_1.OneOf, independent: true },
60
+ oneof_flat: { Component: components_1.OneOfFlat, independent: true },
60
61
  card_oneof: { Component: components_1.CardOneOf, independent: true },
61
62
  secret: { Component: components_1.Secret, independent: true },
62
63
  base: { Component: components_1.ObjectBase, independent: true },
@@ -242,6 +243,7 @@ exports.dynamicViewConfig = {
242
243
  object: {
243
244
  views: {
244
245
  oneof: { Component: components_1.OneOfView, independent: true },
246
+ oneof_flat: { Component: components_1.OneOfFlatView, independent: true },
245
247
  card_oneof: { Component: components_1.CardOneOfView, independent: true },
246
248
  secret: undefined,
247
249
  base: { Component: components_1.ObjectBaseView, independent: true },
@@ -7,6 +7,7 @@ const uikit_1 = require("@gravity-ui/uikit");
7
7
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
8
8
  const MAX_TAB_TITLE_LENGTH = 20;
9
9
  const useOneOf = ({ props, onTogglerChange }) => {
10
+ var _a;
10
11
  const { name, input, spec, Layout } = props;
11
12
  const specProperties = react_1.default.useMemo(() => (lodash_1.default.isObjectLike(spec.properties) ? spec.properties : {}), [spec.properties]);
12
13
  const [oneOfValue, setOneOfValue] = react_1.default.useState(() => {
@@ -39,12 +40,15 @@ const useOneOf = ({ props, onTogglerChange }) => {
39
40
  };
40
41
  }), [spec.description, spec.viewSpec.order, specProperties]);
41
42
  const togglerInput = react_1.default.useMemo(() => {
42
- if (options.length > 3 ||
43
- lodash_1.default.some(options, ({ title }) => title.length > MAX_TAB_TITLE_LENGTH)) {
43
+ var _a, _b;
44
+ if (((_a = spec.viewSpec.oneOfParams) === null || _a === void 0 ? void 0 : _a.toggler) !== 'radio' &&
45
+ (((_b = spec.viewSpec.oneOfParams) === null || _b === void 0 ? void 0 : _b.toggler) === 'select' ||
46
+ options.length > 3 ||
47
+ lodash_1.default.some(options, ({ title }) => title.length > MAX_TAB_TITLE_LENGTH))) {
44
48
  return (react_1.default.createElement(uikit_1.Select, { width: "max", value: [oneOfValue], onUpdate: onOneOfChange, options: options, disabled: spec.viewSpec.disabled, filterable: options.length > 7, qa: name }));
45
49
  }
46
50
  return (react_1.default.createElement(uikit_1.RadioButton, { value: oneOfValue, onChange: (event) => onOneOfChange([event.target.value]), disabled: spec.viewSpec.disabled, qa: name }, options.map((option) => (react_1.default.createElement(uikit_1.RadioButton.Option, { key: option.value, value: option.value }, option.title)))));
47
- }, [options, oneOfValue, onOneOfChange, name]);
51
+ }, [options, oneOfValue, onOneOfChange, name, (_a = spec.viewSpec.oneOfParams) === null || _a === void 0 ? void 0 : _a.toggler]);
48
52
  const toggler = react_1.default.useMemo(() => {
49
53
  if (Layout) {
50
54
  return react_1.default.createElement(Layout, Object.assign({}, props), togglerInput);
@@ -3,8 +3,8 @@ import { FieldValue, ValidateError } from './types';
3
3
  export interface ControllerProps<Value extends FieldValue, SpecType extends Spec> {
4
4
  spec: SpecType;
5
5
  name: string;
6
- initialValue: Value;
6
+ value: Value;
7
7
  parentOnChange: ((childName: string, childValue: FieldValue, childErrors: Record<string, ValidateError>) => void) | null;
8
8
  parentOnUnmount: ((childName: string) => void) | null;
9
9
  }
10
- export declare const Controller: <Value extends FieldValue, SpecType extends Spec>({ spec, name, initialValue, parentOnChange, parentOnUnmount, }: ControllerProps<Value, SpecType>) => JSX.Element | null;
10
+ export declare const Controller: <Value extends FieldValue, SpecType extends Spec>({ spec, name, value, parentOnChange, parentOnUnmount, }: ControllerProps<Value, SpecType>) => JSX.Element | null;
@@ -1,14 +1,15 @@
1
1
  import _ from 'lodash';
2
2
  import { isCorrectSpec } from '../../helpers';
3
3
  import { useComponents, useControllerMirror, useDynamicFormsCtx, useField, useRender, useSearch, useValidate, } from './hooks';
4
- export const Controller = ({ spec, name, initialValue, parentOnChange, parentOnUnmount, }) => {
4
+ export const Controller = ({ spec, name, value, parentOnChange, parentOnUnmount, }) => {
5
5
  const { tools, __mirror } = useDynamicFormsCtx();
6
6
  const { inputEntity, Layout } = useComponents(spec);
7
7
  const render = useRender({ name, spec, inputEntity, Layout });
8
8
  const validate = useValidate(spec);
9
9
  const renderProps = useField({
10
10
  name,
11
- initialValue,
11
+ initialValue: _.get(tools.initialValue, name),
12
+ value,
12
13
  spec,
13
14
  validate,
14
15
  tools,
@@ -32,7 +32,7 @@ export const DynamicField = ({ name, spec, config, Monaco, search, __mirror, })
32
32
  if (correctParams) {
33
33
  return (React.createElement(DynamicFormsCtx.Provider, { value: context },
34
34
  React.createElement(SearchContext.Provider, { value: searchContext },
35
- React.createElement(Controller, { spec: spec, name: name, parentOnChange: null, parentOnUnmount: null, initialValue: _.get(tools.initialValue, name) }),
35
+ React.createElement(Controller, { spec: spec, name: name, parentOnChange: null, parentOnUnmount: null, value: _.get(store.values, name) }),
36
36
  watcher)));
37
37
  }
38
38
  return null;
@@ -4,9 +4,10 @@ export interface UseFieldProps<Value extends FieldValue, SpecType extends Spec>
4
4
  name: string;
5
5
  spec: SpecType;
6
6
  initialValue: Value;
7
+ value: Value;
7
8
  validate?: (value?: Value) => ValidateError;
8
9
  tools: DynamicFormsContext['tools'];
9
10
  parentOnChange: ((childName: string, childValue: FieldValue, childErrors: Record<string, ValidateError>) => void) | null;
10
11
  parentOnUnmount: ((childName: string) => void) | null;
11
12
  }
12
- export declare const useField: <Value extends FieldValue, SpecType extends Spec>({ name, spec, initialValue, validate: propsValidate, tools, parentOnChange, parentOnUnmount, }: UseFieldProps<Value, SpecType>) => FieldRenderProps<Value>;
13
+ export declare const useField: <Value extends FieldValue, SpecType extends Spec>({ name, spec, initialValue, value: externalValue, validate: propsValidate, tools, parentOnChange, parentOnUnmount, }: UseFieldProps<Value, SpecType>) => FieldRenderProps<Value>;
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
2
  import _ from 'lodash';
3
- import { isArraySpec, isNumberSpec, isObjectSpec, isReact18OrMore } from '../../../helpers';
3
+ import { isArraySpec, isNumberSpec, isObjectSpec } from '../../../helpers';
4
4
  import { OBJECT_ARRAY_CNT, OBJECT_ARRAY_FLAG, REMOVED_ITEM } from '../constants';
5
5
  import { isArrayItem, transformArrIn, transformArrOut } from '../utils';
6
- export const useField = ({ name, spec, initialValue, validate: propsValidate, tools, parentOnChange, parentOnUnmount, }) => {
6
+ export const useField = ({ name, spec, initialValue, value: externalValue, validate: propsValidate, tools, parentOnChange, parentOnUnmount, }) => {
7
7
  const firstRenderRef = React.useRef(true);
8
8
  const validate = React.useCallback((value) => {
9
9
  if (value === REMOVED_ITEM) {
@@ -12,7 +12,7 @@ export const useField = ({ name, spec, initialValue, validate: propsValidate, to
12
12
  return propsValidate === null || propsValidate === void 0 ? void 0 : propsValidate(transformArrOut(value));
13
13
  }, [propsValidate]);
14
14
  const [state, setState] = React.useState(() => {
15
- let value = _.cloneDeep(initialValue);
15
+ let value = _.cloneDeep(externalValue);
16
16
  if (_.isNil(value)) {
17
17
  if (spec.defaultValue) {
18
18
  value = transformArrIn(spec.defaultValue);
@@ -29,17 +29,19 @@ export const useField = ({ name, spec, initialValue, validate: propsValidate, to
29
29
  }
30
30
  }
31
31
  const error = validate === null || validate === void 0 ? void 0 : validate(value);
32
+ const dirty = !_.isEqual(value, initialValue);
33
+ const pristine = value === initialValue;
32
34
  return {
33
35
  active: false,
34
- dirty: false,
36
+ dirty,
35
37
  error,
36
38
  invalid: Boolean(error),
37
- modified: false,
38
- pristine: false,
39
- touched: false,
39
+ modified: dirty || !pristine,
40
+ pristine,
41
+ touched: dirty || !pristine,
40
42
  valid: !error,
41
43
  value,
42
- visited: false,
44
+ visited: dirty || !pristine,
43
45
  childErrors: {},
44
46
  };
45
47
  });
@@ -125,16 +127,13 @@ export const useField = ({ name, spec, initialValue, validate: propsValidate, to
125
127
  onDrop,
126
128
  ]);
127
129
  React.useEffect(() => {
128
- if (!firstRenderRef.current || !_.isEqual(initialValue, state.value) || state.error) {
130
+ if (!firstRenderRef.current || !_.isEqual(externalValue, state.value) || state.error) {
129
131
  (parentOnChange ? parentOnChange : tools.onChange)(name, state.value, Object.assign(Object.assign({}, state.childErrors), { [name]: state.error }));
130
132
  }
131
133
  }, [state.value]);
132
134
  React.useEffect(() => {
133
135
  firstRenderRef.current = false;
134
136
  return () => {
135
- if (isReact18OrMore()) {
136
- firstRenderRef.current = true;
137
- }
138
137
  (parentOnUnmount ? parentOnUnmount : tools.onUnmount)(name);
139
138
  };
140
139
  }, []);
@@ -1,19 +1,21 @@
1
1
  import React from 'react';
2
2
  import _ from 'lodash';
3
3
  import { useForm } from 'react-final-form';
4
- import { isReact18OrMore } from '../../../helpers';
5
4
  import { transformArrIn } from '../utils';
6
5
  export const useStore = (name) => {
7
6
  const form = useForm();
8
7
  const firstRenderRef = React.useRef(true);
9
8
  const [store, setStore] = React.useState(() => {
10
- const initialValue = transformArrIn({
9
+ const values = transformArrIn({
11
10
  [name]: _.get(form.getState().values, name),
12
11
  });
12
+ const initialValue = transformArrIn({
13
+ [name]: _.get(form.getState().initialValues, name),
14
+ });
13
15
  return {
14
16
  name,
15
- initialValue,
16
- values: _.cloneDeep(initialValue),
17
+ initialValue: _.cloneDeep(initialValue),
18
+ values: _.cloneDeep(values),
17
19
  errors: {},
18
20
  };
19
21
  });
@@ -26,24 +28,22 @@ export const useStore = (name) => {
26
28
  }), [store.initialValue, setStore, submitFailed]);
27
29
  React.useEffect(() => {
28
30
  if (!firstRenderRef.current) {
29
- const initialValue = transformArrIn({
31
+ const values = transformArrIn({
30
32
  [name]: _.get(form.getState().values, name),
31
33
  });
34
+ const initialValue = transformArrIn({
35
+ [name]: _.get(form.getState().initialValues, name),
36
+ });
32
37
  setStore({
33
38
  name: name,
34
- initialValue,
35
- values: _.cloneDeep(initialValue),
39
+ initialValue: _.cloneDeep(initialValue),
40
+ values: _.cloneDeep(values),
36
41
  errors: {},
37
42
  });
38
43
  }
39
44
  }, [name]);
40
45
  React.useEffect(() => {
41
46
  firstRenderRef.current = false;
42
- return () => {
43
- if (isReact18OrMore()) {
44
- firstRenderRef.current = true;
45
- }
46
- };
47
47
  }, []);
48
48
  return { tools, store };
49
49
  };
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
2
  import type { MonacoEditorProps } from 'react-monaco-editor/lib/types';
3
- import { DynamicFormConfig, FieldObjectValue, FieldValue, ValidateError, WonderMirror } from './';
3
+ import { DynamicFormConfig, FieldValue, ValidateError, WonderMirror } from './';
4
4
  export interface DynamicFormsContext {
5
5
  config: DynamicFormConfig;
6
6
  Monaco?: React.ComponentType<MonacoEditorProps>;
7
7
  tools: {
8
- initialValue: FieldObjectValue;
8
+ initialValue: FieldValue;
9
9
  onChange: (name: string, value: FieldValue, errors?: Record<string, ValidateError>) => void;
10
10
  onUnmount: (name: string) => void;
11
11
  submitFailed: boolean;
@@ -5,4 +5,3 @@ export declare const isBooleanSpec: (candidate: any) => candidate is BooleanSpec
5
5
  export declare const isNumberSpec: (candidate: any) => candidate is NumberSpec<any>;
6
6
  export declare const isObjectSpec: (candidate: any) => candidate is ObjectSpec<any>;
7
7
  export declare const isStringSpec: (candidate: any) => candidate is StringSpec<any>;
8
- export declare const isReact18OrMore: () => boolean;
@@ -1,4 +1,3 @@
1
- import React from 'react';
2
1
  import _ from 'lodash';
3
2
  import { SpecTypes } from './constants';
4
3
  export const isCorrectSpec = (candidate) => _.isObjectLike(candidate) &&
@@ -14,4 +13,3 @@ export const isBooleanSpec = (candidate) => (candidate === null || candidate ===
14
13
  export const isNumberSpec = (candidate) => (candidate === null || candidate === void 0 ? void 0 : candidate.type) === SpecTypes.Number;
15
14
  export const isObjectSpec = (candidate) => (candidate === null || candidate === void 0 ? void 0 : candidate.type) === SpecTypes.Object;
16
15
  export const isStringSpec = (candidate) => (candidate === null || candidate === void 0 ? void 0 : candidate.type) === SpecTypes.String;
17
- export const isReact18OrMore = () => Number(React.version.split('.')[0]) >= 18;
@@ -77,6 +77,9 @@ export interface ObjectSpec<LinkType = any> {
77
77
  layoutOpen?: boolean;
78
78
  order?: string[];
79
79
  link?: LinkType;
80
+ oneOfParams?: {
81
+ toggler?: 'select' | 'radio';
82
+ };
80
83
  };
81
84
  }
82
85
  export interface StringSpec<LinkType = any> {
@@ -38,13 +38,14 @@
38
38
  .df-card__header-left {
39
39
  display: flex;
40
40
  align-items: center;
41
+ flex-grow: 1;
41
42
  }
42
43
  .df-card__header-right {
43
44
  display: flex;
44
45
  align-items: center;
45
46
  }
46
47
  .df-card__header-right > * {
47
- margin-left: 5px;
48
+ margin-left: 10px;
48
49
  }
49
50
  .df-card__title {
50
51
  font-size: var(--yc-text-subheader-2-font-size);
@@ -42,7 +42,7 @@ export const ArrayBase = ({ spec, name, arrayInput, input }) => {
42
42
  if (!itemSpec) {
43
43
  return null;
44
44
  }
45
- return (React.createElement(Controller, { initialValue: (_a = input.value) === null || _a === void 0 ? void 0 : _a[`<${key}>`], parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, spec: itemSpec, name: `${name}.<${key}>`, key: `${name}.<${key}>` }));
45
+ return (React.createElement(Controller, { value: (_a = input.value) === null || _a === void 0 ? void 0 : _a[`<${key}>`], parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, spec: itemSpec, name: `${name}.<${key}>`, key: `${name}.<${key}>` }));
46
46
  }), [keys.join(''), name, getItemSpec, parentOnChange, parentOnUnmount, input.value]);
47
47
  if (!itemSpecCorrect) {
48
48
  return null;
@@ -28,5 +28,5 @@ export const CardOneOf = (props) => {
28
28
  }, [input.onChange, input.name]);
29
29
  const parentOnUnmount = React.useCallback((childName) => input.onChange((currentValue) => currentValue, { [childName]: false }), [input.onChange]);
30
30
  useErrorChecker({ name, meta, open, setOpen });
31
- return (React.createElement(Card, { name: name, title: toggler, description: spec.viewSpec.layoutDescription, actions: actions, open: open, onToggle: onToggle, disableHeaderToggle: true }, specProperties[oneOfValue] ? (React.createElement(Controller, { initialValue: (_a = input.value) === null || _a === void 0 ? void 0 : _a[oneOfValue], spec: specProperties[oneOfValue], name: `${name}.${oneOfValue}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name}.${oneOfValue}` })) : null));
31
+ return (React.createElement(Card, { name: name, title: toggler, description: spec.viewSpec.layoutDescription, actions: actions, open: open, onToggle: onToggle, disableHeaderToggle: true }, specProperties[oneOfValue] ? (React.createElement(Controller, { value: (_a = input.value) === null || _a === void 0 ? void 0 : _a[oneOfValue], spec: specProperties[oneOfValue], name: `${name}.${oneOfValue}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name}.${oneOfValue}` })) : null));
32
32
  };
@@ -24,7 +24,7 @@ export const ObjectBase = (_a) => {
24
24
  const specProperties = Object.assign({}, spec.properties);
25
25
  return (React.createElement(React.Fragment, null, (spec.viewSpec.order || Object.keys(specProperties)).map((property) => {
26
26
  var _a;
27
- return specProperties[property] ? (React.createElement(Controller, { initialValue: (_a = restProps.input.value) === null || _a === void 0 ? void 0 : _a[property], spec: specProperties[property], name: `${name ? name + '.' : ''}${property}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name ? name + '.' : ''}${property}` })) : null;
27
+ return specProperties[property] ? (React.createElement(Controller, { value: (_a = restProps.input.value) === null || _a === void 0 ? void 0 : _a[property], spec: specProperties[property], name: `${name ? name + '.' : ''}${property}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name ? name + '.' : ''}${property}` })) : null;
28
28
  })));
29
29
  }, [
30
30
  spec.properties,
@@ -19,7 +19,7 @@ export const ObjectValueInput = (props) => {
19
19
  if (!childSpec) {
20
20
  return null;
21
21
  }
22
- const content = (React.createElement(Controller, { initialValue: (_a = input.value) === null || _a === void 0 ? void 0 : _a[OBJECT_VALUE_PROPERTY_NAME], spec: childSpec, name: `${name}.${OBJECT_VALUE_PROPERTY_NAME}`, key: `${name}.${OBJECT_VALUE_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount }));
22
+ const content = (React.createElement(Controller, { value: (_a = input.value) === null || _a === void 0 ? void 0 : _a[OBJECT_VALUE_PROPERTY_NAME], spec: childSpec, name: `${name}.${OBJECT_VALUE_PROPERTY_NAME}`, key: `${name}.${OBJECT_VALUE_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount }));
23
23
  if (Layout) {
24
24
  return React.createElement(Layout, Object.assign({}, props), content);
25
25
  }
@@ -5,10 +5,10 @@
5
5
  .df-oneof:last-child > .df-group-indent {
6
6
  margin-bottom: 0;
7
7
  }
8
- .df-oneof .df-group-indent {
8
+ .df-oneof_base .df-group-indent {
9
9
  all: unset;
10
10
  }
11
- .df-oneof .df-group-indent > .df-use-search {
11
+ .df-oneof_base .df-group-indent > .df-use-search {
12
12
  padding-top: 11px;
13
13
  padding-left: 20px;
14
14
  margin-top: 4px;
@@ -16,12 +16,23 @@
16
16
  margin-left: 5px;
17
17
  border-left: 1px solid var(--yc-color-line-generic-accent);
18
18
  }
19
- .df-oneof .df-group-indent > .df-use-search:empty {
19
+ .df-oneof_base .df-group-indent > .df-use-search:empty {
20
20
  display: none;
21
21
  }
22
- .df-oneof .df-group-indent > .df-use-search:last-child {
22
+ .df-oneof_base .df-group-indent > .df-use-search:last-child {
23
23
  margin-bottom: 0;
24
24
  }
25
- .df-oneof .df-group-indent > .df-use-search > .df-simple-vertical-accordeon_view {
25
+ .df-oneof_base .df-group-indent > .df-use-search > .df-simple-vertical-accordeon_view {
26
26
  margin-top: -10px;
27
+ }
28
+ .df-oneof_flat > .df-group-indent {
29
+ margin: 0;
30
+ border-left: none;
31
+ padding: 0;
32
+ }
33
+ .df-oneof_flat > .df-group-indent > .df-use-search {
34
+ margin-top: 15px;
35
+ }
36
+ .df-oneof_flat > .df-group-indent > .df-use-search:empty {
37
+ display: none;
27
38
  }
@@ -1,3 +1,8 @@
1
- import { ObjectIndependentInput } from '../../../../core';
1
+ import React from 'react';
2
+ import { ObjectIndependentInput, ObjectIndependentInputProps } from '../../../../core';
2
3
  import './OneOf.css';
3
- export declare const OneOf: ObjectIndependentInput;
4
+ export interface OneOfProps extends ObjectIndependentInputProps {
5
+ withoutIndent?: boolean;
6
+ }
7
+ export declare const OneOf: React.FC<OneOfProps>;
8
+ export declare const OneOfFlat: ObjectIndependentInput;
@@ -1,12 +1,12 @@
1
1
  import React from 'react';
2
2
  import _ from 'lodash';
3
3
  import { GroupIndent } from '../../';
4
- import { Controller } from '../../../../core';
4
+ import { Controller, } from '../../../../core';
5
5
  import { useOneOf } from '../../../hooks';
6
6
  import { block } from '../../../utils';
7
7
  import './OneOf.css';
8
8
  const b = block('oneof');
9
- export const OneOf = (props) => {
9
+ const OneOfComponent = (props) => {
10
10
  var _a;
11
11
  const { oneOfValue, specProperties, toggler } = useOneOf({ props });
12
12
  const parentOnChange = React.useCallback((childName, childValue, childErrors) => {
@@ -14,8 +14,13 @@ export const OneOf = (props) => {
14
14
  props.input.onChange(value, childErrors);
15
15
  }, [props.input.onChange, props.input.name]);
16
16
  const parentOnUnmount = React.useCallback((childName) => props.input.onChange((currentValue) => currentValue, { [childName]: false }), [props.input.onChange]);
17
- return (React.createElement("div", { className: b() },
17
+ return (React.createElement("div", { className: b({
18
+ base: !props.withoutIndent,
19
+ flat: props.withoutIndent,
20
+ }) },
18
21
  React.createElement("div", null, toggler),
19
22
  specProperties[oneOfValue] ? (React.createElement(GroupIndent, null,
20
- React.createElement(Controller, { initialValue: (_a = props.input.value) === null || _a === void 0 ? void 0 : _a[oneOfValue], spec: specProperties[oneOfValue], name: `${props.name}.${oneOfValue}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${props.name}.${oneOfValue}` }))) : null));
23
+ React.createElement(Controller, { value: (_a = props.input.value) === null || _a === void 0 ? void 0 : _a[oneOfValue], spec: specProperties[oneOfValue], name: `${props.name}.${oneOfValue}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${props.name}.${oneOfValue}` }))) : null));
21
24
  };
25
+ export const OneOf = OneOfComponent;
26
+ export const OneOfFlat = (props) => (React.createElement(OneOfComponent, Object.assign({}, props, { withoutIndent: true })));
@@ -36,5 +36,5 @@ export const OneOfCard = (props) => {
36
36
  }, [input.onChange, input.name]);
37
37
  const parentOnUnmount = React.useCallback((childName) => input.onChange((currentValue) => currentValue, { [childName]: false }), [input.onChange]);
38
38
  useErrorChecker({ name, meta, open, setOpen });
39
- return (React.createElement(AccordeonCard, { className: b(), name: name, header: toggler, description: spec.viewSpec.layoutDescription || '', open: open, onToggle: onToggle, ignoreHeaderToggle: true, headerActionsTemplate: headerActionsTemplate }, specProperties[oneOfValue] ? (React.createElement(Controller, { initialValue: (_a = props.input.value) === null || _a === void 0 ? void 0 : _a[oneOfValue], spec: specProperties[oneOfValue], name: `${name}.${oneOfValue}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name}.${oneOfValue}` })) : null));
39
+ return (React.createElement(AccordeonCard, { className: b(), name: name, header: toggler, description: spec.viewSpec.layoutDescription || '', open: open, onToggle: onToggle, ignoreHeaderToggle: true, headerActionsTemplate: headerActionsTemplate }, specProperties[oneOfValue] ? (React.createElement(Controller, { value: (_a = props.input.value) === null || _a === void 0 ? void 0 : _a[oneOfValue], spec: specProperties[oneOfValue], name: `${name}.${oneOfValue}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name}.${oneOfValue}` })) : null));
40
40
  };
@@ -19,7 +19,7 @@ export const Secret = (props) => {
19
19
  if (!childSpec) {
20
20
  return null;
21
21
  }
22
- const content = (React.createElement(Controller, { initialValue: (_a = input.value) === null || _a === void 0 ? void 0 : _a[SECRET_PROPERTY_NAME], spec: childSpec, name: `${name}.${SECRET_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name}.${SECRET_PROPERTY_NAME}` }));
22
+ const content = (React.createElement(Controller, { value: (_a = input.value) === null || _a === void 0 ? void 0 : _a[SECRET_PROPERTY_NAME], spec: childSpec, name: `${name}.${SECRET_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount, key: `${name}.${SECRET_PROPERTY_NAME}` }));
23
23
  if (Layout) {
24
24
  return React.createElement(Layout, Object.assign({}, props), content);
25
25
  }
@@ -59,7 +59,7 @@ export const TableArrayInput = ({ spec, name, arrayInput, input }) => {
59
59
  arr: isArraySpec(preparedEntitySpec),
60
60
  obj: isObjectSpec(preparedEntitySpec),
61
61
  }), key: `${name}.<${key}>.${property}` },
62
- React.createElement(Controller, { initialValue: (_c = (_b = input.value) === null || _b === void 0 ? void 0 : _b[`<${key}>`]) === null || _c === void 0 ? void 0 : _c[property], spec: preparedEntitySpec, name: `${name}.<${key}>.${property}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount })));
62
+ React.createElement(Controller, { value: (_c = (_b = input.value) === null || _b === void 0 ? void 0 : _b[`<${key}>`]) === null || _c === void 0 ? void 0 : _c[property], spec: preparedEntitySpec, name: `${name}.<${key}>.${property}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount })));
63
63
  },
64
64
  }));
65
65
  return [idxColumn, ...columns, removeColumn];
@@ -20,7 +20,7 @@ export const TextLink = (props) => {
20
20
  if (!childSpec) {
21
21
  return null;
22
22
  }
23
- const content = (React.createElement(Controller, { initialValue: (_a = input.value) === null || _a === void 0 ? void 0 : _a[TEXT_LINK_PROPERTY_NAME], spec: childSpec, name: `${name}.${TEXT_LINK_PROPERTY_NAME}`, key: `${name}.${TEXT_LINK_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount }));
23
+ const content = (React.createElement(Controller, { value: (_a = input.value) === null || _a === void 0 ? void 0 : _a[TEXT_LINK_PROPERTY_NAME], spec: childSpec, name: `${name}.${TEXT_LINK_PROPERTY_NAME}`, key: `${name}.${TEXT_LINK_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount }));
24
24
  if (Layout) {
25
25
  return React.createElement(Layout, Object.assign({}, props), content);
26
26
  }
@@ -0,0 +1,8 @@
1
+ .df-oneof-view .df-group-indent {
2
+ margin-bottom: 20px;
3
+ }
4
+ .df-oneof-view_flat > .df-group-indent {
5
+ margin: 0 0 20px;
6
+ border-left: none;
7
+ padding: 0;
8
+ }
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { ObjectIndependentView, ObjectIndependentViewProps } from '../../../../core';
3
+ import './OneOfView.css';
4
+ export interface OneOfViewProps extends ObjectIndependentViewProps {
5
+ withoutIndent?: boolean;
6
+ }
7
+ export declare const OneOfView: React.FC<OneOfViewProps>;
8
+ export declare const OneOfFlatView: ObjectIndependentView;
@@ -1,8 +1,11 @@
1
1
  import React from 'react';
2
2
  import _ from 'lodash';
3
- import { GroupIndent } from '../';
4
- import { ViewController } from '../../../core';
5
- export const OneOfView = (props) => {
3
+ import { GroupIndent } from '../../';
4
+ import { ViewController } from '../../../../core';
5
+ import { block } from '../../../utils';
6
+ import './OneOfView.css';
7
+ const b = block('oneof-view');
8
+ const OneOfViewComponent = (props) => {
6
9
  const { value = {}, spec, Layout, name } = props;
7
10
  const specProperties = React.useMemo(() => (_.isObjectLike(spec.properties) ? spec.properties : {}), [spec.properties]);
8
11
  const valueKey = React.useMemo(() => Object.keys(value)[0], [value]);
@@ -22,8 +25,10 @@ export const OneOfView = (props) => {
22
25
  if (!value || !Object.keys(value).length) {
23
26
  return null;
24
27
  }
25
- return (React.createElement(React.Fragment, null,
28
+ return (React.createElement("div", { className: b({ flat: props.withoutIndent }) },
26
29
  wrappedValue,
27
30
  specProperties[valueKey] ? (React.createElement(GroupIndent, null,
28
31
  React.createElement(ViewController, { spec: specProperties[valueKey], name: `${name}.${valueKey}`, key: `${name}.${valueKey}` }))) : null));
29
32
  };
33
+ export const OneOfView = OneOfViewComponent;
34
+ export const OneOfFlatView = (props) => (React.createElement(OneOfViewComponent, Object.assign({}, props, { withoutIndent: true })));
@@ -0,0 +1 @@
1
+ export * from './OneOfView';
@@ -0,0 +1 @@
1
+ export * from './OneOfView';
@@ -1,4 +1,4 @@
1
- import { Accordeon, AccordeonCardLayout, ArrayBase, ArrayBaseView, BaseView, CardAccordeon, CardOneOf, CardOneOfView, CardSection, Checkbox, FileInput, FileInputView, Group, Group2, MonacoInput, MonacoInputCard, MonacoView, MonacoViewCard, MultiSelect, MultiSelectView, NumberWithScale, NumberWithScaleView, ObjectBase, ObjectBaseView, ObjectValueInput, ObjectValueInputView, OneOf, OneOfCard, OneOfCardView, OneOfView, Row, Row2, RowVerbose, Secret, Section, Section2, SectionCard, SectionCard2, SectionWithSubtitle, SectionWithSubtitle2, Select, TableArrayInput, TableArrayView, TableCell, Text, TextArea, TextAreaView, TextContent, TextLink, TextLinkView, Transparent, ViewAccordeon, ViewAccordeonCard, ViewCardAccordeon, ViewCardSection, ViewGroup, ViewGroup2, ViewRow, ViewRow2, ViewSection, ViewSection2, ViewSectionCard, ViewSectionCard2, ViewTableCell, ViewTransparent, } from '../components';
1
+ import { Accordeon, AccordeonCardLayout, ArrayBase, ArrayBaseView, BaseView, CardAccordeon, CardOneOf, CardOneOfView, CardSection, Checkbox, FileInput, FileInputView, Group, Group2, MonacoInput, MonacoInputCard, MonacoView, MonacoViewCard, MultiSelect, MultiSelectView, NumberWithScale, NumberWithScaleView, ObjectBase, ObjectBaseView, ObjectValueInput, ObjectValueInputView, OneOf, OneOfCard, OneOfCardView, OneOfFlat, OneOfFlatView, OneOfView, Row, Row2, RowVerbose, Secret, Section, Section2, SectionCard, SectionCard2, SectionWithSubtitle, SectionWithSubtitle2, Select, TableArrayInput, TableArrayView, TableCell, Text, TextArea, TextAreaView, TextContent, TextLink, TextLinkView, Transparent, ViewAccordeon, ViewAccordeonCard, ViewCardAccordeon, ViewCardSection, ViewGroup, ViewGroup2, ViewRow, ViewRow2, ViewSection, ViewSection2, ViewSectionCard, ViewSectionCard2, ViewTableCell, ViewTransparent, } from '../components';
2
2
  import { getArrayValidator, getBooleanValidator, getNumberValidator, getObjectValidator, getStringValidator, } from '../validators';
3
3
  export const dynamicConfig = {
4
4
  array: {
@@ -54,6 +54,7 @@ export const dynamicConfig = {
54
54
  object: {
55
55
  inputs: {
56
56
  oneof: { Component: OneOf, independent: true },
57
+ oneof_flat: { Component: OneOfFlat, independent: true },
57
58
  card_oneof: { Component: CardOneOf, independent: true },
58
59
  secret: { Component: Secret, independent: true },
59
60
  base: { Component: ObjectBase, independent: true },
@@ -239,6 +240,7 @@ export const dynamicViewConfig = {
239
240
  object: {
240
241
  views: {
241
242
  oneof: { Component: OneOfView, independent: true },
243
+ oneof_flat: { Component: OneOfFlatView, independent: true },
242
244
  card_oneof: { Component: CardOneOfView, independent: true },
243
245
  secret: undefined,
244
246
  base: { Component: ObjectBaseView, independent: true },
@@ -3,6 +3,7 @@ import { RadioButton, Select } from '@gravity-ui/uikit';
3
3
  import _ from 'lodash';
4
4
  const MAX_TAB_TITLE_LENGTH = 20;
5
5
  export const useOneOf = ({ props, onTogglerChange }) => {
6
+ var _a;
6
7
  const { name, input, spec, Layout } = props;
7
8
  const specProperties = React.useMemo(() => (_.isObjectLike(spec.properties) ? spec.properties : {}), [spec.properties]);
8
9
  const [oneOfValue, setOneOfValue] = React.useState(() => {
@@ -35,12 +36,15 @@ export const useOneOf = ({ props, onTogglerChange }) => {
35
36
  };
36
37
  }), [spec.description, spec.viewSpec.order, specProperties]);
37
38
  const togglerInput = React.useMemo(() => {
38
- if (options.length > 3 ||
39
- _.some(options, ({ title }) => title.length > MAX_TAB_TITLE_LENGTH)) {
39
+ var _a, _b;
40
+ if (((_a = spec.viewSpec.oneOfParams) === null || _a === void 0 ? void 0 : _a.toggler) !== 'radio' &&
41
+ (((_b = spec.viewSpec.oneOfParams) === null || _b === void 0 ? void 0 : _b.toggler) === 'select' ||
42
+ options.length > 3 ||
43
+ _.some(options, ({ title }) => title.length > MAX_TAB_TITLE_LENGTH))) {
40
44
  return (React.createElement(Select, { width: "max", value: [oneOfValue], onUpdate: onOneOfChange, options: options, disabled: spec.viewSpec.disabled, filterable: options.length > 7, qa: name }));
41
45
  }
42
46
  return (React.createElement(RadioButton, { value: oneOfValue, onChange: (event) => onOneOfChange([event.target.value]), disabled: spec.viewSpec.disabled, qa: name }, options.map((option) => (React.createElement(RadioButton.Option, { key: option.value, value: option.value }, option.title)))));
43
- }, [options, oneOfValue, onOneOfChange, name]);
47
+ }, [options, oneOfValue, onOneOfChange, name, (_a = spec.viewSpec.oneOfParams) === null || _a === void 0 ? void 0 : _a.toggler]);
44
48
  const toggler = React.useMemo(() => {
45
49
  if (Layout) {
46
50
  return React.createElement(Layout, Object.assign({}, props), togglerInput);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dynamic-forms",
3
- "version": "1.6.2",
3
+ "version": "1.7.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "main": "build/cjs/index.js",
@@ -1,2 +0,0 @@
1
- import { ObjectIndependentView } from '../../../core';
2
- export declare const OneOfView: ObjectIndependentView;