@wrrdev/fenix-ui 1.1.17 → 1.3.0
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 +43 -4
- package/dist/components/datepicker/datepicker.js +4 -4
- package/dist/components/datepicker/datepicker.js.map +1 -1
- package/dist/components/editor/editor.js +3 -3
- package/dist/components/editor/editor.js.map +1 -1
- package/dist/components/floatlabel/floatlabel.d.ts +5 -0
- package/dist/components/floatlabel/floatlabel.d.ts.map +1 -1
- package/dist/components/floatlabel/floatlabel.js +52 -25
- package/dist/components/floatlabel/floatlabel.js.map +1 -1
- package/dist/components/input/input.d.ts +11 -0
- package/dist/components/input/input.d.ts.map +1 -1
- package/dist/components/input/input.js +11 -0
- package/dist/components/input/input.js.map +1 -1
- package/dist/components/multiselect/multiselect.js +1 -1
- package/dist/components/multiselect/multiselect.js.map +1 -1
- package/dist/components/orderlist/orderlist.js +1 -1
- package/dist/components/orderlist/orderlist.js.map +1 -1
- package/dist/components/picklist/picklist.js +1 -1
- package/dist/components/picklist/picklist.js.map +1 -1
- package/dist/components/select/select.js +1 -1
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/table/table.d.ts.map +1 -1
- package/dist/components/table/table.js +14 -1
- package/dist/components/table/table.js.map +1 -1
- package/dist/components/textarea/textarea.d.ts +7 -0
- package/dist/components/textarea/textarea.d.ts.map +1 -1
- package/dist/components/textarea/textarea.js +22 -1
- package/dist/components/textarea/textarea.js.map +1 -1
- package/dist/core/jsx.d.ts +10 -0
- package/dist/core/jsx.d.ts.map +1 -1
- package/dist/core/jsx.js.map +1 -1
- package/dist/core/tokens.d.ts +2 -0
- package/dist/core/tokens.d.ts.map +1 -1
- package/dist/core/tokens.js +9 -0
- package/dist/core/tokens.js.map +1 -1
- package/dist/docs/app.d.ts.map +1 -1
- package/dist/docs/componentes/autocomplete.doc.d.ts.map +1 -1
- package/dist/docs/componentes/datepicker.doc.d.ts.map +1 -1
- package/dist/docs/componentes/editor.doc.d.ts.map +1 -1
- package/dist/docs/componentes/floatlabel.doc.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/orderlist.doc.d.ts.map +1 -1
- package/dist/docs/componentes/picklist.doc.d.ts.map +1 -1
- package/dist/docs/componentes/select.doc.d.ts.map +1 -1
- package/dist/docs/componentes/table.doc.d.ts.map +1 -1
- package/dist/docs/componentes/textarea.doc.d.ts.map +1 -1
- package/dist/docs/shared.d.ts +15 -0
- package/dist/docs/shared.d.ts.map +1 -1
- package/dist/docs/shell.d.ts +10 -1
- package/dist/docs/shell.d.ts.map +1 -1
- package/dist/docs/theme-reference.d.ts +53 -0
- package/dist/docs/theme-reference.d.ts.map +1 -0
- package/dist/docs/types.d.ts +2 -0
- package/dist/docs/types.d.ts.map +1 -1
- package/dist/fenix-ui.umd.min.js +200 -169
- package/dist/fenix-ui4.esm.js +119 -38
- package/dist/fenix-ui4.esm.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"picklist.js","sources":["../../../src/components/picklist/picklist.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\n\nexport interface PickListItem {\n [key: string]: unknown;\n}\n\n/**\n * <fx-picklist> - Componente para transferir itens entre duas listas.\n *\n * Permite mover itens entre uma lista de origem e uma lista de destino.\n * Suporta filtro, seleção múltipla, checkbox e templates customizados.\n *\n * Atributos: source, target, source-key, target-key, filter, filter-by,\n * filter-placeholder, dragdrop, striped, selection-mode, source-label, target-label.\n * Evento: `move-to-target` (composed, detail: { items }).\n * Evento: `move-to-source` (composed, detail: { items }).\n * Evento: `selection-change-source` (composed, detail: { selection }).\n * Evento: `selection-change-target` (composed, detail: { selection }).\n */\nexport class FxPickList extends FxElement {\n static override styles = css`\n :host {\n display: block;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n --picklist-primary: var(--fx-color-primary, #3b82f6);\n --picklist-border: var(--fx-border-default, #e2e8f0);\n --picklist-bg: var(--fx-surface-background, #ffffff);\n --picklist-bg-hover: var(--fx-surface-surface-hover, #f1f5f9);\n --picklist-text: var(--fx-text-default, #1e293b);\n --picklist-text-muted: var(--fx-text-muted, #64748b);\n --picklist-radius: var(--fx-radius-md, 8px);\n --picklist-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n --picklist-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n }\n * { box-sizing: border-box; }\n .container {\n display: flex;\n gap: var(--fx-space-sm, 8px);\n align-items: stretch;\n }\n .list-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--fx-space-sm, 8px);\n min-width: 0;\n }\n .list-label {\n font-weight: 600;\n color: var(--picklist-text);\n font-size: calc(var(--fx-font-size) - 1px);\n }\n .select-all-bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);\n background: linear-gradient(135deg, var(--picklist-bg), var(--picklist-bg-hover));\n border: 1px solid var(--picklist-border);\n border-radius: var(--picklist-radius);\n font-size: 0.9em;\n font-weight: 500;\n }\n .select-all-bar label {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm, 10px);\n cursor: pointer;\n user-select: none;\n color: var(--picklist-text);\n }\n .select-all-bar input[type=\"checkbox\"] {\n width: 18px;\n height: 18px;\n accent-color: var(--picklist-primary);\n cursor: pointer;\n }\n .selection-count {\n font-size: 0.85em;\n color: var(--picklist-primary);\n background: color-mix(in srgb, var(--picklist-primary) 12%, transparent);\n padding: 4px 12px;\n border-radius: 20px;\n font-weight: 600;\n }\n .controls {\n display: flex;\n flex-direction: column;\n gap: 4px;\n justify-content: center;\n padding: var(--fx-space-xs, 6px);\n background: var(--picklist-bg);\n border: 1px solid var(--picklist-border);\n border-radius: var(--picklist-radius);\n box-shadow: var(--picklist-shadow);\n height: fit-content;\n position: sticky;\n top: 0;\n align-self: center;\n }\n .control-group {\n display: flex;\n flex-direction: column;\n gap: 3px;\n }\n .control-group + .control-group {\n margin-top: 4px;\n padding-top: 6px;\n border-top: 1px solid var(--picklist-border);\n }\n .list-wrapper {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--fx-space-sm, 8px);\n }\n .filter-wrapper {\n margin-bottom: var(--fx-space-xs, 4px);\n }\n .filter-input {\n width: 100%;\n box-sizing: border-box;\n padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);\n padding-left: 42px;\n border: 1.5px solid var(--picklist-border);\n border-radius: var(--picklist-radius);\n font-family: inherit;\n font-size: inherit;\n color: var(--picklist-text);\n background: var(--picklist-bg) url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E\") no-repeat 14px center;\n transition: var(--picklist-transition);\n }\n .filter-input:focus {\n outline: none;\n border-color: var(--picklist-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n .filter-input::placeholder {\n color: var(--picklist-text-muted);\n }\n .list {\n list-style: none;\n margin: 0;\n padding: 0;\n border: 1px solid var(--picklist-border);\n border-radius: var(--picklist-radius);\n overflow: hidden;\n box-shadow: var(--picklist-shadow);\n min-height: 200px;\n max-height: 450px;\n overflow-y: auto;\n flex: 1;\n }\n .list::-webkit-scrollbar { width: 6px; }\n .list::-webkit-scrollbar-track { background: transparent; }\n .list::-webkit-scrollbar-thumb { background: var(--picklist-border); border-radius: 3px; }\n .list::-webkit-scrollbar-thumb:hover { background: var(--picklist-text-muted); }\n :host([striped]) .list-item:nth-child(even) {\n background: var(--fx-surface-surface, #f8fafc);\n }\n .list-item {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm, 10px);\n padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);\n background: var(--picklist-bg);\n border-bottom: 1px solid var(--picklist-border);\n cursor: pointer;\n user-select: none;\n transition: var(--picklist-transition);\n }\n .list-item:last-child { border-bottom: none; }\n .list-item:hover { background: var(--picklist-bg-hover); }\n .list-item.selected {\n background: color-mix(in srgb, var(--picklist-primary) 8%, transparent);\n border-left: 3px solid var(--picklist-primary);\n padding-left: 11px;\n }\n .list-item:focus-visible {\n outline: none;\n background: color-mix(in srgb, var(--picklist-primary) 15%, transparent);\n }\n .checkbox {\n flex-shrink: 0;\n width: 18px;\n height: 18px;\n accent-color: var(--picklist-primary);\n cursor: pointer;\n transition: var(--picklist-transition);\n }\n .checkbox:hover { transform: scale(1.1); }\n .item-content {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .empty-message {\n padding: var(--fx-space-xl, 32px);\n text-align: center;\n color: var(--picklist-text-muted);\n font-style: italic;\n }\n button.control-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 42px;\n height: 38px;\n padding: 0;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--picklist-text-muted);\n cursor: pointer;\n font-size: 16px;\n line-height: 1;\n transition: var(--picklist-transition);\n position: relative;\n }\n button.control-btn:hover:not(:disabled) {\n background: var(--picklist-bg-hover);\n color: var(--picklist-primary);\n transform: scale(1.1);\n }\n button.control-btn:active:not(:disabled) {\n transform: scale(0.92);\n background: color-mix(in srgb, var(--picklist-primary) 15%, transparent);\n }\n button.control-btn:focus-visible {\n outline: none;\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n button.control-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n transform: none;\n }\n .control-btn-icon { font-size: 18px; line-height: 1; }\n\n button.control-btn:hover::after {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n @media (max-width: 640px) {\n .container { flex-direction: column; }\n .controls {\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: center;\n position: relative;\n }\n .control-group { flex-direction: row; }\n .control-group + .control-group {\n margin-top: 0;\n margin-left: 4px;\n padding-top: 0;\n padding-left: 4px;\n border-top: none;\n border-left: 1px solid var(--picklist-border);\n }\n button.control-btn { width: 44px; height: 40px; }\n button.control-btn::after { display: none; }\n .list { max-height: 300px; min-height: 150px; }\n }\n @keyframes slideIn {\n from { opacity: 0; transform: translateX(-10px); }\n to { opacity: 1; transform: translateX(0); }\n }\n .list-item { animation: slideIn 0.2s ease-out; }\n `;\n\n static override get observedAttributes(): string[] {\n return [\n 'source',\n 'target',\n 'source-key',\n 'target-key',\n 'filter',\n 'filter-by',\n 'filter-placeholder',\n 'dragdrop',\n 'striped',\n 'selection-mode',\n 'show-select-all',\n 'source-label',\n 'target-label',\n ];\n }\n\n set source(value: PickListItem[]) {\n this._source = value;\n this._filteredSource = null;\n this.render();\n }\n get source(): PickListItem[] {\n return this._source;\n }\n private _source: PickListItem[] = [];\n private _filteredSource: PickListItem[] | null = null;\n\n set target(value: PickListItem[]) {\n this._target = value;\n this._filteredTarget = null;\n this.render();\n }\n get target(): PickListItem[] {\n return this._target;\n }\n private _target: PickListItem[] = [];\n private _filteredTarget: PickListItem[] | null = null;\n\n set sourceSelection(value: PickListItem[]) {\n this._sourceSelection = value;\n this.render();\n }\n get sourceSelection(): PickListItem[] {\n return this._sourceSelection;\n }\n private _sourceSelection: PickListItem[] = [];\n\n set targetSelection(value: PickListItem[]) {\n this._targetSelection = value;\n this.render();\n }\n get targetSelection(): PickListItem[] {\n return this._targetSelection;\n }\n private _targetSelection: PickListItem[] = [];\n\n get sourceKey(): string {\n return this.getAttr('source-key', '');\n }\n set sourceKey(v: string) {\n this.setAttribute('source-key', v);\n }\n\n get targetKey(): string {\n return this.getAttr('target-key', '');\n }\n set targetKey(v: string) {\n this.setAttribute('target-key', v);\n }\n\n get filter(): boolean {\n return this.hasAttr('filter');\n }\n set filter(v: boolean) {\n this.toggleAttr('filter', v);\n }\n\n get filterBy(): string {\n return this.getAttr('filter-by', 'label');\n }\n set filterBy(v: string) {\n this.setAttribute('filter-by', v);\n }\n\n get filterPlaceholder(): string {\n return this.getAttr('filter-placeholder', 'Buscar...');\n }\n set filterPlaceholder(v: string) {\n this.setAttribute('filter-placeholder', v);\n }\n\n get dragdrop(): boolean {\n return this.hasAttr('dragdrop');\n }\n set dragdrop(v: boolean) {\n this.toggleAttr('dragdrop', v);\n }\n\n get striped(): boolean {\n return this.hasAttr('striped');\n }\n set striped(v: boolean) {\n this.toggleAttr('striped', v);\n }\n\n get selectionMode(): string {\n const s = this.getAttr('selection-mode', '');\n return s === 'single' || s === 'multiple' ? s : '';\n }\n set selectionMode(v: string) {\n this.setAttribute('selection-mode', v);\n }\n\n get showSelectAll(): boolean {\n return this.hasAttr('show-select-all');\n }\n set showSelectAll(v: boolean) {\n this.toggleAttr('show-select-all', v);\n }\n\n get sourceLabel(): string {\n return this.getAttr('source-label', 'Disponíveis');\n }\n set sourceLabel(v: string) {\n this.setAttribute('source-label', v);\n }\n\n get targetLabel(): string {\n return this.getAttr('target-label', 'Selecionados');\n }\n set targetLabel(v: string) {\n this.setAttribute('target-label', v);\n }\n\n get sourceFilterValue(): string {\n return this._sourceFilterValue;\n }\n set sourceFilterValue(v: string) {\n this._sourceFilterValue = v;\n this._applySourceFilter();\n this._updateListDisplay();\n }\n private _sourceFilterValue = '';\n\n get targetFilterValue(): string {\n return this._targetFilterValue;\n }\n set targetFilterValue(v: string) {\n this._targetFilterValue = v;\n this._applyTargetFilter();\n this._updateListDisplay();\n }\n private _targetFilterValue = '';\n private _filterListenersAttached = false;\n\n private _optionTemplate: ((item: PickListItem) => string) | null = null;\n\n setOptionTemplate(template: (item: PickListItem) => string): void {\n this._optionTemplate = template;\n this.render();\n }\n\n protected override connectedCallback(): void {\n this._parseSourceAttribute();\n this._parseTargetAttribute();\n super.connectedCallback();\n }\n\n protected override attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (this.getAttr('source', '') !== '') {\n this._parseSourceAttribute();\n }\n if (this.getAttr('target', '') !== '') {\n this._parseTargetAttribute();\n }\n super.attributeChangedCallback(name, oldValue, newValue);\n }\n\n private _parseSourceAttribute(): void {\n const dataAttr = this.getAttr('source', '');\n if (dataAttr) {\n try {\n this._source = JSON.parse(dataAttr);\n this._filteredSource = null;\n } catch {\n this._source = [];\n }\n }\n }\n\n private _parseTargetAttribute(): void {\n const dataAttr = this.getAttr('target', '');\n if (dataAttr) {\n try {\n this._target = JSON.parse(dataAttr);\n this._filteredTarget = null;\n } catch {\n this._target = [];\n }\n }\n }\n\n private _applySourceFilter(): void {\n if (!this._sourceFilterValue) {\n this._filteredSource = null;\n return;\n }\n const filterFields = this.filterBy.split(',').map(f => f.trim());\n this._filteredSource = this._source.filter(item => {\n return filterFields.some(field => {\n const value = item[field];\n if (value == null) return false;\n return String(value).toLowerCase().includes(this._sourceFilterValue.toLowerCase());\n });\n });\n }\n\n private _applyTargetFilter(): void {\n if (!this._targetFilterValue) {\n this._filteredTarget = null;\n return;\n }\n const filterFields = this.filterBy.split(',').map(f => f.trim());\n this._filteredTarget = this._target.filter(item => {\n return filterFields.some(field => {\n const value = item[field];\n if (value == null) return false;\n return String(value).toLowerCase().includes(this._targetFilterValue.toLowerCase());\n });\n });\n }\n\n private _getDisplaySource(): PickListItem[] {\n return this._filteredSource || this._source;\n }\n\n private _getDisplayTarget(): PickListItem[] {\n return this._filteredTarget || this._target;\n }\n\n private _getItemKey(item: PickListItem, index: number, isSource: boolean): string {\n const keyField = isSource ? this.sourceKey : this.targetKey;\n if (keyField && item[keyField] != null) {\n return String(item[keyField]);\n }\n if (item['id'] != null) return String(item['id']);\n if (item['key'] != null) return String(item['key']);\n if (item['label'] != null) return String(item['label']);\n if (item['name'] != null) return String(item['name']);\n if (item['value'] != null) return String(item['value']);\n return String(index);\n }\n\n private _getItemLabel(item: PickListItem): string {\n const fields = ['label', 'name', 'title', 'text', 'value'];\n for (const field of fields) {\n if (item[field] != null) {\n return String(item[field]);\n }\n }\n return JSON.stringify(item);\n }\n\n private _isSourceSelected(item: PickListItem, index: number): boolean {\n return this._sourceSelection.some(s => this._getItemKey(s, -1, true) === this._getItemKey(item, index, true));\n }\n\n private _isTargetSelected(item: PickListItem, index: number): boolean {\n return this._targetSelection.some(s => this._getItemKey(s, -1, false) === this._getItemKey(item, index, false));\n }\n\n private _emitMoveToTarget(): void {\n this.dispatchEvent(new CustomEvent('move-to-target', {\n bubbles: true,\n composed: true,\n detail: { items: [...this._sourceSelection], source: [...this._source], target: [...this._target] },\n }));\n }\n\n private _emitMoveToSource(): void {\n this.dispatchEvent(new CustomEvent('move-to-source', {\n bubbles: true,\n composed: true,\n detail: { items: [...this._targetSelection], source: [...this._source], target: [...this._target] },\n }));\n }\n\n private _emitSelectionChangeSource(): void {\n this.dispatchEvent(new CustomEvent('selection-change-source', {\n bubbles: true,\n composed: true,\n detail: { selection: [...this._sourceSelection] },\n }));\n }\n\n private _emitSelectionChangeTarget(): void {\n this.dispatchEvent(new CustomEvent('selection-change-target', {\n bubbles: true,\n composed: true,\n detail: { selection: [...this._targetSelection] },\n }));\n }\n\n protected override render(): void {\n const dSrc = this._getDisplaySource();\n const dTgt = this._getDisplayTarget();\n const hasSel = this.selectionMode;\n const showAll = hasSel === 'multiple' && this.showSelectAll;\n const srcItems = dSrc.length === 0 ? `<li class=\"empty-message\">${this.filter ? 'Nenhum resultado' : 'Nenhum item'}</li>` : dSrc.map((item, i) => `<li class=\"list-item${this._isSourceSelected(item, i) ? ' selected' : ''}\" data-index=\"${i}\" data-list=\"source\" tabindex=\"0\">${hasSel ? '<input type=\"checkbox\" class=\"checkbox\"' + (this._isSourceSelected(item, i) ? ' checked' : '') + ' />' : ''}<span class=\"item-content\">${this._optionTemplate ? this._optionTemplate(item) : esc(this._getItemLabel(item))}</span></li>`).join('');\n const tgtItems = dTgt.length === 0 ? `<li class=\"empty-message\">${this.filter ? 'Nenhum resultado' : 'Nenhum selecionado'}</li>` : dTgt.map((item, i) => `<li class=\"list-item${this._isTargetSelected(item, i) ? ' selected' : ''}\" data-index=\"${i}\" data-list=\"target\" tabindex=\"0\">${hasSel ? '<input type=\"checkbox\" class=\"checkbox\"' + (this._isTargetSelected(item, i) ? ' checked' : '') + ' />' : ''}<span class=\"item-content\">${this._optionTemplate ? this._optionTemplate(item) : esc(this._getItemLabel(item))}</span></li>`).join('');\n const srcAllBar = showAll ? `<div class=\"select-all-bar\" part=\"select-all-bar\"><label><input type=\"checkbox\" class=\"select-all-checkbox\" data-list=\"source\" ${this._sourceSelection.length > 0 && this._sourceSelection.length === this._source.length ? 'checked' : ''} aria-label=\"Selecionar todos da origem\" /> Selecionar Todos</label><span class=\"selection-count\">${this._sourceSelection.length} selecionado(s)</span></div>` : '';\n const tgtAllBar = showAll ? `<div class=\"select-all-bar\" part=\"select-all-bar\"><label><input type=\"checkbox\" class=\"select-all-checkbox\" data-list=\"target\" ${this._targetSelection.length > 0 && this._targetSelection.length === this._target.length ? 'checked' : ''} aria-label=\"Selecionar todos do destino\" /> Selecionar Todos</label><span class=\"selection-count\">${this._targetSelection.length} selecionado(s)</span></div>` : '';\n\n this.setTemplate(`<div class=\"container\"><div class=\"list-container\"><div class=\"list-label\">${esc(this.sourceLabel)} (${this._source.length})</div>${this.filter ? '<div class=\"filter-wrapper\"><input type=\"text\" class=\"filter-input source-filter\" placeholder=\"' + this.filterPlaceholder + '\" value=\"' + esc(this._sourceFilterValue) + '\" /></div>' : ''}${srcAllBar}<div class=\"list-wrapper\"><ul class=\"list source-list\" role=\"listbox\" tabindex=\"0\">${srcItems}</ul></div></div><div class=\"controls\"><div class=\"control-group\"><button class=\"control-btn\" data-action=\"move-all-target\" part=\"control-btn\" aria-label=\"Mover todos para destino\"><span class=\"control-btn-icon\">»</span></button><button class=\"control-btn\" data-action=\"move-target\" part=\"control-btn\" aria-label=\"Mover para destino\"><span class=\"control-btn-icon\">→</span></button></div><div class=\"control-group\"><button class=\"control-btn\" data-action=\"move-source\" part=\"control-btn\" aria-label=\"Mover para origem\"><span class=\"control-btn-icon\">←</span></button><button class=\"control-btn\" data-action=\"move-all-source\" part=\"control-btn\" aria-label=\"Mover todos para origem\"><span class=\"control-btn-icon\">«</span></button></div></div><div class=\"list-container\"><div class=\"list-label\">${esc(this.targetLabel)} (${this._target.length})</div>${this.filter ? '<div class=\"filter-wrapper\"><input type=\"text\" class=\"filter-input target-filter\" placeholder=\"' + this.filterPlaceholder + '\" value=\"' + esc(this._targetFilterValue) + '\" /></div>' : ''}${tgtAllBar}<div class=\"list-wrapper\"><ul class=\"list target-list\" role=\"listbox\" tabindex=\"0\">${tgtItems}</ul></div></div></div>`);\n\n this._attachListeners();\n }\n\n private _attachListeners(): void {\n // Listeners delegados no root, anexados uma unica vez (sobrevivem a re-renders)\n if (!this._filterListenersAttached) {\n this._filterListenersAttached = true;\n\n this.root.addEventListener('input', (e) => {\n const t = e.target as HTMLElement;\n if (t.classList.contains('select-all-checkbox')) {\n this._handleSelectAll(t as HTMLInputElement);\n return;\n }\n if (t.classList.contains('source-filter')) {\n this.sourceFilterValue = (t as HTMLInputElement).value;\n } else if (t.classList.contains('target-filter')) {\n this.targetFilterValue = (t as HTMLInputElement).value;\n }\n });\n\n this.root.addEventListener('click', (e) => {\n const t = e.target as HTMLElement;\n const btn = t.closest('.control-btn') as HTMLButtonElement | null;\n if (btn) {\n switch (btn.dataset.action) {\n case 'move-target': this._moveToTarget(); break;\n case 'move-all-target': this._moveAllToTarget(); break;\n case 'move-source': this._moveToSource(); break;\n case 'move-all-source': this._moveAllToSource(); break;\n }\n return;\n }\n const el = t.closest('.list-item') as HTMLElement | null;\n if (!el) return;\n const isSrc = el.dataset.list === 'source';\n const idx = Number(el.dataset.index);\n const item = (isSrc ? this._getDisplaySource() : this._getDisplayTarget())[idx];\n if (isSrc) this._toggleSourceSelection(item, idx); else this._toggleTargetSelection(item, idx);\n });\n }\n this._updateControlsState();\n }\n\n private _handleSelectAll(checkbox: HTMLInputElement): void {\n const isSrc = checkbox.dataset.list === 'source';\n if (isSrc) {\n this._sourceSelection = checkbox.checked ? [...this._getDisplaySource()] : [];\n this._emitSelectionChangeSource();\n } else {\n this._targetSelection = checkbox.checked ? [...this._getDisplayTarget()] : [];\n this._emitSelectionChangeTarget();\n }\n this._updateSelectionDisplay();\n this._updateControlsState();\n }\n\n /**\n * Atualiza a selecao visual in-place (classes e checkboxes dos itens existentes),\n * sem recriar o DOM — mantendo referencias de elementos validas durante cliques.\n */\n private _updateSelectionDisplay(): void {\n const updateList = (listSel: HTMLElement | null, isSelFn: (item: PickListItem, i: number) => boolean, getData: () => PickListItem[]): void => {\n if (!listSel) return;\n listSel.querySelectorAll<HTMLElement>('.list-item').forEach(el => {\n const idx = Number(el.dataset.index);\n const selected = isSelFn(getData()[idx], idx);\n el.classList.toggle('selected', selected);\n el.setAttribute('aria-selected', String(selected));\n const cb = el.querySelector<HTMLInputElement>('.checkbox');\n if (cb) cb.checked = selected;\n });\n };\n updateList(this.root.querySelector('.source-list'), (it, i) => this._isSourceSelected(it, i), () => this._getDisplaySource());\n updateList(this.root.querySelector('.target-list'), (it, i) => this._isTargetSelected(it, i), () => this._getDisplayTarget());\n this._updateSelectAllBars();\n }\n\n /** Sincroniza as barras \"Selecionar Todos\" (checkbox + contador) sem re-render completo. */\n private _updateSelectAllBars(): void {\n if (!(this.selectionMode === 'multiple' && this.showSelectAll)) return;\n const bars = [\n { el: this.root.querySelector<HTMLInputElement>('.select-all-checkbox[data-list=\"source\"]'), total: this._source.length, sel: this._sourceSelection.length },\n { el: this.root.querySelector<HTMLInputElement>('.select-all-checkbox[data-list=\"target\"]'), total: this._target.length, sel: this._targetSelection.length },\n ];\n bars.forEach(({ el, total, sel }) => {\n if (!el) return;\n el.checked = total > 0 && sel === total;\n const count = el.closest('.select-all-bar')?.querySelector('.selection-count');\n if (count) count.textContent = `${sel} selecionado(s)`;\n });\n }\n\n private _updateControlsState(): void {\n this.root.querySelectorAll<HTMLButtonElement>('.control-btn').forEach(btn => {\n const a = btn.dataset.action;\n btn.disabled = (a === 'move-target' && this._sourceSelection.length === 0) || (a === 'move-all-target' && this._source.length === 0) || (a === 'move-source' && this._targetSelection.length === 0) || (a === 'move-all-source' && this._target.length === 0);\n });\n }\n\n private _moveToTarget(): void {\n if (!this._sourceSelection.length) return;\n const items = [...this._sourceSelection];\n this._source = this._source.filter(s => !items.some(i => this._getItemKey(i, -1, true) === this._getItemKey(s, -1, true)));\n this._target = [...this._target, ...items];\n this._sourceSelection = [];\n this._filteredSource = null;\n this._filteredTarget = null;\n this._updateListDisplay();\n this._updateControlsState();\n this._emitMoveToTarget();\n }\n\n private _moveToSource(): void {\n if (!this._targetSelection.length) return;\n const items = [...this._targetSelection];\n this._target = this._target.filter(t => !items.some(i => this._getItemKey(i, -1, false) === this._getItemKey(t, -1, false)));\n this._source = [...this._source, ...items];\n this._targetSelection = [];\n this._filteredSource = null;\n this._filteredTarget = null;\n this._updateListDisplay();\n this._updateControlsState();\n this._emitMoveToSource();\n }\n\n private _moveAllToTarget(): void {\n const items = [...this._source];\n this._source = [];\n this._target = [...this._target, ...items];\n this._sourceSelection = [];\n this._filteredSource = null;\n this._filteredTarget = null;\n this._updateListDisplay();\n this._updateControlsState();\n this._emitMoveToTarget();\n }\n\n private _moveAllToSource(): void {\n const items = [...this._target];\n this._target = [];\n this._source = [...this._source, ...items];\n this._targetSelection = [];\n this._filteredSource = null;\n this._filteredTarget = null;\n this._updateListDisplay();\n this._updateControlsState();\n this._emitMoveToSource();\n }\n\n private _toggleSourceSelection(item: PickListItem, index: number): void {\n // Sem selection-mode definido, permite selecao simples (um item por vez)\n const mode = this.selectionMode || 'single';\n const key = this._getItemKey(item, index, true);\n const idx = this._sourceSelection.findIndex(s => this._getItemKey(s, -1, true) === key);\n if (idx >= 0) {\n this._sourceSelection.splice(idx, 1);\n } else if (mode === 'multiple') {\n this._sourceSelection.push(item);\n } else {\n this._sourceSelection = [item];\n }\n this._emitSelectionChangeSource();\n this._updateSelectionDisplay();\n this._updateControlsState();\n }\n\n private _toggleTargetSelection(item: PickListItem, index: number): void {\n // Sem selection-mode definido, permite selecao simples (um item por vez)\n const mode = this.selectionMode || 'single';\n const key = this._getItemKey(item, index, false);\n const idx = this._targetSelection.findIndex(s => this._getItemKey(s, -1, false) === key);\n if (idx >= 0) {\n this._targetSelection.splice(idx, 1);\n } else if (mode === 'multiple') {\n this._targetSelection.push(item);\n } else {\n this._targetSelection = [item];\n }\n this._emitSelectionChangeTarget();\n this._updateSelectionDisplay();\n this._updateControlsState();\n }\n\n private _updateListDisplay(): void {\n const srcWrapper = this.root.querySelector('.source-list')?.parentElement;\n const tgtWrapper = this.root.querySelector('.target-list')?.parentElement;\n const srcLabel = this.root.querySelector('.list-container:first-of-type .list-label');\n const tgtLabel = this.root.querySelector('.list-container:last-of-type .list-label');\n if (!srcWrapper || !tgtWrapper) { this.render(); return; }\n const dSrc = this._getDisplaySource();\n const dTgt = this._getDisplayTarget();\n const hasSel = this.selectionMode;\n const srcItems = dSrc.length === 0 ? `<li class=\"empty-message\" part=\"empty-message\">${this.filter ? 'Nenhum resultado' : 'Nenhum item'}</li>` : dSrc.map((item, i) => `<li class=\"list-item${this._isSourceSelected(item, i) ? ' selected' : ''}\" part=\"list-item\" data-index=\"${i}\" data-list=\"source\" role=\"option\" aria-selected=\"${this._isSourceSelected(item, i)}\" tabindex=\"0\">${hasSel ? '<input type=\"checkbox\" class=\"checkbox\" part=\"checkbox\"' + (this._isSourceSelected(item, i) ? ' checked' : '') + ' />' : ''}<span class=\"item-content\" part=\"item-content\">${this._optionTemplate ? this._optionTemplate(item) : esc(this._getItemLabel(item))}</span></li>`).join('');\n const tgtItems = dTgt.length === 0 ? `<li class=\"empty-message\" part=\"empty-message\">${this.filter ? 'Nenhum resultado' : 'Nenhum selecionado'}</li>` : dTgt.map((item, i) => `<li class=\"list-item${this._isTargetSelected(item, i) ? ' selected' : ''}\" part=\"list-item\" data-index=\"${i}\" data-list=\"target\" role=\"option\" aria-selected=\"${this._isTargetSelected(item, i)}\" tabindex=\"0\">${hasSel ? '<input type=\"checkbox\" class=\"checkbox\" part=\"checkbox\"' + (this._isTargetSelected(item, i) ? ' checked' : '') + ' />' : ''}<span class=\"item-content\" part=\"item-content\">${this._optionTemplate ? this._optionTemplate(item) : esc(this._getItemLabel(item))}</span></li>`).join('');\n srcWrapper.innerHTML = `<ul class=\"list source-list\" role=\"listbox\" tabindex=\"0\">${srcItems}</ul>`;\n tgtWrapper.innerHTML = `<ul class=\"list target-list\" role=\"listbox\" tabindex=\"0\">${tgtItems}</ul>`;\n if (srcLabel) srcLabel.textContent = `${this.sourceLabel} (${this._source.length})`;\n if (tgtLabel) tgtLabel.textContent = `${this.targetLabel} (${this._target.length})`;\n this._updateSelectAllBars();\n this._attachListeners();\n }\n}\n\nexport function defineFxPickList(): typeof FxPickList {\n return defineElement('fx-picklist', FxPickList);\n}"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"picklist.js","sources":["../../../src/components/picklist/picklist.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\n\nexport interface PickListItem {\n [key: string]: unknown;\n}\n\n/**\n * <fx-picklist> - Componente para transferir itens entre duas listas.\n *\n * Permite mover itens entre uma lista de origem e uma lista de destino.\n * Suporta filtro, seleção múltipla, checkbox e templates customizados.\n *\n * Atributos: source, target, source-key, target-key, filter, filter-by,\n * filter-placeholder, dragdrop, striped, selection-mode, source-label, target-label.\n * Evento: `move-to-target` (composed, detail: { items }).\n * Evento: `move-to-source` (composed, detail: { items }).\n * Evento: `selection-change-source` (composed, detail: { selection }).\n * Evento: `selection-change-target` (composed, detail: { selection }).\n */\nexport class FxPickList extends FxElement {\n static override styles = css`\n :host {\n display: block;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n --picklist-primary: var(--fx-color-primary, #3b82f6);\n --picklist-border: var(--fx-border-default, #e2e8f0);\n --picklist-bg: var(--fx-surface-background, #ffffff);\n --picklist-bg-hover: var(--fx-surface-surface-hover, #f1f5f9);\n --picklist-text: var(--fx-text-default, #1e293b);\n --picklist-text-muted: var(--fx-text-muted, #64748b);\n --picklist-radius: var(--fx-radius-md, 8px);\n --picklist-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n --picklist-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n }\n * { box-sizing: border-box; }\n .container {\n display: flex;\n gap: var(--fx-space-sm, 8px);\n align-items: stretch;\n }\n .list-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--fx-space-sm, 8px);\n min-width: 0;\n }\n .list-label {\n font-weight: 600;\n color: var(--picklist-text);\n font-size: calc(var(--fx-font-size) - 1px);\n }\n .select-all-bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);\n background: linear-gradient(135deg, var(--picklist-bg), var(--picklist-bg-hover));\n border: 1px solid var(--picklist-border);\n border-radius: var(--picklist-radius);\n font-size: 0.9em;\n font-weight: 500;\n }\n .select-all-bar label {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm, 10px);\n cursor: pointer;\n user-select: none;\n color: var(--picklist-text);\n }\n .select-all-bar input[type=\"checkbox\"] {\n width: 18px;\n height: 18px;\n accent-color: var(--picklist-primary);\n cursor: pointer;\n }\n .selection-count {\n font-size: 0.85em;\n color: var(--picklist-primary);\n background: color-mix(in srgb, var(--picklist-primary) 12%, transparent);\n padding: 4px 12px;\n border-radius: 20px;\n font-weight: 600;\n }\n .controls {\n display: flex;\n flex-direction: column;\n gap: 4px;\n justify-content: center;\n padding: var(--fx-space-xs, 6px);\n background: var(--picklist-bg);\n border: 1px solid var(--picklist-border);\n border-radius: var(--picklist-radius);\n box-shadow: var(--picklist-shadow);\n height: fit-content;\n position: sticky;\n top: 0;\n align-self: center;\n }\n .control-group {\n display: flex;\n flex-direction: column;\n gap: 3px;\n }\n .control-group + .control-group {\n margin-top: 4px;\n padding-top: 6px;\n border-top: 1px solid var(--picklist-border);\n }\n .list-wrapper {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--fx-space-sm, 8px);\n }\n .filter-wrapper {\n margin-bottom: var(--fx-space-xs, 4px);\n }\n .filter-input {\n width: 100%;\n box-sizing: border-box;\n padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);\n padding-left: 42px;\n border: 1.5px solid var(--picklist-border);\n border-radius: var(--picklist-radius);\n font-family: inherit;\n font-size: inherit;\n color: var(--picklist-text);\n background: var(--picklist-bg) url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E\") no-repeat 14px center;\n transition: var(--picklist-transition);\n }\n .filter-input:focus {\n outline: none;\n border-color: var(--picklist-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n .filter-input::placeholder {\n color: var(--picklist-text-muted);\n }\n .list {\n list-style: none;\n margin: 0;\n padding: 0;\n border: 1px solid var(--picklist-border);\n border-radius: var(--picklist-radius);\n overflow: hidden;\n box-shadow: var(--picklist-shadow);\n min-height: 200px;\n max-height: 450px;\n overflow-y: auto;\n flex: 1;\n }\n .list::-webkit-scrollbar { width: 6px; }\n .list::-webkit-scrollbar-track { background: transparent; }\n .list::-webkit-scrollbar-thumb { background: var(--picklist-border); border-radius: 3px; }\n .list::-webkit-scrollbar-thumb:hover { background: var(--picklist-text-muted); }\n :host([striped]) .list-item:nth-child(even) {\n background: var(--fx-surface-surface, #f8fafc);\n }\n .list-item {\n display: flex;\n align-items: center;\n gap: var(--fx-space-sm, 10px);\n padding: var(--fx-space-sm, 10px) var(--fx-space-md, 14px);\n background: var(--picklist-bg);\n border-bottom: 1px solid var(--picklist-border);\n cursor: pointer;\n user-select: none;\n transition: var(--picklist-transition);\n }\n .list-item:last-child { border-bottom: none; }\n .list-item:hover { background: var(--picklist-bg-hover); }\n .list-item.selected {\n background: color-mix(in srgb, var(--picklist-primary) 8%, transparent);\n border-left: 3px solid var(--picklist-primary);\n padding-left: 11px;\n }\n .list-item:focus-visible {\n outline: none;\n background: color-mix(in srgb, var(--picklist-primary) 15%, transparent);\n }\n .checkbox {\n flex-shrink: 0;\n width: 18px;\n height: 18px;\n accent-color: var(--picklist-primary);\n cursor: pointer;\n transition: var(--picklist-transition);\n }\n .checkbox:hover { transform: scale(1.1); }\n .item-content {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .empty-message {\n padding: var(--fx-space-xl, 32px);\n text-align: center;\n color: var(--picklist-text-muted);\n font-style: italic;\n }\n button.control-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 42px;\n height: 38px;\n padding: 0;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--picklist-text-muted);\n cursor: pointer;\n font-size: 16px;\n line-height: 1;\n transition: var(--picklist-transition);\n position: relative;\n }\n button.control-btn:hover:not(:disabled) {\n background: var(--picklist-bg-hover);\n color: var(--picklist-primary);\n transform: scale(1.1);\n }\n button.control-btn:active:not(:disabled) {\n transform: scale(0.92);\n background: color-mix(in srgb, var(--picklist-primary) 15%, transparent);\n }\n button.control-btn:focus-visible {\n outline: none;\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n button.control-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n transform: none;\n }\n .control-btn-icon { font-size: 18px; line-height: 1; }\n\n button.control-btn:hover::after {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n @media (max-width: 640px) {\n .container { flex-direction: column; }\n .controls {\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: center;\n position: relative;\n }\n .control-group { flex-direction: row; }\n .control-group + .control-group {\n margin-top: 0;\n margin-left: 4px;\n padding-top: 0;\n padding-left: 4px;\n border-top: none;\n border-left: 1px solid var(--picklist-border);\n }\n button.control-btn { width: 44px; height: 40px; }\n button.control-btn::after { display: none; }\n .list { max-height: 300px; min-height: 150px; }\n }\n @keyframes slideIn {\n from { opacity: 0; transform: translateX(-10px); }\n to { opacity: 1; transform: translateX(0); }\n }\n .list-item { animation: slideIn 0.2s ease-out; }\n `;\n\n static override get observedAttributes(): string[] {\n return [\n 'source',\n 'target',\n 'source-key',\n 'target-key',\n 'filter',\n 'filter-by',\n 'filter-placeholder',\n 'dragdrop',\n 'striped',\n 'selection-mode',\n 'show-select-all',\n 'source-label',\n 'target-label',\n ];\n }\n\n set source(value: PickListItem[]) {\n this._source = value;\n this._filteredSource = null;\n this.render();\n }\n get source(): PickListItem[] {\n return this._source;\n }\n private _source: PickListItem[] = [];\n private _filteredSource: PickListItem[] | null = null;\n\n set target(value: PickListItem[]) {\n this._target = value;\n this._filteredTarget = null;\n this.render();\n }\n get target(): PickListItem[] {\n return this._target;\n }\n private _target: PickListItem[] = [];\n private _filteredTarget: PickListItem[] | null = null;\n\n set sourceSelection(value: PickListItem[]) {\n this._sourceSelection = value;\n this.render();\n }\n get sourceSelection(): PickListItem[] {\n return this._sourceSelection;\n }\n private _sourceSelection: PickListItem[] = [];\n\n set targetSelection(value: PickListItem[]) {\n this._targetSelection = value;\n this.render();\n }\n get targetSelection(): PickListItem[] {\n return this._targetSelection;\n }\n private _targetSelection: PickListItem[] = [];\n\n get sourceKey(): string {\n return this.getAttr('source-key', '');\n }\n set sourceKey(v: string) {\n this.setAttribute('source-key', v);\n }\n\n get targetKey(): string {\n return this.getAttr('target-key', '');\n }\n set targetKey(v: string) {\n this.setAttribute('target-key', v);\n }\n\n get filter(): boolean {\n return this.hasAttr('filter');\n }\n set filter(v: boolean) {\n this.toggleAttr('filter', v);\n }\n\n get filterBy(): string {\n return this.getAttr('filter-by', 'label');\n }\n set filterBy(v: string) {\n this.setAttribute('filter-by', v);\n }\n\n get filterPlaceholder(): string {\n return this.getAttr('filter-placeholder', 'Buscar...');\n }\n set filterPlaceholder(v: string) {\n this.setAttribute('filter-placeholder', v);\n }\n\n get dragdrop(): boolean {\n return this.hasAttr('dragdrop');\n }\n set dragdrop(v: boolean) {\n this.toggleAttr('dragdrop', v);\n }\n\n get striped(): boolean {\n return this.hasAttr('striped');\n }\n set striped(v: boolean) {\n this.toggleAttr('striped', v);\n }\n\n get selectionMode(): string {\n const s = this.getAttr('selection-mode', '');\n return s === 'single' || s === 'multiple' ? s : '';\n }\n set selectionMode(v: string) {\n this.setAttribute('selection-mode', v);\n }\n\n get showSelectAll(): boolean {\n return this.hasAttr('show-select-all');\n }\n set showSelectAll(v: boolean) {\n this.toggleAttr('show-select-all', v);\n }\n\n get sourceLabel(): string {\n return this.getAttr('source-label', 'Disponíveis');\n }\n set sourceLabel(v: string) {\n this.setAttribute('source-label', v);\n }\n\n get targetLabel(): string {\n return this.getAttr('target-label', 'Selecionados');\n }\n set targetLabel(v: string) {\n this.setAttribute('target-label', v);\n }\n\n get sourceFilterValue(): string {\n return this._sourceFilterValue;\n }\n set sourceFilterValue(v: string) {\n this._sourceFilterValue = v;\n this._applySourceFilter();\n this._updateListDisplay();\n }\n private _sourceFilterValue = '';\n\n get targetFilterValue(): string {\n return this._targetFilterValue;\n }\n set targetFilterValue(v: string) {\n this._targetFilterValue = v;\n this._applyTargetFilter();\n this._updateListDisplay();\n }\n private _targetFilterValue = '';\n private _filterListenersAttached = false;\n\n private _optionTemplate: ((item: PickListItem) => string) | null = null;\n\n setOptionTemplate(template: (item: PickListItem) => string): void {\n this._optionTemplate = template;\n this.render();\n }\n\n protected override connectedCallback(): void {\n this._parseSourceAttribute();\n this._parseTargetAttribute();\n super.connectedCallback();\n }\n\n protected override attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (this.getAttr('source', '') !== '') {\n this._parseSourceAttribute();\n }\n if (this.getAttr('target', '') !== '') {\n this._parseTargetAttribute();\n }\n super.attributeChangedCallback(name, oldValue, newValue);\n }\n\n private _parseSourceAttribute(): void {\n const dataAttr = this.getAttr('source', '');\n if (dataAttr) {\n try {\n this._source = JSON.parse(dataAttr);\n this._filteredSource = null;\n } catch {\n this._source = [];\n }\n }\n }\n\n private _parseTargetAttribute(): void {\n const dataAttr = this.getAttr('target', '');\n if (dataAttr) {\n try {\n this._target = JSON.parse(dataAttr);\n this._filteredTarget = null;\n } catch {\n this._target = [];\n }\n }\n }\n\n private _applySourceFilter(): void {\n if (!this._sourceFilterValue) {\n this._filteredSource = null;\n return;\n }\n const filterFields = this.filterBy.split(',').map(f => f.trim());\n this._filteredSource = this._source.filter(item => {\n return filterFields.some(field => {\n const value = item[field];\n if (value == null) return false;\n return String(value).toLowerCase().includes(this._sourceFilterValue.toLowerCase());\n });\n });\n }\n\n private _applyTargetFilter(): void {\n if (!this._targetFilterValue) {\n this._filteredTarget = null;\n return;\n }\n const filterFields = this.filterBy.split(',').map(f => f.trim());\n this._filteredTarget = this._target.filter(item => {\n return filterFields.some(field => {\n const value = item[field];\n if (value == null) return false;\n return String(value).toLowerCase().includes(this._targetFilterValue.toLowerCase());\n });\n });\n }\n\n private _getDisplaySource(): PickListItem[] {\n return this._filteredSource || this._source;\n }\n\n private _getDisplayTarget(): PickListItem[] {\n return this._filteredTarget || this._target;\n }\n\n private _getItemKey(item: PickListItem, index: number, isSource: boolean): string {\n const keyField = isSource ? this.sourceKey : this.targetKey;\n if (keyField && item[keyField] != null) {\n return String(item[keyField]);\n }\n if (item['id'] != null) return String(item['id']);\n if (item['key'] != null) return String(item['key']);\n if (item['label'] != null) return String(item['label']);\n if (item['name'] != null) return String(item['name']);\n if (item['value'] != null) return String(item['value']);\n return String(index);\n }\n\n private _getItemLabel(item: PickListItem): string {\n const fields = ['label', 'name', 'title', 'text', 'value'];\n for (const field of fields) {\n if (item[field] != null) {\n return String(item[field]);\n }\n }\n return JSON.stringify(item);\n }\n\n private _isSourceSelected(item: PickListItem, index: number): boolean {\n return this._sourceSelection.some(s => this._getItemKey(s, -1, true) === this._getItemKey(item, index, true));\n }\n\n private _isTargetSelected(item: PickListItem, index: number): boolean {\n return this._targetSelection.some(s => this._getItemKey(s, -1, false) === this._getItemKey(item, index, false));\n }\n\n private _emitMoveToTarget(): void {\n this.dispatchEvent(new CustomEvent('move-to-target', {\n bubbles: true,\n composed: true,\n detail: { items: [...this._sourceSelection], source: [...this._source], target: [...this._target] },\n }));\n }\n\n private _emitMoveToSource(): void {\n this.dispatchEvent(new CustomEvent('move-to-source', {\n bubbles: true,\n composed: true,\n detail: { items: [...this._targetSelection], source: [...this._source], target: [...this._target] },\n }));\n }\n\n private _emitSelectionChangeSource(): void {\n this.dispatchEvent(new CustomEvent('selection-change-source', {\n bubbles: true,\n composed: true,\n detail: { selection: [...this._sourceSelection] },\n }));\n }\n\n private _emitSelectionChangeTarget(): void {\n this.dispatchEvent(new CustomEvent('selection-change-target', {\n bubbles: true,\n composed: true,\n detail: { selection: [...this._targetSelection] },\n }));\n }\n\n protected override render(): void {\n const dSrc = this._getDisplaySource();\n const dTgt = this._getDisplayTarget();\n const hasSel = this.selectionMode;\n const showAll = hasSel === 'multiple' && this.showSelectAll;\n const srcItems = dSrc.length === 0 ? `<li class=\"empty-message\">${this.filter ? 'Nenhum resultado' : 'Nenhum item'}</li>` : dSrc.map((item, i) => `<li class=\"list-item${this._isSourceSelected(item, i) ? ' selected' : ''}\" data-index=\"${i}\" data-list=\"source\" tabindex=\"0\">${hasSel ? '<input type=\"checkbox\" class=\"checkbox\"' + (this._isSourceSelected(item, i) ? ' checked' : '') + ' />' : ''}<span class=\"item-content\">${this._optionTemplate ? this._optionTemplate(item) : esc(this._getItemLabel(item))}</span></li>`).join('');\n const tgtItems = dTgt.length === 0 ? `<li class=\"empty-message\">${this.filter ? 'Nenhum resultado' : 'Nenhum selecionado'}</li>` : dTgt.map((item, i) => `<li class=\"list-item${this._isTargetSelected(item, i) ? ' selected' : ''}\" data-index=\"${i}\" data-list=\"target\" tabindex=\"0\">${hasSel ? '<input type=\"checkbox\" class=\"checkbox\"' + (this._isTargetSelected(item, i) ? ' checked' : '') + ' />' : ''}<span class=\"item-content\">${this._optionTemplate ? this._optionTemplate(item) : esc(this._getItemLabel(item))}</span></li>`).join('');\n const srcAllBar = showAll ? `<div class=\"select-all-bar\" part=\"select-all-bar\"><label><input type=\"checkbox\" class=\"select-all-checkbox\" data-list=\"source\" ${this._sourceSelection.length > 0 && this._sourceSelection.length === this._source.length ? 'checked' : ''} aria-label=\"Selecionar todos da origem\" /> Selecionar Todos</label><span class=\"selection-count\">${this._sourceSelection.length} selecionado(s)</span></div>` : '';\n const tgtAllBar = showAll ? `<div class=\"select-all-bar\" part=\"select-all-bar\"><label><input type=\"checkbox\" class=\"select-all-checkbox\" data-list=\"target\" ${this._targetSelection.length > 0 && this._targetSelection.length === this._target.length ? 'checked' : ''} aria-label=\"Selecionar todos do destino\" /> Selecionar Todos</label><span class=\"selection-count\">${this._targetSelection.length} selecionado(s)</span></div>` : '';\n\n this.setTemplate(`<div class=\"container\"><div class=\"list-container\"><div class=\"list-label\">${esc(this.sourceLabel)} (${this._source.length})</div>${this.filter ? '<div class=\"filter-wrapper\"><input type=\"text\" autocomplete=\"off\" class=\"filter-input source-filter\" placeholder=\"' + this.filterPlaceholder + '\" value=\"' + esc(this._sourceFilterValue) + '\" /></div>' : ''}${srcAllBar}<div class=\"list-wrapper\"><ul class=\"list source-list\" role=\"listbox\" tabindex=\"0\">${srcItems}</ul></div></div><div class=\"controls\"><div class=\"control-group\"><button class=\"control-btn\" data-action=\"move-all-target\" part=\"control-btn\" aria-label=\"Mover todos para destino\"><span class=\"control-btn-icon\">»</span></button><button class=\"control-btn\" data-action=\"move-target\" part=\"control-btn\" aria-label=\"Mover para destino\"><span class=\"control-btn-icon\">→</span></button></div><div class=\"control-group\"><button class=\"control-btn\" data-action=\"move-source\" part=\"control-btn\" aria-label=\"Mover para origem\"><span class=\"control-btn-icon\">←</span></button><button class=\"control-btn\" data-action=\"move-all-source\" part=\"control-btn\" aria-label=\"Mover todos para origem\"><span class=\"control-btn-icon\">«</span></button></div></div><div class=\"list-container\"><div class=\"list-label\">${esc(this.targetLabel)} (${this._target.length})</div>${this.filter ? '<div class=\"filter-wrapper\"><input type=\"text\" autocomplete=\"off\" class=\"filter-input target-filter\" placeholder=\"' + this.filterPlaceholder + '\" value=\"' + esc(this._targetFilterValue) + '\" /></div>' : ''}${tgtAllBar}<div class=\"list-wrapper\"><ul class=\"list target-list\" role=\"listbox\" tabindex=\"0\">${tgtItems}</ul></div></div></div>`);\n\n this._attachListeners();\n }\n\n private _attachListeners(): void {\n // Listeners delegados no root, anexados uma unica vez (sobrevivem a re-renders)\n if (!this._filterListenersAttached) {\n this._filterListenersAttached = true;\n\n this.root.addEventListener('input', (e) => {\n const t = e.target as HTMLElement;\n if (t.classList.contains('select-all-checkbox')) {\n this._handleSelectAll(t as HTMLInputElement);\n return;\n }\n if (t.classList.contains('source-filter')) {\n this.sourceFilterValue = (t as HTMLInputElement).value;\n } else if (t.classList.contains('target-filter')) {\n this.targetFilterValue = (t as HTMLInputElement).value;\n }\n });\n\n this.root.addEventListener('click', (e) => {\n const t = e.target as HTMLElement;\n const btn = t.closest('.control-btn') as HTMLButtonElement | null;\n if (btn) {\n switch (btn.dataset.action) {\n case 'move-target': this._moveToTarget(); break;\n case 'move-all-target': this._moveAllToTarget(); break;\n case 'move-source': this._moveToSource(); break;\n case 'move-all-source': this._moveAllToSource(); break;\n }\n return;\n }\n const el = t.closest('.list-item') as HTMLElement | null;\n if (!el) return;\n const isSrc = el.dataset.list === 'source';\n const idx = Number(el.dataset.index);\n const item = (isSrc ? this._getDisplaySource() : this._getDisplayTarget())[idx];\n if (isSrc) this._toggleSourceSelection(item, idx); else this._toggleTargetSelection(item, idx);\n });\n }\n this._updateControlsState();\n }\n\n private _handleSelectAll(checkbox: HTMLInputElement): void {\n const isSrc = checkbox.dataset.list === 'source';\n if (isSrc) {\n this._sourceSelection = checkbox.checked ? [...this._getDisplaySource()] : [];\n this._emitSelectionChangeSource();\n } else {\n this._targetSelection = checkbox.checked ? [...this._getDisplayTarget()] : [];\n this._emitSelectionChangeTarget();\n }\n this._updateSelectionDisplay();\n this._updateControlsState();\n }\n\n /**\n * Atualiza a selecao visual in-place (classes e checkboxes dos itens existentes),\n * sem recriar o DOM — mantendo referencias de elementos validas durante cliques.\n */\n private _updateSelectionDisplay(): void {\n const updateList = (listSel: HTMLElement | null, isSelFn: (item: PickListItem, i: number) => boolean, getData: () => PickListItem[]): void => {\n if (!listSel) return;\n listSel.querySelectorAll<HTMLElement>('.list-item').forEach(el => {\n const idx = Number(el.dataset.index);\n const selected = isSelFn(getData()[idx], idx);\n el.classList.toggle('selected', selected);\n el.setAttribute('aria-selected', String(selected));\n const cb = el.querySelector<HTMLInputElement>('.checkbox');\n if (cb) cb.checked = selected;\n });\n };\n updateList(this.root.querySelector('.source-list'), (it, i) => this._isSourceSelected(it, i), () => this._getDisplaySource());\n updateList(this.root.querySelector('.target-list'), (it, i) => this._isTargetSelected(it, i), () => this._getDisplayTarget());\n this._updateSelectAllBars();\n }\n\n /** Sincroniza as barras \"Selecionar Todos\" (checkbox + contador) sem re-render completo. */\n private _updateSelectAllBars(): void {\n if (!(this.selectionMode === 'multiple' && this.showSelectAll)) return;\n const bars = [\n { el: this.root.querySelector<HTMLInputElement>('.select-all-checkbox[data-list=\"source\"]'), total: this._source.length, sel: this._sourceSelection.length },\n { el: this.root.querySelector<HTMLInputElement>('.select-all-checkbox[data-list=\"target\"]'), total: this._target.length, sel: this._targetSelection.length },\n ];\n bars.forEach(({ el, total, sel }) => {\n if (!el) return;\n el.checked = total > 0 && sel === total;\n const count = el.closest('.select-all-bar')?.querySelector('.selection-count');\n if (count) count.textContent = `${sel} selecionado(s)`;\n });\n }\n\n private _updateControlsState(): void {\n this.root.querySelectorAll<HTMLButtonElement>('.control-btn').forEach(btn => {\n const a = btn.dataset.action;\n btn.disabled = (a === 'move-target' && this._sourceSelection.length === 0) || (a === 'move-all-target' && this._source.length === 0) || (a === 'move-source' && this._targetSelection.length === 0) || (a === 'move-all-source' && this._target.length === 0);\n });\n }\n\n private _moveToTarget(): void {\n if (!this._sourceSelection.length) return;\n const items = [...this._sourceSelection];\n this._source = this._source.filter(s => !items.some(i => this._getItemKey(i, -1, true) === this._getItemKey(s, -1, true)));\n this._target = [...this._target, ...items];\n this._sourceSelection = [];\n this._filteredSource = null;\n this._filteredTarget = null;\n this._updateListDisplay();\n this._updateControlsState();\n this._emitMoveToTarget();\n }\n\n private _moveToSource(): void {\n if (!this._targetSelection.length) return;\n const items = [...this._targetSelection];\n this._target = this._target.filter(t => !items.some(i => this._getItemKey(i, -1, false) === this._getItemKey(t, -1, false)));\n this._source = [...this._source, ...items];\n this._targetSelection = [];\n this._filteredSource = null;\n this._filteredTarget = null;\n this._updateListDisplay();\n this._updateControlsState();\n this._emitMoveToSource();\n }\n\n private _moveAllToTarget(): void {\n const items = [...this._source];\n this._source = [];\n this._target = [...this._target, ...items];\n this._sourceSelection = [];\n this._filteredSource = null;\n this._filteredTarget = null;\n this._updateListDisplay();\n this._updateControlsState();\n this._emitMoveToTarget();\n }\n\n private _moveAllToSource(): void {\n const items = [...this._target];\n this._target = [];\n this._source = [...this._source, ...items];\n this._targetSelection = [];\n this._filteredSource = null;\n this._filteredTarget = null;\n this._updateListDisplay();\n this._updateControlsState();\n this._emitMoveToSource();\n }\n\n private _toggleSourceSelection(item: PickListItem, index: number): void {\n // Sem selection-mode definido, permite selecao simples (um item por vez)\n const mode = this.selectionMode || 'single';\n const key = this._getItemKey(item, index, true);\n const idx = this._sourceSelection.findIndex(s => this._getItemKey(s, -1, true) === key);\n if (idx >= 0) {\n this._sourceSelection.splice(idx, 1);\n } else if (mode === 'multiple') {\n this._sourceSelection.push(item);\n } else {\n this._sourceSelection = [item];\n }\n this._emitSelectionChangeSource();\n this._updateSelectionDisplay();\n this._updateControlsState();\n }\n\n private _toggleTargetSelection(item: PickListItem, index: number): void {\n // Sem selection-mode definido, permite selecao simples (um item por vez)\n const mode = this.selectionMode || 'single';\n const key = this._getItemKey(item, index, false);\n const idx = this._targetSelection.findIndex(s => this._getItemKey(s, -1, false) === key);\n if (idx >= 0) {\n this._targetSelection.splice(idx, 1);\n } else if (mode === 'multiple') {\n this._targetSelection.push(item);\n } else {\n this._targetSelection = [item];\n }\n this._emitSelectionChangeTarget();\n this._updateSelectionDisplay();\n this._updateControlsState();\n }\n\n private _updateListDisplay(): void {\n const srcWrapper = this.root.querySelector('.source-list')?.parentElement;\n const tgtWrapper = this.root.querySelector('.target-list')?.parentElement;\n const srcLabel = this.root.querySelector('.list-container:first-of-type .list-label');\n const tgtLabel = this.root.querySelector('.list-container:last-of-type .list-label');\n if (!srcWrapper || !tgtWrapper) { this.render(); return; }\n const dSrc = this._getDisplaySource();\n const dTgt = this._getDisplayTarget();\n const hasSel = this.selectionMode;\n const srcItems = dSrc.length === 0 ? `<li class=\"empty-message\" part=\"empty-message\">${this.filter ? 'Nenhum resultado' : 'Nenhum item'}</li>` : dSrc.map((item, i) => `<li class=\"list-item${this._isSourceSelected(item, i) ? ' selected' : ''}\" part=\"list-item\" data-index=\"${i}\" data-list=\"source\" role=\"option\" aria-selected=\"${this._isSourceSelected(item, i)}\" tabindex=\"0\">${hasSel ? '<input type=\"checkbox\" class=\"checkbox\" part=\"checkbox\"' + (this._isSourceSelected(item, i) ? ' checked' : '') + ' />' : ''}<span class=\"item-content\" part=\"item-content\">${this._optionTemplate ? this._optionTemplate(item) : esc(this._getItemLabel(item))}</span></li>`).join('');\n const tgtItems = dTgt.length === 0 ? `<li class=\"empty-message\" part=\"empty-message\">${this.filter ? 'Nenhum resultado' : 'Nenhum selecionado'}</li>` : dTgt.map((item, i) => `<li class=\"list-item${this._isTargetSelected(item, i) ? ' selected' : ''}\" part=\"list-item\" data-index=\"${i}\" data-list=\"target\" role=\"option\" aria-selected=\"${this._isTargetSelected(item, i)}\" tabindex=\"0\">${hasSel ? '<input type=\"checkbox\" class=\"checkbox\" part=\"checkbox\"' + (this._isTargetSelected(item, i) ? ' checked' : '') + ' />' : ''}<span class=\"item-content\" part=\"item-content\">${this._optionTemplate ? this._optionTemplate(item) : esc(this._getItemLabel(item))}</span></li>`).join('');\n srcWrapper.innerHTML = `<ul class=\"list source-list\" role=\"listbox\" tabindex=\"0\">${srcItems}</ul>`;\n tgtWrapper.innerHTML = `<ul class=\"list target-list\" role=\"listbox\" tabindex=\"0\">${tgtItems}</ul>`;\n if (srcLabel) srcLabel.textContent = `${this.sourceLabel} (${this._source.length})`;\n if (tgtLabel) tgtLabel.textContent = `${this.targetLabel} (${this._target.length})`;\n this._updateSelectAllBars();\n this._attachListeners();\n }\n}\n\nexport function defineFxPickList(): typeof FxPickList {\n return defineElement('fx-picklist', FxPickList);\n}"],"names":[],"mappings":"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"}
|
|
@@ -260,7 +260,7 @@ const _FxSelect = class _FxSelect extends FxFormElement {
|
|
|
260
260
|
</span>
|
|
261
261
|
</span>
|
|
262
262
|
<div class="panel" part="panel" role="listbox">
|
|
263
|
-
${this.hasAttr("searchable") ? `<input class="search" part="search" type="text" placeholder="${esc(this.getAttr("search-placeholder", "Pesquisar…"))}">` : ""}
|
|
263
|
+
${this.hasAttr("searchable") ? `<input class="search" part="search" type="text" autocomplete="off" placeholder="${esc(this.getAttr("search-placeholder", "Pesquisar…"))}">` : ""}
|
|
264
264
|
${filtered.map((o) => `
|
|
265
265
|
<button type="button" class="opt" role="option" data-value="${esc(o.value)}"
|
|
266
266
|
aria-selected="${o.value === current}">${esc(o.label)}</button>`).join("")}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.js","sources":["../../../src/components/select/select.ts"],"sourcesContent":["import { FxFormElement } from '../../core/form-element';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\n\n/**\n * <fx-select> — Campo de seleção com dropdown customizado.\n *\n * Form-Associated Custom Element: dentro de um <form> entra no FormData\n * (via atributo `name`) e recebe reset/disable do form.\n *\n * Escreva os filhos como `<option>` nativos no light DOM; eles são\n * espelhados automaticamente (MutationObserver):\n *\n * <fx-select value=\"b\" searchable clearable>\n * <option value=\"a\">Opção A</option>\n * <option value=\"b\">Opção B</option>\n * </fx-select>\n *\n * Atributos: value, size (sm|md|lg), disabled, placeholder,\n * searchable, clearable, search-placeholder, no-results,\n * placement (auto|top|bottom — direção do painel; `auto` inverte quando\n * não cabe na viewport).\n * Eventos: `change`, `input` e `valueChange` (composed, detail: { value }) —\n * `input` aciona o v-model do Vue e `valueChange` o [(value)] do Angular.\n */\nexport class FxSelect extends FxFormElement {\n static override styles = css`\n :host {\n display: inline-block;\n vertical-align: middle;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n position: relative;\n /* Largura no HOST (padrão: conteúdo com mín. 200px). CSS externo, classes\n e style inline no elemento definem a largura sem precisar do full. */\n width: var(--fx-select-width, max-content);\n min-width: var(--fx-select-min-width, 200px);\n /* Espaço entre o campo e o painel + altura máxima do painel. Expostos\n como custom property porque ::part() do lado do consumidor tem\n prioridade MENOR que a folha do shadow root e não vence o top. */\n --fx-select-panel-offset: 4px;\n --fx-select-panel-max-height: 260px;\n }\n .trigger {\n display: inline-flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--fx-space-sm);\n box-sizing: border-box;\n min-height: var(--fx-size-md);\n /* Acompanha a largura definida no :host. */\n width: 100%;\n font: inherit;\n /* Altura/linha determinísticas: a caixa fica no token --fx-size-*\n (o line-height fixo impede que a herança da página estoure o min-height). */\n line-height: var(--fx-font-line-height);\n font-weight: var(--fx-font-weight);\n color: var(--fx-text-default);\n text-align: left;\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-xs) var(--fx-space-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 .trigger:hover { border-color: var(--fx-border-hover); }\n .trigger:focus-visible,\n :host([open]) .trigger {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n :host([size='sm']) { min-width: var(--fx-select-min-width-sm, 180px); }\n :host([size='sm']) .trigger { min-height: var(--fx-size-sm); }\n :host([size='lg']) .trigger { min-height: var(--fx-size-lg); font-size: calc(var(--fx-font-size) + 4px); }\n /* Full width: o host estica até o pai e o trigger acompanha. */\n :host([full]) { display: block; width: 100%; }\n :host([full]) { min-width: 0; }\n :host([full]) .trigger { width: 100%; min-width: 0; }\n :host([full]) .panel { width: 100%; }\n /* Validação — borda e brilho JÁ EM REPOUSO (igual ao fx-input); o\n brilho segue --fx-effect-error-ring, que acompanha effect.focus-ring. */\n :host([error]) .trigger,\n :host([invalid]) .trigger {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([error]) .trigger:focus-visible,\n :host([invalid]) .trigger:focus-visible,\n :host([error][open]) .trigger,\n :host([invalid][open]) .trigger {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([success]) .trigger,\n :host([valid]) .trigger {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));\n }\n :host([success]) .trigger:focus-visible,\n :host([valid]) .trigger:focus-visible,\n :host([success][open]) .trigger,\n :host([valid][open]) .trigger {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));\n }\n :host([disabled]) .trigger,\n .trigger[aria-disabled='true'] { opacity: 0.55; cursor: not-allowed; background-color: var(--fx-surface-surface-hover); }\n /* O rótulo encolhe (ellipsis) e os ícones NUNCA saem do campo. */\n .label,\n .placeholder {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .placeholder { color: var(--fx-text-muted); }\n .actions {\n display: inline-flex;\n align-items: center;\n gap: var(--fx-space-xs, 8px);\n flex-shrink: 0;\n }\n .caret { font-size: calc(var(--fx-font-size) - 3px); color: var(--fx-text-muted); pointer-events: none; }\n\n /* Painel do dropdown — a POSIÇÃO vertical é definida pelas regras\n [data-placement] abaixo (o JS de ajustarPosicao decide), por isso\n top/bottom não ficam aqui. */\n .panel {\n position: absolute;\n left: 0;\n z-index: var(--fx-z-dropdown, 1000);\n width: max(100%, 220px);\n max-height: var(--fx-select-panel-max-height, 260px);\n overflow-y: auto;\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 }\n /* Ancestral com overflow (ex.: fx-card) cortaria o painel absoluto:\n nesse caso o JS posiciona com position:fixed a partir do trigger. */\n :host([data-fixed]) .panel {\n position: fixed;\n }\n /* Padrão: abre para baixo. */\n :host([open]:not([data-placement='top'])) .panel {\n top: calc(100% + var(--fx-select-panel-offset, 4px));\n }\n /* placement=\"top\" explícito ou auto-flip: abre para cima. */\n :host([open][placement='top']) .panel,\n :host([open][data-placement='top']) .panel {\n top: auto;\n bottom: calc(100% + var(--fx-select-panel-offset, 4px));\n }\n :host([open]) .panel { display: block; }\n .search {\n position: sticky;\n top: 0;\n width: 100%;\n box-sizing: border-box;\n font: inherit;\n color: var(--fx-text-default);\n background: var(--fx-surface-background);\n border: none;\n border-bottom: 1px solid var(--fx-border-default);\n padding: var(--fx-space-sm) var(--fx-space-md);\n outline: none;\n }\n .opt {\n display: block;\n width: 100%;\n text-align: left;\n font: inherit;\n color: var(--fx-text-default);\n background: none;\n border: none;\n padding: var(--fx-space-sm) var(--fx-space-md);\n cursor: pointer;\n }\n /* Hover e selecionado com a cor primária do tema (igual ao multiselect). */\n .opt:hover { background: color-mix(in srgb, var(--fx-color-primary) 12%, transparent); }\n .opt[aria-selected='true'] {\n background: color-mix(in srgb, var(--fx-color-primary) 18%, transparent);\n color: var(--fx-color-primary);\n font-weight: var(--fx-font-weight);\n }\n .empty { padding: var(--fx-space-sm) var(--fx-space-md); color: var(--fx-text-muted); }\n\n /* Clearable */\n .clear {\n border: none;\n background: transparent;\n color: var(--fx-text-muted);\n font-size: calc(var(--fx-font-size) + 2px);\n line-height: 1;\n cursor: pointer;\n padding: 0;\n }\n .clear:hover { color: var(--fx-color-danger); }\n .clear[hidden] { display: none; }\n `;\n\n // `value` é observado para que `setAttribute('value', ...)` (HTML puro)\n // também atualize o rótulo. Os caminhos internos de change usam\n // `_suppressRender` para renderizar UMA vez, depois de fechar o painel.\n static override get observedAttributes(): string[] {\n // `invalid`/`valid` são aliases aceitos no CSS; sem observá-los o\n // setAttribute no submit não re-renderiza.\n return ['value', 'size', 'disabled', 'placeholder', 'searchable', 'clearable', 'full', 'error', 'invalid', 'success', 'valid', 'placement'];\n }\n\n /** Evita renders em cascata durante mudanças internas agrupadas. */\n private _suppressRender = false;\n /** Resultado de `_precisaFixed` cacheado por abertura (evita getComputedStyle no scroll). */\n private _fixedMode = false;\n private _fixedResolved = false;\n\n protected override attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (this._suppressRender) return;\n super.attributeChangedCallback(name, oldValue, newValue);\n }\n\n /** Espaço (px) entre o campo e o painel — espelha `--fx-select-panel-offset`. */\n private static readonly GAP = 4;\n /** Margem (px) mantida entre o painel e as bordas da viewport. */\n private static readonly MARGEM = 8;\n /** Altura mínima do painel ao ser limitado pelo espaço disponível. */\n private static readonly MIN_ALTURA = 80;\n\n private observer?: MutationObserver;\n private docListener?: (e: Event) => void;\n /** Reposiciona o painel enquanto ele estiver aberto (bound em `_abrir`). */\n private onReflow?: () => void;\n\n /** Tamanho do campo. Padrão: `'md'`. */\n get size(): string {\n const s = this.getAttr('size', 'md');\n return s === 'sm' || s === 'lg' ? s : 'md';\n }\n set size(value: string) {\n this.setAttribute('size', value);\n }\n\n get value(): string {\n return this.getAttr('value');\n }\n set value(value: string | number | null | undefined) {\n const next = value == null ? '' : String(value);\n const prev = this.getAttr('value');\n\n // setAttribute dispara attributeChangedCallback → render (quando conectado).\n if (prev !== next) this.setAttribute('value', next);\n this.updateFormValue();\n }\n\n get disabled(): boolean {\n return this.hasAttr('disabled');\n }\n set disabled(value: boolean) {\n this.toggleAttr('disabled', Boolean(value));\n }\n\n get searchable(): boolean {\n return this.hasAttr('searchable');\n }\n set searchable(value: boolean) {\n this.toggleAttr('searchable', Boolean(value));\n }\n\n get clearable(): boolean {\n return this.hasAttr('clearable');\n }\n set clearable(value: boolean) {\n this.toggleAttr('clearable', Boolean(value));\n }\n\n get full(): boolean {\n return this.hasAttr('full');\n }\n set full(value: boolean) {\n this.toggleAttr('full', Boolean(value));\n }\n\n private get options(): { value: string; label: string }[] {\n return [...this.querySelectorAll('option')].map((o) => ({\n value: o.getAttribute('value') ?? o.textContent?.trim() ?? '',\n label: o.textContent?.trim() ?? '',\n }));\n }\n\n protected override connectedCallback(): void {\n super.connectedCallback();\n // Espelha mudanças nas <option> do light DOM — inclusive `value`/`selected`\n // alterados em runtime pelo framework (Vue atualiza atributos, não filhos).\n this.observer = new MutationObserver((mutations) => {\n // Mudanças no `value` do próprio host são tratadas pelo setter (que já\n // renderiza); ignorá-las evita um segundo render assíncrono.\n if (mutations.every((m) => m.type === 'attributes' && m.target === this)) return;\n this.render();\n });\n this.observer.observe(this, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n attributeFilter: ['value', 'selected'],\n });\n // Fecha o dropdown ao clicar fora.\n this.docListener = (e: Event) => {\n if (!this.hasAttr('open')) return;\n if (e.composedPath().includes(this)) return;\n this._fechar();\n this.render();\n };\n document.addEventListener('click', this.docListener);\n }\n\n protected override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.observer?.disconnect();\n if (this.docListener) document.removeEventListener('click', this.docListener);\n this._unbindReflow();\n }\n\n /** Abre o dropdown, posiciona o painel e passa a reposicioná-lo no reflow. */\n private _abrir(): void {\n // Resolve o modo (fixed/absolute) UMA vez por abertura; o scroll só\n // recalcula coordenadas, sem varrer ancestrais/getComputedStyle.\n this._fixedMode = FxSelect._precisaFixed(this);\n this._fixedResolved = true;\n this.setAttribute('open', '');\n this._bindReflow();\n }\n\n /** Fecha o dropdown e libera os listeners de resize/scroll. */\n private _fechar(): void {\n this.removeAttribute('open');\n // Sem isto o `data-placement` fica preso no host e a próxima abertura\n // mostraria o painel na posição invertida antes do ajuste rodar.\n this.removeAttribute('data-placement');\n this._fixedMode = false;\n this._fixedResolved = false;\n this._unbindReflow();\n }\n\n /** Liga o reposicionamento (resize + scroll interno, em capture). */\n private _bindReflow(): void {\n if (this.onReflow) return;\n this.onReflow = () => {\n if (this.hasAttr('open')) this.ajustarPosicao();\n };\n window.addEventListener('resize', this.onReflow);\n window.addEventListener('scroll', this.onReflow, true);\n }\n\n private _unbindReflow(): void {\n if (!this.onReflow) return;\n window.removeEventListener('resize', this.onReflow);\n window.removeEventListener('scroll', this.onReflow, true);\n this.onReflow = undefined;\n }\n\n /**\n * Decide a posição vertical do painel medindo o espaço real da viewport.\n *\n * `placement=\"top\"`/`\"bottom\"` são respeitados literalmente; o padrão\n * (`auto`) só inverte quando o painel não cabe embaixo E couber melhor\n * acima. Também limita a altura ao espaço disponível e evita overflow\n * horizontal próximo à borda direita.\n */\n protected ajustarPosicao(): void {\n const painel = this.root.querySelector<HTMLElement>('.panel');\n const trigger = this.root.querySelector<HTMLElement>('.trigger');\n if (!painel || !trigger) return;\n\n const r = trigger.getBoundingClientRect();\n const abaixo = window.innerHeight - r.bottom; // espaço livre embaixo\n const acima = r.top; // espaço livre acima\n const desejado = painel.scrollHeight; // altura já com a busca\n const maxAltura = FxSelect._maxAltura(this);\n\n const pedido = this.getAttr('placement', 'auto');\n const paraCima =\n pedido === 'top' ||\n (pedido !== 'bottom' && abaixo < Math.min(desejado, maxAltura) && acima > abaixo);\n\n // O atributo placement do host tem precedência no CSS; data-placement\n // é o canal interno do auto-flip e usa a mesma regra de estilo.\n if (paraCima) this.setAttribute('data-placement', 'top');\n else this.removeAttribute('data-placement');\n\n // Limita a altura ao espaço real disponível (evita o painel vazar da tela).\n const disponivel = Math.max(\n FxSelect.MIN_ALTURA,\n (paraCima ? acima : abaixo) - FxSelect.GAP,\n );\n const altura = Math.min(desejado || disponivel, disponivel, maxAltura);\n painel.style.maxHeight = `${altura}px`;\n\n // Dentro de containers com overflow (fx-card e afins) o painel absoluto é\n // cortado. Nesse caso usa coordenadas fixas a partir do trigger — imune\n // ao clipping do ancestral. Fora disso mantém o fluxo absoluto histórico.\n if (!this._fixedResolved) {\n this._fixedMode = FxSelect._precisaFixed(this);\n this._fixedResolved = true;\n }\n if (this._fixedMode) {\n this.setAttribute('data-fixed', '');\n const largura = Math.max(r.width, 220);\n const esquerda = Math.max(\n FxSelect.MARGEM,\n Math.min(r.left, window.innerWidth - largura - FxSelect.MARGEM),\n );\n const topo = paraCima\n ? Math.max(FxSelect.MARGEM, r.top - FxSelect.GAP - altura)\n : r.bottom + FxSelect.GAP;\n\n painel.style.bottom = 'auto';\n painel.style.width = `${largura}px`;\n painel.style.left = `${esquerda}px`;\n painel.style.top = `${topo}px`;\n return;\n }\n\n // Reset do estado fixed (caso o select tenha sido movido de contexto).\n this.removeAttribute('data-fixed');\n painel.style.top = '';\n painel.style.bottom = '';\n painel.style.width = '';\n\n // Reset do deslocamento horizontal antes de remedir (o painel é recriado\n // a cada render, mas o ajuste pode rodar várias vezes com o mesmo nó).\n painel.style.left = '';\n const largura = painel.offsetWidth;\n const excesso = r.left + largura - (window.innerWidth - FxSelect.MARGEM);\n if (excesso > 0) {\n painel.style.left = `${-excesso}px`;\n painel.style.right = 'auto';\n }\n }\n\n /**\n * Existe ancestral com overflow que cortaria o painel absoluto?\n * `getComputedStyle` é defensivo: em jsdom retorna vazio e o modo\n * histórico (absoluto) é mantido.\n */\n private static _precisaFixed(host: HTMLElement): boolean {\n let el = host.parentElement;\n while (el && el !== document.body && el !== document.documentElement) {\n const cs = getComputedStyle(el);\n const overflow = `${cs.overflow}${cs.overflowX}${cs.overflowY}`;\n if (/(hidden|clip|auto|scroll|overlay)/.test(overflow)) return true;\n el = el.parentElement;\n }\n return false;\n }\n\n /** Altura máxima do painel a partir de `--fx-select-panel-max-height`. */\n private static _maxAltura(host: HTMLElement): number {\n const raw = getComputedStyle(host).getPropertyValue('--fx-select-panel-max-height');\n const n = parseInt(raw, 10);\n return Number.isFinite(n) && n > 0 ? n : 260;\n }\n\n private select(value: string): void {\n // Agrupa: o setter NÃO renderiza aqui; o render acontece uma única vez\n // depois de fechar o painel.\n this._suppressRender = true;\n try {\n this.value = value;\n } finally {\n this._suppressRender = false;\n }\n this._fechar();\n this.render();\n this.emitValueEvents();\n this.dispatchEvent(\n new CustomEvent('change', { bubbles: true, composed: true, detail: { value } }),\n );\n }\n\n /** Navegação por teclado entre as opções do listbox (WCAG 2.1.1). */\n private _navigateOptions(e: KeyboardEvent): void {\n e.preventDefault();\n if (!this.hasAttr('open')) {\n this._abrir();\n this.render();\n }\n const opts = Array.from(this.root.querySelectorAll<HTMLButtonElement>('.opt'));\n if (!opts.length) return;\n const current = opts.indexOf(this.root.activeElement as HTMLButtonElement);\n let next = 0;\n if (e.key === 'ArrowDown') next = current === -1 ? 0 : Math.min(current + 1, opts.length - 1);\n else if (e.key === 'ArrowUp') next = current === -1 ? opts.length - 1 : Math.max(current - 1, 0);\n else if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = opts.length - 1;\n opts[next]?.focus();\n }\n\n protected override render(): void {\n const prevOpen = this.hasAttr('open');\n if (!prevOpen) {\n this._fixedMode = false;\n this._fixedResolved = false;\n }\n const prevSearch = this.root.querySelector<HTMLInputElement>('.search');\n // Estado do campo de busca antes de re-renderizar (valor, foco e cursor).\n const search = prevSearch?.value ?? '';\n const searchFocused =\n prevSearch != null && this.root.activeElement === prevSearch;\n const caretPos = searchFocused ? prevSearch!.selectionStart : null;\n\n const opts = this.options;\n let current = this.getAttr('value');\n if (!current) {\n const explicit = this.querySelector('option[selected]');\n current = explicit?.getAttribute('value') ?? explicit?.textContent?.trim() ?? '';\n }\n const selectedLabel = opts.find((o) => o.value === current)?.label ?? '';\n const placeholder = this.getAttr('placeholder', 'Selecione…');\n\n const filtered = search\n ? opts.filter((o) => o.label.toLowerCase().includes(search.toLowerCase()))\n : opts;\n\n this.setTemplate(`\n <span class=\"trigger\" part=\"trigger\" role=\"button\" tabindex=\"${this.disabled ? -1 : 0}\" aria-haspopup=\"listbox\" aria-expanded=\"${prevOpen}\">\n <span class=\"${selectedLabel ? 'label' : 'placeholder'}\">${esc(selectedLabel) || esc(placeholder)}</span>\n <span class=\"actions\">\n ${this.hasAttr('clearable') && current ? '<button type=\"button\" class=\"clear\" part=\"clear\" aria-label=\"Limpar\">×</button>' : ''}\n <span class=\"caret\">▼</span>\n </span>\n </span>\n <div class=\"panel\" part=\"panel\" role=\"listbox\">\n ${this.hasAttr('searchable') ? `<input class=\"search\" part=\"search\" type=\"text\" placeholder=\"${esc(this.getAttr('search-placeholder', 'Pesquisar…'))}\">` : ''}\n ${filtered.map((o) => `\n <button type=\"button\" class=\"opt\" role=\"option\" data-value=\"${esc(o.value)}\"\n aria-selected=\"${o.value === current}\">${esc(o.label)}</button>`).join('')}\n ${filtered.length === 0 ? `<div class=\"empty\">${esc(this.getAttr('no-results', 'Nenhum resultado'))}</div>` : ''}\n </div>\n `);\n\n if (prevOpen) this.setAttribute('open', '');\n // A medição só é válida com o painel já `display: block` (open aplicado).\n if (this.hasAttr('open')) this.ajustarPosicao();\n const searchInput = this.root.querySelector<HTMLInputElement>('.search');\n if (searchInput) {\n searchInput.value = search;\n searchInput.addEventListener('input', () => this.render());\n searchInput.addEventListener('click', (e) => e.stopPropagation());\n // Re-render não pode roubar o foco nem perder a posição do cursor.\n if (searchFocused) {\n searchInput.focus();\n try { searchInput.setSelectionRange(caretPos!, caretPos!); } catch { /* type=text sempre suporta */ }\n }\n }\n\n const trigger = this.root.querySelector<HTMLElement>('.trigger');\n if (!trigger) return;\n if (this.disabled) trigger.setAttribute('aria-disabled', 'true');\n\n trigger.addEventListener('click', (e) => {\n if (this.disabled) return;\n if ((e.target as HTMLElement).closest('.clear')) return;\n if (this.hasAttr('open')) this._fechar();\n else this._abrir();\n this.render();\n this.root.querySelector<HTMLInputElement>('.search')?.focus();\n });\n\n // Teclado: Enter/Espaço abrem o dropdown; setas/Home/End/Escape navegam.\n trigger.addEventListener('keydown', (e) => {\n if (this.disabled) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n trigger.click();\n return;\n }\n if (e.key === 'Escape') {\n if (this.hasAttr('open')) {\n this._fechar();\n this.render();\n this.root.querySelector<HTMLElement>('.trigger')?.focus();\n }\n return;\n }\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Home' || e.key === 'End') {\n this._navigateOptions(e);\n }\n });\n\n // Limpar.\n this.root.querySelector('.clear')?.addEventListener('click', (e) => {\n e.stopPropagation();\n this._suppressRender = true;\n try {\n this.value = '';\n } finally {\n this._suppressRender = false;\n }\n this._fechar();\n this.render();\n this.emitValueEvents();\n this.dispatchEvent(\n new CustomEvent('change', { bubbles: true, composed: true, detail: { value: '' } }),\n );\n });\n\n // Escolher opção.\n this.root.querySelectorAll<HTMLElement>('.opt').forEach((opt) => {\n opt.addEventListener('click', () => this.select(opt.dataset.value!));\n });\n\n // Publica name/value no form (ElementInternals) a cada render.\n this.updateFormValue();\n }\n\n /** form.reset(): restaura o valor inicial e re-renderiza o rótulo. */\n override formResetCallback(): void {\n this._suppressRender = true;\n try {\n super.formResetCallback();\n } finally {\n this._suppressRender = false;\n }\n this.render();\n }\n}\n\nexport function defineFxSelect(): typeof FxSelect {\n return defineElement('fx-select', FxSelect);\n}\n\n"],"names":["largura"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"select.js","sources":["../../../src/components/select/select.ts"],"sourcesContent":["import { FxFormElement } from '../../core/form-element';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\nimport { esc } from '../../core/sanitize';\n\n/**\n * <fx-select> — Campo de seleção com dropdown customizado.\n *\n * Form-Associated Custom Element: dentro de um <form> entra no FormData\n * (via atributo `name`) e recebe reset/disable do form.\n *\n * Escreva os filhos como `<option>` nativos no light DOM; eles são\n * espelhados automaticamente (MutationObserver):\n *\n * <fx-select value=\"b\" searchable clearable>\n * <option value=\"a\">Opção A</option>\n * <option value=\"b\">Opção B</option>\n * </fx-select>\n *\n * Atributos: value, size (sm|md|lg), disabled, placeholder,\n * searchable, clearable, search-placeholder, no-results,\n * placement (auto|top|bottom — direção do painel; `auto` inverte quando\n * não cabe na viewport).\n * Eventos: `change`, `input` e `valueChange` (composed, detail: { value }) —\n * `input` aciona o v-model do Vue e `valueChange` o [(value)] do Angular.\n */\nexport class FxSelect extends FxFormElement {\n static override styles = css`\n :host {\n display: inline-block;\n vertical-align: middle;\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n position: relative;\n /* Largura no HOST (padrão: conteúdo com mín. 200px). CSS externo, classes\n e style inline no elemento definem a largura sem precisar do full. */\n width: var(--fx-select-width, max-content);\n min-width: var(--fx-select-min-width, 200px);\n /* Espaço entre o campo e o painel + altura máxima do painel. Expostos\n como custom property porque ::part() do lado do consumidor tem\n prioridade MENOR que a folha do shadow root e não vence o top. */\n --fx-select-panel-offset: 4px;\n --fx-select-panel-max-height: 260px;\n }\n .trigger {\n display: inline-flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--fx-space-sm);\n box-sizing: border-box;\n min-height: var(--fx-size-md);\n /* Acompanha a largura definida no :host. */\n width: 100%;\n font: inherit;\n /* Altura/linha determinísticas: a caixa fica no token --fx-size-*\n (o line-height fixo impede que a herança da página estoure o min-height). */\n line-height: var(--fx-font-line-height);\n font-weight: var(--fx-font-weight);\n color: var(--fx-text-default);\n text-align: left;\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-xs) var(--fx-space-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 .trigger:hover { border-color: var(--fx-border-hover); }\n .trigger:focus-visible,\n :host([open]) .trigger {\n outline: none;\n border-color: var(--fx-color-primary);\n box-shadow: var(--fx-effect-focus-ring, none);\n }\n :host([size='sm']) { min-width: var(--fx-select-min-width-sm, 180px); }\n :host([size='sm']) .trigger { min-height: var(--fx-size-sm); }\n :host([size='lg']) .trigger { min-height: var(--fx-size-lg); font-size: calc(var(--fx-font-size) + 4px); }\n /* Full width: o host estica até o pai e o trigger acompanha. */\n :host([full]) { display: block; width: 100%; }\n :host([full]) { min-width: 0; }\n :host([full]) .trigger { width: 100%; min-width: 0; }\n :host([full]) .panel { width: 100%; }\n /* Validação — borda e brilho JÁ EM REPOUSO (igual ao fx-input); o\n brilho segue --fx-effect-error-ring, que acompanha effect.focus-ring. */\n :host([error]) .trigger,\n :host([invalid]) .trigger {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([error]) .trigger:focus-visible,\n :host([invalid]) .trigger:focus-visible,\n :host([error][open]) .trigger,\n :host([invalid][open]) .trigger {\n border-color: var(--fx-color-danger, #dc2626);\n box-shadow: var(--fx-effect-error-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-danger, #dc2626) 18%, transparent));\n }\n :host([success]) .trigger,\n :host([valid]) .trigger {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));\n }\n :host([success]) .trigger:focus-visible,\n :host([valid]) .trigger:focus-visible,\n :host([success][open]) .trigger,\n :host([valid][open]) .trigger {\n border-color: var(--fx-color-success, #16a34a);\n box-shadow: var(--fx-effect-success-ring, 0 0 0 3px color-mix(in srgb, var(--fx-color-success, #16a34a) 18%, transparent));\n }\n :host([disabled]) .trigger,\n .trigger[aria-disabled='true'] { opacity: 0.55; cursor: not-allowed; background-color: var(--fx-surface-surface-hover); }\n /* O rótulo encolhe (ellipsis) e os ícones NUNCA saem do campo. */\n .label,\n .placeholder {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .placeholder { color: var(--fx-text-muted); }\n .actions {\n display: inline-flex;\n align-items: center;\n gap: var(--fx-space-xs, 8px);\n flex-shrink: 0;\n }\n .caret { font-size: calc(var(--fx-font-size) - 3px); color: var(--fx-text-muted); pointer-events: none; }\n\n /* Painel do dropdown — a POSIÇÃO vertical é definida pelas regras\n [data-placement] abaixo (o JS de ajustarPosicao decide), por isso\n top/bottom não ficam aqui. */\n .panel {\n position: absolute;\n left: 0;\n z-index: var(--fx-z-dropdown, 1000);\n width: max(100%, 220px);\n max-height: var(--fx-select-panel-max-height, 260px);\n overflow-y: auto;\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 }\n /* Ancestral com overflow (ex.: fx-card) cortaria o painel absoluto:\n nesse caso o JS posiciona com position:fixed a partir do trigger. */\n :host([data-fixed]) .panel {\n position: fixed;\n }\n /* Padrão: abre para baixo. */\n :host([open]:not([data-placement='top'])) .panel {\n top: calc(100% + var(--fx-select-panel-offset, 4px));\n }\n /* placement=\"top\" explícito ou auto-flip: abre para cima. */\n :host([open][placement='top']) .panel,\n :host([open][data-placement='top']) .panel {\n top: auto;\n bottom: calc(100% + var(--fx-select-panel-offset, 4px));\n }\n :host([open]) .panel { display: block; }\n .search {\n position: sticky;\n top: 0;\n width: 100%;\n box-sizing: border-box;\n font: inherit;\n color: var(--fx-text-default);\n background: var(--fx-surface-background);\n border: none;\n border-bottom: 1px solid var(--fx-border-default);\n padding: var(--fx-space-sm) var(--fx-space-md);\n outline: none;\n }\n .opt {\n display: block;\n width: 100%;\n text-align: left;\n font: inherit;\n color: var(--fx-text-default);\n background: none;\n border: none;\n padding: var(--fx-space-sm) var(--fx-space-md);\n cursor: pointer;\n }\n /* Hover e selecionado com a cor primária do tema (igual ao multiselect). */\n .opt:hover { background: color-mix(in srgb, var(--fx-color-primary) 12%, transparent); }\n .opt[aria-selected='true'] {\n background: color-mix(in srgb, var(--fx-color-primary) 18%, transparent);\n color: var(--fx-color-primary);\n font-weight: var(--fx-font-weight);\n }\n .empty { padding: var(--fx-space-sm) var(--fx-space-md); color: var(--fx-text-muted); }\n\n /* Clearable */\n .clear {\n border: none;\n background: transparent;\n color: var(--fx-text-muted);\n font-size: calc(var(--fx-font-size) + 2px);\n line-height: 1;\n cursor: pointer;\n padding: 0;\n }\n .clear:hover { color: var(--fx-color-danger); }\n .clear[hidden] { display: none; }\n `;\n\n // `value` é observado para que `setAttribute('value', ...)` (HTML puro)\n // também atualize o rótulo. Os caminhos internos de change usam\n // `_suppressRender` para renderizar UMA vez, depois de fechar o painel.\n static override get observedAttributes(): string[] {\n // `invalid`/`valid` são aliases aceitos no CSS; sem observá-los o\n // setAttribute no submit não re-renderiza.\n return ['value', 'size', 'disabled', 'placeholder', 'searchable', 'clearable', 'full', 'error', 'invalid', 'success', 'valid', 'placement'];\n }\n\n /** Evita renders em cascata durante mudanças internas agrupadas. */\n private _suppressRender = false;\n /** Resultado de `_precisaFixed` cacheado por abertura (evita getComputedStyle no scroll). */\n private _fixedMode = false;\n private _fixedResolved = false;\n\n protected override attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (this._suppressRender) return;\n super.attributeChangedCallback(name, oldValue, newValue);\n }\n\n /** Espaço (px) entre o campo e o painel — espelha `--fx-select-panel-offset`. */\n private static readonly GAP = 4;\n /** Margem (px) mantida entre o painel e as bordas da viewport. */\n private static readonly MARGEM = 8;\n /** Altura mínima do painel ao ser limitado pelo espaço disponível. */\n private static readonly MIN_ALTURA = 80;\n\n private observer?: MutationObserver;\n private docListener?: (e: Event) => void;\n /** Reposiciona o painel enquanto ele estiver aberto (bound em `_abrir`). */\n private onReflow?: () => void;\n\n /** Tamanho do campo. Padrão: `'md'`. */\n get size(): string {\n const s = this.getAttr('size', 'md');\n return s === 'sm' || s === 'lg' ? s : 'md';\n }\n set size(value: string) {\n this.setAttribute('size', value);\n }\n\n get value(): string {\n return this.getAttr('value');\n }\n set value(value: string | number | null | undefined) {\n const next = value == null ? '' : String(value);\n const prev = this.getAttr('value');\n\n // setAttribute dispara attributeChangedCallback → render (quando conectado).\n if (prev !== next) this.setAttribute('value', next);\n this.updateFormValue();\n }\n\n get disabled(): boolean {\n return this.hasAttr('disabled');\n }\n set disabled(value: boolean) {\n this.toggleAttr('disabled', Boolean(value));\n }\n\n get searchable(): boolean {\n return this.hasAttr('searchable');\n }\n set searchable(value: boolean) {\n this.toggleAttr('searchable', Boolean(value));\n }\n\n get clearable(): boolean {\n return this.hasAttr('clearable');\n }\n set clearable(value: boolean) {\n this.toggleAttr('clearable', Boolean(value));\n }\n\n get full(): boolean {\n return this.hasAttr('full');\n }\n set full(value: boolean) {\n this.toggleAttr('full', Boolean(value));\n }\n\n private get options(): { value: string; label: string }[] {\n return [...this.querySelectorAll('option')].map((o) => ({\n value: o.getAttribute('value') ?? o.textContent?.trim() ?? '',\n label: o.textContent?.trim() ?? '',\n }));\n }\n\n protected override connectedCallback(): void {\n super.connectedCallback();\n // Espelha mudanças nas <option> do light DOM — inclusive `value`/`selected`\n // alterados em runtime pelo framework (Vue atualiza atributos, não filhos).\n this.observer = new MutationObserver((mutations) => {\n // Mudanças no `value` do próprio host são tratadas pelo setter (que já\n // renderiza); ignorá-las evita um segundo render assíncrono.\n if (mutations.every((m) => m.type === 'attributes' && m.target === this)) return;\n this.render();\n });\n this.observer.observe(this, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n attributeFilter: ['value', 'selected'],\n });\n // Fecha o dropdown ao clicar fora.\n this.docListener = (e: Event) => {\n if (!this.hasAttr('open')) return;\n if (e.composedPath().includes(this)) return;\n this._fechar();\n this.render();\n };\n document.addEventListener('click', this.docListener);\n }\n\n protected override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.observer?.disconnect();\n if (this.docListener) document.removeEventListener('click', this.docListener);\n this._unbindReflow();\n }\n\n /** Abre o dropdown, posiciona o painel e passa a reposicioná-lo no reflow. */\n private _abrir(): void {\n // Resolve o modo (fixed/absolute) UMA vez por abertura; o scroll só\n // recalcula coordenadas, sem varrer ancestrais/getComputedStyle.\n this._fixedMode = FxSelect._precisaFixed(this);\n this._fixedResolved = true;\n this.setAttribute('open', '');\n this._bindReflow();\n }\n\n /** Fecha o dropdown e libera os listeners de resize/scroll. */\n private _fechar(): void {\n this.removeAttribute('open');\n // Sem isto o `data-placement` fica preso no host e a próxima abertura\n // mostraria o painel na posição invertida antes do ajuste rodar.\n this.removeAttribute('data-placement');\n this._fixedMode = false;\n this._fixedResolved = false;\n this._unbindReflow();\n }\n\n /** Liga o reposicionamento (resize + scroll interno, em capture). */\n private _bindReflow(): void {\n if (this.onReflow) return;\n this.onReflow = () => {\n if (this.hasAttr('open')) this.ajustarPosicao();\n };\n window.addEventListener('resize', this.onReflow);\n window.addEventListener('scroll', this.onReflow, true);\n }\n\n private _unbindReflow(): void {\n if (!this.onReflow) return;\n window.removeEventListener('resize', this.onReflow);\n window.removeEventListener('scroll', this.onReflow, true);\n this.onReflow = undefined;\n }\n\n /**\n * Decide a posição vertical do painel medindo o espaço real da viewport.\n *\n * `placement=\"top\"`/`\"bottom\"` são respeitados literalmente; o padrão\n * (`auto`) só inverte quando o painel não cabe embaixo E couber melhor\n * acima. Também limita a altura ao espaço disponível e evita overflow\n * horizontal próximo à borda direita.\n */\n protected ajustarPosicao(): void {\n const painel = this.root.querySelector<HTMLElement>('.panel');\n const trigger = this.root.querySelector<HTMLElement>('.trigger');\n if (!painel || !trigger) return;\n\n const r = trigger.getBoundingClientRect();\n const abaixo = window.innerHeight - r.bottom; // espaço livre embaixo\n const acima = r.top; // espaço livre acima\n const desejado = painel.scrollHeight; // altura já com a busca\n const maxAltura = FxSelect._maxAltura(this);\n\n const pedido = this.getAttr('placement', 'auto');\n const paraCima =\n pedido === 'top' ||\n (pedido !== 'bottom' && abaixo < Math.min(desejado, maxAltura) && acima > abaixo);\n\n // O atributo placement do host tem precedência no CSS; data-placement\n // é o canal interno do auto-flip e usa a mesma regra de estilo.\n if (paraCima) this.setAttribute('data-placement', 'top');\n else this.removeAttribute('data-placement');\n\n // Limita a altura ao espaço real disponível (evita o painel vazar da tela).\n const disponivel = Math.max(\n FxSelect.MIN_ALTURA,\n (paraCima ? acima : abaixo) - FxSelect.GAP,\n );\n const altura = Math.min(desejado || disponivel, disponivel, maxAltura);\n painel.style.maxHeight = `${altura}px`;\n\n // Dentro de containers com overflow (fx-card e afins) o painel absoluto é\n // cortado. Nesse caso usa coordenadas fixas a partir do trigger — imune\n // ao clipping do ancestral. Fora disso mantém o fluxo absoluto histórico.\n if (!this._fixedResolved) {\n this._fixedMode = FxSelect._precisaFixed(this);\n this._fixedResolved = true;\n }\n if (this._fixedMode) {\n this.setAttribute('data-fixed', '');\n const largura = Math.max(r.width, 220);\n const esquerda = Math.max(\n FxSelect.MARGEM,\n Math.min(r.left, window.innerWidth - largura - FxSelect.MARGEM),\n );\n const topo = paraCima\n ? Math.max(FxSelect.MARGEM, r.top - FxSelect.GAP - altura)\n : r.bottom + FxSelect.GAP;\n\n painel.style.bottom = 'auto';\n painel.style.width = `${largura}px`;\n painel.style.left = `${esquerda}px`;\n painel.style.top = `${topo}px`;\n return;\n }\n\n // Reset do estado fixed (caso o select tenha sido movido de contexto).\n this.removeAttribute('data-fixed');\n painel.style.top = '';\n painel.style.bottom = '';\n painel.style.width = '';\n\n // Reset do deslocamento horizontal antes de remedir (o painel é recriado\n // a cada render, mas o ajuste pode rodar várias vezes com o mesmo nó).\n painel.style.left = '';\n const largura = painel.offsetWidth;\n const excesso = r.left + largura - (window.innerWidth - FxSelect.MARGEM);\n if (excesso > 0) {\n painel.style.left = `${-excesso}px`;\n painel.style.right = 'auto';\n }\n }\n\n /**\n * Existe ancestral com overflow que cortaria o painel absoluto?\n * `getComputedStyle` é defensivo: em jsdom retorna vazio e o modo\n * histórico (absoluto) é mantido.\n */\n private static _precisaFixed(host: HTMLElement): boolean {\n let el = host.parentElement;\n while (el && el !== document.body && el !== document.documentElement) {\n const cs = getComputedStyle(el);\n const overflow = `${cs.overflow}${cs.overflowX}${cs.overflowY}`;\n if (/(hidden|clip|auto|scroll|overlay)/.test(overflow)) return true;\n el = el.parentElement;\n }\n return false;\n }\n\n /** Altura máxima do painel a partir de `--fx-select-panel-max-height`. */\n private static _maxAltura(host: HTMLElement): number {\n const raw = getComputedStyle(host).getPropertyValue('--fx-select-panel-max-height');\n const n = parseInt(raw, 10);\n return Number.isFinite(n) && n > 0 ? n : 260;\n }\n\n private select(value: string): void {\n // Agrupa: o setter NÃO renderiza aqui; o render acontece uma única vez\n // depois de fechar o painel.\n this._suppressRender = true;\n try {\n this.value = value;\n } finally {\n this._suppressRender = false;\n }\n this._fechar();\n this.render();\n this.emitValueEvents();\n this.dispatchEvent(\n new CustomEvent('change', { bubbles: true, composed: true, detail: { value } }),\n );\n }\n\n /** Navegação por teclado entre as opções do listbox (WCAG 2.1.1). */\n private _navigateOptions(e: KeyboardEvent): void {\n e.preventDefault();\n if (!this.hasAttr('open')) {\n this._abrir();\n this.render();\n }\n const opts = Array.from(this.root.querySelectorAll<HTMLButtonElement>('.opt'));\n if (!opts.length) return;\n const current = opts.indexOf(this.root.activeElement as HTMLButtonElement);\n let next = 0;\n if (e.key === 'ArrowDown') next = current === -1 ? 0 : Math.min(current + 1, opts.length - 1);\n else if (e.key === 'ArrowUp') next = current === -1 ? opts.length - 1 : Math.max(current - 1, 0);\n else if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = opts.length - 1;\n opts[next]?.focus();\n }\n\n protected override render(): void {\n const prevOpen = this.hasAttr('open');\n if (!prevOpen) {\n this._fixedMode = false;\n this._fixedResolved = false;\n }\n const prevSearch = this.root.querySelector<HTMLInputElement>('.search');\n // Estado do campo de busca antes de re-renderizar (valor, foco e cursor).\n const search = prevSearch?.value ?? '';\n const searchFocused =\n prevSearch != null && this.root.activeElement === prevSearch;\n const caretPos = searchFocused ? prevSearch!.selectionStart : null;\n\n const opts = this.options;\n let current = this.getAttr('value');\n if (!current) {\n const explicit = this.querySelector('option[selected]');\n current = explicit?.getAttribute('value') ?? explicit?.textContent?.trim() ?? '';\n }\n const selectedLabel = opts.find((o) => o.value === current)?.label ?? '';\n const placeholder = this.getAttr('placeholder', 'Selecione…');\n\n const filtered = search\n ? opts.filter((o) => o.label.toLowerCase().includes(search.toLowerCase()))\n : opts;\n\n this.setTemplate(`\n <span class=\"trigger\" part=\"trigger\" role=\"button\" tabindex=\"${this.disabled ? -1 : 0}\" aria-haspopup=\"listbox\" aria-expanded=\"${prevOpen}\">\n <span class=\"${selectedLabel ? 'label' : 'placeholder'}\">${esc(selectedLabel) || esc(placeholder)}</span>\n <span class=\"actions\">\n ${this.hasAttr('clearable') && current ? '<button type=\"button\" class=\"clear\" part=\"clear\" aria-label=\"Limpar\">×</button>' : ''}\n <span class=\"caret\">▼</span>\n </span>\n </span>\n <div class=\"panel\" part=\"panel\" role=\"listbox\">\n ${this.hasAttr('searchable') ? `<input class=\"search\" part=\"search\" type=\"text\" autocomplete=\"off\" placeholder=\"${esc(this.getAttr('search-placeholder', 'Pesquisar…'))}\">` : ''}\n ${filtered.map((o) => `\n <button type=\"button\" class=\"opt\" role=\"option\" data-value=\"${esc(o.value)}\"\n aria-selected=\"${o.value === current}\">${esc(o.label)}</button>`).join('')}\n ${filtered.length === 0 ? `<div class=\"empty\">${esc(this.getAttr('no-results', 'Nenhum resultado'))}</div>` : ''}\n </div>\n `);\n\n if (prevOpen) this.setAttribute('open', '');\n // A medição só é válida com o painel já `display: block` (open aplicado).\n if (this.hasAttr('open')) this.ajustarPosicao();\n const searchInput = this.root.querySelector<HTMLInputElement>('.search');\n if (searchInput) {\n searchInput.value = search;\n searchInput.addEventListener('input', () => this.render());\n searchInput.addEventListener('click', (e) => e.stopPropagation());\n // Re-render não pode roubar o foco nem perder a posição do cursor.\n if (searchFocused) {\n searchInput.focus();\n try { searchInput.setSelectionRange(caretPos!, caretPos!); } catch { /* type=text sempre suporta */ }\n }\n }\n\n const trigger = this.root.querySelector<HTMLElement>('.trigger');\n if (!trigger) return;\n if (this.disabled) trigger.setAttribute('aria-disabled', 'true');\n\n trigger.addEventListener('click', (e) => {\n if (this.disabled) return;\n if ((e.target as HTMLElement).closest('.clear')) return;\n if (this.hasAttr('open')) this._fechar();\n else this._abrir();\n this.render();\n this.root.querySelector<HTMLInputElement>('.search')?.focus();\n });\n\n // Teclado: Enter/Espaço abrem o dropdown; setas/Home/End/Escape navegam.\n trigger.addEventListener('keydown', (e) => {\n if (this.disabled) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n trigger.click();\n return;\n }\n if (e.key === 'Escape') {\n if (this.hasAttr('open')) {\n this._fechar();\n this.render();\n this.root.querySelector<HTMLElement>('.trigger')?.focus();\n }\n return;\n }\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Home' || e.key === 'End') {\n this._navigateOptions(e);\n }\n });\n\n // Limpar.\n this.root.querySelector('.clear')?.addEventListener('click', (e) => {\n e.stopPropagation();\n this._suppressRender = true;\n try {\n this.value = '';\n } finally {\n this._suppressRender = false;\n }\n this._fechar();\n this.render();\n this.emitValueEvents();\n this.dispatchEvent(\n new CustomEvent('change', { bubbles: true, composed: true, detail: { value: '' } }),\n );\n });\n\n // Escolher opção.\n this.root.querySelectorAll<HTMLElement>('.opt').forEach((opt) => {\n opt.addEventListener('click', () => this.select(opt.dataset.value!));\n });\n\n // Publica name/value no form (ElementInternals) a cada render.\n this.updateFormValue();\n }\n\n /** form.reset(): restaura o valor inicial e re-renderiza o rótulo. */\n override formResetCallback(): void {\n this._suppressRender = true;\n try {\n super.formResetCallback();\n } finally {\n this._suppressRender = false;\n }\n this.render();\n }\n}\n\nexport function defineFxSelect(): typeof FxSelect {\n return defineElement('fx-select', FxSelect);\n}\n\n"],"names":["largura"],"mappings":";;;;AA0BO,MAAM,YAAN,MAAM,kBAAiB,cAAc;AAAA,EAArC,cAAA;AAAA,UAAA,GAAA,SAAA;AAiML,SAAQ,kBAAkB;AAE1B,SAAQ,aAAa;AACrB,SAAQ,iBAAiB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAVzB,WAAoB,qBAA+B;AAG7C,WAAO,CAAC,SAAS,QAAQ,YAAY,eAAe,cAAc,aAAa,QAAQ,SAAS,WAAW,WAAW,SAAS,WAAW;AAAA,EAChJ;AAAA,EAQmB,yBAAyB,MAAc,UAAyB,UAA+B;AAChH,QAAI,KAAK,gBAAiB;AAC1B,UAAM,yBAAyB,MAAM,UAAU,QAAQ;AAAA,EACzD;AAAA;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;AACtB,SAAK,aAAa,QAAQ,KAAK;AAAA,EACjC;AAAA,EAEA,IAAI,QAAgB;AAClB,WAAO,KAAK,QAAQ,OAAO;AAAA,EAC7B;AAAA,EACA,IAAI,MAAM,OAA2C;AACnD,UAAM,OAAO,SAAS,OAAO,KAAK,OAAO,KAAK;AAC9C,UAAM,OAAO,KAAK,QAAQ,OAAO;AAGjC,QAAI,SAAS,KAAM,MAAK,aAAa,SAAS,IAAI;AAClD,SAAK,gBAAA;AAAA,EACP;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,EAEA,IAAI,aAAsB;AACxB,WAAO,KAAK,QAAQ,YAAY;AAAA,EAClC;AAAA,EACA,IAAI,WAAW,OAAgB;AAC7B,SAAK,WAAW,cAAc,QAAQ,KAAK,CAAC;AAAA,EAC9C;AAAA,EAEA,IAAI,YAAqB;AACvB,WAAO,KAAK,QAAQ,WAAW;AAAA,EACjC;AAAA,EACA,IAAI,UAAU,OAAgB;AAC5B,SAAK,WAAW,aAAa,QAAQ,KAAK,CAAC;AAAA,EAC7C;AAAA,EAEA,IAAI,OAAgB;AAClB,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AAAA,EACA,IAAI,KAAK,OAAgB;AACvB,SAAK,WAAW,QAAQ,QAAQ,KAAK,CAAC;AAAA,EACxC;AAAA,EAEA,IAAY,UAA8C;AACxD,WAAO,CAAC,GAAG,KAAK,iBAAiB,QAAQ,CAAC,EAAE,IAAI,CAAC,OAAO;AAAA,MACtD,OAAO,EAAE,aAAa,OAAO,KAAK,EAAE,aAAa,UAAU;AAAA,MAC3D,OAAO,EAAE,aAAa,UAAU;AAAA,IAAA,EAChC;AAAA,EACJ;AAAA,EAEmB,oBAA0B;AAC3C,UAAM,kBAAA;AAGN,SAAK,WAAW,IAAI,iBAAiB,CAAC,cAAc;AAGlD,UAAI,UAAU,MAAM,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,WAAW,IAAI,EAAG;AAC1E,WAAK,OAAA;AAAA,IACP,CAAC;AACD,SAAK,SAAS,QAAQ,MAAM;AAAA,MAC1B,WAAW;AAAA,MACX,SAAS;AAAA,MACT,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,iBAAiB,CAAC,SAAS,UAAU;AAAA,IAAA,CACtC;AAED,SAAK,cAAc,CAAC,MAAa;AAC/B,UAAI,CAAC,KAAK,QAAQ,MAAM,EAAG;AAC3B,UAAI,EAAE,aAAA,EAAe,SAAS,IAAI,EAAG;AACrC,WAAK,QAAA;AACL,WAAK,OAAA;AAAA,IACP;AACA,aAAS,iBAAiB,SAAS,KAAK,WAAW;AAAA,EACrD;AAAA,EAEmB,uBAA6B;AAC9C,UAAM,qBAAA;AACN,SAAK,UAAU,WAAA;AACf,QAAI,KAAK,YAAa,UAAS,oBAAoB,SAAS,KAAK,WAAW;AAC5E,SAAK,cAAA;AAAA,EACP;AAAA;AAAA,EAGQ,SAAe;AAGrB,SAAK,aAAa,UAAS,cAAc,IAAI;AAC7C,SAAK,iBAAiB;AACtB,SAAK,aAAa,QAAQ,EAAE;AAC5B,SAAK,YAAA;AAAA,EACP;AAAA;AAAA,EAGQ,UAAgB;AACtB,SAAK,gBAAgB,MAAM;AAG3B,SAAK,gBAAgB,gBAAgB;AACrC,SAAK,aAAa;AAClB,SAAK,iBAAiB;AACtB,SAAK,cAAA;AAAA,EACP;AAAA;AAAA,EAGQ,cAAoB;AAC1B,QAAI,KAAK,SAAU;AACnB,SAAK,WAAW,MAAM;AACpB,UAAI,KAAK,QAAQ,MAAM,QAAQ,eAAA;AAAA,IACjC;AACA,WAAO,iBAAiB,UAAU,KAAK,QAAQ;AAC/C,WAAO,iBAAiB,UAAU,KAAK,UAAU,IAAI;AAAA,EACvD;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,CAAC,KAAK,SAAU;AACpB,WAAO,oBAAoB,UAAU,KAAK,QAAQ;AAClD,WAAO,oBAAoB,UAAU,KAAK,UAAU,IAAI;AACxD,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUU,iBAAuB;AAC/B,UAAM,SAAS,KAAK,KAAK,cAA2B,QAAQ;AAC5D,UAAM,UAAU,KAAK,KAAK,cAA2B,UAAU;AAC/D,QAAI,CAAC,UAAU,CAAC,QAAS;AAEzB,UAAM,IAAI,QAAQ,sBAAA;AAClB,UAAM,SAAS,OAAO,cAAc,EAAE;AACtC,UAAM,QAAQ,EAAE;AAChB,UAAM,WAAW,OAAO;AACxB,UAAM,YAAY,UAAS,WAAW,IAAI;AAE1C,UAAM,SAAS,KAAK,QAAQ,aAAa,MAAM;AAC/C,UAAM,WACJ,WAAW,SACV,WAAW,YAAY,SAAS,KAAK,IAAI,UAAU,SAAS,KAAK,QAAQ;AAI5E,QAAI,SAAU,MAAK,aAAa,kBAAkB,KAAK;AAAA,QAClD,MAAK,gBAAgB,gBAAgB;AAG1C,UAAM,aAAa,KAAK;AAAA,MACtB,UAAS;AAAA,OACR,WAAW,QAAQ,UAAU,UAAS;AAAA,IAAA;AAEzC,UAAM,SAAS,KAAK,IAAI,YAAY,YAAY,YAAY,SAAS;AACrE,WAAO,MAAM,YAAY,GAAG,MAAM;AAKlC,QAAI,CAAC,KAAK,gBAAgB;AACxB,WAAK,aAAa,UAAS,cAAc,IAAI;AAC7C,WAAK,iBAAiB;AAAA,IACxB;AACA,QAAI,KAAK,YAAY;AACnB,WAAK,aAAa,cAAc,EAAE;AAClC,YAAMA,WAAU,KAAK,IAAI,EAAE,OAAO,GAAG;AACrC,YAAM,WAAW,KAAK;AAAA,QACpB,UAAS;AAAA,QACT,KAAK,IAAI,EAAE,MAAM,OAAO,aAAaA,WAAU,UAAS,MAAM;AAAA,MAAA;AAEhE,YAAM,OAAO,WACT,KAAK,IAAI,UAAS,QAAQ,EAAE,MAAM,UAAS,MAAM,MAAM,IACvD,EAAE,SAAS,UAAS;AAExB,aAAO,MAAM,SAAS;AACtB,aAAO,MAAM,QAAQ,GAAGA,QAAO;AAC/B,aAAO,MAAM,OAAO,GAAG,QAAQ;AAC/B,aAAO,MAAM,MAAM,GAAG,IAAI;AAC1B;AAAA,IACF;AAGA,SAAK,gBAAgB,YAAY;AACjC,WAAO,MAAM,MAAM;AACnB,WAAO,MAAM,SAAS;AACtB,WAAO,MAAM,QAAQ;AAIrB,WAAO,MAAM,OAAO;AACpB,UAAM,UAAU,OAAO;AACvB,UAAM,UAAU,EAAE,OAAO,WAAW,OAAO,aAAa,UAAS;AACjE,QAAI,UAAU,GAAG;AACf,aAAO,MAAM,OAAO,GAAG,CAAC,OAAO;AAC/B,aAAO,MAAM,QAAQ;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAe,cAAc,MAA4B;AACvD,QAAI,KAAK,KAAK;AACd,WAAO,MAAM,OAAO,SAAS,QAAQ,OAAO,SAAS,iBAAiB;AACpE,YAAM,KAAK,iBAAiB,EAAE;AAC9B,YAAM,WAAW,GAAG,GAAG,QAAQ,GAAG,GAAG,SAAS,GAAG,GAAG,SAAS;AAC7D,UAAI,oCAAoC,KAAK,QAAQ,EAAG,QAAO;AAC/D,WAAK,GAAG;AAAA,IACV;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OAAe,WAAW,MAA2B;AACnD,UAAM,MAAM,iBAAiB,IAAI,EAAE,iBAAiB,8BAA8B;AAClF,UAAM,IAAI,SAAS,KAAK,EAAE;AAC1B,WAAO,OAAO,SAAS,CAAC,KAAK,IAAI,IAAI,IAAI;AAAA,EAC3C;AAAA,EAEQ,OAAO,OAAqB;AAGlC,SAAK,kBAAkB;AACvB,QAAI;AACF,WAAK,QAAQ;AAAA,IACf,UAAA;AACE,WAAK,kBAAkB;AAAA,IACzB;AACA,SAAK,QAAA;AACL,SAAK,OAAA;AACL,SAAK,gBAAA;AACL,SAAK;AAAA,MACH,IAAI,YAAY,UAAU,EAAE,SAAS,MAAM,UAAU,MAAM,QAAQ,EAAE,QAAM,CAAG;AAAA,IAAA;AAAA,EAElF;AAAA;AAAA,EAGQ,iBAAiB,GAAwB;AAC/C,MAAE,eAAA;AACF,QAAI,CAAC,KAAK,QAAQ,MAAM,GAAG;AACzB,WAAK,OAAA;AACL,WAAK,OAAA;AAAA,IACP;AACA,UAAM,OAAO,MAAM,KAAK,KAAK,KAAK,iBAAoC,MAAM,CAAC;AAC7E,QAAI,CAAC,KAAK,OAAQ;AAClB,UAAM,UAAU,KAAK,QAAQ,KAAK,KAAK,aAAkC;AACzE,QAAI,OAAO;AACX,QAAI,EAAE,QAAQ,YAAa,QAAO,YAAY,KAAK,IAAI,KAAK,IAAI,UAAU,GAAG,KAAK,SAAS,CAAC;AAAA,aACnF,EAAE,QAAQ,UAAW,QAAO,YAAY,KAAK,KAAK,SAAS,IAAI,KAAK,IAAI,UAAU,GAAG,CAAC;AAAA,aACtF,EAAE,QAAQ,OAAQ,QAAO;AAAA,aACzB,EAAE,QAAQ,MAAO,QAAO,KAAK,SAAS;AAC/C,SAAK,IAAI,GAAG,MAAA;AAAA,EACd;AAAA,EAEmB,SAAe;AAChC,UAAM,WAAW,KAAK,QAAQ,MAAM;AACpC,QAAI,CAAC,UAAU;AACb,WAAK,aAAa;AAClB,WAAK,iBAAiB;AAAA,IACxB;AACA,UAAM,aAAa,KAAK,KAAK,cAAgC,SAAS;AAEtE,UAAM,SAAS,YAAY,SAAS;AACpC,UAAM,gBACJ,cAAc,QAAQ,KAAK,KAAK,kBAAkB;AACpD,UAAM,WAAW,gBAAgB,WAAY,iBAAiB;AAE9D,UAAM,OAAO,KAAK;AAClB,QAAI,UAAU,KAAK,QAAQ,OAAO;AAClC,QAAI,CAAC,SAAS;AACZ,YAAM,WAAW,KAAK,cAAc,kBAAkB;AACtD,gBAAU,UAAU,aAAa,OAAO,KAAK,UAAU,aAAa,UAAU;AAAA,IAChF;AACA,UAAM,gBAAgB,KAAK,KAAK,CAAC,MAAM,EAAE,UAAU,OAAO,GAAG,SAAS;AACtE,UAAM,cAAc,KAAK,QAAQ,eAAe,YAAY;AAE5D,UAAM,WAAW,SACb,KAAK,OAAO,CAAC,MAAM,EAAE,MAAM,YAAA,EAAc,SAAS,OAAO,YAAA,CAAa,CAAC,IACvE;AAEJ,SAAK,YAAY;AAAA,qEACgD,KAAK,WAAW,KAAK,CAAC,4CAA4C,QAAQ;AAAA,uBACxH,gBAAgB,UAAU,aAAa,KAAK,IAAI,aAAa,KAAK,IAAI,WAAW,CAAC;AAAA;AAAA,YAE7F,KAAK,QAAQ,WAAW,KAAK,UAAU,oFAAoF,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,UAK/H,KAAK,QAAQ,YAAY,IAAI,mFAAmF,IAAI,KAAK,QAAQ,sBAAsB,YAAY,CAAC,CAAC,OAAO,EAAE;AAAA,UAC9K,SAAS,IAAI,CAAC,MAAM;AAAA,wEAC0C,IAAI,EAAE,KAAK,CAAC;AAAA,6BACvD,EAAE,UAAU,OAAO,KAAK,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC;AAAA,UAC5E,SAAS,WAAW,IAAI,sBAAsB,IAAI,KAAK,QAAQ,cAAc,kBAAkB,CAAC,CAAC,WAAW,EAAE;AAAA;AAAA,KAEnH;AAED,QAAI,SAAU,MAAK,aAAa,QAAQ,EAAE;AAE1C,QAAI,KAAK,QAAQ,MAAM,QAAQ,eAAA;AAC/B,UAAM,cAAc,KAAK,KAAK,cAAgC,SAAS;AACvE,QAAI,aAAa;AACf,kBAAY,QAAQ;AACpB,kBAAY,iBAAiB,SAAS,MAAM,KAAK,QAAQ;AACzD,kBAAY,iBAAiB,SAAS,CAAC,MAAM,EAAE,iBAAiB;AAEhE,UAAI,eAAe;AACjB,oBAAY,MAAA;AACZ,YAAI;AAAE,sBAAY,kBAAkB,UAAW,QAAS;AAAA,QAAG,QAAQ;AAAA,QAAiC;AAAA,MACtG;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,KAAK,cAA2B,UAAU;AAC/D,QAAI,CAAC,QAAS;AACd,QAAI,KAAK,SAAU,SAAQ,aAAa,iBAAiB,MAAM;AAE/D,YAAQ,iBAAiB,SAAS,CAAC,MAAM;AACvC,UAAI,KAAK,SAAU;AACnB,UAAK,EAAE,OAAuB,QAAQ,QAAQ,EAAG;AACjD,UAAI,KAAK,QAAQ,MAAM,QAAQ,QAAA;AAAA,gBACrB,OAAA;AACV,WAAK,OAAA;AACL,WAAK,KAAK,cAAgC,SAAS,GAAG,MAAA;AAAA,IACxD,CAAC;AAGD,YAAQ,iBAAiB,WAAW,CAAC,MAAM;AACzC,UAAI,KAAK,SAAU;AACnB,UAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,UAAE,eAAA;AACF,gBAAQ,MAAA;AACR;AAAA,MACF;AACA,UAAI,EAAE,QAAQ,UAAU;AACtB,YAAI,KAAK,QAAQ,MAAM,GAAG;AACxB,eAAK,QAAA;AACL,eAAK,OAAA;AACL,eAAK,KAAK,cAA2B,UAAU,GAAG,MAAA;AAAA,QACpD;AACA;AAAA,MACF;AACA,UAAI,EAAE,QAAQ,eAAe,EAAE,QAAQ,aAAa,EAAE,QAAQ,UAAU,EAAE,QAAQ,OAAO;AACvF,aAAK,iBAAiB,CAAC;AAAA,MACzB;AAAA,IACF,CAAC;AAGD,SAAK,KAAK,cAAc,QAAQ,GAAG,iBAAiB,SAAS,CAAC,MAAM;AAClE,QAAE,gBAAA;AACF,WAAK,kBAAkB;AACvB,UAAI;AACF,aAAK,QAAQ;AAAA,MACf,UAAA;AACE,aAAK,kBAAkB;AAAA,MACzB;AACA,WAAK,QAAA;AACL,WAAK,OAAA;AACL,WAAK,gBAAA;AACL,WAAK;AAAA,QACH,IAAI,YAAY,UAAU,EAAE,SAAS,MAAM,UAAU,MAAM,QAAQ,EAAE,OAAO,GAAA,GAAM;AAAA,MAAA;AAAA,IAEtF,CAAC;AAGD,SAAK,KAAK,iBAA8B,MAAM,EAAE,QAAQ,CAAC,QAAQ;AAC/D,UAAI,iBAAiB,SAAS,MAAM,KAAK,OAAO,IAAI,QAAQ,KAAM,CAAC;AAAA,IACrE,CAAC;AAGD,SAAK,gBAAA;AAAA,EACP;AAAA;AAAA,EAGS,oBAA0B;AACjC,SAAK,kBAAkB;AACvB,QAAI;AACF,YAAM,kBAAA;AAAA,IACR,UAAA;AACE,WAAK,kBAAkB;AAAA,IACzB;AACA,SAAK,OAAA;AAAA,EACP;AACF;AA/lBE,UAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2MzB,UAAwB,MAAM;AAE9B,UAAwB,SAAS;AAEjC,UAAwB,aAAa;AAhNhC,IAAM,WAAN;AAkmBA,SAAS,iBAAkC;AAChD,SAAO,cAAc,aAAa,QAAQ;AAC5C;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/components/table/table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQ5C,OAAO,WAAW,CAAC;AAEnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,qBAAa,OAAQ,SAAQ,SAAS;IACrC,OAAgB,MAAM,
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/components/table/table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQ5C,OAAO,WAAW,CAAC;AAEnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,qBAAa,OAAQ,SAAQ,SAAS;IACrC,OAAgB,MAAM,SAiTpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAoBjD;IAED,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,eAAe,CAAC,CAAmB;IAC3C,kFAAkF;IAClF,OAAO,CAAC,mBAAmB,CAAmC;IAE9D,IAAI,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAEpC;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAGxC;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAGtB;IAED,IAAI,WAAW,IAAI,MAAM,CAGxB;IACD,IAAI,WAAW,CAAC,KAAK,EAAE,MAAM,EAE5B;IAED,IAAI,IAAI,IAAI,OAAO,CAElB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAEtB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IACD,IAAI,UAAU,CAAC,KAAK,EAAE,OAAO,EAE5B;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAEzB;IAED,IAAI,KAAK,IAAI,OAAO,CAEnB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,OAAO,EAEvB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAEzB;IAED;;;;OAIG;IACH,IAAI,cAAc,IAAI,OAAO,CAE5B;IACD,IAAI,cAAc,CAAC,KAAK,EAAE,OAAO,EAEhC;IAED,OAAO,KAAK,OAAO,GAuBlB;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,OAAO,CAAC,oBAAoB;IAW5B,OAAO,KAAK,eAAe,GAU1B;IAED;;;;OAIG;IACH,OAAO,CAAC,WAAW;cAeA,iBAAiB,IAAI,IAAI;cAkBzB,oBAAoB,IAAI,IAAI;IAK/C,+EAA+E;IAC/E,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,mBAAmB;IAgB3B,OAAO,CAAC,WAAW;IAiDnB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,QAAQ;IAahB;;;;;;;OAOG;IACH,OAAO,CAAC,SAAS,CAAM;cAEJ,MAAM,IAAI,IAAI;IAoPjC;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IAmBtB,oEAAoE;IACpE,OAAO,CAAC,yBAAyB;IAWjC;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,qBAAqB;CAiB7B;AAED,wBAAgB,aAAa,IAAI,OAAO,OAAO,CAE9C"}
|
|
@@ -288,7 +288,7 @@ const _FxTable = class _FxTable extends FxElement {
|
|
|
288
288
|
const activeClass = isSorted ? "active" : "";
|
|
289
289
|
return `<th part="header" class="${c.sortable ? "sortable" : ""}" style="text-align:${c.align}" data-field="${esc(c.field)}">${esc(c.header)}${ind ? `<span class="sort-ind ${activeClass}">${ind}</span>` : ""}</th>`;
|
|
290
290
|
}).join("");
|
|
291
|
-
const filterRow = cols.some((c) => c.filterable) ? `<tr class="filter-row">${cols.map((c) => `<th style="text-align:${c.align}">${c.filterable ? `<input class="filter" data-field="${esc(c.field)}" placeholder="${esc("Filtrar…")}" value="${esc(this.filters[c.field] ?? "")}">` : ""}</th>`).join("")}</tr>` : "";
|
|
291
|
+
const filterRow = cols.some((c) => c.filterable) ? `<tr class="filter-row">${cols.map((c) => `<th style="text-align:${c.align}">${c.filterable ? `<input class="filter" autocomplete="off" data-field="${esc(c.field)}" placeholder="${esc("Filtrar…")}" value="${esc(this.filters[c.field] ?? "")}">` : ""}</th>`).join("")}</tr>` : "";
|
|
292
292
|
const bodyHtml = rows.length ? rows.map(
|
|
293
293
|
(row, i) => `<tr part="row" data-index="${i}">${cols.map((c) => `<td part="cell" style="text-align:${c.align}">${this.cellHtml(c, row)}</td>`).join("")}</tr>`
|
|
294
294
|
).join("") : `<tr><td class="empty" colspan="${cols.length || 1}">${esc(this.getAttr("empty-message", "Nenhum registro encontrado"))}</td></tr>`;
|
|
@@ -568,6 +568,13 @@ _FxTable.styles = css`
|
|
|
568
568
|
border-bottom: 2px solid var(--fx-border-default);
|
|
569
569
|
white-space: nowrap;
|
|
570
570
|
user-select: none;
|
|
571
|
+
/* Cor/peso do cabeçalho por token de TABELA. Sem isso o th herda
|
|
572
|
+
--fx-text-default do host e o peso vem do UA (bold). */
|
|
573
|
+
color: var(
|
|
574
|
+
--fx-table-header-text,
|
|
575
|
+
var(--fx-table-text, var(--fx-text-default))
|
|
576
|
+
);
|
|
577
|
+
font-weight: var(--fx-table-header-weight, bold);
|
|
571
578
|
}
|
|
572
579
|
th.sortable {
|
|
573
580
|
cursor: pointer;
|
|
@@ -612,6 +619,12 @@ _FxTable.styles = css`
|
|
|
612
619
|
td {
|
|
613
620
|
padding: var(--fx-space-sm) var(--fx-space-md);
|
|
614
621
|
border-bottom: 1px solid var(--fx-border-default);
|
|
622
|
+
/* Texto do corpo: token próprio para não depender de
|
|
623
|
+
--fx-text-default (que afeta TODOS os textos do app) e para
|
|
624
|
+
não herdar o font-weight do body da página — era isso que
|
|
625
|
+
fazia a célula parecer mais clara que o cabeçalho. */
|
|
626
|
+
color: var(--fx-table-text, var(--fx-text-default));
|
|
627
|
+
font-weight: var(--fx-table-text-weight, inherit);
|
|
615
628
|
}
|
|
616
629
|
tbody tr {
|
|
617
630
|
cursor: pointer;
|