@anaralabs/lector 3.10.2 → 3.10.3

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.
@@ -124,12 +124,6 @@ declare interface AnnotationTooltipProps {
124
124
  }) => React.ReactNode;
125
125
  }
126
126
 
127
- declare type CacheEntry = {
128
- bitmap: ImageBitmap;
129
- width: number;
130
- height: number;
131
- };
132
-
133
127
  /**
134
128
  * Calculates the highlight rectangles for a given text match.
135
129
  *
@@ -351,51 +345,6 @@ export declare type PDFVirtualizer = Virtualizer<any, any>;
351
345
 
352
346
  export declare const PreviousPage: () => void;
353
347
 
354
- /**
355
- * LRU cache for rendered page bitmaps. When scrolling back to a previously
356
- * rendered page at the same scale, we can draw from cache instantly instead
357
- * of re-rendering through PDF.js.
358
- *
359
- * Cache keys include a document ID to prevent collisions when multiple
360
- * <Root> instances render different PDFs on the same page.
361
- */
362
- declare class RenderCache {
363
- private cache;
364
- private maxEntries;
365
- private invalidatedDocs;
366
- constructor(maxEntries?: number);
367
- private key;
368
- get(documentId: string, pageNumber: number, scale: number, background?: string): CacheEntry | undefined;
369
- set(documentId: string, pageNumber: number, scale: number, canvas: HTMLCanvasElement, background?: string): Promise<void>;
370
- /** Remove all cached entries for a specific document (call on Root unmount). */
371
- invalidateDocument(documentId: string): void;
372
- clear(): void;
373
- }
374
-
375
- export declare const renderCache: RenderCache;
376
-
377
- /**
378
- * Serializes PDF page render operations so only one runs at a time.
379
- * This prevents multiple heavy pages from competing for CPU and blocking the UI.
380
- */
381
- declare class RenderQueue {
382
- private queue;
383
- private running;
384
- enqueue(execute: () => Promise<void>): {
385
- promise: Promise<void>;
386
- cancel: () => void;
387
- };
388
- private flush;
389
- }
390
-
391
- /**
392
- * Global singleton — intentionally shared across all <Root> instances.
393
- * Serializing renders across documents prevents overall GPU/CPU pressure
394
- * on the main thread (CanvasGraphics is single-threaded). The trade-off
395
- * is increased latency in multi-viewer setups.
396
- */
397
- export declare const renderQueue: RenderQueue;
398
-
399
348
  export declare const Root: ForwardRefExoticComponent<Omit<HTMLProps<HTMLDivElement> & usePDFDocumentParams & {
400
349
  loader?: ReactNode;
401
350
  }, "ref"> & RefAttributes<unknown>>;
package/dist/index.js CHANGED
@@ -676,40 +676,6 @@ var ensureAnnotationLayerStyles = () => {
676
676
  style.textContent = annotationLayerStyles;
677
677
  document.head.appendChild(style);
678
678
  };
679
-
680
- // src/lib/cancellable.ts
681
- var cancellable = (promise) => {
682
- let isCancelled = false;
683
- const wrappedPromise = new Promise((resolve, reject) => {
684
- promise.then(
685
- (value) => {
686
- if (!isCancelled) {
687
- resolve(value);
688
- }
689
- },
690
- (error) => {
691
- if (!isCancelled) {
692
- reject(error);
693
- }
694
- }
695
- );
696
- });
697
- return {
698
- promise: wrappedPromise,
699
- cancel() {
700
- isCancelled = true;
701
- }
702
- };
703
- };
704
-
705
- // src/lib/pdfjs.ts
706
- var pdfJsPromise = null;
707
- var loadPdfJs = () => {
708
- if (!pdfJsPromise) {
709
- pdfJsPromise = import('pdfjs-dist/legacy/build/pdf.mjs');
710
- }
711
- return pdfJsPromise;
712
- };
713
679
  var usePdfJump = () => {
714
680
  const virtualizer = usePdf((state) => state.virtualizer);
715
681
  const setHighlight = usePdf((state) => state.setHighlight);
@@ -1041,13 +1007,15 @@ var useAnnotationLayer = (params) => {
1041
1007
  if (linkService._pdfDocumentProxy !== pdfDocumentProxy) {
1042
1008
  linkService.setDocument(pdfDocumentProxy);
1043
1009
  }
1044
- annotationLayerRef.current.innerHTML = "";
1045
- annotationLayerRef.current.className = "annotationLayer";
1010
+ const container = annotationLayerRef.current;
1011
+ let cancelled = false;
1012
+ container.replaceChildren();
1013
+ container.className = "annotationLayer";
1046
1014
  const viewport = pdfPageProxy.getViewport({ scale: 1 }).clone({
1047
1015
  dontFlip: true
1048
1016
  });
1049
1017
  const annotationLayerConfig = {
1050
- div: annotationLayerRef.current,
1018
+ div: container,
1051
1019
  viewport,
1052
1020
  page: pdfPageProxy,
1053
1021
  linkService,
@@ -1058,25 +1026,26 @@ var useAnnotationLayer = (params) => {
1058
1026
  structTreeLayer: void 0,
1059
1027
  commentManager: void 0
1060
1028
  };
1061
- const { cancel } = cancellable(
1062
- (async () => {
1063
- try {
1064
- const { AnnotationLayer: AnnotationLayer2 } = await loadPdfJs();
1065
- const annotationLayer = new AnnotationLayer2(annotationLayerConfig);
1066
- annotationLayerObjectRef.current = annotationLayer;
1067
- const annotations = await pdfPageProxy.getAnnotations();
1068
- await annotationLayer.render({
1069
- ...annotationLayerConfig,
1070
- ...mergedParams,
1071
- annotations,
1072
- linkService
1073
- });
1074
- } catch (_error) {
1075
- }
1076
- })()
1077
- );
1029
+ (async () => {
1030
+ try {
1031
+ if (cancelled) return;
1032
+ const { AnnotationLayer: AnnotationLayer2 } = await import('pdfjs-dist/legacy/build/pdf.mjs');
1033
+ if (cancelled) return;
1034
+ const annotationLayer = new AnnotationLayer2(annotationLayerConfig);
1035
+ annotationLayerObjectRef.current = annotationLayer;
1036
+ const annotations = await pdfPageProxy.getAnnotations();
1037
+ if (cancelled) return;
1038
+ await annotationLayer.render({
1039
+ ...annotationLayerConfig,
1040
+ ...mergedParams,
1041
+ annotations,
1042
+ linkService
1043
+ });
1044
+ } catch (_error) {
1045
+ }
1046
+ })();
1078
1047
  return () => {
1079
- cancel();
1048
+ cancelled = true;
1080
1049
  };
1081
1050
  }, [pdfPageProxy, pdfDocumentProxy, mergedParams, linkService]);
1082
1051
  return {
@@ -1135,125 +1104,6 @@ function clampScaleForPage(targetScale, pageWidth, pageHeight) {
1135
1104
  );
1136
1105
  return Math.max(safeScale, 0);
1137
1106
  }
1138
-
1139
- // src/lib/render-cache.ts
1140
- var RenderCache = class {
1141
- cache = /* @__PURE__ */ new Map();
1142
- maxEntries;
1143
- // Tracks invalidated documents so in-flight createImageBitmap calls
1144
- // don't insert orphaned entries after invalidateDocument() runs.
1145
- invalidatedDocs = /* @__PURE__ */ new Set();
1146
- constructor(maxEntries = 60) {
1147
- this.maxEntries = maxEntries;
1148
- }
1149
- key(documentId, pageNumber, scale, background) {
1150
- return `${documentId}-${pageNumber}-${scale}-${background ?? "white"}`;
1151
- }
1152
- get(documentId, pageNumber, scale, background) {
1153
- const k = this.key(documentId, pageNumber, scale, background);
1154
- const entry = this.cache.get(k);
1155
- if (!entry) return void 0;
1156
- this.cache.delete(k);
1157
- this.cache.set(k, entry);
1158
- return entry;
1159
- }
1160
- async set(documentId, pageNumber, scale, canvas, background) {
1161
- const k = this.key(documentId, pageNumber, scale, background);
1162
- const w = canvas.width;
1163
- const h = canvas.height;
1164
- if (w === 0 || h === 0) return;
1165
- while (this.cache.size >= this.maxEntries) {
1166
- const oldest = this.cache.keys().next().value;
1167
- if (oldest !== void 0) {
1168
- const entry = this.cache.get(oldest);
1169
- entry?.bitmap.close();
1170
- this.cache.delete(oldest);
1171
- }
1172
- }
1173
- try {
1174
- const bitmap = await createImageBitmap(canvas);
1175
- if (this.invalidatedDocs.has(documentId)) {
1176
- bitmap.close();
1177
- return;
1178
- }
1179
- this.cache.set(k, {
1180
- bitmap,
1181
- width: w,
1182
- height: h
1183
- });
1184
- } catch {
1185
- }
1186
- }
1187
- /** Remove all cached entries for a specific document (call on Root unmount). */
1188
- invalidateDocument(documentId) {
1189
- this.invalidatedDocs.add(documentId);
1190
- for (const [k, entry] of this.cache) {
1191
- if (k.startsWith(`${documentId}-`)) {
1192
- entry.bitmap.close();
1193
- this.cache.delete(k);
1194
- }
1195
- }
1196
- setTimeout(() => {
1197
- this.invalidatedDocs.delete(documentId);
1198
- }, 1e3);
1199
- }
1200
- clear() {
1201
- for (const entry of this.cache.values()) {
1202
- entry.bitmap.close();
1203
- }
1204
- this.cache.clear();
1205
- this.invalidatedDocs.clear();
1206
- }
1207
- };
1208
- var renderCache = new RenderCache();
1209
-
1210
- // src/lib/render-queue.ts
1211
- var RenderQueue = class {
1212
- queue = [];
1213
- running = false;
1214
- enqueue(execute) {
1215
- let resolve;
1216
- let reject;
1217
- const promise = new Promise((res, rej) => {
1218
- resolve = res;
1219
- reject = rej;
1220
- });
1221
- const job = {
1222
- execute,
1223
- resolve,
1224
- reject,
1225
- cancelled: false
1226
- };
1227
- this.queue.push(job);
1228
- this.flush();
1229
- return {
1230
- promise,
1231
- cancel: () => {
1232
- job.cancelled = true;
1233
- job.resolve();
1234
- }
1235
- };
1236
- }
1237
- async flush() {
1238
- if (this.running) return;
1239
- this.running = true;
1240
- while (this.queue.length > 0) {
1241
- const job = this.queue.shift();
1242
- if (job.cancelled) {
1243
- job.resolve();
1244
- continue;
1245
- }
1246
- try {
1247
- await job.execute();
1248
- job.resolve();
1249
- } catch (error) {
1250
- job.reject(error);
1251
- }
1252
- }
1253
- this.running = false;
1254
- }
1255
- };
1256
- var renderQueue = new RenderQueue();
1257
1107
  var useDpr = () => {
1258
1108
  const [dpr, setDPR] = useState(
1259
1109
  typeof window === "undefined" ? 1 : Math.min(window.devicePixelRatio, 2)
@@ -1277,123 +1127,149 @@ var useDpr = () => {
1277
1127
  };
1278
1128
 
1279
1129
  // src/hooks/layers/useCanvasLayer.tsx
1130
+ var CACHE_MAX = 60;
1131
+ var cacheEntries = [];
1132
+ var canvasBitmapCache = /* @__PURE__ */ new WeakMap();
1133
+ function clearBitmapCache(documentId) {
1134
+ if (documentId === void 0) {
1135
+ for (const entry of cacheEntries) {
1136
+ entry.bitmap.close();
1137
+ canvasBitmapCache.get(entry.proxy)?.delete(entry.key);
1138
+ }
1139
+ cacheEntries.length = 0;
1140
+ return;
1141
+ }
1142
+ for (let i = cacheEntries.length - 1; i >= 0; i--) {
1143
+ const entry = cacheEntries[i];
1144
+ if (entry.docId !== documentId) continue;
1145
+ entry.bitmap.close();
1146
+ canvasBitmapCache.get(entry.proxy)?.delete(entry.key);
1147
+ cacheEntries.splice(i, 1);
1148
+ }
1149
+ }
1150
+ function cacheKey(scale, background) {
1151
+ const bg = background ?? "white";
1152
+ let hash = Math.round(scale * 1e4);
1153
+ for (let i = 0; i < bg.length; i++) {
1154
+ hash = hash * 31 + bg.charCodeAt(i) | 0;
1155
+ }
1156
+ return hash;
1157
+ }
1158
+ function getCachedBitmap(proxy, scale, background) {
1159
+ const key = cacheKey(scale, background);
1160
+ const bitmap = canvasBitmapCache.get(proxy)?.get(key);
1161
+ if (!bitmap) return null;
1162
+ const idx = cacheEntries.findIndex((e) => e.proxy === proxy && e.key === key);
1163
+ if (idx !== -1 && idx !== cacheEntries.length - 1) {
1164
+ const [entry] = cacheEntries.splice(idx, 1);
1165
+ cacheEntries.push(entry);
1166
+ }
1167
+ return bitmap;
1168
+ }
1169
+ function setCachedBitmap(docId, proxy, scale, background, bitmap) {
1170
+ const key = cacheKey(scale, background);
1171
+ let map = canvasBitmapCache.get(proxy);
1172
+ if (!map) {
1173
+ map = /* @__PURE__ */ new Map();
1174
+ canvasBitmapCache.set(proxy, map);
1175
+ }
1176
+ const existing = map.get(key);
1177
+ if (existing && existing !== bitmap) {
1178
+ existing.close();
1179
+ const idx = cacheEntries.findIndex(
1180
+ (e) => e.proxy === proxy && e.key === key
1181
+ );
1182
+ if (idx !== -1) cacheEntries.splice(idx, 1);
1183
+ }
1184
+ map.set(key, bitmap);
1185
+ cacheEntries.push({ docId, proxy, key, bitmap });
1186
+ while (cacheEntries.length > CACHE_MAX) {
1187
+ const evicted = cacheEntries.shift();
1188
+ const evictedMap = canvasBitmapCache.get(evicted.proxy);
1189
+ if (evictedMap?.get(evicted.key) === evicted.bitmap) {
1190
+ evictedMap.delete(evicted.key);
1191
+ evicted.bitmap.close();
1192
+ }
1193
+ }
1194
+ }
1280
1195
  var useCanvasLayer = ({ background }) => {
1281
1196
  const canvasRef = useRef(null);
1282
1197
  const pageNumber = usePDFPageNumber();
1283
1198
  const dpr = useDpr();
1284
1199
  const bouncyZoom = usePdf((state) => state.zoom);
1200
+ const docId = usePdf((state) => state.pdfDocumentProxy.fingerprints[0] ?? "");
1285
1201
  const pdfPageProxy = usePdf((state) => state.getPdfPageProxy(pageNumber));
1286
1202
  const markPageRendered = usePdf((state) => state.markPageRendered);
1287
1203
  const unmarkPageRendered = usePdf((state) => state.unmarkPageRendered);
1288
- const documentId = usePdf(
1289
- (state) => state.pdfDocumentProxy.fingerprints[0] ?? "default"
1290
- );
1291
1204
  const [zoom] = useDebounce(bouncyZoom, 100);
1292
- const lastRenderedScaleRef = useRef(0);
1293
- const lastBackgroundRef = useRef(background);
1294
- const lastPageProxyRef = useRef(pdfPageProxy);
1295
- const pageDimsRef = useRef(null);
1296
- if (!pageDimsRef.current || pageDimsRef.current.proxy !== pdfPageProxy) {
1297
- const vp = pdfPageProxy.getViewport({ scale: 1 });
1298
- pageDimsRef.current = {
1299
- width: vp.width,
1300
- height: vp.height,
1301
- proxy: pdfPageProxy
1302
- };
1303
- }
1304
1205
  useLayoutEffect(() => {
1305
- if (!canvasRef.current) {
1306
- return;
1307
- }
1308
- if (lastPageProxyRef.current !== pdfPageProxy || lastBackgroundRef.current !== background) {
1309
- lastPageProxyRef.current = pdfPageProxy;
1310
- lastBackgroundRef.current = background;
1311
- lastRenderedScaleRef.current = 0;
1312
- }
1313
- const { width: pageWidth, height: pageHeight } = pageDimsRef.current;
1314
- const bgColor = background ?? "white";
1206
+ if (!canvasRef.current) return;
1207
+ const baseCanvas = canvasRef.current;
1208
+ const baseViewport = pdfPageProxy.getViewport({ scale: 1 });
1209
+ const pageWidth = baseViewport.width;
1210
+ const pageHeight = baseViewport.height;
1315
1211
  const targetBaseScale = dpr * Math.min(zoom, 1);
1316
1212
  const baseScale = clampScaleForPage(targetBaseScale, pageWidth, pageHeight);
1317
- if (baseScale === lastRenderedScaleRef.current) {
1318
- return;
1319
- }
1320
- const w = Math.floor(pageWidth * baseScale);
1321
- const h = Math.floor(pageHeight * baseScale);
1322
- const cssText = `position:absolute;top:0;left:0;width:${pageWidth}px;height:${pageHeight}px;transform:translate(0px,0px);z-index:0;pointer-events:none;background-color:${bgColor}`;
1323
- const swapToCanvas = (source, sw, sh) => {
1324
- const canvas = canvasRef.current;
1325
- if (!canvas) return;
1326
- canvas.width = sw;
1327
- canvas.height = sh;
1328
- canvas.style.cssText = cssText;
1329
- const ctx = canvas.getContext("2d");
1330
- if (ctx) {
1331
- ctx.drawImage(source, 0, 0);
1332
- }
1333
- lastRenderedScaleRef.current = baseScale;
1334
- };
1335
- const cached = renderCache.get(
1336
- documentId,
1337
- pageNumber,
1338
- baseScale,
1339
- background
1340
- );
1213
+ baseCanvas.width = Math.floor(pageWidth * baseScale);
1214
+ baseCanvas.height = Math.floor(pageHeight * baseScale);
1215
+ baseCanvas.style.position = "absolute";
1216
+ baseCanvas.style.top = "0";
1217
+ baseCanvas.style.left = "0";
1218
+ baseCanvas.style.width = `${pageWidth}px`;
1219
+ baseCanvas.style.height = `${pageHeight}px`;
1220
+ baseCanvas.style.transform = "translate(0px, 0px)";
1221
+ baseCanvas.style.zIndex = "0";
1222
+ baseCanvas.style.pointerEvents = "none";
1223
+ baseCanvas.style.backgroundColor = background ?? "white";
1224
+ baseCanvas.style.visibility = "";
1225
+ const context = baseCanvas.getContext("2d");
1226
+ if (!context) return;
1227
+ const cached = getCachedBitmap(pdfPageProxy, baseScale, background);
1341
1228
  if (cached) {
1342
- swapToCanvas(cached.bitmap, cached.width, cached.height);
1229
+ context.drawImage(cached, 0, 0);
1343
1230
  markPageRendered(pageNumber);
1344
1231
  return;
1345
1232
  }
1233
+ context.setTransform(1, 0, 0, 1, 0, 0);
1234
+ context.clearRect(0, 0, baseCanvas.width, baseCanvas.height);
1235
+ baseCanvas.style.visibility = "hidden";
1346
1236
  let cancelled = false;
1347
- let activeRenderingTask = null;
1348
- const job = renderQueue.enqueue(() => {
1349
- return new Promise((resolve, reject) => {
1350
- if (cancelled || !canvasRef.current) {
1351
- resolve();
1352
- return;
1353
- }
1354
- const buffer = document.createElement("canvas");
1355
- buffer.width = w;
1356
- buffer.height = h;
1357
- const bufferCtx = buffer.getContext("2d");
1358
- if (!bufferCtx) {
1359
- resolve();
1360
- return;
1361
- }
1362
- const viewport = pdfPageProxy.getViewport({ scale: baseScale });
1363
- const renderingTask = pdfPageProxy.render({
1364
- canvas: buffer,
1365
- canvasContext: bufferCtx,
1366
- viewport,
1367
- background
1368
- });
1369
- activeRenderingTask = renderingTask;
1370
- renderingTask.promise.then(() => {
1371
- activeRenderingTask = null;
1372
- if (cancelled || !canvasRef.current) {
1373
- resolve();
1374
- return;
1375
- }
1376
- swapToCanvas(buffer, w, h);
1377
- markPageRendered(pageNumber);
1378
- renderCache.set(documentId, pageNumber, baseScale, buffer, background).finally(() => {
1379
- buffer.width = 0;
1380
- buffer.height = 0;
1381
- });
1382
- resolve();
1383
- }).catch((error) => {
1384
- activeRenderingTask = null;
1385
- if (error.name === "RenderingCancelledException") {
1386
- resolve();
1237
+ const viewport = pdfPageProxy.getViewport({ scale: baseScale });
1238
+ const renderingTask = pdfPageProxy.render({
1239
+ canvas: baseCanvas,
1240
+ canvasContext: context,
1241
+ viewport,
1242
+ background
1243
+ });
1244
+ renderingTask.promise.then(() => {
1245
+ if (cancelled) return;
1246
+ baseCanvas.style.visibility = "";
1247
+ markPageRendered(pageNumber);
1248
+ if (typeof createImageBitmap !== "undefined") {
1249
+ createImageBitmap(baseCanvas).then((bitmap) => {
1250
+ if (cancelled) {
1251
+ bitmap.close();
1387
1252
  return;
1388
1253
  }
1389
- reject(error);
1254
+ setCachedBitmap(
1255
+ docId,
1256
+ pdfPageProxy,
1257
+ baseScale,
1258
+ background,
1259
+ bitmap
1260
+ );
1261
+ }).catch(() => {
1390
1262
  });
1391
- });
1263
+ }
1264
+ }).catch((error) => {
1265
+ if (cancelled) return;
1266
+ if (error?.name === "RenderingCancelledException") return;
1267
+ baseCanvas.style.visibility = "";
1268
+ console.error("PDF render error:", error);
1392
1269
  });
1393
1270
  return () => {
1394
1271
  cancelled = true;
1395
- job.cancel();
1396
- void activeRenderingTask?.cancel();
1272
+ void renderingTask.cancel();
1397
1273
  };
1398
1274
  }, [
1399
1275
  pdfPageProxy,
@@ -1401,16 +1277,16 @@ var useCanvasLayer = ({ background }) => {
1401
1277
  dpr,
1402
1278
  zoom,
1403
1279
  pageNumber,
1404
- documentId,
1405
- markPageRendered
1280
+ markPageRendered,
1281
+ docId
1406
1282
  ]);
1407
1283
  useEffect(() => {
1408
1284
  const canvas = canvasRef.current;
1409
1285
  return () => {
1410
1286
  unmarkPageRendered(pageNumber);
1411
1287
  if (canvas) {
1412
- canvas.width = 1;
1413
- canvas.height = 1;
1288
+ canvas.width = 0;
1289
+ canvas.height = 0;
1414
1290
  }
1415
1291
  };
1416
1292
  }, [pageNumber, unmarkPageRendered]);
@@ -2647,10 +2523,8 @@ var useTextLayer = () => {
2647
2523
  textLayerRef.current.cancel();
2648
2524
  textLayerRef.current = null;
2649
2525
  }
2650
- void loadPdfJs().then(({ TextLayer: TextLayer2 }) => {
2651
- if (isCancelled || textContainerRef.current !== textContainer) {
2652
- return;
2653
- }
2526
+ void import('pdfjs-dist/legacy/build/pdf.mjs').then(({ TextLayer: TextLayer2 }) => {
2527
+ if (isCancelled || textContainerRef.current !== textContainer) return;
2654
2528
  const textLayer = new TextLayer2({
2655
2529
  textContentSource: pdfPageProxy.streamTextContent(),
2656
2530
  container: textContainer,
@@ -2659,8 +2533,7 @@ var useTextLayer = () => {
2659
2533
  textLayerRef.current = textLayer;
2660
2534
  return textLayer.render();
2661
2535
  }).then(() => {
2662
- const textLayer = textLayerRef.current;
2663
- if (!textLayer || isCancelled || textContainerRef.current !== textContainer) {
2536
+ if (isCancelled || textContainerRef.current !== textContainer) {
2664
2537
  return;
2665
2538
  }
2666
2539
  const endOfContent = document.createElement("div");
@@ -2668,7 +2541,7 @@ var useTextLayer = () => {
2668
2541
  textContainer.appendChild(endOfContent);
2669
2542
  bindMouseEvents(textContainer, endOfContent);
2670
2543
  }).catch((error) => {
2671
- if (error.name !== "AbortException") {
2544
+ if (error instanceof Error && error.name !== "AbortException") {
2672
2545
  console.error("TextLayer rendering error:", error);
2673
2546
  }
2674
2547
  }).finally(() => {
@@ -2715,6 +2588,33 @@ var TextLayer = memo(
2715
2588
  }
2716
2589
  );
2717
2590
  TextLayer.displayName = "TextLayer";
2591
+
2592
+ // src/lib/cancellable.ts
2593
+ var cancellable = (promise) => {
2594
+ let isCancelled = false;
2595
+ const wrappedPromise = new Promise((resolve, reject) => {
2596
+ promise.then(
2597
+ (value) => {
2598
+ if (!isCancelled) {
2599
+ resolve(value);
2600
+ }
2601
+ },
2602
+ (error) => {
2603
+ if (!isCancelled) {
2604
+ reject(error);
2605
+ }
2606
+ }
2607
+ );
2608
+ });
2609
+ return {
2610
+ promise: wrappedPromise,
2611
+ cancel() {
2612
+ isCancelled = true;
2613
+ }
2614
+ };
2615
+ };
2616
+
2617
+ // src/hooks/usePdfOutline.tsx
2718
2618
  var usePDFOutline = () => {
2719
2619
  const pdfDocumentProxy = usePdf((state) => state.pdfDocumentProxy);
2720
2620
  const [outline, setOutline] = useState();
@@ -5337,6 +5237,17 @@ var Pages = ({
5337
5237
  }
5338
5238
  );
5339
5239
  };
5240
+
5241
+ // src/lib/pdfjs.ts
5242
+ var pdfJsPromise = null;
5243
+ var loadPdfJs = () => {
5244
+ if (!pdfJsPromise) {
5245
+ pdfJsPromise = import('pdfjs-dist/legacy/build/pdf.mjs');
5246
+ }
5247
+ return pdfJsPromise;
5248
+ };
5249
+
5250
+ // src/hooks/document/document.ts
5340
5251
  function buildDocumentInitParams(source, overrides) {
5341
5252
  let params;
5342
5253
  if (typeof source === "string" || source instanceof URL) {
@@ -5476,11 +5387,11 @@ var Root = forwardRef(
5476
5387
  const linkService = useCreatePDFLinkService(
5477
5388
  initialState?.pdfDocumentProxy ?? null
5478
5389
  );
5479
- const documentId = initialState?.pdfDocumentProxy.fingerprints[0];
5390
+ const documentId = initialState?.pdfDocumentProxy?.fingerprints?.[0];
5480
5391
  useEffect(() => {
5481
5392
  if (!documentId) return;
5482
5393
  return () => {
5483
- renderCache.invalidateDocument(documentId);
5394
+ clearBitmapCache(documentId);
5484
5395
  };
5485
5396
  }, [documentId]);
5486
5397
  return /* @__PURE__ */ jsx(Primitive.div, { ref, ...props, children: initialState ? /* @__PURE__ */ jsx(PDFStore.Provider, { initialValue: initialState, children: /* @__PURE__ */ jsx(PDFLinkServiceContext.Provider, { value: linkService, children }) }) : loader ?? "Loading..." });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anaralabs/lector",
3
- "version": "3.10.2",
3
+ "version": "3.10.3",
4
4
  "description": "A headless PDF viewer for React",
5
5
  "author": "andrewdr (https://github.com/andrewdoro)",
6
6
  "license": "MIT",