ngx-mask
Version:
awesome ngx mask
942 lines (939 loc) • 124 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, EventEmitter, inject, Injectable, ElementRef, Renderer2, makeEnvironmentProviders, Directive, Input, Output, HostListener, Pipe } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
const NGX_MASK_CONFIG = new InjectionToken('ngx-mask config');
const NEW_CONFIG = new InjectionToken('new ngx-mask config');
const INITIAL_CONFIG = new InjectionToken('initial ngx-mask config');
const initialConfig = {
suffix: '',
prefix: '',
thousandSeparator: ' ',
decimalMarker: ['.', ','],
clearIfNotMatch: false,
showTemplate: false,
showMaskTyped: false,
placeHolderCharacter: '_',
dropSpecialCharacters: true,
hiddenInput: undefined,
shownMaskExpression: '',
separatorLimit: '',
allowNegativeNumbers: false,
validation: true,
// eslint-disable-next-line @typescript-eslint/quotes
specialCharacters: ['-', '/', '(', ')', '.', ':', ' ', '+', ',', '@', '[', ']', '"', "'"],
leadZeroDateTime: false,
apm: false,
leadZero: false,
keepCharacterPositions: false,
triggerOnMaskChange: false,
inputTransformFn: (value) => value,
outputTransformFn: (value) => value,
maskFilled: new EventEmitter(),
patterns: {
'0': {
pattern: new RegExp('\\d'),
},
'9': {
pattern: new RegExp('\\d'),
optional: true,
},
X: {
pattern: new RegExp('\\d'),
symbol: '*',
},
A: {
pattern: new RegExp('[a-zA-Z0-9]'),
},
S: {
pattern: new RegExp('[a-zA-Z]'),
},
U: {
pattern: new RegExp('[A-Z]'),
},
L: {
pattern: new RegExp('[a-z]'),
},
d: {
pattern: new RegExp('\\d'),
},
m: {
pattern: new RegExp('\\d'),
},
M: {
pattern: new RegExp('\\d'),
},
H: {
pattern: new RegExp('\\d'),
},
h: {
pattern: new RegExp('\\d'),
},
s: {
pattern: new RegExp('\\d'),
},
},
};
const timeMasks = [
"Hh:m0:s0" /* MaskExpression.HOURS_MINUTES_SECONDS */,
"Hh:m0" /* MaskExpression.HOURS_MINUTES */,
"m0:s0" /* MaskExpression.MINUTES_SECONDS */,
];
const withoutValidation = [
"percent" /* MaskExpression.PERCENT */,
"Hh" /* MaskExpression.HOURS_HOUR */,
"s0" /* MaskExpression.SECONDS */,
"m0" /* MaskExpression.MINUTES */,
"separator" /* MaskExpression.SEPARATOR */,
"d0/M0/0000" /* MaskExpression.DAYS_MONTHS_YEARS */,
"d0/M0" /* MaskExpression.DAYS_MONTHS */,
"d0" /* MaskExpression.DAYS */,
"M0" /* MaskExpression.MONTHS */,
];
class NgxMaskApplierService {
constructor() {
this._config = inject(NGX_MASK_CONFIG);
this.dropSpecialCharacters = this._config.dropSpecialCharacters;
this.hiddenInput = this._config.hiddenInput;
this.clearIfNotMatch = this._config.clearIfNotMatch;
this.specialCharacters = this._config.specialCharacters;
this.patterns = this._config.patterns;
this.prefix = this._config.prefix;
this.suffix = this._config.suffix;
this.thousandSeparator = this._config.thousandSeparator;
this.decimalMarker = this._config.decimalMarker;
this.showMaskTyped = this._config.showMaskTyped;
this.placeHolderCharacter = this._config.placeHolderCharacter;
this.validation = this._config.validation;
this.separatorLimit = this._config.separatorLimit;
this.allowNegativeNumbers = this._config.allowNegativeNumbers;
this.leadZeroDateTime = this._config.leadZeroDateTime;
this.leadZero = this._config.leadZero;
this.apm = this._config.apm;
this.inputTransformFn = this._config.inputTransformFn;
this.outputTransformFn = this._config.outputTransformFn;
this.keepCharacterPositions = this._config.keepCharacterPositions;
this._shift = new Set();
this.plusOnePosition = false;
this.maskExpression = '';
this.actualValue = '';
this.showKeepCharacterExp = '';
this.shownMaskExpression = '';
this.deletedSpecialCharacter = false;
this._formatWithSeparators = (str, thousandSeparatorChar, decimalChars, precision) => {
let x = [];
let decimalChar = '';
if (Array.isArray(decimalChars)) {
const regExp = new RegExp(decimalChars.map((v) => ('[\\^$.|?*+()'.indexOf(v) >= 0 ? `\\${v}` : v)).join('|'));
x = str.split(regExp);
decimalChar = str.match(regExp)?.[0] ?? "" /* MaskExpression.EMPTY_STRING */;
}
else {
x = str.split(decimalChars);
decimalChar = decimalChars;
}
const decimals = x.length > 1 ? `${decimalChar}${x[1]}` : "" /* MaskExpression.EMPTY_STRING */;
let res = x[0] ?? "" /* MaskExpression.EMPTY_STRING */;
const separatorLimit = this.separatorLimit.replace(/\s/g, "" /* MaskExpression.EMPTY_STRING */);
if (separatorLimit && +separatorLimit) {
if (res[0] === "-" /* MaskExpression.MINUS */) {
res = `-${res.slice(1, res.length).slice(0, separatorLimit.length)}`;
}
else {
res = res.slice(0, separatorLimit.length);
}
}
const rgx = /(\d+)(\d{3})/;
while (thousandSeparatorChar && rgx.test(res)) {
res = res.replace(rgx, '$1' + thousandSeparatorChar + '$2');
}
if (precision === undefined) {
return res + decimals;
}
else if (precision === 0) {
return res;
}
return res + decimals.substring(0, precision + 1);
};
this.percentage = (str) => {
const sanitizedStr = str.replace(',', '.');
const value = Number(this.allowNegativeNumbers && str.includes("-" /* MaskExpression.MINUS */)
? sanitizedStr.slice(1, str.length)
: sanitizedStr);
return !isNaN(value) && value >= 0 && value <= 100;
};
this.getPrecision = (maskExpression) => {
const x = maskExpression.split("." /* MaskExpression.DOT */);
if (x.length > 1) {
return Number(x[x.length - 1]);
}
return Infinity;
};
this.checkAndRemoveSuffix = (inputValue) => {
for (let i = this.suffix?.length - 1; i >= 0; i--) {
const substr = this.suffix.substring(i, this.suffix?.length);
if (inputValue.includes(substr) &&
i !== this.suffix?.length - 1 &&
(i - 1 < 0 ||
!inputValue.includes(this.suffix.substring(i - 1, this.suffix?.length)))) {
return inputValue.replace(substr, "" /* MaskExpression.EMPTY_STRING */);
}
}
return inputValue;
};
this.checkInputPrecision = (inputValue, precision, decimalMarker) => {
if (precision < Infinity) {
// TODO need think about decimalMarker
if (Array.isArray(decimalMarker)) {
const marker = decimalMarker.find((dm) => dm !== this.thousandSeparator);
// eslint-disable-next-line no-param-reassign
decimalMarker = marker ? marker : decimalMarker[0];
}
const precisionRegEx = new RegExp(this._charToRegExpExpression(decimalMarker) + `\\d{${precision}}.*$`);
const precisionMatch = inputValue.match(precisionRegEx);
const precisionMatchLength = (precisionMatch && precisionMatch[0]?.length) ?? 0;
if (precisionMatchLength - 1 > precision) {
const diff = precisionMatchLength - 1 - precision;
// eslint-disable-next-line no-param-reassign
inputValue = inputValue.substring(0, inputValue.length - diff);
}
if (precision === 0 &&
this._compareOrIncludes(inputValue[inputValue.length - 1], decimalMarker, this.thousandSeparator)) {
// eslint-disable-next-line no-param-reassign
inputValue = inputValue.substring(0, inputValue.length - 1);
}
}
return inputValue;
};
}
applyMaskWithPattern(inputValue, maskAndPattern) {
const [mask, customPattern] = maskAndPattern;
this.customPattern = customPattern;
return this.applyMask(inputValue, mask);
}
applyMask(inputValue, maskExpression, position = 0, justPasted = false, backspaced = false,
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-explicit-any
cb = () => { }) {
if (!maskExpression || typeof inputValue !== 'string') {
return "" /* MaskExpression.EMPTY_STRING */;
}
let cursor = 0;
let result = '';
let multi = false;
let backspaceShift = false;
let shift = 1;
let stepBack = false;
if (inputValue.slice(0, this.prefix.length) === this.prefix) {
// eslint-disable-next-line no-param-reassign
inputValue = inputValue.slice(this.prefix.length, inputValue.length);
}
if (!!this.suffix && inputValue?.length > 0) {
// eslint-disable-next-line no-param-reassign
inputValue = this.checkAndRemoveSuffix(inputValue);
}
if (inputValue === '(' && this.prefix) {
// eslint-disable-next-line no-param-reassign
inputValue = '';
}
const inputArray = inputValue.toString().split("" /* MaskExpression.EMPTY_STRING */);
if (this.allowNegativeNumbers &&
inputValue.slice(cursor, cursor + 1) === "-" /* MaskExpression.MINUS */) {
// eslint-disable-next-line no-param-reassign
result += inputValue.slice(cursor, cursor + 1);
}
if (maskExpression === "IP" /* MaskExpression.IP */) {
const valuesIP = inputValue.split("." /* MaskExpression.DOT */);
this.ipError = this._validIP(valuesIP);
// eslint-disable-next-line no-param-reassign
maskExpression = '099.099.099.099';
}
const arr = [];
for (let i = 0; i < inputValue.length; i++) {
if (inputValue[i]?.match('\\d')) {
arr.push(inputValue[i] ?? "" /* MaskExpression.EMPTY_STRING */);
}
}
if (maskExpression === "CPF_CNPJ" /* MaskExpression.CPF_CNPJ */) {
this.cpfCnpjError = arr.length !== 11 && arr.length !== 14;
if (arr.length > 11) {
// eslint-disable-next-line no-param-reassign
maskExpression = '00.000.000/0000-00';
}
else {
// eslint-disable-next-line no-param-reassign
maskExpression = '000.000.000-00';
}
}
if (maskExpression.startsWith("percent" /* MaskExpression.PERCENT */)) {
if (inputValue.match('[a-z]|[A-Z]') ||
// eslint-disable-next-line no-useless-escape
(inputValue.match(/[-!$%^&*()_+|~=`{}\[\]:";'<>?,\/.]/) && !backspaced)) {
// eslint-disable-next-line no-param-reassign
inputValue = this._stripToDecimal(inputValue);
const precision = this.getPrecision(maskExpression);
// eslint-disable-next-line no-param-reassign
inputValue = this.checkInputPrecision(inputValue, precision, this.decimalMarker);
}
const decimalMarker = typeof this.decimalMarker === 'string' ? this.decimalMarker : "." /* MaskExpression.DOT */;
if (inputValue.indexOf(decimalMarker) > 0 &&
!this.percentage(inputValue.substring(0, inputValue.indexOf(decimalMarker)))) {
let base = inputValue.substring(0, inputValue.indexOf(decimalMarker) - 1);
if (this.allowNegativeNumbers &&
inputValue.slice(cursor, cursor + 1) === "-" /* MaskExpression.MINUS */ &&
!backspaced) {
base = inputValue.substring(0, inputValue.indexOf(decimalMarker));
}
// eslint-disable-next-line no-param-reassign
inputValue = `${base}${inputValue.substring(inputValue.indexOf(decimalMarker), inputValue.length)}`;
}
let value = '';
this.allowNegativeNumbers &&
inputValue.slice(cursor, cursor + 1) === "-" /* MaskExpression.MINUS */
? (value = `${"-" /* MaskExpression.MINUS */}${inputValue.slice(cursor + 1, cursor + inputValue.length)}`)
: (value = inputValue);
if (this.percentage(value)) {
result = this._splitPercentZero(inputValue);
}
else {
result = this._splitPercentZero(inputValue.substring(0, inputValue.length - 1));
}
}
else if (maskExpression.startsWith("separator" /* MaskExpression.SEPARATOR */)) {
if (inputValue.match('[wа-яА-Я]') ||
inputValue.match('[ЁёА-я]') ||
inputValue.match('[a-z]|[A-Z]') ||
inputValue.match(/[-@#!$%\\^&*()_£¬'+|~=`{}\]:";<>.?/]/) ||
inputValue.match('[^A-Za-z0-9,]')) {
// eslint-disable-next-line no-param-reassign
inputValue = this._stripToDecimal(inputValue);
}
const precision = this.getPrecision(maskExpression);
const decimalMarker = Array.isArray(this.decimalMarker)
? "." /* MaskExpression.DOT */
: this.decimalMarker;
if (precision === 0) {
// eslint-disable-next-line no-param-reassign
inputValue = this.allowNegativeNumbers
? inputValue.length > 2 &&
inputValue[0] === "-" /* MaskExpression.MINUS */ &&
inputValue[1] === "0" /* MaskExpression.NUMBER_ZERO */ &&
inputValue[2] !== this.thousandSeparator &&
inputValue[2] !== "," /* MaskExpression.COMMA */ &&
inputValue[2] !== "." /* MaskExpression.DOT */
? '-' + inputValue.slice(2, inputValue.length)
: inputValue[0] === "0" /* MaskExpression.NUMBER_ZERO */ &&
inputValue.length > 1 &&
inputValue[1] !== this.thousandSeparator &&
inputValue[1] !== "," /* MaskExpression.COMMA */ &&
inputValue[1] !== "." /* MaskExpression.DOT */
? inputValue.slice(1, inputValue.length)
: inputValue
: inputValue.length > 1 &&
inputValue[0] === "0" /* MaskExpression.NUMBER_ZERO */ &&
inputValue[1] !== this.thousandSeparator &&
inputValue[1] !== "," /* MaskExpression.COMMA */ &&
inputValue[1] !== "." /* MaskExpression.DOT */
? inputValue.slice(1, inputValue.length)
: inputValue;
}
else {
// eslint-disable-next-line no-param-reassign
if (inputValue[0] === decimalMarker && inputValue.length > 1) {
// eslint-disable-next-line no-param-reassign
inputValue =
"0" /* MaskExpression.NUMBER_ZERO */ + inputValue.slice(0, inputValue.length + 1);
this.plusOnePosition = true;
}
if (inputValue[0] === "0" /* MaskExpression.NUMBER_ZERO */ &&
inputValue[1] !== decimalMarker &&
inputValue[1] !== this.thousandSeparator) {
// eslint-disable-next-line no-param-reassign
inputValue =
inputValue.length > 1
? inputValue.slice(0, 1) +
decimalMarker +
inputValue.slice(1, inputValue.length + 1)
: inputValue;
this.plusOnePosition = true;
}
if (this.allowNegativeNumbers &&
inputValue[0] === "-" /* MaskExpression.MINUS */ &&
(inputValue[1] === decimalMarker ||
inputValue[1] === "0" /* MaskExpression.NUMBER_ZERO */)) {
// eslint-disable-next-line no-param-reassign
inputValue =
inputValue[1] === decimalMarker && inputValue.length > 2
? inputValue.slice(0, 1) +
"0" /* MaskExpression.NUMBER_ZERO */ +
inputValue.slice(1, inputValue.length)
: inputValue[1] === "0" /* MaskExpression.NUMBER_ZERO */ &&
inputValue.length > 2 &&
inputValue[2] !== decimalMarker
? inputValue.slice(0, 2) +
decimalMarker +
inputValue.slice(2, inputValue.length)
: inputValue;
this.plusOnePosition = true;
}
}
if (backspaced) {
if (inputValue[0] === "0" /* MaskExpression.NUMBER_ZERO */ &&
inputValue[1] === this.decimalMarker &&
(inputValue[position] === "0" /* MaskExpression.NUMBER_ZERO */ ||
inputValue[position] === this.decimalMarker)) {
// eslint-disable-next-line no-param-reassign
inputValue = inputValue.slice(2, inputValue.length);
}
if (inputValue[0] === "-" /* MaskExpression.MINUS */ &&
inputValue[1] === "0" /* MaskExpression.NUMBER_ZERO */ &&
inputValue[2] === this.decimalMarker &&
(inputValue[position] === "0" /* MaskExpression.NUMBER_ZERO */ ||
inputValue[position] === this.decimalMarker)) {
// eslint-disable-next-line no-param-reassign
inputValue = "-" /* MaskExpression.MINUS */ + inputValue.slice(3, inputValue.length);
}
// eslint-disable-next-line no-param-reassign
inputValue = this._compareOrIncludes(inputValue[inputValue.length - 1], this.decimalMarker, this.thousandSeparator)
? inputValue.slice(0, inputValue.length - 1)
: inputValue;
}
// TODO: we had different rexexps here for the different cases... but tests dont seam to bother - check this
// separator: no COMMA, dot-sep: no SPACE, COMMA OK, comma-sep: no SPACE, COMMA OK
const thousandSeparatorCharEscaped = this._charToRegExpExpression(this.thousandSeparator);
let invalidChars = '@#!$%^&*()_+|~=`{}\\[\\]:\\s,\\.";<>?\\/'.replace(thousandSeparatorCharEscaped, '');
//.replace(decimalMarkerEscaped, '');
if (Array.isArray(this.decimalMarker)) {
for (const marker of this.decimalMarker) {
invalidChars = invalidChars.replace(this._charToRegExpExpression(marker), "" /* MaskExpression.EMPTY_STRING */);
}
}
else {
invalidChars = invalidChars.replace(this._charToRegExpExpression(this.decimalMarker), '');
}
const invalidCharRegexp = new RegExp('[' + invalidChars + ']');
if (inputValue.match(invalidCharRegexp)) {
// eslint-disable-next-line no-param-reassign
inputValue = inputValue.substring(0, inputValue.length - 1);
}
// eslint-disable-next-line no-param-reassign
inputValue = this.checkInputPrecision(inputValue, precision, this.decimalMarker);
const strForSep = inputValue.replace(new RegExp(thousandSeparatorCharEscaped, 'g'), '');
result = this._formatWithSeparators(strForSep, this.thousandSeparator, this.decimalMarker, precision);
const commaShift = result.indexOf("," /* MaskExpression.COMMA */) - inputValue.indexOf("," /* MaskExpression.COMMA */);
const shiftStep = result.length - inputValue.length;
if (result[position - 1] === this.thousandSeparator && this.prefix && backspaced) {
// eslint-disable-next-line no-param-reassign
position = position - 1;
}
else if (shiftStep > 0 && result[position] !== this.thousandSeparator) {
backspaceShift = true;
let _shift = 0;
do {
this._shift.add(position + _shift);
_shift++;
} while (_shift < shiftStep);
}
else if (result[position - 1] === this.decimalMarker ||
shiftStep === -4 ||
shiftStep === -3 ||
result[position] === "," /* MaskExpression.COMMA */) {
this._shift.clear();
this._shift.add(position - 1);
}
else if ((commaShift !== 0 &&
position > 0 &&
!(result.indexOf("," /* MaskExpression.COMMA */) >= position && position > 3)) ||
(!(result.indexOf("." /* MaskExpression.DOT */) >= position && position > 3) &&
shiftStep <= 0)) {
this._shift.clear();
backspaceShift = true;
shift = shiftStep;
// eslint-disable-next-line no-param-reassign
position += shiftStep;
this._shift.add(position);
}
else {
this._shift.clear();
}
}
else {
for (
// eslint-disable-next-line
let i = 0, inputSymbol = inputArray[0]; i < inputArray.length; i++, inputSymbol = inputArray[i] ?? "" /* MaskExpression.EMPTY_STRING */) {
if (cursor === maskExpression.length) {
break;
}
const symbolStarInPattern = "*" /* MaskExpression.SYMBOL_STAR */ in this.patterns;
if (this._checkSymbolMask(inputSymbol, maskExpression[cursor] ?? "" /* MaskExpression.EMPTY_STRING */) &&
maskExpression[cursor + 1] === "?" /* MaskExpression.SYMBOL_QUESTION */) {
result += inputSymbol;
cursor += 2;
}
else if (maskExpression[cursor + 1] === "*" /* MaskExpression.SYMBOL_STAR */ &&
multi &&
this._checkSymbolMask(inputSymbol, maskExpression[cursor + 2] ?? "" /* MaskExpression.EMPTY_STRING */)) {
result += inputSymbol;
cursor += 3;
multi = false;
}
else if (this._checkSymbolMask(inputSymbol, maskExpression[cursor] ?? "" /* MaskExpression.EMPTY_STRING */) &&
maskExpression[cursor + 1] === "*" /* MaskExpression.SYMBOL_STAR */ &&
!symbolStarInPattern) {
result += inputSymbol;
multi = true;
}
else if (maskExpression[cursor + 1] === "?" /* MaskExpression.SYMBOL_QUESTION */ &&
this._checkSymbolMask(inputSymbol, maskExpression[cursor + 2] ?? "" /* MaskExpression.EMPTY_STRING */)) {
result += inputSymbol;
cursor += 3;
}
else if (this._checkSymbolMask(inputSymbol, maskExpression[cursor] ?? "" /* MaskExpression.EMPTY_STRING */)) {
if (maskExpression[cursor] === "H" /* MaskExpression.HOURS */) {
if (this.apm ? Number(inputSymbol) > 9 : Number(inputSymbol) > 2) {
// eslint-disable-next-line no-param-reassign
position = !this.leadZeroDateTime ? position + 1 : position;
cursor += 1;
this._shiftStep(maskExpression, cursor, inputArray.length);
i--;
if (this.leadZeroDateTime) {
result += '0';
}
continue;
}
}
if (maskExpression[cursor] === "h" /* MaskExpression.HOUR */) {
if (this.apm
? (result.length === 1 && Number(result) > 1) ||
(result === '1' && Number(inputSymbol) > 2) ||
(inputValue.slice(cursor - 1, cursor).length === 1 &&
Number(inputValue.slice(cursor - 1, cursor)) > 2) ||
(inputValue.slice(cursor - 1, cursor) === '1' &&
Number(inputSymbol) > 2)
: (result === '2' && Number(inputSymbol) > 3) ||
((result.slice(cursor - 2, cursor) === '2' ||
result.slice(cursor - 3, cursor) === '2' ||
result.slice(cursor - 4, cursor) === '2' ||
result.slice(cursor - 1, cursor) === '2') &&
Number(inputSymbol) > 3 &&
cursor > 10)) {
// eslint-disable-next-line no-param-reassign
position = position + 1;
cursor += 1;
i--;
continue;
}
}
if (maskExpression[cursor] === "m" /* MaskExpression.MINUTE */ ||
maskExpression[cursor] === "s" /* MaskExpression.SECOND */) {
if (Number(inputSymbol) > 5) {
// eslint-disable-next-line no-param-reassign
position = !this.leadZeroDateTime ? position + 1 : position;
cursor += 1;
this._shiftStep(maskExpression, cursor, inputArray.length);
i--;
if (this.leadZeroDateTime) {
result += '0';
}
continue;
}
}
const daysCount = 31;
const inputValueCursor = inputValue[cursor];
const inputValueCursorPlusOne = inputValue[cursor + 1];
const inputValueCursorPlusTwo = inputValue[cursor + 2];
const inputValueCursorMinusOne = inputValue[cursor - 1];
const inputValueCursorMinusTwo = inputValue[cursor - 2];
const inputValueCursorMinusThree = inputValue[cursor - 3];
const inputValueSliceMinusThreeMinusOne = inputValue.slice(cursor - 3, cursor - 1);
const inputValueSliceMinusOnePlusOne = inputValue.slice(cursor - 1, cursor + 1);
const inputValueSliceCursorPlusTwo = inputValue.slice(cursor, cursor + 2);
const inputValueSliceMinusTwoCursor = inputValue.slice(cursor - 2, cursor);
if (maskExpression[cursor] === "d" /* MaskExpression.DAY */) {
const maskStartWithMonth = maskExpression.slice(0, 2) === "M0" /* MaskExpression.MONTHS */;
const startWithMonthInput = maskExpression.slice(0, 2) === "M0" /* MaskExpression.MONTHS */ &&
this.specialCharacters.includes(inputValueCursorMinusTwo);
if ((Number(inputSymbol) > 3 && this.leadZeroDateTime) ||
(!maskStartWithMonth &&
(Number(inputValueSliceCursorPlusTwo) > daysCount ||
Number(inputValueSliceMinusOnePlusOne) > daysCount ||
(this.specialCharacters.includes(inputValueCursorPlusOne) &&
!backspaced))) ||
(startWithMonthInput
? Number(inputValueSliceMinusOnePlusOne) > daysCount ||
(!this.specialCharacters.includes(inputValueCursor) &&
this.specialCharacters.includes(inputValueCursorPlusTwo)) ||
this.specialCharacters.includes(inputValueCursor)
: Number(inputValueSliceCursorPlusTwo) > daysCount ||
(this.specialCharacters.includes(inputValueCursorPlusOne) &&
!backspaced))) {
// eslint-disable-next-line no-param-reassign
position = !this.leadZeroDateTime ? position + 1 : position;
cursor += 1;
this._shiftStep(maskExpression, cursor, inputArray.length);
i--;
if (this.leadZeroDateTime) {
result += '0';
}
continue;
}
}
if (maskExpression[cursor] === "M" /* MaskExpression.MONTH */) {
const monthsCount = 12;
// mask without day
const withoutDays = cursor === 0 &&
(Number(inputSymbol) > 2 ||
Number(inputValueSliceCursorPlusTwo) > monthsCount ||
(this.specialCharacters.includes(inputValueCursorPlusOne) &&
!backspaced));
// day<10 && month<12 for input
const specialChart = maskExpression.slice(cursor + 2, cursor + 3);
const day1monthInput = inputValueSliceMinusThreeMinusOne.includes(specialChart) &&
maskExpression.includes('d0') &&
((this.specialCharacters.includes(inputValueCursorMinusTwo) &&
Number(inputValueSliceMinusOnePlusOne) > monthsCount &&
!this.specialCharacters.includes(inputValueCursor)) ||
this.specialCharacters.includes(inputValueCursor) ||
(this.specialCharacters.includes(inputValueCursorMinusThree) &&
Number(inputValueSliceMinusTwoCursor) > monthsCount &&
!this.specialCharacters.includes(inputValueCursorMinusOne)) ||
this.specialCharacters.includes(inputValueCursorMinusOne));
// month<12 && day<10 for input
const day2monthInput = Number(inputValueSliceMinusThreeMinusOne) <= daysCount &&
!this.specialCharacters.includes(inputValueSliceMinusThreeMinusOne) &&
this.specialCharacters.includes(inputValueCursorMinusOne) &&
(Number(inputValueSliceCursorPlusTwo) > monthsCount ||
(this.specialCharacters.includes(inputValueCursorPlusOne) &&
!backspaced));
// cursor === 5 && without days
const day2monthInputDot = (Number(inputValueSliceCursorPlusTwo) > monthsCount && cursor === 5) ||
(this.specialCharacters.includes(inputValueCursorPlusOne) &&
cursor === 5);
// // day<10 && month<12 for paste whole data
const day1monthPaste = Number(inputValueSliceMinusThreeMinusOne) > daysCount &&
!this.specialCharacters.includes(inputValueSliceMinusThreeMinusOne) &&
!this.specialCharacters.includes(inputValueSliceMinusTwoCursor) &&
Number(inputValueSliceMinusTwoCursor) > monthsCount &&
maskExpression.includes('d0');
// 10<day<31 && month<12 for paste whole data
const day2monthPaste = Number(inputValueSliceMinusThreeMinusOne) <= daysCount &&
!this.specialCharacters.includes(inputValueSliceMinusThreeMinusOne) &&
!this.specialCharacters.includes(inputValueCursorMinusOne) &&
Number(inputValueSliceMinusOnePlusOne) > monthsCount;
if ((Number(inputSymbol) > 1 && this.leadZeroDateTime) ||
withoutDays ||
day1monthInput ||
day2monthPaste ||
day1monthPaste ||
day2monthInput ||
(day2monthInputDot && !this.leadZeroDateTime)) {
// eslint-disable-next-line no-param-reassign
position = !this.leadZeroDateTime ? position + 1 : position;
cursor += 1;
this._shiftStep(maskExpression, cursor, inputArray.length);
i--;
if (this.leadZeroDateTime) {
result += '0';
}
continue;
}
}
result += inputSymbol;
cursor++;
}
else if ((inputSymbol === " " /* MaskExpression.WHITE_SPACE */ &&
maskExpression[cursor] === " " /* MaskExpression.WHITE_SPACE */) ||
(inputSymbol === "/" /* MaskExpression.SLASH */ &&
maskExpression[cursor] === "/" /* MaskExpression.SLASH */)) {
result += inputSymbol;
cursor++;
}
else if (this.specialCharacters.indexOf(maskExpression[cursor] ?? "" /* MaskExpression.EMPTY_STRING */) !== -1) {
result += maskExpression[cursor];
cursor++;
this._shiftStep(maskExpression, cursor, inputArray.length);
i--;
}
else if (maskExpression[cursor] === "9" /* MaskExpression.NUMBER_NINE */ &&
this.showMaskTyped) {
this._shiftStep(maskExpression, cursor, inputArray.length);
}
else if (this.patterns[maskExpression[cursor] ?? "" /* MaskExpression.EMPTY_STRING */] &&
this.patterns[maskExpression[cursor] ?? "" /* MaskExpression.EMPTY_STRING */]?.optional) {
if (!!inputArray[cursor] &&
maskExpression !== '099.099.099.099' &&
maskExpression !== '000.000.000-00' &&
maskExpression !== '00.000.000/0000-00' &&
!maskExpression.match(/^9+\.0+$/) &&
!this.patterns[maskExpression[cursor] ?? "" /* MaskExpression.EMPTY_STRING */]
?.optional) {
result += inputArray[cursor];
}
if (maskExpression.includes("9" /* MaskExpression.NUMBER_NINE */ + "*" /* MaskExpression.SYMBOL_STAR */) &&
maskExpression.includes("0" /* MaskExpression.NUMBER_ZERO */ + "*" /* MaskExpression.SYMBOL_STAR */)) {
cursor++;
}
cursor++;
i--;
}
else if (this.maskExpression[cursor + 1] === "*" /* MaskExpression.SYMBOL_STAR */ &&
this._findSpecialChar(this.maskExpression[cursor + 2] ?? "" /* MaskExpression.EMPTY_STRING */) &&
this._findSpecialChar(inputSymbol) === this.maskExpression[cursor + 2] &&
multi) {
cursor += 3;
result += inputSymbol;
}
else if (this.maskExpression[cursor + 1] === "?" /* MaskExpression.SYMBOL_QUESTION */ &&
this._findSpecialChar(this.maskExpression[cursor + 2] ?? "" /* MaskExpression.EMPTY_STRING */) &&
this._findSpecialChar(inputSymbol) === this.maskExpression[cursor + 2] &&
multi) {
cursor += 3;
result += inputSymbol;
}
else if (this.showMaskTyped &&
this.specialCharacters.indexOf(inputSymbol) < 0 &&
inputSymbol !== this.placeHolderCharacter &&
this.placeHolderCharacter.length === 1) {
stepBack = true;
}
}
}
if (result.length + 1 === maskExpression.length &&
this.specialCharacters.indexOf(maskExpression[maskExpression.length - 1] ?? "" /* MaskExpression.EMPTY_STRING */) !== -1) {
result += maskExpression[maskExpression.length - 1];
}
let newPosition = position + 1;
while (this._shift.has(newPosition)) {
shift++;
newPosition++;
}
let actualShift = justPasted && !maskExpression.startsWith("separator" /* MaskExpression.SEPARATOR */)
? cursor
: this._shift.has(position)
? shift
: 0;
if (stepBack) {
actualShift--;
}
cb(actualShift, backspaceShift);
if (shift < 0) {
this._shift.clear();
}
let onlySpecial = false;
if (backspaced) {
onlySpecial = inputArray.every((char) => this.specialCharacters.includes(char));
}
let res = `${this.prefix}${onlySpecial ? "" /* MaskExpression.EMPTY_STRING */ : result}${this.showMaskTyped ? '' : this.suffix}`;
if (result.length === 0) {
res = !this.dropSpecialCharacters ? `${this.prefix}${result}` : `${result}`;
}
if (result.includes("-" /* MaskExpression.MINUS */) && this.prefix && this.allowNegativeNumbers) {
if (backspaced && result === "-" /* MaskExpression.MINUS */) {
return '';
}
res = `${"-" /* MaskExpression.MINUS */}${this.prefix}${result
.split("-" /* MaskExpression.MINUS */)
.join("" /* MaskExpression.EMPTY_STRING */)}${this.suffix}`;
}
return res;
}
_findDropSpecialChar(inputSymbol) {
if (Array.isArray(this.dropSpecialCharacters)) {
return this.dropSpecialCharacters.find((val) => val === inputSymbol);
}
return this._findSpecialChar(inputSymbol);
}
_findSpecialChar(inputSymbol) {
return this.specialCharacters.find((val) => val === inputSymbol);
}
_checkSymbolMask(inputSymbol, maskSymbol) {
this.patterns = this.customPattern ? this.customPattern : this.patterns;
return ((this.patterns[maskSymbol]?.pattern &&
this.patterns[maskSymbol]?.pattern.test(inputSymbol)) ??
false);
}
_stripToDecimal(str) {
return str
.split("" /* MaskExpression.EMPTY_STRING */)
.filter((i, idx) => {
const isDecimalMarker = typeof this.decimalMarker === 'string'
? i === this.decimalMarker
: // TODO (inepipenko) use utility type
this.decimalMarker.includes(i);
return (i.match('^-?\\d') ||
i === this.thousandSeparator ||
isDecimalMarker ||
(i === "-" /* MaskExpression.MINUS */ && idx === 0 && this.allowNegativeNumbers));
})
.join("" /* MaskExpression.EMPTY_STRING */);
}
_charToRegExpExpression(char) {
// if (Array.isArray(char)) {
// return char.map((v) => ('[\\^$.|?*+()'.indexOf(v) >= 0 ? `\\${v}` : v)).join('|');
// }
if (char) {
const charsToEscape = '[\\^$.|?*+()';
return char === ' ' ? '\\s' : charsToEscape.indexOf(char) >= 0 ? `\\${char}` : char;
}
return char;
}
_shiftStep(maskExpression, cursor, inputLength) {
const shiftStep = /[*?]/g.test(maskExpression.slice(0, cursor))
? inputLength
: cursor;
this._shift.add(shiftStep + this.prefix.length || 0);
}
_compareOrIncludes(value, comparedValue, excludedValue) {
return Array.isArray(comparedValue)
? comparedValue.filter((v) => v !== excludedValue).includes(value)
: value === comparedValue;
}
_validIP(valuesIP) {
return !(valuesIP.length === 4 &&
!valuesIP.some((value, index) => {
if (valuesIP.length !== index + 1) {
return value === "" /* MaskExpression.EMPTY_STRING */ || Number(value) > 255;
}
return value === "" /* MaskExpression.EMPTY_STRING */ || Number(value.substring(0, 3)) > 255;
}));
}
_splitPercentZero(value) {
if (value === "-" /* MaskExpression.MINUS */ && this.allowNegativeNumbers) {
return value;
}
const decimalIndex = typeof this.decimalMarker === 'string'
? value.indexOf(this.decimalMarker)
: value.indexOf("." /* MaskExpression.DOT */);
const emptyOrMinus = this.allowNegativeNumbers && value.includes("-" /* MaskExpression.MINUS */) ? '-' : '';
if (decimalIndex === -1) {
const parsedValue = parseInt(emptyOrMinus ? value.slice(1, value.length) : value, 10);
return isNaN(parsedValue)
? "" /* MaskExpression.EMPTY_STRING */
: `${emptyOrMinus}${parsedValue}`;
}
else {
const integerPart = parseInt(value.replace('-', '').substring(0, decimalIndex), 10);
const decimalPart = value.substring(decimalIndex + 1);
const integerString = isNaN(integerPart) ? '' : integerPart.toString();
const decimal = typeof this.decimalMarker === 'string' ? this.decimalMarker : "." /* MaskExpression.DOT */;
return integerString === "" /* MaskExpression.EMPTY_STRING */
? "" /* MaskExpression.EMPTY_STRING */
: `${emptyOrMinus}${integerString}${decimal}${decimalPart}`;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.8", ngImport: i0, type: NgxMaskApplierService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.8", ngImport: i0, type: NgxMaskApplierService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.8", ngImport: i0, type: NgxMaskApplierService, decorators: [{
type: Injectable
}] });
class NgxMaskService extends NgxMaskApplierService {
constructor() {
super(...arguments);
this.isNumberValue = false;
this.maskIsShown = '';
this.selStart = null;
this.selEnd = null;
/**
* Whether we are currently in writeValue function, in this case when applying the mask we don't want to trigger onChange function,
* since writeValue should be a one way only process of writing the DOM value based on the Angular model value.
*/
this.writingValue = false;
this.maskChanged = false;
this._maskExpressionArray = [];
this.triggerOnMaskChange = false;
this._previousValue = '';
this._currentValue = '';
this._emitValue = false;
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-explicit-any
this.onChange = (_) => { };
this._elementRef = inject(ElementRef, { optional: true });
this.document = inject(DOCUMENT);
this._config = inject(NGX_MASK_CONFIG);
this._renderer = inject(Renderer2, { optional: true });
}
// eslint-disable-next-line complexity
applyMask(inputValue, maskExpression, position = 0, justPasted = false, backspaced = false,
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-explicit-any
cb = () => { }) {
if (!maskExpression) {
return inputValue !== this.actualValue ? this.actualValue : inputValue;
}
this.maskIsShown = this.showMaskTyped
? this.showMaskInInput()
: "" /* MaskExpression.EMPTY_STRING */;
if (this.maskExpression === "IP" /* MaskExpression.IP */ && this.showMaskTyped) {
this.maskIsShown = this.showMaskInInput(inputValue || "#" /* MaskExpression.HASH */);
}
if (this.maskExpression === "CPF_CNPJ" /* MaskExpression.CPF_CNPJ */ && this.showMaskTyped) {
this.maskIsShown = this.showMaskInInput(inputValue || "#" /* MaskExpression.HASH */);
}
if (!inputValue && this.showMaskTyped) {
this.formControlResult(this.prefix);
return `${this.prefix}${this.maskIsShown}${this.suffix}`;
}
const getSymbol = !!inputValue && typeof this.selStart === 'number'
? inputValue[this.selStart] ?? "" /* MaskExpression.EMPTY_STRING */
: "" /* MaskExpression.EMPTY_STRING */;
let newInputValue = '';
if (this.hiddenInput !== undefined && !this.writingValue) {
let actualResult = inputValue && inputValue.length === 1
? inputValue.split("" /* MaskExpression.EMPTY_STRING */)
: this.actualValue.split("" /* MaskExpression.EMPTY_STRING */);
// eslint-disable @typescript-eslint/no-unused-expressions
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
if (typeof this.selStart === 'object' && typeof this.selEnd === 'object') {
this.selStart = Number(this.selStart);
this.selEnd = Number(this.selEnd);
}
else {
inputValue !== "" /* MaskExpression.EMPTY_STRING */ && actualResult.length
? typeof this.selStart === 'number' && typeof this.selEnd === 'number'
? inputValue.length > actualResult.length
? actualResult.splice(this.selStart, 0, getSymbol)
: inputValue.length < actualResult.length
? actualResult.length - inputValue.length === 1
? backspaced
? actualResult.splice(this.selStart - 1, 1)
: actualResult.splice(inputValue.length - 1, 1)
: actualResult.splice(this.selStart, this.selEnd - this.selStart)
: null
: null
: (actualResult = []);
}
if (this.showMaskTyped) {
if (!this.hiddenInput) {
// eslint-disable-next-line no-param-reassign
inputValue = this.removeMask(inputValue);
}
}
// eslint-enable @typescript-eslint/no-unused-expressions
newInputValue =
this.actualValue.length && actualResult.length <= inputValue.length
? this.shiftTypedSymbols(actualResult.join("" /* MaskExpression.EMPTY_STRING */))
: inputValue;
}
if (justPasted && (this.hiddenInput || !this.hiddenInput)) {
newInputValue = inputValue;
}
if (backspaced &&
this.specialCharacters.indexOf(this.maskExpression[position] ?? "" /* MaskExpression.EMPTY_STRING */) !== -1 &&
this.showMaskTyped &&
!this.prefix) {
newInputValue = this._currentValue;
}
if (this.deletedSpecialCharacter && position) {
if (this.specialCharacters.includes(this.actualValue.slice(position, position + 1))) {
// eslint-disable-next-line no-param-reassign
position = position + 1;
}
else if (maskExpression.slice(position - 1, position + 1) !== "M0" /* MaskExpression.MONTHS */) {
// eslint-disable-next-line no-param-reassign
position = position - 2;
}
// eslint-disable-next-line no-param-reassign
this.deletedSpecialCharacter = false;
}
if (this.showMaskTyped &&
this.placeHolderCharacter.length === 1 &&
!this.leadZeroDateTime) {
// eslint-dis