import { useEffect, useLayoutEffect, useRef } from 'react' import { createPortal } from 'react-dom' import { useUITranslation } from '@/lib/useUITranslation' export type CountsMenuAction = 'copy' | 'copyHeaders' | 'row' | 'column' | 'all' const CountsCellMenu = ( { x, y, act, close }: { x: number y: number act: (action: CountsMenuAction) => void close: () => void }, ) => { const root = useRef (null) const { label, message } = useUITranslation ('counts') useLayoutEffect (() => { const menu = root.current if (menu == null) return const rect = menu.getBoundingClientRect () menu.style.left = `${Math.max (4, Math.min (x, window.innerWidth - rect.width - 4))}px` menu.style.top = `${Math.max (4, Math.min (y, window.innerHeight - rect.height - 4))}px` menu.querySelector ('button')?.focus ({ preventScroll: true }) }, [x, y]) useEffect (() => { const outside = (event: Event) => { if (!root.current?.contains (event.target as Node)) close () } const escape = (event: KeyboardEvent) => { if (event.key === 'Escape') { event.preventDefault () event.stopPropagation () close () } } document.addEventListener ('pointerdown', outside, true) document.addEventListener ('keydown', escape, true) window.addEventListener ('resize', close) document.addEventListener ('scroll', outside, true) return () => { document.removeEventListener ('pointerdown', outside, true) document.removeEventListener ('keydown', escape, true) window.removeEventListener ('resize', close) document.removeEventListener ('scroll', outside, true) } }, [close]) const actions: CountsMenuAction[] = ['copy', 'copyHeaders', 'row', 'column', 'all'] return createPortal (
event.preventDefault ()} onPointerDown={event => event.stopPropagation ()} onKeyDown={event => { event.stopPropagation () if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase () === 'c') { event.preventDefault () act ('copy') return } const buttons = Array.from (root.current?.querySelectorAll ('button') ?? []) const current = buttons.indexOf (document.activeElement as HTMLButtonElement) if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes (event.key)) { event.preventDefault () const next = event.key === 'Home' ? 0 : (event.key === 'End' ? buttons.length - 1 : (current + (event.key === 'ArrowDown' ? 1 : -1) + buttons.length) % buttons.length) buttons[next]?.focus () } if (event.key === 'Tab') close () }}> {actions.map (action => ( ))}
, document.body) } export default CountsCellMenu