@prose-reader/core 1.56.0 → 1.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3,17 +3,17 @@ 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 }) => {
6
+ reader.context.state$.pipe(takeUntil(reader.$.destroy$)).subscribe(({ containerElement }) => {
7
7
  if (!containerElement)
8
8
  return;
9
9
  const onScroll = () => {
10
- if (reader.settings.getSettings().computedPageTurnMode === `controlled`) {
10
+ if (reader.settings.settings.computedPageTurnMode === `controlled`) {
11
11
  containerElement.scrollTo(0, 0);
12
12
  }
13
13
  };
14
14
  containerElement.addEventListener(`scroll`, onScroll);
15
15
  });
16
- reader.registerHook(`item.onLoad`, ({ frame }) => {
16
+ reader.hookManager.register(`item.onLoad`, ({ frame }) => {
17
17
  var _a;
18
18
  (_a = frame.contentDocument) == null ? void 0 : _a.body.setAttribute(`tabindex`, `-1`);
19
19
  });
@@ -102,7 +102,7 @@ const fontsEnhancer = (next) => (options) => {
102
102
  }
103
103
  `;
104
104
  const applyChangeToSpineItem = (requireLayout) => {
105
- reader.manipulateSpineItems(({ removeStyle, addStyle, item }) => {
105
+ reader.spine.manipulateSpineItems(({ removeStyle, addStyle, item }) => {
106
106
  if (item.renditionLayout !== `pre-paginated`) {
107
107
  removeStyle(`prose-reader-fonts`);
108
108
  addStyle(`prose-reader-fonts`, getStyle());
@@ -110,11 +110,15 @@ const fontsEnhancer = (next) => (options) => {
110
110
  return requireLayout;
111
111
  });
112
112
  };
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
- }
113
+ reader.hookManager.register(`item.onLoad`, ({ itemId }) => {
114
+ const item = reader.spineItemManager.get(itemId);
115
+ item == null ? void 0 : item.manipulateSpineItem(({ addStyle, removeStyle }) => {
116
+ if (item.item.renditionLayout !== `pre-paginated`) {
117
+ removeStyle(`prose-reader-fonts`);
118
+ addStyle(`prose-reader-fonts`, getStyle());
119
+ }
120
+ return false;
121
+ });
118
122
  });
119
123
  const shouldRequireLayout = (source) => source.pipe(
120
124
  pairwise(),
@@ -171,25 +175,25 @@ const hotkeysEnhancer = (next) => (options) => {
171
175
  map(([e, { pageTurnDirection }]) => {
172
176
  if (pageTurnDirection === "horizontal") {
173
177
  if (e.key === `ArrowRight`) {
174
- reader.turnRight();
178
+ reader.viewportNavigator.turnRight();
175
179
  }
176
180
  if (e.key === `ArrowLeft`) {
177
- reader.turnLeft();
181
+ reader.viewportNavigator.turnLeft();
178
182
  }
179
183
  }
180
184
  if (pageTurnDirection === "vertical") {
181
185
  if (e.key === `ArrowDown`) {
182
- reader.turnRight();
186
+ reader.viewportNavigator.turnRight();
183
187
  }
184
188
  if (e.key === `ArrowUp`) {
185
- reader.turnLeft();
189
+ reader.viewportNavigator.turnLeft();
186
190
  }
187
191
  }
188
192
  return e;
189
193
  })
190
194
  );
191
195
  navigateOnKey(document).pipe(takeUntil(reader.$.destroy$)).subscribe();
192
- reader.spineItems$.pipe(
196
+ reader.spine.$.spineItems$.pipe(
193
197
  switchMap(
194
198
  (spineItems) => merge(
195
199
  ...spineItems.map(
@@ -205,7 +209,7 @@ const hotkeysEnhancer = (next) => (options) => {
205
209
  };
206
210
  const createMovingSafePan$ = (reader) => {
207
211
  let iframeOverlayForAnimationsElement;
208
- const updateOverlayElement$ = reader.context$.pipe(
212
+ const updateOverlayElement$ = reader.context.state$.pipe(
209
213
  switchMap$1(({ containerElement }) => {
210
214
  if (!containerElement)
211
215
  return NEVER;
@@ -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,9 +273,9 @@ 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);
278
+ const spineItem = reader.spineItemManager.get(item.id);
275
279
  if (!((spineItem == null ? void 0 : spineItem.item.renditionLayout) === `reflowable`))
276
280
  return;
277
281
  const { viewportDimensions } = (spineItem == null ? void 0 : spineItem.getViewPortInformation()) ?? {};
@@ -297,9 +301,9 @@ const layoutEnhancer = (next) => (options) => {
297
301
  pageHorizontalMargin,
298
302
  pageVerticalMargin
299
303
  });
300
- reader.registerHook(`onViewportOffsetAdjust`, () => {
304
+ reader.hookManager.register(`onViewportOffsetAdjust`, () => {
301
305
  let hasRedrawn = false;
302
- reader.manipulateSpineItems(({ frame }) => {
306
+ reader.spine.manipulateSpineItems(({ frame }) => {
303
307
  if (!hasRedrawn && frame) {
304
308
  void frame.getBoundingClientRect().left;
305
309
  hasRedrawn = true;
@@ -307,7 +311,7 @@ const layoutEnhancer = (next) => (options) => {
307
311
  return SHOULD_NOT_LAYOUT;
308
312
  });
309
313
  });
310
- reader.registerHook(`item.onLayoutBeforeMeasurement`, ({ frame, minimumWidth, item, isImageType }) => {
314
+ reader.hookManager.register(`item.onLayoutBeforeMeasurement`, ({ frame, minimumWidth, item, isImageType }) => {
311
315
  var _a, _b;
312
316
  const { pageHorizontalMargin: pageHorizontalMargin2 = 0, pageVerticalMargin: pageVerticalMargin2 = 0 } = settingsSubject$.value;
313
317
  const pageSize = reader.context.getPageSize();
@@ -349,7 +353,7 @@ const layoutEnhancer = (next) => (options) => {
349
353
  fixReflowable(reader);
350
354
  let observer;
351
355
  if (options.layoutAutoResize === `container`) {
352
- reader.context$.pipe(
356
+ reader.context.state$.pipe(
353
357
  map$1((state) => state.containerElement),
354
358
  filter(isDefined),
355
359
  distinctUntilChanged(),
@@ -502,15 +506,15 @@ const linksEnhancer = (next) => (options) => {
502
506
  return false;
503
507
  const hrefUrl = new URL(element.href);
504
508
  const hrefWithoutAnchor = `${hrefUrl.origin}${hrefUrl.pathname}`;
505
- const hasExistingSpineItem = (_a = reader.context.getManifest()) == null ? void 0 : _a.spineItems.some((item) => item.href === hrefWithoutAnchor);
509
+ const hasExistingSpineItem = (_a = reader.context.manifest) == null ? void 0 : _a.spineItems.some((item) => item.href === hrefWithoutAnchor);
506
510
  if (hasExistingSpineItem) {
507
- reader.goToUrl(hrefUrl);
511
+ reader.viewportNavigator.goToUrl(hrefUrl);
508
512
  return true;
509
513
  }
510
514
  return false;
511
515
  };
512
- reader.registerHook(`item.onLoad`, ({ frame }) => {
513
- if (frame.contentDocument) {
516
+ reader.hookManager.register(`item.onLoad`, ({ frame }) => {
517
+ if (frame == null ? void 0 : frame.contentDocument) {
514
518
  Array.from(frame.contentDocument.querySelectorAll(`a`)).forEach(
515
519
  (element) => element.addEventListener(`click`, (e) => {
516
520
  if (e.target && `style` in e.target && `ELEMENT_NODE` in e.target) {
@@ -534,27 +538,27 @@ const linksEnhancer = (next) => (options) => {
534
538
  const createNavigator = (reader) => {
535
539
  const goToNextSpineItem = () => {
536
540
  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;
541
+ const focusedSpineItemIndex = reader.spineItemManager.getFocusedSpineItemIndex() || 0;
542
+ const { end = focusedSpineItemIndex } = reader.spine.locator.getSpineItemsFromReadingOrderPosition(reader.viewportNavigator.getCurrentNavigationPosition()) || {};
543
+ const numberOfSpineItems = ((_a = reader.context.manifest) == null ? void 0 : _a.spineItems.length) ?? 0;
540
544
  const nextItem = end + 1;
541
545
  if (nextItem < numberOfSpineItems) {
542
- reader.goToSpineItem(nextItem);
546
+ reader.viewportNavigator.goToSpineItem(nextItem);
543
547
  }
544
548
  };
545
549
  const goToPreviousSpineItem = () => {
546
- const focusedSpineItemIndex = reader.getFocusedSpineItemIndex() || 0;
547
- const { begin = focusedSpineItemIndex } = reader.locator.getSpineItemsFromReadingOrderPosition(reader.getCurrentNavigationPosition()) || {};
550
+ const focusedSpineItemIndex = reader.spineItemManager.getFocusedSpineItemIndex() || 0;
551
+ const { begin = focusedSpineItemIndex } = reader.spine.locator.getSpineItemsFromReadingOrderPosition(reader.viewportNavigator.getCurrentNavigationPosition()) || {};
548
552
  const nextItem = begin - 1;
549
553
  if (nextItem >= 0) {
550
- reader.goToSpineItem(nextItem);
554
+ reader.viewportNavigator.goToSpineItem(nextItem);
551
555
  }
552
556
  };
553
557
  return {
554
558
  goToNextSpineItem,
555
559
  goToPreviousSpineItem,
556
560
  goToLeftSpineItem: () => {
557
- if (reader.settings.getSettings().computedPageTurnDirection === "vertical")
561
+ if (reader.settings.settings.computedPageTurnDirection === "vertical")
558
562
  return;
559
563
  if (reader.context.isRTL()) {
560
564
  return goToNextSpineItem();
@@ -562,7 +566,7 @@ const createNavigator = (reader) => {
562
566
  return goToPreviousSpineItem();
563
567
  },
564
568
  goToRightSpineItem: () => {
565
- if (reader.settings.getSettings().computedPageTurnDirection === "vertical")
569
+ if (reader.settings.settings.computedPageTurnDirection === "vertical")
566
570
  return;
567
571
  if (reader.context.isRTL()) {
568
572
  return goToPreviousSpineItem();
@@ -573,7 +577,7 @@ const createNavigator = (reader) => {
573
577
  };
574
578
  const createState = (reader) => {
575
579
  return reader.pagination.paginationInfo$.pipe(
576
- withLatestFrom$1(reader.context.$.manifest$, reader.settings.settings$),
580
+ withLatestFrom$1(reader.context.manifest$, reader.settings.settings$),
577
581
  map(([paginationInfo, manifest, { computedPageTurnDirection }]) => {
578
582
  const numberOfSpineItems = (manifest == null ? void 0 : manifest.spineItems.length) ?? 0;
579
583
  const isAtAbsoluteBeginning = paginationInfo.beginSpineItemIndex === 0 && paginationInfo.beginPageIndexInSpineItem === 0;
@@ -637,8 +641,8 @@ const buildChapterInfoFromSpineItem = (manifest, item) => {
637
641
  return buildChaptersInfo(href, ((_a = manifest.nav) == null ? void 0 : _a.toc) ?? [], manifest);
638
642
  };
639
643
  const getChaptersInfo = (reader) => {
640
- const manifest = reader.context.getManifest();
641
- const items = reader.getSpineItems();
644
+ const manifest = reader.context.manifest;
645
+ const items = reader.spineItemManager.getAll();
642
646
  if (!manifest)
643
647
  return {};
644
648
  return items.reduce(
@@ -652,7 +656,7 @@ const getChaptersInfo = (reader) => {
652
656
  );
653
657
  };
654
658
  const trackChapterInfo = (reader) => {
655
- return reader.spineItems$.pipe(
659
+ return reader.spine.$.spineItems$.pipe(
656
660
  startWith([]),
657
661
  map(() => getChaptersInfo(reader))
658
662
  );
@@ -743,7 +747,7 @@ const getClosestValidOffsetFromApproximateOffsetInPages = (offset, pageWidth, it
743
747
  const getSpineItemNumberOfPages = ({ spineItem, reader }) => {
744
748
  const writingMode = spineItem.spineItemFrame.getWritingMode();
745
749
  const { width, height } = spineItem.getElementDimensions();
746
- const settings = reader.settings.getSettings();
750
+ const settings = reader.settings.settings;
747
751
  if (settings.pageTurnDirection === `vertical` && settings.pageTurnMode === `scrollable`) {
748
752
  return 1;
749
753
  }
@@ -752,11 +756,11 @@ const getSpineItemNumberOfPages = ({ spineItem, reader }) => {
752
756
  }
753
757
  return calculateNumberOfPagesForItem(width, reader.context.getPageSize().width);
754
758
  };
755
- const getNumberOfPagesForAllSpineItems = (reader) => reader.getSpineItems().map((item) => {
759
+ const getNumberOfPagesForAllSpineItems = (reader) => reader.spineItemManager.getAll().map((item) => {
756
760
  return getSpineItemNumberOfPages({ spineItem: item, reader });
757
761
  }, 0);
758
762
  const trackTotalPages = (reader) => {
759
- const totalPages$ = reader.$.layout$.pipe(
763
+ const totalPages$ = reader.spine.$.layout$.pipe(
760
764
  debounceTime(10, animationFrameScheduler),
761
765
  withLatestFrom$1(reader.pagination.paginationInfo$),
762
766
  map(() => {
@@ -779,8 +783,8 @@ const trackTotalPages = (reader) => {
779
783
  };
780
784
  const mapPaginationInfoToExtendedInfo = (reader) => (paginationInfo, chaptersInfo) => {
781
785
  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;
786
+ const beginItem = paginationInfo.beginSpineItemIndex !== void 0 ? reader.spineItemManager.get(paginationInfo.beginSpineItemIndex) : void 0;
787
+ const endItem = paginationInfo.endSpineItemIndex !== void 0 ? reader.spineItemManager.get(paginationInfo.endSpineItemIndex) : void 0;
784
788
  return {
785
789
  ...paginationInfo,
786
790
  beginChapterInfo: beginItem ? chaptersInfo[beginItem.item.id] : void 0,
@@ -809,13 +813,13 @@ const mapPaginationInfoToExtendedInfo = (reader) => (paginationInfo, chaptersInf
809
813
  paginationInfo.endSpineItemIndex ?? 0,
810
814
  paginationInfo.endNumberOfPagesInSpineItem,
811
815
  paginationInfo.endPageIndexInSpineItem || 0,
812
- reader.getCurrentViewportPosition(),
816
+ reader.viewportNavigator.getCurrentViewportPosition(),
813
817
  endItem
814
818
  ) : 0,
815
- isUsingSpread: context.isUsingSpreadMode() ?? false
819
+ isUsingSpread: context.state.isUsingSpreadMode ?? false
816
820
  // hasNextChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
817
821
  // hasPreviousChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
818
- // numberOfSpineItems: context.getManifest()?.readingOrder.length,
822
+ // numberOfSpineItems: context.manifest?.readingOrder.length,
819
823
  };
820
824
  };
821
825
  const trackPaginationInfo = (reader) => {
@@ -911,18 +915,22 @@ const themeEnhancer = (next) => (options) => {
911
915
  };
912
916
  };
913
917
  const applyChangeToSpineItem = () => {
914
- reader.manipulateSpineItems(({ removeStyle, addStyle, container }) => {
918
+ reader.spine.manipulateSpineItems(({ removeStyle, addStyle, container }) => {
915
919
  removeStyle(`prose-reader-theme`);
916
920
  addStyle(`prose-reader-theme`, getStyle());
917
921
  applyChangeToSpineItemElement({ container });
918
922
  return false;
919
923
  });
920
924
  };
921
- reader.registerHook(`item.onLoad`, ({ removeStyle, addStyle }) => {
922
- removeStyle(`prose-reader-theme`);
923
- addStyle(`prose-reader-theme`, getStyle());
925
+ reader.hookManager.register(`item.onLoad`, ({ itemId }) => {
926
+ const item = reader.spineItemManager.get(itemId);
927
+ item == null ? void 0 : item.manipulateSpineItem(({ removeStyle, addStyle }) => {
928
+ removeStyle(`prose-reader-theme`);
929
+ addStyle(`prose-reader-theme`, getStyle());
930
+ return false;
931
+ });
924
932
  });
925
- reader.spineItems$.pipe(
933
+ reader.spine.$.spineItems$.pipe(
926
934
  tap((items) => items.map(({ element }) => applyChangeToSpineItemElement({ container: element }))),
927
935
  takeUntil$1(reader.$.destroy$)
928
936
  ).subscribe();
@@ -959,7 +967,7 @@ const createElementZoomer = (reader) => {
959
967
  imgLastPosition = { x: 0, y: 0 };
960
968
  baseScale = 1;
961
969
  lastUserScale = 1;
962
- const container = reader.context.getState().containerElement;
970
+ const container = reader.context.state.containerElement;
963
971
  if (container) {
964
972
  imageMagnifierContainer = container.ownerDocument.createElement(`div`);
965
973
  imageMagnifierContainer.style.cssText = `
@@ -1017,6 +1025,7 @@ const createElementZoomer = (reader) => {
1017
1025
  `transform`,
1018
1026
  `translate3d(${imgLastPosition.x}px, ${imgLastPosition.y}px, 0px) scale3d(${baseScale}, ${baseScale}, 1)`
1019
1027
  );
1028
+ console.log({ delta, imgLastPosition });
1020
1029
  movingLastDelta = delta;
1021
1030
  }
1022
1031
  if (isLast) {
@@ -1134,7 +1143,7 @@ const zoomEnhancer = (next) => (options) => {
1134
1143
  const elementZoomer = createElementZoomer(reader);
1135
1144
  const viewportZoomer = createViewportZoomer(reader);
1136
1145
  const currentZoomerSubject$ = new BehaviorSubject(void 0);
1137
- const isUsingScrollableViewport = () => reader.settings.getSettings().computedPageTurnMode === `scrollable`;
1146
+ const isUsingScrollableViewport = () => reader.settings.settings.computedPageTurnMode === `scrollable`;
1138
1147
  const enter = (imgElement) => {
1139
1148
  var _a;
1140
1149
  (_a = currentZoomerSubject$ == null ? void 0 : currentZoomerSubject$.value) == null ? void 0 : _a.exit();
@@ -1217,143 +1226,100 @@ const isUsingSpreadMode = ({
1217
1226
  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
1227
  };
1219
1228
  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),
1229
+ const areAllItemsPrePaginated = (manifest) => !(manifest == null ? void 0 : manifest.spineItems.some((item) => item.renditionLayout === `reflowable`));
1230
+ class Context {
1231
+ constructor() {
1232
+ this._stateSubject = new BehaviorSubject({
1233
+ marginBottom: 0,
1234
+ marginTop: 0,
1235
+ calculatedInnerMargin: 0,
1236
+ visibleAreaRect: {
1237
+ width: 0,
1238
+ height: 0,
1239
+ x: 0,
1240
+ y: 0
1241
+ }
1242
+ });
1243
+ this.destroy$ = new Subject();
1244
+ this.state$ = this._stateSubject.pipe(distinctUntilChanged(isShallowEqual));
1245
+ this.manifest$ = this._stateSubject.pipe(
1246
+ map$1((state) => state.manifest),
1247
+ filter(isDefined),
1248
+ distinctUntilChanged()
1249
+ );
1250
+ this.containerElement$ = this._stateSubject.pipe(
1251
+ map$1((state) => state.containerElement),
1252
+ filter(isDefined),
1253
+ distinctUntilChanged()
1254
+ );
1255
+ this.hasVerticalWriting$ = this._stateSubject.pipe(
1256
+ map$1((state) => state.hasVerticalWriting),
1257
+ filter(isDefined),
1258
+ distinctUntilChanged()
1259
+ );
1260
+ this.isUsingSpreadMode$ = this._stateSubject.pipe(
1261
+ map$1((state) => state.isUsingSpreadMode),
1262
+ distinctUntilChanged()
1263
+ );
1264
+ this.isRTL = () => {
1265
+ var _a;
1266
+ return ((_a = this._stateSubject.getValue().manifest) == null ? void 0 : _a.readingDirection) === `rtl`;
1267
+ };
1268
+ this.destroy = () => {
1269
+ this._stateSubject.complete();
1270
+ this.destroy$.next();
1271
+ this.destroy$.complete();
1272
+ };
1273
+ }
1274
+ /**
1275
+ * @todo optimize to not run if not necessary
1276
+ */
1277
+ update(newState) {
1278
+ const previousState = this._stateSubject.getValue();
1279
+ const manifest = newState.manifest ?? previousState.manifest;
1280
+ const forceSinglePageMode = newState.forceSinglePageMode ?? previousState.forceSinglePageMode;
1281
+ const visibleAreaRect = newState.visibleAreaRect ?? previousState.visibleAreaRect;
1282
+ const marginTop = newState.marginTop ?? previousState.marginTop;
1283
+ const marginBottom = newState.marginBottom ?? previousState.marginBottom;
1284
+ const newCompleteState = {
1285
+ ...previousState,
1286
+ ...newState,
1287
+ ...newState.visibleAreaRect && {
1288
+ ...newState.visibleAreaRect,
1289
+ height: newState.visibleAreaRect.height - marginTop - marginBottom
1290
+ },
1291
+ ...newState.manifest && {
1292
+ areAllItemsPrePaginated: areAllItemsPrePaginated(manifest),
1293
+ isFullyPrePaginated: isFullyPrePaginated(manifest)
1294
+ },
1261
1295
  isUsingSpreadMode: isUsingSpreadMode({
1262
- manifest: newManifest,
1296
+ manifest,
1263
1297
  visibleAreaRect,
1264
- forceSinglePageMode: settings.getSettings().forceSinglePageMode
1298
+ forceSinglePageMode
1265
1299
  })
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()
1300
+ };
1301
+ if (!isShallowEqual(newCompleteState, previousState)) {
1302
+ this._stateSubject.next(newCompleteState);
1353
1303
  }
1354
- };
1355
- };
1356
- const areAllItemsPrePaginated$1 = (manifest) => !(manifest == null ? void 0 : manifest.spineItems.some((item) => item.renditionLayout === `reflowable`));
1304
+ }
1305
+ get state() {
1306
+ return this._stateSubject.getValue();
1307
+ }
1308
+ get manifest() {
1309
+ return this.state.manifest;
1310
+ }
1311
+ get readingDirection() {
1312
+ var _a;
1313
+ return (_a = this.manifest) == null ? void 0 : _a.readingDirection;
1314
+ }
1315
+ getPageSize() {
1316
+ const { isUsingSpreadMode: isUsingSpreadMode2, visibleAreaRect } = this._stateSubject.getValue();
1317
+ return {
1318
+ width: isUsingSpreadMode2 ? visibleAreaRect.width / 2 : visibleAreaRect.width,
1319
+ height: visibleAreaRect.height
1320
+ };
1321
+ }
1322
+ }
1357
1323
  const __UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT_KEY = `__UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT`;
1358
1324
  const ITEM_EXTENSION_VALID_FOR_FRAME_SRC = [`.xhtml`, `.html`, `.htm`];
1359
1325
  const HTML_PREFIX$1 = `prose-reader`;
@@ -1406,11 +1372,6 @@ const createFrame$ = Report.measurePerformance(`SpineItemFrame createFrame`, Inf
1406
1372
  `;
1407
1373
  return of(frame);
1408
1374
  });
1409
- const createFrameManipulator = (frameElement) => ({
1410
- frame: frameElement,
1411
- removeStyle: createRemoveStyleHelper(frameElement),
1412
- addStyle: createAddStyleHelper(frameElement)
1413
- });
1414
1375
  const getIntrinsicDimensionsFromBase64Img = (data) => new Promise((resolve, reject) => {
1415
1376
  const image = new Image();
1416
1377
  image.src = data;
@@ -1463,15 +1424,14 @@ const createHtmlPageFromResource = async (resourceResponse, item) => {
1463
1424
  const content = await resourceResponse.text();
1464
1425
  return content;
1465
1426
  };
1466
- const isOnLoadHook = (hook) => hook.name === `item.onLoad`;
1467
1427
  const createLoader = ({
1468
1428
  item,
1469
1429
  parent,
1470
1430
  fetchResource,
1471
- hooks$,
1472
1431
  context,
1473
1432
  viewportState$,
1474
- settings
1433
+ settings,
1434
+ hookManager
1475
1435
  }) => {
1476
1436
  const destroySubject$ = new Subject();
1477
1437
  const loadSubject$ = new Subject();
@@ -1479,10 +1439,9 @@ const createLoader = ({
1479
1439
  const frameElementSubject$ = new BehaviorSubject(void 0);
1480
1440
  const isLoadedSubject$ = new BehaviorSubject(false);
1481
1441
  const isReadySubject$ = new BehaviorSubject(false);
1482
- let onLoadHookReturns = [];
1483
1442
  let computedStyleAfterLoad;
1484
1443
  const makeItHot = (source$) => {
1485
- source$.pipe(takeUntil$1(context.$.destroy$)).subscribe();
1444
+ source$.pipe(takeUntil$1(context.destroy$)).subscribe();
1486
1445
  return source$;
1487
1446
  };
1488
1447
  const getHtmlFromResource = (response) => createHtmlPageFromResource(response, item);
@@ -1496,14 +1455,7 @@ const createLoader = ({
1496
1455
  withLatestFrom(frameElementSubject$),
1497
1456
  filter(([_, frame]) => !!frame),
1498
1457
  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 = [];
1458
+ hookManager.destroy(`item.onLoad`, item.id);
1507
1459
  frame == null ? void 0 : frame.remove();
1508
1460
  frameElementSubject$.next(void 0);
1509
1461
  }),
@@ -1548,8 +1500,7 @@ const createLoader = ({
1548
1500
  return EMPTY;
1549
1501
  return fromEvent(frame, `load`).pipe(
1550
1502
  take(1),
1551
- withLatestFrom(hooks$),
1552
- mergeMap(([_, hooks]) => {
1503
+ mergeMap(() => {
1553
1504
  var _a, _b;
1554
1505
  const body = (_a = frame.contentDocument) == null ? void 0 : _a.body;
1555
1506
  if (!body) {
@@ -1560,21 +1511,13 @@ const createLoader = ({
1560
1511
  if ((frame == null ? void 0 : frame.contentDocument) && body) {
1561
1512
  computedStyleAfterLoad = (_b = frame == null ? void 0 : frame.contentWindow) == null ? void 0 : _b.getComputedStyle(body);
1562
1513
  }
1563
- if (settings.getSettings().computedPageTurnMode !== `scrollable`) {
1514
+ if (settings.settings.computedPageTurnMode !== `scrollable`) {
1564
1515
  frame.setAttribute(`tab-index`, `0`);
1565
1516
  }
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);
1517
+ return hookManager.execute(`item.onLoad`, item.id, {
1518
+ itemId: item.id,
1519
+ frame
1520
+ }).pipe(map$1(() => frame));
1578
1521
  })
1579
1522
  );
1580
1523
  }),
@@ -1623,14 +1566,19 @@ const createLoader = ({
1623
1566
  }
1624
1567
  };
1625
1568
  };
1569
+ const createFrameManipulator = (frameElement) => ({
1570
+ frame: frameElement,
1571
+ removeStyle: createRemoveStyleHelper(frameElement),
1572
+ addStyle: createAddStyleHelper(frameElement)
1573
+ });
1626
1574
  const createFrameItem = ({
1627
1575
  item,
1628
1576
  parent,
1629
1577
  fetchResource,
1630
1578
  context,
1631
- hooks$,
1632
1579
  viewportState$,
1633
- settings
1580
+ settings,
1581
+ hookManager
1634
1582
  }) => {
1635
1583
  const destroySubject$ = new Subject();
1636
1584
  const {
@@ -1639,7 +1587,7 @@ const createFrameItem = ({
1639
1587
  unload,
1640
1588
  destroy: loaderDestroy,
1641
1589
  getComputedStyleAfterLoad
1642
- } = createLoader({ context, hooks$, item, parent, fetchResource, viewportState$, settings });
1590
+ } = createLoader({ context, hookManager, item, parent, fetchResource, viewportState$, settings });
1643
1591
  let isLoadedSync = false;
1644
1592
  let isReadySync = false;
1645
1593
  isLoaded$.subscribe({
@@ -1727,7 +1675,7 @@ const createFrameItem = ({
1727
1675
  if (frame) {
1728
1676
  frame.style.width = `${size.width}px`;
1729
1677
  frame.style.height = `${size.height}px`;
1730
- if (settings.getSettings().computedPageTurnMode !== `scrollable`) {
1678
+ if (settings.settings.computedPageTurnMode !== `scrollable`) {
1731
1679
  frame.setAttribute(`tab-index`, `0`);
1732
1680
  }
1733
1681
  }
@@ -1837,198 +1785,24 @@ const createSelectionTracker = () => {
1837
1785
  $: subject.asObservable()
1838
1786
  };
1839
1787
  };
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];
2010
1788
  const createCommonSpineItem = ({
2011
1789
  item,
2012
1790
  context,
2013
1791
  parentElement,
2014
- iframeEventBridgeElement$,
2015
- hooks$,
2016
1792
  viewportState$,
2017
- settings
1793
+ settings,
1794
+ hookManager
2018
1795
  }) => {
2019
- var _a;
2020
1796
  const destroySubject$ = new Subject();
2021
- const containerElement = createContainerElement$1(parentElement, item, hooks$);
1797
+ const containerElement = createContainerElement$1(parentElement, item, hookManager);
2022
1798
  const overlayElement = createOverlayElement(parentElement, item);
2023
1799
  const fingerTracker = createFingerTracker();
2024
1800
  const selectionTracker = createSelectionTracker();
2025
- const frameHooks = createFrameHooks(iframeEventBridgeElement$, fingerTracker, selectionTracker);
2026
1801
  const spineItemFrame = createFrameItem({
2027
1802
  parent: containerElement,
2028
1803
  item,
2029
1804
  context,
2030
- fetchResource: (_a = context.getState()) == null ? void 0 : _a.fetchResource,
2031
- hooks$: hooks$.asObservable().pipe(map$1((hooks) => [...hooks, ...frameHooks])),
1805
+ hookManager,
2032
1806
  viewportState$,
2033
1807
  settings
2034
1808
  });
@@ -2051,12 +1825,12 @@ const createCommonSpineItem = ({
2051
1825
  return memoizedElementDimensions;
2052
1826
  };
2053
1827
  const isImageType = () => {
2054
- var _a2;
2055
- return !!((_a2 = item.mediaType) == null ? void 0 : _a2.startsWith(`image/`));
1828
+ var _a;
1829
+ return !!((_a = item.mediaType) == null ? void 0 : _a.startsWith(`image/`));
2056
1830
  };
2057
1831
  const injectStyle = (cssText) => {
2058
- var _a2, _b;
2059
- (_a2 = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a2.removeStyle(`prose-reader-css`);
1832
+ var _a, _b;
1833
+ (_a = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a.removeStyle(`prose-reader-css`);
2060
1834
  (_b = spineItemFrame.getManipulableFrame()) == null ? void 0 : _b.addStyle(`prose-reader-css`, cssText);
2061
1835
  };
2062
1836
  const adjustPositionOfElement = ({ right, left, top }) => {
@@ -2077,10 +1851,10 @@ const createCommonSpineItem = ({
2077
1851
  }
2078
1852
  };
2079
1853
  const getViewPortInformation = () => {
2080
- var _a2;
1854
+ var _a;
2081
1855
  const { width: pageWidth, height: pageHeight } = context.getPageSize();
2082
1856
  const viewportDimensions = spineItemFrame.getViewportDimensions();
2083
- const frameElement = (_a2 = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a2.frame;
1857
+ const frameElement = (_a = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a.frame;
2084
1858
  if (containerElement && (frameElement == null ? void 0 : frameElement.contentDocument) && (frameElement == null ? void 0 : frameElement.contentWindow) && viewportDimensions) {
2085
1859
  const computedWidthScale = pageWidth / viewportDimensions.width;
2086
1860
  const computedScale = Math.min(computedWidthScale, pageHeight / viewportDimensions.height);
@@ -2090,8 +1864,8 @@ const createCommonSpineItem = ({
2090
1864
  const loadContent = () => spineItemFrame.load();
2091
1865
  const unloadContent = () => spineItemFrame.unload();
2092
1866
  const getBoundingRectOfElementFromSelector = (selector) => {
2093
- var _a2, _b, _c, _d, _e;
2094
- const frame = (_a2 = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a2.frame;
1867
+ var _a, _b, _c, _d, _e;
1868
+ const frame = (_a = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a.frame;
2095
1869
  if (frame && selector) {
2096
1870
  if (selector.startsWith(`#`)) {
2097
1871
  return (_c = (_b = frame.contentDocument) == null ? void 0 : _b.getElementById(selector.replace(`#`, ``))) == null ? void 0 : _c.getBoundingClientRect();
@@ -2136,16 +1910,12 @@ const createCommonSpineItem = ({
2136
1910
  }) => {
2137
1911
  containerElement.style.width = `${width}px`;
2138
1912
  containerElement.style.height = `${height}px`;
2139
- hooks$.getValue().forEach((hook) => {
2140
- if (hook.name === `item.onAfterLayout`) {
2141
- hook.fn({ blankPagePosition, item, minimumWidth });
2142
- }
2143
- });
1913
+ hookManager.execute(`item.onAfterLayout`, void 0, { blankPagePosition, item, minimumWidth });
2144
1914
  setLayoutDirty();
2145
1915
  };
2146
1916
  const translateFramePositionIntoPage = (position) => {
2147
- var _a2, _b;
2148
- const { left = 0, top = 0 } = ((_a2 = spineItemFrame.getFrameElement()) == null ? void 0 : _a2.getBoundingClientRect()) || {};
1917
+ var _a, _b;
1918
+ const { left = 0, top = 0 } = ((_a = spineItemFrame.getFrameElement()) == null ? void 0 : _a.getBoundingClientRect()) || {};
2149
1919
  const computedScale = ((_b = getViewPortInformation()) == null ? void 0 : _b.computedScale) ?? 1;
2150
1920
  const adjustedX = position.clientX * computedScale + left;
2151
1921
  const adjustedY = position.clientY * computedScale + top;
@@ -2155,20 +1925,14 @@ const createCommonSpineItem = ({
2155
1925
  };
2156
1926
  };
2157
1927
  const getResource = async () => {
2158
- const fetchResource = context.getState().fetchResource;
1928
+ const fetchResource = settings.settings.fetchResource;
2159
1929
  const lastFetch = (_) => {
2160
1930
  if (fetchResource) {
2161
1931
  return fetchResource(item);
2162
1932
  }
2163
1933
  return fetch(item.href);
2164
1934
  };
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);
1935
+ return await lastFetch();
2172
1936
  };
2173
1937
  const manipulateSpineItem = (cb) => {
2174
1938
  const manipulableFrame = spineItemFrame.getManipulableFrame();
@@ -2191,16 +1955,12 @@ const createCommonSpineItem = ({
2191
1955
  overlayElement
2192
1956
  });
2193
1957
  };
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
- }
1958
+ const executeOnLayoutBeforeMeasurementHook = (options) => hookManager.execute("item.onLayoutBeforeMeasurement", void 0, {
1959
+ frame: spineItemFrame,
1960
+ container: containerElement,
1961
+ item,
1962
+ isImageType,
1963
+ ...options
2204
1964
  });
2205
1965
  const contentLayout$ = spineItemFrame.$.contentLayoutChange$.pipe(
2206
1966
  withLatestFrom(spineItemFrame.$.isReady$),
@@ -2239,8 +1999,8 @@ const createCommonSpineItem = ({
2239
1999
  destroySubject$.complete();
2240
2000
  },
2241
2001
  isUsingVerticalWriting: () => {
2242
- var _a2;
2243
- return (_a2 = spineItemFrame.getWritingMode()) == null ? void 0 : _a2.startsWith(`vertical`);
2002
+ var _a;
2003
+ return (_a = spineItemFrame.getWritingMode()) == null ? void 0 : _a.startsWith(`vertical`);
2244
2004
  },
2245
2005
  /**
2246
2006
  * @important
@@ -2251,7 +2011,7 @@ const createCommonSpineItem = ({
2251
2011
  * be confined to a single page.
2252
2012
  */
2253
2013
  getReadingDirection: () => {
2254
- return spineItemFrame.getReadingDirection() || context.getReadingDirection();
2014
+ return spineItemFrame.getReadingDirection() || context.readingDirection;
2255
2015
  },
2256
2016
  manipulateSpineItem,
2257
2017
  executeOnLayoutBeforeMeasurementHook,
@@ -2266,7 +2026,7 @@ const createCommonSpineItem = ({
2266
2026
  }
2267
2027
  };
2268
2028
  };
2269
- const createContainerElement$1 = (containerElement, item, hooks$) => {
2029
+ const createContainerElement$1 = (containerElement, item, hookManager) => {
2270
2030
  const element = containerElement.ownerDocument.createElement(`div`);
2271
2031
  element.classList.add(`spineItem`);
2272
2032
  element.classList.add(`spineItem-${item.renditionLayout}`);
@@ -2274,12 +2034,8 @@ const createContainerElement$1 = (containerElement, item, hooks$) => {
2274
2034
  position: absolute;
2275
2035
  overflow: hidden;
2276
2036
  `;
2277
- return hooks$.getValue().reduce((element2, hook) => {
2278
- if (hook.name === `item.onBeforeContainerCreated`) {
2279
- return hook.fn(element2);
2280
- }
2281
- return element2;
2282
- }, element);
2037
+ hookManager.execute("item.onBeforeContainerCreated", void 0, { element });
2038
+ return element;
2283
2039
  };
2284
2040
  const createOverlayElement = (containerElement, item) => {
2285
2041
  const element = containerElement.ownerDocument.createElement(`div`);
@@ -2294,42 +2050,6 @@ const createOverlayElement = (containerElement, item) => {
2294
2050
  `;
2295
2051
  return element;
2296
2052
  };
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
2053
  const getStyleForViewportDocument = () => {
2334
2054
  return `
2335
2055
  body {
@@ -2342,19 +2062,17 @@ const createPrePaginatedSpineItem = ({
2342
2062
  item,
2343
2063
  context,
2344
2064
  containerElement,
2345
- iframeEventBridgeElement$,
2346
- hooks$,
2347
2065
  viewportState$,
2348
- settings
2066
+ settings,
2067
+ hookManager
2349
2068
  }) => {
2350
2069
  const commonSpineItem = createCommonSpineItem({
2351
2070
  context,
2352
2071
  item,
2353
2072
  parentElement: containerElement,
2354
- iframeEventBridgeElement$,
2355
- hooks$,
2356
2073
  viewportState$,
2357
- settings
2074
+ settings,
2075
+ hookManager
2358
2076
  });
2359
2077
  const spineItemFrame = commonSpineItem.spineItemFrame;
2360
2078
  const layout = ({
@@ -2365,15 +2083,15 @@ const createPrePaginatedSpineItem = ({
2365
2083
  var _a;
2366
2084
  const { width: pageWidth, height: pageHeight } = context.getPageSize();
2367
2085
  const { viewportDimensions, computedScale = 1 } = commonSpineItem.getViewPortInformation() ?? {};
2368
- const visibleArea = context.getVisibleAreaRect();
2086
+ const visibleArea = context.state.visibleAreaRect;
2369
2087
  const frameElement = (_a = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a.frame;
2370
2088
  if ((spineItemFrame == null ? void 0 : spineItemFrame.getIsLoaded()) && (frameElement == null ? void 0 : frameElement.contentDocument) && (frameElement == null ? void 0 : frameElement.contentWindow)) {
2371
2089
  const contentWidth = pageWidth;
2372
- const contentHeight = visibleArea.height + context.getCalculatedInnerMargin();
2090
+ const contentHeight = visibleArea.height + context.state.calculatedInnerMargin;
2373
2091
  const cssLink = buildDocumentStyle(
2374
2092
  {
2375
2093
  ...commonSpineItem.getDimensionsForPaginatedContent(),
2376
- enableTouch: settings.getSettings().computedPageTurnMode !== `scrollable`,
2094
+ enableTouch: settings.settings.computedPageTurnMode !== `scrollable`,
2377
2095
  spreadPosition
2378
2096
  },
2379
2097
  viewportDimensions
@@ -2516,19 +2234,17 @@ const createReflowableSpineItem = ({
2516
2234
  item,
2517
2235
  context,
2518
2236
  containerElement,
2519
- iframeEventBridgeElement$,
2520
- hooks$,
2521
2237
  viewportState$,
2522
- settings
2238
+ settings,
2239
+ hookManager
2523
2240
  }) => {
2524
2241
  const commonSpineItem = createCommonSpineItem({
2525
2242
  context,
2526
2243
  item,
2527
2244
  parentElement: containerElement,
2528
- iframeEventBridgeElement$,
2529
- hooks$,
2530
2245
  viewportState$,
2531
- settings
2246
+ settings,
2247
+ hookManager
2532
2248
  });
2533
2249
  const spineItemFrame = commonSpineItem.spineItemFrame;
2534
2250
  let latestContentHeightWhenLoaded;
@@ -2541,12 +2257,12 @@ const createReflowableSpineItem = ({
2541
2257
  (_b = (_a = spineItemFrame.getManipulableFrame()) == null ? void 0 : _a.frame) == null ? void 0 : _b.style.setProperty(`width`, `${pageWidth}px`);
2542
2258
  (_d = (_c = spineItemFrame.getManipulableFrame()) == null ? void 0 : _c.frame) == null ? void 0 : _d.style.setProperty(`height`, `${pageHeight}px`);
2543
2259
  const { viewportDimensions, computedScale = 1 } = commonSpineItem.getViewPortInformation() ?? {};
2544
- const visibleArea = context.getVisibleAreaRect();
2260
+ const visibleArea = context.state.visibleAreaRect;
2545
2261
  const frameElement = (_e = spineItemFrame.getManipulableFrame()) == null ? void 0 : _e.frame;
2546
- const isGloballyPrePaginated = ((_f = context.getManifest()) == null ? void 0 : _f.renditionLayout) === `pre-paginated`;
2262
+ const isGloballyPrePaginated = ((_f = context.manifest) == null ? void 0 : _f.renditionLayout) === `pre-paginated`;
2547
2263
  if ((spineItemFrame == null ? void 0 : spineItemFrame.getIsLoaded()) && (frameElement == null ? void 0 : frameElement.contentDocument) && (frameElement == null ? void 0 : frameElement.contentWindow)) {
2548
2264
  let contentWidth = pageWidth;
2549
- let contentHeight = visibleArea.height + context.getCalculatedInnerMargin();
2265
+ let contentHeight = visibleArea.height + context.state.calculatedInnerMargin;
2550
2266
  frameElement == null ? void 0 : frameElement.style.setProperty(`visibility`, `visible`);
2551
2267
  frameElement == null ? void 0 : frameElement.style.setProperty(`opacity`, `1`);
2552
2268
  if (viewportDimensions) {
@@ -2566,8 +2282,8 @@ const createReflowableSpineItem = ({
2566
2282
  frameElement == null ? void 0 : frameElement.style.setProperty(`transform-origin`, `center center`);
2567
2283
  } else {
2568
2284
  const frameStyle = commonSpineItem.isImageType() ? buildStyleForReflowableImageOnly({
2569
- isScrollable: ((_g = context.getManifest()) == null ? void 0 : _g.renditionFlow) === `scrolled-continuous`,
2570
- enableTouch: settings.getSettings().computedPageTurnMode !== `scrollable`
2285
+ isScrollable: ((_g = context.manifest) == null ? void 0 : _g.renditionFlow) === `scrolled-continuous`,
2286
+ enableTouch: settings.settings.computedPageTurnMode !== `scrollable`
2571
2287
  }) : buildStyleWithMultiColumn(
2572
2288
  commonSpineItem.getDimensionsForReflowableContent(spineItemFrame.isUsingVerticalWriting(), minimumWidth)
2573
2289
  );
@@ -2580,7 +2296,7 @@ const createReflowableSpineItem = ({
2580
2296
  width: minimumWidth,
2581
2297
  height: contentHeight
2582
2298
  });
2583
- } else if (((_h = context.getManifest()) == null ? void 0 : _h.renditionFlow) === `scrolled-continuous`) {
2299
+ } else if (((_h = context.manifest) == null ? void 0 : _h.renditionFlow) === `scrolled-continuous`) {
2584
2300
  contentHeight = frameElement.contentDocument.documentElement.scrollHeight;
2585
2301
  latestContentHeightWhenLoaded = contentHeight;
2586
2302
  spineItemFrame.staticLayout({
@@ -2792,91 +2508,29 @@ const createSpineItem = ({
2792
2508
  item,
2793
2509
  context,
2794
2510
  containerElement,
2795
- iframeEventBridgeElement$,
2796
- hooks$,
2797
2511
  viewportState$,
2798
- settings
2512
+ settings,
2513
+ hookManager
2799
2514
  }) => {
2800
2515
  if (item.renditionLayout === `pre-paginated`) {
2801
2516
  return createPrePaginatedSpineItem({
2802
2517
  item,
2803
2518
  context,
2804
2519
  containerElement,
2805
- iframeEventBridgeElement$,
2806
- hooks$,
2807
2520
  viewportState$,
2808
- settings
2521
+ settings,
2522
+ hookManager
2809
2523
  });
2810
2524
  }
2811
2525
  return createReflowableSpineItem({
2812
2526
  item,
2813
2527
  context,
2814
2528
  containerElement,
2815
- iframeEventBridgeElement$,
2816
- hooks$,
2817
2529
  viewportState$,
2818
- settings
2530
+ settings,
2531
+ hookManager
2819
2532
  });
2820
2533
  };
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
2534
  const ELEMENT_NODE = Node.ELEMENT_NODE;
2881
2535
  const TEXT_NODE = Node.TEXT_NODE;
2882
2536
  const CDATA_SECTION_NODE = Node.CDATA_SECTION_NODE;
@@ -3778,9 +3432,7 @@ const createSpine = ({
3778
3432
  element$,
3779
3433
  context,
3780
3434
  pagination,
3781
- iframeEventBridgeElement$,
3782
3435
  spineItemManager,
3783
- hooks$,
3784
3436
  spineItemLocator,
3785
3437
  spineLocator,
3786
3438
  cfiLocator,
@@ -3788,18 +3440,13 @@ const createSpine = ({
3788
3440
  navigationAdjusted$,
3789
3441
  currentNavigationPosition$,
3790
3442
  viewportState$,
3791
- settings
3443
+ settings,
3444
+ hookManager
3792
3445
  }) => {
3793
3446
  const spineItems$ = new Subject();
3794
3447
  const itemsBeforeDestroySubject$ = new Subject();
3795
3448
  const subject = new Subject();
3796
3449
  const containerElement$ = new BehaviorSubject(noopElement$1);
3797
- const eventsHelper = createEventsHelper({
3798
- context,
3799
- spineItemManager,
3800
- iframeEventBridgeElement$,
3801
- locator: spineLocator
3802
- });
3803
3450
  let selectionSubscription;
3804
3451
  const reload = (manifest) => {
3805
3452
  itemsBeforeDestroySubject$.next();
@@ -3808,11 +3455,10 @@ const createSpine = ({
3808
3455
  const spineItem = createSpineItem({
3809
3456
  item: resource,
3810
3457
  containerElement: containerElement$.getValue(),
3811
- iframeEventBridgeElement$,
3812
3458
  context,
3813
- hooks$,
3814
3459
  viewportState$,
3815
- settings
3460
+ settings,
3461
+ hookManager
3816
3462
  });
3817
3463
  spineItemManager.add(spineItem);
3818
3464
  });
@@ -3831,7 +3477,7 @@ const createSpine = ({
3831
3477
  var _a;
3832
3478
  (_a = spineItemManager.get(id)) == null ? void 0 : _a.manipulateSpineItem(cb);
3833
3479
  };
3834
- context.$.manifest$.pipe(tap(reload), takeUntil$1(context.$.destroy$)).subscribe();
3480
+ context.manifest$.pipe(tap(reload), takeUntil$1(context.destroy$)).subscribe();
3835
3481
  const waitForViewportFree$ = viewportState$.pipe(
3836
3482
  filter((v) => v === `free`),
3837
3483
  take(1)
@@ -3923,7 +3569,7 @@ const createSpine = ({
3923
3569
  Report.error(e);
3924
3570
  return EMPTY;
3925
3571
  }),
3926
- takeUntil$1(context.$.destroy$)
3572
+ takeUntil$1(context.destroy$)
3927
3573
  )
3928
3574
  ).subscribe();
3929
3575
  const itemUpdateOnNavigation$ = navigation$.pipe(
@@ -3969,7 +3615,7 @@ const createSpine = ({
3969
3615
  *
3970
3616
  * The cfi is later adjusted with heavy dom lookup once the viewport is free.
3971
3617
  */
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) : (
3618
+ 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
3619
  /* @todo check ? */
3974
3620
  cfiLocator.getRootCfi(beginSpineItem)
3975
3621
  ),
@@ -3981,7 +3627,7 @@ const createSpine = ({
3981
3627
  spineItem: endSpineItem,
3982
3628
  spineItemIndex: endItemIndex,
3983
3629
  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) : (
3630
+ 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
3631
  /* @todo check ? */
3986
3632
  cfiLocator.getRootCfi(endSpineItem)
3987
3633
  ),
@@ -4005,13 +3651,13 @@ const createSpine = ({
4005
3651
  time2();
4006
3652
  }),
4007
3653
  share(),
4008
- takeUntil$1(context.$.destroy$)
3654
+ takeUntil$1(context.destroy$)
4009
3655
  );
4010
3656
  itemUpdateOnNavigation$.pipe(
4011
3657
  switchMap$1((data) => {
4012
3658
  return adjustPagination(data.position).pipe(takeUntil$1(spineItemManager.$.layout$));
4013
3659
  }),
4014
- takeUntil$1(context.$.destroy$)
3660
+ takeUntil$1(context.destroy$)
4015
3661
  ).subscribe();
4016
3662
  merge(
4017
3663
  /**
@@ -4045,7 +3691,7 @@ const createSpine = ({
4045
3691
  take(1)
4046
3692
  );
4047
3693
  }),
4048
- takeUntil$1(context.$.destroy$)
3694
+ takeUntil$1(context.destroy$)
4049
3695
  ).subscribe();
4050
3696
  const elementSub = element$.pipe().subscribe((element) => {
4051
3697
  const containerElement = createContainerElement(element.ownerDocument);
@@ -4057,7 +3703,6 @@ const createSpine = ({
4057
3703
  locator: spineLocator,
4058
3704
  spineItemLocator,
4059
3705
  cfiLocator,
4060
- normalizeEventForViewport: eventsHelper.normalizeEventForViewport,
4061
3706
  manipulateSpineItems,
4062
3707
  manipulateSpineItem,
4063
3708
  destroy: () => {
@@ -4104,16 +3749,16 @@ const createSpineItemManager = ({ context, settings }) => {
4104
3749
  const orderedSpineItemsSubject$ = new BehaviorSubject([]);
4105
3750
  let focusedSpineItemIndex;
4106
3751
  const layout = () => {
4107
- const manifest = context.getManifest();
3752
+ const manifest = context.manifest;
4108
3753
  const newItemLayoutInformation = [];
4109
3754
  const isGloballyPrePaginated = (manifest == null ? void 0 : manifest.renditionLayout) === `pre-paginated`;
4110
3755
  orderedSpineItemsSubject$.value.reduce(
4111
3756
  ({ horizontalOffset, verticalOffset }, item, index) => {
4112
3757
  let minimumWidth = context.getPageSize().width;
4113
3758
  let blankPagePosition = `none`;
4114
- const itemStartOnNewScreen = horizontalOffset % context.getVisibleAreaRect().width === 0;
3759
+ const itemStartOnNewScreen = horizontalOffset % context.state.visibleAreaRect.width === 0;
4115
3760
  const isLastItem = index === orderedSpineItemsSubject$.value.length - 1;
4116
- if (context.isUsingSpreadMode()) {
3761
+ if (context.state.isUsingSpreadMode) {
4117
3762
  if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && !isLastItem) {
4118
3763
  minimumWidth = context.getPageSize().width * 2;
4119
3764
  }
@@ -4139,10 +3784,10 @@ const createSpineItemManager = ({ context, settings }) => {
4139
3784
  const { width, height } = item.layout({
4140
3785
  minimumWidth,
4141
3786
  blankPagePosition,
4142
- spreadPosition: context.isUsingSpreadMode() ? itemStartOnNewScreen ? context.isRTL() ? `right` : `left` : context.isRTL() ? `left` : `right` : `none`
3787
+ spreadPosition: context.state.isUsingSpreadMode ? itemStartOnNewScreen ? context.isRTL() ? `right` : `left` : context.isRTL() ? `left` : `right` : `none`
4143
3788
  });
4144
- if (settings.getSettings().computedPageTurnDirection === `vertical`) {
4145
- const currentValidEdgeYForVerticalPositioning = itemStartOnNewScreen ? verticalOffset : verticalOffset - context.getVisibleAreaRect().height;
3789
+ if (settings.settings.computedPageTurnDirection === `vertical`) {
3790
+ const currentValidEdgeYForVerticalPositioning = itemStartOnNewScreen ? verticalOffset : verticalOffset - context.state.visibleAreaRect.height;
4146
3791
  const currentValidEdgeXForVerticalPositioning = itemStartOnNewScreen ? 0 : horizontalOffset;
4147
3792
  if (context.isRTL()) {
4148
3793
  item.adjustPositionOfElement({
@@ -4173,8 +3818,8 @@ const createSpineItemManager = ({ context, settings }) => {
4173
3818
  item.adjustPositionOfElement(context.isRTL() ? { right: horizontalOffset, top: 0 } : { left: horizontalOffset, top: 0 });
4174
3819
  newItemLayoutInformation.push({
4175
3820
  ...context.isRTL() ? {
4176
- left: context.getVisibleAreaRect().width - horizontalOffset - width,
4177
- right: context.getVisibleAreaRect().width - horizontalOffset
3821
+ left: context.state.visibleAreaRect.width - horizontalOffset - width,
3822
+ right: context.state.visibleAreaRect.width - horizontalOffset
4178
3823
  } : {
4179
3824
  left: horizontalOffset,
4180
3825
  right: horizontalOffset + width
@@ -4209,9 +3854,9 @@ const createSpineItemManager = ({ context, settings }) => {
4209
3854
  const loadContents = Report.measurePerformance(`loadContents`, 10, (rangeOfIndex) => {
4210
3855
  var _a;
4211
3856
  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`;
3857
+ const numberOfAdjacentSpineItemToPreLoad = settings.settings.numberOfAdjacentSpineItemToPreLoad;
3858
+ const isPrePaginated = ((_a = context.manifest) == null ? void 0 : _a.renditionLayout) === `pre-paginated`;
3859
+ const isUsingFreeScroll = settings.settings.computedPageTurnMode === `scrollable`;
4215
3860
  orderedSpineItemsSubject$.value.forEach((orderedSpineItem, index) => {
4216
3861
  const isBeforeFocusedWithPreload = (
4217
3862
  // we never want to preload anything before on free scroll on flow because it could offset the cursor
@@ -4259,18 +3904,22 @@ const createSpineItemManager = ({ context, settings }) => {
4259
3904
  };
4260
3905
  const add = (spineItem) => {
4261
3906
  orderedSpineItemsSubject$.value.push(spineItem);
4262
- spineItem.$.contentLayout$.pipe(takeUntil$1(context.$.destroy$)).subscribe(() => {
3907
+ spineItem.$.contentLayout$.pipe(takeUntil$1(context.destroy$)).subscribe(() => {
4263
3908
  layout();
4264
3909
  });
4265
3910
  spineItem.$.loaded$.pipe(
4266
3911
  tap(() => {
4267
3912
  if (spineItem.isUsingVerticalWriting()) {
4268
- context.setHasVerticalWriting(true);
3913
+ context.update({
3914
+ hasVerticalWriting: true
3915
+ });
4269
3916
  } else {
4270
- context.setHasVerticalWriting(false);
3917
+ context.update({
3918
+ hasVerticalWriting: false
3919
+ });
4271
3920
  }
4272
3921
  }),
4273
- takeUntil$1(context.$.destroy$)
3922
+ takeUntil$1(context.destroy$)
4274
3923
  ).subscribe();
4275
3924
  spineItem.load();
4276
3925
  };
@@ -4315,7 +3964,154 @@ const createSpineItemManager = ({ context, settings }) => {
4315
3964
  })
4316
3965
  )
4317
3966
  }
4318
- };
3967
+ };
3968
+ };
3969
+ const isHtmlElement = (element) => {
3970
+ return typeof element === `object` && !!element && `nodeType` in element && (element == null ? void 0 : element.nodeType) === Node.ELEMENT_NODE && `innerText` in element;
3971
+ };
3972
+ function createRangeOrCaretFromPoint(doc, startX, startY) {
3973
+ if (`caretPositionFromPoint` in doc) {
3974
+ return doc.caretPositionFromPoint(startX, startY);
3975
+ } else if (typeof doc.caretRangeFromPoint !== `undefined`) {
3976
+ return doc.caretRangeFromPoint(startX, startY);
3977
+ }
3978
+ }
3979
+ const getFirstVisibleNodeForViewport = Report.measurePerformance(
3980
+ `getFirstVisibleNodeForViewport`,
3981
+ 1,
3982
+ (documentOrElement, viewport) => {
3983
+ const element = `body` in documentOrElement ? getFirstVisibleElementForViewport(documentOrElement.body, viewport) : getFirstVisibleElementForViewport(documentOrElement, viewport);
3984
+ const ownerDocument = `createRange` in documentOrElement ? documentOrElement : documentOrElement.ownerDocument;
3985
+ if (element) {
3986
+ let lastValidRange;
3987
+ let lastValidOffset = 0;
3988
+ const range = ownerDocument.createRange();
3989
+ Array.from(element.childNodes).some((childNode) => {
3990
+ range.selectNodeContents(childNode);
3991
+ const rects = range.getClientRects();
3992
+ const visibleRect = getFirstVisibleDOMRect(rects, viewport);
3993
+ if (visibleRect) {
3994
+ lastValidRange = range.cloneRange();
3995
+ const rangeOrCaret = createRangeOrCaretFromPoint(ownerDocument, Math.ceil(visibleRect.left), Math.ceil(visibleRect.top));
3996
+ if (rangeOrCaret && `startContainer` in rangeOrCaret && rangeOrCaret.startContainer === lastValidRange.startContainer) {
3997
+ lastValidOffset = rangeOrCaret.startOffset;
3998
+ }
3999
+ if (rangeOrCaret && `offsetNode` in rangeOrCaret && rangeOrCaret.offsetNode === lastValidRange.startContainer) {
4000
+ lastValidOffset = rangeOrCaret.offset;
4001
+ }
4002
+ return true;
4003
+ }
4004
+ return false;
4005
+ });
4006
+ if (lastValidRange) {
4007
+ return { node: lastValidRange.startContainer, offset: lastValidOffset };
4008
+ }
4009
+ return { node: element, offset: 0 };
4010
+ }
4011
+ return void 0;
4012
+ }
4013
+ );
4014
+ const getFirstVisibleElementForViewport = (element, viewport) => {
4015
+ let lastValidElement;
4016
+ const positionFromViewport = getElementOrNodePositionFromViewPort(element.getBoundingClientRect(), viewport);
4017
+ if (positionFromViewport !== `before` && positionFromViewport !== `after`) {
4018
+ lastValidElement = element;
4019
+ }
4020
+ Array.from(element.children).some((child) => {
4021
+ const childInViewPort = getFirstVisibleElementForViewport(child, viewport);
4022
+ if (childInViewPort) {
4023
+ lastValidElement = childInViewPort;
4024
+ return true;
4025
+ }
4026
+ return false;
4027
+ });
4028
+ return lastValidElement;
4029
+ };
4030
+ function getElementOrNodePositionFromViewPort(domRect, { left, right }) {
4031
+ if (domRect.left <= left && domRect.right <= left)
4032
+ return `before`;
4033
+ if (domRect.left <= left && domRect.right > left && domRect.right <= right)
4034
+ return `partially-before`;
4035
+ if (domRect.left <= right && domRect.right > right)
4036
+ return `partially-after`;
4037
+ if (domRect.left > right)
4038
+ return `after`;
4039
+ return `within`;
4040
+ }
4041
+ function getFirstVisibleDOMRect(domRect, viewport) {
4042
+ return Array.from(domRect).find((domRect2) => {
4043
+ const position = getElementOrNodePositionFromViewPort(domRect2, viewport);
4044
+ if (position !== `before` && position !== `after`) {
4045
+ return true;
4046
+ }
4047
+ return false;
4048
+ });
4049
+ }
4050
+ const getRangeFromNode = (node, offset) => {
4051
+ var _a;
4052
+ if (node.nodeType !== Node.CDATA_SECTION_NODE && node.nodeType !== Node.DOCUMENT_TYPE_NODE) {
4053
+ const range = (_a = node.ownerDocument) == null ? void 0 : _a.createRange();
4054
+ range == null ? void 0 : range.selectNodeContents(node);
4055
+ try {
4056
+ if (offset <= ((range == null ? void 0 : range.endOffset) || 0)) {
4057
+ range == null ? void 0 : range.setStart(node, offset || 0);
4058
+ }
4059
+ } catch (e) {
4060
+ Report.error(e);
4061
+ }
4062
+ return range;
4063
+ }
4064
+ return void 0;
4065
+ };
4066
+ const isPointerEvent = (event) => {
4067
+ var _a, _b, _c, _d, _e;
4068
+ 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)) {
4069
+ const eventView = (_d = (_c = event == null ? void 0 : event.target) == null ? void 0 : _c.ownerDocument) == null ? void 0 : _d.defaultView;
4070
+ if (eventView.PointerEvent) {
4071
+ return event instanceof eventView.PointerEvent;
4072
+ }
4073
+ }
4074
+ if ((event == null ? void 0 : event.view) && ((_e = event == null ? void 0 : event.view) == null ? void 0 : _e.window)) {
4075
+ const eventView = event == null ? void 0 : event.view;
4076
+ if (eventView.PointerEvent) {
4077
+ return event instanceof eventView.PointerEvent;
4078
+ }
4079
+ }
4080
+ return false;
4081
+ };
4082
+ const isMouseEvent = (event) => {
4083
+ var _a, _b, _c, _d, _e;
4084
+ if (isPointerEvent(event))
4085
+ return false;
4086
+ 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)) {
4087
+ const eventView = (_d = (_c = event == null ? void 0 : event.target) == null ? void 0 : _c.ownerDocument) == null ? void 0 : _d.defaultView;
4088
+ if (eventView.MouseEvent) {
4089
+ return event instanceof eventView.MouseEvent;
4090
+ }
4091
+ }
4092
+ if ((event == null ? void 0 : event.view) && ((_e = event == null ? void 0 : event.view) == null ? void 0 : _e.window)) {
4093
+ const eventView = event == null ? void 0 : event.view;
4094
+ if (eventView.MouseEvent) {
4095
+ return event instanceof eventView.MouseEvent;
4096
+ }
4097
+ }
4098
+ return false;
4099
+ };
4100
+ const isTouchEvent = (event) => {
4101
+ var _a, _b, _c, _d, _e;
4102
+ 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)) {
4103
+ const eventView = (_d = (_c = event == null ? void 0 : event.target) == null ? void 0 : _c.ownerDocument) == null ? void 0 : _d.defaultView;
4104
+ if (eventView.TouchEvent) {
4105
+ return event instanceof eventView.TouchEvent;
4106
+ }
4107
+ }
4108
+ if ((event == null ? void 0 : event.view) && ((_e = event == null ? void 0 : event.view) == null ? void 0 : _e.window)) {
4109
+ const eventView = event == null ? void 0 : event.view;
4110
+ if (eventView.TouchEvent) {
4111
+ return event instanceof eventView.TouchEvent;
4112
+ }
4113
+ }
4114
+ return false;
4319
4115
  };
4320
4116
  const createLocationResolver$1 = ({ context }) => {
4321
4117
  const getSafePosition = (unsafeSpineItemPosition, spineItem) => ({
@@ -4537,7 +4333,7 @@ const createNavigationResolver = ({
4537
4333
  { disable: true }
4538
4334
  );
4539
4335
  const getAdjustedPositionForSpread = ({ x, y }) => {
4540
- const isOffsetNotAtEdge = x % context.getVisibleAreaRect().width !== 0;
4336
+ const isOffsetNotAtEdge = x % context.state.visibleAreaRect.width !== 0;
4541
4337
  const correctedX = isOffsetNotAtEdge ? x - context.getPageSize().width : x;
4542
4338
  return { x: correctedX, y };
4543
4339
  };
@@ -4576,7 +4372,7 @@ const createNavigationResolver = ({
4576
4372
  return { x: 0, y: 0 };
4577
4373
  };
4578
4374
  const getNavigationForRightSinglePage = (position) => {
4579
- const pageTurnDirection = settings.getSettings().computedPageTurnDirection;
4375
+ const pageTurnDirection = settings.settings.computedPageTurnDirection;
4580
4376
  const spineItem = locator.getSpineItemFromPosition(position) || spineItemManager.getFocusedSpineItem();
4581
4377
  const defaultNavigation = position;
4582
4378
  if (!spineItem) {
@@ -4595,7 +4391,7 @@ const createNavigationResolver = ({
4595
4391
  }
4596
4392
  };
4597
4393
  const getNavigationForLeftSinglePage = (position) => {
4598
- const pageTurnDirection = settings.getSettings().computedPageTurnDirection;
4394
+ const pageTurnDirection = settings.settings.computedPageTurnDirection;
4599
4395
  const spineItem = locator.getSpineItemFromPosition(position) || spineItemManager.getFocusedSpineItem();
4600
4396
  const defaultNavigation = { ...position, spineItem };
4601
4397
  if (!spineItem) {
@@ -4619,7 +4415,7 @@ const createNavigationResolver = ({
4619
4415
  if ((spineItemOnPosition == null ? void 0 : spineItemOnPosition.isUsingVerticalWriting()) && position.x === navigation.x) {
4620
4416
  return getAdjustedPositionForSpread(navigation);
4621
4417
  }
4622
- if (context.isUsingSpreadMode()) {
4418
+ if (context.state.isUsingSpreadMode) {
4623
4419
  if ((spineItemOnPosition == null ? void 0 : spineItemOnPosition.isUsingVerticalWriting()) && position.x !== navigation.x) {
4624
4420
  return getAdjustedPositionForSpread(
4625
4421
  wrapPositionWithSafeEdge(
@@ -4633,7 +4429,7 @@ const createNavigationResolver = ({
4633
4429
  )
4634
4430
  );
4635
4431
  }
4636
- if (settings.getSettings().computedPageTurnDirection === `vertical` && position.y !== navigation.y) {
4432
+ if (settings.settings.computedPageTurnDirection === `vertical` && position.y !== navigation.y) {
4637
4433
  return getAdjustedPositionForSpread(navigation);
4638
4434
  }
4639
4435
  const doubleNavigation = getNavigationForRightSinglePage(navigation);
@@ -4647,7 +4443,7 @@ const createNavigationResolver = ({
4647
4443
  if ((spineItemOnPosition == null ? void 0 : spineItemOnPosition.isUsingVerticalWriting()) && position.x === navigation.x) {
4648
4444
  return getAdjustedPositionForSpread(navigation);
4649
4445
  }
4650
- if (context.isUsingSpreadMode()) {
4446
+ if (context.state.isUsingSpreadMode) {
4651
4447
  if ((spineItemOnPosition == null ? void 0 : spineItemOnPosition.isUsingVerticalWriting()) && position.x !== navigation.x) {
4652
4448
  return getAdjustedPositionForSpread(
4653
4449
  wrapPositionWithSafeEdge(
@@ -4655,7 +4451,7 @@ const createNavigationResolver = ({
4655
4451
  )
4656
4452
  );
4657
4453
  }
4658
- if (settings.getSettings().computedPageTurnDirection === `vertical` && position.y !== navigation.y) {
4454
+ if (settings.settings.computedPageTurnDirection === `vertical` && position.y !== navigation.y) {
4659
4455
  return getAdjustedPositionForSpread(navigation);
4660
4456
  }
4661
4457
  const doubleNavigation = getNavigationForLeftSinglePage(navigation);
@@ -4668,7 +4464,7 @@ const createNavigationResolver = ({
4668
4464
  try {
4669
4465
  const validUrl = url instanceof URL ? url : new URL(url);
4670
4466
  const urlWithoutAnchor = `${validUrl.origin}${validUrl.pathname}`;
4671
- const existingSpineItem = (_a = context.getManifest()) == null ? void 0 : _a.spineItems.find((item) => item.href === urlWithoutAnchor);
4467
+ const existingSpineItem = (_a = context.manifest) == null ? void 0 : _a.spineItems.find((item) => item.href === urlWithoutAnchor);
4672
4468
  if (existingSpineItem) {
4673
4469
  const spineItem = spineItemManager.get(existingSpineItem.id);
4674
4470
  if (spineItem) {
@@ -4697,15 +4493,15 @@ const createNavigationResolver = ({
4697
4493
  return { x: 0, y: 0 };
4698
4494
  };
4699
4495
  const getMostPredominantNavigationForPosition = (viewportPosition) => {
4700
- const pageTurnDirection = settings.getSettings().computedPageTurnDirection;
4496
+ const pageTurnDirection = settings.settings.computedPageTurnDirection;
4701
4497
  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;
4498
+ const triggerXPosition = pageTurnDirection === `horizontal` ? viewportPosition.x + context.state.visibleAreaRect.width * triggerPercentage : 0;
4499
+ const triggerYPosition = pageTurnDirection === `horizontal` ? 0 : viewportPosition.y + context.state.visibleAreaRect.height * triggerPercentage;
4704
4500
  const midScreenPositionSafePosition = wrapPositionWithSafeEdge({ x: triggerXPosition, y: triggerYPosition });
4705
4501
  return getNavigationForPosition(midScreenPositionSafePosition);
4706
4502
  };
4707
4503
  const isNavigationGoingForwardFrom = (to, from2) => {
4708
- const pageTurnDirection = settings.getSettings().computedPageTurnDirection;
4504
+ const pageTurnDirection = settings.settings.computedPageTurnDirection;
4709
4505
  if (pageTurnDirection === `vertical`) {
4710
4506
  return to.y > from2.y;
4711
4507
  }
@@ -4749,14 +4545,14 @@ const createScrollViewportNavigator = ({
4749
4545
  );
4750
4546
  const adjustReadingOffset = ({ x, y }) => {
4751
4547
  var _a;
4752
- if (settings.getSettings().computedPageTurnMode === `scrollable`) {
4548
+ if (settings.settings.computedPageTurnMode === `scrollable`) {
4753
4549
  lastScrollWasProgrammaticallyTriggered = true;
4754
4550
  (_a = element$.getValue()) == null ? void 0 : _a.scrollTo({ left: x, top: y });
4755
4551
  return true;
4756
4552
  }
4757
4553
  return false;
4758
4554
  };
4759
- const runOnFreePageTurnModeOnly$ = (source) => settings.$.settings$.pipe(
4555
+ const runOnFreePageTurnModeOnly$ = (source) => settings.settings$.pipe(
4760
4556
  map$1(({ computedPageTurnMode }) => computedPageTurnMode),
4761
4557
  distinctUntilChanged(),
4762
4558
  switchMap$1((mode) => iif(() => mode === `controlled`, EMPTY, source))
@@ -4766,7 +4562,7 @@ const createScrollViewportNavigator = ({
4766
4562
  filter(isDefined),
4767
4563
  switchMap$1((element) => fromEvent(element, `scroll`))
4768
4564
  )
4769
- ).pipe(onlyUserScrollFilter, share(), takeUntil$1(context.$.destroy$));
4565
+ ).pipe(onlyUserScrollFilter, share(), takeUntil$1(context.destroy$));
4770
4566
  const getScaledDownPosition = ({ x, y }) => {
4771
4567
  var _a, _b;
4772
4568
  const spineElement = spine.getElement();
@@ -4814,7 +4610,7 @@ const createScrollViewportNavigator = ({
4814
4610
  const userScrollEnd$ = userScroll$.pipe(
4815
4611
  debounceTime$1(SCROLL_FINISHED_DEBOUNCE_TIMEOUT, animationFrameScheduler),
4816
4612
  share(),
4817
- takeUntil$1(context.$.destroy$)
4613
+ takeUntil$1(context.destroy$)
4818
4614
  );
4819
4615
  const state$ = merge(
4820
4616
  userScroll$.pipe(
@@ -4907,7 +4703,7 @@ const createManualViewportNavigator = ({
4907
4703
  filter((e) => e.type === `pageIndex`),
4908
4704
  filter(() => {
4909
4705
  var _a;
4910
- if (((_a = context.getManifest()) == null ? void 0 : _a.renditionLayout) === `reflowable`) {
4706
+ if (((_a = context.manifest) == null ? void 0 : _a.renditionLayout) === `reflowable`) {
4911
4707
  Report.warn(`This method only works for pre-paginated content`);
4912
4708
  return false;
4913
4709
  }
@@ -5041,11 +4837,11 @@ const createPanViewportNavigator = ({
5041
4837
  `${NAMESPACE$1} moveTo`,
5042
4838
  5,
5043
4839
  (delta, { final, start } = {}) => {
5044
- if (settings.getSettings().computedPageTurnMode === `scrollable`) {
4840
+ if (settings.settings.computedPageTurnMode === `scrollable`) {
5045
4841
  Report.warn(`pan control is not available on free page turn mode`);
5046
4842
  return;
5047
4843
  }
5048
- const pageTurnDirection = settings.getSettings().computedPageTurnDirection;
4844
+ const pageTurnDirection = settings.settings.computedPageTurnDirection;
5049
4845
  if (start) {
5050
4846
  stateSubject$.next(`start`);
5051
4847
  movingLastDelta = { x: 0, y: 0 };
@@ -5105,7 +4901,7 @@ const createPanViewportNavigator = ({
5105
4901
  );
5106
4902
  const snapNavigation$ = navigationTriggerSubject$.pipe(
5107
4903
  filter((e) => e.type === `snap`),
5108
- withLatestFrom$1(settings.$.settings$),
4904
+ withLatestFrom$1(settings.settings$),
5109
4905
  switchMap$1(
5110
4906
  ([
5111
4907
  {
@@ -5113,11 +4909,11 @@ const createPanViewportNavigator = ({
5113
4909
  },
5114
4910
  { navigationSnapThreshold }
5115
4911
  ]) => {
5116
- const pageTurnDirection = settings.getSettings().computedPageTurnDirection;
4912
+ const pageTurnDirection = settings.settings.computedPageTurnDirection;
5117
4913
  const movingForward = navigator2.isNavigationGoingForwardFrom(to, from2);
5118
4914
  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;
4915
+ const triggerXPosition = pageTurnDirection === `horizontal` ? to.x + context.state.visibleAreaRect.width * triggerPercentage : 0;
4916
+ const triggerYPosition = pageTurnDirection === `horizontal` ? 0 : to.y + context.state.visibleAreaRect.height * triggerPercentage;
5121
4917
  const midScreenPositionSafePosition = navigator2.wrapPositionWithSafeEdge({
5122
4918
  x: triggerXPosition,
5123
4919
  y: triggerYPosition
@@ -5154,7 +4950,7 @@ const createViewportNavigator = ({
5154
4950
  parentElement$,
5155
4951
  cfiLocator,
5156
4952
  spineLocator,
5157
- hooks$,
4953
+ hookManager,
5158
4954
  spine,
5159
4955
  settings
5160
4956
  }) => {
@@ -5176,7 +4972,7 @@ const createViewportNavigator = ({
5176
4972
  const adjustNavigationSubject$ = new Subject();
5177
4973
  const getCurrentViewportPosition = Report.measurePerformance(`${NAMESPACE} getCurrentViewportPosition`, 1, () => {
5178
4974
  var _a;
5179
- if (settings.getSettings().computedPageTurnMode === `scrollable`) {
4975
+ if (settings.settings.computedPageTurnMode === `scrollable`) {
5180
4976
  return scrollViewportNavigator.getCurrentViewportPosition();
5181
4977
  }
5182
4978
  const { x, y } = ((_a = element$.getValue()) == null ? void 0 : _a.getBoundingClientRect()) ?? { x: 0, y: 0 };
@@ -5220,13 +5016,13 @@ const createViewportNavigator = ({
5220
5016
  const viewportNavigatorsSharedState$ = merge(...viewportNavigators.map(({ $: { state$: state$2 } }) => state$2));
5221
5017
  let lastUserExpectedNavigation;
5222
5018
  const makeItHot = (source$) => {
5223
- source$.pipe(takeUntil$1(context.$.destroy$)).subscribe();
5019
+ source$.pipe(takeUntil$1(context.destroy$)).subscribe();
5224
5020
  return source$;
5225
5021
  };
5226
5022
  const adjustReadingOffset = Report.measurePerformance(
5227
5023
  `adjustReadingOffset`,
5228
5024
  2,
5229
- ({ x, y }, hooks) => {
5025
+ ({ x, y }) => {
5230
5026
  const element = element$.getValue();
5231
5027
  if (!element)
5232
5028
  throw new Error("Invalid element");
@@ -5237,11 +5033,7 @@ const createViewportNavigator = ({
5237
5033
  if (!isAdjusted) {
5238
5034
  element.style.transform = `translate3d(${-x}px, -${y}px, 0)`;
5239
5035
  }
5240
- hooks.forEach((hook) => {
5241
- if (hook.name === `onViewportOffsetAdjust`) {
5242
- hook.fn();
5243
- }
5244
- });
5036
+ hookManager.execute("onViewportOffsetAdjust", void 0, {});
5245
5037
  },
5246
5038
  { disable: true }
5247
5039
  );
@@ -5249,7 +5041,7 @@ const createViewportNavigator = ({
5249
5041
  const lastCfi = pagination.getPaginationInfo().beginCfi;
5250
5042
  let adjustedSpinePosition = currentNavigationPositionSubject$.value;
5251
5043
  const offsetInSpineItem = 0;
5252
- if (settings.getSettings().computedPageTurnMode === `scrollable`) {
5044
+ if (settings.settings.computedPageTurnMode === `scrollable`) {
5253
5045
  adjustedSpinePosition = scrollViewportNavigator.getNavigationForPosition(getCurrentViewportPosition());
5254
5046
  } else if ((lastUserExpectedNavigation == null ? void 0 : lastUserExpectedNavigation.type) === `navigate-from-cfi`) {
5255
5047
  adjustedSpinePosition = navigator2.getNavigationForCfi(lastUserExpectedNavigation.data);
@@ -5294,7 +5086,7 @@ const createViewportNavigator = ({
5294
5086
  layoutSubject$.subscribe(() => {
5295
5087
  currentViewportPositionMemoUnused = void 0;
5296
5088
  });
5297
- const layoutChangeSettings$ = settings.$.settings$.pipe(
5089
+ const layoutChangeSettings$ = settings.settings$.pipe(
5298
5090
  mapKeysTo([`computedPageTurnDirection`, `computedPageTurnMode`, `numberOfAdjacentSpineItemToPreLoad`]),
5299
5091
  distinctUntilChanged(isShallowEqual),
5300
5092
  skip(1)
@@ -5302,7 +5094,7 @@ const createViewportNavigator = ({
5302
5094
  const layout$ = merge(layoutSubject$, layoutChangeSettings$).pipe(
5303
5095
  withLatestFrom(element$),
5304
5096
  tap(([, element]) => {
5305
- if (settings.getSettings().computedPageTurnMode === `scrollable`) {
5097
+ if (settings.settings.computedPageTurnMode === `scrollable`) {
5306
5098
  element.style.removeProperty(`transform`);
5307
5099
  element.style.removeProperty(`transition`);
5308
5100
  element.style.overflow = `scroll`;
@@ -5354,11 +5146,11 @@ const createViewportNavigator = ({
5354
5146
  return { ...event, lastUserExpectedNavigation };
5355
5147
  }),
5356
5148
  share(),
5357
- takeUntil$1(context.$.destroy$)
5149
+ takeUntil$1(context.destroy$)
5358
5150
  );
5359
5151
  const navigationWhichRequireManualAdjust$ = navigation$.pipe(
5360
5152
  filter(({ triggeredBy }) => {
5361
- if (triggeredBy === `scroll` || settings.getSettings().computedPageTurnMode === `scrollable` && triggeredBy === `adjust`) {
5153
+ if (triggeredBy === `scroll` || settings.settings.computedPageTurnMode === `scrollable` && triggeredBy === `adjust`) {
5362
5154
  return false;
5363
5155
  } else {
5364
5156
  return true;
@@ -5370,7 +5162,7 @@ const createViewportNavigator = ({
5370
5162
  navigationWhichRequireManualAdjust$
5371
5163
  ).pipe(
5372
5164
  map$1(({ animation, position }) => {
5373
- const shouldAnimate = !(!animation || animation === `turn` && settings.getSettings().computedPageTurnAnimation === `none`);
5165
+ const shouldAnimate = !(!animation || animation === `turn` && settings.settings.computedPageTurnAnimation === `none`);
5374
5166
  return {
5375
5167
  type: `manualAdjust`,
5376
5168
  shouldAnimate,
@@ -5392,8 +5184,8 @@ const createViewportNavigator = ({
5392
5184
  switchMap$1(([, currentEvent]) => {
5393
5185
  if ((currentEvent == null ? void 0 : currentEvent.type) !== `manualAdjust`)
5394
5186
  return EMPTY;
5395
- const animationDuration = currentEvent.animation === `snap` ? settings.getSettings().computedSnapAnimationDuration : settings.getSettings().computedPageTurnAnimationDuration;
5396
- const pageTurnAnimation = currentEvent.animation === `snap` ? `slide` : settings.getSettings().computedPageTurnAnimation;
5187
+ const animationDuration = currentEvent.animation === `snap` ? settings.settings.computedSnapAnimationDuration : settings.settings.computedPageTurnAnimationDuration;
5188
+ const pageTurnAnimation = currentEvent.animation === `snap` ? `slide` : settings.settings.computedPageTurnAnimation;
5397
5189
  return of(currentEvent).pipe(
5398
5190
  /**
5399
5191
  * @important
@@ -5427,23 +5219,22 @@ const createViewportNavigator = ({
5427
5219
  * need to adjust to anchor to the payload position. This is because we use viewport computed position,
5428
5220
  * not the value set by `setProperty`
5429
5221
  */
5430
- withLatestFrom(hooks$),
5431
- tap(([data, hooks]) => {
5222
+ tap((data) => {
5432
5223
  if (pageTurnAnimation !== `fade`) {
5433
- adjustReadingOffset(data.position, hooks);
5224
+ adjustReadingOffset(data.position);
5434
5225
  }
5435
5226
  }),
5436
5227
  currentEvent.shouldAnimate ? delay(animationDuration / 2, animationFrameScheduler) : identity,
5437
- tap(([data, hooks]) => {
5228
+ tap((data) => {
5438
5229
  if (pageTurnAnimation === `fade`) {
5439
- adjustReadingOffset(data.position, hooks);
5230
+ adjustReadingOffset(data.position);
5440
5231
  element$.getValue().style.setProperty(`opacity`, `1`);
5441
5232
  }
5442
5233
  }),
5443
5234
  currentEvent.shouldAnimate ? delay(animationDuration / 2, animationFrameScheduler) : identity,
5444
- tap(([data, hooks]) => {
5235
+ tap((data) => {
5445
5236
  if (pageTurnAnimation === `fade`) {
5446
- adjustReadingOffset(data.position, hooks);
5237
+ adjustReadingOffset(data.position);
5447
5238
  }
5448
5239
  }),
5449
5240
  takeUntil$1(
@@ -5455,7 +5246,7 @@ const createViewportNavigator = ({
5455
5246
  );
5456
5247
  }),
5457
5248
  share(),
5458
- takeUntil$1(context.$.destroy$)
5249
+ takeUntil$1(context.destroy$)
5459
5250
  );
5460
5251
  const adjustmentState$ = merge(
5461
5252
  merge(manualAdjust$).pipe(map$1(() => `start`)),
@@ -5510,7 +5301,7 @@ const createViewportNavigator = ({
5510
5301
  share()
5511
5302
  );
5512
5303
  const parentElementSub = parentElement$.pipe(filter(isDefined), withLatestFrom(spine.element$)).subscribe(([parentElement, spineElement]) => {
5513
- const element = createElement(parentElement.ownerDocument, hooks$);
5304
+ const element = createElement(parentElement.ownerDocument, hookManager);
5514
5305
  element.appendChild(spineElement);
5515
5306
  parentElement.appendChild(element);
5516
5307
  element$.next(element);
@@ -5546,19 +5337,15 @@ const createViewportNavigator = ({
5546
5337
  }
5547
5338
  };
5548
5339
  };
5549
- const createElement = (doc, hooks$) => {
5340
+ const createElement = (doc, hookManager) => {
5550
5341
  const element = doc.createElement(`div`);
5551
5342
  element.style.cssText = `
5552
5343
  height: 100%;
5553
5344
  position: relative;
5554
5345
  `;
5555
5346
  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);
5347
+ hookManager.execute("viewportNavigator.onBeforeContainerCreated", void 0, { element });
5348
+ return element;
5562
5349
  };
5563
5350
  const createLocationResolver = ({
5564
5351
  spineItemManager,
@@ -5599,7 +5386,7 @@ const createLocationResolver = ({
5599
5386
  const spineItem = spineItemManager.getAll().find((item) => {
5600
5387
  const { left, right, bottom, top } = spineItemManager.getAbsolutePositionOf(item);
5601
5388
  const isWithinXAxis = position.x >= left && position.x < right;
5602
- if (settings.getSettings().computedPageTurnDirection === `horizontal`) {
5389
+ if (settings.settings.computedPageTurnDirection === `horizontal`) {
5603
5390
  return isWithinXAxis;
5604
5391
  } else {
5605
5392
  return isWithinXAxis && position.y >= top && position.y < bottom;
@@ -5626,7 +5413,7 @@ const createLocationResolver = ({
5626
5413
  if (itemAtPositionIndex === void 0)
5627
5414
  return void 0;
5628
5415
  let endPosition = position;
5629
- if (context.isUsingSpreadMode()) {
5416
+ if (context.state.isUsingSpreadMode) {
5630
5417
  endPosition = { x: position.x + context.getPageSize().width, y: position.y };
5631
5418
  }
5632
5419
  const endItemIndex = spineItemManager.getSpineItemIndex(getSpineItemFromPosition(endPosition) || spineItemManager.getFocusedSpineItem()) ?? itemAtPositionIndex;
@@ -5747,80 +5534,170 @@ const createCfiLocator = ({
5747
5534
  generateFromRange
5748
5535
  };
5749
5536
  };
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`,
5537
+ const getComputedSettings = (settings, context) => {
5538
+ const manifest = context.manifest;
5539
+ const hasVerticalWriting = context.state.hasVerticalWriting ?? false;
5540
+ const computedSettings = {
5541
+ computedPageTurnDirection: settings.pageTurnDirection,
5542
+ computedPageTurnAnimation: settings.pageTurnAnimation,
5761
5543
  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
- }
5544
+ computedPageTurnAnimationDuration: 0,
5545
+ computedSnapAnimationDuration: 0
5792
5546
  };
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))) {
5547
+ if ((manifest == null ? void 0 : manifest.renditionFlow) === `scrolled-continuous`) {
5548
+ computedSettings.computedPageTurnMode = `scrollable`;
5549
+ computedSettings.computedPageTurnDirection = `vertical`;
5550
+ } else if (manifest && settings.pageTurnMode === `scrollable` && (manifest.renditionLayout !== `pre-paginated` || !areAllItemsPrePaginated(manifest))) {
5802
5551
  Report.warn(`pageTurnMode ${settings.pageTurnMode} incompatible with current book, switching back to default`);
5803
- settings.computedPageTurnAnimation = `none`;
5804
- settings.computedPageTurnMode = `controlled`;
5552
+ computedSettings.computedPageTurnAnimation = `none`;
5553
+ computedSettings.computedPageTurnMode = `controlled`;
5805
5554
  } else if (settings.pageTurnMode === `scrollable`) {
5806
- settings.computedPageTurnMode = `scrollable`;
5807
- settings.computedPageTurnDirection = `vertical`;
5555
+ computedSettings.computedPageTurnMode = `scrollable`;
5556
+ computedSettings.computedPageTurnDirection = `vertical`;
5808
5557
  }
5809
- if (hasVerticalWriting && settings.computedPageTurnAnimation === `slide`) {
5558
+ if (hasVerticalWriting && computedSettings.computedPageTurnAnimation === `slide`) {
5810
5559
  Report.warn(
5811
- `pageTurnAnimation ${settings.computedPageTurnAnimation} incompatible with current book, switching back to default`
5560
+ `pageTurnAnimation ${computedSettings.computedPageTurnAnimation} incompatible with current book, switching back to default`
5812
5561
  );
5813
- settings.computedPageTurnAnimation = `none`;
5562
+ computedSettings.computedPageTurnAnimation = `none`;
5814
5563
  }
5815
- if (settings.computedPageTurnMode === `scrollable`) {
5816
- settings.computedPageTurnAnimationDuration = 0;
5817
- settings.computedPageTurnAnimation = `none`;
5564
+ if (computedSettings.computedPageTurnMode === `scrollable`) {
5565
+ computedSettings.computedPageTurnAnimationDuration = 0;
5566
+ computedSettings.computedPageTurnAnimation = `none`;
5818
5567
  } else {
5819
- settings.computedPageTurnAnimationDuration = settings.pageTurnAnimationDuration !== void 0 ? settings.pageTurnAnimationDuration : 300;
5568
+ computedSettings.computedPageTurnAnimationDuration = settings.pageTurnAnimationDuration !== void 0 ? settings.pageTurnAnimationDuration : 300;
5820
5569
  }
5570
+ return computedSettings;
5821
5571
  };
5822
- const IFRAME_EVENT_BRIDGE_ELEMENT_ID = `proseReaderIframeEventBridgeElement`;
5823
- const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5572
+ const defaultSettings = {
5573
+ forceSinglePageMode: false,
5574
+ pageTurnAnimation: `none`,
5575
+ // computedPageTurnAnimation: `none`,
5576
+ pageTurnDirection: `horizontal`,
5577
+ // computedPageTurnDirection: `horizontal`,
5578
+ pageTurnAnimationDuration: void 0,
5579
+ // computedPageTurnAnimationDuration: 0,
5580
+ pageTurnMode: `controlled`,
5581
+ // computedPageTurnMode: `controlled`,
5582
+ // computedSnapAnimationDuration: 300,
5583
+ navigationSnapThreshold: 0.3,
5584
+ numberOfAdjacentSpineItemToPreLoad: 0
5585
+ };
5586
+ class SettingsManager {
5587
+ constructor(initialSettings, context) {
5588
+ this._context = context;
5589
+ const settingsWithDefaults = {
5590
+ ...defaultSettings,
5591
+ ...initialSettings
5592
+ };
5593
+ const computedSettings = getComputedSettings(settingsWithDefaults, context);
5594
+ const settings = { ...settingsWithDefaults, ...computedSettings };
5595
+ this._settingsSubject$ = new BehaviorSubject(settings);
5596
+ this.settings$ = this._settingsSubject$.asObservable().pipe(distinctUntilChanged(isShallowEqual));
5597
+ const recomputeSettingsOnContextChange$ = combineLatest([context.hasVerticalWriting$, context.manifest$]).pipe(
5598
+ tap(() => {
5599
+ this._updateSettings(this.settings);
5600
+ })
5601
+ );
5602
+ const updateContextOnSettingsChanges$ = this._settingsSubject$.pipe(
5603
+ tap(({ forceSinglePageMode }) => {
5604
+ context.update({ forceSinglePageMode });
5605
+ })
5606
+ );
5607
+ merge(recomputeSettingsOnContextChange$, updateContextOnSettingsChanges$).pipe(takeUntil$1(context.destroy$)).subscribe();
5608
+ }
5609
+ // @see https://github.com/microsoft/TypeScript/issues/17293
5610
+ _updateSettings(settings) {
5611
+ const computed = getComputedSettings(settings, this._context);
5612
+ const newMergedSettings = { ...settings, ...computed };
5613
+ this._settingsSubject$.next(newMergedSettings);
5614
+ }
5615
+ setSettings(settings) {
5616
+ if (Object.keys(settings).length === 0)
5617
+ return;
5618
+ const newMergedSettings = { ...this._settingsSubject$.value, ...settings };
5619
+ this._updateSettings(newMergedSettings);
5620
+ }
5621
+ get settings() {
5622
+ return this._settingsSubject$.getValue();
5623
+ }
5624
+ destroy() {
5625
+ this._settingsSubject$.complete();
5626
+ }
5627
+ }
5628
+ class HookManager {
5629
+ constructor() {
5630
+ this._hooks = [];
5631
+ this._hookExecutions = [];
5632
+ }
5633
+ /**
5634
+ * Will:
5635
+ * - call destroy function for every execution of this specific hook
5636
+ * - remove the hook for further calls
5637
+ */
5638
+ _deregister(hookToDeregister) {
5639
+ this._hooks = this._hooks.filter((hook) => hook !== hookToDeregister);
5640
+ return this.destroy(hookToDeregister.name, void 0, hookToDeregister);
5641
+ }
5642
+ /**
5643
+ * Ideal when your logic only needs to apply something to the item when it's loaded.
5644
+ * You can manipulate your item later if you need to update it and trigger a layout.
5645
+ * This logic will not run every time there is a layout.
5646
+ */
5647
+ register(name, fn) {
5648
+ const hook = {
5649
+ name,
5650
+ runFn: (params) => {
5651
+ const returnValue = fn(params);
5652
+ if (!returnValue)
5653
+ return of(void 0);
5654
+ return returnValue;
5655
+ }
5656
+ };
5657
+ this._hooks.push(hook);
5658
+ return () => {
5659
+ this._deregister(hook);
5660
+ };
5661
+ }
5662
+ execute(name, id, params) {
5663
+ const hooks = this._hooks.filter((hook) => name === hook.name);
5664
+ const runFns = hooks.map((hook) => {
5665
+ let userDestroyFn = () => of(void 0);
5666
+ const destroySubject = new Subject();
5667
+ const destroy = (fn) => {
5668
+ userDestroyFn = fn;
5669
+ };
5670
+ const destroyFn = () => {
5671
+ destroySubject.next();
5672
+ destroySubject.complete();
5673
+ const result = userDestroyFn();
5674
+ return result ?? of(void 0);
5675
+ };
5676
+ const execution = hook.runFn({ ...params, destroy$: destroySubject.asObservable(), destroy });
5677
+ this._hookExecutions.push({
5678
+ name,
5679
+ id,
5680
+ destroyFn,
5681
+ ref: hook
5682
+ });
5683
+ return execution;
5684
+ });
5685
+ return combineLatest(runFns);
5686
+ }
5687
+ destroy(name, id, ref) {
5688
+ const instances = this._hookExecutions.filter(
5689
+ (hookInstance) => (
5690
+ // by ref is higher priority
5691
+ ref && hookInstance.ref === ref || // otherwise we refine by name and eventually by id
5692
+ name === hookInstance.name && (!id || id && id === hookInstance.id)
5693
+ )
5694
+ );
5695
+ this._hookExecutions = this._hookExecutions.filter((instance) => !instances.includes(instance));
5696
+ const destroyFns = instances.map(({ destroyFn }) => destroyFn());
5697
+ return combineLatest(destroyFns);
5698
+ }
5699
+ }
5700
+ const createReader = (inputSettings) => {
5824
5701
  const stateSubject$ = new BehaviorSubject({
5825
5702
  supportedPageTurnAnimation: [`fade`, `none`, `slide`],
5826
5703
  supportedPageTurnMode: [`controlled`, `scrollable`],
@@ -5829,24 +5706,23 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5829
5706
  });
5830
5707
  const destroy$ = new Subject();
5831
5708
  const selectionSubject$ = new Subject();
5832
- const hooksSubject$ = new BehaviorSubject(initialHooks || []);
5833
5709
  const navigationSubject = new Subject();
5834
5710
  const navigationAdjustedSubject = new Subject();
5835
5711
  const currentNavigationPositionSubject$ = new BehaviorSubject({ x: 0, y: 0 });
5836
5712
  const viewportStateSubject = new BehaviorSubject(`free`);
5837
- const settings = createSettings(inputSettings);
5838
- const context = createContext(settings);
5839
- const spineItemManager = createSpineItemManager({ context, settings });
5713
+ const hookManager = new HookManager();
5714
+ const context = new Context();
5715
+ const settingsManager = new SettingsManager(inputSettings, context);
5716
+ const spineItemManager = createSpineItemManager({ context, settings: settingsManager });
5840
5717
  const pagination = createPagination({ context, spineItemManager });
5841
5718
  const elementSubject$ = new BehaviorSubject(void 0);
5842
5719
  const element$ = elementSubject$.pipe(filter(isDefined));
5843
- const iframeEventBridgeElement$ = new BehaviorSubject(void 0);
5844
5720
  const spineItemLocator = createLocationResolver$1({ context });
5845
5721
  const spineLocator = createLocationResolver({
5846
5722
  context,
5847
5723
  spineItemManager,
5848
5724
  spineItemLocator,
5849
- settings
5725
+ settings: settingsManager
5850
5726
  });
5851
5727
  const cfiLocator = createCfiLocator({
5852
5728
  spineItemManager,
@@ -5856,19 +5732,18 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5856
5732
  const navigation$ = navigationSubject.asObservable();
5857
5733
  const spine = createSpine({
5858
5734
  element$,
5859
- iframeEventBridgeElement$,
5860
5735
  context,
5861
- settings,
5736
+ settings: settingsManager,
5862
5737
  pagination,
5863
5738
  spineItemManager,
5864
- hooks$: hooksSubject$,
5865
5739
  navigation$,
5866
5740
  spineLocator,
5867
5741
  spineItemLocator,
5868
5742
  cfiLocator,
5869
5743
  navigationAdjusted$: navigationAdjustedSubject.asObservable(),
5870
5744
  viewportState$: viewportStateSubject.asObservable(),
5871
- currentNavigationPosition$: currentNavigationPositionSubject$.asObservable()
5745
+ currentNavigationPosition$: currentNavigationPositionSubject$.asObservable(),
5746
+ hookManager
5872
5747
  });
5873
5748
  const viewportNavigator = createViewportNavigator({
5874
5749
  context,
@@ -5877,9 +5752,9 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5877
5752
  parentElement$: elementSubject$,
5878
5753
  cfiLocator,
5879
5754
  spineLocator,
5880
- hooks$: hooksSubject$,
5755
+ hookManager,
5881
5756
  spine,
5882
- settings
5757
+ settings: settingsManager
5883
5758
  });
5884
5759
  viewportNavigator.$.state$.subscribe(viewportStateSubject);
5885
5760
  viewportNavigator.$.navigation$.subscribe(navigationSubject);
@@ -5905,30 +5780,29 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5905
5780
  element.style.height = `${dimensions.height - marginTop - marginBottom}px`;
5906
5781
  element.style.width = `${containerElementEvenWidth - 2 * margin}px`;
5907
5782
  const elementRect = element.getBoundingClientRect();
5908
- context.setVisibleAreaRect({
5909
- x: elementRect.x,
5910
- y: elementRect.y,
5911
- width: containerElementEvenWidth,
5912
- height: dimensions.height
5783
+ context.update({
5784
+ visibleAreaRect: {
5785
+ x: elementRect.x,
5786
+ y: elementRect.y,
5787
+ width: containerElementEvenWidth,
5788
+ height: dimensions.height
5789
+ }
5913
5790
  });
5914
5791
  viewportNavigator.layout();
5915
5792
  };
5916
5793
  const load = (manifest, loadOptions) => {
5917
5794
  var _a;
5918
- if (context.getManifest()) {
5795
+ if (context.manifest) {
5919
5796
  Report.warn(`loading a new book is not supported yet`);
5920
5797
  return;
5921
5798
  }
5922
5799
  Report.log(`load`, { manifest, loadOptions });
5923
5800
  const element = createWrapperElement(loadOptions.containerElement);
5924
- const iframeEventBridgeElement = createIframeEventBridgeElement(loadOptions.containerElement);
5925
5801
  if (loadOptions.containerElement !== ((_a = elementSubject$.getValue()) == null ? void 0 : _a.parentElement)) {
5926
5802
  elementSubject$.next(element);
5927
- iframeEventBridgeElement$.next(iframeEventBridgeElement);
5928
5803
  loadOptions.containerElement.appendChild(element);
5929
- element.appendChild(iframeEventBridgeElement);
5930
5804
  }
5931
- context.load(manifest, loadOptions);
5805
+ context.update({ manifest, ...loadOptions, forceSinglePageMode: settingsManager.settings.forceSinglePageMode });
5932
5806
  layout();
5933
5807
  if (!loadOptions.cfi) {
5934
5808
  viewportNavigator.goToSpineItem(0, { animate: false });
@@ -5936,9 +5810,6 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5936
5810
  viewportNavigator.goToCfi(loadOptions.cfi, { animate: false });
5937
5811
  }
5938
5812
  };
5939
- const registerHook = (name, fn) => {
5940
- hooksSubject$.next([...hooksSubject$.getValue(), { name, fn }]);
5941
- };
5942
5813
  spine.$.$.pipe(
5943
5814
  tap((event) => {
5944
5815
  if (event.type === `onSelectionChange`) {
@@ -5951,18 +5822,18 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5951
5822
  switchMap(({ adjustedSpinePosition }) => {
5952
5823
  return spine.adjustPagination(adjustedSpinePosition).pipe(takeUntil$1(navigation$));
5953
5824
  }),
5954
- takeUntil$1(context.$.destroy$)
5825
+ takeUntil$1(context.destroy$)
5955
5826
  ).subscribe();
5956
- merge(context.$.state$, settings.$.settings$).pipe(
5827
+ merge(context.state$, settingsManager.settings$).pipe(
5957
5828
  map$1(() => void 0),
5958
- withLatestFrom(context.$.state$),
5829
+ withLatestFrom(context.state$),
5959
5830
  map$1(([, { hasVerticalWriting }]) => {
5960
- const manifest = context.getManifest();
5831
+ const manifest = context.manifest;
5961
5832
  return {
5962
5833
  hasVerticalWriting,
5963
5834
  renditionFlow: manifest == null ? void 0 : manifest.renditionFlow,
5964
5835
  renditionLayout: manifest == null ? void 0 : manifest.renditionLayout,
5965
- computedPageTurnMode: settings.getSettings().computedPageTurnMode
5836
+ computedPageTurnMode: settingsManager.settings.computedPageTurnMode
5966
5837
  };
5967
5838
  }),
5968
5839
  distinctUntilChanged(isShallowEqual),
@@ -5970,7 +5841,7 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5970
5841
  ({ hasVerticalWriting, renditionFlow, renditionLayout, computedPageTurnMode }) => {
5971
5842
  return {
5972
5843
  ...stateSubject$.value,
5973
- supportedPageTurnMode: renditionFlow === `scrolled-continuous` ? [`scrollable`] : !context.areAllItemsPrePaginated() ? [`controlled`] : [`controlled`, `scrollable`],
5844
+ supportedPageTurnMode: renditionFlow === `scrolled-continuous` ? [`scrollable`] : !context.state.areAllItemsPrePaginated ? [`controlled`] : [`controlled`, `scrollable`],
5974
5845
  supportedPageTurnAnimation: renditionFlow === `scrolled-continuous` || computedPageTurnMode === `scrollable` ? [`none`] : hasVerticalWriting ? [`fade`, `none`] : [`fade`, `none`, `slide`],
5975
5846
  supportedPageTurnDirection: computedPageTurnMode === `scrollable` ? [`vertical`] : renditionLayout === `reflowable` ? [`horizontal`] : [`horizontal`, `vertical`]
5976
5847
  };
@@ -5979,16 +5850,13 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5979
5850
  takeUntil$1(destroy$)
5980
5851
  ).subscribe(stateSubject$);
5981
5852
  const destroy = () => {
5982
- var _a, _b;
5983
- settings.destroy();
5984
- hooksSubject$.next([]);
5985
- hooksSubject$.complete();
5853
+ var _a;
5854
+ settingsManager.destroy();
5986
5855
  pagination.destroy();
5987
5856
  context.destroy();
5988
5857
  viewportNavigator.destroy();
5989
5858
  spine.destroy();
5990
5859
  (_a = elementSubject$.getValue()) == null ? void 0 : _a.remove();
5991
- (_b = iframeEventBridgeElement$.getValue()) == null ? void 0 : _b.remove();
5992
5860
  stateSubject$.complete();
5993
5861
  selectionSubject$.complete();
5994
5862
  destroy$.next();
@@ -5996,43 +5864,16 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
5996
5864
  };
5997
5865
  const reader = {
5998
5866
  context,
5999
- registerHook,
6000
5867
  spine,
5868
+ hookManager,
6001
5869
  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,
5870
+ spineItemManager,
6025
5871
  layout,
6026
5872
  load,
6027
5873
  destroy,
6028
- spineItems$: spine.$.spineItems$,
6029
- context$: context.$.state$,
6030
5874
  pagination,
6031
- settings: {
6032
- settings$: settings.$.settings$,
6033
- getSettings: settings.getSettings,
6034
- setSettings: (data) => settings.setSettings(data, context.getState())
6035
- },
5875
+ settings: settingsManager,
5876
+ element$,
6036
5877
  $: {
6037
5878
  state$: stateSubject$.asObservable(),
6038
5879
  /**
@@ -6041,21 +5882,12 @@ const createReader = ({ hooks: initialHooks, ...inputSettings }) => {
6041
5882
  * have an effect.
6042
5883
  * It can typically be used to hide a loading indicator.
6043
5884
  */
6044
- loadStatus$: context.$.manifest$.pipe(map$1((manifest) => manifest ? "ready" : "idle")),
5885
+ loadStatus$: context.manifest$.pipe(map$1((manifest) => manifest ? "ready" : "idle")),
6045
5886
  /**
6046
5887
  * Dispatched when a change in selection happens
6047
5888
  */
6048
5889
  selection$: selectionSubject$.asObservable(),
6049
- viewportState$: viewportNavigator.$.state$,
6050
- layout$: spine.$.layout$,
6051
- itemsBeforeDestroy$: spine.$.itemsBeforeDestroy$,
6052
- itemIsReady$: spineItemManager.$.itemIsReady$,
6053
5890
  destroy$
6054
- },
6055
- __debug: {
6056
- pagination,
6057
- context,
6058
- spineItemManager
6059
5891
  }
6060
5892
  };
6061
5893
  return reader;
@@ -6069,19 +5901,6 @@ const createWrapperElement = (containerElement) => {
6069
5901
  element.className = `${HTML_PREFIX$1}-reader`;
6070
5902
  return element;
6071
5903
  };
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
5904
  const utilsEnhancer = (next) => (options) => {
6086
5905
  const reader = next(options);
6087
5906
  const isOrIsWithinValidLink = (target) => {
@@ -6206,9 +6025,9 @@ const createResourcesManager = (context) => {
6206
6025
  var _a, _b;
6207
6026
  if (typeof itemIndexOrId === `string` || typeof itemIndexOrId === `object`) {
6208
6027
  const id = typeof itemIndexOrId === `object` ? itemIndexOrId.id : void 0;
6209
- return (_a = context.getManifest()) == null ? void 0 : _a.spineItems.find((entry) => entry.id === id);
6028
+ return (_a = context.manifest) == null ? void 0 : _a.spineItems.find((entry) => entry.id === id);
6210
6029
  } else {
6211
- return (_b = context.getManifest()) == null ? void 0 : _b.spineItems[itemIndexOrId];
6030
+ return (_b = context.manifest) == null ? void 0 : _b.spineItems[itemIndexOrId];
6212
6031
  }
6213
6032
  };
6214
6033
  const get = async (itemIndexOrId, fetchResource) => {
@@ -6242,9 +6061,9 @@ const createResourcesManager = (context) => {
6242
6061
  })
6243
6062
  );
6244
6063
  }),
6245
- takeUntil$1(context.$.destroy$)
6064
+ takeUntil$1(context.destroy$)
6246
6065
  ).subscribe();
6247
- const onLoad$ = context.$.manifest$.pipe(
6066
+ const onLoad$ = context.manifest$.pipe(
6248
6067
  tap(() => {
6249
6068
  uniqueID = Date.now().toString();
6250
6069
  })
@@ -6268,7 +6087,7 @@ const createResourcesManager = (context) => {
6268
6087
  })
6269
6088
  );
6270
6089
  }),
6271
- takeUntil$1(context.$.destroy$)
6090
+ takeUntil$1(context.destroy$)
6272
6091
  ).subscribe();
6273
6092
  const destroy = () => {
6274
6093
  cache$.complete();
@@ -6281,14 +6100,6 @@ const createResourcesManager = (context) => {
6281
6100
  const resourcesEnhancer = (next) => (options) => {
6282
6101
  const reader = next(options);
6283
6102
  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
6103
  const destroy = () => {
6293
6104
  resourceManager.destroy();
6294
6105
  reader.destroy();
@@ -6299,8 +6110,8 @@ const resourcesEnhancer = (next) => (options) => {
6299
6110
  // ...reader.$,
6300
6111
  // errors$: merge(reader.$.errors$, errorsSubject$.asObservable())
6301
6112
  // },
6302
- destroy,
6303
- load
6113
+ destroy
6114
+ // load,
6304
6115
  };
6305
6116
  };
6306
6117
  const mediaEnhancer = (next) => (options) => {
@@ -6351,7 +6162,7 @@ const mediaEnhancer = (next) => (options) => {
6351
6162
  threshold: 0.5
6352
6163
  }
6353
6164
  );
6354
- reader.registerHook(`item.onLoad`, ({ frame }) => {
6165
+ reader.hookManager.register(`item.onLoad`, ({ frame, destroy: destroy2 }) => {
6355
6166
  var _a;
6356
6167
  frameObserver.observe(frame);
6357
6168
  const videos = (_a = frame.contentDocument) == null ? void 0 : _a.body.getElementsByTagName(`video`);
@@ -6359,10 +6170,10 @@ const mediaEnhancer = (next) => (options) => {
6359
6170
  elementObserver.observe(element);
6360
6171
  return () => elementObserver.unobserve(element);
6361
6172
  });
6362
- return () => {
6173
+ destroy2(() => {
6363
6174
  frameObserver.unobserve(frame);
6364
6175
  unobserveElements.forEach((unobserve) => unobserve());
6365
- };
6176
+ });
6366
6177
  });
6367
6178
  const destroy = () => {
6368
6179
  frameObserver.disconnect();
@@ -6378,16 +6189,16 @@ const progressionEnhancer = (next) => (options) => {
6378
6189
  const reader = next(options);
6379
6190
  const getPercentageEstimate = (context, currentSpineIndex, numberOfPages, pageIndex, currentPosition, currentItem) => {
6380
6191
  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;
6192
+ const isGloballyPrePaginated = ((_a = context.manifest) == null ? void 0 : _a.renditionLayout) === `pre-paginated`;
6193
+ const readingOrderLength = ((_b = context.manifest) == null ? void 0 : _b.spineItems.length) || 0;
6194
+ const estimateBeforeThisItem = ((_c = context.manifest) == null ? void 0 : _c.spineItems.slice(0, currentSpineIndex).reduce((acc, item) => acc + item.progressionWeight, 0)) || 0;
6195
+ const currentItemWeight = ((_e = (_d = context.manifest) == null ? void 0 : _d.spineItems[currentSpineIndex]) == null ? void 0 : _e.progressionWeight) || 0;
6385
6196
  let progressWithinThisItem = (pageIndex + 1) * (currentItemWeight / numberOfPages);
6386
6197
  if (!isGloballyPrePaginated && currentItem.item.renditionLayout === `reflowable` && !currentItem.isReady()) {
6387
6198
  progressWithinThisItem = 0;
6388
6199
  }
6389
6200
  let totalProgress = estimateBeforeThisItem + progressWithinThisItem;
6390
- if (((_f = context.getManifest()) == null ? void 0 : _f.renditionFlow) === `scrolled-continuous`) {
6201
+ if (((_f = context.manifest) == null ? void 0 : _f.renditionFlow) === `scrolled-continuous`) {
6391
6202
  if (currentItem.isReady()) {
6392
6203
  progressWithinThisItem = getScrollPercentageWithinItem(context, currentPosition, currentItem);
6393
6204
  } else {
@@ -6405,11 +6216,11 @@ const progressionEnhancer = (next) => (options) => {
6405
6216
  };
6406
6217
  const getScrollPercentageWithinItem = (context, currentPosition, currentItem) => {
6407
6218
  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));
6219
+ const { top, left } = reader.spineItemManager.getAbsolutePositionOf(currentItem);
6220
+ if (reader.settings.settings.computedPageTurnDirection === `vertical`) {
6221
+ return Math.max(0, Math.min(1, (currentPosition.y - top + context.state.visibleAreaRect.height) / height));
6411
6222
  } else {
6412
- return Math.max(0, Math.min(1, (currentPosition.x - left + context.getVisibleAreaRect().width) / width));
6223
+ return Math.max(0, Math.min(1, (currentPosition.x - left + context.state.visibleAreaRect.width) / width));
6413
6224
  }
6414
6225
  };
6415
6226
  return {
@@ -6431,67 +6242,59 @@ const accessibilityEnhancer = (next) => (options) => {
6431
6242
  }
6432
6243
  });
6433
6244
  }, {});
6434
- reader.registerHook(`item.onLoad`, ({ addStyle, frame }) => {
6245
+ reader.hookManager.register(`item.onLoad`, ({ itemId, frame, destroy }) => {
6435
6246
  var _a;
6436
- addStyle(
6437
- `prose-reader-accessibility`,
6247
+ const item = reader.spineItemManager.get(itemId);
6248
+ if (!item)
6249
+ return;
6250
+ item.manipulateSpineItem(({ addStyle }) => {
6251
+ addStyle(
6252
+ `prose-reader-accessibility`,
6253
+ `
6254
+ :focus-visible {
6255
+ ${/*
6256
+ Some epubs remove the outline, this is not good practice since it reduce accessibility.
6257
+ We will try to restore it by force.
6258
+ */
6259
+ ``}
6260
+ outline: -webkit-focus-ring-color auto 1px;
6261
+ }
6438
6262
  `
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
- );
6263
+ );
6264
+ return false;
6265
+ });
6449
6266
  const links = (_a = frame.contentDocument) == null ? void 0 : _a.body.querySelectorAll(`a`);
6450
6267
  links == null ? void 0 : links.forEach((link) => {
6451
6268
  observer.observe(link);
6452
6269
  });
6453
- return () => {
6270
+ destroy(() => {
6454
6271
  links == null ? void 0 : links.forEach((link) => {
6455
6272
  observer.unobserve(link);
6456
6273
  });
6457
- };
6274
+ });
6458
6275
  });
6459
6276
  return {
6460
6277
  ...reader
6461
6278
  };
6462
6279
  };
6463
6280
  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 = `
6470
- ${element.style.cssText}
6471
- -webkit-transform-style: preserve-3d;
6472
- `;
6473
- return element;
6474
- }
6475
- },
6476
- {
6477
- name: `item.onBeforeContainerCreated`,
6478
- fn: (element) => {
6479
- element.style.cssText = `
6281
+ const webkitEnhancer = (createReader2) => (options) => {
6282
+ const reader = createReader2(options);
6283
+ if (IS_SAFARI) {
6284
+ reader.hookManager.register("viewportNavigator.onBeforeContainerCreated", ({ element }) => {
6285
+ element.style.cssText = `
6480
6286
  ${element.style.cssText}
6481
6287
  -webkit-transform-style: preserve-3d;
6482
- -webkit-backface-visibility: hidden;
6483
6288
  `;
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
- });
6289
+ });
6290
+ reader.hookManager.register("item.onBeforeContainerCreated", ({ element }) => {
6291
+ element.style.cssText = `
6292
+ ${element.style.cssText}
6293
+ -webkit-transform-style: preserve-3d;
6294
+ -webkit-backface-visibility: hidden;
6295
+ `;
6296
+ });
6297
+ }
6495
6298
  return reader;
6496
6299
  };
6497
6300
  const HTML_PREFIX = `${HTML_PREFIX$1}-enhancer-loading`;
@@ -6512,9 +6315,9 @@ const loadingEnhancer = (next) => (options) => {
6512
6315
  };
6513
6316
  }, {})
6514
6317
  );
6515
- const updateEntriesLayout$ = (entries) => combineLatest([reader.$.layout$, reader.theme.$.theme$]).pipe(
6318
+ const updateEntriesLayout$ = (entries) => combineLatest([reader.spine.$.layout$, reader.theme.$.theme$]).pipe(
6516
6319
  map$1(([, theme]) => ({
6517
- width: reader.context.getVisibleAreaRect().width,
6320
+ width: reader.context.state.visibleAreaRect.width,
6518
6321
  theme
6519
6322
  })),
6520
6323
  distinctUntilChanged(isShallowEqual),
@@ -6525,22 +6328,22 @@ const loadingEnhancer = (next) => (options) => {
6525
6328
  });
6526
6329
  })
6527
6330
  );
6528
- const updateEntriesVisibility$ = (entries) => reader.$.itemIsReady$.pipe(
6331
+ const updateEntriesVisibility$ = (entries) => reader.spineItemManager.$.itemIsReady$.pipe(
6529
6332
  tap(({ item, isReady }) => {
6530
6333
  var _a;
6531
6334
  (_a = entries[item.id]) == null ? void 0 : _a.style.setProperty(`visibility`, isReady ? `hidden` : `visible`);
6532
6335
  })
6533
6336
  );
6534
- const destroyEntries$ = (entries) => reader.$.itemsBeforeDestroy$.pipe(
6337
+ const destroyEntries$ = (entries) => reader.spine.$.itemsBeforeDestroy$.pipe(
6535
6338
  map$1(() => {
6536
6339
  Object.values(entries).forEach((element) => element.remove());
6537
6340
  return {};
6538
6341
  })
6539
6342
  );
6540
- const items$ = reader.spineItems$.pipe(
6343
+ const items$ = reader.spine.$.spineItems$.pipe(
6541
6344
  switchMap$1((items) => createEntries$(items)),
6542
6345
  shareReplay(1),
6543
- takeUntil$1(reader.context.$.destroy$)
6346
+ takeUntil$1(reader.context.destroy$)
6544
6347
  );
6545
6348
  items$.pipe(
6546
6349
  switchMap$1((entries) => merge(of(entries), destroyEntries$(entries))),
@@ -6562,7 +6365,7 @@ const createLoadingElementContainer = (containerElement, context) => {
6562
6365
  loadingElement.style.cssText = `
6563
6366
  height: 100%;
6564
6367
  width: 100%;
6565
- max-width: ${context.getVisibleAreaRect().width}px;
6368
+ max-width: ${context.state.visibleAreaRect.width}px;
6566
6369
  text-align: center;
6567
6370
  display: flex;
6568
6371
  justify-content: center;
@@ -6602,6 +6405,155 @@ const publicApiEnhancer = (next) => {
6602
6405
  return reader;
6603
6406
  };
6604
6407
  };
6408
+ const createNormalizeEventForViewport = ({
6409
+ iframeEventBridgeElement$,
6410
+ locator
6411
+ }) => {
6412
+ const normalizeEventForViewport = (event) => {
6413
+ var _a;
6414
+ const eventIsComingFromBridge = event.target === iframeEventBridgeElement$.getValue();
6415
+ const iframeOriginalEvent = getOriginalFrameEventFromDocumentEvent(event);
6416
+ const originalFrame = (_a = iframeOriginalEvent == null ? void 0 : iframeOriginalEvent.view) == null ? void 0 : _a.frameElement;
6417
+ if (!eventIsComingFromBridge || !iframeOriginalEvent || !originalFrame)
6418
+ return event;
6419
+ const spineItem = locator.getSpineItemFromIframe(originalFrame);
6420
+ if (!spineItem)
6421
+ return event;
6422
+ if (isPointerEvent(event)) {
6423
+ const { clientX, clientY } = spineItem.translateFramePositionIntoPage(event);
6424
+ const newEvent = new PointerEvent(event.type, {
6425
+ ...event,
6426
+ pointerId: event.pointerId,
6427
+ clientX,
6428
+ clientY
6429
+ });
6430
+ Object.defineProperty(newEvent, `target`, { value: iframeOriginalEvent.target, enumerable: true });
6431
+ return newEvent;
6432
+ }
6433
+ if (isMouseEvent(event)) {
6434
+ const { clientX, clientY } = spineItem.translateFramePositionIntoPage(event);
6435
+ const newEvent = new MouseEvent(event.type, {
6436
+ ...event,
6437
+ clientX,
6438
+ clientY
6439
+ });
6440
+ Object.defineProperty(newEvent, `target`, { value: iframeOriginalEvent.target, enumerable: true });
6441
+ return newEvent;
6442
+ }
6443
+ if (isTouchEvent(event)) {
6444
+ const touches = Array.from(event.touches).map((touch) => {
6445
+ const { clientX, clientY } = spineItem.translateFramePositionIntoPage(touch);
6446
+ return new Touch({
6447
+ identifier: touch.identifier,
6448
+ target: touch.target,
6449
+ clientX,
6450
+ clientY
6451
+ });
6452
+ });
6453
+ const newEvent = new TouchEvent(event.type, {
6454
+ touches,
6455
+ changedTouches: touches,
6456
+ targetTouches: touches
6457
+ });
6458
+ Object.defineProperty(newEvent, `target`, { value: iframeOriginalEvent.target, enumerable: true });
6459
+ return newEvent;
6460
+ }
6461
+ return event;
6462
+ };
6463
+ return normalizeEventForViewport;
6464
+ };
6465
+ const IFRAME_EVENT_BRIDGE_ELEMENT_ID = `proseReaderIframeEventBridgeElement`;
6466
+ const createIframeEventBridgeElement = (container) => {
6467
+ const iframeEventBridgeElement = container.ownerDocument.createElement(`div`);
6468
+ iframeEventBridgeElement.id = IFRAME_EVENT_BRIDGE_ELEMENT_ID;
6469
+ iframeEventBridgeElement.style.cssText = `
6470
+ position: absolute;
6471
+ height: 100%;
6472
+ width: 100%;
6473
+ top: 0;
6474
+ left: 0;
6475
+ z-index: -1;
6476
+ `;
6477
+ return iframeEventBridgeElement;
6478
+ };
6479
+ const pointerEvents = [
6480
+ `pointercancel`,
6481
+ `pointerdown`,
6482
+ `pointerenter`,
6483
+ `pointerleave`,
6484
+ `pointermove`,
6485
+ `pointerout`,
6486
+ `pointerover`,
6487
+ `pointerup`,
6488
+ `touchstart`,
6489
+ `touchend`
6490
+ ];
6491
+ const mouseEvents = [
6492
+ `click`,
6493
+ `mousedown`,
6494
+ `mouseup`,
6495
+ `mouseenter`,
6496
+ `mouseleave`,
6497
+ `mousemove`,
6498
+ `mouseout`,
6499
+ `mouseover`
6500
+ ];
6501
+ const passthroughEvents = [...pointerEvents, ...mouseEvents];
6502
+ const eventsEnhancer = (next) => (options) => {
6503
+ const iframeEventBridgeElement$ = new BehaviorSubject(void 0);
6504
+ const reader = next(options);
6505
+ reader.hookManager.register(`item.onLoad`, ({ destroy, frame, itemId }) => {
6506
+ const item = reader.spineItemManager.get(itemId);
6507
+ if (!item)
6508
+ return;
6509
+ const unregister = passthroughEvents.map((event) => {
6510
+ var _a;
6511
+ const listener = (e) => {
6512
+ var _a2;
6513
+ let convertedEvent = e;
6514
+ if (isPointerEvent(e)) {
6515
+ convertedEvent = new PointerEvent(e.type, e);
6516
+ }
6517
+ if (isMouseEvent(e)) {
6518
+ convertedEvent = new MouseEvent(e.type, e);
6519
+ }
6520
+ if (convertedEvent !== e) {
6521
+ attachOriginalFrameEventToDocumentEvent(convertedEvent, e);
6522
+ (_a2 = iframeEventBridgeElement$.getValue()) == null ? void 0 : _a2.dispatchEvent(convertedEvent);
6523
+ }
6524
+ };
6525
+ (_a = frame.contentDocument) == null ? void 0 : _a.addEventListener(event, listener);
6526
+ return () => {
6527
+ var _a2;
6528
+ (_a2 = frame.contentDocument) == null ? void 0 : _a2.removeEventListener(event, listener);
6529
+ };
6530
+ });
6531
+ item.selectionTracker.track(frame);
6532
+ item.fingerTracker.track(frame);
6533
+ destroy(() => {
6534
+ unregister.forEach((cb) => cb());
6535
+ });
6536
+ });
6537
+ reader.element$.pipe(
6538
+ tap$1((wrapper) => {
6539
+ var _a;
6540
+ const iframeEventBridgeElement = createIframeEventBridgeElement(wrapper);
6541
+ wrapper.appendChild(iframeEventBridgeElement);
6542
+ (_a = iframeEventBridgeElement$.getValue()) == null ? void 0 : _a.remove();
6543
+ iframeEventBridgeElement$.next(iframeEventBridgeElement);
6544
+ }),
6545
+ takeUntil(reader.$.destroy$)
6546
+ ).subscribe();
6547
+ return {
6548
+ ...reader,
6549
+ events: {
6550
+ normalizeEventForViewport: createNormalizeEventForViewport({
6551
+ iframeEventBridgeElement$,
6552
+ locator: reader.spine.locator
6553
+ })
6554
+ }
6555
+ };
6556
+ };
6605
6557
  const createReaderWithEnhancers = (
6606
6558
  //__
6607
6559
  publicApiEnhancer(
@@ -6621,8 +6573,10 @@ const createReaderWithEnhancers = (
6621
6573
  hotkeysEnhancer(
6622
6574
  paginationEnhancer(
6623
6575
  progressionEnhancer(
6624
- // __
6625
- createReader
6576
+ eventsEnhancer(
6577
+ // __
6578
+ createReader
6579
+ )
6626
6580
  )
6627
6581
  )
6628
6582
  )