@nypl/web-reader 5.0.0 → 5.0.1

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.mjs CHANGED
@@ -1373,7 +1373,7 @@ import * as React29 from "react";
1373
1373
  // src/constants.ts
1374
1374
  var ReadiumWebpubContext = "http://readium.org/webpub/default.jsonld";
1375
1375
  var IS_DEV = process.env.NODE_ENV === "development";
1376
- var HEADER_HEIGHT = 48;
1376
+ var HEADER_HEIGHT = 49;
1377
1377
  var CHROME_HEIGHT = HEADER_HEIGHT;
1378
1378
  var DEFAULT_HEIGHT = `calc(100vh - ${CHROME_HEIGHT}px)`;
1379
1379
  var DEFAULT_SHOULD_GROW_WHEN_SCROLLING = true;
@@ -1413,6 +1413,7 @@ var FONT_DETAILS = {
1413
1413
  fontWeight: "regular"
1414
1414
  }
1415
1415
  };
1416
+ var IN_VIEW_DELAY_MS = 150;
1416
1417
  var LOCAL_STORAGE_SETTINGS_KEY = "web-reader-settings";
1417
1418
  var LOCAL_STORAGE_LOCATIONS_KEY = "web-reader-locations";
1418
1419
  var MAIN_CONTENT_ID = "mainContent";
@@ -7946,6 +7947,7 @@ var ScrollPage = ({
7946
7947
  width,
7947
7948
  height,
7948
7949
  onLoadSuccess,
7950
+ onPageRef,
7949
7951
  placeholderHeight,
7950
7952
  placeholderWidth,
7951
7953
  allowInView,
@@ -7965,8 +7967,9 @@ var ScrollPage = ({
7965
7967
  (el) => {
7966
7968
  if (typeof loadRef === "function") loadRef(el);
7967
7969
  if (typeof visibilityRef === "function") visibilityRef(el);
7970
+ if (onPageRef) onPageRef(pageNumber, el);
7968
7971
  },
7969
- [loadRef, visibilityRef]
7972
+ [loadRef, onPageRef, pageNumber, visibilityRef]
7970
7973
  );
7971
7974
  const handleLoadSuccess = React48.useCallback(
7972
7975
  (page) => {
@@ -8075,7 +8078,24 @@ function usePdfReader(args) {
8075
8078
  const isFetching = !state2.resource;
8076
8079
  const isParsed = typeof state2.numPages === "number";
8077
8080
  const [containerRef, containerSize] = useMeasure();
8078
- const [pageHeight, setPageHeight] = React50.useState(0);
8081
+ const documentContainerRef = React50.useRef(null);
8082
+ const pageRefs = React50.useRef(/* @__PURE__ */ new Map());
8083
+ const setPageRef = React50.useCallback(
8084
+ (pageNumber, element) => {
8085
+ if (element) {
8086
+ pageRefs.current.set(pageNumber, element);
8087
+ return;
8088
+ }
8089
+ pageRefs.current.delete(pageNumber);
8090
+ },
8091
+ []
8092
+ );
8093
+ const scrollState = React50.useRef({
8094
+ ratios: /* @__PURE__ */ new Map(),
8095
+ lastVisiblePage: state2.pageNumber,
8096
+ isInViewUpdate: false,
8097
+ lastProgrammaticNavAt: 0
8098
+ });
8079
8099
  React50.useEffect(() => {
8080
8100
  if (!webpubManifestUrl || !manifest) {
8081
8101
  return dispatch({ type: "ARGS_CHANGED", args: void 0 });
@@ -8148,13 +8168,6 @@ function usePdfReader(args) {
8148
8168
  var _a2;
8149
8169
  resizePage(containerSize, state2.fitMode, (_a2 = state2.rotation) != null ? _a2 : 0, state2.scale);
8150
8170
  }, [containerSize, resizePage, state2.fitMode, state2.rotation, state2.scale]);
8151
- React50.useEffect(() => {
8152
- if (pageHeight === 0 && state2.pdfWidth && state2.pdfHeight) {
8153
- const aspectRatio = state2.pdfHeight / state2.pdfWidth;
8154
- const initialPageHeight = (containerSize.width - READER_MARGIN) * aspectRatio;
8155
- setPageHeight(Math.round(initialPageHeight));
8156
- }
8157
- }, [state2.pdfWidth, state2.pdfHeight, containerSize.width, pageHeight]);
8158
8171
  React50.useEffect(() => {
8159
8172
  var _a2, _b2;
8160
8173
  const isFirstResource = state2.resourceIndex === 0;
@@ -8177,25 +8190,40 @@ function usePdfReader(args) {
8177
8190
  ]);
8178
8191
  React50.useEffect(() => {
8179
8192
  var _a2;
8180
- if (!((_a2 = state2.settings) == null ? void 0 : _a2.isScrolling)) return;
8181
- if (!state2.rendered) return;
8193
+ if (!((_a2 = state2.settings) == null ? void 0 : _a2.isScrolling) || !state2.rendered) return;
8182
8194
  if (scrollState.current.isInViewUpdate) {
8183
8195
  scrollState.current.isInViewUpdate = false;
8184
8196
  return;
8185
8197
  }
8186
- process.nextTick(() => {
8187
- const page = document.querySelector(
8188
- `[data-page-number="${state2.pageNumber}"]`
8189
- );
8190
- page == null ? void 0 : page.scrollIntoView();
8191
- });
8198
+ const documentContainer = documentContainerRef.current;
8199
+ const pageRef = pageRefs.current.get(state2.pageNumber);
8200
+ if (documentContainer && pageRef) {
8201
+ const containerRect = documentContainer.getBoundingClientRect();
8202
+ const pageRect = pageRef.getBoundingClientRect();
8203
+ documentContainer.scrollTo({
8204
+ top: documentContainer.scrollTop + (pageRect.top - containerRect.top)
8205
+ });
8206
+ }
8192
8207
  }, [state2.pageNumber, (_c = state2.settings) == null ? void 0 : _c.isScrolling, state2.rendered]);
8208
+ const beginProgrammaticNavigation = React50.useCallback(
8209
+ (pendingPage) => {
8210
+ const currentScrollState = scrollState.current;
8211
+ currentScrollState.lastVisiblePage = pendingPage;
8212
+ currentScrollState.lastProgrammaticNavAt = Date.now();
8213
+ currentScrollState.ratios.clear();
8214
+ },
8215
+ []
8216
+ );
8193
8217
  const goForward = React50.useCallback(() => __async(null, null, function* () {
8218
+ beginProgrammaticNavigation(
8219
+ state2.numPages ? Math.min(state2.pageNumber + 1, state2.numPages) : state2.pageNumber + 1
8220
+ );
8194
8221
  dispatch({ type: "GO_FORWARD" });
8195
- }), []);
8222
+ }), [beginProgrammaticNavigation, state2.numPages, state2.pageNumber]);
8196
8223
  const goBackward = React50.useCallback(() => __async(null, null, function* () {
8224
+ beginProgrammaticNavigation(Math.max(1, state2.pageNumber - 1));
8197
8225
  dispatch({ type: "GO_BACKWARD" });
8198
- }), []);
8226
+ }), [beginProgrammaticNavigation, state2.pageNumber]);
8199
8227
  const setScroll = React50.useCallback(
8200
8228
  (val) => __async(null, null, function* () {
8201
8229
  const isScrolling = val === "scrolling";
@@ -8221,42 +8249,38 @@ function usePdfReader(args) {
8221
8249
  const goToPage = React50.useCallback((href) => __async(null, null, function* () {
8222
8250
  dispatch({ type: "GO_TO_HREF", href });
8223
8251
  }), []);
8224
- const goToPageNumber = React50.useCallback((page) => {
8225
- dispatch({ type: "GO_TO_PAGE", page });
8226
- }, []);
8252
+ const goToPageNumber = React50.useCallback(
8253
+ (page) => {
8254
+ beginProgrammaticNavigation(page);
8255
+ dispatch({ type: "GO_TO_PAGE", page });
8256
+ },
8257
+ [beginProgrammaticNavigation]
8258
+ );
8227
8259
  const setFitMode = React50.useCallback((mode) => {
8228
8260
  dispatch({ type: "SET_FIT_MODE", fitMode: mode });
8229
8261
  }, []);
8230
- const scrollState = React50.useRef({
8231
- ratios: /* @__PURE__ */ new Map(),
8232
- lastVisiblepage: state2.pageNumber,
8233
- hasScrolled: false,
8234
- isInViewUpdate: false
8235
- });
8236
8262
  const onInView = React50.useCallback(
8237
8263
  (pageNum, ratio) => {
8238
8264
  var _a2;
8239
8265
  const currentScrollState = scrollState.current;
8240
- if (!((_a2 = state2.settings) == null ? void 0 : _a2.isScrolling)) return;
8241
- currentScrollState.ratios.set(pageNum, ratio);
8242
- if (!currentScrollState.hasScrolled && state2.pageNumber === 1) {
8243
- const container = document.querySelector(
8244
- `#${MAIN_CONTENT_ID} .react-pdf__Document`
8245
- );
8246
- if (container && container.scrollTop > 0)
8247
- currentScrollState.hasScrolled = true;
8248
- else return;
8266
+ if (!((_a2 = state2.settings) == null ? void 0 : _a2.isScrolling) || Date.now() - currentScrollState.lastProgrammaticNavAt < IN_VIEW_DELAY_MS)
8267
+ return;
8268
+ if (ratio <= 0) {
8269
+ currentScrollState.ratios.delete(pageNum);
8270
+ return;
8249
8271
  }
8250
- let mostVisiblePage = currentScrollState.lastVisiblepage;
8272
+ currentScrollState.ratios.set(pageNum, ratio);
8273
+ let mostVisiblePage = currentScrollState.lastVisiblePage;
8251
8274
  let maxRatio = -1;
8252
- currentScrollState.ratios.forEach((r, p) => {
8275
+ for (const [p, r] of currentScrollState.ratios) {
8253
8276
  if (r > maxRatio) {
8254
8277
  maxRatio = r;
8255
8278
  mostVisiblePage = p;
8256
8279
  }
8257
- });
8258
- if (mostVisiblePage !== currentScrollState.lastVisiblepage) {
8259
- currentScrollState.lastVisiblepage = mostVisiblePage;
8280
+ if (r > 0.8) break;
8281
+ }
8282
+ if (mostVisiblePage !== currentScrollState.lastVisiblePage) {
8283
+ currentScrollState.lastVisiblePage = mostVisiblePage;
8260
8284
  if (state2.pageNumber !== mostVisiblePage) {
8261
8285
  currentScrollState.isInViewUpdate = true;
8262
8286
  dispatch({ type: "PAGE_IN_VIEW", page: mostVisiblePage });
@@ -8323,7 +8347,7 @@ function usePdfReader(args) {
8323
8347
  tabIndex: -1,
8324
8348
  id: MAIN_CONTENT_ID,
8325
8349
  ref: containerRef,
8326
- height: pageHeight,
8350
+ height,
8327
8351
  sx: {
8328
8352
  ".react-pdf__Document": {
8329
8353
  width: "100%",
@@ -8342,7 +8366,8 @@ function usePdfReader(args) {
8342
8366
  {
8343
8367
  file: state2.resource,
8344
8368
  onLoadSuccess: onDocumentLoadSuccess,
8345
- onLoadError: onDocumentLoadError
8369
+ onLoadError: onDocumentLoadError,
8370
+ inputRef: documentContainerRef
8346
8371
  },
8347
8372
  isParsed && state2.numPages && /* @__PURE__ */ React50.createElement(React50.Fragment, null, state2.settings.isScrolling && Array.from(new Array(state2.numPages), (_, index) => {
8348
8373
  var _a2;
@@ -8360,7 +8385,8 @@ function usePdfReader(args) {
8360
8385
  allowInView: state2.rendered,
8361
8386
  onInView,
8362
8387
  fitMode: state2.fitMode,
8363
- rotate: (_a2 = state2.rotation) != null ? _a2 : 0
8388
+ rotate: (_a2 = state2.rotation) != null ? _a2 : 0,
8389
+ onPageRef: setPageRef
8364
8390
  }
8365
8391
  );
8366
8392
  }), !state2.settings.isScrolling && /* @__PURE__ */ React50.createElement(
@@ -8581,6 +8607,7 @@ export {
8581
8607
  DEFAULT_SHOULD_GROW_WHEN_SCROLLING,
8582
8608
  FONT_DETAILS,
8583
8609
  HEADER_HEIGHT,
8610
+ IN_VIEW_DELAY_MS,
8584
8611
  IS_DEV,
8585
8612
  LOCAL_STORAGE_LOCATIONS_KEY,
8586
8613
  LOCAL_STORAGE_SETTINGS_KEY,