A virtual list that scrolls with the window: it draws the rows in view of
the document's viewport, and spacers as tall as the rest, so a list of
thousands below a header and above a footer costs what thirty rows do,
while the page keeps its own scrolling. Nothing in it scrolls: the
browser restores the document's offset on back and reload, a sticky
header above it sticks, and the page's keys (Space, End) move it.
top is how far the viewport's top is past the list's, so content above
the list, or growing above it, is read every time and never assumed. A
row's height is its border box, measured once drawn; until then it is
estimatedHeight, or with unmeasured: 'mean' the mean of the rows
measured. A row is drawn display: flow-root, so space rows with
padding, not margins. @foldkit/ui's VirtualList is the list in a box
of its own.
A server's page can open the list at a row (init({ from })): its window
starts there, and the rows above it take no room until Track places the
list, which gives them their room and scrolls the window by as much, so
the row stays where the reader saw it. A page without scripts draws that
window in the page's flow (Recipes.WindowList hides the spacers) and
pages by links (pageOf).
The rows drawn and the rows to open next, for links that page a list
without scripts (?from=): previous is the first row whose window
reaches this one's start, next this one's end; none at either end of
the list.
Track resolved with reading, for a Scene test of a page that draws the
list: the reading goes through the view's own onMessage, as it does when
the Mount reports, so the page's update receives its own Message.
Scene.Mount.resolveAll(WindowList.resolveTrack(onMessage, WindowList.Message.Placed({ top: 0, height: 900 }))).
The list's one Mount, on its root: where the viewport lies over the list
(WindowViewport, as Placed) and the heights of the rows drawn
(MeasureRows, as Measured). A failure in either ends both, reported
as this Mount's. Before either reads, it gives the rows above a list opened
at a row their room. A Scene test resolves it with resolveTrack.
The rows drawn, [start, end): those the viewport overlaps, and
overscan more at each end; until a list opened at a row is placed, the
rows from that one. Keep keys between calls: the offsets are cached by
its identity.