A framework-agnostic, universal document renderer with optional chunked loading polyrender.wisp.place/
at main 181 lines 6.2 kB view raw view rendered
1# @polyrender/react 2 3React component and hook for rendering documents in the browser. A thin wrapper around [`@polyrender/core`](https://www.npmjs.com/package/@polyrender/core) that handles React lifecycle, cleanup, and ref-based imperative control. 4 5Supports PDF, EPUB, DOCX, ODT, ODS, CSV/TSV, source code, plain text, and comic book archives (.cbz, .cbr, .cb7, .cbt). 6 7## Installation 8 9```bash 10npm install @polyrender/react @polyrender/core 11``` 12 13Install peer dependencies only for the formats you need: 14 15```bash 16npm install pdfjs-dist # PDF 17npm install epubjs # EPUB 18npm install docx-preview # DOCX 19npm install jszip # ODT, CBZ comic archives 20npm install xlsx # ODS 21npm install papaparse # CSV/TSV 22npm install highlight.js # Code, Markdown, JSON, XML/HTML 23 24# Comic book archives — additional optional backends: 25npm install node-unrar-js # CBR (.cbr, RAR-compressed comics) 26npm install 7z-wasm # CB7 (.cb7, 7-Zip-compressed comics) 27 28# Comic book archives — optional exotic image format decoders: 29npm install @jsquash/jxl # JPEG XL images inside archives 30npm install utif # TIFF images inside archives 31``` 32 33## Quick Start 34 35```tsx 36import { DocumentViewer } from '@polyrender/react' 37import '@polyrender/core/styles.css' 38 39function App() { 40 return ( 41 <DocumentViewer 42 source={{ type: 'url', url: '/report.pdf' }} 43 theme="dark" 44 style={{ width: '100%', height: '80vh' }} 45 onReady={(info) => console.log(`${info.pageCount} pages`)} 46 onPageChange={(page, total) => console.log(`${page}/${total}`)} 47 /> 48 ) 49} 50``` 51 52## `<DocumentViewer>` 53 54Drop-in component. Props mirror `PolyRenderOptions` from `@polyrender/core`. 55 56### Props 57 58| Prop | Type | Default | Description | 59|------|------|---------|-------------| 60| `source` | `DocumentSource \| null` | — | The document to render | 61| `format` | `DocumentFormat` | auto | Override format detection | 62| `theme` | `'dark' \| 'light' \| 'system'` | `'dark'` | Color theme | 63| `className` | `string` | — | Extra CSS class on the root element | 64| `style` | `React.CSSProperties` | — | Styles for the wrapper div (set width/height here) | 65| `initialPage` | `number` | `1` | Starting page | 66| `zoom` | `number \| 'fit-width' \| 'fit-page' \| 'auto'` | — | Initial zoom | 67| `toolbar` | `boolean \| ToolbarConfig` | `true` | Toolbar visibility/config. `ToolbarConfig` fields: `navigation`, `zoom`, `wrapToggle`, `fullscreen`, `info`, `download`, `position` | 68| `showPageNumbers` | `boolean` | — | Show page numbers | 69| `onReady` | `(info: DocumentInfo) => void` | — | Fired when document is loaded | 70| `onPageChange` | `(page, total) => void` | — | Fired on page navigation | 71| `onZoomChange` | `(zoom: number) => void` | — | Fired on zoom change | 72| `onError` | `(error: PolyRenderError) => void` | — | Fired on unrecoverable error | 73| `onLoadingChange` | `(loading: boolean) => void` | — | Fired on loading state change | 74| `pdf` | `PdfOptions` | — | PDF-specific options | 75| `epub` | `EpubOptions` | — | EPUB-specific options | 76| `code` | `CodeOptions` | — | Code-specific options | 77| `csv` | `CsvOptions` | — | CSV/TSV-specific options | 78| `comic` | `ComicOptions` | — | Comic archive options (JXL/TIFF decoders, format filter) | 79 80### Imperative Control via Ref 81 82```tsx 83import { useRef } from 'react' 84import { DocumentViewer, type DocumentViewerRef } from '@polyrender/react' 85import '@polyrender/core/styles.css' 86 87function App() { 88 const viewerRef = useRef<DocumentViewerRef>(null) 89 90 return ( 91 <> 92 <DocumentViewer 93 ref={viewerRef} 94 source={{ type: 'url', url: '/report.pdf' }} 95 style={{ width: '100%', height: '80vh' }} 96 /> 97 <button onClick={() => viewerRef.current?.goToPage(1)}>First page</button> 98 <button onClick={() => viewerRef.current?.setZoom('fit-width')}>Fit width</button> 99 </> 100 ) 101} 102``` 103 104`DocumentViewerRef` exposes: `goToPage(page)`, `setZoom(zoom)`, `getCurrentPage()`, `getPageCount()`, `getZoom()`. 105 106## `useDocumentRenderer` (headless hook) 107 108For building fully custom UI around the renderer: 109 110```tsx 111import { useDocumentRenderer } from '@polyrender/react' 112import '@polyrender/core/styles.css' 113 114function CustomViewer({ url }: { url: string }) { 115 const { containerRef, state, goToPage, setZoom } = useDocumentRenderer({ 116 source: { type: 'url', url }, 117 theme: 'dark', 118 toolbar: false, 119 }) 120 121 return ( 122 <div> 123 <div ref={containerRef} style={{ width: '100%', height: '600px' }} /> 124 <div> 125 <button onClick={() => goToPage(state.currentPage - 1)}>Prev</button> 126 <span>{state.currentPage} / {state.totalPages}</span> 127 <button onClick={() => goToPage(state.currentPage + 1)}>Next</button> 128 <button onClick={() => setZoom(state.zoom * 1.2)}>Zoom In</button> 129 </div> 130 </div> 131 ) 132} 133``` 134 135### Return value 136 137| Field | Type | Description | 138|-------|------|-------------| 139| `containerRef` | `RefObject<HTMLDivElement>` | Attach to your container element | 140| `state` | `PolyRenderState` | Current viewer state | 141| `goToPage` | `(page: number) => void` | Navigate to a page | 142| `setZoom` | `(zoom) => void` | Set zoom level | 143| `ready` | `boolean` | `true` after `onReady` fires | 144| `error` | `PolyRenderError \| null` | Current error, if any | 145 146`PolyRenderState` contains: `loading`, `error`, `currentPage`, `totalPages`, `zoom`, `documentInfo`. 147 148## Document Sources 149 150See [`@polyrender/core`](https://www.npmjs.com/package/@polyrender/core) for full documentation on `FileSource`, `UrlSource`, `PagesSource`, and `ChunkedSource`. 151 152## Theming 153 154Import and apply styles from `@polyrender/core`: 155 156```tsx 157import '@polyrender/core/styles.css' 158``` 159 160Override CSS custom properties on the `.polyrender` root element: 161 162```css 163.my-viewer .polyrender { 164 --dv-bg: #1e1e2e; 165 --dv-text: #cdd6f4; 166 --dv-accent: #89b4fa; 167} 168``` 169 170## Repository 171 172The source code is hosted in two locations: 173 174- **Tangled** (primary): https://tangled.org/aria.pds.witchcraft.systems/polyrender 175- **GitHub** (mirror): https://github.com/BuyMyMojo/polyrender 176 177This package lives under `packages/react` in the monorepo. 178 179## License 180 181Zlib