vue-componentes/src/componentes/EliTabela/EliTabelaMenuAcoes.vue
2026-05-16 17:43:46 -03:00

99 lines
2.8 KiB
Vue

<template>
<div class="eli-teleport-container">
<Teleport to="body">
<ul
v-if="menuAberto !== null && possuiAcoes"
:id="`eli-tabela-acoes-menu-${menuAberto}`"
ref="menuEl"
class="eli-tabela__acoes-menu"
role="menu"
:aria-labelledby="`eli-tabela-acoes-toggle-${menuAberto}`"
:style="{
position: 'fixed',
top: `${posicao.top}px`,
left: `${posicao.left}px`,
zIndex: 999999,
}"
>
<li
v-for="item in acoes"
:key="`acao-${menuAberto}-${item.indice}`"
class="eli-tabela__acoes-item"
role="none"
>
<button
type="button"
class="eli-tabela__acoes-item-botao"
:style="{ color: item.acao.cor }"
role="menuitem"
:aria-label="item.acao.rotulo"
:title="item.acao.rotulo"
@click.stop="emitExecutar(item)"
>
<component
:is="item.acao.icone"
class="eli-tabela__acoes-item-icone"
:size="16"
:stroke-width="2"
/>
<span class="eli-tabela__acoes-item-texto">{{ item.acao.rotulo }}</span>
</button>
</li>
</ul>
</Teleport>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, type PropType, ref } from "vue"
import type { tipoEliTabelaAcao } from "./types-eli-tabela"
type ItemAcao<T> = {
acao: tipoEliTabelaAcao<T>
indice: number
visivel: boolean
}
export default defineComponent({
name: "EliTabelaMenuAcoes",
props: {
menuAberto: {
type: [Number, Object] as PropType<number | null>,
default: null,
},
posicao: {
type: Object as PropType<{ top: number; left: number }>,
required: true,
},
acoes: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic typing needed
type: Array as PropType<Array<ItemAcao<any>>>,
required: true,
},
linha: {
// Aceita qualquer tipo de linha (objeto, string, etc.) sem validação runtime.
type: [Object, String, Number, Array] as PropType<unknown | null>,
required: true,
},
},
emits: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic typing needed
executar(payload: { acao: tipoEliTabelaAcao<any>; linha: unknown }) {
return payload !== null && typeof payload === "object"
},
},
setup(props, { emit }) {
const menuEl = ref<HTMLElement | null>(null)
const possuiAcoes = computed(() => props.acoes.length > 0)
// biome-ignore lint/suspicious/noExplicitAny: dynamic typing needed
function emitExecutar(item: { acao: tipoEliTabelaAcao<any> }) {
if (!props.linha) return
emit("executar", { acao: item.acao, linha: props.linha })
}
return { menuEl, possuiAcoes, emitExecutar }
},
})
</script>