@prose-reader/core 1.72.0 → 1.73.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/cfi/generate/{getCfiForSpineItemPage.d.ts → generateCfiForSpineItemPage.d.ts} +1 -1
  2. package/dist/cfi/lookup/resolveCfi.d.ts +236 -0
  3. package/dist/constants.d.ts +0 -1
  4. package/dist/context/Context.d.ts +6 -29
  5. package/dist/createReaderWithEnhancer.d.ts +252 -9
  6. package/dist/enhancers/events/events.d.ts +1 -6
  7. package/dist/enhancers/events/frames.d.ts +3 -0
  8. package/dist/enhancers/events/normalizeEventForViewport.d.ts +1 -5
  9. package/dist/enhancers/navigation/index.d.ts +1 -1
  10. package/dist/enhancers/navigation/navigators/manualNavigator.d.ts +4 -0
  11. package/dist/enhancers/navigation/resolvers/{getNavigationForLeftPage.d.ts → getNavigationForLeftOrTopPage.d.ts} +1 -1
  12. package/dist/enhancers/navigation/resolvers/{getNavigationForRightPage.d.ts → getNavigationForRightOrBottomPage.d.ts} +1 -1
  13. package/dist/enhancers/navigation/types.d.ts +8 -0
  14. package/dist/enhancers/zoom/ControllableZoomer.d.ts +19 -0
  15. package/dist/enhancers/zoom/ScrollableZoomer.d.ts +16 -0
  16. package/dist/enhancers/zoom/Zoomer.d.ts +21 -0
  17. package/dist/enhancers/zoom/index.d.ts +2 -2
  18. package/dist/enhancers/zoom/types.d.ts +10 -12
  19. package/dist/index.d.ts +3 -1
  20. package/dist/index.js +1021 -923
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.umd.cjs +1041 -941
  23. package/dist/index.umd.cjs.map +1 -1
  24. package/dist/navigation/InternalNavigator.d.ts +3 -5
  25. package/dist/navigation/Navigator.d.ts +1 -3
  26. package/dist/navigation/UserNavigator.d.ts +3 -1
  27. package/dist/navigation/consolidation/withSpineItemLayoutInfo.d.ts +3 -3
  28. package/dist/navigation/consolidation/withSpineItemPosition.d.ts +0 -2
  29. package/dist/navigation/resolvers/NavigationResolver.d.ts +3 -1
  30. package/dist/navigation/resolvers/getAdjustedPositionWithSafeEdge.d.ts +3 -1
  31. package/dist/navigation/restoration/restoreNavigationForControlledPageTurnMode.d.ts +3 -1
  32. package/dist/navigation/restoration/restorePosition.d.ts +3 -1
  33. package/dist/navigation/restoration/withRestoredPosition.d.ts +3 -7
  34. package/dist/navigation/tests/SpineItemsManagerMock.d.ts +2 -1
  35. package/dist/navigation/tests/utils.d.ts +2 -0
  36. package/dist/navigation/viewport/getScaledDownPosition.d.ts +2 -3
  37. package/dist/reader.d.ts +260 -18
  38. package/dist/settings/SettingsInterface.d.ts +2 -2
  39. package/dist/settings/SettingsManager.d.ts +2 -2
  40. package/dist/settings/SettingsManagerOverload.d.ts +2 -2
  41. package/dist/spine/Spine.d.ts +5 -2
  42. package/dist/spine/SpineItemsManager.d.ts +5 -26
  43. package/dist/spine/SpineItemsObserver.d.ts +3 -1
  44. package/dist/spine/SpineLayout.d.ts +49 -0
  45. package/dist/spine/layout/convertViewportPositionToLayoutPosition.d.ts +10 -0
  46. package/dist/spine/loader/SpineItemsLoader.d.ts +3 -1
  47. package/dist/spine/locator/SpineLocator.d.ts +146 -5
  48. package/dist/spine/locator/getAbsolutePageIndexFromPageIndex.d.ts +14 -0
  49. package/dist/spine/locator/getSpineInfoFromAbsolutePageIndex.d.ts +134 -0
  50. package/dist/spine/locator/getSpineItemFromPosition.d.ts +3 -1
  51. package/dist/spine/locator/getSpinePositionFromSpineItemPageIndex.d.ts +13 -0
  52. package/dist/spine/locator/getSpinePositionFromSpineItemPosition.d.ts +10 -0
  53. package/dist/spine/locator/getVisibleSpineItemsFromPosition.d.ts +3 -1
  54. package/dist/spineItem/locationResolver.d.ts +12 -2
  55. package/dist/spineItem/locator/getSpineItemNumberOfPages.d.ts +10 -0
  56. package/dist/spineItem/locator/getSpineItemPagesPosition.d.ts +12 -0
  57. package/dist/spineItem/locator/getSpineItemPositionFromPageIndex.d.ts +12 -0
  58. package/dist/utils/frames.d.ts +1 -0
  59. package/dist/utils/objects.d.ts +1 -6
  60. package/package.json +3 -3
  61. package/dist/enhancers/events/createIframeEventBridgeElement.d.ts +0 -1
  62. package/dist/enhancers/zoom/elementZoomer.d.ts +0 -19
  63. package/dist/enhancers/zoom/viewportZoomer.d.ts +0 -19
  64. package/dist/frames.d.ts +0 -5
package/dist/index.js CHANGED
@@ -1,12 +1,13 @@
1
- import { takeUntil, Subject, combineLatest, map as map$1, switchMap, merge, EMPTY, fromEvent, withLatestFrom, NEVER, Observable, of, scheduled, animationFrameScheduler, distinctUntilChanged as distinctUntilChanged$1, startWith as startWith$1, debounceTime as debounceTime$1, BehaviorSubject, combineLatestWith, tap as tap$1, shareReplay as shareReplay$1, ReplaySubject, filter as filter$1, share, mergeMap, delay, identity, timer, skip as skip$1, exhaustMap, take as take$1, finalize, first as first$1, from, catchError, forkJoin } from "rxjs";
1
+ import { takeUntil, Subject, combineLatest, map as map$1, switchMap, merge, EMPTY, fromEvent, withLatestFrom, NEVER, Observable, of, scheduled, animationFrameScheduler, distinctUntilChanged as distinctUntilChanged$1, startWith as startWith$1, debounceTime as debounceTime$1, BehaviorSubject, combineLatestWith, tap as tap$1, shareReplay as shareReplay$1, ReplaySubject, filter as filter$1, share, mergeMap, delay, identity, timer, skip as skip$1, exhaustMap, first as first$1, finalize, take as take$1, from, catchError, forkJoin } from "rxjs";
2
2
  import { startWith, map, shareReplay, tap, pairwise, switchMap as switchMap$1, take, distinctUntilChanged, takeUntil as takeUntil$1, first, filter, debounceTime, skip, withLatestFrom as withLatestFrom$1, exhaustMap as exhaustMap$1, ignoreElements, endWith, defaultIfEmpty, share as share$1, mergeMap as mergeMap$1, catchError as catchError$1 } from "rxjs/operators";
3
- import { parseContentType, detectMimeTypeFromName } from "@prose-reader/shared";
3
+ import { shallowMergeIfDefined, isShallowEqual, parseContentType, detectMimeTypeFromName } from "@prose-reader/shared";
4
+ import { isShallowEqual as isShallowEqual2 } from "@prose-reader/shared";
4
5
  const chromeEnhancer = (next) => (options) => {
5
6
  const reader = next(options);
6
7
  reader.context.state$.pipe(takeUntil(reader.$.destroy$)).subscribe(({ containerElement }) => {
7
8
  if (!containerElement) return;
8
9
  const onScroll = () => {
9
- if (reader.settings.settings.computedPageTurnMode === `controlled`) {
10
+ if (reader.settings.values.computedPageTurnMode === `controlled`) {
10
11
  containerElement.scrollTo(0, 0);
11
12
  }
12
13
  };
@@ -18,72 +19,6 @@ const chromeEnhancer = (next) => (options) => {
18
19
  });
19
20
  return reader;
20
21
  };
21
- const hasOwn = Object.prototype.hasOwnProperty;
22
- const is = (x, y) => {
23
- if (x === y) {
24
- return x !== 0 || y !== 0 || 1 / x === 1 / y;
25
- } else {
26
- return false;
27
- }
28
- };
29
- const isShallowEqual = (objectA, objectB, options) => {
30
- if (objectA === objectB) {
31
- return true;
32
- }
33
- if (typeof objectA !== `object` || objectA === null) {
34
- return false;
35
- }
36
- if (typeof objectB !== `object` || objectB === null) {
37
- return false;
38
- }
39
- const keysA = Object.keys(objectA);
40
- const keysB = Object.keys(objectB);
41
- if (keysA.length !== keysB.length) {
42
- return false;
43
- }
44
- const isEqual = options && typeof options.customEqual === `function` ? options.customEqual : is;
45
- for (let i = 0; i < keysA.length; i++) {
46
- const key = keysA[i] || ``;
47
- if (!hasOwn.call(objectB, key) || !isEqual(objectA[key], objectB[key])) {
48
- return false;
49
- }
50
- }
51
- return true;
52
- };
53
- const groupBy = (list, getKey) => list.reduce(
54
- (previous, currentItem) => {
55
- const group = getKey(currentItem);
56
- if (!previous[group]) previous[group] = [];
57
- previous[group].push(currentItem);
58
- return previous;
59
- },
60
- {}
61
- );
62
- const getBase64FromBlob = (data) => {
63
- const reader = new FileReader();
64
- return new Promise((resolve) => {
65
- reader.addEventListener(
66
- `load`,
67
- function() {
68
- resolve(reader.result);
69
- },
70
- false
71
- );
72
- reader.readAsDataURL(data);
73
- });
74
- };
75
- function shallowMergeIfDefined(obj1, obj2) {
76
- const result = { ...obj1 };
77
- for (const key in obj2) {
78
- if (Object.prototype.hasOwnProperty.call(obj2, key)) {
79
- const value = obj2[key];
80
- if (value !== void 0 || !(key in obj1)) {
81
- result[key] = value;
82
- }
83
- }
84
- }
85
- return result;
86
- }
87
22
  class SettingsManagerOverload {
88
23
  constructor(initialSettings, settingsManager) {
89
24
  this.settingsManager = settingsManager;
@@ -97,14 +32,14 @@ class SettingsManagerOverload {
97
32
  initialSettings
98
33
  );
99
34
  this.outputSettingsUpdateSubject = new Subject();
100
- this.settings$ = combineLatest([
101
- this.settingsManager.settings$,
35
+ this.values$ = combineLatest([
36
+ this.settingsManager.values$,
102
37
  this.outputSettingsUpdateSubject.pipe(startWith(this.outputSettings))
103
38
  ]).pipe(
104
39
  map(([parentSettings, settings]) => ({ ...parentSettings, ...settings })),
105
40
  shareReplay(1)
106
41
  );
107
- this.settings$.subscribe();
42
+ this.values$.subscribe();
108
43
  }
109
44
  _prepareUpdate(settings) {
110
45
  const parentInputSettings = this.getCleanedParentInputSettings(settings);
@@ -132,9 +67,9 @@ class SettingsManagerOverload {
132
67
  const { commit } = this._prepareUpdate(settings);
133
68
  commit();
134
69
  }
135
- get settings() {
70
+ get values() {
136
71
  return {
137
- ...this.settingsManager.settings,
72
+ ...this.settingsManager.values,
138
73
  ...this.outputSettings
139
74
  };
140
75
  }
@@ -142,6 +77,19 @@ class SettingsManagerOverload {
142
77
  this.outputSettingsUpdateSubject.complete();
143
78
  }
144
79
  }
80
+ const getBase64FromBlob = (data) => {
81
+ const reader = new FileReader();
82
+ return new Promise((resolve) => {
83
+ reader.addEventListener(
84
+ `load`,
85
+ function() {
86
+ resolve(reader.result);
87
+ },
88
+ false
89
+ );
90
+ reader.readAsDataURL(data);
91
+ });
92
+ };
145
93
  let SettingsManager$2 = class SettingsManager extends SettingsManagerOverload {
146
94
  computeOutputSettings(settings) {
147
95
  return settings;
@@ -186,10 +134,10 @@ const fontsEnhancer = (next) => (options) => {
186
134
  */
187
135
  ``}
188
136
  body {
189
- ${settingsManager.settings.fontScale !== 1 ? `font-size: ${settingsManager.settings.fontScale}em !important;` : ``}
190
- ${settingsManager.settings.lineHeight !== `publisher` ? `line-height: ${settingsManager.settings.lineHeight} !important;` : ``}
191
- ${settingsManager.settings.fontWeight !== `publisher` ? `font-weight: ${settingsManager.settings.fontWeight} !important;` : ``}
192
- ${settingsManager.settings.fontJustification !== `publisher` ? `text-align: ${settingsManager.settings.fontJustification} !important;` : ``}
137
+ ${settingsManager.values.fontScale !== 1 ? `font-size: ${settingsManager.values.fontScale}em !important;` : ``}
138
+ ${settingsManager.values.lineHeight !== `publisher` ? `line-height: ${settingsManager.values.lineHeight} !important;` : ``}
139
+ ${settingsManager.values.fontWeight !== `publisher` ? `font-weight: ${settingsManager.values.fontWeight} !important;` : ``}
140
+ ${settingsManager.values.fontJustification !== `publisher` ? `text-align: ${settingsManager.values.fontJustification} !important;` : ``}
193
141
  }
194
142
  `;
195
143
  const applyChangeToSpineItems = (requireLayout) => {
@@ -219,7 +167,7 @@ const fontsEnhancer = (next) => (options) => {
219
167
  return false;
220
168
  })
221
169
  );
222
- settingsManager.settings$.pipe(
170
+ settingsManager.values$.pipe(
223
171
  shouldRequireLayout,
224
172
  tap(applyChangeToSpineItems),
225
173
  takeUntil(reader.$.destroy$)
@@ -237,7 +185,7 @@ const fontsEnhancer = (next) => (options) => {
237
185
  const hotkeysEnhancer = (next) => (options) => {
238
186
  const reader = next(options);
239
187
  const navigateOnKey = (document2) => fromEvent(document2, "keyup").pipe(
240
- withLatestFrom(reader.settings.settings$),
188
+ withLatestFrom(reader.settings.values$),
241
189
  map$1(([e, { pageTurnDirection }]) => {
242
190
  if (pageTurnDirection === "horizontal") {
243
191
  if (e.key === `ArrowRight`) {
@@ -317,8 +265,8 @@ const createMovingSafePan$ = (reader) => {
317
265
  const resetLockViewportFree$ = createResetLock$(
318
266
  reader.navigation.viewportFree$
319
267
  ).pipe(take(1));
320
- const pageTurnMode$ = reader.settings.settings$.pipe(
321
- map(() => reader.settings.settings.computedPageTurnMode),
268
+ const pageTurnMode$ = reader.settings.values$.pipe(
269
+ map(() => reader.settings.values.computedPageTurnMode),
322
270
  distinctUntilChanged()
323
271
  );
324
272
  const handleViewportLock$ = pageTurnMode$.pipe(
@@ -442,7 +390,7 @@ const layoutEnhancer = (next) => (options) => {
442
390
  ({ itemIndex, minimumWidth, isImageType }) => {
443
391
  const item = reader.spineItemsManager.get(itemIndex);
444
392
  const frame = item == null ? void 0 : item.frame;
445
- const { pageHorizontalMargin: pageHorizontalMargin2 = 0, pageVerticalMargin: pageVerticalMargin2 = 0 } = settingsManager.settings;
393
+ const { pageHorizontalMargin: pageHorizontalMargin2 = 0, pageVerticalMargin: pageVerticalMargin2 = 0 } = settingsManager.values;
446
394
  const pageSize = reader.context.getPageSize();
447
395
  if ((item == null ? void 0 : item.item.renditionLayout) === `reflowable` && (frame == null ? void 0 : frame.isReady) && !isImageType() && !frame.getViewportDimensions()) {
448
396
  let columnWidth = pageSize.width - pageHorizontalMargin2 * 2;
@@ -490,7 +438,7 @@ const layoutEnhancer = (next) => (options) => {
490
438
  resizeObserver.disconnect();
491
439
  };
492
440
  });
493
- const layoutOnContainerResize$ = settingsManager.settings$.pipe(
441
+ const layoutOnContainerResize$ = settingsManager.values$.pipe(
494
442
  filter(({ layoutAutoResize: layoutAutoResize2 }) => layoutAutoResize2 === "container"),
495
443
  switchMap$1(() => reader.context.containerElement$),
496
444
  filter(isDefined),
@@ -502,7 +450,7 @@ const layoutEnhancer = (next) => (options) => {
502
450
  );
503
451
  const movingSafePan$ = createMovingSafePan$(reader);
504
452
  movingSafePan$.subscribe();
505
- settingsManager.settings$.pipe(
453
+ settingsManager.values$.pipe(
506
454
  mapKeysTo([`pageHorizontalMargin`, `pageVerticalMargin`]),
507
455
  distinctUntilChanged(isShallowEqual),
508
456
  skip(1),
@@ -708,14 +656,14 @@ const getNavigationForRightSinglePage = ({
708
656
  pageTurnDirection === `horizontal` ? { x: position.x + context.getPageSize().width, y: 0 } : { y: position.y + context.getPageSize().height, x: 0 }
709
657
  );
710
658
  } else {
711
- const readingOrderPosition = spineLocator.getSpinePositionFromSpineItemPosition(
712
- spineItemNavigationForRightPage,
659
+ const readingOrderPosition = spineLocator.getSpinePositionFromSpineItemPosition({
660
+ spineItemPosition: spineItemNavigationForRightPage,
713
661
  spineItem
714
- );
662
+ });
715
663
  return readingOrderPosition;
716
664
  }
717
665
  };
718
- const getNavigationForRightPage = ({
666
+ const getNavigationForRightOrBottomPage = ({
719
667
  position,
720
668
  spineItem,
721
669
  context,
@@ -821,14 +769,14 @@ const getNavigationForLeftSinglePage = ({
821
769
  pageTurnDirection === `horizontal` ? { x: position.x - context.getPageSize().width, y: 0 } : { y: position.y - context.getPageSize().height, x: 0 }
822
770
  );
823
771
  } else {
824
- const readingOrderPosition = spineLocator.getSpinePositionFromSpineItemPosition(
825
- spineItemNavigation,
772
+ const readingOrderPosition = spineLocator.getSpinePositionFromSpineItemPosition({
773
+ spineItemPosition: spineItemNavigation,
826
774
  spineItem
827
- );
775
+ });
828
776
  return readingOrderPosition;
829
777
  }
830
778
  };
831
- const getNavigationForLeftPage = ({
779
+ const getNavigationForLeftOrTopPage = ({
832
780
  position,
833
781
  spineItem,
834
782
  context,
@@ -882,14 +830,26 @@ class ManualNavigator {
882
830
  this.unlock = void 0;
883
831
  }
884
832
  turnRight() {
833
+ return this.turnRightOrBottom();
834
+ }
835
+ turnLeft() {
836
+ return this.turnLeftOrTop();
837
+ }
838
+ turnTop() {
839
+ return this.turnLeftOrTop();
840
+ }
841
+ turnBottom() {
842
+ return this.turnRightOrBottom();
843
+ }
844
+ turnRightOrBottom() {
885
845
  const navigation = this.reader.navigation.getNavigation();
886
846
  const spineItem = this.reader.spineItemsManager.get(navigation.spineItem);
887
847
  if (!spineItem) return;
888
- const position = getNavigationForRightPage({
848
+ const position = getNavigationForRightOrBottomPage({
889
849
  context: this.reader.context,
890
850
  navigationResolver: this.reader.navigation.navigationResolver,
891
851
  position: navigation.position,
892
- computedPageTurnDirection: this.reader.settings.settings.computedPageTurnDirection,
852
+ computedPageTurnDirection: this.reader.settings.values.computedPageTurnDirection,
893
853
  spineItem,
894
854
  spineItemsManager: this.reader.spineItemsManager,
895
855
  spineLocator: this.reader.spine.locator
@@ -898,15 +858,15 @@ class ManualNavigator {
898
858
  position
899
859
  });
900
860
  }
901
- turnLeft() {
861
+ turnLeftOrTop() {
902
862
  const navigation = this.reader.navigation.getNavigation();
903
863
  const spineItem = this.reader.spineItemsManager.get(navigation.spineItem);
904
864
  if (!spineItem) return;
905
- const position = getNavigationForLeftPage({
865
+ const position = getNavigationForLeftOrTopPage({
906
866
  context: this.reader.context,
907
867
  navigationResolver: this.reader.navigation.navigationResolver,
908
868
  position: navigation.position,
909
- computedPageTurnDirection: this.reader.settings.settings.computedPageTurnDirection,
869
+ computedPageTurnDirection: this.reader.settings.values.computedPageTurnDirection,
910
870
  spineItem,
911
871
  spineItemsManager: this.reader.spineItemsManager,
912
872
  spineLocator: this.reader.spine.locator
@@ -954,7 +914,7 @@ class ManualNavigator {
954
914
  });
955
915
  }
956
916
  goToRightSpineItem() {
957
- if (this.reader.settings.settings.computedPageTurnDirection === "vertical") {
917
+ if (this.reader.settings.values.computedPageTurnDirection === "vertical") {
958
918
  Report.warn(
959
919
  `You cannot call this navigation method on vertical direction`
960
920
  );
@@ -966,7 +926,7 @@ class ManualNavigator {
966
926
  return this.goToNextSpineItem();
967
927
  }
968
928
  goToLeftSpineItem() {
969
- if (this.reader.settings.settings.computedPageTurnDirection === "vertical") {
929
+ if (this.reader.settings.values.computedPageTurnDirection === "vertical") {
970
930
  Report.warn(
971
931
  `You cannot call this navigation method on vertical direction`
972
932
  );
@@ -978,7 +938,7 @@ class ManualNavigator {
978
938
  return this.goToPreviousSpineItem();
979
939
  }
980
940
  goToTopSpineItem() {
981
- if (this.reader.settings.settings.computedPageTurnDirection === "horizontal") {
941
+ if (this.reader.settings.values.computedPageTurnDirection === "horizontal") {
982
942
  Report.warn(
983
943
  `You cannot call this navigation method on horizontal direction`
984
944
  );
@@ -987,7 +947,7 @@ class ManualNavigator {
987
947
  return this.goToPreviousSpineItem();
988
948
  }
989
949
  goToBottomSpineItem() {
990
- if (this.reader.settings.settings.computedPageTurnDirection === "horizontal") {
950
+ if (this.reader.settings.values.computedPageTurnDirection === "horizontal") {
991
951
  Report.warn(
992
952
  `You cannot call this navigation method on horizontal direction`
993
953
  );
@@ -1015,16 +975,16 @@ class PanNavigator {
1015
975
  }
1016
976
  moveTo(delta, { final, start } = {}) {
1017
977
  var _a, _b, _c, _d;
1018
- if (this.reader.settings.settings.computedPageTurnMode === `scrollable`) {
978
+ if (this.reader.settings.values.computedPageTurnMode === `scrollable`) {
1019
979
  Report.warn(`pan control is not available on free page turn mode`);
1020
980
  return;
1021
981
  }
1022
- const pageTurnDirection = this.reader.settings.settings.computedPageTurnDirection;
982
+ const pageTurnDirection = this.reader.settings.values.computedPageTurnDirection;
1023
983
  if (start) {
1024
984
  (_a = this.unlock) == null ? void 0 : _a.call(this);
1025
985
  this.unlock = this.reader.navigation.lock();
1026
986
  this.lastDelta = { x: 0, y: 0 };
1027
- this.lastStartPosition = this.reader.navigation.viewportPosition;
987
+ this.lastStartPosition = this.reader.navigation.getViewportPosition();
1028
988
  this.lastPosition = this.lastStartPosition;
1029
989
  }
1030
990
  let navigation = this.reader.navigation.getNavigation().position;
@@ -1061,7 +1021,7 @@ class PanNavigator {
1061
1021
  }
1062
1022
  const observeState = (reader) => {
1063
1023
  return reader.pagination.state$.pipe(
1064
- withLatestFrom(reader.context.manifest$, reader.settings.settings$),
1024
+ withLatestFrom(reader.context.manifest$, reader.settings.values$),
1065
1025
  map$1(
1066
1026
  ([
1067
1027
  paginationInfo,
@@ -1093,10 +1053,11 @@ const navigationEnhancer = (next) => (options) => {
1093
1053
  const state$ = observeState(reader);
1094
1054
  const manualNavigator = new ManualNavigator(reader);
1095
1055
  const panNavigator = new PanNavigator(reader);
1096
- const load = (manifest, loadOptions) => {
1097
- reader.load(manifest, loadOptions);
1098
- if (loadOptions.cfi) {
1099
- manualNavigator.goToCfi(loadOptions.cfi, { animate: false });
1056
+ const load = (options2) => {
1057
+ const { cfi, ...rest } = options2;
1058
+ reader.load(rest);
1059
+ if (cfi) {
1060
+ manualNavigator.goToCfi(cfi, { animate: false });
1100
1061
  }
1101
1062
  };
1102
1063
  return {
@@ -1106,6 +1067,10 @@ const navigationEnhancer = (next) => (options) => {
1106
1067
  ...reader.navigation,
1107
1068
  state$,
1108
1069
  moveTo: panNavigator.moveTo.bind(panNavigator),
1070
+ turnBottom: manualNavigator.turnBottom.bind(manualNavigator),
1071
+ turnTop: manualNavigator.turnTop.bind(manualNavigator),
1072
+ turnLeftOrTop: manualNavigator.turnLeftOrTop.bind(manualNavigator),
1073
+ turnRightOrBottom: manualNavigator.turnRightOrBottom.bind(manualNavigator),
1109
1074
  turnLeft: manualNavigator.turnLeft.bind(manualNavigator),
1110
1075
  turnRight: manualNavigator.turnRight.bind(manualNavigator),
1111
1076
  goToCfi: manualNavigator.goToCfi.bind(manualNavigator),
@@ -1190,7 +1155,7 @@ const getNumberOfPagesForAllSpineItems = (reader) => reader.spineItemsManager.it
1190
1155
  });
1191
1156
  }, 0);
1192
1157
  const trackTotalPages = (reader) => {
1193
- const totalPages$ = reader.spine.layout$.pipe(
1158
+ const totalPages$ = reader.layout$.pipe(
1194
1159
  debounceTime$1(10, animationFrameScheduler),
1195
1160
  withLatestFrom(reader.pagination.state$),
1196
1161
  map$1(() => {
@@ -1414,22 +1379,29 @@ const themeEnhancer = (next) => (options) => {
1414
1379
  }
1415
1380
  };
1416
1381
  };
1417
- const createElementZoomer = (reader) => {
1418
- const isZooming$ = new BehaviorSubject(false);
1419
- let imageMagnifierContainer;
1420
- let imgLastPosition = { x: 0, y: 0 };
1421
- let movingLastDelta = { x: 0, y: 0 };
1422
- let baseScale = 1;
1423
- let lastUserScale = 1;
1424
- const enter = (imgElement) => {
1425
- isZooming$.next(true);
1426
- imgLastPosition = { x: 0, y: 0 };
1427
- baseScale = 1;
1428
- lastUserScale = 1;
1429
- const container = reader.context.state.containerElement;
1382
+ class Zoomer {
1383
+ constructor(reader) {
1384
+ this.reader = reader;
1385
+ }
1386
+ }
1387
+ class ControllableZoomer extends Zoomer {
1388
+ constructor() {
1389
+ super(...arguments);
1390
+ this.isZooming$ = new BehaviorSubject(false);
1391
+ this.currentScale = 1;
1392
+ this.currentPosition = { x: 0, y: 0 };
1393
+ }
1394
+ enter(element) {
1395
+ if (!element) {
1396
+ console.warn(`You need an image to enter zoom`);
1397
+ return;
1398
+ }
1399
+ this.currentPosition = { x: 0, y: 0 };
1400
+ this.currentScale = 1;
1401
+ const container = this.reader.context.state.containerElement;
1430
1402
  if (container) {
1431
- imageMagnifierContainer = container.ownerDocument.createElement(`div`);
1432
- imageMagnifierContainer.style.cssText = `
1403
+ this.element = container.ownerDocument.createElement(`div`);
1404
+ this.element.style.cssText = `
1433
1405
  top: 0;
1434
1406
  left: 0;
1435
1407
  display: block;
@@ -1440,82 +1412,45 @@ const createElementZoomer = (reader) => {
1440
1412
  height: 100%;
1441
1413
  user-select: none;
1442
1414
  `;
1443
- const clonedImgElement = imgElement.cloneNode();
1444
- clonedImgElement.src = imgElement.src;
1415
+ const clonedImgElement = element.cloneNode();
1416
+ clonedImgElement.src = element.src;
1445
1417
  clonedImgElement.style.setProperty(`height`, `100%`);
1446
1418
  clonedImgElement.style.setProperty(`width`, `100%`);
1447
1419
  clonedImgElement.style.setProperty(`object-fit`, `contain`);
1448
1420
  clonedImgElement.style.setProperty(`pointer-events`, `none`);
1449
- imageMagnifierContainer.appendChild(clonedImgElement);
1450
- container.appendChild(imageMagnifierContainer);
1451
- }
1452
- scale(1.2);
1453
- setCurrentScaleAsBase();
1454
- };
1455
- const setCurrentScaleAsBase = () => {
1456
- baseScale = lastUserScale;
1457
- };
1458
- const scale = (userScale) => {
1459
- const imgElement = imageMagnifierContainer == null ? void 0 : imageMagnifierContainer.querySelector(`img`);
1460
- const roundedScale = Math.ceil(
1461
- (userScale < 1 ? baseScale - (1 - userScale) : baseScale + (userScale - 1)) * 100
1462
- ) / 100;
1463
- const newScale = Math.max(roundedScale, 1);
1464
- if (roundedScale < 1) {
1465
- imgLastPosition = { x: 0, y: 0 };
1421
+ this.element.appendChild(clonedImgElement);
1422
+ container.appendChild(this.element);
1423
+ this.isZooming$.next(true);
1466
1424
  }
1425
+ }
1426
+ exit() {
1427
+ var _a;
1428
+ (_a = this.element) == null ? void 0 : _a.remove();
1429
+ this.element = void 0;
1430
+ this.currentPosition = { x: 0, y: 0 };
1431
+ this.currentScale = 1;
1432
+ this.isZooming$.next(false);
1433
+ }
1434
+ moveAt(position) {
1435
+ var _a;
1436
+ const imgElement = (_a = this.element) == null ? void 0 : _a.querySelector(`img`);
1467
1437
  imgElement == null ? void 0 : imgElement.style.setProperty(
1468
1438
  `transform`,
1469
- `translate3d(${imgLastPosition.x}px, ${imgLastPosition.y}px, 0px) scale3d(${newScale}, ${newScale}, 1)`
1439
+ `translate3d(${position.x}px, ${position.y}px, 0px) scale3d(${this.currentScale}, ${this.currentScale}, 1)`
1470
1440
  );
1471
- lastUserScale = newScale;
1472
- };
1473
- const move = (delta, { isFirst, isLast }) => {
1474
- const imgElement = imageMagnifierContainer == null ? void 0 : imageMagnifierContainer.querySelector(`img`);
1475
- if (isFirst) {
1476
- movingLastDelta = delta;
1477
- }
1478
- if (delta) {
1479
- const newOffsetX = delta.x - ((movingLastDelta == null ? void 0 : movingLastDelta.x) || 0);
1480
- const newOffsetY = delta.y - ((movingLastDelta == null ? void 0 : movingLastDelta.y) || 0);
1481
- imgLastPosition = {
1482
- x: imgLastPosition.x + newOffsetX,
1483
- y: imgLastPosition.y + newOffsetY
1484
- };
1485
- imgElement == null ? void 0 : imgElement.style.setProperty(
1486
- `transform`,
1487
- `translate3d(${imgLastPosition.x}px, ${imgLastPosition.y}px, 0px) scale3d(${baseScale}, ${baseScale}, 1)`
1488
- );
1489
- movingLastDelta = delta;
1490
- }
1491
- if (isLast) {
1492
- movingLastDelta = void 0;
1493
- }
1494
- };
1495
- const exit = () => {
1496
- lastUserScale = 1;
1497
- imageMagnifierContainer == null ? void 0 : imageMagnifierContainer.remove();
1498
- imageMagnifierContainer = void 0;
1499
- isZooming$.next(false);
1500
- };
1501
- const _isZooming = () => isZooming$.value;
1502
- const destroy = () => {
1503
- imageMagnifierContainer == null ? void 0 : imageMagnifierContainer.remove();
1504
- imageMagnifierContainer = void 0;
1505
- isZooming$.complete();
1506
- };
1507
- return {
1508
- enter,
1509
- exit,
1510
- move,
1511
- scale,
1512
- setCurrentScaleAsBase,
1513
- getScaleValue: () => lastUserScale,
1514
- isZooming: _isZooming,
1515
- destroy,
1516
- isZooming$: isZooming$.asObservable()
1517
- };
1518
- };
1441
+ this.currentPosition = position;
1442
+ }
1443
+ scaleAt(userScale) {
1444
+ var _a;
1445
+ const computedScale = Math.max(0.01, userScale);
1446
+ const imgElement = (_a = this.element) == null ? void 0 : _a.querySelector(`img`);
1447
+ imgElement == null ? void 0 : imgElement.style.setProperty(
1448
+ `transform`,
1449
+ `translate3d(${this.currentPosition.x}px, ${this.currentPosition.y}px, 0px) scale3d(${computedScale}, ${computedScale}, 1)`
1450
+ );
1451
+ this.currentScale = computedScale;
1452
+ }
1453
+ }
1519
1454
  const getNewScaledOffset = ({
1520
1455
  newScale,
1521
1456
  oldScale,
@@ -1528,35 +1463,33 @@ const getNewScaledOffset = ({
1528
1463
  const realScrollOffset = scrollOffset - oldCenterPosition;
1529
1464
  return Math.max(centerXPosition + realScrollOffset * scaleDifference, 0);
1530
1465
  };
1531
- const createViewportZoomer = (reader) => {
1532
- const isZooming$ = new BehaviorSubject(false);
1533
- let baseScale = 1;
1534
- let lastUserScale = 1;
1535
- const reset = () => {
1536
- scale(0 - baseScale);
1537
- lastUserScale = 1;
1538
- baseScale = 1;
1539
- };
1540
- const enter = () => {
1541
- reset();
1542
- const spineElement = reader.spine.element;
1466
+ class ScrollableZoomer extends Zoomer {
1467
+ constructor() {
1468
+ super(...arguments);
1469
+ this.isZooming$ = new BehaviorSubject(false);
1470
+ this.currentScale = 1;
1471
+ this.currentPosition = { x: 0, y: 0 };
1472
+ }
1473
+ enter() {
1474
+ this.currentScale = 1;
1475
+ this.currentPosition = { x: 0, y: 0 };
1476
+ const spineElement = this.reader.spine.element;
1543
1477
  if (spineElement) {
1544
1478
  spineElement.style.transformOrigin = `0 0`;
1545
1479
  }
1546
- isZooming$.next(true);
1547
- scale(1);
1548
- setCurrentScaleAsBase();
1549
- };
1550
- const setCurrentScaleAsBase = () => {
1551
- baseScale = lastUserScale;
1552
- };
1553
- const scale = (userScale) => {
1554
- const spineElement = reader.spine.element;
1555
- const viewportElement = reader.navigation.getElement();
1480
+ this.isZooming$.next(true);
1481
+ }
1482
+ exit() {
1483
+ this.scaleAt(1);
1484
+ this.isZooming$.next(false);
1485
+ }
1486
+ moveAt() {
1487
+ }
1488
+ scaleAt(userScale) {
1489
+ const spineElement = this.reader.spine.element;
1490
+ const viewportElement = this.reader.navigation.getElement();
1556
1491
  if (!spineElement || !viewportElement) return;
1557
- const roundedScale = Math.ceil(
1558
- (userScale < 1 ? baseScale - (1 - userScale) : baseScale + (userScale - 1)) * 100
1559
- ) / 100;
1492
+ const roundedScale = Math.ceil(userScale * 100) / 100;
1560
1493
  const newScale = Math.max(roundedScale, 1);
1561
1494
  const currentScale = spineElement.getBoundingClientRect().width / spineElement.offsetWidth;
1562
1495
  const currentScrollTop = viewportElement.scrollTop;
@@ -1575,75 +1508,23 @@ const createViewportZoomer = (reader) => {
1575
1508
  screenSize: spineElement.offsetHeight,
1576
1509
  scrollOffset: currentScrollTop
1577
1510
  });
1578
- lastUserScale = newScale;
1579
- };
1580
- const move = (_, __) => {
1581
- };
1582
- const exit = () => {
1583
- reset();
1584
- isZooming$.next(false);
1585
- };
1586
- const _isZooming = () => isZooming$.value;
1587
- const destroy = () => {
1588
- isZooming$.complete();
1589
- };
1590
- return {
1591
- enter,
1592
- exit,
1593
- move,
1594
- scale,
1595
- setCurrentScaleAsBase,
1596
- getScaleValue: () => lastUserScale,
1597
- isZooming: _isZooming,
1598
- destroy,
1599
- isZooming$: isZooming$.asObservable()
1600
- };
1601
- };
1511
+ this.currentScale = roundedScale;
1512
+ }
1513
+ }
1602
1514
  const zoomEnhancer = (next) => (options) => {
1603
1515
  const reader = next(options);
1604
- const elementZoomer = createElementZoomer(reader);
1605
- const viewportZoomer = createViewportZoomer(reader);
1606
- const currentZoomerSubject$ = new BehaviorSubject(void 0);
1607
- const isUsingScrollableViewport = () => reader.settings.settings.computedPageTurnMode === `scrollable`;
1608
- const enter = (imgElement) => {
1609
- var _a;
1610
- (_a = currentZoomerSubject$ == null ? void 0 : currentZoomerSubject$.value) == null ? void 0 : _a.exit();
1611
- if (isUsingScrollableViewport()) {
1612
- viewportZoomer.enter();
1613
- currentZoomerSubject$ == null ? void 0 : currentZoomerSubject$.next(viewportZoomer);
1614
- return;
1615
- }
1616
- if (!imgElement) {
1617
- Report.warn(`You should specify an element to zoom at`);
1618
- return;
1619
- }
1620
- elementZoomer.enter(imgElement);
1621
- currentZoomerSubject$ == null ? void 0 : currentZoomerSubject$.next(elementZoomer);
1622
- };
1623
- const setCurrentScaleAsBase = () => {
1624
- var _a;
1625
- (_a = currentZoomerSubject$.value) == null ? void 0 : _a.setCurrentScaleAsBase();
1626
- };
1627
- const scale = (userScale) => {
1628
- var _a;
1629
- if (!((_a = currentZoomerSubject$.value) == null ? void 0 : _a.isZooming())) {
1630
- Report.warn(`You need to start zoom before being able to call this fn`);
1631
- return;
1632
- }
1633
- currentZoomerSubject$.value.scale(userScale);
1634
- };
1635
- const move = (delta, options2) => {
1636
- var _a;
1637
- (_a = currentZoomerSubject$.value) == null ? void 0 : _a.move(delta, options2);
1638
- };
1639
- const exit = () => {
1640
- var _a;
1641
- (_a = currentZoomerSubject$.value) == null ? void 0 : _a.exit();
1516
+ const controllableZoomer = new ControllableZoomer(reader);
1517
+ const scrollableZoomer = new ScrollableZoomer(reader);
1518
+ const zoomerSubject = new BehaviorSubject(scrollableZoomer);
1519
+ const enter = (element) => {
1520
+ const zoomer = reader.settings.values.computedPageTurnMode === `scrollable` ? scrollableZoomer : controllableZoomer;
1521
+ zoomerSubject.next(zoomer);
1522
+ zoomer.enter(element);
1642
1523
  };
1643
1524
  const destroy = () => {
1644
- elementZoomer.destroy();
1645
- viewportZoomer.destroy();
1646
- currentZoomerSubject$.complete();
1525
+ controllableZoomer.exit();
1526
+ scrollableZoomer.exit();
1527
+ zoomerSubject.complete();
1647
1528
  reader.destroy();
1648
1529
  };
1649
1530
  return {
@@ -1651,23 +1532,23 @@ const zoomEnhancer = (next) => (options) => {
1651
1532
  destroy,
1652
1533
  zoom: {
1653
1534
  enter,
1654
- exit,
1655
- move,
1656
- isZooming: () => {
1657
- var _a;
1658
- return ((_a = currentZoomerSubject$.value) == null ? void 0 : _a.isZooming()) || false;
1535
+ scaleAt: (scale) => zoomerSubject.getValue().scaleAt(scale),
1536
+ moveAt: (position) => zoomerSubject.getValue().moveAt(position),
1537
+ exit: () => zoomerSubject.getValue().exit(),
1538
+ get currentPosition() {
1539
+ return zoomerSubject.getValue().currentPosition;
1659
1540
  },
1660
- getScaleValue: () => {
1661
- var _a;
1662
- return ((_a = currentZoomerSubject$.value) == null ? void 0 : _a.getScaleValue()) || 1;
1541
+ get currentScale() {
1542
+ return zoomerSubject.getValue().currentScale;
1663
1543
  },
1664
- scale,
1665
- isUsingScrollableZoom: isUsingScrollableViewport,
1666
- setCurrentScaleAsBase,
1667
- $: {
1668
- isZooming$: currentZoomerSubject$.pipe(
1669
- switchMap((zoomer) => (zoomer == null ? void 0 : zoomer.isZooming$) || of(false))
1670
- )
1544
+ isZooming$: zoomerSubject.pipe(
1545
+ switchMap((zoomer) => zoomer.isZooming$)
1546
+ ),
1547
+ get zoomContainerElement() {
1548
+ return zoomerSubject.getValue().element;
1549
+ },
1550
+ get isZooming() {
1551
+ return zoomerSubject.getValue().isZooming$.getValue();
1671
1552
  }
1672
1553
  }
1673
1554
  };
@@ -1853,7 +1734,6 @@ class Pagination extends DestroyableClass {
1853
1734
  this.paginationSubject.complete();
1854
1735
  }
1855
1736
  }
1856
- const __UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT_KEY = `__UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT`;
1857
1737
  const ITEM_EXTENSION_VALID_FOR_FRAME_SRC = [`.xhtml`, `.html`, `.htm`];
1858
1738
  const HTML_PREFIX$1 = `prose-reader`;
1859
1739
  const pointerEvents$1 = [
@@ -2038,6 +1918,80 @@ const getClosestValidOffsetFromApproximateOffsetInPages = (offset, pageWidth, it
2038
1918
  return offsetValues[offsetValues.length - 1] || 0;
2039
1919
  return offsetValues.find((offsetRange) => offset < offsetRange + pageWidth) || 0;
2040
1920
  };
1921
+ const getSpineItemNumberOfPages = ({
1922
+ itemHeight,
1923
+ itemWidth,
1924
+ isUsingVerticalWriting,
1925
+ settings,
1926
+ context
1927
+ }) => {
1928
+ const { pageTurnDirection, pageTurnMode } = settings.values;
1929
+ if (pageTurnDirection === `vertical` && pageTurnMode === `scrollable`) {
1930
+ return 1;
1931
+ }
1932
+ if (isUsingVerticalWriting || pageTurnDirection === `vertical`) {
1933
+ return calculateNumberOfPagesForItem(
1934
+ itemHeight,
1935
+ context.getPageSize().height
1936
+ );
1937
+ }
1938
+ return calculateNumberOfPagesForItem(itemWidth, context.getPageSize().width);
1939
+ };
1940
+ const getSpineItemPositionFromPageIndex = ({
1941
+ pageIndex,
1942
+ itemLayout,
1943
+ context,
1944
+ isUsingVerticalWriting
1945
+ }) => {
1946
+ if (isUsingVerticalWriting) {
1947
+ const ltrRelativeOffset2 = getItemOffsetFromPageIndex(
1948
+ context.getPageSize().height,
1949
+ pageIndex,
1950
+ itemLayout.height
1951
+ );
1952
+ return {
1953
+ x: 0,
1954
+ y: ltrRelativeOffset2
1955
+ };
1956
+ }
1957
+ const ltrRelativeOffset = getItemOffsetFromPageIndex(
1958
+ context.getPageSize().width,
1959
+ pageIndex,
1960
+ itemLayout.width
1961
+ );
1962
+ if (context.isRTL()) {
1963
+ return {
1964
+ x: itemLayout.width - ltrRelativeOffset - context.getPageSize().width,
1965
+ y: 0
1966
+ };
1967
+ }
1968
+ return {
1969
+ x: ltrRelativeOffset,
1970
+ y: 0
1971
+ };
1972
+ };
1973
+ const getSpineItemPagesPosition = ({
1974
+ context,
1975
+ isUsingVerticalWriting,
1976
+ settings,
1977
+ itemLayout
1978
+ }) => {
1979
+ const numberOfPages = getSpineItemNumberOfPages({
1980
+ context,
1981
+ isUsingVerticalWriting,
1982
+ itemHeight: itemLayout.height,
1983
+ itemWidth: itemLayout.width,
1984
+ settings
1985
+ });
1986
+ return new Array(numberOfPages).fill(void 0).map(
1987
+ (_, pageIndex) => getSpineItemPositionFromPageIndex({
1988
+ context,
1989
+ isUsingVerticalWriting,
1990
+ itemLayout,
1991
+ pageIndex
1992
+ })
1993
+ );
1994
+ };
2041
1995
  const createSpineItemLocator = ({
2042
1996
  context,
2043
1997
  settings
@@ -2050,52 +2004,6 @@ const createSpineItemLocator = ({
2050
2004
  x: Math.min(itemWidth, Math.max(0, spineItemPosition.x)),
2051
2005
  y: Math.min(itemHeight, Math.max(0, spineItemPosition.y))
2052
2006
  });
2053
- const getSpineItemNumberOfPages = ({
2054
- itemHeight,
2055
- itemWidth,
2056
- isUsingVerticalWriting
2057
- }) => {
2058
- const { pageTurnDirection, pageTurnMode } = settings.settings;
2059
- if (pageTurnDirection === `vertical` && pageTurnMode === `scrollable`) {
2060
- return 1;
2061
- }
2062
- if (isUsingVerticalWriting || pageTurnDirection === `vertical`) {
2063
- return calculateNumberOfPagesForItem(
2064
- itemHeight,
2065
- context.getPageSize().height
2066
- );
2067
- }
2068
- return calculateNumberOfPagesForItem(itemWidth, context.getPageSize().width);
2069
- };
2070
- const getSpineItemPositionFromPageIndex = (pageIndex, spineItem) => {
2071
- const { width: itemWidth, height: itemHeight } = spineItem.getElementDimensions();
2072
- if (spineItem.isUsingVerticalWriting()) {
2073
- const ltrRelativeOffset2 = getItemOffsetFromPageIndex(
2074
- context.getPageSize().height,
2075
- pageIndex,
2076
- itemHeight
2077
- );
2078
- return {
2079
- x: 0,
2080
- y: ltrRelativeOffset2
2081
- };
2082
- }
2083
- const ltrRelativeOffset = getItemOffsetFromPageIndex(
2084
- context.getPageSize().width,
2085
- pageIndex,
2086
- itemWidth
2087
- );
2088
- if (context.isRTL()) {
2089
- return {
2090
- x: itemWidth - ltrRelativeOffset - context.getPageSize().width,
2091
- y: 0
2092
- };
2093
- }
2094
- return {
2095
- x: ltrRelativeOffset,
2096
- y: 0
2097
- };
2098
- };
2099
2007
  const getSpineItemPageIndexFromPosition = ({
2100
2008
  itemWidth,
2101
2009
  itemHeight,
@@ -2113,7 +2021,9 @@ const createSpineItemLocator = ({
2113
2021
  const numberOfPages = getSpineItemNumberOfPages({
2114
2022
  isUsingVerticalWriting,
2115
2023
  itemHeight,
2116
- itemWidth
2024
+ itemWidth,
2025
+ context,
2026
+ settings
2117
2027
  });
2118
2028
  if (isUsingVerticalWriting) {
2119
2029
  return getPageFromOffset(position.y, pageHeight, numberOfPages);
@@ -2133,7 +2043,7 @@ const createSpineItemLocator = ({
2133
2043
  }
2134
2044
  const spineItemWidth = ((_a = spineItem.getElementDimensions()) == null ? void 0 : _a.width) || 0;
2135
2045
  const pageWidth = context.getPageSize().width;
2136
- if (offsetOfNodeInSpineItem) {
2046
+ if (offsetOfNodeInSpineItem !== void 0) {
2137
2047
  const val = getClosestValidOffsetFromApproximateOffsetInPages(
2138
2048
  offsetOfNodeInSpineItem,
2139
2049
  pageWidth,
@@ -2149,10 +2059,12 @@ const createSpineItemLocator = ({
2149
2059
  const frame = (_a = spineItem.frame) == null ? void 0 : _a.element;
2150
2060
  if (((_b = frame == null ? void 0 : frame.contentWindow) == null ? void 0 : _b.document) && // very important because it is being used by next functions
2151
2061
  frame.contentWindow.document.body !== null) {
2152
- const { x: left, y: top } = getSpineItemPositionFromPageIndex(
2062
+ const { x: left, y: top } = getSpineItemPositionFromPageIndex({
2153
2063
  pageIndex,
2154
- spineItem
2155
- );
2064
+ itemLayout: spineItem.getElementDimensions(),
2065
+ context,
2066
+ isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting()
2067
+ });
2156
2068
  const viewport = {
2157
2069
  left,
2158
2070
  right: left + pageSize.width,
@@ -2204,12 +2116,33 @@ const createSpineItemLocator = ({
2204
2116
  };
2205
2117
  return {
2206
2118
  getSpineItemPositionFromNode,
2207
- getSpineItemPositionFromPageIndex,
2119
+ getSpineItemPositionFromPageIndex: ({
2120
+ pageIndex,
2121
+ itemLayout,
2122
+ isUsingVerticalWriting
2123
+ }) => getSpineItemPositionFromPageIndex({
2124
+ context,
2125
+ isUsingVerticalWriting,
2126
+ itemLayout,
2127
+ pageIndex
2128
+ }),
2208
2129
  getSpineItemPageIndexFromPosition,
2209
2130
  getSpineItemPageIndexFromNode,
2210
2131
  getSpineItemClosestPositionFromUnsafePosition,
2211
2132
  getFirstNodeOrRangeAtPage,
2212
- getSpineItemNumberOfPages
2133
+ getSpineItemPagesPosition: ({ item }) => {
2134
+ return getSpineItemPagesPosition({
2135
+ context,
2136
+ isUsingVerticalWriting: !!item.isUsingVerticalWriting(),
2137
+ settings,
2138
+ itemLayout: item.getElementDimensions()
2139
+ });
2140
+ },
2141
+ getSpineItemNumberOfPages: (params) => getSpineItemNumberOfPages({
2142
+ context,
2143
+ settings,
2144
+ ...params
2145
+ })
2213
2146
  };
2214
2147
  };
2215
2148
  const createNavigationResolver$1 = ({
@@ -2224,10 +2157,11 @@ const createNavigationResolver$1 = ({
2224
2157
  itemHeight: height,
2225
2158
  itemWidth: width
2226
2159
  });
2227
- return spineItemLocator.getSpineItemPositionFromPageIndex(
2228
- numberOfPages - 1,
2229
- spineItem
2230
- );
2160
+ return spineItemLocator.getSpineItemPositionFromPageIndex({
2161
+ pageIndex: numberOfPages - 1,
2162
+ isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting(),
2163
+ itemLayout: spineItem.getElementDimensions()
2164
+ });
2231
2165
  };
2232
2166
  const getNavigationFromNode = (spineItem, node, offset) => {
2233
2167
  const position = spineItemLocator.getSpineItemPositionFromNode(
@@ -2264,10 +2198,13 @@ const getAdjustedPositionWithSafeEdge = ({
2264
2198
  isRTL,
2265
2199
  pageSizeHeight,
2266
2200
  spineItemsManager,
2267
- visibleAreaRectWidth
2201
+ visibleAreaRectWidth,
2202
+ spineLayout
2268
2203
  }) => {
2269
- const lastSpineItem = spineItemsManager.get(spineItemsManager.getLength() - 1);
2270
- const distanceOfLastSpineItem = spineItemsManager.getAbsolutePositionOf(
2204
+ const lastSpineItem = spineItemsManager.get(
2205
+ spineItemsManager.items.length - 1
2206
+ );
2207
+ const distanceOfLastSpineItem = spineLayout.getAbsolutePositionOf(
2271
2208
  lastSpineItem || 0
2272
2209
  );
2273
2210
  const maximumYOffset = distanceOfLastSpineItem.bottom - pageSizeHeight;
@@ -2311,10 +2248,10 @@ const getSpinePositionFromSpineItemAnchor = ({
2311
2248
  spineItem,
2312
2249
  context
2313
2250
  });
2314
- const position = spineLocator.getSpinePositionFromSpineItemPosition(
2315
- { x: spineItemOffset, y: 0 },
2251
+ const position = spineLocator.getSpinePositionFromSpineItemPosition({
2252
+ spineItemPosition: { x: spineItemOffset, y: 0 },
2316
2253
  spineItem
2317
- );
2254
+ });
2318
2255
  return position;
2319
2256
  };
2320
2257
  const getNavigationForAnchor = ({
@@ -2390,10 +2327,10 @@ const getNavigationFromSpineItemPosition = ({
2390
2327
  spineItemPosition,
2391
2328
  spineItem
2392
2329
  );
2393
- const spinePosition = spineLocator.getSpinePositionFromSpineItemPosition(
2394
- navigationInSpineItem,
2330
+ const spinePosition = spineLocator.getSpinePositionFromSpineItemPosition({
2331
+ spineItemPosition: navigationInSpineItem,
2395
2332
  spineItem
2396
- );
2333
+ });
2397
2334
  return getAdjustedPositionForSpread({
2398
2335
  position: spinePosition,
2399
2336
  pageSizeWidth: context.getPageSize().width,
@@ -2416,10 +2353,10 @@ const getNavigationForPosition = ({
2416
2353
  spineItem,
2417
2354
  spineItemPosition
2418
2355
  );
2419
- const viewportNavigation = spineLocator.getSpinePositionFromSpineItemPosition(
2420
- spineItemValidPosition,
2356
+ const viewportNavigation = spineLocator.getSpinePositionFromSpineItemPosition({
2357
+ spineItemPosition: spineItemValidPosition,
2421
2358
  spineItem
2422
- );
2359
+ });
2423
2360
  return getAdjustedPositionForSpread({
2424
2361
  position: viewportNavigation,
2425
2362
  pageSizeWidth: context.getPageSize().width,
@@ -2446,14 +2383,15 @@ const getNavigationForSpineItemPage = ({
2446
2383
  spineLocator
2447
2384
  });
2448
2385
  }
2449
- const spineItemNavigation = spineLocator.spineItemLocator.getSpineItemPositionFromPageIndex(
2386
+ const spineItemNavigation = spineLocator.spineItemLocator.getSpineItemPositionFromPageIndex({
2450
2387
  pageIndex,
2388
+ isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting(),
2389
+ itemLayout: spineItem.getElementDimensions()
2390
+ });
2391
+ const readingOffset = spineLocator.getSpinePositionFromSpineItemPosition({
2392
+ spineItemPosition: spineItemNavigation,
2451
2393
  spineItem
2452
- );
2453
- const readingOffset = spineLocator.getSpinePositionFromSpineItemPosition(
2454
- spineItemNavigation,
2455
- spineItem
2456
- );
2394
+ });
2457
2395
  return getAdjustedPositionForSpread({
2458
2396
  position: readingOffset,
2459
2397
  pageSizeWidth: context.getPageSize().width,
@@ -3336,16 +3274,23 @@ const resolveCfi = ({
3336
3274
  if (doc) {
3337
3275
  try {
3338
3276
  const { node, offset: resolvedOffset } = cfiHandler.resolve(doc, {});
3339
- return { node, offset: offset ?? resolvedOffset, spineItemIndex };
3277
+ return {
3278
+ node,
3279
+ offset: offset ?? resolvedOffset,
3280
+ spineItemIndex,
3281
+ spineItem
3282
+ };
3340
3283
  } catch (e) {
3341
3284
  Report.error(e);
3342
3285
  return {
3343
- spineItemIndex
3286
+ spineItemIndex,
3287
+ spineItem
3344
3288
  };
3345
3289
  }
3346
3290
  }
3347
3291
  return {
3348
- spineItemIndex
3292
+ spineItemIndex,
3293
+ spineItem
3349
3294
  };
3350
3295
  };
3351
3296
  const NAMESPACE$4 = `spineNavigator`;
@@ -3353,7 +3298,8 @@ const createNavigationResolver = ({
3353
3298
  context,
3354
3299
  spineItemsManager,
3355
3300
  locator,
3356
- settings
3301
+ settings,
3302
+ spineLayout
3357
3303
  }) => {
3358
3304
  const spineItemNavigator = createNavigationResolver$1({ context, settings });
3359
3305
  const arePositionsDifferent = (a, b) => a.x !== b.x || a.y !== b.y;
@@ -3368,10 +3314,10 @@ const createNavigationResolver = ({
3368
3314
  Report.warn(NAMESPACE$4, `unable to detect item id from cfi ${cfi}`);
3369
3315
  } else {
3370
3316
  const spineItemNavigation = node ? spineItemNavigator.getNavigationFromNode(spineItem, node, offset) : { x: 0, y: 0 };
3371
- const readingPosition = locator.getSpinePositionFromSpineItemPosition(
3372
- spineItemNavigation,
3317
+ const readingPosition = locator.getSpinePositionFromSpineItemPosition({
3318
+ spineItemPosition: spineItemNavigation,
3373
3319
  spineItem
3374
- );
3320
+ });
3375
3321
  return getAdjustedPositionForSpread({
3376
3322
  position: readingPosition,
3377
3323
  pageSizeWidth: context.getPageSize().width,
@@ -3382,10 +3328,10 @@ const createNavigationResolver = ({
3382
3328
  };
3383
3329
  const getNavigationForLastPage = (spineItem) => {
3384
3330
  const spineItemNavigation = spineItemNavigator.getNavigationForLastPage(spineItem);
3385
- const position = locator.getSpinePositionFromSpineItemPosition(
3386
- spineItemNavigation,
3331
+ const position = locator.getSpinePositionFromSpineItemPosition({
3332
+ spineItemPosition: spineItemNavigation,
3387
3333
  spineItem
3388
- );
3334
+ });
3389
3335
  return getAdjustedPositionForSpread({
3390
3336
  position,
3391
3337
  pageSizeWidth: context.getPageSize().width,
@@ -3405,7 +3351,7 @@ const createNavigationResolver = ({
3405
3351
  return { x: 0, y: 0 };
3406
3352
  };
3407
3353
  const getMostPredominantNavigationForPosition = (viewportPosition) => {
3408
- const pageTurnDirection = settings.settings.computedPageTurnDirection;
3354
+ const pageTurnDirection = settings.values.computedPageTurnDirection;
3409
3355
  const triggerPercentage = 0.5;
3410
3356
  const triggerXPosition = pageTurnDirection === `horizontal` ? viewportPosition.x + context.state.visibleAreaRect.width * triggerPercentage : 0;
3411
3357
  const triggerYPosition = pageTurnDirection === `horizontal` ? 0 : viewportPosition.y + context.state.visibleAreaRect.height * triggerPercentage;
@@ -3417,7 +3363,8 @@ const createNavigationResolver = ({
3417
3363
  isRTL: context.isRTL(),
3418
3364
  pageSizeHeight: context.getPageSize().height,
3419
3365
  visibleAreaRectWidth: context.state.visibleAreaRect.width,
3420
- spineItemsManager
3366
+ spineItemsManager,
3367
+ spineLayout
3421
3368
  });
3422
3369
  return getNavigationForPosition({
3423
3370
  context,
@@ -3427,7 +3374,7 @@ const createNavigationResolver = ({
3427
3374
  });
3428
3375
  };
3429
3376
  const isNavigationGoingForwardFrom = (to, from2) => {
3430
- const pageTurnDirection = settings.settings.computedPageTurnDirection;
3377
+ const pageTurnDirection = settings.values.computedPageTurnDirection;
3431
3378
  if (pageTurnDirection === `vertical`) {
3432
3379
  return to.y > from2.y;
3433
3380
  }
@@ -3470,7 +3417,8 @@ const createNavigationResolver = ({
3470
3417
  isRTL: context.isRTL(),
3471
3418
  pageSizeHeight: context.getPageSize().height,
3472
3419
  visibleAreaRectWidth: context.state.visibleAreaRect.width,
3473
- spineItemsManager
3420
+ spineItemsManager,
3421
+ spineLayout
3474
3422
  }),
3475
3423
  isNavigationGoingForwardFrom,
3476
3424
  areNavigationDifferent,
@@ -3485,10 +3433,9 @@ const createNavigationResolver = ({
3485
3433
  };
3486
3434
  const getScaledDownPosition = ({
3487
3435
  position: { x, y },
3488
- spine,
3436
+ spineElement,
3489
3437
  element
3490
3438
  }) => {
3491
- const spineElement = spine.element;
3492
3439
  if (!spineElement) throw new Error("Invalid spine element");
3493
3440
  const spineScaleX = spineElement.getBoundingClientRect().width / spineElement.offsetWidth;
3494
3441
  const scaledDownPosition = {
@@ -3522,7 +3469,7 @@ class ViewportNavigator extends DestroyableClass {
3522
3469
  this.navigateSubject = new Subject();
3523
3470
  this.scrollingSubject = new BehaviorSubject(false);
3524
3471
  this.isScrolling$ = this.scrollingSubject.asObservable();
3525
- const settingsThatRequireLayout$ = settings.settings$.pipe(
3472
+ const settingsThatRequireLayout$ = settings.values$.pipe(
3526
3473
  mapKeysTo([
3527
3474
  `computedPageTurnDirection`,
3528
3475
  `computedPageTurnMode`,
@@ -3536,7 +3483,7 @@ class ViewportNavigator extends DestroyableClass {
3536
3483
  ).pipe(
3537
3484
  withLatestFrom(this.viewportElement$),
3538
3485
  tap$1(([, element]) => {
3539
- if (settings.settings.computedPageTurnMode === `scrollable`) {
3486
+ if (settings.values.computedPageTurnMode === `scrollable`) {
3540
3487
  element.style.removeProperty(`transform`);
3541
3488
  element.style.removeProperty(`transition`);
3542
3489
  element.style.overflow = `scroll`;
@@ -3548,7 +3495,7 @@ class ViewportNavigator extends DestroyableClass {
3548
3495
  );
3549
3496
  this.layout$ = updateElementOnSettingsChange$.pipe(
3550
3497
  tap$1(() => {
3551
- report$2.info(`layout`, settings.settings);
3498
+ report$2.info(`layout`, settings.values);
3552
3499
  }),
3553
3500
  share()
3554
3501
  );
@@ -3559,7 +3506,7 @@ class ViewportNavigator extends DestroyableClass {
3559
3506
  );
3560
3507
  this.isNavigating$ = navigate$.pipe(
3561
3508
  map$1(({ animation, position }) => {
3562
- const shouldAnimate = !(!animation || animation === `turn` && settings.settings.computedPageTurnAnimation === `none`);
3509
+ const shouldAnimate = !(!animation || animation === `turn` && settings.values.computedPageTurnAnimation === `none`);
3563
3510
  return {
3564
3511
  type: `manualAdjust`,
3565
3512
  shouldAnimate,
@@ -3576,8 +3523,8 @@ class ViewportNavigator extends DestroyableClass {
3576
3523
  of(null).pipe(
3577
3524
  mergeMap(() => {
3578
3525
  if ((currentEvent == null ? void 0 : currentEvent.type) !== `manualAdjust`) return of(false);
3579
- const animationDuration = currentEvent.animation === `snap` ? settings.settings.snapAnimationDuration : settings.settings.computedPageTurnAnimationDuration;
3580
- const pageTurnAnimation = currentEvent.animation === `snap` ? `slide` : settings.settings.computedPageTurnAnimation;
3526
+ const animationDuration = currentEvent.animation === `snap` ? settings.values.snapAnimationDuration : settings.values.computedPageTurnAnimationDuration;
3527
+ const pageTurnAnimation = currentEvent.animation === `snap` ? `slide` : settings.values.computedPageTurnAnimation;
3581
3528
  return of(currentEvent).pipe(
3582
3529
  /**
3583
3530
  * @important
@@ -3658,7 +3605,7 @@ class ViewportNavigator extends DestroyableClass {
3658
3605
  */
3659
3606
  setViewportPosition({ x, y }) {
3660
3607
  const element = this.viewportElement$.getValue();
3661
- if (this.settings.settings.computedPageTurnMode === `scrollable`) {
3608
+ if (this.settings.values.computedPageTurnMode === `scrollable`) {
3662
3609
  this.scrollingSubject.next(true);
3663
3610
  element.scrollTo({ left: x, top: y, behavior: "instant" });
3664
3611
  timer(1).pipe(
@@ -3677,14 +3624,14 @@ class ViewportNavigator extends DestroyableClass {
3677
3624
  }
3678
3625
  get viewportPosition() {
3679
3626
  const element = this.viewportElement$.getValue();
3680
- if (this.settings.settings.computedPageTurnMode === `scrollable`) {
3627
+ if (this.settings.values.computedPageTurnMode === `scrollable`) {
3681
3628
  return getScaledDownPosition({
3682
3629
  element,
3683
3630
  position: {
3684
3631
  x: (element == null ? void 0 : element.scrollLeft) ?? 0,
3685
3632
  y: (element == null ? void 0 : element.scrollTop) ?? 0
3686
3633
  },
3687
- spine: this.spine
3634
+ spineElement: this.spine.element
3688
3635
  });
3689
3636
  }
3690
3637
  const { x, y } = (element == null ? void 0 : element.getBoundingClientRect()) ?? {
@@ -3722,18 +3669,19 @@ const SCROLL_FINISHED_DEBOUNCE_TIMEOUT = 500;
3722
3669
  const NAMESPACE$2 = `navigation/UserNavigator`;
3723
3670
  const report$1 = Report.namespace(NAMESPACE$2);
3724
3671
  class UserNavigator extends DestroyableClass {
3725
- constructor(settings, element$, context, scrollHappeningFromBrowser$) {
3672
+ constructor(settings, element$, context, scrollHappeningFromBrowser$, spine) {
3726
3673
  super();
3727
3674
  this.settings = settings;
3728
3675
  this.element$ = element$;
3729
3676
  this.context = context;
3730
3677
  this.scrollHappeningFromBrowser$ = scrollHappeningFromBrowser$;
3678
+ this.spine = spine;
3731
3679
  this.navigationSubject = new Subject();
3732
3680
  this.locker = new Locker();
3733
3681
  this.navigation$ = this.navigationSubject.asObservable();
3734
3682
  const userScroll$ = element$.pipe(
3735
3683
  switchMap(
3736
- (element) => settings.settings$.pipe(
3684
+ (element) => settings.values$.pipe(
3737
3685
  map$1(({ computedPageTurnMode }) => computedPageTurnMode),
3738
3686
  distinctUntilChanged$1(),
3739
3687
  filter$1(
@@ -3750,31 +3698,10 @@ class UserNavigator extends DestroyableClass {
3750
3698
  ),
3751
3699
  share()
3752
3700
  );
3753
- const userScrollEnd$ = userScroll$.pipe(
3754
- exhaustMap(
3755
- () => userScroll$.pipe(
3756
- debounceTime$1(
3757
- SCROLL_FINISHED_DEBOUNCE_TIMEOUT,
3758
- animationFrameScheduler
3759
- )
3760
- )
3761
- ),
3762
- share()
3763
- );
3764
- const lockNavigationWhileScrolling$ = userScroll$.pipe(
3765
- exhaustMap(() => {
3766
- return userScrollEnd$.pipe(
3767
- take$1(1),
3768
- finalize(() => {
3769
- })
3770
- );
3771
- })
3772
- );
3773
- const navigateOnScroll$ = settings.settings$.pipe(
3701
+ const navigateOnScroll$ = settings.values$.pipe(
3774
3702
  map$1(({ computedPageTurnMode }) => computedPageTurnMode),
3775
3703
  distinctUntilChanged$1(),
3776
3704
  filter$1((computedPageTurnMode) => computedPageTurnMode === "scrollable"),
3777
- withLatestFrom(element$),
3778
3705
  switchMap(() => userScroll$),
3779
3706
  exhaustMap((event) => {
3780
3707
  const unlock = this.locker.lock();
@@ -3785,14 +3712,19 @@ class UserNavigator extends DestroyableClass {
3785
3712
  ),
3786
3713
  first$1(),
3787
3714
  tap$1(() => {
3788
- const element = event.target;
3715
+ const targetElement = event.target;
3716
+ const scaledDownPosition = getScaledDownPosition({
3717
+ element: targetElement,
3718
+ position: {
3719
+ x: targetElement.scrollLeft ?? 0,
3720
+ y: targetElement.scrollTop ?? 0
3721
+ },
3722
+ spineElement: this.spine.element
3723
+ });
3789
3724
  this.navigate({
3790
3725
  animation: false,
3791
3726
  type: "scroll",
3792
- position: {
3793
- x: element.scrollLeft ?? 0,
3794
- y: element.scrollTop ?? 0
3795
- }
3727
+ position: scaledDownPosition
3796
3728
  });
3797
3729
  }),
3798
3730
  finalize(() => {
@@ -3801,7 +3733,7 @@ class UserNavigator extends DestroyableClass {
3801
3733
  );
3802
3734
  })
3803
3735
  );
3804
- merge(lockNavigationWhileScrolling$, navigateOnScroll$).pipe(takeUntil(this.destroy$)).subscribe();
3736
+ merge(navigateOnScroll$).pipe(takeUntil(this.destroy$)).subscribe();
3805
3737
  }
3806
3738
  /**
3807
3739
  * Remember that this navigation is not trustable.
@@ -3820,14 +3752,15 @@ const restoreNavigationForControlledPageTurnMode = ({
3820
3752
  spineLocator,
3821
3753
  navigation,
3822
3754
  navigationResolver,
3823
- spineItemsManager
3755
+ spineItemsManager,
3756
+ spineLayout
3824
3757
  }) => {
3825
3758
  var _a, _b;
3826
3759
  const spineItem = spineItemsManager.get(navigation.spineItem);
3827
3760
  if (!spineItem) {
3828
3761
  return { x: 0, y: 0 };
3829
3762
  }
3830
- const spineItemAbsolutePosition = spineItemsManager.getAbsolutePositionOf(spineItem);
3763
+ const spineItemAbsolutePosition = spineLayout.getAbsolutePositionOf(spineItem);
3831
3764
  const isPositionWithinSpineItem = spineLocator.isPositionWithinSpineItem(
3832
3765
  navigation.position,
3833
3766
  spineItem
@@ -3884,12 +3817,13 @@ const restoreNavigationForScrollingPageTurnMode = ({
3884
3817
  spineLocator,
3885
3818
  spineItemsManager,
3886
3819
  settings,
3887
- navigationResolver
3820
+ navigationResolver,
3821
+ spineLayout
3888
3822
  }) => {
3889
3823
  const { spineItem } = navigation;
3890
3824
  const foundSpineItem = spineItemsManager.get(spineItem);
3891
3825
  if (!foundSpineItem) return { x: 0, y: 0 };
3892
- const { height, top } = spineItemsManager.getAbsolutePositionOf(foundSpineItem);
3826
+ const { height, top } = spineLayout.getAbsolutePositionOf(foundSpineItem);
3893
3827
  const isPositionWithinSpineItem = spineLocator.isPositionWithinSpineItem(
3894
3828
  navigation.position,
3895
3829
  foundSpineItem
@@ -3898,7 +3832,7 @@ const restoreNavigationForScrollingPageTurnMode = ({
3898
3832
  y: 0,
3899
3833
  x: 0
3900
3834
  };
3901
- if (settings.settings.computedPageTurnDirection === "vertical") {
3835
+ if (settings.values.computedPageTurnDirection === "vertical") {
3902
3836
  if (top === navigation.spineItemTop && height === navigation.spineItemHeight && isPositionWithinSpineItem) {
3903
3837
  return navigation.position;
3904
3838
  }
@@ -3913,10 +3847,10 @@ const restoreNavigationForScrollingPageTurnMode = ({
3913
3847
  },
3914
3848
  foundSpineItem
3915
3849
  );
3916
- return spineLocator.getSpinePositionFromSpineItemPosition(
3917
- positionInSpineItem2,
3918
- foundSpineItem
3919
- );
3850
+ return spineLocator.getSpinePositionFromSpineItemPosition({
3851
+ spineItemPosition: positionInSpineItem2,
3852
+ spineItem: foundSpineItem
3853
+ });
3920
3854
  }
3921
3855
  if (top === navigation.spineItemTop && height !== navigation.spineItemHeight) {
3922
3856
  const positionYfromBottomPreviousNavigation = (navigation.spineItemHeight ?? positionInSpineItem.y) - positionInSpineItem.y;
@@ -3929,10 +3863,10 @@ const restoreNavigationForScrollingPageTurnMode = ({
3929
3863
  positionInspineItem,
3930
3864
  foundSpineItem
3931
3865
  );
3932
- return spineLocator.getSpinePositionFromSpineItemPosition(
3933
- positionInSpineItem2,
3934
- foundSpineItem
3935
- );
3866
+ return spineLocator.getSpinePositionFromSpineItemPosition({
3867
+ spineItemPosition: positionInSpineItem2,
3868
+ spineItem: foundSpineItem
3869
+ });
3936
3870
  }
3937
3871
  if (!isPositionWithinSpineItem) {
3938
3872
  if (navigation.directionFromLastNavigation === "backward") {
@@ -3940,26 +3874,26 @@ const restoreNavigationForScrollingPageTurnMode = ({
3940
3874
  y: height - positionYfromBottomPreviousNavigation,
3941
3875
  x: navigation.position.x
3942
3876
  };
3943
- return spineLocator.getSpinePositionFromSpineItemPosition(
3944
- spineLocator.getSafeSpineItemPositionFromUnsafeSpineItemPosition(
3877
+ return spineLocator.getSpinePositionFromSpineItemPosition({
3878
+ spineItemPosition: spineLocator.getSafeSpineItemPositionFromUnsafeSpineItemPosition(
3945
3879
  positionInItem,
3946
3880
  foundSpineItem
3947
3881
  ),
3948
- foundSpineItem
3949
- );
3882
+ spineItem: foundSpineItem
3883
+ });
3950
3884
  }
3951
3885
  if (navigation.directionFromLastNavigation === "forward" || navigation.directionFromLastNavigation === "anchor") {
3952
3886
  const positionInItem = {
3953
3887
  y: height - positionYfromBottomPreviousNavigation,
3954
3888
  x: navigation.position.x
3955
3889
  };
3956
- return spineLocator.getSpinePositionFromSpineItemPosition(
3957
- spineLocator.getSafeSpineItemPositionFromUnsafeSpineItemPosition(
3890
+ return spineLocator.getSpinePositionFromSpineItemPosition({
3891
+ spineItemPosition: spineLocator.getSafeSpineItemPositionFromUnsafeSpineItemPosition(
3958
3892
  positionInItem,
3959
3893
  foundSpineItem
3960
3894
  ),
3961
- foundSpineItem
3962
- );
3895
+ spineItem: foundSpineItem
3896
+ });
3963
3897
  }
3964
3898
  return navigationResolver.getNavigationForSpineIndexOrId(foundSpineItem);
3965
3899
  }
@@ -3972,44 +3906,46 @@ const restorePosition = ({
3972
3906
  spineItemsManager,
3973
3907
  settings,
3974
3908
  spineLocator,
3975
- navigationResolver
3909
+ navigationResolver,
3910
+ spineLayout
3976
3911
  }) => {
3977
- if (settings.settings.computedPageTurnMode === "scrollable") {
3912
+ if (settings.values.computedPageTurnMode === "scrollable") {
3978
3913
  return restoreNavigationForScrollingPageTurnMode({
3979
3914
  navigation,
3980
3915
  spineLocator,
3981
3916
  navigationResolver,
3982
3917
  settings,
3983
- spineItemsManager
3918
+ spineItemsManager,
3919
+ spineLayout
3984
3920
  });
3985
3921
  }
3986
3922
  return restoreNavigationForControlledPageTurnMode({
3987
3923
  navigation,
3988
3924
  spineLocator,
3989
3925
  navigationResolver,
3990
- spineItemsManager
3926
+ spineItemsManager,
3927
+ spineLayout
3991
3928
  });
3992
3929
  };
3993
3930
  const withRestoredPosition = ({
3994
- spineItemsManager,
3995
3931
  settings,
3996
- spineLocator,
3997
3932
  navigationResolver,
3998
- spineItemLocator,
3999
- context
3933
+ context,
3934
+ spine
4000
3935
  }) => (stream) => stream.pipe(
4001
3936
  map$1((params) => ({
4002
3937
  ...params,
4003
3938
  navigation: {
4004
3939
  ...params.navigation,
4005
3940
  position: restorePosition({
4006
- spineLocator,
3941
+ spineLocator: spine.locator,
4007
3942
  navigation: params.navigation,
4008
3943
  navigationResolver,
4009
3944
  settings,
4010
- spineItemsManager,
4011
- spineItemLocator,
4012
- context
3945
+ spineItemsManager: spine.spineItemsManager,
3946
+ spineItemLocator: spine.locator.spineItemLocator,
3947
+ context,
3948
+ spineLayout: spine.spineLayout
4013
3949
  })
4014
3950
  }
4015
3951
  }))
@@ -4052,7 +3988,7 @@ const getOrGuessDirection = ({
4052
3988
  if (!navigation.position) {
4053
3989
  return "forward";
4054
3990
  }
4055
- if (settings.settings.computedPageTurnDirection === "vertical") {
3991
+ if (settings.values.computedPageTurnDirection === "vertical") {
4056
3992
  if (navigation.position.y > previousNavigation.position.y) {
4057
3993
  return "forward";
4058
3994
  } else {
@@ -4102,7 +4038,7 @@ const withSpineItemPosition = ({
4102
4038
  navigationResolver
4103
4039
  }) => (stream) => {
4104
4040
  const getPosition = (navigation) => {
4105
- const { navigationSnapThreshold, computedPageTurnMode } = settings.settings;
4041
+ const { navigationSnapThreshold, computedPageTurnMode } = settings.values;
4106
4042
  const spineItem = spineItemsManager.get(navigation.spineItem);
4107
4043
  if (!spineItem || !navigation.position) return void 0;
4108
4044
  if (computedPageTurnMode === "controlled") {
@@ -4124,10 +4060,11 @@ const withSpineItemPosition = ({
4124
4060
  restrictToScreen: true
4125
4061
  });
4126
4062
  const beginPageIndexForDirection = (navigation.directionFromLastNavigation === "forward" || navigation.directionFromLastNavigation === "anchor" ? visiblePagesAtNavigablePosition == null ? void 0 : visiblePagesAtNavigablePosition.beginPageIndex : visiblePagesAtNavigablePosition == null ? void 0 : visiblePagesAtNavigablePosition.endPageIndex) ?? 0;
4127
- const positionInSpineItem = spineLocator.spineItemLocator.getSpineItemPositionFromPageIndex(
4128
- beginPageIndexForDirection,
4129
- spineItem
4130
- );
4063
+ const positionInSpineItem = spineLocator.spineItemLocator.getSpineItemPositionFromPageIndex({
4064
+ pageIndex: beginPageIndexForDirection,
4065
+ isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting(),
4066
+ itemLayout: spineItem.getElementDimensions()
4067
+ });
4131
4068
  return positionInSpineItem;
4132
4069
  }
4133
4070
  return spineLocator.getSpineItemPositionFromSpinePosition(
@@ -4183,13 +4120,13 @@ const withFallbackPosition = ({
4183
4120
  })
4184
4121
  );
4185
4122
  };
4186
- const withSpineItemLayoutInfo = ({ spineItemsManager }) => (stream) => {
4123
+ const withSpineItemLayoutInfo = ({ spine }) => (stream) => {
4187
4124
  return stream.pipe(
4188
4125
  map$1(({ navigation, ...rest }) => {
4189
- const spineItemDimensions = spineItemsManager.getAbsolutePositionOf(
4126
+ const spineItemDimensions = spine.spineLayout.getAbsolutePositionOf(
4190
4127
  navigation.spineItem
4191
4128
  );
4192
- const spineItem = spineItemsManager.get(navigation.spineItem);
4129
+ const spineItem = spine.spineItemsManager.get(navigation.spineItem);
4193
4130
  return {
4194
4131
  navigation: {
4195
4132
  ...navigation,
@@ -4273,14 +4210,14 @@ const withSpineItem = ({
4273
4210
  cfi,
4274
4211
  directionFromLastNavigation: direction
4275
4212
  } = navigation;
4276
- const { navigationSnapThreshold, computedPageTurnMode } = settings.settings;
4213
+ const { navigationSnapThreshold, computedPageTurnMode } = settings.values;
4277
4214
  if (spineItem !== void 0) {
4278
4215
  const existingSpineItem = spineItemsManager.get(spineItem);
4279
4216
  if (existingSpineItem) return existingSpineItem;
4280
4217
  }
4281
4218
  if (typeof spineItem === "number") {
4282
- if (spineItem > spineItemsManager.getLength() - 1) {
4283
- return spineItemsManager.get(spineItemsManager.getLength() - 1);
4219
+ if (spineItem > spineItemsManager.items.length - 1) {
4220
+ return spineItemsManager.get(spineItemsManager.items.length - 1);
4284
4221
  }
4285
4222
  return spineItemsManager.get(0);
4286
4223
  }
@@ -4337,15 +4274,14 @@ const withSpineItem = ({
4337
4274
  const NAMESPACE$1 = `navigation/InternalNavigator`;
4338
4275
  const report = Report.namespace(NAMESPACE$1);
4339
4276
  class InternalNavigator extends DestroyableClass {
4340
- constructor(settings, context, userNavigation$, viewportController, navigationResolver, spineItemsManager, spineLocator, element$, isUserLocked$) {
4277
+ constructor(settings, context, userNavigation$, viewportController, navigationResolver, spine, element$, isUserLocked$) {
4341
4278
  super();
4342
4279
  this.settings = settings;
4343
4280
  this.context = context;
4344
4281
  this.userNavigation$ = userNavigation$;
4345
4282
  this.viewportController = viewportController;
4346
4283
  this.navigationResolver = navigationResolver;
4347
- this.spineItemsManager = spineItemsManager;
4348
- this.spineLocator = spineLocator;
4284
+ this.spine = spine;
4349
4285
  this.element$ = element$;
4350
4286
  this.isUserLocked$ = isUserLocked$;
4351
4287
  this.navigationSubject = new BehaviorSubject({
@@ -4371,7 +4307,7 @@ class InternalNavigator extends DestroyableClass {
4371
4307
  this.locker = new Locker();
4372
4308
  const layoutHasChanged$ = merge(
4373
4309
  viewportController.layout$,
4374
- spineItemsManager.layout$.pipe(filter$1((hasChanged) => hasChanged))
4310
+ spine.spineLayout.layout$.pipe(filter$1(({ hasChanged }) => hasChanged))
4375
4311
  );
4376
4312
  const navigationFromUser$ = userNavigation$.pipe(
4377
4313
  withLatestFrom(this.navigationSubject),
@@ -4395,43 +4331,39 @@ class InternalNavigator extends DestroyableClass {
4395
4331
  context,
4396
4332
  navigationResolver,
4397
4333
  settings,
4398
- spineItemsManager,
4399
- spineLocator
4334
+ spineItemsManager: spine.spineItemsManager,
4335
+ spineLocator: spine.locator
4400
4336
  }),
4401
4337
  withSpineItemPosition({
4402
- context,
4403
4338
  navigationResolver,
4404
4339
  settings,
4405
- spineItemsManager,
4406
- spineLocator
4340
+ spineItemsManager: spine.spineItemsManager,
4341
+ spineLocator: spine.locator
4407
4342
  }),
4408
4343
  withSpineItemLayoutInfo({
4409
- spineItemsManager
4344
+ spine
4410
4345
  })
4411
4346
  ).pipe(
4412
4347
  withFallbackPosition({
4413
4348
  navigationResolver,
4414
- spineItemsManager
4349
+ spineItemsManager: spine.spineItemsManager
4415
4350
  }),
4416
4351
  withLatestFrom(isUserLocked$),
4417
4352
  switchMap(([params, isUserLocked]) => {
4418
- const shouldNotAlterPosition = params.navigation.cfi || params.navigation.url || settings.settings.computedPageTurnMode === "scrollable" || isUserLocked;
4353
+ const shouldNotAlterPosition = params.navigation.cfi || params.navigation.url || settings.values.computedPageTurnMode === "scrollable" || isUserLocked;
4419
4354
  return of(params).pipe(
4420
4355
  shouldNotAlterPosition ? identity : withRestoredPosition({
4421
4356
  navigationResolver,
4422
4357
  settings,
4423
- spineItemsManager,
4424
- spineLocator,
4425
- spineItemLocator: spineLocator.spineItemLocator,
4358
+ spine,
4426
4359
  context
4427
4360
  })
4428
4361
  );
4429
4362
  }),
4430
4363
  withSpineItemPosition({
4431
- spineItemsManager,
4432
- spineLocator,
4364
+ spineItemsManager: spine.spineItemsManager,
4365
+ spineLocator: spine.locator,
4433
4366
  settings,
4434
- context,
4435
4367
  navigationResolver
4436
4368
  }),
4437
4369
  map$1((params) => params.navigation),
@@ -4488,10 +4420,8 @@ class InternalNavigator extends DestroyableClass {
4488
4420
  withRestoredPosition({
4489
4421
  navigationResolver,
4490
4422
  settings,
4491
- spineItemsManager,
4492
- spineLocator,
4493
- spineItemLocator: spineLocator.spineItemLocator,
4494
- context
4423
+ context,
4424
+ spine
4495
4425
  }),
4496
4426
  map$1((params) => {
4497
4427
  const navigation = {
@@ -4506,13 +4436,12 @@ class InternalNavigator extends DestroyableClass {
4506
4436
  };
4507
4437
  }),
4508
4438
  withSpineItemLayoutInfo({
4509
- spineItemsManager
4439
+ spine
4510
4440
  }),
4511
4441
  withSpineItemPosition({
4512
- spineItemsManager,
4513
- spineLocator,
4442
+ spineItemsManager: spine.spineItemsManager,
4443
+ spineLocator: spine.locator,
4514
4444
  settings,
4515
- context,
4516
4445
  navigationResolver
4517
4446
  }),
4518
4447
  map$1(({ navigation }) => navigation),
@@ -4596,7 +4525,6 @@ class InternalNavigator extends DestroyableClass {
4596
4525
  }
4597
4526
  const createNavigator = ({
4598
4527
  spineItemsManager,
4599
- spineItemsObserver,
4600
4528
  context,
4601
4529
  parentElement$,
4602
4530
  hookManager,
@@ -4608,7 +4536,8 @@ const createNavigator = ({
4608
4536
  context,
4609
4537
  settings,
4610
4538
  spineItemsManager,
4611
- locator: spine.locator
4539
+ locator: spine.locator,
4540
+ spineLayout: spine.spineLayout
4612
4541
  });
4613
4542
  const viewportNavigator = new ViewportNavigator(
4614
4543
  settings,
@@ -4620,7 +4549,7 @@ const createNavigator = ({
4620
4549
  const isSpineScrolling$ = merge(
4621
4550
  spine.elementResize$,
4622
4551
  spine.element$.pipe(switchMap$1((element) => fromEvent(element, "scroll"))),
4623
- spineItemsObserver.itemResize$
4552
+ spine.spineItemsObserver.itemResize$
4624
4553
  ).pipe(
4625
4554
  switchMap$1(() => merge(of(true), timer(5).pipe(map(() => false)))),
4626
4555
  startWith(false)
@@ -4638,7 +4567,8 @@ const createNavigator = ({
4638
4567
  settings,
4639
4568
  element$,
4640
4569
  context,
4641
- scrollHappeningFromBrowser$
4570
+ scrollHappeningFromBrowser$,
4571
+ spine
4642
4572
  );
4643
4573
  const internalNavigator = new InternalNavigator(
4644
4574
  settings,
@@ -4646,8 +4576,7 @@ const createNavigator = ({
4646
4576
  userNavigator.navigation$,
4647
4577
  viewportNavigator,
4648
4578
  navigationResolver,
4649
- spineItemsManager,
4650
- spine.locator,
4579
+ spine,
4651
4580
  element$,
4652
4581
  userNavigator.locker.isLocked$
4653
4582
  );
@@ -4729,14 +4658,14 @@ class SettingsManager3 {
4729
4658
  const { commit } = this._prepareUpdate(settings);
4730
4659
  commit();
4731
4660
  }
4732
- get settings() {
4661
+ get values() {
4733
4662
  if (!this.outputSettings) {
4734
4663
  const { commit } = this._prepareUpdate(this.inputSettings);
4735
4664
  return commit();
4736
4665
  }
4737
4666
  return this.outputSettings;
4738
4667
  }
4739
- get settings$() {
4668
+ get values$() {
4740
4669
  if (!this.outputSettings) {
4741
4670
  const { commit } = this._prepareUpdate(this.inputSettings);
4742
4671
  commit();
@@ -4756,10 +4685,10 @@ class ReaderSettingsManager extends SettingsManager3 {
4756
4685
  context.manifest$
4757
4686
  ]).pipe(
4758
4687
  tap(() => {
4759
- this.update(this.settings);
4688
+ this.update(this.values);
4760
4689
  })
4761
4690
  );
4762
- const updateContextOnSettingsChanges$ = this.settings$.pipe(
4691
+ const updateContextOnSettingsChanges$ = this.values$.pipe(
4763
4692
  tap(({ forceSinglePageMode }) => {
4764
4693
  context.update({ forceSinglePageMode });
4765
4694
  })
@@ -4899,7 +4828,7 @@ const getRootCfi = (spineItem) => {
4899
4828
  const itemAnchor = getItemAnchor(spineItem);
4900
4829
  return `epubcfi(/0${itemAnchor}) `;
4901
4830
  };
4902
- const getCfi = Report.measurePerformance(
4831
+ const generateCfiForSpineItemPage = Report.measurePerformance(
4903
4832
  `getCfi`,
4904
4833
  10,
4905
4834
  ({
@@ -4936,7 +4865,7 @@ class PaginationController extends DestroyableClass {
4936
4865
  this.spineItemLocator = spineItemLocator;
4937
4866
  const updatePagination$ = merge(
4938
4867
  this.context.bridgeEvent.navigation$,
4939
- spineItemsManager.layout$.pipe(filter$1((hasChanged) => hasChanged))
4868
+ spine.spineLayout.layout$.pipe(filter$1(({ hasChanged }) => hasChanged))
4940
4869
  ).pipe(
4941
4870
  switchMap(() => {
4942
4871
  const getVisiblePagesFromViewportPosition = ({
@@ -5021,12 +4950,12 @@ class PaginationController extends DestroyableClass {
5021
4950
  const endSpineItem = this.spineItemsManager.get(endSpineItemIndex);
5022
4951
  if (beginSpineItem === void 0 || endSpineItem === void 0) return;
5023
4952
  this.pagination.update({
5024
- beginCfi: getCfi({
4953
+ beginCfi: generateCfiForSpineItemPage({
5025
4954
  pageIndex: beginPageIndexInSpineItem,
5026
4955
  spineItem: beginSpineItem,
5027
4956
  spineItemLocator
5028
4957
  }),
5029
- endCfi: getCfi({
4958
+ endCfi: generateCfiForSpineItemPage({
5030
4959
  pageIndex: endPageIndexInSpineItem,
5031
4960
  spineItem: endSpineItem,
5032
4961
  spineItemLocator
@@ -5055,151 +4984,13 @@ const generateCfiFromRange = ({
5055
4984
  );
5056
4985
  return { start: startCFI, end: endCFI };
5057
4986
  };
5058
- class SpineItemsObserver extends DestroyableClass {
5059
- constructor(spineItemsManager) {
5060
- super();
5061
- this.spineItemsManager = spineItemsManager;
5062
- this.itemIsReady$ = this.spineItemsManager.items$.pipe(
5063
- switchMap((items) => {
5064
- const itemsIsReady$ = items.map(
5065
- (item) => item.$.isReady$.pipe(map$1((isReady) => ({ item, isReady })))
5066
- );
5067
- return merge(...itemsIsReady$);
5068
- }),
5069
- share()
5070
- );
5071
- this.itemResize$ = this.spineItemsManager.items$.pipe(
5072
- switchMap((items) => {
5073
- const resize$ = items.map(
5074
- (item) => observeResize(item.element).pipe(
5075
- map$1((entries) => ({ entries, item }))
5076
- )
5077
- );
5078
- return merge(...resize$);
5079
- }),
5080
- share()
5081
- );
5082
- }
5083
- }
5084
- const NAMESPACE = `spineItemsManager`;
5085
4987
  class SpineItemsManager extends DestroyableClass {
5086
4988
  constructor(context, settings) {
5087
4989
  super();
5088
4990
  this.context = context;
5089
4991
  this.settings = settings;
5090
- this.layoutSubject = new Subject();
5091
- this.itemLayoutInformation = [];
5092
4992
  this.orderedSpineItemsSubject = new BehaviorSubject([]);
5093
4993
  this.items$ = this.orderedSpineItemsSubject.asObservable();
5094
- this.layout$ = this.layoutSubject.asObservable();
5095
- }
5096
- /**
5097
- * @todo
5098
- * move this logic to the spine
5099
- *
5100
- * @todo
5101
- * make sure to check how many times it is being called and try to reduce number of layouts
5102
- * it is called eery time an item is being unload (which can adds up quickly for big books)
5103
- */
5104
- layout() {
5105
- const manifest = this.context.manifest;
5106
- const newItemLayoutInformation = [];
5107
- const isGloballyPrePaginated = (manifest == null ? void 0 : manifest.renditionLayout) === `pre-paginated`;
5108
- this.orderedSpineItemsSubject.value.reduce(
5109
- ({ horizontalOffset, verticalOffset }, item, index) => {
5110
- let minimumWidth = this.context.getPageSize().width;
5111
- let blankPagePosition = `none`;
5112
- const itemStartOnNewScreen = horizontalOffset % this.context.state.visibleAreaRect.width === 0;
5113
- const isLastItem = index === this.orderedSpineItemsSubject.value.length - 1;
5114
- if (this.context.state.isUsingSpreadMode) {
5115
- if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && !isLastItem) {
5116
- minimumWidth = this.context.getPageSize().width * 2;
5117
- }
5118
- if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && isLastItem && itemStartOnNewScreen) {
5119
- minimumWidth = this.context.getPageSize().width * 2;
5120
- }
5121
- const lastItemStartOnNewScreenInAPrepaginatedBook = itemStartOnNewScreen && isLastItem && isGloballyPrePaginated;
5122
- if (item.item.pageSpreadRight && itemStartOnNewScreen && !this.context.isRTL()) {
5123
- blankPagePosition = `before`;
5124
- minimumWidth = this.context.getPageSize().width * 2;
5125
- } else if (item.item.pageSpreadLeft && itemStartOnNewScreen && this.context.isRTL()) {
5126
- blankPagePosition = `before`;
5127
- minimumWidth = this.context.getPageSize().width * 2;
5128
- } else if (lastItemStartOnNewScreenInAPrepaginatedBook) {
5129
- if (this.context.isRTL()) {
5130
- blankPagePosition = `before`;
5131
- } else {
5132
- blankPagePosition = `after`;
5133
- }
5134
- minimumWidth = this.context.getPageSize().width * 2;
5135
- }
5136
- }
5137
- const { width, height } = item.layout({
5138
- minimumWidth,
5139
- blankPagePosition,
5140
- spreadPosition: this.context.state.isUsingSpreadMode ? itemStartOnNewScreen ? this.context.isRTL() ? `right` : `left` : this.context.isRTL() ? `left` : `right` : `none`
5141
- });
5142
- if (this.settings.settings.computedPageTurnDirection === `vertical`) {
5143
- const currentValidEdgeYForVerticalPositioning = itemStartOnNewScreen ? verticalOffset : verticalOffset - this.context.state.visibleAreaRect.height;
5144
- const currentValidEdgeXForVerticalPositioning = itemStartOnNewScreen ? 0 : horizontalOffset;
5145
- if (this.context.isRTL()) {
5146
- item.adjustPositionOfElement({
5147
- top: currentValidEdgeYForVerticalPositioning,
5148
- left: currentValidEdgeXForVerticalPositioning
5149
- });
5150
- } else {
5151
- item.adjustPositionOfElement({
5152
- top: currentValidEdgeYForVerticalPositioning,
5153
- left: currentValidEdgeXForVerticalPositioning
5154
- });
5155
- }
5156
- const newEdgeX = width + currentValidEdgeXForVerticalPositioning;
5157
- const newEdgeY = height + currentValidEdgeYForVerticalPositioning;
5158
- newItemLayoutInformation.push({
5159
- left: currentValidEdgeXForVerticalPositioning,
5160
- right: newEdgeX,
5161
- top: currentValidEdgeYForVerticalPositioning,
5162
- bottom: newEdgeY,
5163
- height,
5164
- width
5165
- });
5166
- return {
5167
- horizontalOffset: newEdgeX,
5168
- verticalOffset: newEdgeY
5169
- };
5170
- }
5171
- item.adjustPositionOfElement(
5172
- this.context.isRTL() ? { right: horizontalOffset, top: 0 } : { left: horizontalOffset, top: 0 }
5173
- );
5174
- newItemLayoutInformation.push({
5175
- ...this.context.isRTL() ? {
5176
- left: this.context.state.visibleAreaRect.width - horizontalOffset - width,
5177
- right: this.context.state.visibleAreaRect.width - horizontalOffset
5178
- } : {
5179
- left: horizontalOffset,
5180
- right: horizontalOffset + width
5181
- },
5182
- top: verticalOffset,
5183
- bottom: height,
5184
- height,
5185
- width
5186
- });
5187
- return {
5188
- horizontalOffset: horizontalOffset + width,
5189
- verticalOffset: 0
5190
- };
5191
- },
5192
- { horizontalOffset: 0, verticalOffset: 0 }
5193
- );
5194
- const hasLayoutChanges = this.itemLayoutInformation.length !== newItemLayoutInformation.length || this.itemLayoutInformation.some(
5195
- (old, index) => !isShallowEqual(old, newItemLayoutInformation[index])
5196
- );
5197
- this.itemLayoutInformation = newItemLayoutInformation;
5198
- Report.log(NAMESPACE, `layout`, {
5199
- hasLayoutChanges,
5200
- itemLayoutInformation: this.itemLayoutInformation
5201
- });
5202
- this.layoutSubject.next(hasLayoutChanges);
5203
4994
  }
5204
4995
  get(indexOrId) {
5205
4996
  if (typeof indexOrId === `number`) {
@@ -5212,24 +5003,6 @@ class SpineItemsManager extends DestroyableClass {
5212
5003
  }
5213
5004
  return indexOrId;
5214
5005
  }
5215
- /**
5216
- * It's important to not use x,y since we need the absolute position of each element. Otherwise x,y would be relative to
5217
- * current window (viewport).
5218
- */
5219
- getAbsolutePositionOf(spineItemOrIndex) {
5220
- const fallback = {
5221
- left: 0,
5222
- right: 0,
5223
- top: 0,
5224
- bottom: 0,
5225
- width: 0,
5226
- height: 0
5227
- };
5228
- const spineItem = this.get(spineItemOrIndex);
5229
- const indexOfItem = spineItem ? this.orderedSpineItemsSubject.value.indexOf(spineItem) : -1;
5230
- const layoutInformation = this.itemLayoutInformation[indexOfItem];
5231
- return layoutInformation || fallback;
5232
- }
5233
5006
  comparePositionOf(toCompare, withItem) {
5234
5007
  const toCompareIndex = this.getSpineItemIndex(toCompare) ?? 0;
5235
5008
  const withIndex = this.getSpineItemIndex(withItem) ?? 0;
@@ -5245,32 +5018,8 @@ class SpineItemsManager extends DestroyableClass {
5245
5018
  ...this.orderedSpineItemsSubject.getValue(),
5246
5019
  ...spineItems
5247
5020
  ]);
5248
- spineItems.forEach((spineItem) => {
5249
- spineItem.$.contentLayout$.pipe(takeUntil$1(this.context.destroy$)).subscribe(() => {
5250
- this.layout();
5251
- });
5252
- spineItem.$.loaded$.pipe(
5253
- tap(() => {
5254
- if (spineItem.isUsingVerticalWriting()) {
5255
- this.context.update({
5256
- hasVerticalWriting: true
5257
- });
5258
- } else {
5259
- this.context.update({
5260
- hasVerticalWriting: false
5261
- });
5262
- }
5263
- }),
5264
- takeUntil$1(this.context.destroy$)
5265
- ).subscribe();
5266
- });
5267
- }
5268
- get items() {
5269
- return this.orderedSpineItemsSubject.value;
5270
- }
5271
- getLength() {
5272
- return this.orderedSpineItemsSubject.value.length;
5273
5021
  }
5022
+ // @todo move
5274
5023
  getSpineItemFromCfi(cfi) {
5275
5024
  const { itemId } = extractProseMetadataFromCfi(cfi);
5276
5025
  if (itemId) {
@@ -5280,52 +5029,22 @@ class SpineItemsManager extends DestroyableClass {
5280
5029
  }
5281
5030
  return void 0;
5282
5031
  }
5032
+ get items() {
5033
+ return this.orderedSpineItemsSubject.value;
5034
+ }
5283
5035
  /**
5284
5036
  * @todo handle reload, remove subscription to each items etc. See add()
5285
5037
  */
5286
5038
  destroyItems() {
5287
5039
  this.orderedSpineItemsSubject.value.forEach((item) => item.destroy());
5288
5040
  }
5289
- destroy() {
5290
- super.destroy();
5291
- this.layoutSubject.complete();
5292
- }
5293
5041
  }
5294
- const createRemoveStyleHelper = (frameElement) => (id) => {
5295
- if (frameElement && frameElement.contentDocument && frameElement.contentDocument.head) {
5296
- const styleElement = frameElement.contentDocument.getElementById(id);
5297
- if (styleElement) {
5298
- styleElement.remove();
5299
- }
5300
- }
5301
- };
5302
- const createAddStyleHelper = (frameElement) => (id, style, prepend = false) => {
5303
- if (frameElement && frameElement.contentDocument && frameElement.contentDocument.head) {
5304
- const userStyle = document.createElement(`style`);
5305
- userStyle.id = id;
5306
- userStyle.innerHTML = style;
5307
- if (prepend) {
5308
- frameElement.contentDocument.head.prepend(userStyle);
5309
- } else {
5310
- frameElement.contentDocument.head.appendChild(userStyle);
5311
- }
5312
- }
5313
- };
5314
5042
  const getAttributeValueFromString = (string, key) => {
5315
5043
  const regExp = new RegExp(key + `\\s*=\\s*([0-9.]+)`, `i`);
5316
5044
  const match = string.match(regExp) || [];
5317
5045
  const firstMatch = match[1] || `0`;
5318
5046
  return match && parseFloat(firstMatch) || 0;
5319
5047
  };
5320
- const getOriginalFrameEventFromDocumentEvent = (event) => {
5321
- return event[__UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT_KEY];
5322
- };
5323
- const attachOriginalFrameEventToDocumentEvent = (event, frameEvent) => {
5324
- Object.defineProperty(event, __UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT_KEY, {
5325
- value: frameEvent,
5326
- enumerable: true
5327
- });
5328
- };
5329
5048
  const getIntrinsicDimensionsFromBase64Img = (data) => new Promise((resolve, reject) => {
5330
5049
  const image = new Image();
5331
5050
  image.src = data;
@@ -5386,7 +5105,7 @@ const attachFrameSrc = ({
5386
5105
  const getHtmlFromResource = (response) => createHtmlPageFromResource(response, item);
5387
5106
  return (stream) => stream.pipe(
5388
5107
  switchMap((frameElement) => {
5389
- const { fetchResource } = settings.settings;
5108
+ const { fetchResource } = settings.values;
5390
5109
  if (!fetchResource && item.href.startsWith(window.location.origin) && // we have an encoding and it's a valid html
5391
5110
  (item.mediaType && [
5392
5111
  `application/xhtml+xml`,
@@ -5438,7 +5157,7 @@ const configureFrame = ({
5438
5157
  }
5439
5158
  frame.setAttribute(`role`, `main`);
5440
5159
  if ((frame == null ? void 0 : frame.contentDocument) && body) ;
5441
- if (settings.settings.computedPageTurnMode !== `scrollable`) {
5160
+ if (settings.values.computedPageTurnMode !== `scrollable`) {
5442
5161
  frame.setAttribute(`tab-index`, `0`);
5443
5162
  }
5444
5163
  const hookResults = hookManager.execute(`item.onLoad`, item.id, {
@@ -5703,7 +5422,7 @@ class FrameItem extends DestroyableClass {
5703
5422
  if (frame) {
5704
5423
  frame.style.width = `${size.width}px`;
5705
5424
  frame.style.height = `${size.height}px`;
5706
- if (this.settings.settings.computedPageTurnMode !== `scrollable`) {
5425
+ if (this.settings.values.computedPageTurnMode !== `scrollable`) {
5707
5426
  frame.setAttribute(`tab-index`, `0`);
5708
5427
  }
5709
5428
  }
@@ -5762,14 +5481,24 @@ class FrameItem extends DestroyableClass {
5762
5481
  }
5763
5482
  addStyle(id, style, prepend) {
5764
5483
  const frameElement = this.loader.element;
5765
- if (frameElement) {
5766
- createAddStyleHelper(frameElement)(id, style, prepend);
5484
+ if (frameElement && frameElement.contentDocument && frameElement.contentDocument.head) {
5485
+ const userStyle = document.createElement(`style`);
5486
+ userStyle.id = id;
5487
+ userStyle.innerHTML = style;
5488
+ if (prepend) {
5489
+ frameElement.contentDocument.head.prepend(userStyle);
5490
+ } else {
5491
+ frameElement.contentDocument.head.appendChild(userStyle);
5492
+ }
5767
5493
  }
5768
5494
  }
5769
5495
  removeStyle(id) {
5770
5496
  const frameElement = this.loader.element;
5771
- if (frameElement) {
5772
- createRemoveStyleHelper(frameElement)(id);
5497
+ if (frameElement && frameElement.contentDocument && frameElement.contentDocument.head) {
5498
+ const styleElement = frameElement.contentDocument.getElementById(id);
5499
+ if (styleElement) {
5500
+ styleElement.remove();
5501
+ }
5773
5502
  }
5774
5503
  }
5775
5504
  }
@@ -5993,7 +5722,7 @@ const createCommonSpineItem = ({
5993
5722
  };
5994
5723
  };
5995
5724
  const getResource = async () => {
5996
- const fetchResource = settings.settings.fetchResource;
5725
+ const fetchResource = settings.values.fetchResource;
5997
5726
  const lastFetch = (_) => {
5998
5727
  if (fetchResource) {
5999
5728
  return fetchResource(item);
@@ -6139,7 +5868,7 @@ const createPrePaginatedSpineItem = ({
6139
5868
  const cssLink = buildDocumentStyle(
6140
5869
  {
6141
5870
  ...commonSpineItem.getDimensionsForPaginatedContent(),
6142
- enableTouch: settings.settings.computedPageTurnMode !== `scrollable`,
5871
+ enableTouch: settings.values.computedPageTurnMode !== `scrollable`,
6143
5872
  spreadPosition
6144
5873
  },
6145
5874
  viewportDimensions
@@ -6522,7 +6251,7 @@ const createReflowableSpineItem = ({
6522
6251
  } else {
6523
6252
  const frameStyle = commonSpineItem.isImageType() ? buildStyleForReflowableImageOnly({
6524
6253
  isScrollable: ((_f = context.manifest) == null ? void 0 : _f.renditionFlow) === `scrolled-continuous`,
6525
- enableTouch: settings.settings.computedPageTurnMode !== `scrollable`
6254
+ enableTouch: settings.values.computedPageTurnMode !== `scrollable`
6526
6255
  }) : buildStyleWithMultiColumn(
6527
6256
  commonSpineItem.getDimensionsForReflowableContent(
6528
6257
  spineItemFrame.isUsingVerticalWriting(),
@@ -6625,12 +6354,13 @@ const createSpineItem = ({
6625
6354
  const getSpineItemFromPosition = ({
6626
6355
  position,
6627
6356
  spineItemsManager,
6357
+ spineLayout,
6628
6358
  settings
6629
6359
  }) => {
6630
6360
  const spineItem = spineItemsManager.items.find((item) => {
6631
- const { left, right, bottom, top } = spineItemsManager.getAbsolutePositionOf(item);
6361
+ const { left, right, bottom, top } = spineLayout.getAbsolutePositionOf(item);
6632
6362
  const isWithinXAxis = position.x >= left && position.x < right;
6633
- if (settings.settings.computedPageTurnDirection === `horizontal`) {
6363
+ if (settings.values.computedPageTurnDirection === `horizontal`) {
6634
6364
  return isWithinXAxis;
6635
6365
  } else {
6636
6366
  return isWithinXAxis && position.y >= top && position.y < bottom;
@@ -6679,9 +6409,15 @@ const getItemVisibilityForPosition = ({
6679
6409
  context
6680
6410
  }) => {
6681
6411
  const viewportLeft = viewportPosition.x;
6682
- const viewportRight = viewportPosition.x + (context.state.visibleAreaRect.width - 1);
6412
+ const viewportRight = Math.max(
6413
+ viewportPosition.x + (context.state.visibleAreaRect.width - 1),
6414
+ 0
6415
+ );
6683
6416
  const viewportTop = viewportPosition.y;
6684
- const viewportBottom = viewportPosition.y + (context.state.visibleAreaRect.height - 1);
6417
+ const viewportBottom = Math.max(
6418
+ viewportPosition.y + (context.state.visibleAreaRect.height - 1),
6419
+ 0
6420
+ );
6685
6421
  const visibleWidthOfItem = Math.min(right, viewportRight) - Math.max(left, viewportLeft);
6686
6422
  const visibleHeightOfItem = Math.min(bottom, viewportBottom) - Math.max(top, viewportTop);
6687
6423
  const itemIsOnTheOuterEdge = visibleWidthOfItem <= 0 || visibleHeightOfItem <= 0;
@@ -6712,12 +6448,18 @@ const getVisibleSpineItemsFromPosition = ({
6712
6448
  restrictToScreen,
6713
6449
  spineItemsManager,
6714
6450
  context,
6715
- settings
6451
+ settings,
6452
+ spineLayout
6716
6453
  }) => {
6717
- const fallbackSpineItem = getSpineItemFromPosition({ position, settings, spineItemsManager }) || spineItemsManager.get(0);
6454
+ const fallbackSpineItem = getSpineItemFromPosition({
6455
+ position,
6456
+ settings,
6457
+ spineItemsManager,
6458
+ spineLayout
6459
+ }) || spineItemsManager.get(0);
6718
6460
  const spineItemsVisible = spineItemsManager.items.reduce(
6719
6461
  (acc, spineItem) => {
6720
- const itemPosition = spineItemsManager.getAbsolutePositionOf(spineItem);
6462
+ const itemPosition = spineLayout.getAbsolutePositionOf(spineItem);
6721
6463
  const { visible } = getItemVisibilityForPosition({
6722
6464
  itemPosition,
6723
6465
  threshold,
@@ -6739,22 +6481,114 @@ const getVisibleSpineItemsFromPosition = ({
6739
6481
  const endItemIndex = spineItemsManager.getSpineItemIndex(endItem);
6740
6482
  return {
6741
6483
  beginIndex: beginItemIndex ?? 0,
6742
- // beginPosition: position,
6743
6484
  endIndex: endItemIndex ?? 0
6744
- // endPosition: position,
6745
6485
  };
6746
6486
  };
6747
- const createSpineLocator = ({
6487
+ const getSpinePositionFromSpineItemPosition = ({
6488
+ spineItemPosition,
6489
+ itemLayout: { left, top }
6490
+ }) => {
6491
+ return {
6492
+ x: left + spineItemPosition.x,
6493
+ y: top + spineItemPosition.y
6494
+ };
6495
+ };
6496
+ const getSpineInfoFromAbsolutePageIndex = ({
6497
+ absolutePageIndex,
6498
+ spineLayout,
6748
6499
  spineItemsManager,
6749
6500
  context,
6750
- spineItemLocator,
6751
6501
  settings
6752
6502
  }) => {
6753
- const getSpineItemPositionFromSpinePosition = Report.measurePerformance(
6754
- `getSpineItemPositionFromSpinePosition`,
6755
- 10,
6503
+ const items = spineItemsManager.items;
6504
+ const { found, currentAbsolutePage } = items.reduce(
6505
+ (acc, item) => {
6506
+ if (acc.found) return acc;
6507
+ const itemLayout = spineLayout.getAbsolutePositionOf(item);
6508
+ const numberOfPages = getSpineItemNumberOfPages({
6509
+ isUsingVerticalWriting: !!item.isUsingVerticalWriting(),
6510
+ itemHeight: itemLayout.height,
6511
+ itemWidth: itemLayout.width,
6512
+ context,
6513
+ settings
6514
+ });
6515
+ const possiblePageIndex = absolutePageIndex - acc.currentAbsolutePage;
6516
+ const currentAbsolutePage2 = acc.currentAbsolutePage + numberOfPages;
6517
+ if (possiblePageIndex <= numberOfPages - 1) {
6518
+ return {
6519
+ ...acc,
6520
+ currentAbsolutePage: currentAbsolutePage2,
6521
+ found: { item, pageIndex: possiblePageIndex }
6522
+ };
6523
+ }
6524
+ return {
6525
+ ...acc,
6526
+ currentAbsolutePage: currentAbsolutePage2
6527
+ };
6528
+ },
6529
+ { currentAbsolutePage: 0 }
6530
+ );
6531
+ if (found) {
6532
+ return {
6533
+ spineItem: found.item,
6534
+ pageIndex: found.pageIndex,
6535
+ itemIndex: spineItemsManager.getSpineItemIndex(found.item) ?? 0,
6536
+ currentAbsolutePage
6537
+ };
6538
+ }
6539
+ return void 0;
6540
+ };
6541
+ const getAbsolutePageIndexFromPageIndex = ({
6542
+ pageIndex,
6543
+ spineItemOrId,
6544
+ spineLayout,
6545
+ spineItemsManager,
6546
+ context,
6547
+ settings
6548
+ }) => {
6549
+ const items = spineItemsManager.items;
6550
+ const spineItem = spineItemsManager.get(spineItemOrId);
6551
+ if (!spineItem) return void 0;
6552
+ const { currentAbsolutePage } = items.reduce(
6553
+ (acc, item) => {
6554
+ if (acc.found) return acc;
6555
+ const itemLayout = spineLayout.getAbsolutePositionOf(item);
6556
+ const numberOfPages = getSpineItemNumberOfPages({
6557
+ isUsingVerticalWriting: !!item.isUsingVerticalWriting(),
6558
+ itemHeight: itemLayout.height,
6559
+ itemWidth: itemLayout.width,
6560
+ context,
6561
+ settings
6562
+ });
6563
+ if (spineItem === item) {
6564
+ if (pageIndex <= numberOfPages - 1) {
6565
+ return {
6566
+ currentAbsolutePage: acc.currentAbsolutePage + pageIndex,
6567
+ found: true
6568
+ };
6569
+ }
6570
+ }
6571
+ return {
6572
+ ...acc,
6573
+ currentAbsolutePage: acc.currentAbsolutePage + numberOfPages
6574
+ };
6575
+ },
6576
+ { currentAbsolutePage: 0, found: false }
6577
+ );
6578
+ return currentAbsolutePage;
6579
+ };
6580
+ const createSpineLocator = ({
6581
+ spineItemsManager,
6582
+ context,
6583
+ spineItemLocator,
6584
+ settings,
6585
+ spineLayout
6586
+ }) => {
6587
+ const getSpineItemPositionFromSpinePosition = Report.measurePerformance(
6588
+ `getSpineItemPositionFromSpinePosition`,
6589
+ 10,
6756
6590
  (position, spineItem) => {
6757
- const { left, top } = spineItemsManager.getAbsolutePositionOf(spineItem);
6591
+ const { left, top } = spineLayout.getAbsolutePositionOf(spineItem);
6758
6592
  return {
6759
6593
  /**
6760
6594
  * when using spread the item could be on the right and therefore will be negative
@@ -6769,15 +6603,11 @@ const createSpineLocator = ({
6769
6603
  },
6770
6604
  { disable: true }
6771
6605
  );
6772
- const getSpinePositionFromSpineItemPosition = (spineItemPosition, spineItem) => {
6773
- const { left, top } = spineItemsManager.getAbsolutePositionOf(spineItem);
6774
- return {
6775
- x: left + spineItemPosition.x,
6776
- y: top + spineItemPosition.y
6777
- };
6778
- };
6779
6606
  const getSpinePositionFromSpineItem = (spineItem) => {
6780
- return getSpinePositionFromSpineItemPosition({ x: 0, y: 0 }, spineItem);
6607
+ return getSpinePositionFromSpineItemPosition({
6608
+ spineItemPosition: { x: 0, y: 0 },
6609
+ itemLayout: spineLayout.getAbsolutePositionOf(spineItem)
6610
+ });
6781
6611
  };
6782
6612
  const getSpineItemFromIframe = (iframe) => {
6783
6613
  return spineItemsManager.items.find((item) => item.frame.element === iframe);
@@ -6810,11 +6640,15 @@ const createSpineLocator = ({
6810
6640
  itemWidth: width
6811
6641
  });
6812
6642
  const pages = Array.from(Array(numberOfPages)).map((_, index) => {
6813
- const spineItemPosition = spineItemLocator.getSpineItemPositionFromPageIndex(index, spineItem);
6814
- const spinePosition = getSpinePositionFromSpineItemPosition(
6643
+ const spineItemPosition = spineItemLocator.getSpineItemPositionFromPageIndex({
6644
+ pageIndex: index,
6645
+ isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting(),
6646
+ itemLayout: spineItem.getElementDimensions()
6647
+ });
6648
+ const spinePosition = getSpinePositionFromSpineItemPosition({
6815
6649
  spineItemPosition,
6816
- spineItem
6817
- );
6650
+ itemLayout: spineLayout.getAbsolutePositionOf(spineItem)
6651
+ });
6818
6652
  return {
6819
6653
  index,
6820
6654
  absolutePosition: {
@@ -6853,24 +6687,48 @@ const createSpineLocator = ({
6853
6687
  };
6854
6688
  };
6855
6689
  const isPositionWithinSpineItem = (position, spineItem) => {
6856
- const { bottom, left, right, top } = spineItemsManager.getAbsolutePositionOf(spineItem);
6690
+ const { bottom, left, right, top } = spineLayout.getAbsolutePositionOf(spineItem);
6857
6691
  return position.x >= left && position.x <= right && position.y <= bottom && position.y >= top;
6858
6692
  };
6859
6693
  const getSafeSpineItemPositionFromUnsafeSpineItemPosition = (unsafePosition, spineItem) => {
6860
- const { height, width } = spineItemsManager.getAbsolutePositionOf(spineItem);
6694
+ const { height, width } = spineLayout.getAbsolutePositionOf(spineItem);
6861
6695
  return {
6862
6696
  x: Math.min(Math.max(0, unsafePosition.x), width),
6863
6697
  y: Math.min(Math.max(0, unsafePosition.y), height)
6864
6698
  };
6865
6699
  };
6866
6700
  return {
6867
- getSpinePositionFromSpineItemPosition,
6701
+ getSpinePositionFromSpineItemPosition: ({
6702
+ spineItem,
6703
+ spineItemPosition
6704
+ }) => {
6705
+ const itemLayout = spineLayout.getAbsolutePositionOf(spineItem);
6706
+ return getSpinePositionFromSpineItemPosition({
6707
+ itemLayout,
6708
+ spineItemPosition
6709
+ });
6710
+ },
6711
+ getAbsolutePageIndexFromPageIndex: (params) => getAbsolutePageIndexFromPageIndex({
6712
+ ...params,
6713
+ context,
6714
+ settings,
6715
+ spineItemsManager,
6716
+ spineLayout
6717
+ }),
6718
+ getSpineInfoFromAbsolutePageIndex: (params) => getSpineInfoFromAbsolutePageIndex({
6719
+ ...params,
6720
+ context,
6721
+ settings,
6722
+ spineItemsManager,
6723
+ spineLayout
6724
+ }),
6868
6725
  getSpinePositionFromSpineItem,
6869
6726
  getSpineItemPositionFromSpinePosition,
6870
6727
  getSpineItemFromPosition: (position) => getSpineItemFromPosition({
6871
6728
  position,
6872
6729
  settings,
6873
- spineItemsManager
6730
+ spineItemsManager,
6731
+ spineLayout
6874
6732
  }),
6875
6733
  getSpineItemFromIframe,
6876
6734
  getSpineItemPageIndexFromNode,
@@ -6878,6 +6736,7 @@ const createSpineLocator = ({
6878
6736
  context,
6879
6737
  settings,
6880
6738
  spineItemsManager,
6739
+ spineLayout,
6881
6740
  ...params
6882
6741
  }),
6883
6742
  getVisiblePagesFromViewportPosition,
@@ -6891,7 +6750,7 @@ const loadItems = ({
6891
6750
  settings
6892
6751
  }) => (stream) => stream.pipe(
6893
6752
  tap$1(([beginIndex, endIndex]) => {
6894
- const { numberOfAdjacentSpineItemToPreLoad } = settings.settings;
6753
+ const { numberOfAdjacentSpineItemToPreLoad } = settings.values;
6895
6754
  const leftMaximumIndex = beginIndex - numberOfAdjacentSpineItemToPreLoad;
6896
6755
  const rightMaximumIndex = endIndex + numberOfAdjacentSpineItemToPreLoad;
6897
6756
  spineItemsManager.items.forEach((orderedSpineItem, index) => {
@@ -6914,17 +6773,18 @@ const mapToItemsToLoad = ({ spineLocator }) => (stream) => stream.pipe(
6914
6773
  })
6915
6774
  );
6916
6775
  class SpineItemsLoader extends DestroyableClass {
6917
- constructor(context, spineItemsManager, spineLocator, settings) {
6776
+ constructor(context, spineItemsManager, spineLocator, settings, spineLayout) {
6918
6777
  super();
6919
6778
  this.context = context;
6920
6779
  this.spineItemsManager = spineItemsManager;
6921
6780
  this.spineLocator = spineLocator;
6922
6781
  this.settings = settings;
6782
+ this.spineLayout = spineLayout;
6923
6783
  const navigationUpdate$ = this.context.bridgeEvent.navigation$;
6924
- const layoutHasChanged$ = spineItemsManager.layout$.pipe(
6925
- filter$1((hasChanged) => hasChanged)
6784
+ const layoutHasChanged$ = this.spineLayout.layout$.pipe(
6785
+ filter$1(({ hasChanged }) => hasChanged)
6926
6786
  );
6927
- const numberOfAdjacentSpineItemToPreLoad$ = settings.settings$.pipe(
6787
+ const numberOfAdjacentSpineItemToPreLoad$ = settings.values$.pipe(
6928
6788
  map$1(
6929
6789
  ({ numberOfAdjacentSpineItemToPreLoad }) => numberOfAdjacentSpineItemToPreLoad
6930
6790
  ),
@@ -6949,6 +6809,272 @@ class SpineItemsLoader extends DestroyableClass {
6949
6809
  loadSpineItems$.pipe(takeUntil(this.destroy$)).subscribe();
6950
6810
  }
6951
6811
  }
6812
+ class SpineItemsObserver extends DestroyableClass {
6813
+ constructor(spineItemsManager, spineLocator) {
6814
+ super();
6815
+ this.spineItemsManager = spineItemsManager;
6816
+ this.spineLocator = spineLocator;
6817
+ this.itemIsReady$ = this.spineItemsManager.items$.pipe(
6818
+ switchMap((items) => {
6819
+ const itemsIsReady$ = items.map(
6820
+ (item) => item.$.isReady$.pipe(map$1((isReady) => ({ item, isReady })))
6821
+ );
6822
+ return merge(...itemsIsReady$);
6823
+ }),
6824
+ share()
6825
+ );
6826
+ this.itemResize$ = this.spineItemsManager.items$.pipe(
6827
+ switchMap((items) => {
6828
+ const resize$ = items.map(
6829
+ (item) => observeResize(item.element).pipe(
6830
+ map$1((entries) => ({ entries, item }))
6831
+ )
6832
+ );
6833
+ return merge(...resize$);
6834
+ }),
6835
+ share()
6836
+ );
6837
+ }
6838
+ }
6839
+ const convertSpinePositionToLayoutPosition = ({
6840
+ position,
6841
+ pageSize
6842
+ }) => {
6843
+ return {
6844
+ x: position.x,
6845
+ y: position.y,
6846
+ left: position.x,
6847
+ top: position.y,
6848
+ width: pageSize.width,
6849
+ height: pageSize.height,
6850
+ bottom: position.y + pageSize.height,
6851
+ right: position.x + pageSize.width
6852
+ };
6853
+ };
6854
+ const NAMESPACE = `SpineLayout`;
6855
+ class SpineLayout extends DestroyableClass {
6856
+ constructor(spineItemsManager, context, settings) {
6857
+ super();
6858
+ this.spineItemsManager = spineItemsManager;
6859
+ this.context = context;
6860
+ this.settings = settings;
6861
+ this.itemLayoutInformation = [];
6862
+ this.layoutSubject = new Subject();
6863
+ spineItemsManager.items$.pipe(
6864
+ switchMap((items) => {
6865
+ const itemsLayout$ = items.map(
6866
+ (spineItem) => spineItem.$.contentLayout$.pipe(
6867
+ tap$1(() => {
6868
+ this.layout();
6869
+ })
6870
+ )
6871
+ );
6872
+ const writingModeUpdate$ = items.map(
6873
+ (spineItem) => spineItem.$.loaded$.pipe(
6874
+ tap$1(() => {
6875
+ if (spineItem.isUsingVerticalWriting()) {
6876
+ this.context.update({
6877
+ hasVerticalWriting: true
6878
+ });
6879
+ } else {
6880
+ this.context.update({
6881
+ hasVerticalWriting: false
6882
+ });
6883
+ }
6884
+ })
6885
+ )
6886
+ );
6887
+ return merge(...itemsLayout$, ...writingModeUpdate$);
6888
+ })
6889
+ ).pipe(takeUntil(this.destroy$)).subscribe();
6890
+ this.layout$ = this.layoutSubject.pipe(
6891
+ map$1((hasChanged) => ({ hasChanged })),
6892
+ startWith$1({ hasChanged: true }),
6893
+ map$1(({ hasChanged }) => {
6894
+ const items = spineItemsManager.items;
6895
+ const spineItemsPagesAbsolutePositions = items.map((item) => {
6896
+ const itemLayout = this.getAbsolutePositionOf(item);
6897
+ const numberOfPages = getSpineItemNumberOfPages({
6898
+ isUsingVerticalWriting: !!item.isUsingVerticalWriting(),
6899
+ itemHeight: itemLayout.height,
6900
+ itemWidth: itemLayout.width,
6901
+ context,
6902
+ settings
6903
+ });
6904
+ const pages2 = new Array(numberOfPages).fill(void 0);
6905
+ return pages2.map(
6906
+ (_, pageIndex) => convertSpinePositionToLayoutPosition({
6907
+ pageSize: this.context.getPageSize(),
6908
+ position: getSpinePositionFromSpineItemPosition({
6909
+ itemLayout,
6910
+ spineItemPosition: getSpineItemPositionFromPageIndex({
6911
+ isUsingVerticalWriting: !!item.isUsingVerticalWriting(),
6912
+ itemLayout,
6913
+ pageIndex,
6914
+ context
6915
+ })
6916
+ })
6917
+ })
6918
+ );
6919
+ });
6920
+ const pages = spineItemsPagesAbsolutePositions.reduce(
6921
+ (acc, itemPages, itemIndex) => {
6922
+ const itemPagesInfo = itemPages.map(
6923
+ (absolutePosition, pageIndex) => ({
6924
+ itemIndex,
6925
+ absolutePageIndex: itemIndex + pageIndex,
6926
+ absolutePosition
6927
+ })
6928
+ );
6929
+ return [...acc, ...itemPagesInfo];
6930
+ },
6931
+ []
6932
+ );
6933
+ return {
6934
+ hasChanged,
6935
+ spineItemsAbsolutePositions: items.map(
6936
+ (item) => this.getAbsolutePositionOf(item)
6937
+ ),
6938
+ spineItemsPagesAbsolutePositions,
6939
+ pages
6940
+ };
6941
+ }),
6942
+ shareReplay$1(1)
6943
+ );
6944
+ }
6945
+ /**
6946
+ * @todo
6947
+ * move this logic to the spine
6948
+ *
6949
+ * @todo
6950
+ * make sure to check how many times it is being called and try to reduce number of layouts
6951
+ * it is called eery time an item is being unload (which can adds up quickly for big books)
6952
+ */
6953
+ layout() {
6954
+ const manifest = this.context.manifest;
6955
+ const newItemLayoutInformation = [];
6956
+ const isGloballyPrePaginated = (manifest == null ? void 0 : manifest.renditionLayout) === `pre-paginated`;
6957
+ this.spineItemsManager.items.reduce(
6958
+ ({ horizontalOffset, verticalOffset }, item, index) => {
6959
+ let minimumWidth = this.context.getPageSize().width;
6960
+ let blankPagePosition = `none`;
6961
+ const itemStartOnNewScreen = horizontalOffset % this.context.state.visibleAreaRect.width === 0;
6962
+ const isLastItem = index === this.spineItemsManager.items.length - 1;
6963
+ if (this.context.state.isUsingSpreadMode) {
6964
+ if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && !isLastItem) {
6965
+ minimumWidth = this.context.getPageSize().width * 2;
6966
+ }
6967
+ if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && isLastItem && itemStartOnNewScreen) {
6968
+ minimumWidth = this.context.getPageSize().width * 2;
6969
+ }
6970
+ const lastItemStartOnNewScreenInAPrepaginatedBook = itemStartOnNewScreen && isLastItem && isGloballyPrePaginated;
6971
+ if (item.item.pageSpreadRight && itemStartOnNewScreen && !this.context.isRTL()) {
6972
+ blankPagePosition = `before`;
6973
+ minimumWidth = this.context.getPageSize().width * 2;
6974
+ } else if (item.item.pageSpreadLeft && itemStartOnNewScreen && this.context.isRTL()) {
6975
+ blankPagePosition = `before`;
6976
+ minimumWidth = this.context.getPageSize().width * 2;
6977
+ } else if (lastItemStartOnNewScreenInAPrepaginatedBook) {
6978
+ if (this.context.isRTL()) {
6979
+ blankPagePosition = `before`;
6980
+ } else {
6981
+ blankPagePosition = `after`;
6982
+ }
6983
+ minimumWidth = this.context.getPageSize().width * 2;
6984
+ }
6985
+ }
6986
+ const { width, height } = item.layout({
6987
+ minimumWidth,
6988
+ blankPagePosition,
6989
+ spreadPosition: this.context.state.isUsingSpreadMode ? itemStartOnNewScreen ? this.context.isRTL() ? `right` : `left` : this.context.isRTL() ? `left` : `right` : `none`
6990
+ });
6991
+ if (this.settings.values.computedPageTurnDirection === `vertical`) {
6992
+ const currentValidEdgeYForVerticalPositioning = itemStartOnNewScreen ? verticalOffset : verticalOffset - this.context.state.visibleAreaRect.height;
6993
+ const currentValidEdgeXForVerticalPositioning = itemStartOnNewScreen ? 0 : horizontalOffset;
6994
+ if (this.context.isRTL()) {
6995
+ item.adjustPositionOfElement({
6996
+ top: currentValidEdgeYForVerticalPositioning,
6997
+ left: currentValidEdgeXForVerticalPositioning
6998
+ });
6999
+ } else {
7000
+ item.adjustPositionOfElement({
7001
+ top: currentValidEdgeYForVerticalPositioning,
7002
+ left: currentValidEdgeXForVerticalPositioning
7003
+ });
7004
+ }
7005
+ const newEdgeX = width + currentValidEdgeXForVerticalPositioning;
7006
+ const newEdgeY = height + currentValidEdgeYForVerticalPositioning;
7007
+ newItemLayoutInformation.push({
7008
+ left: currentValidEdgeXForVerticalPositioning,
7009
+ right: newEdgeX,
7010
+ top: currentValidEdgeYForVerticalPositioning,
7011
+ bottom: newEdgeY,
7012
+ height,
7013
+ width,
7014
+ x: currentValidEdgeXForVerticalPositioning,
7015
+ y: currentValidEdgeYForVerticalPositioning
7016
+ });
7017
+ return {
7018
+ horizontalOffset: newEdgeX,
7019
+ verticalOffset: newEdgeY
7020
+ };
7021
+ }
7022
+ item.adjustPositionOfElement(
7023
+ this.context.isRTL() ? { right: horizontalOffset, top: 0 } : { left: horizontalOffset, top: 0 }
7024
+ );
7025
+ const left = this.context.isRTL() ? this.context.state.visibleAreaRect.width - horizontalOffset - width : horizontalOffset;
7026
+ newItemLayoutInformation.push({
7027
+ right: this.context.isRTL() ? this.context.state.visibleAreaRect.width - horizontalOffset : horizontalOffset + width,
7028
+ left,
7029
+ x: left,
7030
+ top: verticalOffset,
7031
+ bottom: height,
7032
+ height,
7033
+ width,
7034
+ y: verticalOffset
7035
+ });
7036
+ return {
7037
+ horizontalOffset: horizontalOffset + width,
7038
+ verticalOffset: 0
7039
+ };
7040
+ },
7041
+ { horizontalOffset: 0, verticalOffset: 0 }
7042
+ );
7043
+ const hasLayoutChanges = this.itemLayoutInformation.length !== newItemLayoutInformation.length || this.itemLayoutInformation.some(
7044
+ (old, index) => !isShallowEqual(old, newItemLayoutInformation[index])
7045
+ );
7046
+ this.itemLayoutInformation = newItemLayoutInformation;
7047
+ Report.log(NAMESPACE, `layout`, {
7048
+ hasLayoutChanges,
7049
+ itemLayoutInformation: this.itemLayoutInformation
7050
+ });
7051
+ this.layoutSubject.next(hasLayoutChanges);
7052
+ }
7053
+ /**
7054
+ * It's important to not use x,y since we need the absolute position of each element. Otherwise x,y would be relative to
7055
+ * current window (viewport).
7056
+ */
7057
+ getAbsolutePositionOf(spineItemOrIndex) {
7058
+ const fallback = {
7059
+ left: 0,
7060
+ right: 0,
7061
+ top: 0,
7062
+ bottom: 0,
7063
+ width: 0,
7064
+ height: 0,
7065
+ x: 0,
7066
+ y: 0
7067
+ };
7068
+ const spineItem = this.spineItemsManager.get(spineItemOrIndex);
7069
+ const indexOfItem = spineItem ? this.spineItemsManager.items.indexOf(spineItem) : -1;
7070
+ const layoutInformation = this.itemLayoutInformation[indexOfItem];
7071
+ return layoutInformation || fallback;
7072
+ }
7073
+ destroy() {
7074
+ super.destroy();
7075
+ this.layoutSubject.complete();
7076
+ }
7077
+ }
6952
7078
  class Spine extends DestroyableClass {
6953
7079
  constructor(parentElement$, context, pagination, spineItemsManager, spineItemLocator, settings, hookManager) {
6954
7080
  super();
@@ -6965,17 +7091,24 @@ class Spine extends DestroyableClass {
6965
7091
  share$1()
6966
7092
  );
6967
7093
  this.element$ = this.elementSubject.asObservable();
7094
+ this.spineLayout = new SpineLayout(spineItemsManager, context, settings);
6968
7095
  this.locator = createSpineLocator({
6969
7096
  context,
6970
7097
  spineItemsManager,
6971
7098
  spineItemLocator,
6972
- settings
7099
+ settings,
7100
+ spineLayout: this.spineLayout
6973
7101
  });
6974
7102
  this.spineItemsLoader = new SpineItemsLoader(
6975
7103
  this.context,
6976
7104
  spineItemsManager,
6977
7105
  this.locator,
6978
- settings
7106
+ settings,
7107
+ this.spineLayout
7108
+ );
7109
+ this.spineItemsObserver = new SpineItemsObserver(
7110
+ spineItemsManager,
7111
+ this.locator
6979
7112
  );
6980
7113
  const reloadOnManifestChange$ = context.manifest$.pipe(
6981
7114
  tap((manifest) => {
@@ -7010,7 +7143,7 @@ class Spine extends DestroyableClass {
7010
7143
  return this.elementSubject.getValue();
7011
7144
  }
7012
7145
  layout() {
7013
- this.spineItemsManager.layout();
7146
+ this.spineLayout.layout();
7014
7147
  }
7015
7148
  isSelecting() {
7016
7149
  return this.spineItemsManager.items.some(
@@ -7021,9 +7154,6 @@ class Spine extends DestroyableClass {
7021
7154
  var _a;
7022
7155
  return (_a = this.spineItemsManager.items.find((item) => item.selectionTracker.getSelection())) == null ? void 0 : _a.selectionTracker.getSelection();
7023
7156
  }
7024
- get layout$() {
7025
- return this.spineItemsManager.layout$;
7026
- }
7027
7157
  destroy() {
7028
7158
  super.destroy();
7029
7159
  this.spineItemsLoader.destroy();
@@ -7061,11 +7191,9 @@ const createReader = (inputSettings) => {
7061
7191
  settingsManager,
7062
7192
  hookManager
7063
7193
  );
7064
- const spineItemsObserver = new SpineItemsObserver(spineItemsManager);
7065
7194
  const navigator2 = createNavigator({
7066
7195
  context,
7067
7196
  spineItemsManager,
7068
- spineItemsObserver,
7069
7197
  parentElement$: elementSubject$,
7070
7198
  hookManager,
7071
7199
  spine,
@@ -7111,26 +7239,27 @@ const createReader = (inputSettings) => {
7111
7239
  });
7112
7240
  spine.layout();
7113
7241
  };
7114
- const load = (manifest, loadOptions) => {
7242
+ const load = (options) => {
7115
7243
  var _a;
7244
+ const { containerElement, manifest } = options;
7116
7245
  if (context.manifest) {
7117
7246
  Report.warn(`loading a new book is not supported yet`);
7118
7247
  return;
7119
7248
  }
7120
- Report.log(`load`, { manifest, loadOptions });
7121
- const element = createWrapperElement(loadOptions.containerElement);
7122
- if (loadOptions.containerElement !== ((_a = elementSubject$.getValue()) == null ? void 0 : _a.parentElement)) {
7249
+ Report.log(`load`, { options });
7250
+ const element = createWrapperElement(containerElement);
7251
+ if (containerElement !== ((_a = elementSubject$.getValue()) == null ? void 0 : _a.parentElement)) {
7123
7252
  elementSubject$.next(element);
7124
- loadOptions.containerElement.appendChild(element);
7253
+ containerElement.appendChild(element);
7125
7254
  }
7126
7255
  context.update({
7127
7256
  manifest,
7128
- ...loadOptions,
7129
- forceSinglePageMode: settingsManager.settings.forceSinglePageMode
7257
+ containerElement,
7258
+ forceSinglePageMode: settingsManager.values.forceSinglePageMode
7130
7259
  });
7131
7260
  layout();
7132
7261
  };
7133
- merge(context.state$, settingsManager.settings$).pipe(
7262
+ merge(context.state$, settingsManager.values$).pipe(
7134
7263
  map(() => void 0),
7135
7264
  withLatestFrom$1(context.state$),
7136
7265
  map(([, { hasVerticalWriting }]) => {
@@ -7139,7 +7268,7 @@ const createReader = (inputSettings) => {
7139
7268
  hasVerticalWriting,
7140
7269
  renditionFlow: manifest == null ? void 0 : manifest.renditionFlow,
7141
7270
  renditionLayout: manifest == null ? void 0 : manifest.renditionLayout,
7142
- computedPageTurnMode: settingsManager.settings.computedPageTurnMode
7271
+ computedPageTurnMode: settingsManager.values.computedPageTurnMode
7143
7272
  };
7144
7273
  }),
7145
7274
  distinctUntilChanged(isShallowEqual),
@@ -7180,22 +7309,23 @@ const createReader = (inputSettings) => {
7180
7309
  hookManager,
7181
7310
  cfi: {
7182
7311
  generateCfiFromRange,
7312
+ generateCfiForSpineItemPage: (params) => generateCfiForSpineItemPage({
7313
+ ...params,
7314
+ spineItemLocator
7315
+ }),
7183
7316
  resolveCfi: (params) => resolveCfi({ ...params, spineItemsManager })
7184
7317
  },
7185
7318
  navigation: {
7186
7319
  viewportFree$: context.bridgeEvent.viewportFree$,
7187
7320
  viewportBusy$: context.bridgeEvent.viewportBusy$,
7188
- // rest safe
7189
- get viewportPosition() {
7190
- return navigator2.viewportNavigator.viewportPosition;
7191
- },
7321
+ getViewportPosition: () => navigator2.viewportNavigator.viewportPosition,
7192
7322
  getNavigation: navigator2.getNavigation.bind(navigator2),
7193
7323
  getElement: navigator2.getElement.bind(navigator2),
7194
7324
  navigate: navigator2.navigate.bind(navigator2),
7195
7325
  lock: navigator2.lock.bind(navigator2),
7196
7326
  navigationResolver: navigator2.navigationResolver
7197
7327
  },
7198
- spineItemsObserver,
7328
+ spineItemsObserver: spine.spineItemsObserver,
7199
7329
  spineItemsManager,
7200
7330
  layout,
7201
7331
  load,
@@ -7206,17 +7336,19 @@ const createReader = (inputSettings) => {
7206
7336
  },
7207
7337
  settings: settingsManager,
7208
7338
  element$,
7339
+ layout$: spine.spineLayout.layout$,
7340
+ viewportState$: context.bridgeEvent.viewportState$,
7341
+ /**
7342
+ * Dispatched when the reader has loaded a book and is rendering a book.
7343
+ * Using navigation API and getting information about current content will
7344
+ * have an effect.
7345
+ * It can typically be used to hide a loading indicator.
7346
+ */
7347
+ state$: context.manifest$.pipe(
7348
+ map((manifest) => manifest ? "ready" : "idle")
7349
+ ),
7209
7350
  $: {
7210
7351
  state$: stateSubject$.asObservable(),
7211
- /**
7212
- * Dispatched when the reader has loaded a book and is rendering a book.
7213
- * Using navigation API and getting information about current content will
7214
- * have an effect.
7215
- * It can typically be used to hide a loading indicator.
7216
- */
7217
- loadStatus$: context.manifest$.pipe(
7218
- map((manifest) => manifest ? "ready" : "idle")
7219
- ),
7220
7352
  destroy$
7221
7353
  }
7222
7354
  };
@@ -7557,8 +7689,8 @@ const progressionEnhancer = (next) => (options) => {
7557
7689
  };
7558
7690
  const getScrollPercentageWithinItem = (context, currentPosition, currentItem) => {
7559
7691
  const { height, width } = currentItem.getElementDimensions();
7560
- const { top, left } = reader.spineItemsManager.getAbsolutePositionOf(currentItem);
7561
- if (reader.settings.settings.computedPageTurnDirection === `vertical`) {
7692
+ const { top, left } = reader.spine.spineLayout.getAbsolutePositionOf(currentItem);
7693
+ if (reader.settings.values.computedPageTurnDirection === `vertical`) {
7562
7694
  return Math.max(
7563
7695
  0,
7564
7696
  Math.min(
@@ -7678,7 +7810,7 @@ const loadingEnhancer = (next) => (options) => {
7678
7810
  };
7679
7811
  }, {})
7680
7812
  );
7681
- const updateEntriesLayout$ = (entries) => combineLatest([reader.spine.layout$, reader.theme.$.theme$]).pipe(
7813
+ const updateEntriesLayout$ = (entries) => combineLatest([reader.layout$, reader.theme.$.theme$]).pipe(
7682
7814
  map(([, theme]) => ({
7683
7815
  width: reader.context.state.visibleAreaRect.width,
7684
7816
  theme
@@ -7769,84 +7901,74 @@ const defaultLoadingElementCreate = ({
7769
7901
  container.appendChild(detailsElement);
7770
7902
  return container;
7771
7903
  };
7772
- const createNormalizeEventForViewport = ({
7773
- iframeEventBridgeElement$,
7774
- locator
7775
- }) => {
7776
- const normalizeEventForViewport = (event) => {
7777
- var _a;
7778
- const eventIsComingFromBridge = event.target === iframeEventBridgeElement$.getValue();
7779
- const iframeOriginalEvent = getOriginalFrameEventFromDocumentEvent(event);
7780
- const originalFrame = (_a = iframeOriginalEvent == null ? void 0 : iframeOriginalEvent.view) == null ? void 0 : _a.frameElement;
7781
- if (!eventIsComingFromBridge || !iframeOriginalEvent || !originalFrame)
7782
- return event;
7783
- const spineItem = locator.getSpineItemFromIframe(originalFrame);
7784
- if (!spineItem) return event;
7785
- if (isPointerEvent(event)) {
7786
- const { clientX, clientY } = spineItem.translateFramePositionIntoPage(event);
7787
- const newEvent = new PointerEvent(event.type, {
7788
- ...event,
7789
- pointerId: event.pointerId,
7790
- clientX,
7791
- clientY
7792
- });
7793
- Object.defineProperty(newEvent, `target`, {
7794
- value: iframeOriginalEvent.target,
7795
- enumerable: true
7796
- });
7797
- return newEvent;
7798
- }
7799
- if (isMouseEvent(event)) {
7800
- const { clientX, clientY } = spineItem.translateFramePositionIntoPage(event);
7801
- const newEvent = new MouseEvent(event.type, {
7802
- ...event,
7904
+ const __UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT_KEY = `__UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT`;
7905
+ const attachOriginalFrameEventToDocumentEvent = (event, frameEvent) => {
7906
+ Object.defineProperty(event, __UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT_KEY, {
7907
+ value: frameEvent,
7908
+ enumerable: true
7909
+ });
7910
+ };
7911
+ const getOriginalFrameEventFromDocumentEvent = (event) => {
7912
+ return event[__UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT_KEY];
7913
+ };
7914
+ const normalizeEventForViewport = (event, locator) => {
7915
+ var _a;
7916
+ const eventIsComingFromBridge = __UNSAFE_REFERENCE_ORIGINAL_IFRAME_EVENT_KEY in event;
7917
+ const iframeOriginalEvent = getOriginalFrameEventFromDocumentEvent(event);
7918
+ const originalFrame = (_a = iframeOriginalEvent == null ? void 0 : iframeOriginalEvent.view) == null ? void 0 : _a.frameElement;
7919
+ if (!eventIsComingFromBridge || !iframeOriginalEvent || !originalFrame)
7920
+ return event;
7921
+ const spineItem = locator.getSpineItemFromIframe(originalFrame);
7922
+ if (!spineItem) return event;
7923
+ if (isPointerEvent(event)) {
7924
+ const { clientX, clientY } = spineItem.translateFramePositionIntoPage(event);
7925
+ const newEvent = new PointerEvent(event.type, {
7926
+ ...event,
7927
+ pointerId: event.pointerId,
7928
+ clientX,
7929
+ clientY
7930
+ });
7931
+ Object.defineProperty(newEvent, `target`, {
7932
+ value: iframeOriginalEvent.target,
7933
+ enumerable: true
7934
+ });
7935
+ return newEvent;
7936
+ }
7937
+ if (isMouseEvent(event)) {
7938
+ const { clientX, clientY } = spineItem.translateFramePositionIntoPage(event);
7939
+ const newEvent = new MouseEvent(event.type, {
7940
+ ...event,
7941
+ clientX,
7942
+ clientY
7943
+ });
7944
+ Object.defineProperty(newEvent, `target`, {
7945
+ value: iframeOriginalEvent.target,
7946
+ enumerable: true
7947
+ });
7948
+ return newEvent;
7949
+ }
7950
+ if (isTouchEvent(event)) {
7951
+ const touches = Array.from(event.touches).map((touch) => {
7952
+ const { clientX, clientY } = spineItem.translateFramePositionIntoPage(touch);
7953
+ return new Touch({
7954
+ identifier: touch.identifier,
7955
+ target: touch.target,
7803
7956
  clientX,
7804
7957
  clientY
7805
7958
  });
7806
- Object.defineProperty(newEvent, `target`, {
7807
- value: iframeOriginalEvent.target,
7808
- enumerable: true
7809
- });
7810
- return newEvent;
7811
- }
7812
- if (isTouchEvent(event)) {
7813
- const touches = Array.from(event.touches).map((touch) => {
7814
- const { clientX, clientY } = spineItem.translateFramePositionIntoPage(touch);
7815
- return new Touch({
7816
- identifier: touch.identifier,
7817
- target: touch.target,
7818
- clientX,
7819
- clientY
7820
- });
7821
- });
7822
- const newEvent = new TouchEvent(event.type, {
7823
- touches,
7824
- changedTouches: touches,
7825
- targetTouches: touches
7826
- });
7827
- Object.defineProperty(newEvent, `target`, {
7828
- value: iframeOriginalEvent.target,
7829
- enumerable: true
7830
- });
7831
- return newEvent;
7832
- }
7833
- return event;
7834
- };
7835
- return normalizeEventForViewport;
7836
- };
7837
- const IFRAME_EVENT_BRIDGE_ELEMENT_ID = `proseReaderIframeEventBridgeElement`;
7838
- const createIframeEventBridgeElement = (container) => {
7839
- const iframeEventBridgeElement = container.ownerDocument.createElement(`div`);
7840
- iframeEventBridgeElement.id = IFRAME_EVENT_BRIDGE_ELEMENT_ID;
7841
- iframeEventBridgeElement.style.cssText = `
7842
- position: absolute;
7843
- height: 100%;
7844
- width: 100%;
7845
- top: 0;
7846
- left: 0;
7847
- z-index: -1;
7848
- `;
7849
- return iframeEventBridgeElement;
7959
+ });
7960
+ const newEvent = new TouchEvent(event.type, {
7961
+ touches,
7962
+ changedTouches: touches,
7963
+ targetTouches: touches
7964
+ });
7965
+ Object.defineProperty(newEvent, `target`, {
7966
+ value: iframeOriginalEvent.target,
7967
+ enumerable: true
7968
+ });
7969
+ return newEvent;
7970
+ }
7971
+ return event;
7850
7972
  };
7851
7973
  const pointerEvents = [
7852
7974
  `pointercancel`,
@@ -7856,23 +7978,13 @@ const pointerEvents = [
7856
7978
  `pointermove`,
7857
7979
  `pointerout`,
7858
7980
  `pointerover`,
7859
- `pointerup`,
7860
- `touchstart`,
7861
- `touchend`
7981
+ `pointerup`
7862
7982
  ];
7863
- const mouseEvents = [
7864
- `click`,
7865
- `mousedown`,
7866
- `mouseup`,
7867
- `mouseenter`,
7868
- `mouseleave`,
7869
- `mousemove`,
7870
- `mouseout`,
7871
- `mouseover`
7983
+ const passthroughEvents = [
7984
+ ...pointerEvents
7985
+ /*, ...mouseEvents*/
7872
7986
  ];
7873
- const passthroughEvents = [...pointerEvents, ...mouseEvents];
7874
7987
  const eventsEnhancer = (next) => (options) => {
7875
- const iframeEventBridgeElement$ = new BehaviorSubject(void 0);
7876
7988
  const reader = next(options);
7877
7989
  reader.hookManager.register(`item.onLoad`, ({ destroy, frame, itemId }) => {
7878
7990
  const item = reader.spineItemsManager.get(itemId);
@@ -7885,12 +7997,15 @@ const eventsEnhancer = (next) => (options) => {
7885
7997
  if (isPointerEvent(e)) {
7886
7998
  convertedEvent = new PointerEvent(e.type, e);
7887
7999
  }
7888
- if (isMouseEvent(e)) {
7889
- convertedEvent = new MouseEvent(e.type, e);
7890
- }
7891
8000
  if (convertedEvent !== e) {
7892
8001
  attachOriginalFrameEventToDocumentEvent(convertedEvent, e);
7893
- (_a2 = iframeEventBridgeElement$.getValue()) == null ? void 0 : _a2.dispatchEvent(convertedEvent);
8002
+ const normalizedEvent = normalizeEventForViewport(
8003
+ convertedEvent,
8004
+ reader.spine.locator
8005
+ );
8006
+ (_a2 = reader.context.state.containerElement) == null ? void 0 : _a2.dispatchEvent(
8007
+ normalizedEvent
8008
+ );
7894
8009
  }
7895
8010
  };
7896
8011
  (_a = frame.contentDocument) == null ? void 0 : _a.addEventListener(event, listener);
@@ -7905,25 +8020,7 @@ const eventsEnhancer = (next) => (options) => {
7905
8020
  unregister.forEach((cb) => cb());
7906
8021
  });
7907
8022
  });
7908
- reader.element$.pipe(
7909
- tap$1((wrapper) => {
7910
- var _a;
7911
- const iframeEventBridgeElement = createIframeEventBridgeElement(wrapper);
7912
- wrapper.appendChild(iframeEventBridgeElement);
7913
- (_a = iframeEventBridgeElement$.getValue()) == null ? void 0 : _a.remove();
7914
- iframeEventBridgeElement$.next(iframeEventBridgeElement);
7915
- }),
7916
- takeUntil(reader.$.destroy$)
7917
- ).subscribe();
7918
- return {
7919
- ...reader,
7920
- events: {
7921
- normalizeEventForViewport: createNormalizeEventForViewport({
7922
- iframeEventBridgeElement$,
7923
- locator: reader.spine.locator
7924
- })
7925
- }
7926
- };
8023
+ return reader;
7927
8024
  };
7928
8025
  const createReaderWithEnhancers = (
7929
8026
  //__
@@ -7969,7 +8066,8 @@ export {
7969
8066
  Report,
7970
8067
  SettingsManager3 as SettingsManager,
7971
8068
  createReaderWithEnhancers as createReader,
7972
- groupBy,
7973
- isShallowEqual
8069
+ isHtmlElement,
8070
+ isShallowEqual2 as isShallowEqual,
8071
+ waitForSwitch
7974
8072
  };
7975
8073
  //# sourceMappingURL=index.js.map