react-docxodus-viewer 0.1.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 ADDED
@@ -0,0 +1,193 @@
1
+ # Docxodus Viewer
2
+
3
+ A client-side DOCX document viewer and comparison tool built with React. All document processing happens entirely in your browser using WebAssembly - no files are uploaded to any server.
4
+
5
+ **[Live Demo](https://jsv4.github.io/Docxodus-Viewer/)** | **[Docxodus Engine](https://github.com/JSv4/Docxodus)**
6
+
7
+ ## Features
8
+
9
+ ### Document Viewer
10
+ - Convert DOCX files to HTML for viewing in the browser
11
+ - **Comment rendering** with multiple display modes:
12
+ - **Disabled** - Hide all comments
13
+ - **Endnotes** - Comments appear at the end with numbered references
14
+ - **Inline** - Comments shown as tooltips on hover
15
+ - **Margin** - Comments displayed in a side column
16
+ - **Advanced options** (collapsible panel):
17
+ - Page title, CSS prefix, comment CSS prefix
18
+ - Fabricate CSS classes toggle
19
+ - Custom additional CSS
20
+
21
+ ### Document Comparison
22
+ - Compare two DOCX files and generate a redlined document with tracked changes
23
+ - Visual diff with insertions (green), deletions (red), and moves (purple) highlighted
24
+ - **Configurable comparison options:**
25
+ - **Detail Level** - Control comparison granularity (lower = more detailed)
26
+ - **Case-insensitive** - Ignore case differences when comparing
27
+ - **Author name** - Set the author for tracked changes
28
+ - **Show tracked changes** - Toggle visibility of changes in preview
29
+ - Download the comparison result as a DOCX file with tracked changes
30
+
31
+ ### Revision Extraction
32
+ - Extract structured revision data from documents with tracked changes
33
+ - View revision details: type, author, date, and changed text
34
+ - Summary statistics for insertions, deletions, and moves
35
+ - **Move detection options** (collapsible panel):
36
+ - Enable/disable move detection
37
+ - Similarity threshold (50-100%)
38
+ - Minimum word count filter
39
+ - Case-insensitive matching
40
+ - Move pair linking with group badges
41
+
42
+ ## Technology
43
+
44
+ - **React 19** with TypeScript
45
+ - **Vite** for fast development and optimized builds
46
+ - **[Docxodus](https://github.com/docxodus/docxodus)** - WebAssembly-powered DOCX processing engine
47
+
48
+ ## Privacy
49
+
50
+ All document processing happens locally in your browser. Your files never leave your device - there's no server-side processing, no uploads, and no data collection.
51
+
52
+ ## Getting Started
53
+
54
+ ### Prerequisites
55
+
56
+ - Node.js 18+
57
+ - npm or yarn
58
+
59
+ ### Installation
60
+
61
+ ```bash
62
+ # Clone the repository
63
+ git clone https://github.com/JSv4/Docxodus-Viewer.git
64
+ cd Docxodus-Viewer
65
+
66
+ # Install dependencies
67
+ npm install
68
+
69
+ # Start development server
70
+ npm run dev
71
+ ```
72
+
73
+ The app will be available at `http://localhost:5173`
74
+
75
+ ### Building for Production
76
+
77
+ ```bash
78
+ npm run build
79
+ ```
80
+
81
+ The built files will be in the `dist/` directory.
82
+
83
+ ### Updating Docxodus
84
+
85
+ When upgrading the docxodus package, you must also update the WASM files in the `public/` directory:
86
+
87
+ ```bash
88
+ # 1. Update the package
89
+ npm install docxodus@latest
90
+
91
+ # 2. Copy WASM files to public directory
92
+ rm -rf public/wasm && cp -r node_modules/docxodus/dist/wasm public/wasm
93
+
94
+ # 3. Rebuild
95
+ npm run build
96
+ ```
97
+
98
+ The WASM files in `public/wasm/` are served statically and must match the installed package version.
99
+
100
+ ## Deployment
101
+
102
+ ### GitHub Pages
103
+
104
+ This repository includes a GitHub Actions workflow that automatically builds and deploys to GitHub Pages on push to `main`.
105
+
106
+ To enable:
107
+ 1. Go to your repository Settings > Pages
108
+ 2. Set Source to "GitHub Actions"
109
+ 3. Push to `main` branch
110
+
111
+ **Important:** GitHub Pages doesn't support custom HTTP headers. The required COOP/COEP headers for SharedArrayBuffer are injected via a service worker. This is handled automatically by the build.
112
+
113
+ ### Netlify
114
+
115
+ Add a `netlify.toml` to your repo root:
116
+
117
+ ```toml
118
+ [[headers]]
119
+ for = "/*"
120
+ [headers.values]
121
+ Cross-Origin-Opener-Policy = "same-origin"
122
+ Cross-Origin-Embedder-Policy = "require-corp"
123
+ ```
124
+
125
+ ### Vercel
126
+
127
+ Add a `vercel.json` to your repo root:
128
+
129
+ ```json
130
+ {
131
+ "headers": [
132
+ {
133
+ "source": "/(.*)",
134
+ "headers": [
135
+ { "key": "Cross-Origin-Opener-Policy", "value": "same-origin" },
136
+ { "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" }
137
+ ]
138
+ }
139
+ ]
140
+ }
141
+ ```
142
+
143
+ ### Other Platforms
144
+
145
+ The app requires specific CORS headers for the .NET WebAssembly runtime:
146
+
147
+ ```
148
+ Cross-Origin-Opener-Policy: same-origin
149
+ Cross-Origin-Embedder-Policy: require-corp
150
+ ```
151
+
152
+ Ensure your hosting platform sets these headers. Platforms like Netlify and Vercel support custom headers via configuration files.
153
+
154
+ ## Project Structure
155
+
156
+ ```
157
+ src/
158
+ ├── App.tsx # Main app with tab navigation
159
+ ├── App.css # Application styles
160
+ ├── components/
161
+ │ ├── DocumentViewer.tsx # DOCX to HTML conversion
162
+ │ ├── DocumentComparer.tsx # Two-document comparison
163
+ │ └── RevisionViewer.tsx # Revision extraction
164
+ └── main.tsx # Entry point
165
+ ```
166
+
167
+ ## Docxodus Library
168
+
169
+ This viewer is powered by [Docxodus](https://github.com/docxodus/docxodus), a WebAssembly library for DOCX processing. For more information about the underlying engine, including:
170
+
171
+ - API documentation
172
+ - Comment rendering architecture
173
+ - Comparison algorithm details
174
+ - Bundle size and browser support
175
+
176
+ Visit the [Docxodus repository](https://github.com/JSv4/Docxodus).
177
+
178
+ ## Browser Support
179
+
180
+ - Chrome 89+
181
+ - Firefox 89+
182
+ - Safari 15+
183
+ - Edge 89+
184
+
185
+ Requires WebAssembly SIMD support.
186
+
187
+ ## License
188
+
189
+ MIT
190
+
191
+ ## Contributing
192
+
193
+ Contributions are welcome! Please feel free to submit a Pull Request.
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),a=require("react"),J=require("docxodus/react"),d=require("docxodus"),K={paginationScale:.8,showPageNumbers:!0,renderFootnotesAndEndnotes:!0,renderHeadersAndFooters:!0,commentMode:"disabled",annotationMode:"disabled",renderTrackedChanges:!1,showDeletedContent:!0,renderMoveOperations:!0,pageTitle:"Document",cssPrefix:"docx-",fabricateClasses:!0,additionalCss:"",commentCssClassPrefix:"comment-",annotationCssClassPrefix:"annot-"},be="/wasm/";function je(l){switch(l){case"endnote":return d.CommentRenderMode.EndnoteStyle;case"inline":return d.CommentRenderMode.Inline;case"margin":return d.CommentRenderMode.Margin;default:return d.CommentRenderMode.Disabled}}function fe(l){switch(l){case"above":return d.AnnotationLabelMode.Above;case"inline":return d.AnnotationLabelMode.Inline;case"tooltip":return d.AnnotationLabelMode.Tooltip;case"none":return d.AnnotationLabelMode.None;default:return}}function Ce({file:l,html:i,onFileChange:E,onConversionStart:D,onConversionComplete:F,onError:L,onPageChange:M,settings:v,defaultSettings:I,onSettingsChange:O,className:Q,style:Y,toolbar:R="top",showSettingsButton:ee=!0,placeholder:ne="Open a DOCX file to view",wasmBasePath:se=be}){const S=a.useMemo(()=>({...K,...I}),[I]),[te,q]=a.useState(null),[ae,j]=a.useState(null),[V,oe]=a.useState(S),h=l!==void 0?l:te,u=i!==void 0?i:ae,s=a.useMemo(()=>v?{...S,...v}:V,[v,S,V]),{isReady:x,isLoading:p,error:f,convertToHtml:_}=J.useDocxodus(se),[m,U]=a.useState(!1),[Z,C]=a.useState(null),[$,G]=a.useState(""),[c,P]=a.useState(1),[r,w]=a.useState(0),[ie,N]=a.useState(!1),A=a.useRef(null),z=a.useCallback(()=>({commentRenderMode:je(s.commentMode),pageTitle:s.pageTitle,cssPrefix:s.cssPrefix,fabricateClasses:s.fabricateClasses,additionalCss:s.additionalCss||void 0,commentCssClassPrefix:s.commentCssClassPrefix,paginationMode:d.PaginationMode.Paginated,paginationScale:s.paginationScale,renderAnnotations:s.annotationMode!=="disabled",annotationLabelMode:fe(s.annotationMode),annotationCssClassPrefix:s.annotationCssClassPrefix,renderFootnotesAndEndnotes:s.renderFootnotesAndEndnotes,renderHeadersAndFooters:s.renderHeadersAndFooters,renderTrackedChanges:s.renderTrackedChanges,showDeletedContent:s.showDeletedContent,renderMoveOperations:s.renderMoveOperations}),[s]),b=a.useCallback(async n=>{if(x){U(!0),C(null),D?.(),await new Promise(t=>requestAnimationFrame(()=>requestAnimationFrame(t)));try{const t=await _(n,z());i===void 0&&j(t),F?.(t)}catch(t){const g=t instanceof Error?t:new Error(String(t));C(g),L?.(g)}finally{U(!1)}}},[x,_,z,i,D,F,L]);a.useEffect(()=>{x&&h&&!u&&!m&&i===void 0&&b(h)},[x,h,u,m,b,i]);const re=async n=>{const t=n.target.files?.[0];t&&(G(t.name),C(null),P(1),w(0),l===void 0&&(q(t),j(null)),E?.(t),x&&i===void 0&&await b(t))},ce=a.useCallback(async()=>{h&&(i===void 0&&j(null),await b(h))},[h,b,i]),de=()=>{l===void 0&&q(null),i===void 0&&j(null),C(null),G(""),P(1),w(0),E?.(null);const n=document.getElementById("rdv-file-input");n&&(n.value="")},o=a.useCallback(n=>{const t={...s,...n};v===void 0&&oe(t),O?.(t)},[s,v,O]),le=()=>o({paginationScale:Math.min(s.paginationScale+.1,2)}),he=()=>o({paginationScale:Math.max(s.paginationScale-.1,.3)}),ge=n=>o({paginationScale:Math.max(.3,Math.min(2,n))}),y=n=>{const t=A.current;if(!t||n<1||n>r)return;const g=t.querySelector(`[data-page-number="${n}"]`);g&&g.scrollIntoView({behavior:"smooth",block:"start"})},ue=()=>c>1&&y(c-1),me=()=>c<r&&y(c+1),ve=n=>{P(n),M?.(n,r)};a.useEffect(()=>{const n=A.current;if(!n)return;const t=g=>{const H=g.target.closest('a[href^="#"]');if(!H)return;const T=H.getAttribute("href");if(!T||!T.startsWith("#"))return;g.preventDefault();const X=T.substring(1),k=n.querySelector(`[id="${X}"], [name="${X}"]`);k&&(k.scrollIntoView({behavior:"smooth",block:"center"}),k.classList.add("rdv-footnote-highlight"),setTimeout(()=>k.classList.remove("rdv-footnote-highlight"),2e3))};return n.addEventListener("click",t),()=>n.removeEventListener("click",t)},[u]),a.useEffect(()=>{r>0&&M?.(c,r)},[r,c,M]);const B=m||p,xe=()=>e.jsx("div",{className:"rdv-settings-overlay",onClick:()=>N(!1),children:e.jsxs("div",{className:"rdv-settings-modal",onClick:n=>n.stopPropagation(),children:[e.jsxs("div",{className:"rdv-settings-header",children:[e.jsx("h3",{children:"Viewer Settings"}),e.jsx("button",{className:"rdv-settings-close",onClick:()=>N(!1),children:"×"})]}),e.jsxs("div",{className:"rdv-settings-body",children:[e.jsxs("div",{className:"rdv-settings-section",children:[e.jsx("h4",{children:"Display Options"}),e.jsxs("label",{className:"rdv-settings-checkbox",children:[e.jsx("input",{type:"checkbox",checked:s.renderFootnotesAndEndnotes,onChange:n=>o({renderFootnotesAndEndnotes:n.target.checked})}),e.jsx("span",{children:"Show footnotes and endnotes"})]}),e.jsxs("label",{className:"rdv-settings-checkbox",children:[e.jsx("input",{type:"checkbox",checked:s.renderHeadersAndFooters,onChange:n=>o({renderHeadersAndFooters:n.target.checked})}),e.jsx("span",{children:"Show headers and footers"})]}),e.jsxs("label",{className:"rdv-settings-checkbox",children:[e.jsx("input",{type:"checkbox",checked:s.showPageNumbers,onChange:n=>o({showPageNumbers:n.target.checked})}),e.jsx("span",{children:"Show page numbers"})]})]}),e.jsxs("div",{className:"rdv-settings-section",children:[e.jsx("h4",{children:"Comment Rendering"}),e.jsx("div",{className:"rdv-settings-radio-group",children:["disabled","endnote","inline","margin"].map(n=>e.jsxs("label",{className:"rdv-settings-radio",children:[e.jsx("input",{type:"radio",name:"commentMode",checked:s.commentMode===n,onChange:()=>o({commentMode:n})}),e.jsxs("span",{children:[n.charAt(0).toUpperCase()+n.slice(1),n==="endnote"?"s":""]})]},n))})]}),e.jsxs("div",{className:"rdv-settings-section",children:[e.jsx("h4",{children:"Annotation Rendering"}),e.jsx("div",{className:"rdv-settings-radio-group",children:["disabled","above","inline","tooltip","none"].map(n=>e.jsxs("label",{className:"rdv-settings-radio",children:[e.jsx("input",{type:"radio",name:"annotationMode",checked:s.annotationMode===n,onChange:()=>o({annotationMode:n})}),e.jsx("span",{children:n==="none"?"Highlight Only":n.charAt(0).toUpperCase()+n.slice(1)})]},n))})]}),e.jsxs("div",{className:"rdv-settings-section",children:[e.jsx("h4",{children:"Tracked Changes"}),e.jsxs("label",{className:"rdv-settings-checkbox",children:[e.jsx("input",{type:"checkbox",checked:s.renderTrackedChanges,onChange:n=>o({renderTrackedChanges:n.target.checked})}),e.jsx("span",{children:"Show tracked changes"})]}),s.renderTrackedChanges&&e.jsxs("div",{className:"rdv-settings-subsection",children:[e.jsxs("label",{className:"rdv-settings-checkbox",children:[e.jsx("input",{type:"checkbox",checked:s.showDeletedContent,onChange:n=>o({showDeletedContent:n.target.checked})}),e.jsx("span",{children:"Show deleted content"})]}),e.jsxs("label",{className:"rdv-settings-checkbox",children:[e.jsx("input",{type:"checkbox",checked:s.renderMoveOperations,onChange:n=>o({renderMoveOperations:n.target.checked})}),e.jsx("span",{children:"Distinguish move operations"})]})]})]})]}),e.jsx("div",{className:"rdv-settings-footer",children:e.jsx("button",{className:"rdv-settings-apply",onClick:()=>{ce(),N(!1)},children:"Apply & Close"})})]})}),W=()=>e.jsxs("div",{className:"rdv-toolbar",children:[e.jsxs("div",{className:"rdv-toolbar-left",children:[e.jsx("label",{htmlFor:"rdv-file-input",className:"rdv-toolbar-file-btn",children:$||"Open Document"}),e.jsx("input",{id:"rdv-file-input",type:"file",accept:".docx",onChange:re,disabled:B,className:"rdv-file-input"}),$&&e.jsx("button",{className:"rdv-toolbar-btn rdv-toolbar-clear",onClick:de,disabled:B,children:"×"})]}),e.jsx("div",{className:"rdv-toolbar-center",children:u&&r>0&&e.jsxs(e.Fragment,{children:[e.jsx("button",{className:"rdv-toolbar-btn",onClick:ue,disabled:c<=1,title:"Previous Page",children:"◀"}),e.jsxs("div",{className:"rdv-page-input-group",children:[e.jsx("input",{type:"number",className:"rdv-page-input",value:c,min:1,max:r,onChange:n=>{const t=parseInt(n.target.value);isNaN(t)||y(t)}}),e.jsxs("span",{className:"rdv-page-total",children:["/ ",r]})]}),e.jsx("button",{className:"rdv-toolbar-btn",onClick:me,disabled:c>=r,title:"Next Page",children:"▶"}),e.jsx("div",{className:"rdv-toolbar-separator"}),e.jsx("button",{className:"rdv-toolbar-btn",onClick:he,disabled:s.paginationScale<=.3,title:"Zoom Out",children:"−"}),e.jsxs("select",{className:"rdv-zoom-select",value:s.paginationScale,onChange:n=>ge(parseFloat(n.target.value)),children:[e.jsx("option",{value:"0.5",children:"50%"}),e.jsx("option",{value:"0.75",children:"75%"}),e.jsx("option",{value:"0.8",children:"80%"}),e.jsx("option",{value:"0.9",children:"90%"}),e.jsx("option",{value:"1",children:"100%"}),e.jsx("option",{value:"1.25",children:"125%"}),e.jsx("option",{value:"1.5",children:"150%"}),e.jsx("option",{value:"2",children:"200%"})]}),e.jsx("button",{className:"rdv-toolbar-btn",onClick:le,disabled:s.paginationScale>=2,title:"Zoom In",children:"+"})]})}),e.jsx("div",{className:"rdv-toolbar-right",children:ee&&e.jsx("button",{className:"rdv-toolbar-btn rdv-toolbar-settings",onClick:()=>N(!0),title:"Settings",children:"⚙"})})]}),pe=["rdv-viewer",Q].filter(Boolean).join(" ");return e.jsxs("div",{className:pe,style:Y,children:[R==="top"&&e.jsx(W,{}),e.jsxs("div",{className:"rdv-content",children:[f&&e.jsx("div",{className:"rdv-message rdv-message--error",children:e.jsxs("p",{children:["Failed to initialize: ",f.message]})}),!f&&(p||m)&&e.jsxs("div",{className:"rdv-message",children:[e.jsx("div",{className:"rdv-spinner"}),e.jsx("p",{children:p&&h?"Loading engine & preparing document...":p?"Loading document engine...":"Processing document..."})]}),!p&&!f&&!u&&!m&&!h&&e.jsxs("div",{className:"rdv-message",children:[e.jsx("div",{className:"rdv-message__icon",children:"📄"}),e.jsx("p",{children:ne})]}),Z&&!m&&e.jsx("div",{className:"rdv-message rdv-message--error",children:e.jsxs("p",{children:["Error: ",Z.message]})}),u&&!m&&e.jsx("div",{ref:A,className:"rdv-pages",children:e.jsx(J.PaginatedDocument,{html:u,scale:s.paginationScale,showPageNumbers:s.showPageNumbers,pageGap:20,backgroundColor:"#525659",className:"rdv-paginated-document",onPaginationComplete:n=>{w(n.totalPages)},onPageVisible:ve})})]}),R==="bottom"&&e.jsx(W,{}),ie&&e.jsx(xe,{})]})}exports.DEFAULT_SETTINGS=K;exports.DocumentViewer=Ce;
2
+ //# sourceMappingURL=react-docxodus-viewer.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-docxodus-viewer.cjs.js","sources":["../src/types/index.ts","../src/DocumentViewer.tsx"],"sourcesContent":["/**\n * react-docxodus-viewer types\n */\n\nexport type CommentMode = 'disabled' | 'endnote' | 'inline' | 'margin';\nexport type AnnotationMode = 'disabled' | 'above' | 'inline' | 'tooltip' | 'none';\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\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\n /** Initial/controlled viewer settings */\n settings?: Partial<ViewerSettings>;\n /** Default settings (used for uncontrolled mode) */\n defaultSettings?: Partial<ViewerSettings>;\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 /** Placeholder text when no document is loaded */\n placeholder?: string;\n\n /** Base path for WASM files */\n wasmBasePath?: string;\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};\n","import { useState, useCallback, useRef, useEffect, useMemo } from 'react';\nimport { useDocxodus, PaginatedDocument } from 'docxodus/react';\nimport { CommentRenderMode, PaginationMode, AnnotationLabelMode } from 'docxodus';\nimport type { PaginationResult } from 'docxodus/react';\nimport type {\n DocumentViewerProps,\n ViewerSettings,\n CommentMode,\n AnnotationMode,\n} from './types';\nimport { DEFAULT_SETTINGS } from './types';\n\n// Default WASM path - consumers should override this\nconst DEFAULT_WASM_PATH = '/wasm/';\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\nexport function DocumentViewer({\n file: controlledFile,\n html: controlledHtml,\n onFileChange,\n onConversionStart,\n onConversionComplete,\n onError,\n onPageChange,\n settings: controlledSettings,\n defaultSettings,\n onSettingsChange,\n className,\n style,\n toolbar = 'top',\n showSettingsButton = true,\n placeholder = 'Open a DOCX file to view',\n wasmBasePath = DEFAULT_WASM_PATH,\n}: DocumentViewerProps) {\n // Merge default settings\n const mergedDefaults = useMemo(\n () => ({ ...DEFAULT_SETTINGS, ...defaultSettings }),\n [defaultSettings]\n );\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\n const { isReady, isLoading, error: initError, convertToHtml } = useDocxodus(wasmBasePath);\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\n const paginatedContainerRef = useRef<HTMLDivElement>(null);\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 }), [settings]);\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 onConversionStart?.();\n\n // Allow React to render loading state before heavy WASM work\n await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));\n\n try {\n const result = await convertToHtml(fileToConvert, getConvertOptions());\n\n if (controlledHtml === undefined) {\n setInternalHtml(result);\n }\n onConversionComplete?.(result);\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, convertToHtml, getConvertOptions, controlledHtml, onConversionStart, onConversionComplete, onError]);\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\n if (controlledFile === undefined) {\n setInternalFile(selectedFile);\n setInternalHtml(null);\n }\n onFileChange?.(selectedFile);\n\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 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 // 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 </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 // Toolbar component\n const Toolbar = () => (\n <div className=\"rdv-toolbar\">\n <div className=\"rdv-toolbar-left\">\n <label htmlFor=\"rdv-file-input\" className=\"rdv-toolbar-file-btn\">\n {fileName || 'Open Document'}\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 <button className=\"rdv-toolbar-btn rdv-toolbar-clear\" onClick={handleClear} disabled={isProcessing}>\n ×\n </button>\n )}\n </div>\n\n <div className=\"rdv-toolbar-center\">\n {html && totalPages > 0 && (\n <>\n <button\n className=\"rdv-toolbar-btn\"\n onClick={goToPreviousPage}\n disabled={currentPage <= 1}\n title=\"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\"\n onClick={goToNextPage}\n disabled={currentPage >= totalPages}\n title=\"Next Page\"\n >\n ▶\n </button>\n\n <div className=\"rdv-toolbar-separator\" />\n\n <button\n className=\"rdv-toolbar-btn\"\n onClick={handleZoomOut}\n disabled={settings.paginationScale <= 0.3}\n title=\"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 >\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\"\n onClick={handleZoomIn}\n disabled={settings.paginationScale >= 2.0}\n title=\"Zoom In\"\n >\n +\n </button>\n </>\n )}\n </div>\n\n <div className=\"rdv-toolbar-right\">\n {showSettingsButton && (\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-settings\"\n onClick={() => setShowSettings(true)}\n title=\"Settings\"\n >\n ⚙\n </button>\n )}\n </div>\n </div>\n );\n\n const rootClassName = ['rdv-viewer', className].filter(Boolean).join(' ');\n\n return (\n <div 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 <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 {!isLoading && !initError && !html && !isConverting && !file && (\n <div className=\"rdv-message\">\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 {html && !isConverting && (\n <div ref={paginatedContainerRef} className=\"rdv-pages\">\n <PaginatedDocument\n html={html}\n scale={settings.paginationScale}\n showPageNumbers={settings.showPageNumbers}\n pageGap={20}\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 </div>\n\n {toolbar === 'bottom' && <Toolbar />}\n\n {showSettings && <SettingsModal />}\n </div>\n );\n}\n"],"names":["DEFAULT_SETTINGS","DEFAULT_WASM_PATH","getCommentRenderMode","mode","CommentRenderMode","getAnnotationLabelMode","AnnotationLabelMode","DocumentViewer","controlledFile","controlledHtml","onFileChange","onConversionStart","onConversionComplete","onError","onPageChange","controlledSettings","defaultSettings","onSettingsChange","className","style","toolbar","showSettingsButton","placeholder","wasmBasePath","mergedDefaults","useMemo","internalFile","setInternalFile","useState","internalHtml","setInternalHtml","internalSettings","setInternalSettings","file","html","settings","isReady","isLoading","initError","convertToHtml","useDocxodus","isConverting","setIsConverting","error","setError","fileName","setFileName","currentPage","setCurrentPage","totalPages","setTotalPages","showSettings","setShowSettings","paginatedContainerRef","useRef","getConvertOptions","useCallback","PaginationMode","convert","fileToConvert","resolve","result","err","useEffect","handleFileChange","e","selectedFile","reconvert","handleClear","input","updateSettings","updates","newSettings","handleZoomIn","handleZoomOut","handleZoomChange","value","goToPage","pageNum","container","pageElement","goToPreviousPage","goToNextPage","handlePageVisible","pageNumber","handleAnchorClick","anchor","href","targetId","targetElement","isProcessing","SettingsModal","jsx","jsxs","Toolbar","Fragment","page","rootClassName","PaginatedDocument"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ .rdv-viewer{--rdv-border-radius: 8px;--rdv-background: #525659;--rdv-min-height: 500px;--rdv-shadow: 0 4px 20px rgba(0, 0, 0, .15);--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:100%;min-height:var(--rdv-min-height);border-radius:var(--rdv-border-radius);overflow:hidden;background:var(--rdv-background);box-shadow:var(--rdv-shadow)}.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-center,.rdv-toolbar-right{display:flex;align-items:center;gap:.5rem}.rdv-toolbar-center{flex:1;justify-content:center}.rdv-toolbar-file-btn{background:var(--rdv-btn-bg);color:var(--rdv-btn-color);padding:.5rem 1rem;border-radius:var(--rdv-btn-radius);cursor:pointer;font-size:.85rem;transition:background .2s;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:200px;border:none}.rdv-toolbar-file-btn:hover{background:var(--rdv-btn-bg-hover)}.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}.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-clear{padding:.4rem .6rem;font-size:1rem}.rdv-toolbar-settings{font-size:1.1rem}.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 .5rem}.rdv-zoom-select{background:var(--rdv-btn-bg);border:none;color:var(--rdv-btn-color);padding:.4rem .5rem;border-radius:var(--rdv-btn-radius);font-size:.9rem;cursor:pointer}.rdv-zoom-select:focus{outline:none}.rdv-file-input{display:none}.rdv-content{flex:1;overflow:hidden;display:flex;flex-direction:column}.rdv-pages{flex:1;overflow:auto}.rdv-paginated-document{min-height:100%}.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-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)}@media(max-width:768px){.rdv-toolbar{flex-wrap:wrap;gap:.5rem}.rdv-toolbar-center{order:3;flex-basis:100%;justify-content:flex-start}}
@@ -0,0 +1,415 @@
1
+ import { jsxs as a, jsx as e, Fragment as ke } from "react/jsx-runtime";
2
+ import { useMemo as ee, useState as d, useRef as Pe, useCallback as x, useEffect as O } from "react";
3
+ import { useDocxodus as we, PaginatedDocument as xe } from "docxodus/react";
4
+ import { PaginationMode as Me, AnnotationLabelMode as M, CommentRenderMode as S } from "docxodus";
5
+ const Se = {
6
+ paginationScale: 0.8,
7
+ showPageNumbers: !0,
8
+ renderFootnotesAndEndnotes: !0,
9
+ renderHeadersAndFooters: !0,
10
+ commentMode: "disabled",
11
+ annotationMode: "disabled",
12
+ renderTrackedChanges: !1,
13
+ showDeletedContent: !0,
14
+ renderMoveOperations: !0,
15
+ pageTitle: "Document",
16
+ cssPrefix: "docx-",
17
+ fabricateClasses: !0,
18
+ additionalCss: "",
19
+ commentCssClassPrefix: "comment-",
20
+ annotationCssClassPrefix: "annot-"
21
+ }, ye = "/wasm/";
22
+ function Ae(l) {
23
+ switch (l) {
24
+ case "endnote":
25
+ return S.EndnoteStyle;
26
+ case "inline":
27
+ return S.Inline;
28
+ case "margin":
29
+ return S.Margin;
30
+ default:
31
+ return S.Disabled;
32
+ }
33
+ }
34
+ function Te(l) {
35
+ switch (l) {
36
+ case "above":
37
+ return M.Above;
38
+ case "inline":
39
+ return M.Inline;
40
+ case "tooltip":
41
+ return M.Tooltip;
42
+ case "none":
43
+ return M.None;
44
+ default:
45
+ return;
46
+ }
47
+ }
48
+ function Le({
49
+ file: l,
50
+ html: o,
51
+ onFileChange: L,
52
+ onConversionStart: R,
53
+ onConversionComplete: V,
54
+ onError: Z,
55
+ onPageChange: y,
56
+ settings: u,
57
+ defaultSettings: _,
58
+ onSettingsChange: q,
59
+ className: ne,
60
+ style: te,
61
+ toolbar: U = "top",
62
+ showSettingsButton: ae = !0,
63
+ placeholder: se = "Open a DOCX file to view",
64
+ wasmBasePath: ie = ye
65
+ }) {
66
+ const A = ee(
67
+ () => ({ ...Se, ..._ }),
68
+ [_]
69
+ ), [oe, j] = d(null), [re, C] = d(null), [$, ce] = d(A), h = l !== void 0 ? l : oe, m = o !== void 0 ? o : re, t = ee(
70
+ () => u ? { ...A, ...u } : $,
71
+ [u, A, $]
72
+ ), { isReady: p, isLoading: b, error: N, convertToHtml: z } = we(ie), [v, B] = d(!1), [G, k] = d(null), [W, H] = d(""), [c, T] = d(1), [r, E] = d(0), [de, P] = d(!1), F = Pe(null), X = x(() => ({
73
+ commentRenderMode: Ae(t.commentMode),
74
+ pageTitle: t.pageTitle,
75
+ cssPrefix: t.cssPrefix,
76
+ fabricateClasses: t.fabricateClasses,
77
+ additionalCss: t.additionalCss || void 0,
78
+ commentCssClassPrefix: t.commentCssClassPrefix,
79
+ paginationMode: Me.Paginated,
80
+ paginationScale: t.paginationScale,
81
+ renderAnnotations: t.annotationMode !== "disabled",
82
+ annotationLabelMode: Te(t.annotationMode),
83
+ annotationCssClassPrefix: t.annotationCssClassPrefix,
84
+ renderFootnotesAndEndnotes: t.renderFootnotesAndEndnotes,
85
+ renderHeadersAndFooters: t.renderHeadersAndFooters,
86
+ renderTrackedChanges: t.renderTrackedChanges,
87
+ showDeletedContent: t.showDeletedContent,
88
+ renderMoveOperations: t.renderMoveOperations
89
+ }), [t]), f = x(async (n) => {
90
+ if (p) {
91
+ B(!0), k(null), R?.(), await new Promise((s) => requestAnimationFrame(() => requestAnimationFrame(s)));
92
+ try {
93
+ const s = await z(n, X());
94
+ o === void 0 && C(s), V?.(s);
95
+ } catch (s) {
96
+ const g = s instanceof Error ? s : new Error(String(s));
97
+ k(g), Z?.(g);
98
+ } finally {
99
+ B(!1);
100
+ }
101
+ }
102
+ }, [p, z, X, o, R, V, Z]);
103
+ O(() => {
104
+ p && h && !m && !v && o === void 0 && f(h);
105
+ }, [p, h, m, v, f, o]);
106
+ const le = async (n) => {
107
+ const s = n.target.files?.[0];
108
+ s && (H(s.name), k(null), T(1), E(0), l === void 0 && (j(s), C(null)), L?.(s), p && o === void 0 && await f(s));
109
+ }, he = x(async () => {
110
+ h && (o === void 0 && C(null), await f(h));
111
+ }, [h, f, o]), ge = () => {
112
+ l === void 0 && j(null), o === void 0 && C(null), k(null), H(""), T(1), E(0), L?.(null);
113
+ const n = document.getElementById("rdv-file-input");
114
+ n && (n.value = "");
115
+ }, i = x((n) => {
116
+ const s = { ...t, ...n };
117
+ u === void 0 && ce(s), q?.(s);
118
+ }, [t, u, q]), me = () => i({
119
+ paginationScale: Math.min(t.paginationScale + 0.1, 2)
120
+ }), ve = () => i({
121
+ paginationScale: Math.max(t.paginationScale - 0.1, 0.3)
122
+ }), ue = (n) => i({
123
+ paginationScale: Math.max(0.3, Math.min(2, n))
124
+ }), D = (n) => {
125
+ const s = F.current;
126
+ if (!s || n < 1 || n > r) return;
127
+ const g = s.querySelector(`[data-page-number="${n}"]`);
128
+ g && g.scrollIntoView({ behavior: "smooth", block: "start" });
129
+ }, pe = () => c > 1 && D(c - 1), be = () => c < r && D(c + 1), fe = (n) => {
130
+ T(n), y?.(n, r);
131
+ };
132
+ O(() => {
133
+ const n = F.current;
134
+ if (!n) return;
135
+ const s = (g) => {
136
+ const Q = g.target.closest('a[href^="#"]');
137
+ if (!Q) return;
138
+ const I = Q.getAttribute("href");
139
+ if (!I || !I.startsWith("#")) return;
140
+ g.preventDefault();
141
+ const Y = I.substring(1), w = n.querySelector(`[id="${Y}"], [name="${Y}"]`);
142
+ w && (w.scrollIntoView({ behavior: "smooth", block: "center" }), w.classList.add("rdv-footnote-highlight"), setTimeout(() => w.classList.remove("rdv-footnote-highlight"), 2e3));
143
+ };
144
+ return n.addEventListener("click", s), () => n.removeEventListener("click", s);
145
+ }, [m]), O(() => {
146
+ r > 0 && y?.(c, r);
147
+ }, [r, c, y]);
148
+ const J = v || b, Ce = () => /* @__PURE__ */ e("div", { className: "rdv-settings-overlay", onClick: () => P(!1), children: /* @__PURE__ */ a("div", { className: "rdv-settings-modal", onClick: (n) => n.stopPropagation(), children: [
149
+ /* @__PURE__ */ a("div", { className: "rdv-settings-header", children: [
150
+ /* @__PURE__ */ e("h3", { children: "Viewer Settings" }),
151
+ /* @__PURE__ */ e("button", { className: "rdv-settings-close", onClick: () => P(!1), children: "×" })
152
+ ] }),
153
+ /* @__PURE__ */ a("div", { className: "rdv-settings-body", children: [
154
+ /* @__PURE__ */ a("div", { className: "rdv-settings-section", children: [
155
+ /* @__PURE__ */ e("h4", { children: "Display Options" }),
156
+ /* @__PURE__ */ a("label", { className: "rdv-settings-checkbox", children: [
157
+ /* @__PURE__ */ e(
158
+ "input",
159
+ {
160
+ type: "checkbox",
161
+ checked: t.renderFootnotesAndEndnotes,
162
+ onChange: (n) => i({ renderFootnotesAndEndnotes: n.target.checked })
163
+ }
164
+ ),
165
+ /* @__PURE__ */ e("span", { children: "Show footnotes and endnotes" })
166
+ ] }),
167
+ /* @__PURE__ */ a("label", { className: "rdv-settings-checkbox", children: [
168
+ /* @__PURE__ */ e(
169
+ "input",
170
+ {
171
+ type: "checkbox",
172
+ checked: t.renderHeadersAndFooters,
173
+ onChange: (n) => i({ renderHeadersAndFooters: n.target.checked })
174
+ }
175
+ ),
176
+ /* @__PURE__ */ e("span", { children: "Show headers and footers" })
177
+ ] }),
178
+ /* @__PURE__ */ a("label", { className: "rdv-settings-checkbox", children: [
179
+ /* @__PURE__ */ e(
180
+ "input",
181
+ {
182
+ type: "checkbox",
183
+ checked: t.showPageNumbers,
184
+ onChange: (n) => i({ showPageNumbers: n.target.checked })
185
+ }
186
+ ),
187
+ /* @__PURE__ */ e("span", { children: "Show page numbers" })
188
+ ] })
189
+ ] }),
190
+ /* @__PURE__ */ a("div", { className: "rdv-settings-section", children: [
191
+ /* @__PURE__ */ e("h4", { children: "Comment Rendering" }),
192
+ /* @__PURE__ */ e("div", { className: "rdv-settings-radio-group", children: ["disabled", "endnote", "inline", "margin"].map((n) => /* @__PURE__ */ a("label", { className: "rdv-settings-radio", children: [
193
+ /* @__PURE__ */ e(
194
+ "input",
195
+ {
196
+ type: "radio",
197
+ name: "commentMode",
198
+ checked: t.commentMode === n,
199
+ onChange: () => i({ commentMode: n })
200
+ }
201
+ ),
202
+ /* @__PURE__ */ a("span", { children: [
203
+ n.charAt(0).toUpperCase() + n.slice(1),
204
+ n === "endnote" ? "s" : ""
205
+ ] })
206
+ ] }, n)) })
207
+ ] }),
208
+ /* @__PURE__ */ a("div", { className: "rdv-settings-section", children: [
209
+ /* @__PURE__ */ e("h4", { children: "Annotation Rendering" }),
210
+ /* @__PURE__ */ e("div", { className: "rdv-settings-radio-group", children: ["disabled", "above", "inline", "tooltip", "none"].map((n) => /* @__PURE__ */ a("label", { className: "rdv-settings-radio", children: [
211
+ /* @__PURE__ */ e(
212
+ "input",
213
+ {
214
+ type: "radio",
215
+ name: "annotationMode",
216
+ checked: t.annotationMode === n,
217
+ onChange: () => i({ annotationMode: n })
218
+ }
219
+ ),
220
+ /* @__PURE__ */ e("span", { children: n === "none" ? "Highlight Only" : n.charAt(0).toUpperCase() + n.slice(1) })
221
+ ] }, n)) })
222
+ ] }),
223
+ /* @__PURE__ */ a("div", { className: "rdv-settings-section", children: [
224
+ /* @__PURE__ */ e("h4", { children: "Tracked Changes" }),
225
+ /* @__PURE__ */ a("label", { className: "rdv-settings-checkbox", children: [
226
+ /* @__PURE__ */ e(
227
+ "input",
228
+ {
229
+ type: "checkbox",
230
+ checked: t.renderTrackedChanges,
231
+ onChange: (n) => i({ renderTrackedChanges: n.target.checked })
232
+ }
233
+ ),
234
+ /* @__PURE__ */ e("span", { children: "Show tracked changes" })
235
+ ] }),
236
+ t.renderTrackedChanges && /* @__PURE__ */ a("div", { className: "rdv-settings-subsection", children: [
237
+ /* @__PURE__ */ a("label", { className: "rdv-settings-checkbox", children: [
238
+ /* @__PURE__ */ e(
239
+ "input",
240
+ {
241
+ type: "checkbox",
242
+ checked: t.showDeletedContent,
243
+ onChange: (n) => i({ showDeletedContent: n.target.checked })
244
+ }
245
+ ),
246
+ /* @__PURE__ */ e("span", { children: "Show deleted content" })
247
+ ] }),
248
+ /* @__PURE__ */ a("label", { className: "rdv-settings-checkbox", children: [
249
+ /* @__PURE__ */ e(
250
+ "input",
251
+ {
252
+ type: "checkbox",
253
+ checked: t.renderMoveOperations,
254
+ onChange: (n) => i({ renderMoveOperations: n.target.checked })
255
+ }
256
+ ),
257
+ /* @__PURE__ */ e("span", { children: "Distinguish move operations" })
258
+ ] })
259
+ ] })
260
+ ] })
261
+ ] }),
262
+ /* @__PURE__ */ e("div", { className: "rdv-settings-footer", children: /* @__PURE__ */ e("button", { className: "rdv-settings-apply", onClick: () => {
263
+ he(), P(!1);
264
+ }, children: "Apply & Close" }) })
265
+ ] }) }), K = () => /* @__PURE__ */ a("div", { className: "rdv-toolbar", children: [
266
+ /* @__PURE__ */ a("div", { className: "rdv-toolbar-left", children: [
267
+ /* @__PURE__ */ e("label", { htmlFor: "rdv-file-input", className: "rdv-toolbar-file-btn", children: W || "Open Document" }),
268
+ /* @__PURE__ */ e(
269
+ "input",
270
+ {
271
+ id: "rdv-file-input",
272
+ type: "file",
273
+ accept: ".docx",
274
+ onChange: le,
275
+ disabled: J,
276
+ className: "rdv-file-input"
277
+ }
278
+ ),
279
+ W && /* @__PURE__ */ e("button", { className: "rdv-toolbar-btn rdv-toolbar-clear", onClick: ge, disabled: J, children: "×" })
280
+ ] }),
281
+ /* @__PURE__ */ e("div", { className: "rdv-toolbar-center", children: m && r > 0 && /* @__PURE__ */ a(ke, { children: [
282
+ /* @__PURE__ */ e(
283
+ "button",
284
+ {
285
+ className: "rdv-toolbar-btn",
286
+ onClick: pe,
287
+ disabled: c <= 1,
288
+ title: "Previous Page",
289
+ children: "◀"
290
+ }
291
+ ),
292
+ /* @__PURE__ */ a("div", { className: "rdv-page-input-group", children: [
293
+ /* @__PURE__ */ e(
294
+ "input",
295
+ {
296
+ type: "number",
297
+ className: "rdv-page-input",
298
+ value: c,
299
+ min: 1,
300
+ max: r,
301
+ onChange: (n) => {
302
+ const s = parseInt(n.target.value);
303
+ isNaN(s) || D(s);
304
+ }
305
+ }
306
+ ),
307
+ /* @__PURE__ */ a("span", { className: "rdv-page-total", children: [
308
+ "/ ",
309
+ r
310
+ ] })
311
+ ] }),
312
+ /* @__PURE__ */ e(
313
+ "button",
314
+ {
315
+ className: "rdv-toolbar-btn",
316
+ onClick: be,
317
+ disabled: c >= r,
318
+ title: "Next Page",
319
+ children: "▶"
320
+ }
321
+ ),
322
+ /* @__PURE__ */ e("div", { className: "rdv-toolbar-separator" }),
323
+ /* @__PURE__ */ e(
324
+ "button",
325
+ {
326
+ className: "rdv-toolbar-btn",
327
+ onClick: ve,
328
+ disabled: t.paginationScale <= 0.3,
329
+ title: "Zoom Out",
330
+ children: "−"
331
+ }
332
+ ),
333
+ /* @__PURE__ */ a(
334
+ "select",
335
+ {
336
+ className: "rdv-zoom-select",
337
+ value: t.paginationScale,
338
+ onChange: (n) => ue(parseFloat(n.target.value)),
339
+ children: [
340
+ /* @__PURE__ */ e("option", { value: "0.5", children: "50%" }),
341
+ /* @__PURE__ */ e("option", { value: "0.75", children: "75%" }),
342
+ /* @__PURE__ */ e("option", { value: "0.8", children: "80%" }),
343
+ /* @__PURE__ */ e("option", { value: "0.9", children: "90%" }),
344
+ /* @__PURE__ */ e("option", { value: "1", children: "100%" }),
345
+ /* @__PURE__ */ e("option", { value: "1.25", children: "125%" }),
346
+ /* @__PURE__ */ e("option", { value: "1.5", children: "150%" }),
347
+ /* @__PURE__ */ e("option", { value: "2", children: "200%" })
348
+ ]
349
+ }
350
+ ),
351
+ /* @__PURE__ */ e(
352
+ "button",
353
+ {
354
+ className: "rdv-toolbar-btn",
355
+ onClick: me,
356
+ disabled: t.paginationScale >= 2,
357
+ title: "Zoom In",
358
+ children: "+"
359
+ }
360
+ )
361
+ ] }) }),
362
+ /* @__PURE__ */ e("div", { className: "rdv-toolbar-right", children: ae && /* @__PURE__ */ e(
363
+ "button",
364
+ {
365
+ className: "rdv-toolbar-btn rdv-toolbar-settings",
366
+ onClick: () => P(!0),
367
+ title: "Settings",
368
+ children: "⚙"
369
+ }
370
+ ) })
371
+ ] }), Ne = ["rdv-viewer", ne].filter(Boolean).join(" ");
372
+ return /* @__PURE__ */ a("div", { className: Ne, style: te, children: [
373
+ U === "top" && /* @__PURE__ */ e(K, {}),
374
+ /* @__PURE__ */ a("div", { className: "rdv-content", children: [
375
+ N && /* @__PURE__ */ e("div", { className: "rdv-message rdv-message--error", children: /* @__PURE__ */ a("p", { children: [
376
+ "Failed to initialize: ",
377
+ N.message
378
+ ] }) }),
379
+ !N && (b || v) && /* @__PURE__ */ a("div", { className: "rdv-message", children: [
380
+ /* @__PURE__ */ e("div", { className: "rdv-spinner" }),
381
+ /* @__PURE__ */ e("p", { children: b && h ? "Loading engine & preparing document..." : b ? "Loading document engine..." : "Processing document..." })
382
+ ] }),
383
+ !b && !N && !m && !v && !h && /* @__PURE__ */ a("div", { className: "rdv-message", children: [
384
+ /* @__PURE__ */ e("div", { className: "rdv-message__icon", children: "📄" }),
385
+ /* @__PURE__ */ e("p", { children: se })
386
+ ] }),
387
+ G && !v && /* @__PURE__ */ e("div", { className: "rdv-message rdv-message--error", children: /* @__PURE__ */ a("p", { children: [
388
+ "Error: ",
389
+ G.message
390
+ ] }) }),
391
+ m && !v && /* @__PURE__ */ e("div", { ref: F, className: "rdv-pages", children: /* @__PURE__ */ e(
392
+ xe,
393
+ {
394
+ html: m,
395
+ scale: t.paginationScale,
396
+ showPageNumbers: t.showPageNumbers,
397
+ pageGap: 20,
398
+ backgroundColor: "#525659",
399
+ className: "rdv-paginated-document",
400
+ onPaginationComplete: (n) => {
401
+ E(n.totalPages);
402
+ },
403
+ onPageVisible: fe
404
+ }
405
+ ) })
406
+ ] }),
407
+ U === "bottom" && /* @__PURE__ */ e(K, {}),
408
+ de && /* @__PURE__ */ e(Ce, {})
409
+ ] });
410
+ }
411
+ export {
412
+ Se as DEFAULT_SETTINGS,
413
+ Le as DocumentViewer
414
+ };
415
+ //# sourceMappingURL=react-docxodus-viewer.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-docxodus-viewer.es.js","sources":["../src/types/index.ts","../src/DocumentViewer.tsx"],"sourcesContent":["/**\n * react-docxodus-viewer types\n */\n\nexport type CommentMode = 'disabled' | 'endnote' | 'inline' | 'margin';\nexport type AnnotationMode = 'disabled' | 'above' | 'inline' | 'tooltip' | 'none';\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\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\n /** Initial/controlled viewer settings */\n settings?: Partial<ViewerSettings>;\n /** Default settings (used for uncontrolled mode) */\n defaultSettings?: Partial<ViewerSettings>;\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 /** Placeholder text when no document is loaded */\n placeholder?: string;\n\n /** Base path for WASM files */\n wasmBasePath?: string;\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};\n","import { useState, useCallback, useRef, useEffect, useMemo } from 'react';\nimport { useDocxodus, PaginatedDocument } from 'docxodus/react';\nimport { CommentRenderMode, PaginationMode, AnnotationLabelMode } from 'docxodus';\nimport type { PaginationResult } from 'docxodus/react';\nimport type {\n DocumentViewerProps,\n ViewerSettings,\n CommentMode,\n AnnotationMode,\n} from './types';\nimport { DEFAULT_SETTINGS } from './types';\n\n// Default WASM path - consumers should override this\nconst DEFAULT_WASM_PATH = '/wasm/';\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\nexport function DocumentViewer({\n file: controlledFile,\n html: controlledHtml,\n onFileChange,\n onConversionStart,\n onConversionComplete,\n onError,\n onPageChange,\n settings: controlledSettings,\n defaultSettings,\n onSettingsChange,\n className,\n style,\n toolbar = 'top',\n showSettingsButton = true,\n placeholder = 'Open a DOCX file to view',\n wasmBasePath = DEFAULT_WASM_PATH,\n}: DocumentViewerProps) {\n // Merge default settings\n const mergedDefaults = useMemo(\n () => ({ ...DEFAULT_SETTINGS, ...defaultSettings }),\n [defaultSettings]\n );\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\n const { isReady, isLoading, error: initError, convertToHtml } = useDocxodus(wasmBasePath);\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\n const paginatedContainerRef = useRef<HTMLDivElement>(null);\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 }), [settings]);\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 onConversionStart?.();\n\n // Allow React to render loading state before heavy WASM work\n await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));\n\n try {\n const result = await convertToHtml(fileToConvert, getConvertOptions());\n\n if (controlledHtml === undefined) {\n setInternalHtml(result);\n }\n onConversionComplete?.(result);\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, convertToHtml, getConvertOptions, controlledHtml, onConversionStart, onConversionComplete, onError]);\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\n if (controlledFile === undefined) {\n setInternalFile(selectedFile);\n setInternalHtml(null);\n }\n onFileChange?.(selectedFile);\n\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 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 // 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 </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 // Toolbar component\n const Toolbar = () => (\n <div className=\"rdv-toolbar\">\n <div className=\"rdv-toolbar-left\">\n <label htmlFor=\"rdv-file-input\" className=\"rdv-toolbar-file-btn\">\n {fileName || 'Open Document'}\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 <button className=\"rdv-toolbar-btn rdv-toolbar-clear\" onClick={handleClear} disabled={isProcessing}>\n ×\n </button>\n )}\n </div>\n\n <div className=\"rdv-toolbar-center\">\n {html && totalPages > 0 && (\n <>\n <button\n className=\"rdv-toolbar-btn\"\n onClick={goToPreviousPage}\n disabled={currentPage <= 1}\n title=\"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\"\n onClick={goToNextPage}\n disabled={currentPage >= totalPages}\n title=\"Next Page\"\n >\n ▶\n </button>\n\n <div className=\"rdv-toolbar-separator\" />\n\n <button\n className=\"rdv-toolbar-btn\"\n onClick={handleZoomOut}\n disabled={settings.paginationScale <= 0.3}\n title=\"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 >\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\"\n onClick={handleZoomIn}\n disabled={settings.paginationScale >= 2.0}\n title=\"Zoom In\"\n >\n +\n </button>\n </>\n )}\n </div>\n\n <div className=\"rdv-toolbar-right\">\n {showSettingsButton && (\n <button\n className=\"rdv-toolbar-btn rdv-toolbar-settings\"\n onClick={() => setShowSettings(true)}\n title=\"Settings\"\n >\n ⚙\n </button>\n )}\n </div>\n </div>\n );\n\n const rootClassName = ['rdv-viewer', className].filter(Boolean).join(' ');\n\n return (\n <div 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 <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 {!isLoading && !initError && !html && !isConverting && !file && (\n <div className=\"rdv-message\">\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 {html && !isConverting && (\n <div ref={paginatedContainerRef} className=\"rdv-pages\">\n <PaginatedDocument\n html={html}\n scale={settings.paginationScale}\n showPageNumbers={settings.showPageNumbers}\n pageGap={20}\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 </div>\n\n {toolbar === 'bottom' && <Toolbar />}\n\n {showSettings && <SettingsModal />}\n </div>\n );\n}\n"],"names":["DEFAULT_SETTINGS","DEFAULT_WASM_PATH","getCommentRenderMode","mode","CommentRenderMode","getAnnotationLabelMode","AnnotationLabelMode","DocumentViewer","controlledFile","controlledHtml","onFileChange","onConversionStart","onConversionComplete","onError","onPageChange","controlledSettings","defaultSettings","onSettingsChange","className","style","toolbar","showSettingsButton","placeholder","wasmBasePath","mergedDefaults","useMemo","internalFile","setInternalFile","useState","internalHtml","setInternalHtml","internalSettings","setInternalSettings","file","html","settings","isReady","isLoading","initError","convertToHtml","useDocxodus","isConverting","setIsConverting","error","setError","fileName","setFileName","currentPage","setCurrentPage","totalPages","setTotalPages","showSettings","setShowSettings","paginatedContainerRef","useRef","getConvertOptions","useCallback","PaginationMode","convert","fileToConvert","resolve","result","err","useEffect","handleFileChange","e","selectedFile","reconvert","handleClear","input","updateSettings","updates","newSettings","handleZoomIn","handleZoomOut","handleZoomChange","value","goToPage","pageNum","container","pageElement","goToPreviousPage","goToNextPage","handlePageVisible","pageNumber","handleAnchorClick","anchor","href","targetId","targetElement","isProcessing","SettingsModal","jsx","jsxs","Toolbar","Fragment","page","rootClassName","PaginatedDocument"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { DocumentViewerProps } from './types';
2
+ export declare function DocumentViewer({ file: controlledFile, html: controlledHtml, onFileChange, onConversionStart, onConversionComplete, onError, onPageChange, settings: controlledSettings, defaultSettings, onSettingsChange, className, style, toolbar, showSettingsButton, placeholder, wasmBasePath, }: DocumentViewerProps): import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=DocumentViewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocumentViewer.d.ts","sourceRoot":"","sources":["../../src/DocumentViewer.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,mBAAmB,EAIpB,MAAM,SAAS,CAAC;AAyBjB,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,cAAc,EACpB,YAAY,EACZ,iBAAiB,EACjB,oBAAoB,EACpB,OAAO,EACP,YAAY,EACZ,QAAQ,EAAE,kBAAkB,EAC5B,eAAe,EACf,gBAAgB,EAChB,SAAS,EACT,KAAK,EACL,OAAe,EACf,kBAAyB,EACzB,WAAwC,EACxC,YAAgC,GACjC,EAAE,mBAAmB,2CA8erB"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * react-docxodus-viewer
3
+ * A React component for viewing DOCX documents in the browser
4
+ */
5
+ import './styles/DocumentViewer.css';
6
+ export { DocumentViewer } from './DocumentViewer';
7
+ export type { DocumentViewerProps, ViewerSettings, CommentMode, AnnotationMode, } from './types';
8
+ export { DEFAULT_SETTINGS } from './types';
9
+ export type { PaginationResult } from 'docxodus/react';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,6BAA6B,CAAC;AAGrC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,YAAY,EACV,mBAAmB,EACnB,cAAc,EACd,WAAW,EACX,cAAc,GACf,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG3C,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * react-docxodus-viewer types
3
+ */
4
+ export type CommentMode = 'disabled' | 'endnote' | 'inline' | 'margin';
5
+ export type AnnotationMode = 'disabled' | 'above' | 'inline' | 'tooltip' | 'none';
6
+ export interface ViewerSettings {
7
+ /** Zoom scale (0.3 - 2.0) */
8
+ paginationScale: number;
9
+ /** Show page numbers on pages */
10
+ showPageNumbers: boolean;
11
+ /** Render footnotes and endnotes */
12
+ renderFootnotesAndEndnotes: boolean;
13
+ /** Render headers and footers */
14
+ renderHeadersAndFooters: boolean;
15
+ /** Comment rendering mode */
16
+ commentMode: CommentMode;
17
+ /** Annotation rendering mode */
18
+ annotationMode: AnnotationMode;
19
+ /** Show tracked changes */
20
+ renderTrackedChanges: boolean;
21
+ /** Show deleted content in tracked changes */
22
+ showDeletedContent: boolean;
23
+ /** Distinguish move operations in tracked changes */
24
+ renderMoveOperations: boolean;
25
+ /** Page title for converted HTML */
26
+ pageTitle: string;
27
+ /** CSS class prefix for generated elements */
28
+ cssPrefix: string;
29
+ /** Generate CSS classes for styling */
30
+ fabricateClasses: boolean;
31
+ /** Additional CSS to inject */
32
+ additionalCss: string;
33
+ /** CSS class prefix for comments */
34
+ commentCssClassPrefix: string;
35
+ /** CSS class prefix for annotations */
36
+ annotationCssClassPrefix: string;
37
+ }
38
+ export interface DocumentViewerProps {
39
+ /** File to display (controlled mode) */
40
+ file?: File | null;
41
+ /** Pre-converted HTML content (skip conversion) */
42
+ html?: string | null;
43
+ /** Callback when file changes */
44
+ onFileChange?: (file: File | null) => void;
45
+ /** Callback when conversion starts */
46
+ onConversionStart?: () => void;
47
+ /** Callback when conversion completes successfully */
48
+ onConversionComplete?: (html: string) => void;
49
+ /** Callback when an error occurs */
50
+ onError?: (error: Error) => void;
51
+ /** Callback when visible page changes */
52
+ onPageChange?: (page: number, total: number) => void;
53
+ /** Initial/controlled viewer settings */
54
+ settings?: Partial<ViewerSettings>;
55
+ /** Default settings (used for uncontrolled mode) */
56
+ defaultSettings?: Partial<ViewerSettings>;
57
+ /** Callback when settings change */
58
+ onSettingsChange?: (settings: ViewerSettings) => void;
59
+ /** Additional CSS class for the root element */
60
+ className?: string;
61
+ /** Inline styles for the root element */
62
+ style?: React.CSSProperties;
63
+ /** Toolbar position */
64
+ toolbar?: 'top' | 'bottom' | 'none';
65
+ /** Show settings button in toolbar */
66
+ showSettingsButton?: boolean;
67
+ /** Placeholder text when no document is loaded */
68
+ placeholder?: string;
69
+ /** Base path for WASM files */
70
+ wasmBasePath?: string;
71
+ }
72
+ export declare const DEFAULT_SETTINGS: ViewerSettings;
73
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACvE,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAElF,MAAM,WAAW,cAAc;IAC7B,6BAA6B;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,iCAAiC;IACjC,eAAe,EAAE,OAAO,CAAC;IACzB,oCAAoC;IACpC,0BAA0B,EAAE,OAAO,CAAC;IACpC,iCAAiC;IACjC,uBAAuB,EAAE,OAAO,CAAC;IACjC,6BAA6B;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,gCAAgC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,2BAA2B;IAC3B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,8CAA8C;IAC9C,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qDAAqD;IACrD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,uCAAuC;IACvC,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAErB,iCAAiC;IACjC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3C,sCAAsC;IACtC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,sDAAsD;IACtD,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,oCAAoC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,yCAAyC;IACzC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAErD,yCAAyC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACnC,oDAAoD;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1C,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;IAEtD,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,uBAAuB;IACvB,OAAO,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,sCAAsC;IACtC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,+BAA+B;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,gBAAgB,EAAE,cAgB9B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "react-docxodus-viewer",
3
+ "version": "0.1.0",
4
+ "description": "A React component for viewing DOCX documents in the browser, powered by Docxodus",
5
+ "type": "module",
6
+ "main": "./dist/react-docxodus-viewer.cjs.js",
7
+ "module": "./dist/react-docxodus-viewer.es.js",
8
+ "types": "./dist/types/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/types/index.d.ts",
12
+ "import": "./dist/react-docxodus-viewer.es.js",
13
+ "require": "./dist/react-docxodus-viewer.cjs.js"
14
+ },
15
+ "./styles.css": "./dist/react-docxodus-viewer.css"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "sideEffects": [
21
+ "*.css"
22
+ ],
23
+ "scripts": {
24
+ "dev": "vite",
25
+ "build": "npm run build:lib && npm run build:demo",
26
+ "build:lib": "BUILD_LIB=true vite build && tsc -p tsconfig.lib.json",
27
+ "build:demo": "tsc -b && vite build",
28
+ "lint": "eslint .",
29
+ "preview": "vite preview",
30
+ "prepublishOnly": "npm run build:lib"
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/JSv4/react-docxodus-viewer"
35
+ },
36
+ "homepage": "https://github.com/JSv4/react-docxodus-viewer#readme",
37
+ "bugs": {
38
+ "url": "https://github.com/JSv4/react-docxodus-viewer/issues"
39
+ },
40
+ "keywords": [
41
+ "react",
42
+ "docx",
43
+ "viewer",
44
+ "word",
45
+ "document",
46
+ "office",
47
+ "docxodus"
48
+ ],
49
+ "author": "",
50
+ "license": "MIT",
51
+ "peerDependencies": {
52
+ "docxodus": ">=3.9",
53
+ "react": ">=18"
54
+ },
55
+ "dependencies": {},
56
+ "devDependencies": {
57
+ "@eslint/js": "^9.39.1",
58
+ "@types/node": "^24.10.1",
59
+ "@types/react": "^19.2.5",
60
+ "@types/react-dom": "^19.2.3",
61
+ "@vitejs/plugin-react": "^5.1.1",
62
+ "docxodus": "3.9",
63
+ "eslint": "^9.39.1",
64
+ "eslint-plugin-react-hooks": "^7.0.1",
65
+ "eslint-plugin-react-refresh": "^0.4.24",
66
+ "globals": "^16.5.0",
67
+ "react": "^19.2.0",
68
+ "react-dom": "^19.2.0",
69
+ "typescript": "~5.9.3",
70
+ "typescript-eslint": "^8.46.4",
71
+ "vite": "^7.2.4"
72
+ }
73
+ }