intl-tel-input 28.0.8 → 28.0.9

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.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * International Telephone Input v28.0.8
2
+ * International Telephone Input v28.0.9
3
3
  * git+https://github.com/jackocnr/intl-tel-input.git
4
4
  * Licensed under the MIT license
5
5
  */
@@ -3660,6 +3660,7 @@ var _factory = (() => {
3660
3660
  #numerals;
3661
3661
  //* Tracks whether the user has typed/pasted their own formatting chars, so AYT-formatting should back off.
3662
3662
  #userOverrideFormatting = false;
3663
+ #strictPasteSnapshot = null;
3663
3664
  #autoCountryDeferred;
3664
3665
  #utilsDeferred;
3665
3666
  constructor(input, customOptions = {}) {
@@ -3941,21 +3942,30 @@ var _factory = (() => {
3941
3942
  if (detail?.["isCountryChange"]) {
3942
3943
  return;
3943
3944
  }
3944
- const inputValue = this.#getTelInputValue();
3945
- if (this.#isAndroid && e?.data === "+" && separateDialCode && allowDropdown && countrySearch) {
3945
+ let inputValue = this.#getTelInputValue();
3946
+ const isPaste = e?.inputType === INPUT_TYPES.PASTE;
3947
+ const isStrictPaste = strictMode && isPaste;
3948
+ if (this.#isAndroid && !isPaste && e?.data === "+" && separateDialCode && allowDropdown && countrySearch) {
3946
3949
  this.#handleAndroidPlusKey(inputValue);
3947
3950
  return;
3948
3951
  }
3949
- if (this.#isAndroid && strictMode && (e?.data === " " || e?.data === "-" || e?.data === ".")) {
3952
+ if (this.#isAndroid && !isPaste && strictMode && (e?.data === " " || e?.data === "-" || e?.data === ".")) {
3950
3953
  this.#handleAndroidStrictReject(inputValue, e.data);
3951
3954
  return;
3952
3955
  }
3956
+ if (isStrictPaste) {
3957
+ const didRejectPaste = this.#handleStrictPasteInputEvent();
3958
+ if (didRejectPaste) {
3959
+ return;
3960
+ }
3961
+ inputValue = this.#getTelInputValue();
3962
+ }
3953
3963
  if (this.#updateCountryFromNumber(inputValue)) {
3954
3964
  this.#dispatchCountryChangeEvent();
3955
3965
  }
3956
- const isFormattingChar = e?.data && REGEX.NON_PLUS_NUMERIC.test(e.data);
3957
- const isPaste = e?.inputType === INPUT_TYPES.PASTE && inputValue;
3958
- if (isFormattingChar || isPaste && !strictMode) {
3966
+ const isFormattingChar = !isStrictPaste && e?.data && REGEX.NON_PLUS_NUMERIC.test(e.data);
3967
+ const isNonStrictPaste = isPaste && inputValue && !strictMode;
3968
+ if (isFormattingChar || isNonStrictPaste) {
3959
3969
  this.#userOverrideFormatting = true;
3960
3970
  } else if (!REGEX.NON_PLUS_NUMERIC.test(inputValue)) {
3961
3971
  this.#userOverrideFormatting = false;
@@ -4035,20 +4045,37 @@ var _factory = (() => {
4035
4045
  signal: this.#abortController.signal
4036
4046
  });
4037
4047
  }
4038
- // Handle paste events when strictMode is enabled by sanitising the pasted content before it's inserted into the input, and rejecting it entirely if it would result in an invalid number
4048
+ // In strict mode, remember paste details before the browser inserts the pasted text.
4049
+ // The actual sanitisation runs on the following input event so native paste stays enabled.
4039
4050
  #handleStrictPasteEvent = (e) => {
4040
- e.preventDefault();
4041
4051
  const input = this.#ui.telInputEl;
4042
- const selStart = input.selectionStart;
4043
- const selEnd = input.selectionEnd;
4044
4052
  const inputValue = this.#getTelInputValue();
4045
- const before = inputValue.slice(0, selStart ?? void 0);
4046
- const after = inputValue.slice(selEnd ?? void 0);
4053
+ this.#strictPasteSnapshot = {
4054
+ pastedRaw: e.clipboardData?.getData("text") ?? "",
4055
+ value: inputValue,
4056
+ selectionStart: input.selectionStart ?? inputValue.length,
4057
+ selectionEnd: input.selectionEnd ?? inputValue.length
4058
+ };
4059
+ };
4060
+ // Handle paste input events when strictMode is enabled by sanitising the pasted content after
4061
+ // the browser inserts it, and rejecting it entirely if it would result in an invalid number.
4062
+ #handleStrictPasteInputEvent() {
4063
+ const input = this.#ui.telInputEl;
4064
+ const pasteSnapshot = this.#strictPasteSnapshot;
4065
+ this.#strictPasteSnapshot = null;
4066
+ if (!pasteSnapshot) {
4067
+ return false;
4068
+ }
4069
+ const pastedRaw = pasteSnapshot.pastedRaw;
4070
+ const originalValue = pasteSnapshot.value;
4071
+ const selStart = pasteSnapshot.selectionStart;
4072
+ const selEnd = pasteSnapshot.selectionEnd;
4073
+ const before = originalValue.slice(0, selStart);
4074
+ const after = originalValue.slice(selEnd);
4047
4075
  const iso2 = this.#selectedCountry?.iso2;
4048
- const pastedRaw = e.clipboardData.getData("text");
4049
4076
  const pasted = this.#numerals.normalise(pastedRaw);
4050
4077
  const initialCharSelected = selStart === 0 && selEnd > 0;
4051
- const allowLeadingPlus = !inputValue.startsWith("+") || initialCharSelected;
4078
+ const allowLeadingPlus = !originalValue.startsWith("+") || initialCharSelected;
4052
4079
  const allowedChars = pasted.replace(REGEX.NON_PLUS_NUMERIC_GLOBAL, "");
4053
4080
  const hasLeadingPlus = allowedChars.startsWith("+");
4054
4081
  const numerics = allowedChars.replace(/\+/g, "");
@@ -4062,7 +4089,8 @@ var _factory = (() => {
4062
4089
  rejectedInput: pastedRaw,
4063
4090
  reason: "max-length"
4064
4091
  });
4065
- return;
4092
+ this.#restoreValueBeforeStrictPaste(pasteSnapshot);
4093
+ return true;
4066
4094
  }
4067
4095
  if (newValue.length > 5 && intlTelInput.utils) {
4068
4096
  let coreNumber = intlTelInput.utils.getCoreNumber(newValue, iso2);
@@ -4077,10 +4105,11 @@ var _factory = (() => {
4077
4105
  rejectedInput: pastedRaw,
4078
4106
  reason: "max-length"
4079
4107
  });
4080
- return;
4108
+ this.#restoreValueBeforeStrictPaste(pasteSnapshot);
4109
+ return true;
4081
4110
  }
4082
4111
  if (this.#maxCoreNumberLength && coreNumber.length > this.#maxCoreNumberLength) {
4083
- if (input.selectionEnd === inputValue.length) {
4112
+ if (selEnd === originalValue.length) {
4084
4113
  const trimLength = coreNumber.length - this.#maxCoreNumberLength;
4085
4114
  newValue = newValue.slice(0, newValue.length - trimLength);
4086
4115
  rejectReason = "max-length";
@@ -4091,14 +4120,14 @@ var _factory = (() => {
4091
4120
  rejectedInput: pastedRaw,
4092
4121
  reason: "max-length"
4093
4122
  });
4094
- return;
4123
+ this.#restoreValueBeforeStrictPaste(pasteSnapshot);
4124
+ return true;
4095
4125
  }
4096
4126
  }
4097
4127
  }
4098
4128
  this.#setTelInputValue(newValue);
4099
4129
  const caretPos = selStart + sanitised.length;
4100
4130
  input.setSelectionRange(caretPos, caretPos);
4101
- input.dispatchEvent(new InputEvent("input", { bubbles: true }));
4102
4131
  if (rejectReason) {
4103
4132
  if (pasted.length > 0 && sanitised.length === 0) {
4104
4133
  this.#playStrictRejectAnimation();
@@ -4109,7 +4138,15 @@ var _factory = (() => {
4109
4138
  reason: rejectReason
4110
4139
  });
4111
4140
  }
4112
- };
4141
+ return false;
4142
+ }
4143
+ #restoreValueBeforeStrictPaste(pasteSnapshot) {
4144
+ this.#setTelInputValue(pasteSnapshot.value);
4145
+ this.#ui.telInputEl.setSelectionRange(
4146
+ pasteSnapshot.selectionStart,
4147
+ pasteSnapshot.selectionEnd
4148
+ );
4149
+ }
4113
4150
  //* Adhere to the input's maxlength attr.
4114
4151
  #truncateToMaxLength(number) {
4115
4152
  const max = Number(this.#ui.telInputEl.getAttribute("maxlength"));
@@ -4749,7 +4786,7 @@ var _factory = (() => {
4749
4786
  attachUtils,
4750
4787
  startedLoadingUtils: false,
4751
4788
  startedLoadingAutoCountry: false,
4752
- version: "28.0.8",
4789
+ version: "28.0.9",
4753
4790
  NUMBER_FORMAT,
4754
4791
  NUMBER_TYPE,
4755
4792
  VALIDATION_ERROR