intl-tel-input 27.1.3 → 27.2.1

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.
@@ -4571,7 +4571,7 @@ var intlTelInput = Object.assign(
4571
4571
  attachUtils,
4572
4572
  startedLoadingUtils: false,
4573
4573
  startedLoadingAutoCountry: false,
4574
- version: "27.1.3"
4574
+ version: "27.2.1"
4575
4575
  }
4576
4576
  );
4577
4577
  var intlTelInput_default = intlTelInput;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intl-tel-input",
3
- "version": "27.1.3",
3
+ "version": "27.2.1",
4
4
  "description": "A JavaScript plugin for entering and validating international telephone numbers",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -29,7 +29,8 @@
29
29
  "build:translations": "npm run clean:dist:js && npm run clean:tmp && npm run build:translations:gen && npm run build:js",
30
30
  "build:utils:closure": "node scripts/build-utils.js",
31
31
  "build:utils:check": "node scripts/check-lpn-metadata.js",
32
- "build:utils": "npm run clean:utils && npm run build:utils:closure && npm run build:utils:check",
32
+ "build:utils:check:shape": "node scripts/check-utils-shape.js",
33
+ "build:utils": "npm run clean:utils && npm run build:utils:closure && npm run build:utils:check && npm run build:utils:check:shape",
33
34
  "ensure:utils": "node -e \"process.exit(require('node:fs').existsSync('dist/js/utils.js')?0:1)\" || npm run build:utils",
34
35
  "ensure:dts": "node -e \"process.exit(require('node:fs').existsSync('dist/js/intlTelInput.d.ts')?0:1)\" || npm run build:js:dts",
35
36
  "build:css:main": "sass --no-source-map --style=compressed src/css/intlTelInput.scss:dist/css/intlTelInput-no-assets.css src/css/intlTelInputWithAssets.scss:dist/css/intlTelInput.css",
@@ -39,13 +40,20 @@
39
40
  "build:img:sprite": "node --experimental-strip-types scripts/generate-sprite.js",
40
41
  "build:img": "npm run clean:dist:img && npm run build:img:sprite && npm run build:css",
41
42
  "build:js:dts": "node scripts/build-dts.js",
43
+ "build:js:dts:check": "tsc -p scripts/tsconfig.typecheck-dts.json",
44
+ "build:components:dts:check": "tsc -p scripts/tsconfig.typecheck-dts-components.json",
45
+ "typecheck:dts": "npm run ensure:dts && npm run build:js:dts:check",
46
+ "typecheck:dts:components": "tsc -p scripts/tsconfig.typecheck-dts-components.json",
47
+ "typecheck:main": "tsc --noEmit -p tsconfig.json",
48
+ "typecheck:svelte": "svelte-check --workspace svelte --tsconfig tsconfig.json",
49
+ "typecheck:vue": "vue-tsc --noEmit -p vue/tsconfig.build.json",
42
50
  "build:js:core": "node scripts/esbuild.js",
43
- "build:js": "npm run clean:dist:js && npm run clean:tmp && npm run lint:js && npm run build:utils:closure && npm run build:js:dts && npm run build:js:core && npm run build:components",
51
+ "build:js": "npm run clean:dist:js && npm run clean:tmp && npm run lint:js && npm run build:utils:closure && npm run build:utils:check:shape && npm run build:js:dts && npm run build:js:dts:check && npm run typecheck:main && npm run build:js:core && npm run build:components && npm run build:components:dts:check && npm run typecheck:svelte",
44
52
  "build:jsfast": "npm run clean:dist:js:keep-utils && npm run clean:tmp && npm run ensure:utils && npm run build:js:core",
45
53
  "build:jsfast:cmps": "npm run build:jsfast && npm run build:components",
46
- "build:react": "npm run ensure:dts && npm run clean:react && tsc -p react/tsconfig.json && node react/build.js",
47
- "build:vue": "npm run ensure:dts && npm run clean:vue && vite build --config vue/vite.config.mts",
48
- "build:angular": "npm run ensure:dts && npm run clean:angular && ngc -p angular/tsconfig.json && node angular/build.js",
54
+ "build:react": "npm run ensure:dts && npm run clean:react && tsc -p react/tsconfig.build.json && node react/build.js",
55
+ "build:vue": "npm run ensure:dts && npm run clean:vue && npm run typecheck:vue && vite build --config vue/vite.config.mts",
56
+ "build:angular": "npm run ensure:dts && npm run clean:angular && ngc -p angular/tsconfig.build.json && node angular/build.js",
49
57
  "build:components": "npm run build:react && npm run build:vue && npm run build:angular",
50
58
  "build:site": "npm run build --workspace=site",
51
59
  "build": "npm run clean:all && npm run build:img && npm run build:translations:gen && npm run build:js && npm run build:site",
@@ -106,12 +114,14 @@
106
114
  "sass": "^1.83.1",
107
115
  "sharp": "^0.34.5",
108
116
  "svelte": "^5.46.4",
117
+ "svelte-check": "^4.4.6",
109
118
  "typescript": "^6.0.2",
110
119
  "typescript-eslint": "^8.58.0",
111
120
  "vite": "^8.0.7",
112
121
  "vite-plugin-dts": "^4.4.0",
113
122
  "vitest": "^4.1.3",
114
123
  "vue": "^3.5.13",
124
+ "vue-tsc": "^3.2.7",
115
125
  "zone.js": "^0.16.1"
116
126
  },
117
127
  "files": [
package/react/README.md CHANGED
@@ -3,3 +3,11 @@
3
3
  A React component for the [intl-tel-input](https://github.com/jackocnr/intl-tel-input) JavaScript plugin. View the [source code](https://github.com/jackocnr/intl-tel-input/blob/master/react/src/IntlTelInput.tsx).
4
4
 
5
5
  [Explore docs »](https://intl-tel-input.com/docs/react-component)
6
+
7
+ ## Running the demos locally
8
+
9
+ 1. Initialise the submodules: `git submodule update --init --recursive`
10
+ 2. Install dependencies: `npm install`
11
+ 3. Build: `npm run build`
12
+
13
+ You can then open `react/demo/validation/index.html` in your browser to try the validation demo. View the full list of [available demos](https://github.com/jackocnr/intl-tel-input/tree/master/react/demo).
@@ -2,6 +2,8 @@ import intlTelInput, { Iti } from "intl-tel-input";
2
2
  import React from "react";
3
3
  export { intlTelInput };
4
4
  type InputProps = Omit<React.ComponentPropsWithoutRef<"input">, "onInput">;
5
+ export type StrictRejectSource = "key" | "paste";
6
+ export type StrictRejectReason = "invalid" | "max-length";
5
7
  export type IntlTelInputRef = {
6
8
  getInstance: () => Iti | null;
7
9
  getInput: () => HTMLInputElement | null;
@@ -11,6 +13,9 @@ declare const IntlTelInput: React.ForwardRefExoticComponent<Partial<import("intl
11
13
  onChangeCountry?: (iso2: string) => void;
12
14
  onChangeValidity?: (isValid: boolean) => void;
13
15
  onChangeErrorCode?: (errorCode: number | null) => void;
16
+ onOpenCountryDropdown?: () => void;
17
+ onCloseCountryDropdown?: () => void;
18
+ onStrictReject?: (source: StrictRejectSource, rejectedInput: string, reason: StrictRejectReason) => void;
14
19
  usePreciseValidation?: boolean;
15
20
  inputProps?: InputProps;
16
21
  disabled?: boolean | undefined;
@@ -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 = () => {
@@ -2205,8 +2211,12 @@ var applyOptionSideEffects = (o) => {
2205
2211
  }
2206
2212
  o.i18n = { ...en_default, ...o.i18n };
2207
2213
  };
2214
+
2215
+ // src/js/helpers/string.ts
2208
2216
  var getNumeric = (s) => s.replace(/\D/g, "");
2209
2217
  var normaliseString = (s = "") => s.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
2218
+
2219
+ // src/js/helpers/dom.ts
2210
2220
  var buildClassNames = (flags) => Object.keys(flags).filter((k) => Boolean(flags[k])).join(" ");
2211
2221
  var createEl = (tagName, attrs, container) => {
2212
2222
  const el = document.createElement(tagName);
@@ -2220,6 +2230,8 @@ var createEl = (tagName, attrs, container) => {
2220
2230
  }
2221
2231
  return el;
2222
2232
  };
2233
+
2234
+ // src/js/core/icons.ts
2223
2235
  var buildSearchIcon = () => `
2224
2236
  <svg class="iti__search-icon-svg" width="14" height="14" viewBox="0 0 24 24" focusable="false" ${ARIA.HIDDEN}="true">
2225
2237
  <circle cx="11" cy="11" r="7" />
@@ -2245,6 +2257,8 @@ var buildGlobeIcon = () => `
2245
2257
  <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
2258
  <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
2259
  </svg>`;
2260
+
2261
+ // src/js/core/countrySearch.ts
2248
2262
  var getMatchedCountries = (countries, query) => {
2249
2263
  const normalisedQuery = normaliseString(query);
2250
2264
  const iso2Matches = [];
@@ -2288,6 +2302,8 @@ var findFirstCountryStartingWith = (countries, query) => {
2288
2302
  }
2289
2303
  return null;
2290
2304
  };
2305
+
2306
+ // src/js/core/ui.ts
2291
2307
  var UI = class _UI {
2292
2308
  // private
2293
2309
  #options;
@@ -3216,6 +3232,8 @@ var UI = class _UI {
3216
3232
  this.#listItemByIso2.clear();
3217
3233
  }
3218
3234
  };
3235
+
3236
+ // src/js/data/country-data.ts
3219
3237
  var processAllCountries = (options) => {
3220
3238
  const { onlyCountries, excludeCountries } = options;
3221
3239
  if (onlyCountries?.length) {
@@ -3321,6 +3339,8 @@ var cacheSearchTokens = (countries) => {
3321
3339
  c.dialCodePlus = `+${c.dialCode}`;
3322
3340
  }
3323
3341
  };
3342
+
3343
+ // src/js/data/intl-regionless.ts
3324
3344
  var regionlessDialCodes = /* @__PURE__ */ new Set([
3325
3345
  "800",
3326
3346
  "808",
@@ -3335,6 +3355,8 @@ var hasRegionlessDialCode = (number) => {
3335
3355
  const dialCode = getNumeric(number).slice(0, 3);
3336
3356
  return number.startsWith("+") && regionlessDialCodes.has(dialCode);
3337
3357
  };
3358
+
3359
+ // src/js/format/formatting.ts
3338
3360
  var stripSeparateDialCode = (fullNumber, hasValidDialCode, separateDialCode, selectedCountryData) => {
3339
3361
  if (!separateDialCode || !hasValidDialCode) {
3340
3362
  return fullNumber;
@@ -3352,6 +3374,8 @@ var formatNumberAsYouType = (fullNumber, telInputValue, utils, selectedCountryDa
3352
3374
  }
3353
3375
  return result;
3354
3376
  };
3377
+
3378
+ // src/js/format/caret.ts
3355
3379
  var computeNewCaretPosition = (relevantChars, formattedValue, prevCaretPos, isDeleteForwards) => {
3356
3380
  if (prevCaretPos === 0 && !isDeleteForwards) {
3357
3381
  return 0;
@@ -3370,6 +3394,8 @@ var computeNewCaretPosition = (relevantChars, formattedValue, prevCaretPos, isDe
3370
3394
  }
3371
3395
  return formattedValue.length;
3372
3396
  };
3397
+
3398
+ // src/js/data/nanp-regionless.ts
3373
3399
  var regionlessNanpAreaCodes = /* @__PURE__ */ new Set([
3374
3400
  "800",
3375
3401
  "822",
@@ -3397,6 +3423,8 @@ var isRegionlessNanp = (number) => {
3397
3423
  }
3398
3424
  return false;
3399
3425
  };
3426
+
3427
+ // src/js/core/numerals.ts
3400
3428
  var Numerals = class {
3401
3429
  #userNumeralSet;
3402
3430
  constructor(initialValue) {
@@ -3443,6 +3471,8 @@ var Numerals = class {
3443
3471
  return !this.#userNumeralSet || this.#userNumeralSet === "ascii";
3444
3472
  }
3445
3473
  };
3474
+
3475
+ // src/js/intlTelInput.ts
3446
3476
  var nextId = 0;
3447
3477
  var ensureUtils = (methodName) => {
3448
3478
  if (!intlTelInput.utils) {
@@ -4541,7 +4571,7 @@ var intlTelInput = Object.assign(
4541
4571
  attachUtils,
4542
4572
  startedLoadingUtils: false,
4543
4573
  startedLoadingAutoCountry: false,
4544
- version: "27.1.3"
4574
+ version: "27.2.1"
4545
4575
  }
4546
4576
  );
4547
4577
  var intlTelInput_default = intlTelInput;
@@ -4564,6 +4594,9 @@ var IntlTelInput = forwardRef(function IntlTelInput2({
4564
4594
  onChangeCountry = noop,
4565
4595
  onChangeValidity = noop,
4566
4596
  onChangeErrorCode = noop,
4597
+ onOpenCountryDropdown,
4598
+ onCloseCountryDropdown,
4599
+ onStrictReject,
4567
4600
  usePreciseValidation = false,
4568
4601
  inputProps = {},
4569
4602
  disabled = void 0,
@@ -4578,6 +4611,12 @@ var IntlTelInput = forwardRef(function IntlTelInput2({
4578
4611
  const lastEmittedValidityRef = useRef(void 0);
4579
4612
  const lastEmittedErrorCodeRef = useRef(void 0);
4580
4613
  const pendingUpdateRef = useRef(false);
4614
+ const onOpenCountryDropdownRef = useRef(onOpenCountryDropdown);
4615
+ const onCloseCountryDropdownRef = useRef(onCloseCountryDropdown);
4616
+ const onStrictRejectRef = useRef(onStrictReject);
4617
+ onOpenCountryDropdownRef.current = onOpenCountryDropdown;
4618
+ onCloseCountryDropdownRef.current = onCloseCountryDropdown;
4619
+ onStrictRejectRef.current = onStrictReject;
4581
4620
  useImperativeHandle(ref, () => ({
4582
4621
  getInstance: () => itiRef.current,
4583
4622
  getInput: () => inputRef.current
@@ -4628,10 +4667,24 @@ var IntlTelInput = forwardRef(function IntlTelInput2({
4628
4667
  usePreciseValidation
4629
4668
  ]);
4630
4669
  useEffect(() => {
4631
- if (inputRef.current) {
4632
- itiRef.current = intlTelInput_default(inputRef.current, initOptions);
4633
- }
4670
+ const inputEl = inputRef.current;
4671
+ if (!inputEl) {
4672
+ return void 0;
4673
+ }
4674
+ itiRef.current = intlTelInput_default(inputEl, initOptions);
4675
+ const handleOpen = () => onOpenCountryDropdownRef.current?.();
4676
+ const handleClose = () => onCloseCountryDropdownRef.current?.();
4677
+ const handleStrictReject = (e) => {
4678
+ const { source, rejectedInput, reason } = e.detail;
4679
+ onStrictRejectRef.current?.(source, rejectedInput, reason);
4680
+ };
4681
+ inputEl.addEventListener("open:countrydropdown", handleOpen);
4682
+ inputEl.addEventListener("close:countrydropdown", handleClose);
4683
+ inputEl.addEventListener("strict:reject", handleStrictReject);
4634
4684
  return () => {
4685
+ inputEl.removeEventListener("open:countrydropdown", handleOpen);
4686
+ inputEl.removeEventListener("close:countrydropdown", handleClose);
4687
+ inputEl.removeEventListener("strict:reject", handleStrictReject);
4635
4688
  itiRef.current?.destroy();
4636
4689
  };
4637
4690
  }, []);
@@ -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 = () => {
@@ -2205,8 +2211,12 @@ var applyOptionSideEffects = (o) => {
2205
2211
  }
2206
2212
  o.i18n = { ...en_default, ...o.i18n };
2207
2213
  };
2214
+
2215
+ // src/js/helpers/string.ts
2208
2216
  var getNumeric = (s) => s.replace(/\D/g, "");
2209
2217
  var normaliseString = (s = "") => s.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
2218
+
2219
+ // src/js/helpers/dom.ts
2210
2220
  var buildClassNames = (flags) => Object.keys(flags).filter((k) => Boolean(flags[k])).join(" ");
2211
2221
  var createEl = (tagName, attrs, container) => {
2212
2222
  const el = document.createElement(tagName);
@@ -2220,6 +2230,8 @@ var createEl = (tagName, attrs, container) => {
2220
2230
  }
2221
2231
  return el;
2222
2232
  };
2233
+
2234
+ // src/js/core/icons.ts
2223
2235
  var buildSearchIcon = () => `
2224
2236
  <svg class="iti__search-icon-svg" width="14" height="14" viewBox="0 0 24 24" focusable="false" ${ARIA.HIDDEN}="true">
2225
2237
  <circle cx="11" cy="11" r="7" />
@@ -2245,6 +2257,8 @@ var buildGlobeIcon = () => `
2245
2257
  <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
2258
  <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
2259
  </svg>`;
2260
+
2261
+ // src/js/core/countrySearch.ts
2248
2262
  var getMatchedCountries = (countries, query) => {
2249
2263
  const normalisedQuery = normaliseString(query);
2250
2264
  const iso2Matches = [];
@@ -2288,6 +2302,8 @@ var findFirstCountryStartingWith = (countries, query) => {
2288
2302
  }
2289
2303
  return null;
2290
2304
  };
2305
+
2306
+ // src/js/core/ui.ts
2291
2307
  var UI = class _UI {
2292
2308
  // private
2293
2309
  #options;
@@ -3216,6 +3232,8 @@ var UI = class _UI {
3216
3232
  this.#listItemByIso2.clear();
3217
3233
  }
3218
3234
  };
3235
+
3236
+ // src/js/data/country-data.ts
3219
3237
  var processAllCountries = (options) => {
3220
3238
  const { onlyCountries, excludeCountries } = options;
3221
3239
  if (onlyCountries?.length) {
@@ -3321,6 +3339,8 @@ var cacheSearchTokens = (countries) => {
3321
3339
  c.dialCodePlus = `+${c.dialCode}`;
3322
3340
  }
3323
3341
  };
3342
+
3343
+ // src/js/data/intl-regionless.ts
3324
3344
  var regionlessDialCodes = /* @__PURE__ */ new Set([
3325
3345
  "800",
3326
3346
  "808",
@@ -3335,6 +3355,8 @@ var hasRegionlessDialCode = (number) => {
3335
3355
  const dialCode = getNumeric(number).slice(0, 3);
3336
3356
  return number.startsWith("+") && regionlessDialCodes.has(dialCode);
3337
3357
  };
3358
+
3359
+ // src/js/format/formatting.ts
3338
3360
  var stripSeparateDialCode = (fullNumber, hasValidDialCode, separateDialCode, selectedCountryData) => {
3339
3361
  if (!separateDialCode || !hasValidDialCode) {
3340
3362
  return fullNumber;
@@ -3352,6 +3374,8 @@ var formatNumberAsYouType = (fullNumber, telInputValue, utils, selectedCountryDa
3352
3374
  }
3353
3375
  return result;
3354
3376
  };
3377
+
3378
+ // src/js/format/caret.ts
3355
3379
  var computeNewCaretPosition = (relevantChars, formattedValue, prevCaretPos, isDeleteForwards) => {
3356
3380
  if (prevCaretPos === 0 && !isDeleteForwards) {
3357
3381
  return 0;
@@ -3370,6 +3394,8 @@ var computeNewCaretPosition = (relevantChars, formattedValue, prevCaretPos, isDe
3370
3394
  }
3371
3395
  return formattedValue.length;
3372
3396
  };
3397
+
3398
+ // src/js/data/nanp-regionless.ts
3373
3399
  var regionlessNanpAreaCodes = /* @__PURE__ */ new Set([
3374
3400
  "800",
3375
3401
  "822",
@@ -3397,6 +3423,8 @@ var isRegionlessNanp = (number) => {
3397
3423
  }
3398
3424
  return false;
3399
3425
  };
3426
+
3427
+ // src/js/core/numerals.ts
3400
3428
  var Numerals = class {
3401
3429
  #userNumeralSet;
3402
3430
  constructor(initialValue) {
@@ -3443,6 +3471,8 @@ var Numerals = class {
3443
3471
  return !this.#userNumeralSet || this.#userNumeralSet === "ascii";
3444
3472
  }
3445
3473
  };
3474
+
3475
+ // src/js/intlTelInput.ts
3446
3476
  var nextId = 0;
3447
3477
  var ensureUtils = (methodName) => {
3448
3478
  if (!intlTelInput.utils) {
@@ -4541,7 +4571,7 @@ var intlTelInput = Object.assign(
4541
4571
  attachUtils,
4542
4572
  startedLoadingUtils: false,
4543
4573
  startedLoadingAutoCountry: false,
4544
- version: "27.1.3"
4574
+ version: "27.2.1"
4545
4575
  }
4546
4576
  );
4547
4577
  var intlTelInput_default = intlTelInput;
@@ -10877,6 +10907,9 @@ var IntlTelInput = forwardRef(function IntlTelInput2({
10877
10907
  onChangeCountry = noop,
10878
10908
  onChangeValidity = noop,
10879
10909
  onChangeErrorCode = noop,
10910
+ onOpenCountryDropdown,
10911
+ onCloseCountryDropdown,
10912
+ onStrictReject,
10880
10913
  usePreciseValidation = false,
10881
10914
  inputProps = {},
10882
10915
  disabled = void 0,
@@ -10891,6 +10924,12 @@ var IntlTelInput = forwardRef(function IntlTelInput2({
10891
10924
  const lastEmittedValidityRef = useRef(void 0);
10892
10925
  const lastEmittedErrorCodeRef = useRef(void 0);
10893
10926
  const pendingUpdateRef = useRef(false);
10927
+ const onOpenCountryDropdownRef = useRef(onOpenCountryDropdown);
10928
+ const onCloseCountryDropdownRef = useRef(onCloseCountryDropdown);
10929
+ const onStrictRejectRef = useRef(onStrictReject);
10930
+ onOpenCountryDropdownRef.current = onOpenCountryDropdown;
10931
+ onCloseCountryDropdownRef.current = onCloseCountryDropdown;
10932
+ onStrictRejectRef.current = onStrictReject;
10894
10933
  useImperativeHandle(ref, () => ({
10895
10934
  getInstance: () => itiRef.current,
10896
10935
  getInput: () => inputRef.current
@@ -10941,10 +10980,24 @@ var IntlTelInput = forwardRef(function IntlTelInput2({
10941
10980
  usePreciseValidation
10942
10981
  ]);
10943
10982
  useEffect(() => {
10944
- if (inputRef.current) {
10945
- itiRef.current = intlTelInput_default(inputRef.current, initOptions);
10946
- }
10983
+ const inputEl = inputRef.current;
10984
+ if (!inputEl) {
10985
+ return void 0;
10986
+ }
10987
+ itiRef.current = intlTelInput_default(inputEl, initOptions);
10988
+ const handleOpen = () => onOpenCountryDropdownRef.current?.();
10989
+ const handleClose = () => onCloseCountryDropdownRef.current?.();
10990
+ const handleStrictReject = (e) => {
10991
+ const { source, rejectedInput, reason } = e.detail;
10992
+ onStrictRejectRef.current?.(source, rejectedInput, reason);
10993
+ };
10994
+ inputEl.addEventListener("open:countrydropdown", handleOpen);
10995
+ inputEl.addEventListener("close:countrydropdown", handleClose);
10996
+ inputEl.addEventListener("strict:reject", handleStrictReject);
10947
10997
  return () => {
10998
+ inputEl.removeEventListener("open:countrydropdown", handleOpen);
10999
+ inputEl.removeEventListener("close:countrydropdown", handleClose);
11000
+ inputEl.removeEventListener("strict:reject", handleStrictReject);
10948
11001
  itiRef.current?.destroy();
10949
11002
  };
10950
11003
  }, []);
package/svelte/README.md CHANGED
@@ -3,3 +3,12 @@
3
3
  A Svelte 5 component for the [intl-tel-input](https://github.com/jackocnr/intl-tel-input) JavaScript plugin. View the [source code](https://github.com/jackocnr/intl-tel-input/blob/master/svelte/src/IntlTelInput.svelte).
4
4
 
5
5
  [Explore docs »](https://intl-tel-input.com/docs/svelte-component)
6
+
7
+ ## Running the demos locally
8
+
9
+ 1. Initialise the submodules: `git submodule update --init --recursive`
10
+ 2. Install dependencies: `npm install`
11
+ 3. Build: `npm run build`
12
+ 4. Run a demo: `npm run svelte:demo` and copy the given URL into your browser.
13
+
14
+ This defaults to the validation demo — to run a different one, set the `DEMO` env var, e.g. `DEMO=simple npm run svelte:demo`. View the full list of [available demos](https://github.com/jackocnr/intl-tel-input/tree/master/svelte/demo).
@@ -6,6 +6,7 @@
6
6
  <script lang="ts">
7
7
  // Resolves to IntlTelInput.svelte.d.ts (the type declaration file for this component).
8
8
  import type { Props } from "./IntlTelInput.svelte";
9
+ import type { SomeOptions } from "intl-tel-input";
9
10
  import { onMount, onDestroy } from "svelte";
10
11
 
11
12
  // Props
@@ -20,9 +21,18 @@
20
21
  onChangeCountry,
21
22
  onChangeValidity,
22
23
  onChangeErrorCode,
24
+ onOpenCountryDropdown,
25
+ onCloseCountryDropdown,
26
+ onStrictReject,
23
27
  ...initOptions
24
28
  } = $props() as Props;
25
29
 
30
+ type StrictRejectDetail = {
31
+ source: "key" | "paste";
32
+ rejectedInput: string;
33
+ reason: "invalid" | "max-length";
34
+ };
35
+
26
36
  // State
27
37
  let inputElement: HTMLInputElement | undefined = $state();
28
38
  let instance: Iti | undefined = $state();
@@ -96,6 +106,13 @@
96
106
  updateValue();
97
107
  };
98
108
 
109
+ const handleOpenDropdown = (): void => onOpenCountryDropdown?.();
110
+ const handleCloseDropdown = (): void => onCloseCountryDropdown?.();
111
+ const handleStrictReject = (e: Event): void => {
112
+ const { source, rejectedInput, reason } = (e as CustomEvent<StrictRejectDetail>).detail;
113
+ onStrictReject?.(source, rejectedInput, reason);
114
+ };
115
+
99
116
  // Lifecycle
100
117
  onMount(() => {
101
118
  if (inputElement) {
@@ -103,6 +120,10 @@
103
120
  if (disabled) instance.setDisabled(disabled);
104
121
  if (readonly) instance.setReadonly(readonly);
105
122
 
123
+ inputElement.addEventListener("open:countrydropdown", handleOpenDropdown);
124
+ inputElement.addEventListener("close:countrydropdown", handleCloseDropdown);
125
+ inputElement.addEventListener("strict:reject", handleStrictReject);
126
+
106
127
  lastEmittedCountry = instance.getSelectedCountryData()?.iso2 ?? "";
107
128
  hasInitialized = true;
108
129
 
@@ -128,6 +149,11 @@
128
149
  });
129
150
 
130
151
  onDestroy(() => {
152
+ if (inputElement) {
153
+ inputElement.removeEventListener("open:countrydropdown", handleOpenDropdown);
154
+ inputElement.removeEventListener("close:countrydropdown", handleCloseDropdown);
155
+ inputElement.removeEventListener("strict:reject", handleStrictReject);
156
+ }
131
157
  instance?.destroy();
132
158
  });
133
159
 
@@ -4,6 +4,9 @@ import type { Component } from "svelte";
4
4
  import type { Iti, SomeOptions } from "intl-tel-input";
5
5
  import intlTelInput from "intl-tel-input";
6
6
 
7
+ export type StrictRejectSource = "key" | "paste";
8
+ export type StrictRejectReason = "invalid" | "max-length";
9
+
7
10
  export type Props = SomeOptions & {
8
11
  disabled?: boolean;
9
12
  readonly?: boolean;
@@ -15,6 +18,9 @@ export type Props = SomeOptions & {
15
18
  onChangeCountry?: (iso2: string) => void;
16
19
  onChangeValidity?: (isValid: boolean) => void;
17
20
  onChangeErrorCode?: (errorCode: number | null) => void;
21
+ onOpenCountryDropdown?: () => void;
22
+ onCloseCountryDropdown?: () => void;
23
+ onStrictReject?: (source: StrictRejectSource, rejectedInput: string, reason: StrictRejectReason) => void;
18
24
  };
19
25
 
20
26
  export { intlTelInput };
package/vue/README.md CHANGED
@@ -3,3 +3,12 @@
3
3
  A Vue component for the [intl-tel-input](https://github.com/jackocnr/intl-tel-input) JavaScript plugin. View the [source code](https://github.com/jackocnr/intl-tel-input/blob/master/vue/src/IntlTelInput.vue).
4
4
 
5
5
  [Explore docs »](https://intl-tel-input.com/docs/vue-component)
6
+
7
+ ## Running the demos locally
8
+
9
+ 1. Initialise the submodules: `git submodule update --init --recursive`
10
+ 2. Install dependencies: `npm install`
11
+ 3. Build: `npm run build`
12
+ 4. Run a demo: `npm run vue:demo` and copy the given URL into your browser.
13
+
14
+ This defaults to the validation demo — to run a different one, set the `DEMO` env var, e.g. `DEMO=simple npm run vue:demo`. View the full list of [available demos](https://github.com/jackocnr/intl-tel-input/tree/master/vue/demo).
@@ -2517,7 +2517,7 @@ var p = new Set(f.map((e) => e.iso2)), m = (e) => p.has(e), h = f, g = {
2517
2517
  },
2518
2518
  startedLoadingUtils: !1,
2519
2519
  startedLoadingAutoCountry: !1,
2520
- version: "27.1.3"
2520
+ version: "27.2.1"
2521
2521
  }), $ = Q, Ce = /* @__PURE__ */ n({
2522
2522
  inheritAttrs: !1,
2523
2523
  __name: "IntlTelInput",
@@ -2572,6 +2572,9 @@ var p = new Set(f.map((e) => e.iso2)), m = (e) => p.has(e), h = f, g = {
2572
2572
  "changeCountry",
2573
2573
  "changeValidity",
2574
2574
  "changeErrorCode",
2575
+ "openCountryDropdown",
2576
+ "closeCountryDropdown",
2577
+ "strictReject",
2575
2578
  "update:modelValue"
2576
2579
  ],
2577
2580
  setup(n, { expose: d, emit: f }) {
@@ -2615,9 +2618,12 @@ var p = new Set(f.map((e) => e.iso2)), m = (e) => p.has(e), h = f, g = {
2615
2618
  if (!C.value?.isActive()) return;
2616
2619
  let e = C.value.getSelectedCountryData()?.iso2 ?? "";
2617
2620
  e !== T.value && (T.value = e, m("changeCountry", e)), j();
2621
+ }, N = () => m("openCountryDropdown"), P = () => m("closeCountryDropdown"), F = (e) => {
2622
+ let { source: t, rejectedInput: n, reason: r } = e.detail;
2623
+ m("strictReject", t, n, r);
2618
2624
  };
2619
2625
  return a(() => {
2620
- S.value && (C.value = $(S.value, x.value), p.disabled && C.value.setDisabled(p.disabled), p.readonly && C.value.setReadonly(p.readonly), T.value = C.value.getSelectedCountryData()?.iso2 ?? "", C.value.promise.then(() => {
2626
+ S.value && (C.value = $(S.value, x.value), S.value.addEventListener("open:countrydropdown", N), S.value.addEventListener("close:countrydropdown", P), S.value.addEventListener("strict:reject", F), p.disabled && C.value.setDisabled(p.disabled), p.readonly && C.value.setReadonly(p.readonly), T.value = C.value.getSelectedCountryData()?.iso2 ?? "", C.value.promise.then(() => {
2621
2627
  C.value?.isActive() && (v.value && C.value.setNumber(v.value), O ? (O = !1, M()) : (w.value = C.value.getNumber() ?? "", E.value = k(), D.value = E.value ? null : C.value.getValidationError()));
2622
2628
  }));
2623
2629
  }), u(() => p.disabled, (e) => C.value?.setDisabled(e)), u(() => p.readonly, (e) => C.value?.setReadonly(e)), u(() => v.value, (e) => {
@@ -2626,7 +2632,9 @@ var p = new Set(f.map((e) => e.iso2)), m = (e) => p.has(e), h = f, g = {
2626
2632
  let t = e ?? "", n = C.value.getNumber() ?? "";
2627
2633
  document.activeElement === S.value || n === t || (C.value.setNumber(t), A());
2628
2634
  });
2629
- }, { flush: "post" }), o(() => C.value?.destroy()), d({
2635
+ }, { flush: "post" }), o(() => {
2636
+ S.value && (S.value.removeEventListener("open:countrydropdown", N), S.value.removeEventListener("close:countrydropdown", P), S.value.removeEventListener("strict:reject", F)), C.value?.destroy();
2637
+ }), d({
2630
2638
  instance: C,
2631
2639
  input: S
2632
2640
  }), (e, n) => (s(), t("input", i(_.value, {
@@ -1,4 +1,4 @@
1
- import { n as e, t } from "./IntlTelInput-SQtNzOVr.js";
1
+ import { n as e, t } from "./IntlTelInput-CzuiSLVt.js";
2
2
  //#region vue/src/index.ts
3
3
  var n = t;
4
4
  //#endregion