@wrrdev/fenix-ui 1.1.6 → 1.1.8

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 (101) hide show
  1. package/README.md +23 -3
  2. package/dist/assets/{base-css-Be_r8aTo.js → font-CF0TXsAP.js} +39 -3
  3. package/dist/assets/font-CF0TXsAP.js.map +1 -0
  4. package/dist/components/autocomplete/autocomplete.d.ts.map +1 -1
  5. package/dist/components/autocomplete/autocomplete.js +9 -6
  6. package/dist/components/autocomplete/autocomplete.js.map +1 -1
  7. package/dist/components/button/button.d.ts.map +1 -1
  8. package/dist/components/button/button.js +5 -3
  9. package/dist/components/button/button.js.map +1 -1
  10. package/dist/components/datepicker/datepicker.d.ts.map +1 -1
  11. package/dist/components/datepicker/datepicker.js +11 -6
  12. package/dist/components/datepicker/datepicker.js.map +1 -1
  13. package/dist/components/fileupload/fileupload.d.ts +1 -1
  14. package/dist/components/fileupload/fileupload.d.ts.map +1 -1
  15. package/dist/components/fileupload/fileupload.js +5 -3
  16. package/dist/components/fileupload/fileupload.js.map +1 -1
  17. package/dist/components/icon/icon.d.ts +40 -0
  18. package/dist/components/icon/icon.d.ts.map +1 -0
  19. package/dist/components/icon/icon.js +79 -0
  20. package/dist/components/icon/icon.js.map +1 -0
  21. package/dist/components/icon/index.d.ts +8 -0
  22. package/dist/components/icon/index.d.ts.map +1 -0
  23. package/dist/components/icon/index.js +7 -0
  24. package/dist/components/icon/index.js.map +1 -0
  25. package/dist/components/input/input.d.ts.map +1 -1
  26. package/dist/components/input/input.js +12 -6
  27. package/dist/components/input/input.js.map +1 -1
  28. package/dist/components/knob/knob.d.ts +1 -1
  29. package/dist/components/knob/knob.d.ts.map +1 -1
  30. package/dist/components/knob/knob.js +3 -1
  31. package/dist/components/knob/knob.js.map +1 -1
  32. package/dist/components/multiselect/multiselect.d.ts.map +1 -1
  33. package/dist/components/multiselect/multiselect.js +8 -3
  34. package/dist/components/multiselect/multiselect.js.map +1 -1
  35. package/dist/components/orderlist/orderlist.js +2 -2
  36. package/dist/components/orderlist/orderlist.js.map +1 -1
  37. package/dist/components/picklist/picklist.js +2 -2
  38. package/dist/components/picklist/picklist.js.map +1 -1
  39. package/dist/components/select/select.d.ts.map +1 -1
  40. package/dist/components/select/select.js +9 -3
  41. package/dist/components/select/select.js.map +1 -1
  42. package/dist/components/textarea/textarea.d.ts.map +1 -1
  43. package/dist/components/textarea/textarea.js +7 -3
  44. package/dist/components/textarea/textarea.js.map +1 -1
  45. package/dist/components/toggle-button-group/toggle-button-group.d.ts.map +1 -1
  46. package/dist/components/toggle-button-group/toggle-button-group.js +3 -1
  47. package/dist/components/toggle-button-group/toggle-button-group.js.map +1 -1
  48. package/dist/core/jsx.d.ts +22 -0
  49. package/dist/core/jsx.d.ts.map +1 -1
  50. package/dist/core/jsx.js.map +1 -1
  51. package/dist/core/theme.d.ts.map +1 -1
  52. package/dist/core/theme.js +12 -0
  53. package/dist/core/theme.js.map +1 -1
  54. package/dist/core/tokens.d.ts +4 -0
  55. package/dist/core/tokens.d.ts.map +1 -1
  56. package/dist/core/tokens.js +9 -1
  57. package/dist/core/tokens.js.map +1 -1
  58. package/dist/core/vue.d.ts +3 -1
  59. package/dist/core/vue.d.ts.map +1 -1
  60. package/dist/core/vue.js.map +1 -1
  61. package/dist/docs/app.d.ts.map +1 -1
  62. package/dist/docs/componentes/icon.doc.d.ts +9 -0
  63. package/dist/docs/componentes/icon.doc.d.ts.map +1 -0
  64. package/dist/docs/componentes/index.d.ts.map +1 -1
  65. package/dist/fenix-ui.umd.min.js +195 -138
  66. package/dist/fenix-ui2.esm.js.map +1 -1
  67. package/dist/fenix-ui3.esm.js +10 -14
  68. package/dist/fenix-ui3.esm.js.map +1 -1
  69. package/dist/fenix-ui4.esm.js +187 -60
  70. package/dist/fenix-ui4.esm.js.map +1 -1
  71. package/dist/fenix-ui5.esm.js +41 -15
  72. package/dist/fenix-ui5.esm.js.map +1 -1
  73. package/dist/icons/font.d.ts +26 -0
  74. package/dist/icons/font.d.ts.map +1 -0
  75. package/dist/icons/font.js +42 -0
  76. package/dist/icons/font.js.map +1 -0
  77. package/dist/icons/index.d.ts +3 -1
  78. package/dist/icons/index.d.ts.map +1 -1
  79. package/dist/icons/index.js +11 -13
  80. package/dist/icons/index.js.map +1 -1
  81. package/dist/icons/name-union.d.ts +11 -0
  82. package/dist/icons/name-union.d.ts.map +1 -0
  83. package/dist/icons/names.d.ts +0 -1
  84. package/dist/icons/names.d.ts.map +1 -1
  85. package/dist/icons/names.js.map +1 -1
  86. package/dist/icons/types.d.ts +14 -0
  87. package/dist/icons/types.d.ts.map +1 -0
  88. package/dist/index.d.ts +2 -0
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +3 -0
  91. package/dist/index.js.map +1 -1
  92. package/dist/plugins/auto-import.d.ts +19 -2
  93. package/dist/plugins/auto-import.d.ts.map +1 -1
  94. package/dist/plugins/auto-import.js +40 -14
  95. package/dist/plugins/auto-import.js.map +1 -1
  96. package/dist/plugins/index.d.ts +5 -0
  97. package/dist/plugins/index.d.ts.map +1 -1
  98. package/dist/plugins/index.js +1 -1
  99. package/dist/plugins/index.js.map +1 -1
  100. package/package.json +5 -1
  101. package/dist/assets/base-css-Be_r8aTo.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { FxElement } from '../../core/base';
2
2
  /**
3
- * <fx-fileupload> — Seletor de arquivos com upload e progresso (estilo FileUpload do PrimeVue).
3
+ * <fx-fileupload> — Seletor de arquivos com upload e progresso.
4
4
  *
5
5
  * Atributos:
6
6
  * - mode (basic|advanced — `basic`: botão; `advanced`: dropzone com drag & drop);
@@ -1 +1 @@
1
- {"version":3,"file":"fileupload.d.ts","sourceRoot":"","sources":["../../../src/components/fileupload/fileupload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,YAAa,SAAQ,SAAS;IACzC,OAAgB,MAAM,SA0IpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,IAAI,IAAI,IAAI,MAAM,CAGjB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAAuC;IAE7D,4DAA4D;IAC5D,IAAI,KAAK,IAAI,MAAM,CAAkC;IACrD,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,EAAoC;IAEvD,IAAI,QAAQ,IAAI,MAAM,CAAmF;IACzG,IAAI,QAAQ,CAAC,CAAC,EAAE,MAAM,EAA+C;IAErE,4DAA4D;IAC5D,IAAI,KAAK,IAAI,IAAI,EAAE,CAAwB;IAC3C,IAAI,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,EAItB;cAEkB,MAAM,IAAI,IAAI;IA6CjC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,KAAK,CAAS;IAEtB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,WAAW;IAyBnB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,QAAQ;IAMhB,kFAAkF;IAClF,OAAO,CAAC,cAAc;CAyBvB;AAED,wBAAgB,kBAAkB,IAAI,OAAO,YAAY,CAExD"}
1
+ {"version":3,"file":"fileupload.d.ts","sourceRoot":"","sources":["../../../src/components/fileupload/fileupload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,YAAa,SAAQ,SAAS;IACzC,OAAgB,MAAM,SA4IpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,IAAI,IAAI,IAAI,MAAM,CAGjB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAAuC;IAE7D,4DAA4D;IAC5D,IAAI,KAAK,IAAI,MAAM,CAAkC;IACrD,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,EAAoC;IAEvD,IAAI,QAAQ,IAAI,MAAM,CAAmF;IACzG,IAAI,QAAQ,CAAC,CAAC,EAAE,MAAM,EAA+C;IAErE,4DAA4D;IAC5D,IAAI,KAAK,IAAI,IAAI,EAAE,CAAwB;IAC3C,IAAI,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,EAItB;cAEkB,MAAM,IAAI,IAAI;IA6CjC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,KAAK,CAAS;IAEtB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,WAAW;IAyBnB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,QAAQ;IAMhB,kFAAkF;IAClF,OAAO,CAAC,cAAc;CAyBvB;AAED,wBAAgB,kBAAkB,IAAI,OAAO,YAAY,CAExD"}
@@ -165,10 +165,12 @@ _FxFileUpload.styles = css`
165
165
  o botão sem precisar do full (host é shrink-to-fit por padrão). */
166
166
  width: 100%;
167
167
  min-height: var(--fx-size-md);
168
- padding: var(--fx-space-md) var(--fx-space-lg);
168
+ /* Padding vertical no orçamento do token --fx-size-* ⇒ altura padrão. */
169
+ padding: var(--fx-space-sm) var(--fx-space-lg);
169
170
  font-family: inherit;
170
171
  font-size: inherit;
171
172
  font-weight: var(--fx-font-weight);
173
+ line-height: var(--fx-font-line-height);
172
174
  color: var(--fx-text-default);
173
175
  background-color: var(--fx-surface-background);
174
176
  border: 1px solid var(--fx-border-default);
@@ -195,8 +197,8 @@ _FxFileUpload.styles = css`
195
197
  :host([severity='info']) .btn { background: var(--fx-color-info); border-color: transparent; color: #fff; }
196
198
  :host([severity]) .btn:hover { filter: brightness(0.88); }
197
199
  :host([severity]) .btn:focus-visible { border-color: transparent; }
198
- :host([size='sm']) .btn { min-height: var(--fx-size-sm); padding: var(--fx-space-sm) var(--fx-space-md); font-size: calc(var(--fx-font-size) - 2px); }
199
- :host([size='lg']) .btn { min-height: var(--fx-size-lg); padding: var(--fx-space-lg) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); }
200
+ :host([size='sm']) .btn { min-height: var(--fx-size-sm); padding: var(--fx-space-xs) var(--fx-space-md); font-size: calc(var(--fx-font-size) - 2px); }
201
+ :host([size='lg']) .btn { min-height: var(--fx-size-lg); padding: var(--fx-space-sm) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); }
200
202
  :host([size='sm']) .drop { min-height: 72px; }
201
203
  :host([size='lg']) .drop { min-height: 132px; }
202
204
 
@@ -1 +1 @@
1
- {"version":3,"file":"fileupload.js","sources":["../../../src/components/fileupload/fileupload.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, fenixIconHtml } from '../../icons/base-css';\n\n/**\n * <fx-fileupload> — Seletor de arquivos com upload e progresso (estilo FileUpload do PrimeVue).\n *\n * Atributos:\n * - mode (basic|advanced — `basic`: botão; `advanced`: dropzone com drag & drop);\n * - size (sm|md|lg, padrão md);\n * - severity (primary|secondary|success|warning|danger|info — cor do botão no modo basic);\n * - label (texto do botão/área, padrão 'Escolher arquivo');\n * - icon (glifo/emoji exibido antes do texto — sem o atributo, sem ícone);\n * - accept, multiple, disabled (como no <input type=\"file\">);\n * - show-progress (exibe barra + % de upload);\n * - progress (0-100 — o consumidor atualiza durante o upload real);\n * - value (nome(s) do(s) arquivo(s) carregado(s), somente leitura/espelho).\n *\n * Eventos (composed): `select` (detail: { files: File[] }), `remove`, `complete`.\n */\nexport class FxFileUpload extends FxElement {\n static override styles = css`\n :host {\n display: inline-block;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n :host([disabled]) { opacity: 0.55; pointer-events: none; }\n input[type='file'] { display: none; }\n\n /* ---- botão (basic) ---- */\n .btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--fx-space-sm);\n /* Largura acompanha o host: CSS externo/classe/inline no elemento esticam\n o botão sem precisar do full (host é shrink-to-fit por padrão). */\n width: 100%;\n min-height: var(--fx-size-md);\n padding: var(--fx-space-md) var(--fx-space-lg);\n font-family: inherit;\n font-size: inherit;\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 cursor: pointer;\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 background var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .btn:hover { border-color: var(--fx-border-hover); background: var(--fx-surface-surface-hover, rgba(0,0,0,0.03)); }\n .btn:focus-visible {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n /* Severities (como no <fx-button>) — aplicam-se ao botão do modo basic */\n :host([severity='primary']) .btn { background: var(--fx-color-primary); border-color: transparent; color: #fff; }\n :host([severity='secondary']) .btn { background: var(--fx-color-secondary); border-color: transparent; color: #fff; }\n :host([severity='success']) .btn { background: var(--fx-color-success); border-color: transparent; color: #fff; }\n :host([severity='warning']) .btn { background: var(--fx-color-warning); border-color: transparent; color: #fff; }\n :host([severity='danger']) .btn { background: var(--fx-color-danger); border-color: transparent; color: #fff; }\n :host([severity='info']) .btn { background: var(--fx-color-info); border-color: transparent; color: #fff; }\n :host([severity]) .btn:hover { filter: brightness(0.88); }\n :host([severity]) .btn:focus-visible { border-color: transparent; }\n :host([size='sm']) .btn { min-height: var(--fx-size-sm); padding: var(--fx-space-sm) var(--fx-space-md); font-size: calc(var(--fx-font-size) - 2px); }\n :host([size='lg']) .btn { min-height: var(--fx-size-lg); padding: var(--fx-space-lg) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); }\n :host([size='sm']) .drop { min-height: 72px; }\n :host([size='lg']) .drop { min-height: 132px; }\n\n /* ---- dropzone (advanced) ---- */\n .drop {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--fx-space-sm);\n /* Acompanha a largura do host (definida por CSS externo/classe/inline). */\n width: 100%;\n min-height: 100px;\n padding: var(--fx-space-lg);\n border: 2px dashed var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n color: var(--fx-text-muted);\n cursor: pointer;\n text-align: center;\n transition: border-color var(--fx-motion-duration-normal) var(--fx-motion-easing), background var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .drop:hover, .drop.over {\n border-color: var(--fx-color-primary);\n background: color-mix(in srgb, var(--fx-color-primary) 6%, transparent);\n }\n .drop .icon { font-size: calc(var(--fx-font-size) + 12px); line-height: 1; }\n .drop .hint { font-size: calc(var(--fx-font-size) - 2px); }\n\n /* ---- ícone comum ---- */\n .icon { line-height: 1; }\n\n /* ---- arquivo(s) selecionado(s) ---- */\n .files { display: flex; flex-direction: column; gap: var(--fx-space-xs); margin-top: var(--fx-space-sm); }\n .file {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm);\n padding: var(--fx-space-xs) var(--fx-space-sm);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-sm);\n font-size: calc(var(--fx-font-size) - 2px);\n color: var(--fx-text-default);\n }\n .file .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .file .size { color: var(--fx-text-muted); white-space: nowrap; }\n .file .remove {\n border: none;\n background: transparent;\n color: var(--fx-text-muted);\n cursor: pointer;\n font-size: calc(var(--fx-font-size) + 2px);\n line-height: 1;\n padding: 0 var(--fx-space-xs);\n border-radius: var(--fx-radius-full);\n }\n .file .remove:hover { color: var(--fx-color-danger); }\n\n /* ---- progresso ---- */\n .progress-row { display: flex; align-items: center; gap: var(--fx-space-sm); margin-top: var(--fx-space-sm); }\n .track {\n flex: 1;\n height: 6px;\n background: var(--fx-surface-surface-hover);\n border-radius: var(--fx-radius-full);\n overflow: hidden;\n }\n .bar {\n height: 100%;\n width: 0%;\n background: var(--fx-color-primary);\n border-radius: var(--fx-radius-full);\n transition: width var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n :host([progress='100']) .bar { background: var(--fx-color-success); }\n .pct {\n font-size: calc(var(--fx-font-size) - 2px);\n font-weight: 600;\n color: var(--fx-text-default);\n min-width: 34px;\n text-align: right;\n }\n /* Full width: o host estica até o pai e o botão/dropzone acompanha. */\n :host([full]) { display: block; width: 100%; }\n :host([full]) .btn { width: 100%; }\n :host([full]) .drop { width: 100%; }\n /* Base dos glifos Fenix Icons (o @font-face vem de @wrrdev/fenix-ui/icons). */\n ${FENIX_ICON_BASE_CSS}\n `;\n\n static override get observedAttributes(): string[] {\n return ['mode', 'size', 'severity', 'label', 'icon', 'accept', 'multiple', 'disabled', 'show-progress', 'progress', 'value', 'full'];\n }\n\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) { this.setAttribute('size', value); }\n\n /** Nomes dos arquivos selecionados (espelho em `value`). */\n get value(): string { return this.getAttr('value'); }\n set value(v: string) { this.setAttribute('value', v); }\n\n get progress(): number { return Math.min(100, Math.max(0, Number(this.getAttr('progress', '0')) || 0)); }\n set progress(v: number) { this.setAttribute('progress', String(v)); }\n\n /** Arquivos selecionados (não serializável em atributo). */\n get files(): File[] { return this._files; }\n set files(files: File[]) {\n this._files = Array.from(files);\n this.value = this._files.map((f) => f.name).join(', ');\n this._syncFilesArea();\n }\n\n protected override render(): void {\n const mode = this.getAttr('mode', 'basic');\n const advanced = mode === 'advanced';\n const label = this.getAttr('label', 'Escolher arquivo');\n const icon = this.getAttr('icon');\n const accept = this.getAttr('accept');\n const multiple = this.hasAttr('multiple');\n const disabled = this.hasAttr('disabled');\n const showProgress = this.hasAttr('show-progress');\n const pct = this.progress;\n\n const fileInput = `<input type=\"file\" class=\"picker\" ${accept ? `accept=\"${esc(accept)}\"` : ''} ${multiple ? 'multiple' : ''} ${disabled ? 'disabled' : ''} />`;\n\n this.setTemplate(`\n ${advanced\n ? `<div class=\"drop\" part=\"dropzone\" role=\"button\" tabindex=\"0\" aria-label=\"${esc(label)}\">\n ${icon ? `<span class=\"icon\" part=\"icon\" aria-hidden=\"true\">${fenixIconHtml(icon)}</span>` : ''}\n <span>${esc(label)}</span>\n <span class=\"hint\">ou arraste e solte aqui</span>\n </div>`\n : `<button type=\"button\" class=\"btn\" part=\"button\">\n ${icon ? `<span class=\"icon\" part=\"icon\" aria-hidden=\"true\">${fenixIconHtml(icon)}</span>` : ''}\n <span>${esc(label)}</span>\n </button>`}\n ${fileInput}\n <div class=\"files\" part=\"files\"></div>\n ${showProgress ? `\n <div class=\"progress-row\" part=\"progress\">\n <div class=\"track\" role=\"progressbar\" aria-valuenow=\"${pct}\" aria-valuemin=\"0\" aria-valuemax=\"100\">\n <div class=\"bar\" style=\"width: ${pct}%\"></div>\n </div>\n <span class=\"pct\">${pct}%</span>\n </div>` : ''}\n `);\n\n this._bindPicker();\n this._syncFilesArea();\n\n if (!this._done && showProgress && pct >= 100 && this._files.length) {\n this._done = true;\n this.dispatchEvent(new CustomEvent('complete', { bubbles: true, composed: true }));\n }\n if (pct < 100) this._done = false;\n }\n\n private _files: File[] = [];\n private _done = false;\n\n private _picker(): HTMLInputElement | null {\n return this.root.querySelector<HTMLInputElement>('.picker');\n }\n\n private _bindPicker(): void {\n const picker = this._picker();\n if (!picker) return;\n const trigger = this.root.querySelector('.btn') ?? this.root.querySelector('.drop');\n trigger?.addEventListener('click', () => picker.click());\n trigger?.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter' || (e as KeyboardEvent).key === ' ') {\n e.preventDefault();\n picker.click();\n }\n });\n picker.addEventListener('change', () => this._acceptFiles(picker.files ?? []));\n\n // drag & drop (advanced)\n const drop = this.root.querySelector<HTMLElement>('.drop');\n if (!drop) return;\n drop.addEventListener('dragover', (e) => { e.preventDefault(); drop.classList.add('over'); });\n drop.addEventListener('dragleave', () => drop.classList.remove('over'));\n drop.addEventListener('drop', (e) => {\n e.preventDefault();\n drop.classList.remove('over');\n if (e.dataTransfer?.files.length) this._acceptFiles(e.dataTransfer.files);\n });\n }\n\n private _acceptFiles(list: FileList | File[]): void {\n const picked = this.hasAttr('multiple') ? Array.from(list) : [list[0]].filter(Boolean);\n this.files = picked;\n const picker = this._picker();\n if (picker) picker.value = '';\n this.dispatchEvent(\n new CustomEvent('select', { bubbles: true, composed: true, detail: { files: picked } }),\n );\n }\n\n private _fmtSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n }\n\n /** Renderiza a lista de arquivos sem re-renderizar o template (mantém estado). */\n private _syncFilesArea(): void {\n const area = this.root?.querySelector?.('.files') as HTMLElement | null;\n if (!area) return;\n area.innerHTML = this._files\n .map(\n (f, i) => `\n <div class=\"file\" part=\"file\">\n <span class=\"name\">${esc(f.name)}</span>\n <span class=\"size\">${this._fmtSize(f.size)}</span>\n <button type=\"button\" class=\"remove\" data-i=\"${i}\" part=\"remove\" aria-label=\"Remover ${esc(f.name)}\">×</button>\n </div>`,\n )\n .join('');\n area.querySelectorAll<HTMLButtonElement>('.remove').forEach((btn) =>\n btn.addEventListener('click', () => {\n const removed = this._files.splice(Number(btn.dataset.i), 1)[0];\n this.value = this._files.map((f) => f.name).join(', ');\n this.progress = 0;\n this._syncFilesArea();\n this.dispatchEvent(\n new CustomEvent('remove', { bubbles: true, composed: true, detail: { file: removed } }),\n );\n }),\n );\n }\n}\n\nexport function defineFxFileUpload(): typeof FxFileUpload {\n return defineElement('fx-fileupload', FxFileUpload);\n}\n\n\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fileupload.js","sources":["../../../src/components/fileupload/fileupload.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, fenixIconHtml } from '../../icons/base-css';\n\n/**\n * <fx-fileupload> — Seletor de arquivos com upload e progresso.\n *\n * Atributos:\n * - mode (basic|advanced — `basic`: botão; `advanced`: dropzone com drag & drop);\n * - size (sm|md|lg, padrão md);\n * - severity (primary|secondary|success|warning|danger|info — cor do botão no modo basic);\n * - label (texto do botão/área, padrão 'Escolher arquivo');\n * - icon (glifo/emoji exibido antes do texto — sem o atributo, sem ícone);\n * - accept, multiple, disabled (como no <input type=\"file\">);\n * - show-progress (exibe barra + % de upload);\n * - progress (0-100 — o consumidor atualiza durante o upload real);\n * - value (nome(s) do(s) arquivo(s) carregado(s), somente leitura/espelho).\n *\n * Eventos (composed): `select` (detail: { files: File[] }), `remove`, `complete`.\n */\nexport class FxFileUpload extends FxElement {\n static override styles = css`\n :host {\n display: inline-block;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n :host([disabled]) { opacity: 0.55; pointer-events: none; }\n input[type='file'] { display: none; }\n\n /* ---- botão (basic) ---- */\n .btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--fx-space-sm);\n /* Largura acompanha o host: CSS externo/classe/inline no elemento esticam\n o botão sem precisar do full (host é shrink-to-fit por padrão). */\n width: 100%;\n min-height: var(--fx-size-md);\n /* Padding vertical no orçamento do token --fx-size-* ⇒ altura padrão. */\n padding: var(--fx-space-sm) var(--fx-space-lg);\n font-family: inherit;\n font-size: inherit;\n font-weight: var(--fx-font-weight);\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 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 background var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .btn:hover { border-color: var(--fx-border-hover); background: var(--fx-surface-surface-hover, rgba(0,0,0,0.03)); }\n .btn:focus-visible {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n /* Severities (como no <fx-button>) — aplicam-se ao botão do modo basic */\n :host([severity='primary']) .btn { background: var(--fx-color-primary); border-color: transparent; color: #fff; }\n :host([severity='secondary']) .btn { background: var(--fx-color-secondary); border-color: transparent; color: #fff; }\n :host([severity='success']) .btn { background: var(--fx-color-success); border-color: transparent; color: #fff; }\n :host([severity='warning']) .btn { background: var(--fx-color-warning); border-color: transparent; color: #fff; }\n :host([severity='danger']) .btn { background: var(--fx-color-danger); border-color: transparent; color: #fff; }\n :host([severity='info']) .btn { background: var(--fx-color-info); border-color: transparent; color: #fff; }\n :host([severity]) .btn:hover { filter: brightness(0.88); }\n :host([severity]) .btn:focus-visible { border-color: transparent; }\n :host([size='sm']) .btn { min-height: var(--fx-size-sm); padding: var(--fx-space-xs) var(--fx-space-md); font-size: calc(var(--fx-font-size) - 2px); }\n :host([size='lg']) .btn { min-height: var(--fx-size-lg); padding: var(--fx-space-sm) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); }\n :host([size='sm']) .drop { min-height: 72px; }\n :host([size='lg']) .drop { min-height: 132px; }\n\n /* ---- dropzone (advanced) ---- */\n .drop {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--fx-space-sm);\n /* Acompanha a largura do host (definida por CSS externo/classe/inline). */\n width: 100%;\n min-height: 100px;\n padding: var(--fx-space-lg);\n border: 2px dashed var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n color: var(--fx-text-muted);\n cursor: pointer;\n text-align: center;\n transition: border-color var(--fx-motion-duration-normal) var(--fx-motion-easing), background var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .drop:hover, .drop.over {\n border-color: var(--fx-color-primary);\n background: color-mix(in srgb, var(--fx-color-primary) 6%, transparent);\n }\n .drop .icon { font-size: calc(var(--fx-font-size) + 12px); line-height: 1; }\n .drop .hint { font-size: calc(var(--fx-font-size) - 2px); }\n\n /* ---- ícone comum ---- */\n .icon { line-height: 1; }\n\n /* ---- arquivo(s) selecionado(s) ---- */\n .files { display: flex; flex-direction: column; gap: var(--fx-space-xs); margin-top: var(--fx-space-sm); }\n .file {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm);\n padding: var(--fx-space-xs) var(--fx-space-sm);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-sm);\n font-size: calc(var(--fx-font-size) - 2px);\n color: var(--fx-text-default);\n }\n .file .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .file .size { color: var(--fx-text-muted); white-space: nowrap; }\n .file .remove {\n border: none;\n background: transparent;\n color: var(--fx-text-muted);\n cursor: pointer;\n font-size: calc(var(--fx-font-size) + 2px);\n line-height: 1;\n padding: 0 var(--fx-space-xs);\n border-radius: var(--fx-radius-full);\n }\n .file .remove:hover { color: var(--fx-color-danger); }\n\n /* ---- progresso ---- */\n .progress-row { display: flex; align-items: center; gap: var(--fx-space-sm); margin-top: var(--fx-space-sm); }\n .track {\n flex: 1;\n height: 6px;\n background: var(--fx-surface-surface-hover);\n border-radius: var(--fx-radius-full);\n overflow: hidden;\n }\n .bar {\n height: 100%;\n width: 0%;\n background: var(--fx-color-primary);\n border-radius: var(--fx-radius-full);\n transition: width var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n :host([progress='100']) .bar { background: var(--fx-color-success); }\n .pct {\n font-size: calc(var(--fx-font-size) - 2px);\n font-weight: 600;\n color: var(--fx-text-default);\n min-width: 34px;\n text-align: right;\n }\n /* Full width: o host estica até o pai e o botão/dropzone acompanha. */\n :host([full]) { display: block; width: 100%; }\n :host([full]) .btn { width: 100%; }\n :host([full]) .drop { width: 100%; }\n /* Base dos glifos Fenix Icons (o @font-face vem de @wrrdev/fenix-ui/icons). */\n ${FENIX_ICON_BASE_CSS}\n `;\n\n static override get observedAttributes(): string[] {\n return ['mode', 'size', 'severity', 'label', 'icon', 'accept', 'multiple', 'disabled', 'show-progress', 'progress', 'value', 'full'];\n }\n\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) { this.setAttribute('size', value); }\n\n /** Nomes dos arquivos selecionados (espelho em `value`). */\n get value(): string { return this.getAttr('value'); }\n set value(v: string) { this.setAttribute('value', v); }\n\n get progress(): number { return Math.min(100, Math.max(0, Number(this.getAttr('progress', '0')) || 0)); }\n set progress(v: number) { this.setAttribute('progress', String(v)); }\n\n /** Arquivos selecionados (não serializável em atributo). */\n get files(): File[] { return this._files; }\n set files(files: File[]) {\n this._files = Array.from(files);\n this.value = this._files.map((f) => f.name).join(', ');\n this._syncFilesArea();\n }\n\n protected override render(): void {\n const mode = this.getAttr('mode', 'basic');\n const advanced = mode === 'advanced';\n const label = this.getAttr('label', 'Escolher arquivo');\n const icon = this.getAttr('icon');\n const accept = this.getAttr('accept');\n const multiple = this.hasAttr('multiple');\n const disabled = this.hasAttr('disabled');\n const showProgress = this.hasAttr('show-progress');\n const pct = this.progress;\n\n const fileInput = `<input type=\"file\" class=\"picker\" ${accept ? `accept=\"${esc(accept)}\"` : ''} ${multiple ? 'multiple' : ''} ${disabled ? 'disabled' : ''} />`;\n\n this.setTemplate(`\n ${advanced\n ? `<div class=\"drop\" part=\"dropzone\" role=\"button\" tabindex=\"0\" aria-label=\"${esc(label)}\">\n ${icon ? `<span class=\"icon\" part=\"icon\" aria-hidden=\"true\">${fenixIconHtml(icon)}</span>` : ''}\n <span>${esc(label)}</span>\n <span class=\"hint\">ou arraste e solte aqui</span>\n </div>`\n : `<button type=\"button\" class=\"btn\" part=\"button\">\n ${icon ? `<span class=\"icon\" part=\"icon\" aria-hidden=\"true\">${fenixIconHtml(icon)}</span>` : ''}\n <span>${esc(label)}</span>\n </button>`}\n ${fileInput}\n <div class=\"files\" part=\"files\"></div>\n ${showProgress ? `\n <div class=\"progress-row\" part=\"progress\">\n <div class=\"track\" role=\"progressbar\" aria-valuenow=\"${pct}\" aria-valuemin=\"0\" aria-valuemax=\"100\">\n <div class=\"bar\" style=\"width: ${pct}%\"></div>\n </div>\n <span class=\"pct\">${pct}%</span>\n </div>` : ''}\n `);\n\n this._bindPicker();\n this._syncFilesArea();\n\n if (!this._done && showProgress && pct >= 100 && this._files.length) {\n this._done = true;\n this.dispatchEvent(new CustomEvent('complete', { bubbles: true, composed: true }));\n }\n if (pct < 100) this._done = false;\n }\n\n private _files: File[] = [];\n private _done = false;\n\n private _picker(): HTMLInputElement | null {\n return this.root.querySelector<HTMLInputElement>('.picker');\n }\n\n private _bindPicker(): void {\n const picker = this._picker();\n if (!picker) return;\n const trigger = this.root.querySelector('.btn') ?? this.root.querySelector('.drop');\n trigger?.addEventListener('click', () => picker.click());\n trigger?.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter' || (e as KeyboardEvent).key === ' ') {\n e.preventDefault();\n picker.click();\n }\n });\n picker.addEventListener('change', () => this._acceptFiles(picker.files ?? []));\n\n // drag & drop (advanced)\n const drop = this.root.querySelector<HTMLElement>('.drop');\n if (!drop) return;\n drop.addEventListener('dragover', (e) => { e.preventDefault(); drop.classList.add('over'); });\n drop.addEventListener('dragleave', () => drop.classList.remove('over'));\n drop.addEventListener('drop', (e) => {\n e.preventDefault();\n drop.classList.remove('over');\n if (e.dataTransfer?.files.length) this._acceptFiles(e.dataTransfer.files);\n });\n }\n\n private _acceptFiles(list: FileList | File[]): void {\n const picked = this.hasAttr('multiple') ? Array.from(list) : [list[0]].filter(Boolean);\n this.files = picked;\n const picker = this._picker();\n if (picker) picker.value = '';\n this.dispatchEvent(\n new CustomEvent('select', { bubbles: true, composed: true, detail: { files: picked } }),\n );\n }\n\n private _fmtSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n }\n\n /** Renderiza a lista de arquivos sem re-renderizar o template (mantém estado). */\n private _syncFilesArea(): void {\n const area = this.root?.querySelector?.('.files') as HTMLElement | null;\n if (!area) return;\n area.innerHTML = this._files\n .map(\n (f, i) => `\n <div class=\"file\" part=\"file\">\n <span class=\"name\">${esc(f.name)}</span>\n <span class=\"size\">${this._fmtSize(f.size)}</span>\n <button type=\"button\" class=\"remove\" data-i=\"${i}\" part=\"remove\" aria-label=\"Remover ${esc(f.name)}\">×</button>\n </div>`,\n )\n .join('');\n area.querySelectorAll<HTMLButtonElement>('.remove').forEach((btn) =>\n btn.addEventListener('click', () => {\n const removed = this._files.splice(Number(btn.dataset.i), 1)[0];\n this.value = this._files.map((f) => f.name).join(', ');\n this.progress = 0;\n this._syncFilesArea();\n this.dispatchEvent(\n new CustomEvent('remove', { bubbles: true, composed: true, detail: { file: removed } }),\n );\n }),\n );\n }\n}\n\nexport function defineFxFileUpload(): typeof FxFileUpload {\n return defineElement('fx-fileupload', FxFileUpload);\n}\n\n\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { FxElement } from '../../core/base';
2
+ /**
3
+ * <fx-icon> — Glifo da Fenix Icons com AUTOCOMPLETE no editor.
4
+ *
5
+ * Por que existe: a forma antiga (`<i class="fx-icon fx-icon-home">`) é CSS
6
+ * puro — o TypeScript não valida nem sugere nada enquanto você digita, e o
7
+ * auto-import só injeta o import. Com o elemento, o atributo `name` é tipado
8
+ * como `FenixIconName`, então Volar/vue-tsc, React e TSX listam os +4.000
9
+ * glifos válidos (e o hover mostra a assinatura do atributo).
10
+ *
11
+ * Atributos:
12
+ * - name → nome do glifo (ex.: `home`); texto livre/emoji também funciona
13
+ * - size → sm | md | lg | xl (default: 1em, herda o texto ao redor)
14
+ * - label → nome acessível; sem label o ícone é aria-hidden (decorativo)
15
+ * - fill → variante preenchida
16
+ * - bold → traço mais pesado
17
+ *
18
+ * O glifo sai por LIGADURA (o nome vira o conteúdo de texto com a
19
+ * font-family de ícones) — por isso funciona dentro do Shadow DOM, onde as
20
+ * classes `fx-icon-<nome>` do documento não atravessam a fronteira.
21
+ *
22
+ * Tamanho via CSS: --fx-icon-size (-sm/-md/-lg/-xl).
23
+ */
24
+ export declare class FxIcon extends FxElement {
25
+ static styles: string;
26
+ static get observedAttributes(): string[];
27
+ /** Nome do glifo (ou texto livre/emoji). */
28
+ get name(): string;
29
+ set name(value: string);
30
+ /** Tamanho: '' (herda 1em) | 'sm' | 'md' | 'lg' | 'xl'. */
31
+ get size(): string;
32
+ set size(value: string);
33
+ /** Nome acessível; vazio = ícone decorativo (aria-hidden). */
34
+ get label(): string;
35
+ set label(value: string);
36
+ protected connectedCallback(): void;
37
+ protected render(): void;
38
+ }
39
+ export declare function defineFxIcon(): typeof FxIcon;
40
+ //# sourceMappingURL=icon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../../../src/components/icon/icon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAO5C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,MAAO,SAAQ,SAAS;IACnC,OAAgB,MAAM,SAoBpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,4CAA4C;IAC5C,IAAI,IAAI,IAAI,MAAM,CAEjB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAErB;IAED,2DAA2D;IAC3D,IAAI,IAAI,IAAI,MAAM,CAEjB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAGrB;IAED,8DAA8D;IAC9D,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAGtB;cAEkB,iBAAiB,IAAI,IAAI;cAMzB,MAAM,IAAI,IAAI;CAclC;AAED,wBAAgB,YAAY,IAAI,OAAO,MAAM,CAE5C"}
@@ -0,0 +1,79 @@
1
+ import { FxElement } from "../../core/base.js";
2
+ import { css } from "../../core/css.js";
3
+ import { defineElement } from "../../core/define.js";
4
+ import { esc } from "../../core/sanitize.js";
5
+ import { FENIX_ICON_BASE_CSS, isFenixIconName } from "../../icons/base-css.js";
6
+ import { loadFenixIconsFont } from "../../icons/font.js";
7
+ const _FxIcon = class _FxIcon extends FxElement {
8
+ static get observedAttributes() {
9
+ return ["name", "size", "label", "fill", "bold"];
10
+ }
11
+ /** Nome do glifo (ou texto livre/emoji). */
12
+ get name() {
13
+ return this.getAttr("name");
14
+ }
15
+ set name(value) {
16
+ this.setAttribute("name", value);
17
+ }
18
+ /** Tamanho: '' (herda 1em) | 'sm' | 'md' | 'lg' | 'xl'. */
19
+ get size() {
20
+ return this.getAttr("size");
21
+ }
22
+ set size(value) {
23
+ if (value) this.setAttribute("size", value);
24
+ else this.removeAttribute("size");
25
+ }
26
+ /** Nome acessível; vazio = ícone decorativo (aria-hidden). */
27
+ get label() {
28
+ return this.getAttr("label");
29
+ }
30
+ set label(value) {
31
+ if (value) this.setAttribute("label", value);
32
+ else this.removeAttribute("label");
33
+ }
34
+ connectedCallback() {
35
+ loadFenixIconsFont();
36
+ super.connectedCallback();
37
+ }
38
+ render() {
39
+ const name = this.getAttr("name").trim();
40
+ const label = this.getAttr("label").trim();
41
+ const a11y = label ? `role="img" aria-label="${esc(label)}"` : 'aria-hidden="true"';
42
+ if (!name) {
43
+ this.setTemplate(`<span class="icon" part="icon" ${a11y}></span>`);
44
+ return;
45
+ }
46
+ const inner = isFenixIconName(name) ? `<i class="icon fx-icon" part="icon" ${a11y}>${esc(name)}</i>` : `<span class="icon" part="icon" ${a11y}>${esc(name)}</span>`;
47
+ this.setTemplate(inner);
48
+ }
49
+ };
50
+ _FxIcon.styles = css`
51
+ :host {
52
+ display: inline-flex;
53
+ align-items: center;
54
+ justify-content: center;
55
+ vertical-align: middle;
56
+ line-height: 1;
57
+ color: currentColor;
58
+ font-size: var(--fx-icon-size, 1em);
59
+ }
60
+ :host([size='sm']) { font-size: var(--fx-icon-size-sm, 16px); }
61
+ :host([size='md']) { font-size: var(--fx-icon-size-md, 20px); }
62
+ :host([size='lg']) { font-size: var(--fx-icon-size-lg, 24px); }
63
+ :host([size='xl']) { font-size: var(--fx-icon-size-xl, 32px); }
64
+ :host([hidden]) { display: none; }
65
+ .icon { display: inline-block; }
66
+ /* Variantes da fonte (FILL/wght): vencem a classe base .fx-icon. */
67
+ :host([fill]) .icon { font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24; }
68
+ :host([bold]) .icon { font-variation-settings: 'FILL' 0, 'wght' 600, 'GRAD' 0, 'opsz' 24; }
69
+ ${FENIX_ICON_BASE_CSS}
70
+ `;
71
+ let FxIcon = _FxIcon;
72
+ function defineFxIcon() {
73
+ return defineElement("fx-icon", FxIcon);
74
+ }
75
+ export {
76
+ FxIcon,
77
+ defineFxIcon
78
+ };
79
+ //# sourceMappingURL=icon.js.map
@@ -0,0 +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;"}
@@ -0,0 +1,8 @@
1
+ import { FxIcon } from './icon';
2
+ export { FxIcon };
3
+ declare global {
4
+ interface HTMLElementTagNameMap {
5
+ 'fx-icon': FxIcon;
6
+ }
7
+ }
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/icon/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,CAAC;AAIlB,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB;CACF"}
@@ -0,0 +1,7 @@
1
+ import { defineFxIcon } from "./icon.js";
2
+ import { FxIcon } from "./icon.js";
3
+ defineFxIcon();
4
+ export {
5
+ FxIcon
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../src/components/icon/index.ts"],"sourcesContent":["import { FxIcon, defineFxIcon } from './icon';\n\nexport { FxIcon };\n\ndefineFxIcon();\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'fx-icon': FxIcon;\n }\n}\n"],"names":[],"mappings":";;AAIA,aAAA;"}
@@ -1 +1 @@
1
- {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../src/components/input/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C;;;;;;;;;;;;GAYG;AACH,qBAAa,OAAQ,SAAQ,SAAS;IACpC,OAAgB,MAAM,SAiIpB;IAMF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAMjD;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,EAEtB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;cAEkB,MAAM,IAAI,IAAI;CA8DlC;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,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C;;;;;;;;;;;;GAYG;AACH,qBAAa,OAAQ,SAAQ,SAAS;IACpC,OAAgB,MAAM,SAuIpB;IAMF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAMjD;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,EAEtB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;cAEkB,MAAM,IAAI,IAAI;CA8DlC;AAED,wBAAgB,aAAa,IAAI,OAAO,OAAO,CAE9C"}
@@ -121,13 +121,17 @@ _FxInput.styles = css`
121
121
  .field {
122
122
  font-family: inherit;
123
123
  font-size: inherit;
124
+ /* Altura determinística: com line-height fixo, o padding vertical cabe no
125
+ token --fx-size-* e a caixa fica EXATAMENTE no tamanho padrão
126
+ (sm 32 / md 40 / lg 48), igual para todos os campos. */
127
+ line-height: var(--fx-font-line-height);
124
128
  min-height: var(--fx-size-md);
125
129
  font-weight: var(--fx-font-weight);
126
130
  color: var(--fx-text-default);
127
131
  background-color: var(--fx-surface-background);
128
132
  border: 1px solid var(--fx-border-default);
129
133
  border-radius: var(--fx-radius-md);
130
- padding: var(--fx-space-md) var(--fx-space-lg);
134
+ padding: var(--fx-space-sm) var(--fx-space-lg);
131
135
  /* Acompanha a largura definida no :host. */
132
136
  width: 100%;
133
137
  box-sizing: border-box;
@@ -148,25 +152,27 @@ _FxInput.styles = css`
148
152
  cursor: not-allowed;
149
153
  background-color: var(--fx-surface-surface-hover);
150
154
  }
151
- /* Validação: sobrescrevem a borda/foco via token do preset. */
155
+ /* Validação: borda sempre; o brilho (anel) segue o token do preset
156
+ --fx-effect-error-ring, que acompanha effect.focus-ring — anel
157
+ desligado ⇒ erro só com a borda vermelha, ligado ⇒ soma o brilho. */
152
158
  :host([error]) .field,
153
159
  :host([invalid]) .field,
154
160
  :host([error]) .field:focus-visible,
155
161
  :host([invalid]) .field:focus-visible {
156
162
  border-color: var(--fx-color-danger, #dc2626);
157
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent);
163
+ box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));
158
164
  }
159
165
  :host([success]) .field,
160
166
  :host([valid]) .field,
161
167
  :host([success]) .field:focus-visible,
162
168
  :host([valid]) .field:focus-visible {
163
169
  border-color: var(--fx-color-success, #16a34a);
164
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent);
170
+ box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));
165
171
  }
166
172
  :host([size='sm']) { width: var(--fx-input-width-sm, 220px); }
167
- :host([size='sm']) .field { padding: var(--fx-space-sm) var(--fx-space-md); font-size: var(--fx-font-size); min-height: var(--fx-size-sm); }
173
+ :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); }
168
174
  :host([size='lg']) { width: var(--fx-input-width-lg, 300px); }
169
- :host([size='lg']) .field { padding: var(--fx-space-lg) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); min-height: var(--fx-size-lg); }
175
+ :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); }
170
176
  /* Full width: o host estica até o pai e o campo interno acompanha
171
177
  (usar com um container de largura controlada, ex. w-full no Vue). */
172
178
  :host([full]) { display: block; width: 100%; }
@@ -1 +1 @@
1
- {"version":3,"file":"input.js","sources":["../../../src/components/input/input.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, fenixIconHtml } from '../../icons/base-css';\n\n/**\n * <fx-input> — Campo de texto estilizado com os tokens do tema.\n *\n * Atributos: type (text|number|email|password|search|tel|url), value, size,\n * placeholder, disabled, readonly, min, max, step, clearable,\n * full (largura 100% acompanhando o elemento pai), icon (nome do glifo Fenix Icons\n * 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` e `change` (composed, detail: { value }).\n */\nexport class FxInput extends FxElement {\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 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-md) 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: sobrescrevem a borda/foco via token do preset. */\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: 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: 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-sm) 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-lg) 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 /** 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 }\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.getAttr('type', 'text');\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 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 // 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}\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 { FxElement } from '../../core/base';\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';\n\n/**\n * <fx-input> — Campo de texto estilizado com os tokens do tema.\n *\n * Atributos: type (text|number|email|password|search|tel|url), value, size,\n * placeholder, disabled, readonly, min, max, step, clearable,\n * full (largura 100% acompanhando o elemento pai), icon (nome do glifo Fenix Icons\n * 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` e `change` (composed, detail: { value }).\n */\nexport class FxInput extends FxElement {\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 /** 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 }\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.getAttr('type', 'text');\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 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 // 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}\n\nexport function defineFxInput(): typeof FxInput {\n return defineElement('fx-input', FxInput);\n}\n"],"names":[],"mappings":";;;;;AAmBO,MAAM,WAAN,MAAM,iBAAgB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EA8IrC,WAAoB,qBAA+B;AACjD,WAAO;AAAA,MACL;AAAA,MAAQ;AAAA,MAAQ;AAAA,MAChB;AAAA,MAAY;AAAA,MAAY;AAAA,MAAO;AAAA,MAAO;AAAA,MACtC;AAAA,MAAQ;AAAA,MAAY;AAAA,MAAS;AAAA,MAAW;AAAA,MAAW;AAAA,IAAA;AAAA,EAEvD;AAAA;AAAA,EAGA,IAAI,OAAe;AACjB,UAAM,IAAI,KAAK,QAAQ,QAAQ,IAAI;AACnC,WAAO,MAAM,QAAQ,MAAM,OAAO,IAAI;AAAA,EACxC;AAAA,EACA,IAAI,KAAK,OAAe;AACtB,SAAK,aAAa,QAAQ,KAAK;AAAA,EACjC;AAAA,EAEA,IAAI,QAAgB;AAClB,WAAO,KAAK,QAAQ,OAAO;AAAA,EAC7B;AAAA,EACA,IAAI,MAAM,OAAe;AACvB,SAAK,aAAa,SAAS,KAAK;AAAA,EAClC;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO,KAAK,QAAQ,UAAU;AAAA,EAChC;AAAA,EACA,IAAI,SAAS,OAAgB;AAC3B,SAAK,WAAW,YAAY,QAAQ,KAAK,CAAC;AAAA,EAC5C;AAAA,EAEmB,SAAe;AAChC,UAAM,OAAO,KAAK,QAAQ,QAAQ,MAAM;AACxC,UAAM,cAAc,KAAK,QAAQ,aAAa;AAC9C,UAAM,WAAW,KAAK,QAAQ,UAAU;AACxC,UAAM,WAAW,KAAK,QAAQ,UAAU;AACxC,UAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,UAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,UAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,UAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,UAAM,UAAU,KAAK,QAAQ,YAAY,MAAM,MAAM,UAAU,UAAU;AAEzE,UAAM,cAAc,KAAK,cAA2B,eAAe;AACnE,UAAM,cAAc,cAChB,0CACC,OAAO,cAAc,IAAI,IAAI;AAClC,UAAM,aAAa,QAAQ,WAAW;AAEtC,SAAK,YAAY;AAAA,QACb,KAAK,QAAQ,WAAW,IAAI,mCAAmC,EAAE;AAAA,QACjE,aAAa,+BAA+B,OAAO,OAAO,EAAE;AAAA,QAC5D,cAAc,YAAY,SAAS,cAAc,EAAE;AAAA,gDACX,IAAI,IAAI,CAAC;AAAA,UAC/C,cAAc,gBAAgB,IAAI,WAAW,CAAC,MAAM,EAAE;AAAA,UACtD,MAAM,QAAQ,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,MAAM,QAAQ,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,OAAO,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE;AAAA;AAAA,QAEvG,cAAc,YAAY,UAAU,cAAc,EAAE;AAAA,QACpD,aAAa,WAAW,EAAE;AAAA,QAC1B,KAAK,QAAQ,WAAW,IAAI,wGAAwG,EAAE;AAAA,KACzI;AAED,UAAM,QAAQ,KAAK,KAAK,cAAgC,QAAQ;AAChE,QAAI,CAAC,MAAO;AACZ,UAAM,QAAQ,KAAK,QAAQ,OAAO;AAClC,QAAI,SAAU,OAAM,aAAa,YAAY,EAAE;AAC/C,QAAI,SAAU,OAAM,aAAa,YAAY,EAAE;AAE/C,UAAM,OAAO,CAAC,UAAwB;AACpC,WAAK,QAAQ,MAAM;AACnB,WAAK;AAAA,QACH,IAAI,YAAY,OAAO,EAAE,SAAS,MAAM,UAAU,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAA,GAAS;AAAA,MAAA;AAAA,IAE5F;AAGA,UAAM,iBAAiB,SAAS,CAAC,MAAM;AAAE,QAAE,gBAAA;AAAmB,WAAK,OAAO;AAAA,IAAG,CAAC;AAC9E,UAAM,iBAAiB,UAAU,CAAC,MAAM;AAAE,QAAE,gBAAA;AAAmB,WAAK,QAAQ;AAAA,IAAG,CAAC;AAGhF,UAAM,WAAW,KAAK,KAAK,cAAiC,QAAQ;AACpE,UAAM,YAAY,MAAY;AAC5B,gBAAU,gBAAgB,UAAU,MAAM,UAAU,EAAE;AAAA,IACxD;AACA,cAAA;AACA,cAAU,iBAAiB,SAAS,MAAM;AACxC,YAAM,QAAQ;AACd,gBAAA;AACA,WAAK,OAAO;AACZ,WAAK,QAAQ;AACb,YAAM,MAAA;AAAA,IACR,CAAC;AACD,UAAM,iBAAiB,SAAS,SAAS;AAAA,EAC3C;AACF;AA1OE,SAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAsIrB,mBAAmB;AAAA;AAvIlB,IAAM,UAAN;AA6OA,SAAS,gBAAgC;AAC9C,SAAO,cAAc,YAAY,OAAO;AAC1C;"}
@@ -2,7 +2,7 @@ import { FxElement } from '../../core/base';
2
2
  /**
3
3
  * <fx-knob> - Controle giratorio circular para ajuste de valor.
4
4
  *
5
- * Similar ao Knob do PrimeVue, permite ajustar um valor arrastando o mouse
5
+ * permite ajustar um valor arrastando o mouse
6
6
  * ou usando as setas do teclado. Exibe um arco de progresso circular com
7
7
  * o valor central configuravel via valueTemplate.
8
8
  *
@@ -1 +1 @@
1
- {"version":3,"file":"knob.d.ts","sourceRoot":"","sources":["../../../src/components/knob/knob.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;;;;;;GAUG;AACH,qBAAa,MAAO,SAAQ,SAAS;IACnC,OAAgB,MAAM,SAkEpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAcjD;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,EAclB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IACD,IAAI,GAAG,CAAC,CAAC,EAAE,MAAM,EAEhB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IACD,IAAI,GAAG,CAAC,CAAC,EAAE,MAAM,EAEhB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IACD,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,EAEjB;IAED,IAAI,IAAI,IAAI,MAAM,CAGjB;IACD,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,EAEjB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IACD,IAAI,WAAW,CAAC,CAAC,EAAE,MAAM,EAExB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IACD,IAAI,UAAU,CAAC,CAAC,EAAE,MAAM,EAEvB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IACD,IAAI,UAAU,CAAC,CAAC,EAAE,MAAM,EAEvB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,CAAC,EAAE,OAAO,EAEtB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,CAAC,EAAE,OAAO,EAEtB;IAED,IAAI,aAAa,IAAI,MAAM,CAE1B;IACD,IAAI,aAAa,CAAC,CAAC,EAAE,MAAM,EAE1B;IAED,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,WAAW,CAAK;cAEL,MAAM,IAAI,IAAI;IAwCjC,OAAO,CAAC,UAAU;IAOlB,gEAAgE;IAChE,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,eAAe;IAsEvB,OAAO,CAAC,YAAY,CAKlB;IAEF,OAAO,CAAC,UAAU,CAIhB;cAEiB,oBAAoB,IAAI,IAAI;CAKhD;AAED,wBAAgB,YAAY,IAAI,OAAO,MAAM,CAE5C"}
1
+ {"version":3,"file":"knob.d.ts","sourceRoot":"","sources":["../../../src/components/knob/knob.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;;;;;;GAUG;AACH,qBAAa,MAAO,SAAQ,SAAS;IACnC,OAAgB,MAAM,SAoEpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAcjD;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,EAclB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IACD,IAAI,GAAG,CAAC,CAAC,EAAE,MAAM,EAEhB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IACD,IAAI,GAAG,CAAC,CAAC,EAAE,MAAM,EAEhB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IACD,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,EAEjB;IAED,IAAI,IAAI,IAAI,MAAM,CAGjB;IACD,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,EAEjB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IACD,IAAI,WAAW,CAAC,CAAC,EAAE,MAAM,EAExB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IACD,IAAI,UAAU,CAAC,CAAC,EAAE,MAAM,EAEvB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IACD,IAAI,UAAU,CAAC,CAAC,EAAE,MAAM,EAEvB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,CAAC,EAAE,OAAO,EAEtB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,CAAC,EAAE,OAAO,EAEtB;IAED,IAAI,aAAa,IAAI,MAAM,CAE1B;IACD,IAAI,aAAa,CAAC,CAAC,EAAE,MAAM,EAE1B;IAED,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,WAAW,CAAK;cAEL,MAAM,IAAI,IAAI;IAwCjC,OAAO,CAAC,UAAU;IAOlB,gEAAgE;IAChE,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,eAAe;IAsEvB,OAAO,CAAC,YAAY,CAKlB;IAEF,OAAO,CAAC,UAAU,CAIhB;cAEiB,oBAAoB,IAAI,IAAI;CAKhD;AAED,wBAAgB,YAAY,IAAI,OAAO,MAAM,CAE5C"}
@@ -321,7 +321,9 @@ _FxKnob.styles = css`
321
321
  outline: none;
322
322
  }
323
323
  .knob:focus-visible svg {
324
- filter: drop-shadow(var(--fx-effect-focus-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-primary) 22%, transparent)));
324
+ /* Mesmo fallback none dos demais componentes: sem motor de tema (ou com
325
+ effect.focus-ring desligado) não há anel de foco. */
326
+ filter: drop-shadow(var(--fx-effect-focus-ring, none));
325
327
  }
326
328
  `;
327
329
  let FxKnob = _FxKnob;
@@ -1 +1 @@
1
- {"version":3,"file":"knob.js","sources":["../../../src/components/knob/knob.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\n\n/**\n * <fx-knob> - Controle giratorio circular para ajuste de valor.\n *\n * Similar ao Knob do PrimeVue, permite ajustar um valor arrastando o mouse\n * ou usando as setas do teclado. Exibe um arco de progresso circular com\n * o valor central configuravel via valueTemplate.\n *\n * Atributos: value, min, max, step, size, strokeWidth, valueColor, rangeColor,\n * readonly, disabled, valueTemplate.\n * Evento: `change` (composed, detail: { value }).\n */\nexport class FxKnob extends FxElement {\n static override styles = css`\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n --_size: 100px;\n --_stroke-width: 8px;\n --_value-color: var(--fx-color-primary);\n --_range-color: var(--fx-border-default);\n }\n :host([size='sm']) { --_size: 60px; }\n :host([size='lg']) { --_size: 140px; }\n .knob {\n position: relative;\n width: var(--_size);\n height: var(--_size);\n cursor: pointer;\n user-select: none;\n touch-action: none;\n }\n :host([readonly]) .knob,\n :host([disabled]) .knob {\n cursor: default;\n pointer-events: none;\n }\n :host([disabled]) .knob {\n opacity: 0.55;\n }\n svg {\n width: 100%;\n height: 100%;\n transform: rotate(-90deg);\n }\n .track {\n fill: none;\n stroke: var(--_range-color);\n stroke-width: var(--_stroke-width);\n }\n .value {\n fill: none;\n stroke: var(--_value-color);\n stroke-width: var(--_stroke-width);\n stroke-linecap: round;\n transition: stroke-dashoffset var(--fx-motion-duration-fast) var(--fx-motion-easing);\n }\n .label {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n color: var(--fx-text-default);\n pointer-events: none;\n }\n :host([size='sm']) .label { font-size: 11px; }\n :host([size='md']) .label { font-size: 14px; }\n :host([size='lg']) .label { font-size: 18px; }\n .knob:focus-visible {\n outline: none;\n }\n .knob:focus-visible svg {\n filter: drop-shadow(var(--fx-effect-focus-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-primary) 22%, transparent)));\n }\n `;\n\n static override get observedAttributes(): string[] {\n return [\n 'value',\n 'min',\n 'max',\n 'step',\n 'size',\n 'stroke-width',\n 'value-color',\n 'range-color',\n 'readonly',\n 'disabled',\n 'value-template',\n ];\n }\n\n get value(): number {\n return this.clampValue(Number(this.getAttr('value', '0')) || 0);\n }\n set value(v: number) {\n if (this.readonly || this.disabled) return;\n const clamped = this.clampValue(v);\n const current = this.clampValue(Number(this.getAttr('value', '0')) || 0);\n if (clamped !== current) {\n this.setAttribute('value', String(clamped));\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { value: clamped },\n }),\n );\n }\n }\n\n get min(): number {\n return Number(this.getAttr('min', '0')) || 0;\n }\n set min(v: number) {\n this.setAttribute('min', String(v));\n }\n\n get max(): number {\n return Number(this.getAttr('max', '100')) || 100;\n }\n set max(v: number) {\n this.setAttribute('max', String(v));\n }\n\n get step(): number {\n return Number(this.getAttr('step', '1')) || 1;\n }\n set step(v: number) {\n this.setAttribute('step', String(v));\n }\n\n get size(): string {\n const s = this.getAttr('size', 'md');\n return s === 'sm' || s === 'lg' ? s : 'md';\n }\n set size(v: string) {\n this.setAttribute('size', v);\n }\n\n get strokeWidth(): number {\n return Number(this.getAttr('stroke-width', '8')) || 8;\n }\n set strokeWidth(v: number) {\n this.setAttribute('stroke-width', String(v));\n }\n\n get valueColor(): string {\n return this.getAttr('value-color', '');\n }\n set valueColor(v: string) {\n this.setAttribute('value-color', v);\n }\n\n get rangeColor(): string {\n return this.getAttr('range-color', '');\n }\n set rangeColor(v: string) {\n this.setAttribute('range-color', v);\n }\n\n get readonly(): boolean {\n return this.hasAttr('readonly');\n }\n set readonly(v: boolean) {\n this.toggleAttr('readonly', Boolean(v));\n }\n\n get disabled(): boolean {\n return this.hasAttr('disabled');\n }\n set disabled(v: boolean) {\n this.toggleAttr('disabled', Boolean(v));\n }\n\n get valueTemplate(): string {\n return this.getAttr('value-template', '{value}');\n }\n set valueTemplate(v: string) {\n this.setAttribute('value-template', v);\n }\n\n private _isDragging = false;\n private _startY = 0;\n private _startValue = 0;\n\n protected override render(): void {\n const min = this.min;\n const max = this.max;\n const value = this.clampValue(this.value);\n const range = max - min;\n const pct = range > 0 ? (value - min) / range : 0;\n\n const sizeNum = this.getSizeNum();\n const strokeW = this.strokeWidth;\n const radius = (sizeNum - strokeW) / 2;\n const circumference = 2 * Math.PI * radius;\n const offset = circumference * (1 - pct);\n\n const vc = this.valueColor ? this.safeColor(this.valueColor) : '';\n const rc = this.rangeColor ? this.safeColor(this.rangeColor) : '';\n const valueColorStyle = vc ? `--_value-color: ${vc};` : '';\n const rangeColorStyle = rc ? `--_range-color: ${rc};` : '';\n\n const displayValue = this.valueTemplate.replace('{value}', String(Math.round(value)));\n\n this.setTemplate(`\n <div class=\"knob\" part=\"knob\" tabindex=\"${this.disabled ? '-1' : '0'}\"\n role=\"slider\" aria-valuenow=\"${value}\" aria-valuemin=\"${min}\" aria-valuemax=\"${max}\"\n aria-readonly=\"${this.readonly}\" aria-disabled=\"${this.disabled}\"\n style=\"${valueColorStyle}${rangeColorStyle}\">\n <svg viewBox=\"0 0 ${sizeNum} ${sizeNum}\" part=\"svg\">\n <circle class=\"track\" part=\"track\"\n cx=\"${sizeNum / 2}\" cy=\"${sizeNum / 2}\" r=\"${radius}\" />\n <circle class=\"value\" part=\"value\"\n cx=\"${sizeNum / 2}\" cy=\"${sizeNum / 2}\" r=\"${radius}\"\n stroke-dasharray=\"${circumference}\"\n stroke-dashoffset=\"${offset}\" />\n </svg>\n <div class=\"label\" part=\"label\">${esc(displayValue)}</div>\n </div>\n `);\n\n this.attachListeners();\n }\n\n private getSizeNum(): number {\n const s = this.size;\n if (s === 'sm') return 60;\n if (s === 'lg') return 140;\n return 100;\n }\n\n /** Valida um valor de cor CSS, retornando-o seguro ou vazio. */\n private safeColor(value: string): string {\n const v = value.trim();\n if (/^#[0-9a-fA-F]{3,8}$/.test(v)) return v;\n if (/^(rgb|rgba|hsl|hsla)\\([\\d\\s.,%()]+\\)$/i.test(v)) return v;\n if (/^var\\(--[\\w-]+(,\\s*[^)]*)?\\)$/.test(v)) return v;\n if (/^[a-zA-Z]+$/.test(v)) return v;\n return '';\n }\n\n private clampValue(v: number): number {\n const min = this.min;\n const max = this.max;\n const step = this.step;\n let clamped = Math.min(max, Math.max(min, v));\n if (step > 0) {\n clamped = Math.round((clamped - min) / step) * step + min;\n clamped = Math.min(max, Math.max(min, clamped));\n }\n return clamped;\n }\n\n private emitChange(newValue: number): void {\n const clamped = this.clampValue(newValue);\n if (clamped !== this.value) {\n this.value = clamped;\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { value: clamped },\n }),\n );\n }\n }\n\n private attachListeners(): void {\n const knob = this.root.querySelector<HTMLElement>('.knob');\n if (!knob) return;\n\n knob.addEventListener('mousedown', (e: MouseEvent) => {\n if (this.readonly || this.disabled) return;\n e.preventDefault();\n this._isDragging = true;\n this._startY = e.clientY;\n this._startValue = this.value;\n knob.focus();\n document.addEventListener('mousemove', this._onMouseMove);\n document.addEventListener('mouseup', this._onMouseUp);\n });\n\n knob.addEventListener('touchstart', (e: TouchEvent) => {\n if (this.readonly || this.disabled) return;\n e.preventDefault();\n this._isDragging = true;\n this._startY = e.touches[0].clientY;\n this._startValue = this.value;\n knob.focus();\n }, { passive: false });\n\n knob.addEventListener('touchmove', (e: TouchEvent) => {\n if (!this._isDragging || this.readonly || this.disabled) return;\n e.preventDefault();\n const deltaY = this._startY - e.touches[0].clientY;\n const sensitivity = (this.max - this.min) / 100;\n this.emitChange(this._startValue + deltaY * sensitivity);\n }, { passive: false });\n\n knob.addEventListener('touchend', () => {\n this._isDragging = false;\n });\n\n knob.addEventListener('keydown', (e: KeyboardEvent) => {\n if (this.readonly || this.disabled) return;\n const step = this.step;\n switch (e.key) {\n case 'ArrowUp':\n case 'ArrowRight':\n e.preventDefault();\n this.emitChange(this.value + step);\n break;\n case 'ArrowDown':\n case 'ArrowLeft':\n e.preventDefault();\n this.emitChange(this.value - step);\n break;\n case 'Home':\n e.preventDefault();\n this.emitChange(this.min);\n break;\n case 'End':\n e.preventDefault();\n this.emitChange(this.max);\n break;\n case 'PageUp':\n e.preventDefault();\n this.emitChange(this.value + step * 10);\n break;\n case 'PageDown':\n e.preventDefault();\n this.emitChange(this.value - step * 10);\n break;\n }\n });\n }\n\n private _onMouseMove = (e: MouseEvent): void => {\n if (!this._isDragging) return;\n const deltaY = this._startY - e.clientY;\n const sensitivity = (this.max - this.min) / 100;\n this.emitChange(this._startValue + deltaY * sensitivity);\n };\n\n private _onMouseUp = (): void => {\n this._isDragging = false;\n document.removeEventListener('mousemove', this._onMouseMove);\n document.removeEventListener('mouseup', this._onMouseUp);\n };\n\n protected override disconnectedCallback(): void {\n document.removeEventListener('mousemove', this._onMouseMove);\n document.removeEventListener('mouseup', this._onMouseUp);\n super.disconnectedCallback();\n }\n}\n\nexport function defineFxKnob(): typeof FxKnob {\n return defineElement('fx-knob', FxKnob);\n}"],"names":[],"mappings":";;;;AAgBO,MAAM,UAAN,MAAM,gBAAe,UAAU;AAAA,EAA/B,cAAA;AAAA,UAAA,GAAA,SAAA;AA+KL,SAAQ,cAAc;AACtB,SAAQ,UAAU;AAClB,SAAQ,cAAc;AA2JtB,SAAQ,eAAe,CAAC,MAAwB;AAC9C,UAAI,CAAC,KAAK,YAAa;AACvB,YAAM,SAAS,KAAK,UAAU,EAAE;AAChC,YAAM,eAAe,KAAK,MAAM,KAAK,OAAO;AAC5C,WAAK,WAAW,KAAK,cAAc,SAAS,WAAW;AAAA,IACzD;AAEA,SAAQ,aAAa,MAAY;AAC/B,WAAK,cAAc;AACnB,eAAS,oBAAoB,aAAa,KAAK,YAAY;AAC3D,eAAS,oBAAoB,WAAW,KAAK,UAAU;AAAA,IACzD;AAAA,EAAA;AAAA,EAlRA,WAAoB,qBAA+B;AACjD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,IAAI,QAAgB;AAClB,WAAO,KAAK,WAAW,OAAO,KAAK,QAAQ,SAAS,GAAG,CAAC,KAAK,CAAC;AAAA,EAChE;AAAA,EACA,IAAI,MAAM,GAAW;AACnB,QAAI,KAAK,YAAY,KAAK,SAAU;AACpC,UAAM,UAAU,KAAK,WAAW,CAAC;AACjC,UAAM,UAAU,KAAK,WAAW,OAAO,KAAK,QAAQ,SAAS,GAAG,CAAC,KAAK,CAAC;AACvE,QAAI,YAAY,SAAS;AACvB,WAAK,aAAa,SAAS,OAAO,OAAO,CAAC;AAC1C,WAAK;AAAA,QACH,IAAI,YAAY,UAAU;AAAA,UACxB,SAAS;AAAA,UACT,UAAU;AAAA,UACV,QAAQ,EAAE,OAAO,QAAA;AAAA,QAAQ,CAC1B;AAAA,MAAA;AAAA,IAEL;AAAA,EACF;AAAA,EAEA,IAAI,MAAc;AAChB,WAAO,OAAO,KAAK,QAAQ,OAAO,GAAG,CAAC,KAAK;AAAA,EAC7C;AAAA,EACA,IAAI,IAAI,GAAW;AACjB,SAAK,aAAa,OAAO,OAAO,CAAC,CAAC;AAAA,EACpC;AAAA,EAEA,IAAI,MAAc;AAChB,WAAO,OAAO,KAAK,QAAQ,OAAO,KAAK,CAAC,KAAK;AAAA,EAC/C;AAAA,EACA,IAAI,IAAI,GAAW;AACjB,SAAK,aAAa,OAAO,OAAO,CAAC,CAAC;AAAA,EACpC;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,OAAO,KAAK,QAAQ,QAAQ,GAAG,CAAC,KAAK;AAAA,EAC9C;AAAA,EACA,IAAI,KAAK,GAAW;AAClB,SAAK,aAAa,QAAQ,OAAO,CAAC,CAAC;AAAA,EACrC;AAAA,EAEA,IAAI,OAAe;AACjB,UAAM,IAAI,KAAK,QAAQ,QAAQ,IAAI;AACnC,WAAO,MAAM,QAAQ,MAAM,OAAO,IAAI;AAAA,EACxC;AAAA,EACA,IAAI,KAAK,GAAW;AAClB,SAAK,aAAa,QAAQ,CAAC;AAAA,EAC7B;AAAA,EAEA,IAAI,cAAsB;AACxB,WAAO,OAAO,KAAK,QAAQ,gBAAgB,GAAG,CAAC,KAAK;AAAA,EACtD;AAAA,EACA,IAAI,YAAY,GAAW;AACzB,SAAK,aAAa,gBAAgB,OAAO,CAAC,CAAC;AAAA,EAC7C;AAAA,EAEA,IAAI,aAAqB;AACvB,WAAO,KAAK,QAAQ,eAAe,EAAE;AAAA,EACvC;AAAA,EACA,IAAI,WAAW,GAAW;AACxB,SAAK,aAAa,eAAe,CAAC;AAAA,EACpC;AAAA,EAEA,IAAI,aAAqB;AACvB,WAAO,KAAK,QAAQ,eAAe,EAAE;AAAA,EACvC;AAAA,EACA,IAAI,WAAW,GAAW;AACxB,SAAK,aAAa,eAAe,CAAC;AAAA,EACpC;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO,KAAK,QAAQ,UAAU;AAAA,EAChC;AAAA,EACA,IAAI,SAAS,GAAY;AACvB,SAAK,WAAW,YAAY,QAAQ,CAAC,CAAC;AAAA,EACxC;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO,KAAK,QAAQ,UAAU;AAAA,EAChC;AAAA,EACA,IAAI,SAAS,GAAY;AACvB,SAAK,WAAW,YAAY,QAAQ,CAAC,CAAC;AAAA,EACxC;AAAA,EAEA,IAAI,gBAAwB;AAC1B,WAAO,KAAK,QAAQ,kBAAkB,SAAS;AAAA,EACjD;AAAA,EACA,IAAI,cAAc,GAAW;AAC3B,SAAK,aAAa,kBAAkB,CAAC;AAAA,EACvC;AAAA,EAMmB,SAAe;AAChC,UAAM,MAAM,KAAK;AACjB,UAAM,MAAM,KAAK;AACjB,UAAM,QAAQ,KAAK,WAAW,KAAK,KAAK;AACxC,UAAM,QAAQ,MAAM;AACpB,UAAM,MAAM,QAAQ,KAAK,QAAQ,OAAO,QAAQ;AAEhD,UAAM,UAAU,KAAK,WAAA;AACrB,UAAM,UAAU,KAAK;AACrB,UAAM,UAAU,UAAU,WAAW;AACrC,UAAM,gBAAgB,IAAI,KAAK,KAAK;AACpC,UAAM,SAAS,iBAAiB,IAAI;AAEpC,UAAM,KAAK,KAAK,aAAa,KAAK,UAAU,KAAK,UAAU,IAAI;AAC/D,UAAM,KAAK,KAAK,aAAa,KAAK,UAAU,KAAK,UAAU,IAAI;AAC/D,UAAM,kBAAkB,KAAK,mBAAmB,EAAE,MAAM;AACxD,UAAM,kBAAkB,KAAK,mBAAmB,EAAE,MAAM;AAExD,UAAM,eAAe,KAAK,cAAc,QAAQ,WAAW,OAAO,KAAK,MAAM,KAAK,CAAC,CAAC;AAEpF,SAAK,YAAY;AAAA,gDAC2B,KAAK,WAAW,OAAO,GAAG;AAAA,uCACnC,KAAK,oBAAoB,GAAG,oBAAoB,GAAG;AAAA,yBACjE,KAAK,QAAQ,oBAAoB,KAAK,QAAQ;AAAA,iBACtD,eAAe,GAAG,eAAe;AAAA,4BACtB,OAAO,IAAI,OAAO;AAAA;AAAA,kBAE5B,UAAU,CAAC,SAAS,UAAU,CAAC,QAAQ,MAAM;AAAA;AAAA,kBAE7C,UAAU,CAAC,SAAS,UAAU,CAAC,QAAQ,MAAM;AAAA,gCAC/B,aAAa;AAAA,iCACZ,MAAM;AAAA;AAAA,0CAEG,IAAI,YAAY,CAAC;AAAA;AAAA,KAEtD;AAED,SAAK,gBAAA;AAAA,EACP;AAAA,EAEQ,aAAqB;AAC3B,UAAM,IAAI,KAAK;AACf,QAAI,MAAM,KAAM,QAAO;AACvB,QAAI,MAAM,KAAM,QAAO;AACvB,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,UAAU,OAAuB;AACvC,UAAM,IAAI,MAAM,KAAA;AAChB,QAAI,sBAAsB,KAAK,CAAC,EAAG,QAAO;AAC1C,QAAI,yCAAyC,KAAK,CAAC,EAAG,QAAO;AAC7D,QAAI,gCAAgC,KAAK,CAAC,EAAG,QAAO;AACpD,QAAI,cAAc,KAAK,CAAC,EAAG,QAAO;AAClC,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,GAAmB;AACpC,UAAM,MAAM,KAAK;AACjB,UAAM,MAAM,KAAK;AACjB,UAAM,OAAO,KAAK;AAClB,QAAI,UAAU,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,CAAC,CAAC;AAC5C,QAAI,OAAO,GAAG;AACZ,gBAAU,KAAK,OAAO,UAAU,OAAO,IAAI,IAAI,OAAO;AACtD,gBAAU,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,OAAO,CAAC;AAAA,IAChD;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,UAAwB;AACzC,UAAM,UAAU,KAAK,WAAW,QAAQ;AACxC,QAAI,YAAY,KAAK,OAAO;AAC1B,WAAK,QAAQ;AACb,WAAK;AAAA,QACH,IAAI,YAAY,UAAU;AAAA,UACxB,SAAS;AAAA,UACT,UAAU;AAAA,UACV,QAAQ,EAAE,OAAO,QAAA;AAAA,QAAQ,CAC1B;AAAA,MAAA;AAAA,IAEL;AAAA,EACF;AAAA,EAEQ,kBAAwB;AAC9B,UAAM,OAAO,KAAK,KAAK,cAA2B,OAAO;AACzD,QAAI,CAAC,KAAM;AAEX,SAAK,iBAAiB,aAAa,CAAC,MAAkB;AACpD,UAAI,KAAK,YAAY,KAAK,SAAU;AACpC,QAAE,eAAA;AACF,WAAK,cAAc;AACnB,WAAK,UAAU,EAAE;AACjB,WAAK,cAAc,KAAK;AACxB,WAAK,MAAA;AACL,eAAS,iBAAiB,aAAa,KAAK,YAAY;AACxD,eAAS,iBAAiB,WAAW,KAAK,UAAU;AAAA,IACtD,CAAC;AAED,SAAK,iBAAiB,cAAc,CAAC,MAAkB;AACrD,UAAI,KAAK,YAAY,KAAK,SAAU;AACpC,QAAE,eAAA;AACF,WAAK,cAAc;AACnB,WAAK,UAAU,EAAE,QAAQ,CAAC,EAAE;AAC5B,WAAK,cAAc,KAAK;AACxB,WAAK,MAAA;AAAA,IACP,GAAG,EAAE,SAAS,OAAO;AAErB,SAAK,iBAAiB,aAAa,CAAC,MAAkB;AACpD,UAAI,CAAC,KAAK,eAAe,KAAK,YAAY,KAAK,SAAU;AACzD,QAAE,eAAA;AACF,YAAM,SAAS,KAAK,UAAU,EAAE,QAAQ,CAAC,EAAE;AAC3C,YAAM,eAAe,KAAK,MAAM,KAAK,OAAO;AAC5C,WAAK,WAAW,KAAK,cAAc,SAAS,WAAW;AAAA,IACzD,GAAG,EAAE,SAAS,OAAO;AAErB,SAAK,iBAAiB,YAAY,MAAM;AACtC,WAAK,cAAc;AAAA,IACrB,CAAC;AAED,SAAK,iBAAiB,WAAW,CAAC,MAAqB;AACrD,UAAI,KAAK,YAAY,KAAK,SAAU;AACpC,YAAM,OAAO,KAAK;AAClB,cAAQ,EAAE,KAAA;AAAA,QACR,KAAK;AAAA,QACL,KAAK;AACH,YAAE,eAAA;AACF,eAAK,WAAW,KAAK,QAAQ,IAAI;AACjC;AAAA,QACF,KAAK;AAAA,QACL,KAAK;AACH,YAAE,eAAA;AACF,eAAK,WAAW,KAAK,QAAQ,IAAI;AACjC;AAAA,QACF,KAAK;AACH,YAAE,eAAA;AACF,eAAK,WAAW,KAAK,GAAG;AACxB;AAAA,QACF,KAAK;AACH,YAAE,eAAA;AACF,eAAK,WAAW,KAAK,GAAG;AACxB;AAAA,QACF,KAAK;AACH,YAAE,eAAA;AACF,eAAK,WAAW,KAAK,QAAQ,OAAO,EAAE;AACtC;AAAA,QACF,KAAK;AACH,YAAE,eAAA;AACF,eAAK,WAAW,KAAK,QAAQ,OAAO,EAAE;AACtC;AAAA,MAAA;AAAA,IAEN,CAAC;AAAA,EACH;AAAA,EAemB,uBAA6B;AAC9C,aAAS,oBAAoB,aAAa,KAAK,YAAY;AAC3D,aAAS,oBAAoB,WAAW,KAAK,UAAU;AACvD,UAAM,qBAAA;AAAA,EACR;AACF;AA7VE,QAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AADpB,IAAM,SAAN;AAgWA,SAAS,eAA8B;AAC5C,SAAO,cAAc,WAAW,MAAM;AACxC;"}
1
+ {"version":3,"file":"knob.js","sources":["../../../src/components/knob/knob.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\n\n/**\n * <fx-knob> - Controle giratorio circular para ajuste de valor.\n *\n * permite ajustar um valor arrastando o mouse\n * ou usando as setas do teclado. Exibe um arco de progresso circular com\n * o valor central configuravel via valueTemplate.\n *\n * Atributos: value, min, max, step, size, strokeWidth, valueColor, rangeColor,\n * readonly, disabled, valueTemplate.\n * Evento: `change` (composed, detail: { value }).\n */\nexport class FxKnob extends FxElement {\n static override styles = css`\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n --_size: 100px;\n --_stroke-width: 8px;\n --_value-color: var(--fx-color-primary);\n --_range-color: var(--fx-border-default);\n }\n :host([size='sm']) { --_size: 60px; }\n :host([size='lg']) { --_size: 140px; }\n .knob {\n position: relative;\n width: var(--_size);\n height: var(--_size);\n cursor: pointer;\n user-select: none;\n touch-action: none;\n }\n :host([readonly]) .knob,\n :host([disabled]) .knob {\n cursor: default;\n pointer-events: none;\n }\n :host([disabled]) .knob {\n opacity: 0.55;\n }\n svg {\n width: 100%;\n height: 100%;\n transform: rotate(-90deg);\n }\n .track {\n fill: none;\n stroke: var(--_range-color);\n stroke-width: var(--_stroke-width);\n }\n .value {\n fill: none;\n stroke: var(--_value-color);\n stroke-width: var(--_stroke-width);\n stroke-linecap: round;\n transition: stroke-dashoffset var(--fx-motion-duration-fast) var(--fx-motion-easing);\n }\n .label {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n color: var(--fx-text-default);\n pointer-events: none;\n }\n :host([size='sm']) .label { font-size: 11px; }\n :host([size='md']) .label { font-size: 14px; }\n :host([size='lg']) .label { font-size: 18px; }\n .knob:focus-visible {\n outline: none;\n }\n .knob:focus-visible svg {\n /* Mesmo fallback none dos demais componentes: sem motor de tema (ou com\n effect.focus-ring desligado) não há anel de foco. */\n filter: drop-shadow(var(--fx-effect-focus-ring, none));\n }\n `;\n\n static override get observedAttributes(): string[] {\n return [\n 'value',\n 'min',\n 'max',\n 'step',\n 'size',\n 'stroke-width',\n 'value-color',\n 'range-color',\n 'readonly',\n 'disabled',\n 'value-template',\n ];\n }\n\n get value(): number {\n return this.clampValue(Number(this.getAttr('value', '0')) || 0);\n }\n set value(v: number) {\n if (this.readonly || this.disabled) return;\n const clamped = this.clampValue(v);\n const current = this.clampValue(Number(this.getAttr('value', '0')) || 0);\n if (clamped !== current) {\n this.setAttribute('value', String(clamped));\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { value: clamped },\n }),\n );\n }\n }\n\n get min(): number {\n return Number(this.getAttr('min', '0')) || 0;\n }\n set min(v: number) {\n this.setAttribute('min', String(v));\n }\n\n get max(): number {\n return Number(this.getAttr('max', '100')) || 100;\n }\n set max(v: number) {\n this.setAttribute('max', String(v));\n }\n\n get step(): number {\n return Number(this.getAttr('step', '1')) || 1;\n }\n set step(v: number) {\n this.setAttribute('step', String(v));\n }\n\n get size(): string {\n const s = this.getAttr('size', 'md');\n return s === 'sm' || s === 'lg' ? s : 'md';\n }\n set size(v: string) {\n this.setAttribute('size', v);\n }\n\n get strokeWidth(): number {\n return Number(this.getAttr('stroke-width', '8')) || 8;\n }\n set strokeWidth(v: number) {\n this.setAttribute('stroke-width', String(v));\n }\n\n get valueColor(): string {\n return this.getAttr('value-color', '');\n }\n set valueColor(v: string) {\n this.setAttribute('value-color', v);\n }\n\n get rangeColor(): string {\n return this.getAttr('range-color', '');\n }\n set rangeColor(v: string) {\n this.setAttribute('range-color', v);\n }\n\n get readonly(): boolean {\n return this.hasAttr('readonly');\n }\n set readonly(v: boolean) {\n this.toggleAttr('readonly', Boolean(v));\n }\n\n get disabled(): boolean {\n return this.hasAttr('disabled');\n }\n set disabled(v: boolean) {\n this.toggleAttr('disabled', Boolean(v));\n }\n\n get valueTemplate(): string {\n return this.getAttr('value-template', '{value}');\n }\n set valueTemplate(v: string) {\n this.setAttribute('value-template', v);\n }\n\n private _isDragging = false;\n private _startY = 0;\n private _startValue = 0;\n\n protected override render(): void {\n const min = this.min;\n const max = this.max;\n const value = this.clampValue(this.value);\n const range = max - min;\n const pct = range > 0 ? (value - min) / range : 0;\n\n const sizeNum = this.getSizeNum();\n const strokeW = this.strokeWidth;\n const radius = (sizeNum - strokeW) / 2;\n const circumference = 2 * Math.PI * radius;\n const offset = circumference * (1 - pct);\n\n const vc = this.valueColor ? this.safeColor(this.valueColor) : '';\n const rc = this.rangeColor ? this.safeColor(this.rangeColor) : '';\n const valueColorStyle = vc ? `--_value-color: ${vc};` : '';\n const rangeColorStyle = rc ? `--_range-color: ${rc};` : '';\n\n const displayValue = this.valueTemplate.replace('{value}', String(Math.round(value)));\n\n this.setTemplate(`\n <div class=\"knob\" part=\"knob\" tabindex=\"${this.disabled ? '-1' : '0'}\"\n role=\"slider\" aria-valuenow=\"${value}\" aria-valuemin=\"${min}\" aria-valuemax=\"${max}\"\n aria-readonly=\"${this.readonly}\" aria-disabled=\"${this.disabled}\"\n style=\"${valueColorStyle}${rangeColorStyle}\">\n <svg viewBox=\"0 0 ${sizeNum} ${sizeNum}\" part=\"svg\">\n <circle class=\"track\" part=\"track\"\n cx=\"${sizeNum / 2}\" cy=\"${sizeNum / 2}\" r=\"${radius}\" />\n <circle class=\"value\" part=\"value\"\n cx=\"${sizeNum / 2}\" cy=\"${sizeNum / 2}\" r=\"${radius}\"\n stroke-dasharray=\"${circumference}\"\n stroke-dashoffset=\"${offset}\" />\n </svg>\n <div class=\"label\" part=\"label\">${esc(displayValue)}</div>\n </div>\n `);\n\n this.attachListeners();\n }\n\n private getSizeNum(): number {\n const s = this.size;\n if (s === 'sm') return 60;\n if (s === 'lg') return 140;\n return 100;\n }\n\n /** Valida um valor de cor CSS, retornando-o seguro ou vazio. */\n private safeColor(value: string): string {\n const v = value.trim();\n if (/^#[0-9a-fA-F]{3,8}$/.test(v)) return v;\n if (/^(rgb|rgba|hsl|hsla)\\([\\d\\s.,%()]+\\)$/i.test(v)) return v;\n if (/^var\\(--[\\w-]+(,\\s*[^)]*)?\\)$/.test(v)) return v;\n if (/^[a-zA-Z]+$/.test(v)) return v;\n return '';\n }\n\n private clampValue(v: number): number {\n const min = this.min;\n const max = this.max;\n const step = this.step;\n let clamped = Math.min(max, Math.max(min, v));\n if (step > 0) {\n clamped = Math.round((clamped - min) / step) * step + min;\n clamped = Math.min(max, Math.max(min, clamped));\n }\n return clamped;\n }\n\n private emitChange(newValue: number): void {\n const clamped = this.clampValue(newValue);\n if (clamped !== this.value) {\n this.value = clamped;\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { value: clamped },\n }),\n );\n }\n }\n\n private attachListeners(): void {\n const knob = this.root.querySelector<HTMLElement>('.knob');\n if (!knob) return;\n\n knob.addEventListener('mousedown', (e: MouseEvent) => {\n if (this.readonly || this.disabled) return;\n e.preventDefault();\n this._isDragging = true;\n this._startY = e.clientY;\n this._startValue = this.value;\n knob.focus();\n document.addEventListener('mousemove', this._onMouseMove);\n document.addEventListener('mouseup', this._onMouseUp);\n });\n\n knob.addEventListener('touchstart', (e: TouchEvent) => {\n if (this.readonly || this.disabled) return;\n e.preventDefault();\n this._isDragging = true;\n this._startY = e.touches[0].clientY;\n this._startValue = this.value;\n knob.focus();\n }, { passive: false });\n\n knob.addEventListener('touchmove', (e: TouchEvent) => {\n if (!this._isDragging || this.readonly || this.disabled) return;\n e.preventDefault();\n const deltaY = this._startY - e.touches[0].clientY;\n const sensitivity = (this.max - this.min) / 100;\n this.emitChange(this._startValue + deltaY * sensitivity);\n }, { passive: false });\n\n knob.addEventListener('touchend', () => {\n this._isDragging = false;\n });\n\n knob.addEventListener('keydown', (e: KeyboardEvent) => {\n if (this.readonly || this.disabled) return;\n const step = this.step;\n switch (e.key) {\n case 'ArrowUp':\n case 'ArrowRight':\n e.preventDefault();\n this.emitChange(this.value + step);\n break;\n case 'ArrowDown':\n case 'ArrowLeft':\n e.preventDefault();\n this.emitChange(this.value - step);\n break;\n case 'Home':\n e.preventDefault();\n this.emitChange(this.min);\n break;\n case 'End':\n e.preventDefault();\n this.emitChange(this.max);\n break;\n case 'PageUp':\n e.preventDefault();\n this.emitChange(this.value + step * 10);\n break;\n case 'PageDown':\n e.preventDefault();\n this.emitChange(this.value - step * 10);\n break;\n }\n });\n }\n\n private _onMouseMove = (e: MouseEvent): void => {\n if (!this._isDragging) return;\n const deltaY = this._startY - e.clientY;\n const sensitivity = (this.max - this.min) / 100;\n this.emitChange(this._startValue + deltaY * sensitivity);\n };\n\n private _onMouseUp = (): void => {\n this._isDragging = false;\n document.removeEventListener('mousemove', this._onMouseMove);\n document.removeEventListener('mouseup', this._onMouseUp);\n };\n\n protected override disconnectedCallback(): void {\n document.removeEventListener('mousemove', this._onMouseMove);\n document.removeEventListener('mouseup', this._onMouseUp);\n super.disconnectedCallback();\n }\n}\n\nexport function defineFxKnob(): typeof FxKnob {\n return defineElement('fx-knob', FxKnob);\n}"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"multiselect.d.ts","sourceRoot":"","sources":["../../../src/components/multiselect/multiselect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;;;;;GASG;AACH,qBAAa,aAAc,SAAQ,SAAS;IAC1C,OAAgB,MAAM,SAgOpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAIjD;IAED,OAAO,CAAC,QAAQ,CAAC,CAAmB;IACpC,OAAO,CAAC,WAAW,CAAC,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAqB;IAErC,qEAAqE;IACrE,IAAI,MAAM,IAAI,MAAM,EAAE,CAGrB;IACD,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAExB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;IAED,OAAO,KAAK,OAAO,GAKlB;cAEkB,iBAAiB,IAAI,IAAI;cAezB,oBAAoB,IAAI,IAAI;IAM/C,gDAAgD;IAChD,OAAO,CAAC,MAAM;IAYd,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,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;;;;;GASG;AACH,qBAAa,aAAc,SAAQ,SAAS;IAC1C,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;IAErC,qEAAqE;IACrE,IAAI,MAAM,IAAI,MAAM,EAAE,CAGrB;IACD,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAExB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;IAED,OAAO,KAAK,OAAO,GAKlB;cAEkB,iBAAiB,IAAI,IAAI;cAezB,oBAAoB,IAAI,IAAI;IAM/C,gDAAgD;IAChD,OAAO,CAAC,MAAM;IAYd,OAAO,CAAC,WAAW;IAMnB,qEAAqE;IACrE,OAAO,CAAC,gBAAgB;cAiBL,MAAM,IAAI,IAAI;CAwIlC;AAED,wBAAgB,mBAAmB,IAAI,OAAO,aAAa,CAE1D"}