intl-tel-input 28.0.8 → 28.1.0

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.
Files changed (64) hide show
  1. package/dist/js/data.js +1 -1
  2. package/dist/js/data.min.js +1 -1
  3. package/dist/js/i18n/ar.js +3 -3
  4. package/dist/js/i18n/bg.js +2 -2
  5. package/dist/js/i18n/bn.js +2 -2
  6. package/dist/js/i18n/bs.js +2 -2
  7. package/dist/js/i18n/ca.js +2 -2
  8. package/dist/js/i18n/cs.js +2 -2
  9. package/dist/js/i18n/da.js +2 -2
  10. package/dist/js/i18n/de.js +2 -2
  11. package/dist/js/i18n/el.js +2 -2
  12. package/dist/js/i18n/es.js +2 -2
  13. package/dist/js/i18n/et.js +2 -2
  14. package/dist/js/i18n/fa.js +2 -5
  15. package/dist/js/i18n/fi.js +2 -2
  16. package/dist/js/i18n/fil.js +16 -0
  17. package/dist/js/i18n/fr.js +2 -2
  18. package/dist/js/i18n/he.js +19 -0
  19. package/dist/js/i18n/hi.js +2 -2
  20. package/dist/js/i18n/hr.js +2 -2
  21. package/dist/js/i18n/hu.js +2 -5
  22. package/dist/js/i18n/hy.js +19 -0
  23. package/dist/js/i18n/id.js +2 -5
  24. package/dist/js/i18n/index.js +9 -0
  25. package/dist/js/i18n/is.js +21 -0
  26. package/dist/js/i18n/it.js +2 -2
  27. package/dist/js/i18n/ja.js +2 -5
  28. package/dist/js/i18n/kn.js +2 -2
  29. package/dist/js/i18n/ko.js +2 -5
  30. package/dist/js/i18n/lt.js +2 -2
  31. package/dist/js/i18n/lv.js +24 -0
  32. package/dist/js/i18n/mk.js +21 -0
  33. package/dist/js/i18n/mr.js +2 -2
  34. package/dist/js/i18n/ms.js +16 -0
  35. package/dist/js/i18n/nl.js +2 -2
  36. package/dist/js/i18n/no.js +2 -2
  37. package/dist/js/i18n/pl.js +2 -2
  38. package/dist/js/i18n/pt.js +2 -2
  39. package/dist/js/i18n/ro.js +4 -4
  40. package/dist/js/i18n/ru.js +2 -2
  41. package/dist/js/i18n/sk.js +5 -8
  42. package/dist/js/i18n/sl.js +2 -2
  43. package/dist/js/i18n/sq.js +2 -2
  44. package/dist/js/i18n/sr.js +2 -2
  45. package/dist/js/i18n/sv.js +2 -5
  46. package/dist/js/i18n/sw.js +19 -0
  47. package/dist/js/i18n/ta.js +19 -0
  48. package/dist/js/i18n/te.js +2 -2
  49. package/dist/js/i18n/th.js +2 -5
  50. package/dist/js/i18n/tr.js +2 -5
  51. package/dist/js/i18n/uk.js +2 -2
  52. package/dist/js/i18n/ur.js +2 -2
  53. package/dist/js/i18n/uz.js +2 -5
  54. package/dist/js/i18n/vi.js +2 -5
  55. package/dist/js/i18n/zh-hk.js +2 -5
  56. package/dist/js/i18n/zh.js +2 -5
  57. package/dist/js/i18n.d.ts +49 -31
  58. package/dist/js/intlTelInput.js +90 -47
  59. package/dist/js/intlTelInput.min.js +2 -2
  60. package/dist/js/intlTelInput.mjs +89 -46
  61. package/dist/js/intlTelInputWithUtils.js +90 -47
  62. package/dist/js/intlTelInputWithUtils.min.js +2 -2
  63. package/dist/js/intlTelInputWithUtils.mjs +89 -46
  64. package/package.json +1 -1
@@ -1767,7 +1767,8 @@ var CLASSES = {
1767
1767
  FLAG: "iti__flag",
1768
1768
  LOADING: "iti__loading",
1769
1769
  COUNTRY_ITEM: "iti__country",
1770
- HIGHLIGHT: "iti__highlight"
1770
+ HIGHLIGHT: "iti__highlight",
1771
+ STRICT_REJECT_ANIMATION: "iti__strict-reject-animation"
1771
1772
  };
1772
1773
  var KEYS = {
1773
1774
  ARROW_UP: "ArrowUp",
@@ -3123,7 +3124,6 @@ var UI = class _UI {
3123
3124
  }
3124
3125
  //* Keyboard navigation while the dropdown is open: arrow keys navigate, hidden-search keys filter,
3125
3126
  //* and enter/escape invoke the caller's callbacks (which handle country selection / dropdown close).
3126
- //* Listens on document because key events go there when no input has focus.
3127
3127
  //* Uses keydown rather than keypress so non-char keys (arrow, esc) fire and so holding a key repeats.
3128
3128
  #bindDropdownKeydownListener(signal, onEnter, onEscape) {
3129
3129
  let query = "";
@@ -3147,7 +3147,7 @@ var UI = class _UI {
3147
3147
  this.#selectedCountryEl.focus();
3148
3148
  }
3149
3149
  }
3150
- if (!this.#options.countrySearch && e.target !== this.telInputEl && REGEX.HIDDEN_SEARCH_CHAR.test(e.key)) {
3150
+ if (!this.#options.countrySearch && REGEX.HIDDEN_SEARCH_CHAR.test(e.key)) {
3151
3151
  e.stopPropagation();
3152
3152
  if (queryTimer) {
3153
3153
  clearTimeout(queryTimer);
@@ -3159,7 +3159,8 @@ var UI = class _UI {
3159
3159
  }, TIMINGS.HIDDEN_SEARCH_RESET_MS);
3160
3160
  }
3161
3161
  };
3162
- document.addEventListener("keydown", handleKeydown, { signal });
3162
+ this.#selectedCountryEl?.addEventListener("keydown", handleKeydown, { signal });
3163
+ this.#dropdownContentEl?.addEventListener("keydown", handleKeydown, { signal });
3163
3164
  }
3164
3165
  //* Wire up country search input listener: typing filters the list, the clear button resets it.
3165
3166
  #bindSearchInputListener(signal) {
@@ -3324,6 +3325,26 @@ var UI = class _UI {
3324
3325
  setLoading(isLoading) {
3325
3326
  this.#selectedFlagEl.classList.toggle(CLASSES.LOADING, isLoading);
3326
3327
  }
3328
+ //* Play the strict-reject animation (shake, or background-colour flash under prefers-reduced-motion) on the wrapper.
3329
+ //* Called when strictMode rejects the whole input (keystroke, or whole paste).
3330
+ //* Uses the wrapper (not the input) so any separateDialCode / country button move together with the input.
3331
+ playStrictRejectAnimation() {
3332
+ if (!this.#options.strictRejectAnimation) {
3333
+ return;
3334
+ }
3335
+ const wrapperEl = this.telInputEl.parentElement;
3336
+ if (!wrapperEl) {
3337
+ return;
3338
+ }
3339
+ wrapperEl.classList.remove(CLASSES.STRICT_REJECT_ANIMATION);
3340
+ void wrapperEl.offsetWidth;
3341
+ wrapperEl.classList.add(CLASSES.STRICT_REJECT_ANIMATION);
3342
+ wrapperEl.addEventListener(
3343
+ "animationend",
3344
+ () => wrapperEl.classList.remove(CLASSES.STRICT_REJECT_ANIMATION),
3345
+ { once: true }
3346
+ );
3347
+ }
3327
3348
  isLoading() {
3328
3349
  return this.#selectedFlagEl.classList.contains(CLASSES.LOADING);
3329
3350
  }
@@ -3629,6 +3650,7 @@ var Iti = class _Iti {
3629
3650
  #numerals;
3630
3651
  //* Tracks whether the user has typed/pasted their own formatting chars, so AYT-formatting should back off.
3631
3652
  #userOverrideFormatting = false;
3653
+ #strictPasteSnapshot = null;
3632
3654
  #autoCountryDeferred;
3633
3655
  #utilsDeferred;
3634
3656
  constructor(input, customOptions = {}) {
@@ -3839,7 +3861,7 @@ var Iti = class _Iti {
3839
3861
  #handleAndroidStrictReject(inputValue, rejectedInput) {
3840
3862
  const newCaretPos = this.#removeJustTypedChar(inputValue);
3841
3863
  this.#ui.telInputEl.setSelectionRange(newCaretPos, newCaretPos);
3842
- this.#playStrictRejectAnimation();
3864
+ this.#ui.playStrictRejectAnimation();
3843
3865
  this.#dispatchEvent(EVENTS.STRICT_REJECT, {
3844
3866
  source: "key",
3845
3867
  rejectedInput,
@@ -3910,21 +3932,30 @@ var Iti = class _Iti {
3910
3932
  if (detail?.["isCountryChange"]) {
3911
3933
  return;
3912
3934
  }
3913
- const inputValue = this.#getTelInputValue();
3914
- if (this.#isAndroid && e?.data === "+" && separateDialCode && allowDropdown && countrySearch) {
3935
+ let inputValue = this.#getTelInputValue();
3936
+ const isPaste = e?.inputType === INPUT_TYPES.PASTE;
3937
+ const isStrictPaste = strictMode && isPaste;
3938
+ if (this.#isAndroid && !isPaste && e?.data === "+" && separateDialCode && allowDropdown && countrySearch) {
3915
3939
  this.#handleAndroidPlusKey(inputValue);
3916
3940
  return;
3917
3941
  }
3918
- if (this.#isAndroid && strictMode && (e?.data === " " || e?.data === "-" || e?.data === ".")) {
3942
+ if (this.#isAndroid && !isPaste && strictMode && (e?.data === " " || e?.data === "-" || e?.data === ".")) {
3919
3943
  this.#handleAndroidStrictReject(inputValue, e.data);
3920
3944
  return;
3921
3945
  }
3946
+ if (isStrictPaste) {
3947
+ const didRejectPaste = this.#handleStrictPasteInputEvent();
3948
+ if (didRejectPaste) {
3949
+ return;
3950
+ }
3951
+ inputValue = this.#getTelInputValue();
3952
+ }
3922
3953
  if (this.#updateCountryFromNumber(inputValue)) {
3923
3954
  this.#dispatchCountryChangeEvent();
3924
3955
  }
3925
- const isFormattingChar = e?.data && REGEX.NON_PLUS_NUMERIC.test(e.data);
3926
- const isPaste = e?.inputType === INPUT_TYPES.PASTE && inputValue;
3927
- if (isFormattingChar || isPaste && !strictMode) {
3956
+ const isFormattingChar = !isStrictPaste && e?.data && REGEX.NON_PLUS_NUMERIC.test(e.data);
3957
+ const isNonStrictPaste = isPaste && inputValue && !strictMode;
3958
+ if (isFormattingChar || isNonStrictPaste) {
3928
3959
  this.#userOverrideFormatting = true;
3929
3960
  } else if (!REGEX.NON_PLUS_NUMERIC.test(inputValue)) {
3930
3961
  this.#userOverrideFormatting = false;
@@ -3987,7 +4018,7 @@ var Iti = class _Iti {
3987
4018
  const newCountry = this.#resolveCountryChangeFromNumber(newFullNumber);
3988
4019
  const isChangingDialCode = newCountry !== null;
3989
4020
  if (!isAllowedChar || hasExceededMaxLength && !isChangingDialCode && !isInitialPlus) {
3990
- this.#playStrictRejectAnimation();
4021
+ this.#ui.playStrictRejectAnimation();
3991
4022
  this.#dispatchEvent(EVENTS.STRICT_REJECT, {
3992
4023
  source: "key",
3993
4024
  rejectedInput: e.key,
@@ -4004,20 +4035,37 @@ var Iti = class _Iti {
4004
4035
  signal: this.#abortController.signal
4005
4036
  });
4006
4037
  }
4007
- // 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
4038
+ // In strict mode, remember paste details before the browser inserts the pasted text.
4039
+ // The actual sanitisation runs on the following input event so native paste stays enabled.
4008
4040
  #handleStrictPasteEvent = (e) => {
4009
- e.preventDefault();
4010
4041
  const input = this.#ui.telInputEl;
4011
- const selStart = input.selectionStart;
4012
- const selEnd = input.selectionEnd;
4013
4042
  const inputValue = this.#getTelInputValue();
4014
- const before = inputValue.slice(0, selStart ?? void 0);
4015
- const after = inputValue.slice(selEnd ?? void 0);
4043
+ this.#strictPasteSnapshot = {
4044
+ pastedRaw: e.clipboardData?.getData("text") ?? "",
4045
+ value: inputValue,
4046
+ selectionStart: input.selectionStart ?? inputValue.length,
4047
+ selectionEnd: input.selectionEnd ?? inputValue.length
4048
+ };
4049
+ };
4050
+ // Handle paste input events when strictMode is enabled by sanitising the pasted content after
4051
+ // the browser inserts it, and rejecting it entirely if it would result in an invalid number.
4052
+ #handleStrictPasteInputEvent() {
4053
+ const input = this.#ui.telInputEl;
4054
+ const pasteSnapshot = this.#strictPasteSnapshot;
4055
+ this.#strictPasteSnapshot = null;
4056
+ if (!pasteSnapshot) {
4057
+ return false;
4058
+ }
4059
+ const pastedRaw = pasteSnapshot.pastedRaw;
4060
+ const originalValue = pasteSnapshot.value;
4061
+ const selStart = pasteSnapshot.selectionStart;
4062
+ const selEnd = pasteSnapshot.selectionEnd;
4063
+ const before = originalValue.slice(0, selStart);
4064
+ const after = originalValue.slice(selEnd);
4016
4065
  const iso2 = this.#selectedCountry?.iso2;
4017
- const pastedRaw = e.clipboardData.getData("text");
4018
4066
  const pasted = this.#numerals.normalise(pastedRaw);
4019
4067
  const initialCharSelected = selStart === 0 && selEnd > 0;
4020
- const allowLeadingPlus = !inputValue.startsWith("+") || initialCharSelected;
4068
+ const allowLeadingPlus = !originalValue.startsWith("+") || initialCharSelected;
4021
4069
  const allowedChars = pasted.replace(REGEX.NON_PLUS_NUMERIC_GLOBAL, "");
4022
4070
  const hasLeadingPlus = allowedChars.startsWith("+");
4023
4071
  const numerics = allowedChars.replace(/\+/g, "");
@@ -4025,13 +4073,14 @@ var Iti = class _Iti {
4025
4073
  let newValue = before + sanitised + after;
4026
4074
  let rejectReason = sanitised !== pasted ? "invalid" : null;
4027
4075
  if (newValue.length > 30) {
4028
- this.#playStrictRejectAnimation();
4076
+ this.#ui.playStrictRejectAnimation();
4029
4077
  this.#dispatchEvent(EVENTS.STRICT_REJECT, {
4030
4078
  source: "paste",
4031
4079
  rejectedInput: pastedRaw,
4032
4080
  reason: "max-length"
4033
4081
  });
4034
- return;
4082
+ this.#restoreValueBeforeStrictPaste(pasteSnapshot);
4083
+ return true;
4035
4084
  }
4036
4085
  if (newValue.length > 5 && intlTelInput.utils) {
4037
4086
  let coreNumber = intlTelInput.utils.getCoreNumber(newValue, iso2);
@@ -4040,37 +4089,38 @@ var Iti = class _Iti {
4040
4089
  coreNumber = intlTelInput.utils.getCoreNumber(newValue, iso2);
4041
4090
  }
4042
4091
  if (!coreNumber) {
4043
- this.#playStrictRejectAnimation();
4092
+ this.#ui.playStrictRejectAnimation();
4044
4093
  this.#dispatchEvent(EVENTS.STRICT_REJECT, {
4045
4094
  source: "paste",
4046
4095
  rejectedInput: pastedRaw,
4047
4096
  reason: "max-length"
4048
4097
  });
4049
- return;
4098
+ this.#restoreValueBeforeStrictPaste(pasteSnapshot);
4099
+ return true;
4050
4100
  }
4051
4101
  if (this.#maxCoreNumberLength && coreNumber.length > this.#maxCoreNumberLength) {
4052
- if (input.selectionEnd === inputValue.length) {
4102
+ if (selEnd === originalValue.length) {
4053
4103
  const trimLength = coreNumber.length - this.#maxCoreNumberLength;
4054
4104
  newValue = newValue.slice(0, newValue.length - trimLength);
4055
4105
  rejectReason = "max-length";
4056
4106
  } else {
4057
- this.#playStrictRejectAnimation();
4107
+ this.#ui.playStrictRejectAnimation();
4058
4108
  this.#dispatchEvent(EVENTS.STRICT_REJECT, {
4059
4109
  source: "paste",
4060
4110
  rejectedInput: pastedRaw,
4061
4111
  reason: "max-length"
4062
4112
  });
4063
- return;
4113
+ this.#restoreValueBeforeStrictPaste(pasteSnapshot);
4114
+ return true;
4064
4115
  }
4065
4116
  }
4066
4117
  }
4067
4118
  this.#setTelInputValue(newValue);
4068
4119
  const caretPos = selStart + sanitised.length;
4069
4120
  input.setSelectionRange(caretPos, caretPos);
4070
- input.dispatchEvent(new InputEvent("input", { bubbles: true }));
4071
4121
  if (rejectReason) {
4072
4122
  if (pasted.length > 0 && sanitised.length === 0) {
4073
- this.#playStrictRejectAnimation();
4123
+ this.#ui.playStrictRejectAnimation();
4074
4124
  }
4075
4125
  this.#dispatchEvent(EVENTS.STRICT_REJECT, {
4076
4126
  source: "paste",
@@ -4078,27 +4128,20 @@ var Iti = class _Iti {
4078
4128
  reason: rejectReason
4079
4129
  });
4080
4130
  }
4081
- };
4131
+ return false;
4132
+ }
4133
+ #restoreValueBeforeStrictPaste(pasteSnapshot) {
4134
+ this.#setTelInputValue(pasteSnapshot.value);
4135
+ this.#ui.telInputEl.setSelectionRange(
4136
+ pasteSnapshot.selectionStart,
4137
+ pasteSnapshot.selectionEnd
4138
+ );
4139
+ }
4082
4140
  //* Adhere to the input's maxlength attr.
4083
4141
  #truncateToMaxLength(number) {
4084
4142
  const max = Number(this.#ui.telInputEl.getAttribute("maxlength"));
4085
4143
  return max && number.length > max ? number.substring(0, max) : number;
4086
4144
  }
4087
- //* Play the strict-reject animation (shake, or background-colour flash under prefers-reduced-motion) on the wrapper.
4088
- //* Called when strictMode rejects the whole input (keystroke, or whole paste).
4089
- //* Uses the wrapper (not the input) so any separateDialCode / country button move together with the input.
4090
- #playStrictRejectAnimation() {
4091
- if (!this.#options.strictRejectAnimation) {
4092
- return;
4093
- }
4094
- const wrapperEl = this.#ui.telInputEl.parentElement;
4095
- if (!wrapperEl) {
4096
- return;
4097
- }
4098
- wrapperEl.classList.remove("iti__strict-reject-animation");
4099
- void wrapperEl.offsetWidth;
4100
- wrapperEl.classList.add("iti__strict-reject-animation");
4101
- }
4102
4145
  //* Trigger a custom event on the input (typed via ItiEventMap).
4103
4146
  #dispatchEvent(name, detailProps = {}) {
4104
4147
  const e = new CustomEvent(name, {
@@ -4718,7 +4761,7 @@ var intlTelInput = Object.assign(
4718
4761
  attachUtils,
4719
4762
  startedLoadingUtils: false,
4720
4763
  startedLoadingAutoCountry: false,
4721
- version: "28.0.8",
4764
+ version: "28.1.0",
4722
4765
  NUMBER_FORMAT,
4723
4766
  NUMBER_TYPE,
4724
4767
  VALIDATION_ERROR
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intl-tel-input",
3
- "version": "28.0.8",
3
+ "version": "28.1.0",
4
4
  "description": "A JavaScript library for entering, formatting, and validating international telephone numbers",
5
5
  "type": "module",
6
6
  "license": "MIT",