import React, { useState, useEffect, useRef } from 'react'; import { createPortal } from 'react-dom'; import { buildCsv } from './TableBlock'; import { copyTextToClipboard } from '../../utils/clipboard'; interface TableToolbarProps { element: HTMLElement; markdown: string; isExiting?: boolean; onMouseEnter?: () => void; onMouseLeave?: () => void; onExpand?: () => void; } // Floats above a table on hover. Mirrors AnnotationToolbar's positioning + // portal + entry/exit animation pattern so hover-triggered block toolbars // all look and move the same way. Content is table-specific (copy markdown // for now; CSV text button and expand icon planned). When a third use case // appears we should factor the positioning shell into a shared hook. export const TableToolbar: React.FC = ({ element, markdown, isExiting = false, onMouseEnter, onMouseLeave, onExpand, }) => { const [position, setPosition] = useState<{ top: number; right: number } | null>(null); const [copiedMd, setCopiedMd] = useState(false); const [copiedCsv, setCopiedCsv] = useState(false); const toolbarRef = useRef(null); useEffect(() => { const updatePosition = () => { const rect = element.getBoundingClientRect(); setPosition({ top: rect.top - 40, right: window.innerWidth - rect.right, }); }; updatePosition(); window.addEventListener('scroll', updatePosition, true); window.addEventListener('resize', updatePosition); return () => { window.removeEventListener('scroll', updatePosition, true); window.removeEventListener('resize', updatePosition); }; }, [element]); useEffect(() => { setCopiedMd(false); setCopiedCsv(false); }, [element]); const handleCopyMarkdown = async () => { if (await copyTextToClipboard(markdown)) { setCopiedMd(true); setTimeout(() => setCopiedMd(false), 1500); } else { console.error('Failed to copy'); } }; const handleCopyCsv = async () => { if (await copyTextToClipboard(buildCsv(markdown))) { setCopiedCsv(true); setTimeout(() => setCopiedCsv(false), 1500); } else { console.error('Failed to copy'); } }; if (!position) return null; const style: React.CSSProperties = { top: position.top, right: position.right, animation: isExiting ? 'table-toolbar-out 0.15s ease-in forwards' : 'table-toolbar-in 0.15s ease-out', }; return createPortal(
e.stopPropagation()} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} >
{onExpand && ( )}
, document.body, ); }; const CopyIcon = () => ( ); const CheckIcon = () => ( ); const ExpandIcon = () => ( );