react-hook-mask
Version:
React masked input component and hooks
349 lines • 19.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getExpectedCursorPos = void 0;
var maskMain = function (value, maskGenerator) {
var _a, _b;
value = value.toString();
var rules = maskGenerator.rules;
var mask = maskGenerator.generateMask(value);
var transform = maskGenerator.transform;
var len = value.length;
var maskLen = mask.length;
var pos = 0;
var newValue = '';
for (var i = 0; i < Math.min(len, maskLen); i++) {
var maskChar = mask.charAt(i);
var newChar = value.charAt(pos);
var regex = rules.get(maskChar);
if (regex) {
pos++;
if (regex.test(newChar)) {
newValue += newChar;
}
else {
i--;
len--;
}
}
else {
if (maskChar === newChar) {
pos++;
}
else {
len++;
}
newValue += maskChar;
}
}
var transformOffset = 0;
if (transform) {
var beforeTransform = newValue;
newValue = transform(beforeTransform);
transformOffset = ((_a = newValue === null || newValue === void 0 ? void 0 : newValue.length) !== null && _a !== void 0 ? _a : 0) - ((_b = beforeTransform === null || beforeTransform === void 0 ? void 0 : beforeTransform.length) !== null && _b !== void 0 ? _b : 0);
}
return { maskedValue: newValue, mask: mask, transformOffset: transformOffset };
};
var mask = function (value, maskGenerator) {
var _a = maskMain(value, maskGenerator), maskedValue = _a.maskedValue, mask = _a.mask, transformOffset = _a.transformOffset;
var _b = maskMain(maskedValue !== null && maskedValue !== void 0 ? maskedValue : '', maskGenerator), shouldBeTheSame = _b.maskedValue, newMask = _b.mask;
if (maskedValue !== shouldBeTheSame) {
if (typeof console !== 'undefined') {
console === null || console === void 0 ? void 0 : console.error('mask applied to value should not change when applied again', '-> before: ' + value, '-> after: ' + maskedValue + ' (mask: ' + mask + ')', '-> again: ' + shouldBeTheSame + ' (mask: ' + newMask + ')');
}
return { maskedValue: value, mask: mask, transformOffset: 0 };
}
return { maskedValue: maskedValue, mask: mask, transformOffset: transformOffset };
};
var unmask = function (displayValue, maskGenerator) {
var _a;
if (!maskGenerator) {
return displayValue;
}
var rules = maskGenerator.rules;
var mask = maskGenerator.generateMask(displayValue);
var maskLen = (_a = mask === null || mask === void 0 ? void 0 : mask.length) !== null && _a !== void 0 ? _a : 0;
return displayValue
.split('')
.filter(function (_, idx) { return idx < maskLen && rules.has(mask[idx]); })
.join('');
};
var processValue = function (displayValue, maskGenerator) {
var keepMask = maskGenerator.keepMask;
var value = keepMask ? displayValue : unmask(displayValue, maskGenerator);
return value;
};
// Algorithm to get the cursor position after the mask is applied
var getExpectedCursorPos = function (args) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
var displayValue = args.displayValue, oldDisplayValue = args.oldDisplayValue, valueBeforeMask = args.valueBeforeMask, newMask = args.newMask, oldMask = args.oldMask, cursorPosition = args.cursorPosition, lastWentBack = args.lastWentBack;
var oldMaskStr = (_a = oldMask === null || oldMask === void 0 ? void 0 : oldMask.generateMask(oldDisplayValue)) !== null && _a !== void 0 ? _a : '';
var newMaskStr = (_b = newMask === null || newMask === void 0 ? void 0 : newMask.generateMask(displayValue)) !== null && _b !== void 0 ? _b : '';
var oldDynamicAmount = oldMaskStr
.split('')
.filter(function (char, idx) {
return (oldDisplayValue === null || oldDisplayValue === void 0 ? void 0 : oldDisplayValue[idx]) && (oldMask ? oldMask.rules.has(char) : true);
}).length;
var newDynamicAmount = newMaskStr
.split('')
.filter(function (char, idx) {
return (displayValue === null || displayValue === void 0 ? void 0 : displayValue[idx]) && (newMask ? newMask.rules.has(char) : true);
}).length;
if (oldDynamicAmount === newDynamicAmount &&
displayValue === oldDisplayValue) {
var afterMaskLen = (_c = displayValue === null || displayValue === void 0 ? void 0 : displayValue.length) !== null && _c !== void 0 ? _c : 0;
var beforeMaskLen = (_d = valueBeforeMask === null || valueBeforeMask === void 0 ? void 0 : valueBeforeMask.length) !== null && _d !== void 0 ? _d : 0;
if (afterMaskLen > beforeMaskLen) {
// When the new value before the mask was applied had less chars,
// consider to be a case in which a char was deleted.
// Because it's not known if it was deleted before or after the cursor
// (the cursor position before the change is unknown), the flag lastWentBack
// is used to consider if the cursor was before or after the deleted char.
var position = cursorPosition + afterMaskLen - beforeMaskLen;
var goOn = true;
var wentBack = !lastWentBack;
var offset = 0;
// advance the adjacent static chars until there's no more remaining
// if wentBack is true, it will go back until it finds a dynamic char
// if wentBack is false, it will go forward until it finds a dynamic char
while (goOn) {
var idx = position + offset + (wentBack ? -1 : 0);
var maskChar = idx >= 0 && idx < ((_e = newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr.length) !== null && _e !== void 0 ? _e : 0)
? newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr.charAt(idx)
: undefined;
if (!maskChar) {
goOn = false;
}
else {
var regex = (_f = newMask === null || newMask === void 0 ? void 0 : newMask.rules) === null || _f === void 0 ? void 0 : _f.get(maskChar);
if (regex) {
goOn = false;
}
else {
offset = wentBack ? offset - 1 : offset + 1;
}
}
}
var newPosition = Math.max(Math.min(position + offset, (_g = displayValue === null || displayValue === void 0 ? void 0 : displayValue.length) !== null && _g !== void 0 ? _g : 0), 0);
return {
position: newPosition,
wentBack: wentBack,
};
}
else if (afterMaskLen < beforeMaskLen) {
// If 1 or more chars were added, but the end value ended up
// being the same after the mask was applied, the cursor should
// return a number of positions equal to the number of ignored
// chars (those that should have been placed in dynamic positions,
// but the rule wasn't satisfied).
var initial = { ignored: 0, idx: 0 };
var ignored = ((_m = (_l = (_k = valueBeforeMask === null || valueBeforeMask === void 0 ? void 0 : valueBeforeMask.substring(0, Math.min((_h = valueBeforeMask === null || valueBeforeMask === void 0 ? void 0 : valueBeforeMask.length) !== null && _h !== void 0 ? _h : 0, (_j = newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr.length) !== null && _j !== void 0 ? _j : 0, cursorPosition))) === null || _k === void 0 ? void 0 : _k.split('')) === null || _l === void 0 ? void 0 : _l.reduce(function (acc, char) {
var _a, _b;
var ignored = acc.ignored;
var idx = acc.idx;
var len = (_a = newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr.length) !== null && _a !== void 0 ? _a : 0;
while (idx < len) {
if (idx >= cursorPosition) {
return acc;
}
var maskChar = newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr.charAt(idx);
var regex = (_b = newMask === null || newMask === void 0 ? void 0 : newMask.rules) === null || _b === void 0 ? void 0 : _b.get(maskChar);
if (regex) {
if (regex.test(char)) {
return { ignored: ignored, idx: idx + 1 };
}
else {
return { ignored: ignored + 1, idx: idx };
}
}
else {
if (maskChar === char) {
return { ignored: ignored, idx: idx + 1 };
}
idx++;
}
}
return {
ignored: ignored,
idx: idx + 1,
};
}, initial)) !== null && _m !== void 0 ? _m : initial).ignored;
var newPosition = Math.max(Math.min(cursorPosition - ignored, (_o = displayValue === null || displayValue === void 0 ? void 0 : displayValue.length) !== null && _o !== void 0 ? _o : 0), 0);
return {
position: newPosition,
wentBack: lastWentBack,
};
}
else {
return {
position: cursorPosition,
wentBack: lastWentBack,
};
}
}
else if (oldDynamicAmount <= newDynamicAmount) {
var dynamicOffset = newDynamicAmount - oldDynamicAmount;
// Guess the last position of the cursor
var cursorBeforeDynamic_1 = Math.max(Math.min(cursorPosition - dynamicOffset, (_p = oldDisplayValue === null || oldDisplayValue === void 0 ? void 0 : oldDisplayValue.length) !== null && _p !== void 0 ? _p : 0), 0);
var oldStaticAmountBefore = oldMaskStr === null || oldMaskStr === void 0 ? void 0 : oldMaskStr.substring(0, Math.max(cursorBeforeDynamic_1, 0)).split('').filter(function (char, idx) {
return (oldDisplayValue === null || oldDisplayValue === void 0 ? void 0 : oldDisplayValue[idx]) &&
(oldMask ? !oldMask.rules.has(char) : false);
}).length;
var newStaticAmountBefore = newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr.substring(0, Math.max(cursorBeforeDynamic_1, 0)).split('').filter(function (char, idx) {
return (displayValue === null || displayValue === void 0 ? void 0 : displayValue[idx]) && (newMask ? !newMask.rules.has(char) : false);
}).length;
// the difference of static chars between the new and old mask, before the cursor
// and not considering the cursor changes due to dynamic chars
var initialStaticOffset_1 = newStaticAmountBefore - oldStaticAmountBefore;
var exceededOffset_1 = Math.max(((_q = valueBeforeMask === null || valueBeforeMask === void 0 ? void 0 : valueBeforeMask.length) !== null && _q !== void 0 ? _q : 0) - ((_r = displayValue === null || displayValue === void 0 ? void 0 : displayValue.length) !== null && _r !== void 0 ? _r : 0), 0);
// Calculates the number of ignored chars (those that have not satisfied the mask)
// and the number of exceeded chars (those that have not been added to the mask,
// because the end of the mask was reached)
var initial = { ignored: 0, exceeded: 0, staticAdded: 0, idx: 0 };
var _2 = (_t = (_s = valueBeforeMask === null || valueBeforeMask === void 0 ? void 0 : valueBeforeMask.split('')) === null || _s === void 0 ? void 0 : _s.reduce(function (_a, char) {
var _b, _c;
var ignored = _a.ignored, exceeded = _a.exceeded, staticAdded = _a.staticAdded, idx = _a.idx;
var len = (_b = newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr.length) !== null && _b !== void 0 ? _b : 0;
while (idx < len) {
var maskChar = newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr.charAt(idx);
var regex = (_c = newMask === null || newMask === void 0 ? void 0 : newMask.rules) === null || _c === void 0 ? void 0 : _c.get(maskChar);
if (regex) {
if (regex.test(char)) {
return { ignored: ignored, exceeded: exceeded, staticAdded: staticAdded, idx: idx + 1 };
}
else {
var newIgnored = idx >
cursorBeforeDynamic_1 + initialStaticOffset_1 - exceededOffset_1 &&
idx < cursorPosition
? ignored + 1
: ignored;
return {
ignored: newIgnored,
exceeded: exceeded,
staticAdded: !newIgnored && idx < cursorPosition
? staticAdded - 1
: staticAdded,
idx: idx,
};
}
}
else {
if (maskChar === char) {
var newIgnored = idx >
cursorBeforeDynamic_1 + initialStaticOffset_1 - exceededOffset_1 &&
idx < cursorPosition
? ignored + 1
: ignored;
return {
ignored: newIgnored,
exceeded: exceeded,
staticAdded: staticAdded,
idx: idx + 1,
};
}
else {
if (idx < cursorPosition) {
staticAdded = staticAdded + 1;
}
}
idx++;
}
}
// after the entire masked was surpassed, increase the exceeded chars amount
return { ignored: ignored, exceeded: exceeded + 1, staticAdded: staticAdded, idx: idx + 1 };
}, initial)) !== null && _t !== void 0 ? _t : initial, _3 = _2.ignored, charsIgnored = _3 === void 0 ? 0 : _3, _4 = _2.exceeded, charsExceeded = _4 === void 0 ? 0 : _4, _5 = _2.staticAdded, staticAdded = _5 === void 0 ? 0 : _5;
var currentPos = cursorBeforeDynamic_1;
var staticOffset = initialStaticOffset_1;
// calculates the number of static chars that were added to the value,
// starting from the expected last position of the cursor
while (currentPos - staticOffset - charsExceeded <
cursorBeforeDynamic_1 + dynamicOffset) {
var idx = currentPos - charsExceeded;
if (idx < 0) {
currentPos++;
continue;
}
var char = newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr[idx];
if (!char) {
break;
}
var dynamic = newMask ? newMask.rules.has(char) : true;
if (!dynamic) {
staticOffset++;
}
currentPos++;
}
staticOffset = Math.max(staticAdded, staticOffset, 0);
return {
position: Math.min(cursorPosition + staticOffset - charsIgnored, (_u = newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr.length) !== null && _u !== void 0 ? _u : 0),
wentBack: lastWentBack,
};
}
else {
// If a new static char is added to the display value, not present before the mask was applied,
// the cursor position should be moved to the right.
// If a char is removed from the display value, because it was supposed to be dynamic,
// but have not satisfied the condition, the cursor position should be moved to the left.
var offset = (_y = (_x = (_w = valueBeforeMask === null || valueBeforeMask === void 0 ? void 0 : valueBeforeMask.substring(0, Math.min(cursorPosition, (_v = valueBeforeMask === null || valueBeforeMask === void 0 ? void 0 : valueBeforeMask.length) !== null && _v !== void 0 ? _v : 0))) === null || _w === void 0 ? void 0 : _w.split('')) === null || _x === void 0 ? void 0 : _x.reduce(function (acc, char, idx) {
var _a;
var maskChar = newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr[idx];
var regex = (_a = newMask === null || newMask === void 0 ? void 0 : newMask.rules) === null || _a === void 0 ? void 0 : _a.get(maskChar);
if (regex) {
if (regex.test(char)) {
return acc;
}
else {
return acc - 1;
}
}
else {
if (maskChar === char) {
return acc;
}
else {
return acc + 1;
}
}
}, 0)) !== null && _y !== void 0 ? _y : 0;
// Consider the dynamic chars added when the mask was applied
// (due to a call to transform). In this case, the cursor position should
// be moved to the right according to the number of dynamic chars added.
var initial = { dynamic: 0, idx: 0 };
var dynamic = ((_0 = (_z = valueBeforeMask === null || valueBeforeMask === void 0 ? void 0 : valueBeforeMask.split('')) === null || _z === void 0 ? void 0 : _z.reduce(function (acc, char) {
var _a, _b;
var dynamic = acc.dynamic;
var idx = acc.idx;
var len = (_a = newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr.length) !== null && _a !== void 0 ? _a : 0;
while (idx < len) {
var maskChar = newMaskStr === null || newMaskStr === void 0 ? void 0 : newMaskStr[idx];
var regex = (_b = newMask === null || newMask === void 0 ? void 0 : newMask.rules) === null || _b === void 0 ? void 0 : _b.get(maskChar);
if (regex) {
if (regex.test(char)) {
return { dynamic: dynamic + 1, idx: idx + 1 };
}
else {
return acc;
}
}
else {
if (maskChar === char) {
return { dynamic: dynamic, idx: idx + 1 };
}
idx++;
}
}
return acc;
}, initial)) !== null && _0 !== void 0 ? _0 : initial).dynamic;
var dynamicOffset = Math.max(newDynamicAmount - dynamic, 0);
var position = Math.max(Math.min(cursorPosition + offset + dynamicOffset, (_1 = displayValue === null || displayValue === void 0 ? void 0 : displayValue.length) !== null && _1 !== void 0 ? _1 : 0), 0);
return { position: position, wentBack: lastWentBack };
}
};
exports.getExpectedCursorPos = getExpectedCursorPos;
var MaskFunctions = {
getExpectedCursorPos: exports.getExpectedCursorPos,
mask: mask,
processValue: processValue,
unmask: unmask,
};
exports.default = MaskFunctions;
//# sourceMappingURL=mask.js.map