@embedpdf/plugin-annotation 1.0.13 → 1.0.15
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/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +103 -49
- package/dist/index.js.map +1 -1
- package/dist/lib/annotation-plugin.d.ts +1 -0
- package/dist/lib/helpers.d.ts +9 -2
- package/dist/lib/types.d.ts +48 -7
- package/dist/preact/adapter.d.ts +6 -0
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +500 -9
- package/dist/preact/index.js.map +1 -1
- package/dist/react/adapter.d.ts +6 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +500 -9
- package/dist/react/index.js.map +1 -1
- package/dist/shared-preact/components/annotation-container.d.ts +4 -2
- package/dist/shared-preact/components/annotations/free-text-paint.d.ts +10 -0
- package/dist/shared-preact/components/annotations/free-text.d.ts +13 -0
- package/dist/shared-preact/components/annotations/stamp-paint.d.ts +8 -0
- package/dist/shared-preact/components/annotations/stamp.d.ts +12 -0
- package/dist/shared-preact/components/render-annotation.d.ts +1 -1
- package/dist/shared-preact/hooks/use-drag-resize.d.ts +5 -2
- package/dist/shared-react/components/annotation-container.d.ts +4 -2
- package/dist/shared-react/components/annotations/free-text-paint.d.ts +10 -0
- package/dist/shared-react/components/annotations/free-text.d.ts +13 -0
- package/dist/shared-react/components/annotations/stamp-paint.d.ts +8 -0
- package/dist/shared-react/components/annotations/stamp.d.ts +12 -0
- package/dist/shared-react/components/render-annotation.d.ts +1 -1
- package/dist/shared-react/hooks/use-drag-resize.d.ts +5 -2
- package/package.json +9 -9
package/dist/react/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { usePlugin, useCapability } from "@embedpdf/core/react";
|
|
2
|
-
import { AnnotationPlugin, patching, getAnnotationsByPageIndex, getSelectedAnnotationByPageIndex, isInk, isSquare, isCircle, isUnderline, isStrikeout, isSquiggly, isHighlight, isLine, isPolyline, isPolygon,
|
|
2
|
+
import { AnnotationPlugin, patching, getAnnotationsByPageIndex, getSelectedAnnotationByPageIndex, isInk, isSquare, isCircle, isUnderline, isStrikeout, isSquiggly, isHighlight, isLine, isPolyline, isPolygon, isFreeText, isStamp } from "@embedpdf/plugin-annotation";
|
|
3
3
|
import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime";
|
|
4
|
-
import { restoreOffset, rectEquals, PdfAnnotationBorderStyle, PdfAnnotationSubtype, expandRect, rectFromPoints, blendModeToCss, PdfBlendMode } from "@embedpdf/models";
|
|
4
|
+
import { restoreOffset, rectEquals, PdfAnnotationBorderStyle, PdfAnnotationSubtype, expandRect, rectFromPoints, textAlignmentToCss, standardFontCss, PdfVerticalAlignment, ignore, PdfErrorCode, blendModeToCss, PdfBlendMode } from "@embedpdf/models";
|
|
5
5
|
import { usePointerHandlers } from "@embedpdf/plugin-interaction-manager/react";
|
|
6
6
|
import { useSelectionCapability } from "@embedpdf/plugin-selection/react";
|
|
7
7
|
import { Fragment, useState, useRef, useEffect, useLayoutEffect, useMemo, useCallback } from "react";
|
|
8
8
|
const useAnnotationPlugin = () => usePlugin(AnnotationPlugin.id);
|
|
9
9
|
const useAnnotationCapability = () => useCapability(AnnotationPlugin.id);
|
|
10
|
+
const mapDoubleClick = (handler) => handler ? { onDoubleClick: handler } : {};
|
|
10
11
|
function getCounterRotation(rect, rotation) {
|
|
11
12
|
const { width: w, height: h } = rect.size;
|
|
12
13
|
switch (rotation % 4) {
|
|
@@ -149,6 +150,7 @@ function useDragResize({
|
|
|
149
150
|
isResizable,
|
|
150
151
|
computePatch,
|
|
151
152
|
computeVertices,
|
|
153
|
+
lockAspectRatio = false,
|
|
152
154
|
currentRect,
|
|
153
155
|
setCurrentRect,
|
|
154
156
|
setCurrentVertices,
|
|
@@ -183,6 +185,23 @@ function useDragResize({
|
|
|
183
185
|
oy += dy;
|
|
184
186
|
h -= dy;
|
|
185
187
|
}
|
|
188
|
+
if (lockAspectRatio && startRect.current) {
|
|
189
|
+
const ratio = startRect.current.size.width / startRect.current.size.height;
|
|
190
|
+
const anchorRight = ox + w;
|
|
191
|
+
const anchorBottom = oy + h;
|
|
192
|
+
const horizontalPrimary = dir.current.includes("left") || dir.current.includes("right");
|
|
193
|
+
if (horizontalPrimary) {
|
|
194
|
+
h = w / ratio;
|
|
195
|
+
} else {
|
|
196
|
+
w = h * ratio;
|
|
197
|
+
}
|
|
198
|
+
if (dir.current.includes("left")) {
|
|
199
|
+
ox = anchorRight - w;
|
|
200
|
+
}
|
|
201
|
+
if (dir.current.includes("top")) {
|
|
202
|
+
oy = anchorBottom - h;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
186
205
|
}
|
|
187
206
|
if (w < 1 || h < 1) return currentRect;
|
|
188
207
|
w = clamp(w, 1, pageW);
|
|
@@ -219,8 +238,14 @@ function useDragResize({
|
|
|
219
238
|
setCurrentRect(patch.rect ?? nextRect);
|
|
220
239
|
setPreviewObject(patch);
|
|
221
240
|
};
|
|
222
|
-
const onPointerUp = () => {
|
|
241
|
+
const onPointerUp = (e) => {
|
|
223
242
|
if (drag.current === "idle") return;
|
|
243
|
+
if ((e == null ? void 0 : e.currentTarget) && e.pointerId !== void 0) {
|
|
244
|
+
try {
|
|
245
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
246
|
+
} catch {
|
|
247
|
+
}
|
|
248
|
+
}
|
|
224
249
|
const usedDir = dir.current || "bottom-right";
|
|
225
250
|
drag.current = "idle";
|
|
226
251
|
let patch = { rect: currentRect };
|
|
@@ -256,7 +281,9 @@ function useDragResize({
|
|
|
256
281
|
rootHandlers: {
|
|
257
282
|
onPointerDown,
|
|
258
283
|
onPointerMove,
|
|
259
|
-
onPointerUp
|
|
284
|
+
onPointerUp,
|
|
285
|
+
onPointerCancel: () => onPointerUp(),
|
|
286
|
+
onLostPointerCapture: () => onPointerUp()
|
|
260
287
|
},
|
|
261
288
|
startResize
|
|
262
289
|
};
|
|
@@ -334,9 +361,11 @@ function AnnotationContainer({
|
|
|
334
361
|
isSelected = false,
|
|
335
362
|
isDraggable = true,
|
|
336
363
|
isResizable = true,
|
|
364
|
+
lockAspectRatio = false,
|
|
337
365
|
computeVertices,
|
|
338
366
|
computePatch,
|
|
339
367
|
selectionMenu,
|
|
368
|
+
onDoubleClick,
|
|
340
369
|
...props
|
|
341
370
|
}) {
|
|
342
371
|
const { provides: annotationProvides } = useAnnotationCapability();
|
|
@@ -354,6 +383,7 @@ function AnnotationContainer({
|
|
|
354
383
|
isSelected,
|
|
355
384
|
isDraggable,
|
|
356
385
|
isResizable,
|
|
386
|
+
lockAspectRatio,
|
|
357
387
|
computePatch,
|
|
358
388
|
computeVertices,
|
|
359
389
|
currentRect,
|
|
@@ -375,6 +405,7 @@ function AnnotationContainer({
|
|
|
375
405
|
"div",
|
|
376
406
|
{
|
|
377
407
|
...rootHandlers,
|
|
408
|
+
...mapDoubleClick(onDoubleClick),
|
|
378
409
|
style: {
|
|
379
410
|
position: "absolute",
|
|
380
411
|
outline: isSelected ? "1px solid #007ACC" : "none",
|
|
@@ -385,6 +416,9 @@ function AnnotationContainer({
|
|
|
385
416
|
height: `${currentRect.size.height * scale}px`,
|
|
386
417
|
pointerEvents: isSelected ? "auto" : "none",
|
|
387
418
|
cursor: isSelected && isDraggable ? "move" : "default",
|
|
419
|
+
...isSelected && {
|
|
420
|
+
zIndex: 3
|
|
421
|
+
},
|
|
388
422
|
...style
|
|
389
423
|
},
|
|
390
424
|
...props,
|
|
@@ -1191,6 +1225,158 @@ const patchPolygon = (orig, ctx) => {
|
|
|
1191
1225
|
vertices: moved
|
|
1192
1226
|
};
|
|
1193
1227
|
};
|
|
1228
|
+
function FreeText({
|
|
1229
|
+
isSelected,
|
|
1230
|
+
isEditing,
|
|
1231
|
+
annotation,
|
|
1232
|
+
pageIndex,
|
|
1233
|
+
scale,
|
|
1234
|
+
onClick
|
|
1235
|
+
}) {
|
|
1236
|
+
const editorRef = useRef(null);
|
|
1237
|
+
const { provides: annotationProvides } = useAnnotationCapability();
|
|
1238
|
+
useEffect(() => {
|
|
1239
|
+
if (isEditing && editorRef.current) {
|
|
1240
|
+
const editor = editorRef.current;
|
|
1241
|
+
editor.focus();
|
|
1242
|
+
const selection = window.getSelection();
|
|
1243
|
+
if (selection) {
|
|
1244
|
+
const range = document.createRange();
|
|
1245
|
+
range.selectNodeContents(editor);
|
|
1246
|
+
range.collapse(false);
|
|
1247
|
+
selection.removeAllRanges();
|
|
1248
|
+
selection.addRange(range);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
}, [isEditing]);
|
|
1252
|
+
const handleBlur = () => {
|
|
1253
|
+
if (!annotationProvides) return;
|
|
1254
|
+
if (!editorRef.current) return;
|
|
1255
|
+
annotationProvides.updateAnnotation(pageIndex, annotation.localId, {
|
|
1256
|
+
contents: editorRef.current.innerText
|
|
1257
|
+
});
|
|
1258
|
+
};
|
|
1259
|
+
return /* @__PURE__ */ jsx(
|
|
1260
|
+
"div",
|
|
1261
|
+
{
|
|
1262
|
+
style: {
|
|
1263
|
+
position: "absolute",
|
|
1264
|
+
width: annotation.object.rect.size.width * scale,
|
|
1265
|
+
height: annotation.object.rect.size.height * scale,
|
|
1266
|
+
cursor: isSelected && !isEditing ? "move" : "default",
|
|
1267
|
+
pointerEvents: isSelected && !isEditing ? "none" : "auto",
|
|
1268
|
+
zIndex: 2
|
|
1269
|
+
},
|
|
1270
|
+
onPointerDown: onClick,
|
|
1271
|
+
children: /* @__PURE__ */ jsx(
|
|
1272
|
+
"span",
|
|
1273
|
+
{
|
|
1274
|
+
ref: editorRef,
|
|
1275
|
+
onBlur: handleBlur,
|
|
1276
|
+
style: {
|
|
1277
|
+
color: annotation.object.fontColor,
|
|
1278
|
+
fontSize: annotation.object.fontSize * scale,
|
|
1279
|
+
fontFamily: standardFontCss(annotation.object.fontFamily),
|
|
1280
|
+
textAlign: textAlignmentToCss(annotation.object.textAlign),
|
|
1281
|
+
flexDirection: "column",
|
|
1282
|
+
justifyContent: annotation.object.verticalAlign === PdfVerticalAlignment.Top ? "flex-start" : annotation.object.verticalAlign === PdfVerticalAlignment.Middle ? "center" : "flex-end",
|
|
1283
|
+
display: "flex",
|
|
1284
|
+
backgroundColor: annotation.object.backgroundColor,
|
|
1285
|
+
opacity: annotation.object.opacity,
|
|
1286
|
+
width: "100%",
|
|
1287
|
+
height: "100%",
|
|
1288
|
+
lineHeight: "1.18",
|
|
1289
|
+
overflow: "hidden",
|
|
1290
|
+
cursor: isEditing ? "text" : "pointer"
|
|
1291
|
+
},
|
|
1292
|
+
contentEditable: isEditing,
|
|
1293
|
+
suppressContentEditableWarning: true,
|
|
1294
|
+
children: annotation.object.contents
|
|
1295
|
+
}
|
|
1296
|
+
)
|
|
1297
|
+
}
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
function RenderAnnotation({
|
|
1301
|
+
pageIndex,
|
|
1302
|
+
annotation,
|
|
1303
|
+
scaleFactor = 1,
|
|
1304
|
+
style,
|
|
1305
|
+
...props
|
|
1306
|
+
}) {
|
|
1307
|
+
const { provides: annotationProvides } = useAnnotationCapability();
|
|
1308
|
+
const [imageUrl, setImageUrl] = useState(null);
|
|
1309
|
+
const urlRef = useRef(null);
|
|
1310
|
+
const { width, height } = annotation.rect.size;
|
|
1311
|
+
useEffect(() => {
|
|
1312
|
+
if (annotationProvides) {
|
|
1313
|
+
const task = annotationProvides.renderAnnotation({
|
|
1314
|
+
pageIndex,
|
|
1315
|
+
annotation,
|
|
1316
|
+
scaleFactor,
|
|
1317
|
+
dpr: window.devicePixelRatio
|
|
1318
|
+
});
|
|
1319
|
+
task.wait((blob) => {
|
|
1320
|
+
const url = URL.createObjectURL(blob);
|
|
1321
|
+
setImageUrl(url);
|
|
1322
|
+
urlRef.current = url;
|
|
1323
|
+
}, ignore);
|
|
1324
|
+
return () => {
|
|
1325
|
+
if (urlRef.current) {
|
|
1326
|
+
URL.revokeObjectURL(urlRef.current);
|
|
1327
|
+
urlRef.current = null;
|
|
1328
|
+
} else {
|
|
1329
|
+
task.abort({
|
|
1330
|
+
code: PdfErrorCode.Cancelled,
|
|
1331
|
+
message: "canceled render task"
|
|
1332
|
+
});
|
|
1333
|
+
}
|
|
1334
|
+
};
|
|
1335
|
+
}
|
|
1336
|
+
}, [pageIndex, scaleFactor, annotationProvides, annotation.id, width, height]);
|
|
1337
|
+
const handleImageLoad = () => {
|
|
1338
|
+
if (urlRef.current) {
|
|
1339
|
+
URL.revokeObjectURL(urlRef.current);
|
|
1340
|
+
urlRef.current = null;
|
|
1341
|
+
}
|
|
1342
|
+
};
|
|
1343
|
+
return /* @__PURE__ */ jsx(Fragment, { children: imageUrl && /* @__PURE__ */ jsx(
|
|
1344
|
+
"img",
|
|
1345
|
+
{
|
|
1346
|
+
src: imageUrl,
|
|
1347
|
+
onLoad: handleImageLoad,
|
|
1348
|
+
...props,
|
|
1349
|
+
style: {
|
|
1350
|
+
width: "100%",
|
|
1351
|
+
height: "100%",
|
|
1352
|
+
...style || {}
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
) });
|
|
1356
|
+
}
|
|
1357
|
+
function Stamp({ isSelected, annotation, pageIndex, scale, onClick }) {
|
|
1358
|
+
return /* @__PURE__ */ jsx(
|
|
1359
|
+
"div",
|
|
1360
|
+
{
|
|
1361
|
+
style: {
|
|
1362
|
+
position: "absolute",
|
|
1363
|
+
width: "100%",
|
|
1364
|
+
height: "100%",
|
|
1365
|
+
zIndex: 2,
|
|
1366
|
+
pointerEvents: isSelected ? "none" : "auto"
|
|
1367
|
+
},
|
|
1368
|
+
onPointerDown: onClick,
|
|
1369
|
+
children: annotation.pdfId !== void 0 && /* @__PURE__ */ jsx(
|
|
1370
|
+
RenderAnnotation,
|
|
1371
|
+
{
|
|
1372
|
+
pageIndex,
|
|
1373
|
+
annotation: { ...annotation.object, id: annotation.pdfId },
|
|
1374
|
+
scaleFactor: scale
|
|
1375
|
+
}
|
|
1376
|
+
)
|
|
1377
|
+
}
|
|
1378
|
+
);
|
|
1379
|
+
}
|
|
1194
1380
|
function Annotations(annotationsProps) {
|
|
1195
1381
|
const { pageIndex, scale, selectionMenu } = annotationsProps;
|
|
1196
1382
|
const { provides: annotationProvides } = useAnnotationCapability();
|
|
@@ -1198,6 +1384,7 @@ function Annotations(annotationsProps) {
|
|
|
1198
1384
|
const [annotations, setAnnotations] = useState([]);
|
|
1199
1385
|
const { register } = usePointerHandlers({ pageIndex });
|
|
1200
1386
|
const [selectionState, setSelectionState] = useState(null);
|
|
1387
|
+
const [editingId, setEditingId] = useState(null);
|
|
1201
1388
|
useEffect(() => {
|
|
1202
1389
|
if (annotationProvides) {
|
|
1203
1390
|
annotationProvides.onStateChange((state) => {
|
|
@@ -1211,6 +1398,7 @@ function Annotations(annotationsProps) {
|
|
|
1211
1398
|
onPointerDown: (_, pe) => {
|
|
1212
1399
|
if (pe.target === pe.currentTarget && annotationProvides) {
|
|
1213
1400
|
annotationProvides.deselectAnnotation();
|
|
1401
|
+
setEditingId(null);
|
|
1214
1402
|
}
|
|
1215
1403
|
}
|
|
1216
1404
|
}),
|
|
@@ -1222,6 +1410,7 @@ function Annotations(annotationsProps) {
|
|
|
1222
1410
|
if (annotationProvides && selectionProvides) {
|
|
1223
1411
|
annotationProvides.selectAnnotation(pageIndex, annotation.localId);
|
|
1224
1412
|
selectionProvides.clear();
|
|
1413
|
+
setEditingId(null);
|
|
1225
1414
|
}
|
|
1226
1415
|
},
|
|
1227
1416
|
[annotationProvides, selectionProvides, pageIndex]
|
|
@@ -1231,6 +1420,7 @@ function Annotations(annotationsProps) {
|
|
|
1231
1420
|
}, [register, handlers]);
|
|
1232
1421
|
return /* @__PURE__ */ jsx(Fragment$1, { children: annotations.map((annotation) => {
|
|
1233
1422
|
const isSelected = (selectionState == null ? void 0 : selectionState.localId) === annotation.localId;
|
|
1423
|
+
const isEditing = editingId === annotation.localId;
|
|
1234
1424
|
if (isInk(annotation)) {
|
|
1235
1425
|
return /* @__PURE__ */ jsx(
|
|
1236
1426
|
AnnotationContainer,
|
|
@@ -1546,6 +1736,70 @@ function Annotations(annotationsProps) {
|
|
|
1546
1736
|
annotation.localId
|
|
1547
1737
|
);
|
|
1548
1738
|
}
|
|
1739
|
+
if (isFreeText(annotation)) {
|
|
1740
|
+
return /* @__PURE__ */ jsx(
|
|
1741
|
+
AnnotationContainer,
|
|
1742
|
+
{
|
|
1743
|
+
trackedAnnotation: annotation,
|
|
1744
|
+
isSelected,
|
|
1745
|
+
isDraggable: true,
|
|
1746
|
+
isResizable: true,
|
|
1747
|
+
selectionMenu,
|
|
1748
|
+
outlineOffset: 6,
|
|
1749
|
+
onDoubleClick: (e) => {
|
|
1750
|
+
e.stopPropagation();
|
|
1751
|
+
setEditingId(annotation.localId);
|
|
1752
|
+
},
|
|
1753
|
+
style: {
|
|
1754
|
+
mixBlendMode: blendModeToCss(annotation.object.blendMode ?? PdfBlendMode.Normal)
|
|
1755
|
+
},
|
|
1756
|
+
...annotationsProps,
|
|
1757
|
+
children: (object) => /* @__PURE__ */ jsx(
|
|
1758
|
+
FreeText,
|
|
1759
|
+
{
|
|
1760
|
+
isSelected,
|
|
1761
|
+
isEditing,
|
|
1762
|
+
annotation: {
|
|
1763
|
+
...annotation,
|
|
1764
|
+
object
|
|
1765
|
+
},
|
|
1766
|
+
pageIndex,
|
|
1767
|
+
scale,
|
|
1768
|
+
onClick: (e) => handleClick(e, annotation)
|
|
1769
|
+
}
|
|
1770
|
+
)
|
|
1771
|
+
},
|
|
1772
|
+
annotation.localId
|
|
1773
|
+
);
|
|
1774
|
+
}
|
|
1775
|
+
if (isStamp(annotation)) {
|
|
1776
|
+
return /* @__PURE__ */ jsx(
|
|
1777
|
+
AnnotationContainer,
|
|
1778
|
+
{
|
|
1779
|
+
trackedAnnotation: annotation,
|
|
1780
|
+
isSelected,
|
|
1781
|
+
isDraggable: true,
|
|
1782
|
+
isResizable: true,
|
|
1783
|
+
selectionMenu,
|
|
1784
|
+
lockAspectRatio: true,
|
|
1785
|
+
style: {
|
|
1786
|
+
mixBlendMode: blendModeToCss(annotation.object.blendMode ?? PdfBlendMode.Normal)
|
|
1787
|
+
},
|
|
1788
|
+
...annotationsProps,
|
|
1789
|
+
children: (_object) => /* @__PURE__ */ jsx(
|
|
1790
|
+
Stamp,
|
|
1791
|
+
{
|
|
1792
|
+
isSelected,
|
|
1793
|
+
annotation,
|
|
1794
|
+
pageIndex,
|
|
1795
|
+
scale,
|
|
1796
|
+
onClick: (e) => handleClick(e, annotation)
|
|
1797
|
+
}
|
|
1798
|
+
)
|
|
1799
|
+
},
|
|
1800
|
+
annotation.localId
|
|
1801
|
+
);
|
|
1802
|
+
}
|
|
1549
1803
|
return null;
|
|
1550
1804
|
}) });
|
|
1551
1805
|
}
|
|
@@ -1570,8 +1824,9 @@ function TextMarkup({ pageIndex, scale }) {
|
|
|
1570
1824
|
return off;
|
|
1571
1825
|
}, [annotationProvides]);
|
|
1572
1826
|
if (!boundingRect) return null;
|
|
1573
|
-
|
|
1574
|
-
|
|
1827
|
+
if (!activeTool.defaults) return null;
|
|
1828
|
+
switch (activeTool.defaults.subtype) {
|
|
1829
|
+
case PdfAnnotationSubtype.UNDERLINE:
|
|
1575
1830
|
return /* @__PURE__ */ jsx(
|
|
1576
1831
|
"div",
|
|
1577
1832
|
{
|
|
@@ -1592,7 +1847,7 @@ function TextMarkup({ pageIndex, scale }) {
|
|
|
1592
1847
|
)
|
|
1593
1848
|
}
|
|
1594
1849
|
);
|
|
1595
|
-
case
|
|
1850
|
+
case PdfAnnotationSubtype.HIGHLIGHT:
|
|
1596
1851
|
return /* @__PURE__ */ jsx(
|
|
1597
1852
|
"div",
|
|
1598
1853
|
{
|
|
@@ -1613,7 +1868,7 @@ function TextMarkup({ pageIndex, scale }) {
|
|
|
1613
1868
|
)
|
|
1614
1869
|
}
|
|
1615
1870
|
);
|
|
1616
|
-
case
|
|
1871
|
+
case PdfAnnotationSubtype.STRIKEOUT:
|
|
1617
1872
|
return /* @__PURE__ */ jsx(
|
|
1618
1873
|
"div",
|
|
1619
1874
|
{
|
|
@@ -1634,7 +1889,7 @@ function TextMarkup({ pageIndex, scale }) {
|
|
|
1634
1889
|
)
|
|
1635
1890
|
}
|
|
1636
1891
|
);
|
|
1637
|
-
case
|
|
1892
|
+
case PdfAnnotationSubtype.SQUIGGLY:
|
|
1638
1893
|
return /* @__PURE__ */ jsx(
|
|
1639
1894
|
"div",
|
|
1640
1895
|
{
|
|
@@ -2536,6 +2791,224 @@ const PolygonPaint = ({
|
|
|
2536
2791
|
}
|
|
2537
2792
|
);
|
|
2538
2793
|
};
|
|
2794
|
+
const FreeTextPaint = ({
|
|
2795
|
+
pageIndex,
|
|
2796
|
+
scale,
|
|
2797
|
+
pageWidth,
|
|
2798
|
+
pageHeight,
|
|
2799
|
+
cursor = "text"
|
|
2800
|
+
}) => {
|
|
2801
|
+
const { provides: annotationProvides } = useAnnotationCapability();
|
|
2802
|
+
const [activeTool, setActiveTool] = useState({ variantKey: null, defaults: null });
|
|
2803
|
+
useEffect(() => annotationProvides == null ? void 0 : annotationProvides.onActiveToolChange(setActiveTool), [annotationProvides]);
|
|
2804
|
+
if (!activeTool.defaults || activeTool.defaults.subtype !== PdfAnnotationSubtype.FREETEXT)
|
|
2805
|
+
return null;
|
|
2806
|
+
const toolFontColor = activeTool.defaults.fontColor ?? "#000000";
|
|
2807
|
+
const toolOpacity = activeTool.defaults.opacity ?? 1;
|
|
2808
|
+
const toolFontSize = activeTool.defaults.fontSize ?? 12;
|
|
2809
|
+
const toolFontFamily = activeTool.defaults.fontFamily;
|
|
2810
|
+
const toolBackgroundColor = activeTool.defaults.backgroundColor ?? "transparent";
|
|
2811
|
+
const toolTextAlign = activeTool.defaults.textAlign;
|
|
2812
|
+
const toolVerticalAlign = activeTool.defaults.verticalAlign;
|
|
2813
|
+
const toolContent = activeTool.defaults.content ?? "Insert text here";
|
|
2814
|
+
const { register } = usePointerHandlers({ modeId: "freeText", pageIndex });
|
|
2815
|
+
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
|
|
2816
|
+
const pageWidthPDF = pageWidth / scale;
|
|
2817
|
+
const pageHeightPDF = pageHeight / scale;
|
|
2818
|
+
const [start, setStart] = useState(null);
|
|
2819
|
+
const [current, setCurrent] = useState(null);
|
|
2820
|
+
const commitFreeText = (p1, p2) => {
|
|
2821
|
+
const minX2 = Math.min(p1.x, p2.x);
|
|
2822
|
+
const minY2 = Math.min(p1.y, p2.y);
|
|
2823
|
+
const maxX2 = Math.max(p1.x, p2.x);
|
|
2824
|
+
const maxY2 = Math.max(p1.y, p2.y);
|
|
2825
|
+
const w = maxX2 - minX2;
|
|
2826
|
+
const h = maxY2 - minY2;
|
|
2827
|
+
if (w < 1 || h < 1) return;
|
|
2828
|
+
const rect = {
|
|
2829
|
+
origin: { x: minX2, y: minY2 },
|
|
2830
|
+
size: { width: w, height: h }
|
|
2831
|
+
};
|
|
2832
|
+
const anno = {
|
|
2833
|
+
type: PdfAnnotationSubtype.FREETEXT,
|
|
2834
|
+
rect,
|
|
2835
|
+
contents: toolContent,
|
|
2836
|
+
fontColor: toolFontColor,
|
|
2837
|
+
fontSize: toolFontSize,
|
|
2838
|
+
fontFamily: toolFontFamily,
|
|
2839
|
+
opacity: toolOpacity,
|
|
2840
|
+
backgroundColor: toolBackgroundColor,
|
|
2841
|
+
textAlign: toolTextAlign,
|
|
2842
|
+
verticalAlign: toolVerticalAlign,
|
|
2843
|
+
pageIndex,
|
|
2844
|
+
id: Date.now() + Math.random()
|
|
2845
|
+
};
|
|
2846
|
+
annotationProvides.createAnnotation(pageIndex, anno);
|
|
2847
|
+
annotationProvides.setActiveVariant(null);
|
|
2848
|
+
annotationProvides.selectAnnotation(pageIndex, anno.id);
|
|
2849
|
+
};
|
|
2850
|
+
const handlers = useMemo(
|
|
2851
|
+
() => ({
|
|
2852
|
+
onPointerDown: (pos, evt) => {
|
|
2853
|
+
var _a, _b;
|
|
2854
|
+
const x = clamp(pos.x, 0, pageWidthPDF);
|
|
2855
|
+
const y = clamp(pos.y, 0, pageHeightPDF);
|
|
2856
|
+
setStart({ x, y });
|
|
2857
|
+
setCurrent({ x, y });
|
|
2858
|
+
(_b = (_a = evt.target) == null ? void 0 : _a.setPointerCapture) == null ? void 0 : _b.call(_a, evt.pointerId);
|
|
2859
|
+
},
|
|
2860
|
+
onPointerMove: (pos) => {
|
|
2861
|
+
if (!start) return;
|
|
2862
|
+
const x = clamp(pos.x, 0, pageWidthPDF);
|
|
2863
|
+
const y = clamp(pos.y, 0, pageHeightPDF);
|
|
2864
|
+
setCurrent({ x, y });
|
|
2865
|
+
},
|
|
2866
|
+
onPointerUp: (_, evt) => {
|
|
2867
|
+
var _a, _b;
|
|
2868
|
+
if (start && current && annotationProvides) {
|
|
2869
|
+
commitFreeText(start, current);
|
|
2870
|
+
}
|
|
2871
|
+
(_b = (_a = evt.target) == null ? void 0 : _a.releasePointerCapture) == null ? void 0 : _b.call(_a, evt.pointerId);
|
|
2872
|
+
setStart(null);
|
|
2873
|
+
setCurrent(null);
|
|
2874
|
+
},
|
|
2875
|
+
onPointerCancel: (_, evt) => {
|
|
2876
|
+
var _a, _b;
|
|
2877
|
+
(_b = (_a = evt.target) == null ? void 0 : _a.releasePointerCapture) == null ? void 0 : _b.call(_a, evt.pointerId);
|
|
2878
|
+
setStart(null);
|
|
2879
|
+
setCurrent(null);
|
|
2880
|
+
}
|
|
2881
|
+
}),
|
|
2882
|
+
[start, current, annotationProvides, pageWidthPDF, pageHeightPDF]
|
|
2883
|
+
);
|
|
2884
|
+
useEffect(() => register ? register(handlers) : void 0, [register, handlers]);
|
|
2885
|
+
if (!start || !current) return null;
|
|
2886
|
+
const minX = Math.min(start.x, current.x);
|
|
2887
|
+
const minY = Math.min(start.y, current.y);
|
|
2888
|
+
const maxX = Math.max(start.x, current.x);
|
|
2889
|
+
const maxY = Math.max(start.y, current.y);
|
|
2890
|
+
const dw = maxX - minX;
|
|
2891
|
+
const dh = maxY - minY;
|
|
2892
|
+
return /* @__PURE__ */ jsx(
|
|
2893
|
+
"svg",
|
|
2894
|
+
{
|
|
2895
|
+
style: {
|
|
2896
|
+
position: "absolute",
|
|
2897
|
+
left: minX * scale,
|
|
2898
|
+
top: minY * scale,
|
|
2899
|
+
width: dw * scale,
|
|
2900
|
+
height: dh * scale,
|
|
2901
|
+
pointerEvents: "none",
|
|
2902
|
+
zIndex: 2
|
|
2903
|
+
},
|
|
2904
|
+
width: dw * scale,
|
|
2905
|
+
height: dh * scale,
|
|
2906
|
+
viewBox: `0 0 ${dw} ${dh}`,
|
|
2907
|
+
children: /* @__PURE__ */ jsx(
|
|
2908
|
+
"rect",
|
|
2909
|
+
{
|
|
2910
|
+
x: 0,
|
|
2911
|
+
y: 0,
|
|
2912
|
+
width: dw,
|
|
2913
|
+
height: dh,
|
|
2914
|
+
fill: "transparent",
|
|
2915
|
+
style: {
|
|
2916
|
+
stroke: toolFontColor,
|
|
2917
|
+
strokeWidth: 1,
|
|
2918
|
+
strokeDasharray: "4,4",
|
|
2919
|
+
cursor
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
)
|
|
2923
|
+
}
|
|
2924
|
+
);
|
|
2925
|
+
};
|
|
2926
|
+
const StampPaint = ({ pageIndex, scale, pageWidth, pageHeight }) => {
|
|
2927
|
+
const { provides: annotationProvides } = useAnnotationCapability();
|
|
2928
|
+
const inputRef = useRef(null);
|
|
2929
|
+
const canvasRef = useRef(null);
|
|
2930
|
+
const [activeTool, setActiveTool] = useState({ variantKey: null, defaults: null });
|
|
2931
|
+
useEffect(() => {
|
|
2932
|
+
if (!annotationProvides) return;
|
|
2933
|
+
return annotationProvides.onActiveToolChange(setActiveTool);
|
|
2934
|
+
}, [annotationProvides]);
|
|
2935
|
+
if (!activeTool.defaults) return null;
|
|
2936
|
+
if (activeTool.defaults.subtype !== PdfAnnotationSubtype.STAMP) return null;
|
|
2937
|
+
const { register } = usePointerHandlers({ modeId: "stamp", pageIndex });
|
|
2938
|
+
const pageWidthPDF = pageWidth / scale;
|
|
2939
|
+
const pageHeightPDF = pageHeight / scale;
|
|
2940
|
+
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
|
|
2941
|
+
const [start, setStart] = useState(null);
|
|
2942
|
+
const handlers = useMemo(
|
|
2943
|
+
() => ({
|
|
2944
|
+
onPointerDown: (pos, evt) => {
|
|
2945
|
+
var _a;
|
|
2946
|
+
const x = clamp(pos.x, 0, pageWidthPDF);
|
|
2947
|
+
const y = clamp(pos.y, 0, pageHeightPDF);
|
|
2948
|
+
setStart({ x, y });
|
|
2949
|
+
(_a = inputRef.current) == null ? void 0 : _a.click();
|
|
2950
|
+
}
|
|
2951
|
+
}),
|
|
2952
|
+
[pageWidthPDF, pageHeightPDF]
|
|
2953
|
+
);
|
|
2954
|
+
useEffect(() => register ? register(handlers) : void 0, [register, handlers]);
|
|
2955
|
+
const onChange = async (e) => {
|
|
2956
|
+
var _a;
|
|
2957
|
+
if (!annotationProvides || !start) return;
|
|
2958
|
+
const file = (_a = e.currentTarget.files) == null ? void 0 : _a[0];
|
|
2959
|
+
if (!file) return;
|
|
2960
|
+
const img = await new Promise((res, rej) => {
|
|
2961
|
+
const i = new Image();
|
|
2962
|
+
i.onload = () => res(i);
|
|
2963
|
+
i.onerror = rej;
|
|
2964
|
+
i.src = URL.createObjectURL(file);
|
|
2965
|
+
});
|
|
2966
|
+
const imgW = img.naturalWidth;
|
|
2967
|
+
const imgH = img.naturalHeight;
|
|
2968
|
+
const maxW = pageWidthPDF;
|
|
2969
|
+
const maxH = pageHeightPDF;
|
|
2970
|
+
const scaleFactor = Math.min(1, maxW / imgW, maxH / imgH);
|
|
2971
|
+
const pdfW = imgW * scaleFactor;
|
|
2972
|
+
const pdfH = imgH * scaleFactor;
|
|
2973
|
+
const posX = clamp(start.x, 0, maxW - pdfW);
|
|
2974
|
+
const posY = clamp(start.y, 0, maxH - pdfH);
|
|
2975
|
+
const rect = {
|
|
2976
|
+
origin: { x: posX, y: posY },
|
|
2977
|
+
size: { width: pdfW, height: pdfH }
|
|
2978
|
+
};
|
|
2979
|
+
const canvas = canvasRef.current;
|
|
2980
|
+
if (!canvas) return;
|
|
2981
|
+
canvas.width = pdfW;
|
|
2982
|
+
canvas.height = pdfH;
|
|
2983
|
+
const ctx = canvas.getContext("2d");
|
|
2984
|
+
ctx.drawImage(img, 0, 0, pdfW, pdfH);
|
|
2985
|
+
const imageData = ctx.getImageData(0, 0, pdfW, pdfH);
|
|
2986
|
+
const anno = {
|
|
2987
|
+
type: PdfAnnotationSubtype.STAMP,
|
|
2988
|
+
flags: ["print"],
|
|
2989
|
+
pageIndex,
|
|
2990
|
+
id: Date.now() + Math.random(),
|
|
2991
|
+
rect
|
|
2992
|
+
};
|
|
2993
|
+
annotationProvides.createAnnotation(pageIndex, anno, { imageData });
|
|
2994
|
+
annotationProvides.setActiveVariant(null);
|
|
2995
|
+
annotationProvides.selectAnnotation(pageIndex, anno.id);
|
|
2996
|
+
setStart(null);
|
|
2997
|
+
};
|
|
2998
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2999
|
+
/* @__PURE__ */ jsx("canvas", { style: { display: "none" }, ref: canvasRef }),
|
|
3000
|
+
/* @__PURE__ */ jsx(
|
|
3001
|
+
"input",
|
|
3002
|
+
{
|
|
3003
|
+
ref: inputRef,
|
|
3004
|
+
type: "file",
|
|
3005
|
+
accept: "image/png,image/jpeg",
|
|
3006
|
+
style: { display: "none" },
|
|
3007
|
+
onChange
|
|
3008
|
+
}
|
|
3009
|
+
)
|
|
3010
|
+
] });
|
|
3011
|
+
};
|
|
2539
3012
|
function AnnotationLayer({
|
|
2540
3013
|
pageIndex,
|
|
2541
3014
|
scale,
|
|
@@ -2611,6 +3084,24 @@ function AnnotationLayer({
|
|
|
2611
3084
|
pageWidth,
|
|
2612
3085
|
pageHeight
|
|
2613
3086
|
}
|
|
3087
|
+
),
|
|
3088
|
+
/* @__PURE__ */ jsx(
|
|
3089
|
+
FreeTextPaint,
|
|
3090
|
+
{
|
|
3091
|
+
pageIndex,
|
|
3092
|
+
scale,
|
|
3093
|
+
pageWidth,
|
|
3094
|
+
pageHeight
|
|
3095
|
+
}
|
|
3096
|
+
),
|
|
3097
|
+
/* @__PURE__ */ jsx(
|
|
3098
|
+
StampPaint,
|
|
3099
|
+
{
|
|
3100
|
+
pageIndex,
|
|
3101
|
+
scale,
|
|
3102
|
+
pageWidth,
|
|
3103
|
+
pageHeight
|
|
3104
|
+
}
|
|
2614
3105
|
)
|
|
2615
3106
|
]
|
|
2616
3107
|
}
|