Skip to content

Commit 32a03fa

Browse files
committed
fix: adjust positioning calculations for annotations
1 parent 5657516 commit 32a03fa

File tree

3 files changed

+45
-14
lines changed

3 files changed

+45
-14
lines changed

packages/lector/size.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{
33
"name": "Client",
44
"passed": true,
5-
"size": 70354,
5+
"size": 70348,
66
"sizeLimit": 150000
77
}
88
]

packages/lector/src/components/annotation-tooltip.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export const AnnotationTooltip = ({
4848
} = useAnnotationTooltip({
4949
annotation,
5050
onOpenChange,
51+
isOpen: controlledIsOpen,
5152
});
5253

5354
const {
@@ -61,6 +62,7 @@ export const AnnotationTooltip = ({
6162
} = useAnnotationTooltip({
6263
position: "bottom",
6364
annotation,
65+
isOpen: controlledHoverIsOpen,
6466
});
6567

6668
const isOpen = controlledIsOpen ?? uncontrolledIsOpen;

packages/lector/src/hooks/useAnnotationTooltip.ts

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ interface UseAnnotationTooltipProps {
1717
annotation: Annotation;
1818
onOpenChange?: (open: boolean) => void;
1919
position?: "top" | "bottom" | "left" | "right";
20+
isOpen?: boolean;
2021
}
2122

2223
interface UseAnnotationTooltipReturn {
@@ -43,20 +44,25 @@ export const useAnnotationTooltip = ({
4344
annotation,
4445
onOpenChange,
4546
position = "top",
47+
isOpen: controlledIsOpen,
4648
}: UseAnnotationTooltipProps): UseAnnotationTooltipReturn => {
4749
// Show tooltip immediately if it's a new annotation
4850
const isNewAnnotation = Date.now() - new Date(annotation.createdAt).getTime() < 1000;
49-
const [isOpen, setIsOpen] = useState(isNewAnnotation);
51+
const [isPositionCalculated, setIsPositionCalculated] = useState(false);
52+
const [isOpen, setIsOpen] = useState(false);
5053
const viewportRef = usePdf((state) => state.viewportRef);
5154
const scale = usePdf((state) => state.zoom);
5255

56+
// Only show if position is calculated or externally controlled
57+
const effectiveIsOpen = ((isOpen && isPositionCalculated) || controlledIsOpen) ?? false;
58+
5359
const {
5460
refs,
5561
floatingStyles,
5662
context,
5763
} = useFloating({
5864
placement: position,
59-
open: isOpen,
65+
open: effectiveIsOpen,
6066
onOpenChange: (open) => {
6167
setIsOpen(open);
6268
onOpenChange?.(open);
@@ -77,22 +83,31 @@ export const useAnnotationTooltip = ({
7783
const { getReferenceProps, getFloatingProps } = useInteractions([dismiss]);
7884

7985
const updateTooltipPosition = useCallback(() => {
80-
if (!annotation.highlights.length) return;
86+
if (!annotation.highlights.length) {
87+
setIsPositionCalculated(false);
88+
return;
89+
}
8190

8291
const highlightRects = annotation.highlights;
8392
let minLeft = Infinity;
8493
let maxRight = -Infinity;
8594
let minTop = Infinity;
8695
let maxBottom = -Infinity;
8796

88-
refs.setReference({
89-
getBoundingClientRect() {
90-
const viewportElement = viewportRef.current;
91-
if (!viewportElement) return defaultRect;
97+
const viewportElement = viewportRef.current;
98+
if (!viewportElement) {
99+
setIsPositionCalculated(false);
100+
return;
101+
}
92102

93-
const pageElement = viewportElement.querySelector(`[data-page-number="${annotation.pageNumber}"]`);
94-
if (!pageElement) return defaultRect;
103+
const pageElement = viewportElement.querySelector(`[data-page-number="${annotation.pageNumber}"]`);
104+
if (!pageElement) {
105+
setIsPositionCalculated(false);
106+
return;
107+
}
95108

109+
refs.setReference({
110+
getBoundingClientRect() {
96111
const pageRect = pageElement.getBoundingClientRect();
97112

98113
// Calculate the bounding box in viewport coordinates using the PDF scale
@@ -136,11 +151,25 @@ export const useAnnotationTooltip = ({
136151
},
137152
contextElement: viewportRef.current || undefined,
138153
});
139-
}, [annotation.highlights, annotation.pageNumber, refs, viewportRef, scale]);
154+
155+
setIsPositionCalculated(true);
156+
157+
// If it's a new annotation, show it once position is calculated
158+
if (isNewAnnotation) {
159+
setIsOpen(true);
160+
}
161+
}, [annotation.highlights, annotation.pageNumber, refs, viewportRef, scale, isNewAnnotation]);
140162

141163
useEffect(() => {
142164
const viewport = viewportRef.current;
143-
updateTooltipPosition();
165+
166+
// Reset position calculated state when scale changes
167+
setIsPositionCalculated(false);
168+
169+
// Update position with RAF to ensure DOM is ready
170+
requestAnimationFrame(() => {
171+
updateTooltipPosition();
172+
});
144173

145174
const handleScroll = () => {
146175
requestAnimationFrame(updateTooltipPosition);
@@ -164,10 +193,10 @@ export const useAnnotationTooltip = ({
164193
}
165194
window.removeEventListener("resize", handleResize);
166195
};
167-
}, [updateTooltipPosition, viewportRef]);
196+
}, [updateTooltipPosition, viewportRef, scale, controlledIsOpen]);
168197

169198
return {
170-
isOpen,
199+
isOpen: effectiveIsOpen,
171200
setIsOpen,
172201
refs,
173202
floatingStyles,

0 commit comments

Comments
 (0)