@anaralabs/lector 3.5.8 → 3.5.10
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/_tsup-dts-rollup.d.ts +29 -15
- package/dist/index.js +611 -98
- package/package.json +1 -1
|
@@ -24,40 +24,40 @@ import { Virtualizer } from '@tanstack/react-virtual';
|
|
|
24
24
|
declare interface Annotation {
|
|
25
25
|
id: string;
|
|
26
26
|
pageNumber: number;
|
|
27
|
-
highlights:
|
|
28
|
-
|
|
29
|
-
left: number;
|
|
30
|
-
top: number;
|
|
31
|
-
width: number;
|
|
32
|
-
pageNumber: number;
|
|
33
|
-
}>;
|
|
27
|
+
highlights: HighlightRect_alias_2[];
|
|
28
|
+
underlines?: HighlightRect_alias_2[];
|
|
34
29
|
color: string;
|
|
35
30
|
borderColor: string;
|
|
31
|
+
comment?: string;
|
|
36
32
|
createdAt: Date;
|
|
37
33
|
updatedAt: Date;
|
|
38
|
-
comment?: string;
|
|
39
34
|
metadata?: Record<string, unknown>;
|
|
35
|
+
isCommentPending?: boolean;
|
|
40
36
|
}
|
|
41
37
|
export { Annotation }
|
|
42
38
|
export { Annotation as Annotation_alias_1 }
|
|
43
39
|
|
|
44
|
-
export declare const AnnotationHighlightLayer: ({ className, style, renderTooltipContent, renderHoverTooltipContent, tooltipClassName, highlightClassName, focusedAnnotationId, focusedHoverAnnotationId, onAnnotationClick,
|
|
40
|
+
export declare const AnnotationHighlightLayer: ({ className, style, renderTooltipContent, renderHoverTooltipContent, tooltipClassName, highlightClassName, underlineClassName, commentIconPosition, commmentIcon, commentIconClassName, focusedAnnotationId, focusedHoverAnnotationId, onAnnotationClick, onAnnotationTooltipClose, hoverTooltipClassName, }: AnnotationHighlightLayerProps) => JSX.Element;
|
|
45
41
|
|
|
46
42
|
declare interface AnnotationHighlightLayerProps {
|
|
47
43
|
className?: string;
|
|
48
|
-
style?:
|
|
49
|
-
renderTooltipContent: (props: AnnotationTooltipContentProps) =>
|
|
44
|
+
style?: React_2.CSSProperties;
|
|
45
|
+
renderTooltipContent: (props: AnnotationTooltipContentProps) => React_2.ReactNode;
|
|
50
46
|
renderHoverTooltipContent: (props: {
|
|
51
47
|
annotation: Annotation;
|
|
52
48
|
onClose: () => void;
|
|
53
|
-
}) =>
|
|
49
|
+
}) => React_2.ReactNode;
|
|
54
50
|
focusedAnnotationId?: string;
|
|
51
|
+
commmentIcon?: React_2.ReactNode;
|
|
55
52
|
focusedHoverAnnotationId?: string;
|
|
56
53
|
onAnnotationClick?: (annotation: Annotation) => void;
|
|
54
|
+
onAnnotationTooltipClose?: (annotation: Annotation) => void;
|
|
57
55
|
tooltipClassName?: string;
|
|
58
56
|
hoverTooltipClassName?: string;
|
|
59
57
|
highlightClassName?: string;
|
|
60
|
-
|
|
58
|
+
commentIconPosition?: 'highlight' | 'page';
|
|
59
|
+
underlineClassName?: string;
|
|
60
|
+
commentIconClassName?: string;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
@@ -97,7 +97,7 @@ declare interface AnnotationState {
|
|
|
97
97
|
setAnnotations: (annotations: Annotation[]) => void;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
export declare const AnnotationTooltip: ({ annotation, children, renderTooltipContent, hoverTooltipContent, onOpenChange, className, hoverClassName, isOpen: controlledIsOpen,
|
|
100
|
+
export declare const AnnotationTooltip: ({ annotation, children, renderTooltipContent, hoverTooltipContent, onOpenChange, className, hoverClassName, isOpen: controlledIsOpen, hoverIsOpen: controlledHoverIsOpen, }: AnnotationTooltipProps) => JSX.Element;
|
|
101
101
|
|
|
102
102
|
export declare type AnnotationTooltipContentProps = {
|
|
103
103
|
annotation: Annotation;
|
|
@@ -115,7 +115,6 @@ declare interface AnnotationTooltipProps {
|
|
|
115
115
|
className?: string;
|
|
116
116
|
hoverClassName?: string;
|
|
117
117
|
hoverIsOpen?: boolean;
|
|
118
|
-
tooltipBubbleSize: number;
|
|
119
118
|
renderHoverTooltipContent?: (props: {
|
|
120
119
|
annotation: Annotation;
|
|
121
120
|
onClose: () => void;
|
|
@@ -149,6 +148,7 @@ export declare const clamp: (value: number, min: number, max: number) => number;
|
|
|
149
148
|
|
|
150
149
|
declare type CollapsibleSelection = {
|
|
151
150
|
highlights: HighlightRect[];
|
|
151
|
+
underlines?: HighlightRect[];
|
|
152
152
|
text: string;
|
|
153
153
|
isCollapsed: boolean;
|
|
154
154
|
};
|
|
@@ -205,6 +205,14 @@ declare type HighlightRect = {
|
|
|
205
205
|
export { HighlightRect }
|
|
206
206
|
export { HighlightRect as HighlightRect_alias_1 }
|
|
207
207
|
|
|
208
|
+
export declare interface HighlightRect_alias_2 {
|
|
209
|
+
height: number;
|
|
210
|
+
left: number;
|
|
211
|
+
top: number;
|
|
212
|
+
width: number;
|
|
213
|
+
pageNumber: number;
|
|
214
|
+
}
|
|
215
|
+
|
|
208
216
|
export declare interface InitialPDFState {
|
|
209
217
|
pdfDocumentProxy: PDFDocumentProxy;
|
|
210
218
|
pageProxies: PDFPageProxy[];
|
|
@@ -470,6 +478,12 @@ export declare const useSelectionDimensions: () => {
|
|
|
470
478
|
isCollapsed: boolean;
|
|
471
479
|
} | undefined;
|
|
472
480
|
getSelection: () => CollapsibleSelection;
|
|
481
|
+
getAnnotationDimension: () => {
|
|
482
|
+
highlights: HighlightRect[];
|
|
483
|
+
underlines: HighlightRect[];
|
|
484
|
+
text: string;
|
|
485
|
+
isCollapsed: boolean;
|
|
486
|
+
} | undefined;
|
|
473
487
|
};
|
|
474
488
|
|
|
475
489
|
export declare const ZoomIn: ({ ...props }: HTMLProps<HTMLButtonElement>) => JSX.Element;
|
package/dist/index.js
CHANGED
|
@@ -276,7 +276,6 @@ var AnnotationTooltip = ({
|
|
|
276
276
|
className,
|
|
277
277
|
hoverClassName,
|
|
278
278
|
isOpen: controlledIsOpen,
|
|
279
|
-
tooltipBubbleSize,
|
|
280
279
|
hoverIsOpen: controlledHoverIsOpen
|
|
281
280
|
}) => {
|
|
282
281
|
const viewportRef = usePdf((state) => state.viewportRef);
|
|
@@ -345,7 +344,7 @@ var AnnotationTooltip = ({
|
|
|
345
344
|
setHoverIsOpen(false);
|
|
346
345
|
}, [setHoverIsOpen]);
|
|
347
346
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
348
|
-
/* @__PURE__ */
|
|
347
|
+
/* @__PURE__ */ jsx(
|
|
349
348
|
"div",
|
|
350
349
|
{
|
|
351
350
|
ref: (node) => {
|
|
@@ -357,18 +356,7 @@ var AnnotationTooltip = ({
|
|
|
357
356
|
onMouseLeave: handleMouseLeave,
|
|
358
357
|
...getReferenceProps(),
|
|
359
358
|
...getHoverReferenceProps(),
|
|
360
|
-
children
|
|
361
|
-
!isOpen && !hoverIsOpen && annotation.comment && /* @__PURE__ */ jsx("div", { className: "rounded-full", style: {
|
|
362
|
-
position: "absolute",
|
|
363
|
-
top: annotation.highlights[0]?.top ? annotation.highlights[0]?.top - tooltipBubbleSize / 2 : 0,
|
|
364
|
-
left: annotation.highlights[0]?.left ? annotation.highlights[0]?.left - tooltipBubbleSize / 2 : 0,
|
|
365
|
-
backgroundColor: annotation.borderColor,
|
|
366
|
-
height: `${tooltipBubbleSize}px`,
|
|
367
|
-
width: `${tooltipBubbleSize}px`,
|
|
368
|
-
zIndex: 50
|
|
369
|
-
} }),
|
|
370
|
-
children
|
|
371
|
-
]
|
|
359
|
+
children
|
|
372
360
|
}
|
|
373
361
|
),
|
|
374
362
|
isOpen && viewportRef.current && createPortal(
|
|
@@ -449,63 +437,147 @@ var AnnotationHighlightLayer = ({
|
|
|
449
437
|
renderHoverTooltipContent,
|
|
450
438
|
tooltipClassName,
|
|
451
439
|
highlightClassName,
|
|
440
|
+
underlineClassName,
|
|
441
|
+
commentIconPosition,
|
|
442
|
+
commmentIcon,
|
|
443
|
+
commentIconClassName,
|
|
452
444
|
focusedAnnotationId,
|
|
453
445
|
focusedHoverAnnotationId,
|
|
454
446
|
onAnnotationClick,
|
|
455
|
-
|
|
456
|
-
|
|
447
|
+
onAnnotationTooltipClose,
|
|
448
|
+
hoverTooltipClassName
|
|
457
449
|
}) => {
|
|
458
450
|
const { annotations } = useAnnotations();
|
|
459
451
|
const pageNumber = usePDFPageNumber();
|
|
460
452
|
const pageAnnotations = annotations.filter(
|
|
461
453
|
(annotation) => annotation.pageNumber === pageNumber
|
|
462
454
|
);
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
{
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
455
|
+
const getCommentIconPosition = (highlights) => {
|
|
456
|
+
if (!highlights.length) return { top: 0, right: 10 };
|
|
457
|
+
const sortedHighlights = [...highlights].sort((a, b) => {
|
|
458
|
+
const topDiff = a.top - b.top;
|
|
459
|
+
return Math.abs(topDiff) < 3 ? a.left - b.left : topDiff;
|
|
460
|
+
});
|
|
461
|
+
const lines = [];
|
|
462
|
+
let currentLine = [];
|
|
463
|
+
sortedHighlights.forEach((highlight) => {
|
|
464
|
+
if (currentLine.length === 0) {
|
|
465
|
+
currentLine.push(highlight);
|
|
466
|
+
} else {
|
|
467
|
+
const firstInLine = currentLine[0];
|
|
468
|
+
if (Math.abs(highlight.top - firstInLine.top) <= 3) {
|
|
469
|
+
currentLine.push(highlight);
|
|
470
|
+
} else {
|
|
471
|
+
lines.push([...currentLine]);
|
|
472
|
+
currentLine = [highlight];
|
|
475
473
|
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
if (currentLine.length > 0) {
|
|
477
|
+
lines.push(currentLine);
|
|
478
|
+
}
|
|
479
|
+
const PAGE_WIDTH = 600;
|
|
480
|
+
const hasLongLine = lines.some((line) => {
|
|
481
|
+
if (line.length === 0) return false;
|
|
482
|
+
const rightmost2 = Math.max(...line.map((h) => h.left + h.width));
|
|
483
|
+
return rightmost2 > PAGE_WIDTH * 0.8;
|
|
484
|
+
});
|
|
485
|
+
const firstHighlight = highlights[0];
|
|
486
|
+
const firstLine = lines[0] || [];
|
|
487
|
+
const leftmost = Math.min(...firstLine.map((h) => h.left));
|
|
488
|
+
const rightmost = Math.max(...firstLine.map((h) => h.left + h.width));
|
|
489
|
+
const lineCenter = leftmost + (rightmost - leftmost) / 2;
|
|
490
|
+
const shouldPositionRight = hasLongLine || lineCenter > PAGE_WIDTH * 0.5;
|
|
491
|
+
const rightPosition = commentIconPosition === "highlight" ? { left: rightmost + 8 } : { right: 10 };
|
|
492
|
+
const leftPosition = commentIconPosition === "highlight" ? { left: leftmost - 18 } : { left: 20 };
|
|
493
|
+
return {
|
|
494
|
+
top: firstHighlight.top + firstHighlight.height / 2 - 6,
|
|
495
|
+
...shouldPositionRight ? rightPosition : leftPosition
|
|
496
|
+
};
|
|
497
|
+
};
|
|
498
|
+
return /* @__PURE__ */ jsx("div", { className, style, children: pageAnnotations.map((annotation) => {
|
|
499
|
+
return /* @__PURE__ */ jsx(
|
|
500
|
+
AnnotationTooltip,
|
|
501
|
+
{
|
|
479
502
|
annotation,
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
503
|
+
className: tooltipClassName,
|
|
504
|
+
hoverClassName: hoverTooltipClassName,
|
|
505
|
+
isOpen: focusedAnnotationId === annotation.id,
|
|
506
|
+
hoverIsOpen: focusedHoverAnnotationId === annotation.id,
|
|
507
|
+
onOpenChange: (open) => {
|
|
508
|
+
if (open && onAnnotationClick) {
|
|
509
|
+
onAnnotationClick(annotation);
|
|
510
|
+
} else if (!open && onAnnotationTooltipClose) {
|
|
511
|
+
onAnnotationTooltipClose(annotation);
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
renderTooltipContent,
|
|
515
|
+
hoverTooltipContent: renderHoverTooltipContent({
|
|
516
|
+
annotation,
|
|
517
|
+
onClose: () => {
|
|
518
|
+
}
|
|
519
|
+
}),
|
|
520
|
+
children: /* @__PURE__ */ jsxs(
|
|
521
|
+
"div",
|
|
522
|
+
{
|
|
523
|
+
style: { cursor: "pointer" },
|
|
524
|
+
onClick: () => onAnnotationClick?.(annotation),
|
|
525
|
+
children: [
|
|
526
|
+
annotation.highlights.map((highlight, index) => /* @__PURE__ */ jsx(
|
|
527
|
+
"div",
|
|
528
|
+
{
|
|
529
|
+
className: highlightClassName,
|
|
530
|
+
style: {
|
|
531
|
+
position: "absolute",
|
|
532
|
+
top: highlight.top,
|
|
533
|
+
left: highlight.left,
|
|
534
|
+
width: highlight.width,
|
|
535
|
+
height: highlight.height,
|
|
536
|
+
backgroundColor: annotation.color
|
|
537
|
+
},
|
|
538
|
+
"data-highlight-id": annotation.id
|
|
539
|
+
},
|
|
540
|
+
`highlight-${index}`
|
|
541
|
+
)),
|
|
542
|
+
annotation.comment && annotation.underlines?.map((rect, index) => /* @__PURE__ */ jsx(
|
|
543
|
+
"div",
|
|
544
|
+
{
|
|
545
|
+
className: underlineClassName,
|
|
546
|
+
style: {
|
|
547
|
+
position: "absolute",
|
|
548
|
+
top: rect.top,
|
|
549
|
+
left: rect.left,
|
|
550
|
+
width: rect.width,
|
|
551
|
+
height: rect.height,
|
|
552
|
+
backgroundColor: annotation.borderColor,
|
|
553
|
+
borderBottom: "1.5px"
|
|
554
|
+
},
|
|
555
|
+
"data-comment-id": annotation.id
|
|
556
|
+
},
|
|
557
|
+
`underline-${index}`
|
|
558
|
+
)),
|
|
559
|
+
annotation.comment && commmentIcon && /* @__PURE__ */ jsx(
|
|
560
|
+
"div",
|
|
561
|
+
{
|
|
562
|
+
className: commentIconClassName,
|
|
563
|
+
style: {
|
|
564
|
+
position: "absolute",
|
|
565
|
+
...getCommentIconPosition(annotation.highlights),
|
|
566
|
+
color: "gray",
|
|
567
|
+
cursor: "pointer",
|
|
568
|
+
zIndex: 10
|
|
569
|
+
},
|
|
570
|
+
"data-comment-icon-id": annotation.id,
|
|
571
|
+
children: commmentIcon
|
|
572
|
+
}
|
|
573
|
+
)
|
|
574
|
+
]
|
|
575
|
+
}
|
|
576
|
+
)
|
|
577
|
+
},
|
|
578
|
+
annotation.id
|
|
579
|
+
);
|
|
580
|
+
}) });
|
|
509
581
|
};
|
|
510
582
|
|
|
511
583
|
// ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
@@ -1049,48 +1121,341 @@ var CanvasLayer = ({
|
|
|
1049
1121
|
};
|
|
1050
1122
|
|
|
1051
1123
|
// src/hooks/useSelectionDimensions.tsx
|
|
1052
|
-
var MERGE_THRESHOLD =
|
|
1124
|
+
var MERGE_THRESHOLD = 2;
|
|
1053
1125
|
var shouldMergeRects = (rect1, rect2) => {
|
|
1054
1126
|
const verticalOverlap = !(rect1.top > rect2.top + rect2.height || rect2.top > rect1.top + rect1.height);
|
|
1055
|
-
const
|
|
1056
|
-
return verticalOverlap &&
|
|
1127
|
+
const horizontallyConnected = Math.abs(rect1.left + rect1.width - rect2.left) <= MERGE_THRESHOLD || Math.abs(rect2.left + rect2.width - rect1.left) <= MERGE_THRESHOLD || rect1.left < rect2.left + rect2.width && rect2.left < rect1.left + rect1.width;
|
|
1128
|
+
return verticalOverlap && horizontallyConnected;
|
|
1057
1129
|
};
|
|
1058
|
-
var
|
|
1059
|
-
return
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1130
|
+
var consolidateHighlightRects = (rects) => {
|
|
1131
|
+
if (rects.length <= 1) return rects;
|
|
1132
|
+
const sorted = [...rects].sort((a, b) => {
|
|
1133
|
+
const topDiff = a.top - b.top;
|
|
1134
|
+
return Math.abs(topDiff) < 2 ? a.left - b.left : topDiff;
|
|
1135
|
+
});
|
|
1136
|
+
const result = [];
|
|
1137
|
+
let currentGroup = [sorted[0]];
|
|
1138
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
1139
|
+
const currentRect = sorted[i];
|
|
1140
|
+
const lastInGroup = currentGroup[currentGroup.length - 1];
|
|
1141
|
+
const sameLineThreshold = Math.max(lastInGroup.height, currentRect.height) * 0.5;
|
|
1142
|
+
const onSameLine = Math.abs(lastInGroup.top - currentRect.top) < sameLineThreshold;
|
|
1143
|
+
const adjacent = Math.abs(lastInGroup.left + lastInGroup.width - currentRect.left) <= MERGE_THRESHOLD;
|
|
1144
|
+
const overlapping = lastInGroup.left < currentRect.left + currentRect.width && currentRect.left < lastInGroup.left + lastInGroup.width;
|
|
1145
|
+
if (onSameLine && (adjacent || overlapping)) {
|
|
1146
|
+
currentGroup.push(currentRect);
|
|
1147
|
+
} else {
|
|
1148
|
+
if (currentGroup.length === 1) {
|
|
1149
|
+
result.push(currentGroup[0]);
|
|
1150
|
+
} else {
|
|
1151
|
+
result.push(mergeRectGroup(currentGroup));
|
|
1152
|
+
}
|
|
1153
|
+
currentGroup = [currentRect];
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
if (currentGroup.length === 1) {
|
|
1157
|
+
result.push(currentGroup[0]);
|
|
1158
|
+
} else {
|
|
1159
|
+
result.push(mergeRectGroup(currentGroup));
|
|
1160
|
+
}
|
|
1161
|
+
return result;
|
|
1066
1162
|
};
|
|
1067
1163
|
var consolidateRects = (rects) => {
|
|
1068
1164
|
if (rects.length <= 1) return rects;
|
|
1069
|
-
const
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1165
|
+
const result = [];
|
|
1166
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1167
|
+
for (let i = 0; i < rects.length; i++) {
|
|
1168
|
+
if (visited.has(i)) continue;
|
|
1169
|
+
const currentRect = rects[i];
|
|
1170
|
+
if (!currentRect) continue;
|
|
1171
|
+
const currentGroup = [currentRect];
|
|
1172
|
+
visited.add(i);
|
|
1173
|
+
let foundNew = true;
|
|
1174
|
+
while (foundNew) {
|
|
1175
|
+
foundNew = false;
|
|
1176
|
+
for (let j = 0; j < rects.length; j++) {
|
|
1177
|
+
if (visited.has(j)) continue;
|
|
1178
|
+
const candidateRect = rects[j];
|
|
1179
|
+
if (!candidateRect) continue;
|
|
1180
|
+
const shouldMergeWithGroup = currentGroup.some(
|
|
1181
|
+
(groupRect) => doRectsOverlap(groupRect, candidateRect)
|
|
1182
|
+
);
|
|
1183
|
+
if (shouldMergeWithGroup) {
|
|
1184
|
+
currentGroup.push(candidateRect);
|
|
1185
|
+
visited.add(j);
|
|
1186
|
+
foundNew = true;
|
|
1187
|
+
}
|
|
1084
1188
|
}
|
|
1085
1189
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1190
|
+
result.push(mergeRectGroup(currentGroup));
|
|
1191
|
+
}
|
|
1192
|
+
return result;
|
|
1193
|
+
};
|
|
1194
|
+
var doRectsOverlap = (rect1, rect2) => {
|
|
1195
|
+
const horizontalOverlap = rect1.left < rect2.left + rect2.width && rect2.left < rect1.left + rect1.width;
|
|
1196
|
+
const verticalOverlap = rect1.top < rect2.top + rect2.height && rect2.top < rect1.top + rect1.height;
|
|
1197
|
+
const closeEnough = shouldMergeRects(rect1, rect2);
|
|
1198
|
+
return horizontalOverlap && verticalOverlap || closeEnough;
|
|
1199
|
+
};
|
|
1200
|
+
var mergeRectGroup = (rects) => {
|
|
1201
|
+
if (rects.length === 1) {
|
|
1202
|
+
const rect = rects[0];
|
|
1203
|
+
if (!rect) throw new Error("Invalid rect in group");
|
|
1204
|
+
return rect;
|
|
1205
|
+
}
|
|
1206
|
+
const firstRect = rects[0];
|
|
1207
|
+
if (!firstRect) throw new Error("Invalid first rect in group");
|
|
1208
|
+
let minLeft = firstRect.left;
|
|
1209
|
+
let minTop = firstRect.top;
|
|
1210
|
+
let maxRight = firstRect.left + firstRect.width;
|
|
1211
|
+
let maxBottom = firstRect.top + firstRect.height;
|
|
1212
|
+
rects.forEach((rect) => {
|
|
1213
|
+
if (!rect) return;
|
|
1214
|
+
minLeft = Math.min(minLeft, rect.left);
|
|
1215
|
+
minTop = Math.min(minTop, rect.top);
|
|
1216
|
+
maxRight = Math.max(maxRight, rect.left + rect.width);
|
|
1217
|
+
maxBottom = Math.max(maxBottom, rect.top + rect.height);
|
|
1218
|
+
});
|
|
1219
|
+
return {
|
|
1220
|
+
left: minLeft,
|
|
1221
|
+
top: minTop,
|
|
1222
|
+
width: maxRight - minLeft,
|
|
1223
|
+
height: maxBottom - minTop,
|
|
1224
|
+
pageNumber: firstRect.pageNumber
|
|
1225
|
+
};
|
|
1091
1226
|
};
|
|
1092
1227
|
var useSelectionDimensions = () => {
|
|
1093
1228
|
const store = PDFStore.useContext();
|
|
1229
|
+
const getAnnotationDimension = () => {
|
|
1230
|
+
const selection = window.getSelection();
|
|
1231
|
+
if (!selection || selection.isCollapsed) return;
|
|
1232
|
+
const range = selection.getRangeAt(0);
|
|
1233
|
+
const highlightRects = [];
|
|
1234
|
+
const underlineRects = [];
|
|
1235
|
+
const textLayerMapHighlight = /* @__PURE__ */ new Map();
|
|
1236
|
+
const textLayerMapUnderline = /* @__PURE__ */ new Map();
|
|
1237
|
+
const clientRects = Array.from(range.getClientRects()).filter(
|
|
1238
|
+
(rect) => rect.width > 2 && rect.height > 2
|
|
1239
|
+
);
|
|
1240
|
+
clientRects.forEach((clientRect) => {
|
|
1241
|
+
let element = document.elementFromPoint(
|
|
1242
|
+
clientRect.left + 1,
|
|
1243
|
+
clientRect.top + clientRect.height / 2
|
|
1244
|
+
);
|
|
1245
|
+
if (!element) {
|
|
1246
|
+
element = document.elementFromPoint(
|
|
1247
|
+
clientRect.left + clientRect.width / 2,
|
|
1248
|
+
clientRect.top + clientRect.height / 2
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1251
|
+
if (!element) {
|
|
1252
|
+
element = document.elementFromPoint(
|
|
1253
|
+
clientRect.right - 1,
|
|
1254
|
+
clientRect.top + clientRect.height / 2
|
|
1255
|
+
);
|
|
1256
|
+
}
|
|
1257
|
+
if (!element) {
|
|
1258
|
+
element = document.elementFromPoint(
|
|
1259
|
+
clientRect.left + clientRect.width / 2,
|
|
1260
|
+
clientRect.top + 1
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
if (!element) {
|
|
1264
|
+
element = document.elementFromPoint(
|
|
1265
|
+
clientRect.left + clientRect.width / 2,
|
|
1266
|
+
clientRect.bottom - 1
|
|
1267
|
+
);
|
|
1268
|
+
}
|
|
1269
|
+
const textLayer = element?.closest(".textLayer");
|
|
1270
|
+
if (!textLayer) return;
|
|
1271
|
+
const isSuperOrSubScript = (el) => {
|
|
1272
|
+
if (!el) return false;
|
|
1273
|
+
if (el.tagName.toLowerCase() === "sup" || el.tagName.toLowerCase() === "sub") {
|
|
1274
|
+
return true;
|
|
1275
|
+
}
|
|
1276
|
+
const classes = el.className;
|
|
1277
|
+
if (typeof classes === "string") {
|
|
1278
|
+
const superSubClasses = ["superscript", "subscript", "sup", "sub"];
|
|
1279
|
+
if (superSubClasses.some((c) => classes.includes(c))) {
|
|
1280
|
+
return true;
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
const elementRect = el.getBoundingClientRect();
|
|
1284
|
+
if (elementRect.height < 6 && elementRect.width < 15) {
|
|
1285
|
+
const textContent = el.textContent?.trim() || "";
|
|
1286
|
+
if (textContent.length <= 2 && /^[\d\w]{1,2}$/.test(textContent)) {
|
|
1287
|
+
const parentRect = el.parentElement?.getBoundingClientRect();
|
|
1288
|
+
if (parentRect && parentRect.height > elementRect.height * 2) {
|
|
1289
|
+
const elementCenter = elementRect.top + elementRect.height / 2;
|
|
1290
|
+
const parentCenter = parentRect.top + parentRect.height / 2;
|
|
1291
|
+
const verticalOffset = Math.abs(elementCenter - parentCenter);
|
|
1292
|
+
if (verticalOffset > parentRect.height * 0.4) {
|
|
1293
|
+
return true;
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
return false;
|
|
1299
|
+
};
|
|
1300
|
+
const pageNumber = parseInt(
|
|
1301
|
+
textLayer.getAttribute("data-page-number") || "1",
|
|
1302
|
+
10
|
|
1303
|
+
);
|
|
1304
|
+
const textLayerRect = textLayer.getBoundingClientRect();
|
|
1305
|
+
const zoom = store.getState().zoom;
|
|
1306
|
+
const highlightRect = {
|
|
1307
|
+
width: clientRect.width / zoom,
|
|
1308
|
+
height: clientRect.height / zoom,
|
|
1309
|
+
top: (clientRect.top - textLayerRect.top) / zoom,
|
|
1310
|
+
left: (clientRect.left - textLayerRect.left) / zoom,
|
|
1311
|
+
pageNumber
|
|
1312
|
+
};
|
|
1313
|
+
if (!textLayerMapHighlight.has(pageNumber)) {
|
|
1314
|
+
textLayerMapHighlight.set(pageNumber, []);
|
|
1315
|
+
}
|
|
1316
|
+
textLayerMapHighlight.get(pageNumber)?.push(highlightRect);
|
|
1317
|
+
const shouldCreateUnderline = !isSuperOrSubScript(element);
|
|
1318
|
+
if (shouldCreateUnderline) {
|
|
1319
|
+
const baselineOffset = clientRect.height * 0.85;
|
|
1320
|
+
const underlineHeight = 2;
|
|
1321
|
+
const underlineRect = {
|
|
1322
|
+
width: clientRect.width / zoom,
|
|
1323
|
+
height: underlineHeight / zoom,
|
|
1324
|
+
top: (clientRect.top - textLayerRect.top + baselineOffset) / zoom,
|
|
1325
|
+
left: (clientRect.left - textLayerRect.left) / zoom,
|
|
1326
|
+
pageNumber
|
|
1327
|
+
};
|
|
1328
|
+
if (!textLayerMapUnderline.has(pageNumber)) {
|
|
1329
|
+
textLayerMapUnderline.set(pageNumber, []);
|
|
1330
|
+
}
|
|
1331
|
+
textLayerMapUnderline.get(pageNumber)?.push(underlineRect);
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
textLayerMapHighlight.forEach((rects) => {
|
|
1335
|
+
if (rects.length > 0) {
|
|
1336
|
+
const consolidated = consolidateHighlightRects(rects);
|
|
1337
|
+
highlightRects.push(...consolidated);
|
|
1338
|
+
}
|
|
1339
|
+
});
|
|
1340
|
+
textLayerMapUnderline.forEach((rects) => {
|
|
1341
|
+
if (rects.length > 0) {
|
|
1342
|
+
const lineGroups = groupRectsByLine(rects);
|
|
1343
|
+
lineGroups.forEach((group) => {
|
|
1344
|
+
if (group.length === 0) return;
|
|
1345
|
+
group.sort((a, b) => a.left - b.left);
|
|
1346
|
+
let i = 0;
|
|
1347
|
+
while (i < group.length) {
|
|
1348
|
+
const startRect = group[i];
|
|
1349
|
+
if (!startRect) {
|
|
1350
|
+
i++;
|
|
1351
|
+
continue;
|
|
1352
|
+
}
|
|
1353
|
+
let endIndex = i;
|
|
1354
|
+
while (endIndex + 1 < group.length) {
|
|
1355
|
+
const currentRect = group[endIndex];
|
|
1356
|
+
const nextRect = group[endIndex + 1];
|
|
1357
|
+
if (!currentRect || !nextRect) break;
|
|
1358
|
+
const gap = nextRect.left - (currentRect.left + currentRect.width);
|
|
1359
|
+
const maxGapAllowed = Math.max(MERGE_THRESHOLD, currentRect.height * 0.3);
|
|
1360
|
+
if (gap <= maxGapAllowed) {
|
|
1361
|
+
endIndex++;
|
|
1362
|
+
} else {
|
|
1363
|
+
break;
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
const endRect = group[endIndex];
|
|
1367
|
+
if (!endRect) {
|
|
1368
|
+
i++;
|
|
1369
|
+
continue;
|
|
1370
|
+
}
|
|
1371
|
+
const zoom = store.getState().zoom;
|
|
1372
|
+
const lineRect = {
|
|
1373
|
+
width: endRect.left + endRect.width - startRect.left,
|
|
1374
|
+
height: 2 / zoom,
|
|
1375
|
+
// Fixed 2px thickness
|
|
1376
|
+
top: startRect.top,
|
|
1377
|
+
left: startRect.left,
|
|
1378
|
+
pageNumber: startRect.pageNumber
|
|
1379
|
+
};
|
|
1380
|
+
underlineRects.push(lineRect);
|
|
1381
|
+
i = endIndex + 1;
|
|
1382
|
+
}
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
});
|
|
1386
|
+
if (underlineRects.length === 0 && highlightRects.length > 0) {
|
|
1387
|
+
highlightRects.forEach((highlightRect) => {
|
|
1388
|
+
const baselineOffset = highlightRect.height * 0.85;
|
|
1389
|
+
const underlineHeight = 1.5;
|
|
1390
|
+
const underlineRect = {
|
|
1391
|
+
width: highlightRect.width,
|
|
1392
|
+
height: underlineHeight,
|
|
1393
|
+
top: highlightRect.top + baselineOffset,
|
|
1394
|
+
left: highlightRect.left,
|
|
1395
|
+
pageNumber: highlightRect.pageNumber
|
|
1396
|
+
};
|
|
1397
|
+
underlineRects.push(underlineRect);
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
return {
|
|
1401
|
+
highlights: highlightRects.sort((a, b) => a.pageNumber - b.pageNumber),
|
|
1402
|
+
underlines: consolidateUnderlines(underlineRects).sort((a, b) => a.pageNumber - b.pageNumber),
|
|
1403
|
+
text: range.toString().trim(),
|
|
1404
|
+
isCollapsed: false
|
|
1405
|
+
};
|
|
1406
|
+
};
|
|
1407
|
+
const groupRectsByLine = (rects) => {
|
|
1408
|
+
const VERTICAL_TOLERANCE = 3;
|
|
1409
|
+
const groups = [];
|
|
1410
|
+
rects.forEach((rect) => {
|
|
1411
|
+
const centerY = rect.top + rect.height / 2;
|
|
1412
|
+
let foundGroup = false;
|
|
1413
|
+
for (const group of groups) {
|
|
1414
|
+
if (group.length === 0) continue;
|
|
1415
|
+
const firstRect = group[0];
|
|
1416
|
+
if (!firstRect) continue;
|
|
1417
|
+
const groupCenterY = firstRect.top + firstRect.height / 2;
|
|
1418
|
+
if (Math.abs(centerY - groupCenterY) <= VERTICAL_TOLERANCE) {
|
|
1419
|
+
group.push(rect);
|
|
1420
|
+
foundGroup = true;
|
|
1421
|
+
break;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
if (!foundGroup) {
|
|
1425
|
+
groups.push([rect]);
|
|
1426
|
+
}
|
|
1427
|
+
});
|
|
1428
|
+
return groups;
|
|
1429
|
+
};
|
|
1430
|
+
const consolidateUnderlines = (underlines) => {
|
|
1431
|
+
if (underlines.length <= 1) return underlines;
|
|
1432
|
+
const consolidated = [];
|
|
1433
|
+
const sorted = [...underlines].sort((a, b) => {
|
|
1434
|
+
const pageCompare = a.pageNumber - b.pageNumber;
|
|
1435
|
+
if (pageCompare !== 0) return pageCompare;
|
|
1436
|
+
const topCompare = a.top - b.top;
|
|
1437
|
+
return Math.abs(topCompare) < 1 ? a.left - b.left : topCompare;
|
|
1438
|
+
});
|
|
1439
|
+
let current = sorted[0];
|
|
1440
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
1441
|
+
const next = sorted[i];
|
|
1442
|
+
const samePageAndLine = current.pageNumber === next.pageNumber && Math.abs(current.top - next.top) < 1;
|
|
1443
|
+
const horizontallyConnected = samePageAndLine && (Math.abs(current.left + current.width - next.left) <= MERGE_THRESHOLD || current.left < next.left + next.width && next.left < current.left + current.width);
|
|
1444
|
+
if (horizontallyConnected) {
|
|
1445
|
+
const newWidth = Math.max(current.left + current.width, next.left + next.width) - Math.min(current.left, next.left);
|
|
1446
|
+
current = {
|
|
1447
|
+
...current,
|
|
1448
|
+
left: Math.min(current.left, next.left),
|
|
1449
|
+
width: newWidth
|
|
1450
|
+
};
|
|
1451
|
+
} else {
|
|
1452
|
+
consolidated.push(current);
|
|
1453
|
+
current = next;
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
consolidated.push(current);
|
|
1457
|
+
return consolidated;
|
|
1458
|
+
};
|
|
1094
1459
|
const getDimension = () => {
|
|
1095
1460
|
const selection = window.getSelection();
|
|
1096
1461
|
if (!selection || selection.isCollapsed) return;
|
|
@@ -1127,7 +1492,8 @@ var useSelectionDimensions = () => {
|
|
|
1127
1492
|
});
|
|
1128
1493
|
textLayerMap.forEach((rects) => {
|
|
1129
1494
|
if (rects.length > 0) {
|
|
1130
|
-
|
|
1495
|
+
const consolidated = consolidateRects(rects);
|
|
1496
|
+
highlights.push(...consolidated);
|
|
1131
1497
|
}
|
|
1132
1498
|
});
|
|
1133
1499
|
return {
|
|
@@ -1137,7 +1503,7 @@ var useSelectionDimensions = () => {
|
|
|
1137
1503
|
};
|
|
1138
1504
|
};
|
|
1139
1505
|
const getSelection = () => getDimension();
|
|
1140
|
-
return { getDimension, getSelection };
|
|
1506
|
+
return { getDimension, getSelection, getAnnotationDimension };
|
|
1141
1507
|
};
|
|
1142
1508
|
var SelectionTooltip = ({ children }) => {
|
|
1143
1509
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -1522,24 +1888,171 @@ var HighlightLayer = forwardRef(({ asChild, className, style, ...props }, ref) =
|
|
|
1522
1888
|
}) });
|
|
1523
1889
|
});
|
|
1524
1890
|
HighlightLayer.displayName = "HighlightLayer";
|
|
1891
|
+
var createTextSelectionManager = () => {
|
|
1892
|
+
const textLayers = /* @__PURE__ */ new Map();
|
|
1893
|
+
let selectionChangeAbortController = null;
|
|
1894
|
+
let isPointerDown = false;
|
|
1895
|
+
let prevRange = null;
|
|
1896
|
+
let isFirefox;
|
|
1897
|
+
const removeGlobalSelectionListener = (textLayerDiv) => {
|
|
1898
|
+
textLayers.delete(textLayerDiv);
|
|
1899
|
+
if (textLayers.size === 0) {
|
|
1900
|
+
selectionChangeAbortController?.abort();
|
|
1901
|
+
selectionChangeAbortController = null;
|
|
1902
|
+
}
|
|
1903
|
+
};
|
|
1904
|
+
const enableGlobalSelectionListener = () => {
|
|
1905
|
+
if (selectionChangeAbortController) {
|
|
1906
|
+
return;
|
|
1907
|
+
}
|
|
1908
|
+
selectionChangeAbortController = new AbortController();
|
|
1909
|
+
const { signal } = selectionChangeAbortController;
|
|
1910
|
+
const reset = (endDiv, textLayer) => {
|
|
1911
|
+
if (endDiv.parentNode !== textLayer) {
|
|
1912
|
+
textLayer.appendChild(endDiv);
|
|
1913
|
+
}
|
|
1914
|
+
endDiv.style.width = "";
|
|
1915
|
+
endDiv.style.height = "";
|
|
1916
|
+
textLayer.classList.remove("selecting");
|
|
1917
|
+
};
|
|
1918
|
+
document.addEventListener("pointerdown", () => {
|
|
1919
|
+
isPointerDown = true;
|
|
1920
|
+
}, { signal });
|
|
1921
|
+
document.addEventListener("pointerup", () => {
|
|
1922
|
+
isPointerDown = false;
|
|
1923
|
+
textLayers.forEach(reset);
|
|
1924
|
+
}, { signal });
|
|
1925
|
+
window.addEventListener("blur", () => {
|
|
1926
|
+
isPointerDown = false;
|
|
1927
|
+
textLayers.forEach(reset);
|
|
1928
|
+
}, { signal });
|
|
1929
|
+
document.addEventListener("keyup", () => {
|
|
1930
|
+
if (!isPointerDown) {
|
|
1931
|
+
textLayers.forEach(reset);
|
|
1932
|
+
}
|
|
1933
|
+
}, { signal });
|
|
1934
|
+
document.addEventListener("selectionchange", () => {
|
|
1935
|
+
const selection = document.getSelection();
|
|
1936
|
+
if (!selection || selection.rangeCount === 0) {
|
|
1937
|
+
textLayers.forEach(reset);
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
const activeTextLayers = /* @__PURE__ */ new Set();
|
|
1941
|
+
for (let i = 0; i < selection.rangeCount; i++) {
|
|
1942
|
+
const range = selection.getRangeAt(i);
|
|
1943
|
+
for (const textLayerDiv of textLayers.keys()) {
|
|
1944
|
+
if (!activeTextLayers.has(textLayerDiv) && range.intersectsNode(textLayerDiv)) {
|
|
1945
|
+
activeTextLayers.add(textLayerDiv);
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
for (const [textLayerDiv, endDiv] of textLayers) {
|
|
1950
|
+
if (activeTextLayers.has(textLayerDiv)) {
|
|
1951
|
+
textLayerDiv.classList.add("selecting");
|
|
1952
|
+
} else {
|
|
1953
|
+
reset(endDiv, textLayerDiv);
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
if (isFirefox === void 0) {
|
|
1957
|
+
const firstTextLayer = textLayers.keys().next().value;
|
|
1958
|
+
if (firstTextLayer) {
|
|
1959
|
+
isFirefox = getComputedStyle(firstTextLayer).getPropertyValue("-moz-user-select") === "none";
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
if (isFirefox) {
|
|
1963
|
+
return;
|
|
1964
|
+
}
|
|
1965
|
+
try {
|
|
1966
|
+
const range = selection.getRangeAt(0);
|
|
1967
|
+
const modifyStart = prevRange && (range.compareBoundaryPoints(Range.END_TO_END, prevRange) === 0 || range.compareBoundaryPoints(Range.START_TO_END, prevRange) === 0);
|
|
1968
|
+
let anchor = modifyStart ? range.startContainer : range.endContainer;
|
|
1969
|
+
if (anchor.nodeType === Node.TEXT_NODE) {
|
|
1970
|
+
anchor = anchor.parentNode;
|
|
1971
|
+
}
|
|
1972
|
+
const parentTextLayer = anchor.parentElement?.closest(".textLayer");
|
|
1973
|
+
const endDiv = textLayers.get(parentTextLayer);
|
|
1974
|
+
if (endDiv && parentTextLayer) {
|
|
1975
|
+
endDiv.style.width = parentTextLayer.style.width;
|
|
1976
|
+
endDiv.style.height = parentTextLayer.style.height;
|
|
1977
|
+
const insertTarget = modifyStart ? anchor : anchor.nextSibling;
|
|
1978
|
+
if (anchor.parentElement && insertTarget) {
|
|
1979
|
+
anchor.parentElement.insertBefore(endDiv, insertTarget);
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
prevRange = range.cloneRange();
|
|
1983
|
+
} catch {
|
|
1984
|
+
}
|
|
1985
|
+
}, { signal });
|
|
1986
|
+
};
|
|
1987
|
+
const bindMouseEvents2 = (textLayerDiv, endOfContent) => {
|
|
1988
|
+
if (textLayerDiv._textSelectionBound) {
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
textLayerDiv._textSelectionBound = true;
|
|
1992
|
+
textLayers.set(textLayerDiv, endOfContent);
|
|
1993
|
+
enableGlobalSelectionListener();
|
|
1994
|
+
const handleMouseDown = () => {
|
|
1995
|
+
textLayerDiv.classList.add("selecting");
|
|
1996
|
+
};
|
|
1997
|
+
textLayerDiv.addEventListener("mousedown", handleMouseDown);
|
|
1998
|
+
textLayerDiv._cleanupTextSelection = () => {
|
|
1999
|
+
textLayerDiv.removeEventListener("mousedown", handleMouseDown);
|
|
2000
|
+
removeGlobalSelectionListener(textLayerDiv);
|
|
2001
|
+
delete textLayerDiv._textSelectionBound;
|
|
2002
|
+
};
|
|
2003
|
+
};
|
|
2004
|
+
return bindMouseEvents2;
|
|
2005
|
+
};
|
|
2006
|
+
var bindMouseEvents = createTextSelectionManager();
|
|
1525
2007
|
var useTextLayer = () => {
|
|
1526
2008
|
const textContainerRef = useRef(null);
|
|
2009
|
+
const textLayerRef = useRef(null);
|
|
2010
|
+
const isRenderingRef = useRef(false);
|
|
1527
2011
|
const pageNumber = usePDFPageNumber();
|
|
1528
2012
|
const pdfPageProxy = usePdf((state) => state.getPdfPageProxy(pageNumber));
|
|
1529
2013
|
useEffect(() => {
|
|
1530
|
-
|
|
2014
|
+
const textContainer = textContainerRef.current;
|
|
2015
|
+
if (!textContainer || isRenderingRef.current) {
|
|
1531
2016
|
return;
|
|
1532
2017
|
}
|
|
2018
|
+
isRenderingRef.current = true;
|
|
2019
|
+
textContainer.innerHTML = "";
|
|
2020
|
+
if (textLayerRef.current) {
|
|
2021
|
+
textLayerRef.current.cancel();
|
|
2022
|
+
textLayerRef.current = null;
|
|
2023
|
+
}
|
|
1533
2024
|
const textLayer = new TextLayer({
|
|
1534
2025
|
textContentSource: pdfPageProxy.streamTextContent(),
|
|
1535
|
-
container:
|
|
2026
|
+
container: textContainer,
|
|
1536
2027
|
viewport: pdfPageProxy.getViewport({ scale: 1 })
|
|
1537
2028
|
});
|
|
1538
|
-
|
|
2029
|
+
textLayerRef.current = textLayer;
|
|
2030
|
+
textLayer.render().then(() => {
|
|
2031
|
+
if (textLayerRef.current === textLayer && textContainer) {
|
|
2032
|
+
const endOfContent = document.createElement("div");
|
|
2033
|
+
endOfContent.className = "endOfContent";
|
|
2034
|
+
textContainer.appendChild(endOfContent);
|
|
2035
|
+
bindMouseEvents(textContainer, endOfContent);
|
|
2036
|
+
}
|
|
2037
|
+
}).catch((error) => {
|
|
2038
|
+
if (error.name !== "AbortException") {
|
|
2039
|
+
console.error("TextLayer rendering error:", error);
|
|
2040
|
+
}
|
|
2041
|
+
}).finally(() => {
|
|
2042
|
+
isRenderingRef.current = false;
|
|
2043
|
+
});
|
|
1539
2044
|
return () => {
|
|
1540
|
-
|
|
2045
|
+
isRenderingRef.current = false;
|
|
2046
|
+
if (textLayerRef.current) {
|
|
2047
|
+
textLayerRef.current.cancel();
|
|
2048
|
+
textLayerRef.current = null;
|
|
2049
|
+
}
|
|
2050
|
+
if (textContainer?._cleanupTextSelection) {
|
|
2051
|
+
textContainer._cleanupTextSelection();
|
|
2052
|
+
delete textContainer._cleanupTextSelection;
|
|
2053
|
+
}
|
|
1541
2054
|
};
|
|
1542
|
-
}, [pdfPageProxy]);
|
|
2055
|
+
}, [pdfPageProxy.pageNumber]);
|
|
1543
2056
|
return {
|
|
1544
2057
|
textContainerRef,
|
|
1545
2058
|
pageNumber: pdfPageProxy.pageNumber
|