@prose-reader/core 1.56.0 → 1.58.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.
Files changed (100) hide show
  1. package/dist/cfi.d.ts +74 -0
  2. package/dist/constants.d.ts +6 -0
  3. package/dist/context/Context.d.ts +63 -0
  4. package/dist/context/isUsingSpreadMode.d.ts +10 -0
  5. package/dist/createReaderWithEnhancer.d.ts +271 -0
  6. package/dist/enhancers/accessibility.d.ts +3 -0
  7. package/dist/enhancers/chrome.d.ts +3 -0
  8. package/dist/enhancers/events/createIframeEventBridgeElement.d.ts +1 -0
  9. package/dist/enhancers/events/events.d.ts +8 -0
  10. package/dist/enhancers/events/normalizeEventForViewport.d.ts +7 -0
  11. package/dist/enhancers/firefox.d.ts +3 -0
  12. package/dist/enhancers/fonts.d.ts +19 -0
  13. package/dist/enhancers/hotkeys.d.ts +3 -0
  14. package/dist/enhancers/layoutEnhancer/createMovingSafePan$.d.ts +4 -0
  15. package/dist/enhancers/layoutEnhancer/fixReflowable.d.ts +3 -0
  16. package/dist/enhancers/layoutEnhancer/layoutEnhancer.d.ts +10 -0
  17. package/dist/enhancers/layoutEnhancer/types.d.ts +8 -0
  18. package/dist/enhancers/links.d.ts +14 -0
  19. package/dist/enhancers/loadingEnhancer.d.ts +24 -0
  20. package/dist/enhancers/media.d.ts +3 -0
  21. package/dist/enhancers/navigation/navigation.d.ts +9 -0
  22. package/dist/enhancers/navigation/navigator.d.ts +8 -0
  23. package/dist/enhancers/navigation/state.d.ts +12 -0
  24. package/dist/enhancers/pagination/chapters.d.ts +24 -0
  25. package/dist/enhancers/pagination/constants.d.ts +1 -0
  26. package/dist/enhancers/pagination/enhancer.d.ts +14 -0
  27. package/dist/enhancers/pagination/pagination.d.ts +10 -0
  28. package/dist/enhancers/pagination/spine.d.ts +13 -0
  29. package/dist/enhancers/pagination/types.d.ts +19 -0
  30. package/dist/enhancers/pagination.test.d.ts +1 -0
  31. package/dist/enhancers/progression.d.ts +16 -0
  32. package/dist/enhancers/publicApi.d.ts +5 -0
  33. package/dist/enhancers/resources/index.d.ts +3 -0
  34. package/dist/enhancers/resources/indexedDB.d.ts +6 -0
  35. package/dist/enhancers/resources/resourcesManager.d.ts +7 -0
  36. package/dist/enhancers/theme.d.ts +32 -0
  37. package/dist/enhancers/types/enhancer.d.ts +9 -0
  38. package/dist/enhancers/utils.d.ts +7 -0
  39. package/dist/enhancers/webkit.d.ts +3 -0
  40. package/dist/enhancers/zoom/elementZoomer.d.ts +19 -0
  41. package/dist/enhancers/zoom/index.d.ts +4 -0
  42. package/dist/enhancers/zoom/types.d.ts +23 -0
  43. package/dist/enhancers/zoom/viewportZoomer.d.ts +19 -0
  44. package/dist/frames.d.ts +5 -0
  45. package/dist/hooks/HookManager.d.ts +10 -0
  46. package/dist/hooks/types.d.ts +64 -0
  47. package/dist/index.d.ts +9 -4324
  48. package/dist/index.js +1032 -1107
  49. package/dist/index.js.map +1 -1
  50. package/dist/index.umd.cjs +1032 -1107
  51. package/dist/index.umd.cjs.map +1 -1
  52. package/dist/manifest/areAllItemsPrePaginated.d.ts +3 -0
  53. package/dist/manifest/isFullyPrePaginated.d.ts +3 -0
  54. package/dist/pagination/pagination.d.ts +88 -0
  55. package/dist/pagination/types.d.ts +10 -0
  56. package/dist/reader.d.ts +8 -0
  57. package/dist/report.d.ts +26 -0
  58. package/dist/selection.d.ts +7 -0
  59. package/dist/settings/SettingsManager.d.ts +14 -0
  60. package/dist/settings/defaultSettings.d.ts +3 -0
  61. package/dist/settings/getComputedSettings.d.ts +4 -0
  62. package/dist/settings/types.d.ts +19 -0
  63. package/dist/spine/cfiLocator.d.ts +340 -0
  64. package/dist/spine/createSpine.d.ts +31 -0
  65. package/dist/spine/locationResolver.d.ts +636 -0
  66. package/dist/spine/navigationResolver.d.ts +48 -0
  67. package/dist/spine/types.d.ts +10 -0
  68. package/dist/spineItem/commonSpineItem.d.ts +165 -0
  69. package/dist/spineItem/createSpineItem.d.ts +167 -0
  70. package/dist/spineItem/frameItem/createFrame$.d.ts +1 -0
  71. package/dist/spineItem/frameItem/createFrameManipulator.d.ts +5 -0
  72. package/dist/spineItem/frameItem/createHtmlPageFromResource.d.ts +3 -0
  73. package/dist/spineItem/frameItem/frameItem.d.ts +49 -0
  74. package/dist/spineItem/frameItem/loader.d.ts +30 -0
  75. package/dist/spineItem/locationResolver.d.ts +24 -0
  76. package/dist/spineItem/navigationResolver.d.ts +16 -0
  77. package/dist/spineItem/prePaginatedSpineItem.d.ts +166 -0
  78. package/dist/spineItem/reflowableSpineItem.d.ts +165 -0
  79. package/dist/spineItem/styles/getStyleForViewportDocument.d.ts +1 -0
  80. package/dist/spineItem/trackers.d.ts +34 -0
  81. package/dist/spineItem/types.d.ts +19 -0
  82. package/dist/spineItemManager.d.ts +505 -0
  83. package/dist/types/Spine.d.ts +40 -0
  84. package/dist/types/index.d.ts +12 -0
  85. package/dist/types/reader.d.ts +44 -0
  86. package/dist/utils/compose.d.ts +8 -0
  87. package/dist/utils/dom.d.ts +19 -0
  88. package/dist/utils/isDefined.d.ts +1 -0
  89. package/dist/utils/layout.d.ts +7 -0
  90. package/dist/utils/layout.test.d.ts +1 -0
  91. package/dist/utils/manifest.d.ts +3 -0
  92. package/dist/utils/objects.d.ts +6 -0
  93. package/dist/utils/objects.test.d.ts +1 -0
  94. package/dist/utils/rxjs.d.ts +5 -0
  95. package/dist/viewportNavigator/manualViewportNavigator.d.ts +96 -0
  96. package/dist/viewportNavigator/panViewportNavigator.d.ts +55 -0
  97. package/dist/viewportNavigator/scrollViewportNavigator.d.ts +38 -0
  98. package/dist/viewportNavigator/types.d.ts +34 -0
  99. package/dist/viewportNavigator/viewportNavigator.d.ts +82 -0
  100. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -3,17 +3,16 @@ import { withLatestFrom, distinctUntilChanged, shareReplay, tap, pairwise, switc
3
3
  import { parseContentType, detectMimeTypeFromName } from "@prose-reader/shared";
4
4
  const chromeEnhancer = (next) => (options) => {
5
5
  const reader = next(options);
6
- reader.context$.pipe(takeUntil(reader.$.destroy$)).subscribe(({ containerElement }) => {
7
- if (!containerElement)
8
- return;
6
+ reader.context.state$.pipe(takeUntil(reader.$.destroy$)).subscribe(({ containerElement }) => {
7
+ if (!containerElement) return;
9
8
  const onScroll = () => {
10
- if (reader.settings.getSettings().computedPageTurnMode === `controlled`) {
9
+ if (reader.settings.settings.computedPageTurnMode === `controlled`) {
11
10
  containerElement.scrollTo(0, 0);
12
11
  }
13
12
  };
14
13
  containerElement.addEventListener(`scroll`, onScroll);
15
14
  });
16
- reader.registerHook(`item.onLoad`, ({ frame }) => {
15
+ reader.hookManager.register(`item.onLoad`, ({ frame }) => {
17
16
  var _a;
18
17
  (_a = frame.contentDocument) == null ? void 0 : _a.body.setAttribute(`tabindex`, `-1`);
19
18
  });
@@ -54,8 +53,7 @@ const isShallowEqual = (objectA, objectB, options) => {
54
53
  const groupBy = (list, getKey) => list.reduce(
55
54
  (previous, currentItem) => {
56
55
  const group = getKey(currentItem);
57
- if (!previous[group])
58
- previous[group] = [];
56
+ if (!previous[group]) previous[group] = [];
59
57
  previous[group].push(currentItem);
60
58
  return previous;
61
59
  },
@@ -75,7 +73,12 @@ const getBase64FromBlob = (data) => {
75
73
  });
76
74
  };
77
75
  const fontsEnhancer = (next) => (options) => {
78
- const { fontScale = 1, lineHeight = `publisher`, fontWeight = `publisher`, fontJustification = `publisher` } = options;
76
+ const {
77
+ fontScale = 1,
78
+ lineHeight = `publisher`,
79
+ fontWeight = `publisher`,
80
+ fontJustification = `publisher`
81
+ } = options;
79
82
  const changes$ = new Subject();
80
83
  const settings$ = new BehaviorSubject({
81
84
  fontScale,
@@ -102,7 +105,7 @@ const fontsEnhancer = (next) => (options) => {
102
105
  }
103
106
  `;
104
107
  const applyChangeToSpineItem = (requireLayout) => {
105
- reader.manipulateSpineItems(({ removeStyle, addStyle, item }) => {
108
+ reader.spine.manipulateSpineItems(({ removeStyle, addStyle, item }) => {
106
109
  if (item.renditionLayout !== `pre-paginated`) {
107
110
  removeStyle(`prose-reader-fonts`);
108
111
  addStyle(`prose-reader-fonts`, getStyle());
@@ -110,19 +113,21 @@ const fontsEnhancer = (next) => (options) => {
110
113
  return requireLayout;
111
114
  });
112
115
  };
113
- reader.registerHook(`item.onLoad`, ({ removeStyle, addStyle, item }) => {
114
- if (item.renditionLayout !== `pre-paginated`) {
115
- removeStyle(`prose-reader-fonts`);
116
- addStyle(`prose-reader-fonts`, getStyle());
117
- }
116
+ reader.hookManager.register(`item.onLoad`, ({ itemId }) => {
117
+ const item = reader.spineItemManager.get(itemId);
118
+ item == null ? void 0 : item.manipulateSpineItem(({ addStyle, removeStyle }) => {
119
+ if (item.item.renditionLayout !== `pre-paginated`) {
120
+ removeStyle(`prose-reader-fonts`);
121
+ addStyle(`prose-reader-fonts`, getStyle());
122
+ }
123
+ return false;
124
+ });
118
125
  });
119
126
  const shouldRequireLayout = (source) => source.pipe(
120
127
  pairwise(),
121
128
  map(([old, latest]) => {
122
- if (latest.fontScale !== old.fontScale)
123
- return true;
124
- if (latest.lineHeight !== old.lineHeight)
125
- return true;
129
+ if (latest.fontScale !== old.fontScale) return true;
130
+ if (latest.lineHeight !== old.lineHeight) return true;
126
131
  return false;
127
132
  })
128
133
  );
@@ -171,25 +176,25 @@ const hotkeysEnhancer = (next) => (options) => {
171
176
  map(([e, { pageTurnDirection }]) => {
172
177
  if (pageTurnDirection === "horizontal") {
173
178
  if (e.key === `ArrowRight`) {
174
- reader.turnRight();
179
+ reader.viewportNavigator.turnRight();
175
180
  }
176
181
  if (e.key === `ArrowLeft`) {
177
- reader.turnLeft();
182
+ reader.viewportNavigator.turnLeft();
178
183
  }
179
184
  }
180
185
  if (pageTurnDirection === "vertical") {
181
186
  if (e.key === `ArrowDown`) {
182
- reader.turnRight();
187
+ reader.viewportNavigator.turnRight();
183
188
  }
184
189
  if (e.key === `ArrowUp`) {
185
- reader.turnLeft();
190
+ reader.viewportNavigator.turnLeft();
186
191
  }
187
192
  }
188
193
  return e;
189
194
  })
190
195
  );
191
196
  navigateOnKey(document).pipe(takeUntil(reader.$.destroy$)).subscribe();
192
- reader.spineItems$.pipe(
197
+ reader.spine.$.spineItems$.pipe(
193
198
  switchMap(
194
199
  (spineItems) => merge(
195
200
  ...spineItems.map(
@@ -205,10 +210,9 @@ const hotkeysEnhancer = (next) => (options) => {
205
210
  };
206
211
  const createMovingSafePan$ = (reader) => {
207
212
  let iframeOverlayForAnimationsElement;
208
- const updateOverlayElement$ = reader.context$.pipe(
213
+ const updateOverlayElement$ = reader.context.state$.pipe(
209
214
  switchMap$1(({ containerElement }) => {
210
- if (!containerElement)
211
- return NEVER;
215
+ if (!containerElement) return NEVER;
212
216
  return new Observable(() => {
213
217
  iframeOverlayForAnimationsElement = containerElement.ownerDocument.createElement(`div`);
214
218
  iframeOverlayForAnimationsElement.style.cssText = `
@@ -232,8 +236,8 @@ const createMovingSafePan$ = (reader) => {
232
236
  iframeOverlayForAnimationsElement == null ? void 0 : iframeOverlayForAnimationsElement.style.setProperty(`visibility`, `hidden`);
233
237
  })
234
238
  );
235
- const viewportFree$ = reader.$.viewportState$.pipe(filter((data) => data === `free`));
236
- const viewportBusy$ = reader.$.viewportState$.pipe(filter((data) => data === `busy`));
239
+ const viewportFree$ = reader.viewportNavigator.$.state$.pipe(filter((data) => data === `free`));
240
+ const viewportBusy$ = reader.viewportNavigator.$.state$.pipe(filter((data) => data === `busy`));
237
241
  const lockAfterViewportBusy$ = viewportBusy$.pipe(
238
242
  tap(() => {
239
243
  iframeOverlayForAnimationsElement == null ? void 0 : iframeOverlayForAnimationsElement.style.setProperty(`visibility`, `visible`);
@@ -241,7 +245,7 @@ const createMovingSafePan$ = (reader) => {
241
245
  );
242
246
  const resetLockViewportFree$ = createResetLock$(viewportFree$).pipe(take(1));
243
247
  const pageTurnMode$ = reader.settings.settings$.pipe(
244
- map$1(() => reader.settings.getSettings().computedPageTurnMode),
248
+ map$1(() => reader.settings.settings.computedPageTurnMode),
245
249
  distinctUntilChanged()
246
250
  );
247
251
  const handleViewportLock$ = pageTurnMode$.pipe(
@@ -269,11 +273,10 @@ const mapKeysTo = (keys) => {
269
273
  });
270
274
  };
271
275
  const fixReflowable = (reader) => {
272
- reader.registerHook(`item.onAfterLayout`, ({ item, blankPagePosition, minimumWidth }) => {
276
+ reader.hookManager.register(`item.onAfterLayout`, ({ item, blankPagePosition, minimumWidth }) => {
273
277
  var _a;
274
- const spineItem = reader.getSpineItem(item.id);
275
- if (!((spineItem == null ? void 0 : spineItem.item.renditionLayout) === `reflowable`))
276
- return;
278
+ const spineItem = reader.spineItemManager.get(item.id);
279
+ if (!((spineItem == null ? void 0 : spineItem.item.renditionLayout) === `reflowable`)) return;
277
280
  const { viewportDimensions } = (spineItem == null ? void 0 : spineItem.getViewPortInformation()) ?? {};
278
281
  const { width: pageWidth } = reader.context.getPageSize();
279
282
  const frameElement = (_a = spineItem == null ? void 0 : spineItem.spineItemFrame.getManipulableFrame()) == null ? void 0 : _a.frame;
@@ -297,9 +300,9 @@ const layoutEnhancer = (next) => (options) => {
297
300
  pageHorizontalMargin,
298
301
  pageVerticalMargin
299
302
  });
300
- reader.registerHook(`onViewportOffsetAdjust`, () => {
303
+ reader.hookManager.register(`onViewportOffsetAdjust`, () => {
301
304
  let hasRedrawn = false;
302
- reader.manipulateSpineItems(({ frame }) => {
305
+ reader.spine.manipulateSpineItems(({ frame }) => {
303
306
  if (!hasRedrawn && frame) {
304
307
  void frame.getBoundingClientRect().left;
305
308
  hasRedrawn = true;
@@ -307,7 +310,7 @@ const layoutEnhancer = (next) => (options) => {
307
310
  return SHOULD_NOT_LAYOUT;
308
311
  });
309
312
  });
310
- reader.registerHook(`item.onLayoutBeforeMeasurement`, ({ frame, minimumWidth, item, isImageType }) => {
313
+ reader.hookManager.register(`item.onLayoutBeforeMeasurement`, ({ frame, minimumWidth, item, isImageType }) => {
311
314
  var _a, _b;
312
315
  const { pageHorizontalMargin: pageHorizontalMargin2 = 0, pageVerticalMargin: pageVerticalMargin2 = 0 } = settingsSubject$.value;
313
316
  const pageSize = reader.context.getPageSize();
@@ -349,7 +352,7 @@ const layoutEnhancer = (next) => (options) => {
349
352
  fixReflowable(reader);
350
353
  let observer;
351
354
  if (options.layoutAutoResize === `container`) {
352
- reader.context$.pipe(
355
+ reader.context.state$.pipe(
353
356
  map$1((state) => state.containerElement),
354
357
  filter(isDefined),
355
358
  distinctUntilChanged(),
@@ -422,20 +425,16 @@ const createReport = (namespace) => ({
422
425
  log: (...data) => {
423
426
  var _a;
424
427
  if ((_a = getWindow()) == null ? void 0 : _a.__PROSE_READER_DEBUG) {
425
- if (namespace)
426
- console.log(wrap(ROOT_NAMESPACE), wrap(namespace), ...data);
427
- else
428
- console.log(wrap(ROOT_NAMESPACE), ...data);
428
+ if (namespace) console.log(wrap(ROOT_NAMESPACE), wrap(namespace), ...data);
429
+ else console.log(wrap(ROOT_NAMESPACE), ...data);
429
430
  }
430
431
  },
431
432
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
432
433
  warn: (...data) => {
433
434
  var _a;
434
435
  if ((_a = getWindow()) == null ? void 0 : _a.__PROSE_READER_DEBUG) {
435
- if (namespace)
436
- console.warn(wrap(ROOT_NAMESPACE), wrap(namespace), ...data);
437
- else
438
- console.warn(wrap(ROOT_NAMESPACE), ...data);
436
+ if (namespace) console.warn(wrap(ROOT_NAMESPACE), wrap(namespace), ...data);
437
+ else console.warn(wrap(ROOT_NAMESPACE), ...data);
439
438
  }
440
439
  },
441
440
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -458,8 +457,7 @@ const createReport = (namespace) => ({
458
457
  logMetric: (performanceEntry, targetDuration = 0) => {
459
458
  var _a;
460
459
  if ((_a = getWindow()) == null ? void 0 : _a.__PROSE_READER_DEBUG) {
461
- if (performanceEntry.duration <= targetDuration)
462
- ;
460
+ if (performanceEntry.duration <= targetDuration) ;
463
461
  else {
464
462
  console.warn(
465
463
  `[prose-reader] [metric] `,
@@ -471,8 +469,7 @@ const createReport = (namespace) => ({
471
469
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
472
470
  measurePerformance: (name, targetDuration = 10, functionToMeasure, { disable } = {}) => {
473
471
  var _a;
474
- if (disable || !((_a = getWindow()) == null ? void 0 : _a.__PROSE_READER_DEBUG))
475
- return functionToMeasure;
472
+ if (disable || !((_a = getWindow()) == null ? void 0 : _a.__PROSE_READER_DEBUG)) return functionToMeasure;
476
473
  return (...args) => {
477
474
  const t0 = performance.now();
478
475
  const response = functionToMeasure(...args);
@@ -498,19 +495,18 @@ const linksEnhancer = (next) => (options) => {
498
495
  const subject = new Subject();
499
496
  const handleNavigationForClick = (element) => {
500
497
  var _a;
501
- if (!element.href)
502
- return false;
498
+ if (!element.href) return false;
503
499
  const hrefUrl = new URL(element.href);
504
500
  const hrefWithoutAnchor = `${hrefUrl.origin}${hrefUrl.pathname}`;
505
- const hasExistingSpineItem = (_a = reader.context.getManifest()) == null ? void 0 : _a.spineItems.some((item) => item.href === hrefWithoutAnchor);
501
+ const hasExistingSpineItem = (_a = reader.context.manifest) == null ? void 0 : _a.spineItems.some((item) => item.href === hrefWithoutAnchor);
506
502
  if (hasExistingSpineItem) {
507
- reader.goToUrl(hrefUrl);
503
+ reader.viewportNavigator.goToUrl(hrefUrl);
508
504
  return true;
509
505
  }
510
506
  return false;
511
507
  };
512
- reader.registerHook(`item.onLoad`, ({ frame }) => {
513
- if (frame.contentDocument) {
508
+ reader.hookManager.register(`item.onLoad`, ({ frame }) => {
509
+ if (frame == null ? void 0 : frame.contentDocument) {
514
510
  Array.from(frame.contentDocument.querySelectorAll(`a`)).forEach(
515
511
  (element) => element.addEventListener(`click`, (e) => {
516
512
  if (e.target && `style` in e.target && `ELEMENT_NODE` in e.target) {
@@ -534,36 +530,38 @@ const linksEnhancer = (next) => (options) => {
534
530
  const createNavigator = (reader) => {
535
531
  const goToNextSpineItem = () => {
536
532
  var _a;
537
- const focusedSpineItemIndex = reader.getFocusedSpineItemIndex() || 0;
538
- const { end = focusedSpineItemIndex } = reader.locator.getSpineItemsFromReadingOrderPosition(reader.getCurrentNavigationPosition()) || {};
539
- const numberOfSpineItems = ((_a = reader.context.getManifest()) == null ? void 0 : _a.spineItems.length) ?? 0;
533
+ const focusedSpineItemIndex = reader.spineItemManager.getFocusedSpineItemIndex() || 0;
534
+ const { end = focusedSpineItemIndex } = reader.spine.locator.getSpineItemsFromReadingOrderPosition(
535
+ reader.viewportNavigator.getCurrentNavigationPosition()
536
+ ) || {};
537
+ const numberOfSpineItems = ((_a = reader.context.manifest) == null ? void 0 : _a.spineItems.length) ?? 0;
540
538
  const nextItem = end + 1;
541
539
  if (nextItem < numberOfSpineItems) {
542
- reader.goToSpineItem(nextItem);
540
+ reader.viewportNavigator.goToSpineItem(nextItem);
543
541
  }
544
542
  };
545
543
  const goToPreviousSpineItem = () => {
546
- const focusedSpineItemIndex = reader.getFocusedSpineItemIndex() || 0;
547
- const { begin = focusedSpineItemIndex } = reader.locator.getSpineItemsFromReadingOrderPosition(reader.getCurrentNavigationPosition()) || {};
544
+ const focusedSpineItemIndex = reader.spineItemManager.getFocusedSpineItemIndex() || 0;
545
+ const { begin = focusedSpineItemIndex } = reader.spine.locator.getSpineItemsFromReadingOrderPosition(
546
+ reader.viewportNavigator.getCurrentNavigationPosition()
547
+ ) || {};
548
548
  const nextItem = begin - 1;
549
549
  if (nextItem >= 0) {
550
- reader.goToSpineItem(nextItem);
550
+ reader.viewportNavigator.goToSpineItem(nextItem);
551
551
  }
552
552
  };
553
553
  return {
554
554
  goToNextSpineItem,
555
555
  goToPreviousSpineItem,
556
556
  goToLeftSpineItem: () => {
557
- if (reader.settings.getSettings().computedPageTurnDirection === "vertical")
558
- return;
557
+ if (reader.settings.settings.computedPageTurnDirection === "vertical") return;
559
558
  if (reader.context.isRTL()) {
560
559
  return goToNextSpineItem();
561
560
  }
562
561
  return goToPreviousSpineItem();
563
562
  },
564
563
  goToRightSpineItem: () => {
565
- if (reader.settings.getSettings().computedPageTurnDirection === "vertical")
566
- return;
564
+ if (reader.settings.settings.computedPageTurnDirection === "vertical") return;
567
565
  if (reader.context.isRTL()) {
568
566
  return goToPreviousSpineItem();
569
567
  }
@@ -573,7 +571,7 @@ const createNavigator = (reader) => {
573
571
  };
574
572
  const createState = (reader) => {
575
573
  return reader.pagination.paginationInfo$.pipe(
576
- withLatestFrom$1(reader.context.$.manifest$, reader.settings.settings$),
574
+ withLatestFrom$1(reader.context.manifest$, reader.settings.settings$),
577
575
  map(([paginationInfo, manifest, { computedPageTurnDirection }]) => {
578
576
  const numberOfSpineItems = (manifest == null ? void 0 : manifest.spineItems.length) ?? 0;
579
577
  const isAtAbsoluteBeginning = paginationInfo.beginSpineItemIndex === 0 && paginationInfo.beginPageIndexInSpineItem === 0;
@@ -613,8 +611,7 @@ const buildChaptersInfo = (href, tocItem, manifest) => {
613
611
  if (isPossibleTocItemCandidate) {
614
612
  const spineItemIndexOfPossibleCandidate = manifest.spineItems.findIndex((item) => item.href === tocItem2.href);
615
613
  const spineItemIsBeforeThisTocItem = spineItemIndex < spineItemIndexOfPossibleCandidate;
616
- if (spineItemIsBeforeThisTocItem)
617
- return acc;
614
+ if (spineItemIsBeforeThisTocItem) return acc;
618
615
  const info = {
619
616
  title: tocItem2.title,
620
617
  path: tocItem2.path
@@ -637,10 +634,9 @@ const buildChapterInfoFromSpineItem = (manifest, item) => {
637
634
  return buildChaptersInfo(href, ((_a = manifest.nav) == null ? void 0 : _a.toc) ?? [], manifest);
638
635
  };
639
636
  const getChaptersInfo = (reader) => {
640
- const manifest = reader.context.getManifest();
641
- const items = reader.getSpineItems();
642
- if (!manifest)
643
- return {};
637
+ const manifest = reader.context.manifest;
638
+ const items = reader.spineItemManager.getAll();
639
+ if (!manifest) return {};
644
640
  return items.reduce(
645
641
  (acc, { item }) => {
646
642
  return {
@@ -652,7 +648,7 @@ const getChaptersInfo = (reader) => {
652
648
  );
653
649
  };
654
650
  const trackChapterInfo = (reader) => {
655
- return reader.spineItems$.pipe(
651
+ return reader.spine.$.spineItems$.pipe(
656
652
  startWith([]),
657
653
  map(() => getChaptersInfo(reader))
658
654
  );
@@ -729,21 +725,19 @@ const getItemOffsetFromPageIndex = (pageWidth, pageIndex, itemWidth) => {
729
725
  return Math.max(0, Math.min(lastPageOffset, logicalOffset));
730
726
  };
731
727
  const calculateNumberOfPagesForItem = (itemWidth, pageWidth) => {
732
- if ((pageWidth || 0) === 0 || (itemWidth || 0) === 0)
733
- return 1;
728
+ if ((pageWidth || 0) === 0 || (itemWidth || 0) === 0) return 1;
734
729
  return Math.floor(Math.max(1, itemWidth / pageWidth));
735
730
  };
736
731
  const getClosestValidOffsetFromApproximateOffsetInPages = (offset, pageWidth, itemWidth) => {
737
732
  const numberOfPages = calculateNumberOfPagesForItem(itemWidth, pageWidth);
738
733
  const offsetValues = [...Array(numberOfPages)].map((_, i) => i * pageWidth);
739
- if (offset >= numberOfPages * pageWidth)
740
- return offsetValues[offsetValues.length - 1] || 0;
734
+ if (offset >= numberOfPages * pageWidth) return offsetValues[offsetValues.length - 1] || 0;
741
735
  return offsetValues.find((offsetRange) => offset < offsetRange + pageWidth) || 0;
742
736
  };
743
737
  const getSpineItemNumberOfPages = ({ spineItem, reader }) => {
744
738
  const writingMode = spineItem.spineItemFrame.getWritingMode();
745
739
  const { width, height } = spineItem.getElementDimensions();
746
- const settings = reader.settings.getSettings();
740
+ const settings = reader.settings.settings;
747
741
  if (settings.pageTurnDirection === `vertical` && settings.pageTurnMode === `scrollable`) {
748
742
  return 1;
749
743
  }
@@ -752,11 +746,11 @@ const getSpineItemNumberOfPages = ({ spineItem, reader }) => {
752
746
  }
753
747
  return calculateNumberOfPagesForItem(width, reader.context.getPageSize().width);
754
748
  };
755
- const getNumberOfPagesForAllSpineItems = (reader) => reader.getSpineItems().map((item) => {
749
+ const getNumberOfPagesForAllSpineItems = (reader) => reader.spineItemManager.getAll().map((item) => {
756
750
  return getSpineItemNumberOfPages({ spineItem: item, reader });
757
751
  }, 0);
758
752
  const trackTotalPages = (reader) => {
759
- const totalPages$ = reader.$.layout$.pipe(
753
+ const totalPages$ = reader.spine.$.layout$.pipe(
760
754
  debounceTime(10, animationFrameScheduler),
761
755
  withLatestFrom$1(reader.pagination.paginationInfo$),
762
756
  map(() => {
@@ -779,8 +773,8 @@ const trackTotalPages = (reader) => {
779
773
  };
780
774
  const mapPaginationInfoToExtendedInfo = (reader) => (paginationInfo, chaptersInfo) => {
781
775
  const context = reader.context;
782
- const beginItem = paginationInfo.beginSpineItemIndex !== void 0 ? reader.getSpineItem(paginationInfo.beginSpineItemIndex) : void 0;
783
- const endItem = paginationInfo.endSpineItemIndex !== void 0 ? reader.getSpineItem(paginationInfo.endSpineItemIndex) : void 0;
776
+ const beginItem = paginationInfo.beginSpineItemIndex !== void 0 ? reader.spineItemManager.get(paginationInfo.beginSpineItemIndex) : void 0;
777
+ const endItem = paginationInfo.endSpineItemIndex !== void 0 ? reader.spineItemManager.get(paginationInfo.endSpineItemIndex) : void 0;
784
778
  return {
785
779
  ...paginationInfo,
786
780
  beginChapterInfo: beginItem ? chaptersInfo[beginItem.item.id] : void 0,
@@ -809,13 +803,13 @@ const mapPaginationInfoToExtendedInfo = (reader) => (paginationInfo, chaptersInf
809
803
  paginationInfo.endSpineItemIndex ?? 0,
810
804
  paginationInfo.endNumberOfPagesInSpineItem,
811
805
  paginationInfo.endPageIndexInSpineItem || 0,
812
- reader.getCurrentViewportPosition(),
806
+ reader.viewportNavigator.getCurrentViewportPosition(),
813
807
  endItem
814
808
  ) : 0,
815
- isUsingSpread: context.isUsingSpreadMode() ?? false
809
+ isUsingSpread: context.state.isUsingSpreadMode ?? false
816
810
  // hasNextChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
817
811
  // hasPreviousChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
818
- // numberOfSpineItems: context.getManifest()?.readingOrder.length,
812
+ // numberOfSpineItems: context.manifest?.readingOrder.length,
819
813
  };
820
814
  };
821
815
  const trackPaginationInfo = (reader) => {
@@ -836,7 +830,10 @@ const trackPaginationInfo = (reader) => {
836
830
  })),
837
831
  distinctUntilChanged$1(isShallowEqual)
838
832
  );
839
- const paginationInfo$ = combineLatest([extandedBasePagination$, totalPages$]).pipe(
833
+ const paginationInfo$ = combineLatest([
834
+ extandedBasePagination$,
835
+ totalPages$
836
+ ]).pipe(
840
837
  map(([pageInfo, totalPageInfo]) => ({
841
838
  ...pageInfo,
842
839
  ...totalPageInfo,
@@ -911,18 +908,22 @@ const themeEnhancer = (next) => (options) => {
911
908
  };
912
909
  };
913
910
  const applyChangeToSpineItem = () => {
914
- reader.manipulateSpineItems(({ removeStyle, addStyle, container }) => {
911
+ reader.spine.manipulateSpineItems(({ removeStyle, addStyle, container }) => {
915
912
  removeStyle(`prose-reader-theme`);
916
913
  addStyle(`prose-reader-theme`, getStyle());
917
914
  applyChangeToSpineItemElement({ container });
918
915
  return false;
919
916
  });
920
917
  };
921
- reader.registerHook(`item.onLoad`, ({ removeStyle, addStyle }) => {
922
- removeStyle(`prose-reader-theme`);
923
- addStyle(`prose-reader-theme`, getStyle());
918
+ reader.hookManager.register(`item.onLoad`, ({ itemId }) => {
919
+ const item = reader.spineItemManager.get(itemId);
920
+ item == null ? void 0 : item.manipulateSpineItem(({ removeStyle, addStyle }) => {
921
+ removeStyle(`prose-reader-theme`);
922
+ addStyle(`prose-reader-theme`, getStyle());
923
+ return false;
924
+ });
924
925
  });
925
- reader.spineItems$.pipe(
926
+ reader.spine.$.spineItems$.pipe(
926
927
  tap((items) => items.map(({ element }) => applyChangeToSpineItemElement({ container: element }))),
927
928
  takeUntil$1(reader.$.destroy$)
928
929
  ).subscribe();
@@ -959,7 +960,7 @@ const createElementZoomer = (reader) => {
959
960
  imgLastPosition = { x: 0, y: 0 };
960
961
  baseScale = 1;
961
962
  lastUserScale = 1;
962
- const container = reader.context.getState().containerElement;
963
+ const container = reader.context.state.containerElement;
963
964
  if (container) {
964
965
  imageMagnifierContainer = container.ownerDocument.createElement(`div`);
965
966
  imageMagnifierContainer.style.cssText = `
@@ -1017,6 +1018,7 @@ const createElementZoomer = (reader) => {
1017
1018
  `transform`,
1018
1019
  `translate3d(${imgLastPosition.x}px, ${imgLastPosition.y}px, 0px) scale3d(${baseScale}, ${baseScale}, 1)`
1019
1020
  );
1021
+ console.log({ delta, imgLastPosition });
1020
1022
  movingLastDelta = delta;
1021
1023
  }
1022
1024
  if (isLast) {
@@ -1084,8 +1086,7 @@ const createViewportZoomer = (reader) => {
1084
1086
  const scale = (userScale) => {
1085
1087
  const spineElement = reader.spine.getElement();
1086
1088
  const viewportElement = reader.viewportNavigator.getElement();
1087
- if (!spineElement || !viewportElement)
1088
- return;
1089
+ if (!spineElement || !viewportElement) return;
1089
1090
  const roundedScale = Math.ceil((userScale < 1 ? baseScale - (1 - userScale) : baseScale + (userScale - 1)) * 100) / 100;
1090
1091
  const newScale = Math.max(roundedScale, 1);
1091
1092
  const currentScale = spineElement.getBoundingClientRect().width / spineElement.offsetWidth;
@@ -1134,7 +1135,7 @@ const zoomEnhancer = (next) => (options) => {
1134
1135
  const elementZoomer = createElementZoomer(reader);
1135
1136
  const viewportZoomer = createViewportZoomer(reader);
1136
1137
  const currentZoomerSubject$ = new BehaviorSubject(void 0);
1137
- const isUsingScrollableViewport = () => reader.settings.getSettings().computedPageTurnMode === `scrollable`;
1138
+ const isUsingScrollableViewport = () => reader.settings.settings.computedPageTurnMode === `scrollable`;
1138
1139
  const enter = (imgElement) => {
1139
1140
  var _a;
1140
1141
  (_a = currentZoomerSubject$ == null ? void 0 : currentZoomerSubject$.value) == null ? void 0 : _a.exit();
@@ -1207,153 +1208,108 @@ const isUsingSpreadMode = ({
1207
1208
  }) => {
1208
1209
  const { height, width } = visibleAreaRect;
1209
1210
  const isLandscape = width > height;
1210
- if (forceSinglePageMode)
1211
- return false;
1212
- if ((manifest == null ? void 0 : manifest.renditionFlow) === `scrolled-continuous`)
1213
- return false;
1211
+ if (forceSinglePageMode) return false;
1212
+ if ((manifest == null ? void 0 : manifest.renditionFlow) === `scrolled-continuous`) return false;
1214
1213
  if (!isLandscape && (manifest == null ? void 0 : manifest.renditionSpread) === `portrait`) {
1215
1214
  return true;
1216
1215
  }
1217
1216
  return isLandscape && ((manifest == null ? void 0 : manifest.renditionSpread) === void 0 || (manifest == null ? void 0 : manifest.renditionSpread) === `auto` || (manifest == null ? void 0 : manifest.renditionSpread) === `landscape` || (manifest == null ? void 0 : manifest.renditionSpread) === `both`);
1218
1217
  };
1219
1218
  const isFullyPrePaginated = (manifest) => (manifest == null ? void 0 : manifest.renditionLayout) === "pre-paginated" || (manifest == null ? void 0 : manifest.spineItems.every((item) => item.renditionLayout === "pre-paginated"));
1220
- const createContext = (settings) => {
1221
- const stateSubject = new BehaviorSubject({});
1222
- const manifest$ = stateSubject.pipe(
1223
- map$1((state) => state.manifest),
1224
- filter(isDefined),
1225
- distinctUntilChanged()
1226
- );
1227
- const containerElement$ = stateSubject.pipe(
1228
- map$1((state) => state.containerElement),
1229
- filter(isDefined),
1230
- distinctUntilChanged()
1231
- );
1232
- const hasVerticalWriting$ = stateSubject.pipe(
1233
- map$1((state) => state.hasVerticalWriting),
1234
- filter(isDefined),
1235
- distinctUntilChanged()
1236
- );
1237
- const isUsingSpreadMode$ = stateSubject.pipe(
1238
- map$1((state) => state.isUsingSpreadMode),
1239
- distinctUntilChanged()
1240
- );
1241
- const visibleAreaRect = {
1242
- width: 0,
1243
- height: 0,
1244
- x: 0,
1245
- y: 0
1246
- };
1247
- const marginTop = 0;
1248
- const marginBottom = 0;
1249
- const destroy$ = new Subject();
1250
- const setState = (newState) => {
1251
- const newCompleteState = { ...stateSubject.getValue(), ...newState };
1252
- if (!isShallowEqual(newCompleteState, stateSubject.getValue())) {
1253
- stateSubject.next(newCompleteState);
1254
- }
1255
- };
1256
- const load = (newManifest, newLoadOptions) => {
1257
- setState({
1258
- manifest: newManifest,
1259
- ...newLoadOptions,
1260
- isFullyPrePaginated: isFullyPrePaginated(newManifest),
1219
+ const areAllItemsPrePaginated = (manifest) => !(manifest == null ? void 0 : manifest.spineItems.some((item) => item.renditionLayout === `reflowable`));
1220
+ class Context {
1221
+ constructor() {
1222
+ this._stateSubject = new BehaviorSubject({
1223
+ marginBottom: 0,
1224
+ marginTop: 0,
1225
+ calculatedInnerMargin: 0,
1226
+ visibleAreaRect: {
1227
+ width: 0,
1228
+ height: 0,
1229
+ x: 0,
1230
+ y: 0
1231
+ }
1232
+ });
1233
+ this.destroy$ = new Subject();
1234
+ this.state$ = this._stateSubject.pipe(distinctUntilChanged(isShallowEqual));
1235
+ this.manifest$ = this._stateSubject.pipe(
1236
+ map$1((state) => state.manifest),
1237
+ filter(isDefined),
1238
+ distinctUntilChanged()
1239
+ );
1240
+ this.containerElement$ = this._stateSubject.pipe(
1241
+ map$1((state) => state.containerElement),
1242
+ filter(isDefined),
1243
+ distinctUntilChanged()
1244
+ );
1245
+ this.hasVerticalWriting$ = this._stateSubject.pipe(
1246
+ map$1((state) => state.hasVerticalWriting),
1247
+ filter(isDefined),
1248
+ distinctUntilChanged()
1249
+ );
1250
+ this.isUsingSpreadMode$ = this._stateSubject.pipe(
1251
+ map$1((state) => state.isUsingSpreadMode),
1252
+ distinctUntilChanged()
1253
+ );
1254
+ this.isRTL = () => {
1255
+ var _a;
1256
+ return ((_a = this._stateSubject.getValue().manifest) == null ? void 0 : _a.readingDirection) === `rtl`;
1257
+ };
1258
+ this.destroy = () => {
1259
+ this._stateSubject.complete();
1260
+ this.destroy$.next();
1261
+ this.destroy$.complete();
1262
+ };
1263
+ }
1264
+ /**
1265
+ * @todo optimize to not run if not necessary
1266
+ */
1267
+ update(newState) {
1268
+ const previousState = this._stateSubject.getValue();
1269
+ const manifest = newState.manifest ?? previousState.manifest;
1270
+ const forceSinglePageMode = newState.forceSinglePageMode ?? previousState.forceSinglePageMode;
1271
+ const visibleAreaRect = newState.visibleAreaRect ?? previousState.visibleAreaRect;
1272
+ const marginTop = newState.marginTop ?? previousState.marginTop;
1273
+ const marginBottom = newState.marginBottom ?? previousState.marginBottom;
1274
+ const newCompleteState = {
1275
+ ...previousState,
1276
+ ...newState,
1277
+ ...newState.visibleAreaRect && {
1278
+ ...newState.visibleAreaRect,
1279
+ height: newState.visibleAreaRect.height - marginTop - marginBottom
1280
+ },
1281
+ ...newState.manifest && {
1282
+ areAllItemsPrePaginated: areAllItemsPrePaginated(manifest),
1283
+ isFullyPrePaginated: isFullyPrePaginated(manifest)
1284
+ },
1261
1285
  isUsingSpreadMode: isUsingSpreadMode({
1262
- manifest: newManifest,
1286
+ manifest,
1263
1287
  visibleAreaRect,
1264
- forceSinglePageMode: settings.getSettings().forceSinglePageMode
1288
+ forceSinglePageMode
1265
1289
  })
1266
- });
1267
- };
1268
- const isRTL = () => {
1269
- var _a;
1270
- return ((_a = stateSubject.getValue().manifest) == null ? void 0 : _a.readingDirection) === `rtl`;
1271
- };
1272
- const setHasVerticalWriting = (value) => setState({
1273
- hasVerticalWriting: value
1274
- });
1275
- const recomputeSettings$ = merge(hasVerticalWriting$, manifest$);
1276
- recomputeSettings$.pipe(
1277
- withLatestFrom(hasVerticalWriting$, manifest$),
1278
- tap(([, hasVerticalWriting, manifest]) => {
1279
- settings.recompute({ hasVerticalWriting, manifest });
1280
- }),
1281
- takeUntil$1(destroy$)
1282
- ).subscribe();
1283
- settings.$.settings$.pipe(
1284
- map$1(({ forceSinglePageMode }) => forceSinglePageMode),
1285
- distinctUntilChanged(),
1286
- withLatestFrom(manifest$),
1287
- tap(([forceSinglePageMode, manifest]) => {
1288
- setState({
1289
- isUsingSpreadMode: isUsingSpreadMode({
1290
- manifest,
1291
- visibleAreaRect,
1292
- forceSinglePageMode
1293
- })
1294
- });
1295
- }),
1296
- takeUntil$1(destroy$)
1297
- ).subscribe();
1298
- const destroy = () => {
1299
- stateSubject.complete();
1300
- destroy$.next();
1301
- destroy$.complete();
1302
- };
1303
- return {
1304
- load,
1305
- isRTL,
1306
- areAllItemsPrePaginated: () => {
1307
- var _a;
1308
- return areAllItemsPrePaginated$1((_a = stateSubject.getValue()) == null ? void 0 : _a.manifest);
1309
- },
1310
- destroy,
1311
- getCalculatedInnerMargin: () => 0,
1312
- getVisibleAreaRect: () => visibleAreaRect,
1313
- isUsingSpreadMode: () => stateSubject.getValue().isUsingSpreadMode,
1314
- setHasVerticalWriting,
1315
- setVisibleAreaRect: ({ height, width, x, y }) => {
1316
- visibleAreaRect.width = width;
1317
- visibleAreaRect.height = height - marginTop - marginBottom;
1318
- visibleAreaRect.x = x;
1319
- visibleAreaRect.y = y;
1320
- const manifest = stateSubject.getValue().manifest;
1321
- if (manifest) {
1322
- setState({
1323
- isUsingSpreadMode: isUsingSpreadMode({
1324
- manifest,
1325
- visibleAreaRect,
1326
- forceSinglePageMode: settings.getSettings().forceSinglePageMode
1327
- })
1328
- });
1329
- }
1330
- },
1331
- getState: () => stateSubject.getValue(),
1332
- getManifest: () => {
1333
- var _a;
1334
- return (_a = stateSubject.getValue()) == null ? void 0 : _a.manifest;
1335
- },
1336
- getReadingDirection: () => {
1337
- var _a, _b;
1338
- return (_b = (_a = stateSubject.getValue()) == null ? void 0 : _a.manifest) == null ? void 0 : _b.readingDirection;
1339
- },
1340
- getPageSize: () => {
1341
- return {
1342
- width: stateSubject.getValue().isUsingSpreadMode ? visibleAreaRect.width / 2 : visibleAreaRect.width,
1343
- height: visibleAreaRect.height
1344
- };
1345
- },
1346
- containerElement$,
1347
- isUsingSpreadMode$,
1348
- hasVerticalWriting$,
1349
- $: {
1350
- manifest$,
1351
- destroy$: destroy$.asObservable(),
1352
- state$: stateSubject.asObservable()
1290
+ };
1291
+ if (!isShallowEqual(newCompleteState, previousState)) {
1292
+ this._stateSubject.next(newCompleteState);
1353
1293
  }
1354
- };
1355
- };
1356
- const areAllItemsPrePaginated$1 = (manifest) => !(manifest == null ? void 0 : manifest.spineItems.some((item) => item.renditionLayout === `reflowable`));
1294
+ }
1295
+ get state() {
1296
+ return this._stateSubject.getValue();
1297
+ }
1298
+ get manifest() {
1299
+ return this.state.manifest;
1300
+ }
1301
+ get readingDirection() {
1302
+ var _a;
1303
+ return (_a = this.manifest) == null ? void 0 : _a.readingDirection;
1304
+ }
1305
+ getPageSize() {
1306
+ const { isUsingSpreadMode: isUsingSpreadMode2, visibleAreaRect } = this._stateSubject.getValue();
1307
+ return {
1308
+ width: isUsingSpreadMode2 ? visibleAreaRect.width / 2 : visibleAreaRect.width,
1309
+ height: visibleAreaRect.height
1310
+ };
1311
+ }
1312
+ }
1357
1313
  const __UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT_KEY = `__UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT`;
1358
1314
  const ITEM_EXTENSION_VALID_FOR_FRAME_SRC = [`.xhtml`, `.html`, `.htm`];
1359
1315
  const HTML_PREFIX$1 = `prose-reader`;
@@ -1406,11 +1362,6 @@ const createFrame$ = Report.measurePerformance(`SpineItemFrame createFrame`, Inf
1406
1362
  `;
1407
1363
  return of(frame);
1408
1364
  });
1409
- const createFrameManipulator = (frameElement) => ({
1410
- frame: frameElement,
1411
- removeStyle: createRemoveStyleHelper(frameElement),
1412
- addStyle: createAddStyleHelper(frameElement)
1413
- });
1414
1365
  const getIntrinsicDimensionsFromBase64Img = (data) => new Promise((resolve, reject) => {
1415
1366
  const image = new Image();
1416
1367
  image.src = data;
@@ -1420,8 +1371,7 @@ const getIntrinsicDimensionsFromBase64Img = (data) => new Promise((resolve, reje
1420
1371
  image.onerror = reject;
1421
1372
  });
1422
1373
  const createHtmlPageFromResource = async (resourceResponse, item) => {
1423
- if (typeof resourceResponse === `string`)
1424
- return resourceResponse;
1374
+ if (typeof resourceResponse === `string`) return resourceResponse;
1425
1375
  const contentType = parseContentType(resourceResponse.headers.get(`Content-Type`) || ``) || detectMimeTypeFromName(item.href);
1426
1376
  if ([`image/jpg`, `image/jpeg`, `image/png`, `image/webp`].some((mime) => mime === contentType)) {
1427
1377
  const data = await getBase64FromBlob(await resourceResponse.blob());
@@ -1463,15 +1413,14 @@ const createHtmlPageFromResource = async (resourceResponse, item) => {
1463
1413
  const content = await resourceResponse.text();
1464
1414
  return content;
1465
1415
  };
1466
- const isOnLoadHook = (hook) => hook.name === `item.onLoad`;
1467
1416
  const createLoader = ({
1468
1417
  item,
1469
1418
  parent,
1470
1419
  fetchResource,
1471
- hooks$,
1472
1420
  context,
1473
1421
  viewportState$,
1474
- settings
1422
+ settings,
1423
+ hookManager
1475
1424
  }) => {
1476
1425
  const destroySubject$ = new Subject();
1477
1426
  const loadSubject$ = new Subject();
@@ -1479,10 +1428,9 @@ const createLoader = ({
1479
1428
  const frameElementSubject$ = new BehaviorSubject(void 0);
1480
1429
  const isLoadedSubject$ = new BehaviorSubject(false);
1481
1430
  const isReadySubject$ = new BehaviorSubject(false);
1482
- let onLoadHookReturns = [];
1483
1431
  let computedStyleAfterLoad;
1484
1432
  const makeItHot = (source$) => {
1485
- source$.pipe(takeUntil$1(context.$.destroy$)).subscribe();
1433
+ source$.pipe(takeUntil$1(context.destroy$)).subscribe();
1486
1434
  return source$;
1487
1435
  };
1488
1436
  const getHtmlFromResource = (response) => createHtmlPageFromResource(response, item);
@@ -1496,14 +1444,7 @@ const createLoader = ({
1496
1444
  withLatestFrom(frameElementSubject$),
1497
1445
  filter(([_, frame]) => !!frame),
1498
1446
  map$1(([, frame]) => {
1499
- onLoadHookReturns.forEach((fn) => {
1500
- if (fn && `unsubscribe` in fn) {
1501
- fn.unsubscribe();
1502
- } else if (fn) {
1503
- fn();
1504
- }
1505
- });
1506
- onLoadHookReturns = [];
1447
+ hookManager.destroy(`item.onLoad`, item.id);
1507
1448
  frame == null ? void 0 : frame.remove();
1508
1449
  frameElementSubject$.next(void 0);
1509
1450
  }),
@@ -1544,12 +1485,10 @@ const createLoader = ({
1544
1485
  }
1545
1486
  }),
1546
1487
  mergeMap((frame) => {
1547
- if (!frame)
1548
- return EMPTY;
1488
+ if (!frame) return EMPTY;
1549
1489
  return fromEvent(frame, `load`).pipe(
1550
1490
  take(1),
1551
- withLatestFrom(hooks$),
1552
- mergeMap(([_, hooks]) => {
1491
+ mergeMap(() => {
1553
1492
  var _a, _b;
1554
1493
  const body = (_a = frame.contentDocument) == null ? void 0 : _a.body;
1555
1494
  if (!body) {
@@ -1560,21 +1499,14 @@ const createLoader = ({
1560
1499
  if ((frame == null ? void 0 : frame.contentDocument) && body) {
1561
1500
  computedStyleAfterLoad = (_b = frame == null ? void 0 : frame.contentWindow) == null ? void 0 : _b.getComputedStyle(body);
1562
1501
  }
1563
- if (settings.getSettings().computedPageTurnMode !== `scrollable`) {
1502
+ if (settings.settings.computedPageTurnMode !== `scrollable`) {
1564
1503
  frame.setAttribute(`tab-index`, `0`);
1565
1504
  }
1566
- const manipulableFrame = createFrameManipulator(frame);
1567
- onLoadHookReturns = hooks.filter(isOnLoadHook).map((hook) => {
1568
- const hookReturn = hook.fn({
1569
- ...manipulableFrame,
1570
- item
1571
- });
1572
- if (hookReturn && `subscribe` in hookReturn) {
1573
- return hookReturn.subscribe();
1574
- }
1575
- return hookReturn;
1576
- });
1577
- return of(frame);
1505
+ const hookResults = hookManager.execute(`item.onLoad`, item.id, {
1506
+ itemId: item.id,
1507
+ frame
1508
+ }).filter((result) => result instanceof Observable);
1509
+ return combineLatest([of(null), ...hookResults]).pipe(map$1(() => frame));
1578
1510
  })
1579
1511
  );
1580
1512
  }),
@@ -1623,14 +1555,19 @@ const createLoader = ({
1623
1555
  }
1624
1556
  };
1625
1557
  };
1558
+ const createFrameManipulator = (frameElement) => ({
1559
+ frame: frameElement,
1560
+ removeStyle: createRemoveStyleHelper(frameElement),
1561
+ addStyle: createAddStyleHelper(frameElement)
1562
+ });
1626
1563
  const createFrameItem = ({
1627
1564
  item,
1628
1565
  parent,
1629
1566
  fetchResource,
1630
1567
  context,
1631
- hooks$,
1632
1568
  viewportState$,
1633
- settings
1569
+ settings,
1570
+ hookManager
1634
1571
  }) => {
1635
1572
  const destroySubject$ = new Subject();
1636
1573
  const {
@@ -1639,7 +1576,7 @@ const createFrameItem = ({
1639
1576
  unload,
1640
1577
  destroy: loaderDestroy,
1641
1578
  getComputedStyleAfterLoad
1642
- } = createLoader({ context, hooks$, item, parent, fetchResource, viewportState$, settings });
1579
+ } = createLoader({ context, hookManager, item, parent, fetchResource, viewportState$, settings });
1643
1580
  let isLoadedSync = false;
1644
1581
  let isReadySync = false;
1645
1582
  isLoaded$.subscribe({
@@ -1727,7 +1664,7 @@ const createFrameItem = ({
1727
1664
  if (frame) {
1728
1665
  frame.style.width = `${size.width}px`;
1729
1666
  frame.style.height = `${size.height}px`;
1730
- if (settings.getSettings().computedPageTurnMode !== `scrollable`) {
1667
+ if (settings.settings.computedPageTurnMode !== `scrollable`) {
1731
1668
  frame.setAttribute(`tab-index`, `0`);
1732
1669
  }
1733
1670
  }
@@ -1742,8 +1679,7 @@ const createFrameItem = ({
1742
1679
  return `rtl`;
1743
1680
  }
1744
1681
  const direction = (_a = getComputedStyleAfterLoad()) == null ? void 0 : _a.direction;
1745
- if ([`ltr`, `rtl`].includes(direction || ``))
1746
- return direction;
1682
+ if ([`ltr`, `rtl`].includes(direction || ``)) return direction;
1747
1683
  return void 0;
1748
1684
  },
1749
1685
  isUsingVerticalWriting,
@@ -1830,205 +1766,30 @@ const createSelectionTracker = () => {
1830
1766
  getSelection: () => {
1831
1767
  var _a;
1832
1768
  const selection = (_a = frame == null ? void 0 : frame.contentWindow) == null ? void 0 : _a.getSelection();
1833
- if (!(selection == null ? void 0 : selection.anchorNode) || selection.type === `None` || selection.type === `Caret`)
1834
- return void 0;
1769
+ if (!(selection == null ? void 0 : selection.anchorNode) || selection.type === `None` || selection.type === `Caret`) return void 0;
1835
1770
  return selection;
1836
1771
  },
1837
1772
  $: subject.asObservable()
1838
1773
  };
1839
- };
1840
- const isHtmlElement = (element) => {
1841
- return typeof element === `object` && !!element && `nodeType` in element && (element == null ? void 0 : element.nodeType) === Node.ELEMENT_NODE && `innerText` in element;
1842
- };
1843
- function createRangeOrCaretFromPoint(doc, startX, startY) {
1844
- if (`caretPositionFromPoint` in doc) {
1845
- return doc.caretPositionFromPoint(startX, startY);
1846
- } else if (typeof doc.caretRangeFromPoint !== `undefined`) {
1847
- return doc.caretRangeFromPoint(startX, startY);
1848
- }
1849
- }
1850
- const getFirstVisibleNodeForViewport = Report.measurePerformance(
1851
- `getFirstVisibleNodeForViewport`,
1852
- 1,
1853
- (documentOrElement, viewport) => {
1854
- const element = `body` in documentOrElement ? getFirstVisibleElementForViewport(documentOrElement.body, viewport) : getFirstVisibleElementForViewport(documentOrElement, viewport);
1855
- const ownerDocument = `createRange` in documentOrElement ? documentOrElement : documentOrElement.ownerDocument;
1856
- if (element) {
1857
- let lastValidRange;
1858
- let lastValidOffset = 0;
1859
- const range = ownerDocument.createRange();
1860
- Array.from(element.childNodes).some((childNode) => {
1861
- range.selectNodeContents(childNode);
1862
- const rects = range.getClientRects();
1863
- const visibleRect = getFirstVisibleDOMRect(rects, viewport);
1864
- if (visibleRect) {
1865
- lastValidRange = range.cloneRange();
1866
- const rangeOrCaret = createRangeOrCaretFromPoint(ownerDocument, Math.ceil(visibleRect.left), Math.ceil(visibleRect.top));
1867
- if (rangeOrCaret && `startContainer` in rangeOrCaret && rangeOrCaret.startContainer === lastValidRange.startContainer) {
1868
- lastValidOffset = rangeOrCaret.startOffset;
1869
- }
1870
- if (rangeOrCaret && `offsetNode` in rangeOrCaret && rangeOrCaret.offsetNode === lastValidRange.startContainer) {
1871
- lastValidOffset = rangeOrCaret.offset;
1872
- }
1873
- return true;
1874
- }
1875
- return false;
1876
- });
1877
- if (lastValidRange) {
1878
- return { node: lastValidRange.startContainer, offset: lastValidOffset };
1879
- }
1880
- return { node: element, offset: 0 };
1881
- }
1882
- return void 0;
1883
- }
1884
- );
1885
- const getFirstVisibleElementForViewport = (element, viewport) => {
1886
- let lastValidElement;
1887
- const positionFromViewport = getElementOrNodePositionFromViewPort(element.getBoundingClientRect(), viewport);
1888
- if (positionFromViewport !== `before` && positionFromViewport !== `after`) {
1889
- lastValidElement = element;
1890
- }
1891
- Array.from(element.children).some((child) => {
1892
- const childInViewPort = getFirstVisibleElementForViewport(child, viewport);
1893
- if (childInViewPort) {
1894
- lastValidElement = childInViewPort;
1895
- return true;
1896
- }
1897
- return false;
1898
- });
1899
- return lastValidElement;
1900
- };
1901
- function getElementOrNodePositionFromViewPort(domRect, { left, right }) {
1902
- if (domRect.left <= left && domRect.right <= left)
1903
- return `before`;
1904
- if (domRect.left <= left && domRect.right > left && domRect.right <= right)
1905
- return `partially-before`;
1906
- if (domRect.left <= right && domRect.right > right)
1907
- return `partially-after`;
1908
- if (domRect.left > right)
1909
- return `after`;
1910
- return `within`;
1911
- }
1912
- function getFirstVisibleDOMRect(domRect, viewport) {
1913
- return Array.from(domRect).find((domRect2) => {
1914
- const position = getElementOrNodePositionFromViewPort(domRect2, viewport);
1915
- if (position !== `before` && position !== `after`) {
1916
- return true;
1917
- }
1918
- return false;
1919
- });
1920
- }
1921
- const getRangeFromNode = (node, offset) => {
1922
- var _a;
1923
- if (node.nodeType !== Node.CDATA_SECTION_NODE && node.nodeType !== Node.DOCUMENT_TYPE_NODE) {
1924
- const range = (_a = node.ownerDocument) == null ? void 0 : _a.createRange();
1925
- range == null ? void 0 : range.selectNodeContents(node);
1926
- try {
1927
- if (offset <= ((range == null ? void 0 : range.endOffset) || 0)) {
1928
- range == null ? void 0 : range.setStart(node, offset || 0);
1929
- }
1930
- } catch (e) {
1931
- Report.error(e);
1932
- }
1933
- return range;
1934
- }
1935
- return void 0;
1936
- };
1937
- const isPointerEvent = (event) => {
1938
- var _a, _b, _c, _d, _e;
1939
- if ((event == null ? void 0 : event.target) && ((_b = (_a = event == null ? void 0 : event.target) == null ? void 0 : _a.ownerDocument) == null ? void 0 : _b.defaultView)) {
1940
- const eventView = (_d = (_c = event == null ? void 0 : event.target) == null ? void 0 : _c.ownerDocument) == null ? void 0 : _d.defaultView;
1941
- if (eventView.PointerEvent) {
1942
- return event instanceof eventView.PointerEvent;
1943
- }
1944
- }
1945
- if ((event == null ? void 0 : event.view) && ((_e = event == null ? void 0 : event.view) == null ? void 0 : _e.window)) {
1946
- const eventView = event == null ? void 0 : event.view;
1947
- if (eventView.PointerEvent) {
1948
- return event instanceof eventView.PointerEvent;
1949
- }
1950
- }
1951
- return false;
1952
- };
1953
- const isMouseEvent = (event) => {
1954
- var _a, _b, _c, _d, _e;
1955
- if (isPointerEvent(event))
1956
- return false;
1957
- if ((event == null ? void 0 : event.target) && ((_b = (_a = event == null ? void 0 : event.target) == null ? void 0 : _a.ownerDocument) == null ? void 0 : _b.defaultView)) {
1958
- const eventView = (_d = (_c = event == null ? void 0 : event.target) == null ? void 0 : _c.ownerDocument) == null ? void 0 : _d.defaultView;
1959
- if (eventView.MouseEvent) {
1960
- return event instanceof eventView.MouseEvent;
1961
- }
1962
- }
1963
- if ((event == null ? void 0 : event.view) && ((_e = event == null ? void 0 : event.view) == null ? void 0 : _e.window)) {
1964
- const eventView = event == null ? void 0 : event.view;
1965
- if (eventView.MouseEvent) {
1966
- return event instanceof eventView.MouseEvent;
1967
- }
1968
- }
1969
- return false;
1970
- };
1971
- const isTouchEvent = (event) => {
1972
- var _a, _b, _c, _d, _e;
1973
- if ((event == null ? void 0 : event.target) && ((_b = (_a = event == null ? void 0 : event.target) == null ? void 0 : _a.ownerDocument) == null ? void 0 : _b.defaultView)) {
1974
- const eventView = (_d = (_c = event == null ? void 0 : event.target) == null ? void 0 : _c.ownerDocument) == null ? void 0 : _d.defaultView;
1975
- if (eventView.TouchEvent) {
1976
- return event instanceof eventView.TouchEvent;
1977
- }
1978
- }
1979
- if ((event == null ? void 0 : event.view) && ((_e = event == null ? void 0 : event.view) == null ? void 0 : _e.window)) {
1980
- const eventView = event == null ? void 0 : event.view;
1981
- if (eventView.TouchEvent) {
1982
- return event instanceof eventView.TouchEvent;
1983
- }
1984
- }
1985
- return false;
1986
- };
1987
- const pointerEvents = [
1988
- `pointercancel`,
1989
- `pointerdown`,
1990
- `pointerenter`,
1991
- `pointerleave`,
1992
- `pointermove`,
1993
- `pointerout`,
1994
- `pointerover`,
1995
- `pointerup`,
1996
- `touchstart`,
1997
- `touchend`
1998
- ];
1999
- const mouseEvents = [
2000
- `click`,
2001
- `mousedown`,
2002
- `mouseup`,
2003
- `mouseenter`,
2004
- `mouseleave`,
2005
- `mousemove`,
2006
- `mouseout`,
2007
- `mouseover`
2008
- ];
2009
- const passthroughEvents = [...pointerEvents, ...mouseEvents];
1774
+ };
2010
1775
  const createCommonSpineItem = ({
2011
1776
  item,
2012
1777
  context,
2013
1778
  parentElement,
2014
- iframeEventBridgeElement$,
2015
- hooks$,
2016
1779
  viewportState$,
2017
- settings
1780
+ settings,
1781
+ hookManager
2018
1782
  }) => {
2019
- var _a;
2020
1783
  const destroySubject$ = new Subject();
2021
- const containerElement = createContainerElement$1(parentElement, item, hooks$);
1784
+ const containerElement = createContainerElement$1(parentElement, item, hookManager);
2022
1785
  const overlayElement = createOverlayElement(parentElement, item);
2023
1786
  const fingerTracker = createFingerTracker();
2024
1787
  const selectionTracker = createSelectionTracker();
2025
- const frameHooks = createFrameHooks(iframeEventBridgeElement$, fingerTracker, selectionTracker);
2026
1788
  const spineItemFrame = createFrameItem({
2027
1789
  parent: containerElement,
2028
1790
  item,
2029
1791
  context,
2030
- fetchResource: (_a = context.getState()) == null ? void 0 : _a.fetchResource,
2031
- hooks$: hooks$.asObservable().pipe(map$1((hooks) => [...hooks, ...frameHooks])),
1792
+ hookManager,
2032
1793
  viewportState$,
2033
1794
  settings
2034
1795
  });
@@ -2051,12 +1812,12 @@ const createCommonSpineItem = ({
2051
1812
  return memoizedElementDimensions;
2052
1813
  };
2053
1814
  const isImageType = () => {
2054
- var _a2;
2055
- return !!((_a2 = item.mediaType) == null ? void 0 : _a2.startsWith(`image/`));
1815
+ var _a;
1816
+ return !!((_a = item.mediaType) == null ? void 0 : _a.startsWith(`image/`));
2056
1817
  };
2057
1818
  const injectStyle = (cssText) => {
2058
- var _a2, _b;
2059
- (_a2 = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a2.removeStyle(`prose-reader-css`);
1819
+ var _a, _b;
1820
+ (_a = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a.removeStyle(`prose-reader-css`);
2060
1821
  (_b = spineItemFrame.getManipulableFrame()) == null ? void 0 : _b.addStyle(`prose-reader-css`, cssText);
2061
1822
  };
2062
1823
  const adjustPositionOfElement = ({ right, left, top }) => {
@@ -2077,10 +1838,10 @@ const createCommonSpineItem = ({
2077
1838
  }
2078
1839
  };
2079
1840
  const getViewPortInformation = () => {
2080
- var _a2;
1841
+ var _a;
2081
1842
  const { width: pageWidth, height: pageHeight } = context.getPageSize();
2082
1843
  const viewportDimensions = spineItemFrame.getViewportDimensions();
2083
- const frameElement = (_a2 = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a2.frame;
1844
+ const frameElement = (_a = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a.frame;
2084
1845
  if (containerElement && (frameElement == null ? void 0 : frameElement.contentDocument) && (frameElement == null ? void 0 : frameElement.contentWindow) && viewportDimensions) {
2085
1846
  const computedWidthScale = pageWidth / viewportDimensions.width;
2086
1847
  const computedScale = Math.min(computedWidthScale, pageHeight / viewportDimensions.height);
@@ -2090,8 +1851,8 @@ const createCommonSpineItem = ({
2090
1851
  const loadContent = () => spineItemFrame.load();
2091
1852
  const unloadContent = () => spineItemFrame.unload();
2092
1853
  const getBoundingRectOfElementFromSelector = (selector) => {
2093
- var _a2, _b, _c, _d, _e;
2094
- const frame = (_a2 = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a2.frame;
1854
+ var _a, _b, _c, _d, _e;
1855
+ const frame = (_a = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a.frame;
2095
1856
  if (frame && selector) {
2096
1857
  if (selector.startsWith(`#`)) {
2097
1858
  return (_c = (_b = frame.contentDocument) == null ? void 0 : _b.getElementById(selector.replace(`#`, ``))) == null ? void 0 : _c.getBoundingClientRect();
@@ -2136,16 +1897,12 @@ const createCommonSpineItem = ({
2136
1897
  }) => {
2137
1898
  containerElement.style.width = `${width}px`;
2138
1899
  containerElement.style.height = `${height}px`;
2139
- hooks$.getValue().forEach((hook) => {
2140
- if (hook.name === `item.onAfterLayout`) {
2141
- hook.fn({ blankPagePosition, item, minimumWidth });
2142
- }
2143
- });
1900
+ hookManager.execute(`item.onAfterLayout`, void 0, { blankPagePosition, item, minimumWidth });
2144
1901
  setLayoutDirty();
2145
1902
  };
2146
1903
  const translateFramePositionIntoPage = (position) => {
2147
- var _a2, _b;
2148
- const { left = 0, top = 0 } = ((_a2 = spineItemFrame.getFrameElement()) == null ? void 0 : _a2.getBoundingClientRect()) || {};
1904
+ var _a, _b;
1905
+ const { left = 0, top = 0 } = ((_a = spineItemFrame.getFrameElement()) == null ? void 0 : _a.getBoundingClientRect()) || {};
2149
1906
  const computedScale = ((_b = getViewPortInformation()) == null ? void 0 : _b.computedScale) ?? 1;
2150
1907
  const adjustedX = position.clientX * computedScale + left;
2151
1908
  const adjustedY = position.clientY * computedScale + top;
@@ -2155,20 +1912,14 @@ const createCommonSpineItem = ({
2155
1912
  };
2156
1913
  };
2157
1914
  const getResource = async () => {
2158
- const fetchResource = context.getState().fetchResource;
1915
+ const fetchResource = settings.settings.fetchResource;
2159
1916
  const lastFetch = (_) => {
2160
1917
  if (fetchResource) {
2161
1918
  return fetchResource(item);
2162
1919
  }
2163
1920
  return fetch(item.href);
2164
1921
  };
2165
- const finalFetch = hooks$.getValue().reduce((acc, hook) => {
2166
- if (hook.name === `item.onGetResource`) {
2167
- return hook.fn(acc);
2168
- }
2169
- return acc;
2170
- }, lastFetch);
2171
- return await finalFetch(item);
1922
+ return await lastFetch();
2172
1923
  };
2173
1924
  const manipulateSpineItem = (cb) => {
2174
1925
  const manipulableFrame = spineItemFrame.getManipulableFrame();
@@ -2191,16 +1942,12 @@ const createCommonSpineItem = ({
2191
1942
  overlayElement
2192
1943
  });
2193
1944
  };
2194
- const executeOnLayoutBeforeMeasurementHook = (options) => hooks$.getValue().forEach((hook) => {
2195
- if (hook.name === `item.onLayoutBeforeMeasurement`) {
2196
- hook.fn({
2197
- frame: spineItemFrame,
2198
- container: containerElement,
2199
- item,
2200
- isImageType,
2201
- ...options
2202
- });
2203
- }
1945
+ const executeOnLayoutBeforeMeasurementHook = (options) => hookManager.execute("item.onLayoutBeforeMeasurement", void 0, {
1946
+ frame: spineItemFrame,
1947
+ container: containerElement,
1948
+ item,
1949
+ isImageType,
1950
+ ...options
2204
1951
  });
2205
1952
  const contentLayout$ = spineItemFrame.$.contentLayoutChange$.pipe(
2206
1953
  withLatestFrom(spineItemFrame.$.isReady$),
@@ -2239,8 +1986,8 @@ const createCommonSpineItem = ({
2239
1986
  destroySubject$.complete();
2240
1987
  },
2241
1988
  isUsingVerticalWriting: () => {
2242
- var _a2;
2243
- return (_a2 = spineItemFrame.getWritingMode()) == null ? void 0 : _a2.startsWith(`vertical`);
1989
+ var _a;
1990
+ return (_a = spineItemFrame.getWritingMode()) == null ? void 0 : _a.startsWith(`vertical`);
2244
1991
  },
2245
1992
  /**
2246
1993
  * @important
@@ -2251,7 +1998,7 @@ const createCommonSpineItem = ({
2251
1998
  * be confined to a single page.
2252
1999
  */
2253
2000
  getReadingDirection: () => {
2254
- return spineItemFrame.getReadingDirection() || context.getReadingDirection();
2001
+ return spineItemFrame.getReadingDirection() || context.readingDirection;
2255
2002
  },
2256
2003
  manipulateSpineItem,
2257
2004
  executeOnLayoutBeforeMeasurementHook,
@@ -2266,7 +2013,7 @@ const createCommonSpineItem = ({
2266
2013
  }
2267
2014
  };
2268
2015
  };
2269
- const createContainerElement$1 = (containerElement, item, hooks$) => {
2016
+ const createContainerElement$1 = (containerElement, item, hookManager) => {
2270
2017
  const element = containerElement.ownerDocument.createElement(`div`);
2271
2018
  element.classList.add(`spineItem`);
2272
2019
  element.classList.add(`spineItem-${item.renditionLayout}`);
@@ -2274,12 +2021,8 @@ const createContainerElement$1 = (containerElement, item, hooks$) => {
2274
2021
  position: absolute;
2275
2022
  overflow: hidden;
2276
2023
  `;
2277
- return hooks$.getValue().reduce((element2, hook) => {
2278
- if (hook.name === `item.onBeforeContainerCreated`) {
2279
- return hook.fn(element2);
2280
- }
2281
- return element2;
2282
- }, element);
2024
+ hookManager.execute("item.onBeforeContainerCreated", void 0, { element });
2025
+ return element;
2283
2026
  };
2284
2027
  const createOverlayElement = (containerElement, item) => {
2285
2028
  const element = containerElement.ownerDocument.createElement(`div`);
@@ -2294,42 +2037,6 @@ const createOverlayElement = (containerElement, item) => {
2294
2037
  `;
2295
2038
  return element;
2296
2039
  };
2297
- const createFrameHooks = (iframeEventBridgeElement$, fingerTracker, selectionTracker) => {
2298
- return [
2299
- {
2300
- name: `item.onLoad`,
2301
- fn: ({ frame }) => {
2302
- const unregister = passthroughEvents.map((event) => {
2303
- var _a;
2304
- const listener = (e) => {
2305
- var _a2;
2306
- let convertedEvent = e;
2307
- if (isPointerEvent(e)) {
2308
- convertedEvent = new PointerEvent(e.type, e);
2309
- }
2310
- if (isMouseEvent(e)) {
2311
- convertedEvent = new MouseEvent(e.type, e);
2312
- }
2313
- if (convertedEvent !== e) {
2314
- attachOriginalFrameEventToDocumentEvent(convertedEvent, e);
2315
- (_a2 = iframeEventBridgeElement$.getValue()) == null ? void 0 : _a2.dispatchEvent(convertedEvent);
2316
- }
2317
- };
2318
- (_a = frame.contentDocument) == null ? void 0 : _a.addEventListener(event, listener);
2319
- return () => {
2320
- var _a2;
2321
- (_a2 = frame.contentDocument) == null ? void 0 : _a2.removeEventListener(event, listener);
2322
- };
2323
- });
2324
- selectionTracker.track(frame);
2325
- fingerTracker.track(frame);
2326
- return () => {
2327
- unregister.forEach((cb) => cb());
2328
- };
2329
- }
2330
- }
2331
- ];
2332
- };
2333
2040
  const getStyleForViewportDocument = () => {
2334
2041
  return `
2335
2042
  body {
@@ -2342,19 +2049,17 @@ const createPrePaginatedSpineItem = ({
2342
2049
  item,
2343
2050
  context,
2344
2051
  containerElement,
2345
- iframeEventBridgeElement$,
2346
- hooks$,
2347
2052
  viewportState$,
2348
- settings
2053
+ settings,
2054
+ hookManager
2349
2055
  }) => {
2350
2056
  const commonSpineItem = createCommonSpineItem({
2351
2057
  context,
2352
2058
  item,
2353
2059
  parentElement: containerElement,
2354
- iframeEventBridgeElement$,
2355
- hooks$,
2356
2060
  viewportState$,
2357
- settings
2061
+ settings,
2062
+ hookManager
2358
2063
  });
2359
2064
  const spineItemFrame = commonSpineItem.spineItemFrame;
2360
2065
  const layout = ({
@@ -2365,15 +2070,15 @@ const createPrePaginatedSpineItem = ({
2365
2070
  var _a;
2366
2071
  const { width: pageWidth, height: pageHeight } = context.getPageSize();
2367
2072
  const { viewportDimensions, computedScale = 1 } = commonSpineItem.getViewPortInformation() ?? {};
2368
- const visibleArea = context.getVisibleAreaRect();
2073
+ const visibleArea = context.state.visibleAreaRect;
2369
2074
  const frameElement = (_a = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a.frame;
2370
2075
  if ((spineItemFrame == null ? void 0 : spineItemFrame.getIsLoaded()) && (frameElement == null ? void 0 : frameElement.contentDocument) && (frameElement == null ? void 0 : frameElement.contentWindow)) {
2371
2076
  const contentWidth = pageWidth;
2372
- const contentHeight = visibleArea.height + context.getCalculatedInnerMargin();
2077
+ const contentHeight = visibleArea.height + context.state.calculatedInnerMargin;
2373
2078
  const cssLink = buildDocumentStyle(
2374
2079
  {
2375
2080
  ...commonSpineItem.getDimensionsForPaginatedContent(),
2376
- enableTouch: settings.getSettings().computedPageTurnMode !== `scrollable`,
2081
+ enableTouch: settings.settings.computedPageTurnMode !== `scrollable`,
2377
2082
  spreadPosition
2378
2083
  },
2379
2084
  viewportDimensions
@@ -2516,19 +2221,17 @@ const createReflowableSpineItem = ({
2516
2221
  item,
2517
2222
  context,
2518
2223
  containerElement,
2519
- iframeEventBridgeElement$,
2520
- hooks$,
2521
2224
  viewportState$,
2522
- settings
2225
+ settings,
2226
+ hookManager
2523
2227
  }) => {
2524
2228
  const commonSpineItem = createCommonSpineItem({
2525
2229
  context,
2526
2230
  item,
2527
2231
  parentElement: containerElement,
2528
- iframeEventBridgeElement$,
2529
- hooks$,
2530
2232
  viewportState$,
2531
- settings
2233
+ settings,
2234
+ hookManager
2532
2235
  });
2533
2236
  const spineItemFrame = commonSpineItem.spineItemFrame;
2534
2237
  let latestContentHeightWhenLoaded;
@@ -2541,12 +2244,12 @@ const createReflowableSpineItem = ({
2541
2244
  (_b = (_a = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a.frame) == null ? void 0 : _b.style.setProperty(`width`, `${pageWidth}px`);
2542
2245
  (_d = (_c = spineItemFrame.getManipulableFrame()) == null ? void 0 : _c.frame) == null ? void 0 : _d.style.setProperty(`height`, `${pageHeight}px`);
2543
2246
  const { viewportDimensions, computedScale = 1 } = commonSpineItem.getViewPortInformation() ?? {};
2544
- const visibleArea = context.getVisibleAreaRect();
2247
+ const visibleArea = context.state.visibleAreaRect;
2545
2248
  const frameElement = (_e = spineItemFrame.getManipulableFrame()) == null ? void 0 : _e.frame;
2546
- const isGloballyPrePaginated = ((_f = context.getManifest()) == null ? void 0 : _f.renditionLayout) === `pre-paginated`;
2249
+ const isGloballyPrePaginated = ((_f = context.manifest) == null ? void 0 : _f.renditionLayout) === `pre-paginated`;
2547
2250
  if ((spineItemFrame == null ? void 0 : spineItemFrame.getIsLoaded()) && (frameElement == null ? void 0 : frameElement.contentDocument) && (frameElement == null ? void 0 : frameElement.contentWindow)) {
2548
2251
  let contentWidth = pageWidth;
2549
- let contentHeight = visibleArea.height + context.getCalculatedInnerMargin();
2252
+ let contentHeight = visibleArea.height + context.state.calculatedInnerMargin;
2550
2253
  frameElement == null ? void 0 : frameElement.style.setProperty(`visibility`, `visible`);
2551
2254
  frameElement == null ? void 0 : frameElement.style.setProperty(`opacity`, `1`);
2552
2255
  if (viewportDimensions) {
@@ -2566,8 +2269,8 @@ const createReflowableSpineItem = ({
2566
2269
  frameElement == null ? void 0 : frameElement.style.setProperty(`transform-origin`, `center center`);
2567
2270
  } else {
2568
2271
  const frameStyle = commonSpineItem.isImageType() ? buildStyleForReflowableImageOnly({
2569
- isScrollable: ((_g = context.getManifest()) == null ? void 0 : _g.renditionFlow) === `scrolled-continuous`,
2570
- enableTouch: settings.getSettings().computedPageTurnMode !== `scrollable`
2272
+ isScrollable: ((_g = context.manifest) == null ? void 0 : _g.renditionFlow) === `scrolled-continuous`,
2273
+ enableTouch: settings.settings.computedPageTurnMode !== `scrollable`
2571
2274
  }) : buildStyleWithMultiColumn(
2572
2275
  commonSpineItem.getDimensionsForReflowableContent(spineItemFrame.isUsingVerticalWriting(), minimumWidth)
2573
2276
  );
@@ -2580,7 +2283,7 @@ const createReflowableSpineItem = ({
2580
2283
  width: minimumWidth,
2581
2284
  height: contentHeight
2582
2285
  });
2583
- } else if (((_h = context.getManifest()) == null ? void 0 : _h.renditionFlow) === `scrolled-continuous`) {
2286
+ } else if (((_h = context.manifest) == null ? void 0 : _h.renditionFlow) === `scrolled-continuous`) {
2584
2287
  contentHeight = frameElement.contentDocument.documentElement.scrollHeight;
2585
2288
  latestContentHeightWhenLoaded = contentHeight;
2586
2289
  spineItemFrame.staticLayout({
@@ -2644,7 +2347,10 @@ const buildStyleForViewportFrame = () => {
2644
2347
  }
2645
2348
  `;
2646
2349
  };
2647
- const buildStyleForReflowableImageOnly = ({ isScrollable, enableTouch }) => {
2350
+ const buildStyleForReflowableImageOnly = ({
2351
+ isScrollable,
2352
+ enableTouch
2353
+ }) => {
2648
2354
  return `
2649
2355
  ${/*
2650
2356
  * @see https://hammerjs.github.io/touch-action/
@@ -2792,91 +2498,29 @@ const createSpineItem = ({
2792
2498
  item,
2793
2499
  context,
2794
2500
  containerElement,
2795
- iframeEventBridgeElement$,
2796
- hooks$,
2797
2501
  viewportState$,
2798
- settings
2502
+ settings,
2503
+ hookManager
2799
2504
  }) => {
2800
2505
  if (item.renditionLayout === `pre-paginated`) {
2801
2506
  return createPrePaginatedSpineItem({
2802
2507
  item,
2803
2508
  context,
2804
2509
  containerElement,
2805
- iframeEventBridgeElement$,
2806
- hooks$,
2807
2510
  viewportState$,
2808
- settings
2511
+ settings,
2512
+ hookManager
2809
2513
  });
2810
2514
  }
2811
2515
  return createReflowableSpineItem({
2812
2516
  item,
2813
2517
  context,
2814
2518
  containerElement,
2815
- iframeEventBridgeElement$,
2816
- hooks$,
2817
2519
  viewportState$,
2818
- settings
2520
+ settings,
2521
+ hookManager
2819
2522
  });
2820
2523
  };
2821
- const createEventsHelper = ({
2822
- iframeEventBridgeElement$,
2823
- locator
2824
- }) => {
2825
- const normalizeEventForViewport = (event) => {
2826
- var _a;
2827
- const eventIsComingFromBridge = event.target === iframeEventBridgeElement$.getValue();
2828
- const iframeOriginalEvent = getOriginalFrameEventFromDocumentEvent(event);
2829
- const originalFrame = (_a = iframeOriginalEvent == null ? void 0 : iframeOriginalEvent.view) == null ? void 0 : _a.frameElement;
2830
- if (!eventIsComingFromBridge || !iframeOriginalEvent || !originalFrame)
2831
- return event;
2832
- const spineItem = locator.getSpineItemFromIframe(originalFrame);
2833
- if (!spineItem)
2834
- return event;
2835
- if (isPointerEvent(event)) {
2836
- const { clientX, clientY } = spineItem.translateFramePositionIntoPage(event);
2837
- const newEvent = new PointerEvent(event.type, {
2838
- ...event,
2839
- pointerId: event.pointerId,
2840
- clientX,
2841
- clientY
2842
- });
2843
- Object.defineProperty(newEvent, `target`, { value: iframeOriginalEvent.target, enumerable: true });
2844
- return newEvent;
2845
- }
2846
- if (isMouseEvent(event)) {
2847
- const { clientX, clientY } = spineItem.translateFramePositionIntoPage(event);
2848
- const newEvent = new MouseEvent(event.type, {
2849
- ...event,
2850
- clientX,
2851
- clientY
2852
- });
2853
- Object.defineProperty(newEvent, `target`, { value: iframeOriginalEvent.target, enumerable: true });
2854
- return newEvent;
2855
- }
2856
- if (isTouchEvent(event)) {
2857
- const touches = Array.from(event.touches).map((touch) => {
2858
- const { clientX, clientY } = spineItem.translateFramePositionIntoPage(touch);
2859
- return new Touch({
2860
- identifier: touch.identifier,
2861
- target: touch.target,
2862
- clientX,
2863
- clientY
2864
- });
2865
- });
2866
- const newEvent = new TouchEvent(event.type, {
2867
- touches,
2868
- changedTouches: touches,
2869
- targetTouches: touches
2870
- });
2871
- Object.defineProperty(newEvent, `target`, { value: iframeOriginalEvent.target, enumerable: true });
2872
- return newEvent;
2873
- }
2874
- return event;
2875
- };
2876
- return {
2877
- normalizeEventForViewport
2878
- };
2879
- };
2880
2524
  const ELEMENT_NODE = Node.ELEMENT_NODE;
2881
2525
  const TEXT_NODE = Node.TEXT_NODE;
2882
2526
  const CDATA_SECTION_NODE = Node.CDATA_SECTION_NODE;
@@ -2890,8 +2534,7 @@ function matchAll(str, regExp, add) {
2890
2534
  let m;
2891
2535
  do {
2892
2536
  m = str.match(regExp);
2893
- if (!m)
2894
- break;
2537
+ if (!m) break;
2895
2538
  matches.push(m.index + add);
2896
2539
  offset += m.index + m.length;
2897
2540
  str = str.slice(m.index + m.length);
@@ -2954,24 +2597,17 @@ function calcSiblingCount(nodes, n, offset) {
2954
2597
  function compareTemporal(a, b) {
2955
2598
  const isA = typeof a === `number`;
2956
2599
  const isB = typeof b === `number`;
2957
- if (!isA && !isB)
2958
- return 0;
2959
- if (!isA && isB)
2960
- return -1;
2961
- if (isA && !isB)
2962
- return 1;
2600
+ if (!isA && !isB) return 0;
2601
+ if (!isA && isB) return -1;
2602
+ if (isA && !isB) return 1;
2963
2603
  return (a || 0) - (b || 0);
2964
2604
  }
2965
2605
  function compareSpatial(a, b) {
2966
- if (!a && !b)
2967
- return 0;
2968
- if (!a && b)
2969
- return -1;
2970
- if (a && !b)
2971
- return 1;
2606
+ if (!a && !b) return 0;
2607
+ if (!a && b) return -1;
2608
+ if (a && !b) return 1;
2972
2609
  const diff = (a.y || 0) - (b.y || 0);
2973
- if (diff)
2974
- return diff;
2610
+ if (diff) return diff;
2975
2611
  return (a.x || 0) - (b.x || 0);
2976
2612
  }
2977
2613
  class CFI {
@@ -2993,20 +2629,16 @@ class CFI {
2993
2629
  const isCFI = /^epubcfi\((.*)\)$/;
2994
2630
  str = str.trim();
2995
2631
  const m = str.match(isCFI);
2996
- if (!m)
2997
- throw new Error(`Not a valid CFI`);
2998
- if (m.length < 2)
2999
- return;
2632
+ if (!m) throw new Error(`Not a valid CFI`);
2633
+ if (m.length < 2) return;
3000
2634
  str = m[1] || ``;
3001
2635
  let parsed, offset, newDoc;
3002
2636
  let subParts = [];
3003
2637
  let sawComma = 0;
3004
2638
  while (str.length) {
3005
2639
  ({ parsed, offset, newDoc } = this.parse(str));
3006
- if (!parsed || offset === null)
3007
- throw new Error(`Parsing failed`);
3008
- if (sawComma && newDoc)
3009
- throw new Error(`CFI is a range that spans multiple documents. This is not allowed`);
2640
+ if (!parsed || offset === null) throw new Error(`Parsing failed`);
2641
+ if (sawComma && newDoc) throw new Error(`CFI is a range that spans multiple documents. This is not allowed`);
3010
2642
  subParts.push(parsed);
3011
2643
  if (newDoc || str.length - offset <= 0) {
3012
2644
  if (sawComma === 2) {
@@ -3050,8 +2682,7 @@ class CFI {
3050
2682
  if (!parts) {
3051
2683
  if (this.from) {
3052
2684
  this.removeIllegalOpts(this.from);
3053
- if (!this.to)
3054
- return;
2685
+ if (!this.to) return;
3055
2686
  parts = this.to;
3056
2687
  } else {
3057
2688
  parts = this.parts;
@@ -3074,8 +2705,7 @@ class CFI {
3074
2705
  let o;
3075
2706
  while (node.parentNode) {
3076
2707
  o = calcSiblingCount(node.parentNode.childNodes, node, offset);
3077
- if (!cfi && o.offset)
3078
- cfi = `:` + o.offset;
2708
+ if (!cfi && o.offset) cfi = `:` + o.offset;
3079
2709
  cfi = `/` + o.count + (node.id ? `[` + cfiEscape(node.id) + `]` : ``) + cfi;
3080
2710
  node = node.parentNode;
3081
2711
  }
@@ -3092,8 +2722,7 @@ class CFI {
3092
2722
  } else {
3093
2723
  cfi = this.generatePart(node, offset, extra);
3094
2724
  }
3095
- if (extra)
3096
- cfi += extra;
2725
+ if (extra) cfi += extra;
3097
2726
  return `epubcfi(` + cfi + `)`;
3098
2727
  }
3099
2728
  static toParsed(cfi) {
@@ -3110,13 +2739,10 @@ class CFI {
3110
2739
  for (i = 0; i < max; i++) {
3111
2740
  cA = a[i];
3112
2741
  cB = b[i];
3113
- if (!cA)
3114
- return -1;
3115
- if (!cB)
3116
- return 1;
2742
+ if (!cA) return -1;
2743
+ if (!cB) return 1;
3117
2744
  diff = this.compareParts(cA, cB);
3118
- if (diff)
3119
- return diff;
2745
+ if (diff) return diff;
3120
2746
  }
3121
2747
  return 0;
3122
2748
  }
@@ -3133,14 +2759,11 @@ class CFI {
3133
2759
  if (a.isRange || b.isRange) {
3134
2760
  if (a.isRange && b.isRange) {
3135
2761
  const diff = this.comparePath(oA.from, oB.from);
3136
- if (diff)
3137
- return diff;
2762
+ if (diff) return diff;
3138
2763
  return this.comparePath(oA.to, oB.to);
3139
2764
  }
3140
- if (a.isRange)
3141
- oA = oA.from;
3142
- if (b.isRange)
3143
- oB = oB.from;
2765
+ if (a.isRange) oA = oA.from;
2766
+ if (b.isRange) oB = oB.from;
3144
2767
  return this.comparePath(oA, oB);
3145
2768
  } else {
3146
2769
  return this.comparePath(oA, oB);
@@ -3153,29 +2776,22 @@ class CFI {
3153
2776
  for (i = 0; i < max; i++) {
3154
2777
  cA = a[i];
3155
2778
  cB = b[i];
3156
- if (!cA)
3157
- return -1;
3158
- if (!cB)
3159
- return 1;
2779
+ if (!cA) return -1;
2780
+ if (!cB) return 1;
3160
2781
  diff = cA.nodeIndex - cB.nodeIndex;
3161
- if (diff)
3162
- return diff;
2782
+ if (diff) return diff;
3163
2783
  if (cA.nodeIndex === 0) {
3164
2784
  return 0;
3165
2785
  }
3166
- if (i < max - 1)
3167
- continue;
2786
+ if (i < max - 1) continue;
3168
2787
  if (cA.nodeIndex % 2 === 0) {
3169
2788
  diff = compareTemporal(cA.temporal, cB.temporal);
3170
- if (diff)
3171
- return diff;
2789
+ if (diff) return diff;
3172
2790
  diff = compareSpatial(cA.spatial, cB.spatial);
3173
- if (diff)
3174
- return diff;
2791
+ if (diff) return diff;
3175
2792
  }
3176
2793
  diff = (cA.offset || 0) - (cB.offset || 0);
3177
- if (diff)
3178
- return diff;
2794
+ if (diff) return diff;
3179
2795
  }
3180
2796
  return 0;
3181
2797
  }
@@ -3193,8 +2809,7 @@ class CFI {
3193
2809
  return this.decodeEntities(dom, str).length;
3194
2810
  }
3195
2811
  getFrom() {
3196
- if (!this.isRange)
3197
- throw new Error(`Trying to get beginning of non-range CFI`);
2812
+ if (!this.isRange) throw new Error(`Trying to get beginning of non-range CFI`);
3198
2813
  if (!this.from) {
3199
2814
  return this.deepClone(this.parts);
3200
2815
  }
@@ -3203,8 +2818,7 @@ class CFI {
3203
2818
  return parts;
3204
2819
  }
3205
2820
  getTo() {
3206
- if (!this.isRange)
3207
- throw new Error(`Trying to get end of non-range CFI`);
2821
+ if (!this.isRange) throw new Error(`Trying to get end of non-range CFI`);
3208
2822
  const parts = this.deepClone(this.parts);
3209
2823
  parts[parts.length - 1] = parts[parts.length - 1].concat(this.to);
3210
2824
  return parts;
@@ -3220,8 +2834,7 @@ class CFI {
3220
2834
  return this.deepClone(this.parts);
3221
2835
  }
3222
2836
  parseSideBias(o, loc) {
3223
- if (!loc)
3224
- return;
2837
+ if (!loc) return;
3225
2838
  const m = loc.trim().match(/^(.*);s=([ba])$/);
3226
2839
  if (!m || m.length < 3) {
3227
2840
  if (typeof o.textLocationAssertion === `object`) {
@@ -3245,11 +2858,9 @@ class CFI {
3245
2858
  }
3246
2859
  }
3247
2860
  parseSpatialRange(range) {
3248
- if (!range)
3249
- return void 0;
2861
+ if (!range) return void 0;
3250
2862
  const m = range.trim().match(/^([\d\.]+):([\d\.]+)$/);
3251
- if (!m || m.length < 3)
3252
- return void 0;
2863
+ if (!m || m.length < 3) return void 0;
3253
2864
  const o = {
3254
2865
  x: parseInt(m[1]),
3255
2866
  y: parseInt(m[2])
@@ -3339,8 +2950,7 @@ class CFI {
3339
2950
  } else {
3340
2951
  prevState = state;
3341
2952
  state = null;
3342
- if (f && seenColon)
3343
- o.spatial = this.parseSpatialRange(f);
2953
+ if (f && seenColon) o.spatial = this.parseSpatialRange(f);
3344
2954
  f = null;
3345
2955
  }
3346
2956
  }
@@ -3450,8 +3060,7 @@ class CFI {
3450
3060
  }
3451
3061
  escape = false;
3452
3062
  }
3453
- if (!o.nodeIndex && o.nodeIndex !== 0)
3454
- throw new Error(`Missing child node index in CFI`);
3063
+ if (!o.nodeIndex && o.nodeIndex !== 0) throw new Error(`Missing child node index in CFI`);
3455
3064
  return { parsed: o, offset: i, newDoc: state === `!` };
3456
3065
  }
3457
3066
  // The CFI counts child nodes differently from the DOM
@@ -3459,8 +3068,7 @@ class CFI {
3459
3068
  // according to the CFI standard way of counting
3460
3069
  getChildNodeByCFIIndex(dom, parentNode, index, offset) {
3461
3070
  const children = parentNode.childNodes;
3462
- if (!children.length)
3463
- return { node: parentNode, offset: 0 };
3071
+ if (!children.length) return { node: parentNode, offset: 0 };
3464
3072
  if (index <= 0) {
3465
3073
  return { node: children[0], relativeToNode: `before`, offset: 0 };
3466
3074
  }
@@ -3528,8 +3136,7 @@ class CFI {
3528
3136
  }
3529
3137
  }
3530
3138
  isTextNode(node) {
3531
- if (!node)
3532
- return false;
3139
+ if (!node) return false;
3533
3140
  if (node.nodeType === TEXT_NODE || node.nodeType === CDATA_SECTION_NODE) {
3534
3141
  return true;
3535
3142
  }
@@ -3561,15 +3168,13 @@ class CFI {
3561
3168
  str = this.decodeEntities(dom, curNode.textContent);
3562
3169
  nodeLengths[i] = str.length;
3563
3170
  txt += str;
3564
- if (!curNode.nextSibling)
3565
- break;
3171
+ if (!curNode.nextSibling) break;
3566
3172
  curNode = curNode.nextSibling;
3567
3173
  i++;
3568
3174
  }
3569
3175
  const matchOffset = assertion.pre ? assertion.pre.length : 0;
3570
3176
  const m = matchAll(txt, new RegExp(matchStr), matchOffset);
3571
- if (!m.length)
3572
- return { node, offset };
3177
+ if (!m.length) return { node, offset };
3573
3178
  let newOffset = closest(m, offset);
3574
3179
  if (curNode === node && newOffset === offset) {
3575
3180
  return { node, offset };
@@ -3578,11 +3183,9 @@ class CFI {
3578
3183
  curNode = startNode;
3579
3184
  while (newOffset >= nodeLengths[i]) {
3580
3185
  newOffset -= nodeLengths[i];
3581
- if (newOffset < 0)
3582
- return { node, offset };
3186
+ if (newOffset < 0) return { node, offset };
3583
3187
  const nodeOffsets = [];
3584
- if (!curNode.nextSibling || i + 1 >= nodeOffsets.length)
3585
- return { node, offset };
3188
+ if (!curNode.nextSibling || i + 1 >= nodeOffsets.length) return { node, offset };
3586
3189
  i++;
3587
3190
  curNode = curNode.nextSibling;
3588
3191
  }
@@ -3590,8 +3193,7 @@ class CFI {
3590
3193
  }
3591
3194
  resolveNode(index, subparts, dom, opts) {
3592
3195
  opts = Object.assign({}, opts || {});
3593
- if (!dom)
3594
- throw new Error(`Missing DOM argument`);
3196
+ if (!dom) throw new Error(`Missing DOM argument`);
3595
3197
  let startNode;
3596
3198
  if (index === 0) {
3597
3199
  startNode = dom.querySelector(`package`);
@@ -3605,8 +3207,7 @@ class CFI {
3605
3207
  }
3606
3208
  }
3607
3209
  startNode = dom;
3608
- if (!startNode)
3609
- throw new Error(`Document incompatible with CFIs`);
3210
+ if (!startNode) throw new Error(`Document incompatible with CFIs`);
3610
3211
  let node = startNode;
3611
3212
  let startFrom = 0;
3612
3213
  let i;
@@ -3648,40 +3249,33 @@ class CFI {
3648
3249
  throw new Error(`index is out of bounds`);
3649
3250
  }
3650
3251
  const subparts = this.parts[index];
3651
- if (!subparts)
3652
- throw new Error(`Missing CFI part for index: ` + index);
3252
+ if (!subparts) throw new Error(`Missing CFI part for index: ` + index);
3653
3253
  const o = this.resolveNode(index, subparts, dom, opts);
3654
3254
  let node = o.node;
3655
3255
  const tagName = node.tagName.toLowerCase();
3656
3256
  if (tagName === `itemref` && // @ts-ignore
3657
3257
  node.parentNode.tagName.toLowerCase() === `spine`) {
3658
3258
  const idref = node.getAttribute(`idref`);
3659
- if (!idref)
3660
- throw new Error(`Referenced node had not 'idref' attribute`);
3259
+ if (!idref) throw new Error(`Referenced node had not 'idref' attribute`);
3661
3260
  node = dom.getElementById(idref);
3662
- if (!node)
3663
- throw new Error(`Specified node is missing from manifest`);
3261
+ if (!node) throw new Error(`Specified node is missing from manifest`);
3664
3262
  const href = node.getAttribute(`href`);
3665
- if (!href)
3666
- throw new Error(`Manifest item is missing href attribute`);
3263
+ if (!href) throw new Error(`Manifest item is missing href attribute`);
3667
3264
  return href;
3668
3265
  }
3669
3266
  if (tagName === `iframe` || tagName === `embed`) {
3670
3267
  const src = node.getAttribute(`src`);
3671
- if (!src)
3672
- throw new Error(tagName + ` element is missing 'src' attribute`);
3268
+ if (!src) throw new Error(tagName + ` element is missing 'src' attribute`);
3673
3269
  return src;
3674
3270
  }
3675
3271
  if (tagName === `object`) {
3676
3272
  const data = node.getAttribute(`data`);
3677
- if (!data)
3678
- throw new Error(tagName + ` element is missing 'data' attribute`);
3273
+ if (!data) throw new Error(tagName + ` element is missing 'data' attribute`);
3679
3274
  return data;
3680
3275
  }
3681
3276
  if (tagName === `image` || tagName === `use`) {
3682
3277
  const href = node.getAttribute(`xlink:href`);
3683
- if (!href)
3684
- throw new Error(tagName + ` element is missing 'xlink:href' attribute`);
3278
+ if (!href) throw new Error(tagName + ` element is missing 'xlink:href' attribute`);
3685
3279
  return href;
3686
3280
  }
3687
3281
  throw new Error(`No URI found`);
@@ -3692,13 +3286,11 @@ class CFI {
3692
3286
  resolveLocation(dom, parts) {
3693
3287
  const index = parts.length - 1;
3694
3288
  const subparts = parts[index];
3695
- if (!subparts)
3696
- throw new Error(`Missing CFI part for index: ` + index);
3289
+ if (!subparts) throw new Error(`Missing CFI part for index: ` + index);
3697
3290
  const o = this.resolveNode(index, subparts, dom);
3698
3291
  const lastPart = this.deepClone(subparts[subparts.length - 1]);
3699
3292
  delete lastPart.nodeIndex;
3700
- if (!lastPart.offset)
3701
- delete o.offset;
3293
+ if (!lastPart.offset) delete o.offset;
3702
3294
  return { ...lastPart, ...o };
3703
3295
  }
3704
3296
  // Takes the Document or XMLDocument for the final
@@ -3762,12 +3354,20 @@ const createSelection = (selection, item) => {
3762
3354
  toString: () => text,
3763
3355
  getAnchorCfi: () => {
3764
3356
  if (selection.anchorNode) {
3765
- return CFI.generate(selection.anchorNode, selection.anchorOffset, `|[prose~anchor~${encodeURIComponent(item.id)}]`);
3357
+ return CFI.generate(
3358
+ selection.anchorNode,
3359
+ selection.anchorOffset,
3360
+ `|[prose~anchor~${encodeURIComponent(item.id)}]`
3361
+ );
3766
3362
  }
3767
3363
  },
3768
3364
  getFocusCfi: () => {
3769
3365
  if (selection.focusNode) {
3770
- return CFI.generate(selection.focusNode, selection.focusOffset, `|[prose~anchor~${encodeURIComponent(item.id)}]`);
3366
+ return CFI.generate(
3367
+ selection.focusNode,
3368
+ selection.focusOffset,
3369
+ `|[prose~anchor~${encodeURIComponent(item.id)}]`
3370
+ );
3771
3371
  }
3772
3372
  }
3773
3373
  };
@@ -3778,9 +3378,7 @@ const createSpine = ({
3778
3378
  element$,
3779
3379
  context,
3780
3380
  pagination,
3781
- iframeEventBridgeElement$,
3782
3381
  spineItemManager,
3783
- hooks$,
3784
3382
  spineItemLocator,
3785
3383
  spineLocator,
3786
3384
  cfiLocator,
@@ -3788,18 +3386,13 @@ const createSpine = ({
3788
3386
  navigationAdjusted$,
3789
3387
  currentNavigationPosition$,
3790
3388
  viewportState$,
3791
- settings
3389
+ settings,
3390
+ hookManager
3792
3391
  }) => {
3793
3392
  const spineItems$ = new Subject();
3794
3393
  const itemsBeforeDestroySubject$ = new Subject();
3795
3394
  const subject = new Subject();
3796
3395
  const containerElement$ = new BehaviorSubject(noopElement$1);
3797
- const eventsHelper = createEventsHelper({
3798
- context,
3799
- spineItemManager,
3800
- iframeEventBridgeElement$,
3801
- locator: spineLocator
3802
- });
3803
3396
  let selectionSubscription;
3804
3397
  const reload = (manifest) => {
3805
3398
  itemsBeforeDestroySubject$.next();
@@ -3808,11 +3401,10 @@ const createSpine = ({
3808
3401
  const spineItem = createSpineItem({
3809
3402
  item: resource,
3810
3403
  containerElement: containerElement$.getValue(),
3811
- iframeEventBridgeElement$,
3812
3404
  context,
3813
- hooks$,
3814
3405
  viewportState$,
3815
- settings
3406
+ settings,
3407
+ hookManager
3816
3408
  });
3817
3409
  spineItemManager.add(spineItem);
3818
3410
  });
@@ -3831,7 +3423,7 @@ const createSpine = ({
3831
3423
  var _a;
3832
3424
  (_a = spineItemManager.get(id)) == null ? void 0 : _a.manipulateSpineItem(cb);
3833
3425
  };
3834
- context.$.manifest$.pipe(tap(reload), takeUntil$1(context.$.destroy$)).subscribe();
3426
+ context.manifest$.pipe(tap(reload), takeUntil$1(context.destroy$)).subscribe();
3835
3427
  const waitForViewportFree$ = viewportState$.pipe(
3836
3428
  filter((v) => v === `free`),
3837
3429
  take(1)
@@ -3923,7 +3515,7 @@ const createSpine = ({
3923
3515
  Report.error(e);
3924
3516
  return EMPTY;
3925
3517
  }),
3926
- takeUntil$1(context.$.destroy$)
3518
+ takeUntil$1(context.destroy$)
3927
3519
  )
3928
3520
  ).subscribe();
3929
3521
  const itemUpdateOnNavigation$ = navigation$.pipe(
@@ -3949,7 +3541,10 @@ const createSpine = ({
3949
3541
  beginSpineItem
3950
3542
  );
3951
3543
  const beginPageIndex = spineItemLocator.getSpineItemPageIndexFromPosition(beginPosition, beginSpineItem);
3952
- const endPosition = spineLocator.getSpineItemPositionFromSpinePosition(spineItemsFromPosition.endPosition, endSpineItem);
3544
+ const endPosition = spineLocator.getSpineItemPositionFromSpinePosition(
3545
+ spineItemsFromPosition.endPosition,
3546
+ endSpineItem
3547
+ );
3953
3548
  const endPageIndex = spineItemLocator.getSpineItemPageIndexFromPosition(endPosition, endSpineItem);
3954
3549
  const endItemIndex = spineItemManager.getSpineItemIndex(endSpineItem) ?? 0;
3955
3550
  pagination.updateBeginAndEnd(
@@ -3969,7 +3564,7 @@ const createSpine = ({
3969
3564
  *
3970
3565
  * The cfi is later adjusted with heavy dom lookup once the viewport is free.
3971
3566
  */
3972
- cfi: (lastExpectedNavigation == null ? void 0 : lastExpectedNavigation.type) === `navigate-from-cfi` && spineItemToFocus === beginSpineItem ? lastExpectedNavigation.data : data.triggeredBy === `adjust` && settings.getSettings().computedPageTurnMode === `controlled` ? pagination.getPaginationInfo().beginCfi : beginItemIndex !== pagination.getPaginationInfo().beginSpineItemIndex ? cfiLocator.getRootCfi(beginSpineItem) : (
3567
+ cfi: (lastExpectedNavigation == null ? void 0 : lastExpectedNavigation.type) === `navigate-from-cfi` && spineItemToFocus === beginSpineItem ? lastExpectedNavigation.data : data.triggeredBy === `adjust` && settings.settings.computedPageTurnMode === `controlled` ? pagination.getPaginationInfo().beginCfi : beginItemIndex !== pagination.getPaginationInfo().beginSpineItemIndex ? cfiLocator.getRootCfi(beginSpineItem) : (
3973
3568
  /* @todo check ? */
3974
3569
  cfiLocator.getRootCfi(beginSpineItem)
3975
3570
  ),
@@ -3981,7 +3576,7 @@ const createSpine = ({
3981
3576
  spineItem: endSpineItem,
3982
3577
  spineItemIndex: endItemIndex,
3983
3578
  pageIndex: endPageIndex,
3984
- cfi: (lastExpectedNavigation == null ? void 0 : lastExpectedNavigation.type) === `navigate-from-cfi` && spineItemToFocus === endSpineItem ? lastExpectedNavigation.data : data.triggeredBy === `adjust` && settings.getSettings().computedPageTurnMode === `controlled` ? pagination.getPaginationInfo().endCfi : endItemIndex !== pagination.getPaginationInfo().endSpineItemIndex ? cfiLocator.getRootCfi(endSpineItem) : (
3579
+ cfi: (lastExpectedNavigation == null ? void 0 : lastExpectedNavigation.type) === `navigate-from-cfi` && spineItemToFocus === endSpineItem ? lastExpectedNavigation.data : data.triggeredBy === `adjust` && settings.settings.computedPageTurnMode === `controlled` ? pagination.getPaginationInfo().endCfi : endItemIndex !== pagination.getPaginationInfo().endSpineItemIndex ? cfiLocator.getRootCfi(endSpineItem) : (
3985
3580
  /* @todo check ? */
3986
3581
  cfiLocator.getRootCfi(endSpineItem)
3987
3582
  ),
@@ -4005,13 +3600,13 @@ const createSpine = ({
4005
3600
  time2();
4006
3601
  }),
4007
3602
  share(),
4008
- takeUntil$1(context.$.destroy$)
3603
+ takeUntil$1(context.destroy$)
4009
3604
  );
4010
3605
  itemUpdateOnNavigation$.pipe(
4011
3606
  switchMap$1((data) => {
4012
3607
  return adjustPagination(data.position).pipe(takeUntil$1(spineItemManager.$.layout$));
4013
3608
  }),
4014
- takeUntil$1(context.$.destroy$)
3609
+ takeUntil$1(context.destroy$)
4015
3610
  ).subscribe();
4016
3611
  merge(
4017
3612
  /**
@@ -4032,8 +3627,7 @@ const createSpine = ({
4032
3627
  map$1(([, currentNavigationPosition]) => {
4033
3628
  const focusedSpineItemIndex = spineItemManager.getFocusedSpineItemIndex();
4034
3629
  report.log(`update contents`, { focusedSpineItemIndex });
4035
- if (focusedSpineItemIndex === void 0)
4036
- return;
3630
+ if (focusedSpineItemIndex === void 0) return;
4037
3631
  const { begin = focusedSpineItemIndex, end = focusedSpineItemIndex } = spineLocator.getSpineItemsFromReadingOrderPosition(currentNavigationPosition) || {};
4038
3632
  if (begin !== focusedSpineItemIndex && end !== focusedSpineItemIndex) {
4039
3633
  Report.warn(`Current viewport is not in sync with focus item, load from focus item rather than viewport`);
@@ -4045,7 +3639,7 @@ const createSpine = ({
4045
3639
  take(1)
4046
3640
  );
4047
3641
  }),
4048
- takeUntil$1(context.$.destroy$)
3642
+ takeUntil$1(context.destroy$)
4049
3643
  ).subscribe();
4050
3644
  const elementSub = element$.pipe().subscribe((element) => {
4051
3645
  const containerElement = createContainerElement(element.ownerDocument);
@@ -4057,7 +3651,6 @@ const createSpine = ({
4057
3651
  locator: spineLocator,
4058
3652
  spineItemLocator,
4059
3653
  cfiLocator,
4060
- normalizeEventForViewport: eventsHelper.normalizeEventForViewport,
4061
3654
  manipulateSpineItems,
4062
3655
  manipulateSpineItem,
4063
3656
  destroy: () => {
@@ -4104,16 +3697,16 @@ const createSpineItemManager = ({ context, settings }) => {
4104
3697
  const orderedSpineItemsSubject$ = new BehaviorSubject([]);
4105
3698
  let focusedSpineItemIndex;
4106
3699
  const layout = () => {
4107
- const manifest = context.getManifest();
3700
+ const manifest = context.manifest;
4108
3701
  const newItemLayoutInformation = [];
4109
3702
  const isGloballyPrePaginated = (manifest == null ? void 0 : manifest.renditionLayout) === `pre-paginated`;
4110
3703
  orderedSpineItemsSubject$.value.reduce(
4111
3704
  ({ horizontalOffset, verticalOffset }, item, index) => {
4112
3705
  let minimumWidth = context.getPageSize().width;
4113
3706
  let blankPagePosition = `none`;
4114
- const itemStartOnNewScreen = horizontalOffset % context.getVisibleAreaRect().width === 0;
3707
+ const itemStartOnNewScreen = horizontalOffset % context.state.visibleAreaRect.width === 0;
4115
3708
  const isLastItem = index === orderedSpineItemsSubject$.value.length - 1;
4116
- if (context.isUsingSpreadMode()) {
3709
+ if (context.state.isUsingSpreadMode) {
4117
3710
  if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && !isLastItem) {
4118
3711
  minimumWidth = context.getPageSize().width * 2;
4119
3712
  }
@@ -4139,10 +3732,10 @@ const createSpineItemManager = ({ context, settings }) => {
4139
3732
  const { width, height } = item.layout({
4140
3733
  minimumWidth,
4141
3734
  blankPagePosition,
4142
- spreadPosition: context.isUsingSpreadMode() ? itemStartOnNewScreen ? context.isRTL() ? `right` : `left` : context.isRTL() ? `left` : `right` : `none`
3735
+ spreadPosition: context.state.isUsingSpreadMode ? itemStartOnNewScreen ? context.isRTL() ? `right` : `left` : context.isRTL() ? `left` : `right` : `none`
4143
3736
  });
4144
- if (settings.getSettings().computedPageTurnDirection === `vertical`) {
4145
- const currentValidEdgeYForVerticalPositioning = itemStartOnNewScreen ? verticalOffset : verticalOffset - context.getVisibleAreaRect().height;
3737
+ if (settings.settings.computedPageTurnDirection === `vertical`) {
3738
+ const currentValidEdgeYForVerticalPositioning = itemStartOnNewScreen ? verticalOffset : verticalOffset - context.state.visibleAreaRect.height;
4146
3739
  const currentValidEdgeXForVerticalPositioning = itemStartOnNewScreen ? 0 : horizontalOffset;
4147
3740
  if (context.isRTL()) {
4148
3741
  item.adjustPositionOfElement({
@@ -4170,11 +3763,13 @@ const createSpineItemManager = ({ context, settings }) => {
4170
3763
  verticalOffset: newEdgeY
4171
3764
  };
4172
3765
  }
4173
- item.adjustPositionOfElement(context.isRTL() ? { right: horizontalOffset, top: 0 } : { left: horizontalOffset, top: 0 });
3766
+ item.adjustPositionOfElement(
3767
+ context.isRTL() ? { right: horizontalOffset, top: 0 } : { left: horizontalOffset, top: 0 }
3768
+ );
4174
3769
  newItemLayoutInformation.push({
4175
3770
  ...context.isRTL() ? {
4176
- left: context.getVisibleAreaRect().width - horizontalOffset - width,
4177
- right: context.getVisibleAreaRect().width - horizontalOffset
3771
+ left: context.state.visibleAreaRect.width - horizontalOffset - width,
3772
+ right: context.state.visibleAreaRect.width - horizontalOffset
4178
3773
  } : {
4179
3774
  left: horizontalOffset,
4180
3775
  right: horizontalOffset + width
@@ -4191,27 +3786,27 @@ const createSpineItemManager = ({ context, settings }) => {
4191
3786
  },
4192
3787
  { horizontalOffset: 0, verticalOffset: 0 }
4193
3788
  );
4194
- const hasLayoutChanges = itemLayoutInformation.some((old, index) => !isShallowEqual(old, newItemLayoutInformation[index]));
3789
+ const hasLayoutChanges = itemLayoutInformation.some(
3790
+ (old, index) => !isShallowEqual(old, newItemLayoutInformation[index])
3791
+ );
4195
3792
  itemLayoutInformation = newItemLayoutInformation;
4196
3793
  Report.log(NAMESPACE$4, `layout`, { hasLayoutChanges, itemLayoutInformation });
4197
3794
  layout$.next(hasLayoutChanges);
4198
3795
  };
4199
3796
  const focus = (indexOrSpineItem) => {
4200
3797
  const spineItemToFocus = typeof indexOrSpineItem === `number` ? get(indexOrSpineItem) : indexOrSpineItem;
4201
- if (!spineItemToFocus)
4202
- return;
3798
+ if (!spineItemToFocus) return;
4203
3799
  const newActiveSpineItemIndex = orderedSpineItemsSubject$.value.indexOf(spineItemToFocus);
4204
- if (newActiveSpineItemIndex === focusedSpineItemIndex)
4205
- return;
3800
+ if (newActiveSpineItemIndex === focusedSpineItemIndex) return;
4206
3801
  focusedSpineItemIndex = newActiveSpineItemIndex;
4207
3802
  focus$.next({ data: spineItemToFocus });
4208
3803
  };
4209
3804
  const loadContents = Report.measurePerformance(`loadContents`, 10, (rangeOfIndex) => {
4210
3805
  var _a;
4211
3806
  const [leftIndex, rightIndex] = rangeOfIndex;
4212
- const numberOfAdjacentSpineItemToPreLoad = settings.getSettings().numberOfAdjacentSpineItemToPreLoad;
4213
- const isPrePaginated = ((_a = context.getManifest()) == null ? void 0 : _a.renditionLayout) === `pre-paginated`;
4214
- const isUsingFreeScroll = settings.getSettings().computedPageTurnMode === `scrollable`;
3807
+ const numberOfAdjacentSpineItemToPreLoad = settings.settings.numberOfAdjacentSpineItemToPreLoad;
3808
+ const isPrePaginated = ((_a = context.manifest) == null ? void 0 : _a.renditionLayout) === `pre-paginated`;
3809
+ const isUsingFreeScroll = settings.settings.computedPageTurnMode === `scrollable`;
4215
3810
  orderedSpineItemsSubject$.value.forEach((orderedSpineItem, index) => {
4216
3811
  const isBeforeFocusedWithPreload = (
4217
3812
  // we never want to preload anything before on free scroll on flow because it could offset the cursor
@@ -4252,25 +3847,28 @@ const createSpineItemManager = ({ context, settings }) => {
4252
3847
  return `before`;
4253
3848
  };
4254
3849
  const getSpineItemIndex = (spineItem) => {
4255
- if (!spineItem)
4256
- return void 0;
3850
+ if (!spineItem) return void 0;
4257
3851
  const index = orderedSpineItemsSubject$.value.indexOf(spineItem);
4258
3852
  return index < 0 ? void 0 : index;
4259
3853
  };
4260
3854
  const add = (spineItem) => {
4261
3855
  orderedSpineItemsSubject$.value.push(spineItem);
4262
- spineItem.$.contentLayout$.pipe(takeUntil$1(context.$.destroy$)).subscribe(() => {
3856
+ spineItem.$.contentLayout$.pipe(takeUntil$1(context.destroy$)).subscribe(() => {
4263
3857
  layout();
4264
3858
  });
4265
3859
  spineItem.$.loaded$.pipe(
4266
3860
  tap(() => {
4267
3861
  if (spineItem.isUsingVerticalWriting()) {
4268
- context.setHasVerticalWriting(true);
3862
+ context.update({
3863
+ hasVerticalWriting: true
3864
+ });
4269
3865
  } else {
4270
- context.setHasVerticalWriting(false);
3866
+ context.update({
3867
+ hasVerticalWriting: false
3868
+ });
4271
3869
  }
4272
3870
  }),
4273
- takeUntil$1(context.$.destroy$)
3871
+ takeUntil$1(context.destroy$)
4274
3872
  ).subscribe();
4275
3873
  spineItem.load();
4276
3874
  };
@@ -4310,12 +3908,175 @@ const createSpineItemManager = ({ context, settings }) => {
4310
3908
  layout$: layout$.asObservable(),
4311
3909
  itemIsReady$: orderedSpineItemsSubject$.asObservable().pipe(
4312
3910
  switchMap$1((items) => {
4313
- const itemsIsReady$ = items.map((item) => item.$.isReady$.pipe(map$1((isReady) => ({ item: item.item, isReady }))));
3911
+ const itemsIsReady$ = items.map(
3912
+ (item) => item.$.isReady$.pipe(map$1((isReady) => ({ item: item.item, isReady })))
3913
+ );
4314
3914
  return merge(...itemsIsReady$);
4315
3915
  })
4316
3916
  )
4317
3917
  }
4318
- };
3918
+ };
3919
+ };
3920
+ const pointerEvents$1 = [
3921
+ `pointercancel`,
3922
+ `pointerdown`,
3923
+ `pointerenter`,
3924
+ `pointerleave`,
3925
+ `pointermove`,
3926
+ `pointerout`,
3927
+ `pointerover`,
3928
+ `pointerup`
3929
+ // `touchstart` as const,
3930
+ // `touchend` as const,
3931
+ ];
3932
+ const isHtmlElement = (element) => {
3933
+ return typeof element === `object` && !!element && `nodeType` in element && (element == null ? void 0 : element.nodeType) === Node.ELEMENT_NODE && `innerText` in element;
3934
+ };
3935
+ function createRangeOrCaretFromPoint(doc, startX, startY) {
3936
+ if (`caretPositionFromPoint` in doc) {
3937
+ return doc.caretPositionFromPoint(startX, startY);
3938
+ } else if (typeof doc.caretRangeFromPoint !== `undefined`) {
3939
+ return doc.caretRangeFromPoint(startX, startY);
3940
+ }
3941
+ }
3942
+ const getFirstVisibleNodeForViewport = Report.measurePerformance(
3943
+ `getFirstVisibleNodeForViewport`,
3944
+ 1,
3945
+ (documentOrElement, viewport) => {
3946
+ const element = `body` in documentOrElement ? getFirstVisibleElementForViewport(documentOrElement.body, viewport) : getFirstVisibleElementForViewport(documentOrElement, viewport);
3947
+ const ownerDocument = `createRange` in documentOrElement ? documentOrElement : documentOrElement.ownerDocument;
3948
+ if (element) {
3949
+ let lastValidRange;
3950
+ let lastValidOffset = 0;
3951
+ const range = ownerDocument.createRange();
3952
+ Array.from(element.childNodes).some((childNode) => {
3953
+ range.selectNodeContents(childNode);
3954
+ const rects = range.getClientRects();
3955
+ const visibleRect = getFirstVisibleDOMRect(rects, viewport);
3956
+ if (visibleRect) {
3957
+ lastValidRange = range.cloneRange();
3958
+ const rangeOrCaret = createRangeOrCaretFromPoint(
3959
+ ownerDocument,
3960
+ Math.ceil(visibleRect.left),
3961
+ Math.ceil(visibleRect.top)
3962
+ );
3963
+ if (rangeOrCaret && `startContainer` in rangeOrCaret && rangeOrCaret.startContainer === lastValidRange.startContainer) {
3964
+ lastValidOffset = rangeOrCaret.startOffset;
3965
+ }
3966
+ if (rangeOrCaret && `offsetNode` in rangeOrCaret && rangeOrCaret.offsetNode === lastValidRange.startContainer) {
3967
+ lastValidOffset = rangeOrCaret.offset;
3968
+ }
3969
+ return true;
3970
+ }
3971
+ return false;
3972
+ });
3973
+ if (lastValidRange) {
3974
+ return { node: lastValidRange.startContainer, offset: lastValidOffset };
3975
+ }
3976
+ return { node: element, offset: 0 };
3977
+ }
3978
+ return void 0;
3979
+ }
3980
+ );
3981
+ const getFirstVisibleElementForViewport = (element, viewport) => {
3982
+ let lastValidElement;
3983
+ const positionFromViewport = getElementOrNodePositionFromViewPort(element.getBoundingClientRect(), viewport);
3984
+ if (positionFromViewport !== `before` && positionFromViewport !== `after`) {
3985
+ lastValidElement = element;
3986
+ }
3987
+ Array.from(element.children).some((child) => {
3988
+ const childInViewPort = getFirstVisibleElementForViewport(child, viewport);
3989
+ if (childInViewPort) {
3990
+ lastValidElement = childInViewPort;
3991
+ return true;
3992
+ }
3993
+ return false;
3994
+ });
3995
+ return lastValidElement;
3996
+ };
3997
+ function getElementOrNodePositionFromViewPort(domRect, { left, right }) {
3998
+ if (domRect.left <= left && domRect.right <= left) return `before`;
3999
+ if (domRect.left <= left && domRect.right > left && domRect.right <= right) return `partially-before`;
4000
+ if (domRect.left <= right && domRect.right > right) return `partially-after`;
4001
+ if (domRect.left > right) return `after`;
4002
+ return `within`;
4003
+ }
4004
+ function getFirstVisibleDOMRect(domRect, viewport) {
4005
+ return Array.from(domRect).find((domRect2) => {
4006
+ const position = getElementOrNodePositionFromViewPort(domRect2, viewport);
4007
+ if (position !== `before` && position !== `after`) {
4008
+ return true;
4009
+ }
4010
+ return false;
4011
+ });
4012
+ }
4013
+ const getRangeFromNode = (node, offset) => {
4014
+ var _a;
4015
+ if (node.nodeType !== Node.CDATA_SECTION_NODE && node.nodeType !== Node.DOCUMENT_TYPE_NODE) {
4016
+ const range = (_a = node.ownerDocument) == null ? void 0 : _a.createRange();
4017
+ range == null ? void 0 : range.selectNodeContents(node);
4018
+ try {
4019
+ if (offset <= ((range == null ? void 0 : range.endOffset) || 0)) {
4020
+ range == null ? void 0 : range.setStart(node, offset || 0);
4021
+ }
4022
+ } catch (e) {
4023
+ Report.error(e);
4024
+ }
4025
+ return range;
4026
+ }
4027
+ return void 0;
4028
+ };
4029
+ const isPointerEvent = (event) => {
4030
+ var _a, _b, _c, _d, _e;
4031
+ if ((event == null ? void 0 : event.target) && ((_b = (_a = event == null ? void 0 : event.target) == null ? void 0 : _a.ownerDocument) == null ? void 0 : _b.defaultView)) {
4032
+ const eventView = (_d = (_c = event == null ? void 0 : event.target) == null ? void 0 : _c.ownerDocument) == null ? void 0 : _d.defaultView;
4033
+ if (eventView.PointerEvent && event instanceof eventView.PointerEvent) {
4034
+ return true;
4035
+ }
4036
+ }
4037
+ if ((event == null ? void 0 : event.view) && ((_e = event == null ? void 0 : event.view) == null ? void 0 : _e.window)) {
4038
+ const eventView = event == null ? void 0 : event.view;
4039
+ if (eventView.PointerEvent && event instanceof eventView.PointerEvent) {
4040
+ return true;
4041
+ }
4042
+ }
4043
+ if (pointerEvents$1.includes(event.type)) {
4044
+ return true;
4045
+ }
4046
+ return false;
4047
+ };
4048
+ const isMouseEvent = (event) => {
4049
+ var _a, _b, _c, _d, _e;
4050
+ if (isPointerEvent(event)) return false;
4051
+ if ((event == null ? void 0 : event.target) && ((_b = (_a = event == null ? void 0 : event.target) == null ? void 0 : _a.ownerDocument) == null ? void 0 : _b.defaultView)) {
4052
+ const eventView = (_d = (_c = event == null ? void 0 : event.target) == null ? void 0 : _c.ownerDocument) == null ? void 0 : _d.defaultView;
4053
+ if (eventView.MouseEvent) {
4054
+ return event instanceof eventView.MouseEvent;
4055
+ }
4056
+ }
4057
+ if ((event == null ? void 0 : event.view) && ((_e = event == null ? void 0 : event.view) == null ? void 0 : _e.window)) {
4058
+ const eventView = event == null ? void 0 : event.view;
4059
+ if (eventView.MouseEvent) {
4060
+ return event instanceof eventView.MouseEvent;
4061
+ }
4062
+ }
4063
+ return false;
4064
+ };
4065
+ const isTouchEvent = (event) => {
4066
+ var _a, _b, _c, _d, _e;
4067
+ if ((event == null ? void 0 : event.target) && ((_b = (_a = event == null ? void 0 : event.target) == null ? void 0 : _a.ownerDocument) == null ? void 0 : _b.defaultView)) {
4068
+ const eventView = (_d = (_c = event == null ? void 0 : event.target) == null ? void 0 : _c.ownerDocument) == null ? void 0 : _d.defaultView;
4069
+ if (eventView.TouchEvent) {
4070
+ return event instanceof eventView.TouchEvent;
4071
+ }
4072
+ }
4073
+ if ((event == null ? void 0 : event.view) && ((_e = event == null ? void 0 : event.view) == null ? void 0 : _e.window)) {
4074
+ const eventView = event == null ? void 0 : event.view;
4075
+ if (eventView.TouchEvent) {
4076
+ return event instanceof eventView.TouchEvent;
4077
+ }
4078
+ }
4079
+ return false;
4319
4080
  };
4320
4081
  const createLocationResolver$1 = ({ context }) => {
4321
4082
  const getSafePosition = (unsafeSpineItemPosition, spineItem) => ({
@@ -4415,10 +4176,8 @@ const createLocationResolver$1 = ({ context }) => {
4415
4176
  };
4416
4177
  const getPageFromOffset = (offset, pageWidth, numberOfPages) => {
4417
4178
  const offsetValues = [...Array(numberOfPages)].map((_, i) => i * pageWidth);
4418
- if (offset <= 0)
4419
- return 0;
4420
- if (offset >= numberOfPages * pageWidth)
4421
- return numberOfPages - 1;
4179
+ if (offset <= 0) return 0;
4180
+ if (offset >= numberOfPages * pageWidth) return numberOfPages - 1;
4422
4181
  return Math.max(
4423
4182
  0,
4424
4183
  offsetValues.findIndex((offsetRange) => offset < offsetRange + pageWidth)
@@ -4454,7 +4213,10 @@ const createNavigationResolver$1 = ({ context }) => {
4454
4213
  y: position.y + context.getPageSize().height
4455
4214
  };
4456
4215
  }
4457
- const navigationPosition = spineItemLocator.getSpineItemClosestPositionFromUnsafePosition(nextPotentialPosition, spineItem);
4216
+ const navigationPosition = spineItemLocator.getSpineItemClosestPositionFromUnsafePosition(
4217
+ nextPotentialPosition,
4218
+ spineItem
4219
+ );
4458
4220
  return new SpineItemNavigationPosition(navigationPosition);
4459
4221
  };
4460
4222
  const getNavigationForRightPage = (position, spineItem) => {
@@ -4468,7 +4230,10 @@ const createNavigationResolver$1 = ({ context }) => {
4468
4230
  y: position.y - context.getPageSize().height
4469
4231
  };
4470
4232
  }
4471
- const navigationPosition = spineItemLocator.getSpineItemClosestPositionFromUnsafePosition(nextPotentialPosition, spineItem);
4233
+ const navigationPosition = spineItemLocator.getSpineItemClosestPositionFromUnsafePosition(
4234
+ nextPotentialPosition,
4235
+ spineItem
4236
+ );
4472
4237
  return new SpineItemNavigationPosition(navigationPosition);
4473
4238
  };
4474
4239
  const getNavigationForLastPage = (spineItem) => {
@@ -4491,7 +4256,10 @@ const createNavigationResolver$1 = ({ context }) => {
4491
4256
  return new SpineItemNavigationPosition(position || { x: 0, y: 0 });
4492
4257
  };
4493
4258
  const getNavigationForPosition = (spineItem, position) => {
4494
- const potentiallyCorrectedPosition = spineItemLocator.getSpineItemClosestPositionFromUnsafePosition(position, spineItem);
4259
+ const potentiallyCorrectedPosition = spineItemLocator.getSpineItemClosestPositionFromUnsafePosition(
4260
+ position,
4261
+ spineItem
4262
+ );
4495
4263
  return new SpineItemNavigationPosition(potentiallyCorrectedPosition);
4496
4264
  };
4497
4265
  return {
@@ -4537,7 +4305,7 @@ const createNavigationResolver = ({
4537
4305
  { disable: true }
4538
4306
  );
4539
4307
  const getAdjustedPositionForSpread = ({ x, y }) => {
4540
- const isOffsetNotAtEdge = x % context.getVisibleAreaRect().width !== 0;
4308
+ const isOffsetNotAtEdge = x % context.state.visibleAreaRect.width !== 0;
4541
4309
  const correctedX = isOffsetNotAtEdge ? x - context.getPageSize().width : x;
4542
4310
  return { x: correctedX, y };
4543
4311
  };
@@ -4576,7 +4344,7 @@ const createNavigationResolver = ({
4576
4344
  return { x: 0, y: 0 };
4577
4345
  };
4578
4346
  const getNavigationForRightSinglePage = (position) => {
4579
- const pageTurnDirection = settings.getSettings().computedPageTurnDirection;
4347
+ const pageTurnDirection = settings.settings.computedPageTurnDirection;
4580
4348
  const spineItem = locator.getSpineItemFromPosition(position) || spineItemManager.getFocusedSpineItem();
4581
4349
  const defaultNavigation = position;
4582
4350
  if (!spineItem) {
@@ -4590,12 +4358,15 @@ const createNavigationResolver = ({
4590
4358
  pageTurnDirection === `horizontal` ? { x: position.x + context.getPageSize().width, y: 0 } : { y: position.y + context.getPageSize().height, x: 0 }
4591
4359
  );
4592
4360
  } else {
4593
- const readingOrderPosition = locator.getSpinePositionFromSpineItemPosition(spineItemNavigationForRightPage, spineItem);
4361
+ const readingOrderPosition = locator.getSpinePositionFromSpineItemPosition(
4362
+ spineItemNavigationForRightPage,
4363
+ spineItem
4364
+ );
4594
4365
  return readingOrderPosition;
4595
4366
  }
4596
4367
  };
4597
4368
  const getNavigationForLeftSinglePage = (position) => {
4598
- const pageTurnDirection = settings.getSettings().computedPageTurnDirection;
4369
+ const pageTurnDirection = settings.settings.computedPageTurnDirection;
4599
4370
  const spineItem = locator.getSpineItemFromPosition(position) || spineItemManager.getFocusedSpineItem();
4600
4371
  const defaultNavigation = { ...position, spineItem };
4601
4372
  if (!spineItem) {
@@ -4619,7 +4390,7 @@ const createNavigationResolver = ({
4619
4390
  if ((spineItemOnPosition == null ? void 0 : spineItemOnPosition.isUsingVerticalWriting()) && position.x === navigation.x) {
4620
4391
  return getAdjustedPositionForSpread(navigation);
4621
4392
  }
4622
- if (context.isUsingSpreadMode()) {
4393
+ if (context.state.isUsingSpreadMode) {
4623
4394
  if ((spineItemOnPosition == null ? void 0 : spineItemOnPosition.isUsingVerticalWriting()) && position.x !== navigation.x) {
4624
4395
  return getAdjustedPositionForSpread(
4625
4396
  wrapPositionWithSafeEdge(
@@ -4633,7 +4404,7 @@ const createNavigationResolver = ({
4633
4404
  )
4634
4405
  );
4635
4406
  }
4636
- if (settings.getSettings().computedPageTurnDirection === `vertical` && position.y !== navigation.y) {
4407
+ if (settings.settings.computedPageTurnDirection === `vertical` && position.y !== navigation.y) {
4637
4408
  return getAdjustedPositionForSpread(navigation);
4638
4409
  }
4639
4410
  const doubleNavigation = getNavigationForRightSinglePage(navigation);
@@ -4647,7 +4418,7 @@ const createNavigationResolver = ({
4647
4418
  if ((spineItemOnPosition == null ? void 0 : spineItemOnPosition.isUsingVerticalWriting()) && position.x === navigation.x) {
4648
4419
  return getAdjustedPositionForSpread(navigation);
4649
4420
  }
4650
- if (context.isUsingSpreadMode()) {
4421
+ if (context.state.isUsingSpreadMode) {
4651
4422
  if ((spineItemOnPosition == null ? void 0 : spineItemOnPosition.isUsingVerticalWriting()) && position.x !== navigation.x) {
4652
4423
  return getAdjustedPositionForSpread(
4653
4424
  wrapPositionWithSafeEdge(
@@ -4655,7 +4426,7 @@ const createNavigationResolver = ({
4655
4426
  )
4656
4427
  );
4657
4428
  }
4658
- if (settings.getSettings().computedPageTurnDirection === `vertical` && position.y !== navigation.y) {
4429
+ if (settings.settings.computedPageTurnDirection === `vertical` && position.y !== navigation.y) {
4659
4430
  return getAdjustedPositionForSpread(navigation);
4660
4431
  }
4661
4432
  const doubleNavigation = getNavigationForLeftSinglePage(navigation);
@@ -4668,7 +4439,7 @@ const createNavigationResolver = ({
4668
4439
  try {
4669
4440
  const validUrl = url instanceof URL ? url : new URL(url);
4670
4441
  const urlWithoutAnchor = `${validUrl.origin}${validUrl.pathname}`;
4671
- const existingSpineItem = (_a = context.getManifest()) == null ? void 0 : _a.spineItems.find((item) => item.href === urlWithoutAnchor);
4442
+ const existingSpineItem = (_a = context.manifest) == null ? void 0 : _a.spineItems.find((item) => item.href === urlWithoutAnchor);
4672
4443
  if (existingSpineItem) {
4673
4444
  const spineItem = spineItemManager.get(existingSpineItem.id);
4674
4445
  if (spineItem) {
@@ -4697,15 +4468,15 @@ const createNavigationResolver = ({
4697
4468
  return { x: 0, y: 0 };
4698
4469
  };
4699
4470
  const getMostPredominantNavigationForPosition = (viewportPosition) => {
4700
- const pageTurnDirection = settings.getSettings().computedPageTurnDirection;
4471
+ const pageTurnDirection = settings.settings.computedPageTurnDirection;
4701
4472
  const triggerPercentage = 0.5;
4702
- const triggerXPosition = pageTurnDirection === `horizontal` ? viewportPosition.x + context.getVisibleAreaRect().width * triggerPercentage : 0;
4703
- const triggerYPosition = pageTurnDirection === `horizontal` ? 0 : viewportPosition.y + context.getVisibleAreaRect().height * triggerPercentage;
4473
+ const triggerXPosition = pageTurnDirection === `horizontal` ? viewportPosition.x + context.state.visibleAreaRect.width * triggerPercentage : 0;
4474
+ const triggerYPosition = pageTurnDirection === `horizontal` ? 0 : viewportPosition.y + context.state.visibleAreaRect.height * triggerPercentage;
4704
4475
  const midScreenPositionSafePosition = wrapPositionWithSafeEdge({ x: triggerXPosition, y: triggerYPosition });
4705
4476
  return getNavigationForPosition(midScreenPositionSafePosition);
4706
4477
  };
4707
4478
  const isNavigationGoingForwardFrom = (to, from2) => {
4708
- const pageTurnDirection = settings.getSettings().computedPageTurnDirection;
4479
+ const pageTurnDirection = settings.settings.computedPageTurnDirection;
4709
4480
  if (pageTurnDirection === `vertical`) {
4710
4481
  return to.y > from2.y;
4711
4482
  }
@@ -4749,14 +4520,14 @@ const createScrollViewportNavigator = ({
4749
4520
  );
4750
4521
  const adjustReadingOffset = ({ x, y }) => {
4751
4522
  var _a;
4752
- if (settings.getSettings().computedPageTurnMode === `scrollable`) {
4523
+ if (settings.settings.computedPageTurnMode === `scrollable`) {
4753
4524
  lastScrollWasProgrammaticallyTriggered = true;
4754
4525
  (_a = element$.getValue()) == null ? void 0 : _a.scrollTo({ left: x, top: y });
4755
4526
  return true;
4756
4527
  }
4757
4528
  return false;
4758
4529
  };
4759
- const runOnFreePageTurnModeOnly$ = (source) => settings.$.settings$.pipe(
4530
+ const runOnFreePageTurnModeOnly$ = (source) => settings.settings$.pipe(
4760
4531
  map$1(({ computedPageTurnMode }) => computedPageTurnMode),
4761
4532
  distinctUntilChanged(),
4762
4533
  switchMap$1((mode) => iif(() => mode === `controlled`, EMPTY, source))
@@ -4766,12 +4537,11 @@ const createScrollViewportNavigator = ({
4766
4537
  filter(isDefined),
4767
4538
  switchMap$1((element) => fromEvent(element, `scroll`))
4768
4539
  )
4769
- ).pipe(onlyUserScrollFilter, share(), takeUntil$1(context.$.destroy$));
4540
+ ).pipe(onlyUserScrollFilter, share(), takeUntil$1(context.destroy$));
4770
4541
  const getScaledDownPosition = ({ x, y }) => {
4771
4542
  var _a, _b;
4772
4543
  const spineElement = spine.getElement();
4773
- if (!spineElement)
4774
- throw new Error("Invalid spine element");
4544
+ if (!spineElement) throw new Error("Invalid spine element");
4775
4545
  const spineScaleX = spineElement.getBoundingClientRect().width / spineElement.offsetWidth;
4776
4546
  const scaledDownPosition = {
4777
4547
  x: getNewScaledOffset({
@@ -4814,7 +4584,7 @@ const createScrollViewportNavigator = ({
4814
4584
  const userScrollEnd$ = userScroll$.pipe(
4815
4585
  debounceTime$1(SCROLL_FINISHED_DEBOUNCE_TIMEOUT, animationFrameScheduler),
4816
4586
  share(),
4817
- takeUntil$1(context.$.destroy$)
4587
+ takeUntil$1(context.destroy$)
4818
4588
  );
4819
4589
  const state$ = merge(
4820
4590
  userScroll$.pipe(
@@ -4907,7 +4677,7 @@ const createManualViewportNavigator = ({
4907
4677
  filter((e) => e.type === `pageIndex`),
4908
4678
  filter(() => {
4909
4679
  var _a;
4910
- if (((_a = context.getManifest()) == null ? void 0 : _a.renditionLayout) === `reflowable`) {
4680
+ if (((_a = context.manifest) == null ? void 0 : _a.renditionLayout) === `reflowable`) {
4911
4681
  Report.warn(`This method only works for pre-paginated content`);
4912
4682
  return false;
4913
4683
  }
@@ -4926,13 +4696,15 @@ const createManualViewportNavigator = ({
4926
4696
  10,
4927
4697
  (navigation, { allowSpineItemChange = true } = {}) => {
4928
4698
  const currentSpineItem = spineItemManager.getFocusedSpineItem();
4929
- if (!currentSpineItem)
4930
- return EMPTY;
4699
+ if (!currentSpineItem) return EMPTY;
4931
4700
  const newSpineItem = locator.getSpineItemFromPosition(navigation) || currentSpineItem;
4932
4701
  const spineItemHasChanged = newSpineItem !== currentSpineItem;
4933
4702
  if (spineItemHasChanged) {
4934
4703
  if (allowSpineItemChange) {
4935
- const positionOfNewSpineItemComparedToCurrentOne = spineItemManager.comparePositionOf(newSpineItem, currentSpineItem);
4704
+ const positionOfNewSpineItemComparedToCurrentOne = spineItemManager.comparePositionOf(
4705
+ newSpineItem,
4706
+ currentSpineItem
4707
+ );
4936
4708
  if (positionOfNewSpineItemComparedToCurrentOne === `before`) {
4937
4709
  return of({
4938
4710
  ...navigation,
@@ -5041,11 +4813,11 @@ const createPanViewportNavigator = ({
5041
4813
  `${NAMESPACE$1} moveTo`,
5042
4814
  5,
5043
4815
  (delta, { final, start } = {}) => {
5044
- if (settings.getSettings().computedPageTurnMode === `scrollable`) {
4816
+ if (settings.settings.computedPageTurnMode === `scrollable`) {
5045
4817
  Report.warn(`pan control is not available on free page turn mode`);
5046
4818
  return;
5047
4819
  }
5048
- const pageTurnDirection = settings.getSettings().computedPageTurnDirection;
4820
+ const pageTurnDirection = settings.settings.computedPageTurnDirection;
5049
4821
  if (start) {
5050
4822
  stateSubject$.next(`start`);
5051
4823
  movingLastDelta = { x: 0, y: 0 };
@@ -5086,8 +4858,7 @@ const createPanViewportNavigator = ({
5086
4858
  10,
5087
4859
  (navigation, { allowSpineItemChange = true } = {}) => {
5088
4860
  const currentSpineItem = spineItemManager.getFocusedSpineItem();
5089
- if (!currentSpineItem)
5090
- return void 0;
4861
+ if (!currentSpineItem) return void 0;
5091
4862
  const newSpineItem = locator.getSpineItemFromPosition(navigation) || currentSpineItem;
5092
4863
  const spineItemHasChanged = newSpineItem !== currentSpineItem;
5093
4864
  if (spineItemHasChanged) {
@@ -5105,7 +4876,7 @@ const createPanViewportNavigator = ({
5105
4876
  );
5106
4877
  const snapNavigation$ = navigationTriggerSubject$.pipe(
5107
4878
  filter((e) => e.type === `snap`),
5108
- withLatestFrom$1(settings.$.settings$),
4879
+ withLatestFrom$1(settings.settings$),
5109
4880
  switchMap$1(
5110
4881
  ([
5111
4882
  {
@@ -5113,11 +4884,11 @@ const createPanViewportNavigator = ({
5113
4884
  },
5114
4885
  { navigationSnapThreshold }
5115
4886
  ]) => {
5116
- const pageTurnDirection = settings.getSettings().computedPageTurnDirection;
4887
+ const pageTurnDirection = settings.settings.computedPageTurnDirection;
5117
4888
  const movingForward = navigator2.isNavigationGoingForwardFrom(to, from2);
5118
4889
  const triggerPercentage = movingForward ? 1 - navigationSnapThreshold : navigationSnapThreshold;
5119
- const triggerXPosition = pageTurnDirection === `horizontal` ? to.x + context.getVisibleAreaRect().width * triggerPercentage : 0;
5120
- const triggerYPosition = pageTurnDirection === `horizontal` ? 0 : to.y + context.getVisibleAreaRect().height * triggerPercentage;
4890
+ const triggerXPosition = pageTurnDirection === `horizontal` ? to.x + context.state.visibleAreaRect.width * triggerPercentage : 0;
4891
+ const triggerYPosition = pageTurnDirection === `horizontal` ? 0 : to.y + context.state.visibleAreaRect.height * triggerPercentage;
5121
4892
  const midScreenPositionSafePosition = navigator2.wrapPositionWithSafeEdge({
5122
4893
  x: triggerXPosition,
5123
4894
  y: triggerYPosition
@@ -5154,7 +4925,7 @@ const createViewportNavigator = ({
5154
4925
  parentElement$,
5155
4926
  cfiLocator,
5156
4927
  spineLocator,
5157
- hooks$,
4928
+ hookManager,
5158
4929
  spine,
5159
4930
  settings
5160
4931
  }) => {
@@ -5176,7 +4947,7 @@ const createViewportNavigator = ({
5176
4947
  const adjustNavigationSubject$ = new Subject();
5177
4948
  const getCurrentViewportPosition = Report.measurePerformance(`${NAMESPACE} getCurrentViewportPosition`, 1, () => {
5178
4949
  var _a;
5179
- if (settings.getSettings().computedPageTurnMode === `scrollable`) {
4950
+ if (settings.settings.computedPageTurnMode === `scrollable`) {
5180
4951
  return scrollViewportNavigator.getCurrentViewportPosition();
5181
4952
  }
5182
4953
  const { x, y } = ((_a = element$.getValue()) == null ? void 0 : _a.getBoundingClientRect()) ?? { x: 0, y: 0 };
@@ -5220,16 +4991,15 @@ const createViewportNavigator = ({
5220
4991
  const viewportNavigatorsSharedState$ = merge(...viewportNavigators.map(({ $: { state$: state$2 } }) => state$2));
5221
4992
  let lastUserExpectedNavigation;
5222
4993
  const makeItHot = (source$) => {
5223
- source$.pipe(takeUntil$1(context.$.destroy$)).subscribe();
4994
+ source$.pipe(takeUntil$1(context.destroy$)).subscribe();
5224
4995
  return source$;
5225
4996
  };
5226
4997
  const adjustReadingOffset = Report.measurePerformance(
5227
4998
  `adjustReadingOffset`,
5228
4999
  2,
5229
- ({ x, y }, hooks) => {
5000
+ ({ x, y }) => {
5230
5001
  const element = element$.getValue();
5231
- if (!element)
5232
- throw new Error("Invalid element");
5002
+ if (!element) throw new Error("Invalid element");
5233
5003
  currentViewportPositionMemoUnused = void 0;
5234
5004
  const isAdjusted = viewportNavigators.reduce((isAdjusted2, navigator22) => {
5235
5005
  return navigator22.adjustReadingOffset({ x, y }) || isAdjusted2;
@@ -5237,11 +5007,7 @@ const createViewportNavigator = ({
5237
5007
  if (!isAdjusted) {
5238
5008
  element.style.transform = `translate3d(${-x}px, -${y}px, 0)`;
5239
5009
  }
5240
- hooks.forEach((hook) => {
5241
- if (hook.name === `onViewportOffsetAdjust`) {
5242
- hook.fn();
5243
- }
5244
- });
5010
+ hookManager.execute("onViewportOffsetAdjust", void 0, {});
5245
5011
  },
5246
5012
  { disable: true }
5247
5013
  );
@@ -5249,7 +5015,7 @@ const createViewportNavigator = ({
5249
5015
  const lastCfi = pagination.getPaginationInfo().beginCfi;
5250
5016
  let adjustedSpinePosition = currentNavigationPositionSubject$.value;
5251
5017
  const offsetInSpineItem = 0;
5252
- if (settings.getSettings().computedPageTurnMode === `scrollable`) {
5018
+ if (settings.settings.computedPageTurnMode === `scrollable`) {
5253
5019
  adjustedSpinePosition = scrollViewportNavigator.getNavigationForPosition(getCurrentViewportPosition());
5254
5020
  } else if ((lastUserExpectedNavigation == null ? void 0 : lastUserExpectedNavigation.type) === `navigate-from-cfi`) {
5255
5021
  adjustedSpinePosition = navigator2.getNavigationForCfi(lastUserExpectedNavigation.data);
@@ -5294,7 +5060,7 @@ const createViewportNavigator = ({
5294
5060
  layoutSubject$.subscribe(() => {
5295
5061
  currentViewportPositionMemoUnused = void 0;
5296
5062
  });
5297
- const layoutChangeSettings$ = settings.$.settings$.pipe(
5063
+ const layoutChangeSettings$ = settings.settings$.pipe(
5298
5064
  mapKeysTo([`computedPageTurnDirection`, `computedPageTurnMode`, `numberOfAdjacentSpineItemToPreLoad`]),
5299
5065
  distinctUntilChanged(isShallowEqual),
5300
5066
  skip(1)
@@ -5302,7 +5068,7 @@ const createViewportNavigator = ({
5302
5068
  const layout$ = merge(layoutSubject$, layoutChangeSettings$).pipe(
5303
5069
  withLatestFrom(element$),
5304
5070
  tap(([, element]) => {
5305
- if (settings.getSettings().computedPageTurnMode === `scrollable`) {
5071
+ if (settings.settings.computedPageTurnMode === `scrollable`) {
5306
5072
  element.style.removeProperty(`transform`);
5307
5073
  element.style.removeProperty(`transition`);
5308
5074
  element.style.overflow = `scroll`;
@@ -5354,11 +5120,11 @@ const createViewportNavigator = ({
5354
5120
  return { ...event, lastUserExpectedNavigation };
5355
5121
  }),
5356
5122
  share(),
5357
- takeUntil$1(context.$.destroy$)
5123
+ takeUntil$1(context.destroy$)
5358
5124
  );
5359
5125
  const navigationWhichRequireManualAdjust$ = navigation$.pipe(
5360
5126
  filter(({ triggeredBy }) => {
5361
- if (triggeredBy === `scroll` || settings.getSettings().computedPageTurnMode === `scrollable` && triggeredBy === `adjust`) {
5127
+ if (triggeredBy === `scroll` || settings.settings.computedPageTurnMode === `scrollable` && triggeredBy === `adjust`) {
5362
5128
  return false;
5363
5129
  } else {
5364
5130
  return true;
@@ -5370,7 +5136,7 @@ const createViewportNavigator = ({
5370
5136
  navigationWhichRequireManualAdjust$
5371
5137
  ).pipe(
5372
5138
  map$1(({ animation, position }) => {
5373
- const shouldAnimate = !(!animation || animation === `turn` && settings.getSettings().computedPageTurnAnimation === `none`);
5139
+ const shouldAnimate = !(!animation || animation === `turn` && settings.settings.computedPageTurnAnimation === `none`);
5374
5140
  return {
5375
5141
  type: `manualAdjust`,
5376
5142
  shouldAnimate,
@@ -5390,10 +5156,9 @@ const createViewportNavigator = ({
5390
5156
  }
5391
5157
  }),
5392
5158
  switchMap$1(([, currentEvent]) => {
5393
- if ((currentEvent == null ? void 0 : currentEvent.type) !== `manualAdjust`)
5394
- return EMPTY;
5395
- const animationDuration = currentEvent.animation === `snap` ? settings.getSettings().computedSnapAnimationDuration : settings.getSettings().computedPageTurnAnimationDuration;
5396
- const pageTurnAnimation = currentEvent.animation === `snap` ? `slide` : settings.getSettings().computedPageTurnAnimation;
5159
+ if ((currentEvent == null ? void 0 : currentEvent.type) !== `manualAdjust`) return EMPTY;
5160
+ const animationDuration = currentEvent.animation === `snap` ? settings.settings.computedSnapAnimationDuration : settings.settings.computedPageTurnAnimationDuration;
5161
+ const pageTurnAnimation = currentEvent.animation === `snap` ? `slide` : settings.settings.computedPageTurnAnimation;
5397
5162
  return of(currentEvent).pipe(
5398
5163
  /**
5399
5164
  * @important
@@ -5427,23 +5192,22 @@ const createViewportNavigator = ({
5427
5192
  * need to adjust to anchor to the payload position. This is because we use viewport computed position,
5428
5193
  * not the value set by `setProperty`
5429
5194
  */
5430
- withLatestFrom(hooks$),
5431
- tap(([data, hooks]) => {
5195
+ tap((data) => {
5432
5196
  if (pageTurnAnimation !== `fade`) {
5433
- adjustReadingOffset(data.position, hooks);
5197
+ adjustReadingOffset(data.position);
5434
5198
  }
5435
5199
  }),
5436
5200
  currentEvent.shouldAnimate ? delay(animationDuration / 2, animationFrameScheduler) : identity,
5437
- tap(([data, hooks]) => {
5201
+ tap((data) => {
5438
5202
  if (pageTurnAnimation === `fade`) {
5439
- adjustReadingOffset(data.position, hooks);
5203
+ adjustReadingOffset(data.position);
5440
5204
  element$.getValue().style.setProperty(`opacity`, `1`);
5441
5205
  }
5442
5206
  }),
5443
5207
  currentEvent.shouldAnimate ? delay(animationDuration / 2, animationFrameScheduler) : identity,
5444
- tap(([data, hooks]) => {
5208
+ tap((data) => {
5445
5209
  if (pageTurnAnimation === `fade`) {
5446
- adjustReadingOffset(data.position, hooks);
5210
+ adjustReadingOffset(data.position);
5447
5211
  }
5448
5212
  }),
5449
5213
  takeUntil$1(
@@ -5455,7 +5219,7 @@ const createViewportNavigator = ({
5455
5219
  );
5456
5220
  }),
5457
5221
  share(),
5458
- takeUntil$1(context.$.destroy$)
5222
+ takeUntil$1(context.destroy$)
5459
5223
  );
5460
5224
  const adjustmentState$ = merge(
5461
5225
  merge(manualAdjust$).pipe(map$1(() => `start`)),
@@ -5500,8 +5264,7 @@ const createViewportNavigator = ({
5500
5264
  () => waitForViewportFree$.pipe(
5501
5265
  switchMap$1(() => {
5502
5266
  const focusedSpineItem = spineItemManager.getFocusedSpineItem();
5503
- if (!focusedSpineItem)
5504
- return EMPTY;
5267
+ if (!focusedSpineItem) return EMPTY;
5505
5268
  return adjustNavigation(focusedSpineItem);
5506
5269
  }),
5507
5270
  takeUntil$1(navigation$)
@@ -5510,7 +5273,7 @@ const createViewportNavigator = ({
5510
5273
  share()
5511
5274
  );
5512
5275
  const parentElementSub = parentElement$.pipe(filter(isDefined), withLatestFrom(spine.element$)).subscribe(([parentElement, spineElement]) => {
5513
- const element = createElement(parentElement.ownerDocument, hooks$);
5276
+ const element = createElement(parentElement.ownerDocument, hookManager);
5514
5277
  element.appendChild(spineElement);
5515
5278
  parentElement.appendChild(element);
5516
5279
  element$.next(element);
@@ -5546,19 +5309,15 @@ const createViewportNavigator = ({
5546
5309
  }
5547
5310
  };
5548
5311
  };
5549
- const createElement = (doc, hooks$) => {
5312
+ const createElement = (doc, hookManager) => {
5550
5313
  const element = doc.createElement(`div`);
5551
5314
  element.style.cssText = `
5552
5315
  height: 100%;
5553
5316
  position: relative;
5554
5317
  `;
5555
5318
  element.className = `${HTML_PREFIX$1}-viewport-navigator`;
5556
- return hooks$.getValue().reduce((element2, hook) => {
5557
- if (hook.name === `viewportNavigator.onBeforeContainerCreated`) {
5558
- return hook.fn(element2);
5559
- }
5560
- return element2;
5561
- }, element);
5319
+ hookManager.execute("viewportNavigator.onBeforeContainerCreated", void 0, { element });
5320
+ return element;
5562
5321
  };
5563
5322
  const createLocationResolver = ({
5564
5323
  spineItemManager,
@@ -5599,7 +5358,7 @@ const createLocationResolver = ({
5599
5358
  const spineItem = spineItemManager.getAll().find((item) => {
5600
5359
  const { left, right, bottom, top } = spineItemManager.getAbsolutePositionOf(item);
5601
5360
  const isWithinXAxis = position.x >= left && position.x < right;
5602
- if (settings.getSettings().computedPageTurnDirection === `horizontal`) {
5361
+ if (settings.settings.computedPageTurnDirection === `horizontal`) {
5603
5362
  return isWithinXAxis;
5604
5363
  } else {
5605
5364
  return isWithinXAxis && position.y >= top && position.y < bottom;
@@ -5623,13 +5382,14 @@ const createLocationResolver = ({
5623
5382
  const getSpineItemsFromReadingOrderPosition = (position) => {
5624
5383
  const itemAtPosition = getSpineItemFromPosition(position) || spineItemManager.getFocusedSpineItem();
5625
5384
  const itemAtPositionIndex = spineItemManager.getSpineItemIndex(itemAtPosition);
5626
- if (itemAtPositionIndex === void 0)
5627
- return void 0;
5385
+ if (itemAtPositionIndex === void 0) return void 0;
5628
5386
  let endPosition = position;
5629
- if (context.isUsingSpreadMode()) {
5387
+ if (context.state.isUsingSpreadMode) {
5630
5388
  endPosition = { x: position.x + context.getPageSize().width, y: position.y };
5631
5389
  }
5632
- const endItemIndex = spineItemManager.getSpineItemIndex(getSpineItemFromPosition(endPosition) || spineItemManager.getFocusedSpineItem()) ?? itemAtPositionIndex;
5390
+ const endItemIndex = spineItemManager.getSpineItemIndex(
5391
+ getSpineItemFromPosition(endPosition) || spineItemManager.getFocusedSpineItem()
5392
+ ) ?? itemAtPositionIndex;
5633
5393
  const items = [
5634
5394
  { item: itemAtPositionIndex, position },
5635
5395
  { item: endItemIndex, position: endPosition }
@@ -5709,12 +5469,10 @@ const createCfiLocator = ({
5709
5469
  };
5710
5470
  const resolveCfi = (cfiString) => {
5711
5471
  var _a, _b, _c;
5712
- if (!cfiString)
5713
- return void 0;
5472
+ if (!cfiString) return void 0;
5714
5473
  const spineItem = getSpineItemFromCfi(cfiString);
5715
5474
  const spineItemIndex = spineItemManager.getSpineItemIndex(spineItem) || 0;
5716
- if (!spineItem)
5717
- return void 0;
5475
+ if (!spineItem) return void 0;
5718
5476
  const { cleanedCfi, offset } = extractProseMetadataFromCfi(cfiString);
5719
5477
  const cfi = new CFI(cleanedCfi, {});
5720
5478
  const doc = (_c = (_b = (_a = spineItem.spineItemFrame.getManipulableFrame()) == null ? void 0 : _a.frame) == null ? void 0 : _b.contentWindow) == null ? void 0 : _c.document;
@@ -5747,80 +5505,164 @@ const createCfiLocator = ({
5747
5505
  generateFromRange
5748
5506
  };
5749
5507
  };
5750
- const areAllItemsPrePaginated = (manifest) => !(manifest == null ? void 0 : manifest.spineItems.some((item) => item.renditionLayout === `reflowable`));
5751
- const createSettings = (initialSettings) => {
5752
- const mergedSettings = {
5753
- forceSinglePageMode: false,
5754
- pageTurnAnimation: `none`,
5755
- computedPageTurnAnimation: `none`,
5756
- pageTurnDirection: `horizontal`,
5757
- computedPageTurnDirection: `horizontal`,
5758
- pageTurnAnimationDuration: void 0,
5759
- computedPageTurnAnimationDuration: 0,
5760
- pageTurnMode: `controlled`,
5508
+ const getComputedSettings = (settings, context) => {
5509
+ const manifest = context.manifest;
5510
+ const hasVerticalWriting = context.state.hasVerticalWriting ?? false;
5511
+ const computedSettings = {
5512
+ computedPageTurnDirection: settings.pageTurnDirection,
5513
+ computedPageTurnAnimation: settings.pageTurnAnimation,
5761
5514
  computedPageTurnMode: `controlled`,
5762
- computedSnapAnimationDuration: 300,
5763
- navigationSnapThreshold: 0.3,
5764
- numberOfAdjacentSpineItemToPreLoad: 0,
5765
- ...initialSettings
5766
- };
5767
- updateComputedSettings(void 0, mergedSettings, false);
5768
- const settingsSubject$ = new BehaviorSubject(mergedSettings);
5769
- const setSettings = (newSettings, options) => {
5770
- if (Object.keys(newSettings).length === 0)
5771
- return;
5772
- const newMergedSettings = { ...settingsSubject$.value, ...newSettings };
5773
- updateComputedSettings(options.manifest, newMergedSettings, options.hasVerticalWriting ?? false);
5774
- settingsSubject$.next(newMergedSettings);
5775
- };
5776
- const recompute = (options) => {
5777
- const newMergedSettings = { ...settingsSubject$.value };
5778
- updateComputedSettings(options.manifest, newMergedSettings, options.hasVerticalWriting ?? false);
5779
- settingsSubject$.next(newMergedSettings);
5780
- };
5781
- const destroy = () => {
5782
- settingsSubject$.complete();
5783
- };
5784
- return {
5785
- getSettings: () => settingsSubject$.value,
5786
- setSettings,
5787
- recompute,
5788
- destroy,
5789
- $: {
5790
- settings$: settingsSubject$.asObservable().pipe(distinctUntilChanged(isShallowEqual))
5791
- }
5515
+ computedPageTurnAnimationDuration: 0,
5516
+ computedSnapAnimationDuration: 0
5792
5517
  };
5793
- };
5794
- const updateComputedSettings = (newManifest, settings, hasVerticalWriting) => {
5795
- settings.computedPageTurnDirection = settings.pageTurnDirection;
5796
- settings.computedPageTurnAnimation = settings.pageTurnAnimation;
5797
- settings.computedPageTurnMode = `controlled`;
5798
- if ((newManifest == null ? void 0 : newManifest.renditionFlow) === `scrolled-continuous`) {
5799
- settings.computedPageTurnMode = `scrollable`;
5800
- settings.computedPageTurnDirection = `vertical`;
5801
- } else if (newManifest && settings.pageTurnMode === `scrollable` && (newManifest.renditionLayout !== `pre-paginated` || !areAllItemsPrePaginated(newManifest))) {
5518
+ if ((manifest == null ? void 0 : manifest.renditionFlow) === `scrolled-continuous`) {
5519
+ computedSettings.computedPageTurnMode = `scrollable`;
5520
+ computedSettings.computedPageTurnDirection = `vertical`;
5521
+ } else if (manifest && settings.pageTurnMode === `scrollable` && (manifest.renditionLayout !== `pre-paginated` || !areAllItemsPrePaginated(manifest))) {
5802
5522
  Report.warn(`pageTurnMode ${settings.pageTurnMode} incompatible with current book, switching back to default`);
5803
- settings.computedPageTurnAnimation = `none`;
5804
- settings.computedPageTurnMode = `controlled`;
5523
+ computedSettings.computedPageTurnAnimation = `none`;
5524
+ computedSettings.computedPageTurnMode = `controlled`;
5805
5525
  } else if (settings.pageTurnMode === `scrollable`) {
5806
- settings.computedPageTurnMode = `scrollable`;
5807
- settings.computedPageTurnDirection = `vertical`;
5526
+ computedSettings.computedPageTurnMode = `scrollable`;
5527
+ computedSettings.computedPageTurnDirection = `vertical`;
5808
5528
  }
5809
- if (hasVerticalWriting && settings.computedPageTurnAnimation === `slide`) {
5529
+ if (hasVerticalWriting && computedSettings.computedPageTurnAnimation === `slide`) {
5810
5530
  Report.warn(
5811
- `pageTurnAnimation ${settings.computedPageTurnAnimation} incompatible with current book, switching back to default`
5531
+ `pageTurnAnimation ${computedSettings.computedPageTurnAnimation} incompatible with current book, switching back to default`
5812
5532
  );
5813
- settings.computedPageTurnAnimation = `none`;
5533
+ computedSettings.computedPageTurnAnimation = `none`;
5814
5534
  }
5815
- if (settings.computedPageTurnMode === `scrollable`) {
5816
- settings.computedPageTurnAnimationDuration = 0;
5817
- settings.computedPageTurnAnimation = `none`;
5535
+ if (computedSettings.computedPageTurnMode === `scrollable`) {
5536
+ computedSettings.computedPageTurnAnimationDuration = 0;
5537
+ computedSettings.computedPageTurnAnimation = `none`;
5818
5538
  } else {
5819
- settings.computedPageTurnAnimationDuration = settings.pageTurnAnimationDuration !== void 0 ? settings.pageTurnAnimationDuration : 300;
5539
+ computedSettings.computedPageTurnAnimationDuration = settings.pageTurnAnimationDuration !== void 0 ? settings.pageTurnAnimationDuration : 300;
5820
5540
  }
5541
+ return computedSettings;
5821
5542
  };
5822
- const IFRAME_EVENT_BRIDGE_ELEMENT_ID = `proseReaderIframeEventBridgeElement`;
5823
- const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5543
+ const defaultSettings = {
5544
+ forceSinglePageMode: false,
5545
+ pageTurnAnimation: `none`,
5546
+ // computedPageTurnAnimation: `none`,
5547
+ pageTurnDirection: `horizontal`,
5548
+ // computedPageTurnDirection: `horizontal`,
5549
+ pageTurnAnimationDuration: void 0,
5550
+ // computedPageTurnAnimationDuration: 0,
5551
+ pageTurnMode: `controlled`,
5552
+ // computedPageTurnMode: `controlled`,
5553
+ // computedSnapAnimationDuration: 300,
5554
+ navigationSnapThreshold: 0.3,
5555
+ numberOfAdjacentSpineItemToPreLoad: 0
5556
+ };
5557
+ class SettingsManager {
5558
+ constructor(initialSettings, context) {
5559
+ this._context = context;
5560
+ const settingsWithDefaults = {
5561
+ ...defaultSettings,
5562
+ ...initialSettings
5563
+ };
5564
+ const computedSettings = getComputedSettings(settingsWithDefaults, context);
5565
+ const settings = { ...settingsWithDefaults, ...computedSettings };
5566
+ this._settingsSubject$ = new BehaviorSubject(settings);
5567
+ this.settings$ = this._settingsSubject$.asObservable().pipe(distinctUntilChanged(isShallowEqual));
5568
+ const recomputeSettingsOnContextChange$ = combineLatest([context.hasVerticalWriting$, context.manifest$]).pipe(
5569
+ tap(() => {
5570
+ this._updateSettings(this.settings);
5571
+ })
5572
+ );
5573
+ const updateContextOnSettingsChanges$ = this._settingsSubject$.pipe(
5574
+ tap(({ forceSinglePageMode }) => {
5575
+ context.update({ forceSinglePageMode });
5576
+ })
5577
+ );
5578
+ merge(recomputeSettingsOnContextChange$, updateContextOnSettingsChanges$).pipe(takeUntil$1(context.destroy$)).subscribe();
5579
+ }
5580
+ // @see https://github.com/microsoft/TypeScript/issues/17293
5581
+ _updateSettings(settings) {
5582
+ const computed = getComputedSettings(settings, this._context);
5583
+ const newMergedSettings = { ...settings, ...computed };
5584
+ this._settingsSubject$.next(newMergedSettings);
5585
+ }
5586
+ setSettings(settings) {
5587
+ if (Object.keys(settings).length === 0) return;
5588
+ const newMergedSettings = { ...this._settingsSubject$.value, ...settings };
5589
+ this._updateSettings(newMergedSettings);
5590
+ }
5591
+ get settings() {
5592
+ return this._settingsSubject$.getValue();
5593
+ }
5594
+ destroy() {
5595
+ this._settingsSubject$.complete();
5596
+ }
5597
+ }
5598
+ class HookManager {
5599
+ constructor() {
5600
+ this._hooks = [];
5601
+ this._hookExecutions = [];
5602
+ }
5603
+ /**
5604
+ * Will:
5605
+ * - call destroy function for every execution of this specific hook
5606
+ * - remove the hook for further calls
5607
+ */
5608
+ deregister(hookToDeregister) {
5609
+ this._hooks = this._hooks.filter((hook) => hook !== hookToDeregister);
5610
+ return this.destroy(hookToDeregister.name, void 0, hookToDeregister);
5611
+ }
5612
+ /**
5613
+ * Ideal when your logic only needs to apply something to the item when it's loaded.
5614
+ * You can manipulate your item later if you need to update it and trigger a layout.
5615
+ * This logic will not run every time there is a layout.
5616
+ */
5617
+ register(name, fn) {
5618
+ const hook = {
5619
+ name,
5620
+ runFn: fn
5621
+ };
5622
+ this._hooks.push(hook);
5623
+ return () => {
5624
+ this.deregister(hook);
5625
+ };
5626
+ }
5627
+ execute(name, id, params) {
5628
+ const hooks = this._hooks.filter((hook) => name === hook.name);
5629
+ const fnResults = hooks.map((hook) => {
5630
+ let userDestroyFn = () => of(void 0);
5631
+ const destroySubject = new Subject();
5632
+ const destroy = (fn) => {
5633
+ userDestroyFn = fn;
5634
+ };
5635
+ const destroyFn = () => {
5636
+ destroySubject.next();
5637
+ destroySubject.complete();
5638
+ const result = userDestroyFn();
5639
+ return result ?? of(void 0);
5640
+ };
5641
+ const fnResult = hook.runFn({ ...params, destroy$: destroySubject.asObservable(), destroy });
5642
+ this._hookExecutions.push({
5643
+ name,
5644
+ id,
5645
+ destroyFn,
5646
+ ref: hook
5647
+ });
5648
+ return fnResult;
5649
+ });
5650
+ return fnResults;
5651
+ }
5652
+ destroy(name, id, ref) {
5653
+ const instances = this._hookExecutions.filter(
5654
+ (hookInstance) => (
5655
+ // by ref is higher priority
5656
+ ref && hookInstance.ref === ref || // otherwise we refine by name and eventually by id
5657
+ name === hookInstance.name && (!id || id && id === hookInstance.id)
5658
+ )
5659
+ );
5660
+ this._hookExecutions = this._hookExecutions.filter((instance) => !instances.includes(instance));
5661
+ const destroyFns = instances.map(({ destroyFn }) => destroyFn());
5662
+ return combineLatest(destroyFns);
5663
+ }
5664
+ }
5665
+ const createReader = (inputSettings) => {
5824
5666
  const stateSubject$ = new BehaviorSubject({
5825
5667
  supportedPageTurnAnimation: [`fade`, `none`, `slide`],
5826
5668
  supportedPageTurnMode: [`controlled`, `scrollable`],
@@ -5829,24 +5671,23 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5829
5671
  });
5830
5672
  const destroy$ = new Subject();
5831
5673
  const selectionSubject$ = new Subject();
5832
- const hooksSubject$ = new BehaviorSubject(initialHooks || []);
5833
5674
  const navigationSubject = new Subject();
5834
5675
  const navigationAdjustedSubject = new Subject();
5835
5676
  const currentNavigationPositionSubject$ = new BehaviorSubject({ x: 0, y: 0 });
5836
5677
  const viewportStateSubject = new BehaviorSubject(`free`);
5837
- const settings = createSettings(inputSettings);
5838
- const context = createContext(settings);
5839
- const spineItemManager = createSpineItemManager({ context, settings });
5678
+ const hookManager = new HookManager();
5679
+ const context = new Context();
5680
+ const settingsManager = new SettingsManager(inputSettings, context);
5681
+ const spineItemManager = createSpineItemManager({ context, settings: settingsManager });
5840
5682
  const pagination = createPagination({ context, spineItemManager });
5841
5683
  const elementSubject$ = new BehaviorSubject(void 0);
5842
5684
  const element$ = elementSubject$.pipe(filter(isDefined));
5843
- const iframeEventBridgeElement$ = new BehaviorSubject(void 0);
5844
5685
  const spineItemLocator = createLocationResolver$1({ context });
5845
5686
  const spineLocator = createLocationResolver({
5846
5687
  context,
5847
5688
  spineItemManager,
5848
5689
  spineItemLocator,
5849
- settings
5690
+ settings: settingsManager
5850
5691
  });
5851
5692
  const cfiLocator = createCfiLocator({
5852
5693
  spineItemManager,
@@ -5856,19 +5697,18 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5856
5697
  const navigation$ = navigationSubject.asObservable();
5857
5698
  const spine = createSpine({
5858
5699
  element$,
5859
- iframeEventBridgeElement$,
5860
5700
  context,
5861
- settings,
5701
+ settings: settingsManager,
5862
5702
  pagination,
5863
5703
  spineItemManager,
5864
- hooks$: hooksSubject$,
5865
5704
  navigation$,
5866
5705
  spineLocator,
5867
5706
  spineItemLocator,
5868
5707
  cfiLocator,
5869
5708
  navigationAdjusted$: navigationAdjustedSubject.asObservable(),
5870
5709
  viewportState$: viewportStateSubject.asObservable(),
5871
- currentNavigationPosition$: currentNavigationPositionSubject$.asObservable()
5710
+ currentNavigationPosition$: currentNavigationPositionSubject$.asObservable(),
5711
+ hookManager
5872
5712
  });
5873
5713
  const viewportNavigator = createViewportNavigator({
5874
5714
  context,
@@ -5877,9 +5717,9 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5877
5717
  parentElement$: elementSubject$,
5878
5718
  cfiLocator,
5879
5719
  spineLocator,
5880
- hooks$: hooksSubject$,
5720
+ hookManager,
5881
5721
  spine,
5882
- settings
5722
+ settings: settingsManager
5883
5723
  });
5884
5724
  viewportNavigator.$.state$.subscribe(viewportStateSubject);
5885
5725
  viewportNavigator.$.navigation$.subscribe(navigationSubject);
@@ -5889,8 +5729,7 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5889
5729
  var _a;
5890
5730
  const containerElement = (_a = elementSubject$.getValue()) == null ? void 0 : _a.parentElement;
5891
5731
  const element = elementSubject$.getValue();
5892
- if (!element || !containerElement)
5893
- throw new Error("Invalid element");
5732
+ if (!element || !containerElement) throw new Error("Invalid element");
5894
5733
  const dimensions = {
5895
5734
  width: containerElement == null ? void 0 : containerElement.offsetWidth,
5896
5735
  height: containerElement == null ? void 0 : containerElement.offsetHeight
@@ -5905,30 +5744,29 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5905
5744
  element.style.height = `${dimensions.height - marginTop - marginBottom}px`;
5906
5745
  element.style.width = `${containerElementEvenWidth - 2 * margin}px`;
5907
5746
  const elementRect = element.getBoundingClientRect();
5908
- context.setVisibleAreaRect({
5909
- x: elementRect.x,
5910
- y: elementRect.y,
5911
- width: containerElementEvenWidth,
5912
- height: dimensions.height
5747
+ context.update({
5748
+ visibleAreaRect: {
5749
+ x: elementRect.x,
5750
+ y: elementRect.y,
5751
+ width: containerElementEvenWidth,
5752
+ height: dimensions.height
5753
+ }
5913
5754
  });
5914
5755
  viewportNavigator.layout();
5915
5756
  };
5916
5757
  const load = (manifest, loadOptions) => {
5917
5758
  var _a;
5918
- if (context.getManifest()) {
5759
+ if (context.manifest) {
5919
5760
  Report.warn(`loading a new book is not supported yet`);
5920
5761
  return;
5921
5762
  }
5922
5763
  Report.log(`load`, { manifest, loadOptions });
5923
5764
  const element = createWrapperElement(loadOptions.containerElement);
5924
- const iframeEventBridgeElement = createIframeEventBridgeElement(loadOptions.containerElement);
5925
5765
  if (loadOptions.containerElement !== ((_a = elementSubject$.getValue()) == null ? void 0 : _a.parentElement)) {
5926
5766
  elementSubject$.next(element);
5927
- iframeEventBridgeElement$.next(iframeEventBridgeElement);
5928
5767
  loadOptions.containerElement.appendChild(element);
5929
- element.appendChild(iframeEventBridgeElement);
5930
5768
  }
5931
- context.load(manifest, loadOptions);
5769
+ context.update({ manifest, ...loadOptions, forceSinglePageMode: settingsManager.settings.forceSinglePageMode });
5932
5770
  layout();
5933
5771
  if (!loadOptions.cfi) {
5934
5772
  viewportNavigator.goToSpineItem(0, { animate: false });
@@ -5936,9 +5774,6 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5936
5774
  viewportNavigator.goToCfi(loadOptions.cfi, { animate: false });
5937
5775
  }
5938
5776
  };
5939
- const registerHook = (name, fn) => {
5940
- hooksSubject$.next([...hooksSubject$.getValue(), { name, fn }]);
5941
- };
5942
5777
  spine.$.$.pipe(
5943
5778
  tap((event) => {
5944
5779
  if (event.type === `onSelectionChange`) {
@@ -5951,26 +5786,31 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5951
5786
  switchMap(({ adjustedSpinePosition }) => {
5952
5787
  return spine.adjustPagination(adjustedSpinePosition).pipe(takeUntil$1(navigation$));
5953
5788
  }),
5954
- takeUntil$1(context.$.destroy$)
5789
+ takeUntil$1(context.destroy$)
5955
5790
  ).subscribe();
5956
- merge(context.$.state$, settings.$.settings$).pipe(
5791
+ merge(context.state$, settingsManager.settings$).pipe(
5957
5792
  map$1(() => void 0),
5958
- withLatestFrom(context.$.state$),
5793
+ withLatestFrom(context.state$),
5959
5794
  map$1(([, { hasVerticalWriting }]) => {
5960
- const manifest = context.getManifest();
5795
+ const manifest = context.manifest;
5961
5796
  return {
5962
5797
  hasVerticalWriting,
5963
5798
  renditionFlow: manifest == null ? void 0 : manifest.renditionFlow,
5964
5799
  renditionLayout: manifest == null ? void 0 : manifest.renditionLayout,
5965
- computedPageTurnMode: settings.getSettings().computedPageTurnMode
5800
+ computedPageTurnMode: settingsManager.settings.computedPageTurnMode
5966
5801
  };
5967
5802
  }),
5968
5803
  distinctUntilChanged(isShallowEqual),
5969
5804
  map$1(
5970
- ({ hasVerticalWriting, renditionFlow, renditionLayout, computedPageTurnMode }) => {
5805
+ ({
5806
+ hasVerticalWriting,
5807
+ renditionFlow,
5808
+ renditionLayout,
5809
+ computedPageTurnMode
5810
+ }) => {
5971
5811
  return {
5972
5812
  ...stateSubject$.value,
5973
- supportedPageTurnMode: renditionFlow === `scrolled-continuous` ? [`scrollable`] : !context.areAllItemsPrePaginated() ? [`controlled`] : [`controlled`, `scrollable`],
5813
+ supportedPageTurnMode: renditionFlow === `scrolled-continuous` ? [`scrollable`] : !context.state.areAllItemsPrePaginated ? [`controlled`] : [`controlled`, `scrollable`],
5974
5814
  supportedPageTurnAnimation: renditionFlow === `scrolled-continuous` || computedPageTurnMode === `scrollable` ? [`none`] : hasVerticalWriting ? [`fade`, `none`] : [`fade`, `none`, `slide`],
5975
5815
  supportedPageTurnDirection: computedPageTurnMode === `scrollable` ? [`vertical`] : renditionLayout === `reflowable` ? [`horizontal`] : [`horizontal`, `vertical`]
5976
5816
  };
@@ -5979,16 +5819,13 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5979
5819
  takeUntil$1(destroy$)
5980
5820
  ).subscribe(stateSubject$);
5981
5821
  const destroy = () => {
5982
- var _a, _b;
5983
- settings.destroy();
5984
- hooksSubject$.next([]);
5985
- hooksSubject$.complete();
5822
+ var _a;
5823
+ settingsManager.destroy();
5986
5824
  pagination.destroy();
5987
5825
  context.destroy();
5988
5826
  viewportNavigator.destroy();
5989
5827
  spine.destroy();
5990
5828
  (_a = elementSubject$.getValue()) == null ? void 0 : _a.remove();
5991
- (_b = iframeEventBridgeElement$.getValue()) == null ? void 0 : _b.remove();
5992
5829
  stateSubject$.complete();
5993
5830
  selectionSubject$.complete();
5994
5831
  destroy$.next();
@@ -5996,43 +5833,16 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5996
5833
  };
5997
5834
  const reader = {
5998
5835
  context,
5999
- registerHook,
6000
5836
  spine,
5837
+ hookManager,
6001
5838
  viewportNavigator,
6002
- manipulateSpineItems: spine.manipulateSpineItems,
6003
- manipulateSpineItem: spine.manipulateSpineItem,
6004
- moveTo: viewportNavigator.moveTo,
6005
- turnLeft: viewportNavigator.turnLeft,
6006
- turnRight: viewportNavigator.turnRight,
6007
- goToPageOfCurrentChapter: viewportNavigator.goToPageOfCurrentChapter,
6008
- goToPage: viewportNavigator.goToPage,
6009
- goToUrl: viewportNavigator.goToUrl,
6010
- goToCfi: viewportNavigator.goToCfi,
6011
- goToSpineItem: viewportNavigator.goToSpineItem,
6012
- getFocusedSpineItemIndex: spineItemManager.getFocusedSpineItemIndex,
6013
- getSpineItem: spineItemManager.get,
6014
- getSpineItems: spineItemManager.getAll,
6015
- getAbsolutePositionOf: spineItemManager.getAbsolutePositionOf,
6016
- getSelection: spine.getSelection,
6017
- isSelecting: spine.isSelecting,
6018
- normalizeEventForViewport: spine.normalizeEventForViewport,
6019
- getCfiMetaInformation: spine.cfiLocator.getCfiMetaInformation,
6020
- resolveCfi: spine.cfiLocator.resolveCfi,
6021
- generateCfi: spine.cfiLocator.generateFromRange,
6022
- locator: spine.locator,
6023
- getCurrentNavigationPosition: viewportNavigator.getCurrentNavigationPosition,
6024
- getCurrentViewportPosition: viewportNavigator.getCurrentViewportPosition,
5839
+ spineItemManager,
6025
5840
  layout,
6026
5841
  load,
6027
5842
  destroy,
6028
- spineItems$: spine.$.spineItems$,
6029
- context$: context.$.state$,
6030
5843
  pagination,
6031
- settings: {
6032
- settings$: settings.$.settings$,
6033
- getSettings: settings.getSettings,
6034
- setSettings: (data) => settings.setSettings(data, context.getState())
6035
- },
5844
+ settings: settingsManager,
5845
+ element$,
6036
5846
  $: {
6037
5847
  state$: stateSubject$.asObservable(),
6038
5848
  /**
@@ -6041,21 +5851,12 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
6041
5851
  * have an effect.
6042
5852
  * It can typically be used to hide a loading indicator.
6043
5853
  */
6044
- loadStatus$: context.$.manifest$.pipe(map$1((manifest) => manifest ? "ready" : "idle")),
5854
+ loadStatus$: context.manifest$.pipe(map$1((manifest) => manifest ? "ready" : "idle")),
6045
5855
  /**
6046
5856
  * Dispatched when a change in selection happens
6047
5857
  */
6048
5858
  selection$: selectionSubject$.asObservable(),
6049
- viewportState$: viewportNavigator.$.state$,
6050
- layout$: spine.$.layout$,
6051
- itemsBeforeDestroy$: spine.$.itemsBeforeDestroy$,
6052
- itemIsReady$: spineItemManager.$.itemIsReady$,
6053
5859
  destroy$
6054
- },
6055
- __debug: {
6056
- pagination,
6057
- context,
6058
- spineItemManager
6059
5860
  }
6060
5861
  };
6061
5862
  return reader;
@@ -6069,19 +5870,6 @@ const createWrapperElement = (containerElement) => {
6069
5870
  element.className = `${HTML_PREFIX$1}-reader`;
6070
5871
  return element;
6071
5872
  };
6072
- const createIframeEventBridgeElement = (containerElement) => {
6073
- const iframeEventBridgeElement = containerElement.ownerDocument.createElement(`div`);
6074
- iframeEventBridgeElement.id = IFRAME_EVENT_BRIDGE_ELEMENT_ID;
6075
- iframeEventBridgeElement.style.cssText = `
6076
- position: absolute;
6077
- height: 100%;
6078
- width: 100%;
6079
- top: 0;
6080
- left: 0;
6081
- z-index: -1;
6082
- `;
6083
- return iframeEventBridgeElement;
6084
- };
6085
5873
  const utilsEnhancer = (next) => (options) => {
6086
5874
  const reader = next(options);
6087
5875
  const isOrIsWithinValidLink = (target) => {
@@ -6206,15 +5994,14 @@ const createResourcesManager = (context) => {
6206
5994
  var _a, _b;
6207
5995
  if (typeof itemIndexOrId === `string` || typeof itemIndexOrId === `object`) {
6208
5996
  const id = typeof itemIndexOrId === `object` ? itemIndexOrId.id : void 0;
6209
- return (_a = context.getManifest()) == null ? void 0 : _a.spineItems.find((entry) => entry.id === id);
5997
+ return (_a = context.manifest) == null ? void 0 : _a.spineItems.find((entry) => entry.id === id);
6210
5998
  } else {
6211
- return (_b = context.getManifest()) == null ? void 0 : _b.spineItems[itemIndexOrId];
5999
+ return (_b = context.manifest) == null ? void 0 : _b.spineItems[itemIndexOrId];
6212
6000
  }
6213
6001
  };
6214
6002
  const get = async (itemIndexOrId, fetchResource) => {
6215
6003
  const item = retrieveItem(itemIndexOrId);
6216
- if (!item)
6217
- return new Response(`Item not found`, { status: 404 });
6004
+ if (!item) return new Response(`Item not found`, { status: 404 });
6218
6005
  const db = await openDatabase(`prose-reader`);
6219
6006
  const cacheData = await db.get(`${uniqueID}_${item.id}`);
6220
6007
  if (cacheData) {
@@ -6230,8 +6017,7 @@ const createResourcesManager = (context) => {
6230
6017
  cache$.asObservable().pipe(
6231
6018
  mergeMap(({ id, data }) => {
6232
6019
  const item = retrieveItem(id);
6233
- if (!item)
6234
- return EMPTY;
6020
+ if (!item) return EMPTY;
6235
6021
  return from(forkJoin([openDatabase(`prose-reader`), from(data.blob())])).pipe(
6236
6022
  switchMap$1(([db, blob]) => {
6237
6023
  return from(db.put(`${uniqueID}_${item.id}`, blob));
@@ -6242,9 +6028,9 @@ const createResourcesManager = (context) => {
6242
6028
  })
6243
6029
  );
6244
6030
  }),
6245
- takeUntil$1(context.$.destroy$)
6031
+ takeUntil$1(context.destroy$)
6246
6032
  ).subscribe();
6247
- const onLoad$ = context.$.manifest$.pipe(
6033
+ const onLoad$ = context.manifest$.pipe(
6248
6034
  tap(() => {
6249
6035
  uniqueID = Date.now().toString();
6250
6036
  })
@@ -6268,7 +6054,7 @@ const createResourcesManager = (context) => {
6268
6054
  })
6269
6055
  );
6270
6056
  }),
6271
- takeUntil$1(context.$.destroy$)
6057
+ takeUntil$1(context.destroy$)
6272
6058
  ).subscribe();
6273
6059
  const destroy = () => {
6274
6060
  cache$.complete();
@@ -6281,14 +6067,6 @@ const createResourcesManager = (context) => {
6281
6067
  const resourcesEnhancer = (next) => (options) => {
6282
6068
  const reader = next(options);
6283
6069
  const resourceManager = createResourcesManager(reader.context);
6284
- const load = (manifest, loadOptions) => {
6285
- reader.load(manifest, {
6286
- ...loadOptions
6287
- });
6288
- };
6289
- reader.registerHook(`item.onGetResource`, (fetcher) => async (item) => {
6290
- return resourceManager.get(item, fetcher);
6291
- });
6292
6070
  const destroy = () => {
6293
6071
  resourceManager.destroy();
6294
6072
  reader.destroy();
@@ -6299,8 +6077,8 @@ const resourcesEnhancer = (next) => (options) => {
6299
6077
  // ...reader.$,
6300
6078
  // errors$: merge(reader.$.errors$, errorsSubject$.asObservable())
6301
6079
  // },
6302
- destroy,
6303
- load
6080
+ destroy
6081
+ // load,
6304
6082
  };
6305
6083
  };
6306
6084
  const mediaEnhancer = (next) => (options) => {
@@ -6351,7 +6129,7 @@ const mediaEnhancer = (next) => (options) => {
6351
6129
  threshold: 0.5
6352
6130
  }
6353
6131
  );
6354
- reader.registerHook(`item.onLoad`, ({ frame }) => {
6132
+ reader.hookManager.register(`item.onLoad`, ({ frame, destroy: destroy2 }) => {
6355
6133
  var _a;
6356
6134
  frameObserver.observe(frame);
6357
6135
  const videos = (_a = frame.contentDocument) == null ? void 0 : _a.body.getElementsByTagName(`video`);
@@ -6359,10 +6137,10 @@ const mediaEnhancer = (next) => (options) => {
6359
6137
  elementObserver.observe(element);
6360
6138
  return () => elementObserver.unobserve(element);
6361
6139
  });
6362
- return () => {
6140
+ destroy2(() => {
6363
6141
  frameObserver.unobserve(frame);
6364
6142
  unobserveElements.forEach((unobserve) => unobserve());
6365
- };
6143
+ });
6366
6144
  });
6367
6145
  const destroy = () => {
6368
6146
  frameObserver.disconnect();
@@ -6378,22 +6156,26 @@ const progressionEnhancer = (next) => (options) => {
6378
6156
  const reader = next(options);
6379
6157
  const getPercentageEstimate = (context, currentSpineIndex, numberOfPages, pageIndex, currentPosition, currentItem) => {
6380
6158
  var _a, _b, _c, _d, _e, _f;
6381
- const isGloballyPrePaginated = ((_a = context.getManifest()) == null ? void 0 : _a.renditionLayout) === `pre-paginated`;
6382
- const readingOrderLength = ((_b = context.getManifest()) == null ? void 0 : _b.spineItems.length) || 0;
6383
- const estimateBeforeThisItem = ((_c = context.getManifest()) == null ? void 0 : _c.spineItems.slice(0, currentSpineIndex).reduce((acc, item) => acc + item.progressionWeight, 0)) || 0;
6384
- const currentItemWeight = ((_e = (_d = context.getManifest()) == null ? void 0 : _d.spineItems[currentSpineIndex]) == null ? void 0 : _e.progressionWeight) || 0;
6159
+ const isGloballyPrePaginated = ((_a = context.manifest) == null ? void 0 : _a.renditionLayout) === `pre-paginated`;
6160
+ const readingOrderLength = ((_b = context.manifest) == null ? void 0 : _b.spineItems.length) || 0;
6161
+ const estimateBeforeThisItem = ((_c = context.manifest) == null ? void 0 : _c.spineItems.slice(0, currentSpineIndex).reduce((acc, item) => acc + item.progressionWeight, 0)) || 0;
6162
+ const currentItemWeight = ((_e = (_d = context.manifest) == null ? void 0 : _d.spineItems[currentSpineIndex]) == null ? void 0 : _e.progressionWeight) || 0;
6385
6163
  let progressWithinThisItem = (pageIndex + 1) * (currentItemWeight / numberOfPages);
6386
6164
  if (!isGloballyPrePaginated && currentItem.item.renditionLayout === `reflowable` && !currentItem.isReady()) {
6387
6165
  progressWithinThisItem = 0;
6388
6166
  }
6389
6167
  let totalProgress = estimateBeforeThisItem + progressWithinThisItem;
6390
- if (((_f = context.getManifest()) == null ? void 0 : _f.renditionFlow) === `scrolled-continuous`) {
6168
+ if (((_f = context.manifest) == null ? void 0 : _f.renditionFlow) === `scrolled-continuous`) {
6391
6169
  if (currentItem.isReady()) {
6392
6170
  progressWithinThisItem = getScrollPercentageWithinItem(context, currentPosition, currentItem);
6393
6171
  } else {
6394
6172
  progressWithinThisItem = 0;
6395
6173
  }
6396
- totalProgress = getTotalProgressFromPercentages(estimateBeforeThisItem, currentItemWeight, progressWithinThisItem);
6174
+ totalProgress = getTotalProgressFromPercentages(
6175
+ estimateBeforeThisItem,
6176
+ currentItemWeight,
6177
+ progressWithinThisItem
6178
+ );
6397
6179
  }
6398
6180
  if (currentSpineIndex === readingOrderLength - 1 && pageIndex === numberOfPages - 1 && totalProgress > 0.99) {
6399
6181
  return 1;
@@ -6405,11 +6187,11 @@ const progressionEnhancer = (next) => (options) => {
6405
6187
  };
6406
6188
  const getScrollPercentageWithinItem = (context, currentPosition, currentItem) => {
6407
6189
  const { height, width } = currentItem.getElementDimensions();
6408
- const { top, left } = reader.getAbsolutePositionOf(currentItem);
6409
- if (reader.settings.getSettings().computedPageTurnDirection === `vertical`) {
6410
- return Math.max(0, Math.min(1, (currentPosition.y - top + context.getVisibleAreaRect().height) / height));
6190
+ const { top, left } = reader.spineItemManager.getAbsolutePositionOf(currentItem);
6191
+ if (reader.settings.settings.computedPageTurnDirection === `vertical`) {
6192
+ return Math.max(0, Math.min(1, (currentPosition.y - top + context.state.visibleAreaRect.height) / height));
6411
6193
  } else {
6412
- return Math.max(0, Math.min(1, (currentPosition.x - left + context.getVisibleAreaRect().width) / width));
6194
+ return Math.max(0, Math.min(1, (currentPosition.x - left + context.state.visibleAreaRect.width) / width));
6413
6195
  }
6414
6196
  };
6415
6197
  return {
@@ -6431,67 +6213,58 @@ const accessibilityEnhancer = (next) => (options) => {
6431
6213
  }
6432
6214
  });
6433
6215
  }, {});
6434
- reader.registerHook(`item.onLoad`, ({ addStyle, frame }) => {
6216
+ reader.hookManager.register(`item.onLoad`, ({ itemId, frame, destroy }) => {
6435
6217
  var _a;
6436
- addStyle(
6437
- `prose-reader-accessibility`,
6218
+ const item = reader.spineItemManager.get(itemId);
6219
+ if (!item) return;
6220
+ item.manipulateSpineItem(({ addStyle }) => {
6221
+ addStyle(
6222
+ `prose-reader-accessibility`,
6223
+ `
6224
+ :focus-visible {
6225
+ ${/*
6226
+ Some epubs remove the outline, this is not good practice since it reduce accessibility.
6227
+ We will try to restore it by force.
6228
+ */
6229
+ ``}
6230
+ outline: -webkit-focus-ring-color auto 1px;
6231
+ }
6438
6232
  `
6439
- :focus-visible {
6440
- ${/*
6441
- Some epubs remove the outline, this is not good practice since it reduce accessibility.
6442
- We will try to restore it by force.
6443
- */
6444
- ``}
6445
- outline: -webkit-focus-ring-color auto 1px;
6446
- }
6447
- `
6448
- );
6233
+ );
6234
+ return false;
6235
+ });
6449
6236
  const links = (_a = frame.contentDocument) == null ? void 0 : _a.body.querySelectorAll(`a`);
6450
6237
  links == null ? void 0 : links.forEach((link) => {
6451
6238
  observer.observe(link);
6452
6239
  });
6453
- return () => {
6240
+ destroy(() => {
6454
6241
  links == null ? void 0 : links.forEach((link) => {
6455
6242
  observer.unobserve(link);
6456
6243
  });
6457
- };
6244
+ });
6458
6245
  });
6459
6246
  return {
6460
6247
  ...reader
6461
6248
  };
6462
6249
  };
6463
6250
  const IS_SAFARI = navigator.userAgent.indexOf(``) > -1 && navigator.userAgent.indexOf(`Chrome`) <= -1;
6464
- const webkitEnhancer = (next) => (options) => {
6465
- const transformFlickerFixHooks = [
6466
- {
6467
- name: `viewportNavigator.onBeforeContainerCreated`,
6468
- fn: (element) => {
6469
- element.style.cssText = `
6251
+ const webkitEnhancer = (createReader2) => (options) => {
6252
+ const reader = createReader2(options);
6253
+ if (IS_SAFARI) {
6254
+ reader.hookManager.register("viewportNavigator.onBeforeContainerCreated", ({ element }) => {
6255
+ element.style.cssText = `
6470
6256
  ${element.style.cssText}
6471
6257
  -webkit-transform-style: preserve-3d;
6472
6258
  `;
6473
- return element;
6474
- }
6475
- },
6476
- {
6477
- name: `item.onBeforeContainerCreated`,
6478
- fn: (element) => {
6479
- element.style.cssText = `
6480
- ${element.style.cssText}
6481
- -webkit-transform-style: preserve-3d;
6482
- -webkit-backface-visibility: hidden;
6483
- `;
6484
- return element;
6485
- }
6486
- }
6487
- ];
6488
- const existingHooks = options.hooks || [];
6489
- const reader = next({
6490
- ...options,
6491
- ...IS_SAFARI && {
6492
- hooks: [...existingHooks, ...transformFlickerFixHooks]
6493
- }
6494
- });
6259
+ });
6260
+ reader.hookManager.register("item.onBeforeContainerCreated", ({ element }) => {
6261
+ element.style.cssText = `
6262
+ ${element.style.cssText}
6263
+ -webkit-transform-style: preserve-3d;
6264
+ -webkit-backface-visibility: hidden;
6265
+ `;
6266
+ });
6267
+ }
6495
6268
  return reader;
6496
6269
  };
6497
6270
  const HTML_PREFIX = `${HTML_PREFIX$1}-enhancer-loading`;
@@ -6512,9 +6285,9 @@ const loadingEnhancer = (next) => (options) => {
6512
6285
  };
6513
6286
  }, {})
6514
6287
  );
6515
- const updateEntriesLayout$ = (entries) => combineLatest([reader.$.layout$, reader.theme.$.theme$]).pipe(
6288
+ const updateEntriesLayout$ = (entries) => combineLatest([reader.spine.$.layout$, reader.theme.$.theme$]).pipe(
6516
6289
  map$1(([, theme]) => ({
6517
- width: reader.context.getVisibleAreaRect().width,
6290
+ width: reader.context.state.visibleAreaRect.width,
6518
6291
  theme
6519
6292
  })),
6520
6293
  distinctUntilChanged(isShallowEqual),
@@ -6525,22 +6298,22 @@ const loadingEnhancer = (next) => (options) => {
6525
6298
  });
6526
6299
  })
6527
6300
  );
6528
- const updateEntriesVisibility$ = (entries) => reader.$.itemIsReady$.pipe(
6301
+ const updateEntriesVisibility$ = (entries) => reader.spineItemManager.$.itemIsReady$.pipe(
6529
6302
  tap(({ item, isReady }) => {
6530
6303
  var _a;
6531
6304
  (_a = entries[item.id]) == null ? void 0 : _a.style.setProperty(`visibility`, isReady ? `hidden` : `visible`);
6532
6305
  })
6533
6306
  );
6534
- const destroyEntries$ = (entries) => reader.$.itemsBeforeDestroy$.pipe(
6307
+ const destroyEntries$ = (entries) => reader.spine.$.itemsBeforeDestroy$.pipe(
6535
6308
  map$1(() => {
6536
6309
  Object.values(entries).forEach((element) => element.remove());
6537
6310
  return {};
6538
6311
  })
6539
6312
  );
6540
- const items$ = reader.spineItems$.pipe(
6313
+ const items$ = reader.spine.$.spineItems$.pipe(
6541
6314
  switchMap$1((items) => createEntries$(items)),
6542
6315
  shareReplay(1),
6543
- takeUntil$1(reader.context.$.destroy$)
6316
+ takeUntil$1(reader.context.destroy$)
6544
6317
  );
6545
6318
  items$.pipe(
6546
6319
  switchMap$1((entries) => merge(of(entries), destroyEntries$(entries))),
@@ -6562,7 +6335,7 @@ const createLoadingElementContainer = (containerElement, context) => {
6562
6335
  loadingElement.style.cssText = `
6563
6336
  height: 100%;
6564
6337
  width: 100%;
6565
- max-width: ${context.getVisibleAreaRect().width}px;
6338
+ max-width: ${context.state.visibleAreaRect.width}px;
6566
6339
  text-align: center;
6567
6340
  display: flex;
6568
6341
  justify-content: center;
@@ -6576,7 +6349,10 @@ const createLoadingElementContainer = (containerElement, context) => {
6576
6349
  `;
6577
6350
  return loadingElement;
6578
6351
  };
6579
- const defaultLoadingElementCreate = ({ container, item }) => {
6352
+ const defaultLoadingElementCreate = ({
6353
+ container,
6354
+ item
6355
+ }) => {
6580
6356
  const logoElement = container.ownerDocument.createElement(`div`);
6581
6357
  logoElement.innerText = `prose`;
6582
6358
  logoElement.style.cssText = `
@@ -6602,6 +6378,152 @@ const publicApiEnhancer = (next) => {
6602
6378
  return reader;
6603
6379
  };
6604
6380
  };
6381
+ const createNormalizeEventForViewport = ({
6382
+ iframeEventBridgeElement$,
6383
+ locator
6384
+ }) => {
6385
+ const normalizeEventForViewport = (event) => {
6386
+ var _a;
6387
+ const eventIsComingFromBridge = event.target === iframeEventBridgeElement$.getValue();
6388
+ const iframeOriginalEvent = getOriginalFrameEventFromDocumentEvent(event);
6389
+ const originalFrame = (_a = iframeOriginalEvent == null ? void 0 : iframeOriginalEvent.view) == null ? void 0 : _a.frameElement;
6390
+ if (!eventIsComingFromBridge || !iframeOriginalEvent || !originalFrame) return event;
6391
+ const spineItem = locator.getSpineItemFromIframe(originalFrame);
6392
+ if (!spineItem) return event;
6393
+ if (isPointerEvent(event)) {
6394
+ const { clientX, clientY } = spineItem.translateFramePositionIntoPage(event);
6395
+ const newEvent = new PointerEvent(event.type, {
6396
+ ...event,
6397
+ pointerId: event.pointerId,
6398
+ clientX,
6399
+ clientY
6400
+ });
6401
+ Object.defineProperty(newEvent, `target`, { value: iframeOriginalEvent.target, enumerable: true });
6402
+ return newEvent;
6403
+ }
6404
+ if (isMouseEvent(event)) {
6405
+ const { clientX, clientY } = spineItem.translateFramePositionIntoPage(event);
6406
+ const newEvent = new MouseEvent(event.type, {
6407
+ ...event,
6408
+ clientX,
6409
+ clientY
6410
+ });
6411
+ Object.defineProperty(newEvent, `target`, { value: iframeOriginalEvent.target, enumerable: true });
6412
+ return newEvent;
6413
+ }
6414
+ if (isTouchEvent(event)) {
6415
+ const touches = Array.from(event.touches).map((touch) => {
6416
+ const { clientX, clientY } = spineItem.translateFramePositionIntoPage(touch);
6417
+ return new Touch({
6418
+ identifier: touch.identifier,
6419
+ target: touch.target,
6420
+ clientX,
6421
+ clientY
6422
+ });
6423
+ });
6424
+ const newEvent = new TouchEvent(event.type, {
6425
+ touches,
6426
+ changedTouches: touches,
6427
+ targetTouches: touches
6428
+ });
6429
+ Object.defineProperty(newEvent, `target`, { value: iframeOriginalEvent.target, enumerable: true });
6430
+ return newEvent;
6431
+ }
6432
+ return event;
6433
+ };
6434
+ return normalizeEventForViewport;
6435
+ };
6436
+ const IFRAME_EVENT_BRIDGE_ELEMENT_ID = `proseReaderIframeEventBridgeElement`;
6437
+ const createIframeEventBridgeElement = (container) => {
6438
+ const iframeEventBridgeElement = container.ownerDocument.createElement(`div`);
6439
+ iframeEventBridgeElement.id = IFRAME_EVENT_BRIDGE_ELEMENT_ID;
6440
+ iframeEventBridgeElement.style.cssText = `
6441
+ position: absolute;
6442
+ height: 100%;
6443
+ width: 100%;
6444
+ top: 0;
6445
+ left: 0;
6446
+ z-index: -1;
6447
+ `;
6448
+ return iframeEventBridgeElement;
6449
+ };
6450
+ const pointerEvents = [
6451
+ `pointercancel`,
6452
+ `pointerdown`,
6453
+ `pointerenter`,
6454
+ `pointerleave`,
6455
+ `pointermove`,
6456
+ `pointerout`,
6457
+ `pointerover`,
6458
+ `pointerup`,
6459
+ `touchstart`,
6460
+ `touchend`
6461
+ ];
6462
+ const mouseEvents = [
6463
+ `click`,
6464
+ `mousedown`,
6465
+ `mouseup`,
6466
+ `mouseenter`,
6467
+ `mouseleave`,
6468
+ `mousemove`,
6469
+ `mouseout`,
6470
+ `mouseover`
6471
+ ];
6472
+ const passthroughEvents = [...pointerEvents, ...mouseEvents];
6473
+ const eventsEnhancer = (next) => (options) => {
6474
+ const iframeEventBridgeElement$ = new BehaviorSubject(void 0);
6475
+ const reader = next(options);
6476
+ reader.hookManager.register(`item.onLoad`, ({ destroy, frame, itemId }) => {
6477
+ const item = reader.spineItemManager.get(itemId);
6478
+ if (!item) return;
6479
+ const unregister = passthroughEvents.map((event) => {
6480
+ var _a;
6481
+ const listener = (e) => {
6482
+ var _a2;
6483
+ let convertedEvent = e;
6484
+ if (isPointerEvent(e)) {
6485
+ convertedEvent = new PointerEvent(e.type, e);
6486
+ }
6487
+ if (isMouseEvent(e)) {
6488
+ convertedEvent = new MouseEvent(e.type, e);
6489
+ }
6490
+ if (convertedEvent !== e) {
6491
+ attachOriginalFrameEventToDocumentEvent(convertedEvent, e);
6492
+ (_a2 = iframeEventBridgeElement$.getValue()) == null ? void 0 : _a2.dispatchEvent(convertedEvent);
6493
+ }
6494
+ };
6495
+ (_a = frame.contentDocument) == null ? void 0 : _a.addEventListener(event, listener);
6496
+ return () => {
6497
+ var _a2;
6498
+ (_a2 = frame.contentDocument) == null ? void 0 : _a2.removeEventListener(event, listener);
6499
+ };
6500
+ });
6501
+ item.selectionTracker.track(frame);
6502
+ item.fingerTracker.track(frame);
6503
+ destroy(() => {
6504
+ unregister.forEach((cb) => cb());
6505
+ });
6506
+ });
6507
+ reader.element$.pipe(
6508
+ tap$1((wrapper) => {
6509
+ var _a;
6510
+ const iframeEventBridgeElement = createIframeEventBridgeElement(wrapper);
6511
+ wrapper.appendChild(iframeEventBridgeElement);
6512
+ (_a = iframeEventBridgeElement$.getValue()) == null ? void 0 : _a.remove();
6513
+ iframeEventBridgeElement$.next(iframeEventBridgeElement);
6514
+ }),
6515
+ takeUntil(reader.$.destroy$)
6516
+ ).subscribe();
6517
+ return {
6518
+ ...reader,
6519
+ events: {
6520
+ normalizeEventForViewport: createNormalizeEventForViewport({
6521
+ iframeEventBridgeElement$,
6522
+ locator: reader.spine.locator
6523
+ })
6524
+ }
6525
+ };
6526
+ };
6605
6527
  const createReaderWithEnhancers = (
6606
6528
  //__
6607
6529
  publicApiEnhancer(
@@ -6621,8 +6543,10 @@ const createReaderWithEnhancers = (
6621
6543
  hotkeysEnhancer(
6622
6544
  paginationEnhancer(
6623
6545
  progressionEnhancer(
6624
- // __
6625
- createReader
6546
+ eventsEnhancer(
6547
+ // __
6548
+ createReader
6549
+ )
6626
6550
  )
6627
6551
  )
6628
6552
  )
@@ -6642,6 +6566,7 @@ const createReaderWithEnhancers = (
6642
6566
  )
6643
6567
  );
6644
6568
  export {
6569
+ HookManager,
6645
6570
  Report,
6646
6571
  createReaderWithEnhancers as createReader,
6647
6572
  groupBy,