@file-viewer/renderer-pdf 2.2.5 → 2.2.6

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.
Files changed (2) hide show
  1. package/dist/pdf.js +122 -0
  2. package/package.json +2 -2
package/dist/pdf.js CHANGED
@@ -341,6 +341,8 @@ 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;
344
346
  let pdfSearchState = createPdfSearchState();
345
347
  let pdfMatchesCount = { current: 0, total: 0 };
346
348
  let pdfSearchOptions;
@@ -457,9 +459,22 @@ export default async function renderPdf(buffer, target, context) {
457
459
  visit(outlineItems, 0);
458
460
  return result;
459
461
  };
462
+ const navScrollTopByMode = {
463
+ pages: 0,
464
+ outline: 0,
465
+ };
460
466
  const renderNavList = () => {
467
+ if (navList.classList.contains('pdf-page-list')) {
468
+ navScrollTopByMode.pages = navList.scrollTop;
469
+ }
470
+ else if (navList.classList.contains('pdf-outline-list')) {
471
+ navScrollTopByMode.outline = navList.scrollTop;
472
+ }
461
473
  navList.replaceChildren();
462
474
  navList.className = navMode === 'pages' ? 'pdf-page-list' : 'pdf-outline-list';
475
+ const restoreNavScrollTop = () => {
476
+ navList.scrollTop = navScrollTopByMode[navMode];
477
+ };
463
478
  if (navMode === 'pages') {
464
479
  thumbnailObserver === null || thumbnailObserver === void 0 ? void 0 : thumbnailObserver.disconnect();
465
480
  for (let page = 1; page <= pageCount; page += 1) {
@@ -479,6 +494,7 @@ export default async function renderPdf(buffer, target, context) {
479
494
  button.addEventListener('click', () => goToPage(page, 'page-click', 'user'));
480
495
  navList.append(button);
481
496
  }
497
+ restoreNavScrollTop();
482
498
  return;
483
499
  }
484
500
  const entries = flattenedOutlineItems();
@@ -501,6 +517,7 @@ export default async function renderPdf(buffer, target, context) {
501
517
  if (!entries.length) {
502
518
  navList.append(createElement(documentRef, 'div', 'pdf-outline-empty', t('pdf.nav.outlineEmpty')));
503
519
  }
520
+ restoreNavScrollTop();
504
521
  };
505
522
  const paintPdfThumbnail = (pageNumber, thumb) => {
506
523
  const imageUrl = pdfThumbnails.get(pageNumber);
@@ -1020,7 +1037,83 @@ export default async function renderPdf(buffer, target, context) {
1020
1037
  autoFitWidth = false;
1021
1038
  activeFitRequest = null;
1022
1039
  };
1040
+ const getPdfPageElement = (pageNumber) => {
1041
+ var _a;
1042
+ const pageView = (_a = pdfContext.viewer) === null || _a === void 0 ? void 0 : _a.getPageView(pageNumber - 1);
1043
+ return (pageView === null || pageView === void 0 ? void 0 : pageView.div) ||
1044
+ pdfViewerRoot.querySelector(`.page[data-page-number="${pageNumber}"]`);
1045
+ };
1046
+ const captureCurrentPdfPageAnchor = () => {
1047
+ const pageElement = getPdfPageElement(currentPage);
1048
+ if (!pageElement) {
1049
+ return null;
1050
+ }
1051
+ const containerRect = container.getBoundingClientRect();
1052
+ const pageRect = pageElement.getBoundingClientRect();
1053
+ const pageHeight = pageElement.offsetHeight || pageRect.height;
1054
+ if (pageHeight <= 0) {
1055
+ return null;
1056
+ }
1057
+ const pageTop = pageRect.top - containerRect.top + container.scrollTop;
1058
+ const inPageRatio = (container.scrollTop - pageTop) / pageHeight;
1059
+ return {
1060
+ page: currentPage,
1061
+ inPageRatio: Math.max(0, Math.min(1, inPageRatio)),
1062
+ };
1063
+ };
1064
+ const cancelPendingUserRotationRestore = () => {
1065
+ if (!pendingUserRotationAnchor) {
1066
+ return;
1067
+ }
1068
+ pendingUserRotationAnchor = null;
1069
+ rotationOperationVersion += 1;
1070
+ };
1071
+ const restoreUserRotationAnchor = (anchor, operationVersion) => {
1072
+ const apply = () => {
1073
+ if (destroyed ||
1074
+ operationVersion !== rotationOperationVersion ||
1075
+ pendingUserRotationAnchor !== anchor) {
1076
+ return false;
1077
+ }
1078
+ const pageElement = getPdfPageElement(anchor.page);
1079
+ if (!pageElement) {
1080
+ return false;
1081
+ }
1082
+ const containerRect = container.getBoundingClientRect();
1083
+ const pageRect = pageElement.getBoundingClientRect();
1084
+ const pageHeight = pageElement.offsetHeight || pageRect.height;
1085
+ if (pageHeight <= 0) {
1086
+ return false;
1087
+ }
1088
+ const pageTop = pageRect.top - containerRect.top + container.scrollTop;
1089
+ const maxTop = Math.max(0, container.scrollHeight - container.clientHeight);
1090
+ suppressProgrammaticScrollEvents();
1091
+ container.scrollTop = Math.max(0, Math.min(maxTop, pageTop + anchor.inPageRatio * pageHeight));
1092
+ currentPage = anchor.page;
1093
+ syncUi();
1094
+ return true;
1095
+ };
1096
+ apply();
1097
+ void waitForPaint(targetWindow)
1098
+ .then(() => {
1099
+ apply();
1100
+ return waitForPaint(targetWindow);
1101
+ })
1102
+ .then(apply);
1103
+ targetWindow.requestAnimationFrame(() => {
1104
+ apply();
1105
+ targetWindow.requestAnimationFrame(apply);
1106
+ });
1107
+ targetWindow.setTimeout(() => {
1108
+ apply();
1109
+ if (operationVersion === rotationOperationVersion &&
1110
+ pendingUserRotationAnchor === anchor) {
1111
+ pendingUserRotationAnchor = null;
1112
+ }
1113
+ }, 180);
1114
+ };
1023
1115
  const recordUserScrollIntent = () => {
1116
+ cancelPendingUserRotationRestore();
1024
1117
  userScrollIntentUntil = Date.now() + 750;
1025
1118
  suppressScrollEventUntil = 0;
1026
1119
  markFitInteraction('user');
@@ -1313,6 +1406,18 @@ export default async function renderPdf(buffer, target, context) {
1313
1406
  const applyRotation = (rotation, action = 'rotation-change', source = 'viewer', notifyViewState = true) => {
1314
1407
  markFitInteraction(source);
1315
1408
  const normalized = normalizeRotation(rotation);
1409
+ if (source === 'user' && pdfContext.viewer) {
1410
+ pendingUserRotationAnchor || (pendingUserRotationAnchor = captureCurrentPdfPageAnchor());
1411
+ }
1412
+ else {
1413
+ cancelPendingUserRotationRestore();
1414
+ }
1415
+ const pageAnchor = source === 'user' ? pendingUserRotationAnchor : null;
1416
+ const operationVersion = ++rotationOperationVersion;
1417
+ if (pageAnchor) {
1418
+ suppressProgrammaticScrollEvents();
1419
+ currentPage = pageAnchor.page;
1420
+ }
1316
1421
  currentRotation = normalized;
1317
1422
  pdfThumbnails.clear();
1318
1423
  pendingPdfThumbnails.clear();
@@ -1323,6 +1428,9 @@ export default async function renderPdf(buffer, target, context) {
1323
1428
  pdfContext.viewer.pagesRotation = normalized;
1324
1429
  void waitForPaint(targetWindow).then(() => {
1325
1430
  var _a;
1431
+ if (operationVersion !== rotationOperationVersion) {
1432
+ return;
1433
+ }
1326
1434
  const refocusBoundingBoxes = () => {
1327
1435
  if (pdfBoundingBoxController.hasBoxes()) {
1328
1436
  void waitForPaint(targetWindow)
@@ -1331,6 +1439,9 @@ export default async function renderPdf(buffer, target, context) {
1331
1439
  }
1332
1440
  };
1333
1441
  if (reapplyFitAfterLayout(source, notifyViewState)) {
1442
+ if (pageAnchor) {
1443
+ restoreUserRotationAnchor(pageAnchor, operationVersion);
1444
+ }
1334
1445
  if (notifyViewState) {
1335
1446
  emitViewStateChange(action, source);
1336
1447
  }
@@ -1340,6 +1451,9 @@ export default async function renderPdf(buffer, target, context) {
1340
1451
  (_a = pdfContext.viewer) === null || _a === void 0 ? void 0 : _a.update();
1341
1452
  scheduleLegacyPageDimensionPatch();
1342
1453
  syncUi();
1454
+ if (pageAnchor) {
1455
+ restoreUserRotationAnchor(pageAnchor, operationVersion);
1456
+ }
1343
1457
  if (notifyViewState) {
1344
1458
  emitViewStateChange(action, source);
1345
1459
  }
@@ -1358,6 +1472,9 @@ export default async function renderPdf(buffer, target, context) {
1358
1472
  if (!pdfContext.viewer || !pageCount) {
1359
1473
  return;
1360
1474
  }
1475
+ if (source === 'user') {
1476
+ cancelPendingUserRotationRestore();
1477
+ }
1361
1478
  markFitInteraction(source);
1362
1479
  const nextPage = Math.min(pageCount, Math.max(1, pageNumber));
1363
1480
  runWithStableHorizontalScroll(() => {
@@ -1604,6 +1721,11 @@ export default async function renderPdf(buffer, target, context) {
1604
1721
  }
1605
1722
  });
1606
1723
  eventBus.on('pagechanging', ({ pageNumber }) => {
1724
+ if (pendingUserRotationAnchor && pageNumber !== pendingUserRotationAnchor.page) {
1725
+ currentPage = pendingUserRotationAnchor.page;
1726
+ syncUi();
1727
+ return;
1728
+ }
1607
1729
  const previousPage = currentPage;
1608
1730
  currentPage = pageNumber;
1609
1731
  syncUi();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@file-viewer/renderer-pdf",
3
- "version": "2.2.5",
3
+ "version": "2.2.6",
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.5",
57
+ "@file-viewer/core": "2.2.6",
58
58
  "@fontsource-variable/noto-sans-sc": "5.2.10",
59
59
  "pdf-lib": "1.17.1",
60
60
  "pdfjs-dist": "5.4.624"