@relevaince/document-viewer 0.1.0 → 0.2.0

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/getFileType.ts","../src/components/renderers/PdfRenderer.tsx","../src/components/renderers/DocxRenderer.tsx","../src/components/DocumentViewer.tsx"],"sourcesContent":["/**\n * Infer document type from URL extension.\n * Strips query-strings and fragments before matching.\n */\nexport function getFileType(url: string): \"pdf\" | \"docx\" | \"unknown\" {\n const clean = url.split(\"?\")[0].split(\"#\")[0].toLowerCase();\n\n if (clean.endsWith(\".pdf\")) return \"pdf\";\n if (clean.endsWith(\".docx\") || clean.endsWith(\".doc\")) return \"docx\";\n\n return \"unknown\";\n}\n","import React, { useRef, useEffect, useMemo, useCallback } from \"react\";\nimport {\n PdfLoader,\n PdfHighlighter,\n AreaHighlight,\n useHighlightContainerContext,\n} from \"react-pdf-highlighter-extended\";\nimport type {\n Highlight,\n ScaledPosition,\n PdfHighlighterUtils,\n} from \"react-pdf-highlighter-extended\";\nimport type { ViewerTarget } from \"../../types/ViewerTarget\";\n\n/* ------------------------------------------------------------------ */\n/* Constants */\n/* ------------------------------------------------------------------ */\n\nconst CITATION_ID = \"citation-highlight\";\n\nconst DEFAULT_WORKER_URL =\n \"https://unpkg.com/pdfjs-dist@4.4.168/build/pdf.worker.min.mjs\";\n\n/* ------------------------------------------------------------------ */\n/* BBox → Highlight conversion */\n/* ------------------------------------------------------------------ */\n\n/**\n * Convert our normalised (0-1) BBox into the Scaled coordinate system\n * used by react-pdf-highlighter-extended.\n *\n * The library internally computes:\n * viewportX = (viewportWidth × scaled.x1) / scaled.width\n *\n * So `scaled.x1 / scaled.width` must equal the normalised value.\n * We simply store the 0-1 value directly and set width / height to 1.\n */\nfunction bboxToHighlight(target: ViewerTarget): Highlight | null {\n if (!target.bbox) return null;\n\n const page = target.page ?? 1;\n const { x1, y1, x2, y2 } = target.bbox;\n\n const scaledRect = {\n x1,\n y1,\n x2,\n y2,\n width: 1,\n height: 1,\n pageNumber: page,\n };\n\n const position: ScaledPosition = {\n boundingRect: scaledRect,\n rects: [scaledRect],\n };\n\n return {\n id: CITATION_ID,\n type: \"area\",\n position,\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Highlight child renderer */\n/* ------------------------------------------------------------------ */\n\n/**\n * Rendered once per highlight by PdfHighlighter's internal loop.\n * Uses context to access the highlight's viewport position.\n */\nfunction CitationHighlightRenderer() {\n const { highlight, isScrolledTo } = useHighlightContainerContext();\n\n return (\n <AreaHighlight\n highlight={highlight}\n isScrolledTo={isScrolledTo}\n style={{\n background: isScrolledTo\n ? \"rgba(255, 171, 0, 0.35)\"\n : \"rgba(255, 171, 0, 0.2)\",\n border: \"1.5px solid rgba(255, 171, 0, 0.6)\",\n borderRadius: 2,\n transition: \"background 200ms ease\",\n }}\n />\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* PdfRenderer */\n/* ------------------------------------------------------------------ */\n\ninterface PdfRendererProps {\n target: ViewerTarget;\n workerUrl?: string;\n loadingComponent?: React.ReactNode;\n errorComponent?: React.ReactNode;\n onLoadSuccess?: () => void;\n onLoadError?: (err: Error) => void;\n}\n\nexport function PdfRenderer({\n target,\n workerUrl,\n loadingComponent,\n errorComponent,\n onLoadSuccess,\n onLoadError,\n}: PdfRendererProps) {\n const highlighterRef = useRef<PdfHighlighterUtils | null>(null);\n const loadNotifiedRef = useRef(false);\n\n /* Build highlight array from target bbox */\n const highlights = useMemo(() => {\n const h = bboxToHighlight(target);\n return h ? [h] : [];\n }, [target]);\n\n /* Scroll to the citation highlight once the viewer is ready */\n useEffect(() => {\n if (highlights.length === 0) return;\n\n const timer = setTimeout(() => {\n highlighterRef.current?.scrollToHighlight(highlights[0]);\n }, 400);\n\n return () => clearTimeout(timer);\n }, [highlights]);\n\n /* Stable callback so we don't re-trigger PdfHighlighter renders */\n const handleUtilsRef = useCallback((utils: PdfHighlighterUtils) => {\n highlighterRef.current = utils;\n }, []);\n\n return (\n <div style={{ width: \"100%\", height: \"100%\", position: \"relative\" }}>\n <PdfLoader\n document={target.url}\n workerSrc={workerUrl ?? DEFAULT_WORKER_URL}\n beforeLoad={() =>\n loadingComponent ?? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"100%\",\n height: \"100%\",\n color: \"#888\",\n fontSize: 14,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n }}\n >\n Loading PDF…\n </div>\n )\n }\n errorMessage={(error) => {\n onLoadError?.(error);\n return (\n errorComponent ?? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"100%\",\n height: \"100%\",\n color: \"#ef4444\",\n fontSize: 14,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n }}\n >\n Failed to load PDF\n </div>\n )\n );\n }}\n >\n {(pdfDocument) => {\n /* Notify once */\n if (!loadNotifiedRef.current) {\n loadNotifiedRef.current = true;\n onLoadSuccess?.();\n }\n\n return (\n <PdfHighlighter\n pdfDocument={pdfDocument}\n highlights={highlights}\n utilsRef={handleUtilsRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n }}\n >\n <CitationHighlightRenderer />\n </PdfHighlighter>\n );\n }}\n </PdfLoader>\n </div>\n );\n}\n","import React from \"react\";\nimport type { ViewerTarget } from \"../../types/ViewerTarget\";\n\n/**\n * Renders DOCX / DOC files via the free Microsoft Office Online embed viewer.\n * The document URL must be publicly accessible.\n */\nexport function DocxRenderer({ target }: { target: ViewerTarget }) {\n const officeUrl = `https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(\n target.url\n )}`;\n\n return (\n <iframe\n src={officeUrl}\n title={target.title ?? \"Document preview\"}\n style={{\n width: \"100%\",\n height: \"100%\",\n border: \"none\",\n borderRadius: 6,\n background: \"#fff\",\n }}\n />\n );\n}\n","import React from \"react\";\nimport type { DocumentViewerProps } from \"../types/DocumentViewerProps\";\nimport { getFileType } from \"../utils/getFileType\";\nimport { PdfRenderer } from \"./renderers/PdfRenderer\";\nimport { DocxRenderer } from \"./renderers/DocxRenderer\";\n\n/**\n * Top-level component that routes to the correct renderer\n * based on the target's file type.\n *\n * ```tsx\n * <DocumentViewer\n * target={{\n * url: \"https://example.com/report.pdf\",\n * page: 3,\n * bbox: { x1: 0.1, y1: 0.2, x2: 0.5, y2: 0.3 },\n * }}\n * />\n * ```\n */\nexport function DocumentViewer({\n target,\n pdfWorkerUrl,\n loadingComponent,\n errorComponent,\n onLoadStart,\n onLoadSuccess,\n onLoadError,\n className,\n}: DocumentViewerProps) {\n if (!target) return null;\n\n const type = target.fileType ?? getFileType(target.url);\n\n const wrapperStyle: React.CSSProperties = {\n width: \"100%\",\n height: \"100%\",\n position: \"relative\",\n overflow: \"hidden\",\n borderRadius: 8,\n background: \"#fafafa\",\n };\n\n return (\n <div className={className} style={wrapperStyle}>\n {type === \"pdf\" && (\n <PdfRenderer\n target={target}\n workerUrl={pdfWorkerUrl}\n loadingComponent={loadingComponent}\n errorComponent={errorComponent}\n onLoadSuccess={onLoadSuccess}\n onLoadError={onLoadError}\n />\n )}\n\n {type === \"docx\" && <DocxRenderer target={target} />}\n\n {type === \"unknown\" && (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"100%\",\n height: \"100%\",\n color: \"#888\",\n fontSize: 14,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n }}\n >\n Unsupported file type\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsx"]}
1
+ {"version":3,"sources":["../src/components/renderers/PdfRenderer.tsx","../src/components/renderers/ImageRenderer.tsx","../src/components/DocumentViewer.tsx","../src/utils/getFileType.ts","../src/components/renderers/DocxRenderer.tsx","../src/components/renderers/JsonRenderer.tsx","../src/components/renderers/EmlRenderer.tsx"],"sourcesContent":["import React, { useRef, useEffect, useMemo, useCallback } from \"react\";\nimport {\n PdfLoader,\n PdfHighlighter,\n AreaHighlight,\n useHighlightContainerContext,\n} from \"react-pdf-highlighter-extended\";\nimport type {\n Highlight,\n ScaledPosition,\n PdfHighlighterUtils,\n} from \"react-pdf-highlighter-extended\";\nimport type { ViewerTarget } from \"../../types/ViewerTarget\";\n\n/* ------------------------------------------------------------------ */\n/* Constants */\n/* ------------------------------------------------------------------ */\n\nconst CITATION_ID = \"citation-highlight\";\n\nconst DEFAULT_WORKER_URL =\n \"https://unpkg.com/pdfjs-dist@4.4.168/build/pdf.worker.min.mjs\";\n\n/* ------------------------------------------------------------------ */\n/* BBox → Highlight conversion */\n/* ------------------------------------------------------------------ */\n\n/**\n * Convert our normalised (0-1) BBox into the Scaled coordinate system\n * used by react-pdf-highlighter-extended.\n *\n * The library internally computes:\n * viewportX = (viewportWidth × scaled.x1) / scaled.width\n *\n * So `scaled.x1 / scaled.width` must equal the normalised value.\n * We simply store the 0-1 value directly and set width / height to 1.\n */\nfunction bboxToHighlight(target: ViewerTarget): Highlight | null {\n if (!target.bbox) return null;\n\n const page = target.page ?? 1;\n const { x1, y1, x2, y2 } = target.bbox;\n\n const scaledRect = {\n x1,\n y1,\n x2,\n y2,\n width: 1,\n height: 1,\n pageNumber: page,\n };\n\n const position: ScaledPosition = {\n boundingRect: scaledRect,\n rects: [scaledRect],\n };\n\n return {\n id: CITATION_ID,\n type: \"area\",\n position,\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Highlight child renderer */\n/* ------------------------------------------------------------------ */\n\n/**\n * Rendered once per highlight by PdfHighlighter's internal loop.\n * Uses context to access the highlight's viewport position.\n */\nfunction CitationHighlightRenderer() {\n const { highlight, isScrolledTo } = useHighlightContainerContext();\n\n return (\n <AreaHighlight\n highlight={highlight}\n isScrolledTo={isScrolledTo}\n style={{\n background: isScrolledTo\n ? \"rgba(255, 171, 0, 0.35)\"\n : \"rgba(255, 171, 0, 0.2)\",\n border: \"1.5px solid rgba(255, 171, 0, 0.6)\",\n borderRadius: 2,\n transition: \"background 200ms ease\",\n }}\n />\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* PdfRenderer */\n/* ------------------------------------------------------------------ */\n\ninterface PdfRendererProps {\n target: ViewerTarget;\n workerUrl?: string;\n loadingComponent?: React.ReactNode;\n errorComponent?: React.ReactNode;\n onLoadSuccess?: () => void;\n onLoadError?: (err: Error) => void;\n}\n\nexport function PdfRenderer({\n target,\n workerUrl,\n loadingComponent,\n errorComponent,\n onLoadSuccess,\n onLoadError,\n}: PdfRendererProps) {\n const highlighterRef = useRef<PdfHighlighterUtils | null>(null);\n const loadNotifiedRef = useRef(false);\n\n /* Build highlight array from target bbox */\n const highlights = useMemo(() => {\n const h = bboxToHighlight(target);\n return h ? [h] : [];\n }, [target]);\n\n /* Scroll to the citation highlight once the viewer is ready */\n useEffect(() => {\n if (highlights.length === 0) return;\n\n const timer = setTimeout(() => {\n highlighterRef.current?.scrollToHighlight(highlights[0]);\n }, 400);\n\n return () => clearTimeout(timer);\n }, [highlights]);\n\n /* Stable callback so we don't re-trigger PdfHighlighter renders */\n const handleUtilsRef = useCallback((utils: PdfHighlighterUtils) => {\n highlighterRef.current = utils;\n }, []);\n\n return (\n <div style={{ width: \"100%\", height: \"100%\", position: \"relative\" }}>\n <PdfLoader\n document={target.url}\n workerSrc={workerUrl ?? DEFAULT_WORKER_URL}\n beforeLoad={() =>\n loadingComponent ?? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"100%\",\n height: \"100%\",\n color: \"#888\",\n fontSize: 14,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n }}\n >\n Loading PDF…\n </div>\n )\n }\n errorMessage={(error) => {\n onLoadError?.(error);\n return (\n errorComponent ?? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"100%\",\n height: \"100%\",\n color: \"#ef4444\",\n fontSize: 14,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n }}\n >\n Failed to load PDF\n </div>\n )\n );\n }}\n >\n {(pdfDocument) => {\n /* Notify once */\n if (!loadNotifiedRef.current) {\n loadNotifiedRef.current = true;\n onLoadSuccess?.();\n }\n\n return (\n <PdfHighlighter\n pdfDocument={pdfDocument}\n highlights={highlights}\n utilsRef={handleUtilsRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n }}\n >\n <CitationHighlightRenderer />\n </PdfHighlighter>\n );\n }}\n </PdfLoader>\n </div>\n );\n}\n","import React, { useState, useCallback } from \"react\";\nimport { TransformWrapper, TransformComponent } from \"react-zoom-pan-pinch\";\nimport type { ViewerTarget } from \"../../types/ViewerTarget\";\n\nconst containerStyle: React.CSSProperties = {\n position: \"relative\",\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n overflow: \"hidden\",\n background: \"#1a1a1a\",\n};\n\nconst imageStyle: React.CSSProperties = {\n maxWidth: \"100%\",\n maxHeight: \"100%\",\n objectFit: \"contain\",\n display: \"block\",\n};\n\n/**\n * Renders image files with pan, zoom, and pinch support.\n * Uses react-zoom-pan-pinch for touch and mouse gestures.\n */\nexport function ImageRenderer({\n target,\n loadingComponent,\n errorComponent,\n onLoadSuccess,\n onLoadError,\n}: {\n target: ViewerTarget;\n loadingComponent?: React.ReactNode;\n errorComponent?: React.ReactNode;\n onLoadSuccess?: () => void;\n onLoadError?: (err: Error) => void;\n}) {\n const [status, setStatus] = useState<\"loading\" | \"success\" | \"error\">(\"loading\");\n const [error, setError] = useState<Error | null>(null);\n\n const handleLoad = useCallback(() => {\n setStatus(\"success\");\n onLoadSuccess?.();\n }, [onLoadSuccess]);\n\n const handleError = useCallback(() => {\n const err = new Error(\"Failed to load image\");\n setError(err);\n setStatus(\"error\");\n onLoadError?.(err);\n }, [onLoadError]);\n\n if (status === \"error\") {\n return (\n <div style={containerStyle}>\n {errorComponent ?? (\n <div\n style={{\n color: \"#ef4444\",\n fontSize: 14,\n fontFamily: 'system-ui, \"Segoe UI\", Roboto, sans-serif',\n }}\n >\n Failed to load image\n </div>\n )}\n </div>\n );\n }\n\n return (\n <div style={containerStyle}>\n <TransformWrapper\n initialScale={1}\n minScale={0.5}\n maxScale={8}\n centerOnInit\n limitToBounds={false}\n panning={{ velocityDisabled: true }}\n doubleClick={{ mode: \"reset\" }}\n >\n <TransformComponent\n wrapperStyle={{ width: \"100%\", height: \"100%\", cursor: \"grab\" }}\n contentStyle={containerStyle}\n >\n <img\n src={target.url}\n alt={target.title ?? \"Document\"}\n style={imageStyle}\n onLoad={handleLoad}\n onError={handleError}\n draggable={false}\n />\n </TransformComponent>\n </TransformWrapper>\n {status === \"loading\" &&\n (loadingComponent ?? (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#888\",\n fontSize: 14,\n fontFamily: 'system-ui, \"Segoe UI\", Roboto, sans-serif',\n }}\n >\n Loading image…\n </div>\n ))}\n </div>\n );\n}\n","import React, { lazy, Suspense, useState, useEffect } from \"react\";\nimport type { DocumentViewerProps } from \"../types/DocumentViewerProps\";\nimport { getFileType } from \"../utils/getFileType\";\nimport { DocxRenderer } from \"./renderers/DocxRenderer\";\nimport { JsonRenderer } from \"./renderers/JsonRenderer\";\nimport { EmlRenderer } from \"./renderers/EmlRenderer\";\n\n/* ------------------------------------------------------------------ */\n/* Lazy-load PDF so pdfjs-dist never runs on the server. */\n/* ------------------------------------------------------------------ */\nconst LazyPdfRenderer = lazy(() =>\n import(\"./renderers/PdfRenderer\").then((mod) => ({\n default: mod.PdfRenderer,\n }))\n);\n\n/* ------------------------------------------------------------------ */\n/* Lazy-load Image so react-zoom-pan-pinch (DOM) never runs on SSR. */\n/* ------------------------------------------------------------------ */\nconst LazyImageRenderer = lazy(() =>\n import(\"./renderers/ImageRenderer\").then((mod) => ({\n default: mod.ImageRenderer,\n }))\n);\n\n/**\n * Tiny wrapper that defers children until after first client-side mount.\n * Prevents any browser-only code from executing during SSR.\n */\nfunction ClientOnly({\n children,\n fallback,\n}: {\n children: React.ReactNode;\n fallback?: React.ReactNode;\n}) {\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n if (!mounted) return <>{fallback ?? null}</>;\n return <>{children}</>;\n}\n\n/**\n * Top-level component that routes to the correct renderer\n * based on the target's file type.\n *\n * ```tsx\n * <DocumentViewer\n * target={{\n * url: \"https://example.com/report.pdf\",\n * page: 3,\n * bbox: { x1: 0.1, y1: 0.2, x2: 0.5, y2: 0.3 },\n * }}\n * />\n * ```\n */\nexport function DocumentViewer({\n target,\n pdfWorkerUrl,\n loadingComponent,\n errorComponent,\n onLoadStart,\n onLoadSuccess,\n onLoadError,\n className,\n}: DocumentViewerProps) {\n if (!target) return null;\n\n const type = target.fileType ?? getFileType(target.url);\n\n const wrapperStyle: React.CSSProperties = {\n width: \"100%\",\n height: \"100%\",\n position: \"relative\",\n overflow: \"hidden\",\n borderRadius: 8,\n background: \"#fafafa\",\n };\n\n const loadingFallback = loadingComponent ?? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"100%\",\n height: \"100%\",\n color: \"#888\",\n fontSize: 14,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n }}\n >\n Loading…\n </div>\n );\n\n return (\n <div className={className} style={wrapperStyle}>\n {type === \"pdf\" && (\n <ClientOnly fallback={loadingFallback}>\n <Suspense fallback={loadingFallback}>\n <LazyPdfRenderer\n target={target}\n workerUrl={pdfWorkerUrl}\n loadingComponent={loadingComponent}\n errorComponent={errorComponent}\n onLoadSuccess={onLoadSuccess}\n onLoadError={onLoadError}\n />\n </Suspense>\n </ClientOnly>\n )}\n\n {type === \"docx\" && <DocxRenderer target={target} />}\n\n {type === \"image\" && (\n <ClientOnly fallback={loadingFallback}>\n <Suspense fallback={loadingFallback}>\n <LazyImageRenderer\n target={target}\n loadingComponent={loadingComponent}\n errorComponent={errorComponent}\n onLoadSuccess={onLoadSuccess}\n onLoadError={onLoadError}\n />\n </Suspense>\n </ClientOnly>\n )}\n\n {type === \"json\" && (\n <JsonRenderer\n target={target}\n loadingComponent={loadingComponent}\n errorComponent={errorComponent}\n onLoadSuccess={onLoadSuccess}\n onLoadError={onLoadError}\n />\n )}\n\n {type === \"eml\" && (\n <EmlRenderer\n target={target}\n loadingComponent={loadingComponent}\n errorComponent={errorComponent}\n onLoadSuccess={onLoadSuccess}\n onLoadError={onLoadError}\n />\n )}\n\n {type === \"unknown\" && (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"100%\",\n height: \"100%\",\n color: \"#888\",\n fontSize: 14,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n }}\n >\n Unsupported file type\n </div>\n )}\n </div>\n );\n}\n","import type { ViewerFileType } from \"../types/ViewerTarget\";\n\nconst IMAGE_EXT = [\".jpg\", \".jpeg\", \".png\", \".gif\", \".webp\", \".bmp\", \".avif\", \".svg\"];\nconst JSON_EXT = [\".json\"];\nconst EML_EXT = [\".eml\"];\n\n/**\n * Infer document type from URL extension.\n * Strips query-strings and fragments before matching.\n */\nexport function getFileType(url: string): ViewerFileType | \"unknown\" {\n const clean = url.split(\"?\")[0].split(\"#\")[0].toLowerCase();\n\n if (clean.endsWith(\".pdf\")) return \"pdf\";\n if (clean.endsWith(\".docx\") || clean.endsWith(\".doc\")) return \"docx\";\n if (IMAGE_EXT.some((e) => clean.endsWith(e))) return \"image\";\n if (JSON_EXT.some((e) => clean.endsWith(e))) return \"json\";\n if (EML_EXT.some((e) => clean.endsWith(e))) return \"eml\";\n\n return \"unknown\";\n}\n","import React from \"react\";\nimport type { ViewerTarget } from \"../../types/ViewerTarget\";\n\n/**\n * Renders DOCX / DOC files via the free Microsoft Office Online embed viewer.\n * The document URL must be publicly accessible.\n */\nexport function DocxRenderer({ target }: { target: ViewerTarget }) {\n const officeUrl = `https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(\n target.url\n )}`;\n\n return (\n <iframe\n src={officeUrl}\n title={target.title ?? \"Document preview\"}\n style={{\n width: \"100%\",\n height: \"100%\",\n border: \"none\",\n borderRadius: 6,\n background: \"#fff\",\n }}\n />\n );\n}\n","import React, { useState, useEffect, useCallback } from \"react\";\nimport type { ViewerTarget } from \"../../types/ViewerTarget\";\n\nconst containerStyle: React.CSSProperties = {\n width: \"100%\",\n height: \"100%\",\n overflow: \"auto\",\n background: \"#0d1117\",\n padding: 16,\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n fontSize: 13,\n lineHeight: 1.5,\n};\n\ntype JsonNode =\n | { type: \"string\"; value: string; key?: string }\n | { type: \"number\"; value: number; key?: string }\n | { type: \"boolean\"; value: boolean; key?: string }\n | { type: \"null\"; key?: string }\n | { type: \"array\"; children: JsonNode[]; key?: string; open: boolean }\n | { type: \"object\"; children: { key: string; value: JsonNode }[]; key?: string; open: boolean };\n\nfunction formatKey(key: string): string {\n return JSON.stringify(key);\n}\n\nfunction JsonTree({ node, depth = 0 }: { node: JsonNode; depth?: number }) {\n const [open, setOpen] = useState(\n node.type === \"array\" || node.type === \"object\" ? node.open : true\n );\n const isOpen = node.type === \"array\" || node.type === \"object\" ? open : true;\n const indent = depth * 18;\n\n if (node.type === \"string\") {\n return (\n <span>\n {node.key != null && <span style={{ color: \"#79c0ff\" }}>{formatKey(node.key)}</span>}\n {node.key != null && <span style={{ color: \"#6e7681\" }}>: </span>}\n <span style={{ color: \"#a5d6ff\" }}>{JSON.stringify(node.value)}</span>\n </span>\n );\n }\n if (node.type === \"number\") {\n return (\n <span>\n {node.key != null && <span style={{ color: \"#79c0ff\" }}>{formatKey(node.key)}</span>}\n {node.key != null && <span style={{ color: \"#6e7681\" }}>: </span>}\n <span style={{ color: \"#79c0ff\" }}>{node.value}</span>\n </span>\n );\n }\n if (node.type === \"boolean\") {\n return (\n <span>\n {node.key != null && <span style={{ color: \"#79c0ff\" }}>{formatKey(node.key)}</span>}\n {node.key != null && <span style={{ color: \"#6e7681\" }}>: </span>}\n <span style={{ color: \"#ff7b72\" }}>{String(node.value)}</span>\n </span>\n );\n }\n if (node.type === \"null\") {\n return (\n <span>\n {node.key != null && <span style={{ color: \"#79c0ff\" }}>{formatKey(node.key)}</span>}\n {node.key != null && <span style={{ color: \"#6e7681\" }}>: </span>}\n <span style={{ color: \"#6e7681\" }}>null</span>\n </span>\n );\n }\n if (node.type === \"array\") {\n const bracket = isOpen ? \"[\" : \"[ … ]\";\n return (\n <div style={{ marginLeft: indent }}>\n <span\n onClick={() => (node.children.length > 0 ? setOpen(!open) : null)}\n style={{\n cursor: node.children.length > 0 ? \"pointer\" : \"default\",\n color: \"#ffa657\",\n }}\n >\n {node.key != null && (\n <>\n <span style={{ color: \"#79c0ff\" }}>{formatKey(node.key)}</span>\n <span style={{ color: \"#6e7681\" }}>: </span>\n </>\n )}\n {bracket}\n </span>\n {isOpen &&\n node.children.map((child, i) => (\n <div key={i}>\n <JsonTree node={child} depth={depth + 1} />\n {i < node.children.length - 1 && \",\"}\n </div>\n ))}\n {isOpen && <span style={{ color: \"#ffa657\" }}>]</span>}\n </div>\n );\n }\n if (node.type === \"object\") {\n const brace = isOpen ? \"{\" : \"{ … }\";\n return (\n <div style={{ marginLeft: indent }}>\n <span\n onClick={() => (node.children.length > 0 ? setOpen(!open) : null)}\n style={{\n cursor: node.children.length > 0 ? \"pointer\" : \"default\",\n color: \"#ffa657\",\n }}\n >\n {node.key != null && (\n <>\n <span style={{ color: \"#79c0ff\" }}>{formatKey(node.key)}</span>\n <span style={{ color: \"#6e7681\" }}>: </span>\n </>\n )}\n {brace}\n </span>\n {isOpen &&\n node.children.map(({ key, value }, i) => (\n <div key={key}>\n <JsonTree node={{ ...value, key }} depth={depth + 1} />\n {i < node.children.length - 1 && \",\"}\n </div>\n ))}\n {isOpen && <span style={{ color: \"#ffa657\" }}>{\"}\"}</span>}\n </div>\n );\n }\n return null;\n}\n\nfunction parseToTree(value: unknown): JsonNode {\n if (value === null) return { type: \"null\" };\n if (typeof value === \"string\") return { type: \"string\", value };\n if (typeof value === \"number\") return { type: \"number\", value };\n if (typeof value === \"boolean\") return { type: \"boolean\", value };\n if (Array.isArray(value)) {\n return {\n type: \"array\",\n children: value.map((v) => parseToTree(v)),\n open: value.length <= 3,\n };\n }\n if (typeof value === \"object\" && value !== null) {\n const obj = value as Record<string, unknown>;\n return {\n type: \"object\",\n children: Object.entries(obj).map(([k, v]) => ({ key: k, value: parseToTree(v) })),\n open: Object.keys(obj).length <= 5,\n };\n }\n return { type: \"null\" };\n}\n\n/**\n * Renders JSON from a URL with syntax highlighting and collapsible tree.\n * Fetches the URL; CORS must allow it or use a proxy.\n */\nexport function JsonRenderer({\n target,\n loadingComponent,\n errorComponent,\n onLoadSuccess,\n onLoadError,\n}: {\n target: ViewerTarget;\n loadingComponent?: React.ReactNode;\n errorComponent?: React.ReactNode;\n onLoadSuccess?: () => void;\n onLoadError?: (err: Error) => void;\n}) {\n const [state, setState] = useState<\n { status: \"loading\" } | { status: \"success\"; tree: JsonNode } | { status: \"error\"; error: Error }\n >({ status: \"loading\" });\n\n const load = useCallback(async () => {\n try {\n const res = await fetch(target.url, { credentials: \"omit\" });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const raw = await res.text();\n const data = JSON.parse(raw) as unknown;\n setState({ status: \"success\", tree: parseToTree(data) });\n onLoadSuccess?.();\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setState({ status: \"error\", error });\n onLoadError?.(error);\n }\n }, [target.url, onLoadSuccess, onLoadError]);\n\n useEffect(() => {\n load();\n }, [load]);\n\n if (state.status === \"loading\") {\n return (\n <div style={containerStyle}>\n {loadingComponent ?? (\n <div style={{ color: \"#8b949e\" }}>Loading JSON…</div>\n )}\n </div>\n );\n }\n\n if (state.status === \"error\") {\n return (\n <div style={containerStyle}>\n {errorComponent ?? (\n <div style={{ color: \"#f85149\" }}>\n Failed to load JSON: {state.error.message}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <div style={containerStyle}>\n <JsonTree node={state.tree} />\n </div>\n );\n}\n","import React, { useState, useEffect, useCallback } from \"react\";\nimport DOMPurify from \"dompurify\";\nimport type { ViewerTarget } from \"../../types/ViewerTarget\";\n\nconst containerStyle: React.CSSProperties = {\n width: \"100%\",\n height: \"100%\",\n overflow: \"auto\",\n background: \"#fff\",\n fontFamily: 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif',\n fontSize: 14,\n lineHeight: 1.5,\n};\n\ntype ParsedEml = {\n headers: Array<{ key: string; value: string }>;\n bodyText: string | null;\n bodyHtml: string | null;\n};\n\n/**\n * Minimal MIME/EML parser: extracts headers and the first text/plain or text/html part.\n * Does not handle nested multipart or attachments; sufficient for typical .eml preview.\n */\nfunction parseEml(raw: string): ParsedEml {\n const lines = raw.split(/\\r?\\n/);\n const headers: Array<{ key: string; value: string }> = [];\n let i = 0;\n let currentKey: string | null = null;\n let currentValue: string[] = [];\n\n while (i < lines.length) {\n const line = lines[i];\n if (line === \"\") {\n i++;\n break;\n }\n const match = line.match(/^([\\w-]+):\\s*(.*)$/);\n if (match) {\n if (currentKey) {\n headers.push({ key: currentKey, value: currentValue.join(\" \").trim() });\n }\n currentKey = match[1];\n currentValue = [match[2]];\n } else if (currentKey && /^\\s/.test(line)) {\n currentValue.push(line.trim());\n }\n i++;\n }\n\n if (currentKey) {\n headers.push({ key: currentKey, value: currentValue.join(\" \").trim() });\n }\n\n const rest = lines.slice(i).join(\"\\n\");\n const contentType = headers.find(\n (h) => h.key.toLowerCase() === \"content-type\"\n )?.value ?? \"text/plain\";\n const isMultipart = contentType.toLowerCase().includes(\"multipart\");\n let bodyText: string | null = null;\n let bodyHtml: string | null = null;\n\n if (!isMultipart) {\n bodyText = rest.trim() || null;\n if (contentType.toLowerCase().includes(\"text/html\")) {\n bodyHtml = bodyText;\n bodyText = null;\n }\n return { headers, bodyText, bodyHtml };\n }\n\n const boundaryMatch = contentType.match(/boundary\\s*=\\s*[\"']?([^\"'\\s;]+)[\"']?/i);\n const boundary = boundaryMatch?.[1]?.trim();\n if (!boundary) {\n bodyText = rest.trim() || null;\n return { headers, bodyText, bodyHtml: null };\n }\n\n const parts = rest.split(new RegExp(`\\\\r?\\\\n--${escapeRegExp(boundary)}(?:\\\\r?\\\\n|--)`));\n for (const part of parts) {\n if (!part.trim()) continue;\n const [head, ...bodyLines] = part.split(/\\r?\\n\\r?\\n/);\n const body = bodyLines.join(\"\\n\\n\").trim();\n const partType = (head.match(/Content-Type:\\s*([^;\\s]+)/i) ?? [])[1]?.toLowerCase();\n if (partType?.includes(\"text/plain\") && !bodyText) bodyText = body;\n if (partType?.includes(\"text/html\") && !bodyHtml) bodyHtml = body;\n }\n if (!bodyText && !bodyHtml && parts[1]) {\n const [head, ...bodyLines] = parts[1].split(/\\r?\\n\\r?\\n/);\n const body = bodyLines.join(\"\\n\\n\").trim();\n const partType = (head.match(/Content-Type:\\s*([^;\\s]+)/i) ?? [])[1]?.toLowerCase();\n if (partType?.includes(\"text/html\")) bodyHtml = body;\n else bodyText = body;\n }\n\n return { headers, bodyText, bodyHtml };\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nconst HEADER_KEYS = [\"from\", \"to\", \"cc\", \"bcc\", \"subject\", \"date\", \"reply-to\"];\n\n/**\n * Renders .eml (email) files: fetches URL, parses MIME, displays headers and body.\n * HTML body is sanitized with DOMPurify before rendering.\n */\nexport function EmlRenderer({\n target,\n loadingComponent,\n errorComponent,\n onLoadSuccess,\n onLoadError,\n}: {\n target: ViewerTarget;\n loadingComponent?: React.ReactNode;\n errorComponent?: React.ReactNode;\n onLoadSuccess?: () => void;\n onLoadError?: (err: Error) => void;\n}) {\n const [state, setState] = useState<\n | { status: \"loading\" }\n | { status: \"success\"; data: ParsedEml }\n | { status: \"error\"; error: Error }\n >({ status: \"loading\" });\n\n const load = useCallback(async () => {\n try {\n const res = await fetch(target.url, { credentials: \"omit\" });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const raw = await res.text();\n const data = parseEml(raw);\n setState({ status: \"success\", data });\n onLoadSuccess?.();\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setState({ status: \"error\", error });\n onLoadError?.(error);\n }\n }, [target.url, onLoadSuccess, onLoadError]);\n\n useEffect(() => {\n load();\n }, [load]);\n\n if (state.status === \"loading\") {\n return (\n <div style={containerStyle}>\n {loadingComponent ?? (\n <div style={{ padding: 24, color: \"#666\" }}>Loading email…</div>\n )}\n </div>\n );\n }\n\n if (state.status === \"error\") {\n return (\n <div style={containerStyle}>\n {errorComponent ?? (\n <div style={{ padding: 24, color: \"#dc2626\" }}>\n Failed to load email: {state.error.message}\n </div>\n )}\n </div>\n );\n }\n\n const { headers, bodyText, bodyHtml } = state.data;\n const preferredHeaders = HEADER_KEYS.filter((k) =>\n headers.some((h) => h.key.toLowerCase() === k)\n );\n const otherHeaders = headers.filter(\n (h) => !HEADER_KEYS.includes(h.key.toLowerCase())\n );\n\n return (\n <div style={containerStyle}>\n <div style={{ padding: 24, borderBottom: \"1px solid #e5e7eb\" }}>\n {preferredHeaders.map((key) => {\n const h = headers.find((x) => x.key.toLowerCase() === key);\n if (!h) return null;\n return (\n <div key={h.key} style={{ marginBottom: 8 }}>\n <span style={{ color: \"#6b7280\", fontWeight: 600, marginRight: 8 }}>\n {h.key}:\n </span>\n <span style={{ color: \"#111\" }}>{h.value}</span>\n </div>\n );\n })}\n {otherHeaders.length > 0 && (\n <details style={{ marginTop: 12 }}>\n <summary style={{ color: \"#6b7280\", cursor: \"pointer\", fontSize: 13 }}>\n Other headers\n </summary>\n <div style={{ marginTop: 8 }}>\n {otherHeaders.map((h) => (\n <div key={h.key} style={{ marginBottom: 4, fontSize: 13 }}>\n <span style={{ color: \"#6b7280\" }}>{h.key}: </span>\n <span style={{ color: \"#374151\" }}>{h.value}</span>\n </div>\n ))}\n </div>\n </details>\n )}\n </div>\n <div style={{ padding: 24 }}>\n {bodyHtml ? (\n <div\n className=\"document-viewer-eml-body\"\n style={{ maxWidth: 720, overflow: \"auto\" }}\n dangerouslySetInnerHTML={{\n __html: DOMPurify.sanitize(bodyHtml, {\n ALLOWED_TAGS: [\n \"p\", \"br\", \"div\", \"span\", \"a\", \"strong\", \"em\", \"u\", \"b\", \"i\",\n \"ul\", \"ol\", \"li\", \"h1\", \"h2\", \"h3\", \"h4\", \"table\", \"tr\", \"td\", \"th\", \"tbody\", \"thead\",\n \"img\", \"blockquote\", \"hr\", \"pre\", \"code\",\n ],\n ALLOWED_ATTR: [\"href\", \"src\", \"alt\", \"title\", \"target\"],\n }),\n }}\n />\n ) : bodyText ? (\n <pre\n style={{\n margin: 0,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n color: \"#374151\",\n fontFamily: \"inherit\",\n fontSize: \"inherit\",\n }}\n >\n {bodyText}\n </pre>\n ) : (\n <div style={{ color: \"#6b7280\" }}>No body content</div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["useEffect","useCallback","jsx","useState","useCallback","jsx","jsxs","containerStyle","useState","useEffect","jsx","useState","useEffect","useCallback","jsx","jsxs","containerStyle","Fragment","jsx","jsxs","useState","useEffect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relevaince/document-viewer",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Citation-driven document viewer for Relevaince",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -24,10 +24,13 @@
24
24
  "react-dom": ">=18"
25
25
  },
26
26
  "dependencies": {
27
+ "dompurify": "^3.2.2",
27
28
  "pdfjs-dist": "^4.4.168",
28
- "react-pdf-highlighter-extended": "^8.1.0"
29
+ "react-pdf-highlighter-extended": "^8.1.0",
30
+ "react-zoom-pan-pinch": "^3.6.1"
29
31
  },
30
32
  "devDependencies": {
33
+ "@types/dompurify": "^3.0.5",
31
34
  "@types/react": "^18.3.28",
32
35
  "@types/react-dom": "^18.3.7",
33
36
  "tsup": "^8.5.1",
@@ -37,6 +40,10 @@
37
40
  "document-viewer",
38
41
  "pdf",
39
42
  "docx",
43
+ "image",
44
+ "json",
45
+ "eml",
46
+ "email",
40
47
  "citation",
41
48
  "react"
42
49
  ],