@prose-reader/core 1.192.0 → 1.194.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { switchMap, of, fromEvent, take, map, from, takeUntil, Observable, defer, Subject, combineLatest, merge, EMPTY, withLatestFrom, BehaviorSubject, filter, share, first as first$1, mergeMap, endWith, tap as tap$1, finalize, catchError, lastValueFrom, NEVER, scheduled, animationFrameScheduler, distinctUntilChanged as distinctUntilChanged$1, throttleTime, debounceTime as debounceTime$1, startWith as startWith$1, switchScan, forkJoin, shareReplay as shareReplay$1, delay, ReplaySubject, identity, timer, skip as skip$1, exhaustMap, reduce, concatMap } from "rxjs";
2
- import { switchMap as switchMap$1, first, map as map$1, startWith, shareReplay, distinctUntilChanged, tap, pairwise, take as take$1, takeUntil as takeUntil$1, filter as filter$1, debounceTime, skip, mergeMap as mergeMap$1, catchError as catchError$1, withLatestFrom as withLatestFrom$1, share as share$1 } from "rxjs/operators";
2
+ import { switchMap as switchMap$1, first, map as map$1, startWith, shareReplay, distinctUntilChanged, tap, pairwise, take as take$1, takeUntil as takeUntil$1, filter as filter$1, debounceTime, skip, mergeMap as mergeMap$1, catchError as catchError$1, withLatestFrom as withLatestFrom$1 } from "rxjs/operators";
3
3
  import { shallowMergeIfDefined, isShallowEqual, getParentPath, parseContentType, detectMimeTypeFromName, arrayEqual } from "@prose-reader/shared";
4
4
  import { isShallowEqual as isShallowEqual2 } from "@prose-reader/shared";
5
5
  const getAttributeValueFromString = (string, key) => {
@@ -902,7 +902,6 @@ class DocumentRenderer extends DestroyableClass {
902
902
  constructor(params) {
903
903
  super();
904
904
  this.triggerSubject = new Subject();
905
- this.lastLayoutDims = void 0;
906
905
  this.stateSubject = new BehaviorSubject(`idle`);
907
906
  this.unload$ = this.triggerSubject.pipe(
908
907
  withLatestFrom(this.stateSubject),
@@ -1034,57 +1033,8 @@ class DocumentRenderer extends DestroyableClass {
1034
1033
  })
1035
1034
  );
1036
1035
  }
1037
- /**
1038
- * @important
1039
- *
1040
- * If renderer returns undefined as dimensions we will use the previous
1041
- * layout dimensions as fallback. This ensure minmum layout shift during
1042
- * load / unload of items and improve stability..
1043
- */
1044
1036
  layout(params) {
1045
- return defer(() => this.onLayout(params)).pipe(
1046
- map((dims) => {
1047
- var _a, _b, _c, _d;
1048
- const { height: defaultHeight, width: defaultWidth } = this.context.getPageSize();
1049
- if (dims) {
1050
- const { height, width } = dims;
1051
- if (height < defaultHeight || width < defaultWidth) {
1052
- Report.warn(
1053
- `Your height or width is smaller than the page size. Please check your rendering.`
1054
- );
1055
- }
1056
- this.lastLayoutDims = {
1057
- height,
1058
- width,
1059
- pageSize: this.context.getPageSize()
1060
- };
1061
- return this.lastLayoutDims;
1062
- }
1063
- const hasPageSizeChanged = ((_a = this.lastLayoutDims) == null ? void 0 : _a.pageSize.width) !== this.context.getPageSize().width || ((_b = this.lastLayoutDims) == null ? void 0 : _b.pageSize.height) !== this.context.getPageSize().height;
1064
- if (this.renditionLayout === `pre-paginated` || // in the case the page size change, we cannot use the old size reliably
1065
- // we have to drop it and use the default one
1066
- hasPageSizeChanged) {
1067
- this.lastLayoutDims = {
1068
- height: this.context.getPageSize().height,
1069
- width: params.minimumWidth,
1070
- pageSize: this.context.getPageSize()
1071
- };
1072
- } else {
1073
- this.lastLayoutDims = {
1074
- height: Math.max(
1075
- defaultHeight,
1076
- ((_c = this.lastLayoutDims) == null ? void 0 : _c.height) ?? defaultHeight
1077
- ),
1078
- width: Math.max(
1079
- defaultWidth,
1080
- ((_d = this.lastLayoutDims) == null ? void 0 : _d.width) ?? defaultWidth
1081
- ),
1082
- pageSize: this.context.getPageSize()
1083
- };
1084
- }
1085
- return this.lastLayoutDims;
1086
- })
1087
- );
1037
+ return defer(() => this.onLayout(params)).pipe();
1088
1038
  }
1089
1039
  destroy() {
1090
1040
  super.destroy();
@@ -3351,7 +3301,7 @@ const getTotalProgressFromPercentages = (estimateBeforeThisItem, currentItemWeig
3351
3301
  };
3352
3302
  const getScrollPercentageWithinItem = (reader, currentPosition, currentItem) => {
3353
3303
  const context = reader.context;
3354
- const { height, width } = currentItem.getElementDimensions();
3304
+ const { height, width } = currentItem.layoutPosition;
3355
3305
  const { top, left } = reader.spine.spineLayout.getAbsolutePositionOf(currentItem);
3356
3306
  if (reader.settings.values.computedPageTurnDirection === `vertical`) {
3357
3307
  return Math.max(
@@ -3415,7 +3365,7 @@ const getPercentageEstimate = (reader, currentSpineIndex, pageIndex, currentPosi
3415
3365
  );
3416
3366
  };
3417
3367
  const getNumberOfPagesForAllSpineItems = (reader) => reader.spineItemsManager.items.map((item) => {
3418
- const { height, width } = item.getElementDimensions();
3368
+ const { height, width } = item.layoutPosition;
3419
3369
  return reader.spine.spineItemLocator.getSpineItemNumberOfPages({
3420
3370
  isUsingVerticalWriting: !!item.isUsingVerticalWriting(),
3421
3371
  itemHeight: height,
@@ -5615,7 +5565,7 @@ const createSpineItemLocator = ({
5615
5565
  const range = node ? getRangeFromNode(node, offset) : void 0;
5616
5566
  offsetOfNodeInSpineItem = (range == null ? void 0 : range.getBoundingClientRect().x) || offsetOfNodeInSpineItem;
5617
5567
  }
5618
- const spineItemWidth = ((_a = spineItem.getElementDimensions()) == null ? void 0 : _a.width) || 0;
5568
+ const spineItemWidth = ((_a = spineItem.layoutPosition) == null ? void 0 : _a.width) || 0;
5619
5569
  const pageWidth = context.getPageSize().width;
5620
5570
  if (offsetOfNodeInSpineItem !== void 0) {
5621
5571
  const val = getClosestValidOffsetFromApproximateOffsetInPages(
@@ -5635,7 +5585,7 @@ const createSpineItemLocator = ({
5635
5585
  frame.contentWindow.document.body !== null) {
5636
5586
  const { x: left, y: top } = getSpineItemPositionFromPageIndex({
5637
5587
  pageIndex,
5638
- itemLayout: spineItem.getElementDimensions(),
5588
+ itemLayout: spineItem.layoutPosition,
5639
5589
  context,
5640
5590
  isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting()
5641
5591
  });
@@ -5654,7 +5604,7 @@ const createSpineItemLocator = ({
5654
5604
  return void 0;
5655
5605
  };
5656
5606
  const getSpineItemClosestPositionFromUnsafePosition = (unsafePosition, spineItem) => {
5657
- const { width, height } = spineItem.getElementDimensions();
5607
+ const { width, height } = spineItem.layoutPosition;
5658
5608
  const adjustedPosition = {
5659
5609
  x: getClosestValidOffsetFromApproximateOffsetInPages(
5660
5610
  unsafePosition.x,
@@ -5671,7 +5621,7 @@ const createSpineItemLocator = ({
5671
5621
  };
5672
5622
  const getSpineItemPageIndexFromNode = (node, offset, spineItem) => {
5673
5623
  const position = getSpineItemPositionFromNode(node, offset, spineItem);
5674
- const { height, width } = spineItem.getElementDimensions();
5624
+ const { height, width } = spineItem.layoutPosition;
5675
5625
  return position ? getSpineItemPageIndexFromPosition({
5676
5626
  isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting(),
5677
5627
  position,
@@ -5709,7 +5659,7 @@ const createSpineItemLocator = ({
5709
5659
  context,
5710
5660
  isUsingVerticalWriting: !!item.isUsingVerticalWriting(),
5711
5661
  settings,
5712
- itemLayout: item.getElementDimensions()
5662
+ itemLayout: item.layoutPosition
5713
5663
  });
5714
5664
  },
5715
5665
  getSpineItemNumberOfPages: (params) => getSpineItemNumberOfPages({
@@ -5725,7 +5675,7 @@ const createNavigationResolver$1 = ({
5725
5675
  }) => {
5726
5676
  const spineItemLocator = createSpineItemLocator({ context, settings });
5727
5677
  const getNavigationForLastPage = (spineItem) => {
5728
- const { height, width } = spineItem.getElementDimensions();
5678
+ const { height, width } = spineItem.layoutPosition;
5729
5679
  const numberOfPages = spineItemLocator.getSpineItemNumberOfPages({
5730
5680
  isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting(),
5731
5681
  itemHeight: height,
@@ -5734,7 +5684,7 @@ const createNavigationResolver$1 = ({
5734
5684
  return spineItemLocator.getSpineItemPositionFromPageIndex({
5735
5685
  pageIndex: numberOfPages - 1,
5736
5686
  isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting(),
5737
- itemLayout: spineItem.getElementDimensions()
5687
+ itemLayout: spineItem.layoutPosition
5738
5688
  });
5739
5689
  };
5740
5690
  const getNavigationFromNode = (spineItem, node, offset) => {
@@ -5801,7 +5751,7 @@ const getSpineItemOffsetFromAnchor = ({
5801
5751
  context
5802
5752
  }) => {
5803
5753
  var _a;
5804
- const itemWidth = ((_a = spineItem.getElementDimensions()) == null ? void 0 : _a.width) || 0;
5754
+ const itemWidth = ((_a = spineItem.layoutPosition) == null ? void 0 : _a.width) || 0;
5805
5755
  const pageWidth = context.getPageSize().width;
5806
5756
  const anchorElementBoundingRect = spineItem.getBoundingRectOfElementFromSelector(anchor);
5807
5757
  const offsetOfAnchor = (anchorElementBoundingRect == null ? void 0 : anchorElementBoundingRect.x) || 0;
@@ -5960,7 +5910,7 @@ const getNavigationForSpineItemPage = ({
5960
5910
  const spineItemNavigation = spineLocator.spineItemLocator.getSpineItemPositionFromPageIndex({
5961
5911
  pageIndex,
5962
5912
  isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting(),
5963
- itemLayout: spineItem.getElementDimensions()
5913
+ itemLayout: spineItem.layoutPosition
5964
5914
  });
5965
5915
  const readingOffset = spineLocator.getSpinePositionFromSpineItemPosition({
5966
5916
  spineItemPosition: spineItemNavigation,
@@ -6727,7 +6677,7 @@ const withSpineItemPosition = ({
6727
6677
  const positionInSpineItem = spineLocator.spineItemLocator.getSpineItemPositionFromPageIndex({
6728
6678
  pageIndex: beginPageIndexForDirection,
6729
6679
  isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting(),
6730
- itemLayout: spineItem.getElementDimensions()
6680
+ itemLayout: spineItem.layoutPosition
6731
6681
  });
6732
6682
  return positionInSpineItem;
6733
6683
  }
@@ -7426,13 +7376,13 @@ class PaginationController extends DestroyableClass {
7426
7376
  const shouldUpdateEndCfi = previousPagination.endSpineItemIndex !== endSpineItemIndex || endLastCfi === void 0 || isRootCfi(endLastCfi);
7427
7377
  const beginCfi = shouldUpdateBeginCfi ? getRootCfi(beginSpineItem) : beginLastCfi;
7428
7378
  const endCfi = shouldUpdateEndCfi ? getRootCfi(endSpineItem) : endLastCfi;
7429
- const beginSpineItemDimensions = beginSpineItem.getElementDimensions();
7379
+ const beginSpineItemDimensions = beginSpineItem.layoutPosition;
7430
7380
  const beginNumberOfPagesInSpineItem = this.spineItemLocator.getSpineItemNumberOfPages({
7431
7381
  itemHeight: beginSpineItemDimensions.height,
7432
7382
  itemWidth: beginSpineItemDimensions.width,
7433
7383
  isUsingVerticalWriting: !!beginSpineItem.isUsingVerticalWriting()
7434
7384
  });
7435
- const endSpineItemDimensions = endSpineItem.getElementDimensions();
7385
+ const endSpineItemDimensions = endSpineItem.layoutPosition;
7436
7386
  const endNumberOfPagesInSpineItem = this.spineItemLocator.getSpineItemNumberOfPages({
7437
7387
  itemHeight: endSpineItemDimensions.height,
7438
7388
  itemWidth: endSpineItemDimensions.width,
@@ -7607,24 +7557,44 @@ class ReaderSettingsManager extends SettingsManager3 {
7607
7557
  };
7608
7558
  }
7609
7559
  }
7610
- const getSpineItemFromPosition = ({
7611
- position,
7612
- spineItemsManager,
7560
+ const getAbsolutePageIndexFromPageIndex = ({
7561
+ pageIndex,
7562
+ spineItemOrId,
7613
7563
  spineLayout,
7564
+ spineItemsManager,
7565
+ context,
7614
7566
  settings
7615
7567
  }) => {
7616
- const spineItem = spineItemsManager.items.find((item) => {
7617
- const { left, right, bottom, top } = spineLayout.getAbsolutePositionOf(item);
7618
- const isWithinXAxis = position.x >= left && position.x < right;
7619
- if (settings.values.computedPageTurnDirection === `horizontal`) {
7620
- return isWithinXAxis;
7621
- }
7622
- return isWithinXAxis && position.y >= top && position.y < bottom;
7623
- });
7624
- if (position.x === 0 && !spineItem) {
7625
- return spineItemsManager.items[0];
7626
- }
7627
- return spineItem;
7568
+ const items = spineItemsManager.items;
7569
+ const spineItem = spineItemsManager.get(spineItemOrId);
7570
+ if (!spineItem) return void 0;
7571
+ const { currentAbsolutePage } = items.reduce(
7572
+ (acc, item) => {
7573
+ if (acc.found) return acc;
7574
+ const itemLayout = spineLayout.getAbsolutePositionOf(item);
7575
+ const numberOfPages = getSpineItemNumberOfPages({
7576
+ isUsingVerticalWriting: !!item.isUsingVerticalWriting(),
7577
+ itemHeight: itemLayout.height,
7578
+ itemWidth: itemLayout.width,
7579
+ context,
7580
+ settings
7581
+ });
7582
+ if (spineItem === item) {
7583
+ if (pageIndex <= numberOfPages - 1) {
7584
+ return {
7585
+ currentAbsolutePage: acc.currentAbsolutePage + pageIndex,
7586
+ found: true
7587
+ };
7588
+ }
7589
+ }
7590
+ return {
7591
+ ...acc,
7592
+ currentAbsolutePage: acc.currentAbsolutePage + numberOfPages
7593
+ };
7594
+ },
7595
+ { currentAbsolutePage: 0, found: false }
7596
+ );
7597
+ return currentAbsolutePage;
7628
7598
  };
7629
7599
  const isItemVisibleByThresholdForPosition = ({
7630
7600
  itemHeight,
@@ -7700,57 +7670,6 @@ const getItemVisibilityForPosition = ({
7700
7670
  visible: isItemVisibleEnough || isItemVisibleEnoughOnScreen
7701
7671
  };
7702
7672
  };
7703
- const getVisibleSpineItemsFromPosition = ({
7704
- position,
7705
- threshold,
7706
- restrictToScreen,
7707
- spineItemsManager,
7708
- context,
7709
- settings,
7710
- spineLayout
7711
- }) => {
7712
- const fallbackSpineItem = getSpineItemFromPosition({
7713
- position,
7714
- settings,
7715
- spineItemsManager,
7716
- spineLayout
7717
- }) || spineItemsManager.get(0);
7718
- const spineItemsVisible = spineItemsManager.items.reduce(
7719
- (acc, spineItem) => {
7720
- const itemPosition = spineLayout.getAbsolutePositionOf(spineItem);
7721
- const { visible } = getItemVisibilityForPosition({
7722
- itemPosition,
7723
- threshold,
7724
- viewportPosition: position,
7725
- restrictToScreen,
7726
- context
7727
- });
7728
- if (visible) {
7729
- return [...acc, spineItem];
7730
- }
7731
- return acc;
7732
- },
7733
- []
7734
- );
7735
- const beginItem = spineItemsVisible[0] ?? fallbackSpineItem;
7736
- const endItem = spineItemsVisible[spineItemsVisible.length - 1] ?? beginItem;
7737
- if (!beginItem || !endItem) return void 0;
7738
- const beginItemIndex = spineItemsManager.getSpineItemIndex(beginItem);
7739
- const endItemIndex = spineItemsManager.getSpineItemIndex(endItem);
7740
- return {
7741
- beginIndex: beginItemIndex ?? 0,
7742
- endIndex: endItemIndex ?? 0
7743
- };
7744
- };
7745
- const getSpinePositionFromSpineItemPosition = ({
7746
- spineItemPosition,
7747
- itemLayout: { left, top }
7748
- }) => {
7749
- return {
7750
- x: left + spineItemPosition.x,
7751
- y: top + spineItemPosition.y
7752
- };
7753
- };
7754
7673
  const getSpineInfoFromAbsolutePageIndex = ({
7755
7674
  absolutePageIndex,
7756
7675
  spineLayout,
@@ -7796,44 +7715,75 @@ const getSpineInfoFromAbsolutePageIndex = ({
7796
7715
  }
7797
7716
  return void 0;
7798
7717
  };
7799
- const getAbsolutePageIndexFromPageIndex = ({
7800
- pageIndex,
7801
- spineItemOrId,
7718
+ const getSpineItemFromPosition = ({
7719
+ position,
7720
+ spineItemsManager,
7802
7721
  spineLayout,
7722
+ settings
7723
+ }) => {
7724
+ const spineItem = spineItemsManager.items.find((item) => {
7725
+ const { left, right, bottom, top } = spineLayout.getAbsolutePositionOf(item);
7726
+ const isWithinXAxis = position.x >= left && position.x < right;
7727
+ if (settings.values.computedPageTurnDirection === `horizontal`) {
7728
+ return isWithinXAxis;
7729
+ }
7730
+ return isWithinXAxis && position.y >= top && position.y < bottom;
7731
+ });
7732
+ if (position.x === 0 && !spineItem) {
7733
+ return spineItemsManager.items[0];
7734
+ }
7735
+ return spineItem;
7736
+ };
7737
+ const getSpinePositionFromSpineItemPosition = ({
7738
+ spineItemPosition,
7739
+ itemLayout: { left, top }
7740
+ }) => {
7741
+ return {
7742
+ x: left + spineItemPosition.x,
7743
+ y: top + spineItemPosition.y
7744
+ };
7745
+ };
7746
+ const getVisibleSpineItemsFromPosition = ({
7747
+ position,
7748
+ threshold,
7749
+ restrictToScreen,
7803
7750
  spineItemsManager,
7804
7751
  context,
7805
- settings
7752
+ settings,
7753
+ spineLayout
7806
7754
  }) => {
7807
- const items = spineItemsManager.items;
7808
- const spineItem = spineItemsManager.get(spineItemOrId);
7809
- if (!spineItem) return void 0;
7810
- const { currentAbsolutePage } = items.reduce(
7811
- (acc, item) => {
7812
- if (acc.found) return acc;
7813
- const itemLayout = spineLayout.getAbsolutePositionOf(item);
7814
- const numberOfPages = getSpineItemNumberOfPages({
7815
- isUsingVerticalWriting: !!item.isUsingVerticalWriting(),
7816
- itemHeight: itemLayout.height,
7817
- itemWidth: itemLayout.width,
7818
- context,
7819
- settings
7755
+ const fallbackSpineItem = getSpineItemFromPosition({
7756
+ position,
7757
+ settings,
7758
+ spineItemsManager,
7759
+ spineLayout
7760
+ }) || spineItemsManager.get(0);
7761
+ const spineItemsVisible = spineItemsManager.items.reduce(
7762
+ (acc, spineItem) => {
7763
+ const itemPosition = spineLayout.getAbsolutePositionOf(spineItem);
7764
+ const { visible } = getItemVisibilityForPosition({
7765
+ itemPosition,
7766
+ threshold,
7767
+ viewportPosition: position,
7768
+ restrictToScreen,
7769
+ context
7820
7770
  });
7821
- if (spineItem === item) {
7822
- if (pageIndex <= numberOfPages - 1) {
7823
- return {
7824
- currentAbsolutePage: acc.currentAbsolutePage + pageIndex,
7825
- found: true
7826
- };
7827
- }
7771
+ if (visible) {
7772
+ return [...acc, spineItem];
7828
7773
  }
7829
- return {
7830
- ...acc,
7831
- currentAbsolutePage: acc.currentAbsolutePage + numberOfPages
7832
- };
7774
+ return acc;
7833
7775
  },
7834
- { currentAbsolutePage: 0, found: false }
7776
+ []
7835
7777
  );
7836
- return currentAbsolutePage;
7778
+ const beginItem = spineItemsVisible[0] ?? fallbackSpineItem;
7779
+ const endItem = spineItemsVisible[spineItemsVisible.length - 1] ?? beginItem;
7780
+ if (!beginItem || !endItem) return void 0;
7781
+ const beginItemIndex = spineItemsManager.getSpineItemIndex(beginItem);
7782
+ const endItemIndex = spineItemsManager.getSpineItemIndex(endItem);
7783
+ return {
7784
+ beginIndex: beginItemIndex ?? 0,
7785
+ endIndex: endItemIndex ?? 0
7786
+ };
7837
7787
  };
7838
7788
  const createSpineLocator = ({
7839
7789
  spineItemsManager,
@@ -7894,7 +7844,7 @@ const createSpineLocator = ({
7894
7844
  spineItem,
7895
7845
  restrictToScreen
7896
7846
  }) => {
7897
- const { height, width } = spineItem.getElementDimensions();
7847
+ const { height, width } = spineItem.layoutPosition;
7898
7848
  const numberOfPages = spineItemLocator.getSpineItemNumberOfPages({
7899
7849
  isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting(),
7900
7850
  itemHeight: height,
@@ -7904,7 +7854,7 @@ const createSpineLocator = ({
7904
7854
  const spineItemPosition = spineItemLocator.getSpineItemPositionFromPageIndex({
7905
7855
  pageIndex: index,
7906
7856
  isUsingVerticalWriting: !!spineItem.isUsingVerticalWriting(),
7907
- itemLayout: spineItem.getElementDimensions()
7857
+ itemLayout: spineItem.layoutPosition
7908
7858
  });
7909
7859
  const spinePosition = getSpinePositionFromSpineItemPosition({
7910
7860
  spineItemPosition,
@@ -8129,8 +8079,7 @@ const layoutItem = ({
8129
8079
  isGloballyPrePaginated,
8130
8080
  settings,
8131
8081
  index,
8132
- item,
8133
- newItemLayoutInformation
8082
+ item
8134
8083
  }) => {
8135
8084
  let minimumWidth = context.getPageSize().width;
8136
8085
  let blankPagePosition = `none`;
@@ -8182,16 +8131,6 @@ const layoutItem = ({
8182
8131
  }
8183
8132
  const newEdgeX = width + currentValidEdgeXForVerticalPositioning;
8184
8133
  const newEdgeY = height + currentValidEdgeYForVerticalPositioning;
8185
- newItemLayoutInformation.push({
8186
- left: currentValidEdgeXForVerticalPositioning,
8187
- right: newEdgeX,
8188
- top: currentValidEdgeYForVerticalPositioning,
8189
- bottom: newEdgeY,
8190
- height,
8191
- width,
8192
- x: currentValidEdgeXForVerticalPositioning,
8193
- y: currentValidEdgeYForVerticalPositioning
8194
- });
8195
8134
  return {
8196
8135
  horizontalOffset: newEdgeX,
8197
8136
  verticalOffset: newEdgeY
@@ -8200,17 +8139,6 @@ const layoutItem = ({
8200
8139
  item.adjustPositionOfElement(
8201
8140
  context.isRTL() ? { right: horizontalOffset, top: 0 } : { left: horizontalOffset, top: 0 }
8202
8141
  );
8203
- const left = context.isRTL() ? context.state.visibleAreaRect.width - horizontalOffset - width : horizontalOffset;
8204
- newItemLayoutInformation.push({
8205
- right: context.isRTL() ? context.state.visibleAreaRect.width - horizontalOffset : horizontalOffset + width,
8206
- left,
8207
- x: left,
8208
- top: verticalOffset,
8209
- bottom: height,
8210
- height,
8211
- width,
8212
- y: verticalOffset
8213
- });
8214
8142
  return {
8215
8143
  horizontalOffset: horizontalOffset + width,
8216
8144
  verticalOffset: 0
@@ -8225,7 +8153,6 @@ class SpineLayout extends DestroyableClass {
8225
8153
  this.spineItemsManager = spineItemsManager;
8226
8154
  this.context = context;
8227
8155
  this.settings = settings;
8228
- this.itemLayoutInformation = [];
8229
8156
  this.layoutSubject = new Subject();
8230
8157
  spineItemsManager.items$.pipe(
8231
8158
  switchMap((items) => {
@@ -8267,7 +8194,6 @@ class SpineLayout extends DestroyableClass {
8267
8194
  exhaustMap(() => {
8268
8195
  layoutInProgress.next(true);
8269
8196
  const manifest = this.context.manifest;
8270
- const newItemLayoutInformation = [];
8271
8197
  const isGloballyPrePaginated = isFullyPrePaginated(manifest) ?? false;
8272
8198
  return from(this.spineItemsManager.items).pipe(
8273
8199
  reduce(
@@ -8281,31 +8207,22 @@ class SpineLayout extends DestroyableClass {
8281
8207
  item,
8282
8208
  settings: this.settings,
8283
8209
  spineItemsManager: this.spineItemsManager,
8284
- verticalOffset,
8285
- newItemLayoutInformation
8210
+ verticalOffset
8286
8211
  })
8287
8212
  )
8288
8213
  ),
8289
8214
  of({ horizontalOffset: 0, verticalOffset: 0 })
8290
8215
  ),
8291
8216
  concatMap((layout$) => layout$),
8292
- map(() => {
8293
- const hasChanged = this.itemLayoutInformation.length !== newItemLayoutInformation.length || this.itemLayoutInformation.some(
8294
- (old, index) => !isShallowEqual(old, newItemLayoutInformation[index])
8295
- );
8296
- this.itemLayoutInformation = newItemLayoutInformation;
8297
- Report.log(NAMESPACE, `layout`, {
8298
- hasChanged,
8299
- itemLayoutInformation: this.itemLayoutInformation
8300
- });
8301
- return { hasChanged };
8217
+ tap$1(() => {
8218
+ Report.log(NAMESPACE, `layout`);
8302
8219
  }),
8303
8220
  finalize(() => {
8304
8221
  layoutInProgress.next(false);
8305
8222
  })
8306
8223
  );
8307
8224
  }),
8308
- map(({ hasChanged }) => {
8225
+ map(() => {
8309
8226
  const items = spineItemsManager.items;
8310
8227
  const spineItemsPagesAbsolutePositions = items.map((item) => {
8311
8228
  const itemLayout = this.getAbsolutePositionOf(item);
@@ -8346,7 +8263,6 @@ class SpineLayout extends DestroyableClass {
8346
8263
  []
8347
8264
  );
8348
8265
  return {
8349
- hasChanged,
8350
8266
  spineItemsAbsolutePositions: items.map(
8351
8267
  (item) => this.getAbsolutePositionOf(item)
8352
8268
  ),
@@ -8364,12 +8280,9 @@ class SpineLayout extends DestroyableClass {
8364
8280
  layout() {
8365
8281
  this.layoutSubject.next(void 0);
8366
8282
  }
8367
- /**
8368
- * It's important to not use x,y since we need the absolute position of each element. Otherwise x,y would be relative to
8369
- * current window (viewport).
8370
- */
8371
8283
  getAbsolutePositionOf(spineItemOrIndex) {
8372
- const fallback = {
8284
+ var _a;
8285
+ return ((_a = this.spineItemsManager.get(spineItemOrIndex)) == null ? void 0 : _a.layoutPosition) || {
8373
8286
  left: 0,
8374
8287
  right: 0,
8375
8288
  top: 0,
@@ -8379,16 +8292,160 @@ class SpineLayout extends DestroyableClass {
8379
8292
  x: 0,
8380
8293
  y: 0
8381
8294
  };
8382
- const spineItem = this.spineItemsManager.get(spineItemOrIndex);
8383
- const indexOfItem = spineItem ? this.spineItemsManager.items.indexOf(spineItem) : -1;
8384
- const layoutInformation = this.itemLayoutInformation[indexOfItem];
8385
- return layoutInformation || fallback;
8386
8295
  }
8387
8296
  destroy() {
8388
8297
  super.destroy();
8389
8298
  this.layoutSubject.complete();
8390
8299
  }
8391
8300
  }
8301
+ class SpineItemLayout extends DestroyableClass {
8302
+ constructor(item, containerElement, context, hookManager, renderer) {
8303
+ super();
8304
+ this.item = item;
8305
+ this.containerElement = containerElement;
8306
+ this.context = context;
8307
+ this.hookManager = hookManager;
8308
+ this.renderer = renderer;
8309
+ this.layoutTriggerSubject = new Subject();
8310
+ this.lastLayout = null;
8311
+ this.applyDimsAfterLayout = ({
8312
+ blankPagePosition,
8313
+ minimumWidth
8314
+ }) => (stream) => {
8315
+ return stream.pipe(
8316
+ map((dims) => {
8317
+ var _a;
8318
+ const trustableLastLayout = isShallowEqual(
8319
+ (_a = this.lastLayout) == null ? void 0 : _a.pageSize,
8320
+ this.context.getPageSize()
8321
+ ) ? this.lastLayout : void 0;
8322
+ const { width: previousWidth, height: previousHeight } = trustableLastLayout ?? {};
8323
+ const { width = previousWidth, height = previousHeight } = dims ?? {};
8324
+ const { width: pageSizeWidth, height: pageSizeHeight } = this.context.getPageSize();
8325
+ const safeWidth = this.validateDimension(
8326
+ width ?? pageSizeWidth,
8327
+ pageSizeWidth,
8328
+ minimumWidth
8329
+ );
8330
+ const safeHeight = this.validateDimension(
8331
+ height ?? pageSizeHeight,
8332
+ pageSizeHeight,
8333
+ pageSizeHeight
8334
+ );
8335
+ this.lastLayout = {
8336
+ width: safeWidth,
8337
+ height: safeHeight,
8338
+ pageSize: this.context.getPageSize()
8339
+ };
8340
+ this.containerElement.style.width = `${safeWidth}px`;
8341
+ this.containerElement.style.height = `${safeHeight}px`;
8342
+ this.hookManager.execute(`item.onAfterLayout`, void 0, {
8343
+ blankPagePosition,
8344
+ item: this.item,
8345
+ minimumWidth
8346
+ });
8347
+ return { width: safeWidth, height: safeHeight };
8348
+ })
8349
+ );
8350
+ };
8351
+ this.layout = (params) => {
8352
+ const nextResult = deferNextResult(this.layout$.pipe(first$1()));
8353
+ this.layoutTriggerSubject.next(params);
8354
+ return nextResult();
8355
+ };
8356
+ this.adjustPositionOfElement = ({
8357
+ right,
8358
+ left,
8359
+ top
8360
+ }) => {
8361
+ if (right !== void 0) {
8362
+ this.containerElement.style.right = `${right}px`;
8363
+ } else {
8364
+ this.containerElement.style.removeProperty(`right`);
8365
+ }
8366
+ if (left !== void 0) {
8367
+ this.containerElement.style.left = `${left}px`;
8368
+ } else {
8369
+ this.containerElement.style.removeProperty(`left`);
8370
+ }
8371
+ if (top !== void 0) {
8372
+ this.containerElement.style.top = `${top}px`;
8373
+ } else {
8374
+ this.containerElement.style.removeProperty(`top`);
8375
+ }
8376
+ };
8377
+ this.layoutProcess$ = this.layoutTriggerSubject.pipe(
8378
+ switchMap((params) => {
8379
+ const { blankPagePosition, minimumWidth, spreadPosition } = params;
8380
+ this.hookManager.execute(`item.onBeforeLayout`, void 0, {
8381
+ blankPagePosition,
8382
+ item: this.item,
8383
+ minimumWidth
8384
+ });
8385
+ const rendererLayout$ = this.renderer.layout({
8386
+ blankPagePosition,
8387
+ minPageSpread: minimumWidth / this.context.getPageSize().width,
8388
+ minimumWidth,
8389
+ spreadPosition
8390
+ });
8391
+ return merge(
8392
+ of({ type: "start" }),
8393
+ rendererLayout$.pipe(
8394
+ this.applyDimsAfterLayout(params),
8395
+ map(
8396
+ (data) => ({
8397
+ type: "end",
8398
+ data
8399
+ })
8400
+ )
8401
+ )
8402
+ );
8403
+ }),
8404
+ share()
8405
+ );
8406
+ this.layout$ = this.layoutProcess$.pipe(
8407
+ filter((event) => event.type === `end`),
8408
+ map((event) => event.data),
8409
+ share()
8410
+ );
8411
+ }
8412
+ validateDimension(value, pageSize, minimum) {
8413
+ if (value <= 0) return minimum;
8414
+ const maxValue = Math.max(value, minimum);
8415
+ const multiplier = Math.ceil(maxValue / pageSize);
8416
+ const adjustedValue = multiplier * pageSize;
8417
+ return Math.max(adjustedValue, pageSize);
8418
+ }
8419
+ /**
8420
+ * Returns the absolute layout position relative to the parent element which
8421
+ * is supposedly and expectedly the spine element.
8422
+ *
8423
+ * @important
8424
+ *
8425
+ * This method is stable and does not consider scalings or transforms on the parents.
8426
+ *
8427
+ * It does assume and requires that:
8428
+ * - the navigator element and the spine element are direct parents.
8429
+ * - the spine items are correctly positioned in the DOM and with correct styles values.
8430
+ */
8431
+ get layoutPosition() {
8432
+ const left = Math.round(this.containerElement.offsetLeft * 10) / 10;
8433
+ const top = Math.round(this.containerElement.offsetTop * 10) / 10;
8434
+ const width = Math.round(this.containerElement.offsetWidth * 10) / 10;
8435
+ const height = Math.round(this.containerElement.offsetHeight * 10) / 10;
8436
+ const normalizedValues = {
8437
+ left,
8438
+ top,
8439
+ right: left + width,
8440
+ bottom: top + height,
8441
+ x: left,
8442
+ y: top,
8443
+ width,
8444
+ height
8445
+ };
8446
+ return normalizedValues;
8447
+ }
8448
+ }
8392
8449
  class DefaultRenderer extends DocumentRenderer {
8393
8450
  onUnload() {
8394
8451
  return EMPTY;
@@ -8419,28 +8476,6 @@ class SpineItem extends DestroyableClass {
8419
8476
  this.settings = settings;
8420
8477
  this.hookManager = hookManager;
8421
8478
  this.index = index;
8422
- this.layoutTriggerSubject = new Subject();
8423
- this.adjustPositionOfElement = ({
8424
- right,
8425
- left,
8426
- top
8427
- }) => {
8428
- if (right !== void 0) {
8429
- this.containerElement.style.right = `${right}px`;
8430
- } else {
8431
- this.containerElement.style.removeProperty(`right`);
8432
- }
8433
- if (left !== void 0) {
8434
- this.containerElement.style.left = `${left}px`;
8435
- } else {
8436
- this.containerElement.style.removeProperty(`left`);
8437
- }
8438
- if (top !== void 0) {
8439
- this.containerElement.style.top = `${top}px`;
8440
- } else {
8441
- this.containerElement.style.removeProperty(`top`);
8442
- }
8443
- };
8444
8479
  this.getBoundingRectOfElementFromSelector = (selector) => {
8445
8480
  var _a2, _b2, _c, _d;
8446
8481
  const frameElement = this.renderer.getDocumentFrame();
@@ -8451,28 +8486,12 @@ class SpineItem extends DestroyableClass {
8451
8486
  return (_d = (_c = frameElement.contentDocument) == null ? void 0 : _c.querySelector(selector)) == null ? void 0 : _d.getBoundingClientRect();
8452
8487
  }
8453
8488
  };
8454
- this.layout = (params) => {
8455
- const nextResult = deferNextResult(this.layout$.pipe(first()));
8456
- this.layoutTriggerSubject.next(params);
8457
- return nextResult();
8458
- };
8459
8489
  this.load = () => {
8460
8490
  this.renderer.load();
8461
8491
  };
8462
8492
  this.unload = () => {
8463
8493
  this.renderer.unload();
8464
8494
  };
8465
- this.getElementDimensions = () => {
8466
- const rect = this.containerElement.getBoundingClientRect();
8467
- const normalizedValues = {
8468
- ...rect,
8469
- // we want to round to first decimal because it's possible to have half pixel
8470
- // however browser engine can also gives back x.yyyy based on their precision
8471
- width: Math.round(rect.width * 10) / 10,
8472
- height: Math.round(rect.height * 10) / 10
8473
- };
8474
- return normalizedValues;
8475
- };
8476
8495
  this.destroy = () => {
8477
8496
  super.destroy();
8478
8497
  this.containerElement.remove();
@@ -8499,52 +8518,21 @@ class SpineItem extends DestroyableClass {
8499
8518
  resourcesHandler: this.resourcesHandler
8500
8519
  };
8501
8520
  this.renderer = rendererFactory ? rendererFactory(rendererParams) : new DefaultRenderer(rendererParams);
8502
- const layoutProcess$ = this.layoutTriggerSubject.pipe(
8503
- switchMap$1(({ blankPagePosition, minimumWidth, spreadPosition }) => {
8504
- this.hookManager.execute(`item.onBeforeLayout`, void 0, {
8505
- blankPagePosition,
8506
- item: this.item,
8507
- minimumWidth
8508
- });
8509
- const layout$ = this.renderer.layout({
8510
- blankPagePosition,
8511
- minPageSpread: minimumWidth / this.context.getPageSize().width,
8512
- minimumWidth,
8513
- spreadPosition
8514
- });
8515
- return merge(
8516
- of({ type: "start" }),
8517
- layout$.pipe(
8518
- map$1(({ height, width }) => {
8519
- this.containerElement.style.width = `${width}px`;
8520
- this.containerElement.style.height = `${height}px`;
8521
- this.hookManager.execute(`item.onAfterLayout`, void 0, {
8522
- blankPagePosition,
8523
- item: this.item,
8524
- minimumWidth
8525
- });
8526
- return {
8527
- type: "end",
8528
- data: { width, height }
8529
- };
8530
- })
8531
- )
8532
- );
8533
- }),
8534
- share$1()
8521
+ this.spineItemLayout = new SpineItemLayout(
8522
+ item,
8523
+ this.containerElement,
8524
+ context,
8525
+ hookManager,
8526
+ this.renderer
8535
8527
  );
8536
- this.isReady$ = layoutProcess$.pipe(
8528
+ this.isReady$ = this.spineItemLayout.layoutProcess$.pipe(
8537
8529
  withLatestFrom$1(this.renderer.isLoaded$),
8538
8530
  map$1(([event, loaded]) => !!(event.type === `end` && loaded)),
8539
8531
  startWith(false),
8540
8532
  distinctUntilChanged(),
8541
8533
  shareReplay({ refCount: true, bufferSize: 1 })
8542
8534
  );
8543
- this.layout$ = layoutProcess$.pipe(
8544
- filter$1((event) => event.type === `end`),
8545
- map$1((event) => event.data),
8546
- share$1()
8547
- );
8535
+ this.layout$ = this.spineItemLayout.layout$;
8548
8536
  this.needsLayout$ = merge(this.unloaded$, this.loaded$);
8549
8537
  merge(
8550
8538
  /**
@@ -8554,8 +8542,10 @@ class SpineItem extends DestroyableClass {
8554
8542
  * to layout changes may rely on the isReady value.
8555
8543
  */
8556
8544
  this.isReady$,
8557
- this.layout$
8545
+ this.spineItemLayout.layout$
8558
8546
  ).pipe(takeUntil$1(this.destroy$)).subscribe();
8547
+ this.layout = this.spineItemLayout.layout;
8548
+ this.adjustPositionOfElement = this.spineItemLayout.adjustPositionOfElement;
8559
8549
  }
8560
8550
  get element() {
8561
8551
  return this.containerElement;
@@ -8571,6 +8561,9 @@ class SpineItem extends DestroyableClass {
8571
8561
  get readingDirection() {
8572
8562
  return this.renderer.readingDirection;
8573
8563
  }
8564
+ get layoutPosition() {
8565
+ return this.spineItemLayout.layoutPosition;
8566
+ }
8574
8567
  get loaded$() {
8575
8568
  return this.renderer.state$.pipe(
8576
8569
  distinctUntilChanged(),