Pin the row-label columns by index, not through __ROW_PATH__
Row labels still did not fit, because the override was landing on the wrong column. restore_column_size_overrides maps the key "__ROW_PATH__" to index tree_header_offset - 1, which with two group_by levels is index 2 — the first data column. That column is the grand total, which the stylesheet hides, so pinning it changed nothing visible. The row labels are separate columns (rt-col-0 and rt-col-1 here, one per group_by level), so each is measured on its own and set by index through regular-table's saveColumnSizes / restoreColumnSizes, which are index-based and public. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e7c266a871
commit
9ccaabd4c1
@ -1069,7 +1069,7 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
|||||||
grid.resetAutoSize()
|
grid.resetAutoSize()
|
||||||
await grid.draw({ invalid_columns: true })
|
await grid.draw({ invalid_columns: true })
|
||||||
|
|
||||||
await fitRowLabels(viewer, grid)
|
await fitRowLabels(grid)
|
||||||
|
|
||||||
// Widths are not part of ViewConfig, so persist the layout to keep the
|
// Widths are not part of ViewConfig, so persist the layout to keep the
|
||||||
// saved copy in step with what is on screen.
|
// saved copy in step with what is on screen.
|
||||||
@ -1081,47 +1081,53 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pin the row-label column wide enough for the labels it shows.
|
// Pin the row-label columns wide enough for the labels they show.
|
||||||
//
|
//
|
||||||
// Measured with a canvas rather than the DOM: the cell is clipped, so reading
|
// Measured with a canvas rather than the DOM: the cell is clipped, so reading
|
||||||
// its box back gives the width it was allotted, not the width of its text --
|
// its box back gives the width it was allotted, not the width of its text —
|
||||||
// the same circularity that stops headers sizing themselves.
|
// the same circularity that stops headers sizing themselves.
|
||||||
//
|
//
|
||||||
// __ROW_PATH__ is the key restore_column_size_overrides special-cases for this
|
// Set by column *index* through regular-table's own saveColumnSizes /
|
||||||
// column, and an override is what survives every subsequent draw, which is
|
// restoreColumnSizes, not as a plugin_config column_size_override. The override
|
||||||
// exactly why overrides were defeating resetAutoSize in the first place.
|
// path maps the key "__ROW_PATH__" to index tree_header_offset - 1, which with
|
||||||
async function fitRowLabels(viewer, grid) {
|
// two group_by levels is index 2 — the first data column, not a row label.
|
||||||
|
// Pinning that was doing nothing visible because that column is the
|
||||||
|
// grand-total one, which the stylesheet hides.
|
||||||
|
async function fitRowLabels(grid) {
|
||||||
const cells = [...grid.querySelectorAll('tbody th')]
|
const cells = [...grid.querySelectorAll('tbody th')]
|
||||||
if (cells.length === 0) return
|
if (cells.length === 0) return
|
||||||
|
|
||||||
const probe = cells[0]
|
const style = getComputedStyle(cells[0])
|
||||||
const style = getComputedStyle(probe)
|
|
||||||
const ctx = (fitRowLabels._ctx ||= document.createElement('canvas').getContext('2d'))
|
const ctx = (fitRowLabels._ctx ||= document.createElement('canvas').getContext('2d'))
|
||||||
ctx.font = `${style.fontWeight} ${style.fontSize} ${style.fontFamily}`
|
ctx.font = `${style.fontWeight} ${style.fontSize} ${style.fontFamily}`
|
||||||
|
|
||||||
// Indentation is real width: a tree label sits inside a flex container with
|
|
||||||
// the expand control beside it, so measure from the cell's left edge.
|
|
||||||
const padding = parseFloat(style.paddingLeft) + parseFloat(style.paddingRight)
|
const padding = parseFloat(style.paddingLeft) + parseFloat(style.paddingRight)
|
||||||
let widest = 0
|
|
||||||
|
// One width per row-header column, keyed by the rt-col-N the cell carries.
|
||||||
|
const widest = new Map()
|
||||||
for (const cell of cells) {
|
for (const cell of cells) {
|
||||||
|
const col = [...cell.classList]
|
||||||
|
.map(c => /^rt-col-(\d+)$/.exec(c))
|
||||||
|
.find(Boolean)
|
||||||
|
if (!col) continue
|
||||||
|
const idx = Number(col[1])
|
||||||
const text = (cell.textContent || '').trim()
|
const text = (cell.textContent || '').trim()
|
||||||
if (!text) continue
|
if (!text) continue
|
||||||
const indent = cell.querySelector('span.rt-tree-container')
|
// Tree indentation occupies real width, so it counts toward the fit.
|
||||||
? (parseFloat(getComputedStyle(cell.firstElementChild).paddingLeft) || 0)
|
const inner = cell.querySelector('span.rt-tree-container')
|
||||||
: 0
|
const indent = inner ? (parseFloat(getComputedStyle(inner).paddingLeft) || 0) : 0
|
||||||
widest = Math.max(widest, ctx.measureText(text).width + indent)
|
const w = ctx.measureText(text).width + indent
|
||||||
|
widest.set(idx, Math.max(widest.get(idx) ?? 0, w))
|
||||||
}
|
}
|
||||||
if (widest === 0) return
|
if (widest.size === 0) return
|
||||||
|
|
||||||
// A few px over, since canvas metrics and rendered text differ slightly with
|
const sizes = { ...grid.saveColumnSizes() }
|
||||||
// font fallback and letter-spacing.
|
for (const [idx, w] of widest) {
|
||||||
const width = Math.ceil(widest + padding + 8)
|
// A few px over: canvas metrics and rendered text differ slightly with font
|
||||||
|
// fallback and letter-spacing.
|
||||||
const { table: _t, ...cfg } = await viewer.save()
|
sizes[idx] = Math.ceil(w + padding + 8)
|
||||||
const pc = { ...(cfg.plugin_config || {}) }
|
}
|
||||||
pc.columns = { ...(pc.columns || {}) }
|
grid.restoreColumnSizes(sizes)
|
||||||
pc.columns.__ROW_PATH__ = { ...(pc.columns.__ROW_PATH__ || {}), column_size_override: width }
|
await grid.draw({ invalid_columns: true })
|
||||||
await viewer.restore({ ...cfg, plugin_config: pc })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const GRID_CSS = `
|
const GRID_CSS = `
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user