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
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
.SignaturePad__overlay {
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 0;
|
|
4
|
+
left: 0;
|
|
5
|
+
right: 0;
|
|
6
|
+
bottom: 0;
|
|
7
|
+
background: rgba(0, 0, 0, 0.5);
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
z-index: 10000;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.SignaturePad__modal {
|
|
15
|
+
background: white;
|
|
16
|
+
border-radius: 8px;
|
|
17
|
+
padding: 16px;
|
|
18
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.SignaturePad__title {
|
|
22
|
+
margin: 0 0 12px 0;
|
|
23
|
+
font-size: 16px;
|
|
24
|
+
font-weight: 600;
|
|
25
|
+
color: #333;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.SignaturePad__canvas {
|
|
29
|
+
display: block;
|
|
30
|
+
border: 1px solid #ccc;
|
|
31
|
+
border-radius: 4px;
|
|
32
|
+
cursor: crosshair;
|
|
33
|
+
touch-action: none;
|
|
34
|
+
background: white;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.SignaturePad__buttons {
|
|
38
|
+
display: flex;
|
|
39
|
+
gap: 8px;
|
|
40
|
+
margin-top: 12px;
|
|
41
|
+
justify-content: flex-end;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.SignaturePad__button {
|
|
45
|
+
padding: 8px 16px;
|
|
46
|
+
font-size: 14px;
|
|
47
|
+
border-radius: 4px;
|
|
48
|
+
cursor: pointer;
|
|
49
|
+
transition: background-color 0.2s, border-color 0.2s;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.SignaturePad__button--clear {
|
|
53
|
+
background: white;
|
|
54
|
+
border: 1px solid #ccc;
|
|
55
|
+
color: #666;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.SignaturePad__button--clear:hover {
|
|
59
|
+
background: #f5f5f5;
|
|
60
|
+
border-color: #999;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.SignaturePad__button--cancel {
|
|
64
|
+
background: white;
|
|
65
|
+
border: 1px solid #ccc;
|
|
66
|
+
color: #666;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.SignaturePad__button--cancel:hover {
|
|
70
|
+
background: #f5f5f5;
|
|
71
|
+
border-color: #999;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.SignaturePad__button--done {
|
|
75
|
+
background: #2196f3;
|
|
76
|
+
border: 1px solid #2196f3;
|
|
77
|
+
color: white;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.SignaturePad__button--done:hover {
|
|
81
|
+
background: #1976d2;
|
|
82
|
+
border-color: #1976d2;
|
|
83
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
.TextHighlight {
|
|
2
|
+
position: absolute;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.TextHighlight__parts {
|
|
6
|
+
opacity: 1;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.TextHighlight__part {
|
|
10
|
+
cursor: pointer;
|
|
11
|
+
position: absolute;
|
|
12
|
+
background: rgba(255, 226, 143, 1);
|
|
13
|
+
transition: background 0.3s;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.TextHighlight--scrolledTo .TextHighlight__part {
|
|
17
|
+
background: #ff4141;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Toolbar wrapper - creates hover bridge between toolbar and highlight */
|
|
21
|
+
.TextHighlight__toolbar-wrapper {
|
|
22
|
+
z-index: 10;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* Toolbar - appears on hover */
|
|
26
|
+
.TextHighlight__toolbar {
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
gap: 4px;
|
|
30
|
+
padding: 2px 4px;
|
|
31
|
+
background: rgba(0, 0, 0, 0.7);
|
|
32
|
+
border-radius: 4px;
|
|
33
|
+
opacity: 0;
|
|
34
|
+
pointer-events: none;
|
|
35
|
+
transition: opacity 0.2s ease;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.TextHighlight__toolbar--visible {
|
|
39
|
+
opacity: 1;
|
|
40
|
+
pointer-events: auto;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.TextHighlight__style-button,
|
|
44
|
+
.TextHighlight__delete-button {
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
width: 20px;
|
|
49
|
+
height: 20px;
|
|
50
|
+
border: none;
|
|
51
|
+
background: transparent;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
color: white;
|
|
54
|
+
border-radius: 3px;
|
|
55
|
+
padding: 0;
|
|
56
|
+
transition: background 0.2s;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.TextHighlight__style-button:hover {
|
|
60
|
+
background: rgba(255, 255, 255, 0.2);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.TextHighlight__delete-button:hover {
|
|
64
|
+
background: rgba(255, 100, 100, 0.6);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Style Panel */
|
|
68
|
+
.TextHighlight__style-panel {
|
|
69
|
+
margin-top: 4px;
|
|
70
|
+
background: rgba(0, 0, 0, 0.9);
|
|
71
|
+
border-radius: 6px;
|
|
72
|
+
padding: 8px;
|
|
73
|
+
min-width: 180px;
|
|
74
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.TextHighlight__style-row {
|
|
78
|
+
display: flex;
|
|
79
|
+
align-items: center;
|
|
80
|
+
justify-content: space-between;
|
|
81
|
+
margin-bottom: 8px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.TextHighlight__style-row:last-child {
|
|
85
|
+
margin-bottom: 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.TextHighlight__style-row label {
|
|
89
|
+
color: #ccc;
|
|
90
|
+
font-size: 11px;
|
|
91
|
+
text-transform: uppercase;
|
|
92
|
+
letter-spacing: 0.5px;
|
|
93
|
+
margin-right: 8px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Style type buttons (highlight, underline, strikethrough) */
|
|
97
|
+
.TextHighlight__style-buttons {
|
|
98
|
+
display: flex;
|
|
99
|
+
gap: 4px;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.TextHighlight__style-type-button {
|
|
103
|
+
display: flex;
|
|
104
|
+
align-items: center;
|
|
105
|
+
justify-content: center;
|
|
106
|
+
width: 28px;
|
|
107
|
+
height: 28px;
|
|
108
|
+
padding: 0;
|
|
109
|
+
background: transparent;
|
|
110
|
+
border: 1px solid #666;
|
|
111
|
+
border-radius: 4px;
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
color: #f5f5f5;
|
|
114
|
+
transition: all 0.2s;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.TextHighlight__style-type-button:hover {
|
|
118
|
+
border-color: #b958ff;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.TextHighlight__style-type-button.active {
|
|
122
|
+
color: #b958ff;
|
|
123
|
+
border-color: #b958ff;
|
|
124
|
+
background: rgba(185, 88, 255, 0.2);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* Color options */
|
|
128
|
+
.TextHighlight__color-options {
|
|
129
|
+
display: flex;
|
|
130
|
+
align-items: center;
|
|
131
|
+
gap: 6px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.TextHighlight__color-presets {
|
|
135
|
+
display: flex;
|
|
136
|
+
gap: 4px;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.TextHighlight__color-preset {
|
|
140
|
+
width: 18px;
|
|
141
|
+
height: 18px;
|
|
142
|
+
border: 2px solid transparent;
|
|
143
|
+
border-radius: 50%;
|
|
144
|
+
cursor: pointer;
|
|
145
|
+
transition: transform 0.2s, border-color 0.2s;
|
|
146
|
+
padding: 0;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.TextHighlight__color-preset:hover {
|
|
150
|
+
transform: scale(1.15);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.TextHighlight__color-preset.active {
|
|
154
|
+
border-color: #b958ff;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.TextHighlight__color-options input[type="color"] {
|
|
158
|
+
width: 24px;
|
|
159
|
+
height: 24px;
|
|
160
|
+
padding: 0;
|
|
161
|
+
border: none;
|
|
162
|
+
border-radius: 4px;
|
|
163
|
+
cursor: pointer;
|
|
164
|
+
background: transparent;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.TextHighlight__color-options input[type="color"]::-webkit-color-swatch-wrapper {
|
|
168
|
+
padding: 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.TextHighlight__color-options input[type="color"]::-webkit-color-swatch {
|
|
172
|
+
border: 1px solid #666;
|
|
173
|
+
border-radius: 4px;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* Underline style */
|
|
177
|
+
.TextHighlight__part--underline {
|
|
178
|
+
background: transparent !important;
|
|
179
|
+
border-bottom: 2px solid currentColor;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* Strikethrough style */
|
|
183
|
+
.TextHighlight__part.TextHighlight__part--strikethrough {
|
|
184
|
+
background: transparent !important;
|
|
185
|
+
overflow: visible;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.TextHighlight__part.TextHighlight__part--strikethrough::after {
|
|
189
|
+
content: "";
|
|
190
|
+
position: absolute;
|
|
191
|
+
left: 0;
|
|
192
|
+
right: 0;
|
|
193
|
+
top: 50%;
|
|
194
|
+
height: 2px;
|
|
195
|
+
background-color: currentColor;
|
|
196
|
+
transform: translateY(-50%);
|
|
197
|
+
pointer-events: none;
|
|
198
|
+
z-index: 1;
|
|
199
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/* overrides for pdf_viewer.css from PDF.JS web viewer */
|
|
2
|
+
|
|
3
|
+
.textLayer {
|
|
4
|
+
z-index: 2;
|
|
5
|
+
opacity: 1;
|
|
6
|
+
mix-blend-mode: multiply;
|
|
7
|
+
display: flex;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.annotationLayer {
|
|
11
|
+
position: absolute;
|
|
12
|
+
top: 0;
|
|
13
|
+
|
|
14
|
+
z-index: 3;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
html
|
|
18
|
+
body
|
|
19
|
+
.textLayer
|
|
20
|
+
> div:not(.PdfHighlighter__highlight-layer):not(.TextHighlight):not(.TextHighlight-icon) {
|
|
21
|
+
opacity: 1;
|
|
22
|
+
mix-blend-mode: multiply;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.textLayer ::selection {
|
|
26
|
+
mix-blend-mode: multiply;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
|
|
30
|
+
.textLayer {opacity: 0.5;}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Internet Explorer support method */
|
|
34
|
+
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
|
|
35
|
+
.textLayer {opacity: 0.5 }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Microsoft Edge Browser 12+ (All) - @supports method */
|
|
39
|
+
@supports (-ms-ime-align:auto) {
|
|
40
|
+
.textLayer {opacity: 0.5 }
|
|
41
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { Root } from "react-dom/client";
|
|
3
|
+
/**
|
|
4
|
+
* A rectangle as measured by the viewport.
|
|
5
|
+
*
|
|
6
|
+
* @category Type
|
|
7
|
+
*/
|
|
8
|
+
export type LTWH = {
|
|
9
|
+
/** The x coordinate of the top-left of the rectangle. */
|
|
10
|
+
left: number;
|
|
11
|
+
/** The y coordinate of the top-left of the rectangle. */
|
|
12
|
+
top: number;
|
|
13
|
+
/** Width of the rectangle, relative to top left of the viewport. */
|
|
14
|
+
width: number;
|
|
15
|
+
/** Height of the rectangle, relative to top left of the viewport. */
|
|
16
|
+
height: number;
|
|
17
|
+
};
|
|
18
|
+
/** @category Type */
|
|
19
|
+
export type LTWHP = LTWH & {
|
|
20
|
+
/** 1-Indexed page number */
|
|
21
|
+
pageNumber: number;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* "scaled" means that data structure stores (0, 1) coordinates.
|
|
25
|
+
* for clarity reasons I decided not to store actual (0, 1) coordinates but
|
|
26
|
+
* provide width and height, so user can compute ratio himself if needed
|
|
27
|
+
*
|
|
28
|
+
* @category Type
|
|
29
|
+
* @author Artem Tyurin <artem.tyurin@gmail.com>
|
|
30
|
+
*/
|
|
31
|
+
export type Scaled = {
|
|
32
|
+
x1: number;
|
|
33
|
+
y1: number;
|
|
34
|
+
x2: number;
|
|
35
|
+
y2: number;
|
|
36
|
+
width: number;
|
|
37
|
+
height: number;
|
|
38
|
+
/** 1-Indexed page number */
|
|
39
|
+
pageNumber: number;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Position of a Highlight relative to the viewport.
|
|
43
|
+
*
|
|
44
|
+
* @category Type
|
|
45
|
+
*/
|
|
46
|
+
export type ViewportPosition = {
|
|
47
|
+
/** Bounding rectangle for the entire highlight. */
|
|
48
|
+
boundingRect: LTWHP;
|
|
49
|
+
/** For text highlights, the rectangular highlights for each block of text. */
|
|
50
|
+
rects: Array<LTWHP>;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Position of a Highlight with normalised coordinates.
|
|
54
|
+
*
|
|
55
|
+
* @category Type
|
|
56
|
+
*/
|
|
57
|
+
export type ScaledPosition = {
|
|
58
|
+
/** Bounding rectangle for the entire highlight. */
|
|
59
|
+
boundingRect: Scaled;
|
|
60
|
+
/** For text highlights, the rectangular highlights for each block of text. */
|
|
61
|
+
rects: Array<Scaled>;
|
|
62
|
+
/** Rarely applicable property of whether coordinates should be in PDF coordinate space. */
|
|
63
|
+
usePdfCoordinates?: boolean;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* A point in a drawing stroke.
|
|
67
|
+
*
|
|
68
|
+
* @category Type
|
|
69
|
+
*/
|
|
70
|
+
export type DrawingPoint = {
|
|
71
|
+
x: number;
|
|
72
|
+
y: number;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* A stroke in a drawing, with its own color and width.
|
|
76
|
+
*
|
|
77
|
+
* @category Type
|
|
78
|
+
*/
|
|
79
|
+
export type DrawingStroke = {
|
|
80
|
+
points: DrawingPoint[];
|
|
81
|
+
color: string;
|
|
82
|
+
width: number;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Shape types for shape annotations.
|
|
86
|
+
*
|
|
87
|
+
* @category Type
|
|
88
|
+
*/
|
|
89
|
+
export type ShapeType = "rectangle" | "circle" | "arrow";
|
|
90
|
+
/**
|
|
91
|
+
* Shape data for shape highlights.
|
|
92
|
+
*
|
|
93
|
+
* @category Type
|
|
94
|
+
*/
|
|
95
|
+
export type ShapeData = {
|
|
96
|
+
shapeType: ShapeType;
|
|
97
|
+
strokeColor: string;
|
|
98
|
+
strokeWidth: number;
|
|
99
|
+
/** For arrows: start point as percentage of bounding box (0-1) */
|
|
100
|
+
startPoint?: {
|
|
101
|
+
x: number;
|
|
102
|
+
y: number;
|
|
103
|
+
};
|
|
104
|
+
/** For arrows: end point as percentage of bounding box (0-1) */
|
|
105
|
+
endPoint?: {
|
|
106
|
+
x: number;
|
|
107
|
+
y: number;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* The content of a highlight
|
|
112
|
+
*
|
|
113
|
+
* @category Type
|
|
114
|
+
*/
|
|
115
|
+
export type Content = {
|
|
116
|
+
text?: string;
|
|
117
|
+
image?: string;
|
|
118
|
+
/** For drawing highlights, store the stroke data for later editing */
|
|
119
|
+
strokes?: DrawingStroke[];
|
|
120
|
+
/** For shape highlights, store the shape data */
|
|
121
|
+
shape?: ShapeData;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* What type the highlight is. This is the ideal way to determine whether to
|
|
125
|
+
* render it in an AreaHighlight or TextHighlight.
|
|
126
|
+
*
|
|
127
|
+
* @category Type
|
|
128
|
+
*/
|
|
129
|
+
export type HighlightType = "text" | "area" | "freetext" | "image" | "drawing" | "shape";
|
|
130
|
+
/**
|
|
131
|
+
* This represents a selected (text/mouse) area that has been turned into a
|
|
132
|
+
* highlight. If you are storing highlights, they should be stored as this type.
|
|
133
|
+
*
|
|
134
|
+
* @category Type
|
|
135
|
+
*/
|
|
136
|
+
export interface Highlight {
|
|
137
|
+
id: string;
|
|
138
|
+
/**
|
|
139
|
+
* This property is planned to be non-optional in future.
|
|
140
|
+
*/
|
|
141
|
+
type?: HighlightType;
|
|
142
|
+
/**
|
|
143
|
+
* @deprecated If you want your highlight to store content after being a
|
|
144
|
+
* GhostHighlight, you should create your own interface extended off this. If
|
|
145
|
+
* you are currently using this property to determine what kind of highlight
|
|
146
|
+
* to render, please use {@link type}.
|
|
147
|
+
*/
|
|
148
|
+
content?: Content;
|
|
149
|
+
position: ScaledPosition;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* This represents a temporary highlight and is ideal as an intermediary between
|
|
153
|
+
* a selection and a highlight.
|
|
154
|
+
*
|
|
155
|
+
* @category Type
|
|
156
|
+
*/
|
|
157
|
+
export interface GhostHighlight extends Required<Omit<Highlight, "id">> {
|
|
158
|
+
content: Content;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* This represents a rendered highlight, with its position defined by the page
|
|
162
|
+
* viewport.
|
|
163
|
+
*
|
|
164
|
+
* @category Type
|
|
165
|
+
*/
|
|
166
|
+
export type ViewportHighlight<T extends Highlight = Highlight> = Omit<T, "position"> & {
|
|
167
|
+
position: ViewportPosition;
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* An area or text selection in a PDF Document.
|
|
171
|
+
*
|
|
172
|
+
* @category Type
|
|
173
|
+
*/
|
|
174
|
+
export type PdfSelection = GhostHighlight & {
|
|
175
|
+
/** Convert the current selection into a temporary highlight */
|
|
176
|
+
makeGhostHighlight(): GhostHighlight;
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* A PDF.js page representation. This is the reference type for every page in the PdfHighlighter.
|
|
180
|
+
*
|
|
181
|
+
* @category Type
|
|
182
|
+
*/
|
|
183
|
+
export type Page = {
|
|
184
|
+
node: HTMLElement;
|
|
185
|
+
/** 1-Index page number */
|
|
186
|
+
number: number;
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* All the DOM refs for a group of highlights on one page
|
|
190
|
+
*
|
|
191
|
+
* @category Type
|
|
192
|
+
*/
|
|
193
|
+
export type HighlightBindings = {
|
|
194
|
+
reactRoot: Root;
|
|
195
|
+
container: Element;
|
|
196
|
+
textLayer: HTMLElement;
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* A popup that can be viewed inside a PdfHighlighter.
|
|
200
|
+
*
|
|
201
|
+
* @category Type
|
|
202
|
+
*/
|
|
203
|
+
export type Tip = {
|
|
204
|
+
position: ViewportPosition;
|
|
205
|
+
content: ReactNode;
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* The accepted scale values by the PDF.js viewer.
|
|
209
|
+
* Numeric entries accept floats, e.g. 1.2 = 120%
|
|
210
|
+
*
|
|
211
|
+
* @category Type
|
|
212
|
+
*/
|
|
213
|
+
export type PdfScaleValue = "page-actual" | "page-width" | "page-height" | "page-fit" | "auto" | number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-pdf-highlighter-plus",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Set of modern React components for PDF highlighting",
|
|
6
|
+
"author": "Edward Ha <quocvietha08@gmail.com>",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"contributors": [
|
|
9
|
+
{
|
|
10
|
+
"name": "Edward Ha",
|
|
11
|
+
"email": "quocvietha08@gmail.com"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"keywords": [
|
|
15
|
+
"pdf",
|
|
16
|
+
"pdf-annotator",
|
|
17
|
+
"react-pdf",
|
|
18
|
+
"react-pdf-annotator",
|
|
19
|
+
"highlight",
|
|
20
|
+
"annotator",
|
|
21
|
+
"react-component",
|
|
22
|
+
"react"
|
|
23
|
+
],
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"main": "./dist/esm/index.js",
|
|
28
|
+
"module": "./dist/esm/index.js",
|
|
29
|
+
"types": "./dist/esm/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/esm/index.d.ts",
|
|
33
|
+
"import": "./dist/esm/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./style/*": "./dist/esm/style/*"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"start": "npm run dev",
|
|
39
|
+
"dev": "(cd ./example && vite --force)",
|
|
40
|
+
"build": "npm run clean && npm i && npm run build:esm && npm run build:copy-styles && npm run build:example && npm run build:docs",
|
|
41
|
+
"build:vercel": "npm run build:esm && npm run build:copy-styles && npm run build:example && npm run build:docs",
|
|
42
|
+
"build:esm": "tsc",
|
|
43
|
+
"build:copy-styles": "cp -r ./src/style ./dist/esm",
|
|
44
|
+
"build:example": "(cd ./example && npm install && tsc && vite build && mkdir -p \"../public/\" && cp -r example-app ../public/)",
|
|
45
|
+
"build:docs": "npx typedoc",
|
|
46
|
+
"clean": "rm -rf dist public node_modules package-lock.json"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"react": "^18.3.1",
|
|
50
|
+
"react-dom": "^18.3.1"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@radix-ui/react-collapsible": "^1.1.12",
|
|
54
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
55
|
+
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
56
|
+
"@radix-ui/react-popover": "^1.1.15",
|
|
57
|
+
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
58
|
+
"@radix-ui/react-select": "^2.2.6",
|
|
59
|
+
"@radix-ui/react-separator": "^1.1.8",
|
|
60
|
+
"@radix-ui/react-slider": "^1.3.6",
|
|
61
|
+
"@radix-ui/react-slot": "^1.2.4",
|
|
62
|
+
"@radix-ui/react-toggle-group": "^1.1.11",
|
|
63
|
+
"@radix-ui/react-tooltip": "^1.2.8",
|
|
64
|
+
"class-variance-authority": "^0.7.1",
|
|
65
|
+
"clsx": "^2.1.1",
|
|
66
|
+
"lodash.debounce": "^4.0.8",
|
|
67
|
+
"lucide-react": "^0.559.0",
|
|
68
|
+
"pdf-lib": "^1.17.1",
|
|
69
|
+
"pdfjs-dist": "^4.4.168",
|
|
70
|
+
"react-rnd": "^10.4.11",
|
|
71
|
+
"tailwind-merge": "^3.4.0"
|
|
72
|
+
},
|
|
73
|
+
"repository": {
|
|
74
|
+
"type": "git",
|
|
75
|
+
"url": "git+https://github.com/QuocVietHa08/react-pdf-highlighter-plus"
|
|
76
|
+
},
|
|
77
|
+
"devDependencies": {
|
|
78
|
+
"@types/lodash.debounce": "^4.0.9",
|
|
79
|
+
"@types/node": "^20.14.9",
|
|
80
|
+
"@types/react": "^18.3.3",
|
|
81
|
+
"@types/react-dom": "^18.3.0",
|
|
82
|
+
"@vitejs/plugin-react": "^4.3.1",
|
|
83
|
+
"autoprefixer": "^10.4.22",
|
|
84
|
+
"postcss": "^8.5.6",
|
|
85
|
+
"tailwindcss": "^3.4.0",
|
|
86
|
+
"typedoc": "latest",
|
|
87
|
+
"typedoc-theme-category-nav": "latest",
|
|
88
|
+
"typescript": "^5.3.2",
|
|
89
|
+
"vite": "^5.3.3"
|
|
90
|
+
}
|
|
91
|
+
}
|