@webority/ui-elements 0.6.12 → 0.7.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.
@@ -87,16 +87,18 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
87
87
  set value(e) {
88
88
  this._value = e == null ? "" : String(e), c(this, this._value);
89
89
  let t = this._readOptions().find((e) => String(e.value) === this._value);
90
- t && (this._label = h(t.label)), this._syncInput();
90
+ this._label = t ? h(t.label) : "", this._syncInput(), this._renderOptions("");
91
91
  }
92
92
  set options(e) {
93
- this._optionsProp = Array.isArray(e) ? e : [], this._renderOptions();
93
+ this._optionsProp = Array.isArray(e) ? e : [];
94
+ let t = this._readOptions().find((e) => String(e.value) === this._value);
95
+ t && (this._label = h(t.label)), this._renderOptions(), this._syncInput();
94
96
  }
95
97
  get options() {
96
98
  return this._readOptions();
97
99
  }
98
100
  set loading(e) {
99
- this._loading = !!e, this._renderLoading();
101
+ this._loading = !!e, this._renderLoading(), this._renderOptions();
100
102
  }
101
103
  get loading() {
102
104
  return this._loading;
@@ -108,8 +110,10 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
108
110
  return Math.max(0, Number(this.getAttribute("min-chars")) || +!!this._remote);
109
111
  }
110
112
  get _debounceMs() {
111
- let e = Number(this.getAttribute("debounce"));
112
- return Number.isFinite(e) && e >= 0 ? e : 250;
113
+ let e = this.getAttribute("debounce");
114
+ if (e == null || e === "") return 250;
115
+ let t = Number(e);
116
+ return Number.isFinite(t) && t >= 0 ? t : 250;
113
117
  }
114
118
  _snapshotDeclared() {
115
119
  if (this._declared) return;
@@ -564,24 +568,24 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
564
568
  "Th",
565
569
  "Fr",
566
570
  "Sa"
567
- ], D = (e) => String(e).padStart(2, "0"), O = (e, t, n) => `${e}-${D(t + 1)}-${D(n)}`, k = (e) => {
571
+ ], D = (e) => String(e).padStart(2, "0"), ee = (e, t, n) => `${e}-${D(t + 1)}-${D(n)}`, O = (e) => {
568
572
  let t = /^(\d{4})-(\d{2})-(\d{2})$/.exec(e || "");
569
573
  return t ? {
570
574
  y: +t[1],
571
575
  m: t[2] - 1,
572
576
  d: +t[3]
573
577
  } : null;
574
- }, A = (e) => {
575
- let t = k(e);
578
+ }, k = (e) => {
579
+ let t = O(e);
576
580
  return t ? `${D(t.d)} ${T[t.m].slice(0, 3)} ${t.y}` : "";
577
- }, j = (e, t) => new Date(e, t + 1, 0).getDate(), M = (e, t) => {
581
+ }, A = (e, t) => new Date(e, t + 1, 0).getDate(), j = (e, t) => {
578
582
  for (; t < 0;) t += 12, --e;
579
583
  for (; t > 11;) t -= 12, e += 1;
580
584
  return {
581
585
  y: e,
582
586
  m: t
583
587
  };
584
- }, N = class extends HTMLElement {
588
+ }, M = class extends HTMLElement {
585
589
  static get observedAttributes() {
586
590
  return [
587
591
  "start",
@@ -624,13 +628,13 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
624
628
  text: e,
625
629
  empty: !0
626
630
  } : {
627
- text: `${A(this._start) || "Start"} – ${A(this._end) || "End"}`,
631
+ text: `${k(this._start) || "Start"} – ${k(this._end) || "End"}`,
628
632
  empty: !1
629
633
  };
630
634
  }
631
635
  render() {
632
636
  this._start = this.getAttribute("start") || this._start, this._end = this.getAttribute("end") || this._end;
633
- let e = k(this._start);
637
+ let e = O(this._start);
634
638
  e && (this._viewY = e.y, this._viewM = e.m);
635
639
  let t = this.getAttribute("size"), n = t === "sm" ? " input-sm" : t === "lg" ? " input-lg" : "", { text: r, empty: i } = this._label();
636
640
  this.innerHTML = `
@@ -658,20 +662,20 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
658
662
  r || (r = document.createElement("input"), r.type = "hidden", r.setAttribute("data-range-mirror", e), this.appendChild(r)), r.name = t, r.value = n || "";
659
663
  }
660
664
  _limits() {
661
- let e = k(this.getAttribute("min")), t = k(this.getAttribute("max")), n = e ? new Date(e.y, e.m, e.d).getTime() : -Infinity, r = t ? new Date(t.y, t.m, t.d).getTime() : Infinity;
665
+ let e = O(this.getAttribute("min")), t = O(this.getAttribute("max")), n = e ? new Date(e.y, e.m, e.d).getTime() : -Infinity, r = t ? new Date(t.y, t.m, t.d).getTime() : Infinity;
662
666
  return (e, t, i) => {
663
667
  let a = new Date(e, t, i).getTime();
664
668
  return a < n || a > r;
665
669
  };
666
670
  }
667
671
  _monthHtml(e, t) {
668
- let n = this._firstDay(), r = (new Date(e, t, 1).getDay() - n + 7) % 7, i = j(e, t), a = this._limits(), o = E.map((e, t) => E[(t + n) % 7]).map((e) => `<span>${e}</span>`).join(""), s = (e, t, n, r) => {
669
- let i = O(e, t, n), o = a(e, t, n);
672
+ let n = this._firstDay(), r = (new Date(e, t, 1).getDay() - n + 7) % 7, i = A(e, t), a = this._limits(), o = E.map((e, t) => E[(t + n) % 7]).map((e) => `<span>${e}</span>`).join(""), s = (e, t, n, r) => {
673
+ let i = ee(e, t, n), o = a(e, t, n);
670
674
  return `<button type="button" class="${["datepicker-day", r ? "is-outside" : ""].filter(Boolean).join(" ")}" data-iso="${i}"${o ? " disabled" : ""}>${n}</button>`;
671
- }, c = "", l = M(e, t - 1), u = j(l.y, l.m);
675
+ }, c = "", l = j(e, t - 1), u = A(l.y, l.m);
672
676
  for (let e = r - 1; e >= 0; e--) c += s(l.y, l.m, u - e, !0);
673
677
  for (let n = 1; n <= i; n++) c += s(e, t, n, !1);
674
- let d = M(e, t + 1), f = (7 - (r + i) % 7) % 7;
678
+ let d = j(e, t + 1), f = (7 - (r + i) % 7) % 7;
675
679
  for (let e = 1; e <= f; e++) c += s(d.y, d.m, e, !0);
676
680
  return `
677
681
  <div class="daterange-cal">
@@ -683,7 +687,7 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
683
687
  _renderView() {
684
688
  let e = this.querySelector(".daterange-pop");
685
689
  if (!e) return;
686
- let t = M(this._viewY, this._viewM + 1);
690
+ let t = j(this._viewY, this._viewM + 1);
687
691
  e.innerHTML = `
688
692
  <div class="daterange-head">
689
693
  <button type="button" class="datepicker-nav-btn" data-nav="-1" aria-label="Previous month"><i class="bi bi-chevron-left" aria-hidden="true"></i></button>
@@ -709,7 +713,7 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
709
713
  n.classList.toggle("is-range-start", i), n.classList.toggle("is-range-end", a), n.classList.toggle("in-range", o);
710
714
  }
711
715
  let i = e.querySelector("[data-range-hint]");
712
- i && (i.textContent = this._start ? this._end ? `${A(this._start)} – ${A(this._end)}` : "Pick an end date" : "Pick a start date");
716
+ i && (i.textContent = this._start ? this._end ? `${k(this._start)} – ${k(this._end)}` : "Pick an end date" : "Pick a start date");
713
717
  }
714
718
  _position(e, t) {
715
719
  i(e, t);
@@ -730,7 +734,7 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
730
734
  if (!e || !t) return;
731
735
  let r = () => !t.hidden;
732
736
  this._open = () => {
733
- let r = k(this._start);
737
+ let r = O(this._start);
734
738
  if (r) this._viewY = r.y, this._viewM = r.m;
735
739
  else {
736
740
  let e = /* @__PURE__ */ new Date();
@@ -743,7 +747,7 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
743
747
  this._popClick = !0;
744
748
  let t = e.target.closest("[data-nav]");
745
749
  if (t) {
746
- let e = M(this._viewY, this._viewM + Number(t.dataset.nav));
750
+ let e = j(this._viewY, this._viewM + Number(t.dataset.nav));
747
751
  this._viewY = e.y, this._viewM = e.m, this._renderView();
748
752
  return;
749
753
  }
@@ -768,7 +772,7 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
768
772
  disconnectedCallback() {
769
773
  this._onDocClick && document.removeEventListener("click", this._onDocClick), this._onDocKey && document.removeEventListener("keydown", this._onDocKey), o(this);
770
774
  }
771
- }, P = class extends HTMLElement {
775
+ }, N = class extends HTMLElement {
772
776
  _accessibleName() {
773
777
  return this.getAttribute("aria-label") || this.getAttribute("placeholder") || "Select";
774
778
  }
@@ -838,13 +842,13 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
838
842
  let e = this.hasAttribute("searchable"), t = this.getAttribute("search-placeholder") || "Search…", n = this.getAttribute("icon"), r = this.getAttribute("size"), i = r === "sm" ? " search-select-sm" : r === "lg" ? " search-select-lg" : "";
839
843
  c(this, this._values.join(",")), this.innerHTML = `
840
844
  <div class="search-select${i}">
841
- <div class="input search-select-control search-select-multi" role="combobox" aria-haspopup="listbox" aria-expanded="false" aria-label="${F(this._accessibleName())}"${this.hasAttribute("disabled") ? " aria-disabled=\"true\"" : ""}>
842
- ${n ? `<i class="bi bi-${F(n)} search-select-icon" aria-hidden="true"></i>` : ""}
845
+ <div class="input search-select-control search-select-multi" role="combobox" aria-haspopup="listbox" aria-expanded="false" aria-label="${P(this._accessibleName())}"${this.hasAttribute("disabled") ? " aria-disabled=\"true\"" : ""}>
846
+ ${n ? `<i class="bi bi-${P(n)} search-select-icon" aria-hidden="true"></i>` : ""}
843
847
  <div class="ms-chips" data-chips></div>
844
848
  <i class="bi bi-chevron-down search-select-caret" aria-hidden="true"></i>
845
849
  </div>
846
850
  <div class="search-select-menu search-select-menu-fixed" role="listbox" aria-multiselectable="true" tabindex="-1" hidden>
847
- ${e ? `<div class="search-select-search"><i class="bi bi-search" aria-hidden="true"></i><input class="search-select-input" placeholder="${F(t)}" aria-autocomplete="list" /><button type="button" class="search-select-clear" aria-label="Clear search" hidden><i class="bi bi-x" aria-hidden="true"></i></button></div>` : ""}
851
+ ${e ? `<div class="search-select-search"><i class="bi bi-search" aria-hidden="true"></i><input class="search-select-input" placeholder="${P(t)}" aria-autocomplete="list" /><button type="button" class="search-select-clear" aria-label="Clear search" hidden><i class="bi bi-x" aria-hidden="true"></i></button></div>` : ""}
848
852
  <div class="search-select-options"></div>
849
853
  <div class="search-select-empty" hidden>No matches</div>
850
854
  </div>
@@ -858,7 +862,7 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
858
862
  e.innerHTML = `<span class="search-select-placeholder">${u(t)}</span>`;
859
863
  return;
860
864
  }
861
- e.innerHTML = this._values.map((e) => `<span class="chip chip-sm"><span class="chip-label">${this._labelHtmlFor(e)}</span><button type="button" class="chip-remove" data-remove="${F(e)}" aria-label="Remove"><i class="bi bi-x" aria-hidden="true"></i></button></span>`).join(""), this._collapseChips();
865
+ e.innerHTML = this._values.map((e) => `<span class="chip chip-sm"><span class="chip-label">${this._labelHtmlFor(e)}</span><button type="button" class="chip-remove" data-remove="${P(e)}" aria-label="Remove"><i class="bi bi-x" aria-hidden="true"></i></button></span>`).join(""), this._collapseChips();
862
866
  }
863
867
  _collapseChips() {
864
868
  let e = this.querySelector("[data-chips]");
@@ -882,9 +886,9 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
882
886
  let t = this.querySelector(".search-select-options"), n = this.querySelector(".search-select-empty");
883
887
  if (!t) return;
884
888
  let r = (e || "").trim().toLowerCase(), i = this._readOptions();
885
- r && (i = i.filter((e) => ee(e.label).toLowerCase().includes(r))), t.innerHTML = i.map((e) => {
889
+ r && (i = i.filter((e) => te(e.label).toLowerCase().includes(r))), t.innerHTML = i.map((e) => {
886
890
  let t = this._values.includes(String(e.value));
887
- return `<button type="button" role="option" class="search-select-option${t ? " selected" : ""}" data-value="${F(e.value)}" aria-selected="${t}"><span class="ms-opt-label">${f(e)}</span><span class="ms-check"><i class="bi bi-check" aria-hidden="true"></i></span></button>`;
891
+ return `<button type="button" role="option" class="search-select-option${t ? " selected" : ""}" data-value="${P(e.value)}" aria-selected="${t}"><span class="ms-opt-label">${f(e)}</span><span class="ms-check"><i class="bi bi-check" aria-hidden="true"></i></span></button>`;
888
892
  }).join(""), n && (n.hidden = i.length > 0), this._active = -1;
889
893
  }
890
894
  _wire() {
@@ -946,7 +950,7 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
946
950
  disconnectedCallback() {
947
951
  this._onDocClick && document.removeEventListener("click", this._onDocClick), o(this), this._ro?.disconnect(), this._ro = null;
948
952
  }
949
- }, F = (e) => String(e ?? "").replace(/"/g, "&quot;").replace(/</g, "&lt;"), ee = (e) => String(e ?? "").replace(/<[^>]*>/g, ""), I = /[^0-9]/g, L = /[^0-9a-zA-Z]/g, R = class extends HTMLElement {
953
+ }, P = (e) => String(e ?? "").replace(/"/g, "&quot;").replace(/</g, "&lt;"), te = (e) => String(e ?? "").replace(/<[^>]*>/g, ""), ne = /[^0-9]/g, re = /[^0-9a-zA-Z]/g, F = class extends HTMLElement {
950
954
  static get observedAttributes() {
951
955
  return [
952
956
  "value",
@@ -976,7 +980,7 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
976
980
  this._value = this._clean(e), c(this, this._value), this._paint();
977
981
  }
978
982
  _clean(e) {
979
- return (e == null ? "" : String(e)).replace(this.mode === "alphanumeric" ? L : I, "").slice(0, this.length);
983
+ return (e == null ? "" : String(e)).replace(this.mode === "alphanumeric" ? re : ne, "").slice(0, this.length);
980
984
  }
981
985
  connectedCallback() {
982
986
  this._rendered || this.render();
@@ -1042,7 +1046,7 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
1042
1046
  document.activeElement === e && this._paint();
1043
1047
  });
1044
1048
  }
1045
- }, z = [
1049
+ }, I = [
1046
1050
  [
1047
1051
  "AF",
1048
1052
  "Afghanistan",
@@ -2268,11 +2272,67 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
2268
2272
  "Zimbabwe",
2269
2273
  "263"
2270
2274
  ]
2271
- ], B = (e) => (z.find((t) => t[0] === e) || [
2275
+ ], L = (e) => (I.find((t) => t[0] === e) || [
2272
2276
  "",
2273
2277
  "",
2274
2278
  ""
2275
- ])[2], V = (e) => `wui-flag wui-flag-${String(e).toLowerCase()}`, H = class extends HTMLElement {
2279
+ ])[2], R = (e) => `wui-flag wui-flag-${String(e).toLowerCase()}`, z = null, B = null;
2280
+ function ie() {
2281
+ return z ? Promise.resolve(z) : (B ||= Promise.all([import("./libphonenumber-js-BcNT8oq0.js"), import("./examples.mobile.json-BMXTGiGC.js")]).then(([e, t]) => (z = {
2282
+ AsYouType: e.AsYouType,
2283
+ getExampleNumber: e.getExampleNumber,
2284
+ isValidPhoneNumber: e.isValidPhoneNumber,
2285
+ examples: t.default || t
2286
+ }, z)).catch(() => null), B);
2287
+ }
2288
+ function V(e, t) {
2289
+ if (!z || !t) return t;
2290
+ try {
2291
+ return new z.AsYouType(e).input(t);
2292
+ } catch {
2293
+ return t;
2294
+ }
2295
+ }
2296
+ function H(e) {
2297
+ if (!z) return null;
2298
+ try {
2299
+ return z.getExampleNumber(e, z.examples)?.formatNational() || null;
2300
+ } catch {
2301
+ return null;
2302
+ }
2303
+ }
2304
+ function U(e) {
2305
+ if (!z || !e) return null;
2306
+ try {
2307
+ return z.isValidPhoneNumber(e);
2308
+ } catch {
2309
+ return null;
2310
+ }
2311
+ }
2312
+ function ae(e) {
2313
+ if (!z) return null;
2314
+ try {
2315
+ let t = z.getExampleNumber(e, z.examples);
2316
+ return t?.nationalNumber ? t.nationalNumber.length : null;
2317
+ } catch {
2318
+ return null;
2319
+ }
2320
+ }
2321
+ function W(e) {
2322
+ if (!z || !e?.trim().startsWith("+")) return null;
2323
+ try {
2324
+ let t = new z.AsYouType();
2325
+ t.input(e.trim());
2326
+ let n = t.getCountry();
2327
+ return n ? {
2328
+ country: n,
2329
+ national: t.getNationalNumber() || ""
2330
+ } : null;
2331
+ } catch {
2332
+ return null;
2333
+ }
2334
+ }
2335
+ var G = class extends HTMLElement {
2276
2336
  static get observedAttributes() {
2277
2337
  return [
2278
2338
  "value",
@@ -2291,73 +2351,103 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
2291
2351
  this._rendered && (e === "country" && (this._country = n || "IN"), this.render());
2292
2352
  }
2293
2353
  get value() {
2294
- return `+${B(this._country)}${this._national}`;
2354
+ return `+${L(this._country)}${this._national}`;
2295
2355
  }
2296
2356
  set value(e) {
2297
- this._national = String(e ?? "").replace(/[^0-9]/g, ""), this._commit();
2357
+ let t = String(e ?? "").trim(), n = W(t);
2358
+ if (n) this._country = n.country, this._national = n.national.replace(/[^0-9]/g, "");
2359
+ else if (t.startsWith("+")) {
2360
+ let e = t.replace(/[^0-9]/g, ""), n = String(L(this._country));
2361
+ n && e.startsWith(n) && (e = e.slice(n.length)), this._national = e;
2362
+ } else this._national = t.replace(/[^0-9]/g, "");
2363
+ n && this.getAttribute("country") !== this._country ? this.setAttribute("country", this._country) : this._rendered && this.render(), this._commit();
2298
2364
  }
2299
2365
  _commit() {
2300
2366
  c(this, this.value), this.dispatchEvent(new Event("change", { bubbles: !0 }));
2301
2367
  }
2302
2368
  render() {
2303
- let e = this.getAttribute("placeholder") || "Enter phone number";
2369
+ let e = this.getAttribute("placeholder") || H(this._country) || "Enter phone number";
2304
2370
  this._country = this.getAttribute("country") || this._country;
2305
- let t = z.map(([e, t, n]) => `<button type="button" role="option" class="country-dropdown-item${e === this._country ? " selected" : ""}" data-iso="${e}"><span class="${V(e)}" aria-hidden="true"></span><span class="country-name-text">${t}<span class="country-code-text">+${n}</span></span></button>`).join("");
2371
+ let t = I.map(([e, t, n]) => `<button type="button" role="option" class="country-dropdown-item${e === this._country ? " selected" : ""}" data-iso="${e}"><span class="${R(e)}" aria-hidden="true"></span><span class="country-name-text">${t}<span class="country-code-text">+${n}</span></span></button>`).join("");
2306
2372
  this.innerHTML = `
2307
2373
  <div class="phone-input-wrap">
2308
2374
  <div class="phone-country-adornment">
2309
2375
  <button type="button" class="country-toggle" aria-haspopup="listbox" aria-expanded="false"${this.hasAttribute("disabled") ? " disabled" : ""}>
2310
- <span class="${V(this._country)}" data-flag aria-hidden="true"></span>
2376
+ <span class="${R(this._country)}" data-flag aria-hidden="true"></span>
2311
2377
  <i class="bi bi-chevron-down phone-chevron" aria-hidden="true"></i>
2312
- <span class="phone-dial" data-dial>+${B(this._country)}</span>
2378
+ <span class="phone-dial" data-dial>+${L(this._country)}</span>
2313
2379
  </button>
2314
2380
  <div class="country-dropdown-menu" role="listbox" hidden>
2315
2381
  <div class="dropdown-search-wrapper"><span class="dropdown-search-icon"><i class="bi bi-search" aria-hidden="true"></i></span><input type="text" class="dropdown-search-input" placeholder="Search country or code" aria-label="Search countries" /></div>
2316
2382
  <div class="country-list-scroll">${t}<div class="country-empty" hidden>No countries found</div></div>
2317
2383
  </div>
2318
2384
  </div>
2319
- <input type="tel" class="input" placeholder="${U(e)}" value="${U(this._national)}"${this.hasAttribute("disabled") ? " disabled" : ""} />
2320
- </div>`, this._rendered = !0, c(this, this.value), this._wire();
2385
+ <input type="tel" class="input" placeholder="${K(e)}" value="${K(V(this._country, this._national))}"${this.hasAttribute("disabled") ? " disabled" : ""} />
2386
+ </div>
2387
+ <div class="field-error" data-phone-error hidden></div>`, this._rendered = !0, c(this, this.value), this._wire();
2321
2388
  }
2322
2389
  _wire() {
2323
- let e = this.querySelector(".country-toggle"), t = this.querySelector(".country-dropdown-menu"), n = this.querySelector(".dropdown-search-input"), r = this.querySelector(".country-list-scroll"), i = this.querySelector(".country-empty"), a = this.querySelector("input[type=tel]"), o = this.querySelector("[data-flag]"), s = this.querySelector("[data-dial]");
2324
- if (!e || !t) return;
2325
- let l = () => !t.hidden, u = () => {
2326
- let n = e.getBoundingClientRect(), r = t.offsetWidth || 320, i = t.offsetHeight || 320, a = window.innerHeight - n.bottom, o = a < i + 6 && n.top > a ? n.top - i - 6 : n.bottom + 6, s = Math.min(Math.max(8, n.left), Math.max(8, window.innerWidth - r - 8));
2327
- t.style.top = `${Math.max(8, o)}px`, t.style.left = `${s}px`;
2328
- }, d = () => {
2329
- t.hidden = !1, e.setAttribute("aria-expanded", "true"), n.value = "", p(""), u(), n.focus();
2390
+ let e = this.querySelector(".country-toggle"), t = this.querySelector(".phone-input-wrap"), n = this.querySelector(".country-dropdown-menu"), r = this.querySelector(".dropdown-search-input"), i = this.querySelector(".country-list-scroll"), a = this.querySelector(".country-empty"), o = this.querySelector("input[type=tel]"), s = this.querySelector("[data-flag]"), l = this.querySelector("[data-dial]");
2391
+ if (!e || !n) return;
2392
+ let u = () => !n.hidden, d = () => {
2393
+ let r = (t || e).getBoundingClientRect(), i = n.offsetWidth || 320, a = n.offsetHeight || 320, o = window.innerHeight - r.bottom, s = o < a + 6 && r.top > o ? r.top - a - 6 : r.bottom + 6, c = Math.min(Math.max(8, r.left), Math.max(8, window.innerWidth - i - 8));
2394
+ n.style.top = `${Math.max(8, s)}px`, n.style.left = `${c}px`;
2330
2395
  }, f = () => {
2331
- t.hidden = !0, e.setAttribute("aria-expanded", "false");
2396
+ n.hidden = !1, e.setAttribute("aria-expanded", "true"), r.value = "", m(""), d(), r.focus();
2397
+ }, p = () => {
2398
+ n.hidden = !0, e.setAttribute("aria-expanded", "false");
2332
2399
  };
2333
2400
  this._reposition = () => {
2334
- l() && u();
2401
+ u() && d();
2335
2402
  }, window.addEventListener("scroll", this._reposition, !0), window.addEventListener("resize", this._reposition);
2336
- let p = (e) => {
2403
+ let m = (e) => {
2337
2404
  let t = e.trim().toLowerCase(), n = 0;
2338
- for (let e of r.querySelectorAll(".country-dropdown-item")) {
2405
+ for (let e of i.querySelectorAll(".country-dropdown-item")) {
2339
2406
  let r = !t || e.textContent.toLowerCase().includes(t);
2340
2407
  e.hidden = !r, r && (n += 1);
2341
2408
  }
2342
- i && (i.hidden = n > 0);
2343
- }, m = (e) => {
2344
- this._country = e, this.setAttribute("country", e), o && (o.className = V(e)), s && (s.textContent = `+${B(e)}`);
2345
- for (let t of r.querySelectorAll(".country-dropdown-item")) t.classList.toggle("selected", t.dataset.iso === e);
2346
- f(), this._commit();
2409
+ a && (a.hidden = n > 0);
2410
+ }, h = (e) => {
2411
+ this._country = e, this.setAttribute("country", e), s && (s.className = R(e)), l && (l.textContent = `+${L(e)}`);
2412
+ for (let t of i.querySelectorAll(".country-dropdown-item")) t.classList.toggle("selected", t.dataset.iso === e);
2413
+ p(), this._commit();
2347
2414
  };
2348
- e.addEventListener("click", () => l() ? f() : d()), n.addEventListener("input", () => p(n.value)), r.addEventListener("click", (e) => {
2415
+ e.addEventListener("click", () => u() ? p() : f()), r.addEventListener("input", () => m(r.value)), i.addEventListener("click", (e) => {
2349
2416
  let t = e.target.closest(".country-dropdown-item");
2350
- t && m(t.dataset.iso);
2351
- }), a.addEventListener("input", () => {
2352
- this._national = a.value.replace(/[^0-9]/g, ""), this._commit();
2417
+ t && h(t.dataset.iso);
2418
+ });
2419
+ let g = this.querySelector("[data-phone-error]"), _ = (e) => {
2420
+ if (o.classList.toggle("is-invalid", e), e ? o.setAttribute("aria-invalid", "true") : o.removeAttribute("aria-invalid"), g) {
2421
+ if (e) {
2422
+ let e = H(this._country);
2423
+ g.textContent = e ? `Enter a valid phone number, e.g. ${e}` : "Enter a valid phone number";
2424
+ }
2425
+ g.hidden = !e;
2426
+ }
2427
+ };
2428
+ o.addEventListener("input", () => {
2429
+ let e = o.value.replace(/[^0-9]/g, ""), t = ae(this._country);
2430
+ t && e.length > t && (e = e.slice(0, t)), this._national = e;
2431
+ let n = V(this._country, this._national);
2432
+ o.value !== n && (o.value = n), this._commit(), o.classList.contains("is-invalid") && (!this._national || U(this.value) === !0) && _(!1);
2433
+ }), o.addEventListener("blur", () => {
2434
+ _(this._national.length > 0 && U(this.value) === !1);
2435
+ }), o.addEventListener("paste", (e) => {
2436
+ let t = W(e.clipboardData?.getData("text"));
2437
+ t && (e.preventDefault(), this._national = t.national.replace(/[^0-9]/g, ""), t.country === this._country ? o.value = V(this._country, this._national) : this.setAttribute("country", t.country), this._commit(), this.querySelector("input[type=tel]")?.focus());
2353
2438
  }), this._onDocClick = (e) => {
2354
- l() && !this.contains(e.target) && f();
2355
- }, document.addEventListener("click", this._onDocClick), c(this, this.value);
2439
+ u() && !this.contains(e.target) && p();
2440
+ }, document.addEventListener("click", this._onDocClick), ie().then((e) => {
2441
+ if (!(!e || !o) && (this._national && (o.value = V(this._country, this._national)), !this.getAttribute("placeholder"))) {
2442
+ let e = H(this._country);
2443
+ e && (o.placeholder = e);
2444
+ }
2445
+ }), c(this, this.value);
2356
2446
  }
2357
2447
  disconnectedCallback() {
2358
2448
  this._reposition && (window.removeEventListener("scroll", this._reposition, !0), window.removeEventListener("resize", this._reposition)), this._onDocClick && document.removeEventListener("click", this._onDocClick);
2359
2449
  }
2360
- }, U = (e) => String(e ?? "").replace(/"/g, "&quot;").replace(/</g, "&lt;"), W = class extends HTMLElement {
2450
+ }, K = (e) => String(e ?? "").replace(/"/g, "&quot;").replace(/</g, "&lt;"), q = class extends HTMLElement {
2361
2451
  static get observedAttributes() {
2362
2452
  return [
2363
2453
  "value",
@@ -2383,7 +2473,11 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
2383
2473
  this._rendered || this.render();
2384
2474
  }
2385
2475
  attributeChangedCallback(e, t, n) {
2386
- this._rendered && (e === "value" ? this.value = n : this.render());
2476
+ if (e === "value") {
2477
+ this.value = n;
2478
+ return;
2479
+ }
2480
+ this._rendered && this.render();
2387
2481
  }
2388
2482
  get value() {
2389
2483
  return this._value;
@@ -2417,19 +2511,19 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
2417
2511
  d && (this._value = String(d.value)), c(this, this._value);
2418
2512
  let p = e.map((e) => {
2419
2513
  let t = String(e.value) === String(this._value);
2420
- return `<button type="button" role="option" class="search-select-option${t ? " selected" : ""}" data-value="${G(e.value)}" aria-selected="${t}">${f(e)}</button>`;
2514
+ return `<button type="button" role="option" class="search-select-option${t ? " selected" : ""}" data-value="${J(e.value)}" aria-selected="${t}">${f(e)}</button>`;
2421
2515
  }).join("");
2422
2516
  this.innerHTML = `
2423
2517
  <div class="search-select${this.hasAttribute("compact") ? " search-select-compact" : ""}${i}">
2424
- <button type="button" role="combobox" class="input search-select-control" aria-haspopup="listbox" aria-expanded="false" aria-label="${G(this._accessibleName())}"${this.hasAttribute("disabled") ? " disabled" : ""}>
2425
- ${a ? `<i class="bi bi-${G(a)} search-select-icon" aria-hidden="true"></i>` : ""}
2518
+ <button type="button" role="combobox" class="input search-select-control" aria-haspopup="listbox" aria-expanded="false" aria-label="${J(this._accessibleName())}"${this.hasAttribute("disabled") ? " disabled" : ""}>
2519
+ ${a ? `<i class="bi bi-${J(a)} search-select-icon" aria-hidden="true"></i>` : ""}
2426
2520
  ${o ? `<span class="search-select-prefix">${u(o)}</span>` : ""}
2427
2521
  <span class="${d ? "" : "search-select-placeholder"}" data-label>${d ? f(d) : u(s)}</span>
2428
2522
  ${n ? "<span class=\"search-select-reset\" role=\"button\" aria-label=\"Clear selection\" hidden><i class=\"bi bi-x-lg\" aria-hidden=\"true\"></i></span>" : ""}
2429
2523
  <i class="bi bi-chevron-down search-select-caret" aria-hidden="true"></i>
2430
2524
  </button>
2431
2525
  <div class="search-select-menu search-select-menu-fixed" role="listbox" tabindex="-1" hidden>
2432
- ${t ? `<div class="search-select-search"><i class="bi bi-search" aria-hidden="true"></i><input class="search-select-input" placeholder="${G(l)}" aria-autocomplete="list" /><button type="button" class="search-select-clear" aria-label="Clear search" hidden><i class="bi bi-x" aria-hidden="true"></i></button></div>` : ""}
2526
+ ${t ? `<div class="search-select-search"><i class="bi bi-search" aria-hidden="true"></i><input class="search-select-input" placeholder="${J(l)}" aria-autocomplete="list" /><button type="button" class="search-select-clear" aria-label="Clear search" hidden><i class="bi bi-x" aria-hidden="true"></i></button></div>` : ""}
2433
2527
  <div class="search-select-options">${p}<div class="search-select-empty" hidden>No matches</div></div>
2434
2528
  </div>
2435
2529
  </div>`, this._rendered = !0, c(this, this._value), this._wire(), this._syncReset();
@@ -2510,7 +2604,7 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
2510
2604
  t && n(this._visible().indexOf(t));
2511
2605
  }), e.optionsWrap.addEventListener("mouseleave", () => n(-1)), e.search?.addEventListener("input", () => {
2512
2606
  r(e.search.value), n(-1);
2513
- }), e.search?.addEventListener("keydown", u), e.clear?.addEventListener("click", () => {
2607
+ }), e.clear?.addEventListener("click", () => {
2514
2608
  e.search.value = "", r(""), e.search.focus();
2515
2609
  }), e.menu.addEventListener("keydown", u), this._onDocClick = (e) => {
2516
2610
  o() && !this.contains(e.target) && c();
@@ -2521,14 +2615,14 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
2521
2615
  disconnectedCallback() {
2522
2616
  this._onDocClick && document.removeEventListener("click", this._onDocClick), o(this);
2523
2617
  }
2524
- }, G = (e) => String(e ?? "").replace(/"/g, "&quot;").replace(/</g, "&lt;"), K = "image/png,image/jpeg,image/webp", te = 5, q = {
2618
+ }, J = (e) => String(e ?? "").replace(/"/g, "&quot;").replace(/</g, "&lt;"), Y = "image/png,image/jpeg,image/webp", oe = 5, se = {
2525
2619
  "image/png": [".png"],
2526
2620
  "image/jpeg": [".jpg", ".jpeg"],
2527
2621
  "image/webp": [".webp"],
2528
2622
  "image/gif": [".gif"],
2529
2623
  "image/svg+xml": [".svg"],
2530
2624
  "application/pdf": [".pdf"]
2531
- }, J = {
2625
+ }, ce = {
2532
2626
  "image/png": "PNG",
2533
2627
  "image/jpeg": "JPG",
2534
2628
  "image/webp": "WEBP",
@@ -2542,34 +2636,34 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
2542
2636
  ".gif": "GIF",
2543
2637
  ".svg": "SVG",
2544
2638
  ".pdf": "PDF"
2545
- }, Y = (e) => String(e || "").split(",").map((e) => e.trim().toLowerCase()).filter(Boolean);
2546
- function X(e) {
2639
+ }, X = (e) => String(e || "").split(",").map((e) => e.trim().toLowerCase()).filter(Boolean);
2640
+ function Z(e) {
2547
2641
  let t = [];
2548
- for (let n of Y(e)) {
2549
- let e = J[n] || (n.startsWith(".") ? n.slice(1).toUpperCase() : n.toUpperCase());
2642
+ for (let n of X(e)) {
2643
+ let e = ce[n] || (n.startsWith(".") ? n.slice(1).toUpperCase() : n.toUpperCase());
2550
2644
  t.includes(e) || t.push(e);
2551
2645
  }
2552
2646
  return t.length <= 1 ? t[0] || "supported" : `${t.slice(0, -1).join(", ")} or ${t[t.length - 1]}`;
2553
2647
  }
2554
- function Z(e, t) {
2555
- let n = Y(t);
2648
+ function Q(e, t) {
2649
+ let n = X(t);
2556
2650
  if (!n.length) return !0;
2557
2651
  let r = (e.type || "").toLowerCase(), i = (e.name || "").toLowerCase();
2558
- return n.some((e) => e.startsWith(".") ? i.endsWith(e) : e.endsWith("/*") ? r.startsWith(e.slice(0, -1)) : r && r === e ? !0 : !r && (q[e] || []).some((e) => i.endsWith(e)));
2652
+ return n.some((e) => e.startsWith(".") ? i.endsWith(e) : e.endsWith("/*") ? r.startsWith(e.slice(0, -1)) : r && r === e ? !0 : !r && (se[e] || []).some((e) => i.endsWith(e)));
2559
2653
  }
2560
- function ne(e, t = {}) {
2654
+ function le(e, t = {}) {
2561
2655
  if (!e) return null;
2562
- let n = t.accept === void 0 ? K : t.accept, r = t.maxSizeMb || 5;
2563
- return Z(e, n) ? e.size > r * 1024 * 1024 ? `Keep the file under ${r} MB.` : null : `Choose a ${X(n)} file.`;
2656
+ let n = t.accept === void 0 ? Y : t.accept, r = t.maxSizeMb || 5;
2657
+ return Q(e, n) ? e.size > r * 1024 * 1024 ? `Keep the file under ${r} MB.` : null : `Choose a ${Z(n)} file.`;
2564
2658
  }
2565
2659
  //#endregion
2566
2660
  //#region src/index.js
2567
- var Q = (e, t) => {
2661
+ var $ = (e, t) => {
2568
2662
  typeof customElements < "u" && !customElements.get(e) && customElements.define(e, t);
2569
2663
  };
2570
- function $() {
2571
- Q("wui-select", W), Q("wui-phone", H), Q("wui-datepicker", w), Q("wui-date-range", N), Q("wui-autocomplete", p), Q("wui-multiselect", P), Q("wui-otp", R), Q("wui-status-icon", n);
2664
+ function ue() {
2665
+ $("wui-select", q), $("wui-phone", G), $("wui-datepicker", w), $("wui-date-range", M), $("wui-autocomplete", p), $("wui-multiselect", N), $("wui-otp", F), $("wui-status-icon", n);
2572
2666
  }
2573
- $();
2667
+ ue();
2574
2668
  //#endregion
2575
- export { K as DEFAULT_IMAGE_ACCEPT, te as DEFAULT_MAX_SIZE_MB, t as STATUS_TONES, p as WuiAutocomplete, w as WuiDatePicker, N as WuiDateRange, P as WuiMultiSelect, R as WuiOtp, H as WuiPhone, W as WuiSelect, n as WuiStatusIcon, X as acceptLabel, $ as defineWeborityElements, Z as matchesAccept, ne as validateFile };
2669
+ export { Y as DEFAULT_IMAGE_ACCEPT, oe as DEFAULT_MAX_SIZE_MB, t as STATUS_TONES, p as WuiAutocomplete, w as WuiDatePicker, M as WuiDateRange, N as WuiMultiSelect, F as WuiOtp, G as WuiPhone, q as WuiSelect, n as WuiStatusIcon, Z as acceptLabel, ue as defineWeborityElements, Q as matchesAccept, le as validateFile };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/ui-elements",
3
- "version": "0.6.12",
3
+ "version": "0.7.0",
4
4
  "description": "Webority framework-agnostic UI custom elements (<wui-*>) — the single implementation of the interactive components, styled by @webority/theme. Used natively in Razor and wrapped by @webority/ui-react.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -26,10 +26,19 @@
26
26
  "sideEffects": [
27
27
  "./dist/*"
28
28
  ],
29
+ "dependencies": {
30
+ "libphonenumber-js": "^1.13.9"
31
+ },
29
32
  "devDependencies": {
30
- "vite": "^8.0.12"
33
+ "@vitest/coverage-v8": "^3.2.4",
34
+ "jsdom": "^26.0.0",
35
+ "vite": "^8.0.12",
36
+ "vitest": "^3.2.4"
31
37
  },
32
38
  "scripts": {
33
- "build": "vite build && node ../../scripts/sync-rcl-assets.mjs elements"
39
+ "build": "vite build && node ../../scripts/sync-rcl-assets.mjs elements",
40
+ "test": "vitest run",
41
+ "test:watch": "vitest",
42
+ "test:coverage": "vitest run --coverage"
34
43
  }
35
44
  }