rsuite 5.0.3 → 5.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.
- package/CHANGELOG.md +17 -0
- package/MaskedInput/package.json +7 -0
- package/README.md +1 -1
- package/Toggle/styles/index.less +20 -0
- package/Toggle/styles/mixin.less +12 -0
- package/cjs/DOMHelper/index.d.ts +1 -1
- package/cjs/DatePicker/DatePicker.js +3 -2
- package/cjs/DateRangePicker/DateRangePicker.js +3 -2
- package/cjs/Dropdown/DropdownItem.js +23 -16
- package/cjs/MaskedInput/MaskedInput.d.ts +43 -0
- package/cjs/MaskedInput/MaskedInput.js +80 -0
- package/cjs/MaskedInput/adjustCaretPosition.d.ts +11 -0
- package/cjs/MaskedInput/adjustCaretPosition.js +218 -0
- package/cjs/MaskedInput/conformToMask.d.ts +8 -0
- package/cjs/MaskedInput/conformToMask.js +247 -0
- package/cjs/MaskedInput/createTextMaskInputElement.d.ts +7 -0
- package/cjs/MaskedInput/createTextMaskInputElement.js +226 -0
- package/cjs/MaskedInput/index.d.ts +3 -0
- package/cjs/MaskedInput/index.js +11 -0
- package/cjs/MaskedInput/types.d.ts +10 -0
- package/cjs/{@types/icons.js → MaskedInput/types.js} +0 -0
- package/cjs/MaskedInput/utilities.d.ts +7 -0
- package/cjs/MaskedInput/utilities.js +47 -0
- package/cjs/Overlay/positionUtils.js +1 -1
- package/cjs/Picker/PickerToggle.js +3 -3
- package/cjs/Toggle/Toggle.d.ts +2 -0
- package/cjs/Toggle/Toggle.js +23 -5
- package/cjs/index.d.ts +2 -0
- package/cjs/index.js +5 -1
- package/cjs/locales/fa_IR.d.ts +105 -0
- package/cjs/locales/fa_IR.js +84 -0
- package/cjs/locales/index.d.ts +1 -0
- package/cjs/locales/index.js +6 -2
- package/dist/rsuite-rtl.css +58 -0
- package/dist/rsuite-rtl.min.css +1 -1
- package/dist/rsuite-rtl.min.css.map +1 -1
- package/dist/rsuite.css +58 -0
- package/dist/rsuite.js +79 -23
- package/dist/rsuite.js.map +1 -1
- package/dist/rsuite.min.css +1 -1
- package/dist/rsuite.min.css.map +1 -1
- package/dist/rsuite.min.js +1 -1
- package/dist/rsuite.min.js.map +1 -1
- package/esm/DOMHelper/index.d.ts +1 -1
- package/esm/DatePicker/DatePicker.js +3 -2
- package/esm/DateRangePicker/DateRangePicker.js +3 -2
- package/esm/Dropdown/DropdownItem.js +23 -16
- package/esm/MaskedInput/MaskedInput.d.ts +43 -0
- package/esm/MaskedInput/MaskedInput.js +67 -0
- package/esm/MaskedInput/adjustCaretPosition.d.ts +11 -0
- package/esm/MaskedInput/adjustCaretPosition.js +213 -0
- package/esm/MaskedInput/conformToMask.d.ts +8 -0
- package/esm/MaskedInput/conformToMask.js +239 -0
- package/esm/MaskedInput/createTextMaskInputElement.d.ts +7 -0
- package/esm/MaskedInput/createTextMaskInputElement.js +212 -0
- package/esm/MaskedInput/index.d.ts +3 -0
- package/esm/MaskedInput/index.js +2 -0
- package/esm/MaskedInput/types.d.ts +10 -0
- package/esm/{@types/icons.js → MaskedInput/types.js} +0 -0
- package/esm/MaskedInput/utilities.d.ts +7 -0
- package/esm/MaskedInput/utilities.js +38 -0
- package/esm/Overlay/positionUtils.js +1 -1
- package/esm/Picker/PickerToggle.js +1 -1
- package/esm/Toggle/Toggle.d.ts +2 -0
- package/esm/Toggle/Toggle.js +22 -5
- package/esm/index.d.ts +2 -0
- package/esm/index.js +1 -0
- package/esm/locales/fa_IR.d.ts +105 -0
- package/esm/locales/fa_IR.js +74 -0
- package/esm/locales/index.d.ts +1 -0
- package/esm/locales/index.js +2 -1
- package/locales/fa_IR/package.json +7 -0
- package/package.json +3 -4
- package/styles/color-modes/light.less +2 -0
- package/cjs/@types/icons.d.ts +0 -1
- package/esm/@types/icons.d.ts +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# [5.1.0](https://github.com/rsuite/rsuite/compare/v5.0.3...v5.1.0) (2021-10-29)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- **DatePicker:** fix DatePicker does not change value after pressing enter ([#2055](https://github.com/rsuite/rsuite/issues/2055)) ([c775444](https://github.com/rsuite/rsuite/commit/c7754445763f2553a3cc50e195b1dc347f774415))
|
|
6
|
+
- **DateRangePicker:** fix DateRangePicker does not change value after pressing enter ([#2056](https://github.com/rsuite/rsuite/issues/2056)) ([8e5db2e](https://github.com/rsuite/rsuite/commit/8e5db2e54d8e6ad79f7219dc69cd1f52f32a8295))
|
|
7
|
+
- **Dropdown.Item:** item inside Nav not pass "as" ([#2026](https://github.com/rsuite/rsuite/issues/2026)) ([34bfffd](https://github.com/rsuite/rsuite/commit/34bfffdbcd353753912b30b38523e3b62f430e98)), closes [#2025](https://github.com/rsuite/rsuite/issues/2025)
|
|
8
|
+
- **Dropdown.Item:** render custom element inside li ([#2044](https://github.com/rsuite/rsuite/issues/2044)) ([a2e8a00](https://github.com/rsuite/rsuite/commit/a2e8a00c94f77028ed489a65f970264eeb9551ea))
|
|
9
|
+
- **Overlay:** fix position offset inside container ([#2049](https://github.com/rsuite/rsuite/issues/2049)) ([c27b19e](https://github.com/rsuite/rsuite/commit/c27b19e9c9ec0191ccf5d36d9efe6b176b0b6d84))
|
|
10
|
+
- **Toggle:** improve a11y (keyboard focusable + keyboard events) ([#2032](https://github.com/rsuite/rsuite/issues/2032)) ([9fdfd52](https://github.com/rsuite/rsuite/commit/9fdfd52e1eab3ad3e93569112e33ad3490335fbd))
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
- **locales:** Created fa_IR locale to add support of Persian language in Rsuite locals ([#2061](https://github.com/rsuite/rsuite/issues/2061)) ([14e5946](https://github.com/rsuite/rsuite/commit/14e59466cfd285ec1098d67280338a7df1ef8f5f))
|
|
15
|
+
- **MaskedInput:** added support for MaskedInput to replace `react-text-mask` ([#2054](https://github.com/rsuite/rsuite/issues/2054)) ([496416a](https://github.com/rsuite/rsuite/commit/496416a2e4b32362252ef70f5c4e40f785ecf5be))
|
|
16
|
+
- **Toggle:** add loading prop ([#2031](https://github.com/rsuite/rsuite/issues/2031)) ([28778de](https://github.com/rsuite/rsuite/commit/28778de0af0495a1bb68479bf3c679413255ce7b))
|
|
17
|
+
|
|
1
18
|
## [5.0.3](https://github.com/rsuite/rsuite/compare/v5.0.2...v5.0.3) (2021-10-22)
|
|
2
19
|
|
|
3
20
|
### Bug Fixes
|
package/README.md
CHANGED
|
@@ -187,7 +187,7 @@ React Suite is [MIT licensed][license]. Copyright (c) 2016-present, HYPERS.
|
|
|
187
187
|
[discord-svg]: https://img.shields.io/badge/Discord-Join%20chat%20%E2%86%92-738bd7.svg
|
|
188
188
|
[discord-invite]: https://discord.gg/R8mnjwh
|
|
189
189
|
[rsuite-design]: https://rsuitejs.com/design/default
|
|
190
|
-
[live-preview-on-codesandbox]: https://codesandbox.io/s/
|
|
190
|
+
[live-preview-on-codesandbox]: https://codesandbox.io/s/rsuite-template-5vq6zo2z5l
|
|
191
191
|
[rsuite-doc-guide]: https://rsuitejs.com/en/guide/introduction
|
|
192
192
|
[rsuite-doc-guide-themes]: https://rsuitejs.com/en/guide/themes
|
|
193
193
|
[rsuite-doc-guide-intl]: https://rsuitejs.com/en/guide/intl
|
package/Toggle/styles/index.less
CHANGED
|
@@ -32,6 +32,20 @@
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// The switch thumb
|
|
35
|
+
&-loader {
|
|
36
|
+
position: absolute;
|
|
37
|
+
transition: left @toggle-transition, margin-left @toggle-transition, width @toggle-transition;
|
|
38
|
+
|
|
39
|
+
.rs-loader-spin {
|
|
40
|
+
&::before {
|
|
41
|
+
border-color: var(--rs-toggle-loader-ring);
|
|
42
|
+
}
|
|
43
|
+
&::after {
|
|
44
|
+
border-top-color: var(--rs-toggle-loader-rotor);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
35
49
|
&::after {
|
|
36
50
|
content: '';
|
|
37
51
|
cursor: pointer;
|
|
@@ -67,6 +81,12 @@
|
|
|
67
81
|
background-color: var(--rs-toggle-checked-disabled-bg);
|
|
68
82
|
color: var(--rs-toggle-checked-disabled-thumb);
|
|
69
83
|
}
|
|
84
|
+
|
|
85
|
+
&&-loading {
|
|
86
|
+
&::after {
|
|
87
|
+
display: none;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
70
90
|
}
|
|
71
91
|
|
|
72
92
|
// Label text inside the switch
|
package/Toggle/styles/mixin.less
CHANGED
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
min-width: @min-width;
|
|
6
6
|
border-radius: (@toogle-height / 2);
|
|
7
7
|
|
|
8
|
+
&-loader {
|
|
9
|
+
width: @handle-diameter;
|
|
10
|
+
height: @handle-diameter;
|
|
11
|
+
left: @toggle-handle-gap;
|
|
12
|
+
top: @toggle-handle-gap;
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
&::after {
|
|
9
16
|
width: @handle-diameter;
|
|
10
17
|
height: @handle-diameter;
|
|
@@ -44,6 +51,11 @@
|
|
|
44
51
|
margin-left: @toggle-inner-margin;
|
|
45
52
|
}
|
|
46
53
|
}
|
|
54
|
+
|
|
55
|
+
&.rs-btn-toggle-checked &-loader {
|
|
56
|
+
left: 100%;
|
|
57
|
+
margin-left: -(@handle-diameter + @toggle-handle-gap);
|
|
58
|
+
}
|
|
47
59
|
}
|
|
48
60
|
|
|
49
61
|
// Small
|
package/cjs/DOMHelper/index.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ declare const DOMHelper: {
|
|
|
46
46
|
} | DOMRect;
|
|
47
47
|
nodeName: (node: Element) => string;
|
|
48
48
|
getOffsetParent: (node: Element) => Element;
|
|
49
|
-
getPosition: (node: Element, offsetParent?: Element) => DOMRect | {
|
|
49
|
+
getPosition: (node: Element, offsetParent?: Element, calcMargin?: boolean) => DOMRect | {
|
|
50
50
|
top: number;
|
|
51
51
|
left: number;
|
|
52
52
|
height: number;
|
|
@@ -328,7 +328,7 @@ var DatePicker = /*#__PURE__*/_react.default.forwardRef(function (props, ref) {
|
|
|
328
328
|
* The callback after the enter key is triggered on the input
|
|
329
329
|
*/
|
|
330
330
|
|
|
331
|
-
var
|
|
331
|
+
var handleInputPressEnd = (0, _react.useCallback)(function (event) {
|
|
332
332
|
if (inputState === 'Typing') {
|
|
333
333
|
updateValue(event, calendarDate);
|
|
334
334
|
}
|
|
@@ -460,7 +460,8 @@ var DatePicker = /*#__PURE__*/_react.default.forwardRef(function (props, ref) {
|
|
|
460
460
|
inputPlaceholder: typeof placeholder === 'string' && placeholder ? placeholder : formatStr,
|
|
461
461
|
inputMask: _utils.DateUtils.getDateMask(formatStr),
|
|
462
462
|
onInputChange: handleInputChange,
|
|
463
|
-
onInputBlur:
|
|
463
|
+
onInputBlur: handleInputPressEnd,
|
|
464
|
+
onInputPressEnter: handleInputPressEnd,
|
|
464
465
|
onKeyDown: onPickerKeyDown,
|
|
465
466
|
onClean: (0, _utils.createChainedFunction)(handleClean, onClean),
|
|
466
467
|
cleanable: cleanable && !disabled,
|
|
@@ -426,7 +426,7 @@ var DateRangePicker = /*#__PURE__*/_react.default.forwardRef(function (props, re
|
|
|
426
426
|
* The callback after the enter key is triggered on the input
|
|
427
427
|
*/
|
|
428
428
|
|
|
429
|
-
var
|
|
429
|
+
var handleInputPressEnd = (0, _react.useCallback)(function (event) {
|
|
430
430
|
if (inputState === 'Typing') {
|
|
431
431
|
handleValueUpdate(event, selectValue);
|
|
432
432
|
}
|
|
@@ -602,7 +602,8 @@ var DateRangePicker = /*#__PURE__*/_react.default.forwardRef(function (props, re
|
|
|
602
602
|
inputValue: value ? getDisplayString(value, true) : '',
|
|
603
603
|
inputPlaceholder: typeof placeholder === 'string' && placeholder ? placeholder : rangeFormatStr,
|
|
604
604
|
onInputChange: handleInputChange,
|
|
605
|
-
onInputBlur:
|
|
605
|
+
onInputBlur: handleInputPressEnd,
|
|
606
|
+
onInputPressEnter: handleInputPressEnd,
|
|
606
607
|
onKeyDown: onPickerKeyDown,
|
|
607
608
|
onClean: (0, _utils.createChainedFunction)(handleClean, onClean),
|
|
608
609
|
cleanable: cleanable && !disabled,
|
|
@@ -54,7 +54,13 @@ var DropdownItem = /*#__PURE__*/_react.default.forwardRef(function (props, ref)
|
|
|
54
54
|
eventKey = props.eventKey,
|
|
55
55
|
onSelect = props.onSelect,
|
|
56
56
|
icon = props.icon,
|
|
57
|
-
|
|
57
|
+
_props$as = props.as,
|
|
58
|
+
Component = _props$as === void 0 ? 'li' : _props$as,
|
|
59
|
+
divider = props.divider,
|
|
60
|
+
panel = props.panel,
|
|
61
|
+
children = props.children,
|
|
62
|
+
disabled = props.disabled,
|
|
63
|
+
restProps = (0, _objectWithoutPropertiesLoose2.default)(props, ["classPrefix", "className", "active", "eventKey", "onSelect", "icon", "as", "divider", "panel", "children", "disabled"]);
|
|
58
64
|
var internalId = (0, _useInternalId.default)('DropdownItem');
|
|
59
65
|
var nav = (0, _react.useContext)(_NavContext.default);
|
|
60
66
|
var dropdown = (0, _react.useContext)(_DropdownContext.default);
|
|
@@ -106,6 +112,15 @@ var DropdownItem = /*#__PURE__*/_react.default.forwardRef(function (props, ref)
|
|
|
106
112
|
};
|
|
107
113
|
}
|
|
108
114
|
}, [internalId, selected, dispatch]);
|
|
115
|
+
var renderDropdownItem = (0, _react.useCallback)(function (ui) {
|
|
116
|
+
if (Component === 'li') {
|
|
117
|
+
return ui;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return /*#__PURE__*/_react.default.createElement("li", {
|
|
121
|
+
role: "none presentation"
|
|
122
|
+
}, ui);
|
|
123
|
+
}, [Component]);
|
|
109
124
|
|
|
110
125
|
if (sidenav !== null && sidenav !== void 0 && sidenav.expanded) {
|
|
111
126
|
return /*#__PURE__*/_react.default.createElement(_SidenavDropdownItem.default, (0, _extends2.default)({
|
|
@@ -113,28 +128,19 @@ var DropdownItem = /*#__PURE__*/_react.default.forwardRef(function (props, ref)
|
|
|
113
128
|
}, props));
|
|
114
129
|
}
|
|
115
130
|
|
|
116
|
-
var _rest$as = rest.as,
|
|
117
|
-
Component = _rest$as === void 0 ? 'li' : _rest$as,
|
|
118
|
-
divider = rest.divider,
|
|
119
|
-
panel = rest.panel,
|
|
120
|
-
children = rest.children,
|
|
121
|
-
disabled = rest.disabled,
|
|
122
|
-
restProps = (0, _objectWithoutPropertiesLoose2.default)(rest, ["as", "divider", "panel", "children", "disabled"]);
|
|
123
|
-
|
|
124
131
|
if (divider) {
|
|
125
|
-
return /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({
|
|
132
|
+
return renderDropdownItem( /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({
|
|
126
133
|
ref: ref,
|
|
127
134
|
role: "separator",
|
|
128
135
|
className: merge(prefix('divider'), className)
|
|
129
|
-
}, restProps));
|
|
136
|
+
}, restProps)));
|
|
130
137
|
}
|
|
131
138
|
|
|
132
139
|
if (panel) {
|
|
133
|
-
return /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({
|
|
140
|
+
return renderDropdownItem( /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({
|
|
134
141
|
ref: ref,
|
|
135
|
-
role: "none presentation",
|
|
136
142
|
className: merge(prefix('panel'), className)
|
|
137
|
-
}, restProps), children);
|
|
143
|
+
}, restProps), children));
|
|
138
144
|
}
|
|
139
145
|
|
|
140
146
|
if (navbar) {
|
|
@@ -158,6 +164,7 @@ var DropdownItem = /*#__PURE__*/_react.default.forwardRef(function (props, ref)
|
|
|
158
164
|
className: classes,
|
|
159
165
|
"aria-current": selected || undefined
|
|
160
166
|
}, dataAttributes, restProps, {
|
|
167
|
+
as: Component,
|
|
161
168
|
onClick: (0, _utils.createChainedFunction)(handleClickNavbarDropdownItem, restProps.onClick)
|
|
162
169
|
}), icon && /*#__PURE__*/_react.default.cloneElement(icon, {
|
|
163
170
|
className: prefix('menu-icon')
|
|
@@ -188,12 +195,12 @@ var DropdownItem = /*#__PURE__*/_react.default.forwardRef(function (props, ref)
|
|
|
188
195
|
dataAttributes['data-event-key-type'] = typeof eventKey;
|
|
189
196
|
}
|
|
190
197
|
|
|
191
|
-
return /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({
|
|
198
|
+
return renderDropdownItem( /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({
|
|
192
199
|
ref: (0, _utils.mergeRefs)(ref, menuitemRef),
|
|
193
200
|
className: classes
|
|
194
201
|
}, menuitem, dataAttributes, restProps), icon && /*#__PURE__*/_react.default.cloneElement(icon, {
|
|
195
202
|
className: prefix('menu-icon')
|
|
196
|
-
}), children);
|
|
203
|
+
}), children));
|
|
197
204
|
});
|
|
198
205
|
});
|
|
199
206
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MaskType, MaskFunctionType, ConfigType } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* https://github.com/text-mask/text-mask/blob/master/componentDocumentation.md#guide
|
|
5
|
+
*/
|
|
6
|
+
interface TextMaskProps {
|
|
7
|
+
/**
|
|
8
|
+
* `guide` is a boolean that tells the component whether to be in guide or no guide mode.
|
|
9
|
+
*/
|
|
10
|
+
guide?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* `mask` is an array or a function that defines how the user input is going to be masked.
|
|
13
|
+
*/
|
|
14
|
+
mask?: MaskType | MaskFunctionType | boolean;
|
|
15
|
+
/**
|
|
16
|
+
* `showMask` is a boolean that tells the Text Mask component to display the mask as a placeholder
|
|
17
|
+
* in place of the regular placeholder when the input element value is empty.
|
|
18
|
+
*/
|
|
19
|
+
showMask?: boolean;
|
|
20
|
+
/** The placeholder character represents the fillable spot in the mask. The default placeholder character is underscore, _. */
|
|
21
|
+
placeholderChar?: string;
|
|
22
|
+
/** `keepCharPositions` changes the general behavior of the Text Mask component. */
|
|
23
|
+
keepCharPositions?: boolean;
|
|
24
|
+
/** You can provide a `pipe` function that will give you the opportunity to modify the conformed value before it is displayed on the screen. */
|
|
25
|
+
pipe?: (conformedValue: string, config: ConfigType) => string;
|
|
26
|
+
}
|
|
27
|
+
export declare type MaskedInputProps = TextMaskProps & React.HTMLAttributes<HTMLInputElement> & {
|
|
28
|
+
/** Custom rendering DOM */
|
|
29
|
+
render?: (ref: React.Ref<HTMLInputElement>, props: React.HTMLAttributes<HTMLInputElement>) => any;
|
|
30
|
+
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
31
|
+
value?: string | number;
|
|
32
|
+
readOnly?: boolean;
|
|
33
|
+
disabled?: boolean;
|
|
34
|
+
};
|
|
35
|
+
declare const MaskedInput: React.ForwardRefExoticComponent<TextMaskProps & React.HTMLAttributes<HTMLInputElement> & {
|
|
36
|
+
/** Custom rendering DOM */
|
|
37
|
+
render?: (ref: React.Ref<HTMLInputElement>, props: React.HTMLAttributes<HTMLInputElement>) => any;
|
|
38
|
+
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
39
|
+
value?: string | number;
|
|
40
|
+
readOnly?: boolean;
|
|
41
|
+
disabled?: boolean;
|
|
42
|
+
} & React.RefAttributes<HTMLInputElement>>;
|
|
43
|
+
export default MaskedInput;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
|
|
4
|
+
|
|
5
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
6
|
+
|
|
7
|
+
exports.__esModule = true;
|
|
8
|
+
exports.default = void 0;
|
|
9
|
+
|
|
10
|
+
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
|
|
11
|
+
|
|
12
|
+
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
13
|
+
|
|
14
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
15
|
+
|
|
16
|
+
var _omit = _interopRequireDefault(require("lodash/omit"));
|
|
17
|
+
|
|
18
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
19
|
+
|
|
20
|
+
var _createTextMaskInputElement = _interopRequireDefault(require("./createTextMaskInputElement"));
|
|
21
|
+
|
|
22
|
+
var _utils = require("../utils");
|
|
23
|
+
|
|
24
|
+
var defaultRender = function defaultRender(ref, props) {
|
|
25
|
+
return /*#__PURE__*/_react.default.createElement("input", (0, _extends2.default)({
|
|
26
|
+
ref: ref
|
|
27
|
+
}, props));
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
var MaskedInput = /*#__PURE__*/_react.default.forwardRef(function (props, ref) {
|
|
31
|
+
var mask = props.mask,
|
|
32
|
+
_props$guide = props.guide,
|
|
33
|
+
guide = _props$guide === void 0 ? true : _props$guide,
|
|
34
|
+
placeholderChar = props.placeholderChar,
|
|
35
|
+
value = props.value,
|
|
36
|
+
showMask = props.showMask,
|
|
37
|
+
pipe = props.pipe,
|
|
38
|
+
_props$render = props.render,
|
|
39
|
+
render = _props$render === void 0 ? defaultRender : _props$render,
|
|
40
|
+
onChange = props.onChange,
|
|
41
|
+
rest = (0, _objectWithoutPropertiesLoose2.default)(props, ["mask", "guide", "placeholderChar", "value", "showMask", "pipe", "render", "onChange"]);
|
|
42
|
+
var inputRef = (0, _react.useRef)(null);
|
|
43
|
+
var textMaskInputElement = (0, _react.useRef)();
|
|
44
|
+
var initTextMask = (0, _react.useCallback)(function () {
|
|
45
|
+
var _textMaskInputElement;
|
|
46
|
+
|
|
47
|
+
textMaskInputElement.current = (0, _createTextMaskInputElement.default)((0, _extends2.default)({
|
|
48
|
+
inputElement: inputRef.current
|
|
49
|
+
}, props));
|
|
50
|
+
(_textMaskInputElement = textMaskInputElement.current) === null || _textMaskInputElement === void 0 ? void 0 : _textMaskInputElement.update(value);
|
|
51
|
+
}, [props, value]);
|
|
52
|
+
var handleChange = (0, _react.useCallback)(function (event) {
|
|
53
|
+
var _textMaskInputElement2;
|
|
54
|
+
|
|
55
|
+
(_textMaskInputElement2 = textMaskInputElement.current) === null || _textMaskInputElement2 === void 0 ? void 0 : _textMaskInputElement2.update();
|
|
56
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(event);
|
|
57
|
+
}, [onChange]);
|
|
58
|
+
(0, _react.useEffect)(function () {
|
|
59
|
+
initTextMask();
|
|
60
|
+
}, [guide, placeholderChar, showMask, pipe, mask, value, initTextMask]);
|
|
61
|
+
return render((0, _utils.mergeRefs)(inputRef, ref), (0, _extends2.default)({
|
|
62
|
+
onChange: handleChange,
|
|
63
|
+
defaultValue: value
|
|
64
|
+
}, (0, _omit.default)(rest, ['keepCharPositions'])));
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
MaskedInput.displayName = 'MaskedInput';
|
|
68
|
+
MaskedInput.propTypes = {
|
|
69
|
+
render: _propTypes.default.func,
|
|
70
|
+
onChange: _propTypes.default.func,
|
|
71
|
+
mask: _propTypes.default.oneOfType([_propTypes.default.array, _propTypes.default.func, _propTypes.default.bool]).isRequired,
|
|
72
|
+
guide: _propTypes.default.bool,
|
|
73
|
+
value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
|
|
74
|
+
pipe: _propTypes.default.func,
|
|
75
|
+
placeholderChar: _propTypes.default.string,
|
|
76
|
+
keepCharPositions: _propTypes.default.bool,
|
|
77
|
+
showMask: _propTypes.default.bool
|
|
78
|
+
};
|
|
79
|
+
var _default = MaskedInput;
|
|
80
|
+
exports.default = _default;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default function adjustCaretPosition({ previousConformedValue, previousPlaceholder, currentCaretPosition, conformedValue, rawValue, placeholderChar, placeholder, indexesOfPipedChars, caretTrapIndexes }: {
|
|
2
|
+
previousConformedValue?: string;
|
|
3
|
+
previousPlaceholder?: string;
|
|
4
|
+
currentCaretPosition?: number;
|
|
5
|
+
conformedValue: any;
|
|
6
|
+
rawValue: any;
|
|
7
|
+
placeholderChar: any;
|
|
8
|
+
placeholder: any;
|
|
9
|
+
indexesOfPipedChars?: any[];
|
|
10
|
+
caretTrapIndexes?: any[];
|
|
11
|
+
}): number;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = adjustCaretPosition;
|
|
5
|
+
var defaultArray = [];
|
|
6
|
+
var emptyString = '';
|
|
7
|
+
|
|
8
|
+
function adjustCaretPosition(_ref) {
|
|
9
|
+
var _ref$previousConforme = _ref.previousConformedValue,
|
|
10
|
+
previousConformedValue = _ref$previousConforme === void 0 ? emptyString : _ref$previousConforme,
|
|
11
|
+
_ref$previousPlacehol = _ref.previousPlaceholder,
|
|
12
|
+
previousPlaceholder = _ref$previousPlacehol === void 0 ? emptyString : _ref$previousPlacehol,
|
|
13
|
+
_ref$currentCaretPosi = _ref.currentCaretPosition,
|
|
14
|
+
currentCaretPosition = _ref$currentCaretPosi === void 0 ? 0 : _ref$currentCaretPosi,
|
|
15
|
+
conformedValue = _ref.conformedValue,
|
|
16
|
+
rawValue = _ref.rawValue,
|
|
17
|
+
placeholderChar = _ref.placeholderChar,
|
|
18
|
+
placeholder = _ref.placeholder,
|
|
19
|
+
_ref$indexesOfPipedCh = _ref.indexesOfPipedChars,
|
|
20
|
+
indexesOfPipedChars = _ref$indexesOfPipedCh === void 0 ? defaultArray : _ref$indexesOfPipedCh,
|
|
21
|
+
_ref$caretTrapIndexes = _ref.caretTrapIndexes,
|
|
22
|
+
caretTrapIndexes = _ref$caretTrapIndexes === void 0 ? defaultArray : _ref$caretTrapIndexes;
|
|
23
|
+
|
|
24
|
+
if (currentCaretPosition === 0 || !rawValue.length) {
|
|
25
|
+
return 0;
|
|
26
|
+
} // Store lengths for faster performance?
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
var rawValueLength = rawValue.length;
|
|
30
|
+
var previousConformedValueLength = previousConformedValue.length;
|
|
31
|
+
var placeholderLength = placeholder.length;
|
|
32
|
+
var conformedValueLength = conformedValue.length; // This tells us how long the edit is. If user modified input from `(2__)` to `(243__)`,
|
|
33
|
+
// we know the user in this instance pasted two characters
|
|
34
|
+
|
|
35
|
+
var editLength = rawValueLength - previousConformedValueLength; // If the edit length is positive, that means the user is adding characters, not deleting.
|
|
36
|
+
|
|
37
|
+
var isAddition = editLength > 0; // This is the first raw value the user entered that needs to be conformed to mask
|
|
38
|
+
|
|
39
|
+
var isFirstRawValue = previousConformedValueLength === 0; // A partial multi-character edit happens when the user makes a partial selection in their
|
|
40
|
+
// input and edits that selection. That is going from `(123) 432-4348` to `() 432-4348` by
|
|
41
|
+
// selecting the first 3 digits and pressing backspace.
|
|
42
|
+
//
|
|
43
|
+
// Such cases can also happen when the user presses the backspace while holding down the ALT
|
|
44
|
+
// key.
|
|
45
|
+
|
|
46
|
+
var isPartialMultiCharEdit = editLength > 1 && !isFirstRawValue; // This algorithm doesn't support all cases of multi-character edits, so we just return
|
|
47
|
+
// the current caret position.
|
|
48
|
+
//
|
|
49
|
+
// This works fine for most cases.
|
|
50
|
+
|
|
51
|
+
if (isPartialMultiCharEdit) {
|
|
52
|
+
return currentCaretPosition;
|
|
53
|
+
} // For a mask like (111), if the `previousConformedValue` is (1__) and user attempts to enter
|
|
54
|
+
// `f` so the `rawValue` becomes (1f__), the new `conformedValue` would be (1__), which is the
|
|
55
|
+
// same as the original `previousConformedValue`. We handle this case differently for caret
|
|
56
|
+
// positioning.
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
var possiblyHasRejectedChar = isAddition && (previousConformedValue === conformedValue || conformedValue === placeholder);
|
|
60
|
+
var startingSearchIndex = 0;
|
|
61
|
+
var trackRightCharacter;
|
|
62
|
+
var targetChar;
|
|
63
|
+
|
|
64
|
+
if (possiblyHasRejectedChar) {
|
|
65
|
+
startingSearchIndex = currentCaretPosition - editLength;
|
|
66
|
+
} else {
|
|
67
|
+
// At this point in the algorithm, we want to know where the caret is right before the raw input
|
|
68
|
+
// has been conformed, and then see if we can find that same spot in the conformed input.
|
|
69
|
+
//
|
|
70
|
+
// We do that by seeing what character lies immediately before the caret, and then look for that
|
|
71
|
+
// same character in the conformed input and place the caret there.
|
|
72
|
+
// First, we need to normalize the inputs so that letter capitalization between raw input and
|
|
73
|
+
// conformed input wouldn't matter.
|
|
74
|
+
var normalizedConformedValue = conformedValue.toLowerCase();
|
|
75
|
+
var normalizedRawValue = rawValue.toLowerCase(); // Then we take all characters that come before where the caret currently is.
|
|
76
|
+
|
|
77
|
+
var leftHalfChars = normalizedRawValue.substr(0, currentCaretPosition).split(emptyString); // Now we find all the characters in the left half that exist in the conformed input
|
|
78
|
+
// This step ensures that we don't look for a character that was filtered out or rejected by `conformToMask`.
|
|
79
|
+
|
|
80
|
+
var intersection = leftHalfChars.filter(function (char) {
|
|
81
|
+
return normalizedConformedValue.indexOf(char) !== -1;
|
|
82
|
+
}); // The last character in the intersection is the character we want to look for in the conformed
|
|
83
|
+
// value and the one we want to adjust the caret close to
|
|
84
|
+
|
|
85
|
+
targetChar = intersection[intersection.length - 1]; // Calculate the number of mask characters in the previous placeholder
|
|
86
|
+
// from the start of the string up to the place where the caret is
|
|
87
|
+
|
|
88
|
+
var previousLeftMaskChars = previousPlaceholder.substr(0, intersection.length).split(emptyString).filter(function (char) {
|
|
89
|
+
return char !== placeholderChar;
|
|
90
|
+
}).length; // Calculate the number of mask characters in the current placeholder
|
|
91
|
+
// from the start of the string up to the place where the caret is
|
|
92
|
+
|
|
93
|
+
var leftMaskChars = placeholder.substr(0, intersection.length).split(emptyString).filter(function (char) {
|
|
94
|
+
return char !== placeholderChar;
|
|
95
|
+
}).length; // Has the number of mask characters up to the caret changed?
|
|
96
|
+
|
|
97
|
+
var masklengthChanged = leftMaskChars !== previousLeftMaskChars; // Detect if `targetChar` is a mask character and has moved to the left
|
|
98
|
+
|
|
99
|
+
var targetIsMaskMovingLeft = previousPlaceholder[intersection.length - 1] !== undefined && placeholder[intersection.length - 2] !== undefined && previousPlaceholder[intersection.length - 1] !== placeholderChar && previousPlaceholder[intersection.length - 1] !== placeholder[intersection.length - 1] && previousPlaceholder[intersection.length - 1] === placeholder[intersection.length - 2]; // If deleting and the `targetChar` `is a mask character and `masklengthChanged` is true
|
|
100
|
+
// or the mask is moving to the left, we can't use the selected `targetChar` any longer
|
|
101
|
+
// if we are not at the end of the string.
|
|
102
|
+
// In this case, change tracking strategy and track the character to the right of the caret.
|
|
103
|
+
|
|
104
|
+
if (!isAddition && (masklengthChanged || targetIsMaskMovingLeft) && previousLeftMaskChars > 0 && placeholder.indexOf(targetChar) > -1 && rawValue[currentCaretPosition] !== undefined) {
|
|
105
|
+
trackRightCharacter = true;
|
|
106
|
+
targetChar = rawValue[currentCaretPosition];
|
|
107
|
+
} // It is possible that `targetChar` will appear multiple times in the conformed value.
|
|
108
|
+
// We need to know not to select a character that looks like our target character from the placeholder or
|
|
109
|
+
// the piped characters, so we inspect the piped characters and the placeholder to see if they contain
|
|
110
|
+
// characters that match our target character.
|
|
111
|
+
// If the `conformedValue` got piped, we need to know which characters were piped in so that when we look for
|
|
112
|
+
// our `targetChar`, we don't select a piped char by mistake
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
var pipedChars = indexesOfPipedChars.map(function (index) {
|
|
116
|
+
return normalizedConformedValue[index];
|
|
117
|
+
}); // We need to know how many times the `targetChar` occurs in the piped characters.
|
|
118
|
+
|
|
119
|
+
var countTargetCharInPipedChars = pipedChars.filter(function (char) {
|
|
120
|
+
return char === targetChar;
|
|
121
|
+
}).length; // We need to know how many times it occurs in the intersection
|
|
122
|
+
|
|
123
|
+
var countTargetCharInIntersection = intersection.filter(function (char) {
|
|
124
|
+
return char === targetChar;
|
|
125
|
+
}).length; // We need to know if the placeholder contains characters that look like
|
|
126
|
+
// our `targetChar`, so we don't select one of those by mistake.
|
|
127
|
+
|
|
128
|
+
var countTargetCharInPlaceholder = placeholder.substr(0, placeholder.indexOf(placeholderChar)).split(emptyString).filter(function (char, index) {
|
|
129
|
+
return (// Check if `char` is the same as our `targetChar`, so we account for it
|
|
130
|
+
char === targetChar && // but also make sure that both the `rawValue` and placeholder don't have the same character at the same
|
|
131
|
+
// index because if they are equal, that means we are already counting those characters in
|
|
132
|
+
// `countTargetCharInIntersection`
|
|
133
|
+
rawValue[index] !== char
|
|
134
|
+
);
|
|
135
|
+
}).length; // The number of times we need to see occurrences of the `targetChar` before we know it is the one we're looking
|
|
136
|
+
// for is:
|
|
137
|
+
|
|
138
|
+
var requiredNumberOfMatches = countTargetCharInPlaceholder + countTargetCharInIntersection + countTargetCharInPipedChars + ( // The character to the right of the caret isn't included in `intersection`
|
|
139
|
+
// so add one if we are tracking the character to the right
|
|
140
|
+
trackRightCharacter ? 1 : 0); // Now we start looking for the location of the `targetChar`.
|
|
141
|
+
// We keep looping forward and store the index in every iteration. Once we have encountered
|
|
142
|
+
// enough occurrences of the target character, we break out of the loop
|
|
143
|
+
// If are searching for the second `1` in `1214`, `startingSearchIndex` will point at `4`.
|
|
144
|
+
|
|
145
|
+
var numberOfEncounteredMatches = 0;
|
|
146
|
+
|
|
147
|
+
for (var i = 0; i < conformedValueLength; i++) {
|
|
148
|
+
var conformedValueChar = normalizedConformedValue[i];
|
|
149
|
+
startingSearchIndex = i + 1;
|
|
150
|
+
|
|
151
|
+
if (conformedValueChar === targetChar) {
|
|
152
|
+
numberOfEncounteredMatches++;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (numberOfEncounteredMatches >= requiredNumberOfMatches) {
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
} // At this point, if we simply return `startingSearchIndex` as the adjusted caret position,
|
|
160
|
+
// most cases would be handled. However, we want to fast forward or rewind the caret to the
|
|
161
|
+
// closest placeholder character if it happens to be in a non-editable spot. That's what the next
|
|
162
|
+
// logic is for.
|
|
163
|
+
// In case of addition, we fast forward.
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
if (isAddition) {
|
|
167
|
+
// We want to remember the last placeholder character encountered so that if the mask
|
|
168
|
+
// contains more characters after the last placeholder character, we don't forward the caret
|
|
169
|
+
// that far to the right. Instead, we stop it at the last encountered placeholder character.
|
|
170
|
+
var lastPlaceholderChar = startingSearchIndex;
|
|
171
|
+
|
|
172
|
+
for (var _i = startingSearchIndex; _i <= placeholderLength; _i++) {
|
|
173
|
+
if (placeholder[_i] === placeholderChar) {
|
|
174
|
+
lastPlaceholderChar = _i;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if ( // If we're adding, we can position the caret at the next placeholder character.
|
|
178
|
+
placeholder[_i] === placeholderChar || // If a caret trap was set by a mask function, we need to stop at the trap.
|
|
179
|
+
caretTrapIndexes.indexOf(_i) !== -1 || // This is the end of the placeholder. We cannot move any further. Let's put the caret there.
|
|
180
|
+
_i === placeholderLength) {
|
|
181
|
+
return lastPlaceholderChar;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
// In case of deletion, we rewind.
|
|
186
|
+
if (trackRightCharacter) {
|
|
187
|
+
// Searching for the character that was to the right of the caret
|
|
188
|
+
// We start at `startingSearchIndex` - 1 because it includes one character extra to the right
|
|
189
|
+
for (var _i2 = startingSearchIndex - 1; _i2 >= 0; _i2--) {
|
|
190
|
+
// If tracking the character to the right of the cursor, we move to the left until
|
|
191
|
+
// we found the character and then place the caret right before it
|
|
192
|
+
if ( // `targetChar` should be in `conformedValue`, since it was in `rawValue`, just
|
|
193
|
+
// to the right of the caret
|
|
194
|
+
conformedValue[_i2] === targetChar || // If a caret trap was set by a mask function, we need to stop at the trap.
|
|
195
|
+
caretTrapIndexes.indexOf(_i2) !== -1 || // This is the beginning of the placeholder. We cannot move any further.
|
|
196
|
+
// Let's put the caret there.
|
|
197
|
+
_i2 === 0) {
|
|
198
|
+
return _i2;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
} else {
|
|
202
|
+
// Searching for the first placeholder or caret trap to the left
|
|
203
|
+
for (var _i3 = startingSearchIndex; _i3 >= 0; _i3--) {
|
|
204
|
+
// If we're deleting, we stop the caret right before the placeholder character.
|
|
205
|
+
// For example, for mask `(111) 11`, current conformed input `(456) 86`. If user
|
|
206
|
+
// modifies input to `(456 86`. That is, they deleted the `)`, we place the caret
|
|
207
|
+
// right after the first `6`
|
|
208
|
+
if ( // If we're deleting, we can position the caret right before the placeholder character
|
|
209
|
+
placeholder[_i3 - 1] === placeholderChar || // If a caret trap was set by a mask function, we need to stop at the trap.
|
|
210
|
+
caretTrapIndexes.indexOf(_i3) !== -1 || // This is the beginning of the placeholder. We cannot move any further.
|
|
211
|
+
// Let's put the caret there.
|
|
212
|
+
_i3 === 0) {
|
|
213
|
+
return _i3;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MaskType, ConfigType, MaskFunctionType } from './types';
|
|
2
|
+
export declare function isArray(value: any): boolean;
|
|
3
|
+
export default function conformToMask(rawValue?: string, mask?: MaskType | MaskFunctionType, config?: ConfigType): {
|
|
4
|
+
conformedValue: string;
|
|
5
|
+
meta: {
|
|
6
|
+
someCharsRejected: boolean;
|
|
7
|
+
};
|
|
8
|
+
};
|