intl-tel-input 27.2.0 → 27.3.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.
@@ -1,4 +1,4 @@
1
- // dist/js/intlTelInput.mjs
1
+ // src/js/data.ts
2
2
  var rawCountryData = [
3
3
  [
4
4
  "af",
@@ -1755,6 +1755,8 @@ for (const c of rawCountryData) {
1755
1755
  var iso2Set = new Set(allCountries.map((c) => c.iso2));
1756
1756
  var isIso2 = (val) => iso2Set.has(val);
1757
1757
  var data_default = allCountries;
1758
+
1759
+ // src/js/constants.ts
1758
1760
  var EVENTS = {
1759
1761
  OPEN_COUNTRY_DROPDOWN: "open:countrydropdown",
1760
1762
  CLOSE_COUNTRY_DROPDOWN: "close:countrydropdown",
@@ -1879,6 +1881,8 @@ var ARIA = {
1879
1881
  AUTOCOMPLETE: "aria-autocomplete",
1880
1882
  MODAL: "aria-modal"
1881
1883
  };
1884
+
1885
+ // src/js/i18n/en.ts
1882
1886
  var interfaceTranslations = {
1883
1887
  selectedCountryAriaLabel: "Change country for phone number, currently selected ${countryName} (${dialCode})",
1884
1888
  noCountrySelected: "Select country for phone number",
@@ -1897,6 +1901,8 @@ var interfaceTranslations = {
1897
1901
  }
1898
1902
  };
1899
1903
  var en_default = interfaceTranslations;
1904
+
1905
+ // src/js/core/options.ts
1900
1906
  var mediaQuery = (q) => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(q).matches;
1901
1907
  var isNarrowViewport = () => mediaQuery(`(max-width: ${LAYOUT.NARROW_VIEWPORT_WIDTH}px)`);
1902
1908
  var computeDefaultUseFullscreenPopup = () => {
@@ -1960,6 +1966,8 @@ var defaults = {
1960
1966
  searchInputClass: "",
1961
1967
  //* Display the international dial code next to the selected flag.
1962
1968
  separateDialCode: false,
1969
+ //* When strictMode rejects a key (etc), play a short feedback animation
1970
+ strictRejectAnimation: false,
1963
1971
  //* Show flags - for both the selected country, and in the country dropdown
1964
1972
  showFlags: true,
1965
1973
  //* Only allow certain chars e.g. a plus followed by numeric digits, and cap at max valid length.
@@ -2035,6 +2043,7 @@ var validateOptions = (customOptions) => {
2035
2043
  case "showFlags":
2036
2044
  case "separateDialCode":
2037
2045
  case "strictMode":
2046
+ case "strictRejectAnimation":
2038
2047
  case "useFullscreenPopup":
2039
2048
  if (typeof value !== "boolean") {
2040
2049
  warnOption(key, "a boolean", value);
@@ -2205,8 +2214,12 @@ var applyOptionSideEffects = (o) => {
2205
2214
  }
2206
2215
  o.i18n = { ...en_default, ...o.i18n };
2207
2216
  };
2217
+
2218
+ // src/js/helpers/string.ts
2208
2219
  var getNumeric = (s) => s.replace(/\D/g, "");
2209
2220
  var normaliseString = (s = "") => s.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
2221
+
2222
+ // src/js/helpers/dom.ts
2210
2223
  var buildClassNames = (flags) => Object.keys(flags).filter((k) => Boolean(flags[k])).join(" ");
2211
2224
  var createEl = (tagName, attrs, container) => {
2212
2225
  const el = document.createElement(tagName);
@@ -2220,6 +2233,8 @@ var createEl = (tagName, attrs, container) => {
2220
2233
  }
2221
2234
  return el;
2222
2235
  };
2236
+
2237
+ // src/js/core/icons.ts
2223
2238
  var buildSearchIcon = () => `
2224
2239
  <svg class="iti__search-icon-svg" width="14" height="14" viewBox="0 0 24 24" focusable="false" ${ARIA.HIDDEN}="true">
2225
2240
  <circle cx="11" cy="11" r="7" />
@@ -2245,6 +2260,8 @@ var buildGlobeIcon = () => `
2245
2260
  <path d="M508 213a240 240 0 0 0-449-87l-2 5-2 5c-8 14-13 30-17 46a65 65 0 0 1 56 4c16-10 35-19 56-27l9-3c-6 23-10 48-10 74h-16l4 6c3 4 5 8 6 13h6c0 22 3 44 8 65l2 10-25-10-4 5 12 18 9 3 6 2 8 3 9 26 1 2 16-7h1l-5-13-1-2c24 6 49 9 75 10v26l11 10 7 7v-30l1-13c22 0 44-3 65-8l10-2-21 48-1 1a317 317 0 0 1-14 23l-21 5h-2c6 16 7 33 1 50a240 240 0 0 0 211-265m-401-56-11 6c19-44 54-79 98-98-11 20-21 44-29 69-21 6-40 15-58 23m154 182v4c-29-1-57-6-81-13-7-25-12-52-13-81h94zm0-109h-94c1-29 6-56 13-81 24-7 52-12 81-13zm0-112c-22 1-44 4-65 8l-10 2 12-30 9-17 1-2a332 332 0 0 1 13-23c13-4 26-6 40-7zm187 69 6 4c4 12 6 25 6 38v1h-68c-1-26-4-51-10-74l48 20 1 1 14 8zm-14-44 10 20c-20-11-43-21-68-29-8-25-18-49-29-69 37 16 67 44 87 78M279 49h1c13 1 27 3 39 7l14 23 1 2a343 343 0 0 1 12 26l2 5 6 16c-23-6-48-9-74-10h-1zm0 87h1c29 1 56 6 81 13 7 24 12 51 12 80v1h-94zm2 207h-2v-94h95c-1 29-6 56-13 81-24 7-51 12-80 13m86 60-20 10c11-20 21-43 29-68 25-8 48-18 68-29-16 37-43 67-77 87m87-115-7 5-16 9-2 1a337 337 0 0 1-47 21c6-24 9-49 10-75h68c0 13-2 27-6 39"/>
2246
2261
  <path d="m261 428-2-2-22-21a40 40 0 0 0-32-11h-1a37 37 0 0 0-18 8l-1 1-4 2-2 2-5 4c-9-3-36-31-47-44s-32-45-34-55l3-2a151 151 0 0 0 11-9v-1a39 39 0 0 0 5-48l-3-3-11-19-3-4-5-7h-1l-3-3-4-3-5-2a35 35 0 0 0-16-3h-5c-4 1-14 5-24 11l-4 2-4 3-4 2c-9 8-17 17-18 27a380 380 0 0 0 212 259h3c12 0 25-10 36-21l10-12 6-11a39 39 0 0 0-8-40"/>
2247
2262
  </svg>`;
2263
+
2264
+ // src/js/core/countrySearch.ts
2248
2265
  var getMatchedCountries = (countries, query) => {
2249
2266
  const normalisedQuery = normaliseString(query);
2250
2267
  const iso2Matches = [];
@@ -2288,6 +2305,8 @@ var findFirstCountryStartingWith = (countries, query) => {
2288
2305
  }
2289
2306
  return null;
2290
2307
  };
2308
+
2309
+ // src/js/core/ui.ts
2291
2310
  var UI = class _UI {
2292
2311
  // private
2293
2312
  #options;
@@ -3216,6 +3235,8 @@ var UI = class _UI {
3216
3235
  this.#listItemByIso2.clear();
3217
3236
  }
3218
3237
  };
3238
+
3239
+ // src/js/data/country-data.ts
3219
3240
  var processAllCountries = (options) => {
3220
3241
  const { onlyCountries, excludeCountries } = options;
3221
3242
  if (onlyCountries?.length) {
@@ -3321,6 +3342,8 @@ var cacheSearchTokens = (countries) => {
3321
3342
  c.dialCodePlus = `+${c.dialCode}`;
3322
3343
  }
3323
3344
  };
3345
+
3346
+ // src/js/data/intl-regionless.ts
3324
3347
  var regionlessDialCodes = /* @__PURE__ */ new Set([
3325
3348
  "800",
3326
3349
  "808",
@@ -3335,6 +3358,8 @@ var hasRegionlessDialCode = (number) => {
3335
3358
  const dialCode = getNumeric(number).slice(0, 3);
3336
3359
  return number.startsWith("+") && regionlessDialCodes.has(dialCode);
3337
3360
  };
3361
+
3362
+ // src/js/format/formatting.ts
3338
3363
  var stripSeparateDialCode = (fullNumber, hasValidDialCode, separateDialCode, selectedCountryData) => {
3339
3364
  if (!separateDialCode || !hasValidDialCode) {
3340
3365
  return fullNumber;
@@ -3352,6 +3377,8 @@ var formatNumberAsYouType = (fullNumber, telInputValue, utils, selectedCountryDa
3352
3377
  }
3353
3378
  return result;
3354
3379
  };
3380
+
3381
+ // src/js/format/caret.ts
3355
3382
  var computeNewCaretPosition = (relevantChars, formattedValue, prevCaretPos, isDeleteForwards) => {
3356
3383
  if (prevCaretPos === 0 && !isDeleteForwards) {
3357
3384
  return 0;
@@ -3370,6 +3397,8 @@ var computeNewCaretPosition = (relevantChars, formattedValue, prevCaretPos, isDe
3370
3397
  }
3371
3398
  return formattedValue.length;
3372
3399
  };
3400
+
3401
+ // src/js/data/nanp-regionless.ts
3373
3402
  var regionlessNanpAreaCodes = /* @__PURE__ */ new Set([
3374
3403
  "800",
3375
3404
  "822",
@@ -3397,6 +3426,8 @@ var isRegionlessNanp = (number) => {
3397
3426
  }
3398
3427
  return false;
3399
3428
  };
3429
+
3430
+ // src/js/core/numerals.ts
3400
3431
  var Numerals = class {
3401
3432
  #userNumeralSet;
3402
3433
  constructor(initialValue) {
@@ -3443,6 +3474,8 @@ var Numerals = class {
3443
3474
  return !this.#userNumeralSet || this.#userNumeralSet === "ascii";
3444
3475
  }
3445
3476
  };
3477
+
3478
+ // src/js/intlTelInput.ts
3446
3479
  var nextId = 0;
3447
3480
  var ensureUtils = (methodName) => {
3448
3481
  if (!intlTelInput.utils) {
@@ -3499,9 +3532,7 @@ var Iti = class _Iti {
3499
3532
  this.#numerals = new Numerals(input.value);
3500
3533
  this.promise = this.#createInitPromise(this.#options);
3501
3534
  this.#countries = processAllCountries(this.#options);
3502
- const { dialCodes, dialCodeMaxLength, dialCodeToIso2Map } = processDialCodes(
3503
- this.#countries
3504
- );
3535
+ const { dialCodes, dialCodeMaxLength, dialCodeToIso2Map } = processDialCodes(this.#countries);
3505
3536
  this.#dialCodes = dialCodes;
3506
3537
  this.#dialCodeMaxLength = dialCodeMaxLength;
3507
3538
  this.#dialCodeToIso2Map = dialCodeToIso2Map;
@@ -3683,6 +3714,7 @@ var Iti = class _Iti {
3683
3714
  #handleAndroidStrictReject(inputValue, rejectedInput) {
3684
3715
  const newCaretPos = this.#removeJustTypedChar(inputValue);
3685
3716
  this.#ui.telInputEl.setSelectionRange(newCaretPos, newCaretPos);
3717
+ this.#playStrictRejectAnimation();
3686
3718
  this.#dispatchEvent(EVENTS.STRICT_REJECT, {
3687
3719
  source: "key",
3688
3720
  rejectedInput,
@@ -3742,7 +3774,13 @@ var Iti = class _Iti {
3742
3774
  //* On input event: (1) Update selected country, (2) Format-as-you-type.
3743
3775
  //* Note that this fires AFTER the input is updated.
3744
3776
  #handleInputEvent = (e) => {
3745
- const { strictMode, formatAsYouType, separateDialCode, allowDropdown, countrySearch } = this.#options;
3777
+ const {
3778
+ strictMode,
3779
+ formatAsYouType,
3780
+ separateDialCode,
3781
+ allowDropdown,
3782
+ countrySearch
3783
+ } = this.#options;
3746
3784
  const detail = e?.detail;
3747
3785
  if (detail?.["isCountryChange"]) {
3748
3786
  return;
@@ -3824,6 +3862,7 @@ var Iti = class _Iti {
3824
3862
  const newCountry = this.#resolveCountryChangeFromNumber(newFullNumber);
3825
3863
  const isChangingDialCode = newCountry !== null;
3826
3864
  if (!isAllowedChar || hasExceededMaxLength && !isChangingDialCode && !isInitialPlus) {
3865
+ this.#playStrictRejectAnimation();
3827
3866
  this.#dispatchEvent(EVENTS.STRICT_REJECT, {
3828
3867
  source: "key",
3829
3868
  rejectedInput: e.key,
@@ -3866,6 +3905,7 @@ var Iti = class _Iti {
3866
3905
  coreNumber = intlTelInput.utils.getCoreNumber(newValue, iso2);
3867
3906
  }
3868
3907
  if (!coreNumber) {
3908
+ this.#playStrictRejectAnimation();
3869
3909
  this.#dispatchEvent(EVENTS.STRICT_REJECT, {
3870
3910
  source: "paste",
3871
3911
  rejectedInput: pastedRaw,
@@ -3879,6 +3919,7 @@ var Iti = class _Iti {
3879
3919
  newValue = newValue.slice(0, newValue.length - trimLength);
3880
3920
  rejectReason = "max-length";
3881
3921
  } else {
3922
+ this.#playStrictRejectAnimation();
3882
3923
  this.#dispatchEvent(EVENTS.STRICT_REJECT, {
3883
3924
  source: "paste",
3884
3925
  rejectedInput: pastedRaw,
@@ -3893,6 +3934,9 @@ var Iti = class _Iti {
3893
3934
  input.setSelectionRange(caretPos, caretPos);
3894
3935
  input.dispatchEvent(new InputEvent("input", { bubbles: true }));
3895
3936
  if (rejectReason) {
3937
+ if (pasted.length > 0 && sanitised.length === 0) {
3938
+ this.#playStrictRejectAnimation();
3939
+ }
3896
3940
  this.#dispatchEvent(EVENTS.STRICT_REJECT, {
3897
3941
  source: "paste",
3898
3942
  rejectedInput: pastedRaw,
@@ -3905,6 +3949,21 @@ var Iti = class _Iti {
3905
3949
  const max = Number(this.#ui.telInputEl.getAttribute("maxlength"));
3906
3950
  return max && number.length > max ? number.substring(0, max) : number;
3907
3951
  }
3952
+ //* Play the strict-reject animation (shake, or background-colour flash under prefers-reduced-motion) on the wrapper.
3953
+ //* Called when strictMode rejects the whole input (keystroke, or whole paste).
3954
+ //* Uses the wrapper (not the input) so any separateDialCode / country button move together with the input.
3955
+ #playStrictRejectAnimation() {
3956
+ if (!this.#options.strictRejectAnimation) {
3957
+ return;
3958
+ }
3959
+ const wrapperEl = this.#ui.telInputEl.parentElement;
3960
+ if (!wrapperEl) {
3961
+ return;
3962
+ }
3963
+ wrapperEl.classList.remove("iti__strict-reject-animation");
3964
+ void wrapperEl.offsetWidth;
3965
+ wrapperEl.classList.add("iti__strict-reject-animation");
3966
+ }
3908
3967
  //* Trigger a custom event on the input (typed via ItiEventMap).
3909
3968
  #dispatchEvent(name, detailProps = {}) {
3910
3969
  const e = new CustomEvent(name, {
@@ -4541,7 +4600,7 @@ var intlTelInput = Object.assign(
4541
4600
  attachUtils,
4542
4601
  startedLoadingUtils: false,
4543
4602
  startedLoadingAutoCountry: false,
4544
- version: "27.2.0"
4603
+ version: "27.3.0"
4545
4604
  }
4546
4605
  );
4547
4606
  var intlTelInput_default = intlTelInput;
@@ -4576,6 +4635,7 @@ var IntlTelInput = forwardRef(function IntlTelInput2({
4576
4635
  }, ref) {
4577
4636
  const inputRef = useRef(null);
4578
4637
  const itiRef = useRef(null);
4638
+ const pluginInputClassesRef = useRef("");
4579
4639
  const lastEmittedNumberRef = useRef(void 0);
4580
4640
  const lastEmittedCountryRef = useRef(void 0);
4581
4641
  const lastEmittedValidityRef = useRef(void 0);
@@ -4642,6 +4702,7 @@ var IntlTelInput = forwardRef(function IntlTelInput2({
4642
4702
  return void 0;
4643
4703
  }
4644
4704
  itiRef.current = intlTelInput_default(inputEl, initOptions);
4705
+ pluginInputClassesRef.current = inputEl.className;
4645
4706
  const handleOpen = () => onOpenCountryDropdownRef.current?.();
4646
4707
  const handleClose = () => onCloseCountryDropdownRef.current?.();
4647
4708
  const handleStrictReject = (e) => {
@@ -4704,6 +4765,8 @@ var IntlTelInput = forwardRef(function IntlTelInput2({
4704
4765
  for (const [key, val] of Object.entries(inputProps)) {
4705
4766
  if (ignoredInputProps.has(key)) {
4706
4767
  warnInputProp(key);
4768
+ } else if (key === "className") {
4769
+ sanitizedInputProps[key] = `${pluginInputClassesRef.current} ${val}`;
4707
4770
  } else {
4708
4771
  sanitizedInputProps[key] = val;
4709
4772
  }