UNPKG

ngx-mask

Version:

Input masking for modern Angular — Reactive, template-driven and Signal Forms, zoneless and SSR ready. Dates, numbers, separators, custom patterns.

2,913 lines • 141 kB
import * as i0 from "@angular/core";
import { ChangeDetectorRef, Directive, ElementRef, EnvironmentInjector, EventEmitter, Injectable, InjectionToken, Injector, NgZone, Pipe, Renderer2, afterNextRender, booleanAttribute, effect, inject, input, makeEnvironmentProviders, model, output, signal, untracked } from "@angular/core";
import { DOCUMENT } from "@angular/common";
import { NG_VALIDATORS, NG_VALUE_ACCESSOR, NgControl } from "@angular/forms";
var MaskExpression;
(function(MaskExpression) {
	MaskExpression["SEPARATOR"] = "separator";
	MaskExpression["PERCENT"] = "percent";
	MaskExpression["IP"] = "IP";
	MaskExpression["CPF_CNPJ"] = "CPF_CNPJ";
	MaskExpression["CPF_CNPJ_ALPHA"] = "CPF_CNPJ_ALPHA";
	MaskExpression["MONTH"] = "M";
	MaskExpression["MONTHS"] = "M0";
	MaskExpression["MINUTE"] = "m";
	MaskExpression["HOUR"] = "h";
	MaskExpression["HOURS"] = "H";
	MaskExpression["MINUTES"] = "m0";
	MaskExpression["HOURS_HOUR"] = "Hh";
	MaskExpression["SECONDS"] = "s0";
	MaskExpression["HOURS_MINUTES_SECONDS"] = "Hh:m0:s0";
	MaskExpression["EMAIL_MASK"] = "A*@A*.A*";
	MaskExpression["HOURS_MINUTES"] = "Hh:m0";
	MaskExpression["MINUTES_SECONDS"] = "m0:s0";
	MaskExpression["DAYS_MONTHS_YEARS"] = "d0/M0/0000";
	MaskExpression["DAYS_MONTHS"] = "d0/M0";
	MaskExpression["DAYS"] = "d0";
	MaskExpression["DAY"] = "d";
	MaskExpression["SECOND"] = "s";
	MaskExpression["LETTER_S"] = "S";
	MaskExpression["DOT"] = ".";
	MaskExpression["NUMPAD_DECIMAL"] = "Decimal";
	MaskExpression["NUMPAD_DECIMAL_CODE"] = "NumpadDecimal";
	MaskExpression["COMMA"] = ",";
	MaskExpression["CURLY_BRACKETS_LEFT"] = "{";
	MaskExpression["CURLY_BRACKETS_RIGHT"] = "}";
	MaskExpression["MINUS"] = "-";
	MaskExpression["OR"] = "||";
	MaskExpression["HASH"] = "#";
	MaskExpression["EMPTY_STRING"] = "";
	MaskExpression["SYMBOL_STAR"] = "*";
	MaskExpression["SYMBOL_QUESTION"] = "?";
	MaskExpression["SLASH"] = "/";
	MaskExpression["WHITE_SPACE"] = " ";
	MaskExpression["NUMBER_ZERO"] = "0";
	MaskExpression["NUMBER_NINE"] = "9";
	MaskExpression["BACKSPACE"] = "Backspace";
	MaskExpression["DELETE"] = "Delete";
	MaskExpression["ARROW_LEFT"] = "ArrowLeft";
	MaskExpression["ARROW_UP"] = "ArrowUp";
	MaskExpression["DOUBLE_ZERO"] = "00";
})(MaskExpression || (MaskExpression = {}));
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,
	showMaskTyped: false,
	instantPrefix: false,
	placeHolderCharacter: "_",
	dropSpecialCharacters: true,
	hiddenInput: false,
	shownMaskExpression: "",
	separatorLimit: "",
	allowNegativeNumbers: false,
	validation: true,
	specialCharacters: [
		"-",
		"/",
		"(",
		")",
		".",
		":",
		" ",
		"+",
		",",
		"@",
		"[",
		"]",
		"\"",
		"'"
	],
	leadZeroDateTime: false,
	apm: false,
	leadZero: false,
	typeFromDecimals: false,
	keepCharacterPositions: false,
	triggerOnMaskChange: false,
	inputTransformFn: (value) => value,
	outputTransformFn: (value) => value,
	maskFilled: new EventEmitter(),
	maskAliases: {},
	defaultValueOnBlur: null,
	patterns: {
		"0": { pattern: /* @__PURE__ */ new RegExp("\\d") },
		"9": {
			pattern: /* @__PURE__ */ new RegExp("\\d"),
			optional: true
		},
		X: {
			pattern: /* @__PURE__ */ new RegExp("\\d"),
			symbol: "*"
		},
		A: { pattern: /* @__PURE__ */ new RegExp("[a-zA-Z0-9]") },
		S: { pattern: /* @__PURE__ */ new RegExp("[a-zA-Z]") },
		U: { pattern: /* @__PURE__ */ new RegExp("[A-Z]") },
		L: { pattern: /* @__PURE__ */ new RegExp("[a-z]") },
		d: {
			pattern: /* @__PURE__ */ new RegExp("\\d"),
			symbol: "*"
		},
		m: { pattern: /* @__PURE__ */ new RegExp("\\d") },
		M: {
			pattern: /* @__PURE__ */ new RegExp("\\d"),
			symbol: "*"
		},
		H: { pattern: /* @__PURE__ */ new RegExp("\\d") },
		h: { pattern: /* @__PURE__ */ new RegExp("\\d") },
		s: { pattern: /* @__PURE__ */ new RegExp("\\d") }
	}
};
const RESERVED_MASK_TOKENS = /* @__PURE__ */ new Set([
	MaskExpression.IP,
	MaskExpression.CPF_CNPJ,
	MaskExpression.CPF_CNPJ_ALPHA,
	MaskExpression.EMAIL_MASK,
	MaskExpression.SEPARATOR,
	MaskExpression.PERCENT
]);
const warnedShadowedAliases = /* @__PURE__ */ new Set();
function resolveMaskAlias(maskExpression, maskAliases) {
	const expression = maskExpression ?? MaskExpression.EMPTY_STRING;
	if (!expression || !maskAliases) return expression;
	const aliased = maskAliases[expression];
	if (typeof aliased !== "string") return expression;
	if (RESERVED_MASK_TOKENS.has(expression)) {
		if (!warnedShadowedAliases.has(expression)) {
			warnedShadowedAliases.add(expression);
			console.warn(`ngx-mask: mask alias "${expression}" shadows a built-in mask token and is ignored. Rename the alias.`);
		}
		return expression;
	}
	return aliased;
}
const timeMasks = [
	MaskExpression.HOURS_MINUTES_SECONDS,
	MaskExpression.HOURS_MINUTES,
	MaskExpression.MINUTES_SECONDS
];
const withoutValidation = [
	MaskExpression.PERCENT,
	MaskExpression.HOURS_HOUR,
	MaskExpression.SECONDS,
	MaskExpression.MINUTES,
	MaskExpression.SEPARATOR,
	MaskExpression.DAYS_MONTHS_YEARS,
	MaskExpression.DAYS_MONTHS,
	MaskExpression.DAYS,
	MaskExpression.MONTHS
];
function escapeRegExp(value) {
	return (value ?? "").replace(/[.*+?^${}()|[\]\\/-]/g, "\\$&");
}
function nextFillableIndex(maskExpression, specialCharacters, index) {
	let maskIdx = index;
	while (maskIdx < maskExpression.length && specialCharacters.includes(maskExpression[maskIdx] ?? MaskExpression.EMPTY_STRING)) maskIdx += 1;
	return maskIdx;
}
function digitsOf(value) {
	return value.match(/\d/g) ?? [];
}
function ignoreDigitSeparator(separator) {
	return separator && digitsOf(separator).length ? "" : separator;
}
function activeDecimalMarker(value, decimalMarker, thousandSeparator) {
	if (!Array.isArray(decimalMarker)) return decimalMarker;
	const candidates = decimalMarker.filter((dm) => dm !== thousandSeparator);
	return candidates.find((dm) => value.includes(dm)) ?? candidates[0] ?? decimalMarker[0];
}
function usesCommaDecimal(value, decimalMarker, thousandSeparator) {
	return activeDecimalMarker(value, decimalMarker, thousandSeparator) === MaskExpression.COMMA;
}
function displayToPlainDecimal(value, decimalMarker, thousandSeparator) {
	const marker = activeDecimalMarker(value, decimalMarker, thousandSeparator);
	if (!thousandSeparator || marker === thousandSeparator || !value.includes(thousandSeparator) || !value.includes(marker)) return value;
	return value.split(thousandSeparator).join(MaskExpression.EMPTY_STRING).replace(marker, MaskExpression.DOT);
}
function containsStarSymbol(value, maskExpression, thousandSeparator) {
	return value.includes(MaskExpression.SYMBOL_STAR) && !(maskExpression.startsWith(MaskExpression.SEPARATOR) && thousandSeparator?.includes(MaskExpression.SYMBOL_STAR));
}
function retargetSeparatorValue(value, previous, current) {
	const prefix = previous.prefix && value.startsWith(previous.prefix) ? previous.prefix : "";
	const suffix = previous.suffix && value.length >= prefix.length + previous.suffix.length ? value.endsWith(previous.suffix) ? previous.suffix : "" : "";
	const number = value.slice(prefix.length, value.length - suffix.length);
	const previousMarker = activeDecimalMarker(number, previous.decimalMarker, previous.thousandSeparator ?? MaskExpression.EMPTY_STRING);
	const ungrouped = previous.thousandSeparator ? number.split(previous.thousandSeparator).join(MaskExpression.EMPTY_STRING) : number;
	const retargeted = ungrouped.replace(previousMarker, activeDecimalMarker(ungrouped, current.decimalMarker, current.thousandSeparator));
	return `${prefix ? current.prefix : ""}${retargeted}${suffix ? current.suffix : ""}`;
}
const cpfCnpjHandler = function(state, params) {
	const isCpfCnpjAlpha = state.maskExpression === MaskExpression.CPF_CNPJ_ALPHA;
	this.cpfCnpjError = params.arr.length !== 11 && params.arr.length !== 14;
	if (/[a-zA-Z]/.test(state.processedValue) && isCpfCnpjAlpha) state.maskExpression = "AA.AAA.AAA/AAAA-00";
	else if (params.arr.length > 11) state.maskExpression = isCpfCnpjAlpha ? "AA.AAA.AAA/AAAA-00" : "00.000.000/0000-00";
	else state.maskExpression = "000.000.000-00";
	return state;
};
function findDateTimeFieldAt(maskExpression, position) {
	const dateTimeTokens = [
		MaskExpression.DAY,
		MaskExpression.MONTH,
		MaskExpression.HOURS,
		MaskExpression.HOUR,
		MaskExpression.MINUTE,
		MaskExpression.SECOND
	];
	let index = 0;
	while (index < maskExpression.length) {
		const token = maskExpression[index] ?? MaskExpression.EMPTY_STRING;
		if (dateTimeTokens.includes(token)) {
			const next = maskExpression[index + 1];
			const isCombinedHour = (token === MaskExpression.HOURS || token === MaskExpression.HOUR) && next === MaskExpression.HOUR;
			const end = next === MaskExpression.NUMBER_ZERO || isCombinedHour ? index + 2 : index + 1;
			if (position >= index && position <= end) return {
				token,
				start: index,
				end
			};
			index = end;
			continue;
		}
		index++;
	}
	return null;
}
function isDateTimeMask(maskExpression) {
	for (let position = 0; position < maskExpression.length; position++) if (findDateTimeFieldAt(maskExpression, position)) return true;
	return false;
}
function isFieldOverflowing(field, position, elValue, inputValue, apm) {
	const fieldValue = Number(elValue.slice(field.start, field.end));
	const firstDigitValue = position === field.start + 1 ? Number(inputValue.slice(position - 1, position)) : NaN;
	switch (field.token) {
		case MaskExpression.DAY: return fieldValue > 31 && fieldValue < 40 || firstDigitValue > 3;
		case MaskExpression.MONTH: return fieldValue > 12 || firstDigitValue > 1;
		case MaskExpression.HOURS: return apm ? fieldValue > 12 || firstDigitValue > 9 : fieldValue > 23 || firstDigitValue > 2;
		case MaskExpression.HOUR: return apm ? fieldValue > 12 : fieldValue > 23;
		case MaskExpression.MINUTE:
		case MaskExpression.SECOND: return fieldValue > 59 || firstDigitValue > 5;
		default: return false;
	}
}
function leadZeroDateTimeCaret(maskExpression, position, elValue, inputValue, apm) {
	const field = findDateTimeFieldAt(maskExpression, position);
	return field && isFieldOverflowing(field, position, elValue, inputValue, apm) ? position + 2 : position;
}
function overwriteFullDateValue(maskExpression, inputValue, position, code) {
	if (inputValue.length >= maskExpression.length - 1 && code !== MaskExpression.BACKSPACE && maskExpression === MaskExpression.DAYS_MONTHS_YEARS && position < 10) {
		const inputSymbol = inputValue.slice(position - 1, position);
		return inputValue.slice(0, position - 1) + inputSymbol + inputValue.slice(position + 1);
	}
	return null;
}
const FIELD_MAX = {
	d: 31,
	M: 12,
	H: 23,
	h: 23,
	m: 59,
	s: 59
};
function overwriteDateSlot(svc, before, elValue, position) {
	const mask = svc.maskExpression;
	const start = position - 1;
	const display = elValue.length > mask.length ? elValue.slice(0, start) + elValue.slice(position) : before;
	const selEnd = display.length - elValue.length + position;
	const typed = elValue.charAt(start);
	const target = nextFillableIndex(mask, svc.specialCharacters, start);
	const slot = findDateTimeFieldAt(mask, target);
	const field = slot?.end === target ? findDateTimeFieldAt(mask, target + 1) : slot;
	if (!/[dM]/.test(mask) || display.length !== mask.length || !/\d/.test(display.charAt(target)) || elValue !== display.slice(0, start) + typed + display.slice(selEnd) || selEnd > (field?.end ?? target + 1) || selEnd - start > 1 && !svc.leadZeroDateTime) return null;
	if (!svc._checkSymbolMask(typed, mask.charAt(target))) return {
		value: display,
		position: start,
		end: -1
	};
	let value = display.slice(0, target) + typed + display.slice(target + 1);
	let caret = target + 1;
	if (field) {
		const max = svc.apm && /[Hh]/.test(field.token) ? 12 : FIELD_MAX[field.token];
		const over = Number(value.slice(field.start, field.end)) > max;
		if (svc.leadZeroDateTime && (over || selEnd > caret)) {
			const tens = target === field.start && Number(typed) * 10 <= max;
			value = display.slice(0, field.start) + (tens ? typed + "0" : "0" + typed) + display.slice(field.end);
			caret = tens ? caret : field.end;
		} else if (over) return null;
	}
	return {
		value,
		position: caret,
		end: caret
	};
}
const userEdits = /* @__PURE__ */ new WeakMap();
function setUserEdit(service, edit) {
	if (edit) userEdits.set(service, edit);
	else userEdits.delete(service);
}
function userEditFor(service, inputValue) {
	const edit = userEdits.get(service);
	return edit?.value === inputValue ? edit : null;
}
const EMAIL_AT = "@";
const EMAIL_LOCAL_PUNCTUATION = "._+-";
const EMAIL_DOMAIN_PUNCTUATION = ".-";
function isEmailPunctuation(inputSymbol, result) {
	const allowed = result.includes(EMAIL_AT) ? EMAIL_DOMAIN_PUNCTUATION : EMAIL_LOCAL_PUNCTUATION;
	const last = result.slice(-1);
	return allowed.includes(inputSymbol) && last !== MaskExpression.EMPTY_STRING && last !== EMAIL_AT && !(inputSymbol === MaskExpression.DOT && last === MaskExpression.DOT);
}
const genericPatternHandler = function(state, params) {
	const { inputArray } = params;
	const maskExpression = state.maskExpression;
	const processedValue = state.processedValue;
	let { cursor, result, multi, processedPosition, stepBack } = state;
	const userEdit = userEditFor(this, params.inputValue);
	const prefixOffset = params.startsWithPrefix && !params.prefixAlreadyRemovedByCaller ? this.prefix.length : 0;
	for (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 (this.leadZeroDateTime && (maskExpression[cursor] === MaskExpression.HOURS || maskExpression[cursor] === MaskExpression.HOUR && maskExpression[cursor + 1] === MaskExpression.HOUR) && Number(inputSymbol + (inputArray[i + 1] ?? MaskExpression.EMPTY_STRING)) > (this.apm ? 12 : 23) || maskExpression[cursor] === MaskExpression.HOURS && (this.apm ? Number(inputSymbol) > 9 : Number(inputSymbol) > 2)) {
				processedPosition = !this.leadZeroDateTime ? processedPosition + 1 : processedPosition;
				cursor += 1;
				this._shiftStep(cursor);
				i--;
				if (this.leadZeroDateTime) result += "0";
				continue;
			}
			if (maskExpression[cursor] === MaskExpression.HOUR) {
				const previousHourDigit = this.leadZeroDateTime ? result.slice(-1) : processedValue.slice(cursor - 1, cursor);
				if (this.apm ? result.length === 1 && Number(result) > 1 || result === "1" && Number(inputSymbol) > 2 || previousHourDigit.length === 1 && Number(previousHourDigit) > 2 || previousHourDigit === "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) {
					processedPosition = processedPosition + 1;
					cursor += 1;
					i--;
					continue;
				}
			}
			if (maskExpression[cursor] === MaskExpression.MINUTE || maskExpression[cursor] === MaskExpression.SECOND) {
				if (Number(inputSymbol) > 5) {
					processedPosition = !this.leadZeroDateTime ? processedPosition + 1 : processedPosition;
					cursor += 1;
					this._shiftStep(cursor);
					i--;
					if (this.leadZeroDateTime) result += "0";
					continue;
				}
			}
			if (userEdit && this.leadZeroDateTime && !this.keepCharacterPositions && !this.writingValue && inputSymbol === MaskExpression.NUMBER_ZERO && result.slice(-1) === MaskExpression.NUMBER_ZERO && i + prefixOffset >= userEdit.start && i + prefixOffset <= userEdit.end && (maskExpression[cursor - 1] === MaskExpression.DAY || maskExpression[cursor - 1] === MaskExpression.MONTH || this.apm && maskExpression[cursor] === MaskExpression.HOUR && (maskExpression[cursor - 1] === MaskExpression.HOURS || maskExpression[cursor - 1] === MaskExpression.HOUR))) inputSymbol = "1";
			const daysCount = 31;
			const inputValueCursor = processedValue[cursor];
			const inputValueCursorPlusOne = processedValue[cursor + 1];
			const inputValueCursorPlusTwo = processedValue[cursor + 2];
			const inputValueCursorMinusOne = processedValue[cursor - 1];
			const inputValueCursorMinusTwo = processedValue[cursor - 2];
			const inputValueSliceMinusThreeMinusOne = processedValue.slice(cursor - 3, cursor - 1);
			const inputValueSliceMinusOnePlusOne = processedValue.slice(cursor - 1, cursor + 1);
			const inputValueSliceCursorPlusTwo = processedValue.slice(cursor, cursor + 2);
			const inputValueSliceMinusTwoCursor = processedValue.slice(cursor - 2, cursor);
			const windowStart = params.justPasted || this.writingValue ? i : cursor;
			const windowSlice = processedValue.slice(windowStart, windowStart + 2);
			const windowNext = processedValue[windowStart + 1];
			const tokenAbutsDigitField = maskExpression[cursor - 1] === MaskExpression.NUMBER_ZERO;
			if (maskExpression[cursor] === MaskExpression.DAY) {
				const maskStartWithMonth = maskExpression.slice(0, 2) === MaskExpression.MONTHS;
				const startWithMonthInput = maskExpression.slice(0, 2) === MaskExpression.MONTHS && this.specialCharacters.includes(inputValueCursorMinusTwo);
				if (Number(inputSymbol) > 3 && this.leadZeroDateTime || !maskStartWithMonth && (Number(inputValueSliceCursorPlusTwo) > daysCount || !tokenAbutsDigitField && Number(inputValueSliceMinusOnePlusOne) > daysCount || this.specialCharacters.includes(inputValueCursorPlusOne)) || (startWithMonthInput ? Number(inputValueSliceMinusOnePlusOne) > daysCount || !this.specialCharacters.includes(inputValueCursor) && this.specialCharacters.includes(inputValueCursorPlusTwo) || this.specialCharacters.includes(inputValueCursor) : Number(windowSlice) > daysCount || this.specialCharacters.includes(windowNext) && !params.backspaced)) {
					processedPosition = !this.leadZeroDateTime ? processedPosition + 1 : processedPosition;
					cursor += 1;
					this._shiftStep(cursor);
					i--;
					if (this.leadZeroDateTime) result += "0";
					continue;
				}
			}
			if (maskExpression[cursor] === MaskExpression.MONTH) {
				const monthsCount = 12;
				let precedingFieldEnd = cursor - 1;
				while (precedingFieldEnd >= 0 && this.specialCharacters.includes(maskExpression[precedingFieldEnd])) precedingFieldEnd--;
				let precedingFieldStart = precedingFieldEnd;
				while (precedingFieldStart >= 0 && !this.specialCharacters.includes(maskExpression[precedingFieldStart])) precedingFieldStart--;
				const precedingField = maskExpression.slice(precedingFieldStart + 1, precedingFieldEnd + 1);
				const yearFieldPrecedesMonth = precedingField.length > 2 && precedingField.split(MaskExpression.EMPTY_STRING).every((token) => token === MaskExpression.NUMBER_ZERO);
				const withoutDays = cursor === 0 && (Number(inputSymbol) > 2 || Number(inputValueSliceCursorPlusTwo) > monthsCount || this.specialCharacters.includes(inputValueCursorPlusOne) && (!params.backspaced || this.leadZeroDateTime && /\d/.test(inputValueCursorPlusTwo)));
				const monthPair = processedValue.slice(i, i + 2);
				const yearFirstMonthOverflow = this.leadZeroDateTime && yearFieldPrecedesMonth && (Number(monthPair) > monthsCount || this.specialCharacters.includes(monthPair.charAt(1)) && this.specialCharacters.includes(processedValue.charAt(i - 1)));
				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));
				const day2monthInput = !tokenAbutsDigitField && !yearFieldPrecedesMonth && Number(inputValueSliceMinusThreeMinusOne) <= daysCount && !this.specialCharacters.includes(inputValueSliceMinusThreeMinusOne) && this.specialCharacters.includes(inputValueCursorMinusOne) && (Number(inputValueSliceCursorPlusTwo) > monthsCount || this.specialCharacters.includes(inputValueCursorPlusOne));
				const day2monthInputDot = Number(windowSlice) > monthsCount && cursor === 5 || this.specialCharacters.includes(windowNext) && cursor === 5;
				const day1monthPaste = !tokenAbutsDigitField && !yearFieldPrecedesMonth && Number(inputValueSliceMinusThreeMinusOne) > daysCount && !this.specialCharacters.includes(inputValueSliceMinusThreeMinusOne) && !this.specialCharacters.includes(inputValueSliceMinusTwoCursor) && Number(inputValueSliceMinusTwoCursor) > monthsCount && maskExpression.includes("d0");
				const day2monthPaste = !tokenAbutsDigitField && !yearFieldPrecedesMonth && 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 || yearFirstMonthOverflow) {
					processedPosition = !this.leadZeroDateTime ? processedPosition + 1 : processedPosition;
					cursor += 1;
					this._shiftStep(cursor);
					i--;
					if (this.leadZeroDateTime) result += "0";
					continue;
				}
			}
			result += inputSymbol;
			cursor++;
		} else if (this.specialCharacters.includes(inputSymbol) && maskExpression[cursor] === inputSymbol) {
			result += inputSymbol;
			cursor++;
		} else if (this.specialCharacters.indexOf(maskExpression[cursor] ?? MaskExpression.EMPTY_STRING) !== -1) {
			result += maskExpression[cursor];
			cursor++;
			this._shiftStep(cursor);
			i--;
		} else if (maskExpression[cursor] === MaskExpression.NUMBER_NINE && this.showMaskTyped) this._shiftStep(cursor);
		else if (this.patterns[maskExpression[cursor] ?? MaskExpression.EMPTY_STRING] && this.patterns[maskExpression[cursor] ?? MaskExpression.EMPTY_STRING]?.optional) {
			if (inputSymbol.trim() === MaskExpression.EMPTY_STRING) continue;
			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(MaskExpression.NUMBER_NINE + MaskExpression.SYMBOL_STAR) && maskExpression.includes(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] : 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] : inputSymbol === this.maskExpression[cursor + 2]) && multi) {
			cursor += 3;
			result += inputSymbol;
		} else if (maskExpression === MaskExpression.EMAIL_MASK && isEmailPunctuation(inputSymbol, result)) result += inputSymbol;
		else if (this.showMaskTyped && this.specialCharacters.indexOf(inputSymbol) < 0 && inputSymbol !== this.placeHolderCharacter && this.placeHolderCharacter.length === 1) stepBack = true;
	}
	state.cursor = cursor;
	state.result = result;
	state.multi = multi;
	state.processedPosition = processedPosition;
	state.stepBack = stepBack;
	return state;
};
const ipHandler = function(state) {
	const valuesIP = state.processedValue.split(MaskExpression.DOT);
	this.ipError = this._validIP(valuesIP);
	state.maskExpression = "099.099.099.099";
	return state;
};
const percentHandler = function(state, params) {
	const { backspaced } = params;
	const { cursor } = state;
	let processedValue = state.processedValue;
	if (processedValue.match("[a-z]|[A-Z]") || processedValue.match(/[-!$%^&*()_+|~=`{}\[\]:";'<>?,\/.]/) && !backspaced) {
		processedValue = this._stripToDecimal(processedValue);
		const precision = this.getPrecision(state.maskExpression);
		processedValue = this.checkInputPrecision(processedValue, precision);
	}
	const decimalMarker = this._activeDecimalMarker(processedValue);
	if (processedValue.indexOf(decimalMarker) > 0 && !this.percentage(processedValue.substring(0, processedValue.indexOf(decimalMarker)))) {
		let base = processedValue.substring(0, processedValue.indexOf(decimalMarker) - 1);
		if (this.allowNegativeNumbers && processedValue.slice(cursor, cursor + 1) === MaskExpression.MINUS && !backspaced) base = processedValue.substring(0, processedValue.indexOf(decimalMarker));
		processedValue = `${base}${processedValue.substring(processedValue.indexOf(decimalMarker), processedValue.length)}`;
	}
	let value;
	this.allowNegativeNumbers && processedValue.slice(cursor, cursor + 1) === MaskExpression.MINUS ? value = `${MaskExpression.MINUS}${processedValue.slice(cursor + 1, cursor + processedValue.length)}` : value = processedValue;
	if (this.percentage(value)) state.result = this._splitPercentZero(processedValue);
	else state.result = this._splitPercentZero(processedValue.substring(0, processedValue.length - 1));
	state.processedValue = processedValue;
	return state;
};
const INVALID_SEPARATOR_CHARS = [..."@#!$%^&*()_+|~=`{}[]: ,.\";<>?/"];
const separatorHandler = function(state, params) {
	const { backspaced, justPasted, startsWithPrefix, prefixAlreadyRemovedByCaller, cb, inputValue } = params;
	let { processedValue, processedPosition, backspaceShift, shift, stepBack } = state;
	let result;
	if (processedValue.match("[wа-яА-Я]") || processedValue.match("[ЁёА-я]") || processedValue.match("[a-z]|[A-Z]") || processedValue.match(/[-@#!$%\\^&*()_£¬'+|~=`{}\]:";<>.?/]/) || processedValue.match("[^A-Za-z0-9,]")) processedValue = this._stripToDecimal(processedValue);
	const precision = this.getPrecision(state.maskExpression);
	let decimalMarker = this.decimalMarker;
	if (Array.isArray(this.decimalMarker)) decimalMarker = this._activeDecimalMarker(this.actualValue);
	if (this.typeFromDecimals && Number.isFinite(precision) && precision > 0 && !justPasted && !this.writingValue) {
		result = this._formatFromDecimals(processedValue, precision, decimalMarker);
		this._shift.clear();
		const res = result.includes(MaskExpression.MINUS) && this.prefix && this.allowNegativeNumbers ? `${MaskExpression.MINUS}${this.prefix}${result.split(MaskExpression.MINUS).join(MaskExpression.EMPTY_STRING)}${this.suffix}` : result.length ? `${this.prefix}${result}${this.suffix}` : this.instantPrefix ? this.prefix : MaskExpression.EMPTY_STRING;
		cb(res.length - this.suffix.length - processedPosition, true);
		state.earlyReturn = res;
		return state;
	}
	if (!justPasted && !backspaced && !this.writingValue) {
		const isDecimalMarkerChar = (char) => !!char && char !== this.thousandSeparator && (Array.isArray(this.decimalMarker) ? this.decimalMarker.includes(char) : char === this.decimalMarker);
		const prefixOffset = startsWithPrefix && !prefixAlreadyRemovedByCaller ? this.prefix.length : 0;
		const typedMarkerIndex = processedPosition - prefixOffset - 1;
		if (typedMarkerIndex >= 0 && isDecimalMarkerChar(processedValue[typedMarkerIndex])) {
			let markerCount = 0;
			for (const char of processedValue) if (isDecimalMarkerChar(char)) markerCount++;
			if (markerCount > 1) {
				processedValue = processedValue.slice(0, typedMarkerIndex) + processedValue.slice(typedMarkerIndex + 1);
				stepBack = true;
			}
		}
	}
	if (justPasted && Array.isArray(this.decimalMarker)) {
		const markerPositions = [];
		for (let i = 0; i < processedValue.length; i++) {
			const char = processedValue[i];
			if (char !== this.thousandSeparator && this.decimalMarker.includes(char)) markerPositions.push(i);
		}
		if (markerPositions.length > 1) {
			const lastMarkerPosition = markerPositions[markerPositions.length - 1];
			processedValue = processedValue.split(MaskExpression.EMPTY_STRING).filter((_, index) => index === lastMarkerPosition || !markerPositions.includes(index)).join(MaskExpression.EMPTY_STRING);
		}
	}
	if (backspaced) {
		const { decimalMarkerIndex, nonZeroIndex } = this._findFirstNonZeroAndDecimalIndex(processedValue, decimalMarker);
		const zeroIndexMinus = processedValue[0] === MaskExpression.MINUS;
		const zeroIndexDecimalMarker = processedValue[0] === decimalMarker;
		const firstIndexDecimalMarker = processedValue[1] === decimalMarker;
		if (zeroIndexDecimalMarker && !nonZeroIndex || zeroIndexMinus && firstIndexDecimalMarker && !nonZeroIndex) processedValue = MaskExpression.NUMBER_ZERO;
		if (decimalMarkerIndex && nonZeroIndex && zeroIndexMinus && processedPosition === 1) {
			if (decimalMarkerIndex < nonZeroIndex || decimalMarkerIndex > nonZeroIndex) processedValue = MaskExpression.MINUS + processedValue.slice(nonZeroIndex);
		}
		if (decimalMarkerIndex === null && nonZeroIndex && processedValue.length > nonZeroIndex) processedValue = zeroIndexMinus ? MaskExpression.MINUS + processedValue.slice(nonZeroIndex) : processedValue.slice(nonZeroIndex);
		if (decimalMarkerIndex && nonZeroIndex && processedPosition === 0) {
			if (decimalMarkerIndex < nonZeroIndex) processedValue = processedValue.slice(decimalMarkerIndex - 1);
			if (decimalMarkerIndex > nonZeroIndex) processedValue = processedValue.slice(nonZeroIndex);
		}
	}
	if (precision === 0 && !backspaced) processedValue = this.allowNegativeNumbers ? processedValue.length > 2 && processedValue[0] === MaskExpression.MINUS && processedValue[1] === MaskExpression.NUMBER_ZERO && processedValue[2] !== this.thousandSeparator && processedValue[2] !== MaskExpression.COMMA && processedValue[2] !== MaskExpression.DOT ? "-" + processedValue.slice(2, processedValue.length) : processedValue[0] === MaskExpression.NUMBER_ZERO && processedValue.length > 1 && processedValue[1] !== this.thousandSeparator && processedValue[1] !== MaskExpression.COMMA && processedValue[1] !== MaskExpression.DOT ? processedValue.slice(1, processedValue.length) : processedValue : processedValue.length > 1 && processedValue[0] === MaskExpression.NUMBER_ZERO && processedValue[1] !== this.thousandSeparator && processedValue[1] !== MaskExpression.COMMA && processedValue[1] !== MaskExpression.DOT ? processedValue.slice(1, processedValue.length) : processedValue;
	else {
		if (processedValue[0] === decimalMarker && processedValue.length > 1 && !backspaced) {
			processedValue = MaskExpression.NUMBER_ZERO + processedValue.slice(0, processedValue.length + 1);
			this.plusOnePosition = true;
		}
		if (processedValue[0] === MaskExpression.NUMBER_ZERO && processedValue[1] !== decimalMarker && processedValue[1] !== this.thousandSeparator && !backspaced) {
			processedValue = processedValue.length > 1 ? processedValue.slice(0, 1) + decimalMarker + processedValue.slice(1, processedValue.length + 1) : processedValue;
			this.plusOnePosition = true;
		}
		if (this.allowNegativeNumbers && !backspaced && processedValue[0] === MaskExpression.MINUS && (processedValue[1] === decimalMarker || processedValue[1] === MaskExpression.NUMBER_ZERO)) {
			processedValue = processedValue[1] === decimalMarker && processedValue.length > 2 ? processedValue.slice(0, 1) + MaskExpression.NUMBER_ZERO + processedValue.slice(1, processedValue.length) : processedValue[1] === MaskExpression.NUMBER_ZERO && processedValue.length > 2 && processedValue[2] !== decimalMarker ? processedValue.slice(0, 2) + decimalMarker + processedValue.slice(2, processedValue.length) : processedValue;
			this.plusOnePosition = true;
		}
	}
	const thousandSeparatorCharEscaped = this._charToRegExpExpression(this.thousandSeparator);
	const allowedChars = [this.thousandSeparator, ...[this.decimalMarker].flat()];
	const invalidChars = INVALID_SEPARATOR_CHARS.filter((char) => !allowedChars.includes(char)).map((char) => char === " " ? "\\s" : escapeRegExp(char)).join("");
	const invalidCharRegexp = new RegExp("[" + invalidChars + "]");
	if (processedValue.match(invalidCharRegexp)) processedValue = processedValue.substring(0, processedValue.length - 1);
	processedValue = this.checkInputPrecision(processedValue, precision);
	const strForSep = processedValue.replace(new RegExp(thousandSeparatorCharEscaped, "g"), "");
	result = this._formatWithSeparators(strForSep, this.thousandSeparator, this.decimalMarker, precision);
	const commaShift = result.indexOf(MaskExpression.COMMA) - processedValue.indexOf(MaskExpression.COMMA);
	const shiftStep = result.length - processedValue.length;
	const backspacedDecimalMarkerWithSeparatorLimit = backspaced && result.length < inputValue.length - this.suffix.length && this.separatorLimit;
	if ((result[processedPosition - 1] === this.thousandSeparator || result[processedPosition - this.prefix.length]) && this.prefix && backspaced) processedPosition = processedPosition - 1;
	else if (shiftStep > 0 && result[processedPosition] !== this.thousandSeparator || backspacedDecimalMarkerWithSeparatorLimit) {
		backspaceShift = true;
		let _shift = 0;
		do {
			this._shift.add(processedPosition + _shift);
			_shift++;
		} while (_shift < shiftStep);
	} else if (result[processedPosition - 1] === this.thousandSeparator || shiftStep === -4 || shiftStep === -3 || result[processedPosition] === this.thousandSeparator) {
		this._shift.clear();
		this._shift.add(processedPosition - 1);
	} else if (commaShift !== 0 && processedPosition > 0 && !(result.indexOf(MaskExpression.COMMA) >= processedPosition && processedPosition > 3) || !(result.indexOf(MaskExpression.DOT) >= processedPosition && processedPosition > 3) && shiftStep <= 0) {
		this._shift.clear();
		backspaceShift = true;
		shift = shiftStep;
		processedPosition += shiftStep;
		this._shift.add(processedPosition);
	} else this._shift.clear();
	state.processedValue = processedValue;
	state.processedPosition = processedPosition;
	state.result = result;
	state.backspaceShift = backspaceShift;
	state.shift = shift;
	state.stepBack = stepBack;
	return state;
};
const MASK_HANDLERS = [
	{
		id: "ip",
		terminal: false,
		match: (maskExpression) => maskExpression === MaskExpression.IP,
		handle: ipHandler
	},
	{
		id: "cpf-cnpj",
		terminal: false,
		match: (maskExpression) => maskExpression === MaskExpression.CPF_CNPJ || maskExpression === MaskExpression.CPF_CNPJ_ALPHA,
		handle: cpfCnpjHandler
	},
	{
		id: "percent",
		terminal: true,
		match: (maskExpression) => maskExpression.startsWith(MaskExpression.PERCENT),
		handle: percentHandler
	},
	{
		id: "separator",
		terminal: true,
		match: (maskExpression) => maskExpression.startsWith(MaskExpression.SEPARATOR),
		handle: separatorHandler
	}
];
function dispatchMaskHandler(self, state, params) {
	for (const entry of MASK_HANDLERS) if (entry.match(state.maskExpression)) {
		const next = entry.handle.call(self, state, params);
		return entry.terminal ? next : genericPatternHandler.call(self, next, params);
	}
	return genericPatternHandler.call(self, state, params);
}
var NgxMaskApplierService = class NgxMaskApplierService {
	_config = inject(NGX_MASK_CONFIG);
	dropSpecialCharacters = this._config.dropSpecialCharacters;
	hiddenInput = this._config.hiddenInput;
	clearIfNotMatch = this._config.clearIfNotMatch;
	specialCharacters = this._config.specialCharacters;
	patterns = this._config.patterns;
	prefix = this._config.prefix;
	suffix = this._config.suffix;
	_thousandSeparator = ignoreDigitSeparator(this._config.thousandSeparator);
	get thousandSeparator() {
		return this._thousandSeparator;
	}
	set thousandSeparator(value) {
		this._thousandSeparator = ignoreDigitSeparator(value);
	}
	decimalMarker = this._config.decimalMarker;
	showMaskTyped = this._config.showMaskTyped;
	placeHolderCharacter = this._config.placeHolderCharacter;
	validation = this._config.validation;
	separatorLimit = this._config.separatorLimit;
	allowNegativeNumbers = this._config.allowNegativeNumbers;
	leadZeroDateTime = this._config.leadZeroDateTime;
	leadZero = this._config.leadZero;
	typeFromDecimals = this._config.typeFromDecimals;
	apm = this._config.apm;
	inputTransformFn = this._config.inputTransformFn;
	outputTransformFn = this._config.outputTransformFn;
	keepCharacterPositions = this._config.keepCharacterPositions;
	instantPrefix = this._config.instantPrefix;
	triggerOnMaskChange = this._config.triggerOnMaskChange;
	_shift = /* @__PURE__ */ new Set();
	plusOnePosition = false;
	maskExpression = "";
	actualValue = "";
	shownMaskExpression = this._config.shownMaskExpression;
	deletedSpecialCharacter = false;
	writingValue = false;
	ipError;
	cpfCnpjError;
	applyMask(inputValue, maskExpression, position = 0, justPasted = false, backspaced = false, cb = () => {}) {
		if (!maskExpression || typeof inputValue !== "string") return MaskExpression.EMPTY_STRING;
		let cursor = 0;
		let result = "";
		const multi = false;
		let backspaceShift = false;
		let shift = 1;
		let stepBack = false;
		let processedValue = inputValue;
		let processedPosition = position;
		const startsWithPrefix = processedValue.slice(0, this.prefix.length) === this.prefix;
		const prefixAlreadyRemovedByCaller = justPasted && this.showMaskTyped && this.placeHolderCharacter.length === 1 && !this.leadZeroDateTime && processedValue !== this.prefix;
		if (startsWithPrefix && !prefixAlreadyRemovedByCaller) processedValue = processedValue.slice(this.prefix.length);
		if (!!this.suffix && processedValue.length > 0) processedValue = this.checkAndRemoveSuffix(processedValue);
		if (processedValue === "(" && this.prefix) processedValue = "";
		const inputArray = processedValue.toString().split(MaskExpression.EMPTY_STRING);
		if (this.allowNegativeNumbers && processedValue.slice(cursor, cursor + 1) === MaskExpression.MINUS) result += processedValue.slice(cursor, cursor + 1);
		const arr = digitsOf(processedValue);
		const state = {
			processedValue,
			processedPosition,
			cursor,
			result,
			multi,
			backspaceShift,
			shift,
			stepBack,
			maskExpression
		};
		const resolved = dispatchMaskHandler(this, state, {
			inputValue,
			position,
			justPasted,
			backspaced,
			cb,
			inputArray,
			arr,
			startsWithPrefix,
			prefixAlreadyRemovedByCaller
		});
		if (typeof resolved.earlyReturn === "string") return resolved.earlyReturn;
		processedValue = resolved.processedValue;
		processedPosition = resolved.processedPosition;
		cursor = resolved.cursor;
		result = resolved.result;
		backspaceShift = resolved.backspaceShift;
		shift = resolved.shift;
		stepBack = resolved.stepBack;
		maskExpression = resolved.maskExpression;
		if (result[processedPosition - 1] && result.length + 1 === maskExpression.length && this.specialCharacters.indexOf(maskExpression[maskExpression.length - 1] ?? MaskExpression.EMPTY_STRING) !== -1) result += maskExpression[maskExpression.length - 1];
		let newPosition = processedPosition + 1;
		while (this._shift.has(newPosition)) {
			shift++;
			newPosition++;
		}
		let actualShift = justPasted && !maskExpression.startsWith(MaskExpression.SEPARATOR) ? cursor : this._shift.has(processedPosition) ? 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.instantPrefix ? `${this.prefix}${result}` : `${result}`;
		if (processedValue.length === 1 && this.specialCharacters.includes(maskExpression[0]) && processedValue !== maskExpression[0]) {
			const firstPatternIndex = nextFillableIndex(maskExpression, this.specialCharacters, 1);
			if (!this._checkSymbolMask(processedValue, maskExpression[firstPatternIndex] ?? MaskExpression.EMPTY_STRING)) return "";
		}
		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) {
		const pattern = this.patterns[maskSymbol]?.pattern;
		return pattern ? this._testPattern(pattern, inputSymbol) : false;
	}
	_testPattern(pattern, value) {
		pattern.lastIndex = 0;
		return pattern.test(value);
	}
	_formatWithSeparators = (str, thousandSeparatorChar, decimalChars, precision) => {
		let x;
		let decimalChar;
		if (Array.isArray(decimalChars)) {
			const regExp = new RegExp(decimalChars.map((v) => escapeRegExp(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);
		}
		res = this._applyThousandGrouping(res, thousandSeparatorChar);
		if (typeof precision === "undefined") return res + decimals;
		else if (precision === 0) return res;
		return res + decimals.substring(0, precision + 1);
	};
	_formatFromDecimals(value, precision, decimalMarker) {
		const negative = this.allowNegativeNumbers && value.startsWith(MaskExpression.MINUS);
		let digits = value.replace(/\D+/g, MaskExpression.EMPTY_STRING).replace(/^0+/, "");
		if (!digits) return negative ? MaskExpression.MINUS : MaskExpression.EMPTY_STRING;
		const separatorLimit = this.separatorLimit.replace(/\s/g, MaskExpression.EMPTY_STRING);
		if (separatorLimit && +separatorLimit) digits = digits.slice(0, separatorLimit.length + precision);
		digits = digits.padStart(precision + 1, MaskExpression.NUMBER_ZERO);
		const integerPart = this._applyThousandGrouping(digits.slice(0, digits.length - precision), this.thousandSeparator);
		const decimalPart = digits.slice(digits.length - precision);
		return `${negative ? MaskExpression.MINUS : MaskExpression.EMPTY_STRING}${integerPart}${decimalMarker}${decimalPart}`;
	}
	_applyThousandGrouping(digits, separator) {
		const rgx = /(\d+)(\d{3})/;
		let grouped = digits;
		while (separator && rgx.test(grouped)) grouped = grouped.replace(rgx, (_match, head, tail) => head + separator + tail);
		return grouped;
	}
	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;
	};
	getPrecision = (maskExpression) => {
		const x = maskExpression.split(MaskExpression.DOT);
		if (x.length > 1) return Number(x[x.length - 1]);
		return Infinity;
	};
	checkAndRemoveSuffix = (inputValue) => {
		for (let i = this.suffix?.length - 1; i >= 0; i--) {
			const substr = this.suffix.substring(i, this.suffix?.length);
			if (inputValue.endsWith(substr) && i !== this.suffix?.length - 1 && (i === 0 || inputValue.length > substr.length || this.actualValue.endsWith(this.suffix) && inputValue.length <= this.actualValue.length - this.suffix.length) && (i - 1 < 0 || !inputValue.endsWith(this.suffix.substring(i - 1, this.suffix?.length)))) return inputValue.slice(0, inputValue.length - substr.length);
		}
		return inputValue;
	};
	checkInputPrecision = (inputValue, precision) => {
		let processedInputValue = inputValue;
		if (precision < Infinity) {
			const decimalMarker = this._activeDecimalMarker(inputValue);
			const precisionRegEx = new RegExp(this._charToRegExpExpression(decimalMarker) + `\\d{${precision}}.*$`);
			const precisionMatch = processedInputValue.match(precisionRegEx);
			const precisionMatchLength = (precisionMatch && precisionMatch[0]?.length) ?? 0;
			if (precisionMatchLength - 1 > precision) {
				const diff = precisionMatchLength - 1 - precision;
				processedInputValue = processedInputValue.substring(0, processedInputValue.length - diff);
			}
			if (precision === 0 && this._compareOrIncludes(processedInputValue[processedInputValue.length - 1], decimalMarker, this.thousandSeparator)) processedInputValue = processedInputValue.substring(0, processedInputValue.length - 1);
		}
		return processedInputValue;
	};
	_stripToDecimal(str) {
		const isDecimalMarkerChar = (char) => char === MaskExpression.DOT || char === MaskExpression.COMMA;
		return str.split(MaskExpression.EMPTY_STRING).filter((i, idx) => {
			const isDecimalMarker = typeof this.decimalMarker === "string" ? i === this.decimalMarker : isDecimalMarkerChar(i) && 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 (!char) return char;
		return char === " " ? "\\s" : escapeRegExp(char);
	}
	_shiftStep(cursor) {
		this._shift.add(cursor + 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;
		}));
	}
	_activeDecimalMarker(value) {
		return activeDecimalMarker(value, this.decimalMarker, this.thousandSeparator);
	}
	_splitPercentZero(value) {
		if (value === MaskExpression.MINUS && this.allowNegativeNumbers) return value;
		const decimal = this._activeDecimalMarker(value);
		const decimalIndex = value.indexOf(decimal);
		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();
			return integerString === MaskExpression.EMPTY_STRING ? MaskExpression.EMPTY_STRING : `${emptyOrMinus}${integerString}${decimal}${decimalPart}`;
		}
	}
	_findFirstNonZeroAndDecimalIndex(inputString, decimalMarker) {
		let decimalMarkerIndex = null;
		let nonZeroIndex = null;
		for (let i = 0; i < inputString.length; i++) {
			const char = inputString[i];
			if (char === decimalMarker && decimalMarkerIndex === null) decimalMarkerIndex = i;
			if (char && char >= "1" && char <= "9" && nonZeroIndex === null) nonZeroIndex = i;
			if (decimalMarkerIndex !== null && nonZeroIndex !== null) break;
		}
		return {
			decimalMarkerIndex,
			nonZeroIndex
		};
	}
	static ɵfac = i0.ɵɵngDeclareFactory({
		minVersion: "12.0.0",
		version: "22.2.3",
		ngImport: i0,
		type: NgxMaskApplierService,
		deps: [],
		target: i0.ɵɵFactoryTarget.Injectable
	});
	static ɵprov = i0.ɵɵngDeclareInjectable({
		minVersion: "12.0.0",
		version: "22.2.3",
		ngImport: i0,
		type: NgxMaskApplierService
	});
};
i0.ɵɵngDeclareClassMetadata({
	minVersion: "12.0.0",
	version: "22.2.3",
	ngImport: i0,
	type: NgxMaskApplierService,
	decorators: [{ type: Injectable }]
});
var NgxMaskService = class NgxMaskService extends NgxMaskApplierService {
	isNumberValue = false;
	maskIsShown = "";
	selStart = null;
	selEnd = null;
	maskChanged = false;
	previousValue = "";
	currentValue = "";
	isInitialized = false;
	keepCharacterPositionsHandled = null;
	_isFocused = signal(false, ...ngDevMode ? [{ debugName: "_isFocused" }] : /* istanbul ignore next */ []);
	_emitValue = false;
	onChange = (_) => {};
	_elementRef = inject(ElementRef, { optional: true });
	document = inject(DOCUMENT);
	_config = inject(NGX_MASK_CONFIG);
	_renderer = inject(Renderer2, { optional: true });
	applyMask(inputValue, maskExpression, position = 0, justPasted = false, backspaced = false, cb = () => {}) {
		const kcpHandled = this.keepCharacterPositionsHandled;
		this.keepCharacterPositionsHandled = null;
		if (!maskExpression) {
			if (this.maskChanged) {
				const rawValue = this.removeMask(inputValue);
				this.previousValue = this.currentValue;
				this.currentValue = rawValue;
				this.actualValue = rawValue;
				this._emitValue = this.previousValue !== this.currentValue;
				if (this._emitValue && this.triggerOnMaskChange) this.formControlResult(rawValue);
				this._clearMaskChangedUnlessTriggered();
				return rawValue;
			}
			return inputValue !== this.actualValue ? this.actualValue : inputValue;
		}
		if (maskExpression.startsWith(MaskExpression.SEPARATOR) && inputValue && /\d[eE][+-]?\d/.test(inputValue)) {
			const expandedNumber = Number(this._replaceDecimalMarkerToDot(inputValue));
			if (!Number.isNaN(expandedNumber)) {
				inputValue = this._toPlainDecimalString(expandedNumber);
				if (this.decimalMarker === MaskExpression.COMMA || Array.isArray(this.decimalMarker) && this.thousandSeparator === MaskExpression.DOT) inputValue = inputValue.replace(MaskExpression.DOT, MaskExpression.COMMA);
			}
		}
		this.maskIsShown = this.showMaskTyped ? this.showMaskInInput() : MaskExpression.EMPTY_STRING;
		if (this.maskExpression === MaskExpression.IP && this.showMaskTyped) this.maskIsShown = this.showMaskInInput(inputValue || MaskExpression.HASH);
		if ((this.maskExpression === MaskExpression.CPF_CNPJ || this.maskExpression === MaskExpression.CPF_CNPJ_ALPHA) && this.showMaskTyped) this.maskIsShown = this.showMaskInInput(inputValue || MaskExpression.HASH);
		if (!inputValue && this.showMaskTyped) {
			if (!this.writingValue) this.formControlResult(this.prefix);
			this.previousValue = this.currentValue;
			this.currentValue = MaskExpression.EMPTY_STRING;
			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 = "";
		let newPosition = position;
		if ((this.hiddenInput || inputValue && containsStarSymbol(inputValue, this.maskExpression, this.thousandSeparator)) && !this.writingValue) {
			let actualResult = inputValue && inputValue.length === 1 && !backspaced ? inputValue.split(MaskExpression.EMPTY_STRING) : this.actualValue.split(MaskExpression.EMPTY_STRING);
			if (backspaced) actualResult = actualResult.slice(0, position).concat(actualResult.slice(position + 1));
			if (this.showMaskTyped) {
				inputValue = this.removeMask(inputValue);
				actualResult = this.removeMask(actualResult.join("")).split(MaskExpression.EMPTY_STRING);
			}
			if (typeof this.selStart === "object" && typeof this.selEnd === "object") {
				this.selStart = Number(this.selStart);
				this.selEnd = Number(this.selEnd);
			} else if (inputValue !== MaskExpression.EMPTY_STRING && actualResult.length) {
				if (typeof this.selStart === "number" && typeof this.selEnd === "number") {
					if (inputValue.length > actualResult.length) actualResult.splice(this.selStart, 0, getSymbol);
					else if (inputValue.length < actualResult.length) {
						if (actualResult.length - inputValue.length === 1) {
							if (backspaced) actualResult.splice(this.selStart - 1, 1);
							else actualResult.splice(inputValue.length - 1, 1);
						} else actualResult.splice(this.selStart, this.selEnd - this.selStart);
					}
				}
			} else actualResult = [];
			if (this.actualValue.length) {
				if (actualResult.length < inputValue.length) newInputValue = this.shiftTypedSymbols(actualResult.join(MaskExpression.EMPTY_STRING));
				else if (actualResult.length === inputValue.length) newInputValue = actualResult.join(MaskExpression.EMPTY_STRING);
				else newInputValue = inputValue;
			} else newInputValue = inputValue;
		}
		if (justPasted) newInputValue = inputValue;
		if (backspaced && this.specialCharacters.indexOf(this.maskExpression[newPosition] ?? MaskExpression.EMPTY_STRING) !== -1 && this.showMaskTyped && !this.prefix) newInputValue = this.currentValue;
		if (this.deletedSpecialCharacter && newPosition) {
			if (this.specialCharacters.includes(this.actualValue.slice(newPosition, newPosition + 1))) newPosition = newPosition + 1;
			else if (maskExpression.slice(newPosition - 1, newPosition + 1) !== MaskExpression.MONTHS) newPosition = newPosition - 2;
			this.deletedSpecialCharacter = false;
		}
		if (this.showMaskTyped && this.placeHolderCharacter.length === 1 && !this.leadZeroDateTime) newInputValue = this.removeMask(newInputValue);
		if (this.maskChanged) newInputValue = inputValue;
		else newInputValue = Boolean(newInputValue) && newInputValue.length ? newInputValue : inputValue;
		if ((kcpHandled ?? this.showMaskTyped) && this.keepCharacterPositions && this.actualValue && !justPasted && !this.writingValue) {
			const value = this.dropSpecialCharacters ? this.removeMask(this.actualValue) : this.actualValue;
			this.formControlResult(value);
			return this.actualValue ? this.actualValue : `${this.prefix}${this.maskIsShown}${this.suffix}`;
		}
		const result = super.applyMask(newInputValue, maskExpression, newPosition, justPasted, backspaced, cb);
		if ((this.writingValue || !this.maskChanged && inputValue === this.currentValue) && inputValue && !result && this.removeMask(inputValue)) {
			this.actualValue = inputValue;
			this.previousValue = this.currentValue;
			this.currentValue = inputValue;
			return inputValue;
		}
		this.actualValue = this.getActualValue(result);
		if (this.thousandSeparator === MaskExpression.DOT && this.decimalMarker === MaskExpression.DOT) this.decimalMarker = MaskExpression.COMMA;
		if (this.maskExpression.startsWith(MaskExpression.SEPARATOR) && this.dropSpecialCharacters === true) this.specialCharacters = this.specialCharacters.filter((item) => !this._compareOrIncludes(item, this.decimalMarker, this.thousandSeparator));
		if (result || result === "") {
			this.previousValue = this.currentValue;
			this.currentValue = result;
			this._emitValue = this.previousValue !== this.currentValue || this.previousValue === this.currentValue && justPasted;
		}
		if (this._emitValue && (!this.maskChanged || this.triggerOnMaskChange)) this.formControlResult(result);
		this._clearMaskChangedUnlessTriggered();
		if (!this.showMaskTyped || this.showMaskTyped && this.hiddenInput) {
			if (this.hiddenInput) return `${this.hideInput(result, this.maskExpression)}${this.maskIsShown.slice(result.length)}`;
			return result;
		}
		const resLen = result.length;
		const prefNmask = `${this.prefix}${this.maskIsShown}${this.suffix}`;
		if (this.maskExpression === MaskExpression.IP || this.maskExpression === MaskExpression.CPF_CNPJ || this.maskExpression === MaskExpression.CPF_CNPJ_ALPHA) return `${result}${prefNmask}`;
		else if (this.maskExpression.includes(MaskExpression.HOURS)) {
			const countSkipedSymbol = this._numberSkipedSymbols(result);
			return `${result}${prefNmask.slice(resLen + countSkipedSymbol)}`;
		}
		return `${result}${prefNmask.slice(resLen)}`;
	}
	_numberSkipedSymbols(value) {
		const regex = /(^|\D)(\d\D)/g;
		let match = regex.exec(value);
		let countSkipedSymbol = 0;
		while (match != null) {
			countSkipedSymbol += 1;
			match = regex.exec(value);
		}
		return countSkipedSymbol;
	}
	applyValueChanges(position, justPasted, backspaced, cb = () => {}) {
		const formElement = this._elementRef?.nativeElement;
		if (!formElement) return;
		const typedValue = formElement.value;
		const maskedValue = this.applyMask(typedValue, this.maskExpression, position, justPasted, backspaced, cb);
		if (formElement.value === typedValue && formElement.value !== maskedValue) formElement.value = maskedValue;
		if (formElement === this._getActiveElement()) return;
		this.clearIfNotMatchFn();
	}
	hideInput(inputValue, maskExpression) {
		return inputValue.split(MaskExpression.EMPTY_STRING).map((curr, index) => {
			const maskChar = maskExpression[index] ?? MaskExpression.EMPTY_STRING;
			const pattern = this.patterns?.[maskChar];
			if (pattern?.symbol) return pattern.symbol;
			const prevMaskChar = maskExpression[index - 1];
			const prevPattern = prevMaskChar ? this.patterns?.[prevMaskChar] : null;
			if (maskChar === MaskExpression.NUMBER_ZERO && (prevMaskChar === MaskExpression.DAY || prevMaskChar === MaskExpression.MONTH) && prevPattern?.symbol) return prevPattern.symbol;
			return curr;
		}).join(MaskExpression.EMPTY_STRING);
	}
	getActualValue(res) {
		const compare = res.split(MaskExpression.EMPTY_STRING).filter((symbol, i) => {
			const maskChar = this.maskExpression[i] ?? MaskExpression.EMPTY_STRING;
			return this._checkSymbolMask(symbol, maskChar) || this.specialCharacters.includes(maskChar) && symbol === maskChar;
		});
		if (compare.join(MaskExpression.EMPTY_STRING) === res) return compare.join(MaskExpression.EMPTY_STRING);
		return res;
	}
	shiftTypedSymbols(inputValue) {
		let symbolToReplace = "";
		return (inputValue && inputValue.split(MaskExpression.EMPTY_STRING).map((currSymbol, index) => {
			if (this.specialCharacters.includes(inputValue[index + 1] ?? MaskExpression.EMPTY_STRING) && inputValue[index + 1] !== this.maskExpression[index + 1]) {
				symbolToReplace = currSymbol;
				return inputValue[index + 1];
			}
			if (symbolToReplace.length) {
				const replaceSymbol = symbolToReplace;
				symbolToReplace = MaskExpression.EMPTY_STRING;
				return replaceSymbol;
			}
			return currSymbol;
		}) || []).join(MaskExpression.EMPTY_STRING);
	}
	numberToString(value) {
		if (!value && value !== 0 || this.maskExpression.startsWith(MaskExpression.SEPARATOR) && (this.leadZero || !this.dropSpecialCharacters) || this.maskExpression.startsWith(MaskExpression.SEPARATOR) && this.separatorLimit.length > 14 && String(value).length > 14) return String(value);
		return this._toPlainDecimalString(Number(value));
	}
	_toPlainDecimalString(value) {
		const stringValue = String(value);
		const match = /^(-?)(\d+)(?:\.(\d+))?[eE]([+-]?\d+)$/.exec(stringValue);
		if (!match) return stringValue;
		const [, sign, integerPart, fractionPart = "", exponentPart] = match;
		const exponent = Number(exponentPart);
		const digits = `${integerPart}${fractionPart}`;
		const pointIndex = integerPart.length + exponent;
		if (pointIndex <= 0) return `${sign}0.${"0".repeat(-pointIndex)}${digits}`;
		if (pointIndex >= digits.length) return `${sign}${digits}${"0".repeat(pointIndex - digits.length)}`;
		return `${sign}${digits.slice(0, pointIndex)}.${digits.slice(pointIndex)}`;
	}
	showMaskInInput(inputVal) {
		if (this.showMaskTyped && !!this.shownMaskExpression) {
			if (this.maskExpression.length !== this.shownMaskExpression.length) throw new Error("Mask expression must match mask placeholder length");
			else return this.shownMaskExpression;
		} else if (this.showMaskTyped) {
			if (inputVal) {
				if (this.maskExpression === MaskExpression.IP) return this._checkForIp(inputVal);
				if (this.maskExpression === MaskExpression.CPF_CNPJ || this.maskExpression === MaskExpression.CPF_CNPJ_ALPHA) return this._checkForCpfCnpj(inputVal);
			}
			if (this.placeHolderCharacter.length === this.maskExpression.length) return this.placeHolderCharacter;
			return this.maskExpression.replace(/\w/g, this.placeHolderCharacter);
		}
		return "";
	}
	clearIfNotMatchFn() {
		const formElement = this._elementRef?.nativeElement;
		if (!formElement) return;
		if (this.clearIfNotMatch && this.prefix.length + this.maskExpression.length + this.suffix.length !== formElement.value.replace(this.placeHolderCharacter, MaskExpression.EMPTY_STRING).length) {
			this.formElementProperty = ["value", MaskExpression.EMPTY_STRING];
			this.applyMask("", this.maskExpression);
		}
	}
	set formElementProperty([name, value]) {
		if (!this._renderer || !this._elementRef) return;
		queueMicrotask(() => {
			const element = this._elementRef?.nativeElement;
			if (element && Reflect.get(element, name) !== value) this._renderer?.setProperty(element, name, value);
		});
	}
	checkDropSpecialCharAmount(mask) {
		return mask.split(MaskExpression.EMPTY_STRING).filter((item) => this._findDropSpecialChar(item)).length;
	}
	_clearMaskChangedUnlessTriggered() {
		if (!this.triggerOnMaskChange) this.maskChanged = false;
	}
	removeMask(inputValue) {
		return this._removeMask(this._removeSuffix(this._removePrefix(inputValue)), this.specialCharacters.concat("_").concat(this.placeHolderCharacter));
	}
	_checkForIp(inputVal) {
		if (inputVal === MaskExpression.HASH) return `${this.placeHolderCharacter}.${this.placeHolderCharacter}.${this.placeHolderCharacter}.${this.placeHolderCharacter}`;
		const arr = digitsOf(inputVal);
		if (arr.length <= 3) return `${this.placeHolderCharacter}.${this.placeHolderCharacter}.${this.placeHolderCharacter}`;
		if (arr.length > 3 && arr.length <= 6) return `${this.placeHolderCharacter}.${this.placeHolderCharacter}`;
		if (arr.length > 6 && arr.length <= 9) return this.placeHolderCharacter;
		if (arr.length > 9 && arr.length <= 12) return "";
		return "";
	}
	_checkForCpfCnpj(inputVal) {
		const cpf = `${this.placeHolderCharacter}${this.placeHolderCharacter}${this.placeHolderCharacter}.${this.placeHolderCharacter}${this.placeHolderCharacter}${this.placeHolderCharacter}.${this.placeHolderCharacter}${this.placeHolderCharacter}${this.placeHolderCharacter}-${this.placeHolderCharacter}${this.placeHolderCharacter}`;
		const cnpj = `${this.placeHolderCharacter}${this.placeHolderCharacter}.${this.placeHolderCharacter}${this.placeHolderCharacter}${this.placeHolderCharacter}.${this.placeHolderCharacter}${this.placeHolderCharacter}${this.placeHolderCharacter}/${this.placeHolderCharacter}${this.placeHolderCharacter}${this.placeHolderCharacter}${this.placeHolderCharacter}-${this.placeHolderCharacter}${this.placeHolderCharacter}`;
		if (inputVal === MaskExpression.HASH) return cpf;
		const isCpfCnpjAlpha = this.maskExpression === MaskExpression.CPF_CNPJ_ALPHA;
		const hasAnyLetter = /[a-zA-Z]/.test(inputVal);
		const arr = this._countCpfCnpjTypedChars(inputVal, isCpfCnpjAlpha);
		if (isCpfCnpjAlpha && hasAnyLetter) {
			if (arr.length <= 2) return cnpj.slice(arr.length, cnpj.length);
			if (arr.length > 2 && arr.length <= 5) return cnpj.slice(arr.length + 1, cnpj.length);
			if (arr.length > 5 && arr.length <= 8) return cnpj.slice(arr.length + 2, cnpj.length);
			if (arr.length > 8 && arr.length <= 12) return cnpj.slice(arr.length + 3, cnpj.length);
			return cnpj.slice(arr.length + 4, cnpj.length);
		} else {
			if (arr.length <= 3) return cpf.slice(arr.length, cpf.length);
			if (arr.length > 3 && arr.length <= 6) return cpf.slice(arr.length + 1, cpf.length);
			if (arr.length > 6 && arr.length <= 9) return cpf.slice(arr.length + 2, cpf.length);
			if (arr.length > 9 && arr.length < 11) return cpf.slice(arr.length + 3, cpf.length);
		}
		if (arr.length === 11) return "";
		if (arr.length === 12) {
			if (inputVal.length === 17) return cnpj.slice(16, cnpj.length);
			return cnpj.slice(15, cnpj.length);
		}
		if (arr.length > 12 && arr.length <= 14) return cnpj.slice(arr.length + 4, cnpj.length);
		return "";
	}
	_countCpfCnpjTypedChars(inputVal, isCpfCnpjAlpha) {
		return isCpfCnpjAlpha ? inputVal.match(/[a-zA-Z0-9]/g) ?? [] : digitsOf(inputVal);
	}
	_getActiveElement(document = this.document) {
		const shadowRootEl = document?.activeElement?.shadowRoot;
		if (!shadowRootEl?.activeElement) return document.activeElement;
		else return this._getActiveElement(shadowRootEl);
	}
	formControlResult(inputValue) {
		const outputTransformFn = this.outputTransformFn ? this.outputTransformFn : (v) => v;
		this.writingValue = false;
		this.maskChanged = false;
		if (!this.isInitialized && this._emitValue) return;
		if (this.showMaskTyped && this.placeHolderCharacter.length === 1 && this.specialCharacters.indexOf(this.placeHolderCharacter) === -1) inputValue = inputValue.split(this.placeHolderCharacter).join(MaskExpression.EMPTY_STRING);
		const keepSpecialCharacters = this.maskExpression === MaskExpression.EMAIL_MASK;
		if (Array.isArray(this.dropSpecialCharacters) && !keepSpecialCharacters) this.onChange(outputTransformFn(this._toNumber(this._checkSymbols(this._removeMask(this._removeSuffix(this._removePrefix(inputValue)), this.dropSpecialCharacters)))));
		else if (!keepSpecialCharacters && (this.dropSpecialCharacters || !this.dropSpecialCharacters && this.prefix === inputValue)) this.onChange(outputTransformFn(this._toNumber(this._checkSymbols(this._removeSuffix(this._removePrefix(inputValue))))));
		else this.onChange(outputTransformFn(this._toNumber(inputValue)));
	}
	_toNumber(value) {
		if (!this.isNumberValue || value === MaskExpression.EMPTY_STRING) return value;
		if (this.maskExpression.startsWith(MaskExpression.SEPARATOR) && (this.leadZero || !this.dropSpecialCharacters)) return value;
		if (String(value).length > 14 && this.maskExpression.startsWith(MaskExpression.SEPARATOR)) return String(value);
		const num = Number(value);
		if (this.maskExpression.startsWith(MaskExpression.SEPARATOR) && Number.isNaN(num)) {
			const val = String(value).replace(",", ".");
			return Number(val);
		}
		return Number.isNaN(num) ? value : num;
	}
	_removeMask(value, specialCharactersForRemove) {
		if (this.maskExpression.startsWith(MaskExpression.PERCENT) && (value.includes(MaskExpression.DOT) || Array.isArray(this.decimalMarker) && value.includes(MaskExpression.COMMA) && this._activeDecimalMarker(value) === MaskExpression.COMMA)) return value;
		return value ? value.replace(this._regExpForRemove(specialCharactersForRemove), MaskExpression.EMPTY_STRING) : value;
	}
	_removePrefix(value) {
		if (!this.prefix) return value;
		return value ? value.replace(this.prefix, MaskExpression.EMPTY_STRING) : value;
	}
	_removeSuffix(value) {
		if (!this.suffix) return value;
		return value ? value.replace(this.suffix, MaskExpression.EMPTY_STRING) : value;
	}
	_retrieveSeparatorValue(result) {
		let specialCharacters = Array.isArray(this.dropSpecialCharacters) ? this.specialCharacters.filter((v) => {
			return this.dropSpecialCharacters.includes(v);
		}) : this.specialCharacters;
		if (!this.deletedSpecialCharacter && this._checkPatternForSpace() && result.includes(MaskExpression.WHITE_SPACE) && this.maskExpression.includes(MaskExpression.SYMBOL_STAR)) specialCharacters = specialCharacters.filter((char) => char !== MaskExpression.WHITE_SPACE);
		if (!Array.isArray(this.dropSpecialCharacters) && this.maskExpression.startsWith(MaskExpression.SEPARATOR) && this.thousandSeparator && !specialCharacters.includes(this.thousandSeparator)) specialCharacters = [...specialCharacters, this.thousandSeparator];
		return this._removeMask(result, specialCharacters);
	}
	_regExpForRemove(specialCharactersForRemove) {
		return new RegExp(specialCharactersForRemove.map((item) => escapeRegExp(item)).join("|"), "gi");
	}
	_replaceDecimalMarkerToDot(value) {
		const markers = Array.isArray(this.decimalMarker) ? this.decimalMarker : [this.decimalMarker];
		return value.replace(this._regExpForRemove(markers), MaskExpression.DOT);
	}
	_checkSymbols(result) {
		let processedResult = result;
		if (processedResult === MaskExpression.EMPTY_STRING) return processedResult;
		if (this.maskExpression.startsWith(MaskExpression.PERCENT) && this._activeDecimalMarker(processedResult) === MaskExpression.COMMA) processedResult = processedResult.replace(MaskExpression.COMMA, MaskExpression.DOT);
		const separatorPrecision = this._retrieveSeparatorPrecision(this.maskExpression);
		const separatorValue = this.specialCharacters.length === 0 ? this._retrieveSeparatorValue(processedResult) : this._replaceDecimalMarkerToDot(this._retrieveSeparatorValue(processedResult));
		if (!this.isNumberValue) return separatorValue;
		if (separatorPrecision) {
			if (processedResult === this.decimalMarker) return null;
			if (separatorValue.length > 14) return String(separatorValue);
			return this._checkPrecision(this.maskExpression, separatorValue);
		} else return separatorValue;
	}
	_checkPatternForSpace() {
		for (const key in this.patterns) if (this.patterns[key] && this.patterns[key]?.hasOwnProperty("pattern")) {
			const patternString = this.patterns[key]?.pattern.toString();
			const pattern = this.patterns[key]?.pattern;
			if (patternString?.includes(MaskExpression.WHITE_SPACE) && pattern && this._testPattern(pattern, this.maskExpression)) return true;
		}
		return false;
	}
	_retrieveSeparatorPrecision(maskExpression) {
		const matcher = maskExpression.match(new RegExp(`^separator\\.([^d]*)`));
		return matcher ? Number(matcher[1]) : null;
	}
	_checkPrecision(separatorExpression, separatorValue) {
		const separatorPrecision = this.getPrecision(separatorExpression);
		let value = separatorValue;
		if (separatorExpression.indexOf("2") > 0 && !this._isFocused() || this.leadZero && !this._isFocused() && Number(separatorPrecision) > 0 && Number.isFinite(separatorPrecision)) {
			if (this.leadZero && usesCommaDecimal(value, this.decimalMarker, this.thousandSeparator)) value = value.replace(MaskExpression.COMMA, MaskExpression.DOT);
			if (Number.isNaN(Number(value))) return separatorValue;
			const precision = this.leadZero ? Number(separatorPrecision) : 2;
			if (this._exceedsDoublePrecision(value)) return this._stringToFixed(value, precision);
			return Number(value).toFixed(precision);
		}
		return this.numberToString(value);
	}
	_exceedsDoublePrecision(value) {
		if (!/^-?\d+(\.\d+)?$/.test(value)) return false;
		return value.replace(/\D/g, "").replace(/^0+/, "").length > 15;
	}
	_stringToFixed(value, precision) {
		const isNegative = value.startsWith(MaskExpression.MINUS);
		const [integerPart = "0", fractionPart = ""] = (isNegative ? value.slice(1) : value).split(MaskExpression.DOT);
		const paddedFraction = fractionPart.padEnd(precision + 1, "0");
		const keptFraction = paddedFraction.slice(0, precision);
		const shouldRoundUp = (paddedFraction.charCodeAt(precision) || 0) >= 53;
		let scaled = BigInt(integerPart + keptFraction);
		if (shouldRoundUp) scaled += 1n;
		const digits = scaled.toString().padStart(precision + 1, "0");
		const sign = isNegative && scaled > 0n ? MaskExpression.MINUS : "";
		return precision > 0 ? `${sign}${digits.slice(0, -precision)}.${digits.slice(-precision)}` : `${sign}${digits}`;
	}
	_repeatPatternSymbols(maskExp) {
		let start = 0;
		return maskExp.match(/{[0-9]+}/) && maskExp.split(MaskExpression.EMPTY_STRING).reduce((accum, currVal, index) => {
			start = currVal === MaskExpression.CURLY_BRACKETS_LEFT ? index : start;
			if (currVal !== MaskExpression.CURLY_BRACKETS_RIGHT) return this._findSpecialChar(currVal) ? accum + currVal : accum;
			const repeatNumber = Number(maskExp.slice(start + 1, index));
			const replaceWith = new Array(repeatNumber + 1).join(maskExp[start - 1]);
			if (maskExp.slice(0, start).length > 1 && maskExp.includes(MaskExpression.LETTER_S)) {
				const symbols = maskExp.slice(0, start - 1);
				return symbols.includes(MaskExpression.CURLY_BRACKETS_LEFT) ? accum + replaceWith : symbols + accum + replaceWith;
			} else return accum + replaceWith;
		}, "") || maskExp;
	}
	currentLocaleDecimalMarker() {
		return MaskExpression.DOT;
	}
	static ɵfac = i0.ɵɵngDeclareFactory({
		minVersion: "12.0.0",
		version: "22.2.3",
		ngImport: i0,
		type: NgxMaskService,
		deps: null,
		target: i0.ɵɵFactoryTarget.Injectable
	});
	static ɵprov = i0.ɵɵngDeclareInjectable({
		minVersion: "12.0.0",
		version: "22.2.3",
		ngImport: i0,
		type: NgxMaskService
	});
};
i0.ɵɵngDeclareClassMetadata({
	minVersion: "12.0.0",
	version: "22.2.3",
	ngImport: i0,
	type: NgxMaskService,
	decorators: [{ type: Injectable }]
});
function _configFactory() {
	const initConfig = inject(INITIAL_CONFIG);
	const configValue = inject(NEW_CONFIG);
	return configValue instanceof Function ? {
		...initConfig,
		...configValue()
	} : {
		...initConfig,
		...configValue
	};
}
function provideNgxMask(configValue) {
	return [
		{
			provide: NEW_CONFIG,
			useValue: configValue
		},
		{
			provide: INITIAL_CONFIG,
			useValue: initialConfig
		},
		{
			provide: NGX_MASK_CONFIG,
			useFactory: _configFactory
		},
		NgxMaskService
	];
}
function provideEnvironmentNgxMask(configValue) {
	return makeEnvironmentProviders(provideNgxMask(configValue));
}
function resolveKeepCharacterPositions(svc, edit) {
	const { prefix, suffix, showMaskTyped, maskExpression, placeHolderCharacter, specialCharacters, selStart: selStartRaw, selEnd: selEndRaw } = svc;
	const { elValue } = edit;
	let position = edit.position;
	let actualValue = null;
	const inputSymbol = elValue.slice(position - 1, position);
	const prefixLength = prefix.length;
	const maskSkeleton = svc.maskIsShown.length ? svc.maskIsShown : maskExpression.replace(/\w/g, placeHolderCharacter);
	const hasSelection = selStartRaw !== selEndRaw;
	const selStartAbs = Number(selStartRaw);
	const selEndAbs = Number(selEndRaw);
	const selStart = selStartAbs - prefixLength;
	const selEnd = selEndAbs - prefixLength;
	const restoreBefore = (preEditLength) => svc.actualValue && edit.before.length === preEditLength && edit.before.startsWith(elValue.slice(0, selStartAbs)) ? edit.before : null;
	const maskEndOf = (preEditLength) => preEditLength - suffix.length;
	const blankEndOf = (preEditLength) => Math.max(Math.min(selEndAbs, maskEndOf(preEditLength)) - prefixLength, 0);
	const backspaceOrDelete = edit.code === MaskExpression.BACKSPACE || edit.code === MaskExpression.DELETE;
	let handled = true;
	let trimmedBodyEnd = null;
	if (backspaceOrDelete) {
		if (hasSelection) {
			const preEditLength = elValue.length + (selEndAbs - selStartAbs);
			const maskEndAbs = maskEndOf(preEditLength);
			const blankEnd = blankEndOf(preEditLength);
			const displayBefore = restoreBefore(preEditLength) ?? svc.actualValue;
			if (!showMaskTyped && selStartAbs <= prefixLength && selEndAbs >= preEditLength) handled = false;
			else if (selStartRaw === prefixLength) {
				const rest = selEndAbs > maskEndAbs ? suffix : elValue.split(prefix).join("");
				actualValue = `${prefix}${maskSkeleton.slice(0, blankEnd)}${rest}`;
			} else if (selStartRaw === maskSkeleton.length + prefixLength) actualValue = `${elValue}${maskSkeleton.slice(selStart, selEnd)}`;
			else actualValue = `${prefix}${elValue.split(prefix).join("").slice(0, selStart)}${maskSkeleton.slice(selStart, blankEnd)}${displayBefore.slice(selEndAbs, maskEndAbs)}${suffix}`;
			if (!showMaskTyped && actualValue !== null && selEndAbs >= maskEndAbs) {
				const bodyEnd = actualValue.endsWith(suffix) ? actualValue.length - suffix.length : actualValue.length;
				let end = bodyEnd;
				while (end > prefixLength && (actualValue.charAt(end - 1) === placeHolderCharacter || specialCharacters.includes(actualValue.charAt(end - 1)))) end--;
				actualValue = `${actualValue.slice(0, end)}${actualValue.slice(bodyEnd)}`;
				trimmedBodyEnd = end;
			}
		} else if (!specialCharacters.includes(maskExpression.slice(position - prefixLength, position + 1 - prefixLength))) {
			if (!showMaskTyped && position >= elValue.length) handled = false;
			else if (selStart === 1 && prefix) {
				actualValue = `${prefix}${placeHolderCharacter}${elValue.split(prefix).join("").split(suffix).join("")}${suffix}`;
				position = position - 1;
			} else actualValue = `${elValue.substring(0, position)}${placeHolderCharacter}${elValue.substring(position)}`;
		}
		position = edit.code === MaskExpression.DELETE && !hasSelection ? position + 1 : position;
		if (trimmedBodyEnd !== null && suffix) position = Math.min(position, trimmedBodyEnd);
	} else if (hasSelection) {
		const preEditLength = elValue.length - 1 + (selEndAbs - selStartAbs);
		const typedSymbol = elValue.charAt(selStartAbs);
		if (!showMaskTyped && selStartAbs <= prefixLength && selEndAbs >= preEditLength) handled = false;
		else {
			const maskIdx = nextFillableIndex(maskExpression, specialCharacters, Math.max(selStart, 0));
			const head = selStartAbs < prefixLength ? prefix : elValue.slice(0, selStartAbs);
			const maskEndAbs = maskEndOf(preEditLength);
			const prefixLeft = Math.max(prefixLength - selEndAbs, 0);
			const tail = selEndAbs > maskEndAbs ? suffix : elValue.slice(selStartAbs + 1 + prefixLeft);
			const blankEnd = blankEndOf(preEditLength);
			const blanked = `${head}${maskSkeleton.slice(Math.max(selStart, 0), blankEnd)}${tail}`;
			const targetAbs = maskIdx + prefixLength;
			if (targetAbs < blanked.length - suffix.length && svc._checkSymbolMask(typedSymbol, maskExpression[maskIdx] ?? MaskExpression.EMPTY_STRING)) {
				actualValue = `${blanked.slice(0, targetAbs)}${typedSymbol}${blanked.slice(targetAbs + 1)}`;
				position = targetAbs + 1;
			} else {
				actualValue = restoreBefore(preEditLength) ?? blanked;
				position = Math.max(selStartAbs, prefixLength);
			}
		}
	} else {
		const oldDisplay = `${elValue.slice(0, position - 1)}${elValue.slice(position)}`;
		const oldDisplayNoSuffix = suffix ? oldDisplay.split(suffix).join("") : oldDisplay;
		if (position - 1 - prefixLength < 0) {
			actualValue = restoreBefore(elValue.length - 1);
			position = position - 1;
		} else {
			const maskIdx = nextFillableIndex(maskExpression, specialCharacters, position - 1 - prefixLength);
			const targetAbs = maskIdx + prefixLength;
			if (targetAbs >= oldDisplayNoSuffix.length) {
				if (oldDisplayNoSuffix.length <= prefixLength || !showMaskTyped) handled = false;
				else {
					actualValue = restoreBefore(elValue.length - 1);
					position = position - 1;
				}
			} else if (svc._checkSymbolMask(inputSymbol, maskExpression[maskIdx] ?? MaskExpression.EMPTY_STRING)) {
				actualValue = `${oldDisplayNoSuffix.slice(0, targetAbs)}${inputSymbol}${oldDisplayNoSuffix.slice(targetAbs + 1)}${suffix}`;
				position = targetAbs + 1;
			} else {
				actualValue = restoreBefore(elValue.length - 1);
				position = position - 1;
			}
		}
	}
	return {
		actualValue,
		position,
		handled
	};
}
const notFilled = (errors) => ({
	errors,
	filled: false
});
const suffixStart = (display, suffix) => suffix && display.endsWith(suffix) ? display.length - suffix.length : Infinity;
const MIRRORED_INPUTS = [
	"instantPrefix",
	"prefix",
	"suffix",
	"decimalMarker",
	"dropSpecialCharacters",
	"shownMaskExpression",
	"clearIfNotMatch",
	"validation",
	"separatorLimit",
	"typeFromDecimals",
	"leadZeroDateTime",
	"leadZero",
	"triggerOnMaskChange",
	"inputTransformFn",
	"outputTransformFn",
	"keepCharacterPositions"
];
var NgxMaskDirective = class NgxMaskDirective {
	mask = input("", ...ngDevMode ? [{ debugName: "mask" }] : /* istanbul ignore next */ []);
	specialCharacters = input([], ...ngDevMode ? [{ debugName: "specialCharacters" }] : /* istanbul ignore next */ []);
	patterns = input({}, ...ngDevMode ? [{ debugName: "patterns" }] : /* istanbul ignore next */ []);
	prefix = input("", ...ngDevMode ? [{ debugName: "prefix" }] : /* istanbul ignore next */ []);
	suffix = input("", ...ngDevMode ? [{ debugName: "suffix" }] : /* istanbul ignore next */ []);
	thousandSeparator = input(" ", ...ngDevMode ? [{ debugName: "thousandSeparator" }] : /* istanbul ignore next */ []);
	decimalMarker = input(".", ...ngDevMode ? [{ debugName: "decimalMarker" }] : /* istanbul ignore next */ []);
	dropSpecialCharacters = input(null, ...ngDevMode ? [{ debugName: "dropSpecialCharacters" }] : /* istanbul ignore next */ []);
	hiddenInput = input(null, ...ngDevMode ? [{ debugName: "hiddenInput" }] : /* istanbul ignore next */ []);
	showMaskTyped = input(null, ...ngDevMode ? [{ debugName: "showMaskTyped" }] : /* istanbul ignore next */ []);
	placeHolderCharacter = input(null, ...ngDevMode ? [{ debugName: "placeHolderCharacter" }] : /* istanbul ignore next */ []);
	shownMaskExpression = input(null, ...ngDevMode ? [{ debugName: "shownMaskExpression" }] : /* istanbul ignore next */ []);
	clearIfNotMatch = input(null, ...ngDevMode ? [{ debugName: "clearIfNotMatch" }] : /* istanbul ignore next */ []);
	validation = input(null, ...ngDevMode ? [{ debugName: "validation" }] : /* istanbul ignore next */ []);
	separatorLimit = input("", ...ngDevMode ? [{ debugName: "separatorLimit" }] : /* istanbul ignore next */ []);
	typeFromDecimals = input(null, ...ngDevMode ? [{ debugName: "typeFromDecimals" }] : /* istanbul ignore next */ []);
	allowNegativeNumbers = input(null, ...ngDevMode ? [{ debugName: "allowNegativeNumbers" }] : /* istanbul ignore next */ []);
	leadZeroDateTime = input(null, ...ngDevMode ? [{ debugName: "leadZeroDateTime" }] : /* istanbul ignore next */ []);
	leadZero = input(null, ...ngDevMode ? [{ debugName: "leadZero" }] : /* istanbul ignore next */ []);
	triggerOnMaskChange = input(null, ...ngDevMode ? [{ debugName: "triggerOnMaskChange" }] : /* istanbul ignore next */ []);
	apm = input(null, ...ngDevMode ? [{ debugName: "apm" }] : /* istanbul ignore next */ []);
	inputTransformFn = input(null, ...ngDevMode ? [{ debugName: "inputTransformFn" }] : /* istanbul ignore next */ []);
	outputTransformFn = input(null, ...ngDevMode ? [{ debugName: "outputTransformFn" }] : /* istanbul ignore next */ []);
	keepCharacterPositions = input(null, ...ngDevMode ? [{ debugName: "keepCharacterPositions" }] : /* istanbul ignore next */ []);
	instantPrefix = input(null, ...ngDevMode ? [{ debugName: "instantPrefix" }] : /* istanbul ignore next */ []);
	defaultValueOnBlur = input(null, ...ngDevMode ? [{ debugName: "defaultValueOnBlur" }] : /* istanbul ignore next */ []);
	value = model("", ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
	disabled = input(false, {
		...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
		transform: booleanAttribute
	});
	touched = model(false, ...ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []);
	maskFilled = output();
	_maskValue = signal("", ...ngDevMode ? [{ debugName: "_maskValue" }] : /* istanbul ignore next */ []);
	_inputValue = signal("", ...ngDevMode ? [{ debugName: "_inputValue" }] : /* istanbul ignore next */ []);
	_code = signal("", ...ngDevMode ? [{ debugName: "_code" }] : /* istanbul ignore next */ []);
	_maskExpressionArray = signal([], ...ngDevMode ? [{ debugName: "_maskExpressionArray" }] : /* istanbul ignore next */ []);
	_justPasted = signal(false, ...ngDevMode ? [{ debugName: "_justPasted" }] : /* istanbul ignore next */ []);
	_isComposing = signal(false, ...ngDevMode ? [{ debugName: "_isComposing" }] : /* istanbul ignore next */ []);
	_isCvaMode = signal(false, ...ngDevMode ? [{ debugName: "_isCvaMode" }] : /* istanbul ignore next */ []);
	_skipNextValueEffect = signal(false, ...ngDevMode ? [{ debugName: "_skipNextValueEffect" }] : /* istanbul ignore next */ []);
	_lastPropagatedValue = null;
	_writtenValue = null;
	_writeSequence = 0;
	_programmaticWrite = false;
	_valuePropagatedByEdit = null;
	_configApplied = false;
	_pendingInitialValue;
	_hasPendingInitialValue = false;
	_disabledEverSet = false;
	_warnedAboutMultiCharPlaceholder = false;
	_maskService = inject(NgxMaskService, { self: true });
	_config = inject(NGX_MASK_CONFIG);
	_boundConfig = {
		specialCharacters: this._config.specialCharacters,
		decimalMarker: this._config.decimalMarker
	};
	_changeDetectorRef = inject(ChangeDetectorRef);
	_elementRef = inject(ElementRef);
	_renderer = inject(Renderer2);
	_injector = inject(Injector);
	_ngZone = inject(NgZone);
	_ngControl;
	_resolveNgControl() {
		if (typeof this._ngControl === "undefined") this._ngControl = this._injector.get(NgControl, null);
		return this._ngControl;
	}
	onChange = (_) => {};
	onTouch = () => {};
	_onValidatorChange = () => {};
	constructor() {
		this._maskService.onChange = this.onChange = (value) => {
			this._propagateToValueModel(value);
		};
		effect(() => {
			const signalValue = this.value();
			untracked(() => {
				if (this._valueEffectWillWrite(signalValue)) this.writeValue(signalValue);
				else this._skipNextValueEffect.set(false);
			});
		});
		effect(() => {
			const isDisabled = this.disabled();
			untracked(() => {
				if (!isDisabled && !this._disabledEverSet) return;
				this._disabledEverSet = true;
				this.setDisabledState(isDisabled);
			});
		});
	}
	ngOnChanges(changes) {
		const { mask, specialCharacters, patterns, prefix, suffix, thousandSeparator, decimalMarker, dropSpecialCharacters, hiddenInput, showMaskTyped, placeHolderCharacter, clearIfNotMatch, validation, allowNegativeNumbers, apm } = changes;
		const previousSeparators = {
			thousandSeparator: this._maskService.thousandSeparator,
			decimalMarker: this._maskService.decimalMarker,
			prefix: this._maskService.prefix,
			suffix: this._maskService.suffix
		};
		if (mask) {
			if (mask.currentValue !== mask.previousValue && !mask.firstChange) this._maskService.maskChanged = true;
			const resolvedMask = this._resolvedMaskInput();
			const maskParts = resolvedMask.split(MaskExpression.OR);
			if (maskParts.length > 1) {
				this._maskExpressionArray.set(maskParts.sort((a, b) => a.length - b.length));
				this._setMask();
			} else {
				this._maskExpressionArray.set([]);
				this._maskValue.set(resolvedMask);
				this._maskService.maskExpression = this._maskValue();
			}
		}
		if (specialCharacters) {
			if (Array.isArray(specialCharacters.currentValue)) {
				this._boundConfig.specialCharacters = specialCharacters.currentValue;
				this._maskService.specialCharacters = specialCharacters.currentValue;
			}
		}
		if (allowNegativeNumbers) {
			this._maskService.allowNegativeNumbers = allowNegativeNumbers.currentValue;
			this._keepMinusOutOfSpecialCharacters();
		}
		if (patterns && patterns.currentValue) this._maskService.patterns = patterns.currentValue;
		if (apm) this._maskService.apm = apm.currentValue ?? this._config.apm;
		if (decimalMarker) this._boundConfig.decimalMarker = decimalMarker.currentValue;
		if (thousandSeparator) {
			this._maskService.thousandSeparator = thousandSeparator.currentValue;
			if (thousandSeparator.previousValue && thousandSeparator.currentValue) {
				this._maskService.decimalMarker = this._boundConfig.decimalMarker;
				if (thousandSeparator.currentValue === this._maskService.decimalMarker) this._maskService.decimalMarker = thousandSeparator.currentValue === MaskExpression.COMMA ? MaskExpression.DOT : MaskExpression.COMMA;
				this._maskService.writingValue = true;
			}
		}
		if (hiddenInput) {
			this._maskService.hiddenInput = hiddenInput.currentValue;
			if (hiddenInput.previousValue === true && hiddenInput.currentValue === false) this._inputValue.set(this._maskService.actualValue);
		}
		if (showMaskTyped) {
			this._maskService.showMaskTyped = showMaskTyped.currentValue;
			if (showMaskTyped.previousValue === false && showMaskTyped.currentValue === true && this._maskService._isFocused()) afterNextRender(() => {
				queueMicrotask(() => this._ngZone.run(() => {
					this._maskService._elementRef?.nativeElement.click();
				}));
			}, { injector: this._injector });
		}
		if (placeHolderCharacter) {
			this._maskService.placeHolderCharacter = placeHolderCharacter.currentValue ?? this._config.placeHolderCharacter;
			if (typeof placeHolderCharacter.currentValue === "string" && placeHolderCharacter.currentValue.length > 1 && !this._warnedAboutMultiCharPlaceholder) {
				this._warnedAboutMultiCharPlaceholder = true;
				console.warn("Ngx-mask: placeHolderCharacter should be a single character; behavior with multi-character values is undefined (e.g. keepCharacterPositions will not work). Current value:", placeHolderCharacter.currentValue);
			}
		}
		const specialCharactersSources = [
			mask,
			specialCharacters,
			allowNegativeNumbers,
			thousandSeparator,
			decimalMarker,
			dropSpecialCharacters
		];
		if (this._maskValue() && specialCharactersSources.some((change) => change && !change.firstChange)) {
			this._maskService.specialCharacters = this._boundConfig.specialCharacters;
			this._keepMinusOutOfSpecialCharacters();
		}
		for (const key of MIRRORED_INPUTS) {
			const change = changes[key];
			if (change) this._mirrorInput(key, change.currentValue);
		}
		const retargetSeparators = (thousandSeparator || decimalMarker) && this._configApplied && this._maskValue().startsWith(MaskExpression.SEPARATOR) && this._inputValue();
		if (retargetSeparators) {
			this._inputValue.set(retargetSeparatorValue(this._inputValue(), previousSeparators, this._maskService));
			this._maskService.actualValue = this._inputValue();
			this._maskService.writingValue = true;
			this._writeSequence++;
		}
		const valueChange = changes["value"];
		const valueEffectWillRender = !!valueChange && String(valueChange.currentValue) !== this._lastPropagatedValue && this._valueEffectWillWrite(valueChange.currentValue);
		if (retargetSeparators && !this._maskService.maskChanged) this._writeProgrammatically(() => this._applyMask(!valueEffectWillRender));
		else this._applyMask(!valueEffectWillRender);
		if ([
			mask,
			validation,
			patterns,
			prefix,
			suffix,
			dropSpecialCharacters,
			specialCharacters,
			clearIfNotMatch
		].some((change) => change && !change.firstChange)) this._onValidatorChange();
		if (!this._configApplied) {
			this._configApplied = true;
			if (this._hasPendingInitialValue) {
				this._hasPendingInitialValue = false;
				const pendingValue = this._pendingInitialValue;
				this._pendingInitialValue = null;
				this.writeValue(pendingValue);
			}
		}
	}
	_keepMinusOutOfSpecialCharacters() {
		if (this._maskService.allowNegativeNumbers) this._maskService.specialCharacters = this._maskService.specialCharacters.filter((c) => c !== MaskExpression.MINUS);
	}
	validate({ value }) {
		return this._validateValue(value).errors;
	}
	_validateValue(value) {
		const processedValue = typeof value === "number" ? String(value) : value;
		const maskValue = this._maskValue();
		if (!this._maskService.validation || !maskValue) return notFilled(null);
		const isCpfCnpj = maskValue === MaskExpression.CPF_CNPJ || maskValue === MaskExpression.CPF_CNPJ_ALPHA;
		if (maskValue === MaskExpression.IP && this._maskService.ipError) return notFilled(this._createValidationError(processedValue));
		if (isCpfCnpj && this._maskService.cpfCnpjError) return notFilled(this._createValidationError(processedValue));
		if (maskValue.startsWith(MaskExpression.SEPARATOR)) return notFilled(null);
		if (withoutValidation.includes(maskValue)) return notFilled(null);
		if (this._maskService.clearIfNotMatch) return notFilled(null);
		if (timeMasks.includes(maskValue)) return notFilled(this._validateTime(processedValue));
		if (maskValue === MaskExpression.EMAIL_MASK) {
			if (!/^[^@]+@[^@]+\.[^@]+$/.test(processedValue) && processedValue) return notFilled(this._createValidationError(processedValue));
			else return notFilled(null);
		}
		if (processedValue && processedValue.length >= 1) {
			let counterOfOpt = 0;
			if (maskValue.includes(MaskExpression.CURLY_BRACKETS_LEFT) && maskValue.includes(MaskExpression.CURLY_BRACKETS_RIGHT)) {
				const lengthInsideCurlyBrackets = maskValue.slice(maskValue.indexOf(MaskExpression.CURLY_BRACKETS_LEFT) + 1, maskValue.indexOf(MaskExpression.CURLY_BRACKETS_RIGHT));
				return notFilled(lengthInsideCurlyBrackets === String(processedValue.length) ? null : this._createValidationError(processedValue));
			}
			if (maskValue.startsWith(MaskExpression.PERCENT)) return notFilled(null);
			for (const key in this._maskService.patterns) if (this._maskService.patterns[key]?.optional) {
				if (maskValue.indexOf(key) !== maskValue.lastIndexOf(key)) {
					const opt = maskValue.split(MaskExpression.EMPTY_STRING).filter((i) => i === key).join(MaskExpression.EMPTY_STRING);
					counterOfOpt += opt.length;
				} else if (maskValue.indexOf(key) !== -1) counterOfOpt++;
				const firstOptionalIndex = maskValue.indexOf(key);
				if (firstOptionalIndex !== -1 && processedValue.length >= firstOptionalIndex) {
					if (!maskValue.slice(firstOptionalIndex).split(MaskExpression.EMPTY_STRING).some((symbol) => !!this._maskService.patterns[symbol] && !this._maskService.patterns[symbol]?.optional)) return notFilled(null);
					if (!this._maskService.prefix && !this._maskService.suffix && this._isPlainTokenMask(maskValue)) return notFilled(this._matchesMaskWithOptionalSkip(processedValue, maskValue) ? null : this._createValidationError(processedValue));
				}
				if (counterOfOpt === maskValue.length) return notFilled(null);
			}
			if (maskValue.indexOf(MaskExpression.SYMBOL_STAR) > 1 && processedValue.length < maskValue.indexOf(MaskExpression.SYMBOL_STAR) || maskValue.indexOf(MaskExpression.SYMBOL_QUESTION) > 1 && processedValue.length < maskValue.indexOf(MaskExpression.SYMBOL_QUESTION)) return notFilled(this._createValidationError(processedValue));
			if (maskValue.indexOf(MaskExpression.SYMBOL_STAR) === -1 || maskValue.indexOf(MaskExpression.SYMBOL_QUESTION) === -1) {
				const array = maskValue.split("*");
				const length = this._maskService.dropSpecialCharacters ? maskValue.length - this._maskService.checkDropSpecialCharAmount(maskValue) - counterOfOpt : this._maskService.prefix ? maskValue.length + this._maskService.prefix.length - counterOfOpt : maskValue.length - counterOfOpt;
				if (array.length === 1) {
					if (processedValue.length < length) {
						if (this._isCompleteAlternativeBoundary(processedValue)) return notFilled(null);
						return notFilled(this._createValidationError(processedValue));
					}
				}
				if (array.length > 1) {
					const lastIndexArray = array[array.length - 1];
					if (lastIndexArray && this._maskService.specialCharacters.includes(lastIndexArray[0]) && String(processedValue).includes(lastIndexArray[0] ?? "") && !this._maskService.dropSpecialCharacters) {
						const special = processedValue.split(lastIndexArray[0]);
						return notFilled(special[special.length - 1]?.length === lastIndexArray.length - 1 ? null : this._createValidationError(processedValue));
					} else if ((lastIndexArray && !this._maskService.specialCharacters.includes(lastIndexArray[0]) || !lastIndexArray || this._maskService.dropSpecialCharacters) && processedValue.length >= length - 1) return notFilled(null);
					else return notFilled(this._createValidationError(processedValue));
				}
			}
			if (maskValue.indexOf(MaskExpression.SYMBOL_STAR) === 1 || maskValue.indexOf(MaskExpression.SYMBOL_QUESTION) === 1) return notFilled(null);
		}
		return {
			errors: null,
			filled: !!value
		};
	}
	onPaste() {
		this._justPasted.set(true);
	}
	onFocus() {
		this._maskService._isFocused.set(true);
	}
	onModelChange(value) {
		if ((value === MaskExpression.EMPTY_STRING || value === null || typeof value === "undefined") && this._maskService.actualValue) this._maskService.actualValue = this._maskService.getActualValue(MaskExpression.EMPTY_STRING);
	}
	onInput(e) {
		this._writeSequence++;
		this._valuePropagatedByEdit = null;
		this._processInput(e);
		const propagated = this._valuePropagatedByEdit;
		this._valuePropagatedByEdit = null;
		if (propagated !== null && this._validateValue(propagated).filled) this.maskFilled.emit();
	}
	_isBulkInsertion(e) {
		const { inputType, data } = e;
		return typeof inputType === "string" && inputType.startsWith("insert") && inputType !== "insertCompositionText" && typeof data === "string" && data.length > 1;
	}
	_editEndsValue(el) {
		return !this._maskService.removeMask(el.value.slice(el.selectionEnd ?? el.value.length));
	}
	_processInput(e) {
		this._maskService.isInitialized = true;
		const preEditValue = this._inputValue();
		const inputType = e.inputType;
		if (inputType === "deleteContentBackward") this._code.set(MaskExpression.BACKSPACE);
		else if (inputType === "deleteContentForward") this._code.set(MaskExpression.DELETE);
		else if (inputType && (this._code() === MaskExpression.BACKSPACE || this._code() === MaskExpression.DELETE)) this._code.set(inputType);
		if (this._isComposing() && this._maskAcceptsLetterInput()) return;
		const el = e.target;
		const transformedValue = this._maskService.inputTransformFn ? this._maskService.inputTransformFn(el.value) : el.value;
		if (el.type !== "number") {
			if (typeof transformedValue === "string" || typeof transformedValue === "number") {
				const transformedString = transformedValue.toString();
				if (el.value !== transformedString) el.value = transformedString;
				this._inputValue.set(el.value);
				this._setMask();
				if (!this._maskValue()) {
					this.onChange(el.value);
					return;
				}
				if (this._isBulkInsertion(e) && this._editEndsValue(el)) this._justPasted.set(true);
				const pastedValueWithoutPrefix = this._justPasted() && !!this._maskService.prefix && !el.value.startsWith(this._maskService.prefix);
				const caret = el.selectionStart;
				let position = el.selectionStart === 1 ? el.selectionStart + this._maskService.prefix.length : el.selectionStart;
				if (this._maskService.keepCharacterPositions && this._maskService.placeHolderCharacter.length === 1 && !this._justPasted()) {
					const kcp = resolveKeepCharacterPositions(this._maskService, {
						elValue: el.value,
						position,
						code: this._code(),
						before: preEditValue
					});
					if (kcp.actualValue !== null) this._maskService.actualValue = kcp.actualValue;
					position = kcp.position;
					this._maskService.keepCharacterPositionsHandled = kcp.handled;
				}
				if (!this._maskService.hiddenInput && !this._maskService.showMaskTyped && !this._maskService.keepCharacterPositions && this._maskService.selStart !== this._maskService.selEnd && containsStarSymbol(el.value, this._maskService.maskExpression, this._maskService.thousandSeparator)) this._maskService.actualValue = MaskExpression.EMPTY_STRING;
				let caretShift = 0;
				let backspaceShift = false;
				const isDeletion = this._code() === MaskExpression.BACKSPACE || this._code() === MaskExpression.DELETE;
				if (this._code() === MaskExpression.DELETE) this._maskService.deletedSpecialCharacter = true;
				const keepsFullDateOverwrite = this._justPasted() || this._maskService.prefix || this._maskService.suffix || this._maskService.keepCharacterPositions || this._maskService.hiddenInput;
				const overwrite = keepsFullDateOverwrite || isDeletion ? null : overwriteDateSlot(this._maskService, preEditValue, el.value, position);
				if (overwrite) {
					el.value = overwrite.value;
					this._inputValue.set(overwrite.value);
					position = overwrite.position;
				} else if (keepsFullDateOverwrite || !isDeletion) {
					const overwrittenDate = overwriteFullDateValue(this._maskService.maskExpression, this._inputValue(), position, this._code());
					if (overwrittenDate !== null) el.value = overwrittenDate;
				}
				if (this._maskService.leadZeroDateTime) {
					const removedChar = isDeletion ? preEditValue[caret] ?? MaskExpression.EMPTY_STRING : MaskExpression.EMPTY_STRING;
					setUserEdit(this._maskService, this._maskService.specialCharacters.includes(removedChar) ? null : {
						value: el.value,
						start: this._justPasted() ? 0 : caret - 1,
						end: this._justPasted() ? el.value.length : overwrite?.end ?? caret
					});
					position = leadZeroDateTimeCaret(this._maskService.maskExpression, position, el.value, this._inputValue(), !!this._maskService.apm);
				}
				this._maskService.applyValueChanges(position, this._justPasted(), isDeletion, (shift, _backspaceShift) => {
					this._justPasted.set(false);
					caretShift = shift;
					backspaceShift = _backspaceShift;
				});
				setUserEdit(this._maskService, null);
				if (this._maskService._getActiveElement() !== el) return;
				if (this._maskService.plusOnePosition) {
					position = position + 1;
					this._maskService.plusOnePosition = false;
				}
				if (this._maskExpressionArray().length) {
					if (this._code() === MaskExpression.BACKSPACE) {
						const specialChartMinusOne = this._maskService.specialCharacters.includes(this._maskService.actualValue.slice(position - 1, position));
						const allowFewMaskChangeMask = this._maskService.removeMask(this._inputValue())?.length === this._maskService.removeMask(this._maskService.maskExpression)?.length;
						const specialChartPlusOne = this._maskService.specialCharacters.includes(this._maskService.actualValue.slice(position, position + 1));
						if (allowFewMaskChangeMask && !specialChartPlusOne) position = el.selectionStart + 1;
						else position = specialChartMinusOne ? position - 1 : position;
					} else position = el.selectionStart === 1 ? el.selectionStart + this._maskService.prefix.length : el.selectionStart;
				}
				let positionToApply = position + (this._code() === MaskExpression.BACKSPACE && !backspaceShift ? 0 : caretShift);
				if (pastedValueWithoutPrefix && this._maskValue().startsWith(MaskExpression.SEPARATOR)) positionToApply += this._maskService.prefix.length;
				if (positionToApply > this._getActualInputLength()) {
					const decimalMarker = this._maskService.decimalMarker;
					const prefix = this._maskService.prefix;
					const valueWithoutPrefix = el.value.startsWith(prefix) ? el.value.slice(prefix.length) : el.value;
					positionToApply = valueWithoutPrefix.length === 1 && (Array.isArray(decimalMarker) ? decimalMarker.includes(valueWithoutPrefix) : valueWithoutPrefix === decimalMarker) ? this._getActualInputLength() + 1 : this._getActualInputLength();
				}
				if (positionToApply < 0) positionToApply = 0;
				if (el.selectionStart !== positionToApply || el.selectionEnd !== positionToApply) el.setSelectionRange(positionToApply, positionToApply);
			} else console.warn("Ngx-mask writeValue work with string | number, your current value:", typeof transformedValue);
		} else {
			if (!this._maskValue()) {
				this.onChange(el.value);
				return;
			}
			this._maskService.applyValueChanges(el.value.length, this._justPasted(), this._code() === MaskExpression.BACKSPACE || this._code() === MaskExpression.DELETE);
		}
	}
	_maskAcceptsLetterInput() {
		for (const symbol of this._maskService.maskExpression) if (this._maskService._checkSymbolMask("a", symbol) || this._maskService._checkSymbolMask("A", symbol)) return true;
		return false;
	}
	onCompositionStart() {
		this._isComposing.set(true);
	}
	onCompositionEnd(e) {
		this._isComposing.set(false);
		if (!this._maskAcceptsLetterInput()) return;
		this._justPasted.set(true);
		this.onInput(e);
	}
	onBlur(e) {
		if (this._maskValue()) {
			const el = e.target;
			if (this._applyDefaultValueOnBlur(el)) {
				this._writeProgrammatically(() => this._formatOnBlur(el));
				this._changeDetectorRef.markForCheck();
			} else this._formatOnBlur(el);
		}
		this._maskService._isFocused.set(false);
		this.onTouch();
	}
	_formatOnBlur(el) {
		if (this._maskService.leadZero && el.value.length > 0 && typeof this._maskService.decimalMarker === "string") {
			const maskExpression = this._maskService.maskExpression;
			const decimalMarker = this._maskService.decimalMarker;
			const suffix = this._maskService.suffix;
			const precision = Number(this._maskService.maskExpression.slice(maskExpression.length - 1, maskExpression.length));
			if (precision > 0) {
				const unsuffixedValue = suffix ? el.value.split(suffix).join("") : el.value;
				const decimalPart = unsuffixedValue.split(decimalMarker)[1];
				const paddedValue = unsuffixedValue.includes(decimalMarker) ? unsuffixedValue + MaskExpression.NUMBER_ZERO.repeat(precision - (decimalPart?.length || 0)) + suffix : unsuffixedValue + decimalMarker + MaskExpression.NUMBER_ZERO.repeat(precision) + suffix;
				if (paddedValue !== el.value) {
					el.value = paddedValue;
					this._maskService.actualValue = el.value;
					this._maskService.formControlResult(this._maskService.actualValue);
				}
			}
		}
		this._maskService.clearIfNotMatchFn();
	}
	_applyDefaultValueOnBlur(el) {
		const defaultValue = this.defaultValueOnBlur() ?? this._config.defaultValueOnBlur;
		if (!defaultValue || this._maskService.removeMask(el.value)) return false;
		const displayValue = this._writeProgrammatically(() => this._maskService.applyMask(defaultValue, this._maskService.maskExpression));
		el.value = displayValue;
		this._inputValue.set(displayValue);
		return true;
	}
	onClick(e) {
		if (!this._maskValue()) return;
		const el = e.target;
		if (el !== null && el.selectionStart !== null && el.selectionStart === el.selectionEnd && el.selectionStart > this._maskService.prefix.length) {
			if (this._maskService.showMaskTyped && !this._maskService.keepCharacterPositions) {
				this._maskService.maskIsShown = this._maskService.showMaskInInput();
				if (el.setSelectionRange && this._maskService.prefix + this._maskService.maskIsShown === el.value) {
					el.focus();
					el.setSelectionRange(0, 0);
				} else if (el.selectionStart > this._maskService.actualValue.length) el.setSelectionRange(this._maskService.actualValue.length, this._maskService.actualValue.length);
			}
		}
		const nextValue = el && (el.value === this._maskService.prefix ? this._maskService.prefix + this._maskService.maskIsShown : el.value);
		if (el && el.value !== nextValue) el.value = nextValue;
		if (el && el.type !== "number" && (el.selectionStart || el.selectionEnd) <= this._maskService.prefix.length) {
			const specialCharactersAtTheStart = this._maskService.maskExpression.match(new RegExp(`^[${this._maskService.specialCharacters.map((c) => escapeRegExp(c)).join("")}]+`))?.[0].length || 0;
			el.selectionStart = this._maskService.prefix.length + specialCharactersAtTheStart;
			return;
		}
		if (el && el.selectionEnd > this._getActualInputLength()) el.selectionEnd = this._getActualInputLength();
	}
	onKeyDown(event) {
		const e = event;
		if (!this._maskValue()) return;
		if (this._isComposing()) {
			if (e.key === "Enter") {
				this.onCompositionEnd(event);
				return;
			}
			const composingEl = e.target;
			this._inputValue.set(composingEl.value);
			this._maskService.selStart = composingEl.selectionStart;
			this._maskService.selEnd = composingEl.selectionEnd;
			return;
		}
		this._code.set(e.code ? e.code : e.key);
		const el = e.target;
		this._inputValue.set(el.value);
		this._setMask();
		const isTextarea = el.tagName.toLowerCase() === "textarea";
		if (el.type !== "number") {
			if (this._insertNumpadDecimalMarker(e, el)) return;
			if (e.key === MaskExpression.ARROW_UP && !isTextarea) e.preventDefault();
			if (e.key === MaskExpression.ARROW_LEFT || e.key === MaskExpression.BACKSPACE || e.key === MaskExpression.DELETE) {
				if (e.key === MaskExpression.BACKSPACE && el.value.length === 0) el.selectionStart = el.selectionEnd;
				if (e.key === MaskExpression.BACKSPACE && el.selectionStart !== 0) {
					const prefixLength = this._maskService.prefix.length;
					const specialCharacters = this._maskService.specialCharacters;
					if (prefixLength > 1 && el.selectionStart <= prefixLength) el.setSelectionRange(prefixLength, el.selectionEnd);
					else if (this._inputValue().length !== el.selectionStart && el.selectionStart !== 1) {
						const collapsedCaret = el.selectionStart === el.selectionEnd;
						const hopFrom = el.selectionStart;
						while (specialCharacters.includes((this._inputValue()[el.selectionStart - 1] ?? MaskExpression.EMPTY_STRING).toString()) && (prefixLength >= 1 && el.selectionStart > prefixLength || prefixLength === 0)) el.setSelectionRange(el.selectionStart - 1, el.selectionEnd);
						if (this._maskService.keepCharacterPositions && collapsedCaret && el.selectionStart !== hopFrom && el.selectionStart > prefixLength && hopFrom <= suffixStart(this._inputValue(), this._maskService.suffix)) el.setSelectionRange(el.selectionStart - 1, el.selectionEnd);
					}
				}
				const { prefix, suffix, maskExpression, specialCharacters } = this._maskService;
				const numberMask = maskExpression.startsWith(MaskExpression.SEPARATOR) || maskExpression.startsWith(MaskExpression.PERCENT);
				const deleteAtFirstSlot = e.key === MaskExpression.DELETE && el.selectionStart === el.selectionEnd && el.selectionStart === prefix.length && prefix.length > 1 && el.value.startsWith(prefix) && !numberMask && !isDateTimeMask(maskExpression) && !specialCharacters.includes(maskExpression.charAt(0));
				this.checkSelectionOnDeletion(el);
				if (prefix.length && !deleteAtFirstSlot && el.selectionStart <= prefix.length && el.selectionEnd <= prefix.length) e.preventDefault();
				if (e.key === MaskExpression.DELETE && suffix && !numberMask && el.selectionStart === el.selectionEnd && el.selectionStart >= suffixStart(this._inputValue(), this._maskService.suffix)) e.preventDefault();
				const cursorStart = el.selectionStart;
				if (e.key === MaskExpression.BACKSPACE && !el.readOnly && cursorStart === 0 && el.selectionEnd === el.value.length && el.value.length !== 0) {
					e.preventDefault();
					const transformedEmpty = this._maskService.inputTransformFn ? this._maskService.inputTransformFn(MaskExpression.EMPTY_STRING) : MaskExpression.EMPTY_STRING;
					const clearedValue = typeof transformedEmpty === "string" || typeof transformedEmpty === "number" ? String(transformedEmpty) : MaskExpression.EMPTY_STRING;
					const displayValue = this._maskService.applyMask(clearedValue, this._maskService.maskExpression, 0, false, true);
					el.value = displayValue;
					this._inputValue.set(displayValue);
					const caret = Math.min(this._maskService.prefix.length, displayValue.length);
					el.setSelectionRange(caret, caret);
				}
			}
			if (!!this._maskService.suffix && this._maskService.suffix.length > 1 && this._inputValue().length - this._maskService.suffix.length < el.selectionStart) el.setSelectionRange(this._inputValue().length - this._maskService.suffix.length, this._inputValue().length);
			else if (e.code === "KeyA" && e.ctrlKey || e.code === "KeyA" && e.metaKey) {
				el.setSelectionRange(0, this._getActualInputLength());
				e.preventDefault();
			}
			this._maskService.selStart = el.selectionStart;
			this._maskService.selEnd = el.selectionEnd;
		}
	}
	_insertNumpadDecimalMarker(e, el) {
		if (!(e.key === MaskExpression.NUMPAD_DECIMAL || e.code === MaskExpression.NUMPAD_DECIMAL_CODE && e.key === MaskExpression.DOT) || e.ctrlKey || e.metaKey || e.altKey || el.readOnly || !this._maskValue().startsWith(MaskExpression.SEPARATOR)) return false;
		const configuredMarker = this._maskService.decimalMarker;
		const marker = Array.isArray(configuredMarker) ? configuredMarker.find((item) => item !== this._maskService.thousandSeparator) : configuredMarker;
		if (marker !== MaskExpression.COMMA) return false;
		const start = el.selectionStart ?? el.value.length;
		const end = el.selectionEnd ?? start;
		e.preventDefault();
		this._code.set(MaskExpression.NUMPAD_DECIMAL_CODE);
		this._inputValue.set(el.value);
		this._maskService.selStart = start;
		this._maskService.selEnd = end;
		el.value = `${el.value.slice(0, start)}${marker}${el.value.slice(end)}`;
		el.setSelectionRange(start + 1, start + 1);
		el.dispatchEvent(new InputEvent("input", {
			inputType: "insertText",
			data: marker,
			bubbles: true
		}));
		return true;
	}
	_writeProgrammatically(write) {
		const enclosingWrite = this._programmaticWrite;
		this._programmaticWrite = true;
		try {
			return write();
		} finally {
			this._programmaticWrite = enclosingWrite;
		}
	}
	_emitProgrammaticValue(fn, value) {
		const ngControl = this._resolveNgControl();
		const control = ngControl?.control;
		if (ngControl?.valueAccessor === this && control && typeof control.setValue === "function") {
			control.setValue(value, { emitModelToViewChange: false });
			ngControl.viewToModelUpdate(value);
			return;
		}
		const wasPristine = ngControl ? Boolean(ngControl.pristine) : true;
		const wasUntouched = ngControl ? Boolean(ngControl.untouched) : true;
		fn(value);
		if (wasPristine && ngControl?.dirty && typeof control?.markAsPristine === "function") control.markAsPristine({ onlySelf: true });
		if (wasUntouched && ngControl?.touched && typeof control?.markAsUntouched === "function") control.markAsUntouched({ onlySelf: true });
	}
	writeValue(controlValue) {
		if (!this._configApplied && this.mask()) {
			this._pendingInitialValue = controlValue;
			this._hasPendingInitialValue = true;
			return;
		}
		const lastPropagated = this._lastPropagatedValue;
		this._lastPropagatedValue = null;
		if (lastPropagated !== null && lastPropagated !== "" && (typeof controlValue === "string" || typeof controlValue === "number") && String(controlValue) === lastPropagated) return;
		const writeSequence = ++this._writeSequence;
		let value = controlValue;
		const inputTransformFn = this._maskService.inputTransformFn;
		if (typeof value === "object" && value !== null && "value" in value) {
			if ("disable" in value) this.setDisabledState(Boolean(value.disable));
			value = value.value;
		}
		if (value !== null) value = inputTransformFn ? inputTransformFn(value) : value;
		if (typeof value === "string" || typeof value === "number" || value === null || typeof value === "undefined") {
			if (value === null || typeof value === "undefined" || value === "") {
				this._maskService.currentValue = "";
				this._maskService.previousValue = "";
			}
			let inputValue = value;
			if (typeof inputValue === "number" || this._maskValue().startsWith(MaskExpression.SEPARATOR)) {
				inputValue = displayToPlainDecimal(String(inputValue), this._maskService.decimalMarker, this._maskService.thousandSeparator);
				const localeDecimalMarker = this._maskService.currentLocaleDecimalMarker();
				if (!Array.isArray(this._maskService.decimalMarker)) inputValue = this._maskService.decimalMarker !== localeDecimalMarker ? inputValue.replace(localeDecimalMarker, this._maskService.decimalMarker) : inputValue;
				const commaDecimal = usesCommaDecimal(inputValue, this._maskService.decimalMarker, this._maskService.thousandSeparator);
				if (this._maskService.leadZero && inputValue && this.mask() && this._maskService.dropSpecialCharacters !== false) inputValue = this._maskService._checkPrecision(this._maskService.maskExpression, inputValue);
				if (commaDecimal) inputValue = inputValue.toString().replace(MaskExpression.DOT, MaskExpression.COMMA);
				if (this._resolvedMaskInput().startsWith(MaskExpression.SEPARATOR) && this._maskService.leadZero) {
					const isFirstWrite = !this._maskService.isInitialized;
					afterNextRender(() => {
						if (writeSequence !== this._writeSequence) return;
						this._ngZone.run(() => {
							if (isFirstWrite) this._maskService.isInitialized = false;
							this._writeProgrammatically(() => this._maskService.applyMask(inputValue?.toString() ?? "", this._maskService.maskExpression));
							if (isFirstWrite) this._maskService.isInitialized = true;
							this._changeDetectorRef.markForCheck();
						});
					}, { injector: this._injector });
				}
				this._maskService.isNumberValue = true;
			} else if (typeof inputValue === "string" && inputValue !== "") this._maskService.isNumberValue = false;
			if (typeof inputValue !== "string" || value === null || typeof value === "undefined") inputValue = "";
			this._inputValue.set(inputValue);
			this._setMask();
			if (inputValue && this._maskService.maskExpression || this._maskService.maskExpression && (this._maskService.prefix || this._maskService.showMaskTyped)) {
				this._maskService.writingValue = true;
				this._writtenValue = { value: controlValue };
				let displayValue;
				try {
					displayValue = this._writeProgrammatically(() => this._maskedOrVerbatim(inputValue));
				} finally {
					this._writtenValue = null;
				}
				if (writeSequence === this._writeSequence) {
					this._maskService.formElementProperty = ["value", displayValue];
					this._writeElementValueSync(displayValue);
				}
				this._maskService.writingValue = false;
				this._maskService.isInitialized = true;
			} else {
				this._maskService.formElementProperty = ["value", inputValue];
				this._writeElementValueSync(inputValue);
				this._maskService.isInitialized = true;
			}
			this._changeDetectorRef.markForCheck();
		} else console.warn("Ngx-mask writeValue work with string | number, your current value:", typeof value);
	}
	_writeElementValueSync(value) {
		if (this._resolvedMaskInput() !== this._maskValue()) return;
		this._renderer.setProperty(this._elementRef.nativeElement, "value", value);
	}
	_resolvedMaskInput() {
		return resolveMaskAlias(this.mask(), this._config.maskAliases);
	}
	registerOnChange(fn) {
		this._isCvaMode.set(true);
		const originalFn = fn;
		this._maskService.onChange = this.onChange = (value) => {
			if (!this._writtenValue || !Object.is(this._writtenValue.value, value)) {
				if (this._programmaticWrite) this._emitProgrammaticValue(originalFn, value);
				else originalFn(value);
			}
			this._propagateToValueModel(value);
		};
	}
	registerOnValidatorChange(fn) {
		this._onValidatorChange = fn;
	}
	registerOnTouched(fn) {
		this.onTouch = () => {
			fn();
			if (!this.touched()) this.touched.set(true);
		};
	}
	_propagateToValueModel(value) {
		const stringValue = value === null || typeof value === "undefined" ? "" : String(value);
		this._lastPropagatedValue = stringValue;
		this._valuePropagatedByEdit = stringValue;
		untracked(() => {
			if (String(this.value()) !== stringValue) {
				this._skipNextValueEffect.set(true);
				this.value.set(stringValue);
			}
		});
	}
	_valueEffectWillWrite(value) {
		return !this._isCvaMode() && !this._skipNextValueEffect() && String(value) !== String(this._inputValue());
	}
	focus() {
		this._maskService._elementRef?.nativeElement?.focus();
	}
	checkSelectionOnDeletion(el) {
		const prefixLength = this._maskService.prefix.length;
		const suffixLength = this._maskService.suffix.length;
		const inputValueLength = this._inputValue().length;
		el.selectionStart = Math.min(Math.max(prefixLength, el.selectionStart), inputValueLength - suffixLength);
		el.selectionEnd = Math.min(Math.max(prefixLength, el.selectionEnd), inputValueLength - suffixLength);
	}
	setDisabledState(isDisabled) {
		this._renderer.setProperty(this._elementRef.nativeElement, "disabled", isDisabled);
		this._maskService.formElementProperty = ["disabled", isDisabled];
	}
	_mirrorInput(key, value) {
		this._maskService[key] = value;
	}
	_applyMask(renderInputValue) {
		this._maskService.maskExpression = this._maskService._repeatPatternSymbols(this._maskValue() || "");
		if (!renderInputValue) {
			this._maskService.writingValue = false;
			this._maskService._clearMaskChangedUnlessTriggered();
			return;
		}
		this._maskService.formElementProperty = ["value", this._maskedOrVerbatim(this._inputValue())];
		this._maskService.writingValue = false;
		this._maskService._clearMaskChangedUnlessTriggered();
	}
	_maskedOrVerbatim(inputValue) {
		const wasMaskChanged = this._maskService.maskChanged;
		const maskedResult = this._maskService.applyMask(inputValue, this._maskService.maskExpression);
		return !maskedResult && inputValue && !wasMaskChanged && this._maskService.removeMask(inputValue) ? inputValue : maskedResult;
	}
	_validateTime(value) {
		const rowMaskLen = this._maskValue().split(MaskExpression.EMPTY_STRING).filter((s) => s !== ":").length;
		if (!value) return null;
		if (+(value[value.length - 1] ?? -1) === 0 && value.length < rowMaskLen || value.length <= rowMaskLen - 2) return this._createValidationError(value);
		return null;
	}
	_getActualInputLength() {
		return this._maskService.actualValue.length || this._maskService.actualValue.length + this._maskService.prefix.length;
	}
	_isCompleteAlternativeBoundary(processedValue) {
		const alternatives = this._maskExpressionArray();
		if (!alternatives.length) return false;
		const maskValue = this._maskValue();
		const cleanValue = this._maskService.removeMask(processedValue);
		const cleanMask = this._maskService.removeMask(maskValue);
		if (!cleanValue.split(MaskExpression.EMPTY_STRING).every((character, index) => this._maskService._checkSymbolMask(character, cleanMask.charAt(index)))) return false;
		let patternCount = 0;
		let boundaryCharacter = MaskExpression.EMPTY_STRING;
		for (const maskCharacter of maskValue) {
			if (patternCount === cleanValue.length) {
				boundaryCharacter = maskCharacter;
				break;
			}
			if (!this._maskService.specialCharacters.includes(maskCharacter)) patternCount++;
		}
		if (!boundaryCharacter || !this._maskService.specialCharacters.includes(boundaryCharacter)) return false;
		return alternatives.some((alternative) => {
			const requiredLength = this._maskService.dropSpecialCharacters ? alternative.length - this._maskService.checkDropSpecialCharAmount(alternative) : this._maskService.prefix ? alternative.length + this._maskService.prefix.length : alternative.length;
			return processedValue.length === requiredLength;
		});
	}
	_isPlainTokenMask(mask) {
		return mask.split(MaskExpression.EMPTY_STRING).every((symbol) => !!this._maskService.patterns[symbol] || this._maskService.specialCharacters.includes(symbol));
	}
	_matchesMaskWithOptionalSkip(value, mask) {
		const patterns = this._maskService.patterns;
		const failed = /* @__PURE__ */ new Set();
		const match = (maskIndex, valueIndex) => {
			const state = maskIndex * (value.length + 1) + valueIndex;
			if (failed.has(state)) return false;
			const matched = matchFrom(maskIndex, valueIndex);
			if (!matched) failed.add(state);
			return matched;
		};
		const matchFrom = (maskIndex, valueIndex) => {
			if (valueIndex === value.length) return mask.slice(maskIndex).split(MaskExpression.EMPTY_STRING).every((symbol) => !patterns[symbol] || !!patterns[symbol]?.optional);
			if (maskIndex === mask.length) return false;
			const maskSymbol = mask[maskIndex];
			const valueSymbol = value[valueIndex];
			const pattern = patterns[maskSymbol];
			if (pattern) {
				if (this._maskService._checkSymbolMask(valueSymbol, maskSymbol) && match(maskIndex + 1, valueIndex + 1)) return true;
				return !!pattern.optional && match(maskIndex + 1, valueIndex);
			}
			if (valueSymbol === maskSymbol && match(maskIndex + 1, valueIndex + 1)) return true;
			return match(maskIndex + 1, valueIndex);
		};
		return match(0, 0);
	}
	_createValidationError(actualValue) {
		return { mask: {
			requiredMask: this._maskValue(),
			actualValue
		} };
	}
	_setMask() {
		this._maskExpressionArray().some((mask) => {
			if (mask.split(MaskExpression.EMPTY_STRING).some((char) => this._maskService.specialCharacters.includes(char)) && this._inputValue() && this._areAllCharactersInEachStringSame(this._maskExpressionArray()) || mask.includes(MaskExpression.CURLY_BRACKETS_LEFT)) {
				const test = this._maskService.removeMask(this._inputValue())?.length <= this._maskService.removeMask(mask)?.length;
				if (test) {
					const maskValue = mask.includes(MaskExpression.CURLY_BRACKETS_LEFT) ? this._maskService._repeatPatternSymbols(mask) : mask;
					this._maskValue.set(maskValue);
					this._maskService.maskExpression = maskValue;
					return test;
				} else {
					const expression = this._maskExpressionArray()[this._maskExpressionArray().length - 1] ?? MaskExpression.EMPTY_STRING;
					const maskValue = expression.includes(MaskExpression.CURLY_BRACKETS_LEFT) ? this._maskService._repeatPatternSymbols(expression) : expression;
					this._maskValue.set(maskValue);
					this._maskService.maskExpression = maskValue;
				}
			} else {
				const cleanMask = this._maskService.removeMask(mask);
				const check = this._maskService.removeMask(this._inputValue())?.split(MaskExpression.EMPTY_STRING).every((character, index) => {
					const indexMask = cleanMask.charAt(index);
					return this._maskService._checkSymbolMask(character, indexMask);
				});
				if (check || this._justPasted()) {
					this._maskValue.set(mask);
					this._maskService.maskExpression = mask;
					return check;
				}
			}
		});
	}
	_areAllCharactersInEachStringSame(array) {
		const specialCharacters = this._maskService.specialCharacters;
		function removeSpecialCharacters(str) {
			const regex = new RegExp(`[${specialCharacters.map((ch) => escapeRegExp(ch)).join("")}]`, "g");
			return str.replace(regex, "");
		}
		return array.map(removeSpecialCharacters).every((str) => {
			return new Set(str).size === 1;
		});
	}
	static ɵfac = i0.ɵɵngDeclareFactory({
		minVersion: "12.0.0",
		version: "22.2.3",
		ngImport: i0,
		type: NgxMaskDirective,
		deps: [],
		target: i0.ɵɵFactoryTarget.Directive
	});
	static ɵdir = i0.ɵɵngDeclareDirective({
		minVersion: "17.1.0",
		version: "22.2.3",
		type: NgxMaskDirective,
		isStandalone: true,
		selector: "input[mask], textarea[mask]",
		inputs: {
			mask: {
				classPropertyName: "mask",
				publicName: "mask",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			specialCharacters: {
				classPropertyName: "specialCharacters",
				publicName: "specialCharacters",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			patterns: {
				classPropertyName: "patterns",
				publicName: "patterns",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			prefix: {
				classPropertyName: "prefix",
				publicName: "prefix",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			suffix: {
				classPropertyName: "suffix",
				publicName: "suffix",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			thousandSeparator: {
				classPropertyName: "thousandSeparator",
				publicName: "thousandSeparator",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			decimalMarker: {
				classPropertyName: "decimalMarker",
				publicName: "decimalMarker",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			dropSpecialCharacters: {
				classPropertyName: "dropSpecialCharacters",
				publicName: "dropSpecialCharacters",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			hiddenInput: {
				classPropertyName: "hiddenInput",
				publicName: "hiddenInput",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			showMaskTyped: {
				classPropertyName: "showMaskTyped",
				publicName: "showMaskTyped",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			placeHolderCharacter: {
				classPropertyName: "placeHolderCharacter",
				publicName: "placeHolderCharacter",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			shownMaskExpression: {
				classPropertyName: "shownMaskExpression",
				publicName: "shownMaskExpression",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			clearIfNotMatch: {
				classPropertyName: "clearIfNotMatch",
				publicName: "clearIfNotMatch",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			validation: {
				classPropertyName: "validation",
				publicName: "validation",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			separatorLimit: {
				classPropertyName: "separatorLimit",
				publicName: "separatorLimit",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			typeFromDecimals: {
				classPropertyName: "typeFromDecimals",
				publicName: "typeFromDecimals",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			allowNegativeNumbers: {
				classPropertyName: "allowNegativeNumbers",
				publicName: "allowNegativeNumbers",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			leadZeroDateTime: {
				classPropertyName: "leadZeroDateTime",
				publicName: "leadZeroDateTime",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			leadZero: {
				classPropertyName: "leadZero",
				publicName: "leadZero",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			triggerOnMaskChange: {
				classPropertyName: "triggerOnMaskChange",
				publicName: "triggerOnMaskChange",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			apm: {
				classPropertyName: "apm",
				publicName: "apm",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			inputTransformFn: {
				classPropertyName: "inputTransformFn",
				publicName: "inputTransformFn",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			outputTransformFn: {
				classPropertyName: "outputTransformFn",
				publicName: "outputTransformFn",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			keepCharacterPositions: {
				classPropertyName: "keepCharacterPositions",
				publicName: "keepCharacterPositions",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			instantPrefix: {
				classPropertyName: "instantPrefix",
				publicName: "instantPrefix",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			defaultValueOnBlur: {
				classPropertyName: "defaultValueOnBlur",
				publicName: "defaultValueOnBlur",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			value: {
				classPropertyName: "value",
				publicName: "value",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			disabled: {
				classPropertyName: "disabled",
				publicName: "disabled",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			},
			touched: {
				classPropertyName: "touched",
				publicName: "touched",
				isSignal: true,
				isRequired: false,
				transformFunction: null
			}
		},
		outputs: {
			value: "valueChange",
			touched: "touchedChange",
			maskFilled: "maskFilled"
		},
		host: { listeners: {
			"paste": "onPaste()",
			"focus": "onFocus()",
			"ngModelChange": "onModelChange($event)",
			"input": "onInput($event)",
			"compositionstart": "onCompositionStart()",
			"compositionend": "onCompositionEnd($event)",
			"blur": "onBlur($event)",
			"click": "onClick($event)",
			"keydown": "onKeyDown($event)"
		} },
		providers: [
			{
				provide: NG_VALUE_ACCESSOR,
				useExisting: NgxMaskDirective,
				multi: true
			},
			{
				provide: NG_VALIDATORS,
				useExisting: NgxMaskDirective,
				multi: true
			},
			NgxMaskService
		],
		exportAs: ["mask", "ngxMask"],
		usesOnChanges: true,
		ngImport: i0
	});
};
i0.ɵɵngDeclareClassMetadata({
	minVersion: "12.0.0",
	version: "22.2.3",
	ngImport: i0,
	type: NgxMaskDirective,
	decorators: [{
		type: Directive,
		args: [{
			selector: "input[mask], textarea[mask]",
			providers: [
				{
					provide: NG_VALUE_ACCESSOR,
					useExisting: NgxMaskDirective,
					multi: true
				},
				{
					provide: NG_VALIDATORS,
					useExisting: NgxMaskDirective,
					multi: true
				},
				NgxMaskService
			],
			exportAs: "mask,ngxMask",
			host: {
				"(paste)": "onPaste()",
				"(focus)": "onFocus()",
				"(ngModelChange)": "onModelChange($event)",
				"(input)": "onInput($event)",
				"(compositionstart)": "onCompositionStart()",
				"(compositionend)": "onCompositionEnd($event)",
				"(blur)": "onBlur($event)",
				"(click)": "onClick($event)",
				"(keydown)": "onKeyDown($event)"
			}
		}]
	}],
	ctorParameters: () => [],
	propDecorators: {
		mask: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "mask",
				required: false
			}]
		}],
		specialCharacters: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "specialCharacters",
				required: false
			}]
		}],
		patterns: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "patterns",
				required: false
			}]
		}],
		prefix: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "prefix",
				required: false
			}]
		}],
		suffix: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "suffix",
				required: false
			}]
		}],
		thousandSeparator: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "thousandSeparator",
				required: false
			}]
		}],
		decimalMarker: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "decimalMarker",
				required: false
			}]
		}],
		dropSpecialCharacters: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "dropSpecialCharacters",
				required: false
			}]
		}],
		hiddenInput: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "hiddenInput",
				required: false
			}]
		}],
		showMaskTyped: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "showMaskTyped",
				required: false
			}]
		}],
		placeHolderCharacter: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "placeHolderCharacter",
				required: false
			}]
		}],
		shownMaskExpression: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "shownMaskExpression",
				required: false
			}]
		}],
		clearIfNotMatch: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "clearIfNotMatch",
				required: false
			}]
		}],
		validation: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "validation",
				required: false
			}]
		}],
		separatorLimit: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "separatorLimit",
				required: false
			}]
		}],
		typeFromDecimals: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "typeFromDecimals",
				required: false
			}]
		}],
		allowNegativeNumbers: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "allowNegativeNumbers",
				required: false
			}]
		}],
		leadZeroDateTime: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "leadZeroDateTime",
				required: false
			}]
		}],
		leadZero: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "leadZero",
				required: false
			}]
		}],
		triggerOnMaskChange: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "triggerOnMaskChange",
				required: false
			}]
		}],
		apm: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "apm",
				required: false
			}]
		}],
		inputTransformFn: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "inputTransformFn",
				required: false
			}]
		}],
		outputTransformFn: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "outputTransformFn",
				required: false
			}]
		}],
		keepCharacterPositions: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "keepCharacterPositions",
				required: false
			}]
		}],
		instantPrefix: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "instantPrefix",
				required: false
			}]
		}],
		defaultValueOnBlur: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "defaultValueOnBlur",
				required: false
			}]
		}],
		value: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "value",
				required: false
			}]
		}, {
			type: i0.Output,
			args: ["valueChange"]
		}],
		disabled: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "disabled",
				required: false
			}]
		}],
		touched: [{
			type: i0.Input,
			args: [{
				isSignal: true,
				alias: "touched",
				required: false
			}]
		}, {
			type: i0.Output,
			args: ["touchedChange"]
		}],
		maskFilled: [{
			type: i0.Output,
			args: ["maskFilled"]
		}]
	}
});
var NgxMaskPipe = class NgxMaskPipe {
	defaultOptions = inject(NGX_MASK_CONFIG);
	_environmentInjector = inject(EnvironmentInjector);
	_maskService;
	_maskExpressionArray = [];
	mask = "";
	transform(value, mask, { patterns, maskAliases, ...config } = {}) {
		let processedValue = value;
		this._maskService = Injector.create({
			providers: [NgxMaskService, {
				provide: NGX_MASK_CONFIG,
				useValue: this.defaultOptions
			}],
			parent: this._environmentInjector
		}).get(NgxMaskService);
		const resolvedMask = resolveMaskAlias(mask, {
			...this.defaultOptions.maskAliases,
			...maskAliases
		});
		const currentConfig = {
			maskExpression: resolvedMask,
			...this.defaultOptions,
			...config,
			patterns: {
				...this.defaultOptions.patterns,
				...patterns
			}
		};
		Object.entries(currentConfig).forEach(([key, val]) => {
			this._maskService[key] = val;
		});
		if (resolvedMask.includes("||")) {
			this._maskExpressionArray = resolvedMask.split("||").sort((a, b) => a.length - b.length);
			this._setMask(`${processedValue}`);
			return this._maskService.applyMask(`${processedValue}`, this.mask);
		}
		if (resolvedMask.includes(MaskExpression.CURLY_BRACKETS_LEFT)) return this._maskService.applyMask(`${processedValue}`, this._maskService._repeatPatternSymbols(resolvedMask));
		if (resolvedMask.startsWith(MaskExpression.SEPARATOR)) {
			if (config.decimalMarker) this._maskService.decimalMarker = config.decimalMarker;
			if (config.thousandSeparator) this._maskService.thousandSeparator = config.thousandSeparator;
			if (config.leadZero) this._maskService.leadZero = config.leadZero;
			processedValue = String(processedValue);
			const localeDecimalMarker = this._maskService.currentLocaleDecimalMarker();
			if (!Array.isArray(this._maskService.decimalMarker)) processedValue = this._maskService.decimalMarker !== localeDecimalMarker ? processedValue.replace(localeDecimalMarker, this._maskService.decimalMarker) : processedValue;
			if (this._maskService.leadZero && processedValue && this._maskService.dropSpecialCharacters !== false) processedValue = this._maskService._checkPrecision(resolvedMask, processedValue);
			if (this._maskService.decimalMarker === MaskExpression.COMMA) processedValue = processedValue.replace(MaskExpression.DOT, MaskExpression.COMMA);
		}
		if (processedValue === null || typeof processedValue === "undefined") return this._maskService.applyMask("", resolvedMask);
		return this._maskService.applyMask(`${processedValue}`, resolvedMask);
	}
	_setMask(value) {
		if (this._maskExpressionArray.length > 0) this._maskExpressionArray.some((mask) => {
			const test = this._maskService.removeMask(value)?.length <= this._maskService.removeMask(mask)?.length;
			if (value && test) {
				this.mask = mask;
				return test;
			} else this.mask = this._maskExpressionArray[this._maskExpressionArray.length - 1] ?? MaskExpression.EMPTY_STRING;
		});
	}
	static ɵfac = i0.ɵɵngDeclareFactory({
		minVersion: "12.0.0",
		version: "22.2.3",
		ngImport: i0,
		type: NgxMaskPipe,
		deps: [],
		target: i0.ɵɵFactoryTarget.Pipe
	});
	static ɵpipe = i0.ɵɵngDeclarePipe({
		minVersion: "14.0.0",
		version: "22.2.3",
		ngImport: i0,
		type: NgxMaskPipe,
		isStandalone: true,
		name: "mask"
	});
};
i0.ɵɵngDeclareClassMetadata({
	minVersion: "12.0.0",
	version: "22.2.3",
	ngImport: i0,
	type: NgxMaskPipe,
	decorators: [{
		type: Pipe,
		args: [{
			name: "mask",
			pure: true
		}]
	}]
});
export { INITIAL_CONFIG, NEW_CONFIG, NGX_MASK_CONFIG, NgxMaskDirective, NgxMaskPipe, NgxMaskService, initialConfig, provideEnvironmentNgxMask, provideNgxMask, resolveMaskAlias, timeMasks, withoutValidation };

//# sourceMappingURL=ngx-mask.mjs.map