@file-viewer/renderer-pdf 2.1.27 → 2.1.29
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 +105 -72
- package/dist/pdfFit.d.ts +20 -0
- package/dist/pdfFit.js +26 -0
- package/package.json +2 -2
package/dist/pdf.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { getDocument, GlobalWorkerOptions, PDFWorker as PdfJsWorker, PixelsPerInch, } from 'pdfjs-dist/legacy/build/pdf.mjs';
|
|
2
2
|
import { EventBus, GenericL10n, PDFFindController, PDFLinkService, PDFViewer, } from 'pdfjs-dist/legacy/web/pdf_viewer.mjs';
|
|
3
3
|
import { registerFileViewerSearchProvider, registerFileViewerZoomProvider, unregisterFileViewerSearchProvider, unregisterFileViewerZoomProvider, registerFileViewerViewStateProvider, unregisterFileViewerViewStateProvider, createFileViewerZoomChangeEmitter, createFileViewerViewStateChange, createFileViewerViewStateChangeEmitter, createFileViewerTranslator, buildPrintPageStyle, formatCssPixels, DEFAULT_PDF_RANGE_CHUNK_SIZE, resolveFileViewerLocale, resolveFileViewerFitScale, } from '@file-viewer/core';
|
|
4
|
-
import { DEFAULT_FILE_VIEWER_PDF_WORKER_PATH, resolveFileViewerPdfAssetUrls, } from '@file-viewer/core/assets';
|
|
4
|
+
import { DEFAULT_FILE_VIEWER_PDF_WORKER_PATH, resolveFileViewerPdfAssetUrls, resolveFileViewerRuntimeAssetBaseUrl, } from '@file-viewer/core/assets';
|
|
5
5
|
import { pdfViewerStyle } from './pdfStyles.js';
|
|
6
6
|
import { collectMalformedIdentityFontNames, createPdfCjkFontFallbackManager, detectMalformedIdentityCjkFontFamilies, } from './pdfFontFallback.js';
|
|
7
|
+
import { PDF_FIT_HORIZONTAL_PADDING, PDF_PAGE_BORDER_WIDTH, resolvePdfFitViewportSize, } from './pdfFit.js';
|
|
7
8
|
export const DEFAULT_FILE_VIEWER_PDF_WORKER_URL = DEFAULT_FILE_VIEWER_PDF_WORKER_PATH;
|
|
8
9
|
const MIN_SCALE = 0.2;
|
|
9
10
|
const MAX_SCALE = 3;
|
|
10
11
|
const SCALE_STEP = 0.1;
|
|
11
|
-
const FIT_HORIZONTAL_PADDING = 28;
|
|
12
|
-
const PAGE_BORDER_WIDTH = 18;
|
|
13
12
|
const PDF_EXPORT_MAX_PAGE_PIXELS = 8000000;
|
|
14
13
|
const PDF_WORKER_PROBE_TIMEOUT_MS = 1200;
|
|
15
14
|
const PDF_JS_DESTROY_CONSOLE_SUPPRESSION_MS = 1500;
|
|
@@ -254,50 +253,6 @@ const installBundledPdfFakeWorker = async () => {
|
|
|
254
253
|
const resolvePdfWorkerUrl = (options, documentBaseUrl) => {
|
|
255
254
|
return resolveFileViewerPdfAssetUrls(options, documentBaseUrl).workerUrl;
|
|
256
255
|
};
|
|
257
|
-
const readBundlerPublicBaseUrl = () => {
|
|
258
|
-
var _a;
|
|
259
|
-
try {
|
|
260
|
-
const value = (_a = import.meta.env) === null || _a === void 0 ? void 0 : _a.BASE_URL;
|
|
261
|
-
return typeof value === 'string' ? value.trim() : '';
|
|
262
|
-
}
|
|
263
|
-
catch {
|
|
264
|
-
return '';
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
const resolvePdfRuntimeAssetBaseUrl = (documentRef) => {
|
|
268
|
-
const documentBaseUrl = documentRef.baseURI || documentRef.URL || 'file:///';
|
|
269
|
-
const bundlerBaseUrl = readBundlerPublicBaseUrl();
|
|
270
|
-
if (bundlerBaseUrl && bundlerBaseUrl !== '.' && bundlerBaseUrl !== './') {
|
|
271
|
-
try {
|
|
272
|
-
return new URL(bundlerBaseUrl.endsWith('/') ? bundlerBaseUrl : `${bundlerBaseUrl}/`, documentBaseUrl).href;
|
|
273
|
-
}
|
|
274
|
-
catch {
|
|
275
|
-
// Continue with DOM-based public-path detection.
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
// An explicit <base> is authoritative and already reflected by baseURI.
|
|
279
|
-
if (documentRef.querySelector('base[href]')) {
|
|
280
|
-
return documentBaseUrl;
|
|
281
|
-
}
|
|
282
|
-
// Entry scripts remain under the public deployment base when an SPA route
|
|
283
|
-
// changes document.baseURI. This covers Vite and common UMI/Webpack layouts.
|
|
284
|
-
for (const script of Array.from(documentRef.querySelectorAll('script[src]'))) {
|
|
285
|
-
try {
|
|
286
|
-
const scriptUrl = new URL(script.src || script.getAttribute('src') || '', documentBaseUrl);
|
|
287
|
-
const assetDirectory = scriptUrl.pathname.match(/^(.*\/)(?:assets|static)\/[^/]+$/i);
|
|
288
|
-
if (assetDirectory) {
|
|
289
|
-
return new URL(assetDirectory[1], scriptUrl.origin).href;
|
|
290
|
-
}
|
|
291
|
-
if (/\/(?:umi|main|index)(?:[.-][^/]*)?\.(?:m?js)$/i.test(scriptUrl.pathname)) {
|
|
292
|
-
return new URL('./', scriptUrl).href;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
catch {
|
|
296
|
-
// Ignore unrelated or malformed script URLs.
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return documentBaseUrl;
|
|
300
|
-
};
|
|
301
256
|
const buildOutlineItems = (items, prefix = 'outline', getFallbackTitle = index => `Outline ${index + 1}`) => items.map((item, index) => {
|
|
302
257
|
const id = `${prefix}-${index}`;
|
|
303
258
|
const children = Array.isArray(item.items)
|
|
@@ -321,7 +276,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
321
276
|
throw new Error(t('pdf.error.browserWindow'));
|
|
322
277
|
}
|
|
323
278
|
const options = (_a = context === null || context === void 0 ? void 0 : context.options) === null || _a === void 0 ? void 0 : _a.pdf;
|
|
324
|
-
const pdfRuntimeAssetBaseUrl =
|
|
279
|
+
const pdfRuntimeAssetBaseUrl = resolveFileViewerRuntimeAssetBaseUrl(documentRef);
|
|
325
280
|
const cjkFontFallbackEnabled = (options === null || options === void 0 ? void 0 : options.cjkFontFallback) !== false;
|
|
326
281
|
const identityFontRepairEnabled = (options === null || options === void 0 ? void 0 : options.identityFontRepair) !== false;
|
|
327
282
|
const fontInspectionEnabled = cjkFontFallbackEnabled || identityFontRepairEnabled;
|
|
@@ -359,7 +314,9 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
359
314
|
let activeViewStateApplyVersion = 0;
|
|
360
315
|
let pendingInitialViewState = initialViewState;
|
|
361
316
|
let pendingFitRequest = null;
|
|
317
|
+
let activeFitRequest = null;
|
|
362
318
|
let suppressScrollEventUntil = 0;
|
|
319
|
+
let userScrollIntentUntil = 0;
|
|
363
320
|
let scrollStateFrame = 0;
|
|
364
321
|
let pdfSearchState = createPdfSearchState();
|
|
365
322
|
let pdfMatchesCount = { current: 0, total: 0 };
|
|
@@ -937,7 +894,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
937
894
|
label: scaleText(),
|
|
938
895
|
canZoomIn: loadStatus === 'ready' && !!pdfContext.viewer && canZoomIn(),
|
|
939
896
|
canZoomOut: loadStatus === 'ready' && !!pdfContext.viewer && canZoomOut(),
|
|
940
|
-
canReset: loadStatus === 'ready' && !!pdfContext.viewer &&
|
|
897
|
+
canReset: loadStatus === 'ready' && !!pdfContext.viewer && Math.abs(currentScale - 1) > 0.001,
|
|
941
898
|
minScale: MIN_SCALE,
|
|
942
899
|
maxScale: MAX_SCALE,
|
|
943
900
|
});
|
|
@@ -993,6 +950,21 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
993
950
|
const suppressProgrammaticScrollEvents = () => {
|
|
994
951
|
suppressScrollEventUntil = Math.max(suppressScrollEventUntil, Date.now() + 180);
|
|
995
952
|
};
|
|
953
|
+
const markFitInteraction = (source) => {
|
|
954
|
+
if (source !== 'user' && source !== 'api') {
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
if ((activeFitRequest === null || activeFitRequest === void 0 ? void 0 : activeFitRequest.resize) === 'always') {
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
autoFitWidth = false;
|
|
961
|
+
activeFitRequest = null;
|
|
962
|
+
};
|
|
963
|
+
const recordUserScrollIntent = () => {
|
|
964
|
+
userScrollIntentUntil = Date.now() + 750;
|
|
965
|
+
suppressScrollEventUntil = 0;
|
|
966
|
+
markFitInteraction('user');
|
|
967
|
+
};
|
|
996
968
|
const restoreScrollState = (scroll, notify = true) => {
|
|
997
969
|
if (!scroll) {
|
|
998
970
|
return;
|
|
@@ -1020,6 +992,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1020
992
|
const source = applyOptions.source || 'api';
|
|
1021
993
|
const action = applyOptions.action || 'restore';
|
|
1022
994
|
const notify = applyOptions.notify !== false;
|
|
995
|
+
markFitInteraction(source);
|
|
1023
996
|
const applyVersion = ++viewStateApplyVersion;
|
|
1024
997
|
activeViewStateApplyVersion = applyVersion;
|
|
1025
998
|
suppressProgrammaticScrollEvents();
|
|
@@ -1078,7 +1051,11 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1078
1051
|
}
|
|
1079
1052
|
scrollStateFrame = targetWindow.requestAnimationFrame(() => {
|
|
1080
1053
|
scrollStateFrame = 0;
|
|
1081
|
-
|
|
1054
|
+
const source = Date.now() <= userScrollIntentUntil
|
|
1055
|
+
? 'user'
|
|
1056
|
+
: 'viewer';
|
|
1057
|
+
markFitInteraction(source);
|
|
1058
|
+
emitViewStateChange('scroll', source);
|
|
1082
1059
|
});
|
|
1083
1060
|
};
|
|
1084
1061
|
const setScale = (scale, action = 'zoom-change', source = 'viewer', notifyViewState = true) => {
|
|
@@ -1126,13 +1103,15 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1126
1103
|
const getFitWidthScale = (pdfViewer) => {
|
|
1127
1104
|
const pageWidth = getPageWidthAtScaleOne(pdfViewer);
|
|
1128
1105
|
const containerWidth = container.clientWidth || targetWindow.innerWidth;
|
|
1129
|
-
const availableWidth = Math.max(containerWidth -
|
|
1106
|
+
const availableWidth = Math.max(containerWidth - PDF_FIT_HORIZONTAL_PADDING - PDF_PAGE_BORDER_WIDTH, 96);
|
|
1130
1107
|
return pageWidth ? clampScale(availableWidth / pageWidth) : 1;
|
|
1131
1108
|
};
|
|
1132
1109
|
const fitToWidth = (source = 'user', notifyViewState = true) => {
|
|
1133
1110
|
if (!pdfContext.viewer) {
|
|
1134
1111
|
return;
|
|
1135
1112
|
}
|
|
1113
|
+
userScrollIntentUntil = 0;
|
|
1114
|
+
suppressProgrammaticScrollEvents();
|
|
1136
1115
|
autoFitWidth = true;
|
|
1137
1116
|
setScale(getFitWidthScale(pdfContext.viewer), 'zoom-reset', source, notifyViewState);
|
|
1138
1117
|
void waitForPaint(targetWindow).then(() => {
|
|
@@ -1142,6 +1121,8 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1142
1121
|
};
|
|
1143
1122
|
const applyPdfFit = async (request) => {
|
|
1144
1123
|
var _a, _b, _c;
|
|
1124
|
+
userScrollIntentUntil = 0;
|
|
1125
|
+
activeFitRequest = { ...request };
|
|
1145
1126
|
if (!pdfContext.viewer || loadStatus !== 'ready') {
|
|
1146
1127
|
pendingFitRequest = request;
|
|
1147
1128
|
return {
|
|
@@ -1155,13 +1136,20 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1155
1136
|
}
|
|
1156
1137
|
const pageSize = getPageSizeAtScaleOne(pdfContext.viewer);
|
|
1157
1138
|
const mode = request.mode === 'auto' ? 'width' : request.mode;
|
|
1139
|
+
const fitViewport = resolvePdfFitViewportSize({
|
|
1140
|
+
containerWidth: container.clientWidth,
|
|
1141
|
+
containerHeight: container.clientHeight,
|
|
1142
|
+
fallbackWidth: targetWindow.innerWidth,
|
|
1143
|
+
fallbackHeight: targetWindow.innerHeight,
|
|
1144
|
+
request,
|
|
1145
|
+
});
|
|
1158
1146
|
const scale = resolveFileViewerFitScale({
|
|
1159
1147
|
mode,
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1148
|
+
// The core request measures the whole viewer root. PDF's scroll
|
|
1149
|
+
// container is the actual visible document area after the navigation
|
|
1150
|
+
// pane, so prefer it whenever it has been laid out.
|
|
1151
|
+
viewportWidth: fitViewport.width,
|
|
1152
|
+
viewportHeight: fitViewport.height,
|
|
1165
1153
|
contentWidth: pageSize.width,
|
|
1166
1154
|
contentHeight: pageSize.height,
|
|
1167
1155
|
currentScale,
|
|
@@ -1178,9 +1166,17 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1178
1166
|
provider: 'view-state',
|
|
1179
1167
|
};
|
|
1180
1168
|
}
|
|
1169
|
+
suppressProgrammaticScrollEvents();
|
|
1181
1170
|
autoFitWidth = request.mode === 'auto' || request.mode === 'width';
|
|
1182
|
-
|
|
1171
|
+
if (Math.abs(scale - currentScale) > 0.001) {
|
|
1172
|
+
setScale(scale, 'fit', request.source);
|
|
1173
|
+
}
|
|
1174
|
+
else {
|
|
1175
|
+
pdfContext.viewer.update();
|
|
1176
|
+
syncUi();
|
|
1177
|
+
}
|
|
1183
1178
|
await waitForPaint(targetWindow);
|
|
1179
|
+
suppressProgrammaticScrollEvents();
|
|
1184
1180
|
(_c = pdfContext.viewer) === null || _c === void 0 ? void 0 : _c.update();
|
|
1185
1181
|
const state = getPdfViewState();
|
|
1186
1182
|
return {
|
|
@@ -1193,22 +1189,49 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1193
1189
|
state,
|
|
1194
1190
|
};
|
|
1195
1191
|
};
|
|
1196
|
-
const
|
|
1197
|
-
if (!
|
|
1192
|
+
const scheduleFitAfterResize = () => {
|
|
1193
|
+
if (!pdfContext.viewer) {
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
if ((activeFitRequest === null || activeFitRequest === void 0 ? void 0 : activeFitRequest.resize) === 'initial') {
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
if (!activeFitRequest && !autoFitWidth) {
|
|
1198
1200
|
return;
|
|
1199
1201
|
}
|
|
1200
1202
|
targetWindow.cancelAnimationFrame(fitFrame);
|
|
1201
|
-
fitFrame = targetWindow.requestAnimationFrame(() =>
|
|
1203
|
+
fitFrame = targetWindow.requestAnimationFrame(() => {
|
|
1204
|
+
if (activeFitRequest) {
|
|
1205
|
+
void applyPdfFit({ ...activeFitRequest, source: 'viewer' });
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
fitToWidth('viewer');
|
|
1209
|
+
});
|
|
1202
1210
|
};
|
|
1203
1211
|
const zoomIn = (source = 'user') => {
|
|
1204
|
-
|
|
1212
|
+
markFitInteraction(source);
|
|
1205
1213
|
setScale(currentScale + SCALE_STEP, 'zoom-in', source);
|
|
1206
1214
|
};
|
|
1207
1215
|
const zoomOut = (source = 'user') => {
|
|
1208
|
-
|
|
1216
|
+
markFitInteraction(source);
|
|
1209
1217
|
setScale(currentScale - SCALE_STEP, 'zoom-out', source);
|
|
1210
1218
|
};
|
|
1219
|
+
const reapplyFitAfterLayout = (source, notifyViewState = true) => {
|
|
1220
|
+
if (activeFitRequest) {
|
|
1221
|
+
if (activeFitRequest.resize === 'initial') {
|
|
1222
|
+
return false;
|
|
1223
|
+
}
|
|
1224
|
+
void applyPdfFit({ ...activeFitRequest, source });
|
|
1225
|
+
return true;
|
|
1226
|
+
}
|
|
1227
|
+
if (autoFitWidth) {
|
|
1228
|
+
fitToWidth(source, notifyViewState);
|
|
1229
|
+
return true;
|
|
1230
|
+
}
|
|
1231
|
+
return false;
|
|
1232
|
+
};
|
|
1211
1233
|
const applyRotation = (rotation, action = 'rotation-change', source = 'viewer', notifyViewState = true) => {
|
|
1234
|
+
markFitInteraction(source);
|
|
1212
1235
|
const normalized = normalizeRotation(rotation);
|
|
1213
1236
|
currentRotation = normalized;
|
|
1214
1237
|
pdfThumbnails.clear();
|
|
@@ -1220,8 +1243,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1220
1243
|
pdfContext.viewer.pagesRotation = normalized;
|
|
1221
1244
|
void waitForPaint(targetWindow).then(() => {
|
|
1222
1245
|
var _a;
|
|
1223
|
-
if (
|
|
1224
|
-
fitToWidth(source, notifyViewState);
|
|
1246
|
+
if (reapplyFitAfterLayout(source, notifyViewState)) {
|
|
1225
1247
|
if (notifyViewState) {
|
|
1226
1248
|
emitViewStateChange(action, source);
|
|
1227
1249
|
}
|
|
@@ -1247,6 +1269,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1247
1269
|
if (!pdfContext.viewer || !pageCount) {
|
|
1248
1270
|
return;
|
|
1249
1271
|
}
|
|
1272
|
+
markFitInteraction(source);
|
|
1250
1273
|
const nextPage = Math.min(pageCount, Math.max(1, pageNumber));
|
|
1251
1274
|
runWithStableHorizontalScroll(() => {
|
|
1252
1275
|
pdfContext.viewer.currentPageNumber = nextPage;
|
|
@@ -1261,12 +1284,12 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1261
1284
|
if (!navigationEnabled) {
|
|
1262
1285
|
return;
|
|
1263
1286
|
}
|
|
1287
|
+
markFitInteraction(source);
|
|
1264
1288
|
navVisible = !navVisible;
|
|
1265
1289
|
syncUi();
|
|
1266
1290
|
void waitForPaint(targetWindow).then(() => {
|
|
1267
1291
|
var _a;
|
|
1268
|
-
if (
|
|
1269
|
-
fitToWidth(source, notifyViewState);
|
|
1292
|
+
if (reapplyFitAfterLayout(source, notifyViewState)) {
|
|
1270
1293
|
return;
|
|
1271
1294
|
}
|
|
1272
1295
|
(_a = pdfContext.viewer) === null || _a === void 0 ? void 0 : _a.update();
|
|
@@ -1276,6 +1299,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1276
1299
|
}
|
|
1277
1300
|
};
|
|
1278
1301
|
const setNavMode = (mode, source = 'user', notifyViewState = true) => {
|
|
1302
|
+
markFitInteraction(source);
|
|
1279
1303
|
navMode = mode;
|
|
1280
1304
|
syncUi();
|
|
1281
1305
|
if (notifyViewState) {
|
|
@@ -1403,7 +1427,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1403
1427
|
`width:${formatCssPixels(pageWidth)}`,
|
|
1404
1428
|
`height:${formatCssPixels(pageHeight)}`,
|
|
1405
1429
|
].join(';');
|
|
1406
|
-
pagesHtml.push(`<section class="pdf-export-page viewer-print-page" style="${pageStyle}" aria-label="${escapeAttribute(pageTitle)}"><img src="${canvas.toDataURL('image/png')}" alt="${escapeAttribute(pageTitle)}" /></section>`);
|
|
1430
|
+
pagesHtml.push(`<section class="pdf-export-page viewer-print-page" data-viewer-print-page-index="${pageNumber - 1}" style="${pageStyle}" aria-label="${escapeAttribute(pageTitle)}"><img src="${canvas.toDataURL('image/png')}" alt="${escapeAttribute(pageTitle)}" /></section>`);
|
|
1407
1431
|
canvas.width = 0;
|
|
1408
1432
|
canvas.height = 0;
|
|
1409
1433
|
(_b = (_a = page).cleanup) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
@@ -1458,7 +1482,6 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1458
1482
|
var _a;
|
|
1459
1483
|
applyRotation(currentRotation, 'rotation-change', 'viewer', false);
|
|
1460
1484
|
loadStatus = 'ready';
|
|
1461
|
-
fitToWidth('viewer', false);
|
|
1462
1485
|
scheduleLegacyPageDimensionPatch();
|
|
1463
1486
|
syncUi();
|
|
1464
1487
|
(_a = context === null || context === void 0 ? void 0 : context.onProgressiveRender) === null || _a === void 0 ? void 0 : _a.call(context);
|
|
@@ -1477,6 +1500,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1477
1500
|
void applyPdfFit(fitRequest);
|
|
1478
1501
|
}
|
|
1479
1502
|
else {
|
|
1503
|
+
fitToWidth('viewer', false);
|
|
1480
1504
|
emitViewStateChange('init', 'viewer');
|
|
1481
1505
|
}
|
|
1482
1506
|
}
|
|
@@ -1657,6 +1681,7 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1657
1681
|
}
|
|
1658
1682
|
(_c = context === null || context === void 0 ? void 0 : context.registerExportAdapter) === null || _c === void 0 ? void 0 : _c.call(context, {
|
|
1659
1683
|
includeDocumentStyles: false,
|
|
1684
|
+
getPrintMaskPages: () => Array.from(root.querySelectorAll('.pdfViewer .page')),
|
|
1660
1685
|
printStyle: buildPdfPrintStyle,
|
|
1661
1686
|
toHtml: renderPdfPagesForExport,
|
|
1662
1687
|
});
|
|
@@ -1699,11 +1724,12 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1699
1724
|
return getPdfZoomState();
|
|
1700
1725
|
},
|
|
1701
1726
|
resetZoom: () => {
|
|
1702
|
-
|
|
1727
|
+
markFitInteraction('api');
|
|
1728
|
+
setScale(1, 'zoom-reset', 'api');
|
|
1703
1729
|
return getPdfZoomState();
|
|
1704
1730
|
},
|
|
1705
1731
|
setZoom: scale => {
|
|
1706
|
-
|
|
1732
|
+
markFitInteraction('api');
|
|
1707
1733
|
setScale(scale, 'zoom-change', 'api');
|
|
1708
1734
|
return getPdfZoomState();
|
|
1709
1735
|
},
|
|
@@ -1722,14 +1748,21 @@ export default async function renderPdf(buffer, target, context) {
|
|
|
1722
1748
|
nextPageButton.addEventListener('click', () => goToPage(currentPage + 1, 'page-step', 'user'));
|
|
1723
1749
|
zoomOutButton.addEventListener('click', () => zoomOut('user'));
|
|
1724
1750
|
zoomInButton.addEventListener('click', () => zoomIn('user'));
|
|
1725
|
-
scaleButton.addEventListener('click', () =>
|
|
1751
|
+
scaleButton.addEventListener('click', () => {
|
|
1752
|
+
activeFitRequest = null;
|
|
1753
|
+
fitToWidth('user');
|
|
1754
|
+
});
|
|
1726
1755
|
rotateLeftButton.addEventListener('click', () => applyRotation(currentRotation - 90, 'rotate-left', 'user'));
|
|
1727
1756
|
rotateRightButton.addEventListener('click', () => applyRotation(currentRotation + 90, 'rotate-right', 'user'));
|
|
1728
1757
|
pagesTab.addEventListener('click', () => setNavMode('pages', 'user'));
|
|
1729
1758
|
outlineTab.addEventListener('click', () => setNavMode('outline', 'user'));
|
|
1759
|
+
container.addEventListener('wheel', recordUserScrollIntent, { passive: true });
|
|
1760
|
+
container.addEventListener('touchstart', recordUserScrollIntent, { passive: true });
|
|
1761
|
+
container.addEventListener('pointerdown', recordUserScrollIntent, { passive: true });
|
|
1762
|
+
container.addEventListener('keydown', recordUserScrollIntent);
|
|
1730
1763
|
container.addEventListener('scroll', scheduleScrollViewStateChange, { passive: true });
|
|
1731
1764
|
if (targetWindow.ResizeObserver) {
|
|
1732
|
-
resizeObserver = new targetWindow.ResizeObserver(() =>
|
|
1765
|
+
resizeObserver = new targetWindow.ResizeObserver(() => scheduleFitAfterResize());
|
|
1733
1766
|
resizeObserver.observe(container);
|
|
1734
1767
|
}
|
|
1735
1768
|
syncUi();
|
package/dist/pdfFit.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FileViewerFitRequest } from '@file-viewer/core';
|
|
2
|
+
export declare const PDF_FIT_MIN_VIEWPORT_SIZE = 96;
|
|
3
|
+
export declare const PDF_FIT_HORIZONTAL_PADDING = 28;
|
|
4
|
+
export declare const PDF_PAGE_BORDER_WIDTH = 18;
|
|
5
|
+
export interface ResolvePdfFitViewportSizeInput {
|
|
6
|
+
containerWidth: number;
|
|
7
|
+
containerHeight: number;
|
|
8
|
+
fallbackWidth: number;
|
|
9
|
+
fallbackHeight: number;
|
|
10
|
+
request: Pick<FileViewerFitRequest, 'viewportWidth' | 'viewportHeight' | 'padding'>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolves the PDF page viewport after the navigation pane has been laid out.
|
|
14
|
+
* Core request dimensions already exclude fit.padding; live container and
|
|
15
|
+
* window fallback dimensions do not, so only those branches subtract it.
|
|
16
|
+
*/
|
|
17
|
+
export declare const resolvePdfFitViewportSize: ({ containerWidth, containerHeight, fallbackWidth, fallbackHeight, request, }: ResolvePdfFitViewportSizeInput) => {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
};
|
package/dist/pdfFit.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const PDF_FIT_MIN_VIEWPORT_SIZE = 96;
|
|
2
|
+
export const PDF_FIT_HORIZONTAL_PADDING = 28;
|
|
3
|
+
export const PDF_PAGE_BORDER_WIDTH = 18;
|
|
4
|
+
const normalizePadding = (padding) => (Number.isFinite(padding) && Number(padding) > 0 ? Number(padding) : 0);
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the PDF page viewport after the navigation pane has been laid out.
|
|
7
|
+
* Core request dimensions already exclude fit.padding; live container and
|
|
8
|
+
* window fallback dimensions do not, so only those branches subtract it.
|
|
9
|
+
*/
|
|
10
|
+
export const resolvePdfFitViewportSize = ({ containerWidth, containerHeight, fallbackWidth, fallbackHeight, request, }) => {
|
|
11
|
+
const padding = normalizePadding(request.padding);
|
|
12
|
+
const requestWidth = Number(request.viewportWidth) || 0;
|
|
13
|
+
const requestHeight = Number(request.viewportHeight) || 0;
|
|
14
|
+
const hasContainerWidth = containerWidth > 0;
|
|
15
|
+
const hasContainerHeight = containerHeight > 0;
|
|
16
|
+
const width = hasContainerWidth
|
|
17
|
+
? containerWidth - padding * 2
|
|
18
|
+
: requestWidth || fallbackWidth - padding * 2;
|
|
19
|
+
const height = hasContainerHeight
|
|
20
|
+
? containerHeight - padding * 2
|
|
21
|
+
: requestHeight || fallbackHeight - padding * 2;
|
|
22
|
+
return {
|
|
23
|
+
width: Math.max(PDF_FIT_MIN_VIEWPORT_SIZE, width - PDF_FIT_HORIZONTAL_PADDING - PDF_PAGE_BORDER_WIDTH),
|
|
24
|
+
height: Math.max(PDF_FIT_MIN_VIEWPORT_SIZE, height - PDF_PAGE_BORDER_WIDTH),
|
|
25
|
+
};
|
|
26
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@file-viewer/renderer-pdf",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.29",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Standalone PDF renderer plugin for Flyfish File Viewer powered by PDF.js.",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"LICENSE"
|
|
55
55
|
],
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@file-viewer/core": "2.1.
|
|
57
|
+
"@file-viewer/core": "2.1.29",
|
|
58
58
|
"@fontsource-variable/noto-sans-sc": "5.2.10",
|
|
59
59
|
"pdf-lib": "1.17.1",
|
|
60
60
|
"pdfjs-dist": "5.4.624"
|