import { nextTick, onBeforeUnmount, ref, type Ref } from 'vue' export interface UseTableHoverOptions { tableSelector?: string } const ROW_SELECTOR = '.el-table-v2__row' export function useTableHover( options: UseTableHoverOptions = {}, ) { const { tableSelector = '.ivyforms-table' } = options const hoveredRowId: Ref = ref(null) let controller: AbortController | null = null const setHoveredRow = (table: Element, rowKey: string | null) => { table.querySelectorAll(`${ROW_SELECTOR}.hovered`).forEach((el) => { if (!rowKey || el.getAttribute('rowkey') !== rowKey) el.classList.remove('hovered') }) if (!rowKey) { hoveredRowId.value = null return } const parsed = Number(rowKey) hoveredRowId.value = (Number.isNaN(parsed) ? rowKey : parsed) as TId table.querySelectorAll(`${ROW_SELECTOR}[rowkey="${CSS.escape(rowKey)}"]`).forEach((el) => { el.classList.add('hovered') }) } const syncHover = async () => { await nextTick() controller?.abort() controller = new AbortController() const { signal } = controller const table = document.querySelector(tableSelector) if (!table) return table.addEventListener( 'mouseover', (event) => { const target = event.target if (!(target instanceof Element)) return const row = target.closest(ROW_SELECTOR) if (!row || !table.contains(row)) return const rowKey = row.getAttribute('rowkey') if (!rowKey) return setHoveredRow(table, rowKey) }, { signal }, ) table.addEventListener( 'mouseout', (event) => { const target = event.target if (!(target instanceof Element)) return const row = target.closest(ROW_SELECTOR) if (!row) return const related = (event as MouseEvent).relatedTarget if (related instanceof Node && row.contains(related)) return setHoveredRow(table, null) }, { signal }, ) } onBeforeUnmount(() => { controller?.abort() controller = null }) return { hoveredRowId, syncHover } }