You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(ui): add ui.viewport.observe geometry-invalidation signal (SD-3311)
One "your cached getRect() coordinates may be stale, re-query" notification,
rAF-coalesced, payload { reason: 'layout'|'zoom'|'scroll'|'resize'|'mixed' }.
Sources: layout/pagination repaints (post-paint), zoom, and DOM scroll/resize.
The DOM scroll/resize listeners attach only while something is observing.
Lets overlays anchored via getRect re-query on a single signal instead of
hand-wiring scroll + resize + layout + zoom - which also fixes the cases that
wiring silently misses: reflow and zoom fire no scroll event.
Rewires the contract-templates field chip to use it. Before, zooming drifted
the chip ~230px because it only repositioned on scroll/resize/active-change.
Adds a demo regression (chip stays anchored after zoom) and viewport.observe
unit tests (coalescing, mixed reason, unsubscribe).
Copy file name to clipboardExpand all lines: apps/docs/editor/custom-ui/content-controls.mdx
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -40,16 +40,18 @@ The event tells you *what* is active; `getRect` tells you *where* to draw. `acti
40
40
| Read one control |`ui.contentControls.get({ id })`|
41
41
| Position your UI |`ui.contentControls.getRect({ id })`|
42
42
| Scroll a control into view |`ui.contentControls.scrollIntoView({ id })`|
43
+
| Re-anchor your UI when the page moves |`ui.viewport.observe(() => ...)`|
43
44
| Hover and right-click hit-testing |`ui.viewport.entityAt()` / `contextAt()`|
44
45
| Change content, tags, or locks |`editor.doc.contentControls.*`|
45
46
46
47
`active` is the innermost control. For nested controls (an inline field inside a block clause), `activePath` carries the full stack, innermost first, so you don't also need `observe()` just to read the nesting.
47
48
48
49
`scrollIntoView` resolves the control's position from the document, so it works even when the control is on a page that hasn't rendered yet (the page mounts, then scrolls). It scrolls only - it does not move the cursor into the control.
49
50
51
+
`ui.viewport.observe` is the single signal for "your `getRect()` coordinates may be stale, re-query": it fires (coalesced, once per frame) on scroll, resize, zoom, and layout reflow, so an overlay anchored with `getRect` stays glued without hand-wiring those events yourself.
52
+
50
53
## Current limits
51
54
52
-
- No geometry-change subscription. Re-read `getRect()` on scroll, resize, and the `pagination-update` / `zoomChange` events.
53
55
- No focus-by-id helper. Clicking a control in the document still drives selection.
0 commit comments