'use client' import type { GridColumn, GridEditorCell, GridRow } from './types' import { getCellColor } from './gridTableUtils' interface GridTableCellProps { cell: GridEditorCell | undefined col: GridColumn row: GridRow zone: { zone_index: number } rowH: number selectedCell: string | null selectedCells?: Set onSelectCell: (cellId: string) => void onToggleCellSelection?: (cellId: string) => void onCellTextChange: (cellId: string, text: string) => void onNavigate: (cellId: string, direction: 'up' | 'down' | 'left' | 'right') => void onSetCellColor?: (cellId: string, color: string | null | undefined) => void onOpenColorMenu: (cellId: string, x: number, y: number) => void handleKeyDown: (e: React.KeyboardEvent, cellId: string) => void } export function GridTableCell({ cell, col, row, zone, rowH, selectedCell, selectedCells, onSelectCell, onToggleCellSelection, onCellTextChange, onNavigate, onSetCellColor, onOpenColorMenu, handleKeyDown, }: GridTableCellProps) { const cellId = cell?.cell_id ?? `Z${zone.zone_index}_R${String(row.index).padStart(2, '0')}_C${col.index}` const isSelected = selectedCell === cellId const isBold = col.bold || cell?.is_bold const isLowConf = cell && cell.confidence > 0 && cell.confidence < 60 const isMultiSelected = selectedCells?.has(cellId) // Show per-word colored display only when word_boxes match the cell text. // Post-processing steps modify cell.text but not individual word_boxes, // so we fall back to the plain input when they diverge. const wbText = cell?.word_boxes?.map((wb) => wb.text).join(' ') ?? '' const textMatches = !cell?.text || wbText === cell.text // Color: prefer manual override, else word_boxes when text matches const hasOverride = cell?.color_override !== undefined const cellColor = hasOverride ? getCellColor(cell) : (textMatches ? getCellColor(cell) : null) const hasColoredWords = !hasOverride && textMatches && (cell?.word_boxes?.some( (wb) => wb.color_name && wb.color_name !== 'black', ) ?? false) const cellText = cell?.text ?? '' const isMultiLine = cellText.includes('\n') return (
{ if (onSetCellColor) { e.preventDefault() onOpenColorMenu(cellId, e.clientX, e.clientY) } }} > {cellColor && ( wb.color_name !== 'black')?.color_name}`} /> )} {/* Per-word colored display when not editing */} {hasColoredWords && !isSelected ? (
{ if ((e.metaKey || e.ctrlKey) && onToggleCellSelection) { onToggleCellSelection(cellId) } else { onSelectCell(cellId) setTimeout(() => document.getElementById(`cell-${cellId}`)?.focus(), 0) } }} > {cell!.word_boxes!.map((wb, i) => ( {wb.text} {i < cell!.word_boxes!.length - 1 ? ' ' : ''} ))}
) : isMultiLine ? (