Repository navigation
UN-4504 [DEV] Add v1 PDF highlight layer and highlight normalisers - #2407
muhammad-ali-e wants to merge 13 commits into
Conversation
- lib/pdf/highlights turns every producer's shape into one Highlight
{id, page, x, y, w, h, variant, tone, confidence?}, in fractions of
the page box, so highlights hold their place at any zoom:
- LLMWhisperer line_metadata lines, with line confidence read by type
- word boxes, both as a separate list (confidence_metadata) and as the
5th element the agentic table worker sends with page_width; without
page_width, x comes from the PDF page's aspect ratio rather than
v0's division by page height
- Agentic Prompt Studio percentage boxes
Padding, zero-size and junk entries are dropped, and boxes are clamped
to the page. A box spanning the page reads as a line.
- HighlightLayer draws a page's highlights in default, active and
low-confidence tones, as buttons reporting onHighlightClick when a
handler is given.
- PdfPageList takes highlights, activeHighlightId and onHighlightClick
and hands each memoised page only its own highlights.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R7trgcAzu6jxDnit3eeozm
|
The failing hook is There's no fix to port yet. The fix is a one-line change on #2399: Generated by Claude Code |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R7trgcAzu6jxDnit3eeozm
# Conflicts: # frontend/src/v1/components/patterns/document-viewer/PdfPage.tsx
# Conflicts: # frontend/src/v1/components/patterns/document-viewer/PdfPageList.test.tsx
[Medium impact] The PR appears safe to merge; no new actionable issues were found.
|
praveen-formido
left a comment
There was a problem hiding this comment.
Highlights and normalisers. Two correctness items in highlights.ts (duplicate ids across lines, hasMetadata dropped) and one token/theme item on HighlightLayer: mix-blend-multiply over ui:bg-card is invisible in the dark theme until the canvas paints. The rest are smaller.
One upstream note, not for this PR: the cloud agentic_extraction worker emits a top y where agentic_table emits a baseline, and the cloud transformHighlightData subtracts the height again. That predates this stack, but it will surface here once the cloud plugin feeds these normalisers.
# Conflicts: # frontend/src/v1/components/patterns/document-viewer/PdfPage.tsx # frontend/src/v1/components/patterns/document-viewer/PdfPageList.tsx
…d-only blend, per-page active id - normaliseWords puts the line's page and position in the default id, so words on different lines no longer share ids. - Line entries keep their confidence for the label but are not toned; v0 never toned lines, and line confidence on scans sits below 0.9. - Warn with the page index when word boxes are dropped for want of a page width. - Highlights use mix-blend-multiply only once the page canvas holds a picture, so they stay visible on the dark placeholder. - Only the page holding the active highlight receives its id, so moving it re-renders two pages, not all of them. - HighlightLayer builds the style and data props once for both branches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R7trgcAzu6jxDnit3eeozm
|



What
lib/pdf/highlights.ts: normalisers that turn every highlight shape our backends send into oneHighlighttype.components/patterns/document-viewer/HighlightLayer.tsx: draws a page's highlights.PdfPageListnow takeshighlights,activeHighlightIdandonHighlightClick.This is part of the v1 DocumentViewer (P1-T21, UN-4390).
Why
Prompt Studio, HITL, Agentic Prompt Studio and the agentic table each send highlights in a different shape, and v0 decoded them in three places. In v1 the viewer gets one shape, and the decoding lives in one tested module.
How
Highlightshape:{id, page, x, y, w, h, variant: "line" | "box", tone: "default" | "active" | "low-confidence", confidence?}.[page, base_y, height, page_height, line_confidence?]):base_y - heighttobase_y, full width.normaliseWords(line, words)takes LLMWhispererconfidence_metadataas a separate list, rather than appending it to the line as v0 HITL did.normaliseLinestill reads the appended form. The appended form isn't dead code: the agentic table worker sends[page, y, h, 792, {offset, width, page_width}]today (seeEXPECTED_COORDSinworkers/plugins/agentic_table/tests/test_highlight_data.py).page_widthis present it's used. Otherwise x comes from the PDF page's aspect ratio:page_height × pdfWidth / pdfHeight. v0 divided by the page height, which puts word boxes too far left on portrait pages. There's a regression test for this.[page, left%, top%, width%, height%, hasMetadata]): divided by 100.[0, 0, 0, 0]), zero-size and junk entries are dropped.line, so a full-width "word" from the agentic table doesn't look like a word box.lowConfidenceBelow.HighlightLayer:primaryfor default and active (active adds a ring),destructivefor low confidence. Highlights use multiply blending.onHighlightClick, each highlight is a labelled button (e.g. "Highlight on page 1, 62% confidence"), witharia-currenton the active one and the v1 focus ring. Without a handler, highlights are plain non-interactive boxes.pointer-events-none, so only the highlights themselves take clicks.PdfPageList: groups highlights by page once and passes each memoisedPdfPageonly its own stable array. Scrolling therefore doesn't re-render every page.Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)
src/v1/. Nothing in v0 imports it, and v0's highlight code is unchanged.Database Migrations
Env Config
Relevant Docs
Related Issues or PRs
Dependencies Versions
Notes on Testing
bun run typecheck:v1,lint:v1andtest:v1pass (99 unit tests, 56 boundary fixtures).biome ci src/shows no errors.EXPECTED_COORDS, includingpage_widthtaking priority over the aspect ratiotransformHighlightDataoutputonHighlightClickwith the highlightScreenshots
Checklist
I have read and understood the Contribution Guidelines.
Generated by Claude Code