@nypl/web-reader 1.1.1 → 1.2.2

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
@@ -13681,7 +13681,7 @@ var require_entry = __commonJS({
13681
13681
  });
13682
13682
 
13683
13683
  // src/index.tsx
13684
- import React101 from "react";
13684
+ import React102 from "react";
13685
13685
 
13686
13686
  // node_modules/@emotion/react/dist/emotion-react.browser.esm.js
13687
13687
  import { createElement as createElement2, useContext as useContext2, useRef, useLayoutEffect } from "react";
@@ -21262,8 +21262,8 @@ var pseudoSelectors = {
21262
21262
  _ltr: "[dir=ltr] &, &[dir=ltr]",
21263
21263
  _mediaDark: "@media (prefers-color-scheme: dark)",
21264
21264
  _mediaReduceMotion: "@media (prefers-reduced-motion: reduce)",
21265
- _dark: ".chakra-ui-dark &, [data-theme=dark] &, &[data-theme=dark]",
21266
- _light: ".chakra-ui-light &, [data-theme=light] &, &[data-theme=light]"
21265
+ _dark: ".chakra-ui-dark &:not([data-theme]),[data-theme=dark] &:not([data-theme]),&[data-theme=dark]",
21266
+ _light: ".chakra-ui-light &:not([data-theme]),[data-theme=light] &:not([data-theme]),&[data-theme=light]"
21267
21267
  };
21268
21268
  var pseudoPropNames = objectKeys(pseudoSelectors);
21269
21269
  var systemProps = (0, import_lodash.default)({}, background, border, color, flexbox, layout, filter2, ring2, interactivity, grid, others, position2, effect, space, scroll, typography2, textDecoration, transform8, list, transition);
@@ -39302,7 +39302,9 @@ function PdfSettings(props) {
39302
39302
  import * as React66 from "react";
39303
39303
  function HtmlSettings(props) {
39304
39304
  const { navigator: navigator2, readerState, paginationValue } = props;
39305
- const { fontFamily, colorMode } = readerState;
39305
+ if (!readerState.settings)
39306
+ return null;
39307
+ const { fontFamily, colorMode } = readerState.settings;
39306
39308
  const {
39307
39309
  setFontFamily,
39308
39310
  decreaseFontSize,
@@ -39376,11 +39378,11 @@ function HtmlSettings(props) {
39376
39378
 
39377
39379
  // src/ui/SettingsButton.tsx
39378
39380
  function SettingsCard(props) {
39379
- var _a;
39381
+ var _a, _b;
39380
39382
  const [isOpen, setIsOpen] = React67.useState(false);
39381
39383
  const open = () => setIsOpen(true);
39382
39384
  const close = () => setIsOpen(false);
39383
- const paginationValue = ((_a = props.state) == null ? void 0 : _a.isScrolling) ? "scrolling" : "paginated";
39385
+ const paginationValue = ((_b = (_a = props.state) == null ? void 0 : _a.settings) == null ? void 0 : _b.isScrolling) ? "scrolling" : "paginated";
39384
39386
  const contentBgColor = useColorModeValue_default("ui.white", "ui.black", "ui.white");
39385
39387
  return /* @__PURE__ */ React67.createElement(React67.Fragment, null, /* @__PURE__ */ React67.createElement(Popover, {
39386
39388
  placement: "bottom",
@@ -39882,7 +39884,7 @@ function createDescendantContext() {
39882
39884
  import * as React70 from "react";
39883
39885
  import React__default2, { useState as useState24, useCallback as useCallback24, useEffect as useEffect25, useRef as useRef23 } from "react";
39884
39886
 
39885
- // node_modules/@chakra-ui/hooks/dist/use-animation-state-5e0537c8.esm.js
39887
+ // node_modules/@chakra-ui/hooks/dist/use-animation-state-35233362.esm.js
39886
39888
  import * as React69 from "react";
39887
39889
  import { useState as useState22, useEffect as useEffect23 } from "react";
39888
39890
  var useSafeLayoutEffect4 = isBrowser4 ? React69.useLayoutEffect : React69.useEffect;
@@ -41004,6 +41006,12 @@ var FOOTER_HEIGHT = 48;
41004
41006
  var CHROME_HEIGHT = HEADER_HEIGHT + FOOTER_HEIGHT;
41005
41007
  var DEFAULT_HEIGHT = `calc(100vh - ${CHROME_HEIGHT}px)`;
41006
41008
  var DEFAULT_SHOULD_GROW_WHEN_SCROLLING = true;
41009
+ var DEFAULT_SETTINGS = {
41010
+ colorMode: "day",
41011
+ isScrolling: false,
41012
+ fontSize: 100,
41013
+ fontFamily: "publisher"
41014
+ };
41007
41015
 
41008
41016
  // src/ui/Header.tsx
41009
41017
  var DefaultHeaderLeft = () => {
@@ -41147,9 +41155,9 @@ var PageButton_default = PageButton;
41147
41155
 
41148
41156
  // src/ui/manager.tsx
41149
41157
  var ManagerUI = (props) => {
41150
- var _a;
41158
+ var _a, _b;
41151
41159
  return /* @__PURE__ */ React77.createElement(ThemeProvider3, {
41152
- theme: getTheme3((_a = props.state) == null ? void 0 : _a.colorMode)
41160
+ theme: getTheme3((_b = (_a = props.state) == null ? void 0 : _a.settings) == null ? void 0 : _b.colorMode)
41153
41161
  }, /* @__PURE__ */ React77.createElement(WebReaderContent, __spreadValues({}, props)));
41154
41162
  };
41155
41163
  var WebReaderContent = (_a) => {
@@ -41211,7 +41219,7 @@ var WebReaderContent = (_a) => {
41211
41219
  var manager_default = ManagerUI;
41212
41220
 
41213
41221
  // src/useWebReader.tsx
41214
- import React99 from "react";
41222
+ import React100 from "react";
41215
41223
 
41216
41224
  // src/utils/fetch.ts
41217
41225
  function fetchJson(url) {
@@ -44166,7 +44174,7 @@ if (isLocalFileSystem) {
44166
44174
  pdfjs4.GlobalWorkerOptions.workerSrc = "pdf.worker.js";
44167
44175
 
44168
44176
  // src/PdfReader/index.tsx
44169
- import * as React90 from "react";
44177
+ import * as React91 from "react";
44170
44178
 
44171
44179
  // src/PdfReader/useMeasure.tsx
44172
44180
  import * as React88 from "react";
@@ -44522,11 +44530,58 @@ var ScrollPage = ({
44522
44530
  };
44523
44531
  var ScrollPage_default = ScrollPage;
44524
44532
 
44533
+ // src/ui/LoadingSkeleton.tsx
44534
+ import React90 from "react";
44535
+ function LoadingSkeleton({
44536
+ height
44537
+ }) {
44538
+ return /* @__PURE__ */ React90.createElement(React90.Fragment, null, /* @__PURE__ */ React90.createElement(HeaderWrapper, null), /* @__PURE__ */ React90.createElement(Box, {
44539
+ padding: "6",
44540
+ bg: "white",
44541
+ mt: "7",
44542
+ height,
44543
+ "aria-label": "Loading book...",
44544
+ "aria-busy": "true",
44545
+ role: "progressbar"
44546
+ }, /* @__PURE__ */ React90.createElement(Flex, {
44547
+ justifyContent: "center"
44548
+ }, /* @__PURE__ */ React90.createElement(Skeleton, {
44549
+ height: "20px",
44550
+ mb: "7",
44551
+ w: "30%"
44552
+ })), /* @__PURE__ */ React90.createElement(SkeletonText, {
44553
+ mb: "7",
44554
+ noOfLines: 10,
44555
+ spacing: "4"
44556
+ }), /* @__PURE__ */ React90.createElement(SkeletonText, {
44557
+ mb: "7",
44558
+ noOfLines: 5,
44559
+ spacing: "4"
44560
+ })));
44561
+ }
44562
+
44525
44563
  // src/PdfReader/index.tsx
44526
44564
  var IFRAME_WRAPPER_ID = "iframe-wrapper";
44527
44565
  var SCALE_STEP = 0.1;
44528
44566
  function pdfReducer(state2, action) {
44529
44567
  switch (action.type) {
44568
+ case "ARGS_CHANGED": {
44569
+ return {
44570
+ state: "ACTIVE",
44571
+ settings: DEFAULT_SETTINGS,
44572
+ resourceIndex: 0,
44573
+ resource: null,
44574
+ pageNumber: 1,
44575
+ numPages: null,
44576
+ scale: 1,
44577
+ pdfWidth: 0,
44578
+ pdfHeight: 0,
44579
+ pageHeight: void 0,
44580
+ pageWidth: void 0,
44581
+ atStart: true,
44582
+ atEnd: false
44583
+ };
44584
+ }
44530
44585
  case "SET_CURRENT_RESOURCE":
44531
44586
  return __spreadProps(__spreadValues({}, state2), {
44532
44587
  resource: null,
@@ -44548,8 +44603,13 @@ function pdfReducer(state2, action) {
44548
44603
  pageNumber: action.pageNum
44549
44604
  });
44550
44605
  case "SET_SCROLL":
44606
+ if (state2.state !== "ACTIVE") {
44607
+ return handleInvalidTransition(state2, action);
44608
+ }
44551
44609
  return __spreadProps(__spreadValues({}, state2), {
44552
- isScrolling: action.isScrolling
44610
+ settings: __spreadProps(__spreadValues({}, state2.settings), {
44611
+ isScrolling: action.isScrolling
44612
+ })
44553
44613
  });
44554
44614
  case "SET_SCALE":
44555
44615
  return __spreadProps(__spreadValues({}, state2), {
@@ -44581,11 +44641,11 @@ var getResourceUrl = (index, readingOrder) => {
44581
44641
  return readingOrder[index].href;
44582
44642
  };
44583
44643
  var loadResource = (resourceUrl, proxyUrl) => __async(void 0, null, function* () {
44584
- const resource = proxyUrl + encodeURI(resourceUrl);
44585
- const response = yield fetch(resource, { mode: "cors" });
44644
+ const url = proxyUrl ? `${proxyUrl}${encodeURIComponent(resourceUrl)}` : resourceUrl;
44645
+ const response = yield fetch(url, { mode: "cors" });
44586
44646
  const array = new Uint8Array(yield response.arrayBuffer());
44587
44647
  if (!response.ok) {
44588
- throw new Error("Response not Ok for URL: " + resource);
44648
+ throw new Error("Response not Ok for URL: " + url);
44589
44649
  }
44590
44650
  return array;
44591
44651
  });
@@ -44598,33 +44658,57 @@ function usePdfReader(args) {
44598
44658
  webpubManifestUrl,
44599
44659
  manifest,
44600
44660
  proxyUrl,
44601
- readerSettings,
44661
+ getContent,
44662
+ injectables,
44663
+ injectablesFixed,
44602
44664
  height = DEFAULT_HEIGHT,
44603
44665
  growWhenScrolling = DEFAULT_SHOULD_GROW_WHEN_SCROLLING
44604
44666
  } = args != null ? args : {};
44605
- const [state2, dispatch] = React90.useReducer(pdfReducer, {
44606
- colorMode: "day",
44607
- isScrolling: (_a = readerSettings == null ? void 0 : readerSettings.isScrolling) != null ? _a : false,
44608
- fontSize: 16,
44609
- fontFamily: "sans-serif",
44667
+ const [state2, dispatch] = React91.useReducer(pdfReducer, {
44668
+ state: "INACTIVE",
44610
44669
  resourceIndex: 0,
44611
44670
  resource: null,
44612
44671
  pageNumber: 1,
44613
44672
  numPages: null,
44614
- currentTocUrl: null,
44615
44673
  scale: 1,
44616
44674
  pdfWidth: 0,
44617
44675
  pdfHeight: 0,
44618
44676
  pageHeight: void 0,
44619
44677
  pageWidth: void 0,
44620
44678
  atStart: true,
44621
- atEnd: false
44679
+ atEnd: false,
44680
+ settings: void 0
44622
44681
  });
44623
44682
  const isFetching = !state2.resource;
44624
44683
  const isParsed = typeof state2.numPages === "number";
44625
44684
  const isSinglePDF = manifest && (manifest == null ? void 0 : manifest.readingOrder.length) === 1;
44626
44685
  const [containerRef, containerSize] = useMeasure();
44627
- React90.useEffect(() => {
44686
+ React91.useEffect(() => {
44687
+ if (!webpubManifestUrl || !manifest) {
44688
+ return dispatch({ type: "ARGS_CHANGED", args: void 0 });
44689
+ }
44690
+ dispatch({
44691
+ type: "ARGS_CHANGED",
44692
+ args: {
44693
+ webpubManifestUrl,
44694
+ manifest,
44695
+ getContent,
44696
+ injectables,
44697
+ injectablesFixed,
44698
+ height,
44699
+ growWhenScrolling
44700
+ }
44701
+ });
44702
+ }, [
44703
+ webpubManifestUrl,
44704
+ manifest,
44705
+ getContent,
44706
+ injectables,
44707
+ injectablesFixed,
44708
+ height,
44709
+ growWhenScrolling
44710
+ ]);
44711
+ React91.useEffect(() => {
44628
44712
  if (!manifest)
44629
44713
  return;
44630
44714
  if (!manifest.readingOrder || !manifest.readingOrder.length) {
@@ -44638,7 +44722,7 @@ function usePdfReader(args) {
44638
44722
  });
44639
44723
  });
44640
44724
  }, [state2.resourceIndex, manifest, proxyUrl]);
44641
- const resizePage = React90.useCallback((pdfWidth, pdfHeight, containerSize2) => {
44725
+ const resizePage = React91.useCallback((pdfWidth, pdfHeight, containerSize2) => {
44642
44726
  const wRatio = pdfWidth / containerSize2.width;
44643
44727
  const hRatio = pdfHeight / containerSize2.height;
44644
44728
  const fitHorizontal = wRatio > hRatio;
@@ -44646,14 +44730,14 @@ function usePdfReader(args) {
44646
44730
  const height2 = !fitHorizontal ? Math.round(containerSize2.height) : void 0;
44647
44731
  dispatch({ type: "RESIZE_PAGE", width, height: height2 });
44648
44732
  }, []);
44649
- React90.useEffect(() => {
44733
+ React91.useEffect(() => {
44650
44734
  resizePage(state2.pdfWidth, state2.pdfHeight, containerSize);
44651
44735
  }, [containerSize, state2.pdfWidth, state2.pdfHeight, resizePage]);
44652
- React90.useEffect(() => {
44736
+ React91.useEffect(() => {
44653
44737
  var _a2;
44654
- if (!manifest)
44738
+ if (!manifest || state2.state !== "ACTIVE")
44655
44739
  return;
44656
- if (isSinglePDF && state2.isScrolling) {
44740
+ if (isSinglePDF && state2.settings.isScrolling) {
44657
44741
  dispatch({
44658
44742
  type: "BOOK_BOUNDARY_CHANGED",
44659
44743
  atStart: true,
@@ -44663,7 +44747,7 @@ function usePdfReader(args) {
44663
44747
  const isFirstResource = state2.resourceIndex === 0;
44664
44748
  const isResourceStart = isFirstResource && state2.pageNumber === 1;
44665
44749
  const isLastResource = state2.resourceIndex === ((_a2 = manifest == null ? void 0 : manifest.readingOrder) == null ? void 0 : _a2.length) - 1;
44666
- const isResourceEnd = isLastResource && state2.pageNumber === state2.numPages || state2.isScrolling && isLastResource;
44750
+ const isResourceEnd = isLastResource && state2.pageNumber === state2.numPages || state2.settings.isScrolling && isLastResource;
44667
44751
  dispatch({
44668
44752
  type: "BOOK_BOUNDARY_CHANGED",
44669
44753
  atStart: isResourceStart,
@@ -44672,17 +44756,20 @@ function usePdfReader(args) {
44672
44756
  }
44673
44757
  }, [
44674
44758
  manifest,
44675
- state2.isScrolling,
44759
+ state2.state,
44760
+ state2.settings,
44676
44761
  state2.numPages,
44677
44762
  state2.pageNumber,
44678
44763
  state2.resourceIndex,
44679
44764
  isSinglePDF
44680
44765
  ]);
44681
- const goForward = React90.useCallback(() => __async(this, null, function* () {
44766
+ const goForward = React91.useCallback(() => __async(this, null, function* () {
44682
44767
  var _a2;
44683
44768
  if (!state2.numPages)
44684
44769
  return;
44685
- if (state2.pageNumber < state2.numPages && !state2.isScrolling) {
44770
+ if (state2.state !== "ACTIVE")
44771
+ return;
44772
+ if (state2.pageNumber < state2.numPages && !state2.settings.isScrolling) {
44686
44773
  dispatch({
44687
44774
  type: "NAVIGATE_PAGE",
44688
44775
  pageNum: state2.pageNumber + 1
@@ -44696,16 +44783,19 @@ function usePdfReader(args) {
44696
44783
  });
44697
44784
  }
44698
44785
  }), [
44786
+ state2.state,
44699
44787
  manifest,
44700
- state2.isScrolling,
44788
+ state2.settings,
44701
44789
  state2.numPages,
44702
44790
  state2.pageNumber,
44703
44791
  state2.resourceIndex
44704
44792
  ]);
44705
- const goBackward = React90.useCallback(() => __async(this, null, function* () {
44793
+ const goBackward = React91.useCallback(() => __async(this, null, function* () {
44706
44794
  if (!isParsed)
44707
44795
  return;
44708
- if (state2.pageNumber > 1 && !state2.isScrolling) {
44796
+ if (state2.state !== "ACTIVE")
44797
+ return;
44798
+ if (state2.pageNumber > 1 && !state2.settings.isScrolling) {
44709
44799
  dispatch({
44710
44800
  type: "NAVIGATE_PAGE",
44711
44801
  pageNum: state2.pageNumber - 1
@@ -44715,33 +44805,34 @@ function usePdfReader(args) {
44715
44805
  dispatch({
44716
44806
  type: "SET_CURRENT_RESOURCE",
44717
44807
  index: nextIndex,
44718
- shouldNavigateToEnd: !state2.isScrolling
44808
+ shouldNavigateToEnd: !state2.settings.isScrolling
44719
44809
  });
44720
44810
  }
44721
44811
  }), [
44722
44812
  manifest,
44723
44813
  isParsed,
44724
- state2.isScrolling,
44814
+ state2.state,
44815
+ state2.settings,
44725
44816
  state2.pageNumber,
44726
44817
  state2.resourceIndex
44727
44818
  ]);
44728
- const setScroll = React90.useCallback((val) => __async(this, null, function* () {
44819
+ const setScroll = React91.useCallback((val) => __async(this, null, function* () {
44729
44820
  const isScrolling = val === "scrolling";
44730
44821
  dispatch({ type: "SET_SCROLL", isScrolling });
44731
44822
  }), []);
44732
- const zoomIn = React90.useCallback(() => __async(this, null, function* () {
44823
+ const zoomIn = React91.useCallback(() => __async(this, null, function* () {
44733
44824
  dispatch({
44734
44825
  type: "SET_SCALE",
44735
44826
  scale: state2.scale + SCALE_STEP
44736
44827
  });
44737
44828
  }), [state2.scale]);
44738
- const zoomOut = React90.useCallback(() => __async(this, null, function* () {
44829
+ const zoomOut = React91.useCallback(() => __async(this, null, function* () {
44739
44830
  dispatch({
44740
44831
  type: "SET_SCALE",
44741
44832
  scale: state2.scale - SCALE_STEP
44742
44833
  });
44743
44834
  }), [state2.scale]);
44744
- const goToPage = React90.useCallback((href) => __async(this, null, function* () {
44835
+ const goToPage = React91.useCallback((href) => __async(this, null, function* () {
44745
44836
  const getIndexFromHref = (href2) => {
44746
44837
  var _a2;
44747
44838
  const index = (_a2 = manifest == null ? void 0 : manifest.readingOrder) == null ? void 0 : _a2.findIndex((link) => {
@@ -44760,30 +44851,16 @@ function usePdfReader(args) {
44760
44851
  }), [manifest == null ? void 0 : manifest.readingOrder]);
44761
44852
  if (!webpubManifestUrl || !manifest)
44762
44853
  return null;
44763
- if (isFetching) {
44854
+ if (state2.state === "INACTIVE" || isFetching) {
44764
44855
  return {
44765
- type: "PDF",
44766
- isLoading: false,
44767
- content: /* @__PURE__ */ React90.createElement(Flex, {
44768
- as: "main",
44769
- tabIndex: -1,
44770
- id: "iframe-wrapper",
44771
- zIndex: "base",
44772
- alignItems: "center",
44773
- justifyContent: "center",
44774
- flex: "1 0 auto",
44856
+ type: null,
44857
+ isLoading: true,
44858
+ content: /* @__PURE__ */ React91.createElement(LoadingSkeleton, {
44775
44859
  height
44776
- }, "PDF is loading"),
44777
- state: state2,
44778
- manifest,
44779
- navigator: {
44780
- goForward,
44781
- goBackward,
44782
- zoomIn,
44783
- zoomOut,
44784
- setScroll,
44785
- goToPage
44786
- }
44860
+ }),
44861
+ navigator: null,
44862
+ manifest: null,
44863
+ state: null
44787
44864
  };
44788
44865
  }
44789
44866
  const onDocumentLoadSuccess = ({ numPages }) => {
@@ -44804,12 +44881,12 @@ function usePdfReader(args) {
44804
44881
  resizePage(page.width, page.height, containerSize);
44805
44882
  }
44806
44883
  }
44807
- const shouldGrow = state2.isScrolling && growWhenScrolling;
44884
+ const shouldGrow = ((_a = state2.settings) == null ? void 0 : _a.isScrolling) && growWhenScrolling;
44808
44885
  const finalHeight = shouldGrow ? "initial" : height;
44809
44886
  return {
44810
44887
  type: "PDF",
44811
44888
  isLoading: false,
44812
- content: /* @__PURE__ */ React90.createElement(Flex, {
44889
+ content: /* @__PURE__ */ React91.createElement(Flex, {
44813
44890
  as: "main",
44814
44891
  zIndex: "base",
44815
44892
  flex: "1 0 auto",
@@ -44819,16 +44896,16 @@ function usePdfReader(args) {
44819
44896
  id: IFRAME_WRAPPER_ID,
44820
44897
  ref: containerRef,
44821
44898
  height: finalHeight
44822
- }, /* @__PURE__ */ React90.createElement("style", null, `
44899
+ }, /* @__PURE__ */ React91.createElement("style", null, `
44823
44900
  .react-pdf__Document {
44824
44901
  height: calc(100vh - ${HEADER_HEIGHT + FOOTER_HEIGHT}px);
44825
44902
  overflow-x: hidden;
44826
44903
  overflow-y: auto;
44827
44904
  }
44828
- `), /* @__PURE__ */ React90.createElement(Document, {
44905
+ `), /* @__PURE__ */ React91.createElement(Document, {
44829
44906
  file: state2.resource,
44830
44907
  onLoadSuccess: onDocumentLoadSuccess
44831
- }, isParsed && state2.numPages && /* @__PURE__ */ React90.createElement(React90.Fragment, null, state2.isScrolling && Array.from(new Array(state2.numPages), (_, index) => /* @__PURE__ */ React90.createElement(ScrollPage_default, {
44908
+ }, isParsed && state2.numPages && /* @__PURE__ */ React91.createElement(React91.Fragment, null, state2.settings.isScrolling && Array.from(new Array(state2.numPages), (_, index) => /* @__PURE__ */ React91.createElement(ScrollPage_default, {
44832
44909
  key: `page_${index + 1}`,
44833
44910
  width: containerSize.width,
44834
44911
  placeholderHeight: state2.pdfHeight,
@@ -44836,13 +44913,13 @@ function usePdfReader(args) {
44836
44913
  scale: state2.scale,
44837
44914
  pageNumber: index + 1,
44838
44915
  onLoadSuccess: onRenderSuccess
44839
- })), !state2.isScrolling && /* @__PURE__ */ React90.createElement(ChakraPage_default, {
44916
+ })), !state2.settings.isScrolling && /* @__PURE__ */ React91.createElement(ChakraPage_default, {
44840
44917
  pageNumber: state2.pageNumber,
44841
44918
  onLoadSuccess: onRenderSuccess,
44842
44919
  width: state2.pageWidth,
44843
44920
  height: state2.pageHeight,
44844
44921
  scale: state2.scale,
44845
- loading: /* @__PURE__ */ React90.createElement(React90.Fragment, null)
44922
+ loading: /* @__PURE__ */ React91.createElement(React91.Fragment, null)
44846
44923
  })))),
44847
44924
  state: state2,
44848
44925
  manifest,
@@ -44856,39 +44933,13 @@ function usePdfReader(args) {
44856
44933
  }
44857
44934
  };
44858
44935
  }
44936
+ function handleInvalidTransition(state2, action) {
44937
+ console.trace(`Inavlid state transition attempted: ${state2} with ${action.type}`);
44938
+ return state2;
44939
+ }
44859
44940
 
44860
44941
  // src/HtmlReader/index.tsx
44861
- import React98 from "react";
44862
-
44863
- // src/ui/LoadingSkeleton.tsx
44864
- import React91 from "react";
44865
- function LoadingSkeleton({
44866
- height
44867
- }) {
44868
- return /* @__PURE__ */ React91.createElement(React91.Fragment, null, /* @__PURE__ */ React91.createElement(HeaderWrapper, null), /* @__PURE__ */ React91.createElement(Box, {
44869
- padding: "6",
44870
- bg: "white",
44871
- mt: "7",
44872
- height,
44873
- "aria-label": "Loading book...",
44874
- "aria-busy": "true",
44875
- role: "progressbar"
44876
- }, /* @__PURE__ */ React91.createElement(Flex, {
44877
- justifyContent: "center"
44878
- }, /* @__PURE__ */ React91.createElement(Skeleton, {
44879
- height: "20px",
44880
- mb: "7",
44881
- w: "30%"
44882
- })), /* @__PURE__ */ React91.createElement(SkeletonText, {
44883
- mb: "7",
44884
- noOfLines: 10,
44885
- spacing: "4"
44886
- }), /* @__PURE__ */ React91.createElement(SkeletonText, {
44887
- mb: "7",
44888
- noOfLines: 5,
44889
- spacing: "4"
44890
- })));
44891
- }
44942
+ import React99 from "react";
44892
44943
 
44893
44944
  // src/HtmlReader/lib.ts
44894
44945
  var FONT_SIZE_STEP = 4;
@@ -45051,11 +45102,60 @@ var familyToReadiumFamily = {
45051
45102
  "open-dyslexic": "opendyslexic"
45052
45103
  };
45053
45104
 
45054
- // src/HtmlReader/useLocationQuery.ts
45105
+ // src/utils/localstorage.ts
45055
45106
  import React92 from "react";
45107
+ var lsLocationKey = (identifier2) => `web-reader-location-${identifier2}`;
45108
+ function getLocalStorageLocation(identifier2) {
45109
+ const locationKey = lsLocationKey(identifier2);
45110
+ const item = localStorage.getItem(locationKey);
45111
+ if (item) {
45112
+ const record = JSON.parse(item);
45113
+ return record;
45114
+ }
45115
+ return void 0;
45116
+ }
45117
+ var LOCAL_STORAGE_SETTINGS_KEY = "web-reader-settings";
45118
+ function getLocalStorageSettings() {
45119
+ const item = localStorage.getItem(LOCAL_STORAGE_SETTINGS_KEY);
45120
+ if (item) {
45121
+ const settings = JSON.parse(item);
45122
+ return settings;
45123
+ }
45124
+ return void 0;
45125
+ }
45126
+ function useUpdateLocalStorage(identifier2, state2) {
45127
+ React92.useEffect(() => {
45128
+ if (!identifier2)
45129
+ return;
45130
+ const locationKey = lsLocationKey(identifier2);
45131
+ if (state2.location) {
45132
+ const record = {
45133
+ createdAt: Date.now(),
45134
+ location: state2.location
45135
+ };
45136
+ const val = JSON.stringify(record);
45137
+ localStorage.setItem(locationKey, val);
45138
+ }
45139
+ }, [state2.location, identifier2]);
45140
+ React92.useEffect(() => {
45141
+ if (!identifier2 || !state2.settings)
45142
+ return;
45143
+ const settings = {
45144
+ fontSize: state2.settings.fontSize,
45145
+ fontFamily: state2.settings.fontFamily,
45146
+ colorMode: state2.settings.colorMode,
45147
+ isScrolling: state2.settings.isScrolling
45148
+ };
45149
+ const val = JSON.stringify(settings);
45150
+ localStorage.setItem(LOCAL_STORAGE_SETTINGS_KEY, val);
45151
+ }, [state2.settings, identifier2]);
45152
+ }
45153
+
45154
+ // src/HtmlReader/useLocationQuery.ts
45155
+ import React93 from "react";
45056
45156
  var LOCATION_QUERY_TITLE = "location";
45057
45157
  function useLocationQuery(state2) {
45058
- React92.useEffect(() => {
45158
+ React93.useEffect(() => {
45059
45159
  if (state2.state === "READY")
45060
45160
  updateQuery(state2.location);
45061
45161
  }, [state2.location, state2.state]);
@@ -45100,10 +45200,10 @@ function makeHtmlReducer(args) {
45100
45200
  return (state2, _action) => state2;
45101
45201
  const { manifest, webpubManifestUrl } = args;
45102
45202
  return function reducer(state2, action) {
45103
- var _a;
45203
+ var _a, _b, _c;
45104
45204
  function goToNextResource() {
45105
45205
  if (state2.state === "INACTIVE") {
45106
- return handleInvalidTransition(state2, action);
45206
+ return handleInvalidTransition2(state2, action);
45107
45207
  }
45108
45208
  const currentIndex = getCurrentIndex(manifest, state2, webpubManifestUrl);
45109
45209
  const nextIndex = currentIndex + 1;
@@ -45122,7 +45222,7 @@ function makeHtmlReducer(args) {
45122
45222
  }
45123
45223
  function goToPrevResource() {
45124
45224
  if (state2.state === "INACTIVE") {
45125
- return handleInvalidTransition(state2, action);
45225
+ return handleInvalidTransition2(state2, action);
45126
45226
  }
45127
45227
  const currentIndex = getCurrentIndex(manifest, state2, webpubManifestUrl);
45128
45228
  const prevIndex = currentIndex - 1;
@@ -45154,8 +45254,12 @@ function makeHtmlReducer(args) {
45154
45254
  });
45155
45255
  const queryLocation = getLocationQuery();
45156
45256
  const isQueryValid = queryLocation && !!getFromReadingOrder(queryLocation == null ? void 0 : queryLocation.href, manifest, webpubManifestUrl);
45157
- const location = isQueryValid ? queryLocation : defaultStartLocation;
45257
+ const localStorageRecord = getLocalStorageLocation((_a = manifest.metadata.identifier) != null ? _a : webpubManifestUrl);
45258
+ const isLocalStorageLocationValid = !!localStorageRecord && !!getFromReadingOrder(localStorageRecord.location.href, manifest, webpubManifestUrl);
45259
+ const location = isQueryValid ? queryLocation : isLocalStorageLocationValid ? localStorageRecord.location : defaultStartLocation;
45260
+ const settings = (_b = getLocalStorageSettings()) != null ? _b : DEFAULT_SETTINGS;
45158
45261
  const fetchingResource = __spreadProps(__spreadValues({}, state2), {
45262
+ settings,
45159
45263
  state: "FETCHING_RESOURCE",
45160
45264
  location,
45161
45265
  resourceFetchError: void 0,
@@ -45166,7 +45270,7 @@ function makeHtmlReducer(args) {
45166
45270
  }
45167
45271
  case "RESOURCE_FETCH_SUCCESS": {
45168
45272
  if (state2.state === "INACTIVE") {
45169
- return handleInvalidTransition(state2, action);
45273
+ return handleInvalidTransition2(state2, action);
45170
45274
  }
45171
45275
  const newState = __spreadProps(__spreadValues({}, state2), {
45172
45276
  state: "RENDERING_IFRAME",
@@ -45178,7 +45282,7 @@ function makeHtmlReducer(args) {
45178
45282
  }
45179
45283
  case "RESOURCE_FETCH_ERROR": {
45180
45284
  if (state2.state !== "FETCHING_RESOURCE") {
45181
- return handleInvalidTransition(state2, action);
45285
+ return handleInvalidTransition2(state2, action);
45182
45286
  }
45183
45287
  const newState = __spreadProps(__spreadValues({}, state2), {
45184
45288
  state: "RESOURCE_FETCH_ERROR",
@@ -45189,9 +45293,9 @@ function makeHtmlReducer(args) {
45189
45293
  }
45190
45294
  case "IFRAME_LOADED": {
45191
45295
  if (state2.state !== "LOADING_IFRAME") {
45192
- return handleInvalidTransition(state2, action);
45296
+ return handleInvalidTransition2(state2, action);
45193
45297
  }
45194
- const { currentPage, totalPages } = calcPosition(state2.iframe, state2.isScrolling);
45298
+ const { currentPage, totalPages } = calcPosition(state2.iframe, state2.settings.isScrolling);
45195
45299
  const newState = __spreadProps(__spreadValues({}, state2), {
45196
45300
  state: "NAVIGATING",
45197
45301
  location: __spreadProps(__spreadValues({}, state2.location), {
@@ -45211,9 +45315,9 @@ function makeHtmlReducer(args) {
45211
45315
  }
45212
45316
  case "GO_TO_HREF": {
45213
45317
  if (state2.state !== "READY") {
45214
- return handleInvalidTransition(state2, action);
45318
+ return handleInvalidTransition2(state2, action);
45215
45319
  }
45216
- const { link } = (_a = getFromReadingOrder(action.href, manifest, webpubManifestUrl)) != null ? _a : {};
45320
+ const { link } = (_c = getFromReadingOrder(action.href, manifest, webpubManifestUrl)) != null ? _c : {};
45217
45321
  if (!link) {
45218
45322
  console.error(`No readingOrder entry found for href: ${action.href}`);
45219
45323
  return state2;
@@ -45241,7 +45345,7 @@ function makeHtmlReducer(args) {
45241
45345
  }
45242
45346
  case "GO_TO_LOCATION": {
45243
45347
  if (state2.state !== "READY") {
45244
- return handleInvalidTransition(state2, action);
45348
+ return handleInvalidTransition2(state2, action);
45245
45349
  }
45246
45350
  const isNewResource = !isSameResource(action.location.href, state2.location.href, webpubManifestUrl);
45247
45351
  if (isNewResource) {
@@ -45276,9 +45380,9 @@ function makeHtmlReducer(args) {
45276
45380
  }
45277
45381
  case "GO_FORWARD": {
45278
45382
  if (state2.state !== "READY") {
45279
- return handleInvalidTransition(state2, action);
45383
+ return handleInvalidTransition2(state2, action);
45280
45384
  }
45281
- const { progression, totalPages, currentPage } = calcPosition(state2.iframe, state2.isScrolling);
45385
+ const { progression, totalPages, currentPage } = calcPosition(state2.iframe, state2.settings.isScrolling);
45282
45386
  if (currentPage === totalPages) {
45283
45387
  return goToNextResource();
45284
45388
  }
@@ -45299,9 +45403,9 @@ function makeHtmlReducer(args) {
45299
45403
  }
45300
45404
  case "GO_BACKWARD": {
45301
45405
  if (state2.state !== "READY") {
45302
- return handleInvalidTransition(state2, action);
45406
+ return handleInvalidTransition2(state2, action);
45303
45407
  }
45304
- const { progression, totalPages, currentPage } = calcPosition(state2.iframe, state2.isScrolling);
45408
+ const { progression, totalPages, currentPage } = calcPosition(state2.iframe, state2.settings.isScrolling);
45305
45409
  if (currentPage === 1) {
45306
45410
  return goToPrevResource();
45307
45411
  }
@@ -45322,9 +45426,9 @@ function makeHtmlReducer(args) {
45322
45426
  }
45323
45427
  case "NAV_COMPLETE": {
45324
45428
  if (state2.state !== "NAVIGATING") {
45325
- return handleInvalidTransition(state2, action);
45429
+ return handleInvalidTransition2(state2, action);
45326
45430
  }
45327
- const { totalPages, currentPage } = calcPosition(state2.iframe, state2.isScrolling);
45431
+ const { totalPages, currentPage } = calcPosition(state2.iframe, state2.settings.isScrolling);
45328
45432
  const newState = __spreadProps(__spreadValues({}, state2), {
45329
45433
  state: "READY",
45330
45434
  location: __spreadProps(__spreadValues({}, state2.location), {
@@ -45337,17 +45441,24 @@ function makeHtmlReducer(args) {
45337
45441
  return newState;
45338
45442
  }
45339
45443
  case "SET_COLOR_MODE":
45444
+ if (state2.state === "INACTIVE") {
45445
+ return handleInvalidTransition2(state2, action);
45446
+ }
45340
45447
  return __spreadProps(__spreadValues({}, state2), {
45341
- colorMode: action.mode
45448
+ settings: __spreadProps(__spreadValues({}, state2.settings), {
45449
+ colorMode: action.mode
45450
+ })
45342
45451
  });
45343
45452
  case "SET_SCROLL": {
45344
45453
  if (state2.state !== "READY") {
45345
- return handleInvalidTransition(state2, action);
45454
+ return handleInvalidTransition2(state2, action);
45346
45455
  }
45347
- const { currentPageFloor, totalPages } = calcPosition(state2.iframe, state2.isScrolling);
45456
+ const { currentPageFloor, totalPages } = calcPosition(state2.iframe, state2.settings.isScrolling);
45348
45457
  const newState = __spreadProps(__spreadValues({}, state2), {
45349
45458
  state: "NAVIGATING",
45350
- isScrolling: action.isScrolling,
45459
+ settings: __spreadProps(__spreadValues({}, state2.settings), {
45460
+ isScrolling: action.isScrolling
45461
+ }),
45351
45462
  location: __spreadProps(__spreadValues({}, state2.location), {
45352
45463
  locations: {
45353
45464
  position: currentPageFloor,
@@ -45358,27 +45469,42 @@ function makeHtmlReducer(args) {
45358
45469
  return newState;
45359
45470
  }
45360
45471
  case "INCREASE_FONT_SIZE": {
45361
- const newSize = state2.fontSize + FONT_SIZE_STEP;
45472
+ if (state2.state === "INACTIVE") {
45473
+ return handleInvalidTransition2(state2, action);
45474
+ }
45475
+ const newSize = state2.settings.fontSize + FONT_SIZE_STEP;
45362
45476
  return __spreadProps(__spreadValues({}, state2), {
45363
- fontSize: newSize > 0 ? newSize : 0
45477
+ settings: __spreadProps(__spreadValues({}, state2.settings), {
45478
+ fontSize: newSize > 0 ? newSize : 0
45479
+ })
45364
45480
  });
45365
45481
  }
45366
45482
  case "DECREASE_FONT_SIZE": {
45367
- const newSize = state2.fontSize - FONT_SIZE_STEP;
45483
+ if (state2.state === "INACTIVE") {
45484
+ return handleInvalidTransition2(state2, action);
45485
+ }
45486
+ const newSize = state2.settings.fontSize - FONT_SIZE_STEP;
45368
45487
  return __spreadProps(__spreadValues({}, state2), {
45369
- fontSize: newSize > 0 ? newSize : 0
45488
+ settings: __spreadProps(__spreadValues({}, state2.settings), {
45489
+ fontSize: newSize > 0 ? newSize : 0
45490
+ })
45370
45491
  });
45371
45492
  }
45372
45493
  case "SET_FONT_FAMILY":
45494
+ if (state2.state === "INACTIVE") {
45495
+ return handleInvalidTransition2(state2, action);
45496
+ }
45373
45497
  return __spreadProps(__spreadValues({}, state2), {
45374
- fontFamily: action.family
45498
+ settings: __spreadProps(__spreadValues({}, state2.settings), {
45499
+ fontFamily: action.family
45500
+ })
45375
45501
  });
45376
45502
  case "SET_IFRAME": {
45377
45503
  if (action.iframe === null) {
45378
45504
  return state2;
45379
45505
  }
45380
45506
  if (state2.state !== "RENDERING_IFRAME" || !action.iframe) {
45381
- return handleInvalidTransition(state2, action);
45507
+ return handleInvalidTransition2(state2, action);
45382
45508
  }
45383
45509
  const newState = __spreadProps(__spreadValues({}, state2), {
45384
45510
  state: "LOADING_IFRAME",
@@ -45388,9 +45514,9 @@ function makeHtmlReducer(args) {
45388
45514
  }
45389
45515
  case "USER_SCROLLED": {
45390
45516
  if (state2.state !== "READY") {
45391
- return handleInvalidTransition(state2, action);
45517
+ return handleInvalidTransition2(state2, action);
45392
45518
  }
45393
- const { progression, currentPage, totalPages } = calcPosition(state2.iframe, state2.isScrolling);
45519
+ const { progression, currentPage, totalPages } = calcPosition(state2.iframe, state2.settings.isScrolling);
45394
45520
  const newState = __spreadProps(__spreadValues({}, state2), {
45395
45521
  location: __spreadProps(__spreadValues({}, state2.location), {
45396
45522
  locations: {
@@ -45405,23 +45531,19 @@ function makeHtmlReducer(args) {
45405
45531
  }
45406
45532
  };
45407
45533
  }
45408
- function handleInvalidTransition(state2, action) {
45534
+ function handleInvalidTransition2(state2, action) {
45409
45535
  console.trace(`Inavlid state transition attempted: ${state2.state} to ${action.type}`);
45410
45536
  return state2;
45411
45537
  }
45412
45538
  var inactiveState = {
45413
- colorMode: "day",
45414
- isScrolling: false,
45415
- fontSize: 100,
45416
- fontFamily: "sans-serif",
45417
- currentTocUrl: null,
45418
45539
  atStart: false,
45419
45540
  atEnd: false,
45420
45541
  iframe: null,
45421
45542
  resource: void 0,
45422
45543
  resourceFetchError: void 0,
45423
45544
  state: "INACTIVE",
45424
- location: void 0
45545
+ location: void 0,
45546
+ settings: void 0
45425
45547
  };
45426
45548
 
45427
45549
  // src/HtmlReader/effects.ts
@@ -45452,29 +45574,31 @@ function navigateToHash(fragment, iframe, isScrolling) {
45452
45574
  }
45453
45575
  }
45454
45576
  }
45455
- function setCss(html, state2) {
45456
- setCSSProperty(html, "--USER__scroll", getPagination(state2.isScrolling));
45457
- setCSSProperty(html, "--USER__appearance", getColorModeValue(state2.colorMode));
45577
+ function setCss(html, settings) {
45578
+ setCSSProperty(html, "--USER__scroll", getPagination(settings.isScrolling));
45579
+ setCSSProperty(html, "--USER__appearance", getColorModeValue(settings.colorMode));
45458
45580
  setCSSProperty(html, "--USER__advancedSettings", "readium-advanced-on");
45459
- setCSSProperty(html, "--USER__fontOverride", getFontOverride(state2.fontFamily));
45460
- setCSSProperty(html, "--USER__fontFamily", familyToReadiumFamily[state2.fontFamily]);
45461
- setCSSProperty(html, "--USER__fontSize", `${state2.fontSize}%`);
45462
- setCSSProperty(html, "overflow", state2.isScrolling ? "scroll" : "hidden");
45581
+ setCSSProperty(html, "--USER__fontOverride", getFontOverride(settings.fontFamily));
45582
+ setCSSProperty(html, "--USER__fontFamily", familyToReadiumFamily[settings.fontFamily]);
45583
+ setCSSProperty(html, "--USER__fontSize", `${settings.fontSize}%`);
45584
+ setCSSProperty(html, "overflow", settings.isScrolling ? "scroll" : "hidden");
45463
45585
  setCSSProperty(html, "--USER__colCount", "1");
45464
45586
  }
45465
45587
 
45466
45588
  // src/HtmlReader/useResource.tsx
45467
- import React93 from "react";
45589
+ import React94 from "react";
45468
45590
  function useResource(state2, getContent, injectables, dispatch) {
45469
45591
  var _a, _b;
45470
45592
  const currentResourceUrl = (_b = (_a = state2.location) == null ? void 0 : _a.href) != null ? _b : null;
45471
- React93.useEffect(() => {
45593
+ React94.useEffect(() => {
45472
45594
  if (!currentResourceUrl) {
45473
45595
  return;
45474
45596
  }
45475
45597
  function fetchResource(url) {
45476
45598
  return __async(this, null, function* () {
45477
45599
  var _a2, _b2;
45600
+ if (!state2.settings)
45601
+ return;
45478
45602
  try {
45479
45603
  const content = yield getContent(url);
45480
45604
  const mimetype = ((_b2 = (_a2 = state2.location) == null ? void 0 : _a2.type) != null ? _b2 : url.endsWith(".html")) ? "text/html" : "application/xhtml+xml";
@@ -45491,10 +45615,10 @@ function useResource(state2, getContent, injectables, dispatch) {
45491
45615
  }
45492
45616
  injectJS(document2.body);
45493
45617
  setCss(document2.documentElement, {
45494
- colorMode: state2.colorMode,
45495
- fontSize: state2.fontSize,
45496
- fontFamily: state2.fontFamily,
45497
- isScrolling: state2.isScrolling
45618
+ colorMode: state2.settings.colorMode,
45619
+ fontSize: state2.settings.fontSize,
45620
+ fontFamily: state2.settings.fontFamily,
45621
+ isScrolling: state2.settings.isScrolling
45498
45622
  });
45499
45623
  const finalResource = new XMLSerializer().serializeToString(document2);
45500
45624
  dispatch({ type: "RESOURCE_FETCH_SUCCESS", resource: finalResource });
@@ -45533,9 +45657,9 @@ function injectJS(body) {
45533
45657
  }
45534
45658
 
45535
45659
  // src/HtmlReader/useWindowResize.ts
45536
- import React94 from "react";
45660
+ import React95 from "react";
45537
45661
  function useWindowResize(dispatch) {
45538
- React94.useEffect(() => {
45662
+ React95.useEffect(() => {
45539
45663
  function handleResize() {
45540
45664
  dispatch({ type: "WINDOW_RESIZED" });
45541
45665
  }
@@ -45545,11 +45669,11 @@ function useWindowResize(dispatch) {
45545
45669
  }
45546
45670
 
45547
45671
  // src/HtmlReader/useUpdateScroll.ts
45548
- import * as React95 from "react";
45672
+ import * as React96 from "react";
45549
45673
  var SCROLL_STOP_DEBOUNCE = 100;
45550
45674
  function useUpdateScroll(state2, dispatch) {
45551
- const timeout = React95.useRef();
45552
- React95.useLayoutEffect(() => {
45675
+ const timeout = React96.useRef();
45676
+ React96.useLayoutEffect(() => {
45553
45677
  if (state2.state !== "READY")
45554
45678
  return;
45555
45679
  const iframeDocument = state2.iframe.contentDocument;
@@ -45568,9 +45692,9 @@ function useUpdateScroll(state2, dispatch) {
45568
45692
  }
45569
45693
 
45570
45694
  // src/HtmlReader/useUpdateCSS.ts
45571
- import React96 from "react";
45695
+ import React97 from "react";
45572
45696
  function useUpdateCSS(state2, manifest) {
45573
- React96.useEffect(() => {
45697
+ React97.useEffect(() => {
45574
45698
  if (!manifest)
45575
45699
  return;
45576
45700
  if (state2.state !== "NAVIGATING" && state2.state !== "READY")
@@ -45578,14 +45702,14 @@ function useUpdateCSS(state2, manifest) {
45578
45702
  const html = getMaybeIframeHtml(state2.iframe);
45579
45703
  if (!html)
45580
45704
  return;
45581
- setCss(html, state2);
45705
+ setCss(html, state2.settings);
45582
45706
  }, [state2, manifest]);
45583
45707
  }
45584
45708
 
45585
45709
  // src/HtmlReader/useIframeLinkClick.ts
45586
- import React97 from "react";
45710
+ import React98 from "react";
45587
45711
  function useIframeLinkClick(dispatch) {
45588
- React97.useEffect(() => {
45712
+ React98.useEffect(() => {
45589
45713
  window.addEventListener("message", ({ data }) => {
45590
45714
  if (typeof data === "object" && data !== null && "type" in data) {
45591
45715
  switch (data.type) {
@@ -45599,7 +45723,7 @@ function useIframeLinkClick(dispatch) {
45599
45723
 
45600
45724
  // src/HtmlReader/index.tsx
45601
45725
  function useHtmlReader(args) {
45602
- var _a, _b, _c, _d;
45726
+ var _a, _b, _c, _d, _e, _f, _g;
45603
45727
  const {
45604
45728
  webpubManifestUrl,
45605
45729
  manifest,
@@ -45609,15 +45733,17 @@ function useHtmlReader(args) {
45609
45733
  height = DEFAULT_HEIGHT,
45610
45734
  growWhenScrolling = DEFAULT_SHOULD_GROW_WHEN_SCROLLING
45611
45735
  } = args != null ? args : {};
45612
- const [state2, dispatch] = React98.useReducer(makeHtmlReducer(args), inactiveState);
45736
+ const [state2, dispatch] = React99.useReducer(makeHtmlReducer(args), inactiveState);
45613
45737
  const currentResourceUrl = (_b = (_a = state2.location) == null ? void 0 : _a.href) != null ? _b : null;
45614
45738
  useResource(state2, getContent, injectables, dispatch);
45615
45739
  useUpdateScroll(state2, dispatch);
45740
+ const identifier2 = manifest ? (_d = (_c = manifest.metadata.identifier) != null ? _c : webpubManifestUrl) != null ? _d : null : null;
45741
+ useUpdateLocalStorage(identifier2, state2);
45616
45742
  useLocationQuery(state2);
45617
45743
  useWindowResize(dispatch);
45618
45744
  useUpdateCSS(state2, manifest);
45619
45745
  useIframeLinkClick(dispatch);
45620
- React98.useEffect(() => {
45746
+ React99.useEffect(() => {
45621
45747
  if (!webpubManifestUrl || !manifest) {
45622
45748
  return dispatch({ type: "ARGS_CHANGED", args: void 0 });
45623
45749
  }
@@ -45642,24 +45768,29 @@ function useHtmlReader(args) {
45642
45768
  height,
45643
45769
  growWhenScrolling
45644
45770
  ]);
45645
- React98.useEffect(() => {
45771
+ React99.useEffect(() => {
45646
45772
  process.nextTick(() => {
45647
45773
  if (state2.state === "NAVIGATING") {
45648
45774
  const { fragment, progression, position: position5 } = state2.location.locations;
45649
45775
  if (typeof fragment === "string") {
45650
- navigateToHash(fragment, state2.iframe, state2.isScrolling);
45776
+ navigateToHash(fragment, state2.iframe, state2.settings.isScrolling);
45651
45777
  } else if (typeof progression === "number") {
45652
- navigateToProgression(state2.iframe, progression, state2.isScrolling);
45778
+ navigateToProgression(state2.iframe, progression, state2.settings.isScrolling);
45653
45779
  } else if (typeof position5 === "number") {
45654
- const { totalPages } = calcPosition(state2.iframe, state2.isScrolling);
45780
+ const { totalPages } = calcPosition(state2.iframe, state2.settings.isScrolling);
45655
45781
  const calculatedProgression = (position5 - 1) / totalPages;
45656
- navigateToProgression(state2.iframe, calculatedProgression, state2.isScrolling);
45782
+ navigateToProgression(state2.iframe, calculatedProgression, state2.settings.isScrolling);
45657
45783
  }
45658
45784
  dispatch({ type: "NAV_COMPLETE" });
45659
45785
  }
45660
45786
  });
45661
- }, [state2.state, state2.iframe, state2.isScrolling, (_c = state2.location) == null ? void 0 : _c.locations]);
45662
- const navigator2 = React98.useRef({
45787
+ }, [
45788
+ state2.state,
45789
+ state2.iframe,
45790
+ (_e = state2.settings) == null ? void 0 : _e.isScrolling,
45791
+ (_f = state2.location) == null ? void 0 : _f.locations
45792
+ ]);
45793
+ const navigator2 = React99.useRef({
45663
45794
  goToPage(href) {
45664
45795
  dispatch({ type: "GO_TO_HREF", href });
45665
45796
  },
@@ -45700,7 +45831,7 @@ function useHtmlReader(args) {
45700
45831
  });
45701
45832
  }
45702
45833
  }).current;
45703
- const setIframe = React98.useRef((el) => {
45834
+ const setIframe = React99.useRef((el) => {
45704
45835
  dispatch({ type: "SET_IFRAME", iframe: el });
45705
45836
  }).current;
45706
45837
  if (!webpubManifestUrl || !manifest)
@@ -45709,7 +45840,7 @@ function useHtmlReader(args) {
45709
45840
  return {
45710
45841
  type: null,
45711
45842
  isLoading: true,
45712
- content: /* @__PURE__ */ React98.createElement(LoadingSkeleton, {
45843
+ content: /* @__PURE__ */ React99.createElement(LoadingSkeleton, {
45713
45844
  height
45714
45845
  }),
45715
45846
  navigator: null,
@@ -45719,8 +45850,8 @@ function useHtmlReader(args) {
45719
45850
  }
45720
45851
  if (state2.state === "RESOURCE_FETCH_ERROR")
45721
45852
  throw state2.resourceFetchError;
45722
- const shouldGrow = state2.isScrolling && growWhenScrolling;
45723
- const englishTitle = typeof manifest.metadata.title === "string" ? manifest.metadata.title : (_d = manifest.metadata.title.en) != null ? _d : "Unknown Title";
45853
+ const shouldGrow = state2.settings.isScrolling && growWhenScrolling;
45854
+ const englishTitle = typeof manifest.metadata.title === "string" ? manifest.metadata.title : (_g = manifest.metadata.title.en) != null ? _g : "Unknown Title";
45724
45855
  const resourceIndex = manifest.readingOrder.findIndex((link) => isSameResource(link.href, state2.location.href, webpubManifestUrl));
45725
45856
  const numResources = manifest.readingOrder.length;
45726
45857
  const isFirstResource = resourceIndex === 0;
@@ -45732,7 +45863,7 @@ function useHtmlReader(args) {
45732
45863
  return {
45733
45864
  type: "HTML",
45734
45865
  isLoading: false,
45735
- content: /* @__PURE__ */ React98.createElement(React98.Fragment, null, /* @__PURE__ */ React98.createElement("iframe", {
45866
+ content: /* @__PURE__ */ React99.createElement(React99.Fragment, null, /* @__PURE__ */ React99.createElement("iframe", {
45736
45867
  id: "html-reader-iframe",
45737
45868
  onLoad: () => dispatch({ type: "IFRAME_LOADED" }),
45738
45869
  ref: setIframe,
@@ -45782,8 +45913,8 @@ function useWebReader(args) {
45782
45913
  height = DEFAULT_HEIGHT,
45783
45914
  growWhenScrolling = DEFAULT_SHOULD_GROW_WHEN_SCROLLING
45784
45915
  } = args;
45785
- const [manifest, setManifest] = React99.useState(null);
45786
- const [error7, setError] = React99.useState(null);
45916
+ const [manifest, setManifest] = React100.useState(null);
45917
+ const [error7, setError] = React100.useState(null);
45787
45918
  if (error7) {
45788
45919
  throw error7;
45789
45920
  }
@@ -45805,13 +45936,13 @@ function useWebReader(args) {
45805
45936
  height,
45806
45937
  growWhenScrolling
45807
45938
  } : void 0);
45808
- React99.useEffect(() => {
45939
+ React100.useEffect(() => {
45809
45940
  fetchJson(webpubManifestUrl).then(setManifest).catch(setError);
45810
45941
  }, [webpubManifestUrl]);
45811
45942
  if (manifest === null) {
45812
45943
  return {
45813
45944
  isLoading: true,
45814
- content: /* @__PURE__ */ React99.createElement(LoadingSkeleton, {
45945
+ content: /* @__PURE__ */ React100.createElement(LoadingSkeleton, {
45815
45946
  height
45816
45947
  }),
45817
45948
  manifest: null,
@@ -45830,7 +45961,7 @@ function useWebReader(args) {
45830
45961
  }
45831
45962
 
45832
45963
  // src/ServiceWorker/client.ts
45833
- import React100 from "react";
45964
+ import React101 from "react";
45834
45965
 
45835
45966
  // src/ServiceWorker/constants.ts
45836
45967
  var PRECACHE_PUBLICATIONS = "PRECACHE_PUBLICATIONS";
@@ -45838,7 +45969,7 @@ var CACHE_EXPIRATION_SECONDS = 7 * 24 * 60 * 60;
45838
45969
 
45839
45970
  // src/ServiceWorker/client.ts
45840
45971
  function usePublicationSW(publications) {
45841
- React100.useEffect(() => {
45972
+ React101.useEffect(() => {
45842
45973
  var _a;
45843
45974
  if ("serviceWorker" in navigator) {
45844
45975
  const message = {
@@ -45869,17 +46000,18 @@ var WebReaderWithoutBoundary = (_a) => {
45869
46000
  getContent
45870
46001
  }, props));
45871
46002
  const { content } = webReader;
45872
- return /* @__PURE__ */ React101.createElement(manager_default, __spreadValues({
46003
+ return /* @__PURE__ */ React102.createElement(manager_default, __spreadValues({
45873
46004
  headerLeft
45874
46005
  }, webReader), content);
45875
46006
  };
45876
46007
  var WebReader = (props) => {
45877
- return /* @__PURE__ */ React101.createElement(ErrorBoundary_default, __spreadValues({}, props), /* @__PURE__ */ React101.createElement(WebReaderWithoutBoundary, __spreadValues({}, props)));
46008
+ return /* @__PURE__ */ React102.createElement(ErrorBoundary_default, __spreadValues({}, props), /* @__PURE__ */ React102.createElement(WebReaderWithoutBoundary, __spreadValues({}, props)));
45878
46009
  };
45879
46010
  var src_default = WebReader;
45880
46011
  export {
45881
46012
  CHROME_HEIGHT,
45882
46013
  DEFAULT_HEIGHT,
46014
+ DEFAULT_SETTINGS,
45883
46015
  DEFAULT_SHOULD_GROW_WHEN_SCROLLING,
45884
46016
  FOOTER_HEIGHT,
45885
46017
  HEADER_HEIGHT,