react-docxodus-viewer 0.5.1 → 0.7.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.
- package/README.md +1 -0
- package/dist/react-docxodus-viewer.cjs.js +2 -2
- package/dist/react-docxodus-viewer.cjs.js.map +1 -1
- package/dist/react-docxodus-viewer.css +2 -1
- package/dist/react-docxodus-viewer.es.js +1131 -983
- package/dist/react-docxodus-viewer.es.js.map +1 -1
- package/dist/types/DocumentViewer.d.ts +1 -1
- package/dist/types/DocumentViewer.d.ts.map +1 -1
- package/dist/types/components/RevisionPanel.d.ts +1 -1
- package/dist/types/components/RevisionPanel.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +15 -0
- package/dist/types/types/index.d.ts.map +1 -1
- package/package.json +10 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-docxodus-viewer.cjs.js","sources":["../node_modules/docxodus/dist/worker-proxy.js","../src/types/index.ts","../src/components/RevisionPanel.tsx","../src/DocumentViewer.tsx"],"sourcesContent":["/**\n * Worker Proxy - Main thread interface for the Docxodus Web Worker\n *\n * This module provides a Promise-based API that mirrors the main API but\n * executes all WASM operations in a Web Worker, keeping the main thread free.\n *\n * @example\n * ```typescript\n * import { createWorkerDocxodus } from 'docxodus/worker';\n *\n * // Create worker instance\n * const docxodus = await createWorkerDocxodus();\n *\n * // Use the same API as the main module, but non-blocking!\n * const html = await docxodus.convertDocxToHtml(docxFile);\n *\n * // Clean up when done\n * docxodus.terminate();\n * ```\n */\n/**\n * Generate a unique request ID.\n */\nfunction generateId() {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n/**\n * Convert a File or Uint8Array to Uint8Array.\n */\nasync function toBytes(document) {\n if (document instanceof Uint8Array) {\n return document;\n }\n const buffer = await document.arrayBuffer();\n return new Uint8Array(buffer);\n}\n/**\n * Derive the WASM base path from the current module URL.\n */\nfunction deriveWasmBasePath() {\n // Try to get the base path from the current script URL\n if (typeof document !== \"undefined\") {\n // Browser: look for docxodus script tag or use current location\n const scripts = document.querySelectorAll('script[src*=\"docxodus\"]');\n if (scripts.length > 0) {\n const src = scripts[0].src;\n const base = src.substring(0, src.lastIndexOf(\"/\") + 1);\n return base + \"wasm/\";\n }\n }\n // Default fallback\n return \"/wasm/\";\n}\n/**\n * Create a worker-based Docxodus instance.\n *\n * This function spawns a Web Worker that loads the WASM runtime independently.\n * All operations are executed in the worker, keeping the main thread responsive.\n *\n * @param options - Configuration options\n * @returns A Promise that resolves to a WorkerDocxodus instance\n *\n * @example\n * ```typescript\n * // Basic usage\n * const docxodus = await createWorkerDocxodus();\n * const html = await docxodus.convertDocxToHtml(docxFile);\n *\n * // With custom WASM path\n * const docxodus = await createWorkerDocxodus({\n * wasmBasePath: '/assets/wasm/'\n * });\n * ```\n */\nexport async function createWorkerDocxodus(options) {\n // Determine WASM base path\n const wasmBasePath = options?.wasmBasePath ?? deriveWasmBasePath();\n // Determine worker script path\n // The worker bundle should be in the same directory as this module\n let workerUrl;\n // Try to create worker from bundled script or blob\n // For now, we'll use a blob URL to inline the worker path\n const workerScriptPath = new URL(\"./docxodus.worker.js\", import.meta.url)\n .href;\n // Create the worker\n const worker = new Worker(workerScriptPath, { type: \"module\" });\n // Track pending requests\n const pendingRequests = new Map();\n // Track if worker is active\n let isWorkerActive = true;\n // Handle worker messages\n worker.onmessage = (event) => {\n const response = event.data;\n // Handle ready signal\n if (response.type === \"ready\") {\n return;\n }\n // Handle normal responses\n const pending = pendingRequests.get(response.id);\n if (pending) {\n pendingRequests.delete(response.id);\n if (response.success) {\n pending.resolve(response);\n }\n else {\n pending.reject(new Error(response.error || \"Unknown error\"));\n }\n }\n };\n // Handle worker errors\n worker.onerror = (error) => {\n // Reject all pending requests\n for (const pending of pendingRequests.values()) {\n pending.reject(new Error(`Worker error: ${error.message}`));\n }\n pendingRequests.clear();\n isWorkerActive = false;\n };\n /**\n * Send a request to the worker and wait for response.\n */\n function sendRequest(request, transfer) {\n return new Promise((resolve, reject) => {\n if (!isWorkerActive) {\n reject(new Error(\"Worker has been terminated\"));\n return;\n }\n pendingRequests.set(request.id, { resolve, reject });\n if (transfer && transfer.length > 0) {\n worker.postMessage(request, transfer);\n }\n else {\n worker.postMessage(request);\n }\n });\n }\n // Initialize the worker\n const initResponse = await sendRequest({\n id: generateId(),\n type: \"init\",\n wasmBasePath,\n });\n if (!initResponse.success) {\n worker.terminate();\n throw new Error(`Failed to initialize worker: ${initResponse.error}`);\n }\n // Return the WorkerDocxodus instance\n return {\n async convertDocxToHtml(document, options) {\n const bytes = await toBytes(document);\n const response = await sendRequest({\n id: generateId(),\n type: \"convertDocxToHtml\",\n documentBytes: bytes,\n options,\n }, [bytes.buffer]);\n return response.html;\n },\n async compareDocuments(original, modified, options) {\n const originalBytes = await toBytes(original);\n const modifiedBytes = await toBytes(modified);\n const response = await sendRequest({\n id: generateId(),\n type: \"compareDocuments\",\n originalBytes,\n modifiedBytes,\n options,\n }, [originalBytes.buffer, modifiedBytes.buffer]);\n return response.documentBytes;\n },\n async compareDocumentsToHtml(original, modified, options) {\n const originalBytes = await toBytes(original);\n const modifiedBytes = await toBytes(modified);\n const response = await sendRequest({\n id: generateId(),\n type: \"compareDocumentsToHtml\",\n originalBytes,\n modifiedBytes,\n options,\n }, [originalBytes.buffer, modifiedBytes.buffer]);\n return response.html;\n },\n async getRevisions(document, options) {\n const bytes = await toBytes(document);\n const response = await sendRequest({\n id: generateId(),\n type: \"getRevisions\",\n documentBytes: bytes,\n options,\n }, [bytes.buffer]);\n return response.revisions;\n },\n async getDocumentMetadata(document) {\n const bytes = await toBytes(document);\n const response = await sendRequest({\n id: generateId(),\n type: \"getDocumentMetadata\",\n documentBytes: bytes,\n }, [bytes.buffer]);\n return response.metadata;\n },\n async getVersion() {\n const response = await sendRequest({\n id: generateId(),\n type: \"getVersion\",\n });\n return response.version;\n },\n terminate() {\n isWorkerActive = false;\n worker.terminate();\n // Reject any pending requests\n for (const pending of pendingRequests.values()) {\n pending.reject(new Error(\"Worker terminated\"));\n }\n pendingRequests.clear();\n },\n isActive() {\n return isWorkerActive;\n },\n };\n}\n/**\n * Check if Web Workers are supported in the current environment.\n */\nexport function isWorkerSupported() {\n return typeof Worker !== \"undefined\";\n}\n//# sourceMappingURL=worker-proxy.js.map","/**\n * react-docxodus-viewer types\n */\n\nexport type CommentMode = 'disabled' | 'endnote' | 'inline' | 'margin';\nexport type AnnotationMode = 'disabled' | 'above' | 'inline' | 'tooltip' | 'none';\nexport type ViewMode = 'document' | 'revisions';\n/**\n * Automatic zoom-fit mode.\n * - `manual` (default): user controls zoom via the toolbar.\n * - `page-width`: scale so a page's width fills the viewer.\n * - `page`: scale so an entire page fits in the viewer (width and height).\n * Recomputes on initial render and on viewer resize.\n */\nexport type FitMode = 'manual' | 'page-width' | 'page';\n\nexport interface ViewerSettings {\n /** Zoom scale (0.3 - 2.0) */\n paginationScale: number;\n /** Show page numbers on pages */\n showPageNumbers: boolean;\n /** Render footnotes and endnotes */\n renderFootnotesAndEndnotes: boolean;\n /** Render headers and footers */\n renderHeadersAndFooters: boolean;\n /** Comment rendering mode */\n commentMode: CommentMode;\n /** Annotation rendering mode */\n annotationMode: AnnotationMode;\n /** Show tracked changes */\n renderTrackedChanges: boolean;\n /** Show deleted content in tracked changes */\n showDeletedContent: boolean;\n /** Distinguish move operations in tracked changes */\n renderMoveOperations: boolean;\n /** Page title for converted HTML */\n pageTitle: string;\n /** CSS class prefix for generated elements */\n cssPrefix: string;\n /** Generate CSS classes for styling */\n fabricateClasses: boolean;\n /** Additional CSS to inject */\n additionalCss: string;\n /** CSS class prefix for comments */\n commentCssClassPrefix: string;\n /** CSS class prefix for annotations */\n annotationCssClassPrefix: string;\n /**\n * Show placeholders for unsupported content (WMF/EMF images, math equations, form fields, etc.)\n * When enabled, unsupported content displays as styled placeholders instead of being silently dropped.\n */\n renderUnsupportedContentPlaceholders: boolean;\n /**\n * Override the document's default language for the HTML lang attribute.\n * If empty, the language is auto-detected from document settings.\n * Examples: \"en-US\", \"fr-FR\", \"de-DE\", \"ja-JP\"\n */\n documentLanguage: string;\n /**\n * Fixed width for the page container.\n * Accepts a number (pixels) or CSS length string (e.g., \"80vw\", \"100%\", \"50rem\").\n * When set, the viewer maintains this width regardless of content or zoom level,\n * providing pdf.js-like stable sizing behavior. The pages will be centered within\n * this container, and the container will scroll horizontally if content exceeds it.\n * Set to undefined/null for flexible sizing that adapts to content.\n * @example 816 // pixels\n * @example \"80vw\" // viewport width\n * @example \"100%\" // percentage of parent\n */\n stableWidth?: number | string;\n /**\n * Fixed minimum height for the page container.\n * Accepts a number (pixels) or CSS length string (e.g., \"60vh\", \"500px\", \"100%\").\n * When set, the viewer reserves this much vertical space regardless of content,\n * preventing layout shifts during loading. Set to undefined/null for flexible sizing.\n * @example 600 // pixels\n * @example \"70vh\" // viewport height\n * @example \"100%\" // percentage of parent\n */\n stableHeight?: number | string;\n}\n\n/**\n * A custom action button that can be injected into the viewer's toolbar.\n * Renders as an icon button on the right side of the toolbar (before the\n * settings gear), styled to match the built-in toolbar buttons.\n */\nexport interface ToolbarAction {\n /** Stable React key for this action. */\n key: string;\n /**\n * The icon to render inside the button. Accepts any React node — an inline\n * SVG, an icon-library component, an emoji, or a single character. Sized\n * via the parent button (~16px).\n */\n icon: React.ReactNode;\n /**\n * Accessible label, also shown as a tooltip on hover.\n */\n label: string;\n /** Click handler. */\n onClick: () => void;\n /** Disable the button. */\n disabled?: boolean;\n /**\n * Visual variant.\n * - `default`: matches existing toolbar buttons.\n * - `primary`: filled accent color, useful for the main action (e.g. Download).\n */\n variant?: 'default' | 'primary';\n /** Optional extra className appended to the button. */\n className?: string;\n}\n\nexport interface DocumentViewerProps {\n /** File to display (controlled mode) */\n file?: File | null;\n /** Pre-converted HTML content (skip conversion) */\n html?: string | null;\n\n /** Callback when file changes */\n onFileChange?: (file: File | null) => void;\n /** Callback when conversion starts */\n onConversionStart?: () => void;\n /** Callback when conversion completes successfully */\n onConversionComplete?: (html: string) => void;\n /** Callback when an error occurs */\n onError?: (error: Error) => void;\n /** Callback when visible page changes */\n onPageChange?: (page: number, total: number) => void;\n /** Callback when revisions are extracted from document */\n onRevisionsExtracted?: (revisions: import('docxodus').Revision[]) => void;\n\n /** Initial/controlled viewer settings */\n settings?: Partial<ViewerSettings>;\n /** Default settings (used for uncontrolled mode) */\n defaultSettings?: Partial<ViewerSettings>;\n /**\n * Convenience shortcut for the initial zoom level (uncontrolled mode).\n * Equivalent to `defaultSettings.paginationScale`. Range 0.3 – 2.0.\n * Ignored if `fitMode` is set to anything other than `'manual'`,\n * since the auto-fit logic will override the initial scale.\n * @example 1 // 100%\n * @example 0.75 // 75%\n */\n defaultZoom?: number;\n /** Callback when settings change */\n onSettingsChange?: (settings: ViewerSettings) => void;\n\n /** Additional CSS class for the root element */\n className?: string;\n /** Inline styles for the root element */\n style?: React.CSSProperties;\n /** Toolbar position */\n toolbar?: 'top' | 'bottom' | 'none';\n /** Show settings button in toolbar */\n showSettingsButton?: boolean;\n /** Show revisions tab when document has tracked changes */\n showRevisionsTab?: boolean;\n /** Placeholder text when no document is loaded */\n placeholder?: string;\n /**\n * Custom icon-button actions to render in the toolbar's right section,\n * just before the settings button. Useful for hosting apps that want to\n * surface document-level actions (Download, Share, Print, Open Ticket, ...)\n * inside the viewer's chrome rather than awkwardly above it.\n */\n toolbarActions?: ToolbarAction[];\n\n /**\n * Base path for WASM files.\n * Leave undefined for auto-detection (recommended for most setups).\n * Only specify if hosting WASM files at a custom location.\n */\n wasmBasePath?: string;\n /**\n * Use Web Worker for document conversion (keeps UI responsive).\n * Default: true\n */\n useWorker?: boolean;\n /**\n * Automatic zoom-fit mode. When set to `page-width` or `page`, the viewer\n * picks a zoom level that fits the rendered page in the viewer on initial\n * render and on viewer resize. Defaults to `manual` (user-controlled zoom).\n */\n fitMode?: FitMode;\n}\n\nexport const DEFAULT_SETTINGS: ViewerSettings = {\n paginationScale: 0.8,\n showPageNumbers: true,\n renderFootnotesAndEndnotes: true,\n renderHeadersAndFooters: true,\n commentMode: 'disabled',\n annotationMode: 'disabled',\n renderTrackedChanges: false,\n showDeletedContent: true,\n renderMoveOperations: true,\n pageTitle: 'Document',\n cssPrefix: 'docx-',\n fabricateClasses: true,\n additionalCss: '',\n commentCssClassPrefix: 'comment-',\n annotationCssClassPrefix: 'annot-',\n renderUnsupportedContentPlaceholders: true,\n documentLanguage: '',\n};\n","import { useState, useMemo } from 'react';\nimport type { Revision } from 'docxodus/react';\nimport { isInsertion, isDeletion, isMove, isFormatChange } from 'docxodus';\n\ninterface RevisionPanelProps {\n revisions: Revision[];\n}\n\ntype FilterType = 'all' | 'insertions' | 'deletions' | 'moves' | 'formatting';\n\nfunction getRevisionTypeLabel(revision: Revision): string {\n if (isInsertion(revision)) return 'Inserted';\n if (isDeletion(revision)) return 'Deleted';\n if (isMove(revision)) return revision.isMoveSource ? 'Moved from' : 'Moved to';\n if (isFormatChange(revision)) return 'Formatted';\n return String(revision.revisionType);\n}\n\nfunction getRevisionTypeClass(revision: Revision): string {\n if (isInsertion(revision)) return 'rdv-revision--insertion';\n if (isDeletion(revision)) return 'rdv-revision--deletion';\n if (isMove(revision)) return 'rdv-revision--move';\n if (isFormatChange(revision)) return 'rdv-revision--format';\n return '';\n}\n\nfunction formatDate(isoDate: string): string {\n try {\n const date = new Date(isoDate);\n return date.toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n } catch {\n return isoDate;\n }\n}\n\nfunction truncateText(text: string, maxLength: number = 150): string {\n if (text.length <= maxLength) return text;\n return text.substring(0, maxLength) + '...';\n}\n\n// Filter out raw XML values and clean up property names\nfunction isValidPropertyValue(value: string): boolean {\n if (!value || typeof value !== 'string') return false;\n // Filter out raw XML data\n if (value.includes('<') || value.includes('xmlns') || value.includes('Unid=')) return false;\n // Filter out overly long values (likely XML)\n if (value.length > 100) return false;\n return true;\n}\n\n// Make property names more readable\nfunction formatPropertyName(name: string): string {\n // Convert camelCase to Title Case with spaces\n return name\n .replace(/([A-Z])/g, ' $1')\n .replace(/^./, (str) => str.toUpperCase())\n .trim();\n}\n\n// Format property value for display\nfunction formatPropertyValue(value: string): string {\n if (value === 'true') return 'Yes';\n if (value === 'false') return 'No';\n if (value === 'single') return 'Single';\n if (value === 'double') return 'Double';\n return value;\n}\n\ninterface FormatChangeItem {\n property: string;\n oldValue?: string;\n newValue?: string;\n}\n\n// Get paired format changes (old → new for same property)\nfunction getFormatChanges(revision: Revision): FormatChangeItem[] {\n if (!revision.formatChange) return [];\n\n const { oldProperties, newProperties } = revision.formatChange;\n const changes: FormatChangeItem[] = [];\n const processedKeys = new Set<string>();\n\n // Process old properties\n if (oldProperties) {\n for (const [key, value] of Object.entries(oldProperties)) {\n if (!isValidPropertyValue(value)) continue;\n processedKeys.add(key);\n const newValue = newProperties?.[key];\n changes.push({\n property: formatPropertyName(key),\n oldValue: formatPropertyValue(value),\n newValue: newValue && isValidPropertyValue(newValue) ? formatPropertyValue(newValue) : undefined,\n });\n }\n }\n\n // Process new properties not in old\n if (newProperties) {\n for (const [key, value] of Object.entries(newProperties)) {\n if (processedKeys.has(key)) continue;\n if (!isValidPropertyValue(value)) continue;\n changes.push({\n property: formatPropertyName(key),\n oldValue: undefined,\n newValue: formatPropertyValue(value),\n });\n }\n }\n\n return changes;\n}\n\nexport function RevisionPanel({ revisions }: RevisionPanelProps) {\n const [filter, setFilter] = useState<FilterType>('all');\n const [expandedIds, setExpandedIds] = useState<Set<number>>(new Set());\n\n const filteredRevisions = useMemo(() => {\n if (filter === 'all') return revisions;\n return revisions.filter((rev) => {\n switch (filter) {\n case 'insertions': return isInsertion(rev);\n case 'deletions': return isDeletion(rev);\n case 'moves': return isMove(rev);\n case 'formatting': return isFormatChange(rev);\n default: return true;\n }\n });\n }, [revisions, filter]);\n\n const stats = useMemo(() => ({\n total: revisions.length,\n insertions: revisions.filter(isInsertion).length,\n deletions: revisions.filter(isDeletion).length,\n moves: revisions.filter(isMove).length,\n formatting: revisions.filter(isFormatChange).length,\n }), [revisions]);\n\n const toggleExpanded = (index: number) => {\n setExpandedIds((prev) => {\n const next = new Set(prev);\n if (next.has(index)) {\n next.delete(index);\n } else {\n next.add(index);\n }\n return next;\n });\n };\n\n if (revisions.length === 0) {\n return (\n <div className=\"rdv-revision-panel\">\n <div className=\"rdv-revision-empty\">\n <div className=\"rdv-revision-empty__icon\">📝</div>\n <p>No tracked changes found in this document.</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"rdv-revision-panel\">\n <div className=\"rdv-revision-header\">\n <div className=\"rdv-revision-stats\">\n <span className=\"rdv-revision-stat rdv-revision-stat--total\">\n {stats.total} change{stats.total !== 1 ? 's' : ''}\n </span>\n {stats.insertions > 0 && (\n <span className=\"rdv-revision-stat rdv-revision-stat--insertion\">\n +{stats.insertions}\n </span>\n )}\n {stats.deletions > 0 && (\n <span className=\"rdv-revision-stat rdv-revision-stat--deletion\">\n −{stats.deletions}\n </span>\n )}\n {stats.moves > 0 && (\n <span className=\"rdv-revision-stat rdv-revision-stat--move\">\n ↔{stats.moves}\n </span>\n )}\n {stats.formatting > 0 && (\n <span className=\"rdv-revision-stat rdv-revision-stat--format\">\n ✎{stats.formatting}\n </span>\n )}\n </div>\n <select\n className=\"rdv-revision-filter\"\n value={filter}\n onChange={(e) => setFilter(e.target.value as FilterType)}\n >\n <option value=\"all\">All Changes</option>\n <option value=\"insertions\">Insertions ({stats.insertions})</option>\n <option value=\"deletions\">Deletions ({stats.deletions})</option>\n <option value=\"moves\">Moves ({stats.moves})</option>\n <option value=\"formatting\">Formatting ({stats.formatting})</option>\n </select>\n </div>\n\n <div className=\"rdv-revision-list\">\n {filteredRevisions.map((revision, index) => {\n const isExpanded = expandedIds.has(index);\n const needsTruncation = revision.text.length > 150;\n const formatChanges = isFormatChange(revision) ? getFormatChanges(revision) : [];\n\n return (\n <div\n key={index}\n className={`rdv-revision-item ${getRevisionTypeClass(revision)}`}\n >\n <div className=\"rdv-revision-item__header\">\n <span className=\"rdv-revision-type\">\n {getRevisionTypeLabel(revision)}\n </span>\n {isMove(revision) && revision.moveGroupId !== undefined && (\n <span className=\"rdv-revision-move-id\">#{revision.moveGroupId}</span>\n )}\n <span className=\"rdv-revision-author\">{revision.author || 'Unknown'}</span>\n <span className=\"rdv-revision-date\">{formatDate(revision.date)}</span>\n </div>\n\n {revision.text && (\n <div className=\"rdv-revision-item__content\">\n <span className=\"rdv-revision-text\">\n {isExpanded ? revision.text : truncateText(revision.text)}\n </span>\n {needsTruncation && (\n <button\n className=\"rdv-revision-expand\"\n onClick={() => toggleExpanded(index)}\n >\n {isExpanded ? 'Show less' : 'Show more'}\n </button>\n )}\n </div>\n )}\n\n {formatChanges.length > 0 && (\n <div className=\"rdv-revision-item__format-details\">\n {formatChanges.map((change, i) => (\n <div key={i} className=\"rdv-format-change\">\n <span className=\"rdv-format-change__property\">{change.property}</span>\n <span className=\"rdv-format-change__values\">\n {change.oldValue && (\n <span className=\"rdv-format-change__old\">{change.oldValue}</span>\n )}\n {change.oldValue && change.newValue && (\n <span className=\"rdv-format-change__arrow\">→</span>\n )}\n {change.newValue && (\n <span className=\"rdv-format-change__new\">{change.newValue}</span>\n )}\n {!change.oldValue && change.newValue && (\n <span className=\"rdv-format-change__added\">(added)</span>\n )}\n {change.oldValue && !change.newValue && (\n <span className=\"rdv-format-change__removed\">(removed)</span>\n )}\n </span>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n","import { useState, useCallback, useRef, useEffect, useMemo } from 'react';\nimport { useDocxodus, PaginatedDocument } from 'docxodus/react';\nimport type { PaginationResult, Revision, DocumentMetadata } from 'docxodus/react';\nimport { CommentRenderMode, PaginationMode, AnnotationLabelMode, getDocumentMetadata } from 'docxodus';\nimport { createWorkerDocxodus, isWorkerSupported } from 'docxodus/worker';\nimport type { WorkerDocxodus } from 'docxodus/worker';\nimport type {\n DocumentViewerProps,\n ViewerSettings,\n CommentMode,\n AnnotationMode,\n ViewMode,\n FitMode,\n ToolbarAction,\n} from './types';\nimport { DEFAULT_SETTINGS } from './types';\nimport { RevisionPanel } from './components/RevisionPanel';\n\nconst OpenDocumentIcon = () => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"17 8 12 3 7 8\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n </svg>\n);\n\nfunction getCommentRenderMode(mode: CommentMode): CommentRenderMode {\n switch (mode) {\n case 'endnote': return CommentRenderMode.EndnoteStyle;\n case 'inline': return CommentRenderMode.Inline;\n case 'margin': return CommentRenderMode.Margin;\n default: return CommentRenderMode.Disabled;\n }\n}\n\nfunction getAnnotationLabelMode(mode: AnnotationMode): AnnotationLabelMode | undefined {\n switch (mode) {\n case 'above': return AnnotationLabelMode.Above;\n case 'inline': return AnnotationLabelMode.Inline;\n case 'tooltip': return AnnotationLabelMode.Tooltip;\n case 'none': return AnnotationLabelMode.None;\n default: return undefined;\n }\n}\n\nfunction toCssLength(value: number | string | undefined): string | undefined {\n if (value === undefined || value === null) return undefined;\n return typeof value === 'number' ? `${value}px` : value;\n}\n\nconst PAGE_PT_TO_PX = 96 / 72;\nconst FIT_PADDING_PX = 40;\nconst MIN_SCALE = 0.3;\nconst MAX_SCALE = 2.0;\n\nfunction computeFitScale(\n mode: Exclude<FitMode, 'manual'>,\n containerWidth: number,\n containerHeight: number,\n pageWidthPt: number,\n pageHeightPt: number,\n): number {\n const pageWidthPx = pageWidthPt * PAGE_PT_TO_PX;\n const pageHeightPx = pageHeightPt * PAGE_PT_TO_PX;\n const widthScale = (containerWidth - FIT_PADDING_PX) / pageWidthPx;\n const heightScale = (containerHeight - FIT_PADDING_PX) / pageHeightPx;\n const raw = mode === 'page-width' ? widthScale : Math.min(widthScale, heightScale);\n const clamped = Math.max(MIN_SCALE, Math.min(MAX_SCALE, raw));\n return Math.round(clamped * 100) / 100;\n}\n\nexport function DocumentViewer({\n file: controlledFile,\n html: controlledHtml,\n onFileChange,\n onConversionStart,\n onConversionComplete,\n onError,\n onPageChange,\n onRevisionsExtracted,\n settings: controlledSettings,\n defaultSettings,\n defaultZoom,\n onSettingsChange,\n className,\n style,\n toolbar = 'top',\n showSettingsButton = true,\n showRevisionsTab = true,\n placeholder = 'Open a DOCX file to view',\n wasmBasePath,\n useWorker = true,\n fitMode = 'manual',\n toolbarActions,\n}: DocumentViewerProps) {\n // Merge default settings. `defaultZoom` is a convenience shortcut for\n // `defaultSettings.paginationScale`; explicit `defaultSettings` wins if both\n // are provided.\n const mergedDefaults = useMemo(() => {\n const base: ViewerSettings = { ...DEFAULT_SETTINGS };\n if (defaultZoom !== undefined) {\n base.paginationScale = Math.max(0.3, Math.min(2.0, defaultZoom));\n }\n return { ...base, ...defaultSettings };\n }, [defaultSettings, defaultZoom]);\n\n // Internal state (uncontrolled mode)\n const [internalFile, setInternalFile] = useState<File | null>(null);\n const [internalHtml, setInternalHtml] = useState<string | null>(null);\n const [internalSettings, setInternalSettings] = useState<ViewerSettings>(mergedDefaults);\n\n // Determine which values to use (controlled vs uncontrolled)\n const file = controlledFile !== undefined ? controlledFile : internalFile;\n const html = controlledHtml !== undefined ? controlledHtml : internalHtml;\n const settings = useMemo(\n () => controlledSettings\n ? { ...mergedDefaults, ...controlledSettings }\n : internalSettings,\n [controlledSettings, mergedDefaults, internalSettings]\n );\n\n // Docxodus hook (used when not in worker mode)\n const hookResult = useDocxodus(wasmBasePath);\n\n // Worker instance state (used when useWorker=true)\n const [worker, setWorker] = useState<WorkerDocxodus | null>(null);\n const [workerReady, setWorkerReady] = useState(false);\n const [workerLoading, setWorkerLoading] = useState(false);\n const [workerError, setWorkerError] = useState<Error | null>(null);\n\n // Create/destroy worker based on useWorker prop\n const workerRef = useRef<WorkerDocxodus | null>(null);\n\n useEffect(() => {\n if (!useWorker || !isWorkerSupported()) {\n return;\n }\n\n let cancelled = false;\n setWorkerLoading(true);\n setWorkerError(null);\n\n createWorkerDocxodus({ wasmBasePath })\n .then((workerInstance) => {\n if (!cancelled) {\n workerRef.current = workerInstance;\n setWorker(workerInstance);\n setWorkerReady(true);\n setWorkerLoading(false);\n } else {\n workerInstance.terminate();\n }\n })\n .catch((err) => {\n if (!cancelled) {\n setWorkerError(err instanceof Error ? err : new Error(String(err)));\n setWorkerLoading(false);\n }\n });\n\n return () => {\n cancelled = true;\n if (workerRef.current) {\n workerRef.current.terminate();\n workerRef.current = null;\n setWorker(null);\n setWorkerReady(false);\n }\n };\n }, [useWorker, wasmBasePath]);\n\n // Unified ready/loading/error state\n const isReady = useWorker ? workerReady : hookResult.isReady;\n const isLoading = useWorker ? workerLoading : hookResult.isLoading;\n const initError = useWorker ? workerError : hookResult.error;\n\n // Local UI state\n const [isConverting, setIsConverting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [fileName, setFileName] = useState<string>('');\n const [currentPage, setCurrentPage] = useState(1);\n const [totalPages, setTotalPages] = useState(0);\n const [showSettings, setShowSettings] = useState(false);\n const [viewMode, setViewMode] = useState<ViewMode>('document');\n const [revisions, setRevisions] = useState<Revision[]>([]);\n const [isExtractingRevisions, setIsExtractingRevisions] = useState(false);\n\n // Document metadata for progressive loading placeholders\n const [documentMetadata, setDocumentMetadata] = useState<DocumentMetadata | null>(null);\n\n const viewerRef = useRef<HTMLDivElement>(null);\n const paginatedContainerRef = useRef<HTMLDivElement>(null);\n\n // Inter-page gap read from --rdv-page-gap CSS variable (defaults to 20)\n const [pageGap, setPageGap] = useState(20);\n useEffect(() => {\n const readGap = () => {\n const el = viewerRef.current;\n if (!el) return;\n const value = getComputedStyle(el).getPropertyValue('--rdv-page-gap').trim();\n const parsed = parseFloat(value);\n if (!Number.isNaN(parsed)) setPageGap(parsed);\n };\n readGap();\n window.addEventListener('resize', readGap);\n return () => window.removeEventListener('resize', readGap);\n }, []);\n\n // Build conversion options from settings\n const getConvertOptions = useCallback(() => ({\n commentRenderMode: getCommentRenderMode(settings.commentMode),\n pageTitle: settings.pageTitle,\n cssPrefix: settings.cssPrefix,\n fabricateClasses: settings.fabricateClasses,\n additionalCss: settings.additionalCss || undefined,\n commentCssClassPrefix: settings.commentCssClassPrefix,\n paginationMode: PaginationMode.Paginated,\n paginationScale: settings.paginationScale,\n renderAnnotations: settings.annotationMode !== 'disabled',\n annotationLabelMode: getAnnotationLabelMode(settings.annotationMode),\n annotationCssClassPrefix: settings.annotationCssClassPrefix,\n renderFootnotesAndEndnotes: settings.renderFootnotesAndEndnotes,\n renderHeadersAndFooters: settings.renderHeadersAndFooters,\n renderTrackedChanges: settings.renderTrackedChanges,\n showDeletedContent: settings.showDeletedContent,\n renderMoveOperations: settings.renderMoveOperations,\n renderUnsupportedContentPlaceholders: settings.renderUnsupportedContentPlaceholders,\n documentLanguage: settings.documentLanguage || undefined,\n }), [settings]);\n\n // Fetch document metadata quickly (for progressive loading placeholders)\n const fetchMetadata = useCallback(async (fileToFetch: File) => {\n try {\n // Use worker's getDocumentMetadata if available, otherwise direct call\n const metadata = useWorker && worker\n ? await worker.getDocumentMetadata(fileToFetch)\n : await getDocumentMetadata(fileToFetch);\n setDocumentMetadata(metadata);\n } catch {\n // Metadata extraction is non-critical, silently fail\n setDocumentMetadata(null);\n }\n }, [useWorker, worker]);\n\n // Extract revisions from document\n const extractRevisions = useCallback(async (fileToExtract: File) => {\n if (!isReady || !showRevisionsTab) return;\n\n setIsExtractingRevisions(true);\n try {\n const extractedRevisions = useWorker && worker\n ? await worker.getRevisions(fileToExtract)\n : await hookResult.getRevisions(fileToExtract);\n setRevisions(extractedRevisions);\n onRevisionsExtracted?.(extractedRevisions);\n } catch {\n // Revision extraction is non-critical, silently fail\n setRevisions([]);\n } finally {\n setIsExtractingRevisions(false);\n }\n }, [isReady, useWorker, worker, hookResult, showRevisionsTab, onRevisionsExtracted]);\n\n // Convert file to HTML\n const convert = useCallback(async (fileToConvert: File) => {\n if (!isReady) return;\n\n setIsConverting(true);\n setError(null);\n setRevisions([]);\n setViewMode('document');\n // Don't reset documentMetadata here - we want to show placeholders during conversion\n onConversionStart?.();\n\n // Allow React to render loading state before heavy WASM work (only needed for non-worker mode)\n if (!useWorker) {\n await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));\n }\n\n try {\n const result = useWorker && worker\n ? await worker.convertDocxToHtml(fileToConvert, getConvertOptions())\n : await hookResult.convertToHtml(fileToConvert, getConvertOptions());\n\n if (controlledHtml === undefined) {\n setInternalHtml(result);\n }\n onConversionComplete?.(result);\n\n // Extract revisions in background after conversion\n extractRevisions(fileToConvert);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n onError?.(error);\n } finally {\n setIsConverting(false);\n }\n }, [isReady, useWorker, worker, hookResult, getConvertOptions, controlledHtml, onConversionStart, onConversionComplete, onError, extractRevisions]);\n\n // Auto-convert when WASM ready and file available\n useEffect(() => {\n if (isReady && file && !html && !isConverting && controlledHtml === undefined) {\n convert(file);\n }\n }, [isReady, file, html, isConverting, convert, controlledHtml]);\n\n // Handle file input change\n const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const selectedFile = e.target.files?.[0];\n if (selectedFile) {\n setFileName(selectedFile.name);\n setError(null);\n setCurrentPage(1);\n setTotalPages(0);\n setDocumentMetadata(null); // Reset metadata from previous file\n setRevisions([]); // Reset revisions\n setViewMode('document');\n\n if (controlledFile === undefined) {\n setInternalFile(selectedFile);\n setInternalHtml(null);\n }\n onFileChange?.(selectedFile);\n\n // Fetch metadata first for placeholders, then convert\n fetchMetadata(selectedFile);\n if (isReady && controlledHtml === undefined) {\n await convert(selectedFile);\n }\n }\n };\n\n // Reconvert with current settings\n const reconvert = useCallback(async () => {\n if (file) {\n if (controlledHtml === undefined) {\n setInternalHtml(null);\n }\n await convert(file);\n }\n }, [file, convert, controlledHtml]);\n\n // Clear document\n const handleClear = () => {\n if (controlledFile === undefined) {\n setInternalFile(null);\n }\n if (controlledHtml === undefined) {\n setInternalHtml(null);\n }\n setError(null);\n setFileName('');\n setCurrentPage(1);\n setTotalPages(0);\n setRevisions([]);\n setViewMode('document');\n setDocumentMetadata(null);\n onFileChange?.(null);\n\n const input = document.getElementById('rdv-file-input') as HTMLInputElement;\n if (input) input.value = '';\n };\n\n // Update settings\n const updateSettings = useCallback((updates: Partial<ViewerSettings>) => {\n const newSettings = { ...settings, ...updates };\n if (controlledSettings === undefined) {\n setInternalSettings(newSettings);\n }\n onSettingsChange?.(newSettings);\n }, [settings, controlledSettings, onSettingsChange]);\n\n // Zoom controls\n const handleZoomIn = () => updateSettings({\n paginationScale: Math.min(settings.paginationScale + 0.1, 2.0)\n });\n const handleZoomOut = () => updateSettings({\n paginationScale: Math.max(settings.paginationScale - 0.1, 0.3)\n });\n const handleZoomChange = (value: number) => updateSettings({\n paginationScale: Math.max(0.3, Math.min(2.0, value))\n });\n\n // Auto-fit: when fitMode is not 'manual', pick a scale that fits the page\n // into the viewer on initial render and whenever the viewer resizes.\n // settingsRef avoids putting `settings` in this effect's deps, which would\n // re-create the ResizeObserver on every scale change and cause loops.\n const settingsRef = useRef(settings);\n useEffect(() => {\n settingsRef.current = settings;\n });\n useEffect(() => {\n if (fitMode === 'manual' || !documentMetadata || !html) return;\n const container = paginatedContainerRef.current;\n if (!container || typeof ResizeObserver === 'undefined') return;\n\n const section = documentMetadata.sections[0];\n const pageWidthPt = section?.pageWidthPt ?? 612;\n const pageHeightPt = section?.pageHeightPt ?? 792;\n\n const applyFit = () => {\n const scale = computeFitScale(\n fitMode,\n container.clientWidth,\n container.clientHeight,\n pageWidthPt,\n pageHeightPt,\n );\n if (Math.abs(settingsRef.current.paginationScale - scale) < 0.005) return;\n const newSettings = { ...settingsRef.current, paginationScale: scale };\n if (controlledSettings === undefined) {\n setInternalSettings(newSettings);\n }\n onSettingsChange?.(newSettings);\n };\n\n applyFit();\n const ro = new ResizeObserver(applyFit);\n ro.observe(container);\n return () => ro.disconnect();\n }, [fitMode, documentMetadata, html, controlledSettings, onSettingsChange]);\n\n // Page navigation\n const goToPage = (pageNum: number) => {\n const container = paginatedContainerRef.current;\n if (!container || pageNum < 1 || pageNum > totalPages) return;\n const pageElement = container.querySelector(`[data-page-number=\"${pageNum}\"]`);\n if (pageElement) {\n pageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n };\n\n const goToPreviousPage = () => currentPage > 1 && goToPage(currentPage - 1);\n const goToNextPage = () => currentPage < totalPages && goToPage(currentPage + 1);\n\n // Handle page visibility changes\n const handlePageVisible = (pageNumber: number) => {\n setCurrentPage(pageNumber);\n onPageChange?.(pageNumber, totalPages);\n };\n\n // Handle footnote/anchor clicks\n useEffect(() => {\n const container = paginatedContainerRef.current;\n if (!container) return;\n\n const handleAnchorClick = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n const anchor = target.closest('a[href^=\"#\"]') as HTMLAnchorElement | null;\n if (!anchor) return;\n\n const href = anchor.getAttribute('href');\n if (!href || !href.startsWith('#')) return;\n\n e.preventDefault();\n const targetId = href.substring(1);\n const targetElement = container.querySelector(`[id=\"${targetId}\"], [name=\"${targetId}\"]`);\n\n if (targetElement) {\n targetElement.scrollIntoView({ behavior: 'smooth', block: 'center' });\n targetElement.classList.add('rdv-footnote-highlight');\n setTimeout(() => targetElement.classList.remove('rdv-footnote-highlight'), 2000);\n }\n };\n\n container.addEventListener('click', handleAnchorClick);\n return () => container.removeEventListener('click', handleAnchorClick);\n }, [html]);\n\n // Notify parent of page changes when totalPages updates\n useEffect(() => {\n if (totalPages > 0) {\n onPageChange?.(currentPage, totalPages);\n }\n }, [totalPages, currentPage, onPageChange]);\n\n const isProcessing = isConverting || isLoading;\n\n // Settings Modal\n const SettingsModal = () => (\n <div className=\"rdv-settings-overlay\" onClick={() => setShowSettings(false)}>\n <div className=\"rdv-settings-modal\" onClick={(e) => e.stopPropagation()}>\n <div className=\"rdv-settings-header\">\n <h3>Viewer Settings</h3>\n <button className=\"rdv-settings-close\" onClick={() => setShowSettings(false)}>×</button>\n </div>\n <div className=\"rdv-settings-body\">\n <div className=\"rdv-settings-section\">\n <h4>Display Options</h4>\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.renderFootnotesAndEndnotes}\n onChange={(e) => updateSettings({ renderFootnotesAndEndnotes: e.target.checked })}\n />\n <span>Show footnotes and endnotes</span>\n </label>\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.renderHeadersAndFooters}\n onChange={(e) => updateSettings({ renderHeadersAndFooters: e.target.checked })}\n />\n <span>Show headers and footers</span>\n </label>\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.showPageNumbers}\n onChange={(e) => updateSettings({ showPageNumbers: e.target.checked })}\n />\n <span>Show page numbers</span>\n </label>\n </div>\n\n <div className=\"rdv-settings-section\">\n <h4>Comment Rendering</h4>\n <div className=\"rdv-settings-radio-group\">\n {(['disabled', 'endnote', 'inline', 'margin'] as CommentMode[]).map((mode) => (\n <label key={mode} className=\"rdv-settings-radio\">\n <input\n type=\"radio\"\n name=\"commentMode\"\n checked={settings.commentMode === mode}\n onChange={() => updateSettings({ commentMode: mode })}\n />\n <span>{mode.charAt(0).toUpperCase() + mode.slice(1)}{mode === 'endnote' ? 's' : ''}</span>\n </label>\n ))}\n </div>\n </div>\n\n <div className=\"rdv-settings-section\">\n <h4>Annotation Rendering</h4>\n <div className=\"rdv-settings-radio-group\">\n {(['disabled', 'above', 'inline', 'tooltip', 'none'] as AnnotationMode[]).map((mode) => (\n <label key={mode} className=\"rdv-settings-radio\">\n <input\n type=\"radio\"\n name=\"annotationMode\"\n checked={settings.annotationMode === mode}\n onChange={() => updateSettings({ annotationMode: mode })}\n />\n <span>{mode === 'none' ? 'Highlight Only' : mode.charAt(0).toUpperCase() + mode.slice(1)}</span>\n </label>\n ))}\n </div>\n </div>\n\n <div className=\"rdv-settings-section\">\n <h4>Tracked Changes</h4>\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.renderTrackedChanges}\n onChange={(e) => updateSettings({ renderTrackedChanges: e.target.checked })}\n />\n <span>Show tracked changes</span>\n </label>\n {settings.renderTrackedChanges && (\n <div className=\"rdv-settings-subsection\">\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.showDeletedContent}\n onChange={(e) => updateSettings({ showDeletedContent: e.target.checked })}\n />\n <span>Show deleted content</span>\n </label>\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.renderMoveOperations}\n onChange={(e) => updateSettings({ renderMoveOperations: e.target.checked })}\n />\n <span>Distinguish move operations</span>\n </label>\n </div>\n )}\n </div>\n\n <div className=\"rdv-settings-section\">\n <h4>Advanced</h4>\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.renderUnsupportedContentPlaceholders}\n onChange={(e) => updateSettings({ renderUnsupportedContentPlaceholders: e.target.checked })}\n />\n <span>Show placeholders for unsupported content</span>\n </label>\n <p className=\"rdv-settings-hint\">\n Display visual indicators for WMF/EMF images, math equations, form fields, and other unsupported elements\n </p>\n <label className=\"rdv-settings-input-label\">\n <span>Document language override</span>\n <input\n type=\"text\"\n className=\"rdv-settings-text-input\"\n value={settings.documentLanguage}\n onChange={(e) => updateSettings({ documentLanguage: e.target.value })}\n placeholder=\"Auto-detect (e.g., en-US, fr-FR)\"\n />\n </label>\n </div>\n </div>\n <div className=\"rdv-settings-footer\">\n <button className=\"rdv-settings-apply\" onClick={() => { reconvert(); setShowSettings(false); }}>\n Apply & Close\n </button>\n </div>\n </div>\n </div>\n );\n\n const hasRevisions = revisions.length > 0;\n\n // Render a single custom toolbar action button\n const renderToolbarAction = (action: ToolbarAction) => {\n const variantClass = action.variant === 'primary' ? 'rdv-toolbar-icon-btn--primary' : '';\n const classes = [\n 'rdv-toolbar-btn',\n 'rdv-toolbar-icon-btn',\n variantClass,\n action.className,\n ]\n .filter(Boolean)\n .join(' ');\n return (\n <button\n key={action.key}\n type=\"button\"\n className={classes}\n onClick={action.onClick}\n disabled={action.disabled}\n title={action.label}\n aria-label={action.label}\n >\n {action.icon}\n </button>\n );\n };\n\n // Toolbar component\n const Toolbar = () => (\n <div className=\"rdv-toolbar\">\n <div className=\"rdv-toolbar-left\">\n <label\n htmlFor=\"rdv-file-input\"\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn rdv-toolbar-open-btn\"\n title=\"Open Document\"\n aria-label=\"Open Document\"\n >\n <OpenDocumentIcon />\n </label>\n <input\n id=\"rdv-file-input\"\n type=\"file\"\n accept=\".docx\"\n onChange={handleFileChange}\n disabled={isProcessing}\n className=\"rdv-file-input\"\n />\n {fileName && (\n <span className=\"rdv-toolbar-filename\" title={fileName}>\n {fileName}\n </span>\n )}\n {fileName && (\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn rdv-toolbar-clear\"\n onClick={handleClear}\n disabled={isProcessing}\n title=\"Clear Document\"\n aria-label=\"Clear Document\"\n >\n ×\n </button>\n )}\n {showRevisionsTab && hasRevisions && html && (\n <>\n <div className=\"rdv-toolbar-separator\" />\n <div className=\"rdv-view-tabs\">\n <button\n className={`rdv-view-tab ${viewMode === 'document' ? 'rdv-view-tab--active' : ''}`}\n onClick={() => setViewMode('document')}\n title=\"View Document\"\n >\n Document\n </button>\n <button\n className={`rdv-view-tab ${viewMode === 'revisions' ? 'rdv-view-tab--active' : ''}`}\n onClick={() => setViewMode('revisions')}\n title=\"View Tracked Changes\"\n >\n Changes ({revisions.length})\n </button>\n </div>\n </>\n )}\n {showRevisionsTab && isExtractingRevisions && (\n <span className=\"rdv-extracting-indicator\" title=\"Extracting tracked changes...\">\n ...\n </span>\n )}\n </div>\n\n <div className=\"rdv-toolbar-right\">\n {html && totalPages > 0 && viewMode === 'document' && (\n <>\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn\"\n onClick={goToPreviousPage}\n disabled={currentPage <= 1}\n title=\"Previous Page\"\n aria-label=\"Previous Page\"\n >\n ◀\n </button>\n <div className=\"rdv-page-input-group\">\n <input\n type=\"number\"\n className=\"rdv-page-input\"\n value={currentPage}\n min={1}\n max={totalPages}\n onChange={(e) => {\n const page = parseInt(e.target.value);\n if (!isNaN(page)) goToPage(page);\n }}\n />\n <span className=\"rdv-page-total\">/ {totalPages}</span>\n </div>\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn\"\n onClick={goToNextPage}\n disabled={currentPage >= totalPages}\n title=\"Next Page\"\n aria-label=\"Next Page\"\n >\n ▶\n </button>\n\n <div className=\"rdv-toolbar-separator\" />\n\n <div className=\"rdv-zoom-group\">\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn rdv-zoom-btn\"\n onClick={handleZoomOut}\n disabled={settings.paginationScale <= 0.3}\n title=\"Zoom Out\"\n aria-label=\"Zoom Out\"\n >\n −\n </button>\n <select\n className=\"rdv-zoom-select\"\n value={settings.paginationScale}\n onChange={(e) => handleZoomChange(parseFloat(e.target.value))}\n aria-label=\"Zoom level\"\n >\n <option value=\"0.5\">50%</option>\n <option value=\"0.75\">75%</option>\n <option value=\"0.8\">80%</option>\n <option value=\"0.9\">90%</option>\n <option value=\"1\">100%</option>\n <option value=\"1.25\">125%</option>\n <option value=\"1.5\">150%</option>\n <option value=\"2\">200%</option>\n </select>\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn rdv-zoom-btn\"\n onClick={handleZoomIn}\n disabled={settings.paginationScale >= 2.0}\n title=\"Zoom In\"\n aria-label=\"Zoom In\"\n >\n +\n </button>\n </div>\n </>\n )}\n {toolbarActions && toolbarActions.length > 0 && (\n <>\n {html && totalPages > 0 && viewMode === 'document' && (\n <div className=\"rdv-toolbar-separator\" />\n )}\n {toolbarActions.map(renderToolbarAction)}\n </>\n )}\n {showSettingsButton && (\n <>\n {(toolbarActions?.length || (html && totalPages > 0 && viewMode === 'document')) && (\n <div className=\"rdv-toolbar-separator\" />\n )}\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn rdv-toolbar-settings\"\n onClick={() => setShowSettings(true)}\n title=\"Settings\"\n aria-label=\"Settings\"\n >\n ⚙\n </button>\n </>\n )}\n </div>\n </div>\n );\n\n const rootClassName = ['rdv-viewer', className].filter(Boolean).join(' ');\n\n return (\n <div ref={viewerRef} className={rootClassName} style={style}>\n {toolbar === 'top' && <Toolbar />}\n\n <div className=\"rdv-content\">\n {initError && (\n <div className=\"rdv-message rdv-message--error\">\n <p>Failed to initialize: {initError.message}</p>\n </div>\n )}\n\n {!initError && (isLoading || isConverting) && (\n documentMetadata && isConverting ? (\n // Show page placeholders while converting - matches actual page dimensions for stable layout\n <div\n className=\"rdv-pages rdv-pages--loading\"\n style={{\n // Apply stable dimensions to match rendered state - prevents layout shift\n ...(settings.stableWidth && { '--rdv-stable-width': toCssLength(settings.stableWidth) }),\n ...(settings.stableHeight && { minHeight: toCssLength(settings.stableHeight) }),\n } as React.CSSProperties}\n >\n <div className=\"rdv-page-placeholders\" style={{ backgroundColor: '#525659' }}>\n {Array.from({ length: documentMetadata.estimatedPageCount || 1 }).map((_, index) => {\n // Get section for this page (approximate - use first section if not enough)\n const section = documentMetadata.sections[\n Math.min(index, documentMetadata.sections.length - 1)\n ];\n // Calculate scaled dimensions (points to pixels, then apply scale)\n const scale = settings.paginationScale;\n const width = Math.round((section?.pageWidthPt || 612) * (96 / 72) * scale);\n const height = Math.round((section?.pageHeightPt || 792) * (96 / 72) * scale);\n\n return (\n <div\n key={index}\n className=\"rdv-page-placeholder\"\n style={{\n width: `${width}px`,\n height: `${height}px`,\n }}\n >\n <div className=\"rdv-page-placeholder__shimmer\" />\n {index === 0 && (\n <div className=\"rdv-page-placeholder__info\">\n <div className=\"rdv-spinner rdv-spinner--small\"></div>\n <span>Converting document...</span>\n <span className=\"rdv-page-placeholder__count\">\n ~{documentMetadata.estimatedPageCount} page{documentMetadata.estimatedPageCount !== 1 ? 's' : ''}\n </span>\n </div>\n )}\n <div className=\"rdv-page-placeholder__number\">{index + 1}</div>\n </div>\n );\n })}\n </div>\n </div>\n ) : (\n <div className=\"rdv-message\">\n <div className=\"rdv-spinner\"></div>\n <p>\n {isLoading && file\n ? 'Loading engine & preparing document...'\n : isLoading\n ? 'Loading document engine...'\n : 'Processing document...'}\n </p>\n </div>\n )\n )}\n\n {!isLoading && !initError && !html && !isConverting && !file && (\n <div\n className=\"rdv-message\"\n style={{\n // Apply stable dimensions for consistent sizing across all states\n ...(settings.stableWidth && { width: toCssLength(settings.stableWidth), maxWidth: '100%' }),\n ...(settings.stableHeight && { minHeight: toCssLength(settings.stableHeight) }),\n }}\n >\n <div className=\"rdv-message__icon\">📄</div>\n <p>{placeholder}</p>\n </div>\n )}\n\n {error && !isConverting && (\n <div className=\"rdv-message rdv-message--error\">\n <p>Error: {error.message}</p>\n </div>\n )}\n\n {viewMode === 'document' && html && !isConverting && (\n <div\n ref={paginatedContainerRef}\n className=\"rdv-pages\"\n style={{\n // Apply stable dimensions if provided - provides pdf.js-like sizing behavior\n ...(settings.stableWidth && { '--rdv-stable-width': toCssLength(settings.stableWidth) }),\n ...(settings.stableHeight && { minHeight: toCssLength(settings.stableHeight) }),\n } as React.CSSProperties}\n >\n <PaginatedDocument\n html={html}\n scale={settings.paginationScale}\n showPageNumbers={settings.showPageNumbers}\n pageGap={pageGap}\n backgroundColor=\"#525659\"\n className=\"rdv-paginated-document\"\n onPaginationComplete={(result: PaginationResult) => {\n setTotalPages(result.totalPages);\n }}\n onPageVisible={handlePageVisible}\n />\n </div>\n )}\n\n {viewMode === 'revisions' && html && !isConverting && (\n <RevisionPanel revisions={revisions} />\n )}\n </div>\n\n {toolbar === 'bottom' && <Toolbar />}\n\n {showSettings && <SettingsModal />}\n </div>\n );\n}\n"],"names":["generateId","toBytes","document","buffer","deriveWasmBasePath","scripts","src","createWorkerDocxodus","options","wasmBasePath","workerScriptPath","_documentCurrentScript","worker","pendingRequests","isWorkerActive","event","response","pending","error","sendRequest","request","transfer","resolve","reject","initResponse","bytes","original","modified","originalBytes","modifiedBytes","isWorkerSupported","DEFAULT_SETTINGS","getRevisionTypeLabel","revision","isInsertion","isDeletion","isMove","isFormatChange","getRevisionTypeClass","formatDate","isoDate","truncateText","text","maxLength","isValidPropertyValue","value","formatPropertyName","name","str","formatPropertyValue","getFormatChanges","oldProperties","newProperties","changes","processedKeys","key","newValue","RevisionPanel","revisions","filter","setFilter","useState","expandedIds","setExpandedIds","filteredRevisions","useMemo","rev","stats","toggleExpanded","index","prev","next","jsxs","jsx","e","isExpanded","needsTruncation","formatChanges","change","i","OpenDocumentIcon","getCommentRenderMode","mode","CommentRenderMode","getAnnotationLabelMode","AnnotationLabelMode","toCssLength","PAGE_PT_TO_PX","FIT_PADDING_PX","MIN_SCALE","MAX_SCALE","computeFitScale","containerWidth","containerHeight","pageWidthPt","pageHeightPt","pageWidthPx","pageHeightPx","widthScale","heightScale","raw","clamped","DocumentViewer","controlledFile","controlledHtml","onFileChange","onConversionStart","onConversionComplete","onError","onPageChange","onRevisionsExtracted","controlledSettings","defaultSettings","defaultZoom","onSettingsChange","className","style","toolbar","showSettingsButton","showRevisionsTab","placeholder","useWorker","fitMode","toolbarActions","mergedDefaults","base","internalFile","setInternalFile","internalHtml","setInternalHtml","internalSettings","setInternalSettings","file","html","settings","hookResult","useDocxodus","setWorker","workerReady","setWorkerReady","workerLoading","setWorkerLoading","workerError","setWorkerError","workerRef","useRef","useEffect","cancelled","workerInstance","err","isReady","isLoading","initError","isConverting","setIsConverting","setError","fileName","setFileName","currentPage","setCurrentPage","totalPages","setTotalPages","showSettings","setShowSettings","viewMode","setViewMode","setRevisions","isExtractingRevisions","setIsExtractingRevisions","documentMetadata","setDocumentMetadata","viewerRef","paginatedContainerRef","pageGap","setPageGap","readGap","el","parsed","getConvertOptions","useCallback","PaginationMode","fetchMetadata","fileToFetch","metadata","getDocumentMetadata","extractRevisions","fileToExtract","extractedRevisions","convert","fileToConvert","result","handleFileChange","selectedFile","reconvert","handleClear","input","updateSettings","updates","newSettings","handleZoomIn","handleZoomOut","handleZoomChange","settingsRef","container","section","applyFit","scale","ro","goToPage","pageNum","pageElement","goToPreviousPage","goToNextPage","handlePageVisible","pageNumber","handleAnchorClick","anchor","href","targetId","targetElement","isProcessing","SettingsModal","hasRevisions","renderToolbarAction","action","classes","Toolbar","Fragment","page","rootClassName","_","width","height","PaginatedDocument"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"react-docxodus-viewer.cjs.js","names":[],"sources":["../node_modules/docxodus/dist/worker-proxy.js","../src/types/index.ts","../src/components/RevisionPanel.tsx","../src/DocumentViewer.tsx"],"sourcesContent":["/**\n * Worker Proxy - Main thread interface for the Docxodus Web Worker\n *\n * This module provides a Promise-based API that mirrors the main API but\n * executes all WASM operations in a Web Worker, keeping the main thread free.\n *\n * @example\n * ```typescript\n * import { createWorkerDocxodus } from 'docxodus/worker';\n *\n * // Create worker instance\n * const docxodus = await createWorkerDocxodus();\n *\n * // Use the same API as the main module, but non-blocking!\n * const html = await docxodus.convertDocxToHtml(docxFile);\n *\n * // Clean up when done\n * docxodus.terminate();\n * ```\n */\n/**\n * Generate a unique request ID.\n */\nfunction generateId() {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n/**\n * Convert a File or Uint8Array to Uint8Array.\n */\nasync function toBytes(document) {\n if (document instanceof Uint8Array) {\n return document;\n }\n const buffer = await document.arrayBuffer();\n return new Uint8Array(buffer);\n}\n/**\n * Derive the WASM base path from the current module URL.\n */\nfunction deriveWasmBasePath() {\n // Try to get the base path from the current script URL\n if (typeof document !== \"undefined\") {\n // Browser: look for docxodus script tag or use current location\n const scripts = document.querySelectorAll('script[src*=\"docxodus\"]');\n if (scripts.length > 0) {\n const src = scripts[0].src;\n const base = src.substring(0, src.lastIndexOf(\"/\") + 1);\n return base + \"wasm/\";\n }\n }\n // Default fallback\n return \"/wasm/\";\n}\n/**\n * Create a worker-based Docxodus instance.\n *\n * This function spawns a Web Worker that loads the WASM runtime independently.\n * All operations are executed in the worker, keeping the main thread responsive.\n *\n * @param options - Configuration options\n * @returns A Promise that resolves to a WorkerDocxodus instance\n *\n * @example\n * ```typescript\n * // Basic usage\n * const docxodus = await createWorkerDocxodus();\n * const html = await docxodus.convertDocxToHtml(docxFile);\n *\n * // With custom WASM path\n * const docxodus = await createWorkerDocxodus({\n * wasmBasePath: '/assets/wasm/'\n * });\n * ```\n */\nexport async function createWorkerDocxodus(options) {\n // Determine WASM base path\n const wasmBasePath = options?.wasmBasePath ?? deriveWasmBasePath();\n // Determine worker script path\n // The worker bundle should be in the same directory as this module\n let workerUrl;\n // Try to create worker from bundled script or blob\n // For now, we'll use a blob URL to inline the worker path\n const workerScriptPath = new URL(\"./docxodus.worker.js\", import.meta.url)\n .href;\n // Create the worker\n const worker = new Worker(workerScriptPath, { type: \"module\" });\n // Track pending requests\n const pendingRequests = new Map();\n // Track if worker is active\n let isWorkerActive = true;\n // Cached warmup promise. Set on the first prepare() and reused thereafter so\n // repeated/concurrent calls share a single in-flight (or completed) warmup.\n // Reset to null on failure so a later prepare() can retry.\n let preparePromise = null;\n // Handle worker messages\n worker.onmessage = (event) => {\n const response = event.data;\n // Handle ready signal\n if (response.type === \"ready\") {\n return;\n }\n // Handle normal responses\n const pending = pendingRequests.get(response.id);\n if (pending) {\n pendingRequests.delete(response.id);\n if (response.success) {\n pending.resolve(response);\n }\n else {\n pending.reject(new Error(response.error || \"Unknown error\"));\n }\n }\n };\n // Handle worker errors\n worker.onerror = (error) => {\n // Reject all pending requests\n for (const pending of pendingRequests.values()) {\n pending.reject(new Error(`Worker error: ${error.message}`));\n }\n pendingRequests.clear();\n isWorkerActive = false;\n };\n /**\n * Send a request to the worker and wait for response.\n */\n function sendRequest(request, transfer) {\n return new Promise((resolve, reject) => {\n if (!isWorkerActive) {\n reject(new Error(\"Worker has been terminated\"));\n return;\n }\n pendingRequests.set(request.id, { resolve, reject });\n if (transfer && transfer.length > 0) {\n worker.postMessage(request, transfer);\n }\n else {\n worker.postMessage(request);\n }\n });\n }\n // Initialize the worker\n const initResponse = await sendRequest({\n id: generateId(),\n type: \"init\",\n wasmBasePath,\n });\n if (!initResponse.success) {\n worker.terminate();\n throw new Error(`Failed to initialize worker: ${initResponse.error}`);\n }\n // Return the WorkerDocxodus instance\n return {\n async convertDocxToHtml(document, options) {\n const bytes = await toBytes(document);\n const response = await sendRequest({\n id: generateId(),\n type: \"convertDocxToHtml\",\n documentBytes: bytes,\n options,\n }, [bytes.buffer]);\n return response.html;\n },\n async compareDocuments(original, modified, options) {\n const originalBytes = await toBytes(original);\n const modifiedBytes = await toBytes(modified);\n const response = await sendRequest({\n id: generateId(),\n type: \"compareDocuments\",\n originalBytes,\n modifiedBytes,\n options,\n }, [originalBytes.buffer, modifiedBytes.buffer]);\n return response.documentBytes;\n },\n async compareDocumentsToHtml(original, modified, options) {\n const originalBytes = await toBytes(original);\n const modifiedBytes = await toBytes(modified);\n const response = await sendRequest({\n id: generateId(),\n type: \"compareDocumentsToHtml\",\n originalBytes,\n modifiedBytes,\n options,\n }, [originalBytes.buffer, modifiedBytes.buffer]);\n return response.html;\n },\n async getRevisions(document, options) {\n const bytes = await toBytes(document);\n const response = await sendRequest({\n id: generateId(),\n type: \"getRevisions\",\n documentBytes: bytes,\n options,\n }, [bytes.buffer]);\n return response.revisions;\n },\n async getDocumentMetadata(document) {\n const bytes = await toBytes(document);\n const response = await sendRequest({\n id: generateId(),\n type: \"getDocumentMetadata\",\n documentBytes: bytes,\n }, [bytes.buffer]);\n return response.metadata;\n },\n async getVersion() {\n const response = await sendRequest({\n id: generateId(),\n type: \"getVersion\",\n });\n return response.version;\n },\n prepare() {\n // Idempotent: hand back the existing warmup if one is in flight or done.\n if (preparePromise) {\n return preparePromise;\n }\n preparePromise = sendRequest({\n id: generateId(),\n type: \"prepare\",\n }).then(() => undefined);\n // On failure, clear the cache so a subsequent prepare() can retry.\n preparePromise.catch(() => {\n preparePromise = null;\n });\n return preparePromise;\n },\n async openDocxSession(document, settings) {\n const bytes = await toBytes(document);\n const settingsJson = settings ? JSON.stringify(settings) : \"\";\n const openResponse = await sendRequest({\n id: generateId(),\n type: \"sessionOpen\",\n documentBytes: bytes,\n settingsJson,\n }, [bytes.buffer]);\n if (!openResponse.success || openResponse.handle === undefined) {\n throw new Error(`Failed to open worker DocxSession: ${openResponse.error ?? \"unknown error\"}`);\n }\n const handle = openResponse.handle;\n return {\n async addAnnotation(anchorId, span, annotation) {\n const res = await sendRequest({\n id: generateId(),\n type: \"sessionAddAnnotation\",\n handle,\n anchorId,\n spanJson: span ? JSON.stringify(span) : \"\",\n annotationJson: JSON.stringify(annotation),\n });\n if (!res.success) {\n throw new Error(res.error ?? \"sessionAddAnnotation failed\");\n }\n return res.result;\n },\n async removeAnnotation(annotationId) {\n const res = await sendRequest({\n id: generateId(),\n type: \"sessionRemoveAnnotation\",\n handle,\n annotationId,\n });\n if (!res.success) {\n throw new Error(res.error ?? \"sessionRemoveAnnotation failed\");\n }\n return res.result;\n },\n async updateAnnotation(annotationId, update) {\n const res = await sendRequest({\n id: generateId(),\n type: \"sessionUpdateAnnotation\",\n handle,\n annotationId,\n updateJson: JSON.stringify(update),\n });\n if (!res.success) {\n throw new Error(res.error ?? \"sessionUpdateAnnotation failed\");\n }\n return res.result;\n },\n async moveAnnotation(annotationId, newAnchorId, newSpan) {\n const res = await sendRequest({\n id: generateId(),\n type: \"sessionMoveAnnotation\",\n handle,\n annotationId,\n newAnchorId,\n newSpanJson: newSpan ? JSON.stringify(newSpan) : \"\",\n });\n if (!res.success) {\n throw new Error(res.error ?? \"sessionMoveAnnotation failed\");\n }\n return res.result;\n },\n async close() {\n await sendRequest({\n id: generateId(),\n type: \"sessionClose\",\n handle,\n });\n },\n };\n },\n terminate() {\n isWorkerActive = false;\n worker.terminate();\n // Reject any pending requests\n for (const pending of pendingRequests.values()) {\n pending.reject(new Error(\"Worker terminated\"));\n }\n pendingRequests.clear();\n },\n isActive() {\n return isWorkerActive;\n },\n };\n}\n/**\n * Check if Web Workers are supported in the current environment.\n */\nexport function isWorkerSupported() {\n return typeof Worker !== \"undefined\";\n}\n//# sourceMappingURL=worker-proxy.js.map","/**\n * react-docxodus-viewer types\n */\n\nexport type CommentMode = 'disabled' | 'endnote' | 'inline' | 'margin';\nexport type AnnotationMode = 'disabled' | 'above' | 'inline' | 'tooltip' | 'none';\nexport type ViewMode = 'document' | 'revisions';\n/**\n * Automatic zoom-fit mode.\n * - `manual` (default): user controls zoom via the toolbar.\n * - `page-width`: scale so a page's width fills the viewer.\n * - `page`: scale so an entire page fits in the viewer (width and height).\n * Recomputes on initial render and on viewer resize.\n */\nexport type FitMode = 'manual' | 'page-width' | 'page';\n\nexport interface ViewerSettings {\n /** Zoom scale (0.3 - 2.0) */\n paginationScale: number;\n /** Show page numbers on pages */\n showPageNumbers: boolean;\n /** Render footnotes and endnotes */\n renderFootnotesAndEndnotes: boolean;\n /** Render headers and footers */\n renderHeadersAndFooters: boolean;\n /** Comment rendering mode */\n commentMode: CommentMode;\n /** Annotation rendering mode */\n annotationMode: AnnotationMode;\n /** Show tracked changes */\n renderTrackedChanges: boolean;\n /** Show deleted content in tracked changes */\n showDeletedContent: boolean;\n /** Distinguish move operations in tracked changes */\n renderMoveOperations: boolean;\n /** Page title for converted HTML */\n pageTitle: string;\n /** CSS class prefix for generated elements */\n cssPrefix: string;\n /** Generate CSS classes for styling */\n fabricateClasses: boolean;\n /** Additional CSS to inject */\n additionalCss: string;\n /** CSS class prefix for comments */\n commentCssClassPrefix: string;\n /** CSS class prefix for annotations */\n annotationCssClassPrefix: string;\n /**\n * Show placeholders for unsupported content (WMF/EMF images, math equations, form fields, etc.)\n * When enabled, unsupported content displays as styled placeholders instead of being silently dropped.\n */\n renderUnsupportedContentPlaceholders: boolean;\n /**\n * Override the document's default language for the HTML lang attribute.\n * If empty, the language is auto-detected from document settings.\n * Examples: \"en-US\", \"fr-FR\", \"de-DE\", \"ja-JP\"\n */\n documentLanguage: string;\n /**\n * Fixed width for the page container.\n * Accepts a number (pixels) or CSS length string (e.g., \"80vw\", \"100%\", \"50rem\").\n * When set, the viewer maintains this width regardless of content or zoom level,\n * providing pdf.js-like stable sizing behavior. The pages will be centered within\n * this container, and the container will scroll horizontally if content exceeds it.\n * Set to undefined/null for flexible sizing that adapts to content.\n * @example 816 // pixels\n * @example \"80vw\" // viewport width\n * @example \"100%\" // percentage of parent\n */\n stableWidth?: number | string;\n /**\n * Fixed minimum height for the page container.\n * Accepts a number (pixels) or CSS length string (e.g., \"60vh\", \"500px\", \"100%\").\n * When set, the viewer reserves this much vertical space regardless of content,\n * preventing layout shifts during loading. Set to undefined/null for flexible sizing.\n * @example 600 // pixels\n * @example \"70vh\" // viewport height\n * @example \"100%\" // percentage of parent\n */\n stableHeight?: number | string;\n}\n\n/**\n * A custom action button that can be injected into the viewer's toolbar.\n * Renders as an icon button on the right side of the toolbar (before the\n * settings gear), styled to match the built-in toolbar buttons.\n */\nexport interface ToolbarAction {\n /** Stable React key for this action. */\n key: string;\n /**\n * The icon to render inside the button. Accepts any React node — an inline\n * SVG, an icon-library component, an emoji, or a single character. Sized\n * via the parent button (~16px).\n */\n icon: React.ReactNode;\n /**\n * Accessible label, also shown as a tooltip on hover.\n */\n label: string;\n /** Click handler. */\n onClick: () => void;\n /** Disable the button. */\n disabled?: boolean;\n /**\n * Visual variant.\n * - `default`: matches existing toolbar buttons.\n * - `primary`: filled accent color, useful for the main action (e.g. Download).\n */\n variant?: 'default' | 'primary';\n /** Optional extra className appended to the button. */\n className?: string;\n}\n\nexport interface DocumentViewerProps {\n /** File to display (controlled mode) */\n file?: File | null;\n /** Pre-converted HTML content (skip conversion) */\n html?: string | null;\n\n /** Callback when file changes */\n onFileChange?: (file: File | null) => void;\n /** Callback when conversion starts */\n onConversionStart?: () => void;\n /** Callback when conversion completes successfully */\n onConversionComplete?: (html: string) => void;\n /** Callback when an error occurs */\n onError?: (error: Error) => void;\n /** Callback when visible page changes */\n onPageChange?: (page: number, total: number) => void;\n /** Callback when revisions are extracted from document */\n onRevisionsExtracted?: (revisions: import('docxodus').Revision[]) => void;\n\n /** Initial/controlled viewer settings */\n settings?: Partial<ViewerSettings>;\n /** Default settings (used for uncontrolled mode) */\n defaultSettings?: Partial<ViewerSettings>;\n /**\n * Convenience shortcut for the initial zoom level (uncontrolled mode).\n * Equivalent to `defaultSettings.paginationScale`. Range 0.3 – 2.0.\n * Ignored if `fitMode` is set to anything other than `'manual'`,\n * since the auto-fit logic will override the initial scale.\n * @example 1 // 100%\n * @example 0.75 // 75%\n */\n defaultZoom?: number;\n /** Callback when settings change */\n onSettingsChange?: (settings: ViewerSettings) => void;\n\n /** Additional CSS class for the root element */\n className?: string;\n /** Inline styles for the root element */\n style?: React.CSSProperties;\n /** Toolbar position */\n toolbar?: 'top' | 'bottom' | 'none';\n /** Show settings button in toolbar */\n showSettingsButton?: boolean;\n /** Show revisions tab when document has tracked changes */\n showRevisionsTab?: boolean;\n /** Placeholder text when no document is loaded */\n placeholder?: string;\n /**\n * Custom icon-button actions to render in the toolbar's right section,\n * just before the settings button. Useful for hosting apps that want to\n * surface document-level actions (Download, Share, Print, Open Ticket, ...)\n * inside the viewer's chrome rather than awkwardly above it.\n */\n toolbarActions?: ToolbarAction[];\n\n /**\n * Base path for WASM files.\n * Leave undefined for auto-detection (recommended for most setups).\n * Only specify if hosting WASM files at a custom location.\n */\n wasmBasePath?: string;\n /**\n * Use Web Worker for document conversion (keeps UI responsive).\n * Default: true\n */\n useWorker?: boolean;\n /**\n * Eagerly pre-warm the docxodus comparison code path as soon as the worker\n * is ready, before any user action.\n *\n * Creating the worker only warms the conversion runtime; the .NET WASM\n * comparison assemblies stay unloaded until the first compare, which then\n * pays ~3s of assembly-load latency. When `warmup` is true the viewer calls\n * docxodus's `prepare()` on mount so that cost is paid up front and the first\n * comparison is instant. The call is idempotent and fire-and-forget.\n *\n * Only applies in worker mode (`useWorker` is true, the default); it is a\n * no-op when `useWorker={false}`.\n * Default: false\n */\n warmup?: boolean;\n /**\n * Automatic zoom-fit mode. When set to `page-width` or `page`, the viewer\n * picks a zoom level that fits the rendered page in the viewer on initial\n * render and on viewer resize. Defaults to `manual` (user-controlled zoom).\n */\n fitMode?: FitMode;\n}\n\nexport const DEFAULT_SETTINGS: ViewerSettings = {\n paginationScale: 0.8,\n showPageNumbers: true,\n renderFootnotesAndEndnotes: true,\n renderHeadersAndFooters: true,\n commentMode: 'disabled',\n annotationMode: 'disabled',\n renderTrackedChanges: false,\n showDeletedContent: true,\n renderMoveOperations: true,\n pageTitle: 'Document',\n cssPrefix: 'docx-',\n fabricateClasses: true,\n additionalCss: '',\n commentCssClassPrefix: 'comment-',\n annotationCssClassPrefix: 'annot-',\n renderUnsupportedContentPlaceholders: true,\n documentLanguage: '',\n};\n","import { useState, useMemo } from 'react';\nimport type { Revision } from 'docxodus/react';\nimport { isInsertion, isDeletion, isMove, isFormatChange } from 'docxodus';\n\ninterface RevisionPanelProps {\n revisions: Revision[];\n}\n\ntype FilterType = 'all' | 'insertions' | 'deletions' | 'moves' | 'formatting';\n\nfunction getRevisionTypeLabel(revision: Revision): string {\n if (isInsertion(revision)) return 'Inserted';\n if (isDeletion(revision)) return 'Deleted';\n if (isMove(revision)) return revision.isMoveSource ? 'Moved from' : 'Moved to';\n if (isFormatChange(revision)) return 'Formatted';\n return String(revision.revisionType);\n}\n\nfunction getRevisionTypeClass(revision: Revision): string {\n if (isInsertion(revision)) return 'rdv-revision--insertion';\n if (isDeletion(revision)) return 'rdv-revision--deletion';\n if (isMove(revision)) return 'rdv-revision--move';\n if (isFormatChange(revision)) return 'rdv-revision--format';\n return '';\n}\n\nfunction formatDate(isoDate: string): string {\n try {\n const date = new Date(isoDate);\n return date.toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n } catch {\n return isoDate;\n }\n}\n\nfunction truncateText(text: string, maxLength: number = 150): string {\n if (text.length <= maxLength) return text;\n return text.substring(0, maxLength) + '...';\n}\n\n// Filter out raw XML values and clean up property names\nfunction isValidPropertyValue(value: string): boolean {\n if (!value || typeof value !== 'string') return false;\n // Filter out raw XML data\n if (value.includes('<') || value.includes('xmlns') || value.includes('Unid=')) return false;\n // Filter out overly long values (likely XML)\n if (value.length > 100) return false;\n return true;\n}\n\n// Make property names more readable\nfunction formatPropertyName(name: string): string {\n // Convert camelCase to Title Case with spaces\n return name\n .replace(/([A-Z])/g, ' $1')\n .replace(/^./, (str) => str.toUpperCase())\n .trim();\n}\n\n// Format property value for display\nfunction formatPropertyValue(value: string): string {\n if (value === 'true') return 'Yes';\n if (value === 'false') return 'No';\n if (value === 'single') return 'Single';\n if (value === 'double') return 'Double';\n return value;\n}\n\ninterface FormatChangeItem {\n property: string;\n oldValue?: string;\n newValue?: string;\n}\n\n// Get paired format changes (old → new for same property)\nfunction getFormatChanges(revision: Revision): FormatChangeItem[] {\n if (!revision.formatChange) return [];\n\n const { oldProperties, newProperties } = revision.formatChange;\n const changes: FormatChangeItem[] = [];\n const processedKeys = new Set<string>();\n\n // Process old properties\n if (oldProperties) {\n for (const [key, value] of Object.entries(oldProperties)) {\n if (!isValidPropertyValue(value)) continue;\n processedKeys.add(key);\n const newValue = newProperties?.[key];\n changes.push({\n property: formatPropertyName(key),\n oldValue: formatPropertyValue(value),\n newValue: newValue && isValidPropertyValue(newValue) ? formatPropertyValue(newValue) : undefined,\n });\n }\n }\n\n // Process new properties not in old\n if (newProperties) {\n for (const [key, value] of Object.entries(newProperties)) {\n if (processedKeys.has(key)) continue;\n if (!isValidPropertyValue(value)) continue;\n changes.push({\n property: formatPropertyName(key),\n oldValue: undefined,\n newValue: formatPropertyValue(value),\n });\n }\n }\n\n return changes;\n}\n\nexport function RevisionPanel({ revisions }: RevisionPanelProps) {\n const [filter, setFilter] = useState<FilterType>('all');\n const [expandedIds, setExpandedIds] = useState<Set<number>>(new Set());\n\n const filteredRevisions = useMemo(() => {\n if (filter === 'all') return revisions;\n return revisions.filter((rev) => {\n switch (filter) {\n case 'insertions': return isInsertion(rev);\n case 'deletions': return isDeletion(rev);\n case 'moves': return isMove(rev);\n case 'formatting': return isFormatChange(rev);\n default: return true;\n }\n });\n }, [revisions, filter]);\n\n const stats = useMemo(() => ({\n total: revisions.length,\n insertions: revisions.filter(isInsertion).length,\n deletions: revisions.filter(isDeletion).length,\n moves: revisions.filter(isMove).length,\n formatting: revisions.filter(isFormatChange).length,\n }), [revisions]);\n\n const toggleExpanded = (index: number) => {\n setExpandedIds((prev) => {\n const next = new Set(prev);\n if (next.has(index)) {\n next.delete(index);\n } else {\n next.add(index);\n }\n return next;\n });\n };\n\n if (revisions.length === 0) {\n return (\n <div className=\"rdv-revision-panel\">\n <div className=\"rdv-revision-empty\">\n <div className=\"rdv-revision-empty__icon\">📝</div>\n <p>No tracked changes found in this document.</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"rdv-revision-panel\">\n <div className=\"rdv-revision-header\">\n <div className=\"rdv-revision-stats\">\n <span className=\"rdv-revision-stat rdv-revision-stat--total\">\n {stats.total} change{stats.total !== 1 ? 's' : ''}\n </span>\n {stats.insertions > 0 && (\n <span className=\"rdv-revision-stat rdv-revision-stat--insertion\">\n +{stats.insertions}\n </span>\n )}\n {stats.deletions > 0 && (\n <span className=\"rdv-revision-stat rdv-revision-stat--deletion\">\n −{stats.deletions}\n </span>\n )}\n {stats.moves > 0 && (\n <span className=\"rdv-revision-stat rdv-revision-stat--move\">\n ↔{stats.moves}\n </span>\n )}\n {stats.formatting > 0 && (\n <span className=\"rdv-revision-stat rdv-revision-stat--format\">\n ✎{stats.formatting}\n </span>\n )}\n </div>\n <select\n className=\"rdv-revision-filter\"\n value={filter}\n onChange={(e) => setFilter(e.target.value as FilterType)}\n >\n <option value=\"all\">All Changes</option>\n <option value=\"insertions\">Insertions ({stats.insertions})</option>\n <option value=\"deletions\">Deletions ({stats.deletions})</option>\n <option value=\"moves\">Moves ({stats.moves})</option>\n <option value=\"formatting\">Formatting ({stats.formatting})</option>\n </select>\n </div>\n\n <div className=\"rdv-revision-list\">\n {filteredRevisions.map((revision, index) => {\n const isExpanded = expandedIds.has(index);\n const needsTruncation = revision.text.length > 150;\n const formatChanges = isFormatChange(revision) ? getFormatChanges(revision) : [];\n\n return (\n <div\n key={index}\n className={`rdv-revision-item ${getRevisionTypeClass(revision)}`}\n >\n <div className=\"rdv-revision-item__header\">\n <span className=\"rdv-revision-type\">\n {getRevisionTypeLabel(revision)}\n </span>\n {isMove(revision) && revision.moveGroupId !== undefined && (\n <span className=\"rdv-revision-move-id\">#{revision.moveGroupId}</span>\n )}\n <span className=\"rdv-revision-author\">{revision.author || 'Unknown'}</span>\n <span className=\"rdv-revision-date\">{formatDate(revision.date)}</span>\n </div>\n\n {revision.text && (\n <div className=\"rdv-revision-item__content\">\n <span className=\"rdv-revision-text\">\n {isExpanded ? revision.text : truncateText(revision.text)}\n </span>\n {needsTruncation && (\n <button\n className=\"rdv-revision-expand\"\n onClick={() => toggleExpanded(index)}\n >\n {isExpanded ? 'Show less' : 'Show more'}\n </button>\n )}\n </div>\n )}\n\n {formatChanges.length > 0 && (\n <div className=\"rdv-revision-item__format-details\">\n {formatChanges.map((change, i) => (\n <div key={i} className=\"rdv-format-change\">\n <span className=\"rdv-format-change__property\">{change.property}</span>\n <span className=\"rdv-format-change__values\">\n {change.oldValue && (\n <span className=\"rdv-format-change__old\">{change.oldValue}</span>\n )}\n {change.oldValue && change.newValue && (\n <span className=\"rdv-format-change__arrow\">→</span>\n )}\n {change.newValue && (\n <span className=\"rdv-format-change__new\">{change.newValue}</span>\n )}\n {!change.oldValue && change.newValue && (\n <span className=\"rdv-format-change__added\">(added)</span>\n )}\n {change.oldValue && !change.newValue && (\n <span className=\"rdv-format-change__removed\">(removed)</span>\n )}\n </span>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n","import { useState, useCallback, useRef, useEffect, useMemo } from 'react';\nimport { useDocxodus, PaginatedDocument } from 'docxodus/react';\nimport type { PaginationResult, Revision, DocumentMetadata } from 'docxodus/react';\nimport { CommentRenderMode, PaginationMode, AnnotationLabelMode, getDocumentMetadata } from 'docxodus';\nimport { createWorkerDocxodus, isWorkerSupported } from 'docxodus/worker';\nimport type { WorkerDocxodus } from 'docxodus/worker';\nimport type {\n DocumentViewerProps,\n ViewerSettings,\n CommentMode,\n AnnotationMode,\n ViewMode,\n FitMode,\n ToolbarAction,\n} from './types';\nimport { DEFAULT_SETTINGS } from './types';\nimport { RevisionPanel } from './components/RevisionPanel';\n\nconst OpenDocumentIcon = () => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"17 8 12 3 7 8\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n </svg>\n);\n\nfunction getCommentRenderMode(mode: CommentMode): CommentRenderMode {\n switch (mode) {\n case 'endnote': return CommentRenderMode.EndnoteStyle;\n case 'inline': return CommentRenderMode.Inline;\n case 'margin': return CommentRenderMode.Margin;\n default: return CommentRenderMode.Disabled;\n }\n}\n\nfunction getAnnotationLabelMode(mode: AnnotationMode): AnnotationLabelMode | undefined {\n switch (mode) {\n case 'above': return AnnotationLabelMode.Above;\n case 'inline': return AnnotationLabelMode.Inline;\n case 'tooltip': return AnnotationLabelMode.Tooltip;\n case 'none': return AnnotationLabelMode.None;\n default: return undefined;\n }\n}\n\nfunction toCssLength(value: number | string | undefined): string | undefined {\n if (value === undefined || value === null) return undefined;\n return typeof value === 'number' ? `${value}px` : value;\n}\n\nconst PAGE_PT_TO_PX = 96 / 72;\nconst FIT_PADDING_PX = 40;\nconst MIN_SCALE = 0.3;\nconst MAX_SCALE = 2.0;\n\nfunction computeFitScale(\n mode: Exclude<FitMode, 'manual'>,\n containerWidth: number,\n containerHeight: number,\n pageWidthPt: number,\n pageHeightPt: number,\n): number {\n const pageWidthPx = pageWidthPt * PAGE_PT_TO_PX;\n const pageHeightPx = pageHeightPt * PAGE_PT_TO_PX;\n const widthScale = (containerWidth - FIT_PADDING_PX) / pageWidthPx;\n const heightScale = (containerHeight - FIT_PADDING_PX) / pageHeightPx;\n const raw = mode === 'page-width' ? widthScale : Math.min(widthScale, heightScale);\n const clamped = Math.max(MIN_SCALE, Math.min(MAX_SCALE, raw));\n return Math.round(clamped * 100) / 100;\n}\n\nexport function DocumentViewer({\n file: controlledFile,\n html: controlledHtml,\n onFileChange,\n onConversionStart,\n onConversionComplete,\n onError,\n onPageChange,\n onRevisionsExtracted,\n settings: controlledSettings,\n defaultSettings,\n defaultZoom,\n onSettingsChange,\n className,\n style,\n toolbar = 'top',\n showSettingsButton = true,\n showRevisionsTab = true,\n placeholder = 'Open a DOCX file to view',\n wasmBasePath,\n useWorker = true,\n warmup = false,\n fitMode = 'manual',\n toolbarActions,\n}: DocumentViewerProps) {\n // Merge default settings. `defaultZoom` is a convenience shortcut for\n // `defaultSettings.paginationScale`; explicit `defaultSettings` wins if both\n // are provided.\n const mergedDefaults = useMemo(() => {\n const base: ViewerSettings = { ...DEFAULT_SETTINGS };\n if (defaultZoom !== undefined) {\n base.paginationScale = Math.max(0.3, Math.min(2.0, defaultZoom));\n }\n return { ...base, ...defaultSettings };\n }, [defaultSettings, defaultZoom]);\n\n // Internal state (uncontrolled mode)\n const [internalFile, setInternalFile] = useState<File | null>(null);\n const [internalHtml, setInternalHtml] = useState<string | null>(null);\n const [internalSettings, setInternalSettings] = useState<ViewerSettings>(mergedDefaults);\n\n // Determine which values to use (controlled vs uncontrolled)\n const file = controlledFile !== undefined ? controlledFile : internalFile;\n const html = controlledHtml !== undefined ? controlledHtml : internalHtml;\n const settings = useMemo(\n () => controlledSettings\n ? { ...mergedDefaults, ...controlledSettings }\n : internalSettings,\n [controlledSettings, mergedDefaults, internalSettings]\n );\n\n // Docxodus hook (used when not in worker mode)\n const hookResult = useDocxodus(wasmBasePath);\n\n // Worker instance state (used when useWorker=true)\n const [worker, setWorker] = useState<WorkerDocxodus | null>(null);\n const [workerReady, setWorkerReady] = useState(false);\n const [workerError, setWorkerError] = useState<Error | null>(null);\n // Derived rather than tracked separately: true exactly while a worker\n // creation attempt is in flight (started, not yet ready, not yet errored).\n const workerLoading = useWorker && isWorkerSupported() && !workerReady && !workerError;\n\n // Create/destroy worker based on useWorker prop\n const workerRef = useRef<WorkerDocxodus | null>(null);\n\n useEffect(() => {\n if (!useWorker || !isWorkerSupported()) {\n return;\n }\n\n let cancelled = false;\n\n createWorkerDocxodus({ wasmBasePath })\n .then((workerInstance) => {\n if (!cancelled) {\n workerRef.current = workerInstance;\n setWorker(workerInstance);\n setWorkerReady(true);\n setWorkerError(null);\n } else {\n workerInstance.terminate();\n }\n })\n .catch((err) => {\n if (!cancelled) {\n setWorkerError(err instanceof Error ? err : new Error(String(err)));\n }\n });\n\n return () => {\n cancelled = true;\n if (workerRef.current) {\n workerRef.current.terminate();\n workerRef.current = null;\n setWorker(null);\n setWorkerReady(false);\n }\n };\n }, [useWorker, wasmBasePath]);\n\n // Eagerly pre-warm the comparison code path once the worker is ready, so the\n // first comparison doesn't pay the ~3s assembly-load latency. `prepare()` is\n // idempotent and only exists on the worker, so this is a no-op in non-worker\n // mode. Fire-and-forget: warmup failure must not surface as a viewer error.\n useEffect(() => {\n if (!warmup || !worker) return;\n worker.prepare().catch(() => {\n // Pre-warming is a best-effort optimization; ignore failures.\n });\n }, [warmup, worker]);\n\n // Unified ready/loading/error state\n const isReady = useWorker ? workerReady : hookResult.isReady;\n const isLoading = useWorker ? workerLoading : hookResult.isLoading;\n const initError = useWorker ? workerError : hookResult.error;\n\n // Local UI state\n const [isConverting, setIsConverting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [fileName, setFileName] = useState<string>('');\n const [currentPage, setCurrentPage] = useState(1);\n const [totalPages, setTotalPages] = useState(0);\n const [showSettings, setShowSettings] = useState(false);\n const [viewMode, setViewMode] = useState<ViewMode>('document');\n const [revisions, setRevisions] = useState<Revision[]>([]);\n const [isExtractingRevisions, setIsExtractingRevisions] = useState(false);\n\n // Document metadata for progressive loading placeholders\n const [documentMetadata, setDocumentMetadata] = useState<DocumentMetadata | null>(null);\n\n const viewerRef = useRef<HTMLDivElement>(null);\n const paginatedContainerRef = useRef<HTMLDivElement>(null);\n\n // Inter-page gap read from --rdv-page-gap CSS variable (defaults to 20)\n const [pageGap, setPageGap] = useState(20);\n useEffect(() => {\n const readGap = () => {\n const el = viewerRef.current;\n if (!el) return;\n const value = getComputedStyle(el).getPropertyValue('--rdv-page-gap').trim();\n const parsed = parseFloat(value);\n if (!Number.isNaN(parsed)) setPageGap(parsed);\n };\n readGap();\n window.addEventListener('resize', readGap);\n return () => window.removeEventListener('resize', readGap);\n }, []);\n\n // Build conversion options from settings\n const getConvertOptions = useCallback(() => ({\n commentRenderMode: getCommentRenderMode(settings.commentMode),\n pageTitle: settings.pageTitle,\n cssPrefix: settings.cssPrefix,\n fabricateClasses: settings.fabricateClasses,\n additionalCss: settings.additionalCss || undefined,\n commentCssClassPrefix: settings.commentCssClassPrefix,\n paginationMode: PaginationMode.Paginated,\n paginationScale: settings.paginationScale,\n renderAnnotations: settings.annotationMode !== 'disabled',\n annotationLabelMode: getAnnotationLabelMode(settings.annotationMode),\n annotationCssClassPrefix: settings.annotationCssClassPrefix,\n renderFootnotesAndEndnotes: settings.renderFootnotesAndEndnotes,\n renderHeadersAndFooters: settings.renderHeadersAndFooters,\n renderTrackedChanges: settings.renderTrackedChanges,\n showDeletedContent: settings.showDeletedContent,\n renderMoveOperations: settings.renderMoveOperations,\n renderUnsupportedContentPlaceholders: settings.renderUnsupportedContentPlaceholders,\n documentLanguage: settings.documentLanguage || undefined,\n }), [settings]);\n\n // Fetch document metadata quickly (for progressive loading placeholders)\n const fetchMetadata = useCallback(async (fileToFetch: File) => {\n try {\n // Use worker's getDocumentMetadata if available, otherwise direct call\n const metadata = useWorker && worker\n ? await worker.getDocumentMetadata(fileToFetch)\n : await getDocumentMetadata(fileToFetch);\n setDocumentMetadata(metadata);\n } catch {\n // Metadata extraction is non-critical, silently fail\n setDocumentMetadata(null);\n }\n }, [useWorker, worker]);\n\n // Extract revisions from document\n const extractRevisions = useCallback(async (fileToExtract: File) => {\n if (!isReady || !showRevisionsTab) return;\n\n setIsExtractingRevisions(true);\n try {\n const extractedRevisions = useWorker && worker\n ? await worker.getRevisions(fileToExtract)\n : await hookResult.getRevisions(fileToExtract);\n setRevisions(extractedRevisions);\n onRevisionsExtracted?.(extractedRevisions);\n } catch {\n // Revision extraction is non-critical, silently fail\n setRevisions([]);\n } finally {\n setIsExtractingRevisions(false);\n }\n }, [isReady, useWorker, worker, hookResult, showRevisionsTab, onRevisionsExtracted]);\n\n // Convert file to HTML\n const convert = useCallback(async (fileToConvert: File) => {\n if (!isReady) return;\n\n setIsConverting(true);\n setError(null);\n setRevisions([]);\n setViewMode('document');\n // Don't reset documentMetadata here - we want to show placeholders during conversion\n onConversionStart?.();\n\n // Allow React to render loading state before heavy WASM work (only needed for non-worker mode)\n if (!useWorker) {\n await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));\n }\n\n try {\n const result = useWorker && worker\n ? await worker.convertDocxToHtml(fileToConvert, getConvertOptions())\n : await hookResult.convertToHtml(fileToConvert, getConvertOptions());\n\n if (controlledHtml === undefined) {\n setInternalHtml(result);\n }\n onConversionComplete?.(result);\n\n // Extract revisions in background after conversion\n extractRevisions(fileToConvert);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n onError?.(error);\n } finally {\n setIsConverting(false);\n }\n }, [isReady, useWorker, worker, hookResult, getConvertOptions, controlledHtml, onConversionStart, onConversionComplete, onError, extractRevisions]);\n\n // Auto-convert when WASM ready and file available. `convert` sets\n // isConverting synchronously so the UI can show a spinner immediately;\n // that can't be derived instead without breaking controlled-`html` mode,\n // where `html` can stay non-null across a reconvert.\n useEffect(() => {\n if (isReady && file && !html && !isConverting && controlledHtml === undefined) {\n // eslint-disable-next-line react-hooks/set-state-in-effect -- see comment above\n convert(file);\n }\n }, [isReady, file, html, isConverting, convert, controlledHtml]);\n\n // Handle file input change\n const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const selectedFile = e.target.files?.[0];\n if (selectedFile) {\n setFileName(selectedFile.name);\n setError(null);\n setCurrentPage(1);\n setTotalPages(0);\n setDocumentMetadata(null); // Reset metadata from previous file\n setRevisions([]); // Reset revisions\n setViewMode('document');\n\n if (controlledFile === undefined) {\n setInternalFile(selectedFile);\n setInternalHtml(null);\n }\n onFileChange?.(selectedFile);\n\n // Fetch metadata first for placeholders, then convert\n fetchMetadata(selectedFile);\n if (isReady && controlledHtml === undefined) {\n await convert(selectedFile);\n }\n }\n };\n\n // Reconvert with current settings\n const reconvert = useCallback(async () => {\n if (file) {\n if (controlledHtml === undefined) {\n setInternalHtml(null);\n }\n await convert(file);\n }\n }, [file, convert, controlledHtml]);\n\n // Clear document\n const handleClear = () => {\n if (controlledFile === undefined) {\n setInternalFile(null);\n }\n if (controlledHtml === undefined) {\n setInternalHtml(null);\n }\n setError(null);\n setFileName('');\n setCurrentPage(1);\n setTotalPages(0);\n setRevisions([]);\n setViewMode('document');\n setDocumentMetadata(null);\n onFileChange?.(null);\n\n const input = document.getElementById('rdv-file-input') as HTMLInputElement;\n if (input) input.value = '';\n };\n\n // Update settings\n const updateSettings = useCallback((updates: Partial<ViewerSettings>) => {\n const newSettings = { ...settings, ...updates };\n if (controlledSettings === undefined) {\n setInternalSettings(newSettings);\n }\n onSettingsChange?.(newSettings);\n }, [settings, controlledSettings, onSettingsChange]);\n\n // Zoom controls\n const handleZoomIn = () => updateSettings({\n paginationScale: Math.min(settings.paginationScale + 0.1, 2.0)\n });\n const handleZoomOut = () => updateSettings({\n paginationScale: Math.max(settings.paginationScale - 0.1, 0.3)\n });\n const handleZoomChange = (value: number) => updateSettings({\n paginationScale: Math.max(0.3, Math.min(2.0, value))\n });\n\n // Auto-fit: when fitMode is not 'manual', pick a scale that fits the page\n // into the viewer on initial render and whenever the viewer resizes.\n // settingsRef avoids putting `settings` in this effect's deps, which would\n // re-create the ResizeObserver on every scale change and cause loops.\n const settingsRef = useRef(settings);\n useEffect(() => {\n settingsRef.current = settings;\n });\n useEffect(() => {\n if (fitMode === 'manual' || !documentMetadata || !html) return;\n const container = paginatedContainerRef.current;\n if (!container || typeof ResizeObserver === 'undefined') return;\n\n const section = documentMetadata.sections[0];\n const pageWidthPt = section?.pageWidthPt ?? 612;\n const pageHeightPt = section?.pageHeightPt ?? 792;\n\n const applyFit = () => {\n const scale = computeFitScale(\n fitMode,\n container.clientWidth,\n container.clientHeight,\n pageWidthPt,\n pageHeightPt,\n );\n if (Math.abs(settingsRef.current.paginationScale - scale) < 0.005) return;\n const newSettings = { ...settingsRef.current, paginationScale: scale };\n if (controlledSettings === undefined) {\n setInternalSettings(newSettings);\n }\n onSettingsChange?.(newSettings);\n };\n\n applyFit();\n const ro = new ResizeObserver(applyFit);\n ro.observe(container);\n return () => ro.disconnect();\n }, [fitMode, documentMetadata, html, controlledSettings, onSettingsChange]);\n\n // Page navigation\n const goToPage = (pageNum: number) => {\n const container = paginatedContainerRef.current;\n if (!container || pageNum < 1 || pageNum > totalPages) return;\n const pageElement = container.querySelector(`[data-page-number=\"${pageNum}\"]`);\n if (pageElement) {\n pageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n };\n\n const goToPreviousPage = () => currentPage > 1 && goToPage(currentPage - 1);\n const goToNextPage = () => currentPage < totalPages && goToPage(currentPage + 1);\n\n // Handle page visibility changes\n const handlePageVisible = (pageNumber: number) => {\n setCurrentPage(pageNumber);\n onPageChange?.(pageNumber, totalPages);\n };\n\n // Handle footnote/anchor clicks\n useEffect(() => {\n const container = paginatedContainerRef.current;\n if (!container) return;\n\n const handleAnchorClick = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n const anchor = target.closest('a[href^=\"#\"]') as HTMLAnchorElement | null;\n if (!anchor) return;\n\n const href = anchor.getAttribute('href');\n if (!href || !href.startsWith('#')) return;\n\n e.preventDefault();\n const targetId = href.substring(1);\n const targetElement = container.querySelector(`[id=\"${targetId}\"], [name=\"${targetId}\"]`);\n\n if (targetElement) {\n targetElement.scrollIntoView({ behavior: 'smooth', block: 'center' });\n targetElement.classList.add('rdv-footnote-highlight');\n setTimeout(() => targetElement.classList.remove('rdv-footnote-highlight'), 2000);\n }\n };\n\n container.addEventListener('click', handleAnchorClick);\n return () => container.removeEventListener('click', handleAnchorClick);\n }, [html]);\n\n // Notify parent of page changes when totalPages updates\n useEffect(() => {\n if (totalPages > 0) {\n onPageChange?.(currentPage, totalPages);\n }\n }, [totalPages, currentPage, onPageChange]);\n\n const isProcessing = isConverting || isLoading;\n\n // Settings Modal\n const renderSettingsModal = () => (\n <div className=\"rdv-settings-overlay\" onClick={() => setShowSettings(false)}>\n <div className=\"rdv-settings-modal\" onClick={(e) => e.stopPropagation()}>\n <div className=\"rdv-settings-header\">\n <h3>Viewer Settings</h3>\n <button className=\"rdv-settings-close\" onClick={() => setShowSettings(false)}>×</button>\n </div>\n <div className=\"rdv-settings-body\">\n <div className=\"rdv-settings-section\">\n <h4>Display Options</h4>\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.renderFootnotesAndEndnotes}\n onChange={(e) => updateSettings({ renderFootnotesAndEndnotes: e.target.checked })}\n />\n <span>Show footnotes and endnotes</span>\n </label>\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.renderHeadersAndFooters}\n onChange={(e) => updateSettings({ renderHeadersAndFooters: e.target.checked })}\n />\n <span>Show headers and footers</span>\n </label>\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.showPageNumbers}\n onChange={(e) => updateSettings({ showPageNumbers: e.target.checked })}\n />\n <span>Show page numbers</span>\n </label>\n </div>\n\n <div className=\"rdv-settings-section\">\n <h4>Comment Rendering</h4>\n <div className=\"rdv-settings-radio-group\">\n {(['disabled', 'endnote', 'inline', 'margin'] as CommentMode[]).map((mode) => (\n <label key={mode} className=\"rdv-settings-radio\">\n <input\n type=\"radio\"\n name=\"commentMode\"\n checked={settings.commentMode === mode}\n onChange={() => updateSettings({ commentMode: mode })}\n />\n <span>{mode.charAt(0).toUpperCase() + mode.slice(1)}{mode === 'endnote' ? 's' : ''}</span>\n </label>\n ))}\n </div>\n </div>\n\n <div className=\"rdv-settings-section\">\n <h4>Annotation Rendering</h4>\n <div className=\"rdv-settings-radio-group\">\n {(['disabled', 'above', 'inline', 'tooltip', 'none'] as AnnotationMode[]).map((mode) => (\n <label key={mode} className=\"rdv-settings-radio\">\n <input\n type=\"radio\"\n name=\"annotationMode\"\n checked={settings.annotationMode === mode}\n onChange={() => updateSettings({ annotationMode: mode })}\n />\n <span>{mode === 'none' ? 'Highlight Only' : mode.charAt(0).toUpperCase() + mode.slice(1)}</span>\n </label>\n ))}\n </div>\n </div>\n\n <div className=\"rdv-settings-section\">\n <h4>Tracked Changes</h4>\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.renderTrackedChanges}\n onChange={(e) => updateSettings({ renderTrackedChanges: e.target.checked })}\n />\n <span>Show tracked changes</span>\n </label>\n {settings.renderTrackedChanges && (\n <div className=\"rdv-settings-subsection\">\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.showDeletedContent}\n onChange={(e) => updateSettings({ showDeletedContent: e.target.checked })}\n />\n <span>Show deleted content</span>\n </label>\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.renderMoveOperations}\n onChange={(e) => updateSettings({ renderMoveOperations: e.target.checked })}\n />\n <span>Distinguish move operations</span>\n </label>\n </div>\n )}\n </div>\n\n <div className=\"rdv-settings-section\">\n <h4>Advanced</h4>\n <label className=\"rdv-settings-checkbox\">\n <input\n type=\"checkbox\"\n checked={settings.renderUnsupportedContentPlaceholders}\n onChange={(e) => updateSettings({ renderUnsupportedContentPlaceholders: e.target.checked })}\n />\n <span>Show placeholders for unsupported content</span>\n </label>\n <p className=\"rdv-settings-hint\">\n Display visual indicators for WMF/EMF images, math equations, form fields, and other unsupported elements\n </p>\n <label className=\"rdv-settings-input-label\">\n <span>Document language override</span>\n <input\n type=\"text\"\n className=\"rdv-settings-text-input\"\n value={settings.documentLanguage}\n onChange={(e) => updateSettings({ documentLanguage: e.target.value })}\n placeholder=\"Auto-detect (e.g., en-US, fr-FR)\"\n />\n </label>\n </div>\n </div>\n <div className=\"rdv-settings-footer\">\n <button className=\"rdv-settings-apply\" onClick={() => { reconvert(); setShowSettings(false); }}>\n Apply & Close\n </button>\n </div>\n </div>\n </div>\n );\n\n const hasRevisions = revisions.length > 0;\n\n // Render a single custom toolbar action button\n const renderToolbarAction = (action: ToolbarAction) => {\n const variantClass = action.variant === 'primary' ? 'rdv-toolbar-icon-btn--primary' : '';\n const classes = [\n 'rdv-toolbar-btn',\n 'rdv-toolbar-icon-btn',\n variantClass,\n action.className,\n ]\n .filter(Boolean)\n .join(' ');\n return (\n <button\n key={action.key}\n type=\"button\"\n className={classes}\n onClick={action.onClick}\n disabled={action.disabled}\n title={action.label}\n aria-label={action.label}\n >\n {action.icon}\n </button>\n );\n };\n\n // Toolbar component\n const renderToolbar = () => (\n <div className=\"rdv-toolbar\">\n <div className=\"rdv-toolbar-left\">\n <label\n htmlFor=\"rdv-file-input\"\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn rdv-toolbar-open-btn\"\n title=\"Open Document\"\n aria-label=\"Open Document\"\n >\n <OpenDocumentIcon />\n </label>\n <input\n id=\"rdv-file-input\"\n type=\"file\"\n accept=\".docx\"\n onChange={handleFileChange}\n disabled={isProcessing}\n className=\"rdv-file-input\"\n />\n {fileName && (\n <span className=\"rdv-toolbar-filename\" title={fileName}>\n {fileName}\n </span>\n )}\n {fileName && (\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn rdv-toolbar-clear\"\n onClick={handleClear}\n disabled={isProcessing}\n title=\"Clear Document\"\n aria-label=\"Clear Document\"\n >\n ×\n </button>\n )}\n {showRevisionsTab && hasRevisions && html && (\n <>\n <div className=\"rdv-toolbar-separator\" />\n <div className=\"rdv-view-tabs\">\n <button\n className={`rdv-view-tab ${viewMode === 'document' ? 'rdv-view-tab--active' : ''}`}\n onClick={() => setViewMode('document')}\n title=\"View Document\"\n >\n Document\n </button>\n <button\n className={`rdv-view-tab ${viewMode === 'revisions' ? 'rdv-view-tab--active' : ''}`}\n onClick={() => setViewMode('revisions')}\n title=\"View Tracked Changes\"\n >\n Changes ({revisions.length})\n </button>\n </div>\n </>\n )}\n {showRevisionsTab && isExtractingRevisions && (\n <span className=\"rdv-extracting-indicator\" title=\"Extracting tracked changes...\">\n ...\n </span>\n )}\n </div>\n\n <div className=\"rdv-toolbar-right\">\n {html && totalPages > 0 && viewMode === 'document' && (\n <>\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn\"\n onClick={goToPreviousPage}\n disabled={currentPage <= 1}\n title=\"Previous Page\"\n aria-label=\"Previous Page\"\n >\n ◀\n </button>\n <div className=\"rdv-page-input-group\">\n <input\n type=\"number\"\n className=\"rdv-page-input\"\n value={currentPage}\n min={1}\n max={totalPages}\n onChange={(e) => {\n const page = parseInt(e.target.value);\n if (!isNaN(page)) goToPage(page);\n }}\n />\n <span className=\"rdv-page-total\">/ {totalPages}</span>\n </div>\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn\"\n onClick={goToNextPage}\n disabled={currentPage >= totalPages}\n title=\"Next Page\"\n aria-label=\"Next Page\"\n >\n ▶\n </button>\n\n <div className=\"rdv-toolbar-separator\" />\n\n <div className=\"rdv-zoom-group\">\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn rdv-zoom-btn\"\n onClick={handleZoomOut}\n disabled={settings.paginationScale <= 0.3}\n title=\"Zoom Out\"\n aria-label=\"Zoom Out\"\n >\n −\n </button>\n <select\n className=\"rdv-zoom-select\"\n value={settings.paginationScale}\n onChange={(e) => handleZoomChange(parseFloat(e.target.value))}\n aria-label=\"Zoom level\"\n >\n <option value=\"0.5\">50%</option>\n <option value=\"0.75\">75%</option>\n <option value=\"0.8\">80%</option>\n <option value=\"0.9\">90%</option>\n <option value=\"1\">100%</option>\n <option value=\"1.25\">125%</option>\n <option value=\"1.5\">150%</option>\n <option value=\"2\">200%</option>\n </select>\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn rdv-zoom-btn\"\n onClick={handleZoomIn}\n disabled={settings.paginationScale >= 2.0}\n title=\"Zoom In\"\n aria-label=\"Zoom In\"\n >\n +\n </button>\n </div>\n </>\n )}\n {toolbarActions && toolbarActions.length > 0 && (\n <>\n {html && totalPages > 0 && viewMode === 'document' && (\n <div className=\"rdv-toolbar-separator\" />\n )}\n {toolbarActions.map(renderToolbarAction)}\n </>\n )}\n {showSettingsButton && (\n <>\n {(toolbarActions?.length || (html && totalPages > 0 && viewMode === 'document')) && (\n <div className=\"rdv-toolbar-separator\" />\n )}\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-icon-btn rdv-toolbar-settings\"\n onClick={() => setShowSettings(true)}\n title=\"Settings\"\n aria-label=\"Settings\"\n >\n ⚙\n </button>\n </>\n )}\n </div>\n </div>\n );\n\n const rootClassName = ['rdv-viewer', className].filter(Boolean).join(' ');\n\n return (\n <div ref={viewerRef} className={rootClassName} style={style}>\n {toolbar === 'top' && renderToolbar()}\n\n <div className=\"rdv-content\">\n {initError && (\n <div className=\"rdv-message rdv-message--error\">\n <p>Failed to initialize: {initError.message}</p>\n </div>\n )}\n\n {!initError && (isLoading || isConverting) && (\n documentMetadata && isConverting ? (\n // Show page placeholders while converting - matches actual page dimensions for stable layout\n <div\n className=\"rdv-pages rdv-pages--loading\"\n style={{\n // Apply stable dimensions to match rendered state - prevents layout shift\n ...(settings.stableWidth && { '--rdv-stable-width': toCssLength(settings.stableWidth) }),\n ...(settings.stableHeight && { minHeight: toCssLength(settings.stableHeight) }),\n } as React.CSSProperties}\n >\n <div className=\"rdv-page-placeholders\" style={{ backgroundColor: '#525659' }}>\n {Array.from({ length: documentMetadata.estimatedPageCount || 1 }).map((_, index) => {\n // Get section for this page (approximate - use first section if not enough)\n const section = documentMetadata.sections[\n Math.min(index, documentMetadata.sections.length - 1)\n ];\n // Calculate scaled dimensions (points to pixels, then apply scale)\n const scale = settings.paginationScale;\n const width = Math.round((section?.pageWidthPt || 612) * (96 / 72) * scale);\n const height = Math.round((section?.pageHeightPt || 792) * (96 / 72) * scale);\n\n return (\n <div\n key={index}\n className=\"rdv-page-placeholder\"\n style={{\n width: `${width}px`,\n height: `${height}px`,\n }}\n >\n <div className=\"rdv-page-placeholder__shimmer\" />\n {index === 0 && (\n <div className=\"rdv-page-placeholder__info\">\n <div className=\"rdv-spinner rdv-spinner--small\"></div>\n <span>Converting document...</span>\n <span className=\"rdv-page-placeholder__count\">\n ~{documentMetadata.estimatedPageCount} page{documentMetadata.estimatedPageCount !== 1 ? 's' : ''}\n </span>\n </div>\n )}\n <div className=\"rdv-page-placeholder__number\">{index + 1}</div>\n </div>\n );\n })}\n </div>\n </div>\n ) : (\n <div className=\"rdv-message\">\n <div className=\"rdv-spinner\"></div>\n <p>\n {isLoading && file\n ? 'Loading engine & preparing document...'\n : isLoading\n ? 'Loading document engine...'\n : 'Processing document...'}\n </p>\n </div>\n )\n )}\n\n {!isLoading && !initError && !html && !isConverting && !file && (\n <div\n className=\"rdv-message\"\n style={{\n // Apply stable dimensions for consistent sizing across all states\n ...(settings.stableWidth && { width: toCssLength(settings.stableWidth), maxWidth: '100%' }),\n ...(settings.stableHeight && { minHeight: toCssLength(settings.stableHeight) }),\n }}\n >\n <div className=\"rdv-message__icon\">📄</div>\n <p>{placeholder}</p>\n </div>\n )}\n\n {error && !isConverting && (\n <div className=\"rdv-message rdv-message--error\">\n <p>Error: {error.message}</p>\n </div>\n )}\n\n {viewMode === 'document' && html && !isConverting && (\n <div\n ref={paginatedContainerRef}\n className=\"rdv-pages\"\n style={{\n // Apply stable dimensions if provided - provides pdf.js-like sizing behavior\n ...(settings.stableWidth && { '--rdv-stable-width': toCssLength(settings.stableWidth) }),\n ...(settings.stableHeight && { minHeight: toCssLength(settings.stableHeight) }),\n } as React.CSSProperties}\n >\n <PaginatedDocument\n html={html}\n scale={settings.paginationScale}\n showPageNumbers={settings.showPageNumbers}\n pageGap={pageGap}\n backgroundColor=\"#525659\"\n className=\"rdv-paginated-document\"\n onPaginationComplete={(result: PaginationResult) => {\n setTotalPages(result.totalPages);\n }}\n onPageVisible={handlePageVisible}\n />\n </div>\n )}\n\n {viewMode === 'revisions' && html && !isConverting && (\n <RevisionPanel revisions={revisions} />\n )}\n </div>\n\n {toolbar === 'bottom' && renderToolbar()}\n\n {showSettings && renderSettingsModal()}\n </div>\n );\n}\n"],"x_google_ignoreList":[0],"mappings":"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"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
.rdv-viewer{--rdv-border-radius: 8px;--rdv-background: #525659;--rdv-min-height: 400px;--rdv-height: 80vh;--rdv-max-height: 90vh;--rdv-shadow: 0 4px 20px rgba(0, 0, 0, .15);--rdv-stable-width: auto;--rdv-stable-height: auto;--rdv-page-gap: 20px;--rdv-toolbar-bg: #323639;--rdv-toolbar-border: #1a1a1a;--rdv-toolbar-height: auto;--rdv-toolbar-padding: .5rem 1rem;--rdv-btn-bg: #474c50;--rdv-btn-bg-hover: #5a6066;--rdv-btn-color: #d4d4d4;--rdv-btn-radius: 4px;--rdv-btn-disabled-opacity: .4;--rdv-input-bg: #474c50;--rdv-input-color: #d4d4d4;--rdv-input-muted: #9ca3af;--rdv-separator-color: #555;--rdv-message-color: #9ca3af;--rdv-error-color: #ef4444;--rdv-highlight-color: #fef08a;--rdv-modal-overlay: rgba(0, 0, 0, .6);--rdv-modal-bg: white;--rdv-modal-radius: 12px;--rdv-modal-shadow: 0 20px 60px rgba(0, 0, 0, .3);--rdv-modal-border: #e5e7eb;--rdv-modal-title-color: #1f2937;--rdv-modal-text-color: #4b5563;--rdv-modal-muted-color: #6b7280;--rdv-modal-section-bg: #f3f4f6;--rdv-modal-section-bg-hover: #e5e7eb;--rdv-modal-advanced-bg: #f9fafb;--rdv-modal-input-border: #d1d5db;--rdv-modal-input-focus: #3b82f6;--rdv-modal-btn-bg: #3b82f6;--rdv-modal-btn-bg-hover: #2563eb}.rdv-viewer{display:flex;flex-direction:column;height:var(--rdv-height);min-height:var(--rdv-min-height);max-height:var(--rdv-max-height);border-radius:var(--rdv-border-radius);overflow:hidden;background:var(--rdv-background);box-shadow:var(--rdv-shadow)}.rdv-viewer del,.rdv-viewer [data-revision-type=deleted],.rdv-viewer [data-move-source=true]{user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.rdv-toolbar{display:flex;align-items:center;justify-content:space-between;padding:var(--rdv-toolbar-padding);background:var(--rdv-toolbar-bg);border-bottom:1px solid var(--rdv-toolbar-border);flex-shrink:0}.rdv-toolbar-left,.rdv-toolbar-right{display:flex;align-items:center;gap:.375rem}.rdv-toolbar-btn{background:var(--rdv-btn-bg);border:none;color:var(--rdv-btn-color);padding:.4rem .7rem;border-radius:var(--rdv-btn-radius);cursor:pointer;font-size:.9rem;font-weight:700;min-width:32px;transition:background .2s,color .2s}.rdv-toolbar-btn:hover:not(:disabled){background:var(--rdv-btn-bg-hover)}.rdv-toolbar-btn:disabled{opacity:var(--rdv-btn-disabled-opacity);cursor:not-allowed}.rdv-toolbar-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;min-width:32px;height:32px;padding:0;line-height:1}.rdv-toolbar-icon-btn svg{display:block}.rdv-toolbar-icon-btn--primary{background:var(--rdv-btn-primary-bg, #3b82f6);color:var(--rdv-btn-primary-color, #ffffff)}.rdv-toolbar-icon-btn--primary:hover:not(:disabled){background:var(--rdv-btn-primary-bg-hover, #2563eb)}.rdv-toolbar-open-btn{cursor:pointer}.rdv-toolbar-filename{color:var(--rdv-btn-color);font-size:.8rem;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;opacity:.85}.rdv-toolbar-clear{font-size:1.15rem}.rdv-toolbar-settings{font-size:1.05rem}.rdv-page-input-group{display:flex;align-items:center;gap:.25rem;background:var(--rdv-input-bg);border-radius:var(--rdv-btn-radius);padding:0 .5rem}.rdv-page-input{width:50px;background:transparent;border:none;color:var(--rdv-input-color);text-align:center;font-size:.9rem;padding:.4rem 0;-moz-appearance:textfield}.rdv-page-input::-webkit-outer-spin-button,.rdv-page-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.rdv-page-input:focus{outline:none}.rdv-page-total{color:var(--rdv-input-muted);font-size:.9rem}.rdv-toolbar-separator{width:1px;height:24px;background:var(--rdv-separator-color);margin:0 .25rem}.rdv-zoom-group{display:flex;align-items:center;background:var(--rdv-btn-bg);border-radius:var(--rdv-btn-radius);overflow:hidden}.rdv-zoom-group .rdv-zoom-btn{background:transparent;border-radius:0;width:28px;min-width:28px;height:30px}.rdv-zoom-group .rdv-zoom-btn:hover:not(:disabled){background:var(--rdv-btn-bg-hover)}.rdv-zoom-select{background:transparent;border:none;color:var(--rdv-btn-color);padding:.3rem .5rem .3rem .35rem;border-radius:0;font-size:.85rem;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;text-align:center;text-align-last:center}.rdv-zoom-select:focus{outline:none}.rdv-zoom-select:hover{background:var(--rdv-btn-bg-hover)}.rdv-file-input{display:none}.rdv-content{flex:1;overflow:hidden;display:flex;flex-direction:column;min-height:0;contain:strict}.rdv-pages{flex:1;overflow:auto;min-height:0;scroll-behavior:smooth;contain:layout style;width:var(--rdv-stable-width, 100%);max-width:100%}.rdv-pages__stable-wrapper{display:flex;flex-direction:column;align-items:center;min-height:100%}.rdv-paginated-document{min-height:100%;color:#000;-webkit-text-fill-color:initial}.rdv-paginated-document *{-webkit-text-fill-color:inherit}.rdv-message{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;min-height:300px;color:var(--rdv-message-color);text-align:center;padding:2rem}.rdv-message--error{color:var(--rdv-error-color)}.rdv-message__icon{font-size:4rem;margin-bottom:1rem;opacity:.5}.rdv-message p{margin:.5rem 0;font-size:1rem}.rdv-spinner{width:40px;height:40px;border:4px solid rgba(255,255,255,.2);border-top-color:var(--rdv-btn-color);border-radius:50%;animation:rdv-spin 1s linear infinite}@keyframes rdv-spin{to{transform:rotate(360deg)}}.rdv-footnote-highlight{animation:rdv-highlight-pulse 2s ease-out}@keyframes rdv-highlight-pulse{0%{background-color:var(--rdv-highlight-color);box-shadow:0 0 10px var(--rdv-highlight-color)}to{background-color:transparent;box-shadow:none}}.rdv-settings-overlay{position:fixed;inset:0;background:var(--rdv-modal-overlay);display:flex;align-items:center;justify-content:center;z-index:1000;padding:1rem}.rdv-settings-modal{background:var(--rdv-modal-bg);border-radius:var(--rdv-modal-radius);width:100%;max-width:500px;max-height:80vh;display:flex;flex-direction:column;box-shadow:var(--rdv-modal-shadow)}.rdv-settings-header{display:flex;align-items:center;justify-content:space-between;padding:1rem 1.5rem;border-bottom:1px solid var(--rdv-modal-border)}.rdv-settings-header h3{margin:0;font-size:1.25rem;color:var(--rdv-modal-title-color)}.rdv-settings-close{background:none;border:none;font-size:1.5rem;color:var(--rdv-modal-muted-color);cursor:pointer;padding:0;line-height:1}.rdv-settings-close:hover{color:var(--rdv-modal-title-color)}.rdv-settings-body{flex:1;overflow-y:auto;padding:1rem 1.5rem}.rdv-settings-section{margin-bottom:1.5rem}.rdv-settings-section:last-child{margin-bottom:0}.rdv-settings-section h4{margin:0 0 .75rem;font-size:.9rem;font-weight:600;color:#374151;text-transform:uppercase;letter-spacing:.5px}.rdv-settings-checkbox{display:flex;align-items:center;gap:.75rem;padding:.5rem 0;cursor:pointer}.rdv-settings-checkbox input{width:18px;height:18px;cursor:pointer}.rdv-settings-checkbox span{color:var(--rdv-modal-text-color);font-size:.95rem}.rdv-settings-radio-group{display:flex;flex-wrap:wrap;gap:.5rem}.rdv-settings-radio{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:var(--rdv-modal-section-bg);border-radius:6px;cursor:pointer;transition:background .2s}.rdv-settings-radio:hover{background:var(--rdv-modal-section-bg-hover)}.rdv-settings-radio input{cursor:pointer}.rdv-settings-radio span{font-size:.9rem;color:var(--rdv-modal-text-color)}.rdv-settings-subsection{margin-left:1.5rem;padding-left:1rem;border-left:2px solid var(--rdv-modal-border)}.rdv-settings-hint{margin:.25rem 0 .75rem;padding-left:1.75rem;font-size:.8rem;color:var(--rdv-modal-muted-color);line-height:1.4}.rdv-settings-input-label{display:flex;flex-direction:column;gap:.35rem;margin-top:.75rem}.rdv-settings-input-label span{font-size:.9rem;color:var(--rdv-modal-text-color)}.rdv-settings-text-input{padding:.5rem .75rem;border:1px solid var(--rdv-modal-input-border);border-radius:6px;font-size:.9rem;color:var(--rdv-modal-text-color);background:var(--rdv-modal-section-bg)}.rdv-settings-text-input:focus{outline:none;border-color:var(--rdv-modal-input-focus);box-shadow:0 0 0 2px #3b82f633}.rdv-settings-text-input::placeholder{color:var(--rdv-modal-muted-color)}.rdv-settings-toggle-advanced{background:none;border:none;color:var(--rdv-modal-muted-color);font-size:.9rem;cursor:pointer;padding:.5rem 0;display:flex;align-items:center;gap:.5rem}.rdv-settings-toggle-advanced:hover{color:#374151}.rdv-settings-advanced{margin-top:1rem;padding:1rem;background:var(--rdv-modal-advanced-bg);border-radius:8px}.rdv-settings-field{margin-bottom:1rem}.rdv-settings-field:last-child{margin-bottom:0}.rdv-settings-field label{display:block;font-size:.85rem;color:var(--rdv-modal-muted-color);margin-bottom:.25rem}.rdv-settings-field input,.rdv-settings-field textarea{width:100%;padding:.5rem;border:1px solid var(--rdv-modal-input-border);border-radius:6px;font-size:.9rem}.rdv-settings-field input:focus,.rdv-settings-field textarea:focus{outline:none;border-color:var(--rdv-modal-input-focus);box-shadow:0 0 0 2px #3b82f633}.rdv-settings-footer{padding:1rem 1.5rem;border-top:1px solid var(--rdv-modal-border);display:flex;justify-content:flex-end}.rdv-settings-apply{background:var(--rdv-modal-btn-bg);color:#fff;border:none;padding:.75rem 1.5rem;border-radius:6px;font-size:.95rem;font-weight:500;cursor:pointer;transition:background .2s}.rdv-settings-apply:hover{background:var(--rdv-modal-btn-bg-hover)}.rdv-view-tabs{display:flex;gap:2px;background:#0003;border-radius:var(--rdv-btn-radius);padding:2px}.rdv-view-tab{background:transparent;border:none;color:var(--rdv-btn-color);padding:.35rem .75rem;border-radius:calc(var(--rdv-btn-radius) - 2px);cursor:pointer;font-size:.8rem;font-weight:500;transition:background .2s,color .2s;white-space:nowrap}.rdv-view-tab:hover{background:#ffffff1a}.rdv-view-tab--active{background:var(--rdv-btn-bg);color:var(--rdv-btn-color)}.rdv-view-tab--active:hover{background:var(--rdv-btn-bg-hover)}.rdv-extracting-indicator{color:var(--rdv-input-muted);font-size:.8rem;animation:rdv-pulse 1.5s ease-in-out infinite}@keyframes rdv-pulse{0%,to{opacity:.4}50%{opacity:1}}.rdv-revision-panel{display:flex;flex-direction:column;flex:1;min-height:0;background:var(--rdv-background)}.rdv-revision-header{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.75rem 1rem;background:var(--rdv-toolbar-bg);border-bottom:1px solid var(--rdv-toolbar-border);flex-shrink:0}.rdv-revision-stats{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap}.rdv-revision-stat{font-size:.8rem;font-weight:500;padding:.2rem .5rem;border-radius:4px}.rdv-revision-stat--total{color:var(--rdv-btn-color);background:#ffffff1a}.rdv-revision-stat--insertion{color:#22c55e;background:#22c55e26}.rdv-revision-stat--deletion{color:#ef4444;background:#ef444426}.rdv-revision-stat--move{color:#3b82f6;background:#3b82f626}.rdv-revision-stat--format{color:#a855f7;background:#a855f726}.rdv-revision-filter{background:var(--rdv-btn-bg);border:none;color:var(--rdv-btn-color);padding:.4rem .75rem;border-radius:var(--rdv-btn-radius);font-size:.85rem;cursor:pointer}.rdv-revision-filter:focus{outline:none}.rdv-revision-list{flex:1;overflow-y:auto;min-height:0;padding:.75rem;display:flex;flex-direction:column;gap:.5rem;scroll-behavior:smooth}.rdv-revision-item{background:#f8fafc;border-radius:8px;padding:.75rem;border-left:3px solid #94a3b8}.rdv-revision-item.rdv-revision--insertion{border-left-color:#22c55e;background:linear-gradient(to right,#22c55e14,#f8fafc 50%)}.rdv-revision-item.rdv-revision--deletion{border-left-color:#ef4444;background:linear-gradient(to right,#ef444414,#f8fafc 50%)}.rdv-revision-item.rdv-revision--move{border-left-color:#3b82f6;background:linear-gradient(to right,#3b82f614,#f8fafc 50%)}.rdv-revision-item.rdv-revision--format{border-left-color:#a855f7;background:linear-gradient(to right,#a855f714,#f8fafc 50%)}.rdv-revision-item__header{display:flex;align-items:center;gap:.75rem;margin-bottom:.5rem;flex-wrap:wrap}.rdv-revision-type{font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.3px;padding:.15rem .5rem;border-radius:4px;background:#0000000f;color:#475569}.rdv-revision--insertion .rdv-revision-type{background:#22c55e26;color:#15803d}.rdv-revision--deletion .rdv-revision-type{background:#ef444426;color:#dc2626}.rdv-revision--move .rdv-revision-type{background:#3b82f626;color:#2563eb}.rdv-revision--format .rdv-revision-type{background:#a855f726;color:#9333ea}.rdv-revision-author{font-size:.85rem;font-weight:500;color:#334155}.rdv-revision-date{font-size:.75rem;color:#64748b;margin-left:auto}.rdv-revision-item__content{display:flex;flex-direction:column;gap:.25rem}.rdv-revision-text{font-size:.9rem;color:#1e293b;line-height:1.5;word-break:break-word}.rdv-revision--deletion .rdv-revision-text{text-decoration:line-through;color:#94a3b8}.rdv-revision-expand{background:none;border:none;color:#3b82f6;font-size:.8rem;cursor:pointer;padding:0;margin-top:.25rem;align-self:flex-start}.rdv-revision-expand:hover{text-decoration:underline}.rdv-revision-item__format-details{display:flex;flex-direction:column;gap:.375rem;margin-top:.625rem;padding-top:.625rem;border-top:1px dashed #e2e8f0}.rdv-format-change{display:flex;align-items:center;gap:.5rem;font-size:.8rem}.rdv-format-change__property{color:#64748b;font-weight:500;min-width:80px}.rdv-format-change__values{display:flex;align-items:center;gap:.375rem}.rdv-format-change__old{color:#ef4444;background:#ef44441a;padding:.1rem .4rem;border-radius:3px;text-decoration:line-through}.rdv-format-change__arrow{color:#94a3b8;font-size:.75rem}.rdv-format-change__new{color:#22c55e;background:#22c55e1a;padding:.1rem .4rem;border-radius:3px}.rdv-format-change__added,.rdv-format-change__removed{font-size:.7rem;color:#94a3b8;font-style:italic}.rdv-revision-move-id{font-size:.7rem;color:#3b82f6;background:#3b82f61a;padding:.1rem .35rem;border-radius:3px;font-family:monospace}.rdv-revision-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;min-height:300px;color:var(--rdv-message-color);text-align:center;padding:2rem}.rdv-revision-empty__icon{font-size:4rem;margin-bottom:1rem;opacity:.5}.rdv-revision-empty p{margin:.5rem 0;font-size:1rem;color:#64748b}@media(max-width:768px){.rdv-toolbar{flex-wrap:wrap;gap:.5rem}.rdv-toolbar-right{flex-wrap:wrap;row-gap:.5rem}.rdv-toolbar-filename{display:none}.rdv-zoom-select{flex-shrink:1;min-width:0}.rdv-revision-header{flex-direction:column;align-items:flex-start}.rdv-revision-filter{width:100%}}.rdv-pages--loading{flex:1;overflow:auto;min-height:0;scroll-behavior:smooth}.rdv-page-placeholders{display:flex;flex-direction:column;align-items:center;padding:20px;min-height:100%}.rdv-page-placeholder{position:relative;background:#fff;border-radius:2px;box-shadow:0 2px 8px #00000026;overflow:hidden;margin-bottom:var(--rdv-page-gap)}.rdv-page-placeholder:last-child{margin-bottom:0}.rdv-page-placeholder__shimmer{position:absolute;inset:0;background:linear-gradient(90deg,#fff0,#fff6,#fff0);animation:rdv-shimmer 1.5s ease-in-out infinite;background-size:200% 100%}@keyframes rdv-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.rdv-page-placeholder__info{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;flex-direction:column;align-items:center;gap:.75rem;color:#64748b;font-size:.9rem;text-align:center;background:#fffffff2;padding:1.5rem 2rem;border-radius:8px;box-shadow:0 2px 8px #0000001a}.rdv-page-placeholder__count{font-size:.8rem;color:#94a3b8}.rdv-page-placeholder__number{position:absolute;bottom:12px;left:50%;transform:translate(-50%);font-size:.75rem;color:#94a3b8;background:#ffffffe6;padding:2px 8px;border-radius:4px}.rdv-spinner--small{width:24px;height:24px;border-width:3px}
|
|
1
|
+
.rdv-viewer{--rdv-border-radius:8px;--rdv-background:#525659;--rdv-min-height:400px;--rdv-height:80vh;--rdv-max-height:90vh;--rdv-shadow:0 4px 20px #00000026;--rdv-stable-width:auto;--rdv-stable-height:auto;--rdv-page-gap:20px;--rdv-toolbar-bg:#323639;--rdv-toolbar-border:#1a1a1a;--rdv-toolbar-height:auto;--rdv-toolbar-padding:.5rem 1rem;--rdv-btn-bg:#474c50;--rdv-btn-bg-hover:#5a6066;--rdv-btn-color:#d4d4d4;--rdv-btn-radius:4px;--rdv-btn-disabled-opacity:.4;--rdv-input-bg:#474c50;--rdv-input-color:#d4d4d4;--rdv-input-muted:#9ca3af;--rdv-separator-color:#555;--rdv-message-color:#9ca3af;--rdv-error-color:#ef4444;--rdv-highlight-color:#fef08a;--rdv-modal-overlay:#0009;--rdv-modal-bg:white;--rdv-modal-radius:12px;--rdv-modal-shadow:0 20px 60px #0000004d;--rdv-modal-border:#e5e7eb;--rdv-modal-title-color:#1f2937;--rdv-modal-text-color:#4b5563;--rdv-modal-muted-color:#6b7280;--rdv-modal-section-bg:#f3f4f6;--rdv-modal-section-bg-hover:#e5e7eb;--rdv-modal-advanced-bg:#f9fafb;--rdv-modal-input-border:#d1d5db;--rdv-modal-input-focus:#3b82f6;--rdv-modal-btn-bg:#3b82f6;--rdv-modal-btn-bg-hover:#2563eb;height:var(--rdv-height);min-height:var(--rdv-min-height);max-height:var(--rdv-max-height);border-radius:var(--rdv-border-radius);background:var(--rdv-background);box-shadow:var(--rdv-shadow);flex-direction:column;display:flex;overflow:hidden}.rdv-viewer del,.rdv-viewer [data-revision-type=deleted],.rdv-viewer [data-move-source=true]{-webkit-user-select:none;user-select:none}.rdv-toolbar{padding:var(--rdv-toolbar-padding);background:var(--rdv-toolbar-bg);border-bottom:1px solid var(--rdv-toolbar-border);flex-shrink:0;justify-content:space-between;align-items:center;display:flex}.rdv-toolbar-left,.rdv-toolbar-right{align-items:center;gap:.375rem;display:flex}.rdv-toolbar-btn{background:var(--rdv-btn-bg);color:var(--rdv-btn-color);border-radius:var(--rdv-btn-radius);cursor:pointer;border:none;min-width:32px;padding:.4rem .7rem;font-size:.9rem;font-weight:700;transition:background .2s,color .2s}.rdv-toolbar-btn:hover:not(:disabled){background:var(--rdv-btn-bg-hover)}.rdv-toolbar-btn:disabled{opacity:var(--rdv-btn-disabled-opacity);cursor:not-allowed}.rdv-toolbar-icon-btn{justify-content:center;align-items:center;width:32px;min-width:32px;height:32px;padding:0;line-height:1;display:inline-flex}.rdv-toolbar-icon-btn svg{display:block}.rdv-toolbar-icon-btn--primary{background:var(--rdv-btn-primary-bg,#3b82f6);color:var(--rdv-btn-primary-color,#fff)}.rdv-toolbar-icon-btn--primary:hover:not(:disabled){background:var(--rdv-btn-primary-bg-hover,#2563eb)}.rdv-toolbar-open-btn{cursor:pointer}.rdv-toolbar-filename{color:var(--rdv-btn-color);text-overflow:ellipsis;white-space:nowrap;opacity:.85;max-width:180px;font-size:.8rem;overflow:hidden}.rdv-toolbar-clear{font-size:1.15rem}.rdv-toolbar-settings{font-size:1.05rem}.rdv-page-input-group{background:var(--rdv-input-bg);border-radius:var(--rdv-btn-radius);align-items:center;gap:.25rem;padding:0 .5rem;display:flex}.rdv-page-input{width:50px;color:var(--rdv-input-color);text-align:center;-moz-appearance:textfield;background:0 0;border:none;padding:.4rem 0;font-size:.9rem}.rdv-page-input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.rdv-page-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.rdv-page-input:focus{outline:none}.rdv-page-total{color:var(--rdv-input-muted);font-size:.9rem}.rdv-toolbar-separator{background:var(--rdv-separator-color);width:1px;height:24px;margin:0 .25rem}.rdv-zoom-group{background:var(--rdv-btn-bg);border-radius:var(--rdv-btn-radius);align-items:center;display:flex;overflow:hidden}.rdv-zoom-group .rdv-zoom-btn{background:0 0;border-radius:0;width:28px;min-width:28px;height:30px}.rdv-zoom-group .rdv-zoom-btn:hover:not(:disabled){background:var(--rdv-btn-bg-hover)}.rdv-zoom-select{color:var(--rdv-btn-color);cursor:pointer;appearance:none;text-align:center;text-align-last:center;background:0 0;border:none;border-radius:0;padding:.3rem .5rem .3rem .35rem;font-size:.85rem}.rdv-zoom-select:focus{outline:none}.rdv-zoom-select:hover{background:var(--rdv-btn-bg-hover)}.rdv-file-input{display:none}.rdv-content{contain:strict;flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.rdv-pages{scroll-behavior:smooth;contain:layout style;min-height:0;width:var(--rdv-stable-width,100%);flex:1;max-width:100%;overflow:auto}.rdv-pages__stable-wrapper{flex-direction:column;align-items:center;min-height:100%;display:flex}.rdv-paginated-document{color:#000;-webkit-text-fill-color:initial;min-height:100%}.rdv-paginated-document *{-webkit-text-fill-color:inherit}.rdv-message{height:100%;min-height:300px;color:var(--rdv-message-color);text-align:center;flex-direction:column;justify-content:center;align-items:center;padding:2rem;display:flex}.rdv-message--error{color:var(--rdv-error-color)}.rdv-message__icon{opacity:.5;margin-bottom:1rem;font-size:4rem}.rdv-message p{margin:.5rem 0;font-size:1rem}.rdv-spinner{border:4px solid #fff3;border-top-color:var(--rdv-btn-color);border-radius:50%;width:40px;height:40px;animation:1s linear infinite rdv-spin}@keyframes rdv-spin{to{transform:rotate(360deg)}}.rdv-footnote-highlight{animation:2s ease-out rdv-highlight-pulse}@keyframes rdv-highlight-pulse{0%{background-color:var(--rdv-highlight-color);box-shadow:0 0 10px var(--rdv-highlight-color)}to{box-shadow:none;background-color:#0000}}.rdv-settings-overlay{background:var(--rdv-modal-overlay);z-index:1000;justify-content:center;align-items:center;padding:1rem;display:flex;position:fixed;inset:0}.rdv-settings-modal{background:var(--rdv-modal-bg);border-radius:var(--rdv-modal-radius);width:100%;max-width:500px;max-height:80vh;box-shadow:var(--rdv-modal-shadow);flex-direction:column;display:flex}.rdv-settings-header{border-bottom:1px solid var(--rdv-modal-border);justify-content:space-between;align-items:center;padding:1rem 1.5rem;display:flex}.rdv-settings-header h3{color:var(--rdv-modal-title-color);margin:0;font-size:1.25rem}.rdv-settings-close{color:var(--rdv-modal-muted-color);cursor:pointer;background:0 0;border:none;padding:0;font-size:1.5rem;line-height:1}.rdv-settings-close:hover{color:var(--rdv-modal-title-color)}.rdv-settings-body{flex:1;padding:1rem 1.5rem;overflow-y:auto}.rdv-settings-section{margin-bottom:1.5rem}.rdv-settings-section:last-child{margin-bottom:0}.rdv-settings-section h4{color:#374151;text-transform:uppercase;letter-spacing:.5px;margin:0 0 .75rem;font-size:.9rem;font-weight:600}.rdv-settings-checkbox{cursor:pointer;align-items:center;gap:.75rem;padding:.5rem 0;display:flex}.rdv-settings-checkbox input{cursor:pointer;width:18px;height:18px}.rdv-settings-checkbox span{color:var(--rdv-modal-text-color);font-size:.95rem}.rdv-settings-radio-group{flex-wrap:wrap;gap:.5rem;display:flex}.rdv-settings-radio{background:var(--rdv-modal-section-bg);cursor:pointer;border-radius:6px;align-items:center;gap:.5rem;padding:.5rem .75rem;transition:background .2s;display:flex}.rdv-settings-radio:hover{background:var(--rdv-modal-section-bg-hover)}.rdv-settings-radio input{cursor:pointer}.rdv-settings-radio span{color:var(--rdv-modal-text-color);font-size:.9rem}.rdv-settings-subsection{border-left:2px solid var(--rdv-modal-border);margin-left:1.5rem;padding-left:1rem}.rdv-settings-hint{color:var(--rdv-modal-muted-color);margin:.25rem 0 .75rem;padding-left:1.75rem;font-size:.8rem;line-height:1.4}.rdv-settings-input-label{flex-direction:column;gap:.35rem;margin-top:.75rem;display:flex}.rdv-settings-input-label span{color:var(--rdv-modal-text-color);font-size:.9rem}.rdv-settings-text-input{border:1px solid var(--rdv-modal-input-border);color:var(--rdv-modal-text-color);background:var(--rdv-modal-section-bg);border-radius:6px;padding:.5rem .75rem;font-size:.9rem}.rdv-settings-text-input:focus{border-color:var(--rdv-modal-input-focus);outline:none;box-shadow:0 0 0 2px #3b82f633}.rdv-settings-text-input::placeholder{color:var(--rdv-modal-muted-color)}.rdv-settings-toggle-advanced{color:var(--rdv-modal-muted-color);cursor:pointer;background:0 0;border:none;align-items:center;gap:.5rem;padding:.5rem 0;font-size:.9rem;display:flex}.rdv-settings-toggle-advanced:hover{color:#374151}.rdv-settings-advanced{background:var(--rdv-modal-advanced-bg);border-radius:8px;margin-top:1rem;padding:1rem}.rdv-settings-field{margin-bottom:1rem}.rdv-settings-field:last-child{margin-bottom:0}.rdv-settings-field label{color:var(--rdv-modal-muted-color);margin-bottom:.25rem;font-size:.85rem;display:block}.rdv-settings-field input,.rdv-settings-field textarea{border:1px solid var(--rdv-modal-input-border);border-radius:6px;width:100%;padding:.5rem;font-size:.9rem}.rdv-settings-field input:focus,.rdv-settings-field textarea:focus{border-color:var(--rdv-modal-input-focus);outline:none;box-shadow:0 0 0 2px #3b82f633}.rdv-settings-footer{border-top:1px solid var(--rdv-modal-border);justify-content:flex-end;padding:1rem 1.5rem;display:flex}.rdv-settings-apply{background:var(--rdv-modal-btn-bg);color:#fff;cursor:pointer;border:none;border-radius:6px;padding:.75rem 1.5rem;font-size:.95rem;font-weight:500;transition:background .2s}.rdv-settings-apply:hover{background:var(--rdv-modal-btn-bg-hover)}.rdv-view-tabs{border-radius:var(--rdv-btn-radius);background:#0003;gap:2px;padding:2px;display:flex}.rdv-view-tab{color:var(--rdv-btn-color);border-radius:calc(var(--rdv-btn-radius) - 2px);cursor:pointer;white-space:nowrap;background:0 0;border:none;padding:.35rem .75rem;font-size:.8rem;font-weight:500;transition:background .2s,color .2s}.rdv-view-tab:hover{background:#ffffff1a}.rdv-view-tab--active{background:var(--rdv-btn-bg);color:var(--rdv-btn-color)}.rdv-view-tab--active:hover{background:var(--rdv-btn-bg-hover)}.rdv-extracting-indicator{color:var(--rdv-input-muted);font-size:.8rem;animation:1.5s ease-in-out infinite rdv-pulse}@keyframes rdv-pulse{0%,to{opacity:.4}50%{opacity:1}}.rdv-revision-panel{background:var(--rdv-background);flex-direction:column;flex:1;min-height:0;display:flex}.rdv-revision-header{background:var(--rdv-toolbar-bg);border-bottom:1px solid var(--rdv-toolbar-border);flex-shrink:0;justify-content:space-between;align-items:center;gap:1rem;padding:.75rem 1rem;display:flex}.rdv-revision-stats{flex-wrap:wrap;align-items:center;gap:.75rem;display:flex}.rdv-revision-stat{border-radius:4px;padding:.2rem .5rem;font-size:.8rem;font-weight:500}.rdv-revision-stat--total{color:var(--rdv-btn-color);background:#ffffff1a}.rdv-revision-stat--insertion{color:#22c55e;background:#22c55e26}.rdv-revision-stat--deletion{color:#ef4444;background:#ef444426}.rdv-revision-stat--move{color:#3b82f6;background:#3b82f626}.rdv-revision-stat--format{color:#a855f7;background:#a855f726}.rdv-revision-filter{background:var(--rdv-btn-bg);color:var(--rdv-btn-color);border-radius:var(--rdv-btn-radius);cursor:pointer;border:none;padding:.4rem .75rem;font-size:.85rem}.rdv-revision-filter:focus{outline:none}.rdv-revision-list{scroll-behavior:smooth;flex-direction:column;flex:1;gap:.5rem;min-height:0;padding:.75rem;display:flex;overflow-y:auto}.rdv-revision-item{background:#f8fafc;border-left:3px solid #94a3b8;border-radius:8px;padding:.75rem}.rdv-revision-item.rdv-revision--insertion{background:linear-gradient(90deg,#22c55e14,#f8fafc 50%);border-left-color:#22c55e}.rdv-revision-item.rdv-revision--deletion{background:linear-gradient(90deg,#ef444414,#f8fafc 50%);border-left-color:#ef4444}.rdv-revision-item.rdv-revision--move{background:linear-gradient(90deg,#3b82f614,#f8fafc 50%);border-left-color:#3b82f6}.rdv-revision-item.rdv-revision--format{background:linear-gradient(90deg,#a855f714,#f8fafc 50%);border-left-color:#a855f7}.rdv-revision-item__header{flex-wrap:wrap;align-items:center;gap:.75rem;margin-bottom:.5rem;display:flex}.rdv-revision-type{text-transform:uppercase;letter-spacing:.3px;color:#475569;background:#0000000f;border-radius:4px;padding:.15rem .5rem;font-size:.75rem;font-weight:600}.rdv-revision--insertion .rdv-revision-type{color:#15803d;background:#22c55e26}.rdv-revision--deletion .rdv-revision-type{color:#dc2626;background:#ef444426}.rdv-revision--move .rdv-revision-type{color:#2563eb;background:#3b82f626}.rdv-revision--format .rdv-revision-type{color:#9333ea;background:#a855f726}.rdv-revision-author{color:#334155;font-size:.85rem;font-weight:500}.rdv-revision-date{color:#64748b;margin-left:auto;font-size:.75rem}.rdv-revision-item__content{flex-direction:column;gap:.25rem;display:flex}.rdv-revision-text{color:#1e293b;word-break:break-word;font-size:.9rem;line-height:1.5}.rdv-revision--deletion .rdv-revision-text{color:#94a3b8;text-decoration:line-through}.rdv-revision-expand{color:#3b82f6;cursor:pointer;background:0 0;border:none;align-self:flex-start;margin-top:.25rem;padding:0;font-size:.8rem}.rdv-revision-expand:hover{text-decoration:underline}.rdv-revision-item__format-details{border-top:1px dashed #e2e8f0;flex-direction:column;gap:.375rem;margin-top:.625rem;padding-top:.625rem;display:flex}.rdv-format-change{align-items:center;gap:.5rem;font-size:.8rem;display:flex}.rdv-format-change__property{color:#64748b;min-width:80px;font-weight:500}.rdv-format-change__values{align-items:center;gap:.375rem;display:flex}.rdv-format-change__old{color:#ef4444;background:#ef44441a;border-radius:3px;padding:.1rem .4rem;text-decoration:line-through}.rdv-format-change__arrow{color:#94a3b8;font-size:.75rem}.rdv-format-change__new{color:#22c55e;background:#22c55e1a;border-radius:3px;padding:.1rem .4rem}.rdv-format-change__added,.rdv-format-change__removed{color:#94a3b8;font-size:.7rem;font-style:italic}.rdv-revision-move-id{color:#3b82f6;background:#3b82f61a;border-radius:3px;padding:.1rem .35rem;font-family:monospace;font-size:.7rem}.rdv-revision-empty{height:100%;min-height:300px;color:var(--rdv-message-color);text-align:center;flex-direction:column;justify-content:center;align-items:center;padding:2rem;display:flex}.rdv-revision-empty__icon{opacity:.5;margin-bottom:1rem;font-size:4rem}.rdv-revision-empty p{color:#64748b;margin:.5rem 0;font-size:1rem}@media (width<=768px){.rdv-toolbar{flex-wrap:wrap;gap:.5rem}.rdv-toolbar-right{flex-wrap:wrap;row-gap:.5rem}.rdv-toolbar-filename{display:none}.rdv-zoom-select{flex-shrink:1;min-width:0}.rdv-revision-header{flex-direction:column;align-items:flex-start}.rdv-revision-filter{width:100%}}.rdv-pages--loading{scroll-behavior:smooth;flex:1;min-height:0;overflow:auto}.rdv-page-placeholders{flex-direction:column;align-items:center;min-height:100%;padding:20px;display:flex}.rdv-page-placeholder{margin-bottom:var(--rdv-page-gap);background:#fff;border-radius:2px;position:relative;overflow:hidden;box-shadow:0 2px 8px #00000026}.rdv-page-placeholder:last-child{margin-bottom:0}.rdv-page-placeholder__shimmer{background:linear-gradient(90deg,#fff0 0%,#fff6 50%,#fff0 100%) 0 0/200% 100%;animation:1.5s ease-in-out infinite rdv-shimmer;position:absolute;inset:0}@keyframes rdv-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.rdv-page-placeholder__info{color:#64748b;text-align:center;background:#fffffff2;border-radius:8px;flex-direction:column;align-items:center;gap:.75rem;padding:1.5rem 2rem;font-size:.9rem;display:flex;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);box-shadow:0 2px 8px #0000001a}.rdv-page-placeholder__count{color:#94a3b8;font-size:.8rem}.rdv-page-placeholder__number{color:#94a3b8;background:#ffffffe6;border-radius:4px;padding:2px 8px;font-size:.75rem;position:absolute;bottom:12px;left:50%;transform:translate(-50%)}.rdv-spinner--small{border-width:3px;width:24px;height:24px}
|
|
2
|
+
/*$vite$:1*/
|