@gravity-ui/dynamic-forms 1.2.0 → 1.4.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 (99) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +34 -5
  3. package/build/cjs/lib/core/components/Form/Controller.js +9 -3
  4. package/build/cjs/lib/core/components/Form/DynamicField.js +11 -4
  5. package/build/cjs/lib/core/components/Form/hooks/index.js +3 -0
  6. package/build/cjs/lib/core/components/Form/hooks/useControllerMirror.js +19 -0
  7. package/build/cjs/lib/core/components/Form/hooks/useDynamicFieldMirror.js +22 -0
  8. package/build/cjs/lib/core/components/Form/hooks/useField.js +1 -1
  9. package/build/cjs/lib/core/components/Form/hooks/useIntegrationFF.js +46 -0
  10. package/build/cjs/lib/core/components/Form/hooks/useSearchStore.js +5 -2
  11. package/build/cjs/lib/core/components/Form/hooks/useStore.js +3 -35
  12. package/build/cjs/lib/core/components/Form/types/index.js +2 -0
  13. package/build/cjs/lib/core/components/Form/types/mirror.js +2 -0
  14. package/build/cjs/lib/core/components/Form/types/store.js +2 -0
  15. package/build/cjs/lib/core/components/View/ViewController.js +2 -2
  16. package/build/cjs/lib/core/components/View/hooks/useComponents.js +1 -3
  17. package/build/cjs/lib/kit/components/Inputs/FileInput/FileInput.css +20 -0
  18. package/build/cjs/lib/kit/components/Inputs/FileInput/FileInput.js +50 -0
  19. package/build/cjs/lib/kit/components/Inputs/FileInput/index.js +4 -0
  20. package/build/cjs/lib/kit/components/Inputs/FileInput/utils.js +16 -0
  21. package/build/cjs/lib/kit/components/Inputs/TableArrayInput/TableArrayInput.js +3 -2
  22. package/build/cjs/lib/kit/components/Inputs/TextLink/TextLink.js +20 -0
  23. package/build/cjs/lib/kit/components/Inputs/TextLink/index.js +4 -0
  24. package/build/cjs/lib/kit/components/Inputs/index.js +2 -0
  25. package/build/cjs/lib/kit/components/Layouts/Row/Row.css +18 -10
  26. package/build/cjs/lib/kit/components/Layouts/Row/Row.js +4 -5
  27. package/build/cjs/lib/kit/components/Views/FileInputView/FileInputView.js +12 -0
  28. package/build/cjs/lib/kit/components/Views/FileInputView/index.js +4 -0
  29. package/build/cjs/lib/kit/components/Views/TextLinkView/TextLinkView.js +17 -0
  30. package/build/cjs/lib/kit/components/Views/TextLinkView/index.js +4 -0
  31. package/build/cjs/lib/kit/components/Views/index.js +2 -0
  32. package/build/cjs/lib/kit/constants/config.js +8 -0
  33. package/build/cjs/lib/kit/i18n/en.json +3 -1
  34. package/build/cjs/lib/kit/i18n/ru.json +3 -1
  35. package/build/cjs/lib/kit/utils/common.js +1 -26
  36. package/build/cjs/lib/kit/validators/validators.js +8 -8
  37. package/build/esm/lib/core/components/Form/Controller.js +9 -3
  38. package/build/esm/lib/core/components/Form/DynamicField.d.ts +2 -1
  39. package/build/esm/lib/core/components/Form/DynamicField.js +12 -5
  40. package/build/esm/lib/core/components/Form/hooks/index.d.ts +3 -0
  41. package/build/esm/lib/core/components/Form/hooks/index.js +3 -0
  42. package/build/esm/lib/core/components/Form/hooks/useControllerMirror.d.ts +2 -0
  43. package/build/esm/lib/core/components/Form/hooks/useControllerMirror.js +14 -0
  44. package/build/esm/lib/core/components/Form/hooks/useDynamicFieldMirror.d.ts +2 -0
  45. package/build/esm/lib/core/components/Form/hooks/useDynamicFieldMirror.js +17 -0
  46. package/build/esm/lib/core/components/Form/hooks/useField.d.ts +2 -2
  47. package/build/esm/lib/core/components/Form/hooks/useField.js +1 -1
  48. package/build/esm/lib/core/components/Form/hooks/useIntegrationFF.d.ts +2 -0
  49. package/build/esm/lib/core/components/Form/hooks/useIntegrationFF.js +41 -0
  50. package/build/esm/lib/core/components/Form/hooks/useSearchStore.d.ts +2 -4
  51. package/build/esm/lib/core/components/Form/hooks/useSearchStore.js +5 -2
  52. package/build/esm/lib/core/components/Form/hooks/useStore.d.ts +2 -8
  53. package/build/esm/lib/core/components/Form/hooks/useStore.js +5 -37
  54. package/build/esm/lib/core/components/Form/types/context.d.ts +2 -1
  55. package/build/esm/lib/core/components/Form/types/index.d.ts +2 -0
  56. package/build/esm/lib/core/components/Form/types/index.js +2 -0
  57. package/build/esm/lib/core/components/Form/types/mirror.d.ts +17 -0
  58. package/build/esm/lib/core/components/Form/types/mirror.js +1 -0
  59. package/build/esm/lib/core/components/Form/types/store.d.ts +7 -0
  60. package/build/esm/lib/core/components/Form/types/store.js +1 -0
  61. package/build/esm/lib/core/components/View/ViewController.js +2 -2
  62. package/build/esm/lib/core/components/View/hooks/useComponents.d.ts +2 -2
  63. package/build/esm/lib/core/components/View/hooks/useComponents.js +1 -3
  64. package/build/esm/lib/core/constants.d.ts +1 -0
  65. package/build/esm/lib/core/types/specs.d.ts +6 -1
  66. package/build/esm/lib/kit/components/Inputs/FileInput/FileInput.css +20 -0
  67. package/build/esm/lib/kit/components/Inputs/FileInput/FileInput.d.ts +4 -0
  68. package/build/esm/lib/kit/components/Inputs/FileInput/FileInput.js +46 -0
  69. package/build/esm/lib/kit/components/Inputs/FileInput/index.d.ts +1 -0
  70. package/build/esm/lib/kit/components/Inputs/FileInput/index.js +1 -0
  71. package/build/esm/lib/kit/components/Inputs/FileInput/utils.d.ts +2 -0
  72. package/build/esm/lib/kit/components/Inputs/FileInput/utils.js +12 -0
  73. package/build/esm/lib/kit/components/Inputs/TableArrayInput/TableArrayInput.js +3 -2
  74. package/build/esm/lib/kit/components/Inputs/TextLink/TextLink.d.ts +2 -0
  75. package/build/esm/lib/kit/components/Inputs/TextLink/TextLink.js +15 -0
  76. package/build/esm/lib/kit/components/Inputs/TextLink/index.d.ts +1 -0
  77. package/build/esm/lib/kit/components/Inputs/TextLink/index.js +1 -0
  78. package/build/esm/lib/kit/components/Inputs/index.d.ts +2 -0
  79. package/build/esm/lib/kit/components/Inputs/index.js +2 -0
  80. package/build/esm/lib/kit/components/Layouts/Row/Row.css +18 -10
  81. package/build/esm/lib/kit/components/Layouts/Row/Row.js +4 -5
  82. package/build/esm/lib/kit/components/Views/FileInputView/FileInputView.d.ts +3 -0
  83. package/build/esm/lib/kit/components/Views/FileInputView/FileInputView.js +7 -0
  84. package/build/esm/lib/kit/components/Views/FileInputView/index.d.ts +1 -0
  85. package/build/esm/lib/kit/components/Views/FileInputView/index.js +1 -0
  86. package/build/esm/lib/kit/components/Views/TextLinkView/TextLinkView.d.ts +2 -0
  87. package/build/esm/lib/kit/components/Views/TextLinkView/TextLinkView.js +12 -0
  88. package/build/esm/lib/kit/components/Views/TextLinkView/index.d.ts +1 -0
  89. package/build/esm/lib/kit/components/Views/TextLinkView/index.js +1 -0
  90. package/build/esm/lib/kit/components/Views/index.d.ts +2 -0
  91. package/build/esm/lib/kit/components/Views/index.js +2 -0
  92. package/build/esm/lib/kit/constants/config.js +9 -1
  93. package/build/esm/lib/kit/i18n/en.json +3 -1
  94. package/build/esm/lib/kit/i18n/ru.json +3 -1
  95. package/build/esm/lib/kit/utils/common.d.ts +0 -2
  96. package/build/esm/lib/kit/utils/common.js +0 -24
  97. package/build/esm/lib/kit/validators/validators.d.ts +2 -0
  98. package/build/esm/lib/kit/validators/validators.js +8 -8
  99. package/package.json +12 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.4.0](https://github.com/gravity-ui/dynamic-forms/compare/v1.3.0...v1.4.0) (2023-04-11)
4
+
5
+
6
+ ### Features
7
+
8
+ * **FileInput:** added new input file input ([#24](https://github.com/gravity-ui/dynamic-forms/issues/24)) ([1553318](https://github.com/gravity-ui/dynamic-forms/commit/155331839e50ab4192b69ba32992e37b972378c4))
9
+
10
+ ## [1.3.0](https://github.com/gravity-ui/dynamic-forms/compare/v1.2.0...v1.3.0) (2023-03-31)
11
+
12
+
13
+ ### Features
14
+
15
+ * update row note position ([#20](https://github.com/gravity-ui/dynamic-forms/issues/20)) ([4f15395](https://github.com/gravity-ui/dynamic-forms/commit/4f153959596d3325ddeb2c2e9b24382e36d2db75))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * add fixes + tests ([#15](https://github.com/gravity-ui/dynamic-forms/issues/15)) ([80113dd](https://github.com/gravity-ui/dynamic-forms/commit/80113dd05737b18158865506ed3ac8479d69e8d0))
21
+ * **search:** fixed bug related to form blinking ([#21](https://github.com/gravity-ui/dynamic-forms/issues/21)) ([20bab2f](https://github.com/gravity-ui/dynamic-forms/commit/20bab2f628d698714bcee35993583f2c7712e843))
22
+ * **textArea:** fixed row for text area ([#22](https://github.com/gravity-ui/dynamic-forms/issues/22)) ([d5469e7](https://github.com/gravity-ui/dynamic-forms/commit/d5469e7dd0eee86b26e8daba94e93d2fa9465b96))
23
+
3
24
  ## [1.2.0](https://github.com/gravity-ui/dynamic-forms/compare/v1.1.1...v1.2.0) (2023-03-23)
4
25
 
5
26
 
package/README.md CHANGED
@@ -1,10 +1,6 @@
1
1
  # @gravity-ui/dynamic-forms · [![npm package](https://img.shields.io/npm/v/@gravity-ui/dynamic-forms)](https://www.npmjs.com/package/@gravity-ui/dynamic-forms) [![CI](https://img.shields.io/github/actions/workflow/status/gravity-ui/dynamic-forms/.github/workflows/ci.yml?label=CI&logo=github)](https://github.com/gravity-ui/dynamic-forms/actions/workflows/ci.yml?query=branch:main) [![storybook](https://img.shields.io/badge/Storybook-deployed-ff4685)](https://preview.gravity-ui.com/dynamic-forms/)
2
2
 
3
- This is a template for typical package.
4
-
5
- 1. Create a new repository and use this repository as a template.
6
- 2. Replace `dynamic-forms` through the whole repository with your name.
7
- 3. Overwrite other things at your desire.
3
+ The JSON Schema-based library for rendering forms and form values.
8
4
 
9
5
  ## Install
10
6
 
@@ -13,3 +9,36 @@ npm install --save-dev @gravity-ui/dynamic-forms
13
9
  ```
14
10
 
15
11
  ## Usage
12
+
13
+ ```jsx
14
+ import {DynamicField, Spec, dynamicConfig} from '@gravity-ui/dynamic-forms';
15
+
16
+ // To embed in a final-form
17
+ <DynamicField name={name} spec={spec} config={config} />;
18
+
19
+ import {DynamicView, dynamicViewConfig} from '@gravity-ui/dynamic-forms';
20
+
21
+ // To get an overview of the values
22
+ <DynamicView value={value} spec={spec} config={dynamicViewConfig} />;
23
+ ```
24
+
25
+ ### I18N
26
+
27
+ Certain components include text tokens (words and phrases) that are available in two languages: `en` (the default) and `ru`. To set the language, use the `configure` function:
28
+
29
+ ```js
30
+ // index.js
31
+
32
+ import {configure, Lang} from '@gravity-ui/dynamic-forms';
33
+
34
+ configure({lang: Lang.Ru});
35
+ ```
36
+
37
+ ## Development
38
+
39
+ To start the development server with storybook execute the following command:
40
+
41
+ ```shell
42
+ npm ci
43
+ npm run dev
44
+ ```
@@ -5,9 +5,8 @@ const tslib_1 = require("tslib");
5
5
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
6
6
  const helpers_1 = require("../../helpers");
7
7
  const hooks_1 = require("./hooks");
8
- const useSearch_1 = require("./hooks/useSearch");
9
8
  const Controller = ({ spec, name, initialValue, parentOnChange, parentOnUnmount, }) => {
10
- const { tools } = (0, hooks_1.useDynamicFormsCtx)();
9
+ const { tools, __mirror } = (0, hooks_1.useDynamicFormsCtx)();
11
10
  const { inputEntity, Layout } = (0, hooks_1.useComponents)(spec);
12
11
  const render = (0, hooks_1.useRender)({ name, spec, inputEntity, Layout });
13
12
  const validate = (0, hooks_1.useValidate)(spec);
@@ -20,7 +19,14 @@ const Controller = ({ spec, name, initialValue, parentOnChange, parentOnUnmount,
20
19
  parentOnChange,
21
20
  parentOnUnmount,
22
21
  });
23
- const withSearch = (0, useSearch_1.useSearch)(spec, renderProps.input.value, name);
22
+ const withSearch = (0, hooks_1.useSearch)(spec, renderProps.input.value, name);
23
+ (0, hooks_1.useControllerMirror)(name, {
24
+ useComponents: { inputEntity, Layout },
25
+ useRender: render,
26
+ useValidate: validate,
27
+ useField: renderProps,
28
+ useSearch: withSearch,
29
+ }, __mirror);
24
30
  if (lodash_1.default.isString(name) && (0, helpers_1.isCorrectSpec)(spec)) {
25
31
  return withSearch(render(renderProps));
26
32
  }
@@ -9,16 +9,18 @@ const helpers_1 = require("../../helpers");
9
9
  const Controller_1 = require("./Controller");
10
10
  const hooks_1 = require("./hooks");
11
11
  const utils_1 = require("./utils");
12
- const DynamicField = ({ name, spec, config, Monaco, search }) => {
12
+ const DynamicField = ({ name, spec, config, Monaco, search, __mirror, }) => {
13
13
  const DynamicFormsCtx = (0, hooks_1.useCreateContext)();
14
14
  const SearchContext = (0, hooks_1.useCreateSearchContext)();
15
- const { tools, watcher } = (0, hooks_1.useStore)(name);
16
- const { setField, removeField, isHiddenField } = (0, hooks_1.useSearchStore)(name);
15
+ const { tools, store } = (0, hooks_1.useStore)(name);
16
+ const watcher = (0, hooks_1.useIntegrationFF)(store);
17
+ const { store: searchStore, setField, removeField, isHiddenField } = (0, hooks_1.useSearchStore)();
17
18
  const context = react_1.default.useMemo(() => ({
18
19
  config,
19
20
  Monaco: (0, react_is_1.isValidElementType)(Monaco) ? Monaco : undefined,
20
21
  tools,
21
- }), [tools, config, Monaco]);
22
+ __mirror,
23
+ }), [tools, config, Monaco, __mirror]);
22
24
  const searchContext = react_1.default.useMemo(() => ({
23
25
  setField,
24
26
  removeField,
@@ -26,6 +28,11 @@ const DynamicField = ({ name, spec, config, Monaco, search }) => {
26
28
  searchFunction: lodash_1.default.isFunction(search) ? search : (0, utils_1.getDefaultSearchFunction)(search),
27
29
  }), [isHiddenField, removeField, search, setField]);
28
30
  const correctParams = react_1.default.useMemo(() => lodash_1.default.isString(name) && (0, helpers_1.isCorrectSpec)(spec) && (0, utils_1.isCorrectConfig)(config), [name, spec, config]);
31
+ (0, hooks_1.useDynamicFieldMirror)({
32
+ useStore: { tools, store },
33
+ useIntegrationFF: watcher,
34
+ useSearchStore: { store: searchStore, setField, removeField, isHiddenField },
35
+ }, __mirror);
29
36
  if (correctParams) {
30
37
  return (react_1.default.createElement(DynamicFormsCtx.Provider, { value: context },
31
38
  react_1.default.createElement(SearchContext.Provider, { value: searchContext },
@@ -2,9 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./useComponents"), exports);
5
+ tslib_1.__exportStar(require("./useControllerMirror"), exports);
5
6
  tslib_1.__exportStar(require("./useCreateContext"), exports);
7
+ tslib_1.__exportStar(require("./useDynamicFieldMirror"), exports);
6
8
  tslib_1.__exportStar(require("./useDynamicFormsCtx"), exports);
7
9
  tslib_1.__exportStar(require("./useField"), exports);
10
+ tslib_1.__exportStar(require("./useIntegrationFF"), exports);
8
11
  tslib_1.__exportStar(require("./useRender"), exports);
9
12
  tslib_1.__exportStar(require("./useStore"), exports);
10
13
  tslib_1.__exportStar(require("./useValidate"), exports);
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useControllerMirror = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const useControllerMirror = (name, params, __mirror) => {
7
+ if (__mirror === null || __mirror === void 0 ? void 0 : __mirror.controller) {
8
+ __mirror.controller[name] = params;
9
+ }
10
+ react_1.default.useEffect(() => {
11
+ return () => {
12
+ var _a;
13
+ if ((_a = __mirror === null || __mirror === void 0 ? void 0 : __mirror.controller) === null || _a === void 0 ? void 0 : _a[name]) {
14
+ delete __mirror.controller[name];
15
+ }
16
+ };
17
+ }, []);
18
+ };
19
+ exports.useControllerMirror = useControllerMirror;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useDynamicFieldMirror = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const useDynamicFieldMirror = (params, __mirror) => {
7
+ if (__mirror === null || __mirror === void 0 ? void 0 : __mirror.field) {
8
+ __mirror.field.useStore = params.useStore;
9
+ __mirror.field.useIntegrationFF = params.useIntegrationFF;
10
+ __mirror.field.useSearchStore = params.useSearchStore;
11
+ }
12
+ react_1.default.useEffect(() => {
13
+ return () => {
14
+ if (__mirror === null || __mirror === void 0 ? void 0 : __mirror.field) {
15
+ delete __mirror.field.useStore;
16
+ delete __mirror.field.useIntegrationFF;
17
+ delete __mirror.field.useSearchStore;
18
+ }
19
+ };
20
+ }, []);
21
+ };
22
+ exports.useDynamicFieldMirror = useDynamicFieldMirror;
@@ -126,7 +126,7 @@ const useField = ({ name, spec, initialValue, validate: propsValidate, tools, pa
126
126
  onDrop,
127
127
  ]);
128
128
  react_1.default.useEffect(() => {
129
- if (!firstRenderRef.current || !lodash_1.default.isEqual(initialValue, state.value)) {
129
+ if (!firstRenderRef.current || !lodash_1.default.isEqual(initialValue, state.value) || state.error) {
130
130
  (parentOnChange ? parentOnChange : tools.onChange)(name, state.value, Object.assign(Object.assign({}, state.childErrors), { [name]: state.error }));
131
131
  }
132
132
  }, [state.value]);
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useIntegrationFF = 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 debounce_1 = tslib_1.__importDefault(require("lodash/debounce"));
8
+ const react_final_form_1 = require("react-final-form");
9
+ const utils_1 = require("../utils");
10
+ const useIntegrationFF = (store) => {
11
+ const form = (0, react_final_form_1.useForm)();
12
+ const watcher = react_1.default.useMemo(() => {
13
+ const props = {
14
+ name: store.name,
15
+ render: () => null,
16
+ subscription: {},
17
+ validate: () => {
18
+ const asyncErrors = [];
19
+ let error;
20
+ lodash_1.default.values(store.errors).forEach((err) => {
21
+ if (err) {
22
+ if (lodash_1.default.isFunction(err === null || err === void 0 ? void 0 : err.then)) {
23
+ asyncErrors.push(err);
24
+ }
25
+ else {
26
+ error = err;
27
+ }
28
+ }
29
+ });
30
+ if (asyncErrors.length) {
31
+ return Promise.all(asyncErrors).then((r) => r[0]);
32
+ }
33
+ return error;
34
+ },
35
+ };
36
+ return react_1.default.createElement(react_final_form_1.Field, Object.assign({}, props));
37
+ }, [store.name, store.errors]);
38
+ const change = react_1.default.useCallback((0, debounce_1.default)((value) => {
39
+ form.change(store.name, lodash_1.default.get((0, utils_1.transformArrOut)(value), store.name));
40
+ }, 100), [form.change, store.name]);
41
+ react_1.default.useEffect(() => {
42
+ change(store.values);
43
+ }, [store.values]);
44
+ return watcher;
45
+ };
46
+ exports.useIntegrationFF = useIntegrationFF;
@@ -5,8 +5,8 @@ const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
7
7
  const __1 = require("../");
8
- const useSearchStore = (name) => {
9
- const [store, setStore] = react_1.default.useState({ [name]: false });
8
+ const useSearchStore = () => {
9
+ const [store, setStore] = react_1.default.useState({});
10
10
  const isHiddenField = react_1.default.useCallback((name) => {
11
11
  const selfFlag = store[name];
12
12
  if (selfFlag === false) {
@@ -24,6 +24,9 @@ const useSearchStore = (name) => {
24
24
  return false;
25
25
  }
26
26
  }
27
+ if (lodash_1.default.isUndefined(selfFlag)) {
28
+ return false;
29
+ }
27
30
  return true;
28
31
  }, [store]);
29
32
  return {
@@ -21,44 +21,12 @@ const useStore = (name) => {
21
21
  };
22
22
  });
23
23
  const submitFailed = form.getState().submitFailed;
24
- const watcher = react_1.default.useMemo(() => {
25
- const props = {
26
- name: store.name,
27
- render: () => null,
28
- subscription: {},
29
- validate: () => {
30
- const asyncErrors = [];
31
- let error;
32
- lodash_1.default.values(store.errors).forEach((err) => {
33
- if (err) {
34
- if (lodash_1.default.isFunction(err === null || err === void 0 ? void 0 : err.then)) {
35
- asyncErrors.push(err);
36
- }
37
- else {
38
- error = err;
39
- }
40
- }
41
- });
42
- if (asyncErrors.length) {
43
- return Promise.all(asyncErrors).then((r) => r[0]);
44
- }
45
- return error;
46
- },
47
- };
48
- return react_1.default.createElement(react_final_form_1.Field, Object.assign({}, props));
49
- }, [store.name, store.errors]);
50
24
  const tools = react_1.default.useMemo(() => ({
51
25
  initialValue: store.initialValue,
52
- onChange: (name, value, errors) => setStore((store) => (Object.assign(Object.assign({}, store), { values: lodash_1.default.set(Object.assign({}, store.values), name, value), errors: errors || {} }))),
53
- onUnmount: (name) => setStore((store) => (Object.assign(Object.assign({}, store), { errors: lodash_1.default.omit(store.errors, Object.keys(store.errors).filter((key) => key.startsWith(name))) }))),
26
+ onChange: (name, value, errors) => setStore((store) => (Object.assign(Object.assign({}, store), { values: lodash_1.default.set(Object.assign({}, store.values), name, lodash_1.default.clone(value)), errors: errors || {} }))),
27
+ onUnmount: (name) => setStore((store) => (Object.assign(Object.assign({}, store), { values: lodash_1.default.omit(store.values, name), errors: lodash_1.default.omit(store.errors, Object.keys(store.errors).filter((key) => key.startsWith(name))) }))),
54
28
  submitFailed,
55
29
  }), [store.initialValue, setStore, submitFailed]);
56
- const change = react_1.default.useCallback(lodash_1.default.debounce((value) => {
57
- form.change(store.name, lodash_1.default.get((0, utils_1.transformArrOut)(value), store.name));
58
- }, 100), [form.change, store.name]);
59
- react_1.default.useEffect(() => {
60
- change(store.values);
61
- }, [store.values]);
62
30
  react_1.default.useEffect(() => {
63
31
  if (!firstRenderRef.current) {
64
32
  const initialValue = (0, utils_1.transformArrIn)({
@@ -75,6 +43,6 @@ const useStore = (name) => {
75
43
  react_1.default.useEffect(() => {
76
44
  firstRenderRef.current = false;
77
45
  }, []);
78
- return { tools, watcher };
46
+ return { tools, store };
79
47
  };
80
48
  exports.useStore = useStore;
@@ -8,8 +8,10 @@ tslib_1.__exportStar(require("./context"), exports);
8
8
  tslib_1.__exportStar(require("./field"), exports);
9
9
  tslib_1.__exportStar(require("./input"), exports);
10
10
  tslib_1.__exportStar(require("./layout"), exports);
11
+ tslib_1.__exportStar(require("./mirror"), exports);
11
12
  tslib_1.__exportStar(require("./number"), exports);
12
13
  tslib_1.__exportStar(require("./object"), exports);
14
+ tslib_1.__exportStar(require("./store"), exports);
13
15
  tslib_1.__exportStar(require("./string"), exports);
14
16
  tslib_1.__exportStar(require("./validators"), exports);
15
17
  tslib_1.__exportStar(require("./value"), exports);
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -5,8 +5,8 @@ const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const hooks_1 = require("./hooks");
7
7
  const ViewController = ({ spec, name, }) => {
8
- const { value, Link } = (0, hooks_1.useDynamicFormsCtx)();
9
- const { viewEntity, Layout } = (0, hooks_1.useComponents)(spec);
8
+ const { config, value, Link } = (0, hooks_1.useDynamicFormsCtx)();
9
+ const { viewEntity, Layout } = (0, hooks_1.useComponents)(spec, config);
10
10
  const render = (0, hooks_1.useRender)({ name, value, spec, viewEntity, Layout, Link });
11
11
  return react_1.default.createElement(react_1.default.Fragment, null, render);
12
12
  };
@@ -7,10 +7,8 @@ const lodash_1 = tslib_1.__importDefault(require("lodash"));
7
7
  const react_is_1 = require("react-is");
8
8
  const helpers_1 = require("../../../helpers");
9
9
  const helpers_2 = require("../helpers");
10
- const _1 = require("./");
11
- const useComponents = (spec) => {
10
+ const useComponents = (spec, config) => {
12
11
  var _a, _b;
13
- const { config } = (0, _1.useDynamicFormsCtx)();
14
12
  const { views, layouts } = react_1.default.useMemo(() => {
15
13
  if ((0, helpers_2.isCorrectViewConfig)(config) && (0, helpers_1.isCorrectSpec)(spec)) {
16
14
  return config[spec.type];
@@ -0,0 +1,20 @@
1
+ .df-file-input {
2
+ display: flex;
3
+ }
4
+ .df-file-input__input {
5
+ opacity: 0;
6
+ position: absolute;
7
+ clip: rect(0 0 0 0);
8
+ width: 1px;
9
+ height: 1px;
10
+ margin: -1px;
11
+ }
12
+ .df-file-input__file-name {
13
+ display: block;
14
+ margin: auto 10px;
15
+ max-width: 160px;
16
+ text-overflow: ellipsis;
17
+ overflow: hidden;
18
+ white-space: nowrap;
19
+ color: var(--yc-color-text-secondary);
20
+ }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FileInput = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const icons_1 = require("@gravity-ui/icons");
7
+ const uikit_1 = require("@gravity-ui/uikit");
8
+ const i18n_1 = tslib_1.__importDefault(require("../../../../kit/i18n"));
9
+ const utils_1 = require("../../../utils");
10
+ const utils_2 = require("./utils");
11
+ const b = (0, utils_1.block)('file-input');
12
+ const FileInput = ({ input, spec }) => {
13
+ var _a, _b;
14
+ const { value, onChange } = input;
15
+ const inputRef = react_1.default.useRef(null);
16
+ const [fileName, setFileName] = react_1.default.useState('');
17
+ const handleClick = react_1.default.useCallback(() => {
18
+ var _a;
19
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.click();
20
+ }, []);
21
+ const handleDownload = react_1.default.useCallback(async (file) => { var _a; return await (0, utils_2.readFile)(file, (_a = spec.viewSpec.fileInput) === null || _a === void 0 ? void 0 : _a.readAsMethod); }, [(_a = spec.viewSpec.fileInput) === null || _a === void 0 ? void 0 : _a.readAsMethod]);
22
+ const handleReset = react_1.default.useCallback(() => {
23
+ setFileName('');
24
+ onChange('');
25
+ }, [onChange]);
26
+ const handleInputChange = react_1.default.useCallback(async (event) => {
27
+ const file = event.target.files;
28
+ if (file && file.length > 0) {
29
+ setFileName(file[0].name);
30
+ const data = (await handleDownload(file[0]));
31
+ onChange(data);
32
+ }
33
+ }, [handleDownload, onChange]);
34
+ const fileNameContent = react_1.default.useMemo(() => {
35
+ if (value) {
36
+ if (fileName) {
37
+ return react_1.default.createElement(react_1.default.Fragment, null, fileName);
38
+ }
39
+ return (react_1.default.createElement(uikit_1.Label, { size: "m", theme: "info" }, (0, i18n_1.default)('label-data_loaded')));
40
+ }
41
+ return null;
42
+ }, [fileName, value]);
43
+ return (react_1.default.createElement("div", { className: b() },
44
+ react_1.default.createElement(uikit_1.Button, { disabled: spec.viewSpec.disabled, onClick: handleClick }, (0, i18n_1.default)('button-upload_file')),
45
+ react_1.default.createElement("input", { type: "file", ref: inputRef, autoComplete: "off", disabled: spec.viewSpec.disabled, onChange: handleInputChange, className: b('input'), tabIndex: -1, accept: (_b = spec.viewSpec.fileInput) === null || _b === void 0 ? void 0 : _b.accept }),
46
+ react_1.default.createElement("span", { className: b('file-name') }, fileNameContent),
47
+ value ? (react_1.default.createElement(uikit_1.Button, { view: "flat", onClick: handleReset, disabled: spec.viewSpec.disabled },
48
+ react_1.default.createElement(uikit_1.Icon, { data: icons_1.Xmark, size: 16 }))) : null));
49
+ };
50
+ exports.FileInput = FileInput;
@@ -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("./FileInput"), exports);
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readFile = void 0;
4
+ function readFile(file, readAsMethod = 'readAsBinaryString') {
5
+ return new Promise((resolve, reject) => {
6
+ const reader = new FileReader();
7
+ if (typeof reader[readAsMethod] !== 'function') {
8
+ reject(new Error(`Unknown parameter: ${readAsMethod}`));
9
+ return;
10
+ }
11
+ reader.addEventListener('load', () => resolve(reader.result));
12
+ reader.addEventListener('error', () => reject(reader.error));
13
+ reader[readAsMethod](file);
14
+ });
15
+ }
16
+ exports.readFile = readFile;
@@ -68,9 +68,10 @@ const TableArrayInput = ({ spec, name, arrayInput, input }) => {
68
68
  return [idxColumn, ...columns, removeColumn];
69
69
  }, [name, spec, onItemRemove, parentOnChange, parentOnUnmount, input.value]);
70
70
  const getRowClassNames = react_1.default.useCallback(({ key }) => {
71
- const searchResult = isHiddenField(`${name}.<${key}>`);
71
+ var _a;
72
+ const searchResult = (_a = spec.viewSpec.table) === null || _a === void 0 ? void 0 : _a.every(({ property }) => isHiddenField(`${name}.<${key}>.${property}`));
72
73
  return [b('row', { hidden: searchResult })];
73
- }, [isHiddenField, name]);
74
+ }, [isHiddenField, name, spec.viewSpec.table]);
74
75
  if (!columns) {
75
76
  return null;
76
77
  }
@@ -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);
@@ -4,6 +4,7 @@ const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./ArrayBase"), exports);
5
5
  tslib_1.__exportStar(require("./CardOneOf"), exports);
6
6
  tslib_1.__exportStar(require("./Checkbox"), exports);
7
+ tslib_1.__exportStar(require("./FileInput"), exports);
7
8
  tslib_1.__exportStar(require("./MultiSelect"), exports);
8
9
  tslib_1.__exportStar(require("./ObjectBase"), exports);
9
10
  tslib_1.__exportStar(require("./OneOf"), exports);
@@ -14,5 +15,6 @@ tslib_1.__exportStar(require("./TableArrayInput"), exports);
14
15
  tslib_1.__exportStar(require("./Text"), exports);
15
16
  tslib_1.__exportStar(require("./TextArea"), exports);
16
17
  tslib_1.__exportStar(require("./TextContent"), exports);
18
+ tslib_1.__exportStar(require("./TextLink"), exports);
17
19
  tslib_1.__exportStar(require("./NumberWithScale"), exports);
18
20
  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,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FileInputView = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const i18n_1 = tslib_1.__importDefault(require("../../../../kit/i18n"));
7
+ const components_1 = require("../../../components");
8
+ const FileInputView = ({ value, spec }) => {
9
+ var _a;
10
+ return (react_1.default.createElement(components_1.LongValue, { value: ((_a = spec.viewSpec.fileInput) === null || _a === void 0 ? void 0 : _a.ignoreText) ? (0, i18n_1.default)('label-data_loaded') : value }));
11
+ };
12
+ exports.FileInputView = FileInputView;
@@ -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("./FileInputView"), exports);