@wrrdev/fenix-ui 1.0.14 → 1.0.16
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.
- package/README.md +332 -332
- package/dist/components/accordion/accordion.d.ts +1 -0
- package/dist/components/accordion/accordion.d.ts.map +1 -1
- package/dist/components/accordion/accordion.js +18 -13
- package/dist/components/accordion/accordion.js.map +1 -1
- package/dist/components/accordion/index.js.map +1 -1
- package/dist/components/alert/alert.d.ts.map +1 -1
- package/dist/components/alert/alert.js +2 -1
- package/dist/components/alert/alert.js.map +1 -1
- package/dist/components/alert/index.js.map +1 -1
- package/dist/components/autocomplete/autocomplete.d.ts +3 -0
- package/dist/components/autocomplete/autocomplete.d.ts.map +1 -1
- package/dist/components/autocomplete/autocomplete.js +28 -4
- package/dist/components/autocomplete/autocomplete.js.map +1 -1
- package/dist/components/autocomplete/index.js.map +1 -1
- package/dist/components/datepicker/datepicker.d.ts.map +1 -1
- package/dist/components/datepicker/datepicker.js +7 -6
- package/dist/components/datepicker/datepicker.js.map +1 -1
- package/dist/components/dialog/dialog.d.ts +4 -0
- package/dist/components/dialog/dialog.d.ts.map +1 -1
- package/dist/components/dialog/dialog.js +42 -4
- package/dist/components/dialog/dialog.js.map +1 -1
- package/dist/components/dialog/index.js.map +1 -1
- package/dist/components/drawer/drawer.d.ts +5 -0
- package/dist/components/drawer/drawer.d.ts.map +1 -1
- package/dist/components/drawer/drawer.js +49 -15
- package/dist/components/drawer/drawer.js.map +1 -1
- package/dist/components/dropdown/dropdown.d.ts +5 -0
- package/dist/components/dropdown/dropdown.d.ts.map +1 -1
- package/dist/components/dropdown/dropdown.js +34 -10
- package/dist/components/dropdown/dropdown.js.map +1 -1
- package/dist/components/input/input.d.ts.map +1 -1
- package/dist/components/input/input.js +4 -3
- package/dist/components/input/input.js.map +1 -1
- package/dist/components/knob/index.js.map +1 -1
- package/dist/components/knob/knob.d.ts +2 -0
- package/dist/components/knob/knob.d.ts.map +1 -1
- package/dist/components/knob/knob.js +15 -3
- package/dist/components/knob/knob.js.map +1 -1
- package/dist/components/multiselect/multiselect.d.ts +2 -0
- package/dist/components/multiselect/multiselect.d.ts.map +1 -1
- package/dist/components/multiselect/multiselect.js +38 -8
- package/dist/components/multiselect/multiselect.js.map +1 -1
- package/dist/components/orderlist/orderlist.d.ts.map +1 -1
- package/dist/components/orderlist/orderlist.js +1 -3
- package/dist/components/orderlist/orderlist.js.map +1 -1
- package/dist/components/pagination/index.js.map +1 -1
- package/dist/components/pagination/pagination.d.ts +1 -0
- package/dist/components/pagination/pagination.d.ts.map +1 -1
- package/dist/components/pagination/pagination.js +19 -8
- package/dist/components/pagination/pagination.js.map +1 -1
- package/dist/components/picklist/picklist.d.ts.map +1 -1
- package/dist/components/picklist/picklist.js +1 -3
- package/dist/components/picklist/picklist.js.map +1 -1
- package/dist/components/progress/index.js.map +1 -1
- package/dist/components/progress/progress.d.ts.map +1 -1
- package/dist/components/progress/progress.js +2 -1
- package/dist/components/progress/progress.js.map +1 -1
- package/dist/components/radio/radio.js +1 -1
- package/dist/components/radio/radio.js.map +1 -1
- package/dist/components/select/select.d.ts +2 -0
- package/dist/components/select/select.d.ts.map +1 -1
- package/dist/components/select/select.js +36 -5
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/skeleton/index.js.map +1 -1
- package/dist/components/skeleton/skeleton.d.ts +2 -0
- package/dist/components/skeleton/skeleton.d.ts.map +1 -1
- package/dist/components/skeleton/skeleton.js +7 -2
- package/dist/components/skeleton/skeleton.js.map +1 -1
- package/dist/components/table/expr.d.ts +38 -0
- package/dist/components/table/expr.d.ts.map +1 -0
- package/dist/components/table/expr.js +429 -0
- package/dist/components/table/expr.js.map +1 -0
- package/dist/components/table/table.d.ts +26 -8
- package/dist/components/table/table.d.ts.map +1 -1
- package/dist/components/table/table.js +402 -140
- package/dist/components/table/table.js.map +1 -1
- package/dist/components/tabs/tabs.d.ts.map +1 -1
- package/dist/components/tabs/tabs.js +3 -2
- package/dist/components/tabs/tabs.js.map +1 -1
- package/dist/components/textarea/index.js.map +1 -1
- package/dist/components/textarea/textarea.d.ts.map +1 -1
- package/dist/components/textarea/textarea.js +4 -3
- package/dist/components/textarea/textarea.js.map +1 -1
- package/dist/components/toast/index.js.map +1 -1
- package/dist/components/tooltip/directive.js.map +1 -1
- package/dist/components/tooltip/index.js.map +1 -1
- package/dist/components/tooltip/tooltip.d.ts.map +1 -1
- package/dist/components/tooltip/tooltip.js +2 -1
- package/dist/components/tooltip/tooltip.js.map +1 -1
- package/dist/core/jsx.js.map +1 -1
- package/dist/core/presets.js.map +1 -1
- package/dist/core/sanitize.d.ts +36 -0
- package/dist/core/sanitize.d.ts.map +1 -0
- package/dist/core/sanitize.js +37 -0
- package/dist/core/sanitize.js.map +1 -0
- package/dist/core/tokens.js.map +1 -1
- package/dist/core/vue.js.map +1 -1
- package/dist/docs/app.d.ts.map +1 -1
- package/dist/docs/componentes/table.doc.d.ts.map +1 -1
- package/dist/fenix-ui.esm.js.map +1 -1
- package/dist/fenix-ui.umd.min.js +339 -208
- package/dist/fenix-ui2.esm.js +1156 -243
- package/dist/fenix-ui2.esm.js.map +1 -1
- package/dist/fenix-ui3.esm.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins/auto-import.js.map +1 -1
- package/package.json +212 -212
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accordion.d.ts","sourceRoot":"","sources":["../../../src/components/accordion/accordion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"accordion.d.ts","sourceRoot":"","sources":["../../../src/components/accordion/accordion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,SAAQ,SAAS;IAC7C,OAAgB,MAAM,SAoEpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IACD,IAAI,MAAM,CAAC,CAAC,EAAE,MAAM,EAEnB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,EAElB;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;cAEkB,iBAAiB,IAAI,IAAI;cAuBzB,oBAAoB,IAAI,IAAI;IAK/C,OAAO,CAAC,GAAG,CAAiC;IAC5C,OAAO,CAAC,sBAAsB,CAAS;cAEpB,MAAM,IAAI,IAAI;CAwBlC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,WAAY,SAAQ,SAAS;IACxC,OAAgB,MAAM,SAapB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,CAAC,EAAE,OAAO,EAEtB;IAED,iCAAiC;IACjC,IAAI,MAAM,IAAI,MAAM,EAAE,CAErB;IACD,IAAI,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAErB;cAEkB,iBAAiB,IAAI,IAAI;cASzB,oBAAoB,IAAI,IAAI;IAK/C,OAAO,CAAC,SAAS,CAAiC;cAE/B,MAAM,IAAI,IAAI;IAUjC,6DAA6D;IAC7D,OAAO,KAAK,MAAM,GAEjB;IAED,OAAO,CAAC,KAAK;IAsBb,OAAO,CAAC,YAAY,CAAS;IAE7B,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,kBAAkB,CAAS;IAEnC,mEAAmE;IACnE,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAqBrC,iCAAiC;IACjC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKzB,kCAAkC;IAClC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAI3B;AAED,wBAAgB,iBAAiB,IAAI,OAAO,WAAW,CAEtD;AAED,wBAAgB,sBAAsB,IAAI,OAAO,gBAAgB,CAEhE"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { FxElement } from "../../core/base.js";
|
|
2
2
|
import { css } from "../../core/css.js";
|
|
3
3
|
import { defineElement } from "../../core/define.js";
|
|
4
|
+
import { esc } from "../../core/sanitize.js";
|
|
4
5
|
const _FxAccordionPanel = class _FxAccordionPanel extends FxElement {
|
|
5
6
|
constructor() {
|
|
6
7
|
super(...arguments);
|
|
7
8
|
this._mo = null;
|
|
9
|
+
this._clickListenerAttached = false;
|
|
8
10
|
}
|
|
9
11
|
static get observedAttributes() {
|
|
10
12
|
return ["header", "expanded", "disabled"];
|
|
@@ -35,18 +37,21 @@ const _FxAccordionPanel = class _FxAccordionPanel extends FxElement {
|
|
|
35
37
|
}
|
|
36
38
|
connectedCallback() {
|
|
37
39
|
super.connectedCallback();
|
|
38
|
-
this.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
if (!this._clickListenerAttached) {
|
|
41
|
+
this._clickListenerAttached = true;
|
|
42
|
+
this.addEventListener("click", (e) => {
|
|
43
|
+
const path = e.composedPath();
|
|
44
|
+
if (!path.some((el) => el.classList?.contains("header"))) return;
|
|
45
|
+
if (this.disabled) return;
|
|
46
|
+
this.dispatchEvent(
|
|
47
|
+
new CustomEvent("fx-accordion-toggle", {
|
|
48
|
+
bubbles: true,
|
|
49
|
+
composed: true,
|
|
50
|
+
detail: { panel: this }
|
|
51
|
+
})
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
50
55
|
this._mo = new MutationObserver(() => this.render());
|
|
51
56
|
this._mo.observe(this, { attributes: true, attributeFilter: ["expanded", "header", "disabled"] });
|
|
52
57
|
}
|
|
@@ -61,7 +66,7 @@ const _FxAccordionPanel = class _FxAccordionPanel extends FxElement {
|
|
|
61
66
|
aria-expanded="${this.expanded}"
|
|
62
67
|
${this.disabled ? 'aria-disabled="true"' : ""}>
|
|
63
68
|
<span class="header-text" part="header-text">
|
|
64
|
-
<slot name="header">${this.header}</slot>
|
|
69
|
+
<slot name="header">${esc(this.header)}</slot>
|
|
65
70
|
</span>
|
|
66
71
|
<span class="chevron" part="chevron" aria-hidden="true">
|
|
67
72
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accordion.js","sources":["../../../src/components/accordion/accordion.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\r\nimport { css } from '../../core/css';\r\nimport { defineElement } from '../../core/define';\r\n\r\n/**\r\n * <fx-accordion-panel> — Painel individual do accordion.\r\n *\r\n * Atributos:\r\n * - header: titulo exibido no cabecalho (ou use o slot \"header\").\r\n * - value: identificador unico do painel (usado pelo fx-accordion).\r\n * - expanded: presenca indica painel aberto (controlado pelo fx-accordion).\r\n * - disabled: impede a abertura do painel.\r\n */\r\nexport class FxAccordionPanel extends FxElement {\r\n static override styles = css`\r\n :host {\r\n display: block;\r\n font-family: var(--fx-font-family);\r\n font-size: var(--fx-font-size);\r\n color: var(--fx-text-default);\r\n }\r\n /* A borda fica no wrapper interno (nao no :host): regras do documento\r\n externo (ex.: preflight do Tailwind com border-width: 0) vencem as\r\n regras :host do shadow tree, o que apagaria a linha divisoria. */\r\n .panel {\r\n border-bottom: 1px solid var(--fx-border-default);\r\n }\r\n :host(:last-child) .panel { border-bottom: none; }\r\n :host([disabled]) { opacity: 0.6; pointer-events: none; }\r\n .header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: var(--fx-space-md);\r\n width: 100%;\r\n box-sizing: border-box;\r\n padding: var(--fx-space-lg, 20px) var(--fx-space-md, 14px);\r\n border: none;\r\n background: transparent;\r\n font-family: inherit;\r\n font-size: inherit;\r\n font-weight: 500;\r\n color: var(--fx-text-muted);\r\n text-align: left;\r\n cursor: pointer;\r\n transition: color var(--fx-motion-duration-fast, 150ms) var(--fx-motion-easing, ease),\r\n background var(--fx-motion-duration-fast, 150ms) var(--fx-motion-easing, ease);\r\n }\r\n .header:hover { color: var(--fx-text-default); }\r\n .header:focus-visible {\r\n outline: none;\r\n box-shadow: var(--fx-effect-focus-ring, none);\r\n border-radius: var(--fx-radius-sm, 4px);\r\n }\r\n :host([expanded]) .header {\r\n color: var(--fx-text-default);\r\n font-weight: 700;\r\n }\r\n .header-text { flex: 1; min-width: 0; }\r\n .chevron {\r\n flex-shrink: 0;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 24px;\r\n height: 24px;\r\n color: var(--fx-text-muted);\r\n transition: transform var(--fx-motion-duration-normal, 250ms) var(--fx-motion-easing, ease);\r\n }\r\n :host([expanded]) .chevron { transform: rotate(180deg); color: var(--fx-color-primary); }\r\n .content {\r\n display: grid;\r\n grid-template-rows: 0fr;\r\n transition: grid-template-rows var(--fx-motion-duration-normal, 250ms) var(--fx-motion-easing, ease);\r\n }\r\n :host([expanded]) .content { grid-template-rows: 1fr; }\r\n .content-inner { overflow: hidden; }\r\n .content-pad {\r\n padding: 0 var(--fx-space-md, 14px) var(--fx-space-lg, 20px);\r\n color: var(--fx-text-muted);\r\n line-height: 1.6;\r\n }\r\n `;\r\n\r\n static override get observedAttributes(): string[] {\r\n return ['header', 'expanded', 'disabled'];\r\n }\r\n\r\n get header(): string {\r\n return this.getAttr('header', '');\r\n }\r\n set header(v: string) {\r\n this.setAttribute('header', v);\r\n }\r\n\r\n get value(): string {\r\n return this.getAttr('value', '');\r\n }\r\n set value(v: string) {\r\n this.setAttribute('value', v);\r\n }\r\n\r\n get expanded(): boolean {\r\n return this.hasAttr('expanded');\r\n }\r\n set expanded(v: boolean) {\r\n this.toggleAttr('expanded', v);\r\n }\r\n\r\n get disabled(): boolean {\r\n return this.hasAttr('disabled');\r\n }\r\n set disabled(v: boolean) {\r\n this.toggleAttr('disabled', v);\r\n }\r\n\r\n protected override connectedCallback(): void {\r\n super.connectedCallback();\r\n // O clique vem do shadow root; composedPath() revela o alvo real.\r\n this.addEventListener('click', (e) => {\r\n const path = e.composedPath() as HTMLElement[];\r\n if (!path.some((el) => el.classList?.contains('header'))) return;\r\n if (this.disabled) return;\r\n this.dispatchEvent(\r\n new CustomEvent('fx-accordion-toggle', {\r\n bubbles: true,\r\n composed: true,\r\n detail: { panel: this },\r\n }),\r\n );\r\n });\r\n // Re-render quando o atributo expanded muda (para aria-expanded).\r\n this._mo = new MutationObserver(() => this.render());\r\n this._mo.observe(this, { attributes: true, attributeFilter: ['expanded', 'header', 'disabled'] });\r\n }\r\n\r\n protected override disconnectedCallback(): void {\r\n this._mo?.disconnect();\r\n this._mo = null;\r\n }\r\n\r\n private _mo: MutationObserver | null = null;\r\n\r\n protected override render(): void {\r\n this.setTemplate(`\r\n <div class=\"panel\" part=\"panel\">\r\n <button type=\"button\" class=\"header\" part=\"header\" role=\"button\"\r\n aria-expanded=\"${this.expanded}\"\r\n ${this.disabled ? 'aria-disabled=\"true\"' : ''}>\r\n <span class=\"header-text\" part=\"header-text\">\r\n <slot name=\"header\">${this.header}</slot>\r\n </span>\r\n <span class=\"chevron\" part=\"chevron\" aria-hidden=\"true\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </span>\r\n </button>\r\n <div class=\"content\" part=\"content\" role=\"region\">\r\n <div class=\"content-inner\">\r\n <div class=\"content-pad\" part=\"content-pad\"><slot></slot></div>\r\n </div>\r\n </div>\r\n </div>\r\n `);\r\n }\r\n}\r\n\r\n/**\r\n * <fx-accordion> — Conjunto de paineis expansivos (estilo PrimeVue).\r\n *\r\n * Por padrao (modo single) abrir um painel fecha os outros.\r\n * Adicione o atributo `multiple` para permitir varios paineis abertos.\r\n *\r\n * Uso:\r\n * <fx-accordion value=\"p1\">\r\n * <fx-accordion-panel value=\"p1\" header=\"Titulo 1\">Conteudo…</fx-accordion-panel>\r\n * <fx-accordion-panel value=\"p2\" header=\"Titulo 2\">Conteudo…</fx-accordion-panel>\r\n * </fx-accordion>\r\n *\r\n * Atributos:\r\n * - value: valor(es) ativo(s), separados por virgula no modo multiple.\r\n * - multiple: permite manter varios paineis abertos ao mesmo tempo.\r\n *\r\n * Evento: `change` (composed, detail: { value: string[] }).\r\n */\r\nexport class FxAccordion extends FxElement {\r\n static override styles = css`\r\n :host {\r\n display: block;\r\n font-family: var(--fx-font-family);\r\n font-size: var(--fx-font-size);\r\n }\r\n .accordion {\r\n background: var(--fx-surface-background, #ffffff);\r\n border: 1px solid var(--fx-border-default);\r\n border-radius: var(--fx-radius-md, 8px);\r\n overflow: hidden;\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);\r\n }\r\n `;\r\n\r\n static override get observedAttributes(): string[] {\r\n return ['value', 'multiple'];\r\n }\r\n\r\n get multiple(): boolean {\r\n return this.hasAttr('multiple');\r\n }\r\n set multiple(v: boolean) {\r\n this.toggleAttr('multiple', v);\r\n }\r\n\r\n /** Valores ativos como array. */\r\n get values(): string[] {\r\n return this.getAttr('value', '').split(',').map(s => s.trim()).filter(Boolean);\r\n }\r\n set values(v: string[]) {\r\n this.setAttribute('value', v.join(','));\r\n }\r\n\r\n protected override connectedCallback(): void {\r\n this._observer = new MutationObserver(() => this._sync());\r\n this._observer.observe(this, { childList: true, subtree: true });\r\n super.connectedCallback();\r\n // Os paineis filhos podem ainda nao estar upgradados no primeiro sync;\r\n // reagenda para depois da fila de upgrade de custom elements.\r\n queueMicrotask(() => this._sync());\r\n }\r\n\r\n protected override disconnectedCallback(): void {\r\n this._observer?.disconnect();\r\n this._observer = null;\r\n }\r\n\r\n private _observer: MutationObserver | null = null;\r\n\r\n protected override render(): void {\r\n this.setTemplate(`\r\n <div class=\"accordion\" part=\"accordion\">\r\n <slot></slot>\r\n </div>\r\n `);\r\n this._sync();\r\n this._attachListeners();\r\n }\r\n\r\n /** Painéis do accordion (filhos diretos ou descendentes). */\r\n private get panels(): FxAccordionPanel[] {\r\n return Array.from(this.querySelectorAll<FxAccordionPanel>('fx-accordion-panel'));\r\n }\r\n\r\n private _sync(): void {\r\n const actives = this.values;\r\n // Leitura via getAttribute (nao via getters) porque os paineis filhos\r\n // podem ainda nao estar upgradados quando o accordion conecta.\r\n const panels = Array.from(this.querySelectorAll('fx-accordion-panel'));\r\n // Apenas na conexao inicial (sem valor definido): abre o primeiro painel.\r\n if (!this._initialized && actives.length === 0 && panels.length > 0) {\r\n this._initialized = true;\r\n const first = panels.find((p) => !p.hasAttribute('disabled'));\r\n if (first) {\r\n this.values = [first.getAttribute('value') || '0'];\r\n return;\r\n }\r\n }\r\n this._initialized = true;\r\n panels.forEach((p, i) => {\r\n const v = p.getAttribute('value') || String(i);\r\n if (!p.hasAttribute('value')) p.setAttribute('value', v);\r\n p.toggleAttribute('expanded', actives.includes(v));\r\n });\r\n }\r\n\r\n private _initialized = false;\r\n\r\n private _attachListeners(): void {\r\n if (this._listenersAttached) return;\r\n this._listenersAttached = true;\r\n // O painel emite 'fx-accordion-toggle' a partir do proprio host\r\n // (event retargeting do Shadow DOM impede usar closest('.header') aqui).\r\n this.addEventListener('fx-accordion-toggle', (e) => {\r\n const panel = (e as CustomEvent).detail?.panel as FxAccordionPanel | undefined;\r\n if (!panel || panel.disabled) return;\r\n this.toggle(panel);\r\n });\r\n }\r\n\r\n private _listenersAttached = false;\r\n\r\n /** Abre/fecha um painel respeitando o modo (single | multiple). */\r\n toggle(panel: FxAccordionPanel): void {\r\n const v = panel.value;\r\n let actives = this.values;\r\n if (panel.expanded) {\r\n actives = actives.filter(a => a !== v);\r\n } else if (this.multiple) {\r\n actives = [...actives, v];\r\n } else {\r\n actives = [v];\r\n }\r\n this.values = actives;\r\n this._sync();\r\n this.dispatchEvent(\r\n new CustomEvent('change', {\r\n bubbles: true,\r\n composed: true,\r\n detail: { value: actives },\r\n }),\r\n );\r\n }\r\n\r\n /** Abre um painel pelo valor. */\r\n open(value: string): void {\r\n const panel = this.panels.find((p, i) => (p.value || String(i)) === value);\r\n if (panel && !panel.expanded) this.toggle(panel);\r\n }\r\n\r\n /** Fecha um painel pelo valor. */\r\n close(value: string): void {\r\n const panel = this.panels.find((p, i) => (p.value || String(i)) === value);\r\n if (panel && panel.expanded) this.toggle(panel);\r\n }\r\n}\r\n\r\nexport function defineFxAccordion(): typeof FxAccordion {\r\n return defineElement('fx-accordion', FxAccordion);\r\n}\r\n\r\nexport function defineFxAccordionPanel(): typeof FxAccordionPanel {\r\n return defineElement('fx-accordion-panel', FxAccordionPanel);\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"accordion.js","sources":["../../../src/components/accordion/accordion.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-accordion-panel> — Painel individual do accordion.\n *\n * Atributos:\n * - header: titulo exibido no cabecalho (ou use o slot \"header\").\n * - value: identificador unico do painel (usado pelo fx-accordion).\n * - expanded: presenca indica painel aberto (controlado pelo fx-accordion).\n * - disabled: impede a abertura do painel.\n */\nexport class FxAccordionPanel extends FxElement {\n static override styles = css`\n :host {\n display: block;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n color: var(--fx-text-default);\n }\n /* A borda fica no wrapper interno (nao no :host): regras do documento\n externo (ex.: preflight do Tailwind com border-width: 0) vencem as\n regras :host do shadow tree, o que apagaria a linha divisoria. */\n .panel {\n border-bottom: 1px solid var(--fx-border-default);\n }\n :host(:last-child) .panel { border-bottom: none; }\n :host([disabled]) { opacity: 0.6; pointer-events: none; }\n .header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--fx-space-md);\n width: 100%;\n box-sizing: border-box;\n padding: var(--fx-space-lg, 20px) var(--fx-space-md, 14px);\n border: none;\n background: transparent;\n font-family: inherit;\n font-size: inherit;\n font-weight: 500;\n color: var(--fx-text-muted);\n text-align: left;\n cursor: pointer;\n transition: color var(--fx-motion-duration-fast, 150ms) var(--fx-motion-easing, ease),\n background var(--fx-motion-duration-fast, 150ms) var(--fx-motion-easing, ease);\n }\n .header:hover { color: var(--fx-text-default); }\n .header:focus-visible {\n outline: none;\n box-shadow: var(--fx-effect-focus-ring, none);\n border-radius: var(--fx-radius-sm, 4px);\n }\n :host([expanded]) .header {\n color: var(--fx-text-default);\n font-weight: 700;\n }\n .header-text { flex: 1; min-width: 0; }\n .chevron {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n color: var(--fx-text-muted);\n transition: transform var(--fx-motion-duration-normal, 250ms) var(--fx-motion-easing, ease);\n }\n :host([expanded]) .chevron { transform: rotate(180deg); color: var(--fx-color-primary); }\n .content {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows var(--fx-motion-duration-normal, 250ms) var(--fx-motion-easing, ease);\n }\n :host([expanded]) .content { grid-template-rows: 1fr; }\n .content-inner { overflow: hidden; }\n .content-pad {\n padding: 0 var(--fx-space-md, 14px) var(--fx-space-lg, 20px);\n color: var(--fx-text-muted);\n line-height: 1.6;\n }\n `;\n\n static override get observedAttributes(): string[] {\n return ['header', 'expanded', 'disabled'];\n }\n\n get header(): string {\n return this.getAttr('header', '');\n }\n set header(v: string) {\n this.setAttribute('header', v);\n }\n\n get value(): string {\n return this.getAttr('value', '');\n }\n set value(v: string) {\n this.setAttribute('value', v);\n }\n\n get expanded(): boolean {\n return this.hasAttr('expanded');\n }\n set expanded(v: boolean) {\n this.toggleAttr('expanded', v);\n }\n\n get disabled(): boolean {\n return this.hasAttr('disabled');\n }\n set disabled(v: boolean) {\n this.toggleAttr('disabled', v);\n }\n\n protected override connectedCallback(): void {\n super.connectedCallback();\n // O clique vem do shadow root; composedPath() revela o alvo real.\n if (!this._clickListenerAttached) {\n this._clickListenerAttached = true;\n this.addEventListener('click', (e) => {\n const path = e.composedPath() as HTMLElement[];\n if (!path.some((el) => el.classList?.contains('header'))) return;\n if (this.disabled) return;\n this.dispatchEvent(\n new CustomEvent('fx-accordion-toggle', {\n bubbles: true,\n composed: true,\n detail: { panel: this },\n }),\n );\n });\n }\n // Re-render quando o atributo expanded muda (para aria-expanded).\n this._mo = new MutationObserver(() => this.render());\n this._mo.observe(this, { attributes: true, attributeFilter: ['expanded', 'header', 'disabled'] });\n }\n\n protected override disconnectedCallback(): void {\n this._mo?.disconnect();\n this._mo = null;\n }\n\n private _mo: MutationObserver | null = null;\n private _clickListenerAttached = false;\n\n protected override render(): void {\n this.setTemplate(`\n <div class=\"panel\" part=\"panel\">\n <button type=\"button\" class=\"header\" part=\"header\" role=\"button\"\n aria-expanded=\"${this.expanded}\"\n ${this.disabled ? 'aria-disabled=\"true\"' : ''}>\n <span class=\"header-text\" part=\"header-text\">\n <slot name=\"header\">${esc(this.header)}</slot>\n </span>\n <span class=\"chevron\" part=\"chevron\" aria-hidden=\"true\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </span>\n </button>\n <div class=\"content\" part=\"content\" role=\"region\">\n <div class=\"content-inner\">\n <div class=\"content-pad\" part=\"content-pad\"><slot></slot></div>\n </div>\n </div>\n </div>\n `);\n }\n}\n\n/**\n * <fx-accordion> — Conjunto de paineis expansivos (estilo PrimeVue).\n *\n * Por padrao (modo single) abrir um painel fecha os outros.\n * Adicione o atributo `multiple` para permitir varios paineis abertos.\n *\n * Uso:\n * <fx-accordion value=\"p1\">\n * <fx-accordion-panel value=\"p1\" header=\"Titulo 1\">Conteudo…</fx-accordion-panel>\n * <fx-accordion-panel value=\"p2\" header=\"Titulo 2\">Conteudo…</fx-accordion-panel>\n * </fx-accordion>\n *\n * Atributos:\n * - value: valor(es) ativo(s), separados por virgula no modo multiple.\n * - multiple: permite manter varios paineis abertos ao mesmo tempo.\n *\n * Evento: `change` (composed, detail: { value: string[] }).\n */\nexport class FxAccordion extends FxElement {\n static override styles = css`\n :host {\n display: block;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n .accordion {\n background: var(--fx-surface-background, #ffffff);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md, 8px);\n overflow: hidden;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);\n }\n `;\n\n static override get observedAttributes(): string[] {\n return ['value', 'multiple'];\n }\n\n get multiple(): boolean {\n return this.hasAttr('multiple');\n }\n set multiple(v: boolean) {\n this.toggleAttr('multiple', v);\n }\n\n /** Valores ativos como array. */\n get values(): string[] {\n return this.getAttr('value', '').split(',').map(s => s.trim()).filter(Boolean);\n }\n set values(v: string[]) {\n this.setAttribute('value', v.join(','));\n }\n\n protected override connectedCallback(): void {\n this._observer = new MutationObserver(() => this._sync());\n this._observer.observe(this, { childList: true, subtree: true });\n super.connectedCallback();\n // Os paineis filhos podem ainda nao estar upgradados no primeiro sync;\n // reagenda para depois da fila de upgrade de custom elements.\n queueMicrotask(() => this._sync());\n }\n\n protected override disconnectedCallback(): void {\n this._observer?.disconnect();\n this._observer = null;\n }\n\n private _observer: MutationObserver | null = null;\n\n protected override render(): void {\n this.setTemplate(`\n <div class=\"accordion\" part=\"accordion\">\n <slot></slot>\n </div>\n `);\n this._sync();\n this._attachListeners();\n }\n\n /** Painéis do accordion (filhos diretos ou descendentes). */\n private get panels(): FxAccordionPanel[] {\n return Array.from(this.querySelectorAll<FxAccordionPanel>('fx-accordion-panel'));\n }\n\n private _sync(): void {\n const actives = this.values;\n // Leitura via getAttribute (nao via getters) porque os paineis filhos\n // podem ainda nao estar upgradados quando o accordion conecta.\n const panels = Array.from(this.querySelectorAll('fx-accordion-panel'));\n // Apenas na conexao inicial (sem valor definido): abre o primeiro painel.\n if (!this._initialized && actives.length === 0 && panels.length > 0) {\n this._initialized = true;\n const first = panels.find((p) => !p.hasAttribute('disabled'));\n if (first) {\n this.values = [first.getAttribute('value') || '0'];\n return;\n }\n }\n this._initialized = true;\n panels.forEach((p, i) => {\n const v = p.getAttribute('value') || String(i);\n if (!p.hasAttribute('value')) p.setAttribute('value', v);\n p.toggleAttribute('expanded', actives.includes(v));\n });\n }\n\n private _initialized = false;\n\n private _attachListeners(): void {\n if (this._listenersAttached) return;\n this._listenersAttached = true;\n // O painel emite 'fx-accordion-toggle' a partir do proprio host\n // (event retargeting do Shadow DOM impede usar closest('.header') aqui).\n this.addEventListener('fx-accordion-toggle', (e) => {\n const panel = (e as CustomEvent).detail?.panel as FxAccordionPanel | undefined;\n if (!panel || panel.disabled) return;\n this.toggle(panel);\n });\n }\n\n private _listenersAttached = false;\n\n /** Abre/fecha um painel respeitando o modo (single | multiple). */\n toggle(panel: FxAccordionPanel): void {\n const v = panel.value;\n let actives = this.values;\n if (panel.expanded) {\n actives = actives.filter(a => a !== v);\n } else if (this.multiple) {\n actives = [...actives, v];\n } else {\n actives = [v];\n }\n this.values = actives;\n this._sync();\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: { value: actives },\n }),\n );\n }\n\n /** Abre um painel pelo valor. */\n open(value: string): void {\n const panel = this.panels.find((p, i) => (p.value || String(i)) === value);\n if (panel && !panel.expanded) this.toggle(panel);\n }\n\n /** Fecha um painel pelo valor. */\n close(value: string): void {\n const panel = this.panels.find((p, i) => (p.value || String(i)) === value);\n if (panel && panel.expanded) this.toggle(panel);\n }\n}\n\nexport function defineFxAccordion(): typeof FxAccordion {\n return defineElement('fx-accordion', FxAccordion);\n}\n\nexport function defineFxAccordionPanel(): typeof FxAccordionPanel {\n return defineElement('fx-accordion-panel', FxAccordionPanel);\n}\n"],"names":[],"mappings":";;;;AAcO,MAAM,oBAAN,MAAM,0BAAyB,UAAU;AAAA,EAAzC,cAAA;AAAA,UAAA,GAAA,SAAA;AAmIL,SAAQ,MAA+B;AACvC,SAAQ,yBAAyB;AAAA,EAAA;AAAA,EA7DjC,WAAoB,qBAA+B;AACjD,WAAO,CAAC,UAAU,YAAY,UAAU;AAAA,EAC1C;AAAA,EAEA,IAAI,SAAiB;AACnB,WAAO,KAAK,QAAQ,UAAU,EAAE;AAAA,EAClC;AAAA,EACA,IAAI,OAAO,GAAW;AACpB,SAAK,aAAa,UAAU,CAAC;AAAA,EAC/B;AAAA,EAEA,IAAI,QAAgB;AAClB,WAAO,KAAK,QAAQ,SAAS,EAAE;AAAA,EACjC;AAAA,EACA,IAAI,MAAM,GAAW;AACnB,SAAK,aAAa,SAAS,CAAC;AAAA,EAC9B;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO,KAAK,QAAQ,UAAU;AAAA,EAChC;AAAA,EACA,IAAI,SAAS,GAAY;AACvB,SAAK,WAAW,YAAY,CAAC;AAAA,EAC/B;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO,KAAK,QAAQ,UAAU;AAAA,EAChC;AAAA,EACA,IAAI,SAAS,GAAY;AACvB,SAAK,WAAW,YAAY,CAAC;AAAA,EAC/B;AAAA,EAEmB,oBAA0B;AAC3C,UAAM,kBAAA;AAEN,QAAI,CAAC,KAAK,wBAAwB;AAChC,WAAK,yBAAyB;AAC9B,WAAK,iBAAiB,SAAS,CAAC,MAAM;AACpC,cAAM,OAAO,EAAE,aAAA;AACf,YAAI,CAAC,KAAK,KAAK,CAAC,OAAO,GAAG,WAAW,SAAS,QAAQ,CAAC,EAAG;AAC1D,YAAI,KAAK,SAAU;AACnB,aAAK;AAAA,UACH,IAAI,YAAY,uBAAuB;AAAA,YACrC,SAAS;AAAA,YACT,UAAU;AAAA,YACV,QAAQ,EAAE,OAAO,KAAA;AAAA,UAAK,CACvB;AAAA,QAAA;AAAA,MAEL,CAAC;AAAA,IACH;AAEA,SAAK,MAAM,IAAI,iBAAiB,MAAM,KAAK,QAAQ;AACnD,SAAK,IAAI,QAAQ,MAAM,EAAE,YAAY,MAAM,iBAAiB,CAAC,YAAY,UAAU,UAAU,EAAA,CAAG;AAAA,EAClG;AAAA,EAEmB,uBAA6B;AAC9C,SAAK,KAAK,WAAA;AACV,SAAK,MAAM;AAAA,EACb;AAAA,EAKmB,SAAe;AAChC,SAAK,YAAY;AAAA;AAAA;AAAA,2BAGM,KAAK,QAAQ;AAAA,YAC5B,KAAK,WAAW,yBAAyB,EAAE;AAAA;AAAA,kCAErB,IAAI,KAAK,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAe7C;AAAA,EACH;AACF;AA7JE,kBAAgB,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;AADpB,IAAM,mBAAN;AAkLA,MAAM,eAAN,MAAM,qBAAoB,UAAU;AAAA,EAApC,cAAA;AAAA,UAAA,GAAA,SAAA;AAiDL,SAAQ,YAAqC;AAuC7C,SAAQ,eAAe;AAcvB,SAAQ,qBAAqB;AAAA,EAAA;AAAA,EAtF7B,WAAoB,qBAA+B;AACjD,WAAO,CAAC,SAAS,UAAU;AAAA,EAC7B;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO,KAAK,QAAQ,UAAU;AAAA,EAChC;AAAA,EACA,IAAI,SAAS,GAAY;AACvB,SAAK,WAAW,YAAY,CAAC;AAAA,EAC/B;AAAA;AAAA,EAGA,IAAI,SAAmB;AACrB,WAAO,KAAK,QAAQ,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAA,CAAM,EAAE,OAAO,OAAO;AAAA,EAC/E;AAAA,EACA,IAAI,OAAO,GAAa;AACtB,SAAK,aAAa,SAAS,EAAE,KAAK,GAAG,CAAC;AAAA,EACxC;AAAA,EAEmB,oBAA0B;AAC3C,SAAK,YAAY,IAAI,iBAAiB,MAAM,KAAK,OAAO;AACxD,SAAK,UAAU,QAAQ,MAAM,EAAE,WAAW,MAAM,SAAS,MAAM;AAC/D,UAAM,kBAAA;AAGN,mBAAe,MAAM,KAAK,OAAO;AAAA,EACnC;AAAA,EAEmB,uBAA6B;AAC9C,SAAK,WAAW,WAAA;AAChB,SAAK,YAAY;AAAA,EACnB;AAAA,EAImB,SAAe;AAChC,SAAK,YAAY;AAAA;AAAA;AAAA;AAAA,KAIhB;AACD,SAAK,MAAA;AACL,SAAK,iBAAA;AAAA,EACP;AAAA;AAAA,EAGA,IAAY,SAA6B;AACvC,WAAO,MAAM,KAAK,KAAK,iBAAmC,oBAAoB,CAAC;AAAA,EACjF;AAAA,EAEQ,QAAc;AACpB,UAAM,UAAU,KAAK;AAGrB,UAAM,SAAS,MAAM,KAAK,KAAK,iBAAiB,oBAAoB,CAAC;AAErE,QAAI,CAAC,KAAK,gBAAgB,QAAQ,WAAW,KAAK,OAAO,SAAS,GAAG;AACnE,WAAK,eAAe;AACpB,YAAM,QAAQ,OAAO,KAAK,CAAC,MAAM,CAAC,EAAE,aAAa,UAAU,CAAC;AAC5D,UAAI,OAAO;AACT,aAAK,SAAS,CAAC,MAAM,aAAa,OAAO,KAAK,GAAG;AACjD;AAAA,MACF;AAAA,IACF;AACA,SAAK,eAAe;AACpB,WAAO,QAAQ,CAAC,GAAG,MAAM;AACvB,YAAM,IAAI,EAAE,aAAa,OAAO,KAAK,OAAO,CAAC;AAC7C,UAAI,CAAC,EAAE,aAAa,OAAO,EAAG,GAAE,aAAa,SAAS,CAAC;AACvD,QAAE,gBAAgB,YAAY,QAAQ,SAAS,CAAC,CAAC;AAAA,IACnD,CAAC;AAAA,EACH;AAAA,EAIQ,mBAAyB;AAC/B,QAAI,KAAK,mBAAoB;AAC7B,SAAK,qBAAqB;AAG1B,SAAK,iBAAiB,uBAAuB,CAAC,MAAM;AAClD,YAAM,QAAS,EAAkB,QAAQ;AACzC,UAAI,CAAC,SAAS,MAAM,SAAU;AAC9B,WAAK,OAAO,KAAK;AAAA,IACnB,CAAC;AAAA,EACH;AAAA;AAAA,EAKA,OAAO,OAA+B;AACpC,UAAM,IAAI,MAAM;AAChB,QAAI,UAAU,KAAK;AACnB,QAAI,MAAM,UAAU;AAClB,gBAAU,QAAQ,OAAO,CAAA,MAAK,MAAM,CAAC;AAAA,IACvC,WAAW,KAAK,UAAU;AACxB,gBAAU,CAAC,GAAG,SAAS,CAAC;AAAA,IAC1B,OAAO;AACL,gBAAU,CAAC,CAAC;AAAA,IACd;AACA,SAAK,SAAS;AACd,SAAK,MAAA;AACL,SAAK;AAAA,MACH,IAAI,YAAY,UAAU;AAAA,QACxB,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,EAAE,OAAO,QAAA;AAAA,MAAQ,CAC1B;AAAA,IAAA;AAAA,EAEL;AAAA;AAAA,EAGA,KAAK,OAAqB;AACxB,UAAM,QAAQ,KAAK,OAAO,KAAK,CAAC,GAAG,OAAO,EAAE,SAAS,OAAO,CAAC,OAAO,KAAK;AACzE,QAAI,SAAS,CAAC,MAAM,SAAU,MAAK,OAAO,KAAK;AAAA,EACjD;AAAA;AAAA,EAGA,MAAM,OAAqB;AACzB,UAAM,QAAQ,KAAK,OAAO,KAAK,CAAC,GAAG,OAAO,EAAE,SAAS,OAAO,CAAC,OAAO,KAAK;AACzE,QAAI,SAAS,MAAM,SAAU,MAAK,OAAO,KAAK;AAAA,EAChD;AACF;AAxIE,aAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AADpB,IAAM,cAAN;AA2IA,SAAS,oBAAwC;AACtD,SAAO,cAAc,gBAAgB,WAAW;AAClD;AAEO,SAAS,yBAAkD;AAChE,SAAO,cAAc,sBAAsB,gBAAgB;AAC7D;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/accordion/index.ts"],"sourcesContent":["import { defineFxAccordion, defineFxAccordionPanel } from './accordion';\
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/accordion/index.ts"],"sourcesContent":["import { defineFxAccordion, defineFxAccordionPanel } from './accordion';\n\n// Reexporta as classes para uso programático (ex.: instanceof, herança).\nexport { FxAccordion, FxAccordionPanel } from './accordion';\n\n// Auto-registro: basta importar o subpath `@wrrdev/fenix-ui/accordion`\n// para que os componentes sejam definidos no CustomElementRegistry.\ndefineFxAccordion();\ndefineFxAccordionPanel();\n"],"names":[],"mappings":";;AAOA,kBAAA;AACA,uBAAA;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alert.d.ts","sourceRoot":"","sources":["../../../src/components/alert/alert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"alert.d.ts","sourceRoot":"","sources":["../../../src/components/alert/alert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;GAKG;AACH,qBAAa,OAAQ,SAAQ,SAAS;IACpC,OAAgB,MAAM,SAiCpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;cAEkB,MAAM,IAAI,IAAI;CAuBlC;AAED,wBAAgB,aAAa,IAAI,OAAO,OAAO,CAE9C"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FxElement } from "../../core/base.js";
|
|
2
2
|
import { css } from "../../core/css.js";
|
|
3
3
|
import { defineElement } from "../../core/define.js";
|
|
4
|
+
import { esc } from "../../core/sanitize.js";
|
|
4
5
|
const _FxAlert = class _FxAlert extends FxElement {
|
|
5
6
|
static get observedAttributes() {
|
|
6
7
|
return ["variant", "title", "dismissible"];
|
|
@@ -18,7 +19,7 @@ const _FxAlert = class _FxAlert extends FxElement {
|
|
|
18
19
|
<div class="alert" part="alert" role="alert">
|
|
19
20
|
<span class="icon">${icons[variant] ?? "ℹ"}</span>
|
|
20
21
|
<div class="content">
|
|
21
|
-
${title ? `<div class="title">${title}</div>` : ""}
|
|
22
|
+
${title ? `<div class="title">${esc(title)}</div>` : ""}
|
|
22
23
|
<div class="body"><slot></slot></div>
|
|
23
24
|
</div>
|
|
24
25
|
${this.hasAttr("dismissible") ? '<button type="button" class="close" aria-label="Fechar">×</button>' : ""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alert.js","sources":["../../../src/components/alert/alert.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\n\n/**\n * <fx-alert> — Aviso inline com variantes semânticas.\n *\n * Atributos: variant (info|success|warning|danger, padrão info), title, dismissible.\n * Slot padrão: conteúdo da mensagem. Evento `dismiss`.\n */\nexport class FxAlert extends FxElement {\n static override styles = css`\n :host {\n display: block;\n font-family: var(--fx-font-family);\n --_color: var(--fx-color-primary);\n --_bg: color-mix(in srgb, var(--fx-color-primary) 10%, var(--fx-surface-background));\n }\n :host([variant='info']) { --_color: var(--fx-color-info); --_bg: color-mix(in srgb, var(--fx-color-info) 10%, var(--fx-surface-background)); }\n :host([variant='success']) { --_color: var(--fx-color-success); --_bg: color-mix(in srgb, var(--fx-color-success) 10%, var(--fx-surface-background)); }\n :host([variant='warning']) { --_color: var(--fx-color-warning); --_bg: color-mix(in srgb, var(--fx-color-warning) 12%, var(--fx-surface-background)); }\n :host([variant='danger']) { --_color: var(--fx-color-danger); --_bg: color-mix(in srgb, var(--fx-color-danger) 10%, var(--fx-surface-background)); }\n .alert {\n display: flex;\n align-items: flex-start;\n gap: var(--fx-space-md);\n background: var(--_bg);\n border: 1px solid color-mix(in srgb, var(--_color) 30%, transparent);\n border-radius: var(--fx-radius-md);\n padding: var(--fx-space-md) var(--fx-space-lg);\n font-size: var(--fx-font-size);\n color: var(--fx-text-default);\n }\n :host([hidden]) { display: none; }\n .icon { color: var(--_color); font-weight: bold; line-height: 1.4; }\n .content { flex: 1; }\n .title { font-weight: 600; }\n .body { margin-top: 2px; }\n .close {\n border: none; background: transparent; cursor: pointer;\n color: var(--fx-text-muted); font-size: calc(var(--fx-font-size) + 2px);\n line-height: 1; padding: 0; border-radius: var(--fx-radius-full);\n }\n .close:hover { color: var(--_color); }\n `;\n\n static override get observedAttributes(): string[] {\n return ['variant', 'title', 'dismissible'];\n }\n\n protected override render(): void {\n const variant = this.getAttr('variant', 'info');\n const title = this.getAttr('title');\n const icons: Record<string, string> = {\n info: 'ℹ', success: '✓', warning: '⚠', danger: '✕',\n };\n\n this.setTemplate(`\n <div class=\"alert\" part=\"alert\" role=\"alert\">\n <span class=\"icon\">${icons[variant] ?? 'ℹ'}</span>\n <div class=\"content\">\n ${title ? `<div class=\"title\">${title}</div>` : ''}\n <div class=\"body\"><slot></slot></div>\n </div>\n ${this.hasAttr('dismissible') ? '<button type=\"button\" class=\"close\" aria-label=\"Fechar\">×</button>' : ''}\n </div>\n `);\n\n this.root.querySelector('.close')?.addEventListener('click', () => {\n this.hidden = true;\n this.dispatchEvent(new CustomEvent('dismiss', { bubbles: true, composed: true }));\n });\n }\n}\n\nexport function defineFxAlert(): typeof FxAlert {\n return defineElement('fx-alert', FxAlert);\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"alert.js","sources":["../../../src/components/alert/alert.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-alert> — Aviso inline com variantes semânticas.\n *\n * Atributos: variant (info|success|warning|danger, padrão info), title, dismissible.\n * Slot padrão: conteúdo da mensagem. Evento `dismiss`.\n */\nexport class FxAlert extends FxElement {\n static override styles = css`\n :host {\n display: block;\n font-family: var(--fx-font-family);\n --_color: var(--fx-color-primary);\n --_bg: color-mix(in srgb, var(--fx-color-primary) 10%, var(--fx-surface-background));\n }\n :host([variant='info']) { --_color: var(--fx-color-info); --_bg: color-mix(in srgb, var(--fx-color-info) 10%, var(--fx-surface-background)); }\n :host([variant='success']) { --_color: var(--fx-color-success); --_bg: color-mix(in srgb, var(--fx-color-success) 10%, var(--fx-surface-background)); }\n :host([variant='warning']) { --_color: var(--fx-color-warning); --_bg: color-mix(in srgb, var(--fx-color-warning) 12%, var(--fx-surface-background)); }\n :host([variant='danger']) { --_color: var(--fx-color-danger); --_bg: color-mix(in srgb, var(--fx-color-danger) 10%, var(--fx-surface-background)); }\n .alert {\n display: flex;\n align-items: flex-start;\n gap: var(--fx-space-md);\n background: var(--_bg);\n border: 1px solid color-mix(in srgb, var(--_color) 30%, transparent);\n border-radius: var(--fx-radius-md);\n padding: var(--fx-space-md) var(--fx-space-lg);\n font-size: var(--fx-font-size);\n color: var(--fx-text-default);\n }\n :host([hidden]) { display: none; }\n .icon { color: var(--_color); font-weight: bold; line-height: 1.4; }\n .content { flex: 1; }\n .title { font-weight: 600; }\n .body { margin-top: 2px; }\n .close {\n border: none; background: transparent; cursor: pointer;\n color: var(--fx-text-muted); font-size: calc(var(--fx-font-size) + 2px);\n line-height: 1; padding: 0; border-radius: var(--fx-radius-full);\n }\n .close:hover { color: var(--_color); }\n `;\n\n static override get observedAttributes(): string[] {\n return ['variant', 'title', 'dismissible'];\n }\n\n protected override render(): void {\n const variant = this.getAttr('variant', 'info');\n const title = this.getAttr('title');\n const icons: Record<string, string> = {\n info: 'ℹ', success: '✓', warning: '⚠', danger: '✕',\n };\n\n this.setTemplate(`\n <div class=\"alert\" part=\"alert\" role=\"alert\">\n <span class=\"icon\">${icons[variant] ?? 'ℹ'}</span>\n <div class=\"content\">\n ${title ? `<div class=\"title\">${esc(title)}</div>` : ''}\n <div class=\"body\"><slot></slot></div>\n </div>\n ${this.hasAttr('dismissible') ? '<button type=\"button\" class=\"close\" aria-label=\"Fechar\">×</button>' : ''}\n </div>\n `);\n\n this.root.querySelector('.close')?.addEventListener('click', () => {\n this.hidden = true;\n this.dispatchEvent(new CustomEvent('dismiss', { bubbles: true, composed: true }));\n });\n }\n}\n\nexport function defineFxAlert(): typeof FxAlert {\n return defineElement('fx-alert', FxAlert);\n}\n"],"names":[],"mappings":";;;;AAWO,MAAM,WAAN,MAAM,iBAAgB,UAAU;AAAA,EAoCrC,WAAoB,qBAA+B;AACjD,WAAO,CAAC,WAAW,SAAS,aAAa;AAAA,EAC3C;AAAA,EAEmB,SAAe;AAChC,UAAM,UAAU,KAAK,QAAQ,WAAW,MAAM;AAC9C,UAAM,QAAQ,KAAK,QAAQ,OAAO;AAClC,UAAM,QAAgC;AAAA,MACpC,MAAM;AAAA,MAAK,SAAS;AAAA,MAAK,SAAS;AAAA,MAAK,QAAQ;AAAA,IAAA;AAGjD,SAAK,YAAY;AAAA;AAAA,6BAEQ,MAAM,OAAO,KAAK,GAAG;AAAA;AAAA,YAEtC,QAAQ,sBAAsB,IAAI,KAAK,CAAC,WAAW,EAAE;AAAA;AAAA;AAAA,UAGvD,KAAK,QAAQ,aAAa,IAAI,uEAAuE,EAAE;AAAA;AAAA,KAE5G;AAED,SAAK,KAAK,cAAc,QAAQ,GAAG,iBAAiB,SAAS,MAAM;AACjE,WAAK,SAAS;AACd,WAAK,cAAc,IAAI,YAAY,WAAW,EAAE,SAAS,MAAM,UAAU,KAAA,CAAM,CAAC;AAAA,IAClF,CAAC;AAAA,EACH;AACF;AA9DE,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;AADpB,IAAM,UAAN;AAiEA,SAAS,gBAAgC;AAC9C,SAAO,cAAc,YAAY,OAAO;AAC1C;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/alert/index.ts"],"sourcesContent":["import { FxAlert, defineFxAlert } from './alert';\n\nexport { FxAlert };\n\n\ndefineFxAlert();\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'fx-alert': FxAlert;\n }\n}\n\
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/alert/index.ts"],"sourcesContent":["import { FxAlert, defineFxAlert } from './alert';\n\nexport { FxAlert };\n\n\ndefineFxAlert();\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'fx-alert': FxAlert;\n }\n}\n\n"],"names":[],"mappings":";;AAKA,cAAA;"}
|
|
@@ -17,6 +17,9 @@ export declare class FxAutocomplete extends FxElement {
|
|
|
17
17
|
/** Setter necessário para o Vue (patchDOMProp seta `source` como
|
|
18
18
|
* propriedade, pois o getter existe no prototype). */
|
|
19
19
|
set source(value: string | string[]);
|
|
20
|
+
private docListener?;
|
|
21
|
+
protected connectedCallback(): void;
|
|
22
|
+
protected disconnectedCallback(): void;
|
|
20
23
|
protected render(): void;
|
|
21
24
|
}
|
|
22
25
|
export declare function defineFxAutocomplete(): typeof FxAutocomplete;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../../../src/components/autocomplete/autocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../../../src/components/autocomplete/autocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;;GAMG;AACH,qBAAa,cAAe,SAAQ,SAAS;IAC3C,OAAgB,MAAM,SA8DpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,IAAI,IAAI,IAAI,MAAM,CAGjB;IACD,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,EAAmC;IACrD,IAAI,KAAK,IAAI,MAAM,CAAkC;IACrD,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,EAAoC;IAEvD,IAAI,MAAM,IAAI,MAAM,EAAE,CAOrB;IACD;2DACuD;IACvD,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAElC;IAED,OAAO,CAAC,WAAW,CAAC,CAAqB;cAEtB,iBAAiB,IAAI,IAAI;cAQzB,oBAAoB,IAAI,IAAI;cAM5B,MAAM,IAAI,IAAI;CA6DlC;AAED,wBAAgB,oBAAoB,IAAI,OAAO,cAAc,CAE5D"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FxElement } from "../../core/base.js";
|
|
2
2
|
import { css } from "../../core/css.js";
|
|
3
3
|
import { defineElement } from "../../core/define.js";
|
|
4
|
+
import { esc } from "../../core/sanitize.js";
|
|
4
5
|
const _FxAutocomplete = class _FxAutocomplete extends FxElement {
|
|
5
6
|
static get observedAttributes() {
|
|
6
7
|
return ["size", "placeholder", "source", "disabled", "min-chars"];
|
|
@@ -31,11 +32,23 @@ const _FxAutocomplete = class _FxAutocomplete extends FxElement {
|
|
|
31
32
|
set source(value) {
|
|
32
33
|
this.setAttribute("source", typeof value === "string" ? value : JSON.stringify(value));
|
|
33
34
|
}
|
|
35
|
+
connectedCallback() {
|
|
36
|
+
super.connectedCallback();
|
|
37
|
+
this.docListener = (e) => {
|
|
38
|
+
if (!this.contains(e.target)) this.toggleAttr("open", false);
|
|
39
|
+
};
|
|
40
|
+
document.addEventListener("click", this.docListener);
|
|
41
|
+
}
|
|
42
|
+
disconnectedCallback() {
|
|
43
|
+
super.disconnectedCallback();
|
|
44
|
+
if (this.docListener) document.removeEventListener("click", this.docListener);
|
|
45
|
+
this.docListener = void 0;
|
|
46
|
+
}
|
|
34
47
|
render() {
|
|
35
48
|
const placeholder = this.getAttr("placeholder");
|
|
36
49
|
this.setTemplate(`
|
|
37
50
|
<input class="field" part="input" type="text"
|
|
38
|
-
${placeholder ? `placeholder="${placeholder}"` : ""} autocomplete="off"/>
|
|
51
|
+
${placeholder ? `placeholder="${esc(placeholder)}"` : ""} autocomplete="off"/>
|
|
39
52
|
<div class="list" part="list" role="listbox"></div>
|
|
40
53
|
`);
|
|
41
54
|
const field = this.root.querySelector(".field");
|
|
@@ -48,7 +61,7 @@ const _FxAutocomplete = class _FxAutocomplete extends FxElement {
|
|
|
48
61
|
if (!list) return;
|
|
49
62
|
const q = field.value.toLowerCase();
|
|
50
63
|
const matches = this.source.filter((s) => s.toLowerCase().includes(q)).slice(0, 8);
|
|
51
|
-
list.innerHTML = matches.length ? matches.map((m) => `<button type="button" class="opt" role="option" data-v="${m}">${m}</button>`).join("") : '<div class="empty">Nenhum resultado</div>';
|
|
64
|
+
list.innerHTML = matches.length ? matches.map((m) => `<button type="button" class="opt" role="option" data-v="${esc(m)}">${esc(m)}</button>`).join("") : '<div class="empty">Nenhum resultado</div>';
|
|
52
65
|
list.querySelectorAll(".opt").forEach((btn) => {
|
|
53
66
|
btn.addEventListener("click", () => {
|
|
54
67
|
field.value = btn.dataset.v ?? "";
|
|
@@ -70,8 +83,19 @@ const _FxAutocomplete = class _FxAutocomplete extends FxElement {
|
|
|
70
83
|
field.addEventListener("focus", () => {
|
|
71
84
|
if (field.value.length >= minChars) openList();
|
|
72
85
|
});
|
|
73
|
-
|
|
74
|
-
if (
|
|
86
|
+
field.addEventListener("keydown", (e) => {
|
|
87
|
+
if (e.key === "Escape") {
|
|
88
|
+
this.toggleAttr("open", false);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (e.key !== "ArrowDown" && e.key !== "ArrowUp") return;
|
|
92
|
+
e.preventDefault();
|
|
93
|
+
if (!this.hasAttr("open")) openList();
|
|
94
|
+
const opts = Array.from(this.root.querySelectorAll(".opt"));
|
|
95
|
+
if (!opts.length) return;
|
|
96
|
+
const current = opts.indexOf(this.root.activeElement);
|
|
97
|
+
const next = e.key === "ArrowDown" ? current === -1 ? 0 : Math.min(current + 1, opts.length - 1) : current === -1 ? opts.length - 1 : Math.max(current - 1, 0);
|
|
98
|
+
opts[next]?.focus();
|
|
75
99
|
});
|
|
76
100
|
}
|
|
77
101
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autocomplete.js","sources":["../../../src/components/autocomplete/autocomplete.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\n\n/**\n * <fx-autocomplete> — Campo de texto com sugestões filtradas.\n *\n * Atributos: value, size, placeholder, source (JSON array de strings),\n * disabled, min-chars (padrão 1).\n * Evento: `select` (composed, detail: { value }).\n */\nexport class FxAutocomplete extends FxElement {\n static override styles = css`\n :host {\n position: relative;\n display: inline-block;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n input {\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 padding: var(--fx-space-md) var(--fx-space-lg);\n width: 260px;\n min-height: var(--fx-size-md);\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 input::placeholder { color: var(--fx-text-muted); opacity: 1; }\n input:hover { border-color: var(--fx-border-hover); }\n input:focus-visible {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n :host([size='sm']) input { width: 220px; min-height: var(--fx-size-sm); padding: var(--fx-space-sm) var(--fx-space-md); }\n :host([size='lg']) input { width: 300px; min-height: var(--fx-size-lg); }\n .list {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n background: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n box-shadow: var(--fx-shadow-lg);\n z-index: var(--fx-z-dropdown, 1000);\n max-height: 220px;\n overflow-y: auto;\n display: none;\n }\n :host([open]) .list { display: block; }\n .opt {\n display: block;\n width: 100%;\n text-align: left;\n border: none;\n background: transparent;\n font-family: inherit;\n font-size: inherit;\n color: var(--fx-text-default);\n padding: var(--fx-space-sm) var(--fx-space-md);\n cursor: pointer;\n transition: background var(--fx-motion-duration-fast) var(--fx-motion-easing);\n }\n .opt:hover { background: color-mix(in srgb, var(--fx-color-primary) 12%, var(--fx-surface-background)); color: var(--fx-color-primary); }\n .empty { color: var(--fx-text-muted); font-size: calc(var(--fx-font-size) - 2px); padding: var(--fx-space-sm) var(--fx-space-md); }\n `;\n\n static override get observedAttributes(): string[] {\n return ['size', 'placeholder', 'source', 'disabled', 'min-chars'];\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) { this.setAttribute('size', v); }\n get value(): string { return this.getAttr('value'); }\n set value(v: string) { this.setAttribute('value', v); }\n\n get source(): string[] {\n try {\n const raw = JSON.parse(this.getAttr('source', '[]'));\n return Array.isArray(raw) ? raw.map(String) : [];\n } catch {\n return [];\n }\n }\n /** Setter necessário para o Vue (patchDOMProp seta `source` como\n * propriedade, pois o getter existe no prototype). */\n set source(value: string | string[]) {\n this.setAttribute('source', typeof value === 'string' ? value : JSON.stringify(value));\n }\n\n protected override render(): void {\n const placeholder = this.getAttr('placeholder');\n\n this.setTemplate(`\n <input class=\"field\" part=\"input\" type=\"text\"\n ${placeholder ? `placeholder=\"${placeholder}\"` : ''} autocomplete=\"off\"/>\n <div class=\"list\" part=\"list\" role=\"listbox\"></div>\n `);\n\n const field = this.root.querySelector<HTMLInputElement>('.field');\n if (!field) return;\n field.value = this.value;\n if (this.hasAttr('disabled')) field.setAttribute('disabled', '');\n\n const list = this.root.querySelector<HTMLElement>('.list');\n const minChars = Number(this.getAttr('min-chars', '1')) || 1;\n\n const openList = (): void => {\n if (!list) return;\n const q = field.value.toLowerCase();\n const matches = this.source.filter((s) => s.toLowerCase().includes(q)).slice(0, 8);\n list.innerHTML = matches.length\n ? matches.map((m) => `<button type=\"button\" class=\"opt\" role=\"option\" data-v=\"${m}\">${m}</button>`).join('')\n : '<div class=\"empty\">Nenhum resultado</div>';\n list.querySelectorAll<HTMLButtonElement>('.opt').forEach((btn) => {\n btn.addEventListener('click', () => {\n field.value = btn.dataset.v ?? '';\n this.value = field.value;\n this.toggleAttr('open', false);\n this.dispatchEvent(new CustomEvent('select', {\n bubbles: true, composed: true, detail: { value: this.value },\n }));\n });\n });\n this.toggleAttr('open', true);\n };\n\n // Reabrir com foco sem re-render (evita perder digitação)\n field.addEventListener('input', () => {\n this.value = field.value;\n openList();\n });\n field.addEventListener('focus', () => { if (field.value.length >= minChars) openList(); });\n\n document.addEventListener('click', (e) => {\n if (!this.contains(e.target as Node)) this.toggleAttr('open', false);\n });\n }\n}\n\nexport function defineFxAutocomplete(): typeof FxAutocomplete {\n return defineElement('fx-autocomplete', FxAutocomplete);\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"autocomplete.js","sources":["../../../src/components/autocomplete/autocomplete.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-autocomplete> — Campo de texto com sugestões filtradas.\n *\n * Atributos: value, size, placeholder, source (JSON array de strings),\n * disabled, min-chars (padrão 1).\n * Evento: `select` (composed, detail: { value }).\n */\nexport class FxAutocomplete extends FxElement {\n static override styles = css`\n :host {\n position: relative;\n display: inline-block;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n input {\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 padding: var(--fx-space-md) var(--fx-space-lg);\n width: 260px;\n min-height: var(--fx-size-md);\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 input::placeholder { color: var(--fx-text-muted); opacity: 1; }\n input:hover { border-color: var(--fx-border-hover); }\n input:focus-visible {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n :host([size='sm']) input { width: 220px; min-height: var(--fx-size-sm); padding: var(--fx-space-sm) var(--fx-space-md); }\n :host([size='lg']) input { width: 300px; min-height: var(--fx-size-lg); }\n .list {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n background: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n box-shadow: var(--fx-shadow-lg);\n z-index: var(--fx-z-dropdown, 1000);\n max-height: 220px;\n overflow-y: auto;\n display: none;\n }\n :host([open]) .list { display: block; }\n .opt {\n display: block;\n width: 100%;\n text-align: left;\n border: none;\n background: transparent;\n font-family: inherit;\n font-size: inherit;\n color: var(--fx-text-default);\n padding: var(--fx-space-sm) var(--fx-space-md);\n cursor: pointer;\n transition: background var(--fx-motion-duration-fast) var(--fx-motion-easing);\n }\n .opt:hover { background: color-mix(in srgb, var(--fx-color-primary) 12%, var(--fx-surface-background)); color: var(--fx-color-primary); }\n .empty { color: var(--fx-text-muted); font-size: calc(var(--fx-font-size) - 2px); padding: var(--fx-space-sm) var(--fx-space-md); }\n `;\n\n static override get observedAttributes(): string[] {\n return ['size', 'placeholder', 'source', 'disabled', 'min-chars'];\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) { this.setAttribute('size', v); }\n get value(): string { return this.getAttr('value'); }\n set value(v: string) { this.setAttribute('value', v); }\n\n get source(): string[] {\n try {\n const raw = JSON.parse(this.getAttr('source', '[]'));\n return Array.isArray(raw) ? raw.map(String) : [];\n } catch {\n return [];\n }\n }\n /** Setter necessário para o Vue (patchDOMProp seta `source` como\n * propriedade, pois o getter existe no prototype). */\n set source(value: string | string[]) {\n this.setAttribute('source', typeof value === 'string' ? value : JSON.stringify(value));\n }\n\n private docListener?: (e: Event) => void;\n\n protected override connectedCallback(): void {\n super.connectedCallback();\n this.docListener = (e: Event) => {\n if (!this.contains(e.target as Node)) this.toggleAttr('open', false);\n };\n document.addEventListener('click', this.docListener);\n }\n\n protected override disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.docListener) document.removeEventListener('click', this.docListener);\n this.docListener = undefined;\n }\n\n protected override render(): void {\n const placeholder = this.getAttr('placeholder');\n\n this.setTemplate(`\n <input class=\"field\" part=\"input\" type=\"text\"\n ${placeholder ? `placeholder=\"${esc(placeholder)}\"` : ''} autocomplete=\"off\"/>\n <div class=\"list\" part=\"list\" role=\"listbox\"></div>\n `);\n\n const field = this.root.querySelector<HTMLInputElement>('.field');\n if (!field) return;\n field.value = this.value;\n if (this.hasAttr('disabled')) field.setAttribute('disabled', '');\n\n const list = this.root.querySelector<HTMLElement>('.list');\n const minChars = Number(this.getAttr('min-chars', '1')) || 1;\n\n const openList = (): void => {\n if (!list) return;\n const q = field.value.toLowerCase();\n const matches = this.source.filter((s) => s.toLowerCase().includes(q)).slice(0, 8);\n list.innerHTML = matches.length\n ? matches.map((m) => `<button type=\"button\" class=\"opt\" role=\"option\" data-v=\"${esc(m)}\">${esc(m)}</button>`).join('')\n : '<div class=\"empty\">Nenhum resultado</div>';\n list.querySelectorAll<HTMLButtonElement>('.opt').forEach((btn) => {\n btn.addEventListener('click', () => {\n field.value = btn.dataset.v ?? '';\n this.value = field.value;\n this.toggleAttr('open', false);\n this.dispatchEvent(new CustomEvent('select', {\n bubbles: true, composed: true, detail: { value: this.value },\n }));\n });\n });\n this.toggleAttr('open', true);\n };\n\n // Reabrir com foco sem re-render (evita perder digitação)\n field.addEventListener('input', () => {\n this.value = field.value;\n openList();\n });\n field.addEventListener('focus', () => { if (field.value.length >= minChars) openList(); });\n // Navegação por teclado: setas movem o foco entre as sugestões; ESC fecha.\n field.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n this.toggleAttr('open', false);\n return;\n }\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp') return;\n e.preventDefault();\n if (!this.hasAttr('open')) openList();\n const opts = Array.from(this.root.querySelectorAll<HTMLButtonElement>('.opt'));\n if (!opts.length) return;\n const current = opts.indexOf(this.root.activeElement as HTMLButtonElement);\n const next = e.key === 'ArrowDown'\n ? (current === -1 ? 0 : Math.min(current + 1, opts.length - 1))\n : (current === -1 ? opts.length - 1 : Math.max(current - 1, 0));\n opts[next]?.focus();\n });\n }\n}\n\nexport function defineFxAutocomplete(): typeof FxAutocomplete {\n return defineElement('fx-autocomplete', FxAutocomplete);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/autocomplete/index.ts"],"sourcesContent":["import { FxAutocomplete, defineFxAutocomplete } from './autocomplete';\n\nexport { FxAutocomplete };\n\n\ndefineFxAutocomplete();\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'fx-autocomplete': FxAutocomplete;\n }\n}\n\
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/autocomplete/index.ts"],"sourcesContent":["import { FxAutocomplete, defineFxAutocomplete } from './autocomplete';\n\nexport { FxAutocomplete };\n\n\ndefineFxAutocomplete();\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'fx-autocomplete': FxAutocomplete;\n }\n}\n\n"],"names":[],"mappings":";;AAKA,qBAAA;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datepicker.d.ts","sourceRoot":"","sources":["../../../src/components/datepicker/datepicker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"datepicker.d.ts","sourceRoot":"","sources":["../../../src/components/datepicker/datepicker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,YAAa,SAAQ,SAAS;IACzC,OAAgB,MAAM,SA+IpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,OAAO,CAAC,WAAW,CAAC,CAAqB;IACzC,6CAA6C;IAC7C,OAAO,CAAC,IAAI,CAAwB;IAEpC,IAAI,IAAI,IAAI,MAAM,CAGjB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAErB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,EAElB;IAED,gDAAgD;IAChD,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;cAEkB,iBAAiB,IAAI,IAAI;cAWzB,oBAAoB,IAAI,IAAI;IAK/C,wFAAwF;IACxF,OAAO,CAAC,UAAU;IAyBlB,8CAA8C;IAC9C,OAAO,CAAC,WAAW;IAoBnB,iDAAiD;IACjD,OAAO,CAAC,QAAQ;IAKhB,sDAAsD;IACtD,OAAO,CAAC,iBAAiB;IAQzB,+DAA+D;IAC/D,OAAO,CAAC,QAAQ;cAOG,MAAM,IAAI,IAAI;IAqJjC,OAAO,CAAC,UAAU;IAMlB;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAgClB,8DAA8D;IAC9D,OAAO,CAAC,WAAW;CAkCpB;AAED,wBAAgB,kBAAkB,IAAI,OAAO,YAAY,CAExD"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FxElement } from "../../core/base.js";
|
|
2
2
|
import { css } from "../../core/css.js";
|
|
3
3
|
import { defineElement } from "../../core/define.js";
|
|
4
|
+
import { esc } from "../../core/sanitize.js";
|
|
4
5
|
const _FxDatepicker = class _FxDatepicker extends FxElement {
|
|
5
6
|
constructor() {
|
|
6
7
|
super(...arguments);
|
|
@@ -103,21 +104,21 @@ const _FxDatepicker = class _FxDatepicker extends FxElement {
|
|
|
103
104
|
const hasValue = text.length > 0;
|
|
104
105
|
const showTime = this.hasAttr("show-time");
|
|
105
106
|
this.loadTimeFromValue();
|
|
106
|
-
let calAttrs = `min="${this.getAttr("min")}" max="${this.getAttr("max")}"`;
|
|
107
|
+
let calAttrs = `min="${esc(this.getAttr("min"))}" max="${esc(this.getAttr("max"))}"`;
|
|
107
108
|
if (this.mode === "range") {
|
|
108
|
-
calAttrs += ` range start="${this.getAttr("start")}" end="${this.getAttr("end")}"`;
|
|
109
|
+
calAttrs += ` range start="${esc(this.getAttr("start"))}" end="${esc(this.getAttr("end"))}"`;
|
|
109
110
|
} else if (this.mode === "multiple") {
|
|
110
111
|
const dates = this.values.map((v) => v.split("T")[0]).join(",");
|
|
111
|
-
calAttrs += ` mode="multiple" values="${dates}"`;
|
|
112
|
+
calAttrs += ` mode="multiple" values="${esc(dates)}"`;
|
|
112
113
|
} else {
|
|
113
114
|
const v = this.value.split("T")[0] ?? "";
|
|
114
|
-
calAttrs += ` value="${v}"`;
|
|
115
|
+
calAttrs += ` value="${esc(v)}"`;
|
|
115
116
|
}
|
|
116
117
|
this.setTemplate(`
|
|
117
118
|
<div class="field" part="field">
|
|
118
119
|
<input class="display" part="display" type="text" ${this.hasAttr("free-text") && !disabled ? "" : "readonly"}
|
|
119
|
-
placeholder="${this.getAttr("placeholder", "dd/mm/aaaa")}"
|
|
120
|
-
value="${text}" ${disabled ? "disabled" : ""}>
|
|
120
|
+
placeholder="${esc(this.getAttr("placeholder", "dd/mm/aaaa"))}"
|
|
121
|
+
value="${esc(text)}" ${disabled ? "disabled" : ""}>
|
|
121
122
|
<button type="button" class="clear" part="clear" aria-label="Limpar"
|
|
122
123
|
${clearable && hasValue ? "" : "hidden"}>
|
|
123
124
|
×
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datepicker.js","sources":["../../../src/components/datepicker/datepicker.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\n\n/**\n * <fx-datepicker> — Campo de data com calendário suspenso.\n *\n * Um input com ícone de calendário no final; ao clicar, abre o\n * <fx-calendar> em um popover. As datas selecionadas aparecem no input.\n *\n * Atributos:\n * - mode=\"single\" | \"range\" | \"multiple\" (padrão: single)\n * - value=\"YYYY-MM-DD\" → single\n * - start/end → range\n * - values=\"a,b,c\" → múltiplas datas (CSV)\n * - min/max, placeholder, disabled, clearable, size (sm|md|lg)\n * - format=\"dd/mm/yyyy\" → máscara de exibição (tokens: dd mm yyyy, HH MM SS)\n * - show-time → inclui seleção de hora:minuto:segundo no popover;\n * o valor passa a ser \"YYYY-MM-DDTHH:mm:ss\"\n *\n * Evento: `change` (composed):\n * - single: { value }\n * - range: { value, start, end }\n * - multiple: { values: string[] }\n */\nexport class FxDatepicker extends FxElement {\n static override styles = css`\n :host {\n display: inline-block;\n vertical-align: middle;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n position: relative;\n }\n .field {\n display: inline-flex;\n align-items: center;\n gap: var(--fx-space-xs);\n width: 100%;\n box-sizing: border-box;\n /* Base = tamanho padrão (md): 40px */\n min-height: var(--fx-size-md, 40px);\n min-width: 150px;\n padding: var(--fx-space-xs) var(--fx-space-md);\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 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 :host([size='sm']) .field { min-height: 32px; min-width: 180px; }\n :host([size='md']) .field { min-height: 40px; }\n :host([size='lg']) .field { min-height: 48px; min-width: 220px; font-size: calc(var(--fx-font-size) + 4px); }\n /* Range e multiple exibem mais de uma data: campo mais largo */\n :host([mode='range']) .field { min-width: 250px; }\n :host([mode='multiple']) .field { min-width: 220px; }\n :host([mode='range'][size='lg']) .field { min-width: 360px; }\n :host([mode='multiple'][size='lg']) .field { min-width: 320px; }\n :host([show-time]) .field { min-width: 250px; }\n /* Validação */\n :host([error]) .field,\n :host([invalid]) .field {\n border-color: var(--fx-color-danger, #dc2626);\n }\n :host([error]) .field:focus-within,\n :host([invalid]) .field:focus-within,\n :host([error][open]) .field,\n :host([invalid][open]) .field {\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 border-color: var(--fx-color-success, #16a34a);\n }\n :host([success]) .field:focus-within,\n :host([valid]) .field:focus-within,\n :host([success][open]) .field,\n :host([valid][open]) .field {\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 .field:hover { border-color: var(--fx-border-hover); }\n .field:focus-within {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n .display {\n flex: 1;\n border: none;\n background: none;\n font: inherit;\n color: var(--fx-text-default);\n outline: none;\n cursor: pointer;\n text-align: left;\n padding: 0;\n min-width: 0;\n }\n .display::placeholder { color: var(--fx-text-muted); }\n .cal-icon { color: var(--fx-text-muted); display: inline-flex; pointer-events: none; }\n .clear {\n border: none;\n background: none;\n color: var(--fx-text-muted);\n cursor: pointer;\n font-size: calc(var(--fx-font-size) + 4px);\n line-height: 1;\n padding: 0 2px;\n border-radius: var(--fx-radius-full);\n }\n .clear:hover { color: var(--fx-color-danger); }\n .clear[hidden] { display: none; }\n .pop {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n z-index: var(--fx-z-dropdown, 1000);\n display: none;\n background: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n box-shadow: var(--fx-shadow-lg);\n overflow: hidden;\n }\n :host([up]) .pop {\n top: auto;\n bottom: calc(100% + 4px);\n }\n :host([open]) .pop { display: block; }\n .time-row {\n display: flex;\n align-items: center;\n gap: var(--fx-space-xs);\n padding: var(--fx-space-sm) var(--fx-space-md);\n border-top: 1px solid var(--fx-border-default);\n background: var(--fx-surface-background);\n border-radius: 0 0 var(--fx-radius-md) var(--fx-radius-md);\n font-size: calc(var(--fx-font-size) - 2px);\n color: var(--fx-text-default);\n }\n .time-row label { color: var(--fx-text-muted); }\n .time-row input {\n width: 38px;\n font: inherit;\n color: var(--fx-text-default);\n background: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-sm);\n padding: 2px 2px;\n outline: none;\n text-align: center;\n -moz-appearance: textfield;\n appearance: textfield;\n }\n .time-row input::-webkit-outer-spin-button,\n .time-row input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }\n .time-row .sep { color: var(--fx-text-muted); font-weight: bold; padding: 0 1px; }\n .time-row input:focus {\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n :host([disabled]) .field { opacity: 0.55; cursor: not-allowed; background: var(--fx-surface-surface-hover); }\n :host([disabled]) .display { cursor: not-allowed; }\n :host([free-text]) .display { cursor: text; }\n :host([free-text]) .display.invalid { border-bottom: 2px solid var(--fx-color-danger); }\n `;\n\n static override get observedAttributes(): string[] {\n return ['value', 'start', 'end', 'values', 'mode', 'min', 'max', 'placeholder', 'disabled', 'format', 'show-time', 'free-text'];\n }\n\n private docListener?: (e: Event) => void;\n /** Hora/minuto/segundo do modo show-time. */\n private time = { h: 0, m: 0, s: 0 };\n\n get mode(): string {\n const m = this.getAttr('mode', 'single');\n return ['single', 'range', 'multiple'].includes(m) ? m : 'single';\n }\n set mode(value: string) {\n this.setAttribute('mode', value);\n }\n\n get value(): string {\n return this.getAttr('value');\n }\n set value(v: string) {\n this.setAttribute('value', v);\n }\n\n /** Datas do modo múltiplo (CSV no atributo). */\n get values(): string[] {\n const csv = this.getAttr('values');\n return csv ? csv.split(',').map((v) => v.trim()).filter(Boolean) : [];\n }\n set values(list: string[]) {\n this.setAttribute('values', list.join(','));\n }\n\n 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 connectedCallback(): void {\n super.connectedCallback();\n // Fecha o popover ao clicar fora.\n this.docListener = (e: Event) => {\n if (!this.hasAttr('open')) return;\n if (e.composedPath().includes(this)) return;\n this.removeAttribute('open');\n };\n document.addEventListener('click', this.docListener);\n }\n\n protected override disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.docListener) document.removeEventListener('click', this.docListener);\n }\n\n /** Formata uma data ISO (\"YYYY-MM-DD\" ou com \"THH:mm:ss\") segundo o atributo format. */\n private formatDate(iso: string): string {\n if (!iso) return '';\n const fmt = this.getAttr('format');\n // Sem máscara: exibe apenas a parte da data (a hora entra via timeText\n // quando show-time está ativo — nunca duplicada).\n if (!fmt) return iso.split('T')[0]!;\n const [datePart, timePart] = iso.split('T');\n const [y = '', m = '', d = ''] = datePart.split('-');\n const [H = '00', M = '00', S = '00'] = (timePart ?? '').split(':');\n // Placeholders para evitar colisão entre mm (mês) e MM (minuto).\n return fmt\n .replace(/yyyy/gi, '\\u0001')\n .replace(/MM/g, '\\u0005')\n .replace(/mm/g, '\\u0002')\n .replace(/dd/gi, '\\u0003')\n .replace(/HH/g, '\\u0004')\n .replace(/SS/gi, '\\u0006')\n .replace(/\\u0001/g, y)\n .replace(/\\u0002/g, m)\n .replace(/\\u0003/g, d)\n .replace(/\\u0004/g, H)\n .replace(/\\u0005/g, M)\n .replace(/\\u0006/g, S);\n }\n\n /** Texto exibido no input conforme o modo. */\n private displayText(): string {\n if (this.mode === 'range') {\n const s = this.getAttr('start');\n const e = this.getAttr('end');\n const arrow = this.hasAttr('show-time') ? ' ' : ' → ';\n if (!s && !e) return '';\n if (this.hasAttr('show-time')) {\n const f = (iso?: string): string => (iso ? `${this.formatDate(iso)} ${this.timeText()}` : iso ? `${this.formatDate(iso)} …` : '');\n return s && e ? `${f(s)} → ${f(e)}` : f(s);\n }\n void arrow;\n return s && e ? `${this.formatDate(s)} → ${this.formatDate(e)}` : s ? `${this.formatDate(s)} → …` : '';\n }\n if (this.mode === 'multiple') {\n return this.values.map((v) => this.formatDate(v)).join(', ');\n }\n const base = this.formatDate(this.value);\n return base && this.hasAttr('show-time') ? `${base} ${this.timeText()}` : base;\n }\n\n /** \"HH:MM:SS\" do estado interno de show-time. */\n private timeText(): string {\n const p = (n: number): string => String(n).padStart(2, '0');\n return `${p(this.time.h)}:${p(this.time.m)}:${p(this.time.s)}`;\n }\n\n /** Extrai hora de um valor ISO inicial, se houver. */\n private loadTimeFromValue(): void {\n const src = this.value || this.getAttr('start') || '';\n const t = src.split('T')[1];\n if (!t) return;\n const [h, m, s] = t.split(':').map((n) => parseInt(n, 10));\n this.time = { h: h || 0, m: m || 0, s: s || 0 };\n }\n\n /** Anexa o horário interno ao ISO puro vindo do calendário. */\n private withTime(iso: string): string {\n if (!iso) return iso;\n return this.hasAttr('show-time')\n ? `${iso}T${this.timeText()}`\n : iso;\n }\n\n protected override render(): void {\n const disabled = this.disabled;\n const clearable = this.hasAttr('clearable');\n const text = this.displayText();\n const hasValue = text.length > 0;\n const showTime = this.hasAttr('show-time');\n this.loadTimeFromValue();\n\n // Atributos repassados ao calendário interno, conforme o modo.\n let calAttrs = `min=\"${this.getAttr('min')}\" max=\"${this.getAttr('max')}\"`;\n if (this.mode === 'range') {\n calAttrs += ` range start=\"${this.getAttr('start')}\" end=\"${this.getAttr('end')}\"`;\n } else if (this.mode === 'multiple') {\n // Repassa apenas as partes de data (sem hora) para o calendário pintar.\n const dates = this.values.map((v) => v.split('T')[0]).join(',');\n calAttrs += ` mode=\"multiple\" values=\"${dates}\"`;\n } else {\n const v = this.value.split('T')[0] ?? '';\n calAttrs += ` value=\"${v}\"`;\n }\n\n this.setTemplate(`\n <div class=\"field\" part=\"field\">\n <input class=\"display\" part=\"display\" type=\"text\" ${this.hasAttr('free-text') && !disabled ? '' : 'readonly'}\n placeholder=\"${this.getAttr('placeholder', 'dd/mm/aaaa')}\"\n value=\"${text}\" ${disabled ? 'disabled' : ''}>\n <button type=\"button\" class=\"clear\" part=\"clear\" aria-label=\"Limpar\"\n ${clearable && hasValue ? '' : 'hidden'}>\n ×\n </button>\n <span class=\"cal-icon\" part=\"icon\" aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\"/>\n <path d=\"M16 2v4M8 2v4M3 10h18\"/>\n </svg>\n </span>\n </div>\n <div class=\"pop\" part=\"popover\">\n <fx-calendar ${calAttrs}></fx-calendar>\n ${\n showTime\n ? `<div class=\"time-row\" part=\"time\">\n <input class=\"t-h\" type=\"number\" min=\"0\" max=\"23\" value=\"${this.time.h}\" aria-label=\"Hora\"><span class=\"sep\">:</span>\n <input class=\"t-m\" type=\"number\" min=\"0\" max=\"59\" value=\"${this.time.m}\" aria-label=\"Minuto\"><span class=\"sep\">:</span>\n <input class=\"t-s\" type=\"number\" min=\"0\" max=\"59\" value=\"${this.time.s}\" aria-label=\"Segundo\">\n </div>`\n : ''\n }\n </div>\n `);\n\n const field = this.root.querySelector('.field');\n if (!field) return;\n if (disabled) return;\n\n field.addEventListener('click', (e) => {\n if ((e.target as HTMLElement).closest('.clear')) return;\n // Com free-text, clicar no próprio input serve para digitar — não abre.\n if (this.hasAttr('free-text') && (e.target as HTMLElement).classList.contains('display')) return;\n this.toggleAttribute('open');\n // Flip vertical: se não cabe abaixo, abre para cima.\n if (this.hasAttr('open')) {\n const r = this.getBoundingClientRect();\n this.toggleAttribute('up', r.bottom + 340 > window.innerHeight && r.top > 340);\n } else {\n this.removeAttribute('up');\n }\n });\n\n // Limpar: zera tudo conforme o modo.\n this.root.querySelector('.clear')?.addEventListener('click', (e) => {\n e.stopPropagation();\n this.removeAttribute('value');\n this.removeAttribute('start');\n this.removeAttribute('end');\n this.removeAttribute('values');\n this.removeAttribute('open');\n this.render();\n this.emitChange({});\n });\n\n // Sincroniza seleção do calendário de volta para os atributos.\n const cal = this.root.querySelector<HTMLElement>('.pop fx-calendar');\n cal?.addEventListener('change', (e) => {\n const d = (e as CustomEvent).detail ?? {};\n if (d.start !== undefined || d.end !== undefined) {\n if (d.start) this.setAttribute('start', this.withTime(d.start));\n else this.removeAttribute('start');\n if (d.end) this.setAttribute('end', this.withTime(d.end));\n else this.removeAttribute('end');\n }\n if (d.values !== undefined) {\n this.values = d.values.map((v: string) => this.withTime(v));\n }\n if (d.value !== undefined) {\n if (d.value) this.setAttribute('value', this.withTime(d.value));\n else this.removeAttribute('value');\n // No modo single, fecha ao escolher.\n if (this.mode === 'single') this.removeAttribute('open');\n }\n this.render();\n this.emitChange(d);\n });\n\n // free-text: valida ao sair do campo ou pressionar Enter.\n const display = this.root.querySelector<HTMLInputElement>('.display');\n if (display && this.hasAttr('free-text') && !disabled) {\n display.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this.commitTyped(display);\n }\n });\n display.addEventListener('blur', () => this.commitTyped(display));\n }\n\n // show-time: captura alterações de hora/minuto/segundo.\n if (showTime) {\n const applyTime = (): void => {\n const h = this.root.querySelector<HTMLInputElement>('.t-h');\n const m = this.root.querySelector<HTMLInputElement>('.t-m');\n const s = this.root.querySelector<HTMLInputElement>('.t-s');\n const clamp = (v: string | undefined, max: number): number =>\n Math.min(max, Math.max(0, parseInt(v ?? '0', 10) || 0));\n this.time = {\n h: clamp(h?.value, 23),\n m: clamp(m?.value, 59),\n s: clamp(s?.value, 59),\n };\n // Reanexa o horário aos valores já selecionados.\n const reattach = (iso: string): string => iso.split('T')[0] ? `${iso.split('T')[0]}T${this.timeText()}` : iso;\n if (this.value) this.setAttribute('value', reattach(this.value));\n if (this.getAttr('start')) this.setAttribute('start', reattach(this.getAttr('start')));\n if (this.getAttr('end')) this.setAttribute('end', reattach(this.getAttr('end')));\n if (this.values.length) {\n this.values = this.values.map((v) => reattach(v));\n }\n // Atualiza apenas o texto do input, sem re-render completo.\n const display = this.root.querySelector<HTMLInputElement>('.display');\n if (display) display.value = this.displayText();\n this.emitChange({ value: this.value });\n };\n ['.t-h', '.t-m', '.t-s'].forEach((sel) => {\n this.root.querySelector(sel)?.addEventListener('input', applyTime);\n });\n }\n }\n\n private emitChange(detail: Record<string, unknown>): void {\n this.dispatchEvent(\n new CustomEvent('change', { bubbles: true, composed: true, detail }),\n );\n }\n\n /**\n * Interpreta o texto digitado livremente e devolve ISO \"YYYY-MM-DD\"\n * (ou null se inválido). Aceita a máscara do atributo `format`\n * (tokens dd/mm/yyyy) ou ISO direto.\n */\n private parseTyped(raw: string): string | null {\n const text = raw.trim();\n if (!text) return null;\n const fmt = this.getAttr('format', 'dd/mm/yyyy').toLowerCase();\n\n // Ordem dos tokens conforme a máscara informada.\n const order = ['dd', 'mm', 'yyyy'].filter((t) => fmt.includes(t));\n if (order.length < 3) return null;\n\n const parts = text.split(new RegExp(`[^0-9]+`)).filter(Boolean);\n if (parts.length !== 3) return null;\n\n const map: Record<string, string> = {};\n order.forEach((t, i) => (map[t] = parts[i]!));\n const iso = `${map['yyyy']}-${(map['mm'] ?? '').padStart(2, '0')}-${(map['dd'] ?? '').padStart(2, '0')}`;\n\n // Validação de data real.\n const d = new Date(`${iso}T12:00:00`);\n if (Number.isNaN(d.getTime())) return null;\n const [y, m, day] = iso.split('-').map((n) => parseInt(n, 10));\n if (d.getFullYear() !== y || d.getMonth() + 1 !== m || d.getDate() !== day) return null;\n\n // Limites min/max (apenas a parte da data).\n const cmp = (a: string, b: string): number => a.split('T')[0]!.localeCompare(b.split('T')[0]!);\n const min = this.getAttr('min');\n const max = this.getAttr('max');\n if (min && cmp(iso, min) < 0) return null;\n if (max && cmp(iso, max) > 0) return null;\n\n return iso;\n }\n\n /** Aplica o texto digitado no modo free-text (blur/Enter). */\n private commitTyped(input: HTMLInputElement): void {\n const parsed = this.parseTyped(input.value);\n if (!parsed) {\n // Inválido: sinaliza, reverte o texto e emite evento.\n input.classList.add('invalid');\n this.dispatchEvent(\n new CustomEvent('invalid', { bubbles: true, composed: true, detail: { text: input.value } }),\n );\n input.value = this.displayText();\n setTimeout(() => input.classList.remove('invalid'), 1500);\n return;\n }\n if (this.mode === 'single') {\n this.setAttribute('value', this.withTime(parsed));\n this.emitChange({ value: this.value });\n } else if (this.mode === 'range') {\n // Primeira digitação vira start; com start preenchido, vira end.\n if (!this.getAttr('start') || (this.getAttr('start') && this.getAttr('end'))) {\n this.setAttribute('start', this.withTime(parsed));\n this.removeAttribute('end');\n } else {\n const [a, b] = [this.getAttr('start')!.split('T')[0]!, parsed].sort();\n this.setAttribute('start', this.withTime(a));\n this.setAttribute('end', this.withTime(b));\n }\n this.emitChange({ start: this.getAttr('start'), end: this.getAttr('end') });\n } else {\n const list = this.values.filter((v) => v.split('T')[0] !== parsed);\n list.push(this.withTime(parsed));\n this.values = list;\n this.emitChange({ values: this.values });\n }\n this.render();\n }\n}\n\nexport function defineFxDatepicker(): typeof FxDatepicker {\n return defineElement('fx-datepicker', FxDatepicker);\n}\n\n"],"names":["display"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"datepicker.js","sources":["../../../src/components/datepicker/datepicker.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-datepicker> — Campo de data com calendário suspenso.\n *\n * Um input com ícone de calendário no final; ao clicar, abre o\n * <fx-calendar> em um popover. As datas selecionadas aparecem no input.\n *\n * Atributos:\n * - mode=\"single\" | \"range\" | \"multiple\" (padrão: single)\n * - value=\"YYYY-MM-DD\" → single\n * - start/end → range\n * - values=\"a,b,c\" → múltiplas datas (CSV)\n * - min/max, placeholder, disabled, clearable, size (sm|md|lg)\n * - format=\"dd/mm/yyyy\" → máscara de exibição (tokens: dd mm yyyy, HH MM SS)\n * - show-time → inclui seleção de hora:minuto:segundo no popover;\n * o valor passa a ser \"YYYY-MM-DDTHH:mm:ss\"\n *\n * Evento: `change` (composed):\n * - single: { value }\n * - range: { value, start, end }\n * - multiple: { values: string[] }\n */\nexport class FxDatepicker extends FxElement {\n static override styles = css`\n :host {\n display: inline-block;\n vertical-align: middle;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n position: relative;\n }\n .field {\n display: inline-flex;\n align-items: center;\n gap: var(--fx-space-xs);\n width: 100%;\n box-sizing: border-box;\n /* Base = tamanho padrão (md): 40px */\n min-height: var(--fx-size-md, 40px);\n min-width: 150px;\n padding: var(--fx-space-xs) var(--fx-space-md);\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 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 :host([size='sm']) .field { min-height: 32px; min-width: 180px; }\n :host([size='md']) .field { min-height: 40px; }\n :host([size='lg']) .field { min-height: 48px; min-width: 220px; font-size: calc(var(--fx-font-size) + 4px); }\n /* Range e multiple exibem mais de uma data: campo mais largo */\n :host([mode='range']) .field { min-width: 250px; }\n :host([mode='multiple']) .field { min-width: 220px; }\n :host([mode='range'][size='lg']) .field { min-width: 360px; }\n :host([mode='multiple'][size='lg']) .field { min-width: 320px; }\n :host([show-time]) .field { min-width: 250px; }\n /* Validação */\n :host([error]) .field,\n :host([invalid]) .field {\n border-color: var(--fx-color-danger, #dc2626);\n }\n :host([error]) .field:focus-within,\n :host([invalid]) .field:focus-within,\n :host([error][open]) .field,\n :host([invalid][open]) .field {\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 border-color: var(--fx-color-success, #16a34a);\n }\n :host([success]) .field:focus-within,\n :host([valid]) .field:focus-within,\n :host([success][open]) .field,\n :host([valid][open]) .field {\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 .field:hover { border-color: var(--fx-border-hover); }\n .field:focus-within {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n .display {\n flex: 1;\n border: none;\n background: none;\n font: inherit;\n color: var(--fx-text-default);\n outline: none;\n cursor: pointer;\n text-align: left;\n padding: 0;\n min-width: 0;\n }\n .display::placeholder { color: var(--fx-text-muted); }\n .cal-icon { color: var(--fx-text-muted); display: inline-flex; pointer-events: none; }\n .clear {\n border: none;\n background: none;\n color: var(--fx-text-muted);\n cursor: pointer;\n font-size: calc(var(--fx-font-size) + 4px);\n line-height: 1;\n padding: 0 2px;\n border-radius: var(--fx-radius-full);\n }\n .clear:hover { color: var(--fx-color-danger); }\n .clear[hidden] { display: none; }\n .pop {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n z-index: var(--fx-z-dropdown, 1000);\n display: none;\n background: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n box-shadow: var(--fx-shadow-lg);\n overflow: hidden;\n }\n :host([up]) .pop {\n top: auto;\n bottom: calc(100% + 4px);\n }\n :host([open]) .pop { display: block; }\n .time-row {\n display: flex;\n align-items: center;\n gap: var(--fx-space-xs);\n padding: var(--fx-space-sm) var(--fx-space-md);\n border-top: 1px solid var(--fx-border-default);\n background: var(--fx-surface-background);\n border-radius: 0 0 var(--fx-radius-md) var(--fx-radius-md);\n font-size: calc(var(--fx-font-size) - 2px);\n color: var(--fx-text-default);\n }\n .time-row label { color: var(--fx-text-muted); }\n .time-row input {\n width: 38px;\n font: inherit;\n color: var(--fx-text-default);\n background: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-sm);\n padding: 2px 2px;\n outline: none;\n text-align: center;\n -moz-appearance: textfield;\n appearance: textfield;\n }\n .time-row input::-webkit-outer-spin-button,\n .time-row input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }\n .time-row .sep { color: var(--fx-text-muted); font-weight: bold; padding: 0 1px; }\n .time-row input:focus {\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n :host([disabled]) .field { opacity: 0.55; cursor: not-allowed; background: var(--fx-surface-surface-hover); }\n :host([disabled]) .display { cursor: not-allowed; }\n :host([free-text]) .display { cursor: text; }\n :host([free-text]) .display.invalid { border-bottom: 2px solid var(--fx-color-danger); }\n `;\n\n static override get observedAttributes(): string[] {\n return ['value', 'start', 'end', 'values', 'mode', 'min', 'max', 'placeholder', 'disabled', 'format', 'show-time', 'free-text'];\n }\n\n private docListener?: (e: Event) => void;\n /** Hora/minuto/segundo do modo show-time. */\n private time = { h: 0, m: 0, s: 0 };\n\n get mode(): string {\n const m = this.getAttr('mode', 'single');\n return ['single', 'range', 'multiple'].includes(m) ? m : 'single';\n }\n set mode(value: string) {\n this.setAttribute('mode', value);\n }\n\n get value(): string {\n return this.getAttr('value');\n }\n set value(v: string) {\n this.setAttribute('value', v);\n }\n\n /** Datas do modo múltiplo (CSV no atributo). */\n get values(): string[] {\n const csv = this.getAttr('values');\n return csv ? csv.split(',').map((v) => v.trim()).filter(Boolean) : [];\n }\n set values(list: string[]) {\n this.setAttribute('values', list.join(','));\n }\n\n 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 connectedCallback(): void {\n super.connectedCallback();\n // Fecha o popover ao clicar fora.\n this.docListener = (e: Event) => {\n if (!this.hasAttr('open')) return;\n if (e.composedPath().includes(this)) return;\n this.removeAttribute('open');\n };\n document.addEventListener('click', this.docListener);\n }\n\n protected override disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.docListener) document.removeEventListener('click', this.docListener);\n }\n\n /** Formata uma data ISO (\"YYYY-MM-DD\" ou com \"THH:mm:ss\") segundo o atributo format. */\n private formatDate(iso: string): string {\n if (!iso) return '';\n const fmt = this.getAttr('format');\n // Sem máscara: exibe apenas a parte da data (a hora entra via timeText\n // quando show-time está ativo — nunca duplicada).\n if (!fmt) return iso.split('T')[0]!;\n const [datePart, timePart] = iso.split('T');\n const [y = '', m = '', d = ''] = datePart.split('-');\n const [H = '00', M = '00', S = '00'] = (timePart ?? '').split(':');\n // Placeholders para evitar colisão entre mm (mês) e MM (minuto).\n return fmt\n .replace(/yyyy/gi, '\\u0001')\n .replace(/MM/g, '\\u0005')\n .replace(/mm/g, '\\u0002')\n .replace(/dd/gi, '\\u0003')\n .replace(/HH/g, '\\u0004')\n .replace(/SS/gi, '\\u0006')\n .replace(/\\u0001/g, y)\n .replace(/\\u0002/g, m)\n .replace(/\\u0003/g, d)\n .replace(/\\u0004/g, H)\n .replace(/\\u0005/g, M)\n .replace(/\\u0006/g, S);\n }\n\n /** Texto exibido no input conforme o modo. */\n private displayText(): string {\n if (this.mode === 'range') {\n const s = this.getAttr('start');\n const e = this.getAttr('end');\n const arrow = this.hasAttr('show-time') ? ' ' : ' → ';\n if (!s && !e) return '';\n if (this.hasAttr('show-time')) {\n const f = (iso?: string): string => (iso ? `${this.formatDate(iso)} ${this.timeText()}` : iso ? `${this.formatDate(iso)} …` : '');\n return s && e ? `${f(s)} → ${f(e)}` : f(s);\n }\n void arrow;\n return s && e ? `${this.formatDate(s)} → ${this.formatDate(e)}` : s ? `${this.formatDate(s)} → …` : '';\n }\n if (this.mode === 'multiple') {\n return this.values.map((v) => this.formatDate(v)).join(', ');\n }\n const base = this.formatDate(this.value);\n return base && this.hasAttr('show-time') ? `${base} ${this.timeText()}` : base;\n }\n\n /** \"HH:MM:SS\" do estado interno de show-time. */\n private timeText(): string {\n const p = (n: number): string => String(n).padStart(2, '0');\n return `${p(this.time.h)}:${p(this.time.m)}:${p(this.time.s)}`;\n }\n\n /** Extrai hora de um valor ISO inicial, se houver. */\n private loadTimeFromValue(): void {\n const src = this.value || this.getAttr('start') || '';\n const t = src.split('T')[1];\n if (!t) return;\n const [h, m, s] = t.split(':').map((n) => parseInt(n, 10));\n this.time = { h: h || 0, m: m || 0, s: s || 0 };\n }\n\n /** Anexa o horário interno ao ISO puro vindo do calendário. */\n private withTime(iso: string): string {\n if (!iso) return iso;\n return this.hasAttr('show-time')\n ? `${iso}T${this.timeText()}`\n : iso;\n }\n\n protected override render(): void {\n const disabled = this.disabled;\n const clearable = this.hasAttr('clearable');\n const text = this.displayText();\n const hasValue = text.length > 0;\n const showTime = this.hasAttr('show-time');\n this.loadTimeFromValue();\n\n // Atributos repassados ao calendário interno, conforme o modo.\n let calAttrs = `min=\"${esc(this.getAttr('min'))}\" max=\"${esc(this.getAttr('max'))}\"`;\n if (this.mode === 'range') {\n calAttrs += ` range start=\"${esc(this.getAttr('start'))}\" end=\"${esc(this.getAttr('end'))}\"`;\n } else if (this.mode === 'multiple') {\n // Repassa apenas as partes de data (sem hora) para o calendário pintar.\n const dates = this.values.map((v) => v.split('T')[0]).join(',');\n calAttrs += ` mode=\"multiple\" values=\"${esc(dates)}\"`;\n } else {\n const v = this.value.split('T')[0] ?? '';\n calAttrs += ` value=\"${esc(v)}\"`;\n }\n\n this.setTemplate(`\n <div class=\"field\" part=\"field\">\n <input class=\"display\" part=\"display\" type=\"text\" ${this.hasAttr('free-text') && !disabled ? '' : 'readonly'}\n placeholder=\"${esc(this.getAttr('placeholder', 'dd/mm/aaaa'))}\"\n value=\"${esc(text)}\" ${disabled ? 'disabled' : ''}>\n <button type=\"button\" class=\"clear\" part=\"clear\" aria-label=\"Limpar\"\n ${clearable && hasValue ? '' : 'hidden'}>\n ×\n </button>\n <span class=\"cal-icon\" part=\"icon\" aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\"/>\n <path d=\"M16 2v4M8 2v4M3 10h18\"/>\n </svg>\n </span>\n </div>\n <div class=\"pop\" part=\"popover\">\n <fx-calendar ${calAttrs}></fx-calendar>\n ${\n showTime\n ? `<div class=\"time-row\" part=\"time\">\n <input class=\"t-h\" type=\"number\" min=\"0\" max=\"23\" value=\"${this.time.h}\" aria-label=\"Hora\"><span class=\"sep\">:</span>\n <input class=\"t-m\" type=\"number\" min=\"0\" max=\"59\" value=\"${this.time.m}\" aria-label=\"Minuto\"><span class=\"sep\">:</span>\n <input class=\"t-s\" type=\"number\" min=\"0\" max=\"59\" value=\"${this.time.s}\" aria-label=\"Segundo\">\n </div>`\n : ''\n }\n </div>\n `);\n\n const field = this.root.querySelector('.field');\n if (!field) return;\n if (disabled) return;\n\n field.addEventListener('click', (e) => {\n if ((e.target as HTMLElement).closest('.clear')) return;\n // Com free-text, clicar no próprio input serve para digitar — não abre.\n if (this.hasAttr('free-text') && (e.target as HTMLElement).classList.contains('display')) return;\n this.toggleAttribute('open');\n // Flip vertical: se não cabe abaixo, abre para cima.\n if (this.hasAttr('open')) {\n const r = this.getBoundingClientRect();\n this.toggleAttribute('up', r.bottom + 340 > window.innerHeight && r.top > 340);\n } else {\n this.removeAttribute('up');\n }\n });\n\n // Limpar: zera tudo conforme o modo.\n this.root.querySelector('.clear')?.addEventListener('click', (e) => {\n e.stopPropagation();\n this.removeAttribute('value');\n this.removeAttribute('start');\n this.removeAttribute('end');\n this.removeAttribute('values');\n this.removeAttribute('open');\n this.render();\n this.emitChange({});\n });\n\n // Sincroniza seleção do calendário de volta para os atributos.\n const cal = this.root.querySelector<HTMLElement>('.pop fx-calendar');\n cal?.addEventListener('change', (e) => {\n const d = (e as CustomEvent).detail ?? {};\n if (d.start !== undefined || d.end !== undefined) {\n if (d.start) this.setAttribute('start', this.withTime(d.start));\n else this.removeAttribute('start');\n if (d.end) this.setAttribute('end', this.withTime(d.end));\n else this.removeAttribute('end');\n }\n if (d.values !== undefined) {\n this.values = d.values.map((v: string) => this.withTime(v));\n }\n if (d.value !== undefined) {\n if (d.value) this.setAttribute('value', this.withTime(d.value));\n else this.removeAttribute('value');\n // No modo single, fecha ao escolher.\n if (this.mode === 'single') this.removeAttribute('open');\n }\n this.render();\n this.emitChange(d);\n });\n\n // free-text: valida ao sair do campo ou pressionar Enter.\n const display = this.root.querySelector<HTMLInputElement>('.display');\n if (display && this.hasAttr('free-text') && !disabled) {\n display.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this.commitTyped(display);\n }\n });\n display.addEventListener('blur', () => this.commitTyped(display));\n }\n\n // show-time: captura alterações de hora/minuto/segundo.\n if (showTime) {\n const applyTime = (): void => {\n const h = this.root.querySelector<HTMLInputElement>('.t-h');\n const m = this.root.querySelector<HTMLInputElement>('.t-m');\n const s = this.root.querySelector<HTMLInputElement>('.t-s');\n const clamp = (v: string | undefined, max: number): number =>\n Math.min(max, Math.max(0, parseInt(v ?? '0', 10) || 0));\n this.time = {\n h: clamp(h?.value, 23),\n m: clamp(m?.value, 59),\n s: clamp(s?.value, 59),\n };\n // Reanexa o horário aos valores já selecionados.\n const reattach = (iso: string): string => iso.split('T')[0] ? `${iso.split('T')[0]}T${this.timeText()}` : iso;\n if (this.value) this.setAttribute('value', reattach(this.value));\n if (this.getAttr('start')) this.setAttribute('start', reattach(this.getAttr('start')));\n if (this.getAttr('end')) this.setAttribute('end', reattach(this.getAttr('end')));\n if (this.values.length) {\n this.values = this.values.map((v) => reattach(v));\n }\n // Atualiza apenas o texto do input, sem re-render completo.\n const display = this.root.querySelector<HTMLInputElement>('.display');\n if (display) display.value = this.displayText();\n this.emitChange({ value: this.value });\n };\n ['.t-h', '.t-m', '.t-s'].forEach((sel) => {\n this.root.querySelector(sel)?.addEventListener('input', applyTime);\n });\n }\n }\n\n private emitChange(detail: Record<string, unknown>): void {\n this.dispatchEvent(\n new CustomEvent('change', { bubbles: true, composed: true, detail }),\n );\n }\n\n /**\n * Interpreta o texto digitado livremente e devolve ISO \"YYYY-MM-DD\"\n * (ou null se inválido). Aceita a máscara do atributo `format`\n * (tokens dd/mm/yyyy) ou ISO direto.\n */\n private parseTyped(raw: string): string | null {\n const text = raw.trim();\n if (!text) return null;\n const fmt = this.getAttr('format', 'dd/mm/yyyy').toLowerCase();\n\n // Ordem dos tokens conforme a máscara informada.\n const order = ['dd', 'mm', 'yyyy'].filter((t) => fmt.includes(t));\n if (order.length < 3) return null;\n\n const parts = text.split(new RegExp(`[^0-9]+`)).filter(Boolean);\n if (parts.length !== 3) return null;\n\n const map: Record<string, string> = {};\n order.forEach((t, i) => (map[t] = parts[i]!));\n const iso = `${map['yyyy']}-${(map['mm'] ?? '').padStart(2, '0')}-${(map['dd'] ?? '').padStart(2, '0')}`;\n\n // Validação de data real.\n const d = new Date(`${iso}T12:00:00`);\n if (Number.isNaN(d.getTime())) return null;\n const [y, m, day] = iso.split('-').map((n) => parseInt(n, 10));\n if (d.getFullYear() !== y || d.getMonth() + 1 !== m || d.getDate() !== day) return null;\n\n // Limites min/max (apenas a parte da data).\n const cmp = (a: string, b: string): number => a.split('T')[0]!.localeCompare(b.split('T')[0]!);\n const min = this.getAttr('min');\n const max = this.getAttr('max');\n if (min && cmp(iso, min) < 0) return null;\n if (max && cmp(iso, max) > 0) return null;\n\n return iso;\n }\n\n /** Aplica o texto digitado no modo free-text (blur/Enter). */\n private commitTyped(input: HTMLInputElement): void {\n const parsed = this.parseTyped(input.value);\n if (!parsed) {\n // Inválido: sinaliza, reverte o texto e emite evento.\n input.classList.add('invalid');\n this.dispatchEvent(\n new CustomEvent('invalid', { bubbles: true, composed: true, detail: { text: input.value } }),\n );\n input.value = this.displayText();\n setTimeout(() => input.classList.remove('invalid'), 1500);\n return;\n }\n if (this.mode === 'single') {\n this.setAttribute('value', this.withTime(parsed));\n this.emitChange({ value: this.value });\n } else if (this.mode === 'range') {\n // Primeira digitação vira start; com start preenchido, vira end.\n if (!this.getAttr('start') || (this.getAttr('start') && this.getAttr('end'))) {\n this.setAttribute('start', this.withTime(parsed));\n this.removeAttribute('end');\n } else {\n const [a, b] = [this.getAttr('start')!.split('T')[0]!, parsed].sort();\n this.setAttribute('start', this.withTime(a));\n this.setAttribute('end', this.withTime(b));\n }\n this.emitChange({ start: this.getAttr('start'), end: this.getAttr('end') });\n } else {\n const list = this.values.filter((v) => v.split('T')[0] !== parsed);\n list.push(this.withTime(parsed));\n this.values = list;\n this.emitChange({ values: this.values });\n }\n this.render();\n }\n}\n\nexport function defineFxDatepicker(): typeof FxDatepicker {\n return defineElement('fx-datepicker', FxDatepicker);\n}\n\n"],"names":["display"],"mappings":"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"}
|
|
@@ -13,6 +13,10 @@ export declare class FxDialog extends FxElement {
|
|
|
13
13
|
set open(value: boolean);
|
|
14
14
|
protected render(): void;
|
|
15
15
|
private _cleanup?;
|
|
16
|
+
private _previouslyFocused;
|
|
17
|
+
/** Mantém o foco dentro do modal (WCAG 2.4.3 / 2.1.2). */
|
|
18
|
+
private _trapFocus;
|
|
19
|
+
private _restoreFocus;
|
|
16
20
|
disconnectedCallback(): void;
|
|
17
21
|
}
|
|
18
22
|
export declare function defineFxDialog(): typeof FxDialog;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../src/components/dialog/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../src/components/dialog/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;;GAMG;AACH,qBAAa,QAAS,SAAQ,SAAS;IACrC,OAAgB,MAAM,SAqEpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,IAAI,IAAI,IAAI,OAAO,CAAiC;IACpD,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAAqC;cAEzC,MAAM,IAAI,IAAI;IA8CjC,OAAO,CAAC,QAAQ,CAAC,CAAa;IAC9B,OAAO,CAAC,kBAAkB,CAA4B;IAEtD,0DAA0D;IAC1D,OAAO,CAAC,UAAU;IAmBlB,OAAO,CAAC,aAAa;IAKZ,oBAAoB,IAAI,IAAI;CAMtC;AAED,wBAAgB,cAAc,IAAI,OAAO,QAAQ,CAEhD"}
|