@wrrdev/fenix-ui 1.0.13 → 1.0.15

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 (114) hide show
  1. package/README.md +332 -332
  2. package/dist/components/accordion/accordion.d.ts +1 -0
  3. package/dist/components/accordion/accordion.d.ts.map +1 -1
  4. package/dist/components/accordion/accordion.js +18 -13
  5. package/dist/components/accordion/accordion.js.map +1 -1
  6. package/dist/components/accordion/index.js.map +1 -1
  7. package/dist/components/alert/alert.d.ts.map +1 -1
  8. package/dist/components/alert/alert.js +2 -1
  9. package/dist/components/alert/alert.js.map +1 -1
  10. package/dist/components/alert/index.js.map +1 -1
  11. package/dist/components/autocomplete/autocomplete.d.ts +3 -0
  12. package/dist/components/autocomplete/autocomplete.d.ts.map +1 -1
  13. package/dist/components/autocomplete/autocomplete.js +28 -4
  14. package/dist/components/autocomplete/autocomplete.js.map +1 -1
  15. package/dist/components/autocomplete/index.js.map +1 -1
  16. package/dist/components/datepicker/datepicker.d.ts.map +1 -1
  17. package/dist/components/datepicker/datepicker.js +7 -6
  18. package/dist/components/datepicker/datepicker.js.map +1 -1
  19. package/dist/components/dialog/dialog.d.ts +4 -0
  20. package/dist/components/dialog/dialog.d.ts.map +1 -1
  21. package/dist/components/dialog/dialog.js +42 -4
  22. package/dist/components/dialog/dialog.js.map +1 -1
  23. package/dist/components/dialog/index.js.map +1 -1
  24. package/dist/components/drawer/drawer.d.ts +5 -0
  25. package/dist/components/drawer/drawer.d.ts.map +1 -1
  26. package/dist/components/drawer/drawer.js +49 -15
  27. package/dist/components/drawer/drawer.js.map +1 -1
  28. package/dist/components/dropdown/dropdown.d.ts +5 -0
  29. package/dist/components/dropdown/dropdown.d.ts.map +1 -1
  30. package/dist/components/dropdown/dropdown.js +34 -10
  31. package/dist/components/dropdown/dropdown.js.map +1 -1
  32. package/dist/components/input/input.d.ts.map +1 -1
  33. package/dist/components/input/input.js +4 -3
  34. package/dist/components/input/input.js.map +1 -1
  35. package/dist/components/knob/index.js.map +1 -1
  36. package/dist/components/knob/knob.d.ts +2 -0
  37. package/dist/components/knob/knob.d.ts.map +1 -1
  38. package/dist/components/knob/knob.js +15 -3
  39. package/dist/components/knob/knob.js.map +1 -1
  40. package/dist/components/multiselect/multiselect.d.ts +2 -0
  41. package/dist/components/multiselect/multiselect.d.ts.map +1 -1
  42. package/dist/components/multiselect/multiselect.js +38 -8
  43. package/dist/components/multiselect/multiselect.js.map +1 -1
  44. package/dist/components/orderlist/orderlist.d.ts.map +1 -1
  45. package/dist/components/orderlist/orderlist.js +1 -3
  46. package/dist/components/orderlist/orderlist.js.map +1 -1
  47. package/dist/components/pagination/index.js.map +1 -1
  48. package/dist/components/pagination/pagination.d.ts +1 -0
  49. package/dist/components/pagination/pagination.d.ts.map +1 -1
  50. package/dist/components/pagination/pagination.js +19 -8
  51. package/dist/components/pagination/pagination.js.map +1 -1
  52. package/dist/components/picklist/picklist.d.ts.map +1 -1
  53. package/dist/components/picklist/picklist.js +1 -3
  54. package/dist/components/picklist/picklist.js.map +1 -1
  55. package/dist/components/progress/index.js.map +1 -1
  56. package/dist/components/progress/progress.d.ts.map +1 -1
  57. package/dist/components/progress/progress.js +2 -1
  58. package/dist/components/progress/progress.js.map +1 -1
  59. package/dist/components/radio/radio.js +1 -1
  60. package/dist/components/radio/radio.js.map +1 -1
  61. package/dist/components/select/select.d.ts +2 -0
  62. package/dist/components/select/select.d.ts.map +1 -1
  63. package/dist/components/select/select.js +36 -5
  64. package/dist/components/select/select.js.map +1 -1
  65. package/dist/components/skeleton/index.js.map +1 -1
  66. package/dist/components/skeleton/skeleton.d.ts +2 -0
  67. package/dist/components/skeleton/skeleton.d.ts.map +1 -1
  68. package/dist/components/skeleton/skeleton.js +7 -2
  69. package/dist/components/skeleton/skeleton.js.map +1 -1
  70. package/dist/components/table/expr.d.ts +38 -0
  71. package/dist/components/table/expr.d.ts.map +1 -0
  72. package/dist/components/table/expr.js +429 -0
  73. package/dist/components/table/expr.js.map +1 -0
  74. package/dist/components/table/table.d.ts +26 -8
  75. package/dist/components/table/table.d.ts.map +1 -1
  76. package/dist/components/table/table.js +402 -140
  77. package/dist/components/table/table.js.map +1 -1
  78. package/dist/components/tabs/tabs.d.ts.map +1 -1
  79. package/dist/components/tabs/tabs.js +3 -2
  80. package/dist/components/tabs/tabs.js.map +1 -1
  81. package/dist/components/textarea/index.js.map +1 -1
  82. package/dist/components/textarea/textarea.d.ts.map +1 -1
  83. package/dist/components/textarea/textarea.js +4 -3
  84. package/dist/components/textarea/textarea.js.map +1 -1
  85. package/dist/components/toast/index.js.map +1 -1
  86. package/dist/components/tooltip/directive.js.map +1 -1
  87. package/dist/components/tooltip/index.js.map +1 -1
  88. package/dist/components/tooltip/tooltip.d.ts.map +1 -1
  89. package/dist/components/tooltip/tooltip.js +2 -1
  90. package/dist/components/tooltip/tooltip.js.map +1 -1
  91. package/dist/core/jsx.js.map +1 -1
  92. package/dist/core/presets.js.map +1 -1
  93. package/dist/core/sanitize.d.ts +36 -0
  94. package/dist/core/sanitize.d.ts.map +1 -0
  95. package/dist/core/sanitize.js +37 -0
  96. package/dist/core/sanitize.js.map +1 -0
  97. package/dist/core/tokens.js.map +1 -1
  98. package/dist/core/vue.js.map +1 -1
  99. package/dist/docs/app.d.ts.map +1 -1
  100. package/dist/docs/componentes/table.doc.d.ts.map +1 -1
  101. package/dist/fenix-ui.esm.js.map +1 -1
  102. package/dist/fenix-ui.umd.min.js +339 -208
  103. package/dist/fenix-ui2.esm.js +1156 -243
  104. package/dist/fenix-ui2.esm.js.map +1 -1
  105. package/dist/fenix-ui3.esm.js +7 -1
  106. package/dist/fenix-ui3.esm.js.map +1 -1
  107. package/dist/index.d.ts +2 -1
  108. package/dist/index.d.ts.map +1 -1
  109. package/dist/index.js +4 -0
  110. package/dist/index.js.map +1 -1
  111. package/dist/plugins/auto-import.d.ts.map +1 -1
  112. package/dist/plugins/auto-import.js +7 -1
  113. package/dist/plugins/auto-import.js.map +1 -1
  114. package/package.json +212 -212
@@ -1,6 +1,8 @@
1
1
  import { FxElement } from "../../core/base.js";
2
2
  import { css } from "../../core/css.js";
3
3
  import { defineElement } from "../../core/define.js";
4
+ import { esc } from "../../core/sanitize.js";
5
+ import "../select/index.js";
4
6
  const _FxPagination = class _FxPagination extends FxElement {
5
7
  static get observedAttributes() {
6
8
  return ["page", "total", "rows", "rows-options", "position"];
@@ -42,9 +44,9 @@ const _FxPagination = class _FxPagination extends FxElement {
42
44
  ${window_[window_.length - 1] !== pages && pages > 5 ? `<button type="button" class="nav" data-go="${pages}">${pages}</button>` : ""}
43
45
  <button type="button" class="nav" part="next" data-go="${current + 1}" ${current >= pages ? "disabled" : ""}>›</button>
44
46
  ${opts.length ? `
45
- <select class="nav" part="rows" aria-label="Itens por página">
46
- ${opts.map((o) => `<option value="${o}" ${Number(o) === this.rows ? "selected" : ""}>${o}</option>`).join("")}
47
- </select>` : ""}
47
+ <fx-select class="rows-sel" part="rows" size="sm" value="${this.rows}" aria-label="Itens por página">
48
+ ${opts.map((o) => `<option value="${esc(o)}">${esc(o)}</option>`).join("")}
49
+ </fx-select>` : ""}
48
50
  `);
49
51
  function total0(page, rows) {
50
52
  return (page - 1) * rows + 1;
@@ -58,9 +60,11 @@ const _FxPagination = class _FxPagination extends FxElement {
58
60
  }
59
61
  });
60
62
  });
61
- const sel = this.root.querySelector("select.nav");
62
- sel?.addEventListener("change", () => {
63
- this.rows = Number(sel.value);
63
+ const sel = this.root.querySelector("fx-select.rows-sel");
64
+ sel?.addEventListener("change", (e) => {
65
+ const value = Number(e.detail?.value);
66
+ if (!value || value === this.rows) return;
67
+ this.rows = value;
64
68
  this.page = 1;
65
69
  this.emit();
66
70
  });
@@ -99,7 +103,7 @@ _FxPagination.styles = css`
99
103
  border-color var(--fx-motion-duration-fast) var(--fx-motion-easing),
100
104
  background var(--fx-motion-duration-fast) var(--fx-motion-easing);
101
105
  }
102
- .nav:hover:not([disabled]) { border-color: var(--fx-color-primary); color: var(--fx-color-primary); }
106
+ .nav:hover:not([disabled]):not(.active) { border-color: var(--fx-color-primary); color: var(--fx-color-primary); }
103
107
  .nav[disabled] { opacity: 0.5; cursor: not-allowed; }
104
108
  .nav.active {
105
109
  background: var(--fx-color-primary);
@@ -108,7 +112,14 @@ _FxPagination.styles = css`
108
112
  font-weight: 600;
109
113
  }
110
114
  .info { color: var(--fx-text-muted); font-size: calc(var(--fx-font-size) - 2px); }
111
- select.nav { cursor: pointer; }
115
+ fx-select { vertical-align: middle; }
116
+ fx-select::part(trigger) {
117
+ min-width: 64px !important;
118
+ min-height: var(--fx-size-sm) !important;
119
+ padding: 0 var(--fx-space-sm) !important;
120
+ border-radius: var(--fx-radius-sm) !important;
121
+ font-size: calc(var(--fx-font-size) - 2px) !important;
122
+ }
112
123
  `;
113
124
  let FxPagination = _FxPagination;
114
125
  function defineFxPagination() {
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.js","sources":["../../../src/components/pagination/pagination.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\n\n/**\n * <fx-pagination> — Paginação standalone.\n *\n * Atributos: page (atual), total (itens), rows (por página), rows-options,\n * position (left|center|right).\n * Evento: `page-change` (composed, detail: { page, rows }).\n */\nexport class FxPagination extends FxElement {\n static override styles = css`\n :host {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm);\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n color: var(--fx-text-default);\n }\n :host([position='center']) { justify-content: center; }\n :host([position='right']) { justify-content: flex-end; }\n .nav {\n min-width: var(--fx-size-sm);\n height: var(--fx-size-sm);\n border: 1px solid var(--fx-border-default);\n background: var(--fx-surface-background);\n color: var(--fx-text-default);\n font-family: inherit;\n font-size: calc(var(--fx-font-size) - 2px);\n border-radius: var(--fx-radius-sm);\n cursor: pointer;\n padding: 0 var(--fx-space-sm);\n transition:\n border-color var(--fx-motion-duration-fast) var(--fx-motion-easing),\n background var(--fx-motion-duration-fast) var(--fx-motion-easing);\n }\n .nav:hover:not([disabled]) { border-color: var(--fx-color-primary); color: var(--fx-color-primary); }\n .nav[disabled] { opacity: 0.5; cursor: not-allowed; }\n .nav.active {\n background: var(--fx-color-primary);\n border-color: var(--fx-color-primary);\n color: #fff;\n font-weight: 600;\n }\n .info { color: var(--fx-text-muted); font-size: calc(var(--fx-font-size) - 2px); }\n select.nav { cursor: pointer; }\n `;\n\n static override get observedAttributes(): string[] {\n return ['page', 'total', 'rows', 'rows-options', 'position'];\n }\n\n get page(): number { return Number(this.getAttr('page', '1')) || 1; }\n set page(v: number) { this.setAttribute('page', String(v)); }\n get total(): number { return Number(this.getAttr('total', '0')) || 0; }\n set total(v: number) { this.setAttribute('total', String(v)); }\n get rows(): number { return Number(this.getAttr('rows', '10')) || 10; }\n set rows(v: number) { this.setAttribute('rows', String(v)); }\n\n private get pages(): number {\n return Math.max(1, Math.ceil(this.total / this.rows));\n }\n\n protected override render(): void {\n const pages = this.pages;\n const current = Math.min(Math.max(1, this.page), pages);\n const opts = (this.getAttr('rows-options', '5,10,20,50') || '').split(',').map((s) => s.trim()).filter(Boolean);\n\n // Janela de páginas: mostra até 5 com elipses simplificada\n const window_: number[] = [];\n for (let p = Math.max(1, current - 2); p <= Math.min(pages, current + 2); p++) window_.push(p);\n\n const from = total0(current, this.rows);\n const to = Math.min(current * this.rows, this.total);\n\n this.setTemplate(`\n <span class=\"info\">${this.total ? `${from}-${to} de ${this.total}` : '0 itens'}</span>\n <button type=\"button\" class=\"nav\" part=\"prev\" data-go=\"${current - 1}\" ${current <= 1 ? 'disabled' : ''}>‹</button>\n ${window_[0] !== 1 && pages > 5 ? `<button type=\"button\" class=\"nav\" data-go=\"1\">1</button>` : ''}\n ${window_.map((p) => `<button type=\"button\" class=\"nav ${p === current ? 'active' : ''}\" data-go=\"${p}\">${p}</button>`).join('')}\n ${window_[window_.length - 1] !== pages && pages > 5 ? `<button type=\"button\" class=\"nav\" data-go=\"${pages}\">${pages}</button>` : ''}\n <button type=\"button\" class=\"nav\" part=\"next\" data-go=\"${current + 1}\" ${current >= pages ? 'disabled' : ''}>›</button>\n ${opts.length ? `\n <select class=\"nav\" part=\"rows\" aria-label=\"Itens por página\">\n ${opts.map((o) => `<option value=\"${o}\" ${Number(o) === this.rows ? 'selected' : ''}>${o}</option>`).join('')}\n </select>` : ''}\n `);\n\n function total0(page: number, rows: number): number {\n return (page - 1) * rows + 1;\n }\n\n this.root.querySelectorAll<HTMLButtonElement>('.nav[data-go]').forEach((btn) => {\n btn.addEventListener('click', () => {\n const target = Number(btn.dataset.go);\n if (target >= 1 && target <= pages && target !== current) {\n this.page = target;\n this.emit();\n }\n });\n });\n const sel = this.root.querySelector<HTMLSelectElement>('select.nav');\n sel?.addEventListener('change', () => {\n this.rows = Number(sel.value);\n this.page = 1;\n this.emit();\n });\n }\n\n private emit(): void {\n this.dispatchEvent(new CustomEvent('page-change', {\n bubbles: true, composed: true,\n detail: { page: this.page, rows: this.rows },\n }));\n }\n}\n\nexport function defineFxPagination(): typeof FxPagination {\n return defineElement('fx-pagination', FxPagination);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pagination.js","sources":["../../../src/components/pagination/pagination.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\nimport '../select';\n\n/**\n * <fx-pagination> — Paginação standalone.\n *\n * Atributos: page (atual), total (itens), rows (por página), rows-options,\n * position (left|center|right).\n * Evento: `page-change` (composed, detail: { page, rows }).\n */\nexport class FxPagination extends FxElement {\n static override styles = css`\n :host {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm);\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n color: var(--fx-text-default);\n }\n :host([position='center']) { justify-content: center; }\n :host([position='right']) { justify-content: flex-end; }\n .nav {\n min-width: var(--fx-size-sm);\n height: var(--fx-size-sm);\n border: 1px solid var(--fx-border-default);\n background: var(--fx-surface-background);\n color: var(--fx-text-default);\n font-family: inherit;\n font-size: calc(var(--fx-font-size) - 2px);\n border-radius: var(--fx-radius-sm);\n cursor: pointer;\n padding: 0 var(--fx-space-sm);\n transition:\n border-color var(--fx-motion-duration-fast) var(--fx-motion-easing),\n background var(--fx-motion-duration-fast) var(--fx-motion-easing);\n }\n .nav:hover:not([disabled]):not(.active) { border-color: var(--fx-color-primary); color: var(--fx-color-primary); }\n .nav[disabled] { opacity: 0.5; cursor: not-allowed; }\n .nav.active {\n background: var(--fx-color-primary);\n border-color: var(--fx-color-primary);\n color: #fff;\n font-weight: 600;\n }\n .info { color: var(--fx-text-muted); font-size: calc(var(--fx-font-size) - 2px); }\n fx-select { vertical-align: middle; }\n fx-select::part(trigger) {\n min-width: 64px !important;\n min-height: var(--fx-size-sm) !important;\n padding: 0 var(--fx-space-sm) !important;\n border-radius: var(--fx-radius-sm) !important;\n font-size: calc(var(--fx-font-size) - 2px) !important;\n }\n `;\n\n static override get observedAttributes(): string[] {\n return ['page', 'total', 'rows', 'rows-options', 'position'];\n }\n\n get page(): number { return Number(this.getAttr('page', '1')) || 1; }\n set page(v: number) { this.setAttribute('page', String(v)); }\n get total(): number { return Number(this.getAttr('total', '0')) || 0; }\n set total(v: number) { this.setAttribute('total', String(v)); }\n get rows(): number { return Number(this.getAttr('rows', '10')) || 10; }\n set rows(v: number) { this.setAttribute('rows', String(v)); }\n\n private get pages(): number {\n return Math.max(1, Math.ceil(this.total / this.rows));\n }\n\n protected override render(): void {\n const pages = this.pages;\n const current = Math.min(Math.max(1, this.page), pages);\n const opts = (this.getAttr('rows-options', '5,10,20,50') || '').split(',').map((s) => s.trim()).filter(Boolean);\n\n // Janela de páginas: mostra até 5 com elipses simplificada\n const window_: number[] = [];\n for (let p = Math.max(1, current - 2); p <= Math.min(pages, current + 2); p++) window_.push(p);\n\n const from = total0(current, this.rows);\n const to = Math.min(current * this.rows, this.total);\n\n this.setTemplate(`\n <span class=\"info\">${this.total ? `${from}-${to} de ${this.total}` : '0 itens'}</span>\n <button type=\"button\" class=\"nav\" part=\"prev\" data-go=\"${current - 1}\" ${current <= 1 ? 'disabled' : ''}>‹</button>\n ${window_[0] !== 1 && pages > 5 ? `<button type=\"button\" class=\"nav\" data-go=\"1\">1</button>` : ''}\n ${window_.map((p) => `<button type=\"button\" class=\"nav ${p === current ? 'active' : ''}\" data-go=\"${p}\">${p}</button>`).join('')}\n ${window_[window_.length - 1] !== pages && pages > 5 ? `<button type=\"button\" class=\"nav\" data-go=\"${pages}\">${pages}</button>` : ''}\n <button type=\"button\" class=\"nav\" part=\"next\" data-go=\"${current + 1}\" ${current >= pages ? 'disabled' : ''}>›</button>\n ${opts.length ? `\n <fx-select class=\"rows-sel\" part=\"rows\" size=\"sm\" value=\"${this.rows}\" aria-label=\"Itens por página\">\n ${opts.map((o) => `<option value=\"${esc(o)}\">${esc(o)}</option>`).join('')}\n </fx-select>` : ''}\n `);\n\n function total0(page: number, rows: number): number {\n return (page - 1) * rows + 1;\n }\n\n this.root.querySelectorAll<HTMLButtonElement>('.nav[data-go]').forEach((btn) => {\n btn.addEventListener('click', () => {\n const target = Number(btn.dataset.go);\n if (target >= 1 && target <= pages && target !== current) {\n this.page = target;\n this.emit();\n }\n });\n });\n const sel = this.root.querySelector<HTMLElement>('fx-select.rows-sel');\n sel?.addEventListener('change', (e) => {\n const value = Number((e as CustomEvent).detail?.value);\n if (!value || value === this.rows) return;\n this.rows = value;\n this.page = 1;\n this.emit();\n });\n }\n\n private emit(): void {\n this.dispatchEvent(new CustomEvent('page-change', {\n bubbles: true, composed: true,\n detail: { page: this.page, rows: this.rows },\n }));\n }\n}\n\nexport function defineFxPagination(): typeof FxPagination {\n return defineElement('fx-pagination', FxPagination);\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"picklist.d.ts","sourceRoot":"","sources":["../../../src/components/picklist/picklist.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"picklist.d.ts","sourceRoot":"","sources":["../../../src/components/picklist/picklist.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { FxElement } from "../../core/base.js";
2
2
  import { css } from "../../core/css.js";
3
3
  import { defineElement } from "../../core/define.js";
4
+ import { esc } from "../../core/sanitize.js";
4
5
  const _FxPickList = class _FxPickList extends FxElement {
5
6
  constructor() {
6
7
  super(...arguments);
@@ -736,9 +737,6 @@ _FxPickList.styles = css`
736
737
  .list-item { animation: slideIn 0.2s ease-out; }
737
738
  `;
738
739
  let FxPickList = _FxPickList;
739
- function esc(s) {
740
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
741
- }
742
740
  function defineFxPickList() {
743
741
  return defineElement("fx-picklist", FxPickList);
744
742
  }
@@ -1 +1 @@
1
- {"version":3,"file":"picklist.js","sources":["../../../src/components/picklist/picklist.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\r\nimport { css } from '../../core/css';\r\nimport { defineElement } from '../../core/define';\r\n\r\nexport interface PickListItem {\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * <fx-picklist> - Componente para transferir itens entre duas listas.\r\n *\r\n * Permite mover itens entre uma lista de origem e uma lista de destino.\r\n * Suporta filtro, seleção múltipla, checkbox e templates customizados.\r\n *\r\n * Atributos: source, target, source-key, target-key, filter, filter-by,\r\n * filter-placeholder, dragdrop, striped, selection-mode, source-label, target-label.\r\n * Evento: `move-to-target` (composed, detail: { items }).\r\n * Evento: `move-to-source` (composed, detail: { items }).\r\n * Evento: `selection-change-source` (composed, detail: { selection }).\r\n * Evento: `selection-change-target` (composed, detail: { selection }).\r\n */\r\nexport class FxPickList extends FxElement {\r\n static override styles = css`\r\n :host {\r\n display: block;\r\n font-family: var(--fx-font-family);\r\n font-size: var(--fx-font-size);\r\n --picklist-primary: var(--fx-color-primary, #3b82f6);\r\n --picklist-border: var(--fx-border-default, #e2e8f0);\r\n --picklist-bg: var(--fx-surface-background, #ffffff);\r\n --picklist-bg-hover: var(--fx-surface-surface-hover, #f1f5f9);\r\n --picklist-text: var(--fx-text-default, #1e293b);\r\n --picklist-text-muted: var(--fx-text-muted, #64748b);\r\n --picklist-radius: var(--fx-radius-md, 8px);\r\n --picklist-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\r\n --picklist-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\r\n }\r\n * { box-sizing: border-box; }\r\n .container {\r\n display: flex;\r\n gap: var(--fx-space-sm, 8px);\r\n align-items: stretch;\r\n }\r\n .list-container {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n gap: var(--fx-space-sm, 8px);\r\n min-width: 0;\r\n }\r\n .list-label {\r\n font-weight: 600;\r\n color: var(--picklist-text);\r\n font-size: calc(var(--fx-font-size) - 1px);\r\n }\r\n .select-all-bar {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);\r\n background: linear-gradient(135deg, var(--picklist-bg), var(--picklist-bg-hover));\r\n border: 1px solid var(--picklist-border);\r\n border-radius: var(--picklist-radius);\r\n font-size: 0.9em;\r\n font-weight: 500;\r\n }\r\n .select-all-bar label {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--fx-space-sm, 10px);\r\n cursor: pointer;\r\n user-select: none;\r\n color: var(--picklist-text);\r\n }\r\n .select-all-bar input[type=\"checkbox\"] {\r\n width: 18px;\r\n height: 18px;\r\n accent-color: var(--picklist-primary);\r\n cursor: pointer;\r\n }\r\n .selection-count {\r\n font-size: 0.85em;\r\n color: var(--picklist-primary);\r\n background: color-mix(in srgb, var(--picklist-primary) 12%, transparent);\r\n padding: 4px 12px;\r\n border-radius: 20px;\r\n font-weight: 600;\r\n }\r\n .controls {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n justify-content: center;\r\n padding: var(--fx-space-xs, 6px);\r\n background: var(--picklist-bg);\r\n border: 1px solid var(--picklist-border);\r\n border-radius: var(--picklist-radius);\r\n box-shadow: var(--picklist-shadow);\r\n height: fit-content;\r\n position: sticky;\r\n top: 0;\r\n align-self: center;\r\n }\r\n .control-group {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 3px;\r\n }\r\n .control-group + .control-group {\r\n margin-top: 4px;\r\n padding-top: 6px;\r\n border-top: 1px solid var(--picklist-border);\r\n }\r\n .list-wrapper {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n gap: var(--fx-space-sm, 8px);\r\n }\r\n .filter-wrapper {\r\n margin-bottom: var(--fx-space-xs, 4px);\r\n }\r\n .filter-input {\r\n width: 100%;\r\n box-sizing: border-box;\r\n padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);\r\n padding-left: 42px;\r\n border: 1.5px solid var(--picklist-border);\r\n border-radius: var(--picklist-radius);\r\n font-family: inherit;\r\n font-size: inherit;\r\n color: var(--picklist-text);\r\n 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;\r\n transition: var(--picklist-transition);\r\n }\r\n .filter-input:focus {\r\n outline: none;\r\n border-color: var(--picklist-primary);\r\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--picklist-primary) 20%, transparent);\r\n }\r\n .filter-input::placeholder {\r\n color: var(--picklist-text-muted);\r\n }\r\n .list {\r\n list-style: none;\r\n margin: 0;\r\n padding: 0;\r\n border: 1px solid var(--picklist-border);\r\n border-radius: var(--picklist-radius);\r\n overflow: hidden;\r\n box-shadow: var(--picklist-shadow);\r\n min-height: 200px;\r\n max-height: 450px;\r\n overflow-y: auto;\r\n flex: 1;\r\n }\r\n .list::-webkit-scrollbar { width: 6px; }\r\n .list::-webkit-scrollbar-track { background: transparent; }\r\n .list::-webkit-scrollbar-thumb { background: var(--picklist-border); border-radius: 3px; }\r\n .list::-webkit-scrollbar-thumb:hover { background: var(--picklist-text-muted); }\r\n :host([striped]) .list-item:nth-child(even) {\r\n background: var(--fx-surface-surface, #f8fafc);\r\n }\r\n .list-item {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--fx-space-sm, 10px);\r\n padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);\r\n background: var(--picklist-bg);\r\n border-bottom: 1px solid var(--picklist-border);\r\n cursor: pointer;\r\n user-select: none;\r\n transition: var(--picklist-transition);\r\n }\r\n .list-item:last-child { border-bottom: none; }\r\n .list-item:hover { background: var(--picklist-bg-hover); }\r\n .list-item.selected {\r\n background: color-mix(in srgb, var(--picklist-primary) 8%, transparent);\r\n border-left: 3px solid var(--picklist-primary);\r\n padding-left: 11px;\r\n }\r\n .list-item:focus-visible {\r\n outline: none;\r\n background: color-mix(in srgb, var(--picklist-primary) 15%, transparent);\r\n }\r\n .checkbox {\r\n flex-shrink: 0;\r\n width: 18px;\r\n height: 18px;\r\n accent-color: var(--picklist-primary);\r\n cursor: pointer;\r\n transition: var(--picklist-transition);\r\n }\r\n .checkbox:hover { transform: scale(1.1); }\r\n .item-content {\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n }\r\n .empty-message {\r\n padding: var(--fx-space-xl, 32px);\r\n text-align: center;\r\n color: var(--picklist-text-muted);\r\n font-style: italic;\r\n }\r\n button.control-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 42px;\r\n height: 38px;\r\n padding: 0;\r\n border: none;\r\n border-radius: 8px;\r\n background: transparent;\r\n color: var(--picklist-text-muted);\r\n cursor: pointer;\r\n font-size: 16px;\r\n line-height: 1;\r\n transition: var(--picklist-transition);\r\n position: relative;\r\n }\r\n button.control-btn:hover:not(:disabled) {\r\n background: var(--picklist-bg-hover);\r\n color: var(--picklist-primary);\r\n transform: scale(1.1);\r\n }\r\n button.control-btn:active:not(:disabled) {\r\n transform: scale(0.92);\r\n background: color-mix(in srgb, var(--picklist-primary) 15%, transparent);\r\n }\r\n button.control-btn:focus-visible {\r\n outline: none;\r\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--picklist-primary) 30%, transparent);\r\n }\r\n button.control-btn:disabled {\r\n opacity: 0.3;\r\n cursor: not-allowed;\r\n transform: none;\r\n }\r\n .control-btn-icon { font-size: 18px; line-height: 1; }\r\n\r\n button.control-btn:hover::after {\r\n opacity: 1;\r\n transform: translateX(-50%) translateY(0);\r\n }\r\n @media (max-width: 640px) {\r\n .container { flex-direction: column; }\r\n .controls {\r\n flex-direction: row;\r\n flex-wrap: wrap;\r\n justify-content: center;\r\n position: relative;\r\n }\r\n .control-group { flex-direction: row; }\r\n .control-group + .control-group {\r\n margin-top: 0;\r\n margin-left: 4px;\r\n padding-top: 0;\r\n padding-left: 4px;\r\n border-top: none;\r\n border-left: 1px solid var(--picklist-border);\r\n }\r\n button.control-btn { width: 44px; height: 40px; }\r\n button.control-btn::after { display: none; }\r\n .list { max-height: 300px; min-height: 150px; }\r\n }\r\n @keyframes slideIn {\r\n from { opacity: 0; transform: translateX(-10px); }\r\n to { opacity: 1; transform: translateX(0); }\r\n }\r\n .list-item { animation: slideIn 0.2s ease-out; }\r\n `;\r\n\r\n static override get observedAttributes(): string[] {\r\n return [\r\n 'source',\r\n 'target',\r\n 'source-key',\r\n 'target-key',\r\n 'filter',\r\n 'filter-by',\r\n 'filter-placeholder',\r\n 'dragdrop',\r\n 'striped',\r\n 'selection-mode',\r\n 'show-select-all',\r\n 'source-label',\r\n 'target-label',\r\n ];\r\n }\r\n\r\n set source(value: PickListItem[]) {\r\n this._source = value;\r\n this._filteredSource = null;\r\n this.render();\r\n }\r\n get source(): PickListItem[] {\r\n return this._source;\r\n }\r\n private _source: PickListItem[] = [];\r\n private _filteredSource: PickListItem[] | null = null;\r\n\r\n set target(value: PickListItem[]) {\r\n this._target = value;\r\n this._filteredTarget = null;\r\n this.render();\r\n }\r\n get target(): PickListItem[] {\r\n return this._target;\r\n }\r\n private _target: PickListItem[] = [];\r\n private _filteredTarget: PickListItem[] | null = null;\r\n\r\n set sourceSelection(value: PickListItem[]) {\r\n this._sourceSelection = value;\r\n this.render();\r\n }\r\n get sourceSelection(): PickListItem[] {\r\n return this._sourceSelection;\r\n }\r\n private _sourceSelection: PickListItem[] = [];\r\n\r\n set targetSelection(value: PickListItem[]) {\r\n this._targetSelection = value;\r\n this.render();\r\n }\r\n get targetSelection(): PickListItem[] {\r\n return this._targetSelection;\r\n }\r\n private _targetSelection: PickListItem[] = [];\r\n\r\n get sourceKey(): string {\r\n return this.getAttr('source-key', '');\r\n }\r\n set sourceKey(v: string) {\r\n this.setAttribute('source-key', v);\r\n }\r\n\r\n get targetKey(): string {\r\n return this.getAttr('target-key', '');\r\n }\r\n set targetKey(v: string) {\r\n this.setAttribute('target-key', v);\r\n }\r\n\r\n get filter(): boolean {\r\n return this.hasAttr('filter');\r\n }\r\n set filter(v: boolean) {\r\n this.toggleAttr('filter', v);\r\n }\r\n\r\n get filterBy(): string {\r\n return this.getAttr('filter-by', 'label');\r\n }\r\n set filterBy(v: string) {\r\n this.setAttribute('filter-by', v);\r\n }\r\n\r\n get filterPlaceholder(): string {\r\n return this.getAttr('filter-placeholder', 'Buscar...');\r\n }\r\n set filterPlaceholder(v: string) {\r\n this.setAttribute('filter-placeholder', v);\r\n }\r\n\r\n get dragdrop(): boolean {\r\n return this.hasAttr('dragdrop');\r\n }\r\n set dragdrop(v: boolean) {\r\n this.toggleAttr('dragdrop', v);\r\n }\r\n\r\n get striped(): boolean {\r\n return this.hasAttr('striped');\r\n }\r\n set striped(v: boolean) {\r\n this.toggleAttr('striped', v);\r\n }\r\n\r\n get selectionMode(): string {\r\n const s = this.getAttr('selection-mode', '');\r\n return s === 'single' || s === 'multiple' ? s : '';\r\n }\r\n set selectionMode(v: string) {\r\n this.setAttribute('selection-mode', v);\r\n }\r\n\r\n get showSelectAll(): boolean {\r\n return this.hasAttr('show-select-all');\r\n }\r\n set showSelectAll(v: boolean) {\r\n this.toggleAttr('show-select-all', v);\r\n }\r\n\r\n get sourceLabel(): string {\r\n return this.getAttr('source-label', 'Disponíveis');\r\n }\r\n set sourceLabel(v: string) {\r\n this.setAttribute('source-label', v);\r\n }\r\n\r\n get targetLabel(): string {\r\n return this.getAttr('target-label', 'Selecionados');\r\n }\r\n set targetLabel(v: string) {\r\n this.setAttribute('target-label', v);\r\n }\r\n\r\n get sourceFilterValue(): string {\r\n return this._sourceFilterValue;\r\n }\r\n set sourceFilterValue(v: string) {\r\n this._sourceFilterValue = v;\r\n this._applySourceFilter();\r\n this._updateListDisplay();\r\n }\r\n private _sourceFilterValue = '';\r\n\r\n get targetFilterValue(): string {\r\n return this._targetFilterValue;\r\n }\r\n set targetFilterValue(v: string) {\r\n this._targetFilterValue = v;\r\n this._applyTargetFilter();\r\n this._updateListDisplay();\r\n }\r\n private _targetFilterValue = '';\r\n private _filterListenersAttached = false;\r\n\r\n private _optionTemplate: ((item: PickListItem) => string) | null = null;\r\n\r\n setOptionTemplate(template: (item: PickListItem) => string): void {\r\n this._optionTemplate = template;\r\n this.render();\r\n }\r\n\r\n protected override connectedCallback(): void {\r\n this._parseSourceAttribute();\r\n this._parseTargetAttribute();\r\n super.connectedCallback();\r\n }\r\n\r\n protected override attributeChangedCallback(): void {\r\n if (this.getAttr('source', '') !== '') {\r\n this._parseSourceAttribute();\r\n }\r\n if (this.getAttr('target', '') !== '') {\r\n this._parseTargetAttribute();\r\n }\r\n super.attributeChangedCallback();\r\n }\r\n\r\n private _parseSourceAttribute(): void {\r\n const dataAttr = this.getAttr('source', '');\r\n if (dataAttr) {\r\n try {\r\n this._source = JSON.parse(dataAttr);\r\n this._filteredSource = null;\r\n } catch {\r\n this._source = [];\r\n }\r\n }\r\n }\r\n\r\n private _parseTargetAttribute(): void {\r\n const dataAttr = this.getAttr('target', '');\r\n if (dataAttr) {\r\n try {\r\n this._target = JSON.parse(dataAttr);\r\n this._filteredTarget = null;\r\n } catch {\r\n this._target = [];\r\n }\r\n }\r\n }\r\n\r\n private _applySourceFilter(): void {\r\n if (!this._sourceFilterValue) {\r\n this._filteredSource = null;\r\n return;\r\n }\r\n const filterFields = this.filterBy.split(',').map(f => f.trim());\r\n this._filteredSource = this._source.filter(item => {\r\n return filterFields.some(field => {\r\n const value = item[field];\r\n if (value == null) return false;\r\n return String(value).toLowerCase().includes(this._sourceFilterValue.toLowerCase());\r\n });\r\n });\r\n }\r\n\r\n private _applyTargetFilter(): void {\r\n if (!this._targetFilterValue) {\r\n this._filteredTarget = null;\r\n return;\r\n }\r\n const filterFields = this.filterBy.split(',').map(f => f.trim());\r\n this._filteredTarget = this._target.filter(item => {\r\n return filterFields.some(field => {\r\n const value = item[field];\r\n if (value == null) return false;\r\n return String(value).toLowerCase().includes(this._targetFilterValue.toLowerCase());\r\n });\r\n });\r\n }\r\n\r\n private _getDisplaySource(): PickListItem[] {\r\n return this._filteredSource || this._source;\r\n }\r\n\r\n private _getDisplayTarget(): PickListItem[] {\r\n return this._filteredTarget || this._target;\r\n }\r\n\r\n private _getItemKey(item: PickListItem, index: number, isSource: boolean): string {\r\n const keyField = isSource ? this.sourceKey : this.targetKey;\r\n if (keyField && item[keyField] != null) {\r\n return String(item[keyField]);\r\n }\r\n if (item['id'] != null) return String(item['id']);\r\n if (item['key'] != null) return String(item['key']);\r\n if (item['label'] != null) return String(item['label']);\r\n if (item['name'] != null) return String(item['name']);\r\n if (item['value'] != null) return String(item['value']);\r\n return String(index);\r\n }\r\n\r\n private _getItemLabel(item: PickListItem): string {\r\n const fields = ['label', 'name', 'title', 'text', 'value'];\r\n for (const field of fields) {\r\n if (item[field] != null) {\r\n return String(item[field]);\r\n }\r\n }\r\n return JSON.stringify(item);\r\n }\r\n\r\n private _isSourceSelected(item: PickListItem, index: number): boolean {\r\n return this._sourceSelection.some(s => this._getItemKey(s, -1, true) === this._getItemKey(item, index, true));\r\n }\r\n\r\n private _isTargetSelected(item: PickListItem, index: number): boolean {\r\n return this._targetSelection.some(s => this._getItemKey(s, -1, false) === this._getItemKey(item, index, false));\r\n }\r\n\r\n private _emitMoveToTarget(): void {\r\n this.dispatchEvent(new CustomEvent('move-to-target', {\r\n bubbles: true,\r\n composed: true,\r\n detail: { items: [...this._sourceSelection], source: [...this._source], target: [...this._target] },\r\n }));\r\n }\r\n\r\n private _emitMoveToSource(): void {\r\n this.dispatchEvent(new CustomEvent('move-to-source', {\r\n bubbles: true,\r\n composed: true,\r\n detail: { items: [...this._targetSelection], source: [...this._source], target: [...this._target] },\r\n }));\r\n }\r\n\r\n private _emitSelectionChangeSource(): void {\r\n this.dispatchEvent(new CustomEvent('selection-change-source', {\r\n bubbles: true,\r\n composed: true,\r\n detail: { selection: [...this._sourceSelection] },\r\n }));\r\n }\r\n\r\n private _emitSelectionChangeTarget(): void {\r\n this.dispatchEvent(new CustomEvent('selection-change-target', {\r\n bubbles: true,\r\n composed: true,\r\n detail: { selection: [...this._targetSelection] },\r\n }));\r\n }\r\n\r\n protected override render(): void {\r\n const dSrc = this._getDisplaySource();\r\n const dTgt = this._getDisplayTarget();\r\n const hasSel = this.selectionMode;\r\n const showAll = hasSel === 'multiple' && this.showSelectAll;\r\n 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('');\r\n 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('');\r\n 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>` : '';\r\n 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>` : '';\r\n\r\n 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>`);\r\n\r\n this._attachListeners();\r\n }\r\n\r\n private _attachListeners(): void {\r\n // Listeners delegados no root, anexados uma unica vez (sobrevivem a re-renders)\r\n if (!this._filterListenersAttached) {\r\n this._filterListenersAttached = true;\r\n\r\n this.root.addEventListener('input', (e) => {\r\n const t = e.target as HTMLElement;\r\n if (t.classList.contains('select-all-checkbox')) {\r\n this._handleSelectAll(t as HTMLInputElement);\r\n return;\r\n }\r\n if (t.classList.contains('source-filter')) {\r\n this.sourceFilterValue = (t as HTMLInputElement).value;\r\n } else if (t.classList.contains('target-filter')) {\r\n this.targetFilterValue = (t as HTMLInputElement).value;\r\n }\r\n });\r\n\r\n this.root.addEventListener('click', (e) => {\r\n const t = e.target as HTMLElement;\r\n const btn = t.closest('.control-btn') as HTMLButtonElement | null;\r\n if (btn) {\r\n switch (btn.dataset.action) {\r\n case 'move-target': this._moveToTarget(); break;\r\n case 'move-all-target': this._moveAllToTarget(); break;\r\n case 'move-source': this._moveToSource(); break;\r\n case 'move-all-source': this._moveAllToSource(); break;\r\n }\r\n return;\r\n }\r\n const el = t.closest('.list-item') as HTMLElement | null;\r\n if (!el) return;\r\n const isSrc = el.dataset.list === 'source';\r\n const idx = Number(el.dataset.index);\r\n const item = (isSrc ? this._getDisplaySource() : this._getDisplayTarget())[idx];\r\n if (isSrc) this._toggleSourceSelection(item, idx); else this._toggleTargetSelection(item, idx);\r\n });\r\n }\r\n this._updateControlsState();\r\n }\r\n\r\n private _handleSelectAll(checkbox: HTMLInputElement): void {\r\n const isSrc = checkbox.dataset.list === 'source';\r\n if (isSrc) {\r\n this._sourceSelection = checkbox.checked ? [...this._getDisplaySource()] : [];\r\n this._emitSelectionChangeSource();\r\n } else {\r\n this._targetSelection = checkbox.checked ? [...this._getDisplayTarget()] : [];\r\n this._emitSelectionChangeTarget();\r\n }\r\n this._updateSelectionDisplay();\r\n this._updateControlsState();\r\n }\r\n\r\n /**\r\n * Atualiza a selecao visual in-place (classes e checkboxes dos itens existentes),\r\n * sem recriar o DOM — mantendo referencias de elementos validas durante cliques.\r\n */\r\n private _updateSelectionDisplay(): void {\r\n const updateList = (listSel: HTMLElement | null, isSelFn: (item: PickListItem, i: number) => boolean, getData: () => PickListItem[]): void => {\r\n if (!listSel) return;\r\n listSel.querySelectorAll<HTMLElement>('.list-item').forEach(el => {\r\n const idx = Number(el.dataset.index);\r\n const selected = isSelFn(getData()[idx], idx);\r\n el.classList.toggle('selected', selected);\r\n el.setAttribute('aria-selected', String(selected));\r\n const cb = el.querySelector<HTMLInputElement>('.checkbox');\r\n if (cb) cb.checked = selected;\r\n });\r\n };\r\n updateList(this.root.querySelector('.source-list'), (it, i) => this._isSourceSelected(it, i), () => this._getDisplaySource());\r\n updateList(this.root.querySelector('.target-list'), (it, i) => this._isTargetSelected(it, i), () => this._getDisplayTarget());\r\n this._updateSelectAllBars();\r\n }\r\n\r\n /** Sincroniza as barras \"Selecionar Todos\" (checkbox + contador) sem re-render completo. */\r\n private _updateSelectAllBars(): void {\r\n if (!(this.selectionMode === 'multiple' && this.showSelectAll)) return;\r\n const bars = [\r\n { el: this.root.querySelector<HTMLInputElement>('.select-all-checkbox[data-list=\"source\"]'), total: this._source.length, sel: this._sourceSelection.length },\r\n { el: this.root.querySelector<HTMLInputElement>('.select-all-checkbox[data-list=\"target\"]'), total: this._target.length, sel: this._targetSelection.length },\r\n ];\r\n bars.forEach(({ el, total, sel }) => {\r\n if (!el) return;\r\n el.checked = total > 0 && sel === total;\r\n const count = el.closest('.select-all-bar')?.querySelector('.selection-count');\r\n if (count) count.textContent = `${sel} selecionado(s)`;\r\n });\r\n }\r\n\r\n private _updateControlsState(): void {\r\n this.root.querySelectorAll<HTMLButtonElement>('.control-btn').forEach(btn => {\r\n const a = btn.dataset.action;\r\n 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);\r\n });\r\n }\r\n\r\n private _moveToTarget(): void {\r\n if (!this._sourceSelection.length) return;\r\n const items = [...this._sourceSelection];\r\n this._source = this._source.filter(s => !items.some(i => this._getItemKey(i, -1, true) === this._getItemKey(s, -1, true)));\r\n this._target = [...this._target, ...items];\r\n this._sourceSelection = [];\r\n this._filteredSource = null;\r\n this._filteredTarget = null;\r\n this._updateListDisplay();\r\n this._updateControlsState();\r\n this._emitMoveToTarget();\r\n }\r\n\r\n private _moveToSource(): void {\r\n if (!this._targetSelection.length) return;\r\n const items = [...this._targetSelection];\r\n this._target = this._target.filter(t => !items.some(i => this._getItemKey(i, -1, false) === this._getItemKey(t, -1, false)));\r\n this._source = [...this._source, ...items];\r\n this._targetSelection = [];\r\n this._filteredSource = null;\r\n this._filteredTarget = null;\r\n this._updateListDisplay();\r\n this._updateControlsState();\r\n this._emitMoveToSource();\r\n }\r\n\r\n private _moveAllToTarget(): void {\r\n const items = [...this._source];\r\n this._source = [];\r\n this._target = [...this._target, ...items];\r\n this._sourceSelection = [];\r\n this._filteredSource = null;\r\n this._filteredTarget = null;\r\n this._updateListDisplay();\r\n this._updateControlsState();\r\n this._emitMoveToTarget();\r\n }\r\n\r\n private _moveAllToSource(): void {\r\n const items = [...this._target];\r\n this._target = [];\r\n this._source = [...this._source, ...items];\r\n this._targetSelection = [];\r\n this._filteredSource = null;\r\n this._filteredTarget = null;\r\n this._updateListDisplay();\r\n this._updateControlsState();\r\n this._emitMoveToSource();\r\n }\r\n\r\n private _toggleSourceSelection(item: PickListItem, index: number): void {\r\n // Sem selection-mode definido, permite selecao simples (um item por vez)\r\n const mode = this.selectionMode || 'single';\r\n const key = this._getItemKey(item, index, true);\r\n const idx = this._sourceSelection.findIndex(s => this._getItemKey(s, -1, true) === key);\r\n if (idx >= 0) {\r\n this._sourceSelection.splice(idx, 1);\r\n } else if (mode === 'multiple') {\r\n this._sourceSelection.push(item);\r\n } else {\r\n this._sourceSelection = [item];\r\n }\r\n this._emitSelectionChangeSource();\r\n this._updateSelectionDisplay();\r\n this._updateControlsState();\r\n }\r\n\r\n private _toggleTargetSelection(item: PickListItem, index: number): void {\r\n // Sem selection-mode definido, permite selecao simples (um item por vez)\r\n const mode = this.selectionMode || 'single';\r\n const key = this._getItemKey(item, index, false);\r\n const idx = this._targetSelection.findIndex(s => this._getItemKey(s, -1, false) === key);\r\n if (idx >= 0) {\r\n this._targetSelection.splice(idx, 1);\r\n } else if (mode === 'multiple') {\r\n this._targetSelection.push(item);\r\n } else {\r\n this._targetSelection = [item];\r\n }\r\n this._emitSelectionChangeTarget();\r\n this._updateSelectionDisplay();\r\n this._updateControlsState();\r\n }\r\n\r\n private _updateListDisplay(): void {\r\n const srcWrapper = this.root.querySelector('.source-list')?.parentElement;\r\n const tgtWrapper = this.root.querySelector('.target-list')?.parentElement;\r\n const srcLabel = this.root.querySelector('.list-container:first-of-type .list-label');\r\n const tgtLabel = this.root.querySelector('.list-container:last-of-type .list-label');\r\n if (!srcWrapper || !tgtWrapper) { this.render(); return; }\r\n const dSrc = this._getDisplaySource();\r\n const dTgt = this._getDisplayTarget();\r\n const hasSel = this.selectionMode;\r\n 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('');\r\n 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('');\r\n srcWrapper.innerHTML = `<ul class=\"list source-list\" role=\"listbox\" tabindex=\"0\">${srcItems}</ul>`;\r\n tgtWrapper.innerHTML = `<ul class=\"list target-list\" role=\"listbox\" tabindex=\"0\">${tgtItems}</ul>`;\r\n if (srcLabel) srcLabel.textContent = `${this.sourceLabel} (${this._source.length})`;\r\n if (tgtLabel) tgtLabel.textContent = `${this.targetLabel} (${this._target.length})`;\r\n this._updateSelectAllBars();\r\n this._attachListeners();\r\n }\r\n}\r\n\r\nfunction esc(s: string): string {\r\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\r\n}\r\n\r\nexport function defineFxPickList(): typeof FxPickList {\r\n return defineElement('fx-picklist', FxPickList);\r\n}"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"picklist.js","sources":["../../../src/components/picklist/picklist.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\n\nexport interface PickListItem {\n [key: string]: unknown;\n}\n\n/**\n * <fx-picklist> - Componente para transferir itens entre duas listas.\n *\n * Permite mover itens entre uma lista de origem e uma lista de destino.\n * Suporta filtro, seleção múltipla, checkbox e templates customizados.\n *\n * Atributos: source, target, source-key, target-key, filter, filter-by,\n * filter-placeholder, dragdrop, striped, selection-mode, source-label, target-label.\n * Evento: `move-to-target` (composed, detail: { items }).\n * Evento: `move-to-source` (composed, detail: { items }).\n * Evento: `selection-change-source` (composed, detail: { selection }).\n * Evento: `selection-change-target` (composed, detail: { selection }).\n */\nexport class FxPickList extends FxElement {\n static override styles = css`\n :host {\n display: block;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n --picklist-primary: var(--fx-color-primary, #3b82f6);\n --picklist-border: var(--fx-border-default, #e2e8f0);\n --picklist-bg: var(--fx-surface-background, #ffffff);\n --picklist-bg-hover: var(--fx-surface-surface-hover, #f1f5f9);\n --picklist-text: var(--fx-text-default, #1e293b);\n --picklist-text-muted: var(--fx-text-muted, #64748b);\n --picklist-radius: var(--fx-radius-md, 8px);\n --picklist-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n --picklist-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n }\n * { box-sizing: border-box; }\n .container {\n display: flex;\n gap: var(--fx-space-sm, 8px);\n align-items: stretch;\n }\n .list-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--fx-space-sm, 8px);\n min-width: 0;\n }\n .list-label {\n font-weight: 600;\n color: var(--picklist-text);\n font-size: calc(var(--fx-font-size) - 1px);\n }\n .select-all-bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);\n background: linear-gradient(135deg, var(--picklist-bg), var(--picklist-bg-hover));\n border: 1px solid var(--picklist-border);\n border-radius: var(--picklist-radius);\n font-size: 0.9em;\n font-weight: 500;\n }\n .select-all-bar label {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm, 10px);\n cursor: pointer;\n user-select: none;\n color: var(--picklist-text);\n }\n .select-all-bar input[type=\"checkbox\"] {\n width: 18px;\n height: 18px;\n accent-color: var(--picklist-primary);\n cursor: pointer;\n }\n .selection-count {\n font-size: 0.85em;\n color: var(--picklist-primary);\n background: color-mix(in srgb, var(--picklist-primary) 12%, transparent);\n padding: 4px 12px;\n border-radius: 20px;\n font-weight: 600;\n }\n .controls {\n display: flex;\n flex-direction: column;\n gap: 4px;\n justify-content: center;\n padding: var(--fx-space-xs, 6px);\n background: var(--picklist-bg);\n border: 1px solid var(--picklist-border);\n border-radius: var(--picklist-radius);\n box-shadow: var(--picklist-shadow);\n height: fit-content;\n position: sticky;\n top: 0;\n align-self: center;\n }\n .control-group {\n display: flex;\n flex-direction: column;\n gap: 3px;\n }\n .control-group + .control-group {\n margin-top: 4px;\n padding-top: 6px;\n border-top: 1px solid var(--picklist-border);\n }\n .list-wrapper {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--fx-space-sm, 8px);\n }\n .filter-wrapper {\n margin-bottom: var(--fx-space-xs, 4px);\n }\n .filter-input {\n width: 100%;\n box-sizing: border-box;\n padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);\n padding-left: 42px;\n border: 1.5px solid var(--picklist-border);\n border-radius: var(--picklist-radius);\n font-family: inherit;\n font-size: inherit;\n color: var(--picklist-text);\n 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;\n transition: var(--picklist-transition);\n }\n .filter-input:focus {\n outline: none;\n border-color: var(--picklist-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--picklist-primary) 20%, transparent);\n }\n .filter-input::placeholder {\n color: var(--picklist-text-muted);\n }\n .list {\n list-style: none;\n margin: 0;\n padding: 0;\n border: 1px solid var(--picklist-border);\n border-radius: var(--picklist-radius);\n overflow: hidden;\n box-shadow: var(--picklist-shadow);\n min-height: 200px;\n max-height: 450px;\n overflow-y: auto;\n flex: 1;\n }\n .list::-webkit-scrollbar { width: 6px; }\n .list::-webkit-scrollbar-track { background: transparent; }\n .list::-webkit-scrollbar-thumb { background: var(--picklist-border); border-radius: 3px; }\n .list::-webkit-scrollbar-thumb:hover { background: var(--picklist-text-muted); }\n :host([striped]) .list-item:nth-child(even) {\n background: var(--fx-surface-surface, #f8fafc);\n }\n .list-item {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm, 10px);\n padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);\n background: var(--picklist-bg);\n border-bottom: 1px solid var(--picklist-border);\n cursor: pointer;\n user-select: none;\n transition: var(--picklist-transition);\n }\n .list-item:last-child { border-bottom: none; }\n .list-item:hover { background: var(--picklist-bg-hover); }\n .list-item.selected {\n background: color-mix(in srgb, var(--picklist-primary) 8%, transparent);\n border-left: 3px solid var(--picklist-primary);\n padding-left: 11px;\n }\n .list-item:focus-visible {\n outline: none;\n background: color-mix(in srgb, var(--picklist-primary) 15%, transparent);\n }\n .checkbox {\n flex-shrink: 0;\n width: 18px;\n height: 18px;\n accent-color: var(--picklist-primary);\n cursor: pointer;\n transition: var(--picklist-transition);\n }\n .checkbox:hover { transform: scale(1.1); }\n .item-content {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .empty-message {\n padding: var(--fx-space-xl, 32px);\n text-align: center;\n color: var(--picklist-text-muted);\n font-style: italic;\n }\n button.control-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 42px;\n height: 38px;\n padding: 0;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--picklist-text-muted);\n cursor: pointer;\n font-size: 16px;\n line-height: 1;\n transition: var(--picklist-transition);\n position: relative;\n }\n button.control-btn:hover:not(:disabled) {\n background: var(--picklist-bg-hover);\n color: var(--picklist-primary);\n transform: scale(1.1);\n }\n button.control-btn:active:not(:disabled) {\n transform: scale(0.92);\n background: color-mix(in srgb, var(--picklist-primary) 15%, transparent);\n }\n button.control-btn:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--picklist-primary) 30%, transparent);\n }\n button.control-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n transform: none;\n }\n .control-btn-icon { font-size: 18px; line-height: 1; }\n\n button.control-btn:hover::after {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n @media (max-width: 640px) {\n .container { flex-direction: column; }\n .controls {\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: center;\n position: relative;\n }\n .control-group { flex-direction: row; }\n .control-group + .control-group {\n margin-top: 0;\n margin-left: 4px;\n padding-top: 0;\n padding-left: 4px;\n border-top: none;\n border-left: 1px solid var(--picklist-border);\n }\n button.control-btn { width: 44px; height: 40px; }\n button.control-btn::after { display: none; }\n .list { max-height: 300px; min-height: 150px; }\n }\n @keyframes slideIn {\n from { opacity: 0; transform: translateX(-10px); }\n to { opacity: 1; transform: translateX(0); }\n }\n .list-item { animation: slideIn 0.2s ease-out; }\n `;\n\n static override get observedAttributes(): string[] {\n return [\n 'source',\n 'target',\n 'source-key',\n 'target-key',\n 'filter',\n 'filter-by',\n 'filter-placeholder',\n 'dragdrop',\n 'striped',\n 'selection-mode',\n 'show-select-all',\n 'source-label',\n 'target-label',\n ];\n }\n\n set source(value: PickListItem[]) {\n this._source = value;\n this._filteredSource = null;\n this.render();\n }\n get source(): PickListItem[] {\n return this._source;\n }\n private _source: PickListItem[] = [];\n private _filteredSource: PickListItem[] | null = null;\n\n set target(value: PickListItem[]) {\n this._target = value;\n this._filteredTarget = null;\n this.render();\n }\n get target(): PickListItem[] {\n return this._target;\n }\n private _target: PickListItem[] = [];\n private _filteredTarget: PickListItem[] | null = null;\n\n set sourceSelection(value: PickListItem[]) {\n this._sourceSelection = value;\n this.render();\n }\n get sourceSelection(): PickListItem[] {\n return this._sourceSelection;\n }\n private _sourceSelection: PickListItem[] = [];\n\n set targetSelection(value: PickListItem[]) {\n this._targetSelection = value;\n this.render();\n }\n get targetSelection(): PickListItem[] {\n return this._targetSelection;\n }\n private _targetSelection: PickListItem[] = [];\n\n get sourceKey(): string {\n return this.getAttr('source-key', '');\n }\n set sourceKey(v: string) {\n this.setAttribute('source-key', v);\n }\n\n get targetKey(): string {\n return this.getAttr('target-key', '');\n }\n set targetKey(v: string) {\n this.setAttribute('target-key', v);\n }\n\n get filter(): boolean {\n return this.hasAttr('filter');\n }\n set filter(v: boolean) {\n this.toggleAttr('filter', v);\n }\n\n get filterBy(): string {\n return this.getAttr('filter-by', 'label');\n }\n set filterBy(v: string) {\n this.setAttribute('filter-by', v);\n }\n\n get filterPlaceholder(): string {\n return this.getAttr('filter-placeholder', 'Buscar...');\n }\n set filterPlaceholder(v: string) {\n this.setAttribute('filter-placeholder', v);\n }\n\n get dragdrop(): boolean {\n return this.hasAttr('dragdrop');\n }\n set dragdrop(v: boolean) {\n this.toggleAttr('dragdrop', v);\n }\n\n get striped(): boolean {\n return this.hasAttr('striped');\n }\n set striped(v: boolean) {\n this.toggleAttr('striped', v);\n }\n\n get selectionMode(): string {\n const s = this.getAttr('selection-mode', '');\n return s === 'single' || s === 'multiple' ? s : '';\n }\n set selectionMode(v: string) {\n this.setAttribute('selection-mode', v);\n }\n\n get showSelectAll(): boolean {\n return this.hasAttr('show-select-all');\n }\n set showSelectAll(v: boolean) {\n this.toggleAttr('show-select-all', v);\n }\n\n get sourceLabel(): string {\n return this.getAttr('source-label', 'Disponíveis');\n }\n set sourceLabel(v: string) {\n this.setAttribute('source-label', v);\n }\n\n get targetLabel(): string {\n return this.getAttr('target-label', 'Selecionados');\n }\n set targetLabel(v: string) {\n this.setAttribute('target-label', v);\n }\n\n get sourceFilterValue(): string {\n return this._sourceFilterValue;\n }\n set sourceFilterValue(v: string) {\n this._sourceFilterValue = v;\n this._applySourceFilter();\n this._updateListDisplay();\n }\n private _sourceFilterValue = '';\n\n get targetFilterValue(): string {\n return this._targetFilterValue;\n }\n set targetFilterValue(v: string) {\n this._targetFilterValue = v;\n this._applyTargetFilter();\n this._updateListDisplay();\n }\n private _targetFilterValue = '';\n private _filterListenersAttached = false;\n\n private _optionTemplate: ((item: PickListItem) => string) | null = null;\n\n setOptionTemplate(template: (item: PickListItem) => string): void {\n this._optionTemplate = template;\n this.render();\n }\n\n protected override connectedCallback(): void {\n this._parseSourceAttribute();\n this._parseTargetAttribute();\n super.connectedCallback();\n }\n\n protected override attributeChangedCallback(): void {\n if (this.getAttr('source', '') !== '') {\n this._parseSourceAttribute();\n }\n if (this.getAttr('target', '') !== '') {\n this._parseTargetAttribute();\n }\n super.attributeChangedCallback();\n }\n\n private _parseSourceAttribute(): void {\n const dataAttr = this.getAttr('source', '');\n if (dataAttr) {\n try {\n this._source = JSON.parse(dataAttr);\n this._filteredSource = null;\n } catch {\n this._source = [];\n }\n }\n }\n\n private _parseTargetAttribute(): void {\n const dataAttr = this.getAttr('target', '');\n if (dataAttr) {\n try {\n this._target = JSON.parse(dataAttr);\n this._filteredTarget = null;\n } catch {\n this._target = [];\n }\n }\n }\n\n private _applySourceFilter(): void {\n if (!this._sourceFilterValue) {\n this._filteredSource = null;\n return;\n }\n const filterFields = this.filterBy.split(',').map(f => f.trim());\n this._filteredSource = this._source.filter(item => {\n return filterFields.some(field => {\n const value = item[field];\n if (value == null) return false;\n return String(value).toLowerCase().includes(this._sourceFilterValue.toLowerCase());\n });\n });\n }\n\n private _applyTargetFilter(): void {\n if (!this._targetFilterValue) {\n this._filteredTarget = null;\n return;\n }\n const filterFields = this.filterBy.split(',').map(f => f.trim());\n this._filteredTarget = this._target.filter(item => {\n return filterFields.some(field => {\n const value = item[field];\n if (value == null) return false;\n return String(value).toLowerCase().includes(this._targetFilterValue.toLowerCase());\n });\n });\n }\n\n private _getDisplaySource(): PickListItem[] {\n return this._filteredSource || this._source;\n }\n\n private _getDisplayTarget(): PickListItem[] {\n return this._filteredTarget || this._target;\n }\n\n private _getItemKey(item: PickListItem, index: number, isSource: boolean): string {\n const keyField = isSource ? this.sourceKey : this.targetKey;\n if (keyField && item[keyField] != null) {\n return String(item[keyField]);\n }\n if (item['id'] != null) return String(item['id']);\n if (item['key'] != null) return String(item['key']);\n if (item['label'] != null) return String(item['label']);\n if (item['name'] != null) return String(item['name']);\n if (item['value'] != null) return String(item['value']);\n return String(index);\n }\n\n private _getItemLabel(item: PickListItem): string {\n const fields = ['label', 'name', 'title', 'text', 'value'];\n for (const field of fields) {\n if (item[field] != null) {\n return String(item[field]);\n }\n }\n return JSON.stringify(item);\n }\n\n private _isSourceSelected(item: PickListItem, index: number): boolean {\n return this._sourceSelection.some(s => this._getItemKey(s, -1, true) === this._getItemKey(item, index, true));\n }\n\n private _isTargetSelected(item: PickListItem, index: number): boolean {\n return this._targetSelection.some(s => this._getItemKey(s, -1, false) === this._getItemKey(item, index, false));\n }\n\n private _emitMoveToTarget(): void {\n this.dispatchEvent(new CustomEvent('move-to-target', {\n bubbles: true,\n composed: true,\n detail: { items: [...this._sourceSelection], source: [...this._source], target: [...this._target] },\n }));\n }\n\n private _emitMoveToSource(): void {\n this.dispatchEvent(new CustomEvent('move-to-source', {\n bubbles: true,\n composed: true,\n detail: { items: [...this._targetSelection], source: [...this._source], target: [...this._target] },\n }));\n }\n\n private _emitSelectionChangeSource(): void {\n this.dispatchEvent(new CustomEvent('selection-change-source', {\n bubbles: true,\n composed: true,\n detail: { selection: [...this._sourceSelection] },\n }));\n }\n\n private _emitSelectionChangeTarget(): void {\n this.dispatchEvent(new CustomEvent('selection-change-target', {\n bubbles: true,\n composed: true,\n detail: { selection: [...this._targetSelection] },\n }));\n }\n\n protected override render(): void {\n const dSrc = this._getDisplaySource();\n const dTgt = this._getDisplayTarget();\n const hasSel = this.selectionMode;\n const showAll = hasSel === 'multiple' && this.showSelectAll;\n 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('');\n 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('');\n 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>` : '';\n 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>` : '';\n\n 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>`);\n\n this._attachListeners();\n }\n\n private _attachListeners(): void {\n // Listeners delegados no root, anexados uma unica vez (sobrevivem a re-renders)\n if (!this._filterListenersAttached) {\n this._filterListenersAttached = true;\n\n this.root.addEventListener('input', (e) => {\n const t = e.target as HTMLElement;\n if (t.classList.contains('select-all-checkbox')) {\n this._handleSelectAll(t as HTMLInputElement);\n return;\n }\n if (t.classList.contains('source-filter')) {\n this.sourceFilterValue = (t as HTMLInputElement).value;\n } else if (t.classList.contains('target-filter')) {\n this.targetFilterValue = (t as HTMLInputElement).value;\n }\n });\n\n this.root.addEventListener('click', (e) => {\n const t = e.target as HTMLElement;\n const btn = t.closest('.control-btn') as HTMLButtonElement | null;\n if (btn) {\n switch (btn.dataset.action) {\n case 'move-target': this._moveToTarget(); break;\n case 'move-all-target': this._moveAllToTarget(); break;\n case 'move-source': this._moveToSource(); break;\n case 'move-all-source': this._moveAllToSource(); break;\n }\n return;\n }\n const el = t.closest('.list-item') as HTMLElement | null;\n if (!el) return;\n const isSrc = el.dataset.list === 'source';\n const idx = Number(el.dataset.index);\n const item = (isSrc ? this._getDisplaySource() : this._getDisplayTarget())[idx];\n if (isSrc) this._toggleSourceSelection(item, idx); else this._toggleTargetSelection(item, idx);\n });\n }\n this._updateControlsState();\n }\n\n private _handleSelectAll(checkbox: HTMLInputElement): void {\n const isSrc = checkbox.dataset.list === 'source';\n if (isSrc) {\n this._sourceSelection = checkbox.checked ? [...this._getDisplaySource()] : [];\n this._emitSelectionChangeSource();\n } else {\n this._targetSelection = checkbox.checked ? [...this._getDisplayTarget()] : [];\n this._emitSelectionChangeTarget();\n }\n this._updateSelectionDisplay();\n this._updateControlsState();\n }\n\n /**\n * Atualiza a selecao visual in-place (classes e checkboxes dos itens existentes),\n * sem recriar o DOM — mantendo referencias de elementos validas durante cliques.\n */\n private _updateSelectionDisplay(): void {\n const updateList = (listSel: HTMLElement | null, isSelFn: (item: PickListItem, i: number) => boolean, getData: () => PickListItem[]): void => {\n if (!listSel) return;\n listSel.querySelectorAll<HTMLElement>('.list-item').forEach(el => {\n const idx = Number(el.dataset.index);\n const selected = isSelFn(getData()[idx], idx);\n el.classList.toggle('selected', selected);\n el.setAttribute('aria-selected', String(selected));\n const cb = el.querySelector<HTMLInputElement>('.checkbox');\n if (cb) cb.checked = selected;\n });\n };\n updateList(this.root.querySelector('.source-list'), (it, i) => this._isSourceSelected(it, i), () => this._getDisplaySource());\n updateList(this.root.querySelector('.target-list'), (it, i) => this._isTargetSelected(it, i), () => this._getDisplayTarget());\n this._updateSelectAllBars();\n }\n\n /** Sincroniza as barras \"Selecionar Todos\" (checkbox + contador) sem re-render completo. */\n private _updateSelectAllBars(): void {\n if (!(this.selectionMode === 'multiple' && this.showSelectAll)) return;\n const bars = [\n { el: this.root.querySelector<HTMLInputElement>('.select-all-checkbox[data-list=\"source\"]'), total: this._source.length, sel: this._sourceSelection.length },\n { el: this.root.querySelector<HTMLInputElement>('.select-all-checkbox[data-list=\"target\"]'), total: this._target.length, sel: this._targetSelection.length },\n ];\n bars.forEach(({ el, total, sel }) => {\n if (!el) return;\n el.checked = total > 0 && sel === total;\n const count = el.closest('.select-all-bar')?.querySelector('.selection-count');\n if (count) count.textContent = `${sel} selecionado(s)`;\n });\n }\n\n private _updateControlsState(): void {\n this.root.querySelectorAll<HTMLButtonElement>('.control-btn').forEach(btn => {\n const a = btn.dataset.action;\n 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);\n });\n }\n\n private _moveToTarget(): void {\n if (!this._sourceSelection.length) return;\n const items = [...this._sourceSelection];\n this._source = this._source.filter(s => !items.some(i => this._getItemKey(i, -1, true) === this._getItemKey(s, -1, true)));\n this._target = [...this._target, ...items];\n this._sourceSelection = [];\n this._filteredSource = null;\n this._filteredTarget = null;\n this._updateListDisplay();\n this._updateControlsState();\n this._emitMoveToTarget();\n }\n\n private _moveToSource(): void {\n if (!this._targetSelection.length) return;\n const items = [...this._targetSelection];\n this._target = this._target.filter(t => !items.some(i => this._getItemKey(i, -1, false) === this._getItemKey(t, -1, false)));\n this._source = [...this._source, ...items];\n this._targetSelection = [];\n this._filteredSource = null;\n this._filteredTarget = null;\n this._updateListDisplay();\n this._updateControlsState();\n this._emitMoveToSource();\n }\n\n private _moveAllToTarget(): void {\n const items = [...this._source];\n this._source = [];\n this._target = [...this._target, ...items];\n this._sourceSelection = [];\n this._filteredSource = null;\n this._filteredTarget = null;\n this._updateListDisplay();\n this._updateControlsState();\n this._emitMoveToTarget();\n }\n\n private _moveAllToSource(): void {\n const items = [...this._target];\n this._target = [];\n this._source = [...this._source, ...items];\n this._targetSelection = [];\n this._filteredSource = null;\n this._filteredTarget = null;\n this._updateListDisplay();\n this._updateControlsState();\n this._emitMoveToSource();\n }\n\n private _toggleSourceSelection(item: PickListItem, index: number): void {\n // Sem selection-mode definido, permite selecao simples (um item por vez)\n const mode = this.selectionMode || 'single';\n const key = this._getItemKey(item, index, true);\n const idx = this._sourceSelection.findIndex(s => this._getItemKey(s, -1, true) === key);\n if (idx >= 0) {\n this._sourceSelection.splice(idx, 1);\n } else if (mode === 'multiple') {\n this._sourceSelection.push(item);\n } else {\n this._sourceSelection = [item];\n }\n this._emitSelectionChangeSource();\n this._updateSelectionDisplay();\n this._updateControlsState();\n }\n\n private _toggleTargetSelection(item: PickListItem, index: number): void {\n // Sem selection-mode definido, permite selecao simples (um item por vez)\n const mode = this.selectionMode || 'single';\n const key = this._getItemKey(item, index, false);\n const idx = this._targetSelection.findIndex(s => this._getItemKey(s, -1, false) === key);\n if (idx >= 0) {\n this._targetSelection.splice(idx, 1);\n } else if (mode === 'multiple') {\n this._targetSelection.push(item);\n } else {\n this._targetSelection = [item];\n }\n this._emitSelectionChangeTarget();\n this._updateSelectionDisplay();\n this._updateControlsState();\n }\n\n private _updateListDisplay(): void {\n const srcWrapper = this.root.querySelector('.source-list')?.parentElement;\n const tgtWrapper = this.root.querySelector('.target-list')?.parentElement;\n const srcLabel = this.root.querySelector('.list-container:first-of-type .list-label');\n const tgtLabel = this.root.querySelector('.list-container:last-of-type .list-label');\n if (!srcWrapper || !tgtWrapper) { this.render(); return; }\n const dSrc = this._getDisplaySource();\n const dTgt = this._getDisplayTarget();\n const hasSel = this.selectionMode;\n 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('');\n 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('');\n srcWrapper.innerHTML = `<ul class=\"list source-list\" role=\"listbox\" tabindex=\"0\">${srcItems}</ul>`;\n tgtWrapper.innerHTML = `<ul class=\"list target-list\" role=\"listbox\" tabindex=\"0\">${tgtItems}</ul>`;\n if (srcLabel) srcLabel.textContent = `${this.sourceLabel} (${this._source.length})`;\n if (tgtLabel) tgtLabel.textContent = `${this.targetLabel} (${this._target.length})`;\n this._updateSelectAllBars();\n this._attachListeners();\n }\n}\n\nexport function defineFxPickList(): typeof FxPickList {\n return defineElement('fx-picklist', FxPickList);\n}"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/components/progress/index.ts"],"sourcesContent":["import { FxProgress, defineFxProgress } from './progress';\n\nexport { FxProgress };\n\n\ndefineFxProgress();\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'fx-progress': FxProgress;\n }\n}\n\r\n\r\n"],"names":[],"mappings":";;AAKA,iBAAA;"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/components/progress/index.ts"],"sourcesContent":["import { FxProgress, defineFxProgress } from './progress';\n\nexport { FxProgress };\n\n\ndefineFxProgress();\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'fx-progress': FxProgress;\n }\n}\n\n\n"],"names":[],"mappings":";;AAKA,iBAAA;"}
@@ -1 +1 @@
1
- {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../../src/components/progress/progress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C;;;;;;GAMG;AACH,qBAAa,UAAW,SAAQ,SAAS;IACvC,OAAgB,MAAM,SAkDpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,IAAI,KAAK,IAAI,MAAM,CAAoD;IACvE,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,EAAwE;cAExE,MAAM,IAAI,IAAI;IAwBjC,OAAO,CAAC,KAAK,CAAS;CACvB;AAED,wBAAgB,gBAAgB,IAAI,OAAO,UAAU,CAEpD"}
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../../src/components/progress/progress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;;GAMG;AACH,qBAAa,UAAW,SAAQ,SAAS;IACvC,OAAgB,MAAM,SAkDpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,IAAI,KAAK,IAAI,MAAM,CAAoD;IACvE,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,EAAwE;cAExE,MAAM,IAAI,IAAI;IAwBjC,OAAO,CAAC,KAAK,CAAS;CACvB;AAED,wBAAgB,gBAAgB,IAAI,OAAO,UAAU,CAEpD"}
@@ -1,6 +1,7 @@
1
1
  import { FxElement } from "../../core/base.js";
2
2
  import { css } from "../../core/css.js";
3
3
  import { defineElement } from "../../core/define.js";
4
+ import { esc } from "../../core/sanitize.js";
4
5
  const _FxProgress = class _FxProgress extends FxElement {
5
6
  constructor() {
6
7
  super(...arguments);
@@ -21,7 +22,7 @@ const _FxProgress = class _FxProgress extends FxElement {
21
22
  const labelText = this.getAttr("label");
22
23
  const showPct = !indeterminate && !this.hasAttr("hide-label");
23
24
  this.setTemplate(`
24
- ${labelText ? `<div class="caption" part="caption">${labelText}</div>` : ""}
25
+ ${labelText ? `<div class="caption" part="caption">${esc(labelText)}</div>` : ""}
25
26
  <div class="row">
26
27
  <div class="track" part="track" role="progressbar"
27
28
  aria-valuenow="${pct}" aria-valuemin="0" aria-valuemax="100">
@@ -1 +1 @@
1
- {"version":3,"file":"progress.js","sources":["../../../src/components/progress/progress.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\n\n/**\n * <fx-progress> — Indicador de progresso determinado/indeterminado.\n *\n * Atributos: value (0-100), indeterminate, variant (primary|success|warning|danger),\n * label (mostra %), size (sm|md|lg).\n * Evento: `complete` quando chega a 100.\n */\nexport class FxProgress extends FxElement {\n static override styles = css`\n :host {\n display: block;\n font-family: var(--fx-font-family);\n --_color: var(--fx-color-primary);\n }\n :host([variant='success']) { --_color: var(--fx-color-success); }\n :host([variant='warning']) { --_color: var(--fx-color-warning); }\n :host([variant='danger']) { --_color: var(--fx-color-danger); }\n .row {\n display: flex;\n align-items: center;\n gap: var(--fx-space-md);\n }\n .track {\n flex: 1;\n height: 8px;\n background: var(--fx-surface-surface-hover);\n border-radius: var(--fx-radius-full);\n overflow: hidden;\n }\n :host([size='sm']) .track { height: 4px; }\n :host([size='lg']) .track { height: 12px; }\n .bar {\n height: 100%;\n width: 0%;\n background: var(--_color);\n border-radius: var(--fx-radius-full);\n transition: width var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n :host([indeterminate]) .bar {\n width: 40%;\n animation: slide 1.2s ease-in-out infinite;\n }\n @keyframes slide {\n from { transform: translateX(-100%); }\n to { transform: translateX(350%); }\n }\n .pct {\n font-size: calc(var(--fx-font-size) - 2px);\n color: var(--fx-text-default);\n font-weight: 600;\n min-width: 34px;\n text-align: right;\n }\n .caption {\n font-size: calc(var(--fx-font-size) - 2px);\n color: var(--fx-text-muted);\n margin-bottom: var(--fx-space-xs);\n }\n `;\n\n static override get observedAttributes(): string[] {\n return ['value', 'indeterminate', 'variant', 'label', 'hide-label', 'size'];\n }\n\n get value(): number { return Number(this.getAttr('value', '0')) || 0; }\n set value(v: number) { this.setAttribute('value', String(Math.min(100, Math.max(0, v)))); }\n\n protected override render(): void {\n const pct = Math.min(100, Math.max(0, this.value));\n const indeterminate = this.hasAttr('indeterminate');\n const labelText = this.getAttr('label');\n const showPct = !indeterminate && !this.hasAttr('hide-label');\n\n this.setTemplate(`\n ${labelText ? `<div class=\"caption\" part=\"caption\">${labelText}</div>` : ''}\n <div class=\"row\">\n <div class=\"track\" part=\"track\" role=\"progressbar\"\n aria-valuenow=\"${pct}\" aria-valuemin=\"0\" aria-valuemax=\"100\">\n <div class=\"bar\" part=\"bar\" style=\"width: ${indeterminate ? '40%' : `${pct}%`}\"></div>\n </div>\n ${showPct ? `<span class=\"pct\">${pct}%</span>` : ''}\n </div>\n `);\n\n if (!this._done && !this.hasAttr('indeterminate') && pct >= 100) {\n this._done = true;\n this.dispatchEvent(new CustomEvent('complete', { bubbles: true, composed: true }));\n }\n if (pct < 100) this._done = false;\n }\n\n private _done = false;\n}\n\nexport function defineFxProgress(): typeof FxProgress {\n return defineElement('fx-progress', FxProgress);\n}\n"],"names":[],"mappings":";;;AAWO,MAAM,cAAN,MAAM,oBAAmB,UAAU;AAAA,EAAnC,cAAA;AAAA,UAAA,GAAA,SAAA;AAoFL,SAAQ,QAAQ;AAAA,EAAA;AAAA,EA/BhB,WAAoB,qBAA+B;AACjD,WAAO,CAAC,SAAS,iBAAiB,WAAW,SAAS,cAAc,MAAM;AAAA,EAC5E;AAAA,EAEA,IAAI,QAAgB;AAAE,WAAO,OAAO,KAAK,QAAQ,SAAS,GAAG,CAAC,KAAK;AAAA,EAAG;AAAA,EACtE,IAAI,MAAM,GAAW;AAAE,SAAK,aAAa,SAAS,OAAO,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;AAAA,EAAG;AAAA,EAEvE,SAAe;AAChC,UAAM,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC;AACjD,UAAM,gBAAgB,KAAK,QAAQ,eAAe;AAClD,UAAM,YAAY,KAAK,QAAQ,OAAO;AACtC,UAAM,UAAU,CAAC,iBAAiB,CAAC,KAAK,QAAQ,YAAY;AAE5D,SAAK,YAAY;AAAA,QACb,YAAY,uCAAuC,SAAS,WAAW,EAAE;AAAA;AAAA;AAAA,2BAGtD,GAAG;AAAA,sDACwB,gBAAgB,QAAQ,GAAG,GAAG,GAAG;AAAA;AAAA,UAE7E,UAAU,qBAAqB,GAAG,aAAa,EAAE;AAAA;AAAA,KAEtD;AAED,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,QAAQ,eAAe,KAAK,OAAO,KAAK;AAC/D,WAAK,QAAQ;AACb,WAAK,cAAc,IAAI,YAAY,YAAY,EAAE,SAAS,MAAM,UAAU,KAAA,CAAM,CAAC;AAAA,IACnF;AACA,QAAI,MAAM,IAAK,MAAK,QAAQ;AAAA,EAC9B;AAGF;AApFE,YAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AADpB,IAAM,aAAN;AAuFA,SAAS,mBAAsC;AACpD,SAAO,cAAc,eAAe,UAAU;AAChD;"}
1
+ {"version":3,"file":"progress.js","sources":["../../../src/components/progress/progress.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\n\n/**\n * <fx-progress> — Indicador de progresso determinado/indeterminado.\n *\n * Atributos: value (0-100), indeterminate, variant (primary|success|warning|danger),\n * label (mostra %), size (sm|md|lg).\n * Evento: `complete` quando chega a 100.\n */\nexport class FxProgress extends FxElement {\n static override styles = css`\n :host {\n display: block;\n font-family: var(--fx-font-family);\n --_color: var(--fx-color-primary);\n }\n :host([variant='success']) { --_color: var(--fx-color-success); }\n :host([variant='warning']) { --_color: var(--fx-color-warning); }\n :host([variant='danger']) { --_color: var(--fx-color-danger); }\n .row {\n display: flex;\n align-items: center;\n gap: var(--fx-space-md);\n }\n .track {\n flex: 1;\n height: 8px;\n background: var(--fx-surface-surface-hover);\n border-radius: var(--fx-radius-full);\n overflow: hidden;\n }\n :host([size='sm']) .track { height: 4px; }\n :host([size='lg']) .track { height: 12px; }\n .bar {\n height: 100%;\n width: 0%;\n background: var(--_color);\n border-radius: var(--fx-radius-full);\n transition: width var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n :host([indeterminate]) .bar {\n width: 40%;\n animation: slide 1.2s ease-in-out infinite;\n }\n @keyframes slide {\n from { transform: translateX(-100%); }\n to { transform: translateX(350%); }\n }\n .pct {\n font-size: calc(var(--fx-font-size) - 2px);\n color: var(--fx-text-default);\n font-weight: 600;\n min-width: 34px;\n text-align: right;\n }\n .caption {\n font-size: calc(var(--fx-font-size) - 2px);\n color: var(--fx-text-muted);\n margin-bottom: var(--fx-space-xs);\n }\n `;\n\n static override get observedAttributes(): string[] {\n return ['value', 'indeterminate', 'variant', 'label', 'hide-label', 'size'];\n }\n\n get value(): number { return Number(this.getAttr('value', '0')) || 0; }\n set value(v: number) { this.setAttribute('value', String(Math.min(100, Math.max(0, v)))); }\n\n protected override render(): void {\n const pct = Math.min(100, Math.max(0, this.value));\n const indeterminate = this.hasAttr('indeterminate');\n const labelText = this.getAttr('label');\n const showPct = !indeterminate && !this.hasAttr('hide-label');\n\n this.setTemplate(`\n ${labelText ? `<div class=\"caption\" part=\"caption\">${esc(labelText)}</div>` : ''}\n <div class=\"row\">\n <div class=\"track\" part=\"track\" role=\"progressbar\"\n aria-valuenow=\"${pct}\" aria-valuemin=\"0\" aria-valuemax=\"100\">\n <div class=\"bar\" part=\"bar\" style=\"width: ${indeterminate ? '40%' : `${pct}%`}\"></div>\n </div>\n ${showPct ? `<span class=\"pct\">${pct}%</span>` : ''}\n </div>\n `);\n\n if (!this._done && !this.hasAttr('indeterminate') && pct >= 100) {\n this._done = true;\n this.dispatchEvent(new CustomEvent('complete', { bubbles: true, composed: true }));\n }\n if (pct < 100) this._done = false;\n }\n\n private _done = false;\n}\n\nexport function defineFxProgress(): typeof FxProgress {\n return defineElement('fx-progress', FxProgress);\n}\n"],"names":[],"mappings":";;;;AAYO,MAAM,cAAN,MAAM,oBAAmB,UAAU;AAAA,EAAnC,cAAA;AAAA,UAAA,GAAA,SAAA;AAoFL,SAAQ,QAAQ;AAAA,EAAA;AAAA,EA/BhB,WAAoB,qBAA+B;AACjD,WAAO,CAAC,SAAS,iBAAiB,WAAW,SAAS,cAAc,MAAM;AAAA,EAC5E;AAAA,EAEA,IAAI,QAAgB;AAAE,WAAO,OAAO,KAAK,QAAQ,SAAS,GAAG,CAAC,KAAK;AAAA,EAAG;AAAA,EACtE,IAAI,MAAM,GAAW;AAAE,SAAK,aAAa,SAAS,OAAO,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;AAAA,EAAG;AAAA,EAEvE,SAAe;AAChC,UAAM,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC;AACjD,UAAM,gBAAgB,KAAK,QAAQ,eAAe;AAClD,UAAM,YAAY,KAAK,QAAQ,OAAO;AACtC,UAAM,UAAU,CAAC,iBAAiB,CAAC,KAAK,QAAQ,YAAY;AAE5D,SAAK,YAAY;AAAA,QACb,YAAY,uCAAuC,IAAI,SAAS,CAAC,WAAW,EAAE;AAAA;AAAA;AAAA,2BAG3D,GAAG;AAAA,sDACwB,gBAAgB,QAAQ,GAAG,GAAG,GAAG;AAAA;AAAA,UAE7E,UAAU,qBAAqB,GAAG,aAAa,EAAE;AAAA;AAAA,KAEtD;AAED,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,QAAQ,eAAe,KAAK,OAAO,KAAK;AAC/D,WAAK,QAAQ;AACb,WAAK,cAAc,IAAI,YAAY,YAAY,EAAE,SAAS,MAAM,UAAU,KAAA,CAAM,CAAC;AAAA,IACnF;AACA,QAAI,MAAM,IAAK,MAAK,QAAQ;AAAA,EAC9B;AAGF;AApFE,YAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AADpB,IAAM,aAAN;AAuFA,SAAS,mBAAsC;AACpD,SAAO,cAAc,eAAe,UAAU;AAChD;"}
@@ -51,7 +51,7 @@ const _FxRadio = class _FxRadio extends FxElement {
51
51
  if (this.disabled || this.checked) return;
52
52
  const name = this.getAttr("name");
53
53
  if (name) {
54
- document.querySelectorAll(`fx-radio[name="${name}"]`).forEach((r) => {
54
+ document.querySelectorAll(`fx-radio[name="${CSS.escape(name)}"]`).forEach((r) => {
55
55
  r.checked = false;
56
56
  });
57
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"radio.js","sources":["../../../src/components/radio/radio.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\n\n/**\n * <fx-radio> — Botão de opção. Radios com o mesmo `name` formam um grupo\n * (seleção exclusiva gerenciada pelo próprio componente).\n *\n * Atributos: checked, disabled, value, name, size (sm|md|lg).\n * Evento: `change` (composed, detail: { checked, value }).\n */\nexport class FxRadio extends FxElement {\n static override styles = css`\n :host {\n display: inline-flex;\n vertical-align: middle;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n .box {\n display: inline-flex;\n align-items: center;\n gap: var(--fx-space-sm);\n cursor: pointer;\n user-select: none;\n color: var(--fx-text-default);\n -webkit-tap-highlight-color: transparent;\n }\n .control {\n width: var(--fx-size-radio, 18px);\n height: var(--fx-size-radio, 18px);\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--fx-border-hover);\n border-radius: var(--fx-radius-full);\n background: var(--fx-surface-background);\n transition:\n border-color var(--fx-motion-duration-fast) var(--fx-motion-easing),\n box-shadow var(--fx-motion-duration-fast) var(--fx-motion-easing);\n }\n .box:hover .control { border-color: var(--fx-color-primary); }\n .box:focus-visible .control {\n outline: none;\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n .dot {\n width: calc(100% - 8px);\n height: calc(100% - 8px);\n border-radius: var(--fx-radius-full);\n background: var(--fx-color-primary);\n transform: scale(0);\n transition: transform var(--fx-motion-duration-fast) var(--fx-motion-easing);\n }\n :host([checked]) .control { border-color: var(--fx-color-primary); }\n :host([checked]) .dot { transform: scale(1); }\n /* Validação */\n :host([error]) .control,\n :host([invalid]) .control { border-color: var(--fx-color-danger, #dc2626); }\n :host([success]) .control,\n :host([valid]) .control { border-color: var(--fx-color-success, #16a34a); }\n .label { display: inline-flex; align-items: center; }\n :host([disabled]) .box {\n opacity: 0.55;\n cursor: not-allowed;\n pointer-events: none;\n }\n `;\n\n static override get observedAttributes(): string[] {\n return ['checked', 'disabled'];\n }\n\n get checked(): boolean {\n return this.hasAttr('checked');\n }\n set checked(value: boolean) {\n this.toggleAttr('checked', Boolean(value));\n }\n\n get disabled(): boolean {\n return this.hasAttr('disabled');\n }\n set disabled(value: boolean) {\n this.toggleAttr('disabled', Boolean(value));\n }\n\n /** Tamanho do controle. Padrão: `'md'`. */\n get size(): string {\n const s = this.getAttr('size', 'md');\n return s === 'sm' || s === 'lg' ? s : 'md';\n }\n set size(value: string) {\n this.setAttribute('size', value);\n }\n\n protected override render(): void {\n const px = this.size === 'sm' ? '14px' : this.size === 'lg' ? '22px' : '18px';\n if (!this.style.getPropertyValue('--fx-size-radio')) {\n this.style.setProperty('--fx-size-radio', px);\n }\n\n this.setTemplate(`\n <span class=\"box\" part=\"box\" role=\"radio\" tabindex=\"0\"\n aria-checked=\"${this.checked}\" aria-disabled=\"${this.disabled}\">\n <span class=\"control\" part=\"control\"><span class=\"dot\" part=\"dot\"></span></span>\n <span class=\"label\" part=\"label\"><slot></slot></span>\n </span>\n `);\n\n const box = this.root.querySelector<HTMLElement>('.box');\n if (!box) return;\n box.addEventListener('click', () => this.select());\n box.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === ' ' || (e as KeyboardEvent).key === 'Enter') {\n e.preventDefault();\n this.select();\n }\n });\n }\n\n private select(): void {\n if (this.disabled || this.checked) return;\n // Desmarca os outros radios do mesmo grupo (mesmo name).\n const name = this.getAttr('name');\n if (name) {\n document.querySelectorAll(`fx-radio[name=\"${name}\"]`).forEach((r) => {\n (r as FxRadio).checked = false;\n });\n }\n this.checked = true;\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { checked: true, value: this.getAttr('value') },\n }),\n );\n }\n}\n\nexport function defineFxRadio(): typeof FxRadio {\n return defineElement('fx-radio', FxRadio);\n}\n"],"names":[],"mappings":";;;AAWO,MAAM,WAAN,MAAM,iBAAgB,UAAU;AAAA,EA2DrC,WAAoB,qBAA+B;AACjD,WAAO,CAAC,WAAW,UAAU;AAAA,EAC/B;AAAA,EAEA,IAAI,UAAmB;AACrB,WAAO,KAAK,QAAQ,SAAS;AAAA,EAC/B;AAAA,EACA,IAAI,QAAQ,OAAgB;AAC1B,SAAK,WAAW,WAAW,QAAQ,KAAK,CAAC;AAAA,EAC3C;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO,KAAK,QAAQ,UAAU;AAAA,EAChC;AAAA,EACA,IAAI,SAAS,OAAgB;AAC3B,SAAK,WAAW,YAAY,QAAQ,KAAK,CAAC;AAAA,EAC5C;AAAA;AAAA,EAGA,IAAI,OAAe;AACjB,UAAM,IAAI,KAAK,QAAQ,QAAQ,IAAI;AACnC,WAAO,MAAM,QAAQ,MAAM,OAAO,IAAI;AAAA,EACxC;AAAA,EACA,IAAI,KAAK,OAAe;AACtB,SAAK,aAAa,QAAQ,KAAK;AAAA,EACjC;AAAA,EAEmB,SAAe;AAChC,UAAM,KAAK,KAAK,SAAS,OAAO,SAAS,KAAK,SAAS,OAAO,SAAS;AACvE,QAAI,CAAC,KAAK,MAAM,iBAAiB,iBAAiB,GAAG;AACnD,WAAK,MAAM,YAAY,mBAAmB,EAAE;AAAA,IAC9C;AAEA,SAAK,YAAY;AAAA;AAAA,wBAEG,KAAK,OAAO,oBAAoB,KAAK,QAAQ;AAAA;AAAA;AAAA;AAAA,KAIhE;AAED,UAAM,MAAM,KAAK,KAAK,cAA2B,MAAM;AACvD,QAAI,CAAC,IAAK;AACV,QAAI,iBAAiB,SAAS,MAAM,KAAK,QAAQ;AACjD,QAAI,iBAAiB,WAAW,CAAC,MAAM;AACrC,UAAK,EAAoB,QAAQ,OAAQ,EAAoB,QAAQ,SAAS;AAC5E,UAAE,eAAA;AACF,aAAK,OAAA;AAAA,MACP;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,SAAe;AACrB,QAAI,KAAK,YAAY,KAAK,QAAS;AAEnC,UAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,QAAI,MAAM;AACR,eAAS,iBAAiB,kBAAkB,IAAI,IAAI,EAAE,QAAQ,CAAC,MAAM;AAClE,UAAc,UAAU;AAAA,MAC3B,CAAC;AAAA,IACH;AACA,SAAK,UAAU;AACf,SAAK;AAAA,MACH,IAAI,YAAY,UAAU;AAAA,QACxB,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,EAAE,SAAS,MAAM,OAAO,KAAK,QAAQ,OAAO,EAAA;AAAA,MAAE,CACvD;AAAA,IAAA;AAAA,EAEL;AACF;AAhIE,SAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AADpB,IAAM,UAAN;AAmIA,SAAS,gBAAgC;AAC9C,SAAO,cAAc,YAAY,OAAO;AAC1C;"}
1
+ {"version":3,"file":"radio.js","sources":["../../../src/components/radio/radio.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\n\n/**\n * <fx-radio> — Botão de opção. Radios com o mesmo `name` formam um grupo\n * (seleção exclusiva gerenciada pelo próprio componente).\n *\n * Atributos: checked, disabled, value, name, size (sm|md|lg).\n * Evento: `change` (composed, detail: { checked, value }).\n */\nexport class FxRadio extends FxElement {\n static override styles = css`\n :host {\n display: inline-flex;\n vertical-align: middle;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n .box {\n display: inline-flex;\n align-items: center;\n gap: var(--fx-space-sm);\n cursor: pointer;\n user-select: none;\n color: var(--fx-text-default);\n -webkit-tap-highlight-color: transparent;\n }\n .control {\n width: var(--fx-size-radio, 18px);\n height: var(--fx-size-radio, 18px);\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--fx-border-hover);\n border-radius: var(--fx-radius-full);\n background: var(--fx-surface-background);\n transition:\n border-color var(--fx-motion-duration-fast) var(--fx-motion-easing),\n box-shadow var(--fx-motion-duration-fast) var(--fx-motion-easing);\n }\n .box:hover .control { border-color: var(--fx-color-primary); }\n .box:focus-visible .control {\n outline: none;\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n .dot {\n width: calc(100% - 8px);\n height: calc(100% - 8px);\n border-radius: var(--fx-radius-full);\n background: var(--fx-color-primary);\n transform: scale(0);\n transition: transform var(--fx-motion-duration-fast) var(--fx-motion-easing);\n }\n :host([checked]) .control { border-color: var(--fx-color-primary); }\n :host([checked]) .dot { transform: scale(1); }\n /* Validação */\n :host([error]) .control,\n :host([invalid]) .control { border-color: var(--fx-color-danger, #dc2626); }\n :host([success]) .control,\n :host([valid]) .control { border-color: var(--fx-color-success, #16a34a); }\n .label { display: inline-flex; align-items: center; }\n :host([disabled]) .box {\n opacity: 0.55;\n cursor: not-allowed;\n pointer-events: none;\n }\n `;\n\n static override get observedAttributes(): string[] {\n return ['checked', 'disabled'];\n }\n\n get checked(): boolean {\n return this.hasAttr('checked');\n }\n set checked(value: boolean) {\n this.toggleAttr('checked', Boolean(value));\n }\n\n get disabled(): boolean {\n return this.hasAttr('disabled');\n }\n set disabled(value: boolean) {\n this.toggleAttr('disabled', Boolean(value));\n }\n\n /** Tamanho do controle. Padrão: `'md'`. */\n get size(): string {\n const s = this.getAttr('size', 'md');\n return s === 'sm' || s === 'lg' ? s : 'md';\n }\n set size(value: string) {\n this.setAttribute('size', value);\n }\n\n protected override render(): void {\n const px = this.size === 'sm' ? '14px' : this.size === 'lg' ? '22px' : '18px';\n if (!this.style.getPropertyValue('--fx-size-radio')) {\n this.style.setProperty('--fx-size-radio', px);\n }\n\n this.setTemplate(`\n <span class=\"box\" part=\"box\" role=\"radio\" tabindex=\"0\"\n aria-checked=\"${this.checked}\" aria-disabled=\"${this.disabled}\">\n <span class=\"control\" part=\"control\"><span class=\"dot\" part=\"dot\"></span></span>\n <span class=\"label\" part=\"label\"><slot></slot></span>\n </span>\n `);\n\n const box = this.root.querySelector<HTMLElement>('.box');\n if (!box) return;\n box.addEventListener('click', () => this.select());\n box.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === ' ' || (e as KeyboardEvent).key === 'Enter') {\n e.preventDefault();\n this.select();\n }\n });\n }\n\n private select(): void {\n if (this.disabled || this.checked) return;\n // Desmarca os outros radios do mesmo grupo (mesmo name).\n const name = this.getAttr('name');\n if (name) {\n document.querySelectorAll(`fx-radio[name=\"${CSS.escape(name)}\"]`).forEach((r) => {\n (r as FxRadio).checked = false;\n });\n }\n this.checked = true;\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { checked: true, value: this.getAttr('value') },\n }),\n );\n }\n}\n\nexport function defineFxRadio(): typeof FxRadio {\n return defineElement('fx-radio', FxRadio);\n}\n"],"names":[],"mappings":";;;AAWO,MAAM,WAAN,MAAM,iBAAgB,UAAU;AAAA,EA2DrC,WAAoB,qBAA+B;AACjD,WAAO,CAAC,WAAW,UAAU;AAAA,EAC/B;AAAA,EAEA,IAAI,UAAmB;AACrB,WAAO,KAAK,QAAQ,SAAS;AAAA,EAC/B;AAAA,EACA,IAAI,QAAQ,OAAgB;AAC1B,SAAK,WAAW,WAAW,QAAQ,KAAK,CAAC;AAAA,EAC3C;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO,KAAK,QAAQ,UAAU;AAAA,EAChC;AAAA,EACA,IAAI,SAAS,OAAgB;AAC3B,SAAK,WAAW,YAAY,QAAQ,KAAK,CAAC;AAAA,EAC5C;AAAA;AAAA,EAGA,IAAI,OAAe;AACjB,UAAM,IAAI,KAAK,QAAQ,QAAQ,IAAI;AACnC,WAAO,MAAM,QAAQ,MAAM,OAAO,IAAI;AAAA,EACxC;AAAA,EACA,IAAI,KAAK,OAAe;AACtB,SAAK,aAAa,QAAQ,KAAK;AAAA,EACjC;AAAA,EAEmB,SAAe;AAChC,UAAM,KAAK,KAAK,SAAS,OAAO,SAAS,KAAK,SAAS,OAAO,SAAS;AACvE,QAAI,CAAC,KAAK,MAAM,iBAAiB,iBAAiB,GAAG;AACnD,WAAK,MAAM,YAAY,mBAAmB,EAAE;AAAA,IAC9C;AAEA,SAAK,YAAY;AAAA;AAAA,wBAEG,KAAK,OAAO,oBAAoB,KAAK,QAAQ;AAAA;AAAA;AAAA;AAAA,KAIhE;AAED,UAAM,MAAM,KAAK,KAAK,cAA2B,MAAM;AACvD,QAAI,CAAC,IAAK;AACV,QAAI,iBAAiB,SAAS,MAAM,KAAK,QAAQ;AACjD,QAAI,iBAAiB,WAAW,CAAC,MAAM;AACrC,UAAK,EAAoB,QAAQ,OAAQ,EAAoB,QAAQ,SAAS;AAC5E,UAAE,eAAA;AACF,aAAK,OAAA;AAAA,MACP;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,SAAe;AACrB,QAAI,KAAK,YAAY,KAAK,QAAS;AAEnC,UAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,QAAI,MAAM;AACR,eAAS,iBAAiB,kBAAkB,IAAI,OAAO,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM;AAC9E,UAAc,UAAU;AAAA,MAC3B,CAAC;AAAA,IACH;AACA,SAAK,UAAU;AACf,SAAK;AAAA,MACH,IAAI,YAAY,UAAU;AAAA,QACxB,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,EAAE,SAAS,MAAM,OAAO,KAAK,QAAQ,OAAO,EAAA;AAAA,MAAE,CACvD;AAAA,IAAA;AAAA,EAEL;AACF;AAhIE,SAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AADpB,IAAM,UAAN;AAmIA,SAAS,gBAAgC;AAC9C,SAAO,cAAc,YAAY,OAAO;AAC1C;"}
@@ -30,6 +30,8 @@ export declare class FxSelect extends FxElement {
30
30
  protected connectedCallback(): void;
31
31
  protected disconnectedCallback(): void;
32
32
  private select;
33
+ /** Navegação por teclado entre as opções do listbox (WCAG 2.1.1). */
34
+ private _navigateOptions;
33
35
  protected render(): void;
34
36
  }
35
37
  export declare function defineFxSelect(): typeof FxSelect;
@@ -1 +1 @@
1
- {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/components/select/select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C;;;;;;;;;;;;;;GAcG;AACH,qBAAa,QAAS,SAAQ,SAAS;IACrC,OAAgB,MAAM,SA8IpB;IAIF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,OAAO,CAAC,QAAQ,CAAC,CAAmB;IACpC,OAAO,CAAC,WAAW,CAAC,CAAqB;IAEzC,wCAAwC;IACxC,IAAI,IAAI,IAAI,MAAM,CAGjB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAErB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAEtB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;IAED,OAAO,KAAK,OAAO,GAKlB;cAEkB,iBAAiB,IAAI,IAAI;cAezB,oBAAoB,IAAI,IAAI;IAM/C,OAAO,CAAC,MAAM;cASK,MAAM,IAAI,IAAI;CAwFlC;AAED,wBAAgB,cAAc,IAAI,OAAO,QAAQ,CAEhD"}
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/components/select/select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;;;;;;;;;;GAcG;AACH,qBAAa,QAAS,SAAQ,SAAS;IACrC,OAAgB,MAAM,SA8IpB;IAIF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,OAAO,CAAC,QAAQ,CAAC,CAAmB;IACpC,OAAO,CAAC,WAAW,CAAC,CAAqB;IAEzC,wCAAwC;IACxC,IAAI,IAAI,IAAI,MAAM,CAGjB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAErB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAEtB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;IAED,OAAO,KAAK,OAAO,GAKlB;cAEkB,iBAAiB,IAAI,IAAI;cAezB,oBAAoB,IAAI,IAAI;IAM/C,OAAO,CAAC,MAAM;IASd,qEAAqE;IACrE,OAAO,CAAC,gBAAgB;cAiBL,MAAM,IAAI,IAAI;CAqGlC;AAED,wBAAgB,cAAc,IAAI,OAAO,QAAQ,CAEhD"}
@@ -1,6 +1,7 @@
1
1
  import { FxElement } from "../../core/base.js";
2
2
  import { css } from "../../core/css.js";
3
3
  import { defineElement } from "../../core/define.js";
4
+ import { esc } from "../../core/sanitize.js";
4
5
  const _FxSelect = class _FxSelect extends FxElement {
5
6
  // `value` fica FORA da observação: refleti-lo no change não pode
6
7
  // re-renderizar o template e fechar o dropdown.
@@ -58,6 +59,23 @@ const _FxSelect = class _FxSelect extends FxElement {
58
59
  new CustomEvent("change", { bubbles: true, composed: true, detail: { value } })
59
60
  );
60
61
  }
62
+ /** Navegação por teclado entre as opções do listbox (WCAG 2.1.1). */
63
+ _navigateOptions(e) {
64
+ e.preventDefault();
65
+ if (!this.hasAttr("open")) {
66
+ this.toggleAttribute("open");
67
+ this.render();
68
+ }
69
+ const opts = Array.from(this.root.querySelectorAll(".opt"));
70
+ if (!opts.length) return;
71
+ const current = opts.indexOf(this.root.activeElement);
72
+ let next = 0;
73
+ if (e.key === "ArrowDown") next = current === -1 ? 0 : Math.min(current + 1, opts.length - 1);
74
+ else if (e.key === "ArrowUp") next = current === -1 ? opts.length - 1 : Math.max(current - 1, 0);
75
+ else if (e.key === "Home") next = 0;
76
+ else if (e.key === "End") next = opts.length - 1;
77
+ opts[next]?.focus();
78
+ }
61
79
  render() {
62
80
  const prevOpen = this.hasAttr("open");
63
81
  const prevSearch = this.root.querySelector(".search");
@@ -75,18 +93,18 @@ const _FxSelect = class _FxSelect extends FxElement {
75
93
  const filtered = search ? opts.filter((o) => o.label.toLowerCase().includes(search.toLowerCase())) : opts;
76
94
  this.setTemplate(`
77
95
  <span class="trigger" part="trigger" role="button" tabindex="${this.disabled ? -1 : 0}" aria-haspopup="listbox" aria-expanded="${prevOpen}">
78
- <span class="${selectedLabel ? "label" : "placeholder"}">${selectedLabel || placeholder}</span>
96
+ <span class="${selectedLabel ? "label" : "placeholder"}">${esc(selectedLabel) || esc(placeholder)}</span>
79
97
  <span class="actions">
80
98
  ${this.hasAttr("clearable") && current ? '<button type="button" class="clear" part="clear" aria-label="Limpar">×</button>' : ""}
81
99
  <span class="caret">▼</span>
82
100
  </span>
83
101
  </span>
84
102
  <div class="panel" part="panel" role="listbox">
85
- ${this.hasAttr("searchable") ? `<input class="search" part="search" type="text" placeholder="${this.getAttr("search-placeholder", "Pesquisar…")}">` : ""}
103
+ ${this.hasAttr("searchable") ? `<input class="search" part="search" type="text" placeholder="${esc(this.getAttr("search-placeholder", "Pesquisar…"))}">` : ""}
86
104
  ${filtered.map((o) => `
87
- <button type="button" class="opt" role="option" data-value="${o.value}"
88
- aria-selected="${o.value === current}">${o.label}</button>`).join("")}
89
- ${filtered.length === 0 ? `<div class="empty">${this.getAttr("no-results", "Nenhum resultado")}</div>` : ""}
105
+ <button type="button" class="opt" role="option" data-value="${esc(o.value)}"
106
+ aria-selected="${o.value === current}">${esc(o.label)}</button>`).join("")}
107
+ ${filtered.length === 0 ? `<div class="empty">${esc(this.getAttr("no-results", "Nenhum resultado"))}</div>` : ""}
90
108
  </div>
91
109
  `);
92
110
  if (prevOpen) this.setAttribute("open", "");
@@ -114,9 +132,22 @@ const _FxSelect = class _FxSelect extends FxElement {
114
132
  this.root.querySelector(".search")?.focus();
115
133
  });
116
134
  trigger.addEventListener("keydown", (e) => {
135
+ if (this.disabled) return;
117
136
  if (e.key === "Enter" || e.key === " ") {
118
137
  e.preventDefault();
119
138
  trigger.click();
139
+ return;
140
+ }
141
+ if (e.key === "Escape") {
142
+ if (this.hasAttr("open")) {
143
+ this.removeAttribute("open");
144
+ this.render();
145
+ this.root.querySelector(".trigger")?.focus();
146
+ }
147
+ return;
148
+ }
149
+ if (e.key === "ArrowDown" || e.key === "ArrowUp" || e.key === "Home" || e.key === "End") {
150
+ this._navigateOptions(e);
120
151
  }
121
152
  });
122
153
  this.root.querySelector(".clear")?.addEventListener("click", (e) => {