feat: suporte para selecionar campos na tabela
This commit is contained in:
parent
7dc071373a
commit
0886fd5c3e
16 changed files with 5867 additions and 4684 deletions
9715
dist/eli-vue.es.js
vendored
9715
dist/eli-vue.es.js
vendored
File diff suppressed because one or more lines are too long
99
dist/eli-vue.umd.js
vendored
99
dist/eli-vue.umd.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -11,6 +11,11 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
type: PropType<tipoEliTabelaConsulta<any>>;
|
type: PropType<tipoEliTabelaConsulta<any>>;
|
||||||
required: true;
|
required: true;
|
||||||
};
|
};
|
||||||
|
/** Array de itens selecionados (v-model:selecionados) */
|
||||||
|
selecionados: {
|
||||||
|
type: PropType<unknown[]>;
|
||||||
|
default: () => never[];
|
||||||
|
};
|
||||||
}>, {
|
}>, {
|
||||||
isDev: boolean;
|
isDev: boolean;
|
||||||
tabela: import("vue").ComputedRef<tipoEliTabelaConsulta<any>>;
|
tabela: import("vue").ComputedRef<tipoEliTabelaConsulta<any>>;
|
||||||
|
|
@ -77,6 +82,12 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
temColunasInvisiveis: import("vue").ComputedRef<boolean>;
|
temColunasInvisiveis: import("vue").ComputedRef<boolean>;
|
||||||
colunasInvisiveisEfetivas: import("vue").ComputedRef<tipoEliColuna<any>[]>;
|
colunasInvisiveisEfetivas: import("vue").ComputedRef<tipoEliColuna<any>[]>;
|
||||||
linhasExpandidas: import("vue").Ref<Record<number, boolean>, Record<number, boolean>>;
|
linhasExpandidas: import("vue").Ref<Record<number, boolean>, Record<number, boolean>>;
|
||||||
|
mostrarSelecao: import("vue").ComputedRef<boolean>;
|
||||||
|
isSelecionado: (linha: unknown) => boolean;
|
||||||
|
alternarSelecao: (linha: unknown) => void;
|
||||||
|
todosSelecionados: import("vue").ComputedRef<boolean>;
|
||||||
|
algunsSelecionados: import("vue").ComputedRef<boolean>;
|
||||||
|
alternarSelecaoTodos: (forcarMarcar?: boolean) => void;
|
||||||
abrirModalColunas: () => void;
|
abrirModalColunas: () => void;
|
||||||
abrirModalFiltro: () => void;
|
abrirModalFiltro: () => void;
|
||||||
fecharModalColunas: () => void;
|
fecharModalColunas: () => void;
|
||||||
|
|
@ -129,13 +140,22 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
top: number;
|
top: number;
|
||||||
left: number;
|
left: number;
|
||||||
}>;
|
}>;
|
||||||
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:selecionados"[], "update:selecionados", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
||||||
/** Configuração principal da tabela (colunas, consulta e ações) */
|
/** Configuração principal da tabela (colunas, consulta e ações) */
|
||||||
tabela: {
|
tabela: {
|
||||||
type: PropType<tipoEliTabelaConsulta<any>>;
|
type: PropType<tipoEliTabelaConsulta<any>>;
|
||||||
required: true;
|
required: true;
|
||||||
};
|
};
|
||||||
}>> & Readonly<{}>, {}, {}, {
|
/** Array de itens selecionados (v-model:selecionados) */
|
||||||
|
selecionados: {
|
||||||
|
type: PropType<unknown[]>;
|
||||||
|
default: () => never[];
|
||||||
|
};
|
||||||
|
}>> & Readonly<{
|
||||||
|
"onUpdate:selecionados"?: ((...args: any[]) => any) | undefined;
|
||||||
|
}>, {
|
||||||
|
selecionados: unknown[];
|
||||||
|
}, {}, {
|
||||||
EliTabelaCabecalho: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
EliTabelaCabecalho: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
||||||
exibirBusca: {
|
exibirBusca: {
|
||||||
type: BooleanConstructor;
|
type: BooleanConstructor;
|
||||||
|
|
@ -366,6 +386,18 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
type: PropType<"asc" | "desc">;
|
type: PropType<"asc" | "desc">;
|
||||||
required: true;
|
required: true;
|
||||||
};
|
};
|
||||||
|
mostrarSelecao: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
todosSelecionados: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
algunsSelecionados: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
}>, {
|
}>, {
|
||||||
ArrowUp: import("@lucide/vue").LucideIcon;
|
ArrowUp: import("@lucide/vue").LucideIcon;
|
||||||
ArrowDown: import("@lucide/vue").LucideIcon;
|
ArrowDown: import("@lucide/vue").LucideIcon;
|
||||||
|
|
@ -373,6 +405,7 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
emitAlternarOrdenacao: (chave: string) => void;
|
emitAlternarOrdenacao: (chave: string) => void;
|
||||||
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||||
alternarOrdenacao(chave: string): boolean;
|
alternarOrdenacao(chave: string): boolean;
|
||||||
|
"alternar-selecao-todos": () => true;
|
||||||
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
||||||
colunas: {
|
colunas: {
|
||||||
type: PropType<Array<tipoEliColuna<any>>>;
|
type: PropType<Array<tipoEliColuna<any>>>;
|
||||||
|
|
@ -394,10 +427,26 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
type: PropType<"asc" | "desc">;
|
type: PropType<"asc" | "desc">;
|
||||||
required: true;
|
required: true;
|
||||||
};
|
};
|
||||||
|
mostrarSelecao: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
todosSelecionados: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
algunsSelecionados: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
}>> & Readonly<{
|
}>> & Readonly<{
|
||||||
|
"onAlternar-selecao-todos"?: (() => any) | undefined;
|
||||||
onAlternarOrdenacao?: ((chave: string) => any) | undefined;
|
onAlternarOrdenacao?: ((chave: string) => any) | undefined;
|
||||||
}>, {
|
}>, {
|
||||||
|
mostrarSelecao: boolean;
|
||||||
colunaOrdenacao: string | null;
|
colunaOrdenacao: string | null;
|
||||||
|
todosSelecionados: boolean;
|
||||||
|
algunsSelecionados: boolean;
|
||||||
}, {}, {
|
}, {}, {
|
||||||
ArrowUp: import("@lucide/vue").LucideIcon;
|
ArrowUp: import("@lucide/vue").LucideIcon;
|
||||||
ArrowDown: import("@lucide/vue").LucideIcon;
|
ArrowDown: import("@lucide/vue").LucideIcon;
|
||||||
|
|
@ -443,6 +492,18 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
type: PropType<(indice: number) => void>;
|
type: PropType<(indice: number) => void>;
|
||||||
required: true;
|
required: true;
|
||||||
};
|
};
|
||||||
|
mostrarSelecao: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
isSelecionado: {
|
||||||
|
type: PropType<(linha: unknown) => boolean>;
|
||||||
|
required: true;
|
||||||
|
};
|
||||||
|
alternarSelecao: {
|
||||||
|
type: PropType<(linha: unknown) => void>;
|
||||||
|
required: true;
|
||||||
|
};
|
||||||
}>, {
|
}>, {
|
||||||
ChevronRight: import("@lucide/vue").LucideIcon;
|
ChevronRight: import("@lucide/vue").LucideIcon;
|
||||||
ChevronDown: import("@lucide/vue").LucideIcon;
|
ChevronDown: import("@lucide/vue").LucideIcon;
|
||||||
|
|
@ -487,7 +548,21 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
type: PropType<(indice: number) => void>;
|
type: PropType<(indice: number) => void>;
|
||||||
required: true;
|
required: true;
|
||||||
};
|
};
|
||||||
}>> & Readonly<{}>, {}, {}, {
|
mostrarSelecao: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
isSelecionado: {
|
||||||
|
type: PropType<(linha: unknown) => boolean>;
|
||||||
|
required: true;
|
||||||
|
};
|
||||||
|
alternarSelecao: {
|
||||||
|
type: PropType<(linha: unknown) => void>;
|
||||||
|
required: true;
|
||||||
|
};
|
||||||
|
}>> & Readonly<{}>, {
|
||||||
|
mostrarSelecao: boolean;
|
||||||
|
}, {}, {
|
||||||
EliTabelaCelula: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
EliTabelaCelula: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
||||||
celula: {
|
celula: {
|
||||||
type: PropType<import("./types-eli-tabela").tipoComponenteCelula>;
|
type: PropType<import("./types-eli-tabela").tipoComponenteCelula>;
|
||||||
|
|
@ -828,11 +903,13 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
}>, {
|
}>, {
|
||||||
visiveisLocal: import("vue").Ref<string[], string[]>;
|
visiveisLocal: import("vue").Ref<string[], string[]>;
|
||||||
invisiveisLocal: import("vue").Ref<string[], string[]>;
|
invisiveisLocal: import("vue").Ref<string[], string[]>;
|
||||||
|
itemSendoArrastado: import("vue").Ref<string | null, string | null>;
|
||||||
emitFechar: () => void;
|
emitFechar: () => void;
|
||||||
emitSalvar: () => void;
|
emitSalvar: () => void;
|
||||||
onDragStart: (e: DragEvent, rotulo: string, origem: "visiveis" | "invisiveis", index: number) => void;
|
onDragStart: (e: DragEvent, rotulo: string) => void;
|
||||||
onDropItem: (e: DragEvent, destino: "visiveis" | "invisiveis", index: number) => void;
|
onDragEnd: () => void;
|
||||||
onDropLista: (e: DragEvent, destino: "visiveis" | "invisiveis", _index: number | null) => void;
|
onDragOverItem: (alvoRotulo: string, destino: "visiveis" | "invisiveis") => void;
|
||||||
|
onDragOverLista: (destino: "visiveis" | "invisiveis") => void;
|
||||||
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||||
fechar(): true;
|
fechar(): true;
|
||||||
salvar(_config: EliTabelaColunasConfig): true;
|
salvar(_config: EliTabelaColunasConfig): true;
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,18 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
type: PropType<(indice: number) => void>;
|
type: PropType<(indice: number) => void>;
|
||||||
required: true;
|
required: true;
|
||||||
};
|
};
|
||||||
|
mostrarSelecao: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
isSelecionado: {
|
||||||
|
type: PropType<(linha: unknown) => boolean>;
|
||||||
|
required: true;
|
||||||
|
};
|
||||||
|
alternarSelecao: {
|
||||||
|
type: PropType<(linha: unknown) => void>;
|
||||||
|
required: true;
|
||||||
|
};
|
||||||
}>, {
|
}>, {
|
||||||
ChevronRight: import("@lucide/vue").LucideIcon;
|
ChevronRight: import("@lucide/vue").LucideIcon;
|
||||||
ChevronDown: import("@lucide/vue").LucideIcon;
|
ChevronDown: import("@lucide/vue").LucideIcon;
|
||||||
|
|
@ -87,7 +99,21 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
type: PropType<(indice: number) => void>;
|
type: PropType<(indice: number) => void>;
|
||||||
required: true;
|
required: true;
|
||||||
};
|
};
|
||||||
}>> & Readonly<{}>, {}, {}, {
|
mostrarSelecao: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
isSelecionado: {
|
||||||
|
type: PropType<(linha: unknown) => boolean>;
|
||||||
|
required: true;
|
||||||
|
};
|
||||||
|
alternarSelecao: {
|
||||||
|
type: PropType<(linha: unknown) => void>;
|
||||||
|
required: true;
|
||||||
|
};
|
||||||
|
}>> & Readonly<{}>, {
|
||||||
|
mostrarSelecao: boolean;
|
||||||
|
}, {}, {
|
||||||
EliTabelaCelula: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
EliTabelaCelula: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
||||||
celula: {
|
celula: {
|
||||||
type: PropType<import("./types-eli-tabela").tipoComponenteCelula>;
|
type: PropType<import("./types-eli-tabela").tipoComponenteCelula>;
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,18 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
type: PropType<"asc" | "desc">;
|
type: PropType<"asc" | "desc">;
|
||||||
required: true;
|
required: true;
|
||||||
};
|
};
|
||||||
|
mostrarSelecao: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
todosSelecionados: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
algunsSelecionados: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
}>, {
|
}>, {
|
||||||
ArrowUp: import("@lucide/vue").LucideIcon;
|
ArrowUp: import("@lucide/vue").LucideIcon;
|
||||||
ArrowDown: import("@lucide/vue").LucideIcon;
|
ArrowDown: import("@lucide/vue").LucideIcon;
|
||||||
|
|
@ -30,6 +42,7 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
emitAlternarOrdenacao: (chave: string) => void;
|
emitAlternarOrdenacao: (chave: string) => void;
|
||||||
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||||
alternarOrdenacao(chave: string): boolean;
|
alternarOrdenacao(chave: string): boolean;
|
||||||
|
"alternar-selecao-todos": () => true;
|
||||||
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
||||||
colunas: {
|
colunas: {
|
||||||
type: PropType<Array<tipoEliColuna<any>>>;
|
type: PropType<Array<tipoEliColuna<any>>>;
|
||||||
|
|
@ -51,10 +64,26 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
type: PropType<"asc" | "desc">;
|
type: PropType<"asc" | "desc">;
|
||||||
required: true;
|
required: true;
|
||||||
};
|
};
|
||||||
|
mostrarSelecao: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
todosSelecionados: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
algunsSelecionados: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
}>> & Readonly<{
|
}>> & Readonly<{
|
||||||
|
"onAlternar-selecao-todos"?: (() => any) | undefined;
|
||||||
onAlternarOrdenacao?: ((chave: string) => any) | undefined;
|
onAlternarOrdenacao?: ((chave: string) => any) | undefined;
|
||||||
}>, {
|
}>, {
|
||||||
|
mostrarSelecao: boolean;
|
||||||
colunaOrdenacao: string | null;
|
colunaOrdenacao: string | null;
|
||||||
|
todosSelecionados: boolean;
|
||||||
|
algunsSelecionados: boolean;
|
||||||
}, {}, {
|
}, {}, {
|
||||||
ArrowUp: import("@lucide/vue").LucideIcon;
|
ArrowUp: import("@lucide/vue").LucideIcon;
|
||||||
ArrowDown: import("@lucide/vue").LucideIcon;
|
ArrowDown: import("@lucide/vue").LucideIcon;
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,13 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
||||||
}>, {
|
}>, {
|
||||||
visiveisLocal: import("vue").Ref<string[], string[]>;
|
visiveisLocal: import("vue").Ref<string[], string[]>;
|
||||||
invisiveisLocal: import("vue").Ref<string[], string[]>;
|
invisiveisLocal: import("vue").Ref<string[], string[]>;
|
||||||
|
itemSendoArrastado: import("vue").Ref<string | null, string | null>;
|
||||||
emitFechar: () => void;
|
emitFechar: () => void;
|
||||||
emitSalvar: () => void;
|
emitSalvar: () => void;
|
||||||
onDragStart: (e: DragEvent, rotulo: string, origem: OrigemLista, index: number) => void;
|
onDragStart: (e: DragEvent, rotulo: string) => void;
|
||||||
onDropItem: (e: DragEvent, destino: OrigemLista, index: number) => void;
|
onDragEnd: () => void;
|
||||||
onDropLista: (e: DragEvent, destino: OrigemLista, _index: number | null) => void;
|
onDragOverItem: (alvoRotulo: string, destino: OrigemLista) => void;
|
||||||
|
onDragOverLista: (destino: OrigemLista) => void;
|
||||||
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||||
fechar(): true;
|
fechar(): true;
|
||||||
salvar(_config: EliTabelaColunasConfig): true;
|
salvar(_config: EliTabelaColunasConfig): true;
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,10 @@ export type tipoEliTabelaConsulta<T> = {
|
||||||
nome: string;
|
nome: string;
|
||||||
/** Indica se a caixa de busca deve ser exibida acima da tabela. */
|
/** Indica se a caixa de busca deve ser exibida acima da tabela. */
|
||||||
mostrarCaixaDeBusca?: boolean;
|
mostrarCaixaDeBusca?: boolean;
|
||||||
|
/** Habilita seleção múltipla (checkboxes) nas linhas da tabela. */
|
||||||
|
mostrar_selecao?: boolean;
|
||||||
|
/** Chave (ex: "id") para identificar unicamente a linha nas seleções entre páginas. */
|
||||||
|
chave_selecao?: keyof T;
|
||||||
/** Lista de colunas da tabela. */
|
/** Lista de colunas da tabela. */
|
||||||
colunas: tipoEliColuna<T>[];
|
colunas: tipoEliColuna<T>[];
|
||||||
/** Quantidade de registros solicitados por consulta (padrão `10`). */
|
/** Quantidade de registros solicitados por consulta (padrão `10`). */
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "eli-vue",
|
"name": "eli-vue",
|
||||||
"version": "0.1.128",
|
"version": "0.1.144",
|
||||||
"private": false,
|
"private": false,
|
||||||
"main": "./dist/eli-vue.umd.js",
|
"main": "./dist/eli-vue.umd.js",
|
||||||
"module": "./dist/eli-vue.es.js",
|
"module": "./dist/eli-vue.es.js",
|
||||||
|
|
|
||||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
|
|
@ -19,7 +19,7 @@ importers:
|
||||||
version: 1.11.19
|
version: 1.11.19
|
||||||
p-comuns:
|
p-comuns:
|
||||||
specifier: git+https://git2.idz.one/publico/_comuns.git
|
specifier: git+https://git2.idz.one/publico/_comuns.git
|
||||||
version: git+https://git2.idz.one/publico/_comuns.git#64ddd6ad8af5e09a81d247fb1b23c2b05731d321(cross-fetch@4.1.0)(dayjs@1.11.19)(uuid@13.0.0)(zod@4.3.6)
|
version: git+https://git2.idz.one/publico/_comuns.git#64ddd6ad8af5e09a81d247fb1b23c2b05731d321(cross-fetch@4.1.0)(dayjs@1.11.19)(uuid@13.0.0)(zod@4.4.3)
|
||||||
p-respostas:
|
p-respostas:
|
||||||
specifier: git+https://git2.idz.one/publico/_respostas.git
|
specifier: git+https://git2.idz.one/publico/_respostas.git
|
||||||
version: git+https://git2.idz.one/publico/_respostas.git#8c24d790ace7255404745dcbdf12c5396e8b9843(cross-fetch@4.1.0)(dayjs@1.11.19)(uuid@13.0.0)
|
version: git+https://git2.idz.one/publico/_respostas.git#8c24d790ace7255404745dcbdf12c5396e8b9843(cross-fetch@4.1.0)(dayjs@1.11.19)(uuid@13.0.0)
|
||||||
|
|
@ -27,8 +27,8 @@ importers:
|
||||||
specifier: ^13.0.0
|
specifier: ^13.0.0
|
||||||
version: 13.0.0
|
version: 13.0.0
|
||||||
zod:
|
zod:
|
||||||
specifier: 4.3.6
|
specifier: 4.4.3
|
||||||
version: 4.3.6
|
version: 4.4.3
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@biomejs/biome':
|
'@biomejs/biome':
|
||||||
specifier: 2.4.12
|
specifier: 2.4.12
|
||||||
|
|
@ -837,8 +837,8 @@ packages:
|
||||||
zod@4.1.4:
|
zod@4.1.4:
|
||||||
resolution: {integrity: sha512-2YqJuWkU6IIK9qcE4k1lLLhyZ6zFw7XVRdQGpV97jEIZwTrscUw+DY31Xczd8nwaoksyJUIxCojZXwckJovWxA==}
|
resolution: {integrity: sha512-2YqJuWkU6IIK9qcE4k1lLLhyZ6zFw7XVRdQGpV97jEIZwTrscUw+DY31Xczd8nwaoksyJUIxCojZXwckJovWxA==}
|
||||||
|
|
||||||
zod@4.3.6:
|
zod@4.4.3:
|
||||||
resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==}
|
resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==}
|
||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
|
|
||||||
|
|
@ -1315,12 +1315,12 @@ snapshots:
|
||||||
uuid: 13.0.0
|
uuid: 13.0.0
|
||||||
zod: 4.1.4
|
zod: 4.1.4
|
||||||
|
|
||||||
p-comuns@git+https://git2.idz.one/publico/_comuns.git#64ddd6ad8af5e09a81d247fb1b23c2b05731d321(cross-fetch@4.1.0)(dayjs@1.11.19)(uuid@13.0.0)(zod@4.3.6):
|
p-comuns@git+https://git2.idz.one/publico/_comuns.git#64ddd6ad8af5e09a81d247fb1b23c2b05731d321(cross-fetch@4.1.0)(dayjs@1.11.19)(uuid@13.0.0)(zod@4.4.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
cross-fetch: 4.1.0
|
cross-fetch: 4.1.0
|
||||||
dayjs: 1.11.19
|
dayjs: 1.11.19
|
||||||
uuid: 13.0.0
|
uuid: 13.0.0
|
||||||
zod: 4.3.6
|
zod: 4.4.3
|
||||||
|
|
||||||
p-respostas@git+https://git2.idz.one/publico/_respostas.git#8c24d790ace7255404745dcbdf12c5396e8b9843(cross-fetch@4.1.0)(dayjs@1.11.19)(uuid@13.0.0):
|
p-respostas@git+https://git2.idz.one/publico/_respostas.git#8c24d790ace7255404745dcbdf12c5396e8b9843(cross-fetch@4.1.0)(dayjs@1.11.19)(uuid@13.0.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -1466,4 +1466,4 @@ snapshots:
|
||||||
|
|
||||||
zod@4.1.4: {}
|
zod@4.1.4: {}
|
||||||
|
|
||||||
zod@4.3.6: {}
|
zod@4.4.3: {}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,20 @@
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Corrige o vazamento (pontas quadradas) do fundo dos th/td nas bordas arredondadas da tabela */
|
||||||
|
.eli-tabela__table thead tr:first-child th:first-child {
|
||||||
|
border-top-left-radius: 11px;
|
||||||
|
}
|
||||||
|
.eli-tabela__table thead tr:first-child th:last-child {
|
||||||
|
border-top-right-radius: 11px;
|
||||||
|
}
|
||||||
|
.eli-tabela__table tbody tr:last-child td:first-child {
|
||||||
|
border-bottom-left-radius: 11px;
|
||||||
|
}
|
||||||
|
.eli-tabela__table tbody tr:last-child td:last-child {
|
||||||
|
border-bottom-right-radius: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
.eli-tabela__tbody {
|
.eli-tabela__tbody {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +80,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.eli-tabela__th-botao--ativo {
|
.eli-tabela__th-botao--ativo {
|
||||||
color: rgba(37, 99, 235, 0.95);
|
color: rgba(15, 23, 42, 0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
.eli-tabela__th-texto {
|
.eli-tabela__th-texto {
|
||||||
|
|
@ -395,3 +409,70 @@
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* =========================================
|
||||||
|
* Seleção (Checkboxes)
|
||||||
|
* ========================================= */
|
||||||
|
.eli-tabela__th--selecao,
|
||||||
|
.eli-tabela__td--selecao {
|
||||||
|
width: 48px;
|
||||||
|
min-width: 48px;
|
||||||
|
max-width: 48px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0 8px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eli-tabela__checkbox {
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 2px solid rgba(0, 0, 0, 0.54);
|
||||||
|
border-radius: 2px;
|
||||||
|
margin: 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
position: relative;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
background-color: transparent;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eli-tabela__checkbox:hover {
|
||||||
|
border-color: rgba(0, 0, 0, 0.87);
|
||||||
|
}
|
||||||
|
|
||||||
|
.eli-tabela__checkbox:checked,
|
||||||
|
.eli-tabela__checkbox:indeterminate {
|
||||||
|
background-color: #1976d2;
|
||||||
|
border-color: #1976d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eli-tabela__checkbox:checked::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 4px;
|
||||||
|
width: 4px;
|
||||||
|
height: 9px;
|
||||||
|
border: solid white;
|
||||||
|
border-width: 0 2px 2px 0;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.eli-tabela__checkbox:indeterminate::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
left: 2px;
|
||||||
|
width: 8px;
|
||||||
|
height: 2px;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eli-tabela__checkbox:focus-visible {
|
||||||
|
box-shadow: 0 0 0 2px rgba(25, 118, 210, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,11 @@
|
||||||
:temColunasInvisiveis="temColunasInvisiveis"
|
:temColunasInvisiveis="temColunasInvisiveis"
|
||||||
:colunaOrdenacao="colunaOrdenacao"
|
:colunaOrdenacao="colunaOrdenacao"
|
||||||
:direcaoOrdenacao="direcaoOrdenacao"
|
:direcaoOrdenacao="direcaoOrdenacao"
|
||||||
|
:mostrarSelecao="mostrarSelecao"
|
||||||
|
:todosSelecionados="todosSelecionados"
|
||||||
|
:algunsSelecionados="algunsSelecionados"
|
||||||
@alternar-ordenacao="alternarOrdenacao"
|
@alternar-ordenacao="alternarOrdenacao"
|
||||||
|
@alternar-selecao-todos="alternarSelecaoTodos"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<tbody v-if="carregando || Boolean(erro) || !linhas.length">
|
<tbody v-if="carregando || Boolean(erro) || !linhas.length">
|
||||||
|
|
@ -73,6 +77,9 @@
|
||||||
:possuiAcoes="possuiAcoes"
|
:possuiAcoes="possuiAcoes"
|
||||||
:toggleMenu="toggleMenu"
|
:toggleMenu="toggleMenu"
|
||||||
:alternarLinhaExpandida="alternarLinhaExpandida"
|
:alternarLinhaExpandida="alternarLinhaExpandida"
|
||||||
|
:mostrarSelecao="mostrarSelecao"
|
||||||
|
:isSelecionado="isSelecionado"
|
||||||
|
:alternarSelecao="alternarSelecao"
|
||||||
/>
|
/>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
@ -165,8 +172,14 @@ export default defineComponent({
|
||||||
type: Object as PropType<tipoEliTabelaConsulta<any>>,
|
type: Object as PropType<tipoEliTabelaConsulta<any>>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
/** Array de itens selecionados (v-model:selecionados) */
|
||||||
|
selecionados: {
|
||||||
|
type: Array as PropType<unknown[]>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
emits: ["update:selecionados"],
|
||||||
|
setup(props, { emit }) {
|
||||||
/** Flag para habilitar elementos de debug */
|
/** Flag para habilitar elementos de debug */
|
||||||
const isDev = import.meta.env.DEV
|
const isDev = import.meta.env.DEV
|
||||||
/** Estados de carregamento/erro e dados retornados */
|
/** Estados de carregamento/erro e dados retornados */
|
||||||
|
|
@ -258,6 +271,84 @@ export default defineComponent({
|
||||||
/** Alias reativo da prop tabela */
|
/** Alias reativo da prop tabela */
|
||||||
const tabela = computed(() => props.tabela)
|
const tabela = computed(() => props.tabela)
|
||||||
|
|
||||||
|
/** Seleção Múltipla */
|
||||||
|
const mostrarSelecao = computed(() => Boolean(props.tabela.mostrar_selecao))
|
||||||
|
const chaveSelecao = computed(
|
||||||
|
() => props.tabela.chave_selecao as string | undefined,
|
||||||
|
)
|
||||||
|
|
||||||
|
function obterChaveLinha(linha: unknown): unknown {
|
||||||
|
if (chaveSelecao.value && linha && typeof linha === "object") {
|
||||||
|
return (linha as Record<string, unknown>)[chaveSelecao.value]
|
||||||
|
}
|
||||||
|
return linha
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSelecionado(linha: unknown): boolean {
|
||||||
|
const chave = obterChaveLinha(linha)
|
||||||
|
if (chaveSelecao.value) {
|
||||||
|
return props.selecionados.some((s) => obterChaveLinha(s) === chave)
|
||||||
|
}
|
||||||
|
return props.selecionados.includes(linha)
|
||||||
|
}
|
||||||
|
|
||||||
|
function alternarSelecao(linha: unknown) {
|
||||||
|
const atual = [...props.selecionados]
|
||||||
|
const chave = obterChaveLinha(linha)
|
||||||
|
|
||||||
|
let index = -1
|
||||||
|
if (chaveSelecao.value) {
|
||||||
|
index = atual.findIndex((s) => obterChaveLinha(s) === chave)
|
||||||
|
} else {
|
||||||
|
index = atual.indexOf(linha)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index === -1) {
|
||||||
|
atual.push(linha)
|
||||||
|
} else {
|
||||||
|
atual.splice(index, 1)
|
||||||
|
}
|
||||||
|
emit("update:selecionados", atual)
|
||||||
|
}
|
||||||
|
|
||||||
|
const todosSelecionados = computed(() => {
|
||||||
|
if (linhasPaginadas.value.length === 0) return false
|
||||||
|
return linhasPaginadas.value.every((linha) => isSelecionado(linha))
|
||||||
|
})
|
||||||
|
|
||||||
|
const algunsSelecionados = computed(() => {
|
||||||
|
if (linhasPaginadas.value.length === 0) return false
|
||||||
|
return (
|
||||||
|
linhasPaginadas.value.some((linha) => isSelecionado(linha)) &&
|
||||||
|
!todosSelecionados.value
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
function alternarSelecaoTodos(forcarMarcar?: boolean) {
|
||||||
|
const marcarTodos = forcarMarcar ?? !todosSelecionados.value
|
||||||
|
let atual = [...props.selecionados]
|
||||||
|
|
||||||
|
if (marcarTodos) {
|
||||||
|
// Adiciona os que faltam na página atual
|
||||||
|
for (const linha of linhasPaginadas.value) {
|
||||||
|
if (!isSelecionado(linha)) {
|
||||||
|
atual.push(linha)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Remove os da página atual
|
||||||
|
const chavesPagina = linhasPaginadas.value.map(obterChaveLinha)
|
||||||
|
if (chaveSelecao.value) {
|
||||||
|
atual = atual.filter(
|
||||||
|
(s) => !chavesPagina.includes(obterChaveLinha(s)),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
atual = atual.filter((s) => !chavesPagina.includes(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit("update:selecionados", atual)
|
||||||
|
}
|
||||||
|
|
||||||
/** Exibição da busca e ações do cabeçalho */
|
/** Exibição da busca e ações do cabeçalho */
|
||||||
const exibirBusca = computed(() =>
|
const exibirBusca = computed(() =>
|
||||||
Boolean(props.tabela.mostrarCaixaDeBusca),
|
Boolean(props.tabela.mostrarCaixaDeBusca),
|
||||||
|
|
@ -859,6 +950,14 @@ export default defineComponent({
|
||||||
colunasInvisiveisEfetivas,
|
colunasInvisiveisEfetivas,
|
||||||
linhasExpandidas,
|
linhasExpandidas,
|
||||||
|
|
||||||
|
// selecao
|
||||||
|
mostrarSelecao,
|
||||||
|
isSelecionado,
|
||||||
|
alternarSelecao,
|
||||||
|
todosSelecionados,
|
||||||
|
algunsSelecionados,
|
||||||
|
alternarSelecaoTodos,
|
||||||
|
|
||||||
abrirModalColunas,
|
abrirModalColunas,
|
||||||
abrirModalFiltro,
|
abrirModalFiltro,
|
||||||
fecharModalColunas,
|
fecharModalColunas,
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,17 @@
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
<td v-if="mostrarSelecao" class="eli-tabela__td eli-tabela__td--selecao" :key="`td-${i}-selecao`">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="eli-tabela__checkbox"
|
||||||
|
:checked="isSelecionado(linha)"
|
||||||
|
@change="alternarSelecao(linha)"
|
||||||
|
@click.stop
|
||||||
|
aria-label="Selecionar linha"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
|
||||||
<td
|
<td
|
||||||
v-for="(coluna, j) in colunas"
|
v-for="(coluna, j) in colunas"
|
||||||
:key="`td-${i}-${j}`"
|
:key="`td-${i}-${j}`"
|
||||||
|
|
@ -63,7 +74,7 @@
|
||||||
>
|
>
|
||||||
<td
|
<td
|
||||||
class="eli-tabela__td eli-tabela__td--detalhes"
|
class="eli-tabela__td eli-tabela__td--detalhes"
|
||||||
:colspan="(temColunasInvisiveis ? 1 : 0) + colunas.length + (temAcoes ? 1 : 0)"
|
:colspan="(temColunasInvisiveis ? 1 : 0) + (mostrarSelecao ? 1 : 0) + colunas.length + (temAcoes ? 1 : 0)"
|
||||||
>
|
>
|
||||||
<EliTabelaDetalhesLinha :linha="linha" :colunasInvisiveis="colunasInvisiveis" />
|
<EliTabelaDetalhesLinha :linha="linha" :colunasInvisiveis="colunasInvisiveis" />
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -131,6 +142,18 @@ export default defineComponent({
|
||||||
type: Function as PropType<(indice: number) => void>,
|
type: Function as PropType<(indice: number) => void>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
mostrarSelecao: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
isSelecionado: {
|
||||||
|
type: Function as PropType<(linha: unknown) => boolean>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
alternarSelecao: {
|
||||||
|
type: Function as PropType<(linha: unknown) => void>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,17 @@
|
||||||
<tr class="eli-tabela__tr eli-tabela__tr--header">
|
<tr class="eli-tabela__tr eli-tabela__tr--header">
|
||||||
<th v-if="temColunasInvisiveis" class="eli-tabela__th eli-tabela__th--expander" scope="col"></th>
|
<th v-if="temColunasInvisiveis" class="eli-tabela__th eli-tabela__th--expander" scope="col"></th>
|
||||||
|
|
||||||
|
<th v-if="mostrarSelecao" class="eli-tabela__th eli-tabela__th--selecao" scope="col">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="eli-tabela__checkbox"
|
||||||
|
:checked="todosSelecionados"
|
||||||
|
:indeterminate="algunsSelecionados"
|
||||||
|
@change="$emit('alternar-selecao-todos')"
|
||||||
|
aria-label="Selecionar todos os itens da página"
|
||||||
|
/>
|
||||||
|
</th>
|
||||||
|
|
||||||
<th
|
<th
|
||||||
v-for="(coluna, idx) in colunas"
|
v-for="(coluna, idx) in colunas"
|
||||||
:key="`th-${idx}`"
|
:key="`th-${idx}`"
|
||||||
|
|
@ -78,11 +89,24 @@ export default defineComponent({
|
||||||
type: String as PropType<"asc" | "desc">,
|
type: String as PropType<"asc" | "desc">,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
mostrarSelecao: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
todosSelecionados: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
algunsSelecionados: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
emits: {
|
emits: {
|
||||||
alternarOrdenacao(chave: string) {
|
alternarOrdenacao(chave: string) {
|
||||||
return typeof chave === "string" && chave.length > 0
|
return typeof chave === "string" && chave.length > 0
|
||||||
},
|
},
|
||||||
|
"alternar-selecao-todos": () => true,
|
||||||
},
|
},
|
||||||
setup(_props, { emit }) {
|
setup(_props, { emit }) {
|
||||||
// biome-ignore lint/suspicious/noExplicitAny: dynamic column
|
// biome-ignore lint/suspicious/noExplicitAny: dynamic column
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,88 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="aberto" class="eli-tabela-modal-colunas__overlay" role="presentation" @click.self="emitFechar">
|
<Teleport to="body">
|
||||||
<div
|
<div v-if="aberto" class="eli-tabela-modal-colunas__overlay" role="presentation" @click.self="emitFechar">
|
||||||
class="eli-tabela-modal-colunas__modal"
|
<div
|
||||||
role="dialog"
|
class="eli-tabela-modal-colunas__modal"
|
||||||
aria-modal="true"
|
role="dialog"
|
||||||
aria-label="Configurar colunas"
|
aria-modal="true"
|
||||||
>
|
aria-label="Configurar colunas"
|
||||||
<header class="eli-tabela-modal-colunas__header">
|
>
|
||||||
<h3 class="eli-tabela-modal-colunas__titulo">Colunas</h3>
|
<header class="eli-tabela-modal-colunas__header">
|
||||||
<button type="button" class="eli-tabela-modal-colunas__fechar" aria-label="Fechar" @click="emitFechar">
|
<h3 class="eli-tabela-modal-colunas__titulo">Colunas</h3>
|
||||||
×
|
<button type="button" class="eli-tabela-modal-colunas__fechar" aria-label="Fechar" @click="emitFechar">
|
||||||
</button>
|
×
|
||||||
</header>
|
</button>
|
||||||
|
</header>
|
||||||
|
|
||||||
<div class="eli-tabela-modal-colunas__conteudo">
|
<div class="eli-tabela-modal-colunas__conteudo">
|
||||||
<div class="eli-tabela-modal-colunas__coluna">
|
<div class="eli-tabela-modal-colunas__coluna">
|
||||||
<div class="eli-tabela-modal-colunas__coluna-titulo">Visíveis</div>
|
<div class="eli-tabela-modal-colunas__coluna-titulo">Visíveis</div>
|
||||||
<div
|
<TransitionGroup
|
||||||
class="eli-tabela-modal-colunas__lista"
|
name="list"
|
||||||
@dragover.prevent
|
tag="div"
|
||||||
@drop="(e) => onDropLista(e, 'visiveis', null)"
|
class="eli-tabela-modal-colunas__lista"
|
||||||
>
|
@dragover.prevent="onDragOverLista('visiveis')"
|
||||||
<div
|
@drop="onDragEnd"
|
||||||
v-for="(rotulo, idx) in visiveisLocal"
|
|
||||||
:key="`vis-${rotulo}`"
|
|
||||||
class="eli-tabela-modal-colunas__item"
|
|
||||||
draggable="true"
|
|
||||||
@dragstart="(e) => onDragStart(e, rotulo, 'visiveis', idx)"
|
|
||||||
@dragover.prevent
|
|
||||||
@drop="(e) => onDropItem(e, 'visiveis', idx)"
|
|
||||||
>
|
>
|
||||||
<span class="eli-tabela-modal-colunas__item-handle" aria-hidden="true">⋮⋮</span>
|
<div
|
||||||
<span class="eli-tabela-modal-colunas__item-texto">{{ rotulo }}</span>
|
v-for="rotulo in visiveisLocal"
|
||||||
</div>
|
:key="`vis-${rotulo}`"
|
||||||
|
class="eli-tabela-modal-colunas__item"
|
||||||
|
:class="{
|
||||||
|
'eli-tabela-modal-colunas__item--arrastando': itemSendoArrastado === rotulo
|
||||||
|
}"
|
||||||
|
draggable="true"
|
||||||
|
@dragstart="onDragStart($event, rotulo)"
|
||||||
|
@dragend="onDragEnd"
|
||||||
|
@dragover.stop.prevent="onDragOverItem(rotulo, 'visiveis')"
|
||||||
|
@drop.stop.prevent="onDragEnd"
|
||||||
|
>
|
||||||
|
<span class="eli-tabela-modal-colunas__item-handle" aria-hidden="true">⋮⋮</span>
|
||||||
|
<span class="eli-tabela-modal-colunas__item-texto">{{ rotulo }}</span>
|
||||||
|
</div>
|
||||||
|
</TransitionGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="eli-tabela-modal-colunas__coluna">
|
||||||
|
<div class="eli-tabela-modal-colunas__coluna-titulo">Invisíveis</div>
|
||||||
|
<TransitionGroup
|
||||||
|
name="list"
|
||||||
|
tag="div"
|
||||||
|
class="eli-tabela-modal-colunas__lista"
|
||||||
|
@dragover.prevent="onDragOverLista('invisiveis')"
|
||||||
|
@drop="onDragEnd"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="rotulo in invisiveisLocal"
|
||||||
|
:key="`inv-${rotulo}`"
|
||||||
|
class="eli-tabela-modal-colunas__item"
|
||||||
|
:class="{
|
||||||
|
'eli-tabela-modal-colunas__item--arrastando': itemSendoArrastado === rotulo
|
||||||
|
}"
|
||||||
|
draggable="true"
|
||||||
|
@dragstart="onDragStart($event, rotulo)"
|
||||||
|
@dragend="onDragEnd"
|
||||||
|
@dragover.stop.prevent="onDragOverItem(rotulo, 'invisiveis')"
|
||||||
|
@drop.stop.prevent="onDragEnd"
|
||||||
|
>
|
||||||
|
<span class="eli-tabela-modal-colunas__item-handle" aria-hidden="true">⋮⋮</span>
|
||||||
|
<span class="eli-tabela-modal-colunas__item-texto">{{ rotulo }}</span>
|
||||||
|
</div>
|
||||||
|
</TransitionGroup>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="eli-tabela-modal-colunas__coluna">
|
<footer class="eli-tabela-modal-colunas__footer">
|
||||||
<div class="eli-tabela-modal-colunas__coluna-titulo">Invisíveis</div>
|
<button type="button" class="eli-tabela-modal-colunas__botao eli-tabela-modal-colunas__botao--sec" @click="emitFechar">
|
||||||
<div
|
Cancelar
|
||||||
class="eli-tabela-modal-colunas__lista"
|
</button>
|
||||||
@dragover.prevent
|
<button type="button" class="eli-tabela-modal-colunas__botao eli-tabela-modal-colunas__botao--prim" @click="emitSalvar">
|
||||||
@drop="(e) => onDropLista(e, 'invisiveis', null)"
|
Salvar
|
||||||
>
|
</button>
|
||||||
<div
|
</footer>
|
||||||
v-for="(rotulo, idx) in invisiveisLocal"
|
|
||||||
:key="`inv-${rotulo}`"
|
|
||||||
class="eli-tabela-modal-colunas__item"
|
|
||||||
draggable="true"
|
|
||||||
@dragstart="(e) => onDragStart(e, rotulo, 'invisiveis', idx)"
|
|
||||||
@dragover.prevent
|
|
||||||
@drop="(e) => onDropItem(e, 'invisiveis', idx)"
|
|
||||||
>
|
|
||||||
<span class="eli-tabela-modal-colunas__item-handle" aria-hidden="true">⋮⋮</span>
|
|
||||||
<span class="eli-tabela-modal-colunas__item-texto">{{ rotulo }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer class="eli-tabela-modal-colunas__footer">
|
|
||||||
<button type="button" class="eli-tabela-modal-colunas__botao eli-tabela-modal-colunas__botao--sec" @click="emitFechar">
|
|
||||||
Cancelar
|
|
||||||
</button>
|
|
||||||
<button type="button" class="eli-tabela-modal-colunas__botao eli-tabela-modal-colunas__botao--prim" @click="emitSalvar">
|
|
||||||
Salvar
|
|
||||||
</button>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
@ -78,14 +92,6 @@ import type { tipoEliColuna } from "./types-eli-tabela"
|
||||||
|
|
||||||
type OrigemLista = "visiveis" | "invisiveis"
|
type OrigemLista = "visiveis" | "invisiveis"
|
||||||
|
|
||||||
type DragPayload = {
|
|
||||||
rotulo: string
|
|
||||||
origem: OrigemLista
|
|
||||||
index: number
|
|
||||||
}
|
|
||||||
|
|
||||||
const DRAG_MIME = "application/x-eli-tabela-coluna"
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "EliTabelaModalColunas",
|
name: "EliTabelaModalColunas",
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -119,6 +125,8 @@ export default defineComponent({
|
||||||
const visiveisLocal = ref<string[]>([])
|
const visiveisLocal = ref<string[]>([])
|
||||||
const invisiveisLocal = ref<string[]>([])
|
const invisiveisLocal = ref<string[]>([])
|
||||||
|
|
||||||
|
const itemSendoArrastado = ref<string | null>(null)
|
||||||
|
|
||||||
function sincronizarEstado() {
|
function sincronizarEstado() {
|
||||||
const todos = props.rotulosColunas
|
const todos = props.rotulosColunas
|
||||||
const configTemDados =
|
const configTemDados =
|
||||||
|
|
@ -178,118 +186,66 @@ export default defineComponent({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeDragData(e: DragEvent, payload: DragPayload) {
|
function onDragStart(e: DragEvent, rotulo: string) {
|
||||||
try {
|
itemSendoArrastado.value = rotulo
|
||||||
e.dataTransfer?.setData(DRAG_MIME, JSON.stringify(payload))
|
if (e.dataTransfer) {
|
||||||
e.dataTransfer?.setData("text/plain", payload.rotulo)
|
e.dataTransfer.setData("text/plain", rotulo)
|
||||||
if (e.dataTransfer) {
|
e.dataTransfer.effectAllowed = "move"
|
||||||
e.dataTransfer.effectAllowed = "move"
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// ignore
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function readDragData(e: DragEvent): DragPayload | null {
|
function onDragEnd() {
|
||||||
try {
|
itemSendoArrastado.value = null
|
||||||
const raw = e.dataTransfer?.getData(DRAG_MIME)
|
|
||||||
if (!raw) return null
|
|
||||||
const parsed = JSON.parse(raw)
|
|
||||||
if (
|
|
||||||
!parsed ||
|
|
||||||
typeof parsed.rotulo !== "string" ||
|
|
||||||
(parsed.origem !== "visiveis" && parsed.origem !== "invisiveis")
|
|
||||||
) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return parsed as DragPayload
|
|
||||||
} catch {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removerDaOrigem(payload: DragPayload) {
|
function onDragOverItem(alvoRotulo: string, destino: OrigemLista) {
|
||||||
|
const draggedRotulo = itemSendoArrastado.value
|
||||||
|
if (!draggedRotulo || draggedRotulo === alvoRotulo) return
|
||||||
|
|
||||||
|
const origemVisIdx = visiveisLocal.value.indexOf(draggedRotulo)
|
||||||
|
const origemInvIdx = invisiveisLocal.value.indexOf(draggedRotulo)
|
||||||
|
const origem =
|
||||||
|
origemVisIdx >= 0 ? "visiveis" : origemInvIdx >= 0 ? "invisiveis" : null
|
||||||
|
if (!origem) return
|
||||||
|
|
||||||
const origemArr =
|
const origemArr =
|
||||||
payload.origem === "visiveis"
|
origem === "visiveis" ? visiveisLocal.value : invisiveisLocal.value
|
||||||
? visiveisLocal.value
|
const destinoArr =
|
||||||
: invisiveisLocal.value
|
|
||||||
const idx = origemArr.indexOf(payload.rotulo)
|
|
||||||
if (idx >= 0) origemArr.splice(idx, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
function inserirNoDestino(
|
|
||||||
destino: OrigemLista,
|
|
||||||
rotulo: string,
|
|
||||||
index: number | null,
|
|
||||||
) {
|
|
||||||
const arr =
|
|
||||||
destino === "visiveis" ? visiveisLocal.value : invisiveisLocal.value
|
destino === "visiveis" ? visiveisLocal.value : invisiveisLocal.value
|
||||||
// remove duplicatas
|
|
||||||
const existing = arr.indexOf(rotulo)
|
|
||||||
if (existing >= 0) arr.splice(existing, 1)
|
|
||||||
|
|
||||||
if (index === null || index < 0 || index > arr.length) {
|
const dragIdx = origemArr.indexOf(draggedRotulo)
|
||||||
arr.push(rotulo)
|
const alvoIdx = destinoArr.indexOf(alvoRotulo)
|
||||||
} else {
|
|
||||||
arr.splice(index, 0, rotulo)
|
origemArr.splice(dragIdx, 1)
|
||||||
}
|
destinoArr.splice(alvoIdx, 0, draggedRotulo)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDragStart(
|
function onDragOverLista(destino: OrigemLista) {
|
||||||
e: DragEvent,
|
const draggedRotulo = itemSendoArrastado.value
|
||||||
rotulo: string,
|
if (!draggedRotulo) return
|
||||||
origem: OrigemLista,
|
|
||||||
index: number,
|
|
||||||
) {
|
|
||||||
writeDragData(e, { rotulo, origem, index })
|
|
||||||
}
|
|
||||||
|
|
||||||
function onDropItem(e: DragEvent, destino: OrigemLista, index: number) {
|
const destinoArr =
|
||||||
const payload = readDragData(e)
|
destino === "visiveis" ? visiveisLocal.value : invisiveisLocal.value
|
||||||
if (!payload) return
|
if (destinoArr[destinoArr.length - 1] === draggedRotulo) return
|
||||||
|
|
||||||
// remove da origem e insere no destino na posição do item
|
const origemVisIdx = visiveisLocal.value.indexOf(draggedRotulo)
|
||||||
removerDaOrigem(payload)
|
const origemInvIdx = invisiveisLocal.value.indexOf(draggedRotulo)
|
||||||
inserirNoDestino(destino, payload.rotulo, index)
|
if (origemVisIdx >= 0) visiveisLocal.value.splice(origemVisIdx, 1)
|
||||||
|
if (origemInvIdx >= 0) invisiveisLocal.value.splice(origemInvIdx, 1)
|
||||||
|
|
||||||
// garante que uma coluna não fique nos 2 lados
|
destinoArr.push(draggedRotulo)
|
||||||
if (destino === "visiveis") {
|
|
||||||
const idxInv = invisiveisLocal.value.indexOf(payload.rotulo)
|
|
||||||
if (idxInv >= 0) invisiveisLocal.value.splice(idxInv, 1)
|
|
||||||
} else {
|
|
||||||
const idxVis = visiveisLocal.value.indexOf(payload.rotulo)
|
|
||||||
if (idxVis >= 0) visiveisLocal.value.splice(idxVis, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onDropLista(
|
|
||||||
e: DragEvent,
|
|
||||||
destino: OrigemLista,
|
|
||||||
_index: number | null,
|
|
||||||
) {
|
|
||||||
const payload = readDragData(e)
|
|
||||||
if (!payload) return
|
|
||||||
|
|
||||||
removerDaOrigem(payload)
|
|
||||||
inserirNoDestino(destino, payload.rotulo, null)
|
|
||||||
|
|
||||||
if (destino === "visiveis") {
|
|
||||||
const idxInv = invisiveisLocal.value.indexOf(payload.rotulo)
|
|
||||||
if (idxInv >= 0) invisiveisLocal.value.splice(idxInv, 1)
|
|
||||||
} else {
|
|
||||||
const idxVis = visiveisLocal.value.indexOf(payload.rotulo)
|
|
||||||
if (idxVis >= 0) visiveisLocal.value.splice(idxVis, 1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
visiveisLocal,
|
visiveisLocal,
|
||||||
invisiveisLocal,
|
invisiveisLocal,
|
||||||
|
itemSendoArrastado,
|
||||||
emitFechar,
|
emitFechar,
|
||||||
emitSalvar,
|
emitSalvar,
|
||||||
onDragStart,
|
onDragStart,
|
||||||
onDropItem,
|
onDragEnd,
|
||||||
onDropLista,
|
onDragOverItem,
|
||||||
|
onDragOverLista,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
@ -364,6 +320,8 @@ export default defineComponent({
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background: rgba(15, 23, 42, 0.01);
|
background: rgba(15, 23, 42, 0.01);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.eli-tabela-modal-colunas__item {
|
.eli-tabela-modal-colunas__item {
|
||||||
|
|
@ -376,6 +334,7 @@ export default defineComponent({
|
||||||
background: #fff;
|
background: #fff;
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
transition: box-shadow 0.15s, opacity 0.15s, transform 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.eli-tabela-modal-colunas__item + .eli-tabela-modal-colunas__item {
|
.eli-tabela-modal-colunas__item + .eli-tabela-modal-colunas__item {
|
||||||
|
|
@ -386,6 +345,31 @@ export default defineComponent({
|
||||||
cursor: grabbing;
|
cursor: grabbing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.eli-tabela-modal-colunas__item--arrastando {
|
||||||
|
opacity: 0.1;
|
||||||
|
background: #f8fafc;
|
||||||
|
border-style: dashed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animações de reposicionamento e listas do Vue TransitionGroup */
|
||||||
|
.list-move,
|
||||||
|
.list-enter-active,
|
||||||
|
.list-leave-active {
|
||||||
|
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-enter-from,
|
||||||
|
.list-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-leave-active {
|
||||||
|
/* position absolute para suavizar a animação de saída de outras listas */
|
||||||
|
position: absolute;
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
}
|
||||||
|
|
||||||
.eli-tabela-modal-colunas__item-handle {
|
.eli-tabela-modal-colunas__item-handle {
|
||||||
color: rgba(15, 23, 42, 0.55);
|
color: rgba(15, 23, 42, 0.55);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,10 @@ export type tipoEliTabelaConsulta<T> = {
|
||||||
nome: string
|
nome: string
|
||||||
/** Indica se a caixa de busca deve ser exibida acima da tabela. */
|
/** Indica se a caixa de busca deve ser exibida acima da tabela. */
|
||||||
mostrarCaixaDeBusca?: boolean
|
mostrarCaixaDeBusca?: boolean
|
||||||
|
/** Habilita seleção múltipla (checkboxes) nas linhas da tabela. */
|
||||||
|
mostrar_selecao?: boolean
|
||||||
|
/** Chave (ex: "id") para identificar unicamente a linha nas seleções entre páginas. */
|
||||||
|
chave_selecao?: keyof T
|
||||||
/** Lista de colunas da tabela. */
|
/** Lista de colunas da tabela. */
|
||||||
colunas: tipoEliColuna<T>[]
|
colunas: tipoEliColuna<T>[]
|
||||||
/** Quantidade de registros solicitados por consulta (padrão `10`). */
|
/** Quantidade de registros solicitados por consulta (padrão `10`). */
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@
|
||||||
<h2>EliTabela</h2>
|
<h2>EliTabela</h2>
|
||||||
|
|
||||||
<!-- Exemplo: botão de ação "Novo" no cabeçalho que adiciona uma linha -->
|
<!-- Exemplo: botão de ação "Novo" no cabeçalho que adiciona uma linha -->
|
||||||
<EliTabela :tabela="tabelaOk" :key="versaoTabelaOk" />
|
<div style="margin-bottom: 12px">
|
||||||
|
<strong>Selecionados:</strong> {{ selecionados.map(s => s.empreendedor).join(', ') || 'Nenhum' }}
|
||||||
|
</div>
|
||||||
|
<EliTabela :tabela="tabelaOk" :key="versaoTabelaOk" v-model:selecionados="selecionados" />
|
||||||
|
|
||||||
<EliTabela :tabela="tabelaVazia" />
|
<EliTabela :tabela="tabelaVazia" />
|
||||||
|
|
||||||
|
|
@ -97,6 +100,7 @@ export default defineComponent({
|
||||||
]
|
]
|
||||||
|
|
||||||
const versaoTabelaOk = ref(0)
|
const versaoTabelaOk = ref(0)
|
||||||
|
const selecionados = ref<Linha[]>([])
|
||||||
const mostrarModalCadastro = ref(false)
|
const mostrarModalCadastro = ref(false)
|
||||||
const salvando = ref(false)
|
const salvando = ref(false)
|
||||||
const novoCadastro = ref({
|
const novoCadastro = ref({
|
||||||
|
|
@ -175,6 +179,8 @@ export default defineComponent({
|
||||||
nome: "ExemploPlaygroundData",
|
nome: "ExemploPlaygroundData",
|
||||||
registros_por_consulta: 10,
|
registros_por_consulta: 10,
|
||||||
mostrarCaixaDeBusca: true,
|
mostrarCaixaDeBusca: true,
|
||||||
|
mostrar_selecao: true,
|
||||||
|
chave_selecao: "empreendedor",
|
||||||
acoesTabela: [
|
acoesTabela: [
|
||||||
{
|
{
|
||||||
posicao: "superior",
|
posicao: "superior",
|
||||||
|
|
@ -300,6 +306,7 @@ export default defineComponent({
|
||||||
{
|
{
|
||||||
chave: "empreendedor",
|
chave: "empreendedor",
|
||||||
rotulo: "Empreendedor",
|
rotulo: "Empreendedor",
|
||||||
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||||
filtro: (valor: unknown) =>
|
filtro: (valor: unknown) =>
|
||||||
criarFiltro26({
|
criarFiltro26({
|
||||||
// biome-ignore lint/suspicious/noExplicitAny: playground
|
// biome-ignore lint/suspicious/noExplicitAny: playground
|
||||||
|
|
@ -310,7 +317,8 @@ export default defineComponent({
|
||||||
{
|
{
|
||||||
chave: "documento",
|
chave: "documento",
|
||||||
rotulo: "Documento",
|
rotulo: "Documento",
|
||||||
filtro: (valor: unknown) =>
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||||
|
filtro: (valor: string) =>
|
||||||
criarFiltro26({
|
criarFiltro26({
|
||||||
// biome-ignore lint/suspicious/noExplicitAny: playground
|
// biome-ignore lint/suspicious/noExplicitAny: playground
|
||||||
documento: { like: valor as string } as any,
|
documento: { like: valor as string } as any,
|
||||||
|
|
@ -323,7 +331,8 @@ export default defineComponent({
|
||||||
{
|
{
|
||||||
chave: "email",
|
chave: "email",
|
||||||
rotulo: "E-mail",
|
rotulo: "E-mail",
|
||||||
filtro: (valor: unknown) =>
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||||
|
filtro: (valor: string) =>
|
||||||
criarFiltro26({
|
criarFiltro26({
|
||||||
// biome-ignore lint/suspicious/noExplicitAny: playground
|
// biome-ignore lint/suspicious/noExplicitAny: playground
|
||||||
email: { like: valor as string } as any,
|
email: { like: valor as string } as any,
|
||||||
|
|
@ -407,6 +416,7 @@ export default defineComponent({
|
||||||
novoCadastro,
|
novoCadastro,
|
||||||
salvarNovoCadastro,
|
salvarNovoCadastro,
|
||||||
erroCadastro,
|
erroCadastro,
|
||||||
|
selecionados,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue