95 lines
2.5 KiB
Vue
95 lines
2.5 KiB
Vue
<template>
|
|
<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>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { computed, defineComponent, PropType, ref } from "vue";
|
|
import type { EliTabelaAcao } from "./types-eli-tabela";
|
|
|
|
type ItemAcao<T> = {
|
|
acao: EliTabelaAcao<T>;
|
|
indice: number;
|
|
visivel: boolean;
|
|
};
|
|
|
|
export default defineComponent({
|
|
name: "EliTabelaMenuAcoes",
|
|
props: {
|
|
menuAberto: {
|
|
type: Number as PropType<number | null>,
|
|
required: true,
|
|
},
|
|
posicao: {
|
|
type: Object as PropType<{ top: number; left: number }>,
|
|
required: true,
|
|
},
|
|
acoes: {
|
|
type: Array as PropType<Array<ItemAcao<any>>>,
|
|
required: true,
|
|
},
|
|
linha: {
|
|
// Aceita qualquer tipo de linha (objeto, string, etc.) sem validação runtime.
|
|
type: null as unknown as PropType<unknown | null>,
|
|
required: true,
|
|
},
|
|
},
|
|
emits: {
|
|
executar(payload: { acao: EliTabelaAcao<any>; linha: unknown }) {
|
|
return payload !== null && typeof payload === "object";
|
|
},
|
|
},
|
|
setup(props, { emit, expose }) {
|
|
const menuEl = ref<HTMLElement | null>(null);
|
|
expose({ menuEl });
|
|
|
|
const possuiAcoes = computed(() => props.acoes.length > 0);
|
|
|
|
function emitExecutar(item: { acao: EliTabelaAcao<any> }) {
|
|
if (!props.linha) return;
|
|
emit("executar", { acao: item.acao, linha: props.linha });
|
|
}
|
|
|
|
return { menuEl, possuiAcoes, emitExecutar };
|
|
},
|
|
});
|
|
</script>
|