@arbidocs/react 0.5.119 → 0.5.120
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-K6ELFSG6.cjs → chunk-AJRYZ3IC.cjs} +3 -3
- package/dist/{chunk-K6ELFSG6.cjs.map → chunk-AJRYZ3IC.cjs.map} +1 -1
- package/dist/{chunk-Z3W4XFWB.cjs → chunk-C72FSQUE.cjs} +3 -3
- package/dist/{chunk-Z3W4XFWB.cjs.map → chunk-C72FSQUE.cjs.map} +1 -1
- package/dist/{chunk-LBAG7KL7.cjs → chunk-KDYYAZXP.cjs} +105 -29
- package/dist/chunk-KDYYAZXP.cjs.map +1 -0
- package/dist/document-tools/core.cjs +80 -80
- package/dist/document-tools/index.cjs +80 -80
- package/dist/entities/SharingEntity.js +85 -0
- package/dist/entities/SharingEntity.js.map +7 -0
- package/dist/entities/index.js +8 -0
- package/dist/entities/index.js.map +2 -2
- package/dist/index.cjs +294 -282
- package/dist/{index.d-CYXcTKYt.d.ts → index.d-DYlUprG9.d.ts} +31 -1
- package/dist/index.d.ts +11 -2
- package/dist/shell/index.cjs +37 -37
- package/dist/ui/index.cjs +166 -154
- package/dist/ui/index.d.ts +1 -1
- package/dist/viewers/index.cjs +2 -1
- package/dist/viewers/index.cjs.map +1 -1
- package/dist/viewers/index.d.ts +4 -0
- package/dist/viewers/useProcessedChunks.js +2 -1
- package/dist/viewers/useProcessedChunks.js.map +2 -2
- package/package.json +3 -3
- package/dist/chunk-LBAG7KL7.cjs.map +0 -1
package/dist/ui/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ARBI_MARK_SRC, a as AgentBadge, b as AiMarkdown, c as ArbiIcon, d as Avatar, e as AvatarFallback, f as AvatarImage, B as BASE_COLORS, g as Badge, h as BadgeProps, i as Button, j as ButtonProps, C as COLUMN_LABEL_FALLBACKS, k as Card, l as CardContent, m as CardDescription, n as CardFooter, o as CardHeader, p as CardProps, q as CardTitle, r as Checkbox, s as Collapsible, t as CollapsibleContent, u as CollapsibleTrigger, v as Command, w as CommandDialog, x as CommandEmpty, y as CommandGroup, z as CommandInput, D as CommandItem, E as CommandList, F as CommandSeparator, G as CommandShortcut, H as DEFAULT_METADATA_TAGS, I as DebouncedInput, J as DebouncedInputProps, K as Dialog, L as DialogClose, M as DialogContent, N as DialogDescription, O as DialogFooter, P as DialogHeader, Q as DialogOverlay, R as DialogPortal, S as DialogPresentation, T as DialogTitle, U as DialogTrigger, V as DictateContextValue, W as DocumentEntity, X as DocumentEntityProps, Y as DocumentLike, Z as DropdownMenu, _ as DropdownMenuCheckboxItem, $ as DropdownMenuContent, a0 as DropdownMenuGroup, a1 as DropdownMenuItem, a2 as DropdownMenuLabel, a3 as DropdownMenuPortal, a4 as DropdownMenuRadioGroup, a5 as DropdownMenuRadioItem, a6 as DropdownMenuSeparator, a7 as DropdownMenuShortcut, a8 as DropdownMenuSub, a9 as DropdownMenuSubContent, aa as DropdownMenuSubTrigger, ab as DropdownMenuTrigger, ac as ENTITY_MAPPINGS, ad as EntityIcon, ae as EntityIconComponent, af as EntityLabelForm, ag as EntityNoun, ah as EntityPill, ai as EntityRegistryOverride, aj as EntitySize, ak as EntityType, al as EntityVocabulary, am as FileTypeIcon, an as FolderTreeNode, ao as FormatRelativeTimeOptions, ap as HoverCard, aq as HoverCardContent, ar as HoverCardTrigger, as as IconToggle, at as IconToggleProps, au as IdentityBusy, av as IdentityProblem, aw as IdentityPurchase, ax as IdentityState, ay as IdentityStatus, az as IdentityStep, aA as IdentityVerificationFlow, aB as Input, aC as InputProps, aD as Label, aE as MarkMenu, aF as MarkMenuItem, aG as MarkMenuProps, aH as MarkdownCode, aI as MarkdownLink, aJ as MarkdownRenderer, aK as MarkdownRendererProps, aL as MarkdownStreamingContext, aM as NEUTRAL_GRAY, aN as PLACEHOLDER_COLOR, aO as PassageCard, aP as PassageCardProps, aQ as Popover, aR as PopoverAnchor, aS as PopoverClose, aT as PopoverContent, aU as PopoverTrigger, aV as PortalContainerProvider, aW as PresenceDisplayStatus, aX as PresenceLabel, aY as Progress, aZ as ProjectEntity, a_ as ProjectEntityProps, a$ as ProjectRelation, b0 as ProviderIcon, b1 as RadioGroup, b2 as RadioGroupItem, b3 as Rag, b4 as
|
|
1
|
+
export { A as ARBI_MARK_SRC, a as AgentBadge, b as AiMarkdown, c as ArbiIcon, d as Avatar, e as AvatarFallback, f as AvatarImage, B as BASE_COLORS, g as Badge, h as BadgeProps, i as Button, j as ButtonProps, C as COLUMN_LABEL_FALLBACKS, k as Card, l as CardContent, m as CardDescription, n as CardFooter, o as CardHeader, p as CardProps, q as CardTitle, r as Checkbox, s as Collapsible, t as CollapsibleContent, u as CollapsibleTrigger, v as Command, w as CommandDialog, x as CommandEmpty, y as CommandGroup, z as CommandInput, D as CommandItem, E as CommandList, F as CommandSeparator, G as CommandShortcut, H as DEFAULT_METADATA_TAGS, I as DebouncedInput, J as DebouncedInputProps, K as Dialog, L as DialogClose, M as DialogContent, N as DialogDescription, O as DialogFooter, P as DialogHeader, Q as DialogOverlay, R as DialogPortal, S as DialogPresentation, T as DialogTitle, U as DialogTrigger, V as DictateContextValue, W as DocumentEntity, X as DocumentEntityProps, Y as DocumentLike, Z as DropdownMenu, _ as DropdownMenuCheckboxItem, $ as DropdownMenuContent, a0 as DropdownMenuGroup, a1 as DropdownMenuItem, a2 as DropdownMenuLabel, a3 as DropdownMenuPortal, a4 as DropdownMenuRadioGroup, a5 as DropdownMenuRadioItem, a6 as DropdownMenuSeparator, a7 as DropdownMenuShortcut, a8 as DropdownMenuSub, a9 as DropdownMenuSubContent, aa as DropdownMenuSubTrigger, ab as DropdownMenuTrigger, ac as ENTITY_MAPPINGS, ad as EntityIcon, ae as EntityIconComponent, af as EntityLabelForm, ag as EntityNoun, ah as EntityPill, ai as EntityRegistryOverride, aj as EntitySize, ak as EntityType, al as EntityVocabulary, am as FileTypeIcon, an as FolderTreeNode, ao as FormatRelativeTimeOptions, ap as HoverCard, aq as HoverCardContent, ar as HoverCardTrigger, as as IconToggle, at as IconToggleProps, au as IdentityBusy, av as IdentityProblem, aw as IdentityPurchase, ax as IdentityState, ay as IdentityStatus, az as IdentityStep, aA as IdentityVerificationFlow, aB as Input, aC as InputProps, aD as Label, aE as MarkMenu, aF as MarkMenuItem, aG as MarkMenuProps, aH as MarkdownCode, aI as MarkdownLink, aJ as MarkdownRenderer, aK as MarkdownRendererProps, aL as MarkdownStreamingContext, aM as NEUTRAL_GRAY, aN as PLACEHOLDER_COLOR, aO as PassageCard, aP as PassageCardProps, aQ as Popover, aR as PopoverAnchor, aS as PopoverClose, aT as PopoverContent, aU as PopoverTrigger, aV as PortalContainerProvider, aW as PresenceDisplayStatus, aX as PresenceLabel, aY as Progress, aZ as ProjectEntity, a_ as ProjectEntityProps, a$ as ProjectRelation, b0 as ProviderIcon, b1 as RadioGroup, b2 as RadioGroupItem, b3 as Rag, b4 as SHARING_LABELS, b5 as ScrollArea, b6 as ScrollBar, b7 as Select, b8 as SelectContent, b9 as SelectGroup, ba as SelectItem, bb as SelectLabel, bc as SelectScrollDownButton, bd as SelectScrollUpButton, be as SelectSeparator, bf as SelectTrigger, bg as SelectValue, bh as Separator, bi as SharingEntity, bj as SharingEntityProps, bk as ShieldIcon, bl as ShieldIconProps, bm as Slider, bn as StatusBadgeComponent, bo as StatusBadgeProps, bp as StatusPill, bq as StatusPillProps, br as StatusVariant, bs as Switch, bt as TAG_TYPE_ICONS, bu as TAG_TYPE_LABELS, bv as Table, bw as TableBody, bx as TableCaption, by as TableCell, bz as TableFooter, bA as TableHead, bB as TableHeader, bC as TableRow, bD as Tabs, bE as TabsContent, bF as TabsList, bG as TabsTrigger, bH as TagEntity, bI as TagEntityProps, bJ as TagLike, bK as Textarea, bL as TextareaProps, bM as ThreadVisibilityIcon, bN as Toggle, bO as ToggleGroup, bP as ToggleGroupItem, bQ as Tooltip, bR as TooltipContent, bS as TooltipProvider, bT as TooltipTrigger, bU as UserEntity, bV as UserEntityProps, bW as UserMenu, bX as UserMenuItem, bY as UserMenuProps, bZ as UserMenuStatus, b_ as VISIBILITY_ICONS, b$ as VerifiedBadge, c0 as VerifiedBadgeProps, c1 as VerifiedToggle, c2 as VisibilityIcon, c3 as VisibilityToggle, c4 as VisibilityToggleProps, c5 as agentAvatarColors, c6 as badgeVariants, c7 as buildFolderTree, c8 as buttonVariants, c9 as canonicalFolderPath, ca as cardVariants, cb as closeOpenEmphasis, cc as cn, cd as configureEntityRegistry, ce as configureEntityVocabulary, cf as configureRagLabels, cg as configureSharingMembers, ch as configureStatusRegistry, ci as createUserAvatarIcon, cj as entityNoun, ck as extensionFromMime, cl as formatCompactLastSeen, cm as formatDocDate, cn as formatFolderLabel, co as formatFriendlyDate, cp as formatRelativeTime, cq as friendlyFileType, cr as getDocIcon, cs as getDocumentAuthor, ct as getDocumentDate, cu as getDocumentNature, cv as getDocumentSubject, cw as getDocumentTitle, cx as getEntityColor, cy as getEntityColorStyles, cz as getEntityIcon, cA as getEntityLabel, cB as getFileExtension, cC as getFileTypeIcon, cD as getStatusVariant, cE as getTagTypeIcon, cF as getTagTypeLabel, cG as getUserAvatarColor, cH as getUserDisplayName, cI as getUserInitials, cJ as getWorkspaceColor, cK as isAgent, cL as isAudioFile, cM as isDocumentAddableToConversation, cN as isDownloadOnlyFile, cO as isImageDocument, cP as isImageFile, cQ as isMediaFile, cR as isVideoFile, cS as markdownBaseComponents, cT as markdownSanitizeSchema, cU as markdownToPlainText, cV as markdownToPlainTextBlocks, cX as splitMarkdownBlocks, cY as tagKindNouns, cZ as tagKindTitle, c_ as toggleVariants, c$ as trimOpenCitation, d0 as useDictateContext, d1 as usePortalContainer, d2 as usesOriginalBytesForViewer } from '../index.d-DYlUprG9.js';
|
|
2
2
|
export { L as LazyChunk, l as lazyChunk, a as lazyComponent, p as preloadChunks } from '../lazy-chunk.d-B6YDLMKI.js';
|
|
3
3
|
import 'clsx';
|
|
4
4
|
import 'react';
|
package/dist/viewers/index.cjs
CHANGED
|
@@ -220,7 +220,8 @@ function useProcessedChunks(chunks, footnotes) {
|
|
|
220
220
|
content: hasFootnotes ? inlineFootnotes(chunk.content, footnotes) : chunk.content,
|
|
221
221
|
chunkIndex: chunk.metadata?.chunk_doc_idx,
|
|
222
222
|
chunkExtId: chunk.metadata?.chunk_ext_id,
|
|
223
|
-
docTitle: chunk.metadata?.doc_title ?? void 0
|
|
223
|
+
docTitle: chunk.metadata?.doc_title ?? void 0,
|
|
224
|
+
pageBbox: chunk.metadata?.page_bbox ?? void 0
|
|
224
225
|
});
|
|
225
226
|
});
|
|
226
227
|
if (currentPageChunks.length > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/viewers/DocxViewer.tsx","../../src/viewers/XlsxViewer.tsx","../../src/viewers/useProcessedChunks.ts","../../src/viewers/selection-runs.ts"],"names":["useRef","useState","useEffect","useLayoutEffect","jsx","jsxs","useMemo"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * DocxViewer\n *\n * Renders DOCX files natively using docx-preview, preserving track changes\n * (shown as strikethrough deletions + inserted text) and inline comments.\n *\n * Pages render at their natural width and are scaled down to fit the\n * container, so the document resizes with the panel instead of clipping.\n *\n * `docx-preview` is an OPTIONAL peer dependency, imported dynamically — a\n * consumer that never renders a .docx does not need it installed. If it is\n * missing the viewer shows a load error rather than crashing the app.\n */\n\nimport { useEffect, useLayoutEffect, useRef, useState } from 'react'\n\nexport interface DocxViewerProps {\n blob: Blob\n}\n\n/** Natural width of the rendered document: widest page plus wrapper padding. */\nfunction measureContentWidth(container: HTMLElement): number {\n let pageWidth = 0\n container.querySelectorAll<HTMLElement>('section.docx').forEach((section) => {\n pageWidth = Math.max(pageWidth, section.offsetWidth)\n })\n if (pageWidth === 0) return 0\n\n const wrapper = container.querySelector<HTMLElement>('.docx-wrapper')\n if (wrapper) {\n const style = window.getComputedStyle(wrapper)\n pageWidth += (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0)\n }\n return pageWidth\n}\n\nexport function DocxViewer({ blob }: DocxViewerProps) {\n const outerRef = useRef<HTMLDivElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n const [error, setError] = useState<string | null>(null)\n const [isLoading, setIsLoading] = useState(true)\n const [containerWidth, setContainerWidth] = useState(0)\n const [contentWidth, setContentWidth] = useState(0)\n\n // Track container width so the document rescales when the panel is resized\n useEffect(() => {\n const outer = outerRef.current\n if (!outer) return\n\n const updateWidth = () => setContainerWidth(outer.clientWidth)\n updateWidth()\n\n const resizeObserver = new ResizeObserver(updateWidth)\n resizeObserver.observe(outer)\n return () => resizeObserver.disconnect()\n }, [])\n\n useEffect(() => {\n const container = containerRef.current\n if (!container) return\n\n let cancelled = false\n\n setIsLoading(true)\n setError(null)\n setContentWidth(0)\n container.innerHTML = ''\n\n import('docx-preview')\n .then(({ renderAsync }) => {\n if (cancelled) return\n return renderAsync(blob, container, undefined, {\n ignoreLastRenderedPageBreak: false,\n })\n })\n .then(() => {\n if (!cancelled) setIsLoading(false)\n })\n .catch((err) => {\n if (!cancelled) {\n console.error('DocxViewer render error:', err)\n setError('Failed to render document')\n setIsLoading(false)\n }\n })\n\n return () => {\n cancelled = true\n }\n }, [blob])\n\n // Measure after the body is unhidden — offsetWidth is 0 while `hidden` (display: none)\n useLayoutEffect(() => {\n const container = containerRef.current\n if (isLoading || error || !container) return\n setContentWidth(measureContentWidth(container))\n }, [isLoading, error])\n\n const scale =\n containerWidth > 0 && contentWidth > 0 ? Math.min(1, containerWidth / contentWidth) : 1\n\n return (\n <div ref={outerRef} className=\"w-full h-full overflow-auto bg-muted\" data-testid=\"docx-viewer\">\n {isLoading && (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-sm text-muted-foreground\">Loading document...</div>\n </div>\n )}\n {error && (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-destructive\">{error}</div>\n </div>\n )}\n <div\n ref={containerRef}\n data-testid=\"docx-viewer-body\"\n className={`docx-viewer-body${isLoading || error ? ' hidden' : ''}`}\n style={{ zoom: scale }}\n />\n </div>\n )\n}\n","/**\n * XlsxViewer\n *\n * Renders spreadsheets natively using SheetJS, showing every sheet with a tab\n * bar. Preserves cell data and multiple sheets.\n *\n * `xlsx` is an OPTIONAL peer dependency, imported dynamically — a consumer that\n * never renders a spreadsheet does not need it installed. If it is missing the\n * viewer shows a load error rather than crashing the app.\n */\n\nimport { useEffect, useRef, useState } from 'react'\nimport type { WorkSheet } from 'xlsx'\n\nexport interface XlsxViewerProps {\n blob: Blob\n}\n\ntype WorkbookRef = {\n SheetNames: string[]\n Sheets: Record<string, WorkSheet>\n}\n\nexport function XlsxViewer({ blob }: XlsxViewerProps) {\n const [sheets, setSheets] = useState<string[]>([])\n const [activeSheet, setActiveSheet] = useState<string>('')\n const [rows, setRows] = useState<unknown[][]>([])\n const [error, setError] = useState<string | null>(null)\n const [isLoading, setIsLoading] = useState(true)\n const workbookRef = useRef<WorkbookRef | null>(null)\n\n const renderSheet = async (sheetName: string, wb: WorkbookRef) => {\n const XLSX = await import('xlsx')\n const sheet = wb.Sheets[sheetName]\n const data = XLSX.utils.sheet_to_json<unknown[]>(sheet, { header: 1, defval: '' })\n setRows(data)\n setActiveSheet(sheetName)\n }\n\n useEffect(() => {\n let cancelled = false\n\n blob\n .arrayBuffer()\n .then(async (buffer) => {\n if (cancelled) return\n const XLSX = await import('xlsx')\n const wb = XLSX.read(buffer, { type: 'array' }) as WorkbookRef\n workbookRef.current = wb\n const sheetNames = wb.SheetNames\n setSheets(sheetNames)\n const data = XLSX.utils.sheet_to_json<unknown[]>(wb.Sheets[sheetNames[0]], {\n header: 1,\n defval: '',\n })\n if (!cancelled) {\n setRows(data)\n setActiveSheet(sheetNames[0])\n setIsLoading(false)\n }\n })\n .catch((err) => {\n if (!cancelled) {\n console.error('XlsxViewer error:', err)\n setError('Failed to render spreadsheet')\n setIsLoading(false)\n }\n })\n\n return () => {\n cancelled = true\n }\n }, [blob])\n\n const handleSheetChange = (sheetName: string) => {\n if (workbookRef.current) {\n renderSheet(sheetName, workbookRef.current)\n }\n }\n\n if (isLoading) {\n return (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-sm text-muted-foreground\">Loading spreadsheet...</div>\n </div>\n )\n }\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-destructive\">{error}</div>\n </div>\n )\n }\n\n // Find max columns across all rows for consistent table width\n const colCount = rows.reduce((max, row) => Math.max(max, (row as unknown[]).length), 0)\n\n return (\n <div\n className=\"w-full h-full flex flex-col overflow-hidden bg-background\"\n data-testid=\"xlsx-viewer\"\n >\n {/* Sheet tabs */}\n {sheets.length > 0 && (\n <div className=\"flex-shrink-0 flex items-center gap-0.5 px-2 pt-1 border-b bg-muted overflow-x-auto\">\n {sheets.map((sheet) => (\n <button\n key={sheet}\n onClick={() => handleSheetChange(sheet)}\n className={`px-3 py-1 text-sm font-medium whitespace-nowrap rounded-t transition-colors border-x border-t ${\n sheet === activeSheet\n ? 'bg-background text-primary border-border'\n : 'bg-muted text-muted-foreground border-transparent hover:bg-muted hover:text-foreground'\n }`}\n >\n {sheet}\n </button>\n ))}\n </div>\n )}\n\n {/* Spreadsheet table */}\n <div className=\"flex-1 overflow-auto\">\n <table className=\"text-sm border-collapse min-w-full\">\n <tbody>\n {rows.map((row, rowIdx) => (\n <tr\n key={rowIdx}\n className={rowIdx === 0 ? 'bg-muted font-semibold sticky top-0' : 'hover:bg-accent'}\n >\n {/* Row number gutter */}\n <td className=\"border border-border px-1 text-center text-muted-foreground bg-muted select-none w-8 min-w-[2rem]\">\n {rowIdx + 1}\n </td>\n {Array.from({ length: colCount }).map((_, colIdx) => (\n <td\n key={colIdx}\n className=\"border border-border px-2 py-0.5 whitespace-nowrap max-w-[200px] overflow-hidden text-ellipsis\"\n title={String((row as unknown[])[colIdx] ?? '')}\n >\n {String((row as unknown[])[colIdx] ?? '')}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n {rows.length === 0 && (\n <div className=\"flex items-center justify-center p-8 text-sm text-muted-foreground\">\n Empty sheet\n </div>\n )}\n </div>\n </div>\n )\n}\n","/**\n * Processed Chunks Hook\n *\n * Processes raw document chunks into page-grouped structure.\n * Pre-computes footnote inlining so it runs once during processing, not on every render.\n */\n\nimport { useMemo } from 'react'\n\nexport interface RawChunk {\n content: string\n metadata?: {\n page_number?: number\n chunk_doc_idx?: number\n chunk_ext_id?: string\n doc_title?: string | null\n }\n}\n\nexport interface ProcessedChunk {\n content: string\n chunkIndex: number | undefined\n chunkExtId: string | undefined\n docTitle: string | undefined\n}\n\nexport interface ProcessedPage {\n pageNumber: number | null\n chunks: ProcessedChunk[]\n}\n\nexport interface UseProcessedChunksResult {\n processedChunks: ProcessedPage[]\n maxPageNumber: number\n}\n\n/**\n * Replace GFM footnote references [^key] with inline footnote content\n * and strip footnote definition blocks from the chunk text.\n * Uses the pre-parsed footnotes map from the backend.\n */\nfunction inlineFootnotes(content: string, footnotes: Record<string, string>): string {\n if (!footnotes || Object.keys(footnotes).length === 0) return content\n\n let result = content\n\n // Strip GFM footnote definition blocks: [^key]: content (and continuation lines)\n result = result.replace(/^\\[\\^[^\\]]+\\]:[ \\t]+.*(?:\\n(?:[ \\t]+.+)?)*/gm, '')\n\n // Replace footnote references [^key] with superscript + inline content\n result = result.replace(/\\[\\^([^\\]]+)\\]/g, (_match, key) => {\n const fnContent = footnotes[key]\n if (!fnContent) return `<sup class=\"fn-ref\">${key}</sup>`\n const escaped = fnContent\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n return `<sup class=\"fn-ref\">${key}</sup><span class=\"fn-inline\" title=\"${escaped}\">[${escaped}]</span>`\n })\n\n return result.trim()\n}\n\nexport function useProcessedChunks(\n chunks: RawChunk[] | undefined,\n footnotes?: Record<string, string>\n): UseProcessedChunksResult {\n return useMemo(() => {\n if (!chunks || chunks.length === 0) {\n return { processedChunks: [], maxPageNumber: 0 }\n }\n\n const hasFootnotes = footnotes && Object.keys(footnotes).length > 0\n const chunksByPage: ProcessedPage[] = []\n let currentPageNumber = -1\n let currentPageChunks: ProcessedChunk[] = []\n let maxPageNumber = 0\n\n chunks.forEach((chunk) => {\n const pageNum = chunk.metadata?.page_number\n\n // Track max page number\n if (pageNum && pageNum > maxPageNumber) {\n maxPageNumber = pageNum\n }\n\n // If page changed, save previous page and start new one\n if (pageNum !== currentPageNumber) {\n if (currentPageChunks.length > 0) {\n chunksByPage.push({\n pageNumber: currentPageNumber > 0 ? currentPageNumber : null,\n chunks: currentPageChunks,\n })\n }\n currentPageNumber = pageNum ?? -1\n currentPageChunks = []\n }\n\n currentPageChunks.push({\n content: hasFootnotes ? inlineFootnotes(chunk.content, footnotes) : chunk.content,\n chunkIndex: chunk.metadata?.chunk_doc_idx,\n chunkExtId: chunk.metadata?.chunk_ext_id,\n docTitle: chunk.metadata?.doc_title ?? undefined,\n })\n })\n\n // Add the last page\n if (currentPageChunks.length > 0) {\n chunksByPage.push({\n pageNumber: currentPageNumber > 0 ? currentPageNumber : null,\n chunks: currentPageChunks,\n })\n }\n\n return { processedChunks: chunksByPage, maxPageNumber }\n }, [chunks, footnotes])\n}\n","/**\n * Contiguous-run grouping for selected passages.\n *\n * Selecting passages 4–9 is one citation, not six. This collapses a flat set of\n * selected chunk ids into the contiguous runs they form in document order, so\n * the viewer can draw each run as a single block with a single \"p.3(4–9)\" label\n * instead of stacking six identical pills.\n *\n * Purely positional: the pages arrive in document order (which is\n * `chunk_doc_idx` order), so adjacency is just \"next in the list\".\n */\n\nexport interface RunChunk {\n chunkExtId: string | undefined\n /** 0-based index within the document; displayed 1-based */\n chunkIndex: number | undefined\n}\n\nexport interface RunPage {\n pageNumber: number | null\n chunks: RunChunk[]\n}\n\n/** Where a selected chunk sits inside its contiguous run of selected chunks. */\nexport interface ChunkRunInfo {\n isStart: boolean\n isEnd: boolean\n /** Set only on the run's first member — the bounds its single label shows. */\n endIndex: number | undefined\n endPage: number | null | undefined\n}\n\nexport function computeSelectionRuns(\n pages: RunPage[],\n selectedChunks: Set<string>\n): Map<string, ChunkRunInfo> {\n const runs = new Map<string, ChunkRunInfo>()\n if (selectedChunks.size === 0) return runs\n\n const flat = pages.flatMap((page) =>\n page.chunks.map((c) => ({ ...c, pageNumber: page.pageNumber }))\n )\n\n let i = 0\n while (i < flat.length) {\n const chunk = flat[i]\n if (!chunk.chunkExtId || !selectedChunks.has(chunk.chunkExtId)) {\n i += 1\n continue\n }\n\n // Walk forward while the neighbours are also selected.\n let end = i\n while (\n end + 1 < flat.length &&\n flat[end + 1].chunkExtId &&\n selectedChunks.has(flat[end + 1].chunkExtId!)\n ) {\n end += 1\n }\n\n const last = flat[end]\n const endIndex = last.chunkIndex !== undefined ? last.chunkIndex + 1 : undefined\n for (let k = i; k <= end; k += 1) {\n const id = flat[k].chunkExtId\n if (!id) continue\n runs.set(id, {\n isStart: k === i,\n isEnd: k === end,\n // Only the run's first member carries the label bounds.\n endIndex: k === i ? endIndex : undefined,\n endPage: k === i ? last.pageNumber : undefined,\n })\n }\n i = end + 1\n }\n\n return runs\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/viewers/DocxViewer.tsx","../../src/viewers/XlsxViewer.tsx","../../src/viewers/useProcessedChunks.ts","../../src/viewers/selection-runs.ts"],"names":["useRef","useState","useEffect","useLayoutEffect","jsx","jsxs","useMemo"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * DocxViewer\n *\n * Renders DOCX files natively using docx-preview, preserving track changes\n * (shown as strikethrough deletions + inserted text) and inline comments.\n *\n * Pages render at their natural width and are scaled down to fit the\n * container, so the document resizes with the panel instead of clipping.\n *\n * `docx-preview` is an OPTIONAL peer dependency, imported dynamically — a\n * consumer that never renders a .docx does not need it installed. If it is\n * missing the viewer shows a load error rather than crashing the app.\n */\n\nimport { useEffect, useLayoutEffect, useRef, useState } from 'react'\n\nexport interface DocxViewerProps {\n blob: Blob\n}\n\n/** Natural width of the rendered document: widest page plus wrapper padding. */\nfunction measureContentWidth(container: HTMLElement): number {\n let pageWidth = 0\n container.querySelectorAll<HTMLElement>('section.docx').forEach((section) => {\n pageWidth = Math.max(pageWidth, section.offsetWidth)\n })\n if (pageWidth === 0) return 0\n\n const wrapper = container.querySelector<HTMLElement>('.docx-wrapper')\n if (wrapper) {\n const style = window.getComputedStyle(wrapper)\n pageWidth += (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0)\n }\n return pageWidth\n}\n\nexport function DocxViewer({ blob }: DocxViewerProps) {\n const outerRef = useRef<HTMLDivElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n const [error, setError] = useState<string | null>(null)\n const [isLoading, setIsLoading] = useState(true)\n const [containerWidth, setContainerWidth] = useState(0)\n const [contentWidth, setContentWidth] = useState(0)\n\n // Track container width so the document rescales when the panel is resized\n useEffect(() => {\n const outer = outerRef.current\n if (!outer) return\n\n const updateWidth = () => setContainerWidth(outer.clientWidth)\n updateWidth()\n\n const resizeObserver = new ResizeObserver(updateWidth)\n resizeObserver.observe(outer)\n return () => resizeObserver.disconnect()\n }, [])\n\n useEffect(() => {\n const container = containerRef.current\n if (!container) return\n\n let cancelled = false\n\n setIsLoading(true)\n setError(null)\n setContentWidth(0)\n container.innerHTML = ''\n\n import('docx-preview')\n .then(({ renderAsync }) => {\n if (cancelled) return\n return renderAsync(blob, container, undefined, {\n ignoreLastRenderedPageBreak: false,\n })\n })\n .then(() => {\n if (!cancelled) setIsLoading(false)\n })\n .catch((err) => {\n if (!cancelled) {\n console.error('DocxViewer render error:', err)\n setError('Failed to render document')\n setIsLoading(false)\n }\n })\n\n return () => {\n cancelled = true\n }\n }, [blob])\n\n // Measure after the body is unhidden — offsetWidth is 0 while `hidden` (display: none)\n useLayoutEffect(() => {\n const container = containerRef.current\n if (isLoading || error || !container) return\n setContentWidth(measureContentWidth(container))\n }, [isLoading, error])\n\n const scale =\n containerWidth > 0 && contentWidth > 0 ? Math.min(1, containerWidth / contentWidth) : 1\n\n return (\n <div ref={outerRef} className=\"w-full h-full overflow-auto bg-muted\" data-testid=\"docx-viewer\">\n {isLoading && (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-sm text-muted-foreground\">Loading document...</div>\n </div>\n )}\n {error && (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-destructive\">{error}</div>\n </div>\n )}\n <div\n ref={containerRef}\n data-testid=\"docx-viewer-body\"\n className={`docx-viewer-body${isLoading || error ? ' hidden' : ''}`}\n style={{ zoom: scale }}\n />\n </div>\n )\n}\n","/**\n * XlsxViewer\n *\n * Renders spreadsheets natively using SheetJS, showing every sheet with a tab\n * bar. Preserves cell data and multiple sheets.\n *\n * `xlsx` is an OPTIONAL peer dependency, imported dynamically — a consumer that\n * never renders a spreadsheet does not need it installed. If it is missing the\n * viewer shows a load error rather than crashing the app.\n */\n\nimport { useEffect, useRef, useState } from 'react'\nimport type { WorkSheet } from 'xlsx'\n\nexport interface XlsxViewerProps {\n blob: Blob\n}\n\ntype WorkbookRef = {\n SheetNames: string[]\n Sheets: Record<string, WorkSheet>\n}\n\nexport function XlsxViewer({ blob }: XlsxViewerProps) {\n const [sheets, setSheets] = useState<string[]>([])\n const [activeSheet, setActiveSheet] = useState<string>('')\n const [rows, setRows] = useState<unknown[][]>([])\n const [error, setError] = useState<string | null>(null)\n const [isLoading, setIsLoading] = useState(true)\n const workbookRef = useRef<WorkbookRef | null>(null)\n\n const renderSheet = async (sheetName: string, wb: WorkbookRef) => {\n const XLSX = await import('xlsx')\n const sheet = wb.Sheets[sheetName]\n const data = XLSX.utils.sheet_to_json<unknown[]>(sheet, { header: 1, defval: '' })\n setRows(data)\n setActiveSheet(sheetName)\n }\n\n useEffect(() => {\n let cancelled = false\n\n blob\n .arrayBuffer()\n .then(async (buffer) => {\n if (cancelled) return\n const XLSX = await import('xlsx')\n const wb = XLSX.read(buffer, { type: 'array' }) as WorkbookRef\n workbookRef.current = wb\n const sheetNames = wb.SheetNames\n setSheets(sheetNames)\n const data = XLSX.utils.sheet_to_json<unknown[]>(wb.Sheets[sheetNames[0]], {\n header: 1,\n defval: '',\n })\n if (!cancelled) {\n setRows(data)\n setActiveSheet(sheetNames[0])\n setIsLoading(false)\n }\n })\n .catch((err) => {\n if (!cancelled) {\n console.error('XlsxViewer error:', err)\n setError('Failed to render spreadsheet')\n setIsLoading(false)\n }\n })\n\n return () => {\n cancelled = true\n }\n }, [blob])\n\n const handleSheetChange = (sheetName: string) => {\n if (workbookRef.current) {\n renderSheet(sheetName, workbookRef.current)\n }\n }\n\n if (isLoading) {\n return (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-sm text-muted-foreground\">Loading spreadsheet...</div>\n </div>\n )\n }\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-destructive\">{error}</div>\n </div>\n )\n }\n\n // Find max columns across all rows for consistent table width\n const colCount = rows.reduce((max, row) => Math.max(max, (row as unknown[]).length), 0)\n\n return (\n <div\n className=\"w-full h-full flex flex-col overflow-hidden bg-background\"\n data-testid=\"xlsx-viewer\"\n >\n {/* Sheet tabs */}\n {sheets.length > 0 && (\n <div className=\"flex-shrink-0 flex items-center gap-0.5 px-2 pt-1 border-b bg-muted overflow-x-auto\">\n {sheets.map((sheet) => (\n <button\n key={sheet}\n onClick={() => handleSheetChange(sheet)}\n className={`px-3 py-1 text-sm font-medium whitespace-nowrap rounded-t transition-colors border-x border-t ${\n sheet === activeSheet\n ? 'bg-background text-primary border-border'\n : 'bg-muted text-muted-foreground border-transparent hover:bg-muted hover:text-foreground'\n }`}\n >\n {sheet}\n </button>\n ))}\n </div>\n )}\n\n {/* Spreadsheet table */}\n <div className=\"flex-1 overflow-auto\">\n <table className=\"text-sm border-collapse min-w-full\">\n <tbody>\n {rows.map((row, rowIdx) => (\n <tr\n key={rowIdx}\n className={rowIdx === 0 ? 'bg-muted font-semibold sticky top-0' : 'hover:bg-accent'}\n >\n {/* Row number gutter */}\n <td className=\"border border-border px-1 text-center text-muted-foreground bg-muted select-none w-8 min-w-[2rem]\">\n {rowIdx + 1}\n </td>\n {Array.from({ length: colCount }).map((_, colIdx) => (\n <td\n key={colIdx}\n className=\"border border-border px-2 py-0.5 whitespace-nowrap max-w-[200px] overflow-hidden text-ellipsis\"\n title={String((row as unknown[])[colIdx] ?? '')}\n >\n {String((row as unknown[])[colIdx] ?? '')}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n {rows.length === 0 && (\n <div className=\"flex items-center justify-center p-8 text-sm text-muted-foreground\">\n Empty sheet\n </div>\n )}\n </div>\n </div>\n )\n}\n","/**\n * Processed Chunks Hook\n *\n * Processes raw document chunks into page-grouped structure.\n * Pre-computes footnote inlining so it runs once during processing, not on every render.\n */\n\nimport { useMemo } from 'react'\n\nexport interface RawChunk {\n content: string\n metadata?: {\n page_number?: number\n chunk_doc_idx?: number\n chunk_ext_id?: string\n doc_title?: string | null\n /** Where the chunk sits on its page: [x0, y0, x1, y1] as fractions of the page, top-left origin. */\n page_bbox?: number[] | null\n }\n}\n\nexport interface ProcessedChunk {\n content: string\n chunkIndex: number | undefined\n chunkExtId: string | undefined\n docTitle: string | undefined\n /** Where the chunk sits on its page, as fractions of the page; absent for older parses. */\n pageBbox?: number[]\n}\n\nexport interface ProcessedPage {\n pageNumber: number | null\n chunks: ProcessedChunk[]\n}\n\nexport interface UseProcessedChunksResult {\n processedChunks: ProcessedPage[]\n maxPageNumber: number\n}\n\n/**\n * Replace GFM footnote references [^key] with inline footnote content\n * and strip footnote definition blocks from the chunk text.\n * Uses the pre-parsed footnotes map from the backend.\n */\nfunction inlineFootnotes(content: string, footnotes: Record<string, string>): string {\n if (!footnotes || Object.keys(footnotes).length === 0) return content\n\n let result = content\n\n // Strip GFM footnote definition blocks: [^key]: content (and continuation lines)\n result = result.replace(/^\\[\\^[^\\]]+\\]:[ \\t]+.*(?:\\n(?:[ \\t]+.+)?)*/gm, '')\n\n // Replace footnote references [^key] with superscript + inline content\n result = result.replace(/\\[\\^([^\\]]+)\\]/g, (_match, key) => {\n const fnContent = footnotes[key]\n if (!fnContent) return `<sup class=\"fn-ref\">${key}</sup>`\n const escaped = fnContent\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n return `<sup class=\"fn-ref\">${key}</sup><span class=\"fn-inline\" title=\"${escaped}\">[${escaped}]</span>`\n })\n\n return result.trim()\n}\n\nexport function useProcessedChunks(\n chunks: RawChunk[] | undefined,\n footnotes?: Record<string, string>\n): UseProcessedChunksResult {\n return useMemo(() => {\n if (!chunks || chunks.length === 0) {\n return { processedChunks: [], maxPageNumber: 0 }\n }\n\n const hasFootnotes = footnotes && Object.keys(footnotes).length > 0\n const chunksByPage: ProcessedPage[] = []\n let currentPageNumber = -1\n let currentPageChunks: ProcessedChunk[] = []\n let maxPageNumber = 0\n\n chunks.forEach((chunk) => {\n const pageNum = chunk.metadata?.page_number\n\n // Track max page number\n if (pageNum && pageNum > maxPageNumber) {\n maxPageNumber = pageNum\n }\n\n // If page changed, save previous page and start new one\n if (pageNum !== currentPageNumber) {\n if (currentPageChunks.length > 0) {\n chunksByPage.push({\n pageNumber: currentPageNumber > 0 ? currentPageNumber : null,\n chunks: currentPageChunks,\n })\n }\n currentPageNumber = pageNum ?? -1\n currentPageChunks = []\n }\n\n currentPageChunks.push({\n content: hasFootnotes ? inlineFootnotes(chunk.content, footnotes) : chunk.content,\n chunkIndex: chunk.metadata?.chunk_doc_idx,\n chunkExtId: chunk.metadata?.chunk_ext_id,\n docTitle: chunk.metadata?.doc_title ?? undefined,\n pageBbox: chunk.metadata?.page_bbox ?? undefined,\n })\n })\n\n // Add the last page\n if (currentPageChunks.length > 0) {\n chunksByPage.push({\n pageNumber: currentPageNumber > 0 ? currentPageNumber : null,\n chunks: currentPageChunks,\n })\n }\n\n return { processedChunks: chunksByPage, maxPageNumber }\n }, [chunks, footnotes])\n}\n","/**\n * Contiguous-run grouping for selected passages.\n *\n * Selecting passages 4–9 is one citation, not six. This collapses a flat set of\n * selected chunk ids into the contiguous runs they form in document order, so\n * the viewer can draw each run as a single block with a single \"p.3(4–9)\" label\n * instead of stacking six identical pills.\n *\n * Purely positional: the pages arrive in document order (which is\n * `chunk_doc_idx` order), so adjacency is just \"next in the list\".\n */\n\nexport interface RunChunk {\n chunkExtId: string | undefined\n /** 0-based index within the document; displayed 1-based */\n chunkIndex: number | undefined\n}\n\nexport interface RunPage {\n pageNumber: number | null\n chunks: RunChunk[]\n}\n\n/** Where a selected chunk sits inside its contiguous run of selected chunks. */\nexport interface ChunkRunInfo {\n isStart: boolean\n isEnd: boolean\n /** Set only on the run's first member — the bounds its single label shows. */\n endIndex: number | undefined\n endPage: number | null | undefined\n}\n\nexport function computeSelectionRuns(\n pages: RunPage[],\n selectedChunks: Set<string>\n): Map<string, ChunkRunInfo> {\n const runs = new Map<string, ChunkRunInfo>()\n if (selectedChunks.size === 0) return runs\n\n const flat = pages.flatMap((page) =>\n page.chunks.map((c) => ({ ...c, pageNumber: page.pageNumber }))\n )\n\n let i = 0\n while (i < flat.length) {\n const chunk = flat[i]\n if (!chunk.chunkExtId || !selectedChunks.has(chunk.chunkExtId)) {\n i += 1\n continue\n }\n\n // Walk forward while the neighbours are also selected.\n let end = i\n while (\n end + 1 < flat.length &&\n flat[end + 1].chunkExtId &&\n selectedChunks.has(flat[end + 1].chunkExtId!)\n ) {\n end += 1\n }\n\n const last = flat[end]\n const endIndex = last.chunkIndex !== undefined ? last.chunkIndex + 1 : undefined\n for (let k = i; k <= end; k += 1) {\n const id = flat[k].chunkExtId\n if (!id) continue\n runs.set(id, {\n isStart: k === i,\n isEnd: k === end,\n // Only the run's first member carries the label bounds.\n endIndex: k === i ? endIndex : undefined,\n endPage: k === i ? last.pageNumber : undefined,\n })\n }\n i = end + 1\n }\n\n return runs\n}\n"]}
|
package/dist/viewers/index.d.ts
CHANGED
|
@@ -211,6 +211,8 @@ interface RawChunk {
|
|
|
211
211
|
chunk_doc_idx?: number;
|
|
212
212
|
chunk_ext_id?: string;
|
|
213
213
|
doc_title?: string | null;
|
|
214
|
+
/** Where the chunk sits on its page: [x0, y0, x1, y1] as fractions of the page, top-left origin. */
|
|
215
|
+
page_bbox?: number[] | null;
|
|
214
216
|
};
|
|
215
217
|
}
|
|
216
218
|
interface ProcessedChunk {
|
|
@@ -218,6 +220,8 @@ interface ProcessedChunk {
|
|
|
218
220
|
chunkIndex: number | undefined;
|
|
219
221
|
chunkExtId: string | undefined;
|
|
220
222
|
docTitle: string | undefined;
|
|
223
|
+
/** Where the chunk sits on its page, as fractions of the page; absent for older parses. */
|
|
224
|
+
pageBbox?: number[];
|
|
221
225
|
}
|
|
222
226
|
interface ProcessedPage {
|
|
223
227
|
pageNumber: number | null;
|
|
@@ -40,7 +40,8 @@ function useProcessedChunks(chunks, footnotes) {
|
|
|
40
40
|
content: hasFootnotes ? inlineFootnotes(chunk.content, footnotes) : chunk.content,
|
|
41
41
|
chunkIndex: chunk.metadata?.chunk_doc_idx,
|
|
42
42
|
chunkExtId: chunk.metadata?.chunk_ext_id,
|
|
43
|
-
docTitle: chunk.metadata?.doc_title ?? void 0
|
|
43
|
+
docTitle: chunk.metadata?.doc_title ?? void 0,
|
|
44
|
+
pageBbox: chunk.metadata?.page_bbox ?? void 0
|
|
44
45
|
});
|
|
45
46
|
});
|
|
46
47
|
if (currentPageChunks.length > 0) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/viewers/useProcessedChunks.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Processed Chunks Hook\n *\n * Processes raw document chunks into page-grouped structure.\n * Pre-computes footnote inlining so it runs once during processing, not on every render.\n */\n\nimport { useMemo } from 'react'\n\nexport interface RawChunk {\n content: string\n metadata?: {\n page_number?: number\n chunk_doc_idx?: number\n chunk_ext_id?: string\n doc_title?: string | null\n }\n}\n\nexport interface ProcessedChunk {\n content: string\n chunkIndex: number | undefined\n chunkExtId: string | undefined\n docTitle: string | undefined\n}\n\nexport interface ProcessedPage {\n pageNumber: number | null\n chunks: ProcessedChunk[]\n}\n\nexport interface UseProcessedChunksResult {\n processedChunks: ProcessedPage[]\n maxPageNumber: number\n}\n\n/**\n * Replace GFM footnote references [^key] with inline footnote content\n * and strip footnote definition blocks from the chunk text.\n * Uses the pre-parsed footnotes map from the backend.\n */\nfunction inlineFootnotes(content: string, footnotes: Record<string, string>): string {\n if (!footnotes || Object.keys(footnotes).length === 0) return content\n\n let result = content\n\n // Strip GFM footnote definition blocks: [^key]: content (and continuation lines)\n result = result.replace(/^\\[\\^[^\\]]+\\]:[ \\t]+.*(?:\\n(?:[ \\t]+.+)?)*/gm, '')\n\n // Replace footnote references [^key] with superscript + inline content\n result = result.replace(/\\[\\^([^\\]]+)\\]/g, (_match, key) => {\n const fnContent = footnotes[key]\n if (!fnContent) return `<sup class=\"fn-ref\">${key}</sup>`\n const escaped = fnContent\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n return `<sup class=\"fn-ref\">${key}</sup><span class=\"fn-inline\" title=\"${escaped}\">[${escaped}]</span>`\n })\n\n return result.trim()\n}\n\nexport function useProcessedChunks(\n chunks: RawChunk[] | undefined,\n footnotes?: Record<string, string>\n): UseProcessedChunksResult {\n return useMemo(() => {\n if (!chunks || chunks.length === 0) {\n return { processedChunks: [], maxPageNumber: 0 }\n }\n\n const hasFootnotes = footnotes && Object.keys(footnotes).length > 0\n const chunksByPage: ProcessedPage[] = []\n let currentPageNumber = -1\n let currentPageChunks: ProcessedChunk[] = []\n let maxPageNumber = 0\n\n chunks.forEach((chunk) => {\n const pageNum = chunk.metadata?.page_number\n\n // Track max page number\n if (pageNum && pageNum > maxPageNumber) {\n maxPageNumber = pageNum\n }\n\n // If page changed, save previous page and start new one\n if (pageNum !== currentPageNumber) {\n if (currentPageChunks.length > 0) {\n chunksByPage.push({\n pageNumber: currentPageNumber > 0 ? currentPageNumber : null,\n chunks: currentPageChunks,\n })\n }\n currentPageNumber = pageNum ?? -1\n currentPageChunks = []\n }\n\n currentPageChunks.push({\n content: hasFootnotes ? inlineFootnotes(chunk.content, footnotes) : chunk.content,\n chunkIndex: chunk.metadata?.chunk_doc_idx,\n chunkExtId: chunk.metadata?.chunk_ext_id,\n docTitle: chunk.metadata?.doc_title ?? undefined,\n })\n })\n\n // Add the last page\n if (currentPageChunks.length > 0) {\n chunksByPage.push({\n pageNumber: currentPageNumber > 0 ? currentPageNumber : null,\n chunks: currentPageChunks,\n })\n }\n\n return { processedChunks: chunksByPage, maxPageNumber }\n }, [chunks, footnotes])\n}\n"],
|
|
5
|
-
"mappings": "AAOA,SAAS,eAAe;
|
|
4
|
+
"sourcesContent": ["/**\n * Processed Chunks Hook\n *\n * Processes raw document chunks into page-grouped structure.\n * Pre-computes footnote inlining so it runs once during processing, not on every render.\n */\n\nimport { useMemo } from 'react'\n\nexport interface RawChunk {\n content: string\n metadata?: {\n page_number?: number\n chunk_doc_idx?: number\n chunk_ext_id?: string\n doc_title?: string | null\n /** Where the chunk sits on its page: [x0, y0, x1, y1] as fractions of the page, top-left origin. */\n page_bbox?: number[] | null\n }\n}\n\nexport interface ProcessedChunk {\n content: string\n chunkIndex: number | undefined\n chunkExtId: string | undefined\n docTitle: string | undefined\n /** Where the chunk sits on its page, as fractions of the page; absent for older parses. */\n pageBbox?: number[]\n}\n\nexport interface ProcessedPage {\n pageNumber: number | null\n chunks: ProcessedChunk[]\n}\n\nexport interface UseProcessedChunksResult {\n processedChunks: ProcessedPage[]\n maxPageNumber: number\n}\n\n/**\n * Replace GFM footnote references [^key] with inline footnote content\n * and strip footnote definition blocks from the chunk text.\n * Uses the pre-parsed footnotes map from the backend.\n */\nfunction inlineFootnotes(content: string, footnotes: Record<string, string>): string {\n if (!footnotes || Object.keys(footnotes).length === 0) return content\n\n let result = content\n\n // Strip GFM footnote definition blocks: [^key]: content (and continuation lines)\n result = result.replace(/^\\[\\^[^\\]]+\\]:[ \\t]+.*(?:\\n(?:[ \\t]+.+)?)*/gm, '')\n\n // Replace footnote references [^key] with superscript + inline content\n result = result.replace(/\\[\\^([^\\]]+)\\]/g, (_match, key) => {\n const fnContent = footnotes[key]\n if (!fnContent) return `<sup class=\"fn-ref\">${key}</sup>`\n const escaped = fnContent\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n return `<sup class=\"fn-ref\">${key}</sup><span class=\"fn-inline\" title=\"${escaped}\">[${escaped}]</span>`\n })\n\n return result.trim()\n}\n\nexport function useProcessedChunks(\n chunks: RawChunk[] | undefined,\n footnotes?: Record<string, string>\n): UseProcessedChunksResult {\n return useMemo(() => {\n if (!chunks || chunks.length === 0) {\n return { processedChunks: [], maxPageNumber: 0 }\n }\n\n const hasFootnotes = footnotes && Object.keys(footnotes).length > 0\n const chunksByPage: ProcessedPage[] = []\n let currentPageNumber = -1\n let currentPageChunks: ProcessedChunk[] = []\n let maxPageNumber = 0\n\n chunks.forEach((chunk) => {\n const pageNum = chunk.metadata?.page_number\n\n // Track max page number\n if (pageNum && pageNum > maxPageNumber) {\n maxPageNumber = pageNum\n }\n\n // If page changed, save previous page and start new one\n if (pageNum !== currentPageNumber) {\n if (currentPageChunks.length > 0) {\n chunksByPage.push({\n pageNumber: currentPageNumber > 0 ? currentPageNumber : null,\n chunks: currentPageChunks,\n })\n }\n currentPageNumber = pageNum ?? -1\n currentPageChunks = []\n }\n\n currentPageChunks.push({\n content: hasFootnotes ? inlineFootnotes(chunk.content, footnotes) : chunk.content,\n chunkIndex: chunk.metadata?.chunk_doc_idx,\n chunkExtId: chunk.metadata?.chunk_ext_id,\n docTitle: chunk.metadata?.doc_title ?? undefined,\n pageBbox: chunk.metadata?.page_bbox ?? undefined,\n })\n })\n\n // Add the last page\n if (currentPageChunks.length > 0) {\n chunksByPage.push({\n pageNumber: currentPageNumber > 0 ? currentPageNumber : null,\n chunks: currentPageChunks,\n })\n }\n\n return { processedChunks: chunksByPage, maxPageNumber }\n }, [chunks, footnotes])\n}\n"],
|
|
5
|
+
"mappings": "AAOA,SAAS,eAAe;AAsCxB,SAAS,gBAAgB,SAAiB,WAA2C;AACnF,MAAI,CAAC,aAAa,OAAO,KAAK,SAAS,EAAE,WAAW,EAAG,QAAO;AAE9D,MAAI,SAAS;AAGb,WAAS,OAAO,QAAQ,gDAAgD,EAAE;AAG1E,WAAS,OAAO,QAAQ,mBAAmB,CAAC,QAAQ,QAAQ;AAC1D,UAAM,YAAY,UAAU,GAAG;AAC/B,QAAI,CAAC,UAAW,QAAO,uBAAuB,GAAG;AACjD,UAAM,UAAU,UACb,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ;AACzB,WAAO,uBAAuB,GAAG,wCAAwC,OAAO,MAAM,OAAO;AAAA,EAC/F,CAAC;AAED,SAAO,OAAO,KAAK;AACrB;AAEO,SAAS,mBACd,QACA,WAC0B;AAC1B,SAAO,QAAQ,MAAM;AACnB,QAAI,CAAC,UAAU,OAAO,WAAW,GAAG;AAClC,aAAO,EAAE,iBAAiB,CAAC,GAAG,eAAe,EAAE;AAAA,IACjD;AAEA,UAAM,eAAe,aAAa,OAAO,KAAK,SAAS,EAAE,SAAS;AAClE,UAAM,eAAgC,CAAC;AACvC,QAAI,oBAAoB;AACxB,QAAI,oBAAsC,CAAC;AAC3C,QAAI,gBAAgB;AAEpB,WAAO,QAAQ,CAAC,UAAU;AACxB,YAAM,UAAU,MAAM,UAAU;AAGhC,UAAI,WAAW,UAAU,eAAe;AACtC,wBAAgB;AAAA,MAClB;AAGA,UAAI,YAAY,mBAAmB;AACjC,YAAI,kBAAkB,SAAS,GAAG;AAChC,uBAAa,KAAK;AAAA,YAChB,YAAY,oBAAoB,IAAI,oBAAoB;AAAA,YACxD,QAAQ;AAAA,UACV,CAAC;AAAA,QACH;AACA,4BAAoB,WAAW;AAC/B,4BAAoB,CAAC;AAAA,MACvB;AAEA,wBAAkB,KAAK;AAAA,QACrB,SAAS,eAAe,gBAAgB,MAAM,SAAS,SAAS,IAAI,MAAM;AAAA,QAC1E,YAAY,MAAM,UAAU;AAAA,QAC5B,YAAY,MAAM,UAAU;AAAA,QAC5B,UAAU,MAAM,UAAU,aAAa;AAAA,QACvC,UAAU,MAAM,UAAU,aAAa;AAAA,MACzC,CAAC;AAAA,IACH,CAAC;AAGD,QAAI,kBAAkB,SAAS,GAAG;AAChC,mBAAa,KAAK;AAAA,QAChB,YAAY,oBAAoB,IAAI,oBAAoB;AAAA,QACxD,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAEA,WAAO,EAAE,iBAAiB,cAAc,cAAc;AAAA,EACxD,GAAG,CAAC,QAAQ,SAAS,CAAC;AACxB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arbidocs/react",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.120",
|
|
4
4
|
"description": "React hooks and provider for the ARBI SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -117,8 +117,8 @@
|
|
|
117
117
|
"build-storybook": "storybook build"
|
|
118
118
|
},
|
|
119
119
|
"dependencies": {
|
|
120
|
-
"@arbidocs/client": "0.5.
|
|
121
|
-
"@arbidocs/sdk": "0.5.
|
|
120
|
+
"@arbidocs/client": "0.5.120",
|
|
121
|
+
"@arbidocs/sdk": "0.5.120",
|
|
122
122
|
"@didit-protocol/sdk-web": "0.4.0",
|
|
123
123
|
"@livekit/components-react": "2.9.24",
|
|
124
124
|
"@radix-ui/react-avatar": "^1.2.0",
|