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.
@@ -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
  */
@@ -1792,6 +1792,29 @@ var _factory = (() => {
1792
1792
  // used for synthetic input trigger
1793
1793
  STRICT_REJECT: "strict:reject"
1794
1794
  };
1795
+ var ITI_SLOTS = [
1796
+ "container",
1797
+ "input",
1798
+ "countryContainer",
1799
+ "selectedCountry",
1800
+ "selectedCountryPrimary",
1801
+ "selectedFlag",
1802
+ "arrow",
1803
+ "selectedDialCode",
1804
+ "countrySelector",
1805
+ "countrySelectorContainer",
1806
+ "searchWrapper",
1807
+ "searchIcon",
1808
+ "searchInput",
1809
+ "searchClear",
1810
+ "countryList",
1811
+ "countryListItem",
1812
+ "countryListItemFlag",
1813
+ "countryName",
1814
+ "dialCode",
1815
+ "countryCheck",
1816
+ "noResults"
1817
+ ];
1795
1818
  var CLASSES = {
1796
1819
  HIDE: "iti__hide",
1797
1820
  V_HIDE: "iti__v-hide",
@@ -1968,6 +1991,8 @@ var _factory = (() => {
1968
1991
  allowNumberExtensions: false,
1969
1992
  // Allow alphanumeric "phonewords" (e.g. +1 800 FLOWERS) as valid numbers
1970
1993
  allowPhonewords: false,
1994
+ //* Add custom classes to the elements we generate, keyed by slot name e.g. { selectedCountry: "rounded-l-lg" }.
1995
+ classNames: {},
1971
1996
  //* Add a custom class to the (injected) container element.
1972
1997
  containerClass: "",
1973
1998
  //* Locale for localising country names via Intl.DisplayNames.
@@ -2030,6 +2055,7 @@ var _factory = (() => {
2030
2055
  return v.nodeType === 1 && typeof v.tagName === "string" && typeof v.appendChild === "function";
2031
2056
  };
2032
2057
  var placeholderPolicySet = new Set(Object.values(PLACEHOLDER_POLICY));
2058
+ var slotSet = new Set(ITI_SLOTS);
2033
2059
  var warn = (message) => {
2034
2060
  console.warn(`[intl-tel-input] ${message}`);
2035
2061
  };
@@ -2130,6 +2156,26 @@ var _factory = (() => {
2130
2156
  }
2131
2157
  validatedOptions[key] = value;
2132
2158
  break;
2159
+ case "classNames": {
2160
+ if (!isPlainObject(value)) {
2161
+ warnOption("classNames", "an object", value);
2162
+ break;
2163
+ }
2164
+ const validSlots = {};
2165
+ for (const [slot, slotValue] of Object.entries(value)) {
2166
+ if (!slotSet.has(slot)) {
2167
+ warn(
2168
+ `Unknown slot '${slot}' in 'classNames'. Valid slots: ${ITI_SLOTS.join(", ")}. Skipping.`
2169
+ );
2170
+ } else if (typeof slotValue !== "string") {
2171
+ warnOption(`classNames.${slot}`, "a string", slotValue);
2172
+ } else {
2173
+ validSlots[slot] = slotValue.trim().replace(/\s+/g, " ");
2174
+ }
2175
+ }
2176
+ validatedOptions[key] = validSlots;
2177
+ break;
2178
+ }
2133
2179
  case "countryOrder": {
2134
2180
  if (value === null) {
2135
2181
  validatedOptions[key] = value;
@@ -2542,11 +2588,18 @@ var _factory = (() => {
2542
2588
  );
2543
2589
  }
2544
2590
  }
2591
+ //* Append any consumer-supplied classes (via the classNames option) for the given slot to our own classes for that element.
2592
+ #withSlotClass(slot, ourClasses) {
2593
+ const custom = this.#options.classNames[slot];
2594
+ return custom ? `${ourClasses} ${custom}` : ourClasses;
2595
+ }
2545
2596
  //* Generate all of the markup for the core library: the selected country overlay, and the country selector.
2546
2597
  buildMarkup(countries, searchTokens) {
2547
2598
  this.#countries = countries;
2548
2599
  this.#searchTokens = searchTokens;
2549
- this.telInputEl.classList.add("iti__tel-input");
2600
+ this.telInputEl.classList.add(
2601
+ ...this.#withSlotClass("input", "iti__tel-input").split(" ")
2602
+ );
2550
2603
  if (!this.telInputEl.hasAttribute("type")) {
2551
2604
  this.telInputEl.setAttribute("type", "tel");
2552
2605
  }
@@ -2574,7 +2627,9 @@ var _factory = (() => {
2574
2627
  "iti--inline-country-selector": countrySelectorMode !== COUNTRY_SELECTOR_MODE.FULLSCREEN,
2575
2628
  [containerClass]: Boolean(containerClass)
2576
2629
  });
2577
- const wrapper = createEl("div", { class: parentClasses });
2630
+ const wrapper = createEl("div", {
2631
+ class: this.#withSlotClass("container", parentClasses)
2632
+ });
2578
2633
  if (this.#isRTL) {
2579
2634
  wrapper.setAttribute("dir", "ltr");
2580
2635
  }
@@ -2590,7 +2645,12 @@ var _factory = (() => {
2590
2645
  this.#countryContainerEl = createEl(
2591
2646
  "div",
2592
2647
  // visibly hidden until we measure its width to set the input padding correctly
2593
- { class: `iti__country-container ${CLASSES.V_HIDE}` },
2648
+ {
2649
+ class: this.#withSlotClass(
2650
+ "countryContainer",
2651
+ `iti__country-container ${CLASSES.V_HIDE}`
2652
+ )
2653
+ },
2594
2654
  wrapper
2595
2655
  );
2596
2656
  if (enableCountrySelector) {
@@ -2598,7 +2658,7 @@ var _factory = (() => {
2598
2658
  "button",
2599
2659
  {
2600
2660
  type: "button",
2601
- class: "iti__selected-country",
2661
+ class: this.#withSlotClass("selectedCountry", "iti__selected-country"),
2602
2662
  [ARIA.EXPANDED]: "false",
2603
2663
  [ARIA.LABEL]: this.#options.uiTranslations.noCountrySelected,
2604
2664
  [ARIA.HASPOPUP]: "dialog",
@@ -2612,31 +2672,44 @@ var _factory = (() => {
2612
2672
  } else {
2613
2673
  this.#selectedCountryEl = createEl(
2614
2674
  "div",
2615
- { class: "iti__selected-country" },
2675
+ { class: this.#withSlotClass("selectedCountry", "iti__selected-country") },
2616
2676
  this.#countryContainerEl
2617
2677
  );
2618
2678
  }
2619
2679
  const selectedCountryPrimary = createEl(
2620
2680
  "div",
2621
- { class: "iti__selected-country-primary" },
2681
+ {
2682
+ class: this.#withSlotClass(
2683
+ "selectedCountryPrimary",
2684
+ "iti__selected-country-primary"
2685
+ )
2686
+ },
2622
2687
  this.#selectedCountryEl
2623
2688
  );
2624
2689
  this.#selectedFlagEl = createEl(
2625
2690
  "div",
2626
- { class: CLASSES.FLAG },
2691
+ { class: this.#withSlotClass("selectedFlag", CLASSES.FLAG) },
2627
2692
  selectedCountryPrimary
2628
2693
  );
2629
2694
  if (enableCountrySelector) {
2630
2695
  this.#arrowEl = createEl(
2631
2696
  "div",
2632
- { class: "iti__arrow", [ARIA.HIDDEN]: "true" },
2697
+ {
2698
+ class: this.#withSlotClass("arrow", "iti__arrow"),
2699
+ [ARIA.HIDDEN]: "true"
2700
+ },
2633
2701
  selectedCountryPrimary
2634
2702
  );
2635
2703
  }
2636
2704
  if (separateDialCode) {
2637
2705
  this.#selectedDialCodeEl = createEl(
2638
2706
  "div",
2639
- { class: "iti__selected-dial-code" },
2707
+ {
2708
+ class: this.#withSlotClass(
2709
+ "selectedDialCode",
2710
+ "iti__selected-dial-code"
2711
+ )
2712
+ },
2640
2713
  this.#selectedCountryEl
2641
2714
  );
2642
2715
  }
@@ -2667,7 +2740,10 @@ var _factory = (() => {
2667
2740
  const extraClasses = matchDropdownWidth ? "" : "iti--flexible-dropdown-width";
2668
2741
  this.#countrySelectorEl = createEl("div", {
2669
2742
  id: `iti-${this.#id}__country-selector`,
2670
- class: `iti__country-selector ${CLASSES.HIDE} ${extraClasses}`,
2743
+ class: this.#withSlotClass(
2744
+ "countrySelector",
2745
+ `iti__country-selector ${CLASSES.HIDE} ${extraClasses}`
2746
+ ),
2671
2747
  role: "dialog",
2672
2748
  [ARIA.MODAL]: "true"
2673
2749
  });
@@ -2680,7 +2756,7 @@ var _factory = (() => {
2680
2756
  this.#countryListEl = createEl(
2681
2757
  "ul",
2682
2758
  {
2683
- class: "iti__country-list",
2759
+ class: this.#withSlotClass("countryList", "iti__country-list"),
2684
2760
  id: `iti-${this.#id}__country-listbox`,
2685
2761
  role: "listbox",
2686
2762
  [ARIA.LABEL]: uiTranslations.countryListAriaLabel
@@ -2699,7 +2775,9 @@ var _factory = (() => {
2699
2775
  "iti--inline-country-selector": !isFullscreen,
2700
2776
  [containerClass]: Boolean(containerClass)
2701
2777
  });
2702
- this.#detachedCountrySelectorEl = createEl("div", { class: wrapperClasses });
2778
+ this.#detachedCountrySelectorEl = createEl("div", {
2779
+ class: this.#withSlotClass("countrySelectorContainer", wrapperClasses)
2780
+ });
2703
2781
  this.#detachedCountrySelectorEl.appendChild(this.#countrySelectorEl);
2704
2782
  } else {
2705
2783
  this.#countryContainerEl.appendChild(this.#countrySelectorEl);
@@ -2720,13 +2798,13 @@ var _factory = (() => {
2720
2798
  const { uiTranslations, searchInputClass } = this.#options;
2721
2799
  const searchWrapper = createEl(
2722
2800
  "div",
2723
- { class: "iti__search-input-wrapper" },
2801
+ { class: this.#withSlotClass("searchWrapper", "iti__search-input-wrapper") },
2724
2802
  this.#countrySelectorEl
2725
2803
  );
2726
2804
  this.#searchIconEl = createEl(
2727
2805
  "span",
2728
2806
  {
2729
- class: "iti__search-icon",
2807
+ class: this.#withSlotClass("searchIcon", "iti__search-icon"),
2730
2808
  [ARIA.HIDDEN]: "true"
2731
2809
  },
2732
2810
  searchWrapper
@@ -2738,7 +2816,10 @@ var _factory = (() => {
2738
2816
  id: `iti-${this.#id}__search-input`,
2739
2817
  // Chrome says inputs need either a name or an id
2740
2818
  type: "search",
2741
- class: `iti__search-input ${searchInputClass}`,
2819
+ class: this.#withSlotClass(
2820
+ "searchInput",
2821
+ `iti__search-input ${searchInputClass}`
2822
+ ),
2742
2823
  placeholder: uiTranslations.searchPlaceholder,
2743
2824
  // 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
2744
2825
  role: "combobox",
@@ -2754,7 +2835,10 @@ var _factory = (() => {
2754
2835
  "button",
2755
2836
  {
2756
2837
  type: "button",
2757
- class: `iti__search-clear ${CLASSES.HIDE}`,
2838
+ class: this.#withSlotClass(
2839
+ "searchClear",
2840
+ `iti__search-clear ${CLASSES.HIDE}`
2841
+ ),
2758
2842
  [ARIA.LABEL]: uiTranslations.clearSearchAriaLabel,
2759
2843
  tabindex: "-1"
2760
2844
  },
@@ -2769,7 +2853,7 @@ var _factory = (() => {
2769
2853
  this.#noResultsMessageEl = createEl(
2770
2854
  "div",
2771
2855
  {
2772
- class: `iti__no-results ${CLASSES.HIDE}`,
2856
+ class: this.#withSlotClass("noResults", `iti__no-results ${CLASSES.HIDE}`),
2773
2857
  [ARIA.HIDDEN]: "true"
2774
2858
  // all a11y messaging happens in this.#searchResultsLiveRegionEl
2775
2859
  },
@@ -2823,11 +2907,9 @@ var _factory = (() => {
2823
2907
  //* For each country: add a country list item <li> to the countryList <ul> container.
2824
2908
  #appendListItems() {
2825
2909
  const frag = document.createDocumentFragment();
2910
+ const liClass = this.#withSlotClass("countryListItem", CLASSES.COUNTRY_ITEM);
2826
2911
  for (let i = 0; i < this.#countries.length; i++) {
2827
2912
  const c = this.#countries[i];
2828
- const liClass = buildClassNames({
2829
- [CLASSES.COUNTRY_ITEM]: true
2830
- });
2831
2913
  const listItem = createEl("li", {
2832
2914
  id: `iti-${this.#id}__item-${c.iso2}`,
2833
2915
  class: liClass,
@@ -2839,11 +2921,28 @@ var _factory = (() => {
2839
2921
  listItem.dataset[DATA_KEYS.ISO2] = c.iso2;
2840
2922
  this.#listItemByIso2.set(c.iso2, listItem);
2841
2923
  if (this.#options.showFlags) {
2842
- createEl("div", { class: `${CLASSES.FLAG} iti__${c.iso2}` }, listItem);
2924
+ createEl(
2925
+ "div",
2926
+ {
2927
+ class: this.#withSlotClass(
2928
+ "countryListItemFlag",
2929
+ `${CLASSES.FLAG} iti__${c.iso2}`
2930
+ )
2931
+ },
2932
+ listItem
2933
+ );
2843
2934
  }
2844
- const nameEl = createEl("span", { class: "iti__country-name" }, listItem);
2935
+ const nameEl = createEl(
2936
+ "span",
2937
+ { class: this.#withSlotClass("countryName", "iti__country-name") },
2938
+ listItem
2939
+ );
2845
2940
  nameEl.textContent = `${c.name} `;
2846
- const dialEl = createEl("span", { class: "iti__dial-code" }, nameEl);
2941
+ const dialEl = createEl(
2942
+ "span",
2943
+ { class: this.#withSlotClass("dialCode", "iti__dial-code") },
2944
+ nameEl
2945
+ );
2847
2946
  if (this.#isRTL) {
2848
2947
  dialEl.setAttribute("dir", "ltr");
2849
2948
  }
@@ -3290,7 +3389,10 @@ var _factory = (() => {
3290
3389
  newListItem.setAttribute(ARIA.SELECTED, "true");
3291
3390
  const checkIcon = createEl(
3292
3391
  "span",
3293
- { class: "iti__country-check", [ARIA.HIDDEN]: "true" },
3392
+ {
3393
+ class: this.#withSlotClass("countryCheck", "iti__country-check"),
3394
+ [ARIA.HIDDEN]: "true"
3395
+ },
3294
3396
  newListItem
3295
3397
  );
3296
3398
  checkIcon.appendChild(buildCheckIcon());
@@ -3477,7 +3579,10 @@ var _factory = (() => {
3477
3579
  this.#updateSelectedListItem(iso2);
3478
3580
  }
3479
3581
  if (this.#selectedCountryEl) {
3480
- const flagClass = iso2 && showFlags ? `${CLASSES.FLAG} iti__${iso2}` : `${CLASSES.FLAG} ${CLASSES.GLOBE}`;
3582
+ const flagClass = this.#withSlotClass(
3583
+ "selectedFlag",
3584
+ iso2 && showFlags ? `${CLASSES.FLAG} iti__${iso2}` : `${CLASSES.FLAG} ${CLASSES.GLOBE}`
3585
+ );
3481
3586
  let ariaLabel, title;
3482
3587
  let flagContent = null;
3483
3588
  if (iso2) {
@@ -4874,7 +4979,7 @@ var _factory = (() => {
4874
4979
  attachUtils,
4875
4980
  startedLoadingUtils: false,
4876
4981
  startedLoadingAutoCountry: false,
4877
- version: "29.1.3",
4982
+ version: "29.2.0",
4878
4983
  NUMBER_FORMAT,
4879
4984
  NUMBER_TYPE,
4880
4985
  VALIDATION_ERROR,