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