telpick 2.0.1 → 2.0.3

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.
@@ -554,41 +554,41 @@ const S = [
554
554
  ];
555
555
  (function() {
556
556
  if (typeof document < "u" && document.currentScript && document.currentScript.src) {
557
- const i = document.currentScript.src.replace(/\/[^/]*$/, "");
558
- typeof globalThis < "u" ? globalThis.__TELPICK_SCRIPT_BASE__ = i : typeof window < "u" && (window.__TELPICK_SCRIPT_BASE__ = i);
557
+ const d = document.currentScript.src.replace(/\/[^/]*$/, "");
558
+ typeof globalThis < "u" ? globalThis.__TELPICK_SCRIPT_BASE__ = d : typeof window < "u" && (window.__TELPICK_SCRIPT_BASE__ = d);
559
559
  }
560
560
  })();
561
561
  function P() {
562
- const i = typeof globalThis < "u" && globalThis.__TELPICK_SCRIPT_BASE__ ? globalThis.__TELPICK_SCRIPT_BASE__ : typeof window < "u" && window.__TELPICK_SCRIPT_BASE__ || "";
563
- return i ? `${i.replace(/\/$/, "")}/assets/flags` : "";
562
+ const d = typeof globalThis < "u" && globalThis.__TELPICK_SCRIPT_BASE__ ? globalThis.__TELPICK_SCRIPT_BASE__ : typeof window < "u" && window.__TELPICK_SCRIPT_BASE__ || "";
563
+ return d ? `${d.replace(/\/$/, "")}/assets/flags` : typeof import.meta < "u" && import.meta.url ? new URL("./assets/flags/", self.location).href : "";
564
564
  }
565
565
  class T {
566
- constructor({ code: c = null, onChange: r = () => {
566
+ constructor({ code: n = null, onChange: r = () => {
567
567
  }, styleOverrides: o = {}, baseFlagUrl: t = "" } = {}) {
568
- this.code = c, this.onChange = r, this.styleOverrides = o, this.baseFlagUrl = t || P(), this.codes = [], this.selectedCode = c, this.isDropdownOpen = !1, this.searchQuery = "", this.container = null, this.dropdown = null, this._outsideHandler = null, this._scrollResizeCleanup = null, this._boundUpdatePosition = () => this._updateDropdownPosition(), this._getFlagUrl = this._getFlagUrl.bind(this);
568
+ this.code = n, this.onChange = r, this.styleOverrides = o, this.baseFlagUrl = t || P(), this.codes = [], this.selectedCode = n, this.isDropdownOpen = !1, this.searchQuery = "", this.container = null, this.dropdown = null, this._outsideHandler = null, this._scrollResizeCleanup = null, this._boundUpdatePosition = () => this._updateDropdownPosition(), this._getFlagUrl = this._getFlagUrl.bind(this);
569
569
  }
570
570
  _updateDropdownPosition() {
571
571
  if (!this.dropdown || !this.container)
572
572
  return;
573
- const c = this.container.getBoundingClientRect();
574
- this.dropdown.style.position = "fixed", this.dropdown.style.top = `${c.bottom + 4}px`, this.dropdown.style.left = `${c.left}px`, this.dropdown.style.marginTop = "0";
573
+ const n = this.container.getBoundingClientRect();
574
+ this.dropdown.style.position = "fixed", this.dropdown.style.top = `${n.bottom + 4}px`, this.dropdown.style.left = `${n.left}px`, this.dropdown.style.marginTop = "0";
575
575
  }
576
- _getFlagUrl(c, r) {
577
- const o = c ? c.replace(/^.*\//, "") : r ? `${String(r).toLowerCase()}.webp` : "";
576
+ _getFlagUrl(n, r) {
577
+ const o = n ? n.replace(/^.*\//, "") : r ? `${String(r).toLowerCase()}.webp` : "";
578
578
  if (!o && !r)
579
579
  return "";
580
580
  if (this.baseFlagUrl) {
581
581
  const t = this.baseFlagUrl.replace(/\/$/, "");
582
582
  if (t.includes("flagcdn.com")) {
583
- const l = String(r || o && o.replace(/\.[^.]+$/, "") || "").toLowerCase();
584
- return l ? `${t}/${l}.png` : "";
583
+ const i = String(r || o && o.replace(/\.[^.]+$/, "") || "").toLowerCase();
584
+ return i ? `${t}/${i}.png` : "";
585
585
  }
586
586
  return `${t}/${o}`;
587
587
  }
588
- return c || (r ? `/flags/${String(r).toLowerCase()}.webp` : "");
588
+ return "";
589
589
  }
590
- async init(c) {
591
- if (this.container = c, this.codes = [...S].sort((o, t) => o.country.localeCompare(t.country, "es")), this.code) {
590
+ async init(n) {
591
+ if (this.container = n, this.codes = [...S].sort((o, t) => o.country.localeCompare(t.country, "es")), this.code) {
592
592
  const o = this.codes.find((t) => t.country_code === this.code);
593
593
  o && (this.selectedCode = o.country_code);
594
594
  } else {
@@ -622,10 +622,10 @@ class T {
622
622
  }
623
623
  ];
624
624
  let t = null;
625
- for (const l of o)
625
+ for (const i of o)
626
626
  try {
627
627
  if (t = await Promise.race([
628
- l(),
628
+ i(),
629
629
  new Promise((s) => setTimeout(() => s(null), 3e3))
630
630
  ]), t)
631
631
  break;
@@ -633,7 +633,7 @@ class T {
633
633
  }
634
634
  if (!t)
635
635
  try {
636
- const l = Intl.DateTimeFormat().resolvedOptions().timeZone, e = {
636
+ const i = Intl.DateTimeFormat().resolvedOptions().timeZone, e = {
637
637
  "America/Lima": "PE",
638
638
  "America/Bogota": "CO",
639
639
  "America/Mexico_City": "MX",
@@ -695,15 +695,15 @@ class T {
695
695
  "Africa/Johannesburg": "ZA",
696
696
  "Africa/Nairobi": "KE",
697
697
  "Africa/Lagos": "NG"
698
- }[l];
698
+ }[i];
699
699
  e && (t = this.codes.find((u) => u.country_code === e));
700
700
  } catch {
701
701
  }
702
702
  if (t)
703
703
  this.selectedCode = t.country_code;
704
704
  else {
705
- const l = this.codes.find((s) => s.country_code === "CO");
706
- l && (this.selectedCode = l.country_code);
705
+ const i = this.codes.find((s) => s.country_code === "CO");
706
+ i && (this.selectedCode = i.country_code);
707
707
  }
708
708
  }
709
709
  this.render();
@@ -712,8 +712,8 @@ class T {
712
712
  }
713
713
  render() {
714
714
  this._scrollResizeCleanup && (this._scrollResizeCleanup(), this._scrollResizeCleanup = null), this.dropdown && this.dropdown.parentNode && (this.dropdown.parentNode.removeChild(this.dropdown), this.dropdown = null), this.container.innerHTML = "";
715
- const c = document.createElement("button");
716
- c.className = "telpick-btn", Object.assign(c.style, this.styleOverrides), c.onclick = () => {
715
+ const n = document.createElement("button");
716
+ n.className = "telpick-btn", Object.assign(n.style, this.styleOverrides), n.onclick = () => {
717
717
  this.isDropdownOpen = !this.isDropdownOpen, this.render();
718
718
  };
719
719
  const r = document.createElement("div");
@@ -723,17 +723,17 @@ class T {
723
723
  const e = document.createElement("img");
724
724
  e.src = t, e.className = "w-full h-full object-cover", e.alt = o.country || "flag", e.loading = "lazy", e.referrerPolicy = "no-referrer", r.appendChild(e);
725
725
  }
726
- c.appendChild(r);
727
- const l = document.createElement("span");
728
- l.textContent = o.code, c.appendChild(l);
726
+ n.appendChild(r);
727
+ const i = document.createElement("span");
728
+ i.textContent = o.code, n.appendChild(i);
729
729
  const s = document.createElement("span");
730
- if (s.className = "ml-auto", s.textContent = "▼", c.appendChild(s), this.container.appendChild(c), this.isDropdownOpen) {
731
- this.dropdown = document.createElement("div"), this.dropdown.className = "telpick-dropdown", this.dropdown.onclick = (n) => n.stopPropagation(), this.dropdown.onmousedown = (n) => n.stopPropagation();
730
+ if (s.className = "ml-auto", s.textContent = "▼", n.appendChild(s), this.container.appendChild(n), this.isDropdownOpen) {
731
+ this.dropdown = document.createElement("div"), this.dropdown.className = "telpick-dropdown", this.dropdown.onclick = (c) => c.stopPropagation(), this.dropdown.onmousedown = (c) => c.stopPropagation();
732
732
  const e = document.createElement("input");
733
- e.className = "telpick-search", e.type = "text", e.placeholder = "Buscar país...", e.value = this.searchQuery, e.oninput = (n) => {
733
+ e.className = "telpick-search", e.type = "text", e.placeholder = "Buscar país...", e.value = this.searchQuery, e.oninput = (c) => {
734
734
  var h;
735
- n.stopPropagation();
736
- const d = n.target, _ = d.selectionStart || 0, f = d.value;
735
+ c.stopPropagation();
736
+ const l = c.target, _ = l.selectionStart || 0, f = l.value;
737
737
  this.searchQuery = f;
738
738
  const p = (h = this.dropdown) == null ? void 0 : h.querySelector("ul");
739
739
  p ? (p.innerHTML = "", (this.searchQuery ? this.codes.filter((a) => a.country.toLowerCase().includes(this.searchQuery.toLowerCase())) : this.codes).forEach((a) => {
@@ -760,25 +760,25 @@ class T {
760
760
  e.setSelectionRange(a, a);
761
761
  }
762
762
  })) : this.render();
763
- }, e.onclick = (n) => n.stopPropagation(), e.onmousedown = (n) => n.stopPropagation(), this.dropdown.appendChild(e);
763
+ }, e.onclick = (c) => c.stopPropagation(), e.onmousedown = (c) => c.stopPropagation(), this.dropdown.appendChild(e);
764
764
  const u = document.createElement("ul");
765
- u.style.maxHeight = "130px", u.style.overflowY = "auto", (this.searchQuery ? this.codes.filter((n) => n.country.toLowerCase().includes(this.searchQuery.toLowerCase())) : this.codes).forEach((n) => {
766
- const d = document.createElement("li"), _ = n.country_code === this.selectedCode && this.selectedCode !== null && this.selectedCode !== void 0;
767
- d.className = `telpick-item ${_ ? "telpick-item-selected" : ""}`, d.setAttribute("aria-selected", _), d.onclick = () => {
768
- this.selectedCode = n.country_code, this.onChange(n), this.isDropdownOpen = !1, this.searchQuery = "", this.render();
765
+ u.style.maxHeight = "130px", u.style.overflowY = "auto", (this.searchQuery ? this.codes.filter((c) => c.country.toLowerCase().includes(this.searchQuery.toLowerCase())) : this.codes).forEach((c) => {
766
+ const l = document.createElement("li"), _ = c.country_code === this.selectedCode && this.selectedCode !== null && this.selectedCode !== void 0;
767
+ l.className = `telpick-item ${_ ? "telpick-item-selected" : ""}`, l.setAttribute("aria-selected", _), l.onclick = () => {
768
+ this.selectedCode = c.country_code, this.onChange(c), this.isDropdownOpen = !1, this.searchQuery = "", this.render();
769
769
  };
770
770
  const f = document.createElement("div");
771
771
  f.className = "telpick-flag";
772
- const p = this._getFlagUrl(n.flag, n.country_code);
772
+ const p = this._getFlagUrl(c.flag, c.country_code);
773
773
  if (p) {
774
774
  const a = document.createElement("img");
775
- a.src = p, a.className = "w-full h-full object-cover", a.alt = n.country || "flag", a.loading = "lazy", a.referrerPolicy = "no-referrer", f.appendChild(a);
775
+ a.src = p, a.className = "w-full h-full object-cover", a.alt = c.country || "flag", a.loading = "lazy", a.referrerPolicy = "no-referrer", f.appendChild(a);
776
776
  }
777
- d.appendChild(f);
777
+ l.appendChild(f);
778
778
  const h = document.createElement("span");
779
- h.textContent = n.country, d.appendChild(h);
779
+ h.textContent = c.country, l.appendChild(h);
780
780
  const w = document.createElement("span");
781
- w.className = "ml-auto", w.textContent = n.code, d.appendChild(w), u.appendChild(d);
781
+ w.className = "ml-auto", w.textContent = c.code, l.appendChild(w), u.appendChild(l);
782
782
  }), this.dropdown.appendChild(u), document.body.appendChild(this.dropdown), this._updateDropdownPosition(), this._scrollResizeCleanup = () => {
783
783
  window.removeEventListener("scroll", this._boundUpdatePosition, !0), window.removeEventListener("resize", this._boundUpdatePosition);
784
784
  }, window.addEventListener("scroll", this._boundUpdatePosition, !0), window.addEventListener("resize", this._boundUpdatePosition), requestAnimationFrame(() => {
@@ -787,8 +787,8 @@ class T {
787
787
  }
788
788
  }
789
789
  _setupOutsideClick() {
790
- this._outsideHandler && document.removeEventListener("click", this._outsideHandler), this._outsideHandler = (c) => {
791
- const r = c.target;
790
+ this._outsideHandler && document.removeEventListener("click", this._outsideHandler), this._outsideHandler = (n) => {
791
+ const r = n.target;
792
792
  if (this.isDropdownOpen && this.container && r) {
793
793
  const o = this.container.contains(r), t = this.dropdown && this.dropdown.contains(r);
794
794
  !o && !t && (this.isDropdownOpen = !1, this.render());
@@ -1 +1 @@
1
- (function(l,w){typeof exports=="object"&&typeof module<"u"?w(exports):typeof define=="function"&&define.amd?define(["exports"],w):(l=typeof globalThis<"u"?globalThis:l||self,w(l.Telpick={}))})(this,function(l){"use strict";const w="",T=[{country:"Afganistán",code:"+93",flag:"/flags/af.png",country_code:"AF"},{country:"Albania",code:"+355",flag:"/flags/al.webp",country_code:"AL"},{country:"Alemania",code:"+49",flag:"/flags/de.webp",country_code:"DE"},{country:"Andorra",code:"+376",flag:"/flags/ad.webp",country_code:"AD"},{country:"Antigua y Barbuda",code:"+1",flag:"/flags/ag.webp",country_code:"AG"},{country:"Arabia Saudita",code:"+966",flag:"/flags/sa.webp",country_code:"SA"},{country:"Argentina",code:"+54",flag:"/flags/ar.webp",country_code:"AR"},{country:"Australia",code:"+61",flag:"/flags/au.webp",country_code:"AU"},{country:"Austria",code:"+43",flag:"/flags/at.webp",country_code:"AT"},{country:"Bahamas",code:"+1",flag:"/flags/bs.webp",country_code:"BS"},{country:"Bangladés",code:"+880",flag:"/flags/bd.webp",country_code:"BD"},{country:"Barbados",code:"+1",flag:"/flags/bb.webp",country_code:"BB"},{country:"Bélgica",code:"+32",flag:"/flags/be.webp",country_code:"BE"},{country:"Belice",code:"+501",flag:"/flags/bz.webp",country_code:"BZ"},{country:"Bielorrusia",code:"+375",flag:"/flags/by.webp",country_code:"BY"},{country:"Bolivia",code:"+591",flag:"/flags/bo.webp",country_code:"BO"},{country:"Bosnia y Herzegovina",code:"+387",flag:"/flags/ba.webp",country_code:"BA"},{country:"Brasil",code:"+55",flag:"/flags/br.webp",country_code:"BR"},{country:"Bulgaria",code:"+359",flag:"/flags/bg.webp",country_code:"BG"},{country:"Canadá",code:"+1",flag:"/flags/ca.webp",country_code:"CA"},{country:"Chile",code:"+56",flag:"/flags/cl.webp",country_code:"CL"},{country:"China",code:"+86",flag:"/flags/cn.webp",country_code:"CN"},{country:"Colombia",code:"+57",flag:"/flags/co.webp",country_code:"CO"},{country:"Corea del Sur",code:"+82",flag:"/flags/kr.webp",country_code:"KR"},{country:"Costa Rica",code:"+506",flag:"/flags/cr.webp",country_code:"CR"},{country:"Croacia",code:"+385",flag:"/flags/hr.webp",country_code:"HR"},{country:"Cuba",code:"+53",flag:"/flags/cu.webp",country_code:"CU"},{country:"Dinamarca",code:"+45",flag:"/flags/dk.webp",country_code:"DK"},{country:"Dominica",code:"+1",flag:"/flags/dm.webp",country_code:"DM"},{country:"Ecuador",code:"+593",flag:"/flags/ec.webp",country_code:"EC"},{country:"Egipto",code:"+20",flag:"/flags/eg.webp",country_code:"EG"},{country:"El Salvador",code:"+503",flag:"/flags/sv.webp",country_code:"SV"},{country:"España",code:"+34",flag:"/flags/es.webp",country_code:"ES"},{country:"Estados Unidos",code:"+1",flag:"/flags/us.webp",country_code:"US"},{country:"Estonia",code:"+372",flag:"/flags/ee.webp",country_code:"EE"},{country:"Filipinas",code:"+63",flag:"/flags/ph.webp",country_code:"PH"},{country:"Finlandia",code:"+358",flag:"/flags/fi.webp",country_code:"FI"},{country:"Francia",code:"+33",flag:"/flags/fr.webp",country_code:"FR"},{country:"Granada",code:"+1",flag:"/flags/gd.webp",country_code:"GD"},{country:"Grecia",code:"+30",flag:"/flags/gr.webp",country_code:"GR"},{country:"Guatemala",code:"+502",flag:"/flags/gt.webp",country_code:"GT"},{country:"Guyana",code:"+592",flag:"/flags/gy.webp",country_code:"GY"},{country:"Haití",code:"+509",flag:"/flags/ht.webp",country_code:"HT"},{country:"Honduras",code:"+504",flag:"/flags/hn.webp",country_code:"HN"},{country:"Hungría",code:"+36",flag:"/flags/hu.webp",country_code:"HU"},{country:"India",code:"+91",flag:"/flags/in.webp",country_code:"IN"},{country:"Indonesia",code:"+62",flag:"/flags/id.webp",country_code:"ID"},{country:"Irak",code:"+964",flag:"/flags/iq.webp",country_code:"IQ"},{country:"Irlanda",code:"+353",flag:"/flags/ie.webp",country_code:"IE"},{country:"Islandia",code:"+354",flag:"/flags/is.webp",country_code:"IS"},{country:"Israel",code:"+972",flag:"/flags/il.webp",country_code:"IL"},{country:"Italia",code:"+39",flag:"/flags/it.webp",country_code:"IT"},{country:"Jamaica",code:"+1",flag:"/flags/jm.webp",country_code:"JM"},{country:"Japón",code:"+81",flag:"/flags/jp.webp",country_code:"JP"},{country:"Kenia",code:"+254",flag:"/flags/ke.webp",country_code:"KE"},{country:"Letonia",code:"+371",flag:"/flags/lv.webp",country_code:"LV"},{country:"Lituania",code:"+370",flag:"/flags/lt.webp",country_code:"LT"},{country:"Luxemburgo",code:"+352",flag:"/flags/lu.webp",country_code:"LU"},{country:"Malasia",code:"+60",flag:"/flags/my.webp",country_code:"MY"},{country:"Malta",code:"+356",flag:"/flags/mt.webp",country_code:"MT"},{country:"México",code:"+52",flag:"/flags/mx.webp",country_code:"MX"},{country:"Mónaco",code:"+377",flag:"/flags/mc.webp",country_code:"MC"},{country:"Nicaragua",code:"+505",flag:"/flags/ni.webp",country_code:"NI"},{country:"Nigeria",code:"+234",flag:"/flags/ng.webp",country_code:"NG"},{country:"Noruega",code:"+47",flag:"/flags/no.webp",country_code:"NO"},{country:"Nueva Zelanda",code:"+64",flag:"/flags/nz.webp",country_code:"NZ"},{country:"Países Bajos",code:"+31",flag:"/flags/nl.webp",country_code:"NL"},{country:"Pakistán",code:"+92",flag:"/flags/pk.webp",country_code:"PK"},{country:"Panamá",code:"+507",flag:"/flags/pa.webp",country_code:"PA"},{country:"Paraguay",code:"+595",flag:"/flags/py.webp",country_code:"PY"},{country:"Perú",code:"+51",flag:"/flags/pe.webp",country_code:"PE"},{country:"Polonia",code:"+48",flag:"/flags/pl.webp",country_code:"PL"},{country:"Portugal",code:"+351",flag:"/flags/pt.webp",country_code:"PT"},{country:"Reino Unido",code:"+44",flag:"/flags/gb.webp",country_code:"GB"},{country:"República Checa",code:"+420",flag:"/flags/cz.webp",country_code:"CZ"},{country:"República Dominicana",code:"+1",flag:"/flags/do.webp",country_code:"DO"},{country:"Rumanía",code:"+40",flag:"/flags/ro.webp",country_code:"RO"},{country:"Rusia",code:"+7",flag:"/flags/ru.webp",country_code:"RU"},{country:"San Cristóbal y Nieves",code:"+1",flag:"/flags/kn.webp",country_code:"KN"},{country:"San Vicente y las Granadinas",code:"+1",flag:"/flags/vc.webp",country_code:"VC"},{country:"Santa Lucía",code:"+1",flag:"/flags/lc.webp",country_code:"LC"},{country:"Singapur",code:"+65",flag:"/flags/sg.webp",country_code:"SG"},{country:"Sudáfrica",code:"+27",flag:"/flags/za.webp",country_code:"ZA"},{country:"Suecia",code:"+46",flag:"/flags/se.webp",country_code:"SE"},{country:"Suiza",code:"+41",flag:"/flags/ch.webp",country_code:"CH"},{country:"Surinam",code:"+597",flag:"/flags/sr.webp",country_code:"SR"},{country:"Tailandia",code:"+66",flag:"/flags/th.webp",country_code:"TH"},{country:"Trinidad y Tobago",code:"+1",flag:"/flags/tt.webp",country_code:"TT"},{country:"Ucrania",code:"+380",flag:"/flags/ua.webp",country_code:"UA"},{country:"Uruguay",code:"+598",flag:"/flags/uy.webp",country_code:"UY"},{country:"Venezuela",code:"+58",flag:"/flags/ve.webp",country_code:"VE"},{country:"Vietnam",code:"+84",flag:"/flags/vn.webp",country_code:"VN"}];(function(){if(typeof document<"u"&&document.currentScript&&document.currentScript.src){const u=document.currentScript.src.replace(/\/[^/]*$/,"");typeof globalThis<"u"?globalThis.__TELPICK_SCRIPT_BASE__=u:typeof window<"u"&&(window.__TELPICK_SCRIPT_BASE__=u)}})();function v(){const u=typeof globalThis<"u"&&globalThis.__TELPICK_SCRIPT_BASE__?globalThis.__TELPICK_SCRIPT_BASE__:typeof window<"u"&&window.__TELPICK_SCRIPT_BASE__||"";return u?`${u.replace(/\/$/,"")}/assets/flags`:""}class E{constructor({code:t=null,onChange:r=()=>{},styleOverrides:o={},baseFlagUrl:c=""}={}){this.code=t,this.onChange=r,this.styleOverrides=o,this.baseFlagUrl=c||v(),this.codes=[],this.selectedCode=t,this.isDropdownOpen=!1,this.searchQuery="",this.container=null,this.dropdown=null,this._outsideHandler=null,this._scrollResizeCleanup=null,this._boundUpdatePosition=()=>this._updateDropdownPosition(),this._getFlagUrl=this._getFlagUrl.bind(this)}_updateDropdownPosition(){if(!this.dropdown||!this.container)return;const t=this.container.getBoundingClientRect();this.dropdown.style.position="fixed",this.dropdown.style.top=`${t.bottom+4}px`,this.dropdown.style.left=`${t.left}px`,this.dropdown.style.marginTop="0"}_getFlagUrl(t,r){const o=t?t.replace(/^.*\//,""):r?`${String(r).toLowerCase()}.webp`:"";if(!o&&!r)return"";if(this.baseFlagUrl){const c=this.baseFlagUrl.replace(/\/$/,"");if(c.includes("flagcdn.com")){const i=String(r||o&&o.replace(/\.[^.]+$/,"")||"").toLowerCase();return i?`${c}/${i}.png`:""}return`${c}/${o}`}return t||(r?`/flags/${String(r).toLowerCase()}.webp`:"")}async init(t){if(this.container=t,this.codes=[...T].sort((o,c)=>o.country.localeCompare(c.country,"es")),this.code){const o=this.codes.find(c=>c.country_code===this.code);o&&(this.selectedCode=o.country_code)}else{const o=[async()=>{try{const s=await(await fetch("https://ip-api.com/json/?fields=countryCode")).json();if(s.countryCode)return this.codes.find(e=>e.country_code===s.countryCode)}catch{}return null},async()=>{try{const s=await(await fetch("https://get.geojs.io/v1/ip/country.json")).json();if(s.country)return this.codes.find(e=>e.country_code===s.country)}catch{}return null},async()=>{try{const s=await(await fetch("https://ipapi.co/json/")).json();if(s.country_code)return this.codes.find(e=>e.country_code===s.country_code)}catch{}return null}];let c=null;for(const i of o)try{if(c=await Promise.race([i(),new Promise(s=>setTimeout(()=>s(null),3e3))]),c)break}catch{}if(!c)try{const i=Intl.DateTimeFormat().resolvedOptions().timeZone,e={"America/Lima":"PE","America/Bogota":"CO","America/Mexico_City":"MX","America/Argentina/Buenos_Aires":"AR","America/Santiago":"CL","America/Caracas":"VE","America/Montevideo":"UY","America/Asuncion":"PY","America/La_Paz":"BO","America/Guayaquil":"EC","America/Panama":"PA","America/Costa_Rica":"CR","America/Managua":"NI","America/Tegucigalpa":"HN","America/Guatemala":"GT","America/El_Salvador":"SV","America/Havana":"CU","America/Santo_Domingo":"DO","America/Jamaica":"JM","America/Port-au-Prince":"HT","Europe/Madrid":"ES","Europe/London":"GB","Europe/Paris":"FR","Europe/Berlin":"DE","Europe/Rome":"IT","Europe/Amsterdam":"NL","Europe/Brussels":"BE","Europe/Vienna":"AT","Europe/Zurich":"CH","Europe/Stockholm":"SE","Europe/Oslo":"NO","Europe/Copenhagen":"DK","Europe/Helsinki":"FI","Europe/Warsaw":"PL","Europe/Prague":"CZ","Europe/Bucharest":"RO","Europe/Moscow":"RU","America/New_York":"US","America/Chicago":"US","America/Denver":"US","America/Los_Angeles":"US","America/Toronto":"CA","America/Vancouver":"CA","Asia/Tokyo":"JP","Asia/Shanghai":"CN","Asia/Hong_Kong":"CN","Asia/Seoul":"KR","Asia/Singapore":"SG","Asia/Bangkok":"TH","Asia/Jakarta":"ID","Asia/Manila":"PH","Asia/Kolkata":"IN","Asia/Dubai":"AE","Asia/Riyadh":"SA","Australia/Sydney":"AU","Australia/Melbourne":"AU","Pacific/Auckland":"NZ","Africa/Cairo":"EG","Africa/Johannesburg":"ZA","Africa/Nairobi":"KE","Africa/Lagos":"NG"}[i];e&&(c=this.codes.find(f=>f.country_code===e))}catch{}if(c)this.selectedCode=c.country_code;else{const i=this.codes.find(s=>s.country_code==="CO");i&&(this.selectedCode=i.country_code)}}this.render();const r=this.codes.find(o=>o.country_code===this.selectedCode);r&&this.onChange(r),this._setupOutsideClick()}render(){this._scrollResizeCleanup&&(this._scrollResizeCleanup(),this._scrollResizeCleanup=null),this.dropdown&&this.dropdown.parentNode&&(this.dropdown.parentNode.removeChild(this.dropdown),this.dropdown=null),this.container.innerHTML="";const t=document.createElement("button");t.className="telpick-btn",Object.assign(t.style,this.styleOverrides),t.onclick=()=>{this.isDropdownOpen=!this.isDropdownOpen,this.render()};const r=document.createElement("div");r.className="telpick-flag";const o=this.codes.find(e=>e.country_code===this.selectedCode)||{country_code:"",code:"",country:"",flag:""},c=this._getFlagUrl(o.flag,o.country_code);if(c){const e=document.createElement("img");e.src=c,e.className="w-full h-full object-cover",e.alt=o.country||"flag",e.loading="lazy",e.referrerPolicy="no-referrer",r.appendChild(e)}t.appendChild(r);const i=document.createElement("span");i.textContent=o.code,t.appendChild(i);const s=document.createElement("span");if(s.className="ml-auto",s.textContent="▼",t.appendChild(s),this.container.appendChild(t),this.isDropdownOpen){this.dropdown=document.createElement("div"),this.dropdown.className="telpick-dropdown",this.dropdown.onclick=n=>n.stopPropagation(),this.dropdown.onmousedown=n=>n.stopPropagation();const e=document.createElement("input");e.className="telpick-search",e.type="text",e.placeholder="Buscar país...",e.value=this.searchQuery,e.oninput=n=>{var _;n.stopPropagation();const d=n.target,b=d.selectionStart||0,p=d.value;this.searchQuery=p;const g=(_=this.dropdown)==null?void 0:_.querySelector("ul");g?(g.innerHTML="",(this.searchQuery?this.codes.filter(a=>a.country.toLowerCase().includes(this.searchQuery.toLowerCase())):this.codes).forEach(a=>{const y=document.createElement("li"),N=a.country_code===this.selectedCode&&this.selectedCode!==null&&this.selectedCode!==void 0;y.className=`telpick-item ${N?"telpick-item-selected":""}`,y.onclick=()=>{this.selectedCode=a.country_code,this.onChange(a),this.isDropdownOpen=!1,this.searchQuery="",this.render()};const C=document.createElement("div");C.className="telpick-flag";const S=this._getFlagUrl(a.flag,a.country_code);if(S){const h=document.createElement("img");h.src=S,h.className="w-full h-full object-cover",h.alt=a.country||"flag",h.loading="lazy",h.referrerPolicy="no-referrer",C.appendChild(h)}y.appendChild(C);const P=document.createElement("span");P.textContent=a.country,y.appendChild(P);const A=document.createElement("span");A.className="ml-auto",A.textContent=a.code,y.appendChild(A),g.appendChild(y)}),requestAnimationFrame(()=>{if(e){e.focus();const a=Math.min(b+1,p.length);e.setSelectionRange(a,a)}})):this.render()},e.onclick=n=>n.stopPropagation(),e.onmousedown=n=>n.stopPropagation(),this.dropdown.appendChild(e);const f=document.createElement("ul");f.style.maxHeight="130px",f.style.overflowY="auto",(this.searchQuery?this.codes.filter(n=>n.country.toLowerCase().includes(this.searchQuery.toLowerCase())):this.codes).forEach(n=>{const d=document.createElement("li"),b=n.country_code===this.selectedCode&&this.selectedCode!==null&&this.selectedCode!==void 0;d.className=`telpick-item ${b?"telpick-item-selected":""}`,d.setAttribute("aria-selected",b),d.onclick=()=>{this.selectedCode=n.country_code,this.onChange(n),this.isDropdownOpen=!1,this.searchQuery="",this.render()};const p=document.createElement("div");p.className="telpick-flag";const g=this._getFlagUrl(n.flag,n.country_code);if(g){const a=document.createElement("img");a.src=g,a.className="w-full h-full object-cover",a.alt=n.country||"flag",a.loading="lazy",a.referrerPolicy="no-referrer",p.appendChild(a)}d.appendChild(p);const _=document.createElement("span");_.textContent=n.country,d.appendChild(_);const m=document.createElement("span");m.className="ml-auto",m.textContent=n.code,d.appendChild(m),f.appendChild(d)}),this.dropdown.appendChild(f),document.body.appendChild(this.dropdown),this._updateDropdownPosition(),this._scrollResizeCleanup=()=>{window.removeEventListener("scroll",this._boundUpdatePosition,!0),window.removeEventListener("resize",this._boundUpdatePosition)},window.addEventListener("scroll",this._boundUpdatePosition,!0),window.addEventListener("resize",this._boundUpdatePosition),requestAnimationFrame(()=>{e&&e.focus()})}}_setupOutsideClick(){this._outsideHandler&&document.removeEventListener("click",this._outsideHandler),this._outsideHandler=t=>{const r=t.target;if(this.isDropdownOpen&&this.container&&r){const o=this.container.contains(r),c=this.dropdown&&this.dropdown.contains(r);!o&&!c&&(this.isDropdownOpen=!1,this.render())}},document.addEventListener("click",this._outsideHandler,!0)}destroy(){this._outsideHandler&&document.removeEventListener("click",this._outsideHandler),this._scrollResizeCleanup&&(this._scrollResizeCleanup(),this._scrollResizeCleanup=null),this.dropdown&&this.dropdown.parentNode&&(this.dropdown.parentNode.removeChild(this.dropdown),this.dropdown=null),this.container.innerHTML=""}}window.Telpick=E,l.Telpick=E,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})});
1
+ (function(u,d){typeof exports=="object"&&typeof module<"u"?d(exports):typeof define=="function"&&define.amd?define(["exports"],d):(u=typeof globalThis<"u"?globalThis:u||self,d(u.Telpick={}))})(this,function(u){"use strict";var d=typeof document<"u"?document.currentScript:null;const v="",T=[{country:"Afganistán",code:"+93",flag:"/flags/af.png",country_code:"AF"},{country:"Albania",code:"+355",flag:"/flags/al.webp",country_code:"AL"},{country:"Alemania",code:"+49",flag:"/flags/de.webp",country_code:"DE"},{country:"Andorra",code:"+376",flag:"/flags/ad.webp",country_code:"AD"},{country:"Antigua y Barbuda",code:"+1",flag:"/flags/ag.webp",country_code:"AG"},{country:"Arabia Saudita",code:"+966",flag:"/flags/sa.webp",country_code:"SA"},{country:"Argentina",code:"+54",flag:"/flags/ar.webp",country_code:"AR"},{country:"Australia",code:"+61",flag:"/flags/au.webp",country_code:"AU"},{country:"Austria",code:"+43",flag:"/flags/at.webp",country_code:"AT"},{country:"Bahamas",code:"+1",flag:"/flags/bs.webp",country_code:"BS"},{country:"Bangladés",code:"+880",flag:"/flags/bd.webp",country_code:"BD"},{country:"Barbados",code:"+1",flag:"/flags/bb.webp",country_code:"BB"},{country:"Bélgica",code:"+32",flag:"/flags/be.webp",country_code:"BE"},{country:"Belice",code:"+501",flag:"/flags/bz.webp",country_code:"BZ"},{country:"Bielorrusia",code:"+375",flag:"/flags/by.webp",country_code:"BY"},{country:"Bolivia",code:"+591",flag:"/flags/bo.webp",country_code:"BO"},{country:"Bosnia y Herzegovina",code:"+387",flag:"/flags/ba.webp",country_code:"BA"},{country:"Brasil",code:"+55",flag:"/flags/br.webp",country_code:"BR"},{country:"Bulgaria",code:"+359",flag:"/flags/bg.webp",country_code:"BG"},{country:"Canadá",code:"+1",flag:"/flags/ca.webp",country_code:"CA"},{country:"Chile",code:"+56",flag:"/flags/cl.webp",country_code:"CL"},{country:"China",code:"+86",flag:"/flags/cn.webp",country_code:"CN"},{country:"Colombia",code:"+57",flag:"/flags/co.webp",country_code:"CO"},{country:"Corea del Sur",code:"+82",flag:"/flags/kr.webp",country_code:"KR"},{country:"Costa Rica",code:"+506",flag:"/flags/cr.webp",country_code:"CR"},{country:"Croacia",code:"+385",flag:"/flags/hr.webp",country_code:"HR"},{country:"Cuba",code:"+53",flag:"/flags/cu.webp",country_code:"CU"},{country:"Dinamarca",code:"+45",flag:"/flags/dk.webp",country_code:"DK"},{country:"Dominica",code:"+1",flag:"/flags/dm.webp",country_code:"DM"},{country:"Ecuador",code:"+593",flag:"/flags/ec.webp",country_code:"EC"},{country:"Egipto",code:"+20",flag:"/flags/eg.webp",country_code:"EG"},{country:"El Salvador",code:"+503",flag:"/flags/sv.webp",country_code:"SV"},{country:"España",code:"+34",flag:"/flags/es.webp",country_code:"ES"},{country:"Estados Unidos",code:"+1",flag:"/flags/us.webp",country_code:"US"},{country:"Estonia",code:"+372",flag:"/flags/ee.webp",country_code:"EE"},{country:"Filipinas",code:"+63",flag:"/flags/ph.webp",country_code:"PH"},{country:"Finlandia",code:"+358",flag:"/flags/fi.webp",country_code:"FI"},{country:"Francia",code:"+33",flag:"/flags/fr.webp",country_code:"FR"},{country:"Granada",code:"+1",flag:"/flags/gd.webp",country_code:"GD"},{country:"Grecia",code:"+30",flag:"/flags/gr.webp",country_code:"GR"},{country:"Guatemala",code:"+502",flag:"/flags/gt.webp",country_code:"GT"},{country:"Guyana",code:"+592",flag:"/flags/gy.webp",country_code:"GY"},{country:"Haití",code:"+509",flag:"/flags/ht.webp",country_code:"HT"},{country:"Honduras",code:"+504",flag:"/flags/hn.webp",country_code:"HN"},{country:"Hungría",code:"+36",flag:"/flags/hu.webp",country_code:"HU"},{country:"India",code:"+91",flag:"/flags/in.webp",country_code:"IN"},{country:"Indonesia",code:"+62",flag:"/flags/id.webp",country_code:"ID"},{country:"Irak",code:"+964",flag:"/flags/iq.webp",country_code:"IQ"},{country:"Irlanda",code:"+353",flag:"/flags/ie.webp",country_code:"IE"},{country:"Islandia",code:"+354",flag:"/flags/is.webp",country_code:"IS"},{country:"Israel",code:"+972",flag:"/flags/il.webp",country_code:"IL"},{country:"Italia",code:"+39",flag:"/flags/it.webp",country_code:"IT"},{country:"Jamaica",code:"+1",flag:"/flags/jm.webp",country_code:"JM"},{country:"Japón",code:"+81",flag:"/flags/jp.webp",country_code:"JP"},{country:"Kenia",code:"+254",flag:"/flags/ke.webp",country_code:"KE"},{country:"Letonia",code:"+371",flag:"/flags/lv.webp",country_code:"LV"},{country:"Lituania",code:"+370",flag:"/flags/lt.webp",country_code:"LT"},{country:"Luxemburgo",code:"+352",flag:"/flags/lu.webp",country_code:"LU"},{country:"Malasia",code:"+60",flag:"/flags/my.webp",country_code:"MY"},{country:"Malta",code:"+356",flag:"/flags/mt.webp",country_code:"MT"},{country:"México",code:"+52",flag:"/flags/mx.webp",country_code:"MX"},{country:"Mónaco",code:"+377",flag:"/flags/mc.webp",country_code:"MC"},{country:"Nicaragua",code:"+505",flag:"/flags/ni.webp",country_code:"NI"},{country:"Nigeria",code:"+234",flag:"/flags/ng.webp",country_code:"NG"},{country:"Noruega",code:"+47",flag:"/flags/no.webp",country_code:"NO"},{country:"Nueva Zelanda",code:"+64",flag:"/flags/nz.webp",country_code:"NZ"},{country:"Países Bajos",code:"+31",flag:"/flags/nl.webp",country_code:"NL"},{country:"Pakistán",code:"+92",flag:"/flags/pk.webp",country_code:"PK"},{country:"Panamá",code:"+507",flag:"/flags/pa.webp",country_code:"PA"},{country:"Paraguay",code:"+595",flag:"/flags/py.webp",country_code:"PY"},{country:"Perú",code:"+51",flag:"/flags/pe.webp",country_code:"PE"},{country:"Polonia",code:"+48",flag:"/flags/pl.webp",country_code:"PL"},{country:"Portugal",code:"+351",flag:"/flags/pt.webp",country_code:"PT"},{country:"Reino Unido",code:"+44",flag:"/flags/gb.webp",country_code:"GB"},{country:"República Checa",code:"+420",flag:"/flags/cz.webp",country_code:"CZ"},{country:"República Dominicana",code:"+1",flag:"/flags/do.webp",country_code:"DO"},{country:"Rumanía",code:"+40",flag:"/flags/ro.webp",country_code:"RO"},{country:"Rusia",code:"+7",flag:"/flags/ru.webp",country_code:"RU"},{country:"San Cristóbal y Nieves",code:"+1",flag:"/flags/kn.webp",country_code:"KN"},{country:"San Vicente y las Granadinas",code:"+1",flag:"/flags/vc.webp",country_code:"VC"},{country:"Santa Lucía",code:"+1",flag:"/flags/lc.webp",country_code:"LC"},{country:"Singapur",code:"+65",flag:"/flags/sg.webp",country_code:"SG"},{country:"Sudáfrica",code:"+27",flag:"/flags/za.webp",country_code:"ZA"},{country:"Suecia",code:"+46",flag:"/flags/se.webp",country_code:"SE"},{country:"Suiza",code:"+41",flag:"/flags/ch.webp",country_code:"CH"},{country:"Surinam",code:"+597",flag:"/flags/sr.webp",country_code:"SR"},{country:"Tailandia",code:"+66",flag:"/flags/th.webp",country_code:"TH"},{country:"Trinidad y Tobago",code:"+1",flag:"/flags/tt.webp",country_code:"TT"},{country:"Ucrania",code:"+380",flag:"/flags/ua.webp",country_code:"UA"},{country:"Uruguay",code:"+598",flag:"/flags/uy.webp",country_code:"UY"},{country:"Venezuela",code:"+58",flag:"/flags/ve.webp",country_code:"VE"},{country:"Vietnam",code:"+84",flag:"/flags/vn.webp",country_code:"VN"}];(function(){if(typeof document<"u"&&document.currentScript&&document.currentScript.src){const f=document.currentScript.src.replace(/\/[^/]*$/,"");typeof globalThis<"u"?globalThis.__TELPICK_SCRIPT_BASE__=f:typeof window<"u"&&(window.__TELPICK_SCRIPT_BASE__=f)}})();function R(){const f=typeof globalThis<"u"&&globalThis.__TELPICK_SCRIPT_BASE__?globalThis.__TELPICK_SCRIPT_BASE__:typeof window<"u"&&window.__TELPICK_SCRIPT_BASE__||"";return f?`${f.replace(/\/$/,"")}/assets/flags`:typeof{url:typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:d&&d.tagName.toUpperCase()==="SCRIPT"&&d.src||new URL("telpick.umd.js",document.baseURI).href}<"u"&&(typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:d&&d.tagName.toUpperCase()==="SCRIPT"&&d.src||new URL("telpick.umd.js",document.baseURI).href)?new URL("./assets/flags/",self.location).href:""}class E{constructor({code:n=null,onChange:r=()=>{},styleOverrides:o={},baseFlagUrl:t=""}={}){this.code=n,this.onChange=r,this.styleOverrides=o,this.baseFlagUrl=t||R(),this.codes=[],this.selectedCode=n,this.isDropdownOpen=!1,this.searchQuery="",this.container=null,this.dropdown=null,this._outsideHandler=null,this._scrollResizeCleanup=null,this._boundUpdatePosition=()=>this._updateDropdownPosition(),this._getFlagUrl=this._getFlagUrl.bind(this)}_updateDropdownPosition(){if(!this.dropdown||!this.container)return;const n=this.container.getBoundingClientRect();this.dropdown.style.position="fixed",this.dropdown.style.top=`${n.bottom+4}px`,this.dropdown.style.left=`${n.left}px`,this.dropdown.style.marginTop="0"}_getFlagUrl(n,r){const o=n?n.replace(/^.*\//,""):r?`${String(r).toLowerCase()}.webp`:"";if(!o&&!r)return"";if(this.baseFlagUrl){const t=this.baseFlagUrl.replace(/\/$/,"");if(t.includes("flagcdn.com")){const i=String(r||o&&o.replace(/\.[^.]+$/,"")||"").toLowerCase();return i?`${t}/${i}.png`:""}return`${t}/${o}`}return""}async init(n){if(this.container=n,this.codes=[...T].sort((o,t)=>o.country.localeCompare(t.country,"es")),this.code){const o=this.codes.find(t=>t.country_code===this.code);o&&(this.selectedCode=o.country_code)}else{const o=[async()=>{try{const s=await(await fetch("https://ip-api.com/json/?fields=countryCode")).json();if(s.countryCode)return this.codes.find(e=>e.country_code===s.countryCode)}catch{}return null},async()=>{try{const s=await(await fetch("https://get.geojs.io/v1/ip/country.json")).json();if(s.country)return this.codes.find(e=>e.country_code===s.country)}catch{}return null},async()=>{try{const s=await(await fetch("https://ipapi.co/json/")).json();if(s.country_code)return this.codes.find(e=>e.country_code===s.country_code)}catch{}return null}];let t=null;for(const i of o)try{if(t=await Promise.race([i(),new Promise(s=>setTimeout(()=>s(null),3e3))]),t)break}catch{}if(!t)try{const i=Intl.DateTimeFormat().resolvedOptions().timeZone,e={"America/Lima":"PE","America/Bogota":"CO","America/Mexico_City":"MX","America/Argentina/Buenos_Aires":"AR","America/Santiago":"CL","America/Caracas":"VE","America/Montevideo":"UY","America/Asuncion":"PY","America/La_Paz":"BO","America/Guayaquil":"EC","America/Panama":"PA","America/Costa_Rica":"CR","America/Managua":"NI","America/Tegucigalpa":"HN","America/Guatemala":"GT","America/El_Salvador":"SV","America/Havana":"CU","America/Santo_Domingo":"DO","America/Jamaica":"JM","America/Port-au-Prince":"HT","Europe/Madrid":"ES","Europe/London":"GB","Europe/Paris":"FR","Europe/Berlin":"DE","Europe/Rome":"IT","Europe/Amsterdam":"NL","Europe/Brussels":"BE","Europe/Vienna":"AT","Europe/Zurich":"CH","Europe/Stockholm":"SE","Europe/Oslo":"NO","Europe/Copenhagen":"DK","Europe/Helsinki":"FI","Europe/Warsaw":"PL","Europe/Prague":"CZ","Europe/Bucharest":"RO","Europe/Moscow":"RU","America/New_York":"US","America/Chicago":"US","America/Denver":"US","America/Los_Angeles":"US","America/Toronto":"CA","America/Vancouver":"CA","Asia/Tokyo":"JP","Asia/Shanghai":"CN","Asia/Hong_Kong":"CN","Asia/Seoul":"KR","Asia/Singapore":"SG","Asia/Bangkok":"TH","Asia/Jakarta":"ID","Asia/Manila":"PH","Asia/Kolkata":"IN","Asia/Dubai":"AE","Asia/Riyadh":"SA","Australia/Sydney":"AU","Australia/Melbourne":"AU","Pacific/Auckland":"NZ","Africa/Cairo":"EG","Africa/Johannesburg":"ZA","Africa/Nairobi":"KE","Africa/Lagos":"NG"}[i];e&&(t=this.codes.find(p=>p.country_code===e))}catch{}if(t)this.selectedCode=t.country_code;else{const i=this.codes.find(s=>s.country_code==="CO");i&&(this.selectedCode=i.country_code)}}this.render();const r=this.codes.find(o=>o.country_code===this.selectedCode);r&&this.onChange(r),this._setupOutsideClick()}render(){this._scrollResizeCleanup&&(this._scrollResizeCleanup(),this._scrollResizeCleanup=null),this.dropdown&&this.dropdown.parentNode&&(this.dropdown.parentNode.removeChild(this.dropdown),this.dropdown=null),this.container.innerHTML="";const n=document.createElement("button");n.className="telpick-btn",Object.assign(n.style,this.styleOverrides),n.onclick=()=>{this.isDropdownOpen=!this.isDropdownOpen,this.render()};const r=document.createElement("div");r.className="telpick-flag";const o=this.codes.find(e=>e.country_code===this.selectedCode)||{country_code:"",code:"",country:"",flag:""},t=this._getFlagUrl(o.flag,o.country_code);if(t){const e=document.createElement("img");e.src=t,e.className="w-full h-full object-cover",e.alt=o.country||"flag",e.loading="lazy",e.referrerPolicy="no-referrer",r.appendChild(e)}n.appendChild(r);const i=document.createElement("span");i.textContent=o.code,n.appendChild(i);const s=document.createElement("span");if(s.className="ml-auto",s.textContent="▼",n.appendChild(s),this.container.appendChild(n),this.isDropdownOpen){this.dropdown=document.createElement("div"),this.dropdown.className="telpick-dropdown",this.dropdown.onclick=c=>c.stopPropagation(),this.dropdown.onmousedown=c=>c.stopPropagation();const e=document.createElement("input");e.className="telpick-search",e.type="text",e.placeholder="Buscar país...",e.value=this.searchQuery,e.oninput=c=>{var w;c.stopPropagation();const l=c.target,m=l.selectionStart||0,g=l.value;this.searchQuery=g;const y=(w=this.dropdown)==null?void 0:w.querySelector("ul");y?(y.innerHTML="",(this.searchQuery?this.codes.filter(a=>a.country.toLowerCase().includes(this.searchQuery.toLowerCase())):this.codes).forEach(a=>{const h=document.createElement("li"),U=a.country_code===this.selectedCode&&this.selectedCode!==null&&this.selectedCode!==void 0;h.className=`telpick-item ${U?"telpick-item-selected":""}`,h.onclick=()=>{this.selectedCode=a.country_code,this.onChange(a),this.isDropdownOpen=!1,this.searchQuery="",this.render()};const C=document.createElement("div");C.className="telpick-flag";const S=this._getFlagUrl(a.flag,a.country_code);if(S){const _=document.createElement("img");_.src=S,_.className="w-full h-full object-cover",_.alt=a.country||"flag",_.loading="lazy",_.referrerPolicy="no-referrer",C.appendChild(_)}h.appendChild(C);const P=document.createElement("span");P.textContent=a.country,h.appendChild(P);const A=document.createElement("span");A.className="ml-auto",A.textContent=a.code,h.appendChild(A),y.appendChild(h)}),requestAnimationFrame(()=>{if(e){e.focus();const a=Math.min(m+1,g.length);e.setSelectionRange(a,a)}})):this.render()},e.onclick=c=>c.stopPropagation(),e.onmousedown=c=>c.stopPropagation(),this.dropdown.appendChild(e);const p=document.createElement("ul");p.style.maxHeight="130px",p.style.overflowY="auto",(this.searchQuery?this.codes.filter(c=>c.country.toLowerCase().includes(this.searchQuery.toLowerCase())):this.codes).forEach(c=>{const l=document.createElement("li"),m=c.country_code===this.selectedCode&&this.selectedCode!==null&&this.selectedCode!==void 0;l.className=`telpick-item ${m?"telpick-item-selected":""}`,l.setAttribute("aria-selected",m),l.onclick=()=>{this.selectedCode=c.country_code,this.onChange(c),this.isDropdownOpen=!1,this.searchQuery="",this.render()};const g=document.createElement("div");g.className="telpick-flag";const y=this._getFlagUrl(c.flag,c.country_code);if(y){const a=document.createElement("img");a.src=y,a.className="w-full h-full object-cover",a.alt=c.country||"flag",a.loading="lazy",a.referrerPolicy="no-referrer",g.appendChild(a)}l.appendChild(g);const w=document.createElement("span");w.textContent=c.country,l.appendChild(w);const b=document.createElement("span");b.className="ml-auto",b.textContent=c.code,l.appendChild(b),p.appendChild(l)}),this.dropdown.appendChild(p),document.body.appendChild(this.dropdown),this._updateDropdownPosition(),this._scrollResizeCleanup=()=>{window.removeEventListener("scroll",this._boundUpdatePosition,!0),window.removeEventListener("resize",this._boundUpdatePosition)},window.addEventListener("scroll",this._boundUpdatePosition,!0),window.addEventListener("resize",this._boundUpdatePosition),requestAnimationFrame(()=>{e&&e.focus()})}}_setupOutsideClick(){this._outsideHandler&&document.removeEventListener("click",this._outsideHandler),this._outsideHandler=n=>{const r=n.target;if(this.isDropdownOpen&&this.container&&r){const o=this.container.contains(r),t=this.dropdown&&this.dropdown.contains(r);!o&&!t&&(this.isDropdownOpen=!1,this.render())}},document.addEventListener("click",this._outsideHandler,!0)}destroy(){this._outsideHandler&&document.removeEventListener("click",this._outsideHandler),this._scrollResizeCleanup&&(this._scrollResizeCleanup(),this._scrollResizeCleanup=null),this.dropdown&&this.dropdown.parentNode&&(this.dropdown.parentNode.removeChild(this.dropdown),this.dropdown=null),this.container.innerHTML=""}}window.Telpick=E,u.Telpick=E,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "telpick",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "Multi-platform country and phone code selector with a modern design, smooth animations, and automatic IP detection.",
5
5
  "main": "dist/telpick.es.js",
6
6
  "module": "dist/telpick.es.js",
package/src/demo-init.js CHANGED
@@ -6,8 +6,8 @@ import Telpick from './telpick.js'
6
6
 
7
7
  window.Telpick = Telpick
8
8
 
9
- // Base para banderas locales (src/assets/flags). En otros proyectos pasa baseFlagUrl al constructor o usa 'https://flagcdn.com/w40' si no tienes banderas.
10
- const flagsBase = new URL('./assets/flags', import.meta.url).href
9
+ // Base para banderas: en build (GitHub Pages) están en /telpick/src/assets/flags; en dev en /src/assets/flags.
10
+ const flagsBase = `${(import.meta.env.BASE_URL || '/').replace(/([^/])$/, '$1/')}src/assets/flags`
11
11
 
12
12
  function initDemo() {
13
13
  const container = document.getElementById('telpick-container')
package/src/telpick.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import countryCodesData from './assets/country-code.json'
2
2
 
3
- // Al cargar por <script src="...">, guardar la URL base para resolver assets (banderas) en CDN
3
+
4
4
  ;(function () {
5
5
  if (typeof document !== 'undefined' && document.currentScript && document.currentScript.src) {
6
6
  const base = document.currentScript.src.replace(/\/[^/]*$/, '')
@@ -10,10 +10,14 @@ import countryCodesData from './assets/country-code.json'
10
10
  })()
11
11
 
12
12
  function _getDefaultBaseFlagUrl() {
13
- const base = typeof globalThis !== 'undefined' && globalThis.__TELPICK_SCRIPT_BASE__
13
+ const scriptBase = typeof globalThis !== 'undefined' && globalThis.__TELPICK_SCRIPT_BASE__
14
14
  ? globalThis.__TELPICK_SCRIPT_BASE__
15
15
  : (typeof window !== 'undefined' && window.__TELPICK_SCRIPT_BASE__) || ''
16
- return base ? `${base.replace(/\/$/, '')}/assets/flags` : ''
16
+ if (scriptBase) return `${scriptBase.replace(/\/$/, '')}/assets/flags`
17
+ if (typeof import.meta !== 'undefined' && import.meta.url) {
18
+ return new URL('./assets/flags/', import.meta.url).href
19
+ }
20
+ return ''
17
21
  }
18
22
 
19
23
  class Telpick {
@@ -54,7 +58,8 @@ class Telpick {
54
58
  }
55
59
  return `${base}/${filename}`
56
60
  }
57
- return flagPathFromJson || (countryCode ? `/flags/${String(countryCode).toLowerCase()}.webp` : '')
61
+
62
+ return ''
58
63
  }
59
64
 
60
65
  async init(container) {
@@ -1,7 +0,0 @@
1
- // Telpick CDN loader
2
- // <script src="https://unpkg.com/telpick/dist/telpick.umd.js"></script>
3
- // window.Telpick disponible
4
-
5
- // Ejemplo de uso:
6
- // const telpick = new Telpick({ code: null, onChange: (country) => console.log(country) })
7
- // telpick.init(document.getElementById('telpick-container'))
@@ -1,186 +0,0 @@
1
- import React, { useState, useEffect, useRef, useMemo } from 'react'
2
- import { createPortal } from 'react-dom'
3
- import { getDefaultCountry, useClickOutside, CountryCode, TelpickProps } from './telpick'
4
- import './telpick.css'
5
-
6
- function getFlagUrl(baseFlagUrl: string, flagPath: string, countryCode: string): string {
7
- const base = (baseFlagUrl || '').replace(/\/$/, '')
8
- if (!base) return flagPath || (countryCode ? `https://flagcdn.com/w40/${countryCode.toLowerCase()}.png` : '')
9
- if (base.includes('flagcdn.com')) {
10
- const code = (countryCode || (flagPath && flagPath.replace(/^.*\//, '').replace(/\.[^.]+$/, '')) || '').toLowerCase()
11
- return code ? `${base}/${code}.png` : ''
12
- }
13
- const filename = flagPath ? flagPath.replace(/^.*\//, '') : `${(countryCode || '').toLowerCase()}.webp`
14
- return filename ? `${base}/${filename}` : ''
15
- }
16
-
17
- export function TelpickReact({ code, onChange, styleOverrides, baseFlagUrl = '' }: TelpickProps) {
18
- const [codes, setCodes] = useState<CountryCode[]>([])
19
- const [selectedCode, setSelectedCode] = useState(code)
20
- const [isDropdownOpen, setDropdownOpen] = useState(false)
21
- const [searchQuery, setSearchQuery] = useState('')
22
- const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0 })
23
- const wrapperRef = useRef<HTMLDivElement>(null)
24
- const buttonRef = useRef<HTMLButtonElement>(null)
25
- const portalDropdownRef = useRef<HTMLDivElement>(null)
26
- const searchInputRef = useRef<HTMLInputElement>(null)
27
-
28
- useEffect(() => {
29
- fetch('/resources/api/country-codes.json')
30
- .then(res => res.json())
31
- .then(data => {
32
- const sorted = data.sort((a, b) => a.country.localeCompare(b.country, 'es'))
33
- setCodes(sorted)
34
- if (!code) {
35
- getDefaultCountry(data).then(def => {
36
- if (def) {
37
- setSelectedCode(def.country_code)
38
- onChange && onChange(def)
39
- }
40
- })
41
- } else {
42
- setSelectedCode(code)
43
- }
44
- })
45
- }, [code, onChange])
46
-
47
- useEffect(() => {
48
- if (code !== undefined && code !== selectedCode) {
49
- setSelectedCode(code)
50
- }
51
- }, [code])
52
-
53
- function updateDropdownPosition() {
54
- if (buttonRef.current) {
55
- const rect = buttonRef.current.getBoundingClientRect()
56
- setDropdownPosition({ top: rect.bottom + 4, left: rect.left })
57
- }
58
- }
59
-
60
- useEffect(() => {
61
- if (isDropdownOpen) {
62
- updateDropdownPosition()
63
- window.addEventListener('scroll', updateDropdownPosition, true)
64
- window.addEventListener('resize', updateDropdownPosition)
65
- return () => {
66
- window.removeEventListener('scroll', updateDropdownPosition, true)
67
- window.removeEventListener('resize', updateDropdownPosition)
68
- }
69
- }
70
- }, [isDropdownOpen])
71
-
72
- useEffect(() => {
73
- if (wrapperRef.current) {
74
- const remove = useClickOutside(wrapperRef.current, () => setDropdownOpen(false), () => portalDropdownRef.current)
75
- return remove
76
- }
77
- }, [])
78
-
79
- useEffect(() => {
80
- if (isDropdownOpen && searchInputRef.current) {
81
- searchInputRef.current.focus()
82
- }
83
- }, [isDropdownOpen])
84
-
85
- const selectCode = (item: CountryCode) => {
86
- setSelectedCode(item.country_code)
87
- onChange && onChange(item)
88
- setDropdownOpen(false)
89
- setSearchQuery('')
90
- }
91
-
92
- const selectedCountry = codes.find(c => c.country_code === selectedCode) || {
93
- country_code: selectedCode,
94
- flag: '',
95
- country: '',
96
- code: '',
97
- }
98
-
99
- const filteredCodes = useMemo(() => {
100
- if (!searchQuery) return codes
101
- return codes.filter(c => c.country.toLowerCase().includes(searchQuery.toLowerCase()))
102
- }, [codes, searchQuery])
103
-
104
- const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
105
- const cursorPosition = e.target.selectionStart || 0
106
- const newValue = e.target.value
107
- setSearchQuery(newValue)
108
- requestAnimationFrame(() => {
109
- if (searchInputRef.current) {
110
- searchInputRef.current.focus()
111
- const newCursorPos = Math.min(cursorPosition + 1, newValue.length)
112
- searchInputRef.current.setSelectionRange(newCursorPos, newCursorPos)
113
- }
114
- })
115
- }
116
-
117
- const dropdownContent = isDropdownOpen ? (
118
- <div
119
- ref={portalDropdownRef}
120
- className="telpick-dropdown"
121
- role="listbox"
122
- style={{
123
- position: 'fixed',
124
- top: dropdownPosition.top,
125
- left: dropdownPosition.left,
126
- marginTop: 0
127
- }}
128
- onClick={(e) => e.stopPropagation()}
129
- onMouseDown={(e) => e.stopPropagation()}
130
- >
131
- <input
132
- ref={searchInputRef}
133
- value={searchQuery}
134
- onChange={handleSearchChange}
135
- onClick={(e) => e.stopPropagation()}
136
- onMouseDown={(e) => e.stopPropagation()}
137
- type="text"
138
- placeholder="Buscar país..."
139
- className="telpick-search"
140
- autoFocus
141
- />
142
- <ul>
143
- {filteredCodes.map((item, index) => {
144
- const isSelected = item.country_code === selectedCode && selectedCode !== null && selectedCode !== undefined
145
- return (
146
- <li
147
- key={`${item.country_code}-${index}`}
148
- onClick={() => selectCode(item)}
149
- className={`telpick-item ${isSelected ? 'telpick-item-selected' : ''}`}
150
- role="option"
151
- aria-selected={isSelected}
152
- >
153
- <div className="telpick-flag">
154
- <img src={getFlagUrl(baseFlagUrl, item.flag, item.country_code)} alt={item.country} />
155
- </div>
156
- <span>{item.country}</span>
157
- <span className="ml-auto">{item.code}</span>
158
- </li>
159
- )
160
- })}
161
- </ul>
162
- </div>
163
- ) : null
164
-
165
- return (
166
- <div className="telpick-wrapper relative" ref={wrapperRef}>
167
- <button
168
- ref={buttonRef}
169
- onClick={() => setDropdownOpen(!isDropdownOpen)}
170
- className="telpick-btn"
171
- style={styleOverrides}
172
- aria-expanded={isDropdownOpen}
173
- aria-haspopup="listbox"
174
- >
175
- <div className="telpick-flag">
176
- {getFlagUrl(baseFlagUrl, selectedCountry.flag, selectedCountry.country_code) && (
177
- <img src={getFlagUrl(baseFlagUrl, selectedCountry.flag, selectedCountry.country_code)} alt={selectedCountry.country || 'flag'} />
178
- )}
179
- </div>
180
- <span>{selectedCountry.code}</span>
181
- <span className="telpick-arrow ml-auto">▼</span>
182
- </button>
183
- {createPortal(dropdownContent, document.body)}
184
- </div>
185
- )
186
- }
package/src/telpick.ts DELETED
@@ -1,163 +0,0 @@
1
- export interface CountryCode {
2
- country_code: string;
3
- flag: string;
4
- country: string;
5
- code: string;
6
- }
7
-
8
- export interface TelpickProps {
9
- code?: string;
10
- onChange?: (country: CountryCode) => void;
11
- styleOverrides?: Partial<Record<string, string>>;
12
- baseFlagUrl?: string;
13
- }
14
-
15
- export async function getDefaultCountry(codes: CountryCode[]): Promise<CountryCode | null> {
16
- const services = [
17
- async () => {
18
- try {
19
- const res = await fetch('https://ip-api.com/json/?fields=countryCode')
20
- const data = await res.json()
21
- if (data.countryCode) {
22
- return codes.find(c => c.country_code === data.countryCode) || null
23
- }
24
- } catch {}
25
- return null
26
- },
27
- async () => {
28
- try {
29
- const res = await fetch('https://get.geojs.io/v1/ip/country.json')
30
- const data = await res.json()
31
- if (data.country) {
32
- return codes.find(c => c.country_code === data.country) || null
33
- }
34
- } catch {}
35
- return null
36
- },
37
- async () => {
38
- try {
39
- const res = await fetch('https://ipapi.co/json/')
40
- const data = await res.json()
41
- if (data.country_code) {
42
- return codes.find(c => c.country_code === data.country_code) || null
43
- }
44
- } catch {}
45
- return null
46
- },
47
- async () => {
48
- try {
49
- const res = await fetch('https://ip-api.io/json/')
50
- const data = await res.json()
51
- if (data.country_code) {
52
- return codes.find(c => c.country_code === data.country_code) || null
53
- }
54
- } catch {}
55
- return null
56
- }
57
- ]
58
-
59
- for (const service of services) {
60
- try {
61
- const result = await Promise.race([
62
- service(),
63
- new Promise<null>((resolve) => setTimeout(() => resolve(null), 3000))
64
- ])
65
- if (result) return result
66
- } catch {
67
- continue
68
- }
69
- }
70
-
71
- try {
72
- const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
73
- const timezoneToCountry: Record<string, string> = {
74
- 'America/Lima': 'PE',
75
- 'America/Bogota': 'CO',
76
- 'America/Mexico_City': 'MX',
77
- 'America/Argentina/Buenos_Aires': 'AR',
78
- 'America/Santiago': 'CL',
79
- 'America/Caracas': 'VE',
80
- 'America/Montevideo': 'UY',
81
- 'America/Asuncion': 'PY',
82
- 'America/La_Paz': 'BO',
83
- 'America/Guayaquil': 'EC',
84
- 'America/Panama': 'PA',
85
- 'America/Costa_Rica': 'CR',
86
- 'America/Managua': 'NI',
87
- 'America/Tegucigalpa': 'HN',
88
- 'America/Guatemala': 'GT',
89
- 'America/El_Salvador': 'SV',
90
- 'America/Havana': 'CU',
91
- 'America/Santo_Domingo': 'DO',
92
- 'America/Jamaica': 'JM',
93
- 'America/Port-au-Prince': 'HT',
94
- 'Europe/Madrid': 'ES',
95
- 'Europe/London': 'GB',
96
- 'Europe/Paris': 'FR',
97
- 'Europe/Berlin': 'DE',
98
- 'Europe/Rome': 'IT',
99
- 'Europe/Amsterdam': 'NL',
100
- 'Europe/Brussels': 'BE',
101
- 'Europe/Vienna': 'AT',
102
- 'Europe/Zurich': 'CH',
103
- 'Europe/Stockholm': 'SE',
104
- 'Europe/Oslo': 'NO',
105
- 'Europe/Copenhagen': 'DK',
106
- 'Europe/Helsinki': 'FI',
107
- 'Europe/Warsaw': 'PL',
108
- 'Europe/Prague': 'CZ',
109
- 'Europe/Bucharest': 'RO',
110
- 'Europe/Moscow': 'RU',
111
- 'America/New_York': 'US',
112
- 'America/Chicago': 'US',
113
- 'America/Denver': 'US',
114
- 'America/Los_Angeles': 'US',
115
- 'America/Toronto': 'CA',
116
- 'America/Vancouver': 'CA',
117
- 'Asia/Tokyo': 'JP',
118
- 'Asia/Shanghai': 'CN',
119
- 'Asia/Hong_Kong': 'CN',
120
- 'Asia/Seoul': 'KR',
121
- 'Asia/Singapore': 'SG',
122
- 'Asia/Bangkok': 'TH',
123
- 'Asia/Jakarta': 'ID',
124
- 'Asia/Manila': 'PH',
125
- 'Asia/Kolkata': 'IN',
126
- 'Asia/Dubai': 'AE',
127
- 'Asia/Riyadh': 'SA',
128
- 'Australia/Sydney': 'AU',
129
- 'Australia/Melbourne': 'AU',
130
- 'Pacific/Auckland': 'NZ',
131
- 'Africa/Cairo': 'EG',
132
- 'Africa/Johannesburg': 'ZA',
133
- 'Africa/Nairobi': 'KE',
134
- 'Africa/Lagos': 'NG'
135
- }
136
-
137
- const countryCode = timezoneToCountry[timezone]
138
- if (countryCode) {
139
- return codes.find(c => c.country_code === countryCode) || null
140
- }
141
- } catch {}
142
-
143
- return codes.find(c => c.country_code === 'CO') || null
144
- }
145
-
146
- export function useClickOutside(
147
- ref: HTMLElement,
148
- cb: () => void,
149
- /** Cuando el dropdown se renderiza en un portal/Teleport, pasar su ref (o getter) para no cerrar al hacer click dentro */
150
- ignoreRef?: HTMLElement | null | (() => HTMLElement | null)
151
- ) {
152
- function handler(e: MouseEvent) {
153
- const target = e.target as Node
154
- if (!ref || !target) return
155
- const ignore = typeof ignoreRef === 'function' ? ignoreRef() : ignoreRef
156
- if (ignore && ignore.contains(target)) return
157
- const dropdown = ref.querySelector('.telpick-dropdown')
158
- const inDropdown = dropdown ? dropdown.contains(target) : false
159
- if (!ref.contains(target) && !inDropdown) cb()
160
- }
161
- document.addEventListener('click', handler, true)
162
- return () => document.removeEventListener('click', handler, true)
163
- }
@@ -1,199 +0,0 @@
1
- import { getDefaultCountry, useClickOutside, CountryCode, TelpickProps } from './telpick'
2
- import './telpick.css'
3
-
4
- export class TelpickVanilla {
5
- constructor(options = {}) {
6
- this.code = options.code || null
7
- this.onChange = options.onChange || (() => {})
8
- this.styleOverrides = options.styleOverrides || {}
9
- this.codes = []
10
- this.selectedCode = this.code
11
- this.isDropdownOpen = false
12
- this.searchQuery = ''
13
- this.container = null
14
- this.dropdown = null
15
- this.searchInput = null
16
- }
17
-
18
- async init(container) {
19
- this.container = container
20
- const res = await fetch('/resources/api/country-codes.json')
21
- const data = await res.json()
22
- this.codes = data.sort((a, b) => a.country.localeCompare(b.country, 'es'))
23
- if (!this.code) {
24
- const def = await getDefaultCountry(this.codes)
25
- if (def) this.selectedCode = def.country_code
26
- }
27
- this.render()
28
- useClickOutside(this.container, () => {
29
- this.closeDropdown()
30
- })
31
- }
32
-
33
- render() {
34
- if (this.isDropdownOpen && this.dropdown && this.searchInput) {
35
- const ul = this.dropdown.querySelector('ul')
36
- if (ul) {
37
- ul.innerHTML = ''
38
- const filtered = !this.searchQuery
39
- ? this.codes
40
- : this.codes.filter(c => c.country.toLowerCase().includes(this.searchQuery.toLowerCase()))
41
-
42
- filtered.forEach((item, index) => {
43
- const li = document.createElement('li')
44
- const isSelected = item.country_code === this.selectedCode && this.selectedCode !== null && this.selectedCode !== undefined
45
- li.className = `telpick-item ${isSelected ? 'telpick-item-selected' : ''}`
46
- li.setAttribute('role', 'option')
47
- li.setAttribute('aria-selected', isSelected)
48
- li.onclick = () => {
49
- this.selectedCode = item.country_code
50
- this.onChange(item)
51
- this.isDropdownOpen = false
52
- this.searchQuery = ''
53
- this.render()
54
- }
55
-
56
- const flag = document.createElement('div')
57
- flag.className = 'telpick-flag'
58
- const img = document.createElement('img')
59
- img.src = item.flag
60
- img.alt = item.country
61
- flag.appendChild(img)
62
- li.appendChild(flag)
63
-
64
- const countrySpan = document.createElement('span')
65
- countrySpan.textContent = item.country
66
- li.appendChild(countrySpan)
67
-
68
- const codeSpan = document.createElement('span')
69
- codeSpan.className = 'ml-auto'
70
- codeSpan.textContent = item.code
71
- li.appendChild(codeSpan)
72
-
73
- ul.appendChild(li)
74
- })
75
- }
76
- return
77
- }
78
-
79
- this.container.innerHTML = ''
80
- this.container.className = 'telpick-wrapper relative'
81
-
82
- const btn = document.createElement('button')
83
- btn.className = 'telpick-btn'
84
- btn.setAttribute('aria-expanded', this.isDropdownOpen)
85
- btn.setAttribute('aria-haspopup', 'listbox')
86
- Object.assign(btn.style, this.styleOverrides)
87
- btn.onclick = () => {
88
- this.isDropdownOpen = !this.isDropdownOpen
89
- this.render()
90
- }
91
-
92
- const flagDiv = document.createElement('div')
93
- flagDiv.className = 'telpick-flag'
94
- const selectedCountry = this.codes.find(c => c.country_code === this.selectedCode) || { flag: '', code: '', country: '' }
95
- if (selectedCountry.flag) {
96
- const img = document.createElement('img')
97
- img.src = selectedCountry.flag
98
- img.alt = selectedCountry.country || 'flag'
99
- flagDiv.appendChild(img)
100
- }
101
- btn.appendChild(flagDiv)
102
-
103
- const codeSpan = document.createElement('span')
104
- codeSpan.textContent = selectedCountry.code
105
- btn.appendChild(codeSpan)
106
-
107
- const arrowSpan = document.createElement('span')
108
- arrowSpan.className = 'telpick-arrow ml-auto'
109
- arrowSpan.textContent = '▼'
110
- btn.appendChild(arrowSpan)
111
- this.container.appendChild(btn)
112
-
113
- if (this.isDropdownOpen) {
114
- this.dropdown = document.createElement('div')
115
- this.dropdown.className = 'telpick-dropdown'
116
- this.dropdown.setAttribute('role', 'listbox')
117
- this.dropdown.onclick = e => e.stopPropagation()
118
- this.dropdown.onmousedown = e => e.stopPropagation()
119
-
120
- const input = document.createElement('input')
121
- input.className = 'telpick-search'
122
- input.type = 'text'
123
- input.placeholder = 'Buscar país...'
124
- input.value = this.searchQuery
125
- input.autofocus = true
126
- this.searchInput = input
127
- input.oninput = e => {
128
- e.stopPropagation()
129
- const inputEl = e.target
130
- const cursorPos = inputEl.selectionStart || 0
131
- const newValue = inputEl.value
132
- this.searchQuery = newValue
133
- this.render()
134
- requestAnimationFrame(() => {
135
- if (this.searchInput) {
136
- this.searchInput.focus()
137
- const newCursorPos = Math.min(cursorPos + 1, newValue.length)
138
- this.searchInput.setSelectionRange(newCursorPos, newCursorPos)
139
- }
140
- })
141
- }
142
- input.onclick = e => e.stopPropagation()
143
- input.onmousedown = e => e.stopPropagation()
144
- this.dropdown.appendChild(input)
145
-
146
- const ul = document.createElement('ul')
147
- const filtered = !this.searchQuery
148
- ? this.codes
149
- : this.codes.filter(c => c.country.toLowerCase().includes(this.searchQuery.toLowerCase()))
150
-
151
- filtered.forEach((item, index) => {
152
- const li = document.createElement('li')
153
- const isSelected = item.country_code === this.selectedCode && this.selectedCode !== null && this.selectedCode !== undefined
154
- li.className = `telpick-item ${isSelected ? 'telpick-item-selected' : ''}`
155
- li.setAttribute('role', 'option')
156
- li.setAttribute('aria-selected', isSelected)
157
- li.onclick = () => {
158
- this.selectedCode = item.country_code
159
- this.onChange(item)
160
- this.isDropdownOpen = false
161
- this.searchQuery = ''
162
- this.render()
163
- }
164
-
165
- const flag = document.createElement('div')
166
- flag.className = 'telpick-flag'
167
- const img = document.createElement('img')
168
- img.src = item.flag
169
- img.alt = item.country
170
- flag.appendChild(img)
171
- li.appendChild(flag)
172
-
173
- const countrySpan = document.createElement('span')
174
- countrySpan.textContent = item.country
175
- li.appendChild(countrySpan)
176
-
177
- const codeSpan = document.createElement('span')
178
- codeSpan.className = 'ml-auto'
179
- codeSpan.textContent = item.code
180
- li.appendChild(codeSpan)
181
-
182
- ul.appendChild(li)
183
- })
184
- this.dropdown.appendChild(ul)
185
- this.container.appendChild(this.dropdown)
186
-
187
- requestAnimationFrame(() => {
188
- if (this.searchInput) {
189
- this.searchInput.focus()
190
- }
191
- })
192
- }
193
- }
194
-
195
- closeDropdown() {
196
- this.isDropdownOpen = false
197
- this.render()
198
- }
199
- }
@@ -1,191 +0,0 @@
1
- import { defineComponent, ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
2
- import { getDefaultCountry, useClickOutside, CountryCode, TelpickProps } from './telpick'
3
- import './telpick.css'
4
-
5
- export const TelpickVue = defineComponent({
6
- name: 'TelpickVue',
7
- props: {
8
- code: { type: String, default: null },
9
- styleOverrides: { type: Object, default: () => ({}) },
10
- baseFlagUrl: { type: String, default: '' }
11
- },
12
- emits: ['update:code'],
13
- setup(props, { emit }) {
14
- const codes = ref<CountryCode[]>([])
15
- const selectedCode = ref(props.code)
16
- const isDropdownOpen = ref(false)
17
- const searchQuery = ref('')
18
- const wrapperRef = ref<HTMLElement | null>(null)
19
- const buttonRef = ref<HTMLElement | null>(null)
20
- const dropdownRef = ref<HTMLElement | null>(null)
21
- const searchInputRef = ref<HTMLInputElement | null>(null)
22
- const dropdownStyle = ref<Record<string, string>>({})
23
-
24
- const handleSearchInput = (e: Event) => {
25
- const input = e.target as HTMLInputElement
26
- const cursorPos = input.selectionStart || 0
27
- const newValue = input.value
28
- searchQuery.value = newValue
29
- requestAnimationFrame(() => {
30
- if (searchInputRef.value) {
31
- searchInputRef.value.focus()
32
- const newCursorPos = Math.min(cursorPos + 1, newValue.length)
33
- searchInputRef.value.setSelectionRange(newCursorPos, newCursorPos)
34
- }
35
- })
36
- }
37
-
38
- const selectCode = (item: CountryCode) => {
39
- selectedCode.value = item.country_code
40
- emit('update:code', item)
41
- isDropdownOpen.value = false
42
- searchQuery.value = ''
43
- }
44
-
45
- const selectedCountry = computed(() => {
46
- return (
47
- codes.value.find((c) => c.country_code === selectedCode.value) || {
48
- country_code: selectedCode.value,
49
- flag: '',
50
- country: '',
51
- code: '',
52
- }
53
- )
54
- })
55
-
56
- function getFlagUrl(flagPath: string, countryCode: string) {
57
- const base = (props.baseFlagUrl || '').replace(/\/$/, '')
58
- if (!base) return flagPath || (countryCode ? `https://flagcdn.com/w40/${countryCode.toLowerCase()}.png` : '')
59
- if (base.includes('flagcdn.com')) {
60
- const code = (countryCode || (flagPath && flagPath.replace(/^.*\//, '').replace(/\.[^.]+$/, '')) || '').toLowerCase()
61
- return code ? `${base}/${code}.png` : ''
62
- }
63
- const filename = flagPath ? flagPath.replace(/^.*\//, '') : `${(countryCode || '').toLowerCase()}.webp`
64
- return filename ? `${base}/${filename}` : ''
65
- }
66
-
67
- function updateDropdownPosition() {
68
- if (!buttonRef.value) return
69
- const rect = buttonRef.value.getBoundingClientRect()
70
- dropdownStyle.value = {
71
- position: 'fixed',
72
- top: `${rect.bottom + 4}px`,
73
- left: `${rect.left}px`,
74
- marginTop: '0'
75
- }
76
- }
77
-
78
- const filteredCodes = computed(() => {
79
- if (!searchQuery.value) return codes.value
80
- return codes.value.filter((c) =>
81
- c.country.toLowerCase().includes(searchQuery.value.toLowerCase())
82
- )
83
- })
84
-
85
- watch(() => props.code, (newCode) => {
86
- if (newCode !== undefined && newCode !== null) {
87
- selectedCode.value = newCode
88
- }
89
- })
90
-
91
- const scrollResizeCleanup = ref<(() => void) | null>(null)
92
- watch(isDropdownOpen, async () => {
93
- if (scrollResizeCleanup.value) {
94
- scrollResizeCleanup.value()
95
- scrollResizeCleanup.value = null
96
- }
97
- if (isDropdownOpen.value) {
98
- await nextTick()
99
- updateDropdownPosition()
100
- if (searchInputRef.value) searchInputRef.value.focus()
101
- const onScrollResize = () => updateDropdownPosition()
102
- window.addEventListener('scroll', onScrollResize, true)
103
- window.addEventListener('resize', onScrollResize)
104
- scrollResizeCleanup.value = () => {
105
- window.removeEventListener('scroll', onScrollResize, true)
106
- window.removeEventListener('resize', onScrollResize)
107
- }
108
- }
109
- })
110
- onUnmounted(() => {
111
- if (scrollResizeCleanup.value) scrollResizeCleanup.value()
112
- })
113
-
114
- onMounted(async () => {
115
- const response = await fetch('/resources/api/country-codes.json')
116
- const data = await response.json()
117
- codes.value = data.sort((a, b) => a.country.localeCompare(b.country, 'es'))
118
- if (!props.code) {
119
- const def = await getDefaultCountry(codes.value)
120
- if (def) selectCode(def)
121
- }
122
- if (wrapperRef.value) {
123
- const remove = useClickOutside(wrapperRef.value, () => {
124
- isDropdownOpen.value = false
125
- }, () => dropdownRef.value)
126
- onUnmounted(remove)
127
- }
128
- })
129
-
130
- return {
131
- codes,
132
- selectedCode,
133
- isDropdownOpen,
134
- searchQuery,
135
- selectCode,
136
- selectedCountry,
137
- filteredCodes,
138
- wrapperRef,
139
- buttonRef,
140
- dropdownRef,
141
- dropdownStyle,
142
- searchInputRef,
143
- handleSearchInput,
144
- getFlagUrl
145
- }
146
- },
147
- template: `
148
- <div class="telpick-wrapper relative" ref="wrapperRef">
149
- <button
150
- ref="buttonRef"
151
- @click="isDropdownOpen = !isDropdownOpen"
152
- class="telpick-btn"
153
- :style="styleOverrides"
154
- :aria-expanded="isDropdownOpen"
155
- aria-haspopup="listbox"
156
- >
157
- <div class="telpick-flag">
158
- <img v-if="getFlagUrl(selectedCountry.flag, selectedCountry.country_code)" :src="getFlagUrl(selectedCountry.flag, selectedCountry.country_code)" :alt="selectedCountry.country || 'flag'" />
159
- </div>
160
- <span>{{ selectedCountry.code }}</span>
161
- <span class="telpick-arrow ml-auto">▼</span>
162
- </button>
163
- <Teleport to="body">
164
- <Transition name="telpick-dropdown">
165
- <div v-if="isDropdownOpen" ref="dropdownRef" class="telpick-dropdown" role="listbox" :style="dropdownStyle" @click.stop @mousedown.stop>
166
- <input
167
- ref="searchInputRef"
168
- v-model="searchQuery"
169
- type="text"
170
- placeholder="Buscar país..."
171
- class="telpick-search"
172
- @input="handleSearchInput"
173
- @click.stop
174
- @mousedown.stop
175
- autofocus
176
- />
177
- <ul>
178
- <li v-for="(item, index) in filteredCodes" :key="\`\${item.country_code}-\${index}\`" @click="selectCode(item)" :class="['telpick-item', { 'telpick-item-selected': item.country_code === selectedCode && selectedCode !== null && selectedCode !== undefined }]" role="option" :aria-selected="item.country_code === selectedCode && selectedCode !== null && selectedCode !== undefined">
179
- <div class="telpick-flag">
180
- <img :src="getFlagUrl(item.flag, item.country_code)" :alt="item.country" />
181
- </div>
182
- <span>{{ item.country }}</span>
183
- <span class="ml-auto">{{ item.code }}</span>
184
- </li>
185
- </ul>
186
- </div>
187
- </Transition>
188
- </Teleport>
189
- </div>
190
- `
191
- })
@@ -1,37 +0,0 @@
1
- // Wrapper para Vue, React y CDN usando Vanilla JS
2
- // Vue y React pueden usar el componente vanilla vía ref
3
-
4
- // Vue wrapper
5
- export function TelpickVue(props, { emit }) {
6
- let telpickInstance = null
7
- return {
8
- mounted() {
9
- telpickInstance = new window.Telpick({
10
- code: props.code,
11
- onChange: country => emit('update:code', country),
12
- styleOverrides: props.styleOverrides || {}
13
- })
14
- telpickInstance.init(this.$el)
15
- },
16
- beforeUnmount() {
17
- telpickInstance && telpickInstance.destroy()
18
- },
19
- render() {
20
- return null // Render handled by vanilla
21
- }
22
- }
23
- }
24
-
25
- // React wrapper
26
- import React, { useRef, useEffect } from 'react'
27
- export function TelpickReact({ code, onChange, styleOverrides }) {
28
- const ref = useRef()
29
- useEffect(() => {
30
- const telpickInstance = new window.Telpick({ code, onChange, styleOverrides })
31
- telpickInstance.init(ref.current)
32
- return () => telpickInstance.destroy()
33
- }, [code, onChange, styleOverrides])
34
- return <div ref={ref}></div>
35
- }
36
-
37
- // CDN usage: window.Telpick