v0.4.3
Fixed
Block toolbars no longer cost work on every scroll frame. Every code, diagram, and table toolbar registered its own capturing window scroll listener and requested an animation frame per scroll event. Each frame measured its block with getBoundingClientRect and called classList.add or classList.remove — for every block on the page, on screen or not, whether or not the state changed. DOMTokenList add and remove rewrite the class attribute even when the token is already in the requested state, so each block produced a layout read and a mutation record per frame. A host scrolling a 64k px transcript measured ~600 mutation records and ~2,000 rect reads per second from toolbars alone; afterwards the same scroll measured 9 mutation records per second.
watchStickyHeader replaces the per-block listeners:
- one shared
IntersectionObservertracks which blocks are on screen; an off-screen block cannot span the toolbar band, so it is cleared and never measured; - one capturing scroll/resize listener is attached only while some block is on screen;
- each pass reads every on-screen block before writing any class, so a frame lays out once;
- the
scrollclass is toggled only when the stuck state flips.
Without IntersectionObserver, every block counts as on screen (the previous behaviour, without the redundant writes).
Compatibility
No API change. The toolbar's scroll class keeps its meaning and thresholds; onViewportScroll stays exported. Patch release.