@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
@@ -0,0 +1,749 @@
1
+ import { FxElement } from "../../core/base.js";
2
+ import { css } from "../../core/css.js";
3
+ import { defineElement } from "../../core/define.js";
4
+ const _FxPickList = class _FxPickList extends FxElement {
5
+ constructor() {
6
+ super(...arguments);
7
+ this._source = [];
8
+ this._filteredSource = null;
9
+ this._target = [];
10
+ this._filteredTarget = null;
11
+ this._sourceSelection = [];
12
+ this._targetSelection = [];
13
+ this._sourceFilterValue = "";
14
+ this._targetFilterValue = "";
15
+ this._filterListenersAttached = false;
16
+ this._optionTemplate = null;
17
+ }
18
+ static get observedAttributes() {
19
+ return [
20
+ "source",
21
+ "target",
22
+ "source-key",
23
+ "target-key",
24
+ "filter",
25
+ "filter-by",
26
+ "filter-placeholder",
27
+ "dragdrop",
28
+ "striped",
29
+ "selection-mode",
30
+ "show-select-all",
31
+ "source-label",
32
+ "target-label"
33
+ ];
34
+ }
35
+ set source(value) {
36
+ this._source = value;
37
+ this._filteredSource = null;
38
+ this.render();
39
+ }
40
+ get source() {
41
+ return this._source;
42
+ }
43
+ set target(value) {
44
+ this._target = value;
45
+ this._filteredTarget = null;
46
+ this.render();
47
+ }
48
+ get target() {
49
+ return this._target;
50
+ }
51
+ set sourceSelection(value) {
52
+ this._sourceSelection = value;
53
+ this.render();
54
+ }
55
+ get sourceSelection() {
56
+ return this._sourceSelection;
57
+ }
58
+ set targetSelection(value) {
59
+ this._targetSelection = value;
60
+ this.render();
61
+ }
62
+ get targetSelection() {
63
+ return this._targetSelection;
64
+ }
65
+ get sourceKey() {
66
+ return this.getAttr("source-key", "");
67
+ }
68
+ set sourceKey(v) {
69
+ this.setAttribute("source-key", v);
70
+ }
71
+ get targetKey() {
72
+ return this.getAttr("target-key", "");
73
+ }
74
+ set targetKey(v) {
75
+ this.setAttribute("target-key", v);
76
+ }
77
+ get filter() {
78
+ return this.hasAttr("filter");
79
+ }
80
+ set filter(v) {
81
+ this.toggleAttr("filter", v);
82
+ }
83
+ get filterBy() {
84
+ return this.getAttr("filter-by", "label");
85
+ }
86
+ set filterBy(v) {
87
+ this.setAttribute("filter-by", v);
88
+ }
89
+ get filterPlaceholder() {
90
+ return this.getAttr("filter-placeholder", "Buscar...");
91
+ }
92
+ set filterPlaceholder(v) {
93
+ this.setAttribute("filter-placeholder", v);
94
+ }
95
+ get dragdrop() {
96
+ return this.hasAttr("dragdrop");
97
+ }
98
+ set dragdrop(v) {
99
+ this.toggleAttr("dragdrop", v);
100
+ }
101
+ get striped() {
102
+ return this.hasAttr("striped");
103
+ }
104
+ set striped(v) {
105
+ this.toggleAttr("striped", v);
106
+ }
107
+ get selectionMode() {
108
+ const s = this.getAttr("selection-mode", "");
109
+ return s === "single" || s === "multiple" ? s : "";
110
+ }
111
+ set selectionMode(v) {
112
+ this.setAttribute("selection-mode", v);
113
+ }
114
+ get showSelectAll() {
115
+ return this.hasAttr("show-select-all");
116
+ }
117
+ set showSelectAll(v) {
118
+ this.toggleAttr("show-select-all", v);
119
+ }
120
+ get sourceLabel() {
121
+ return this.getAttr("source-label", "Disponíveis");
122
+ }
123
+ set sourceLabel(v) {
124
+ this.setAttribute("source-label", v);
125
+ }
126
+ get targetLabel() {
127
+ return this.getAttr("target-label", "Selecionados");
128
+ }
129
+ set targetLabel(v) {
130
+ this.setAttribute("target-label", v);
131
+ }
132
+ get sourceFilterValue() {
133
+ return this._sourceFilterValue;
134
+ }
135
+ set sourceFilterValue(v) {
136
+ this._sourceFilterValue = v;
137
+ this._applySourceFilter();
138
+ this._updateListDisplay();
139
+ }
140
+ get targetFilterValue() {
141
+ return this._targetFilterValue;
142
+ }
143
+ set targetFilterValue(v) {
144
+ this._targetFilterValue = v;
145
+ this._applyTargetFilter();
146
+ this._updateListDisplay();
147
+ }
148
+ setOptionTemplate(template) {
149
+ this._optionTemplate = template;
150
+ this.render();
151
+ }
152
+ connectedCallback() {
153
+ this._parseSourceAttribute();
154
+ this._parseTargetAttribute();
155
+ super.connectedCallback();
156
+ }
157
+ attributeChangedCallback() {
158
+ if (this.getAttr("source", "") !== "") {
159
+ this._parseSourceAttribute();
160
+ }
161
+ if (this.getAttr("target", "") !== "") {
162
+ this._parseTargetAttribute();
163
+ }
164
+ super.attributeChangedCallback();
165
+ }
166
+ _parseSourceAttribute() {
167
+ const dataAttr = this.getAttr("source", "");
168
+ if (dataAttr) {
169
+ try {
170
+ this._source = JSON.parse(dataAttr);
171
+ this._filteredSource = null;
172
+ } catch {
173
+ this._source = [];
174
+ }
175
+ }
176
+ }
177
+ _parseTargetAttribute() {
178
+ const dataAttr = this.getAttr("target", "");
179
+ if (dataAttr) {
180
+ try {
181
+ this._target = JSON.parse(dataAttr);
182
+ this._filteredTarget = null;
183
+ } catch {
184
+ this._target = [];
185
+ }
186
+ }
187
+ }
188
+ _applySourceFilter() {
189
+ if (!this._sourceFilterValue) {
190
+ this._filteredSource = null;
191
+ return;
192
+ }
193
+ const filterFields = this.filterBy.split(",").map((f) => f.trim());
194
+ this._filteredSource = this._source.filter((item) => {
195
+ return filterFields.some((field) => {
196
+ const value = item[field];
197
+ if (value == null) return false;
198
+ return String(value).toLowerCase().includes(this._sourceFilterValue.toLowerCase());
199
+ });
200
+ });
201
+ }
202
+ _applyTargetFilter() {
203
+ if (!this._targetFilterValue) {
204
+ this._filteredTarget = null;
205
+ return;
206
+ }
207
+ const filterFields = this.filterBy.split(",").map((f) => f.trim());
208
+ this._filteredTarget = this._target.filter((item) => {
209
+ return filterFields.some((field) => {
210
+ const value = item[field];
211
+ if (value == null) return false;
212
+ return String(value).toLowerCase().includes(this._targetFilterValue.toLowerCase());
213
+ });
214
+ });
215
+ }
216
+ _getDisplaySource() {
217
+ return this._filteredSource || this._source;
218
+ }
219
+ _getDisplayTarget() {
220
+ return this._filteredTarget || this._target;
221
+ }
222
+ _getItemKey(item, index, isSource) {
223
+ const keyField = isSource ? this.sourceKey : this.targetKey;
224
+ if (keyField && item[keyField] != null) {
225
+ return String(item[keyField]);
226
+ }
227
+ if (item["id"] != null) return String(item["id"]);
228
+ if (item["key"] != null) return String(item["key"]);
229
+ if (item["label"] != null) return String(item["label"]);
230
+ if (item["name"] != null) return String(item["name"]);
231
+ if (item["value"] != null) return String(item["value"]);
232
+ return String(index);
233
+ }
234
+ _getItemLabel(item) {
235
+ const fields = ["label", "name", "title", "text", "value"];
236
+ for (const field of fields) {
237
+ if (item[field] != null) {
238
+ return String(item[field]);
239
+ }
240
+ }
241
+ return JSON.stringify(item);
242
+ }
243
+ _isSourceSelected(item, index) {
244
+ return this._sourceSelection.some((s) => this._getItemKey(s, -1, true) === this._getItemKey(item, index, true));
245
+ }
246
+ _isTargetSelected(item, index) {
247
+ return this._targetSelection.some((s) => this._getItemKey(s, -1, false) === this._getItemKey(item, index, false));
248
+ }
249
+ _emitMoveToTarget() {
250
+ this.dispatchEvent(new CustomEvent("move-to-target", {
251
+ bubbles: true,
252
+ composed: true,
253
+ detail: { items: [...this._sourceSelection], source: [...this._source], target: [...this._target] }
254
+ }));
255
+ }
256
+ _emitMoveToSource() {
257
+ this.dispatchEvent(new CustomEvent("move-to-source", {
258
+ bubbles: true,
259
+ composed: true,
260
+ detail: { items: [...this._targetSelection], source: [...this._source], target: [...this._target] }
261
+ }));
262
+ }
263
+ _emitSelectionChangeSource() {
264
+ this.dispatchEvent(new CustomEvent("selection-change-source", {
265
+ bubbles: true,
266
+ composed: true,
267
+ detail: { selection: [...this._sourceSelection] }
268
+ }));
269
+ }
270
+ _emitSelectionChangeTarget() {
271
+ this.dispatchEvent(new CustomEvent("selection-change-target", {
272
+ bubbles: true,
273
+ composed: true,
274
+ detail: { selection: [...this._targetSelection] }
275
+ }));
276
+ }
277
+ render() {
278
+ const dSrc = this._getDisplaySource();
279
+ const dTgt = this._getDisplayTarget();
280
+ const hasSel = this.selectionMode;
281
+ const showAll = hasSel === "multiple" && this.showSelectAll;
282
+ 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("");
283
+ 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("");
284
+ 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>` : "";
285
+ 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>` : "";
286
+ 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>`);
287
+ this._attachListeners();
288
+ }
289
+ _attachListeners() {
290
+ if (!this._filterListenersAttached) {
291
+ this._filterListenersAttached = true;
292
+ this.root.addEventListener("input", (e) => {
293
+ const t = e.target;
294
+ if (t.classList.contains("select-all-checkbox")) {
295
+ this._handleSelectAll(t);
296
+ return;
297
+ }
298
+ if (t.classList.contains("source-filter")) {
299
+ this.sourceFilterValue = t.value;
300
+ } else if (t.classList.contains("target-filter")) {
301
+ this.targetFilterValue = t.value;
302
+ }
303
+ });
304
+ this.root.addEventListener("click", (e) => {
305
+ const t = e.target;
306
+ const btn = t.closest(".control-btn");
307
+ if (btn) {
308
+ switch (btn.dataset.action) {
309
+ case "move-target":
310
+ this._moveToTarget();
311
+ break;
312
+ case "move-all-target":
313
+ this._moveAllToTarget();
314
+ break;
315
+ case "move-source":
316
+ this._moveToSource();
317
+ break;
318
+ case "move-all-source":
319
+ this._moveAllToSource();
320
+ break;
321
+ }
322
+ return;
323
+ }
324
+ const el = t.closest(".list-item");
325
+ if (!el) return;
326
+ const isSrc = el.dataset.list === "source";
327
+ const idx = Number(el.dataset.index);
328
+ const item = (isSrc ? this._getDisplaySource() : this._getDisplayTarget())[idx];
329
+ if (isSrc) this._toggleSourceSelection(item, idx);
330
+ else this._toggleTargetSelection(item, idx);
331
+ });
332
+ }
333
+ this._updateControlsState();
334
+ }
335
+ _handleSelectAll(checkbox) {
336
+ const isSrc = checkbox.dataset.list === "source";
337
+ if (isSrc) {
338
+ this._sourceSelection = checkbox.checked ? [...this._getDisplaySource()] : [];
339
+ this._emitSelectionChangeSource();
340
+ } else {
341
+ this._targetSelection = checkbox.checked ? [...this._getDisplayTarget()] : [];
342
+ this._emitSelectionChangeTarget();
343
+ }
344
+ this._updateSelectionDisplay();
345
+ this._updateControlsState();
346
+ }
347
+ /**
348
+ * Atualiza a selecao visual in-place (classes e checkboxes dos itens existentes),
349
+ * sem recriar o DOM — mantendo referencias de elementos validas durante cliques.
350
+ */
351
+ _updateSelectionDisplay() {
352
+ const updateList = (listSel, isSelFn, getData) => {
353
+ if (!listSel) return;
354
+ listSel.querySelectorAll(".list-item").forEach((el) => {
355
+ const idx = Number(el.dataset.index);
356
+ const selected = isSelFn(getData()[idx], idx);
357
+ el.classList.toggle("selected", selected);
358
+ el.setAttribute("aria-selected", String(selected));
359
+ const cb = el.querySelector(".checkbox");
360
+ if (cb) cb.checked = selected;
361
+ });
362
+ };
363
+ updateList(this.root.querySelector(".source-list"), (it, i) => this._isSourceSelected(it, i), () => this._getDisplaySource());
364
+ updateList(this.root.querySelector(".target-list"), (it, i) => this._isTargetSelected(it, i), () => this._getDisplayTarget());
365
+ this._updateSelectAllBars();
366
+ }
367
+ /** Sincroniza as barras "Selecionar Todos" (checkbox + contador) sem re-render completo. */
368
+ _updateSelectAllBars() {
369
+ if (!(this.selectionMode === "multiple" && this.showSelectAll)) return;
370
+ const bars = [
371
+ { el: this.root.querySelector('.select-all-checkbox[data-list="source"]'), total: this._source.length, sel: this._sourceSelection.length },
372
+ { el: this.root.querySelector('.select-all-checkbox[data-list="target"]'), total: this._target.length, sel: this._targetSelection.length }
373
+ ];
374
+ bars.forEach(({ el, total, sel }) => {
375
+ if (!el) return;
376
+ el.checked = total > 0 && sel === total;
377
+ const count = el.closest(".select-all-bar")?.querySelector(".selection-count");
378
+ if (count) count.textContent = `${sel} selecionado(s)`;
379
+ });
380
+ }
381
+ _updateControlsState() {
382
+ this.root.querySelectorAll(".control-btn").forEach((btn) => {
383
+ const a = btn.dataset.action;
384
+ 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;
385
+ });
386
+ }
387
+ _moveToTarget() {
388
+ if (!this._sourceSelection.length) return;
389
+ const items = [...this._sourceSelection];
390
+ this._source = this._source.filter((s) => !items.some((i) => this._getItemKey(i, -1, true) === this._getItemKey(s, -1, true)));
391
+ this._target = [...this._target, ...items];
392
+ this._sourceSelection = [];
393
+ this._filteredSource = null;
394
+ this._filteredTarget = null;
395
+ this._updateListDisplay();
396
+ this._updateControlsState();
397
+ this._emitMoveToTarget();
398
+ }
399
+ _moveToSource() {
400
+ if (!this._targetSelection.length) return;
401
+ const items = [...this._targetSelection];
402
+ this._target = this._target.filter((t) => !items.some((i) => this._getItemKey(i, -1, false) === this._getItemKey(t, -1, false)));
403
+ this._source = [...this._source, ...items];
404
+ this._targetSelection = [];
405
+ this._filteredSource = null;
406
+ this._filteredTarget = null;
407
+ this._updateListDisplay();
408
+ this._updateControlsState();
409
+ this._emitMoveToSource();
410
+ }
411
+ _moveAllToTarget() {
412
+ const items = [...this._source];
413
+ this._source = [];
414
+ this._target = [...this._target, ...items];
415
+ this._sourceSelection = [];
416
+ this._filteredSource = null;
417
+ this._filteredTarget = null;
418
+ this._updateListDisplay();
419
+ this._updateControlsState();
420
+ this._emitMoveToTarget();
421
+ }
422
+ _moveAllToSource() {
423
+ const items = [...this._target];
424
+ this._target = [];
425
+ this._source = [...this._source, ...items];
426
+ this._targetSelection = [];
427
+ this._filteredSource = null;
428
+ this._filteredTarget = null;
429
+ this._updateListDisplay();
430
+ this._updateControlsState();
431
+ this._emitMoveToSource();
432
+ }
433
+ _toggleSourceSelection(item, index) {
434
+ const mode = this.selectionMode || "single";
435
+ const key = this._getItemKey(item, index, true);
436
+ const idx = this._sourceSelection.findIndex((s) => this._getItemKey(s, -1, true) === key);
437
+ if (idx >= 0) {
438
+ this._sourceSelection.splice(idx, 1);
439
+ } else if (mode === "multiple") {
440
+ this._sourceSelection.push(item);
441
+ } else {
442
+ this._sourceSelection = [item];
443
+ }
444
+ this._emitSelectionChangeSource();
445
+ this._updateSelectionDisplay();
446
+ this._updateControlsState();
447
+ }
448
+ _toggleTargetSelection(item, index) {
449
+ const mode = this.selectionMode || "single";
450
+ const key = this._getItemKey(item, index, false);
451
+ const idx = this._targetSelection.findIndex((s) => this._getItemKey(s, -1, false) === key);
452
+ if (idx >= 0) {
453
+ this._targetSelection.splice(idx, 1);
454
+ } else if (mode === "multiple") {
455
+ this._targetSelection.push(item);
456
+ } else {
457
+ this._targetSelection = [item];
458
+ }
459
+ this._emitSelectionChangeTarget();
460
+ this._updateSelectionDisplay();
461
+ this._updateControlsState();
462
+ }
463
+ _updateListDisplay() {
464
+ const srcWrapper = this.root.querySelector(".source-list")?.parentElement;
465
+ const tgtWrapper = this.root.querySelector(".target-list")?.parentElement;
466
+ const srcLabel = this.root.querySelector(".list-container:first-of-type .list-label");
467
+ const tgtLabel = this.root.querySelector(".list-container:last-of-type .list-label");
468
+ if (!srcWrapper || !tgtWrapper) {
469
+ this.render();
470
+ return;
471
+ }
472
+ const dSrc = this._getDisplaySource();
473
+ const dTgt = this._getDisplayTarget();
474
+ const hasSel = this.selectionMode;
475
+ 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("");
476
+ 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("");
477
+ srcWrapper.innerHTML = `<ul class="list source-list" role="listbox" tabindex="0">${srcItems}</ul>`;
478
+ tgtWrapper.innerHTML = `<ul class="list target-list" role="listbox" tabindex="0">${tgtItems}</ul>`;
479
+ if (srcLabel) srcLabel.textContent = `${this.sourceLabel} (${this._source.length})`;
480
+ if (tgtLabel) tgtLabel.textContent = `${this.targetLabel} (${this._target.length})`;
481
+ this._updateSelectAllBars();
482
+ this._attachListeners();
483
+ }
484
+ };
485
+ _FxPickList.styles = css`
486
+ :host {
487
+ display: block;
488
+ font-family: var(--fx-font-family);
489
+ font-size: var(--fx-font-size);
490
+ --picklist-primary: var(--fx-color-primary, #3b82f6);
491
+ --picklist-border: var(--fx-border-default, #e2e8f0);
492
+ --picklist-bg: var(--fx-surface-background, #ffffff);
493
+ --picklist-bg-hover: var(--fx-surface-surface-hover, #f1f5f9);
494
+ --picklist-text: var(--fx-text-default, #1e293b);
495
+ --picklist-text-muted: var(--fx-text-muted, #64748b);
496
+ --picklist-radius: var(--fx-radius-md, 8px);
497
+ --picklist-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
498
+ --picklist-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
499
+ }
500
+ * { box-sizing: border-box; }
501
+ .container {
502
+ display: flex;
503
+ gap: var(--fx-space-sm, 8px);
504
+ align-items: stretch;
505
+ }
506
+ .list-container {
507
+ flex: 1;
508
+ display: flex;
509
+ flex-direction: column;
510
+ gap: var(--fx-space-sm, 8px);
511
+ min-width: 0;
512
+ }
513
+ .list-label {
514
+ font-weight: 600;
515
+ color: var(--picklist-text);
516
+ font-size: calc(var(--fx-font-size) - 1px);
517
+ }
518
+ .select-all-bar {
519
+ display: flex;
520
+ align-items: center;
521
+ justify-content: space-between;
522
+ padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);
523
+ background: linear-gradient(135deg, var(--picklist-bg), var(--picklist-bg-hover));
524
+ border: 1px solid var(--picklist-border);
525
+ border-radius: var(--picklist-radius);
526
+ font-size: 0.9em;
527
+ font-weight: 500;
528
+ }
529
+ .select-all-bar label {
530
+ display: flex;
531
+ align-items: center;
532
+ gap: var(--fx-space-sm, 10px);
533
+ cursor: pointer;
534
+ user-select: none;
535
+ color: var(--picklist-text);
536
+ }
537
+ .select-all-bar input[type="checkbox"] {
538
+ width: 18px;
539
+ height: 18px;
540
+ accent-color: var(--picklist-primary);
541
+ cursor: pointer;
542
+ }
543
+ .selection-count {
544
+ font-size: 0.85em;
545
+ color: var(--picklist-primary);
546
+ background: color-mix(in srgb, var(--picklist-primary) 12%, transparent);
547
+ padding: 4px 12px;
548
+ border-radius: 20px;
549
+ font-weight: 600;
550
+ }
551
+ .controls {
552
+ display: flex;
553
+ flex-direction: column;
554
+ gap: 4px;
555
+ justify-content: center;
556
+ padding: var(--fx-space-xs, 6px);
557
+ background: var(--picklist-bg);
558
+ border: 1px solid var(--picklist-border);
559
+ border-radius: var(--picklist-radius);
560
+ box-shadow: var(--picklist-shadow);
561
+ height: fit-content;
562
+ position: sticky;
563
+ top: 0;
564
+ align-self: center;
565
+ }
566
+ .control-group {
567
+ display: flex;
568
+ flex-direction: column;
569
+ gap: 3px;
570
+ }
571
+ .control-group + .control-group {
572
+ margin-top: 4px;
573
+ padding-top: 6px;
574
+ border-top: 1px solid var(--picklist-border);
575
+ }
576
+ .list-wrapper {
577
+ flex: 1;
578
+ display: flex;
579
+ flex-direction: column;
580
+ gap: var(--fx-space-sm, 8px);
581
+ }
582
+ .filter-wrapper {
583
+ margin-bottom: var(--fx-space-xs, 4px);
584
+ }
585
+ .filter-input {
586
+ width: 100%;
587
+ box-sizing: border-box;
588
+ padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);
589
+ padding-left: 42px;
590
+ border: 1.5px solid var(--picklist-border);
591
+ border-radius: var(--picklist-radius);
592
+ font-family: inherit;
593
+ font-size: inherit;
594
+ color: var(--picklist-text);
595
+ 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;
596
+ transition: var(--picklist-transition);
597
+ }
598
+ .filter-input:focus {
599
+ outline: none;
600
+ border-color: var(--picklist-primary);
601
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--picklist-primary) 20%, transparent);
602
+ }
603
+ .filter-input::placeholder {
604
+ color: var(--picklist-text-muted);
605
+ }
606
+ .list {
607
+ list-style: none;
608
+ margin: 0;
609
+ padding: 0;
610
+ border: 1px solid var(--picklist-border);
611
+ border-radius: var(--picklist-radius);
612
+ overflow: hidden;
613
+ box-shadow: var(--picklist-shadow);
614
+ min-height: 200px;
615
+ max-height: 450px;
616
+ overflow-y: auto;
617
+ flex: 1;
618
+ }
619
+ .list::-webkit-scrollbar { width: 6px; }
620
+ .list::-webkit-scrollbar-track { background: transparent; }
621
+ .list::-webkit-scrollbar-thumb { background: var(--picklist-border); border-radius: 3px; }
622
+ .list::-webkit-scrollbar-thumb:hover { background: var(--picklist-text-muted); }
623
+ :host([striped]) .list-item:nth-child(even) {
624
+ background: var(--fx-surface-surface, #f8fafc);
625
+ }
626
+ .list-item {
627
+ display: flex;
628
+ align-items: center;
629
+ gap: var(--fx-space-sm, 10px);
630
+ padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);
631
+ background: var(--picklist-bg);
632
+ border-bottom: 1px solid var(--picklist-border);
633
+ cursor: pointer;
634
+ user-select: none;
635
+ transition: var(--picklist-transition);
636
+ }
637
+ .list-item:last-child { border-bottom: none; }
638
+ .list-item:hover { background: var(--picklist-bg-hover); }
639
+ .list-item.selected {
640
+ background: color-mix(in srgb, var(--picklist-primary) 8%, transparent);
641
+ border-left: 3px solid var(--picklist-primary);
642
+ padding-left: 11px;
643
+ }
644
+ .list-item:focus-visible {
645
+ outline: none;
646
+ background: color-mix(in srgb, var(--picklist-primary) 15%, transparent);
647
+ }
648
+ .checkbox {
649
+ flex-shrink: 0;
650
+ width: 18px;
651
+ height: 18px;
652
+ accent-color: var(--picklist-primary);
653
+ cursor: pointer;
654
+ transition: var(--picklist-transition);
655
+ }
656
+ .checkbox:hover { transform: scale(1.1); }
657
+ .item-content {
658
+ flex: 1;
659
+ min-width: 0;
660
+ overflow: hidden;
661
+ text-overflow: ellipsis;
662
+ white-space: nowrap;
663
+ }
664
+ .empty-message {
665
+ padding: var(--fx-space-xl, 32px);
666
+ text-align: center;
667
+ color: var(--picklist-text-muted);
668
+ font-style: italic;
669
+ }
670
+ button.control-btn {
671
+ display: flex;
672
+ align-items: center;
673
+ justify-content: center;
674
+ width: 42px;
675
+ height: 38px;
676
+ padding: 0;
677
+ border: none;
678
+ border-radius: 8px;
679
+ background: transparent;
680
+ color: var(--picklist-text-muted);
681
+ cursor: pointer;
682
+ font-size: 16px;
683
+ line-height: 1;
684
+ transition: var(--picklist-transition);
685
+ position: relative;
686
+ }
687
+ button.control-btn:hover:not(:disabled) {
688
+ background: var(--picklist-bg-hover);
689
+ color: var(--picklist-primary);
690
+ transform: scale(1.1);
691
+ }
692
+ button.control-btn:active:not(:disabled) {
693
+ transform: scale(0.92);
694
+ background: color-mix(in srgb, var(--picklist-primary) 15%, transparent);
695
+ }
696
+ button.control-btn:focus-visible {
697
+ outline: none;
698
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--picklist-primary) 30%, transparent);
699
+ }
700
+ button.control-btn:disabled {
701
+ opacity: 0.3;
702
+ cursor: not-allowed;
703
+ transform: none;
704
+ }
705
+ .control-btn-icon { font-size: 18px; line-height: 1; }
706
+
707
+ button.control-btn:hover::after {
708
+ opacity: 1;
709
+ transform: translateX(-50%) translateY(0);
710
+ }
711
+ @media (max-width: 640px) {
712
+ .container { flex-direction: column; }
713
+ .controls {
714
+ flex-direction: row;
715
+ flex-wrap: wrap;
716
+ justify-content: center;
717
+ position: relative;
718
+ }
719
+ .control-group { flex-direction: row; }
720
+ .control-group + .control-group {
721
+ margin-top: 0;
722
+ margin-left: 4px;
723
+ padding-top: 0;
724
+ padding-left: 4px;
725
+ border-top: none;
726
+ border-left: 1px solid var(--picklist-border);
727
+ }
728
+ button.control-btn { width: 44px; height: 40px; }
729
+ button.control-btn::after { display: none; }
730
+ .list { max-height: 300px; min-height: 150px; }
731
+ }
732
+ @keyframes slideIn {
733
+ from { opacity: 0; transform: translateX(-10px); }
734
+ to { opacity: 1; transform: translateX(0); }
735
+ }
736
+ .list-item { animation: slideIn 0.2s ease-out; }
737
+ `;
738
+ let FxPickList = _FxPickList;
739
+ function esc(s) {
740
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
741
+ }
742
+ function defineFxPickList() {
743
+ return defineElement("fx-picklist", FxPickList);
744
+ }
745
+ export {
746
+ FxPickList,
747
+ defineFxPickList
748
+ };
749
+ //# sourceMappingURL=picklist.js.map