Skip to content

Commit 9ab8bb8

Browse files
committed
Added Readme.md file for PDF viewer component
1 parent 59df219 commit 9ab8bb8

File tree

1 file changed

+182
-0
lines changed
  • Client-Side Components/UI Pages/PDF viewer page in tsx

1 file changed

+182
-0
lines changed
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# 📄 PDF Viewer Component
2+
3+
A lightweight client-side **React PDF viewer** built with **pdf.js**, designed to render and display uploaded PDF files seamlessly inside your web app.
4+
5+
---
6+
7+
## 🚀 Features
8+
9+
***Client-side rendering** — No server dependency
10+
* 📚 **Multi-page support** — Renders every page dynamically
11+
* 🧠 **Efficient memory use** — Prevents redundant re-rendering
12+
* 🧩 **Easy integration** — Drop into any React or Next.js app
13+
* 🎨 **Customizable container** — Style with Tailwind or CSS
14+
15+
---
16+
17+
## 🧱 Tech Stack
18+
19+
* **React / Next.js** (client component)
20+
* **pdfjs-dist** (`pdf.js` library for parsing and rendering PDFs)
21+
* **TypeScript**
22+
23+
---
24+
25+
## 📦 Installation
26+
27+
```bash
28+
# Using npm
29+
npm install pdfjs-dist
30+
31+
# OR using yarn
32+
yarn add pdfjs-dist
33+
```
34+
35+
---
36+
37+
## 🧩 Usage
38+
39+
### 1. Add the worker file
40+
41+
You need the PDF.js worker file (`pdf.worker.min.mjs`) to be available in your public folder.
42+
43+
**Structure:**
44+
45+
```
46+
/public/pdfjs/pdf.worker.min.mjs
47+
```
48+
49+
You can get it from:
50+
51+
```
52+
node_modules/pdfjs-dist/build/pdf.worker.min.mjs
53+
```
54+
55+
---
56+
57+
### 2. Import and use the component
58+
59+
```tsx
60+
"use client";
61+
import PdfViewer from "@/components/PdfViewer";
62+
import { useState } from "react";
63+
64+
export default function Page() {
65+
const [file, setFile] = useState<File | null>(null);
66+
67+
return (
68+
<div className="p-4 space-y-4">
69+
<input
70+
type="file"
71+
accept="application/pdf"
72+
onChange={(e) => {
73+
const selectedFile = e.target.files?.[0];
74+
if (selectedFile) setFile(selectedFile);
75+
}}
76+
/>
77+
78+
{file && <PdfViewer file={file} />}
79+
</div>
80+
);
81+
}
82+
```
83+
84+
---
85+
86+
## 🧠 Component Details
87+
88+
### **File:** `PdfViewer.tsx`
89+
90+
```tsx
91+
"use client";
92+
import { getDocument, GlobalWorkerOptions } from "pdfjs-dist/legacy/build/pdf.mjs";
93+
import { useEffect, useRef } from "react";
94+
95+
GlobalWorkerOptions.workerSrc = "/pdfjs/pdf.worker.min.mjs";
96+
97+
export default function PdfViewer({ file }: { file: File }) {
98+
const containerRef = useRef<HTMLDivElement>(null);
99+
const hasRendered = useRef(false);
100+
101+
useEffect(() => {
102+
if (!file || file.size === 0) return;
103+
if (hasRendered.current) return;
104+
105+
hasRendered.current = true;
106+
const container = containerRef.current;
107+
if (!container) return;
108+
109+
const renderPDF = async () => {
110+
container.innerHTML = "";
111+
112+
const arrayBuffer = await file.arrayBuffer();
113+
const pdf = await getDocument({ data: arrayBuffer }).promise;
114+
115+
for (let i = 1; i <= pdf.numPages; i++) {
116+
const page = await pdf.getPage(i);
117+
const viewport = page.getViewport({ scale: 1.2 });
118+
119+
const canvas = document.createElement("canvas");
120+
const context = canvas.getContext("2d")!;
121+
canvas.height = viewport.height;
122+
canvas.width = viewport.width;
123+
124+
await page.render({ canvasContext: context, viewport }).promise;
125+
126+
canvas.id = `page_${i}`;
127+
container.appendChild(canvas);
128+
}
129+
};
130+
131+
renderPDF();
132+
133+
return () => {
134+
if (container) container.innerHTML = "";
135+
};
136+
}, [file]);
137+
138+
return (
139+
<div
140+
ref={containerRef}
141+
className="pdf-container overflow-auto h-full shadow-xl"
142+
/>
143+
);
144+
}
145+
```
146+
147+
---
148+
149+
## 🎨 Styling Example (Optional)
150+
151+
```css
152+
.pdf-container {
153+
background-color: #f9f9f9;
154+
padding: 1rem;
155+
border-radius: 12px;
156+
display: flex;
157+
flex-direction: column;
158+
gap: 1rem;
159+
}
160+
canvas {
161+
border: 1px solid #ddd;
162+
border-radius: 8px;
163+
}
164+
```
165+
166+
---
167+
168+
## ⚠️ Notes
169+
170+
* Make sure the **PDF.js worker file path** matches:
171+
172+
```ts
173+
GlobalWorkerOptions.workerSrc = "/pdfjs/pdf.worker.min.mjs";
174+
```
175+
* This component renders each page on a separate `<canvas>`.
176+
* For large PDFs, consider lazy loading or pagination to improve performance.
177+
178+
---
179+
180+
## 🧑‍💻 License
181+
182+
This component is released under the **MIT License** — free to use and modify in your projects.

0 commit comments

Comments
 (0)