Skip to content

feat(ui): viewport geometry-invalidation hook ui.viewport.observe (SD-3311)#3570

Merged
caio-pizzol merged 2 commits into
mainfrom
caio/sd-3311-viewport-observe
May 29, 2026
Merged

feat(ui): viewport geometry-invalidation hook ui.viewport.observe (SD-3311)#3570
caio-pizzol merged 2 commits into
mainfrom
caio/sd-3311-viewport-observe

Conversation

@caio-pizzol
Copy link
Copy Markdown
Contributor

Overlays anchored to a content control / comment / tracked change via ui.viewport.getRect have no way to know when those coordinates go stale, so today consumers hand-wire scroll + resize + layout + zoom listeners - and still miss cases. This adds one signal to listen to instead.

ui.viewport.observe(listener) fires (rAF-coalesced, once per frame) after anything that can move painted rectangles: layout/pagination repaints, zoom, and DOM scroll/resize. The payload is just { reason } - re-query getRect from the listener. The scroll/resize listeners attach only while something is observing.

A correction worth noting: scroll was never the problem - the field chip's capture-phase window listener already catches the editor's internal scroll. The real gap is layout reflow and zoom, which fire no scroll event. A probe confirmed it: zooming moved a control 230px while the chip stayed put. Because zoomChange fires before the re-paint, the hook tags the next post-paint layout flush as 'zoom' rather than notifying early with stale rects.

Rewires the contract-templates field chip to this single signal (dropping its hand-wired scroll/resize), which fixes the 230px zoom drift. The demo regression asserts the chip stays anchored after a zoom (red before, green after).

Verified: viewport.observe unit tests (coalescing / mixed / unsubscribe); contract-templates-chip-anchor 4/4 (no retries); pnpm check:types clean; pnpm check:public:superdoc 13/13; demo suite green

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).
@caio-pizzol caio-pizzol requested a review from a team as a code owner May 29, 2026 16:09
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 29, 2026

SD-3311

@github-actions
Copy link
Copy Markdown
Contributor

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20f684975d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/super-editor/src/ui/create-super-doc-ui.ts Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 6 files

Tip: cubic could auto-approve low-risk PRs like this, if it thinks it's safe to merge. Learn more

Re-trigger cubic

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

layoutUpdated and paginationUpdate are emitted back-to-back with the same
payload for the same paint (PresentationEditor.ts:6491-6492), so subscribing
geometry invalidation to both double-counted one repaint: a zoom coalesced to
'mixed' and the 'zoom' reason was unreachable. Subscribe to layoutUpdated only
- it covers every repaint. Adds regression coverage for the zoom and plain
layout reasons.
@caio-pizzol caio-pizzol merged commit 3bbdbe5 into main May 29, 2026
30 checks passed
@caio-pizzol caio-pizzol deleted the caio/sd-3311-viewport-observe branch May 29, 2026 16:29
@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 29, 2026

🎉 This PR is included in superdoc-cli v0.15.0

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 29, 2026

🎉 This PR is included in superdoc-sdk v1.14.0

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 29, 2026

🎉 This PR is included in @superdoc-dev/mcp v0.10.0

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 29, 2026

🎉 This PR is included in superdoc v1.38.0

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 29, 2026

🎉 This PR is included in @superdoc-dev/react v1.9.0

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 29, 2026

🎉 This PR is included in vscode-ext v2.10.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants