@anaralabs/lector 3.5.0 → 3.5.1

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/README.md CHANGED
@@ -1,5 +1,4 @@
1
1
  <p align="center">
2
- <!-- <h1 align="center"><img src="https://www.anara.ai/icons/logo.png" width="196" /></h1> -->
3
2
  <p align="center">
4
3
  <i>Simple primitives to compose powerful PDF viewing experiences.<br>powered by <code><a href="https://mozilla.github.io/pdf.js/">PDF.js</a></code> and <code><a href="https://reactjs.org/">React</a></code></i>
5
4
  </p>
@@ -44,7 +44,7 @@ export declare const AnnotationHighlightLayer: ({ className, style, renderToolti
44
44
  declare interface AnnotationHighlightLayerProps {
45
45
  className?: string;
46
46
  style?: React.CSSProperties;
47
- renderTooltipContent?: (props: {
47
+ renderTooltipContent: (props: {
48
48
  annotation: Annotation;
49
49
  onClose: () => void;
50
50
  }) => React.ReactNode;
@@ -328,8 +328,6 @@ export declare interface SearchResults {
328
328
  hasMoreResults: boolean;
329
329
  }
330
330
 
331
- declare type Selection_2 = Omit<CollapsibleSelection, "isCollapsed">;
332
-
333
331
  export declare const SelectionTooltip: ({ children }: SelectionTooltipProps) => JSX.Element;
334
332
 
335
333
  declare interface SelectionTooltipProps {
@@ -362,24 +360,6 @@ export declare const Thumbnails: ({ children, ...props }: HTMLProps<HTMLDivEleme
362
360
 
363
361
  export declare const TotalPages: ({ ...props }: HTMLProps<HTMLDivElement>) => JSX.Element;
364
362
 
365
- export declare const useAnnotationActions: ({ annotation, onClose, }: UseAnnotationActionsProps) => UseAnnotationActionsReturn;
366
-
367
- declare interface UseAnnotationActionsProps {
368
- annotation: Annotation;
369
- onClose?: () => void;
370
- }
371
-
372
- declare interface UseAnnotationActionsReturn {
373
- comment: string;
374
- isEditing: boolean;
375
- setComment: (comment: string) => void;
376
- setIsEditing: (isEditing: boolean) => void;
377
- handleSaveComment: () => void;
378
- handleColorChange: (color: string) => void;
379
- handleCancelEdit: () => void;
380
- colors: string[];
381
- }
382
-
383
363
  declare const useAnnotations: UseBoundStore<StoreApi<AnnotationState>>;
384
364
  export { useAnnotations }
385
365
  export { useAnnotations as useAnnotations_alias_1 }
@@ -458,8 +438,12 @@ export declare const useSearch: () => {
458
438
  };
459
439
 
460
440
  export declare const useSelectionDimensions: () => {
461
- getDimension: () => CollapsibleSelection | undefined;
462
- getSelection: () => Selection_2;
441
+ getDimension: () => {
442
+ highlights: HighlightRect[];
443
+ text: string;
444
+ isCollapsed: boolean;
445
+ } | undefined;
446
+ getSelection: () => CollapsibleSelection;
463
447
  };
464
448
 
465
449
  export declare const ZoomIn: ({ ...props }: HTMLProps<HTMLButtonElement>) => JSX.Element;
package/dist/index.js CHANGED
@@ -200,6 +200,7 @@ var useAnnotationTooltip = ({
200
200
  });
201
201
  }, [annotation.highlights, annotation.pageNumber, refs, viewportRef]);
202
202
  useEffect(() => {
203
+ const viewport = viewportRef.current;
203
204
  updateTooltipPosition();
204
205
  const handleScroll = () => {
205
206
  requestAnimationFrame(updateTooltipPosition);
@@ -207,15 +208,15 @@ var useAnnotationTooltip = ({
207
208
  const handleResize = () => {
208
209
  requestAnimationFrame(updateTooltipPosition);
209
210
  };
210
- if (viewportRef.current) {
211
- viewportRef.current.addEventListener("scroll", handleScroll, {
211
+ if (viewport) {
212
+ viewport.addEventListener("scroll", handleScroll, {
212
213
  passive: true
213
214
  });
214
215
  }
215
216
  window.addEventListener("resize", handleResize, { passive: true });
216
217
  return () => {
217
- if (viewportRef.current) {
218
- viewportRef.current.removeEventListener("scroll", handleScroll);
218
+ if (viewport) {
219
+ viewport.removeEventListener("scroll", handleScroll);
219
220
  }
220
221
  window.removeEventListener("resize", handleResize);
221
222
  };
@@ -310,116 +311,6 @@ var PDFPageNumberContext = createContext(0);
310
311
  var usePDFPageNumber = () => {
311
312
  return useContext(PDFPageNumberContext);
312
313
  };
313
- var useAnnotationActions = ({
314
- annotation,
315
- onClose
316
- }) => {
317
- const { updateAnnotation } = useAnnotations();
318
- const [comment, setComment] = useState(annotation.comment || "");
319
- const [isEditing, setIsEditing] = useState(false);
320
- const handleSaveComment = useCallback(() => {
321
- updateAnnotation(annotation.id, { comment });
322
- setIsEditing(false);
323
- onClose?.();
324
- }, [annotation.id, comment, updateAnnotation, onClose]);
325
- const handleColorChange = useCallback(
326
- (color) => {
327
- updateAnnotation(annotation.id, { color });
328
- onClose?.();
329
- },
330
- [annotation.id, updateAnnotation, onClose]
331
- );
332
- const handleCancelEdit = useCallback(() => {
333
- setIsEditing(false);
334
- onClose?.();
335
- }, [onClose]);
336
- const colors = [
337
- "rgba(255, 255, 0, 0.3)",
338
- // Yellow
339
- "rgba(0, 255, 0, 0.3)",
340
- // Green
341
- "rgba(255, 182, 193, 0.3)",
342
- // Pink
343
- "rgba(135, 206, 235, 0.3)"
344
- // Sky Blue
345
- ];
346
- return {
347
- comment,
348
- isEditing,
349
- setComment,
350
- setIsEditing,
351
- handleSaveComment,
352
- handleColorChange,
353
- handleCancelEdit,
354
- colors
355
- };
356
- };
357
- var DefaultAnnotationTooltipContent = ({
358
- annotation,
359
- onClose
360
- }) => {
361
- const {
362
- comment,
363
- isEditing,
364
- setComment,
365
- setIsEditing,
366
- handleSaveComment,
367
- handleColorChange,
368
- handleCancelEdit,
369
- colors
370
- } = useAnnotationActions({
371
- annotation,
372
- onClose
373
- });
374
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
375
- /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: colors.map((color) => /* @__PURE__ */ jsx(
376
- "button",
377
- {
378
- className: "w-6 h-6 rounded",
379
- style: { backgroundColor: color },
380
- onClick: () => handleColorChange(color)
381
- },
382
- color
383
- )) }),
384
- isEditing ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
385
- /* @__PURE__ */ jsx(
386
- "textarea",
387
- {
388
- value: comment,
389
- onChange: (e) => setComment(e.target.value),
390
- className: "border rounded p-2 text-sm",
391
- placeholder: "Add a comment...",
392
- rows: 3
393
- }
394
- ),
395
- /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
396
- /* @__PURE__ */ jsx(
397
- "button",
398
- {
399
- onClick: handleCancelEdit,
400
- className: "px-2 py-1 text-sm text-gray-600 hover:text-gray-800",
401
- children: "Cancel"
402
- }
403
- ),
404
- /* @__PURE__ */ jsx(
405
- "button",
406
- {
407
- onClick: handleSaveComment,
408
- className: "px-2 py-1 text-sm bg-blue-500 text-white rounded hover:bg-blue-600",
409
- children: "Save"
410
- }
411
- )
412
- ] })
413
- ] }) : /* @__PURE__ */ jsx("div", { children: annotation.comment ? /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-700", children: annotation.comment }) : /* @__PURE__ */ jsx(
414
- "button",
415
- {
416
- onClick: () => setIsEditing(true),
417
- className: "text-sm text-blue-500 hover:text-blue-600",
418
- children: "Add comment"
419
- }
420
- ) })
421
- ] });
422
- };
423
314
  var AnnotationHighlightLayer = ({
424
315
  className,
425
316
  style,
@@ -442,18 +333,11 @@ var AnnotationHighlightLayer = ({
442
333
  onAnnotationClick(annotation);
443
334
  }
444
335
  },
445
- tooltipContent: renderTooltipContent ? renderTooltipContent({
336
+ tooltipContent: renderTooltipContent({
446
337
  annotation,
447
338
  onClose: () => {
448
339
  }
449
- }) : /* @__PURE__ */ jsx(
450
- DefaultAnnotationTooltipContent,
451
- {
452
- annotation,
453
- onClose: () => {
454
- }
455
- }
456
- ),
340
+ }),
457
341
  children: /* @__PURE__ */ jsx(
458
342
  "div",
459
343
  {
@@ -469,10 +353,11 @@ var AnnotationHighlightLayer = ({
469
353
  width: highlight.width,
470
354
  height: highlight.height,
471
355
  backgroundColor: annotation.color || "rgba(255, 255, 0, 0.3)",
472
- transition: "background-color 0.2s ease",
473
- cursor: "pointer",
474
- opacity: focusedAnnotationId === annotation.id ? 1 : 0.5
475
- }
356
+ mixBlendMode: "multiply",
357
+ transition: "all 0.2s ease",
358
+ cursor: "pointer"
359
+ },
360
+ "data-highlight-id": annotation.id
476
361
  },
477
362
  index
478
363
  ))
@@ -1020,13 +905,13 @@ var CanvasLayer = ({
1020
905
  };
1021
906
 
1022
907
  // src/hooks/useSelectionDimensions.tsx
1023
- var MERGE_THRESHOLD = 20;
1024
- var shouldMergeRectangles = (rect1, rect2) => {
908
+ var MERGE_THRESHOLD = 5;
909
+ var shouldMergeRects = (rect1, rect2) => {
1025
910
  const verticalOverlap = !(rect1.top > rect2.top + rect2.height || rect2.top > rect1.top + rect1.height);
1026
911
  const horizontallyClose = 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;
1027
912
  return verticalOverlap && horizontallyClose;
1028
913
  };
1029
- var mergeRectangles = (rect1, rect2) => {
914
+ var mergeRects = (rect1, rect2) => {
1030
915
  return {
1031
916
  left: Math.min(rect1.left, rect2.left),
1032
917
  top: Math.min(rect1.top, rect2.top),
@@ -1037,38 +922,28 @@ var mergeRectangles = (rect1, rect2) => {
1037
922
  };
1038
923
  var consolidateRects = (rects) => {
1039
924
  if (rects.length <= 1) return rects;
1040
- const sortedRectangles = rects.toSorted((a, b) => a.top - b.top);
1041
- let withinThresholdMergedRectangles = sortedRectangles[0];
1042
- const allMergedRectangles = [];
1043
- const blowUpMergedRectangles = (rect) => {
1044
- return {
1045
- ...rect,
1046
- left: rect.left - 2,
1047
- top: rect.top - 2,
1048
- width: rect.width + 4,
1049
- height: rect.height + 2
1050
- };
1051
- };
1052
- for (const [index, currentRectangle] of sortedRectangles.entries()) {
1053
- withinThresholdMergedRectangles = mergeRectangles(
1054
- withinThresholdMergedRectangles,
1055
- currentRectangle
1056
- );
1057
- const nextRectangle = sortedRectangles[index + 1];
1058
- if (!nextRectangle) {
1059
- allMergedRectangles.push(
1060
- blowUpMergedRectangles(withinThresholdMergedRectangles)
1061
- );
1062
- break;
1063
- }
1064
- if (!shouldMergeRectangles(withinThresholdMergedRectangles, nextRectangle)) {
1065
- allMergedRectangles.push(
1066
- blowUpMergedRectangles(withinThresholdMergedRectangles)
1067
- );
1068
- withinThresholdMergedRectangles = nextRectangle;
925
+ const sortedRects = [...rects].sort((a, b) => a.top - b.top);
926
+ let hasChanges;
927
+ do {
928
+ hasChanges = false;
929
+ let currentRect = sortedRects[0];
930
+ const tempResult = [];
931
+ for (let i = 1; i < sortedRects.length; i++) {
932
+ const sorted = sortedRects[i];
933
+ if (!currentRect || !sorted) continue;
934
+ if (shouldMergeRects(currentRect, sorted)) {
935
+ currentRect = mergeRects(currentRect, sorted);
936
+ hasChanges = true;
937
+ } else {
938
+ tempResult.push(currentRect);
939
+ currentRect = sorted;
940
+ }
1069
941
  }
1070
- }
1071
- return allMergedRectangles;
942
+ if (currentRect) tempResult.push(currentRect);
943
+ sortedRects.length = 0;
944
+ sortedRects.push(...tempResult);
945
+ } while (hasChanges);
946
+ return sortedRects;
1072
947
  };
1073
948
  var useSelectionDimensions = () => {
1074
949
  const store = PDFStore.useContext();
@@ -1397,13 +1272,15 @@ var ColoredHighlightLayer = ({
1397
1272
  onHighlight
1398
1273
  }) => {
1399
1274
  const pageNumber = usePDFPageNumber();
1400
- const { getSelection } = useSelectionDimensions();
1275
+ const { getDimension } = useSelectionDimensions();
1401
1276
  const highlights = usePdf(
1402
1277
  (state) => state.coloredHighlights
1403
1278
  );
1404
1279
  const addColoredHighlight = usePdf((state) => state.addColoredHighlight);
1405
1280
  const handleHighlighting = useCallback((color) => {
1406
- const { highlights: highlights2, text } = getSelection();
1281
+ const dimension = getDimension();
1282
+ if (!dimension) return;
1283
+ const { highlights: highlights2, text } = dimension;
1407
1284
  if (highlights2[0]) {
1408
1285
  const highlight = {
1409
1286
  uuid: v4(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anaralabs/lector",
3
- "version": "3.5.0",
3
+ "version": "3.5.1",
4
4
  "description": "Headless PDF viewer for React",
5
5
  "author": "andrewdr (https://github.com/andrewdoro)",
6
6
  "license": "MIT",