@nypl/web-reader 4.1.0 → 4.3.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/esm/index.js CHANGED
@@ -34516,8 +34516,8 @@ var FONT_DETAILS = {
34516
34516
  },
34517
34517
  "sans-serif": {
34518
34518
  heading: "Sans-serif font",
34519
- body: "Helvetica",
34520
- token: "sansSerif",
34519
+ body: "Roboto",
34520
+ token: "body",
34521
34521
  fontWeight: "regular"
34522
34522
  },
34523
34523
  "open-dyslexic": {
@@ -34866,18 +34866,6 @@ import React42 from "react";
34866
34866
  var Fonts = () => /* @__PURE__ */ React42.createElement(Global, {
34867
34867
  styles: `
34868
34868
  /* latin */
34869
- @font-face {
34870
- font-family: 'Helvetica';
34871
- src: url('Helvetica.eot');
34872
- src: local('Helvetica'),
34873
- url('Helvetica.eot?#iefix') format('embedded-opentype'),
34874
- url('Helvetica.woff2') format('woff2'),
34875
- url('Helvetica.woff') format('woff'),
34876
- url('Helvetica.ttf') format('truetype');
34877
- font-weight: normal;
34878
- font-style: normal;
34879
- font-display: swap;
34880
- }
34881
34869
  @font-face {
34882
34870
  font-family: 'OpenDyslexic';
34883
34871
  font-style: normal;
@@ -34887,29 +34875,6 @@ var Fonts = () => /* @__PURE__ */ React42.createElement(Global, {
34887
34875
  url('/fonts/opendyslexic/opendyslexic-regular-webfont.woff')
34888
34876
  format('woff');
34889
34877
  }
34890
- @font-face {
34891
- font-family: 'robotoregular';
34892
- src: url('Roboto-Regular-webfont.eot');
34893
- src: url('Roboto-Regular-webfont.eot?#iefix') format('embedded-opentype'),
34894
- url('Roboto-Regular-webfont.woff2') format('woff2'),
34895
- url('Roboto-Regular-webfont.woff') format('woff'),
34896
- url('Roboto-Regular-webfont.ttf') format('truetype'),
34897
- url('Roboto-Regular-webfont.svg#robotoregular') format('svg');
34898
- font-weight: normal;
34899
- font-style: normal;
34900
- }
34901
- @font-face {
34902
- font-family: 'robotolight';
34903
- src: url('Roboto-Light-webfont.eot');
34904
- src: url('Roboto-Light-webfont.eot?#iefix') format('embedded-opentype'),
34905
- url('Roboto-Light-webfont.woff2') format('woff2'),
34906
- url('Roboto-Light-webfont.woff') format('woff'),
34907
- url('Roboto-Light-webfont.ttf') format('truetype'),
34908
- url('Roboto-Light-webfont.svg#robotolight') format('svg');
34909
- font-weight: normal;
34910
- font-style: normal;
34911
-
34912
- }
34913
34878
  `
34914
34879
  });
34915
34880
  var fonts_default = Fonts;
@@ -34984,7 +34949,6 @@ var typography3 = {
34984
34949
  body: "Roboto, -apple-system, BlinkMacSystemFont, system-ui, sans-serif",
34985
34950
  heading: "Roboto, -apple-system, BlinkMacSystemFont, system-ui, sans-serif",
34986
34951
  serif: `'Georgia', serif`,
34987
- sansSerif: `'Helvetica', 'Arial', serif`,
34988
34952
  opendyslexic: `'OpenDyslexic', sans-serif`
34989
34953
  }
34990
34954
  };
@@ -35574,7 +35538,12 @@ var variantSolid6 = (getColor4) => (props) => {
35574
35538
  const bgColor = getColor4("ui.gray.light-warm", "ui.black", "ui.sepia");
35575
35539
  const bgColorActive = getColor4("ui.gray.active", "ui.gray.x-dark", "ui.sepiaChecked");
35576
35540
  const color3 = getColor4("gray.800", "ui.white", "gray.800");
35577
- const _focus = { bgColor: bgColorActive, color: color3 };
35541
+ const _focus = {
35542
+ bgColor: bgColorActive,
35543
+ color: color3,
35544
+ ring: "2px",
35545
+ ringInset: "inset"
35546
+ };
35578
35547
  const _hover = {
35579
35548
  bgColor: bgColorActive,
35580
35549
  color: color3,
@@ -35586,7 +35555,7 @@ var variantSolid6 = (getColor4) => (props) => {
35586
35555
  return {
35587
35556
  border: "none",
35588
35557
  borderColor: "gray.100",
35589
- height: "48px",
35558
+ height: "45px",
35590
35559
  transition: "none",
35591
35560
  fontSize: 0,
35592
35561
  letterSpacing: 1,
@@ -35613,6 +35582,9 @@ var variantSettings = (getColor4) => (props) => {
35613
35582
  width: [8, 16, 36],
35614
35583
  fontSize: [0, 0, 2],
35615
35584
  whiteSpace: ["normal", "normal", "nowrap"],
35585
+ p: {
35586
+ textAlign: "center"
35587
+ },
35616
35588
  _active: {
35617
35589
  bgColor
35618
35590
  },
@@ -35621,7 +35593,8 @@ var variantSettings = (getColor4) => (props) => {
35621
35593
  bgColor: checkedBgColor,
35622
35594
  borderBottomColor: checkedBgColor,
35623
35595
  p: {
35624
- textDecoration: "underline"
35596
+ textDecoration: "underline",
35597
+ textUnderlinePosition: "under"
35625
35598
  }
35626
35599
  },
35627
35600
  _hover: {
@@ -35652,7 +35625,23 @@ function getTheme3(colorMode = "day") {
35652
35625
 
35653
35626
  // src/ui/ToggleButton.tsx
35654
35627
  function ToggleButton(props) {
35655
- const _a = props, { children, colorMode, icon, iconFill, label, value } = _a, rest = __objRest(_a, ["children", "colorMode", "icon", "iconFill", "label", "value"]);
35628
+ const _a = props, {
35629
+ children,
35630
+ colorMode,
35631
+ icon,
35632
+ iconFill,
35633
+ label,
35634
+ value,
35635
+ isChecked
35636
+ } = _a, rest = __objRest(_a, [
35637
+ "children",
35638
+ "colorMode",
35639
+ "icon",
35640
+ "iconFill",
35641
+ "label",
35642
+ "value",
35643
+ "isChecked"
35644
+ ]);
35656
35645
  const { getInputProps, getCheckboxProps } = useRadio(props);
35657
35646
  const input = getInputProps();
35658
35647
  const checkbox = getCheckboxProps();
@@ -35679,7 +35668,7 @@ function ToggleButton(props) {
35679
35668
  }
35680
35669
  var FontToggleButton = (props) => {
35681
35670
  return /* @__PURE__ */ React43.createElement(ToggleButton, __spreadValues({
35682
- fontSize: [-1, -1, 0],
35671
+ fontSize: [-2, -2, -1, -1, 0],
35683
35672
  py: 6
35684
35673
  }, props));
35685
35674
  };
@@ -35694,7 +35683,8 @@ var ColorModeToggleButton = (_a) => {
35694
35683
  _checked: {
35695
35684
  bgColor,
35696
35685
  p: {
35697
- textDecoration: "underline"
35686
+ textDecoration: "underline",
35687
+ textUnderlinePosition: "under"
35698
35688
  }
35699
35689
  }
35700
35690
  }
@@ -35907,28 +35897,31 @@ function HtmlSettings(props) {
35907
35897
  }), /* @__PURE__ */ React48.createElement(FontToggleButton, {
35908
35898
  value: "sans-serif",
35909
35899
  label: "Sans-Serif",
35910
- fontFamily: "sansSerif",
35900
+ fontFamily: "body",
35911
35901
  fontWeight: "regular"
35912
35902
  }), /* @__PURE__ */ React48.createElement(FontToggleButton, {
35913
35903
  value: "open-dyslexic",
35914
35904
  label: "Dyslexia",
35915
35905
  fontFamily: "opendyslexic",
35916
35906
  fontWeight: "regular"
35917
- })), /* @__PURE__ */ React48.createElement(Stack, {
35907
+ })), /* @__PURE__ */ React48.createElement(Box, {
35918
35908
  bgColor: checkedButtonBgColor,
35919
- px: 7,
35920
- py: 5
35909
+ display: "flex",
35910
+ flexDirection: "column",
35911
+ px: [3, 3, 7],
35912
+ py: [4, 4, 5]
35921
35913
  }, /* @__PURE__ */ React48.createElement(Heading, {
35922
35914
  as: "h3",
35923
35915
  color: buttonTextColor,
35924
- pb: "10px",
35916
+ pb: [1.5, 1.5, 2.5],
35925
35917
  fontSize: 2,
35926
35918
  fontWeight: "light"
35927
35919
  }, FONT_DETAILS[fontFamily].heading), /* @__PURE__ */ React48.createElement(Text, {
35928
35920
  color: buttonTextColor,
35929
35921
  fontFamily: FONT_DETAILS[fontFamily].token,
35930
35922
  fontSize: -1,
35931
- fontWeight: FONT_DETAILS[fontFamily].fontWeight
35923
+ fontWeight: FONT_DETAILS[fontFamily].fontWeight,
35924
+ margin: 0
35932
35925
  }, FONT_DETAILS[fontFamily].body)), /* @__PURE__ */ React48.createElement(ToggleGroup_default, {
35933
35926
  value: colorMode,
35934
35927
  label: "reading theme options",
@@ -36038,31 +36031,35 @@ function SettingsCard(props) {
36038
36031
  const paginationValue = ((_b = (_a = props.state) == null ? void 0 : _a.settings) == null ? void 0 : _b.isScrolling) ? "scrolling" : "paginated";
36039
36032
  return /* @__PURE__ */ React49.createElement(React49.Fragment, null, /* @__PURE__ */ React49.createElement(Popover, {
36040
36033
  gutter: 0,
36034
+ closeOnBlur: true,
36041
36035
  placement: "bottom-start",
36042
36036
  isOpen,
36043
- onOpen: open,
36044
36037
  onClose: close,
36038
+ onOpen: open,
36045
36039
  autoFocus: true,
36046
36040
  preventOverflow: true,
36047
36041
  strategy: "fixed"
36048
36042
  }, /* @__PURE__ */ React49.createElement(PopoverTrigger, null, /* @__PURE__ */ React49.createElement(Button_default, {
36043
+ "aria-label": "Settings",
36049
36044
  onClick: open,
36045
+ onMouseDown: (e) => e.preventDefault(),
36050
36046
  border: "none",
36051
- "aria-label": "Settings",
36052
- leftIcon: /* @__PURE__ */ React49.createElement(Icon, {
36053
- as: ReaderSettings_default,
36054
- w: 6,
36055
- h: 6,
36056
- fill: iconFill
36057
- })
36058
- }, /* @__PURE__ */ React49.createElement(Text, {
36047
+ gap: [0, 0, 2]
36048
+ }, /* @__PURE__ */ React49.createElement(Icon, {
36049
+ as: ReaderSettings_default,
36050
+ fill: iconFill,
36051
+ w: 6,
36052
+ h: 6
36053
+ }), /* @__PURE__ */ React49.createElement(Text, {
36059
36054
  variant: "headerNav"
36060
36055
  }, "Settings"))), /* @__PURE__ */ React49.createElement(PopoverContent, {
36061
36056
  overflow: "hidden",
36062
36057
  bgColor: contentBgColor,
36063
- borderRadius: "0 0 4px 4px",
36064
- boxShadow: "0 4px 4px -2px #424242",
36065
- width: "inherit",
36058
+ borderColor: "ui.gray.disabled",
36059
+ borderRadius: "0 0 2px 2px",
36060
+ filter: "drop-shadow(0 1px 2px #00000040)",
36061
+ width: ["90vw", "90vw", "inherit"],
36062
+ marginRight: [4, 4, 4, 0],
36066
36063
  maxWidth: "100vw"
36067
36064
  }, /* @__PURE__ */ React49.createElement(PopoverBody, {
36068
36065
  p: 0
@@ -36941,7 +36938,7 @@ function Header(props) {
36941
36938
  bg: mainBgColor
36942
36939
  }, headerLeft != null ? headerLeft : /* @__PURE__ */ React53.createElement(DefaultHeaderLeft, null), /* @__PURE__ */ React53.createElement(HStack, {
36943
36940
  ml: "auto",
36944
- spacing: 1
36941
+ spacing: 0
36945
36942
  }, /* @__PURE__ */ React53.createElement(TableOfContent, {
36946
36943
  containerRef,
36947
36944
  navigator: navigator2,
@@ -36950,14 +36947,17 @@ function Header(props) {
36950
36947
  "aria-expanded": isFullscreen,
36951
36948
  "aria-label": "Toggle full screen",
36952
36949
  border: "none",
36950
+ bgColor: mainBgColor,
36951
+ gap: [0, 0, 2],
36953
36952
  onClick: toggleFullScreen2,
36954
- leftIcon: /* @__PURE__ */ React53.createElement(Icon, {
36955
- as: isFullscreen ? ToggleFullScreenExit_default : ToggleFullScreen_default,
36956
- fill: iconFill,
36957
- w: 6,
36958
- h: 6
36959
- })
36960
- }, /* @__PURE__ */ React53.createElement(Text, {
36953
+ _active: { bgColor: mainBgColor },
36954
+ _focus: { bgColor: mainBgColor, ring: "2px", ringInset: "inset" }
36955
+ }, /* @__PURE__ */ React53.createElement(Icon, {
36956
+ as: isFullscreen ? ToggleFullScreenExit_default : ToggleFullScreen_default,
36957
+ fill: iconFill,
36958
+ w: 6,
36959
+ h: 6
36960
+ }), /* @__PURE__ */ React53.createElement(Text, {
36961
36961
  variant: "headerNav"
36962
36962
  }, isFullscreen ? "Full screen exit" : "Full screen"))));
36963
36963
  }
@@ -36974,7 +36974,7 @@ var HeaderWrapper = React53.forwardRef((_a, ref) => {
36974
36974
  zIndex: "sticky",
36975
36975
  alignContent: "space-between",
36976
36976
  alignItems: "center",
36977
- px: 8,
36977
+ px: [0, 0, 8],
36978
36978
  borderBottom: "1px solid",
36979
36979
  borderColor: "gray.100"
36980
36980
  }, rest), children);
@@ -40496,81 +40496,10 @@ function LoadingSkeleton({
40496
40496
  }));
40497
40497
  }
40498
40498
 
40499
- // src/PdfReader/index.tsx
40499
+ // src/PdfReader/lib.ts
40500
40500
  var IFRAME_WRAPPER_ID = "iframe-wrapper";
40501
40501
  var SCALE_STEP = 0.1;
40502
40502
  var START_QUERY = "start";
40503
- function pdfReducer(state2, action) {
40504
- switch (action.type) {
40505
- case "ARGS_CHANGED": {
40506
- return {
40507
- state: "ACTIVE",
40508
- settings: DEFAULT_SETTINGS,
40509
- resourceIndex: 0,
40510
- resource: null,
40511
- pageNumber: 1,
40512
- numPages: null,
40513
- scale: 1,
40514
- pdfWidth: 0,
40515
- pdfHeight: 0,
40516
- pageHeight: void 0,
40517
- pageWidth: void 0,
40518
- atStart: true,
40519
- atEnd: false
40520
- };
40521
- }
40522
- case "SET_CURRENT_RESOURCE":
40523
- return __spreadProps(__spreadValues({}, state2), {
40524
- resource: null,
40525
- resourceIndex: action.index,
40526
- pageNumber: action.shouldNavigateToEnd ? -1 : 1,
40527
- numPages: null
40528
- });
40529
- case "RESOURCE_FETCH_SUCCESS":
40530
- return __spreadProps(__spreadValues({}, state2), {
40531
- resource: action.resource
40532
- });
40533
- case "PDF_PARSED":
40534
- return __spreadProps(__spreadValues({}, state2), {
40535
- numPages: action.numPages,
40536
- pageNumber: state2.pageNumber === -1 ? action.numPages : state2.pageNumber
40537
- });
40538
- case "NAVIGATE_PAGE":
40539
- return __spreadProps(__spreadValues({}, state2), {
40540
- pageNumber: action.pageNum
40541
- });
40542
- case "SET_SCROLL":
40543
- if (state2.state !== "ACTIVE") {
40544
- return handleInvalidTransition(state2, action);
40545
- }
40546
- return __spreadProps(__spreadValues({}, state2), {
40547
- settings: __spreadProps(__spreadValues({}, state2.settings), {
40548
- isScrolling: action.isScrolling
40549
- })
40550
- });
40551
- case "SET_SCALE":
40552
- return __spreadProps(__spreadValues({}, state2), {
40553
- scale: action.scale
40554
- });
40555
- case "PAGE_LOAD_SUCCESS":
40556
- return __spreadProps(__spreadValues({}, state2), {
40557
- pdfWidth: action.width,
40558
- pdfHeight: action.height,
40559
- pageWidth: action.width,
40560
- pageHeight: action.height
40561
- });
40562
- case "RESIZE_PAGE":
40563
- return __spreadProps(__spreadValues({}, state2), {
40564
- pageWidth: action.width,
40565
- pageHeight: action.height
40566
- });
40567
- case "BOOK_BOUNDARY_CHANGED":
40568
- return __spreadProps(__spreadValues({}, state2), {
40569
- atStart: action.atStart,
40570
- atEnd: action.atEnd
40571
- });
40572
- }
40573
- }
40574
40503
  var getResourceUrl = (index, readingOrder) => {
40575
40504
  if (!readingOrder || !readingOrder.length) {
40576
40505
  throw new Error("A manifest has been returned, but has no reading order");
@@ -40581,19 +40510,197 @@ var loadResource = (resourceUrl, proxyUrl) => __async(void 0, null, function* ()
40581
40510
  const url = proxyUrl ? `${proxyUrl}${encodeURIComponent(resourceUrl)}` : resourceUrl;
40582
40511
  const response = yield fetch(url, { mode: "cors" });
40583
40512
  const array = new Uint8Array(yield response.arrayBuffer());
40584
- console.log("proxied", url, response);
40585
40513
  if (!response.ok) {
40586
40514
  throw new Error("Response not Ok for URL: " + url);
40587
40515
  }
40588
40516
  return array;
40589
40517
  });
40590
- var getStartPage = (resourceUrl) => {
40591
- const params = new URL(resourceUrl).searchParams;
40518
+ function getIndexFromHref(href, manifest) {
40519
+ var _a;
40520
+ const input = new URL(href);
40521
+ const index = (_a = manifest == null ? void 0 : manifest.readingOrder) == null ? void 0 : _a.findIndex((link2) => {
40522
+ return doHrefsMatch(link2.href, input);
40523
+ });
40524
+ if (index < 0) {
40525
+ throw new Error(`Cannot find resource in readingOrder: ${href}`);
40526
+ }
40527
+ return index;
40528
+ }
40529
+ function doHrefsMatch(href1, href2) {
40530
+ const input1 = new URL(href1);
40531
+ const input2 = new URL(href2);
40532
+ return input1.pathname === input2.pathname && input1.hostname === input2.hostname && input1.protocol === input2.protocol;
40533
+ }
40534
+ var getStartPageFromHref = (href) => {
40535
+ const params = new URL(href).searchParams;
40592
40536
  const startPage = params.get(START_QUERY);
40593
- return startPage ? parseInt(startPage) : 1;
40537
+ return startPage ? parseInt(startPage) : void 0;
40538
+ };
40539
+ var getPageNumberFromHref = (href) => {
40540
+ const hash4 = new URL(href).hash;
40541
+ try {
40542
+ const strPageNumber = hash4.replace("#page=", "");
40543
+ if (!strPageNumber || strPageNumber === "NaN")
40544
+ return void 0;
40545
+ const pageNumber = parseInt(strPageNumber);
40546
+ return pageNumber;
40547
+ } catch (e) {
40548
+ console.warn(`Failed to parse page number from hash ${hash4}`);
40549
+ return void 0;
40550
+ }
40594
40551
  };
40552
+
40553
+ // src/PdfReader/reducer.ts
40554
+ function makePdfReducer(args) {
40555
+ if (!args)
40556
+ return (state2, _action) => state2;
40557
+ const { manifest } = args;
40558
+ return function reducer(state2, action) {
40559
+ var _a, _b, _c;
40560
+ if (state2.state !== "ACTIVE" && action.type !== "ARGS_CHANGED") {
40561
+ return handleInvalidTransition(state2, action);
40562
+ }
40563
+ function goToLocation(index, page = 1) {
40564
+ const shouldResetResource = state2.resourceIndex !== index;
40565
+ const href = manifest.readingOrder[index].href;
40566
+ const startPage = getStartPageFromHref(href);
40567
+ const isNavigatingToEnd = page === -1;
40568
+ const requestedPageIsBeforeStartPage = startPage && page < startPage;
40569
+ const pageNumberToNavigateTo = !isNavigatingToEnd && requestedPageIsBeforeStartPage ? startPage : page;
40570
+ const newState = __spreadProps(__spreadValues({}, state2), {
40571
+ resourceIndex: index,
40572
+ pageNumber: pageNumberToNavigateTo
40573
+ });
40574
+ if (shouldResetResource) {
40575
+ return __spreadProps(__spreadValues({}, newState), {
40576
+ resource: null,
40577
+ numPages: null,
40578
+ rendered: false,
40579
+ pageHeight: void 0,
40580
+ pageWidth: void 0,
40581
+ pdfHeight: 0,
40582
+ pdfWidth: 0
40583
+ });
40584
+ }
40585
+ return newState;
40586
+ }
40587
+ switch (action.type) {
40588
+ case "ARGS_CHANGED": {
40589
+ return {
40590
+ state: "ACTIVE",
40591
+ settings: DEFAULT_SETTINGS,
40592
+ resourceIndex: 0,
40593
+ resource: null,
40594
+ pageNumber: 1,
40595
+ numPages: null,
40596
+ scale: 1,
40597
+ pdfWidth: 0,
40598
+ pdfHeight: 0,
40599
+ pageHeight: void 0,
40600
+ pageWidth: void 0,
40601
+ atStart: true,
40602
+ atEnd: false,
40603
+ rendered: false
40604
+ };
40605
+ }
40606
+ case "GO_FORWARD": {
40607
+ if ((_a = state2.settings) == null ? void 0 : _a.isScrolling) {
40608
+ const atEndOfBook2 = state2.resourceIndex === args.manifest.readingOrder.length - 1;
40609
+ if (atEndOfBook2)
40610
+ return state2;
40611
+ return goToLocation(state2.resourceIndex + 1);
40612
+ }
40613
+ if (!state2.numPages)
40614
+ return state2;
40615
+ const atEndOfResource = state2.pageNumber === state2.numPages;
40616
+ const atEndOfBook = state2.resourceIndex === args.manifest.readingOrder.length - 1;
40617
+ if (atEndOfResource) {
40618
+ if (atEndOfBook)
40619
+ return state2;
40620
+ return goToLocation(state2.resourceIndex + 1);
40621
+ }
40622
+ return goToLocation(state2.resourceIndex, state2.pageNumber + 1);
40623
+ }
40624
+ case "GO_BACKWARD": {
40625
+ if ((_b = state2.settings) == null ? void 0 : _b.isScrolling) {
40626
+ const atStartOfBook2 = state2.resourceIndex === 0;
40627
+ if (atStartOfBook2)
40628
+ return state2;
40629
+ return goToLocation(state2.resourceIndex - 1);
40630
+ }
40631
+ if (!state2.numPages)
40632
+ return state2;
40633
+ const atStartOfResource = isStartOfResource(state2.pageNumber, args.manifest.readingOrder[state2.resourceIndex].href);
40634
+ const atStartOfBook = state2.resourceIndex === 0;
40635
+ if (atStartOfResource) {
40636
+ if (atStartOfBook)
40637
+ return state2;
40638
+ return __spreadValues({}, goToLocation(state2.resourceIndex - 1, -1));
40639
+ }
40640
+ return goToLocation(state2.resourceIndex, state2.pageNumber - 1);
40641
+ }
40642
+ case "GO_TO_HREF": {
40643
+ const resourceIndex = getIndexFromHref(action.href, args.manifest);
40644
+ const startPage = getStartPageFromHref(action.href);
40645
+ const pageNumber = getPageNumberFromHref(action.href);
40646
+ const page = (_c = pageNumber != null ? pageNumber : startPage) != null ? _c : 1;
40647
+ return goToLocation(resourceIndex, page);
40648
+ }
40649
+ case "RESOURCE_FETCH_SUCCESS":
40650
+ return __spreadProps(__spreadValues({}, state2), {
40651
+ resource: action.resource
40652
+ });
40653
+ case "PDF_PARSED":
40654
+ return __spreadProps(__spreadValues({}, state2), {
40655
+ numPages: action.numPages,
40656
+ pageNumber: state2.pageNumber === -1 ? action.numPages : state2.pageNumber
40657
+ });
40658
+ case "SET_SCROLL":
40659
+ if (state2.state !== "ACTIVE") {
40660
+ return handleInvalidTransition(state2, action);
40661
+ }
40662
+ return __spreadProps(__spreadValues({}, state2), {
40663
+ settings: __spreadProps(__spreadValues({}, state2.settings), {
40664
+ isScrolling: action.isScrolling
40665
+ })
40666
+ });
40667
+ case "SET_SCALE":
40668
+ return __spreadProps(__spreadValues({}, state2), {
40669
+ scale: action.scale
40670
+ });
40671
+ case "PAGE_LOAD_SUCCESS":
40672
+ return __spreadProps(__spreadValues({}, state2), {
40673
+ rendered: true,
40674
+ pdfWidth: action.width,
40675
+ pdfHeight: action.height,
40676
+ pageWidth: action.width,
40677
+ pageHeight: action.height
40678
+ });
40679
+ case "RESIZE_PAGE":
40680
+ return __spreadProps(__spreadValues({}, state2), {
40681
+ pageWidth: action.width,
40682
+ pageHeight: action.height
40683
+ });
40684
+ case "BOOK_BOUNDARY_CHANGED":
40685
+ return __spreadProps(__spreadValues({}, state2), {
40686
+ atStart: action.atStart,
40687
+ atEnd: action.atEnd
40688
+ });
40689
+ }
40690
+ };
40691
+ }
40692
+ function handleInvalidTransition(state2, action) {
40693
+ console.trace(`Inavlid state transition attempted: ${state2} with ${action.type}`);
40694
+ return state2;
40695
+ }
40696
+ function isStartOfResource(pageNumber, resourceHref) {
40697
+ const startPage = getStartPageFromHref(resourceHref);
40698
+ return pageNumber === (startPage != null ? startPage : 1);
40699
+ }
40700
+
40701
+ // src/PdfReader/index.tsx
40595
40702
  function usePdfReader(args) {
40596
- var _a;
40703
+ var _a, _b, _c, _d;
40597
40704
  if (args == null ? void 0 : args.pdfWorkerSrc) {
40598
40705
  pdfjs4.GlobalWorkerOptions.workerSrc = args.pdfWorkerSrc;
40599
40706
  }
@@ -40607,7 +40714,7 @@ function usePdfReader(args) {
40607
40714
  height = DEFAULT_HEIGHT,
40608
40715
  growWhenScrolling = DEFAULT_SHOULD_GROW_WHEN_SCROLLING
40609
40716
  } = args != null ? args : {};
40610
- const [state2, dispatch] = React71.useReducer(pdfReducer, {
40717
+ const [state2, dispatch] = React71.useReducer(makePdfReducer(args), {
40611
40718
  state: "INACTIVE",
40612
40719
  resourceIndex: 0,
40613
40720
  resource: null,
@@ -40620,11 +40727,11 @@ function usePdfReader(args) {
40620
40727
  pageWidth: void 0,
40621
40728
  atStart: true,
40622
40729
  atEnd: false,
40623
- settings: void 0
40730
+ settings: void 0,
40731
+ rendered: false
40624
40732
  });
40625
40733
  const isFetching = !state2.resource;
40626
40734
  const isParsed = typeof state2.numPages === "number";
40627
- const isSinglePDF = manifest && (manifest == null ? void 0 : manifest.readingOrder.length) === 1;
40628
40735
  const [containerRef, containerSize] = useMeasure();
40629
40736
  React71.useEffect(() => {
40630
40737
  if (!webpubManifestUrl || !manifest) {
@@ -40677,96 +40784,43 @@ function usePdfReader(args) {
40677
40784
  resizePage(state2.pdfWidth, state2.pdfHeight, containerSize);
40678
40785
  }, [containerSize, state2.pdfWidth, state2.pdfHeight, resizePage]);
40679
40786
  React71.useEffect(() => {
40680
- var _a2;
40681
- if (!manifest || state2.state !== "ACTIVE")
40682
- return;
40683
- if (isSinglePDF && state2.settings.isScrolling) {
40684
- dispatch({
40685
- type: "BOOK_BOUNDARY_CHANGED",
40686
- atStart: true,
40687
- atEnd: true
40688
- });
40689
- } else {
40690
- const isFirstResource = state2.resourceIndex === 0;
40691
- const isResourceStart = isFirstResource && state2.pageNumber === 1;
40692
- const isLastResource = state2.resourceIndex === ((_a2 = manifest == null ? void 0 : manifest.readingOrder) == null ? void 0 : _a2.length) - 1;
40693
- const isResourceEnd = isLastResource && state2.pageNumber === state2.numPages || state2.settings.isScrolling && isLastResource;
40694
- dispatch({
40695
- type: "BOOK_BOUNDARY_CHANGED",
40696
- atStart: isResourceStart,
40697
- atEnd: isResourceEnd
40698
- });
40699
- }
40787
+ var _a2, _b2, _c2;
40788
+ const isScrolling = (_a2 = state2.settings) == null ? void 0 : _a2.isScrolling;
40789
+ const isFirstResource = state2.resourceIndex === 0;
40790
+ const isFirstResourceStart = isFirstResource && state2.pageNumber === 1;
40791
+ const showPrevButton = isScrolling ? !isFirstResource : !isFirstResourceStart;
40792
+ const isLastResource = state2.resourceIndex === ((_c2 = (_b2 = manifest == null ? void 0 : manifest.readingOrder) == null ? void 0 : _b2.length) != null ? _c2 : 1) - 1;
40793
+ const isLastResourceEnd = isLastResource && state2.pageNumber === state2.numPages;
40794
+ const showNextButton = isScrolling ? !isLastResource : !isLastResourceEnd;
40795
+ dispatch({
40796
+ type: "BOOK_BOUNDARY_CHANGED",
40797
+ atStart: !showPrevButton,
40798
+ atEnd: !showNextButton
40799
+ });
40700
40800
  }, [
40701
- manifest,
40702
- state2.state,
40703
- state2.settings,
40704
- state2.numPages,
40801
+ (_a = manifest == null ? void 0 : manifest.readingOrder) == null ? void 0 : _a.length,
40705
40802
  state2.pageNumber,
40706
40803
  state2.resourceIndex,
40707
- isSinglePDF
40804
+ (_b = state2.settings) == null ? void 0 : _b.isScrolling,
40805
+ state2.numPages
40708
40806
  ]);
40709
- const goForward = React71.useCallback(() => __async(this, null, function* () {
40807
+ React71.useEffect(() => {
40710
40808
  var _a2;
40711
- if (!state2.numPages)
40809
+ if (!((_a2 = state2.settings) == null ? void 0 : _a2.isScrolling))
40712
40810
  return;
40713
- if (state2.state !== "ACTIVE")
40811
+ if (!state2.rendered)
40714
40812
  return;
40715
- if (state2.pageNumber < state2.numPages && !state2.settings.isScrolling) {
40716
- dispatch({
40717
- type: "NAVIGATE_PAGE",
40718
- pageNum: state2.pageNumber + 1
40719
- });
40720
- } else if (manifest && manifest.readingOrder && state2.resourceIndex < ((_a2 = manifest == null ? void 0 : manifest.readingOrder) == null ? void 0 : _a2.length) - 1) {
40721
- const nextIndex = state2.resourceIndex + 1;
40722
- dispatch({
40723
- type: "SET_CURRENT_RESOURCE",
40724
- index: nextIndex,
40725
- shouldNavigateToEnd: false
40726
- });
40727
- if (manifest == null ? void 0 : manifest.readingOrder[nextIndex]) {
40728
- const pageNum = getStartPage(manifest == null ? void 0 : manifest.readingOrder[nextIndex].href);
40729
- dispatch({
40730
- type: "NAVIGATE_PAGE",
40731
- pageNum
40732
- });
40733
- }
40734
- }
40735
- }), [
40736
- state2.state,
40737
- manifest,
40738
- state2.settings,
40739
- state2.numPages,
40740
- state2.pageNumber,
40741
- state2.resourceIndex
40742
- ]);
40813
+ process.nextTick(() => {
40814
+ const page = document.querySelector(`[data-page-number="${state2.pageNumber}"]`);
40815
+ page == null ? void 0 : page.scrollIntoView();
40816
+ });
40817
+ }, [state2.pageNumber, (_c = state2.settings) == null ? void 0 : _c.isScrolling, state2.rendered]);
40818
+ const goForward = React71.useCallback(() => __async(this, null, function* () {
40819
+ dispatch({ type: "GO_FORWARD" });
40820
+ }), []);
40743
40821
  const goBackward = React71.useCallback(() => __async(this, null, function* () {
40744
- if (!isParsed)
40745
- return;
40746
- if (state2.state !== "ACTIVE")
40747
- return;
40748
- const startPage = (manifest == null ? void 0 : manifest.readingOrder) && (manifest == null ? void 0 : manifest.readingOrder[state2.resourceIndex]) ? getStartPage(manifest == null ? void 0 : manifest.readingOrder[state2.resourceIndex].href) : 1;
40749
- if (state2.pageNumber > startPage && !state2.settings.isScrolling) {
40750
- dispatch({
40751
- type: "NAVIGATE_PAGE",
40752
- pageNum: state2.pageNumber - 1
40753
- });
40754
- } else if ((manifest == null ? void 0 : manifest.readingOrder) && state2.resourceIndex > 0) {
40755
- const nextIndex = state2.resourceIndex - 1;
40756
- dispatch({
40757
- type: "SET_CURRENT_RESOURCE",
40758
- index: nextIndex,
40759
- shouldNavigateToEnd: !state2.settings.isScrolling
40760
- });
40761
- }
40762
- }), [
40763
- manifest,
40764
- isParsed,
40765
- state2.state,
40766
- state2.settings,
40767
- state2.pageNumber,
40768
- state2.resourceIndex
40769
- ]);
40822
+ dispatch({ type: "GO_BACKWARD" });
40823
+ }), []);
40770
40824
  const setScroll = React71.useCallback((val) => __async(this, null, function* () {
40771
40825
  const isScrolling = val === "scrolling";
40772
40826
  dispatch({ type: "SET_SCROLL", isScrolling });
@@ -40784,30 +40838,8 @@ function usePdfReader(args) {
40784
40838
  });
40785
40839
  }), [state2.scale]);
40786
40840
  const goToPage = React71.useCallback((href) => __async(this, null, function* () {
40787
- const getIndexFromHref = (href2) => {
40788
- var _a2;
40789
- const index = (_a2 = manifest == null ? void 0 : manifest.readingOrder) == null ? void 0 : _a2.findIndex((link2) => {
40790
- return link2.href === href2;
40791
- });
40792
- if (index < 0) {
40793
- throw new Error("Cannot find resource in readingOrder");
40794
- }
40795
- return index;
40796
- };
40797
- const resourceIndex = getIndexFromHref(href);
40798
- dispatch({
40799
- type: "SET_CURRENT_RESOURCE",
40800
- index: resourceIndex,
40801
- shouldNavigateToEnd: false
40802
- });
40803
- if ((manifest == null ? void 0 : manifest.readingOrder) && (manifest == null ? void 0 : manifest.readingOrder[resourceIndex])) {
40804
- const startPage = getStartPage(manifest == null ? void 0 : manifest.readingOrder[resourceIndex].href);
40805
- dispatch({
40806
- type: "NAVIGATE_PAGE",
40807
- pageNum: startPage
40808
- });
40809
- }
40810
- }), [manifest == null ? void 0 : manifest.readingOrder]);
40841
+ dispatch({ type: "GO_TO_HREF", href });
40842
+ }), []);
40811
40843
  if (!webpubManifestUrl || !manifest)
40812
40844
  return null;
40813
40845
  if (state2.state === "INACTIVE" || isFetching) {
@@ -40841,7 +40873,7 @@ function usePdfReader(args) {
40841
40873
  resizePage(page.width, page.height, containerSize);
40842
40874
  }
40843
40875
  }
40844
- const shouldGrow = ((_a = state2.settings) == null ? void 0 : _a.isScrolling) && growWhenScrolling;
40876
+ const shouldGrow = ((_d = state2.settings) == null ? void 0 : _d.isScrolling) && growWhenScrolling;
40845
40877
  const finalHeight = shouldGrow ? "initial" : height;
40846
40878
  return {
40847
40879
  type: "PDF",
@@ -40893,10 +40925,6 @@ function usePdfReader(args) {
40893
40925
  }
40894
40926
  };
40895
40927
  }
40896
- function handleInvalidTransition(state2, action) {
40897
- console.trace(`Inavlid state transition attempted: ${state2} with ${action.type}`);
40898
- return state2;
40899
- }
40900
40928
 
40901
40929
  // src/HtmlReader/index.tsx
40902
40930
  import React79 from "react";
@@ -41935,9 +41963,9 @@ function useHtmlReader(args) {
41935
41963
  const numResources = manifest.readingOrder.length;
41936
41964
  const isFirstResource = resourceIndex === 0;
41937
41965
  const isLastResource = resourceIndex === numResources - 1;
41938
- const isStartOfResource = state2.location.locations.position === 1;
41966
+ const isStartOfResource2 = state2.location.locations.position === 1;
41939
41967
  const isEndOfResource = state2.location.locations.remainingPositions === 0;
41940
- const atStart = isFirstResource && isStartOfResource;
41968
+ const atStart = isFirstResource && isStartOfResource2;
41941
41969
  const atEnd = isLastResource && isEndOfResource;
41942
41970
  return {
41943
41971
  type: "HTML",
@@ -42046,6 +42074,44 @@ function useWebReader(args) {
42046
42074
  throw new Error(`No reader was initialized for the webpub with url: ${webpubManifestUrl} and type: ${readerType}.`);
42047
42075
  }
42048
42076
 
42077
+ // src/PdfReader/addTocToManifest.tsx
42078
+ function addTocToManifest(manifest, getResource, pdfWorkerSrc) {
42079
+ return __async(this, null, function* () {
42080
+ const pdfUrl = manifest.readingOrder[0].href;
42081
+ const pdfData = yield getResource(pdfUrl);
42082
+ try {
42083
+ pdfjs4.GlobalWorkerOptions.workerSrc = pdfWorkerSrc;
42084
+ const pdf = yield pdfjs4.getDocument(pdfData).promise;
42085
+ const outline5 = yield pdf.getOutline();
42086
+ const tocPromises = outline5.map((chapter) => __async(this, null, function* () {
42087
+ const dest = chapter.dest;
42088
+ if (dest && dest.length > 0) {
42089
+ const ref = dest[0];
42090
+ const pageIndex = yield pdf.getPageIndex(ref);
42091
+ if (typeof pageIndex !== "number")
42092
+ return void 0;
42093
+ if (pageIndex) {
42094
+ const link2 = {
42095
+ title: chapter.title,
42096
+ href: `${pdfUrl}#page=${pageIndex + 1}`,
42097
+ children: []
42098
+ };
42099
+ return link2;
42100
+ }
42101
+ }
42102
+ return void 0;
42103
+ }));
42104
+ const toc = (yield Promise.all(tocPromises)).filter((item) => !!item);
42105
+ if (toc.length > 0) {
42106
+ manifest.toc = toc;
42107
+ }
42108
+ } catch (e) {
42109
+ console.error(e);
42110
+ }
42111
+ return manifest;
42112
+ });
42113
+ }
42114
+
42049
42115
  // src/index.tsx
42050
42116
  var WebReaderWithoutBoundary = (_a) => {
42051
42117
  var _b = _a, {
@@ -42086,6 +42152,7 @@ export {
42086
42152
  LOCAL_STORAGE_SETTINGS_KEY,
42087
42153
  ReadiumWebpubContext,
42088
42154
  WebReaderWithoutBoundary,
42155
+ addTocToManifest,
42089
42156
  clearWebReaderLocalStorage,
42090
42157
  src_default as default,
42091
42158
  getTheme3 as getTheme,