GridTable: render multi-line cells with textarea
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 46s
CI / test-go-edu-search (push) Successful in 46s
CI / test-python-klausur (push) Failing after 2m53s
CI / test-python-agent-core (push) Successful in 32s
CI / test-nodejs-website (push) Successful in 34s
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 46s
CI / test-go-edu-search (push) Successful in 46s
CI / test-python-klausur (push) Failing after 2m53s
CI / test-python-agent-core (push) Successful in 32s
CI / test-nodejs-website (push) Successful in 34s
Cells containing \n (bullet items with continuation lines) now use <textarea> instead of <input type=text>, making all lines visible. Row height auto-expands based on line count in the cell. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -107,12 +107,18 @@ export function GridTable({
|
|||||||
const row = zone.rows.find((r) => r.index === rowIndex)
|
const row = zone.rows.find((r) => r.index === rowIndex)
|
||||||
if (!row) return Math.max(MIN_ROW_HEIGHT, avgRowHeightPx * scale)
|
if (!row) return Math.max(MIN_ROW_HEIGHT, avgRowHeightPx * scale)
|
||||||
|
|
||||||
|
// Multi-line cells (containing \n): expand height based on line count
|
||||||
|
const rowCells = zone.cells.filter((c) => c.row_index === rowIndex)
|
||||||
|
const maxLines = Math.max(1, ...rowCells.map((c) => (c.text ?? '').split('\n').length))
|
||||||
|
if (maxLines > 1) {
|
||||||
|
const lineH = Math.max(MIN_ROW_HEIGHT, avgRowHeightPx * scale)
|
||||||
|
return lineH * maxLines
|
||||||
|
}
|
||||||
|
|
||||||
if (isHeader) {
|
if (isHeader) {
|
||||||
// Headers keep their measured height
|
|
||||||
const measuredH = row.y_max_px - row.y_min_px
|
const measuredH = row.y_max_px - row.y_min_px
|
||||||
return Math.max(MIN_ROW_HEIGHT, measuredH * scale)
|
return Math.max(MIN_ROW_HEIGHT, measuredH * scale)
|
||||||
}
|
}
|
||||||
// Content rows use average for uniformity
|
|
||||||
return Math.max(MIN_ROW_HEIGHT, avgRowHeightPx * scale)
|
return Math.max(MIN_ROW_HEIGHT, avgRowHeightPx * scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,25 +541,52 @@ export function GridTable({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<input
|
{(cell?.text ?? '').includes('\n') ? (
|
||||||
id={`cell-${cellId}`}
|
<textarea
|
||||||
type="text"
|
id={`cell-${cellId}`}
|
||||||
value={cell?.text ?? ''}
|
value={cell?.text ?? ''}
|
||||||
onChange={(e) => onCellTextChange(cellId, e.target.value)}
|
onChange={(e) => onCellTextChange(cellId, e.target.value)}
|
||||||
onFocus={() => onSelectCell(cellId)}
|
onFocus={() => onSelectCell(cellId)}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
if ((e.metaKey || e.ctrlKey) && onToggleCellSelection) {
|
if ((e.metaKey || e.ctrlKey) && onToggleCellSelection) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
onToggleCellSelection(cellId)
|
onToggleCellSelection(cellId)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(e) => handleKeyDown(e, cellId)}
|
onKeyDown={(e) => {
|
||||||
className={`w-full px-2 bg-transparent border-0 outline-none ${
|
if (e.key === 'Tab') {
|
||||||
isBold ? 'font-bold' : 'font-normal'
|
e.preventDefault()
|
||||||
}`}
|
onNavigate(cellId, e.shiftKey ? 'left' : 'right')
|
||||||
style={{ color: cellColor || undefined }}
|
}
|
||||||
spellCheck={false}
|
}}
|
||||||
/>
|
rows={(cell?.text ?? '').split('\n').length}
|
||||||
|
className={`w-full px-2 bg-transparent border-0 outline-none resize-none ${
|
||||||
|
isBold ? 'font-bold' : 'font-normal'
|
||||||
|
}`}
|
||||||
|
style={{ color: cellColor || undefined }}
|
||||||
|
spellCheck={false}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<input
|
||||||
|
id={`cell-${cellId}`}
|
||||||
|
type="text"
|
||||||
|
value={cell?.text ?? ''}
|
||||||
|
onChange={(e) => onCellTextChange(cellId, e.target.value)}
|
||||||
|
onFocus={() => onSelectCell(cellId)}
|
||||||
|
onClick={(e) => {
|
||||||
|
if ((e.metaKey || e.ctrlKey) && onToggleCellSelection) {
|
||||||
|
e.preventDefault()
|
||||||
|
onToggleCellSelection(cellId)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onKeyDown={(e) => handleKeyDown(e, cellId)}
|
||||||
|
className={`w-full px-2 bg-transparent border-0 outline-none ${
|
||||||
|
isBold ? 'font-bold' : 'font-normal'
|
||||||
|
}`}
|
||||||
|
style={{ color: cellColor || undefined }}
|
||||||
|
spellCheck={false}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user