@iamjariwala/react-doc-viewer 0.2.0 → 1.0.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 +526 -379
- package/package.json +47 -6
- package/dist/DocViewer.d.ts +0 -21
- package/dist/components/DocumentNav.d.ts +0 -3
- package/dist/components/FileName.d.ts +0 -3
- package/dist/components/HeaderBar.d.ts +0 -3
- package/dist/components/LoadingTimout.d.ts +0 -3
- package/dist/components/ProxyRenderer.d.ts +0 -3
- package/dist/components/common/Button.d.ts +0 -16
- package/dist/components/common/index.d.ts +0 -1
- package/dist/components/icons/index.d.ts +0 -8
- package/dist/cssStyles.d.ts +0 -1
- package/dist/defaultTheme.d.ts +0 -3
- package/dist/empty-DBAFSQIv.cjs +0 -1
- package/dist/empty-GlqisfcO.js +0 -4
- package/dist/features/annotations/components/AnnotationLayer.d.ts +0 -10
- package/dist/features/annotations/components/AnnotationToolbar.d.ts +0 -3
- package/dist/features/annotations/components/ColorPicker.d.ts +0 -3
- package/dist/features/annotations/components/CommentMarker.d.ts +0 -8
- package/dist/features/annotations/components/CommentPopover.d.ts +0 -9
- package/dist/features/annotations/components/TextHighlight.d.ts +0 -8
- package/dist/features/annotations/components/icons/index.d.ts +0 -13
- package/dist/features/annotations/hooks/useAnnotationExport.d.ts +0 -9
- package/dist/features/annotations/hooks/useDrawingCanvas.d.ts +0 -15
- package/dist/features/annotations/hooks/useTextSelection.d.ts +0 -10
- package/dist/features/annotations/index.d.ts +0 -13
- package/dist/features/annotations/state/actions.d.ts +0 -52
- package/dist/features/annotations/state/index.d.ts +0 -17
- package/dist/features/annotations/state/reducer.d.ts +0 -17
- package/dist/features/annotations/types/index.d.ts +0 -44
- package/dist/features/drag-drop/components/DropZoneOverlay.d.ts +0 -9
- package/dist/features/drag-drop/hooks/useDragDrop.d.ts +0 -11
- package/dist/features/drag-drop/hooks/useFileProcessor.d.ts +0 -13
- package/dist/features/drag-drop/index.d.ts +0 -4
- package/dist/features/drag-drop/types/index.d.ts +0 -19
- package/dist/features/thumbnail-sidebar/components/ThumbnailItem.d.ts +0 -11
- package/dist/features/thumbnail-sidebar/components/ThumbnailSidebar.d.ts +0 -8
- package/dist/features/thumbnail-sidebar/components/ThumbnailToggle.d.ts +0 -7
- package/dist/features/thumbnail-sidebar/hooks/useThumbnailGenerator.d.ts +0 -13
- package/dist/features/thumbnail-sidebar/index.d.ts +0 -6
- package/dist/features/thumbnail-sidebar/state/actions.d.ts +0 -31
- package/dist/features/thumbnail-sidebar/state/index.d.ts +0 -15
- package/dist/features/thumbnail-sidebar/state/reducer.d.ts +0 -11
- package/dist/hooks/useDocumentLoader.d.ts +0 -13
- package/dist/hooks/useRendererSelector.d.ts +0 -5
- package/dist/hooks/useTranslation.d.ts +0 -3
- package/dist/hooks/useWindowSize.d.ts +0 -4
- package/dist/i18n.d.ts +0 -158
- package/dist/index-BW6EMUiE.cjs +0 -797
- package/dist/index-CYjVmFQ0.cjs +0 -10
- package/dist/index-DHMTXjv6.cjs +0 -1
- package/dist/index-Dg8HfAtq.js +0 -21246
- package/dist/index-dGGNa2HA.js +0 -3350
- package/dist/index-nyGAOsVK.js +0 -42
- package/dist/index.css +0 -1
- package/dist/index.d.ts +0 -8
- package/dist/locales/ar.json.d.ts +0 -13
- package/dist/locales/de.json.d.ts +0 -13
- package/dist/locales/en.json.d.ts +0 -26
- package/dist/locales/es.json.d.ts +0 -13
- package/dist/locales/fr.json.d.ts +0 -13
- package/dist/locales/it.json.d.ts +0 -13
- package/dist/locales/ja.json.d.ts +0 -13
- package/dist/locales/pl.json.d.ts +0 -13
- package/dist/locales/pt.json.d.ts +0 -13
- package/dist/locales/ru.json.d.ts +0 -13
- package/dist/locales/se.json.d.ts +0 -13
- package/dist/locales/sr.json.d.ts +0 -13
- package/dist/locales/sr_cyr.json.d.ts +0 -13
- package/dist/locales/tr.json.d.ts +0 -13
- package/dist/models.d.ts +0 -122
- package/dist/react-doc-viewer.cjs +0 -1
- package/dist/react-doc-viewer.js +0 -23
- package/dist/renderers/bmp/index.d.ts +0 -4
- package/dist/renderers/csv/index.d.ts +0 -4
- package/dist/renderers/gif/index.d.ts +0 -4
- package/dist/renderers/html/index.d.ts +0 -4
- package/dist/renderers/image/index.d.ts +0 -4
- package/dist/renderers/index.d.ts +0 -15
- package/dist/renderers/jpg/index.d.ts +0 -4
- package/dist/renderers/msdoc/index.d.ts +0 -4
- package/dist/renderers/pdf/components/PDFControls.d.ts +0 -4
- package/dist/renderers/pdf/components/PDFPagination.d.ts +0 -4
- package/dist/renderers/pdf/components/PDFThumbnailGenerator.d.ts +0 -3
- package/dist/renderers/pdf/components/icons/index.d.ts +0 -9
- package/dist/renderers/pdf/components/pages/PDFAllPages.d.ts +0 -7
- package/dist/renderers/pdf/components/pages/PDFPages.d.ts +0 -4
- package/dist/renderers/pdf/components/pages/PDFSinglePage.d.ts +0 -7
- package/dist/renderers/pdf/index.d.ts +0 -4
- package/dist/renderers/pdf/state/actions.d.ts +0 -32
- package/dist/renderers/pdf/state/index.d.ts +0 -13
- package/dist/renderers/pdf/state/reducer.d.ts +0 -15
- package/dist/renderers/png/index.d.ts +0 -4
- package/dist/renderers/tiff/index.d.ts +0 -4
- package/dist/renderers/tiff/tiffToCanvas.d.ts +0 -1
- package/dist/renderers/txt/index.d.ts +0 -4
- package/dist/renderers/video/index.d.ts +0 -4
- package/dist/renderers/webp/index.d.ts +0 -4
- package/dist/store/DocViewerProvider.d.ts +0 -22
- package/dist/store/actions.d.ts +0 -63
- package/dist/store/mainStateReducer.d.ts +0 -23
- package/dist/url-BH2U_nez.cjs +0 -3
- package/dist/url-Dk8Xia2J.js +0 -560
- package/dist/utils/fileLoaders.d.ts +0 -13
- package/dist/utils/getFileName.d.ts +0 -3
package/README.md
CHANGED
|
@@ -1,568 +1,715 @@
|
|
|
1
|
-
[](https://www.npmjs.com/package/@iamjariwala/react-doc-viewer)
|
|
2
|
+
[](https://www.npmjs.com/package/@iamjariwala/react-doc-viewer)
|
|
3
|
+
[](https://github.com/mehuljariwala/react-doc-viewer/blob/main/LICENSE)
|
|
4
|
+
[](https://www.typescriptlang.org/)
|
|
5
|
+
[](https://reactjs.org/)
|
|
3
6
|
|
|
4
|
-
# @
|
|
7
|
+
# @iamjariwala/react-doc-viewer
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
React document viewer and PDF viewer component — render PDF, Word, Excel, PowerPoint, images, video, CSV, and 20+ file types with drag-and-drop, annotations, thumbnails, and i18n. Drop-in React component for document preview and file viewing.
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
## Why @iamjariwala/react-doc-viewer?
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
Most React document viewers only handle PDFs or require expensive commercial licenses. This library is the **most feature-complete open-source document viewer for React** — supporting 20+ file types in a single component, with built-in annotations, drag-and-drop, thumbnail navigation, and full TypeScript support.
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
**Best for:**
|
|
16
|
+
- Apps that need to preview multiple file types (PDF, Word, Excel, images, video) without separate libraries for each
|
|
17
|
+
- Document management systems, file browsers, and content platforms
|
|
18
|
+
- Projects that need annotation, highlighting, or commenting on documents
|
|
19
|
+
- Teams that want a single drop-in component instead of stitching together 5+ libraries
|
|
20
|
+
|
|
21
|
+
### How it compares
|
|
22
|
+
|
|
23
|
+
| Feature | @iamjariwala/react-doc-viewer | react-pdf | @cyntler/react-doc-viewer | react-file-viewer |
|
|
24
|
+
| ------- | :--: | :--: | :--: | :--: |
|
|
25
|
+
| PDF rendering | Yes | Yes | Yes | Yes |
|
|
26
|
+
| Office docs (Word, Excel, PPT) | Yes | -- | Yes | Partial |
|
|
27
|
+
| Images (PNG, JPG, GIF, WebP, TIFF, BMP) | Yes | -- | Yes | Partial |
|
|
28
|
+
| Video (MP4) | Yes | -- | Yes | Yes |
|
|
29
|
+
| CSV / TXT / HTML | Yes | -- | Yes | Partial |
|
|
30
|
+
| Drag & Drop | Yes | -- | -- | -- |
|
|
31
|
+
| Annotations (highlight, draw, comment) | Yes | -- | -- | -- |
|
|
32
|
+
| Thumbnail sidebar | Yes | -- | -- | -- |
|
|
33
|
+
| Programmatic page navigation | Yes | Yes | -- | -- |
|
|
34
|
+
| i18n (14 languages) | Yes | -- | -- | -- |
|
|
35
|
+
| Custom renderers | Yes | -- | Yes | -- |
|
|
36
|
+
| Theming | Yes | -- | Yes | -- |
|
|
37
|
+
| TypeScript | Yes | Yes | Yes | -- |
|
|
38
|
+
| Actively maintained (2024+) | Yes | Yes | -- | -- |
|
|
39
|
+
| License | Apache-2.0 | MIT | MIT | MIT |
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
### Feature Highlights
|
|
44
|
+
|
|
45
|
+
| | | |
|
|
46
|
+
|:--|:--|:--|
|
|
47
|
+
| **Multi-Format Support** -- PDF, DOCX, images, video, CSV & more | **Drag & Drop** -- Drop files directly onto the viewer | **Annotations** -- Highlight, draw, and comment on documents |
|
|
48
|
+
| **Thumbnail Sidebar** -- Visual page navigation for PDFs | **14 Languages** -- Built-in i18n with community translations | **Theming** -- Full color control via theme object |
|
|
49
|
+
| **Custom Renderers** -- Extend or replace any file type renderer | **Page Navigation** -- Programmatic page jump via ref or prop | |
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### What's New in v0.2.0
|
|
54
|
+
|
|
55
|
+
- **Drag & Drop** -- Drop files directly onto the viewer to add or replace documents
|
|
56
|
+
- **Thumbnail Sidebar** -- Visual page navigation with auto-scroll for PDFs
|
|
57
|
+
- **Annotations** -- Highlight text, freehand draw, and add comments with export support
|
|
58
|
+
- **Page Jump** -- Navigate to any page programmatically via ref or prop
|
|
59
|
+
|
|
60
|
+
## Table of Contents
|
|
14
61
|
|
|
15
62
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
16
63
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
17
64
|
## Table of Contents
|
|
18
65
|
|
|
19
|
-
- [Supported
|
|
20
|
-
- [
|
|
66
|
+
- [Supported File Types](#supported-file-types)
|
|
67
|
+
- [Live Demo](#live-demo)
|
|
21
68
|
- [Installation](#installation)
|
|
22
|
-
- [
|
|
23
|
-
|
|
24
|
-
- [
|
|
69
|
+
- [Quick Start](#quick-start)
|
|
70
|
+
- [Documents](#documents)
|
|
71
|
+
- [Remote & Local Files](#remote--local-files)
|
|
25
72
|
- [Initial Active Document](#initial-active-document)
|
|
26
|
-
- [
|
|
27
|
-
- [
|
|
28
|
-
|
|
73
|
+
- [Controlled Document](#controlled-document)
|
|
74
|
+
- [Blob / Uploaded Files](#blob--uploaded-files)
|
|
75
|
+
- [Renderers](#renderers)
|
|
76
|
+
- [Built-in Renderers](#built-in-renderers)
|
|
29
77
|
- [Custom Renderer](#custom-renderer)
|
|
30
78
|
- [Custom File Loader](#custom-file-loader)
|
|
31
|
-
- [
|
|
32
|
-
- [
|
|
33
|
-
- [
|
|
34
|
-
- [
|
|
35
|
-
- [
|
|
36
|
-
|
|
37
|
-
- [
|
|
38
|
-
- [
|
|
39
|
-
- [Styled Components](#styled-components)
|
|
40
|
-
- [Using DocViewerRef](#using-docviewerref)
|
|
41
|
-
- [Config](#config)
|
|
42
|
-
- [Overriding Header Component](#overriding-header-component)
|
|
79
|
+
- [Features](#features)
|
|
80
|
+
- [Drag & Drop](#drag--drop)
|
|
81
|
+
- [Thumbnail Sidebar](#thumbnail-sidebar)
|
|
82
|
+
- [Annotations](#annotations)
|
|
83
|
+
- [Page Navigation](#page-navigation)
|
|
84
|
+
- [Configuration](#configuration)
|
|
85
|
+
- [Full Config Reference](#full-config-reference)
|
|
86
|
+
- [Overriding Header](#overriding-header)
|
|
43
87
|
- [Overriding Loading Renderer](#overriding-loading-renderer)
|
|
44
88
|
- [Overriding No Renderer (Error)](#overriding-no-renderer-error)
|
|
89
|
+
- [Theming](#theming)
|
|
90
|
+
- [Styling](#styling)
|
|
91
|
+
- [Internationalization (i18n)](#internationalization-i18n)
|
|
92
|
+
- [Advanced](#advanced)
|
|
93
|
+
- [DocViewerRef](#docviewerref)
|
|
94
|
+
- [Custom HTTP Verb](#custom-http-verb)
|
|
95
|
+
- [Custom Request Headers](#custom-request-headers)
|
|
96
|
+
- [FAQ](#faq)
|
|
97
|
+
- [Contributing](#contributing)
|
|
98
|
+
- [License](#license)
|
|
45
99
|
|
|
46
100
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
47
101
|
|
|
48
|
-
## Supported
|
|
49
|
-
|
|
50
|
-
| Extension | MIME Type
|
|
51
|
-
| --------- |
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
| mp4 | video/mp4 | |
|
|
71
|
-
| webp | image/webp | |
|
|
72
|
-
|
|
73
|
-
## Storybook Demo
|
|
74
|
-
|
|
75
|
-
https://mehuljariwala.github.io/react-doc-viewer
|
|
76
|
-
|
|
77
|
-
## Installation
|
|
102
|
+
## Supported File Types
|
|
103
|
+
|
|
104
|
+
| Extension | MIME Type | Notes |
|
|
105
|
+
| --------- | --------- | ----- |
|
|
106
|
+
| pdf | `application/pdf` | |
|
|
107
|
+
| png | `image/png` | |
|
|
108
|
+
| jpg / jpeg | `image/jpg`, `image/jpeg` | |
|
|
109
|
+
| gif | `image/gif` | |
|
|
110
|
+
| bmp | `image/bmp` | |
|
|
111
|
+
| tiff | `image/tiff` | |
|
|
112
|
+
| webp | `image/webp` | |
|
|
113
|
+
| csv | `text/csv` | |
|
|
114
|
+
| txt | `text/plain` | |
|
|
115
|
+
| htm / html | `text/htm`, `text/html` | |
|
|
116
|
+
| mp4 | `video/mp4` | |
|
|
117
|
+
| doc | `application/msword` | Public URLs only |
|
|
118
|
+
| docx | `application/vnd.openxmlformats-officedocument.wordprocessingml.document` | Public URLs only |
|
|
119
|
+
| xls | `application/vnd.ms-excel` | Public URLs only |
|
|
120
|
+
| xlsx | `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` | Public URLs only |
|
|
121
|
+
| ppt | `application/vnd.ms-powerpoint` | Public URLs only |
|
|
122
|
+
| pptx | `application/vnd.openxmlformats-officedocument.presentationml.presentation` | Public URLs only |
|
|
123
|
+
| odt | `application/vnd.oasis.opendocument.text` | |
|
|
78
124
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
npm i @mehuljariwala/react-doc-viewer
|
|
83
|
-
# or
|
|
84
|
-
yarn add @mehuljariwala/react-doc-viewer
|
|
85
|
-
```
|
|
125
|
+
> [!IMPORTANT]
|
|
126
|
+
> MS Office documents (doc, docx, xls, xlsx, ppt, pptx) use Microsoft's online viewing service via iframe and **require publicly accessible URLs**.
|
|
86
127
|
|
|
87
|
-
##
|
|
128
|
+
## Live Demo
|
|
88
129
|
|
|
89
|
-
|
|
130
|
+
[Storybook Demo](https://mehuljariwala.github.io/react-doc-viewer)
|
|
90
131
|
|
|
91
|
-
|
|
132
|
+
## Installation
|
|
92
133
|
|
|
93
|
-
|
|
134
|
+
```bash
|
|
135
|
+
npm install @iamjariwala/react-doc-viewer
|
|
136
|
+
```
|
|
94
137
|
|
|
95
|
-
```
|
|
96
|
-
|
|
138
|
+
```bash
|
|
139
|
+
yarn add @iamjariwala/react-doc-viewer
|
|
97
140
|
```
|
|
98
141
|
|
|
99
|
-
|
|
142
|
+
```bash
|
|
143
|
+
pnpm add @iamjariwala/react-doc-viewer
|
|
144
|
+
```
|
|
100
145
|
|
|
101
|
-
|
|
102
|
-
Each document object must have a uri to a file, either a url that returns a file or a local file.
|
|
146
|
+
## Quick Start
|
|
103
147
|
|
|
104
148
|
```tsx
|
|
105
|
-
import DocViewer, { DocViewerRenderers } from "@
|
|
106
|
-
import "@
|
|
149
|
+
import DocViewer, { DocViewerRenderers } from "@iamjariwala/react-doc-viewer";
|
|
150
|
+
import "@iamjariwala/react-doc-viewer/dist/index.css";
|
|
107
151
|
|
|
108
152
|
function App() {
|
|
109
153
|
const docs = [
|
|
110
|
-
{ uri: "https://
|
|
111
|
-
{ uri:
|
|
154
|
+
{ uri: "https://example.com/sample.pdf" },
|
|
155
|
+
{ uri: "https://example.com/photo.png" },
|
|
112
156
|
];
|
|
113
157
|
|
|
114
158
|
return <DocViewer documents={docs} pluginRenderers={DocViewerRenderers} />;
|
|
115
159
|
}
|
|
116
160
|
```
|
|
117
161
|
|
|
118
|
-
|
|
162
|
+
> The CSS import is required for correct rendering of PDF and other file types.
|
|
119
163
|
|
|
120
|
-
|
|
164
|
+
## Documents
|
|
121
165
|
|
|
122
|
-
|
|
123
|
-
import DocViewer, { DocViewerRenderers } from "@mehuljariwala/react-doc-viewer";
|
|
124
|
-
import "@mehuljariwala/react-doc-viewer/dist/index.css";
|
|
166
|
+
### Remote & Local Files
|
|
125
167
|
|
|
126
|
-
|
|
127
|
-
const docs = [
|
|
128
|
-
{ uri: "https://url-to-my-pdf.pdf" }, // Remote file
|
|
129
|
-
{ uri: require("./example-files/pdf.pdf") }, // Local File
|
|
130
|
-
];
|
|
168
|
+
Each document needs a `uri` pointing to a file URL or a local file path.
|
|
131
169
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
/>
|
|
138
|
-
);
|
|
139
|
-
};
|
|
170
|
+
```tsx
|
|
171
|
+
const docs = [
|
|
172
|
+
{ uri: "https://example.com/file.pdf" },
|
|
173
|
+
{ uri: require("./files/document.pdf") },
|
|
174
|
+
];
|
|
140
175
|
```
|
|
141
176
|
|
|
142
|
-
###
|
|
177
|
+
### Initial Active Document
|
|
143
178
|
|
|
144
|
-
|
|
179
|
+
By default the first document is displayed. Use `initialActiveDocument` to change this:
|
|
145
180
|
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
181
|
+
```tsx
|
|
182
|
+
<DocViewer
|
|
183
|
+
documents={docs}
|
|
184
|
+
initialActiveDocument={docs[1]}
|
|
185
|
+
pluginRenderers={DocViewerRenderers}
|
|
186
|
+
/>
|
|
187
|
+
```
|
|
153
188
|
|
|
154
|
-
|
|
155
|
-
setActiveDocument(document);
|
|
156
|
-
};
|
|
189
|
+
### Controlled Document
|
|
157
190
|
|
|
158
|
-
|
|
159
|
-
<>
|
|
160
|
-
<DocViewer
|
|
161
|
-
documents={docs}
|
|
162
|
-
activeDocument={activeDocument}
|
|
163
|
-
onDocumentChange={handleDocumentChange}
|
|
164
|
-
/>
|
|
165
|
-
</>
|
|
166
|
-
);
|
|
167
|
-
};
|
|
168
|
-
```
|
|
191
|
+
Control which document is displayed with `activeDocument` and `onDocumentChange`:
|
|
169
192
|
|
|
170
|
-
|
|
193
|
+
```tsx
|
|
194
|
+
const [activeDocument, setActiveDocument] = useState(docs[0]);
|
|
171
195
|
|
|
172
|
-
|
|
196
|
+
<DocViewer
|
|
197
|
+
documents={docs}
|
|
198
|
+
activeDocument={activeDocument}
|
|
199
|
+
onDocumentChange={setActiveDocument}
|
|
200
|
+
pluginRenderers={DocViewerRenderers}
|
|
201
|
+
/>
|
|
202
|
+
```
|
|
173
203
|
|
|
174
|
-
|
|
175
|
-
const DocViewerWithInputApp = () => {
|
|
176
|
-
const [selectedDocs, setSelectedDocs] = useState<File[]>([]);
|
|
204
|
+
### Blob / Uploaded Files
|
|
177
205
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
206
|
+
Display user-uploaded files using blob URLs:
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
const [files, setFiles] = useState<File[]>([]);
|
|
210
|
+
|
|
211
|
+
<>
|
|
212
|
+
<input
|
|
213
|
+
type="file"
|
|
214
|
+
accept=".pdf"
|
|
215
|
+
multiple
|
|
216
|
+
onChange={(e) =>
|
|
217
|
+
e.target.files?.length && setFiles(Array.from(e.target.files))
|
|
218
|
+
}
|
|
219
|
+
/>
|
|
220
|
+
<DocViewer
|
|
221
|
+
documents={files.map((file) => ({
|
|
222
|
+
uri: window.URL.createObjectURL(file),
|
|
223
|
+
fileName: file.name,
|
|
224
|
+
}))}
|
|
225
|
+
pluginRenderers={DocViewerRenderers}
|
|
226
|
+
/>
|
|
227
|
+
</>
|
|
199
228
|
```
|
|
200
229
|
|
|
201
|
-
|
|
230
|
+
## Renderers
|
|
231
|
+
|
|
232
|
+
### Built-in Renderers
|
|
202
233
|
|
|
203
|
-
|
|
204
|
-
`DocViewerRenderers` is an Array of all the included renderers.
|
|
234
|
+
Use all built-in renderers:
|
|
205
235
|
|
|
206
236
|
```tsx
|
|
207
|
-
import DocViewer, { DocViewerRenderers } from "@
|
|
208
|
-
import "@mehuljariwala/react-doc-viewer/dist/index.css";
|
|
237
|
+
import DocViewer, { DocViewerRenderers } from "@iamjariwala/react-doc-viewer";
|
|
209
238
|
|
|
210
|
-
<DocViewer
|
|
211
|
-
pluginRenderers={DocViewerRenderers}
|
|
212
|
-
{/* ... */}
|
|
213
|
-
/>;
|
|
239
|
+
<DocViewer pluginRenderers={DocViewerRenderers} documents={docs} />;
|
|
214
240
|
```
|
|
215
241
|
|
|
216
|
-
Or
|
|
242
|
+
Or import only what you need:
|
|
217
243
|
|
|
218
244
|
```tsx
|
|
219
|
-
import DocViewer, { PDFRenderer, PNGRenderer } from "@
|
|
220
|
-
import "@mehuljariwala/react-doc-viewer/dist/index.css";
|
|
245
|
+
import DocViewer, { PDFRenderer, PNGRenderer } from "@iamjariwala/react-doc-viewer";
|
|
221
246
|
|
|
222
|
-
<DocViewer
|
|
223
|
-
pluginRenderers={[PDFRenderer, PNGRenderer]}
|
|
224
|
-
{/* ... */}
|
|
225
|
-
/>;
|
|
247
|
+
<DocViewer pluginRenderers={[PDFRenderer, PNGRenderer]} documents={docs} />;
|
|
226
248
|
```
|
|
227
249
|
|
|
250
|
+
**Available renderers:** `BMPRenderer`, `CSVRenderer`, `GIFRenderer`, `HTMLRenderer`, `JPGRenderer`, `MSDocRenderer`, `PDFRenderer`, `PNGRenderer`, `TIFFRenderer`, `TXTRenderer`, `VideoRenderer`, `WebPRenderer`
|
|
251
|
+
|
|
228
252
|
### Custom Renderer
|
|
229
253
|
|
|
230
|
-
|
|
254
|
+
Create a renderer for any file type by defining `fileTypes`, `weight`, and a React component:
|
|
231
255
|
|
|
232
256
|
```tsx
|
|
233
|
-
import
|
|
234
|
-
import DocViewer from "@mehuljariwala/react-doc-viewer";
|
|
257
|
+
import { DocRenderer } from "@iamjariwala/react-doc-viewer";
|
|
235
258
|
|
|
236
|
-
const
|
|
237
|
-
mainState: { currentDocument },
|
|
238
|
-
}) => {
|
|
259
|
+
const MyPNGRenderer: DocRenderer = ({ mainState: { currentDocument } }) => {
|
|
239
260
|
if (!currentDocument) return null;
|
|
240
|
-
|
|
241
|
-
return (
|
|
242
|
-
<div id="my-png-renderer">
|
|
243
|
-
<img id="png-img" src={currentDocument.fileData as string} />
|
|
244
|
-
</div>
|
|
245
|
-
);
|
|
261
|
+
return <img src={currentDocument.fileData as string} />;
|
|
246
262
|
};
|
|
247
263
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
And supply it to `pluginRenderers` inside an `Array`.
|
|
264
|
+
MyPNGRenderer.fileTypes = ["png", "image/png"];
|
|
265
|
+
MyPNGRenderer.weight = 1;
|
|
253
266
|
|
|
254
|
-
|
|
255
|
-
import DocViewer, { DocViewerRenderers } from "@mehuljariwala/react-doc-viewer";
|
|
256
|
-
import "@mehuljariwala/react-doc-viewer/dist/index.css";
|
|
257
|
-
|
|
258
|
-
<DocViewer
|
|
259
|
-
pluginRenderers={[MyCustomPNGRenderer]}
|
|
260
|
-
documents={
|
|
261
|
-
[
|
|
262
|
-
// ...
|
|
263
|
-
]
|
|
264
|
-
}
|
|
265
|
-
/>;
|
|
267
|
+
<DocViewer pluginRenderers={[MyPNGRenderer]} documents={docs} />;
|
|
266
268
|
```
|
|
267
269
|
|
|
268
270
|
### Custom File Loader
|
|
269
271
|
|
|
270
|
-
|
|
271
|
-
You can decorate your custom renderer with a callback to do as you wish. e.g. Load the file yourself in an iFrame.
|
|
272
|
+
Prevent the default file loading and handle it yourself:
|
|
272
273
|
|
|
273
274
|
```tsx
|
|
274
|
-
|
|
275
|
-
documentURI
|
|
276
|
-
signal,
|
|
277
|
-
fileLoaderComplete,
|
|
278
|
-
}) => {
|
|
279
|
-
myCustomFileLoaderCode().then(() => {
|
|
280
|
-
// Whenever you have finished you must call fileLoaderComplete() to remove the loading animation
|
|
275
|
+
MyPNGRenderer.fileLoader = ({ documentURI, signal, fileLoaderComplete }) => {
|
|
276
|
+
myCustomLoader(documentURI).then(() => {
|
|
281
277
|
fileLoaderComplete();
|
|
282
278
|
});
|
|
283
279
|
};
|
|
284
280
|
```
|
|
285
281
|
|
|
286
|
-
##
|
|
282
|
+
## Features
|
|
283
|
+
|
|
284
|
+
### Drag & Drop
|
|
287
285
|
|
|
288
|
-
|
|
286
|
+
Enable file drag-and-drop to add or replace documents in the viewer.
|
|
289
287
|
|
|
290
|
-
```
|
|
288
|
+
```tsx
|
|
291
289
|
<DocViewer
|
|
292
290
|
documents={docs}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
291
|
+
pluginRenderers={DocViewerRenderers}
|
|
292
|
+
config={{
|
|
293
|
+
dragDrop: {
|
|
294
|
+
enableDragDrop: true,
|
|
295
|
+
acceptedFileTypes: ["application/pdf", "image/*"],
|
|
296
|
+
maxFileSize: 50 * 1024 * 1024, // 50 MB
|
|
297
|
+
dropBehavior: "append",
|
|
298
|
+
onDrop: (files) => {
|
|
299
|
+
console.log("Files dropped:", files);
|
|
300
|
+
},
|
|
301
|
+
onDropRejected: (files, reason) => {
|
|
302
|
+
console.log("Rejected:", reason);
|
|
303
|
+
},
|
|
304
|
+
},
|
|
301
305
|
}}
|
|
302
306
|
/>
|
|
303
307
|
```
|
|
304
308
|
|
|
305
|
-
|
|
309
|
+
| Option | Type | Default | Description |
|
|
310
|
+
| ------ | ---- | ------- | ----------- |
|
|
311
|
+
| `enableDragDrop` | `boolean` | `false` | Enable drag-and-drop |
|
|
312
|
+
| `acceptedFileTypes` | `string[]` | all types | MIME types to accept (supports wildcards like `image/*`) |
|
|
313
|
+
| `maxFileSize` | `number` | unlimited | Max file size in bytes |
|
|
314
|
+
| `dropBehavior` | `"append" \| "replace"` | `"append"` | Add to or replace existing documents |
|
|
315
|
+
| `onDrop` | `(files: File[]) => void` | -- | Callback when files are accepted |
|
|
316
|
+
| `onDropRejected` | `(files: File[], reason: "file-type" \| "file-size" \| "unknown") => void` | -- | Callback when files are rejected |
|
|
306
317
|
|
|
307
|
-
|
|
308
|
-
By default, `@mehuljariwala/react-doc-viewer` fetches document metadata through a `HEAD` request in order to guess its `Content-Type`.
|
|
309
|
-
If you need to have a specific verb for the pre-fetching, use the `prefetchMethod` option on the DocViewer:
|
|
318
|
+
### Thumbnail Sidebar
|
|
310
319
|
|
|
311
|
-
|
|
312
|
-
import DocViewer, { DocViewerRenderers } from "@mehuljariwala/react-doc-viewer";
|
|
313
|
-
|
|
314
|
-
<DocViewer prefetchMethod="GET" />;
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
## Custom Request Headers
|
|
318
|
-
|
|
319
|
-
Provide request headers, i.e. for authenticating with an API etc.
|
|
320
|
+
Display a visual sidebar with page thumbnails for quick PDF navigation.
|
|
320
321
|
|
|
321
322
|
```tsx
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
323
|
+
<DocViewer
|
|
324
|
+
documents={docs}
|
|
325
|
+
pluginRenderers={DocViewerRenderers}
|
|
326
|
+
config={{
|
|
327
|
+
thumbnail: {
|
|
328
|
+
enableThumbnails: true,
|
|
329
|
+
thumbnailWidth: 120,
|
|
330
|
+
sidebarDefaultOpen: true,
|
|
331
|
+
},
|
|
332
|
+
}}
|
|
333
|
+
/>
|
|
328
334
|
```
|
|
329
335
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
336
|
+
| Option | Type | Default | Description |
|
|
337
|
+
| ------ | ---- | ------- | ----------- |
|
|
338
|
+
| `enableThumbnails` | `boolean` | `false` | Enable thumbnail sidebar |
|
|
339
|
+
| `thumbnailWidth` | `number` | `120` | Width of each thumbnail in pixels |
|
|
340
|
+
| `sidebarDefaultOpen` | `boolean` | `false` | Open sidebar by default |
|
|
333
341
|
|
|
334
|
-
|
|
335
|
-
<DocViewer documents={docs} language="pl" />
|
|
336
|
-
```
|
|
342
|
+
### Annotations
|
|
337
343
|
|
|
338
|
-
|
|
344
|
+
Add highlights, freehand drawings, and comments to your documents.
|
|
339
345
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
346
|
+
```tsx
|
|
347
|
+
<DocViewer
|
|
348
|
+
documents={docs}
|
|
349
|
+
pluginRenderers={DocViewerRenderers}
|
|
350
|
+
config={{
|
|
351
|
+
annotations: {
|
|
352
|
+
enableAnnotations: true,
|
|
353
|
+
defaultColor: "#FFFF00",
|
|
354
|
+
colors: ["#FFFF00", "#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4"],
|
|
355
|
+
tools: ["select", "highlight", "pen", "comment", "eraser"],
|
|
356
|
+
onAnnotationChange: (annotations) => {
|
|
357
|
+
console.log("Annotations:", annotations);
|
|
358
|
+
},
|
|
359
|
+
initialAnnotations: [],
|
|
360
|
+
},
|
|
361
|
+
}}
|
|
362
|
+
/>
|
|
363
|
+
```
|
|
343
364
|
|
|
344
|
-
|
|
365
|
+
| Option | Type | Default | Description |
|
|
366
|
+
| ------ | ---- | ------- | ----------- |
|
|
367
|
+
| `enableAnnotations` | `boolean` | `false` | Enable annotation toolbar |
|
|
368
|
+
| `defaultColor` | `string` | -- | Default color for new annotations |
|
|
369
|
+
| `colors` | `string[]` | -- | Color palette for the picker |
|
|
370
|
+
| `tools` | `AnnotationTool[]` | all | Which tools to show: `"select"`, `"highlight"`, `"pen"`, `"comment"`, `"eraser"` |
|
|
371
|
+
| `onAnnotationChange` | `(annotations: IAnnotation[]) => void` | -- | Callback when annotations change |
|
|
372
|
+
| `initialAnnotations` | `IAnnotation[]` | `[]` | Pre-loaded annotations |
|
|
345
373
|
|
|
346
|
-
|
|
347
|
-
<DocViewer documents={docs} className="my-doc-viewer-style" />
|
|
348
|
-
```
|
|
374
|
+
**Exporting annotations** -- Use the `useAnnotationExport` hook:
|
|
349
375
|
|
|
350
|
-
|
|
376
|
+
```tsx
|
|
377
|
+
import { useAnnotationExport } from "@iamjariwala/react-doc-viewer";
|
|
351
378
|
|
|
352
|
-
|
|
379
|
+
function AnnotationControls() {
|
|
380
|
+
const {
|
|
381
|
+
exportAnnotations,
|
|
382
|
+
exportAsJSON,
|
|
383
|
+
downloadAnnotations,
|
|
384
|
+
getAnnotationsForPage,
|
|
385
|
+
annotationCount,
|
|
386
|
+
} = useAnnotationExport();
|
|
353
387
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
388
|
+
return (
|
|
389
|
+
<button onClick={() => downloadAnnotations("my-annotations.json")}>
|
|
390
|
+
Download {annotationCount} Annotations
|
|
391
|
+
</button>
|
|
392
|
+
);
|
|
357
393
|
}
|
|
358
394
|
```
|
|
359
395
|
|
|
360
|
-
###
|
|
396
|
+
### Page Navigation
|
|
361
397
|
|
|
362
|
-
|
|
363
|
-
<DocViewer documents={docs} style={{ width: 500, height: 500 }} />
|
|
364
|
-
```
|
|
398
|
+
Jump to a specific page using a ref or the `jumpToPage` prop.
|
|
365
399
|
|
|
366
|
-
|
|
400
|
+
**Using ref:**
|
|
367
401
|
|
|
368
402
|
```tsx
|
|
369
|
-
import
|
|
403
|
+
import DocViewer, { DocViewerRef } from "@iamjariwala/react-doc-viewer";
|
|
370
404
|
|
|
371
|
-
|
|
405
|
+
const docViewerRef = useRef<DocViewerRef>(null);
|
|
372
406
|
|
|
373
|
-
<
|
|
374
|
-
|
|
375
|
-
// ...
|
|
407
|
+
<DocViewer ref={docViewerRef} documents={docs} pluginRenderers={DocViewerRenderers} />;
|
|
376
408
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
409
|
+
docViewerRef.current?.goToPage(5);
|
|
410
|
+
docViewerRef.current?.prev();
|
|
411
|
+
docViewerRef.current?.next();
|
|
380
412
|
```
|
|
381
413
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
Since **v1.13.0** you can control the display of the document with `reference`.
|
|
414
|
+
**Using the `jumpToPage` prop:**
|
|
385
415
|
|
|
386
416
|
```tsx
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
export const UsingRef = () => {
|
|
390
|
-
const docViewerRef = useRef<DocViewerRef>(null);
|
|
417
|
+
const [page, setPage] = useState(1);
|
|
391
418
|
|
|
392
|
-
|
|
393
|
-
<>
|
|
394
|
-
<div>
|
|
395
|
-
<button onClick={() => docViewerRef?.current?.prev()}>
|
|
396
|
-
Prev Document By Ref
|
|
397
|
-
</button>
|
|
398
|
-
<button onClick={() => docViewerRef?.current?.next()}>
|
|
399
|
-
Next Document By Ref
|
|
400
|
-
</button>
|
|
401
|
-
</div>
|
|
402
|
-
<DocViewer
|
|
403
|
-
ref={docViewerRef}
|
|
404
|
-
documents={docs}
|
|
405
|
-
config={{ header: { disableHeader: true } }}
|
|
406
|
-
/>
|
|
407
|
-
</>
|
|
408
|
-
);
|
|
409
|
-
};
|
|
419
|
+
<DocViewer documents={docs} pluginRenderers={DocViewerRenderers} jumpToPage={page} />;
|
|
410
420
|
```
|
|
411
421
|
|
|
412
|
-
##
|
|
422
|
+
## Configuration
|
|
413
423
|
|
|
414
|
-
|
|
424
|
+
### Full Config Reference
|
|
415
425
|
|
|
416
426
|
```tsx
|
|
417
427
|
<DocViewer
|
|
418
428
|
documents={docs}
|
|
429
|
+
pluginRenderers={DocViewerRenderers}
|
|
419
430
|
config={{
|
|
420
431
|
header: {
|
|
421
432
|
disableHeader: false,
|
|
422
433
|
disableFileName: false,
|
|
423
434
|
retainURLParams: false,
|
|
435
|
+
overrideComponent: MyHeader,
|
|
424
436
|
},
|
|
425
|
-
|
|
437
|
+
loadingRenderer: {
|
|
438
|
+
overrideComponent: MyLoader,
|
|
439
|
+
showLoadingTimeout: 500,
|
|
440
|
+
},
|
|
441
|
+
noRenderer: {
|
|
442
|
+
overrideComponent: MyError,
|
|
443
|
+
},
|
|
444
|
+
csvDelimiter: ",",
|
|
426
445
|
pdfZoom: {
|
|
427
|
-
defaultZoom: 1.1,
|
|
428
|
-
zoomJump: 0.2,
|
|
446
|
+
defaultZoom: 1.1,
|
|
447
|
+
zoomJump: 0.2,
|
|
448
|
+
},
|
|
449
|
+
pdfVerticalScrollByDefault: true,
|
|
450
|
+
dragDrop: {
|
|
451
|
+
enableDragDrop: true,
|
|
452
|
+
acceptedFileTypes: ["application/pdf", "image/*"],
|
|
453
|
+
maxFileSize: 50 * 1024 * 1024,
|
|
454
|
+
dropBehavior: "append",
|
|
455
|
+
onDrop: (files) => console.log(files),
|
|
456
|
+
onDropRejected: (files, reason) => console.log(reason),
|
|
457
|
+
},
|
|
458
|
+
thumbnail: {
|
|
459
|
+
enableThumbnails: true,
|
|
460
|
+
thumbnailWidth: 120,
|
|
461
|
+
sidebarDefaultOpen: false,
|
|
462
|
+
},
|
|
463
|
+
annotations: {
|
|
464
|
+
enableAnnotations: true,
|
|
465
|
+
defaultColor: "#FFFF00",
|
|
466
|
+
colors: ["#FFFF00", "#FF6B6B", "#4ECDC4"],
|
|
467
|
+
tools: ["select", "highlight", "pen", "comment", "eraser"],
|
|
468
|
+
onAnnotationChange: (annotations) => console.log(annotations),
|
|
469
|
+
initialAnnotations: [],
|
|
429
470
|
},
|
|
430
|
-
pdfVerticalScrollByDefault: true, // false as default
|
|
431
471
|
}}
|
|
432
472
|
/>
|
|
433
473
|
```
|
|
434
474
|
|
|
435
|
-
### Overriding Header
|
|
436
|
-
|
|
437
|
-
You can pass a callback function to `config.header.overrideComponent` that returns a React Element. The function's parameters will be populated and usable, this function will also be re-called whenever the mainState updates.
|
|
438
|
-
Parameters include the state object from the main component, and document navigation functions for `previousDocument` and `nextDocument`.
|
|
439
|
-
|
|
440
|
-
Example:
|
|
475
|
+
### Overriding Header
|
|
441
476
|
|
|
442
477
|
```tsx
|
|
478
|
+
import { IHeaderOverride } from "@iamjariwala/react-doc-viewer";
|
|
479
|
+
|
|
443
480
|
const MyHeader: IHeaderOverride = (state, previousDocument, nextDocument) => {
|
|
444
|
-
if (!state.currentDocument
|
|
445
|
-
return null;
|
|
446
|
-
}
|
|
481
|
+
if (!state.currentDocument) return null;
|
|
447
482
|
|
|
448
483
|
return (
|
|
449
|
-
|
|
450
|
-
<
|
|
451
|
-
<
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
</div>
|
|
462
|
-
</>
|
|
484
|
+
<div>
|
|
485
|
+
<span>{state.currentDocument.uri}</span>
|
|
486
|
+
<button onClick={previousDocument} disabled={state.currentFileNo === 0}>
|
|
487
|
+
Prev
|
|
488
|
+
</button>
|
|
489
|
+
<button
|
|
490
|
+
onClick={nextDocument}
|
|
491
|
+
disabled={state.currentFileNo >= state.documents.length - 1}
|
|
492
|
+
>
|
|
493
|
+
Next
|
|
494
|
+
</button>
|
|
495
|
+
</div>
|
|
463
496
|
);
|
|
464
497
|
};
|
|
465
498
|
|
|
466
499
|
<DocViewer
|
|
500
|
+
documents={docs}
|
|
467
501
|
pluginRenderers={DocViewerRenderers}
|
|
468
|
-
|
|
469
|
-
{
|
|
470
|
-
// ...
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
config={{
|
|
474
|
-
header: {
|
|
475
|
-
overrideComponent: MyHeader,
|
|
476
|
-
},
|
|
477
|
-
}}
|
|
502
|
+
config={{ header: { overrideComponent: MyHeader } }}
|
|
478
503
|
/>;
|
|
479
504
|
```
|
|
480
505
|
|
|
481
506
|
### Overriding Loading Renderer
|
|
482
507
|
|
|
483
|
-
You can pass a callback function to `config.loadingRenderer.overrideComponent` that returns a React Element.
|
|
484
|
-
|
|
485
|
-
Example:
|
|
486
|
-
|
|
487
508
|
```tsx
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
if (fileText) {
|
|
492
|
-
return <div>Loading Renderer ({fileText})...</div>;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
return <div>Loading Renderer...</div>;
|
|
509
|
+
const MyLoader = ({ document, fileName }: { document: IDocument | undefined; fileName: string }) => {
|
|
510
|
+
return <div>Loading {fileName || document?.fileType}...</div>;
|
|
496
511
|
};
|
|
497
512
|
|
|
498
513
|
<DocViewer
|
|
514
|
+
documents={docs}
|
|
499
515
|
pluginRenderers={DocViewerRenderers}
|
|
500
|
-
documents={
|
|
501
|
-
{
|
|
502
|
-
// ...
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
516
|
config={{
|
|
506
517
|
loadingRenderer: {
|
|
507
|
-
overrideComponent:
|
|
518
|
+
overrideComponent: MyLoader,
|
|
519
|
+
showLoadingTimeout: 500,
|
|
508
520
|
},
|
|
509
521
|
}}
|
|
510
522
|
/>;
|
|
511
523
|
```
|
|
512
524
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
You can change this time value or disable this feature to make the component display immediately:
|
|
525
|
+
### Overriding No Renderer (Error)
|
|
516
526
|
|
|
517
527
|
```tsx
|
|
518
|
-
const
|
|
519
|
-
|
|
528
|
+
const MyError = ({ document, fileName }: { document: IDocument | undefined; fileName: string }) => {
|
|
529
|
+
return <div>Unsupported file: {fileName || document?.fileType}</div>;
|
|
520
530
|
};
|
|
521
531
|
|
|
522
532
|
<DocViewer
|
|
533
|
+
documents={docs}
|
|
523
534
|
pluginRenderers={DocViewerRenderers}
|
|
524
|
-
|
|
525
|
-
{
|
|
526
|
-
// ...
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
config={{
|
|
530
|
-
loadingRenderer: {
|
|
531
|
-
overrideComponent: MyLoadingRenderer,
|
|
532
|
-
showLoadingTimeout: false, // false if you want to disable or number to provide your own value (ms)
|
|
533
|
-
},
|
|
534
|
-
}}
|
|
535
|
+
config={{ noRenderer: { overrideComponent: MyError } }}
|
|
535
536
|
/>;
|
|
536
537
|
```
|
|
537
538
|
|
|
538
|
-
|
|
539
|
+
## Theming
|
|
539
540
|
|
|
540
|
-
|
|
541
|
+
Customize the viewer's appearance with a theme object:
|
|
541
542
|
|
|
542
|
-
|
|
543
|
+
```tsx
|
|
544
|
+
<DocViewer
|
|
545
|
+
documents={docs}
|
|
546
|
+
pluginRenderers={DocViewerRenderers}
|
|
547
|
+
theme={{
|
|
548
|
+
primary: "#5296d8",
|
|
549
|
+
secondary: "#ffffff",
|
|
550
|
+
tertiary: "#5296d899",
|
|
551
|
+
textPrimary: "#ffffff",
|
|
552
|
+
textSecondary: "#5296d8",
|
|
553
|
+
textTertiary: "#00000099",
|
|
554
|
+
disableThemeScrollbar: false,
|
|
555
|
+
}}
|
|
556
|
+
/>
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
| Property | Type | Default | Description |
|
|
560
|
+
| -------- | ---- | ------- | ----------- |
|
|
561
|
+
| `primary` | `string` | `"#fff"` | Primary background color |
|
|
562
|
+
| `secondary` | `string` | `"#000"` | Secondary background color |
|
|
563
|
+
| `tertiary` | `string` | `"#ffffff99"` | Tertiary background color |
|
|
564
|
+
| `textPrimary` | `string` | `"#000"` | Primary text color |
|
|
565
|
+
| `textSecondary` | `string` | `"#fff"` | Secondary text color |
|
|
566
|
+
| `textTertiary` | `string` | `"#00000044"` | Tertiary text color |
|
|
567
|
+
| `disableThemeScrollbar` | `boolean` | `false` | Disable themed scrollbar styling |
|
|
568
|
+
|
|
569
|
+
## Styling
|
|
570
|
+
|
|
571
|
+
**CSS class:**
|
|
543
572
|
|
|
544
573
|
```tsx
|
|
545
|
-
|
|
546
|
-
|
|
574
|
+
<DocViewer documents={docs} pluginRenderers={DocViewerRenderers} className="my-viewer" />
|
|
575
|
+
```
|
|
547
576
|
|
|
548
|
-
|
|
549
|
-
return <div>No Renderer Error! ({fileText})</div>;
|
|
550
|
-
}
|
|
577
|
+
**Inline styles:**
|
|
551
578
|
|
|
552
|
-
|
|
553
|
-
}
|
|
579
|
+
```tsx
|
|
580
|
+
<DocViewer documents={docs} pluginRenderers={DocViewerRenderers} style={{ width: 500, height: 500 }} />
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
**Styled Components:**
|
|
584
|
+
|
|
585
|
+
```tsx
|
|
586
|
+
import styled from "styled-components";
|
|
587
|
+
import DocViewer from "@iamjariwala/react-doc-viewer";
|
|
588
|
+
|
|
589
|
+
const MyDocViewer = styled(DocViewer)`
|
|
590
|
+
border-radius: 10px;
|
|
591
|
+
`;
|
|
592
|
+
|
|
593
|
+
<MyDocViewer documents={docs} />;
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
**Override internal elements by DOM ID:**
|
|
597
|
+
|
|
598
|
+
```css
|
|
599
|
+
#react-doc-viewer #header-bar {
|
|
600
|
+
background-color: #faf;
|
|
601
|
+
}
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
## Internationalization (i18n)
|
|
605
|
+
|
|
606
|
+
Pass a `language` prop to translate the UI:
|
|
607
|
+
|
|
608
|
+
```tsx
|
|
609
|
+
<DocViewer documents={docs} pluginRenderers={DocViewerRenderers} language="pl" />
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
**Supported languages:**
|
|
613
|
+
|
|
614
|
+
| Code | Language |
|
|
615
|
+
| ---- | -------- |
|
|
616
|
+
| `en` | English |
|
|
617
|
+
| `ar` | Arabic |
|
|
618
|
+
| `de` | German |
|
|
619
|
+
| `es` | Spanish |
|
|
620
|
+
| `fr` | French |
|
|
621
|
+
| `it` | Italian |
|
|
622
|
+
| `ja` | Japanese |
|
|
623
|
+
| `pl` | Polish |
|
|
624
|
+
| `pt` | Portuguese |
|
|
625
|
+
| `ru` | Russian |
|
|
626
|
+
| `se` | Swedish |
|
|
627
|
+
| `sr` | Serbian (Latin) |
|
|
628
|
+
| `sr_cyr` | Serbian (Cyrillic) |
|
|
629
|
+
| `tr` | Turkish |
|
|
630
|
+
|
|
631
|
+
Translation files are in `src/locales/`. PRs for new languages are welcome.
|
|
632
|
+
|
|
633
|
+
## Advanced
|
|
634
|
+
|
|
635
|
+
### DocViewerRef
|
|
636
|
+
|
|
637
|
+
Control the viewer programmatically:
|
|
638
|
+
|
|
639
|
+
```tsx
|
|
640
|
+
import DocViewer, { DocViewerRef } from "@iamjariwala/react-doc-viewer";
|
|
641
|
+
|
|
642
|
+
const docViewerRef = useRef<DocViewerRef>(null);
|
|
643
|
+
|
|
644
|
+
<DocViewer ref={docViewerRef} documents={docs} pluginRenderers={DocViewerRenderers} />;
|
|
645
|
+
|
|
646
|
+
docViewerRef.current?.prev();
|
|
647
|
+
docViewerRef.current?.next();
|
|
648
|
+
docViewerRef.current?.goToPage(3);
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
### Custom HTTP Verb
|
|
652
|
+
|
|
653
|
+
Some services (like AWS S3) require a specific HTTP verb for pre-fetching. By default, `HEAD` is used:
|
|
554
654
|
|
|
655
|
+
```tsx
|
|
656
|
+
<DocViewer documents={docs} pluginRenderers={DocViewerRenderers} prefetchMethod="GET" />
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### Custom Request Headers
|
|
660
|
+
|
|
661
|
+
Provide custom headers for authenticated requests:
|
|
662
|
+
|
|
663
|
+
```tsx
|
|
555
664
|
<DocViewer
|
|
665
|
+
documents={docs}
|
|
556
666
|
pluginRenderers={DocViewerRenderers}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
}
|
|
562
|
-
config={{
|
|
563
|
-
noRenderer: {
|
|
564
|
-
overrideComponent: MyNoRenderer,
|
|
565
|
-
},
|
|
667
|
+
prefetchMethod="GET"
|
|
668
|
+
requestHeaders={{
|
|
669
|
+
"X-Access-Token": "1234567890",
|
|
670
|
+
"My-Custom-Header": "value",
|
|
566
671
|
}}
|
|
567
|
-
|
|
672
|
+
/>
|
|
568
673
|
```
|
|
674
|
+
|
|
675
|
+
## FAQ
|
|
676
|
+
|
|
677
|
+
**What is the best React document viewer library?**
|
|
678
|
+
@iamjariwala/react-doc-viewer is an open-source React document viewer that supports 20+ file types (PDF, Word, Excel, PowerPoint, images, video, CSV, HTML, and more) in a single component. It includes built-in annotations, drag-and-drop, thumbnail navigation, theming, and i18n — features that most alternatives require paid licenses or multiple libraries to achieve.
|
|
679
|
+
|
|
680
|
+
**How do I display a PDF in React?**
|
|
681
|
+
Install `@iamjariwala/react-doc-viewer`, import `DocViewer` and `DocViewerRenderers`, pass your PDF URL as a document, and the component handles rendering, zoom, pagination, and page navigation automatically. See [Quick Start](#quick-start).
|
|
682
|
+
|
|
683
|
+
**Can I view Word, Excel, and PowerPoint files in React?**
|
|
684
|
+
Yes. This library renders `.doc`, `.docx`, `.xls`, `.xlsx`, `.ppt`, and `.pptx` files using Microsoft's online viewing service. The files must be accessible via a public URL.
|
|
685
|
+
|
|
686
|
+
**Does it support annotations and highlighting?**
|
|
687
|
+
Yes. Enable annotations via config to get text highlighting, freehand drawing, comments, and an eraser tool. Annotations can be exported as JSON and pre-loaded from saved data. See [Annotations](#annotations).
|
|
688
|
+
|
|
689
|
+
**Does it work with Next.js?**
|
|
690
|
+
Yes. The library works with Next.js and other React frameworks. A Next.js example project is included in the repository under `use-cases/nextjs/`.
|
|
691
|
+
|
|
692
|
+
**Can I add my own file type renderer?**
|
|
693
|
+
Yes. Create a custom renderer component with `fileTypes` and `weight` properties and pass it via `pluginRenderers`. You can also override the file loading logic. See [Custom Renderer](#custom-renderer).
|
|
694
|
+
|
|
695
|
+
**How does this compare to react-pdf?**
|
|
696
|
+
react-pdf only handles PDF files. @iamjariwala/react-doc-viewer handles 20+ file types including PDF, and adds drag-and-drop, annotations, thumbnails, theming, and i18n on top. If you only need PDF rendering, react-pdf is lighter. If you need multi-format support or advanced features, this library covers more ground.
|
|
697
|
+
|
|
698
|
+
## Contributing
|
|
699
|
+
|
|
700
|
+
Contributions are welcome. Please open an issue first to discuss significant changes. PRs for bug fixes, new renderers, and translations are appreciated.
|
|
701
|
+
|
|
702
|
+
```bash
|
|
703
|
+
git clone https://github.com/mehuljariwala/react-doc-viewer.git
|
|
704
|
+
cd react-doc-viewer
|
|
705
|
+
npm install
|
|
706
|
+
npm start
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
## License
|
|
710
|
+
|
|
711
|
+
[Apache-2.0](./LICENSE)
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
715
|
+
<sub>Forked from [@cyntler/react-doc-viewer](https://github.com/cyntler/react-doc-viewer).</sub>
|