extend
blockbounding-box-citations-blocksource: ok · hit
Bounding Box Citations
An extraction citation block linked to source PDF bounding boxes.
npx shadcn add "https://ui.extend.ai/r/bounding-box-citations-block.json"free
No selection tags yet — empty means no evidence, not lack of support.
Dependencies
Bundle weight · lightRegistry dependencies
@extend/bounding-box-citations@extend/pdf-block-resizable-shell@extend/pdf-viewer
Files1 · source cached 10/14/2026, 11:58:34 AM
registry/new-york-v4/blocks/bounding-box-citations-block.tsx
"use client"
import * as React from "react"
import {
findReviewField,
getMetadataLocation,
getReviewFieldLocation,
getReviewLocationKey,
HumanReviewHighlight,
HumanReviewPanel,
REVIEW_FIELDS,
type HumanReviewTheme,
type JsonValue,
type ReviewField,
type ReviewLocation,
type ReviewMetadataEntry,
} from "@/components/extend/bounding-box-citations"
import { PdfBlockResizableShell } from "@/components/extend/pdf-block-resizable-shell"
import { PDFViewer, type PDFViewerHandle } from "@/components/extend/pdf-viewer"
const DEFAULT_ZOOM = 1
export function HumanReviewBlock({
file,
fields = REVIEW_FIELDS,
className,
metadata,
resolveArrayItemMetadataPath,
resolveLocation,
showExpected = true,
theme,
}: {
file?: string
fields?: ReviewField[]
className?: string
metadata?: Record<string, ReviewMetadataEntry>
resolveArrayItemMetadataPath?: (
metadataPath: string,
rowIndex: number,
rowValue: JsonValue
) => string | undefined
resolveLocation?: (metadataPath: string) => ReviewLocation | undefined
showExpected?: boolean
theme?: HumanReviewTheme
}) {
const [activeFieldKey, setActiveFieldKey] = React.useState(fields[0]?.key)
const [hoverLocation, setHoverLocation] =
React.useState<ReviewLocation | null>(null)
const viewerRef = React.useRef<PDFViewerHandle>(null)
const hoverLocationKeyRef = React.useRef<string | null>(null)
const resolveFieldLocation = React.useCallback(
(metadataPath: string) =>
resolveLocation?.(metadataPath) ??
getMetadataLocation(metadata, metadataPath),
[metadata, resolveLocation]
)
const activeField = findReviewField(fields, activeFieldKey) ?? fields[0]
const activeLocation =
hoverLocation ?? getReviewFieldLocation(activeField, resolveFieldLocation)
if (!activeFieldKey && fields[0]) {
setActiveFieldKey(fields[0].key)
}
const focusField = React.useCallback(
(field: ReviewField) => {
if (field.key === activeFieldKey) return
setActiveFieldKey(field.key)
const location = getReviewFieldLocation(field, resolveFieldLocation)
if (location) {
viewerRef.current?.scrollToPageArea(location.page, location.area)
}
},
[activeFieldKey, resolveFieldLocation]
)
const handleLocationHover = React.useCallback((location?: ReviewLocation) => {
setHoverLocation(location ?? null)
const locationKey = getReviewLocationKey(location)
if (!location) {
hoverLocationKeyRef.current = null
return
}
if (locationKey === hoverLocationKeyRef.current) return
hoverLocationKeyRef.current = locationKey
viewerRef.current?.scrollToPageArea(location.page, location.area, {
behavior: "auto",
})
}, [])
return (
<PdfBlockResizableShell
autoSaveId="pdf-block-bounding-box-citations"
className={className}
rightDefaultSize={42}
rightMaxSize={60}
rightMinSize={30}
left={
<PDFViewer
ref={viewerRef}
src={file}
defaultZoom={DEFAULT_ZOOM}
renderPageOverlay={({ pageNumber }) =>
activeLocation?.page === pageNumber ? (
<HumanReviewHighlight location={activeLocation} />
) : null
}
/>
}
right={
<aside className="min-h-0 bg-background">
<HumanReviewPanel
fields={fields}
activeFieldKey={activeField?.key}
className="h-full min-h-0"
theme={theme}
showExpected={showExpected}
onFieldFocus={focusField}
onLocationHover={handleLocationHover}
resolveArrayItemMetadataPath={resolveArrayItemMetadataPath}
resolveLocation={resolveFieldLocation}
/>
</aside>
}
/>
)
}