@webority/ui-elements 0.7.0 → 0.7.2

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.
@@ -69,7 +69,8 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
69
69
  "debounce",
70
70
  "remote",
71
71
  "size",
72
- "aria-label"
72
+ "aria-label",
73
+ "allow-custom"
73
74
  ];
74
75
  }
75
76
  constructor() {
@@ -106,6 +107,13 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
106
107
  get _remote() {
107
108
  return this.hasAttribute("remote");
108
109
  }
110
+ get _allowCustom() {
111
+ return this.hasAttribute("allow-custom");
112
+ }
113
+ _matchesKnownOption(e) {
114
+ let t = e.toLowerCase();
115
+ return this._readOptions().some((e) => h(e.label).toLowerCase() === t || String(e.value ?? "").toLowerCase() === t);
116
+ }
109
117
  get _minChars() {
110
118
  return Math.max(0, Number(this.getAttribute("min-chars")) || +!!this._remote);
111
119
  }
@@ -172,13 +180,22 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
172
180
  _renderOptions(e) {
173
181
  let t = this._refs();
174
182
  if (!t.optionsWrap) return;
175
- let n = (e ?? (t.input ? t.input.value : "")).trim().toLowerCase(), r = this._readOptions();
176
- !this._remote && n && (r = r.filter((e) => h(e.label).toLowerCase().includes(n))), t.optionsWrap.innerHTML = r.map((e) => {
183
+ let n = e ?? (t.input ? t.input.value : ""), r = n.trim().toLowerCase(), i = this._readOptions();
184
+ !this._remote && r && (i = i.filter((e) => h(e.label).toLowerCase().includes(r)));
185
+ let a = n.trim(), o = this._allowCustom && a && !this._matchesKnownOption(a) ? [...i, {
186
+ value: a,
187
+ custom: !0
188
+ }] : i;
189
+ t.optionsWrap.innerHTML = o.map((e) => {
190
+ if (e.custom) {
191
+ let t = `Add “${u(e.value)}”`;
192
+ return `<button type="button" role="option" class="search-select-option search-select-option-custom" data-value="${m(e.value)}" data-custom="true" aria-selected="false">${t}</button>`;
193
+ }
177
194
  let t = String(e.value) === String(this._value);
178
195
  return `<button type="button" role="option" class="search-select-option${t ? " selected" : ""}" data-value="${m(e.value)}" aria-selected="${t}">${f(e)}</button>`;
179
196
  }).join(""), this._active = -1;
180
- let i = n.length < this._minChars;
181
- t.hint && (t.hint.hidden = !(this._remote && i && !r.length)), t.empty && (t.empty.hidden = this._loading || r.length > 0 || this._remote && i);
197
+ let s = r.length < this._minChars;
198
+ t.hint && (t.hint.hidden = !(this._remote && s && !i.length)), t.empty && (t.empty.hidden = this._loading || o.length > 0 || this._remote && s);
182
199
  }
183
200
  _wire() {
184
201
  let e = this._refs();
@@ -193,7 +210,16 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
193
210
  }, l = () => {
194
211
  e.menu.hidden = !0, e.control.setAttribute("aria-expanded", "false"), e.control.classList.remove("open"), r(-1), this._syncInput();
195
212
  }, u = (t) => {
196
- this._value = t.dataset.value, this._label = h(t.innerHTML), c(this, this._value), e.input.value = this._label, this.dispatchEvent(new Event("change", { bubbles: !0 })), l(), e.input.focus();
213
+ let n = t.dataset.custom === "true";
214
+ this._value = t.dataset.value, this._label = n ? t.dataset.value : h(t.innerHTML), c(this, this._value), e.input.value = this._label, this.dispatchEvent(new CustomEvent("change", {
215
+ bubbles: !0,
216
+ detail: { isCustom: n }
217
+ })), l(), e.input.focus();
218
+ }, d = (t) => {
219
+ this._value = t, this._label = t, c(this, t), e.input.value = t, this.dispatchEvent(new CustomEvent("change", {
220
+ bubbles: !0,
221
+ detail: { isCustom: !0 }
222
+ })), l();
197
223
  };
198
224
  e.input.addEventListener("focus", () => s()), e.input.addEventListener("input", () => {
199
225
  let t = e.input.value;
@@ -206,9 +232,21 @@ var l = Symbol("wui.trustedHtml"), u = (e) => String(e ?? "").replace(/&/g, "&am
206
232
  }));
207
233
  }, this._debounceMs);
208
234
  } else this._renderOptions(t);
209
- }), e.input.addEventListener("keydown", (e) => {
210
- let t = n();
211
- e.key === "ArrowDown" ? (e.preventDefault(), o() || s(), r(Math.min(this._active + 1, t.length - 1))) : e.key === "ArrowUp" ? (e.preventDefault(), r(Math.max(this._active - 1, 0))) : e.key === "Enter" ? t[this._active] && (e.preventDefault(), u(t[this._active])) : e.key === "Escape" && l();
235
+ }), e.input.addEventListener("keydown", (t) => {
236
+ let i = n();
237
+ if (t.key === "ArrowDown") t.preventDefault(), o() || s(), r(Math.min(this._active + 1, i.length - 1));
238
+ else if (t.key === "ArrowUp") t.preventDefault(), r(Math.max(this._active - 1, 0));
239
+ else if (t.key === "Enter") {
240
+ if (i[this._active]) t.preventDefault(), u(i[this._active]);
241
+ else if (this._allowCustom) {
242
+ let n = e.input.value.trim();
243
+ n && !this._matchesKnownOption(n) && (t.preventDefault(), d(n));
244
+ }
245
+ } else t.key === "Escape" && l();
246
+ }), e.input.addEventListener("blur", (t) => {
247
+ if (!this._allowCustom || t.relatedTarget && this.contains(t.relatedTarget)) return;
248
+ let n = e.input.value.trim();
249
+ !n || n === this._label || this._matchesKnownOption(n) || d(n);
212
250
  }), e.optionsWrap.addEventListener("click", (e) => {
213
251
  let t = e.target.closest(".search-select-option");
214
252
  t && u(t);
@@ -2636,8 +2674,29 @@ var G = class extends HTMLElement {
2636
2674
  ".gif": "GIF",
2637
2675
  ".svg": "SVG",
2638
2676
  ".pdf": "PDF"
2639
- }, X = (e) => String(e || "").split(",").map((e) => e.trim().toLowerCase()).filter(Boolean);
2640
- function Z(e) {
2677
+ }, X = (e) => String(e || "").split(",").map((e) => e.trim().toLowerCase()).filter(Boolean), Z = [
2678
+ ".png",
2679
+ ".jpg",
2680
+ ".jpeg",
2681
+ ".webp",
2682
+ ".gif",
2683
+ ".svg",
2684
+ ".bmp",
2685
+ ".avif",
2686
+ ".heic"
2687
+ ];
2688
+ function le(e) {
2689
+ if (!e) return !1;
2690
+ let t = typeof e == "object" && e.type ? String(e.type).toLowerCase() : "";
2691
+ if (t) return t.startsWith("image/");
2692
+ let n = typeof e == "string" ? e : e.name || e.url || "", r = String(n).toLowerCase();
2693
+ return Z.some((e) => r.endsWith(e));
2694
+ }
2695
+ function ue(e) {
2696
+ let t = X(e);
2697
+ return t.length ? t.every((e) => e.startsWith(".") ? Z.includes(e) : e === "image/*" || e.startsWith("image/")) : !1;
2698
+ }
2699
+ function Q(e) {
2641
2700
  let t = [];
2642
2701
  for (let n of X(e)) {
2643
2702
  let e = ce[n] || (n.startsWith(".") ? n.slice(1).toUpperCase() : n.toUpperCase());
@@ -2645,25 +2704,25 @@ function Z(e) {
2645
2704
  }
2646
2705
  return t.length <= 1 ? t[0] || "supported" : `${t.slice(0, -1).join(", ")} or ${t[t.length - 1]}`;
2647
2706
  }
2648
- function Q(e, t) {
2707
+ function de(e, t) {
2649
2708
  let n = X(t);
2650
2709
  if (!n.length) return !0;
2651
2710
  let r = (e.type || "").toLowerCase(), i = (e.name || "").toLowerCase();
2652
2711
  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)));
2653
2712
  }
2654
- function le(e, t = {}) {
2713
+ function fe(e, t = {}) {
2655
2714
  if (!e) return null;
2656
2715
  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.`;
2716
+ return de(e, n) ? e.size > r * 1024 * 1024 ? `Keep the file under ${r} MB.` : null : `Choose a ${Q(n)} file.`;
2658
2717
  }
2659
2718
  //#endregion
2660
2719
  //#region src/index.js
2661
2720
  var $ = (e, t) => {
2662
2721
  typeof customElements < "u" && !customElements.get(e) && customElements.define(e, t);
2663
2722
  };
2664
- function ue() {
2723
+ function pe() {
2665
2724
  $("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);
2666
2725
  }
2667
- ue();
2726
+ pe();
2668
2727
  //#endregion
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 };
2728
+ 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, Q as acceptLabel, pe as defineWeborityElements, le as isImageFile, ue as isImageOnlyAccept, de as matchesAccept, fe as validateFile };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/ui-elements",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
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",