@prose-reader/core 1.20.0 → 1.22.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 (35) hide show
  1. package/dist/context.d.ts +6 -1
  2. package/dist/createReaderWithEnhancer.d.ts +233 -805
  3. package/dist/enhancers/accessibility.d.ts +231 -805
  4. package/dist/enhancers/chrome.d.ts +231 -805
  5. package/dist/enhancers/cssFix.d.ts +6639 -0
  6. package/dist/enhancers/fonts.d.ts +233 -807
  7. package/dist/enhancers/hotkeys.d.ts +231 -805
  8. package/dist/enhancers/layoutEnhancer/layoutEnhancer.d.ts +231 -805
  9. package/dist/enhancers/links.d.ts +231 -805
  10. package/dist/enhancers/loadingEnhancer.d.ts +231 -805
  11. package/dist/enhancers/media.d.ts +231 -805
  12. package/dist/enhancers/navigation.d.ts +231 -805
  13. package/dist/enhancers/pagination.d.ts +233 -805
  14. package/dist/enhancers/progression.d.ts +231 -805
  15. package/dist/enhancers/resources/index.d.ts +231 -805
  16. package/dist/enhancers/theme.d.ts +231 -805
  17. package/dist/enhancers/types/enhancer.d.ts +231 -805
  18. package/dist/enhancers/utils.d.ts +231 -805
  19. package/dist/enhancers/webkit.d.ts +231 -805
  20. package/dist/enhancers/zoom/index.d.ts +231 -805
  21. package/dist/prose.js +300 -278
  22. package/dist/prose.js.map +1 -1
  23. package/dist/prose.umd.cjs +299 -277
  24. package/dist/prose.umd.cjs.map +1 -1
  25. package/dist/reader.d.ts +231 -805
  26. package/dist/spine/locationResolver.d.ts +7 -17
  27. package/dist/spine/navigationResolver.d.ts +5 -8
  28. package/dist/spine/types.d.ts +10 -0
  29. package/dist/spineItem/locationResolver.d.ts +3 -7
  30. package/dist/spineItem/navigationResolver.d.ts +7 -17
  31. package/dist/spineItem/types.d.ts +19 -0
  32. package/dist/spineItemManager.d.ts +6 -519
  33. package/dist/types/Hook.d.ts +6 -6
  34. package/dist/types/Spine.d.ts +1 -5
  35. package/package.json +3 -3
package/dist/prose.js CHANGED
@@ -1,4 +1,4 @@
1
- import { BehaviorSubject, takeUntil as takeUntil$1, combineLatest, map as map$1, of, scheduled as scheduled$1, animationFrameScheduler, Subject as Subject$1, distinctUntilChanged as distinctUntilChanged$1, switchMap as switchMap$1, from as from$1, merge, EMPTY as EMPTY$1, fromEvent, interval, iif, withLatestFrom as withLatestFrom$1, identity as identity$1, take as take$1, forkJoin } from "rxjs";
1
+ import { Subject as Subject$1, BehaviorSubject, map as map$1, takeUntil as takeUntil$1, combineLatest, switchMap as switchMap$1, merge, EMPTY as EMPTY$1, fromEvent, withLatestFrom as withLatestFrom$1, of, scheduled as scheduled$1, animationFrameScheduler, distinctUntilChanged as distinctUntilChanged$1, from as from$1, interval, iif, identity as identity$1, take as take$1, forkJoin } from "rxjs";
2
2
  import { parseContentType, detectMimeTypeFromName } from "@prose-reader/shared";
3
3
  const SHOULD_NOT_LAYOUT$3 = false;
4
4
  const chromeEnhancer = (next) => (options) => {
@@ -2115,9 +2115,62 @@ function withLatestFrom() {
2115
2115
  }));
2116
2116
  });
2117
2117
  }
2118
+ const hasOwn = Object.prototype.hasOwnProperty;
2119
+ const is = (x, y) => {
2120
+ if (x === y) {
2121
+ return x !== 0 || y !== 0 || 1 / x === 1 / y;
2122
+ } else {
2123
+ return false;
2124
+ }
2125
+ };
2126
+ const isShallowEqual = (objectA, objectB, options) => {
2127
+ if (objectA === objectB) {
2128
+ return true;
2129
+ }
2130
+ if (typeof objectA !== `object` || objectA === null) {
2131
+ return false;
2132
+ }
2133
+ if (typeof objectB !== `object` || objectB === null) {
2134
+ return false;
2135
+ }
2136
+ const keysA = Object.keys(objectA);
2137
+ const keysB = Object.keys(objectB);
2138
+ if (keysA.length !== keysB.length) {
2139
+ return false;
2140
+ }
2141
+ const isEqual = options && typeof options.customEqual === `function` ? options.customEqual : is;
2142
+ for (let i = 0; i < keysA.length; i++) {
2143
+ const key = keysA[i] || ``;
2144
+ if (!hasOwn.call(objectB, key) || !isEqual(objectA[key], objectB[key])) {
2145
+ return false;
2146
+ }
2147
+ }
2148
+ return true;
2149
+ };
2150
+ const groupBy = (list, getKey) => list.reduce((previous, currentItem) => {
2151
+ const group = getKey(currentItem);
2152
+ if (!previous[group])
2153
+ previous[group] = [];
2154
+ previous[group].push(currentItem);
2155
+ return previous;
2156
+ }, {});
2157
+ const getBase64FromBlob = (data) => {
2158
+ const reader = new FileReader();
2159
+ return new Promise((resolve) => {
2160
+ reader.addEventListener(
2161
+ `load`,
2162
+ function() {
2163
+ resolve(reader.result);
2164
+ },
2165
+ false
2166
+ );
2167
+ reader.readAsDataURL(data);
2168
+ });
2169
+ };
2118
2170
  const fontsEnhancer = (next) => (options) => {
2119
2171
  const { fontScale = 1, lineHeight = `publisher`, fontWeight = `publisher`, fontJustification = `publisher` } = options;
2120
- const settingsSubject$ = new BehaviorSubject({
2172
+ const changes$ = new Subject$1();
2173
+ const settings$ = new BehaviorSubject({
2121
2174
  fontScale,
2122
2175
  lineHeight,
2123
2176
  fontWeight,
@@ -2135,10 +2188,10 @@ const fontsEnhancer = (next) => (options) => {
2135
2188
  */
2136
2189
  ``}
2137
2190
  body {
2138
- ${settingsSubject$.value.fontScale !== 1 ? `font-size: ${settingsSubject$.value.fontScale}em !important;` : ``}
2139
- ${settingsSubject$.value.lineHeight !== `publisher` ? `line-height: ${settingsSubject$.value.lineHeight} !important;` : ``}
2140
- ${settingsSubject$.value.fontWeight !== `publisher` ? `font-weight: ${settingsSubject$.value.fontWeight} !important;` : ``}
2141
- ${settingsSubject$.value.fontJustification !== `publisher` ? `text-align: ${settingsSubject$.value.fontJustification} !important;` : ``}
2191
+ ${settings$.value.fontScale !== 1 ? `font-size: ${settings$.value.fontScale}em !important;` : ``}
2192
+ ${settings$.value.lineHeight !== `publisher` ? `line-height: ${settings$.value.lineHeight} !important;` : ``}
2193
+ ${settings$.value.fontWeight !== `publisher` ? `font-weight: ${settings$.value.fontWeight} !important;` : ``}
2194
+ ${settings$.value.fontJustification !== `publisher` ? `text-align: ${settings$.value.fontJustification} !important;` : ``}
2142
2195
  }
2143
2196
  `;
2144
2197
  const applyChangeToSpineItem = (requireLayout) => {
@@ -2166,8 +2219,20 @@ const fontsEnhancer = (next) => (options) => {
2166
2219
  return false;
2167
2220
  })
2168
2221
  );
2169
- settingsSubject$.asObservable().pipe(shouldRequireLayout, tap(applyChangeToSpineItem), takeUntil$1(reader.$.destroy$)).subscribe();
2170
- const settings$ = combineLatest([reader.settings$, settingsSubject$]).pipe(
2222
+ const newSettings$ = changes$.pipe(
2223
+ withLatestFrom(settings$),
2224
+ map$1(([changes, settings]) => ({
2225
+ fontJustification: changes.fontJustification ?? settings.fontJustification,
2226
+ fontWeight: changes.fontWeight ?? settings.fontWeight,
2227
+ lineHeight: changes.lineHeight ?? settings.lineHeight,
2228
+ fontScale: Math.max(0.01, changes.fontScale ?? settings.fontScale)
2229
+ })),
2230
+ distinctUntilChanged(isShallowEqual),
2231
+ shareReplay(1)
2232
+ );
2233
+ newSettings$.subscribe(settings$);
2234
+ settings$.pipe(shouldRequireLayout, tap(applyChangeToSpineItem), takeUntil$1(reader.$.destroy$)).subscribe();
2235
+ const settingsMerge$ = combineLatest([reader.settings$, settings$]).pipe(
2171
2236
  map$1(([innerSettings, settings]) => ({
2172
2237
  ...innerSettings,
2173
2238
  ...settings
@@ -2175,56 +2240,56 @@ const fontsEnhancer = (next) => (options) => {
2175
2240
  );
2176
2241
  return {
2177
2242
  ...reader,
2178
- /**
2179
- * Absorb current enhancer settings and passthrough the rest to reader
2180
- */
2243
+ destroy: () => {
2244
+ changes$.complete();
2245
+ settings$.complete();
2246
+ },
2181
2247
  setSettings: (settings) => {
2182
- const {
2183
- fontJustification: fontJustification2 = settingsSubject$.value.fontJustification,
2184
- fontScale: fontScale2 = settingsSubject$.value.fontScale,
2185
- fontWeight: fontWeight2 = settingsSubject$.value.fontWeight,
2186
- lineHeight: lineHeight2 = settingsSubject$.value.lineHeight,
2187
- ...passthroughSettings
2188
- } = settings;
2189
- if (hasOneKey(settings, [`fontJustification`, `fontScale`, `fontWeight`, `lineHeight`])) {
2190
- settingsSubject$.next({ fontJustification: fontJustification2, fontScale: fontScale2, fontWeight: fontWeight2, lineHeight: lineHeight2 });
2191
- }
2248
+ const { fontJustification: fontJustification2, fontScale: fontScale2, fontWeight: fontWeight2, lineHeight: lineHeight2, ...passthroughSettings } = settings;
2249
+ changes$.next({ fontJustification: fontJustification2, fontScale: fontScale2, fontWeight: fontWeight2, lineHeight: lineHeight2 });
2192
2250
  reader.setSettings(passthroughSettings);
2193
2251
  },
2194
- /**
2195
- * Combine reader settings with enhancer settings
2196
- */
2197
- settings$
2252
+ settings$: settingsMerge$
2198
2253
  };
2199
2254
  };
2200
- const hasOneKey = (obj, keys) => keys.some((key) => key in obj);
2201
2255
  const hotkeysEnhancer = (next) => (options) => {
2202
2256
  const reader = next(options);
2203
- const onKeyPress = (e) => {
2204
- if (e.key === `ArrowRight`) {
2205
- reader.turnRight();
2206
- }
2207
- if (e.key === `ArrowLeft`) {
2208
- reader.turnLeft();
2209
- }
2210
- };
2211
- document.addEventListener(`keyup`, onKeyPress);
2212
- reader.registerHook(`item.onLoad`, ({ frame }) => {
2213
- var _a;
2214
- (_a = frame.contentDocument) == null ? void 0 : _a.addEventListener(`keyup`, onKeyPress);
2215
- return () => {
2216
- var _a2;
2217
- (_a2 = frame.contentDocument) == null ? void 0 : _a2.removeEventListener(`keyup`, onKeyPress);
2218
- };
2219
- });
2220
- const destroy = () => {
2221
- document.removeEventListener(`keyup`, onKeyPress);
2222
- reader.destroy();
2223
- };
2224
- return {
2225
- ...reader,
2226
- destroy
2227
- };
2257
+ const navigateOnKey = (document2) => fromEvent(document2, "keyup").pipe(
2258
+ withLatestFrom$1(reader.settings$),
2259
+ map$1(([e, { pageTurnDirection }]) => {
2260
+ if (pageTurnDirection === "horizontal") {
2261
+ if (e.key === `ArrowRight`) {
2262
+ reader.turnRight();
2263
+ }
2264
+ if (e.key === `ArrowLeft`) {
2265
+ reader.turnLeft();
2266
+ }
2267
+ }
2268
+ if (pageTurnDirection === "vertical") {
2269
+ if (e.key === `ArrowDown`) {
2270
+ reader.turnRight();
2271
+ }
2272
+ if (e.key === `ArrowUp`) {
2273
+ reader.turnLeft();
2274
+ }
2275
+ }
2276
+ return e;
2277
+ })
2278
+ );
2279
+ navigateOnKey(document).pipe(takeUntil$1(reader.$.destroy$)).subscribe();
2280
+ reader.spineItems$.pipe(
2281
+ switchMap$1(
2282
+ (spineItems) => merge(
2283
+ ...spineItems.map(
2284
+ (item) => item.$.loaded$.pipe(
2285
+ switchMap$1((iframe) => (iframe == null ? void 0 : iframe.contentDocument) ? navigateOnKey(iframe.contentDocument) : EMPTY$1)
2286
+ )
2287
+ )
2288
+ )
2289
+ ),
2290
+ takeUntil$1(reader.$.destroy$)
2291
+ ).subscribe();
2292
+ return reader;
2228
2293
  };
2229
2294
  const SHOULD_NOT_LAYOUT$2 = false;
2230
2295
  const createMovingSafePan$ = (reader) => {
@@ -2280,58 +2345,6 @@ const mapKeysTo = (keys) => {
2280
2345
  }, {});
2281
2346
  });
2282
2347
  };
2283
- const hasOwn = Object.prototype.hasOwnProperty;
2284
- const is = (x, y) => {
2285
- if (x === y) {
2286
- return x !== 0 || y !== 0 || 1 / x === 1 / y;
2287
- } else {
2288
- return false;
2289
- }
2290
- };
2291
- const isShallowEqual = (objectA, objectB, options) => {
2292
- if (objectA === objectB) {
2293
- return true;
2294
- }
2295
- if (typeof objectA !== `object` || objectA === null) {
2296
- return false;
2297
- }
2298
- if (typeof objectB !== `object` || objectB === null) {
2299
- return false;
2300
- }
2301
- const keysA = Object.keys(objectA);
2302
- const keysB = Object.keys(objectB);
2303
- if (keysA.length !== keysB.length) {
2304
- return false;
2305
- }
2306
- const isEqual = options && typeof options.customEqual === `function` ? options.customEqual : is;
2307
- for (let i = 0; i < keysA.length; i++) {
2308
- const key = keysA[i] || ``;
2309
- if (!hasOwn.call(objectB, key) || !isEqual(objectA[key], objectB[key])) {
2310
- return false;
2311
- }
2312
- }
2313
- return true;
2314
- };
2315
- const groupBy = (list, getKey) => list.reduce((previous, currentItem) => {
2316
- const group = getKey(currentItem);
2317
- if (!previous[group])
2318
- previous[group] = [];
2319
- previous[group].push(currentItem);
2320
- return previous;
2321
- }, {});
2322
- const getBase64FromBlob = (data) => {
2323
- const reader = new FileReader();
2324
- return new Promise((resolve) => {
2325
- reader.addEventListener(
2326
- `load`,
2327
- function() {
2328
- resolve(reader.result);
2329
- },
2330
- false
2331
- );
2332
- reader.readAsDataURL(data);
2333
- });
2334
- };
2335
2348
  const fixReflowable = (reader) => {
2336
2349
  reader.registerHook(`item.onAfterLayout`, ({ item, blankPagePosition, minimumWidth }) => {
2337
2350
  var _a;
@@ -2687,7 +2700,7 @@ const getClosestValidOffsetFromApproximateOffsetInPages = (offset, pageWidth, it
2687
2700
  return offsetValues.find((offsetRange) => offset < offsetRange + pageWidth) || 0;
2688
2701
  };
2689
2702
  const NAMESPACE$5 = `paginationEnhancer`;
2690
- const report$1 = Report.namespace(NAMESPACE$5);
2703
+ Report.namespace(NAMESPACE$5);
2691
2704
  const paginationEnhancer = (next) => (options) => {
2692
2705
  const reader = next(options);
2693
2706
  const chaptersInfo = {};
@@ -2697,8 +2710,12 @@ const paginationEnhancer = (next) => (options) => {
2697
2710
  };
2698
2711
  const mapPaginationInfoToExtendedInfo = (paginationInfo) => {
2699
2712
  const context = reader.context;
2713
+ const manifest = context.getManifest();
2714
+ const numberOfSpineItems = (manifest == null ? void 0 : manifest.spineItems.length) ?? 0;
2700
2715
  const beginItem = paginationInfo.beginSpineItemIndex !== void 0 ? reader.getSpineItem(paginationInfo.beginSpineItemIndex) : void 0;
2701
2716
  const endItem = paginationInfo.endSpineItemIndex !== void 0 ? reader.getSpineItem(paginationInfo.endSpineItemIndex) : void 0;
2717
+ const isAtAbsoluteBeginning = paginationInfo.beginSpineItemIndex === 0 && paginationInfo.beginPageIndex === 0;
2718
+ const isAtAbsoluteEnd = paginationInfo.endPageIndex === paginationInfo.endNumberOfPages - 1 && paginationInfo.endSpineItemIndex === Math.max(numberOfSpineItems - 1, 0);
2702
2719
  return {
2703
2720
  beginPageIndexInChapter: paginationInfo.beginPageIndex,
2704
2721
  beginNumberOfPagesInChapter: paginationInfo.beginNumberOfPages,
@@ -2714,19 +2731,14 @@ const paginationEnhancer = (next) => (options) => {
2714
2731
  // charOffset: number;
2715
2732
  // serializeString?: string;
2716
2733
  beginSpineItemIndex: paginationInfo.beginSpineItemIndex,
2717
- // spineItemPath: beginItem?.item.path,
2718
- // spineItemId: beginItem?.item.id,
2719
2734
  beginCfi: paginationInfo.beginCfi,
2720
2735
  beginSpineItemReadingDirection: beginItem == null ? void 0 : beginItem.getReadingDirection(),
2721
2736
  endChapterInfo: endItem ? chaptersInfo[endItem.item.id] : void 0,
2722
2737
  endPageIndexInChapter: paginationInfo.endPageIndex,
2723
2738
  endNumberOfPagesInChapter: paginationInfo.endNumberOfPages,
2724
2739
  endSpineItemIndex: paginationInfo.endSpineItemIndex,
2725
- // spineItemPath: endItem?.item.path,
2726
- // spineItemId: endItem?.item.id,
2727
2740
  endSpineItemReadingDirection: endItem == null ? void 0 : endItem.getReadingDirection(),
2728
2741
  endCfi: paginationInfo.endCfi,
2729
- // end: ReadingLocation;
2730
2742
  // spineItemReadingDirection: focusedSpineItem?.getReadingDirection(),
2731
2743
  /**
2732
2744
  * This percentage is based of the weight (kb) of every items and the number of pages.
@@ -2742,12 +2754,12 @@ const paginationEnhancer = (next) => (options) => {
2742
2754
  reader.getCurrentViewportPosition(),
2743
2755
  endItem
2744
2756
  ) : 0,
2745
- isUsingSpread: context.shouldDisplaySpread()
2746
- // chaptersOfBook: number;
2747
- // chapter: string;
2757
+ isUsingSpread: context.shouldDisplaySpread(),
2748
2758
  // hasNextChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
2749
2759
  // hasPreviousChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
2750
2760
  // numberOfSpineItems: context.getManifest()?.readingOrder.length,
2761
+ canGoLeft: (manifest == null ? void 0 : manifest.readingDirection) === "ltr" && !isAtAbsoluteBeginning || (manifest == null ? void 0 : manifest.readingDirection) === "rtl" && !isAtAbsoluteEnd,
2762
+ canGoRight: (manifest == null ? void 0 : manifest.readingDirection) === "ltr" && !isAtAbsoluteEnd || (manifest == null ? void 0 : manifest.readingDirection) === "rtl" && !isAtAbsoluteBeginning
2751
2763
  };
2752
2764
  };
2753
2765
  const getSpineItemNumberOfPages = (spineItem) => {
@@ -2765,7 +2777,7 @@ const paginationEnhancer = (next) => (options) => {
2765
2777
  const getNumberOfPagesPerItems = () => reader.getSpineItems().map((item) => {
2766
2778
  return getSpineItemNumberOfPages(item);
2767
2779
  }, 0);
2768
- reader.$.itemsCreated$.pipe(
2780
+ reader.spineItems$.pipe(
2769
2781
  tap(
2770
2782
  (items) => items.forEach(({ item }) => {
2771
2783
  chaptersInfo[item.id] = getChapterInfo2(item);
@@ -2806,9 +2818,6 @@ const paginationEnhancer = (next) => (options) => {
2806
2818
  beginAbsolutePageIndex: totalPageInfo.numberOfPagesPerItems.slice(0, pageInfo.beginSpineItemIndex).reduce((acc, numberOfPagesForItem) => acc + numberOfPagesForItem, pageInfo.beginPageIndexInChapter ?? 0),
2807
2819
  endAbsolutePageIndex: totalPageInfo.numberOfPagesPerItems.slice(0, pageInfo.endSpineItemIndex).reduce((acc, numberOfPagesForItem) => acc + numberOfPagesForItem, pageInfo.endPageIndexInChapter ?? 0)
2808
2820
  })),
2809
- tap((data) => {
2810
- report$1.log(`pagination`, data);
2811
- }),
2812
2821
  shareReplay(1),
2813
2822
  takeUntil(reader.$.destroy$)
2814
2823
  );
@@ -2910,7 +2919,7 @@ const themeEnhancer = (next) => (options) => {
2910
2919
  removeStyle(`prose-reader-theme`);
2911
2920
  addStyle(`prose-reader-theme`, getStyle());
2912
2921
  });
2913
- reader.$.itemsCreated$.pipe(
2922
+ reader.spineItems$.pipe(
2914
2923
  tap((items) => items.map(({ element }) => applyChangeToSpineItemElement({ container: element }))),
2915
2924
  takeUntil(reader.$.destroy$)
2916
2925
  ).subscribe();
@@ -3318,7 +3327,7 @@ const createContext = (initialSettings) => {
3318
3327
  getVisibleAreaRect: () => visibleAreaRect,
3319
3328
  shouldDisplaySpread,
3320
3329
  setHasVerticalWriting,
3321
- setVisibleAreaRect: (x, y, width, height) => {
3330
+ setVisibleAreaRect: ({ height, width, x, y }) => {
3322
3331
  visibleAreaRect.width = width;
3323
3332
  visibleAreaRect.height = height - marginTop - marginBottom;
3324
3333
  visibleAreaRect.x = x;
@@ -3631,13 +3640,17 @@ const createFrameItem = ({
3631
3640
  getComputedStyleAfterLoad
3632
3641
  } = createLoader({ context, hooks$, item, parent, fetchResource, viewportState$ });
3633
3642
  let isLoadedSync = false;
3634
- const isReadySubject$ = new BehaviorSubject(false);
3643
+ let isReadySync = false;
3635
3644
  isLoaded$.subscribe({
3636
3645
  next: (value) => {
3637
3646
  isLoadedSync = value;
3638
3647
  }
3639
3648
  });
3640
- isReady$.subscribe(isReadySubject$);
3649
+ isReady$.subscribe({
3650
+ next: (value) => {
3651
+ isReadySync = value;
3652
+ }
3653
+ });
3641
3654
  const getManipulableFrame = () => {
3642
3655
  const frame = frameElement$.value;
3643
3656
  if (isLoadedSync && frame) {
@@ -3689,8 +3702,14 @@ const createFrameItem = ({
3689
3702
  destroySubject$.complete();
3690
3703
  };
3691
3704
  return {
3705
+ /**
3706
+ * @deprecated
3707
+ */
3692
3708
  getIsLoaded: () => isLoadedSync,
3693
- getIsReady: () => isReadySubject$.value,
3709
+ /**
3710
+ * @deprecated
3711
+ */
3712
+ getIsReady: () => isReadySync,
3694
3713
  getViewportDimensions,
3695
3714
  getFrameElement: () => frameElement$.getValue(),
3696
3715
  getHtmlFromResource,
@@ -3734,7 +3753,7 @@ const createFrameItem = ({
3734
3753
  unloaded$,
3735
3754
  loaded$,
3736
3755
  ready$,
3737
- isReady$: isReadySubject$.asObservable(),
3756
+ isReady$,
3738
3757
  /**
3739
3758
  * This is used as upstream layout change. This event is being listened to by upper app
3740
3759
  * in order to layout again and adjust every element based on the new content.
@@ -4217,6 +4236,14 @@ const createCommonSpineItem = ({
4217
4236
  var _a2;
4218
4237
  return (_a2 = spineItemFrame.getWritingMode()) == null ? void 0 : _a2.startsWith(`vertical`);
4219
4238
  },
4239
+ /**
4240
+ * @important
4241
+ * Do not use this value for layout and navigation. It will be in possible conflict
4242
+ * with the global reading direction. A book should not mix them anyway. A page can have
4243
+ * a different reading direction for style reason but it should be in theory pre-paginated.
4244
+ * For example an english page in a japanese manga. That's expected and will
4245
+ * be confined to a single page.
4246
+ */
4220
4247
  getReadingDirection: () => {
4221
4248
  return spineItemFrame.getReadingDirection() || context.getReadingDirection();
4222
4249
  },
@@ -5746,7 +5773,7 @@ const createSpine = ({
5746
5773
  currentNavigationPosition$,
5747
5774
  viewportState$
5748
5775
  }) => {
5749
- const itemsCreatedSubject$ = new Subject$1();
5776
+ const spineItems$ = new Subject$1();
5750
5777
  const itemsBeforeDestroySubject$ = new Subject$1();
5751
5778
  const subject = new Subject$1();
5752
5779
  const containerElement = createContainerElement(ownerDocument, hooks$);
@@ -5761,7 +5788,7 @@ const createSpine = ({
5761
5788
  var _a;
5762
5789
  itemsBeforeDestroySubject$.next();
5763
5790
  spineItemManager.destroyItems();
5764
- (_a = context.getManifest()) == null ? void 0 : _a.spineItems.map(async (resource) => {
5791
+ (_a = context.getManifest()) == null ? void 0 : _a.spineItems.map((resource) => {
5765
5792
  const spineItem = createSpineItem({
5766
5793
  item: resource,
5767
5794
  containerElement,
@@ -5772,7 +5799,7 @@ const createSpine = ({
5772
5799
  });
5773
5800
  spineItemManager.add(spineItem);
5774
5801
  });
5775
- itemsCreatedSubject$.next(spineItemManager.getAll());
5802
+ spineItems$.next(spineItemManager.getAll());
5776
5803
  };
5777
5804
  const manipulateSpineItems = (cb) => {
5778
5805
  let shouldLayout = false;
@@ -6018,7 +6045,7 @@ const createSpine = ({
6018
6045
  manipulateSpineItems,
6019
6046
  manipulateSpineItem,
6020
6047
  destroy: () => {
6021
- itemsCreatedSubject$.complete();
6048
+ spineItems$.complete();
6022
6049
  itemsBeforeDestroySubject$.next();
6023
6050
  itemsBeforeDestroySubject$.complete();
6024
6051
  subject.complete();
@@ -6038,7 +6065,7 @@ const createSpine = ({
6038
6065
  $: {
6039
6066
  $: subject.asObservable(),
6040
6067
  layout$: spineItemManager.$.layout$,
6041
- itemsCreated$: itemsCreatedSubject$.asObservable(),
6068
+ spineItems$: spineItems$.asObservable(),
6042
6069
  itemsBeforeDestroy$: itemsBeforeDestroySubject$.asObservable()
6043
6070
  }
6044
6071
  };
@@ -6079,10 +6106,10 @@ const createSpineItemManager = ({ context }) => {
6079
6106
  const isGloballyPrePaginated = (manifest == null ? void 0 : manifest.renditionLayout) === `pre-paginated`;
6080
6107
  manifest ? getCoverItem(manifest) : void 0;
6081
6108
  orderedSpineItemsSubject$.value.reduce(
6082
- (edgeOffset, item, index) => {
6109
+ ({ horizontalOffset, verticalOffset }, item, index) => {
6083
6110
  let minimumWidth = context.getPageSize().width;
6084
6111
  let blankPagePosition = `none`;
6085
- const itemStartOnNewScreen = edgeOffset.edgeX % context.getVisibleAreaRect().width === 0;
6112
+ const itemStartOnNewScreen = horizontalOffset % context.getVisibleAreaRect().width === 0;
6086
6113
  const isLastItem = index === orderedSpineItemsSubject$.value.length - 1;
6087
6114
  if (context.shouldDisplaySpread()) {
6088
6115
  if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && !isLastItem) {
@@ -6113,8 +6140,8 @@ const createSpineItemManager = ({ context }) => {
6113
6140
  spreadPosition: context.shouldDisplaySpread() ? itemStartOnNewScreen ? context.isRTL() ? `right` : `left` : context.isRTL() ? `left` : `right` : `none`
6114
6141
  });
6115
6142
  if (context.getSettings().computedPageTurnDirection === `vertical`) {
6116
- const currentValidEdgeYForVerticalPositioning = itemStartOnNewScreen ? edgeOffset.edgeY : edgeOffset.edgeY - context.getVisibleAreaRect().height;
6117
- const currentValidEdgeXForVerticalPositioning = itemStartOnNewScreen ? 0 : edgeOffset.edgeX;
6143
+ const currentValidEdgeYForVerticalPositioning = itemStartOnNewScreen ? verticalOffset : verticalOffset - context.getVisibleAreaRect().height;
6144
+ const currentValidEdgeXForVerticalPositioning = itemStartOnNewScreen ? 0 : horizontalOffset;
6118
6145
  if (context.isRTL()) {
6119
6146
  item.adjustPositionOfElement({
6120
6147
  top: currentValidEdgeYForVerticalPositioning,
@@ -6126,41 +6153,41 @@ const createSpineItemManager = ({ context }) => {
6126
6153
  left: currentValidEdgeXForVerticalPositioning
6127
6154
  });
6128
6155
  }
6129
- const newEdgeX2 = width + currentValidEdgeXForVerticalPositioning;
6156
+ const newEdgeX = width + currentValidEdgeXForVerticalPositioning;
6130
6157
  const newEdgeY = height + currentValidEdgeYForVerticalPositioning;
6131
6158
  newItemLayoutInformation.push({
6132
- leftStart: currentValidEdgeXForVerticalPositioning,
6133
- leftEnd: newEdgeX2,
6134
- topStart: currentValidEdgeYForVerticalPositioning,
6135
- topEnd: newEdgeY,
6159
+ left: currentValidEdgeXForVerticalPositioning,
6160
+ right: newEdgeX,
6161
+ top: currentValidEdgeYForVerticalPositioning,
6162
+ bottom: newEdgeY,
6136
6163
  height,
6137
6164
  width
6138
6165
  });
6139
6166
  return {
6140
- edgeX: newEdgeX2,
6141
- edgeY: newEdgeY
6167
+ horizontalOffset: newEdgeX,
6168
+ verticalOffset: newEdgeY
6142
6169
  };
6143
6170
  }
6144
- if (context.isRTL()) {
6145
- item.adjustPositionOfElement({ right: edgeOffset.edgeX, top: 0 });
6146
- } else {
6147
- item.adjustPositionOfElement({ left: edgeOffset.edgeX, top: 0 });
6148
- }
6149
- const newEdgeX = width + edgeOffset.edgeX;
6171
+ item.adjustPositionOfElement(context.isRTL() ? { right: horizontalOffset, top: 0 } : { left: horizontalOffset, top: 0 });
6150
6172
  newItemLayoutInformation.push({
6151
- leftStart: edgeOffset.edgeX,
6152
- leftEnd: newEdgeX,
6153
- topStart: edgeOffset.edgeY,
6154
- topEnd: height,
6173
+ ...context.isRTL() ? {
6174
+ left: context.getVisibleAreaRect().width - horizontalOffset - width,
6175
+ right: context.getVisibleAreaRect().width - horizontalOffset
6176
+ } : {
6177
+ left: horizontalOffset,
6178
+ right: horizontalOffset + width
6179
+ },
6180
+ top: verticalOffset,
6181
+ bottom: height,
6155
6182
  height,
6156
6183
  width
6157
6184
  });
6158
6185
  return {
6159
- edgeX: newEdgeX,
6160
- edgeY: 0
6186
+ horizontalOffset: horizontalOffset + width,
6187
+ verticalOffset: 0
6161
6188
  };
6162
6189
  },
6163
- { edgeX: 0, edgeY: 0 }
6190
+ { horizontalOffset: 0, verticalOffset: 0 }
6164
6191
  );
6165
6192
  const hasLayoutChanges = itemLayoutInformation.some((old, index) => !isShallowEqual(old, newItemLayoutInformation[index]));
6166
6193
  itemLayoutInformation = newItemLayoutInformation;
@@ -6202,34 +6229,18 @@ const createSpineItemManager = ({ context }) => {
6202
6229
  }
6203
6230
  return orderedSpineItemsSubject$.value.find(({ item }) => item.id === indexOrId);
6204
6231
  };
6205
- const getAbsolutePositionOf = Report.measurePerformance(
6206
- `getAbsolutePositionOf`,
6207
- 10,
6208
- (spineItemOrIndex) => {
6209
- context.getSettings().computedPageTurnDirection;
6210
- const indexOfItem = typeof spineItemOrIndex === `number` ? spineItemOrIndex : orderedSpineItemsSubject$.value.indexOf(spineItemOrIndex);
6211
- const layoutInformation = itemLayoutInformation[indexOfItem];
6212
- if (!layoutInformation) {
6213
- return {
6214
- leftStart: 0,
6215
- leftEnd: 0,
6216
- topStart: 0,
6217
- topEnd: 0,
6218
- width: 0,
6219
- height: 0
6220
- };
6221
- }
6222
- return itemLayoutInformation[indexOfItem] || {
6223
- leftStart: 0,
6224
- leftEnd: 0,
6225
- topStart: 0,
6226
- topEnd: 0,
6227
- width: 0,
6228
- height: 0
6229
- };
6230
- },
6231
- { disable: true }
6232
- );
6232
+ const getAbsolutePositionOf = (spineItemOrIndex) => {
6233
+ const indexOfItem = typeof spineItemOrIndex === `number` ? spineItemOrIndex : orderedSpineItemsSubject$.value.indexOf(spineItemOrIndex);
6234
+ const layoutInformation = itemLayoutInformation[indexOfItem];
6235
+ return layoutInformation || {
6236
+ left: 0,
6237
+ right: 0,
6238
+ top: 0,
6239
+ bottom: 0,
6240
+ width: 0,
6241
+ height: 0
6242
+ };
6243
+ };
6233
6244
  const getFocusedSpineItem = () => focusedSpineItemIndex !== void 0 ? orderedSpineItemsSubject$.value[focusedSpineItemIndex] : void 0;
6234
6245
  const comparePositionOf = (toCompare, withItem) => {
6235
6246
  const isAfter = orderedSpineItemsSubject$.value.indexOf(toCompare) > orderedSpineItemsSubject$.value.indexOf(withItem);
@@ -6267,26 +6278,6 @@ const createSpineItemManager = ({ context }) => {
6267
6278
  const item = getFocusedSpineItem();
6268
6279
  return item && getSpineItemIndex(item);
6269
6280
  };
6270
- const getSpineItemAtPosition = Report.measurePerformance(
6271
- `getSpineItemAtPosition`,
6272
- 10,
6273
- (position) => {
6274
- const detectedItem = orderedSpineItemsSubject$.value.find((item) => {
6275
- const { leftStart, leftEnd, topEnd, topStart } = getAbsolutePositionOf(item);
6276
- const isWithinXAxis = position.x >= leftStart && position.x < leftEnd;
6277
- if (context.getSettings().computedPageTurnDirection === `horizontal`) {
6278
- return isWithinXAxis;
6279
- } else {
6280
- return isWithinXAxis && position.y >= topStart && position.y < topEnd;
6281
- }
6282
- });
6283
- if (position.x === 0 && !detectedItem) {
6284
- return orderedSpineItemsSubject$.value[0];
6285
- }
6286
- return detectedItem;
6287
- },
6288
- { disable: true }
6289
- );
6290
6281
  const destroyItems = () => {
6291
6282
  orderedSpineItemsSubject$.value.forEach((item) => item.destroy());
6292
6283
  };
@@ -6306,7 +6297,6 @@ const createSpineItemManager = ({ context }) => {
6306
6297
  loadContents,
6307
6298
  comparePositionOf,
6308
6299
  getAbsolutePositionOf,
6309
- getSpineItemAtPosition,
6310
6300
  getFocusedSpineItem,
6311
6301
  getFocusedSpineItemIndex,
6312
6302
  getSpineItemIndex,
@@ -6324,9 +6314,12 @@ const createSpineItemManager = ({ context }) => {
6324
6314
  };
6325
6315
  };
6326
6316
  const createLocationResolver$1 = ({ context }) => {
6317
+ const getSafePosition = (unsafeSpineItemPosition, spineItem) => ({
6318
+ x: Math.min(spineItem.getElementDimensions().width, Math.max(0, unsafeSpineItemPosition.x)),
6319
+ y: Math.min(spineItem.getElementDimensions().height, Math.max(0, unsafeSpineItemPosition.y))
6320
+ });
6327
6321
  const getSpineItemPositionFromPageIndex = (pageIndex, spineItem) => {
6328
6322
  const { width: itemWidth, height: itemHeight } = spineItem.getElementDimensions();
6329
- const itemReadingDirection = spineItem.getReadingDirection();
6330
6323
  if (spineItem.isUsingVerticalWriting()) {
6331
6324
  const ltrRelativeOffset2 = getItemOffsetFromPageIndex(context.getPageSize().height, pageIndex, itemHeight);
6332
6325
  return {
@@ -6335,7 +6328,7 @@ const createLocationResolver$1 = ({ context }) => {
6335
6328
  };
6336
6329
  }
6337
6330
  const ltrRelativeOffset = getItemOffsetFromPageIndex(context.getPageSize().width, pageIndex, itemWidth);
6338
- if (itemReadingDirection === `rtl`) {
6331
+ if (context.isRTL()) {
6339
6332
  return {
6340
6333
  x: itemWidth - ltrRelativeOffset - context.getPageSize().width,
6341
6334
  y: 0
@@ -6348,19 +6341,16 @@ const createLocationResolver$1 = ({ context }) => {
6348
6341
  };
6349
6342
  const getSpineItemPageIndexFromPosition = (position, spineItem) => {
6350
6343
  const { width: itemWidth, height: itemHeight } = spineItem.getElementDimensions();
6351
- const itemReadingDirection = spineItem.getReadingDirection();
6352
6344
  const pageWidth = context.getPageSize().width;
6353
6345
  const pageHeight = context.getPageSize().height;
6354
- let offsetNormalizedForLtr = Math.min(itemWidth, Math.max(0, position.x));
6355
- if (itemReadingDirection === `rtl`) {
6356
- offsetNormalizedForLtr = itemWidth - offsetNormalizedForLtr - context.getPageSize().width;
6357
- }
6346
+ const safePosition = getSafePosition(position, spineItem);
6347
+ const offset = context.isRTL() ? itemWidth - safePosition.x - context.getPageSize().width : safePosition.x;
6358
6348
  if (spineItem.isUsingVerticalWriting()) {
6359
6349
  const numberOfPages = getNumberOfPages(itemHeight, pageHeight);
6360
6350
  return getPageFromOffset(position.y, pageHeight, numberOfPages);
6361
6351
  } else {
6362
6352
  const numberOfPages = getNumberOfPages(itemWidth, pageWidth);
6363
- const pageIndex = getPageFromOffset(offsetNormalizedForLtr, pageWidth, numberOfPages);
6353
+ const pageIndex = getPageFromOffset(offset, pageWidth, numberOfPages);
6364
6354
  return pageIndex;
6365
6355
  }
6366
6356
  };
@@ -6440,6 +6430,13 @@ const createLocationResolver$1 = ({ context }) => {
6440
6430
  getFirstNodeOrRangeAtPage
6441
6431
  };
6442
6432
  };
6433
+ class SpineItemNavigationPosition {
6434
+ constructor(position) {
6435
+ this.__symbol = `SpineItemNavigationPosition`;
6436
+ this.x = position.x;
6437
+ this.y = position.y;
6438
+ }
6439
+ }
6443
6440
  const createNavigationResolver$1 = ({ context }) => {
6444
6441
  const spineItemLocator = createLocationResolver$1({ context });
6445
6442
  const getNavigationForLeftPage = (position, spineItem) => {
@@ -6453,7 +6450,8 @@ const createNavigationResolver$1 = ({ context }) => {
6453
6450
  y: position.y + context.getPageSize().height
6454
6451
  };
6455
6452
  }
6456
- return spineItemLocator.getSpineItemClosestPositionFromUnsafePosition(nextPotentialPosition, spineItem);
6453
+ const navigationPosition = spineItemLocator.getSpineItemClosestPositionFromUnsafePosition(nextPotentialPosition, spineItem);
6454
+ return new SpineItemNavigationPosition(navigationPosition);
6457
6455
  };
6458
6456
  const getNavigationForRightPage = (position, spineItem) => {
6459
6457
  let nextPotentialPosition = {
@@ -6466,7 +6464,8 @@ const createNavigationResolver$1 = ({ context }) => {
6466
6464
  y: position.y - context.getPageSize().height
6467
6465
  };
6468
6466
  }
6469
- return spineItemLocator.getSpineItemClosestPositionFromUnsafePosition(nextPotentialPosition, spineItem);
6467
+ const navigationPosition = spineItemLocator.getSpineItemClosestPositionFromUnsafePosition(nextPotentialPosition, spineItem);
6468
+ return new SpineItemNavigationPosition(navigationPosition);
6470
6469
  };
6471
6470
  const getNavigationForLastPage = (spineItem) => {
6472
6471
  if (spineItem.isUsingVerticalWriting()) {
@@ -6480,16 +6479,16 @@ const createNavigationResolver$1 = ({ context }) => {
6480
6479
  }
6481
6480
  };
6482
6481
  const getNavigationForPage = (pageIndex, spineItem) => {
6483
- const currentViewport = spineItemLocator.getSpineItemPositionFromPageIndex(pageIndex, spineItem);
6484
- return currentViewport;
6482
+ const { x, y } = spineItemLocator.getSpineItemPositionFromPageIndex(pageIndex, spineItem);
6483
+ return new SpineItemNavigationPosition({ x, y });
6485
6484
  };
6486
6485
  const getNavigationFromNode = (spineItem, node, offset) => {
6487
6486
  const position = spineItemLocator.getSpineItemPositionFromNode(node, offset, spineItem);
6488
- return position || { x: 0, y: 0 };
6487
+ return new SpineItemNavigationPosition(position || { x: 0, y: 0 });
6489
6488
  };
6490
6489
  const getNavigationForPosition = (spineItem, position) => {
6491
6490
  const potentiallyCorrectedPosition = spineItemLocator.getSpineItemClosestPositionFromUnsafePosition(position, spineItem);
6492
- return potentiallyCorrectedPosition;
6491
+ return new SpineItemNavigationPosition(potentiallyCorrectedPosition);
6493
6492
  };
6494
6493
  return {
6495
6494
  getNavigationForLeftPage,
@@ -6516,11 +6515,18 @@ const createNavigationResolver = ({
6516
6515
  (position) => {
6517
6516
  const lastSpineItem = spineItemManager.get(spineItemManager.getLength() - 1);
6518
6517
  const distanceOfLastSpineItem = spineItemManager.getAbsolutePositionOf(lastSpineItem || 0);
6519
- const maximumXOffset = distanceOfLastSpineItem.leftEnd - context.getPageSize().width;
6520
- const maximumYOffset = distanceOfLastSpineItem.topEnd - context.getPageSize().height;
6518
+ const maximumYOffset = distanceOfLastSpineItem.bottom - context.getPageSize().height;
6519
+ const y = Math.min(Math.max(0, position.y), maximumYOffset);
6520
+ if (context.isRTL()) {
6521
+ return {
6522
+ x: Math.max(Math.min(0, position.x), distanceOfLastSpineItem.left),
6523
+ y
6524
+ };
6525
+ }
6526
+ const maximumXOffset = distanceOfLastSpineItem.right - context.getPageSize().width;
6521
6527
  return {
6522
6528
  x: Math.min(Math.max(0, position.x), maximumXOffset),
6523
- y: Math.min(Math.max(0, position.y), maximumYOffset)
6529
+ y
6524
6530
  };
6525
6531
  },
6526
6532
  { disable: true }
@@ -6536,7 +6542,7 @@ const createNavigationResolver = ({
6536
6542
  if (!spineItem) {
6537
6543
  Report.warn(NAMESPACE$3, `unable to detect item id from cfi ${cfi}`);
6538
6544
  } else {
6539
- const spineItemNavigation = node ? spineItemNavigator.getNavigationFromNode(spineItem, node, offset) : { x: 0, y: 0 };
6545
+ const spineItemNavigation = node ? spineItemNavigator.getNavigationFromNode(spineItem, node, offset) : new SpineItemNavigationPosition({ x: 0, y: 0 });
6540
6546
  const readingPosition = locator.getSpinePositionFromSpineItemPosition(spineItemNavigation, spineItem);
6541
6547
  return { ...getAdjustedPositionForSpread(readingPosition), spineItem };
6542
6548
  }
@@ -6573,10 +6579,10 @@ const createNavigationResolver = ({
6573
6579
  }
6574
6580
  const spineItemPosition = locator.getSpineItemPositionFromSpinePosition(position, spineItem);
6575
6581
  const spineItemNavigationForRightPage = spineItemNavigator.getNavigationForRightPage(spineItemPosition, spineItem);
6576
- const isNewNavigationInCurrentItem = !spineItemPosition.outsideOfBoundaries && arePositionsDifferent(spineItemNavigationForRightPage, spineItemPosition);
6582
+ const isNewNavigationInCurrentItem = arePositionsDifferent(spineItemNavigationForRightPage, spineItemPosition);
6577
6583
  if (!isNewNavigationInCurrentItem) {
6578
6584
  return wrapPositionWithSafeEdge(
6579
- context.isRTL() ? pageTurnDirection === `horizontal` ? { x: position.x - context.getPageSize().width, y: 0 } : { y: position.y + context.getPageSize().height, x: 0 } : pageTurnDirection === `horizontal` ? { x: position.x + context.getPageSize().width, y: 0 } : { y: position.y + context.getPageSize().height, x: 0 }
6585
+ pageTurnDirection === `horizontal` ? { x: position.x + context.getPageSize().width, y: 0 } : { y: position.y + context.getPageSize().height, x: 0 }
6580
6586
  );
6581
6587
  } else {
6582
6588
  const readingOrderPosition = locator.getSpinePositionFromSpineItemPosition(spineItemNavigationForRightPage, spineItem);
@@ -6592,10 +6598,10 @@ const createNavigationResolver = ({
6592
6598
  }
6593
6599
  const spineItemPosition = locator.getSpineItemPositionFromSpinePosition(position, spineItem);
6594
6600
  const spineItemNavigation = spineItemNavigator.getNavigationForLeftPage(spineItemPosition, spineItem);
6595
- const isNewNavigationInCurrentItem = !spineItemPosition.outsideOfBoundaries && arePositionsDifferent(spineItemNavigation, spineItemPosition);
6601
+ const isNewNavigationInCurrentItem = arePositionsDifferent(spineItemNavigation, spineItemPosition);
6596
6602
  if (!isNewNavigationInCurrentItem) {
6597
6603
  return wrapPositionWithSafeEdge(
6598
- context.isRTL() ? pageTurnDirection === `horizontal` ? { x: position.x + context.getPageSize().width, y: 0 } : { y: position.y - context.getPageSize().height, x: 0 } : pageTurnDirection === `horizontal` ? { x: position.x - context.getPageSize().width, y: 0 } : { y: position.y - context.getPageSize().height, x: 0 }
6604
+ pageTurnDirection === `horizontal` ? { x: position.x - context.getPageSize().width, y: 0 } : { y: position.y - context.getPageSize().height, x: 0 }
6599
6605
  );
6600
6606
  } else {
6601
6607
  const readingOrderPosition = locator.getSpinePositionFromSpineItemPosition(spineItemNavigation, spineItem);
@@ -6604,7 +6610,7 @@ const createNavigationResolver = ({
6604
6610
  };
6605
6611
  const getNavigationForRightPage = (position) => {
6606
6612
  const spineItemOnPosition = locator.getSpineItemFromPosition(position) || spineItemManager.getFocusedSpineItem();
6607
- let navigation = getNavigationForRightSinglePage(position);
6613
+ const navigation = getNavigationForRightSinglePage(position);
6608
6614
  if ((spineItemOnPosition == null ? void 0 : spineItemOnPosition.isUsingVerticalWriting()) && position.x === navigation.x) {
6609
6615
  return getAdjustedPositionForSpread(navigation);
6610
6616
  }
@@ -6625,13 +6631,14 @@ const createNavigationResolver = ({
6625
6631
  if (context.getSettings().computedPageTurnDirection === `vertical` && position.y !== navigation.y) {
6626
6632
  return getAdjustedPositionForSpread(navigation);
6627
6633
  }
6628
- navigation = getNavigationForRightSinglePage(navigation);
6634
+ const doubleNavigation = getNavigationForRightSinglePage(navigation);
6635
+ return getAdjustedPositionForSpread(doubleNavigation);
6629
6636
  }
6630
6637
  return getAdjustedPositionForSpread(navigation);
6631
6638
  };
6632
6639
  const getNavigationForLeftPage = (position) => {
6633
6640
  const spineItemOnPosition = locator.getSpineItemFromPosition(position) || spineItemManager.getFocusedSpineItem();
6634
- let navigation = getNavigationForLeftSinglePage(position);
6641
+ const navigation = getNavigationForLeftSinglePage(position);
6635
6642
  if ((spineItemOnPosition == null ? void 0 : spineItemOnPosition.isUsingVerticalWriting()) && position.x === navigation.x) {
6636
6643
  return getAdjustedPositionForSpread(navigation);
6637
6644
  }
@@ -6646,17 +6653,17 @@ const createNavigationResolver = ({
6646
6653
  if (context.getSettings().computedPageTurnDirection === `vertical` && position.y !== navigation.y) {
6647
6654
  return getAdjustedPositionForSpread(navigation);
6648
6655
  }
6649
- navigation = getNavigationForLeftSinglePage(navigation);
6656
+ const doubleNavigation = getNavigationForLeftSinglePage(navigation);
6657
+ return getAdjustedPositionForSpread(doubleNavigation);
6650
6658
  }
6651
6659
  return getAdjustedPositionForSpread(navigation);
6652
6660
  };
6653
6661
  const getNavigationForUrl = (url) => {
6654
- var _a, _b;
6662
+ var _a;
6655
6663
  try {
6656
6664
  const validUrl = url instanceof URL ? url : new URL(url);
6657
6665
  const urlWithoutAnchor = `${validUrl.origin}${validUrl.pathname}`;
6658
6666
  const existingSpineItem = (_a = context.getManifest()) == null ? void 0 : _a.spineItems.find((item) => item.href === urlWithoutAnchor);
6659
- console.log({ validUrl, urlWithoutAnchor, existingSpineItem }, (_b = context.getManifest()) == null ? void 0 : _b.spineItems);
6660
6667
  if (existingSpineItem) {
6661
6668
  const spineItem = spineItemManager.get(existingSpineItem.id);
6662
6669
  if (spineItem) {
@@ -6911,7 +6918,11 @@ const createManualViewportNavigator = ({
6911
6918
  if (allowSpineItemChange) {
6912
6919
  const positionOfNewSpineItemComparedToCurrentOne = spineItemManager.comparePositionOf(newSpineItem, currentSpineItem);
6913
6920
  if (positionOfNewSpineItemComparedToCurrentOne === `before`) {
6914
- return of({ ...navigation, lastUserExpectedNavigation: { type: `navigate-from-next-item` }, animate: true });
6921
+ return of({
6922
+ ...navigation,
6923
+ lastUserExpectedNavigation: { type: `navigate-from-next-item` },
6924
+ animate: true
6925
+ });
6915
6926
  } else {
6916
6927
  return of({
6917
6928
  ...navigation,
@@ -7028,7 +7039,7 @@ const createPanViewportNavigator = ({
7028
7039
  const correctedX = delta.x - ((movingLastDelta == null ? void 0 : movingLastDelta.x) || 0);
7029
7040
  const correctedY = delta.y - ((movingLastDelta == null ? void 0 : movingLastDelta.y) || 0);
7030
7041
  navigation = navigator2.wrapPositionWithSafeEdge({
7031
- x: pageTurnDirection === `horizontal` ? context.isRTL() ? movingLastPosition.x + correctedX : movingLastPosition.x - correctedX : 0,
7042
+ x: pageTurnDirection === `horizontal` ? movingLastPosition.x - correctedX : 0,
7032
7043
  y: pageTurnDirection === `horizontal` ? 0 : movingLastPosition.y - correctedY
7033
7044
  });
7034
7045
  movingLastDelta = delta;
@@ -7090,7 +7101,10 @@ const createPanViewportNavigator = ({
7090
7101
  const triggerPercentage = movingForward ? 1 - navigationSnapThreshold : navigationSnapThreshold;
7091
7102
  const triggerXPosition = pageTurnDirection === `horizontal` ? to.x + context.getVisibleAreaRect().width * triggerPercentage : 0;
7092
7103
  const triggerYPosition = pageTurnDirection === `horizontal` ? 0 : to.y + context.getVisibleAreaRect().height * triggerPercentage;
7093
- const midScreenPositionSafePosition = navigator2.wrapPositionWithSafeEdge({ x: triggerXPosition, y: triggerYPosition });
7104
+ const midScreenPositionSafePosition = navigator2.wrapPositionWithSafeEdge({
7105
+ x: triggerXPosition,
7106
+ y: triggerYPosition
7107
+ });
7094
7108
  const finalNavigation = navigator2.getNavigationForPosition(midScreenPositionSafePosition);
7095
7109
  const lastUserExpectedNavigation = getLastUserExpectedNavigation(finalNavigation);
7096
7110
  return of({ ...finalNavigation, lastUserExpectedNavigation });
@@ -7129,7 +7143,11 @@ const createViewportNavigator = ({
7129
7143
  element.appendChild(spine.element);
7130
7144
  const layoutSubject$ = new Subject$1();
7131
7145
  let currentViewportPositionMemoUnused;
7132
- const currentNavigationPositionSubject$ = new BehaviorSubject({ x: -1, y: 0, spineItem: void 0 });
7146
+ const currentNavigationPositionSubject$ = new BehaviorSubject({
7147
+ x: -1,
7148
+ y: 0,
7149
+ spineItem: void 0
7150
+ });
7133
7151
  const navigator2 = createNavigationResolver({
7134
7152
  context,
7135
7153
  spineItemManager,
@@ -7139,8 +7157,6 @@ const createViewportNavigator = ({
7139
7157
  const adjustNavigationSubject$ = new Subject$1();
7140
7158
  parentElement.appendChild(element);
7141
7159
  const getCurrentViewportPosition = Report.measurePerformance(`${NAMESPACE} getCurrentViewportPosition`, 1, () => {
7142
- if (currentViewportPositionMemoUnused && (currentViewportPositionMemoUnused == null ? void 0 : currentViewportPositionMemoUnused.x) !== ~~(Math.abs(element.getBoundingClientRect().x) * 10) / 10)
7143
- ;
7144
7160
  if (context.getSettings().computedPageTurnMode === `scrollable`) {
7145
7161
  return scrollViewportNavigator.getCurrentViewportPosition();
7146
7162
  }
@@ -7149,7 +7165,8 @@ const createViewportNavigator = ({
7149
7165
  // we want to round to first decimal because it's possible to have half pixel
7150
7166
  // however browser engine can also gives back x.yyyy based on their precision
7151
7167
  // @see https://stackoverflow.com/questions/13847053/difference-between-and-math-floor for ~~
7152
- x: ~~(Math.abs(x) * 10) / 10,
7168
+ x: ~~(x * -1 * 10) / 10,
7169
+ // x: ~~(x * 10) / 10,
7153
7170
  y: ~~(Math.abs(y) * 10) / 10
7154
7171
  };
7155
7172
  currentViewportPositionMemoUnused = newValue;
@@ -7196,11 +7213,7 @@ const createViewportNavigator = ({
7196
7213
  return navigator22.adjustReadingOffset({ x, y }) || isAdjusted2;
7197
7214
  }, false);
7198
7215
  if (!isAdjusted) {
7199
- if (context.isRTL()) {
7200
- element.style.transform = `translate3d(${x}px, -${y}px, 0)`;
7201
- } else {
7202
- element.style.transform = `translate3d(-${x}px, -${y}px, 0)`;
7203
- }
7216
+ element.style.transform = `translate3d(${-x}px, -${y}px, 0)`;
7204
7217
  }
7205
7218
  hooks.forEach((hook) => {
7206
7219
  if (hook.name === `onViewportOffsetAdjust`) {
@@ -7525,14 +7538,7 @@ const createLocationResolver = ({
7525
7538
  `getSpineItemPositionFromSpinePosition`,
7526
7539
  10,
7527
7540
  (position, spineItem) => {
7528
- const { leftEnd, leftStart, topStart, topEnd } = spineItemManager.getAbsolutePositionOf(spineItem);
7529
- if (context.isRTL()) {
7530
- return {
7531
- x: leftEnd - position.x - context.getPageSize().width,
7532
- // y: (topEnd - position.y) - context.getPageSize().height,
7533
- y: Math.max(0, position.y - topStart)
7534
- };
7535
- }
7541
+ const { left, top } = spineItemManager.getAbsolutePositionOf(spineItem);
7536
7542
  return {
7537
7543
  /**
7538
7544
  * when using spread the item could be on the right and therefore will be negative
@@ -7541,31 +7547,35 @@ const createLocationResolver = ({
7541
7547
  * 400 - 600 = -200.
7542
7548
  * However we can assume we are at 0, because we in fact can see the beginning of the item
7543
7549
  */
7544
- x: Math.max(0, position.x - leftStart),
7545
- y: Math.max(0, position.y - topStart)
7550
+ x: position.x - left,
7551
+ y: position.y - top
7546
7552
  };
7547
7553
  },
7548
7554
  { disable: true }
7549
7555
  );
7550
7556
  const getSpinePositionFromSpineItemPosition = (spineItemPosition, spineItem) => {
7551
- const { leftEnd, leftStart, topStart, topEnd } = spineItemManager.getAbsolutePositionOf(spineItem);
7552
- if (context.isRTL()) {
7553
- return {
7554
- x: leftEnd - spineItemPosition.x - context.getPageSize().width,
7555
- // y: (topEnd - spineItemPosition.y) - context.getPageSize().height,
7556
- y: topStart + spineItemPosition.y
7557
- };
7558
- }
7557
+ const { left, top } = spineItemManager.getAbsolutePositionOf(spineItem);
7559
7558
  return {
7560
- x: leftStart + spineItemPosition.x,
7561
- y: topStart + spineItemPosition.y
7559
+ x: left + spineItemPosition.x,
7560
+ y: top + spineItemPosition.y
7562
7561
  };
7563
7562
  };
7564
7563
  const getSpineItemFromPosition = Report.measurePerformance(
7565
7564
  `getSpineItemFromOffset`,
7566
7565
  10,
7567
7566
  (position) => {
7568
- const spineItem = spineItemManager.getSpineItemAtPosition(position);
7567
+ const spineItem = spineItemManager.getAll().find((item) => {
7568
+ const { left, right, bottom, top } = spineItemManager.getAbsolutePositionOf(item);
7569
+ const isWithinXAxis = position.x >= left && position.x < right;
7570
+ if (context.getSettings().computedPageTurnDirection === `horizontal`) {
7571
+ return isWithinXAxis;
7572
+ } else {
7573
+ return isWithinXAxis && position.y >= top && position.y < bottom;
7574
+ }
7575
+ });
7576
+ if (position.x === 0 && !spineItem) {
7577
+ return spineItemManager.getAll()[0];
7578
+ }
7569
7579
  return spineItem;
7570
7580
  },
7571
7581
  { disable: true }
@@ -7579,23 +7589,30 @@ const createLocationResolver = ({
7579
7589
  return position;
7580
7590
  };
7581
7591
  const getSpineItemsFromReadingOrderPosition = (position) => {
7582
- const beginItem = getSpineItemFromPosition(position) || spineItemManager.getFocusedSpineItem();
7583
- const beginItemIndex = spineItemManager.getSpineItemIndex(beginItem);
7584
- if (beginItemIndex === void 0)
7592
+ const itemAtPosition = getSpineItemFromPosition(position) || spineItemManager.getFocusedSpineItem();
7593
+ const itemAtPositionIndex = spineItemManager.getSpineItemIndex(itemAtPosition);
7594
+ if (itemAtPositionIndex === void 0)
7585
7595
  return void 0;
7586
7596
  let endPosition = position;
7587
7597
  if (context.shouldDisplaySpread()) {
7588
7598
  endPosition = { x: position.x + context.getPageSize().width, y: position.y };
7589
7599
  }
7590
- const endItemIndex = spineItemManager.getSpineItemIndex(getSpineItemFromPosition(endPosition) || spineItemManager.getFocusedSpineItem()) ?? beginItemIndex;
7591
- const [left = beginItemIndex, right = beginItemIndex] = [beginItemIndex, endItemIndex].sort((a, b) => a - b);
7600
+ const endItemIndex = spineItemManager.getSpineItemIndex(getSpineItemFromPosition(endPosition) || spineItemManager.getFocusedSpineItem()) ?? itemAtPositionIndex;
7601
+ const items = [
7602
+ { item: itemAtPositionIndex, position },
7603
+ { item: endItemIndex, position: endPosition }
7604
+ ];
7605
+ const [begin, end] = items.sort((a, b) => {
7606
+ if (a.item === b.item) {
7607
+ return context.isRTL() ? b.position.x - a.position.x : a.position.x - b.position.x;
7608
+ }
7609
+ return a.item - b.item;
7610
+ });
7592
7611
  return {
7593
- begin: beginItemIndex,
7594
- beginPosition: position,
7595
- end: endItemIndex,
7596
- endPosition,
7597
- left,
7598
- right
7612
+ begin: begin.item,
7613
+ beginPosition: begin.position,
7614
+ end: end.item,
7615
+ endPosition: end.position
7599
7616
  };
7600
7617
  };
7601
7618
  const getSpineItemFromIframe = (iframe) => {
@@ -7777,7 +7794,12 @@ const createReader = ({ containerElement, hooks: initialHooks, ...settings }) =>
7777
7794
  element.style.height = `${dimensions.height - marginTop - marginBottom}px`;
7778
7795
  element.style.width = `${containerElementEvenWidth - 2 * margin}px`;
7779
7796
  const elementRect = element.getBoundingClientRect();
7780
- context.setVisibleAreaRect(elementRect.x, elementRect.y, containerElementEvenWidth, dimensions.height);
7797
+ context.setVisibleAreaRect({
7798
+ x: elementRect.x,
7799
+ y: elementRect.y,
7800
+ width: containerElementEvenWidth,
7801
+ height: dimensions.height
7802
+ });
7781
7803
  viewportNavigator.layout();
7782
7804
  };
7783
7805
  const load = (manifest, loadOptions = {}) => {
@@ -7898,6 +7920,7 @@ const createReader = ({ containerElement, hooks: initialHooks, ...settings }) =>
7898
7920
  * BehaviorSubject
7899
7921
  */
7900
7922
  pagination$: pagination.$.info$,
7923
+ spineItems$: spine.$.spineItems$,
7901
7924
  $: {
7902
7925
  state$: stateSubject$.asObservable(),
7903
7926
  /**
@@ -7913,7 +7936,6 @@ const createReader = ({ containerElement, hooks: initialHooks, ...settings }) =>
7913
7936
  selection$: selectionSubject$.asObservable(),
7914
7937
  viewportState$: viewportNavigator.$.state$,
7915
7938
  layout$: spine.$.layout$,
7916
- itemsCreated$: spine.$.itemsCreated$,
7917
7939
  itemsBeforeDestroy$: spine.$.itemsBeforeDestroy$,
7918
7940
  itemIsReady$: spineItemManager.$.itemIsReady$,
7919
7941
  destroy$
@@ -8271,11 +8293,11 @@ const progressionEnhancer = (next) => (options) => {
8271
8293
  };
8272
8294
  const getScrollPercentageWithinItem = (context, currentPosition, currentItem) => {
8273
8295
  const { height, width } = currentItem.getElementDimensions();
8274
- const { topStart, leftStart } = reader.getAbsolutePositionOf(currentItem);
8296
+ const { top, left } = reader.getAbsolutePositionOf(currentItem);
8275
8297
  if (context.getSettings().computedPageTurnDirection === `vertical`) {
8276
- return Math.max(0, Math.min(1, (currentPosition.y - topStart + context.getVisibleAreaRect().height) / height));
8298
+ return Math.max(0, Math.min(1, (currentPosition.y - top + context.getVisibleAreaRect().height) / height));
8277
8299
  } else {
8278
- return Math.max(0, Math.min(1, (currentPosition.x - leftStart + context.getVisibleAreaRect().width) / width));
8300
+ return Math.max(0, Math.min(1, (currentPosition.x - left + context.getVisibleAreaRect().width) / width));
8279
8301
  }
8280
8302
  };
8281
8303
  return {
@@ -8403,7 +8425,7 @@ const loadingEnhancer = (next) => (options) => {
8403
8425
  return {};
8404
8426
  })
8405
8427
  );
8406
- const items$ = reader.$.itemsCreated$.pipe(
8428
+ const items$ = reader.spineItems$.pipe(
8407
8429
  switchMap((items) => createEntries$(items)),
8408
8430
  shareReplay(1),
8409
8431
  takeUntil(reader.context.$.destroy$)