(clientX: number, clientY: number)
| 155 | * Uses elementsFromPoint to skip the interaction layer, shadow DOM host, and placeholder elements. |
| 156 | */ |
| 157 | export function getPageElementAtPoint(clientX: number, clientY: number): HTMLElement | null { |
| 158 | // Check cache first — avoids expensive elementsFromPoint on small mouse movements |
| 159 | const cached = getCachedElement(clientX, clientY); |
| 160 | if (cached !== undefined) return cached; |
| 161 | |
| 162 | const elements = document.elementsFromPoint(clientX, clientY); |
| 163 | let result: HTMLElement | null = null; |
| 164 | |
| 165 | for (const el of elements) { |
| 166 | if (!(el instanceof HTMLElement)) continue; |
| 167 | if (el.closest("#react-rewrite-root")) continue; |
| 168 | if (el.hasAttribute("data-react-rewrite-interaction")) continue; |
| 169 | if (el.hasAttribute("data-react-rewrite-placeholder")) continue; |
| 170 | if (el === document.body || el === document.documentElement) continue; |
| 171 | if (isFullPageElement(el)) continue; |
| 172 | result = el; |
| 173 | break; |
| 174 | } |
| 175 | |
| 176 | setCachedElement(clientX, clientY, result); |
| 177 | return result; |
| 178 | } |
| 179 | |
| 180 | export function destroyInteraction(): void { |
| 181 | document.removeEventListener("scroll", clearElementCache, true); |
no test coverage detected