@file-viewer/renderer-pdf 2.2.5 → 2.2.7
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/pdf.js +160 -4
- package/package.json +2 -2
package/dist/pdf.js
CHANGED
|
@@ -341,6 +341,10 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
341
341
|
let suppressScrollEventUntil = 0;
|
|
342
342
|
let userScrollIntentUntil = 0;
|
|
343
343
|
let scrollStateFrame = 0;
|
|
344
|
+
let rotationOperationVersion = 0;
|
|
345
|
+
let pendingUserRotationAnchor = null;
|
|
346
|
+
let zoomOperationVersion = 0;
|
|
347
|
+
let pendingUserZoomAnchor = null;
|
|
344
348
|
let pdfSearchState = createPdfSearchState();
|
|
345
349
|
let pdfMatchesCount = { current: 0, total: 0 };
|
|
346
350
|
let pdfSearchOptions;
|
|
@@ -457,9 +461,22 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
457
461
|
visit(outlineItems, 0);
|
|
458
462
|
return result;
|
|
459
463
|
};
|
|
464
|
+
const navScrollTopByMode = {
|
|
465
|
+
pages: 0,
|
|
466
|
+
outline: 0,
|
|
467
|
+
};
|
|
460
468
|
const renderNavList = () => {
|
|
469
|
+
if (navList.classList.contains('pdf-page-list')) {
|
|
470
|
+
navScrollTopByMode.pages = navList.scrollTop;
|
|
471
|
+
}
|
|
472
|
+
else if (navList.classList.contains('pdf-outline-list')) {
|
|
473
|
+
navScrollTopByMode.outline = navList.scrollTop;
|
|
474
|
+
}
|
|
461
475
|
navList.replaceChildren();
|
|
462
476
|
navList.className = navMode === 'pages' ? 'pdf-page-list' : 'pdf-outline-list';
|
|
477
|
+
const restoreNavScrollTop = () => {
|
|
478
|
+
navList.scrollTop = navScrollTopByMode[navMode];
|
|
479
|
+
};
|
|
463
480
|
if (navMode === 'pages') {
|
|
464
481
|
thumbnailObserver === null || thumbnailObserver === void 0 ? void 0 : thumbnailObserver.disconnect();
|
|
465
482
|
for (let page = 1; page <= pageCount; page += 1) {
|
|
@@ -479,6 +496,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
479
496
|
button.addEventListener('click', () => goToPage(page, 'page-click', 'user'));
|
|
480
497
|
navList.append(button);
|
|
481
498
|
}
|
|
499
|
+
restoreNavScrollTop();
|
|
482
500
|
return;
|
|
483
501
|
}
|
|
484
502
|
const entries = flattenedOutlineItems();
|
|
@@ -501,6 +519,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
501
519
|
if (!entries.length) {
|
|
502
520
|
navList.append(createElement(documentRef, 'div', 'pdf-outline-empty', t('pdf.nav.outlineEmpty')));
|
|
503
521
|
}
|
|
522
|
+
restoreNavScrollTop();
|
|
504
523
|
};
|
|
505
524
|
const paintPdfThumbnail = (pageNumber, thumb) => {
|
|
506
525
|
const imageUrl = pdfThumbnails.get(pageNumber);
|
|
@@ -1020,7 +1039,93 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1020
1039
|
autoFitWidth = false;
|
|
1021
1040
|
activeFitRequest = null;
|
|
1022
1041
|
};
|
|
1042
|
+
const getPdfPageElement = (pageNumber) => {
|
|
1043
|
+
var _a;
|
|
1044
|
+
const pageView = (_a = pdfContext.viewer) === null || _a === void 0 ? void 0 : _a.getPageView(pageNumber - 1);
|
|
1045
|
+
return (pageView === null || pageView === void 0 ? void 0 : pageView.div) ||
|
|
1046
|
+
pdfViewerRoot.querySelector(`.page[data-page-number="${pageNumber}"]`);
|
|
1047
|
+
};
|
|
1048
|
+
const captureCurrentPdfPageAnchor = () => {
|
|
1049
|
+
const pageElement = getPdfPageElement(currentPage);
|
|
1050
|
+
if (!pageElement) {
|
|
1051
|
+
return null;
|
|
1052
|
+
}
|
|
1053
|
+
const containerRect = container.getBoundingClientRect();
|
|
1054
|
+
const pageRect = pageElement.getBoundingClientRect();
|
|
1055
|
+
const pageHeight = pageElement.offsetHeight || pageRect.height;
|
|
1056
|
+
if (pageHeight <= 0) {
|
|
1057
|
+
return null;
|
|
1058
|
+
}
|
|
1059
|
+
const pageTop = pageRect.top - containerRect.top + container.scrollTop;
|
|
1060
|
+
const inPageRatio = (container.scrollTop - pageTop) / pageHeight;
|
|
1061
|
+
return {
|
|
1062
|
+
page: currentPage,
|
|
1063
|
+
inPageRatio: Math.max(0, Math.min(1, inPageRatio)),
|
|
1064
|
+
};
|
|
1065
|
+
};
|
|
1066
|
+
const cancelPendingUserRotationRestore = () => {
|
|
1067
|
+
if (!pendingUserRotationAnchor) {
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
pendingUserRotationAnchor = null;
|
|
1071
|
+
rotationOperationVersion += 1;
|
|
1072
|
+
};
|
|
1073
|
+
const cancelPendingUserZoomRestore = () => {
|
|
1074
|
+
if (!pendingUserZoomAnchor) {
|
|
1075
|
+
return;
|
|
1076
|
+
}
|
|
1077
|
+
pendingUserZoomAnchor = null;
|
|
1078
|
+
zoomOperationVersion += 1;
|
|
1079
|
+
};
|
|
1080
|
+
const restorePdfPageAnchor = (anchor, isActive, release) => {
|
|
1081
|
+
const apply = () => {
|
|
1082
|
+
if (destroyed || !isActive()) {
|
|
1083
|
+
return false;
|
|
1084
|
+
}
|
|
1085
|
+
const pageElement = getPdfPageElement(anchor.page);
|
|
1086
|
+
if (!pageElement) {
|
|
1087
|
+
return false;
|
|
1088
|
+
}
|
|
1089
|
+
const containerRect = container.getBoundingClientRect();
|
|
1090
|
+
const pageRect = pageElement.getBoundingClientRect();
|
|
1091
|
+
const pageHeight = pageElement.offsetHeight || pageRect.height;
|
|
1092
|
+
if (pageHeight <= 0) {
|
|
1093
|
+
return false;
|
|
1094
|
+
}
|
|
1095
|
+
const pageTop = pageRect.top - containerRect.top + container.scrollTop;
|
|
1096
|
+
const maxTop = Math.max(0, container.scrollHeight - container.clientHeight);
|
|
1097
|
+
suppressProgrammaticScrollEvents();
|
|
1098
|
+
container.scrollTop = Math.max(0, Math.min(maxTop, pageTop + anchor.inPageRatio * pageHeight));
|
|
1099
|
+
currentPage = anchor.page;
|
|
1100
|
+
syncUi();
|
|
1101
|
+
return true;
|
|
1102
|
+
};
|
|
1103
|
+
apply();
|
|
1104
|
+
void waitForPaint(targetWindow)
|
|
1105
|
+
.then(() => {
|
|
1106
|
+
apply();
|
|
1107
|
+
return waitForPaint(targetWindow);
|
|
1108
|
+
})
|
|
1109
|
+
.then(apply);
|
|
1110
|
+
targetWindow.requestAnimationFrame(() => {
|
|
1111
|
+
apply();
|
|
1112
|
+
targetWindow.requestAnimationFrame(apply);
|
|
1113
|
+
});
|
|
1114
|
+
targetWindow.setTimeout(() => {
|
|
1115
|
+
apply();
|
|
1116
|
+
if (isActive())
|
|
1117
|
+
release();
|
|
1118
|
+
}, 180);
|
|
1119
|
+
};
|
|
1120
|
+
const restoreUserRotationAnchor = (anchor, operationVersion) => restorePdfPageAnchor(anchor, () => operationVersion === rotationOperationVersion && pendingUserRotationAnchor === anchor, () => {
|
|
1121
|
+
pendingUserRotationAnchor = null;
|
|
1122
|
+
});
|
|
1123
|
+
const restoreUserZoomAnchor = (anchor, operationVersion) => restorePdfPageAnchor(anchor, () => operationVersion === zoomOperationVersion && pendingUserZoomAnchor === anchor, () => {
|
|
1124
|
+
pendingUserZoomAnchor = null;
|
|
1125
|
+
});
|
|
1023
1126
|
const recordUserScrollIntent = () => {
|
|
1127
|
+
cancelPendingUserRotationRestore();
|
|
1128
|
+
cancelPendingUserZoomRestore();
|
|
1024
1129
|
userScrollIntentUntil = Date.now() + 750;
|
|
1025
1130
|
suppressScrollEventUntil = 0;
|
|
1026
1131
|
markFitInteraction('user');
|
|
@@ -1190,6 +1295,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1190
1295
|
if (!pdfContext.viewer) {
|
|
1191
1296
|
return;
|
|
1192
1297
|
}
|
|
1298
|
+
cancelPendingUserZoomRestore();
|
|
1193
1299
|
userScrollIntentUntil = 0;
|
|
1194
1300
|
suppressProgrammaticScrollEvents();
|
|
1195
1301
|
autoFitWidth = true;
|
|
@@ -1201,6 +1307,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1201
1307
|
};
|
|
1202
1308
|
const applyPdfFit = async (request) => {
|
|
1203
1309
|
var _a, _b, _c;
|
|
1310
|
+
cancelPendingUserZoomRestore();
|
|
1204
1311
|
userScrollIntentUntil = 0;
|
|
1205
1312
|
activeFitRequest = { ...request };
|
|
1206
1313
|
if (!pdfContext.viewer || loadStatus !== 'ready') {
|
|
@@ -1288,13 +1395,30 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1288
1395
|
fitToWidth('viewer');
|
|
1289
1396
|
});
|
|
1290
1397
|
};
|
|
1398
|
+
const setAnchoredScale = (scale, action, source) => {
|
|
1399
|
+
if (!pdfContext.viewer) {
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1402
|
+
cancelPendingUserRotationRestore();
|
|
1403
|
+
pendingUserZoomAnchor || (pendingUserZoomAnchor = captureCurrentPdfPageAnchor());
|
|
1404
|
+
const pageAnchor = pendingUserZoomAnchor;
|
|
1405
|
+
const operationVersion = ++zoomOperationVersion;
|
|
1406
|
+
if (pageAnchor) {
|
|
1407
|
+
suppressProgrammaticScrollEvents();
|
|
1408
|
+
currentPage = pageAnchor.page;
|
|
1409
|
+
}
|
|
1410
|
+
setScale(scale, action, source);
|
|
1411
|
+
if (pageAnchor) {
|
|
1412
|
+
restoreUserZoomAnchor(pageAnchor, operationVersion);
|
|
1413
|
+
}
|
|
1414
|
+
};
|
|
1291
1415
|
const zoomIn = (source = 'user') => {
|
|
1292
1416
|
markFitInteraction(source);
|
|
1293
|
-
|
|
1417
|
+
setAnchoredScale(currentScale + SCALE_STEP, 'zoom-in', source);
|
|
1294
1418
|
};
|
|
1295
1419
|
const zoomOut = (source = 'user') => {
|
|
1296
1420
|
markFitInteraction(source);
|
|
1297
|
-
|
|
1421
|
+
setAnchoredScale(currentScale - SCALE_STEP, 'zoom-out', source);
|
|
1298
1422
|
};
|
|
1299
1423
|
const reapplyFitAfterLayout = (source, notifyViewState = true) => {
|
|
1300
1424
|
if (activeFitRequest) {
|
|
@@ -1313,6 +1437,19 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1313
1437
|
const applyRotation = (rotation, action = 'rotation-change', source = 'viewer', notifyViewState = true) => {
|
|
1314
1438
|
markFitInteraction(source);
|
|
1315
1439
|
const normalized = normalizeRotation(rotation);
|
|
1440
|
+
if (source === 'user' && pdfContext.viewer) {
|
|
1441
|
+
cancelPendingUserZoomRestore();
|
|
1442
|
+
pendingUserRotationAnchor || (pendingUserRotationAnchor = captureCurrentPdfPageAnchor());
|
|
1443
|
+
}
|
|
1444
|
+
else {
|
|
1445
|
+
cancelPendingUserRotationRestore();
|
|
1446
|
+
}
|
|
1447
|
+
const pageAnchor = source === 'user' ? pendingUserRotationAnchor : null;
|
|
1448
|
+
const operationVersion = ++rotationOperationVersion;
|
|
1449
|
+
if (pageAnchor) {
|
|
1450
|
+
suppressProgrammaticScrollEvents();
|
|
1451
|
+
currentPage = pageAnchor.page;
|
|
1452
|
+
}
|
|
1316
1453
|
currentRotation = normalized;
|
|
1317
1454
|
pdfThumbnails.clear();
|
|
1318
1455
|
pendingPdfThumbnails.clear();
|
|
@@ -1323,6 +1460,9 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1323
1460
|
pdfContext.viewer.pagesRotation = normalized;
|
|
1324
1461
|
void waitForPaint(targetWindow).then(() => {
|
|
1325
1462
|
var _a;
|
|
1463
|
+
if (operationVersion !== rotationOperationVersion) {
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1326
1466
|
const refocusBoundingBoxes = () => {
|
|
1327
1467
|
if (pdfBoundingBoxController.hasBoxes()) {
|
|
1328
1468
|
void waitForPaint(targetWindow)
|
|
@@ -1331,6 +1471,9 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1331
1471
|
}
|
|
1332
1472
|
};
|
|
1333
1473
|
if (reapplyFitAfterLayout(source, notifyViewState)) {
|
|
1474
|
+
if (pageAnchor) {
|
|
1475
|
+
restoreUserRotationAnchor(pageAnchor, operationVersion);
|
|
1476
|
+
}
|
|
1334
1477
|
if (notifyViewState) {
|
|
1335
1478
|
emitViewStateChange(action, source);
|
|
1336
1479
|
}
|
|
@@ -1340,6 +1483,9 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1340
1483
|
(_a = pdfContext.viewer) === null || _a === void 0 ? void 0 : _a.update();
|
|
1341
1484
|
scheduleLegacyPageDimensionPatch();
|
|
1342
1485
|
syncUi();
|
|
1486
|
+
if (pageAnchor) {
|
|
1487
|
+
restoreUserRotationAnchor(pageAnchor, operationVersion);
|
|
1488
|
+
}
|
|
1343
1489
|
if (notifyViewState) {
|
|
1344
1490
|
emitViewStateChange(action, source);
|
|
1345
1491
|
}
|
|
@@ -1358,6 +1504,10 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1358
1504
|
if (!pdfContext.viewer || !pageCount) {
|
|
1359
1505
|
return;
|
|
1360
1506
|
}
|
|
1507
|
+
if (source === 'user') {
|
|
1508
|
+
cancelPendingUserRotationRestore();
|
|
1509
|
+
cancelPendingUserZoomRestore();
|
|
1510
|
+
}
|
|
1361
1511
|
markFitInteraction(source);
|
|
1362
1512
|
const nextPage = Math.min(pageCount, Math.max(1, pageNumber));
|
|
1363
1513
|
runWithStableHorizontalScroll(() => {
|
|
@@ -1604,6 +1754,12 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1604
1754
|
}
|
|
1605
1755
|
});
|
|
1606
1756
|
eventBus.on('pagechanging', ({ pageNumber }) => {
|
|
1757
|
+
const pendingPageAnchor = pendingUserRotationAnchor || pendingUserZoomAnchor;
|
|
1758
|
+
if (pendingPageAnchor && pageNumber !== pendingPageAnchor.page) {
|
|
1759
|
+
currentPage = pendingPageAnchor.page;
|
|
1760
|
+
syncUi();
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1607
1763
|
const previousPage = currentPage;
|
|
1608
1764
|
currentPage = pageNumber;
|
|
1609
1765
|
syncUi();
|
|
@@ -1823,12 +1979,12 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1823
1979
|
},
|
|
1824
1980
|
resetZoom: () => {
|
|
1825
1981
|
markFitInteraction('api');
|
|
1826
|
-
|
|
1982
|
+
setAnchoredScale(1, 'zoom-reset', 'api');
|
|
1827
1983
|
return getPdfZoomState();
|
|
1828
1984
|
},
|
|
1829
1985
|
setZoom: scale => {
|
|
1830
1986
|
markFitInteraction('api');
|
|
1831
|
-
|
|
1987
|
+
setAnchoredScale(scale, 'zoom-change', 'api');
|
|
1832
1988
|
return getPdfZoomState();
|
|
1833
1989
|
},
|
|
1834
1990
|
fit: applyPdfFit,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@file-viewer/renderer-pdf",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Standalone PDF renderer plugin for File Viewer powered by PDF.js.",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"LICENSE"
|
|
55
55
|
],
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@file-viewer/core": "2.2.
|
|
57
|
+
"@file-viewer/core": "2.2.7",
|
|
58
58
|
"@fontsource-variable/noto-sans-sc": "5.2.10",
|
|
59
59
|
"pdf-lib": "1.17.1",
|
|
60
60
|
"pdfjs-dist": "5.4.624"
|