@skbkontur/react-ui 4.25.0 → 4.25.1-MaskedInput-fix.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/CHANGELOG.md +8 -0
- package/LICENSE +21 -21
- package/cjs/components/Gapped/Gapped.md +43 -43
- package/cjs/components/Input/Input.d.ts +3 -2
- package/cjs/components/Input/Input.js +7 -4
- package/cjs/components/Input/Input.js.map +1 -1
- package/cjs/components/MaskedInput/MaskedInput.d.ts +22 -4
- package/cjs/components/MaskedInput/MaskedInput.helpers.d.ts +10 -0
- package/cjs/components/MaskedInput/MaskedInput.helpers.js +30 -0
- package/cjs/components/MaskedInput/MaskedInput.helpers.js.map +1 -0
- package/cjs/components/MaskedInput/MaskedInput.js +190 -20
- package/cjs/components/MaskedInput/MaskedInput.js.map +1 -1
- package/cjs/components/MaskedInput/MaskedInput.md +173 -9
- package/cjs/components/MaskedInput/MaskedInput.styles.d.ts +3 -0
- package/cjs/components/MaskedInput/MaskedInput.styles.js +4 -0
- package/cjs/components/MaskedInput/MaskedInput.styles.js.map +1 -0
- package/cjs/components/RadioGroup/RadioGroup.md +43 -43
- package/cjs/index.d.ts +3 -0
- package/cjs/index.js +3 -0
- package/cjs/index.js.map +1 -1
- package/cjs/internal/MaskedInputElement/MaskedInputElement.d.ts +6 -9
- package/cjs/internal/MaskedInputElement/MaskedInputElement.js +99 -129
- package/cjs/internal/MaskedInputElement/MaskedInputElement.js.map +1 -1
- package/cjs/internal/MaskedInputElement/MaskedInputElement.styles.d.ts +2 -3
- package/cjs/internal/MaskedInputElement/MaskedInputElement.styles.js +7 -17
- package/cjs/internal/MaskedInputElement/MaskedInputElement.styles.js.map +1 -1
- package/cjs/internal/ThemeShowcase/ThemeShowcase.md +13 -13
- package/cjs/lib/styles/HoldSelectionColor.js +1 -1
- package/cjs/lib/styles/HoldSelectionColor.js.map +1 -1
- package/cjs/lib/styles/UiFont.d.ts +4 -0
- package/cjs/lib/styles/UiFont.js +39 -0
- package/cjs/lib/styles/UiFont.js.map +1 -0
- package/components/Gapped/Gapped.md +43 -43
- package/components/Input/Input/Input.js +8 -4
- package/components/Input/Input/Input.js.map +1 -1
- package/components/Input/Input.d.ts +3 -2
- package/components/MaskedInput/MaskedInput/MaskedInput.js +171 -22
- package/components/MaskedInput/MaskedInput/MaskedInput.js.map +1 -1
- package/components/MaskedInput/MaskedInput.d.ts +22 -4
- package/components/MaskedInput/MaskedInput.helpers/MaskedInput.helpers.js +27 -0
- package/components/MaskedInput/MaskedInput.helpers/MaskedInput.helpers.js.map +1 -0
- package/components/MaskedInput/MaskedInput.helpers/package.json +6 -0
- package/components/MaskedInput/MaskedInput.helpers.d.ts +10 -0
- package/components/MaskedInput/MaskedInput.md +173 -9
- package/components/MaskedInput/MaskedInput.styles/MaskedInput.styles.js +4 -0
- package/components/MaskedInput/MaskedInput.styles/MaskedInput.styles.js.map +1 -0
- package/components/MaskedInput/MaskedInput.styles/package.json +6 -0
- package/components/MaskedInput/MaskedInput.styles.d.ts +3 -0
- package/components/RadioGroup/RadioGroup.md +43 -43
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/index.js.map +1 -1
- package/internal/MaskedInputElement/MaskedInputElement/MaskedInputElement.js +105 -161
- package/internal/MaskedInputElement/MaskedInputElement/MaskedInputElement.js.map +1 -1
- package/internal/MaskedInputElement/MaskedInputElement.d.ts +6 -9
- package/internal/MaskedInputElement/MaskedInputElement.styles/MaskedInputElement.styles.js +5 -8
- package/internal/MaskedInputElement/MaskedInputElement.styles/MaskedInputElement.styles.js.map +1 -1
- package/internal/MaskedInputElement/MaskedInputElement.styles.d.ts +2 -3
- package/internal/ThemeShowcase/ThemeShowcase.md +13 -13
- package/lib/styles/HoldSelectionColor/HoldSelectionColor.js +1 -1
- package/lib/styles/HoldSelectionColor/HoldSelectionColor.js.map +1 -1
- package/lib/styles/UiFont/UiFont.js +30 -0
- package/lib/styles/UiFont/UiFont.js.map +1 -0
- package/lib/styles/UiFont/package.json +6 -0
- package/lib/styles/UiFont.d.ts +4 -0
- package/package.json +2 -5
- package/cjs/internal/MaskedInputElement/MaskedInputElement.helpers.d.ts +0 -16
- package/cjs/internal/MaskedInputElement/MaskedInputElement.helpers.js +0 -52
- package/cjs/internal/MaskedInputElement/MaskedInputElement.helpers.js.map +0 -1
- package/internal/MaskedInputElement/MaskedInputElement.helpers/MaskedInputElement.helpers.js +0 -43
- package/internal/MaskedInputElement/MaskedInputElement.helpers/MaskedInputElement.helpers.js.map +0 -1
- package/internal/MaskedInputElement/MaskedInputElement.helpers/package.json +0 -6
- package/internal/MaskedInputElement/MaskedInputElement.helpers.d.ts +0 -16
|
@@ -1,9 +1,38 @@
|
|
|
1
1
|
"use strict";var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;exports.__esModule = true;exports.MaskedInput = void 0;var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));var _react = _interopRequireWildcard(require("react"));
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _reactImask = require("react-imask");
|
|
4
|
+
var _globalObject = require("@skbkontur/global-object");
|
|
5
|
+
|
|
4
6
|
|
|
5
7
|
var _MaskedInputElement = require("../../internal/MaskedInputElement");
|
|
6
|
-
var _forwardRefAndName = require("../../lib/forwardRefAndName");
|
|
8
|
+
var _forwardRefAndName = require("../../lib/forwardRefAndName");
|
|
9
|
+
var _Emotion = require("../../lib/theming/Emotion");
|
|
10
|
+
var _UiFont = require("../../lib/styles/UiFont");
|
|
11
|
+
var _Input = require("../Input");
|
|
12
|
+
var _identifiers = require("../../lib/events/keyboard/identifiers");
|
|
13
|
+
var _isInstanceOf = require("../../lib/isInstanceOf");
|
|
14
|
+
|
|
15
|
+
var _MaskedInput = require("./MaskedInput.styles");
|
|
16
|
+
var _MaskedInput2 = require("./MaskedInput.helpers");var _excluded = ["onAccept"],_excluded2 = ["mask", "maskChar", "formatChars", "alwaysShowMask", "imaskProps", "placeholder", "onValueChange", "onUnexpectedInput", "onKeyDownCapture", "onChange", "element"];
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
7
36
|
|
|
8
37
|
|
|
9
38
|
|
|
@@ -32,47 +61,188 @@ var _forwardRefAndName = require("../../lib/forwardRefAndName");var _excluded =
|
|
|
32
61
|
var MaskedInput = (0, _forwardRefAndName.forwardRefAndName)(
|
|
33
62
|
'MaskedInput',
|
|
34
63
|
function MaskedInput(props, ref) {
|
|
35
|
-
var
|
|
64
|
+
var
|
|
65
|
+
mask =
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
props.mask,maskChar = props.maskChar,formatChars = props.formatChars,alwaysShowMask = props.alwaysShowMask,_props$imaskProps = props.imaskProps;_props$imaskProps = _props$imaskProps === void 0 ? {} : _props$imaskProps;var onAccept = _props$imaskProps.onAccept,customIMaskProps = (0, _objectWithoutPropertiesLoose2.default)(_props$imaskProps, _excluded),placeholder = props.placeholder,onValueChange = props.onValueChange,onUnexpectedInput = props.onUnexpectedInput,onKeyDownCapture = props.onKeyDownCapture,onChange = props.onChange,element = props.element,inputProps = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded2);
|
|
78
|
+
|
|
79
|
+
var inputRef = (0, _react.useRef)(null);
|
|
80
|
+
var imaskRef = (0, _react.useRef)(null);
|
|
81
|
+
|
|
36
82
|
var _useState = (0, _react.useState)(false),focused = _useState[0],setFocused = _useState[1];
|
|
83
|
+
var prevValue = (0, _react.useRef)(props.value || String(props.defaultValue) || '');
|
|
84
|
+
var prevSelectionStart = (0, _react.useRef)(null);
|
|
85
|
+
|
|
37
86
|
var showPlaceholder = !(alwaysShowMask || focused);
|
|
38
|
-
var innerRef = (0, _react.useRef)(null);
|
|
39
87
|
|
|
40
|
-
(0, _react.useImperativeHandle)(
|
|
88
|
+
(0, _react.useImperativeHandle)(
|
|
89
|
+
ref,
|
|
90
|
+
function () {return (
|
|
91
|
+
inputRef.current &&
|
|
92
|
+
Object.assign(inputRef.current, {
|
|
93
|
+
selectAll: inputRef.current.delaySelectAll }));},
|
|
94
|
+
|
|
95
|
+
[]);
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
(0, _react.useEffect)(function () {var _inputRef$current;
|
|
99
|
+
/**
|
|
100
|
+
* Для корректной работы `onUnexpectedInput` надо знать предыдущий `value`,
|
|
101
|
+
* но `imask` при монтировании не вызывает `onAccept`, если `value` невалиден или `laze=false`
|
|
102
|
+
* Поэтому актуальный `value` при монтировании надо получать вручную
|
|
103
|
+
*/
|
|
104
|
+
if ((_inputRef$current = inputRef.current) != null && _inputRef$current.input) {
|
|
105
|
+
prevValue.current = inputRef.current.input.value;
|
|
106
|
+
prevSelectionStart.current = inputRef.current.input.selectionStart;
|
|
107
|
+
}
|
|
108
|
+
}, []);
|
|
109
|
+
|
|
110
|
+
// useEffect(() => {
|
|
111
|
+
// inputRef.current &&
|
|
112
|
+
// (inputRef.current.selectAll = () => {
|
|
113
|
+
// setTimeout(() => {
|
|
114
|
+
// inputRef.current?.setSelectionRange(0, 999);
|
|
115
|
+
// });
|
|
116
|
+
// });
|
|
117
|
+
// }, []);
|
|
118
|
+
|
|
119
|
+
var imaskProps = getCompatibleIMaskProps();
|
|
41
120
|
|
|
42
121
|
return /*#__PURE__*/(
|
|
43
122
|
_react.default.createElement(_Input.Input, (0, _extends2.default)({
|
|
44
|
-
ref:
|
|
123
|
+
ref: inputRef },
|
|
45
124
|
inputProps, {
|
|
46
125
|
placeholder: showPlaceholder ? placeholder : undefined,
|
|
47
126
|
onFocus: handleFocus,
|
|
48
127
|
onBlur: handleBlur,
|
|
128
|
+
onInput: handleInput,
|
|
129
|
+
onMouseUp: handleSelect,
|
|
130
|
+
onKeyDownCapture: handleKeyDownCapture,
|
|
131
|
+
className: (0, _Emotion.cx)(_MaskedInput.globalClasses.root, _UiFont.uiFontGlobalClasses.root),
|
|
132
|
+
"data-tid": _MaskedInputElement.MaskedInputElementDataTids.root,
|
|
49
133
|
element: /*#__PURE__*/
|
|
50
|
-
_react.default.createElement(_MaskedInputElement.MaskedInputElement, {
|
|
51
|
-
|
|
52
|
-
maskChar: maskChar,
|
|
53
|
-
formatChars: formatChars,
|
|
54
|
-
alwaysShowMask: alwaysShowMask,
|
|
55
|
-
onUnexpectedInput: handleUnexpectedInput }) })));
|
|
134
|
+
_react.default.createElement(_MaskedInputElement.MaskedInputElement, { maskChars: getMaskChars(imaskProps) }, /*#__PURE__*/
|
|
135
|
+
_react.default.createElement(_reactImask.IMaskInput, (0, _extends2.default)({ ref: imaskRef }, imaskProps, { onAccept: handleAccept }))) })));
|
|
56
136
|
|
|
57
137
|
|
|
58
138
|
|
|
59
139
|
|
|
60
140
|
|
|
61
|
-
function
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
141
|
+
function handleSelect(e) {var _inputRef$current2;
|
|
142
|
+
if (
|
|
143
|
+
(0, _isInstanceOf.isInstanceOf)(e.target, _globalObject.globalObject.HTMLInputElement) &&
|
|
144
|
+
e.target === ((_inputRef$current2 = inputRef.current) == null ? void 0 : _inputRef$current2.input) &&
|
|
145
|
+
e.target.closest('.react-ui-masked-input-root'))
|
|
146
|
+
{var _imaskRef$current;
|
|
147
|
+
var nearest = (_imaskRef$current = imaskRef.current) == null ? void 0 : _imaskRef$current.maskRef.masked.nearestInputPos(e.target.value.length, 'LEFT');
|
|
148
|
+
if (
|
|
149
|
+
typeof e.target.selectionStart === 'number' &&
|
|
150
|
+
typeof nearest === 'number' &&
|
|
151
|
+
e.target.selectionStart >= nearest)
|
|
152
|
+
{
|
|
153
|
+
e.target.selectionStart = nearest;
|
|
154
|
+
e.target.selectionEnd = nearest;
|
|
155
|
+
}
|
|
66
156
|
}
|
|
67
157
|
}
|
|
68
158
|
|
|
69
|
-
function
|
|
159
|
+
function getCompatibleIMaskProps() {
|
|
160
|
+
return (0, _extends2.default)({
|
|
161
|
+
mask: mask.replace(/0/g, '{\\0}'),
|
|
162
|
+
placeholderChar: (0, _MaskedInput2.getMaskChar)(maskChar),
|
|
163
|
+
definitions: (0, _MaskedInput2.getDefinitions)(formatChars),
|
|
164
|
+
eager: true,
|
|
165
|
+
overwrite: 'shift',
|
|
166
|
+
lazy: alwaysShowMask === null ? true : !(alwaysShowMask || focused) },
|
|
167
|
+
customIMaskProps);
|
|
168
|
+
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function getMaskChars(imaskProps) {
|
|
172
|
+
var imaskPropsFix = imaskProps;
|
|
173
|
+
var maskChars = [imaskPropsFix.placeholderChar];
|
|
174
|
+
if (imaskPropsFix.blocks) {
|
|
175
|
+
Object.values(imaskPropsFix.blocks).forEach(
|
|
176
|
+
function (_ref) {var placeholderChar = _ref.placeholderChar;return placeholderChar && maskChars.push(placeholderChar);});
|
|
177
|
+
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return maskChars;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function handleAccept() {for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {args[_key] = arguments[_key];}
|
|
184
|
+
var value = args[0],e = args[2];
|
|
185
|
+
|
|
186
|
+
onAccept == null ? void 0 : onAccept.apply(void 0, args);
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Метод `onAccept` может вызываться при монтировании, если не задан проп `defaultValue`.
|
|
190
|
+
* Но нативный `input` никогда не вызывает `onChange` при монтировании.
|
|
191
|
+
* Наше событие `onValueChange` в `Input` вывается в тех же случаях, что и нативный `onChange`,
|
|
192
|
+
* поэтому чтобы сохранить консинстентность будем ориентироваться на наличие аргумента `e`.
|
|
193
|
+
* Он содержит нативное событие, вызвавшее изменение.
|
|
194
|
+
* Если его нет, значит `imask` вызывал `onAccept` по некой собственной логике.
|
|
195
|
+
*/
|
|
196
|
+
e && (onValueChange == null ? void 0 : onValueChange(value));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Отслеживаем неожиданные нажатия
|
|
201
|
+
* handleAccept не вызывается когда значение с маской не меняется
|
|
202
|
+
* Сначала вызывается handleAccept, затем handleInput
|
|
203
|
+
*/
|
|
204
|
+
function handleInput(e) {
|
|
205
|
+
if (prevValue.current === e.target.value && prevSelectionStart.current === e.target.selectionStart) {
|
|
206
|
+
handleUnexpectedInput(e.target.value);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
prevValue.current = e.target.value;
|
|
210
|
+
|
|
211
|
+
props.onInput == null ? void 0 : props.onInput(e);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function handleFocus(e) {var _inputRef$current3;
|
|
70
215
|
setFocused(true);
|
|
71
|
-
props.onFocus
|
|
216
|
+
props.onFocus == null ? void 0 : props.onFocus(e);
|
|
217
|
+
|
|
218
|
+
// если `value` из пропов отличается от `value`, которое получит `input` после обработки,
|
|
219
|
+
// то `imask` будет ставить курсор за последним валидным символом.
|
|
220
|
+
props.selectAllOnFocus && ((_inputRef$current3 = inputRef.current) == null ? void 0 : _inputRef$current3.delaySelectAll());
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function handleUnexpectedInput(value) {if (value === void 0) {value = '';}
|
|
224
|
+
if (onUnexpectedInput) {
|
|
225
|
+
onUnexpectedInput(value);
|
|
226
|
+
} else if (inputRef.current) {
|
|
227
|
+
inputRef.current.blink();
|
|
228
|
+
}
|
|
72
229
|
}
|
|
73
230
|
|
|
74
231
|
function handleBlur(e) {
|
|
75
232
|
setFocused(false);
|
|
76
|
-
props.onBlur
|
|
233
|
+
props.onBlur == null ? void 0 : props.onBlur(e);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function handleKeyDownCapture(e) {
|
|
237
|
+
var isDeleteKey = (0, _identifiers.someKeys)(_identifiers.isKeyBackspace, _identifiers.isKeyDelete)(e);
|
|
238
|
+
|
|
239
|
+
prevSelectionStart.current = e.currentTarget.selectionStart;
|
|
240
|
+
|
|
241
|
+
if (!e.currentTarget.value && isDeleteKey && !e.repeat) {
|
|
242
|
+
handleUnexpectedInput(e.currentTarget.value);
|
|
243
|
+
prevValue.current = e.currentTarget.value;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
onKeyDownCapture == null ? void 0 : onKeyDownCapture(e);
|
|
77
247
|
}
|
|
78
248
|
});exports.MaskedInput = MaskedInput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["MaskedInput.tsx"],"names":["MaskedInput","props","ref","mask","maskChar","formatChars","alwaysShowMask","placeholder","inputProps","focused","setFocused","showPlaceholder","innerRef","current","undefined","handleFocus","handleBlur","handleUnexpectedInput","value","onUnexpectedInput","blink","e","onFocus","onBlur"],"mappings":"8cAAA;;AAEA;;AAEA;AACA,gE;;;;;;;;;;;;;;;;;;;;;;AAsBA;AACA;AACA;AACA;AACO,IAAMA,WAAW,GAAG;AACzB,aADyB;AAEzB,SAASA,WAAT,CAAqBC,KAArB,EAA8CC,GAA9C,EAAsE;AACpE,MAAQC,IAAR,GAAoFF,KAApF,CAAQE,IAAR,CAAcC,QAAd,GAAoFH,KAApF,CAAcG,QAAd,CAAwBC,WAAxB,GAAoFJ,KAApF,CAAwBI,WAAxB,CAAqCC,cAArC,GAAoFL,KAApF,CAAqCK,cAArC,CAAqDC,WAArD,GAAoFN,KAApF,CAAqDM,WAArD,CAAqEC,UAArE,+CAAoFP,KAApF;AACA,kBAA8B,qBAAS,KAAT,CAA9B,CAAOQ,OAAP,gBAAgBC,UAAhB;AACA,MAAMC,eAAe,GAAG,EAAEL,cAAc,IAAIG,OAApB,CAAxB;AACA,MAAMG,QAAQ,GAAG,mBAAc,IAAd,CAAjB;;AAEA,kCAAoBV,GAApB,EAAyB,oBAAMU,QAAQ,CAACC,OAAf,EAAzB;;AAEA;AACE,iCAAC,YAAD;AACE,MAAA,GAAG,EAAED,QADP;AAEMJ,IAAAA,UAFN;AAGE,MAAA,WAAW,EAAEG,eAAe,GAAGJ,WAAH,GAAiBO,SAH/C;AAIE,MAAA,OAAO,EAAEC,WAJX;AAKE,MAAA,MAAM,EAAEC,UALV;AAME,MAAA,OAAO;AACL,mCAAC,sCAAD;AACE,QAAA,IAAI,EAAEb,IADR;AAEE,QAAA,QAAQ,EAAEC,QAFZ;AAGE,QAAA,WAAW,EAAEC,WAHf;AAIE,QAAA,cAAc,EAAEC,cAJlB;AAKE,QAAA,iBAAiB,EAAEW,qBALrB,GAPJ,IADF;;;;;;AAmBA,WAASA,qBAAT,CAA+BC,KAA/B,EAA8C;AAC5C,QAAIjB,KAAK,CAACkB,iBAAV,EAA6B;AAC3BlB,MAAAA,KAAK,CAACkB,iBAAN,CAAwBD,KAAxB;AACD,KAFD,MAEO,IAAIN,QAAQ,CAACC,OAAb,EAAsB;AAC3BD,MAAAA,QAAQ,CAACC,OAAT,CAAiBO,KAAjB;AACD;AACF;;AAED,WAASL,WAAT,CAAqBM,CAArB,EAA4D;AAC1DX,IAAAA,UAAU,CAAC,IAAD,CAAV;AACAT,IAAAA,KAAK,CAACqB,OAAN,IAAiBrB,KAAK,CAACqB,OAAN,CAAcD,CAAd,CAAjB;AACD;;AAED,WAASL,UAAT,CAAoBK,CAApB,EAA2D;AACzDX,IAAAA,UAAU,CAAC,KAAD,CAAV;AACAT,IAAAA,KAAK,CAACsB,MAAN,IAAgBtB,KAAK,CAACsB,MAAN,CAAaF,CAAb,CAAhB;AACD;AACF,CA9CwB,CAApB,C","sourcesContent":["import React, { Ref, useImperativeHandle, useRef, useState } from 'react';\n\nimport { Input, InputProps, InputType } from '../Input';\nimport { Nullable } from '../../typings/utility-types';\nimport { MaskedInputElement } from '../../internal/MaskedInputElement';\nimport { forwardRefAndName } from '../../lib/forwardRefAndName';\n\nexport interface MaskedProps {\n /** Паттерн маски */\n mask: string;\n /** Символ маски */\n maskChar?: Nullable<string>;\n /**\n * Словарь символов-регулярок для маски\n * @default { '9': '[0-9]', 'a': '[A-Za-z]', '*': '[A-Za-z0-9]' }\n */\n formatChars?: Record<string, string>;\n /** Показывать символы маски */\n alwaysShowMask?: boolean;\n}\n\nexport type MaskInputType = Exclude<InputType, 'number' | 'date' | 'time' | 'password'>;\n\nexport interface MaskedInputProps extends MaskedProps, Omit<InputProps, 'mask' | 'maxLength' | 'type' | 'element'> {\n type?: MaskInputType;\n}\n\n/**\n * Интерфейс пропсов наследуется от `Input`.\n * Из пропсов `Input` исключены некоторые не применимые к полю с маской пропсы и сокращен список возможных значений в type.\n */\nexport const MaskedInput = forwardRefAndName(\n 'MaskedInput',\n function MaskedInput(props: MaskedInputProps, ref: Ref<Input | null>) {\n const { mask, maskChar, formatChars, alwaysShowMask, placeholder, ...inputProps } = props;\n const [focused, setFocused] = useState(false);\n const showPlaceholder = !(alwaysShowMask || focused);\n const innerRef = useRef<Input>(null);\n\n useImperativeHandle(ref, () => innerRef.current);\n\n return (\n <Input\n ref={innerRef}\n {...inputProps}\n placeholder={showPlaceholder ? placeholder : undefined}\n onFocus={handleFocus}\n onBlur={handleBlur}\n element={\n <MaskedInputElement\n mask={mask}\n maskChar={maskChar}\n formatChars={formatChars}\n alwaysShowMask={alwaysShowMask}\n onUnexpectedInput={handleUnexpectedInput}\n />\n }\n />\n );\n\n function handleUnexpectedInput(value: string) {\n if (props.onUnexpectedInput) {\n props.onUnexpectedInput(value);\n } else if (innerRef.current) {\n innerRef.current.blink();\n }\n }\n\n function handleFocus(e: React.FocusEvent<HTMLInputElement>) {\n setFocused(true);\n props.onFocus && props.onFocus(e);\n }\n\n function handleBlur(e: React.FocusEvent<HTMLInputElement>) {\n setFocused(false);\n props.onBlur && props.onBlur(e);\n }\n },\n);\n"]}
|
|
1
|
+
{"version":3,"sources":["MaskedInput.tsx"],"names":["MaskedInput","props","ref","mask","maskChar","formatChars","alwaysShowMask","imaskProps","onAccept","customIMaskProps","placeholder","onValueChange","onUnexpectedInput","onKeyDownCapture","onChange","element","inputProps","inputRef","imaskRef","focused","setFocused","prevValue","value","String","defaultValue","prevSelectionStart","showPlaceholder","current","Object","assign","selectAll","delaySelectAll","input","selectionStart","getCompatibleIMaskProps","undefined","handleFocus","handleBlur","handleInput","handleSelect","handleKeyDownCapture","globalClasses","root","uiFontGlobalClasses","MaskedInputElementDataTids","getMaskChars","handleAccept","e","target","globalObject","HTMLInputElement","closest","nearest","maskRef","masked","nearestInputPos","length","selectionEnd","replace","placeholderChar","definitions","eager","overwrite","lazy","imaskPropsFix","maskChars","blocks","values","forEach","push","args","handleUnexpectedInput","onInput","onFocus","selectAllOnFocus","blink","onBlur","isDeleteKey","isKeyBackspace","isKeyDelete","currentTarget","repeat"],"mappings":"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","sourcesContent":["import React, { Ref, useImperativeHandle, useRef, useState, useEffect } from 'react';\nimport { InputMask, MaskedPatternOptions, MaskedPattern } from 'imask';\nimport { IMaskInput, IMaskInputProps } from 'react-imask';\nimport { globalObject } from '@skbkontur/global-object';\n\nimport { Nullable } from '../../typings/utility-types';\nimport { MaskedInputElement, MaskedInputElementDataTids } from '../../internal/MaskedInputElement';\nimport { forwardRefAndName } from '../../lib/forwardRefAndName';\nimport { cx } from '../../lib/theming/Emotion';\nimport { uiFontGlobalClasses } from '../../lib/styles/UiFont';\nimport { Input, InputProps, InputType } from '../Input';\nimport { isKeyBackspace, isKeyDelete, someKeys } from '../../lib/events/keyboard/identifiers';\nimport { isInstanceOf } from '../../lib/isInstanceOf';\n\nimport { globalClasses } from './MaskedInput.styles';\nimport { getDefinitions, getMaskChar } from './MaskedInput.helpers';\n\nexport interface MaskedProps {\n /** Паттерн маски */\n mask: string;\n /** Символ маски */\n maskChar?: Nullable<string>;\n /**\n * Словарь символов-регулярок для маски\n * @default { '9': '[0-9]', 'a': '[A-Za-z]', '*': '[A-Za-z0-9]' }\n */\n formatChars?: Record<string, string>;\n /**\n * Показывать символы маски\n *\n * null - не показывать\n * true - показывать всегда\n * false - показывать по фокусу\n */\n alwaysShowMask?: boolean | null;\n /**\n * Пропы для компонента `IMaskInput`\n *\n * @see https://imask.js.org/guide.html\n */\n imaskProps?: IMaskInputProps<HTMLInputElement>;\n}\n\nexport type MaskInputType = Exclude<InputType, 'number' | 'date' | 'time' | 'password'>;\n\nexport interface IMaskRefType {\n maskRef: InputMask<MaskedPatternOptions>;\n element: HTMLInputElement;\n}\n\nexport interface MaskedInputProps\n extends MaskedProps,\n Omit<InputProps, 'mask' | 'maxLength' | 'type' | 'alwaysShowMask'> {\n type?: MaskInputType;\n}\n\n/**\n * Интерфейс пропсов наследуется от `Input`.\n * Из пропсов `Input` исключены некоторые не применимые к полю с маской пропсы и сокращен список возможных значений в type.\n */\nexport const MaskedInput = forwardRefAndName(\n 'MaskedInput',\n function MaskedInput(props: MaskedInputProps, ref: Ref<Input | null>) {\n const {\n mask,\n maskChar,\n formatChars,\n alwaysShowMask,\n imaskProps: { onAccept, ...customIMaskProps } = {},\n placeholder,\n onValueChange,\n onUnexpectedInput,\n onKeyDownCapture,\n onChange,\n element,\n ...inputProps\n } = props;\n\n const inputRef = useRef<Input>(null);\n const imaskRef = useRef<IMaskRefType>(null);\n\n const [focused, setFocused] = useState(false);\n const prevValue = useRef<string>(props.value || String(props.defaultValue) || '');\n const prevSelectionStart = useRef<number | null>(null);\n\n const showPlaceholder = !(alwaysShowMask || focused);\n\n useImperativeHandle(\n ref,\n () =>\n inputRef.current &&\n Object.assign(inputRef.current, {\n selectAll: inputRef.current.delaySelectAll,\n }),\n [],\n );\n\n useEffect(() => {\n /**\n * Для корректной работы `onUnexpectedInput` надо знать предыдущий `value`,\n * но `imask` при монтировании не вызывает `onAccept`, если `value` невалиден или `laze=false`\n * Поэтому актуальный `value` при монтировании надо получать вручную\n */\n if (inputRef.current?.input) {\n prevValue.current = inputRef.current.input.value;\n prevSelectionStart.current = inputRef.current.input.selectionStart;\n }\n }, []);\n\n // useEffect(() => {\n // inputRef.current &&\n // (inputRef.current.selectAll = () => {\n // setTimeout(() => {\n // inputRef.current?.setSelectionRange(0, 999);\n // });\n // });\n // }, []);\n\n const imaskProps = getCompatibleIMaskProps();\n\n return (\n <Input\n ref={inputRef}\n {...inputProps}\n placeholder={showPlaceholder ? placeholder : undefined}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onInput={handleInput}\n onMouseUp={handleSelect}\n onKeyDownCapture={handleKeyDownCapture}\n className={cx(globalClasses.root, uiFontGlobalClasses.root)}\n data-tid={MaskedInputElementDataTids.root}\n element={\n <MaskedInputElement maskChars={getMaskChars(imaskProps)}>\n <IMaskInput ref={imaskRef} {...imaskProps} onAccept={handleAccept} />\n </MaskedInputElement>\n }\n />\n );\n\n function handleSelect(e: React.MouseEvent<HTMLInputElement>) {\n if (\n isInstanceOf(e.target, globalObject.HTMLInputElement) &&\n e.target === inputRef.current?.input &&\n e.target.closest('.react-ui-masked-input-root')\n ) {\n const nearest = imaskRef.current?.maskRef.masked.nearestInputPos(e.target.value.length, 'LEFT');\n if (\n typeof e.target.selectionStart === 'number' &&\n typeof nearest === 'number' &&\n e.target.selectionStart >= nearest\n ) {\n e.target.selectionStart = nearest;\n e.target.selectionEnd = nearest;\n }\n }\n }\n\n function getCompatibleIMaskProps(): IMaskInputProps<HTMLInputElement> {\n return {\n mask: mask.replace(/0/g, '{\\\\0}') as any,\n placeholderChar: getMaskChar(maskChar),\n definitions: getDefinitions(formatChars),\n eager: true,\n overwrite: 'shift',\n lazy: alwaysShowMask === null ? true : !(alwaysShowMask || focused),\n ...customIMaskProps,\n } as IMaskInputProps<HTMLInputElement>;\n }\n\n function getMaskChars(imaskProps: IMaskInputProps<HTMLInputElement>): string[] {\n const imaskPropsFix = imaskProps as MaskedPattern;\n const maskChars = [imaskPropsFix.placeholderChar];\n if (imaskPropsFix.blocks) {\n (Object.values(imaskPropsFix.blocks) as Array<{ placeholderChar?: string }>).forEach(\n ({ placeholderChar }) => placeholderChar && maskChars.push(placeholderChar),\n );\n }\n\n return maskChars;\n }\n\n function handleAccept(...args: Parameters<Required<IMaskInputProps<HTMLInputElement>>['onAccept']>) {\n const [value, , e] = args;\n\n onAccept?.(...args);\n\n /**\n * Метод `onAccept` может вызываться при монтировании, если не задан проп `defaultValue`.\n * Но нативный `input` никогда не вызывает `onChange` при монтировании.\n * Наше событие `onValueChange` в `Input` вывается в тех же случаях, что и нативный `onChange`,\n * поэтому чтобы сохранить консинстентность будем ориентироваться на наличие аргумента `e`.\n * Он содержит нативное событие, вызвавшее изменение.\n * Если его нет, значит `imask` вызывал `onAccept` по некой собственной логике.\n */\n e && onValueChange?.(value);\n }\n\n /**\n * Отслеживаем неожиданные нажатия\n * handleAccept не вызывается когда значение с маской не меняется\n * Сначала вызывается handleAccept, затем handleInput\n */\n function handleInput(e: React.ChangeEvent<HTMLInputElement>) {\n if (prevValue.current === e.target.value && prevSelectionStart.current === e.target.selectionStart) {\n handleUnexpectedInput(e.target.value);\n }\n\n prevValue.current = e.target.value;\n\n props.onInput?.(e);\n }\n\n function handleFocus(e: React.FocusEvent<HTMLInputElement>) {\n setFocused(true);\n props.onFocus?.(e);\n\n // если `value` из пропов отличается от `value`, которое получит `input` после обработки,\n // то `imask` будет ставить курсор за последним валидным символом.\n props.selectAllOnFocus && inputRef.current?.delaySelectAll();\n }\n\n function handleUnexpectedInput(value = '') {\n if (onUnexpectedInput) {\n onUnexpectedInput(value);\n } else if (inputRef.current) {\n inputRef.current.blink();\n }\n }\n\n function handleBlur(e: React.FocusEvent<HTMLInputElement>) {\n setFocused(false);\n props.onBlur?.(e);\n }\n\n function handleKeyDownCapture(e: React.KeyboardEvent<HTMLInputElement>) {\n const isDeleteKey = someKeys(isKeyBackspace, isKeyDelete)(e);\n\n prevSelectionStart.current = e.currentTarget.selectionStart;\n\n if (!e.currentTarget.value && isDeleteKey && !e.repeat) {\n handleUnexpectedInput(e.currentTarget.value);\n prevValue.current = e.currentTarget.value;\n }\n\n onKeyDownCapture?.(e);\n }\n },\n);\n"]}
|
|
@@ -1,21 +1,185 @@
|
|
|
1
|
+
#### `mask`
|
|
2
|
+
|
|
3
|
+
Маска телефона
|
|
4
|
+
|
|
5
|
+
```jsx harmony
|
|
6
|
+
const [value, setValue] = React.useState('123');
|
|
7
|
+
|
|
8
|
+
<MaskedInput
|
|
9
|
+
mask="+7 999-999-99-99"
|
|
10
|
+
alwaysShowMask
|
|
11
|
+
value={value}
|
|
12
|
+
onValueChange={setValue}
|
|
13
|
+
/>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
#### `maskChar`
|
|
17
|
+
|
|
18
|
+
может изменить символ значения с маской
|
|
19
|
+
|
|
20
|
+
```jsx harmony
|
|
21
|
+
<MaskedInput
|
|
22
|
+
mask="9999 9999 9999 9999"
|
|
23
|
+
maskChar="X"
|
|
24
|
+
placeholder="Номер карты"
|
|
25
|
+
alwaysShowMask
|
|
26
|
+
/>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
#### `formatChars`
|
|
30
|
+
|
|
31
|
+
При необходимости можно настроить собственный словарь.
|
|
32
|
+
|
|
33
|
+
Возможности `imaskProps.blocks` намного шире. Смотрите пример ниже.
|
|
34
|
+
|
|
35
|
+
```jsx harmony
|
|
36
|
+
const [value, setValue] = React.useState('');
|
|
37
|
+
|
|
38
|
+
<MaskedInput
|
|
39
|
+
mask="Hh:Mm:Ss"
|
|
40
|
+
alwaysShowMask
|
|
41
|
+
formatChars={{
|
|
42
|
+
H: '[0-2]',
|
|
43
|
+
h: value.startsWith('2') ? '[0-3]' : '[0-9]',
|
|
44
|
+
M: '[0-5]',
|
|
45
|
+
m: '[0-9]',
|
|
46
|
+
S: '[0-5]',
|
|
47
|
+
s: '[0-9]',
|
|
48
|
+
}}
|
|
49
|
+
value={value}
|
|
50
|
+
onValueChange={setValue}
|
|
51
|
+
/>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
#### `alwaysShowMask`
|
|
55
|
+
|
|
56
|
+
Показывает маску всегда. Placeholder в этом случае игнорируется.
|
|
57
|
+
Логика немного отличается от старой реализации, из-за специфики iMask.
|
|
58
|
+
Раньше маска обязательно появлялась при фокусе, но теперь чтобы маску было видно надо явно задать этот проп.
|
|
59
|
+
|
|
60
|
+
```jsx harmony
|
|
61
|
+
<MaskedInput mask="+7 (999) 999-99-99" alwaysShowMask placeholder="Номер телефона" />
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
#### `imaskProps`*
|
|
65
|
+
|
|
66
|
+
Переопределяет пропы iMask.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
Контрол используется внутри пакет [iMask](https://imask.js.org/). Пропы `mask`, `maskChar` и `formatChars` прокидываются
|
|
71
|
+
с необходимыми доработками. Также для обратной совместимости со старым поведением добавляется несколько других пропов.
|
|
72
|
+
|
|
73
|
+
Обратите внимание, что в `definitions` попадает **`0: /\d/`**. Это дефолтное поле, которое нельзя удалить. Но в старой
|
|
74
|
+
реализации `0` считался фиксированным символом, из-за чего приходится немного редактировать маску.
|
|
75
|
+
|
|
76
|
+
Конвертация пропов выглядит примерно так:
|
|
77
|
+
|
|
78
|
+
```typescript static
|
|
79
|
+
mask: mask.replace(/0/g, '{\\0}'),
|
|
80
|
+
placeholderChar: props.maskChar || '_',
|
|
81
|
+
definitions: props.formatChars || { '9': /[0-9]/, a: /[A-Za-z]/, '*': /[A-Za-z0-9]/ },
|
|
82
|
+
eager: true,
|
|
83
|
+
overwrite: 'shift',
|
|
84
|
+
lazy: !alwaysShowMask,
|
|
85
|
+
...props.imaskProps,
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
##### `imaskProps.unmask`
|
|
91
|
+
|
|
92
|
+
Можно сразу получать value без фиксированных символов маски
|
|
93
|
+
|
|
1
94
|
```jsx harmony
|
|
2
|
-
|
|
95
|
+
const [value, setValue] = React.useState('');
|
|
96
|
+
|
|
97
|
+
<>
|
|
98
|
+
<span>unmask value: {value}</span>
|
|
99
|
+
<br />
|
|
100
|
+
<MaskedInput
|
|
101
|
+
mask="+7 (999) 999-99-99"
|
|
102
|
+
imaskProps={{
|
|
103
|
+
unmask: true
|
|
104
|
+
}}
|
|
105
|
+
alwaysShowMask
|
|
106
|
+
value={value}
|
|
107
|
+
onValueChange={setValue}
|
|
108
|
+
/>
|
|
109
|
+
</>
|
|
3
110
|
```
|
|
4
111
|
|
|
5
|
-
|
|
112
|
+
##### `imaskProps.mask []`
|
|
113
|
+
|
|
114
|
+
Опциональные части маски
|
|
115
|
+
|
|
6
116
|
```jsx harmony
|
|
7
|
-
|
|
117
|
+
const [value, setValue] = React.useState('');
|
|
118
|
+
const [complete, setComplete] = React.useState(false);
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
<MaskedInput
|
|
122
|
+
mask="99-999999[99]-99"
|
|
123
|
+
alwaysShowMask
|
|
124
|
+
rightIcon={complete ? '✅' : '⬜'}
|
|
125
|
+
imaskProps={{
|
|
126
|
+
onAccept: (v, imask) => {
|
|
127
|
+
setValue(v);
|
|
128
|
+
setComplete(imask.masked.isComplete);
|
|
129
|
+
}
|
|
130
|
+
}}
|
|
131
|
+
/>
|
|
8
132
|
```
|
|
9
133
|
|
|
10
|
-
|
|
134
|
+
##### `imaskProps.mask {}`
|
|
135
|
+
|
|
136
|
+
Фиксированные части маски, которые попадут в `value` при `unmask = true`. Любой невалидный символ (например`пробел`) переведёт каретку за фиксированный символ.
|
|
137
|
+
|
|
11
138
|
```jsx harmony
|
|
12
|
-
|
|
139
|
+
const [value, setValue] = React.useState('');
|
|
140
|
+
const [complete, setComplete] = React.useState(false);
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
<>
|
|
144
|
+
<span>unmask value: {value}</span>
|
|
145
|
+
<br />
|
|
146
|
+
<MaskedInput
|
|
147
|
+
mask="aa[aaaaaaaaaaaaaaaaa]{@}aa[aaaaaaaaaaaaaaaaa]{\.}aa[aaaa]"
|
|
148
|
+
alwaysShowMask
|
|
149
|
+
rightIcon={complete ? '✅' : '⬜'}
|
|
150
|
+
imaskProps={{
|
|
151
|
+
unmask: true,
|
|
152
|
+
onAccept: (v, imask) => {
|
|
153
|
+
setValue(v);
|
|
154
|
+
setComplete(imask.masked.isComplete);
|
|
155
|
+
}
|
|
156
|
+
}}
|
|
157
|
+
/>
|
|
158
|
+
</>
|
|
13
159
|
```
|
|
14
160
|
|
|
15
|
-
|
|
161
|
+
##### `imaskProps.blocks`
|
|
16
162
|
|
|
17
|
-
|
|
163
|
+
Пример маски времени. Нажмите цифру `6`, чтобы сработало автозаполнение.
|
|
18
164
|
|
|
19
|
-
|
|
165
|
+
```jsx harmony
|
|
166
|
+
import IMask from 'imask';
|
|
20
167
|
|
|
21
|
-
|
|
168
|
+
const block = {
|
|
169
|
+
mask: IMask.MaskedRange,
|
|
170
|
+
from: 0,
|
|
171
|
+
autofix: 'pad',
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
<MaskedInput
|
|
175
|
+
mask="HH:MM:SS"
|
|
176
|
+
imaskProps={{
|
|
177
|
+
blocks: {
|
|
178
|
+
HH: { ...block, to: 23, },
|
|
179
|
+
MM: { ...block, to: 59, },
|
|
180
|
+
SS: { ...block, to: 59, },
|
|
181
|
+
}
|
|
182
|
+
}}
|
|
183
|
+
alwaysShowMask
|
|
184
|
+
/>
|
|
185
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["MaskedInput.styles.ts"],"names":["globalClasses","root"],"mappings":"sEAAA;;AAEO,IAAMA,aAAa,GAAG,qBAAO,cAAP,EAAuB;AAClDC,EAAAA,IAAI,EAAE,MAD4C,EAAvB,CAAtB,C","sourcesContent":["import { prefix } from '../../lib/theming/Emotion';\n\nexport const globalClasses = prefix('masked-input')({\n root: 'root',\n});\n"]}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
```jsx harmony
|
|
2
|
-
import { Gapped, Radio } from '@skbkontur/react-ui';
|
|
3
|
-
|
|
4
|
-
let items = ['One', 'Two', 'Three', 'Four'];
|
|
5
|
-
|
|
6
|
-
let simpleRadioGroup = (
|
|
7
|
-
<div>
|
|
8
|
-
<h2>Numbers</h2>
|
|
9
|
-
<RadioGroup name="number-simple" items={items} defaultValue="One" />
|
|
10
|
-
</div>
|
|
11
|
-
);
|
|
12
|
-
|
|
13
|
-
let complexRadioGroup = (
|
|
14
|
-
<div>
|
|
15
|
-
<h2>Numbers</h2>
|
|
16
|
-
<RadioGroup name="number-complex" defaultValue="3">
|
|
17
|
-
<Gapped gap={40}>
|
|
18
|
-
<Gapped vertical gap={0}>
|
|
19
|
-
<b>Odd</b>
|
|
20
|
-
<Radio value="1">One</Radio>
|
|
21
|
-
<Radio value="3">Three</Radio>
|
|
22
|
-
<Radio value="5" disabled>
|
|
23
|
-
Five
|
|
24
|
-
</Radio>
|
|
25
|
-
<Radio value="7">Seven</Radio>
|
|
26
|
-
</Gapped>
|
|
27
|
-
<Gapped vertical gap={0}>
|
|
28
|
-
<b>Even</b>
|
|
29
|
-
<Radio value="2">Two</Radio>
|
|
30
|
-
<Radio value="4">Four</Radio>
|
|
31
|
-
<Radio value="6">Six</Radio>
|
|
32
|
-
<Radio value="8">Eight</Radio>
|
|
33
|
-
</Gapped>
|
|
34
|
-
</Gapped>
|
|
35
|
-
</RadioGroup>
|
|
36
|
-
</div>
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
<div>
|
|
40
|
-
{simpleRadioGroup}
|
|
41
|
-
{complexRadioGroup}
|
|
42
|
-
</div>;
|
|
43
|
-
```
|
|
1
|
+
```jsx harmony
|
|
2
|
+
import { Gapped, Radio } from '@skbkontur/react-ui';
|
|
3
|
+
|
|
4
|
+
let items = ['One', 'Two', 'Three', 'Four'];
|
|
5
|
+
|
|
6
|
+
let simpleRadioGroup = (
|
|
7
|
+
<div>
|
|
8
|
+
<h2>Numbers</h2>
|
|
9
|
+
<RadioGroup name="number-simple" items={items} defaultValue="One" />
|
|
10
|
+
</div>
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
let complexRadioGroup = (
|
|
14
|
+
<div>
|
|
15
|
+
<h2>Numbers</h2>
|
|
16
|
+
<RadioGroup name="number-complex" defaultValue="3">
|
|
17
|
+
<Gapped gap={40}>
|
|
18
|
+
<Gapped vertical gap={0}>
|
|
19
|
+
<b>Odd</b>
|
|
20
|
+
<Radio value="1">One</Radio>
|
|
21
|
+
<Radio value="3">Three</Radio>
|
|
22
|
+
<Radio value="5" disabled>
|
|
23
|
+
Five
|
|
24
|
+
</Radio>
|
|
25
|
+
<Radio value="7">Seven</Radio>
|
|
26
|
+
</Gapped>
|
|
27
|
+
<Gapped vertical gap={0}>
|
|
28
|
+
<b>Even</b>
|
|
29
|
+
<Radio value="2">Two</Radio>
|
|
30
|
+
<Radio value="4">Four</Radio>
|
|
31
|
+
<Radio value="6">Six</Radio>
|
|
32
|
+
<Radio value="8">Eight</Radio>
|
|
33
|
+
</Gapped>
|
|
34
|
+
</Gapped>
|
|
35
|
+
</RadioGroup>
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
<div>
|
|
40
|
+
{simpleRadioGroup}
|
|
41
|
+
{complexRadioGroup}
|
|
42
|
+
</div>;
|
|
43
|
+
```
|
package/cjs/index.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ export * from './components/TokenInput';
|
|
|
45
45
|
export * from './components/Tooltip';
|
|
46
46
|
export * from './components/TooltipMenu';
|
|
47
47
|
export * from './components/ResponsiveLayout';
|
|
48
|
+
export * from './components/MaskedInput';
|
|
48
49
|
export * from './lib/featureFlagsContext';
|
|
49
50
|
export * from './lib/locale';
|
|
50
51
|
export * from './lib/theming/ThemeContext';
|
|
@@ -55,6 +56,8 @@ export * from './lib/theming/themes/DefaultTheme8pxOld';
|
|
|
55
56
|
export * from './lib/theming/themes/FlatTheme8pxOld';
|
|
56
57
|
export * from './lib/theming/themes/Theme2022';
|
|
57
58
|
export * from './lib/theming/themes/Theme2022Dark';
|
|
59
|
+
export * from './lib/theming/themes/Theme2022Update2024';
|
|
60
|
+
export * from './lib/theming/themes/Theme2022DarkUpdate2024';
|
|
58
61
|
export * from './lib/types/props';
|
|
59
62
|
export * from './internal/Popup/types';
|
|
60
63
|
export * as ColorFunctions from './lib/styles/ColorFunctions';
|
package/cjs/index.js
CHANGED
|
@@ -45,6 +45,7 @@ var _TokenInput = require("./components/TokenInput");Object.keys(_TokenInput).fo
|
|
|
45
45
|
var _Tooltip = require("./components/Tooltip");Object.keys(_Tooltip).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _Tooltip[key]) return;exports[key] = _Tooltip[key];});
|
|
46
46
|
var _TooltipMenu = require("./components/TooltipMenu");Object.keys(_TooltipMenu).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _TooltipMenu[key]) return;exports[key] = _TooltipMenu[key];});
|
|
47
47
|
var _ResponsiveLayout = require("./components/ResponsiveLayout");Object.keys(_ResponsiveLayout).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _ResponsiveLayout[key]) return;exports[key] = _ResponsiveLayout[key];});
|
|
48
|
+
var _MaskedInput = require("./components/MaskedInput");Object.keys(_MaskedInput).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _MaskedInput[key]) return;exports[key] = _MaskedInput[key];});
|
|
48
49
|
var _featureFlagsContext = require("./lib/featureFlagsContext");Object.keys(_featureFlagsContext).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _featureFlagsContext[key]) return;exports[key] = _featureFlagsContext[key];});
|
|
49
50
|
var _locale = require("./lib/locale");Object.keys(_locale).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _locale[key]) return;exports[key] = _locale[key];});
|
|
50
51
|
var _ThemeContext = require("./lib/theming/ThemeContext");Object.keys(_ThemeContext).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _ThemeContext[key]) return;exports[key] = _ThemeContext[key];});
|
|
@@ -55,5 +56,7 @@ var _DefaultTheme8pxOld = require("./lib/theming/themes/DefaultTheme8pxOld");Obj
|
|
|
55
56
|
var _FlatTheme8pxOld = require("./lib/theming/themes/FlatTheme8pxOld");Object.keys(_FlatTheme8pxOld).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _FlatTheme8pxOld[key]) return;exports[key] = _FlatTheme8pxOld[key];});
|
|
56
57
|
var _Theme = require("./lib/theming/themes/Theme2022");Object.keys(_Theme).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _Theme[key]) return;exports[key] = _Theme[key];});
|
|
57
58
|
var _Theme2022Dark = require("./lib/theming/themes/Theme2022Dark");Object.keys(_Theme2022Dark).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _Theme2022Dark[key]) return;exports[key] = _Theme2022Dark[key];});
|
|
59
|
+
var _Theme2022Update = require("./lib/theming/themes/Theme2022Update2024");Object.keys(_Theme2022Update).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _Theme2022Update[key]) return;exports[key] = _Theme2022Update[key];});
|
|
60
|
+
var _Theme2022DarkUpdate = require("./lib/theming/themes/Theme2022DarkUpdate2024");Object.keys(_Theme2022DarkUpdate).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _Theme2022DarkUpdate[key]) return;exports[key] = _Theme2022DarkUpdate[key];});
|
|
58
61
|
var _props = require("./lib/types/props");Object.keys(_props).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _props[key]) return;exports[key] = _props[key];});
|
|
59
62
|
var _types = require("./internal/Popup/types");Object.keys(_types).forEach(function (key) {if (key === "default" || key === "__esModule") return;if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;if (key in exports && exports[key] === _types[key]) return;exports[key] = _types[key];});var _ColorFunctions = _interopRequireWildcard(require("./lib/styles/ColorFunctions"));exports.ColorFunctions = _ColorFunctions;var _DimensionFunctions = _interopRequireWildcard(require("./lib/styles/DimensionFunctions"));exports.DimensionFunctions = _DimensionFunctions;
|