@anaralabs/lector 3.10.1 → 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.
- package/dist/_tsup-dts-rollup.d.ts +0 -51
- package/dist/index.js +233 -289
- package/package.json +1 -1
|
@@ -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
|
|
1045
|
-
|
|
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:
|
|
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
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
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
|
-
|
|
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 = 30) {
|
|
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,116 +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
1205
|
useLayoutEffect(() => {
|
|
1296
|
-
if (!canvasRef.current)
|
|
1297
|
-
|
|
1298
|
-
}
|
|
1299
|
-
if (lastPageProxyRef.current !== pdfPageProxy || lastBackgroundRef.current !== background) {
|
|
1300
|
-
lastPageProxyRef.current = pdfPageProxy;
|
|
1301
|
-
lastBackgroundRef.current = background;
|
|
1302
|
-
lastRenderedScaleRef.current = 0;
|
|
1303
|
-
}
|
|
1206
|
+
if (!canvasRef.current) return;
|
|
1207
|
+
const baseCanvas = canvasRef.current;
|
|
1304
1208
|
const baseViewport = pdfPageProxy.getViewport({ scale: 1 });
|
|
1305
1209
|
const pageWidth = baseViewport.width;
|
|
1306
1210
|
const pageHeight = baseViewport.height;
|
|
1307
|
-
const bgColor = background ?? "white";
|
|
1308
1211
|
const targetBaseScale = dpr * Math.min(zoom, 1);
|
|
1309
1212
|
const baseScale = clampScaleForPage(targetBaseScale, pageWidth, pageHeight);
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
}
|
|
1326
|
-
lastRenderedScaleRef.current = baseScale;
|
|
1327
|
-
};
|
|
1328
|
-
const cached = renderCache.get(
|
|
1329
|
-
documentId,
|
|
1330
|
-
pageNumber,
|
|
1331
|
-
baseScale,
|
|
1332
|
-
background
|
|
1333
|
-
);
|
|
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);
|
|
1334
1228
|
if (cached) {
|
|
1335
|
-
|
|
1229
|
+
context.drawImage(cached, 0, 0);
|
|
1336
1230
|
markPageRendered(pageNumber);
|
|
1337
1231
|
return;
|
|
1338
1232
|
}
|
|
1233
|
+
context.setTransform(1, 0, 0, 1, 0, 0);
|
|
1234
|
+
context.clearRect(0, 0, baseCanvas.width, baseCanvas.height);
|
|
1235
|
+
baseCanvas.style.visibility = "hidden";
|
|
1339
1236
|
let cancelled = false;
|
|
1340
|
-
|
|
1341
|
-
const
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
const viewport = pdfPageProxy.getViewport({ scale: baseScale });
|
|
1356
|
-
const renderingTask = pdfPageProxy.render({
|
|
1357
|
-
canvas: buffer,
|
|
1358
|
-
canvasContext: bufferCtx,
|
|
1359
|
-
viewport,
|
|
1360
|
-
background
|
|
1361
|
-
});
|
|
1362
|
-
activeRenderingTask = renderingTask;
|
|
1363
|
-
renderingTask.promise.then(() => {
|
|
1364
|
-
activeRenderingTask = null;
|
|
1365
|
-
if (cancelled || !canvasRef.current) {
|
|
1366
|
-
resolve();
|
|
1367
|
-
return;
|
|
1368
|
-
}
|
|
1369
|
-
swapToCanvas(buffer, w, h);
|
|
1370
|
-
markPageRendered(pageNumber);
|
|
1371
|
-
renderCache.set(documentId, pageNumber, baseScale, buffer, background).finally(() => {
|
|
1372
|
-
buffer.width = 0;
|
|
1373
|
-
buffer.height = 0;
|
|
1374
|
-
});
|
|
1375
|
-
resolve();
|
|
1376
|
-
}).catch((error) => {
|
|
1377
|
-
activeRenderingTask = null;
|
|
1378
|
-
if (error.name === "RenderingCancelledException") {
|
|
1379
|
-
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();
|
|
1380
1252
|
return;
|
|
1381
1253
|
}
|
|
1382
|
-
|
|
1254
|
+
setCachedBitmap(
|
|
1255
|
+
docId,
|
|
1256
|
+
pdfPageProxy,
|
|
1257
|
+
baseScale,
|
|
1258
|
+
background,
|
|
1259
|
+
bitmap
|
|
1260
|
+
);
|
|
1261
|
+
}).catch(() => {
|
|
1383
1262
|
});
|
|
1384
|
-
}
|
|
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);
|
|
1385
1269
|
});
|
|
1386
1270
|
return () => {
|
|
1387
1271
|
cancelled = true;
|
|
1388
|
-
|
|
1389
|
-
void activeRenderingTask?.cancel();
|
|
1272
|
+
void renderingTask.cancel();
|
|
1390
1273
|
};
|
|
1391
1274
|
}, [
|
|
1392
1275
|
pdfPageProxy,
|
|
@@ -1394,16 +1277,16 @@ var useCanvasLayer = ({ background }) => {
|
|
|
1394
1277
|
dpr,
|
|
1395
1278
|
zoom,
|
|
1396
1279
|
pageNumber,
|
|
1397
|
-
|
|
1398
|
-
|
|
1280
|
+
markPageRendered,
|
|
1281
|
+
docId
|
|
1399
1282
|
]);
|
|
1400
1283
|
useEffect(() => {
|
|
1401
1284
|
const canvas = canvasRef.current;
|
|
1402
1285
|
return () => {
|
|
1403
1286
|
unmarkPageRendered(pageNumber);
|
|
1404
1287
|
if (canvas) {
|
|
1405
|
-
canvas.width =
|
|
1406
|
-
canvas.height =
|
|
1288
|
+
canvas.width = 0;
|
|
1289
|
+
canvas.height = 0;
|
|
1407
1290
|
}
|
|
1408
1291
|
};
|
|
1409
1292
|
}, [pageNumber, unmarkPageRendered]);
|
|
@@ -1490,6 +1373,15 @@ var useDetailCanvasLayer = ({
|
|
|
1490
1373
|
const pdfPageProxy = usePdf((state) => state.getPdfPageProxy(pageNumber));
|
|
1491
1374
|
const viewportRef = usePdf((state) => state.viewportRef);
|
|
1492
1375
|
const [zoom] = useDebounce(bouncyZoom, 200);
|
|
1376
|
+
const pageDimsRef = useRef(null);
|
|
1377
|
+
if (!pageDimsRef.current || pageDimsRef.current.proxy !== pdfPageProxy) {
|
|
1378
|
+
const vp = pdfPageProxy.getViewport({ scale: 1 });
|
|
1379
|
+
pageDimsRef.current = {
|
|
1380
|
+
width: vp.width,
|
|
1381
|
+
height: vp.height,
|
|
1382
|
+
proxy: pdfPageProxy
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1493
1385
|
useLayoutEffect(() => {
|
|
1494
1386
|
const scrollContainer = viewportRef?.current;
|
|
1495
1387
|
if (!scrollContainer) {
|
|
@@ -1515,9 +1407,7 @@ var useDetailCanvasLayer = ({
|
|
|
1515
1407
|
hideDetailCanvas();
|
|
1516
1408
|
return;
|
|
1517
1409
|
}
|
|
1518
|
-
const
|
|
1519
|
-
const pageWidth = baseViewport.width;
|
|
1520
|
-
const pageHeight = baseViewport.height;
|
|
1410
|
+
const { width: pageWidth, height: pageHeight } = pageDimsRef.current;
|
|
1521
1411
|
const scrollX = scrollContainer.scrollLeft / zoom;
|
|
1522
1412
|
const scrollY = scrollContainer.scrollTop / zoom;
|
|
1523
1413
|
const viewportWidth = scrollContainer.clientWidth / zoom;
|
|
@@ -2633,10 +2523,8 @@ var useTextLayer = () => {
|
|
|
2633
2523
|
textLayerRef.current.cancel();
|
|
2634
2524
|
textLayerRef.current = null;
|
|
2635
2525
|
}
|
|
2636
|
-
void
|
|
2637
|
-
if (isCancelled || textContainerRef.current !== textContainer)
|
|
2638
|
-
return;
|
|
2639
|
-
}
|
|
2526
|
+
void import('pdfjs-dist/legacy/build/pdf.mjs').then(({ TextLayer: TextLayer2 }) => {
|
|
2527
|
+
if (isCancelled || textContainerRef.current !== textContainer) return;
|
|
2640
2528
|
const textLayer = new TextLayer2({
|
|
2641
2529
|
textContentSource: pdfPageProxy.streamTextContent(),
|
|
2642
2530
|
container: textContainer,
|
|
@@ -2645,8 +2533,7 @@ var useTextLayer = () => {
|
|
|
2645
2533
|
textLayerRef.current = textLayer;
|
|
2646
2534
|
return textLayer.render();
|
|
2647
2535
|
}).then(() => {
|
|
2648
|
-
|
|
2649
|
-
if (!textLayer || isCancelled || textContainerRef.current !== textContainer) {
|
|
2536
|
+
if (isCancelled || textContainerRef.current !== textContainer) {
|
|
2650
2537
|
return;
|
|
2651
2538
|
}
|
|
2652
2539
|
const endOfContent = document.createElement("div");
|
|
@@ -2654,7 +2541,7 @@ var useTextLayer = () => {
|
|
|
2654
2541
|
textContainer.appendChild(endOfContent);
|
|
2655
2542
|
bindMouseEvents(textContainer, endOfContent);
|
|
2656
2543
|
}).catch((error) => {
|
|
2657
|
-
if (error.name !== "AbortException") {
|
|
2544
|
+
if (error instanceof Error && error.name !== "AbortException") {
|
|
2658
2545
|
console.error("TextLayer rendering error:", error);
|
|
2659
2546
|
}
|
|
2660
2547
|
}).finally(() => {
|
|
@@ -2701,6 +2588,33 @@ var TextLayer = memo(
|
|
|
2701
2588
|
}
|
|
2702
2589
|
);
|
|
2703
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
|
|
2704
2618
|
var usePDFOutline = () => {
|
|
2705
2619
|
const pdfDocumentProxy = usePdf((state) => state.pdfDocumentProxy);
|
|
2706
2620
|
const [outline, setOutline] = useState();
|
|
@@ -4930,7 +4844,7 @@ var useViewportContainer = ({
|
|
|
4930
4844
|
elementWrapperRef,
|
|
4931
4845
|
elementRef
|
|
4932
4846
|
}) => {
|
|
4933
|
-
const
|
|
4847
|
+
const originRef = useRef([0, 0]);
|
|
4934
4848
|
const wheelInertia = useRef({
|
|
4935
4849
|
active: false,
|
|
4936
4850
|
lastTime: 0,
|
|
@@ -4950,28 +4864,46 @@ var useViewportContainer = ({
|
|
|
4950
4864
|
translateY: 0,
|
|
4951
4865
|
zoom
|
|
4952
4866
|
});
|
|
4867
|
+
const zoomRafRef = useRef(null);
|
|
4868
|
+
const lastPushedZoomRef = useRef(zoom);
|
|
4953
4869
|
const updateTransform = useCallback(
|
|
4954
4870
|
(zoomUpdate) => {
|
|
4955
4871
|
if (!elementRef.current || !containerRef.current || !elementWrapperRef.current) {
|
|
4956
4872
|
return;
|
|
4957
4873
|
}
|
|
4958
4874
|
const { zoom: zoom2, translateX, translateY } = transformations.current;
|
|
4875
|
+
const naturalWidth = parseFloat(elementRef.current.style.width) || elementRef.current.offsetWidth;
|
|
4876
|
+
const naturalHeight = parseFloat(elementRef.current.style.height) || elementRef.current.offsetHeight;
|
|
4959
4877
|
elementRef.current.style.transform = `scale3d(${zoom2}, ${zoom2}, 1)`;
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
const width = elementBoundingBox.width;
|
|
4963
|
-
elementWrapperRef.current.style.width = `${width}px`;
|
|
4964
|
-
elementWrapperRef.current.style.height = `${elementBoundingBox.height}px`;
|
|
4878
|
+
elementWrapperRef.current.style.width = `${naturalWidth * zoom2}px`;
|
|
4879
|
+
elementWrapperRef.current.style.height = `${naturalHeight * zoom2}px`;
|
|
4965
4880
|
containerRef.current.scrollTop = translateY;
|
|
4966
4881
|
containerRef.current.scrollLeft = translateX;
|
|
4967
|
-
if (zoomUpdate
|
|
4882
|
+
if (zoomUpdate && zoomRafRef.current === null) {
|
|
4883
|
+
zoomRafRef.current = requestAnimationFrame(() => {
|
|
4884
|
+
zoomRafRef.current = null;
|
|
4885
|
+
const z = transformations.current.zoom;
|
|
4886
|
+
lastPushedZoomRef.current = z;
|
|
4887
|
+
updateZoom(() => z);
|
|
4888
|
+
});
|
|
4889
|
+
}
|
|
4968
4890
|
},
|
|
4969
4891
|
[containerRef, elementRef, elementWrapperRef, updateZoom]
|
|
4970
4892
|
);
|
|
4893
|
+
useEffect(() => {
|
|
4894
|
+
return () => {
|
|
4895
|
+
if (zoomRafRef.current !== null) {
|
|
4896
|
+
cancelAnimationFrame(zoomRafRef.current);
|
|
4897
|
+
}
|
|
4898
|
+
};
|
|
4899
|
+
}, []);
|
|
4971
4900
|
useEffect(() => {
|
|
4972
4901
|
if (transformations.current.zoom === zoom || !containerRef.current) {
|
|
4973
4902
|
return;
|
|
4974
4903
|
}
|
|
4904
|
+
if (zoom === lastPushedZoomRef.current) {
|
|
4905
|
+
return;
|
|
4906
|
+
}
|
|
4975
4907
|
const prevZoom = transformations.current.zoom;
|
|
4976
4908
|
if (!prevZoom || !Number.isFinite(prevZoom)) {
|
|
4977
4909
|
transformations.current = {
|
|
@@ -5050,7 +4982,7 @@ var useViewportContainer = ({
|
|
|
5050
4982
|
useGesture(
|
|
5051
4983
|
{
|
|
5052
4984
|
onPinch: (state) => {
|
|
5053
|
-
const { origin
|
|
4985
|
+
const { origin, first, movement, delta, event, memo: memo7 } = state;
|
|
5054
4986
|
const [ms] = movement;
|
|
5055
4987
|
const [deltaScale] = delta;
|
|
5056
4988
|
const currentElement = elementRef.current;
|
|
@@ -5061,17 +4993,17 @@ var useViewportContainer = ({
|
|
|
5061
4993
|
const containerRect = currentContainer.getBoundingClientRect();
|
|
5062
4994
|
const currentZoom = transformations.current.zoom;
|
|
5063
4995
|
const contentPosition = [
|
|
5064
|
-
|
|
5065
|
-
|
|
4996
|
+
origin[0] - elementRect.left,
|
|
4997
|
+
origin[1] - elementRect.top
|
|
5066
4998
|
];
|
|
5067
4999
|
const containerPosition = [
|
|
5068
|
-
|
|
5069
|
-
|
|
5000
|
+
origin[0] - containerRect.left,
|
|
5001
|
+
origin[1] - containerRect.top
|
|
5070
5002
|
];
|
|
5071
|
-
|
|
5003
|
+
originRef.current = [
|
|
5072
5004
|
contentPosition[0] / currentZoom,
|
|
5073
5005
|
contentPosition[1] / currentZoom
|
|
5074
|
-
]
|
|
5006
|
+
];
|
|
5075
5007
|
return {
|
|
5076
5008
|
contentPosition,
|
|
5077
5009
|
containerPosition,
|
|
@@ -5120,7 +5052,7 @@ var useViewportContainer = ({
|
|
|
5120
5052
|
}
|
|
5121
5053
|
);
|
|
5122
5054
|
return {
|
|
5123
|
-
origin
|
|
5055
|
+
origin: originRef.current
|
|
5124
5056
|
};
|
|
5125
5057
|
};
|
|
5126
5058
|
var selectLargestPageWidth = (state) => state.viewports.reduce((max, vp) => Math.max(max, vp.width), 0);
|
|
@@ -5280,6 +5212,7 @@ var Pages = ({
|
|
|
5280
5212
|
alignItems: "center",
|
|
5281
5213
|
flexDirection: "column",
|
|
5282
5214
|
transformOrigin: "0 0",
|
|
5215
|
+
willChange: "transform",
|
|
5283
5216
|
// width: "max-content",
|
|
5284
5217
|
width: largestPageWidth,
|
|
5285
5218
|
margin: "0 auto"
|
|
@@ -5304,6 +5237,17 @@ var Pages = ({
|
|
|
5304
5237
|
}
|
|
5305
5238
|
);
|
|
5306
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
|
|
5307
5251
|
function buildDocumentInitParams(source, overrides) {
|
|
5308
5252
|
let params;
|
|
5309
5253
|
if (typeof source === "string" || source instanceof URL) {
|
|
@@ -5443,11 +5387,11 @@ var Root = forwardRef(
|
|
|
5443
5387
|
const linkService = useCreatePDFLinkService(
|
|
5444
5388
|
initialState?.pdfDocumentProxy ?? null
|
|
5445
5389
|
);
|
|
5446
|
-
const documentId = initialState?.pdfDocumentProxy
|
|
5390
|
+
const documentId = initialState?.pdfDocumentProxy?.fingerprints?.[0];
|
|
5447
5391
|
useEffect(() => {
|
|
5448
5392
|
if (!documentId) return;
|
|
5449
5393
|
return () => {
|
|
5450
|
-
|
|
5394
|
+
clearBitmapCache(documentId);
|
|
5451
5395
|
};
|
|
5452
5396
|
}, [documentId]);
|
|
5453
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..." });
|