@wrrdev/fenix-ui 1.1.5 → 1.1.7
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 +77 -2
- package/dist/components/autocomplete/autocomplete.d.ts.map +1 -1
- package/dist/components/autocomplete/autocomplete.js +16 -7
- package/dist/components/autocomplete/autocomplete.js.map +1 -1
- package/dist/components/button/button.d.ts.map +1 -1
- package/dist/components/button/button.js +7 -5
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/card/card.d.ts +2 -1
- package/dist/components/card/card.d.ts.map +1 -1
- package/dist/components/card/card.js +5 -2
- package/dist/components/card/card.js.map +1 -1
- package/dist/components/datepicker/datepicker.d.ts.map +1 -1
- package/dist/components/datepicker/datepicker.js +11 -6
- package/dist/components/datepicker/datepicker.js.map +1 -1
- package/dist/components/fileupload/fileupload.d.ts +1 -1
- package/dist/components/fileupload/fileupload.d.ts.map +1 -1
- package/dist/components/fileupload/fileupload.js +10 -3
- package/dist/components/fileupload/fileupload.js.map +1 -1
- package/dist/components/icon/icon.d.ts +40 -0
- package/dist/components/icon/icon.d.ts.map +1 -0
- package/dist/components/icon/index.d.ts +8 -0
- package/dist/components/icon/index.d.ts.map +1 -0
- package/dist/components/input/input.d.ts +3 -0
- package/dist/components/input/input.d.ts.map +1 -1
- package/dist/components/input/input.js +24 -8
- package/dist/components/input/input.js.map +1 -1
- package/dist/components/knob/knob.d.ts +1 -1
- package/dist/components/knob/knob.d.ts.map +1 -1
- package/dist/components/knob/knob.js +3 -1
- package/dist/components/knob/knob.js.map +1 -1
- package/dist/components/multiselect/multiselect.d.ts.map +1 -1
- package/dist/components/multiselect/multiselect.js +17 -6
- package/dist/components/multiselect/multiselect.js.map +1 -1
- package/dist/components/orderlist/orderlist.js +2 -2
- package/dist/components/orderlist/orderlist.js.map +1 -1
- package/dist/components/picklist/picklist.js +2 -2
- package/dist/components/picklist/picklist.js.map +1 -1
- package/dist/components/select/select.d.ts.map +1 -1
- package/dist/components/select/select.js +18 -5
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/textarea/textarea.d.ts.map +1 -1
- package/dist/components/textarea/textarea.js +16 -5
- package/dist/components/textarea/textarea.js.map +1 -1
- package/dist/components/toggle-button-group/toggle-button-group.d.ts.map +1 -1
- package/dist/components/toggle-button-group/toggle-button-group.js +3 -1
- package/dist/components/toggle-button-group/toggle-button-group.js.map +1 -1
- package/dist/core/jsx.d.ts +233 -29
- package/dist/core/jsx.d.ts.map +1 -1
- package/dist/core/jsx.js.map +1 -1
- package/dist/core/presets.js +1 -1
- package/dist/core/presets.js.map +1 -1
- package/dist/core/react.d.ts +20 -0
- package/dist/core/react.d.ts.map +1 -0
- package/dist/core/react.js +5 -0
- package/dist/core/react.js.map +1 -0
- package/dist/core/theme.d.ts.map +1 -1
- package/dist/core/theme.js +12 -0
- package/dist/core/theme.js.map +1 -1
- package/dist/core/tokens.d.ts +4 -0
- package/dist/core/tokens.d.ts.map +1 -1
- package/dist/core/tokens.js +9 -1
- package/dist/core/tokens.js.map +1 -1
- package/dist/core/vue.d.ts +47 -2
- package/dist/core/vue.d.ts.map +1 -1
- package/dist/core/vue.js.map +1 -1
- package/dist/docs/app.d.ts +6 -0
- package/dist/docs/app.d.ts.map +1 -1
- package/dist/docs/componentes/autocomplete.doc.d.ts.map +1 -1
- package/dist/docs/componentes/card.doc.d.ts.map +1 -1
- package/dist/docs/componentes/icon.doc.d.ts +9 -0
- package/dist/docs/componentes/icon.doc.d.ts.map +1 -0
- package/dist/docs/componentes/index.d.ts.map +1 -1
- package/dist/docs/componentes/input.doc.d.ts.map +1 -1
- package/dist/docs/componentes/multiselect.doc.d.ts.map +1 -1
- package/dist/docs/componentes/select.doc.d.ts.map +1 -1
- package/dist/docs/componentes/textarea.doc.d.ts.map +1 -1
- package/dist/fenix-ui.esm.js +2 -2
- package/dist/fenix-ui.esm.js.map +1 -1
- package/dist/fenix-ui.umd.min.js +296 -215
- package/dist/fenix-ui2.esm.js +2 -4321
- package/dist/fenix-ui2.esm.js.map +1 -1
- package/dist/fenix-ui3.esm.js +4338 -10616
- package/dist/fenix-ui3.esm.js.map +1 -1
- package/dist/fenix-ui4.esm.js +10724 -104
- package/dist/fenix-ui4.esm.js.map +1 -1
- package/dist/fenix-ui5.esm.js +111 -0
- package/dist/fenix-ui5.esm.js.map +1 -0
- package/dist/icons/font.d.ts +26 -0
- package/dist/icons/font.d.ts.map +1 -0
- package/dist/icons/font.js +42 -0
- package/dist/icons/font.js.map +1 -0
- package/dist/icons/index.d.ts +3 -1
- package/dist/icons/index.d.ts.map +1 -1
- package/dist/icons/index.js +11 -13
- package/dist/icons/index.js.map +1 -1
- package/dist/icons/name-union.d.ts +11 -0
- package/dist/icons/name-union.d.ts.map +1 -0
- package/dist/icons/names.d.ts +0 -1
- package/dist/icons/names.d.ts.map +1 -1
- package/dist/icons/names.js.map +1 -1
- package/dist/icons/types.d.ts +14 -0
- package/dist/icons/types.d.ts.map +1 -0
- package/dist/plugins/auto-import.d.ts.map +1 -1
- package/dist/plugins/auto-import.js +1 -0
- package/dist/plugins/auto-import.js.map +1 -1
- package/package.json +10 -5
|
@@ -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';\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 /* Full width: o host estica até o pai (os min-width dos modos são\n descartados para permitir layouts estreitos sob controle do pai). */\n :host([full]) { display: block; width: 100%; }\n :host([full]) .field { min-width: 0; }\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', 'error', 'invalid', 'success', 'valid'];\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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"}
|
|
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 /* Altura determinística: a caixa fica EXATAMENTE no token --fx-size-*. */\n line-height: var(--fx-font-line-height);\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: var(--fx-size-sm); min-width: 180px; }\n :host([size='md']) .field { min-height: var(--fx-size-md); }\n :host([size='lg']) .field { min-height: var(--fx-size-lg); 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 /* Full width: o host estica até o pai (os min-width dos modos são\n descartados para permitir layouts estreitos sob controle do pai). */\n :host([full]) { display: block; width: 100%; }\n :host([full]) .field { min-width: 0; }\n /* Validação — borda e brilho JÁ EM REPOUSO (igual ao fx-input); o brilho\n segue o token --fx-effect-error-ring, que acompanha effect.focus-ring. */\n :host([error]) .field,\n :host([invalid]) .field {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([error]) .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: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([success]) .field,\n :host([valid]) .field {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));\n }\n :host([success]) .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: var(--fx-effect-success-ring, 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', 'error', 'invalid', 'success', 'valid'];\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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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FxElement } from '../../core/base';
|
|
2
2
|
/**
|
|
3
|
-
* <fx-fileupload> — Seletor de arquivos com upload e progresso
|
|
3
|
+
* <fx-fileupload> — Seletor de arquivos com upload e progresso.
|
|
4
4
|
*
|
|
5
5
|
* Atributos:
|
|
6
6
|
* - mode (basic|advanced — `basic`: botão; `advanced`: dropzone com drag & drop);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileupload.d.ts","sourceRoot":"","sources":["../../../src/components/fileupload/fileupload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,YAAa,SAAQ,SAAS;IACzC,OAAgB,MAAM,
|
|
1
|
+
{"version":3,"file":"fileupload.d.ts","sourceRoot":"","sources":["../../../src/components/fileupload/fileupload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,YAAa,SAAQ,SAAS;IACzC,OAAgB,MAAM,SA4IpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,IAAI,IAAI,IAAI,MAAM,CAGjB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAAuC;IAE7D,4DAA4D;IAC5D,IAAI,KAAK,IAAI,MAAM,CAAkC;IACrD,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,EAAoC;IAEvD,IAAI,QAAQ,IAAI,MAAM,CAAmF;IACzG,IAAI,QAAQ,CAAC,CAAC,EAAE,MAAM,EAA+C;IAErE,4DAA4D;IAC5D,IAAI,KAAK,IAAI,IAAI,EAAE,CAAwB;IAC3C,IAAI,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,EAItB;cAEkB,MAAM,IAAI,IAAI;IA6CjC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,KAAK,CAAS;IAEtB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,WAAW;IAyBnB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,QAAQ;IAMhB,kFAAkF;IAClF,OAAO,CAAC,cAAc;CAyBvB;AAED,wBAAgB,kBAAkB,IAAI,OAAO,YAAY,CAExD"}
|
|
@@ -161,11 +161,16 @@ _FxFileUpload.styles = css`
|
|
|
161
161
|
align-items: center;
|
|
162
162
|
justify-content: center;
|
|
163
163
|
gap: var(--fx-space-sm);
|
|
164
|
+
/* Largura acompanha o host: CSS externo/classe/inline no elemento esticam
|
|
165
|
+
o botão sem precisar do full (host é shrink-to-fit por padrão). */
|
|
166
|
+
width: 100%;
|
|
164
167
|
min-height: var(--fx-size-md);
|
|
165
|
-
|
|
168
|
+
/* Padding vertical no orçamento do token --fx-size-* ⇒ altura padrão. */
|
|
169
|
+
padding: var(--fx-space-sm) var(--fx-space-lg);
|
|
166
170
|
font-family: inherit;
|
|
167
171
|
font-size: inherit;
|
|
168
172
|
font-weight: var(--fx-font-weight);
|
|
173
|
+
line-height: var(--fx-font-line-height);
|
|
169
174
|
color: var(--fx-text-default);
|
|
170
175
|
background-color: var(--fx-surface-background);
|
|
171
176
|
border: 1px solid var(--fx-border-default);
|
|
@@ -192,8 +197,8 @@ _FxFileUpload.styles = css`
|
|
|
192
197
|
:host([severity='info']) .btn { background: var(--fx-color-info); border-color: transparent; color: #fff; }
|
|
193
198
|
:host([severity]) .btn:hover { filter: brightness(0.88); }
|
|
194
199
|
:host([severity]) .btn:focus-visible { border-color: transparent; }
|
|
195
|
-
:host([size='sm']) .btn { min-height: var(--fx-size-sm); padding: var(--fx-space-
|
|
196
|
-
:host([size='lg']) .btn { min-height: var(--fx-size-lg); padding: var(--fx-space-
|
|
200
|
+
:host([size='sm']) .btn { min-height: var(--fx-size-sm); padding: var(--fx-space-xs) var(--fx-space-md); font-size: calc(var(--fx-font-size) - 2px); }
|
|
201
|
+
:host([size='lg']) .btn { min-height: var(--fx-size-lg); padding: var(--fx-space-sm) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); }
|
|
197
202
|
:host([size='sm']) .drop { min-height: 72px; }
|
|
198
203
|
:host([size='lg']) .drop { min-height: 132px; }
|
|
199
204
|
|
|
@@ -204,6 +209,8 @@ _FxFileUpload.styles = css`
|
|
|
204
209
|
align-items: center;
|
|
205
210
|
justify-content: center;
|
|
206
211
|
gap: var(--fx-space-sm);
|
|
212
|
+
/* Acompanha a largura do host (definida por CSS externo/classe/inline). */
|
|
213
|
+
width: 100%;
|
|
207
214
|
min-height: 100px;
|
|
208
215
|
padding: var(--fx-space-lg);
|
|
209
216
|
border: 2px dashed var(--fx-border-default);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileupload.js","sources":["../../../src/components/fileupload/fileupload.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\nimport { FENIX_ICON_BASE_CSS, fenixIconHtml } from '../../icons/base-css';\n\n/**\n * <fx-fileupload> — Seletor de arquivos com upload e progresso (estilo FileUpload do PrimeVue).\n *\n * Atributos:\n * - mode (basic|advanced — `basic`: botão; `advanced`: dropzone com drag & drop);\n * - size (sm|md|lg, padrão md);\n * - severity (primary|secondary|success|warning|danger|info — cor do botão no modo basic);\n * - label (texto do botão/área, padrão 'Escolher arquivo');\n * - icon (glifo/emoji exibido antes do texto — sem o atributo, sem ícone);\n * - accept, multiple, disabled (como no <input type=\"file\">);\n * - show-progress (exibe barra + % de upload);\n * - progress (0-100 — o consumidor atualiza durante o upload real);\n * - value (nome(s) do(s) arquivo(s) carregado(s), somente leitura/espelho).\n *\n * Eventos (composed): `select` (detail: { files: File[] }), `remove`, `complete`.\n */\nexport class FxFileUpload extends FxElement {\n static override styles = css`\n :host {\n display: inline-block;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n :host([disabled]) { opacity: 0.55; pointer-events: none; }\n input[type='file'] { display: none; }\n\n /* ---- botão (basic) ---- */\n .btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--fx-space-sm);\n min-height: var(--fx-size-md);\n padding: var(--fx-space-md) var(--fx-space-lg);\n font-family: inherit;\n font-size: inherit;\n font-weight: var(--fx-font-weight);\n color: var(--fx-text-default);\n background-color: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n cursor: pointer;\n box-sizing: border-box;\n transition:\n border-color var(--fx-motion-duration-normal) var(--fx-motion-easing),\n box-shadow var(--fx-motion-duration-normal) var(--fx-motion-easing),\n background var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .btn:hover { border-color: var(--fx-border-hover); background: var(--fx-surface-surface-hover, rgba(0,0,0,0.03)); }\n .btn:focus-visible {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n /* Severities (como no <fx-button>) — aplicam-se ao botão do modo basic */\n :host([severity='primary']) .btn { background: var(--fx-color-primary); border-color: transparent; color: #fff; }\n :host([severity='secondary']) .btn { background: var(--fx-color-secondary); border-color: transparent; color: #fff; }\n :host([severity='success']) .btn { background: var(--fx-color-success); border-color: transparent; color: #fff; }\n :host([severity='warning']) .btn { background: var(--fx-color-warning); border-color: transparent; color: #fff; }\n :host([severity='danger']) .btn { background: var(--fx-color-danger); border-color: transparent; color: #fff; }\n :host([severity='info']) .btn { background: var(--fx-color-info); border-color: transparent; color: #fff; }\n :host([severity]) .btn:hover { filter: brightness(0.88); }\n :host([severity]) .btn:focus-visible { border-color: transparent; }\n :host([size='sm']) .btn { min-height: var(--fx-size-sm); padding: var(--fx-space-sm) var(--fx-space-md); font-size: calc(var(--fx-font-size) - 2px); }\n :host([size='lg']) .btn { min-height: var(--fx-size-lg); padding: var(--fx-space-lg) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); }\n :host([size='sm']) .drop { min-height: 72px; }\n :host([size='lg']) .drop { min-height: 132px; }\n\n /* ---- dropzone (advanced) ---- */\n .drop {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--fx-space-sm);\n min-height: 100px;\n padding: var(--fx-space-lg);\n border: 2px dashed var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n color: var(--fx-text-muted);\n cursor: pointer;\n text-align: center;\n transition: border-color var(--fx-motion-duration-normal) var(--fx-motion-easing), background var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .drop:hover, .drop.over {\n border-color: var(--fx-color-primary);\n background: color-mix(in srgb, var(--fx-color-primary) 6%, transparent);\n }\n .drop .icon { font-size: calc(var(--fx-font-size) + 12px); line-height: 1; }\n .drop .hint { font-size: calc(var(--fx-font-size) - 2px); }\n\n /* ---- ícone comum ---- */\n .icon { line-height: 1; }\n\n /* ---- arquivo(s) selecionado(s) ---- */\n .files { display: flex; flex-direction: column; gap: var(--fx-space-xs); margin-top: var(--fx-space-sm); }\n .file {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm);\n padding: var(--fx-space-xs) var(--fx-space-sm);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-sm);\n font-size: calc(var(--fx-font-size) - 2px);\n color: var(--fx-text-default);\n }\n .file .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .file .size { color: var(--fx-text-muted); white-space: nowrap; }\n .file .remove {\n border: none;\n background: transparent;\n color: var(--fx-text-muted);\n cursor: pointer;\n font-size: calc(var(--fx-font-size) + 2px);\n line-height: 1;\n padding: 0 var(--fx-space-xs);\n border-radius: var(--fx-radius-full);\n }\n .file .remove:hover { color: var(--fx-color-danger); }\n\n /* ---- progresso ---- */\n .progress-row { display: flex; align-items: center; gap: var(--fx-space-sm); margin-top: var(--fx-space-sm); }\n .track {\n flex: 1;\n height: 6px;\n background: var(--fx-surface-surface-hover);\n border-radius: var(--fx-radius-full);\n overflow: hidden;\n }\n .bar {\n height: 100%;\n width: 0%;\n background: var(--fx-color-primary);\n border-radius: var(--fx-radius-full);\n transition: width var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n :host([progress='100']) .bar { background: var(--fx-color-success); }\n .pct {\n font-size: calc(var(--fx-font-size) - 2px);\n font-weight: 600;\n color: var(--fx-text-default);\n min-width: 34px;\n text-align: right;\n }\n /* Full width: o host estica até o pai e o botão/dropzone acompanha. */\n :host([full]) { display: block; width: 100%; }\n :host([full]) .btn { width: 100%; }\n :host([full]) .drop { width: 100%; }\n /* Base dos glifos Fenix Icons (o @font-face vem de @wrrdev/fenix-ui/icons). */\n ${FENIX_ICON_BASE_CSS}\n `;\n\n static override get observedAttributes(): string[] {\n return ['mode', 'size', 'severity', 'label', 'icon', 'accept', 'multiple', 'disabled', 'show-progress', 'progress', 'value', 'full'];\n }\n\n get size(): string {\n const s = this.getAttr('size', 'md');\n return s === 'sm' || s === 'lg' ? s : 'md';\n }\n set size(value: string) { this.setAttribute('size', value); }\n\n /** Nomes dos arquivos selecionados (espelho em `value`). */\n get value(): string { return this.getAttr('value'); }\n set value(v: string) { this.setAttribute('value', v); }\n\n get progress(): number { return Math.min(100, Math.max(0, Number(this.getAttr('progress', '0')) || 0)); }\n set progress(v: number) { this.setAttribute('progress', String(v)); }\n\n /** Arquivos selecionados (não serializável em atributo). */\n get files(): File[] { return this._files; }\n set files(files: File[]) {\n this._files = Array.from(files);\n this.value = this._files.map((f) => f.name).join(', ');\n this._syncFilesArea();\n }\n\n protected override render(): void {\n const mode = this.getAttr('mode', 'basic');\n const advanced = mode === 'advanced';\n const label = this.getAttr('label', 'Escolher arquivo');\n const icon = this.getAttr('icon');\n const accept = this.getAttr('accept');\n const multiple = this.hasAttr('multiple');\n const disabled = this.hasAttr('disabled');\n const showProgress = this.hasAttr('show-progress');\n const pct = this.progress;\n\n const fileInput = `<input type=\"file\" class=\"picker\" ${accept ? `accept=\"${esc(accept)}\"` : ''} ${multiple ? 'multiple' : ''} ${disabled ? 'disabled' : ''} />`;\n\n this.setTemplate(`\n ${advanced\n ? `<div class=\"drop\" part=\"dropzone\" role=\"button\" tabindex=\"0\" aria-label=\"${esc(label)}\">\n ${icon ? `<span class=\"icon\" part=\"icon\" aria-hidden=\"true\">${fenixIconHtml(icon)}</span>` : ''}\n <span>${esc(label)}</span>\n <span class=\"hint\">ou arraste e solte aqui</span>\n </div>`\n : `<button type=\"button\" class=\"btn\" part=\"button\">\n ${icon ? `<span class=\"icon\" part=\"icon\" aria-hidden=\"true\">${fenixIconHtml(icon)}</span>` : ''}\n <span>${esc(label)}</span>\n </button>`}\n ${fileInput}\n <div class=\"files\" part=\"files\"></div>\n ${showProgress ? `\n <div class=\"progress-row\" part=\"progress\">\n <div class=\"track\" role=\"progressbar\" aria-valuenow=\"${pct}\" aria-valuemin=\"0\" aria-valuemax=\"100\">\n <div class=\"bar\" style=\"width: ${pct}%\"></div>\n </div>\n <span class=\"pct\">${pct}%</span>\n </div>` : ''}\n `);\n\n this._bindPicker();\n this._syncFilesArea();\n\n if (!this._done && showProgress && pct >= 100 && this._files.length) {\n this._done = true;\n this.dispatchEvent(new CustomEvent('complete', { bubbles: true, composed: true }));\n }\n if (pct < 100) this._done = false;\n }\n\n private _files: File[] = [];\n private _done = false;\n\n private _picker(): HTMLInputElement | null {\n return this.root.querySelector<HTMLInputElement>('.picker');\n }\n\n private _bindPicker(): void {\n const picker = this._picker();\n if (!picker) return;\n const trigger = this.root.querySelector('.btn') ?? this.root.querySelector('.drop');\n trigger?.addEventListener('click', () => picker.click());\n trigger?.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter' || (e as KeyboardEvent).key === ' ') {\n e.preventDefault();\n picker.click();\n }\n });\n picker.addEventListener('change', () => this._acceptFiles(picker.files ?? []));\n\n // drag & drop (advanced)\n const drop = this.root.querySelector<HTMLElement>('.drop');\n if (!drop) return;\n drop.addEventListener('dragover', (e) => { e.preventDefault(); drop.classList.add('over'); });\n drop.addEventListener('dragleave', () => drop.classList.remove('over'));\n drop.addEventListener('drop', (e) => {\n e.preventDefault();\n drop.classList.remove('over');\n if (e.dataTransfer?.files.length) this._acceptFiles(e.dataTransfer.files);\n });\n }\n\n private _acceptFiles(list: FileList | File[]): void {\n const picked = this.hasAttr('multiple') ? Array.from(list) : [list[0]].filter(Boolean);\n this.files = picked;\n const picker = this._picker();\n if (picker) picker.value = '';\n this.dispatchEvent(\n new CustomEvent('select', { bubbles: true, composed: true, detail: { files: picked } }),\n );\n }\n\n private _fmtSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n }\n\n /** Renderiza a lista de arquivos sem re-renderizar o template (mantém estado). */\n private _syncFilesArea(): void {\n const area = this.root?.querySelector?.('.files') as HTMLElement | null;\n if (!area) return;\n area.innerHTML = this._files\n .map(\n (f, i) => `\n <div class=\"file\" part=\"file\">\n <span class=\"name\">${esc(f.name)}</span>\n <span class=\"size\">${this._fmtSize(f.size)}</span>\n <button type=\"button\" class=\"remove\" data-i=\"${i}\" part=\"remove\" aria-label=\"Remover ${esc(f.name)}\">×</button>\n </div>`,\n )\n .join('');\n area.querySelectorAll<HTMLButtonElement>('.remove').forEach((btn) =>\n btn.addEventListener('click', () => {\n const removed = this._files.splice(Number(btn.dataset.i), 1)[0];\n this.value = this._files.map((f) => f.name).join(', ');\n this.progress = 0;\n this._syncFilesArea();\n this.dispatchEvent(\n new CustomEvent('remove', { bubbles: true, composed: true, detail: { file: removed } }),\n );\n }),\n );\n }\n}\n\nexport function defineFxFileUpload(): typeof FxFileUpload {\n return defineElement('fx-fileupload', FxFileUpload);\n}\n\n\n"],"names":[],"mappings":";;;;;AAsBO,MAAM,gBAAN,MAAM,sBAAqB,UAAU;AAAA,EAArC,cAAA;AAAA,UAAA,GAAA,SAAA;AA8ML,SAAQ,SAAiB,CAAA;AACzB,SAAQ,QAAQ;AAAA,EAAA;AAAA,EAvEhB,WAAoB,qBAA+B;AACjD,WAAO,CAAC,QAAQ,QAAQ,YAAY,SAAS,QAAQ,UAAU,YAAY,YAAY,iBAAiB,YAAY,SAAS,MAAM;AAAA,EACrI;AAAA,EAEA,IAAI,OAAe;AACjB,UAAM,IAAI,KAAK,QAAQ,QAAQ,IAAI;AACnC,WAAO,MAAM,QAAQ,MAAM,OAAO,IAAI;AAAA,EACxC;AAAA,EACA,IAAI,KAAK,OAAe;AAAE,SAAK,aAAa,QAAQ,KAAK;AAAA,EAAG;AAAA;AAAA,EAG5D,IAAI,QAAgB;AAAE,WAAO,KAAK,QAAQ,OAAO;AAAA,EAAG;AAAA,EACpD,IAAI,MAAM,GAAW;AAAE,SAAK,aAAa,SAAS,CAAC;AAAA,EAAG;AAAA,EAEtD,IAAI,WAAmB;AAAE,WAAO,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,OAAO,KAAK,QAAQ,YAAY,GAAG,CAAC,KAAK,CAAC,CAAC;AAAA,EAAG;AAAA,EACxG,IAAI,SAAS,GAAW;AAAE,SAAK,aAAa,YAAY,OAAO,CAAC,CAAC;AAAA,EAAG;AAAA;AAAA,EAGpE,IAAI,QAAgB;AAAE,WAAO,KAAK;AAAA,EAAQ;AAAA,EAC1C,IAAI,MAAM,OAAe;AACvB,SAAK,SAAS,MAAM,KAAK,KAAK;AAC9B,SAAK,QAAQ,KAAK,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI;AACrD,SAAK,eAAA;AAAA,EACP;AAAA,EAEmB,SAAe;AAChC,UAAM,OAAO,KAAK,QAAQ,QAAQ,OAAO;AACzC,UAAM,WAAW,SAAS;AAC1B,UAAM,QAAQ,KAAK,QAAQ,SAAS,kBAAkB;AACtD,UAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,UAAM,SAAS,KAAK,QAAQ,QAAQ;AACpC,UAAM,WAAW,KAAK,QAAQ,UAAU;AACxC,UAAM,WAAW,KAAK,QAAQ,UAAU;AACxC,UAAM,eAAe,KAAK,QAAQ,eAAe;AACjD,UAAM,MAAM,KAAK;AAEjB,UAAM,YAAY,qCAAqC,SAAS,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,IAAI,WAAW,aAAa,EAAE,IAAI,WAAW,aAAa,EAAE;AAE1J,SAAK,YAAY;AAAA,QACb,WACE,4EAA4E,IAAI,KAAK,CAAC;AAAA,eACjF,OAAO,qDAAqD,cAAc,IAAI,CAAC,YAAY,EAAE;AAAA,qBACvF,IAAI,KAAK,CAAC;AAAA;AAAA,qBAGrB;AAAA,eACK,OAAO,qDAAqD,cAAc,IAAI,CAAC,YAAY,EAAE;AAAA,qBACvF,IAAI,KAAK,CAAC;AAAA,qBACV;AAAA,QACb,SAAS;AAAA;AAAA,QAET,eAAe;AAAA;AAAA,+DAEwC,GAAG;AAAA,2CACvB,GAAG;AAAA;AAAA,4BAElB,GAAG;AAAA,gBACf,EAAE;AAAA,KACb;AAED,SAAK,YAAA;AACL,SAAK,eAAA;AAEL,QAAI,CAAC,KAAK,SAAS,gBAAgB,OAAO,OAAO,KAAK,OAAO,QAAQ;AACnE,WAAK,QAAQ;AACb,WAAK,cAAc,IAAI,YAAY,YAAY,EAAE,SAAS,MAAM,UAAU,KAAA,CAAM,CAAC;AAAA,IACnF;AACA,QAAI,MAAM,IAAK,MAAK,QAAQ;AAAA,EAC9B;AAAA,EAKQ,UAAmC;AACzC,WAAO,KAAK,KAAK,cAAgC,SAAS;AAAA,EAC5D;AAAA,EAEQ,cAAoB;AAC1B,UAAM,SAAS,KAAK,QAAA;AACpB,QAAI,CAAC,OAAQ;AACb,UAAM,UAAU,KAAK,KAAK,cAAc,MAAM,KAAK,KAAK,KAAK,cAAc,OAAO;AAClF,aAAS,iBAAiB,SAAS,MAAM,OAAO,OAAO;AACvD,aAAS,iBAAiB,WAAW,CAAC,MAAM;AAC1C,UAAK,EAAoB,QAAQ,WAAY,EAAoB,QAAQ,KAAK;AAC5E,UAAE,eAAA;AACF,eAAO,MAAA;AAAA,MACT;AAAA,IACF,CAAC;AACD,WAAO,iBAAiB,UAAU,MAAM,KAAK,aAAa,OAAO,SAAS,CAAA,CAAE,CAAC;AAG7E,UAAM,OAAO,KAAK,KAAK,cAA2B,OAAO;AACzD,QAAI,CAAC,KAAM;AACX,SAAK,iBAAiB,YAAY,CAAC,MAAM;AAAE,QAAE,eAAA;AAAkB,WAAK,UAAU,IAAI,MAAM;AAAA,IAAG,CAAC;AAC5F,SAAK,iBAAiB,aAAa,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC;AACtE,SAAK,iBAAiB,QAAQ,CAAC,MAAM;AACnC,QAAE,eAAA;AACF,WAAK,UAAU,OAAO,MAAM;AAC5B,UAAI,EAAE,cAAc,MAAM,aAAa,aAAa,EAAE,aAAa,KAAK;AAAA,IAC1E,CAAC;AAAA,EACH;AAAA,EAEQ,aAAa,MAA+B;AAClD,UAAM,SAAS,KAAK,QAAQ,UAAU,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,OAAO;AACrF,SAAK,QAAQ;AACb,UAAM,SAAS,KAAK,QAAA;AACpB,QAAI,eAAe,QAAQ;AAC3B,SAAK;AAAA,MACH,IAAI,YAAY,UAAU,EAAE,SAAS,MAAM,UAAU,MAAM,QAAQ,EAAE,OAAO,OAAA,GAAU;AAAA,IAAA;AAAA,EAE1F;AAAA,EAEQ,SAAS,OAAuB;AACtC,QAAI,QAAQ,KAAM,QAAO,GAAG,KAAK;AACjC,QAAI,QAAQ,OAAO,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAC5D,WAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC9C;AAAA;AAAA,EAGQ,iBAAuB;AAC7B,UAAM,OAAO,KAAK,MAAM,gBAAgB,QAAQ;AAChD,QAAI,CAAC,KAAM;AACX,SAAK,YAAY,KAAK,OACnB;AAAA,MACC,CAAC,GAAG,MAAM;AAAA;AAAA,+BAEa,IAAI,EAAE,IAAI,CAAC;AAAA,+BACX,KAAK,SAAS,EAAE,IAAI,CAAC;AAAA,yDACK,CAAC,uCAAuC,IAAI,EAAE,IAAI,CAAC;AAAA;AAAA,IAAA,EAGrG,KAAK,EAAE;AACV,SAAK,iBAAoC,SAAS,EAAE;AAAA,MAAQ,CAAC,QAC3D,IAAI,iBAAiB,SAAS,MAAM;AAClC,cAAM,UAAU,KAAK,OAAO,OAAO,OAAO,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;AAC9D,aAAK,QAAQ,KAAK,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI;AACrD,aAAK,WAAW;AAChB,aAAK,eAAA;AACL,aAAK;AAAA,UACH,IAAI,YAAY,UAAU,EAAE,SAAS,MAAM,UAAU,MAAM,QAAQ,EAAE,MAAM,QAAA,GAAW;AAAA,QAAA;AAAA,MAE1F,CAAC;AAAA,IAAA;AAAA,EAEL;AACF;AAvRE,cAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAoIrB,mBAAmB;AAAA;AArIlB,IAAM,eAAN;AA0RA,SAAS,qBAA0C;AACxD,SAAO,cAAc,iBAAiB,YAAY;AACpD;"}
|
|
1
|
+
{"version":3,"file":"fileupload.js","sources":["../../../src/components/fileupload/fileupload.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\nimport { FENIX_ICON_BASE_CSS, fenixIconHtml } from '../../icons/base-css';\n\n/**\n * <fx-fileupload> — Seletor de arquivos com upload e progresso.\n *\n * Atributos:\n * - mode (basic|advanced — `basic`: botão; `advanced`: dropzone com drag & drop);\n * - size (sm|md|lg, padrão md);\n * - severity (primary|secondary|success|warning|danger|info — cor do botão no modo basic);\n * - label (texto do botão/área, padrão 'Escolher arquivo');\n * - icon (glifo/emoji exibido antes do texto — sem o atributo, sem ícone);\n * - accept, multiple, disabled (como no <input type=\"file\">);\n * - show-progress (exibe barra + % de upload);\n * - progress (0-100 — o consumidor atualiza durante o upload real);\n * - value (nome(s) do(s) arquivo(s) carregado(s), somente leitura/espelho).\n *\n * Eventos (composed): `select` (detail: { files: File[] }), `remove`, `complete`.\n */\nexport class FxFileUpload extends FxElement {\n static override styles = css`\n :host {\n display: inline-block;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n :host([disabled]) { opacity: 0.55; pointer-events: none; }\n input[type='file'] { display: none; }\n\n /* ---- botão (basic) ---- */\n .btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--fx-space-sm);\n /* Largura acompanha o host: CSS externo/classe/inline no elemento esticam\n o botão sem precisar do full (host é shrink-to-fit por padrão). */\n width: 100%;\n min-height: var(--fx-size-md);\n /* Padding vertical no orçamento do token --fx-size-* ⇒ altura padrão. */\n padding: var(--fx-space-sm) var(--fx-space-lg);\n font-family: inherit;\n font-size: inherit;\n font-weight: var(--fx-font-weight);\n line-height: var(--fx-font-line-height);\n color: var(--fx-text-default);\n background-color: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n cursor: pointer;\n box-sizing: border-box;\n transition:\n border-color var(--fx-motion-duration-normal) var(--fx-motion-easing),\n box-shadow var(--fx-motion-duration-normal) var(--fx-motion-easing),\n background var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .btn:hover { border-color: var(--fx-border-hover); background: var(--fx-surface-surface-hover, rgba(0,0,0,0.03)); }\n .btn:focus-visible {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n /* Severities (como no <fx-button>) — aplicam-se ao botão do modo basic */\n :host([severity='primary']) .btn { background: var(--fx-color-primary); border-color: transparent; color: #fff; }\n :host([severity='secondary']) .btn { background: var(--fx-color-secondary); border-color: transparent; color: #fff; }\n :host([severity='success']) .btn { background: var(--fx-color-success); border-color: transparent; color: #fff; }\n :host([severity='warning']) .btn { background: var(--fx-color-warning); border-color: transparent; color: #fff; }\n :host([severity='danger']) .btn { background: var(--fx-color-danger); border-color: transparent; color: #fff; }\n :host([severity='info']) .btn { background: var(--fx-color-info); border-color: transparent; color: #fff; }\n :host([severity]) .btn:hover { filter: brightness(0.88); }\n :host([severity]) .btn:focus-visible { border-color: transparent; }\n :host([size='sm']) .btn { min-height: var(--fx-size-sm); padding: var(--fx-space-xs) var(--fx-space-md); font-size: calc(var(--fx-font-size) - 2px); }\n :host([size='lg']) .btn { min-height: var(--fx-size-lg); padding: var(--fx-space-sm) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); }\n :host([size='sm']) .drop { min-height: 72px; }\n :host([size='lg']) .drop { min-height: 132px; }\n\n /* ---- dropzone (advanced) ---- */\n .drop {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--fx-space-sm);\n /* Acompanha a largura do host (definida por CSS externo/classe/inline). */\n width: 100%;\n min-height: 100px;\n padding: var(--fx-space-lg);\n border: 2px dashed var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n color: var(--fx-text-muted);\n cursor: pointer;\n text-align: center;\n transition: border-color var(--fx-motion-duration-normal) var(--fx-motion-easing), background var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .drop:hover, .drop.over {\n border-color: var(--fx-color-primary);\n background: color-mix(in srgb, var(--fx-color-primary) 6%, transparent);\n }\n .drop .icon { font-size: calc(var(--fx-font-size) + 12px); line-height: 1; }\n .drop .hint { font-size: calc(var(--fx-font-size) - 2px); }\n\n /* ---- ícone comum ---- */\n .icon { line-height: 1; }\n\n /* ---- arquivo(s) selecionado(s) ---- */\n .files { display: flex; flex-direction: column; gap: var(--fx-space-xs); margin-top: var(--fx-space-sm); }\n .file {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm);\n padding: var(--fx-space-xs) var(--fx-space-sm);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-sm);\n font-size: calc(var(--fx-font-size) - 2px);\n color: var(--fx-text-default);\n }\n .file .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .file .size { color: var(--fx-text-muted); white-space: nowrap; }\n .file .remove {\n border: none;\n background: transparent;\n color: var(--fx-text-muted);\n cursor: pointer;\n font-size: calc(var(--fx-font-size) + 2px);\n line-height: 1;\n padding: 0 var(--fx-space-xs);\n border-radius: var(--fx-radius-full);\n }\n .file .remove:hover { color: var(--fx-color-danger); }\n\n /* ---- progresso ---- */\n .progress-row { display: flex; align-items: center; gap: var(--fx-space-sm); margin-top: var(--fx-space-sm); }\n .track {\n flex: 1;\n height: 6px;\n background: var(--fx-surface-surface-hover);\n border-radius: var(--fx-radius-full);\n overflow: hidden;\n }\n .bar {\n height: 100%;\n width: 0%;\n background: var(--fx-color-primary);\n border-radius: var(--fx-radius-full);\n transition: width var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n :host([progress='100']) .bar { background: var(--fx-color-success); }\n .pct {\n font-size: calc(var(--fx-font-size) - 2px);\n font-weight: 600;\n color: var(--fx-text-default);\n min-width: 34px;\n text-align: right;\n }\n /* Full width: o host estica até o pai e o botão/dropzone acompanha. */\n :host([full]) { display: block; width: 100%; }\n :host([full]) .btn { width: 100%; }\n :host([full]) .drop { width: 100%; }\n /* Base dos glifos Fenix Icons (o @font-face vem de @wrrdev/fenix-ui/icons). */\n ${FENIX_ICON_BASE_CSS}\n `;\n\n static override get observedAttributes(): string[] {\n return ['mode', 'size', 'severity', 'label', 'icon', 'accept', 'multiple', 'disabled', 'show-progress', 'progress', 'value', 'full'];\n }\n\n get size(): string {\n const s = this.getAttr('size', 'md');\n return s === 'sm' || s === 'lg' ? s : 'md';\n }\n set size(value: string) { this.setAttribute('size', value); }\n\n /** Nomes dos arquivos selecionados (espelho em `value`). */\n get value(): string { return this.getAttr('value'); }\n set value(v: string) { this.setAttribute('value', v); }\n\n get progress(): number { return Math.min(100, Math.max(0, Number(this.getAttr('progress', '0')) || 0)); }\n set progress(v: number) { this.setAttribute('progress', String(v)); }\n\n /** Arquivos selecionados (não serializável em atributo). */\n get files(): File[] { return this._files; }\n set files(files: File[]) {\n this._files = Array.from(files);\n this.value = this._files.map((f) => f.name).join(', ');\n this._syncFilesArea();\n }\n\n protected override render(): void {\n const mode = this.getAttr('mode', 'basic');\n const advanced = mode === 'advanced';\n const label = this.getAttr('label', 'Escolher arquivo');\n const icon = this.getAttr('icon');\n const accept = this.getAttr('accept');\n const multiple = this.hasAttr('multiple');\n const disabled = this.hasAttr('disabled');\n const showProgress = this.hasAttr('show-progress');\n const pct = this.progress;\n\n const fileInput = `<input type=\"file\" class=\"picker\" ${accept ? `accept=\"${esc(accept)}\"` : ''} ${multiple ? 'multiple' : ''} ${disabled ? 'disabled' : ''} />`;\n\n this.setTemplate(`\n ${advanced\n ? `<div class=\"drop\" part=\"dropzone\" role=\"button\" tabindex=\"0\" aria-label=\"${esc(label)}\">\n ${icon ? `<span class=\"icon\" part=\"icon\" aria-hidden=\"true\">${fenixIconHtml(icon)}</span>` : ''}\n <span>${esc(label)}</span>\n <span class=\"hint\">ou arraste e solte aqui</span>\n </div>`\n : `<button type=\"button\" class=\"btn\" part=\"button\">\n ${icon ? `<span class=\"icon\" part=\"icon\" aria-hidden=\"true\">${fenixIconHtml(icon)}</span>` : ''}\n <span>${esc(label)}</span>\n </button>`}\n ${fileInput}\n <div class=\"files\" part=\"files\"></div>\n ${showProgress ? `\n <div class=\"progress-row\" part=\"progress\">\n <div class=\"track\" role=\"progressbar\" aria-valuenow=\"${pct}\" aria-valuemin=\"0\" aria-valuemax=\"100\">\n <div class=\"bar\" style=\"width: ${pct}%\"></div>\n </div>\n <span class=\"pct\">${pct}%</span>\n </div>` : ''}\n `);\n\n this._bindPicker();\n this._syncFilesArea();\n\n if (!this._done && showProgress && pct >= 100 && this._files.length) {\n this._done = true;\n this.dispatchEvent(new CustomEvent('complete', { bubbles: true, composed: true }));\n }\n if (pct < 100) this._done = false;\n }\n\n private _files: File[] = [];\n private _done = false;\n\n private _picker(): HTMLInputElement | null {\n return this.root.querySelector<HTMLInputElement>('.picker');\n }\n\n private _bindPicker(): void {\n const picker = this._picker();\n if (!picker) return;\n const trigger = this.root.querySelector('.btn') ?? this.root.querySelector('.drop');\n trigger?.addEventListener('click', () => picker.click());\n trigger?.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter' || (e as KeyboardEvent).key === ' ') {\n e.preventDefault();\n picker.click();\n }\n });\n picker.addEventListener('change', () => this._acceptFiles(picker.files ?? []));\n\n // drag & drop (advanced)\n const drop = this.root.querySelector<HTMLElement>('.drop');\n if (!drop) return;\n drop.addEventListener('dragover', (e) => { e.preventDefault(); drop.classList.add('over'); });\n drop.addEventListener('dragleave', () => drop.classList.remove('over'));\n drop.addEventListener('drop', (e) => {\n e.preventDefault();\n drop.classList.remove('over');\n if (e.dataTransfer?.files.length) this._acceptFiles(e.dataTransfer.files);\n });\n }\n\n private _acceptFiles(list: FileList | File[]): void {\n const picked = this.hasAttr('multiple') ? Array.from(list) : [list[0]].filter(Boolean);\n this.files = picked;\n const picker = this._picker();\n if (picker) picker.value = '';\n this.dispatchEvent(\n new CustomEvent('select', { bubbles: true, composed: true, detail: { files: picked } }),\n );\n }\n\n private _fmtSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n }\n\n /** Renderiza a lista de arquivos sem re-renderizar o template (mantém estado). */\n private _syncFilesArea(): void {\n const area = this.root?.querySelector?.('.files') as HTMLElement | null;\n if (!area) return;\n area.innerHTML = this._files\n .map(\n (f, i) => `\n <div class=\"file\" part=\"file\">\n <span class=\"name\">${esc(f.name)}</span>\n <span class=\"size\">${this._fmtSize(f.size)}</span>\n <button type=\"button\" class=\"remove\" data-i=\"${i}\" part=\"remove\" aria-label=\"Remover ${esc(f.name)}\">×</button>\n </div>`,\n )\n .join('');\n area.querySelectorAll<HTMLButtonElement>('.remove').forEach((btn) =>\n btn.addEventListener('click', () => {\n const removed = this._files.splice(Number(btn.dataset.i), 1)[0];\n this.value = this._files.map((f) => f.name).join(', ');\n this.progress = 0;\n this._syncFilesArea();\n this.dispatchEvent(\n new CustomEvent('remove', { bubbles: true, composed: true, detail: { file: removed } }),\n );\n }),\n );\n }\n}\n\nexport function defineFxFileUpload(): typeof FxFileUpload {\n return defineElement('fx-fileupload', FxFileUpload);\n}\n\n\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { FxElement } from '../../core/base';
|
|
2
|
+
/**
|
|
3
|
+
* <fx-icon> — Glifo da Fenix Icons com AUTOCOMPLETE no editor.
|
|
4
|
+
*
|
|
5
|
+
* Por que existe: a forma antiga (`<i class="fx-icon fx-icon-home">`) é CSS
|
|
6
|
+
* puro — o TypeScript não valida nem sugere nada enquanto você digita, e o
|
|
7
|
+
* auto-import só injeta o import. Com o elemento, o atributo `name` é tipado
|
|
8
|
+
* como `FenixIconName`, então Volar/vue-tsc, React e TSX listam os +4.000
|
|
9
|
+
* glifos válidos (e o hover mostra a assinatura do atributo).
|
|
10
|
+
*
|
|
11
|
+
* Atributos:
|
|
12
|
+
* - name → nome do glifo (ex.: `home`); texto livre/emoji também funciona
|
|
13
|
+
* - size → sm | md | lg | xl (default: 1em, herda o texto ao redor)
|
|
14
|
+
* - label → nome acessível; sem label o ícone é aria-hidden (decorativo)
|
|
15
|
+
* - fill → variante preenchida
|
|
16
|
+
* - bold → traço mais pesado
|
|
17
|
+
*
|
|
18
|
+
* O glifo sai por LIGADURA (o nome vira o conteúdo de texto com a
|
|
19
|
+
* font-family de ícones) — por isso funciona dentro do Shadow DOM, onde as
|
|
20
|
+
* classes `fx-icon-<nome>` do documento não atravessam a fronteira.
|
|
21
|
+
*
|
|
22
|
+
* Tamanho via CSS: --fx-icon-size (-sm/-md/-lg/-xl).
|
|
23
|
+
*/
|
|
24
|
+
export declare class FxIcon extends FxElement {
|
|
25
|
+
static styles: string;
|
|
26
|
+
static get observedAttributes(): string[];
|
|
27
|
+
/** Nome do glifo (ou texto livre/emoji). */
|
|
28
|
+
get name(): string;
|
|
29
|
+
set name(value: string);
|
|
30
|
+
/** Tamanho: '' (herda 1em) | 'sm' | 'md' | 'lg' | 'xl'. */
|
|
31
|
+
get size(): string;
|
|
32
|
+
set size(value: string);
|
|
33
|
+
/** Nome acessível; vazio = ícone decorativo (aria-hidden). */
|
|
34
|
+
get label(): string;
|
|
35
|
+
set label(value: string);
|
|
36
|
+
protected connectedCallback(): void;
|
|
37
|
+
protected render(): void;
|
|
38
|
+
}
|
|
39
|
+
export declare function defineFxIcon(): typeof FxIcon;
|
|
40
|
+
//# sourceMappingURL=icon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../../../src/components/icon/icon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAO5C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,MAAO,SAAQ,SAAS;IACnC,OAAgB,MAAM,SAoBpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,4CAA4C;IAC5C,IAAI,IAAI,IAAI,MAAM,CAEjB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAErB;IAED,2DAA2D;IAC3D,IAAI,IAAI,IAAI,MAAM,CAEjB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAGrB;IAED,8DAA8D;IAC9D,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAGtB;cAEkB,iBAAiB,IAAI,IAAI;cAMzB,MAAM,IAAI,IAAI;CAclC;AAED,wBAAgB,YAAY,IAAI,OAAO,MAAM,CAE5C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/icon/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,CAAC;AAIlB,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB;CACF"}
|
|
@@ -6,6 +6,9 @@ import { FxElement } from '../../core/base';
|
|
|
6
6
|
* placeholder, disabled, readonly, min, max, step, clearable,
|
|
7
7
|
* full (largura 100% acompanhando o elemento pai), icon (nome do glifo Fenix Icons
|
|
8
8
|
* ou emoji/texto livre) e icon-pos (left|right, padrão left).
|
|
9
|
+
* Largura: o default (260px; sm 220px / lg 300px) fica no HOST via tokens
|
|
10
|
+
* --fx-input-width(-sm|-lg) — CSS externo, classes e style inline no elemento
|
|
11
|
+
* vencem o default sem precisar de atributo.
|
|
9
12
|
* Slots: `icon` (ícone customizado no lugar do atributo).
|
|
10
13
|
* Eventos: `input` e `change` (composed, detail: { value }).
|
|
11
14
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../src/components/input/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../src/components/input/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C;;;;;;;;;;;;GAYG;AACH,qBAAa,OAAQ,SAAQ,SAAS;IACpC,OAAgB,MAAM,SAuIpB;IAMF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAMjD;IAED,wCAAwC;IACxC,IAAI,IAAI,IAAI,MAAM,CAGjB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAErB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAEtB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;cAEkB,MAAM,IAAI,IAAI;CA8DlC;AAED,wBAAgB,aAAa,IAAI,OAAO,OAAO,CAE9C"}
|
|
@@ -109,20 +109,31 @@ _FxInput.styles = css`
|
|
|
109
109
|
:host {
|
|
110
110
|
display: inline-block;
|
|
111
111
|
vertical-align: middle;
|
|
112
|
+
/* Largura padrão no HOST (e não no .field interno): assim CSS externo,
|
|
113
|
+
classes do framework (ex.: w-full) e style inline no elemento vencem
|
|
114
|
+
este default naturalmente — regras do documento têm precedência sobre
|
|
115
|
+
:host. Default global trocável via token: --fx-input-width (-sm/-lg). */
|
|
116
|
+
width: var(--fx-input-width, 260px);
|
|
117
|
+
vertical-align: middle;
|
|
112
118
|
font-family: var(--fx-font-family);
|
|
113
119
|
font-size: var(--fx-font-size);
|
|
114
120
|
}
|
|
115
121
|
.field {
|
|
116
122
|
font-family: inherit;
|
|
117
123
|
font-size: inherit;
|
|
124
|
+
/* Altura determinística: com line-height fixo, o padding vertical cabe no
|
|
125
|
+
token --fx-size-* e a caixa fica EXATAMENTE no tamanho padrão
|
|
126
|
+
(sm 32 / md 40 / lg 48), igual para todos os campos. */
|
|
127
|
+
line-height: var(--fx-font-line-height);
|
|
118
128
|
min-height: var(--fx-size-md);
|
|
119
129
|
font-weight: var(--fx-font-weight);
|
|
120
130
|
color: var(--fx-text-default);
|
|
121
131
|
background-color: var(--fx-surface-background);
|
|
122
132
|
border: 1px solid var(--fx-border-default);
|
|
123
133
|
border-radius: var(--fx-radius-md);
|
|
124
|
-
padding: var(--fx-space-
|
|
125
|
-
|
|
134
|
+
padding: var(--fx-space-sm) var(--fx-space-lg);
|
|
135
|
+
/* Acompanha a largura definida no :host. */
|
|
136
|
+
width: 100%;
|
|
126
137
|
box-sizing: border-box;
|
|
127
138
|
transition:
|
|
128
139
|
border-color var(--fx-motion-duration-normal) var(--fx-motion-easing),
|
|
@@ -141,23 +152,27 @@ _FxInput.styles = css`
|
|
|
141
152
|
cursor: not-allowed;
|
|
142
153
|
background-color: var(--fx-surface-surface-hover);
|
|
143
154
|
}
|
|
144
|
-
/* Validação:
|
|
155
|
+
/* Validação: borda sempre; o brilho (anel) segue o token do preset
|
|
156
|
+
--fx-effect-error-ring, que acompanha effect.focus-ring — anel
|
|
157
|
+
desligado ⇒ erro só com a borda vermelha, ligado ⇒ soma o brilho. */
|
|
145
158
|
:host([error]) .field,
|
|
146
159
|
:host([invalid]) .field,
|
|
147
160
|
:host([error]) .field:focus-visible,
|
|
148
161
|
:host([invalid]) .field:focus-visible {
|
|
149
162
|
border-color: var(--fx-color-danger, #dc2626);
|
|
150
|
-
box-shadow: 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent);
|
|
163
|
+
box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));
|
|
151
164
|
}
|
|
152
165
|
:host([success]) .field,
|
|
153
166
|
:host([valid]) .field,
|
|
154
167
|
:host([success]) .field:focus-visible,
|
|
155
168
|
:host([valid]) .field:focus-visible {
|
|
156
169
|
border-color: var(--fx-color-success, #16a34a);
|
|
157
|
-
box-shadow: 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent);
|
|
170
|
+
box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));
|
|
158
171
|
}
|
|
159
|
-
:host([size='sm'])
|
|
160
|
-
:host([size='
|
|
172
|
+
:host([size='sm']) { width: var(--fx-input-width-sm, 220px); }
|
|
173
|
+
:host([size='sm']) .field { padding: var(--fx-space-xs) var(--fx-space-md); font-size: var(--fx-font-size); min-height: var(--fx-size-sm); }
|
|
174
|
+
:host([size='lg']) { width: var(--fx-input-width-lg, 300px); }
|
|
175
|
+
:host([size='lg']) .field { padding: var(--fx-space-sm) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); min-height: var(--fx-size-lg); }
|
|
161
176
|
/* Full width: o host estica até o pai e o campo interno acompanha
|
|
162
177
|
(usar com um container de largura controlada, ex. w-full no Vue). */
|
|
163
178
|
:host([full]) { display: block; width: 100%; }
|
|
@@ -165,7 +180,7 @@ _FxInput.styles = css`
|
|
|
165
180
|
/* Clearable */
|
|
166
181
|
:host([clearable]) { position: relative; display: inline-flex; }
|
|
167
182
|
:host([clearable][full]) { display: block; }
|
|
168
|
-
.wrap { position: relative; display: inline-flex; align-items: center; }
|
|
183
|
+
.wrap { position: relative; display: inline-flex; align-items: center; width: 100%; }
|
|
169
184
|
:host([full]) .wrap { display: flex; width: 100%; }
|
|
170
185
|
:host([clearable]) .field { padding-right: var(--fx-space-xl); }
|
|
171
186
|
:host([clearable][full]) .field { flex: 1 1 auto; }
|
|
@@ -175,6 +190,7 @@ _FxInput.styles = css`
|
|
|
175
190
|
position: relative;
|
|
176
191
|
display: inline-flex;
|
|
177
192
|
box-sizing: border-box;
|
|
193
|
+
width: 100%;
|
|
178
194
|
}
|
|
179
195
|
.field-icon .field { flex: 1 1 auto; min-width: 0; }
|
|
180
196
|
:host([full]) .field-icon { display: flex; width: 100%; }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.js","sources":["../../../src/components/input/input.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\nimport { FENIX_ICON_BASE_CSS, fenixIconHtml } from '../../icons/base-css';\n\n/**\n * <fx-input> — Campo de texto estilizado com os tokens do tema.\n *\n * Atributos: type (text|number|email|password|search|tel|url), value, size,\n * placeholder, disabled, readonly, min, max, step, clearable,\n * full (largura 100% acompanhando o elemento pai), icon (nome do glifo Fenix Icons\n * ou emoji/texto livre) e icon-pos (left|right, padrão left).\n * Slots: `icon` (ícone customizado no lugar do atributo).\n * Eventos: `input` e `change` (composed, detail: { value }).\n */\nexport class FxInput extends FxElement {\n static override styles = css`\n :host {\n display: inline-block;\n vertical-align: middle;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n .field {\n font-family: inherit;\n font-size: inherit;\n min-height: var(--fx-size-md);\n font-weight: var(--fx-font-weight);\n color: var(--fx-text-default);\n background-color: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n padding: var(--fx-space-md) var(--fx-space-lg);\n width: 260px;\n box-sizing: border-box;\n transition:\n border-color var(--fx-motion-duration-normal) var(--fx-motion-easing),\n box-shadow var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .field::placeholder { color: var(--fx-text-muted); opacity: 1; }\n .field:hover { border-color: var(--fx-border-hover); }\n .field:focus-visible {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n .field:disabled,\n .field[readonly] {\n opacity: 0.55;\n cursor: not-allowed;\n background-color: var(--fx-surface-surface-hover);\n }\n /* Validação: sobrescrevem a borda/foco via token do preset. */\n :host([error]) .field,\n :host([invalid]) .field,\n :host([error]) .field:focus-visible,\n :host([invalid]) .field:focus-visible {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent);\n }\n :host([success]) .field,\n :host([valid]) .field,\n :host([success]) .field:focus-visible,\n :host([valid]) .field:focus-visible {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent);\n }\n :host([size='sm']) .field { padding: var(--fx-space-sm) var(--fx-space-md); font-size: var(--fx-font-size); width: 220px; min-height: var(--fx-size-sm); }\n :host([size='lg']) .field { padding: var(--fx-space-lg) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); width: 300px; min-height: var(--fx-size-lg); }\n /* Full width: o host estica até o pai e o campo interno acompanha\n (usar com um container de largura controlada, ex. w-full no Vue). */\n :host([full]) { display: block; width: 100%; }\n :host([full]) .field { width: 100%; }\n /* Clearable */\n :host([clearable]) { position: relative; display: inline-flex; }\n :host([clearable][full]) { display: block; }\n .wrap { position: relative; display: inline-flex; align-items: center; }\n :host([full]) .wrap { display: flex; width: 100%; }\n :host([clearable]) .field { padding-right: var(--fx-space-xl); }\n :host([clearable][full]) .field { flex: 1 1 auto; }\n /* Ícones (attr icon + slot icon) — DENTRO do campo, sobre o padding\n (padrão Material/PrimeVue). Tamanho ajustável via --fx-input-icon-size. */\n .field-icon {\n position: relative;\n display: inline-flex;\n box-sizing: border-box;\n }\n .field-icon .field { flex: 1 1 auto; min-width: 0; }\n :host([full]) .field-icon { display: flex; width: 100%; }\n .field-icon .fx-icon,\n .field-icon ::slotted([slot='icon']) {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px));\n line-height: 1;\n color: var(--fx-text-muted);\n pointer-events: none;\n z-index: 1;\n }\n .field-icon.icon-left .fx-icon,\n .field-icon.icon-left ::slotted([slot='icon']) { left: var(--fx-space-md); }\n .field-icon.icon-right .fx-icon,\n .field-icon.icon-right ::slotted([slot='icon']) { right: var(--fx-space-md); }\n /* padding = posição do ícone + largura + folga extra para o texto\n não colar no glifo. */\n .field-icon.icon-left .field {\n padding-left: calc(var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px)) + var(--fx-space-md) + var(--fx-space-sm));\n }\n .field-icon.icon-right .field {\n padding-right: calc(var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px)) + var(--fx-space-md) + var(--fx-space-sm));\n }\n /* icon-pos right + clearable: desloca o × para não sobrepor o ícone. */\n .field-icon.icon-right + .clear {\n right: calc(var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px)) + var(--fx-space-lg));\n }\n .clear {\n position: absolute;\n right: var(--fx-space-xs);\n border: none;\n background: transparent;\n color: var(--fx-text-muted);\n font-size: calc(var(--fx-font-size) + 4px);\n line-height: 1;\n cursor: pointer;\n padding: 0 var(--fx-space-xs);\n border-radius: var(--fx-radius-full);\n }\n .clear:hover { color: var(--fx-color-danger); }\n .clear[hidden] { display: none; }\n /* Base dos glifos Fenix Icons (o @font-face vem de @wrrdev/fenix-ui/icons). */\n ${FENIX_ICON_BASE_CSS}\n `;\n\n // `value` fica FORA da observação: refleti-lo a cada tecla não pode\n // re-renderizar o template, senão o campo perde o foco ao digitar.\n // `error`/`success` (+ aliases `invalid`/`valid`) PRECISAM ser observados:\n // é assim que o toggle no playground / setAttribute no submit re-renderiza.\n static override get observedAttributes(): string[] {\n return [\n 'type', 'size', 'placeholder',\n 'disabled', 'readonly', 'min', 'max', 'step',\n 'icon', 'icon-pos', 'error', 'invalid', 'success', 'valid',\n ];\n }\n\n /** Tamanho do campo. Padrão: `'md'`. */\n get size(): string {\n const s = this.getAttr('size', 'md');\n return s === 'sm' || s === 'lg' ? s : 'md';\n }\n set size(value: string) {\n this.setAttribute('size', value);\n }\n\n get value(): string {\n return this.getAttr('value');\n }\n set value(value: string) {\n this.setAttribute('value', value);\n }\n\n get disabled(): boolean {\n return this.hasAttr('disabled');\n }\n set disabled(value: boolean) {\n this.toggleAttr('disabled', Boolean(value));\n }\n\n protected override render(): void {\n const type = this.getAttr('type', 'text');\n const placeholder = this.getAttr('placeholder');\n const readonly = this.hasAttr('readonly');\n const disabled = this.hasAttr('disabled');\n const min = this.getAttr('min');\n const max = this.getAttr('max');\n const step = this.getAttr('step');\n const icon = this.getAttr('icon');\n const iconPos = this.getAttr('icon-pos', 'left') === 'right' ? 'right' : 'left';\n // Slot `icon` vence o atributo `icon`; sem nenhum dos dois, sem ícone.\n const slottedIcon = this.querySelector<HTMLElement>('[slot=\"icon\"]');\n const iconContent = slottedIcon\n ? '<slot name=\"icon\" part=\"icon\"></slot>'\n : (icon ? fenixIconHtml(icon) : '');\n const useIconBox = Boolean(iconContent);\n\n this.setTemplate(`\n ${this.hasAttr('clearable') ? '<div class=\"wrap\" part=\"wrap\">' : ''}\n ${useIconBox ? `<div class=\"field-icon icon-${iconPos}\">` : ''}\n ${useIconBox && iconPos === 'left' ? iconContent : ''}\n <input class=\"field\" part=\"input\" type=\"${esc(type)}\"\n ${placeholder ? `placeholder=\"${esc(placeholder)}\"` : ''}\n ${min ? `min=\"${esc(min)}\"` : ''} ${max ? `max=\"${esc(max)}\"` : ''} ${step ? `step=\"${esc(step)}\"` : ''}\n />\n ${useIconBox && iconPos === 'right' ? iconContent : ''}\n ${useIconBox ? '</div>' : ''}\n ${this.hasAttr('clearable') ? '<button type=\"button\" class=\"clear\" part=\"clear\" aria-label=\"Limpar\" tabindex=\"-1\">×</button></div>' : ''}\n `);\n\n const field = this.root.querySelector<HTMLInputElement>('.field');\n if (!field) return;\n field.value = this.getAttr('value');\n if (disabled) field.setAttribute('disabled', '');\n if (readonly) field.setAttribute('readonly', '');\n\n const emit = (event: string): void => {\n this.value = field.value;\n this.dispatchEvent(\n new CustomEvent(event, { bubbles: true, composed: true, detail: { value: field.value } }),\n );\n };\n // Bloqueia o evento nativo (composed, sem detail) para que só o\n // CustomEvent com detail chegue aos consumidores.\n field.addEventListener('input', (e) => { e.stopPropagation(); emit('input'); });\n field.addEventListener('change', (e) => { e.stopPropagation(); emit('change'); });\n\n // Clearable: botão × que limpa o campo e emite input/change vazios.\n const clearBtn = this.root.querySelector<HTMLButtonElement>('.clear');\n const syncClear = (): void => {\n clearBtn?.toggleAttribute('hidden', field.value === '');\n };\n syncClear();\n clearBtn?.addEventListener('click', () => {\n field.value = '';\n syncClear();\n emit('input');\n emit('change');\n field.focus();\n });\n field.addEventListener('input', syncClear);\n }\n}\n\nexport function defineFxInput(): typeof FxInput {\n return defineElement('fx-input', FxInput);\n}\n"],"names":[],"mappings":";;;;;AAgBO,MAAM,WAAN,MAAM,iBAAgB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EA8HrC,WAAoB,qBAA+B;AACjD,WAAO;AAAA,MACL;AAAA,MAAQ;AAAA,MAAQ;AAAA,MAChB;AAAA,MAAY;AAAA,MAAY;AAAA,MAAO;AAAA,MAAO;AAAA,MACtC;AAAA,MAAQ;AAAA,MAAY;AAAA,MAAS;AAAA,MAAW;AAAA,MAAW;AAAA,IAAA;AAAA,EAEvD;AAAA;AAAA,EAGA,IAAI,OAAe;AACjB,UAAM,IAAI,KAAK,QAAQ,QAAQ,IAAI;AACnC,WAAO,MAAM,QAAQ,MAAM,OAAO,IAAI;AAAA,EACxC;AAAA,EACA,IAAI,KAAK,OAAe;AACtB,SAAK,aAAa,QAAQ,KAAK;AAAA,EACjC;AAAA,EAEA,IAAI,QAAgB;AAClB,WAAO,KAAK,QAAQ,OAAO;AAAA,EAC7B;AAAA,EACA,IAAI,MAAM,OAAe;AACvB,SAAK,aAAa,SAAS,KAAK;AAAA,EAClC;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO,KAAK,QAAQ,UAAU;AAAA,EAChC;AAAA,EACA,IAAI,SAAS,OAAgB;AAC3B,SAAK,WAAW,YAAY,QAAQ,KAAK,CAAC;AAAA,EAC5C;AAAA,EAEmB,SAAe;AAChC,UAAM,OAAO,KAAK,QAAQ,QAAQ,MAAM;AACxC,UAAM,cAAc,KAAK,QAAQ,aAAa;AAC9C,UAAM,WAAW,KAAK,QAAQ,UAAU;AACxC,UAAM,WAAW,KAAK,QAAQ,UAAU;AACxC,UAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,UAAM,MAAM,KAAK,QAAQ,KAAK;AAC9B,UAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,UAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,UAAM,UAAU,KAAK,QAAQ,YAAY,MAAM,MAAM,UAAU,UAAU;AAEzE,UAAM,cAAc,KAAK,cAA2B,eAAe;AACnE,UAAM,cAAc,cAChB,0CACC,OAAO,cAAc,IAAI,IAAI;AAClC,UAAM,aAAa,QAAQ,WAAW;AAEtC,SAAK,YAAY;AAAA,QACb,KAAK,QAAQ,WAAW,IAAI,mCAAmC,EAAE;AAAA,QACjE,aAAa,+BAA+B,OAAO,OAAO,EAAE;AAAA,QAC5D,cAAc,YAAY,SAAS,cAAc,EAAE;AAAA,gDACX,IAAI,IAAI,CAAC;AAAA,UAC/C,cAAc,gBAAgB,IAAI,WAAW,CAAC,MAAM,EAAE;AAAA,UACtD,MAAM,QAAQ,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,MAAM,QAAQ,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,OAAO,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE;AAAA;AAAA,QAEvG,cAAc,YAAY,UAAU,cAAc,EAAE;AAAA,QACpD,aAAa,WAAW,EAAE;AAAA,QAC1B,KAAK,QAAQ,WAAW,IAAI,wGAAwG,EAAE;AAAA,KACzI;AAED,UAAM,QAAQ,KAAK,KAAK,cAAgC,QAAQ;AAChE,QAAI,CAAC,MAAO;AACZ,UAAM,QAAQ,KAAK,QAAQ,OAAO;AAClC,QAAI,SAAU,OAAM,aAAa,YAAY,EAAE;AAC/C,QAAI,SAAU,OAAM,aAAa,YAAY,EAAE;AAE/C,UAAM,OAAO,CAAC,UAAwB;AACpC,WAAK,QAAQ,MAAM;AACnB,WAAK;AAAA,QACH,IAAI,YAAY,OAAO,EAAE,SAAS,MAAM,UAAU,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAA,GAAS;AAAA,MAAA;AAAA,IAE5F;AAGA,UAAM,iBAAiB,SAAS,CAAC,MAAM;AAAE,QAAE,gBAAA;AAAmB,WAAK,OAAO;AAAA,IAAG,CAAC;AAC9E,UAAM,iBAAiB,UAAU,CAAC,MAAM;AAAE,QAAE,gBAAA;AAAmB,WAAK,QAAQ;AAAA,IAAG,CAAC;AAGhF,UAAM,WAAW,KAAK,KAAK,cAAiC,QAAQ;AACpE,UAAM,YAAY,MAAY;AAC5B,gBAAU,gBAAgB,UAAU,MAAM,UAAU,EAAE;AAAA,IACxD;AACA,cAAA;AACA,cAAU,iBAAiB,SAAS,MAAM;AACxC,YAAM,QAAQ;AACd,gBAAA;AACA,WAAK,OAAO;AACZ,WAAK,QAAQ;AACb,YAAM,MAAA;AAAA,IACR,CAAC;AACD,UAAM,iBAAiB,SAAS,SAAS;AAAA,EAC3C;AACF;AA1NE,SAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAsHrB,mBAAmB;AAAA;AAvHlB,IAAM,UAAN;AA6NA,SAAS,gBAAgC;AAC9C,SAAO,cAAc,YAAY,OAAO;AAC1C;"}
|
|
1
|
+
{"version":3,"file":"input.js","sources":["../../../src/components/input/input.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\nimport { FENIX_ICON_BASE_CSS, fenixIconHtml } from '../../icons/base-css';\n\n/**\n * <fx-input> — Campo de texto estilizado com os tokens do tema.\n *\n * Atributos: type (text|number|email|password|search|tel|url), value, size,\n * placeholder, disabled, readonly, min, max, step, clearable,\n * full (largura 100% acompanhando o elemento pai), icon (nome do glifo Fenix Icons\n * ou emoji/texto livre) e icon-pos (left|right, padrão left).\n * Largura: o default (260px; sm 220px / lg 300px) fica no HOST via tokens\n * --fx-input-width(-sm|-lg) — CSS externo, classes e style inline no elemento\n * vencem o default sem precisar de atributo.\n * Slots: `icon` (ícone customizado no lugar do atributo).\n * Eventos: `input` e `change` (composed, detail: { value }).\n */\nexport class FxInput extends FxElement {\n static override styles = css`\n :host {\n display: inline-block;\n vertical-align: middle;\n /* Largura padrão no HOST (e não no .field interno): assim CSS externo,\n classes do framework (ex.: w-full) e style inline no elemento vencem\n este default naturalmente — regras do documento têm precedência sobre\n :host. Default global trocável via token: --fx-input-width (-sm/-lg). */\n width: var(--fx-input-width, 260px);\n vertical-align: middle;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n }\n .field {\n font-family: inherit;\n font-size: inherit;\n /* Altura determinística: com line-height fixo, o padding vertical cabe no\n token --fx-size-* e a caixa fica EXATAMENTE no tamanho padrão\n (sm 32 / md 40 / lg 48), igual para todos os campos. */\n line-height: var(--fx-font-line-height);\n min-height: var(--fx-size-md);\n font-weight: var(--fx-font-weight);\n color: var(--fx-text-default);\n background-color: var(--fx-surface-background);\n border: 1px solid var(--fx-border-default);\n border-radius: var(--fx-radius-md);\n padding: var(--fx-space-sm) var(--fx-space-lg);\n /* Acompanha a largura definida no :host. */\n width: 100%;\n box-sizing: border-box;\n transition:\n border-color var(--fx-motion-duration-normal) var(--fx-motion-easing),\n box-shadow var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .field::placeholder { color: var(--fx-text-muted); opacity: 1; }\n .field:hover { border-color: var(--fx-border-hover); }\n .field:focus-visible {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n .field:disabled,\n .field[readonly] {\n opacity: 0.55;\n cursor: not-allowed;\n background-color: var(--fx-surface-surface-hover);\n }\n /* Validação: borda sempre; o brilho (anel) segue o token do preset\n --fx-effect-error-ring, que acompanha effect.focus-ring — anel\n desligado ⇒ erro só com a borda vermelha, ligado ⇒ soma o brilho. */\n :host([error]) .field,\n :host([invalid]) .field,\n :host([error]) .field:focus-visible,\n :host([invalid]) .field:focus-visible {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([success]) .field,\n :host([valid]) .field,\n :host([success]) .field:focus-visible,\n :host([valid]) .field:focus-visible {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));\n }\n :host([size='sm']) { width: var(--fx-input-width-sm, 220px); }\n :host([size='sm']) .field { padding: var(--fx-space-xs) var(--fx-space-md); font-size: var(--fx-font-size); min-height: var(--fx-size-sm); }\n :host([size='lg']) { width: var(--fx-input-width-lg, 300px); }\n :host([size='lg']) .field { padding: var(--fx-space-sm) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); min-height: var(--fx-size-lg); }\n /* Full width: o host estica até o pai e o campo interno acompanha\n (usar com um container de largura controlada, ex. w-full no Vue). */\n :host([full]) { display: block; width: 100%; }\n :host([full]) .field { width: 100%; }\n /* Clearable */\n :host([clearable]) { position: relative; display: inline-flex; }\n :host([clearable][full]) { display: block; }\n .wrap { position: relative; display: inline-flex; align-items: center; width: 100%; }\n :host([full]) .wrap { display: flex; width: 100%; }\n :host([clearable]) .field { padding-right: var(--fx-space-xl); }\n :host([clearable][full]) .field { flex: 1 1 auto; }\n /* Ícones (attr icon + slot icon) — DENTRO do campo, sobre o padding\n (padrão Material/PrimeVue). Tamanho ajustável via --fx-input-icon-size. */\n .field-icon {\n position: relative;\n display: inline-flex;\n box-sizing: border-box;\n width: 100%;\n }\n .field-icon .field { flex: 1 1 auto; min-width: 0; }\n :host([full]) .field-icon { display: flex; width: 100%; }\n .field-icon .fx-icon,\n .field-icon ::slotted([slot='icon']) {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px));\n line-height: 1;\n color: var(--fx-text-muted);\n pointer-events: none;\n z-index: 1;\n }\n .field-icon.icon-left .fx-icon,\n .field-icon.icon-left ::slotted([slot='icon']) { left: var(--fx-space-md); }\n .field-icon.icon-right .fx-icon,\n .field-icon.icon-right ::slotted([slot='icon']) { right: var(--fx-space-md); }\n /* padding = posição do ícone + largura + folga extra para o texto\n não colar no glifo. */\n .field-icon.icon-left .field {\n padding-left: calc(var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px)) + var(--fx-space-md) + var(--fx-space-sm));\n }\n .field-icon.icon-right .field {\n padding-right: calc(var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px)) + var(--fx-space-md) + var(--fx-space-sm));\n }\n /* icon-pos right + clearable: desloca o × para não sobrepor o ícone. */\n .field-icon.icon-right + .clear {\n right: calc(var(--fx-input-icon-size, calc(var(--fx-font-size) + 6px)) + var(--fx-space-lg));\n }\n .clear {\n position: absolute;\n right: var(--fx-space-xs);\n border: none;\n background: transparent;\n color: var(--fx-text-muted);\n font-size: calc(var(--fx-font-size) + 4px);\n line-height: 1;\n cursor: pointer;\n padding: 0 var(--fx-space-xs);\n border-radius: var(--fx-radius-full);\n }\n .clear:hover { color: var(--fx-color-danger); }\n .clear[hidden] { display: none; }\n /* Base dos glifos Fenix Icons (o @font-face vem de @wrrdev/fenix-ui/icons). */\n ${FENIX_ICON_BASE_CSS}\n `;\n\n // `value` fica FORA da observação: refleti-lo a cada tecla não pode\n // re-renderizar o template, senão o campo perde o foco ao digitar.\n // `error`/`success` (+ aliases `invalid`/`valid`) PRECISAM ser observados:\n // é assim que o toggle no playground / setAttribute no submit re-renderiza.\n static override get observedAttributes(): string[] {\n return [\n 'type', 'size', 'placeholder',\n 'disabled', 'readonly', 'min', 'max', 'step',\n 'icon', 'icon-pos', 'error', 'invalid', 'success', 'valid',\n ];\n }\n\n /** Tamanho do campo. Padrão: `'md'`. */\n get size(): string {\n const s = this.getAttr('size', 'md');\n return s === 'sm' || s === 'lg' ? s : 'md';\n }\n set size(value: string) {\n this.setAttribute('size', value);\n }\n\n get value(): string {\n return this.getAttr('value');\n }\n set value(value: string) {\n this.setAttribute('value', value);\n }\n\n get disabled(): boolean {\n return this.hasAttr('disabled');\n }\n set disabled(value: boolean) {\n this.toggleAttr('disabled', Boolean(value));\n }\n\n protected override render(): void {\n const type = this.getAttr('type', 'text');\n const placeholder = this.getAttr('placeholder');\n const readonly = this.hasAttr('readonly');\n const disabled = this.hasAttr('disabled');\n const min = this.getAttr('min');\n const max = this.getAttr('max');\n const step = this.getAttr('step');\n const icon = this.getAttr('icon');\n const iconPos = this.getAttr('icon-pos', 'left') === 'right' ? 'right' : 'left';\n // Slot `icon` vence o atributo `icon`; sem nenhum dos dois, sem ícone.\n const slottedIcon = this.querySelector<HTMLElement>('[slot=\"icon\"]');\n const iconContent = slottedIcon\n ? '<slot name=\"icon\" part=\"icon\"></slot>'\n : (icon ? fenixIconHtml(icon) : '');\n const useIconBox = Boolean(iconContent);\n\n this.setTemplate(`\n ${this.hasAttr('clearable') ? '<div class=\"wrap\" part=\"wrap\">' : ''}\n ${useIconBox ? `<div class=\"field-icon icon-${iconPos}\">` : ''}\n ${useIconBox && iconPos === 'left' ? iconContent : ''}\n <input class=\"field\" part=\"input\" type=\"${esc(type)}\"\n ${placeholder ? `placeholder=\"${esc(placeholder)}\"` : ''}\n ${min ? `min=\"${esc(min)}\"` : ''} ${max ? `max=\"${esc(max)}\"` : ''} ${step ? `step=\"${esc(step)}\"` : ''}\n />\n ${useIconBox && iconPos === 'right' ? iconContent : ''}\n ${useIconBox ? '</div>' : ''}\n ${this.hasAttr('clearable') ? '<button type=\"button\" class=\"clear\" part=\"clear\" aria-label=\"Limpar\" tabindex=\"-1\">×</button></div>' : ''}\n `);\n\n const field = this.root.querySelector<HTMLInputElement>('.field');\n if (!field) return;\n field.value = this.getAttr('value');\n if (disabled) field.setAttribute('disabled', '');\n if (readonly) field.setAttribute('readonly', '');\n\n const emit = (event: string): void => {\n this.value = field.value;\n this.dispatchEvent(\n new CustomEvent(event, { bubbles: true, composed: true, detail: { value: field.value } }),\n );\n };\n // Bloqueia o evento nativo (composed, sem detail) para que só o\n // CustomEvent com detail chegue aos consumidores.\n field.addEventListener('input', (e) => { e.stopPropagation(); emit('input'); });\n field.addEventListener('change', (e) => { e.stopPropagation(); emit('change'); });\n\n // Clearable: botão × que limpa o campo e emite input/change vazios.\n const clearBtn = this.root.querySelector<HTMLButtonElement>('.clear');\n const syncClear = (): void => {\n clearBtn?.toggleAttribute('hidden', field.value === '');\n };\n syncClear();\n clearBtn?.addEventListener('click', () => {\n field.value = '';\n syncClear();\n emit('input');\n emit('change');\n field.focus();\n });\n field.addEventListener('input', syncClear);\n }\n}\n\nexport function defineFxInput(): typeof FxInput {\n return defineElement('fx-input', FxInput);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { FxElement } from '../../core/base';
|
|
|
2
2
|
/**
|
|
3
3
|
* <fx-knob> - Controle giratorio circular para ajuste de valor.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* permite ajustar um valor arrastando o mouse
|
|
6
6
|
* ou usando as setas do teclado. Exibe um arco de progresso circular com
|
|
7
7
|
* o valor central configuravel via valueTemplate.
|
|
8
8
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"knob.d.ts","sourceRoot":"","sources":["../../../src/components/knob/knob.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;;;;;;GAUG;AACH,qBAAa,MAAO,SAAQ,SAAS;IACnC,OAAgB,MAAM,
|
|
1
|
+
{"version":3,"file":"knob.d.ts","sourceRoot":"","sources":["../../../src/components/knob/knob.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C;;;;;;;;;;GAUG;AACH,qBAAa,MAAO,SAAQ,SAAS;IACnC,OAAgB,MAAM,SAoEpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAcjD;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,EAclB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IACD,IAAI,GAAG,CAAC,CAAC,EAAE,MAAM,EAEhB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IACD,IAAI,GAAG,CAAC,CAAC,EAAE,MAAM,EAEhB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IACD,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,EAEjB;IAED,IAAI,IAAI,IAAI,MAAM,CAGjB;IACD,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,EAEjB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IACD,IAAI,WAAW,CAAC,CAAC,EAAE,MAAM,EAExB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IACD,IAAI,UAAU,CAAC,CAAC,EAAE,MAAM,EAEvB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IACD,IAAI,UAAU,CAAC,CAAC,EAAE,MAAM,EAEvB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,CAAC,EAAE,OAAO,EAEtB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,CAAC,EAAE,OAAO,EAEtB;IAED,IAAI,aAAa,IAAI,MAAM,CAE1B;IACD,IAAI,aAAa,CAAC,CAAC,EAAE,MAAM,EAE1B;IAED,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,WAAW,CAAK;cAEL,MAAM,IAAI,IAAI;IAwCjC,OAAO,CAAC,UAAU;IAOlB,gEAAgE;IAChE,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,eAAe;IAsEvB,OAAO,CAAC,YAAY,CAKlB;IAEF,OAAO,CAAC,UAAU,CAIhB;cAEiB,oBAAoB,IAAI,IAAI;CAKhD;AAED,wBAAgB,YAAY,IAAI,OAAO,MAAM,CAE5C"}
|
|
@@ -321,7 +321,9 @@ _FxKnob.styles = css`
|
|
|
321
321
|
outline: none;
|
|
322
322
|
}
|
|
323
323
|
.knob:focus-visible svg {
|
|
324
|
-
|
|
324
|
+
/* Mesmo fallback none dos demais componentes: sem motor de tema (ou com
|
|
325
|
+
effect.focus-ring desligado) não há anel de foco. */
|
|
326
|
+
filter: drop-shadow(var(--fx-effect-focus-ring, none));
|
|
325
327
|
}
|
|
326
328
|
`;
|
|
327
329
|
let FxKnob = _FxKnob;
|