react-pdfjs-multi 1.0.0-rc.4 → 1.0.0-rc.5

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 CHANGED
@@ -2,64 +2,86 @@
2
2
 
3
3
  React wrapper for pdfjs with multiple file support.
4
4
 
5
- This library uses [pdf.js][1].
5
+ You can find a working example [here][2].
6
6
 
7
- > What does in development mean:
8
- >
9
- > 1. **MINOR** versions represent **breaking changes**
10
- > 1. **PATCH** versions represent **fixes _and_ features**
11
- > 1. There are **no deprecation warnings** between releases
7
+ This library uses [pdf.js][1].
12
8
 
13
9
  ## Installation & Usage
14
10
 
15
- `yarn add react-pdfjs-multi`
11
+ `npm i react-pdfjs-multi`
16
12
 
17
- or
13
+ ### Example Usage
18
14
 
19
- `npm i react-pdfjs-multi`
15
+ #### Minimal example
20
16
 
21
- Example Usage MultiViewer:
17
+ If you only need the defaults, you can render the component with just the `pdfs` array and the bundled CSS.
22
18
 
23
- ```javascript
19
+ ```tsx
24
20
  import React from 'react';
25
21
  import { PdfMultiViewer } from 'react-pdfjs-multi';
22
+ import workerSrc from 'react-pdfjs-multi/dist/pdf.worker.min.mjs?url';
26
23
  import 'react-pdfjs-multi/dist/react-pdfjs-multi.css';
27
24
 
28
- const MultiViewerExample = () => {
29
- const pdfFiles = [
30
- 'pdfs/test-pdf-a.pdf',
31
- {
32
- title:
33
- 'Trace-based Just-in-Time Type Specialization for DynamicLanguages',
34
- source: 'pdfs/compressed.tracemonkey-pldi-09.pdf',
35
- },
36
- 'pdfs/test-pdf-b.pdf',
37
- 'pdfs/test-pdf-c.pdf',
38
- ];
39
-
40
- return (
41
- <PdfMultiViewer
42
- pdfs={pdfFiles}
43
- i18nData={{
44
- download: 'Herunterladen',
45
- scaleDown: 'Verkleinern',
46
- scaleUp: 'Vergrößern',
47
- originalSize: 'Originalgröße',
48
- pages: 'Seiten',
49
- zoom: 'Automatischer Zoom',
50
- }}
51
- />
52
- );
25
+ const MinimalMultiViewer = () => (
26
+ <PdfMultiViewer pdfs={['/pdfs/sample-a.pdf', '/pdfs/sample-b.pdf']} />
27
+ );
28
+
29
+ export default MinimalMultiViewer;
30
+ ```
31
+
32
+ #### MultiViewer customization
33
+
34
+ This example picks a non-default document via `initialLoadIndex`, and the `icons` prop overrides the visual assets via CSS variables.
35
+
36
+ ```tsx
37
+ import React from 'react';
38
+ import { PdfMultiViewer, type IconConfig } from 'react-pdfjs-multi';
39
+ import workerSrc from 'react-pdfjs-multi/dist/pdf.worker.min.mjs?url';
40
+ import 'react-pdfjs-multi/dist/react-pdfjs-multi.css';
41
+
42
+ const pdfs = ['/pdfs/sample-a.pdf', '/pdfs/sample-b.pdf'];
43
+
44
+ const icons: IconConfig = {
45
+ zoomIn: '/icons/zoom-in.svg',
46
+ zoomOut: '/icons/zoom-out.svg',
47
+ rotateLeft: '/icons/rotate-left.svg',
48
+ rotateRight: '/icons/rotate-right.svg',
49
+ download: '/icons/download.svg',
50
+ toggleList: '/icons/toggle-list.svg',
51
+ selectArrow: '/icons/select-arrow.svg',
52
+ texture: 'none',
53
53
  };
54
54
 
55
+ const MultiViewerExample = () => (
56
+ <PdfMultiViewer
57
+ pdfs={pdfs}
58
+ workerSrc={workerSrc}
59
+ icons={icons}
60
+ rendererIcons={icons}
61
+ initialLoadIndex={1}
62
+ i18nData={{
63
+ download: 'Download',
64
+ scaleDown: 'Scale down',
65
+ scaleUp: 'Scale up',
66
+ }}
67
+ />
68
+ );
69
+
55
70
  export default MultiViewerExample;
56
71
  ```
57
72
 
58
- Example Usage Renderer (Typescript)
73
+ #### PdfRenderer integration
59
74
 
60
- ```typescript
61
- import React, { FC, useState, useEffect } from 'react';
62
- import { PdfRenderer, PdfjsLib, PDFDocumentProxy } from 'react-pdfjs-multi';
75
+ When building your own viewer, assign the worker once and listen to the `pdfChangeHook` if you need to cache zoom/rotation/scroll positions manually.
76
+
77
+ ```tsx
78
+ import React, { FC, useEffect, useState } from 'react';
79
+ import {
80
+ PdfRenderer,
81
+ PdfjsLib,
82
+ type PDFDocumentProxy,
83
+ type RendererDocumentPosition,
84
+ } from 'react-pdfjs-multi';
63
85
  import workerSrc from 'react-pdfjs-multi/dist/pdf.worker.min.mjs?url';
64
86
 
65
87
  PdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;
@@ -67,21 +89,25 @@ PdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;
67
89
  const RendererExample: FC = () => {
68
90
  const [pdfDoc, setPdfDoc] = useState<PDFDocumentProxy>();
69
91
 
92
+ const logPosition = (index: string, position: RendererDocumentPosition) => {
93
+ console.log('document position', index, position);
94
+ };
95
+
70
96
  useEffect(() => {
71
- const getPdfDoc = async () => {
97
+ const load = async () => {
72
98
  const doc = await PdfjsLib.getDocument({
73
- url: 'pdfs/compressed.tracemonkey-pldi-09.pdf',
99
+ url: '/pdfs/sample-a.pdf',
74
100
  }).promise;
75
101
 
76
102
  setPdfDoc(doc);
77
103
  };
78
104
 
79
- getPdfDoc();
105
+ load();
80
106
  }, []);
81
107
 
82
108
  if (!pdfDoc) return null;
83
109
 
84
- return <PdfRenderer pdfDoc={pdfDoc} downloadBtn={false} />;
110
+ return <PdfRenderer pdfDoc={pdfDoc} downloadBtn pdfChangeHook={logPosition} />;
85
111
  };
86
112
 
87
113
  export default RendererExample;
@@ -91,14 +117,15 @@ export default RendererExample;
91
117
 
92
118
  A minimal workspace example lives at `apps/example`.
93
119
 
120
+ - `apps/example/src/examples/DefaultExample.tsx`
121
+ - `apps/example/src/examples/ContrastExample.tsx` + `ContrastExample.css`
122
+
94
123
  ```bash
95
124
  pnpm install
96
125
  pnpm start
97
126
  pnpm dev:example
98
127
  ```
99
128
 
100
- Run `pnpm start` and `pnpm dev:example` in separate terminals during development.
101
-
102
129
  ### Styling
103
130
 
104
131
  This library ships with optional default styles in
@@ -119,6 +146,70 @@ Example override:
119
146
  }
120
147
  ```
121
148
 
149
+ #### Theming recipe (example)
150
+
151
+ Here is a compact “high-contrast” pattern similar to the example app. It uses
152
+ icon overrides, CSS variables, and a scoped theme class:
153
+
154
+ ```tsx
155
+ import React from 'react';
156
+ import type { IconConfig } from 'react-pdfjs-multi';
157
+ import { PdfMultiViewer } from 'react-pdfjs-multi';
158
+
159
+ const icons: IconConfig = {
160
+ zoomIn: '/icons/zoom-in.svg',
161
+ zoomOut: '/icons/zoom-out.svg',
162
+ rotateLeft: '/icons/rotate-left.svg',
163
+ rotateRight: '/icons/rotate-right.svg',
164
+ download: '/icons/download.svg',
165
+ toggleList: '/icons/toggle-list.svg',
166
+ selectArrow: '/icons/select-arrow.svg',
167
+ };
168
+
169
+ const viewerStyle = {
170
+ '--pdfjs-multi-bg': '#0a0f1c',
171
+ '--pdfjs-multi-texture': 'none',
172
+ '--pdfjs-multi-text': '#e2e8f0',
173
+ '--pdfjs-multi-surface': 'rgba(15, 23, 42, 0.9)',
174
+ '--pdfjs-multi-surface-active': 'rgba(30, 41, 59, 0.92)',
175
+ '--pdfjs-multi-muted-text': '#94a3b8',
176
+ } as const;
177
+
178
+ const rendererStyle = {
179
+ '--pdfjs-multi-controls-bg': '#0f172a',
180
+ '--pdfjs-multi-controls-text': '#f8fafc',
181
+ '--pdfjs-multi-control-icon-size': '18px',
182
+ '--pdfjs-multi-select-text': '#f8fafc',
183
+ } as const;
184
+
185
+ const HighContrastViewer = () => (
186
+ <div className="theme-contrast">
187
+ <PdfMultiViewer
188
+ pdfs={['/pdfs/sample-a.pdf', '/pdfs/sample-b.pdf']}
189
+ icons={icons}
190
+ rendererIcons={icons}
191
+ style={viewerStyle}
192
+ rendererStyle={rendererStyle}
193
+ />
194
+ </div>
195
+ );
196
+ ```
197
+
198
+ ```css
199
+ .theme-contrast .renderer-controls {
200
+ /* renderer-controls defines its own icon vars, so inherit in themed skins */
201
+ --pdfjs-multi-control-icon-zoom-out: inherit;
202
+ --pdfjs-multi-control-icon-zoom-in: inherit;
203
+ --pdfjs-multi-control-icon-rotate-left: inherit;
204
+ --pdfjs-multi-control-icon-rotate-right: inherit;
205
+ --pdfjs-multi-control-icon-download: inherit;
206
+ }
207
+
208
+ .theme-contrast .dropdown-toolbar-container {
209
+ --pdfjs-multi-select-icon: inherit;
210
+ }
211
+ ```
212
+
122
213
  Available variables (non-exhaustive):
123
214
 
124
215
  | Scope | Variable | Default | Purpose |
@@ -166,24 +257,35 @@ const icons: IconConfig = {
166
257
  };
167
258
  ```
168
259
 
260
+ If you want the same icon set applied to the renderer controls, pass
261
+ `rendererIcons` to `PdfMultiViewer` (or use `icons` directly on `PdfRenderer`).
262
+
169
263
  ### PdfMultiViewer
170
264
 
171
- The MultiViewer allows you to pass an array of source strings or an object definition and it lazy-loads PDFs by default, showing the renderer as soon as the active PDF is loaded.
265
+ The MultiViewer allows you to pass an array of source strings or objects (optionally with a custom `title`) and it lazy-loads PDFs by default, showing the renderer as soon as the active PDF is loaded.
266
+ The list is guarded by the toggle in the option bar; on widths between ~330px and ~667px it switches into an overlay so the renderer keeps the extra space, and selecting a document when the list is overlaid closes it automatically. The viewer also records zoom, rotation, and scroll positions per document via the embedded `pdfChangeHook`, so revisiting a PDF restores the position you left it in.
172
267
 
173
268
  Props:
174
269
 
175
270
  | Name | Required | Default | Type | Description |
176
271
  | --------------- | -------- | ------- | --------------- | -------------------------------------------------------------- |
177
- | pdfs | true | | {array} | An array of strings or objects |
272
+ | pdfs | true | | {array} | Strings or `{ source, title? }` objects for each PDF |
178
273
  | autoZoom | | true | {boolean} | enables/disables autoZoom on component mount and window resize |
274
+ | className | | | {string} | Adds a class to the outer viewer container |
179
275
  | controls | | true | {boolean} | enables/disables controls to e.g. change renderer zoom |
180
276
  | icons | | | {IconConfig} | Override default icons and texture |
277
+ | rendererIcons | | | {IconConfig} | Override renderer control icons |
278
+ | rendererClassName | | | {string} | Adds a class to the renderer container |
279
+ | rendererStyle | | | {CSSProperties} | Inline styles for the renderer container |
181
280
  | i18nData | | {}\* | {I18nData} | An object of translated strings, default language is en |
182
281
  | startIndex | | 0 | {number} | first pdf to display using array index |
183
282
  | lazyLoad | | true | {boolean} | load only the active PDF until a list item is selected |
184
283
  | initialLoadIndex| | startIndex | {number|string} | which PDF to prefetch on mount when lazyLoad is enabled |
284
+ | style | | | {CSSProperties} | Inline styles for the outer viewer container |
185
285
  | workerSrc | | | {string} | pdf.js worker URL |
186
286
 
287
+ When `lazyLoad` is enabled (the default), you can use `initialLoadIndex` to prime a different PDF than the one shown first, and `PdfMultiViewer` already passes its own `pdfChangeHook` to `PdfRenderer` so zoom/rotation/scroll state is cached automatically; you only need to provide your own hook if you want that data for something else.
288
+
187
289
  ### i18n
188
290
 
189
291
  To be able to use different i18n libraries eg. i18next or react-intl you can pass an i18n object with translated strings to the component.
@@ -216,10 +318,12 @@ Props:
216
318
  | ------------- | -------- | ------- | ------------------ | -------------------------------------------------------------- |
217
319
  | pdfDoc | true | | {PDFDocumentProxy} | A proxy of the pdf document to display |
218
320
  | autoZoom | | true | {boolean} | enables/disables autoZoom on component mount and window resize |
321
+ | className | | | {string} | Adds a class to the renderer container |
219
322
  | controls | | true | {boolean} | enables/disables controls to e.g. change renderer zoom |
220
323
  | downloadBtn | | true | {boolean} | enables/disables download button |
221
324
  | icons | | | {IconConfig} | Override default icons and texture |
222
325
  | i18nData | | {}\* | {I18nDataRenderer} | An object of translated strings, default language is en |
326
+ | style | | | {CSSProperties} | Inline styles for the renderer container |
223
327
  | zoom | | null | {number} | Initial Zoom |
224
328
  | rotation | | null | {number} | Initial Rotation |
225
329
  | scrollTop | | null | {number} | Initial ScrollTop |
@@ -228,3 +332,4 @@ Props:
228
332
  | pdfChangeHook | | null | {func} | Callback function which gets a position object |
229
333
 
230
334
  [1]: https://mozilla.github.io/pdf.js/
335
+ [2]: https://optimisticupdate.github.io/react-pdfjs-multi/
@@ -1,12 +1,18 @@
1
+ import type { CSSProperties } from 'react';
1
2
  import '@/components/PdfMultiViewer/PdfMultiViewer.css';
2
3
  import { type I18nData, type PdfSource } from '@/components/PdfMultiViewer/usePdfMultiViewer';
3
4
  import type { IconConfig } from '@/types/iconConfig';
4
5
  type DefaultProps = {
5
6
  autoZoom?: boolean;
7
+ className?: string;
6
8
  controls?: boolean;
7
9
  icons?: IconConfig;
8
10
  lazyLoad?: boolean;
9
11
  initialLoadIndex?: string | number;
12
+ rendererIcons?: IconConfig;
13
+ rendererClassName?: string;
14
+ rendererStyle?: CSSProperties;
15
+ style?: CSSProperties;
10
16
  startIndex?: string;
11
17
  i18nData?: I18nData;
12
18
  workerSrc?: string;
@@ -14,6 +20,6 @@ type DefaultProps = {
14
20
  type Props = {
15
21
  pdfs: PdfSource[];
16
22
  } & Partial<DefaultProps>;
17
- declare const PdfMultiViewer: ({ pdfs, autoZoom, controls, icons, lazyLoad, initialLoadIndex, startIndex, i18nData, workerSrc, }: Props) => import("react/jsx-runtime").JSX.Element;
23
+ declare const PdfMultiViewer: ({ pdfs, autoZoom, className, controls, icons, lazyLoad, initialLoadIndex, rendererIcons, rendererClassName, rendererStyle, style, startIndex, i18nData, workerSrc, }: Props) => import("react/jsx-runtime").JSX.Element;
18
24
  export default PdfMultiViewer;
19
25
  export type { I18nData };
@@ -1,9 +1,11 @@
1
1
  import type { CSSProperties, RefObject } from 'react';
2
2
  import type { I18nData, PdfFile } from '@/components/PdfMultiViewer/usePdfMultiViewer';
3
3
  import type { RendererDocumentPosition } from '@/components/PdfRenderer/usePdfRenderer';
4
+ import type { IconConfig } from '@/types/iconConfig';
4
5
  type Props = {
5
6
  activeIndex: string;
6
7
  autoZoom: boolean;
8
+ className?: string;
7
9
  controls: boolean;
8
10
  files: PdfFile[];
9
11
  iconStyles?: CSSProperties;
@@ -11,10 +13,13 @@ type Props = {
11
13
  listVisible: boolean;
12
14
  overlayMode: boolean;
13
15
  pdfToShow?: PdfFile;
16
+ rendererIcons?: IconConfig;
17
+ rendererClassName?: string;
18
+ rendererStyle?: CSSProperties;
14
19
  viewerContainerRef: RefObject<HTMLDivElement>;
15
20
  onRememberPosition: (index: string, position: RendererDocumentPosition) => void;
16
21
  onSelectPdf: (nextIndex: string, file: PdfFile) => () => void;
17
22
  onToggleList: () => void;
18
23
  };
19
- declare const PdfMultiViewerView: ({ activeIndex, autoZoom, controls, files, iconStyles, i18nData, listVisible, overlayMode, pdfToShow, viewerContainerRef, onRememberPosition, onSelectPdf, onToggleList, }: Props) => import("react/jsx-runtime").JSX.Element;
24
+ declare const PdfMultiViewerView: ({ activeIndex, autoZoom, className, controls, files, iconStyles, i18nData, listVisible, overlayMode, pdfToShow, rendererIcons, rendererClassName, rendererStyle, viewerContainerRef, onRememberPosition, onSelectPdf, onToggleList, }: Props) => import("react/jsx-runtime").JSX.Element;
20
25
  export default PdfMultiViewerView;
@@ -2,7 +2,7 @@ import type { PDFDocumentProxy } from 'pdfjs-dist';
2
2
  import type { RendererDocumentPosition } from '@/components/PdfRenderer/usePdfRenderer';
3
3
  import type { I18nDataRenderer } from '@/contexts';
4
4
  export type PdfDefinition = {
5
- title: string;
5
+ title?: string;
6
6
  source: string;
7
7
  };
8
8
  export type PdfSource = string | PdfDefinition;
@@ -35,7 +35,7 @@ export declare const usePdfMultiViewer: ({ pdfs, startIndex, i18nData, lazyLoad,
35
35
  i18nData: I18nData;
36
36
  listVisible: boolean;
37
37
  overlayMode: boolean;
38
- pdfToShow: PdfFile;
38
+ pdfToShow: PdfFile | undefined;
39
39
  rememberPosition: (index: string, position: RendererDocumentPosition) => void;
40
40
  selectPdf: (nextIndex: string, file: PdfFile) => () => void;
41
41
  toggleList: () => void;
@@ -1,5 +1,6 @@
1
1
  import type { PDFDocumentProxy } from 'pdfjs-dist';
2
2
  import type { PDFViewer } from 'pdfjs-dist/web/pdf_viewer.mjs';
3
+ import type { CSSProperties } from 'react';
3
4
  import 'pdfjs-dist/web/pdf_viewer.css';
4
5
  import '@/components/PdfRenderer/PdfRenderer.css';
5
6
  import { type PdfChangeHook } from '@/components/PdfRenderer/usePdfRenderer';
@@ -9,11 +10,13 @@ export type { RendererDocumentPosition } from '@/components/PdfRenderer/usePdfRe
9
10
  type DefaultProps = {
10
11
  activeIndex?: string;
11
12
  autoZoom?: boolean;
13
+ className?: string;
12
14
  controls?: boolean;
13
15
  downloadBtn: boolean;
14
16
  icons?: IconConfig;
15
17
  i18nData?: I18nDataRenderer;
16
18
  pdfChangeHook?: PdfChangeHook | null;
19
+ style?: CSSProperties;
17
20
  zoom?: number;
18
21
  rotation?: number;
19
22
  scrollTop?: number | null;
@@ -1,7 +1,9 @@
1
+ import type { CSSProperties } from 'react';
1
2
  import '@/components/PdfRenderer/PdfRendererControls.css';
2
3
  type Props = {
3
4
  autoZoom?: boolean;
4
5
  downloadBtn?: boolean;
6
+ iconStyles?: CSSProperties;
5
7
  onDownload: () => void;
6
8
  onZoomIn: () => void;
7
9
  onZoomOut: () => void;
@@ -10,5 +12,5 @@ type Props = {
10
12
  scale: number;
11
13
  setScale: (scale: number) => void;
12
14
  };
13
- declare const PdfControls: ({ autoZoom, downloadBtn, onDownload, onZoomIn, onZoomOut, onRotateRight, onRotateLeft, scale, setScale, }: Props) => import("react/jsx-runtime").JSX.Element;
15
+ declare const PdfControls: ({ autoZoom, downloadBtn, iconStyles, onDownload, onZoomIn, onZoomOut, onRotateRight, onRotateLeft, scale, setScale, }: Props) => import("react/jsx-runtime").JSX.Element;
14
16
  export default PdfControls;
@@ -2,6 +2,7 @@ import type { CSSProperties, RefObject } from 'react';
2
2
  import { type I18nDataRenderer } from '@/contexts';
3
3
  type Props = {
4
4
  autoZoom: boolean;
5
+ className?: string;
5
6
  containerRef: RefObject<HTMLDivElement>;
6
7
  controls: boolean;
7
8
  downloadBtn: boolean;
@@ -16,5 +17,5 @@ type Props = {
16
17
  onZoomIn: () => void;
17
18
  onZoomOut: () => void;
18
19
  };
19
- declare const PdfRendererView: ({ autoZoom, containerRef, controls, downloadBtn, iconStyles, i18nData, isLoading, scale, setScale, onDownload, onRotateLeft, onRotateRight, onZoomIn, onZoomOut, }: Props) => import("react/jsx-runtime").JSX.Element;
20
+ declare const PdfRendererView: ({ autoZoom, className, containerRef, controls, downloadBtn, iconStyles, i18nData, isLoading, scale, setScale, onDownload, onRotateLeft, onRotateRight, onZoomIn, onZoomOut, }: Props) => import("react/jsx-runtime").JSX.Element;
20
21
  export default PdfRendererView;