docs/solutions/logic-errors/2026-04-03-slate-react-v2-projection-proof-must-split-range-semantics-from-react-overlay-store.md
The first honest decorations and annotation-anchor proof for slate-react-v2
looked like it wanted one big new subsystem.
That was the trap.
There are two different jobs here:
Range into local text slices keyed by runtime idTrying to do both in one package boundary would have recreated the old blur:
slate-v2 would start owning render-time overlay stateslate-react-v2 would start guessing document semanticsThe proof became clean only after the seam was split explicitly:
slate-v2 owns pure range semantics:
Editor.projectRange(editor, range)slate-react-v2 owns the overlay projection runtime:
createSlateProjectionStore(editor, source)useSlateProjections(runtimeId)The source function stays logical:
refresh()The store then projects those logical ranges into local per-runtime-id slices.
This cut fixes the actual slate-react pain instead of hiding it:
It also keeps the next step obvious:
For Slate overlay architecture:
If a decorations or annotations design cannot say those three lines cleanly, it is not done.