react-input-mask-format 2.1.0 → 2.3.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/README.md +139 -1
- package/dist/chunk-CEZXZ7IJ.js +42 -0
- package/dist/chunk-CEZXZ7IJ.js.map +1 -0
- package/dist/index.cjs +214 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +199 -22
- package/dist/index.js.map +1 -1
- package/dist/number.cjs +342 -0
- package/dist/number.cjs.map +1 -0
- package/dist/number.d.cts +46 -0
- package/dist/number.d.ts +46 -0
- package/dist/number.js +280 -0
- package/dist/number.js.map +1 -0
- package/dist/presets.d.cts +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/time.cjs +240 -0
- package/dist/time.cjs.map +1 -0
- package/dist/time.d.cts +28 -0
- package/dist/time.d.ts +28 -0
- package/dist/time.js +178 -0
- package/dist/time.js.map +1 -0
- package/dist/{types-Bfu5Jmh0.d.cts → types-BTNqtchO.d.cts} +17 -1
- package/dist/{types-Bfu5Jmh0.d.ts → types-BTNqtchO.d.ts} +17 -1
- package/package.json +12 -2
package/README.md
CHANGED
|
@@ -10,7 +10,16 @@ Made with attention to UX.
|
|
|
10
10
|
|
|
11
11
|
A maintained fork of [react-input-mask](https://github.com/sanniassin/react-input-mask).
|
|
12
12
|
|
|
13
|
-
## What's new in 2.
|
|
13
|
+
## What's new in 2.3
|
|
14
|
+
|
|
15
|
+
- `react-input-mask-format/time` — HH:MM (24h) masked input with clamping, see [Time](#time--react-input-mask-formattime)
|
|
16
|
+
|
|
17
|
+
### 2.2
|
|
18
|
+
|
|
19
|
+
- `useMask` hook — mask your own `<input>` with no wrapper component, see [useMask hook](#usemask-hook)
|
|
20
|
+
- `react-input-mask-format/number` — numeric & currency masking, a lightweight `react-number-format` alternative, see [Numeric & currency](#numeric--currency--react-input-mask-formatnumber)
|
|
21
|
+
|
|
22
|
+
### 2.1
|
|
14
23
|
|
|
15
24
|
- `transform` prop (`uppercase` / `lowercase` / custom) — see [transform](#transform)
|
|
16
25
|
- Custom tokens via RegExp `formatChars` + shipped `extendedFormatChars` (`A`, `Я`, `#`)
|
|
@@ -161,6 +170,135 @@ isValidKzIban("KZ86 125K ZT50 0410 0100"); // ISO 7064 MOD-97
|
|
|
161
170
|
luhn("4242 4242 4242 4242"); // card Luhn
|
|
162
171
|
```
|
|
163
172
|
|
|
173
|
+
## `useMask` hook
|
|
174
|
+
|
|
175
|
+
Mask your own `<input>` with no wrapper component. `useMask` returns a ref
|
|
176
|
+
callback:
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
import { useMask } from "react-input-mask-format";
|
|
180
|
+
|
|
181
|
+
function Phone() {
|
|
182
|
+
const ref = useMask({ mask: "+7 (999) 999-99-99", maskPlaceholder: "_" });
|
|
183
|
+
return <input ref={ref} name="phone" />;
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
`useMask` is **uncontrolled**: attach it to an input you don't drive with a
|
|
188
|
+
React `value` prop, and read the masked value through your own `onChange` (it
|
|
189
|
+
fires with the masked value) or on form submit. For a controlled component,
|
|
190
|
+
use `<InputMask>`.
|
|
191
|
+
|
|
192
|
+
Options: `mask`, `maskPlaceholder`, `alwaysShowMask`, `formatChars`,
|
|
193
|
+
`transform`, `beforeMaskedStateChange`.
|
|
194
|
+
|
|
195
|
+
## Numeric & currency — `react-input-mask-format/number`
|
|
196
|
+
|
|
197
|
+
A separate, tree-shakeable entry for formatting numbers, currency, and
|
|
198
|
+
percentages. Prop names match `react-number-format`, so migration is mostly a
|
|
199
|
+
find-and-replace of the import.
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
import { NumberFormat } from "react-input-mask-format/number";
|
|
203
|
+
|
|
204
|
+
function Amount() {
|
|
205
|
+
const [value, setValue] = React.useState<number>();
|
|
206
|
+
return (
|
|
207
|
+
<NumberFormat
|
|
208
|
+
value={value ?? ""}
|
|
209
|
+
onValueChange={({ floatValue }) => setValue(floatValue)}
|
|
210
|
+
thousandSeparator="," decimalScale={2} fixedDecimalScale prefix="$ "
|
|
211
|
+
allowNegative
|
|
212
|
+
/>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
`onValueChange` receives `{ value, formattedValue, floatValue }`:
|
|
218
|
+
|
|
219
|
+
```txt
|
|
220
|
+
typing "1234.5" → value "1234.5" formattedValue "$ 1,234.50" floatValue 1234.5
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Options: `thousandSeparator` (`true` → `,`, or a custom string),
|
|
224
|
+
`decimalSeparator` (default `.`), `decimalScale` (truncates, no rounding),
|
|
225
|
+
`fixedDecimalScale`, `prefix`, `suffix`, `allowNegative` (default `true`),
|
|
226
|
+
`allowLeadingZeros`, and `isAllowed(values) => boolean` (reject an edit, e.g.
|
|
227
|
+
for min/max).
|
|
228
|
+
|
|
229
|
+
There is also a ref hook and the pure helpers:
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
import { useNumberFormat, formatNumber, parseNumber } from "react-input-mask-format/number";
|
|
233
|
+
|
|
234
|
+
const ref = useNumberFormat({ thousandSeparator: " ", decimalScale: 2, prefix: "$ " });
|
|
235
|
+
// <input ref={ref} />
|
|
236
|
+
|
|
237
|
+
formatNumber(1234.5, { thousandSeparator: ",", decimalScale: 2, fixedDecimalScale: true }); // "1,234.50"
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Migrating from react-number-format
|
|
241
|
+
|
|
242
|
+
`NumberFormat`'s props (`thousandSeparator`, `decimalSeparator`, `decimalScale`,
|
|
243
|
+
`fixedDecimalScale`, `prefix`, `suffix`, `allowNegative`, `allowLeadingZeros`,
|
|
244
|
+
`isAllowed`, `onValueChange`) mirror `react-number-format`'s `NumericFormat`.
|
|
245
|
+
The main differences: `decimalScale` **truncates** rather than rounds while
|
|
246
|
+
typing, and this package ships a single `NumberFormat` (no separate
|
|
247
|
+
`PatternFormat` — use the mask engine / `<InputMask>` for pattern masks).
|
|
248
|
+
|
|
249
|
+
## Time — `react-input-mask-format/time`
|
|
250
|
+
|
|
251
|
+
A separate, tree-shakeable entry for formatting times in 24-hour format (HH:MM).
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
import { TimeFormat, useTimeFormat, formatTime } from "react-input-mask-format/time";
|
|
255
|
+
|
|
256
|
+
// controlled component
|
|
257
|
+
<TimeFormat value={time} onValueChange={(v) => setTime(v.value)} />
|
|
258
|
+
|
|
259
|
+
// bring-your-own input (e.g. a design-system Input)
|
|
260
|
+
const ref = useTimeFormat({ onValueChange: (v) => setTime(v.value) });
|
|
261
|
+
<input ref={ref} />
|
|
262
|
+
|
|
263
|
+
formatTime("2999"); // "23:59"
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
`onValueChange` receives `{ value, formattedValue, hours, minutes }`:
|
|
267
|
+
|
|
268
|
+
```txt
|
|
269
|
+
typing "1234" → value "12:34" formattedValue "12:34" hours 12 minutes 34
|
|
270
|
+
typing "12" → value "" formattedValue "12:" hours 12 minutes undefined
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
`value` remains empty until both hours and minutes are complete. The canonical
|
|
274
|
+
`value` always uses `:` as the separator, regardless of the display `separator`
|
|
275
|
+
option.
|
|
276
|
+
|
|
277
|
+
**Clamping**: When hours are complete (two digits), they're clamped to ≤23.
|
|
278
|
+
When minutes are complete, they're clamped to ≤59. A single digit is never
|
|
279
|
+
clamped.
|
|
280
|
+
|
|
281
|
+
Because an incomplete time has an empty canonical `value`, a controlled parent
|
|
282
|
+
that resets `value` to `""` won't visibly clear a partially-typed field; to
|
|
283
|
+
force-clear it, remount the input with a changed React `key`.
|
|
284
|
+
|
|
285
|
+
Options: `separator` (default `:`).
|
|
286
|
+
|
|
287
|
+
There is also a ref hook and the pure helpers:
|
|
288
|
+
|
|
289
|
+
```tsx
|
|
290
|
+
import { useTimeFormat, formatTime, parseTime } from "react-input-mask-format/time";
|
|
291
|
+
|
|
292
|
+
const ref = useTimeFormat({ separator: ":" });
|
|
293
|
+
// <input ref={ref} />
|
|
294
|
+
|
|
295
|
+
formatTime("2999", { separator: ":" }); // "23:59"
|
|
296
|
+
parseTime("14:30"); // { value: "14:30", formattedValue: "14:30", hours: 14, minutes: 30 }
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Reserved for a later minor release**: seconds (HH:MM:SS) and 12-hour format
|
|
300
|
+
with AM/PM.
|
|
301
|
+
|
|
164
302
|
### `maskPlaceholder`
|
|
165
303
|
|
|
166
304
|
```jsx
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/utils/input.ts
|
|
2
|
+
function setInputSelection(input, start, end) {
|
|
3
|
+
if (end === void 0) {
|
|
4
|
+
end = start;
|
|
5
|
+
}
|
|
6
|
+
input.setSelectionRange(start, end);
|
|
7
|
+
}
|
|
8
|
+
function getInputSelection(input) {
|
|
9
|
+
const start = input.selectionStart;
|
|
10
|
+
const end = input.selectionEnd;
|
|
11
|
+
return {
|
|
12
|
+
start,
|
|
13
|
+
end,
|
|
14
|
+
length: (end != null ? end : 0) - (start != null ? start : 0)
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function isInputFocused(input) {
|
|
18
|
+
const inputDocument = input.ownerDocument;
|
|
19
|
+
return inputDocument.hasFocus() && inputDocument.activeElement === input;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/set-native-value.ts
|
|
23
|
+
function setNativeValue(input, value) {
|
|
24
|
+
const descriptor = Object.getOwnPropertyDescriptor(
|
|
25
|
+
HTMLInputElement.prototype,
|
|
26
|
+
"value"
|
|
27
|
+
);
|
|
28
|
+
const setter = descriptor && descriptor.set;
|
|
29
|
+
if (setter) {
|
|
30
|
+
setter.call(input, value);
|
|
31
|
+
} else {
|
|
32
|
+
input.value = value;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
setInputSelection,
|
|
38
|
+
getInputSelection,
|
|
39
|
+
isInputFocused,
|
|
40
|
+
setNativeValue
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=chunk-CEZXZ7IJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/input.ts","../src/set-native-value.ts"],"sourcesContent":["import type { Selection } from \"../types\";\n\nexport function setInputSelection(\n input: HTMLInputElement,\n start: number,\n end?: number\n): void {\n if (end === undefined) {\n end = start;\n }\n input.setSelectionRange(start, end);\n}\n\nexport function getInputSelection(input: HTMLInputElement): Required<Selection> {\n const start = input.selectionStart;\n const end = input.selectionEnd;\n\n return {\n start,\n end,\n length: (end ?? 0) - (start ?? 0)\n };\n}\n\nexport function isInputFocused(input: HTMLInputElement): boolean {\n const inputDocument = input.ownerDocument;\n return inputDocument.hasFocus() && inputDocument.activeElement === input;\n}\n","// Write to input.value through the native prototype setter so React's\n// internal value tracker stays stale. The user's keystroke `input` event then\n// bubbles into React's root listener, which sees masked value != stale tracker\n// and fires the consumer's onChange with the masked value. Using the tracked\n// (React-wrapped) setter instead would suppress that onChange.\nexport function setNativeValue(input: HTMLInputElement, value: string): void {\n const descriptor = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n \"value\"\n );\n const setter = descriptor && descriptor.set;\n if (setter) {\n setter.call(input, value);\n } else {\n input.value = value;\n }\n}\n"],"mappings":";AAEO,SAAS,kBACd,OACA,OACA,KACM;AACN,MAAI,QAAQ,QAAW;AACrB,UAAM;AAAA,EACR;AACA,QAAM,kBAAkB,OAAO,GAAG;AACpC;AAEO,SAAS,kBAAkB,OAA8C;AAC9E,QAAM,QAAQ,MAAM;AACpB,QAAM,MAAM,MAAM;AAElB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS,oBAAO,MAAM,wBAAS;AAAA,EACjC;AACF;AAEO,SAAS,eAAe,OAAkC;AAC/D,QAAM,gBAAgB,MAAM;AAC5B,SAAO,cAAc,SAAS,KAAK,cAAc,kBAAkB;AACrE;;;ACtBO,SAAS,eAAe,OAAyB,OAAqB;AAC3E,QAAM,aAAa,OAAO;AAAA,IACxB,iBAAiB;AAAA,IACjB;AAAA,EACF;AACA,QAAM,SAAS,cAAc,WAAW;AACxC,MAAI,QAAQ;AACV,WAAO,KAAK,OAAO,KAAK;AAAA,EAC1B,OAAO;AACL,UAAM,QAAQ;AAAA,EAChB;AACF;","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -32,10 +32,11 @@ var src_exports = {};
|
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
default: () => src_default,
|
|
34
34
|
defaultFormatChars: () => defaultFormatChars,
|
|
35
|
-
extendedFormatChars: () => extendedFormatChars
|
|
35
|
+
extendedFormatChars: () => extendedFormatChars,
|
|
36
|
+
useMask: () => useMask
|
|
36
37
|
});
|
|
37
38
|
module.exports = __toCommonJS(src_exports);
|
|
38
|
-
var
|
|
39
|
+
var import_react3 = __toESM(require("react"), 1);
|
|
39
40
|
|
|
40
41
|
// src/hooks.ts
|
|
41
42
|
var import_react = require("react");
|
|
@@ -672,8 +673,212 @@ function resolveTransform(transform) {
|
|
|
672
673
|
return void 0;
|
|
673
674
|
}
|
|
674
675
|
|
|
676
|
+
// src/use-mask.ts
|
|
677
|
+
var import_react2 = require("react");
|
|
678
|
+
|
|
679
|
+
// src/set-native-value.ts
|
|
680
|
+
function setNativeValue(input, value) {
|
|
681
|
+
const descriptor = Object.getOwnPropertyDescriptor(
|
|
682
|
+
HTMLInputElement.prototype,
|
|
683
|
+
"value"
|
|
684
|
+
);
|
|
685
|
+
const setter = descriptor && descriptor.set;
|
|
686
|
+
if (setter) {
|
|
687
|
+
setter.call(input, value);
|
|
688
|
+
} else {
|
|
689
|
+
input.value = value;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// src/bind-mask.ts
|
|
694
|
+
var IS_JSDOM = typeof navigator !== "undefined" && navigator.userAgent.includes("jsdom");
|
|
695
|
+
function createMaskController(maskUtils, options) {
|
|
696
|
+
let input = null;
|
|
697
|
+
let lastValue = "";
|
|
698
|
+
let lastSelection = { start: null, end: null };
|
|
699
|
+
function getInputState() {
|
|
700
|
+
return { value: input.value, selection: getInputSelection(input) };
|
|
701
|
+
}
|
|
702
|
+
function getLastInputState() {
|
|
703
|
+
return { value: lastValue, selection: lastSelection };
|
|
704
|
+
}
|
|
705
|
+
function setInputState({ value, selection }) {
|
|
706
|
+
setNativeValue(input, value);
|
|
707
|
+
lastValue = value;
|
|
708
|
+
if (input && isInputFocused(input) && selection.start !== null && selection.end !== null) {
|
|
709
|
+
setInputSelection(input, selection.start, selection.end);
|
|
710
|
+
lastSelection = getInputSelection(input);
|
|
711
|
+
} else {
|
|
712
|
+
lastSelection = selection;
|
|
713
|
+
}
|
|
714
|
+
if (IS_JSDOM) {
|
|
715
|
+
const resyncValue = value;
|
|
716
|
+
const resyncSelection = selection;
|
|
717
|
+
queueMicrotask(() => {
|
|
718
|
+
if (!input || input.value !== resyncValue) return;
|
|
719
|
+
input.value = resyncValue;
|
|
720
|
+
if (isInputFocused(input) && resyncSelection.start !== null && resyncSelection.end !== null) {
|
|
721
|
+
setInputSelection(input, resyncSelection.start, resyncSelection.end);
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
function handleInput() {
|
|
727
|
+
const currentState = getInputState();
|
|
728
|
+
const previousState = getLastInputState();
|
|
729
|
+
let nextState = maskUtils.processChange(currentState, previousState);
|
|
730
|
+
if (options.beforeMaskedStateChange) {
|
|
731
|
+
nextState = options.beforeMaskedStateChange({ currentState, previousState, nextState });
|
|
732
|
+
}
|
|
733
|
+
setInputState(nextState);
|
|
734
|
+
}
|
|
735
|
+
function handleFocus() {
|
|
736
|
+
const currentValue = getInputState().value;
|
|
737
|
+
if (!maskUtils.isValueFilled(currentValue)) {
|
|
738
|
+
const newValue = maskUtils.formatValue(currentValue);
|
|
739
|
+
const newSelection = maskUtils.getDefaultSelectionForValue(newValue);
|
|
740
|
+
let nextState = { value: newValue, selection: newSelection };
|
|
741
|
+
if (options.beforeMaskedStateChange) {
|
|
742
|
+
nextState = options.beforeMaskedStateChange({ currentState: getInputState(), nextState });
|
|
743
|
+
}
|
|
744
|
+
setInputState(nextState);
|
|
745
|
+
defer(() => {
|
|
746
|
+
if (input && isInputFocused(input)) {
|
|
747
|
+
setInputSelection(input, lastSelection.start, lastSelection.end);
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
function handleBlur() {
|
|
753
|
+
const lastValueOnBlur = getLastInputState().value;
|
|
754
|
+
if (!options.alwaysShowMask && maskUtils.isValueEmpty(lastValueOnBlur)) {
|
|
755
|
+
let nextState = { value: "", selection: { start: null, end: null } };
|
|
756
|
+
if (options.beforeMaskedStateChange) {
|
|
757
|
+
nextState = options.beforeMaskedStateChange({ currentState: getInputState(), nextState });
|
|
758
|
+
}
|
|
759
|
+
setInputState(nextState);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
function handleMouseDown(event) {
|
|
763
|
+
if (!input) return;
|
|
764
|
+
const { value } = getInputState();
|
|
765
|
+
const inputDocument = getElementDocument(input);
|
|
766
|
+
if (!isInputFocused(input) && !maskUtils.isValueFilled(value)) {
|
|
767
|
+
const mouseDownX = event.clientX;
|
|
768
|
+
const mouseDownY = event.clientY;
|
|
769
|
+
const mouseDownTime = (/* @__PURE__ */ new Date()).getTime();
|
|
770
|
+
const mouseUpHandler = (mouseUpEvent) => {
|
|
771
|
+
inputDocument.removeEventListener("mouseup", mouseUpHandler);
|
|
772
|
+
if (!input || !isInputFocused(input)) return;
|
|
773
|
+
const deltaX = Math.abs(mouseUpEvent.clientX - mouseDownX);
|
|
774
|
+
const deltaY = Math.abs(mouseUpEvent.clientY - mouseDownY);
|
|
775
|
+
const axisDelta = Math.max(deltaX, deltaY);
|
|
776
|
+
const timeDelta = (/* @__PURE__ */ new Date()).getTime() - mouseDownTime;
|
|
777
|
+
if (axisDelta <= 10 && timeDelta <= 200 || axisDelta <= 5 && timeDelta <= 300) {
|
|
778
|
+
const newSelection = maskUtils.getDefaultSelectionForValue(lastValue);
|
|
779
|
+
if (newSelection.start !== null && newSelection.end !== null) {
|
|
780
|
+
setInputSelection(input, newSelection.start, newSelection.end);
|
|
781
|
+
lastSelection = getInputSelection(input);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
inputDocument.addEventListener("mouseup", mouseUpHandler);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
function bind(el) {
|
|
789
|
+
input = el;
|
|
790
|
+
lastValue = el.value;
|
|
791
|
+
lastSelection = getInputSelection(el);
|
|
792
|
+
const formatted = maskUtils.formatValue(el.value);
|
|
793
|
+
if (!maskUtils.isValueEmpty(formatted) || options.alwaysShowMask) {
|
|
794
|
+
setNativeValue(el, formatted);
|
|
795
|
+
lastValue = formatted;
|
|
796
|
+
}
|
|
797
|
+
el.addEventListener("input", handleInput);
|
|
798
|
+
el.addEventListener("focus", handleFocus);
|
|
799
|
+
el.addEventListener("blur", handleBlur);
|
|
800
|
+
el.addEventListener("mousedown", handleMouseDown);
|
|
801
|
+
}
|
|
802
|
+
function unbind() {
|
|
803
|
+
if (input) {
|
|
804
|
+
input.removeEventListener("input", handleInput);
|
|
805
|
+
input.removeEventListener("focus", handleFocus);
|
|
806
|
+
input.removeEventListener("blur", handleBlur);
|
|
807
|
+
input.removeEventListener("mousedown", handleMouseDown);
|
|
808
|
+
}
|
|
809
|
+
input = null;
|
|
810
|
+
}
|
|
811
|
+
function update(nextMaskUtils, nextOptions) {
|
|
812
|
+
maskUtils = nextMaskUtils;
|
|
813
|
+
options = nextOptions;
|
|
814
|
+
}
|
|
815
|
+
return { bind, unbind, update };
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
// src/use-mask.ts
|
|
819
|
+
function useMask(options) {
|
|
820
|
+
const {
|
|
821
|
+
mask,
|
|
822
|
+
maskPlaceholder: maskPlaceholderProp,
|
|
823
|
+
alwaysShowMask = false,
|
|
824
|
+
formatChars,
|
|
825
|
+
transform,
|
|
826
|
+
beforeMaskedStateChange: beforeMaskedStateChangeProp,
|
|
827
|
+
beforeMaskedValueChange
|
|
828
|
+
} = options;
|
|
829
|
+
if (beforeMaskedValueChange !== void 0) {
|
|
830
|
+
warnDeprecatedOnce(
|
|
831
|
+
"beforeMaskedValueChange",
|
|
832
|
+
"beforeMaskedValueChange is deprecated, use beforeMaskedStateChange."
|
|
833
|
+
);
|
|
834
|
+
}
|
|
835
|
+
const resolvedPlaceholder = resolveMaskPlaceholder(maskPlaceholderProp, void 0);
|
|
836
|
+
const maskPlaceholder = resolvedPlaceholder === void 0 ? "_" : resolvedPlaceholder;
|
|
837
|
+
const { formatChars: normalizedFormatChars, hasLegacyString } = normalizeFormatChars(formatChars);
|
|
838
|
+
if (hasLegacyString) {
|
|
839
|
+
warnDeprecatedOnce(
|
|
840
|
+
"formatChars",
|
|
841
|
+
"string values in formatChars are deprecated, pass RegExp values instead."
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
const maskUtils = new MaskUtils({
|
|
845
|
+
mask: mask != null ? mask : null,
|
|
846
|
+
maskPlaceholder,
|
|
847
|
+
formatChars: normalizedFormatChars,
|
|
848
|
+
transform: resolveTransform(transform)
|
|
849
|
+
});
|
|
850
|
+
let beforeMaskedStateChange = beforeMaskedStateChangeProp;
|
|
851
|
+
if (!beforeMaskedStateChange && beforeMaskedValueChange) {
|
|
852
|
+
const v2MaskOptions = {
|
|
853
|
+
mask: mask != null ? mask : void 0,
|
|
854
|
+
maskChar: maskPlaceholder,
|
|
855
|
+
alwaysShowMask,
|
|
856
|
+
formatChars: formatChars != null ? formatChars : { "9": "[0-9]", a: "[A-Za-z]", "*": "[A-Za-z0-9]" },
|
|
857
|
+
permanents: maskUtils.maskOptions.permanents
|
|
858
|
+
};
|
|
859
|
+
beforeMaskedStateChange = createBeforeMaskedStateChangeAdapter(beforeMaskedValueChange, v2MaskOptions);
|
|
860
|
+
}
|
|
861
|
+
const controllerOptions = { alwaysShowMask, beforeMaskedStateChange };
|
|
862
|
+
const controllerRef = (0, import_react2.useRef)(null);
|
|
863
|
+
(0, import_react2.useEffect)(() => {
|
|
864
|
+
var _a;
|
|
865
|
+
(_a = controllerRef.current) == null ? void 0 : _a.update(maskUtils, controllerOptions);
|
|
866
|
+
});
|
|
867
|
+
return (0, import_react2.useCallback)((el) => {
|
|
868
|
+
var _a;
|
|
869
|
+
if (el) {
|
|
870
|
+
const controller = createMaskController(maskUtils, controllerOptions);
|
|
871
|
+
controller.bind(el);
|
|
872
|
+
controllerRef.current = controller;
|
|
873
|
+
} else {
|
|
874
|
+
(_a = controllerRef.current) == null ? void 0 : _a.unbind();
|
|
875
|
+
controllerRef.current = null;
|
|
876
|
+
}
|
|
877
|
+
}, []);
|
|
878
|
+
}
|
|
879
|
+
|
|
675
880
|
// src/index.tsx
|
|
676
|
-
var InputMask = (0,
|
|
881
|
+
var InputMask = (0, import_react3.forwardRef)(function InputMask2(props, forwardedRef) {
|
|
677
882
|
const {
|
|
678
883
|
alwaysShowMask = false,
|
|
679
884
|
children,
|
|
@@ -856,7 +1061,7 @@ var InputMask = (0, import_react2.forwardRef)(function InputMask2(props, forward
|
|
|
856
1061
|
renderValue = newValue;
|
|
857
1062
|
}
|
|
858
1063
|
const lastSelection = getLastInputState().selection;
|
|
859
|
-
(0,
|
|
1064
|
+
(0, import_react3.useLayoutEffect)(() => {
|
|
860
1065
|
if (isMasked && isControlled) {
|
|
861
1066
|
setInputState({
|
|
862
1067
|
...getLastInputState(),
|
|
@@ -864,7 +1069,7 @@ var InputMask = (0, import_react2.forwardRef)(function InputMask2(props, forward
|
|
|
864
1069
|
});
|
|
865
1070
|
}
|
|
866
1071
|
});
|
|
867
|
-
(0,
|
|
1072
|
+
(0, import_react3.useLayoutEffect)(() => {
|
|
868
1073
|
if (!isMasked) {
|
|
869
1074
|
return;
|
|
870
1075
|
}
|
|
@@ -921,15 +1126,16 @@ var InputMask = (0, import_react2.forwardRef)(function InputMask2(props, forward
|
|
|
921
1126
|
};
|
|
922
1127
|
if (children) {
|
|
923
1128
|
validateChildren(props, children);
|
|
924
|
-
return
|
|
1129
|
+
return import_react3.default.cloneElement(children, inputProps);
|
|
925
1130
|
}
|
|
926
|
-
return /* @__PURE__ */
|
|
1131
|
+
return /* @__PURE__ */ import_react3.default.createElement("input", { ...inputProps });
|
|
927
1132
|
});
|
|
928
1133
|
InputMask.displayName = "InputMask";
|
|
929
1134
|
var src_default = InputMask;
|
|
930
1135
|
// Annotate the CommonJS export names for ESM import in node:
|
|
931
1136
|
0 && (module.exports = {
|
|
932
1137
|
defaultFormatChars,
|
|
933
|
-
extendedFormatChars
|
|
1138
|
+
extendedFormatChars,
|
|
1139
|
+
useMask
|
|
934
1140
|
});
|
|
935
1141
|
//# sourceMappingURL=index.cjs.map
|