react-pdf-highlighter-plus 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/LICENSE +22 -0
- package/README.md +411 -0
- package/dist/esm/components/AreaHighlight.d.ts +82 -0
- package/dist/esm/components/AreaHighlight.js +109 -0
- package/dist/esm/components/AreaHighlight.js.map +1 -0
- package/dist/esm/components/DrawingCanvas.d.ts +48 -0
- package/dist/esm/components/DrawingCanvas.js +277 -0
- package/dist/esm/components/DrawingCanvas.js.map +1 -0
- package/dist/esm/components/DrawingHighlight.d.ts +70 -0
- package/dist/esm/components/DrawingHighlight.js +164 -0
- package/dist/esm/components/DrawingHighlight.js.map +1 -0
- package/dist/esm/components/FreetextHighlight.d.ts +112 -0
- package/dist/esm/components/FreetextHighlight.js +193 -0
- package/dist/esm/components/FreetextHighlight.js.map +1 -0
- package/dist/esm/components/HighlightLayer.d.ts +49 -0
- package/dist/esm/components/HighlightLayer.js +37 -0
- package/dist/esm/components/HighlightLayer.js.map +1 -0
- package/dist/esm/components/ImageHighlight.d.ts +63 -0
- package/dist/esm/components/ImageHighlight.js +65 -0
- package/dist/esm/components/ImageHighlight.js.map +1 -0
- package/dist/esm/components/MonitoredHighlightContainer.d.ts +37 -0
- package/dist/esm/components/MonitoredHighlightContainer.js +42 -0
- package/dist/esm/components/MonitoredHighlightContainer.js.map +1 -0
- package/dist/esm/components/MouseMonitor.d.ts +34 -0
- package/dist/esm/components/MouseMonitor.js +30 -0
- package/dist/esm/components/MouseMonitor.js.map +1 -0
- package/dist/esm/components/MouseSelection.d.ts +66 -0
- package/dist/esm/components/MouseSelection.js +122 -0
- package/dist/esm/components/MouseSelection.js.map +1 -0
- package/dist/esm/components/PdfHighlighter.d.ts +184 -0
- package/dist/esm/components/PdfHighlighter.js +410 -0
- package/dist/esm/components/PdfHighlighter.js.map +1 -0
- package/dist/esm/components/PdfLoader.d.ts +55 -0
- package/dist/esm/components/PdfLoader.js +57 -0
- package/dist/esm/components/PdfLoader.js.map +1 -0
- package/dist/esm/components/ShapeCanvas.d.ts +51 -0
- package/dist/esm/components/ShapeCanvas.js +205 -0
- package/dist/esm/components/ShapeCanvas.js.map +1 -0
- package/dist/esm/components/ShapeHighlight.d.ts +107 -0
- package/dist/esm/components/ShapeHighlight.js +140 -0
- package/dist/esm/components/ShapeHighlight.js.map +1 -0
- package/dist/esm/components/SignaturePad.d.ts +40 -0
- package/dist/esm/components/SignaturePad.js +138 -0
- package/dist/esm/components/SignaturePad.js.map +1 -0
- package/dist/esm/components/TextHighlight.d.ts +93 -0
- package/dist/esm/components/TextHighlight.js +115 -0
- package/dist/esm/components/TextHighlight.js.map +1 -0
- package/dist/esm/components/TipContainer.d.ts +27 -0
- package/dist/esm/components/TipContainer.js +58 -0
- package/dist/esm/components/TipContainer.js.map +1 -0
- package/dist/esm/contexts/HighlightContext.d.ts +44 -0
- package/dist/esm/contexts/HighlightContext.js +16 -0
- package/dist/esm/contexts/HighlightContext.js.map +1 -0
- package/dist/esm/contexts/PdfHighlighterContext.d.ts +89 -0
- package/dist/esm/contexts/PdfHighlighterContext.js +16 -0
- package/dist/esm/contexts/PdfHighlighterContext.js.map +1 -0
- package/dist/esm/index.d.ts +19 -0
- package/dist/esm/index.js +19 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/lib/coordinates.d.ts +16 -0
- package/dist/esm/lib/coordinates.js +69 -0
- package/dist/esm/lib/coordinates.js.map +1 -0
- package/dist/esm/lib/export-pdf.d.ts +81 -0
- package/dist/esm/lib/export-pdf.js +511 -0
- package/dist/esm/lib/export-pdf.js.map +1 -0
- package/dist/esm/lib/get-bounding-rect.d.ts +3 -0
- package/dist/esm/lib/get-bounding-rect.js +35 -0
- package/dist/esm/lib/get-bounding-rect.js.map +1 -0
- package/dist/esm/lib/get-client-rects.d.ts +3 -0
- package/dist/esm/lib/get-client-rects.js +43 -0
- package/dist/esm/lib/get-client-rects.js.map +1 -0
- package/dist/esm/lib/group-highlights-by-page.d.ts +6 -0
- package/dist/esm/lib/group-highlights-by-page.js +23 -0
- package/dist/esm/lib/group-highlights-by-page.js.map +1 -0
- package/dist/esm/lib/optimize-client-rects.d.ts +3 -0
- package/dist/esm/lib/optimize-client-rects.js +65 -0
- package/dist/esm/lib/optimize-client-rects.js.map +1 -0
- package/dist/esm/lib/pdfjs-dom.d.ts +9 -0
- package/dist/esm/lib/pdfjs-dom.js +55 -0
- package/dist/esm/lib/pdfjs-dom.js.map +1 -0
- package/dist/esm/lib/screenshot.d.ts +4 -0
- package/dist/esm/lib/screenshot.js +24 -0
- package/dist/esm/lib/screenshot.js.map +1 -0
- package/dist/esm/style/AreaHighlight.css +134 -0
- package/dist/esm/style/DrawingCanvas.css +62 -0
- package/dist/esm/style/DrawingHighlight.css +184 -0
- package/dist/esm/style/FreetextHighlight.css +249 -0
- package/dist/esm/style/ImageHighlight.css +97 -0
- package/dist/esm/style/MouseSelection.css +15 -0
- package/dist/esm/style/PdfHighlighter.css +77 -0
- package/dist/esm/style/ShapeCanvas.css +47 -0
- package/dist/esm/style/ShapeHighlight.css +182 -0
- package/dist/esm/style/SignaturePad.css +83 -0
- package/dist/esm/style/TextHighlight.css +199 -0
- package/dist/esm/style/pdf_viewer.css +41 -0
- package/dist/esm/types.d.ts +213 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +91 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Daniel Arnould
|
|
4
|
+
Copyright (c) 2017 Artem Tyurin
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# react-pdf-highlighter-plus
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://github.com/QuocVietHa08/react-pdf-highlighter-plus/stargazers">
|
|
5
|
+
<img src="https://img.shields.io/github/stars/QuocVietHa08/react-pdf-highlighter-plus?style=social" alt="GitHub stars">
|
|
6
|
+
</a>
|
|
7
|
+
<a href="https://github.com/QuocVietHa08/react-pdf-highlighter-plus/actions/workflows/node.js.yml">
|
|
8
|
+
<img src="https://github.com/QuocVietHa08/react-pdf-highlighter-plus/actions/workflows/node.js.yml/badge.svg" alt="Node.js CI">
|
|
9
|
+
</a>
|
|
10
|
+
<a href="https://badge.fury.io/js/react-pdf-highlighter-extended">
|
|
11
|
+
<img src="https://badge.fury.io/js/react-pdf-highlighter-extended.svg" alt="npm version">
|
|
12
|
+
</a>
|
|
13
|
+
<a href="https://www.npmjs.com/package/react-pdf-highlighter-extended">
|
|
14
|
+
<img src="https://img.shields.io/npm/dm/react-pdf-highlighter-extended.svg" alt="npm downloads">
|
|
15
|
+
</a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<strong>A powerful React library for annotating PDF documents</strong>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
<p align="center">
|
|
23
|
+
Text highlights • Area highlights • Freetext notes • Images & signatures • Freehand drawing • PDF export
|
|
24
|
+
</p>
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Overview
|
|
29
|
+
|
|
30
|
+
`react-pdf-highlighter-plus` provides a highly customizable annotation experience for PDF documents in React applications. Built on [PDF.js](https://github.com/mozilla/pdf.js), it stores highlight positions in viewport-independent coordinates, making them portable across different screen sizes.
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
| Feature | Description |
|
|
35
|
+
|---------|-------------|
|
|
36
|
+
| **Text Highlights** | Select and highlight text passages |
|
|
37
|
+
| **Area Highlights** | Draw rectangular regions on PDFs |
|
|
38
|
+
| **Freetext Notes** | Draggable, editable sticky notes with custom styling |
|
|
39
|
+
| **Images & Signatures** | Upload images or draw signatures directly on PDFs |
|
|
40
|
+
| **Freehand Drawing** | Draw freehand annotations with customizable stroke |
|
|
41
|
+
| **PDF Export** | Export annotated PDF with all highlights embedded |
|
|
42
|
+
| **Zoom Support** | Full zoom functionality with position-independent data |
|
|
43
|
+
| **Fully Customizable** | Exposed styling on all components |
|
|
44
|
+
|
|
45
|
+
## Quick Links
|
|
46
|
+
|
|
47
|
+
| Resource | Link |
|
|
48
|
+
|----------|------|
|
|
49
|
+
| Live Demo | [View Demo](https://quocvietha08.github.io/react-pdf-highlighter-plus/example-app/) |
|
|
50
|
+
| Documentation | [API Docs](https://quocvietha08.github.io/react-pdf-highlighter-plus/docs/) |
|
|
51
|
+
| NPM Package | [npm](https://www.npmjs.com/package/react-pdf-highlighter-extended) |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Installation (Coming soon)
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install react-pdf-highlighter-extended
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
### Basic Setup
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import {
|
|
69
|
+
PdfLoader,
|
|
70
|
+
PdfHighlighter,
|
|
71
|
+
TextHighlight,
|
|
72
|
+
AreaHighlight,
|
|
73
|
+
useHighlightContainerContext,
|
|
74
|
+
} from "react-pdf-highlighter-extended";
|
|
75
|
+
|
|
76
|
+
function App() {
|
|
77
|
+
const [highlights, setHighlights] = useState([]);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<PdfLoader document="https://example.com/document.pdf">
|
|
81
|
+
{(pdfDocument) => (
|
|
82
|
+
<PdfHighlighter
|
|
83
|
+
pdfDocument={pdfDocument}
|
|
84
|
+
highlights={highlights}
|
|
85
|
+
enableAreaSelection={(e) => e.altKey}
|
|
86
|
+
>
|
|
87
|
+
<HighlightContainer />
|
|
88
|
+
</PdfHighlighter>
|
|
89
|
+
)}
|
|
90
|
+
</PdfLoader>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function HighlightContainer() {
|
|
95
|
+
const { highlight, isScrolledTo } = useHighlightContainerContext();
|
|
96
|
+
|
|
97
|
+
return highlight.type === "text" ? (
|
|
98
|
+
<TextHighlight highlight={highlight} isScrolledTo={isScrolledTo} />
|
|
99
|
+
) : (
|
|
100
|
+
<AreaHighlight highlight={highlight} isScrolledTo={isScrolledTo} />
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Highlight Types
|
|
108
|
+
|
|
109
|
+
### 1. Text Highlights
|
|
110
|
+
|
|
111
|
+
Select text in the PDF to create highlights.
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
<TextHighlight
|
|
115
|
+
highlight={highlight}
|
|
116
|
+
isScrolledTo={isScrolledTo}
|
|
117
|
+
style={{ background: "rgba(255, 226, 143, 1)" }}
|
|
118
|
+
/>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 2. Area Highlights
|
|
122
|
+
|
|
123
|
+
Hold `Alt` and drag to create rectangular highlights.
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
<PdfHighlighter
|
|
127
|
+
enableAreaSelection={(event) => event.altKey}
|
|
128
|
+
// ...
|
|
129
|
+
>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 3. Freetext Notes
|
|
133
|
+
|
|
134
|
+
Create draggable, editable text annotations with customizable styling.
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
import { FreetextHighlight } from "react-pdf-highlighter-extended";
|
|
138
|
+
|
|
139
|
+
<PdfHighlighter
|
|
140
|
+
enableFreetextCreation={() => freetextMode}
|
|
141
|
+
onFreetextClick={(position) => {
|
|
142
|
+
addHighlight({ type: "freetext", position, content: { text: "Note" } });
|
|
143
|
+
}}
|
|
144
|
+
>
|
|
145
|
+
|
|
146
|
+
// In your highlight container:
|
|
147
|
+
<FreetextHighlight
|
|
148
|
+
highlight={highlight}
|
|
149
|
+
onChange={handlePositionChange}
|
|
150
|
+
onTextChange={handleTextChange}
|
|
151
|
+
onStyleChange={handleStyleChange}
|
|
152
|
+
color="#333333"
|
|
153
|
+
backgroundColor="#ffffc8"
|
|
154
|
+
fontSize="14px"
|
|
155
|
+
/>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Features:**
|
|
159
|
+
- Drag to reposition
|
|
160
|
+
- Click to edit text
|
|
161
|
+
- Built-in style panel (colors, font size, font family)
|
|
162
|
+
- Toolbar appears on hover
|
|
163
|
+
|
|
164
|
+
[Full Documentation →](docs/freetext-highlights.md)
|
|
165
|
+
|
|
166
|
+
### 4. Images & Signatures
|
|
167
|
+
|
|
168
|
+
Upload images or draw signatures and place them on PDFs.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import { ImageHighlight, SignaturePad } from "react-pdf-highlighter-extended";
|
|
172
|
+
|
|
173
|
+
// Signature pad modal
|
|
174
|
+
<SignaturePad
|
|
175
|
+
isOpen={isOpen}
|
|
176
|
+
onComplete={(dataUrl) => setPendingImage(dataUrl)}
|
|
177
|
+
onClose={() => setIsOpen(false)}
|
|
178
|
+
/>
|
|
179
|
+
|
|
180
|
+
// In your highlight container:
|
|
181
|
+
<ImageHighlight
|
|
182
|
+
highlight={highlight}
|
|
183
|
+
onChange={handlePositionChange}
|
|
184
|
+
onEditStart={() => toggleEditInProgress(true)}
|
|
185
|
+
onEditEnd={() => toggleEditInProgress(false)}
|
|
186
|
+
/>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Features:**
|
|
190
|
+
- Upload any image format
|
|
191
|
+
- Draw signatures with mouse or touch
|
|
192
|
+
- Drag to reposition
|
|
193
|
+
- Resize while maintaining aspect ratio
|
|
194
|
+
- Toolbar appears on hover
|
|
195
|
+
|
|
196
|
+
[Full Documentation →](docs/image-signature-highlights.md)
|
|
197
|
+
|
|
198
|
+
### 5. Freehand Drawing
|
|
199
|
+
|
|
200
|
+
Draw freehand annotations directly on PDFs.
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
import { DrawingHighlight } from "react-pdf-highlighter-extended";
|
|
204
|
+
|
|
205
|
+
<PdfHighlighter
|
|
206
|
+
enableDrawingCreation={() => drawingMode}
|
|
207
|
+
onDrawingComplete={(position, dataUrl) => {
|
|
208
|
+
addHighlight({ type: "drawing", position, content: { image: dataUrl } });
|
|
209
|
+
}}
|
|
210
|
+
drawingConfig={{
|
|
211
|
+
strokeColor: "#ff0000",
|
|
212
|
+
strokeWidth: 2,
|
|
213
|
+
}}
|
|
214
|
+
>
|
|
215
|
+
|
|
216
|
+
// In your highlight container:
|
|
217
|
+
<DrawingHighlight
|
|
218
|
+
highlight={highlight}
|
|
219
|
+
onChange={handlePositionChange}
|
|
220
|
+
/>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Features:**
|
|
224
|
+
- Freehand drawing with mouse or touch
|
|
225
|
+
- Customizable stroke color and width
|
|
226
|
+
- Stored as PNG for PDF export compatibility
|
|
227
|
+
- Drag to reposition
|
|
228
|
+
|
|
229
|
+
[Full Documentation →](docs/drawing-highlights.md)
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## PDF Export
|
|
234
|
+
|
|
235
|
+
Export your annotated PDF with all highlights embedded.
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
import { exportPdf } from "react-pdf-highlighter-extended";
|
|
239
|
+
|
|
240
|
+
const handleExport = async () => {
|
|
241
|
+
const pdfBytes = await exportPdf(pdfUrl, highlights, {
|
|
242
|
+
textHighlightColor: "rgba(255, 226, 143, 0.5)",
|
|
243
|
+
areaHighlightColor: "rgba(255, 226, 143, 0.5)",
|
|
244
|
+
onProgress: (current, total) => console.log(`${current}/${total} pages`),
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Download the file
|
|
248
|
+
const blob = new Blob([pdfBytes], { type: "application/pdf" });
|
|
249
|
+
const url = URL.createObjectURL(blob);
|
|
250
|
+
const a = document.createElement("a");
|
|
251
|
+
a.href = url;
|
|
252
|
+
a.download = "annotated.pdf";
|
|
253
|
+
a.click();
|
|
254
|
+
URL.revokeObjectURL(url);
|
|
255
|
+
};
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Supported highlight types:**
|
|
259
|
+
- Text highlights (colored rectangles)
|
|
260
|
+
- Area highlights (colored rectangles)
|
|
261
|
+
- Freetext notes (background + wrapped text)
|
|
262
|
+
- Images & signatures (embedded PNG/JPG)
|
|
263
|
+
- Freehand drawings (embedded PNG)
|
|
264
|
+
|
|
265
|
+
[Full Documentation →](docs/pdf-export.md)
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Component Architecture
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
┌─────────────────────────────────────────────────────┐
|
|
273
|
+
│ PdfLoader │
|
|
274
|
+
│ Loads PDF document via PDF.js │
|
|
275
|
+
│ │
|
|
276
|
+
│ ┌───────────────────────────────────────────────┐ │
|
|
277
|
+
│ │ PdfHighlighter │ │
|
|
278
|
+
│ │ Manages viewer, events, coordinate systems │ │
|
|
279
|
+
│ │ │ │
|
|
280
|
+
│ │ ┌─────────────────────────────────────────┐ │ │
|
|
281
|
+
│ │ │ User-defined HighlightContainer │ │ │
|
|
282
|
+
│ │ │ Renders highlights using context hooks │ │ │
|
|
283
|
+
│ │ │ │ │ │
|
|
284
|
+
│ │ │ • TextHighlight │ │ │
|
|
285
|
+
│ │ │ • AreaHighlight │ │ │
|
|
286
|
+
│ │ │ • FreetextHighlight │ │ │
|
|
287
|
+
│ │ │ • ImageHighlight │ │ │
|
|
288
|
+
│ │ │ • DrawingHighlight │ │ │
|
|
289
|
+
│ │ └─────────────────────────────────────────┘ │ │
|
|
290
|
+
│ └───────────────────────────────────────────────┘ │
|
|
291
|
+
└─────────────────────────────────────────────────────┘
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Context Hooks
|
|
295
|
+
|
|
296
|
+
| Hook | Purpose |
|
|
297
|
+
|------|---------|
|
|
298
|
+
| `usePdfHighlighterContext()` | Viewer utilities: `scrollToHighlight`, `setTip`, `getCurrentSelection` |
|
|
299
|
+
| `useHighlightContainerContext()` | Per-highlight utilities: `highlight`, `viewportToScaled`, `screenshot` |
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Coordinate Systems
|
|
304
|
+
|
|
305
|
+
The library uses two coordinate systems:
|
|
306
|
+
|
|
307
|
+
| System | Description | Use Case |
|
|
308
|
+
|--------|-------------|----------|
|
|
309
|
+
| **Viewport** | Pixel coordinates relative to current zoom | Rendering on screen |
|
|
310
|
+
| **Scaled** | Normalized (0-1) coordinates relative to page | Storage & retrieval |
|
|
311
|
+
|
|
312
|
+
```tsx
|
|
313
|
+
// Converting between systems
|
|
314
|
+
const { viewportToScaled } = useHighlightContainerContext();
|
|
315
|
+
|
|
316
|
+
// Save position (viewport → scaled)
|
|
317
|
+
const scaledPosition = viewportToScaled(boundingRect);
|
|
318
|
+
|
|
319
|
+
// Highlights are automatically converted to viewport when rendering
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Customization
|
|
325
|
+
|
|
326
|
+
### Custom Highlight Interface
|
|
327
|
+
|
|
328
|
+
```tsx
|
|
329
|
+
interface MyHighlight extends Highlight {
|
|
330
|
+
category: string;
|
|
331
|
+
comment?: string;
|
|
332
|
+
author?: string;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Use the generic type
|
|
336
|
+
const { highlight } = useHighlightContainerContext<MyHighlight>();
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Custom Styling
|
|
340
|
+
|
|
341
|
+
```tsx
|
|
342
|
+
// Via props
|
|
343
|
+
<TextHighlight
|
|
344
|
+
highlight={highlight}
|
|
345
|
+
style={{ background: categoryColors[highlight.category] }}
|
|
346
|
+
/>
|
|
347
|
+
|
|
348
|
+
// Via CSS classes
|
|
349
|
+
.TextHighlight { }
|
|
350
|
+
.AreaHighlight { }
|
|
351
|
+
.FreetextHighlight { }
|
|
352
|
+
.ImageHighlight { }
|
|
353
|
+
.DrawingHighlight { }
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Tips and Popups
|
|
357
|
+
|
|
358
|
+
```tsx
|
|
359
|
+
import { MonitoredHighlightContainer } from "react-pdf-highlighter-extended";
|
|
360
|
+
|
|
361
|
+
<MonitoredHighlightContainer
|
|
362
|
+
highlightTip={{
|
|
363
|
+
position: highlight.position,
|
|
364
|
+
content: <MyPopup highlight={highlight} />,
|
|
365
|
+
}}
|
|
366
|
+
>
|
|
367
|
+
<TextHighlight highlight={highlight} />
|
|
368
|
+
</MonitoredHighlightContainer>
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Running Locally
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
git clone https://github.com/QuocVietHa08/react-pdf-highlighter-plus.git
|
|
377
|
+
cd react-pdf-highlighter-plus
|
|
378
|
+
npm install
|
|
379
|
+
npm run dev
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## API Reference
|
|
385
|
+
|
|
386
|
+
See the full [API Reference](docs/api-reference.md) for detailed documentation on all components and types.
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Contributing
|
|
391
|
+
|
|
392
|
+
Contributions are welcome! Please:
|
|
393
|
+
|
|
394
|
+
1. Fork the repository
|
|
395
|
+
2. Create a feature branch
|
|
396
|
+
3. Make your changes
|
|
397
|
+
4. Submit a pull request
|
|
398
|
+
|
|
399
|
+
For bugs, please [open an issue](https://github.com/QuocVietHa08/react-pdf-highlighter-plus/issues) with clear reproduction steps.
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## License
|
|
404
|
+
|
|
405
|
+
MIT
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## Credits
|
|
410
|
+
|
|
411
|
+
Originally forked from [`react-pdf-highlighter`](https://github.com/agentcooper/react-pdf-highlighter) with significant architectural changes including context-based APIs, zoom support, freetext/image/drawing highlights, and PDF export functionality.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import React, { CSSProperties, MouseEvent, ReactNode } from "react";
|
|
2
|
+
import "../style/AreaHighlight.css";
|
|
3
|
+
import type { LTWHP, ViewportHighlight } from "../types";
|
|
4
|
+
/**
|
|
5
|
+
* Style options for area highlight appearance.
|
|
6
|
+
*/
|
|
7
|
+
export interface AreaHighlightStyle {
|
|
8
|
+
highlightColor?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The props type for {@link AreaHighlight}.
|
|
12
|
+
*
|
|
13
|
+
* @category Component Properties
|
|
14
|
+
*/
|
|
15
|
+
export interface AreaHighlightProps {
|
|
16
|
+
/**
|
|
17
|
+
* The highlight to be rendered as an {@link AreaHighlight}.
|
|
18
|
+
*/
|
|
19
|
+
highlight: ViewportHighlight;
|
|
20
|
+
/**
|
|
21
|
+
* A callback triggered whenever the highlight area is either finished
|
|
22
|
+
* being moved or resized.
|
|
23
|
+
*
|
|
24
|
+
* @param rect - The updated highlight area.
|
|
25
|
+
*/
|
|
26
|
+
onChange?(rect: LTWHP): void;
|
|
27
|
+
/**
|
|
28
|
+
* Has the highlight been auto-scrolled into view? By default, this will render the highlight red.
|
|
29
|
+
*/
|
|
30
|
+
isScrolledTo?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* react-rnd bounds on the highlight area. This is useful for preventing the user
|
|
33
|
+
* moving the highlight off the viewer/page. See [react-rnd docs](https://github.com/bokuweb/react-rnd).
|
|
34
|
+
*/
|
|
35
|
+
bounds?: string | Element;
|
|
36
|
+
/**
|
|
37
|
+
* A callback triggered whenever a context menu is opened on the highlight area.
|
|
38
|
+
*
|
|
39
|
+
* @param event - The mouse event associated with the context menu.
|
|
40
|
+
*/
|
|
41
|
+
onContextMenu?(event: MouseEvent<HTMLDivElement>): void;
|
|
42
|
+
/**
|
|
43
|
+
* Event called whenever the user tries to move or resize an {@link AreaHighlight}.
|
|
44
|
+
*/
|
|
45
|
+
onEditStart?(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Custom styling to be applied to the {@link AreaHighlight} component.
|
|
48
|
+
*/
|
|
49
|
+
style?: CSSProperties;
|
|
50
|
+
/**
|
|
51
|
+
* Background color for the highlight.
|
|
52
|
+
* Default: "rgba(255, 226, 143, 1)" (yellow)
|
|
53
|
+
*/
|
|
54
|
+
highlightColor?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Callback triggered when the style changes.
|
|
57
|
+
*/
|
|
58
|
+
onStyleChange?(style: AreaHighlightStyle): void;
|
|
59
|
+
/**
|
|
60
|
+
* Callback triggered when the delete button is clicked.
|
|
61
|
+
*/
|
|
62
|
+
onDelete?(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Custom style icon. Replaces the default palette icon.
|
|
65
|
+
*/
|
|
66
|
+
styleIcon?: ReactNode;
|
|
67
|
+
/**
|
|
68
|
+
* Custom delete icon. Replaces the default trash icon.
|
|
69
|
+
*/
|
|
70
|
+
deleteIcon?: ReactNode;
|
|
71
|
+
/**
|
|
72
|
+
* Custom color presets for the style panel.
|
|
73
|
+
* Default: ["rgba(255, 226, 143, 1)", "#ffcdd2", "#c8e6c9", "#bbdefb", "#e1bee7"]
|
|
74
|
+
*/
|
|
75
|
+
colorPresets?: string[];
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Renders a resizeable and interactive rectangular area for a highlight.
|
|
79
|
+
*
|
|
80
|
+
* @category Component
|
|
81
|
+
*/
|
|
82
|
+
export declare const AreaHighlight: ({ highlight, onChange, isScrolledTo, bounds, onContextMenu, onEditStart, style, highlightColor, onStyleChange, onDelete, styleIcon, deleteIcon, colorPresets, }: AreaHighlightProps) => React.JSX.Element;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React, { useState, useRef, useEffect, } from "react";
|
|
2
|
+
import { getPageFromElement } from "../lib/pdfjs-dom";
|
|
3
|
+
import "../style/AreaHighlight.css";
|
|
4
|
+
import { Rnd } from "react-rnd";
|
|
5
|
+
// Default icons
|
|
6
|
+
const DefaultStyleIcon = () => (React.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor" },
|
|
7
|
+
React.createElement("path", { d: "M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z" })));
|
|
8
|
+
const DefaultDeleteIcon = () => (React.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor" },
|
|
9
|
+
React.createElement("path", { d: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" })));
|
|
10
|
+
// Default color presets
|
|
11
|
+
const DEFAULT_COLOR_PRESETS = [
|
|
12
|
+
"rgba(255, 226, 143, 1)", // Yellow (default)
|
|
13
|
+
"#ffcdd2", // Light red
|
|
14
|
+
"#c8e6c9", // Light green
|
|
15
|
+
"#bbdefb", // Light blue
|
|
16
|
+
"#e1bee7", // Light purple
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* Renders a resizeable and interactive rectangular area for a highlight.
|
|
20
|
+
*
|
|
21
|
+
* @category Component
|
|
22
|
+
*/
|
|
23
|
+
export const AreaHighlight = ({ highlight, onChange, isScrolledTo, bounds, onContextMenu, onEditStart, style, highlightColor = "rgba(255, 226, 143, 1)", onStyleChange, onDelete, styleIcon, deleteIcon, colorPresets = DEFAULT_COLOR_PRESETS, }) => {
|
|
24
|
+
const [isStylePanelOpen, setIsStylePanelOpen] = useState(false);
|
|
25
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
26
|
+
const stylePanelRef = useRef(null);
|
|
27
|
+
// Close style panel when clicking outside
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!isStylePanelOpen)
|
|
30
|
+
return;
|
|
31
|
+
const handleClickOutside = (e) => {
|
|
32
|
+
if (stylePanelRef.current &&
|
|
33
|
+
!stylePanelRef.current.contains(e.target)) {
|
|
34
|
+
setIsStylePanelOpen(false);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
// Delay adding listener to avoid immediate close
|
|
38
|
+
const timeoutId = setTimeout(() => {
|
|
39
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
40
|
+
}, 0);
|
|
41
|
+
return () => {
|
|
42
|
+
clearTimeout(timeoutId);
|
|
43
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
44
|
+
};
|
|
45
|
+
}, [isStylePanelOpen]);
|
|
46
|
+
const highlightClass = isScrolledTo ? "AreaHighlight--scrolledTo" : "";
|
|
47
|
+
// Generate key based on position. This forces a remount (and a defaultpos update)
|
|
48
|
+
// whenever highlight position changes (e.g., when updated, scale changes, etc.)
|
|
49
|
+
// We don't use position as state because when updating Rnd this would happen and cause flickering:
|
|
50
|
+
// User moves Rnd -> Rnd records new pos -> Rnd jumps back -> highlight updates -> Rnd re-renders at new pos
|
|
51
|
+
const key = `${highlight.position.boundingRect.width}${highlight.position.boundingRect.height}${highlight.position.boundingRect.left}${highlight.position.boundingRect.top}`;
|
|
52
|
+
// Merge custom style with highlight color
|
|
53
|
+
const mergedStyle = {
|
|
54
|
+
...style,
|
|
55
|
+
backgroundColor: highlightColor,
|
|
56
|
+
};
|
|
57
|
+
return (React.createElement("div", { className: `AreaHighlight ${highlightClass}`, onContextMenu: onContextMenu },
|
|
58
|
+
(onStyleChange || onDelete) && (React.createElement("div", { className: "AreaHighlight__toolbar-wrapper", style: {
|
|
59
|
+
position: "absolute",
|
|
60
|
+
left: highlight.position.boundingRect.left,
|
|
61
|
+
top: highlight.position.boundingRect.top - 28,
|
|
62
|
+
paddingBottom: 12,
|
|
63
|
+
}, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false) },
|
|
64
|
+
React.createElement("div", { className: `AreaHighlight__toolbar ${isHovered || isStylePanelOpen ? "AreaHighlight__toolbar--visible" : ""}` },
|
|
65
|
+
onStyleChange && (React.createElement("button", { className: "AreaHighlight__style-button", onClick: (e) => {
|
|
66
|
+
e.stopPropagation();
|
|
67
|
+
setIsStylePanelOpen(!isStylePanelOpen);
|
|
68
|
+
}, title: "Change color", type: "button" }, styleIcon || React.createElement(DefaultStyleIcon, null))),
|
|
69
|
+
onDelete && (React.createElement("button", { className: "AreaHighlight__delete-button", onClick: (e) => {
|
|
70
|
+
e.stopPropagation();
|
|
71
|
+
onDelete();
|
|
72
|
+
}, title: "Delete", type: "button" }, deleteIcon || React.createElement(DefaultDeleteIcon, null)))),
|
|
73
|
+
isStylePanelOpen && onStyleChange && (React.createElement("div", { className: "AreaHighlight__style-panel", ref: stylePanelRef, onClick: (e) => e.stopPropagation() },
|
|
74
|
+
React.createElement("div", { className: "AreaHighlight__style-row" },
|
|
75
|
+
React.createElement("label", null, "Color"),
|
|
76
|
+
React.createElement("div", { className: "AreaHighlight__color-options" },
|
|
77
|
+
React.createElement("div", { className: "AreaHighlight__color-presets" }, colorPresets.map((c) => (React.createElement("button", { key: c, type: "button", className: `AreaHighlight__color-preset ${highlightColor === c ? "active" : ""}`, style: { backgroundColor: c }, onClick: () => onStyleChange({ highlightColor: c }), title: c })))),
|
|
78
|
+
React.createElement("input", { type: "color", value: highlightColor, onChange: (e) => {
|
|
79
|
+
onStyleChange({ highlightColor: e.target.value });
|
|
80
|
+
} }))))))),
|
|
81
|
+
React.createElement(Rnd, { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), className: "AreaHighlight__part", onDragStop: (_, data) => {
|
|
82
|
+
const boundingRect = {
|
|
83
|
+
...highlight.position.boundingRect,
|
|
84
|
+
top: data.y,
|
|
85
|
+
left: data.x,
|
|
86
|
+
};
|
|
87
|
+
onChange && onChange(boundingRect);
|
|
88
|
+
}, onResizeStop: (_mouseEvent, _direction, ref, _delta, position) => {
|
|
89
|
+
const boundingRect = {
|
|
90
|
+
top: position.y,
|
|
91
|
+
left: position.x,
|
|
92
|
+
width: ref.offsetWidth,
|
|
93
|
+
height: ref.offsetHeight,
|
|
94
|
+
pageNumber: getPageFromElement(ref)?.number || -1,
|
|
95
|
+
};
|
|
96
|
+
onChange && onChange(boundingRect);
|
|
97
|
+
}, onDragStart: onEditStart, onResizeStart: onEditStart, default: {
|
|
98
|
+
x: highlight.position.boundingRect.left,
|
|
99
|
+
y: highlight.position.boundingRect.top,
|
|
100
|
+
width: highlight.position.boundingRect.width,
|
|
101
|
+
height: highlight.position.boundingRect.height,
|
|
102
|
+
}, key: key, bounds: bounds,
|
|
103
|
+
// Prevevent any event clicks as clicking is already used for movement
|
|
104
|
+
onClick: (event) => {
|
|
105
|
+
event.stopPropagation();
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
}, style: mergedStyle })));
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=AreaHighlight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AreaHighlight.js","sourceRoot":"","sources":["../../../src/components/AreaHighlight.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { DrawingStroke, ScaledPosition } from "../types";
|
|
3
|
+
import "../style/DrawingCanvas.css";
|
|
4
|
+
import type { PDFViewer as TPDFViewer } from "pdfjs-dist/web/pdf_viewer.mjs";
|
|
5
|
+
/**
|
|
6
|
+
* The props type for {@link DrawingCanvas}.
|
|
7
|
+
*
|
|
8
|
+
* @category Component Properties
|
|
9
|
+
*/
|
|
10
|
+
export interface DrawingCanvasProps {
|
|
11
|
+
/**
|
|
12
|
+
* Whether drawing mode is active.
|
|
13
|
+
*/
|
|
14
|
+
isActive: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Stroke color for drawing.
|
|
17
|
+
* @default "#000000"
|
|
18
|
+
*/
|
|
19
|
+
strokeColor?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Stroke width for drawing.
|
|
22
|
+
* @default 3
|
|
23
|
+
*/
|
|
24
|
+
strokeWidth?: number;
|
|
25
|
+
/**
|
|
26
|
+
* The PDF viewer instance.
|
|
27
|
+
*/
|
|
28
|
+
viewer: InstanceType<typeof TPDFViewer>;
|
|
29
|
+
/**
|
|
30
|
+
* Callback when drawing is complete.
|
|
31
|
+
*
|
|
32
|
+
* @param dataUrl - The drawing as a PNG data URL.
|
|
33
|
+
* @param position - Scaled position of the drawing on the page.
|
|
34
|
+
* @param strokes - The stroke data for later editing.
|
|
35
|
+
*/
|
|
36
|
+
onComplete: (dataUrl: string, position: ScaledPosition, strokes: DrawingStroke[]) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Callback when drawing is cancelled.
|
|
39
|
+
*/
|
|
40
|
+
onCancel: () => void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A transparent overlay canvas for freehand drawing on PDF pages.
|
|
44
|
+
* Supports mouse and touch input.
|
|
45
|
+
*
|
|
46
|
+
* @category Component
|
|
47
|
+
*/
|
|
48
|
+
export declare const DrawingCanvas: ({ isActive, strokeColor, strokeWidth, viewer, onComplete, onCancel, }: DrawingCanvasProps) => React.JSX.Element | null;
|