Atualização floresta

This commit is contained in:
Luiz Silva 2026-05-31 11:27:51 -03:00
parent 0886fd5c3e
commit 2d4d8f8929
103 changed files with 19266 additions and 14160 deletions

View file

@ -0,0 +1,139 @@
/**
* useColunasOrdenacao
* Composable que encapsula a lógica de drag-and-drop e sincronização de estado
* do modal de configuração de colunas da EliTabela.
*
* Responsável por:
* - Sincronizar colunas visíveis/invisíveis com a configuração persistida
* - Aplicar ordem salva e adicionar novas colunas ao final
* - Gerenciar eventos de arrastar-e-soltar entre as duas listas
*
* Extraído de `EliTabelaModalColunas.vue` para manter o componente abaixo de 250 linhas.
*/
import { type Ref, ref, watch } from "vue"
import type { EliTabelaColunasConfig } from "./colunasStorage"
import type { tipoEliColuna } from "./types-eli-tabela"
type OrigemLista = "visiveis" | "invisiveis"
interface UseColunasOrdenacaoOptions {
aberto: Ref<boolean>
rotulosColunas: Ref<string[]>
configInicial: Ref<EliTabelaColunasConfig>
// biome-ignore lint/suspicious/noExplicitAny: colunas genéricas — tipo parametrizado no pai
colunas: Ref<tipoEliColuna<any>[]>
}
/**
* Composable de drag-and-drop para reordenação e alternância de visibilidade de colunas.
* Sincroniza automaticamente quando `aberto`, `rotulosColunas`, `configInicial` ou `colunas` mudam.
*
* @param options.aberto - Ref que controla se o modal está aberto (gatilho de sincronização)
* @param options.rotulosColunas - Ref com todos os rótulos de colunas da tabela
* @param options.configInicial - Ref com a configuração persistida (visíveis + invisíveis)
* @param options.colunas - Ref com a definição completa das colunas (para ler `visivel: false` padrão)
* @returns Estado reativo e handlers de drag-and-drop prontos para o template
*/
export function useColunasOrdenacao({
aberto,
rotulosColunas,
configInicial,
colunas,
}: UseColunasOrdenacaoOptions) {
const visiveisLocal = ref<string[]>([])
const invisiveisLocal = ref<string[]>([])
const itemSendoArrastado = ref<string | null>(null)
function sincronizarEstado() {
const todos = rotulosColunas.value
const configTemDados =
(configInicial.value.visiveis?.length ?? 0) > 0 ||
(configInicial.value.invisiveis?.length ?? 0) > 0
const invisiveisPadraoSet = new Set(
colunas.value.filter((c) => c.visivel === false).map((c) => c.rotulo),
)
const invisiveisSet = configTemDados
? new Set(configInicial.value.invisiveis ?? [])
: invisiveisPadraoSet
const baseVisiveis = todos.filter((r) => !invisiveisSet.has(r))
const ordemSalva = configInicial.value.visiveis ?? []
const setVis = new Set(baseVisiveis)
const ordenadas: string[] = []
for (const r of ordemSalva) {
if (setVis.has(r)) ordenadas.push(r)
}
for (const r of baseVisiveis) {
if (!ordenadas.includes(r)) ordenadas.push(r)
}
visiveisLocal.value = ordenadas
invisiveisLocal.value = todos.filter((r) => invisiveisSet.has(r))
}
watch(
() => [aberto.value, rotulosColunas.value, configInicial.value, colunas.value] as const,
() => {
if (aberto.value) sincronizarEstado()
},
{ deep: true, immediate: true },
)
function onDragStart(e: DragEvent, rotulo: string) {
itemSendoArrastado.value = rotulo
if (e.dataTransfer) {
e.dataTransfer.setData("text/plain", rotulo)
e.dataTransfer.effectAllowed = "move"
}
}
function onDragEnd() {
itemSendoArrastado.value = null
}
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 = origem === "visiveis" ? visiveisLocal.value : invisiveisLocal.value
const destinoArr = destino === "visiveis" ? visiveisLocal.value : invisiveisLocal.value
const dragIdx = origemArr.indexOf(draggedRotulo)
const alvoIdx = destinoArr.indexOf(alvoRotulo)
origemArr.splice(dragIdx, 1)
destinoArr.splice(alvoIdx, 0, draggedRotulo)
}
function onDragOverLista(destino: OrigemLista) {
const draggedRotulo = itemSendoArrastado.value
if (!draggedRotulo) return
const destinoArr = destino === "visiveis" ? visiveisLocal.value : invisiveisLocal.value
if (destinoArr[destinoArr.length - 1] === draggedRotulo) return
const origemVisIdx = visiveisLocal.value.indexOf(draggedRotulo)
const origemInvIdx = invisiveisLocal.value.indexOf(draggedRotulo)
if (origemVisIdx >= 0) visiveisLocal.value.splice(origemVisIdx, 1)
if (origemInvIdx >= 0) invisiveisLocal.value.splice(origemInvIdx, 1)
destinoArr.push(draggedRotulo)
}
return {
visiveisLocal,
invisiveisLocal,
itemSendoArrastado,
onDragStart,
onDragEnd,
onDragOverItem,
onDragOverLista,
}
}