@anaralabs/lector 3.9.1 → 3.10.0

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.
@@ -4,11 +4,12 @@ import type { DocumentInitParameters } from 'pdfjs-dist/types/src/display/api';
4
4
  import { ForwardRefExoticComponent } from 'react';
5
5
  import { FunctionComponent } from 'react';
6
6
  import { HTMLProps } from 'react';
7
- import type { IPDFLinkService } from 'pdfjs-dist/types/web/interfaces';
8
7
  import { JSX } from 'react/jsx-runtime';
9
- import type { JSX as JSX_2 } from 'react';
8
+ import { JSX as JSX_2 } from 'react';
9
+ import { MemoExoticComponent } from 'react';
10
10
  import type { PageViewport } from 'pdfjs-dist';
11
- import { PDFDocumentProxy } from 'pdfjs-dist';
11
+ import type { PDFDocumentProxy } from 'pdfjs-dist';
12
+ import { pdfjsDist } from 'pdfjs-dist';
12
13
  import type { PDFPageProxy } from 'pdfjs-dist';
13
14
  import type { default as React_2 } from 'react';
14
15
  import { ReactElement } from 'react';
@@ -68,7 +69,7 @@ declare interface AnnotationHighlightLayerProps {
68
69
  * @param jumpOptions - Options for page navigation behavior when clicking internal links.
69
70
  * See `usePdfJump` hook for available options.
70
71
  */
71
- export declare const AnnotationLayer: ({ renderForms, externalLinksEnabled, jumpOptions, className, style, ...props }: AnnotationLayerParams & HTMLProps<HTMLDivElement>) => JSX.Element;
72
+ export declare const AnnotationLayer: MemoExoticComponent<({ renderForms, externalLinksEnabled, jumpOptions, className, style, ...props }: AnnotationLayerParams & HTMLProps<HTMLDivElement>) => JSX.Element>;
72
73
 
73
74
  declare interface AnnotationLayerParams {
74
75
  /**
@@ -142,9 +143,9 @@ export declare const cancellable: <T extends Promise<unknown>>(promise: T) => {
142
143
  cancel: () => void;
143
144
  };
144
145
 
145
- export declare const CanvasLayer: ({ style, background, ...props }: HTMLProps<HTMLCanvasElement> & {
146
- background?: string;
147
- }) => JSX.Element;
146
+ export declare const CanvasLayer: MemoExoticComponent<({ style, background, ...props }: HTMLProps<HTMLCanvasElement> & {
147
+ background?: string;
148
+ }) => JSX.Element>;
148
149
 
149
150
  export declare const clamp: (value: number, minimum: number, maximum: number) => number;
150
151
 
@@ -175,9 +176,11 @@ export declare const CurrentPage: ({ ...props }: HTMLProps<HTMLInputElement>) =>
175
176
 
176
177
  export declare const CurrentZoom: ({ ...props }: HTMLProps<HTMLInputElement>) => JSX.Element;
177
178
 
178
- export declare const CustomLayer: ({ children, }: {
179
- children: (pageNumber: number) => JSX_2.Element;
180
- }) => JSX_2.Element;
179
+ export declare const CustomLayer: MemoExoticComponent<({ children }: {
180
+ children: (pageNumber: number) => JSX_2.Element;
181
+ }) => JSX_2.Element>;
182
+
183
+ export declare const ensureAnnotationLayerStyles: () => void;
181
184
 
182
185
  export declare const firstMemo: <T>(first: boolean, memo: unknown, initializer: () => T) => T;
183
186
 
@@ -225,7 +228,7 @@ export declare interface InitialPDFState {
225
228
  zoomOptions?: ZoomOptions;
226
229
  }
227
230
 
228
- export declare class LinkService implements IPDFLinkService {
231
+ export declare class LinkService {
229
232
  _pdfDocumentProxy?: PDFDocumentProxy;
230
233
  externalLinkEnabled: boolean;
231
234
  isInPresentationMode: boolean;
@@ -252,6 +255,8 @@ export declare class LinkService implements IPDFLinkService {
252
255
  unregisterPageNavigationCallback(): void;
253
256
  }
254
257
 
258
+ export declare const loadPdfJs: () => Promise<pdfjsDist>;
259
+
255
260
  export declare const NextPage: () => void;
256
261
 
257
262
  export declare const Outline: ({ children, ...props }: HTMLProps<HTMLUListElement> & {
@@ -273,10 +278,10 @@ declare interface OutlineItemProps extends HTMLProps<HTMLDivElement> {
273
278
 
274
279
  declare type OutlineItemType = NonNullable<ReturnType<typeof usePDFOutline>>[number];
275
280
 
276
- export declare const Page: ({ children, pageNumber, style, ...props }: HTMLProps<HTMLDivElement> & {
277
- children: ReactNode;
278
- pageNumber?: number;
279
- }) => JSX.Element;
281
+ export declare const Page: MemoExoticComponent<({ children, pageNumber, style, ...props }: HTMLProps<HTMLDivElement> & {
282
+ children: ReactNode;
283
+ pageNumber?: number;
284
+ }) => JSX.Element>;
280
285
 
281
286
  export declare const Pages: ({ children, gap, virtualizerOptions, initialOffset, onOffsetChange, ...props }: HTMLProps<HTMLDivElement> & {
282
287
  virtualizerOptions?: {
@@ -371,12 +376,14 @@ declare interface SelectionTooltipProps {
371
376
 
372
377
  export declare type Source = string | URL | TypedArray | ArrayBuffer | DocumentInitParameters;
373
378
 
379
+ export declare const subscribeToViewportInvalidation: (viewport: HTMLDivElement, callback: ViewportCallback) => () => void;
380
+
374
381
  declare type TextContent = {
375
382
  pageNumber: number;
376
383
  text: string;
377
384
  };
378
385
 
379
- export declare const TextLayer: ({ className, style, ...props }: HTMLProps<HTMLDivElement>) => JSX.Element;
386
+ export declare const TextLayer: MemoExoticComponent<({ className, style, ...props }: HTMLProps<HTMLDivElement>) => JSX.Element>;
380
387
 
381
388
  declare interface TextPosition {
382
389
  pageNumber: number;
@@ -494,6 +501,8 @@ export declare const useSelectionDimensions: () => {
494
501
  } | undefined;
495
502
  };
496
503
 
504
+ declare type ViewportCallback = () => void;
505
+
497
506
  export declare const ZoomIn: ({ ...props }: HTMLProps<HTMLButtonElement>) => JSX.Element;
498
507
 
499
508
  export declare interface ZoomOptions {
package/dist/index.js CHANGED
@@ -1,18 +1,15 @@
1
1
  'use client';
2
2
 
3
- import React, { createContext, forwardRef, useRef, useState, useCallback, useContext, useEffect, cloneElement, createRef, useMemo, useLayoutEffect } from 'react';
3
+ import React, { createContext, memo, forwardRef, cloneElement, useRef, useState, useCallback, useContext, useEffect, useMemo, useLayoutEffect, createRef } 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 { create, useStore, createStore } from 'zustand';
7
- import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
8
- import { AnnotationLayer, TextLayer, getDocument } from 'pdfjs-dist';
7
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
8
  import { useDebounce } from 'use-debounce';
10
9
  import { v4 } from 'uuid';
11
10
  import { Slot } from '@radix-ui/react-slot';
12
11
  import { useVirtualizer, elementScroll, debounce } from '@tanstack/react-virtual';
13
12
 
14
- // src/components/annotation-tooltip.tsx
15
-
16
13
  // src/lib/clamp.ts
17
14
  var clamp = (value, minimum, maximum) => {
18
15
  return Math.min(Math.max(value, minimum), maximum);
@@ -615,6 +612,56 @@ function clsx() {
615
612
  }
616
613
  var clsx_default = clsx;
617
614
 
615
+ // src/lib/annotation-layer-styles.ts
616
+ var ANNOTATION_LAYER_STYLE_ID = "lector-annotation-layer-styles";
617
+ var annotationLayerStyles = `
618
+ .annotationLayer {
619
+ position: absolute;
620
+ left: 0;
621
+ top: 0;
622
+ right: 0;
623
+ bottom: 0;
624
+ overflow: hidden;
625
+ opacity: 1;
626
+ z-index: 3;
627
+ }
628
+
629
+ .annotationLayer section {
630
+ position: absolute;
631
+ }
632
+
633
+ .annotationLayer .linkAnnotation > a,
634
+ .annotationLayer .buttonWidgetAnnotation.pushButton > a {
635
+ position: absolute;
636
+ font-size: 1em;
637
+ top: 0;
638
+ left: 0;
639
+ width: 100%;
640
+ height: 100%;
641
+ background: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7") 0 0 repeat;
642
+ cursor: pointer;
643
+ }
644
+
645
+ .annotationLayer .linkAnnotation > a:hover,
646
+ .annotationLayer .buttonWidgetAnnotation.pushButton > a:hover {
647
+ opacity: 0.2;
648
+ background: rgba(255, 255, 0, 1);
649
+ box-shadow: 0 2px 10px rgba(255, 255, 0, 1);
650
+ }
651
+ `;
652
+ var ensureAnnotationLayerStyles = () => {
653
+ if (typeof document === "undefined") {
654
+ return;
655
+ }
656
+ if (document.getElementById(ANNOTATION_LAYER_STYLE_ID)) {
657
+ return;
658
+ }
659
+ const style = document.createElement("style");
660
+ style.id = ANNOTATION_LAYER_STYLE_ID;
661
+ style.textContent = annotationLayerStyles;
662
+ document.head.appendChild(style);
663
+ };
664
+
618
665
  // src/lib/cancellable.ts
619
666
  var cancellable = (promise) => {
620
667
  let isCancelled = false;
@@ -639,6 +686,15 @@ var cancellable = (promise) => {
639
686
  }
640
687
  };
641
688
  };
689
+
690
+ // src/lib/pdfjs.ts
691
+ var pdfJsPromise = null;
692
+ var loadPdfJs = () => {
693
+ if (!pdfJsPromise) {
694
+ pdfJsPromise = import('pdfjs-dist');
695
+ }
696
+ return pdfJsPromise;
697
+ };
642
698
  var usePdfJump = () => {
643
699
  const virtualizer = usePdf((state) => state.virtualizer);
644
700
  const setHighlight = usePdf((state) => state.setHighlight);
@@ -931,46 +987,7 @@ var useAnnotationLayer = (params) => {
931
987
  };
932
988
  }, [jumpToPage, linkService, mergedParams.jumpOptions]);
933
989
  useEffect(() => {
934
- const style = document.createElement("style");
935
- style.textContent = `
936
- .annotationLayer {
937
- position: absolute;
938
- left: 0;
939
- top: 0;
940
- right: 0;
941
- bottom: 0;
942
- overflow: hidden;
943
- opacity: 1;
944
- z-index: 3;
945
- }
946
-
947
- .annotationLayer section {
948
- position: absolute;
949
- }
950
-
951
- .annotationLayer .linkAnnotation > a,
952
- .annotationLayer .buttonWidgetAnnotation.pushButton > a {
953
- position: absolute;
954
- font-size: 1em;
955
- top: 0;
956
- left: 0;
957
- width: 100%;
958
- height: 100%;
959
- background: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7") 0 0 repeat;
960
- cursor: pointer;
961
- }
962
-
963
- .annotationLayer .linkAnnotation > a:hover,
964
- .annotationLayer .buttonWidgetAnnotation.pushButton > a:hover {
965
- opacity: 0.2;
966
- background: rgba(255, 255, 0, 1);
967
- box-shadow: 0 2px 10px rgba(255, 255, 0, 1);
968
- }
969
- `;
970
- document.head.appendChild(style);
971
- return () => {
972
- document.head.removeChild(style);
973
- };
990
+ ensureAnnotationLayerStyles();
974
991
  }, []);
975
992
  useEffect(() => {
976
993
  if (!annotationLayerRef.current) return;
@@ -1011,22 +1028,27 @@ var useAnnotationLayer = (params) => {
1011
1028
  }
1012
1029
  annotationLayerRef.current.innerHTML = "";
1013
1030
  annotationLayerRef.current.className = "annotationLayer";
1014
- const viewport = pdfPageProxy.getViewport({ scale: 1 });
1031
+ const viewport = pdfPageProxy.getViewport({ scale: 1 }).clone({
1032
+ dontFlip: true
1033
+ });
1015
1034
  const annotationLayerConfig = {
1016
1035
  div: annotationLayerRef.current,
1017
1036
  viewport,
1018
1037
  page: pdfPageProxy,
1019
1038
  linkService,
1039
+ annotationStorage: void 0,
1020
1040
  accessibilityManager: void 0,
1021
1041
  annotationCanvasMap: void 0,
1022
1042
  annotationEditorUIManager: void 0,
1023
- structTreeLayer: void 0
1043
+ structTreeLayer: void 0,
1044
+ commentManager: void 0
1024
1045
  };
1025
- const annotationLayer = new AnnotationLayer(annotationLayerConfig);
1026
- annotationLayerObjectRef.current = annotationLayer;
1027
1046
  const { cancel } = cancellable(
1028
1047
  (async () => {
1029
1048
  try {
1049
+ const { AnnotationLayer: AnnotationLayer2 } = await loadPdfJs();
1050
+ const annotationLayer = new AnnotationLayer2(annotationLayerConfig);
1051
+ annotationLayerObjectRef.current = annotationLayer;
1030
1052
  const annotations = await pdfPageProxy.getAnnotations();
1031
1053
  await annotationLayer.render({
1032
1054
  ...annotationLayerConfig,
@@ -1046,34 +1068,37 @@ var useAnnotationLayer = (params) => {
1046
1068
  annotationLayerRef
1047
1069
  };
1048
1070
  };
1049
- var AnnotationLayer2 = ({
1050
- renderForms = true,
1051
- externalLinksEnabled = true,
1052
- jumpOptions = { behavior: "smooth", align: "start" },
1053
- className,
1054
- style,
1055
- ...props
1056
- }) => {
1057
- const { annotationLayerRef } = useAnnotationLayer({
1058
- renderForms,
1059
- externalLinksEnabled,
1060
- jumpOptions
1061
- });
1062
- return /* @__PURE__ */ jsx(
1063
- "div",
1064
- {
1065
- className: clsx_default("annotationLayer", className),
1066
- style: {
1067
- ...style,
1068
- position: "absolute",
1069
- top: 0,
1070
- left: 0
1071
- },
1072
- ...props,
1073
- ref: annotationLayerRef
1074
- }
1075
- );
1076
- };
1071
+ var AnnotationLayer = memo(
1072
+ ({
1073
+ renderForms = true,
1074
+ externalLinksEnabled = true,
1075
+ jumpOptions = { behavior: "smooth", align: "start" },
1076
+ className,
1077
+ style,
1078
+ ...props
1079
+ }) => {
1080
+ const { annotationLayerRef } = useAnnotationLayer({
1081
+ renderForms,
1082
+ externalLinksEnabled,
1083
+ jumpOptions
1084
+ });
1085
+ return /* @__PURE__ */ jsx(
1086
+ "div",
1087
+ {
1088
+ className: clsx_default("annotationLayer", className),
1089
+ style: {
1090
+ ...style,
1091
+ position: "absolute",
1092
+ top: 0,
1093
+ left: 0
1094
+ },
1095
+ ...props,
1096
+ ref: annotationLayerRef
1097
+ }
1098
+ );
1099
+ }
1100
+ );
1101
+ AnnotationLayer.displayName = "AnnotationLayer";
1077
1102
  var useDpr = () => {
1078
1103
  const [dpr, setDPR] = useState(
1079
1104
  typeof window === "undefined" ? 1 : Math.min(window.devicePixelRatio, 2)
@@ -1146,6 +1171,7 @@ var useCanvasLayer = ({ background }) => {
1146
1171
  baseCanvas.style.transform = "translate(0px, 0px)";
1147
1172
  baseCanvas.style.zIndex = "0";
1148
1173
  baseCanvas.style.pointerEvents = "none";
1174
+ baseCanvas.style.backgroundColor = background ?? "white";
1149
1175
  const context = baseCanvas.getContext("2d");
1150
1176
  if (!context) {
1151
1177
  return;
@@ -1154,6 +1180,7 @@ var useCanvasLayer = ({ background }) => {
1154
1180
  context.clearRect(0, 0, baseCanvas.width, baseCanvas.height);
1155
1181
  const viewport = pdfPageProxy.getViewport({ scale: baseScale });
1156
1182
  const renderingTask = pdfPageProxy.render({
1183
+ canvas: baseCanvas,
1157
1184
  canvasContext: context,
1158
1185
  viewport,
1159
1186
  background
@@ -1172,8 +1199,74 @@ var useCanvasLayer = ({ background }) => {
1172
1199
  canvasRef
1173
1200
  };
1174
1201
  };
1202
+
1203
+ // src/lib/viewport-invalidation.ts
1204
+ var viewportInvalidationRegistry = /* @__PURE__ */ new WeakMap();
1205
+ var notifyCallbacks = (entry) => {
1206
+ entry.rafId = null;
1207
+ entry.callbacks.forEach((callback) => {
1208
+ callback();
1209
+ });
1210
+ };
1211
+ var scheduleInvalidation = (entry) => {
1212
+ if (entry.rafId !== null) {
1213
+ return;
1214
+ }
1215
+ entry.rafId = requestAnimationFrame(() => {
1216
+ notifyCallbacks(entry);
1217
+ });
1218
+ };
1219
+ var subscribeToViewportInvalidation = (viewport, callback) => {
1220
+ let entry = viewportInvalidationRegistry.get(viewport);
1221
+ if (!entry) {
1222
+ const callbacks = /* @__PURE__ */ new Set();
1223
+ const schedule = () => {
1224
+ const currentEntry = viewportInvalidationRegistry.get(viewport);
1225
+ if (!currentEntry) {
1226
+ return;
1227
+ }
1228
+ scheduleInvalidation(currentEntry);
1229
+ };
1230
+ entry = {
1231
+ callbacks,
1232
+ scrollListener: schedule,
1233
+ windowResizeListener: schedule,
1234
+ resizeObserver: typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(schedule),
1235
+ rafId: null
1236
+ };
1237
+ viewport.addEventListener("scroll", entry.scrollListener, {
1238
+ passive: true
1239
+ });
1240
+ window.addEventListener("resize", entry.windowResizeListener, {
1241
+ passive: true
1242
+ });
1243
+ entry.resizeObserver?.observe(viewport);
1244
+ viewportInvalidationRegistry.set(viewport, entry);
1245
+ }
1246
+ entry.callbacks.add(callback);
1247
+ return () => {
1248
+ const currentEntry = viewportInvalidationRegistry.get(viewport);
1249
+ if (!currentEntry) {
1250
+ return;
1251
+ }
1252
+ currentEntry.callbacks.delete(callback);
1253
+ if (currentEntry.callbacks.size > 0) {
1254
+ return;
1255
+ }
1256
+ if (currentEntry.rafId !== null) {
1257
+ cancelAnimationFrame(currentEntry.rafId);
1258
+ }
1259
+ viewport.removeEventListener("scroll", currentEntry.scrollListener);
1260
+ window.removeEventListener("resize", currentEntry.windowResizeListener);
1261
+ currentEntry.resizeObserver?.disconnect();
1262
+ viewportInvalidationRegistry.delete(viewport);
1263
+ };
1264
+ };
1265
+
1266
+ // src/hooks/layers/useDetailCanvasLayer.tsx
1175
1267
  var MAX_CANVAS_PIXELS2 = 16777216;
1176
1268
  var MAX_CANVAS_DIMENSION2 = 32767;
1269
+ var DETAIL_RENDER_IDLE_MS = 80;
1177
1270
  var useDetailCanvasLayer = ({
1178
1271
  background,
1179
1272
  baseCanvasRef
@@ -1183,29 +1276,23 @@ var useDetailCanvasLayer = ({
1183
1276
  const pageNumber = usePDFPageNumber();
1184
1277
  const dpr = useDpr();
1185
1278
  const bouncyZoom = usePdf((state) => state.zoom);
1279
+ const isPinching = usePdf((state) => state.isPinching);
1186
1280
  const pdfPageProxy = usePdf((state) => state.getPdfPageProxy(pageNumber));
1187
1281
  const viewportRef = usePdf((state) => state.viewportRef);
1188
1282
  const [zoom] = useDebounce(bouncyZoom, 200);
1189
- const [scrollTick, setScrollTick] = useState(0);
1190
- const [debouncedScrollTick] = useDebounce(scrollTick, 20);
1191
- const ensureDetailCanvas = useCallback(() => {
1192
- let detailCanvas = detailCanvasRef.current;
1283
+ const getDetailCanvas = useCallback(() => {
1284
+ const detailCanvas = detailCanvasRef.current;
1193
1285
  if (!detailCanvas) {
1194
- const parent = baseCanvasRef.current?.parentElement;
1195
- if (!parent) {
1196
- return null;
1197
- }
1198
- detailCanvas = document.createElement("canvas");
1199
- parent.appendChild(detailCanvas);
1200
- detailCanvasRef.current = detailCanvas;
1286
+ return null;
1201
1287
  }
1202
1288
  detailCanvas.style.position = "absolute";
1203
1289
  detailCanvas.style.top = "0";
1204
1290
  detailCanvas.style.left = "0";
1205
1291
  detailCanvas.style.pointerEvents = "none";
1206
- detailCanvas.style.zIndex = "0";
1292
+ detailCanvas.style.zIndex = "1";
1293
+ detailCanvas.style.backgroundColor = background ?? "white";
1207
1294
  return detailCanvas;
1208
- }, [baseCanvasRef]);
1295
+ }, [background]);
1209
1296
  const clampScaleForPage = useCallback(
1210
1297
  (targetScale, pageWidth, pageHeight) => {
1211
1298
  if (!targetScale) {
@@ -1228,151 +1315,183 @@ var useDetailCanvasLayer = ({
1228
1315
  );
1229
1316
  useLayoutEffect(() => {
1230
1317
  const scrollContainer = viewportRef?.current;
1231
- if (!scrollContainer) return;
1232
- const handleScroll = () => {
1233
- setScrollTick((prev) => prev + 1);
1234
- };
1235
- scrollContainer.addEventListener("scroll", handleScroll, { passive: true });
1236
- return () => {
1237
- scrollContainer.removeEventListener("scroll", handleScroll);
1238
- };
1239
- }, [viewportRef?.current]);
1240
- useLayoutEffect(() => {
1241
- if (!viewportRef?.current) {
1318
+ if (!scrollContainer) {
1242
1319
  return;
1243
1320
  }
1244
- const detailCanvas = ensureDetailCanvas();
1321
+ const detailCanvas = getDetailCanvas();
1245
1322
  const container = containerRef.current;
1246
1323
  if (!detailCanvas || !container) {
1247
1324
  return;
1248
1325
  }
1249
- const scrollContainer = viewportRef.current;
1250
- const pageContainer = baseCanvasRef.current?.parentElement ?? null;
1251
- if (!pageContainer) {
1252
- detailCanvas.style.display = "none";
1253
- detailCanvas.width = 0;
1254
- detailCanvas.height = 0;
1255
- return;
1256
- }
1257
- const baseViewport = pdfPageProxy.getViewport({ scale: 1 });
1258
- const pageWidth = baseViewport.width;
1259
- const pageHeight = baseViewport.height;
1260
- const scrollX = scrollContainer.scrollLeft / zoom;
1261
- const scrollY = scrollContainer.scrollTop / zoom;
1262
- const viewportWidth = scrollContainer.clientWidth / zoom;
1263
- const viewportHeight = scrollContainer.clientHeight / zoom;
1264
- const pageRect = pageContainer.getBoundingClientRect();
1265
- const containerRect = scrollContainer.getBoundingClientRect();
1266
- const pageLeft = (pageRect.left - containerRect.left) / zoom + scrollX;
1267
- const pageTop = (pageRect.top - containerRect.top) / zoom + scrollY;
1268
- const visibleLeft = Math.max(0, scrollX - pageLeft);
1269
- const visibleTop = Math.max(0, scrollY - pageTop);
1270
- const visibleRight = Math.min(
1271
- pageWidth,
1272
- scrollX + viewportWidth - pageLeft
1273
- );
1274
- const visibleBottom = Math.min(
1275
- pageHeight,
1276
- scrollY + viewportHeight - pageTop
1277
- );
1278
- const visibleWidth = Math.max(0, visibleRight - visibleLeft);
1279
- const visibleHeight = Math.max(0, visibleBottom - visibleTop);
1280
- const targetDetailScale = dpr * zoom * 1.3;
1281
- const baseTargetScale = dpr * Math.min(zoom, 1);
1282
- const baseScale = clampScaleForPage(baseTargetScale, pageWidth, pageHeight);
1283
- const needsDetail = zoom > 1 && targetDetailScale - baseScale > 1e-3;
1284
- if (!needsDetail || visibleWidth <= 0 || visibleHeight <= 0) {
1285
- detailCanvas.style.display = "none";
1286
- detailCanvas.width = 0;
1287
- detailCanvas.height = 0;
1288
- return;
1289
- }
1290
- detailCanvas.style.display = "block";
1291
- const pdfOffsetX = visibleLeft;
1292
- const pdfOffsetY = visibleTop;
1293
- const pdfWidth = visibleWidth * targetDetailScale;
1294
- const pdfHeight = visibleHeight * targetDetailScale;
1295
- const effectiveScale = targetDetailScale;
1296
- const actualWidth = pdfWidth;
1297
- const actualHeight = pdfHeight;
1298
- detailCanvas.width = actualWidth;
1299
- detailCanvas.height = actualHeight;
1300
- const scaledWidth = visibleWidth * zoom;
1301
- const scaledHeight = visibleHeight * zoom;
1302
- detailCanvas.style.width = `${scaledWidth}px`;
1303
- detailCanvas.style.height = `${scaledHeight}px`;
1304
- detailCanvas.style.transformOrigin = "center center";
1305
- detailCanvas.style.transform = `translate(${visibleLeft * zoom}px, ${visibleTop * zoom}px) `;
1306
- container.style.transform = `scale3d(${1 / zoom}, ${1 / zoom}, 1)`;
1307
- container.style.transformOrigin = `0 0`;
1308
- const context = detailCanvas.getContext("2d");
1309
- if (!context) {
1310
- return;
1311
- }
1312
- context.setTransform(1, 0, 0, 1, 0, 0);
1313
- context.clearRect(0, 0, detailCanvas.width, detailCanvas.height);
1314
- const transform = [
1315
- 1,
1316
- 0,
1317
- 0,
1318
- 1,
1319
- -pdfOffsetX * effectiveScale,
1320
- -pdfOffsetY * effectiveScale
1321
- ];
1322
- const detailViewport = pdfPageProxy.getViewport({ scale: effectiveScale });
1323
- const renderingTask = pdfPageProxy.render({
1324
- canvasContext: context,
1325
- viewport: detailViewport,
1326
- background,
1327
- transform
1328
- });
1329
- renderingTask.promise.catch((error) => {
1330
- if (error.name === "RenderingCancelledException") {
1326
+ let renderingTask = null;
1327
+ let renderTimeoutId = null;
1328
+ const hideDetailCanvas = () => {
1329
+ renderingTask?.cancel();
1330
+ detailCanvas.style.display = "block";
1331
+ detailCanvas.style.opacity = "0";
1332
+ container.style.transform = "";
1333
+ container.style.transformOrigin = "";
1334
+ };
1335
+ const renderDetailCanvas = () => {
1336
+ const pageContainer = baseCanvasRef.current?.parentElement ?? null;
1337
+ if (!pageContainer) {
1338
+ hideDetailCanvas();
1331
1339
  return;
1332
1340
  }
1333
- throw error;
1334
- });
1341
+ const baseViewport = pdfPageProxy.getViewport({ scale: 1 });
1342
+ const pageWidth = baseViewport.width;
1343
+ const pageHeight = baseViewport.height;
1344
+ const scrollX = scrollContainer.scrollLeft / zoom;
1345
+ const scrollY = scrollContainer.scrollTop / zoom;
1346
+ const viewportWidth = scrollContainer.clientWidth / zoom;
1347
+ const viewportHeight = scrollContainer.clientHeight / zoom;
1348
+ const pageRect = pageContainer.getBoundingClientRect();
1349
+ const containerRect = scrollContainer.getBoundingClientRect();
1350
+ const pageLeft = (pageRect.left - containerRect.left) / zoom + scrollX;
1351
+ const pageTop = (pageRect.top - containerRect.top) / zoom + scrollY;
1352
+ const visibleLeft = Math.max(0, scrollX - pageLeft);
1353
+ const visibleTop = Math.max(0, scrollY - pageTop);
1354
+ const visibleRight = Math.min(
1355
+ pageWidth,
1356
+ scrollX + viewportWidth - pageLeft
1357
+ );
1358
+ const visibleBottom = Math.min(
1359
+ pageHeight,
1360
+ scrollY + viewportHeight - pageTop
1361
+ );
1362
+ const visibleWidth = Math.max(0, visibleRight - visibleLeft);
1363
+ const visibleHeight = Math.max(0, visibleBottom - visibleTop);
1364
+ const targetDetailScale = dpr * zoom * 1.3;
1365
+ const baseTargetScale = dpr * Math.min(zoom, 1);
1366
+ const baseScale = clampScaleForPage(
1367
+ baseTargetScale,
1368
+ pageWidth,
1369
+ pageHeight
1370
+ );
1371
+ const needsDetail = zoom > 1 && targetDetailScale - baseScale > 1e-3;
1372
+ if (isPinching || !needsDetail || visibleWidth <= 0 || visibleHeight <= 0) {
1373
+ hideDetailCanvas();
1374
+ return;
1375
+ }
1376
+ renderingTask?.cancel();
1377
+ detailCanvas.style.display = "block";
1378
+ detailCanvas.style.opacity = "0";
1379
+ const pdfOffsetX = visibleLeft;
1380
+ const pdfOffsetY = visibleTop;
1381
+ const effectiveScale = targetDetailScale;
1382
+ const actualWidth = visibleWidth * effectiveScale;
1383
+ const actualHeight = visibleHeight * effectiveScale;
1384
+ detailCanvas.width = actualWidth;
1385
+ detailCanvas.height = actualHeight;
1386
+ detailCanvas.style.width = `${visibleWidth * zoom}px`;
1387
+ detailCanvas.style.height = `${visibleHeight * zoom}px`;
1388
+ detailCanvas.style.transformOrigin = "center center";
1389
+ detailCanvas.style.transform = `translate(${visibleLeft * zoom}px, ${visibleTop * zoom}px)`;
1390
+ container.style.transform = `scale3d(${1 / zoom}, ${1 / zoom}, 1)`;
1391
+ container.style.transformOrigin = "0 0";
1392
+ const context = detailCanvas.getContext("2d");
1393
+ if (!context) {
1394
+ return;
1395
+ }
1396
+ context.setTransform(1, 0, 0, 1, 0, 0);
1397
+ context.clearRect(0, 0, detailCanvas.width, detailCanvas.height);
1398
+ const transform = [
1399
+ 1,
1400
+ 0,
1401
+ 0,
1402
+ 1,
1403
+ -pdfOffsetX * effectiveScale,
1404
+ -pdfOffsetY * effectiveScale
1405
+ ];
1406
+ const detailViewport = pdfPageProxy.getViewport({
1407
+ scale: effectiveScale
1408
+ });
1409
+ const currentRenderingTask = pdfPageProxy.render({
1410
+ canvas: detailCanvas,
1411
+ canvasContext: context,
1412
+ viewport: detailViewport,
1413
+ background,
1414
+ transform
1415
+ });
1416
+ renderingTask = currentRenderingTask;
1417
+ currentRenderingTask.promise.then(() => {
1418
+ if (renderingTask === currentRenderingTask) {
1419
+ detailCanvas.style.opacity = "1";
1420
+ }
1421
+ }).catch((error) => {
1422
+ if (error.name === "RenderingCancelledException") {
1423
+ return;
1424
+ }
1425
+ throw error;
1426
+ }).finally(() => {
1427
+ if (renderingTask === currentRenderingTask) {
1428
+ renderingTask = null;
1429
+ }
1430
+ });
1431
+ };
1432
+ const scheduleRender = (delay = DETAIL_RENDER_IDLE_MS) => {
1433
+ if (renderTimeoutId !== null) {
1434
+ clearTimeout(renderTimeoutId);
1435
+ }
1436
+ hideDetailCanvas();
1437
+ renderTimeoutId = setTimeout(() => {
1438
+ renderTimeoutId = null;
1439
+ renderDetailCanvas();
1440
+ }, delay);
1441
+ };
1442
+ const unsubscribe = subscribeToViewportInvalidation(
1443
+ scrollContainer,
1444
+ scheduleRender
1445
+ );
1446
+ scheduleRender(isPinching ? DETAIL_RENDER_IDLE_MS * 2 : 0);
1335
1447
  return () => {
1336
- void renderingTask.cancel();
1448
+ unsubscribe();
1449
+ if (renderTimeoutId !== null) {
1450
+ clearTimeout(renderTimeoutId);
1451
+ }
1452
+ void renderingTask?.cancel();
1337
1453
  };
1338
1454
  }, [
1339
1455
  pdfPageProxy,
1340
1456
  zoom,
1457
+ isPinching,
1341
1458
  background,
1342
1459
  dpr,
1343
1460
  viewportRef,
1344
- ensureDetailCanvas,
1461
+ getDetailCanvas,
1345
1462
  clampScaleForPage,
1346
- baseCanvasRef,
1347
- debouncedScrollTick
1463
+ baseCanvasRef
1348
1464
  ]);
1349
1465
  return {
1350
1466
  detailCanvasRef,
1351
1467
  containerRef
1352
1468
  };
1353
1469
  };
1354
- var CanvasLayer = ({
1355
- style,
1356
- background,
1357
- ...props
1358
- }) => {
1359
- const { canvasRef } = useCanvasLayer({ background });
1360
- const { detailCanvasRef, containerRef } = useDetailCanvasLayer({
1470
+ var CanvasLayer = memo(
1471
+ ({
1472
+ style,
1361
1473
  background,
1362
- baseCanvasRef: canvasRef
1363
- });
1364
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1365
- /* @__PURE__ */ jsx("canvas", { ...props, ref: canvasRef, style }),
1366
- /* @__PURE__ */ jsx(
1367
- "div",
1368
- {
1369
- ref: containerRef,
1370
- className: "absolute top-0 left-0 w-full h-full flex items-center justify-center",
1371
- children: /* @__PURE__ */ jsx("canvas", { ref: detailCanvasRef })
1372
- }
1373
- )
1374
- ] });
1375
- };
1474
+ ...props
1475
+ }) => {
1476
+ const { canvasRef } = useCanvasLayer({ background });
1477
+ const { detailCanvasRef, containerRef } = useDetailCanvasLayer({
1478
+ background,
1479
+ baseCanvasRef: canvasRef
1480
+ });
1481
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1482
+ /* @__PURE__ */ jsx("canvas", { ...props, ref: canvasRef, style }),
1483
+ /* @__PURE__ */ jsx(
1484
+ "div",
1485
+ {
1486
+ ref: containerRef,
1487
+ className: "absolute top-0 left-0 w-full h-full flex items-center justify-center",
1488
+ children: /* @__PURE__ */ jsx("canvas", { ref: detailCanvasRef })
1489
+ }
1490
+ )
1491
+ ] });
1492
+ }
1493
+ );
1494
+ CanvasLayer.displayName = "CanvasLayer";
1376
1495
 
1377
1496
  // src/hooks/useSelectionDimensions.tsx
1378
1497
  var MERGE_THRESHOLD = 2;
@@ -2118,14 +2237,13 @@ var ColoredHighlightLayer = ({
2118
2237
  )
2119
2238
  ] });
2120
2239
  };
2121
-
2122
- // src/components/layers/custom-layer.tsx
2123
- var CustomLayer = ({
2124
- children
2125
- }) => {
2126
- const pageNumber = usePDFPageNumber();
2127
- return children(pageNumber);
2128
- };
2240
+ var CustomLayer = memo(
2241
+ ({ children }) => {
2242
+ const pageNumber = usePDFPageNumber();
2243
+ return children(pageNumber);
2244
+ }
2245
+ );
2246
+ CustomLayer.displayName = "CustomLayer";
2129
2247
  var convertToPercentString = (rect) => {
2130
2248
  return {
2131
2249
  top: `${rect.top}%`,
@@ -2319,25 +2437,33 @@ var useTextLayer = () => {
2319
2437
  if (!textContainer || isRenderingRef.current) {
2320
2438
  return;
2321
2439
  }
2440
+ let isCancelled = false;
2322
2441
  isRenderingRef.current = true;
2323
2442
  textContainer.innerHTML = "";
2324
2443
  if (textLayerRef.current) {
2325
2444
  textLayerRef.current.cancel();
2326
2445
  textLayerRef.current = null;
2327
2446
  }
2328
- const textLayer = new TextLayer({
2329
- textContentSource: pdfPageProxy.streamTextContent(),
2330
- container: textContainer,
2331
- viewport: pdfPageProxy.getViewport({ scale: 1 })
2332
- });
2333
- textLayerRef.current = textLayer;
2334
- textLayer.render().then(() => {
2335
- if (textLayerRef.current === textLayer && textContainer) {
2336
- const endOfContent = document.createElement("div");
2337
- endOfContent.className = "endOfContent";
2338
- textContainer.appendChild(endOfContent);
2339
- bindMouseEvents(textContainer, endOfContent);
2447
+ void loadPdfJs().then(({ TextLayer: TextLayer2 }) => {
2448
+ if (isCancelled || textContainerRef.current !== textContainer) {
2449
+ return;
2450
+ }
2451
+ const textLayer = new TextLayer2({
2452
+ textContentSource: pdfPageProxy.streamTextContent(),
2453
+ container: textContainer,
2454
+ viewport: pdfPageProxy.getViewport({ scale: 1 })
2455
+ });
2456
+ textLayerRef.current = textLayer;
2457
+ return textLayer.render();
2458
+ }).then(() => {
2459
+ const textLayer = textLayerRef.current;
2460
+ if (!textLayer || isCancelled || textContainerRef.current !== textContainer) {
2461
+ return;
2340
2462
  }
2463
+ const endOfContent = document.createElement("div");
2464
+ endOfContent.className = "endOfContent";
2465
+ textContainer.appendChild(endOfContent);
2466
+ bindMouseEvents(textContainer, endOfContent);
2341
2467
  }).catch((error) => {
2342
2468
  if (error.name !== "AbortException") {
2343
2469
  console.error("TextLayer rendering error:", error);
@@ -2346,6 +2472,7 @@ var useTextLayer = () => {
2346
2472
  isRenderingRef.current = false;
2347
2473
  });
2348
2474
  return () => {
2475
+ isCancelled = true;
2349
2476
  isRenderingRef.current = false;
2350
2477
  if (textLayerRef.current) {
2351
2478
  textLayerRef.current.cancel();
@@ -2362,30 +2489,29 @@ var useTextLayer = () => {
2362
2489
  pageNumber: pdfPageProxy.pageNumber
2363
2490
  };
2364
2491
  };
2365
- var TextLayer2 = ({
2366
- className,
2367
- style,
2368
- ...props
2369
- }) => {
2370
- const { textContainerRef, pageNumber } = useTextLayer();
2371
- return /* @__PURE__ */ jsx(
2372
- "div",
2373
- {
2374
- className: clsx_default("textLayer", className),
2375
- style: {
2376
- ...style,
2377
- position: "absolute",
2378
- top: 0,
2379
- left: 0
2380
- },
2381
- ...props,
2382
- ...{
2383
- "data-page-number": pageNumber
2384
- },
2385
- ref: textContainerRef
2386
- }
2387
- );
2388
- };
2492
+ var TextLayer = memo(
2493
+ ({ className, style, ...props }) => {
2494
+ const { textContainerRef, pageNumber } = useTextLayer();
2495
+ return /* @__PURE__ */ jsx(
2496
+ "div",
2497
+ {
2498
+ className: clsx_default("textLayer", className),
2499
+ style: {
2500
+ ...style,
2501
+ position: "absolute",
2502
+ top: 0,
2503
+ left: 0
2504
+ },
2505
+ ...props,
2506
+ ...{
2507
+ "data-page-number": pageNumber
2508
+ },
2509
+ ref: textContainerRef
2510
+ }
2511
+ );
2512
+ }
2513
+ );
2514
+ TextLayer.displayName = "TextLayer";
2389
2515
  var usePDFOutline = () => {
2390
2516
  const pdfDocumentProxy = usePdf((state) => state.pdfDocumentProxy);
2391
2517
  const [outline, setOutline] = useState();
@@ -2523,40 +2649,44 @@ var Outline = ({
2523
2649
  });
2524
2650
  }) });
2525
2651
  };
2526
- var Page = ({
2527
- children,
2528
- pageNumber = 1,
2529
- style,
2530
- ...props
2531
- }) => {
2532
- const pdfPageProxy = usePdf((state) => state.getPdfPageProxy(pageNumber));
2533
- const viewport = usePdf((state) => state.viewports[pageNumber - 1]);
2534
- const width = viewport?.width ?? (pdfPageProxy.view[2] ?? 0) - (pdfPageProxy.view[0] ?? 0);
2535
- const height = viewport?.height ?? (pdfPageProxy.view[3] ?? 0) - (pdfPageProxy.view[1] ?? 0);
2536
- return /* @__PURE__ */ jsx(PDFPageNumberContext.Provider, { value: pdfPageProxy.pageNumber, children: /* @__PURE__ */ jsx(
2537
- Primitive.div,
2538
- {
2539
- style: {
2540
- display: "block"
2541
- },
2542
- children: /* @__PURE__ */ jsx(
2543
- "div",
2544
- {
2545
- style: {
2546
- ...style,
2547
- "--scale-factor": 1,
2548
- "--total-scale-factor": 1,
2549
- position: "relative",
2550
- width,
2551
- height
2552
- },
2553
- ...props,
2554
- children
2555
- }
2556
- )
2557
- }
2558
- ) });
2559
- };
2652
+ var Page = memo(
2653
+ ({
2654
+ children,
2655
+ pageNumber = 1,
2656
+ style,
2657
+ ...props
2658
+ }) => {
2659
+ const pdfPageProxy = usePdf((state) => state.getPdfPageProxy(pageNumber));
2660
+ const viewport = usePdf((state) => state.viewports[pageNumber - 1]);
2661
+ const width = viewport?.width ?? (pdfPageProxy.view[2] ?? 0) - (pdfPageProxy.view[0] ?? 0);
2662
+ const height = viewport?.height ?? (pdfPageProxy.view[3] ?? 0) - (pdfPageProxy.view[1] ?? 0);
2663
+ return /* @__PURE__ */ jsx(PDFPageNumberContext.Provider, { value: pdfPageProxy.pageNumber, children: /* @__PURE__ */ jsx(
2664
+ Primitive.div,
2665
+ {
2666
+ style: {
2667
+ display: "block"
2668
+ },
2669
+ children: /* @__PURE__ */ jsx(
2670
+ "div",
2671
+ {
2672
+ style: {
2673
+ "--scale-factor": 1,
2674
+ "--total-scale-factor": 1,
2675
+ backgroundColor: "white",
2676
+ position: "relative",
2677
+ width,
2678
+ height,
2679
+ ...style
2680
+ },
2681
+ ...props,
2682
+ children
2683
+ }
2684
+ )
2685
+ }
2686
+ ) });
2687
+ }
2688
+ );
2689
+ Page.displayName = "Page";
2560
2690
  var NextPage = () => {
2561
2691
  };
2562
2692
  var PreviousPage = () => {
@@ -3177,10 +3307,10 @@ var Engine = class {
3177
3307
  const config = this.config;
3178
3308
  if (!state._active) this.clean();
3179
3309
  if ((state._blocked || !state.intentional) && !state._force && !config.triggerAllEvents) return;
3180
- const memo = this.handler(_objectSpread2(_objectSpread2(_objectSpread2({}, shared), state), {}, {
3310
+ const memo7 = this.handler(_objectSpread2(_objectSpread2(_objectSpread2({}, shared), state), {}, {
3181
3311
  [this.aliasKey]: state.values
3182
3312
  }));
3183
- if (memo !== void 0) state.memo = memo;
3313
+ if (memo7 !== void 0) state.memo = memo7;
3184
3314
  }
3185
3315
  clean() {
3186
3316
  this.eventStore.clean();
@@ -4529,11 +4659,11 @@ Please add \`${key}Action\` when creating your handler.`);
4529
4659
  const startKey = handlerKey + "Start";
4530
4660
  const endKey = handlerKey + "End";
4531
4661
  const fn = (state) => {
4532
- let memo = void 0;
4662
+ let memo7 = void 0;
4533
4663
  if (state.first && startKey in handlers) handlers[startKey](state);
4534
- if (handlerKey in handlers) memo = handlers[handlerKey](state);
4664
+ if (handlerKey in handlers) memo7 = handlers[handlerKey](state);
4535
4665
  if (state.last && endKey in handlers) handlers[endKey](state);
4536
- return memo;
4666
+ return memo7;
4537
4667
  };
4538
4668
  internalHandlers[key] = fn;
4539
4669
  config[key] = config[key] || {};
@@ -4585,8 +4715,8 @@ function useGesture(handlers, config) {
4585
4715
  }
4586
4716
 
4587
4717
  // src/lib/memo.ts
4588
- var firstMemo = (first, memo, initializer) => {
4589
- if (!first && !memo) {
4718
+ var firstMemo = (first, memo7, initializer) => {
4719
+ if (!first && !memo7) {
4590
4720
  throw new Error(
4591
4721
  "Missing memo initialization. You likely forgot to return the result of `firstMemo` in the event function"
4592
4722
  );
@@ -4594,7 +4724,7 @@ var firstMemo = (first, memo, initializer) => {
4594
4724
  if (first) {
4595
4725
  return initializer();
4596
4726
  }
4597
- return memo;
4727
+ return memo7;
4598
4728
  };
4599
4729
 
4600
4730
  // src/hooks/viewport/useViewportContainer.tsx
@@ -4726,13 +4856,13 @@ var useViewportContainer = ({
4726
4856
  useGesture(
4727
4857
  {
4728
4858
  onPinch: (state) => {
4729
- const { origin: origin2, first, movement, delta, event, memo } = state;
4859
+ const { origin: origin2, first, movement, delta, event, memo: memo7 } = state;
4730
4860
  const [ms] = movement;
4731
4861
  const [deltaScale] = delta;
4732
4862
  const currentElement = elementRef.current;
4733
4863
  const currentContainer = containerRef.current;
4734
4864
  if (!currentElement || !currentContainer) return;
4735
- const newMemo = firstMemo(first, memo, () => {
4865
+ const newMemo = firstMemo(first, memo7, () => {
4736
4866
  const elementRect = currentElement.getBoundingClientRect();
4737
4867
  const containerRect = currentContainer.getBoundingClientRect();
4738
4868
  const currentZoom = transformations.current.zoom;
@@ -4801,10 +4931,39 @@ var useViewportContainer = ({
4801
4931
  };
4802
4932
  var DEFAULT_HEIGHT = 600;
4803
4933
  var EXTRA_HEIGHT = 0;
4934
+ var VirtualizedPageItem = memo(
4935
+ ({ child, virtualItem, innerBoxWidth }) => {
4936
+ return /* @__PURE__ */ jsx(
4937
+ "div",
4938
+ {
4939
+ style: {
4940
+ width: innerBoxWidth,
4941
+ height: "0px"
4942
+ },
4943
+ children: /* @__PURE__ */ jsx(
4944
+ "div",
4945
+ {
4946
+ style: {
4947
+ height: `${virtualItem.size}px`,
4948
+ transform: `translateY(${virtualItem.start}px)`
4949
+ },
4950
+ children: cloneElement(child, {
4951
+ key: virtualItem.key,
4952
+ //@ts-expect-error pageNumber is not a valid react key
4953
+ pageNumber: virtualItem.index + 1
4954
+ })
4955
+ }
4956
+ )
4957
+ }
4958
+ );
4959
+ },
4960
+ (prev, next) => prev.child === next.child && prev.innerBoxWidth === next.innerBoxWidth && prev.virtualItem.key === next.virtualItem.key && prev.virtualItem.index === next.virtualItem.index && prev.virtualItem.size === next.virtualItem.size && prev.virtualItem.start === next.virtualItem.start
4961
+ );
4962
+ VirtualizedPageItem.displayName = "VirtualizedPageItem";
4804
4963
  var Pages = ({
4805
4964
  children,
4806
4965
  gap = 10,
4807
- virtualizerOptions = { overscan: 2 },
4966
+ virtualizerOptions = { overscan: 1 },
4808
4967
  initialOffset,
4809
4968
  onOffsetChange,
4810
4969
  ...props
@@ -4870,7 +5029,9 @@ var Pages = ({
4870
5029
  });
4871
5030
  useFitWidth({ viewportRef: containerRef });
4872
5031
  const largestPageWidth = usePdf(
4873
- (state) => Math.max(...state.viewports.map((v) => v.width))
5032
+ (state) => state.viewports.reduce((largestWidth, viewport) => {
5033
+ return Math.max(largestWidth, viewport.width);
5034
+ }, 0)
4874
5035
  );
4875
5036
  useEffect(() => {
4876
5037
  virtualizer.getOffsetForAlignment = (toOffset, align, itemSize = 0) => {
@@ -4931,26 +5092,11 @@ var Pages = ({
4931
5092
  const innerBoxWidth = viewports?.[virtualItem.index] ? viewports[virtualItem.index]?.width : 0;
4932
5093
  if (!innerBoxWidth) return null;
4933
5094
  return /* @__PURE__ */ jsx(
4934
- "div",
5095
+ VirtualizedPageItem,
4935
5096
  {
4936
- style: {
4937
- width: innerBoxWidth,
4938
- height: `0px`
4939
- },
4940
- children: /* @__PURE__ */ jsx(
4941
- "div",
4942
- {
4943
- style: {
4944
- height: `${virtualItem.size}px`,
4945
- transform: `translateY(${virtualItem.start}px)`
4946
- },
4947
- children: cloneElement(children, {
4948
- key: virtualItem.key,
4949
- //@ts-expect-error pageNumber is not a valid react key
4950
- pageNumber: virtualItem.index + 1
4951
- })
4952
- }
4953
- )
5097
+ child: children,
5098
+ virtualItem,
5099
+ innerBoxWidth
4954
5100
  },
4955
5101
  virtualItem.key
4956
5102
  );
@@ -5006,28 +5152,44 @@ var usePDFDocumentContext = ({
5006
5152
  const loadDocument = () => {
5007
5153
  setInitialState(null);
5008
5154
  setProgress(0);
5009
- const loadingTask = getDocument(source);
5010
- loadingTask.onProgress = (progressEvent) => {
5011
- if (progressEvent.loaded === progressEvent.total) {
5155
+ let loadingTask = null;
5156
+ let isDisposed = false;
5157
+ void loadPdfJs().then(({ getDocument }) => {
5158
+ if (isDisposed) {
5012
5159
  return;
5013
5160
  }
5014
- setProgress(progressEvent.loaded / progressEvent.total);
5015
- };
5016
- const loadingPromise = loadingTask.promise.then((proxy) => {
5017
- onDocumentLoad?.({ proxy, source });
5018
- setProgress(1);
5019
- generateViewports(proxy);
5161
+ loadingTask = getDocument(source);
5162
+ loadingTask.onProgress = (progressEvent) => {
5163
+ if (progressEvent.loaded === progressEvent.total) {
5164
+ return;
5165
+ }
5166
+ setProgress(progressEvent.loaded / progressEvent.total);
5167
+ };
5168
+ return loadingTask.promise.then((proxy) => {
5169
+ if (isDisposed || loadingTask?.destroyed) {
5170
+ return;
5171
+ }
5172
+ onDocumentLoad?.({ proxy, source });
5173
+ setProgress(1);
5174
+ return generateViewports(proxy);
5175
+ }).catch((error) => {
5176
+ if (isDisposed || loadingTask?.destroyed) {
5177
+ return;
5178
+ }
5179
+ console.error("Error loading PDF document", error);
5180
+ });
5020
5181
  }).catch((error) => {
5021
- if (loadingTask.destroyed) {
5182
+ if (isDisposed) {
5022
5183
  return;
5023
5184
  }
5024
- console.error("Error loading PDF document", error);
5185
+ console.error("Error loading PDF.js", error);
5025
5186
  });
5026
5187
  return () => {
5027
- loadingPromise.finally(() => loadingTask.destroy());
5188
+ isDisposed = true;
5189
+ void loadingTask?.destroy();
5028
5190
  };
5029
5191
  };
5030
- loadDocument();
5192
+ return loadDocument();
5031
5193
  }, [source]);
5032
5194
  return {
5033
5195
  initialState
@@ -5118,6 +5280,7 @@ var useThumbnail = (pageNumber, config = {}) => {
5118
5280
  const context = canvas.getContext("2d");
5119
5281
  if (!context) return;
5120
5282
  const renderTask = pageProxy.render({
5283
+ canvas,
5121
5284
  canvasContext: context,
5122
5285
  viewport: scaledViewport
5123
5286
  });
@@ -5468,4 +5631,4 @@ function mergeAdjacentRects(rects) {
5468
5631
  return merged;
5469
5632
  }
5470
5633
 
5471
- export { AnnotationHighlightLayer, AnnotationLayer2 as AnnotationLayer, AnnotationTooltip, CanvasLayer, ColoredHighlightLayer, CurrentPage, CurrentZoom, CustomLayer, HighlightLayer, LinkService, NextPage, Outline, OutlineChildItems, OutlineItem, PDFLinkServiceContext, Page, Pages, PreviousPage, Root, Search, SelectionTooltip, TextLayer2 as TextLayer, Thumbnail, Thumbnails, TotalPages, ZoomIn, ZoomOut, calculateHighlightRects, useAnnotations, useCreatePDFLinkService, usePDFLinkService, usePDFPageNumber, usePdf, usePdfJump, useSearch, useSelectionDimensions };
5634
+ export { AnnotationHighlightLayer, AnnotationLayer, AnnotationTooltip, CanvasLayer, ColoredHighlightLayer, CurrentPage, CurrentZoom, CustomLayer, HighlightLayer, LinkService, NextPage, Outline, OutlineChildItems, OutlineItem, PDFLinkServiceContext, Page, Pages, PreviousPage, Root, Search, SelectionTooltip, TextLayer, Thumbnail, Thumbnails, TotalPages, ZoomIn, ZoomOut, calculateHighlightRects, useAnnotations, useCreatePDFLinkService, usePDFLinkService, usePDFPageNumber, usePdf, usePdfJump, useSearch, useSelectionDimensions };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anaralabs/lector",
3
- "version": "3.9.1",
3
+ "version": "3.10.0",
4
4
  "description": "Headless PDF viewer for React",
5
5
  "author": "andrewdr (https://github.com/andrewdoro)",
6
6
  "license": "MIT",
@@ -44,7 +44,7 @@
44
44
  "@vitejs/plugin-react": "^4.3.4",
45
45
  "@vitest/browser": "^2.0.4",
46
46
  "clsx": "^2.1.1",
47
- "pdfjs-dist": "^4.10.38",
47
+ "pdfjs-dist": "^5.5.207",
48
48
  "playwright": "^1.45.3",
49
49
  "react": "^19.1.1",
50
50
  "size-limit": "^11.1.6",
@@ -57,7 +57,7 @@
57
57
  "webdriverio": "^8.39.1"
58
58
  },
59
59
  "peerDependencies": {
60
- "pdfjs-dist": "^4.9",
60
+ "pdfjs-dist": "^5.5.207",
61
61
  "react": ">=19"
62
62
  },
63
63
  "dependencies": {