@wrrdev/fenix-ui 1.1.10 → 1.1.11

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.
Files changed (35) hide show
  1. package/README.md +20 -2
  2. package/dist/assets/{font-CF0TXsAP.js → font-DPeWTz-n.js} +58 -13
  3. package/dist/assets/font-DPeWTz-n.js.map +1 -0
  4. package/dist/components/breadcrumb/breadcrumb.d.ts +4 -0
  5. package/dist/components/breadcrumb/breadcrumb.d.ts.map +1 -1
  6. package/dist/components/breadcrumb/breadcrumb.js +12 -2
  7. package/dist/components/breadcrumb/breadcrumb.js.map +1 -1
  8. package/dist/components/table/table.d.ts +16 -0
  9. package/dist/components/table/table.d.ts.map +1 -1
  10. package/dist/components/table/table.js +28 -1
  11. package/dist/components/table/table.js.map +1 -1
  12. package/dist/components/toast/toast.d.ts +8 -0
  13. package/dist/components/toast/toast.d.ts.map +1 -1
  14. package/dist/components/toast/toast.js +13 -0
  15. package/dist/components/toast/toast.js.map +1 -1
  16. package/dist/components/tooltip/directive.d.ts +8 -0
  17. package/dist/components/tooltip/directive.d.ts.map +1 -1
  18. package/dist/components/tooltip/directive.js +59 -18
  19. package/dist/components/tooltip/directive.js.map +1 -1
  20. package/dist/docs/app.d.ts.map +1 -1
  21. package/dist/fenix-ui.umd.min.js +142 -142
  22. package/dist/fenix-ui3.esm.js +8 -13
  23. package/dist/fenix-ui3.esm.js.map +1 -1
  24. package/dist/fenix-ui4.esm.js +184 -93
  25. package/dist/fenix-ui4.esm.js.map +1 -1
  26. package/dist/icons/font.d.ts +23 -0
  27. package/dist/icons/font.d.ts.map +1 -1
  28. package/dist/icons/font.js +54 -8
  29. package/dist/icons/font.js.map +1 -1
  30. package/dist/icons/index.d.ts +7 -2
  31. package/dist/icons/index.d.ts.map +1 -1
  32. package/dist/icons/index.js +6 -11
  33. package/dist/icons/index.js.map +1 -1
  34. package/package.json +1 -1
  35. package/dist/assets/font-CF0TXsAP.js.map +0 -1
@@ -5,8 +5,8 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
5
5
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
6
6
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
7
7
  var _FxToast_instances, syncProgress_fn, render_fn;
8
- import { a as FENIX_ICON_BASE_CSS, f as fenixIconHtml, e as esc, l as loadFenixIconsFont, i as isFenixIconName } from "./assets/font-CF0TXsAP.js";
9
- import { s, g } from "./assets/font-CF0TXsAP.js";
8
+ import { a as FENIX_ICON_BASE_CSS, f as fenixIconHtml, g as esc, l as loadFenixIconsFont, i as isFenixIconName } from "./assets/font-DPeWTz-n.js";
9
+ import { h, j } from "./assets/font-DPeWTz-n.js";
10
10
  const lightTokens = {
11
11
  color: {
12
12
  primary: "#c2410c",
@@ -353,8 +353,8 @@ const _FxButton = class _FxButton extends FxElement {
353
353
  }
354
354
  /** Tamanho. Padrão: `'md'`. */
355
355
  get size() {
356
- const s2 = this.getAttr("size", "md");
357
- return s2 === "sm" || s2 === "lg" ? s2 : "md";
356
+ const s = this.getAttr("size", "md");
357
+ return s === "sm" || s === "lg" ? s : "md";
358
358
  }
359
359
  set size(value) {
360
360
  this.setAttribute("size", value);
@@ -582,8 +582,8 @@ const _FxSpinner = class _FxSpinner extends FxElement {
582
582
  }
583
583
  /** Tamanho do spinner. Padrão: `'md'`. */
584
584
  get size() {
585
- const s2 = this.getAttr("size", "md");
586
- return s2 === "sm" || s2 === "lg" ? s2 : "md";
585
+ const s = this.getAttr("size", "md");
586
+ return s === "sm" || s === "lg" ? s : "md";
587
587
  }
588
588
  set size(value) {
589
589
  this.setAttribute("size", value);
@@ -627,8 +627,8 @@ const _FxSelect = class _FxSelect extends FxElement {
627
627
  }
628
628
  /** Tamanho do campo. Padrão: `'md'`. */
629
629
  get size() {
630
- const s2 = this.getAttr("size", "md");
631
- return s2 === "sm" || s2 === "lg" ? s2 : "md";
630
+ const s = this.getAttr("size", "md");
631
+ return s === "sm" || s === "lg" ? s : "md";
632
632
  }
633
633
  set size(value) {
634
634
  this.setAttribute("size", value);
@@ -971,8 +971,8 @@ const _FxInput = class _FxInput extends FxElement {
971
971
  }
972
972
  /** Tamanho do campo. Padrão: `'md'`. */
973
973
  get size() {
974
- const s2 = this.getAttr("size", "md");
975
- return s2 === "sm" || s2 === "lg" ? s2 : "md";
974
+ const s = this.getAttr("size", "md");
975
+ return s === "sm" || s === "lg" ? s : "md";
976
976
  }
977
977
  set size(value) {
978
978
  this.setAttribute("size", value);
@@ -1195,8 +1195,8 @@ const _FxSwitch = class _FxSwitch extends FxElement {
1195
1195
  }
1196
1196
  /** Tamanho da trilha. Padrão: `'md'`. */
1197
1197
  get size() {
1198
- const s2 = this.getAttr("size", "md");
1199
- return s2 === "sm" || s2 === "lg" ? s2 : "md";
1198
+ const s = this.getAttr("size", "md");
1199
+ return s === "sm" || s === "lg" ? s : "md";
1200
1200
  }
1201
1201
  set size(value) {
1202
1202
  this.setAttribute("size", value);
@@ -1838,13 +1838,13 @@ const _FxCalendar = class _FxCalendar extends FxElement {
1838
1838
  this.values.map((iso) => parseBound(iso)?.lo ?? 0).filter(Boolean)
1839
1839
  );
1840
1840
  if (this.mode === "range") {
1841
- let s2 = this.pickStart;
1841
+ let s = this.pickStart;
1842
1842
  let e = this.pickEnd;
1843
1843
  const attrS = parseBound(this.getAttr("start", ""));
1844
1844
  const attrE = parseBound(this.getAttr("end", ""));
1845
- if (s2 === null && attrS) s2 = attrS.lo;
1845
+ if (s === null && attrS) s = attrS.lo;
1846
1846
  if (e === null && attrE) e = attrE.lo;
1847
- return { start: s2, end: e, single: null, multi };
1847
+ return { start: s, end: e, single: null, multi };
1848
1848
  }
1849
1849
  if (this.mode === "multiple") {
1850
1850
  return { start: null, end: null, single: null, multi };
@@ -2220,15 +2220,15 @@ const _FxDatepicker = class _FxDatepicker extends FxElement {
2220
2220
  /** Texto exibido no input conforme o modo. */
2221
2221
  displayText() {
2222
2222
  if (this.mode === "range") {
2223
- const s2 = this.getAttr("start");
2223
+ const s = this.getAttr("start");
2224
2224
  const e = this.getAttr("end");
2225
2225
  this.hasAttr("show-time") ? " " : " → ";
2226
- if (!s2 && !e) return "";
2226
+ if (!s && !e) return "";
2227
2227
  if (this.hasAttr("show-time")) {
2228
2228
  const f = (iso) => iso ? `${this.formatDate(iso)} ${this.timeText()}` : iso ? `${this.formatDate(iso)} …` : "";
2229
- return s2 && e ? `${f(s2)} → ${f(e)}` : f(s2);
2229
+ return s && e ? `${f(s)} → ${f(e)}` : f(s);
2230
2230
  }
2231
- return s2 && e ? `${this.formatDate(s2)} → ${this.formatDate(e)}` : s2 ? `${this.formatDate(s2)} → …` : "";
2231
+ return s && e ? `${this.formatDate(s)} → ${this.formatDate(e)}` : s ? `${this.formatDate(s)} → …` : "";
2232
2232
  }
2233
2233
  if (this.mode === "multiple") {
2234
2234
  return this.values.map((v) => this.formatDate(v)).join(", ");
@@ -2246,8 +2246,8 @@ const _FxDatepicker = class _FxDatepicker extends FxElement {
2246
2246
  const src = this.value || this.getAttr("start") || "";
2247
2247
  const t = src.split("T")[1];
2248
2248
  if (!t) return;
2249
- const [h, m, s2] = t.split(":").map((n) => parseInt(n, 10));
2250
- this.time = { h: h || 0, m: m || 0, s: s2 || 0 };
2249
+ const [h2, m, s] = t.split(":").map((n) => parseInt(n, 10));
2250
+ this.time = { h: h2 || 0, m: m || 0, s: s || 0 };
2251
2251
  }
2252
2252
  /** Anexa o horário interno ao ISO puro vindo do calendário. */
2253
2253
  withTime(iso) {
@@ -2353,14 +2353,14 @@ const _FxDatepicker = class _FxDatepicker extends FxElement {
2353
2353
  }
2354
2354
  if (showTime) {
2355
2355
  const applyTime = () => {
2356
- const h = this.root.querySelector(".t-h");
2356
+ const h2 = this.root.querySelector(".t-h");
2357
2357
  const m = this.root.querySelector(".t-m");
2358
- const s2 = this.root.querySelector(".t-s");
2358
+ const s = this.root.querySelector(".t-s");
2359
2359
  const clamp = (v, max) => Math.min(max, Math.max(0, parseInt(v ?? "0", 10) || 0));
2360
2360
  this.time = {
2361
- h: clamp(h?.value, 23),
2361
+ h: clamp(h2?.value, 23),
2362
2362
  m: clamp(m?.value, 59),
2363
- s: clamp(s2?.value, 59)
2363
+ s: clamp(s?.value, 59)
2364
2364
  };
2365
2365
  const reattach = (iso) => iso.split("T")[0] ? `${iso.split("T")[0]}T${this.timeText()}` : iso;
2366
2366
  if (this.value) this.setAttribute("value", reattach(this.value));
@@ -2626,8 +2626,8 @@ const _FxCheckbox = class _FxCheckbox extends FxElement {
2626
2626
  }
2627
2627
  /** Tamanho do controle. Padrão: `'md'`. */
2628
2628
  get size() {
2629
- const s2 = this.getAttr("size", "md");
2630
- return s2 === "sm" || s2 === "lg" ? s2 : "md";
2629
+ const s = this.getAttr("size", "md");
2630
+ return s === "sm" || s === "lg" ? s : "md";
2631
2631
  }
2632
2632
  set size(value) {
2633
2633
  this.setAttribute("size", value);
@@ -2755,8 +2755,8 @@ const _FxRadio = class _FxRadio extends FxElement {
2755
2755
  }
2756
2756
  /** Tamanho do controle. Padrão: `'md'`. */
2757
2757
  get size() {
2758
- const s2 = this.getAttr("size", "md");
2759
- return s2 === "sm" || s2 === "lg" ? s2 : "md";
2758
+ const s = this.getAttr("size", "md");
2759
+ return s === "sm" || s === "lg" ? s : "md";
2760
2760
  }
2761
2761
  set size(value) {
2762
2762
  this.setAttribute("size", value);
@@ -3294,6 +3294,7 @@ const _FxTable = class _FxTable extends FxElement {
3294
3294
  this.sortDir = 1;
3295
3295
  this.filters = {};
3296
3296
  this.globalSearch = "";
3297
+ this._shellKey = "";
3297
3298
  }
3298
3299
  static get observedAttributes() {
3299
3300
  return [
@@ -3488,7 +3489,7 @@ const _FxTable = class _FxTable extends FxElement {
3488
3489
  if (!input) return [];
3489
3490
  const attr = input.getAttribute("data-search-fields");
3490
3491
  if (attr === null) return [];
3491
- return attr.split(",").map((s2) => s2.trim()).filter(Boolean);
3492
+ return attr.split(",").map((s) => s.trim()).filter(Boolean);
3492
3493
  }
3493
3494
  cellHtml(col, row) {
3494
3495
  const template = col.template?.innerHTML ?? col.directTemplate;
@@ -3530,6 +3531,23 @@ const _FxTable = class _FxTable extends FxElement {
3530
3531
  </div>`;
3531
3532
  const loading = this.hasAttr("loading");
3532
3533
  const loadingHtml = loading ? `<div class="loading-overlay" part="loading-overlay"><div class="tbl-spinner" part="spinner"></div><span class="loading-text">${esc(this.getAttr("loading-message", "Carregando…"))}</span></div>` : "";
3534
+ const shellKey = [
3535
+ toolbarHtml,
3536
+ headHtml,
3537
+ filterRow,
3538
+ pagerHtml,
3539
+ loadingHtml,
3540
+ cols.length
3541
+ ].join("|");
3542
+ if (shellKey === this._shellKey) {
3543
+ const tbody = this.root.querySelector("tbody");
3544
+ if (tbody) {
3545
+ tbody.innerHTML = bodyHtml;
3546
+ this._bindRowClicks(rows);
3547
+ return;
3548
+ }
3549
+ }
3550
+ this._shellKey = shellKey;
3533
3551
  this.setTemplate(`
3534
3552
  ${toolbarHtml}
3535
3553
  <div class="table-wrap">
@@ -3633,6 +3651,16 @@ const _FxTable = class _FxTable extends FxElement {
3633
3651
  this.page = 0;
3634
3652
  this.render();
3635
3653
  });
3654
+ this._bindRowClicks(rows);
3655
+ this._restoreToolbarSearch();
3656
+ }
3657
+ /**
3658
+ * Liga o clique das linhas ao evento `row-click`.
3659
+ *
3660
+ * Extraído do render para ser reaproveitado no caminho rápido (troca só do
3661
+ * <tbody>): os <tr> são novos, então precisam ser rebound.
3662
+ */
3663
+ _bindRowClicks(rows) {
3636
3664
  this.root.querySelectorAll("tbody tr[data-index]").forEach((tr) => {
3637
3665
  tr.addEventListener("click", () => {
3638
3666
  this.dispatchEvent(
@@ -3647,7 +3675,6 @@ const _FxTable = class _FxTable extends FxElement {
3647
3675
  );
3648
3676
  });
3649
3677
  });
3650
- this._restoreToolbarSearch();
3651
3678
  }
3652
3679
  _restoreToolbarSearch() {
3653
3680
  const input = this.root.querySelector(
@@ -4202,8 +4229,8 @@ const _FxTextarea = class _FxTextarea extends FxElement {
4202
4229
  return ["size", "placeholder", "disabled", "readonly", "rows", "maxlength", "error", "invalid", "success", "valid"];
4203
4230
  }
4204
4231
  get size() {
4205
- const s2 = this.getAttr("size", "md");
4206
- return s2 === "sm" || s2 === "lg" ? s2 : "md";
4232
+ const s = this.getAttr("size", "md");
4233
+ return s === "sm" || s === "lg" ? s : "md";
4207
4234
  }
4208
4235
  set size(value) {
4209
4236
  this.setAttribute("size", value);
@@ -4796,8 +4823,8 @@ const _FxFileUpload = class _FxFileUpload extends FxElement {
4796
4823
  return ["mode", "size", "severity", "label", "icon", "accept", "multiple", "disabled", "show-progress", "progress", "value", "full"];
4797
4824
  }
4798
4825
  get size() {
4799
- const s2 = this.getAttr("size", "md");
4800
- return s2 === "sm" || s2 === "lg" ? s2 : "md";
4826
+ const s = this.getAttr("size", "md");
4827
+ return s === "sm" || s === "lg" ? s : "md";
4801
4828
  }
4802
4829
  set size(value) {
4803
4830
  this.setAttribute("size", value);
@@ -5721,26 +5748,36 @@ const _FxBreadcrumb = class _FxBreadcrumb extends FxElement {
5721
5748
  item.setAttribute("aria-current", isLast ? "page" : "false");
5722
5749
  nav.appendChild(item);
5723
5750
  if (isLast) return;
5724
- const s2 = document.createElement("span");
5725
- s2.className = "sep";
5726
- s2.setAttribute("part", "separator");
5727
- s2.setAttribute("aria-hidden", "true");
5728
- s2.textContent = sep;
5729
- nav.appendChild(s2);
5751
+ const s = document.createElement("span");
5752
+ s.className = "sep";
5753
+ s.setAttribute("part", "separator");
5754
+ s.setAttribute("aria-hidden", "true");
5755
+ s.textContent = sep;
5756
+ nav.appendChild(s);
5730
5757
  });
5731
5758
  }
5732
5759
  connectedCallback() {
5733
5760
  super.connectedCallback();
5734
5761
  const obs = new MutationObserver(() => {
5735
5762
  if (this.children.length > 0) {
5736
- obs.disconnect();
5763
+ this._stopObservingChildren();
5737
5764
  this._decorateItems();
5738
5765
  }
5739
5766
  });
5767
+ this._childObserver = obs;
5740
5768
  obs.observe(this, { childList: true });
5741
- if (this.children.length > 0) this._decorateItems();
5769
+ if (this.children.length > 0) {
5770
+ this._stopObservingChildren();
5771
+ this._decorateItems();
5772
+ }
5773
+ }
5774
+ /** Desconecta o observer de filhos (evita trabalho eterno após o connect). */
5775
+ _stopObservingChildren() {
5776
+ this._childObserver?.disconnect();
5777
+ this._childObserver = void 0;
5742
5778
  }
5743
5779
  disconnectedCallback() {
5780
+ this._stopObservingChildren();
5744
5781
  super.disconnectedCallback();
5745
5782
  this._items = [];
5746
5783
  }
@@ -6300,7 +6337,7 @@ const _FxMenu = class _FxMenu extends FxElement {
6300
6337
  }
6301
6338
  render() {
6302
6339
  const titleAttr = this.getAttr("titles");
6303
- const titles = titleAttr ? titleAttr.split(",").map((s2) => s2.trim()) : [];
6340
+ const titles = titleAttr ? titleAttr.split(",").map((s) => s.trim()) : [];
6304
6341
  const items = this.items;
6305
6342
  const itemsHtml = items.map((it, i) => {
6306
6343
  const label = titles[i] || it.textContent?.trim() || `Item ${i + 1}`;
@@ -6432,7 +6469,7 @@ const _FxToggleButtonGroup = class _FxToggleButtonGroup extends FxElement {
6432
6469
  }
6433
6470
  get value() {
6434
6471
  const raw = this.getAttr("value");
6435
- return raw ? raw.split(",").map((s2) => s2.trim()).filter(Boolean) : [];
6472
+ return raw ? raw.split(",").map((s) => s.trim()).filter(Boolean) : [];
6436
6473
  }
6437
6474
  set value(v) {
6438
6475
  this.setAttribute("value", v.join(","));
@@ -6863,7 +6900,7 @@ const _FxCarousel = class _FxCarousel extends FxElement {
6863
6900
  }
6864
6901
  render() {
6865
6902
  this._slides = Array.from(this.children).filter((el) => el.matches('[slot="slide"]'));
6866
- const contentsHtml = this._slides.map((s2, i) => `<div class="slide" part="slide" data-i="${i}" ${i === this.active ? "" : "hidden"}>${s2.innerHTML}</div>`).join("");
6903
+ const contentsHtml = this._slides.map((s, i) => `<div class="slide" part="slide" data-i="${i}" ${i === this.active ? "" : "hidden"}>${s.innerHTML}</div>`).join("");
6867
6904
  this.setTemplate(`
6868
6905
  <div class="viewport" part="viewport">
6869
6906
  ${contentsHtml}
@@ -6897,8 +6934,8 @@ const _FxCarousel = class _FxCarousel extends FxElement {
6897
6934
  }
6898
6935
  if (String(target) === this.getAttribute("active")) return;
6899
6936
  this.active = target;
6900
- this.root.querySelectorAll(".slide").forEach((s2) => {
6901
- s2.toggleAttribute("hidden", Number(s2.dataset.i) !== target);
6937
+ this.root.querySelectorAll(".slide").forEach((s) => {
6938
+ s.toggleAttribute("hidden", Number(s.dataset.i) !== target);
6902
6939
  });
6903
6940
  this.root.querySelectorAll(".dot").forEach((d) => {
6904
6941
  d.classList.toggle("on", Number(d.dataset.i) === target);
@@ -7153,6 +7190,7 @@ function defineFxTree() {
7153
7190
  return defineElement("fx-tree", FxTree);
7154
7191
  }
7155
7192
  defineFxTree();
7193
+ const REMOVED_EVENT = "fx-toast:removed";
7156
7194
  const KIND_COLOR = {
7157
7195
  success: "var(--fx-color-success, #10b981)",
7158
7196
  error: "var(--fx-color-danger, #f43f5e)",
@@ -7343,9 +7381,18 @@ class FxToast extends HTMLElement {
7343
7381
  }
7344
7382
  __privateMethod(this, _FxToast_instances, syncProgress_fn).call(this);
7345
7383
  }
7384
+ /**
7385
+ * Limpa recursos ao sair do DOM e avisa a API imperativa (`FenixToast`).
7386
+ *
7387
+ * O aviso é essencial: `dismiss()` (timer ou botão de fechar) tira o
7388
+ * elemento do DOM mas, sem isto, `ToastApi.map` continuaria segurando uma
7389
+ * referência forte para cada toast já dispensado — crescimento de memória
7390
+ * sem limite em uso prolongado.
7391
+ */
7346
7392
  disconnectedCallback() {
7347
7393
  if (this.timer) clearTimeout(this.timer);
7348
7394
  this.timer = null;
7395
+ this.dispatchEvent(new CustomEvent(REMOVED_EVENT, { bubbles: false, composed: false }));
7349
7396
  }
7350
7397
  attributeChangedCallback(name) {
7351
7398
  if (name === "duration" || name === "progress" || name === "progress-origin" || name === "kind") {
@@ -7467,6 +7514,9 @@ class ToastApi {
7467
7514
  if (o.progress) el.setAttribute("progress", o.progress);
7468
7515
  if (o.progressOrigin) el.setAttribute("progress-origin", o.progressOrigin);
7469
7516
  regionFor(o.position ?? "top-right").appendChild(el);
7517
+ el.addEventListener(REMOVED_EVENT, () => {
7518
+ if (this.map.get(id) === el) this.map.delete(id);
7519
+ });
7470
7520
  this.map.set(id, el);
7471
7521
  return id;
7472
7522
  }
@@ -7651,6 +7701,8 @@ const _FxTooltipManager = class _FxTooltipManager {
7651
7701
  this.observer = null;
7652
7702
  this.behaviors = /* @__PURE__ */ new Map();
7653
7703
  this.injectedStyles = null;
7704
+ this._pending = { added: [] };
7705
+ this._flushScheduled = false;
7654
7706
  this.injectStyles();
7655
7707
  this.observe();
7656
7708
  this.processExistingElements();
@@ -7661,6 +7713,20 @@ const _FxTooltipManager = class _FxTooltipManager {
7661
7713
  }
7662
7714
  return _FxTooltipManager.instance;
7663
7715
  }
7716
+ /** Quantos tooltips estão ativos agora (0 se a diretiva nunca foi iniciada). */
7717
+ static peekActiveCount() {
7718
+ return _FxTooltipManager.instance?.behaviors.size ?? 0;
7719
+ }
7720
+ /**
7721
+ * Quantos tooltips estão ativamente gerenciados.
7722
+ *
7723
+ * Deve acompanhar o número de elementos `[fx-tooltip]` no documento: um
7724
+ * valor crescente depois de trocar de tela significa comportamento retido
7725
+ * (vazamento). Usado nos testes de regressão e no diagnóstico em produção.
7726
+ */
7727
+ get activeCount() {
7728
+ return this.behaviors.size;
7729
+ }
7664
7730
  injectStyles() {
7665
7731
  if (document.getElementById("fx-tooltip-directive-styles")) return;
7666
7732
  this.injectedStyles = document.createElement("style");
@@ -7670,32 +7736,55 @@ const _FxTooltipManager = class _FxTooltipManager {
7670
7736
  }
7671
7737
  observe() {
7672
7738
  this.observer = new MutationObserver((mutations) => {
7673
- for (const mutation of mutations) {
7674
- if (mutation.type === "childList") {
7675
- mutation.addedNodes.forEach((node) => {
7676
- if (node instanceof HTMLElement) {
7677
- this.processElement(node);
7678
- node.querySelectorAll("[fx-tooltip]").forEach((el) => this.processElement(el));
7679
- }
7680
- });
7681
- }
7682
- if (mutation.type === "attributes" && mutation.target instanceof HTMLElement) {
7683
- const target = mutation.target;
7684
- if (target.hasAttribute("fx-tooltip")) {
7685
- this.processElement(target);
7686
- } else if (this.behaviors.has(target)) {
7687
- this.removeBehavior(target);
7688
- }
7689
- }
7690
- }
7739
+ this._pending.added.push(...mutations);
7740
+ if (this._flushScheduled) return;
7741
+ this._flushScheduled = true;
7742
+ const run = () => {
7743
+ this._flushScheduled = false;
7744
+ const batch = this._pending;
7745
+ this._pending = { added: [] };
7746
+ this._flush(batch.added);
7747
+ };
7748
+ if (typeof requestAnimationFrame === "function") requestAnimationFrame(run);
7749
+ else setTimeout(run, 0);
7691
7750
  });
7692
7751
  this.observer.observe(document.body, {
7693
7752
  childList: true,
7694
7753
  subtree: true,
7695
7754
  attributes: true,
7755
+ // `attributeFilter` é o que mantém o custo baixo: o browser só notifica
7756
+ // mudanças nestes 3 atributos, e não em qualquer atributo da página.
7696
7757
  attributeFilter: ["fx-tooltip", "fx-tooltip-position", "fx-tooltip-html"]
7697
7758
  });
7698
7759
  }
7760
+ /** Um passe de verificação sobre todos os registros acumulados. */
7761
+ _flush(records) {
7762
+ const toProcess = /* @__PURE__ */ new Set();
7763
+ const toRemove = /* @__PURE__ */ new Set();
7764
+ for (const mutation of records) {
7765
+ if (mutation.type === "childList") {
7766
+ mutation.addedNodes.forEach((node) => {
7767
+ if (node instanceof HTMLElement) {
7768
+ toProcess.add(node);
7769
+ node.querySelectorAll("[fx-tooltip]").forEach((el) => toProcess.add(el));
7770
+ }
7771
+ });
7772
+ mutation.removedNodes.forEach((node) => {
7773
+ if (node instanceof HTMLElement) {
7774
+ toRemove.add(node);
7775
+ node.querySelectorAll("[fx-tooltip]").forEach((el) => toRemove.add(el));
7776
+ }
7777
+ });
7778
+ }
7779
+ if (mutation.type === "attributes" && mutation.target instanceof HTMLElement) {
7780
+ const target = mutation.target;
7781
+ if (target.hasAttribute("fx-tooltip")) toProcess.add(target);
7782
+ else toRemove.add(target);
7783
+ }
7784
+ }
7785
+ toRemove.forEach((el) => this.removeBehavior(el));
7786
+ toProcess.forEach((el) => this.processElement(el));
7787
+ }
7699
7788
  processExistingElements() {
7700
7789
  document.querySelectorAll("[fx-tooltip]").forEach((el) => this.processElement(el));
7701
7790
  }
@@ -7718,6 +7807,8 @@ const _FxTooltipManager = class _FxTooltipManager {
7718
7807
  }
7719
7808
  }
7720
7809
  destroy() {
7810
+ this._pending.added = [];
7811
+ this._flushScheduled = false;
7721
7812
  if (this.observer) {
7722
7813
  this.observer.disconnect();
7723
7814
  this.observer = null;
@@ -8122,8 +8213,8 @@ const _FxSkeleton = class _FxSkeleton extends FxElement {
8122
8213
  return;
8123
8214
  }
8124
8215
  if (variant === "rect") {
8125
- const s2 = style || "width:100%;height:80px;";
8126
- this.setTemplate(`<div class="bone" part="bone" style="${s2}"></div>`);
8216
+ const s = style || "width:100%;height:80px;";
8217
+ this.setTemplate(`<div class="bone" part="bone" style="${s}"></div>`);
8127
8218
  return;
8128
8219
  }
8129
8220
  const lines = Number(this.getAttr("lines", "3")) || 3;
@@ -8638,7 +8729,7 @@ const _FxPagination = class _FxPagination extends FxElement {
8638
8729
  render() {
8639
8730
  const pages = this.pages;
8640
8731
  const current = Math.min(Math.max(1, this.page), pages);
8641
- const opts = (this.getAttr("rows-options", "5,10,20,50") || "").split(",").map((s2) => s2.trim()).filter(Boolean);
8732
+ const opts = (this.getAttr("rows-options", "5,10,20,50") || "").split(",").map((s) => s.trim()).filter(Boolean);
8642
8733
  const window_ = [];
8643
8734
  for (let p = Math.max(1, current - 2); p <= Math.min(pages, current + 2); p++) window_.push(p);
8644
8735
  const from = total0(current, this.rows);
@@ -8748,8 +8839,8 @@ const _FxAutocomplete = class _FxAutocomplete extends FxElement {
8748
8839
  return ["size", "placeholder", "source", "disabled", "min-chars", "error", "invalid", "success", "valid"];
8749
8840
  }
8750
8841
  get size() {
8751
- const s2 = this.getAttr("size", "md");
8752
- return s2 === "sm" || s2 === "lg" ? s2 : "md";
8842
+ const s = this.getAttr("size", "md");
8843
+ return s === "sm" || s === "lg" ? s : "md";
8753
8844
  }
8754
8845
  set size(v) {
8755
8846
  this.setAttribute("size", v);
@@ -8801,7 +8892,7 @@ const _FxAutocomplete = class _FxAutocomplete extends FxElement {
8801
8892
  const openList = () => {
8802
8893
  if (!list) return;
8803
8894
  const q = field.value.toLowerCase();
8804
- const matches = this.source.filter((s2) => s2.toLowerCase().includes(q)).slice(0, 8);
8895
+ const matches = this.source.filter((s) => s.toLowerCase().includes(q)).slice(0, 8);
8805
8896
  list.innerHTML = matches.length ? matches.map((m) => `<button type="button" class="opt" role="option" data-v="${esc(m)}">${esc(m)}</button>`).join("") : '<div class="empty">Nenhum resultado</div>';
8806
8897
  list.querySelectorAll(".opt").forEach((btn) => {
8807
8898
  btn.addEventListener("click", () => {
@@ -9001,8 +9092,8 @@ const _FxKnob = class _FxKnob extends FxElement {
9001
9092
  this.setAttribute("step", String(v));
9002
9093
  }
9003
9094
  get size() {
9004
- const s2 = this.getAttr("size", "md");
9005
- return s2 === "sm" || s2 === "lg" ? s2 : "md";
9095
+ const s = this.getAttr("size", "md");
9096
+ return s === "sm" || s === "lg" ? s : "md";
9006
9097
  }
9007
9098
  set size(v) {
9008
9099
  this.setAttribute("size", v);
@@ -9078,9 +9169,9 @@ const _FxKnob = class _FxKnob extends FxElement {
9078
9169
  this.attachListeners();
9079
9170
  }
9080
9171
  getSizeNum() {
9081
- const s2 = this.size;
9082
- if (s2 === "sm") return 60;
9083
- if (s2 === "lg") return 140;
9172
+ const s = this.size;
9173
+ if (s === "sm") return 60;
9174
+ if (s === "lg") return 140;
9084
9175
  return 100;
9085
9176
  }
9086
9177
  /** Valida um valor de cor CSS, retornando-o seguro ou vazio. */
@@ -9344,8 +9435,8 @@ const _FxOrderList = class _FxOrderList extends FxElement {
9344
9435
  this.toggleAttr("striped", v);
9345
9436
  }
9346
9437
  get selectionMode() {
9347
- const s2 = this.getAttr("selection-mode", "");
9348
- return s2 === "single" || s2 === "multiple" ? s2 : "";
9438
+ const s = this.getAttr("selection-mode", "");
9439
+ return s === "single" || s === "multiple" ? s : "";
9349
9440
  }
9350
9441
  set selectionMode(v) {
9351
9442
  this.setAttribute("selection-mode", v);
@@ -9427,7 +9518,7 @@ const _FxOrderList = class _FxOrderList extends FxElement {
9427
9518
  return JSON.stringify(item);
9428
9519
  }
9429
9520
  _isSelected(item) {
9430
- return this._selection.some((s2) => this._getItemKey(s2, -1) === this._getItemKey(item, -1));
9521
+ return this._selection.some((s) => this._getItemKey(s, -1) === this._getItemKey(item, -1));
9431
9522
  }
9432
9523
  _moveItem(fromIndex, toIndex) {
9433
9524
  const actualFrom = this._getActualIndex(fromIndex);
@@ -9463,7 +9554,7 @@ const _FxOrderList = class _FxOrderList extends FxElement {
9463
9554
  }
9464
9555
  _toggleSelection(item) {
9465
9556
  const key2 = this._getItemKey(item, -1);
9466
- const index = this._selection.findIndex((s2) => this._getItemKey(s2, -1) === key2);
9557
+ const index = this._selection.findIndex((s) => this._getItemKey(s, -1) === key2);
9467
9558
  if (index >= 0) {
9468
9559
  this._selection.splice(index, 1);
9469
9560
  } else if (this.selectionMode === "multiple") {
@@ -9737,7 +9828,7 @@ const _FxOrderList = class _FxOrderList extends FxElement {
9737
9828
  _handleMoveAction(action) {
9738
9829
  if (!this._selection.length) return;
9739
9830
  const displayData = this._getDisplayData();
9740
- const selectedIndices = this._selection.map((s2) => displayData.findIndex((d) => this._getItemKey(d, -1) === this._getItemKey(s2, -1))).filter((i) => i >= 0).sort((a, b) => a - b);
9831
+ const selectedIndices = this._selection.map((s) => displayData.findIndex((d) => this._getItemKey(d, -1) === this._getItemKey(s, -1))).filter((i) => i >= 0).sort((a, b) => a - b);
9741
9832
  if (selectedIndices.length === 0) return;
9742
9833
  switch (action) {
9743
9834
  case "top":
@@ -9813,7 +9904,7 @@ const _FxOrderList = class _FxOrderList extends FxElement {
9813
9904
  }
9814
9905
  _updateControlsState() {
9815
9906
  const displayData = this._getDisplayData();
9816
- const selectedIndices = this._selection.map((s2) => displayData.findIndex((d) => this._getItemKey(d, -1) === this._getItemKey(s2, -1))).filter((i) => i >= 0);
9907
+ const selectedIndices = this._selection.map((s) => displayData.findIndex((d) => this._getItemKey(d, -1) === this._getItemKey(s, -1))).filter((i) => i >= 0);
9817
9908
  const buttons = this.root.querySelectorAll(".control-btn");
9818
9909
  buttons.forEach((btn) => {
9819
9910
  const action = btn.dataset.action;
@@ -10019,8 +10110,8 @@ const _FxPickList = class _FxPickList extends FxElement {
10019
10110
  this.toggleAttr("striped", v);
10020
10111
  }
10021
10112
  get selectionMode() {
10022
- const s2 = this.getAttr("selection-mode", "");
10023
- return s2 === "single" || s2 === "multiple" ? s2 : "";
10113
+ const s = this.getAttr("selection-mode", "");
10114
+ return s === "single" || s === "multiple" ? s : "";
10024
10115
  }
10025
10116
  set selectionMode(v) {
10026
10117
  this.setAttribute("selection-mode", v);
@@ -10155,10 +10246,10 @@ const _FxPickList = class _FxPickList extends FxElement {
10155
10246
  return JSON.stringify(item);
10156
10247
  }
10157
10248
  _isSourceSelected(item, index) {
10158
- return this._sourceSelection.some((s2) => this._getItemKey(s2, -1, true) === this._getItemKey(item, index, true));
10249
+ return this._sourceSelection.some((s) => this._getItemKey(s, -1, true) === this._getItemKey(item, index, true));
10159
10250
  }
10160
10251
  _isTargetSelected(item, index) {
10161
- return this._targetSelection.some((s2) => this._getItemKey(s2, -1, false) === this._getItemKey(item, index, false));
10252
+ return this._targetSelection.some((s) => this._getItemKey(s, -1, false) === this._getItemKey(item, index, false));
10162
10253
  }
10163
10254
  _emitMoveToTarget() {
10164
10255
  this.dispatchEvent(new CustomEvent("move-to-target", {
@@ -10301,7 +10392,7 @@ const _FxPickList = class _FxPickList extends FxElement {
10301
10392
  _moveToTarget() {
10302
10393
  if (!this._sourceSelection.length) return;
10303
10394
  const items = [...this._sourceSelection];
10304
- this._source = this._source.filter((s2) => !items.some((i) => this._getItemKey(i, -1, true) === this._getItemKey(s2, -1, true)));
10395
+ this._source = this._source.filter((s) => !items.some((i) => this._getItemKey(i, -1, true) === this._getItemKey(s, -1, true)));
10305
10396
  this._target = [...this._target, ...items];
10306
10397
  this._sourceSelection = [];
10307
10398
  this._filteredSource = null;
@@ -10347,7 +10438,7 @@ const _FxPickList = class _FxPickList extends FxElement {
10347
10438
  _toggleSourceSelection(item, index) {
10348
10439
  const mode = this.selectionMode || "single";
10349
10440
  const key2 = this._getItemKey(item, index, true);
10350
- const idx = this._sourceSelection.findIndex((s2) => this._getItemKey(s2, -1, true) === key2);
10441
+ const idx = this._sourceSelection.findIndex((s) => this._getItemKey(s, -1, true) === key2);
10351
10442
  if (idx >= 0) {
10352
10443
  this._sourceSelection.splice(idx, 1);
10353
10444
  } else if (mode === "multiple") {
@@ -10362,7 +10453,7 @@ const _FxPickList = class _FxPickList extends FxElement {
10362
10453
  _toggleTargetSelection(item, index) {
10363
10454
  const mode = this.selectionMode || "single";
10364
10455
  const key2 = this._getItemKey(item, index, false);
10365
- const idx = this._targetSelection.findIndex((s2) => this._getItemKey(s2, -1, false) === key2);
10456
+ const idx = this._targetSelection.findIndex((s) => this._getItemKey(s, -1, false) === key2);
10366
10457
  if (idx >= 0) {
10367
10458
  this._targetSelection.splice(idx, 1);
10368
10459
  } else if (mode === "multiple") {
@@ -10825,7 +10916,7 @@ const _FxAccordion = class _FxAccordion extends FxElement {
10825
10916
  }
10826
10917
  /** Valores ativos como array. */
10827
10918
  get values() {
10828
- return this.getAttr("value", "").split(",").map((s2) => s2.trim()).filter(Boolean);
10919
+ return this.getAttr("value", "").split(",").map((s) => s.trim()).filter(Boolean);
10829
10920
  }
10830
10921
  set values(v) {
10831
10922
  this.setAttribute("value", v.join(","));
@@ -11007,9 +11098,9 @@ export {
11007
11098
  lightTokens,
11008
11099
  listPresets,
11009
11100
  resetTheme,
11010
- s as sanitizeData,
11101
+ h as sanitizeData,
11011
11102
  setTokens,
11012
- g as stripTags,
11103
+ j as stripTags,
11013
11104
  theme,
11014
11105
  themePresets,
11015
11106
  tokenCssVars