ngx-mask 16.2.4 → 16.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,6 +24,7 @@ const initialConfig = {
24
24
  // eslint-disable-next-line @typescript-eslint/quotes
25
25
  specialCharacters: ['-', '/', '(', ')', '.', ':', ' ', '+', ',', '@', '[', ']', '"', "'"],
26
26
  leadZeroDateTime: false,
27
+ apm: false,
27
28
  leadZero: false,
28
29
  triggerOnMaskChange: false,
29
30
  maskFilled: new EventEmitter(),
@@ -107,6 +108,7 @@ class NgxMaskApplierService {
107
108
  this.allowNegativeNumbers = this._config.allowNegativeNumbers;
108
109
  this.leadZeroDateTime = this._config.leadZeroDateTime;
109
110
  this.leadZero = this._config.leadZero;
111
+ this.apm = this._config.apm;
110
112
  this._shift = new Set();
111
113
  this.maskExpression = '';
112
114
  this.actualValue = '';
@@ -148,7 +150,9 @@ class NgxMaskApplierService {
148
150
  return res + decimals.substring(0, precision + 1);
149
151
  };
150
152
  this.percentage = (str) => {
151
- return Number(str) >= 0 && Number(str) <= 100;
153
+ const sanitizedStr = str.replace(',', '.');
154
+ const value = Number(sanitizedStr);
155
+ return !isNaN(value) && value >= 0 && value <= 100;
152
156
  };
153
157
  this.getPrecision = (maskExpression) => {
154
158
  const x = maskExpression.split("." /* MaskExpression.DOT */);
@@ -255,22 +259,24 @@ class NgxMaskApplierService {
255
259
  if (maskExpression.startsWith("percent" /* MaskExpression.PERCENT */)) {
256
260
  if (inputValue.match('[a-z]|[A-Z]') ||
257
261
  // eslint-disable-next-line no-useless-escape
258
- inputValue.match(/[-!$%^&*()_+|~=`{}\[\]:";'<>?,\/.]/)) {
262
+ (inputValue.match(/[-!$%^&*()_+|~=`{}\[\]:";'<>?,\/.]/) && !backspaced)) {
259
263
  // eslint-disable-next-line no-param-reassign
260
264
  inputValue = this._stripToDecimal(inputValue);
261
265
  const precision = this.getPrecision(maskExpression);
262
266
  // eslint-disable-next-line no-param-reassign
263
267
  inputValue = this.checkInputPrecision(inputValue, precision, this.decimalMarker);
264
268
  }
265
- if (inputValue.indexOf("." /* MaskExpression.DOT */) > 0 &&
266
- !this.percentage(inputValue.substring(0, inputValue.indexOf("." /* MaskExpression.DOT */)))) {
267
- let base = inputValue.substring(0, inputValue.indexOf("." /* MaskExpression.DOT */) - 1);
269
+ const decimalMarker = typeof this.decimalMarker === 'string' ? this.decimalMarker : "." /* MaskExpression.DOT */;
270
+ if (inputValue.indexOf(decimalMarker) > 0 &&
271
+ !this.percentage(inputValue.substring(0, inputValue.indexOf(decimalMarker)))) {
272
+ let base = inputValue.substring(0, inputValue.indexOf(decimalMarker) - 1);
268
273
  if (this.allowNegativeNumbers &&
269
- inputValue.slice(cursor, cursor + 1) === "-" /* MaskExpression.MINUS */) {
270
- base = inputValue.substring(0, inputValue.indexOf("." /* MaskExpression.DOT */));
274
+ inputValue.slice(cursor, cursor + 1) === "-" /* MaskExpression.MINUS */ &&
275
+ !backspaced) {
276
+ base = inputValue.substring(0, inputValue.indexOf(decimalMarker));
271
277
  }
272
278
  // eslint-disable-next-line no-param-reassign
273
- inputValue = `${base}${inputValue.substring(inputValue.indexOf("." /* MaskExpression.DOT */), inputValue.length)}`;
279
+ inputValue = `${base}${inputValue.substring(inputValue.indexOf(decimalMarker), inputValue.length)}`;
274
280
  }
275
281
  let value = '';
276
282
  this.allowNegativeNumbers &&
@@ -343,6 +349,12 @@ class NgxMaskApplierService {
343
349
  _shift++;
344
350
  } while (_shift < shiftStep);
345
351
  }
352
+ else if (result[position - 1] === this.decimalMarker ||
353
+ shiftStep === -4 ||
354
+ shiftStep === -3) {
355
+ this._shift.clear();
356
+ this._shift.add(position - 1);
357
+ }
346
358
  else if ((commaShift !== 0 &&
347
359
  position > 0 &&
348
360
  !(result.indexOf("," /* MaskExpression.COMMA */) >= position && position > 3)) ||
@@ -392,7 +404,7 @@ class NgxMaskApplierService {
392
404
  }
393
405
  else if (this._checkSymbolMask(inputSymbol, maskExpression[cursor] ?? "" /* MaskExpression.EMPTY_STRING */)) {
394
406
  if (maskExpression[cursor] === "H" /* MaskExpression.HOURS */) {
395
- if (Number(inputSymbol) > 2) {
407
+ if (this.apm ? Number(inputSymbol) > 9 : Number(inputSymbol) > 2) {
396
408
  // eslint-disable-next-line no-param-reassign
397
409
  position = position + 1;
398
410
  cursor += 1;
@@ -405,13 +417,20 @@ class NgxMaskApplierService {
405
417
  }
406
418
  }
407
419
  if (maskExpression[cursor] === "h" /* MaskExpression.HOUR */) {
408
- if ((result === '2' && Number(inputSymbol) > 3) ||
409
- ((result.slice(cursor - 2, cursor) === '2' ||
410
- result.slice(cursor - 3, cursor) === '2' ||
411
- result.slice(cursor - 4, cursor) === '2' ||
412
- result.slice(cursor - 1, cursor) === '2') &&
413
- Number(inputSymbol) > 3 &&
414
- cursor > 10)) {
420
+ if (this.apm
421
+ ? (result.length === 1 && Number(result) > 1) ||
422
+ (result === '1' && Number(inputSymbol) > 1) ||
423
+ (inputValue.slice(cursor - 1, cursor).length === 1 &&
424
+ Number(inputValue.slice(cursor - 1, cursor)) > 1) ||
425
+ (inputValue.slice(cursor - 1, cursor) === '1' &&
426
+ Number(inputSymbol) > 1)
427
+ : (result === '2' && Number(inputSymbol) > 3) ||
428
+ ((result.slice(cursor - 2, cursor) === '2' ||
429
+ result.slice(cursor - 3, cursor) === '2' ||
430
+ result.slice(cursor - 4, cursor) === '2' ||
431
+ result.slice(cursor - 1, cursor) === '2') &&
432
+ Number(inputSymbol) > 3 &&
433
+ cursor > 10)) {
415
434
  // eslint-disable-next-line no-param-reassign
416
435
  position = position + 1;
417
436
  cursor += 1;
@@ -515,7 +534,7 @@ class NgxMaskApplierService {
515
534
  day2monthPaste ||
516
535
  day1monthPaste ||
517
536
  day2monthInput ||
518
- day2monthInputDot) {
537
+ (day2monthInputDot && !this.leadZeroDateTime)) {
519
538
  // eslint-disable-next-line no-param-reassign
520
539
  position = position + 1;
521
540
  cursor += 1;
@@ -673,7 +692,9 @@ class NgxMaskApplierService {
673
692
  }));
674
693
  }
675
694
  _splitPercentZero(value) {
676
- const decimalIndex = value.indexOf("." /* MaskExpression.DOT */);
695
+ const decimalIndex = typeof this.decimalMarker === 'string'
696
+ ? value.indexOf(this.decimalMarker)
697
+ : value.indexOf("." /* MaskExpression.DOT */);
677
698
  if (decimalIndex === -1) {
678
699
  const parsedValue = parseInt(value, 10);
679
700
  return isNaN(parsedValue) ? "" /* MaskExpression.EMPTY_STRING */ : parsedValue.toString();
@@ -682,9 +703,10 @@ class NgxMaskApplierService {
682
703
  const integerPart = parseInt(value.substring(0, decimalIndex), 10);
683
704
  const decimalPart = value.substring(decimalIndex + 1);
684
705
  const integerString = isNaN(integerPart) ? '' : integerPart.toString();
706
+ const decimal = typeof this.decimalMarker === 'string' ? this.decimalMarker : "." /* MaskExpression.DOT */;
685
707
  return integerString === "" /* MaskExpression.EMPTY_STRING */
686
708
  ? "" /* MaskExpression.EMPTY_STRING */
687
- : integerString + "." /* MaskExpression.DOT */ + decimalPart;
709
+ : integerString + decimal + decimalPart;
688
710
  }
689
711
  }
690
712
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: NgxMaskApplierService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -709,6 +731,9 @@ class NgxMaskService extends NgxMaskApplierService {
709
731
  this.maskChanged = false;
710
732
  this._maskExpressionArray = [];
711
733
  this.triggerOnMaskChange = false;
734
+ this._emitValue = false;
735
+ this._previousValue = '';
736
+ this._currentValue = '';
712
737
  // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-explicit-any
713
738
  this.onChange = (_) => { };
714
739
  this.document = inject(DOCUMENT);
@@ -741,7 +766,9 @@ class NgxMaskService extends NgxMaskApplierService {
741
766
  : "" /* MaskExpression.EMPTY_STRING */;
742
767
  let newInputValue = '';
743
768
  if (this.hiddenInput !== undefined && !this.writingValue) {
744
- let actualResult = this.actualValue.split("" /* MaskExpression.EMPTY_STRING */);
769
+ let actualResult = inputValue && inputValue.length === 1
770
+ ? inputValue.split("" /* MaskExpression.EMPTY_STRING */)
771
+ : this.actualValue.split("" /* MaskExpression.EMPTY_STRING */);
745
772
  // eslint-disable @typescript-eslint/no-unused-expressions
746
773
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions
747
774
  if (typeof this.selStart === 'object' && typeof this.selEnd === 'object') {
@@ -775,7 +802,7 @@ class NgxMaskService extends NgxMaskApplierService {
775
802
  ? this.shiftTypedSymbols(actualResult.join("" /* MaskExpression.EMPTY_STRING */))
776
803
  : inputValue;
777
804
  }
778
- if (justPasted && this.hiddenInput) {
805
+ if (justPasted && (this.hiddenInput || !this.hiddenInput)) {
779
806
  newInputValue = inputValue;
780
807
  }
781
808
  if (this.deletedSpecialCharacter && position) {
@@ -790,7 +817,9 @@ class NgxMaskService extends NgxMaskApplierService {
790
817
  // eslint-disable-next-line no-param-reassign
791
818
  this.deletedSpecialCharacter = false;
792
819
  }
793
- if (this.showMaskTyped && this.placeHolderCharacter.length === 1) {
820
+ if (this.showMaskTyped &&
821
+ this.placeHolderCharacter.length === 1 &&
822
+ !this.leadZeroDateTime) {
794
823
  // eslint-disable-next-line no-param-reassign
795
824
  inputValue = this.removeMask(inputValue);
796
825
  }
@@ -815,7 +844,12 @@ class NgxMaskService extends NgxMaskApplierService {
815
844
  this.specialCharacters = this.specialCharacters.filter((item) => !this._compareOrIncludes(item, this.decimalMarker, this.thousandSeparator) //item !== this.decimalMarker, // !
816
845
  );
817
846
  }
818
- this.formControlResult(result);
847
+ if (result || result === '') {
848
+ this._previousValue = this._currentValue;
849
+ this._currentValue = result;
850
+ this._emitValue = this._previousValue !== this._currentValue || this.maskChanged;
851
+ }
852
+ this._emitValue ? this.formControlResult(result) : '';
819
853
  if (!this.showMaskTyped || (this.showMaskTyped && this.hiddenInput)) {
820
854
  if (this.hiddenInput) {
821
855
  if (backspaced) {
@@ -1156,6 +1190,11 @@ class NgxMaskService extends NgxMaskApplierService {
1156
1190
  if (result === "" /* MaskExpression.EMPTY_STRING */) {
1157
1191
  return result;
1158
1192
  }
1193
+ if (this.maskExpression.startsWith("percent" /* MaskExpression.PERCENT */) &&
1194
+ this.decimalMarker === "," /* MaskExpression.COMMA */) {
1195
+ // eslint-disable-next-line no-param-reassign
1196
+ result = result.replace("," /* MaskExpression.COMMA */, "." /* MaskExpression.DOT */);
1197
+ }
1159
1198
  const separatorPrecision = this._retrieveSeparatorPrecision(this.maskExpression);
1160
1199
  const separatorValue = this._replaceDecimalMarkerToDot(this._retrieveSeparatorValue(result));
1161
1200
  if (!this.isNumberValue) {
@@ -1279,6 +1318,7 @@ class NgxMaskDirective {
1279
1318
  this.leadZeroDateTime = null;
1280
1319
  this.leadZero = null;
1281
1320
  this.triggerOnMaskChange = null;
1321
+ this.apm = null;
1282
1322
  this.maskFilled = new EventEmitter();
1283
1323
  this._maskValue = '';
1284
1324
  this._position = null;
@@ -1295,7 +1335,7 @@ class NgxMaskDirective {
1295
1335
  this.onTouch = () => { };
1296
1336
  }
1297
1337
  ngOnChanges(changes) {
1298
- const { maskExpression, specialCharacters, patterns, prefix, suffix, thousandSeparator, decimalMarker, dropSpecialCharacters, hiddenInput, showMaskTyped, placeHolderCharacter, shownMaskExpression, showTemplate, clearIfNotMatch, validation, separatorLimit, allowNegativeNumbers, leadZeroDateTime, leadZero, triggerOnMaskChange, } = changes;
1338
+ const { maskExpression, specialCharacters, patterns, prefix, suffix, thousandSeparator, decimalMarker, dropSpecialCharacters, hiddenInput, showMaskTyped, placeHolderCharacter, shownMaskExpression, showTemplate, clearIfNotMatch, validation, separatorLimit, allowNegativeNumbers, leadZeroDateTime, leadZero, triggerOnMaskChange, apm, } = changes;
1299
1339
  if (maskExpression) {
1300
1340
  if (maskExpression.currentValue !== maskExpression.previousValue &&
1301
1341
  !maskExpression.firstChange) {
@@ -1335,6 +1375,9 @@ class NgxMaskDirective {
1335
1375
  if (patterns && patterns.currentValue) {
1336
1376
  this._maskService.patterns = patterns.currentValue;
1337
1377
  }
1378
+ if (apm && apm.currentValue) {
1379
+ this._maskService.apm = apm.currentValue;
1380
+ }
1338
1381
  if (prefix) {
1339
1382
  this._maskService.prefix = prefix.currentValue;
1340
1383
  }
@@ -1529,6 +1572,16 @@ class NgxMaskDirective {
1529
1572
  if (this._code === "Delete" /* MaskExpression.DELETE */ && "separator" /* MaskExpression.SEPARATOR */) {
1530
1573
  this._maskService.deletedSpecialCharacter = true;
1531
1574
  }
1575
+ if (this._inputValue.length >= this._maskService.maskExpression.length - 1 &&
1576
+ this._code !== "Backspace" /* MaskExpression.BACKSPACE */ &&
1577
+ this._maskService.maskExpression === "d0/M0/0000" /* MaskExpression.DAYS_MONTHS_YEARS */ &&
1578
+ position < 10) {
1579
+ const inputSymbol = this._inputValue.slice(position - 1, position);
1580
+ el.value =
1581
+ this._inputValue.slice(0, position - 1) +
1582
+ inputSymbol +
1583
+ this._inputValue.slice(position + 1);
1584
+ }
1532
1585
  this._maskService.applyValueChanges(position, this._justPasted, this._code === "Backspace" /* MaskExpression.BACKSPACE */ || this._code === "Delete" /* MaskExpression.DELETE */, (shift, _backspaceShift) => {
1533
1586
  this._justPasted = false;
1534
1587
  caretShift = shift;
@@ -1584,10 +1637,16 @@ class NgxMaskDirective {
1584
1637
  const maskExpression = this._maskService.maskExpression;
1585
1638
  const precision = Number(this._maskService.maskExpression.slice(maskExpression.length - 1, maskExpression.length));
1586
1639
  if (precision > 1) {
1640
+ el.value = this.suffix ? el.value.split(this.suffix).join('') : el.value;
1587
1641
  const decimalPart = el.value.split(this.decimalMarker)[1];
1588
1642
  el.value = el.value.includes(this.decimalMarker)
1589
- ? el.value + '0'.repeat(precision - decimalPart.length)
1590
- : el.value + this.decimalMarker + '0'.repeat(precision);
1643
+ ? el.value +
1644
+ "0" /* MaskExpression.NUMBER_ZERO */.repeat(precision - decimalPart.length) +
1645
+ this.suffix
1646
+ : el.value +
1647
+ this.decimalMarker +
1648
+ "0" /* MaskExpression.NUMBER_ZERO */.repeat(precision) +
1649
+ this.suffix;
1591
1650
  this._maskService.actualValue = el.value;
1592
1651
  }
1593
1652
  }
@@ -1885,7 +1944,7 @@ class NgxMaskDirective {
1885
1944
  });
1886
1945
  }
1887
1946
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: NgxMaskDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1888
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.1", 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" }, outputs: { maskFilled: "maskFilled" }, host: { listeners: { "paste": "onPaste()", "ngModelChange": "onModelChange($event)", "input": "onInput($event)", "compositionstart": "onCompositionStart($event)", "compositionend": "onCompositionEnd($event)", "blur": "onBlur($event)", "click": "onClick($event)", "keydown": "onKeyDown($event)" } }, providers: [
1947
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.1", 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" }, outputs: { maskFilled: "maskFilled" }, host: { listeners: { "paste": "onPaste()", "ngModelChange": "onModelChange($event)", "input": "onInput($event)", "compositionstart": "onCompositionStart($event)", "compositionend": "onCompositionEnd($event)", "blur": "onBlur($event)", "click": "onClick($event)", "keydown": "onKeyDown($event)" } }, providers: [
1889
1948
  {
1890
1949
  provide: NG_VALUE_ACCESSOR,
1891
1950
  useExisting: NgxMaskDirective,
@@ -1960,6 +2019,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImpor
1960
2019
  type: Input
1961
2020
  }], triggerOnMaskChange: [{
1962
2021
  type: Input
2022
+ }], apm: [{
2023
+ type: Input
1963
2024
  }], maskFilled: [{
1964
2025
  type: Output
1965
2026
  }], onPaste: [{