@gravity-ui/dynamic-forms 2.4.0 → 2.6.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 (56) hide show
  1. package/build/cjs/lib/core/components/Form/Controller.js +1 -1
  2. package/build/cjs/lib/kit/components/Inputs/ArrayBase/ArrayBase.js +2 -14
  3. package/build/cjs/lib/kit/components/Inputs/MultiSelect/MultiSelect.css +3 -0
  4. package/build/cjs/lib/kit/components/Inputs/MultiSelect/MultiSelect.js +18 -5
  5. package/build/cjs/lib/kit/components/Inputs/ObjectBase/ObjectBase.css +11 -0
  6. package/build/cjs/lib/kit/components/Inputs/ObjectBase/ObjectBase.js +19 -8
  7. package/build/cjs/lib/kit/components/Inputs/Select/Select.css +3 -0
  8. package/build/cjs/lib/kit/components/Inputs/Select/Select.js +18 -5
  9. package/build/cjs/lib/kit/components/Inputs/TextContent/TextContent.css +11 -0
  10. package/build/cjs/lib/kit/components/Inputs/TextContent/TextContent.js +25 -8
  11. package/build/cjs/lib/kit/components/Inputs/TextContent/utils.js +22 -0
  12. package/build/cjs/lib/kit/components/LazyLoader/LazyLoader.js +22 -0
  13. package/build/cjs/lib/kit/components/LazyLoader/index.js +4 -0
  14. package/build/cjs/lib/kit/components/Views/ObjectBaseView/ObjectBaseView.css +11 -0
  15. package/build/cjs/lib/kit/components/Views/ObjectBaseView/ObjectBaseView.js +28 -0
  16. package/build/cjs/lib/kit/components/Views/ObjectBaseView/index.js +4 -0
  17. package/build/cjs/lib/kit/components/index.js +1 -0
  18. package/build/cjs/lib/kit/constants/config.js +4 -0
  19. package/build/cjs/lib/kit/utils/common.js +10 -3
  20. package/build/cjs/lib/kit/utils/index.js +1 -0
  21. package/build/cjs/lib/kit/utils/objectInline.js +8 -0
  22. package/build/esm/lib/core/components/Form/Controller.js +1 -1
  23. package/build/esm/lib/core/types/specs.d.ts +20 -1
  24. package/build/esm/lib/kit/components/Inputs/ArrayBase/ArrayBase.js +3 -15
  25. package/build/esm/lib/kit/components/Inputs/MultiSelect/MultiSelect.css +3 -0
  26. package/build/esm/lib/kit/components/Inputs/MultiSelect/MultiSelect.js +19 -6
  27. package/build/esm/lib/kit/components/Inputs/ObjectBase/ObjectBase.css +11 -0
  28. package/build/esm/lib/kit/components/Inputs/ObjectBase/ObjectBase.d.ts +8 -2
  29. package/build/esm/lib/kit/components/Inputs/ObjectBase/ObjectBase.js +18 -7
  30. package/build/esm/lib/kit/components/Inputs/Select/Select.css +3 -0
  31. package/build/esm/lib/kit/components/Inputs/Select/Select.js +19 -6
  32. package/build/esm/lib/kit/components/Inputs/TextContent/TextContent.css +11 -0
  33. package/build/esm/lib/kit/components/Inputs/TextContent/TextContent.js +26 -9
  34. package/build/esm/lib/kit/components/Inputs/TextContent/utils.d.ts +2 -0
  35. package/build/esm/lib/kit/components/Inputs/TextContent/utils.js +17 -0
  36. package/build/esm/lib/kit/components/LazyLoader/LazyLoader.d.ts +6 -0
  37. package/build/esm/lib/kit/components/LazyLoader/LazyLoader.js +17 -0
  38. package/build/esm/lib/kit/components/LazyLoader/index.d.ts +1 -0
  39. package/build/esm/lib/kit/components/LazyLoader/index.js +1 -0
  40. package/build/esm/lib/kit/components/Views/ObjectBaseView/ObjectBaseView.css +11 -0
  41. package/build/esm/lib/kit/components/Views/ObjectBaseView/ObjectBaseView.d.ts +8 -0
  42. package/build/esm/lib/kit/components/Views/ObjectBaseView/ObjectBaseView.js +24 -0
  43. package/build/esm/lib/kit/components/Views/ObjectBaseView/index.d.ts +1 -0
  44. package/build/esm/lib/kit/components/Views/ObjectBaseView/index.js +1 -0
  45. package/build/esm/lib/kit/components/index.d.ts +1 -0
  46. package/build/esm/lib/kit/components/index.js +1 -0
  47. package/build/esm/lib/kit/constants/config.js +5 -1
  48. package/build/esm/lib/kit/utils/common.js +10 -3
  49. package/build/esm/lib/kit/utils/index.d.ts +1 -0
  50. package/build/esm/lib/kit/utils/index.js +1 -0
  51. package/build/esm/lib/kit/utils/objectInline.d.ts +4 -0
  52. package/build/esm/lib/kit/utils/objectInline.js +4 -0
  53. package/package.json +1 -1
  54. package/build/cjs/lib/kit/components/Views/ObjectBaseView.js +0 -20
  55. package/build/esm/lib/kit/components/Views/ObjectBaseView.d.ts +0 -2
  56. package/build/esm/lib/kit/components/Views/ObjectBaseView.js +0 -16
@@ -28,7 +28,7 @@ const Controller = ({ spec, name, value, parentOnChange, parentOnUnmount, }) =>
28
28
  useField: renderProps,
29
29
  useSearch: withSearch,
30
30
  }, __mirror);
31
- if (lodash_1.default.isString(name) && (0, helpers_1.isCorrectSpec)(spec)) {
31
+ if (lodash_1.default.isString(name) && (0, helpers_1.isCorrectSpec)(spec) && !spec.viewSpec.hideInput) {
32
32
  return withSearch(render(renderProps));
33
33
  }
34
34
  return null;
@@ -27,19 +27,7 @@ const ArrayBase = ({ spec, name, arrayInput, input }) => {
27
27
  }, [spec.items, itemSpecCorrect]);
28
28
  const parentOnChange = react_1.default.useCallback((childName, childValue, childErrors) => input.onChange((currentValue) => lodash_1.default.set(Object.assign({}, currentValue), childName.split(`${input.name}.`).join(''), childValue), childErrors), [input.onChange, input.name]);
29
29
  const AddButton = react_1.default.useCallback(() => {
30
- let onClick = () => {
31
- var _a;
32
- let item;
33
- if (!((_a = spec.items) === null || _a === void 0 ? void 0 : _a.required)) {
34
- if ((0, core_1.isArraySpec)(spec.items)) {
35
- item = { [core_1.OBJECT_ARRAY_FLAG]: true, [core_1.OBJECT_ARRAY_CNT]: 0 };
36
- }
37
- else if ((0, core_1.isObjectSpec)(spec.items)) {
38
- item = {};
39
- }
40
- }
41
- arrayInput.onItemAdd(item);
42
- };
30
+ let onClick = () => arrayInput.onItemAdd(undefined);
43
31
  let qa = `${name}-add-item`;
44
32
  let title = spec.viewSpec.itemLabel;
45
33
  if (!arrayInput.value && spec.defaultValue) {
@@ -57,10 +45,10 @@ const ArrayBase = ({ spec, name, arrayInput, input }) => {
57
45
  input,
58
46
  name,
59
47
  spec.defaultValue,
60
- spec.items,
61
48
  spec.viewSpec.disabled,
62
49
  spec.viewSpec.itemLabel,
63
50
  spec.viewSpec.layoutTitle,
51
+ spec.viewSpec.addButtonPosition,
64
52
  ]);
65
53
  const items = react_1.default.useMemo(() => keys.map((key, idx) => {
66
54
  var _a;
@@ -1,3 +1,6 @@
1
1
  .df-multi-select {
2
2
  max-width: 305px;
3
+ }
4
+ .df-multi-select__meta-text {
5
+ display: block;
3
6
  }
@@ -8,21 +8,34 @@ const core_1 = require("../../../../core");
8
8
  const utils_1 = require("../../../utils");
9
9
  const b = (0, utils_1.block)('multi-select');
10
10
  const MultiSelect = ({ name, input, spec }) => {
11
- var _a;
11
+ var _a, _b, _c, _d;
12
12
  const { value, onBlur, onChange, onFocus } = input;
13
13
  const filterable = react_1.default.useMemo(() => { var _a; return (((_a = spec.enum) === null || _a === void 0 ? void 0 : _a.length) || 0) > 9; }, [(_a = spec.enum) === null || _a === void 0 ? void 0 : _a.length]);
14
14
  const options = react_1.default.useMemo(() => {
15
15
  var _a;
16
16
  return (_a = spec.enum) === null || _a === void 0 ? void 0 : _a.map((id) => {
17
- var _a;
17
+ var _a, _b, _c, _d, _e;
18
18
  return ({
19
19
  id,
20
20
  value: id,
21
- content: ((_a = spec.description) === null || _a === void 0 ? void 0 : _a[id]) || id,
21
+ text: ((_a = spec.description) === null || _a === void 0 ? void 0 : _a[id]) || id,
22
+ content: ((_c = (_b = spec.viewSpec.selectParams) === null || _b === void 0 ? void 0 : _b.meta) === null || _c === void 0 ? void 0 : _c[id]) ? (react_1.default.createElement("div", { key: id },
23
+ react_1.default.createElement(uikit_1.Text, null, ((_d = spec.description) === null || _d === void 0 ? void 0 : _d[id]) || id),
24
+ react_1.default.createElement(uikit_1.Text, { color: "secondary", className: b('meta-text') }, spec.viewSpec.selectParams.meta[id]))) : (((_e = spec.description) === null || _e === void 0 ? void 0 : _e[id]) || id),
22
25
  key: id,
23
26
  });
24
27
  });
25
- }, [spec.enum, spec.description]);
28
+ }, [spec.enum, spec.description, (_b = spec.viewSpec.selectParams) === null || _b === void 0 ? void 0 : _b.meta]);
29
+ const renderOption = react_1.default.useCallback((option) => {
30
+ return react_1.default.createElement(react_1.default.Fragment, { key: option.value }, option.content || option.value);
31
+ }, []);
32
+ const getOptionHeight = react_1.default.useCallback(() => {
33
+ var _a;
34
+ if ((_a = spec.viewSpec.selectParams) === null || _a === void 0 ? void 0 : _a.meta) {
35
+ return 44;
36
+ }
37
+ return 28;
38
+ }, [(_c = spec.viewSpec.selectParams) === null || _c === void 0 ? void 0 : _c.meta]);
26
39
  const handleToggle = react_1.default.useCallback((open) => {
27
40
  if (open) {
28
41
  onFocus();
@@ -33,6 +46,6 @@ const MultiSelect = ({ name, input, spec }) => {
33
46
  }, [onFocus, onBlur]);
34
47
  const _value = react_1.default.useMemo(() => (0, core_1.transformArrOut)(value), [value]);
35
48
  const handleChange = react_1.default.useCallback((value) => onChange((0, core_1.transformArrIn)(value)), [onChange]);
36
- return (react_1.default.createElement(uikit_1.Select, { width: "max", className: b(), value: _value, options: options, onUpdate: handleChange, onOpenChange: handleToggle, disabled: spec.viewSpec.disabled, placeholder: spec.viewSpec.placeholder, filterable: filterable, multiple: true, qa: name }));
49
+ return (react_1.default.createElement(uikit_1.Select, { width: "max", className: b(), value: _value, options: options, onUpdate: handleChange, onOpenChange: handleToggle, disabled: spec.viewSpec.disabled, placeholder: spec.viewSpec.placeholder, filterable: filterable, filterPlaceholder: (_d = spec.viewSpec.selectParams) === null || _d === void 0 ? void 0 : _d.filterPlaceholder, renderOption: renderOption, getOptionHeight: getOptionHeight, multiple: true, qa: name }));
37
50
  };
38
51
  exports.MultiSelect = MultiSelect;
@@ -0,0 +1,11 @@
1
+ .df-object-base__content_inline {
2
+ display: flex;
3
+ }
4
+ .df-object-base__content_inline > .df-use-search {
5
+ width: 150px;
6
+ margin-bottom: 0;
7
+ margin-right: 8px;
8
+ }
9
+ .df-object-base__content_inline > .df-use-search:last-child {
10
+ margin-right: 0;
11
+ }
@@ -1,14 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ObjectBase = void 0;
3
+ exports.ObjectInline = exports.ObjectBase = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const icons_1 = require("@gravity-ui/icons");
7
7
  const uikit_1 = require("@gravity-ui/uikit");
8
8
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
9
9
  const core_1 = require("../../../../core");
10
+ const utils_1 = require("../../../utils");
11
+ const b = (0, utils_1.block)('object-base');
10
12
  const ObjectBase = (_a) => {
11
- var { spec, name, Layout } = _a, restProps = tslib_1.__rest(_a, ["spec", "name", "Layout"]);
13
+ var { inline, spec, name, Layout } = _a, restProps = tslib_1.__rest(_a, ["inline", "spec", "name", "Layout"]);
12
14
  const addBtn = react_1.default.useMemo(() => {
13
15
  var _a;
14
16
  return (react_1.default.createElement(uikit_1.Button, { onClick: () => restProps.input.onChange((0, core_1.transformArrIn)(spec.defaultValue) || {}), disabled: (_a = spec.viewSpec) === null || _a === void 0 ? void 0 : _a.disabled, qa: `${name}-init-obj` },
@@ -17,25 +19,30 @@ const ObjectBase = (_a) => {
17
19
  }, [spec.defaultValue, spec.viewSpec.layoutTitle, restProps.input.onChange]);
18
20
  const parentOnChange = react_1.default.useCallback((childName, childValue, childErrors) => restProps.input.onChange((currentValue) => lodash_1.default.set(Object.assign({}, currentValue), childName.split(`${restProps.input.name}.`).join(''), childValue), childErrors), [restProps.input.onChange, restProps.input.name]);
19
21
  const content = react_1.default.useMemo(() => {
20
- if (!lodash_1.default.isObjectLike(spec.properties) || !Object.keys(spec.properties || {}).length) {
22
+ if (!spec.properties ||
23
+ !lodash_1.default.isObjectLike(spec.properties) ||
24
+ !Object.keys(spec.properties || {}).length) {
21
25
  return null;
22
26
  }
23
- if (!restProps.input.value) {
27
+ if (!inline && !restProps.input.value) {
24
28
  return addBtn;
25
29
  }
26
- const specProperties = Object.assign({}, spec.properties);
27
- return (react_1.default.createElement(react_1.default.Fragment, null, (spec.viewSpec.order || Object.keys(specProperties)).map((property) => {
30
+ const specProperties = inline
31
+ ? (0, utils_1.filterPropertiesForObjectInline)(spec.properties)
32
+ : spec.properties;
33
+ return (react_1.default.createElement("div", { className: b('content', { inline }) }, (spec.viewSpec.order || Object.keys(specProperties)).map((property) => {
28
34
  var _a;
29
35
  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: restProps.input.parentOnUnmount, key: `${name ? name + '.' : ''}${property}` })) : null;
30
36
  })));
31
37
  }, [
32
38
  spec.properties,
33
39
  spec.viewSpec.order,
34
- name,
35
40
  restProps.input.value,
41
+ restProps.input.parentOnUnmount,
42
+ inline,
36
43
  addBtn,
44
+ name,
37
45
  parentOnChange,
38
- restProps.input.parentOnUnmount,
39
46
  ]);
40
47
  if (!Layout || !content) {
41
48
  return content;
@@ -43,3 +50,7 @@ const ObjectBase = (_a) => {
43
50
  return (react_1.default.createElement(Layout, Object.assign({ spec: spec, name: name }, restProps), content));
44
51
  };
45
52
  exports.ObjectBase = ObjectBase;
53
+ const ObjectInline = (props) => {
54
+ return react_1.default.createElement(exports.ObjectBase, Object.assign({}, props, { inline: true }));
55
+ };
56
+ exports.ObjectInline = ObjectInline;
@@ -1,3 +1,6 @@
1
1
  .df-select {
2
2
  max-width: 305px;
3
+ }
4
+ .df-select__meta-text {
5
+ display: block;
3
6
  }
@@ -7,21 +7,34 @@ const uikit_1 = require("@gravity-ui/uikit");
7
7
  const utils_1 = require("../../../utils");
8
8
  const b = (0, utils_1.block)('select');
9
9
  const Select = ({ name, input, spec }) => {
10
- var _a;
10
+ var _a, _b, _c, _d;
11
11
  const { value, onBlur, onChange, onFocus } = input;
12
12
  const filterable = react_1.default.useMemo(() => { var _a; return (((_a = spec.enum) === null || _a === void 0 ? void 0 : _a.length) || 0) > 9; }, [(_a = spec.enum) === null || _a === void 0 ? void 0 : _a.length]);
13
13
  const options = react_1.default.useMemo(() => {
14
14
  var _a;
15
15
  return (_a = spec.enum) === null || _a === void 0 ? void 0 : _a.map((id) => {
16
- var _a;
16
+ var _a, _b, _c, _d, _e;
17
17
  return ({
18
18
  id,
19
19
  value: id,
20
- content: ((_a = spec.description) === null || _a === void 0 ? void 0 : _a[id]) || id,
20
+ text: ((_a = spec.description) === null || _a === void 0 ? void 0 : _a[id]) || id,
21
+ content: ((_c = (_b = spec.viewSpec.selectParams) === null || _b === void 0 ? void 0 : _b.meta) === null || _c === void 0 ? void 0 : _c[id]) ? (react_1.default.createElement("div", { key: id },
22
+ react_1.default.createElement(uikit_1.Text, null, ((_d = spec.description) === null || _d === void 0 ? void 0 : _d[id]) || id),
23
+ react_1.default.createElement(uikit_1.Text, { color: "secondary", className: b('meta-text') }, spec.viewSpec.selectParams.meta[id]))) : (((_e = spec.description) === null || _e === void 0 ? void 0 : _e[id]) || id),
21
24
  key: id,
22
25
  });
23
26
  });
24
- }, [spec.enum, spec.description]);
27
+ }, [spec.enum, spec.description, (_b = spec.viewSpec.selectParams) === null || _b === void 0 ? void 0 : _b.meta]);
28
+ const renderOption = react_1.default.useCallback((option) => {
29
+ return react_1.default.createElement(react_1.default.Fragment, { key: option.value }, option.content || option.value);
30
+ }, []);
31
+ const getOptionHeight = react_1.default.useCallback(() => {
32
+ var _a;
33
+ if ((_a = spec.viewSpec.selectParams) === null || _a === void 0 ? void 0 : _a.meta) {
34
+ return 44;
35
+ }
36
+ return 28;
37
+ }, [(_c = spec.viewSpec.selectParams) === null || _c === void 0 ? void 0 : _c.meta]);
25
38
  const handleChange = react_1.default.useCallback((v) => onChange(v[0]), [onChange]);
26
39
  const handleToggle = react_1.default.useCallback((open) => {
27
40
  if (open) {
@@ -31,6 +44,6 @@ const Select = ({ name, input, spec }) => {
31
44
  onBlur();
32
45
  }
33
46
  }, [onFocus, onBlur]);
34
- return (react_1.default.createElement(uikit_1.Select, { className: b(), width: "max", value: [value], options: options, onUpdate: handleChange, onOpenChange: handleToggle, disabled: spec.viewSpec.disabled, placeholder: spec.viewSpec.placeholder, filterable: filterable, qa: name }));
47
+ return (react_1.default.createElement(uikit_1.Select, { className: b(), width: "max", value: [value], options: options, onUpdate: handleChange, onOpenChange: handleToggle, disabled: spec.viewSpec.disabled, placeholder: spec.viewSpec.placeholder, filterable: filterable, filterPlaceholder: (_d = spec.viewSpec.selectParams) === null || _d === void 0 ? void 0 : _d.filterPlaceholder, getOptionHeight: getOptionHeight, renderOption: renderOption, qa: name }));
35
48
  };
36
49
  exports.Select = Select;
@@ -5,4 +5,15 @@
5
5
  .df-text-content .yc-label__text {
6
6
  text-align: initial;
7
7
  white-space: initial;
8
+ }
9
+ .df-text-content__icon {
10
+ display: flex;
11
+ align-items: center;
12
+ margin-right: 4px;
13
+ }
14
+ .df-text-content__wrapper {
15
+ display: flex;
16
+ }
17
+ .df-text-content__separator {
18
+ margin: 0 4px;
8
19
  }
@@ -4,21 +4,38 @@ exports.TextContent = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const uikit_1 = require("@gravity-ui/uikit");
7
+ const lodash_1 = tslib_1.__importDefault(require("lodash"));
7
8
  const utils_1 = require("../../../utils");
9
+ const LazyLoader_1 = require("../../LazyLoader");
10
+ const utils_2 = require("./utils");
8
11
  const b = (0, utils_1.block)('text-content');
9
12
  const TextContent = (_a) => {
10
- var { spec, Layout } = _a, restProps = tslib_1.__rest(_a, ["spec", "Layout"]);
11
- const { themeLabel, layoutDescription } = spec.viewSpec;
12
- if (!layoutDescription) {
13
+ var _b;
14
+ var { spec, Layout, input } = _a, restProps = tslib_1.__rest(_a, ["spec", "Layout", "input"]);
15
+ const { textContentParams, layoutDescription } = spec.viewSpec;
16
+ const text = react_1.default.useMemo(() => ((textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text) ? textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text : layoutDescription), [layoutDescription, textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text]);
17
+ if (!text) {
13
18
  return null;
14
19
  }
15
- let content = react_1.default.createElement("span", { dangerouslySetInnerHTML: { __html: layoutDescription } });
16
- if (themeLabel) {
17
- content = (react_1.default.createElement(uikit_1.Label, { size: "m", theme: themeLabel, className: b() }, content));
20
+ const iconLib = (textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.icon) ? (react_1.default.createElement(LazyLoader_1.LazyLoader, { component: (0, utils_2.loadIcon)(textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.icon) })) : null;
21
+ let content = react_1.default.createElement("span", { dangerouslySetInnerHTML: { __html: text } });
22
+ if (textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.themeLabel) {
23
+ content = (react_1.default.createElement(uikit_1.Label, { size: "m", theme: textContentParams.themeLabel, className: b(), value: input.value, icon: iconLib }, content));
24
+ }
25
+ else {
26
+ content = (react_1.default.createElement("div", { className: b('wrapper') },
27
+ iconLib ? (react_1.default.createElement(uikit_1.Text, { color: (_b = spec.viewSpec.textContentParams) === null || _b === void 0 ? void 0 : _b.iconColor, className: b('icon') }, iconLib)) : null,
28
+ content,
29
+ input.value ? (react_1.default.createElement(react_1.default.Fragment, null,
30
+ react_1.default.createElement("span", { className: b('separator') }, ":"),
31
+ react_1.default.createElement(uikit_1.Text, { color: "secondary" }, input.value))) : null));
18
32
  }
19
33
  if (Layout) {
20
- const _spec = Object.assign(Object.assign({}, spec), { viewSpec: Object.assign(Object.assign({}, spec.viewSpec), { layoutDescription: undefined }) });
21
- return (react_1.default.createElement(Layout, Object.assign({ spec: _spec }, restProps), content));
34
+ const _spec = lodash_1.default.cloneDeep(spec);
35
+ if (!(textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text)) {
36
+ _spec.viewSpec.layoutDescription = undefined;
37
+ }
38
+ return (react_1.default.createElement(Layout, Object.assign({ spec: _spec, input: input }, restProps), content));
22
39
  }
23
40
  return content;
24
41
  };
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadIcon = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const loadIcon = (name) => {
7
+ const Icon = react_1.default.lazy(() => {
8
+ return new Promise((resolve) => {
9
+ const icon = Promise.resolve().then(() => tslib_1.__importStar(require(`@gravity-ui/icons`))).then((module) => {
10
+ if (module[name]) {
11
+ return { default: module[name] };
12
+ }
13
+ return {
14
+ default: () => null,
15
+ };
16
+ });
17
+ resolve(icon);
18
+ });
19
+ });
20
+ return Icon;
21
+ };
22
+ exports.loadIcon = loadIcon;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LazyLoader = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const lodash_1 = tslib_1.__importDefault(require("lodash"));
7
+ const LazyLoader = ({ component, initialFallback = react_1.default.createElement(react_1.default.Fragment, null), }) => {
8
+ const fallback = react_1.default.useRef(() => initialFallback);
9
+ const Component = component;
10
+ const updateFallback = async () => {
11
+ const result = await component._result;
12
+ if (!lodash_1.default.isUndefined(result)) {
13
+ fallback.current = result.default;
14
+ }
15
+ };
16
+ react_1.default.useEffect(() => {
17
+ updateFallback();
18
+ }, [component]);
19
+ return (react_1.default.createElement(react_1.default.Suspense, { fallback: react_1.default.createElement(fallback.current, null) },
20
+ react_1.default.createElement(Component, null)));
21
+ };
22
+ exports.LazyLoader = LazyLoader;
@@ -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("./LazyLoader"), exports);
@@ -0,0 +1,11 @@
1
+ .df-object-base-view__content_inline {
2
+ display: flex;
3
+ }
4
+ .df-object-base-view__content_inline > div {
5
+ flex: auto;
6
+ margin-right: 8px;
7
+ margin-bottom: 0;
8
+ }
9
+ .df-object-base-view__content_inline > div:last-child {
10
+ margin-right: 0;
11
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ObjectInlineView = exports.ObjectBaseView = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const lodash_1 = tslib_1.__importDefault(require("lodash"));
7
+ const core_1 = require("../../../../core");
8
+ const utils_1 = require("../../../utils");
9
+ const b = (0, utils_1.block)('object-base-view');
10
+ const ObjectBaseView = (_a) => {
11
+ var { inline, spec, name, Layout } = _a, restProps = tslib_1.__rest(_a, ["inline", "spec", "name", "Layout"]);
12
+ if (!spec.properties || !lodash_1.default.isObjectLike(spec.properties)) {
13
+ return null;
14
+ }
15
+ const specProperties = inline
16
+ ? (0, utils_1.filterPropertiesForObjectInline)(spec.properties)
17
+ : spec.properties;
18
+ const content = (react_1.default.createElement("div", { className: b('content', { inline }) }, (spec.viewSpec.order || Object.keys(specProperties)).map((property) => specProperties[property] ? (react_1.default.createElement(core_1.ViewController, { spec: specProperties[property], name: `${name ? name + '.' : ''}${property}`, key: `${name ? name + '.' : ''}${property}` })) : null)));
19
+ if (!Layout) {
20
+ return content;
21
+ }
22
+ return (react_1.default.createElement(Layout, Object.assign({ spec: spec, name: name }, restProps), content));
23
+ };
24
+ exports.ObjectBaseView = ObjectBaseView;
25
+ const ObjectInlineView = (props) => {
26
+ return react_1.default.createElement(exports.ObjectBaseView, Object.assign({}, props, { inline: true }));
27
+ };
28
+ exports.ObjectInlineView = ObjectInlineView;
@@ -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("./ObjectBaseView"), exports);
@@ -8,6 +8,7 @@ tslib_1.__exportStar(require("./ErrorWrapper"), exports);
8
8
  tslib_1.__exportStar(require("./GroupIndent"), exports);
9
9
  tslib_1.__exportStar(require("./Inputs"), exports);
10
10
  tslib_1.__exportStar(require("./Layouts"), exports);
11
+ tslib_1.__exportStar(require("./LazyLoader"), exports);
11
12
  tslib_1.__exportStar(require("./LongValue"), exports);
12
13
  tslib_1.__exportStar(require("./SimpleVerticalAccordeon"), exports);
13
14
  tslib_1.__exportStar(require("./TogglerCard"), exports);
@@ -66,6 +66,7 @@ exports.dynamicConfig = {
66
66
  object_value: { Component: components_1.ObjectValueInput, independent: true },
67
67
  multi_oneof: { Component: components_1.MultiOneOf, independent: true },
68
68
  multi_oneof_flat: { Component: components_1.MultiOneOfFlat, independent: true },
69
+ inline: { Component: components_1.ObjectInline, independent: true },
69
70
  },
70
71
  layouts: {
71
72
  row: components_1.Row,
@@ -167,6 +168,7 @@ exports.dynamicCardConfig = {
167
168
  object_value: { Component: components_1.ObjectValueInput, independent: true },
168
169
  multi_oneof: { Component: components_1.MultiOneOf, independent: true },
169
170
  multi_oneof_flat: { Component: components_1.MultiOneOfFlat, independent: true },
171
+ inline: { Component: components_1.ObjectInline, independent: true },
170
172
  },
171
173
  layouts: {
172
174
  row: components_1.Row2,
@@ -261,6 +263,7 @@ exports.dynamicViewConfig = {
261
263
  object_value: { Component: components_1.ObjectValueInputView, independent: true },
262
264
  multi_oneof: { Component: components_1.MultiOneOfView, independent: true },
263
265
  multi_oneof_flat: { Component: components_1.MultiOneOfFlatView, independent: true },
266
+ inline: { Component: components_1.ObjectInlineView, independent: true },
264
267
  },
265
268
  layouts: {
266
269
  row: components_1.ViewRow,
@@ -346,6 +349,7 @@ exports.dynamicViewCardConfig = {
346
349
  object_value: { Component: components_1.ObjectValueInputView, independent: true },
347
350
  multi_oneof: { Component: components_1.MultiOneOfView, independent: true },
348
351
  multi_oneof_flat: { Component: components_1.MultiOneOfFlatView, independent: true },
352
+ inline: { Component: components_1.ObjectInlineView, independent: true },
349
353
  },
350
354
  layouts: {
351
355
  row: components_1.ViewRow2,
@@ -36,7 +36,7 @@ const isNotEmptyValue = (value, spec) => {
36
36
  };
37
37
  exports.isNotEmptyValue = isNotEmptyValue;
38
38
  const prepareSpec = (spec, parseJsonDefaultValue) => {
39
- var _a, _b, _c, _d;
39
+ var _a, _b, _c, _d, _e, _f, _g, _h;
40
40
  if (lodash_1.default.isObjectLike(spec)) {
41
41
  const result = lodash_1.default.cloneDeep(spec);
42
42
  if (lodash_1.default.isString(result.type)) {
@@ -48,7 +48,7 @@ const prepareSpec = (spec, parseJsonDefaultValue) => {
48
48
  try {
49
49
  _defaultValue = JSON.parse(result.defaultValue);
50
50
  }
51
- catch (_e) {
51
+ catch (_j) {
52
52
  _defaultValue = undefined;
53
53
  }
54
54
  }
@@ -70,7 +70,14 @@ const prepareSpec = (spec, parseJsonDefaultValue) => {
70
70
  result.viewSpec.addButtonPosition = result.viewSpec.addButtonPosition.toLowerCase();
71
71
  }
72
72
  if (lodash_1.default.isString((_d = result.viewSpec) === null || _d === void 0 ? void 0 : _d.themeLabel)) {
73
- result.viewSpec.themeLabel = result.viewSpec.themeLabel.toLowerCase();
73
+ result.viewSpec.textContentParams = Object.assign(Object.assign({}, result.viewSpec.textContentParams), { themeLabel: result.viewSpec.themeLabel.toLowerCase() });
74
+ }
75
+ if (lodash_1.default.isString((_f = (_e = result.viewSpec) === null || _e === void 0 ? void 0 : _e.oneOfParams) === null || _f === void 0 ? void 0 : _f.toggler)) {
76
+ result.viewSpec.oneOfParams.toggler = result.viewSpec.oneOfParams.toggler.toLowerCase();
77
+ }
78
+ if (lodash_1.default.isString((_h = (_g = result.viewSpec) === null || _g === void 0 ? void 0 : _g.textContentParams) === null || _h === void 0 ? void 0 : _h.themeLabel)) {
79
+ result.viewSpec.textContentParams.themeLabel =
80
+ result.viewSpec.textContentParams.themeLabel.toLowerCase();
74
81
  }
75
82
  if (lodash_1.default.isString(result.validator)) {
76
83
  result.validator = result.validator.toLowerCase();
@@ -4,3 +4,4 @@ const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./cn"), exports);
5
5
  tslib_1.__exportStar(require("./common"), exports);
6
6
  tslib_1.__exportStar(require("./bigIntMath"), exports);
7
+ tslib_1.__exportStar(require("./objectInline"), exports);
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.filterPropertiesForObjectInline = void 0;
4
+ const core_1 = require("../../core");
5
+ const filterPropertiesForObjectInline = (properties) => {
6
+ return Object.fromEntries(Object.entries(properties).filter(([, propSpec]) => (0, core_1.isStringSpec)(propSpec) || (0, core_1.isNumberSpec)(propSpec)));
7
+ };
8
+ exports.filterPropertiesForObjectInline = filterPropertiesForObjectInline;
@@ -24,7 +24,7 @@ export const Controller = ({ spec, name, value, parentOnChange, parentOnUnmount,
24
24
  useField: renderProps,
25
25
  useSearch: withSearch,
26
26
  }, __mirror);
27
- if (_.isString(name) && isCorrectSpec(spec)) {
27
+ if (_.isString(name) && isCorrectSpec(spec) && !spec.viewSpec.hideInput) {
28
28
  return withSearch(render(renderProps));
29
29
  }
30
30
  return null;
@@ -1,4 +1,5 @@
1
1
  import { LabelProps } from '@gravity-ui/uikit';
2
+ import { ColorTextBaseProps } from '@gravity-ui/uikit/build/esm/components/Text/colorText/colorText';
2
3
  import { ReadAsMethod, SpecTypes } from '../constants';
3
4
  import { ArrayValue, ObjectValue } from './';
4
5
  export interface ArraySpec<LinkType = any> {
@@ -27,6 +28,11 @@ export interface ArraySpec<LinkType = any> {
27
28
  link?: LinkType;
28
29
  placeholder?: string;
29
30
  addButtonPosition?: 'down' | 'right';
31
+ hideInput?: boolean;
32
+ selectParams?: {
33
+ filterPlaceholder?: string;
34
+ meta?: Record<string, string>;
35
+ };
30
36
  };
31
37
  }
32
38
  export interface BooleanSpec<LinkType = any> {
@@ -42,6 +48,7 @@ export interface BooleanSpec<LinkType = any> {
42
48
  layoutDescription?: string;
43
49
  layoutOpen?: boolean;
44
50
  link?: LinkType;
51
+ hideInput?: boolean;
45
52
  };
46
53
  }
47
54
  export interface NumberSpec<LinkType = any> {
@@ -62,6 +69,7 @@ export interface NumberSpec<LinkType = any> {
62
69
  link?: LinkType;
63
70
  placeholder?: string;
64
71
  copy?: boolean;
72
+ hideInput?: boolean;
65
73
  };
66
74
  }
67
75
  export interface ObjectSpec<LinkType = any> {
@@ -84,6 +92,7 @@ export interface ObjectSpec<LinkType = any> {
84
92
  toggler?: 'select' | 'radio' | 'card';
85
93
  };
86
94
  placeholder?: string;
95
+ hideInput?: boolean;
87
96
  };
88
97
  }
89
98
  export interface StringSpec<LinkType = any> {
@@ -119,13 +128,23 @@ export interface StringSpec<LinkType = any> {
119
128
  };
120
129
  hideValues?: string[];
121
130
  placeholder?: string;
122
- themeLabel?: LabelProps['theme'];
131
+ hideInput?: boolean;
132
+ textContentParams?: {
133
+ themeLabel?: LabelProps['theme'];
134
+ text: string;
135
+ icon?: string;
136
+ iconColor?: ColorTextBaseProps['color'];
137
+ };
123
138
  fileInput?: {
124
139
  accept?: string;
125
140
  readAsMethod?: ReadAsMethod;
126
141
  ignoreText?: boolean;
127
142
  };
128
143
  copy?: boolean;
144
+ selectParams?: {
145
+ filterPlaceholder?: string;
146
+ meta?: Record<string, string>;
147
+ };
129
148
  };
130
149
  }
131
150
  export type Spec = ArraySpec | BooleanSpec | NumberSpec | ObjectSpec | StringSpec;
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { Plus } from '@gravity-ui/icons';
3
3
  import { Button, Icon, Label } from '@gravity-ui/uikit';
4
4
  import _ from 'lodash';
5
- import { Controller, OBJECT_ARRAY_CNT, OBJECT_ARRAY_FLAG, isArraySpec, isCorrectSpec, isObjectSpec, transformArrIn, } from '../../../../core';
5
+ import { Controller, OBJECT_ARRAY_CNT, OBJECT_ARRAY_FLAG, isCorrectSpec, transformArrIn, } from '../../../../core';
6
6
  import { block } from '../../../utils';
7
7
  import './ArrayBase.css';
8
8
  const b = block('array-base');
@@ -24,19 +24,7 @@ export const ArrayBase = ({ spec, name, arrayInput, input }) => {
24
24
  }, [spec.items, itemSpecCorrect]);
25
25
  const parentOnChange = React.useCallback((childName, childValue, childErrors) => input.onChange((currentValue) => _.set(Object.assign({}, currentValue), childName.split(`${input.name}.`).join(''), childValue), childErrors), [input.onChange, input.name]);
26
26
  const AddButton = React.useCallback(() => {
27
- let onClick = () => {
28
- var _a;
29
- let item;
30
- if (!((_a = spec.items) === null || _a === void 0 ? void 0 : _a.required)) {
31
- if (isArraySpec(spec.items)) {
32
- item = { [OBJECT_ARRAY_FLAG]: true, [OBJECT_ARRAY_CNT]: 0 };
33
- }
34
- else if (isObjectSpec(spec.items)) {
35
- item = {};
36
- }
37
- }
38
- arrayInput.onItemAdd(item);
39
- };
27
+ let onClick = () => arrayInput.onItemAdd(undefined);
40
28
  let qa = `${name}-add-item`;
41
29
  let title = spec.viewSpec.itemLabel;
42
30
  if (!arrayInput.value && spec.defaultValue) {
@@ -54,10 +42,10 @@ export const ArrayBase = ({ spec, name, arrayInput, input }) => {
54
42
  input,
55
43
  name,
56
44
  spec.defaultValue,
57
- spec.items,
58
45
  spec.viewSpec.disabled,
59
46
  spec.viewSpec.itemLabel,
60
47
  spec.viewSpec.layoutTitle,
48
+ spec.viewSpec.addButtonPosition,
61
49
  ]);
62
50
  const items = React.useMemo(() => keys.map((key, idx) => {
63
51
  var _a;
@@ -1,3 +1,6 @@
1
1
  .df-multi-select {
2
2
  max-width: 305px;
3
+ }
4
+ .df-multi-select__meta-text {
5
+ display: block;
3
6
  }
@@ -1,25 +1,38 @@
1
1
  import React from 'react';
2
- import { Select } from '@gravity-ui/uikit';
2
+ import { Select, Text } from '@gravity-ui/uikit';
3
3
  import { transformArrIn, transformArrOut } from '../../../../core';
4
4
  import { block } from '../../../utils';
5
5
  import './MultiSelect.css';
6
6
  const b = block('multi-select');
7
7
  export const MultiSelect = ({ name, input, spec }) => {
8
- var _a;
8
+ var _a, _b, _c, _d;
9
9
  const { value, onBlur, onChange, onFocus } = input;
10
10
  const filterable = React.useMemo(() => { var _a; return (((_a = spec.enum) === null || _a === void 0 ? void 0 : _a.length) || 0) > 9; }, [(_a = spec.enum) === null || _a === void 0 ? void 0 : _a.length]);
11
11
  const options = React.useMemo(() => {
12
12
  var _a;
13
13
  return (_a = spec.enum) === null || _a === void 0 ? void 0 : _a.map((id) => {
14
- var _a;
14
+ var _a, _b, _c, _d, _e;
15
15
  return ({
16
16
  id,
17
17
  value: id,
18
- content: ((_a = spec.description) === null || _a === void 0 ? void 0 : _a[id]) || id,
18
+ text: ((_a = spec.description) === null || _a === void 0 ? void 0 : _a[id]) || id,
19
+ content: ((_c = (_b = spec.viewSpec.selectParams) === null || _b === void 0 ? void 0 : _b.meta) === null || _c === void 0 ? void 0 : _c[id]) ? (React.createElement("div", { key: id },
20
+ React.createElement(Text, null, ((_d = spec.description) === null || _d === void 0 ? void 0 : _d[id]) || id),
21
+ React.createElement(Text, { color: "secondary", className: b('meta-text') }, spec.viewSpec.selectParams.meta[id]))) : (((_e = spec.description) === null || _e === void 0 ? void 0 : _e[id]) || id),
19
22
  key: id,
20
23
  });
21
24
  });
22
- }, [spec.enum, spec.description]);
25
+ }, [spec.enum, spec.description, (_b = spec.viewSpec.selectParams) === null || _b === void 0 ? void 0 : _b.meta]);
26
+ const renderOption = React.useCallback((option) => {
27
+ return React.createElement(React.Fragment, { key: option.value }, option.content || option.value);
28
+ }, []);
29
+ const getOptionHeight = React.useCallback(() => {
30
+ var _a;
31
+ if ((_a = spec.viewSpec.selectParams) === null || _a === void 0 ? void 0 : _a.meta) {
32
+ return 44;
33
+ }
34
+ return 28;
35
+ }, [(_c = spec.viewSpec.selectParams) === null || _c === void 0 ? void 0 : _c.meta]);
23
36
  const handleToggle = React.useCallback((open) => {
24
37
  if (open) {
25
38
  onFocus();
@@ -30,5 +43,5 @@ export const MultiSelect = ({ name, input, spec }) => {
30
43
  }, [onFocus, onBlur]);
31
44
  const _value = React.useMemo(() => transformArrOut(value), [value]);
32
45
  const handleChange = React.useCallback((value) => onChange(transformArrIn(value)), [onChange]);
33
- return (React.createElement(Select, { width: "max", className: b(), value: _value, options: options, onUpdate: handleChange, onOpenChange: handleToggle, disabled: spec.viewSpec.disabled, placeholder: spec.viewSpec.placeholder, filterable: filterable, multiple: true, qa: name }));
46
+ return (React.createElement(Select, { width: "max", className: b(), value: _value, options: options, onUpdate: handleChange, onOpenChange: handleToggle, disabled: spec.viewSpec.disabled, placeholder: spec.viewSpec.placeholder, filterable: filterable, filterPlaceholder: (_d = spec.viewSpec.selectParams) === null || _d === void 0 ? void 0 : _d.filterPlaceholder, renderOption: renderOption, getOptionHeight: getOptionHeight, multiple: true, qa: name }));
34
47
  };
@@ -0,0 +1,11 @@
1
+ .df-object-base__content_inline {
2
+ display: flex;
3
+ }
4
+ .df-object-base__content_inline > .df-use-search {
5
+ width: 150px;
6
+ margin-bottom: 0;
7
+ margin-right: 8px;
8
+ }
9
+ .df-object-base__content_inline > .df-use-search:last-child {
10
+ margin-right: 0;
11
+ }
@@ -1,2 +1,8 @@
1
- import { ObjectIndependentInput } from '../../../../core';
2
- export declare const ObjectBase: ObjectIndependentInput;
1
+ import React from 'react';
2
+ import { ObjectIndependentInput, ObjectIndependentInputProps } from '../../../../core';
3
+ import './ObjectBase.css';
4
+ export interface ObjectBaseProps extends ObjectIndependentInputProps {
5
+ inline?: boolean;
6
+ }
7
+ export declare const ObjectBase: React.FC<ObjectBaseProps>;
8
+ export declare const ObjectInline: ObjectIndependentInput;
@@ -4,8 +4,11 @@ import { Plus } from '@gravity-ui/icons';
4
4
  import { Button, Icon } from '@gravity-ui/uikit';
5
5
  import _ from 'lodash';
6
6
  import { Controller, transformArrIn, } from '../../../../core';
7
+ import { block, filterPropertiesForObjectInline } from '../../../utils';
8
+ import './ObjectBase.css';
9
+ const b = block('object-base');
7
10
  export const ObjectBase = (_a) => {
8
- var { spec, name, Layout } = _a, restProps = __rest(_a, ["spec", "name", "Layout"]);
11
+ var { inline, spec, name, Layout } = _a, restProps = __rest(_a, ["inline", "spec", "name", "Layout"]);
9
12
  const addBtn = React.useMemo(() => {
10
13
  var _a;
11
14
  return (React.createElement(Button, { onClick: () => restProps.input.onChange(transformArrIn(spec.defaultValue) || {}), disabled: (_a = spec.viewSpec) === null || _a === void 0 ? void 0 : _a.disabled, qa: `${name}-init-obj` },
@@ -14,28 +17,36 @@ export const ObjectBase = (_a) => {
14
17
  }, [spec.defaultValue, spec.viewSpec.layoutTitle, restProps.input.onChange]);
15
18
  const parentOnChange = React.useCallback((childName, childValue, childErrors) => restProps.input.onChange((currentValue) => _.set(Object.assign({}, currentValue), childName.split(`${restProps.input.name}.`).join(''), childValue), childErrors), [restProps.input.onChange, restProps.input.name]);
16
19
  const content = React.useMemo(() => {
17
- if (!_.isObjectLike(spec.properties) || !Object.keys(spec.properties || {}).length) {
20
+ if (!spec.properties ||
21
+ !_.isObjectLike(spec.properties) ||
22
+ !Object.keys(spec.properties || {}).length) {
18
23
  return null;
19
24
  }
20
- if (!restProps.input.value) {
25
+ if (!inline && !restProps.input.value) {
21
26
  return addBtn;
22
27
  }
23
- const specProperties = Object.assign({}, spec.properties);
24
- return (React.createElement(React.Fragment, null, (spec.viewSpec.order || Object.keys(specProperties)).map((property) => {
28
+ const specProperties = inline
29
+ ? filterPropertiesForObjectInline(spec.properties)
30
+ : spec.properties;
31
+ return (React.createElement("div", { className: b('content', { inline }) }, (spec.viewSpec.order || Object.keys(specProperties)).map((property) => {
25
32
  var _a;
26
33
  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: restProps.input.parentOnUnmount, key: `${name ? name + '.' : ''}${property}` })) : null;
27
34
  })));
28
35
  }, [
29
36
  spec.properties,
30
37
  spec.viewSpec.order,
31
- name,
32
38
  restProps.input.value,
39
+ restProps.input.parentOnUnmount,
40
+ inline,
33
41
  addBtn,
42
+ name,
34
43
  parentOnChange,
35
- restProps.input.parentOnUnmount,
36
44
  ]);
37
45
  if (!Layout || !content) {
38
46
  return content;
39
47
  }
40
48
  return (React.createElement(Layout, Object.assign({ spec: spec, name: name }, restProps), content));
41
49
  };
50
+ export const ObjectInline = (props) => {
51
+ return React.createElement(ObjectBase, Object.assign({}, props, { inline: true }));
52
+ };
@@ -1,3 +1,6 @@
1
1
  .df-select {
2
2
  max-width: 305px;
3
+ }
4
+ .df-select__meta-text {
5
+ display: block;
3
6
  }
@@ -1,24 +1,37 @@
1
1
  import React from 'react';
2
- import { Select as SelectBase } from '@gravity-ui/uikit';
2
+ import { Select as SelectBase, Text } from '@gravity-ui/uikit';
3
3
  import { block } from '../../../utils';
4
4
  import './Select.css';
5
5
  const b = block('select');
6
6
  export const Select = ({ name, input, spec }) => {
7
- var _a;
7
+ var _a, _b, _c, _d;
8
8
  const { value, onBlur, onChange, onFocus } = input;
9
9
  const filterable = React.useMemo(() => { var _a; return (((_a = spec.enum) === null || _a === void 0 ? void 0 : _a.length) || 0) > 9; }, [(_a = spec.enum) === null || _a === void 0 ? void 0 : _a.length]);
10
10
  const options = React.useMemo(() => {
11
11
  var _a;
12
12
  return (_a = spec.enum) === null || _a === void 0 ? void 0 : _a.map((id) => {
13
- var _a;
13
+ var _a, _b, _c, _d, _e;
14
14
  return ({
15
15
  id,
16
16
  value: id,
17
- content: ((_a = spec.description) === null || _a === void 0 ? void 0 : _a[id]) || id,
17
+ text: ((_a = spec.description) === null || _a === void 0 ? void 0 : _a[id]) || id,
18
+ content: ((_c = (_b = spec.viewSpec.selectParams) === null || _b === void 0 ? void 0 : _b.meta) === null || _c === void 0 ? void 0 : _c[id]) ? (React.createElement("div", { key: id },
19
+ React.createElement(Text, null, ((_d = spec.description) === null || _d === void 0 ? void 0 : _d[id]) || id),
20
+ React.createElement(Text, { color: "secondary", className: b('meta-text') }, spec.viewSpec.selectParams.meta[id]))) : (((_e = spec.description) === null || _e === void 0 ? void 0 : _e[id]) || id),
18
21
  key: id,
19
22
  });
20
23
  });
21
- }, [spec.enum, spec.description]);
24
+ }, [spec.enum, spec.description, (_b = spec.viewSpec.selectParams) === null || _b === void 0 ? void 0 : _b.meta]);
25
+ const renderOption = React.useCallback((option) => {
26
+ return React.createElement(React.Fragment, { key: option.value }, option.content || option.value);
27
+ }, []);
28
+ const getOptionHeight = React.useCallback(() => {
29
+ var _a;
30
+ if ((_a = spec.viewSpec.selectParams) === null || _a === void 0 ? void 0 : _a.meta) {
31
+ return 44;
32
+ }
33
+ return 28;
34
+ }, [(_c = spec.viewSpec.selectParams) === null || _c === void 0 ? void 0 : _c.meta]);
22
35
  const handleChange = React.useCallback((v) => onChange(v[0]), [onChange]);
23
36
  const handleToggle = React.useCallback((open) => {
24
37
  if (open) {
@@ -28,5 +41,5 @@ export const Select = ({ name, input, spec }) => {
28
41
  onBlur();
29
42
  }
30
43
  }, [onFocus, onBlur]);
31
- return (React.createElement(SelectBase, { className: b(), width: "max", value: [value], options: options, onUpdate: handleChange, onOpenChange: handleToggle, disabled: spec.viewSpec.disabled, placeholder: spec.viewSpec.placeholder, filterable: filterable, qa: name }));
44
+ return (React.createElement(SelectBase, { className: b(), width: "max", value: [value], options: options, onUpdate: handleChange, onOpenChange: handleToggle, disabled: spec.viewSpec.disabled, placeholder: spec.viewSpec.placeholder, filterable: filterable, filterPlaceholder: (_d = spec.viewSpec.selectParams) === null || _d === void 0 ? void 0 : _d.filterPlaceholder, getOptionHeight: getOptionHeight, renderOption: renderOption, qa: name }));
32
45
  };
@@ -5,4 +5,15 @@
5
5
  .df-text-content .yc-label__text {
6
6
  text-align: initial;
7
7
  white-space: initial;
8
+ }
9
+ .df-text-content__icon {
10
+ display: flex;
11
+ align-items: center;
12
+ margin-right: 4px;
13
+ }
14
+ .df-text-content__wrapper {
15
+ display: flex;
16
+ }
17
+ .df-text-content__separator {
18
+ margin: 0 4px;
8
19
  }
@@ -1,22 +1,39 @@
1
1
  import { __rest } from "tslib";
2
2
  import React from 'react';
3
- import { Label } from '@gravity-ui/uikit';
3
+ import { Label, Text } from '@gravity-ui/uikit';
4
+ import _ from 'lodash';
4
5
  import { block } from '../../../utils';
6
+ import { LazyLoader } from '../../LazyLoader';
7
+ import { loadIcon } from './utils';
5
8
  import './TextContent.css';
6
9
  const b = block('text-content');
7
10
  export const TextContent = (_a) => {
8
- var { spec, Layout } = _a, restProps = __rest(_a, ["spec", "Layout"]);
9
- const { themeLabel, layoutDescription } = spec.viewSpec;
10
- if (!layoutDescription) {
11
+ var _b;
12
+ var { spec, Layout, input } = _a, restProps = __rest(_a, ["spec", "Layout", "input"]);
13
+ const { textContentParams, layoutDescription } = spec.viewSpec;
14
+ const text = React.useMemo(() => ((textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text) ? textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text : layoutDescription), [layoutDescription, textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text]);
15
+ if (!text) {
11
16
  return null;
12
17
  }
13
- let content = React.createElement("span", { dangerouslySetInnerHTML: { __html: layoutDescription } });
14
- if (themeLabel) {
15
- content = (React.createElement(Label, { size: "m", theme: themeLabel, className: b() }, content));
18
+ const iconLib = (textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.icon) ? (React.createElement(LazyLoader, { component: loadIcon(textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.icon) })) : null;
19
+ let content = React.createElement("span", { dangerouslySetInnerHTML: { __html: text } });
20
+ if (textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.themeLabel) {
21
+ content = (React.createElement(Label, { size: "m", theme: textContentParams.themeLabel, className: b(), value: input.value, icon: iconLib }, content));
22
+ }
23
+ else {
24
+ content = (React.createElement("div", { className: b('wrapper') },
25
+ iconLib ? (React.createElement(Text, { color: (_b = spec.viewSpec.textContentParams) === null || _b === void 0 ? void 0 : _b.iconColor, className: b('icon') }, iconLib)) : null,
26
+ content,
27
+ input.value ? (React.createElement(React.Fragment, null,
28
+ React.createElement("span", { className: b('separator') }, ":"),
29
+ React.createElement(Text, { color: "secondary" }, input.value))) : null));
16
30
  }
17
31
  if (Layout) {
18
- const _spec = Object.assign(Object.assign({}, spec), { viewSpec: Object.assign(Object.assign({}, spec.viewSpec), { layoutDescription: undefined }) });
19
- return (React.createElement(Layout, Object.assign({ spec: _spec }, restProps), content));
32
+ const _spec = _.cloneDeep(spec);
33
+ if (!(textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text)) {
34
+ _spec.viewSpec.layoutDescription = undefined;
35
+ }
36
+ return (React.createElement(Layout, Object.assign({ spec: _spec, input: input }, restProps), content));
20
37
  }
21
38
  return content;
22
39
  };
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const loadIcon: (name: string) => React.LazyExoticComponent<React.ComponentType<any>>;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ export const loadIcon = (name) => {
3
+ const Icon = React.lazy(() => {
4
+ return new Promise((resolve) => {
5
+ const icon = import(`@gravity-ui/icons`).then((module) => {
6
+ if (module[name]) {
7
+ return { default: module[name] };
8
+ }
9
+ return {
10
+ default: () => null,
11
+ };
12
+ });
13
+ resolve(icon);
14
+ });
15
+ });
16
+ return Icon;
17
+ };
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export type LazyLoaderProps = {
3
+ component: React.LazyExoticComponent<React.ComponentType<any>>;
4
+ initialFallback?: JSX.Element;
5
+ };
6
+ export declare const LazyLoader: ({ component, initialFallback, }: LazyLoaderProps) => JSX.Element;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import _ from 'lodash';
3
+ export const LazyLoader = ({ component, initialFallback = React.createElement(React.Fragment, null), }) => {
4
+ const fallback = React.useRef(() => initialFallback);
5
+ const Component = component;
6
+ const updateFallback = async () => {
7
+ const result = await component._result;
8
+ if (!_.isUndefined(result)) {
9
+ fallback.current = result.default;
10
+ }
11
+ };
12
+ React.useEffect(() => {
13
+ updateFallback();
14
+ }, [component]);
15
+ return (React.createElement(React.Suspense, { fallback: React.createElement(fallback.current, null) },
16
+ React.createElement(Component, null)));
17
+ };
@@ -0,0 +1 @@
1
+ export * from './LazyLoader';
@@ -0,0 +1 @@
1
+ export * from './LazyLoader';
@@ -0,0 +1,11 @@
1
+ .df-object-base-view__content_inline {
2
+ display: flex;
3
+ }
4
+ .df-object-base-view__content_inline > div {
5
+ flex: auto;
6
+ margin-right: 8px;
7
+ margin-bottom: 0;
8
+ }
9
+ .df-object-base-view__content_inline > div:last-child {
10
+ margin-right: 0;
11
+ }
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { ObjectIndependentView, ObjectIndependentViewProps } from '../../../../core';
3
+ import './ObjectBaseView.css';
4
+ export interface ObjectBaseViewProps extends ObjectIndependentViewProps {
5
+ inline?: boolean;
6
+ }
7
+ export declare const ObjectBaseView: React.FC<ObjectBaseViewProps>;
8
+ export declare const ObjectInlineView: ObjectIndependentView;
@@ -0,0 +1,24 @@
1
+ import { __rest } from "tslib";
2
+ import React from 'react';
3
+ import _ from 'lodash';
4
+ import { ViewController } from '../../../../core';
5
+ import { block, filterPropertiesForObjectInline } from '../../../utils';
6
+ import './ObjectBaseView.css';
7
+ const b = block('object-base-view');
8
+ export const ObjectBaseView = (_a) => {
9
+ var { inline, spec, name, Layout } = _a, restProps = __rest(_a, ["inline", "spec", "name", "Layout"]);
10
+ if (!spec.properties || !_.isObjectLike(spec.properties)) {
11
+ return null;
12
+ }
13
+ const specProperties = inline
14
+ ? filterPropertiesForObjectInline(spec.properties)
15
+ : spec.properties;
16
+ const content = (React.createElement("div", { className: b('content', { inline }) }, (spec.viewSpec.order || Object.keys(specProperties)).map((property) => specProperties[property] ? (React.createElement(ViewController, { spec: specProperties[property], name: `${name ? name + '.' : ''}${property}`, key: `${name ? name + '.' : ''}${property}` })) : null)));
17
+ if (!Layout) {
18
+ return content;
19
+ }
20
+ return (React.createElement(Layout, Object.assign({ spec: spec, name: name }, restProps), content));
21
+ };
22
+ export const ObjectInlineView = (props) => {
23
+ return React.createElement(ObjectBaseView, Object.assign({}, props, { inline: true }));
24
+ };
@@ -0,0 +1 @@
1
+ export * from './ObjectBaseView';
@@ -0,0 +1 @@
1
+ export * from './ObjectBaseView';
@@ -5,6 +5,7 @@ export * from './ErrorWrapper';
5
5
  export * from './GroupIndent';
6
6
  export * from './Inputs';
7
7
  export * from './Layouts';
8
+ export * from './LazyLoader';
8
9
  export * from './LongValue';
9
10
  export * from './SimpleVerticalAccordeon';
10
11
  export * from './TogglerCard';
@@ -5,6 +5,7 @@ export * from './ErrorWrapper';
5
5
  export * from './GroupIndent';
6
6
  export * from './Inputs';
7
7
  export * from './Layouts';
8
+ export * from './LazyLoader';
8
9
  export * from './LongValue';
9
10
  export * from './SimpleVerticalAccordeon';
10
11
  export * from './TogglerCard';
@@ -1,4 +1,4 @@
1
- import { Accordeon, AccordeonCardLayout, ArrayBase, ArrayBaseView, BaseView, CardAccordeon, CardOneOf, CardOneOfView, CardSection, Checkbox, FileInput, FileInputView, Group, Group2, MonacoInput, MonacoInputCard, MonacoView, MonacoViewCard, MultiOneOf, MultiOneOfFlat, MultiOneOfFlatView, MultiOneOfView, 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, Switch, 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, MultiOneOf, MultiOneOfFlat, MultiOneOfFlatView, MultiOneOfView, MultiSelect, MultiSelectView, NumberWithScale, NumberWithScaleView, ObjectBase, ObjectBaseView, ObjectInline, ObjectInlineView, ObjectValueInput, ObjectValueInputView, OneOf, OneOfCard, OneOfCardView, OneOfFlat, OneOfFlatView, OneOfView, Row, Row2, RowVerbose, Secret, Section, Section2, SectionCard, SectionCard2, SectionWithSubtitle, SectionWithSubtitle2, Select, Switch, 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: {
@@ -63,6 +63,7 @@ export const dynamicConfig = {
63
63
  object_value: { Component: ObjectValueInput, independent: true },
64
64
  multi_oneof: { Component: MultiOneOf, independent: true },
65
65
  multi_oneof_flat: { Component: MultiOneOfFlat, independent: true },
66
+ inline: { Component: ObjectInline, independent: true },
66
67
  },
67
68
  layouts: {
68
69
  row: Row,
@@ -164,6 +165,7 @@ export const dynamicCardConfig = {
164
165
  object_value: { Component: ObjectValueInput, independent: true },
165
166
  multi_oneof: { Component: MultiOneOf, independent: true },
166
167
  multi_oneof_flat: { Component: MultiOneOfFlat, independent: true },
168
+ inline: { Component: ObjectInline, independent: true },
167
169
  },
168
170
  layouts: {
169
171
  row: Row2,
@@ -258,6 +260,7 @@ export const dynamicViewConfig = {
258
260
  object_value: { Component: ObjectValueInputView, independent: true },
259
261
  multi_oneof: { Component: MultiOneOfView, independent: true },
260
262
  multi_oneof_flat: { Component: MultiOneOfFlatView, independent: true },
263
+ inline: { Component: ObjectInlineView, independent: true },
261
264
  },
262
265
  layouts: {
263
266
  row: ViewRow,
@@ -343,6 +346,7 @@ export const dynamicViewCardConfig = {
343
346
  object_value: { Component: ObjectValueInputView, independent: true },
344
347
  multi_oneof: { Component: MultiOneOfView, independent: true },
345
348
  multi_oneof_flat: { Component: MultiOneOfFlatView, independent: true },
349
+ inline: { Component: ObjectInlineView, independent: true },
346
350
  },
347
351
  layouts: {
348
352
  row: ViewRow2,
@@ -31,7 +31,7 @@ export const isNotEmptyValue = (value, spec) => {
31
31
  return true;
32
32
  };
33
33
  export const prepareSpec = (spec, parseJsonDefaultValue) => {
34
- var _a, _b, _c, _d;
34
+ var _a, _b, _c, _d, _e, _f, _g, _h;
35
35
  if (_.isObjectLike(spec)) {
36
36
  const result = _.cloneDeep(spec);
37
37
  if (_.isString(result.type)) {
@@ -43,7 +43,7 @@ export const prepareSpec = (spec, parseJsonDefaultValue) => {
43
43
  try {
44
44
  _defaultValue = JSON.parse(result.defaultValue);
45
45
  }
46
- catch (_e) {
46
+ catch (_j) {
47
47
  _defaultValue = undefined;
48
48
  }
49
49
  }
@@ -65,7 +65,14 @@ export const prepareSpec = (spec, parseJsonDefaultValue) => {
65
65
  result.viewSpec.addButtonPosition = result.viewSpec.addButtonPosition.toLowerCase();
66
66
  }
67
67
  if (_.isString((_d = result.viewSpec) === null || _d === void 0 ? void 0 : _d.themeLabel)) {
68
- result.viewSpec.themeLabel = result.viewSpec.themeLabel.toLowerCase();
68
+ result.viewSpec.textContentParams = Object.assign(Object.assign({}, result.viewSpec.textContentParams), { themeLabel: result.viewSpec.themeLabel.toLowerCase() });
69
+ }
70
+ if (_.isString((_f = (_e = result.viewSpec) === null || _e === void 0 ? void 0 : _e.oneOfParams) === null || _f === void 0 ? void 0 : _f.toggler)) {
71
+ result.viewSpec.oneOfParams.toggler = result.viewSpec.oneOfParams.toggler.toLowerCase();
72
+ }
73
+ if (_.isString((_h = (_g = result.viewSpec) === null || _g === void 0 ? void 0 : _g.textContentParams) === null || _h === void 0 ? void 0 : _h.themeLabel)) {
74
+ result.viewSpec.textContentParams.themeLabel =
75
+ result.viewSpec.textContentParams.themeLabel.toLowerCase();
69
76
  }
70
77
  if (_.isString(result.validator)) {
71
78
  result.validator = result.validator.toLowerCase();
@@ -1,3 +1,4 @@
1
1
  export * from './cn';
2
2
  export * from './common';
3
3
  export * from './bigIntMath';
4
+ export * from './objectInline';
@@ -1,3 +1,4 @@
1
1
  export * from './cn';
2
2
  export * from './common';
3
3
  export * from './bigIntMath';
4
+ export * from './objectInline';
@@ -0,0 +1,4 @@
1
+ import { Spec } from '../../core';
2
+ export declare const filterPropertiesForObjectInline: (properties: Record<string, Spec>) => {
3
+ [k: string]: Spec;
4
+ };
@@ -0,0 +1,4 @@
1
+ import { isNumberSpec, isStringSpec } from '../../core';
2
+ export const filterPropertiesForObjectInline = (properties) => {
3
+ return Object.fromEntries(Object.entries(properties).filter(([, propSpec]) => isStringSpec(propSpec) || isNumberSpec(propSpec)));
4
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dynamic-forms",
3
- "version": "2.4.0",
3
+ "version": "2.6.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "main": "build/cjs/index.js",
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ObjectBaseView = void 0;
4
- const tslib_1 = require("tslib");
5
- const react_1 = tslib_1.__importDefault(require("react"));
6
- const lodash_1 = tslib_1.__importDefault(require("lodash"));
7
- const core_1 = require("../../../core");
8
- const ObjectBaseView = (_a) => {
9
- var { spec, name, Layout } = _a, restProps = tslib_1.__rest(_a, ["spec", "name", "Layout"]);
10
- if (!lodash_1.default.isObjectLike(spec.properties)) {
11
- return null;
12
- }
13
- const specProperties = Object.assign({}, spec.properties);
14
- const content = (react_1.default.createElement(react_1.default.Fragment, null, (spec.viewSpec.order || Object.keys(specProperties)).map((property) => specProperties[property] ? (react_1.default.createElement(core_1.ViewController, { spec: specProperties[property], name: `${name ? name + '.' : ''}${property}`, key: `${name ? name + '.' : ''}${property}` })) : null)));
15
- if (!Layout) {
16
- return content;
17
- }
18
- return (react_1.default.createElement(Layout, Object.assign({ spec: spec, name: name }, restProps), content));
19
- };
20
- exports.ObjectBaseView = ObjectBaseView;
@@ -1,2 +0,0 @@
1
- import { ObjectIndependentView } from '../../../core';
2
- export declare const ObjectBaseView: ObjectIndependentView;
@@ -1,16 +0,0 @@
1
- import { __rest } from "tslib";
2
- import React from 'react';
3
- import _ from 'lodash';
4
- import { ViewController } from '../../../core';
5
- export const ObjectBaseView = (_a) => {
6
- var { spec, name, Layout } = _a, restProps = __rest(_a, ["spec", "name", "Layout"]);
7
- if (!_.isObjectLike(spec.properties)) {
8
- return null;
9
- }
10
- const specProperties = Object.assign({}, spec.properties);
11
- const content = (React.createElement(React.Fragment, null, (spec.viewSpec.order || Object.keys(specProperties)).map((property) => specProperties[property] ? (React.createElement(ViewController, { spec: specProperties[property], name: `${name ? name + '.' : ''}${property}`, key: `${name ? name + '.' : ''}${property}` })) : null)));
12
- if (!Layout) {
13
- return content;
14
- }
15
- return (React.createElement(Layout, Object.assign({ spec: spec, name: name }, restProps), content));
16
- };