diff --git a/src/components/eli/EliTabela/EliTabela.vue b/src/components/eli/EliTabela/EliTabela.vue
index ac519be..f2b3c5f 100644
--- a/src/components/eli/EliTabela/EliTabela.vue
+++ b/src/components/eli/EliTabela/EliTabela.vue
@@ -8,6 +8,7 @@ import { computed, defineComponent, h, onBeforeUnmount, onMounted, PropType, ref
import type { ComponentPublicInstance } from "vue";
import { ArrowDown, ArrowUp, MoreVertical } from "lucide-vue-next";
import { codigosResposta } from "p-respostas";
+import EliTabelaPaginacao from "./EliTabelaPaginacao.vue";
import type { EliTabelaConsulta } from "./types-eli-tabela";
export default defineComponent({
@@ -93,18 +94,6 @@ export default defineComponent({
}
}
- function paginaAnterior() {
- if (paginaAtual.value > 1) {
- paginaAtual.value -= 1;
- }
- }
-
- function proximaPagina() {
- if (paginaAtual.value < totalPaginas.value) {
- paginaAtual.value += 1;
- }
- }
-
function irParaPagina(pagina: number) {
const alvo = Math.min(Math.max(1, pagina), totalPaginas.value);
if (alvo !== paginaAtual.value) {
@@ -112,62 +101,6 @@ export default defineComponent({
}
}
- function rangePaginacao(maximoBotoes = 7) {
- const total = totalPaginas.value;
- const atual = paginaAtual.value;
- const resultado: Array<{ label: string; pagina?: number; ativo?: boolean; disabled?: boolean }> = [];
-
- if (total <= maximoBotoes) {
- for (let pagina = 1; pagina <= total; pagina += 1) {
- resultado.push({
- label: String(pagina),
- pagina,
- ativo: pagina === atual,
- });
- }
- return resultado;
- }
-
- const adicionarPagina = (pagina: number) => {
- resultado.push({
- label: String(pagina),
- pagina,
- ativo: pagina === atual,
- });
- };
-
- const adicionarEllipsis = () => {
- resultado.push({ label: "…", disabled: true });
- };
-
- const visiveis = Math.max(3, maximoBotoes - 2);
- let inicio = Math.max(2, atual - Math.floor(visiveis / 2));
- let fim = inicio + visiveis - 1;
-
- if (fim >= total) {
- fim = total - 1;
- inicio = fim - visiveis + 1;
- }
-
- adicionarPagina(1);
-
- if (inicio > 2) {
- adicionarEllipsis();
- }
-
- for (let pagina = inicio; pagina <= fim; pagina += 1) {
- adicionarPagina(pagina);
- }
-
- if (fim < total - 1) {
- adicionarEllipsis();
- }
-
- adicionarPagina(total);
-
- return resultado;
- }
-
function handleClickFora(evento: MouseEvent) {
if (menuAberto.value === null) {
return;
@@ -475,10 +408,6 @@ export default defineComponent({
);
}
- const podeVoltar = paginaAtual.value > 1;
- const podeAvancar = paginaAtual.value < totalPaginas.value;
- const botoesPaginacao = rangePaginacao();
-
const conteudoTabela = [
h("table", { class: "eli-tabela__table" }, [
h(
@@ -659,72 +588,14 @@ export default defineComponent({
if (totalPaginas.value > 1 && quantidade.value > 0) {
conteudoTabela.push(
- h(
- "nav",
- {
- class: "eli-tabela__paginacao",
- role: "navigation",
- "aria-label": "Paginação de resultados",
+ h(EliTabelaPaginacao, {
+ pagina: paginaAtual.value,
+ totalPaginas: totalPaginas.value,
+ maximoBotoes: props.tabela.maximo_botoes_paginacao,
+ onAlterar: (pagina: number) => {
+ irParaPagina(pagina);
},
- [
- h(
- "button",
- {
- type: "button",
- class: "eli-tabela__pagina-botao",
- onClick: paginaAnterior,
- disabled: !podeVoltar,
- "aria-label": "Página anterior",
- },
- "<<"
- ),
- ...botoesPaginacao.map((item, indice) =>
- item.disabled || !item.pagina
- ? h(
- "span",
- {
- key: `${item.label}-${indice}`,
- class: "eli-tabela__pagina-ellipsis",
- "aria-hidden": "true",
- },
- item.label
- )
- : h(
- "button",
- {
- key: `${item.label}-${indice}`,
- type: "button",
- class: [
- "eli-tabela__pagina-botao",
- item.ativo
- ? "eli-tabela__pagina-botao--ativo"
- : undefined,
- ],
- disabled: item.ativo,
- "aria-current": item.ativo ? "page" : undefined,
- "aria-label": `Ir para página ${item.label}`,
- onClick: () => {
- if (item.pagina) {
- irParaPagina(item.pagina);
- }
- },
- },
- item.label
- )
- ),
- h(
- "button",
- {
- type: "button",
- class: "eli-tabela__pagina-botao",
- onClick: proximaPagina,
- disabled: !podeAvancar,
- "aria-label": "Próxima página",
- },
- ">>"
- ),
- ]
- )
+ })
);
}
@@ -818,66 +689,6 @@ export default defineComponent({
opacity: 0;
}
-.eli-tabela__paginacao {
- display: flex;
- align-items: center;
- justify-content: flex-end;
- gap: 12px;
- margin-top: 12px;
- flex-wrap: wrap;
-}
-
-.eli-tabela__pagina-botao {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- gap: 6px;
- padding: 6px 14px;
- border-radius: 9999px;
- border: 1px solid rgba(15, 23, 42, 0.12);
- background: #ffffff;
- font-size: 0.875rem;
- font-weight: 500;
- color: rgba(15, 23, 42, 0.82);
- cursor: pointer;
- transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
-}
-
-.eli-tabela__pagina-botao:hover,
-.eli-tabela__pagina-botao:focus-visible {
- background-color: rgba(37, 99, 235, 0.08);
- border-color: rgba(37, 99, 235, 0.4);
- color: rgba(37, 99, 235, 0.95);
-}
-
-.eli-tabela__pagina-botao:focus-visible {
- outline: 2px solid rgba(37, 99, 235, 0.45);
- outline-offset: 2px;
-}
-
-.eli-tabela__pagina-botao:disabled {
- cursor: default;
- opacity: 0.5;
- background: rgba(148, 163, 184, 0.08);
- border-color: rgba(148, 163, 184, 0.18);
- color: rgba(71, 85, 105, 0.75);
-}
-
-.eli-tabela__pagina-botao--ativo {
- background: rgba(37, 99, 235, 0.12);
- border-color: rgba(37, 99, 235, 0.4);
- color: rgba(37, 99, 235, 0.95);
-}
-
-.eli-tabela__pagina-ellipsis {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- width: 32px;
- color: rgba(107, 114, 128, 0.85);
- font-size: 0.9rem;
-}
-
.eli-tabela__tr:last-child .eli-tabela__td {
border-bottom: none;
}
diff --git a/src/components/eli/EliTabela/EliTabelaPaginacao.vue b/src/components/eli/EliTabela/EliTabelaPaginacao.vue
new file mode 100644
index 0000000..50a5a87
--- /dev/null
+++ b/src/components/eli/EliTabela/EliTabelaPaginacao.vue
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+
diff --git a/src/components/eli/EliTabela/types-eli-tabela.ts b/src/components/eli/EliTabela/types-eli-tabela.ts
index 49c51bc..f77df38 100644
--- a/src/components/eli/EliTabela/types-eli-tabela.ts
+++ b/src/components/eli/EliTabela/types-eli-tabela.ts
@@ -39,6 +39,7 @@ export type EliTabelaConsulta = {
offSet?: number;
limit?: number;
}) => Promise>>;
+ maximo_botoes_paginacao?: number;
/** Mensagem exibida quando a consulta retorna ok porém sem dados. */
mensagemVazio?: string;
acoes?: EliTabelaAcao[];