- {/* Row number */}
- (
+ onToggleColumnBold(zone.zone_index, col.index)}
+ title={`Spalte ${col.index + 1} — Klick fuer Fett-Toggle`}
+ >
+
+ {col.label}
+ {col.bold && (
+
+ B
+
+ )}
+
+ {/* Right-edge resize handle */}
+ {ci < numCols - 1 && (
+ {
+ e.stopPropagation()
+ handleColResizeStart(ci, e.clientX)
+ }}
+ />
+ )}
+
+ ))}
+
+ {/* ============================================================ */}
+ {/* Data rows */}
+ {/* ============================================================ */}
+ {zone.rows.map((row) => {
+ const rowH = getRowHeight(row.index, row.is_header)
+ const isSpanning = zone.cells.some(
+ (c) => c.row_index === row.index && c.col_type === 'spanning_header',
+ )
+
+ return (
+
+ {/* Row number cell */}
+ onToggleRowHeader(zone.zone_index, row.index)}
title={`Zeile ${row.index + 1} — Klick fuer Header-Toggle`}
>
{row.index + 1}
{row.is_header && H}
- |
+ {/* Bottom-edge resize handle */}
+ {
+ e.stopPropagation()
+ handleRowResizeStart(row.index, e.clientY, rowH)
+ }}
+ />
+
- {/* Cells */}
- {zone.columns.map((col) => {
- const cell = cellMap.get(`${row.index}_${col.index}`)
- 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 cellColor = getCellColor(cell)
- const hasColoredWords = cell?.word_boxes?.some(
- (wb) => wb.color_name && wb.color_name !== 'black',
- ) ?? false
+ {/* Cells — spanning header or normal columns */}
+ {isSpanning ? (
+
+ {(() => {
+ const spanCell = zone.cells.find(
+ (c) => c.row_index === row.index && c.col_type === 'spanning_header',
+ )
+ if (!spanCell) return null
+ const cellId = spanCell.cell_id
+ const isSelected = selectedCell === cellId
+ const cellColor = getCellColor(spanCell)
+ return (
+
+ {cellColor && (
+
+ )}
+ onCellTextChange(cellId, e.target.value)}
+ onFocus={() => onSelectCell(cellId)}
+ onKeyDown={(e) => handleKeyDown(e, cellId)}
+ className={`w-full px-3 py-1 bg-transparent border-0 outline-none text-center ${
+ isSelected ? 'ring-2 ring-teal-500 ring-inset rounded' : ''
+ }`}
+ style={{ color: cellColor || undefined }}
+ spellCheck={false}
+ />
+
+ )
+ })()}
+
+ ) : (
+ zone.columns.map((col) => {
+ const cell = cellMap.get(`${row.index}_${col.index}`)
+ 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 cellColor = getCellColor(cell)
+ const hasColoredWords =
+ cell?.word_boxes?.some(
+ (wb) => wb.color_name && wb.color_name !== 'black',
+ ) ?? false
- return (
-
-
+ return (
+
{cellColor && (
wb.color_name !== 'black')?.color_name}`}
+ title={`Farbe: ${cell?.word_boxes?.find((wb) => wb.color_name !== 'black')?.color_name}`}
/>
)}
{/* Per-word colored display when not editing */}
{hasColoredWords && !isSelected ? (
{
onSelectCell(cellId)
setTimeout(() => document.getElementById(`cell-${cellId}`)?.focus(), 0)
@@ -185,20 +412,20 @@ export function GridTable({
}}
onFocus={() => onSelectCell(cellId)}
onKeyDown={(e) => handleKeyDown(e, cellId)}
- className={`w-full px-2 py-1.5 bg-transparent border-0 outline-none ${
+ className={`w-full px-2 bg-transparent border-0 outline-none ${
isBold ? 'font-bold' : 'font-normal'
- } ${row.is_header ? 'text-base' : 'text-sm'}`}
+ }`}
spellCheck={false}
/>
)}
- |
- )
- })}
-
- ))}
-