pdfjs-reader-core 0.1.5 → 0.2.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.
- package/dist/index.cjs +950 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +408 -6
- package/dist/index.d.ts +408 -6
- package/dist/index.js +929 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -310,6 +310,9 @@ var init_highlight_storage = __esm({
|
|
|
310
310
|
|
|
311
311
|
// src/store/viewer-store.ts
|
|
312
312
|
import { createStore } from "zustand/vanilla";
|
|
313
|
+
function generateRequestId() {
|
|
314
|
+
return `scroll-${Date.now()}-${++requestCounter}`;
|
|
315
|
+
}
|
|
313
316
|
function createViewerStore(initialOverrides = {}) {
|
|
314
317
|
return createStore()((set, get) => ({
|
|
315
318
|
...initialState,
|
|
@@ -362,6 +365,46 @@ function createViewerStore(initialOverrides = {}) {
|
|
|
362
365
|
set({ currentPage: currentPage - 1 });
|
|
363
366
|
}
|
|
364
367
|
},
|
|
368
|
+
// Scroll coordination actions
|
|
369
|
+
requestScrollToPage: (page, behavior = "smooth") => {
|
|
370
|
+
const { numPages } = get();
|
|
371
|
+
const validPage = Math.max(1, Math.min(page, numPages));
|
|
372
|
+
return new Promise((resolve) => {
|
|
373
|
+
const requestId = generateRequestId();
|
|
374
|
+
const timeoutId = setTimeout(() => {
|
|
375
|
+
const callback = scrollCallbacks.get(requestId);
|
|
376
|
+
if (callback) {
|
|
377
|
+
scrollCallbacks.delete(requestId);
|
|
378
|
+
callback.resolve();
|
|
379
|
+
}
|
|
380
|
+
const currentRequest = get().scrollToPageRequest;
|
|
381
|
+
if (currentRequest?.requestId === requestId) {
|
|
382
|
+
set({ scrollToPageRequest: null });
|
|
383
|
+
}
|
|
384
|
+
}, SCROLL_TIMEOUT_MS);
|
|
385
|
+
scrollCallbacks.set(requestId, { resolve, timeoutId });
|
|
386
|
+
set({
|
|
387
|
+
currentPage: validPage,
|
|
388
|
+
scrollToPageRequest: {
|
|
389
|
+
page: validPage,
|
|
390
|
+
requestId,
|
|
391
|
+
behavior
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
},
|
|
396
|
+
completeScrollRequest: (requestId) => {
|
|
397
|
+
const callback = scrollCallbacks.get(requestId);
|
|
398
|
+
if (callback) {
|
|
399
|
+
clearTimeout(callback.timeoutId);
|
|
400
|
+
scrollCallbacks.delete(requestId);
|
|
401
|
+
callback.resolve();
|
|
402
|
+
}
|
|
403
|
+
const currentRequest = get().scrollToPageRequest;
|
|
404
|
+
if (currentRequest?.requestId === requestId) {
|
|
405
|
+
set({ scrollToPageRequest: null });
|
|
406
|
+
}
|
|
407
|
+
},
|
|
365
408
|
// Zoom actions
|
|
366
409
|
setScale: (scale) => {
|
|
367
410
|
const clampedScale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));
|
|
@@ -428,13 +471,16 @@ function createViewerStore(initialOverrides = {}) {
|
|
|
428
471
|
}
|
|
429
472
|
}));
|
|
430
473
|
}
|
|
431
|
-
var ZOOM_LEVELS, MIN_SCALE, MAX_SCALE, initialState;
|
|
474
|
+
var ZOOM_LEVELS, MIN_SCALE, MAX_SCALE, SCROLL_TIMEOUT_MS, scrollCallbacks, requestCounter, initialState;
|
|
432
475
|
var init_viewer_store = __esm({
|
|
433
476
|
"src/store/viewer-store.ts"() {
|
|
434
477
|
"use strict";
|
|
435
478
|
ZOOM_LEVELS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2, 3, 4];
|
|
436
479
|
MIN_SCALE = 0.1;
|
|
437
480
|
MAX_SCALE = 10;
|
|
481
|
+
SCROLL_TIMEOUT_MS = 3e3;
|
|
482
|
+
scrollCallbacks = /* @__PURE__ */ new Map();
|
|
483
|
+
requestCounter = 0;
|
|
438
484
|
initialState = {
|
|
439
485
|
// Document state
|
|
440
486
|
document: null,
|
|
@@ -445,6 +491,8 @@ var init_viewer_store = __esm({
|
|
|
445
491
|
currentPage: 1,
|
|
446
492
|
scale: 1,
|
|
447
493
|
rotation: 0,
|
|
494
|
+
// Scroll coordination
|
|
495
|
+
scrollToPageRequest: null,
|
|
448
496
|
// UI state
|
|
449
497
|
viewMode: "single",
|
|
450
498
|
scrollMode: "single",
|
|
@@ -1253,6 +1301,252 @@ var init_agent_api = __esm({
|
|
|
1253
1301
|
}
|
|
1254
1302
|
});
|
|
1255
1303
|
|
|
1304
|
+
// src/utils/text-search.ts
|
|
1305
|
+
async function extractPageText(document2, pageNumber) {
|
|
1306
|
+
const page = await document2.getPage(pageNumber);
|
|
1307
|
+
const textContent = await page.getTextContent();
|
|
1308
|
+
const viewport = page.getViewport({ scale: 1 });
|
|
1309
|
+
let fullText = "";
|
|
1310
|
+
const charPositions = [];
|
|
1311
|
+
for (const item of textContent.items) {
|
|
1312
|
+
if ("str" in item && item.str) {
|
|
1313
|
+
const tx = item.transform;
|
|
1314
|
+
const x = tx[4];
|
|
1315
|
+
const y = viewport.height - tx[5];
|
|
1316
|
+
const width = item.width ?? 0;
|
|
1317
|
+
const height = item.height ?? 12;
|
|
1318
|
+
const charWidth = item.str.length > 0 ? width / item.str.length : width;
|
|
1319
|
+
for (let i = 0; i < item.str.length; i++) {
|
|
1320
|
+
charPositions.push({
|
|
1321
|
+
char: item.str[i],
|
|
1322
|
+
rect: {
|
|
1323
|
+
x: x + i * charWidth,
|
|
1324
|
+
y: y - height,
|
|
1325
|
+
width: charWidth,
|
|
1326
|
+
height
|
|
1327
|
+
}
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
fullText += item.str;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
return { fullText, charPositions };
|
|
1334
|
+
}
|
|
1335
|
+
async function findTextOnPage(document2, pageNumber, query, options = {}) {
|
|
1336
|
+
const { caseSensitive = false, wholeWord = false } = options;
|
|
1337
|
+
if (!query || pageNumber < 1 || pageNumber > document2.numPages) {
|
|
1338
|
+
return [];
|
|
1339
|
+
}
|
|
1340
|
+
const { fullText, charPositions } = await extractPageText(document2, pageNumber);
|
|
1341
|
+
const matches = [];
|
|
1342
|
+
const searchText = caseSensitive ? query : query.toLowerCase();
|
|
1343
|
+
const textToSearch = caseSensitive ? fullText : fullText.toLowerCase();
|
|
1344
|
+
let startIndex = 0;
|
|
1345
|
+
while (true) {
|
|
1346
|
+
const matchIndex = textToSearch.indexOf(searchText, startIndex);
|
|
1347
|
+
if (matchIndex === -1) break;
|
|
1348
|
+
if (wholeWord) {
|
|
1349
|
+
const beforeChar = matchIndex > 0 ? textToSearch[matchIndex - 1] : " ";
|
|
1350
|
+
const afterChar = matchIndex + query.length < textToSearch.length ? textToSearch[matchIndex + query.length] : " ";
|
|
1351
|
+
if (/\w/.test(beforeChar) || /\w/.test(afterChar)) {
|
|
1352
|
+
startIndex = matchIndex + 1;
|
|
1353
|
+
continue;
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
const matchRects = [];
|
|
1357
|
+
for (let i = matchIndex; i < matchIndex + query.length && i < charPositions.length; i++) {
|
|
1358
|
+
matchRects.push(charPositions[i].rect);
|
|
1359
|
+
}
|
|
1360
|
+
const mergedRects = mergeAdjacentRects(matchRects);
|
|
1361
|
+
matches.push({
|
|
1362
|
+
text: fullText.substring(matchIndex, matchIndex + query.length),
|
|
1363
|
+
rects: mergedRects,
|
|
1364
|
+
pageNumber,
|
|
1365
|
+
startIndex: matchIndex
|
|
1366
|
+
});
|
|
1367
|
+
startIndex = matchIndex + 1;
|
|
1368
|
+
}
|
|
1369
|
+
return matches;
|
|
1370
|
+
}
|
|
1371
|
+
async function findTextInDocument(document2, query, options = {}) {
|
|
1372
|
+
const { pageRange, ...findOptions } = options;
|
|
1373
|
+
const pagesToSearch = pageRange ?? Array.from({ length: document2.numPages }, (_, i) => i + 1);
|
|
1374
|
+
const allMatches = [];
|
|
1375
|
+
for (const pageNum of pagesToSearch) {
|
|
1376
|
+
if (pageNum < 1 || pageNum > document2.numPages) continue;
|
|
1377
|
+
try {
|
|
1378
|
+
const matches = await findTextOnPage(document2, pageNum, query, findOptions);
|
|
1379
|
+
allMatches.push(...matches);
|
|
1380
|
+
} catch {
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
return allMatches;
|
|
1384
|
+
}
|
|
1385
|
+
function mergeAdjacentRects(rects) {
|
|
1386
|
+
if (rects.length === 0) return [];
|
|
1387
|
+
const sorted = [...rects].sort((a, b) => a.y - b.y || a.x - b.x);
|
|
1388
|
+
const merged = [];
|
|
1389
|
+
let current = { ...sorted[0] };
|
|
1390
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
1391
|
+
const rect = sorted[i];
|
|
1392
|
+
if (Math.abs(rect.y - current.y) < 2 && rect.x <= current.x + current.width + 2) {
|
|
1393
|
+
const newRight = Math.max(current.x + current.width, rect.x + rect.width);
|
|
1394
|
+
current.width = newRight - current.x;
|
|
1395
|
+
current.height = Math.max(current.height, rect.height);
|
|
1396
|
+
} else {
|
|
1397
|
+
merged.push(current);
|
|
1398
|
+
current = { ...rect };
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
merged.push(current);
|
|
1402
|
+
return merged;
|
|
1403
|
+
}
|
|
1404
|
+
async function getPageText(document2, pageNumber) {
|
|
1405
|
+
if (pageNumber < 1 || pageNumber > document2.numPages) {
|
|
1406
|
+
return "";
|
|
1407
|
+
}
|
|
1408
|
+
const page = await document2.getPage(pageNumber);
|
|
1409
|
+
const textContent = await page.getTextContent();
|
|
1410
|
+
return textContent.items.filter((item) => "str" in item).map((item) => item.str).join("");
|
|
1411
|
+
}
|
|
1412
|
+
async function countTextOnPage(document2, pageNumber, query, options = {}) {
|
|
1413
|
+
const { caseSensitive = false, wholeWord = false } = options;
|
|
1414
|
+
if (!query || pageNumber < 1 || pageNumber > document2.numPages) {
|
|
1415
|
+
return 0;
|
|
1416
|
+
}
|
|
1417
|
+
const text = await getPageText(document2, pageNumber);
|
|
1418
|
+
const searchText = caseSensitive ? query : query.toLowerCase();
|
|
1419
|
+
const textToSearch = caseSensitive ? text : text.toLowerCase();
|
|
1420
|
+
let count = 0;
|
|
1421
|
+
let startIndex = 0;
|
|
1422
|
+
while (true) {
|
|
1423
|
+
const matchIndex = textToSearch.indexOf(searchText, startIndex);
|
|
1424
|
+
if (matchIndex === -1) break;
|
|
1425
|
+
if (wholeWord) {
|
|
1426
|
+
const beforeChar = matchIndex > 0 ? textToSearch[matchIndex - 1] : " ";
|
|
1427
|
+
const afterChar = matchIndex + query.length < textToSearch.length ? textToSearch[matchIndex + query.length] : " ";
|
|
1428
|
+
if (/\w/.test(beforeChar) || /\w/.test(afterChar)) {
|
|
1429
|
+
startIndex = matchIndex + 1;
|
|
1430
|
+
continue;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
count++;
|
|
1434
|
+
startIndex = matchIndex + 1;
|
|
1435
|
+
}
|
|
1436
|
+
return count;
|
|
1437
|
+
}
|
|
1438
|
+
var init_text_search = __esm({
|
|
1439
|
+
"src/utils/text-search.ts"() {
|
|
1440
|
+
"use strict";
|
|
1441
|
+
}
|
|
1442
|
+
});
|
|
1443
|
+
|
|
1444
|
+
// src/utils/coordinates.ts
|
|
1445
|
+
function pdfToViewport(x, y, scale, pageHeight) {
|
|
1446
|
+
return {
|
|
1447
|
+
x: x * scale,
|
|
1448
|
+
y: (pageHeight - y) * scale
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
function viewportToPDF(x, y, scale, pageHeight) {
|
|
1452
|
+
return {
|
|
1453
|
+
x: x / scale,
|
|
1454
|
+
y: pageHeight - y / scale
|
|
1455
|
+
};
|
|
1456
|
+
}
|
|
1457
|
+
function percentToPDF(xPercent, yPercent, pageWidth, pageHeight) {
|
|
1458
|
+
return {
|
|
1459
|
+
x: xPercent / 100 * pageWidth,
|
|
1460
|
+
y: yPercent / 100 * pageHeight
|
|
1461
|
+
};
|
|
1462
|
+
}
|
|
1463
|
+
function pdfToPercent(x, y, pageWidth, pageHeight) {
|
|
1464
|
+
return {
|
|
1465
|
+
x: x / pageWidth * 100,
|
|
1466
|
+
y: y / pageHeight * 100
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
function percentToViewport(xPercent, yPercent, pageWidth, pageHeight, scale) {
|
|
1470
|
+
return {
|
|
1471
|
+
x: xPercent / 100 * pageWidth * scale,
|
|
1472
|
+
y: yPercent / 100 * pageHeight * scale
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
function viewportToPercent(x, y, pageWidth, pageHeight, scale) {
|
|
1476
|
+
return {
|
|
1477
|
+
x: x / (pageWidth * scale) * 100,
|
|
1478
|
+
y: y / (pageHeight * scale) * 100
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
function applyRotation(x, y, rotation, pageWidth, pageHeight) {
|
|
1482
|
+
const normalizedRotation = (rotation % 360 + 360) % 360;
|
|
1483
|
+
switch (normalizedRotation) {
|
|
1484
|
+
case 90:
|
|
1485
|
+
return { x: y, y: pageWidth - x };
|
|
1486
|
+
case 180:
|
|
1487
|
+
return { x: pageWidth - x, y: pageHeight - y };
|
|
1488
|
+
case 270:
|
|
1489
|
+
return { x: pageHeight - y, y: x };
|
|
1490
|
+
default:
|
|
1491
|
+
return { x, y };
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
function removeRotation(x, y, rotation, pageWidth, pageHeight) {
|
|
1495
|
+
const normalizedRotation = (rotation % 360 + 360) % 360;
|
|
1496
|
+
switch (normalizedRotation) {
|
|
1497
|
+
case 90:
|
|
1498
|
+
return { x: pageWidth - y, y: x };
|
|
1499
|
+
case 180:
|
|
1500
|
+
return { x: pageWidth - x, y: pageHeight - y };
|
|
1501
|
+
case 270:
|
|
1502
|
+
return { x: y, y: pageHeight - x };
|
|
1503
|
+
default:
|
|
1504
|
+
return { x, y };
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
function getRotatedDimensions(width, height, rotation) {
|
|
1508
|
+
const normalizedRotation = (rotation % 360 + 360) % 360;
|
|
1509
|
+
if (normalizedRotation === 90 || normalizedRotation === 270) {
|
|
1510
|
+
return { width: height, height: width };
|
|
1511
|
+
}
|
|
1512
|
+
return { width, height };
|
|
1513
|
+
}
|
|
1514
|
+
function scaleRect(rect, fromScale, toScale) {
|
|
1515
|
+
const ratio = toScale / fromScale;
|
|
1516
|
+
return {
|
|
1517
|
+
x: rect.x * ratio,
|
|
1518
|
+
y: rect.y * ratio,
|
|
1519
|
+
width: rect.width * ratio,
|
|
1520
|
+
height: rect.height * ratio
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1523
|
+
function isPointInRect(point, rect) {
|
|
1524
|
+
return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
|
|
1525
|
+
}
|
|
1526
|
+
function doRectsIntersect(rectA, rectB) {
|
|
1527
|
+
return !(rectA.x + rectA.width < rectB.x || rectB.x + rectB.width < rectA.x || rectA.y + rectA.height < rectB.y || rectB.y + rectB.height < rectA.y);
|
|
1528
|
+
}
|
|
1529
|
+
function getRectIntersection(rectA, rectB) {
|
|
1530
|
+
const x = Math.max(rectA.x, rectB.x);
|
|
1531
|
+
const y = Math.max(rectA.y, rectB.y);
|
|
1532
|
+
const right = Math.min(rectA.x + rectA.width, rectB.x + rectB.width);
|
|
1533
|
+
const bottom = Math.min(rectA.y + rectA.height, rectB.y + rectB.height);
|
|
1534
|
+
if (right <= x || bottom <= y) {
|
|
1535
|
+
return null;
|
|
1536
|
+
}
|
|
1537
|
+
return {
|
|
1538
|
+
x,
|
|
1539
|
+
y,
|
|
1540
|
+
width: right - x,
|
|
1541
|
+
height: bottom - y
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
var init_coordinates = __esm({
|
|
1545
|
+
"src/utils/coordinates.ts"() {
|
|
1546
|
+
"use strict";
|
|
1547
|
+
}
|
|
1548
|
+
});
|
|
1549
|
+
|
|
1256
1550
|
// src/utils/index.ts
|
|
1257
1551
|
var init_utils = __esm({
|
|
1258
1552
|
"src/utils/index.ts"() {
|
|
@@ -1265,6 +1559,8 @@ var init_utils = __esm({
|
|
|
1265
1559
|
init_export_annotations();
|
|
1266
1560
|
init_student_storage();
|
|
1267
1561
|
init_agent_api();
|
|
1562
|
+
init_text_search();
|
|
1563
|
+
init_coordinates();
|
|
1268
1564
|
}
|
|
1269
1565
|
});
|
|
1270
1566
|
|
|
@@ -7889,6 +8185,8 @@ var init_DocumentContainer = __esm({
|
|
|
7889
8185
|
nextPage,
|
|
7890
8186
|
previousPage
|
|
7891
8187
|
} = usePDFViewer();
|
|
8188
|
+
const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
|
|
8189
|
+
const { viewerStore } = usePDFViewerStores();
|
|
7892
8190
|
const [currentPageObj, setCurrentPageObj] = useState18(null);
|
|
7893
8191
|
const [isLoadingPage, setIsLoadingPage] = useState18(false);
|
|
7894
8192
|
const containerRef = useRef16(null);
|
|
@@ -7954,6 +8252,11 @@ var init_DocumentContainer = __esm({
|
|
|
7954
8252
|
const page = await document2.getPage(currentPage);
|
|
7955
8253
|
if (!cancelled && document2 === documentRef.current) {
|
|
7956
8254
|
setCurrentPageObj(page);
|
|
8255
|
+
if (scrollToPageRequest && scrollToPageRequest.page === currentPage) {
|
|
8256
|
+
requestAnimationFrame(() => {
|
|
8257
|
+
viewerStore.getState().completeScrollRequest(scrollToPageRequest.requestId);
|
|
8258
|
+
});
|
|
8259
|
+
}
|
|
7957
8260
|
}
|
|
7958
8261
|
} catch (error) {
|
|
7959
8262
|
if (!cancelled) {
|
|
@@ -7972,7 +8275,7 @@ var init_DocumentContainer = __esm({
|
|
|
7972
8275
|
return () => {
|
|
7973
8276
|
cancelled = true;
|
|
7974
8277
|
};
|
|
7975
|
-
}, [document2, currentPage]);
|
|
8278
|
+
}, [document2, currentPage, scrollToPageRequest, viewerStore]);
|
|
7976
8279
|
const getPageElement = useCallback29(() => {
|
|
7977
8280
|
return containerRef.current?.querySelector(`[data-page-number="${currentPage}"]`);
|
|
7978
8281
|
}, [currentPage]);
|
|
@@ -8114,6 +8417,8 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
8114
8417
|
nextPage,
|
|
8115
8418
|
previousPage
|
|
8116
8419
|
} = usePDFViewer();
|
|
8420
|
+
const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
|
|
8421
|
+
const { viewerStore } = usePDFViewerStores();
|
|
8117
8422
|
const containerRef = useRef17(null);
|
|
8118
8423
|
const scrollContainerRef = useRef17(null);
|
|
8119
8424
|
const documentRef = useRef17(null);
|
|
@@ -8251,6 +8556,45 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
8251
8556
|
loadPages();
|
|
8252
8557
|
}, [document2, visiblePages, pageObjects]);
|
|
8253
8558
|
useEffect20(() => {
|
|
8559
|
+
if (!scrollToPageRequest || !scrollContainerRef.current || pageInfos.length === 0) return;
|
|
8560
|
+
const { page, requestId, behavior } = scrollToPageRequest;
|
|
8561
|
+
const pageInfo = pageInfos.find((p) => p.pageNumber === page);
|
|
8562
|
+
if (!pageInfo) {
|
|
8563
|
+
viewerStore.getState().completeScrollRequest(requestId);
|
|
8564
|
+
return;
|
|
8565
|
+
}
|
|
8566
|
+
const container = scrollContainerRef.current;
|
|
8567
|
+
const targetScroll = pageInfo.top - pageGap;
|
|
8568
|
+
const scrollTop = container.scrollTop;
|
|
8569
|
+
const viewportHeight = container.clientHeight;
|
|
8570
|
+
const isVisible = targetScroll >= scrollTop && pageInfo.top + pageInfo.height <= scrollTop + viewportHeight;
|
|
8571
|
+
if (isVisible) {
|
|
8572
|
+
viewerStore.getState().completeScrollRequest(requestId);
|
|
8573
|
+
return;
|
|
8574
|
+
}
|
|
8575
|
+
container.scrollTo({
|
|
8576
|
+
top: targetScroll,
|
|
8577
|
+
behavior
|
|
8578
|
+
});
|
|
8579
|
+
if (behavior === "instant") {
|
|
8580
|
+
requestAnimationFrame(() => {
|
|
8581
|
+
viewerStore.getState().completeScrollRequest(requestId);
|
|
8582
|
+
});
|
|
8583
|
+
} else {
|
|
8584
|
+
let scrollEndTimeout;
|
|
8585
|
+
const handleScrollEnd = () => {
|
|
8586
|
+
clearTimeout(scrollEndTimeout);
|
|
8587
|
+
scrollEndTimeout = setTimeout(() => {
|
|
8588
|
+
container.removeEventListener("scroll", handleScrollEnd);
|
|
8589
|
+
viewerStore.getState().completeScrollRequest(requestId);
|
|
8590
|
+
}, 100);
|
|
8591
|
+
};
|
|
8592
|
+
container.addEventListener("scroll", handleScrollEnd, { passive: true });
|
|
8593
|
+
handleScrollEnd();
|
|
8594
|
+
}
|
|
8595
|
+
}, [scrollToPageRequest, pageInfos, pageGap, viewerStore]);
|
|
8596
|
+
useEffect20(() => {
|
|
8597
|
+
if (scrollToPageRequest) return;
|
|
8254
8598
|
if (!scrollContainerRef.current || pageInfos.length === 0) return;
|
|
8255
8599
|
const pageInfo = pageInfos.find((p) => p.pageNumber === currentPage);
|
|
8256
8600
|
if (pageInfo) {
|
|
@@ -8265,7 +8609,7 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
8265
8609
|
});
|
|
8266
8610
|
}
|
|
8267
8611
|
}
|
|
8268
|
-
}, [currentPage, pageInfos, pageGap]);
|
|
8612
|
+
}, [currentPage, pageInfos, pageGap, scrollToPageRequest]);
|
|
8269
8613
|
const handlePinchZoom = useCallback30(
|
|
8270
8614
|
(pinchScale) => {
|
|
8271
8615
|
const newScale = Math.max(0.25, Math.min(4, baseScaleRef.current * pinchScale));
|
|
@@ -8472,6 +8816,8 @@ var init_DualPageContainer = __esm({
|
|
|
8472
8816
|
setScale,
|
|
8473
8817
|
goToPage
|
|
8474
8818
|
} = usePDFViewer();
|
|
8819
|
+
const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
|
|
8820
|
+
const { viewerStore } = usePDFViewerStores();
|
|
8475
8821
|
const containerRef = useRef18(null);
|
|
8476
8822
|
const documentRef = useRef18(null);
|
|
8477
8823
|
const baseScaleRef = useRef18(scale);
|
|
@@ -8557,6 +8903,14 @@ var init_DualPageContainer = __esm({
|
|
|
8557
8903
|
if (!cancelled) {
|
|
8558
8904
|
setLeftPage(left);
|
|
8559
8905
|
setRightPage(right);
|
|
8906
|
+
if (scrollToPageRequest) {
|
|
8907
|
+
const requestedPage = scrollToPageRequest.page;
|
|
8908
|
+
if (requestedPage === spread2.left || requestedPage === spread2.right) {
|
|
8909
|
+
requestAnimationFrame(() => {
|
|
8910
|
+
viewerStore.getState().completeScrollRequest(scrollToPageRequest.requestId);
|
|
8911
|
+
});
|
|
8912
|
+
}
|
|
8913
|
+
}
|
|
8560
8914
|
}
|
|
8561
8915
|
} catch (error) {
|
|
8562
8916
|
if (!cancelled) {
|
|
@@ -8572,7 +8926,7 @@ var init_DualPageContainer = __esm({
|
|
|
8572
8926
|
return () => {
|
|
8573
8927
|
cancelled = true;
|
|
8574
8928
|
};
|
|
8575
|
-
}, [document2, currentPage, getSpreadPages]);
|
|
8929
|
+
}, [document2, currentPage, getSpreadPages, scrollToPageRequest, viewerStore]);
|
|
8576
8930
|
const goToPreviousSpread = useCallback31(() => {
|
|
8577
8931
|
const spread2 = getSpreadPages(currentPage);
|
|
8578
8932
|
const leftmostPage = spread2.left || spread2.right || currentPage;
|
|
@@ -8769,10 +9123,14 @@ var init_FloatingZoomControls = __esm({
|
|
|
8769
9123
|
const scale = useViewerStore((s) => s.scale);
|
|
8770
9124
|
const document2 = useViewerStore((s) => s.document);
|
|
8771
9125
|
const handleZoomIn = useCallback32(() => {
|
|
8772
|
-
viewerStore.getState().
|
|
9126
|
+
const currentScale = viewerStore.getState().scale;
|
|
9127
|
+
const newScale = Math.min(4, currentScale + 0.05);
|
|
9128
|
+
viewerStore.getState().setScale(newScale);
|
|
8773
9129
|
}, [viewerStore]);
|
|
8774
9130
|
const handleZoomOut = useCallback32(() => {
|
|
8775
|
-
viewerStore.getState().
|
|
9131
|
+
const currentScale = viewerStore.getState().scale;
|
|
9132
|
+
const newScale = Math.max(0.1, currentScale - 0.05);
|
|
9133
|
+
viewerStore.getState().setScale(newScale);
|
|
8776
9134
|
}, [viewerStore]);
|
|
8777
9135
|
const handleFitToWidth = useCallback32(() => {
|
|
8778
9136
|
viewerStore.getState().setScale(1);
|
|
@@ -8945,6 +9303,7 @@ var init_PDFViewerClient = __esm({
|
|
|
8945
9303
|
PDFViewerInner = memo25(function PDFViewerInner2({
|
|
8946
9304
|
src,
|
|
8947
9305
|
initialPage = 1,
|
|
9306
|
+
page: controlledPage,
|
|
8948
9307
|
initialScale = "auto",
|
|
8949
9308
|
showToolbar = true,
|
|
8950
9309
|
showSidebar = true,
|
|
@@ -8954,9 +9313,17 @@ var init_PDFViewerClient = __esm({
|
|
|
8954
9313
|
onDocumentLoad,
|
|
8955
9314
|
onPageChange,
|
|
8956
9315
|
onScaleChange,
|
|
9316
|
+
onZoomChange,
|
|
8957
9317
|
onError,
|
|
9318
|
+
onPageRenderStart,
|
|
9319
|
+
onPageRenderComplete,
|
|
9320
|
+
onHighlightAdded,
|
|
9321
|
+
onHighlightRemoved,
|
|
9322
|
+
onAnnotationAdded,
|
|
8958
9323
|
workerSrc,
|
|
8959
9324
|
className,
|
|
9325
|
+
loadingComponent,
|
|
9326
|
+
errorComponent,
|
|
8960
9327
|
onReady
|
|
8961
9328
|
}) {
|
|
8962
9329
|
const { viewerStore, annotationStore, searchStore } = usePDFViewerStores();
|
|
@@ -8966,12 +9333,26 @@ var init_PDFViewerClient = __esm({
|
|
|
8966
9333
|
const onErrorRef = useRef19(onError);
|
|
8967
9334
|
const onPageChangeRef = useRef19(onPageChange);
|
|
8968
9335
|
const onScaleChangeRef = useRef19(onScaleChange);
|
|
9336
|
+
const onZoomChangeRef = useRef19(onZoomChange);
|
|
9337
|
+
const onPageRenderStartRef = useRef19(onPageRenderStart);
|
|
9338
|
+
const onPageRenderCompleteRef = useRef19(onPageRenderComplete);
|
|
9339
|
+
const onHighlightAddedRef = useRef19(onHighlightAdded);
|
|
9340
|
+
const onHighlightRemovedRef = useRef19(onHighlightRemoved);
|
|
9341
|
+
const onAnnotationAddedRef = useRef19(onAnnotationAdded);
|
|
8969
9342
|
const onReadyRef = useRef19(onReady);
|
|
8970
9343
|
onDocumentLoadRef.current = onDocumentLoad;
|
|
8971
9344
|
onErrorRef.current = onError;
|
|
8972
9345
|
onPageChangeRef.current = onPageChange;
|
|
8973
9346
|
onScaleChangeRef.current = onScaleChange;
|
|
9347
|
+
onZoomChangeRef.current = onZoomChange;
|
|
9348
|
+
onPageRenderStartRef.current = onPageRenderStart;
|
|
9349
|
+
onPageRenderCompleteRef.current = onPageRenderComplete;
|
|
9350
|
+
onHighlightAddedRef.current = onHighlightAdded;
|
|
9351
|
+
onHighlightRemovedRef.current = onHighlightRemoved;
|
|
9352
|
+
onAnnotationAddedRef.current = onAnnotationAdded;
|
|
8974
9353
|
onReadyRef.current = onReady;
|
|
9354
|
+
const isControlled = controlledPage !== void 0;
|
|
9355
|
+
const prevControlledPageRef = useRef19(controlledPage);
|
|
8975
9356
|
const srcIdRef = useRef19(null);
|
|
8976
9357
|
const currentPage = useViewerStore((s) => s.currentPage);
|
|
8977
9358
|
const scale = useViewerStore((s) => s.scale);
|
|
@@ -9112,8 +9493,9 @@ var init_PDFViewerClient = __esm({
|
|
|
9112
9493
|
}
|
|
9113
9494
|
},
|
|
9114
9495
|
// ==================== Navigation ====================
|
|
9115
|
-
goToPage: (page) => {
|
|
9116
|
-
|
|
9496
|
+
goToPage: async (page, options) => {
|
|
9497
|
+
const behavior = options?.behavior ?? "smooth";
|
|
9498
|
+
await viewerStore.getState().requestScrollToPage(page, behavior);
|
|
9117
9499
|
},
|
|
9118
9500
|
nextPage: () => {
|
|
9119
9501
|
viewerStore.getState().nextPage();
|
|
@@ -9173,6 +9555,246 @@ var init_PDFViewerClient = __esm({
|
|
|
9173
9555
|
clearSearch: () => {
|
|
9174
9556
|
searchStore.getState().clearSearch();
|
|
9175
9557
|
},
|
|
9558
|
+
// ==================== Combined Search & Highlight ====================
|
|
9559
|
+
searchAndHighlight: async (query, options) => {
|
|
9560
|
+
const doc = viewerStore.getState().document;
|
|
9561
|
+
if (!doc) {
|
|
9562
|
+
return { matchCount: 0, highlightIds: [], matches: [] };
|
|
9563
|
+
}
|
|
9564
|
+
const color = options?.color ?? "yellow";
|
|
9565
|
+
const caseSensitive = options?.caseSensitive ?? false;
|
|
9566
|
+
const wholeWord = options?.wholeWord ?? false;
|
|
9567
|
+
const scrollToFirst = options?.scrollToFirst ?? true;
|
|
9568
|
+
const clearPrevious = options?.clearPrevious ?? true;
|
|
9569
|
+
if (clearPrevious) {
|
|
9570
|
+
const existingHighlights = annotationStore.getState().highlights;
|
|
9571
|
+
for (const h of existingHighlights) {
|
|
9572
|
+
if (h.source === "search") {
|
|
9573
|
+
annotationStore.getState().removeHighlight(h.id);
|
|
9574
|
+
}
|
|
9575
|
+
}
|
|
9576
|
+
}
|
|
9577
|
+
let pagesToSearch;
|
|
9578
|
+
if (options?.pageRange) {
|
|
9579
|
+
if (Array.isArray(options.pageRange)) {
|
|
9580
|
+
pagesToSearch = options.pageRange;
|
|
9581
|
+
} else {
|
|
9582
|
+
const { start, end } = options.pageRange;
|
|
9583
|
+
pagesToSearch = Array.from({ length: end - start + 1 }, (_, i) => start + i);
|
|
9584
|
+
}
|
|
9585
|
+
} else {
|
|
9586
|
+
pagesToSearch = Array.from({ length: doc.numPages }, (_, i) => i + 1);
|
|
9587
|
+
}
|
|
9588
|
+
const result = {
|
|
9589
|
+
matchCount: 0,
|
|
9590
|
+
highlightIds: [],
|
|
9591
|
+
matches: []
|
|
9592
|
+
};
|
|
9593
|
+
const searchText = caseSensitive ? query : query.toLowerCase();
|
|
9594
|
+
for (const pageNum of pagesToSearch) {
|
|
9595
|
+
if (pageNum < 1 || pageNum > doc.numPages) continue;
|
|
9596
|
+
try {
|
|
9597
|
+
const page = await doc.getPage(pageNum);
|
|
9598
|
+
const textContent = await page.getTextContent();
|
|
9599
|
+
const viewport = page.getViewport({ scale: 1 });
|
|
9600
|
+
let fullText = "";
|
|
9601
|
+
const charPositions = [];
|
|
9602
|
+
for (const item of textContent.items) {
|
|
9603
|
+
if ("str" in item && item.str) {
|
|
9604
|
+
const tx = item.transform;
|
|
9605
|
+
const x = tx[4];
|
|
9606
|
+
const y = viewport.height - tx[5];
|
|
9607
|
+
const width = item.width ?? 0;
|
|
9608
|
+
const height = item.height ?? 12;
|
|
9609
|
+
const charWidth = item.str.length > 0 ? width / item.str.length : width;
|
|
9610
|
+
for (let i = 0; i < item.str.length; i++) {
|
|
9611
|
+
charPositions.push({
|
|
9612
|
+
char: item.str[i],
|
|
9613
|
+
rect: {
|
|
9614
|
+
x: x + i * charWidth,
|
|
9615
|
+
y: y - height,
|
|
9616
|
+
width: charWidth,
|
|
9617
|
+
height
|
|
9618
|
+
}
|
|
9619
|
+
});
|
|
9620
|
+
}
|
|
9621
|
+
fullText += item.str;
|
|
9622
|
+
}
|
|
9623
|
+
}
|
|
9624
|
+
const textToSearch = caseSensitive ? fullText : fullText.toLowerCase();
|
|
9625
|
+
let startIndex = 0;
|
|
9626
|
+
while (true) {
|
|
9627
|
+
let matchIndex = textToSearch.indexOf(searchText, startIndex);
|
|
9628
|
+
if (matchIndex === -1) break;
|
|
9629
|
+
if (wholeWord) {
|
|
9630
|
+
const beforeChar = matchIndex > 0 ? textToSearch[matchIndex - 1] : " ";
|
|
9631
|
+
const afterChar = matchIndex + query.length < textToSearch.length ? textToSearch[matchIndex + query.length] : " ";
|
|
9632
|
+
if (/\w/.test(beforeChar) || /\w/.test(afterChar)) {
|
|
9633
|
+
startIndex = matchIndex + 1;
|
|
9634
|
+
continue;
|
|
9635
|
+
}
|
|
9636
|
+
}
|
|
9637
|
+
const matchRects = [];
|
|
9638
|
+
for (let i = matchIndex; i < matchIndex + query.length && i < charPositions.length; i++) {
|
|
9639
|
+
matchRects.push(charPositions[i].rect);
|
|
9640
|
+
}
|
|
9641
|
+
const mergedRects = mergeRects2(matchRects);
|
|
9642
|
+
const highlight = annotationStore.getState().addHighlight({
|
|
9643
|
+
pageNumber: pageNum,
|
|
9644
|
+
rects: mergedRects,
|
|
9645
|
+
color,
|
|
9646
|
+
text: fullText.substring(matchIndex, matchIndex + query.length),
|
|
9647
|
+
source: "search"
|
|
9648
|
+
});
|
|
9649
|
+
result.matchCount++;
|
|
9650
|
+
result.highlightIds.push(highlight.id);
|
|
9651
|
+
result.matches.push({
|
|
9652
|
+
pageNumber: pageNum,
|
|
9653
|
+
text: fullText.substring(matchIndex, matchIndex + query.length),
|
|
9654
|
+
highlightId: highlight.id,
|
|
9655
|
+
rects: mergedRects
|
|
9656
|
+
});
|
|
9657
|
+
startIndex = matchIndex + 1;
|
|
9658
|
+
}
|
|
9659
|
+
} catch {
|
|
9660
|
+
}
|
|
9661
|
+
}
|
|
9662
|
+
if (scrollToFirst && result.matches.length > 0) {
|
|
9663
|
+
const firstMatch = result.matches[0];
|
|
9664
|
+
await viewerStore.getState().requestScrollToPage(firstMatch.pageNumber, "smooth");
|
|
9665
|
+
}
|
|
9666
|
+
return result;
|
|
9667
|
+
},
|
|
9668
|
+
// ==================== Agent Tools ====================
|
|
9669
|
+
agentTools: {
|
|
9670
|
+
navigateToPage: async (page) => {
|
|
9671
|
+
try {
|
|
9672
|
+
const { currentPage: currentPage2, numPages } = viewerStore.getState();
|
|
9673
|
+
if (numPages === 0) {
|
|
9674
|
+
return {
|
|
9675
|
+
success: false,
|
|
9676
|
+
error: { code: "NO_DOCUMENT", message: "No document is loaded" }
|
|
9677
|
+
};
|
|
9678
|
+
}
|
|
9679
|
+
if (page < 1 || page > numPages) {
|
|
9680
|
+
return {
|
|
9681
|
+
success: false,
|
|
9682
|
+
error: { code: "INVALID_PAGE", message: `Page ${page} is out of range (1-${numPages})` }
|
|
9683
|
+
};
|
|
9684
|
+
}
|
|
9685
|
+
const previousPage = currentPage2;
|
|
9686
|
+
await viewerStore.getState().requestScrollToPage(page, "smooth");
|
|
9687
|
+
return {
|
|
9688
|
+
success: true,
|
|
9689
|
+
data: { previousPage, currentPage: page }
|
|
9690
|
+
};
|
|
9691
|
+
} catch (err) {
|
|
9692
|
+
return {
|
|
9693
|
+
success: false,
|
|
9694
|
+
error: { code: "NAVIGATION_FAILED", message: err instanceof Error ? err.message : "Unknown error" }
|
|
9695
|
+
};
|
|
9696
|
+
}
|
|
9697
|
+
},
|
|
9698
|
+
highlightText: async (text, options) => {
|
|
9699
|
+
try {
|
|
9700
|
+
const highlightIds = await handle.highlightText(text, options);
|
|
9701
|
+
return {
|
|
9702
|
+
success: true,
|
|
9703
|
+
data: { matchCount: highlightIds.length, highlightIds }
|
|
9704
|
+
};
|
|
9705
|
+
} catch (err) {
|
|
9706
|
+
return {
|
|
9707
|
+
success: false,
|
|
9708
|
+
error: { code: "HIGHLIGHT_FAILED", message: err instanceof Error ? err.message : "Unknown error" }
|
|
9709
|
+
};
|
|
9710
|
+
}
|
|
9711
|
+
},
|
|
9712
|
+
getPageContent: async (page) => {
|
|
9713
|
+
try {
|
|
9714
|
+
const doc = viewerStore.getState().document;
|
|
9715
|
+
if (!doc) {
|
|
9716
|
+
return {
|
|
9717
|
+
success: false,
|
|
9718
|
+
error: { code: "NO_DOCUMENT", message: "No document is loaded" }
|
|
9719
|
+
};
|
|
9720
|
+
}
|
|
9721
|
+
if (page < 1 || page > doc.numPages) {
|
|
9722
|
+
return {
|
|
9723
|
+
success: false,
|
|
9724
|
+
error: { code: "INVALID_PAGE", message: `Page ${page} is out of range (1-${doc.numPages})` }
|
|
9725
|
+
};
|
|
9726
|
+
}
|
|
9727
|
+
const pageObj = await doc.getPage(page);
|
|
9728
|
+
const textContent = await pageObj.getTextContent();
|
|
9729
|
+
const text = textContent.items.filter((item) => "str" in item).map((item) => item.str).join("");
|
|
9730
|
+
return {
|
|
9731
|
+
success: true,
|
|
9732
|
+
data: { text }
|
|
9733
|
+
};
|
|
9734
|
+
} catch (err) {
|
|
9735
|
+
return {
|
|
9736
|
+
success: false,
|
|
9737
|
+
error: { code: "CONTENT_FETCH_FAILED", message: err instanceof Error ? err.message : "Unknown error" }
|
|
9738
|
+
};
|
|
9739
|
+
}
|
|
9740
|
+
},
|
|
9741
|
+
clearAllVisuals: async () => {
|
|
9742
|
+
try {
|
|
9743
|
+
const highlights = annotationStore.getState().highlights;
|
|
9744
|
+
for (const h of highlights) {
|
|
9745
|
+
annotationStore.getState().removeHighlight(h.id);
|
|
9746
|
+
}
|
|
9747
|
+
const annotations = annotationStore.getState().annotations;
|
|
9748
|
+
for (const a of annotations) {
|
|
9749
|
+
annotationStore.getState().removeAnnotation(a.id);
|
|
9750
|
+
}
|
|
9751
|
+
return { success: true };
|
|
9752
|
+
} catch (err) {
|
|
9753
|
+
return {
|
|
9754
|
+
success: false,
|
|
9755
|
+
error: { code: "CLEAR_FAILED", message: err instanceof Error ? err.message : "Unknown error" }
|
|
9756
|
+
};
|
|
9757
|
+
}
|
|
9758
|
+
}
|
|
9759
|
+
},
|
|
9760
|
+
// ==================== Coordinate Helpers ====================
|
|
9761
|
+
coordinates: {
|
|
9762
|
+
getPageDimensions: (page) => {
|
|
9763
|
+
const doc = viewerStore.getState().document;
|
|
9764
|
+
if (!doc || page < 1 || page > doc.numPages) {
|
|
9765
|
+
return null;
|
|
9766
|
+
}
|
|
9767
|
+
try {
|
|
9768
|
+
return {
|
|
9769
|
+
width: 612,
|
|
9770
|
+
// Default US Letter width
|
|
9771
|
+
height: 792,
|
|
9772
|
+
// Default US Letter height
|
|
9773
|
+
rotation: viewerStore.getState().rotation
|
|
9774
|
+
};
|
|
9775
|
+
} catch {
|
|
9776
|
+
return null;
|
|
9777
|
+
}
|
|
9778
|
+
},
|
|
9779
|
+
percentToPixels: (xPercent, yPercent, page) => {
|
|
9780
|
+
const dimensions = handle.coordinates.getPageDimensions(page);
|
|
9781
|
+
if (!dimensions) return null;
|
|
9782
|
+
const scale2 = viewerStore.getState().scale;
|
|
9783
|
+
return {
|
|
9784
|
+
x: xPercent / 100 * dimensions.width * scale2,
|
|
9785
|
+
y: yPercent / 100 * dimensions.height * scale2
|
|
9786
|
+
};
|
|
9787
|
+
},
|
|
9788
|
+
pixelsToPercent: (x, y, page) => {
|
|
9789
|
+
const dimensions = handle.coordinates.getPageDimensions(page);
|
|
9790
|
+
if (!dimensions) return null;
|
|
9791
|
+
const scale2 = viewerStore.getState().scale;
|
|
9792
|
+
return {
|
|
9793
|
+
x: x / (dimensions.width * scale2) * 100,
|
|
9794
|
+
y: y / (dimensions.height * scale2) * 100
|
|
9795
|
+
};
|
|
9796
|
+
}
|
|
9797
|
+
},
|
|
9176
9798
|
// ==================== Document ====================
|
|
9177
9799
|
getDocument: () => {
|
|
9178
9800
|
return viewerStore.getState().document;
|
|
@@ -9259,10 +9881,36 @@ var init_PDFViewerClient = __esm({
|
|
|
9259
9881
|
if (prevScaleRef.current !== scale) {
|
|
9260
9882
|
prevScaleRef.current = scale;
|
|
9261
9883
|
onScaleChangeRef.current?.(scale);
|
|
9884
|
+
onZoomChangeRef.current?.(scale);
|
|
9262
9885
|
}
|
|
9263
9886
|
}, [scale]);
|
|
9887
|
+
useEffect22(() => {
|
|
9888
|
+
if (!isControlled || controlledPage === void 0) return;
|
|
9889
|
+
if (prevControlledPageRef.current === controlledPage) return;
|
|
9890
|
+
prevControlledPageRef.current = controlledPage;
|
|
9891
|
+
const { numPages, currentPage: currentPage2 } = viewerStore.getState();
|
|
9892
|
+
if (numPages > 0 && controlledPage !== currentPage2) {
|
|
9893
|
+
viewerStore.getState().requestScrollToPage(controlledPage, "smooth");
|
|
9894
|
+
}
|
|
9895
|
+
}, [controlledPage, isControlled, viewerStore]);
|
|
9264
9896
|
const themeClass = theme === "dark" ? "dark" : "";
|
|
9265
9897
|
if (error) {
|
|
9898
|
+
if (errorComponent) {
|
|
9899
|
+
const errorContent = typeof errorComponent === "function" ? errorComponent(error, handleRetry) : errorComponent;
|
|
9900
|
+
return /* @__PURE__ */ jsx26(
|
|
9901
|
+
"div",
|
|
9902
|
+
{
|
|
9903
|
+
className: cn(
|
|
9904
|
+
"pdf-viewer pdf-viewer-error",
|
|
9905
|
+
"flex flex-col h-full",
|
|
9906
|
+
"bg-white dark:bg-gray-900",
|
|
9907
|
+
themeClass,
|
|
9908
|
+
className
|
|
9909
|
+
),
|
|
9910
|
+
children: errorContent
|
|
9911
|
+
}
|
|
9912
|
+
);
|
|
9913
|
+
}
|
|
9266
9914
|
return /* @__PURE__ */ jsx26(
|
|
9267
9915
|
"div",
|
|
9268
9916
|
{
|
|
@@ -9318,7 +9966,7 @@ var init_PDFViewerClient = __esm({
|
|
|
9318
9966
|
renderContainer()
|
|
9319
9967
|
] }),
|
|
9320
9968
|
showFloatingZoom && /* @__PURE__ */ jsx26(FloatingZoomControls, { position: "bottom-right" }),
|
|
9321
|
-
isLoading && /* @__PURE__ */ jsx26("div", { className: "absolute inset-0 flex items-center justify-center bg-white/80 dark:bg-gray-900/80", children: /* @__PURE__ */ jsxs22("div", { className: "flex flex-col items-center", children: [
|
|
9969
|
+
isLoading && /* @__PURE__ */ jsx26("div", { className: "absolute inset-0 flex items-center justify-center bg-white/80 dark:bg-gray-900/80", children: loadingComponent ?? /* @__PURE__ */ jsxs22("div", { className: "flex flex-col items-center", children: [
|
|
9322
9970
|
/* @__PURE__ */ jsx26("div", { className: "w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" }),
|
|
9323
9971
|
/* @__PURE__ */ jsx26("div", { className: "mt-2 text-sm text-gray-500", children: "Loading PDF..." })
|
|
9324
9972
|
] }) })
|
|
@@ -10692,10 +11340,247 @@ var Minimap = memo34(function Minimap2({
|
|
|
10692
11340
|
// src/components/index.ts
|
|
10693
11341
|
init_FloatingZoomControls2();
|
|
10694
11342
|
|
|
11343
|
+
// src/components/PDFThumbnailNav/PDFThumbnailNav.tsx
|
|
11344
|
+
init_hooks();
|
|
11345
|
+
init_utils();
|
|
11346
|
+
import { memo as memo35, useEffect as useEffect26, useState as useState28, useRef as useRef25, useCallback as useCallback41 } from "react";
|
|
11347
|
+
import { jsx as jsx36, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
11348
|
+
var DEFAULT_WIDTH = 612;
|
|
11349
|
+
var DEFAULT_HEIGHT = 792;
|
|
11350
|
+
var PDFThumbnailNav = memo35(function PDFThumbnailNav2({
|
|
11351
|
+
thumbnailScale = 0.15,
|
|
11352
|
+
orientation = "vertical",
|
|
11353
|
+
maxVisible = 10,
|
|
11354
|
+
className,
|
|
11355
|
+
onThumbnailClick,
|
|
11356
|
+
gap = 8,
|
|
11357
|
+
showPageNumbers = true
|
|
11358
|
+
}) {
|
|
11359
|
+
const { document: document2, numPages, currentPage } = usePDFViewer();
|
|
11360
|
+
const { viewerStore } = usePDFViewerStores();
|
|
11361
|
+
const containerRef = useRef25(null);
|
|
11362
|
+
const [thumbnails, setThumbnails] = useState28(/* @__PURE__ */ new Map());
|
|
11363
|
+
const [visibleRange, setVisibleRange] = useState28({ start: 1, end: maxVisible });
|
|
11364
|
+
const renderQueueRef = useRef25(/* @__PURE__ */ new Set());
|
|
11365
|
+
const pageCache = useRef25(/* @__PURE__ */ new Map());
|
|
11366
|
+
const thumbnailWidth = Math.floor(DEFAULT_WIDTH * thumbnailScale);
|
|
11367
|
+
const thumbnailHeight = Math.floor(DEFAULT_HEIGHT * thumbnailScale);
|
|
11368
|
+
const updateVisibleRange = useCallback41(() => {
|
|
11369
|
+
if (!containerRef.current || numPages === 0) return;
|
|
11370
|
+
const container = containerRef.current;
|
|
11371
|
+
const isHorizontal2 = orientation === "horizontal";
|
|
11372
|
+
const scrollPosition = isHorizontal2 ? container.scrollLeft : container.scrollTop;
|
|
11373
|
+
const viewportSize = isHorizontal2 ? container.clientWidth : container.clientHeight;
|
|
11374
|
+
const itemSize = (isHorizontal2 ? thumbnailWidth : thumbnailHeight) + gap;
|
|
11375
|
+
const firstVisible = Math.max(1, Math.floor(scrollPosition / itemSize) + 1);
|
|
11376
|
+
const visibleCount = Math.ceil(viewportSize / itemSize) + 2;
|
|
11377
|
+
const lastVisible = Math.min(numPages, firstVisible + visibleCount);
|
|
11378
|
+
setVisibleRange({ start: firstVisible, end: lastVisible });
|
|
11379
|
+
}, [numPages, orientation, thumbnailWidth, thumbnailHeight, gap]);
|
|
11380
|
+
useEffect26(() => {
|
|
11381
|
+
const container = containerRef.current;
|
|
11382
|
+
if (!container) return;
|
|
11383
|
+
const handleScroll = () => {
|
|
11384
|
+
requestAnimationFrame(updateVisibleRange);
|
|
11385
|
+
};
|
|
11386
|
+
container.addEventListener("scroll", handleScroll, { passive: true });
|
|
11387
|
+
updateVisibleRange();
|
|
11388
|
+
return () => container.removeEventListener("scroll", handleScroll);
|
|
11389
|
+
}, [updateVisibleRange]);
|
|
11390
|
+
useEffect26(() => {
|
|
11391
|
+
if (!document2) {
|
|
11392
|
+
setThumbnails(/* @__PURE__ */ new Map());
|
|
11393
|
+
pageCache.current.clear();
|
|
11394
|
+
return;
|
|
11395
|
+
}
|
|
11396
|
+
const renderThumbnails = async () => {
|
|
11397
|
+
const newThumbnails = new Map(thumbnails);
|
|
11398
|
+
const pagesToRender = [];
|
|
11399
|
+
for (let i = visibleRange.start; i <= visibleRange.end; i++) {
|
|
11400
|
+
if (!newThumbnails.has(i) && !renderQueueRef.current.has(i)) {
|
|
11401
|
+
pagesToRender.push(i);
|
|
11402
|
+
renderQueueRef.current.add(i);
|
|
11403
|
+
}
|
|
11404
|
+
}
|
|
11405
|
+
for (const pageNum of pagesToRender) {
|
|
11406
|
+
try {
|
|
11407
|
+
let page = pageCache.current.get(pageNum);
|
|
11408
|
+
if (!page) {
|
|
11409
|
+
page = await document2.getPage(pageNum);
|
|
11410
|
+
pageCache.current.set(pageNum, page);
|
|
11411
|
+
}
|
|
11412
|
+
const viewport = page.getViewport({ scale: thumbnailScale });
|
|
11413
|
+
const canvas = window.document.createElement("canvas");
|
|
11414
|
+
canvas.width = Math.floor(viewport.width);
|
|
11415
|
+
canvas.height = Math.floor(viewport.height);
|
|
11416
|
+
const ctx = canvas.getContext("2d");
|
|
11417
|
+
if (ctx) {
|
|
11418
|
+
await page.render({
|
|
11419
|
+
canvasContext: ctx,
|
|
11420
|
+
viewport
|
|
11421
|
+
}).promise;
|
|
11422
|
+
newThumbnails.set(pageNum, {
|
|
11423
|
+
pageNumber: pageNum,
|
|
11424
|
+
canvas,
|
|
11425
|
+
width: canvas.width,
|
|
11426
|
+
height: canvas.height
|
|
11427
|
+
});
|
|
11428
|
+
}
|
|
11429
|
+
} catch (error) {
|
|
11430
|
+
console.error(`Failed to render thumbnail for page ${pageNum}:`, error);
|
|
11431
|
+
} finally {
|
|
11432
|
+
renderQueueRef.current.delete(pageNum);
|
|
11433
|
+
}
|
|
11434
|
+
}
|
|
11435
|
+
if (pagesToRender.length > 0) {
|
|
11436
|
+
setThumbnails(newThumbnails);
|
|
11437
|
+
}
|
|
11438
|
+
};
|
|
11439
|
+
renderThumbnails();
|
|
11440
|
+
}, [document2, visibleRange, thumbnailScale, thumbnails]);
|
|
11441
|
+
useEffect26(() => {
|
|
11442
|
+
if (!containerRef.current || numPages === 0) return;
|
|
11443
|
+
const container = containerRef.current;
|
|
11444
|
+
const isHorizontal2 = orientation === "horizontal";
|
|
11445
|
+
const itemSize = (isHorizontal2 ? thumbnailWidth : thumbnailHeight) + gap;
|
|
11446
|
+
const targetPosition = (currentPage - 1) * itemSize;
|
|
11447
|
+
const scrollPosition = isHorizontal2 ? container.scrollLeft : container.scrollTop;
|
|
11448
|
+
const viewportSize = isHorizontal2 ? container.clientWidth : container.clientHeight;
|
|
11449
|
+
if (targetPosition < scrollPosition || targetPosition + itemSize > scrollPosition + viewportSize) {
|
|
11450
|
+
const targetScroll = targetPosition - (viewportSize - itemSize) / 2;
|
|
11451
|
+
container.scrollTo({
|
|
11452
|
+
[isHorizontal2 ? "left" : "top"]: Math.max(0, targetScroll),
|
|
11453
|
+
behavior: "smooth"
|
|
11454
|
+
});
|
|
11455
|
+
}
|
|
11456
|
+
}, [currentPage, numPages, orientation, thumbnailWidth, thumbnailHeight, gap]);
|
|
11457
|
+
const handleThumbnailClick = useCallback41((pageNum) => {
|
|
11458
|
+
onThumbnailClick?.(pageNum);
|
|
11459
|
+
viewerStore.getState().requestScrollToPage(pageNum, "smooth");
|
|
11460
|
+
}, [onThumbnailClick, viewerStore]);
|
|
11461
|
+
if (!document2 || numPages === 0) {
|
|
11462
|
+
return /* @__PURE__ */ jsx36(
|
|
11463
|
+
"div",
|
|
11464
|
+
{
|
|
11465
|
+
className: cn(
|
|
11466
|
+
"pdf-thumbnail-nav",
|
|
11467
|
+
"flex items-center justify-center",
|
|
11468
|
+
"bg-gray-100 dark:bg-gray-800",
|
|
11469
|
+
"text-gray-500 dark:text-gray-400",
|
|
11470
|
+
"text-sm",
|
|
11471
|
+
className
|
|
11472
|
+
),
|
|
11473
|
+
style: {
|
|
11474
|
+
width: orientation === "vertical" ? thumbnailWidth + 24 : "100%",
|
|
11475
|
+
height: orientation === "horizontal" ? thumbnailHeight + 40 : "100%"
|
|
11476
|
+
},
|
|
11477
|
+
children: "No document"
|
|
11478
|
+
}
|
|
11479
|
+
);
|
|
11480
|
+
}
|
|
11481
|
+
const isHorizontal = orientation === "horizontal";
|
|
11482
|
+
const totalSize = numPages * ((isHorizontal ? thumbnailWidth : thumbnailHeight) + gap) - gap;
|
|
11483
|
+
return /* @__PURE__ */ jsx36(
|
|
11484
|
+
"div",
|
|
11485
|
+
{
|
|
11486
|
+
ref: containerRef,
|
|
11487
|
+
className: cn(
|
|
11488
|
+
"pdf-thumbnail-nav",
|
|
11489
|
+
"overflow-auto",
|
|
11490
|
+
"bg-gray-100 dark:bg-gray-800",
|
|
11491
|
+
isHorizontal ? "flex-row" : "flex-col",
|
|
11492
|
+
className
|
|
11493
|
+
),
|
|
11494
|
+
style: {
|
|
11495
|
+
...isHorizontal ? { overflowX: "auto", overflowY: "hidden" } : { overflowX: "hidden", overflowY: "auto" }
|
|
11496
|
+
},
|
|
11497
|
+
children: /* @__PURE__ */ jsx36(
|
|
11498
|
+
"div",
|
|
11499
|
+
{
|
|
11500
|
+
className: cn(
|
|
11501
|
+
"relative",
|
|
11502
|
+
isHorizontal ? "flex flex-row items-center" : "flex flex-col items-center"
|
|
11503
|
+
),
|
|
11504
|
+
style: {
|
|
11505
|
+
[isHorizontal ? "width" : "height"]: totalSize,
|
|
11506
|
+
[isHorizontal ? "minWidth" : "minHeight"]: totalSize,
|
|
11507
|
+
padding: gap / 2,
|
|
11508
|
+
gap
|
|
11509
|
+
},
|
|
11510
|
+
children: Array.from({ length: numPages }, (_, i) => i + 1).map((pageNum) => {
|
|
11511
|
+
const thumbnail = thumbnails.get(pageNum);
|
|
11512
|
+
const isActive = pageNum === currentPage;
|
|
11513
|
+
const isVisible = pageNum >= visibleRange.start && pageNum <= visibleRange.end;
|
|
11514
|
+
return /* @__PURE__ */ jsxs30(
|
|
11515
|
+
"div",
|
|
11516
|
+
{
|
|
11517
|
+
className: cn(
|
|
11518
|
+
"pdf-thumbnail",
|
|
11519
|
+
"flex-shrink-0 cursor-pointer transition-all duration-200",
|
|
11520
|
+
"border-2 rounded shadow-sm hover:shadow-md",
|
|
11521
|
+
isActive ? "border-blue-500 ring-2 ring-blue-200 dark:ring-blue-800" : "border-gray-300 dark:border-gray-600 hover:border-blue-400"
|
|
11522
|
+
),
|
|
11523
|
+
style: {
|
|
11524
|
+
width: thumbnailWidth,
|
|
11525
|
+
height: thumbnailHeight + (showPageNumbers ? 24 : 0)
|
|
11526
|
+
},
|
|
11527
|
+
onClick: () => handleThumbnailClick(pageNum),
|
|
11528
|
+
role: "button",
|
|
11529
|
+
tabIndex: 0,
|
|
11530
|
+
"aria-label": `Go to page ${pageNum}`,
|
|
11531
|
+
"aria-current": isActive ? "page" : void 0,
|
|
11532
|
+
onKeyDown: (e) => {
|
|
11533
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
11534
|
+
e.preventDefault();
|
|
11535
|
+
handleThumbnailClick(pageNum);
|
|
11536
|
+
}
|
|
11537
|
+
},
|
|
11538
|
+
children: [
|
|
11539
|
+
/* @__PURE__ */ jsx36(
|
|
11540
|
+
"div",
|
|
11541
|
+
{
|
|
11542
|
+
className: "relative bg-white dark:bg-gray-700",
|
|
11543
|
+
style: {
|
|
11544
|
+
width: thumbnailWidth,
|
|
11545
|
+
height: thumbnailHeight
|
|
11546
|
+
},
|
|
11547
|
+
children: isVisible && thumbnail?.canvas ? /* @__PURE__ */ jsx36(
|
|
11548
|
+
"img",
|
|
11549
|
+
{
|
|
11550
|
+
src: thumbnail.canvas.toDataURL(),
|
|
11551
|
+
alt: `Page ${pageNum}`,
|
|
11552
|
+
className: "w-full h-full object-contain",
|
|
11553
|
+
loading: "lazy"
|
|
11554
|
+
}
|
|
11555
|
+
) : /* @__PURE__ */ jsx36("div", { className: "absolute inset-0 flex items-center justify-center text-gray-400 dark:text-gray-500 text-xs", children: pageNum })
|
|
11556
|
+
}
|
|
11557
|
+
),
|
|
11558
|
+
showPageNumbers && /* @__PURE__ */ jsx36(
|
|
11559
|
+
"div",
|
|
11560
|
+
{
|
|
11561
|
+
className: cn(
|
|
11562
|
+
"text-center text-xs py-1",
|
|
11563
|
+
"bg-gray-50 dark:bg-gray-700",
|
|
11564
|
+
isActive ? "text-blue-600 dark:text-blue-400 font-medium" : "text-gray-600 dark:text-gray-400"
|
|
11565
|
+
),
|
|
11566
|
+
children: pageNum
|
|
11567
|
+
}
|
|
11568
|
+
)
|
|
11569
|
+
]
|
|
11570
|
+
},
|
|
11571
|
+
pageNum
|
|
11572
|
+
);
|
|
11573
|
+
})
|
|
11574
|
+
}
|
|
11575
|
+
)
|
|
11576
|
+
}
|
|
11577
|
+
);
|
|
11578
|
+
});
|
|
11579
|
+
|
|
10695
11580
|
// src/components/ErrorBoundary/PDFErrorBoundary.tsx
|
|
10696
11581
|
init_utils();
|
|
10697
11582
|
import { Component } from "react";
|
|
10698
|
-
import { jsx as
|
|
11583
|
+
import { jsx as jsx37, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
10699
11584
|
var PDFErrorBoundary = class extends Component {
|
|
10700
11585
|
constructor(props) {
|
|
10701
11586
|
super(props);
|
|
@@ -10723,7 +11608,7 @@ var PDFErrorBoundary = class extends Component {
|
|
|
10723
11608
|
return fallback;
|
|
10724
11609
|
}
|
|
10725
11610
|
if (showDefaultUI) {
|
|
10726
|
-
return /* @__PURE__ */
|
|
11611
|
+
return /* @__PURE__ */ jsx37(
|
|
10727
11612
|
DefaultErrorUI,
|
|
10728
11613
|
{
|
|
10729
11614
|
error,
|
|
@@ -10742,7 +11627,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10742
11627
|
const isNetworkError = error.message.includes("fetch") || error.message.includes("network") || error.message.includes("Failed to load");
|
|
10743
11628
|
let title = "Something went wrong";
|
|
10744
11629
|
let description = error.message;
|
|
10745
|
-
let icon = /* @__PURE__ */
|
|
11630
|
+
let icon = /* @__PURE__ */ jsx37("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx37(
|
|
10746
11631
|
"path",
|
|
10747
11632
|
{
|
|
10748
11633
|
strokeLinecap: "round",
|
|
@@ -10754,7 +11639,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10754
11639
|
if (isPDFError) {
|
|
10755
11640
|
title = "Unable to load PDF";
|
|
10756
11641
|
description = "The PDF file could not be loaded. It may be corrupted or in an unsupported format.";
|
|
10757
|
-
icon = /* @__PURE__ */
|
|
11642
|
+
icon = /* @__PURE__ */ jsx37("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx37(
|
|
10758
11643
|
"path",
|
|
10759
11644
|
{
|
|
10760
11645
|
strokeLinecap: "round",
|
|
@@ -10766,7 +11651,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10766
11651
|
} else if (isNetworkError) {
|
|
10767
11652
|
title = "Network error";
|
|
10768
11653
|
description = "Unable to fetch the PDF file. Please check your internet connection and try again.";
|
|
10769
|
-
icon = /* @__PURE__ */
|
|
11654
|
+
icon = /* @__PURE__ */ jsx37("svg", { className: "w-12 h-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx37(
|
|
10770
11655
|
"path",
|
|
10771
11656
|
{
|
|
10772
11657
|
strokeLinecap: "round",
|
|
@@ -10776,7 +11661,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10776
11661
|
}
|
|
10777
11662
|
) });
|
|
10778
11663
|
}
|
|
10779
|
-
return /* @__PURE__ */
|
|
11664
|
+
return /* @__PURE__ */ jsxs31(
|
|
10780
11665
|
"div",
|
|
10781
11666
|
{
|
|
10782
11667
|
className: cn(
|
|
@@ -10789,14 +11674,14 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10789
11674
|
),
|
|
10790
11675
|
children: [
|
|
10791
11676
|
icon,
|
|
10792
|
-
/* @__PURE__ */
|
|
10793
|
-
/* @__PURE__ */
|
|
10794
|
-
/* @__PURE__ */
|
|
10795
|
-
/* @__PURE__ */
|
|
10796
|
-
/* @__PURE__ */
|
|
11677
|
+
/* @__PURE__ */ jsx37("h2", { className: "mt-4 text-xl font-semibold text-gray-900 dark:text-gray-100", children: title }),
|
|
11678
|
+
/* @__PURE__ */ jsx37("p", { className: "mt-2 text-sm text-gray-600 dark:text-gray-400 max-w-md", children: description }),
|
|
11679
|
+
/* @__PURE__ */ jsxs31("details", { className: "mt-4 text-left max-w-md w-full", children: [
|
|
11680
|
+
/* @__PURE__ */ jsx37("summary", { className: "cursor-pointer text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200", children: "Technical details" }),
|
|
11681
|
+
/* @__PURE__ */ jsx37("pre", { className: "mt-2 p-2 bg-gray-100 dark:bg-gray-800 rounded text-xs overflow-auto", children: error.stack || error.message })
|
|
10797
11682
|
] }),
|
|
10798
|
-
/* @__PURE__ */
|
|
10799
|
-
/* @__PURE__ */
|
|
11683
|
+
/* @__PURE__ */ jsxs31("div", { className: "mt-6 flex gap-3", children: [
|
|
11684
|
+
/* @__PURE__ */ jsx37(
|
|
10800
11685
|
"button",
|
|
10801
11686
|
{
|
|
10802
11687
|
onClick: onReset,
|
|
@@ -10810,7 +11695,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10810
11695
|
children: "Try again"
|
|
10811
11696
|
}
|
|
10812
11697
|
),
|
|
10813
|
-
/* @__PURE__ */
|
|
11698
|
+
/* @__PURE__ */ jsx37(
|
|
10814
11699
|
"button",
|
|
10815
11700
|
{
|
|
10816
11701
|
onClick: () => window.location.reload(),
|
|
@@ -10830,7 +11715,7 @@ function DefaultErrorUI({ error, onReset, className }) {
|
|
|
10830
11715
|
);
|
|
10831
11716
|
}
|
|
10832
11717
|
function withErrorBoundary({ component, ...props }) {
|
|
10833
|
-
return /* @__PURE__ */
|
|
11718
|
+
return /* @__PURE__ */ jsx37(PDFErrorBoundary, { ...props, children: component });
|
|
10834
11719
|
}
|
|
10835
11720
|
|
|
10836
11721
|
// src/index.ts
|
|
@@ -10864,6 +11749,7 @@ export {
|
|
|
10864
11749
|
OutlinePanel,
|
|
10865
11750
|
PDFErrorBoundary,
|
|
10866
11751
|
PDFPage,
|
|
11752
|
+
PDFThumbnailNav,
|
|
10867
11753
|
PDFViewer,
|
|
10868
11754
|
PDFViewerClient,
|
|
10869
11755
|
PDFViewerContext,
|
|
@@ -10882,9 +11768,11 @@ export {
|
|
|
10882
11768
|
ThumbnailPanel,
|
|
10883
11769
|
Toolbar,
|
|
10884
11770
|
VirtualizedDocumentContainer,
|
|
11771
|
+
applyRotation,
|
|
10885
11772
|
clearHighlights,
|
|
10886
11773
|
clearStudentData,
|
|
10887
11774
|
cn,
|
|
11775
|
+
countTextOnPage,
|
|
10888
11776
|
createAgentAPI,
|
|
10889
11777
|
createAgentStore,
|
|
10890
11778
|
createAnnotationStore,
|
|
@@ -10893,6 +11781,7 @@ export {
|
|
|
10893
11781
|
createSearchStore,
|
|
10894
11782
|
createStudentStore,
|
|
10895
11783
|
createViewerStore,
|
|
11784
|
+
doRectsIntersect,
|
|
10896
11785
|
downloadAnnotationsAsJSON,
|
|
10897
11786
|
downloadAnnotationsAsMarkdown,
|
|
10898
11787
|
downloadFile,
|
|
@@ -10900,25 +11789,39 @@ export {
|
|
|
10900
11789
|
exportAnnotationsAsMarkdown,
|
|
10901
11790
|
exportHighlightsAsJSON,
|
|
10902
11791
|
exportHighlightsAsMarkdown,
|
|
11792
|
+
extractPageText,
|
|
11793
|
+
findTextInDocument,
|
|
11794
|
+
findTextOnPage,
|
|
10903
11795
|
generateDocumentId,
|
|
10904
11796
|
getAllDocumentIds,
|
|
10905
11797
|
getAllStudentDataDocumentIds,
|
|
10906
11798
|
getMetadata,
|
|
10907
11799
|
getOutline,
|
|
10908
11800
|
getPage,
|
|
11801
|
+
getPageText,
|
|
10909
11802
|
getPageTextContent,
|
|
10910
11803
|
getPluginManager,
|
|
11804
|
+
getRectIntersection,
|
|
11805
|
+
getRotatedDimensions,
|
|
10911
11806
|
getStorageStats,
|
|
10912
11807
|
importHighlightsFromJSON,
|
|
10913
11808
|
initializePDFJS,
|
|
10914
11809
|
isPDFJSInitialized,
|
|
11810
|
+
isPointInRect,
|
|
10915
11811
|
loadDocument,
|
|
10916
11812
|
loadHighlights,
|
|
10917
11813
|
loadStudentData,
|
|
11814
|
+
mergeAdjacentRects,
|
|
11815
|
+
pdfToPercent,
|
|
11816
|
+
pdfToViewport,
|
|
10918
11817
|
pdfjsLib,
|
|
11818
|
+
percentToPDF,
|
|
11819
|
+
percentToViewport,
|
|
10919
11820
|
quickViewer,
|
|
11821
|
+
removeRotation,
|
|
10920
11822
|
saveHighlights,
|
|
10921
11823
|
saveStudentData,
|
|
11824
|
+
scaleRect,
|
|
10922
11825
|
useAgentContext,
|
|
10923
11826
|
useAgentStore,
|
|
10924
11827
|
useAnnotationStore,
|
|
@@ -10940,6 +11843,8 @@ export {
|
|
|
10940
11843
|
useTouchGestures,
|
|
10941
11844
|
useViewerStore,
|
|
10942
11845
|
useZoom,
|
|
11846
|
+
viewportToPDF,
|
|
11847
|
+
viewportToPercent,
|
|
10943
11848
|
withErrorBoundary
|
|
10944
11849
|
};
|
|
10945
11850
|
//# sourceMappingURL=index.js.map
|