├── public
├── logo192.png
├── logo512.png
├── files
│ └── PDFTRON_about.pdf
└── manifest.json
├── README.md
├── setupTests.js
├── src
├── App.css
├── index.css
├── reportWebVitals.js
├── App.test.jsx
├── index.tsx
├── App.tsx
└── logo.svg
├── LICENSE
├── tools
└── copy-webviewer-files.cjs
├── vite.config.js
├── .gitignore
├── CONTRIBUTING.md
├── index.html
└── package.json
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ApryseSDK/webviewer-react-sample/HEAD/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ApryseSDK/webviewer-react-sample/HEAD/public/logo512.png
--------------------------------------------------------------------------------
/public/files/PDFTRON_about.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ApryseSDK/webviewer-react-sample/HEAD/public/files/PDFTRON_about.pdf
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WebViewer - React sample
2 |
3 | ⚠️ This sample has been moved to the [webviewer-samples repo](https://github.com/ApryseSDK/webviewer-samples/tree/main/webviewer-react). ⚠️
--------------------------------------------------------------------------------
/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | width: 100%;
3 | height: 100%;
4 | display: flex;
5 | flex-direction: column;
6 | }
7 |
8 | .App .header {
9 | width: 100%;
10 | height: 60px;
11 | padding: 8px 8px 8px 16px;
12 | box-sizing: border-box;
13 | background: #00a5e4;
14 | font-size: 1.2em;
15 | line-height: 44px;
16 | color: white;
17 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2024 Apryse Systems Inc. All rights reserved.
2 | WebViewer UI project/codebase or any derived works is only permitted in solutions with an active commercial Apryse WebViewer license. For exact licensing terms refer to the commercial WebViewer license. For licensing, pricing, or product questions, Contact [Sales](https://apryse.com/form/contact-sales).
--------------------------------------------------------------------------------
/tools/copy-webviewer-files.cjs:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra');
2 |
3 | const copyFiles = async () => {
4 | try {
5 | await fs.copy('./node_modules/@pdftron/webviewer/public', './public/webviewer/lib');
6 | console.log('WebViewer files copied over successfully');
7 | } catch (err) {
8 | console.error(err);
9 | }
10 | };
11 |
12 | copyFiles();
13 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | html,
2 | body,
3 | #root {
4 | width: 100%;
5 | height: 100%;
6 | margin: 0;
7 | padding: 0;
8 | font-family: Arial, Helvetica, sans-serif;
9 | overflow: hidden;
10 | }
11 |
12 | .webviewer {
13 | flex: 1;
14 | margin: 8px;
15 | -webkit-box-shadow: 1px 1px 10px #999;
16 | box-shadow: 1px 1px 10px #999;
17 | box-sizing: border-box;
18 | height: calc(100% - 76px);
19 | }
--------------------------------------------------------------------------------
/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | server: {
8 | port: 3000,
9 | open: true,
10 | },
11 | test: {
12 | globals: true,
13 | environment: 'jsdom',
14 | setupFiles: '/setupTests.js',
15 | },
16 | build: {
17 | outDir: 'build',
18 | }
19 | });
20 |
--------------------------------------------------------------------------------
/src/App.test.jsx:
--------------------------------------------------------------------------------
1 | import { render, screen } from '@testing-library/react';
2 | import App from './App';
3 |
4 | // Mock fetch globally prventing the error by intercepting all fetch calls and returning mock data.
5 | global.fetch = vi.fn((url) =>
6 | Promise.resolve({
7 | text: () => Promise.resolve(`Mocked fetch content for URL: ${url}`),
8 | })
9 | );
10 |
11 | test('renders react sample', () => {
12 | render();
13 | const linkElement = screen.getByText(/react sample/i);
14 | expect(linkElement).toBeInTheDocument();
15 | });
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # WebViewer
4 | public/webviewer
5 |
6 | # dependencies
7 | /node_modules
8 | /.pnp
9 | .pnp.js
10 |
11 | # testing
12 | /coverage
13 |
14 | # production
15 | /build
16 |
17 | # misc
18 | .DS_Store
19 | .env.local
20 | .env.development.local
21 | .env.test.local
22 | .env.production.local
23 | package-lock.json
24 | /public/assets/webviewer/core
25 | /public/assets/webviewer/ui
26 |
27 | npm-debug.log*
28 | yarn-debug.log*
29 | yarn-error.log*
30 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 | import reportWebVitals from './reportWebVitals';
6 |
7 | const root = ReactDOM.createRoot(document.getElementById('root'));
8 | root.render(
9 |
10 | );
11 |
12 | // If you want to start measuring performance in your app, pass a function
13 | // to log results (for example: reportWebVitals(console.log))
14 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
15 | reportWebVitals();
16 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to WebViewer - React sample
2 |
3 | ## Issues
4 | 1. Check existing issues (open/closed) to avoid duplicates.
5 | 2. Be clear about what the problem is.
6 | 3. Make sure to paste error output or logs.
7 | 4. Code snapshot or demos on online code editor will be very helpful.
8 |
9 | ## Pull requests
10 | 1. Fork the repository.
11 | 2. Create a branch from `master`.
12 | 3. Update the source code using style guides described below.
13 | 4. Lint your code with `npm run lint`.
14 | 5. Commit and push the changes with descriptive messages.
15 | 6. Create a pull request to `master`.
16 |
17 | \* Please note that all pull requests should be tied to an issue, and all but the most trivial pull requests should be discussed before hand.
18 |
19 | ## Style guides
20 | - Tab indentation (size of 2 spaces).
21 | - `'` instead of `"`.
22 | - Curly braces for block statements.
23 | - 1TBS brace style.
24 | - Semicolon at the end of each statement.
25 | - Object shorthand for ES6.
26 | - Parenthesis around arrow function argument.
27 | - Minimum line breaks.
28 | - No `use strict`.
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
14 |
15 | React Sample
16 |
17 |
18 |
19 |
20 |
21 |
22 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webviewer-react-sample",
3 | "version": "1.0.0",
4 | "private": true,
5 | "type": "module",
6 | "dependencies": {
7 | "@pdftron/webviewer": "^11.0.0",
8 | "@testing-library/jest-dom": "^6.6.3",
9 | "@testing-library/react": "^16.1.0",
10 | "@testing-library/user-event": "^13.5.0",
11 | "@types/fs-extra": "^11.0.4",
12 | "fs-extra": "^11.2.0",
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0",
15 | "web-vitals": "^2.1.4"
16 | },
17 | "scripts": {
18 | "start": "vite",
19 | "build": "vite build",
20 | "lint": "eslint .",
21 | "preview": "vite preview",
22 | "test": "vitest",
23 | "postinstall": "node tools/copy-webviewer-files.cjs"
24 | },
25 | "eslintConfig": {
26 | "extends": [
27 | "react-app",
28 | "react-app/jest"
29 | ]
30 | },
31 | "browserslist": {
32 | "production": [
33 | ">0.2%",
34 | "not dead",
35 | "not op_mini all"
36 | ],
37 | "development": [
38 | "last 1 chrome version",
39 | "last 1 firefox version",
40 | "last 1 safari version"
41 | ]
42 | },
43 | "devDependencies": {
44 | "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
45 | "@vitejs/plugin-react": "^4.3.4",
46 | "jsdom": "^25.0.1",
47 | "vite": "^6.0.3",
48 | "vitest": "^2.1.8"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React, { useRef, useEffect } from 'react';
2 | import WebViewer from '@pdftron/webviewer';
3 | import './App.css';
4 |
5 | const App = () => {
6 | const viewer = useRef(null);
7 |
8 | // if using a class, equivalent of componentDidMount
9 | useEffect(() => {
10 | // If you prefer to use the Iframe implementation, you can replace this line with: WebViewer.Iframe(...)
11 | WebViewer.WebComponent(
12 | {
13 | path: '/webviewer/lib',
14 | initialDoc: '/files/PDFTRON_about.pdf',
15 | licenseKey: 'your_license_key', // sign up to get a free trial key at https://dev.apryse.com
16 | },
17 | viewer.current,
18 | ).then((instance) => {
19 | const { documentViewer, annotationManager, Annotations } = instance.Core;
20 |
21 | documentViewer.addEventListener('documentLoaded', () => {
22 | const rectangleAnnot = new Annotations.RectangleAnnotation({
23 | PageNumber: 1,
24 | // values are in page coordinates with (0, 0) in the top left
25 | X: 100,
26 | Y: 150,
27 | Width: 200,
28 | Height: 50,
29 | Author: annotationManager.getCurrentUser()
30 | });
31 |
32 | annotationManager.addAnnotation(rectangleAnnot);
33 | // need to draw the annotation otherwise it won't show up until the page is refreshed
34 | annotationManager.redrawAnnotation(rectangleAnnot);
35 | });
36 | });
37 | }, []);
38 |
39 | return (
40 |
41 |
React sample
42 |
43 |
44 | );
45 | };
46 |
47 | export default App;
48 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------