StepAnsicht: dominant row height for content + proportional box rows
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 33s
CI / test-go-edu-search (push) Successful in 43s
CI / test-python-klausur (push) Failing after 2m35s
CI / test-python-agent-core (push) Successful in 34s
CI / test-nodejs-website (push) Successful in 31s

Content sections: use dominant (median) row height from all content
rows instead of per-section average. This ensures uniform row height
above and below boxes (the standard case on textbook pages).

Box sections: distribute height proportionally by text line count
per row. A header (1 line) gets 1/7 of box height, a bullet with
3 lines gets 3/7. Fixes Box 2 where row 3 was cut off because
even distribution didn't account for multi-line cells.

Removed overflow:hidden from box container to prevent clipping.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-14 17:43:02 +02:00
parent 1b7e095176
commit 7085c87618

View File

@@ -173,6 +173,22 @@ export function StepAnsicht({ sessionId, onNext }: StepAnsichtProps) {
const panelHeight = imgH * scale
const contentZone = grid.zones.find((z) => z.zone_type === 'content')
// Dominant row height: median of row-to-row spacings (excluding box-gap jumps)
const dominantRowH = useMemo(() => {
const cz = grid.zones.find((z) => z.zone_type === 'content')
if (!cz || cz.rows.length < 2) return 47
const spacings: number[] = []
for (let i = 0; i < cz.rows.length - 1; i++) {
const y1 = cz.rows[i].y_min_px ?? (cz.rows[i] as any).y_min ?? 0
const y2 = cz.rows[i + 1].y_min_px ?? (cz.rows[i + 1] as any).y_min ?? 0
const d = y2 - y1
if (d > 0 && d < 100) spacings.push(d)
}
if (spacings.length === 0) return 47
spacings.sort((a, b) => a - b)
return spacings[Math.floor(spacings.length / 2)]
}, [grid])
return (
<div className="space-y-3">
{/* Header */}
@@ -237,7 +253,7 @@ export function StepAnsicht({ sessionId, onNext }: StepAnsichtProps) {
rows={sec.rows}
yStart={sec.yStart}
scale={scale}
avgRowH={sec.avgRowH}
avgRowH={dominantRowH}
/>
)
}
@@ -375,13 +391,19 @@ function BoxSectionRenderer({ zone, scale, avgRowH }: {
const colScale = totalColW > 0 ? width / totalColW : 1
const numCols = zone.columns.length
// Evenly distribute rows within the box
const numRows = zone.rows.length
const evenRowH = numRows > 0 ? height / numRows : rowH
// Distribute box height proportionally by text line count per row
const rowLineCounts = zone.rows.map((row) => {
const maxLines = Math.max(1, ...zone.cells
.filter((c) => c.row_index === row.index)
.map((c) => (c.text ?? '').split('\n').length))
return maxLines
})
const totalLines = rowLineCounts.reduce((s, n) => s + n, 0)
const lineUnitH = totalLines > 0 ? height / totalLines : height
return (
<div
className="absolute overflow-hidden"
className="absolute"
style={{
left: `${left}px`,
top: `${top}px`,
@@ -395,14 +417,12 @@ function BoxSectionRenderer({ zone, scale, avgRowH }: {
}}
>
<div style={{ display: 'grid', gridTemplateColumns: colWidths.map((w) => `${(w * colScale).toFixed(1)}px`).join(' ') }}>
{zone.rows.map((row) => {
{zone.rows.map((row, rowIdx) => {
const isSpanning = zone.cells.some((c) => c.row_index === row.index && c.col_type === 'spanning_header')
// Multi-line height
const maxLines = Math.max(1, ...zone.cells
.filter((c) => c.row_index === row.index)
.map((c) => (c.text ?? '').split('\n').length))
const cellRowH = evenRowH * (maxLines > 1 ? maxLines * 0.7 : 1)
// Height proportional to text line count
const rowLines = rowLineCounts[rowIdx] || 1
const cellRowH = lineUnitH * rowLines
return (
<div key={row.index} style={{ display: 'contents' }}>