UNPKG

ngx-mask

Version:
952 lines 160 kB
import { DOCUMENT } from '@angular/common'; import { Directive, EventEmitter, HostListener, Input, Output, inject, } from '@angular/core'; import { NG_VALIDATORS, NG_VALUE_ACCESSOR, } from '@angular/forms'; import { NGX_MASK_CONFIG, timeMasks, withoutValidation } from './ngx-mask.config'; import { NgxMaskService } from './ngx-mask.service'; import * as i0 from "@angular/core"; export class NgxMaskDirective { constructor() { this.maskExpression = ''; this.specialCharacters = []; this.patterns = {}; this.prefix = ''; this.suffix = ''; this.thousandSeparator = ' '; this.decimalMarker = '.'; this.dropSpecialCharacters = null; this.hiddenInput = null; this.showMaskTyped = null; this.placeHolderCharacter = null; this.shownMaskExpression = null; this.showTemplate = null; this.clearIfNotMatch = null; this.validation = null; this.separatorLimit = null; this.allowNegativeNumbers = null; this.leadZeroDateTime = null; this.leadZero = null; this.triggerOnMaskChange = null; this.apm = null; this.inputTransformFn = null; this.outputTransformFn = null; this.keepCharacterPositions = null; this.maskFilled = new EventEmitter(); this._maskValue = ''; this._position = null; this._maskExpressionArray = []; this._allowFewMaskChangeMask = false; this._justPasted = false; this._isFocused = false; /**For IME composition event */ this._isComposing = false; this.document = inject(DOCUMENT); this._maskService = inject(NgxMaskService, { self: true }); this._config = inject(NGX_MASK_CONFIG); // eslint-disable-next-line @typescript-eslint/no-explicit-any this.onChange = (_) => { }; this.onTouch = () => { }; } ngOnChanges(changes) { const { maskExpression, specialCharacters, patterns, prefix, suffix, thousandSeparator, decimalMarker, dropSpecialCharacters, hiddenInput, showMaskTyped, placeHolderCharacter, shownMaskExpression, showTemplate, clearIfNotMatch, validation, separatorLimit, allowNegativeNumbers, leadZeroDateTime, leadZero, triggerOnMaskChange, apm, inputTransformFn, outputTransformFn, keepCharacterPositions, } = changes; if (maskExpression) { if (maskExpression.currentValue !== maskExpression.previousValue && !maskExpression.firstChange) { this._maskService.maskChanged = true; } if (maskExpression.currentValue && maskExpression.currentValue.split("||" /* MaskExpression.OR */).length > 1) { this._maskExpressionArray = maskExpression.currentValue .split("||" /* MaskExpression.OR */) .sort((a, b) => { return a.length - b.length; }); this._setMask(); } else { this._maskExpressionArray = []; this._maskValue = maskExpression.currentValue || "" /* MaskExpression.EMPTY_STRING */; this._maskService.maskExpression = this._maskValue; } } if (specialCharacters) { if (!specialCharacters.currentValue || !Array.isArray(specialCharacters.currentValue)) { return; } else { this._maskService.specialCharacters = specialCharacters.currentValue || []; } } if (allowNegativeNumbers) { this._maskService.allowNegativeNumbers = allowNegativeNumbers.currentValue; if (this._maskService.allowNegativeNumbers) { this._maskService.specialCharacters = this._maskService.specialCharacters.filter((c) => c !== "-" /* MaskExpression.MINUS */); } } // Only overwrite the mask available patterns if a pattern has actually been passed in if (patterns && patterns.currentValue) { this._maskService.patterns = patterns.currentValue; } if (apm && apm.currentValue) { this._maskService.apm = apm.currentValue; } if (prefix) { this._maskService.prefix = prefix.currentValue; } if (suffix) { this._maskService.suffix = suffix.currentValue; } if (thousandSeparator) { this._maskService.thousandSeparator = thousandSeparator.currentValue; } if (decimalMarker) { this._maskService.decimalMarker = decimalMarker.currentValue; } if (dropSpecialCharacters) { this._maskService.dropSpecialCharacters = dropSpecialCharacters.currentValue; } if (hiddenInput) { this._maskService.hiddenInput = hiddenInput.currentValue; } if (showMaskTyped) { this._maskService.showMaskTyped = showMaskTyped.currentValue; if (showMaskTyped.previousValue === false && showMaskTyped.currentValue === true && this._isFocused) { requestAnimationFrame(() => { this._maskService._elementRef?.nativeElement.click(); }); } } if (placeHolderCharacter) { this._maskService.placeHolderCharacter = placeHolderCharacter.currentValue; } if (shownMaskExpression) { this._maskService.shownMaskExpression = shownMaskExpression.currentValue; } if (showTemplate) { this._maskService.showTemplate = showTemplate.currentValue; } if (clearIfNotMatch) { this._maskService.clearIfNotMatch = clearIfNotMatch.currentValue; } if (validation) { this._maskService.validation = validation.currentValue; } if (separatorLimit) { this._maskService.separatorLimit = separatorLimit.currentValue; } if (leadZeroDateTime) { this._maskService.leadZeroDateTime = leadZeroDateTime.currentValue; } if (leadZero) { this._maskService.leadZero = leadZero.currentValue; } if (triggerOnMaskChange) { this._maskService.triggerOnMaskChange = triggerOnMaskChange.currentValue; } if (inputTransformFn) { this._maskService.inputTransformFn = inputTransformFn.currentValue; } if (outputTransformFn) { this._maskService.outputTransformFn = outputTransformFn.currentValue; } if (keepCharacterPositions) { this._maskService.keepCharacterPositions = keepCharacterPositions.currentValue; } this._applyMask(); } validate({ value }) { if (!this._maskService.validation || !this._maskValue) { return null; } if (this._maskService.ipError) { return this._createValidationError(value); } if (this._maskService.cpfCnpjError) { return this._createValidationError(value); } if (this._maskValue.startsWith("separator" /* MaskExpression.SEPARATOR */)) { return null; } if (withoutValidation.includes(this._maskValue)) { return null; } if (this._maskService.clearIfNotMatch) { return null; } if (timeMasks.includes(this._maskValue)) { return this._validateTime(value); } if (value && value.toString().length >= 1) { let counterOfOpt = 0; if (this._maskValue.includes("{" /* MaskExpression.CURLY_BRACKETS_LEFT */) && this._maskValue.includes("}" /* MaskExpression.CURLY_BRACKETS_RIGHT */)) { const lengthInsideCurlyBrackets = this._maskValue.slice(this._maskValue.indexOf("{" /* MaskExpression.CURLY_BRACKETS_LEFT */) + 1, this._maskValue.indexOf("}" /* MaskExpression.CURLY_BRACKETS_RIGHT */)); return lengthInsideCurlyBrackets === String(value.length) ? null : this._createValidationError(value); } if (this._maskValue.startsWith("percent" /* MaskExpression.PERCENT */)) { return null; } for (const key in this._maskService.patterns) { if (this._maskService.patterns[key]?.optional) { if (this._maskValue.indexOf(key) !== this._maskValue.lastIndexOf(key)) { const opt = this._maskValue .split("" /* MaskExpression.EMPTY_STRING */) .filter((i) => i === key) .join("" /* MaskExpression.EMPTY_STRING */); counterOfOpt += opt.length; } else if (this._maskValue.indexOf(key) !== -1) { counterOfOpt++; } if (this._maskValue.indexOf(key) !== -1 && value.toString().length >= this._maskValue.indexOf(key)) { return null; } if (counterOfOpt === this._maskValue.length) { return null; } } } if ((this._maskValue.indexOf("*" /* MaskExpression.SYMBOL_STAR */) > 1 && value.toString().length < this._maskValue.indexOf("*" /* MaskExpression.SYMBOL_STAR */)) || (this._maskValue.indexOf("?" /* MaskExpression.SYMBOL_QUESTION */) > 1 && value.toString().length < this._maskValue.indexOf("?" /* MaskExpression.SYMBOL_QUESTION */))) { return this._createValidationError(value); } if (this._maskValue.indexOf("*" /* MaskExpression.SYMBOL_STAR */) === -1 || this._maskValue.indexOf("?" /* MaskExpression.SYMBOL_QUESTION */) === -1) { // eslint-disable-next-line no-param-reassign value = typeof value === 'number' ? String(value) : value; const array = this._maskValue.split('*'); const length = this._maskService.dropSpecialCharacters ? this._maskValue.length - this._maskService.checkDropSpecialCharAmount(this._maskValue) - counterOfOpt : this.prefix ? this._maskValue.length + this.prefix.length - counterOfOpt : this._maskValue.length - counterOfOpt; if (array.length === 1) { if (value.toString().length < length) { return this._createValidationError(value); } } if (array.length > 1) { const lastIndexArray = array[array.length - 1]; if (lastIndexArray && this._maskService.specialCharacters.includes(lastIndexArray[0]) && String(value).includes(lastIndexArray[0] ?? '') && !this.dropSpecialCharacters) { const special = value.split(lastIndexArray[0]); return special[special.length - 1].length === lastIndexArray.length - 1 ? null : this._createValidationError(value); } else if (((lastIndexArray && !this._maskService.specialCharacters.includes(lastIndexArray[0])) || !lastIndexArray || this._maskService.dropSpecialCharacters) && value.length >= length - 1) { return null; } else { return this._createValidationError(value); } } } if (this._maskValue.indexOf("*" /* MaskExpression.SYMBOL_STAR */) === 1 || this._maskValue.indexOf("?" /* MaskExpression.SYMBOL_QUESTION */) === 1) { return null; } } if (value) { this.maskFilled.emit(); return null; } return null; } onPaste() { this._justPasted = true; } onFocus() { this._isFocused = true; } onModelChange(value) { // on form reset we need to update the actualValue if ((value === "" /* MaskExpression.EMPTY_STRING */ || value === null || value === undefined) && this._maskService.actualValue) { this._maskService.actualValue = this._maskService.getActualValue("" /* MaskExpression.EMPTY_STRING */); } } onInput(e) { // If IME is composing text, we wait for the composed text. if (this._isComposing) return; const el = e.target; const transformedValue = this._maskService.inputTransformFn(el.value); if (el.type !== 'number') { if (typeof transformedValue === 'string' || typeof transformedValue === 'number') { el.value = transformedValue.toString(); this._inputValue = el.value; this._setMask(); if (!this._maskValue) { this.onChange(el.value); return; } let position = el.selectionStart === 1 ? el.selectionStart + this._maskService.prefix.length : el.selectionStart; if (this.showMaskTyped && this.keepCharacterPositions && this._maskService.placeHolderCharacter.length === 1) { const inputSymbol = el.value.slice(position - 1, position); const prefixLength = this.prefix.length; const checkSymbols = this._maskService._checkSymbolMask(inputSymbol, this._maskService.maskExpression[position - 1 - prefixLength] ?? "" /* MaskExpression.EMPTY_STRING */); const checkSpecialCharacter = this._maskService._checkSymbolMask(inputSymbol, this._maskService.maskExpression[position + 1 - prefixLength] ?? "" /* MaskExpression.EMPTY_STRING */); const selectRangeBackspace = this._maskService.selStart === this._maskService.selEnd; const selStart = Number(this._maskService.selStart) - prefixLength; const selEnd = Number(this._maskService.selEnd) - prefixLength; if (this._code === "Backspace" /* MaskExpression.BACKSPACE */) { if (!selectRangeBackspace) { if (this._maskService.selStart === prefixLength) { this._maskService.actualValue = `${this.prefix}${this._maskService.maskIsShown.slice(0, selEnd)}${this._inputValue.split(this.prefix).join('')}`; } else if (this._maskService.selStart === this._maskService.maskIsShown.length + prefixLength) { this._maskService.actualValue = `${this._inputValue}${this._maskService.maskIsShown.slice(selStart, selEnd)}`; } else { this._maskService.actualValue = `${this.prefix}${this._inputValue .split(this.prefix) .join('') .slice(0, selStart)}${this._maskService.maskIsShown.slice(selStart, selEnd)}${this._maskService.actualValue.slice(selEnd + prefixLength, this._maskService.maskIsShown.length + prefixLength)}${this.suffix}`; } } else if (!this._maskService.specialCharacters.includes(this._maskService.maskExpression.slice(position - this.prefix.length, position + 1 - this.prefix.length)) && selectRangeBackspace) { if (selStart === 1 && this.prefix) { this._maskService.actualValue = `${this.prefix}${this._maskService.placeHolderCharacter}${el.value .split(this.prefix) .join('') .split(this.suffix) .join('')}${this.suffix}`; position = position - 1; } else { const part1 = el.value.substring(0, position); const part2 = el.value.substring(position); this._maskService.actualValue = `${part1}${this._maskService.placeHolderCharacter}${part2}`; } } } if (this._code !== "Backspace" /* MaskExpression.BACKSPACE */) { if (!checkSymbols && !checkSpecialCharacter && selectRangeBackspace) { position = Number(el.selectionStart) - 1; } else if (this._maskService.specialCharacters.includes(el.value.slice(position, position + 1)) && checkSpecialCharacter && !this._maskService.specialCharacters.includes(el.value.slice(position + 1, position + 2))) { this._maskService.actualValue = `${el.value.slice(0, position - 1)}${el.value.slice(position, position + 1)}${inputSymbol}${el.value.slice(position + 2)}`; position = position + 1; } else if (checkSymbols) { if (el.value.length === 1 && position === 1) { this._maskService.actualValue = `${this.prefix}${inputSymbol}${this._maskService.maskIsShown.slice(1, this._maskService.maskIsShown.length)}${this.suffix}`; } else { this._maskService.actualValue = `${el.value.slice(0, position - 1)}${inputSymbol}${el.value .slice(position + 1) .split(this.suffix) .join('')}${this.suffix}`; } } else if (this.prefix && el.value.length === 1 && position - prefixLength === 1 && this._maskService._checkSymbolMask(el.value, this._maskService.maskExpression[position - 1 - prefixLength] ?? "" /* MaskExpression.EMPTY_STRING */)) { this._maskService.actualValue = `${this.prefix}${el.value}${this._maskService.maskIsShown.slice(1, this._maskService.maskIsShown.length)}${this.suffix}`; } } } let caretShift = 0; let backspaceShift = false; if (this._code === "Delete" /* MaskExpression.DELETE */ && "separator" /* MaskExpression.SEPARATOR */) { this._maskService.deletedSpecialCharacter = true; } if (this._inputValue.length >= this._maskService.maskExpression.length - 1 && this._code !== "Backspace" /* MaskExpression.BACKSPACE */ && this._maskService.maskExpression === "d0/M0/0000" /* MaskExpression.DAYS_MONTHS_YEARS */ && position < 10) { const inputSymbol = this._inputValue.slice(position - 1, position); el.value = this._inputValue.slice(0, position - 1) + inputSymbol + this._inputValue.slice(position + 1); } if (this._maskService.maskExpression === "d0/M0/0000" /* MaskExpression.DAYS_MONTHS_YEARS */ && this.leadZeroDateTime) { if ((position < 3 && Number(el.value) > 31 && Number(el.value) < 40) || (position === 5 && Number(el.value.slice(3, 5)) > 12)) { position = position + 2; } } if (this._maskService.maskExpression === "Hh:m0:s0" /* MaskExpression.HOURS_MINUTES_SECONDS */ && this.apm) { if (this._justPasted && el.value.slice(0, 2) === "00" /* MaskExpression.DOUBLE_ZERO */) { el.value = el.value.slice(1, 2) + el.value.slice(2, el.value.length); } el.value = el.value === "00" /* MaskExpression.DOUBLE_ZERO */ ? "0" /* MaskExpression.NUMBER_ZERO */ : el.value; } this._maskService.applyValueChanges(position, this._justPasted, this._code === "Backspace" /* MaskExpression.BACKSPACE */ || this._code === "Delete" /* MaskExpression.DELETE */, (shift, _backspaceShift) => { this._justPasted = false; caretShift = shift; backspaceShift = _backspaceShift; }); // only set the selection if the element is active if (this._getActiveElement() !== el) { return; } if (this._maskService.plusOnePosition) { position = position + 1; this._maskService.plusOnePosition = false; } // update position after applyValueChanges to prevent cursor on wrong position when it has an array of maskExpression if (this._maskExpressionArray.length) { if (this._code === "Backspace" /* MaskExpression.BACKSPACE */) { const specialChartMinusOne = this.specialCharacters.includes(this._maskService.actualValue.slice(position - 1, position)); const specialChartPlusOne = this.specialCharacters.includes(this._maskService.actualValue.slice(position, position + 1)); if (this._allowFewMaskChangeMask && !specialChartPlusOne) { position = el.selectionStart + 1; this._allowFewMaskChangeMask = false; } else { position = specialChartMinusOne ? position - 1 : position; } } else { position = el.selectionStart === 1 ? el.selectionStart + this._maskService.prefix.length : el.selectionStart; } } this._position = this._position === 1 && this._inputValue.length === 1 ? null : this._position; let positionToApply = this._position ? this._inputValue.length + position + caretShift : position + (this._code === "Backspace" /* MaskExpression.BACKSPACE */ && !backspaceShift ? 0 : caretShift); if (positionToApply > this._getActualInputLength()) { positionToApply = el.value === this._maskService.decimalMarker && el.value.length === 1 ? this._getActualInputLength() + 1 : this._getActualInputLength(); } if (positionToApply < 0) { positionToApply = 0; } el.setSelectionRange(positionToApply, positionToApply); this._position = null; } 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 === "Backspace" /* MaskExpression.BACKSPACE */ || this._code === "Delete" /* MaskExpression.DELETE */); } } // IME starts onCompositionStart() { this._isComposing = true; } // IME completes onCompositionEnd(e) { this._isComposing = false; this._justPasted = true; this.onInput(e); } onBlur(e) { if (this._maskValue) { const el = e.target; if (this.leadZero && el.value.length > 0 && typeof this.decimalMarker === 'string') { const maskExpression = this._maskService.maskExpression; const precision = Number(this._maskService.maskExpression.slice(maskExpression.length - 1, maskExpression.length)); if (precision > 0) { el.value = this.suffix ? el.value.split(this.suffix).join('') : el.value; const decimalPart = el.value.split(this.decimalMarker)[1]; el.value = el.value.includes(this.decimalMarker) ? el.value + "0" /* MaskExpression.NUMBER_ZERO */.repeat(precision - decimalPart.length) + this.suffix : el.value + this.decimalMarker + "0" /* MaskExpression.NUMBER_ZERO */.repeat(precision) + this.suffix; this._maskService.actualValue = el.value; } } this._maskService.clearIfNotMatchFn(); } this._isFocused = false; this.onTouch(); } onClick(e) { if (!this._maskValue) { return; } const el = e.target; const posStart = 0; const posEnd = 0; if (el !== null && el.selectionStart !== null && el.selectionStart === el.selectionEnd && el.selectionStart > this._maskService.prefix.length && // eslint-disable-next-line e.keyCode !== 38) { if (this._maskService.showMaskTyped && !this.keepCharacterPositions) { // We are showing the mask in the input this._maskService.maskIsShown = this._maskService.showMaskInInput(); if (el.setSelectionRange && this._maskService.prefix + this._maskService.maskIsShown === el.value) { // the input ONLY contains the mask, so position the cursor at the start el.focus(); el.setSelectionRange(posStart, posEnd); } else { // the input contains some characters already if (el.selectionStart > this._maskService.actualValue.length) { // if the user clicked beyond our value's length, position the cursor at the end of our value 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); /** Fix of cursor position jumping to end in most browsers no matter where cursor is inserted onFocus */ if (el && el.value !== nextValue) { el.value = nextValue; } /** fix of cursor position with prefix when mouse click occur */ if (el && el.type !== 'number' && (el.selectionStart || el.selectionEnd) <= this._maskService.prefix.length) { el.selectionStart = this._maskService.prefix.length; return; } /** select only inserted text */ if (el && el.selectionEnd > this._getActualInputLength()) { el.selectionEnd = this._getActualInputLength(); } } onKeyDown(e) { if (!this._maskValue) { return; } if (this._isComposing) { // User finalize their choice from IME composition, so trigger onInput() for the composed text. if (e.key === 'Enter') this.onCompositionEnd(e); return; } this._code = e.code ? e.code : e.key; const el = e.target; this._inputValue = el.value; this._setMask(); if (el.type !== 'number') { if (e.key === "ArrowUp" /* MaskExpression.ARROW_UP */) { e.preventDefault(); } if (e.key === "ArrowLeft" /* MaskExpression.ARROW_LEFT */ || e.key === "Backspace" /* MaskExpression.BACKSPACE */ || e.key === "Delete" /* MaskExpression.DELETE */) { if (e.key === "Backspace" /* MaskExpression.BACKSPACE */ && el.value.length === 0) { el.selectionStart = el.selectionEnd; } if (e.key === "Backspace" /* MaskExpression.BACKSPACE */ && el.selectionStart !== 0) { // If specialChars is false, (shouldn't ever happen) then set to the defaults this.specialCharacters = this.specialCharacters?.length ? this.specialCharacters : this._config.specialCharacters; if (this.prefix.length > 1 && el.selectionStart <= this.prefix.length) { el.setSelectionRange(this.prefix.length, el.selectionEnd); } else { if (this._inputValue.length !== el.selectionStart && el.selectionStart !== 1) { while (this.specialCharacters.includes((this._inputValue[el.selectionStart - 1] ?? "" /* MaskExpression.EMPTY_STRING */).toString()) && ((this.prefix.length >= 1 && el.selectionStart > this.prefix.length) || this.prefix.length === 0)) { el.setSelectionRange(el.selectionStart - 1, el.selectionEnd); } } } } this.checkSelectionOnDeletion(el); if (this._maskService.prefix.length && el.selectionStart <= this._maskService.prefix.length && el.selectionEnd <= this._maskService.prefix.length) { e.preventDefault(); } const cursorStart = el.selectionStart; if (e.key === "Backspace" /* MaskExpression.BACKSPACE */ && !el.readOnly && cursorStart === 0 && el.selectionEnd === el.value.length && el.value.length !== 0) { this._position = this._maskService.prefix ? this._maskService.prefix.length : 0; this._maskService.applyMask(this._maskService.prefix, this._maskService.maskExpression, this._position); } } if (!!this.suffix && this.suffix.length > 1 && this._inputValue.length - this.suffix.length < el.selectionStart) { el.setSelectionRange(this._inputValue.length - this.suffix.length, this._inputValue.length); } else if ((e.code === 'KeyA' && e.ctrlKey) || (e.code === 'KeyA' && e.metaKey) // Cmd + A (Mac) ) { el.setSelectionRange(0, this._getActualInputLength()); e.preventDefault(); } this._maskService.selStart = el.selectionStart; this._maskService.selEnd = el.selectionEnd; } } /** It writes the value in the input */ async writeValue(controlValue) { if (typeof controlValue === 'object' && controlValue !== null && 'value' in controlValue) { if ('disable' in controlValue) { this.setDisabledState(Boolean(controlValue.disable)); } // eslint-disable-next-line no-param-reassign controlValue = controlValue.value; } if (controlValue !== null) { // eslint-disable-next-line no-param-reassign controlValue = this.inputTransformFn ? this.inputTransformFn(controlValue) : controlValue; } if (typeof controlValue === 'string' || typeof controlValue === 'number' || controlValue === null || controlValue === undefined) { if (controlValue === null || controlValue === undefined || controlValue === '') { this._maskService._currentValue = ''; this._maskService._previousValue = ''; } let inputValue = controlValue; if (typeof inputValue === 'number' || this._maskValue.startsWith("separator" /* MaskExpression.SEPARATOR */)) { inputValue = String(inputValue); const localeDecimalMarker = this._maskService.currentLocaleDecimalMarker(); if (!Array.isArray(this._maskService.decimalMarker)) { inputValue = this._maskService.decimalMarker !== localeDecimalMarker ? inputValue.replace(localeDecimalMarker, this._maskService.decimalMarker) : inputValue; } if (this._maskService.leadZero && inputValue && this.maskExpression && this.dropSpecialCharacters !== false) { inputValue = this._maskService._checkPrecision(this._maskService.maskExpression, inputValue); } if (this.decimalMarker === "," /* MaskExpression.COMMA */ || (Array.isArray(this._maskService.decimalMarker) && this.thousandSeparator === "." /* MaskExpression.DOT */)) { inputValue = inputValue .toString() .replace("." /* MaskExpression.DOT */, "," /* MaskExpression.COMMA */); } if (this.maskExpression?.startsWith("separator" /* MaskExpression.SEPARATOR */) && this.leadZero) { requestAnimationFrame(() => { this._maskService.applyMask(inputValue?.toString() ?? '', this._maskService.maskExpression); }); } this._maskService.isNumberValue = true; } if (typeof inputValue !== 'string') { inputValue = ''; } this._inputValue = inputValue; this._setMask(); if ((inputValue && this._maskService.maskExpression) || (this._maskService.maskExpression && (this._maskService.prefix || this._maskService.showMaskTyped))) { // Let the service we know we are writing value so that triggering onChange function won't happen during applyMask typeof this.inputTransformFn !== 'function' ? (this._maskService.writingValue = true) : ''; this._maskService.formElementProperty = [ 'value', this._maskService.applyMask(inputValue, this._maskService.maskExpression), ]; // Let the service know we've finished writing value typeof this.inputTransformFn !== 'function' ? (this._maskService.writingValue = false) : ''; } else { this._maskService.formElementProperty = ['value', inputValue]; } this._inputValue = inputValue; } else { console.warn('Ngx-mask writeValue work with string | number, your current value:', typeof controlValue); } } registerOnChange(fn) { this._maskService.onChange = this.onChange = fn; } registerOnTouched(fn) { this.onTouch = fn; } _getActiveElement(document = this.document) { const shadowRootEl = document?.activeElement?.shadowRoot; if (!shadowRootEl?.activeElement) { return document.activeElement; } else { return this._getActiveElement(shadowRootEl); } } checkSelectionOnDeletion(el) { el.selectionStart = Math.min(Math.max(this.prefix.length, el.selectionStart), this._inputValue.length - this.suffix.length); el.selectionEnd = Math.min(Math.max(this.prefix.length, el.selectionEnd), this._inputValue.length - this.suffix.length); } /** It disables the input element */ setDisabledState(isDisabled) { this._maskService.formElementProperty = ['disabled', isDisabled]; } // eslint-disable-next-line @typescript-eslint/no-explicit-any _applyMask() { this._maskService.maskExpression = this._maskService._repeatPatternSymbols(this._maskValue || ''); this._maskService.formElementProperty = [ 'value', this._maskService.applyMask(this._inputValue, this._maskService.maskExpression), ]; } _validateTime(value) { const rowMaskLen = this._maskValue .split("" /* MaskExpression.EMPTY_STRING */) .filter((s) => s !== ':').length; if (!value) { return null; // Don't validate empty values to allow for optional form control } 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); } _createValidationError(actualValue) { return { mask: { requiredMask: this._maskValue, actualValue, }, }; } _setMask() { this._maskExpressionArray.some((mask) => { const specialChart = mask .split("" /* MaskExpression.EMPTY_STRING */) .some((char) => this._maskService.specialCharacters.includes(char)); if ((specialChart && 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) { this._maskValue = this.maskExpression = this._maskService.maskExpression = mask.includes("{" /* MaskExpression.CURLY_BRACKETS_LEFT */) ? this._maskService._repeatPatternSymbols(mask) : mask; return test; } else { if (this._code === "Backspace" /* MaskExpression.BACKSPACE */) { this._allowFewMaskChangeMask = true; } const expression = this._maskExpressionArray[this._maskExpressionArray.length - 1] ?? "" /* MaskExpression.EMPTY_STRING */; this._maskValue = this.maskExpression = this._maskService.maskExpression = expression.includes("{" /* MaskExpression.CURLY_BRACKETS_LEFT */) ? this._maskService._repeatPatternSymbols(expression) : expression; } } else { const check = this._maskService .removeMask(this._inputValue) ?.split("" /* MaskExpression.EMPTY_STRING */) .every((character, index) => { const indexMask = mask.charAt(index); return this._maskService._checkSymbolMask(character, indexMask); }); if (check || this._justPasted) { this._maskValue = this.maskExpression = this._maskService.maskExpression = mask; return check; } } }); } _areAllCharactersInEachStringSame(array) { const specialCharacters = this._maskService.specialCharacters; function removeSpecialCharacters(str) { const regex = new RegExp(`[${specialCharacters.map((ch) => `\\${ch}`).join('')}]`, 'g'); return str.replace(regex, ''); } const processedArr = array.map(removeSpecialCharacters); return processedArr.every((str) => { const uniqueCharacters = new Set(str); return uniqueCharacters.size === 1; }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.8", ngImport: i0, type: NgxMaskDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.8", type: NgxMaskDirective, isStandalone: true, selector: "input[mask], textarea[mask]", inputs: { maskExpression: ["mask", "maskExpression"], specialCharacters: "specialCharacters", patterns: "patterns", prefix: "prefix", suffix: "suffix", thousandSeparator: "thousandSeparator", decimalMarker: "decimalMarker", dropSpecialCharacters: "dropSpecialCharacters", hiddenInput: "hiddenInput", showMaskTyped: "showMaskTyped", placeHolderCharacter: "placeHolderCharacter", shownMaskExpression: "shownMaskExpression", showTemplate: "showTemplate", clearIfNotMatch: "clearIfNotMatch", validation: "validation", separatorLimit: "separatorLimit", allowNegativeNumbers: "allowNegativeNumbers", leadZeroDateTime: "leadZeroDateTime", leadZero: "leadZero", triggerOnMaskChange: "triggerOnMaskChange", apm: "apm", inputTransformFn: "inputTransformFn", outputTransformFn: "outputTransformFn", keepCharacterPositions: "keepCharacterPositions" }, outputs: { maskFilled: "maskFilled" }, host: { listeners: { "paste": "onPaste()", "focus": "onFocus($event)", "ngModelChange": "onModelChange($event)", "input": "onInput($event)", "compositionstart": "onCompositionStart($event)", "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: "17.3.8", ngImport: i0, type: NgxMaskDirective, decorators: [{ type: Directive, args: [{ selector: 'input[mask], textarea[mask]', standalone: true, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: NgxMaskDirective, multi: true, }, { provide: NG_VALIDATORS, useExisting: NgxMaskDirective, multi: true, }, NgxMaskService, ], exportAs: 'mask,ngxMask', }] }], propDecorators: { maskExpression: [{ type: Input, args: ['mask'] }], specialCharacters: [{ type: Input }], patterns: [{ type: Input }], prefix: [{ type: Input }], suffix: [{ type: Input }], thousandSeparator: [{ type: Input }], decimalMarker: [{ type: Input }], dropSpecialCharacters: [{ type: Input }], hiddenInput: [{ type: Input }], showMaskTyped: [{ type: Input }], placeHolderCharacter: [{ type: Input }], shownMaskExpression: [{ type: Input }], showTemplate: [{ type: Input }], clearIfNotMatch: [{ type: Input }], validation: [{ type: Input }], separatorLimit: [{ type: Input }], allowNegativeNumbers: [{ type: Input }], leadZeroDateTime: [{ type: Input }], leadZero: [{ type: Input }], triggerOnMaskChange: [{ type: Input }], apm: [{ type: Input }], inputTransformFn: [{ type: Input }], outputTransformFn: [{ type: Input }], keepCharacterPositions: [{ type: Input }], maskFilled: [{ type: Output }], onPaste: [{ type: HostListener, args: ['paste'] }], onFocus: [{ type: HostListener, args: ['focus', ['$event']] }], onModelChange: [{ type: HostListener, args: ['ngModelChange', ['$event']] }], onInput: [{ type: HostListener, args: ['input', ['$event']] }], onCompositionStart: [{ type: HostListener, args: ['compositionstart', ['$event']] }], onCompositionEnd: [{ type: HostListener, args: ['compositionend', ['$event']] }], onBlur: [{ type: HostListener, args: ['blur', ['$event']] }], onClick: [{ type: HostListener, args: ['click', ['$event']] }], onKeyDown: [{ type: HostListener, args: ['keydown', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW1hc2suZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LW1hc2stbGliL3NyYy9saWIvbmd4LW1hc2suZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMzQyxPQUFPLEVBQ0gsU0FBUyxFQUNULFlBQVksRUFDWixZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFFTixNQUFNLEdBQ1QsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUdILGFBQWEsRUFDYixpQkFBaUIsR0FHcEIsTUFBTSxnQkFBZ0IsQ0FBQztBQUd4QixPQUFPLEVBQVcsZUFBZSxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzNGLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7QUFxQnBELE1BQU0sT0FBTyxnQkFBZ0I7SUFsQjdCO1FBbUIwQixtQkFBYyxHQUE4QixFQUFFLENBQUM7UUFFckQsc0JBQWlCLEdBQWlDLEVBQUUsQ0FBQztRQUVyRCxhQUFRLEdBQXdCLEVBQUUsQ0FBQztRQUVuQyxXQUFNLEdBQXNCLEVBQUUsQ0FBQztRQUUvQixXQUFNLEdBQXNCLEVBQUUsQ0FBQztRQUUvQixzQkFBaUIsR0FBaUMsR0FBRyxDQUFDO1FBRXRELGtCQUFhLEdBQTZCLEdBQUcsQ0FBQztRQUU5QywwQkFBcUIsR0FBNEMsSUFBSSxDQUFDO1FBRXRFLGdCQUFXLEdBQWtDLElBQUksQ0FBQztRQUVsRCxrQkFBYSxHQUFvQyxJQUFJLENBQUM7UUFFdEQseUJBQW9CLEdBQTJDLElBQUksQ0FBQztRQUVwRSx3QkFBbUIsR0FBMEMsSUFBSSxDQUFDO1FBRWxFLGlCQUFZLEdBQW1DLElBQUksQ0FBQztRQUVwRCxvQkFBZSxHQUFzQyxJQUFJLENBQUM7UUFFMUQsZUFBVSxHQUFpQyxJQUFJLENBQUM7UUFFaEQsbUJBQWMsR0FBcUMsSUFBSSxDQUFDO1FBRXhELHlCQUFvQixHQUEyQyxJQUFJLENBQUM7UUFFcEUscUJBQWdCLEdBQXVDLElBQUksQ0FBQztRQUU1RCxhQUFRLEdBQStCLElBQUksQ0FBQztRQUU1Qyx3QkFBbUIsR0FBMEMsSUFBSSxDQUFDO1FBRWxFLFFBQUcsR0FBMEIsSUFBSSxDQUFDO1FBRWxDLHFCQUFnQixHQUF1QyxJQUFJLENBQUM7UUFFNUQsc0JBQWlCLEdBQXdDLElBQUksQ0FBQztRQUU5RCwyQkFBc0IsR0FBNkMsSUFBSSxDQUFDO1FBRXZFLGVBQVUsR0FBMEIsSUFBSSxZQUFZLEVBQVEsQ0FBQztRQUV0RSxlQUFVLEdBQUcsRUFBRSxDQUFDO1FBSWhCLGNBQVMsR0FBa0IsSUFBSSxDQUFDO1FBSWhDLHlCQUFvQixHQUFhLEVBQUUsQ0FBQztRQUVwQyw0QkFBdUIsR0FBWSxLQUFLLENBQUM7UUFFekMsZ0JBQVcsR0FBRyxLQUFLLENBQUM7UUFFcEIsZUFBVSxHQUFHLEtBQUssQ0FBQztRQUUzQiwrQkFBK0I7UUFDdkIsaUJBQVksR0FBRyxLQUFLLENBQUM7UUFFWixhQUFRLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRXRDLGlCQUFZLEdBQUcsTUFBTSxDQUFDLGNBQWMsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRW5ELFlBQU8sR0FBRyxNQUFNLENBQVUsZUFBZSxDQUFDLENBQUM7UUFFckQsOERBQThEO1FBQ3ZELGFBQVEsR0FBRyxDQUFDLENBQU0sRUFBRSxFQUFFLEdBQUUsQ0FBQyxDQUFDO1FBRTFCLFlBQU8sR0FBRyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUM7S0F3Z0M3QjtJQXRnQ1UsV0FBVyxDQUFDLE9BQXNCO1FBQ3JDLE1BQU0sRUFDRixjQUFjLEVBQ2QsaUJBQWlCLEVBQ2pCLFFBQVEsRUFDUixNQUFNLEVBQ04sTUFBTSxFQUNOLGlCQUFpQixFQUNqQixhQUFhLEVBQ