@gravity-ui/dynamic-forms 4.0.0 → 4.1.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 (105) hide show
  1. package/build/cjs/lib/core/components/Form/Controller/Controller.js +2 -2
  2. package/build/cjs/lib/core/components/Form/Controller/utils.js +45 -34
  3. package/build/cjs/lib/core/components/Form/DynamicField.js +6 -4
  4. package/build/cjs/lib/core/components/Form/hooks/useCreateContext.js +2 -2
  5. package/build/cjs/lib/core/components/Form/hooks/useCreateSearchContext.js +2 -2
  6. package/build/cjs/lib/core/components/Form/hooks/useIntegrationFF.js +6 -4
  7. package/build/cjs/lib/core/components/Form/hooks/useMutators.js +11 -7
  8. package/build/cjs/lib/core/components/Form/hooks/useSearchStore.js +4 -3
  9. package/build/cjs/lib/core/components/Form/hooks/useStore.js +15 -11
  10. package/build/cjs/lib/core/components/Form/utils/common.js +14 -11
  11. package/build/cjs/lib/core/components/View/helpers.js +5 -5
  12. package/build/cjs/lib/core/components/View/hooks/useComponents.js +2 -2
  13. package/build/cjs/lib/core/components/View/hooks/useCreateContext.js +2 -2
  14. package/build/cjs/lib/core/components/View/hooks/useRender.js +4 -3
  15. package/build/cjs/lib/core/helpers.js +5 -4
  16. package/build/cjs/lib/kit/components/AccordeonCard/AccordeonCard.js +2 -2
  17. package/build/cjs/lib/kit/components/Card/Card.js +2 -2
  18. package/build/cjs/lib/kit/components/GenerateRandomValueButton/GenerateRandomValueButton.js +2 -2
  19. package/build/cjs/lib/kit/components/Inputs/ArrayBase/ArrayBase.js +2 -2
  20. package/build/cjs/lib/kit/components/Inputs/CardOneOf/CardOneOf.js +2 -2
  21. package/build/cjs/lib/kit/components/Inputs/MultiOneOf/MultiOneOf.js +4 -3
  22. package/build/cjs/lib/kit/components/Inputs/ObjectBase/ObjectBase.css +6 -0
  23. package/build/cjs/lib/kit/components/Inputs/ObjectBase/ObjectBase.js +11 -5
  24. package/build/cjs/lib/kit/components/Inputs/ObjectValueInput/ObjectValueInput.js +7 -6
  25. package/build/cjs/lib/kit/components/Inputs/OneOf/OneOf.js +2 -2
  26. package/build/cjs/lib/kit/components/Inputs/Secret/Secret.js +4 -3
  27. package/build/cjs/lib/kit/components/Inputs/TableArrayInput/TableArrayInput.js +4 -3
  28. package/build/cjs/lib/kit/components/Inputs/Text/Text.js +2 -2
  29. package/build/cjs/lib/kit/components/Inputs/TextContent/TextContent.js +2 -2
  30. package/build/cjs/lib/kit/components/Inputs/TextLink/TextLink.js +4 -3
  31. package/build/cjs/lib/kit/components/LazyLoader/LazyLoader.js +2 -2
  32. package/build/cjs/lib/kit/components/ViewLayouts/ViewAccordeon/ViewAccordeon.js +2 -2
  33. package/build/cjs/lib/kit/components/ViewLayouts/ViewAccordeonCard/ViewAccordeonCard.js +2 -2
  34. package/build/cjs/lib/kit/components/ViewLayouts/ViewCardAccordeon.js +2 -2
  35. package/build/cjs/lib/kit/components/Views/ArrayBaseView/ArrayBaseView.js +2 -2
  36. package/build/cjs/lib/kit/components/Views/BaseView/BaseView.js +2 -2
  37. package/build/cjs/lib/kit/components/Views/CardOneOfView.js +2 -2
  38. package/build/cjs/lib/kit/components/Views/MultiOneOfView/MultiOneOfView.js +2 -2
  39. package/build/cjs/lib/kit/components/Views/ObjectBaseView/ObjectBaseView.css +6 -0
  40. package/build/cjs/lib/kit/components/Views/ObjectBaseView/ObjectBaseView.js +16 -9
  41. package/build/cjs/lib/kit/components/Views/ObjectValueInputView/ObjectValueInputView.js +5 -5
  42. package/build/cjs/lib/kit/components/Views/OneOfView/OneOfView.js +17 -6
  43. package/build/cjs/lib/kit/components/Views/TextLinkView/TextLinkView.js +2 -2
  44. package/build/cjs/lib/kit/constants/common.js +2 -1
  45. package/build/cjs/lib/kit/hooks/useOneOf/useOneOf.css +5 -0
  46. package/build/cjs/lib/kit/hooks/useOneOf/useOneOf.js +35 -7
  47. package/build/cjs/lib/kit/utils/common.js +30 -25
  48. package/build/cjs/lib/kit/utils/index.js +1 -0
  49. package/build/cjs/lib/kit/utils/objectKeys.js +7 -0
  50. package/build/cjs/lib/kit/validators/validators.js +9 -7
  51. package/build/esm/lib/core/components/Form/Controller/Controller.js +2 -2
  52. package/build/esm/lib/core/components/Form/Controller/utils.js +45 -34
  53. package/build/esm/lib/core/components/Form/DynamicField.js +6 -4
  54. package/build/esm/lib/core/components/Form/hooks/useCreateContext.js +2 -2
  55. package/build/esm/lib/core/components/Form/hooks/useCreateSearchContext.js +2 -2
  56. package/build/esm/lib/core/components/Form/hooks/useIntegrationFF.js +6 -4
  57. package/build/esm/lib/core/components/Form/hooks/useMutators.js +11 -7
  58. package/build/esm/lib/core/components/Form/hooks/useSearchStore.js +4 -3
  59. package/build/esm/lib/core/components/Form/hooks/useStore.js +15 -11
  60. package/build/esm/lib/core/components/Form/utils/common.js +14 -11
  61. package/build/esm/lib/core/components/View/helpers.js +5 -5
  62. package/build/esm/lib/core/components/View/hooks/useComponents.js +2 -2
  63. package/build/esm/lib/core/components/View/hooks/useCreateContext.js +2 -2
  64. package/build/esm/lib/core/components/View/hooks/useRender.js +4 -3
  65. package/build/esm/lib/core/helpers.js +5 -4
  66. package/build/esm/lib/core/types/specs.d.ts +3 -1
  67. package/build/esm/lib/kit/components/AccordeonCard/AccordeonCard.js +2 -2
  68. package/build/esm/lib/kit/components/Card/Card.js +2 -2
  69. package/build/esm/lib/kit/components/GenerateRandomValueButton/GenerateRandomValueButton.js +2 -2
  70. package/build/esm/lib/kit/components/Inputs/ArrayBase/ArrayBase.js +2 -2
  71. package/build/esm/lib/kit/components/Inputs/CardOneOf/CardOneOf.js +2 -2
  72. package/build/esm/lib/kit/components/Inputs/MultiOneOf/MultiOneOf.js +4 -3
  73. package/build/esm/lib/kit/components/Inputs/ObjectBase/ObjectBase.css +6 -0
  74. package/build/esm/lib/kit/components/Inputs/ObjectBase/ObjectBase.js +12 -6
  75. package/build/esm/lib/kit/components/Inputs/ObjectValueInput/ObjectValueInput.js +5 -4
  76. package/build/esm/lib/kit/components/Inputs/OneOf/OneOf.js +2 -2
  77. package/build/esm/lib/kit/components/Inputs/Secret/Secret.js +4 -3
  78. package/build/esm/lib/kit/components/Inputs/TableArrayInput/TableArrayInput.js +4 -3
  79. package/build/esm/lib/kit/components/Inputs/Text/Text.js +2 -2
  80. package/build/esm/lib/kit/components/Inputs/TextContent/TextContent.js +2 -2
  81. package/build/esm/lib/kit/components/Inputs/TextLink/TextLink.js +4 -3
  82. package/build/esm/lib/kit/components/LazyLoader/LazyLoader.js +2 -2
  83. package/build/esm/lib/kit/components/ViewLayouts/ViewAccordeon/ViewAccordeon.js +2 -2
  84. package/build/esm/lib/kit/components/ViewLayouts/ViewAccordeonCard/ViewAccordeonCard.js +2 -2
  85. package/build/esm/lib/kit/components/ViewLayouts/ViewCardAccordeon.js +2 -2
  86. package/build/esm/lib/kit/components/Views/ArrayBaseView/ArrayBaseView.js +2 -2
  87. package/build/esm/lib/kit/components/Views/BaseView/BaseView.js +2 -2
  88. package/build/esm/lib/kit/components/Views/CardOneOfView.js +2 -2
  89. package/build/esm/lib/kit/components/Views/MultiOneOfView/MultiOneOfView.js +2 -2
  90. package/build/esm/lib/kit/components/Views/ObjectBaseView/ObjectBaseView.css +6 -0
  91. package/build/esm/lib/kit/components/Views/ObjectBaseView/ObjectBaseView.js +16 -9
  92. package/build/esm/lib/kit/components/Views/ObjectValueInputView/ObjectValueInputView.js +3 -3
  93. package/build/esm/lib/kit/components/Views/OneOfView/OneOfView.js +18 -7
  94. package/build/esm/lib/kit/components/Views/TextLinkView/TextLinkView.js +2 -2
  95. package/build/esm/lib/kit/constants/common.d.ts +1 -0
  96. package/build/esm/lib/kit/constants/common.js +1 -0
  97. package/build/esm/lib/kit/hooks/useOneOf/useOneOf.css +5 -0
  98. package/build/esm/lib/kit/hooks/useOneOf/useOneOf.js +37 -9
  99. package/build/esm/lib/kit/utils/common.js +30 -25
  100. package/build/esm/lib/kit/utils/index.d.ts +1 -0
  101. package/build/esm/lib/kit/utils/index.js +1 -0
  102. package/build/esm/lib/kit/utils/objectKeys.d.ts +4 -0
  103. package/build/esm/lib/kit/utils/objectKeys.js +3 -0
  104. package/build/esm/lib/kit/validators/validators.js +9 -7
  105. package/package.json +1 -1
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
- import _ from 'lodash';
2
+ import isBoolean from 'lodash/isBoolean';
3
3
  import { isNotEmptyValue } from '../../../utils';
4
4
  import { AccordeonCard } from '../../AccordeonCard';
5
5
  export const ViewAccordeonCard = ({ value, name, spec, children, }) => {
6
- const [open, setOpen] = React.useState(_.isBoolean(spec.viewSpec.layoutOpen) ? spec.viewSpec.layoutOpen : true);
6
+ const [open, setOpen] = React.useState(isBoolean(spec.viewSpec.layoutOpen) ? spec.viewSpec.layoutOpen : true);
7
7
  if (!isNotEmptyValue(value, spec)) {
8
8
  return null;
9
9
  }
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
- import _ from 'lodash';
2
+ import isBoolean from 'lodash/isBoolean';
3
3
  import { Card } from '../';
4
4
  import { isNotEmptyValue } from '../../utils';
5
5
  export const ViewCardAccordeon = ({ name, value, spec, children, }) => {
6
- const [open, setOpen] = React.useState(_.isBoolean(spec.viewSpec.layoutOpen) ? spec.viewSpec.layoutOpen : true);
6
+ const [open, setOpen] = React.useState(isBoolean(spec.viewSpec.layoutOpen) ? spec.viewSpec.layoutOpen : true);
7
7
  const onToggle = React.useCallback(() => setOpen((f) => !f), [setOpen]);
8
8
  if (!isNotEmptyValue(value, spec)) {
9
9
  return null;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Label } from '@gravity-ui/uikit';
3
- import _ from 'lodash';
3
+ import map from 'lodash/map';
4
4
  import { ViewController, isCorrectSpec } from '../../../../core';
5
5
  import { block } from '../../../utils';
6
6
  import './ArrayBaseView.css';
@@ -17,7 +17,7 @@ export const ArrayBaseView = ({ spec, name, value = [] }) => {
17
17
  : `${idx + 1}` });
18
18
  return itemSpec;
19
19
  }, [spec.items, itemSpecCorrect]);
20
- const items = React.useMemo(() => _.map(value, (__, idx) => {
20
+ const items = React.useMemo(() => map(value, (__, idx) => {
21
21
  const itemSpec = getItemSpec(idx);
22
22
  if (!itemSpec) {
23
23
  return null;
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
- import _ from 'lodash';
2
+ import isString from 'lodash/isString';
3
3
  import { LongValue } from '../../../components';
4
4
  export const BaseView = ({ value, spec, linkValue, }) => {
5
5
  var _a;
6
- if (_.isString(value) && linkValue) {
6
+ if (isString(value) && linkValue) {
7
7
  return React.createElement(React.Fragment, null, linkValue);
8
8
  }
9
9
  return (React.createElement(LongValue, { value: ((_a = spec === null || spec === void 0 ? void 0 : spec.description) === null || _a === void 0 ? void 0 : _a[String(value)]) || String(value) }));
@@ -1,12 +1,12 @@
1
1
  import React from 'react';
2
- import _ from 'lodash';
2
+ import isObjectLike from 'lodash/isObjectLike';
3
3
  import { Card, ViewRow } from '../';
4
4
  import { ViewController } from '../../../core';
5
5
  export const CardOneOfView = (props) => {
6
6
  const { value = {}, spec, name } = props;
7
7
  const [open, setOpen] = React.useState(true);
8
8
  const onToggle = React.useCallback(() => setOpen((f) => !f), [setOpen]);
9
- const specProperties = React.useMemo(() => (_.isObjectLike(spec.properties) ? spec.properties : {}), [spec.properties]);
9
+ const specProperties = React.useMemo(() => (isObjectLike(spec.properties) ? spec.properties : {}), [spec.properties]);
10
10
  const valueKey = React.useMemo(() => Object.keys(value)[0], [value]);
11
11
  const valueName = React.useMemo(() => {
12
12
  var _a, _b;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Popover } from '@gravity-ui/uikit';
3
- import _ from 'lodash';
3
+ import isObjectLike from 'lodash/isObjectLike';
4
4
  import { ViewController } from '../../../../core';
5
5
  import { block } from '../../../utils';
6
6
  import { GroupIndent } from '../../GroupIndent';
@@ -8,7 +8,7 @@ import './MultiOneOfView.css';
8
8
  const b = block('multi-oneof-view');
9
9
  export const MultiOneOfView = (props) => {
10
10
  const { name, value, Layout, spec, withoutIndent } = props;
11
- const specProperties = React.useMemo(() => (_.isObjectLike(spec.properties) ? spec.properties : {}), [spec.properties]);
11
+ const specProperties = React.useMemo(() => (isObjectLike(spec.properties) ? spec.properties : {}), [spec.properties]);
12
12
  const values = React.useMemo(() => Object.keys(value || []), [value]);
13
13
  const items = React.useMemo(() => values.map((value) => {
14
14
  var _a, _b;
@@ -8,4 +8,10 @@
8
8
  }
9
9
  .df-object-base-view__content_inline > div:last-child {
10
10
  margin-right: 0;
11
+ }
12
+ .df-object-base-view__delimiter {
13
+ display: flex;
14
+ margin-right: 8px;
15
+ align-items: center;
16
+ white-space: nowrap;
11
17
  }
@@ -1,20 +1,27 @@
1
1
  import { __rest } from "tslib";
2
2
  import React from 'react';
3
- import _ from 'lodash';
3
+ import isObjectLike from 'lodash/isObjectLike';
4
+ import { Text } from '@gravity-ui/uikit';
4
5
  import { ViewController } from '../../../../core';
5
6
  import { block, filterPropertiesForObjectInline } from '../../../utils';
6
7
  import './ObjectBaseView.css';
7
8
  const b = block('object-base-view');
8
9
  export const ObjectBaseView = (_a) => {
9
10
  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) {
11
+ const content = React.useMemo(() => {
12
+ if (!spec.properties || !isObjectLike(spec.properties)) {
13
+ return null;
14
+ }
15
+ const specProperties = inline
16
+ ? filterPropertiesForObjectInline(spec.properties)
17
+ : spec.properties;
18
+ const delimiter = spec.viewSpec.delimiter;
19
+ const orderProperties = spec.viewSpec.order || Object.keys(specProperties);
20
+ return (React.createElement("div", { className: b('content', { inline }) }, orderProperties.map((property) => specProperties[property] ? (React.createElement(React.Fragment, { key: `${name ? name + '.' : ''}${property}` },
21
+ React.createElement(ViewController, { spec: specProperties[property], name: `${name ? name + '.' : ''}${property}` }),
22
+ delimiter && delimiter[property] ? (React.createElement(Text, { className: b('delimiter') }, delimiter[property])) : null)) : null)));
23
+ }, [inline, name, spec.properties, spec.viewSpec.delimiter, spec.viewSpec.order]);
24
+ if (!Layout || !content) {
18
25
  return content;
19
26
  }
20
27
  return (React.createElement(Layout, Object.assign({ spec: spec, name: name }, restProps), content));
@@ -1,14 +1,14 @@
1
1
  import { __rest } from "tslib";
2
2
  import React from 'react';
3
- import _ from 'lodash';
3
+ import cloneDeep from 'lodash/cloneDeep';
4
4
  import { ViewController } from '../../../../core';
5
- const OBJECT_VALUE_PROPERTY_NAME = 'value';
5
+ import { OBJECT_VALUE_PROPERTY_NAME } from '../../../constants/common';
6
6
  export const ObjectValueInputView = (_a) => {
7
7
  var { spec, name, Layout } = _a, restProps = __rest(_a, ["spec", "name", "Layout"]);
8
8
  const childSpec = React.useMemo(() => {
9
9
  var _a;
10
10
  if ((_a = spec.properties) === null || _a === void 0 ? void 0 : _a[OBJECT_VALUE_PROPERTY_NAME]) {
11
- const childSpec = _.cloneDeep(spec.properties[OBJECT_VALUE_PROPERTY_NAME]);
11
+ const childSpec = cloneDeep(spec.properties[OBJECT_VALUE_PROPERTY_NAME]);
12
12
  childSpec.viewSpec.layout = '';
13
13
  return childSpec;
14
14
  }
@@ -1,20 +1,31 @@
1
1
  import React from 'react';
2
- import _ from 'lodash';
2
+ import isObjectLike from 'lodash/isObjectLike';
3
3
  import { GroupIndent } from '../../';
4
4
  import { ViewController } from '../../../../core';
5
- import { block } from '../../../utils';
5
+ import { block, objectKeys } from '../../../utils';
6
6
  import './OneOfView.css';
7
7
  const b = block('oneof-view');
8
8
  const OneOfViewComponent = (props) => {
9
+ var _a, _b;
9
10
  const { value = {}, spec, Layout, name } = props;
10
- const specProperties = React.useMemo(() => (_.isObjectLike(spec.properties) ? spec.properties : {}), [spec.properties]);
11
+ const specProperties = React.useMemo(() => (isObjectLike(spec.properties) ? spec.properties : {}), [spec.properties]);
12
+ const specBooleanMap = React.useMemo(() => { var _a; return (_a = spec.viewSpec.oneOfParams) === null || _a === void 0 ? void 0 : _a.booleanMap; }, [(_a = spec.viewSpec.oneOfParams) === null || _a === void 0 ? void 0 : _a.booleanMap]);
11
13
  const valueKey = React.useMemo(() => Object.keys(value)[0], [value]);
12
14
  const valueName = React.useMemo(() => {
13
- var _a, _b;
14
- return (((_a = spec.description) === null || _a === void 0 ? void 0 : _a[valueKey]) ||
15
- ((_b = specProperties[valueKey]) === null || _b === void 0 ? void 0 : _b.viewSpec.layoutTitle) ||
15
+ var _a, _b, _c;
16
+ if (((_a = spec.viewSpec.oneOfParams) === null || _a === void 0 ? void 0 : _a.toggler) === 'checkbox' && specBooleanMap) {
17
+ return objectKeys(specBooleanMap).find((key) => specBooleanMap[key] === valueKey);
18
+ }
19
+ return (((_b = spec.description) === null || _b === void 0 ? void 0 : _b[valueKey]) ||
20
+ ((_c = specProperties[valueKey]) === null || _c === void 0 ? void 0 : _c.viewSpec.layoutTitle) ||
16
21
  valueKey);
17
- }, [valueKey, spec.description, specProperties]);
22
+ }, [
23
+ valueKey,
24
+ spec.description,
25
+ specProperties,
26
+ (_b = spec.viewSpec.oneOfParams) === null || _b === void 0 ? void 0 : _b.toggler,
27
+ specBooleanMap,
28
+ ]);
18
29
  const wrappedValue = React.useMemo(() => {
19
30
  if (Layout) {
20
31
  return (React.createElement(Layout, Object.assign({}, props, { value: valueName }),
@@ -1,6 +1,6 @@
1
1
  import { __rest } from "tslib";
2
2
  import React from 'react';
3
- import _ from 'lodash';
3
+ import cloneDeep from 'lodash/cloneDeep';
4
4
  import { ViewController, isStringSpec } from '../../../../core';
5
5
  const TEXT_LINK_PROPERTY_NAME = 'text';
6
6
  export const TextLinkView = (_a) => {
@@ -9,7 +9,7 @@ export const TextLinkView = (_a) => {
9
9
  var _a;
10
10
  if (((_a = spec.properties) === null || _a === void 0 ? void 0 : _a[TEXT_LINK_PROPERTY_NAME]) &&
11
11
  isStringSpec(spec.properties[TEXT_LINK_PROPERTY_NAME])) {
12
- const childSpec = _.cloneDeep(spec.properties[TEXT_LINK_PROPERTY_NAME]);
12
+ const childSpec = cloneDeep(spec.properties[TEXT_LINK_PROPERTY_NAME]);
13
13
  childSpec.viewSpec.layout = '';
14
14
  childSpec.viewSpec.link = value === null || value === void 0 ? void 0 : value.link;
15
15
  return childSpec;
@@ -1,3 +1,4 @@
1
1
  import type { PopoverProps } from '@gravity-ui/uikit';
2
2
  export declare const COMMON_POPOVER_PLACEMENT: PopoverProps['placement'];
3
3
  export declare const COMMON_TITLE_MAX_WIDTH = 533;
4
+ export declare const OBJECT_VALUE_PROPERTY_NAME = "value";
@@ -1,2 +1,3 @@
1
1
  export const COMMON_POPOVER_PLACEMENT = ['bottom', 'top'];
2
2
  export const COMMON_TITLE_MAX_WIDTH = 533;
3
+ export const OBJECT_VALUE_PROPERTY_NAME = 'value';
@@ -11,4 +11,9 @@
11
11
  }
12
12
  .df-use-oneof__card > :first-child {
13
13
  margin-right: 8px;
14
+ }
15
+ .df-use-oneof__checkbox {
16
+ height: 28px;
17
+ display: flex;
18
+ align-items: center;
14
19
  }
@@ -1,18 +1,20 @@
1
1
  import React from 'react';
2
- import { RadioButton, Select } from '@gravity-ui/uikit';
3
- import _ from 'lodash';
2
+ import { Checkbox, RadioButton, Select } from '@gravity-ui/uikit';
3
+ import isObjectLike from 'lodash/isObjectLike';
4
+ import some from 'lodash/some';
4
5
  import { TogglerCard } from '../../components';
5
- import { block } from '../../utils';
6
+ import { block, objectKeys } from '../../utils';
6
7
  import './useOneOf.css';
7
8
  const b = block('use-oneof');
8
9
  const MAX_TAB_TITLE_LENGTH = 20;
9
10
  export const useOneOf = ({ props, onTogglerChange }) => {
10
- var _a;
11
+ var _a, _b;
11
12
  const { name, input, spec, Layout } = props;
12
- const specProperties = React.useMemo(() => (_.isObjectLike(spec.properties) ? spec.properties : {}), [spec.properties]);
13
+ const specProperties = React.useMemo(() => (isObjectLike(spec.properties) ? spec.properties : {}), [spec.properties]);
14
+ const specBooleanMap = React.useMemo(() => { var _a; return (_a = spec.viewSpec.oneOfParams) === null || _a === void 0 ? void 0 : _a.booleanMap; }, [(_a = spec.viewSpec.oneOfParams) === null || _a === void 0 ? void 0 : _a.booleanMap]);
13
15
  const [oneOfValue, setOneOfValue] = React.useState(() => {
14
16
  let valueKeys;
15
- if (_.isObjectLike(input.value)) {
17
+ if (isObjectLike(input.value)) {
16
18
  const keys = Object.keys(input.value);
17
19
  if (keys.length) {
18
20
  valueKeys = keys;
@@ -27,6 +29,20 @@ export const useOneOf = ({ props, onTogglerChange }) => {
27
29
  onTogglerChange === null || onTogglerChange === void 0 ? void 0 : onTogglerChange(newValue);
28
30
  }
29
31
  }, [setOneOfValue, input.onChange, oneOfValue]);
32
+ const onCheckboxChange = React.useCallback((checked) => {
33
+ if (specBooleanMap) {
34
+ const value = String(checked);
35
+ const newValue = specBooleanMap[value];
36
+ onOneOfChange([newValue]);
37
+ }
38
+ }, [onOneOfChange, specBooleanMap]);
39
+ const checkboxValue = React.useMemo(() => {
40
+ if (specBooleanMap) {
41
+ const keyBooleanMap = objectKeys(specBooleanMap).find((key) => specBooleanMap[key] === oneOfValue);
42
+ return keyBooleanMap === 'true';
43
+ }
44
+ return undefined;
45
+ }, [oneOfValue, specBooleanMap]);
30
46
  const options = React.useMemo(() => (spec.viewSpec.order || Object.keys(specProperties)).map((value) => {
31
47
  var _a, _b;
32
48
  const title = ((_a = spec.description) === null || _a === void 0 ? void 0 : _a[value]) ||
@@ -40,18 +56,23 @@ export const useOneOf = ({ props, onTogglerChange }) => {
40
56
  };
41
57
  }), [spec.description, spec.viewSpec.order, specProperties]);
42
58
  const togglerType = React.useMemo(() => {
43
- var _a, _b, _c;
59
+ var _a, _b, _c, _d;
44
60
  if (((_a = spec.viewSpec.oneOfParams) === null || _a === void 0 ? void 0 : _a.toggler) === 'card' && options.length < 3) {
45
61
  return 'card';
46
62
  }
47
63
  if (((_b = spec.viewSpec.oneOfParams) === null || _b === void 0 ? void 0 : _b.toggler) !== 'radio' &&
48
64
  (((_c = spec.viewSpec.oneOfParams) === null || _c === void 0 ? void 0 : _c.toggler) === 'select' ||
49
65
  options.length > 3 ||
50
- _.some(options, ({ title }) => title.length > MAX_TAB_TITLE_LENGTH))) {
66
+ some(options, ({ title }) => title.length > MAX_TAB_TITLE_LENGTH))) {
51
67
  return 'select';
52
68
  }
69
+ if (((_d = spec.viewSpec.oneOfParams) === null || _d === void 0 ? void 0 : _d.toggler) === 'checkbox' &&
70
+ options.length === 2 &&
71
+ specBooleanMap) {
72
+ return 'checkbox';
73
+ }
53
74
  return 'radio';
54
- }, [options, (_a = spec.viewSpec.oneOfParams) === null || _a === void 0 ? void 0 : _a.toggler]);
75
+ }, [options, (_b = spec.viewSpec.oneOfParams) === null || _b === void 0 ? void 0 : _b.toggler, specBooleanMap]);
55
76
  const togglerInput = React.useMemo(() => {
56
77
  if (togglerType === 'card') {
57
78
  return (React.createElement("div", { className: b('card') }, options.map(({ value }) => {
@@ -65,15 +86,22 @@ export const useOneOf = ({ props, onTogglerChange }) => {
65
86
  if (togglerType === 'select') {
66
87
  return (React.createElement(Select, { width: "max", value: [oneOfValue], onUpdate: onOneOfChange, options: options, disabled: spec.viewSpec.disabled, filterable: options.length > 7, qa: name }));
67
88
  }
89
+ if (togglerType === 'checkbox') {
90
+ return (React.createElement("div", { className: b('checkbox') },
91
+ React.createElement(Checkbox, { checked: checkboxValue, onUpdate: onCheckboxChange, disabled: spec.viewSpec.disabled, qa: name })));
92
+ }
68
93
  return (React.createElement(RadioButton, { value: oneOfValue, onChange: (event) => onOneOfChange([event.target.value]), disabled: spec.viewSpec.disabled, qa: name }, options.map((option) => (React.createElement(RadioButton.Option, { key: option.value, value: option.value }, option.title)))));
69
94
  }, [
70
95
  togglerType,
71
96
  oneOfValue,
72
97
  spec.viewSpec.disabled,
98
+ spec.description,
73
99
  name,
74
100
  options,
75
101
  onOneOfChange,
76
102
  specProperties,
103
+ onCheckboxChange,
104
+ checkboxValue,
77
105
  ]);
78
106
  const toggler = React.useMemo(() => {
79
107
  if (Layout) {
@@ -1,13 +1,18 @@
1
- import _ from 'lodash';
1
+ import cloneDeep from 'lodash/cloneDeep';
2
+ import isArray from 'lodash/isArray';
3
+ import isNil from 'lodash/isNil';
4
+ import isObject from 'lodash/isObject';
5
+ import isObjectLike from 'lodash/isObjectLike';
6
+ import isString from 'lodash/isString';
2
7
  import { SpecTypes, isArraySpec, isObjectSpec, isStringSpec, } from '../../core';
3
8
  import { isFloat } from '../validators/helpers';
4
9
  import { divide } from './bigIntMath';
5
10
  export const isNotEmptyValue = (value, spec) => {
6
11
  var _a;
7
- if (_.isNil(value)) {
12
+ if (isNil(value)) {
8
13
  return false;
9
14
  }
10
- if (_.isString(value)) {
15
+ if (isString(value)) {
11
16
  if (!value) {
12
17
  return false;
13
18
  }
@@ -15,7 +20,7 @@ export const isNotEmptyValue = (value, spec) => {
15
20
  return false;
16
21
  }
17
22
  }
18
- if (_.isObject(value) && isObjectSpec(spec)) {
23
+ if (isObject(value) && isObjectSpec(spec)) {
19
24
  const keys = Object.keys(value);
20
25
  // the only case when an empty object is considered a non-empty value is when it is a stub for oneof
21
26
  if (!keys.filter((key) => { var _a; return isNotEmptyValue(value[key], (_a = spec.properties) === null || _a === void 0 ? void 0 : _a[key]); }).length &&
@@ -23,7 +28,7 @@ export const isNotEmptyValue = (value, spec) => {
23
28
  return false;
24
29
  }
25
30
  }
26
- if (_.isArray(value) &&
31
+ if (isArray(value) &&
27
32
  isArraySpec(spec) &&
28
33
  !value.filter((item) => isNotEmptyValue(item, spec.items)).length) {
29
34
  return false;
@@ -32,12 +37,12 @@ export const isNotEmptyValue = (value, spec) => {
32
37
  };
33
38
  export const prepareSpec = (spec, parseJsonDefaultValue) => {
34
39
  var _a, _b, _c, _d, _e, _f, _g, _h;
35
- if (_.isObjectLike(spec)) {
36
- const result = _.cloneDeep(spec);
37
- if (_.isString(result.type)) {
40
+ if (isObjectLike(spec)) {
41
+ const result = cloneDeep(spec);
42
+ if (isString(result.type)) {
38
43
  result.type = result.type.toLowerCase();
39
44
  }
40
- if (!_.isNil(result.defaultValue)) {
45
+ if (!isNil(result.defaultValue)) {
41
46
  let _defaultValue = result.defaultValue;
42
47
  if (parseJsonDefaultValue) {
43
48
  try {
@@ -48,33 +53,33 @@ export const prepareSpec = (spec, parseJsonDefaultValue) => {
48
53
  }
49
54
  }
50
55
  if (typeof _defaultValue === result.type ||
51
- (_.isArray(_defaultValue) && result.type === SpecTypes.Array)) {
56
+ (isArray(_defaultValue) && result.type === SpecTypes.Array)) {
52
57
  result.defaultValue = _defaultValue;
53
58
  }
54
59
  else {
55
60
  result.defaultValue = undefined;
56
61
  }
57
62
  }
58
- if (_.isString((_a = result.viewSpec) === null || _a === void 0 ? void 0 : _a.type)) {
63
+ if (isString((_a = result.viewSpec) === null || _a === void 0 ? void 0 : _a.type)) {
59
64
  result.viewSpec.type = result.viewSpec.type.toLowerCase();
60
65
  }
61
- if (_.isString((_b = result.viewSpec) === null || _b === void 0 ? void 0 : _b.layout)) {
66
+ if (isString((_b = result.viewSpec) === null || _b === void 0 ? void 0 : _b.layout)) {
62
67
  result.viewSpec.layout = result.viewSpec.layout.toLowerCase();
63
68
  }
64
- if (_.isString((_c = result.viewSpec) === null || _c === void 0 ? void 0 : _c.addButtonPosition)) {
69
+ if (isString((_c = result.viewSpec) === null || _c === void 0 ? void 0 : _c.addButtonPosition)) {
65
70
  result.viewSpec.addButtonPosition = result.viewSpec.addButtonPosition.toLowerCase();
66
71
  }
67
- if (_.isString((_d = result.viewSpec) === null || _d === void 0 ? void 0 : _d.themeLabel)) {
72
+ if (isString((_d = result.viewSpec) === null || _d === void 0 ? void 0 : _d.themeLabel)) {
68
73
  result.viewSpec.textContentParams = Object.assign(Object.assign({}, result.viewSpec.textContentParams), { themeLabel: result.viewSpec.themeLabel.toLowerCase() });
69
74
  }
70
- if (_.isString((_f = (_e = result.viewSpec) === null || _e === void 0 ? void 0 : _e.oneOfParams) === null || _f === void 0 ? void 0 : _f.toggler)) {
75
+ if (isString((_f = (_e = result.viewSpec) === null || _e === void 0 ? void 0 : _e.oneOfParams) === null || _f === void 0 ? void 0 : _f.toggler)) {
71
76
  result.viewSpec.oneOfParams.toggler = result.viewSpec.oneOfParams.toggler.toLowerCase();
72
77
  }
73
- if (_.isString((_h = (_g = result.viewSpec) === null || _g === void 0 ? void 0 : _g.textContentParams) === null || _h === void 0 ? void 0 : _h.themeLabel)) {
78
+ if (isString((_h = (_g = result.viewSpec) === null || _g === void 0 ? void 0 : _g.textContentParams) === null || _h === void 0 ? void 0 : _h.themeLabel)) {
74
79
  result.viewSpec.textContentParams.themeLabel =
75
80
  result.viewSpec.textContentParams.themeLabel.toLowerCase();
76
81
  }
77
- if (_.isString(result.validator)) {
82
+ if (isString(result.validator)) {
78
83
  result.validator = result.validator.toLowerCase();
79
84
  }
80
85
  if (result.maxLength === '0' &&
@@ -83,10 +88,10 @@ export const prepareSpec = (spec, parseJsonDefaultValue) => {
83
88
  result.minLength = undefined;
84
89
  }
85
90
  else {
86
- if (!_.isNil(result.maxLength) && isFloat(`${result.maxLength}`)) {
91
+ if (!isNil(result.maxLength) && isFloat(`${result.maxLength}`)) {
87
92
  result.maxLength = BigInt(result.maxLength);
88
93
  }
89
- if (!_.isNil(result.minLength) && isFloat(`${result.minLength}`)) {
94
+ if (!isNil(result.minLength) && isFloat(`${result.minLength}`)) {
90
95
  result.minLength = BigInt(result.minLength);
91
96
  }
92
97
  }
@@ -98,17 +103,17 @@ export const prepareSpec = (spec, parseJsonDefaultValue) => {
98
103
  result.minimum = undefined;
99
104
  }
100
105
  else {
101
- if (!_.isNil(result.maximum) && isFloat(`${result.maximum}`)) {
106
+ if (!isNil(result.maximum) && isFloat(`${result.maximum}`)) {
102
107
  result.maximum = Number(result.maximum);
103
108
  }
104
- if (!_.isNil(result.minimum) && isFloat(`${result.minimum}`)) {
109
+ if (!isNil(result.minimum) && isFloat(`${result.minimum}`)) {
105
110
  result.minimum = Number(result.minimum);
106
111
  }
107
112
  }
108
- if (_.isString(result.format)) {
113
+ if (isString(result.format)) {
109
114
  result.format = result.format.toLowerCase();
110
115
  }
111
- if (_.isObjectLike(result.properties)) {
116
+ if (isObjectLike(result.properties)) {
112
117
  Object.keys(result.properties).forEach((key) => {
113
118
  result.properties[key] = prepareSpec(result.properties[key], parseJsonDefaultValue);
114
119
  });
@@ -120,8 +125,8 @@ export const prepareSpec = (spec, parseJsonDefaultValue) => {
120
125
  export const isCorrectSizeParams = (spec) => {
121
126
  const { sizeParams } = spec.viewSpec;
122
127
  if (!sizeParams ||
123
- !_.isString(sizeParams.defaultType) ||
124
- !_.isObject(sizeParams.scale) ||
128
+ !isString(sizeParams.defaultType) ||
129
+ !isObject(sizeParams.scale) ||
125
130
  !sizeParams.scale[sizeParams.defaultType] ||
126
131
  Object.values(sizeParams.scale).some(({ factor }) => !divide(factor, factor))) {
127
132
  return false;
@@ -2,3 +2,4 @@ export * from './cn';
2
2
  export * from './common';
3
3
  export * from './bigIntMath';
4
4
  export * from './objectInline';
5
+ export * from './objectKeys';
@@ -2,3 +2,4 @@ export * from './cn';
2
2
  export * from './common';
3
3
  export * from './bigIntMath';
4
4
  export * from './objectInline';
5
+ export * from './objectKeys';
@@ -0,0 +1,4 @@
1
+ type Dictionary<T> = Record<string, T>;
2
+ type KeysOf<T> = T extends Dictionary<unknown> ? `${Exclude<keyof T, symbol>}` : never;
3
+ export declare function objectKeys<T extends Dictionary<unknown>>(obj: T): KeysOf<T>[];
4
+ export {};
@@ -0,0 +1,3 @@
1
+ export function objectKeys(obj) {
2
+ return Object.keys(obj);
3
+ }
@@ -1,4 +1,6 @@
1
- import _ from 'lodash';
1
+ import isArray from 'lodash/isArray';
2
+ import isNumber from 'lodash/isNumber';
3
+ import isString from 'lodash/isString';
2
4
  import { ErrorMessages } from '../validators';
3
5
  import { isFloat, isInt } from './helpers';
4
6
  export const getArrayValidator = (params = {}) => {
@@ -6,7 +8,7 @@ export const getArrayValidator = (params = {}) => {
6
8
  return (spec, value) => {
7
9
  const errorMessages = Object.assign(Object.assign({}, ErrorMessages), customErrorMessages);
8
10
  const valueLength = (value === null || value === void 0 ? void 0 : value.length) || 0;
9
- if (!ignoreRequiredCheck && spec.required && !_.isArray(value)) {
11
+ if (!ignoreRequiredCheck && spec.required && !isArray(value)) {
10
12
  return errorMessages.REQUIRED;
11
13
  }
12
14
  if (!ignoreMaxLengthCheck &&
@@ -63,18 +65,18 @@ export const getNumberValidator = (params = {}) => {
63
65
  }
64
66
  }
65
67
  if (!ignoreMaximumCheck &&
66
- _.isNumber(spec.maximum) &&
68
+ isNumber(spec.maximum) &&
67
69
  stringValue.length &&
68
70
  Number(stringValue) > spec.maximum) {
69
71
  return errorMessages.maxNumber(spec.maximum);
70
72
  }
71
73
  if (!ignoreMinimumCheck &&
72
- _.isNumber(spec.minimum) &&
74
+ isNumber(spec.minimum) &&
73
75
  stringValue.length &&
74
76
  spec.minimum > Number(stringValue)) {
75
77
  return errorMessages.minNumber(spec.minimum);
76
78
  }
77
- if (_.isString(spec.format) && stringValue.length) {
79
+ if (isString(spec.format) && stringValue.length) {
78
80
  if (!ignoreIntCheck && spec.format === 'int64' && !isInt(stringValue)) {
79
81
  return errorMessages.INT;
80
82
  }
@@ -119,10 +121,10 @@ export const getStringValidator = (params = {}) => {
119
121
  valueLength < spec.minLength) {
120
122
  return errorMessages.minLength(spec.minLength);
121
123
  }
122
- if (_.isString(spec.pattern) && spec.pattern.length) {
124
+ if (isString(spec.pattern) && spec.pattern.length) {
123
125
  const regex = new RegExp(spec.pattern);
124
126
  if (!ignoreRegExpCheck && !regex.test(value)) {
125
- return _.isString(spec.patternError) && spec.patternError.length
127
+ return isString(spec.patternError) && spec.patternError.length
126
128
  ? spec.patternError
127
129
  : errorMessages.INVALID;
128
130
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dynamic-forms",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "main": "build/cjs/index.js",