Skip to content

feat(ui): add ui.viewport.getHost and positionAt (SD-2943)#3157

Merged
caio-pizzol merged 4 commits intomainfrom
caio/sd-2943-viewport-host-positionat
May 5, 2026
Merged

feat(ui): add ui.viewport.getHost and positionAt (SD-2943)#3157
caio-pizzol merged 4 commits intomainfrom
caio/sd-2943-viewport-host-positionat

Conversation

@caio-pizzol
Copy link
Copy Markdown
Contributor

Two primitives the custom-UI demo (and external consumers) keep reaching for and not finding:

ui.viewport.getHost(): HTMLElement | null returns the editor's painted host element. Custom UI components attach contextmenu / hover / drag listeners to this element instead of document + a fragile closest('.editor-shell') filter against a class name the consumer happens to control. The information already exists on presentationEditor.visibleHost; this just lifts it onto the public controller.

ui.viewport.positionAt({ x, y }): ViewportPositionHit | null resolves a viewport coordinate to a caret position on the routed editor's PM document. Returns both point: SelectionPoint and target: SelectionTarget (a collapsed selection at the click) so consumers pass whichever shape their downstream editor.doc.* call needs. The natural pair to entityAt: while entityAt answers "what entity is under this point?", positionAt answers "what caret position is under this point?" — the missing primitive that lets right-click menus offer Paste here / Insert at this point honestly, instead of dispatching against the user's previous selection somewhere else in the doc.

Both methods scope to the controller's painted host. Multi-instance pages can't leak across controllers; post-destroy calls return null. The structural type for presentationEditor gains the corresponding posAtCoords shape so the controller doesn't need a cast.

First of three SD-2936 follow-ups. SD-2945 (auto-pass click context to context-menu commands) depends on this; SD-2944 (disableContextMenu semantics) is independent and can land in parallel.

Verified: pnpm exec vitest run src/ui → 252 passed (16 files, +4 new); pnpm exec tsc -b tsconfig.references.json → clean.

Two primitives consumers building custom UI keep reaching for and not
finding on the public surface:

ui.viewport.getHost() returns the editor's painted host element so
custom-UI components scope DOM listeners to the editor without a CSS
class filter. The information already lives on
presentationEditor.visibleHost; this lifts it onto the controller.

ui.viewport.positionAt({ x, y }) resolves a viewport coordinate to a
caret position on the routed editor's PM document, returning both the
SelectionPoint and the SelectionTarget shapes so consumers can pass
the result straight to editor.doc.insert / replace / etc. The natural
pair to entityAt: while entityAt answers "what entity is under this
point?", positionAt answers "what caret position is under this
point?" — the missing primitive that lets right-click menus offer
"Paste here" / "Insert at this point" honestly, instead of dispatching
against the user's previous selection.

Both methods scope to the controller's painted host: a multi-instance
page can't have one controller's positionAt return positions in
another's PM doc, and post-destroy calls return null.

Tests cover the happy path, the no-editor-mounted case, and the
missing-posAtCoords stub case.
@caio-pizzol caio-pizzol requested a review from a team as a code owner May 5, 2026 13:41
@linear
Copy link
Copy Markdown

linear Bot commented May 5, 2026

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: fe79026a83

ℹ️ 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/position-at.ts Outdated
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

caio-pizzol and others added 3 commits May 5, 2026 11:59
…-2943)

readBlockId now uses the sdBlockId ?? id ?? blockId fallback the
selection resolver already applies, so positionAt resolves paragraph
clicks instead of returning null. Adds PresentationEditor.getActiveStoryLocator
(unifies story-session and header/footer-session locators) and threads
the result onto SelectionPoint.story / SelectionTarget.story so doc-api
operations route to the active story instead of falling back to body.
@caio-pizzol caio-pizzol merged commit 3b6900a into main May 5, 2026
67 checks passed
@caio-pizzol caio-pizzol deleted the caio/sd-2943-viewport-host-positionat branch May 5, 2026 16:31
@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 5, 2026

🎉 This PR is included in vscode-ext v2.3.0-next.98

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 5, 2026

🎉 This PR is included in @superdoc-dev/mcp v0.3.0-next.54

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 5, 2026

🎉 This PR is included in @superdoc-dev/react v1.2.0-next.96

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 5, 2026

🎉 This PR is included in superdoc-cli v0.8.0-next.72

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 5, 2026

🎉 This PR is included in superdoc-sdk v1.8.0-next.55

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 5, 2026

🎉 This PR is included in superdoc v1.30.0-next.55

The release is available on GitHub release

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