feat(custom-ui): developer citation demo over anchored metadata (SD-3199)#3370
feat(custom-ui): developer citation demo over anchored metadata (SD-3199)#3370caio-pizzol wants to merge 1 commit into
Conversation
Adds an end-to-end citation flow to the custom-ui demo, exercising every metadata.* method on a real Editor: - Selection popover gains a Cite button next to Comment. - Composer captures the selection (mirrors CommentComposer's pattern) and prompts for the customer-owned identity model: citationId, sourceId, displayText, optional locator. The payload makes explicit that the SDT w:tag is the document anchor key while citation identity is the customer's foreign key. - Citations sidebar tab lists every entry. Scroll-to uses metadata.resolve + ui.viewport.scrollIntoView. Edit reveals an inline form that calls metadata.update. Remove cleans the payload and the anchor. - Highlight overlay paints rects[] from ui.contentControls.getRect for each anchor; line-wrapped citations get per-line underlines. Two-step lookup: metadata id (w:tag) -> SDT node id via the contentControls slice. - Hover popover composes ui.viewport.entityAt + metadata.get, throttled to 60ms + RAF. No new public API surface. Validates the SD-3104 metadata stack against the customer-shaped flow.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ba77d03274
ℹ️ 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".
| if (!ui || !canPost || !capturedTarget) return; | ||
| setPosting(true); | ||
| setError(null); | ||
| const result = attach(capturedTarget, { |
There was a problem hiding this comment.
Guard unsupported selection targets before attaching citation
SelectionCapture.selectionTarget can represent cross-paragraph ranges, but metadata.attach rejects those targets and throws INVALID_TARGET in that case. This handler enables posting for any non-null capturedTarget and calls attach(...) directly, so selecting text across paragraph boundaries causes an uncaught exception (and leaves the composer in a broken posting state) instead of showing a validation message. Use the existing single-paragraph guard path (attachAtSelection/textTargetToSelectionTarget) or catch and map attach exceptions to setError.
Useful? React with 👍 / 👎.
|
Closing in favor of #3372 (SD-3208), the customer-shaped AI citation flow. After researching how Harvey / Legora / CoCounsel / Lexis+ surface citations, the manual select-text-then-fill-the-form pattern this demo showed is not how legal-AI products actually work; the model emits text plus citations and the human's role is verification. The data plumbing this demo exercised is already proven by the SD-3104 doc-api story in main ( Branch stays on the remote for now in case any of it needs to be referenced. |
Customer-facing citation demo built on the metadata.* contract from SD-3104. Customer-facing counterpart to the developer-shaped SD-3199 demo (superdoc-dev#3370, draft); both lean on the same anchored-metadata model. What this shows: - Generate draft with sources — mocked stand-in for a chat-driven RAG pipeline. Inserts a pre-canned paragraph and attaches citations to specific phrases. - Sources sidebar grouped by sourceId, showing source title, type, provider, deep link, and the cited locations within the document. - Hover popover with displayText, locator, excerpt, provider, confidence — the verification surface so a lawyer can trust the output without leaving the doc. - Highlight overlay on cited spans using getRect.rects, so line-wrapped citations get clean per-line underlines visible through the text. - Scroll-to, Edit, Remove per citation. All six metadata.* methods exercised. What this does not show: - The button is a stand-in for a chat-driven AI workflow, not the recommended product UX. A real integration plugs a chat panel + Insert into document action. - Generation is mocked. No LLM is wired. - Verification status is a render-time concern; external verification signals can change over time, so it is not persisted in the payload.
This PR is scoped as a developer integration demo for anchored metadata citations, not the customer-facing AI citation showcase.
It shows how to compose the primitives that landed in #3351:
editor.doc.metadata.*for attach, list, get, update, remove, and resolveui.contentControlsfor mapping an anchored metadata id (w:tag) to the painted content-control node idui.viewportfor hover hit-testing and scroll-to-source behaviorui.selectionfor selection capture in the developer-facing manual attach flowThe demo separates document anchoring from customer identity:
w:tagis SuperDoc's document anchor keycitationId/sourceIdin the JSON payload are customer-owned lookup keysThis remains useful for engineers integrating the metadata API, but it is not intended to model how legal AI citation products create citations. The customer-facing AI-generated citation showcase is tracked separately in SD-3205: mocked draft generation, source-backed excerpts, references grouped by source, and render-time verification signals.
Notes from the verification pass:
ui.contentControls.getRecttakes the SDT's PM node id, not thew:tag. The demo currently builds a tag-to-node-id map from the content-controls slice. This is useful evidence for a future metadata-specific geometry/hover convenience surface.modules.contentControls.builtInChromeopt-out work.superdoc/uideclaration resolution is unchanged. Verification for this PR is Vite/browser-based rather thantsc -b.