feat(ui): add ui.viewport.getHost and positionAt (SD-2943)#3157
feat(ui): add ui.viewport.getHost and positionAt (SD-2943)#3157caio-pizzol merged 4 commits intomainfrom
Conversation
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.
There was a problem hiding this comment.
💡 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".
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…-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.
|
🎉 This PR is included in vscode-ext v2.3.0-next.98 |
|
🎉 This PR is included in @superdoc-dev/mcp v0.3.0-next.54 The release is available on GitHub release |
|
🎉 This PR is included in @superdoc-dev/react v1.2.0-next.96 The release is available on GitHub release |
|
🎉 This PR is included in superdoc-cli v0.8.0-next.72 The release is available on GitHub release |
|
🎉 This PR is included in superdoc-sdk v1.8.0-next.55 |
|
🎉 This PR is included in superdoc v1.30.0-next.55 The release is available on GitHub release |
Two primitives the custom-UI demo (and external consumers) keep reaching for and not finding:
ui.viewport.getHost(): HTMLElement | nullreturns the editor's painted host element. Custom UI components attachcontextmenu/ hover / drag listeners to this element instead ofdocument+ a fragileclosest('.editor-shell')filter against a class name the consumer happens to control. The information already exists onpresentationEditor.visibleHost; this just lifts it onto the public controller.ui.viewport.positionAt({ x, y }): ViewportPositionHit | nullresolves a viewport coordinate to a caret position on the routed editor's PM document. Returns bothpoint: SelectionPointandtarget: SelectionTarget(a collapsed selection at the click) so consumers pass whichever shape their downstreameditor.doc.*call needs. The natural pair toentityAt: whileentityAtanswers "what entity is under this point?",positionAtanswers "what caret position is under this point?" — the missing primitive that lets right-click menus offerPaste here/Insert at this pointhonestly, 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 forpresentationEditorgains the correspondingposAtCoordsshape 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 (
disableContextMenusemantics) 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.