@wrrdev/fenix-ui 1.1.11 → 1.1.13
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 +2 -2
- package/dist/components/card/card.d.ts +10 -0
- package/dist/components/card/card.d.ts.map +1 -1
- package/dist/components/card/card.js +18 -0
- package/dist/components/card/card.js.map +1 -1
- package/dist/components/select/select.d.ts +29 -1
- package/dist/components/select/select.d.ts.map +1 -1
- package/dist/components/select/select.js +98 -10
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/table/table.d.ts +2 -1
- package/dist/components/table/table.d.ts.map +1 -1
- package/dist/components/table/table.js +92 -22
- package/dist/components/table/table.js.map +1 -1
- package/dist/core/jsx.d.ts +19 -0
- package/dist/core/jsx.d.ts.map +1 -1
- package/dist/core/jsx.js.map +1 -1
- package/dist/docs/componentes/card.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/fenix-ui.umd.min.js +188 -105
- package/dist/fenix-ui4.esm.js +207 -31
- package/dist/fenix-ui4.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/fenix-ui4.esm.js
CHANGED
|
@@ -623,7 +623,7 @@ const _FxSelect = class _FxSelect extends FxElement {
|
|
|
623
623
|
// `value` fica FORA da observação: refleti-lo no change não pode
|
|
624
624
|
// re-renderizar o template e fechar o dropdown.
|
|
625
625
|
static get observedAttributes() {
|
|
626
|
-
return ["size", "disabled", "placeholder", "searchable", "clearable", "error", "invalid", "success", "valid"];
|
|
626
|
+
return ["size", "disabled", "placeholder", "searchable", "clearable", "error", "invalid", "success", "valid", "placement"];
|
|
627
627
|
}
|
|
628
628
|
/** Tamanho do campo. Padrão: `'md'`. */
|
|
629
629
|
get size() {
|
|
@@ -658,7 +658,7 @@ const _FxSelect = class _FxSelect extends FxElement {
|
|
|
658
658
|
this.docListener = (e) => {
|
|
659
659
|
if (!this.hasAttr("open")) return;
|
|
660
660
|
if (e.composedPath().includes(this)) return;
|
|
661
|
-
this.
|
|
661
|
+
this._fechar();
|
|
662
662
|
this.render();
|
|
663
663
|
};
|
|
664
664
|
document.addEventListener("click", this.docListener);
|
|
@@ -667,10 +667,77 @@ const _FxSelect = class _FxSelect extends FxElement {
|
|
|
667
667
|
super.disconnectedCallback();
|
|
668
668
|
this.observer?.disconnect();
|
|
669
669
|
if (this.docListener) document.removeEventListener("click", this.docListener);
|
|
670
|
+
this._unbindReflow();
|
|
671
|
+
}
|
|
672
|
+
/** Abre o dropdown, posiciona o painel e passa a reposicioná-lo no reflow. */
|
|
673
|
+
_abrir() {
|
|
674
|
+
this.setAttribute("open", "");
|
|
675
|
+
this._bindReflow();
|
|
676
|
+
}
|
|
677
|
+
/** Fecha o dropdown e libera os listeners de resize/scroll. */
|
|
678
|
+
_fechar() {
|
|
679
|
+
this.removeAttribute("open");
|
|
680
|
+
this.removeAttribute("data-placement");
|
|
681
|
+
this._unbindReflow();
|
|
682
|
+
}
|
|
683
|
+
/** Liga o reposicionamento (resize + scroll interno, em capture). */
|
|
684
|
+
_bindReflow() {
|
|
685
|
+
if (this.onReflow) return;
|
|
686
|
+
this.onReflow = () => {
|
|
687
|
+
if (this.hasAttr("open")) this.ajustarPosicao();
|
|
688
|
+
};
|
|
689
|
+
window.addEventListener("resize", this.onReflow);
|
|
690
|
+
window.addEventListener("scroll", this.onReflow, true);
|
|
691
|
+
}
|
|
692
|
+
_unbindReflow() {
|
|
693
|
+
if (!this.onReflow) return;
|
|
694
|
+
window.removeEventListener("resize", this.onReflow);
|
|
695
|
+
window.removeEventListener("scroll", this.onReflow, true);
|
|
696
|
+
this.onReflow = void 0;
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Decide a posição vertical do painel medindo o espaço real da viewport.
|
|
700
|
+
*
|
|
701
|
+
* `placement="top"`/`"bottom"` são respeitados literalmente; o padrão
|
|
702
|
+
* (`auto`) só inverte quando o painel não cabe embaixo E couber melhor
|
|
703
|
+
* acima. Também limita a altura ao espaço disponível e evita overflow
|
|
704
|
+
* horizontal próximo à borda direita.
|
|
705
|
+
*/
|
|
706
|
+
ajustarPosicao() {
|
|
707
|
+
const painel = this.root.querySelector(".panel");
|
|
708
|
+
const trigger = this.root.querySelector(".trigger");
|
|
709
|
+
if (!painel || !trigger) return;
|
|
710
|
+
const r = trigger.getBoundingClientRect();
|
|
711
|
+
const abaixo = window.innerHeight - r.bottom;
|
|
712
|
+
const acima = r.top;
|
|
713
|
+
const desejado = painel.scrollHeight;
|
|
714
|
+
const maxAltura = _FxSelect._maxAltura(this);
|
|
715
|
+
const pedido = this.getAttr("placement", "auto");
|
|
716
|
+
const paraCima = pedido === "top" || pedido !== "bottom" && abaixo < Math.min(desejado, maxAltura) && acima > abaixo;
|
|
717
|
+
if (paraCima) this.setAttribute("data-placement", "top");
|
|
718
|
+
else this.removeAttribute("data-placement");
|
|
719
|
+
const disponivel = Math.max(
|
|
720
|
+
_FxSelect.MIN_ALTURA,
|
|
721
|
+
(paraCima ? acima : abaixo) - _FxSelect.GAP
|
|
722
|
+
);
|
|
723
|
+
painel.style.maxHeight = `${Math.min(desejado || disponivel, disponivel, maxAltura)}px`;
|
|
724
|
+
painel.style.left = "";
|
|
725
|
+
const largura = painel.offsetWidth;
|
|
726
|
+
const excesso = r.left + largura - (window.innerWidth - _FxSelect.MARGEM);
|
|
727
|
+
if (excesso > 0) {
|
|
728
|
+
painel.style.left = `${-excesso}px`;
|
|
729
|
+
painel.style.right = "auto";
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
/** Altura máxima do painel a partir de `--fx-select-panel-max-height`. */
|
|
733
|
+
static _maxAltura(host) {
|
|
734
|
+
const raw = getComputedStyle(host).getPropertyValue("--fx-select-panel-max-height");
|
|
735
|
+
const n = parseInt(raw, 10);
|
|
736
|
+
return Number.isFinite(n) && n > 0 ? n : 260;
|
|
670
737
|
}
|
|
671
738
|
select(value) {
|
|
672
739
|
this.value = value;
|
|
673
|
-
this.
|
|
740
|
+
this._fechar();
|
|
674
741
|
this.render();
|
|
675
742
|
this.dispatchEvent(
|
|
676
743
|
new CustomEvent("change", { bubbles: true, composed: true, detail: { value } })
|
|
@@ -680,7 +747,7 @@ const _FxSelect = class _FxSelect extends FxElement {
|
|
|
680
747
|
_navigateOptions(e) {
|
|
681
748
|
e.preventDefault();
|
|
682
749
|
if (!this.hasAttr("open")) {
|
|
683
|
-
this.
|
|
750
|
+
this._abrir();
|
|
684
751
|
this.render();
|
|
685
752
|
}
|
|
686
753
|
const opts = Array.from(this.root.querySelectorAll(".opt"));
|
|
@@ -725,6 +792,7 @@ const _FxSelect = class _FxSelect extends FxElement {
|
|
|
725
792
|
</div>
|
|
726
793
|
`);
|
|
727
794
|
if (prevOpen) this.setAttribute("open", "");
|
|
795
|
+
if (this.hasAttr("open")) this.ajustarPosicao();
|
|
728
796
|
const searchInput = this.root.querySelector(".search");
|
|
729
797
|
if (searchInput) {
|
|
730
798
|
searchInput.value = search;
|
|
@@ -744,7 +812,8 @@ const _FxSelect = class _FxSelect extends FxElement {
|
|
|
744
812
|
trigger.addEventListener("click", (e) => {
|
|
745
813
|
if (this.disabled) return;
|
|
746
814
|
if (e.target.closest(".clear")) return;
|
|
747
|
-
this.
|
|
815
|
+
if (this.hasAttr("open")) this._fechar();
|
|
816
|
+
else this._abrir();
|
|
748
817
|
this.render();
|
|
749
818
|
this.root.querySelector(".search")?.focus();
|
|
750
819
|
});
|
|
@@ -757,7 +826,7 @@ const _FxSelect = class _FxSelect extends FxElement {
|
|
|
757
826
|
}
|
|
758
827
|
if (e.key === "Escape") {
|
|
759
828
|
if (this.hasAttr("open")) {
|
|
760
|
-
this.
|
|
829
|
+
this._fechar();
|
|
761
830
|
this.render();
|
|
762
831
|
this.root.querySelector(".trigger")?.focus();
|
|
763
832
|
}
|
|
@@ -770,7 +839,7 @@ const _FxSelect = class _FxSelect extends FxElement {
|
|
|
770
839
|
this.root.querySelector(".clear")?.addEventListener("click", (e) => {
|
|
771
840
|
e.stopPropagation();
|
|
772
841
|
this.value = "";
|
|
773
|
-
this.
|
|
842
|
+
this._fechar();
|
|
774
843
|
this.render();
|
|
775
844
|
this.dispatchEvent(
|
|
776
845
|
new CustomEvent("change", { bubbles: true, composed: true, detail: { value: "" } })
|
|
@@ -792,6 +861,11 @@ _FxSelect.styles = css`
|
|
|
792
861
|
e style inline no elemento definem a largura sem precisar do full. */
|
|
793
862
|
width: var(--fx-select-width, max-content);
|
|
794
863
|
min-width: var(--fx-select-min-width, 200px);
|
|
864
|
+
/* Espaço entre o campo e o painel + altura máxima do painel. Expostos
|
|
865
|
+
como custom property porque ::part() do lado do consumidor tem
|
|
866
|
+
prioridade MENOR que a folha do shadow root e não vence o top. */
|
|
867
|
+
--fx-select-panel-offset: 4px;
|
|
868
|
+
--fx-select-panel-max-height: 260px;
|
|
795
869
|
}
|
|
796
870
|
.trigger {
|
|
797
871
|
display: inline-flex;
|
|
@@ -879,14 +953,15 @@ _FxSelect.styles = css`
|
|
|
879
953
|
}
|
|
880
954
|
.caret { font-size: calc(var(--fx-font-size) - 3px); color: var(--fx-text-muted); pointer-events: none; }
|
|
881
955
|
|
|
882
|
-
/* Painel do dropdown
|
|
956
|
+
/* Painel do dropdown — a POSIÇÃO vertical é definida pelas regras
|
|
957
|
+
[data-placement] abaixo (o JS de ajustarPosicao decide), por isso
|
|
958
|
+
top/bottom não ficam aqui. */
|
|
883
959
|
.panel {
|
|
884
960
|
position: absolute;
|
|
885
|
-
top: calc(100% + 4px);
|
|
886
961
|
left: 0;
|
|
887
962
|
z-index: var(--fx-z-dropdown, 1000);
|
|
888
963
|
width: max(100%, 220px);
|
|
889
|
-
max-height: 260px;
|
|
964
|
+
max-height: var(--fx-select-panel-max-height, 260px);
|
|
890
965
|
overflow-y: auto;
|
|
891
966
|
display: none;
|
|
892
967
|
background: var(--fx-surface-background);
|
|
@@ -894,6 +969,16 @@ _FxSelect.styles = css`
|
|
|
894
969
|
border-radius: var(--fx-radius-md);
|
|
895
970
|
box-shadow: var(--fx-shadow-lg);
|
|
896
971
|
}
|
|
972
|
+
/* Padrão: abre para baixo. */
|
|
973
|
+
:host([open]:not([data-placement='top'])) .panel {
|
|
974
|
+
top: calc(100% + var(--fx-select-panel-offset, 4px));
|
|
975
|
+
}
|
|
976
|
+
/* placement="top" explícito ou auto-flip: abre para cima. */
|
|
977
|
+
:host([open][placement='top']) .panel,
|
|
978
|
+
:host([open][data-placement='top']) .panel {
|
|
979
|
+
top: auto;
|
|
980
|
+
bottom: calc(100% + var(--fx-select-panel-offset, 4px));
|
|
981
|
+
}
|
|
897
982
|
:host([open]) .panel { display: block; }
|
|
898
983
|
.search {
|
|
899
984
|
position: sticky;
|
|
@@ -941,6 +1026,9 @@ _FxSelect.styles = css`
|
|
|
941
1026
|
.clear:hover { color: var(--fx-color-danger); }
|
|
942
1027
|
.clear[hidden] { display: none; }
|
|
943
1028
|
`;
|
|
1029
|
+
_FxSelect.GAP = 4;
|
|
1030
|
+
_FxSelect.MARGEM = 8;
|
|
1031
|
+
_FxSelect.MIN_ALTURA = 80;
|
|
944
1032
|
let FxSelect = _FxSelect;
|
|
945
1033
|
function defineFxSelect() {
|
|
946
1034
|
return defineElement("fx-select", FxSelect);
|
|
@@ -3311,7 +3399,10 @@ const _FxTable = class _FxTable extends FxElement {
|
|
|
3311
3399
|
"loading",
|
|
3312
3400
|
"loading-message",
|
|
3313
3401
|
"sort-field",
|
|
3314
|
-
"sort-order"
|
|
3402
|
+
"sort-order",
|
|
3403
|
+
"rounded",
|
|
3404
|
+
"radius",
|
|
3405
|
+
"no-borders-x"
|
|
3315
3406
|
];
|
|
3316
3407
|
}
|
|
3317
3408
|
get data() {
|
|
@@ -3550,16 +3641,18 @@ const _FxTable = class _FxTable extends FxElement {
|
|
|
3550
3641
|
this._shellKey = shellKey;
|
|
3551
3642
|
this.setTemplate(`
|
|
3552
3643
|
${toolbarHtml}
|
|
3553
|
-
<div class="
|
|
3554
|
-
<div class="
|
|
3555
|
-
<
|
|
3556
|
-
<
|
|
3557
|
-
|
|
3558
|
-
|
|
3644
|
+
<div class="frame${toolbar ? " has-toolbar" : ""}" part="frame">
|
|
3645
|
+
<div class="table-wrap">
|
|
3646
|
+
<div class="scroll">
|
|
3647
|
+
<table part="table">
|
|
3648
|
+
<thead><tr>${headHtml}</tr>${filterRow}</thead>
|
|
3649
|
+
<tbody>${bodyHtml}</tbody>
|
|
3650
|
+
</table>
|
|
3651
|
+
</div>
|
|
3652
|
+
${loadingHtml}
|
|
3559
3653
|
</div>
|
|
3560
|
-
${
|
|
3654
|
+
${pagerHtml}
|
|
3561
3655
|
</div>
|
|
3562
|
-
${pagerHtml}
|
|
3563
3656
|
`);
|
|
3564
3657
|
this.root.querySelectorAll("th.sortable").forEach((th) => {
|
|
3565
3658
|
th.addEventListener("click", () => {
|
|
@@ -3691,14 +3784,61 @@ _FxTable.styles = css`
|
|
|
3691
3784
|
font-size: var(--fx-font-size);
|
|
3692
3785
|
color: var(--fx-text-default);
|
|
3693
3786
|
background: var(--fx-surface-background);
|
|
3787
|
+
/* Raio da moldura (tabela + paginação). O atributo "rounded"
|
|
3788
|
+
sobrescreve este valor e o consumidor também pode sobrescrever
|
|
3789
|
+
por CSS: fx-table { --fx-table-radius: 20px; }. */
|
|
3790
|
+
--fx-table-radius: var(--fx-radius-md);
|
|
3791
|
+
}
|
|
3792
|
+
/* Arredondamento das bordas — "none" deixa tudo reto, como nos demais
|
|
3793
|
+
tokens de radius do design system. "rounded" é o nome atual; "radius"
|
|
3794
|
+
segue aceito como alias para ficar consistente com o <fx-card>. */
|
|
3795
|
+
:host([rounded="none"]),
|
|
3796
|
+
:host([radius="none"]) {
|
|
3797
|
+
--fx-table-radius: var(--fx-radius-none, 0);
|
|
3798
|
+
}
|
|
3799
|
+
:host([rounded="sm"]),
|
|
3800
|
+
:host([radius="sm"]) {
|
|
3801
|
+
--fx-table-radius: var(--fx-radius-sm);
|
|
3802
|
+
}
|
|
3803
|
+
:host([rounded="md"]),
|
|
3804
|
+
:host([radius="md"]) {
|
|
3805
|
+
--fx-table-radius: var(--fx-radius-md);
|
|
3806
|
+
}
|
|
3807
|
+
:host([rounded="lg"]),
|
|
3808
|
+
:host([radius="lg"]) {
|
|
3809
|
+
--fx-table-radius: var(--fx-radius-lg);
|
|
3810
|
+
}
|
|
3811
|
+
/* Moldura: uma única borda envolvendo a tabela E a paginação, para que
|
|
3812
|
+
o pager não fique "solto" fora do contorno da tabela. */
|
|
3813
|
+
.frame {
|
|
3814
|
+
border: 1px solid var(--fx-border-default);
|
|
3815
|
+
border-radius: var(--fx-table-radius);
|
|
3816
|
+
background: var(--fx-surface-background);
|
|
3817
|
+
}
|
|
3818
|
+
/* Com toolbar no topo, quem desenha a borda superior é a própria
|
|
3819
|
+
toolbar — a moldura desenha apenas o contorno restante. */
|
|
3820
|
+
.frame.has-toolbar {
|
|
3821
|
+
border-top: none;
|
|
3822
|
+
}
|
|
3823
|
+
/* "no-borders-x": mantém somente as bordas de topo e de base
|
|
3824
|
+
(tabela encaixada em um layout que já desenha as laterais). */
|
|
3825
|
+
:host([no-borders-x]) .frame,
|
|
3826
|
+
:host([no-borders-x]) .toolbar {
|
|
3827
|
+
border-left: none;
|
|
3828
|
+
border-right: none;
|
|
3694
3829
|
}
|
|
3695
3830
|
.table-wrap {
|
|
3696
3831
|
position: relative;
|
|
3697
3832
|
}
|
|
3698
3833
|
.scroll {
|
|
3699
3834
|
overflow-x: auto;
|
|
3700
|
-
|
|
3701
|
-
|
|
3835
|
+
/* O topo acompanha o raio da moldura; a base fica reta porque o
|
|
3836
|
+
rodapé (.pager) é quem a desenha. */
|
|
3837
|
+
border-radius: var(--fx-table-radius) var(--fx-table-radius) 0 0;
|
|
3838
|
+
}
|
|
3839
|
+
/* Sem paginação não existe rodapé: a moldura fecha embaixo. */
|
|
3840
|
+
:host(:not([pagination])) .scroll {
|
|
3841
|
+
border-radius: var(--fx-table-radius);
|
|
3702
3842
|
}
|
|
3703
3843
|
table {
|
|
3704
3844
|
width: 100%;
|
|
@@ -3785,7 +3925,13 @@ _FxTable.styles = css`
|
|
|
3785
3925
|
align-items: center;
|
|
3786
3926
|
gap: var(--fx-space-sm);
|
|
3787
3927
|
flex-wrap: wrap;
|
|
3788
|
-
|
|
3928
|
+
/* O rodapé é parte da moldura: borda só no topo (separando da
|
|
3929
|
+
tabela) e o mesmo padding horizontal das células. Antes ele
|
|
3930
|
+
ficava fora do contorno, sem borda e sem respiro lateral. */
|
|
3931
|
+
padding: var(--fx-space-sm) var(--fx-space-md);
|
|
3932
|
+
border-top: 1px solid var(--fx-border-default);
|
|
3933
|
+
border-radius: 0 0 var(--fx-table-radius) var(--fx-table-radius);
|
|
3934
|
+
background: var(--fx-surface-background);
|
|
3789
3935
|
}
|
|
3790
3936
|
:host([pagination-position="center"]) .pager {
|
|
3791
3937
|
justify-content: center;
|
|
@@ -3834,15 +3980,27 @@ _FxTable.styles = css`
|
|
|
3834
3980
|
color: #fff;
|
|
3835
3981
|
font-weight: var(--fx-font-weight);
|
|
3836
3982
|
}
|
|
3837
|
-
|
|
3983
|
+
/* O seletor "Por página" só mostra números, então não pode herdar a
|
|
3984
|
+
largura padrão do <fx-select> (200px / 180px em size="sm"), que
|
|
3985
|
+
deixava o rodapé da paginação desproporcional. O limite tem que ser
|
|
3986
|
+
no HOST — apertar só ::part(trigger) não funciona, porque o
|
|
3987
|
+
trigger é width:100% e continua herdando o min-width do host.
|
|
3988
|
+
O painel (dropdown) continua largo (220px) em select.ts. */
|
|
3989
|
+
fx-select.rows-sel {
|
|
3838
3990
|
vertical-align: middle;
|
|
3991
|
+
/* Não deixa o flex do .pager esticar nem esmagar o controle. */
|
|
3992
|
+
flex: none;
|
|
3993
|
+
width: auto;
|
|
3994
|
+
--fx-select-min-width: 56px;
|
|
3995
|
+
--fx-select-min-width-sm: 56px;
|
|
3839
3996
|
}
|
|
3840
|
-
fx-select::part(trigger) {
|
|
3841
|
-
min-width:
|
|
3842
|
-
min-height: var(--fx-size-sm)
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3997
|
+
fx-select.rows-sel::part(trigger) {
|
|
3998
|
+
min-width: 0;
|
|
3999
|
+
min-height: var(--fx-size-sm);
|
|
4000
|
+
/* Padding curto: sobra espaço para o número + caret. */
|
|
4001
|
+
padding: 0 var(--fx-space-xs);
|
|
4002
|
+
border-radius: var(--fx-radius-sm);
|
|
4003
|
+
font-size: calc(var(--fx-font-size) - 2px);
|
|
3846
4004
|
}
|
|
3847
4005
|
.toolbar {
|
|
3848
4006
|
display: flex;
|
|
@@ -3852,7 +4010,7 @@ _FxTable.styles = css`
|
|
|
3852
4010
|
padding: var(--fx-space-sm) var(--fx-space-md);
|
|
3853
4011
|
border: 1px solid var(--fx-border-default);
|
|
3854
4012
|
border-bottom: none;
|
|
3855
|
-
border-radius: var(--fx-radius
|
|
4013
|
+
border-radius: var(--fx-table-radius) var(--fx-table-radius) 0 0;
|
|
3856
4014
|
background: var(--fx-surface-background);
|
|
3857
4015
|
}
|
|
3858
4016
|
.toolbar:empty {
|
|
@@ -3873,7 +4031,7 @@ _FxTable.styles = css`
|
|
|
3873
4031
|
);
|
|
3874
4032
|
backdrop-filter: blur(2px);
|
|
3875
4033
|
z-index: 10;
|
|
3876
|
-
border-radius: var(--fx-radius-
|
|
4034
|
+
border-radius: var(--fx-table-radius) var(--fx-table-radius) 0 0;
|
|
3877
4035
|
}
|
|
3878
4036
|
.tbl-spinner {
|
|
3879
4037
|
width: 32px;
|
|
@@ -5650,6 +5808,24 @@ const _FxCard = class _FxCard extends FxElement {
|
|
|
5650
5808
|
<footer part="footer"><slot name="footer"></slot></footer>
|
|
5651
5809
|
</div>
|
|
5652
5810
|
`);
|
|
5811
|
+
this._syncSlots();
|
|
5812
|
+
for (const name of ["header", "footer"]) {
|
|
5813
|
+
this.root.querySelector(`slot[name="${name}"]`)?.addEventListener("slotchange", () => this._syncSlots());
|
|
5814
|
+
}
|
|
5815
|
+
}
|
|
5816
|
+
/**
|
|
5817
|
+
* Esconde `header`/`footer` quando o respectivo slot não recebeu nenhum nó.
|
|
5818
|
+
* O `<slot>` fica no shadow e os nós no light DOM, então a checagem é feita
|
|
5819
|
+
* via `assignedNodes()` — cobre conteúdo adicionado dinamicamente.
|
|
5820
|
+
*/
|
|
5821
|
+
_syncSlots() {
|
|
5822
|
+
for (const name of ["header", "footer"]) {
|
|
5823
|
+
const slot = this.root.querySelector(`slot[name="${name}"]`);
|
|
5824
|
+
const section = this.root.querySelector(name);
|
|
5825
|
+
if (!slot || !section) continue;
|
|
5826
|
+
const temConteudo = slot.assignedNodes({ flatten: true }).some((n) => n.nodeType === 1 || (n.textContent ?? "").trim() !== "") || name === "header" && Boolean(this.getAttr("heading"));
|
|
5827
|
+
section.toggleAttribute("hidden", !temConteudo);
|
|
5828
|
+
}
|
|
5653
5829
|
}
|
|
5654
5830
|
};
|
|
5655
5831
|
_FxCard.styles = css`
|