schedgrid/dom
Bind a scroll container to the engine and hit-test pointer events.
import { bindScrollElement, viewportPoint } from 'schedgrid/dom';bindScrollElement(grid, element, options?)
Wires a scroll container to the engine in both directions and returns the unbind function.
- element → grid.
scrollevents becomesetScrolland size changes (throughResizeObserver) becomesetViewport, both read once up front. - grid → element. When something else moves the grid's scroll (a canvas
twin handling wheel events, a "scroll to today" button), the element
follows. The resulting
scrollevent reports the same offset, whichsetScrollignores by value, so the loop closes without a guard flag.
On bind the grid wins: the element is moved to the grid's current scroll
offset rather than asked where it is. That is what makes createGrid's
scroll option survive being bound to an element, and what carries the
offset across a rebind onto a fresh element. If the element clamps the write
to its own maximum, the grid adopts the clamped value.
const unbind = bindScrollElement(grid, scroller);
// later
unbind();Prop
Type
The binder only needs a slice of HTMLElement, so it can drive any
scrollable and be stubbed in tests without a DOM:
Prop
Type
viewportPoint(element, event)
Pointer position relative to the scroll container's padding box, which is
the viewport space grid.indexAt and grid.cellAt expect.
scroller.addEventListener('pointermove', (e) => {
const cell = grid.cellAt(viewportPoint(scroller, e));
// { row, column } or null outside the content
});Pinned bands are resolved before scroll is applied, so a pointer over the header row reports the header row wherever the user has scrolled.