@wrrdev/fenix-ui 1.1.15 → 1.1.17

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 (107) hide show
  1. package/README.md +2 -2
  2. package/dist/components/autocomplete/autocomplete.d.ts +3 -1
  3. package/dist/components/autocomplete/autocomplete.d.ts.map +1 -1
  4. package/dist/components/autocomplete/autocomplete.js +7 -1
  5. package/dist/components/autocomplete/autocomplete.js.map +1 -1
  6. package/dist/components/avatar/avatar.d.ts +1 -0
  7. package/dist/components/avatar/avatar.d.ts.map +1 -1
  8. package/dist/components/avatar/avatar.js +3 -0
  9. package/dist/components/avatar/avatar.js.map +1 -1
  10. package/dist/components/badge/badge.d.ts +4 -0
  11. package/dist/components/badge/badge.d.ts.map +1 -1
  12. package/dist/components/badge/badge.js +12 -0
  13. package/dist/components/badge/badge.js.map +1 -1
  14. package/dist/components/button/button.d.ts +2 -0
  15. package/dist/components/button/button.d.ts.map +1 -1
  16. package/dist/components/button/button.js +6 -0
  17. package/dist/components/button/button.js.map +1 -1
  18. package/dist/components/card/card.d.ts +2 -0
  19. package/dist/components/card/card.d.ts.map +1 -1
  20. package/dist/components/card/card.js +6 -0
  21. package/dist/components/card/card.js.map +1 -1
  22. package/dist/components/checkbox/checkbox.d.ts +5 -1
  23. package/dist/components/checkbox/checkbox.d.ts.map +1 -1
  24. package/dist/components/checkbox/checkbox.js +7 -8
  25. package/dist/components/checkbox/checkbox.js.map +1 -1
  26. package/dist/components/datepicker/datepicker.d.ts +17 -2
  27. package/dist/components/datepicker/datepicker.d.ts.map +1 -1
  28. package/dist/components/datepicker/datepicker.js +113 -42
  29. package/dist/components/datepicker/datepicker.js.map +1 -1
  30. package/dist/components/dialog/dialog.d.ts +4 -1
  31. package/dist/components/dialog/dialog.d.ts.map +1 -1
  32. package/dist/components/dialog/dialog.js +41 -18
  33. package/dist/components/dialog/dialog.js.map +1 -1
  34. package/dist/components/drawer/drawer.d.ts +5 -1
  35. package/dist/components/drawer/drawer.d.ts.map +1 -1
  36. package/dist/components/drawer/drawer.js +39 -17
  37. package/dist/components/drawer/drawer.js.map +1 -1
  38. package/dist/components/fileupload/fileupload.d.ts +13 -1
  39. package/dist/components/fileupload/fileupload.d.ts.map +1 -1
  40. package/dist/components/fileupload/fileupload.js +29 -1
  41. package/dist/components/fileupload/fileupload.js.map +1 -1
  42. package/dist/components/floatlabel/floatlabel.d.ts +15 -0
  43. package/dist/components/floatlabel/floatlabel.d.ts.map +1 -1
  44. package/dist/components/floatlabel/floatlabel.js +47 -1
  45. package/dist/components/floatlabel/floatlabel.js.map +1 -1
  46. package/dist/components/icon/icon.d.ts +4 -0
  47. package/dist/components/icon/icon.d.ts.map +1 -1
  48. package/dist/components/icon/icon.js +12 -0
  49. package/dist/components/icon/icon.js.map +1 -1
  50. package/dist/components/input/input.d.ts +9 -2
  51. package/dist/components/input/input.d.ts.map +1 -1
  52. package/dist/components/input/input.js +56 -8
  53. package/dist/components/input/input.js.map +1 -1
  54. package/dist/components/multiselect/multiselect.d.ts +8 -1
  55. package/dist/components/multiselect/multiselect.d.ts.map +1 -1
  56. package/dist/components/multiselect/multiselect.js +61 -9
  57. package/dist/components/multiselect/multiselect.js.map +1 -1
  58. package/dist/components/orderlist/orderlist.d.ts +7 -0
  59. package/dist/components/orderlist/orderlist.d.ts.map +1 -1
  60. package/dist/components/orderlist/orderlist.js +34 -2
  61. package/dist/components/orderlist/orderlist.js.map +1 -1
  62. package/dist/components/pagination/pagination.d.ts +3 -0
  63. package/dist/components/pagination/pagination.d.ts.map +1 -1
  64. package/dist/components/pagination/pagination.js +19 -9
  65. package/dist/components/pagination/pagination.js.map +1 -1
  66. package/dist/components/radio/radio.d.ts +6 -0
  67. package/dist/components/radio/radio.d.ts.map +1 -1
  68. package/dist/components/radio/radio.js +12 -6
  69. package/dist/components/radio/radio.js.map +1 -1
  70. package/dist/components/select/select.d.ts +19 -1
  71. package/dist/components/select/select.d.ts.map +1 -1
  72. package/dist/components/select/select.js +116 -10
  73. package/dist/components/select/select.js.map +1 -1
  74. package/dist/components/switch/switch.d.ts +4 -1
  75. package/dist/components/switch/switch.d.ts.map +1 -1
  76. package/dist/components/switch/switch.js +2 -1
  77. package/dist/components/switch/switch.js.map +1 -1
  78. package/dist/components/table/table.d.ts +27 -0
  79. package/dist/components/table/table.d.ts.map +1 -1
  80. package/dist/components/table/table.js +126 -24
  81. package/dist/components/table/table.js.map +1 -1
  82. package/dist/components/tabs/tabs.d.ts +6 -0
  83. package/dist/components/tabs/tabs.d.ts.map +1 -1
  84. package/dist/components/tabs/tabs.js +34 -0
  85. package/dist/components/tabs/tabs.js.map +1 -1
  86. package/dist/components/textarea/textarea.d.ts +5 -1
  87. package/dist/components/textarea/textarea.d.ts.map +1 -1
  88. package/dist/components/textarea/textarea.js +25 -6
  89. package/dist/components/textarea/textarea.js.map +1 -1
  90. package/dist/core/jsx.d.ts +11 -5
  91. package/dist/core/jsx.d.ts.map +1 -1
  92. package/dist/core/jsx.js.map +1 -1
  93. package/dist/core/modal.d.ts +31 -0
  94. package/dist/core/modal.d.ts.map +1 -0
  95. package/dist/core/modal.js +61 -0
  96. package/dist/core/modal.js.map +1 -0
  97. package/dist/core/page-range.d.ts +31 -0
  98. package/dist/core/page-range.d.ts.map +1 -0
  99. package/dist/core/page-range.js +41 -0
  100. package/dist/core/page-range.js.map +1 -0
  101. package/dist/docs/componentes/input.doc.d.ts.map +1 -1
  102. package/dist/docs/componentes/orderlist.doc.d.ts.map +1 -1
  103. package/dist/docs/componentes/table.doc.d.ts.map +1 -1
  104. package/dist/fenix-ui.umd.min.js +261 -227
  105. package/dist/fenix-ui4.esm.js +987 -260
  106. package/dist/fenix-ui4.esm.js.map +1 -1
  107. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"icon.js","sources":["../../../src/components/icon/icon.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\nimport { FENIX_ICON_BASE_CSS, isFenixIconName } from '../../icons/base-css';\nimport { loadFenixIconsFont } from '../../icons/font';\n\n/**\n * <fx-icon> — Glifo da Fenix Icons com AUTOCOMPLETE no editor.\n *\n * Por que existe: a forma antiga (`<i class=\"fx-icon fx-icon-home\">`) é CSS\n * puro — o TypeScript não valida nem sugere nada enquanto você digita, e o\n * auto-import só injeta o import. Com o elemento, o atributo `name` é tipado\n * como `FenixIconName`, então Volar/vue-tsc, React e TSX listam os +4.000\n * glifos válidos (e o hover mostra a assinatura do atributo).\n *\n * Atributos:\n * - name → nome do glifo (ex.: `home`); texto livre/emoji também funciona\n * - size → sm | md | lg | xl (default: 1em, herda o texto ao redor)\n * - label → nome acessível; sem label o ícone é aria-hidden (decorativo)\n * - fill → variante preenchida\n * - bold → traço mais pesado\n *\n * O glifo sai por LIGADURA (o nome vira o conteúdo de texto com a\n * font-family de ícones) — por isso funciona dentro do Shadow DOM, onde as\n * classes `fx-icon-<nome>` do documento não atravessam a fronteira.\n *\n * Tamanho via CSS: --fx-icon-size (-sm/-md/-lg/-xl).\n */\nexport class FxIcon extends FxElement {\n static override styles = css`\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n vertical-align: middle;\n line-height: 1;\n color: currentColor;\n font-size: var(--fx-icon-size, 1em);\n }\n :host([size='sm']) { font-size: var(--fx-icon-size-sm, 16px); }\n :host([size='md']) { font-size: var(--fx-icon-size-md, 20px); }\n :host([size='lg']) { font-size: var(--fx-icon-size-lg, 24px); }\n :host([size='xl']) { font-size: var(--fx-icon-size-xl, 32px); }\n :host([hidden]) { display: none; }\n .icon { display: inline-block; }\n /* Variantes da fonte (FILL/wght): vencem a classe base .fx-icon. */\n :host([fill]) .icon { font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24; }\n :host([bold]) .icon { font-variation-settings: 'FILL' 0, 'wght' 600, 'GRAD' 0, 'opsz' 24; }\n ${FENIX_ICON_BASE_CSS}\n `;\n\n static override get observedAttributes(): string[] {\n return ['name', 'size', 'label', 'fill', 'bold'];\n }\n\n /** Nome do glifo (ou texto livre/emoji). */\n get name(): string {\n return this.getAttr('name');\n }\n set name(value: string) {\n this.setAttribute('name', value);\n }\n\n /** Tamanho: '' (herda 1em) | 'sm' | 'md' | 'lg' | 'xl'. */\n get size(): string {\n return this.getAttr('size');\n }\n set size(value: string) {\n if (value) this.setAttribute('size', value);\n else this.removeAttribute('size');\n }\n\n /** Nome acessível; vazio = ícone decorativo (aria-hidden). */\n get label(): string {\n return this.getAttr('label');\n }\n set label(value: string) {\n if (value) this.setAttribute('label', value);\n else this.removeAttribute('label');\n }\n\n protected override connectedCallback(): void {\n // O glifo depende do @font-face: garante o CSS leve (sem as 4k classes).\n loadFenixIconsFont();\n super.connectedCallback();\n }\n\n protected override render(): void {\n const name = this.getAttr('name').trim();\n const label = this.getAttr('label').trim();\n const a11y = label ? `role=\"img\" aria-label=\"${esc(label)}\"` : 'aria-hidden=\"true\"';\n if (!name) {\n this.setTemplate(`<span class=\"icon\" part=\"icon\" ${a11y}></span>`);\n return;\n }\n // Nome válido → ligadura (glifo). Emoji/texto livre → texto puro.\n const inner = isFenixIconName(name)\n ? `<i class=\"icon fx-icon\" part=\"icon\" ${a11y}>${esc(name)}</i>`\n : `<span class=\"icon\" part=\"icon\" ${a11y}>${esc(name)}</span>`;\n this.setTemplate(inner);\n }\n}\n\nexport function defineFxIcon(): typeof FxIcon {\n return defineElement('fx-icon', FxIcon);\n}\n"],"names":[],"mappings":";;;;;;AA6BO,MAAM,UAAN,MAAM,gBAAe,UAAU;AAAA,EAuBpC,WAAoB,qBAA+B;AACjD,WAAO,CAAC,QAAQ,QAAQ,SAAS,QAAQ,MAAM;AAAA,EACjD;AAAA;AAAA,EAGA,IAAI,OAAe;AACjB,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AAAA,EACA,IAAI,KAAK,OAAe;AACtB,SAAK,aAAa,QAAQ,KAAK;AAAA,EACjC;AAAA;AAAA,EAGA,IAAI,OAAe;AACjB,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AAAA,EACA,IAAI,KAAK,OAAe;AACtB,QAAI,MAAO,MAAK,aAAa,QAAQ,KAAK;AAAA,QACrC,MAAK,gBAAgB,MAAM;AAAA,EAClC;AAAA;AAAA,EAGA,IAAI,QAAgB;AAClB,WAAO,KAAK,QAAQ,OAAO;AAAA,EAC7B;AAAA,EACA,IAAI,MAAM,OAAe;AACvB,QAAI,MAAO,MAAK,aAAa,SAAS,KAAK;AAAA,QACtC,MAAK,gBAAgB,OAAO;AAAA,EACnC;AAAA,EAEmB,oBAA0B;AAE3C,uBAAA;AACA,UAAM,kBAAA;AAAA,EACR;AAAA,EAEmB,SAAe;AAChC,UAAM,OAAO,KAAK,QAAQ,MAAM,EAAE,KAAA;AAClC,UAAM,QAAQ,KAAK,QAAQ,OAAO,EAAE,KAAA;AACpC,UAAM,OAAO,QAAQ,0BAA0B,IAAI,KAAK,CAAC,MAAM;AAC/D,QAAI,CAAC,MAAM;AACT,WAAK,YAAY,kCAAkC,IAAI,UAAU;AACjE;AAAA,IACF;AAEA,UAAM,QAAQ,gBAAgB,IAAI,IAC9B,uCAAuC,IAAI,IAAI,IAAI,IAAI,CAAC,SACxD,kCAAkC,IAAI,IAAI,IAAI,IAAI,CAAC;AACvD,SAAK,YAAY,KAAK;AAAA,EACxB;AACF;AAxEE,QAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAmBrB,mBAAmB;AAAA;AApBlB,IAAM,SAAN;AA2EA,SAAS,eAA8B;AAC5C,SAAO,cAAc,WAAW,MAAM;AACxC;"}
1
+ {"version":3,"file":"icon.js","sources":["../../../src/components/icon/icon.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\nimport { FENIX_ICON_BASE_CSS, isFenixIconName } from '../../icons/base-css';\nimport { loadFenixIconsFont } from '../../icons/font';\n\n/**\n * <fx-icon> — Glifo da Fenix Icons com AUTOCOMPLETE no editor.\n *\n * Por que existe: a forma antiga (`<i class=\"fx-icon fx-icon-home\">`) é CSS\n * puro — o TypeScript não valida nem sugere nada enquanto você digita, e o\n * auto-import só injeta o import. Com o elemento, o atributo `name` é tipado\n * como `FenixIconName`, então Volar/vue-tsc, React e TSX listam os +4.000\n * glifos válidos (e o hover mostra a assinatura do atributo).\n *\n * Atributos:\n * - name → nome do glifo (ex.: `home`); texto livre/emoji também funciona\n * - size → sm | md | lg | xl (default: 1em, herda o texto ao redor)\n * - label → nome acessível; sem label o ícone é aria-hidden (decorativo)\n * - fill → variante preenchida\n * - bold → traço mais pesado\n *\n * O glifo sai por LIGADURA (o nome vira o conteúdo de texto com a\n * font-family de ícones) — por isso funciona dentro do Shadow DOM, onde as\n * classes `fx-icon-<nome>` do documento não atravessam a fronteira.\n *\n * Tamanho via CSS: --fx-icon-size (-sm/-md/-lg/-xl).\n */\nexport class FxIcon extends FxElement {\n static override styles = css`\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n vertical-align: middle;\n line-height: 1;\n color: currentColor;\n font-size: var(--fx-icon-size, 1em);\n }\n :host([size='sm']) { font-size: var(--fx-icon-size-sm, 16px); }\n :host([size='md']) { font-size: var(--fx-icon-size-md, 20px); }\n :host([size='lg']) { font-size: var(--fx-icon-size-lg, 24px); }\n :host([size='xl']) { font-size: var(--fx-icon-size-xl, 32px); }\n :host([hidden]) { display: none; }\n .icon { display: inline-block; }\n /* Variantes da fonte (FILL/wght): vencem a classe base .fx-icon. */\n :host([fill]) .icon { font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24; }\n :host([bold]) .icon { font-variation-settings: 'FILL' 0, 'wght' 600, 'GRAD' 0, 'opsz' 24; }\n ${FENIX_ICON_BASE_CSS}\n `;\n\n static override get observedAttributes(): string[] {\n return ['name', 'size', 'label', 'fill', 'bold'];\n }\n\n /** Nome do glifo (ou texto livre/emoji). */\n get name(): string {\n return this.getAttr('name');\n }\n set name(value: string) {\n this.setAttribute('name', value);\n }\n\n /** Tamanho: '' (herda 1em) | 'sm' | 'md' | 'lg' | 'xl'. */\n get size(): string {\n return this.getAttr('size');\n }\n set size(value: string) {\n if (value) this.setAttribute('size', value);\n else this.removeAttribute('size');\n }\n\n /** Nome acessível; vazio = ícone decorativo (aria-hidden). */\n get label(): string {\n return this.getAttr('label');\n }\n set label(value: string) {\n if (value) this.setAttribute('label', value);\n else this.removeAttribute('label');\n }\n\n get fill(): boolean {\n return this.hasAttr('fill');\n }\n set fill(value: boolean) {\n this.toggleAttr('fill', Boolean(value));\n }\n\n get bold(): boolean {\n return this.hasAttr('bold');\n }\n set bold(value: boolean) {\n this.toggleAttr('bold', Boolean(value));\n }\n\n protected override connectedCallback(): void {\n // O glifo depende do @font-face: garante o CSS leve (sem as 4k classes).\n loadFenixIconsFont();\n super.connectedCallback();\n }\n\n protected override render(): void {\n const name = this.getAttr('name').trim();\n const label = this.getAttr('label').trim();\n const a11y = label ? `role=\"img\" aria-label=\"${esc(label)}\"` : 'aria-hidden=\"true\"';\n if (!name) {\n this.setTemplate(`<span class=\"icon\" part=\"icon\" ${a11y}></span>`);\n return;\n }\n // Nome válido → ligadura (glifo). Emoji/texto livre → texto puro.\n const inner = isFenixIconName(name)\n ? `<i class=\"icon fx-icon\" part=\"icon\" ${a11y}>${esc(name)}</i>`\n : `<span class=\"icon\" part=\"icon\" ${a11y}>${esc(name)}</span>`;\n this.setTemplate(inner);\n }\n}\n\nexport function defineFxIcon(): typeof FxIcon {\n return defineElement('fx-icon', FxIcon);\n}\n"],"names":[],"mappings":";;;;;;AA6BO,MAAM,UAAN,MAAM,gBAAe,UAAU;AAAA,EAuBpC,WAAoB,qBAA+B;AACjD,WAAO,CAAC,QAAQ,QAAQ,SAAS,QAAQ,MAAM;AAAA,EACjD;AAAA;AAAA,EAGA,IAAI,OAAe;AACjB,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AAAA,EACA,IAAI,KAAK,OAAe;AACtB,SAAK,aAAa,QAAQ,KAAK;AAAA,EACjC;AAAA;AAAA,EAGA,IAAI,OAAe;AACjB,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AAAA,EACA,IAAI,KAAK,OAAe;AACtB,QAAI,MAAO,MAAK,aAAa,QAAQ,KAAK;AAAA,QACrC,MAAK,gBAAgB,MAAM;AAAA,EAClC;AAAA;AAAA,EAGA,IAAI,QAAgB;AAClB,WAAO,KAAK,QAAQ,OAAO;AAAA,EAC7B;AAAA,EACA,IAAI,MAAM,OAAe;AACvB,QAAI,MAAO,MAAK,aAAa,SAAS,KAAK;AAAA,QACtC,MAAK,gBAAgB,OAAO;AAAA,EACnC;AAAA,EAEA,IAAI,OAAgB;AAClB,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AAAA,EACA,IAAI,KAAK,OAAgB;AACvB,SAAK,WAAW,QAAQ,QAAQ,KAAK,CAAC;AAAA,EACxC;AAAA,EAEA,IAAI,OAAgB;AAClB,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AAAA,EACA,IAAI,KAAK,OAAgB;AACvB,SAAK,WAAW,QAAQ,QAAQ,KAAK,CAAC;AAAA,EACxC;AAAA,EAEmB,oBAA0B;AAE3C,uBAAA;AACA,UAAM,kBAAA;AAAA,EACR;AAAA,EAEmB,SAAe;AAChC,UAAM,OAAO,KAAK,QAAQ,MAAM,EAAE,KAAA;AAClC,UAAM,QAAQ,KAAK,QAAQ,OAAO,EAAE,KAAA;AACpC,UAAM,OAAO,QAAQ,0BAA0B,IAAI,KAAK,CAAC,MAAM;AAC/D,QAAI,CAAC,MAAM;AACT,WAAK,YAAY,kCAAkC,IAAI,UAAU;AACjE;AAAA,IACF;AAEA,UAAM,QAAQ,gBAAgB,IAAI,IAC9B,uCAAuC,IAAI,IAAI,IAAI,IAAI,CAAC,SACxD,kCAAkC,IAAI,IAAI,IAAI,IAAI,CAAC;AACvD,SAAK,YAAY,KAAK;AAAA,EACxB;AACF;AAtFE,QAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAmBrB,mBAAmB;AAAA;AApBlB,IAAM,SAAN;AAyFA,SAAS,eAA8B;AAC5C,SAAO,cAAc,WAAW,MAAM;AACxC;"}
@@ -7,7 +7,8 @@ import type { FxInputType } from '../../core/jsx';
7
7
  * (via atributo `name`), recebe reset/disable do form, é alvo de
8
8
  * `<label for>`/`autofocus` e o Enter submete o form.
9
9
  *
10
- * Atributos: type (text|number|password), value, name,
10
+ * Atributos: type (text|number|password|email|tel|url|search|date|time|
11
+ * datetime-local|month|week|color), value, name,
11
12
  * size, placeholder, disabled, readonly, min, max, step, autofocus,
12
13
  * clearable, full (largura 100% acompanhando o elemento pai), icon (nome do
13
14
  * glifo Fenix Icons ou emoji/texto livre) e icon-pos (left|right, padrão left).
@@ -28,9 +29,15 @@ export declare class FxInput extends FxFormElement {
28
29
  get size(): string;
29
30
  set size(value: string);
30
31
  get value(): string;
31
- set value(value: string);
32
+ set value(value: string | number | null | undefined);
32
33
  get disabled(): boolean;
33
34
  set disabled(value: boolean);
35
+ get readonly(): boolean;
36
+ set readonly(value: boolean);
37
+ get clearable(): boolean;
38
+ set clearable(value: boolean);
39
+ get full(): boolean;
40
+ set full(value: boolean);
34
41
  protected render(): void;
35
42
  /** Empurra o atributo `value` para o campo interno sem re-renderizar. */
36
43
  protected syncInternalControl(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../src/components/input/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAKxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAclD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,OAAQ,SAAQ,aAAa;IACxC,OAAgB,MAAM,SAuIpB;IAMF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAMjD;IAED,+CAA+C;IAC/C,IAAa,IAAI,IAAI,WAAW,CAE/B;IACD,IAAa,IAAI,CAAC,KAAK,EAAE,WAAW,EAEnC;IAED,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,EAMtB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;cAEkB,MAAM,IAAI,IAAI;IAiFjC,yEAAyE;cACtD,mBAAmB,IAAI,IAAI;CAO/C;AAED,wBAAgB,aAAa,IAAI,OAAO,OAAO,CAE9C"}
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../src/components/input/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAKxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA4BlD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,OAAQ,SAAQ,aAAa;IACxC,OAAgB,MAAM,SAuIpB;IAMF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAOjD;IAED,+CAA+C;IAC/C,IAAa,IAAI,IAAI,WAAW,CAE/B;IACD,IAAa,IAAI,CAAC,KAAK,EAAE,WAAW,EAEnC;IAED,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,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EAMlD;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IACD,IAAI,SAAS,CAAC,KAAK,EAAE,OAAO,EAE3B;IAED,IAAI,IAAI,IAAI,OAAO,CAElB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAEtB;cAEkB,MAAM,IAAI,IAAI;IAgGjC,yEAAyE;cACtD,mBAAmB,IAAI,IAAI;CAO/C;AAED,wBAAgB,aAAa,IAAI,OAAO,OAAO,CAE9C"}
@@ -3,7 +3,21 @@ import { css } from "../../core/css.js";
3
3
  import { defineElement } from "../../core/define.js";
4
4
  import { esc } from "../../core/sanitize.js";
5
5
  import { FENIX_ICON_BASE_CSS, fenixIconHtml } from "../../icons/base-css.js";
6
- const INPUT_TYPES = /* @__PURE__ */ new Set(["text", "number", "password"]);
6
+ const INPUT_TYPES = /* @__PURE__ */ new Set([
7
+ "text",
8
+ "number",
9
+ "password",
10
+ "email",
11
+ "tel",
12
+ "url",
13
+ "search",
14
+ "date",
15
+ "time",
16
+ "datetime-local",
17
+ "month",
18
+ "week",
19
+ "color"
20
+ ]);
7
21
  function normalizeInputType(value) {
8
22
  const type = (value || "text").toLowerCase();
9
23
  return INPUT_TYPES.has(type) ? type : "text";
@@ -23,6 +37,8 @@ const _FxInput = class _FxInput extends FxFormElement {
23
37
  "min",
24
38
  "max",
25
39
  "step",
40
+ "clearable",
41
+ "full",
26
42
  "icon",
27
43
  "icon-pos",
28
44
  "error",
@@ -50,7 +66,7 @@ const _FxInput = class _FxInput extends FxFormElement {
50
66
  return this.getAttr("value");
51
67
  }
52
68
  set value(value) {
53
- this.setAttribute("value", value);
69
+ this.setAttribute("value", value == null ? "" : String(value));
54
70
  this.syncInternalControl();
55
71
  this.updateFormValue();
56
72
  }
@@ -60,6 +76,24 @@ const _FxInput = class _FxInput extends FxFormElement {
60
76
  set disabled(value) {
61
77
  this.toggleAttr("disabled", Boolean(value));
62
78
  }
79
+ get readonly() {
80
+ return this.hasAttr("readonly");
81
+ }
82
+ set readonly(value) {
83
+ this.toggleAttr("readonly", Boolean(value));
84
+ }
85
+ get clearable() {
86
+ return this.hasAttr("clearable");
87
+ }
88
+ set clearable(value) {
89
+ this.toggleAttr("clearable", Boolean(value));
90
+ }
91
+ get full() {
92
+ return this.hasAttr("full");
93
+ }
94
+ set full(value) {
95
+ this.toggleAttr("full", Boolean(value));
96
+ }
63
97
  render() {
64
98
  const type = this.type;
65
99
  const placeholder = this.getAttr("placeholder");
@@ -90,20 +124,27 @@ const _FxInput = class _FxInput extends FxFormElement {
90
124
  field.value = this.getAttr("value");
91
125
  if (disabled) field.setAttribute("disabled", "");
92
126
  if (readonly) field.setAttribute("readonly", "");
93
- const emit = (event) => {
127
+ const notifyInput = () => {
94
128
  this.value = field.value;
95
129
  this.emitValueEvents();
130
+ };
131
+ const notifyChange = () => {
132
+ this.value = field.value;
96
133
  this.dispatchEvent(
97
- new CustomEvent(event, { bubbles: true, composed: true, detail: { value: field.value } })
134
+ new CustomEvent("change", {
135
+ bubbles: true,
136
+ composed: true,
137
+ detail: { value: field.value }
138
+ })
98
139
  );
99
140
  };
100
141
  field.addEventListener("input", (e) => {
101
142
  e.stopPropagation();
102
- emit("input");
143
+ notifyInput();
103
144
  });
104
145
  field.addEventListener("change", (e) => {
105
146
  e.stopPropagation();
106
- emit("change");
147
+ notifyChange();
107
148
  });
108
149
  field.addEventListener("keydown", (e) => {
109
150
  if (e.key !== "Enter" || e.isComposing) return;
@@ -119,8 +160,15 @@ const _FxInput = class _FxInput extends FxFormElement {
119
160
  clearBtn?.addEventListener("click", () => {
120
161
  field.value = "";
121
162
  syncClear();
122
- emit("input");
123
- emit("change");
163
+ this.value = "";
164
+ this.emitValueEvents();
165
+ this.dispatchEvent(
166
+ new CustomEvent("change", {
167
+ bubbles: true,
168
+ composed: true,
169
+ detail: { value: "" }
170
+ })
171
+ );
124
172
  field.focus();
125
173
  });
126
174
  field.addEventListener("input", syncClear);
@@ -1 +1 @@
1
- {"version":3,"file":"input.js","sources":["../../../src/components/input/input.ts"],"sourcesContent":["import { FxFormElement } from '../../core/form-element';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\nimport { FENIX_ICON_BASE_CSS, fenixIconHtml } from '../../icons/base-css';\nimport type { FxInputType } from '../../core/jsx';\n\n/**\n * Tipos suportados pelo <fx-input>: text, number e password.\n * Qualquer outro tipo (email, search, date, file, range, checkbox, radio…)\n * cai em `text` em runtime.\n */\nconst INPUT_TYPES = new Set(['text', 'number', 'password']);\n\nfunction normalizeInputType(value: string): string {\n const type = (value || 'text').toLowerCase();\n return INPUT_TYPES.has(type) ? type : 'text';\n}\n\n/**\n * <fx-input> — Campo de texto estilizado com os tokens do tema.\n *\n * Form-Associated Custom Element: dentro de um <form> entra no FormData\n * (via atributo `name`), recebe reset/disable do form, é alvo de\n * `<label for>`/`autofocus` e o Enter submete o form.\n *\n * Atributos: type (text|number|password), value, name,\n * size, placeholder, disabled, readonly, min, max, step, autofocus,\n * clearable, full (largura 100% acompanhando o elemento pai), icon (nome do\n * glifo Fenix Icons ou emoji/texto livre) e icon-pos (left|right, padrão left).\n * Largura: o default (260px; sm 220px / lg 300px) fica no HOST via tokens\n * --fx-input-width(-sm|-lg) — CSS externo, classes e style inline no elemento\n * vencem o default sem precisar de atributo.\n * Slots: `icon` (ícone customizado no lugar do atributo).\n * Eventos: `input`, `change` e `valueChange` (composed, detail: { value }) —\n * `input` aciona o v-model do Vue e `valueChange` o [(value)] do Angular.\n */\nexport class FxInput extends FxFormElement {\n static override styles = css`\n :host {\n display: inline-block;\n vertical-align: middle;\n /* Largura padrão no HOST (e não no .field interno): assim CSS externo,\n classes do framework (ex.: w-full) e style inline no elemento vencem\n este default naturalmente — regras do documento têm precedência sobre\n :host. Default global trocável via token: --fx-input-width (-sm/-lg). */\n width: var(--fx-input-width, 260px);\n vertical-align: middle;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n .field {\n font-family: inherit;\n font-size: inherit;\n /* Altura determinística: com line-height fixo, o padding vertical cabe no\n token --fx-size-* e a caixa fica EXATAMENTE no tamanho padrão\n (sm 32 / md 40 / lg 48), igual para todos os campos. */\n line-height: var(--fx-font-line-height);\n min-height: var(--fx-size-md);\n font-weight: var(--fx-font-weight);\n color: var(--fx-text-default);\n background-color: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n padding: var(--fx-space-sm) var(--fx-space-lg);\n /* Acompanha a largura definida no :host. */\n width: 100%;\n box-sizing: border-box;\n transition:\n border-color var(--fx-motion-duration-normal) var(--fx-motion-easing),\n box-shadow var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .field::placeholder { color: var(--fx-text-muted); opacity: 1; }\n .field:hover { border-color: var(--fx-border-hover); }\n .field:focus-visible {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n .field:disabled,\n .field[readonly] {\n opacity: 0.55;\n cursor: not-allowed;\n background-color: var(--fx-surface-surface-hover);\n }\n /* Validação: borda sempre; o brilho (anel) segue o token do preset\n --fx-effect-error-ring, que acompanha effect.focus-ring — anel\n desligado ⇒ erro só com a borda vermelha, ligado ⇒ soma o brilho. */\n :host([error]) .field,\n :host([invalid]) .field,\n :host([error]) .field:focus-visible,\n :host([invalid]) .field:focus-visible {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([success]) .field,\n :host([valid]) .field,\n :host([success]) .field:focus-visible,\n :host([valid]) .field:focus-visible {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));\n }\n :host([size='sm']) { width: var(--fx-input-width-sm, 220px); }\n :host([size='sm']) .field { padding: var(--fx-space-xs) var(--fx-space-md); font-size: var(--fx-font-size); min-height: var(--fx-size-sm); }\n :host([size='lg']) { width: var(--fx-input-width-lg, 300px); }\n :host([size='lg']) .field { padding: var(--fx-space-sm) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); min-height: var(--fx-size-lg); }\n /* Full width: o host estica até o pai e o campo interno acompanha\n (usar com um container de largura controlada, ex. w-full no Vue). */\n :host([full]) { display: block; width: 100%; }\n :host([full]) .field { width: 100%; }\n /* Clearable */\n :host([clearable]) { position: relative; display: inline-flex; }\n :host([clearable][full]) { display: block; }\n .wrap { position: relative; display: inline-flex; align-items: center; width: 100%; }\n :host([full]) .wrap { display: flex; width: 100%; }\n :host([clearable]) .field { padding-right: var(--fx-space-xl); }\n :host([clearable][full]) .field { flex: 1 1 auto; }\n /* Ícones (attr icon + slot icon) — DENTRO do campo, sobre o padding\n (padrão Material/PrimeVue). Tamanho ajustável via --fx-input-icon-size. */\n .field-icon {\n position: relative;\n display: inline-flex;\n box-sizing: border-box;\n width: 100%;\n }\n .field-icon .field { flex: 1 1 auto; min-width: 0; }\n :host([full]) .field-icon { display: flex; width: 100%; }\n .field-icon .fx-icon,\n .field-icon ::slotted([slot='icon']) {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px));\n line-height: 1;\n color: var(--fx-text-muted);\n pointer-events: none;\n z-index: 1;\n }\n .field-icon.icon-left .fx-icon,\n .field-icon.icon-left ::slotted([slot='icon']) { left: var(--fx-space-md); }\n .field-icon.icon-right .fx-icon,\n .field-icon.icon-right ::slotted([slot='icon']) { right: var(--fx-space-md); }\n /* padding = posição do ícone + largura + folga extra para o texto\n não colar no glifo. */\n .field-icon.icon-left .field {\n padding-left: calc(var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px)) + var(--fx-space-md) + var(--fx-space-sm));\n }\n .field-icon.icon-right .field {\n padding-right: calc(var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px)) + var(--fx-space-md) + var(--fx-space-sm));\n }\n /* icon-pos right + clearable: desloca o × para não sobrepor o ícone. */\n .field-icon.icon-right + .clear {\n right: calc(var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px)) + var(--fx-space-lg));\n }\n .clear {\n position: absolute;\n right: var(--fx-space-xs);\n border: none;\n background: transparent;\n color: var(--fx-text-muted);\n font-size: calc(var(--fx-font-size) + 4px);\n line-height: 1;\n cursor: pointer;\n padding: 0 var(--fx-space-xs);\n border-radius: var(--fx-radius-full);\n }\n .clear:hover { color: var(--fx-color-danger); }\n .clear[hidden] { display: none; }\n /* Base dos glifos Fenix Icons (o @font-face vem de @wrrdev/fenix-ui/icons). */\n ${FENIX_ICON_BASE_CSS}\n `;\n\n // `value` fica FORA da observação: refleti-lo a cada tecla não pode\n // re-renderizar o template, senão o campo perde o foco ao digitar.\n // `error`/`success` (+ aliases `invalid`/`valid`) PRECISAM ser observados:\n // é assim que o toggle no playground / setAttribute no submit re-renderiza.\n static override get observedAttributes(): string[] {\n return [\n 'type', 'size', 'placeholder',\n 'disabled', 'readonly', 'min', 'max', 'step',\n 'icon', 'icon-pos', 'error', 'invalid', 'success', 'valid',\n ];\n }\n\n /** Tipo do input interno. Padrão: `'text'`. */\n override get type(): FxInputType {\n return normalizeInputType(this.getAttr('type', 'text')) as FxInputType;\n }\n override set type(value: FxInputType) {\n this.setAttribute('type', normalizeInputType(value));\n }\n\n /** Tamanho do campo. 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 get value(): string {\n return this.getAttr('value');\n }\n set value(value: string) {\n this.setAttribute('value', value);\n // `value` NÃO é observado (re-render a cada tecla perderia o foco): o\n // campo interno é sincronizado aqui, sem re-render, preservando foco/cursor.\n this.syncInternalControl();\n this.updateFormValue();\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 protected override render(): void {\n const type = this.type;\n const placeholder = this.getAttr('placeholder');\n const readonly = this.hasAttr('readonly');\n const disabled = this.hasAttr('disabled');\n const min = this.getAttr('min');\n const max = this.getAttr('max');\n const step = this.getAttr('step');\n const icon = this.getAttr('icon');\n const iconPos = this.getAttr('icon-pos', 'left') === 'right' ? 'right' : 'left';\n // Slot `icon` vence o atributo `icon`; sem nenhum dos dois, sem ícone.\n const slottedIcon = this.querySelector<HTMLElement>('[slot=\"icon\"]');\n const iconContent = slottedIcon\n ? '<slot name=\"icon\" part=\"icon\"></slot>'\n : (icon ? fenixIconHtml(icon) : '');\n const useIconBox = Boolean(iconContent);\n\n this.setTemplate(`\n ${this.hasAttr('clearable') ? '<div class=\"wrap\" part=\"wrap\">' : ''}\n ${useIconBox ? `<div class=\"field-icon icon-${iconPos}\">` : ''}\n ${useIconBox && iconPos === 'left' ? iconContent : ''}\n <input class=\"field\" part=\"input\" type=\"${esc(type)}\"\n ${placeholder ? `placeholder=\"${esc(placeholder)}\"` : ''}\n ${min ? `min=\"${esc(min)}\"` : ''} ${max ? `max=\"${esc(max)}\"` : ''} ${step ? `step=\"${esc(step)}\"` : ''}\n />\n ${useIconBox && iconPos === 'right' ? iconContent : ''}\n ${useIconBox ? '</div>' : ''}\n ${this.hasAttr('clearable') ? '<button type=\"button\" class=\"clear\" part=\"clear\" aria-label=\"Limpar\" tabindex=\"-1\">×</button></div>' : ''}\n `);\n\n const field = this.root.querySelector<HTMLInputElement>('.field');\n if (!field) return;\n field.value = this.getAttr('value');\n if (disabled) field.setAttribute('disabled', '');\n if (readonly) field.setAttribute('readonly', '');\n\n const emit = (event: string): void => {\n this.value = field.value;\n // input (v-model do Vue) + valueChange ([(value)] do Angular).\n this.emitValueEvents();\n this.dispatchEvent(\n new CustomEvent(event, { bubbles: true, composed: true, detail: { value: field.value } }),\n );\n };\n // Bloqueia o evento nativo (composed, sem detail) para que só o\n // CustomEvent com detail chegue aos consumidores.\n field.addEventListener('input', (e) => { e.stopPropagation(); emit('input'); });\n field.addEventListener('change', (e) => { e.stopPropagation(); emit('change'); });\n\n // Enter submete o form: o <input> interno vive no Shadow DOM e NÃO se\n // associa ao <form> do light DOM (a fronteira do shadow corta a associação\n // por árvore) — por isso a submissão implícita é acionada manualmente.\n // Ouvintes de submit no form (ex.: submit.prevent de frameworks) seguem\n // recebendo o evento normalmente.\n field.addEventListener('keydown', (e) => {\n if (e.key !== 'Enter' || e.isComposing) return;\n if (!this.form) return;\n e.preventDefault();\n this.form.requestSubmit();\n });\n\n // Clearable: botão × que limpa o campo e emite input/change vazios.\n const clearBtn = this.root.querySelector<HTMLButtonElement>('.clear');\n const syncClear = (): void => {\n clearBtn?.toggleAttribute('hidden', field.value === '');\n };\n syncClear();\n clearBtn?.addEventListener('click', () => {\n field.value = '';\n syncClear();\n emit('input');\n emit('change');\n field.focus();\n });\n field.addEventListener('input', syncClear);\n\n // Publica name/value no form (ElementInternals) a cada render — cobre o\n // estado inicial e mudanças de atributos observados.\n this.updateFormValue();\n }\n\n /** Empurra o atributo `value` para o campo interno sem re-renderizar. */\n protected override syncInternalControl(): void {\n const field = this.root.querySelector<HTMLInputElement>('.field');\n const value = this.getAttr('value');\n const type = this.type;\n if (field && field.type !== type) field.type = type;\n if (field && field.value !== value) field.value = value;\n }\n}\n\nexport function defineFxInput(): typeof FxInput {\n return defineElement('fx-input', FxInput);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"input.js","sources":["../../../src/components/input/input.ts"],"sourcesContent":["import { FxFormElement } from '../../core/form-element';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\nimport { FENIX_ICON_BASE_CSS, fenixIconHtml } from '../../icons/base-css';\nimport type { FxInputType } from '../../core/jsx';\n\n/**\n * Tipos nativos aceitos pelo <fx-input>. Os tipos com semântica própria\n * (file, checkbox, radio, submit, reset, button, image) continuam fora:\n * eles não fazem sentido no componente de texto.\n */\nconst INPUT_TYPES = new Set([\n 'text',\n 'number',\n 'password',\n 'email',\n 'tel',\n 'url',\n 'search',\n 'date',\n 'time',\n 'datetime-local',\n 'month',\n 'week',\n 'color',\n]);\n\nfunction normalizeInputType(value: string): string {\n const type = (value || 'text').toLowerCase();\n return INPUT_TYPES.has(type) ? type : 'text';\n}\n\n/**\n * <fx-input> — Campo de texto estilizado com os tokens do tema.\n *\n * Form-Associated Custom Element: dentro de um <form> entra no FormData\n * (via atributo `name`), recebe reset/disable do form, é alvo de\n * `<label for>`/`autofocus` e o Enter submete o form.\n *\n * Atributos: type (text|number|password|email|tel|url|search|date|time|\n * datetime-local|month|week|color), value, name,\n * size, placeholder, disabled, readonly, min, max, step, autofocus,\n * clearable, full (largura 100% acompanhando o elemento pai), icon (nome do\n * glifo Fenix Icons ou emoji/texto livre) e icon-pos (left|right, padrão left).\n * Largura: o default (260px; sm 220px / lg 300px) fica no HOST via tokens\n * --fx-input-width(-sm|-lg) — CSS externo, classes e style inline no elemento\n * vencem o default sem precisar de atributo.\n * Slots: `icon` (ícone customizado no lugar do atributo).\n * Eventos: `input`, `change` e `valueChange` (composed, detail: { value }) —\n * `input` aciona o v-model do Vue e `valueChange` o [(value)] do Angular.\n */\nexport class FxInput extends FxFormElement {\n static override styles = css`\n :host {\n display: inline-block;\n vertical-align: middle;\n /* Largura padrão no HOST (e não no .field interno): assim CSS externo,\n classes do framework (ex.: w-full) e style inline no elemento vencem\n este default naturalmente — regras do documento têm precedência sobre\n :host. Default global trocável via token: --fx-input-width (-sm/-lg). */\n width: var(--fx-input-width, 260px);\n vertical-align: middle;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n .field {\n font-family: inherit;\n font-size: inherit;\n /* Altura determinística: com line-height fixo, o padding vertical cabe no\n token --fx-size-* e a caixa fica EXATAMENTE no tamanho padrão\n (sm 32 / md 40 / lg 48), igual para todos os campos. */\n line-height: var(--fx-font-line-height);\n min-height: var(--fx-size-md);\n font-weight: var(--fx-font-weight);\n color: var(--fx-text-default);\n background-color: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n padding: var(--fx-space-sm) var(--fx-space-lg);\n /* Acompanha a largura definida no :host. */\n width: 100%;\n box-sizing: border-box;\n transition:\n border-color var(--fx-motion-duration-normal) var(--fx-motion-easing),\n box-shadow var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .field::placeholder { color: var(--fx-text-muted); opacity: 1; }\n .field:hover { border-color: var(--fx-border-hover); }\n .field:focus-visible {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n .field:disabled,\n .field[readonly] {\n opacity: 0.55;\n cursor: not-allowed;\n background-color: var(--fx-surface-surface-hover);\n }\n /* Validação: borda sempre; o brilho (anel) segue o token do preset\n --fx-effect-error-ring, que acompanha effect.focus-ring — anel\n desligado ⇒ erro só com a borda vermelha, ligado ⇒ soma o brilho. */\n :host([error]) .field,\n :host([invalid]) .field,\n :host([error]) .field:focus-visible,\n :host([invalid]) .field:focus-visible {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([success]) .field,\n :host([valid]) .field,\n :host([success]) .field:focus-visible,\n :host([valid]) .field:focus-visible {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));\n }\n :host([size='sm']) { width: var(--fx-input-width-sm, 220px); }\n :host([size='sm']) .field { padding: var(--fx-space-xs) var(--fx-space-md); font-size: var(--fx-font-size); min-height: var(--fx-size-sm); }\n :host([size='lg']) { width: var(--fx-input-width-lg, 300px); }\n :host([size='lg']) .field { padding: var(--fx-space-sm) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); min-height: var(--fx-size-lg); }\n /* Full width: o host estica até o pai e o campo interno acompanha\n (usar com um container de largura controlada, ex. w-full no Vue). */\n :host([full]) { display: block; width: 100%; }\n :host([full]) .field { width: 100%; }\n /* Clearable */\n :host([clearable]) { position: relative; display: inline-flex; }\n :host([clearable][full]) { display: block; }\n .wrap { position: relative; display: inline-flex; align-items: center; width: 100%; }\n :host([full]) .wrap { display: flex; width: 100%; }\n :host([clearable]) .field { padding-right: var(--fx-space-xl); }\n :host([clearable][full]) .field { flex: 1 1 auto; }\n /* Ícones (attr icon + slot icon) — DENTRO do campo, sobre o padding\n (padrão Material/PrimeVue). Tamanho ajustável via --fx-input-icon-size. */\n .field-icon {\n position: relative;\n display: inline-flex;\n box-sizing: border-box;\n width: 100%;\n }\n .field-icon .field { flex: 1 1 auto; min-width: 0; }\n :host([full]) .field-icon { display: flex; width: 100%; }\n .field-icon .fx-icon,\n .field-icon ::slotted([slot='icon']) {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px));\n line-height: 1;\n color: var(--fx-text-muted);\n pointer-events: none;\n z-index: 1;\n }\n .field-icon.icon-left .fx-icon,\n .field-icon.icon-left ::slotted([slot='icon']) { left: var(--fx-space-md); }\n .field-icon.icon-right .fx-icon,\n .field-icon.icon-right ::slotted([slot='icon']) { right: var(--fx-space-md); }\n /* padding = posição do ícone + largura + folga extra para o texto\n não colar no glifo. */\n .field-icon.icon-left .field {\n padding-left: calc(var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px)) + var(--fx-space-md) + var(--fx-space-sm));\n }\n .field-icon.icon-right .field {\n padding-right: calc(var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px)) + var(--fx-space-md) + var(--fx-space-sm));\n }\n /* icon-pos right + clearable: desloca o × para não sobrepor o ícone. */\n .field-icon.icon-right + .clear {\n right: calc(var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px)) + var(--fx-space-lg));\n }\n .clear {\n position: absolute;\n right: var(--fx-space-xs);\n border: none;\n background: transparent;\n color: var(--fx-text-muted);\n font-size: calc(var(--fx-font-size) + 4px);\n line-height: 1;\n cursor: pointer;\n padding: 0 var(--fx-space-xs);\n border-radius: var(--fx-radius-full);\n }\n .clear:hover { color: var(--fx-color-danger); }\n .clear[hidden] { display: none; }\n /* Base dos glifos Fenix Icons (o @font-face vem de @wrrdev/fenix-ui/icons). */\n ${FENIX_ICON_BASE_CSS}\n `;\n\n // `value` fica FORA da observação: refleti-lo a cada tecla não pode\n // re-renderizar o template, senão o campo perde o foco ao digitar.\n // `error`/`success` (+ aliases `invalid`/`valid`) PRECISAM ser observados:\n // é assim que o toggle no playground / setAttribute no submit re-renderiza.\n static override get observedAttributes(): string[] {\n return [\n 'type', 'size', 'placeholder',\n 'disabled', 'readonly', 'min', 'max', 'step',\n 'clearable', 'full',\n 'icon', 'icon-pos', 'error', 'invalid', 'success', 'valid',\n ];\n }\n\n /** Tipo do input interno. Padrão: `'text'`. */\n override get type(): FxInputType {\n return normalizeInputType(this.getAttr('type', 'text')) as FxInputType;\n }\n override set type(value: FxInputType) {\n this.setAttribute('type', normalizeInputType(value));\n }\n\n /** Tamanho do campo. 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 get value(): string {\n return this.getAttr('value');\n }\n set value(value: string | number | null | undefined) {\n this.setAttribute('value', value == null ? '' : String(value));\n // `value` NÃO é observado (re-render a cada tecla perderia o foco): o\n // campo interno é sincronizado aqui, sem re-render, preservando foco/cursor.\n this.syncInternalControl();\n this.updateFormValue();\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 get readonly(): boolean {\n return this.hasAttr('readonly');\n }\n set readonly(value: boolean) {\n this.toggleAttr('readonly', Boolean(value));\n }\n\n get clearable(): boolean {\n return this.hasAttr('clearable');\n }\n set clearable(value: boolean) {\n this.toggleAttr('clearable', Boolean(value));\n }\n\n get full(): boolean {\n return this.hasAttr('full');\n }\n set full(value: boolean) {\n this.toggleAttr('full', Boolean(value));\n }\n\n protected override render(): void {\n const type = this.type;\n const placeholder = this.getAttr('placeholder');\n const readonly = this.hasAttr('readonly');\n const disabled = this.hasAttr('disabled');\n const min = this.getAttr('min');\n const max = this.getAttr('max');\n const step = this.getAttr('step');\n const icon = this.getAttr('icon');\n const iconPos = this.getAttr('icon-pos', 'left') === 'right' ? 'right' : 'left';\n // Slot `icon` vence o atributo `icon`; sem nenhum dos dois, sem ícone.\n const slottedIcon = this.querySelector<HTMLElement>('[slot=\"icon\"]');\n const iconContent = slottedIcon\n ? '<slot name=\"icon\" part=\"icon\"></slot>'\n : (icon ? fenixIconHtml(icon) : '');\n const useIconBox = Boolean(iconContent);\n\n this.setTemplate(`\n ${this.hasAttr('clearable') ? '<div class=\"wrap\" part=\"wrap\">' : ''}\n ${useIconBox ? `<div class=\"field-icon icon-${iconPos}\">` : ''}\n ${useIconBox && iconPos === 'left' ? iconContent : ''}\n <input class=\"field\" part=\"input\" type=\"${esc(type)}\"\n ${placeholder ? `placeholder=\"${esc(placeholder)}\"` : ''}\n ${min ? `min=\"${esc(min)}\"` : ''} ${max ? `max=\"${esc(max)}\"` : ''} ${step ? `step=\"${esc(step)}\"` : ''}\n />\n ${useIconBox && iconPos === 'right' ? iconContent : ''}\n ${useIconBox ? '</div>' : ''}\n ${this.hasAttr('clearable') ? '<button type=\"button\" class=\"clear\" part=\"clear\" aria-label=\"Limpar\" tabindex=\"-1\">×</button></div>' : ''}\n `);\n\n const field = this.root.querySelector<HTMLInputElement>('.field');\n if (!field) return;\n field.value = this.getAttr('value');\n if (disabled) field.setAttribute('disabled', '');\n if (readonly) field.setAttribute('readonly', '');\n\n // Cada interação emite UM `input` (v-model) + `valueChange` (Angular).\n // O `change` só existe no evento nativo de mudança/limpar.\n const notifyInput = (): void => {\n this.value = field.value;\n this.emitValueEvents();\n };\n const notifyChange = (): void => {\n this.value = field.value;\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { value: field.value },\n }),\n );\n };\n // Bloqueia o evento nativo (composed, sem detail) para que só o\n // CustomEvent com detail chegue aos consumidores.\n field.addEventListener('input', (e) => { e.stopPropagation(); notifyInput(); });\n field.addEventListener('change', (e) => { e.stopPropagation(); notifyChange(); });\n\n // Enter submete o form: o <input> interno vive no Shadow DOM e NÃO se\n // associa ao <form> do light DOM (a fronteira do shadow corta a associação\n // por árvore) — por isso a submissão implícita é acionada manualmente.\n // Ouvintes de submit no form (ex.: submit.prevent de frameworks) seguem\n // recebendo o evento normalmente.\n field.addEventListener('keydown', (e) => {\n if (e.key !== 'Enter' || e.isComposing) return;\n if (!this.form) return;\n e.preventDefault();\n this.form.requestSubmit();\n });\n\n // Clearable: botão × que limpa o campo e emite input/change vazios.\n const clearBtn = this.root.querySelector<HTMLButtonElement>('.clear');\n const syncClear = (): void => {\n clearBtn?.toggleAttribute('hidden', field.value === '');\n };\n syncClear();\n clearBtn?.addEventListener('click', () => {\n field.value = '';\n syncClear();\n this.value = '';\n this.emitValueEvents();\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { value: '' },\n }),\n );\n field.focus();\n });\n field.addEventListener('input', syncClear);\n\n // Publica name/value no form (ElementInternals) a cada render — cobre o\n // estado inicial e mudanças de atributos observados.\n this.updateFormValue();\n }\n\n /** Empurra o atributo `value` para o campo interno sem re-renderizar. */\n protected override syncInternalControl(): void {\n const field = this.root.querySelector<HTMLInputElement>('.field');\n const value = this.getAttr('value');\n const type = this.type;\n if (field && field.type !== type) field.type = type;\n if (field && field.value !== value) field.value = value;\n }\n}\n\nexport function defineFxInput(): typeof FxInput {\n return defineElement('fx-input', FxInput);\n}\n"],"names":[],"mappings":"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"}
@@ -21,13 +21,20 @@ export declare class FxMultiselect extends FxFormElement {
21
21
  private selected;
22
22
  /** Seleção inicial (para form.reset() restaurar o estado). */
23
23
  private _initialValues?;
24
+ protected attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
24
25
  /** Valores selecionados (CSV no atributo / array na propriedade). */
25
26
  get values(): string[];
26
- set values(list: string[]);
27
+ set values(list: string[] | null | undefined);
27
28
  /** No FormData do form: uma entrada `name` por valor selecionado. */
28
29
  protected getFormValue(): string | FormData | null;
29
30
  get disabled(): boolean;
30
31
  set disabled(value: boolean);
32
+ get searchable(): boolean;
33
+ set searchable(value: boolean);
34
+ get clearable(): boolean;
35
+ set clearable(value: boolean);
36
+ get full(): boolean;
37
+ set full(value: boolean);
31
38
  private get options();
32
39
  protected connectedCallback(): void;
33
40
  protected disconnectedCallback(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"multiselect.d.ts","sourceRoot":"","sources":["../../../src/components/multiselect/multiselect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAKxD;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAc,SAAQ,aAAa;IAC9C,OAAgB,MAAM,SAqOpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAIjD;IAED,OAAO,CAAC,QAAQ,CAAC,CAAmB;IACpC,OAAO,CAAC,WAAW,CAAC,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAqB;IACrC,8DAA8D;IAC9D,OAAO,CAAC,cAAc,CAAC,CAAW;IAElC,qEAAqE;IACrE,IAAI,MAAM,IAAI,MAAM,EAAE,CAGrB;IACD,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAExB;IAED,qEAAqE;cAClD,YAAY,IAAI,MAAM,GAAG,QAAQ,GAAG,IAAI;IAQ3D,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;IAED,OAAO,KAAK,OAAO,GAKlB;cAEkB,iBAAiB,IAAI,IAAI;cAgBzB,oBAAoB,IAAI,IAAI;IAM/C,gDAAgD;IAChD,OAAO,CAAC,MAAM;IAqBd,gDAAgD;IACvC,iBAAiB,IAAI,IAAI;IAQlC,OAAO,CAAC,WAAW;IAMnB,qEAAqE;IACrE,OAAO,CAAC,gBAAgB;cAiBL,MAAM,IAAI,IAAI;CAwIlC;AAED,wBAAgB,mBAAmB,IAAI,OAAO,aAAa,CAE1D"}
1
+ {"version":3,"file":"multiselect.d.ts","sourceRoot":"","sources":["../../../src/components/multiselect/multiselect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAKxD;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAc,SAAQ,aAAa;IAC9C,OAAgB,MAAM,SAqOpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAgBjD;IAED,OAAO,CAAC,QAAQ,CAAC,CAAmB;IACpC,OAAO,CAAC,WAAW,CAAC,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAqB;IACrC,8DAA8D;IAC9D,OAAO,CAAC,cAAc,CAAC,CAAW;cAEf,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAOjH,qEAAqE;IACrE,IAAI,MAAM,IAAI,MAAM,EAAE,CAGrB;IACD,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,EAY3C;IAED,qEAAqE;cAClD,YAAY,IAAI,MAAM,GAAG,QAAQ,GAAG,IAAI;IAQ3D,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IACD,IAAI,UAAU,CAAC,KAAK,EAAE,OAAO,EAE5B;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IACD,IAAI,SAAS,CAAC,KAAK,EAAE,OAAO,EAE3B;IAED,IAAI,IAAI,IAAI,OAAO,CAElB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAEtB;IAED,OAAO,KAAK,OAAO,GAKlB;cAEkB,iBAAiB,IAAI,IAAI;cAwBzB,oBAAoB,IAAI,IAAI;IAM/C,gDAAgD;IAChD,OAAO,CAAC,MAAM;IAwBd,gDAAgD;IACvC,iBAAiB,IAAI,IAAI;IAOlC,OAAO,CAAC,WAAW;IAMnB,qEAAqE;IACrE,OAAO,CAAC,gBAAgB;cAiBL,MAAM,IAAI,IAAI;CA4IlC;AAED,wBAAgB,mBAAmB,IAAI,OAAO,aAAa,CAE1D"}
@@ -8,7 +8,23 @@ const _FxMultiselect = class _FxMultiselect extends FxFormElement {
8
8
  this.selected = /* @__PURE__ */ new Set();
9
9
  }
10
10
  static get observedAttributes() {
11
- return ["disabled", "placeholder", "error", "invalid", "success", "valid"];
11
+ return [
12
+ "values",
13
+ "size",
14
+ "disabled",
15
+ "placeholder",
16
+ "searchable",
17
+ "clearable",
18
+ "full",
19
+ "error",
20
+ "invalid",
21
+ "success",
22
+ "valid"
23
+ ];
24
+ }
25
+ attributeChangedCallback(name, oldValue, newValue) {
26
+ if (name === "values") this.selected = new Set(this.values);
27
+ super.attributeChangedCallback(name, oldValue, newValue);
12
28
  }
13
29
  /** Valores selecionados (CSV no atributo / array na propriedade). */
14
30
  get values() {
@@ -16,7 +32,15 @@ const _FxMultiselect = class _FxMultiselect extends FxFormElement {
16
32
  return csv ? csv.split(",").map((v) => v.trim()).filter(Boolean) : [];
17
33
  }
18
34
  set values(list) {
19
- this.setAttribute("values", list.join(","));
35
+ const values = Array.isArray(list) ? list.map(String) : [];
36
+ this.selected = new Set(values);
37
+ const csv = values.join(",");
38
+ if (this.getAttr("values") !== csv) {
39
+ this.setAttribute("values", csv);
40
+ } else if (this.isConnected) {
41
+ this.render();
42
+ }
43
+ this.updateFormValue();
20
44
  }
21
45
  /** No FormData do form: uma entrada `name` por valor selecionado. */
22
46
  getFormValue() {
@@ -32,6 +56,24 @@ const _FxMultiselect = class _FxMultiselect extends FxFormElement {
32
56
  set disabled(value) {
33
57
  this.toggleAttr("disabled", Boolean(value));
34
58
  }
59
+ get searchable() {
60
+ return this.hasAttr("searchable");
61
+ }
62
+ set searchable(value) {
63
+ this.toggleAttr("searchable", Boolean(value));
64
+ }
65
+ get clearable() {
66
+ return this.hasAttr("clearable");
67
+ }
68
+ set clearable(value) {
69
+ this.toggleAttr("clearable", Boolean(value));
70
+ }
71
+ get full() {
72
+ return this.hasAttr("full");
73
+ }
74
+ set full(value) {
75
+ this.toggleAttr("full", Boolean(value));
76
+ }
35
77
  get options() {
36
78
  return [...this.querySelectorAll("option")].map((o) => ({
37
79
  value: o.getAttribute("value") ?? o.textContent?.trim() ?? "",
@@ -43,7 +85,15 @@ const _FxMultiselect = class _FxMultiselect extends FxFormElement {
43
85
  if (!this._initialValues) this._initialValues = [...this.values];
44
86
  super.connectedCallback();
45
87
  this.observer = new MutationObserver(() => this.render());
46
- this.observer.observe(this, { childList: true, subtree: true, characterData: true });
88
+ this.observer.observe(this, {
89
+ childList: true,
90
+ subtree: true,
91
+ characterData: true,
92
+ // Vue atualiza `:value`/`:selected` das <option> no light DOM; sem
93
+ // observar atributos o label/valor antigo permanecia em tela.
94
+ attributes: true,
95
+ attributeFilter: ["value", "selected"]
96
+ });
47
97
  this.docListener = (e) => {
48
98
  if (!this.hasAttr("open")) return;
49
99
  if (e.composedPath().includes(this)) return;
@@ -59,8 +109,10 @@ const _FxMultiselect = class _FxMultiselect extends FxFormElement {
59
109
  }
60
110
  /** Aplica a seleção, reflete e emite change. */
61
111
  commit() {
62
- this.values = [...this.selected];
63
- this.render();
112
+ const next = [...this.selected];
113
+ const same = next.join(",") === this.values.join(",");
114
+ this.values = next;
115
+ if (same && this.isConnected) this.render();
64
116
  this.updateFormValue();
65
117
  this.dispatchEvent(
66
118
  new CustomEvent("change", {
@@ -81,8 +133,6 @@ const _FxMultiselect = class _FxMultiselect extends FxFormElement {
81
133
  formResetCallback() {
82
134
  const initial = this._initialValues ?? [];
83
135
  this.values = initial;
84
- this.selected = new Set(initial);
85
- this.render();
86
136
  this.updateFormValue();
87
137
  }
88
138
  toggleValue(value) {
@@ -111,8 +161,10 @@ const _FxMultiselect = class _FxMultiselect extends FxFormElement {
111
161
  const wasOpen = this.hasAttr("open");
112
162
  const search = this.root.querySelector(".search")?.value ?? "";
113
163
  const opts = this.options;
114
- for (const v of [...this.selected]) {
115
- if (!opts.some((o) => o.value === v)) this.selected.delete(v);
164
+ if (opts.length > 0) {
165
+ for (const v of [...this.selected]) {
166
+ if (!opts.some((o) => o.value === v)) this.selected.delete(v);
167
+ }
116
168
  }
117
169
  const chips = opts.filter((o) => this.selected.has(o.value));
118
170
  const placeholder = this.getAttr("placeholder", "Selecione…");
@@ -1 +1 @@
1
- {"version":3,"file":"multiselect.js","sources":["../../../src/components/multiselect/multiselect.ts"],"sourcesContent":["import { FxFormElement } from '../../core/form-element';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\n\n/**\n * <fx-multiselect> — Seleção múltipla .\n *\n * Form-Associated Custom Element: dentro de um <form> entra no FormData com\n * UMA entrada por valor selecionado (via atributo `name`).\n *\n * Dropdown customizado com painel (overlay), checkbox por item, pesquisa\n * opcional e ação de limpar. Opções via <option> nativos no light DOM.\n *\n * Atributos: values (CSV), searchable, clearable, disabled, placeholder,\n * size (sm|md|lg), no-results.\n * Eventos: `change` e `valuesChange` (composed, detail: { values: string[] }) —\n * `valuesChange` é o two-way binding do Angular [(value)] em seleção múltipla.\n */\nexport class FxMultiselect extends FxFormElement {\n static override styles = css`\n :host {\n display: inline-block;\n vertical-align: middle;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n position: relative;\n /* Largura padrão no HOST: CSS externo, classes e style inline no elemento\n vencem este default naturalmente (regras do documento > :host). */\n width: var(--fx-multiselect-width, 240px);\n }\n .trigger {\n display: inline-flex;\n align-items: center;\n flex-wrap: nowrap;\n gap: var(--fx-space-xs);\n /* Acompanha a largura definida no :host. */\n width: 100%;\n box-sizing: border-box;\n min-height: var(--fx-size-md);\n padding: var(--fx-space-xs) var(--fx-space-md);\n font: inherit;\n /* Altura determinística: a caixa fica no token --fx-size-*. */\n line-height: var(--fx-font-line-height);\n color: var(--fx-text-default);\n background-color: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n cursor: pointer;\n text-align: left;\n transition: border-color var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n /* Área dos chips: encolhe e quebra linha internamente,\n mantendo os ícones sempre dentro do componente. */\n .lead {\n display: inline-flex;\n flex-wrap: wrap;\n gap: var(--fx-space-xs);\n flex: 1;\n min-width: 0;\n overflow: hidden;\n }\n :host([size='sm']) { width: var(--fx-multiselect-width-sm, 200px); }\n :host([size='sm']) .trigger { min-height: var(--fx-size-sm); }\n :host([size='lg']) { width: var(--fx-multiselect-width-lg, 280px); }\n :host([size='lg']) .trigger { min-height: var(--fx-size-lg); font-size: calc(var(--fx-font-size) + 4px); }\n /* Full width: o host estica até o pai e o trigger acompanha. */\n :host([full]) { display: block; width: 100%; }\n :host([full]) .trigger { width: 100%; }\n /* Validação — borda e brilho JÁ EM REPOUSO (igual ao fx-input); o brilho\n segue o token --fx-effect-error-ring, que acompanha effect.focus-ring. */\n :host([error]) .trigger,\n :host([invalid]) .trigger {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([error]) .trigger:focus-visible,\n :host([invalid]) .trigger:focus-visible,\n :host([error][open]) .trigger,\n :host([invalid][open]) .trigger {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([success]) .trigger,\n :host([valid]) .trigger {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));\n }\n :host([success]) .trigger:focus-visible,\n :host([valid]) .trigger:focus-visible,\n :host([success][open]) .trigger,\n :host([valid][open]) .trigger {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));\n }\n .trigger:hover { border-color: var(--fx-border-hover); }\n .trigger:focus-visible {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n .trigger[aria-expanded='true'] { border-color: var(--fx-color-primary); }\n .placeholder { color: var(--fx-text-muted); }\n .chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n background: color-mix(in srgb, var(--fx-color-primary) 14%, transparent);\n color: var(--fx-color-primary);\n border-radius: var(--fx-radius-sm);\n padding: 2px 6px;\n font-size: calc(var(--fx-font-size) - 2px);\n }\n .chip__x {\n border: none;\n background: none;\n color: inherit;\n cursor: pointer;\n font-size: calc(var(--fx-font-size) - 1px);\n line-height: 1;\n padding: 0;\n }\n .trigger-right {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n color: var(--fx-text-muted);\n }\n .icon-btn {\n border: none;\n background: none;\n color: inherit;\n cursor: pointer;\n font-size: calc(var(--fx-font-size) + 2px);\n line-height: 1;\n padding: 0 2px;\n border-radius: var(--fx-radius-full);\n }\n .icon-btn:hover { color: var(--fx-color-danger); }\n .caret {\n font-size: calc(var(--fx-font-size) - 3px);\n transition: transform var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n :host([open]) .caret { transform: rotate(180deg); }\n\n /* Painel (overlay ) */\n .panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n z-index: var(--fx-z-dropdown, 1000);\n width: max(100%, 240px);\n background: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n box-shadow: var(--fx-shadow-lg);\n display: none;\n overflow: hidden;\n }\n :host([up]) .panel {\n top: auto;\n bottom: calc(100% + 4px);\n }\n :host([open]) .panel { display: block; }\n .panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--fx-space-sm);\n padding: var(--fx-space-xs) var(--fx-space-md);\n border-bottom: 1px solid var(--fx-border-default);\n background: var(--fx-surface-surface-hover);\n }\n .count { font-size: calc(var(--fx-font-size) - 2px); color: var(--fx-text-muted); }\n .clear-all {\n border: none;\n background: none;\n font: inherit;\n font-size: calc(var(--fx-font-size) - 2px);\n color: var(--fx-color-primary);\n cursor: pointer;\n padding: 0;\n }\n .clear-all:hover { text-decoration: underline; }\n .search {\n width: 100%;\n box-sizing: border-box;\n font: inherit;\n color: var(--fx-text-default);\n background: var(--fx-surface-background);\n border: none;\n border-bottom: 1px solid var(--fx-border-default);\n padding: var(--fx-space-sm) var(--fx-space-md);\n outline: none;\n }\n .list {\n max-height: 240px;\n overflow-y: auto;\n list-style: none;\n margin: 0;\n padding: var(--fx-space-3xs, 4px);\n }\n .opt {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm);\n width: 100%;\n padding: var(--fx-space-xs) var(--fx-space-md);\n border: none;\n background: none;\n font: inherit;\n color: var(--fx-text-default);\n cursor: pointer;\n border-radius: var(--fx-radius-sm);\n text-align: left;\n }\n .opt:hover { background: color-mix(in srgb, var(--fx-color-primary) 12%, transparent); }\n .opt[aria-selected='true'] {\n background: color-mix(in srgb, var(--fx-color-primary) 16%, transparent);\n color: var(--fx-color-primary);\n font-weight: var(--fx-font-weight);\n }\n /* Checkbox visual */\n .box {\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--fx-border-default);\n border-radius: calc(var(--fx-radius-sm) / 2);\n font-size: 11px;\n line-height: 1;\n color: transparent;\n transition:\n background-color var(--fx-motion-duration-fast) var(--fx-motion-easing),\n border-color var(--fx-motion-duration-fast) var(--fx-motion-easing),\n color var(--fx-motion-duration-fast) var(--fx-motion-easing);\n }\n .opt[aria-selected='true'] .box {\n background: var(--fx-color-primary);\n border-color: var(--fx-color-primary);\n color: #fff;\n }\n .opt[aria-selected='true'] .box::after { content: '✓'; }\n .empty { padding: var(--fx-space-md); color: var(--fx-text-muted); text-align: center; }\n :host([disabled]) .trigger { opacity: 0.55; cursor: not-allowed; background: var(--fx-surface-surface-hover); }\n `;\n\n static override get observedAttributes(): string[] {\n // `error`/`success` (+ aliases `invalid`/`valid`) PRECISAM ser observados:\n // é assim que o toggle no playground / setAttribute no submit re-renderiza.\n return ['disabled', 'placeholder', 'error', 'invalid', 'success', 'valid'];\n }\n\n private observer?: MutationObserver;\n private docListener?: (e: Event) => void;\n private selected = new Set<string>();\n /** Seleção inicial (para form.reset() restaurar o estado). */\n private _initialValues?: string[];\n\n /** Valores selecionados (CSV no atributo / array na propriedade). */\n get values(): string[] {\n const csv = this.getAttr('values');\n return csv ? csv.split(',').map((v) => v.trim()).filter(Boolean) : [];\n }\n set values(list: string[]) {\n this.setAttribute('values', list.join(','));\n }\n\n /** No FormData do form: uma entrada `name` por valor selecionado. */\n protected override getFormValue(): string | FormData | null {\n const values = this.values;\n if (!this.name || values.length === 0) return null;\n const fd = new FormData();\n values.forEach((v) => fd.append(this.name, v));\n return fd;\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 private get options(): { value: string; label: string }[] {\n return [...this.querySelectorAll('option')].map((o) => ({\n value: o.getAttribute('value') ?? o.textContent?.trim() ?? '',\n label: o.textContent?.trim() ?? '',\n }));\n }\n\n protected override connectedCallback(): void {\n // Popula a seleção ANTES do primeiro render (super chama render).\n this.selected = new Set(this.values);\n if (!this._initialValues) this._initialValues = [...this.values];\n super.connectedCallback();\n this.observer = new MutationObserver(() => this.render());\n this.observer.observe(this, { childList: true, subtree: true, characterData: true });\n this.docListener = (e: Event) => {\n if (!this.hasAttr('open')) return;\n if (e.composedPath().includes(this)) return;\n this.removeAttribute('open');\n this.render();\n };\n document.addEventListener('click', this.docListener);\n }\n\n protected override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.observer?.disconnect();\n if (this.docListener) document.removeEventListener('click', this.docListener);\n }\n\n /** Aplica a seleção, reflete e emite change. */\n private commit(): void {\n this.values = [...this.selected];\n this.render();\n this.updateFormValue();\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { values: [...this.selected] },\n }),\n );\n // Two-way binding do Angular: [(value)] em selecao multipla -> valuesChange.\n this.dispatchEvent(\n new CustomEvent('valuesChange', {\n bubbles: true,\n composed: true,\n detail: { values: [...this.selected] },\n }),\n );\n }\n\n /** form.reset(): restaura a seleção inicial. */\n override formResetCallback(): void {\n const initial = this._initialValues ?? [];\n this.values = initial;\n this.selected = new Set(initial);\n this.render();\n this.updateFormValue();\n }\n\n private toggleValue(value: string): void {\n if (this.selected.has(value)) this.selected.delete(value);\n else this.selected.add(value);\n this.commit();\n }\n\n /** Navegação por teclado entre as opções do listbox (WCAG 2.1.1). */\n private _navigateOptions(e: KeyboardEvent): void {\n e.preventDefault();\n if (!this.hasAttr('open')) {\n this.toggleAttribute('open');\n this.render();\n }\n const opts = Array.from(this.root.querySelectorAll<HTMLButtonElement>('.opt'));\n if (!opts.length) return;\n const current = opts.indexOf(this.root.activeElement as HTMLButtonElement);\n let next = 0;\n if (e.key === 'ArrowDown') next = current === -1 ? 0 : Math.min(current + 1, opts.length - 1);\n else if (e.key === 'ArrowUp') next = current === -1 ? opts.length - 1 : Math.max(current - 1, 0);\n else if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = opts.length - 1;\n opts[next]?.focus();\n }\n\n protected override render(): void {\n const wasOpen = this.hasAttr('open');\n // Preserva o estado do campo de pesquisa entre re-renders.\n const search = this.root.querySelector<HTMLInputElement>('.search')?.value ?? '';\n\n const opts = this.options;\n for (const v of [...this.selected]) {\n if (!opts.some((o) => o.value === v)) this.selected.delete(v);\n }\n\n const chips = opts.filter((o) => this.selected.has(o.value));\n const placeholder = this.getAttr('placeholder', 'Selecione…');\n const filtered = search\n ? opts.filter((o) => o.label.toLowerCase().includes(search.toLowerCase()))\n : opts;\n\n this.setTemplate(`\n <span class=\"trigger\" part=\"trigger\" role=\"button\" tabindex=\"${this.disabled ? -1 : 0}\" aria-haspopup=\"listbox\" aria-expanded=\"${wasOpen}\" aria-disabled=\"${this.disabled}\">\n <span class=\"lead\">\n ${\n chips.length\n ? chips.map((c) => `\n <span class=\"chip\" data-value=\"${esc(c.value)}\">\n ${esc(c.label)}\n <span class=\"chip__x\" role=\"button\" aria-label=\"Remover ${esc(c.label)}\">×</span>\n </span>`).join('')\n : `<span class=\"placeholder\">${esc(placeholder)}</span>`\n }\n </span>\n <span class=\"trigger-right\">\n ${this.hasAttr('clearable') && chips.length ? '<button type=\"button\" class=\"icon-btn clear\" part=\"clear\" aria-label=\"Limpar seleção\">×</button>' : ''}\n <span class=\"caret\">▼</span>\n </span>\n </span>\n <div class=\"panel\" part=\"panel\" role=\"listbox\" aria-multiselectable=\"true\">\n <div class=\"panel-header\">\n <span class=\"count\">${chips.length} selecionado${chips.length === 1 ? '' : 's'}</span>\n ${this.hasAttr('clearable') && chips.length ? '<button type=\"button\" class=\"clear-all\">Limpar tudo</button>' : ''}\n </div>\n ${this.hasAttr('searchable') ? `<input class=\"search\" part=\"search\" type=\"text\" placeholder=\"${esc(this.getAttr('search-placeholder', 'Pesquisar…'))}\">` : ''}\n <ul class=\"list\">\n ${filtered.map((o) => `\n <li><button type=\"button\" class=\"opt\" role=\"option\" data-value=\"${esc(o.value)}\"\n aria-selected=\"${this.selected.has(o.value)}\">\n <span class=\"box\" aria-hidden=\"true\"></span>${esc(o.label)}\n </button></li>`).join('')}\n ${filtered.length === 0 ? `<li class=\"empty\">${esc(this.getAttr('no-results', 'Nenhum resultado'))}</li>` : ''}\n </ul>\n </div>\n `);\n\n // Reabre o painel se estava aberto antes do re-render.\n if (wasOpen) this.setAttribute('open', '');\n\n const searchInput = this.root.querySelector<HTMLInputElement>('.search');\n if (searchInput) {\n searchInput.value = search;\n // Preserva foco e posição do cursor entre os re-renders da digitação.\n searchInput.addEventListener('input', () => {\n const pos = searchInput.selectionStart ?? searchInput.value.length;\n this.render();\n const si = this.root.querySelector<HTMLInputElement>('.search');\n if (si) {\n si.focus();\n si.setSelectionRange(pos, pos);\n }\n });\n searchInput.addEventListener('click', (e) => e.stopPropagation());\n }\n\n const trigger = this.root.querySelector<HTMLElement>('.trigger');\n if (!trigger) return;\n\n trigger.addEventListener('click', (e) => {\n if (this.disabled) return;\n if ((e.target as HTMLElement).closest('.clear')) return;\n if ((e.target as HTMLElement).closest('.chip__x')) return;\n this.toggleAttribute('open');\n // Flip vertical: se não cabe abaixo, abre para cima.\n if (this.hasAttr('open')) {\n const r = this.getBoundingClientRect();\n this.toggleAttribute('up', r.bottom + 300 > window.innerHeight && r.top > 300);\n } else {\n this.removeAttribute('up');\n }\n this.render();\n });\n\n // Acessibilidade: Enter/Espaço abrem o painel (span role=button); setas navegam.\n trigger.addEventListener('keydown', (e) => {\n if (this.disabled) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n trigger.dispatchEvent(new MouseEvent('click', { bubbles: true }));\n return;\n }\n if (e.key === 'Escape') {\n if (this.hasAttr('open')) {\n this.removeAttribute('open');\n this.render();\n this.root.querySelector<HTMLElement>('.trigger')?.focus();\n }\n return;\n }\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Home' || e.key === 'End') {\n this._navigateOptions(e);\n }\n });\n\n // × de limpar tudo no trigger.\n this.root.querySelector('.clear')?.addEventListener('click', (e) => {\n e.stopPropagation();\n this.selected.clear();\n this.commit();\n });\n\n // \"Limpar tudo\" no cabeçalho do painel.\n this.root.querySelector('.clear-all')?.addEventListener('click', (e) => {\n e.stopPropagation();\n this.selected.clear();\n this.commit();\n });\n\n // Remover chip individual.\n this.root.querySelectorAll<HTMLElement>('.chip').forEach((chip) => {\n chip.querySelector('.chip__x')?.addEventListener('click', (e) => {\n e.stopPropagation();\n this.toggleValue(chip.dataset.value!);\n });\n });\n\n // Alternar opções.\n this.root.querySelectorAll<HTMLElement>('.opt').forEach((opt) => {\n opt.addEventListener('click', () => this.toggleValue(opt.dataset.value!));\n });\n }\n}\n\nexport function defineFxMultiselect(): typeof FxMultiselect {\n return defineElement('fx-multiselect', FxMultiselect);\n}\n\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"multiselect.js","sources":["../../../src/components/multiselect/multiselect.ts"],"sourcesContent":["import { FxFormElement } from '../../core/form-element';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\n\n/**\n * <fx-multiselect> — Seleção múltipla .\n *\n * Form-Associated Custom Element: dentro de um <form> entra no FormData com\n * UMA entrada por valor selecionado (via atributo `name`).\n *\n * Dropdown customizado com painel (overlay), checkbox por item, pesquisa\n * opcional e ação de limpar. Opções via <option> nativos no light DOM.\n *\n * Atributos: values (CSV), searchable, clearable, disabled, placeholder,\n * size (sm|md|lg), no-results.\n * Eventos: `change` e `valuesChange` (composed, detail: { values: string[] }) —\n * `valuesChange` é o two-way binding do Angular [(value)] em seleção múltipla.\n */\nexport class FxMultiselect extends FxFormElement {\n static override styles = css`\n :host {\n display: inline-block;\n vertical-align: middle;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n position: relative;\n /* Largura padrão no HOST: CSS externo, classes e style inline no elemento\n vencem este default naturalmente (regras do documento > :host). */\n width: var(--fx-multiselect-width, 240px);\n }\n .trigger {\n display: inline-flex;\n align-items: center;\n flex-wrap: nowrap;\n gap: var(--fx-space-xs);\n /* Acompanha a largura definida no :host. */\n width: 100%;\n box-sizing: border-box;\n min-height: var(--fx-size-md);\n padding: var(--fx-space-xs) var(--fx-space-md);\n font: inherit;\n /* Altura determinística: a caixa fica no token --fx-size-*. */\n line-height: var(--fx-font-line-height);\n color: var(--fx-text-default);\n background-color: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n cursor: pointer;\n text-align: left;\n transition: border-color var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n /* Área dos chips: encolhe e quebra linha internamente,\n mantendo os ícones sempre dentro do componente. */\n .lead {\n display: inline-flex;\n flex-wrap: wrap;\n gap: var(--fx-space-xs);\n flex: 1;\n min-width: 0;\n overflow: hidden;\n }\n :host([size='sm']) { width: var(--fx-multiselect-width-sm, 200px); }\n :host([size='sm']) .trigger { min-height: var(--fx-size-sm); }\n :host([size='lg']) { width: var(--fx-multiselect-width-lg, 280px); }\n :host([size='lg']) .trigger { min-height: var(--fx-size-lg); font-size: calc(var(--fx-font-size) + 4px); }\n /* Full width: o host estica até o pai e o trigger acompanha. */\n :host([full]) { display: block; width: 100%; }\n :host([full]) .trigger { width: 100%; }\n /* Validação — borda e brilho JÁ EM REPOUSO (igual ao fx-input); o brilho\n segue o token --fx-effect-error-ring, que acompanha effect.focus-ring. */\n :host([error]) .trigger,\n :host([invalid]) .trigger {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([error]) .trigger:focus-visible,\n :host([invalid]) .trigger:focus-visible,\n :host([error][open]) .trigger,\n :host([invalid][open]) .trigger {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([success]) .trigger,\n :host([valid]) .trigger {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));\n }\n :host([success]) .trigger:focus-visible,\n :host([valid]) .trigger:focus-visible,\n :host([success][open]) .trigger,\n :host([valid][open]) .trigger {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));\n }\n .trigger:hover { border-color: var(--fx-border-hover); }\n .trigger:focus-visible {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n .trigger[aria-expanded='true'] { border-color: var(--fx-color-primary); }\n .placeholder { color: var(--fx-text-muted); }\n .chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n background: color-mix(in srgb, var(--fx-color-primary) 14%, transparent);\n color: var(--fx-color-primary);\n border-radius: var(--fx-radius-sm);\n padding: 2px 6px;\n font-size: calc(var(--fx-font-size) - 2px);\n }\n .chip__x {\n border: none;\n background: none;\n color: inherit;\n cursor: pointer;\n font-size: calc(var(--fx-font-size) - 1px);\n line-height: 1;\n padding: 0;\n }\n .trigger-right {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n color: var(--fx-text-muted);\n }\n .icon-btn {\n border: none;\n background: none;\n color: inherit;\n cursor: pointer;\n font-size: calc(var(--fx-font-size) + 2px);\n line-height: 1;\n padding: 0 2px;\n border-radius: var(--fx-radius-full);\n }\n .icon-btn:hover { color: var(--fx-color-danger); }\n .caret {\n font-size: calc(var(--fx-font-size) - 3px);\n transition: transform var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n :host([open]) .caret { transform: rotate(180deg); }\n\n /* Painel (overlay ) */\n .panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n z-index: var(--fx-z-dropdown, 1000);\n width: max(100%, 240px);\n background: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n box-shadow: var(--fx-shadow-lg);\n display: none;\n overflow: hidden;\n }\n :host([up]) .panel {\n top: auto;\n bottom: calc(100% + 4px);\n }\n :host([open]) .panel { display: block; }\n .panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--fx-space-sm);\n padding: var(--fx-space-xs) var(--fx-space-md);\n border-bottom: 1px solid var(--fx-border-default);\n background: var(--fx-surface-surface-hover);\n }\n .count { font-size: calc(var(--fx-font-size) - 2px); color: var(--fx-text-muted); }\n .clear-all {\n border: none;\n background: none;\n font: inherit;\n font-size: calc(var(--fx-font-size) - 2px);\n color: var(--fx-color-primary);\n cursor: pointer;\n padding: 0;\n }\n .clear-all:hover { text-decoration: underline; }\n .search {\n width: 100%;\n box-sizing: border-box;\n font: inherit;\n color: var(--fx-text-default);\n background: var(--fx-surface-background);\n border: none;\n border-bottom: 1px solid var(--fx-border-default);\n padding: var(--fx-space-sm) var(--fx-space-md);\n outline: none;\n }\n .list {\n max-height: 240px;\n overflow-y: auto;\n list-style: none;\n margin: 0;\n padding: var(--fx-space-3xs, 4px);\n }\n .opt {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm);\n width: 100%;\n padding: var(--fx-space-xs) var(--fx-space-md);\n border: none;\n background: none;\n font: inherit;\n color: var(--fx-text-default);\n cursor: pointer;\n border-radius: var(--fx-radius-sm);\n text-align: left;\n }\n .opt:hover { background: color-mix(in srgb, var(--fx-color-primary) 12%, transparent); }\n .opt[aria-selected='true'] {\n background: color-mix(in srgb, var(--fx-color-primary) 16%, transparent);\n color: var(--fx-color-primary);\n font-weight: var(--fx-font-weight);\n }\n /* Checkbox visual */\n .box {\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--fx-border-default);\n border-radius: calc(var(--fx-radius-sm) / 2);\n font-size: 11px;\n line-height: 1;\n color: transparent;\n transition:\n background-color var(--fx-motion-duration-fast) var(--fx-motion-easing),\n border-color var(--fx-motion-duration-fast) var(--fx-motion-easing),\n color var(--fx-motion-duration-fast) var(--fx-motion-easing);\n }\n .opt[aria-selected='true'] .box {\n background: var(--fx-color-primary);\n border-color: var(--fx-color-primary);\n color: #fff;\n }\n .opt[aria-selected='true'] .box::after { content: '✓'; }\n .empty { padding: var(--fx-space-md); color: var(--fx-text-muted); text-align: center; }\n :host([disabled]) .trigger { opacity: 0.55; cursor: not-allowed; background: var(--fx-surface-surface-hover); }\n `;\n\n static override get observedAttributes(): string[] {\n // `error`/`success` (+ aliases `invalid`/`valid`) PRECISAM ser observados:\n // é assim que o toggle no playground / setAttribute no submit re-renderiza.\n return [\n 'values',\n 'size',\n 'disabled',\n 'placeholder',\n 'searchable',\n 'clearable',\n 'full',\n 'error',\n 'invalid',\n 'success',\n 'valid',\n ];\n }\n\n private observer?: MutationObserver;\n private docListener?: (e: Event) => void;\n private selected = new Set<string>();\n /** Seleção inicial (para form.reset() restaurar o estado). */\n private _initialValues?: string[];\n\n protected override attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n // `values` pode chegar como atributo (HTML puro) ou propriedade (Vue).\n // Sincroniza o estado interno antes do render da base.\n if (name === 'values') this.selected = new Set(this.values);\n super.attributeChangedCallback(name, oldValue, newValue);\n }\n\n /** Valores selecionados (CSV no atributo / array na propriedade). */\n get values(): string[] {\n const csv = this.getAttr('values');\n return csv ? csv.split(',').map((v) => v.trim()).filter(Boolean) : [];\n }\n set values(list: string[] | null | undefined) {\n const values = Array.isArray(list) ? list.map(String) : [];\n // O estado interno precisa acompanhar o binding `:values` do Vue — só\n // refletir o atributo deixava a UI desatualizada.\n this.selected = new Set(values);\n const csv = values.join(',');\n if (this.getAttr('values') !== csv) {\n this.setAttribute('values', csv); // observado → render\n } else if (this.isConnected) {\n this.render();\n }\n this.updateFormValue();\n }\n\n /** No FormData do form: uma entrada `name` por valor selecionado. */\n protected override getFormValue(): string | FormData | null {\n const values = this.values;\n if (!this.name || values.length === 0) return null;\n const fd = new FormData();\n values.forEach((v) => fd.append(this.name, v));\n return fd;\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 get searchable(): boolean {\n return this.hasAttr('searchable');\n }\n set searchable(value: boolean) {\n this.toggleAttr('searchable', Boolean(value));\n }\n\n get clearable(): boolean {\n return this.hasAttr('clearable');\n }\n set clearable(value: boolean) {\n this.toggleAttr('clearable', Boolean(value));\n }\n\n get full(): boolean {\n return this.hasAttr('full');\n }\n set full(value: boolean) {\n this.toggleAttr('full', Boolean(value));\n }\n\n private get options(): { value: string; label: string }[] {\n return [...this.querySelectorAll('option')].map((o) => ({\n value: o.getAttribute('value') ?? o.textContent?.trim() ?? '',\n label: o.textContent?.trim() ?? '',\n }));\n }\n\n protected override connectedCallback(): void {\n // Popula a seleção ANTES do primeiro render (super chama render).\n this.selected = new Set(this.values);\n if (!this._initialValues) this._initialValues = [...this.values];\n super.connectedCallback();\n this.observer = new MutationObserver(() => this.render());\n this.observer.observe(this, {\n childList: true,\n subtree: true,\n characterData: true,\n // Vue atualiza `:value`/`:selected` das <option> no light DOM; sem\n // observar atributos o label/valor antigo permanecia em tela.\n attributes: true,\n attributeFilter: ['value', 'selected'],\n });\n this.docListener = (e: Event) => {\n if (!this.hasAttr('open')) return;\n if (e.composedPath().includes(this)) return;\n this.removeAttribute('open');\n this.render();\n };\n document.addEventListener('click', this.docListener);\n }\n\n protected override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.observer?.disconnect();\n if (this.docListener) document.removeEventListener('click', this.docListener);\n }\n\n /** Aplica a seleção, reflete e emite change. */\n private commit(): void {\n // `values` é observado e renderiza quando o CSV muda (uma única vez).\n const next = [...this.selected];\n const same = next.join(',') === this.values.join(',');\n this.values = next;\n if (same && this.isConnected) this.render();\n this.updateFormValue();\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { values: [...this.selected] },\n }),\n );\n // Two-way binding do Angular: [(value)] em selecao multipla -> valuesChange.\n this.dispatchEvent(\n new CustomEvent('valuesChange', {\n bubbles: true,\n composed: true,\n detail: { values: [...this.selected] },\n }),\n );\n }\n\n /** form.reset(): restaura a seleção inicial. */\n override formResetCallback(): void {\n const initial = this._initialValues ?? [];\n // `values` sincroniza `selected` e renderiza (uma vez) quando muda.\n this.values = initial;\n this.updateFormValue();\n }\n\n private toggleValue(value: string): void {\n if (this.selected.has(value)) this.selected.delete(value);\n else this.selected.add(value);\n this.commit();\n }\n\n /** Navegação por teclado entre as opções do listbox (WCAG 2.1.1). */\n private _navigateOptions(e: KeyboardEvent): void {\n e.preventDefault();\n if (!this.hasAttr('open')) {\n this.toggleAttribute('open');\n this.render();\n }\n const opts = Array.from(this.root.querySelectorAll<HTMLButtonElement>('.opt'));\n if (!opts.length) return;\n const current = opts.indexOf(this.root.activeElement as HTMLButtonElement);\n let next = 0;\n if (e.key === 'ArrowDown') next = current === -1 ? 0 : Math.min(current + 1, opts.length - 1);\n else if (e.key === 'ArrowUp') next = current === -1 ? opts.length - 1 : Math.max(current - 1, 0);\n else if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = opts.length - 1;\n opts[next]?.focus();\n }\n\n protected override render(): void {\n const wasOpen = this.hasAttr('open');\n // Preserva o estado do campo de pesquisa entre re-renders.\n const search = this.root.querySelector<HTMLInputElement>('.search')?.value ?? '';\n\n const opts = this.options;\n // Só remove valores órfãos quando as opções já chegaram: com `v-for`\n // (opções depois do valor), limpar aqui apagaria a seleção controlada.\n if (opts.length > 0) {\n for (const v of [...this.selected]) {\n if (!opts.some((o) => o.value === v)) this.selected.delete(v);\n }\n }\n\n const chips = opts.filter((o) => this.selected.has(o.value));\n const placeholder = this.getAttr('placeholder', 'Selecione…');\n const filtered = search\n ? opts.filter((o) => o.label.toLowerCase().includes(search.toLowerCase()))\n : opts;\n\n this.setTemplate(`\n <span class=\"trigger\" part=\"trigger\" role=\"button\" tabindex=\"${this.disabled ? -1 : 0}\" aria-haspopup=\"listbox\" aria-expanded=\"${wasOpen}\" aria-disabled=\"${this.disabled}\">\n <span class=\"lead\">\n ${\n chips.length\n ? chips.map((c) => `\n <span class=\"chip\" data-value=\"${esc(c.value)}\">\n ${esc(c.label)}\n <span class=\"chip__x\" role=\"button\" aria-label=\"Remover ${esc(c.label)}\">×</span>\n </span>`).join('')\n : `<span class=\"placeholder\">${esc(placeholder)}</span>`\n }\n </span>\n <span class=\"trigger-right\">\n ${this.hasAttr('clearable') && chips.length ? '<button type=\"button\" class=\"icon-btn clear\" part=\"clear\" aria-label=\"Limpar seleção\">×</button>' : ''}\n <span class=\"caret\">▼</span>\n </span>\n </span>\n <div class=\"panel\" part=\"panel\" role=\"listbox\" aria-multiselectable=\"true\">\n <div class=\"panel-header\">\n <span class=\"count\">${chips.length} selecionado${chips.length === 1 ? '' : 's'}</span>\n ${this.hasAttr('clearable') && chips.length ? '<button type=\"button\" class=\"clear-all\">Limpar tudo</button>' : ''}\n </div>\n ${this.hasAttr('searchable') ? `<input class=\"search\" part=\"search\" type=\"text\" placeholder=\"${esc(this.getAttr('search-placeholder', 'Pesquisar…'))}\">` : ''}\n <ul class=\"list\">\n ${filtered.map((o) => `\n <li><button type=\"button\" class=\"opt\" role=\"option\" data-value=\"${esc(o.value)}\"\n aria-selected=\"${this.selected.has(o.value)}\">\n <span class=\"box\" aria-hidden=\"true\"></span>${esc(o.label)}\n </button></li>`).join('')}\n ${filtered.length === 0 ? `<li class=\"empty\">${esc(this.getAttr('no-results', 'Nenhum resultado'))}</li>` : ''}\n </ul>\n </div>\n `);\n\n // Reabre o painel se estava aberto antes do re-render.\n if (wasOpen) this.setAttribute('open', '');\n\n const searchInput = this.root.querySelector<HTMLInputElement>('.search');\n if (searchInput) {\n searchInput.value = search;\n // Preserva foco e posição do cursor entre os re-renders da digitação.\n searchInput.addEventListener('input', () => {\n const pos = searchInput.selectionStart ?? searchInput.value.length;\n this.render();\n const si = this.root.querySelector<HTMLInputElement>('.search');\n if (si) {\n si.focus();\n si.setSelectionRange(pos, pos);\n }\n });\n searchInput.addEventListener('click', (e) => e.stopPropagation());\n }\n\n const trigger = this.root.querySelector<HTMLElement>('.trigger');\n if (!trigger) return;\n\n trigger.addEventListener('click', (e) => {\n if (this.disabled) return;\n if ((e.target as HTMLElement).closest('.clear')) return;\n if ((e.target as HTMLElement).closest('.chip__x')) return;\n this.toggleAttribute('open');\n // Flip vertical: se não cabe abaixo, abre para cima.\n if (this.hasAttr('open')) {\n const r = this.getBoundingClientRect();\n this.toggleAttribute('up', r.bottom + 300 > window.innerHeight && r.top > 300);\n } else {\n this.removeAttribute('up');\n }\n this.render();\n });\n\n // Acessibilidade: Enter/Espaço abrem o painel (span role=button); setas navegam.\n trigger.addEventListener('keydown', (e) => {\n if (this.disabled) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n trigger.dispatchEvent(new MouseEvent('click', { bubbles: true }));\n return;\n }\n if (e.key === 'Escape') {\n if (this.hasAttr('open')) {\n this.removeAttribute('open');\n this.render();\n this.root.querySelector<HTMLElement>('.trigger')?.focus();\n }\n return;\n }\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Home' || e.key === 'End') {\n this._navigateOptions(e);\n }\n });\n\n // × de limpar tudo no trigger.\n this.root.querySelector('.clear')?.addEventListener('click', (e) => {\n e.stopPropagation();\n this.selected.clear();\n this.commit();\n });\n\n // \"Limpar tudo\" no cabeçalho do painel.\n this.root.querySelector('.clear-all')?.addEventListener('click', (e) => {\n e.stopPropagation();\n this.selected.clear();\n this.commit();\n });\n\n // Remover chip individual.\n this.root.querySelectorAll<HTMLElement>('.chip').forEach((chip) => {\n chip.querySelector('.chip__x')?.addEventListener('click', (e) => {\n e.stopPropagation();\n this.toggleValue(chip.dataset.value!);\n });\n });\n\n // Alternar opções.\n this.root.querySelectorAll<HTMLElement>('.opt').forEach((opt) => {\n opt.addEventListener('click', () => this.toggleValue(opt.dataset.value!));\n });\n }\n}\n\nexport function defineFxMultiselect(): typeof FxMultiselect {\n return defineElement('fx-multiselect', FxMultiselect);\n}\n\n"],"names":[],"mappings":"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"}
@@ -20,6 +20,13 @@ export declare class FxOrderList extends FxElement {
20
20
  get data(): OrderListItem[];
21
21
  private _data;
22
22
  private _filteredData;
23
+ /**
24
+ * Alias de `data` para o binding do Vue/React: `data` colide com a
25
+ * tipagem nativa de atributos HTML (`dataset`/`data-*`) e não reflete em
26
+ * atributo. `items` funciona como propriedade e como atributo JSON.
27
+ */
28
+ get items(): OrderListItem[];
29
+ set items(value: OrderListItem[]);
23
30
  set selection(value: OrderListItem[]);
24
31
  get selection(): OrderListItem[];
25
32
  private _selection;
@@ -1 +1 @@
1
- {"version":3,"file":"orderlist.d.ts","sourceRoot":"","sources":["../../../src/components/orderlist/orderlist.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orderlist.d.ts","sourceRoot":"","sources":["../../../src/components/orderlist/orderlist.ts"],"names":[],"mappings":"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"}