sliver_tree/_reorder_preview_engine library

Internal: paint-only make-room preview engine.

Holds per-nid Y offsets that open a gap at the prospective drop slot during a drag: rows after the vacated slot shift up, rows at/after the gap shift down, and the offsets are HELD until re-targeted or released. Deliberately a sibling of SlideAnimationEngine rather than an extension of it: the FLIP engine's model is "start at a delta, decay to zero, remove at settle", while a preview is the inverse, "start at zero, animate to a held non-zero target, persist". Grafting hold semantics onto the FLIP tick loop would entangle its composition, re-baseline and settle protocols; composing the two engines' deltas at the TreeController read surface keeps both simple.

Painted positions need NO render-layer changes for previews to work: every painted position, the painted-truth snapshot of VISIBLE rows (FLIP baselines!), painted-space hit testing and the overreach bound all read slide deltas through TreeController.getSlideDeltaNid / hasActiveSlides / composedSlideAbsDeltaBound, and those delegators compose slide + preview. Two carve-outs are named rather than accidental. LIFECYCLE decisions (the edge- and exit-ghost prune and paint gates, stale eviction, and RenderSliverTree.isNodeRetained's delta clause) read the FLIP-only accessors instead, because a HELD offset never goes idle and a composed read would suspend them for the length of a drag. And the exit ghost's painted-truth BASE reads TreeController.getHeldPreviewDeltaNid directly, because what it needs is the anchor's SETTLED position, which under a held preview is structural + preview (RenderSliverTree._exitGhostPaintedBaseScrollSpace). The free consequence is the seamless commit handoff: a FLIP baseline staged while a preview is held captures the SHIFTED painted positions; the commit clears the preview and mutates; the consume-time snapshot reads post-mutation structural positions, so rows that were previewing at their destination get near-zero FLIP deltas.

Same raw-Ticker rationale as the slide engine: ticks are the only place listeners fire, and Ticker.start never fires synchronously, so engine calls are legal from any phase. Paint-only: consumers route preview ticks to markNeedsPaint exactly like slide ticks (the composed hasActiveSlides makes that automatic).

Keyed by nid, not key: every caller sits below TreeController, which resolves keys once. Not exported from the package barrel.

Classes

ReorderPreviewEngine
Paint-only held-offset engine. See the library doc for how it composes with the FLIP engine.