react-input-mask-format 1.0.5 → 2.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/dist/index.js ADDED
@@ -0,0 +1,899 @@
1
+ // src/index.tsx
2
+ import React, { useLayoutEffect as useLayoutEffect2, forwardRef } from "react";
3
+
4
+ // src/hooks.ts
5
+ import { useCallback, useEffect, useLayoutEffect, useRef } from "react";
6
+
7
+ // src/utils/defer.ts
8
+ function defer(fn) {
9
+ return requestAnimationFrame(fn);
10
+ }
11
+ function cancelDefer(deferId) {
12
+ if (deferId !== null) {
13
+ cancelAnimationFrame(deferId);
14
+ }
15
+ }
16
+
17
+ // src/utils/input.ts
18
+ function setInputSelection(input, start, end) {
19
+ if (end === void 0) {
20
+ end = start;
21
+ }
22
+ input.setSelectionRange(start, end);
23
+ }
24
+ function getInputSelection(input) {
25
+ const start = input.selectionStart;
26
+ const end = input.selectionEnd;
27
+ return {
28
+ start,
29
+ end,
30
+ length: (end != null ? end : 0) - (start != null ? start : 0)
31
+ };
32
+ }
33
+ function isInputFocused(input) {
34
+ const inputDocument = input.ownerDocument;
35
+ return inputDocument.hasFocus() && inputDocument.activeElement === input;
36
+ }
37
+
38
+ // src/utils/helpers.ts
39
+ function getElementDocument(element) {
40
+ return element == null ? void 0 : element.ownerDocument;
41
+ }
42
+ function getElementWindow(element) {
43
+ var _a;
44
+ return (_a = getElementDocument(element)) == null ? void 0 : _a.defaultView;
45
+ }
46
+ function isDOMElement(element) {
47
+ const elementWindow = getElementWindow(element);
48
+ return !!elementWindow && element instanceof elementWindow.HTMLElement;
49
+ }
50
+ function isFunction(value) {
51
+ return typeof value === "function";
52
+ }
53
+ function findLastIndex(array, predicate) {
54
+ for (let i = array.length - 1; i >= 0; i--) {
55
+ const x = array[i];
56
+ if (predicate(x, i)) {
57
+ return i;
58
+ }
59
+ }
60
+ return -1;
61
+ }
62
+ function repeat(string, n = 1) {
63
+ let result = "";
64
+ for (let i = 0; i < n; i++) {
65
+ result += string;
66
+ }
67
+ return result;
68
+ }
69
+ function toString(value) {
70
+ return `${value}`;
71
+ }
72
+
73
+ // src/hooks.ts
74
+ function useInputElement(inputRef) {
75
+ return useCallback(() => {
76
+ let input = inputRef.current;
77
+ const isDOMNode = typeof window !== "undefined" && isDOMElement(input);
78
+ if (!input || !isDOMNode) {
79
+ return null;
80
+ }
81
+ if (input.nodeName !== "INPUT") {
82
+ input = input.querySelector("input");
83
+ }
84
+ if (!input) {
85
+ throw new Error("react-input-mask: inputComponent doesn't contain input node");
86
+ }
87
+ return input;
88
+ }, [inputRef]);
89
+ }
90
+ function useDeferLoop(callback) {
91
+ const deferIdRef = useRef(null);
92
+ const runLoop = useCallback(() => {
93
+ if (deferIdRef.current !== null) {
94
+ return;
95
+ }
96
+ function loop() {
97
+ callback();
98
+ deferIdRef.current = defer(loop);
99
+ }
100
+ loop();
101
+ }, [callback]);
102
+ const stopLoop = useCallback(() => {
103
+ cancelDefer(deferIdRef.current);
104
+ deferIdRef.current = null;
105
+ }, []);
106
+ useEffect(() => {
107
+ if (deferIdRef.current) {
108
+ stopLoop();
109
+ runLoop();
110
+ }
111
+ }, [runLoop, stopLoop]);
112
+ useEffect(() => cancelDefer(deferIdRef.current), []);
113
+ return [runLoop, stopLoop];
114
+ }
115
+ function useSelection(inputRef, isMasked) {
116
+ const selectionRef = useRef({ start: null, end: null });
117
+ const getInputElement = useInputElement(inputRef);
118
+ const getSelection = useCallback(() => {
119
+ const input = getInputElement();
120
+ return getInputSelection(input);
121
+ }, [getInputElement]);
122
+ const getLastSelection = useCallback(() => {
123
+ return selectionRef.current;
124
+ }, []);
125
+ const setSelection = useCallback(
126
+ (selection) => {
127
+ const input = getInputElement();
128
+ if (!input || !isInputFocused(input)) {
129
+ return;
130
+ }
131
+ setInputSelection(input, selection.start, selection.end);
132
+ selectionRef.current = getSelection();
133
+ },
134
+ [getInputElement, getSelection]
135
+ );
136
+ const selectionLoop = useCallback(() => {
137
+ selectionRef.current = getSelection();
138
+ }, [getSelection]);
139
+ const [runSelectionLoop, stopSelectionLoop] = useDeferLoop(selectionLoop);
140
+ useLayoutEffect(() => {
141
+ if (!isMasked) {
142
+ return;
143
+ }
144
+ const input = getInputElement();
145
+ if (!input) return;
146
+ input.addEventListener("focus", runSelectionLoop);
147
+ input.addEventListener("blur", stopSelectionLoop);
148
+ if (isInputFocused(input)) {
149
+ runSelectionLoop();
150
+ }
151
+ return () => {
152
+ input.removeEventListener("focus", runSelectionLoop);
153
+ input.removeEventListener("blur", stopSelectionLoop);
154
+ stopSelectionLoop();
155
+ };
156
+ });
157
+ return { getSelection, getLastSelection, setSelection };
158
+ }
159
+ function useValue(inputRef, initialValue) {
160
+ const getInputElement = useInputElement(inputRef);
161
+ const valueRef = useRef(initialValue);
162
+ const getValue = useCallback(() => {
163
+ return getInputElement().value;
164
+ }, [getInputElement]);
165
+ const getLastValue = useCallback(() => {
166
+ return valueRef.current;
167
+ }, []);
168
+ const setValue = useCallback(
169
+ (newValue) => {
170
+ valueRef.current = newValue;
171
+ const input = getInputElement();
172
+ if (input) {
173
+ input.value = newValue;
174
+ }
175
+ },
176
+ [getInputElement]
177
+ );
178
+ return {
179
+ getValue,
180
+ getLastValue,
181
+ setValue
182
+ };
183
+ }
184
+ function useInputState(initialValue, isMasked) {
185
+ const inputRef = useRef(null);
186
+ const { getSelection, getLastSelection, setSelection } = useSelection(inputRef, isMasked);
187
+ const { getValue, getLastValue, setValue } = useValue(inputRef, initialValue);
188
+ function getLastInputState() {
189
+ return {
190
+ value: getLastValue(),
191
+ selection: getLastSelection()
192
+ };
193
+ }
194
+ function getInputState() {
195
+ return {
196
+ value: getValue(),
197
+ selection: getSelection()
198
+ };
199
+ }
200
+ function setInputState({ value, selection }) {
201
+ setValue(value);
202
+ setSelection(selection);
203
+ }
204
+ return {
205
+ inputRef,
206
+ getInputState,
207
+ getLastInputState,
208
+ setInputState
209
+ };
210
+ }
211
+ function usePrevious(value) {
212
+ const ref = useRef(void 0);
213
+ useEffect(() => {
214
+ ref.current = value;
215
+ });
216
+ return ref.current;
217
+ }
218
+
219
+ // src/constants.ts
220
+ var CONTROLLED_PROPS = [
221
+ "disabled",
222
+ "onBlur",
223
+ "onChange",
224
+ "onFocus",
225
+ "onMouseDown",
226
+ "readOnly",
227
+ "value"
228
+ ];
229
+ var defaultFormatChars = {
230
+ "9": /[0-9]/,
231
+ a: /[A-Za-z]/,
232
+ "*": /[A-Za-z0-9]/
233
+ };
234
+ var extendedFormatChars = {
235
+ ...defaultFormatChars,
236
+ A: /[A-Z]/,
237
+ "\u042F": /[А-Яа-яЁёӘәҒғҚқҢңӨөҰұҮүҺһІі]/,
238
+ "#": /[0-9A-Fa-f]/
239
+ };
240
+
241
+ // src/validate-props.ts
242
+ function warnDev(condition, message) {
243
+ if (process.env.NODE_ENV !== "production" && !condition) {
244
+ console.error(`react-input-mask-format: ${message}`);
245
+ }
246
+ }
247
+ function invariant(condition, message) {
248
+ if (!condition) {
249
+ throw new Error(`react-input-mask-format: ${message}`);
250
+ }
251
+ }
252
+ function validateMaxLength(props) {
253
+ warnDev(
254
+ !props.maxLength || !props.mask,
255
+ "maxLength property shouldn't be passed to the masked input. It breaks masking and unnecessary because length is limited by the mask length."
256
+ );
257
+ }
258
+ function validateMaskPlaceholder(props) {
259
+ const { mask, maskPlaceholder } = props;
260
+ invariant(
261
+ !mask || !maskPlaceholder || maskPlaceholder.length === 1 || maskPlaceholder.length === mask.length,
262
+ `maskPlaceholder should either be a single character or have the same length as the mask:
263
+ mask: ${mask}
264
+ maskPlaceholder: ${maskPlaceholder}`
265
+ );
266
+ }
267
+ function validateChildren(props, inputElement) {
268
+ const conflictProps = CONTROLLED_PROPS.filter(
269
+ (propId) => inputElement.props[propId] != null && inputElement.props[propId] !== props[propId]
270
+ );
271
+ invariant(
272
+ !conflictProps.length,
273
+ `the following props should be passed to the InputMask component, not to children: ${conflictProps.join(",")}`
274
+ );
275
+ }
276
+
277
+ // src/utils/parse-mask.ts
278
+ function parseMask({
279
+ mask,
280
+ maskPlaceholder,
281
+ formatChars = defaultFormatChars
282
+ }) {
283
+ const permanents = [];
284
+ if (!mask) {
285
+ return {
286
+ maskPlaceholder: null,
287
+ mask: null,
288
+ prefix: null,
289
+ lastEditablePosition: null,
290
+ permanents: []
291
+ };
292
+ }
293
+ let parsedMask;
294
+ if (typeof mask === "string") {
295
+ let isPermanent = false;
296
+ let parsedMaskString = "";
297
+ mask.split("").forEach((character) => {
298
+ if (!isPermanent && character === "\\") {
299
+ isPermanent = true;
300
+ } else {
301
+ if (isPermanent || !formatChars[character]) {
302
+ permanents.push(parsedMaskString.length);
303
+ }
304
+ parsedMaskString += character;
305
+ isPermanent = false;
306
+ }
307
+ });
308
+ parsedMask = parsedMaskString.split("").map((character, index) => {
309
+ if (permanents.indexOf(index) === -1) {
310
+ return formatChars[character];
311
+ }
312
+ return character;
313
+ });
314
+ } else {
315
+ mask.forEach((character, index) => {
316
+ if (typeof character === "string") {
317
+ permanents.push(index);
318
+ }
319
+ });
320
+ parsedMask = mask;
321
+ }
322
+ let parsedPlaceholder = maskPlaceholder != null ? maskPlaceholder : null;
323
+ if (parsedPlaceholder) {
324
+ let placeholderChars;
325
+ if (parsedPlaceholder.length === 1) {
326
+ placeholderChars = parsedMask.map((character, index) => {
327
+ if (permanents.indexOf(index) !== -1) {
328
+ return character;
329
+ }
330
+ return parsedPlaceholder;
331
+ });
332
+ } else {
333
+ placeholderChars = parsedPlaceholder.split("");
334
+ }
335
+ permanents.forEach((position) => {
336
+ placeholderChars[position] = parsedMask[position];
337
+ });
338
+ parsedPlaceholder = placeholderChars.join("");
339
+ }
340
+ const prefix = permanents.filter((position, index) => position === index).map((position) => parsedMask[position]).join("");
341
+ let lastEditablePosition = parsedMask.length - 1;
342
+ while (permanents.indexOf(lastEditablePosition) !== -1) {
343
+ lastEditablePosition--;
344
+ }
345
+ return {
346
+ maskPlaceholder: parsedPlaceholder,
347
+ prefix,
348
+ mask: parsedMask,
349
+ lastEditablePosition,
350
+ permanents
351
+ };
352
+ }
353
+
354
+ // src/utils/mask.ts
355
+ var MaskUtils = class {
356
+ constructor(options) {
357
+ this.isCharacterAllowedAtPosition = (character, position) => {
358
+ const { maskPlaceholder } = this.maskOptions;
359
+ if (this.isCharacterFillingPosition(character, position)) {
360
+ return true;
361
+ }
362
+ if (!maskPlaceholder) {
363
+ return false;
364
+ }
365
+ return maskPlaceholder[position] === character;
366
+ };
367
+ this.isCharacterFillingPosition = (character, position) => {
368
+ const { mask } = this.maskOptions;
369
+ if (!character || position >= mask.length) {
370
+ return false;
371
+ }
372
+ if (!this.isPositionEditable(position)) {
373
+ return mask[position] === character;
374
+ }
375
+ const charRule = mask[position];
376
+ return new RegExp(charRule).test(character);
377
+ };
378
+ this.isPositionEditable = (position) => {
379
+ const { mask, permanents } = this.maskOptions;
380
+ return position < mask.length && permanents.indexOf(position) === -1;
381
+ };
382
+ this.isValueEmpty = (value) => {
383
+ return value.split("").every((character, position) => {
384
+ return !this.isPositionEditable(position) || !this.isCharacterFillingPosition(character, position);
385
+ });
386
+ };
387
+ this.isValueFilled = (value) => {
388
+ return this.getFilledLength(value) === this.maskOptions.lastEditablePosition + 1;
389
+ };
390
+ this.getDefaultSelectionForValue = (value) => {
391
+ const filledLength = this.getFilledLength(value);
392
+ const cursorPosition = this.getRightEditablePosition(filledLength);
393
+ return { start: cursorPosition, end: cursorPosition };
394
+ };
395
+ this.getFilledLength = (value) => {
396
+ const characters = value.split("");
397
+ const lastFilledIndex = findLastIndex(characters, (character, position) => {
398
+ return this.isPositionEditable(position) && this.isCharacterFillingPosition(character, position);
399
+ });
400
+ return lastFilledIndex + 1;
401
+ };
402
+ this.getStringFillingLengthAtPosition = (string, position) => {
403
+ const characters = string.split("");
404
+ const insertedValue = characters.reduce((value, character) => {
405
+ return this.insertCharacterAtPosition(value, character, value.length);
406
+ }, repeat(" ", position));
407
+ return insertedValue.length - position;
408
+ };
409
+ this.getLeftEditablePosition = (position) => {
410
+ for (let i = position; i >= 0; i--) {
411
+ if (this.isPositionEditable(i)) {
412
+ return i;
413
+ }
414
+ }
415
+ return null;
416
+ };
417
+ this.getRightEditablePosition = (position) => {
418
+ const { mask } = this.maskOptions;
419
+ for (let i = position; i < mask.length; i++) {
420
+ if (this.isPositionEditable(i)) {
421
+ return i;
422
+ }
423
+ }
424
+ return null;
425
+ };
426
+ this.formatValue = (value) => {
427
+ const { maskPlaceholder, mask } = this.maskOptions;
428
+ if (!maskPlaceholder) {
429
+ value = this.insertStringAtPosition("", value, 0);
430
+ while (value.length < mask.length && !this.isPositionEditable(value.length)) {
431
+ value += mask[value.length];
432
+ }
433
+ return value;
434
+ }
435
+ return this.insertStringAtPosition(maskPlaceholder, value, 0);
436
+ };
437
+ this.clearRange = (value, start, len) => {
438
+ if (!len) {
439
+ return value;
440
+ }
441
+ const end = start + len;
442
+ const { maskPlaceholder, mask } = this.maskOptions;
443
+ const clearedValue = value.split("").map((character, i) => {
444
+ const isEditable = this.isPositionEditable(i);
445
+ if (!maskPlaceholder && i >= end && !isEditable) {
446
+ return "";
447
+ }
448
+ if (i < start || i >= end) {
449
+ return character;
450
+ }
451
+ if (!isEditable) {
452
+ return mask[i];
453
+ }
454
+ if (maskPlaceholder) {
455
+ return maskPlaceholder[i];
456
+ }
457
+ return "";
458
+ }).join("");
459
+ return this.formatValue(clearedValue);
460
+ };
461
+ this.insertCharacterAtPosition = (value, character, position) => {
462
+ const { mask, maskPlaceholder } = this.maskOptions;
463
+ if (position >= mask.length) {
464
+ return value;
465
+ }
466
+ const transformedCharacter = this.transform && this.isPositionEditable(position) ? this.transform(character, position) : character;
467
+ const isAllowed = this.isCharacterAllowedAtPosition(transformedCharacter, position);
468
+ const isEditable = this.isPositionEditable(position);
469
+ const nextEditablePosition = this.getRightEditablePosition(position);
470
+ const isNextPlaceholder = maskPlaceholder && nextEditablePosition ? transformedCharacter === maskPlaceholder[nextEditablePosition] : null;
471
+ const valueBefore = value.slice(0, position);
472
+ if (isAllowed || !isEditable) {
473
+ const insertedCharacter = isAllowed ? transformedCharacter : mask[position];
474
+ value = valueBefore + insertedCharacter;
475
+ }
476
+ if (!isAllowed && !isEditable && !isNextPlaceholder) {
477
+ value = this.insertCharacterAtPosition(value, character, position + 1);
478
+ }
479
+ return value;
480
+ };
481
+ this.insertStringAtPosition = (value, string, position) => {
482
+ const { mask, maskPlaceholder } = this.maskOptions;
483
+ if (!string || position >= mask.length) {
484
+ return value;
485
+ }
486
+ const characters = string.split("");
487
+ const isFixedLength = this.isValueFilled(value) || !!maskPlaceholder;
488
+ const valueAfter = value.slice(position);
489
+ value = characters.reduce((value2, character) => {
490
+ return this.insertCharacterAtPosition(value2, character, value2.length);
491
+ }, value.slice(0, position));
492
+ if (isFixedLength) {
493
+ value += valueAfter.slice(value.length - position);
494
+ } else if (this.isValueFilled(value)) {
495
+ value += mask.slice(value.length).join("");
496
+ } else {
497
+ const editableCharactersAfter = valueAfter.split("").filter((character, i) => {
498
+ return this.isPositionEditable(position + i);
499
+ });
500
+ value = editableCharactersAfter.reduce((value2, character) => {
501
+ const nextEditablePosition = this.getRightEditablePosition(
502
+ value2.length
503
+ );
504
+ if (nextEditablePosition === null) {
505
+ return value2;
506
+ }
507
+ if (!this.isPositionEditable(value2.length)) {
508
+ value2 += mask.slice(value2.length, nextEditablePosition).join("");
509
+ }
510
+ return this.insertCharacterAtPosition(value2, character, value2.length);
511
+ }, value);
512
+ }
513
+ return value;
514
+ };
515
+ this.processChange = (currentState, previousState) => {
516
+ const { mask, prefix, lastEditablePosition } = this.maskOptions;
517
+ const { value, selection } = currentState;
518
+ const previousValue = previousState.value;
519
+ const previousSelection = previousState.selection;
520
+ let newValue = value;
521
+ let enteredString = "";
522
+ let formattedEnteredStringLength = 0;
523
+ let removedLength = 0;
524
+ let cursorPosition = Math.min(previousSelection.start, selection.start);
525
+ if (selection.end > previousSelection.start) {
526
+ enteredString = newValue.slice(previousSelection.start, selection.end);
527
+ formattedEnteredStringLength = this.getStringFillingLengthAtPosition(
528
+ enteredString,
529
+ cursorPosition
530
+ );
531
+ if (!formattedEnteredStringLength) {
532
+ removedLength = 0;
533
+ } else {
534
+ removedLength = previousSelection.length;
535
+ }
536
+ } else if (newValue.length < previousValue.length) {
537
+ removedLength = previousValue.length - newValue.length;
538
+ }
539
+ newValue = previousValue;
540
+ if (removedLength) {
541
+ if (removedLength === 1 && !previousSelection.length) {
542
+ const deleteFromRight = previousSelection.start === selection.start;
543
+ cursorPosition = deleteFromRight ? this.getRightEditablePosition(selection.start) : this.getLeftEditablePosition(selection.start);
544
+ }
545
+ newValue = this.clearRange(newValue, cursorPosition, removedLength);
546
+ }
547
+ newValue = this.insertStringAtPosition(
548
+ newValue,
549
+ enteredString,
550
+ cursorPosition
551
+ );
552
+ cursorPosition += formattedEnteredStringLength;
553
+ if (cursorPosition >= mask.length) {
554
+ cursorPosition = mask.length;
555
+ } else if (cursorPosition < prefix.length && !formattedEnteredStringLength) {
556
+ cursorPosition = prefix.length;
557
+ } else if (cursorPosition >= prefix.length && cursorPosition < lastEditablePosition && formattedEnteredStringLength) {
558
+ cursorPosition = this.getRightEditablePosition(cursorPosition);
559
+ }
560
+ newValue = this.formatValue(newValue);
561
+ return {
562
+ value: newValue,
563
+ enteredString,
564
+ selection: { start: cursorPosition, end: cursorPosition }
565
+ };
566
+ };
567
+ this.maskOptions = parseMask(options);
568
+ this.transform = options.transform;
569
+ }
570
+ };
571
+
572
+ // src/v2-compat.ts
573
+ var warned = /* @__PURE__ */ new Set();
574
+ function warnDeprecatedOnce(prop, message) {
575
+ if (process.env.NODE_ENV !== "production" && !warned.has(prop)) {
576
+ warned.add(prop);
577
+ console.warn(`react-input-mask-format: ${message}`);
578
+ }
579
+ }
580
+ function resolveMaskPlaceholder(maskPlaceholder, maskChar) {
581
+ if (maskPlaceholder !== void 0) {
582
+ return maskPlaceholder;
583
+ }
584
+ return maskChar;
585
+ }
586
+ function normalizeFormatChars(formatChars) {
587
+ if (!formatChars) {
588
+ return { formatChars: void 0, hasLegacyString: false };
589
+ }
590
+ const result = {};
591
+ let hasLegacyString = false;
592
+ for (const key of Object.keys(formatChars)) {
593
+ const value = formatChars[key];
594
+ if (typeof value === "string") {
595
+ hasLegacyString = true;
596
+ result[key] = new RegExp(value);
597
+ } else {
598
+ result[key] = value;
599
+ }
600
+ }
601
+ return { formatChars: result, hasLegacyString };
602
+ }
603
+ function createBeforeMaskedStateChangeAdapter(beforeMaskedValueChange, maskOptions) {
604
+ return ({ previousState, currentState, nextState }) => {
605
+ var _a, _b;
606
+ return beforeMaskedValueChange(
607
+ nextState,
608
+ (_a = previousState != null ? previousState : currentState) != null ? _a : null,
609
+ (_b = nextState.enteredString) != null ? _b : null,
610
+ maskOptions
611
+ );
612
+ };
613
+ }
614
+
615
+ // src/utils/transform.ts
616
+ function resolveTransform(transform) {
617
+ if (!transform) {
618
+ return void 0;
619
+ }
620
+ if (transform === "uppercase") {
621
+ return (char) => char.toUpperCase();
622
+ }
623
+ if (transform === "lowercase") {
624
+ return (char) => char.toLowerCase();
625
+ }
626
+ if (typeof transform === "function") {
627
+ return transform;
628
+ }
629
+ if (process.env.NODE_ENV !== "production") {
630
+ console.error(
631
+ `react-input-mask-format: invalid transform "${String(
632
+ transform
633
+ )}", expected "uppercase" | "lowercase" | (char, position) => char`
634
+ );
635
+ }
636
+ return void 0;
637
+ }
638
+
639
+ // src/index.tsx
640
+ var InputMask = forwardRef(function InputMask2(props, forwardedRef) {
641
+ const {
642
+ alwaysShowMask = false,
643
+ children,
644
+ mask,
645
+ maskPlaceholder: maskPlaceholderProp,
646
+ beforeMaskedStateChange: beforeMaskedStateChangeProp,
647
+ transform,
648
+ maskChar,
649
+ formatChars,
650
+ beforeMaskedValueChange,
651
+ ...restProps
652
+ } = props;
653
+ if (maskChar !== void 0) {
654
+ warnDeprecatedOnce("maskChar", "maskChar is deprecated, use maskPlaceholder instead. See migration guide: https://github.com/Temirtator/react-input-mask-format#migrating-from-react-input-mask");
655
+ }
656
+ if (beforeMaskedValueChange !== void 0) {
657
+ warnDeprecatedOnce("beforeMaskedValueChange", "beforeMaskedValueChange is deprecated, use beforeMaskedStateChange. See migration guide: https://github.com/Temirtator/react-input-mask-format#migrating-from-react-input-mask");
658
+ }
659
+ const resolvedPlaceholder = resolveMaskPlaceholder(maskPlaceholderProp, maskChar);
660
+ const maskPlaceholder = resolvedPlaceholder === void 0 ? "_" : resolvedPlaceholder;
661
+ validateMaxLength(props);
662
+ validateMaskPlaceholder({ ...props, maskPlaceholder });
663
+ const { formatChars: normalizedFormatChars, hasLegacyString } = normalizeFormatChars(formatChars);
664
+ if (hasLegacyString) {
665
+ warnDeprecatedOnce(
666
+ "formatChars",
667
+ 'string values in formatChars are deprecated, pass RegExp values instead (e.g. { "#": /[0-9]/ }). See migration guide: https://github.com/Temirtator/react-input-mask-format#migrating-from-react-input-mask'
668
+ );
669
+ }
670
+ const maskUtils = new MaskUtils({
671
+ mask,
672
+ maskPlaceholder,
673
+ formatChars: normalizedFormatChars,
674
+ transform: resolveTransform(transform)
675
+ });
676
+ let beforeMaskedStateChange = beforeMaskedStateChangeProp;
677
+ if (!beforeMaskedStateChange && beforeMaskedValueChange) {
678
+ const v2MaskOptions = {
679
+ mask,
680
+ maskChar: maskPlaceholder,
681
+ alwaysShowMask,
682
+ formatChars: formatChars != null ? formatChars : { "9": "[0-9]", a: "[A-Za-z]", "*": "[A-Za-z0-9]" },
683
+ permanents: maskUtils.maskOptions.permanents
684
+ };
685
+ beforeMaskedStateChange = createBeforeMaskedStateChangeAdapter(
686
+ beforeMaskedValueChange,
687
+ v2MaskOptions
688
+ );
689
+ }
690
+ const isMasked = !!mask;
691
+ const isEditable = !restProps.disabled && !restProps.readOnly;
692
+ const isControlled = props.value !== null && props.value !== void 0;
693
+ const previousIsMasked = usePrevious(isMasked);
694
+ const initialValue = toString(
695
+ (isControlled ? props.value : props.defaultValue) || ""
696
+ );
697
+ const {
698
+ inputRef,
699
+ getInputState,
700
+ setInputState,
701
+ getLastInputState
702
+ } = useInputState(initialValue, isMasked);
703
+ const getInputElement = useInputElement(inputRef);
704
+ function onChange(event) {
705
+ const currentState = getInputState();
706
+ const previousState = getLastInputState();
707
+ let newInputState = maskUtils.processChange(currentState, previousState);
708
+ if (beforeMaskedStateChange) {
709
+ newInputState = beforeMaskedStateChange({
710
+ currentState,
711
+ previousState,
712
+ nextState: newInputState
713
+ });
714
+ }
715
+ setInputState(newInputState);
716
+ if (props.onChange) {
717
+ props.onChange(event);
718
+ }
719
+ }
720
+ function onFocus(event) {
721
+ inputRef.current = event.target;
722
+ const currentValue = getInputState().value;
723
+ if (isMasked && !maskUtils.isValueFilled(currentValue)) {
724
+ let newValue = maskUtils.formatValue(currentValue);
725
+ let newSelection = maskUtils.getDefaultSelectionForValue(newValue);
726
+ let newInputState = {
727
+ value: newValue,
728
+ selection: newSelection
729
+ };
730
+ if (beforeMaskedStateChange) {
731
+ newInputState = beforeMaskedStateChange({
732
+ currentState: getInputState(),
733
+ nextState: newInputState
734
+ });
735
+ newValue = newInputState.value;
736
+ newSelection = newInputState.selection;
737
+ }
738
+ setInputState(newInputState);
739
+ if (newValue !== currentValue && props.onChange) {
740
+ props.onChange(event);
741
+ }
742
+ defer(() => {
743
+ setInputState(getLastInputState());
744
+ });
745
+ }
746
+ if (props.onFocus) {
747
+ props.onFocus(event);
748
+ }
749
+ }
750
+ function onBlur(event) {
751
+ const currentValue = getInputState().value;
752
+ const lastValue = getLastInputState().value;
753
+ if (isMasked && !alwaysShowMask && maskUtils.isValueEmpty(lastValue)) {
754
+ let newValue = "";
755
+ let newInputState = {
756
+ value: newValue,
757
+ selection: { start: null, end: null }
758
+ };
759
+ if (beforeMaskedStateChange) {
760
+ newInputState = beforeMaskedStateChange({
761
+ currentState: getInputState(),
762
+ nextState: newInputState
763
+ });
764
+ newValue = newInputState.value;
765
+ }
766
+ setInputState(newInputState);
767
+ if (newValue !== currentValue && props.onChange) {
768
+ props.onChange(event);
769
+ }
770
+ }
771
+ if (props.onBlur) {
772
+ props.onBlur(event);
773
+ }
774
+ }
775
+ function onMouseDown(event) {
776
+ const input = getInputElement();
777
+ const { value } = getInputState();
778
+ const inputDocument = getElementDocument(input);
779
+ if (!isInputFocused(input) && !maskUtils.isValueFilled(value)) {
780
+ const mouseDownX = event.clientX;
781
+ const mouseDownY = event.clientY;
782
+ const mouseDownTime = (/* @__PURE__ */ new Date()).getTime();
783
+ const mouseUpHandler = (mouseUpEvent) => {
784
+ inputDocument.removeEventListener("mouseup", mouseUpHandler);
785
+ if (!isInputFocused(input)) {
786
+ return;
787
+ }
788
+ const deltaX = Math.abs(mouseUpEvent.clientX - mouseDownX);
789
+ const deltaY = Math.abs(mouseUpEvent.clientY - mouseDownY);
790
+ const axisDelta = Math.max(deltaX, deltaY);
791
+ const timeDelta = (/* @__PURE__ */ new Date()).getTime() - mouseDownTime;
792
+ if (axisDelta <= 10 && timeDelta <= 200 || axisDelta <= 5 && timeDelta <= 300) {
793
+ const lastState = getLastInputState();
794
+ const newSelection = maskUtils.getDefaultSelectionForValue(
795
+ lastState.value
796
+ );
797
+ const newState = {
798
+ ...lastState,
799
+ selection: newSelection
800
+ };
801
+ setInputState(newState);
802
+ }
803
+ };
804
+ inputDocument.addEventListener("mouseup", mouseUpHandler);
805
+ }
806
+ if (props.onMouseDown) {
807
+ props.onMouseDown(event);
808
+ }
809
+ }
810
+ let renderValue = props.value;
811
+ if (isMasked && isControlled) {
812
+ const input = getInputElement();
813
+ const isFocused = !!input && isInputFocused(input);
814
+ let newValue = isFocused || alwaysShowMask || props.value ? maskUtils.formatValue(props.value) : props.value;
815
+ if (beforeMaskedStateChange) {
816
+ newValue = beforeMaskedStateChange({
817
+ nextState: { value: newValue, selection: { start: null, end: null } }
818
+ }).value;
819
+ }
820
+ renderValue = newValue;
821
+ }
822
+ const lastSelection = getLastInputState().selection;
823
+ useLayoutEffect2(() => {
824
+ if (isMasked && isControlled) {
825
+ setInputState({
826
+ ...getLastInputState(),
827
+ value: renderValue
828
+ });
829
+ }
830
+ });
831
+ useLayoutEffect2(() => {
832
+ if (!isMasked) {
833
+ return;
834
+ }
835
+ const input = getInputElement();
836
+ const isFocused = isInputFocused(input);
837
+ const previousSelection = lastSelection;
838
+ const currentState = getInputState();
839
+ let newInputState = { ...currentState };
840
+ if (!isControlled) {
841
+ const currentValue = currentState.value;
842
+ const formattedValue = maskUtils.formatValue(currentValue);
843
+ const isValueEmpty = maskUtils.isValueEmpty(formattedValue);
844
+ const shouldFormatValue = !isValueEmpty || isFocused || alwaysShowMask;
845
+ if (shouldFormatValue) {
846
+ newInputState.value = formattedValue;
847
+ } else if (isValueEmpty && !isFocused) {
848
+ newInputState.value = "";
849
+ }
850
+ }
851
+ if (isFocused && !previousIsMasked) {
852
+ newInputState.selection = maskUtils.getDefaultSelectionForValue(
853
+ newInputState.value
854
+ );
855
+ } else if (isControlled && isFocused && previousSelection) {
856
+ if (previousSelection.start !== null && previousSelection.end !== null) {
857
+ newInputState.selection = previousSelection;
858
+ }
859
+ }
860
+ if (beforeMaskedStateChange) {
861
+ newInputState = beforeMaskedStateChange({
862
+ currentState,
863
+ nextState: newInputState
864
+ });
865
+ }
866
+ setInputState(newInputState);
867
+ });
868
+ const inputProps = {
869
+ ...restProps,
870
+ onFocus,
871
+ onBlur,
872
+ onChange: isMasked && isEditable ? onChange : props.onChange,
873
+ onMouseDown: isMasked && isEditable ? onMouseDown : props.onMouseDown,
874
+ // `ref` may target either the plain <input> DOM node or, when custom
875
+ // children are used, whatever node the child's own ref forwards to.
876
+ ref: (ref) => {
877
+ inputRef.current = ref;
878
+ if (isFunction(forwardedRef)) {
879
+ forwardedRef(ref);
880
+ } else if (forwardedRef !== null && typeof forwardedRef === "object") {
881
+ forwardedRef.current = ref;
882
+ }
883
+ },
884
+ value: isMasked && isControlled ? renderValue : props.value
885
+ };
886
+ if (children) {
887
+ validateChildren(props, children);
888
+ return React.cloneElement(children, inputProps);
889
+ }
890
+ return /* @__PURE__ */ React.createElement("input", { ...inputProps });
891
+ });
892
+ InputMask.displayName = "InputMask";
893
+ var src_default = InputMask;
894
+ export {
895
+ src_default as default,
896
+ defaultFormatChars,
897
+ extendedFormatChars
898
+ };
899
+ //# sourceMappingURL=index.js.map