@anaralabs/lector 3.5.3 → 3.5.5

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.
@@ -40,7 +40,7 @@ declare interface Annotation {
40
40
  export { Annotation }
41
41
  export { Annotation as Annotation_alias_1 }
42
42
 
43
- export declare const AnnotationHighlightLayer: ({ className, style, renderTooltipContent, tooltipClassName, focusedAnnotationId, onAnnotationClick, }: AnnotationHighlightLayerProps) => JSX.Element;
43
+ export declare const AnnotationHighlightLayer: ({ className, style, renderTooltipContent, renderHoverTooltipContent, tooltipClassName, highlightClassName, focusedAnnotationId, focusedHoverAnnotationId, onAnnotationClick, hoverTooltipClassName }: AnnotationHighlightLayerProps) => JSX.Element;
44
44
 
45
45
  declare interface AnnotationHighlightLayerProps {
46
46
  className?: string;
@@ -49,9 +49,16 @@ declare interface AnnotationHighlightLayerProps {
49
49
  annotation: Annotation;
50
50
  onClose: () => void;
51
51
  }) => React.ReactNode;
52
+ renderHoverTooltipContent: (props: {
53
+ annotation: Annotation;
54
+ onClose: () => void;
55
+ }) => React.ReactNode;
52
56
  focusedAnnotationId?: string;
57
+ focusedHoverAnnotationId?: string;
53
58
  onAnnotationClick?: (annotation: Annotation) => void;
54
59
  tooltipClassName?: string;
60
+ hoverTooltipClassName?: string;
61
+ highlightClassName?: string;
55
62
  }
56
63
 
57
64
  /**
@@ -91,15 +98,22 @@ declare interface AnnotationState {
91
98
  setAnnotations: (annotations: Annotation[]) => void;
92
99
  }
93
100
 
94
- export declare const AnnotationTooltip: ({ annotation, children, tooltipContent, onOpenChange, className, isOpen: controlledIsOpen, }: AnnotationTooltipProps) => JSX.Element;
101
+ export declare const AnnotationTooltip: ({ annotation, children, tooltipContent, hoverTooltipContent, onOpenChange, className, hoverClassName, isOpen: controlledIsOpen, hoverIsOpen: controlledHoverIsOpen, }: AnnotationTooltipProps) => JSX.Element;
95
102
 
96
103
  declare interface AnnotationTooltipProps {
97
104
  annotation: Annotation;
98
105
  children: React.ReactNode;
99
106
  tooltipContent: React.ReactNode;
107
+ hoverTooltipContent?: React.ReactNode;
100
108
  onOpenChange?: (open: boolean) => void;
101
109
  isOpen?: boolean;
102
110
  className?: string;
111
+ hoverClassName?: string;
112
+ hoverIsOpen?: boolean;
113
+ renderHoverTooltipContent?: (props: {
114
+ annotation: Annotation;
115
+ onClose: () => void;
116
+ }) => React.ReactNode;
103
117
  }
104
118
 
105
119
  /**
@@ -367,11 +381,12 @@ declare const useAnnotations: UseBoundStore<StoreApi<AnnotationState>>;
367
381
  export { useAnnotations }
368
382
  export { useAnnotations as useAnnotations_alias_1 }
369
383
 
370
- export declare const useAnnotationTooltip: ({ annotation, onOpenChange, }: UseAnnotationTooltipProps) => UseAnnotationTooltipReturn;
384
+ export declare const useAnnotationTooltip: ({ annotation, onOpenChange, position, }: UseAnnotationTooltipProps) => UseAnnotationTooltipReturn;
371
385
 
372
386
  declare interface UseAnnotationTooltipProps {
373
387
  annotation: Annotation;
374
388
  onOpenChange?: (open: boolean) => void;
389
+ position?: "top" | "bottom" | "left" | "right";
375
390
  }
376
391
 
377
392
  declare interface UseAnnotationTooltipReturn {
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import React, { createContext, forwardRef, useCallback, useContext, useState, useRef, useEffect, cloneElement, createRef, useLayoutEffect } from 'react';
3
+ import React, { createContext, forwardRef, useRef, useCallback, useContext, useState, useEffect, cloneElement, createRef, useLayoutEffect } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
5
  import { useFloating, autoUpdate, offset, shift, useDismiss, useInteractions, inline, flip } from '@floating-ui/react';
6
6
  import { useVirtualizer, elementScroll, debounce } from '@tanstack/react-virtual';
@@ -146,7 +146,8 @@ var defaultRect = {
146
146
  };
147
147
  var useAnnotationTooltip = ({
148
148
  annotation,
149
- onOpenChange
149
+ onOpenChange,
150
+ position = "top"
150
151
  }) => {
151
152
  const isNewAnnotation = Date.now() - new Date(annotation.createdAt).getTime() < 1e3;
152
153
  const [isOpen, setIsOpen] = useState(isNewAnnotation);
@@ -157,7 +158,7 @@ var useAnnotationTooltip = ({
157
158
  floatingStyles,
158
159
  context
159
160
  } = useFloating({
160
- placement: "top",
161
+ placement: position,
161
162
  open: isOpen,
162
163
  onOpenChange: (open) => {
163
164
  setIsOpen(open);
@@ -261,11 +262,16 @@ var AnnotationTooltip = ({
261
262
  annotation,
262
263
  children,
263
264
  tooltipContent,
265
+ hoverTooltipContent,
264
266
  onOpenChange,
265
267
  className,
266
- isOpen: controlledIsOpen
268
+ hoverClassName,
269
+ isOpen: controlledIsOpen,
270
+ hoverIsOpen: controlledHoverIsOpen
267
271
  }) => {
268
272
  const viewportRef = usePdf((state) => state.viewportRef);
273
+ const closeTimeoutRef = useRef(null);
274
+ const isMouseInTooltipRef = useRef(false);
269
275
  const {
270
276
  isOpen: uncontrolledIsOpen,
271
277
  setIsOpen,
@@ -277,19 +283,66 @@ var AnnotationTooltip = ({
277
283
  annotation,
278
284
  onOpenChange
279
285
  });
286
+ const {
287
+ isOpen: uncontrolledHoverIsOpen,
288
+ setIsOpen: setHoverIsOpen,
289
+ refs: hoverRefs,
290
+ floatingStyles: hoverFloatingStyles,
291
+ getFloatingProps: getHoverFloatingProps,
292
+ getReferenceProps: getHoverReferenceProps
293
+ } = useAnnotationTooltip({
294
+ position: "bottom",
295
+ annotation
296
+ });
280
297
  const isOpen = controlledIsOpen ?? uncontrolledIsOpen;
298
+ const hoverIsOpen = controlledHoverIsOpen || uncontrolledHoverIsOpen;
281
299
  const handleClick = useCallback(() => {
282
300
  if (controlledIsOpen === void 0) {
283
301
  setIsOpen(!isOpen);
284
302
  }
285
303
  }, [controlledIsOpen, isOpen, setIsOpen]);
304
+ const handleMouseEnter = useCallback(() => {
305
+ if (hoverTooltipContent) {
306
+ if (closeTimeoutRef.current) {
307
+ clearTimeout(closeTimeoutRef.current);
308
+ closeTimeoutRef.current = null;
309
+ }
310
+ setHoverIsOpen(true);
311
+ }
312
+ }, [hoverTooltipContent, setHoverIsOpen]);
313
+ const closeTooltip = useCallback(() => {
314
+ if (!isMouseInTooltipRef.current) {
315
+ setHoverIsOpen(false);
316
+ }
317
+ }, [setHoverIsOpen]);
318
+ const handleMouseLeave = useCallback(() => {
319
+ if (!hoverTooltipContent) return;
320
+ closeTimeoutRef.current = setTimeout(closeTooltip, 100);
321
+ }, [hoverTooltipContent, closeTooltip]);
322
+ const handleTooltipMouseEnter = useCallback(() => {
323
+ isMouseInTooltipRef.current = true;
324
+ if (closeTimeoutRef.current) {
325
+ clearTimeout(closeTimeoutRef.current);
326
+ closeTimeoutRef.current = null;
327
+ }
328
+ }, []);
329
+ const handleTooltipMouseLeave = useCallback(() => {
330
+ isMouseInTooltipRef.current = false;
331
+ setHoverIsOpen(false);
332
+ }, [setHoverIsOpen]);
286
333
  return /* @__PURE__ */ jsxs(Fragment, { children: [
287
334
  /* @__PURE__ */ jsx(
288
335
  "div",
289
336
  {
290
- ref: refs.setReference,
337
+ ref: (node) => {
338
+ refs.setReference(node);
339
+ hoverRefs.setReference(node);
340
+ },
291
341
  onClick: handleClick,
342
+ onMouseEnter: handleMouseEnter,
343
+ onMouseLeave: handleMouseLeave,
292
344
  ...getReferenceProps(),
345
+ ...getHoverReferenceProps(),
293
346
  children
294
347
  }
295
348
  ),
@@ -299,16 +352,39 @@ var AnnotationTooltip = ({
299
352
  {
300
353
  ref: refs.setFloating,
301
354
  className,
355
+ "data-annotation-tooltip": "click",
302
356
  style: {
303
357
  ...floatingStyles,
304
358
  position: "absolute",
305
- pointerEvents: "auto"
359
+ pointerEvents: "auto",
360
+ zIndex: 50
306
361
  },
307
362
  ...getFloatingProps(),
308
363
  children: tooltipContent
309
364
  }
310
365
  ),
311
366
  viewportRef.current
367
+ ),
368
+ !isOpen && hoverIsOpen && annotation.comment && hoverTooltipContent && viewportRef.current && createPortal(
369
+ /* @__PURE__ */ jsx(
370
+ "div",
371
+ {
372
+ ref: hoverRefs.setFloating,
373
+ className: hoverClassName,
374
+ "data-annotation-tooltip": "hover",
375
+ style: {
376
+ ...hoverFloatingStyles,
377
+ position: "absolute",
378
+ pointerEvents: "auto",
379
+ zIndex: 51
380
+ },
381
+ onMouseEnter: handleTooltipMouseEnter,
382
+ onMouseLeave: handleTooltipMouseLeave,
383
+ ...getHoverFloatingProps(),
384
+ children: hoverTooltipContent
385
+ }
386
+ ),
387
+ viewportRef.current
312
388
  )
313
389
  ] });
314
390
  };
@@ -341,9 +417,13 @@ var AnnotationHighlightLayer = ({
341
417
  className,
342
418
  style,
343
419
  renderTooltipContent,
420
+ renderHoverTooltipContent,
344
421
  tooltipClassName,
422
+ highlightClassName,
345
423
  focusedAnnotationId,
346
- onAnnotationClick
424
+ focusedHoverAnnotationId,
425
+ onAnnotationClick,
426
+ hoverTooltipClassName
347
427
  }) => {
348
428
  const { annotations } = useAnnotations();
349
429
  const pageNumber = usePDFPageNumber();
@@ -355,7 +435,9 @@ var AnnotationHighlightLayer = ({
355
435
  {
356
436
  annotation,
357
437
  className: tooltipClassName,
438
+ hoverClassName: hoverTooltipClassName,
358
439
  isOpen: focusedAnnotationId === annotation.id,
440
+ hoverIsOpen: focusedHoverAnnotationId === annotation.id,
359
441
  onOpenChange: (open) => {
360
442
  if (open && onAnnotationClick) {
361
443
  onAnnotationClick(annotation);
@@ -366,6 +448,11 @@ var AnnotationHighlightLayer = ({
366
448
  onClose: () => {
367
449
  }
368
450
  }),
451
+ hoverTooltipContent: renderHoverTooltipContent({
452
+ annotation,
453
+ onClose: () => {
454
+ }
455
+ }),
369
456
  children: /* @__PURE__ */ jsx(
370
457
  "div",
371
458
  {
@@ -374,16 +461,14 @@ var AnnotationHighlightLayer = ({
374
461
  children: annotation.highlights.map((highlight, index) => /* @__PURE__ */ jsx(
375
462
  "div",
376
463
  {
464
+ className: highlightClassName,
377
465
  style: {
378
466
  position: "absolute",
379
467
  top: highlight.top,
380
468
  left: highlight.left,
381
469
  width: highlight.width,
382
470
  height: highlight.height,
383
- backgroundColor: annotation.color || "rgba(255, 255, 0, 0.3)",
384
- mixBlendMode: "multiply",
385
- transition: "all 0.2s ease",
386
- cursor: "pointer"
471
+ backgroundColor: annotation.color
387
472
  },
388
473
  "data-highlight-id": annotation.id
389
474
  },
@@ -1072,7 +1157,27 @@ var SelectionTooltip = ({ children }) => {
1072
1157
  const handleSelectionChange = () => {
1073
1158
  const selection = document.getSelection();
1074
1159
  if (selection && viewportRef.current?.contains(selection.anchorNode)) {
1075
- requestAnimationFrame(updateTooltipPosition);
1160
+ const anchorNode = selection.anchorNode;
1161
+ const focusNode = selection.focusNode;
1162
+ const isInUnselectableArea = (node) => {
1163
+ if (!node) return false;
1164
+ let element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
1165
+ while (element) {
1166
+ if (element.getAttribute("data-annotation-tooltip")) {
1167
+ return true;
1168
+ }
1169
+ if (element.hasAttribute("data-floating-ui-portal")) {
1170
+ return true;
1171
+ }
1172
+ element = element.parentElement;
1173
+ }
1174
+ return false;
1175
+ };
1176
+ if (!isInUnselectableArea(anchorNode) && !isInUnselectableArea(focusNode)) {
1177
+ requestAnimationFrame(updateTooltipPosition);
1178
+ } else {
1179
+ setIsOpen(false);
1180
+ }
1076
1181
  } else {
1077
1182
  setIsOpen(false);
1078
1183
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anaralabs/lector",
3
- "version": "3.5.3",
3
+ "version": "3.5.5",
4
4
  "description": "Headless PDF viewer for React",
5
5
  "author": "andrewdr (https://github.com/andrewdoro)",
6
6
  "license": "MIT",