@prose-reader/core 1.201.0 → 1.203.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 (32) hide show
  1. package/dist/createReaderWithEnhancer.d.ts +10 -10
  2. package/dist/enhancers/{layoutEnhancer → layout}/types.d.ts +1 -0
  3. package/dist/enhancers/layout/viewportMode.d.ts +3 -0
  4. package/dist/enhancers/navigation/navigators/manualNavigator.d.ts +1 -1
  5. package/dist/enhancers/pagination/enhancer.d.ts +1 -1
  6. package/dist/enhancers/pagination/pagination.d.ts +1 -1
  7. package/dist/enhancers/pagination/progression.d.ts +1 -1
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +169 -96
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.umd.cjs +171 -97
  12. package/dist/index.umd.cjs.map +1 -1
  13. package/dist/navigation/InternalNavigator.d.ts +1 -1
  14. package/dist/navigation/Navigator.d.ts +4 -2
  15. package/dist/navigation/UserScrollNavigation.d.ts +18 -0
  16. package/dist/navigation/consolidation/mapUserNavigationToInternal.d.ts +1 -1
  17. package/dist/navigation/controllers/ScrollNavigationController.d.ts +1 -0
  18. package/dist/navigation/tests/utils.d.ts +0 -11
  19. package/dist/navigation/types.d.ts +11 -0
  20. package/dist/reader.d.ts +2 -2
  21. package/dist/settings/SettingsManagerOverload.d.ts +1 -0
  22. package/dist/spine/loader/SpineItemsLoader.d.ts +2 -1
  23. package/dist/spineItem/renderer/DocumentRenderer.d.ts +4 -1
  24. package/dist/utils/rxjs.d.ts +1 -0
  25. package/dist/viewport/Viewport.d.ts +5 -1
  26. package/package.json +3 -3
  27. package/dist/navigation/UserNavigator.d.ts +0 -29
  28. package/dist/enhancers/{layoutEnhancer → layout}/SettingsManager.d.ts +1 -1
  29. /package/dist/enhancers/{layoutEnhancer → layout}/createMovingSafePan$.d.ts +0 -0
  30. /package/dist/enhancers/{layoutEnhancer → layout}/fixReflowable.d.ts +0 -0
  31. /package/dist/enhancers/{layoutEnhancer → layout}/layoutEnhancer.d.ts +0 -0
  32. /package/dist/enhancers/{layoutEnhancer → layout}/layoutInfo.d.ts +0 -0
@@ -1,5 +1,5 @@
1
- export declare const createReaderWithEnhancers: (options: Partial<import('./settings/types').CoreInputSettings> & Partial<import('./enhancers/layoutEnhancer/types').InputSettings> & {
2
- theme?: import('./enhancers/theme').Theme;
1
+ export declare const createReaderWithEnhancers: (options: Partial<import('./settings/types').CoreInputSettings> & Partial<import('./enhancers/layout/types').InputSettings> & {
2
+ theme?: import('.').Theme;
3
3
  } & Partial<import('./enhancers/fonts/types').InputSettings> & {
4
4
  loadingElementCreate?: (options: {
5
5
  container: HTMLElement;
@@ -55,9 +55,9 @@ export declare const createReaderWithEnhancers: (options: Partial<import('./sett
55
55
  internalNavigator: import('./navigation/InternalNavigator').InternalNavigator;
56
56
  scrollNavigationController: import('./navigation/controllers/ScrollNavigationController').ScrollNavigationController;
57
57
  controlledNavigationController: import('./navigation/controllers/ControlledNavigationController').ControlledNavigationController;
58
- isLocked$: import('rxjs').Observable<boolean>;
58
+ locker: import('./navigation/Locker').Locker;
59
59
  viewportState$: import('rxjs').Observable<"free" | "busy">;
60
- navigate: (to: import('./navigation/UserNavigator').UserNavigationEntry) => void;
60
+ navigate: (to: import('./navigation/types').UserNavigationEntry) => void;
61
61
  lock(): () => void;
62
62
  navigationResolver: {
63
63
  getNavigationForUrl: (url: string | URL) => {
@@ -119,8 +119,8 @@ export declare const createReaderWithEnhancers: (options: Partial<import('./sett
119
119
  }>;
120
120
  destroy$: import('rxjs').Subject<void>;
121
121
  };
122
- }, "settings"> & import('./enhancers/layoutEnhancer/layoutEnhancer').LayoutEnhancerOutput & {
123
- settings: import('./settings/SettingsInterface').SettingsInterface<import('./settings/types').CoreInputSettings & import('./enhancers/layoutEnhancer/types').InputSettings, import('./enhancers/layoutEnhancer/types').InputSettings & import('./settings/types').CoreInputSettings & import('./settings/types').ComputedCoreSettings>;
122
+ }, "settings"> & import('./enhancers/layout/layoutEnhancer').LayoutEnhancerOutput & {
123
+ settings: import('./settings/SettingsInterface').SettingsInterface<import('./settings/types').CoreInputSettings & import('./enhancers/layout/types').InputSettings, import('./enhancers/layout/types').InputSettings & import('./settings/types').CoreInputSettings & import('./settings/types').ComputedCoreSettings>;
124
124
  }, "pagination"> & {
125
125
  pagination: Omit<{
126
126
  getState: () => import('./pagination/Pagination').PaginationInfo;
@@ -133,10 +133,10 @@ export declare const createReaderWithEnhancers: (options: Partial<import('./sett
133
133
  };
134
134
  } & {
135
135
  theme: {
136
- set: (theme: import('./enhancers/theme').Theme) => void;
137
- get: () => import('./enhancers/theme').Theme;
136
+ set: (theme: import('.').Theme) => void;
137
+ get: () => import('.').Theme;
138
138
  $: {
139
- theme$: import('rxjs').Observable<import('./enhancers/theme').Theme>;
139
+ theme$: import('rxjs').Observable<import('.').Theme>;
140
140
  };
141
141
  };
142
142
  } & {
@@ -146,7 +146,7 @@ export declare const createReaderWithEnhancers: (options: Partial<import('./sett
146
146
  isOrIsWithinValidLink: (target: Event[`target`]) => boolean;
147
147
  };
148
148
  }, "settings"> & {
149
- settings: import('./settings/SettingsInterface').SettingsInterface<import('./settings/types').CoreInputSettings & import('./enhancers/layoutEnhancer/types').InputSettings & import('./enhancers/fonts/types').InputSettings, import('./enhancers/fonts/types').InputSettings & import('./enhancers/layoutEnhancer/types').InputSettings & import('./settings/types').CoreInputSettings & import('./settings/types').ComputedCoreSettings>;
149
+ settings: import('./settings/SettingsInterface').SettingsInterface<import('./settings/types').CoreInputSettings & import('./enhancers/layout/types').InputSettings & import('./enhancers/fonts/types').InputSettings, import('./enhancers/fonts/types').InputSettings & import('./enhancers/layout/types').InputSettings & import('./settings/types').CoreInputSettings & import('./settings/types').ComputedCoreSettings>;
150
150
  } & {
151
151
  loading: {
152
152
  $: {
@@ -3,5 +3,6 @@ export type InputSettings = {
3
3
  pageVerticalMargin: number;
4
4
  layoutAutoResize: `container` | false;
5
5
  layoutLayerTransition: boolean;
6
+ viewportMode: `normal` | `thumbnails`;
6
7
  };
7
8
  export type OutputSettings = InputSettings;
@@ -0,0 +1,3 @@
1
+ import { Observable } from 'rxjs';
2
+ import { Reader } from '../../reader';
3
+ export declare const createViewportModeHandler: (reader: Reader, viewportMode$: Observable<`normal` | `thumbnails`>) => Observable<"normal" | "thumbnails">;
@@ -1,4 +1,4 @@
1
- import { UserNavigationEntry } from '../../../navigation/UserNavigator';
1
+ import { UserNavigationEntry } from '../../../navigation/types';
2
2
  import { Reader } from '../../../reader';
3
3
  import { SpinePosition } from '../../../spine/types';
4
4
  export declare class ManualNavigator {
@@ -1,6 +1,6 @@
1
1
  import { Observable } from 'rxjs';
2
2
  import { PaginationInfo } from '../../pagination/Pagination';
3
- import { LayoutEnhancerOutput } from '../layoutEnhancer/layoutEnhancer';
3
+ import { LayoutEnhancerOutput } from '../layout/layoutEnhancer';
4
4
  import { EnhancerOutput, RootEnhancer } from '../types/enhancer';
5
5
  import { ConsolidatedResource, LocatableResource } from './locate';
6
6
  import { ExtraPaginationInfo } from './types';
@@ -1,7 +1,7 @@
1
1
  import { Observable, ObservedValueOf } from 'rxjs';
2
2
  import { PaginationInfo } from '../../pagination/Pagination';
3
3
  import { Reader } from '../../reader';
4
- import { LayoutEnhancerOutput } from '../layoutEnhancer/layoutEnhancer';
4
+ import { LayoutEnhancerOutput } from '../layout/layoutEnhancer';
5
5
  import { trackChapterInfo } from './chapters';
6
6
  import { EnhancerPaginationInto, ExtraPaginationInfo } from './types';
7
7
  export declare const mapPaginationInfoToExtendedInfo: (reader: Reader, paginationInfo: PaginationInfo, chaptersInfo: ObservedValueOf<ReturnType<typeof trackChapterInfo>>, percentageEstimateOfBook: number) => Observable<Omit<ExtraPaginationInfo, "beginAbsolutePageIndex" | "endAbsolutePageIndex" | "beginAbsolutePageIndex" | "numberOfTotalPages">>;
@@ -1,6 +1,6 @@
1
1
  import { Reader } from '../../reader';
2
2
  import { SpineItem } from '../../spineItem/SpineItem';
3
- import { LayoutEnhancerOutput } from '../layoutEnhancer/layoutEnhancer';
3
+ import { LayoutEnhancerOutput } from '../layout/layoutEnhancer';
4
4
  export declare const getPercentageEstimate: (reader: Reader & LayoutEnhancerOutput, currentSpineIndex: number, pageIndex: number, currentPosition: {
5
5
  x: number;
6
6
  y: number;
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import { createReaderWithEnhancers as createReader } from './createReaderWithEnh
2
2
  export type { Manifest } from '@prose-reader/shared';
3
3
  export { DocumentRenderer } from './spineItem/renderer/DocumentRenderer';
4
4
  export { ResourceHandler } from './spineItem/resources/ResourceHandler';
5
+ export type { Theme } from './enhancers/theme';
5
6
  export { HookManager } from './hooks/HookManager';
6
7
  export { SettingsManager } from './settings/SettingsManager';
7
8
  export type Reader = ReturnType<typeof createReader>;
package/dist/index.js CHANGED
@@ -2,7 +2,6 @@ import { switchMap, of, fromEvent, take, map, from, takeUntil, Observable, defer
2
2
  import { switchMap as switchMap$1, first, map as map$1, distinctUntilChanged, startWith, shareReplay, 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 { isShallowEqual, shallowMergeIfDefined, getParentPath, parseContentType, detectMimeTypeFromName, arrayEqual } from "@prose-reader/shared";
4
4
  import { isShallowEqual as isShallowEqual2 } from "@prose-reader/shared";
5
- import { isDefined as isDefined$1 } from "reactjrx";
6
5
  const getAttributeValueFromString = (string, key) => {
7
6
  const regExp = new RegExp(`${key}\\s*=\\s*([0-9.]+)`, `i`);
8
7
  const match = string.match(regExp) || [];
@@ -678,6 +677,17 @@ const observeMutation = (target, options) => {
678
677
  return () => observer.disconnect();
679
678
  });
680
679
  };
680
+ function observeIntersection(element, options) {
681
+ return new Observable((observer) => {
682
+ const intersectionObserver = new IntersectionObserver((entries) => {
683
+ observer.next(entries);
684
+ }, options);
685
+ intersectionObserver.observe(element);
686
+ return () => {
687
+ intersectionObserver.disconnect();
688
+ };
689
+ });
690
+ }
681
691
  class SettingsManagerOverload {
682
692
  constructor(initialSettings, settingsManager) {
683
693
  this.settingsManager = settingsManager;
@@ -732,9 +742,12 @@ class SettingsManagerOverload {
732
742
  ...this.outputSettings
733
743
  };
734
744
  }
735
- watch(keys) {
745
+ watch(keyOrKeys) {
746
+ if (Array.isArray(keyOrKeys)) {
747
+ return this.values$.pipe(watchKeys(keyOrKeys));
748
+ }
736
749
  return this.values$.pipe(
737
- mapKeysTo(keys),
750
+ map$1((result) => result[keyOrKeys]),
738
751
  distinctUntilChanged(isShallowEqual)
739
752
  );
740
753
  }
@@ -932,7 +945,7 @@ class DestroyableClass {
932
945
  this.destroySubject.complete();
933
946
  }
934
947
  }
935
- class DocumentRenderer extends DestroyableClass {
948
+ const _DocumentRenderer = class _DocumentRenderer extends DestroyableClass {
936
949
  constructor(params) {
937
950
  super();
938
951
  this.triggerSubject = new Subject();
@@ -1022,6 +1035,12 @@ class DocumentRenderer extends DestroyableClass {
1022
1035
  );
1023
1036
  merge(unload$).pipe(takeUntil(this.destroy$)).subscribe();
1024
1037
  }
1038
+ setDocumentContainer(element) {
1039
+ this._documentContainer = element;
1040
+ this._documentContainer.classList.add(
1041
+ _DocumentRenderer.DOCUMENT_CONTAINER_CLASS_NAME
1042
+ );
1043
+ }
1025
1044
  attach() {
1026
1045
  if (this.documentContainer) {
1027
1046
  this.containerElement.appendChild(this.documentContainer);
@@ -1029,8 +1048,8 @@ class DocumentRenderer extends DestroyableClass {
1029
1048
  }
1030
1049
  detach() {
1031
1050
  var _a;
1032
- (_a = this.documentContainer) == null ? void 0 : _a.remove();
1033
- this.documentContainer = void 0;
1051
+ (_a = this._documentContainer) == null ? void 0 : _a.remove();
1052
+ this._documentContainer = void 0;
1034
1053
  }
1035
1054
  get state$() {
1036
1055
  return this.stateSubject;
@@ -1071,8 +1090,12 @@ class DocumentRenderer extends DestroyableClass {
1071
1090
  return defer(() => this.onLayout(params)).pipe();
1072
1091
  }
1073
1092
  destroy() {
1074
- super.destroy();
1093
+ this.unload();
1075
1094
  this.stateSubject.complete();
1095
+ super.destroy();
1096
+ }
1097
+ get documentContainer() {
1098
+ return this._documentContainer;
1076
1099
  }
1077
1100
  get writingMode() {
1078
1101
  return void 0;
@@ -1091,7 +1114,9 @@ class DocumentRenderer extends DestroyableClass {
1091
1114
  }
1092
1115
  return ((_a = this.context.manifest) == null ? void 0 : _a.renditionLayout) ?? "reflowable";
1093
1116
  }
1094
- }
1117
+ };
1118
+ _DocumentRenderer.DOCUMENT_CONTAINER_CLASS_NAME = `prose-reader-document-container`;
1119
+ let DocumentRenderer = _DocumentRenderer;
1095
1120
  const defaultGetResource = (item) => new URL(item.href);
1096
1121
  class ResourceHandler {
1097
1122
  constructor(item, settings) {
@@ -1884,7 +1909,7 @@ class HtmlRenderer extends DocumentRenderer {
1884
1909
  }
1885
1910
  onCreateDocument() {
1886
1911
  const frameElement = createFrameElement();
1887
- this.documentContainer = frameElement;
1912
+ this.setDocumentContainer(frameElement);
1888
1913
  return of(frameElement);
1889
1914
  }
1890
1915
  onLoadDocument() {
@@ -2054,6 +2079,7 @@ let SettingsManager$1 = class SettingsManager2 extends SettingsManagerOverload {
2054
2079
  pageHorizontalMargin,
2055
2080
  pageVerticalMargin,
2056
2081
  layoutLayerTransition,
2082
+ viewportMode,
2057
2083
  ...rest
2058
2084
  } = settings;
2059
2085
  return rest;
@@ -2063,7 +2089,8 @@ let SettingsManager$1 = class SettingsManager2 extends SettingsManagerOverload {
2063
2089
  layoutAutoResize: "container",
2064
2090
  pageHorizontalMargin: 24,
2065
2091
  pageVerticalMargin: 24,
2066
- layoutLayerTransition: true
2092
+ layoutLayerTransition: true,
2093
+ viewportMode: "normal"
2067
2094
  };
2068
2095
  }
2069
2096
  };
@@ -2241,6 +2268,24 @@ const createLayoutInfo = (reader) => {
2241
2268
  info$.pipe(takeUntil(reader.$.destroy$)).subscribe();
2242
2269
  return { layout$, info$ };
2243
2270
  };
2271
+ const createViewportModeHandler = (reader, viewportMode$) => {
2272
+ return viewportMode$.pipe(
2273
+ tap$1((viewportMode) => {
2274
+ reader.viewport.value.element.style.transition = `transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275)`;
2275
+ if (reader.settings.values.computedPageTurnMode === "scrollable") {
2276
+ reader.viewport.value.element.style.transformOrigin = `top`;
2277
+ } else {
2278
+ reader.viewport.value.element.style.transformOrigin = `center`;
2279
+ }
2280
+ if (viewportMode === `thumbnails`) {
2281
+ reader.viewport.value.element.style.transform = `scale(0.5)`;
2282
+ } else {
2283
+ reader.viewport.value.element.style.transform = `scale(1)`;
2284
+ }
2285
+ reader.layout();
2286
+ })
2287
+ );
2288
+ };
2244
2289
  const layoutEnhancer = (next) => (options) => {
2245
2290
  const {
2246
2291
  pageHorizontalMargin,
@@ -2376,11 +2421,16 @@ const layoutEnhancer = (next) => (options) => {
2376
2421
  })
2377
2422
  );
2378
2423
  const { layout$, info$ } = createLayoutInfo(reader);
2424
+ const viewportModeHandler$ = createViewportModeHandler(
2425
+ reader,
2426
+ settingsManager.watch(`viewportMode`)
2427
+ );
2379
2428
  merge(
2380
2429
  updateSpineItemClassName$,
2381
2430
  revealItemOnReady$,
2382
2431
  movingSafePan$,
2383
- layoutOnContainerResize$
2432
+ layoutOnContainerResize$,
2433
+ viewportModeHandler$
2384
2434
  ).pipe(takeUntil$1(reader.$.destroy$)).subscribe();
2385
2435
  return {
2386
2436
  ...reader,
@@ -2526,7 +2576,7 @@ class ImageRenderer extends DocumentRenderer {
2526
2576
  const imgElement = this.containerElement.ownerDocument.createElement(`img`);
2527
2577
  return from(this.resourcesHandler.getResource()).pipe(
2528
2578
  switchMap((responseOrUrl) => {
2529
- this.documentContainer = imgElement;
2579
+ this.setDocumentContainer(imgElement);
2530
2580
  imgElement.style.objectFit = `contain`;
2531
2581
  imgElement.style.userSelect = `none`;
2532
2582
  if (responseOrUrl instanceof URL) {
@@ -2699,7 +2749,7 @@ const handleLinksNavigation = (reader, manualNavigator) => {
2699
2749
  })
2700
2750
  );
2701
2751
  };
2702
- const report$4 = Report.namespace(`navigation`);
2752
+ const report$3 = Report.namespace(`navigation`);
2703
2753
  class SpineItemPosition {
2704
2754
  constructor(position) {
2705
2755
  this.__symbol = Symbol(`SpineItemPosition`);
@@ -3099,7 +3149,7 @@ class ManualNavigator {
3099
3149
  pageIndex,
3100
3150
  spineItemId
3101
3151
  });
3102
- report$4.debug(`.goToPageOfSpineItem()`, {
3152
+ report$3.debug(`.goToPageOfSpineItem()`, {
3103
3153
  pageIndex,
3104
3154
  spineItemId,
3105
3155
  ...rest,
@@ -3117,7 +3167,7 @@ class ManualNavigator {
3117
3167
  const foundInfo = this.reader.spine.locator.getSpineInfoFromAbsolutePageIndex({
3118
3168
  absolutePageIndex
3119
3169
  });
3120
- report$4.debug(`.goToAbsolutePageIndex()`, {
3170
+ report$3.debug(`.goToAbsolutePageIndex()`, {
3121
3171
  absolutePageIndex,
3122
3172
  ...rest,
3123
3173
  foundInfo
@@ -3160,7 +3210,7 @@ class PanNavigator {
3160
3210
  }
3161
3211
  let navigation = this.reader.navigation.getNavigation().position;
3162
3212
  if (delta) {
3163
- const viewportScale = this.reader.viewport.absoluteViewport.width / this.reader.viewport.absoluteViewport.width;
3213
+ const viewportScale = this.reader.viewport.absoluteViewport.width / this.reader.viewport.relativeViewport.width;
3164
3214
  const correctedX = Math.floor(delta.x) - (((_b = this.lastDelta) == null ? void 0 : _b.x) || 0);
3165
3215
  const correctedY = Math.floor(delta.y) - (((_c = this.lastDelta) == null ? void 0 : _c.y) || 0);
3166
3216
  const x = Math.floor(
@@ -3286,7 +3336,7 @@ const navigationEnhancer = (next) => (options) => {
3286
3336
  }
3287
3337
  };
3288
3338
  };
3289
- const NAMESPACE$5 = `paginationEnhancer`;
3339
+ const NAMESPACE$4 = `paginationEnhancer`;
3290
3340
  const consolidate = (item, reader) => {
3291
3341
  var _a;
3292
3342
  let itemPageIndex = (_a = item.meta) == null ? void 0 : _a.itemPageIndex;
@@ -3641,7 +3691,7 @@ const trackPaginationInfo = (reader) => {
3641
3691
  );
3642
3692
  return { paginationInfo$, getPaginationInfo: () => currentValue.value };
3643
3693
  };
3644
- Report.namespace(NAMESPACE$5);
3694
+ Report.namespace(NAMESPACE$4);
3645
3695
  const paginationEnhancer = (next) => (options) => {
3646
3696
  const reader = next(options);
3647
3697
  const { paginationInfo$, getPaginationInfo } = trackPaginationInfo(reader);
@@ -6158,8 +6208,8 @@ const withRestoredPosition = ({
6158
6208
  );
6159
6209
  })
6160
6210
  );
6161
- const NAMESPACE$4 = `navigation/InternalNavigator`;
6162
- const report$3 = Report.namespace(NAMESPACE$4);
6211
+ const NAMESPACE$3 = `navigation/InternalNavigator`;
6212
+ const report$2 = Report.namespace(NAMESPACE$3);
6163
6213
  class InternalNavigator extends DestroyableClass {
6164
6214
  constructor(settings, context, userNavigation$, viewportController, scrollNavigationController, navigationResolver, spine, isUserLocked$) {
6165
6215
  super();
@@ -6361,7 +6411,7 @@ class InternalNavigator extends DestroyableClass {
6361
6411
  );
6362
6412
  const notifyNavigationUpdate = (stream) => stream.pipe(
6363
6413
  tap$1(([currentNavigation, previousNavigation]) => {
6364
- report$3.info(
6414
+ report$2.info(
6365
6415
  `navigation updated from ${currentNavigation.meta.triggeredBy} of type ${currentNavigation.type}`,
6366
6416
  {
6367
6417
  previousNavigation,
@@ -6437,40 +6487,23 @@ const getScaledDownPosition = ({
6437
6487
  return scaledDownPosition;
6438
6488
  };
6439
6489
  const SCROLL_FINISHED_DEBOUNCE_TIMEOUT = 500;
6440
- const NAMESPACE$3 = `navigation/UserNavigator`;
6441
- const report$2 = Report.namespace(NAMESPACE$3);
6442
- class UserNavigator extends DestroyableClass {
6443
- constructor(settings, scrollNavigatorElement$, context, scrollHappeningFromBrowser$, spine) {
6490
+ class UserScrollNavigation extends DestroyableClass {
6491
+ constructor(settings, context, spine, scrollNavigationController, locker) {
6444
6492
  super();
6445
6493
  this.settings = settings;
6446
- this.scrollNavigatorElement$ = scrollNavigatorElement$;
6447
6494
  this.context = context;
6448
- this.scrollHappeningFromBrowser$ = scrollHappeningFromBrowser$;
6449
6495
  this.spine = spine;
6496
+ this.scrollNavigationController = scrollNavigationController;
6497
+ this.locker = locker;
6450
6498
  this.navigationSubject = new Subject();
6451
- this.locker = new Locker();
6452
6499
  this.navigation$ = this.navigationSubject.asObservable();
6453
- const userScroll$ = scrollNavigatorElement$.pipe(
6454
- filter(isDefined$1),
6455
- switchMap(
6456
- (element) => settings.watch(["computedPageTurnMode"]).pipe(
6457
- switchMap(
6458
- ({ computedPageTurnMode }) => computedPageTurnMode === "controlled" ? NEVER : fromEvent(element, `scroll`).pipe(
6459
- withLatestFrom(scrollHappeningFromBrowser$),
6460
- filter(
6461
- ([, shouldAvoidScrollEvent]) => !shouldAvoidScrollEvent
6462
- ),
6463
- map(([event]) => event)
6464
- )
6465
- )
6466
- )
6467
- ),
6468
- share()
6469
- );
6470
- const navigateOnScroll$ = userScroll$.pipe(
6500
+ const navigateOnScroll$ = this.scrollNavigationController.userScroll$.pipe(
6471
6501
  exhaustMap((event) => {
6472
6502
  const unlock = this.locker.lock();
6473
- return merge(userScroll$, of(event)).pipe(
6503
+ return merge(
6504
+ this.scrollNavigationController.userScroll$,
6505
+ of(event)
6506
+ ).pipe(
6474
6507
  debounceTime$1(
6475
6508
  SCROLL_FINISHED_DEBOUNCE_TIMEOUT,
6476
6509
  animationFrameScheduler
@@ -6486,7 +6519,7 @@ class UserNavigator extends DestroyableClass {
6486
6519
  }),
6487
6520
  spineElement: this.spine.element
6488
6521
  });
6489
- this.navigate({
6522
+ this.navigationSubject.next({
6490
6523
  animation: false,
6491
6524
  type: "scroll",
6492
6525
  position: scaledDownPosition
@@ -6500,15 +6533,6 @@ class UserNavigator extends DestroyableClass {
6500
6533
  );
6501
6534
  merge(navigateOnScroll$).pipe(takeUntil(this.destroy$)).subscribe();
6502
6535
  }
6503
- /**
6504
- * Remember that this navigation is not trustable.
6505
- *
6506
- * It needs to be verified and adjusted if necessary before becoming internal.
6507
- */
6508
- navigate(to) {
6509
- report$2.info(`.navigate`, to);
6510
- this.navigationSubject.next(to);
6511
- }
6512
6536
  }
6513
6537
  const spinePositionToTranslation = (position) => {
6514
6538
  return {
@@ -6773,6 +6797,46 @@ class ScrollNavigationController extends ReactiveEntity {
6773
6797
  switchMap(() => merge(of(true), of(false))),
6774
6798
  shareReplay$1(1)
6775
6799
  );
6800
+ const isSpineScrolling$ = merge(
6801
+ spine.element$.pipe(switchMap((element) => observeResize(element))),
6802
+ spine.element$.pipe(switchMap((element) => fromEvent(element, "scroll"))),
6803
+ spine.spineItemsObserver.itemResize$
6804
+ ).pipe(
6805
+ switchMap(
6806
+ () => timer(10).pipe(
6807
+ map(() => false),
6808
+ startWith$1(true)
6809
+ )
6810
+ ),
6811
+ distinctUntilChanged$1(),
6812
+ startWith$1(false)
6813
+ );
6814
+ const scrollHappeningFromBrowser$ = combineLatest([
6815
+ isSpineScrolling$,
6816
+ this.isScrolling$
6817
+ ]).pipe(
6818
+ map(
6819
+ ([spineScrolling, viewportScrolling]) => spineScrolling || viewportScrolling
6820
+ ),
6821
+ shareReplay$1(1)
6822
+ );
6823
+ this.userScroll$ = this.watch("element").pipe(
6824
+ filter(isDefined),
6825
+ switchMap(
6826
+ (element) => settings.watch(["computedPageTurnMode"]).pipe(
6827
+ switchMap(
6828
+ ({ computedPageTurnMode }) => computedPageTurnMode === "controlled" ? NEVER : fromEvent(element, `scroll`).pipe(
6829
+ withLatestFrom(scrollHappeningFromBrowser$),
6830
+ filter(
6831
+ ([, shouldAvoidScrollEvent]) => !shouldAvoidScrollEvent
6832
+ ),
6833
+ map(([event]) => event)
6834
+ )
6835
+ )
6836
+ )
6837
+ ),
6838
+ share()
6839
+ );
6776
6840
  merge(elementCreation$, toggleElementDisplay$, navigate$).pipe(takeUntil(this.destroy$)).subscribe();
6777
6841
  }
6778
6842
  navigate(navigation) {
@@ -7416,6 +7480,8 @@ const createNavigator = ({
7416
7480
  settings,
7417
7481
  viewport
7418
7482
  }) => {
7483
+ const userExplicitNavigationSubject = new Subject();
7484
+ const locker = new Locker();
7419
7485
  const navigationResolver = createNavigationResolver({
7420
7486
  context,
7421
7487
  settings,
@@ -7437,58 +7503,42 @@ const createNavigator = ({
7437
7503
  spine,
7438
7504
  context
7439
7505
  );
7440
- const isSpineScrolling$ = merge(
7441
- spine.element$.pipe(switchMap$1((element) => observeResize(element))),
7442
- spine.element$.pipe(switchMap$1((element) => fromEvent(element, "scroll"))),
7443
- spine.spineItemsObserver.itemResize$
7444
- ).pipe(
7445
- switchMap$1(
7446
- () => timer(10).pipe(
7447
- map$1(() => false),
7448
- startWith(true)
7449
- )
7450
- ),
7451
- distinctUntilChanged(),
7452
- startWith(false)
7453
- );
7454
- const scrollHappeningFromBrowser$ = combineLatest([
7455
- isSpineScrolling$,
7456
- scrollNavigationController.isScrolling$
7457
- ]).pipe(
7458
- map$1(
7459
- ([spineScrolling, viewportScrolling]) => spineScrolling || viewportScrolling
7460
- ),
7461
- shareReplay(1)
7462
- );
7463
- const userNavigator = new UserNavigator(
7506
+ const userScrollNavigation = new UserScrollNavigation(
7464
7507
  settings,
7465
- scrollNavigationController.watch("element"),
7466
7508
  context,
7467
- scrollHappeningFromBrowser$,
7468
- spine
7509
+ spine,
7510
+ scrollNavigationController,
7511
+ locker
7512
+ );
7513
+ const userNavigation$ = merge(
7514
+ userExplicitNavigationSubject,
7515
+ userScrollNavigation.navigation$
7469
7516
  );
7470
7517
  const internalNavigator = new InternalNavigator(
7471
7518
  settings,
7472
7519
  context,
7473
- userNavigator.navigation$,
7520
+ userNavigation$,
7474
7521
  controlledNavigationController,
7475
7522
  scrollNavigationController,
7476
7523
  navigationResolver,
7477
7524
  spine,
7478
- userNavigator.locker.isLocked$
7525
+ locker.isLocked$
7479
7526
  );
7480
7527
  const viewportState$ = combineLatest([
7481
7528
  controlledNavigationController.isNavigating$,
7482
7529
  scrollNavigationController.isNavigating$,
7483
- userNavigator.locker.isLocked$,
7530
+ locker.isLocked$,
7484
7531
  internalNavigator.locker.isLocked$
7485
7532
  ]).pipe(
7486
7533
  map$1((states) => states.some((isLocked) => isLocked) ? `busy` : `free`),
7487
7534
  distinctUntilChanged(),
7488
7535
  shareReplay(1)
7489
7536
  );
7537
+ const navigate = (to) => {
7538
+ userExplicitNavigationSubject.next(to);
7539
+ };
7490
7540
  const destroy = () => {
7491
- userNavigator.destroy();
7541
+ userScrollNavigation.destroy();
7492
7542
  controlledNavigationController.destroy();
7493
7543
  internalNavigator.destroy();
7494
7544
  };
@@ -7498,11 +7548,11 @@ const createNavigator = ({
7498
7548
  internalNavigator,
7499
7549
  scrollNavigationController,
7500
7550
  controlledNavigationController,
7501
- isLocked$: userNavigator.locker.isLocked$,
7551
+ locker,
7502
7552
  viewportState$,
7503
- navigate: userNavigator.navigate.bind(userNavigator),
7553
+ navigate,
7504
7554
  lock() {
7505
- return userNavigator.locker.lock();
7555
+ return locker.lock();
7506
7556
  },
7507
7557
  navigationResolver,
7508
7558
  navigation$: internalNavigator.navigation$
@@ -8369,11 +8419,16 @@ class SpineItemsLoader extends DestroyableClass {
8369
8419
  loadSpineItems$.pipe(takeUntil(this.destroy$)).subscribe();
8370
8420
  }
8371
8421
  forceOpen(spineItems) {
8372
- this.forcedOpenSubject.next([...this.forcedOpenSubject.value, spineItems]);
8422
+ const indexes = spineItems.map(
8423
+ (item) => typeof item === "number" ? item : item.index
8424
+ );
8425
+ this.forcedOpenSubject.next([...this.forcedOpenSubject.value, indexes]);
8373
8426
  return () => {
8374
8427
  if (this.isDestroyed) return;
8375
8428
  this.forcedOpenSubject.next(
8376
- this.forcedOpenSubject.value.filter((item) => item !== spineItems)
8429
+ this.forcedOpenSubject.value.filter(
8430
+ (arrayOfIndexes) => arrayOfIndexes !== indexes
8431
+ )
8377
8432
  );
8378
8433
  };
8379
8434
  }
@@ -8955,11 +9010,23 @@ class Viewport extends ReactiveEntity {
8955
9010
  `;
8956
9011
  element.className = `${HTML_PREFIX$1}-viewport`;
8957
9012
  super({
8958
- element
9013
+ element,
9014
+ pageSize: {
9015
+ width: 1,
9016
+ height: 1
9017
+ }
8959
9018
  });
8960
9019
  this.context = context;
9020
+ const updatePageSize$ = this.context.watch("visibleAreaRect").pipe(
9021
+ tap$1(() => {
9022
+ this.update({
9023
+ pageSize: this.calculatePageSize()
9024
+ });
9025
+ })
9026
+ );
9027
+ merge(updatePageSize$).pipe(takeUntil(this.destroy$)).subscribe();
8961
9028
  }
8962
- getPageSize() {
9029
+ calculatePageSize() {
8963
9030
  const absoluteViewport = this.absoluteViewport;
8964
9031
  const { isUsingSpreadMode: isUsingSpreadMode2 } = this.context.state;
8965
9032
  return {
@@ -8978,6 +9045,9 @@ class Viewport extends ReactiveEntity {
8978
9045
  * @important
8979
9046
  *
8980
9047
  * Contains long floating values.
9048
+ *
9049
+ * @todo take position of translate into consideration in something
9050
+ * like relativeViewportPosition or even better a ViewportSlicePosition
8981
9051
  */
8982
9052
  get relativeViewport() {
8983
9053
  const absoluteViewport = this.absoluteViewport;
@@ -9038,7 +9108,9 @@ const createReader = (inputSettings) => {
9038
9108
  );
9039
9109
  navigator2.viewportState$.subscribe(context.bridgeEvent.viewportStateSubject);
9040
9110
  navigator2.navigation$.subscribe(context.bridgeEvent.navigationSubject);
9041
- navigator2.isLocked$.subscribe(context.bridgeEvent.navigationIsLockedSubject);
9111
+ navigator2.locker.isLocked$.subscribe(
9112
+ context.bridgeEvent.navigationIsLockedSubject
9113
+ );
9042
9114
  pagination.state$.subscribe(context.bridgeEvent.paginationSubject);
9043
9115
  const layout = () => {
9044
9116
  var _a;
@@ -9243,6 +9315,7 @@ export {
9243
9315
  isHtmlTagElement,
9244
9316
  isShallowEqual2 as isShallowEqual,
9245
9317
  mapKeysTo,
9318
+ observeIntersection,
9246
9319
  observeMutation,
9247
9320
  observeResize,
9248
9321
  removeCSS,