@react-pdf-kit/viewer 2.7.4-rc.0 → 2.7.4-rc.2

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
@@ -32,6 +32,10 @@
32
32
  - **Modern Browser Compatibility**: The React PDF Viewer components seamlessly across modern browsers, eliminating compatibility headaches.
33
33
  - **Active Development & Support**: With regular updates and a responsive support team, React PDF Kit evolves to meet developer needs.
34
34
 
35
+ <p align="center">
36
+ <img src="https://github.com/user-attachments/assets/8803229a-2f59-48d1-aecc-628ae759862f" alt="React PDF Kit demo">
37
+ </p>
38
+
35
39
  # 📜 Background
36
40
 
37
41
  As developers ourselves, we faced many issues such as browser incompatibility and customizability while trying to render a PDF document or working with PDF libraries. Having faced issues using PDF libraries, we want the solution to be flexible for React.js developers and teams. More importantly, the technical document must be easy to use!
@@ -78,23 +82,13 @@ As newer PDF.js versions rely on more modern browser APIs, minimum supported bro
78
82
 
79
83
  React PDF Kit v2.0.0 defaults to PDF.js `5.4.530`.
80
84
 
81
- | Chrome | Firefox | Edge | Safari | Safari iOS | Chrome Android |
82
- | ------ | ------- | ---- | ------ | ---------- | -------------- |
83
- | 126+ | 126+ | 126+ | 18.4+ | 18.4+ | 126+ |
84
-
85
- <Aside>
86
- It's currently not recommended to use a PDF.js worker version beyond `5.4.530` because it will support fewer browser versions.
87
- </Aside>
88
-
89
- #### Using PDF.js 4.10.38
85
+ | Configuration | Chrome | Firefox | Edge | Safari | Safari iOS | Chrome Android |
86
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ------- | ---- | ------ | ---------- | -------------- |
87
+ | React PDF Kit v2 | 126+ | 126+ | 126+ | 18.4+ | 18.4+ | 126+ |
88
+ | [React PDF Kit v2 + Polyfills](https://www.react-pdf-kit.dev/docs/usage-guide/legacy-browser-support.html#polyfills-library?utm_source=github&utm_medium=referral) | 119+ | 121+ | 119+ | 18.3+ | 18.3+ | 119+ |
89
+ | [React PDF Kit v2 + Polyfills + Legacy PDF.js Worker](https://www.react-pdf-kit.dev/docs/usage-guide/legacy-browser-support.html#override-the-pdfjs-worker?utm_source=github&utm_medium=referral) | 101+ | 101+ | 101+ | 16.5+ | 16.5+ | 101+ |
90
90
 
91
- If you need broader browser compatibility, you can continue using PDF.js `4.10.38`, which supports:
92
-
93
- | Chrome | Firefox | Edge | Safari | Safari iOS | Chrome Android |
94
- | ------ | ------- | ---- | ------ | ---------- | -------------- |
95
- | 119+ | 115+ | 115+ | 17.4+ | 17.4+ | 126+ |
96
-
97
- To change the version of PDF.js used, refer to [Dependency Override](https://docs.react-pdf-kit.dev/usage-guide/overriding-dependency?utm_source=github&utm_medium=referral) guide.
91
+ To change the version of PDF.js used, refer to [Dependency Override](https://www.react-pdf-kit.dev/docs/usage-guide/overriding-dependency?utm_source=github&utm_medium=referral) guide.
98
92
 
99
93
  ## 2. Install the Package
100
94
 
@@ -133,25 +127,33 @@ yarn add @react-pdf-kit/viewer
133
127
  pnpm add @react-pdf-kit/viewer
134
128
  ```
135
129
 
136
- For more information on how to use different package managers, please visit our [installation guide](https://docs.react-pdf-kit.dev/introduction/getting-started/#installation?utm_source=github&utm_medium=referral).
130
+ For more information on how to use different package managers, please visit our [installation guide](https://www.react-pdf-kit.dev/docs/introduction/getting-started/#installation?utm_source=github&utm_medium=referral).
137
131
 
138
132
  ## 3. Import and Use the Component
139
133
 
140
134
  The following structure demonstrates how to build a React PDF viewer by importing and assembling components. This modular approach gives you the flexibility to customize the viewer as needed.
141
135
 
142
136
  ```tsx
143
- <RPConfig> {/* Configuration license and pdfjs-dist worker */}
144
- <RPTheme> {/* Theme customization (optional) */}
145
- <RPProvider> {/* Viewer context provider */}
146
- <RPLayout toolbar> {/* Provide the default toolbar structure */}
147
- <RPPages /> {/* Render the actual PDF content */}
137
+ <RPConfig>
138
+ {' '}
139
+ {/* Configuration license and pdfjs-dist worker */}
140
+ <RPTheme>
141
+ {' '}
142
+ {/* Theme customization (optional) */}
143
+ <RPProvider>
144
+ {' '}
145
+ {/* Viewer context provider */}
146
+ <RPLayout toolbar>
147
+ {' '}
148
+ {/* Provide the default toolbar structure */}
149
+ <RPPages /> {/* Render the actual PDF content */}
148
150
  </RPLayout>
149
151
  </RPProvider>
150
152
  </RPTheme>
151
153
  </RPConfig>
152
154
  ```
153
155
 
154
- _Remark: For more information on each component, please refer to [Component](https://docs.react-pdf-kit.dev/components/overview?utm_source=github&utm_medium=referral)._
156
+ _Remark: For more information on each component, please refer to [Component](https://www.react-pdf-kit.dev/docs/components/overview?utm_source=github&utm_medium=referral)._
155
157
 
156
158
  ### Basic Usage
157
159
 
@@ -176,7 +178,7 @@ const App = () => {
176
178
  export default App
177
179
  ```
178
180
 
179
- The PDF viewer will automatically adjust to fit its container's dimensions. You can control the size by setting the `style` prop on `RPLayout`. For more information on using React PDF, visit our [basic usage guide](https://docs.react-pdf-kit.dev/introduction/basic-usage?utm_source=github&utm_medium=referral)
181
+ The PDF viewer will automatically adjust to fit its container's dimensions. You can control the size by setting the `style` prop on `RPLayout`. For more information on using React PDF, visit our [basic usage guide](https://www.react-pdf-kit.dev/docs/introduction/basic-usage?utm_source=github&utm_medium=referral)
180
182
 
181
183
  You may also check out our [Starter Toolkit](#pushpin-starter-toolkit) for examples to get you started.
182
184
 
@@ -186,6 +188,17 @@ To enhance React PDF Kit further, we offer built-in hooks and props that let you
186
188
 
187
189
  For detailed usage, refer to our [Documentation][reactpdf-docs].
188
190
 
191
+ ### 5. Localization
192
+
193
+ React PDF Kit supports multiple languages out of the box. Pass a locale JSON file to `RPConfig` to translate all viewer text:
194
+
195
+ ```jsx
196
+ import zhCN from './localization/zh_CN.json'
197
+ ;<RPConfig localization={zhCN}>{/* ... */}</RPConfig>
198
+ ```
199
+
200
+ We ship locale files for English, Italian, Portuguese, Thai, and Chinese (Simplified). You can also create your own -- see the [Localization Guide](./localization/README.md) for the full list of translation keys and instructions on adding a new language. If you've created a locale we don't support yet, feel free to open a PR to share it with the community!
201
+
189
202
  # :pushpin: Starter Toolkit
190
203
 
191
204
  Here are some sample projects to get started on React PDF quickly:
@@ -215,7 +228,7 @@ Here are some sample projects to get started on React PDF quickly:
215
228
 
216
229
  # 📝 Changelog
217
230
 
218
- Check out our latest release [v2.0.0 (20 February 2026)](https://docs.react-pdf-kit.dev/introduction/changelog/#v200-20-february-2026?utm_source=github&utm_medium=referral)
231
+ Check out our latest release [v2.7.3 (9 July 2026)](https://www.react-pdf-kit.dev/docs/introduction/changelog/#v273-9-July-2026?utm_source=github&utm_medium=referral)
219
232
 
220
233
  # :raising_hand: Need Help?
221
234
 
@@ -230,10 +243,11 @@ If you would like to use React PDF commercially, please purchase a license from
230
243
  # Acknowledgement
231
244
 
232
245
  - [pdf.js](https://github.com/mozilla/pdf.js)
246
+ - [node-forge](https://github.com/digitalbazaar/forge)
233
247
  - [Img Shields](https://shields.io)
234
248
  - [React.js](https://reactjs.org/)
235
249
 
236
250
  [reactpdf]: https://www.react-pdf-kit.dev/?utm_source=github&utm_medium=referral
237
- [reactpdf-docs]: https://docs.react-pdf-kit.dev/?utm_source=github&utm_medium=referral
251
+ [reactpdf-docs]: https://www.react-pdf-kit.dev/docs/?utm_source=github&utm_medium=referral
238
252
  [npm]: https://www.npmjs.com/package/@react-pdf-kit/viewer
239
253
  [twitter]: https://www.x.com/ReactPDF
@@ -1,6 +1,8 @@
1
1
  import { NormalizedKeyword } from './types';
2
2
  export declare const EMPTY_KEYWORD_REGEXP: NormalizedKeyword;
3
+ export declare const DOCS_URL = "https://www.react-pdf-kit.dev/docs";
3
4
  export declare const ORGANIZATION_ALLOWED_FEATURES_MESSAGE = "This feature is only available for the Organization license";
4
5
  export declare const INVALID_OR_CORRUPTED_PDF_MESSAGE = "Invalid or corrupted PDF file.";
5
6
  export declare const BROWSER_NOT_SUPPORTED_MESSAGE = "React PDF Kit is unable to render on this browser.";
6
7
  export declare const WASM_URL_REQUIRED_MESSAGE = "This PDF uses JPEG 2000 images and requires pdf.js WASM assets. Please set wasmUrl in RPConfig.";
8
+ export declare const WASM_URL_REQUIRED_CONSOLE_MESSAGE = "This PDF uses JPEG 2000 images and requires pdf.js WASM assets. Please set wasmUrl in RPConfig. Learn more: https://www.react-pdf-kit.dev/docs/components/rp-config";
@@ -3,6 +3,6 @@ var e = {
3
3
  keyword: "",
4
4
  regExp: /* @__PURE__ */ RegExp(" "),
5
5
  wholeWords: !1
6
- }, t = "This feature is only available for the Organization license", n = "Invalid or corrupted PDF file.", r = "React PDF Kit is unable to render on this browser.", i = "This PDF uses JPEG 2000 images and requires pdf.js WASM assets. Please set wasmUrl in RPConfig.";
6
+ }, t = "https://www.react-pdf-kit.dev/docs", n = "This feature is only available for the Organization license", r = "Invalid or corrupted PDF file.", i = "React PDF Kit is unable to render on this browser.", a = "This PDF uses JPEG 2000 images and requires pdf.js WASM assets. Please set wasmUrl in RPConfig.", o = `${a} Learn more: ${t}/components/rp-config`;
7
7
  //#endregion
8
- export { r as BROWSER_NOT_SUPPORTED_MESSAGE, e as EMPTY_KEYWORD_REGEXP, n as INVALID_OR_CORRUPTED_PDF_MESSAGE, t as ORGANIZATION_ALLOWED_FEATURES_MESSAGE, i as WASM_URL_REQUIRED_MESSAGE };
8
+ export { i as BROWSER_NOT_SUPPORTED_MESSAGE, t as DOCS_URL, e as EMPTY_KEYWORD_REGEXP, r as INVALID_OR_CORRUPTED_PDF_MESSAGE, n as ORGANIZATION_ALLOWED_FEATURES_MESSAGE, o as WASM_URL_REQUIRED_CONSOLE_MESSAGE, a as WASM_URL_REQUIRED_MESSAGE };
@@ -3,7 +3,7 @@ import { LicenseType as t } from "../types.js";
3
3
  import { appConsole as n } from "../appConsole.js";
4
4
  import { useCallback as r, useEffect as i, useState as a } from "react";
5
5
  //#region lib/utils/hooks/useLicense.ts
6
- var o = /* @__PURE__ */ new Date("2026-07-15T11:17:10.649Z"), s = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvIokvErJ0Fctu0jduSAx\ngr+5Har/VSuZLlOunS28hnlqqA+OF1apHL7RYkjBosS15yvviYdLrVWYHpHnoY4b\nHLQ9I6YX6FMB9T/VbB4xLdVdKvfi8r49aTScl5EKuSpgpPgz2VSJTfvVGcRuth/Y\nBm7PPGYdL2l2gvKDxchmmsHFPukGki9L4JOUeIVX0GXAxabENckaEH/iC1NZhX+W\nvXnpHeHuIIKlZ16LSivXNgo6BH2Z3GFdg4G3cAaXr6qNP8fsacYNqv2SpTW1viFD\nvzcGRabN25gpJAp9/syeScefWH3OiJY1lmw88oTiJbjIoiq6AkPhfn3G9mF54nvR\nkwIDAQAB\n-----END PUBLIC KEY-----", c = "Please visit https://app.react-pdf-kit.dev to generate a new license key.", l = {
6
+ var o = /* @__PURE__ */ new Date("2026-07-22T07:16:44.906Z"), s = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvIokvErJ0Fctu0jduSAx\ngr+5Har/VSuZLlOunS28hnlqqA+OF1apHL7RYkjBosS15yvviYdLrVWYHpHnoY4b\nHLQ9I6YX6FMB9T/VbB4xLdVdKvfi8r49aTScl5EKuSpgpPgz2VSJTfvVGcRuth/Y\nBm7PPGYdL2l2gvKDxchmmsHFPukGki9L4JOUeIVX0GXAxabENckaEH/iC1NZhX+W\nvXnpHeHuIIKlZ16LSivXNgo6BH2Z3GFdg4G3cAaXr6qNP8fsacYNqv2SpTW1viFD\nvzcGRabN25gpJAp9/syeScefWH3OiJY1lmw88oTiJbjIoiq6AkPhfn3G9mF54nvR\nkwIDAQAB\n-----END PUBLIC KEY-----", c = "Please visit https://app.react-pdf-kit.dev to generate a new license key.", l = {
7
7
  invalidLicense: `You are currently using without a valid license. ${c}`,
8
8
  mismatchedDomain: `Your license key is not valid for the current domain / IP. ${c}`,
9
9
  expired: `Your license key has expired. ${c}`,
@@ -2,87 +2,88 @@
2
2
  import { ErrorType as e } from "../types.js";
3
3
  import { getThumbnailViewport as t } from "../getThumbnailViewport.js";
4
4
  import { useConfigContext as n } from "../../contexts/ConfigContext.js";
5
- import { useDocumentPasswordContext as r } from "../../contexts/DocumentPasswordContext.js";
6
- import { BROWSER_NOT_SUPPORTED_MESSAGE as i, INVALID_OR_CORRUPTED_PDF_MESSAGE as a, WASM_URL_REQUIRED_MESSAGE as o } from "../const.js";
7
- import { useEffect as s, useRef as c, useState as l } from "react";
8
- import * as u from "pdfjs-dist";
5
+ import { appConsole as r } from "../appConsole.js";
6
+ import { useDocumentPasswordContext as i } from "../../contexts/DocumentPasswordContext.js";
7
+ import { BROWSER_NOT_SUPPORTED_MESSAGE as a, INVALID_OR_CORRUPTED_PDF_MESSAGE as o, WASM_URL_REQUIRED_CONSOLE_MESSAGE as s, WASM_URL_REQUIRED_MESSAGE as c } from "../const.js";
8
+ import { useEffect as l, useRef as u, useState as d } from "react";
9
+ import * as f from "pdfjs-dist";
9
10
  //#region lib/utils/hooks/useLoadPdf.ts
10
- var d = new TextEncoder().encode("/JPXDecode");
11
- function f(e) {
12
- return e.some((t, n) => t === d[0] ? d.every((t, r) => e[n + r] === t) : !1);
11
+ var p = new TextEncoder().encode("/JPXDecode");
12
+ function m(e) {
13
+ return e.some((t, n) => t === p[0] ? p.every((t, r) => e[n + r] === t) : !1);
13
14
  }
14
- function p(e) {
15
- let t = Error(a);
15
+ function h(e) {
16
+ let t = Error(o);
16
17
  return t.cause = e, t;
17
18
  }
18
- function m() {
19
- return Error(o);
19
+ function g() {
20
+ return Error(c);
20
21
  }
21
- function h(e) {
22
- let t = Error(i);
22
+ function _(e) {
23
+ let t = Error(a);
23
24
  return t.cause = e, t;
24
25
  }
25
- var g = (i, a, o = {}) => {
26
- let [d, g] = l(), { workerUrlAdded: _, wasmUrl: v } = n(), [y, b] = l(/* @__PURE__ */ new Map()), x = c(), [S, C] = l(0), [w, T] = l(!1), [E, D] = l(), { password: O, passwordError: k, setPasswordError: A, passwordRequired: j, setPasswordRequired: M } = r(), { onLoadError: N, onLoaded: P, onLoadProgress: F, disableAutoFetch: I, disableStream: L, rangeChunkSize: R, withCredentials: z, httpHeaders: B } = o;
27
- return s(() => {
28
- F && F(S);
29
- }, [S, F]), s(() => {
30
- if (!_ || !i) return;
31
- C(0), D(void 0), x.current = Date.now();
32
- let t = x.current, n = {
33
- url: i,
34
- cMapPacked: a?.isCompressed ?? !0,
35
- ...a?.url && { cMapUrl: a.url },
36
- ...O && { password: O },
37
- ...I !== void 0 && { disableAutoFetch: I },
38
- ...L !== void 0 && { disableStream: L },
39
- ...R !== void 0 && { rangeChunkSize: R },
40
- ...z !== void 0 && { withCredentials: z },
41
- ...B !== void 0 && { httpHeaders: B },
42
- ...v && { wasmUrl: v },
43
- verbosity: u.VerbosityLevel.ERRORS
26
+ var v = (a, o, c = {}) => {
27
+ let [p, v] = d(), { workerUrlAdded: y, wasmUrl: b } = n(), [x, S] = d(/* @__PURE__ */ new Map()), C = u(), [w, T] = d(0), [E, D] = d(!1), [O, k] = d(), { password: A, passwordError: j, setPasswordError: M, passwordRequired: N, setPasswordRequired: P } = i(), { onLoadError: F, onLoaded: I, onLoadProgress: L, disableAutoFetch: R, disableStream: z, rangeChunkSize: B, withCredentials: V, httpHeaders: H } = c;
28
+ return l(() => {
29
+ L && L(w);
30
+ }, [w, L]), l(() => {
31
+ if (!y || !a) return;
32
+ T(0), k(void 0), C.current = Date.now();
33
+ let t = C.current, n = {
34
+ url: a,
35
+ cMapPacked: o?.isCompressed ?? !0,
36
+ ...o?.url && { cMapUrl: o.url },
37
+ ...A && { password: A },
38
+ ...R !== void 0 && { disableAutoFetch: R },
39
+ ...z !== void 0 && { disableStream: z },
40
+ ...B !== void 0 && { rangeChunkSize: B },
41
+ ...V !== void 0 && { withCredentials: V },
42
+ ...H !== void 0 && { httpHeaders: H },
43
+ ...b && { wasmUrl: b },
44
+ verbosity: f.VerbosityLevel.ERRORS
44
45
  };
45
46
  try {
46
- let r = u.getDocument(n);
47
- r.onProgress = (e) => {
48
- if (t === x.current) {
47
+ let i = f.getDocument(n);
48
+ i.onProgress = (e) => {
49
+ if (t === C.current) {
49
50
  let { loaded: t, total: n } = e;
50
- C(n ? Math.min(100, Math.round(t / n * 100)) : 0);
51
+ T(n ? Math.min(100, Math.round(t / n * 100)) : 0);
51
52
  }
52
- }, T(!0), g(void 0);
53
- let i = r.promise.then(async (n) => !v && f(await n.getData()) ? (t === x.current && (g(void 0), D(e.WASM_URL_REQUIRED)), N?.(m()), n) : (t === x.current && (g(n), C(100)), P && P(n), M(!1), A(""), n)).catch((t) => {
53
+ }, D(!0), v(void 0);
54
+ let a = i.promise.then(async (n) => !b && m(await n.getData()) ? (t === C.current && (v(void 0), k(e.WASM_URL_REQUIRED)), r.error(s), F?.(g()), n) : (t === C.current && (v(n), T(100)), I && I(n), P(!1), M(""), n)).catch((t) => {
54
55
  if (t instanceof Error && t.name === "PasswordException") {
55
56
  let e = t.code;
56
- M(!0), e === u.PasswordResponses.INCORRECT_PASSWORD ? A("Incorrect password") : A(void 0);
57
- } else t instanceof Error && t.name === "InvalidPDFException" && O ? (M(!0), A("Incorrect password")) : t instanceof Error && t.name === "InvalidPDFException" ? (D(e.INVALID_OR_CORRUPTED_PDF), N?.(p(t))) : N && N(t);
57
+ P(!0), e === f.PasswordResponses.INCORRECT_PASSWORD ? M("Incorrect password") : M(void 0);
58
+ } else t instanceof Error && t.name === "InvalidPDFException" && A ? (P(!0), M("Incorrect password")) : t instanceof Error && t.name === "InvalidPDFException" ? (k(e.INVALID_OR_CORRUPTED_PDF), F?.(h(t))) : F && F(t);
58
59
  }).finally(() => {
59
- T(!1);
60
+ D(!1);
60
61
  });
61
62
  return () => {
62
- i.finally(() => {
63
- r.destroy();
63
+ a.finally(() => {
64
+ i.destroy();
64
65
  });
65
66
  };
66
67
  } catch (t) {
67
- D(e.NOT_SUPPORTED), N?.(h(t));
68
+ k(e.NOT_SUPPORTED), F?.(_(t));
68
69
  }
69
70
  }, [
70
- i,
71
- _,
72
- v,
73
- O,
74
- N,
75
- P
76
- ]), s(() => {
77
- if (j) return;
71
+ a,
72
+ y,
73
+ b,
74
+ A,
75
+ F,
76
+ I
77
+ ]), l(() => {
78
+ if (N) return;
78
79
  let n = /* @__PURE__ */ new Map();
79
- if (!d || w) {
80
- b(n);
80
+ if (!p || E) {
81
+ S(n);
81
82
  return;
82
83
  }
83
- let r = d.numPages, i = [];
84
+ let r = p.numPages, i = [];
84
85
  for (let e = 1; e <= r; e++) {
85
- let t = d.getPage(e);
86
+ let t = p.getPage(e);
86
87
  i.push(t);
87
88
  }
88
89
  Promise.allSettled(i).then((e) => {
@@ -96,24 +97,24 @@ var g = (i, a, o = {}) => {
96
97
  thumbnailScale: i,
97
98
  defaultRotation: a.rotation
98
99
  });
99
- }), b(n);
100
+ }), S(n);
100
101
  }).catch((t) => {
101
- g(void 0), D(e.INVALID_OR_CORRUPTED_PDF), N?.(p(t));
102
+ v(void 0), k(e.INVALID_OR_CORRUPTED_PDF), F?.(h(t));
102
103
  });
103
104
  }, [
104
- d,
105
- w,
106
- j,
107
- N
105
+ p,
106
+ E,
107
+ N,
108
+ F
108
109
  ]), {
109
- pdf: d,
110
- pages: y,
111
- loading: w,
112
- error: E,
113
- loadingProgress: S,
114
- passwordRequired: j,
115
- passwordError: k
110
+ pdf: p,
111
+ pages: x,
112
+ loading: E,
113
+ error: O,
114
+ loadingProgress: w,
115
+ passwordRequired: N,
116
+ passwordError: j
116
117
  };
117
118
  };
118
119
  //#endregion
119
- export { g as useLoadPdf };
120
+ export { v as useLoadPdf };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-pdf-kit/viewer",
3
- "version": "2.7.4-rc.0",
3
+ "version": "2.7.4-rc.2",
4
4
  "private": false,
5
5
  "description": "A react-pdf-viewer component for React and Next.js. Suitable for react-pdf document.",
6
6
  "keywords": [