@gravity-ui/dynamic-forms 5.14.0 → 5.16.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.
- package/build/cjs/lib/kit/components/Inputs/TextContent/TextContent.css +3 -1
- package/build/cjs/lib/kit/components/Inputs/TextContent/TextContent.js +8 -3
- package/build/cjs/lib/kit/components/Inputs/TextContent/utils.js +5 -1
- package/build/cjs/lib/kit/components/Views/TextContentView.js +4 -3
- package/build/cjs/lib/kit/constants/config.js +1 -0
- package/build/cjs/lib/kit/i18n/en.json +2 -0
- package/build/cjs/lib/kit/i18n/ru.json +2 -0
- package/build/cjs/lib/kit/validators/helpers.js +70 -1
- package/build/cjs/lib/kit/validators/messages.js +6 -0
- package/build/cjs/lib/kit/validators/validators.js +68 -1
- package/build/esm/lib/core/types/specs.d.ts +5 -0
- package/build/esm/lib/kit/components/Inputs/TextContent/TextContent.css +3 -1
- package/build/esm/lib/kit/components/Inputs/TextContent/TextContent.js +9 -4
- package/build/esm/lib/kit/components/Inputs/TextContent/utils.d.ts +2 -0
- package/build/esm/lib/kit/components/Inputs/TextContent/utils.js +3 -0
- package/build/esm/lib/kit/components/Views/TextContentView.js +4 -3
- package/build/esm/lib/kit/constants/config.js +2 -1
- package/build/esm/lib/kit/i18n/en.json +2 -0
- package/build/esm/lib/kit/i18n/ru.json +2 -0
- package/build/esm/lib/kit/validators/helpers.d.ts +5 -0
- package/build/esm/lib/kit/validators/helpers.js +68 -0
- package/build/esm/lib/kit/validators/messages.js +6 -0
- package/build/esm/lib/kit/validators/types.d.ts +2 -0
- package/build/esm/lib/kit/validators/validators.d.ts +4 -1
- package/build/esm/lib/kit/validators/validators.js +67 -1
- package/package.json +1 -1
|
@@ -26,9 +26,11 @@
|
|
|
26
26
|
white-space: initial;
|
|
27
27
|
line-height: var(--_--height);
|
|
28
28
|
}
|
|
29
|
-
.df-text-content__icon {
|
|
29
|
+
.df-text-content__icon, .df-text-content__alert-icon {
|
|
30
30
|
display: flex;
|
|
31
31
|
align-items: center;
|
|
32
|
+
}
|
|
33
|
+
.df-text-content__icon {
|
|
32
34
|
margin-right: var(--df-text-content-icon-margin-right, var(--g-spacing-1));
|
|
33
35
|
}
|
|
34
36
|
.df-text-content__wrapper {
|
|
@@ -14,18 +14,23 @@ const TextContentComponent = ({ spec, value, Layout, }) => {
|
|
|
14
14
|
var _a;
|
|
15
15
|
const { textContentParams, layoutDescription } = spec.viewSpec;
|
|
16
16
|
const text = react_1.default.useMemo(() => ((textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text) ? textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text : layoutDescription), [layoutDescription, textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text]);
|
|
17
|
+
const iconName = textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.icon;
|
|
18
|
+
const alertView = textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.viewAlert;
|
|
19
|
+
const hasIconParam = typeof iconName === 'string';
|
|
20
|
+
const IconComponent = react_1.default.useMemo(() => (iconName ? (0, utils_2.loadIcon)(iconName) : undefined), [iconName]);
|
|
21
|
+
const iconLib = react_1.default.useMemo(() => (IconComponent ? react_1.default.createElement(LazyLoader_1.LazyLoader, { component: IconComponent }) : null), [IconComponent]);
|
|
22
|
+
const alertIcon = react_1.default.useMemo(() => (iconLib ? react_1.default.createElement("span", { className: b('alert-icon') }, iconLib) : null), [iconLib]);
|
|
17
23
|
if (!text) {
|
|
18
24
|
return null;
|
|
19
25
|
}
|
|
20
|
-
const iconLib = (textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.icon) ? (react_1.default.createElement(LazyLoader_1.LazyLoader, { component: (0, utils_2.loadIcon)(textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.icon) })) : undefined;
|
|
21
26
|
let content = react_1.default.createElement("span", { dangerouslySetInnerHTML: { __html: text } });
|
|
22
27
|
if (textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.themeAlert) {
|
|
23
28
|
const titleAlert = (textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.titleAlert) || !(0, lodash_1.isEmpty)(textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.titleAlert)
|
|
24
29
|
? textContentParams.titleAlert
|
|
25
30
|
: undefined;
|
|
26
|
-
content = (react_1.default.createElement(uikit_1.Alert, { icon:
|
|
31
|
+
content = (react_1.default.createElement(uikit_1.Alert, Object.assign({}, (alertIcon || hasIconParam ? { icon: alertIcon } : {}), { message: content,
|
|
27
32
|
// If the title is an empty line, then you need to explicitly write undefined, otherwise there will be an additional indent
|
|
28
|
-
title: titleAlert, theme: textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.themeAlert, view:
|
|
33
|
+
title: titleAlert, theme: textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.themeAlert, view: (0, utils_2.isAlertView)(alertView) ? alertView : undefined })));
|
|
29
34
|
}
|
|
30
35
|
else if (textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.themeLabel) {
|
|
31
36
|
content = (react_1.default.createElement(uikit_1.Label, { size: "m", theme: textContentParams.themeLabel, className: b(), value: value, icon: iconLib }, content));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loadIcon = void 0;
|
|
3
|
+
exports.isAlertView = exports.loadIcon = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const react_1 = tslib_1.__importDefault(require("react"));
|
|
6
6
|
const loadIcon = (name) => {
|
|
@@ -20,3 +20,7 @@ const loadIcon = (name) => {
|
|
|
20
20
|
return Icon;
|
|
21
21
|
};
|
|
22
22
|
exports.loadIcon = loadIcon;
|
|
23
|
+
const isAlertView = (view) => {
|
|
24
|
+
return view === 'filled' || view === 'outlined';
|
|
25
|
+
};
|
|
26
|
+
exports.isAlertView = isAlertView;
|
|
@@ -5,16 +5,17 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const react_1 = tslib_1.__importDefault(require("react"));
|
|
6
6
|
const Inputs_1 = require("../Inputs");
|
|
7
7
|
const TextContentView = ({ name, spec, Layout, value }) => {
|
|
8
|
+
var _a;
|
|
9
|
+
const layoutValue = ((_a = spec.viewSpec.textContentParams) === null || _a === void 0 ? void 0 : _a.text) || spec.viewSpec.layoutDescription || value;
|
|
8
10
|
const WrappedLayout = react_1.default.useMemo(() => {
|
|
9
11
|
if (Layout) {
|
|
10
12
|
const Component = (props) => {
|
|
11
|
-
|
|
12
|
-
return react_1.default.createElement(Layout, Object.assign({ name: name, value: VALUE_STUB }, props));
|
|
13
|
+
return react_1.default.createElement(Layout, Object.assign({ name: name, value: layoutValue }, props));
|
|
13
14
|
};
|
|
14
15
|
return Component;
|
|
15
16
|
}
|
|
16
17
|
return undefined;
|
|
17
|
-
}, [Layout, name]);
|
|
18
|
+
}, [Layout, layoutValue, name]);
|
|
18
19
|
return react_1.default.createElement(Inputs_1.TextContentComponent, { spec: spec, value: value, Layout: WrappedLayout });
|
|
19
20
|
};
|
|
20
21
|
exports.TextContentView = TextContentView;
|
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
],
|
|
38
38
|
"label_error-min-number": "Value must be an integer no less than {{count}}",
|
|
39
39
|
"label_error-max-number": "Value must not be greater than {{count}}",
|
|
40
|
+
"label_error-min-number-with-scale": "Value must be no less than {{count}} {{scale}}",
|
|
41
|
+
"label_error-max-number-with-scale": "Value must not be greater than {{count}} {{scale}}",
|
|
40
42
|
"label_error-space-end": "Value must not end with a space",
|
|
41
43
|
"label_error-space-start": "Value must not start with a space",
|
|
42
44
|
"label_error-zero-start": "Value must not start with a zero",
|
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
],
|
|
38
38
|
"label_error-min-number": "Значение должно быть числом не меньше {{count}}",
|
|
39
39
|
"label_error-max-number": "Значение должно быть числом не больше {{count}}",
|
|
40
|
+
"label_error-min-number-with-scale": "Значение должно быть не меньше {{count}} {{scale}}",
|
|
41
|
+
"label_error-max-number-with-scale": "Значение должно быть не больше {{count}} {{scale}}",
|
|
40
42
|
"label_error-space-end": "Значение не должно заканчиваться пробелом",
|
|
41
43
|
"label_error-space-start": "Значение не должно начинаться с пробела",
|
|
42
44
|
"label_error-zero-start": "Значение не должно начинаться с нуля",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isFloat = exports.isInt = void 0;
|
|
3
|
+
exports.getScaledLimit = exports.isFloat = exports.isInt = void 0;
|
|
4
|
+
const utils_1 = require("../utils");
|
|
4
5
|
const isInt = (value) => {
|
|
5
6
|
const regex = /^(?:[-+]?(?:0|[1-9]\d*))$/;
|
|
6
7
|
return regex.test(value);
|
|
@@ -11,3 +12,71 @@ const isFloat = (value) => {
|
|
|
11
12
|
return regex.test(value);
|
|
12
13
|
};
|
|
13
14
|
exports.isFloat = isFloat;
|
|
15
|
+
const scaleValue = (value, scaleFactor, defaultFactor) => {
|
|
16
|
+
if (defaultFactor === scaleFactor) {
|
|
17
|
+
return String(value);
|
|
18
|
+
}
|
|
19
|
+
const valueStr = String(value);
|
|
20
|
+
try {
|
|
21
|
+
if (BigInt(scaleFactor) > BigInt(defaultFactor)) {
|
|
22
|
+
const ratio = (0, utils_1.divide)(scaleFactor, defaultFactor);
|
|
23
|
+
return ratio ? (0, utils_1.divide)(valueStr, ratio, 6) : null;
|
|
24
|
+
}
|
|
25
|
+
const ratio = (0, utils_1.divide)(defaultFactor, scaleFactor);
|
|
26
|
+
return ratio ? (0, utils_1.multiply)(valueStr, ratio, 6) : null;
|
|
27
|
+
}
|
|
28
|
+
catch (_a) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const isReadable = (numStr) => {
|
|
33
|
+
if (numStr === null) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
// Math.abs does not support BigInt
|
|
37
|
+
const intPart = numStr.split('.')[0].replace('-', '');
|
|
38
|
+
try {
|
|
39
|
+
return BigInt(intPart) >= BigInt(1);
|
|
40
|
+
}
|
|
41
|
+
catch (_a) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const getMostAppropriateScale = (sizeParams, value) => {
|
|
46
|
+
const { defaultType, scale } = sizeParams;
|
|
47
|
+
const valueStr = String(value);
|
|
48
|
+
const defaultFactor = scale[defaultType].factor;
|
|
49
|
+
let bestType = defaultType;
|
|
50
|
+
Object.keys(scale).forEach((key) => {
|
|
51
|
+
if (BigInt(scale[key].factor) > BigInt(scale[bestType].factor)) {
|
|
52
|
+
const ratio = (0, utils_1.divide)(scale[key].factor, defaultFactor);
|
|
53
|
+
if (!ratio) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (!isReadable((0, utils_1.divide)(valueStr, ratio, 2))) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
bestType = key;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return bestType;
|
|
63
|
+
};
|
|
64
|
+
const getScaledLimit = (spec, limit) => {
|
|
65
|
+
var _a;
|
|
66
|
+
const sizeParams = (_a = spec.viewSpec) === null || _a === void 0 ? void 0 : _a.sizeParams;
|
|
67
|
+
if (!sizeParams) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
const mostAppropriateScale = getMostAppropriateScale(sizeParams, limit);
|
|
71
|
+
const scaleEntry = sizeParams.scale[mostAppropriateScale];
|
|
72
|
+
const defaultEntry = sizeParams.scale[sizeParams.defaultType];
|
|
73
|
+
if (!scaleEntry || !defaultEntry) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
const count = scaleValue(limit, scaleEntry.factor, defaultEntry.factor);
|
|
77
|
+
if (count === null) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
return { count, scaleTitle: scaleEntry.title };
|
|
81
|
+
};
|
|
82
|
+
exports.getScaledLimit = getScaledLimit;
|
|
@@ -27,6 +27,12 @@ const getErrorMessages = () => ({
|
|
|
27
27
|
maxNumber(count) {
|
|
28
28
|
return (0, i18n_1.default)('label_error-max-number', { count });
|
|
29
29
|
},
|
|
30
|
+
minNumberWithScale(count, scale) {
|
|
31
|
+
return (0, i18n_1.default)('label_error-min-number-with-scale', { count, scale });
|
|
32
|
+
},
|
|
33
|
+
maxNumberWithScale(count, scale) {
|
|
34
|
+
return (0, i18n_1.default)('label_error-max-number-with-scale', { count, scale });
|
|
35
|
+
},
|
|
30
36
|
SPACE_START: (0, i18n_1.default)('label_error-space-start'),
|
|
31
37
|
SPACE_END: (0, i18n_1.default)('label_error-space-end'),
|
|
32
38
|
DOT_END: (0, i18n_1.default)('label_error-dot-end'),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getStringValidator = exports.getObjectValidator = exports.getNumberValidator = exports.getBooleanValidator = exports.getArrayValidator = void 0;
|
|
3
|
+
exports.getStringValidator = exports.getObjectValidator = exports.getNumberWithScaleValidator = exports.getNumberValidator = exports.getBooleanValidator = exports.getArrayValidator = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const isArray_1 = tslib_1.__importDefault(require("lodash/isArray"));
|
|
6
6
|
const isNumber_1 = tslib_1.__importDefault(require("lodash/isNumber"));
|
|
@@ -101,6 +101,73 @@ const getNumberValidator = (params = {}) => {
|
|
|
101
101
|
};
|
|
102
102
|
};
|
|
103
103
|
exports.getNumberValidator = getNumberValidator;
|
|
104
|
+
const getNumberWithScaleValidator = (params = {}) => {
|
|
105
|
+
const { ignoreRequiredCheck, ignoreSpaceStartCheck, ignoreSpaceEndCheck, ignoreNumberCheck, ignoreMaximumCheck, ignoreMinimumCheck, ignoreIntCheck, ignoreDotEnd, ignoreZeroStart, ignoreInvalidZeroFormat, ignoreZeroEnd, customErrorMessages, } = params;
|
|
106
|
+
// eslint-disable-next-line complexity
|
|
107
|
+
return (spec, value = '') => {
|
|
108
|
+
const errorMessages = Object.assign(Object.assign({}, validators_1.ErrorMessages), customErrorMessages);
|
|
109
|
+
const stringValue = String(value);
|
|
110
|
+
if (!ignoreRequiredCheck && spec.required && !stringValue.length) {
|
|
111
|
+
return errorMessages.REQUIRED;
|
|
112
|
+
}
|
|
113
|
+
if (stringValue.length) {
|
|
114
|
+
if (!ignoreSpaceStartCheck && !stringValue[0].trim()) {
|
|
115
|
+
return errorMessages.SPACE_START;
|
|
116
|
+
}
|
|
117
|
+
if (!ignoreSpaceEndCheck && !stringValue[stringValue.length - 1].trim()) {
|
|
118
|
+
return errorMessages.SPACE_END;
|
|
119
|
+
}
|
|
120
|
+
if (!ignoreDotEnd && stringValue[stringValue.length - 1] === '.') {
|
|
121
|
+
return errorMessages.DOT_END;
|
|
122
|
+
}
|
|
123
|
+
if (!ignoreNumberCheck && !(0, helpers_1.isFloat)(stringValue)) {
|
|
124
|
+
return errorMessages.NUMBER;
|
|
125
|
+
}
|
|
126
|
+
if (!ignoreZeroStart &&
|
|
127
|
+
((stringValue.length > 1 && stringValue[0] === '0' && stringValue[1] !== '.') ||
|
|
128
|
+
(stringValue.length > 2 &&
|
|
129
|
+
stringValue.substring(0, 2) === '-0' &&
|
|
130
|
+
stringValue[2] !== '.'))) {
|
|
131
|
+
return errorMessages.ZERO_START;
|
|
132
|
+
}
|
|
133
|
+
if (!ignoreInvalidZeroFormat &&
|
|
134
|
+
stringValue.trim().length > 1 &&
|
|
135
|
+
Number(stringValue.trim()) === 0) {
|
|
136
|
+
return errorMessages.INVALID_ZERO_FORMAT;
|
|
137
|
+
}
|
|
138
|
+
if (!ignoreZeroEnd &&
|
|
139
|
+
!(0, helpers_1.isInt)(stringValue) &&
|
|
140
|
+
stringValue[stringValue.length - 1] === '0') {
|
|
141
|
+
return errorMessages.ZERO_END;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (!ignoreMaximumCheck &&
|
|
145
|
+
(0, isNumber_1.default)(spec.maximum) &&
|
|
146
|
+
stringValue.length &&
|
|
147
|
+
Number(stringValue) > spec.maximum) {
|
|
148
|
+
const scaled = (0, helpers_1.getScaledLimit)(spec, spec.maximum);
|
|
149
|
+
return scaled
|
|
150
|
+
? errorMessages.maxNumberWithScale(scaled.count, scaled.scaleTitle)
|
|
151
|
+
: errorMessages.maxNumber(spec.maximum);
|
|
152
|
+
}
|
|
153
|
+
if (!ignoreMinimumCheck &&
|
|
154
|
+
(0, isNumber_1.default)(spec.minimum) &&
|
|
155
|
+
stringValue.length &&
|
|
156
|
+
spec.minimum > Number(stringValue)) {
|
|
157
|
+
const scaled = (0, helpers_1.getScaledLimit)(spec, spec.minimum);
|
|
158
|
+
return scaled
|
|
159
|
+
? errorMessages.minNumberWithScale(scaled.count, scaled.scaleTitle)
|
|
160
|
+
: errorMessages.minNumber(spec.minimum);
|
|
161
|
+
}
|
|
162
|
+
if ((0, isString_1.default)(spec.format) && stringValue.length) {
|
|
163
|
+
if (!ignoreIntCheck && spec.format === 'int64' && !(0, helpers_1.isInt)(stringValue)) {
|
|
164
|
+
return errorMessages.INT;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
exports.getNumberWithScaleValidator = getNumberWithScaleValidator;
|
|
104
171
|
const getObjectValidator = (params = {}) => {
|
|
105
172
|
const { ignoreRequiredCheck, customErrorMessages } = params;
|
|
106
173
|
return (spec, value) => {
|
|
@@ -186,4 +186,9 @@ export interface StringSpec<LinkType = any, InputComponentProps extends Record<s
|
|
|
186
186
|
generateRandomValueButton?: boolean;
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
|
+
export interface NumberWithScaleSpec extends StringSpec {
|
|
190
|
+
minimum?: number;
|
|
191
|
+
maximum?: number;
|
|
192
|
+
format?: 'float' | 'int64';
|
|
193
|
+
}
|
|
189
194
|
export type Spec<LinkType = any, InputComponentProps extends Record<string, any> | undefined = undefined, LayoutComponentProps extends Record<string, any> | undefined = undefined> = ArraySpec<LinkType, InputComponentProps, LayoutComponentProps> | BooleanSpec<LinkType, InputComponentProps, LayoutComponentProps> | NumberSpec<LinkType, InputComponentProps, LayoutComponentProps> | ObjectSpec<LinkType, InputComponentProps, LayoutComponentProps> | StringSpec<LinkType, InputComponentProps, LayoutComponentProps>;
|
|
@@ -26,9 +26,11 @@
|
|
|
26
26
|
white-space: initial;
|
|
27
27
|
line-height: var(--_--height);
|
|
28
28
|
}
|
|
29
|
-
.df-text-content__icon {
|
|
29
|
+
.df-text-content__icon, .df-text-content__alert-icon {
|
|
30
30
|
display: flex;
|
|
31
31
|
align-items: center;
|
|
32
|
+
}
|
|
33
|
+
.df-text-content__icon {
|
|
32
34
|
margin-right: var(--df-text-content-icon-margin-right, var(--g-spacing-1));
|
|
33
35
|
}
|
|
34
36
|
.df-text-content__wrapper {
|
|
@@ -4,25 +4,30 @@ import { isEmpty } from 'lodash';
|
|
|
4
4
|
import cloneDeep from 'lodash/cloneDeep';
|
|
5
5
|
import { block } from '../../../utils';
|
|
6
6
|
import { LazyLoader } from '../../LazyLoader';
|
|
7
|
-
import { loadIcon } from './utils';
|
|
7
|
+
import { isAlertView, loadIcon } from './utils';
|
|
8
8
|
import './TextContent.css';
|
|
9
9
|
const b = block('text-content');
|
|
10
10
|
export const TextContentComponent = ({ spec, value, Layout, }) => {
|
|
11
11
|
var _a;
|
|
12
12
|
const { textContentParams, layoutDescription } = spec.viewSpec;
|
|
13
13
|
const text = React.useMemo(() => ((textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text) ? textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text : layoutDescription), [layoutDescription, textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.text]);
|
|
14
|
+
const iconName = textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.icon;
|
|
15
|
+
const alertView = textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.viewAlert;
|
|
16
|
+
const hasIconParam = typeof iconName === 'string';
|
|
17
|
+
const IconComponent = React.useMemo(() => (iconName ? loadIcon(iconName) : undefined), [iconName]);
|
|
18
|
+
const iconLib = React.useMemo(() => (IconComponent ? React.createElement(LazyLoader, { component: IconComponent }) : null), [IconComponent]);
|
|
19
|
+
const alertIcon = React.useMemo(() => (iconLib ? React.createElement("span", { className: b('alert-icon') }, iconLib) : null), [iconLib]);
|
|
14
20
|
if (!text) {
|
|
15
21
|
return null;
|
|
16
22
|
}
|
|
17
|
-
const iconLib = (textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.icon) ? (React.createElement(LazyLoader, { component: loadIcon(textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.icon) })) : undefined;
|
|
18
23
|
let content = React.createElement("span", { dangerouslySetInnerHTML: { __html: text } });
|
|
19
24
|
if (textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.themeAlert) {
|
|
20
25
|
const titleAlert = (textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.titleAlert) || !isEmpty(textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.titleAlert)
|
|
21
26
|
? textContentParams.titleAlert
|
|
22
27
|
: undefined;
|
|
23
|
-
content = (React.createElement(Alert, { icon:
|
|
28
|
+
content = (React.createElement(Alert, Object.assign({}, (alertIcon || hasIconParam ? { icon: alertIcon } : {}), { message: content,
|
|
24
29
|
// If the title is an empty line, then you need to explicitly write undefined, otherwise there will be an additional indent
|
|
25
|
-
title: titleAlert, theme: textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.themeAlert, view:
|
|
30
|
+
title: titleAlert, theme: textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.themeAlert, view: isAlertView(alertView) ? alertView : undefined })));
|
|
26
31
|
}
|
|
27
32
|
else if (textContentParams === null || textContentParams === void 0 ? void 0 : textContentParams.themeLabel) {
|
|
28
33
|
content = (React.createElement(Label, { size: "m", theme: textContentParams.themeLabel, className: b(), value: value, icon: iconLib }, content));
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { TextContentComponent } from '../Inputs';
|
|
3
3
|
export const TextContentView = ({ name, spec, Layout, value }) => {
|
|
4
|
+
var _a;
|
|
5
|
+
const layoutValue = ((_a = spec.viewSpec.textContentParams) === null || _a === void 0 ? void 0 : _a.text) || spec.viewSpec.layoutDescription || value;
|
|
4
6
|
const WrappedLayout = React.useMemo(() => {
|
|
5
7
|
if (Layout) {
|
|
6
8
|
const Component = (props) => {
|
|
7
|
-
|
|
8
|
-
return React.createElement(Layout, Object.assign({ name: name, value: VALUE_STUB }, props));
|
|
9
|
+
return React.createElement(Layout, Object.assign({ name: name, value: layoutValue }, props));
|
|
9
10
|
};
|
|
10
11
|
return Component;
|
|
11
12
|
}
|
|
12
13
|
return undefined;
|
|
13
|
-
}, [Layout, name]);
|
|
14
|
+
}, [Layout, layoutValue, name]);
|
|
14
15
|
return React.createElement(TextContentComponent, { spec: spec, value: value, Layout: WrappedLayout });
|
|
15
16
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Accordeon, AccordeonCardForm, ArrayBase, ArrayBaseView, BaseView, CardAccordeon, CardOneOf, CardOneOfView, CardSection, Checkbox, CheckboxGroup, CheckboxGroupView, Column, DateInput, DateView, FileInput, FileInputView, Group, Group2, MonacoInput, MonacoView, MultiOneOf, MultiOneOfFlat, MultiOneOfFlatView, MultiOneOfView, MultiSelect, MultiSelectView, NumInput, NumberWithScale, NumberWithScaleView, ObjectBase, ObjectBaseView, ObjectInline, ObjectInlineView, ObjectValueInput, ObjectValueInputView, OneOf, OneOfFlat, OneOfFlatView, OneOfView, RadioGroup, RangeInputPicker, RangeInputPickerNumber, RangeInputPickerNumberView, RangeInputPickerView, Row, RowVerbose, Secret, Section, Section2, Select, Switch, TableArrayInput, TableArrayView, TableCell, Text, TextArea, TextAreaView, TextContent, TextContentView, TextLink, TextLinkView, TimeRangeSelector, TimeRangeSelectorView, Transparent, ViewAccordeon, ViewAccordeonCard, ViewCardAccordeon, ViewCardSection, ViewColumn, ViewGroup, ViewGroup2, ViewRow, ViewSection, ViewSection2, ViewTableCell, ViewTransparent, } from '../components';
|
|
2
|
-
import { getArrayValidator, getBooleanValidator, getNumberValidator, getObjectValidator, getStringValidator, } from '../validators';
|
|
2
|
+
import { getArrayValidator, getBooleanValidator, getNumberValidator, getNumberWithScaleValidator, getObjectValidator, getStringValidator, } from '../validators';
|
|
3
3
|
export const dynamicConfig = {
|
|
4
4
|
array: {
|
|
5
5
|
inputs: {
|
|
@@ -120,6 +120,7 @@ export const dynamicConfig = {
|
|
|
120
120
|
validators: {
|
|
121
121
|
base: getStringValidator(),
|
|
122
122
|
number: getNumberValidator(),
|
|
123
|
+
number_with_scale: getNumberWithScaleValidator(),
|
|
123
124
|
},
|
|
124
125
|
},
|
|
125
126
|
};
|
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
],
|
|
38
38
|
"label_error-min-number": "Value must be an integer no less than {{count}}",
|
|
39
39
|
"label_error-max-number": "Value must not be greater than {{count}}",
|
|
40
|
+
"label_error-min-number-with-scale": "Value must be no less than {{count}} {{scale}}",
|
|
41
|
+
"label_error-max-number-with-scale": "Value must not be greater than {{count}} {{scale}}",
|
|
40
42
|
"label_error-space-end": "Value must not end with a space",
|
|
41
43
|
"label_error-space-start": "Value must not start with a space",
|
|
42
44
|
"label_error-zero-start": "Value must not start with a zero",
|
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
],
|
|
38
38
|
"label_error-min-number": "Значение должно быть числом не меньше {{count}}",
|
|
39
39
|
"label_error-max-number": "Значение должно быть числом не больше {{count}}",
|
|
40
|
+
"label_error-min-number-with-scale": "Значение должно быть не меньше {{count}} {{scale}}",
|
|
41
|
+
"label_error-max-number-with-scale": "Значение должно быть не больше {{count}} {{scale}}",
|
|
40
42
|
"label_error-space-end": "Значение не должно заканчиваться пробелом",
|
|
41
43
|
"label_error-space-start": "Значение не должно начинаться с пробела",
|
|
42
44
|
"label_error-zero-start": "Значение не должно начинаться с нуля",
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
+
import type { StringSpec } from 'src/lib/core';
|
|
1
2
|
export declare const isInt: (value: string) => boolean;
|
|
2
3
|
export declare const isFloat: (value: string) => boolean;
|
|
4
|
+
export declare const getScaledLimit: (spec: StringSpec, limit: number) => {
|
|
5
|
+
count: string;
|
|
6
|
+
scaleTitle: string;
|
|
7
|
+
} | undefined;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { divide, multiply } from '../utils';
|
|
1
2
|
export const isInt = (value) => {
|
|
2
3
|
const regex = /^(?:[-+]?(?:0|[1-9]\d*))$/;
|
|
3
4
|
return regex.test(value);
|
|
@@ -6,3 +7,70 @@ export const isFloat = (value) => {
|
|
|
6
7
|
const regex = /^(?:[-+]?(?:\d+))?(?:\.\d*)?(?:[eE][+-]?(?:\d+))?$/;
|
|
7
8
|
return regex.test(value);
|
|
8
9
|
};
|
|
10
|
+
const scaleValue = (value, scaleFactor, defaultFactor) => {
|
|
11
|
+
if (defaultFactor === scaleFactor) {
|
|
12
|
+
return String(value);
|
|
13
|
+
}
|
|
14
|
+
const valueStr = String(value);
|
|
15
|
+
try {
|
|
16
|
+
if (BigInt(scaleFactor) > BigInt(defaultFactor)) {
|
|
17
|
+
const ratio = divide(scaleFactor, defaultFactor);
|
|
18
|
+
return ratio ? divide(valueStr, ratio, 6) : null;
|
|
19
|
+
}
|
|
20
|
+
const ratio = divide(defaultFactor, scaleFactor);
|
|
21
|
+
return ratio ? multiply(valueStr, ratio, 6) : null;
|
|
22
|
+
}
|
|
23
|
+
catch (_a) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const isReadable = (numStr) => {
|
|
28
|
+
if (numStr === null) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
// Math.abs does not support BigInt
|
|
32
|
+
const intPart = numStr.split('.')[0].replace('-', '');
|
|
33
|
+
try {
|
|
34
|
+
return BigInt(intPart) >= BigInt(1);
|
|
35
|
+
}
|
|
36
|
+
catch (_a) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const getMostAppropriateScale = (sizeParams, value) => {
|
|
41
|
+
const { defaultType, scale } = sizeParams;
|
|
42
|
+
const valueStr = String(value);
|
|
43
|
+
const defaultFactor = scale[defaultType].factor;
|
|
44
|
+
let bestType = defaultType;
|
|
45
|
+
Object.keys(scale).forEach((key) => {
|
|
46
|
+
if (BigInt(scale[key].factor) > BigInt(scale[bestType].factor)) {
|
|
47
|
+
const ratio = divide(scale[key].factor, defaultFactor);
|
|
48
|
+
if (!ratio) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (!isReadable(divide(valueStr, ratio, 2))) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
bestType = key;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return bestType;
|
|
58
|
+
};
|
|
59
|
+
export const getScaledLimit = (spec, limit) => {
|
|
60
|
+
var _a;
|
|
61
|
+
const sizeParams = (_a = spec.viewSpec) === null || _a === void 0 ? void 0 : _a.sizeParams;
|
|
62
|
+
if (!sizeParams) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
const mostAppropriateScale = getMostAppropriateScale(sizeParams, limit);
|
|
66
|
+
const scaleEntry = sizeParams.scale[mostAppropriateScale];
|
|
67
|
+
const defaultEntry = sizeParams.scale[sizeParams.defaultType];
|
|
68
|
+
if (!scaleEntry || !defaultEntry) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
const count = scaleValue(limit, scaleEntry.factor, defaultEntry.factor);
|
|
72
|
+
if (count === null) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
return { count, scaleTitle: scaleEntry.title };
|
|
76
|
+
};
|
|
@@ -23,6 +23,12 @@ const getErrorMessages = () => ({
|
|
|
23
23
|
maxNumber(count) {
|
|
24
24
|
return i18n('label_error-max-number', { count });
|
|
25
25
|
},
|
|
26
|
+
minNumberWithScale(count, scale) {
|
|
27
|
+
return i18n('label_error-min-number-with-scale', { count, scale });
|
|
28
|
+
},
|
|
29
|
+
maxNumberWithScale(count, scale) {
|
|
30
|
+
return i18n('label_error-max-number-with-scale', { count, scale });
|
|
31
|
+
},
|
|
26
32
|
SPACE_START: i18n('label_error-space-start'),
|
|
27
33
|
SPACE_END: i18n('label_error-space-end'),
|
|
28
34
|
DOT_END: i18n('label_error-dot-end'),
|
|
@@ -9,6 +9,8 @@ export interface ErrorMessagesType {
|
|
|
9
9
|
maxLengthArr: (count: number | bigint) => string;
|
|
10
10
|
minNumber: (count: number | bigint) => string;
|
|
11
11
|
maxNumber: (count: number | bigint) => string;
|
|
12
|
+
minNumberWithScale: (count: number | bigint | string, scale: string) => string;
|
|
13
|
+
maxNumberWithScale: (count: number | bigint | string, scale: string) => string;
|
|
12
14
|
SPACE_START: string;
|
|
13
15
|
SPACE_END: string;
|
|
14
16
|
DOT_END: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ArraySpec, ArrayValue, BooleanSpec, NumberSpec, ObjectSpec, ObjectValue, StringSpec } from '../../core';
|
|
1
|
+
import type { ArraySpec, ArrayValue, BooleanSpec, NumberSpec, NumberWithScaleSpec, ObjectSpec, ObjectValue, StringSpec } from '../../core';
|
|
2
2
|
import type { ErrorMessagesType } from './types';
|
|
3
3
|
interface CommonValidatorParams {
|
|
4
4
|
ignoreRequiredCheck?: boolean;
|
|
@@ -25,6 +25,9 @@ export interface GetNumberValidatorParams extends CommonValidatorParams {
|
|
|
25
25
|
ignoreZeroEnd?: boolean;
|
|
26
26
|
}
|
|
27
27
|
export declare const getNumberValidator: (params?: GetNumberValidatorParams) => (spec: NumberSpec, value?: string | number) => string | false;
|
|
28
|
+
export interface GetNumberWithScaleValidatorParams extends GetNumberValidatorParams {
|
|
29
|
+
}
|
|
30
|
+
export declare const getNumberWithScaleValidator: (params?: GetNumberWithScaleValidatorParams) => (spec: NumberWithScaleSpec, value?: string) => string | false;
|
|
28
31
|
export interface GetObjectValidatorParams extends CommonValidatorParams {
|
|
29
32
|
}
|
|
30
33
|
export declare const getObjectValidator: (params?: GetObjectValidatorParams) => (spec: ObjectSpec, value?: ObjectValue) => string | false;
|
|
@@ -2,7 +2,7 @@ import isArray from 'lodash/isArray';
|
|
|
2
2
|
import isNumber from 'lodash/isNumber';
|
|
3
3
|
import isString from 'lodash/isString';
|
|
4
4
|
import { ErrorMessages } from '../validators';
|
|
5
|
-
import { isFloat, isInt } from './helpers';
|
|
5
|
+
import { getScaledLimit, isFloat, isInt } from './helpers';
|
|
6
6
|
export const getArrayValidator = (params = {}) => {
|
|
7
7
|
const { ignoreRequiredCheck, ignoreMaxLengthCheck, ignoreMinLengthCheck, customErrorMessages } = params;
|
|
8
8
|
return (spec, value) => {
|
|
@@ -94,6 +94,72 @@ export const getNumberValidator = (params = {}) => {
|
|
|
94
94
|
return false;
|
|
95
95
|
};
|
|
96
96
|
};
|
|
97
|
+
export const getNumberWithScaleValidator = (params = {}) => {
|
|
98
|
+
const { ignoreRequiredCheck, ignoreSpaceStartCheck, ignoreSpaceEndCheck, ignoreNumberCheck, ignoreMaximumCheck, ignoreMinimumCheck, ignoreIntCheck, ignoreDotEnd, ignoreZeroStart, ignoreInvalidZeroFormat, ignoreZeroEnd, customErrorMessages, } = params;
|
|
99
|
+
// eslint-disable-next-line complexity
|
|
100
|
+
return (spec, value = '') => {
|
|
101
|
+
const errorMessages = Object.assign(Object.assign({}, ErrorMessages), customErrorMessages);
|
|
102
|
+
const stringValue = String(value);
|
|
103
|
+
if (!ignoreRequiredCheck && spec.required && !stringValue.length) {
|
|
104
|
+
return errorMessages.REQUIRED;
|
|
105
|
+
}
|
|
106
|
+
if (stringValue.length) {
|
|
107
|
+
if (!ignoreSpaceStartCheck && !stringValue[0].trim()) {
|
|
108
|
+
return errorMessages.SPACE_START;
|
|
109
|
+
}
|
|
110
|
+
if (!ignoreSpaceEndCheck && !stringValue[stringValue.length - 1].trim()) {
|
|
111
|
+
return errorMessages.SPACE_END;
|
|
112
|
+
}
|
|
113
|
+
if (!ignoreDotEnd && stringValue[stringValue.length - 1] === '.') {
|
|
114
|
+
return errorMessages.DOT_END;
|
|
115
|
+
}
|
|
116
|
+
if (!ignoreNumberCheck && !isFloat(stringValue)) {
|
|
117
|
+
return errorMessages.NUMBER;
|
|
118
|
+
}
|
|
119
|
+
if (!ignoreZeroStart &&
|
|
120
|
+
((stringValue.length > 1 && stringValue[0] === '0' && stringValue[1] !== '.') ||
|
|
121
|
+
(stringValue.length > 2 &&
|
|
122
|
+
stringValue.substring(0, 2) === '-0' &&
|
|
123
|
+
stringValue[2] !== '.'))) {
|
|
124
|
+
return errorMessages.ZERO_START;
|
|
125
|
+
}
|
|
126
|
+
if (!ignoreInvalidZeroFormat &&
|
|
127
|
+
stringValue.trim().length > 1 &&
|
|
128
|
+
Number(stringValue.trim()) === 0) {
|
|
129
|
+
return errorMessages.INVALID_ZERO_FORMAT;
|
|
130
|
+
}
|
|
131
|
+
if (!ignoreZeroEnd &&
|
|
132
|
+
!isInt(stringValue) &&
|
|
133
|
+
stringValue[stringValue.length - 1] === '0') {
|
|
134
|
+
return errorMessages.ZERO_END;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (!ignoreMaximumCheck &&
|
|
138
|
+
isNumber(spec.maximum) &&
|
|
139
|
+
stringValue.length &&
|
|
140
|
+
Number(stringValue) > spec.maximum) {
|
|
141
|
+
const scaled = getScaledLimit(spec, spec.maximum);
|
|
142
|
+
return scaled
|
|
143
|
+
? errorMessages.maxNumberWithScale(scaled.count, scaled.scaleTitle)
|
|
144
|
+
: errorMessages.maxNumber(spec.maximum);
|
|
145
|
+
}
|
|
146
|
+
if (!ignoreMinimumCheck &&
|
|
147
|
+
isNumber(spec.minimum) &&
|
|
148
|
+
stringValue.length &&
|
|
149
|
+
spec.minimum > Number(stringValue)) {
|
|
150
|
+
const scaled = getScaledLimit(spec, spec.minimum);
|
|
151
|
+
return scaled
|
|
152
|
+
? errorMessages.minNumberWithScale(scaled.count, scaled.scaleTitle)
|
|
153
|
+
: errorMessages.minNumber(spec.minimum);
|
|
154
|
+
}
|
|
155
|
+
if (isString(spec.format) && stringValue.length) {
|
|
156
|
+
if (!ignoreIntCheck && spec.format === 'int64' && !isInt(stringValue)) {
|
|
157
|
+
return errorMessages.INT;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return false;
|
|
161
|
+
};
|
|
162
|
+
};
|
|
97
163
|
export const getObjectValidator = (params = {}) => {
|
|
98
164
|
const { ignoreRequiredCheck, customErrorMessages } = params;
|
|
99
165
|
return (spec, value) => {
|