intl-tel-input 29.1.3 → 29.2.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.
package/dist/js/data.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * International Telephone Input v29.1.3
2
+ * International Telephone Input v29.2.0
3
3
  * git+https://github.com/jackocnr/intl-tel-input.git
4
4
  * Licensed under the MIT license
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*
2
- * International Telephone Input v29.1.3
2
+ * International Telephone Input v29.2.0
3
3
  * git+https://github.com/jackocnr/intl-tel-input.git
4
4
  * Licensed under the MIT license
5
5
  */
@@ -1616,6 +1616,29 @@ export type UiTranslations = {
1616
1616
  searchSummaryAria?: (count: number) => string;
1617
1617
  countryNames?: Partial<Record<Iso2, string>>;
1618
1618
  };
1619
+ declare const ITI_SLOTS: readonly [
1620
+ "container",
1621
+ "input",
1622
+ "countryContainer",
1623
+ "selectedCountry",
1624
+ "selectedCountryPrimary",
1625
+ "selectedFlag",
1626
+ "arrow",
1627
+ "selectedDialCode",
1628
+ "countrySelector",
1629
+ "countrySelectorContainer",
1630
+ "searchWrapper",
1631
+ "searchIcon",
1632
+ "searchInput",
1633
+ "searchClear",
1634
+ "countryList",
1635
+ "countryListItem",
1636
+ "countryListItemFlag",
1637
+ "countryName",
1638
+ "dialCode",
1639
+ "countryCheck",
1640
+ "noResults"
1641
+ ];
1619
1642
  export declare const PLACEHOLDER_POLICY: {
1620
1643
  readonly AGGRESSIVE: "AGGRESSIVE";
1621
1644
  readonly POLITE: "POLITE";
@@ -1709,11 +1732,63 @@ export type NumberType = ArrayValues<typeof NUMBER_TYPES>;
1709
1732
  export type ValidationError = ArrayValues<typeof VALIDATION_ERRORS>;
1710
1733
  export type ValueOf<T> = T[keyof T];
1711
1734
  export type CountrySelectorMode = ArrayValues<typeof COUNTRY_SELECTOR_MODES>;
1735
+ export type ItiSlot = ArrayValues<typeof ITI_SLOTS>;
1736
+ export interface ItiClassNames {
1737
+ /** The injected `<div class="iti">` wrapping the input and the selected country. */
1738
+ container?: string;
1739
+ /** The `<input>` itself. */
1740
+ input?: string;
1741
+ /** The `<div>` wrapping the selected country, which overlays the left of the input. */
1742
+ countryContainer?: string;
1743
+ /** The selected country `<button>` (or `<div>` when the country selector is disabled). */
1744
+ selectedCountry?: string;
1745
+ /** The `<div>` inside the selected country that gets the hover highlight. */
1746
+ selectedCountryPrimary?: string;
1747
+ /** The selected country's flag (or globe icon) `<div>`. */
1748
+ selectedFlag?: string;
1749
+ /** The dropdown arrow `<div>`. */
1750
+ arrow?: string;
1751
+ /** The selected country's dial code `<div>`. Requires `separateDialCode`. */
1752
+ selectedDialCode?: string;
1753
+ /** The country selector `<div>` i.e. the dropdown or the fullscreen popup. */
1754
+ countrySelector?: string;
1755
+ /**
1756
+ * The `<div>` wrapping the country selector when it is rendered outside the
1757
+ * main container — i.e. the fullscreen popup, or when `dropdownParent` is set.
1758
+ * This element only handles positioning, so it is mainly useful for getting a
1759
+ * scoping class (e.g. a theme class) onto a country selector that would
1760
+ * otherwise escape it. Does not exist for a normal inline dropdown.
1761
+ */
1762
+ countrySelectorContainer?: string;
1763
+ /** The `<div>` wrapping the country search input and its icons. Requires `countrySearch`. */
1764
+ searchWrapper?: string;
1765
+ /** The search (magnifying glass) icon `<span>`. Requires `countrySearch`. */
1766
+ searchIcon?: string;
1767
+ /** The country search `<input>`. Requires `countrySearch`. */
1768
+ searchInput?: string;
1769
+ /** The clear-search `<button>`. Requires `countrySearch`. */
1770
+ searchClear?: string;
1771
+ /** The country list `<ul>`. */
1772
+ countryList?: string;
1773
+ /** Every country `<li>` in the country list. */
1774
+ countryListItem?: string;
1775
+ /** The flag `<div>` inside every country `<li>`. Requires `showFlags`. */
1776
+ countryListItemFlag?: string;
1777
+ /** The country name `<span>` inside every country `<li>`. */
1778
+ countryName?: string;
1779
+ /** The dial code `<span>` inside every country name. */
1780
+ dialCode?: string;
1781
+ /** The check icon `<span>` added to the currently selected country `<li>`. */
1782
+ countryCheck?: string;
1783
+ /** The "no results" message `<div>`. Requires `countrySearch`. */
1784
+ noResults?: string;
1785
+ }
1712
1786
  export interface AllOptions {
1713
1787
  countrySelectorMode: CountrySelectorMode;
1714
1788
  allowedNumberTypes: NumberType[] | null;
1715
1789
  allowNumberExtensions: boolean;
1716
1790
  allowPhonewords: boolean;
1791
+ classNames: ItiClassNames;
1717
1792
  containerClass: string;
1718
1793
  countryNameLocale: string;
1719
1794
  countryNameOverrides: Partial<Record<Iso2, string>>;
@@ -1,5 +1,5 @@
1
1
  /*
2
- * International Telephone Input v29.1.3
2
+ * International Telephone Input v29.2.0
3
3
  * git+https://github.com/jackocnr/intl-tel-input.git
4
4
  * Licensed under the MIT license
5
5
  */
@@ -1798,6 +1798,29 @@ var _factory = (() => {
1798
1798
  // used for synthetic input trigger
1799
1799
  STRICT_REJECT: "strict:reject"
1800
1800
  };
1801
+ var ITI_SLOTS = [
1802
+ "container",
1803
+ "input",
1804
+ "countryContainer",
1805
+ "selectedCountry",
1806
+ "selectedCountryPrimary",
1807
+ "selectedFlag",
1808
+ "arrow",
1809
+ "selectedDialCode",
1810
+ "countrySelector",
1811
+ "countrySelectorContainer",
1812
+ "searchWrapper",
1813
+ "searchIcon",
1814
+ "searchInput",
1815
+ "searchClear",
1816
+ "countryList",
1817
+ "countryListItem",
1818
+ "countryListItemFlag",
1819
+ "countryName",
1820
+ "dialCode",
1821
+ "countryCheck",
1822
+ "noResults"
1823
+ ];
1801
1824
  var CLASSES = {
1802
1825
  HIDE: "iti__hide",
1803
1826
  V_HIDE: "iti__v-hide",
@@ -1974,6 +1997,8 @@ var _factory = (() => {
1974
1997
  allowNumberExtensions: false,
1975
1998
  // Allow alphanumeric "phonewords" (e.g. +1 800 FLOWERS) as valid numbers
1976
1999
  allowPhonewords: false,
2000
+ //* Add custom classes to the elements we generate, keyed by slot name e.g. { selectedCountry: "rounded-l-lg" }.
2001
+ classNames: {},
1977
2002
  //* Add a custom class to the (injected) container element.
1978
2003
  containerClass: "",
1979
2004
  //* Locale for localising country names via Intl.DisplayNames.
@@ -2036,6 +2061,7 @@ var _factory = (() => {
2036
2061
  return v.nodeType === 1 && typeof v.tagName === "string" && typeof v.appendChild === "function";
2037
2062
  };
2038
2063
  var placeholderPolicySet = new Set(Object.values(PLACEHOLDER_POLICY));
2064
+ var slotSet = new Set(ITI_SLOTS);
2039
2065
  var warn = (message) => {
2040
2066
  console.warn(`[intl-tel-input] ${message}`);
2041
2067
  };
@@ -2136,6 +2162,26 @@ var _factory = (() => {
2136
2162
  }
2137
2163
  validatedOptions[key] = value;
2138
2164
  break;
2165
+ case "classNames": {
2166
+ if (!isPlainObject(value)) {
2167
+ warnOption("classNames", "an object", value);
2168
+ break;
2169
+ }
2170
+ const validSlots = {};
2171
+ for (const [slot, slotValue] of Object.entries(value)) {
2172
+ if (!slotSet.has(slot)) {
2173
+ warn(
2174
+ `Unknown slot '${slot}' in 'classNames'. Valid slots: ${ITI_SLOTS.join(", ")}. Skipping.`
2175
+ );
2176
+ } else if (typeof slotValue !== "string") {
2177
+ warnOption(`classNames.${slot}`, "a string", slotValue);
2178
+ } else {
2179
+ validSlots[slot] = slotValue.trim().replace(/\s+/g, " ");
2180
+ }
2181
+ }
2182
+ validatedOptions[key] = validSlots;
2183
+ break;
2184
+ }
2139
2185
  case "countryOrder": {
2140
2186
  if (value === null) {
2141
2187
  validatedOptions[key] = value;
@@ -2548,11 +2594,18 @@ var _factory = (() => {
2548
2594
  );
2549
2595
  }
2550
2596
  }
2597
+ //* Append any consumer-supplied classes (via the classNames option) for the given slot to our own classes for that element.
2598
+ #withSlotClass(slot, ourClasses) {
2599
+ const custom = this.#options.classNames[slot];
2600
+ return custom ? `${ourClasses} ${custom}` : ourClasses;
2601
+ }
2551
2602
  //* Generate all of the markup for the core library: the selected country overlay, and the country selector.
2552
2603
  buildMarkup(countries, searchTokens) {
2553
2604
  this.#countries = countries;
2554
2605
  this.#searchTokens = searchTokens;
2555
- this.telInputEl.classList.add("iti__tel-input");
2606
+ this.telInputEl.classList.add(
2607
+ ...this.#withSlotClass("input", "iti__tel-input").split(" ")
2608
+ );
2556
2609
  if (!this.telInputEl.hasAttribute("type")) {
2557
2610
  this.telInputEl.setAttribute("type", "tel");
2558
2611
  }
@@ -2580,7 +2633,9 @@ var _factory = (() => {
2580
2633
  "iti--inline-country-selector": countrySelectorMode !== COUNTRY_SELECTOR_MODE.FULLSCREEN,
2581
2634
  [containerClass]: Boolean(containerClass)
2582
2635
  });
2583
- const wrapper = createEl("div", { class: parentClasses });
2636
+ const wrapper = createEl("div", {
2637
+ class: this.#withSlotClass("container", parentClasses)
2638
+ });
2584
2639
  if (this.#isRTL) {
2585
2640
  wrapper.setAttribute("dir", "ltr");
2586
2641
  }
@@ -2596,7 +2651,12 @@ var _factory = (() => {
2596
2651
  this.#countryContainerEl = createEl(
2597
2652
  "div",
2598
2653
  // visibly hidden until we measure its width to set the input padding correctly
2599
- { class: `iti__country-container ${CLASSES.V_HIDE}` },
2654
+ {
2655
+ class: this.#withSlotClass(
2656
+ "countryContainer",
2657
+ `iti__country-container ${CLASSES.V_HIDE}`
2658
+ )
2659
+ },
2600
2660
  wrapper
2601
2661
  );
2602
2662
  if (enableCountrySelector) {
@@ -2604,7 +2664,7 @@ var _factory = (() => {
2604
2664
  "button",
2605
2665
  {
2606
2666
  type: "button",
2607
- class: "iti__selected-country",
2667
+ class: this.#withSlotClass("selectedCountry", "iti__selected-country"),
2608
2668
  [ARIA.EXPANDED]: "false",
2609
2669
  [ARIA.LABEL]: this.#options.uiTranslations.noCountrySelected,
2610
2670
  [ARIA.HASPOPUP]: "dialog",
@@ -2618,31 +2678,44 @@ var _factory = (() => {
2618
2678
  } else {
2619
2679
  this.#selectedCountryEl = createEl(
2620
2680
  "div",
2621
- { class: "iti__selected-country" },
2681
+ { class: this.#withSlotClass("selectedCountry", "iti__selected-country") },
2622
2682
  this.#countryContainerEl
2623
2683
  );
2624
2684
  }
2625
2685
  const selectedCountryPrimary = createEl(
2626
2686
  "div",
2627
- { class: "iti__selected-country-primary" },
2687
+ {
2688
+ class: this.#withSlotClass(
2689
+ "selectedCountryPrimary",
2690
+ "iti__selected-country-primary"
2691
+ )
2692
+ },
2628
2693
  this.#selectedCountryEl
2629
2694
  );
2630
2695
  this.#selectedFlagEl = createEl(
2631
2696
  "div",
2632
- { class: CLASSES.FLAG },
2697
+ { class: this.#withSlotClass("selectedFlag", CLASSES.FLAG) },
2633
2698
  selectedCountryPrimary
2634
2699
  );
2635
2700
  if (enableCountrySelector) {
2636
2701
  this.#arrowEl = createEl(
2637
2702
  "div",
2638
- { class: "iti__arrow", [ARIA.HIDDEN]: "true" },
2703
+ {
2704
+ class: this.#withSlotClass("arrow", "iti__arrow"),
2705
+ [ARIA.HIDDEN]: "true"
2706
+ },
2639
2707
  selectedCountryPrimary
2640
2708
  );
2641
2709
  }
2642
2710
  if (separateDialCode) {
2643
2711
  this.#selectedDialCodeEl = createEl(
2644
2712
  "div",
2645
- { class: "iti__selected-dial-code" },
2713
+ {
2714
+ class: this.#withSlotClass(
2715
+ "selectedDialCode",
2716
+ "iti__selected-dial-code"
2717
+ )
2718
+ },
2646
2719
  this.#selectedCountryEl
2647
2720
  );
2648
2721
  }
@@ -2673,7 +2746,10 @@ var _factory = (() => {
2673
2746
  const extraClasses = matchDropdownWidth ? "" : "iti--flexible-dropdown-width";
2674
2747
  this.#countrySelectorEl = createEl("div", {
2675
2748
  id: `iti-${this.#id}__country-selector`,
2676
- class: `iti__country-selector ${CLASSES.HIDE} ${extraClasses}`,
2749
+ class: this.#withSlotClass(
2750
+ "countrySelector",
2751
+ `iti__country-selector ${CLASSES.HIDE} ${extraClasses}`
2752
+ ),
2677
2753
  role: "dialog",
2678
2754
  [ARIA.MODAL]: "true"
2679
2755
  });
@@ -2686,7 +2762,7 @@ var _factory = (() => {
2686
2762
  this.#countryListEl = createEl(
2687
2763
  "ul",
2688
2764
  {
2689
- class: "iti__country-list",
2765
+ class: this.#withSlotClass("countryList", "iti__country-list"),
2690
2766
  id: `iti-${this.#id}__country-listbox`,
2691
2767
  role: "listbox",
2692
2768
  [ARIA.LABEL]: uiTranslations.countryListAriaLabel
@@ -2705,7 +2781,9 @@ var _factory = (() => {
2705
2781
  "iti--inline-country-selector": !isFullscreen,
2706
2782
  [containerClass]: Boolean(containerClass)
2707
2783
  });
2708
- this.#detachedCountrySelectorEl = createEl("div", { class: wrapperClasses });
2784
+ this.#detachedCountrySelectorEl = createEl("div", {
2785
+ class: this.#withSlotClass("countrySelectorContainer", wrapperClasses)
2786
+ });
2709
2787
  this.#detachedCountrySelectorEl.appendChild(this.#countrySelectorEl);
2710
2788
  } else {
2711
2789
  this.#countryContainerEl.appendChild(this.#countrySelectorEl);
@@ -2726,13 +2804,13 @@ var _factory = (() => {
2726
2804
  const { uiTranslations, searchInputClass } = this.#options;
2727
2805
  const searchWrapper = createEl(
2728
2806
  "div",
2729
- { class: "iti__search-input-wrapper" },
2807
+ { class: this.#withSlotClass("searchWrapper", "iti__search-input-wrapper") },
2730
2808
  this.#countrySelectorEl
2731
2809
  );
2732
2810
  this.#searchIconEl = createEl(
2733
2811
  "span",
2734
2812
  {
2735
- class: "iti__search-icon",
2813
+ class: this.#withSlotClass("searchIcon", "iti__search-icon"),
2736
2814
  [ARIA.HIDDEN]: "true"
2737
2815
  },
2738
2816
  searchWrapper
@@ -2744,7 +2822,10 @@ var _factory = (() => {
2744
2822
  id: `iti-${this.#id}__search-input`,
2745
2823
  // Chrome says inputs need either a name or an id
2746
2824
  type: "search",
2747
- class: `iti__search-input ${searchInputClass}`,
2825
+ class: this.#withSlotClass(
2826
+ "searchInput",
2827
+ `iti__search-input ${searchInputClass}`
2828
+ ),
2748
2829
  placeholder: uiTranslations.searchPlaceholder,
2749
2830
  // role=combobox + aria-autocomplete=list + aria-activedescendant allows maintaining focus on the search input while allowing users to navigate search results with up/down keyboard keys
2750
2831
  role: "combobox",
@@ -2760,7 +2841,10 @@ var _factory = (() => {
2760
2841
  "button",
2761
2842
  {
2762
2843
  type: "button",
2763
- class: `iti__search-clear ${CLASSES.HIDE}`,
2844
+ class: this.#withSlotClass(
2845
+ "searchClear",
2846
+ `iti__search-clear ${CLASSES.HIDE}`
2847
+ ),
2764
2848
  [ARIA.LABEL]: uiTranslations.clearSearchAriaLabel,
2765
2849
  tabindex: "-1"
2766
2850
  },
@@ -2775,7 +2859,7 @@ var _factory = (() => {
2775
2859
  this.#noResultsMessageEl = createEl(
2776
2860
  "div",
2777
2861
  {
2778
- class: `iti__no-results ${CLASSES.HIDE}`,
2862
+ class: this.#withSlotClass("noResults", `iti__no-results ${CLASSES.HIDE}`),
2779
2863
  [ARIA.HIDDEN]: "true"
2780
2864
  // all a11y messaging happens in this.#searchResultsLiveRegionEl
2781
2865
  },
@@ -2829,11 +2913,9 @@ var _factory = (() => {
2829
2913
  //* For each country: add a country list item <li> to the countryList <ul> container.
2830
2914
  #appendListItems() {
2831
2915
  const frag = document.createDocumentFragment();
2916
+ const liClass = this.#withSlotClass("countryListItem", CLASSES.COUNTRY_ITEM);
2832
2917
  for (let i = 0; i < this.#countries.length; i++) {
2833
2918
  const c = this.#countries[i];
2834
- const liClass = buildClassNames({
2835
- [CLASSES.COUNTRY_ITEM]: true
2836
- });
2837
2919
  const listItem = createEl("li", {
2838
2920
  id: `iti-${this.#id}__item-${c.iso2}`,
2839
2921
  class: liClass,
@@ -2845,11 +2927,28 @@ var _factory = (() => {
2845
2927
  listItem.dataset[DATA_KEYS.ISO2] = c.iso2;
2846
2928
  this.#listItemByIso2.set(c.iso2, listItem);
2847
2929
  if (this.#options.showFlags) {
2848
- createEl("div", { class: `${CLASSES.FLAG} iti__${c.iso2}` }, listItem);
2930
+ createEl(
2931
+ "div",
2932
+ {
2933
+ class: this.#withSlotClass(
2934
+ "countryListItemFlag",
2935
+ `${CLASSES.FLAG} iti__${c.iso2}`
2936
+ )
2937
+ },
2938
+ listItem
2939
+ );
2849
2940
  }
2850
- const nameEl = createEl("span", { class: "iti__country-name" }, listItem);
2941
+ const nameEl = createEl(
2942
+ "span",
2943
+ { class: this.#withSlotClass("countryName", "iti__country-name") },
2944
+ listItem
2945
+ );
2851
2946
  nameEl.textContent = `${c.name} `;
2852
- const dialEl = createEl("span", { class: "iti__dial-code" }, nameEl);
2947
+ const dialEl = createEl(
2948
+ "span",
2949
+ { class: this.#withSlotClass("dialCode", "iti__dial-code") },
2950
+ nameEl
2951
+ );
2853
2952
  if (this.#isRTL) {
2854
2953
  dialEl.setAttribute("dir", "ltr");
2855
2954
  }
@@ -3296,7 +3395,10 @@ var _factory = (() => {
3296
3395
  newListItem.setAttribute(ARIA.SELECTED, "true");
3297
3396
  const checkIcon = createEl(
3298
3397
  "span",
3299
- { class: "iti__country-check", [ARIA.HIDDEN]: "true" },
3398
+ {
3399
+ class: this.#withSlotClass("countryCheck", "iti__country-check"),
3400
+ [ARIA.HIDDEN]: "true"
3401
+ },
3300
3402
  newListItem
3301
3403
  );
3302
3404
  checkIcon.appendChild(buildCheckIcon());
@@ -3483,7 +3585,10 @@ var _factory = (() => {
3483
3585
  this.#updateSelectedListItem(iso2);
3484
3586
  }
3485
3587
  if (this.#selectedCountryEl) {
3486
- const flagClass = iso2 && showFlags ? `${CLASSES.FLAG} iti__${iso2}` : `${CLASSES.FLAG} ${CLASSES.GLOBE}`;
3588
+ const flagClass = this.#withSlotClass(
3589
+ "selectedFlag",
3590
+ iso2 && showFlags ? `${CLASSES.FLAG} iti__${iso2}` : `${CLASSES.FLAG} ${CLASSES.GLOBE}`
3591
+ );
3487
3592
  let ariaLabel, title;
3488
3593
  let flagContent = null;
3489
3594
  if (iso2) {
@@ -4880,7 +4985,7 @@ var _factory = (() => {
4880
4985
  attachUtils,
4881
4986
  startedLoadingUtils: false,
4882
4987
  startedLoadingAutoCountry: false,
4883
- version: "29.1.3",
4988
+ version: "29.2.0",
4884
4989
  NUMBER_FORMAT,
4885
4990
  NUMBER_TYPE,
4886
4991
  VALIDATION_ERROR,