"use client"; import { useState } from "react"; import { EntityModal } from "./entity-modal"; import { FmBboxThumb } from "./fm/bbox-thumb"; import { FmChip } from "./fm/badges"; export interface Match { entity_id: string; class: string; alias_matched: string; start: number; end: number; } interface ReaderContentProps { ocr: string; matches: Match[]; imagesDetected?: Array<{ bbox?: { x: number; y: number; w: number; h: number }; image_type?: string; caption_ocr?: string; local_image_index?: number; }>; docId: string; pageNum: number; } interface Segment { text: string; match?: Match; } function segmentText(text: string, matches: Match[]): Segment[] { if (!matches || matches.length === 0) return [{ text }]; const sorted = [...matches].sort((a, b) => a.start - b.start); const segs: Segment[] = []; let cursor = 0; for (const m of sorted) { if (m.start < cursor) continue; if (m.start > cursor) segs.push({ text: text.slice(cursor, m.start) }); segs.push({ text: text.slice(m.start, m.end), match: m }); cursor = m.end; } if (cursor < text.length) segs.push({ text: text.slice(cursor) }); return segs; } export function ReaderContent({ ocr, matches, imagesDetected = [], docId, pageNum }: ReaderContentProps) { const [modalEntity, setModalEntity] = useState<{ cls: string; id: string } | null>(null); const segments = segmentText(ocr, matches); return ( <>
{segments.map((seg, i) =>
seg.match ? (
setModalEntity({ cls: seg.match!.class, id: seg.match!.entity_id })}
role="button"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
setModalEntity({ cls: seg.match!.class, id: seg.match!.entity_id });
}
}}
title={`${seg.match.class}/${seg.match.entity_id}`}
>
{seg.text}
) : (
{seg.text}
),
)}
{imagesDetected.length > 0 && (