@wrrdev/fenix-ui 1.0.14 → 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 (111) 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.map +1 -1
  106. package/dist/index.d.ts +2 -1
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +4 -0
  109. package/dist/index.js.map +1 -1
  110. package/dist/plugins/auto-import.js.map +1 -1
  111. 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) => {