Find the datagrid by asking the DOM, not by guessing the nesting

The rule was injected into perspective-viewer-datagrid's shadow root, which
is not where the cells live, so it applied to nothing and the grand-total
column stayed visible.

Locates regular-table by walking through shadow roots and injects into
whatever root contains it, via getRootNode(). That makes no assumption about
how the plugin nests -- which is the assumption that was wrong, and the kind
that breaks on a Perspective upgrade anyway.

The grid is built asynchronously after load, so hideSplitTotal now reports
whether it found anything and is retried once on a short delay, as well as
from the config-update handler.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Trowbridge 2026-09-17 13:06:28 -04:00
parent 484798cac5
commit ebe0288202

View File

@ -659,7 +659,7 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
// the named table in time.
await viewer.load(tableRef.current)
viewer.setAttribute('theme', dark ? 'Pro Dark' : 'Pro Light')
hideSplitTotal()
if (!hideSplitTotal()) setTimeout(hideSplitTotal, 400)
// restore last-used layout or build default
// Strip cfg.table table is already loaded by reference above; a stale name
@ -841,15 +841,36 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
}
`
// Find the grid wherever it is. Guessing the nesting was wrong once already --
// the plugin element's own shadow root is not where the cells live -- so locate
// regular-table by walking through shadow roots, then inject into whatever root
// actually contains it via getRootNode(). No structural assumption survives a
// Perspective upgrade; this one asks the DOM instead.
function deepFindRegularTable(node, depth = 0) {
if (!node || depth > 12) return null
if (node.tagName === 'REGULAR-TABLE') return node
for (const child of node.children || []) {
const hit = deepFindRegularTable(child, depth + 1)
if (hit) return hit
}
if (node.shadowRoot) return deepFindRegularTable(node.shadowRoot, depth + 1)
return null
}
function hideSplitTotal() {
const viewer = viewerRef.current
const root = viewer?.shadowRoot
?.querySelector('perspective-viewer-datagrid')?.shadowRoot
if (!root || root.getElementById?.('pf-hide-split-total')) return
if (!viewer) return
const grid = deepFindRegularTable(viewer)
// The grid is built asynchronously after load, so it may not exist yet.
// Retried from the config-update handler, and once on a short delay.
if (!grid) return false
const root = grid.getRootNode()
if (!root || root.querySelector?.('#pf-hide-split-total')) return true
const style = document.createElement('style')
style.id = 'pf-hide-split-total'
style.textContent = HIDE_SPLIT_TOTAL_CSS
root.appendChild(style)
;(root.appendChild ? root : document.head).appendChild(style)
return true
}
// Row depth is a ViewConfig field, so it is set through restore() rather than