@polyrender/react
v0.2.0
Published
React components for the PolyRender universal document renderer
Maintainers
Readme
@polyrender/react
React component and hook for rendering documents in the browser. A thin wrapper around @polyrender/core that handles React lifecycle, cleanup, and ref-based imperative control.
Supports PDF, EPUB, DOCX, ODT, ODS, CSV/TSV, source code, plain text, and comic book archives (.cbz, .cbr, .cb7, .cbt).
Installation
npm install @polyrender/react @polyrender/coreInstall peer dependencies only for the formats you need:
npm install pdfjs-dist # PDF
npm install epubjs # EPUB
npm install docx-preview # DOCX
npm install jszip # ODT, CBZ comic archives
npm install xlsx # ODS
npm install papaparse # CSV/TSV
npm install highlight.js # Code, Markdown, JSON, XML/HTML
# Comic book archives — additional optional backends:
npm install node-unrar-js # CBR (.cbr, RAR-compressed comics)
npm install 7z-wasm # CB7 (.cb7, 7-Zip-compressed comics)
# Comic book archives — optional exotic image format decoders:
npm install @jsquash/jxl # JPEG XL images inside archives
npm install utif # TIFF images inside archivesQuick Start
import { DocumentViewer } from '@polyrender/react'
import '@polyrender/core/styles.css'
function App() {
return (
<DocumentViewer
source={{ type: 'url', url: '/report.pdf' }}
theme="dark"
style={{ width: '100%', height: '80vh' }}
onReady={(info) => console.log(`${info.pageCount} pages`)}
onPageChange={(page, total) => console.log(`${page}/${total}`)}
/>
)
}<DocumentViewer>
Drop-in component. Props mirror PolyRenderOptions from @polyrender/core.
Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| source | DocumentSource \| null | — | The document to render |
| format | DocumentFormat | auto | Override format detection |
| theme | 'dark' \| 'light' \| 'system' | 'dark' | Color theme |
| className | string | — | Extra CSS class on the root element |
| style | React.CSSProperties | — | Styles for the wrapper div (set width/height here) |
| initialPage | number | 1 | Starting page |
| zoom | number \| 'fit-width' \| 'fit-page' \| 'auto' | — | Initial zoom |
| toolbar | boolean \| ToolbarConfig | true | Toolbar visibility/config. ToolbarConfig fields: navigation, zoom, wrapToggle, fullscreen, info, download, position |
| showPageNumbers | boolean | — | Show page numbers |
| onReady | (info: DocumentInfo) => void | — | Fired when document is loaded |
| onPageChange | (page, total) => void | — | Fired on page navigation |
| onZoomChange | (zoom: number) => void | — | Fired on zoom change |
| onError | (error: PolyRenderError) => void | — | Fired on unrecoverable error |
| onLoadingChange | (loading: boolean) => void | — | Fired on loading state change |
| pdf | PdfOptions | — | PDF-specific options |
| epub | EpubOptions | — | EPUB-specific options |
| code | CodeOptions | — | Code-specific options |
| csv | CsvOptions | — | CSV/TSV-specific options |
| comic | ComicOptions | — | Comic archive options (JXL/TIFF decoders, format filter) |
Imperative Control via Ref
import { useRef } from 'react'
import { DocumentViewer, type DocumentViewerRef } from '@polyrender/react'
import '@polyrender/core/styles.css'
function App() {
const viewerRef = useRef<DocumentViewerRef>(null)
return (
<>
<DocumentViewer
ref={viewerRef}
source={{ type: 'url', url: '/report.pdf' }}
style={{ width: '100%', height: '80vh' }}
/>
<button onClick={() => viewerRef.current?.goToPage(1)}>First page</button>
<button onClick={() => viewerRef.current?.setZoom('fit-width')}>Fit width</button>
</>
)
}DocumentViewerRef exposes: goToPage(page), setZoom(zoom), getCurrentPage(), getPageCount(), getZoom().
useDocumentRenderer (headless hook)
For building fully custom UI around the renderer:
import { useDocumentRenderer } from '@polyrender/react'
import '@polyrender/core/styles.css'
function CustomViewer({ url }: { url: string }) {
const { containerRef, state, goToPage, setZoom } = useDocumentRenderer({
source: { type: 'url', url },
theme: 'dark',
toolbar: false,
})
return (
<div>
<div ref={containerRef} style={{ width: '100%', height: '600px' }} />
<div>
<button onClick={() => goToPage(state.currentPage - 1)}>Prev</button>
<span>{state.currentPage} / {state.totalPages}</span>
<button onClick={() => goToPage(state.currentPage + 1)}>Next</button>
<button onClick={() => setZoom(state.zoom * 1.2)}>Zoom In</button>
</div>
</div>
)
}Return value
| Field | Type | Description |
|-------|------|-------------|
| containerRef | RefObject<HTMLDivElement> | Attach to your container element |
| state | PolyRenderState | Current viewer state |
| goToPage | (page: number) => void | Navigate to a page |
| setZoom | (zoom) => void | Set zoom level |
| ready | boolean | true after onReady fires |
| error | PolyRenderError \| null | Current error, if any |
PolyRenderState contains: loading, error, currentPage, totalPages, zoom, documentInfo.
Document Sources
See @polyrender/core for full documentation on FileSource, UrlSource, PagesSource, and ChunkedSource.
Theming
Import and apply styles from @polyrender/core:
import '@polyrender/core/styles.css'Override CSS custom properties on the .polyrender root element:
.my-viewer .polyrender {
--dv-bg: #1e1e2e;
--dv-text: #cdd6f4;
--dv-accent: #89b4fa;
}Repository
The source code is hosted in two locations:
- Tangled (primary): https://tangled.org/aria.pds.witchcraft.systems/polyrender
- GitHub (mirror): https://github.com/BuyMyMojo/polyrender
This package lives under packages/react in the monorepo.
License
Zlib
