docs/solutions/logic-errors/2026-04-03-slate-v2-range-refs-must-be-transaction-aware-and-default-inward.md
The next seam after the projection proof was durable annotation anchors.
The tempting shortcut was obvious:
rangeRefThat would have been wrong twice.
The first honest v2 cut worked only after two decisions:
inwardTransaction awareness matters because slate-v2 already treats draft mutation as
private. If ref objects update eagerly while editor.children still points at
the previous committed snapshot, refs and document state drift out of alignment.
The fix was:
ref.current only at commitunref()inward wonLegacy Slate defaults rangeRef() to forward, even though Range.transform()
itself defaults to inward.
For persistent annotation anchors, forward is the wrong default.
inward is better because insertions at the range boundary do not casually
expand the anchored span. That matches the actual goal:
For Slate v2 durable anchors:
inward is the sane default for annotation-style range refsIf a ref design breaks commit alignment or defaults to boundary expansion for no good reason, it is carrying legacy baggage instead of solving the v2 problem.