@gravity-ui/dynamic-forms 1.1.1 → 1.3.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 (101) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/build/cjs/lib/core/components/Form/Controller.js +10 -2
  3. package/build/cjs/lib/core/components/Form/DynamicField.js +23 -7
  4. package/build/cjs/lib/core/components/Form/hooks/index.js +7 -0
  5. package/build/cjs/lib/core/components/Form/hooks/useComponents.js +2 -2
  6. package/build/cjs/lib/core/components/Form/hooks/useControllerMirror.js +19 -0
  7. package/build/cjs/lib/core/components/Form/hooks/useCreateSearchContext.js +9 -0
  8. package/build/cjs/lib/core/components/Form/hooks/useDynamicFieldMirror.js +22 -0
  9. package/build/cjs/lib/core/components/Form/hooks/useField.js +7 -7
  10. package/build/cjs/lib/core/components/Form/hooks/useIntegrationFF.js +46 -0
  11. package/build/cjs/lib/core/components/Form/hooks/useSearch/index.js +4 -0
  12. package/build/cjs/lib/core/components/Form/hooks/useSearch/useSearch.css +9 -0
  13. package/build/cjs/lib/core/components/Form/hooks/useSearch/useSearch.js +22 -0
  14. package/build/cjs/lib/core/components/Form/hooks/useSearchContext.js +12 -0
  15. package/build/cjs/lib/core/components/Form/hooks/useSearchStore.js +41 -0
  16. package/build/cjs/lib/core/components/Form/hooks/useStore.js +6 -38
  17. package/build/cjs/lib/core/components/Form/hooks/useValidate.js +2 -2
  18. package/build/cjs/lib/core/components/Form/index.js +1 -1
  19. package/build/cjs/lib/core/components/Form/types/index.js +3 -0
  20. package/build/cjs/lib/core/components/Form/types/mirror.js +2 -0
  21. package/build/cjs/lib/core/components/Form/types/search.js +2 -0
  22. package/build/cjs/lib/core/components/Form/types/store.js +2 -0
  23. package/build/cjs/lib/core/components/Form/{helpers.js → utils/common.js} +2 -2
  24. package/build/cjs/lib/core/components/Form/utils/index.js +5 -0
  25. package/build/cjs/lib/core/components/Form/utils/search.js +19 -0
  26. package/build/cjs/lib/kit/components/Inputs/TableArrayInput/TableArrayInput.css +10 -0
  27. package/build/cjs/lib/kit/components/Inputs/TableArrayInput/TableArrayInput.js +20 -9
  28. package/build/cjs/lib/kit/components/Inputs/TextLink/TextLink.js +20 -0
  29. package/build/cjs/lib/kit/components/Inputs/TextLink/index.js +4 -0
  30. package/build/cjs/lib/kit/components/Inputs/index.js +1 -0
  31. package/build/cjs/lib/kit/components/Layouts/Row/Row.css +18 -10
  32. package/build/cjs/lib/kit/components/Layouts/Row/Row.js +4 -5
  33. package/build/cjs/lib/kit/components/Views/TextLinkView/TextLinkView.js +17 -0
  34. package/build/cjs/lib/kit/components/Views/TextLinkView/index.js +4 -0
  35. package/build/cjs/lib/kit/components/Views/index.js +1 -0
  36. package/build/cjs/lib/kit/constants/config.js +4 -0
  37. package/build/cjs/lib/kit/validators/validators.js +1 -2
  38. package/build/esm/lib/core/components/Form/Controller.js +11 -3
  39. package/build/esm/lib/core/components/Form/DynamicField.d.ts +3 -1
  40. package/build/esm/lib/core/components/Form/DynamicField.js +23 -7
  41. package/build/esm/lib/core/components/Form/hooks/index.d.ts +7 -0
  42. package/build/esm/lib/core/components/Form/hooks/index.js +7 -0
  43. package/build/esm/lib/core/components/Form/hooks/useComponents.js +1 -1
  44. package/build/esm/lib/core/components/Form/hooks/useControllerMirror.d.ts +2 -0
  45. package/build/esm/lib/core/components/Form/hooks/useControllerMirror.js +14 -0
  46. package/build/esm/lib/core/components/Form/hooks/useCreateSearchContext.d.ts +3 -0
  47. package/build/esm/lib/core/components/Form/hooks/useCreateSearchContext.js +4 -0
  48. package/build/esm/lib/core/components/Form/hooks/useDynamicFieldMirror.d.ts +2 -0
  49. package/build/esm/lib/core/components/Form/hooks/useDynamicFieldMirror.js +17 -0
  50. package/build/esm/lib/core/components/Form/hooks/useField.d.ts +2 -2
  51. package/build/esm/lib/core/components/Form/hooks/useField.js +2 -2
  52. package/build/esm/lib/core/components/Form/hooks/useIntegrationFF.d.ts +2 -0
  53. package/build/esm/lib/core/components/Form/hooks/useIntegrationFF.js +41 -0
  54. package/build/esm/lib/core/components/Form/hooks/useSearch/index.d.ts +1 -0
  55. package/build/esm/lib/core/components/Form/hooks/useSearch/index.js +1 -0
  56. package/build/esm/lib/core/components/Form/hooks/useSearch/useSearch.css +9 -0
  57. package/build/esm/lib/core/components/Form/hooks/useSearch/useSearch.d.ts +4 -0
  58. package/build/esm/lib/core/components/Form/hooks/useSearch/useSearch.js +18 -0
  59. package/build/esm/lib/core/components/Form/hooks/useSearchContext.d.ts +1 -0
  60. package/build/esm/lib/core/components/Form/hooks/useSearchContext.js +7 -0
  61. package/build/esm/lib/core/components/Form/hooks/useSearchStore.d.ts +6 -0
  62. package/build/esm/lib/core/components/Form/hooks/useSearchStore.js +36 -0
  63. package/build/esm/lib/core/components/Form/hooks/useStore.d.ts +2 -8
  64. package/build/esm/lib/core/components/Form/hooks/useStore.js +5 -37
  65. package/build/esm/lib/core/components/Form/hooks/useValidate.js +1 -1
  66. package/build/esm/lib/core/components/Form/index.d.ts +1 -1
  67. package/build/esm/lib/core/components/Form/index.js +1 -1
  68. package/build/esm/lib/core/components/Form/types/context.d.ts +2 -1
  69. package/build/esm/lib/core/components/Form/types/index.d.ts +3 -0
  70. package/build/esm/lib/core/components/Form/types/index.js +3 -0
  71. package/build/esm/lib/core/components/Form/types/mirror.d.ts +17 -0
  72. package/build/esm/lib/core/components/Form/types/mirror.js +1 -0
  73. package/build/esm/lib/core/components/Form/types/search.d.ts +8 -0
  74. package/build/esm/lib/core/components/Form/types/search.js +1 -0
  75. package/build/esm/lib/core/components/Form/types/store.d.ts +7 -0
  76. package/build/esm/lib/core/components/Form/types/store.js +1 -0
  77. package/build/esm/lib/core/components/Form/{helpers.d.ts → utils/common.d.ts} +1 -1
  78. package/build/esm/lib/core/components/Form/{helpers.js → utils/common.js} +2 -2
  79. package/build/esm/lib/core/components/Form/utils/index.d.ts +2 -0
  80. package/build/esm/lib/core/components/Form/utils/index.js +2 -0
  81. package/build/esm/lib/core/components/Form/utils/search.d.ts +3 -0
  82. package/build/esm/lib/core/components/Form/utils/search.js +14 -0
  83. package/build/esm/lib/kit/components/Inputs/TableArrayInput/TableArrayInput.css +10 -0
  84. package/build/esm/lib/kit/components/Inputs/TableArrayInput/TableArrayInput.js +20 -9
  85. package/build/esm/lib/kit/components/Inputs/TextLink/TextLink.d.ts +2 -0
  86. package/build/esm/lib/kit/components/Inputs/TextLink/TextLink.js +15 -0
  87. package/build/esm/lib/kit/components/Inputs/TextLink/index.d.ts +1 -0
  88. package/build/esm/lib/kit/components/Inputs/TextLink/index.js +1 -0
  89. package/build/esm/lib/kit/components/Inputs/index.d.ts +1 -0
  90. package/build/esm/lib/kit/components/Inputs/index.js +1 -0
  91. package/build/esm/lib/kit/components/Layouts/Row/Row.css +18 -10
  92. package/build/esm/lib/kit/components/Layouts/Row/Row.js +4 -5
  93. package/build/esm/lib/kit/components/Views/TextLinkView/TextLinkView.d.ts +2 -0
  94. package/build/esm/lib/kit/components/Views/TextLinkView/TextLinkView.js +12 -0
  95. package/build/esm/lib/kit/components/Views/TextLinkView/index.d.ts +1 -0
  96. package/build/esm/lib/kit/components/Views/TextLinkView/index.js +1 -0
  97. package/build/esm/lib/kit/components/Views/index.d.ts +1 -0
  98. package/build/esm/lib/kit/components/Views/index.js +1 -0
  99. package/build/esm/lib/kit/constants/config.js +5 -1
  100. package/build/esm/lib/kit/validators/validators.js +1 -2
  101. package/package.json +12 -4
@@ -7,15 +7,20 @@ 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 hooks_1 = require("../../../../core/components/Form/hooks");
10
11
  const utils_1 = require("../../../utils");
11
12
  const b = (0, utils_1.block)('table-array');
12
13
  const TableArrayInput = ({ spec, name, arrayInput, input }) => {
14
+ const { isHiddenField } = (0, hooks_1.useSearchContext)();
13
15
  const keys = react_1.default.useMemo(() => Object.keys(arrayInput.value || {})
14
16
  .filter((k) => k !== core_1.OBJECT_ARRAY_FLAG &&
15
17
  k !== core_1.OBJECT_ARRAY_CNT &&
16
18
  arrayInput.value[k] !== core_1.REMOVED_ITEM)
17
19
  .map((k) => k.split('<').join('').split('>').join(''))
18
- .sort((a, b) => Number(a) - Number(b)), [arrayInput.value]);
20
+ .sort((a, b) => Number(a) - Number(b))
21
+ .map((key) => ({
22
+ key,
23
+ })), [arrayInput.value]);
19
24
  const onItemAdd = react_1.default.useCallback(() => {
20
25
  arrayInput.onItemAdd({});
21
26
  }, [arrayInput.onItemAdd]);
@@ -33,39 +38,45 @@ const TableArrayInput = ({ spec, name, arrayInput, input }) => {
33
38
  id: 'idx',
34
39
  name: '',
35
40
  sticky: 'left',
36
- template: (key, idx) => (react_1.default.createElement("div", { className: b('idx'), key: `idx-${key}` }, idx + 1)),
41
+ template: ({ key }, idx) => (react_1.default.createElement("div", { className: b('idx'), key: `idx-${key}` }, idx + 1)),
37
42
  };
38
43
  const removeColumn = {
39
44
  id: 'remove',
40
45
  name: '',
41
46
  sticky: 'right',
42
- template: (key) => (react_1.default.createElement(uikit_1.Button, { view: "flat", onClick: () => onItemRemove(key), key: `remove-${key}` },
47
+ template: ({ key }) => (react_1.default.createElement(uikit_1.Button, { view: "flat", onClick: () => onItemRemove(key), key: `remove-${key}` },
43
48
  react_1.default.createElement(uikit_1.Icon, { data: icons_1.Xmark, size: 16 }))),
44
49
  };
45
50
  const columns = table.map(({ property, label }) => ({
46
51
  id: property,
47
52
  name: label,
48
- template: (key) => {
53
+ template: ({ key, }, idx) => {
49
54
  var _a, _b, _c;
50
55
  const entitySpec = (_a = items === null || items === void 0 ? void 0 : items.properties) === null || _a === void 0 ? void 0 : _a[property];
51
56
  if (!entitySpec) {
52
57
  return null;
53
58
  }
59
+ const preparedEntitySpec = Object.assign(Object.assign({}, entitySpec), { viewSpec: Object.assign(Object.assign({}, entitySpec.viewSpec), { layoutTitle: table.map(({ label }) => label).join(` ${idx + 1} `) + ` ${idx + 1}` }) });
54
60
  return (react_1.default.createElement("div", { className: b('cell', {
55
- bool: (0, core_1.isBooleanSpec)(entitySpec),
56
- arr: (0, core_1.isArraySpec)(entitySpec),
57
- obj: (0, core_1.isObjectSpec)(entitySpec),
61
+ bool: (0, core_1.isBooleanSpec)(preparedEntitySpec),
62
+ arr: (0, core_1.isArraySpec)(preparedEntitySpec),
63
+ obj: (0, core_1.isObjectSpec)(preparedEntitySpec),
58
64
  }), key: `${name}.<${key}>.${property}` },
59
- 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: entitySpec, name: `${name}.<${key}>.${property}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount })));
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 })));
60
66
  },
61
67
  }));
62
68
  return [idxColumn, ...columns, removeColumn];
63
69
  }, [name, spec, onItemRemove, parentOnChange, parentOnUnmount, input.value]);
70
+ const getRowClassNames = react_1.default.useCallback(({ key }) => {
71
+ var _a;
72
+ const searchResult = (_a = spec.viewSpec.table) === null || _a === void 0 ? void 0 : _a.every(({ property }) => isHiddenField(`${name}.<${key}>.${property}`));
73
+ return [b('row', { hidden: searchResult })];
74
+ }, [isHiddenField, name, spec.viewSpec.table]);
64
75
  if (!columns) {
65
76
  return null;
66
77
  }
67
78
  return (react_1.default.createElement("div", { className: b() },
68
- keys.length ? (react_1.default.createElement(uikit_1.Table, { className: b('table'), data: keys, columns: columns, getRowId: (_, idx) => `${name}-${idx}`, verticalAlign: "top" })) : null,
79
+ keys.length ? (react_1.default.createElement(uikit_1.Table, { className: b('table'), data: keys, columns: columns, getRowId: (_, idx) => `${name}-${idx}`, verticalAlign: "top", getRowClassNames: getRowClassNames })) : null,
69
80
  !arrayInput.value && spec.defaultValue ? (react_1.default.createElement(uikit_1.Button, { onClick: () => input.onChange((0, core_1.transformArrIn)(spec.defaultValue)), disabled: spec.viewSpec.disabled },
70
81
  react_1.default.createElement(uikit_1.Icon, { data: icons_1.Plus, size: 14 }),
71
82
  spec.viewSpec.layoutTitle || null)) : (react_1.default.createElement(uikit_1.Button, { onClick: onItemAdd, disabled: spec.viewSpec.disabled },
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TextLink = 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 TEXT_LINK_PROPERTY_NAME = 'text';
9
+ const TextLink = ({ spec, input, name }) => {
10
+ var _a;
11
+ const parentOnChange = react_1.default.useCallback((childName, childValue, childErrors) => input.onChange((currentValue) => lodash_1.default.set(Object.assign({}, currentValue), childName.split(`${name}.`).join(''), childValue), childErrors), [input.onChange, input.name]);
12
+ const parentOnUnmount = react_1.default.useCallback((childName) => input.onChange((currentValue) => currentValue, { [childName]: false }), [input.onChange]);
13
+ const specProperties = Object.assign({}, spec.properties);
14
+ if (!specProperties[TEXT_LINK_PROPERTY_NAME] ||
15
+ !(0, core_1.isStringSpec)(specProperties[TEXT_LINK_PROPERTY_NAME])) {
16
+ return null;
17
+ }
18
+ return (react_1.default.createElement(core_1.Controller, { initialValue: (_a = input.value) === null || _a === void 0 ? void 0 : _a[TEXT_LINK_PROPERTY_NAME], spec: specProperties[TEXT_LINK_PROPERTY_NAME], name: `${name}.${TEXT_LINK_PROPERTY_NAME}`, key: `${name}.${TEXT_LINK_PROPERTY_NAME}`, parentOnChange: parentOnChange, parentOnUnmount: parentOnUnmount }));
19
+ };
20
+ exports.TextLink = TextLink;
@@ -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("./TextLink"), exports);
@@ -14,5 +14,6 @@ tslib_1.__exportStar(require("./TableArrayInput"), exports);
14
14
  tslib_1.__exportStar(require("./Text"), exports);
15
15
  tslib_1.__exportStar(require("./TextArea"), exports);
16
16
  tslib_1.__exportStar(require("./TextContent"), exports);
17
+ tslib_1.__exportStar(require("./TextLink"), exports);
17
18
  tslib_1.__exportStar(require("./NumberWithScale"), exports);
18
19
  tslib_1.__exportStar(require("./MonacoInput"), exports);
@@ -13,13 +13,16 @@
13
13
  }
14
14
  .df-row__left {
15
15
  width: 180px;
16
+ min-height: 28px;
16
17
  display: flex;
18
+ margin-bottom: auto;
17
19
  flex-direction: column;
18
20
  flex-shrink: 0;
19
21
  }
20
22
  .df-row__left-inner {
21
- min-height: 28px;
22
- display: flex;
23
+ display: inline;
24
+ margin-top: auto;
25
+ margin-bottom: auto;
23
26
  }
24
27
  .df-row__left::after {
25
28
  content: "";
@@ -27,18 +30,24 @@
27
30
  flex-shrink: 1;
28
31
  }
29
32
  .df-row__title {
30
- align-self: center;
33
+ word-break: break-word;
34
+ margin-right: 3px;
35
+ }
36
+ .df-row__title_required::after {
37
+ content: "*";
38
+ color: var(--yc-color-text-danger);
31
39
  }
32
40
  .df-row__note {
33
- height: 28px;
34
- display: flex;
35
- align-items: center;
36
- margin-left: 5px;
41
+ padding-right: 16px;
42
+ }
43
+ .df-row__note-inner {
44
+ position: absolute;
45
+ margin-top: 1px;
37
46
  }
38
- .df-row__note .yc-help-popover {
47
+ .df-row__note-inner .yc-help-popover {
39
48
  display: flex;
40
49
  }
41
- .df-row__note .yc-help-popover > span {
50
+ .df-row__note-inner .yc-help-popover > span {
42
51
  display: flex;
43
52
  }
44
53
  .df-row__right {
@@ -59,6 +68,5 @@
59
68
  margin-left: 5px;
60
69
  }
61
70
  .df-row__required-mark {
62
- margin-left: 2px;
63
71
  color: var(--yc-color-text-danger);
64
72
  }
@@ -14,11 +14,10 @@ const RowBase = ({ name, spec, input, meta, verboseDescription, children, }) =>
14
14
  return (react_1.default.createElement("div", { className: b({ 'extra-width': (0, core_1.isArraySpec)(spec) || arrayItem }) },
15
15
  react_1.default.createElement("div", { className: b('left') },
16
16
  react_1.default.createElement("div", { className: b('left-inner') },
17
- react_1.default.createElement("div", { className: b('title') },
18
- spec.viewSpec.layoutTitle,
19
- spec.required && react_1.default.createElement("span", { className: b('required-mark') }, "*")),
20
- !verboseDescription && spec.viewSpec.layoutDescription ? (react_1.default.createElement("div", { className: b('note') },
21
- react_1.default.createElement(uikit_1.HelpPopover, { htmlContent: spec.viewSpec.layoutDescription, placement: ['bottom', 'top'] }))) : null)),
17
+ react_1.default.createElement("span", { className: b('title', { required: spec.required }) }, spec.viewSpec.layoutTitle),
18
+ !verboseDescription && spec.viewSpec.layoutDescription ? (react_1.default.createElement("span", { className: b('note') },
19
+ react_1.default.createElement("span", { className: b('note-inner') },
20
+ react_1.default.createElement(uikit_1.HelpPopover, { htmlContent: spec.viewSpec.layoutDescription, placement: ['bottom', 'top'] })))) : null)),
22
21
  react_1.default.createElement("div", { className: b('right') },
23
22
  react_1.default.createElement("div", { className: b('right-inner') },
24
23
  react_1.default.createElement(components_1.ErrorWrapper, { name: name, meta: meta, withoutChildErrorStyles: (0, core_1.isArraySpec)(spec) || (0, core_1.isObjectSpec)(spec) }, children),
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TextLinkView = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const core_1 = require("../../../../core");
7
+ const TEXT_LINK_PROPERTY_NAME = 'text';
8
+ const TextLinkView = ({ value, spec, name }) => {
9
+ const specProperties = spec.properties;
10
+ const preparedSpec = react_1.default.useMemo(() => {
11
+ var _a;
12
+ return specProperties && specProperties[TEXT_LINK_PROPERTY_NAME]
13
+ ? Object.assign(Object.assign({}, specProperties[TEXT_LINK_PROPERTY_NAME]), { viewSpec: Object.assign(Object.assign({}, (_a = specProperties[TEXT_LINK_PROPERTY_NAME]) === null || _a === void 0 ? void 0 : _a.viewSpec), { link: value === null || value === void 0 ? void 0 : value.link }) }) : undefined;
14
+ }, [specProperties, value === null || value === void 0 ? void 0 : value.link]);
15
+ return preparedSpec ? (react_1.default.createElement(core_1.ViewController, { spec: preparedSpec, name: `${name}.${TEXT_LINK_PROPERTY_NAME}` })) : null;
16
+ };
17
+ exports.TextLinkView = TextLinkView;
@@ -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("./TextLinkView"), exports);
@@ -12,3 +12,4 @@ tslib_1.__exportStar(require("./OneOfCardView"), exports);
12
12
  tslib_1.__exportStar(require("./OneOfView"), exports);
13
13
  tslib_1.__exportStar(require("./TableArrayView"), exports);
14
14
  tslib_1.__exportStar(require("./TextAreaView"), exports);
15
+ tslib_1.__exportStar(require("./TextLinkView"), exports);
@@ -60,6 +60,7 @@ exports.dynamicConfig = {
60
60
  card_oneof: { Component: components_1.CardOneOf, independent: true },
61
61
  secret: { Component: components_1.Secret, independent: true },
62
62
  base: { Component: components_1.ObjectBase, independent: true },
63
+ text_link: { Component: components_1.TextLink, independent: true },
63
64
  },
64
65
  layouts: {
65
66
  row: components_1.Row,
@@ -155,6 +156,7 @@ exports.dynamicCardConfig = {
155
156
  oneof: { Component: components_1.OneOfCard, independent: true },
156
157
  secret: { Component: components_1.Secret, independent: true },
157
158
  base: { Component: components_1.ObjectBase, independent: true },
159
+ text_link: { Component: components_1.TextLink, independent: true },
158
160
  },
159
161
  layouts: {
160
162
  row: components_1.Row2,
@@ -239,6 +241,7 @@ exports.dynamicViewConfig = {
239
241
  card_oneof: { Component: components_1.CardOneOfView, independent: true },
240
242
  secret: undefined,
241
243
  base: { Component: components_1.ObjectBaseView, independent: true },
244
+ text_link: { Component: components_1.TextLinkView, independent: true },
242
245
  },
243
246
  layouts: {
244
247
  row: components_1.ViewRow,
@@ -316,6 +319,7 @@ exports.dynamicViewCardConfig = {
316
319
  oneof: { Component: components_1.OneOfCardView, independent: true },
317
320
  secret: undefined,
318
321
  base: { Component: components_1.ObjectBaseView, independent: true },
322
+ text_link: { Component: components_1.TextLinkView, independent: true },
319
323
  },
320
324
  layouts: {
321
325
  row: components_1.ViewRow2,
@@ -71,8 +71,7 @@ const getNumberValidator = (params = {}) => {
71
71
  }
72
72
  if (!ignoreMinimumCheck &&
73
73
  lodash_1.default.isNumber(spec.minimum) &&
74
- stringValue.length &&
75
- spec.minimum > Number(stringValue)) {
74
+ ((stringValue.length && spec.minimum > Number(stringValue)) || !stringValue.length)) {
76
75
  return validators_1.ErrorMessages.minNumber(spec.minimum);
77
76
  }
78
77
  if (lodash_1.default.isString(spec.format) && stringValue.length) {
@@ -1,8 +1,8 @@
1
1
  import _ from 'lodash';
2
2
  import { isCorrectSpec } from '../../helpers';
3
- import { useComponents, useDynamicFormsCtx, useField, useRender, useValidate } from './hooks';
3
+ import { useComponents, useControllerMirror, useDynamicFormsCtx, useField, useRender, useSearch, useValidate, } from './hooks';
4
4
  export const Controller = ({ spec, name, initialValue, parentOnChange, parentOnUnmount, }) => {
5
- const { tools } = useDynamicFormsCtx();
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);
@@ -15,8 +15,16 @@ export const Controller = ({ spec, name, initialValue, parentOnChange, parentOnU
15
15
  parentOnChange,
16
16
  parentOnUnmount,
17
17
  });
18
+ const withSearch = useSearch(spec, renderProps.input.value, name);
19
+ useControllerMirror(name, {
20
+ useComponents: { inputEntity, Layout },
21
+ useRender: render,
22
+ useValidate: validate,
23
+ useField: renderProps,
24
+ useSearch: withSearch,
25
+ }, __mirror);
18
26
  if (_.isString(name) && isCorrectSpec(spec)) {
19
- return render(renderProps);
27
+ return withSearch(render(renderProps));
20
28
  }
21
29
  return null;
22
30
  };
@@ -1,11 +1,13 @@
1
1
  import React from 'react';
2
2
  import type { MonacoEditorProps } from 'react-monaco-editor/lib/types';
3
3
  import { Spec } from '../../types';
4
- import { DynamicFormConfig } from './types';
4
+ import { DynamicFormConfig, FieldValue, WonderMirror } from './types';
5
5
  export interface DynamicFieldProps {
6
6
  name: string;
7
7
  spec: Spec;
8
8
  config: DynamicFormConfig;
9
9
  Monaco?: React.ComponentType<MonacoEditorProps>;
10
+ search?: string | ((spec: Spec, input: FieldValue, name: string) => boolean);
11
+ __mirror?: WonderMirror;
10
12
  }
11
13
  export declare const DynamicField: React.FC<DynamicFieldProps>;
@@ -3,21 +3,37 @@ import _ from 'lodash';
3
3
  import { isValidElementType } from 'react-is';
4
4
  import { isCorrectSpec } from '../../helpers';
5
5
  import { Controller } from './Controller';
6
- import { isCorrectConfig } from './helpers';
7
- import { useCreateContext, useStore } from './hooks';
8
- export const DynamicField = ({ name, spec, config, Monaco }) => {
6
+ import { useCreateContext, useCreateSearchContext, useDynamicFieldMirror, useIntegrationFF, useSearchStore, useStore, } from './hooks';
7
+ import { getDefaultSearchFunction, isCorrectConfig } from './utils';
8
+ export const DynamicField = ({ name, spec, config, Monaco, search, __mirror, }) => {
9
9
  const DynamicFormsCtx = useCreateContext();
10
- const { tools, watcher } = useStore(name);
10
+ const SearchContext = useCreateSearchContext();
11
+ const { tools, store } = useStore(name);
12
+ const watcher = useIntegrationFF(store);
13
+ const { store: searchStore, setField, removeField, isHiddenField } = useSearchStore();
11
14
  const context = React.useMemo(() => ({
12
15
  config,
13
16
  Monaco: isValidElementType(Monaco) ? Monaco : undefined,
14
17
  tools,
15
- }), [tools, config, Monaco]);
18
+ __mirror,
19
+ }), [tools, config, Monaco, __mirror]);
20
+ const searchContext = React.useMemo(() => ({
21
+ setField,
22
+ removeField,
23
+ isHiddenField,
24
+ searchFunction: _.isFunction(search) ? search : getDefaultSearchFunction(search),
25
+ }), [isHiddenField, removeField, search, setField]);
16
26
  const correctParams = React.useMemo(() => _.isString(name) && isCorrectSpec(spec) && isCorrectConfig(config), [name, spec, config]);
27
+ useDynamicFieldMirror({
28
+ useStore: { tools, store },
29
+ useIntegrationFF: watcher,
30
+ useSearchStore: { store: searchStore, setField, removeField, isHiddenField },
31
+ }, __mirror);
17
32
  if (correctParams) {
18
33
  return (React.createElement(DynamicFormsCtx.Provider, { value: context },
19
- React.createElement(Controller, { spec: spec, name: name, parentOnChange: null, parentOnUnmount: null, initialValue: _.get(tools.initialValue, name) }),
20
- watcher));
34
+ React.createElement(SearchContext.Provider, { value: searchContext },
35
+ React.createElement(Controller, { spec: spec, name: name, parentOnChange: null, parentOnUnmount: null, initialValue: _.get(tools.initialValue, name) }),
36
+ watcher)));
21
37
  }
22
38
  return null;
23
39
  };
@@ -1,8 +1,15 @@
1
1
  export * from './useComponents';
2
+ export * from './useControllerMirror';
2
3
  export * from './useCreateContext';
4
+ export * from './useDynamicFieldMirror';
3
5
  export * from './useDynamicFormsCtx';
4
6
  export * from './useField';
7
+ export * from './useIntegrationFF';
5
8
  export * from './useRender';
6
9
  export * from './useStore';
7
10
  export * from './useValidate';
8
11
  export * from './useMonaco';
12
+ export * from './useSearchStore';
13
+ export * from './useSearchContext';
14
+ export * from './useSearch';
15
+ export * from './useCreateSearchContext';
@@ -1,8 +1,15 @@
1
1
  export * from './useComponents';
2
+ export * from './useControllerMirror';
2
3
  export * from './useCreateContext';
4
+ export * from './useDynamicFieldMirror';
3
5
  export * from './useDynamicFormsCtx';
4
6
  export * from './useField';
7
+ export * from './useIntegrationFF';
5
8
  export * from './useRender';
6
9
  export * from './useStore';
7
10
  export * from './useValidate';
8
11
  export * from './useMonaco';
12
+ export * from './useSearchStore';
13
+ export * from './useSearchContext';
14
+ export * from './useSearch';
15
+ export * from './useCreateSearchContext';
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import _ from 'lodash';
3
3
  import { isValidElementType } from 'react-is';
4
4
  import { isCorrectSpec } from '../../../helpers';
5
- import { isCorrectConfig } from '../helpers';
5
+ import { isCorrectConfig } from '../utils';
6
6
  import { useDynamicFormsCtx } from './';
7
7
  export const useComponents = (spec) => {
8
8
  var _a, _b;
@@ -0,0 +1,2 @@
1
+ import { ControllerMirror, WonderMirror } from '../types';
2
+ export declare const useControllerMirror: (name: string, params: ControllerMirror, __mirror?: WonderMirror) => void;
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ export const useControllerMirror = (name, params, __mirror) => {
3
+ if (__mirror === null || __mirror === void 0 ? void 0 : __mirror.controller) {
4
+ __mirror.controller[name] = params;
5
+ }
6
+ React.useEffect(() => {
7
+ return () => {
8
+ var _a;
9
+ if ((_a = __mirror === null || __mirror === void 0 ? void 0 : __mirror.controller) === null || _a === void 0 ? void 0 : _a[name]) {
10
+ delete __mirror.controller[name];
11
+ }
12
+ };
13
+ }, []);
14
+ };
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import { SearchContext } from '../types';
3
+ export declare const useCreateSearchContext: () => React.Context<SearchContext>;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import _ from 'lodash';
3
+ const createContext = _.once(() => React.createContext({}));
4
+ export const useCreateSearchContext = () => createContext();
@@ -0,0 +1,2 @@
1
+ import { DynamicFieldMirror, WonderMirror } from '../types';
2
+ export declare const useDynamicFieldMirror: (params: DynamicFieldMirror, __mirror?: WonderMirror) => void;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ export const useDynamicFieldMirror = (params, __mirror) => {
3
+ if (__mirror === null || __mirror === void 0 ? void 0 : __mirror.field) {
4
+ __mirror.field.useStore = params.useStore;
5
+ __mirror.field.useIntegrationFF = params.useIntegrationFF;
6
+ __mirror.field.useSearchStore = params.useSearchStore;
7
+ }
8
+ React.useEffect(() => {
9
+ return () => {
10
+ if (__mirror === null || __mirror === void 0 ? void 0 : __mirror.field) {
11
+ delete __mirror.field.useStore;
12
+ delete __mirror.field.useIntegrationFF;
13
+ delete __mirror.field.useSearchStore;
14
+ }
15
+ };
16
+ }, []);
17
+ };
@@ -1,6 +1,6 @@
1
1
  import { Spec } from '../../../types';
2
2
  import { DynamicFormsContext, FieldRenderProps, FieldValue, ValidateError } from '../types';
3
- export interface FieldProps<Value extends FieldValue, SpecType extends Spec> {
3
+ export interface UseFieldProps<Value extends FieldValue, SpecType extends Spec> {
4
4
  name: string;
5
5
  spec: SpecType;
6
6
  initialValue: Value;
@@ -9,4 +9,4 @@ export interface FieldProps<Value extends FieldValue, SpecType extends Spec> {
9
9
  parentOnChange: ((childName: string, childValue: FieldValue, childErrors: Record<string, ValidateError>) => void) | null;
10
10
  parentOnUnmount: ((childName: string) => void) | null;
11
11
  }
12
- export declare const useField: <Value extends FieldValue, SpecType extends Spec>({ name, spec, initialValue, validate: propsValidate, tools, parentOnChange, parentOnUnmount, }: FieldProps<Value, SpecType>) => FieldRenderProps<Value>;
12
+ export declare const useField: <Value extends FieldValue, SpecType extends Spec>({ name, spec, initialValue, validate: propsValidate, tools, parentOnChange, parentOnUnmount, }: UseFieldProps<Value, SpecType>) => FieldRenderProps<Value>;
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import _ from 'lodash';
3
3
  import { isArraySpec, isObjectSpec } from '../../../helpers';
4
4
  import { OBJECT_ARRAY_CNT, OBJECT_ARRAY_FLAG, REMOVED_ITEM } from '../constants';
5
- import { isArrayItem, transformArrIn, transformArrOut } from '../helpers';
5
+ import { isArrayItem, transformArrIn, transformArrOut } from '../utils';
6
6
  export const useField = ({ name, spec, initialValue, validate: propsValidate, tools, parentOnChange, parentOnUnmount, }) => {
7
7
  const firstRenderRef = React.useRef(true);
8
8
  const validate = React.useCallback((value) => {
@@ -122,7 +122,7 @@ export const useField = ({ name, spec, initialValue, validate: propsValidate, to
122
122
  onDrop,
123
123
  ]);
124
124
  React.useEffect(() => {
125
- if (!firstRenderRef.current || !_.isEqual(initialValue, state.value)) {
125
+ if (!firstRenderRef.current || !_.isEqual(initialValue, state.value) || state.error) {
126
126
  (parentOnChange ? parentOnChange : tools.onChange)(name, state.value, Object.assign(Object.assign({}, state.childErrors), { [name]: state.error }));
127
127
  }
128
128
  }, [state.value]);
@@ -0,0 +1,2 @@
1
+ import { DynamicFieldStore } from '../types';
2
+ export declare const useIntegrationFF: (store: DynamicFieldStore) => JSX.Element;
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import _ from 'lodash';
3
+ import debounce from 'lodash/debounce';
4
+ import { Field as FinalFormField, useForm } from 'react-final-form';
5
+ import { transformArrOut } from '../utils';
6
+ export const useIntegrationFF = (store) => {
7
+ const form = useForm();
8
+ const watcher = React.useMemo(() => {
9
+ const props = {
10
+ name: store.name,
11
+ render: () => null,
12
+ subscription: {},
13
+ validate: () => {
14
+ const asyncErrors = [];
15
+ let error;
16
+ _.values(store.errors).forEach((err) => {
17
+ if (err) {
18
+ if (_.isFunction(err === null || err === void 0 ? void 0 : err.then)) {
19
+ asyncErrors.push(err);
20
+ }
21
+ else {
22
+ error = err;
23
+ }
24
+ }
25
+ });
26
+ if (asyncErrors.length) {
27
+ return Promise.all(asyncErrors).then((r) => r[0]);
28
+ }
29
+ return error;
30
+ },
31
+ };
32
+ return React.createElement(FinalFormField, Object.assign({}, props));
33
+ }, [store.name, store.errors]);
34
+ const change = React.useCallback(debounce((value) => {
35
+ form.change(store.name, _.get(transformArrOut(value), store.name));
36
+ }, 100), [form.change, store.name]);
37
+ React.useEffect(() => {
38
+ change(store.values);
39
+ }, [store.values]);
40
+ return watcher;
41
+ };
@@ -0,0 +1 @@
1
+ export * from './useSearch';
@@ -0,0 +1 @@
1
+ export * from './useSearch';
@@ -0,0 +1,9 @@
1
+ .df-use-search {
2
+ margin-bottom: 15px;
3
+ }
4
+ .df-use-search_hidden {
5
+ display: none;
6
+ }
7
+ .df-use-search:last-child {
8
+ margin-bottom: 0;
9
+ }
@@ -0,0 +1,4 @@
1
+ import { Spec } from '../../../../types';
2
+ import { FieldValue } from '../../types';
3
+ import './useSearch.css';
4
+ export declare const useSearch: (spec: Spec, value: FieldValue, name: string) => (children: JSX.Element | null) => JSX.Element;
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { block } from '../../../../../kit/utils';
3
+ import { useSearchContext } from '../useSearchContext';
4
+ import './useSearch.css';
5
+ const b = block('use-search');
6
+ export const useSearch = (spec, value, name) => {
7
+ const { setField, removeField, isHiddenField, searchFunction } = useSearchContext();
8
+ const searchResult = React.useMemo(() => !searchFunction(spec, value, name), [name, searchFunction, spec, value]);
9
+ const hidden = React.useMemo(() => isHiddenField(name), [isHiddenField, name]);
10
+ const withSearch = React.useCallback((children) => React.createElement("div", { className: b({ hidden: hidden }) }, children), [hidden]);
11
+ React.useEffect(() => {
12
+ setField(name, searchResult);
13
+ }, [searchResult]);
14
+ React.useEffect(() => {
15
+ return () => removeField(name);
16
+ }, []);
17
+ return withSearch;
18
+ };
@@ -0,0 +1 @@
1
+ export declare const useSearchContext: () => import("..").SearchContext;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { useCreateSearchContext } from './index';
3
+ export const useSearchContext = () => {
4
+ const SearchContext = useCreateSearchContext();
5
+ const context = React.useContext(SearchContext);
6
+ return context;
7
+ };
@@ -0,0 +1,6 @@
1
+ export declare const useSearchStore: () => {
2
+ store: Record<string, boolean>;
3
+ setField: (name: string, search: boolean) => void;
4
+ removeField: (name: string) => void;
5
+ isHiddenField: (name: string) => boolean;
6
+ };
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+ import _ from 'lodash';
3
+ import { getParentName } from '../';
4
+ export const useSearchStore = () => {
5
+ const [store, setStore] = React.useState({});
6
+ const isHiddenField = React.useCallback((name) => {
7
+ const selfFlag = store[name];
8
+ if (selfFlag === false) {
9
+ return false;
10
+ }
11
+ let parentName = getParentName(name);
12
+ while (parentName) {
13
+ if (store[parentName] === false) {
14
+ return false;
15
+ }
16
+ parentName = getParentName(parentName);
17
+ }
18
+ for (const key of Object.keys(store)) {
19
+ if (key.includes(name + '.') && !store[key]) {
20
+ return false;
21
+ }
22
+ }
23
+ if (_.isUndefined(selfFlag)) {
24
+ return false;
25
+ }
26
+ return true;
27
+ }, [store]);
28
+ return {
29
+ store,
30
+ setField: (name, search) => setStore((store) => (Object.assign(Object.assign({}, store), { [name]: search }))),
31
+ removeField: (name) => {
32
+ setStore((store) => _.omit(store, name));
33
+ },
34
+ isHiddenField,
35
+ };
36
+ };