@wrrdev/fenix-ui 1.0.5 → 1.0.7

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 (129) hide show
  1. package/README.md +314 -314
  2. package/dist/.nojekyll +0 -0
  3. package/dist/components/accordion/accordion.d.ts +72 -0
  4. package/dist/components/accordion/accordion.d.ts.map +1 -0
  5. package/dist/components/accordion/accordion.js +277 -0
  6. package/dist/components/accordion/accordion.js.map +1 -0
  7. package/dist/components/accordion/index.d.ts +2 -0
  8. package/dist/components/accordion/index.d.ts.map +1 -0
  9. package/dist/components/accordion/index.js +9 -0
  10. package/dist/components/accordion/index.js.map +1 -0
  11. package/dist/components/calendar/calendar.d.ts +2 -2
  12. package/dist/components/calendar/calendar.d.ts.map +1 -1
  13. package/dist/components/calendar/calendar.js +187 -89
  14. package/dist/components/calendar/calendar.js.map +1 -1
  15. package/dist/components/dropdown/dropdown.d.ts.map +1 -1
  16. package/dist/components/dropdown/dropdown.js +1 -1
  17. package/dist/components/dropdown/dropdown.js.map +1 -1
  18. package/dist/components/knob/index.d.ts +8 -0
  19. package/dist/components/knob/index.d.ts.map +1 -0
  20. package/dist/components/knob/index.js +7 -0
  21. package/dist/components/knob/index.js.map +1 -0
  22. package/dist/components/knob/knob.d.ts +51 -0
  23. package/dist/components/knob/knob.d.ts.map +1 -0
  24. package/dist/components/knob/knob.js +323 -0
  25. package/dist/components/knob/knob.js.map +1 -0
  26. package/dist/components/orderlist/index.d.ts +3 -0
  27. package/dist/components/orderlist/index.d.ts.map +1 -0
  28. package/dist/components/orderlist/index.js +7 -0
  29. package/dist/components/orderlist/index.js.map +1 -0
  30. package/dist/components/orderlist/orderlist.d.ts +78 -0
  31. package/dist/components/orderlist/orderlist.d.ts.map +1 -0
  32. package/dist/components/orderlist/orderlist.js +666 -0
  33. package/dist/components/orderlist/orderlist.js.map +1 -0
  34. package/dist/components/picklist/index.d.ts +3 -0
  35. package/dist/components/picklist/index.d.ts.map +1 -0
  36. package/dist/components/picklist/index.js +7 -0
  37. package/dist/components/picklist/index.js.map +1 -0
  38. package/dist/components/picklist/picklist.d.ts +102 -0
  39. package/dist/components/picklist/picklist.d.ts.map +1 -0
  40. package/dist/components/picklist/picklist.js +749 -0
  41. package/dist/components/picklist/picklist.js.map +1 -0
  42. package/dist/components/tooltip/directive.d.ts +31 -0
  43. package/dist/components/tooltip/directive.d.ts.map +1 -0
  44. package/dist/components/tooltip/directive.js +294 -0
  45. package/dist/components/tooltip/directive.js.map +1 -0
  46. package/dist/components/tooltip/index.d.ts +2 -1
  47. package/dist/components/tooltip/index.d.ts.map +1 -1
  48. package/dist/components/tooltip/index.js +4 -1
  49. package/dist/components/tooltip/index.js.map +1 -1
  50. package/dist/core/presets.d.ts.map +1 -1
  51. package/dist/core/presets.js +48 -9
  52. package/dist/core/presets.js.map +1 -1
  53. package/dist/core/tokens.d.ts.map +1 -1
  54. package/dist/core/tokens.js +4 -4
  55. package/dist/core/tokens.js.map +1 -1
  56. package/dist/docs/app.d.ts +3 -25
  57. package/dist/docs/app.d.ts.map +1 -1
  58. package/dist/docs/componentes/accordion.doc.d.ts +8 -0
  59. package/dist/docs/componentes/accordion.doc.d.ts.map +1 -0
  60. package/dist/docs/componentes/alert.doc.d.ts +8 -0
  61. package/dist/docs/componentes/alert.doc.d.ts.map +1 -0
  62. package/dist/docs/componentes/autocomplete.doc.d.ts +8 -0
  63. package/dist/docs/componentes/autocomplete.doc.d.ts.map +1 -0
  64. package/dist/docs/componentes/badge.doc.d.ts +8 -0
  65. package/dist/docs/componentes/badge.doc.d.ts.map +1 -0
  66. package/dist/docs/componentes/button.doc.d.ts +8 -0
  67. package/dist/docs/componentes/button.doc.d.ts.map +1 -0
  68. package/dist/docs/componentes/calendar.doc.d.ts +8 -0
  69. package/dist/docs/componentes/calendar.doc.d.ts.map +1 -0
  70. package/dist/docs/componentes/checkbox.doc.d.ts +8 -0
  71. package/dist/docs/componentes/checkbox.doc.d.ts.map +1 -0
  72. package/dist/docs/componentes/datepicker.doc.d.ts +8 -0
  73. package/dist/docs/componentes/datepicker.doc.d.ts.map +1 -0
  74. package/dist/docs/componentes/dialog.doc.d.ts +8 -0
  75. package/dist/docs/componentes/dialog.doc.d.ts.map +1 -0
  76. package/dist/docs/componentes/drawer.doc.d.ts +8 -0
  77. package/dist/docs/componentes/drawer.doc.d.ts.map +1 -0
  78. package/dist/docs/componentes/dropdown.doc.d.ts +8 -0
  79. package/dist/docs/componentes/dropdown.doc.d.ts.map +1 -0
  80. package/dist/docs/componentes/floatlabel.doc.d.ts +8 -0
  81. package/dist/docs/componentes/floatlabel.doc.d.ts.map +1 -0
  82. package/dist/docs/componentes/index.d.ts +10 -0
  83. package/dist/docs/componentes/index.d.ts.map +1 -0
  84. package/dist/docs/componentes/input.doc.d.ts +8 -0
  85. package/dist/docs/componentes/input.doc.d.ts.map +1 -0
  86. package/dist/docs/componentes/knob.doc.d.ts +8 -0
  87. package/dist/docs/componentes/knob.doc.d.ts.map +1 -0
  88. package/dist/docs/componentes/multiselect.doc.d.ts +8 -0
  89. package/dist/docs/componentes/multiselect.doc.d.ts.map +1 -0
  90. package/dist/docs/componentes/orderlist.doc.d.ts +8 -0
  91. package/dist/docs/componentes/orderlist.doc.d.ts.map +1 -0
  92. package/dist/docs/componentes/pagination.doc.d.ts +8 -0
  93. package/dist/docs/componentes/pagination.doc.d.ts.map +1 -0
  94. package/dist/docs/componentes/picklist.doc.d.ts +8 -0
  95. package/dist/docs/componentes/picklist.doc.d.ts.map +1 -0
  96. package/dist/docs/componentes/progress.doc.d.ts +8 -0
  97. package/dist/docs/componentes/progress.doc.d.ts.map +1 -0
  98. package/dist/docs/componentes/radio.doc.d.ts +8 -0
  99. package/dist/docs/componentes/radio.doc.d.ts.map +1 -0
  100. package/dist/docs/componentes/select.doc.d.ts +8 -0
  101. package/dist/docs/componentes/select.doc.d.ts.map +1 -0
  102. package/dist/docs/componentes/skeleton.doc.d.ts +8 -0
  103. package/dist/docs/componentes/skeleton.doc.d.ts.map +1 -0
  104. package/dist/docs/componentes/spinner.doc.d.ts +8 -0
  105. package/dist/docs/componentes/spinner.doc.d.ts.map +1 -0
  106. package/dist/docs/componentes/switch.doc.d.ts +8 -0
  107. package/dist/docs/componentes/switch.doc.d.ts.map +1 -0
  108. package/dist/docs/componentes/table.doc.d.ts +8 -0
  109. package/dist/docs/componentes/table.doc.d.ts.map +1 -0
  110. package/dist/docs/componentes/tabs.doc.d.ts +8 -0
  111. package/dist/docs/componentes/tabs.doc.d.ts.map +1 -0
  112. package/dist/docs/componentes/textarea.doc.d.ts +8 -0
  113. package/dist/docs/componentes/textarea.doc.d.ts.map +1 -0
  114. package/dist/docs/componentes/toast.doc.d.ts +8 -0
  115. package/dist/docs/componentes/toast.doc.d.ts.map +1 -0
  116. package/dist/docs/componentes/tooltip.doc.d.ts +25 -0
  117. package/dist/docs/componentes/tooltip.doc.d.ts.map +1 -0
  118. package/dist/docs/shared.d.ts +9 -0
  119. package/dist/docs/shared.d.ts.map +1 -0
  120. package/dist/docs/types.d.ts +47 -0
  121. package/dist/docs/types.d.ts.map +1 -0
  122. package/dist/fenix-ui.umd.min.js +815 -157
  123. package/dist/fenix-ui2.esm.js +2522 -103
  124. package/dist/fenix-ui2.esm.js.map +1 -1
  125. package/dist/index.d.ts +4 -0
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +16 -0
  128. package/dist/index.js.map +1 -1
  129. package/package.json +212 -187
@@ -7,9 +7,9 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
7
7
  var _FxToast_instances, render_fn;
8
8
  const lightTokens = {
9
9
  color: {
10
- primary: "#4f46e5",
11
- secondary: "#8b5cf6",
12
- success: "#10b981",
10
+ primary: "#c2410c",
11
+ secondary: "#991B1B",
12
+ success: "#10b972",
13
13
  warning: "#f59e0b",
14
14
  danger: "#f43f5e",
15
15
  info: "#0ea5e9"
@@ -20,7 +20,7 @@ const lightTokens = {
20
20
  "surface-hover": "#eef2f7"
21
21
  },
22
22
  text: {
23
- default: "#0f172a",
23
+ default: "#10182c",
24
24
  muted: "#64748b",
25
25
  disabled: "#94a3b8"
26
26
  },
@@ -160,23 +160,44 @@ const themePresets = {
160
160
  name: "seiya",
161
161
  label: "Seiya",
162
162
  tokens: {
163
- color: { primary: "#e11d48", secondary: "#fb7185", info: "#f43f5e", danger: "#be123c" },
164
- radius: { sm: "6px", md: "10px", lg: "16px" }
163
+ color: {
164
+ primary: "#e11d48",
165
+ secondary: "#fb7185",
166
+ info: "#f43f5e",
167
+ danger: "#be123c"
168
+ },
169
+ radius: { sm: "6px", md: "10px", lg: "16px" },
170
+ effect: {
171
+ "focus-ring": "none"
172
+ }
165
173
  }
166
174
  }),
167
175
  shiryu: register({
168
176
  name: "shiryu",
169
177
  label: "Shiryu",
170
178
  tokens: {
171
- color: { primary: "#0d9488", secondary: "#2dd4bf", success: "#059669", info: "#14b8a6" },
172
- radius: { sm: "4px", md: "8px", lg: "14px" }
179
+ color: {
180
+ primary: "#0d9488",
181
+ secondary: "#2dd4bf",
182
+ success: "#059669",
183
+ info: "#14b8a6"
184
+ },
185
+ radius: { sm: "4px", md: "8px", lg: "14px" },
186
+ effect: {
187
+ "focus-ring": "none"
188
+ }
173
189
  }
174
190
  }),
175
191
  hyoga: register({
176
192
  name: "hyoga",
177
193
  label: "Hyoga",
178
194
  tokens: {
179
- color: { primary: "#0284c7", secondary: "#38bdf8", info: "#06b6d4", danger: "#e11d48" },
195
+ color: {
196
+ primary: "#0284c7",
197
+ secondary: "#38bdf8",
198
+ info: "#06b6d4",
199
+ danger: "#e11d48"
200
+ },
180
201
  surface: { surface: "#f0f9ff", "surface-hover": "#e0f2fe" },
181
202
  radius: { sm: "8px", md: "12px", lg: "18px" }
182
203
  }
@@ -185,7 +206,12 @@ const themePresets = {
185
206
  name: "shun",
186
207
  label: "Shun",
187
208
  tokens: {
188
- color: { primary: "#db2777", secondary: "#f472b6", info: "#ec4899", warning: "#c026d3" },
209
+ color: {
210
+ primary: "#db2777",
211
+ secondary: "#f472b6",
212
+ info: "#ec4899",
213
+ warning: "#c026d3"
214
+ },
189
215
  radius: { sm: "10px", md: "14px", lg: "20px" }
190
216
  }
191
217
  }),
@@ -193,7 +219,12 @@ const themePresets = {
193
219
  name: "ikki",
194
220
  label: "Ikki",
195
221
  tokens: {
196
- color: { primary: "#ea580c", secondary: "#fb923c", danger: "#dc2626", warning: "#f59e0b" },
222
+ color: {
223
+ primary: "#ea580c",
224
+ secondary: "#fb923c",
225
+ danger: "#dc2626",
226
+ warning: "#f59e0b"
227
+ },
197
228
  radius: { sm: "2px", md: "4px", lg: "6px" }
198
229
  }
199
230
  }),
@@ -201,8 +232,16 @@ const themePresets = {
201
232
  name: "aiolia",
202
233
  label: "Aiolia",
203
234
  tokens: {
204
- color: { primary: "#b45309", secondary: "#f59e0b", warning: "#eab308", info: "#84cc16" },
205
- radius: { sm: "6px", md: "12px", lg: "20px" }
235
+ color: {
236
+ primary: "#b45309",
237
+ secondary: "#f59e0b",
238
+ warning: "#eab308",
239
+ info: "#84cc16"
240
+ },
241
+ radius: { sm: "6px", md: "12px", lg: "20px" },
242
+ effect: {
243
+ "focus-ring": "none"
244
+ }
206
245
  }
207
246
  })
208
247
  };
@@ -1488,7 +1527,18 @@ const _FxCalendar = class _FxCalendar extends FxElement {
1488
1527
  this.pickEnd = null;
1489
1528
  }
1490
1529
  static get observedAttributes() {
1491
- return ["value", "start", "end", "min", "max", "range", "mode", "values", "locale", "disabled"];
1530
+ return [
1531
+ "value",
1532
+ "start",
1533
+ "end",
1534
+ "min",
1535
+ "max",
1536
+ "range",
1537
+ "mode",
1538
+ "values",
1539
+ "locale",
1540
+ "disabled"
1541
+ ];
1492
1542
  }
1493
1543
  /** Modo de seleção: 'single' | 'range' | 'multiple'. */
1494
1544
  get mode() {
@@ -1556,7 +1606,11 @@ const _FxCalendar = class _FxCalendar extends FxElement {
1556
1606
  return key(date.getFullYear(), date.getMonth() + 1, date.getDate());
1557
1607
  }
1558
1608
  keyToDate(k) {
1559
- return new Date(Math.floor(k / 1e4), Math.floor(k / 100) % 100 - 1, k % 100);
1609
+ return new Date(
1610
+ Math.floor(k / 1e4),
1611
+ Math.floor(k / 100) % 100 - 1,
1612
+ k % 100
1613
+ );
1560
1614
  }
1561
1615
  iso(k) {
1562
1616
  const d = this.keyToDate(k);
@@ -1565,7 +1619,9 @@ const _FxCalendar = class _FxCalendar extends FxElement {
1565
1619
  }
1566
1620
  /** Seleção atual para pintura (chaves). */
1567
1621
  selection() {
1568
- const multi = new Set(this.values.map((iso) => parseBound(iso)?.lo ?? 0).filter(Boolean));
1622
+ const multi = new Set(
1623
+ this.values.map((iso) => parseBound(iso)?.lo ?? 0).filter(Boolean)
1624
+ );
1569
1625
  if (this.mode === "range") {
1570
1626
  let s = this.pickStart;
1571
1627
  let e = this.pickEnd;
@@ -1589,13 +1645,31 @@ const _FxCalendar = class _FxCalendar extends FxElement {
1589
1645
  };
1590
1646
  this.setAttribute("start", detail.start);
1591
1647
  this.setAttribute("end", detail.end);
1592
- this.dispatchEvent(new CustomEvent("change", { bubbles: true, composed: true, detail }));
1648
+ this.dispatchEvent(
1649
+ new CustomEvent("change", {
1650
+ bubbles: true,
1651
+ composed: true,
1652
+ detail
1653
+ })
1654
+ );
1593
1655
  } else if (this.mode === "multiple") {
1594
1656
  const values = this.values;
1595
- this.dispatchEvent(new CustomEvent("change", { bubbles: true, composed: true, detail: { values } }));
1657
+ this.dispatchEvent(
1658
+ new CustomEvent("change", {
1659
+ bubbles: true,
1660
+ composed: true,
1661
+ detail: { values }
1662
+ })
1663
+ );
1596
1664
  } else {
1597
1665
  const value = this.getAttr("value");
1598
- this.dispatchEvent(new CustomEvent("change", { bubbles: true, composed: true, detail: { value } }));
1666
+ this.dispatchEvent(
1667
+ new CustomEvent("change", {
1668
+ bubbles: true,
1669
+ composed: true,
1670
+ detail: { value }
1671
+ })
1672
+ );
1599
1673
  }
1600
1674
  }
1601
1675
  pickDay(k) {
@@ -1608,7 +1682,8 @@ const _FxCalendar = class _FxCalendar extends FxElement {
1608
1682
  this.render();
1609
1683
  return;
1610
1684
  }
1611
- if (k < this.pickStart) [this.pickStart, this.pickEnd] = [k, this.pickStart];
1685
+ if (k < this.pickStart)
1686
+ [this.pickStart, this.pickEnd] = [k, this.pickStart];
1612
1687
  else this.pickEnd = k;
1613
1688
  this.emit();
1614
1689
  } else if (this.mode === "multiple") {
@@ -1640,7 +1715,10 @@ const _FxCalendar = class _FxCalendar extends FxElement {
1640
1715
  const sel = this.selection();
1641
1716
  const loc = this.locale();
1642
1717
  const titles = {
1643
- days: this.fmt({ month: "long", year: "numeric" }, new Date(this.cursor.y, this.cursor.m, 1)),
1718
+ days: this.fmt(
1719
+ { month: "long", year: "numeric" },
1720
+ new Date(this.cursor.y, this.cursor.m, 1)
1721
+ ),
1644
1722
  months: String(this.cursor.y),
1645
1723
  years: `${Math.floor(this.cursor.y / 12) * 12} – ${Math.floor(this.cursor.y / 12) * 12 + 11}`
1646
1724
  };
@@ -1674,7 +1752,10 @@ const _FxCalendar = class _FxCalendar extends FxElement {
1674
1752
  <div class="grid ${this.view}">${cells}</div>
1675
1753
  `);
1676
1754
  this.root.querySelectorAll("[data-nav]").forEach(
1677
- (b) => b.addEventListener("click", () => this.navigate(Number(b.dataset.nav)))
1755
+ (b) => b.addEventListener(
1756
+ "click",
1757
+ () => this.navigate(Number(b.dataset.nav))
1758
+ )
1678
1759
  );
1679
1760
  const gotoBtn = this.root.querySelector("[data-goto]");
1680
1761
  gotoBtn?.addEventListener("click", () => {
@@ -1682,7 +1763,10 @@ const _FxCalendar = class _FxCalendar extends FxElement {
1682
1763
  this.render();
1683
1764
  });
1684
1765
  this.root.querySelectorAll("[data-day]").forEach(
1685
- (b) => b.addEventListener("click", () => this.pickDay(Number(b.dataset.day)))
1766
+ (b) => b.addEventListener(
1767
+ "click",
1768
+ () => this.pickDay(Number(b.dataset.day))
1769
+ )
1686
1770
  );
1687
1771
  this.root.querySelectorAll("[data-month]").forEach(
1688
1772
  (b) => b.addEventListener("click", () => {
@@ -1713,95 +1797,148 @@ const _FxCalendar = class _FxCalendar extends FxElement {
1713
1797
  const k = key(y, m + 1, d);
1714
1798
  const isSel = sel.single === k || sel.start === k || sel.end === k || sel.multi.has(k);
1715
1799
  const inRange = sel.start !== null && sel.end !== null && k > sel.start && k < sel.end;
1716
- const cls = ["cell", isSel ? "sel" : "", inRange ? "in-range" : "", k === todayK ? "today" : ""].filter(Boolean).join(" ");
1800
+ const cls = [
1801
+ "cell",
1802
+ isSel ? "sel" : "",
1803
+ inRange ? "in-range" : "",
1804
+ k === todayK ? "today" : ""
1805
+ ].filter(Boolean).join(" ");
1717
1806
  html += `<button type="button" class="${cls}" data-day="${k}" ${this.dayDisabled(y, m, d) ? "disabled" : ""}>${d}</button>`;
1718
1807
  }
1719
1808
  return html;
1720
1809
  }
1721
1810
  };
1722
1811
  _FxCalendar.styles = css`
1723
- :host {
1724
- display: inline-block;
1725
- font-family: var(--fx-font-family);
1726
- font-size: var(--fx-font-size);
1727
- color: var(--fx-text-default);
1728
- background: var(--fx-surface-background);
1729
- border: 1px solid var(--fx-border-default);
1730
- border-radius: var(--fx-radius-md);
1731
- box-shadow: var(--fx-shadow-sm);
1732
- padding: var(--fx-space-sm);
1733
- user-select: none;
1734
- }
1735
- :host([disabled]) { opacity: 0.55; pointer-events: none; }
1736
- .head {
1812
+ :host {
1813
+ display: inline-block;
1814
+ font-family: var(--fx-font-family);
1815
+ font-size: var(--fx-font-size);
1816
+ color: var(--fx-text-default);
1817
+ background: var(--fx-surface-background);
1818
+ border: 1px solid var(--fx-border-default);
1819
+ border-radius: var(--fx-radius-md);
1820
+ box-shadow: var(--fx-shadow-sm);
1821
+ padding: var(--fx-space-sm);
1822
+ user-select: none;
1823
+ }
1824
+ :host([disabled]) {
1825
+ opacity: 0.55;
1826
+ pointer-events: none;
1827
+ }
1828
+ .head {
1829
+ display: flex;
1830
+ height: 48px;
1831
+ align-items: center;
1832
+ justify-content: space-between;
1833
+ gap: var(--fx-space-xs);
1834
+ margin-bottom: var(--fx-space-xs);
1835
+ border-bottom: 1px solid var(--fx-border-default);
1836
+ }
1837
+
1838
+ .title {
1839
+ min-width: 24px;
1840
+ border: none;
1841
+ background: none;
1842
+ color: var(--fx-text-default);
1843
+ cursor: pointer;
1844
+ font: inherit;
1845
+ border-radius: var(--fx-radius-sm);
1846
+ }
1847
+ .nav {
1737
1848
  display: flex;
1738
1849
  align-items: center;
1739
- justify-content: space-between;
1740
- gap: var(--fx-space-xs);
1741
- margin-bottom: var(--fx-space-xs);
1742
- }
1743
- .nav,
1744
- .title {
1745
- border: none;
1746
- background: none;
1747
- color: var(--fx-text-default);
1748
- cursor: pointer;
1749
- font: inherit;
1750
- border-radius: var(--fx-radius-sm);
1751
- padding: var(--fx-space-3xs, 4px) var(--fx-space-xs);
1752
- }
1753
- .nav:hover, .title:hover { background: var(--fx-surface-surface-hover); }
1754
- .title { font-weight: var(--fx-font-weight); text-transform: capitalize; flex: 1; }
1755
- .grid {
1756
- display: grid;
1757
- grid-template-columns: repeat(7, 34px);
1758
- gap: 2px;
1759
- }
1760
- .grid.months, .grid.years { grid-template-columns: repeat(4, minmax(52px, 1fr)); }
1761
- .wd {
1762
- text-align: center;
1763
- color: var(--fx-text-muted);
1764
- font-size: calc(var(--fx-font-size) - 2px);
1765
- padding: var(--fx-space-3xs, 4px) 0;
1766
- text-transform: capitalize;
1767
- }
1768
- .cell {
1769
- position: relative;
1770
- border: none;
1771
- background: none;
1772
- font: inherit;
1773
- color: var(--fx-text-default);
1774
- height: 32px;
1775
- border-radius: var(--fx-radius-sm);
1776
- cursor: pointer;
1777
- display: inline-flex;
1778
- align-items: center;
1779
1850
  justify-content: center;
1851
+ font-size: 20px;
1852
+ border: none;
1853
+ background: none;
1854
+ color: var(--fx-text-muted);
1855
+ cursor: pointer;
1856
+ border-radius: var(--fx-radius-sm);
1780
1857
  }
1781
- .cell:hover { background: color-mix(in srgb, var(--fx-color-primary) 12%, transparent); }
1782
- .cell.muted { color: var(--fx-text-disabled); }
1783
- .cell.today::after {
1784
- content: '';
1785
- position: absolute;
1786
- bottom: 3px;
1787
- width: 4px;
1788
- height: 4px;
1789
- border-radius: var(--fx-radius-full);
1790
- background: var(--fx-color-primary);
1791
- }
1792
- .cell.sel {
1793
- background: var(--fx-color-primary);
1794
- color: #fff;
1795
- font-weight: var(--fx-font-weight);
1796
- }
1797
- .cell.sel::after { background: #fff; }
1798
- .cell.in-range {
1799
- background: color-mix(in srgb, var(--fx-color-primary) 16%, transparent);
1800
- border-radius: 0;
1801
- }
1802
- .grid.months .cell, .grid.years .cell { height: 40px; }
1803
- .cell[disabled] { opacity: 0.35; cursor: not-allowed; pointer-events: none; }
1804
- `;
1858
+ .nav:hover,
1859
+ .title:hover {
1860
+ background: var(--fx-surface-surface-hover);
1861
+ }
1862
+ .title {
1863
+ padding: var(--fx-space-3xs, 4px) var(--fx-space-xs);
1864
+ font-weight: var(--fx-font-weight);
1865
+ text-transform: capitalize;
1866
+ flex: 1;
1867
+ }
1868
+ .grid {
1869
+ display: grid;
1870
+ grid-template-columns: repeat(7, 34px);
1871
+ gap: 2px;
1872
+ }
1873
+ .grid.months,
1874
+ .grid.years {
1875
+ grid-template-columns: repeat(4, minmax(52px, 1fr));
1876
+ }
1877
+ .wd {
1878
+ text-align: center;
1879
+ color: var(--fx-text-muted);
1880
+ font-size: calc(var(--fx-font-size) - 2px);
1881
+ padding: var(--fx-space-3xs, 4px) 0;
1882
+ text-transform: capitalize;
1883
+ }
1884
+ .cell {
1885
+ position: relative;
1886
+ border: none;
1887
+ background: none;
1888
+ font: inherit;
1889
+ color: var(--fx-text-default);
1890
+ height: 32px;
1891
+ border-radius: var(--fx-radius-sm);
1892
+ cursor: pointer;
1893
+ display: inline-flex;
1894
+ align-items: center;
1895
+ justify-content: center;
1896
+ }
1897
+ .cell:hover {
1898
+ background: color-mix(
1899
+ in srgb,
1900
+ var(--fx-color-primary) 12%,
1901
+ transparent
1902
+ );
1903
+ }
1904
+ .cell.muted {
1905
+ color: var(--fx-text-disabled);
1906
+ }
1907
+ .cell.today::after {
1908
+ content: "";
1909
+ position: absolute;
1910
+ bottom: 3px;
1911
+ width: 4px;
1912
+ height: 4px;
1913
+ border-radius: var(--fx-radius-full);
1914
+ background: var(--fx-color-primary);
1915
+ }
1916
+ .cell.sel {
1917
+ background: var(--fx-color-primary);
1918
+ color: #fff;
1919
+ font-weight: var(--fx-font-weight);
1920
+ }
1921
+ .cell.sel::after {
1922
+ background: #fff;
1923
+ }
1924
+ .cell.in-range {
1925
+ background: color-mix(
1926
+ in srgb,
1927
+ var(--fx-color-primary) 16%,
1928
+ transparent
1929
+ );
1930
+ border-radius: 0;
1931
+ }
1932
+ .grid.months .cell,
1933
+ .grid.years .cell {
1934
+ height: 40px;
1935
+ }
1936
+ .cell[disabled] {
1937
+ opacity: 0.35;
1938
+ cursor: not-allowed;
1939
+ pointer-events: none;
1940
+ }
1941
+ `;
1805
1942
  let FxCalendar = _FxCalendar;
1806
1943
  function defineFxCalendar() {
1807
1944
  return defineElement("fx-calendar", FxCalendar);
@@ -3487,6 +3624,295 @@ let FxTooltip = _FxTooltip;
3487
3624
  function defineFxTooltip() {
3488
3625
  return defineElement("fx-tooltip", FxTooltip);
3489
3626
  }
3627
+ const DEFAULT_CONFIG = {
3628
+ position: "top"
3629
+ };
3630
+ class TooltipBehavior {
3631
+ constructor(element) {
3632
+ this.tooltipElement = null;
3633
+ this.showTimeout = null;
3634
+ this.hideTimeout = null;
3635
+ this.show = () => {
3636
+ if (this.hideTimeout) {
3637
+ clearTimeout(this.hideTimeout);
3638
+ this.hideTimeout = null;
3639
+ }
3640
+ this.showTimeout = window.setTimeout(() => {
3641
+ if (this.tooltipElement) {
3642
+ this.tooltipElement.classList.add("fx-tooltip-visible");
3643
+ }
3644
+ }, 100);
3645
+ };
3646
+ this.hide = () => {
3647
+ if (this.showTimeout) {
3648
+ clearTimeout(this.showTimeout);
3649
+ this.showTimeout = null;
3650
+ }
3651
+ this.hideTimeout = window.setTimeout(() => {
3652
+ if (this.tooltipElement) {
3653
+ this.tooltipElement.classList.remove("fx-tooltip-visible");
3654
+ }
3655
+ }, 50);
3656
+ };
3657
+ this.element = element;
3658
+ this.config = this.parseConfig();
3659
+ this.init();
3660
+ }
3661
+ parseConfig() {
3662
+ const position = this.element.getAttribute("fx-tooltip-position");
3663
+ return {
3664
+ position: position && ["top", "bottom", "left", "right"].includes(position) ? position : DEFAULT_CONFIG.position,
3665
+ html: this.element.hasAttribute("fx-tooltip-html")
3666
+ };
3667
+ }
3668
+ init() {
3669
+ const computedStyle = window.getComputedStyle(this.element);
3670
+ if (computedStyle.position === "static") {
3671
+ this.element.style.position = "relative";
3672
+ }
3673
+ this.createTooltipElement();
3674
+ this.element.addEventListener("mouseenter", this.show);
3675
+ this.element.addEventListener("mouseleave", this.hide);
3676
+ this.element.addEventListener("focus", this.show);
3677
+ this.element.addEventListener("blur", this.hide);
3678
+ }
3679
+ createTooltipElement() {
3680
+ const content = this.element.getAttribute("fx-tooltip");
3681
+ if (!content) return;
3682
+ this.tooltipElement = document.createElement("span");
3683
+ this.tooltipElement.setAttribute("role", "tooltip");
3684
+ this.tooltipElement.setAttribute("data-fx-tooltip", "");
3685
+ this.tooltipElement.className = `fx-tooltip-bubble fx-tooltip-${this.config.position}`;
3686
+ if (this.config.html) {
3687
+ this.tooltipElement.innerHTML = content;
3688
+ } else {
3689
+ this.tooltipElement.textContent = content;
3690
+ }
3691
+ this.element.appendChild(this.tooltipElement);
3692
+ }
3693
+ update() {
3694
+ this.config = this.parseConfig();
3695
+ if (this.tooltipElement) {
3696
+ this.tooltipElement.remove();
3697
+ this.tooltipElement = null;
3698
+ }
3699
+ this.createTooltipElement();
3700
+ }
3701
+ destroy() {
3702
+ this.element.removeEventListener("mouseenter", this.show);
3703
+ this.element.removeEventListener("mouseleave", this.hide);
3704
+ this.element.removeEventListener("focus", this.show);
3705
+ this.element.removeEventListener("blur", this.hide);
3706
+ if (this.showTimeout) clearTimeout(this.showTimeout);
3707
+ if (this.hideTimeout) clearTimeout(this.hideTimeout);
3708
+ if (this.tooltipElement) {
3709
+ this.tooltipElement.remove();
3710
+ this.tooltipElement = null;
3711
+ }
3712
+ }
3713
+ }
3714
+ const _FxTooltipManager = class _FxTooltipManager {
3715
+ constructor() {
3716
+ this.observer = null;
3717
+ this.behaviors = /* @__PURE__ */ new Map();
3718
+ this.injectedStyles = null;
3719
+ this.injectStyles();
3720
+ this.observe();
3721
+ this.processExistingElements();
3722
+ }
3723
+ static getInstance() {
3724
+ if (!_FxTooltipManager.instance) {
3725
+ _FxTooltipManager.instance = new _FxTooltipManager();
3726
+ }
3727
+ return _FxTooltipManager.instance;
3728
+ }
3729
+ injectStyles() {
3730
+ if (document.getElementById("fx-tooltip-directive-styles")) return;
3731
+ this.injectedStyles = document.createElement("style");
3732
+ this.injectedStyles.id = "fx-tooltip-directive-styles";
3733
+ this.injectedStyles.textContent = getTooltipStyles();
3734
+ document.head.appendChild(this.injectedStyles);
3735
+ }
3736
+ observe() {
3737
+ this.observer = new MutationObserver((mutations) => {
3738
+ for (const mutation of mutations) {
3739
+ if (mutation.type === "childList") {
3740
+ mutation.addedNodes.forEach((node) => {
3741
+ if (node instanceof HTMLElement) {
3742
+ this.processElement(node);
3743
+ node.querySelectorAll("[fx-tooltip]").forEach((el) => this.processElement(el));
3744
+ }
3745
+ });
3746
+ }
3747
+ if (mutation.type === "attributes" && mutation.target instanceof HTMLElement) {
3748
+ const target = mutation.target;
3749
+ if (target.hasAttribute("fx-tooltip")) {
3750
+ this.processElement(target);
3751
+ } else if (this.behaviors.has(target)) {
3752
+ this.removeBehavior(target);
3753
+ }
3754
+ }
3755
+ }
3756
+ });
3757
+ this.observer.observe(document.body, {
3758
+ childList: true,
3759
+ subtree: true,
3760
+ attributes: true,
3761
+ attributeFilter: ["fx-tooltip", "fx-tooltip-position", "fx-tooltip-html"]
3762
+ });
3763
+ }
3764
+ processExistingElements() {
3765
+ document.querySelectorAll("[fx-tooltip]").forEach((el) => this.processElement(el));
3766
+ }
3767
+ processElement(element) {
3768
+ if (!element.hasAttribute("fx-tooltip")) {
3769
+ this.removeBehavior(element);
3770
+ return;
3771
+ }
3772
+ if (this.behaviors.has(element)) {
3773
+ this.behaviors.get(element).update();
3774
+ } else {
3775
+ this.behaviors.set(element, new TooltipBehavior(element));
3776
+ }
3777
+ }
3778
+ removeBehavior(element) {
3779
+ const behavior = this.behaviors.get(element);
3780
+ if (behavior) {
3781
+ behavior.destroy();
3782
+ this.behaviors.delete(element);
3783
+ }
3784
+ }
3785
+ destroy() {
3786
+ if (this.observer) {
3787
+ this.observer.disconnect();
3788
+ this.observer = null;
3789
+ }
3790
+ this.behaviors.forEach((behavior) => behavior.destroy());
3791
+ this.behaviors.clear();
3792
+ if (this.injectedStyles) {
3793
+ this.injectedStyles.remove();
3794
+ this.injectedStyles = null;
3795
+ }
3796
+ _FxTooltipManager.instance = null;
3797
+ }
3798
+ };
3799
+ _FxTooltipManager.instance = null;
3800
+ let FxTooltipManager = _FxTooltipManager;
3801
+ function getTooltipStyles() {
3802
+ return (
3803
+ /* css */
3804
+ `
3805
+ [fx-tooltip] {
3806
+ position: relative;
3807
+ }
3808
+
3809
+ .fx-tooltip-bubble {
3810
+ position: absolute;
3811
+ background: var(--fx-text-default, #1e293b);
3812
+ color: var(--fx-surface-background, #fff);
3813
+ font-family: var(--fx-font-family, system-ui, -apple-system, sans-serif);
3814
+ font-size: calc(var(--fx-font-size, 14px) - 2px);
3815
+ line-height: 1.45;
3816
+ padding: var(--fx-space-xs, 4px) var(--fx-space-md, 12px);
3817
+ border-radius: var(--fx-radius-sm, 4px);
3818
+ box-shadow: var(--fx-shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.1));
3819
+ width: max-content;
3820
+ min-width: 60px;
3821
+ max-width: var(--fx-tooltip-max-width, 320px);
3822
+ white-space: normal;
3823
+ text-align: center;
3824
+ opacity: 0;
3825
+ visibility: hidden;
3826
+ transition: opacity var(--fx-motion-duration-fast, 150ms) var(--fx-motion-easing, ease);
3827
+ z-index: var(--fx-z-tooltip, 1050);
3828
+ pointer-events: none;
3829
+ }
3830
+
3831
+ .fx-tooltip-bubble.fx-tooltip-visible {
3832
+ opacity: 1;
3833
+ visibility: visible;
3834
+ }
3835
+
3836
+ .fx-tooltip-top {
3837
+ bottom: calc(100% + 6px);
3838
+ left: 50%;
3839
+ transform: translateX(-50%);
3840
+ }
3841
+ .fx-tooltip-top::after {
3842
+ content: '';
3843
+ position: absolute;
3844
+ top: 100%;
3845
+ left: 50%;
3846
+ transform: translateX(-50%);
3847
+ border: 5px solid transparent;
3848
+ border-top-color: var(--fx-text-default, #1e293b);
3849
+ }
3850
+
3851
+ .fx-tooltip-bottom {
3852
+ top: calc(100% + 6px);
3853
+ left: 50%;
3854
+ transform: translateX(-50%);
3855
+ bottom: auto;
3856
+ }
3857
+ .fx-tooltip-bottom::after {
3858
+ content: '';
3859
+ position: absolute;
3860
+ bottom: 100%;
3861
+ left: 50%;
3862
+ transform: translateX(-50%);
3863
+ border: 5px solid transparent;
3864
+ border-bottom-color: var(--fx-text-default, #1e293b);
3865
+ }
3866
+
3867
+ .fx-tooltip-left {
3868
+ right: calc(100% + 6px);
3869
+ top: 50%;
3870
+ transform: translateY(-50%);
3871
+ left: auto;
3872
+ bottom: auto;
3873
+ }
3874
+ .fx-tooltip-left::after {
3875
+ content: '';
3876
+ position: absolute;
3877
+ top: 50%;
3878
+ left: 100%;
3879
+ transform: translateY(-50%);
3880
+ border: 5px solid transparent;
3881
+ border-left-color: var(--fx-text-default, #1e293b);
3882
+ }
3883
+
3884
+ .fx-tooltip-right {
3885
+ left: calc(100% + 6px);
3886
+ top: 50%;
3887
+ transform: translateY(-50%);
3888
+ right: auto;
3889
+ bottom: auto;
3890
+ }
3891
+ .fx-tooltip-right::after {
3892
+ content: '';
3893
+ position: absolute;
3894
+ top: 50%;
3895
+ right: 100%;
3896
+ transform: translateY(-50%);
3897
+ border: 5px solid transparent;
3898
+ border-right-color: var(--fx-text-default, #1e293b);
3899
+ }
3900
+ `
3901
+ );
3902
+ }
3903
+ function defineFxTooltipDirective() {
3904
+ if (typeof window === "undefined") return;
3905
+ if (document.readyState === "loading") {
3906
+ document.addEventListener("DOMContentLoaded", () => {
3907
+ FxTooltipManager.getInstance();
3908
+ });
3909
+ } else {
3910
+ FxTooltipManager.getInstance();
3911
+ }
3912
+ }
3913
+ function destroyFxTooltipDirective() {
3914
+ FxTooltipManager.getInstance().destroy();
3915
+ }
3490
3916
  defineFxTooltip();
3491
3917
  const _FxTabs = class _FxTabs extends FxElement {
3492
3918
  static get observedAttributes() {
@@ -3870,7 +4296,7 @@ const _FxDropdown = class _FxDropdown extends FxElement {
3870
4296
  ${label} ▾
3871
4297
  </span>
3872
4298
  <div class="panel" role="menu" part="panel">
3873
- ${items.length ? items.map((i) => `<div class="item-slot"><slot name="_${i.getAttribute("value") ?? ""}"></slot></div>`) : '<div class="empty">Nenhuma ação</div>'}
4299
+ ${items.length ? "" : '<div class="empty">Nenhuma ação</div>'}
3874
4300
  <slot></slot>
3875
4301
  </div>
3876
4302
  `);
@@ -4419,10 +4845,1998 @@ function defineFxAutocomplete() {
4419
4845
  return defineElement("fx-autocomplete", FxAutocomplete);
4420
4846
  }
4421
4847
  defineFxAutocomplete();
4848
+ const _FxKnob = class _FxKnob extends FxElement {
4849
+ constructor() {
4850
+ super(...arguments);
4851
+ this._isDragging = false;
4852
+ this._startY = 0;
4853
+ this._startValue = 0;
4854
+ this._onMouseMove = (e) => {
4855
+ if (!this._isDragging) return;
4856
+ const deltaY = this._startY - e.clientY;
4857
+ const sensitivity = (this.max - this.min) / 100;
4858
+ this.emitChange(this._startValue + deltaY * sensitivity);
4859
+ };
4860
+ this._onMouseUp = () => {
4861
+ this._isDragging = false;
4862
+ document.removeEventListener("mousemove", this._onMouseMove);
4863
+ document.removeEventListener("mouseup", this._onMouseUp);
4864
+ };
4865
+ }
4866
+ static get observedAttributes() {
4867
+ return [
4868
+ "value",
4869
+ "min",
4870
+ "max",
4871
+ "step",
4872
+ "size",
4873
+ "stroke-width",
4874
+ "value-color",
4875
+ "range-color",
4876
+ "readonly",
4877
+ "disabled",
4878
+ "value-template"
4879
+ ];
4880
+ }
4881
+ get value() {
4882
+ return this.clampValue(Number(this.getAttr("value", "0")) || 0);
4883
+ }
4884
+ set value(v) {
4885
+ if (this.readonly || this.disabled) return;
4886
+ const clamped = this.clampValue(v);
4887
+ const current = this.clampValue(Number(this.getAttr("value", "0")) || 0);
4888
+ if (clamped !== current) {
4889
+ this.setAttribute("value", String(clamped));
4890
+ this.dispatchEvent(
4891
+ new CustomEvent("change", {
4892
+ bubbles: true,
4893
+ composed: true,
4894
+ detail: { value: clamped }
4895
+ })
4896
+ );
4897
+ }
4898
+ }
4899
+ get min() {
4900
+ return Number(this.getAttr("min", "0")) || 0;
4901
+ }
4902
+ set min(v) {
4903
+ this.setAttribute("min", String(v));
4904
+ }
4905
+ get max() {
4906
+ return Number(this.getAttr("max", "100")) || 100;
4907
+ }
4908
+ set max(v) {
4909
+ this.setAttribute("max", String(v));
4910
+ }
4911
+ get step() {
4912
+ return Number(this.getAttr("step", "1")) || 1;
4913
+ }
4914
+ set step(v) {
4915
+ this.setAttribute("step", String(v));
4916
+ }
4917
+ get size() {
4918
+ const s = this.getAttr("size", "md");
4919
+ return s === "sm" || s === "lg" ? s : "md";
4920
+ }
4921
+ set size(v) {
4922
+ this.setAttribute("size", v);
4923
+ }
4924
+ get strokeWidth() {
4925
+ return Number(this.getAttr("stroke-width", "8")) || 8;
4926
+ }
4927
+ set strokeWidth(v) {
4928
+ this.setAttribute("stroke-width", String(v));
4929
+ }
4930
+ get valueColor() {
4931
+ return this.getAttr("value-color", "");
4932
+ }
4933
+ set valueColor(v) {
4934
+ this.setAttribute("value-color", v);
4935
+ }
4936
+ get rangeColor() {
4937
+ return this.getAttr("range-color", "");
4938
+ }
4939
+ set rangeColor(v) {
4940
+ this.setAttribute("range-color", v);
4941
+ }
4942
+ get readonly() {
4943
+ return this.hasAttr("readonly");
4944
+ }
4945
+ set readonly(v) {
4946
+ this.toggleAttr("readonly", Boolean(v));
4947
+ }
4948
+ get disabled() {
4949
+ return this.hasAttr("disabled");
4950
+ }
4951
+ set disabled(v) {
4952
+ this.toggleAttr("disabled", Boolean(v));
4953
+ }
4954
+ get valueTemplate() {
4955
+ return this.getAttr("value-template", "{value}");
4956
+ }
4957
+ set valueTemplate(v) {
4958
+ this.setAttribute("value-template", v);
4959
+ }
4960
+ render() {
4961
+ const min = this.min;
4962
+ const max = this.max;
4963
+ const value = this.clampValue(this.value);
4964
+ const range = max - min;
4965
+ const pct = range > 0 ? (value - min) / range : 0;
4966
+ const sizeNum = this.getSizeNum();
4967
+ const strokeW = this.strokeWidth;
4968
+ const radius = (sizeNum - strokeW) / 2;
4969
+ const circumference = 2 * Math.PI * radius;
4970
+ const offset = circumference * (1 - pct);
4971
+ const valueColorStyle = this.valueColor ? `--_value-color: ${this.valueColor};` : "";
4972
+ const rangeColorStyle = this.rangeColor ? `--_range-color: ${this.rangeColor};` : "";
4973
+ const displayValue = this.valueTemplate.replace("{value}", String(Math.round(value)));
4974
+ this.setTemplate(`
4975
+ <div class="knob" part="knob" tabindex="${this.disabled ? "-1" : "0"}"
4976
+ role="slider" aria-valuenow="${value}" aria-valuemin="${min}" aria-valuemax="${max}"
4977
+ aria-readonly="${this.readonly}" aria-disabled="${this.disabled}"
4978
+ style="${valueColorStyle}${rangeColorStyle}">
4979
+ <svg viewBox="0 0 ${sizeNum} ${sizeNum}" part="svg">
4980
+ <circle class="track" part="track"
4981
+ cx="${sizeNum / 2}" cy="${sizeNum / 2}" r="${radius}" />
4982
+ <circle class="value" part="value"
4983
+ cx="${sizeNum / 2}" cy="${sizeNum / 2}" r="${radius}"
4984
+ stroke-dasharray="${circumference}"
4985
+ stroke-dashoffset="${offset}" />
4986
+ </svg>
4987
+ <div class="label" part="label">${displayValue}</div>
4988
+ </div>
4989
+ `);
4990
+ this.attachListeners();
4991
+ }
4992
+ getSizeNum() {
4993
+ const s = this.size;
4994
+ if (s === "sm") return 60;
4995
+ if (s === "lg") return 140;
4996
+ return 100;
4997
+ }
4998
+ clampValue(v) {
4999
+ const min = this.min;
5000
+ const max = this.max;
5001
+ const step = this.step;
5002
+ let clamped = Math.min(max, Math.max(min, v));
5003
+ if (step > 0) {
5004
+ clamped = Math.round((clamped - min) / step) * step + min;
5005
+ clamped = Math.min(max, Math.max(min, clamped));
5006
+ }
5007
+ return clamped;
5008
+ }
5009
+ emitChange(newValue) {
5010
+ const clamped = this.clampValue(newValue);
5011
+ if (clamped !== this.value) {
5012
+ this.value = clamped;
5013
+ this.dispatchEvent(
5014
+ new CustomEvent("change", {
5015
+ bubbles: true,
5016
+ composed: true,
5017
+ detail: { value: clamped }
5018
+ })
5019
+ );
5020
+ }
5021
+ }
5022
+ attachListeners() {
5023
+ const knob = this.root.querySelector(".knob");
5024
+ if (!knob) return;
5025
+ knob.addEventListener("mousedown", (e) => {
5026
+ if (this.readonly || this.disabled) return;
5027
+ e.preventDefault();
5028
+ this._isDragging = true;
5029
+ this._startY = e.clientY;
5030
+ this._startValue = this.value;
5031
+ knob.focus();
5032
+ document.addEventListener("mousemove", this._onMouseMove);
5033
+ document.addEventListener("mouseup", this._onMouseUp);
5034
+ });
5035
+ knob.addEventListener("touchstart", (e) => {
5036
+ if (this.readonly || this.disabled) return;
5037
+ e.preventDefault();
5038
+ this._isDragging = true;
5039
+ this._startY = e.touches[0].clientY;
5040
+ this._startValue = this.value;
5041
+ knob.focus();
5042
+ }, { passive: false });
5043
+ knob.addEventListener("touchmove", (e) => {
5044
+ if (!this._isDragging || this.readonly || this.disabled) return;
5045
+ e.preventDefault();
5046
+ const deltaY = this._startY - e.touches[0].clientY;
5047
+ const sensitivity = (this.max - this.min) / 100;
5048
+ this.emitChange(this._startValue + deltaY * sensitivity);
5049
+ }, { passive: false });
5050
+ knob.addEventListener("touchend", () => {
5051
+ this._isDragging = false;
5052
+ });
5053
+ knob.addEventListener("keydown", (e) => {
5054
+ if (this.readonly || this.disabled) return;
5055
+ const step = this.step;
5056
+ switch (e.key) {
5057
+ case "ArrowUp":
5058
+ case "ArrowRight":
5059
+ e.preventDefault();
5060
+ this.emitChange(this.value + step);
5061
+ break;
5062
+ case "ArrowDown":
5063
+ case "ArrowLeft":
5064
+ e.preventDefault();
5065
+ this.emitChange(this.value - step);
5066
+ break;
5067
+ case "Home":
5068
+ e.preventDefault();
5069
+ this.emitChange(this.min);
5070
+ break;
5071
+ case "End":
5072
+ e.preventDefault();
5073
+ this.emitChange(this.max);
5074
+ break;
5075
+ case "PageUp":
5076
+ e.preventDefault();
5077
+ this.emitChange(this.value + step * 10);
5078
+ break;
5079
+ case "PageDown":
5080
+ e.preventDefault();
5081
+ this.emitChange(this.value - step * 10);
5082
+ break;
5083
+ }
5084
+ });
5085
+ }
5086
+ disconnectedCallback() {
5087
+ document.removeEventListener("mousemove", this._onMouseMove);
5088
+ document.removeEventListener("mouseup", this._onMouseUp);
5089
+ super.disconnectedCallback();
5090
+ }
5091
+ };
5092
+ _FxKnob.styles = css`
5093
+ :host {
5094
+ display: inline-flex;
5095
+ align-items: center;
5096
+ justify-content: center;
5097
+ font-family: var(--fx-font-family);
5098
+ font-size: var(--fx-font-size);
5099
+ --_size: 100px;
5100
+ --_stroke-width: 8px;
5101
+ --_value-color: var(--fx-color-primary);
5102
+ --_range-color: var(--fx-border-default);
5103
+ }
5104
+ :host([size='sm']) { --_size: 60px; }
5105
+ :host([size='lg']) { --_size: 140px; }
5106
+ .knob {
5107
+ position: relative;
5108
+ width: var(--_size);
5109
+ height: var(--_size);
5110
+ cursor: pointer;
5111
+ user-select: none;
5112
+ touch-action: none;
5113
+ }
5114
+ :host([readonly]) .knob,
5115
+ :host([disabled]) .knob {
5116
+ cursor: default;
5117
+ pointer-events: none;
5118
+ }
5119
+ :host([disabled]) .knob {
5120
+ opacity: 0.55;
5121
+ }
5122
+ svg {
5123
+ width: 100%;
5124
+ height: 100%;
5125
+ transform: rotate(-90deg);
5126
+ }
5127
+ .track {
5128
+ fill: none;
5129
+ stroke: var(--_range-color);
5130
+ stroke-width: var(--_stroke-width);
5131
+ }
5132
+ .value {
5133
+ fill: none;
5134
+ stroke: var(--_value-color);
5135
+ stroke-width: var(--_stroke-width);
5136
+ stroke-linecap: round;
5137
+ transition: stroke-dashoffset var(--fx-motion-duration-fast) var(--fx-motion-easing);
5138
+ }
5139
+ .label {
5140
+ position: absolute;
5141
+ inset: 0;
5142
+ display: flex;
5143
+ align-items: center;
5144
+ justify-content: center;
5145
+ font-weight: 600;
5146
+ color: var(--fx-text-default);
5147
+ pointer-events: none;
5148
+ }
5149
+ :host([size='sm']) .label { font-size: 11px; }
5150
+ :host([size='md']) .label { font-size: 14px; }
5151
+ :host([size='lg']) .label { font-size: 18px; }
5152
+ .knob:focus-visible {
5153
+ outline: none;
5154
+ }
5155
+ .knob:focus-visible svg {
5156
+ filter: drop-shadow(var(--fx-effect-focus-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-primary) 22%, transparent)));
5157
+ }
5158
+ `;
5159
+ let FxKnob = _FxKnob;
5160
+ function defineFxKnob() {
5161
+ return defineElement("fx-knob", FxKnob);
5162
+ }
5163
+ defineFxKnob();
5164
+ const _FxOrderList = class _FxOrderList extends FxElement {
5165
+ constructor() {
5166
+ super(...arguments);
5167
+ this._data = [];
5168
+ this._filteredData = null;
5169
+ this._selection = [];
5170
+ this._filterValue = "";
5171
+ this._draggedIndex = null;
5172
+ this._listenersAttached = false;
5173
+ this._optionTemplate = null;
5174
+ }
5175
+ static get observedAttributes() {
5176
+ return [
5177
+ "data",
5178
+ "data-key",
5179
+ "filter",
5180
+ "filter-by",
5181
+ "filter-placeholder",
5182
+ "breakpoint",
5183
+ "controls-location",
5184
+ "dragdrop",
5185
+ "striped",
5186
+ "selection-mode",
5187
+ "show-select-all"
5188
+ ];
5189
+ }
5190
+ set data(value) {
5191
+ this._data = value;
5192
+ this._filteredData = null;
5193
+ this.render();
5194
+ }
5195
+ get data() {
5196
+ return this._data;
5197
+ }
5198
+ set selection(value) {
5199
+ this._selection = value;
5200
+ this.render();
5201
+ }
5202
+ get selection() {
5203
+ return this._selection;
5204
+ }
5205
+ get dataKey() {
5206
+ return this.getAttr("data-key", "");
5207
+ }
5208
+ set dataKey(v) {
5209
+ this.setAttribute("data-key", v);
5210
+ }
5211
+ get filter() {
5212
+ return this.hasAttr("filter");
5213
+ }
5214
+ set filter(v) {
5215
+ this.toggleAttr("filter", v);
5216
+ }
5217
+ get filterBy() {
5218
+ return this.getAttr("filter-by", "label");
5219
+ }
5220
+ set filterBy(v) {
5221
+ this.setAttribute("filter-by", v);
5222
+ }
5223
+ get filterPlaceholder() {
5224
+ return this.getAttr("filter-placeholder", "Buscar...");
5225
+ }
5226
+ set filterPlaceholder(v) {
5227
+ this.setAttribute("filter-placeholder", v);
5228
+ }
5229
+ get breakpoint() {
5230
+ return this.getAttr("breakpoint", "960px");
5231
+ }
5232
+ set breakpoint(v) {
5233
+ this.setAttribute("breakpoint", v);
5234
+ }
5235
+ get dragdrop() {
5236
+ return this.hasAttr("dragdrop");
5237
+ }
5238
+ set dragdrop(v) {
5239
+ this.toggleAttr("dragdrop", v);
5240
+ }
5241
+ get striped() {
5242
+ return this.hasAttr("striped");
5243
+ }
5244
+ set striped(v) {
5245
+ this.toggleAttr("striped", v);
5246
+ }
5247
+ get selectionMode() {
5248
+ const s = this.getAttr("selection-mode", "");
5249
+ return s === "single" || s === "multiple" ? s : "";
5250
+ }
5251
+ set selectionMode(v) {
5252
+ this.setAttribute("selection-mode", v);
5253
+ }
5254
+ get showSelectAll() {
5255
+ return this.hasAttr("show-select-all");
5256
+ }
5257
+ set showSelectAll(v) {
5258
+ this.toggleAttr("show-select-all", v);
5259
+ }
5260
+ get filterValue() {
5261
+ return this._filterValue;
5262
+ }
5263
+ set filterValue(v) {
5264
+ this._filterValue = v;
5265
+ this._applyFilter();
5266
+ this._updateListDisplay();
5267
+ }
5268
+ setOptionTemplate(template) {
5269
+ this._optionTemplate = template;
5270
+ this.render();
5271
+ }
5272
+ connectedCallback() {
5273
+ this._parseDataAttribute();
5274
+ super.connectedCallback();
5275
+ }
5276
+ attributeChangedCallback() {
5277
+ if (this.getAttr("data", "") !== "") {
5278
+ this._parseDataAttribute();
5279
+ }
5280
+ super.attributeChangedCallback();
5281
+ }
5282
+ _parseDataAttribute() {
5283
+ const dataAttr = this.getAttr("data", "");
5284
+ if (dataAttr) {
5285
+ try {
5286
+ this._data = JSON.parse(dataAttr);
5287
+ this._filteredData = null;
5288
+ } catch {
5289
+ this._data = [];
5290
+ }
5291
+ }
5292
+ }
5293
+ _applyFilter() {
5294
+ if (!this._filterValue) {
5295
+ this._filteredData = null;
5296
+ return;
5297
+ }
5298
+ const filterFields = this.filterBy.split(",").map((f) => f.trim());
5299
+ this._filteredData = this._data.filter((item) => {
5300
+ return filterFields.some((field) => {
5301
+ const value = item[field];
5302
+ if (value == null) return false;
5303
+ return String(value).toLowerCase().includes(this._filterValue.toLowerCase());
5304
+ });
5305
+ });
5306
+ }
5307
+ _getDisplayData() {
5308
+ return this._filteredData || this._data;
5309
+ }
5310
+ _getItemKey(item, index) {
5311
+ if (this.dataKey && item[this.dataKey] != null) {
5312
+ return String(item[this.dataKey]);
5313
+ }
5314
+ if (item["id"] != null) return String(item["id"]);
5315
+ if (item["key"] != null) return String(item["key"]);
5316
+ if (item["label"] != null) return String(item["label"]);
5317
+ if (item["name"] != null) return String(item["name"]);
5318
+ if (item["value"] != null) return String(item["value"]);
5319
+ return String(index);
5320
+ }
5321
+ _getItemLabel(item) {
5322
+ const fields = ["label", "name", "title", "text", "value"];
5323
+ for (const field of fields) {
5324
+ if (item[field] != null) {
5325
+ return String(item[field]);
5326
+ }
5327
+ }
5328
+ return JSON.stringify(item);
5329
+ }
5330
+ _isSelected(item) {
5331
+ return this._selection.some((s) => this._getItemKey(s, -1) === this._getItemKey(item, -1));
5332
+ }
5333
+ _moveItem(fromIndex, toIndex) {
5334
+ const actualFrom = this._getActualIndex(fromIndex);
5335
+ const actualTo = this._getActualIndex(toIndex);
5336
+ if (actualFrom === -1 || actualTo === -1) return;
5337
+ const item = this._data.splice(actualFrom, 1)[0];
5338
+ this._data.splice(actualTo, 0, item);
5339
+ this._applyFilter();
5340
+ this._updateListDisplay();
5341
+ this._updateControlsState();
5342
+ this._emitReorder();
5343
+ }
5344
+ _getActualIndex(displayIndex) {
5345
+ if (this._filteredData) {
5346
+ const item = this._filteredData[displayIndex];
5347
+ return this._data.findIndex((d) => this._getItemKey(d, -1) === this._getItemKey(item, -1));
5348
+ }
5349
+ return displayIndex;
5350
+ }
5351
+ _emitReorder() {
5352
+ this.dispatchEvent(new CustomEvent("reorder", {
5353
+ bubbles: true,
5354
+ composed: true,
5355
+ detail: { items: [...this._data] }
5356
+ }));
5357
+ }
5358
+ _emitSelectionChange() {
5359
+ this.dispatchEvent(new CustomEvent("selection-change", {
5360
+ bubbles: true,
5361
+ composed: true,
5362
+ detail: { selection: [...this._selection] }
5363
+ }));
5364
+ }
5365
+ _toggleSelection(item) {
5366
+ const key2 = this._getItemKey(item, -1);
5367
+ const index = this._selection.findIndex((s) => this._getItemKey(s, -1) === key2);
5368
+ if (index >= 0) {
5369
+ this._selection.splice(index, 1);
5370
+ } else if (this.selectionMode === "multiple") {
5371
+ this._selection.push(item);
5372
+ } else {
5373
+ this._selection = [item];
5374
+ }
5375
+ this._emitSelectionChange();
5376
+ this._updateListDisplay();
5377
+ this._updateControlsState();
5378
+ }
5379
+ _selectAll() {
5380
+ const displayData = this._getDisplayData();
5381
+ this._selection = [...displayData];
5382
+ this._emitSelectionChange();
5383
+ this._updateListDisplay();
5384
+ this._updateControlsState();
5385
+ }
5386
+ _deselectAll() {
5387
+ this._selection = [];
5388
+ this._emitSelectionChange();
5389
+ this._updateListDisplay();
5390
+ this._updateControlsState();
5391
+ }
5392
+ _toggleSelectAll() {
5393
+ const displayData = this._getDisplayData();
5394
+ if (this._selection.length === displayData.length) {
5395
+ this._deselectAll();
5396
+ } else {
5397
+ this._selectAll();
5398
+ }
5399
+ }
5400
+ render() {
5401
+ const displayData = this._getDisplayData();
5402
+ const hasSelection = this.selectionMode;
5403
+ const hasMultipleSelection = this.selectionMode === "multiple";
5404
+ const allSelected = hasMultipleSelection && displayData.length > 0 && this._selection.length === displayData.length;
5405
+ this.setTemplate(`
5406
+ <div class="container" part="container">
5407
+ ${this.filter ? `
5408
+ <div class="filter-wrapper" part="filter-wrapper">
5409
+ <input type="text" class="filter-input" part="filter-input"
5410
+ placeholder="${this.filterPlaceholder}"
5411
+ value="${esc$1(this._filterValue)}"
5412
+ aria-label="Filtrar lista" />
5413
+ </div>
5414
+ ` : ""}
5415
+ <div class="main-row" part="main-row">
5416
+ <div class="controls-bar" part="controls-bar">
5417
+ <div class="control-group">
5418
+ <button class="control-btn" data-action="top" part="control-btn" aria-label="Mover para o inicio">
5419
+ <span class="control-btn-icon">«</span>
5420
+ </button>
5421
+ <button class="control-btn" data-action="up" part="control-btn" aria-label="Mover para cima">
5422
+ <span class="control-btn-icon">↑</span>
5423
+ </button>
5424
+ </div>
5425
+ <div class="control-group">
5426
+ <button class="control-btn" data-action="down" part="control-btn" aria-label="Mover para baixo">
5427
+ <span class="control-btn-icon">↓</span>
5428
+ </button>
5429
+ <button class="control-btn" data-action="bottom" part="control-btn" aria-label="Mover para o fim">
5430
+ <span class="control-btn-icon">»</span>
5431
+ </button>
5432
+ </div>
5433
+ </div>
5434
+ <div class="list-wrapper" part="list-wrapper">
5435
+ ${hasMultipleSelection && this.showSelectAll ? `
5436
+ <div class="select-all-bar" part="select-all-bar">
5437
+ <label>
5438
+ <input type="checkbox" class="select-all-checkbox"
5439
+ ${allSelected ? "checked" : ""}
5440
+ aria-label="Selecionar todos" />
5441
+ Selecionar Todos
5442
+ </label>
5443
+ <span class="selection-count">${this._selection.length} selecionado(s)</span>
5444
+ </div>
5445
+ ` : ""}
5446
+ <ul class="list" part="list" role="listbox"
5447
+ aria-multiselectable="${hasMultipleSelection}"
5448
+ tabindex="0">
5449
+ ${displayData.length === 0 ? `
5450
+ <li class="empty-message" part="empty-message">
5451
+ ${this.filter ? "Nenhum resultado encontrado" : "Nenhum item disponivel"}
5452
+ </li>
5453
+ ` : displayData.map((item, index) => {
5454
+ const key2 = this._getItemKey(item, index);
5455
+ const label = this._getItemLabel(item);
5456
+ const isSelected = this._isSelected(item);
5457
+ const content = this._optionTemplate ? this._optionTemplate(item) : esc$1(label);
5458
+ return `
5459
+ <li class="list-item${isSelected ? " selected" : ""}" part="list-item"
5460
+ data-index="${index}" data-key="${esc$1(key2)}"
5461
+ role="option" aria-selected="${isSelected}"
5462
+ ${this.dragdrop ? 'draggable="true"' : ""}
5463
+ tabindex="0">
5464
+ ${this.dragdrop ? '<span class="drag-handle" part="drag-handle" aria-label="Arrastar">⋮⋮</span>' : ""}
5465
+ ${hasSelection ? `
5466
+ <input type="checkbox" class="checkbox" part="checkbox"
5467
+ ${isSelected ? "checked" : ""}
5468
+ aria-label="Selecionar ${esc$1(label)}" />
5469
+ ` : ""}
5470
+ <span class="item-content" part="item-content">${content}</span>
5471
+ </li>
5472
+ `;
5473
+ }).join("")}
5474
+ </ul>
5475
+ </div>
5476
+ </div>
5477
+ </div>
5478
+ `);
5479
+ this._attachListeners();
5480
+ this._attachItemListeners(this.root.querySelector(".list"));
5481
+ this._updateControlsState();
5482
+ }
5483
+ _attachListeners() {
5484
+ if (this._listenersAttached) return;
5485
+ this._listenersAttached = true;
5486
+ const root = this.root;
5487
+ root.addEventListener("input", (e) => {
5488
+ const t = e.target;
5489
+ if (t.classList.contains("filter-input")) {
5490
+ this.filterValue = t.value;
5491
+ }
5492
+ });
5493
+ root.addEventListener("change", (e) => {
5494
+ const t = e.target;
5495
+ if (t.classList.contains("select-all-checkbox")) {
5496
+ this._toggleSelectAll();
5497
+ }
5498
+ });
5499
+ root.addEventListener("click", (e) => {
5500
+ const target = e.target;
5501
+ const btn = target.closest(".control-btn");
5502
+ if (btn) {
5503
+ this._handleMoveAction(btn.dataset.action);
5504
+ }
5505
+ });
5506
+ let dragOverElement = null;
5507
+ root.addEventListener("dragstart", (e) => {
5508
+ const target = e.target.closest(".list-item");
5509
+ if (!target) return;
5510
+ this._draggedIndex = Number(target.dataset.index);
5511
+ target.classList.add("dragging");
5512
+ e.dataTransfer.effectAllowed = "move";
5513
+ });
5514
+ root.addEventListener("dragend", (e) => {
5515
+ const target = e.target;
5516
+ target.classList.remove("dragging");
5517
+ this._draggedIndex = null;
5518
+ root.querySelectorAll(".drag-over").forEach((el) => el.classList.remove("drag-over"));
5519
+ dragOverElement = null;
5520
+ });
5521
+ root.addEventListener("dragover", (e) => {
5522
+ e.preventDefault();
5523
+ const target = e.target.closest(".list-item");
5524
+ if (!target || target.classList.contains("dragging")) return;
5525
+ if (dragOverElement) dragOverElement.classList.remove("drag-over");
5526
+ target.classList.add("drag-over");
5527
+ dragOverElement = target;
5528
+ });
5529
+ root.addEventListener("drop", (e) => {
5530
+ e.preventDefault();
5531
+ if (this._draggedIndex === null) return;
5532
+ const target = e.target.closest(".list-item");
5533
+ if (!target) return;
5534
+ const toIndex = Number(target.dataset.index);
5535
+ target.classList.remove("drag-over");
5536
+ dragOverElement = null;
5537
+ this._moveItem(this._draggedIndex, toIndex);
5538
+ this._draggedIndex = null;
5539
+ });
5540
+ this._updateControlsState();
5541
+ }
5542
+ _attachItemListeners(list) {
5543
+ if (!list) return;
5544
+ list.addEventListener("click", (e) => {
5545
+ const target = e.target;
5546
+ const itemEl = target.closest(".list-item");
5547
+ if (!itemEl) return;
5548
+ if (target.classList.contains("checkbox")) {
5549
+ e.stopPropagation();
5550
+ const idxC = Number(itemEl.dataset.index);
5551
+ this._toggleSelection(this._getDisplayData()[idxC]);
5552
+ return;
5553
+ }
5554
+ const idxI = Number(itemEl.dataset.index);
5555
+ this._toggleSelection(this._getDisplayData()[idxI]);
5556
+ });
5557
+ list.addEventListener("keydown", (e) => {
5558
+ const target = e.target;
5559
+ if (!target.classList.contains("list-item")) return;
5560
+ const items = Array.from(list.querySelectorAll(".list-item"));
5561
+ const currentIndex = items.indexOf(target);
5562
+ const ke = e;
5563
+ switch (ke.key) {
5564
+ case "ArrowUp":
5565
+ e.preventDefault();
5566
+ if (currentIndex > 0) items[currentIndex - 1].focus();
5567
+ break;
5568
+ case "ArrowDown":
5569
+ e.preventDefault();
5570
+ if (currentIndex < items.length - 1) items[currentIndex + 1].focus();
5571
+ break;
5572
+ case " ":
5573
+ case "Enter":
5574
+ e.preventDefault();
5575
+ if (this.selectionMode) {
5576
+ const index = Number(target.dataset.index);
5577
+ this._toggleSelection(this._getDisplayData()[index]);
5578
+ }
5579
+ break;
5580
+ }
5581
+ });
5582
+ }
5583
+ _updateListDisplay() {
5584
+ const listWrapper = this.root.querySelector(".list-wrapper");
5585
+ if (!listWrapper) {
5586
+ this.render();
5587
+ return;
5588
+ }
5589
+ const displayData = this._getDisplayData();
5590
+ const hasSelection = this.selectionMode;
5591
+ const hasMultipleSelection = this.selectionMode === "multiple";
5592
+ const allSelected = hasMultipleSelection && displayData.length > 0 && this._selection.length === displayData.length;
5593
+ listWrapper.innerHTML = `
5594
+ ${hasMultipleSelection && this.showSelectAll ? `
5595
+ <div class="select-all-bar" part="select-all-bar">
5596
+ <label>
5597
+ <input type="checkbox" class="select-all-checkbox"
5598
+ ${allSelected ? "checked" : ""}
5599
+ aria-label="Selecionar todos" />
5600
+ Selecionar Todos
5601
+ </label>
5602
+ <span class="selection-count">${this._selection.length} selecionado(s)</span>
5603
+ </div>
5604
+ ` : ""}
5605
+ <ul class="list" part="list" role="listbox"
5606
+ aria-multiselectable="${hasMultipleSelection}"
5607
+ tabindex="0">
5608
+ ${displayData.length === 0 ? `
5609
+ <li class="empty-message" part="empty-message">
5610
+ ${this.filter ? "Nenhum resultado encontrado" : "Nenhum item disponivel"}
5611
+ </li>
5612
+ ` : displayData.map((item, index) => {
5613
+ const key2 = this._getItemKey(item, index);
5614
+ const label = this._getItemLabel(item);
5615
+ const isSelected = this._isSelected(item);
5616
+ const content = this._optionTemplate ? this._optionTemplate(item) : esc$1(label);
5617
+ return `
5618
+ <li class="list-item${isSelected ? " selected" : ""}" part="list-item"
5619
+ data-index="${index}" data-key="${esc$1(key2)}"
5620
+ role="option" aria-selected="${isSelected}"
5621
+ ${this.dragdrop ? 'draggable="true"' : ""}
5622
+ tabindex="0">
5623
+ ${this.dragdrop ? '<span class="drag-handle" part="drag-handle" aria-label="Arrastar">⋮⋮</span>' : ""}
5624
+ ${hasSelection ? `
5625
+ <input type="checkbox" class="checkbox" part="checkbox"
5626
+ ${isSelected ? "checked" : ""}
5627
+ aria-label="Selecionar ${esc$1(label)}" />
5628
+ ` : ""}
5629
+ <span class="item-content" part="item-content">${content}</span>
5630
+ </li>
5631
+ `;
5632
+ }).join("")}
5633
+ </ul>
5634
+ `;
5635
+ this._attachListeners();
5636
+ this._attachItemListeners(this.root.querySelector(".list"));
5637
+ }
5638
+ _handleMoveAction(action) {
5639
+ if (!this._selection.length) return;
5640
+ const displayData = this._getDisplayData();
5641
+ 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);
5642
+ if (selectedIndices.length === 0) return;
5643
+ switch (action) {
5644
+ case "top":
5645
+ this._moveSelectedToStart(selectedIndices);
5646
+ break;
5647
+ case "up":
5648
+ this._moveSelectedByOne(selectedIndices, -1);
5649
+ break;
5650
+ case "down":
5651
+ this._moveSelectedByOne(selectedIndices, 1);
5652
+ break;
5653
+ case "bottom":
5654
+ this._moveSelectedToEnd(selectedIndices);
5655
+ break;
5656
+ }
5657
+ }
5658
+ _moveSelectedToStart(indices) {
5659
+ const items = [];
5660
+ const actualIndices = [];
5661
+ for (const idx of indices) {
5662
+ const actualIdx = this._getActualIndex(idx);
5663
+ items.push(this._data[actualIdx]);
5664
+ actualIndices.push(actualIdx);
5665
+ }
5666
+ actualIndices.sort((a, b) => b - a).forEach((i) => this._data.splice(i, 1));
5667
+ const insertIdx = this._getActualIndex(0);
5668
+ this._data.splice(insertIdx, 0, ...items);
5669
+ this._applyFilter();
5670
+ this._updateListDisplay();
5671
+ this._updateControlsState();
5672
+ this._emitReorder();
5673
+ }
5674
+ _moveSelectedToEnd(indices) {
5675
+ const items = [];
5676
+ const actualIndices = [];
5677
+ for (const idx of indices) {
5678
+ const actualIdx = this._getActualIndex(idx);
5679
+ items.push(this._data[actualIdx]);
5680
+ actualIndices.push(actualIdx);
5681
+ }
5682
+ actualIndices.sort((a, b) => b - a).forEach((i) => this._data.splice(i, 1));
5683
+ const displayData = this._getDisplayData();
5684
+ const insertIdx = this._getActualIndex(displayData.length - 1);
5685
+ this._data.splice(insertIdx + 1, 0, ...items);
5686
+ this._applyFilter();
5687
+ this._updateListDisplay();
5688
+ this._updateControlsState();
5689
+ this._emitReorder();
5690
+ }
5691
+ _moveSelectedByOne(indices, delta) {
5692
+ const displayData = this._getDisplayData();
5693
+ if (displayData.length === 0) return;
5694
+ const actualIndices = indices.map((idx) => this._getActualIndex(idx)).filter((idx) => idx >= 0).sort((a, b) => a - b);
5695
+ if (actualIndices.length === 0) return;
5696
+ if (delta < 0 && actualIndices[0] <= 0) return;
5697
+ if (delta > 0 && actualIndices[actualIndices.length - 1] >= this._data.length - 1) return;
5698
+ const selectedItems = actualIndices.map((idx) => this._data[idx]);
5699
+ for (let i = actualIndices.length - 1; i >= 0; i--) {
5700
+ this._data.splice(actualIndices[i], 1);
5701
+ }
5702
+ let insertIndex;
5703
+ if (delta < 0) {
5704
+ insertIndex = actualIndices[0] - 1;
5705
+ } else {
5706
+ insertIndex = actualIndices[actualIndices.length - 1] - actualIndices.length + 1 + 1;
5707
+ }
5708
+ insertIndex = Math.max(0, Math.min(insertIndex, this._data.length));
5709
+ this._data.splice(insertIndex, 0, ...selectedItems);
5710
+ this._applyFilter();
5711
+ this._updateListDisplay();
5712
+ this._updateControlsState();
5713
+ this._emitReorder();
5714
+ }
5715
+ _updateControlsState() {
5716
+ const displayData = this._getDisplayData();
5717
+ const selectedIndices = this._selection.map((s) => displayData.findIndex((d) => this._getItemKey(d, -1) === this._getItemKey(s, -1))).filter((i) => i >= 0);
5718
+ const buttons = this.root.querySelectorAll(".control-btn");
5719
+ buttons.forEach((btn) => {
5720
+ const action = btn.dataset.action;
5721
+ let disabled = selectedIndices.length === 0;
5722
+ if (!disabled) {
5723
+ switch (action) {
5724
+ case "top":
5725
+ case "up":
5726
+ disabled = selectedIndices[0] === 0;
5727
+ break;
5728
+ case "bottom":
5729
+ case "down":
5730
+ disabled = selectedIndices[selectedIndices.length - 1] === displayData.length - 1;
5731
+ break;
5732
+ }
5733
+ }
5734
+ btn.disabled = disabled;
5735
+ });
5736
+ }
5737
+ };
5738
+ _FxOrderList.styles = css`
5739
+
5740
+ :host {
5741
+ display: block;
5742
+ font-family: var(--fx-font-family);
5743
+ font-size: var(--fx-font-size);
5744
+ --orderlist-primary: var(--fx-color-primary, #3b82f6);
5745
+ --orderlist-border: var(--fx-border-default, #e2e8f0);
5746
+ --orderlist-bg: var(--fx-surface-background, #ffffff);
5747
+ --orderlist-bg-hover: var(--fx-surface-surface-hover, #f1f5f9);
5748
+ --orderlist-text: var(--fx-text-default, #1e293b);
5749
+ --orderlist-text-muted: var(--fx-text-muted, #64748b);
5750
+ --orderlist-radius: var(--fx-radius-md, 8px);
5751
+ --orderlist-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
5752
+ --orderlist-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
5753
+ }
5754
+ * { box-sizing: border-box; }
5755
+ .container { display: flex; flex-direction: column; gap: var(--fx-space-md, 16px); }
5756
+ .list-wrapper { display: flex; flex-direction: column; gap: var(--fx-space-sm, 8px); flex: 1; min-width: 0; }
5757
+ .select-all-bar { display: flex; align-items: center; justify-content: space-between; padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px); background: linear-gradient(135deg, var(--orderlist-bg), var(--orderlist-bg-hover)); border: 1px solid var(--orderlist-border); border-radius: var(--orderlist-radius); font-size: 0.9em; font-weight: 500; }
5758
+ .select-all-bar label { display: flex; align-items: center; gap: var(--fx-space-sm, 10px); cursor: pointer; user-select: none; color: var(--orderlist-text); }
5759
+ .select-all-bar input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--orderlist-primary); cursor: pointer; }
5760
+ .filter-wrapper { margin-bottom: var(--fx-space-xs, 4px); }
5761
+ .filter-input { width: 100%; padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px); padding-left: 42px; border: 1.5px solid var(--orderlist-border); border-radius: var(--orderlist-radius); font-family: inherit; font-size: inherit; color: var(--orderlist-text); background: var(--orderlist-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E") no-repeat 14px center; transition: var(--orderlist-transition); }
5762
+ .filter-input:focus { outline: none; border-color: var(--orderlist-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--orderlist-primary) 20%, transparent); }
5763
+ .filter-input::placeholder { color: var(--orderlist-text-muted); }
5764
+ .main-row { display: flex; align-items: stretch; gap: var(--fx-space-sm, 8px); }
5765
+ .list { list-style: none; margin: 0; padding: 0; border: 1px solid var(--orderlist-border); border-radius: var(--orderlist-radius); overflow: hidden; box-shadow: var(--orderlist-shadow); max-height: 450px; overflow-y: auto; flex: 1; }
5766
+ .list::-webkit-scrollbar { width: 6px; }
5767
+ .list::-webkit-scrollbar-track { background: transparent; }
5768
+ .list::-webkit-scrollbar-thumb { background: var(--orderlist-border); border-radius: 3px; }
5769
+ .list::-webkit-scrollbar-thumb:hover { background: var(--orderlist-text-muted); }
5770
+ .selection-count { font-size: 0.85em; color: var(--orderlist-primary); background: color-mix(in srgb, var(--orderlist-primary) 12%, transparent); padding: 4px 12px; border-radius: 20px; font-weight: 600; }
5771
+ :host([striped]) .list-item:nth-child(even) { background: var(--fx-surface-surface, #f8fafc); }
5772
+ .list-item { display: flex; align-items: center; gap: var(--fx-space-sm, 10px); padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px); background: var(--orderlist-bg); border-bottom: 1px solid var(--orderlist-border); cursor: pointer; user-select: none; transition: var(--orderlist-transition); }
5773
+ .list-item:last-child { border-bottom: none; }
5774
+ .list-item:hover { background: var(--orderlist-bg-hover); }
5775
+ .list-item.selected { background: color-mix(in srgb, var(--orderlist-primary) 8%, transparent); border-left: 3px solid var(--orderlist-primary); padding-left: 11px; }
5776
+ .list-item:focus-visible { outline: none; background: color-mix(in srgb, var(--orderlist-primary) 15%, transparent); }
5777
+ .list-item.dragging { opacity: 0.5; background: var(--orderlist-bg-hover); }
5778
+ .list-item.drag-over { border-top: 2px solid var(--orderlist-primary); }
5779
+ .drag-handle { color: var(--orderlist-text-muted); cursor: grab; flex-shrink: 0; font-size: 1.2em; opacity: 0.6; transition: var(--orderlist-transition); }
5780
+ .drag-handle:hover { opacity: 1; }
5781
+ .drag-handle:active { cursor: grabbing; }
5782
+ .item-content { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
5783
+ .checkbox { flex-shrink: 0; width: 18px; height: 18px; accent-color: var(--orderlist-primary); cursor: pointer; transition: var(--orderlist-transition); }
5784
+ .checkbox:hover { transform: scale(1.1); }
5785
+ .empty-message { padding: var(--fx-space-xl, 32px); text-align: center; color: var(--orderlist-text-muted); font-style: italic; }
5786
+ .controls-bar {
5787
+ display: flex;
5788
+ flex-direction: column;
5789
+ gap: 4px;
5790
+ padding: var(--fx-space-xs, 6px);
5791
+ background: var(--orderlist-bg);
5792
+ border: 1px solid var(--orderlist-border);
5793
+ border-radius: var(--orderlist-radius);
5794
+ box-shadow: var(--orderlist-shadow);
5795
+ height: fit-content;
5796
+ position: sticky;
5797
+ top: 0;
5798
+ align-self: flex-start;
5799
+ }
5800
+ .control-group { display: flex; flex-direction: column; gap: 3px; }
5801
+ .control-group + .control-group { margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--orderlist-border); }
5802
+ button.control-btn { display: flex; align-items: center; justify-content: center; width: 42px; height: 38px; padding: 0; border: none; border-radius: 8px; background: transparent; color: var(--orderlist-text-muted); cursor: pointer; font-size: 16px; line-height: 1; transition: var(--orderlist-transition); position: relative; }
5803
+ button.control-btn:hover:not(:disabled) { background: var(--orderlist-bg-hover); color: var(--orderlist-primary); transform: scale(1.1); }
5804
+ button.control-btn:active:not(:disabled) { transform: scale(0.92); background: color-mix(in srgb, var(--orderlist-primary) 15%, transparent); }
5805
+ button.control-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--orderlist-primary) 30%, transparent); }
5806
+ button.control-btn:disabled { opacity: 0.3; cursor: not-allowed; transform: none; }
5807
+ .control-btn-icon { font-size: 18px; line-height: 1; }
5808
+ /* Tooltip nos botoes */
5809
+ button.control-btn:hover::after { opacity: 1; transform: translateY(-50%) translateX(0); }
5810
+ @media (max-width: 640px) { .main-row { flex-direction: column; } .controls-bar { flex-direction: row; flex-wrap: wrap; justify-content: center; position: relative; } .control-group { flex-direction: row; } .control-group + .control-group { margin-top: 0; margin-left: 4px; padding-top: 0; padding-left: 4px; border-top: none; border-left: 1px solid var(--orderlist-border); } button.control-btn { width: 44px; height: 40px; } button.control-btn::after { display: none; } .list { max-height: 300px; } }
5811
+ @keyframes slideIn { from { opacity: 0; transform: translateX(-10px); } to { opacity: 1; transform: translateX(0); } }
5812
+ .list-item { animation: slideIn 0.2s ease-out; }
5813
+ @media (prefers-color-scheme: light) { :host { --orderlist-border: #334155; --orderlist-bg: #1e293b; --orderlist-bg-hover: #334155; --orderlist-text: #f1f5f9; --orderlist-text-muted: #94a3b8; --orderlist-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); } }
5814
+ `;
5815
+ let FxOrderList = _FxOrderList;
5816
+ function esc$1(s) {
5817
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
5818
+ }
5819
+ function defineFxOrderList() {
5820
+ return defineElement("fx-orderlist", FxOrderList);
5821
+ }
5822
+ defineFxOrderList();
5823
+ const _FxPickList = class _FxPickList extends FxElement {
5824
+ constructor() {
5825
+ super(...arguments);
5826
+ this._source = [];
5827
+ this._filteredSource = null;
5828
+ this._target = [];
5829
+ this._filteredTarget = null;
5830
+ this._sourceSelection = [];
5831
+ this._targetSelection = [];
5832
+ this._sourceFilterValue = "";
5833
+ this._targetFilterValue = "";
5834
+ this._filterListenersAttached = false;
5835
+ this._optionTemplate = null;
5836
+ }
5837
+ static get observedAttributes() {
5838
+ return [
5839
+ "source",
5840
+ "target",
5841
+ "source-key",
5842
+ "target-key",
5843
+ "filter",
5844
+ "filter-by",
5845
+ "filter-placeholder",
5846
+ "dragdrop",
5847
+ "striped",
5848
+ "selection-mode",
5849
+ "show-select-all",
5850
+ "source-label",
5851
+ "target-label"
5852
+ ];
5853
+ }
5854
+ set source(value) {
5855
+ this._source = value;
5856
+ this._filteredSource = null;
5857
+ this.render();
5858
+ }
5859
+ get source() {
5860
+ return this._source;
5861
+ }
5862
+ set target(value) {
5863
+ this._target = value;
5864
+ this._filteredTarget = null;
5865
+ this.render();
5866
+ }
5867
+ get target() {
5868
+ return this._target;
5869
+ }
5870
+ set sourceSelection(value) {
5871
+ this._sourceSelection = value;
5872
+ this.render();
5873
+ }
5874
+ get sourceSelection() {
5875
+ return this._sourceSelection;
5876
+ }
5877
+ set targetSelection(value) {
5878
+ this._targetSelection = value;
5879
+ this.render();
5880
+ }
5881
+ get targetSelection() {
5882
+ return this._targetSelection;
5883
+ }
5884
+ get sourceKey() {
5885
+ return this.getAttr("source-key", "");
5886
+ }
5887
+ set sourceKey(v) {
5888
+ this.setAttribute("source-key", v);
5889
+ }
5890
+ get targetKey() {
5891
+ return this.getAttr("target-key", "");
5892
+ }
5893
+ set targetKey(v) {
5894
+ this.setAttribute("target-key", v);
5895
+ }
5896
+ get filter() {
5897
+ return this.hasAttr("filter");
5898
+ }
5899
+ set filter(v) {
5900
+ this.toggleAttr("filter", v);
5901
+ }
5902
+ get filterBy() {
5903
+ return this.getAttr("filter-by", "label");
5904
+ }
5905
+ set filterBy(v) {
5906
+ this.setAttribute("filter-by", v);
5907
+ }
5908
+ get filterPlaceholder() {
5909
+ return this.getAttr("filter-placeholder", "Buscar...");
5910
+ }
5911
+ set filterPlaceholder(v) {
5912
+ this.setAttribute("filter-placeholder", v);
5913
+ }
5914
+ get dragdrop() {
5915
+ return this.hasAttr("dragdrop");
5916
+ }
5917
+ set dragdrop(v) {
5918
+ this.toggleAttr("dragdrop", v);
5919
+ }
5920
+ get striped() {
5921
+ return this.hasAttr("striped");
5922
+ }
5923
+ set striped(v) {
5924
+ this.toggleAttr("striped", v);
5925
+ }
5926
+ get selectionMode() {
5927
+ const s = this.getAttr("selection-mode", "");
5928
+ return s === "single" || s === "multiple" ? s : "";
5929
+ }
5930
+ set selectionMode(v) {
5931
+ this.setAttribute("selection-mode", v);
5932
+ }
5933
+ get showSelectAll() {
5934
+ return this.hasAttr("show-select-all");
5935
+ }
5936
+ set showSelectAll(v) {
5937
+ this.toggleAttr("show-select-all", v);
5938
+ }
5939
+ get sourceLabel() {
5940
+ return this.getAttr("source-label", "Disponíveis");
5941
+ }
5942
+ set sourceLabel(v) {
5943
+ this.setAttribute("source-label", v);
5944
+ }
5945
+ get targetLabel() {
5946
+ return this.getAttr("target-label", "Selecionados");
5947
+ }
5948
+ set targetLabel(v) {
5949
+ this.setAttribute("target-label", v);
5950
+ }
5951
+ get sourceFilterValue() {
5952
+ return this._sourceFilterValue;
5953
+ }
5954
+ set sourceFilterValue(v) {
5955
+ this._sourceFilterValue = v;
5956
+ this._applySourceFilter();
5957
+ this._updateListDisplay();
5958
+ }
5959
+ get targetFilterValue() {
5960
+ return this._targetFilterValue;
5961
+ }
5962
+ set targetFilterValue(v) {
5963
+ this._targetFilterValue = v;
5964
+ this._applyTargetFilter();
5965
+ this._updateListDisplay();
5966
+ }
5967
+ setOptionTemplate(template) {
5968
+ this._optionTemplate = template;
5969
+ this.render();
5970
+ }
5971
+ connectedCallback() {
5972
+ this._parseSourceAttribute();
5973
+ this._parseTargetAttribute();
5974
+ super.connectedCallback();
5975
+ }
5976
+ attributeChangedCallback() {
5977
+ if (this.getAttr("source", "") !== "") {
5978
+ this._parseSourceAttribute();
5979
+ }
5980
+ if (this.getAttr("target", "") !== "") {
5981
+ this._parseTargetAttribute();
5982
+ }
5983
+ super.attributeChangedCallback();
5984
+ }
5985
+ _parseSourceAttribute() {
5986
+ const dataAttr = this.getAttr("source", "");
5987
+ if (dataAttr) {
5988
+ try {
5989
+ this._source = JSON.parse(dataAttr);
5990
+ this._filteredSource = null;
5991
+ } catch {
5992
+ this._source = [];
5993
+ }
5994
+ }
5995
+ }
5996
+ _parseTargetAttribute() {
5997
+ const dataAttr = this.getAttr("target", "");
5998
+ if (dataAttr) {
5999
+ try {
6000
+ this._target = JSON.parse(dataAttr);
6001
+ this._filteredTarget = null;
6002
+ } catch {
6003
+ this._target = [];
6004
+ }
6005
+ }
6006
+ }
6007
+ _applySourceFilter() {
6008
+ if (!this._sourceFilterValue) {
6009
+ this._filteredSource = null;
6010
+ return;
6011
+ }
6012
+ const filterFields = this.filterBy.split(",").map((f) => f.trim());
6013
+ this._filteredSource = this._source.filter((item) => {
6014
+ return filterFields.some((field) => {
6015
+ const value = item[field];
6016
+ if (value == null) return false;
6017
+ return String(value).toLowerCase().includes(this._sourceFilterValue.toLowerCase());
6018
+ });
6019
+ });
6020
+ }
6021
+ _applyTargetFilter() {
6022
+ if (!this._targetFilterValue) {
6023
+ this._filteredTarget = null;
6024
+ return;
6025
+ }
6026
+ const filterFields = this.filterBy.split(",").map((f) => f.trim());
6027
+ this._filteredTarget = this._target.filter((item) => {
6028
+ return filterFields.some((field) => {
6029
+ const value = item[field];
6030
+ if (value == null) return false;
6031
+ return String(value).toLowerCase().includes(this._targetFilterValue.toLowerCase());
6032
+ });
6033
+ });
6034
+ }
6035
+ _getDisplaySource() {
6036
+ return this._filteredSource || this._source;
6037
+ }
6038
+ _getDisplayTarget() {
6039
+ return this._filteredTarget || this._target;
6040
+ }
6041
+ _getItemKey(item, index, isSource) {
6042
+ const keyField = isSource ? this.sourceKey : this.targetKey;
6043
+ if (keyField && item[keyField] != null) {
6044
+ return String(item[keyField]);
6045
+ }
6046
+ if (item["id"] != null) return String(item["id"]);
6047
+ if (item["key"] != null) return String(item["key"]);
6048
+ if (item["label"] != null) return String(item["label"]);
6049
+ if (item["name"] != null) return String(item["name"]);
6050
+ if (item["value"] != null) return String(item["value"]);
6051
+ return String(index);
6052
+ }
6053
+ _getItemLabel(item) {
6054
+ const fields = ["label", "name", "title", "text", "value"];
6055
+ for (const field of fields) {
6056
+ if (item[field] != null) {
6057
+ return String(item[field]);
6058
+ }
6059
+ }
6060
+ return JSON.stringify(item);
6061
+ }
6062
+ _isSourceSelected(item, index) {
6063
+ return this._sourceSelection.some((s) => this._getItemKey(s, -1, true) === this._getItemKey(item, index, true));
6064
+ }
6065
+ _isTargetSelected(item, index) {
6066
+ return this._targetSelection.some((s) => this._getItemKey(s, -1, false) === this._getItemKey(item, index, false));
6067
+ }
6068
+ _emitMoveToTarget() {
6069
+ this.dispatchEvent(new CustomEvent("move-to-target", {
6070
+ bubbles: true,
6071
+ composed: true,
6072
+ detail: { items: [...this._sourceSelection], source: [...this._source], target: [...this._target] }
6073
+ }));
6074
+ }
6075
+ _emitMoveToSource() {
6076
+ this.dispatchEvent(new CustomEvent("move-to-source", {
6077
+ bubbles: true,
6078
+ composed: true,
6079
+ detail: { items: [...this._targetSelection], source: [...this._source], target: [...this._target] }
6080
+ }));
6081
+ }
6082
+ _emitSelectionChangeSource() {
6083
+ this.dispatchEvent(new CustomEvent("selection-change-source", {
6084
+ bubbles: true,
6085
+ composed: true,
6086
+ detail: { selection: [...this._sourceSelection] }
6087
+ }));
6088
+ }
6089
+ _emitSelectionChangeTarget() {
6090
+ this.dispatchEvent(new CustomEvent("selection-change-target", {
6091
+ bubbles: true,
6092
+ composed: true,
6093
+ detail: { selection: [...this._targetSelection] }
6094
+ }));
6095
+ }
6096
+ render() {
6097
+ const dSrc = this._getDisplaySource();
6098
+ const dTgt = this._getDisplayTarget();
6099
+ const hasSel = this.selectionMode;
6100
+ const showAll = hasSel === "multiple" && this.showSelectAll;
6101
+ const srcItems = dSrc.length === 0 ? `<li class="empty-message">${this.filter ? "Nenhum resultado" : "Nenhum item"}</li>` : dSrc.map((item, i) => `<li class="list-item${this._isSourceSelected(item, i) ? " selected" : ""}" data-index="${i}" data-list="source" tabindex="0">${hasSel ? '<input type="checkbox" class="checkbox"' + (this._isSourceSelected(item, i) ? " checked" : "") + " />" : ""}<span class="item-content">${this._optionTemplate ? this._optionTemplate(item) : esc(this._getItemLabel(item))}</span></li>`).join("");
6102
+ const tgtItems = dTgt.length === 0 ? `<li class="empty-message">${this.filter ? "Nenhum resultado" : "Nenhum selecionado"}</li>` : dTgt.map((item, i) => `<li class="list-item${this._isTargetSelected(item, i) ? " selected" : ""}" data-index="${i}" data-list="target" tabindex="0">${hasSel ? '<input type="checkbox" class="checkbox"' + (this._isTargetSelected(item, i) ? " checked" : "") + " />" : ""}<span class="item-content">${this._optionTemplate ? this._optionTemplate(item) : esc(this._getItemLabel(item))}</span></li>`).join("");
6103
+ const srcAllBar = showAll ? `<div class="select-all-bar" part="select-all-bar"><label><input type="checkbox" class="select-all-checkbox" data-list="source" ${this._sourceSelection.length > 0 && this._sourceSelection.length === this._source.length ? "checked" : ""} aria-label="Selecionar todos da origem" /> Selecionar Todos</label><span class="selection-count">${this._sourceSelection.length} selecionado(s)</span></div>` : "";
6104
+ const tgtAllBar = showAll ? `<div class="select-all-bar" part="select-all-bar"><label><input type="checkbox" class="select-all-checkbox" data-list="target" ${this._targetSelection.length > 0 && this._targetSelection.length === this._target.length ? "checked" : ""} aria-label="Selecionar todos do destino" /> Selecionar Todos</label><span class="selection-count">${this._targetSelection.length} selecionado(s)</span></div>` : "";
6105
+ this.setTemplate(`<div class="container"><div class="list-container"><div class="list-label">${esc(this.sourceLabel)} (${this._source.length})</div>${this.filter ? '<div class="filter-wrapper"><input type="text" class="filter-input source-filter" placeholder="' + this.filterPlaceholder + '" value="' + esc(this._sourceFilterValue) + '" /></div>' : ""}${srcAllBar}<div class="list-wrapper"><ul class="list source-list" role="listbox" tabindex="0">${srcItems}</ul></div></div><div class="controls"><div class="control-group"><button class="control-btn" data-action="move-all-target" part="control-btn" aria-label="Mover todos para destino"><span class="control-btn-icon">»</span></button><button class="control-btn" data-action="move-target" part="control-btn" aria-label="Mover para destino"><span class="control-btn-icon">→</span></button></div><div class="control-group"><button class="control-btn" data-action="move-source" part="control-btn" aria-label="Mover para origem"><span class="control-btn-icon">←</span></button><button class="control-btn" data-action="move-all-source" part="control-btn" aria-label="Mover todos para origem"><span class="control-btn-icon">«</span></button></div></div><div class="list-container"><div class="list-label">${esc(this.targetLabel)} (${this._target.length})</div>${this.filter ? '<div class="filter-wrapper"><input type="text" class="filter-input target-filter" placeholder="' + this.filterPlaceholder + '" value="' + esc(this._targetFilterValue) + '" /></div>' : ""}${tgtAllBar}<div class="list-wrapper"><ul class="list target-list" role="listbox" tabindex="0">${tgtItems}</ul></div></div></div>`);
6106
+ this._attachListeners();
6107
+ }
6108
+ _attachListeners() {
6109
+ if (!this._filterListenersAttached) {
6110
+ this._filterListenersAttached = true;
6111
+ this.root.addEventListener("input", (e) => {
6112
+ const t = e.target;
6113
+ if (t.classList.contains("select-all-checkbox")) {
6114
+ this._handleSelectAll(t);
6115
+ return;
6116
+ }
6117
+ if (t.classList.contains("source-filter")) {
6118
+ this.sourceFilterValue = t.value;
6119
+ } else if (t.classList.contains("target-filter")) {
6120
+ this.targetFilterValue = t.value;
6121
+ }
6122
+ });
6123
+ this.root.addEventListener("click", (e) => {
6124
+ const t = e.target;
6125
+ const btn = t.closest(".control-btn");
6126
+ if (btn) {
6127
+ switch (btn.dataset.action) {
6128
+ case "move-target":
6129
+ this._moveToTarget();
6130
+ break;
6131
+ case "move-all-target":
6132
+ this._moveAllToTarget();
6133
+ break;
6134
+ case "move-source":
6135
+ this._moveToSource();
6136
+ break;
6137
+ case "move-all-source":
6138
+ this._moveAllToSource();
6139
+ break;
6140
+ }
6141
+ return;
6142
+ }
6143
+ const el = t.closest(".list-item");
6144
+ if (!el) return;
6145
+ const isSrc = el.dataset.list === "source";
6146
+ const idx = Number(el.dataset.index);
6147
+ const item = (isSrc ? this._getDisplaySource() : this._getDisplayTarget())[idx];
6148
+ if (isSrc) this._toggleSourceSelection(item, idx);
6149
+ else this._toggleTargetSelection(item, idx);
6150
+ });
6151
+ }
6152
+ this._updateControlsState();
6153
+ }
6154
+ _handleSelectAll(checkbox) {
6155
+ const isSrc = checkbox.dataset.list === "source";
6156
+ if (isSrc) {
6157
+ this._sourceSelection = checkbox.checked ? [...this._getDisplaySource()] : [];
6158
+ this._emitSelectionChangeSource();
6159
+ } else {
6160
+ this._targetSelection = checkbox.checked ? [...this._getDisplayTarget()] : [];
6161
+ this._emitSelectionChangeTarget();
6162
+ }
6163
+ this._updateSelectionDisplay();
6164
+ this._updateControlsState();
6165
+ }
6166
+ /**
6167
+ * Atualiza a selecao visual in-place (classes e checkboxes dos itens existentes),
6168
+ * sem recriar o DOM — mantendo referencias de elementos validas durante cliques.
6169
+ */
6170
+ _updateSelectionDisplay() {
6171
+ const updateList = (listSel, isSelFn, getData) => {
6172
+ if (!listSel) return;
6173
+ listSel.querySelectorAll(".list-item").forEach((el) => {
6174
+ const idx = Number(el.dataset.index);
6175
+ const selected = isSelFn(getData()[idx], idx);
6176
+ el.classList.toggle("selected", selected);
6177
+ el.setAttribute("aria-selected", String(selected));
6178
+ const cb = el.querySelector(".checkbox");
6179
+ if (cb) cb.checked = selected;
6180
+ });
6181
+ };
6182
+ updateList(this.root.querySelector(".source-list"), (it, i) => this._isSourceSelected(it, i), () => this._getDisplaySource());
6183
+ updateList(this.root.querySelector(".target-list"), (it, i) => this._isTargetSelected(it, i), () => this._getDisplayTarget());
6184
+ this._updateSelectAllBars();
6185
+ }
6186
+ /** Sincroniza as barras "Selecionar Todos" (checkbox + contador) sem re-render completo. */
6187
+ _updateSelectAllBars() {
6188
+ if (!(this.selectionMode === "multiple" && this.showSelectAll)) return;
6189
+ const bars = [
6190
+ { el: this.root.querySelector('.select-all-checkbox[data-list="source"]'), total: this._source.length, sel: this._sourceSelection.length },
6191
+ { el: this.root.querySelector('.select-all-checkbox[data-list="target"]'), total: this._target.length, sel: this._targetSelection.length }
6192
+ ];
6193
+ bars.forEach(({ el, total, sel }) => {
6194
+ if (!el) return;
6195
+ el.checked = total > 0 && sel === total;
6196
+ const count = el.closest(".select-all-bar")?.querySelector(".selection-count");
6197
+ if (count) count.textContent = `${sel} selecionado(s)`;
6198
+ });
6199
+ }
6200
+ _updateControlsState() {
6201
+ this.root.querySelectorAll(".control-btn").forEach((btn) => {
6202
+ const a = btn.dataset.action;
6203
+ btn.disabled = a === "move-target" && this._sourceSelection.length === 0 || a === "move-all-target" && this._source.length === 0 || a === "move-source" && this._targetSelection.length === 0 || a === "move-all-source" && this._target.length === 0;
6204
+ });
6205
+ }
6206
+ _moveToTarget() {
6207
+ if (!this._sourceSelection.length) return;
6208
+ const items = [...this._sourceSelection];
6209
+ this._source = this._source.filter((s) => !items.some((i) => this._getItemKey(i, -1, true) === this._getItemKey(s, -1, true)));
6210
+ this._target = [...this._target, ...items];
6211
+ this._sourceSelection = [];
6212
+ this._filteredSource = null;
6213
+ this._filteredTarget = null;
6214
+ this._updateListDisplay();
6215
+ this._updateControlsState();
6216
+ this._emitMoveToTarget();
6217
+ }
6218
+ _moveToSource() {
6219
+ if (!this._targetSelection.length) return;
6220
+ const items = [...this._targetSelection];
6221
+ this._target = this._target.filter((t) => !items.some((i) => this._getItemKey(i, -1, false) === this._getItemKey(t, -1, false)));
6222
+ this._source = [...this._source, ...items];
6223
+ this._targetSelection = [];
6224
+ this._filteredSource = null;
6225
+ this._filteredTarget = null;
6226
+ this._updateListDisplay();
6227
+ this._updateControlsState();
6228
+ this._emitMoveToSource();
6229
+ }
6230
+ _moveAllToTarget() {
6231
+ const items = [...this._source];
6232
+ this._source = [];
6233
+ this._target = [...this._target, ...items];
6234
+ this._sourceSelection = [];
6235
+ this._filteredSource = null;
6236
+ this._filteredTarget = null;
6237
+ this._updateListDisplay();
6238
+ this._updateControlsState();
6239
+ this._emitMoveToTarget();
6240
+ }
6241
+ _moveAllToSource() {
6242
+ const items = [...this._target];
6243
+ this._target = [];
6244
+ this._source = [...this._source, ...items];
6245
+ this._targetSelection = [];
6246
+ this._filteredSource = null;
6247
+ this._filteredTarget = null;
6248
+ this._updateListDisplay();
6249
+ this._updateControlsState();
6250
+ this._emitMoveToSource();
6251
+ }
6252
+ _toggleSourceSelection(item, index) {
6253
+ const mode = this.selectionMode || "single";
6254
+ const key2 = this._getItemKey(item, index, true);
6255
+ const idx = this._sourceSelection.findIndex((s) => this._getItemKey(s, -1, true) === key2);
6256
+ if (idx >= 0) {
6257
+ this._sourceSelection.splice(idx, 1);
6258
+ } else if (mode === "multiple") {
6259
+ this._sourceSelection.push(item);
6260
+ } else {
6261
+ this._sourceSelection = [item];
6262
+ }
6263
+ this._emitSelectionChangeSource();
6264
+ this._updateSelectionDisplay();
6265
+ this._updateControlsState();
6266
+ }
6267
+ _toggleTargetSelection(item, index) {
6268
+ const mode = this.selectionMode || "single";
6269
+ const key2 = this._getItemKey(item, index, false);
6270
+ const idx = this._targetSelection.findIndex((s) => this._getItemKey(s, -1, false) === key2);
6271
+ if (idx >= 0) {
6272
+ this._targetSelection.splice(idx, 1);
6273
+ } else if (mode === "multiple") {
6274
+ this._targetSelection.push(item);
6275
+ } else {
6276
+ this._targetSelection = [item];
6277
+ }
6278
+ this._emitSelectionChangeTarget();
6279
+ this._updateSelectionDisplay();
6280
+ this._updateControlsState();
6281
+ }
6282
+ _updateListDisplay() {
6283
+ const srcWrapper = this.root.querySelector(".source-list")?.parentElement;
6284
+ const tgtWrapper = this.root.querySelector(".target-list")?.parentElement;
6285
+ const srcLabel = this.root.querySelector(".list-container:first-of-type .list-label");
6286
+ const tgtLabel = this.root.querySelector(".list-container:last-of-type .list-label");
6287
+ if (!srcWrapper || !tgtWrapper) {
6288
+ this.render();
6289
+ return;
6290
+ }
6291
+ const dSrc = this._getDisplaySource();
6292
+ const dTgt = this._getDisplayTarget();
6293
+ const hasSel = this.selectionMode;
6294
+ const srcItems = dSrc.length === 0 ? `<li class="empty-message" part="empty-message">${this.filter ? "Nenhum resultado" : "Nenhum item"}</li>` : dSrc.map((item, i) => `<li class="list-item${this._isSourceSelected(item, i) ? " selected" : ""}" part="list-item" data-index="${i}" data-list="source" role="option" aria-selected="${this._isSourceSelected(item, i)}" tabindex="0">${hasSel ? '<input type="checkbox" class="checkbox" part="checkbox"' + (this._isSourceSelected(item, i) ? " checked" : "") + " />" : ""}<span class="item-content" part="item-content">${this._optionTemplate ? this._optionTemplate(item) : esc(this._getItemLabel(item))}</span></li>`).join("");
6295
+ const tgtItems = dTgt.length === 0 ? `<li class="empty-message" part="empty-message">${this.filter ? "Nenhum resultado" : "Nenhum selecionado"}</li>` : dTgt.map((item, i) => `<li class="list-item${this._isTargetSelected(item, i) ? " selected" : ""}" part="list-item" data-index="${i}" data-list="target" role="option" aria-selected="${this._isTargetSelected(item, i)}" tabindex="0">${hasSel ? '<input type="checkbox" class="checkbox" part="checkbox"' + (this._isTargetSelected(item, i) ? " checked" : "") + " />" : ""}<span class="item-content" part="item-content">${this._optionTemplate ? this._optionTemplate(item) : esc(this._getItemLabel(item))}</span></li>`).join("");
6296
+ srcWrapper.innerHTML = `<ul class="list source-list" role="listbox" tabindex="0">${srcItems}</ul>`;
6297
+ tgtWrapper.innerHTML = `<ul class="list target-list" role="listbox" tabindex="0">${tgtItems}</ul>`;
6298
+ if (srcLabel) srcLabel.textContent = `${this.sourceLabel} (${this._source.length})`;
6299
+ if (tgtLabel) tgtLabel.textContent = `${this.targetLabel} (${this._target.length})`;
6300
+ this._updateSelectAllBars();
6301
+ this._attachListeners();
6302
+ }
6303
+ };
6304
+ _FxPickList.styles = css`
6305
+ :host {
6306
+ display: block;
6307
+ font-family: var(--fx-font-family);
6308
+ font-size: var(--fx-font-size);
6309
+ --picklist-primary: var(--fx-color-primary, #3b82f6);
6310
+ --picklist-border: var(--fx-border-default, #e2e8f0);
6311
+ --picklist-bg: var(--fx-surface-background, #ffffff);
6312
+ --picklist-bg-hover: var(--fx-surface-surface-hover, #f1f5f9);
6313
+ --picklist-text: var(--fx-text-default, #1e293b);
6314
+ --picklist-text-muted: var(--fx-text-muted, #64748b);
6315
+ --picklist-radius: var(--fx-radius-md, 8px);
6316
+ --picklist-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
6317
+ --picklist-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
6318
+ }
6319
+ * { box-sizing: border-box; }
6320
+ .container {
6321
+ display: flex;
6322
+ gap: var(--fx-space-sm, 8px);
6323
+ align-items: stretch;
6324
+ }
6325
+ .list-container {
6326
+ flex: 1;
6327
+ display: flex;
6328
+ flex-direction: column;
6329
+ gap: var(--fx-space-sm, 8px);
6330
+ min-width: 0;
6331
+ }
6332
+ .list-label {
6333
+ font-weight: 600;
6334
+ color: var(--picklist-text);
6335
+ font-size: calc(var(--fx-font-size) - 1px);
6336
+ }
6337
+ .select-all-bar {
6338
+ display: flex;
6339
+ align-items: center;
6340
+ justify-content: space-between;
6341
+ padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);
6342
+ background: linear-gradient(135deg, var(--picklist-bg), var(--picklist-bg-hover));
6343
+ border: 1px solid var(--picklist-border);
6344
+ border-radius: var(--picklist-radius);
6345
+ font-size: 0.9em;
6346
+ font-weight: 500;
6347
+ }
6348
+ .select-all-bar label {
6349
+ display: flex;
6350
+ align-items: center;
6351
+ gap: var(--fx-space-sm, 10px);
6352
+ cursor: pointer;
6353
+ user-select: none;
6354
+ color: var(--picklist-text);
6355
+ }
6356
+ .select-all-bar input[type="checkbox"] {
6357
+ width: 18px;
6358
+ height: 18px;
6359
+ accent-color: var(--picklist-primary);
6360
+ cursor: pointer;
6361
+ }
6362
+ .selection-count {
6363
+ font-size: 0.85em;
6364
+ color: var(--picklist-primary);
6365
+ background: color-mix(in srgb, var(--picklist-primary) 12%, transparent);
6366
+ padding: 4px 12px;
6367
+ border-radius: 20px;
6368
+ font-weight: 600;
6369
+ }
6370
+ .controls {
6371
+ display: flex;
6372
+ flex-direction: column;
6373
+ gap: 4px;
6374
+ justify-content: center;
6375
+ padding: var(--fx-space-xs, 6px);
6376
+ background: var(--picklist-bg);
6377
+ border: 1px solid var(--picklist-border);
6378
+ border-radius: var(--picklist-radius);
6379
+ box-shadow: var(--picklist-shadow);
6380
+ height: fit-content;
6381
+ position: sticky;
6382
+ top: 0;
6383
+ align-self: center;
6384
+ }
6385
+ .control-group {
6386
+ display: flex;
6387
+ flex-direction: column;
6388
+ gap: 3px;
6389
+ }
6390
+ .control-group + .control-group {
6391
+ margin-top: 4px;
6392
+ padding-top: 6px;
6393
+ border-top: 1px solid var(--picklist-border);
6394
+ }
6395
+ .list-wrapper {
6396
+ flex: 1;
6397
+ display: flex;
6398
+ flex-direction: column;
6399
+ gap: var(--fx-space-sm, 8px);
6400
+ }
6401
+ .filter-wrapper {
6402
+ margin-bottom: var(--fx-space-xs, 4px);
6403
+ }
6404
+ .filter-input {
6405
+ width: 100%;
6406
+ box-sizing: border-box;
6407
+ padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);
6408
+ padding-left: 42px;
6409
+ border: 1.5px solid var(--picklist-border);
6410
+ border-radius: var(--picklist-radius);
6411
+ font-family: inherit;
6412
+ font-size: inherit;
6413
+ color: var(--picklist-text);
6414
+ background: var(--picklist-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E") no-repeat 14px center;
6415
+ transition: var(--picklist-transition);
6416
+ }
6417
+ .filter-input:focus {
6418
+ outline: none;
6419
+ border-color: var(--picklist-primary);
6420
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--picklist-primary) 20%, transparent);
6421
+ }
6422
+ .filter-input::placeholder {
6423
+ color: var(--picklist-text-muted);
6424
+ }
6425
+ .list {
6426
+ list-style: none;
6427
+ margin: 0;
6428
+ padding: 0;
6429
+ border: 1px solid var(--picklist-border);
6430
+ border-radius: var(--picklist-radius);
6431
+ overflow: hidden;
6432
+ box-shadow: var(--picklist-shadow);
6433
+ min-height: 200px;
6434
+ max-height: 450px;
6435
+ overflow-y: auto;
6436
+ flex: 1;
6437
+ }
6438
+ .list::-webkit-scrollbar { width: 6px; }
6439
+ .list::-webkit-scrollbar-track { background: transparent; }
6440
+ .list::-webkit-scrollbar-thumb { background: var(--picklist-border); border-radius: 3px; }
6441
+ .list::-webkit-scrollbar-thumb:hover { background: var(--picklist-text-muted); }
6442
+ :host([striped]) .list-item:nth-child(even) {
6443
+ background: var(--fx-surface-surface, #f8fafc);
6444
+ }
6445
+ .list-item {
6446
+ display: flex;
6447
+ align-items: center;
6448
+ gap: var(--fx-space-sm, 10px);
6449
+ padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);
6450
+ background: var(--picklist-bg);
6451
+ border-bottom: 1px solid var(--picklist-border);
6452
+ cursor: pointer;
6453
+ user-select: none;
6454
+ transition: var(--picklist-transition);
6455
+ }
6456
+ .list-item:last-child { border-bottom: none; }
6457
+ .list-item:hover { background: var(--picklist-bg-hover); }
6458
+ .list-item.selected {
6459
+ background: color-mix(in srgb, var(--picklist-primary) 8%, transparent);
6460
+ border-left: 3px solid var(--picklist-primary);
6461
+ padding-left: 11px;
6462
+ }
6463
+ .list-item:focus-visible {
6464
+ outline: none;
6465
+ background: color-mix(in srgb, var(--picklist-primary) 15%, transparent);
6466
+ }
6467
+ .checkbox {
6468
+ flex-shrink: 0;
6469
+ width: 18px;
6470
+ height: 18px;
6471
+ accent-color: var(--picklist-primary);
6472
+ cursor: pointer;
6473
+ transition: var(--picklist-transition);
6474
+ }
6475
+ .checkbox:hover { transform: scale(1.1); }
6476
+ .item-content {
6477
+ flex: 1;
6478
+ min-width: 0;
6479
+ overflow: hidden;
6480
+ text-overflow: ellipsis;
6481
+ white-space: nowrap;
6482
+ }
6483
+ .empty-message {
6484
+ padding: var(--fx-space-xl, 32px);
6485
+ text-align: center;
6486
+ color: var(--picklist-text-muted);
6487
+ font-style: italic;
6488
+ }
6489
+ button.control-btn {
6490
+ display: flex;
6491
+ align-items: center;
6492
+ justify-content: center;
6493
+ width: 42px;
6494
+ height: 38px;
6495
+ padding: 0;
6496
+ border: none;
6497
+ border-radius: 8px;
6498
+ background: transparent;
6499
+ color: var(--picklist-text-muted);
6500
+ cursor: pointer;
6501
+ font-size: 16px;
6502
+ line-height: 1;
6503
+ transition: var(--picklist-transition);
6504
+ position: relative;
6505
+ }
6506
+ button.control-btn:hover:not(:disabled) {
6507
+ background: var(--picklist-bg-hover);
6508
+ color: var(--picklist-primary);
6509
+ transform: scale(1.1);
6510
+ }
6511
+ button.control-btn:active:not(:disabled) {
6512
+ transform: scale(0.92);
6513
+ background: color-mix(in srgb, var(--picklist-primary) 15%, transparent);
6514
+ }
6515
+ button.control-btn:focus-visible {
6516
+ outline: none;
6517
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--picklist-primary) 30%, transparent);
6518
+ }
6519
+ button.control-btn:disabled {
6520
+ opacity: 0.3;
6521
+ cursor: not-allowed;
6522
+ transform: none;
6523
+ }
6524
+ .control-btn-icon { font-size: 18px; line-height: 1; }
6525
+
6526
+ button.control-btn:hover::after {
6527
+ opacity: 1;
6528
+ transform: translateX(-50%) translateY(0);
6529
+ }
6530
+ @media (max-width: 640px) {
6531
+ .container { flex-direction: column; }
6532
+ .controls {
6533
+ flex-direction: row;
6534
+ flex-wrap: wrap;
6535
+ justify-content: center;
6536
+ position: relative;
6537
+ }
6538
+ .control-group { flex-direction: row; }
6539
+ .control-group + .control-group {
6540
+ margin-top: 0;
6541
+ margin-left: 4px;
6542
+ padding-top: 0;
6543
+ padding-left: 4px;
6544
+ border-top: none;
6545
+ border-left: 1px solid var(--picklist-border);
6546
+ }
6547
+ button.control-btn { width: 44px; height: 40px; }
6548
+ button.control-btn::after { display: none; }
6549
+ .list { max-height: 300px; min-height: 150px; }
6550
+ }
6551
+ @keyframes slideIn {
6552
+ from { opacity: 0; transform: translateX(-10px); }
6553
+ to { opacity: 1; transform: translateX(0); }
6554
+ }
6555
+ .list-item { animation: slideIn 0.2s ease-out; }
6556
+ `;
6557
+ let FxPickList = _FxPickList;
6558
+ function esc(s) {
6559
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
6560
+ }
6561
+ function defineFxPickList() {
6562
+ return defineElement("fx-picklist", FxPickList);
6563
+ }
6564
+ defineFxPickList();
6565
+ const _FxAccordionPanel = class _FxAccordionPanel extends FxElement {
6566
+ constructor() {
6567
+ super(...arguments);
6568
+ this._mo = null;
6569
+ }
6570
+ static get observedAttributes() {
6571
+ return ["header", "expanded", "disabled"];
6572
+ }
6573
+ get header() {
6574
+ return this.getAttr("header", "");
6575
+ }
6576
+ set header(v) {
6577
+ this.setAttribute("header", v);
6578
+ }
6579
+ get value() {
6580
+ return this.getAttr("value", "");
6581
+ }
6582
+ set value(v) {
6583
+ this.setAttribute("value", v);
6584
+ }
6585
+ get expanded() {
6586
+ return this.hasAttr("expanded");
6587
+ }
6588
+ set expanded(v) {
6589
+ this.toggleAttr("expanded", v);
6590
+ }
6591
+ get disabled() {
6592
+ return this.hasAttr("disabled");
6593
+ }
6594
+ set disabled(v) {
6595
+ this.toggleAttr("disabled", v);
6596
+ }
6597
+ connectedCallback() {
6598
+ super.connectedCallback();
6599
+ this.addEventListener("click", (e) => {
6600
+ const path = e.composedPath();
6601
+ if (!path.some((el) => el.classList?.contains("header"))) return;
6602
+ if (this.disabled) return;
6603
+ this.dispatchEvent(
6604
+ new CustomEvent("fx-accordion-toggle", {
6605
+ bubbles: true,
6606
+ composed: true,
6607
+ detail: { panel: this }
6608
+ })
6609
+ );
6610
+ });
6611
+ this._mo = new MutationObserver(() => this.render());
6612
+ this._mo.observe(this, { attributes: true, attributeFilter: ["expanded", "header", "disabled"] });
6613
+ }
6614
+ disconnectedCallback() {
6615
+ this._mo?.disconnect();
6616
+ this._mo = null;
6617
+ }
6618
+ render() {
6619
+ this.setTemplate(`
6620
+ <button type="button" class="header" part="header" role="button"
6621
+ aria-expanded="${this.expanded}"
6622
+ ${this.disabled ? 'aria-disabled="true"' : ""}>
6623
+ <span class="header-text" part="header-text">
6624
+ <slot name="header">${this.header}</slot>
6625
+ </span>
6626
+ <span class="chevron" part="chevron" aria-hidden="true">
6627
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none"
6628
+ stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
6629
+ <polyline points="6 9 12 15 18 9"></polyline>
6630
+ </svg>
6631
+ </span>
6632
+ </button>
6633
+ <div class="content" part="content" role="region">
6634
+ <div class="content-inner">
6635
+ <div class="content-pad" part="content-pad"><slot></slot></div>
6636
+ </div>
6637
+ </div>
6638
+ `);
6639
+ }
6640
+ };
6641
+ _FxAccordionPanel.styles = css`
6642
+ :host {
6643
+ display: block;
6644
+ font-family: var(--fx-font-family);
6645
+ font-size: var(--fx-font-size);
6646
+ color: var(--fx-text-default);
6647
+ border-bottom: 1px solid var(--fx-border-default);
6648
+ }
6649
+ :host(:last-child) { border-bottom: none; }
6650
+ :host([disabled]) { opacity: 0.6; pointer-events: none; }
6651
+ .header {
6652
+ display: flex;
6653
+ align-items: center;
6654
+ justify-content: space-between;
6655
+ gap: var(--fx-space-md);
6656
+ width: 100%;
6657
+ box-sizing: border-box;
6658
+ padding: var(--fx-space-lg, 20px) var(--fx-space-md, 14px);
6659
+ border: none;
6660
+ background: transparent;
6661
+ font-family: inherit;
6662
+ font-size: inherit;
6663
+ font-weight: 500;
6664
+ color: var(--fx-text-muted);
6665
+ text-align: left;
6666
+ cursor: pointer;
6667
+ transition: color var(--fx-motion-duration-fast, 150ms) var(--fx-motion-easing, ease),
6668
+ background var(--fx-motion-duration-fast, 150ms) var(--fx-motion-easing, ease);
6669
+ }
6670
+ .header:hover { color: var(--fx-text-default); }
6671
+ .header:focus-visible {
6672
+ outline: none;
6673
+ box-shadow: var(--fx-effect-focus-ring, none);
6674
+ border-radius: var(--fx-radius-sm, 4px);
6675
+ }
6676
+ :host([expanded]) .header {
6677
+ color: var(--fx-text-default);
6678
+ font-weight: 700;
6679
+ }
6680
+ .header-text { flex: 1; min-width: 0; }
6681
+ .chevron {
6682
+ flex-shrink: 0;
6683
+ display: inline-flex;
6684
+ align-items: center;
6685
+ justify-content: center;
6686
+ width: 24px;
6687
+ height: 24px;
6688
+ color: var(--fx-text-muted);
6689
+ transition: transform var(--fx-motion-duration-normal, 250ms) var(--fx-motion-easing, ease);
6690
+ }
6691
+ :host([expanded]) .chevron { transform: rotate(180deg); color: var(--fx-color-primary); }
6692
+ .content {
6693
+ display: grid;
6694
+ grid-template-rows: 0fr;
6695
+ transition: grid-template-rows var(--fx-motion-duration-normal, 250ms) var(--fx-motion-easing, ease);
6696
+ }
6697
+ :host([expanded]) .content { grid-template-rows: 1fr; }
6698
+ .content-inner { overflow: hidden; }
6699
+ .content-pad {
6700
+ padding: 0 var(--fx-space-md, 14px) var(--fx-space-lg, 20px);
6701
+ color: var(--fx-text-muted);
6702
+ line-height: 1.6;
6703
+ }
6704
+ `;
6705
+ let FxAccordionPanel = _FxAccordionPanel;
6706
+ const _FxAccordion = class _FxAccordion extends FxElement {
6707
+ constructor() {
6708
+ super(...arguments);
6709
+ this._observer = null;
6710
+ this._initialized = false;
6711
+ this._listenersAttached = false;
6712
+ }
6713
+ static get observedAttributes() {
6714
+ return ["value", "multiple"];
6715
+ }
6716
+ get multiple() {
6717
+ return this.hasAttr("multiple");
6718
+ }
6719
+ set multiple(v) {
6720
+ this.toggleAttr("multiple", v);
6721
+ }
6722
+ /** Valores ativos como array. */
6723
+ get values() {
6724
+ return this.getAttr("value", "").split(",").map((s) => s.trim()).filter(Boolean);
6725
+ }
6726
+ set values(v) {
6727
+ this.setAttribute("value", v.join(","));
6728
+ }
6729
+ connectedCallback() {
6730
+ this._observer = new MutationObserver(() => this._sync());
6731
+ this._observer.observe(this, { childList: true, subtree: true });
6732
+ super.connectedCallback();
6733
+ queueMicrotask(() => this._sync());
6734
+ }
6735
+ disconnectedCallback() {
6736
+ this._observer?.disconnect();
6737
+ this._observer = null;
6738
+ }
6739
+ render() {
6740
+ this.setTemplate(`
6741
+ <div class="accordion" part="accordion">
6742
+ <slot></slot>
6743
+ </div>
6744
+ `);
6745
+ this._sync();
6746
+ this._attachListeners();
6747
+ }
6748
+ /** Painéis do accordion (filhos diretos ou descendentes). */
6749
+ get panels() {
6750
+ return Array.from(this.querySelectorAll("fx-accordion-panel"));
6751
+ }
6752
+ _sync() {
6753
+ const actives = this.values;
6754
+ const panels = Array.from(this.querySelectorAll("fx-accordion-panel"));
6755
+ if (!this._initialized && actives.length === 0 && panels.length > 0) {
6756
+ this._initialized = true;
6757
+ const first = panels.find((p) => !p.hasAttribute("disabled"));
6758
+ if (first) {
6759
+ this.values = [first.getAttribute("value") || "0"];
6760
+ return;
6761
+ }
6762
+ }
6763
+ this._initialized = true;
6764
+ panels.forEach((p, i) => {
6765
+ const v = p.getAttribute("value") || String(i);
6766
+ if (!p.hasAttribute("value")) p.setAttribute("value", v);
6767
+ p.toggleAttribute("expanded", actives.includes(v));
6768
+ });
6769
+ }
6770
+ _attachListeners() {
6771
+ if (this._listenersAttached) return;
6772
+ this._listenersAttached = true;
6773
+ this.addEventListener("fx-accordion-toggle", (e) => {
6774
+ const panel = e.detail?.panel;
6775
+ if (!panel || panel.disabled) return;
6776
+ this.toggle(panel);
6777
+ });
6778
+ }
6779
+ /** Abre/fecha um painel respeitando o modo (single | multiple). */
6780
+ toggle(panel) {
6781
+ const v = panel.value;
6782
+ let actives = this.values;
6783
+ if (panel.expanded) {
6784
+ actives = actives.filter((a) => a !== v);
6785
+ } else if (this.multiple) {
6786
+ actives = [...actives, v];
6787
+ } else {
6788
+ actives = [v];
6789
+ }
6790
+ this.values = actives;
6791
+ this._sync();
6792
+ this.dispatchEvent(
6793
+ new CustomEvent("change", {
6794
+ bubbles: true,
6795
+ composed: true,
6796
+ detail: { value: actives }
6797
+ })
6798
+ );
6799
+ }
6800
+ /** Abre um painel pelo valor. */
6801
+ open(value) {
6802
+ const panel = this.panels.find((p, i) => (p.value || String(i)) === value);
6803
+ if (panel && !panel.expanded) this.toggle(panel);
6804
+ }
6805
+ /** Fecha um painel pelo valor. */
6806
+ close(value) {
6807
+ const panel = this.panels.find((p, i) => (p.value || String(i)) === value);
6808
+ if (panel && panel.expanded) this.toggle(panel);
6809
+ }
6810
+ };
6811
+ _FxAccordion.styles = css`
6812
+ :host {
6813
+ display: block;
6814
+ font-family: var(--fx-font-family);
6815
+ font-size: var(--fx-font-size);
6816
+ }
6817
+ .accordion {
6818
+ background: var(--fx-surface-background, #ffffff);
6819
+ border: 1px solid var(--fx-border-default);
6820
+ border-radius: var(--fx-radius-md, 8px);
6821
+ overflow: hidden;
6822
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
6823
+ }
6824
+ `;
6825
+ let FxAccordion = _FxAccordion;
6826
+ function defineFxAccordion() {
6827
+ return defineElement("fx-accordion", FxAccordion);
6828
+ }
6829
+ function defineFxAccordionPanel() {
6830
+ return defineElement("fx-accordion-panel", FxAccordionPanel);
6831
+ }
6832
+ defineFxAccordion();
6833
+ defineFxAccordionPanel();
4422
6834
  export {
4423
6835
  FX_JSX_TYPES,
4424
6836
  FenixToast,
4425
6837
  FenixUI,
6838
+ FxAccordion,
6839
+ FxAccordionPanel,
4426
6840
  FxAlert,
4427
6841
  FxAutocomplete,
4428
6842
  FxBadge,
@@ -4437,8 +6851,11 @@ export {
4437
6851
  FxElement,
4438
6852
  FxFloatlabel,
4439
6853
  FxInput,
6854
+ FxKnob,
4440
6855
  FxMultiselect,
6856
+ FxOrderList,
4441
6857
  FxPagination,
6858
+ FxPickList,
4442
6859
  FxProgress,
4443
6860
  FxRadio,
4444
6861
  FxSelect,
@@ -4461,6 +6878,8 @@ export {
4461
6878
  defaultTokens,
4462
6879
  defineCustomPreset,
4463
6880
  defineElement,
6881
+ defineFxTooltipDirective,
6882
+ destroyFxTooltipDirective,
4464
6883
  kebabToCamel,
4465
6884
  lightTokens,
4466
6885
  listPresets,