react-hook-mask
Version:
React masked input component and hooks
201 lines • 11 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.useMask = void 0;
var react_1 = __importDefault(require("react"));
var mask_1 = __importDefault(require("../utils/mask"));
var getExpectedCursorPos = mask_1.default.getExpectedCursorPos, mask = mask_1.default.mask, processValue = mask_1.default.processValue;
var useMask = function (_a) {
var _b;
var outerValue = _a.outerValue, maskGenerator = _a.maskGenerator, onChange = _a.onChange, getCursorPosition = _a.getCursorPosition, setCursorPosition = _a.setCursorPosition, keepMask = _a.keepMask;
var lastOuterValueRef = react_1.default.useRef(outerValue);
var lastValueRef = react_1.default.useRef(outerValue);
var lastDisplayValueRef = react_1.default.useRef(outerValue);
var lastCursorPositionRef = react_1.default.useRef((_b = outerValue === null || outerValue === void 0 ? void 0 : outerValue.length) !== null && _b !== void 0 ? _b : 0);
var cursorBeforeMaskValueRef = react_1.default.useRef(outerValue);
var lastWentBackRef = react_1.default.useRef(false);
var lastMaskRef = react_1.default.useRef(maskGenerator);
var lastCursorMaskRef = react_1.default.useRef(maskGenerator);
var _c = react_1.default.useState(outerValue), value = _c[0], setValue = _c[1];
var _d = react_1.default.useState(value), displayValue = _d[0], setDisplayValue = _d[1];
var _e = react_1.default.useState(displayValue), lastCursorValue = _e[0], setLastCursorValue = _e[1];
var _f = react_1.default.useState(), lastMaskValue = _f[0], setLastMaskValue = _f[1];
var _g = react_1.default.useState(false), needUpdateCursor = _g[0], setNeedUpdateCursor = _g[1];
var updateDisplayValue = react_1.default.useCallback(function (value, userInput) {
if (userInput && getCursorPosition) {
// Remove static chars after the cursor position to not be duplicated
// after the mask is applied (when the mask starts with static chars,
// but the user types before those chars, the mask generator will
// add the static chars automatically)
// See: https://github.com/lucasbasquerotto/react-masked-input/issues/3
if (value && maskGenerator) {
var cursorPosition_1 = getCursorPosition();
var afterStr = cursorPosition_1 <= (value === null || value === void 0 ? void 0 : value.length)
? value === null || value === void 0 ? void 0 : value.substring(cursorPosition_1)
: undefined;
if (afterStr) {
var currentMask = maskGenerator.generateMask(value);
var initialStaticChars = '';
var idx = 0;
var currentChar = currentMask === null || currentMask === void 0 ? void 0 : currentMask.charAt(idx);
while (currentChar && !maskGenerator.rules.has(currentChar)) {
initialStaticChars += currentChar;
idx++;
currentChar = currentMask === null || currentMask === void 0 ? void 0 : currentMask.charAt(idx);
}
if (initialStaticChars) {
var startChars = '';
var afterChars = initialStaticChars;
while (afterChars &&
value.startsWith(startChars) &&
!afterStr.startsWith(afterChars)) {
startChars += afterChars === null || afterChars === void 0 ? void 0 : afterChars.charAt(0);
afterChars = afterChars.substring(1);
}
if (afterChars &&
value.startsWith(startChars) &&
afterStr.startsWith(afterChars)) {
value =
value.substring(0, cursorPosition_1) +
value.substring(cursorPosition_1 + afterChars.length);
}
}
}
}
// Updates the cursor position when the user types a char
var cursorPosition = getCursorPosition();
lastCursorPositionRef.current = cursorPosition;
cursorBeforeMaskValueRef.current = value;
setNeedUpdateCursor(true);
}
if ((value !== null && value !== void 0 ? value : '').trim() === '') {
setDisplayValue('');
setValue('');
lastMaskRef.current = undefined;
lastOuterValueRef.current = '';
return { displayValue: '' };
}
else if (maskGenerator) {
var _a = mask(value, maskGenerator), maskedValue = _a.maskedValue, currentMask = _a.mask, transformOffset = _a.transformOffset;
var processedValue = processValue(maskedValue !== null && maskedValue !== void 0 ? maskedValue : '', maskGenerator);
setDisplayValue(maskedValue !== null && maskedValue !== void 0 ? maskedValue : undefined);
setValue(processedValue !== null && processedValue !== void 0 ? processedValue : undefined);
lastMaskRef.current = maskGenerator;
lastOuterValueRef.current = processedValue !== null && processedValue !== void 0 ? processedValue : undefined;
if (transformOffset && userInput && getCursorPosition) {
var cursorPosition = getCursorPosition();
var newCursorPosition = cursorPosition + transformOffset;
lastCursorPositionRef.current = newCursorPosition;
cursorBeforeMaskValueRef.current = value;
setNeedUpdateCursor(true);
}
return { displayValue: maskedValue, mask: currentMask };
}
else {
setDisplayValue(value);
setValue(value);
lastMaskRef.current = undefined;
lastOuterValueRef.current = value !== null && value !== void 0 ? value : undefined;
return { displayValue: value };
}
}, [maskGenerator, getCursorPosition]);
var updateCursor = react_1.default.useCallback(function (_a) {
var _b;
var displayValue = _a.displayValue, oldDisplayValue = _a.oldDisplayValue, newMask = _a.newMask, oldMask = _a.oldMask, force = _a.force;
if (setCursorPosition && getCursorPosition) {
var _c = getExpectedCursorPos({
displayValue: displayValue,
oldDisplayValue: oldDisplayValue,
valueBeforeMask: (_b = cursorBeforeMaskValueRef.current) !== null && _b !== void 0 ? _b : '',
newMask: newMask,
oldMask: oldMask,
cursorPosition: lastCursorPositionRef.current,
lastWentBack: lastWentBackRef.current,
}), newExpectedCursorPos = _c.position, _d = _c.wentBack, wentBack = _d === void 0 ? false : _d;
if (force || lastCursorPositionRef.current !== newExpectedCursorPos) {
lastCursorPositionRef.current = newExpectedCursorPos;
setCursorPosition(newExpectedCursorPos);
}
lastWentBackRef.current = wentBack;
}
}, [setCursorPosition, getCursorPosition]);
react_1.default.useEffect(function () {
var maskValue = ((maskGenerator === null || maskGenerator === void 0 ? void 0 : maskGenerator.generateMask) &&
(maskGenerator === null || maskGenerator === void 0 ? void 0 : maskGenerator.generateMask(value !== null && value !== void 0 ? value : ''))) ||
undefined;
if (maskValue !== lastMaskValue ||
outerValue !== lastOuterValueRef.current) {
setLastMaskValue(maskValue);
lastOuterValueRef.current = outerValue;
if (maskValue !== lastMaskValue || outerValue !== value) {
updateDisplayValue(outerValue !== null && outerValue !== void 0 ? outerValue : '');
}
}
}, [
lastMaskValue,
setLastMaskValue,
maskGenerator,
outerValue,
value,
updateDisplayValue,
]);
react_1.default.useEffect(function () {
if (value !== lastValueRef.current) {
lastValueRef.current = value;
updateDisplayValue(value !== null && value !== void 0 ? value : '');
if (!keepMask && onChange) {
onChange(value !== null && value !== void 0 ? value : '');
}
}
}, [value, maskGenerator, updateDisplayValue, keepMask, onChange]);
react_1.default.useEffect(function () {
if (displayValue !== lastDisplayValueRef.current) {
var newDisplayValue = updateDisplayValue(displayValue !== null && displayValue !== void 0 ? displayValue : '').displayValue;
if ((newDisplayValue !== null && newDisplayValue !== void 0 ? newDisplayValue : '') === (displayValue !== null && displayValue !== void 0 ? displayValue : '')) {
lastDisplayValueRef.current = newDisplayValue !== null && newDisplayValue !== void 0 ? newDisplayValue : undefined;
if (keepMask && onChange) {
onChange(newDisplayValue !== null && newDisplayValue !== void 0 ? newDisplayValue : '');
}
}
}
}, [displayValue, updateDisplayValue, keepMask, onChange]);
react_1.default.useEffect(function () {
var _a;
var newPos = getCursorPosition
? getCursorPosition()
: lastCursorPositionRef.current;
var force = newPos !== lastCursorPositionRef.current;
if (displayValue === lastDisplayValueRef.current &&
(lastCursorValue !== lastDisplayValueRef.current ||
force ||
needUpdateCursor)) {
setNeedUpdateCursor(false);
setLastCursorValue(lastDisplayValueRef.current);
lastCursorMaskRef.current = lastMaskRef.current;
updateCursor({
displayValue: (_a = lastDisplayValueRef.current) !== null && _a !== void 0 ? _a : '',
oldDisplayValue: lastCursorValue !== null && lastCursorValue !== void 0 ? lastCursorValue : '',
newMask: lastMaskRef.current,
oldMask: lastCursorMaskRef.current,
force: force,
});
}
}, [
lastCursorValue,
displayValue,
needUpdateCursor,
getCursorPosition,
updateCursor,
]);
var result = react_1.default.useMemo(function () { return ({
displayValue: displayValue,
setDisplayValue: function (value) {
updateDisplayValue(value, true);
},
}); }, [displayValue, updateDisplayValue]);
return result;
};
exports.useMask = useMask;
//# sourceMappingURL=use-mask.js.map