@prose-reader/core 1.133.0 → 1.135.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,6 +1,6 @@
1
- import { takeUntil, Subject, combineLatest, switchMap, fromEvent, take, map as map$1, from, of, merge, EMPTY, withLatestFrom, NEVER, Observable, scheduled, animationFrameScheduler, defer, distinctUntilChanged as distinctUntilChanged$1, tap as tap$1, throttleTime, finalize, startWith as startWith$1, debounceTime as debounceTime$1, BehaviorSubject, combineLatestWith, shareReplay as shareReplay$1, switchScan, forkJoin, scan, ReplaySubject, filter as filter$1, share, mergeMap, delay, identity, timer, skip as skip$1, exhaustMap, first as first$1, lastValueFrom, endWith, catchError, reduce, concatMap } from "rxjs";
2
- import { startWith, map, shareReplay, tap, pairwise, switchMap as switchMap$1, take as take$1, distinctUntilChanged, takeUntil as takeUntil$1, first, filter, debounceTime, skip, withLatestFrom as withLatestFrom$1, share as share$1, mergeMap as mergeMap$1, catchError as catchError$1 } from "rxjs/operators";
3
- import { shallowMergeIfDefined, isShallowEqual, detectMimeTypeFromName, parseContentType, getParentPath } from "@prose-reader/shared";
1
+ import { takeUntil, Observable, of, defer, Subject, combineLatest, switchMap as switchMap$1, fromEvent, take, map as map$1, from, merge, EMPTY, withLatestFrom, NEVER, scheduled, animationFrameScheduler, distinctUntilChanged as distinctUntilChanged$1, tap as tap$1, throttleTime, finalize, startWith as startWith$1, debounceTime as debounceTime$1, BehaviorSubject, combineLatestWith, shareReplay as shareReplay$1, switchScan, forkJoin, ReplaySubject, filter as filter$1, share, mergeMap, delay, identity, timer, skip as skip$1, exhaustMap, first as first$1, lastValueFrom, endWith, catchError, reduce, concatMap } from "rxjs";
2
+ import { map, switchMap, first, startWith, shareReplay, distinctUntilChanged, tap, pairwise, take as take$1, takeUntil as takeUntil$1, filter, debounceTime, skip, withLatestFrom as withLatestFrom$1, share as share$1, mergeMap as mergeMap$1, catchError as catchError$1 } from "rxjs/operators";
3
+ import { shallowMergeIfDefined, isShallowEqual, detectMimeTypeFromName, arrayEqual, parseContentType, getParentPath } from "@prose-reader/shared";
4
4
  import { isShallowEqual as isShallowEqual2 } from "@prose-reader/shared";
5
5
  const chromeEnhancer = (next) => (options) => {
6
6
  const reader = next(options);
@@ -13,14 +13,82 @@ const chromeEnhancer = (next) => (options) => {
13
13
  };
14
14
  containerElement.addEventListener(`scroll`, onScroll);
15
15
  });
16
- reader.hookManager.register(`item.onDocumentLoad`, ({ layers }) => {
17
- var _a, _b;
18
- const frame = (_a = layers[0]) == null ? void 0 : _a.element;
19
- if (!(frame instanceof HTMLIFrameElement)) return;
20
- (_b = frame.contentDocument) == null ? void 0 : _b.body.setAttribute(`tabindex`, `-1`);
16
+ reader.hookManager.register(`item.onDocumentLoad`, ({ itemId }) => {
17
+ var _a;
18
+ const item = reader.spineItemsManager.get(itemId);
19
+ const frame = item == null ? void 0 : item.renderer.getDocumentFrame();
20
+ if (!frame) return;
21
+ (_a = frame.contentDocument) == null ? void 0 : _a.body.setAttribute(`tabindex`, `-1`);
21
22
  });
22
23
  return reader;
23
24
  };
25
+ const mapKeysTo = (keys) => {
26
+ return map((obj) => {
27
+ return Object.entries(obj).reduce(
28
+ (acc, [key, entry]) => {
29
+ if (keys.includes(key)) {
30
+ return {
31
+ ...acc,
32
+ [key]: entry
33
+ };
34
+ }
35
+ return acc;
36
+ },
37
+ {}
38
+ );
39
+ });
40
+ };
41
+ function observeResize(element) {
42
+ return new Observable((observer) => {
43
+ const resizeObserver = new ResizeObserver((entries) => {
44
+ observer.next(entries);
45
+ });
46
+ resizeObserver.observe(element);
47
+ return () => {
48
+ resizeObserver.disconnect();
49
+ };
50
+ });
51
+ }
52
+ const waitForSwitch = (waitForStream) => (stream) => stream.pipe(
53
+ switchMap(
54
+ (value) => waitForStream.pipe(
55
+ first(),
56
+ map(() => value)
57
+ )
58
+ )
59
+ );
60
+ const deferNextResult = (stream) => {
61
+ let value;
62
+ const sub = stream.subscribe((result) => {
63
+ value = { result };
64
+ });
65
+ return () => {
66
+ sub.unsubscribe();
67
+ if (value) {
68
+ return of(value.result);
69
+ }
70
+ return stream;
71
+ };
72
+ };
73
+ function idle() {
74
+ return new Observable((observer) => {
75
+ if (window.requestIdleCallback) {
76
+ const handle = window.requestIdleCallback(() => {
77
+ observer.next();
78
+ observer.complete();
79
+ });
80
+ return () => cancelIdleCallback(handle);
81
+ }
82
+ const timeout = setTimeout(() => {
83
+ observer.next();
84
+ observer.complete();
85
+ }, 1);
86
+ return () => clearTimeout(timeout);
87
+ });
88
+ }
89
+ function deferIdle(callback) {
90
+ return defer(() => idle().pipe(switchMap(callback)));
91
+ }
24
92
  class SettingsManagerOverload {
25
93
  constructor(initialSettings, settingsManager) {
26
94
  this.settingsManager = settingsManager;
@@ -75,6 +143,12 @@ class SettingsManagerOverload {
75
143
  ...this.outputSettings
76
144
  };
77
145
  }
146
+ watch(keys) {
147
+ return this.values$.pipe(
148
+ mapKeysTo(keys),
149
+ distinctUntilChanged(isShallowEqual)
150
+ );
151
+ }
78
152
  destroy() {
79
153
  this.outputSettingsUpdateSubject.complete();
80
154
  }
@@ -167,7 +241,7 @@ const getFrameViewportInfo = (frame) => {
167
241
  return { hasViewport: false };
168
242
  };
169
243
  const waitForFrameLoad = (stream) => stream.pipe(
170
- switchMap(
244
+ switchMap$1(
171
245
  (frame) => fromEvent(frame, `load`).pipe(
172
246
  take(1),
173
247
  map$1(() => frame)
@@ -175,7 +249,7 @@ const waitForFrameLoad = (stream) => stream.pipe(
175
249
  )
176
250
  );
177
251
  const waitForFrameReady = (stream) => stream.pipe(
178
- switchMap(
252
+ switchMap$1(
179
253
  (frame) => {
180
254
  var _a;
181
255
  return from(((_a = frame == null ? void 0 : frame.contentDocument) == null ? void 0 : _a.fonts.ready) || of(void 0)).pipe(
@@ -216,12 +290,11 @@ const fontsEnhancer = (next) => (options) => {
216
290
  `;
217
291
  const applyChangeToSpineItems = (requireLayout) => {
218
292
  reader.spineItemsManager.items.forEach((item) => {
219
- if (item.item.renditionLayout !== `pre-paginated`) {
220
- item.renderer.layers.forEach((layer) => {
221
- if (layer.element instanceof HTMLIFrameElement) {
222
- upsertCSS(layer.element, `prose-reader-fonts`, getStyle());
223
- }
224
- });
293
+ if (item.renditionLayout !== `pre-paginated`) {
294
+ const frame = item.renderer.getDocumentFrame();
295
+ if (frame) {
296
+ upsertCSS(frame, `prose-reader-fonts`, getStyle());
297
+ }
225
298
  }
226
299
  });
227
300
  if (requireLayout) {
@@ -230,12 +303,11 @@ const fontsEnhancer = (next) => (options) => {
230
303
  };
231
304
  reader.hookManager.register(`item.onDocumentLoad`, ({ itemId }) => {
232
305
  const item = reader.spineItemsManager.get(itemId);
233
- if ((item == null ? void 0 : item.item.renditionLayout) !== `pre-paginated`) {
234
- item == null ? void 0 : item.renderer.layers.forEach((layer) => {
235
- if (layer.element instanceof HTMLIFrameElement) {
236
- upsertCSS(layer.element, `prose-reader-fonts`, getStyle());
237
- }
238
- });
306
+ if ((item == null ? void 0 : item.renditionLayout) !== `pre-paginated`) {
307
+ const frame = item == null ? void 0 : item.renderer.getDocumentFrame();
308
+ if (frame) {
309
+ upsertCSS(frame, `prose-reader-fonts`, getStyle());
310
+ }
239
311
  }
240
312
  });
241
313
  const shouldRequireLayout = (source) => source.pipe(
@@ -287,13 +359,12 @@ const hotkeysEnhancer = (next) => (options) => {
287
359
  );
288
360
  navigateOnKey(document).pipe(takeUntil(reader.$.destroy$)).subscribe();
289
361
  reader.spineItemsManager.items$.pipe(
290
- switchMap(
362
+ switchMap$1(
291
363
  (spineItems) => merge(
292
364
  ...spineItems.map(
293
365
  (item) => item.loaded$.pipe(
294
- switchMap(() => {
295
- var _a;
296
- const element = (_a = item.renderer.layers[0]) == null ? void 0 : _a.element;
366
+ switchMap$1(() => {
367
+ const element = item.renderer.getDocumentFrame();
297
368
  return element instanceof HTMLIFrameElement && (element == null ? void 0 : element.contentDocument) ? navigateOnKey(element.contentDocument) : EMPTY;
298
369
  })
299
370
  )
@@ -307,7 +378,7 @@ const hotkeysEnhancer = (next) => (options) => {
307
378
  const createMovingSafePan$ = (reader) => {
308
379
  let iframeOverlayForAnimationsElement;
309
380
  const updateOverlayElement$ = reader.context.state$.pipe(
310
- switchMap$1(({ containerElement }) => {
381
+ switchMap(({ containerElement }) => {
311
382
  if (!containerElement) return NEVER;
312
383
  return new Observable(() => {
313
384
  iframeOverlayForAnimationsElement = containerElement.ownerDocument.createElement(`div`);
@@ -351,92 +422,24 @@ const createMovingSafePan$ = (reader) => {
351
422
  distinctUntilChanged()
352
423
  );
353
424
  const handleViewportLock$ = pageTurnMode$.pipe(
354
- switchMap$1(
355
- (mode) => mode === `controlled` ? lockAfterViewportBusy$.pipe(switchMap$1(() => resetLockViewportFree$)) : createResetLock$(of(void 0))
425
+ switchMap(
426
+ (mode) => mode === `controlled` ? lockAfterViewportBusy$.pipe(switchMap(() => resetLockViewportFree$)) : createResetLock$(of(void 0))
356
427
  ),
357
428
  takeUntil$1(reader.$.destroy$)
358
429
  );
359
430
  return merge(updateOverlayElement$, handleViewportLock$);
360
431
  };
361
- const mapKeysTo = (keys) => {
362
- return map((obj) => {
363
- return Object.entries(obj).reduce(
364
- (acc, [key, entry]) => {
365
- if (keys.includes(key)) {
366
- return {
367
- ...acc,
368
- [key]: entry
369
- };
370
- }
371
- return acc;
372
- },
373
- {}
374
- );
375
- });
376
- };
377
- function observeResize(element) {
378
- return new Observable((observer) => {
379
- const resizeObserver = new ResizeObserver((entries) => {
380
- observer.next(entries);
381
- });
382
- resizeObserver.observe(element);
383
- return () => {
384
- resizeObserver.disconnect();
385
- };
386
- });
387
- }
388
- const waitForSwitch = (waitForStream) => (stream) => stream.pipe(
389
- switchMap$1(
390
- (value) => waitForStream.pipe(
391
- first(),
392
- map(() => value)
393
- )
394
- )
395
- );
396
- const deferNextResult = (stream) => {
397
- let value;
398
- const sub = stream.subscribe((result) => {
399
- value = { result };
400
- });
401
- return () => {
402
- sub.unsubscribe();
403
- if (value) {
404
- return of(value.result);
405
- }
406
- return stream;
407
- };
408
- };
409
- function idle() {
410
- return new Observable((observer) => {
411
- if (window.requestIdleCallback) {
412
- const handle = window.requestIdleCallback(() => {
413
- observer.next();
414
- observer.complete();
415
- });
416
- return () => cancelIdleCallback(handle);
417
- }
418
- const timeout = setTimeout(() => {
419
- observer.next();
420
- observer.complete();
421
- }, 1);
422
- return () => clearTimeout(timeout);
423
- });
424
- }
425
- function deferIdle(callback) {
426
- return defer(() => idle().pipe(switchMap$1(callback)));
427
- }
428
432
  const fixReflowable = (reader) => {
429
433
  reader.hookManager.register(
430
434
  `item.onAfterLayout`,
431
435
  ({ item, blankPagePosition, minimumWidth }) => {
432
- var _a, _b;
433
436
  const spineItem = reader.spineItemsManager.get(item.id);
434
- const element = (_a = spineItem == null ? void 0 : spineItem.renderer.layers[0]) == null ? void 0 : _a.element;
435
- if (!((spineItem == null ? void 0 : spineItem.item.renditionLayout) === `reflowable`) || !(element instanceof HTMLIFrameElement))
437
+ const element = spineItem == null ? void 0 : spineItem.renderer.getDocumentFrame();
438
+ if (!((spineItem == null ? void 0 : spineItem.renditionLayout) === `reflowable`) || !(element instanceof HTMLIFrameElement))
436
439
  return;
437
440
  const { hasViewport } = getFrameViewportInfo(element);
438
441
  const { width: pageWidth } = reader.context.getPageSize();
439
- const frameElement = (_b = spineItem == null ? void 0 : spineItem.renderer.layers[0]) == null ? void 0 : _b.element;
442
+ const frameElement = spineItem == null ? void 0 : spineItem.renderer.getDocumentFrame();
440
443
  if (hasViewport) {
441
444
  const spineManagerWantAFullWidthItem = pageWidth < minimumWidth;
442
445
  const noBlankPageAsked = blankPagePosition === `none`;
@@ -503,8 +506,7 @@ const layoutEnhancer = (next) => (options) => {
503
506
  reader.hookManager.register(`onViewportOffsetAdjust`, () => {
504
507
  let hasRedrawn = false;
505
508
  reader.spineItemsManager.items.forEach((item) => {
506
- var _a;
507
- const frame = (_a = item.renderer.layers[0]) == null ? void 0 : _a.element;
509
+ const frame = item.renderer.getDocumentFrame();
508
510
  if (!hasRedrawn && frame) {
509
511
  void frame.getBoundingClientRect().left;
510
512
  hasRedrawn = true;
@@ -517,7 +519,7 @@ const layoutEnhancer = (next) => (options) => {
517
519
  const isImageType = !!(mimeType == null ? void 0 : mimeType.startsWith(`image/`));
518
520
  const { pageHorizontalMargin: pageHorizontalMargin2 = 0, pageVerticalMargin: pageVerticalMargin2 = 0 } = settingsManager.values;
519
521
  const pageSize = reader.context.getPageSize();
520
- if ((spineItem == null ? void 0 : spineItem.item.renditionLayout) === `reflowable` && !isImageType) {
522
+ if ((spineItem == null ? void 0 : spineItem.renditionLayout) === `reflowable` && !isImageType) {
521
523
  let columnWidth = pageSize.width - pageHorizontalMargin2 * 2;
522
524
  const columnHeight = pageSize.height - pageVerticalMargin2 * 2;
523
525
  let width = pageSize.width - pageHorizontalMargin2 * 2;
@@ -527,12 +529,12 @@ const layoutEnhancer = (next) => (options) => {
527
529
  columnWidth = columnHeight;
528
530
  columnGap = pageVerticalMargin2 * 2;
529
531
  }
530
- spineItem == null ? void 0 : spineItem.renderer.layers.forEach((layer) => {
531
- if (layer.element instanceof HTMLIFrameElement) {
532
- upsertCSS(
533
- layer.element,
534
- `prose-layout-enhancer-css`,
535
- `
532
+ const frame = spineItem == null ? void 0 : spineItem.renderer.getDocumentFrame();
533
+ if (frame) {
534
+ upsertCSS(
535
+ frame,
536
+ `prose-layout-enhancer-css`,
537
+ `
536
538
  body {
537
539
  width: ${width}px !important;
538
540
  margin: ${pageVerticalMargin2}px ${pageHorizontalMargin2}px !important;
@@ -551,9 +553,8 @@ const layoutEnhancer = (next) => (options) => {
551
553
  max-width: ${columnWidth}px;
552
554
  }
553
555
  `
554
- );
555
- }
556
- });
556
+ );
557
+ }
557
558
  }
558
559
  });
559
560
  fixReflowable(reader);
@@ -592,18 +593,16 @@ const layoutEnhancer = (next) => (options) => {
592
593
  });
593
594
  const layoutOnContainerResize$ = settingsManager.values$.pipe(
594
595
  filter(({ layoutAutoResize: layoutAutoResize2 }) => layoutAutoResize2 === "container"),
595
- switchMap$1(() => reader.context.containerElement$),
596
+ switchMap(() => reader.context.containerElement$),
596
597
  filter(isDefined),
597
- switchMap$1((container) => observeContainerResize(container)),
598
+ switchMap((container) => observeContainerResize(container)),
598
599
  debounceTime(100),
599
600
  tap(() => {
600
601
  reader == null ? void 0 : reader.layout();
601
602
  })
602
603
  );
603
604
  const movingSafePan$ = createMovingSafePan$(reader);
604
- settingsManager.values$.pipe(
605
- mapKeysTo([`pageHorizontalMargin`, `pageVerticalMargin`]),
606
- distinctUntilChanged(isShallowEqual),
605
+ settingsManager.watch([`pageHorizontalMargin`, `pageVerticalMargin`]).pipe(
607
606
  skip(1),
608
607
  tap(() => {
609
608
  reader.layout();
@@ -681,6 +680,16 @@ const createReport = (namespace) => ({
681
680
  else console.info(wrap(ROOT_NAMESPACE), ...data);
682
681
  }
683
682
  },
683
+ debug: namespace ? Function.prototype.bind.call(
684
+ console.debug,
685
+ console,
686
+ wrap(`${ROOT_NAMESPACE}`),
687
+ wrap(namespace)
688
+ ) : Function.prototype.bind.call(
689
+ console.debug,
690
+ console,
691
+ wrap(`${ROOT_NAMESPACE}`)
692
+ ),
684
693
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
685
694
  error: (...data) => {
686
695
  console.error(...data);
@@ -739,10 +748,10 @@ const linksEnhancer = (next) => (options) => {
739
748
  }
740
749
  return false;
741
750
  };
742
- reader.hookManager.register(`item.onDocumentLoad`, ({ layers }) => {
743
- var _a;
744
- const frame = (_a = layers[0]) == null ? void 0 : _a.element;
745
- if (!(frame instanceof HTMLIFrameElement)) return;
751
+ reader.hookManager.register(`item.onDocumentLoad`, ({ itemId }) => {
752
+ const item = reader.spineItemsManager.get(itemId);
753
+ const frame = item == null ? void 0 : item.renderer.getDocumentFrame();
754
+ if (!frame) return;
746
755
  if (frame == null ? void 0 : frame.contentDocument) {
747
756
  Array.from(frame.contentDocument.querySelectorAll(`a`)).forEach(
748
757
  (element) => element.addEventListener(`click`, (e) => {
@@ -991,6 +1000,7 @@ const getNavigationForLeftOrTopPage = ({
991
1000
  }
992
1001
  return navigationResolver.getAdjustedPositionForSpread(navigation);
993
1002
  };
1003
+ const report$4 = Report.namespace(`navigation`);
994
1004
  class ManualNavigator {
995
1005
  constructor(reader) {
996
1006
  this.reader = reader;
@@ -1149,6 +1159,12 @@ class ManualNavigator {
1149
1159
  pageIndex,
1150
1160
  spineItemId
1151
1161
  });
1162
+ report$4.debug(`.goToPageOfSpineItem()`, {
1163
+ pageIndex,
1164
+ spineItemId,
1165
+ ...rest,
1166
+ position
1167
+ });
1152
1168
  this.reader.navigation.navigate({
1153
1169
  position,
1154
1170
  ...rest
@@ -1161,6 +1177,11 @@ class ManualNavigator {
1161
1177
  const foundInfo = this.reader.spine.locator.getSpineInfoFromAbsolutePageIndex({
1162
1178
  absolutePageIndex
1163
1179
  });
1180
+ report$4.debug(`.goToAbsolutePageIndex()`, {
1181
+ absolutePageIndex,
1182
+ ...rest,
1183
+ foundInfo
1184
+ });
1164
1185
  if (foundInfo) {
1165
1186
  const position = this.reader.navigation.navigationResolver.getNavigationForSpineItemPage(
1166
1187
  {
@@ -1480,7 +1501,7 @@ const trackPaginationInfo = (reader) => {
1480
1501
  });
1481
1502
  const extandedBasePagination$ = reader.pagination.state$.pipe(
1482
1503
  combineLatestWith(chaptersInfo$),
1483
- switchMap(
1504
+ switchMap$1(
1484
1505
  ([info, chaptersInfo]) => mapPaginationInfoToExtendedInfo(reader, info, chaptersInfo).pipe(
1485
1506
  map$1((extendedInfo) => ({
1486
1507
  ...info,
@@ -1520,7 +1541,7 @@ const consolidate = (item, reader) => {
1520
1541
  const { itemIndex } = reader.cfi.parseCfi(item.cfi);
1521
1542
  const spineItem = reader.spineItemsManager.get(itemIndex);
1522
1543
  if (!spineItem) return of({ ...item, meta: { ...item.meta, itemIndex } });
1523
- if (spineItem.item.renditionLayout === `pre-paginated`) {
1544
+ if (spineItem.renditionLayout === `pre-paginated`) {
1524
1545
  itemPageIndex = 0;
1525
1546
  }
1526
1547
  return idle().pipe(
@@ -1529,7 +1550,7 @@ const consolidate = (item, reader) => {
1529
1550
  var _a2, _b, _c;
1530
1551
  let range = void 0;
1531
1552
  const { node: startNode, offset: startOffset } = reader.cfi.resolveCfi({ cfi: item.cfi }) ?? {};
1532
- if (spineItem.item.renditionLayout !== `pre-paginated` && startNode) {
1553
+ if (spineItem.renditionLayout !== `pre-paginated` && startNode) {
1533
1554
  itemPageIndex = reader.spine.locator.spineItemLocator.getSpineItemPageIndexFromNode(
1534
1555
  startNode,
1535
1556
  startOffset ?? 0,
@@ -1568,13 +1589,7 @@ const consolidate = (item, reader) => {
1568
1589
  };
1569
1590
  const createLocator = (reader) => (resources) => {
1570
1591
  return deferIdle(() => {
1571
- if (!resources.length)
1572
- return of({ isStale: false, data: resources });
1573
- const StaleSymbol = Symbol("stale");
1574
- const markStale$ = reader.layout$.pipe(
1575
- startWith$1(null),
1576
- map$1(() => StaleSymbol)
1577
- );
1592
+ if (!resources.length) return of(resources);
1578
1593
  const consolidate$ = reader.layout$.pipe(
1579
1594
  debounceTime$1(10),
1580
1595
  startWith$1(null),
@@ -1588,27 +1603,20 @@ const createLocator = (reader) => (resources) => {
1588
1603
  );
1589
1604
  }, resources)
1590
1605
  );
1591
- const run$ = merge(markStale$, consolidate$).pipe(
1592
- scan(
1593
- (acc, value) => {
1594
- if (value === StaleSymbol) {
1595
- return {
1596
- ...acc,
1597
- isStale: true
1598
- };
1599
- }
1600
- return {
1601
- isStale: false,
1602
- data: value
1603
- };
1604
- },
1605
- {
1606
- isStale: true,
1607
- data: resources
1608
- }
1609
- )
1606
+ const reflowableItemIndexes = resources.map((item) => reader.cfi.parseCfi(item.cfi).itemIndex).filter(isDefined).filter((index) => {
1607
+ var _a;
1608
+ return ((_a = reader.spineItemsManager.get(index)) == null ? void 0 : _a.renditionLayout) === `reflowable`;
1609
+ });
1610
+ const release = reader.spine.spineItemsLoader.forceOpen(
1611
+ reflowableItemIndexes
1612
+ );
1613
+ return consolidate$.pipe(
1614
+ finalize(() => {
1615
+ setTimeout(() => {
1616
+ release();
1617
+ }, 1e3);
1618
+ })
1610
1619
  );
1611
- return run$;
1612
1620
  });
1613
1621
  };
1614
1622
  Report.namespace(NAMESPACE$6);
@@ -1685,22 +1693,20 @@ const themeEnhancer = (next) => (options) => {
1685
1693
  };
1686
1694
  const applyChangeToSpineItem = () => {
1687
1695
  reader.spineItemsManager.items.forEach((item) => {
1688
- item.renderer.layers.forEach((layer) => {
1689
- if (layer.element instanceof HTMLIFrameElement) {
1690
- upsertCSS(layer.element, `prose-reader-theme`, getStyle());
1691
- }
1692
- });
1696
+ const frame = item.renderer.getDocumentFrame();
1697
+ if (frame) {
1698
+ upsertCSS(frame, `prose-reader-theme`, getStyle());
1699
+ }
1693
1700
  applyChangeToSpineItemElement({ container: item.element });
1694
1701
  });
1695
1702
  };
1696
1703
  reader.hookManager.register(`item.onDocumentLoad`, ({ itemId }) => {
1697
1704
  const item = reader.spineItemsManager.get(itemId);
1698
- if ((item == null ? void 0 : item.item.renditionLayout) !== "pre-paginated") {
1699
- item == null ? void 0 : item.renderer.layers.forEach((layer) => {
1700
- if (layer.element instanceof HTMLIFrameElement) {
1701
- upsertCSS(layer.element, `prose-reader-theme`, getStyle());
1702
- }
1703
- });
1705
+ if ((item == null ? void 0 : item.renditionLayout) !== "pre-paginated") {
1706
+ const frame = item == null ? void 0 : item.renderer.getDocumentFrame();
1707
+ if (frame) {
1708
+ upsertCSS(frame, `prose-reader-theme`, getStyle());
1709
+ }
1704
1710
  }
1705
1711
  });
1706
1712
  reader.spineItemsManager.items$.pipe(
@@ -1895,7 +1901,7 @@ const zoomEnhancer = (next) => (options) => {
1895
1901
  return zoomerSubject.getValue().currentScale;
1896
1902
  },
1897
1903
  isZooming$: zoomerSubject.pipe(
1898
- switchMap((zoomer) => zoomer.isZooming$)
1904
+ switchMap$1((zoomer) => zoomer.isZooming$)
1899
1905
  ),
1900
1906
  get zoomContainerElement() {
1901
1907
  return zoomerSubject.getValue().element;
@@ -2039,10 +2045,13 @@ class Context {
2039
2045
  }
2040
2046
  class DestroyableClass {
2041
2047
  constructor() {
2048
+ this.isDestroyed = false;
2042
2049
  this.destroySubject = new Subject();
2043
2050
  this.destroy$ = this.destroySubject.asObservable();
2044
2051
  }
2045
2052
  destroy() {
2053
+ if (this.isDestroyed) return;
2054
+ this.isDestroyed = true;
2046
2055
  this.destroySubject.next();
2047
2056
  this.destroySubject.complete();
2048
2057
  }
@@ -2408,10 +2417,10 @@ const createSpineItemLocator = ({
2408
2417
  return void 0;
2409
2418
  };
2410
2419
  const getFirstNodeOrRangeAtPage = (pageIndex, spineItem) => {
2411
- var _a, _b, _c;
2420
+ var _a, _b;
2412
2421
  const pageSize = context.getPageSize();
2413
- const frame = (_b = (_a = spineItem.renderer) == null ? void 0 : _a.layers[0]) == null ? void 0 : _b.element;
2414
- if (frame instanceof HTMLIFrameElement && ((_c = frame == null ? void 0 : frame.contentWindow) == null ? void 0 : _c.document) && // very important because it is being used by next functions
2422
+ const frame = (_a = spineItem.renderer) == null ? void 0 : _a.getDocumentFrame();
2423
+ if (frame && ((_b = frame == null ? void 0 : frame.contentWindow) == null ? void 0 : _b.document) && // very important because it is being used by next functions
2415
2424
  frame.contentWindow.document.body !== null) {
2416
2425
  const { x: left, y: top } = getSpineItemPositionFromPageIndex({
2417
2426
  pageIndex,
@@ -3621,15 +3630,15 @@ const resolveCfi = ({
3621
3630
  cfi,
3622
3631
  spineItemsManager
3623
3632
  }) => {
3624
- var _a, _b;
3633
+ var _a;
3625
3634
  if (!cfi) return void 0;
3626
3635
  const spineItem = spineItemsManager.getSpineItemFromCfi(cfi);
3627
3636
  if (!spineItem) return void 0;
3628
3637
  const { cleanedCfi, offset } = parseCfi(cfi);
3629
3638
  const cfiHandler = new CfiHandler(cleanedCfi, {});
3630
- const rendererElement = (_a = spineItem.renderer.layers[0]) == null ? void 0 : _a.element;
3639
+ const rendererElement = spineItem.renderer.getDocumentFrame();
3631
3640
  if (rendererElement instanceof HTMLIFrameElement) {
3632
- const doc = (_b = rendererElement.contentWindow) == null ? void 0 : _b.document;
3641
+ const doc = (_a = rendererElement.contentWindow) == null ? void 0 : _a.document;
3633
3642
  if (doc) {
3634
3643
  try {
3635
3644
  const { node, offset: resolvedOffset } = cfiHandler.resolve(doc, {});
@@ -3826,14 +3835,11 @@ class ViewportNavigator extends DestroyableClass {
3826
3835
  this.navigateSubject = new Subject();
3827
3836
  this.scrollingSubject = new BehaviorSubject(false);
3828
3837
  this.isScrolling$ = this.scrollingSubject.asObservable();
3829
- const settingsThatRequireLayout$ = settings.values$.pipe(
3830
- mapKeysTo([
3831
- `computedPageTurnDirection`,
3832
- `computedPageTurnMode`,
3833
- `numberOfAdjacentSpineItemToPreLoad`
3834
- ]),
3835
- distinctUntilChanged$1(isShallowEqual)
3836
- );
3838
+ const settingsThatRequireLayout$ = settings.watch([
3839
+ `computedPageTurnDirection`,
3840
+ `computedPageTurnMode`,
3841
+ `numberOfAdjacentSpineItemToPreLoad`
3842
+ ]);
3837
3843
  const updateElementOnSettingsChange$ = merge(
3838
3844
  settingsThatRequireLayout$,
3839
3845
  this.viewportElement$
@@ -3872,7 +3878,7 @@ class ViewportNavigator extends DestroyableClass {
3872
3878
  position
3873
3879
  };
3874
3880
  }),
3875
- switchMap((currentEvent) => {
3881
+ switchMap$1((currentEvent) => {
3876
3882
  const element = this.viewportElement$.getValue();
3877
3883
  element.style.setProperty(`transition`, `none`);
3878
3884
  element.style.setProperty(`opacity`, `1`);
@@ -4038,14 +4044,14 @@ class UserNavigator extends DestroyableClass {
4038
4044
  this.locker = new Locker();
4039
4045
  this.navigation$ = this.navigationSubject.asObservable();
4040
4046
  const userScroll$ = element$.pipe(
4041
- switchMap(
4047
+ switchMap$1(
4042
4048
  (element) => settings.values$.pipe(
4043
4049
  map$1(({ computedPageTurnMode }) => computedPageTurnMode),
4044
4050
  distinctUntilChanged$1(),
4045
4051
  filter$1(
4046
4052
  (computedPageTurnMode) => computedPageTurnMode === "scrollable"
4047
4053
  ),
4048
- switchMap(() => {
4054
+ switchMap$1(() => {
4049
4055
  return fromEvent(element, `scroll`).pipe(
4050
4056
  withLatestFrom(scrollHappeningFromBrowser$),
4051
4057
  filter$1(([, shouldAvoidScrollEvent]) => !shouldAvoidScrollEvent),
@@ -4060,7 +4066,7 @@ class UserNavigator extends DestroyableClass {
4060
4066
  map$1(({ computedPageTurnMode }) => computedPageTurnMode),
4061
4067
  distinctUntilChanged$1(),
4062
4068
  filter$1((computedPageTurnMode) => computedPageTurnMode === "scrollable"),
4063
- switchMap(() => userScroll$),
4069
+ switchMap$1(() => userScroll$),
4064
4070
  exhaustMap((event) => {
4065
4071
  const unlock = this.locker.lock();
4066
4072
  return merge(userScroll$, of(event)).pipe(
@@ -4639,7 +4645,7 @@ const consolidateWithPagination = (context, navigation$, spine) => context.bridg
4639
4645
  * Otherwise we might save something incomplete and thus restore
4640
4646
  * the user to an invalid location.
4641
4647
  */
4642
- switchMap(([pagination, navigation]) => {
4648
+ switchMap$1(([pagination, navigation]) => {
4643
4649
  const spineItem = spine.spineItemsManager.get(navigation.spineItem);
4644
4650
  return ((spineItem == null ? void 0 : spineItem.isReady$.pipe(first$1())) ?? of(false)).pipe(
4645
4651
  filter$1((isReady) => isReady),
@@ -4740,7 +4746,7 @@ class InternalNavigator extends DestroyableClass {
4740
4746
  spineItemsManager: spine.spineItemsManager
4741
4747
  }),
4742
4748
  withLatestFrom(isUserLocked$),
4743
- switchMap(([params, isUserLocked]) => {
4749
+ switchMap$1(([params, isUserLocked]) => {
4744
4750
  const shouldNotAlterPosition = params.navigation.cfi || params.navigation.url || settings.values.computedPageTurnMode === "scrollable" || isUserLocked;
4745
4751
  return of(params).pipe(
4746
4752
  shouldNotAlterPosition ? identity : withRestoredPosition({
@@ -4763,7 +4769,7 @@ class InternalNavigator extends DestroyableClass {
4763
4769
  const navigationUpdateFollowingUserUnlock$ = navigationFromUser$.pipe(
4764
4770
  withLatestFrom(isUserLocked$),
4765
4771
  filter$1(([, isUserLocked]) => isUserLocked),
4766
- switchMap(([navigation]) => {
4772
+ switchMap$1(([navigation]) => {
4767
4773
  const unlock = this.locker.lock();
4768
4774
  return isUserLocked$.pipe(
4769
4775
  filter$1((isUserLocked) => !isUserLocked),
@@ -4783,9 +4789,9 @@ class InternalNavigator extends DestroyableClass {
4783
4789
  share()
4784
4790
  );
4785
4791
  const navigationUpateFromLayout$ = layoutHasChanged$.pipe(
4786
- switchMap(() => {
4792
+ switchMap$1(() => {
4787
4793
  return of(null).pipe(
4788
- switchMap(
4794
+ switchMap$1(
4789
4795
  () => isUserLocked$.pipe(
4790
4796
  filter$1((isLocked) => !isLocked),
4791
4797
  first$1()
@@ -4937,10 +4943,10 @@ const createNavigator = ({
4937
4943
  );
4938
4944
  const isSpineScrolling$ = merge(
4939
4945
  spine.elementResize$,
4940
- spine.element$.pipe(switchMap$1((element) => fromEvent(element, "scroll"))),
4946
+ spine.element$.pipe(switchMap((element) => fromEvent(element, "scroll"))),
4941
4947
  spine.spineItemsObserver.itemResize$
4942
4948
  ).pipe(
4943
- switchMap$1(() => merge(of(true), timer(5).pipe(map(() => false)))),
4949
+ switchMap(() => merge(of(true), timer(5).pipe(map(() => false)))),
4944
4950
  startWith(false)
4945
4951
  );
4946
4952
  const scrollHappeningFromBrowser$ = combineLatest([
@@ -5024,7 +5030,7 @@ class SettingsManager3 extends DestroyableClass {
5024
5030
  };
5025
5031
  this.inputSettings = settingsWithDefaults;
5026
5032
  this.outputSettingsUpdateSubject = new Subject();
5027
- this._settings$ = this.outputSettingsUpdateSubject.asObservable().pipe(shareReplay(1));
5033
+ this._settings$ = this.outputSettingsUpdateSubject.asObservable().pipe(shareReplay$1(1));
5028
5034
  this._settings$.subscribe();
5029
5035
  }
5030
5036
  _prepareUpdate(settings) {
@@ -5062,6 +5068,12 @@ class SettingsManager3 extends DestroyableClass {
5062
5068
  }
5063
5069
  return this._settings$;
5064
5070
  }
5071
+ watch(keys) {
5072
+ return this.values$.pipe(
5073
+ mapKeysTo(keys),
5074
+ distinctUntilChanged$1(isShallowEqual)
5075
+ );
5076
+ }
5065
5077
  destroy() {
5066
5078
  super.destroy();
5067
5079
  this.outputSettingsUpdateSubject.complete();
@@ -5235,13 +5247,13 @@ const generateCfiForSpineItemPage = Report.measurePerformance(
5235
5247
  spineItem,
5236
5248
  spineItemLocator
5237
5249
  }) => {
5238
- var _a, _b;
5250
+ var _a;
5239
5251
  const nodeOrRange = spineItemLocator.getFirstNodeOrRangeAtPage(
5240
5252
  pageIndex,
5241
5253
  spineItem
5242
5254
  );
5243
- const rendererElement = (_a = spineItem.renderer.layers[0]) == null ? void 0 : _a.element;
5244
- if (nodeOrRange && rendererElement instanceof HTMLIFrameElement && ((_b = rendererElement.contentWindow) == null ? void 0 : _b.document)) {
5255
+ const rendererElement = spineItem.renderer.getDocumentFrame();
5256
+ if (nodeOrRange && rendererElement instanceof HTMLIFrameElement && ((_a = rendererElement.contentWindow) == null ? void 0 : _a.document)) {
5245
5257
  const cfiString = generateCfi(
5246
5258
  nodeOrRange.node,
5247
5259
  nodeOrRange.offset,
@@ -5264,7 +5276,7 @@ class PaginationController extends DestroyableClass {
5264
5276
  this.context.bridgeEvent.navigation$,
5265
5277
  spine.spineLayout.layout$.pipe(filter$1(({ hasChanged }) => hasChanged))
5266
5278
  ).pipe(
5267
- switchMap(() => {
5279
+ switchMap$1(() => {
5268
5280
  const getVisiblePagesFromViewportPosition = ({
5269
5281
  spineItem,
5270
5282
  position
@@ -5390,6 +5402,7 @@ class DocumentRenderer extends DestroyableClass {
5390
5402
  constructor(params) {
5391
5403
  super();
5392
5404
  this.triggerSubject = new Subject();
5405
+ this.lastLayoutDims = void 0;
5393
5406
  this.stateSubject = new BehaviorSubject(`idle`);
5394
5407
  this.unload$ = this.triggerSubject.pipe(
5395
5408
  withLatestFrom(this.stateSubject),
@@ -5423,7 +5436,7 @@ class DocumentRenderer extends DestroyableClass {
5423
5436
  share()
5424
5437
  );
5425
5438
  this.load$.pipe(
5426
- switchMap(() => {
5439
+ switchMap$1(() => {
5427
5440
  this.stateSubject.next(`loading`);
5428
5441
  const createDocument$ = this.onCreateDocument().pipe(
5429
5442
  endWith(null),
@@ -5436,7 +5449,7 @@ class DocumentRenderer extends DestroyableClass {
5436
5449
  layers: this.layers
5437
5450
  });
5438
5451
  }),
5439
- switchMap(() => {
5452
+ switchMap$1(() => {
5440
5453
  const loadDocument$ = this.onLoadDocument().pipe(
5441
5454
  endWith(null),
5442
5455
  first$1()
@@ -5444,7 +5457,7 @@ class DocumentRenderer extends DestroyableClass {
5444
5457
  return loadDocument$;
5445
5458
  }),
5446
5459
  waitForSwitch(this.context.bridgeEvent.viewportFree$),
5447
- switchMap(() => {
5460
+ switchMap$1(() => {
5448
5461
  const hookResults = this.hookManager.execute(`item.onDocumentLoad`, this.item.id, {
5449
5462
  itemId: this.item.id,
5450
5463
  layers: this.layers
@@ -5461,14 +5474,14 @@ class DocumentRenderer extends DestroyableClass {
5461
5474
  })
5462
5475
  ).subscribe();
5463
5476
  const unload$ = unloadTrigger$.pipe(
5464
- switchMap(() => {
5477
+ switchMap$1(() => {
5465
5478
  this.stateSubject.next(`unloading`);
5466
5479
  return this.context.bridgeEvent.viewportFree$.pipe(
5467
5480
  first$1(),
5468
5481
  tap$1(() => {
5469
5482
  this.hookManager.destroy(`item.onDocumentLoad`, this.item.id);
5470
5483
  }),
5471
- switchMap(() => {
5484
+ switchMap$1(() => {
5472
5485
  const onUnload$ = this.onUnload().pipe(endWith(null), first$1());
5473
5486
  return onUnload$;
5474
5487
  }),
@@ -5516,6 +5529,24 @@ class DocumentRenderer extends DestroyableClass {
5516
5529
  })
5517
5530
  );
5518
5531
  }
5532
+ /**
5533
+ * @important
5534
+ *
5535
+ * If renderer returns undefined as dimensions we will use the previous
5536
+ * layout dimensions as fallback. This ensure minmum layout shift during
5537
+ * load / unload of items and improve stability..
5538
+ */
5539
+ layout(params) {
5540
+ return defer(() => this.onLayout(params)).pipe(
5541
+ map$1((dims) => {
5542
+ const { height, width } = dims ?? this.lastLayoutDims ?? { height: 0, width: 0 };
5543
+ const minHeight = Math.max(height, this.context.getPageSize().height);
5544
+ const minWidth = Math.max(width, params.minimumWidth);
5545
+ this.lastLayoutDims = { height: minHeight, width: minWidth };
5546
+ return this.lastLayoutDims;
5547
+ })
5548
+ );
5549
+ }
5519
5550
  destroy() {
5520
5551
  super.destroy();
5521
5552
  this.stateSubject.complete();
@@ -5543,6 +5574,9 @@ class DefaultRenderer extends DocumentRenderer {
5543
5574
  onRenderHeadless() {
5544
5575
  return EMPTY;
5545
5576
  }
5577
+ getDocumentFrame() {
5578
+ return void 0;
5579
+ }
5546
5580
  }
5547
5581
  class SpineItem extends DestroyableClass {
5548
5582
  constructor(item, parentElement, context, settings, hookManager, index) {
@@ -5577,13 +5611,13 @@ class SpineItem extends DestroyableClass {
5577
5611
  }
5578
5612
  };
5579
5613
  this.getBoundingRectOfElementFromSelector = (selector) => {
5580
- var _a2, _b2, _c, _d, _e;
5581
- const frameElement = (_a2 = this.renderer.layers[0]) == null ? void 0 : _a2.element;
5614
+ var _a2, _b2, _c, _d;
5615
+ const frameElement = this.renderer.getDocumentFrame();
5582
5616
  if (frameElement && frameElement instanceof HTMLIFrameElement && selector) {
5583
5617
  if (selector.startsWith(`#`)) {
5584
- return (_c = (_b2 = frameElement.contentDocument) == null ? void 0 : _b2.getElementById(selector.replace(`#`, ``))) == null ? void 0 : _c.getBoundingClientRect();
5618
+ return (_b2 = (_a2 = frameElement.contentDocument) == null ? void 0 : _a2.getElementById(selector.replace(`#`, ``))) == null ? void 0 : _b2.getBoundingClientRect();
5585
5619
  }
5586
- return (_e = (_d = frameElement.contentDocument) == null ? void 0 : _d.querySelector(selector)) == null ? void 0 : _e.getBoundingClientRect();
5620
+ return (_d = (_c = frameElement.contentDocument) == null ? void 0 : _c.querySelector(selector)) == null ? void 0 : _d.getBoundingClientRect();
5587
5621
  }
5588
5622
  };
5589
5623
  this.layout = (params) => {
@@ -5591,7 +5625,9 @@ class SpineItem extends DestroyableClass {
5591
5625
  this.layoutTriggerSubject.next(params);
5592
5626
  return nextResult();
5593
5627
  };
5594
- this.load = () => this.renderer.load();
5628
+ this.load = () => {
5629
+ this.renderer.load();
5630
+ };
5595
5631
  this.unload = () => {
5596
5632
  this.renderer.unload();
5597
5633
  };
@@ -5633,32 +5669,24 @@ class SpineItem extends DestroyableClass {
5633
5669
  };
5634
5670
  this.renderer = rendererFactory ? rendererFactory(rendererParams) : new DefaultRenderer(rendererParams);
5635
5671
  const layoutProcess$ = this.layoutTriggerSubject.pipe(
5636
- switchMap$1(({ blankPagePosition, minimumWidth, spreadPosition }) => {
5672
+ switchMap(({ blankPagePosition, minimumWidth, spreadPosition }) => {
5637
5673
  this.hookManager.execute(`item.onBeforeLayout`, void 0, {
5638
5674
  blankPagePosition,
5639
5675
  item: this.item,
5640
5676
  minimumWidth
5641
5677
  });
5642
- const layout$ = defer(
5643
- () => this.renderer.onLayout({
5644
- blankPagePosition,
5645
- minPageSpread: minimumWidth / this.context.getPageSize().width,
5646
- minimumWidth,
5647
- spreadPosition
5648
- })
5649
- );
5678
+ const layout$ = this.renderer.layout({
5679
+ blankPagePosition,
5680
+ minPageSpread: minimumWidth / this.context.getPageSize().width,
5681
+ minimumWidth,
5682
+ spreadPosition
5683
+ });
5650
5684
  return merge(
5651
5685
  of({ type: "start" }),
5652
5686
  layout$.pipe(
5653
- map((dims) => {
5654
- const { height, width } = dims ?? { height: 0, width: 0 };
5655
- const minHeight = Math.max(
5656
- height,
5657
- this.context.getPageSize().height
5658
- );
5659
- const minWidth = Math.max(width, minimumWidth);
5660
- this.containerElement.style.width = `${minWidth}px`;
5661
- this.containerElement.style.height = `${minHeight}px`;
5687
+ map(({ height, width }) => {
5688
+ this.containerElement.style.width = `${width}px`;
5689
+ this.containerElement.style.height = `${height}px`;
5662
5690
  this.hookManager.execute(`item.onAfterLayout`, void 0, {
5663
5691
  blankPagePosition,
5664
5692
  item: this.item,
@@ -5666,7 +5694,7 @@ class SpineItem extends DestroyableClass {
5666
5694
  });
5667
5695
  return {
5668
5696
  type: "end",
5669
- data: { width: minWidth, height: minHeight }
5697
+ data: { width, height }
5670
5698
  };
5671
5699
  })
5672
5700
  )
@@ -5722,7 +5750,7 @@ class SpineItem extends DestroyableClass {
5722
5750
  return this.renderer.state$.pipe(
5723
5751
  distinctUntilChanged(),
5724
5752
  filter((state) => state !== "idle"),
5725
- switchMap$1(
5753
+ switchMap(
5726
5754
  () => this.renderer.state$.pipe(
5727
5755
  filter((state) => state === `idle`),
5728
5756
  first()
@@ -5730,6 +5758,12 @@ class SpineItem extends DestroyableClass {
5730
5758
  )
5731
5759
  );
5732
5760
  }
5761
+ get renditionLayout() {
5762
+ var _a;
5763
+ const itemRenditionLayout = this.item.renditionLayout;
5764
+ if (itemRenditionLayout) return itemRenditionLayout;
5765
+ return ((_a = this.context.manifest) == null ? void 0 : _a.renditionLayout) ?? "reflowable";
5766
+ }
5733
5767
  }
5734
5768
  const createContainerElement = (containerElement, item, hookManager) => {
5735
5769
  const element = containerElement.ownerDocument.createElement(`div`);
@@ -6059,8 +6093,8 @@ const createSpineLocator = ({
6059
6093
  };
6060
6094
  const getSpineItemFromIframe = (iframe) => {
6061
6095
  return spineItemsManager.items.find((item) => {
6062
- var _a;
6063
- return ((_a = item.renderer.layers[0]) == null ? void 0 : _a.element) === iframe;
6096
+ const element = item.renderer.getDocumentFrame();
6097
+ return element === iframe;
6064
6098
  });
6065
6099
  };
6066
6100
  const getSpineItemPageIndexFromNode = (node, offset, spineItemOrIndex) => {
@@ -6196,33 +6230,6 @@ const createSpineLocator = ({
6196
6230
  getSafeSpineItemPositionFromUnsafeSpineItemPosition
6197
6231
  };
6198
6232
  };
6199
- const loadItems = ({
6200
- spineItemsManager,
6201
- settings
6202
- }) => (stream) => stream.pipe(
6203
- tap$1(([beginIndex, endIndex]) => {
6204
- const { numberOfAdjacentSpineItemToPreLoad } = settings.values;
6205
- const leftMaximumIndex = beginIndex - numberOfAdjacentSpineItemToPreLoad;
6206
- const rightMaximumIndex = endIndex + numberOfAdjacentSpineItemToPreLoad;
6207
- spineItemsManager.items.forEach((orderedSpineItem, index) => {
6208
- const isWithinRange = index >= leftMaximumIndex && index <= rightMaximumIndex;
6209
- if (isWithinRange) {
6210
- orderedSpineItem.load();
6211
- } else {
6212
- orderedSpineItem.unload();
6213
- }
6214
- });
6215
- })
6216
- );
6217
- const mapToItemsToLoad = ({ spineLocator }) => (stream) => stream.pipe(
6218
- map$1((position) => {
6219
- const { beginIndex = 0, endIndex = 0 } = spineLocator.getVisibleSpineItemsFromPosition({
6220
- position,
6221
- threshold: 0
6222
- }) || {};
6223
- return [beginIndex, endIndex];
6224
- })
6225
- );
6226
6233
  class SpineItemsLoader extends DestroyableClass {
6227
6234
  constructor(context, spineItemsManager, spineLocator, settings, spineLayout) {
6228
6235
  super();
@@ -6231,34 +6238,62 @@ class SpineItemsLoader extends DestroyableClass {
6231
6238
  this.spineLocator = spineLocator;
6232
6239
  this.settings = settings;
6233
6240
  this.spineLayout = spineLayout;
6234
- const navigationUpdate$ = this.context.bridgeEvent.navigation$;
6235
- const layoutHasChanged$ = this.spineLayout.layout$.pipe(
6236
- filter$1(({ hasChanged }) => hasChanged)
6241
+ this.forcedOpenSubject = new BehaviorSubject([]);
6242
+ const forcedOpen$ = this.forcedOpenSubject.pipe(
6243
+ map$1((v) => [...new Set(v.flat())].sort()),
6244
+ distinctUntilChanged$1(arrayEqual),
6245
+ shareReplay$1({ bufferSize: 1, refCount: true })
6237
6246
  );
6238
- const numberOfAdjacentSpineItemToPreLoad$ = settings.values$.pipe(
6239
- map$1(
6240
- ({ numberOfAdjacentSpineItemToPreLoad }) => numberOfAdjacentSpineItemToPreLoad
6241
- ),
6242
- skip$1(1),
6243
- distinctUntilChanged$1()
6247
+ const shouldReloadSpineItems$ = merge(
6248
+ this.context.bridgeEvent.navigation$,
6249
+ this.spineLayout.layout$,
6250
+ forcedOpen$,
6251
+ settings.watch(["numberOfAdjacentSpineItemToPreLoad"])
6244
6252
  );
6245
- const loadSpineItems$ = merge(
6246
- navigationUpdate$,
6247
- layoutHasChanged$,
6248
- numberOfAdjacentSpineItemToPreLoad$
6249
- ).pipe(
6253
+ const loadSpineItems$ = shouldReloadSpineItems$.pipe(
6250
6254
  // this can be changed by whatever we want and SHOULD not break navigation.
6251
6255
  // Ideally loading faster is better but loading too close to user navigating can
6252
6256
  // be dangerous.
6253
6257
  debounceTime$1(100, animationFrameScheduler),
6254
6258
  waitForSwitch(this.context.bridgeEvent.viewportFree$),
6255
- withLatestFrom(this.context.bridgeEvent.navigation$),
6256
- map$1(([, navigation]) => navigation.position),
6257
- mapToItemsToLoad({ spineLocator }),
6258
- loadItems({ spineItemsManager, settings })
6259
+ withLatestFrom(this.context.bridgeEvent.navigation$, forcedOpen$),
6260
+ map$1(([, navigation, forcedOpenIndexes]) => {
6261
+ const { numberOfAdjacentSpineItemToPreLoad } = settings.values;
6262
+ const { beginIndex = 0, endIndex = 0 } = spineLocator.getVisibleSpineItemsFromPosition({
6263
+ position: navigation.position,
6264
+ threshold: 0
6265
+ }) || {};
6266
+ const beginMaximumIndex = beginIndex - numberOfAdjacentSpineItemToPreLoad;
6267
+ const endMaximumIndex = endIndex + numberOfAdjacentSpineItemToPreLoad;
6268
+ const visibleIndexes = Array.from(
6269
+ { length: endMaximumIndex - beginMaximumIndex + 1 },
6270
+ (_, i) => beginMaximumIndex + i
6271
+ );
6272
+ const indexesToLoad = [...forcedOpenIndexes, ...visibleIndexes];
6273
+ spineItemsManager.items.forEach((orderedSpineItem, index) => {
6274
+ if (indexesToLoad.includes(index)) {
6275
+ orderedSpineItem.load();
6276
+ } else {
6277
+ orderedSpineItem.unload();
6278
+ }
6279
+ });
6280
+ })
6259
6281
  );
6260
6282
  loadSpineItems$.pipe(takeUntil(this.destroy$)).subscribe();
6261
6283
  }
6284
+ forceOpen(spineItems) {
6285
+ this.forcedOpenSubject.next([...this.forcedOpenSubject.value, spineItems]);
6286
+ return () => {
6287
+ if (this.isDestroyed) return;
6288
+ this.forcedOpenSubject.next(
6289
+ this.forcedOpenSubject.value.filter((item) => item !== spineItems)
6290
+ );
6291
+ };
6292
+ }
6293
+ destroy() {
6294
+ super.destroy();
6295
+ this.forcedOpenSubject.complete();
6296
+ }
6262
6297
  }
6263
6298
  class SpineItemsObserver extends DestroyableClass {
6264
6299
  constructor(spineItemsManager, spineLocator) {
@@ -6266,7 +6301,7 @@ class SpineItemsObserver extends DestroyableClass {
6266
6301
  this.spineItemsManager = spineItemsManager;
6267
6302
  this.spineLocator = spineLocator;
6268
6303
  this.itemIsReady$ = this.spineItemsManager.items$.pipe(
6269
- switchMap((items) => {
6304
+ switchMap$1((items) => {
6270
6305
  const itemsIsReady$ = items.map(
6271
6306
  (item) => item.isReady$.pipe(map$1((isReady) => ({ item, isReady })))
6272
6307
  );
@@ -6275,7 +6310,7 @@ class SpineItemsObserver extends DestroyableClass {
6275
6310
  share()
6276
6311
  );
6277
6312
  this.itemResize$ = this.spineItemsManager.items$.pipe(
6278
- switchMap((items) => {
6313
+ switchMap$1((items) => {
6279
6314
  const resize$ = items.map(
6280
6315
  (item) => observeResize(item.element).pipe(
6281
6316
  map$1((entries) => ({ entries, item }))
@@ -6286,7 +6321,7 @@ class SpineItemsObserver extends DestroyableClass {
6286
6321
  share()
6287
6322
  );
6288
6323
  this.itemLoaded$ = this.spineItemsManager.items$.pipe(
6289
- switchMap((items) => {
6324
+ switchMap$1((items) => {
6290
6325
  const itemsIsReady$ = items.map(
6291
6326
  (item) => item.loaded$.pipe(map$1(() => item))
6292
6327
  );
@@ -6326,10 +6361,10 @@ const layoutItem = ({
6326
6361
  const itemStartOnNewScreen = horizontalOffset % context.state.visibleAreaRect.width === 0;
6327
6362
  const isLastItem = index === spineItemsManager.items.length - 1;
6328
6363
  if (context.state.isUsingSpreadMode) {
6329
- if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && !isLastItem) {
6364
+ if (!isGloballyPrePaginated && item.renditionLayout === `reflowable` && !isLastItem) {
6330
6365
  minimumWidth = context.getPageSize().width * 2;
6331
6366
  }
6332
- if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && isLastItem && itemStartOnNewScreen) {
6367
+ if (!isGloballyPrePaginated && item.renditionLayout === `reflowable` && isLastItem && itemStartOnNewScreen) {
6333
6368
  minimumWidth = context.getPageSize().width * 2;
6334
6369
  }
6335
6370
  const lastItemStartOnNewScreenInAPrepaginatedBook = itemStartOnNewScreen && isLastItem && isGloballyPrePaginated;
@@ -6417,7 +6452,7 @@ class SpineLayout extends DestroyableClass {
6417
6452
  this.itemLayoutInformation = [];
6418
6453
  this.layoutSubject = new Subject();
6419
6454
  spineItemsManager.items$.pipe(
6420
- switchMap((items) => {
6455
+ switchMap$1((items) => {
6421
6456
  const needsLayouts$ = items.map(
6422
6457
  (spineItem) => spineItem.needsLayout$.pipe(
6423
6458
  tap$1(() => {
@@ -6590,7 +6625,7 @@ class Spine extends DestroyableClass {
6590
6625
  this.hookManager = hookManager;
6591
6626
  this.elementSubject = new BehaviorSubject(noopElement());
6592
6627
  this.elementResize$ = this.elementSubject.pipe(
6593
- switchMap$1((element) => observeResize(element)),
6628
+ switchMap((element) => observeResize(element)),
6594
6629
  share$1()
6595
6630
  );
6596
6631
  this.element$ = this.elementSubject.asObservable();
@@ -7020,7 +7055,7 @@ const createResourcesManager = (context) => {
7020
7055
  return from(
7021
7056
  forkJoin([openDatabase(`prose-reader`), from(data.blob())])
7022
7057
  ).pipe(
7023
- switchMap$1(([db, blob]) => {
7058
+ switchMap(([db, blob]) => {
7024
7059
  return from(db.put(`${uniqueID}_${item.id}`, blob));
7025
7060
  }),
7026
7061
  catchError$1((error) => {
@@ -7037,15 +7072,15 @@ const createResourcesManager = (context) => {
7037
7072
  })
7038
7073
  );
7039
7074
  merge(onLoad$).pipe(
7040
- switchMap$1(() => {
7075
+ switchMap(() => {
7041
7076
  Report.log(`Cleanup up old cache...`);
7042
7077
  return from(openDatabase(`prose-reader`)).pipe(
7043
- switchMap$1(
7078
+ switchMap(
7044
7079
  (db) => from(db.keys()).pipe(
7045
7080
  map(
7046
7081
  (keys) => keys.filter((key) => !key.toString().startsWith(uniqueID))
7047
7082
  ),
7048
- switchMap$1((keysToRemove) => {
7083
+ switchMap((keysToRemove) => {
7049
7084
  const promises = keysToRemove.map((key) => db.remove(key));
7050
7085
  return from(Promise.all(promises));
7051
7086
  })
@@ -7093,7 +7128,7 @@ class ImageRenderer extends DocumentRenderer {
7093
7128
  }
7094
7129
  onCreateDocument() {
7095
7130
  return from(this.resourcesHandler.getResource()).pipe(
7096
- switchMap((responseOrUrl) => {
7131
+ switchMap$1((responseOrUrl) => {
7097
7132
  const imgElement = this.containerElement.ownerDocument.createElement(`img`);
7098
7133
  this.layers = [{ element: imgElement }];
7099
7134
  imgElement.style.objectFit = `contain`;
@@ -7162,6 +7197,9 @@ class ImageRenderer extends DocumentRenderer {
7162
7197
  onRenderHeadless() {
7163
7198
  return EMPTY;
7164
7199
  }
7200
+ getDocumentFrame() {
7201
+ return void 0;
7202
+ }
7165
7203
  }
7166
7204
  const mediaEnhancer = (next) => (options) => {
7167
7205
  const reader = next({
@@ -7227,10 +7265,10 @@ const mediaEnhancer = (next) => (options) => {
7227
7265
  );
7228
7266
  reader.hookManager.register(
7229
7267
  `item.onDocumentLoad`,
7230
- ({ layers, destroy: destroy2 }) => {
7268
+ ({ destroy: destroy2, itemId }) => {
7231
7269
  var _a, _b;
7232
- const frame = (_a = layers[0]) == null ? void 0 : _a.element;
7233
- if (!(frame instanceof HTMLIFrameElement)) return;
7270
+ const frame = (_a = reader.spineItemsManager.get(itemId)) == null ? void 0 : _a.renderer.getDocumentFrame();
7271
+ if (!frame) return;
7234
7272
  frameObserver.observe(frame);
7235
7273
  const videos = (_b = frame.contentDocument) == null ? void 0 : _b.body.getElementsByTagName(`video`);
7236
7274
  const unobserveElements = Array.from(videos || []).map((element) => {
@@ -7265,7 +7303,7 @@ const progressionEnhancer = (next) => (options) => {
7265
7303
  const estimateBeforeThisItem = ((_c = context.manifest) == null ? void 0 : _c.spineItems.slice(0, currentSpineIndex).reduce((acc, item) => acc + (item.progressionWeight ?? 0), 0)) || 0;
7266
7304
  const currentItemWeight = ((_e = (_d = context.manifest) == null ? void 0 : _d.spineItems[currentSpineIndex]) == null ? void 0 : _e.progressionWeight) || 0;
7267
7305
  let progressWithinThisItem = (pageIndex + 1) * (currentItemWeight / numberOfPages);
7268
- if (!isGloballyPrePaginated && currentItem.item.renditionLayout === `reflowable` && !itemIsReady) {
7306
+ if (!isGloballyPrePaginated && currentItem.renditionLayout === `reflowable` && !itemIsReady) {
7269
7307
  progressWithinThisItem = 0;
7270
7308
  }
7271
7309
  let totalProgress = estimateBeforeThisItem + progressWithinThisItem;
@@ -7337,31 +7375,27 @@ const accessibilityEnhancer = (next) => (options) => {
7337
7375
  }, {});
7338
7376
  reader.hookManager.register(
7339
7377
  `item.onDocumentLoad`,
7340
- ({ itemId, layers, destroy }) => {
7341
- var _a, _b;
7342
- const frame = (_a = layers[0]) == null ? void 0 : _a.element;
7343
- if (!(frame instanceof HTMLIFrameElement)) return;
7378
+ ({ itemId, destroy }) => {
7379
+ var _a;
7344
7380
  const item = reader.spineItemsManager.get(itemId);
7345
7381
  if (!item) return;
7346
- item.renderer.layers.forEach((layer) => {
7347
- if (layer.element instanceof HTMLIFrameElement) {
7348
- upsertCSS(
7349
- layer.element,
7350
- `prose-reader-accessibility`,
7351
- `
7382
+ const frame = item.renderer.getDocumentFrame();
7383
+ if (!frame) return;
7384
+ upsertCSS(
7385
+ frame,
7386
+ `prose-reader-accessibility`,
7387
+ `
7352
7388
  :focus-visible {
7353
7389
  ${/*
7354
- Some epubs remove the outline, this is not good practice since it reduce accessibility.
7355
- We will try to restore it by force.
7356
- */
7357
- ``}
7390
+ Some epubs remove the outline, this is not good practice since it reduce accessibility.
7391
+ We will try to restore it by force.
7392
+ */
7393
+ ``}
7358
7394
  outline: -webkit-focus-ring-color auto 1px;
7359
7395
  }
7360
7396
  `
7361
- );
7362
- }
7363
- });
7364
- const links = (_b = frame.contentDocument) == null ? void 0 : _b.body.querySelectorAll(`a`);
7397
+ );
7398
+ const links = (_a = frame.contentDocument) == null ? void 0 : _a.body.querySelectorAll(`a`);
7365
7399
  links == null ? void 0 : links.forEach((link) => {
7366
7400
  observer.observe(link);
7367
7401
  });
@@ -7481,12 +7515,12 @@ const loadingEnhancer = (next) => (options) => {
7481
7515
  })
7482
7516
  );
7483
7517
  const loadingItems$ = reader.spineItemsManager.items$.pipe(
7484
- switchMap$1((items) => createEntries$(items)),
7518
+ switchMap((items) => createEntries$(items)),
7485
7519
  shareReplay(1),
7486
7520
  takeUntil$1(reader.context.destroy$)
7487
7521
  );
7488
7522
  loadingItems$.pipe(
7489
- switchMap$1(
7523
+ switchMap(
7490
7524
  (entries) => merge(
7491
7525
  updateEntriesLayout$(entries),
7492
7526
  updateEntriesVisibility$(entries)
@@ -7527,11 +7561,11 @@ const translateFramePositionIntoPage = ({
7527
7561
  };
7528
7562
  };
7529
7563
  const normalizeEventForViewport = (event, iframeOriginalEvent, locator, context) => {
7530
- var _a, _b;
7564
+ var _a;
7531
7565
  const originalFrame = (_a = iframeOriginalEvent == null ? void 0 : iframeOriginalEvent.view) == null ? void 0 : _a.frameElement;
7532
7566
  if (!iframeOriginalEvent || !originalFrame) return event;
7533
7567
  const spineItem = locator.getSpineItemFromIframe(originalFrame);
7534
- const frameElement = (_b = spineItem == null ? void 0 : spineItem.renderer.layers[0]) == null ? void 0 : _b.element;
7568
+ const frameElement = originalFrame;
7535
7569
  const { height: pageHeight, width: pageWidth } = context.getPageSize();
7536
7570
  if (!spineItem || !(frameElement instanceof HTMLIFrameElement)) return event;
7537
7571
  if (isPointerEvent(event)) {
@@ -7617,18 +7651,14 @@ const eventsEnhancer = (next) => (options) => {
7617
7651
  const reader = next(options);
7618
7652
  reader.hookManager.register(
7619
7653
  `item.onDocumentLoad`,
7620
- ({ destroy, layers, itemId }) => {
7621
- var _a;
7622
- const frame = (_a = layers.find(
7623
- (layer) => layer.element instanceof HTMLIFrameElement
7624
- )) == null ? void 0 : _a.element;
7625
- if (!(frame instanceof HTMLIFrameElement)) return;
7654
+ ({ destroy, itemId }) => {
7626
7655
  const item = reader.spineItemsManager.get(itemId);
7627
- if (!item) return;
7656
+ const frame = item == null ? void 0 : item.renderer.getDocumentFrame();
7657
+ if (!frame || !item) return;
7628
7658
  const unregister = passthroughEvents.map((event) => {
7629
- var _a2;
7659
+ var _a;
7630
7660
  const listener = (e) => {
7631
- var _a3;
7661
+ var _a2;
7632
7662
  let convertedEvent = e;
7633
7663
  if (isPointerEvent(e)) {
7634
7664
  convertedEvent = new PointerEvent(e.type, e);
@@ -7640,15 +7670,15 @@ const eventsEnhancer = (next) => (options) => {
7640
7670
  reader.spine.locator,
7641
7671
  reader.context
7642
7672
  );
7643
- (_a3 = reader.context.state.containerElement) == null ? void 0 : _a3.dispatchEvent(
7673
+ (_a2 = reader.context.state.containerElement) == null ? void 0 : _a2.dispatchEvent(
7644
7674
  normalizedEvent
7645
7675
  );
7646
7676
  }
7647
7677
  };
7648
- (_a2 = frame.contentDocument) == null ? void 0 : _a2.addEventListener(event, listener);
7678
+ (_a = frame.contentDocument) == null ? void 0 : _a.addEventListener(event, listener);
7649
7679
  return () => {
7650
- var _a3;
7651
- (_a3 = frame.contentDocument) == null ? void 0 : _a3.removeEventListener(event, listener);
7680
+ var _a2;
7681
+ (_a2 = frame.contentDocument) == null ? void 0 : _a2.removeEventListener(event, listener);
7652
7682
  };
7653
7683
  });
7654
7684
  destroy(() => {
@@ -7702,7 +7732,7 @@ const createHtmlPageFromResource = async (resourceResponse, item) => {
7702
7732
  return `
7703
7733
  <html>
7704
7734
  <head>
7705
- ${item.renditionLayout !== `reflowable` ? `<meta name="viewport" content="width=${width}, height=${height}">` : ``}
7735
+ ${item.renditionLayout === `pre-paginated` ? `<meta name="viewport" content="width=${width}, height=${height}">` : ``}
7706
7736
  </head>
7707
7737
  <body style="margin: 0px;" tab-index="-1;">
7708
7738
  <img
@@ -7742,9 +7772,9 @@ const attachFrameSrc = ({
7742
7772
  }) => {
7743
7773
  const getHtmlFromResource = (response) => createHtmlPageFromResource(response, item);
7744
7774
  return (stream) => stream.pipe(
7745
- switchMap((frameElement) => {
7775
+ switchMap$1((frameElement) => {
7746
7776
  return from(resourcesHandler.getResource()).pipe(
7747
- switchMap((resource) => {
7777
+ switchMap$1((resource) => {
7748
7778
  if (resource instanceof URL && item.href.startsWith(window.location.origin) && // we have an encoding and it's a valid html
7749
7779
  (item.mediaType && [
7750
7780
  `application/xhtml+xml`,
@@ -7761,7 +7791,7 @@ const attachFrameSrc = ({
7761
7791
  const resourceResponse$ = resource instanceof URL ? from(resourcesHandler.fetchResource()) : resource instanceof Response ? of(resource) : EMPTY;
7762
7792
  return resourceResponse$.pipe(
7763
7793
  filter$1((response) => response instanceof Response),
7764
- switchMap((response) => from(getHtmlFromResource(response))),
7794
+ switchMap$1((response) => from(getHtmlFromResource(response))),
7765
7795
  tap$1((htmlDoc) => {
7766
7796
  if (htmlDoc) {
7767
7797
  const blob = new Blob([htmlDoc], { type: "text/html" });
@@ -8293,7 +8323,7 @@ const loadMedias = ({
8293
8323
  item,
8294
8324
  context
8295
8325
  }) => (stream) => stream.pipe(
8296
- switchMap((frameElement) => {
8326
+ switchMap$1((frameElement) => {
8297
8327
  var _a;
8298
8328
  const images = ((_a = frameElement.contentDocument) == null ? void 0 : _a.getElementsByTagName("img")) || [];
8299
8329
  const imageObservables = Array.from(images).map((img) => {
@@ -8383,12 +8413,12 @@ class HtmlRenderer extends DocumentRenderer {
8383
8413
  blankPagePosition,
8384
8414
  spreadPosition
8385
8415
  }) {
8386
- var _a;
8416
+ var _a, _b;
8387
8417
  const { width: pageWidth, height: pageHeight } = this.context.getPageSize();
8388
8418
  const frameElement = this.getFrameElement();
8389
- if (!frameElement) return of({ width: pageWidth, height: pageHeight });
8419
+ if (!frameElement) return of(void 0);
8390
8420
  const isUsingVerticalWriting = !!((_a = this.writingMode) == null ? void 0 : _a.startsWith(`vertical`));
8391
- if (this.item.renditionLayout === `pre-paginated`) {
8421
+ if (this.item.renditionLayout === `pre-paginated` || !this.item.renditionLayout && ((_b = this.context.manifest) == null ? void 0 : _b.renditionLayout) === `pre-paginated`) {
8392
8422
  const dims = renderPrePaginated({
8393
8423
  blankPagePosition,
8394
8424
  enableTouch: this.settings.values.computedPageTurnMode !== `scrollable`,
@@ -8419,7 +8449,7 @@ class HtmlRenderer extends DocumentRenderer {
8419
8449
  }
8420
8450
  onRenderHeadless() {
8421
8451
  return from(this.resourcesHandler.fetchResource()).pipe(
8422
- switchMap((resource) => {
8452
+ switchMap$1((resource) => {
8423
8453
  if (resource instanceof Response) {
8424
8454
  const contentType = resource.headers.get("content-type") ?? "";
8425
8455
  const parsableContentTypes = [
@@ -8483,6 +8513,9 @@ class HtmlRenderer extends DocumentRenderer {
8483
8513
  return void 0;
8484
8514
  }
8485
8515
  }
8516
+ getDocumentFrame() {
8517
+ return this.getFrameElement();
8518
+ }
8486
8519
  }
8487
8520
  const htmlEnhancer = (next) => (options) => {
8488
8521
  const reader = next({
@@ -8570,12 +8603,13 @@ const selectionEnhancer = (next) => (options) => {
8570
8603
  const selectionWithPointerUpSubject = new Subject();
8571
8604
  reader.hookManager.register(
8572
8605
  `item.onDocumentLoad`,
8573
- ({ itemId, layers, destroy$, destroy }) => {
8574
- var _a, _b;
8575
- const frame = (_a = layers[0]) == null ? void 0 : _a.element;
8606
+ ({ itemId, destroy$, destroy }) => {
8607
+ var _a;
8608
+ const item = reader.spineItemsManager.get(itemId);
8609
+ const frame = item == null ? void 0 : item.renderer.getDocumentFrame();
8576
8610
  const itemIndex = reader.spineItemsManager.getSpineItemIndex(itemId) ?? 0;
8577
- if (frame instanceof HTMLIFrameElement) {
8578
- const frameDoc = frame.contentDocument || ((_b = frame.contentWindow) == null ? void 0 : _b.document);
8611
+ if (frame) {
8612
+ const frameDoc = frame.contentDocument || ((_a = frame.contentWindow) == null ? void 0 : _a.document);
8579
8613
  if (frameDoc) {
8580
8614
  const selectionTracker = new SelectionTracker(frameDoc);
8581
8615
  merge(
@@ -8624,14 +8658,14 @@ const selectionEnhancer = (next) => (options) => {
8624
8658
  share()
8625
8659
  );
8626
8660
  const selectionEnd$ = selectionStart$.pipe(
8627
- switchMap(() => selection$),
8661
+ switchMap$1(() => selection$),
8628
8662
  distinctUntilChanged$1(),
8629
8663
  filter$1((selection) => !selection),
8630
8664
  share()
8631
8665
  );
8632
8666
  const selectionAfterPointerUp$ = selectionWithPointerUpSubject.asObservable();
8633
8667
  const lastSelectionOnPointerdown$ = reader.context.containerElement$.pipe(
8634
- switchMap((container) => fromEvent(container, "pointerdown")),
8668
+ switchMap$1((container) => fromEvent(container, "pointerdown")),
8635
8669
  withLatestFrom(selection$),
8636
8670
  map$1(([, selection]) => selection),
8637
8671
  startWith$1(void 0),