@d-i-t-a/reader 3.0.0-alpha.8 → 3.0.0-alpha.9

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 (37) hide show
  1. package/dist/esm/index.js +576 -297
  2. package/dist/esm/index.js.map +4 -4
  3. package/dist/injectables/style/mo.css +42 -0
  4. package/dist/reader.js +51 -51
  5. package/dist/reader.js.map +4 -4
  6. package/dist/types/index.d.ts +4 -1
  7. package/dist/types/model/user-settings/UserSettings.d.ts +1 -1
  8. package/dist/types/model/v3/Publication.d.ts +1 -1
  9. package/dist/types/modules/AnnotationModule.d.ts +3 -3
  10. package/dist/types/modules/BookmarkModule.d.ts +3 -3
  11. package/dist/types/modules/TTS/TTSModule2.d.ts +2 -2
  12. package/dist/types/modules/TTS/TTSSettings.d.ts +1 -1
  13. package/dist/types/modules/citation/CitationModule.d.ts +2 -2
  14. package/dist/types/modules/consumption/ConsumptionModule.d.ts +2 -2
  15. package/dist/types/modules/highlight/TextHighlighter.d.ts +2 -2
  16. package/dist/types/modules/history/HistoryModule.d.ts +2 -2
  17. package/dist/types/modules/linefocus/LineFocusModule.d.ts +2 -2
  18. package/dist/types/modules/mediaoverlays/MediaOverlayModule.d.ts +3 -3
  19. package/dist/types/modules/pagebreak/PageBreakModule.d.ts +2 -2
  20. package/dist/types/modules/positions/TimelineModule.d.ts +2 -2
  21. package/dist/types/modules/protection/ContentProtectionModule.d.ts +2 -2
  22. package/dist/types/modules/sampleread/SampleReadEventHandler.d.ts +3 -3
  23. package/dist/types/modules/search/DefinitionsModule.d.ts +2 -2
  24. package/dist/types/modules/search/Popup.d.ts +3 -3
  25. package/dist/types/modules/search/SearchModule.d.ts +2 -2
  26. package/dist/types/navigator/{IFrameNavigator.d.ts → EpubNavigator.d.ts} +29 -9
  27. package/dist/types/navigator/Navigator.d.ts +8 -8
  28. package/dist/types/navigator/PDFNavigator.d.ts +6 -6
  29. package/dist/types/navigator/VisualNavigator.d.ts +91 -0
  30. package/dist/types/reader.d.ts +11 -11
  31. package/dist/types/utils/EventHandler.d.ts +3 -3
  32. package/dist/types/utils/KeyboardEventHandler.d.ts +3 -3
  33. package/dist/types/utils/TouchEventHandler.d.ts +3 -3
  34. package/dist/types/views/BookView.d.ts +14 -2
  35. package/dist/types/views/FixedBookView.d.ts +3 -3
  36. package/dist/types/views/ReflowableBookView.d.ts +3 -3
  37. package/package.json +1 -1
package/dist/esm/index.js CHANGED
@@ -29944,24 +29944,6 @@ var require_jscrypto = __commonJS({
29944
29944
  }
29945
29945
  });
29946
29946
 
29947
- // src/utils/HTMLTemplates.ts
29948
- var readerLoading, readerError;
29949
- var init_HTMLTemplates = __esm({
29950
- "src/utils/HTMLTemplates.ts"() {
29951
- init_polyfills();
29952
- init_IconLib();
29953
- readerLoading = `${icons.loading}`;
29954
- readerError = `
29955
- <span>
29956
- ${icons.error}
29957
- </span>
29958
- <span>There was an error loading this page.</span>
29959
- <button class="go-back">Go back</button>
29960
- <button class="try-again">Try again</button>
29961
- `;
29962
- }
29963
- });
29964
-
29965
29947
  // node_modules/eventemitter3/index.js
29966
29948
  var require_eventemitter3 = __commonJS({
29967
29949
  "node_modules/eventemitter3/index.js"(exports, module) {
@@ -30135,6 +30117,264 @@ var init_eventemitter3 = __esm({
30135
30117
  }
30136
30118
  });
30137
30119
 
30120
+ // src/navigator/VisualNavigator.ts
30121
+ var NavigatorFeature, VisualNavigator;
30122
+ var init_VisualNavigator = __esm({
30123
+ "src/navigator/VisualNavigator.ts"() {
30124
+ init_polyfills();
30125
+ init_eventemitter3();
30126
+ NavigatorFeature = {
30127
+ TTS: "tts",
30128
+ MediaOverlays: "mediaOverlays",
30129
+ Search: "search",
30130
+ Annotations: "annotations",
30131
+ Bookmarks: "bookmarks",
30132
+ Zoom: "zoom",
30133
+ LineFocus: "lineFocus",
30134
+ Definitions: "definitions",
30135
+ Citations: "citations",
30136
+ ContentProtection: "contentProtection",
30137
+ Consumption: "consumption",
30138
+ History: "history",
30139
+ Timeline: "timeline"
30140
+ };
30141
+ VisualNavigator = class extends eventemitter3_default {
30142
+ // ── Capability query ──────────────────────────────────────────
30143
+ /**
30144
+ * Check if this navigator supports a given feature.
30145
+ * Replaces instanceof checks in D2Reader.
30146
+ */
30147
+ supports(_feature) {
30148
+ return false;
30149
+ }
30150
+ // ── Default no-ops for optional features ──────────────────────
30151
+ // Subclasses override what they support. D2Reader calls these
30152
+ // without instanceof checks — if the navigator doesn't support
30153
+ // the feature, the no-op runs silently.
30154
+ startReadAloud() {
30155
+ }
30156
+ stopReadAloud() {
30157
+ }
30158
+ pauseReadAloud() {
30159
+ }
30160
+ resumeReadAloud() {
30161
+ }
30162
+ startReadAlong() {
30163
+ }
30164
+ stopReadAlong() {
30165
+ }
30166
+ pauseReadAlong() {
30167
+ }
30168
+ resumeReadAlong() {
30169
+ }
30170
+ hideLayer(_layer) {
30171
+ }
30172
+ showLayer(_layer) {
30173
+ }
30174
+ activateMarker(_id, _position) {
30175
+ }
30176
+ deactivateMarker() {
30177
+ }
30178
+ snapToSelector(_selector) {
30179
+ }
30180
+ applyAttributes(_value) {
30181
+ }
30182
+ mostRecentNavigatedTocItem() {
30183
+ return void 0;
30184
+ }
30185
+ // ── RTL-aware navigation ──────────────────────────────────────
30186
+ /**
30187
+ * Navigate left — respects reading progression direction.
30188
+ * In LTR: goes to previous page. In RTL: goes to next page.
30189
+ */
30190
+ goLeft() {
30191
+ const rtl = this.publication.metadata?.readingProgression === "rtl" || this.publication.metadata?.otherMetadata?.["rendition:spread-direction"] === "rtl";
30192
+ if (rtl) {
30193
+ this.nextPage();
30194
+ } else {
30195
+ this.previousPage();
30196
+ }
30197
+ }
30198
+ /**
30199
+ * Navigate right — respects reading progression direction.
30200
+ * In LTR: goes to next page. In RTL: goes to previous page.
30201
+ */
30202
+ goRight() {
30203
+ const rtl = this.publication.metadata?.readingProgression === "rtl" || this.publication.metadata?.otherMetadata?.["rendition:spread-direction"] === "rtl";
30204
+ if (rtl) {
30205
+ this.previousPage();
30206
+ } else {
30207
+ this.nextPage();
30208
+ }
30209
+ }
30210
+ // ── Zoom (for FXL and PDF) ────────────────────────────────────
30211
+ // Default no-ops. PDFNavigator and EpubNavigator (FXL) override.
30212
+ fitToPage() {
30213
+ }
30214
+ fitToWidth() {
30215
+ }
30216
+ zoomIn() {
30217
+ }
30218
+ zoomOut() {
30219
+ }
30220
+ activateHand() {
30221
+ }
30222
+ deactivateHand() {
30223
+ }
30224
+ };
30225
+ }
30226
+ });
30227
+
30228
+ // src/utils/HTMLTemplates.ts
30229
+ var readerLoading, readerError;
30230
+ var init_HTMLTemplates = __esm({
30231
+ "src/utils/HTMLTemplates.ts"() {
30232
+ init_polyfills();
30233
+ init_IconLib();
30234
+ readerLoading = `${icons.loading}`;
30235
+ readerError = `
30236
+ <span>
30237
+ ${icons.error}
30238
+ </span>
30239
+ <span>There was an error loading this page.</span>
30240
+ <button class="go-back">Go back</button>
30241
+ <button class="try-again">Try again</button>
30242
+ `;
30243
+ }
30244
+ });
30245
+
30246
+ // src/utils/GrabToPan.ts
30247
+ var CSS_CLASS_GRAB, GrabToPan;
30248
+ var init_GrabToPan = __esm({
30249
+ "src/utils/GrabToPan.ts"() {
30250
+ init_polyfills();
30251
+ CSS_CLASS_GRAB = "grab-to-pan-grab";
30252
+ GrabToPan = class {
30253
+ /**
30254
+ * Construct a GrabToPan instance for a given HTML element.
30255
+ * @param {Element} options.element
30256
+ * @param {function} [options.ignoreTarget] - See `ignoreTarget(node)`.
30257
+ * @param {function(boolean)} [options.onActiveChanged] - Called when
30258
+ * grab-to-pan is (de)activated. The first argument is a boolean that
30259
+ * shows whether grab-to-pan is activated.
30260
+ */
30261
+ constructor(options) {
30262
+ this.element = options.element;
30263
+ this.document = options.element.ownerDocument;
30264
+ if (typeof options.ignoreTarget === "function") {
30265
+ this.ignoreTarget = options.ignoreTarget;
30266
+ }
30267
+ this.onActiveChanged = options.onActiveChanged;
30268
+ this.activate = this.activate.bind(this);
30269
+ this.deactivate = this.deactivate.bind(this);
30270
+ this.toggle = this.toggle.bind(this);
30271
+ this._onMouseDown = this.#onMouseDown.bind(this);
30272
+ this._onMouseMove = this.#onMouseMove.bind(this);
30273
+ this._endPan = this.#endPan.bind(this);
30274
+ const overlay = this.overlay = document.createElement("div");
30275
+ overlay.className = "grab-to-pan-grabbing";
30276
+ }
30277
+ /**
30278
+ * Bind a mousedown event to the element to enable grab-detection.
30279
+ */
30280
+ activate() {
30281
+ if (!this.active) {
30282
+ this.active = true;
30283
+ this.element.addEventListener("mousedown", this._onMouseDown, true);
30284
+ this.element.classList.add(CSS_CLASS_GRAB);
30285
+ this.onActiveChanged?.(true);
30286
+ }
30287
+ }
30288
+ /**
30289
+ * Removes all events. Any pending pan session is immediately stopped.
30290
+ */
30291
+ deactivate() {
30292
+ if (this.active) {
30293
+ this.active = false;
30294
+ this.element.removeEventListener("mousedown", this._onMouseDown, true);
30295
+ this._endPan();
30296
+ this.element.classList.remove(CSS_CLASS_GRAB);
30297
+ this.onActiveChanged?.(false);
30298
+ }
30299
+ }
30300
+ toggle() {
30301
+ if (this.active) {
30302
+ this.deactivate();
30303
+ } else {
30304
+ this.activate();
30305
+ }
30306
+ }
30307
+ /**
30308
+ * Whether to not pan if the target element is clicked.
30309
+ * Override this method to change the default behaviour.
30310
+ *
30311
+ * @param {Element} node - The target of the event.
30312
+ * @returns {boolean} Whether to not react to the click event.
30313
+ */
30314
+ ignoreTarget(node) {
30315
+ return node.matches(
30316
+ "a[href], a[href] *, input, textarea, button, button *, select, option"
30317
+ );
30318
+ }
30319
+ #onMouseDown(event) {
30320
+ if (event.button !== 0 || this.ignoreTarget(event.target)) {
30321
+ return;
30322
+ }
30323
+ if (event.originalTarget) {
30324
+ try {
30325
+ event.originalTarget.tagName;
30326
+ } catch (e7) {
30327
+ return;
30328
+ }
30329
+ }
30330
+ this.scrollLeftStart = this.element.scrollLeft;
30331
+ this.scrollTopStart = this.element.scrollTop;
30332
+ this.clientXStart = event.clientX;
30333
+ this.clientYStart = event.clientY;
30334
+ this.document.addEventListener("mousemove", this._onMouseMove, true);
30335
+ this.document.addEventListener("mouseup", this._endPan, true);
30336
+ this.element.addEventListener("scroll", this._endPan, true);
30337
+ event.preventDefault();
30338
+ event.stopPropagation();
30339
+ const focusedElement = document.activeElement;
30340
+ if (focusedElement && !focusedElement.contains(event.target)) {
30341
+ focusedElement.blur();
30342
+ }
30343
+ }
30344
+ #onMouseMove(event) {
30345
+ this.element.removeEventListener("scroll", this._endPan, true);
30346
+ if (!(event.buttons & 1)) {
30347
+ this._endPan();
30348
+ return;
30349
+ }
30350
+ const xDiff = event.clientX - this.clientXStart;
30351
+ const yDiff = event.clientY - this.clientYStart;
30352
+ const scrollTop = this.scrollTopStart - yDiff;
30353
+ const scrollLeft = this.scrollLeftStart - xDiff;
30354
+ if (this.element.scrollTo) {
30355
+ this.element.scrollTo({
30356
+ top: scrollTop,
30357
+ left: scrollLeft,
30358
+ behavior: "instant"
30359
+ });
30360
+ } else {
30361
+ this.element.scrollTop = scrollTop;
30362
+ this.element.scrollLeft = scrollLeft;
30363
+ }
30364
+ if (!this.overlay.parentNode) {
30365
+ document.body.append(this.overlay);
30366
+ }
30367
+ }
30368
+ #endPan() {
30369
+ this.element.removeEventListener("scroll", this._endPan, true);
30370
+ this.document.removeEventListener("mousemove", this._onMouseMove, true);
30371
+ this.document.removeEventListener("mouseup", this._endPan, true);
30372
+ this.overlay.remove();
30373
+ }
30374
+ };
30375
+ }
30376
+ });
30377
+
30138
30378
  // node_modules/pdfjs-dist/build/pdf.mjs
30139
30379
  function setVerbosityLevel(level) {
30140
30380
  if (Number.isInteger(level)) {
@@ -65271,138 +65511,6 @@ var init_pdf_viewer = __esm({
65271
65511
  }
65272
65512
  });
65273
65513
 
65274
- // src/utils/GrabToPan.ts
65275
- var CSS_CLASS_GRAB, GrabToPan;
65276
- var init_GrabToPan = __esm({
65277
- "src/utils/GrabToPan.ts"() {
65278
- init_polyfills();
65279
- CSS_CLASS_GRAB = "grab-to-pan-grab";
65280
- GrabToPan = class {
65281
- /**
65282
- * Construct a GrabToPan instance for a given HTML element.
65283
- * @param {Element} options.element
65284
- * @param {function} [options.ignoreTarget] - See `ignoreTarget(node)`.
65285
- * @param {function(boolean)} [options.onActiveChanged] - Called when
65286
- * grab-to-pan is (de)activated. The first argument is a boolean that
65287
- * shows whether grab-to-pan is activated.
65288
- */
65289
- constructor(options) {
65290
- this.element = options.element;
65291
- this.document = options.element.ownerDocument;
65292
- if (typeof options.ignoreTarget === "function") {
65293
- this.ignoreTarget = options.ignoreTarget;
65294
- }
65295
- this.onActiveChanged = options.onActiveChanged;
65296
- this.activate = this.activate.bind(this);
65297
- this.deactivate = this.deactivate.bind(this);
65298
- this.toggle = this.toggle.bind(this);
65299
- this._onMouseDown = this.#onMouseDown.bind(this);
65300
- this._onMouseMove = this.#onMouseMove.bind(this);
65301
- this._endPan = this.#endPan.bind(this);
65302
- const overlay = this.overlay = document.createElement("div");
65303
- overlay.className = "grab-to-pan-grabbing";
65304
- }
65305
- /**
65306
- * Bind a mousedown event to the element to enable grab-detection.
65307
- */
65308
- activate() {
65309
- if (!this.active) {
65310
- this.active = true;
65311
- this.element.addEventListener("mousedown", this._onMouseDown, true);
65312
- this.element.classList.add(CSS_CLASS_GRAB);
65313
- this.onActiveChanged?.(true);
65314
- }
65315
- }
65316
- /**
65317
- * Removes all events. Any pending pan session is immediately stopped.
65318
- */
65319
- deactivate() {
65320
- if (this.active) {
65321
- this.active = false;
65322
- this.element.removeEventListener("mousedown", this._onMouseDown, true);
65323
- this._endPan();
65324
- this.element.classList.remove(CSS_CLASS_GRAB);
65325
- this.onActiveChanged?.(false);
65326
- }
65327
- }
65328
- toggle() {
65329
- if (this.active) {
65330
- this.deactivate();
65331
- } else {
65332
- this.activate();
65333
- }
65334
- }
65335
- /**
65336
- * Whether to not pan if the target element is clicked.
65337
- * Override this method to change the default behaviour.
65338
- *
65339
- * @param {Element} node - The target of the event.
65340
- * @returns {boolean} Whether to not react to the click event.
65341
- */
65342
- ignoreTarget(node) {
65343
- return node.matches(
65344
- "a[href], a[href] *, input, textarea, button, button *, select, option"
65345
- );
65346
- }
65347
- #onMouseDown(event) {
65348
- if (event.button !== 0 || this.ignoreTarget(event.target)) {
65349
- return;
65350
- }
65351
- if (event.originalTarget) {
65352
- try {
65353
- event.originalTarget.tagName;
65354
- } catch (e7) {
65355
- return;
65356
- }
65357
- }
65358
- this.scrollLeftStart = this.element.scrollLeft;
65359
- this.scrollTopStart = this.element.scrollTop;
65360
- this.clientXStart = event.clientX;
65361
- this.clientYStart = event.clientY;
65362
- this.document.addEventListener("mousemove", this._onMouseMove, true);
65363
- this.document.addEventListener("mouseup", this._endPan, true);
65364
- this.element.addEventListener("scroll", this._endPan, true);
65365
- event.preventDefault();
65366
- event.stopPropagation();
65367
- const focusedElement = document.activeElement;
65368
- if (focusedElement && !focusedElement.contains(event.target)) {
65369
- focusedElement.blur();
65370
- }
65371
- }
65372
- #onMouseMove(event) {
65373
- this.element.removeEventListener("scroll", this._endPan, true);
65374
- if (!(event.buttons & 1)) {
65375
- this._endPan();
65376
- return;
65377
- }
65378
- const xDiff = event.clientX - this.clientXStart;
65379
- const yDiff = event.clientY - this.clientYStart;
65380
- const scrollTop = this.scrollTopStart - yDiff;
65381
- const scrollLeft = this.scrollLeftStart - xDiff;
65382
- if (this.element.scrollTo) {
65383
- this.element.scrollTo({
65384
- top: scrollTop,
65385
- left: scrollLeft,
65386
- behavior: "instant"
65387
- });
65388
- } else {
65389
- this.element.scrollTop = scrollTop;
65390
- this.element.scrollLeft = scrollLeft;
65391
- }
65392
- if (!this.overlay.parentNode) {
65393
- document.body.append(this.overlay);
65394
- }
65395
- }
65396
- #endPan() {
65397
- this.element.removeEventListener("scroll", this._endPan, true);
65398
- this.document.removeEventListener("mousemove", this._onMouseMove, true);
65399
- this.document.removeEventListener("mouseup", this._endPan, true);
65400
- this.overlay.remove();
65401
- }
65402
- };
65403
- }
65404
- });
65405
-
65406
65514
  // src/navigator/PDFNavigator.ts
65407
65515
  var PDFNavigator_exports = {};
65408
65516
  __export(PDFNavigator_exports, {
@@ -65417,7 +65525,7 @@ var init_PDFNavigator = __esm({
65417
65525
  "src/navigator/PDFNavigator.ts"() {
65418
65526
  init_polyfills();
65419
65527
  import_debounce8 = __toESM(require_debounce());
65420
- init_eventemitter3();
65528
+ init_VisualNavigator();
65421
65529
  init_Events();
65422
65530
  init_pdf();
65423
65531
  init_pdf_viewer();
@@ -65430,7 +65538,7 @@ var init_PDFNavigator = __esm({
65430
65538
  ScaleType2[ScaleType2["Width"] = 1] = "Width";
65431
65539
  return ScaleType2;
65432
65540
  })(ScaleType || {});
65433
- _PDFNavigator = class _PDFNavigator extends eventemitter3_default {
65541
+ _PDFNavigator = class _PDFNavigator extends VisualNavigator {
65434
65542
  constructor(settings, publication, api, workerSrc, annotator, initialLastReadingPosition, viewStore) {
65435
65543
  super();
65436
65544
  this.isPDF = true;
@@ -65459,6 +65567,20 @@ var init_PDFNavigator = __esm({
65459
65567
  this.initialLastReadingPosition = initialLastReadingPosition;
65460
65568
  this.viewStore = viewStore;
65461
65569
  }
65570
+ supports(feature) {
65571
+ switch (feature) {
65572
+ case NavigatorFeature.Search:
65573
+ return true;
65574
+ case NavigatorFeature.Annotations:
65575
+ return true;
65576
+ case NavigatorFeature.Zoom:
65577
+ return true;
65578
+ case NavigatorFeature.Bookmarks:
65579
+ return true;
65580
+ default:
65581
+ return false;
65582
+ }
65583
+ }
65462
65584
  // ── Factory ────────────────────────────────────────────────────────────────
65463
65585
  static async create(config2) {
65464
65586
  const nav = new this(
@@ -69324,6 +69446,8 @@ var ReflowableBookView = class {
69324
69446
  if (html) {
69325
69447
  html.style.setProperty("--USER__scroll", "readium-scroll-on");
69326
69448
  }
69449
+ const spacer = doc.getElementById("r2d2bc-column-spacer");
69450
+ if (spacer) spacer.remove();
69327
69451
  }
69328
69452
  this.setSize();
69329
69453
  this.setIframeHeight(this.iframe);
@@ -69345,8 +69469,8 @@ var ReflowableBookView = class {
69345
69469
  this.setSize();
69346
69470
  this.padOddColumns();
69347
69471
  }
69348
- if (this.navigator.rights.enableContentProtection) {
69349
- this.navigator.contentProtectionModule?.recalculate();
69472
+ if (this.host.isContentProtectionEnabled()) {
69473
+ this.host.recalculateContentProtection();
69350
69474
  }
69351
69475
  }
69352
69476
  start() {
@@ -69454,8 +69578,8 @@ var ReflowableBookView = class {
69454
69578
  let roundedLeftWidth = Math.floor(left / width) * width;
69455
69579
  element.style.height = originalHeight;
69456
69580
  this.setLeftColumnsWidth(roundedLeftWidth);
69457
- if (this.navigator.rights.enableContentProtection) {
69458
- this.navigator.contentProtectionModule?.recalculate(0);
69581
+ if (this.host.isContentProtectionEnabled()) {
69582
+ this.host.recalculateContentProtection(0);
69459
69583
  }
69460
69584
  }
69461
69585
  }
@@ -69479,8 +69603,8 @@ var ReflowableBookView = class {
69479
69603
  }
69480
69604
  element.style.height = originalHeight;
69481
69605
  this.setLeftColumnsWidth(roundedLeftWidth);
69482
- if (this.navigator.rights.enableContentProtection) {
69483
- this.navigator.contentProtectionModule?.recalculate(200);
69606
+ if (this.host.isContentProtectionEnabled()) {
69607
+ this.host.recalculateContentProtection(200);
69484
69608
  }
69485
69609
  }
69486
69610
  }
@@ -69537,10 +69661,10 @@ var ReflowableBookView = class {
69537
69661
  } else {
69538
69662
  this.setLeftColumnsWidth(0);
69539
69663
  }
69540
- this.navigator.checkResourcePosition();
69664
+ this.host.checkResourcePosition();
69541
69665
  }
69542
- if (this.navigator.rights.enableContentProtection) {
69543
- this.navigator.contentProtectionModule?.recalculate();
69666
+ if (this.host.isContentProtectionEnabled()) {
69667
+ this.host.recalculateContentProtection();
69544
69668
  }
69545
69669
  }
69546
69670
  goToNextPage() {
@@ -69568,10 +69692,10 @@ var ReflowableBookView = class {
69568
69692
  } else {
69569
69693
  this.setLeftColumnsWidth(scrollWidth);
69570
69694
  }
69571
- this.navigator.checkResourcePosition();
69695
+ this.host.checkResourcePosition();
69572
69696
  }
69573
- if (this.navigator.rights.enableContentProtection) {
69574
- this.navigator.contentProtectionModule?.recalculate();
69697
+ if (this.host.isContentProtectionEnabled()) {
69698
+ this.host.recalculateContentProtection();
69575
69699
  }
69576
69700
  }
69577
69701
  // doesn't exist in scroll mode
@@ -70217,7 +70341,7 @@ var _UserSettings = class _UserSettings {
70217
70341
  if (html) {
70218
70342
  const rootElement = findElement(document, "#root") || document.documentElement;
70219
70343
  const body = findElement(html, "body");
70220
- if (this.view?.navigator.publication.isReflowable) {
70344
+ if (this.view?.host?.isReflowable()) {
70221
70345
  if (await this.getProperty(ReadiumCSS.FONT_SIZE_KEY)) {
70222
70346
  html.style.setProperty(
70223
70347
  ReadiumCSS.FONT_SIZE_KEY,
@@ -70243,7 +70367,7 @@ var _UserSettings = class _UserSettings {
70243
70367
  this.userProperties.getByRef(ReadiumCSS.COLUMN_COUNT_REF)?.toString() ?? null
70244
70368
  );
70245
70369
  }
70246
- if (this.view?.navigator.publication.isReflowable) {
70370
+ if (this.view?.host?.isReflowable()) {
70247
70371
  if (await this.getProperty(ReadiumCSS.TEXT_ALIGNMENT_KEY)) {
70248
70372
  if (this.userProperties.getByRef(ReadiumCSS.TEXT_ALIGNMENT_REF)?.toString() === "auto") {
70249
70373
  html.style.removeProperty(ReadiumCSS.TEXT_ALIGNMENT_KEY);
@@ -70330,14 +70454,14 @@ var _UserSettings = class _UserSettings {
70330
70454
  setAttr(rootElement, "data-viewer-theme", "day");
70331
70455
  if (body) setAttr(body, "data-viewer-theme", "day");
70332
70456
  }
70333
- if (this.view?.navigator.publication.isFixedLayout) {
70457
+ if (this.view?.host?.isFixedLayout()) {
70334
70458
  if (await this.getProperty(ReadiumCSS.DIRECTION_KEY)) {
70335
70459
  let value = this.userProperties.getByRef(ReadiumCSS.DIRECTION_REF)?.toString() ?? null;
70336
70460
  html.style.setProperty(ReadiumCSS.DIRECTION_KEY, value);
70337
- this.view.navigator.setDirection(value);
70461
+ this.view.host?.setDirection(value);
70338
70462
  }
70339
70463
  }
70340
- if (this.view?.navigator.publication.isReflowable) {
70464
+ if (this.view?.host?.isReflowable()) {
70341
70465
  if (await this.getProperty(ReadiumCSS.FONT_FAMILY_KEY)) {
70342
70466
  html.style.setProperty(
70343
70467
  ReadiumCSS.FONT_FAMILY_KEY,
@@ -81969,8 +82093,9 @@ var TTSSettings = class {
81969
82093
  }
81970
82094
  };
81971
82095
 
81972
- // src/navigator/IFrameNavigator.ts
82096
+ // src/navigator/EpubNavigator.ts
81973
82097
  init_polyfills();
82098
+ init_VisualNavigator();
81974
82099
  init_Events();
81975
82100
  init_EventHandler();
81976
82101
  init_HTMLUtilities();
@@ -83637,9 +83762,6 @@ var DefinitionsModule = class {
83637
83762
  }
83638
83763
  };
83639
83764
 
83640
- // src/navigator/IFrameNavigator.ts
83641
- init_eventemitter3();
83642
-
83643
83765
  // src/modules/linefocus/LineFocusModule.ts
83644
83766
  init_polyfills();
83645
83767
  init_HTMLUtilities();
@@ -84627,12 +84749,31 @@ var CitationModule = class {
84627
84749
  }
84628
84750
  };
84629
84751
 
84630
- // src/navigator/IFrameNavigator.ts
84752
+ // src/navigator/EpubNavigator.ts
84631
84753
  var import_loglevel23 = __toESM(require_loglevel());
84632
- var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84754
+ init_GrabToPan();
84755
+ var EpubNavigator = class _EpubNavigator extends VisualNavigator {
84633
84756
  constructor(settings, annotator = void 0, initialLastReadingPosition = void 0, publication, api, rights, tts, injectables, attributes, services, sample, requestConfig, highlighter, modules) {
84634
84757
  super();
84635
84758
  this.iframes = [];
84759
+ // ── FXL zoom ────────────────────────────────────────────────
84760
+ this.fxlZoomKeyHandler = (event) => {
84761
+ if (/input|select|option|textarea/i.test(
84762
+ event.target.tagName
84763
+ ))
84764
+ return;
84765
+ const key = event.key;
84766
+ if (key === "=" || key === "+") {
84767
+ this.zoomIn();
84768
+ } else if (key === "-") {
84769
+ this.zoomOut();
84770
+ } else if (key === "0") {
84771
+ this.fitToPage();
84772
+ } else {
84773
+ return;
84774
+ }
84775
+ event.preventDefault();
84776
+ };
84636
84777
  this.sideNavExpanded = false;
84637
84778
  this.currentChapterLink = { href: "" };
84638
84779
  this.currentSpreadLinks = {};
@@ -84653,6 +84794,8 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84653
84794
  enableCitations: false
84654
84795
  };
84655
84796
  this.didInitKeyboardEventHandler = false;
84797
+ this.fxlContentWidth = 0;
84798
+ this.fxlContentHeight = 0;
84656
84799
  this.onResize = () => {
84657
84800
  clearTimeout(this.timeout);
84658
84801
  this.timeout = setTimeout(this.handleResize.bind(this), 200);
@@ -84734,7 +84877,14 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84734
84877
  this.annotator = annotator;
84735
84878
  this.view = settings.view;
84736
84879
  this.view.attributes = attributes;
84737
- this.view.navigator = this;
84880
+ this.view.host = {
84881
+ checkResourcePosition: () => this.checkResourcePosition(),
84882
+ recalculateContentProtection: (delay2) => this.contentProtectionModule?.recalculate(delay2),
84883
+ isContentProtectionEnabled: () => !!this.rights.enableContentProtection,
84884
+ isFixedLayout: () => this.publication.isFixedLayout,
84885
+ isReflowable: () => this.publication.isReflowable,
84886
+ setDirection: (direction) => this.setDirection(direction)
84887
+ };
84738
84888
  this.eventHandler = new EventHandler(this);
84739
84889
  this.touchEventHandler = new TouchEventHandler(this);
84740
84890
  this.keyboardEventHandler = new KeyboardEventHandler(this);
@@ -84765,6 +84915,117 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84765
84915
  this.requestConfig = requestConfig;
84766
84916
  this.sampleReadEventHandler = new SampleReadEventHandler(this);
84767
84917
  }
84918
+ supports(feature) {
84919
+ switch (feature) {
84920
+ case NavigatorFeature.TTS:
84921
+ return !!this.rights.enableTTS && !!this.ttsModule;
84922
+ case NavigatorFeature.MediaOverlays:
84923
+ return !!this.rights.enableMediaOverlays && !!this.mediaOverlayModule && this.hasMediaOverlays;
84924
+ case NavigatorFeature.Search:
84925
+ return !!this.rights.enableSearch && !!this.searchModule;
84926
+ case NavigatorFeature.Annotations:
84927
+ return !!this.rights.enableAnnotations && !!this.annotationModule;
84928
+ case NavigatorFeature.Bookmarks:
84929
+ return !!this.rights.enableBookmarks && !!this.bookmarkModule;
84930
+ case NavigatorFeature.Zoom:
84931
+ return this.publication.isFixedLayout;
84932
+ case NavigatorFeature.LineFocus:
84933
+ return !!this.rights.enableLineFocus && !!this.lineFocusModule;
84934
+ case NavigatorFeature.Definitions:
84935
+ return !!this.rights.enableDefinitions && !!this.definitionsModule;
84936
+ case NavigatorFeature.Citations:
84937
+ return !!this.rights.enableCitations && !!this.citationModule;
84938
+ case NavigatorFeature.ContentProtection:
84939
+ return !!this.rights.enableContentProtection && !!this.contentProtectionModule;
84940
+ case NavigatorFeature.Consumption:
84941
+ return !!this.rights.enableConsumption && !!this.consumptionModule;
84942
+ case NavigatorFeature.History:
84943
+ return !!this.rights.enableHistory && !!this.historyModule;
84944
+ case NavigatorFeature.Timeline:
84945
+ return !!this.rights.enableTimeline && !!this.timelineModule;
84946
+ default:
84947
+ return false;
84948
+ }
84949
+ }
84950
+ getFxlCurrentScale() {
84951
+ const match2 = this.spreads?.style.transform?.match(/scale\(([^)]+)\)/);
84952
+ return match2 ? parseFloat(match2[1]) : 1;
84953
+ }
84954
+ fitToPage() {
84955
+ if (!this.publication.isFixedLayout) return;
84956
+ this.handleResize();
84957
+ }
84958
+ zoomIn() {
84959
+ if (!this.publication.isFixedLayout) return;
84960
+ this.setFxlScale(this.getFxlCurrentScale() * 1.15);
84961
+ }
84962
+ zoomOut() {
84963
+ if (!this.publication.isFixedLayout) return;
84964
+ this.setFxlScale(this.getFxlCurrentScale() / 1.15);
84965
+ }
84966
+ setFxlScale(newScale) {
84967
+ if (!this.spreads || !this.fxlZoomContainer) return;
84968
+ this.spreads.style.transform = "scale(" + newScale + ")";
84969
+ this.updateFxlZoomContainer(newScale);
84970
+ }
84971
+ updateFxlZoomContainer(scale) {
84972
+ if (!this.fxlZoomContainer || !this.fxlContentWidth || !this.fxlContentHeight)
84973
+ return;
84974
+ this.fxlZoomContainer.style.width = this.fxlContentWidth * scale + "px";
84975
+ this.fxlZoomContainer.style.height = this.fxlContentHeight * scale + "px";
84976
+ this.spreads.style.width = this.fxlContentWidth + "px";
84977
+ this.spreads.style.height = this.fxlContentHeight + "px";
84978
+ if (this.fxlHandTool) {
84979
+ requestAnimationFrame(() => {
84980
+ if (!this.fxlScrollContainer) return;
84981
+ const isZoomed = this.fxlScrollContainer.scrollWidth > this.fxlScrollContainer.clientWidth || this.fxlScrollContainer.scrollHeight > this.fxlScrollContainer.clientHeight;
84982
+ if (isZoomed) {
84983
+ this.activateHand();
84984
+ } else {
84985
+ this.deactivateHand();
84986
+ }
84987
+ });
84988
+ }
84989
+ }
84990
+ setupFxlPan() {
84991
+ const el = this.fxlScrollContainer;
84992
+ if (!el) return;
84993
+ this.fxlPanOverlay = document.createElement("div");
84994
+ this.fxlPanOverlay.style.position = "absolute";
84995
+ this.fxlPanOverlay.style.top = "0";
84996
+ this.fxlPanOverlay.style.left = "0";
84997
+ this.fxlPanOverlay.style.width = "100%";
84998
+ this.fxlPanOverlay.style.height = "100%";
84999
+ this.fxlPanOverlay.style.pointerEvents = "none";
85000
+ this.fxlPanOverlay.style.zIndex = "1";
85001
+ this.fxlZoomContainer.style.position = "relative";
85002
+ this.fxlZoomContainer.appendChild(this.fxlPanOverlay);
85003
+ this.fxlHandTool = new GrabToPan({ element: el });
85004
+ }
85005
+ activateHand() {
85006
+ if (!this.publication.isFixedLayout) return;
85007
+ if (this.fxlPanOverlay) {
85008
+ this.fxlPanOverlay.style.pointerEvents = "auto";
85009
+ }
85010
+ this.fxlHandTool?.activate();
85011
+ const panBtn = document.querySelector("#fxl-pan a");
85012
+ if (panBtn) {
85013
+ panBtn.classList.add("active");
85014
+ panBtn.style.color = "#039be5";
85015
+ }
85016
+ }
85017
+ deactivateHand() {
85018
+ if (!this.publication.isFixedLayout) return;
85019
+ if (this.fxlPanOverlay) {
85020
+ this.fxlPanOverlay.style.pointerEvents = "none";
85021
+ }
85022
+ this.fxlHandTool?.deactivate();
85023
+ const panBtn = document.querySelector("#fxl-pan a");
85024
+ if (panBtn) {
85025
+ panBtn.classList.remove("active");
85026
+ panBtn.style.color = "";
85027
+ }
85028
+ }
84768
85029
  static async create(config2) {
84769
85030
  const navigator2 = new this(
84770
85031
  config2.settings,
@@ -84829,7 +85090,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84829
85090
  removeEventListenerOptional(
84830
85091
  this.goBackButton,
84831
85092
  "click",
84832
- _IFrameNavigator.goBack.bind(this)
85093
+ _EpubNavigator.goBack.bind(this)
84833
85094
  );
84834
85095
  removeEventListenerOptional(
84835
85096
  this.espandMenuIcon,
@@ -84845,12 +85106,15 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84845
85106
  }
84846
85107
  setDirection(direction) {
84847
85108
  let dir = "";
84848
- if (direction === "rtl" || direction === "ltr") dir = direction;
84849
- if (direction === "auto")
84850
- dir = this.publication.metadata?.readingProgression;
84851
- if (dir) {
84852
- if (dir === "rtl") this.spreads.style.flexDirection = "row-reverse";
84853
- if (dir === "ltr") this.spreads.style.flexDirection = "row";
85109
+ if (direction === "rtl" || direction === "ltr") {
85110
+ dir = direction;
85111
+ } else if (direction === "auto") {
85112
+ dir = this.publication.metadata?.readingProgression || this.publication.metadata?.otherMetadata?.["rendition:spread-direction"] || "ltr";
85113
+ }
85114
+ if (dir === "rtl" || dir === "ltr") {
85115
+ if (this.publication.isFixedLayout) {
85116
+ this.spreads.style.flexDirection = dir === "rtl" ? "row-reverse" : "row";
85117
+ }
84854
85118
  this.keyboardEventHandler.rtl = dir === "rtl";
84855
85119
  if (this.api?.direction) this.api?.direction(dir);
84856
85120
  this.emit(ReaderEvent.Direction, dir);
@@ -84889,11 +85153,33 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84889
85153
  this.spreads = document.createElement("div");
84890
85154
  this.firstSpread = document.createElement("div");
84891
85155
  this.spreads.style.display = "flex";
84892
- this.spreads.style.alignItems = "center";
84893
- this.spreads.style.justifyContent = "center";
85156
+ this.spreads.style.transformOrigin = "0 0";
84894
85157
  this.spreads.appendChild(this.firstSpread);
84895
85158
  this.firstSpread.appendChild(this.iframes[0]);
84896
- wrapper.appendChild(this.spreads);
85159
+ this.fxlScrollContainer = document.createElement("div");
85160
+ this.fxlScrollContainer.style.position = "absolute";
85161
+ this.fxlScrollContainer.style.top = "0";
85162
+ this.fxlScrollContainer.style.right = "0";
85163
+ const timelineEl = document.getElementById("container-view-timeline");
85164
+ this.fxlScrollContainer.style.left = timelineEl && this.rights.enableTimeline ? "70px" : "0";
85165
+ const infoBottom = document.getElementById("reader-info-bottom");
85166
+ this.fxlScrollContainer.style.bottom = infoBottom ? (this.attributes?.bottomInfoHeight ?? 40) + "px" : "0";
85167
+ this.fxlScrollContainer.style.overflow = "auto";
85168
+ this.fxlScrollContainer.style.display = "flex";
85169
+ this.fxlZoomContainer = document.createElement("div");
85170
+ this.fxlZoomContainer.style.margin = "auto";
85171
+ this.fxlZoomContainer.style.flexShrink = "0";
85172
+ this.fxlZoomContainer.style.overflow = "hidden";
85173
+ if (this.attributes?.fixedLayoutShadow !== false) {
85174
+ this.fxlZoomContainer.style.padding = "12px";
85175
+ this.fxlZoomContainer.style.boxSizing = "content-box";
85176
+ }
85177
+ this.fxlZoomContainer.appendChild(this.spreads);
85178
+ this.fxlScrollContainer.appendChild(this.fxlZoomContainer);
85179
+ wrapper.style.position = "relative";
85180
+ wrapper.appendChild(this.fxlScrollContainer);
85181
+ document.addEventListener("keydown", this.fxlZoomKeyHandler);
85182
+ this.setupFxlPan();
84897
85183
  let dir = "";
84898
85184
  switch (this.settings.direction) {
84899
85185
  case 0:
@@ -84941,13 +85227,23 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84941
85227
  }
84942
85228
  }
84943
85229
  if (this.publication.isFixedLayout) {
84944
- const minHeight = wrapper.clientHeight;
84945
- var iframeParent = this.iframes[0].parentElement?.parentElement;
84946
- iframeParent.style.height = minHeight + 40 + "px";
84947
85230
  } else {
84948
85231
  if (this.iframes.length === 2) {
84949
85232
  this.iframes.pop();
84950
85233
  }
85234
+ let dir = "";
85235
+ switch (this.settings.direction) {
85236
+ case 0:
85237
+ dir = "auto";
85238
+ break;
85239
+ case 1:
85240
+ dir = "ltr";
85241
+ break;
85242
+ case 2:
85243
+ dir = "rtl";
85244
+ break;
85245
+ }
85246
+ this.setDirection(dir);
84951
85247
  }
84952
85248
  this.loadingMessage = findElement(
84953
85249
  mainElement,
@@ -85143,7 +85439,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85143
85439
  if (menuSearch)
85144
85440
  menuSearch.parentElement?.style.setProperty("display", "none");
85145
85441
  }
85146
- if (menuSearch && this.view?.navigator.publication.isFixedLayout) {
85442
+ if (menuSearch && this.publication.isFixedLayout) {
85147
85443
  menuSearch.parentElement?.style.setProperty("display", "none");
85148
85444
  }
85149
85445
  if (this.hasMediaOverlays) {
@@ -85217,7 +85513,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85217
85513
  addEventListenerOptional(
85218
85514
  this.goBackButton,
85219
85515
  "click",
85220
- _IFrameNavigator.goBack.bind(this)
85516
+ _EpubNavigator.goBack.bind(this)
85221
85517
  );
85222
85518
  addEventListenerOptional(
85223
85519
  this.espandMenuIcon,
@@ -85659,6 +85955,12 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85659
85955
  this.didInitKeyboardEventHandler = true;
85660
85956
  }
85661
85957
  }
85958
+ if (this.publication.isFixedLayout && iframe.contentDocument) {
85959
+ iframe.contentDocument.addEventListener(
85960
+ "keydown",
85961
+ this.fxlZoomKeyHandler
85962
+ );
85963
+ }
85662
85964
  if (this.view?.layout !== "fixed") {
85663
85965
  if (this.view?.isScrollMode()) {
85664
85966
  iframe.height = "0";
@@ -85723,6 +86025,9 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85723
86025
  setTimeout(() => {
85724
86026
  if (this.mediaOverlayModule) {
85725
86027
  this.mediaOverlayModule.settings.resourceReady = true;
86028
+ if (this.mediaOverlayModule.settings.playing) {
86029
+ this.mediaOverlayModule.bindClickHandler();
86030
+ }
85726
86031
  }
85727
86032
  }, 300);
85728
86033
  }, 200);
@@ -85752,7 +86057,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85752
86057
  const bases = iframe.contentDocument.getElementsByTagName("base");
85753
86058
  if (bases.length === 0) {
85754
86059
  head.insertBefore(
85755
- _IFrameNavigator.createBase(this.currentChapterLink.href),
86060
+ _EpubNavigator.createBase(this.currentChapterLink.href),
85756
86061
  head.firstChild
85757
86062
  );
85758
86063
  }
@@ -85761,32 +86066,32 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85761
86066
  if (injectable.fontFamily) {
85762
86067
  this.settings.initAddedFont();
85763
86068
  if (!injectable.systemFont && injectable.url) {
85764
- const link = _IFrameNavigator.createCssLink(injectable.url);
86069
+ const link = _EpubNavigator.createCssLink(injectable.url);
85765
86070
  head.appendChild(link);
85766
86071
  addLoadingInjectable(link);
85767
86072
  }
85768
86073
  } else if (injectable.r2before && injectable.url) {
85769
- const link = _IFrameNavigator.createCssLink(injectable.url);
86074
+ const link = _EpubNavigator.createCssLink(injectable.url);
85770
86075
  head.insertBefore(link, head.firstChild);
85771
86076
  addLoadingInjectable(link);
85772
86077
  } else if (injectable.r2default && injectable.url) {
85773
- const link = _IFrameNavigator.createCssLink(injectable.url);
86078
+ const link = _EpubNavigator.createCssLink(injectable.url);
85774
86079
  head.insertBefore(link, head.childNodes[1]);
85775
86080
  addLoadingInjectable(link);
85776
86081
  } else if (injectable.r2after && injectable.url) {
85777
86082
  if (injectable.appearance) {
85778
86083
  this.settings.initAddedAppearance();
85779
86084
  }
85780
- const link = _IFrameNavigator.createCssLink(injectable.url);
86085
+ const link = _EpubNavigator.createCssLink(injectable.url);
85781
86086
  head.appendChild(link);
85782
86087
  addLoadingInjectable(link);
85783
86088
  } else if (injectable.url) {
85784
- const link = _IFrameNavigator.createCssLink(injectable.url);
86089
+ const link = _EpubNavigator.createCssLink(injectable.url);
85785
86090
  head.appendChild(link);
85786
86091
  addLoadingInjectable(link);
85787
86092
  }
85788
86093
  } else if (injectable.type === "script" && injectable.url) {
85789
- const script = _IFrameNavigator.createJavascriptLink(
86094
+ const script = _EpubNavigator.createJavascriptLink(
85790
86095
  injectable.url,
85791
86096
  injectable.async ?? false
85792
86097
  );
@@ -85805,7 +86110,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85805
86110
  */
85806
86111
  abortOnError(e7) {
85807
86112
  if (this.api?.onError) {
85808
- const trueError = e7 instanceof Error ? e7 : typeof e7 === "string" ? new Error(e7) : new Error("An unknown error occurred in the IFrameNavigator.");
86113
+ const trueError = e7 instanceof Error ? e7 : typeof e7 === "string" ? new Error(e7) : new Error("An unknown error occurred in the EpubNavigator.");
85809
86114
  this.api.onError(trueError);
85810
86115
  this.emit(ReaderEvent.Error, trueError);
85811
86116
  } else {
@@ -85831,7 +86136,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85831
86136
  const bases = doc.getElementsByTagName("base");
85832
86137
  if (bases.length === 0) {
85833
86138
  doc.head.insertBefore(
85834
- _IFrameNavigator.createBase(href),
86139
+ _EpubNavigator.createBase(href),
85835
86140
  doc.head.firstChild
85836
86141
  );
85837
86142
  }
@@ -85851,7 +86156,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85851
86156
  const bases = doc.getElementsByTagName("base");
85852
86157
  if (bases.length === 0) {
85853
86158
  doc.head.insertBefore(
85854
- _IFrameNavigator.createBase(href),
86159
+ _EpubNavigator.createBase(href),
85855
86160
  doc.head.firstChild
85856
86161
  );
85857
86162
  }
@@ -86203,13 +86508,15 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86203
86508
  }
86204
86509
  }
86205
86510
  }
86206
- var iframeParent = index2 === 0 && this.iframes.length === 2 ? this.iframes[1].parentElement?.parentElement : this.iframes[0].parentElement?.parentElement;
86207
- if (iframeParent && width) {
86511
+ if (width) {
86512
+ if (!this.fxlScrollContainer) return;
86208
86513
  const fxlMargin = this.attributes?.fixedLayoutMargin ?? 100;
86209
- var widthRatio = (parseInt(getComputedStyle(iframeParent).width) - fxlMargin) / (this.iframes.length === 2 ? parseInt(width.toString().replace("px", "")) * 2 + fxlMargin * 2 : parseInt(width.toString().replace("px", "")));
86210
- var heightRatio = (parseInt(getComputedStyle(iframeParent).height) - fxlMargin) / parseInt(height.toString().replace("px", ""));
86514
+ const contentW = parseInt(width.toString().replace("px", ""));
86515
+ const contentH = parseInt(height.toString().replace("px", ""));
86516
+ var widthRatio = (this.fxlScrollContainer.clientWidth - fxlMargin) / (this.iframes.length === 2 ? contentW * 2 + fxlMargin * 2 : contentW);
86517
+ var heightRatio = (this.fxlScrollContainer.clientHeight - fxlMargin) / contentH;
86211
86518
  var scale = Math.min(widthRatio, heightRatio);
86212
- iframeParent.style.transform = "scale(" + scale + ")";
86519
+ this.spreads.style.transform = "scale(" + scale + ")";
86213
86520
  for (const iframe of this.iframes) {
86214
86521
  iframe.style.height = height;
86215
86522
  iframe.style.width = width;
@@ -86217,6 +86524,9 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86217
86524
  iframe.parentElement.style.height = height;
86218
86525
  }
86219
86526
  }
86527
+ this.fxlContentWidth = this.iframes.length === 2 ? contentW * 2 : contentW;
86528
+ this.fxlContentHeight = contentH;
86529
+ this.updateFxlZoomContainer(scale);
86220
86530
  }
86221
86531
  }, 400);
86222
86532
  }
@@ -86579,10 +86889,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86579
86889
  }
86580
86890
  if (this.publication.isFixedLayout) {
86581
86891
  var index2 = this.publication.getSpineIndex(this.currentChapterLink.href);
86582
- const minHeight = getHeight() - 40 - (this.attributes?.margin ?? 0);
86583
- var iframeParent = index2 === 0 && this.iframes.length === 2 ? this.iframes[1].parentElement?.parentElement : this.iframes[0].parentElement?.parentElement;
86584
- if (iframeParent) {
86585
- iframeParent.style.height = minHeight + 40 + "px";
86892
+ if (this.fxlScrollContainer) {
86586
86893
  let height, width;
86587
86894
  let doc;
86588
86895
  if (index2 === 0 && this.iframes?.length === 2) {
@@ -86620,14 +86927,14 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86620
86927
  }
86621
86928
  }
86622
86929
  const fxlMargin = this.attributes?.fixedLayoutMargin ?? 100;
86623
- var widthRatio = (parseInt(getComputedStyle(iframeParent).width) - fxlMargin) / (this.iframes.length === 2 ? parseInt(
86930
+ const contentW = parseInt(
86624
86931
  width.toString().endsWith("px") ? width?.replace("px", "") : width
86625
- ) * 2 + fxlMargin * 2 : parseInt(
86626
- width.toString().endsWith("px") ? width?.replace("px", "") : width
86627
- ));
86628
- var heightRatio = (parseInt(getComputedStyle(iframeParent).height) - fxlMargin) / parseInt(height.toString().replace("px", ""));
86932
+ );
86933
+ const contentH = parseInt(height.toString().replace("px", ""));
86934
+ var widthRatio = (this.fxlScrollContainer.clientWidth - fxlMargin) / (this.iframes.length === 2 ? contentW * 2 + fxlMargin * 2 : contentW);
86935
+ var heightRatio = (this.fxlScrollContainer.clientHeight - fxlMargin) / contentH;
86629
86936
  var scale = Math.min(widthRatio, heightRatio);
86630
- iframeParent.style.transform = "scale(" + scale + ")";
86937
+ this.spreads.style.transform = "scale(" + scale + ")";
86631
86938
  for (const iframe of this.iframes) {
86632
86939
  iframe.style.height = height;
86633
86940
  iframe.style.width = width;
@@ -86635,6 +86942,9 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86635
86942
  iframe.parentElement.style.height = height;
86636
86943
  }
86637
86944
  }
86945
+ this.fxlContentWidth = this.iframes.length === 2 ? contentW * 2 : contentW;
86946
+ this.fxlContentHeight = contentH;
86947
+ this.updateFxlZoomContainer(scale);
86638
86948
  }
86639
86949
  }
86640
86950
  const oldPosition = this.view?.getCurrentPosition();
@@ -87324,6 +87634,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
87324
87634
  }
87325
87635
  }
87326
87636
  };
87637
+ var IFrameNavigator = EpubNavigator;
87327
87638
 
87328
87639
  // src/store/LocalAnnotator.ts
87329
87640
  init_polyfills();
@@ -87813,6 +88124,7 @@ var LayerSettings = class {
87813
88124
  };
87814
88125
 
87815
88126
  // src/reader.ts
88127
+ init_VisualNavigator();
87816
88128
  var _PDFNavigatorClass;
87817
88129
  async function loadPDFNavigator() {
87818
88130
  if (!_PDFNavigatorClass) {
@@ -87849,54 +88161,38 @@ var D2Reader = class _D2Reader {
87849
88161
  */
87850
88162
  /** Start TTS Read Aloud */
87851
88163
  this.startReadAloud = () => {
87852
- if (this.navigator instanceof IFrameNavigator) {
87853
- this.navigator.startReadAloud();
87854
- }
88164
+ this.navigator.startReadAloud();
87855
88165
  };
87856
- /** Start TTS Read Aloud */
88166
+ /** Stop TTS Read Aloud */
87857
88167
  this.stopReadAloud = () => {
87858
- if (this.navigator instanceof IFrameNavigator) {
87859
- this.navigator.stopReadAloud();
87860
- }
88168
+ this.navigator.stopReadAloud();
87861
88169
  };
87862
- /** Start TTS Read Aloud */
88170
+ /** Pause TTS Read Aloud */
87863
88171
  this.pauseReadAloud = () => {
87864
- if (this.navigator instanceof IFrameNavigator) {
87865
- this.navigator.pauseReadAloud();
87866
- }
88172
+ this.navigator.pauseReadAloud();
87867
88173
  };
87868
- /** Start TTS Read Aloud */
88174
+ /** Resume TTS Read Aloud */
87869
88175
  this.resumeReadAloud = () => {
87870
- if (this.navigator instanceof IFrameNavigator) {
87871
- this.navigator.resumeReadAloud();
87872
- }
88176
+ this.navigator.resumeReadAloud();
87873
88177
  };
87874
88178
  /**
87875
88179
  * Read Along
87876
88180
  */
87877
88181
  /** Start Media Overlay Read Along */
87878
88182
  this.startReadAlong = () => {
87879
- if (this.navigator instanceof IFrameNavigator) {
87880
- this.navigator.startReadAlong();
87881
- }
88183
+ this.navigator.startReadAlong();
87882
88184
  };
87883
88185
  /** Stop Media Overlay Read Along */
87884
88186
  this.stopReadAlong = () => {
87885
- if (this.navigator instanceof IFrameNavigator) {
87886
- this.navigator.stopReadAlong();
87887
- }
88187
+ this.navigator.stopReadAlong();
87888
88188
  };
87889
88189
  /** Pause Media Overlay Read Along */
87890
88190
  this.pauseReadAlong = () => {
87891
- if (this.navigator instanceof IFrameNavigator) {
87892
- this.navigator.pauseReadAlong();
87893
- }
88191
+ this.navigator.pauseReadAlong();
87894
88192
  };
87895
88193
  /** Resume Media Overlay Read Along */
87896
88194
  this.resumeReadAlong = () => {
87897
- if (this.navigator instanceof IFrameNavigator) {
87898
- this.navigator.resumeReadAlong();
87899
- }
88195
+ this.navigator.resumeReadAlong();
87900
88196
  };
87901
88197
  /**
87902
88198
  * Bookmarks and annotations
@@ -87945,20 +88241,20 @@ var D2Reader = class _D2Reader {
87945
88241
  };
87946
88242
  /** Hide Layer */
87947
88243
  this.hideLayer = (layer) => {
87948
- return this.navigator instanceof IFrameNavigator ? this.navigator?.hideLayer(layer) : false;
88244
+ this.navigator.hideLayer(layer);
87949
88245
  };
87950
88246
  /** Show Layer */
87951
88247
  this.showLayer = (layer) => {
87952
- return this.navigator instanceof IFrameNavigator ? this.navigator?.showLayer(layer) : false;
88248
+ this.navigator.showLayer(layer);
87953
88249
  };
87954
88250
  /** Activate Marker <br>
87955
88251
  * Activated Marker will be used for active annotation creation */
87956
88252
  this.activateMarker = (id2, position) => {
87957
- return this.navigator instanceof IFrameNavigator ? this.navigator?.activateMarker(id2, position) : false;
88253
+ this.navigator.activateMarker(id2, position);
87958
88254
  };
87959
88255
  /** Deactivate Marker */
87960
88256
  this.deactivateMarker = () => {
87961
- return this.navigator instanceof IFrameNavigator ? this.navigator?.deactivateMarker() : false;
88257
+ this.navigator.deactivateMarker();
87962
88258
  };
87963
88259
  /**
87964
88260
  * Definitions
@@ -87989,17 +88285,17 @@ var D2Reader = class _D2Reader {
87989
88285
  return await this.searchModule?.search(term, current) ?? [];
87990
88286
  };
87991
88287
  this.goToSearchIndex = async (href, index2, current) => {
87992
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableSearch) {
88288
+ if (this.navigator.supports(NavigatorFeature.Search)) {
87993
88289
  await this.searchModule?.goToSearchIndex(href, index2, current);
87994
88290
  }
87995
88291
  };
87996
88292
  this.goToSearchID = async (href, index2, current) => {
87997
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableSearch) {
88293
+ if (this.navigator.supports(NavigatorFeature.Search)) {
87998
88294
  await this.searchModule?.goToSearchID(href, index2, current);
87999
88295
  }
88000
88296
  };
88001
88297
  this.clearSearch = async () => {
88002
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableSearch) {
88298
+ if (this.navigator.supports(NavigatorFeature.Search)) {
88003
88299
  await this.searchModule?.clearSearch();
88004
88300
  }
88005
88301
  };
@@ -88016,16 +88312,16 @@ var D2Reader = class _D2Reader {
88016
88312
  return await this.settings.scroll(value);
88017
88313
  };
88018
88314
  /**
88019
- * Used to increase anything that can be increased,
88020
- * such as pitch, rate, volume, fontSize
88021
- */
88315
+ * Used to increase anything that can be increased,
88316
+ * such as pitch, rate, volume, fontSize
88317
+ */
88022
88318
  this.increase = async (incremental) => {
88023
88319
  if (this.isTTSIncrementable(incremental)) {
88024
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableTTS) {
88320
+ if (this.navigator.supports(NavigatorFeature.TTS)) {
88025
88321
  await this.ttsSettings?.increase(incremental);
88026
88322
  }
88027
88323
  } else if (this.isMOIncrementable(incremental)) {
88028
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableMediaOverlays) {
88324
+ if (this.navigator.supports(NavigatorFeature.MediaOverlays)) {
88029
88325
  await this.mediaOverlaySettings?.increase(incremental);
88030
88326
  }
88031
88327
  } else {
@@ -88038,11 +88334,11 @@ var D2Reader = class _D2Reader {
88038
88334
  */
88039
88335
  this.decrease = async (incremental) => {
88040
88336
  if (this.isTTSIncrementable(incremental)) {
88041
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableTTS) {
88337
+ if (this.navigator.supports(NavigatorFeature.TTS)) {
88042
88338
  await this.ttsSettings?.decrease(incremental);
88043
88339
  }
88044
88340
  } else if (this.isMOIncrementable(incremental)) {
88045
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableMediaOverlays) {
88341
+ if (this.navigator.supports(NavigatorFeature.MediaOverlays)) {
88046
88342
  await this.mediaOverlaySettings?.decrease(incremental);
88047
88343
  }
88048
88344
  } else {
@@ -88060,12 +88356,12 @@ var D2Reader = class _D2Reader {
88060
88356
  * TTS Settings
88061
88357
  */
88062
88358
  this.resetTTSSettings = () => {
88063
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableTTS) {
88359
+ if (this.navigator.supports(NavigatorFeature.TTS)) {
88064
88360
  this.ttsSettings?.resetTTSSettings();
88065
88361
  }
88066
88362
  };
88067
88363
  this.applyTTSSettings = async (ttsSettings) => {
88068
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableTTS) {
88364
+ if (this.navigator.supports(NavigatorFeature.TTS)) {
88069
88365
  await this.ttsSettings?.applyTTSSettings(ttsSettings);
88070
88366
  }
88071
88367
  };
@@ -88078,7 +88374,7 @@ var D2Reader = class _D2Reader {
88078
88374
  // }
88079
88375
  // };
88080
88376
  this.applyPreferredVoice = async (value) => {
88081
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableTTS) {
88377
+ if (this.navigator.supports(NavigatorFeature.TTS)) {
88082
88378
  await this.ttsSettings?.applyPreferredVoice(value);
88083
88379
  }
88084
88380
  };
@@ -88086,12 +88382,12 @@ var D2Reader = class _D2Reader {
88086
88382
  * Media Overlay Settings
88087
88383
  */
88088
88384
  this.resetMediaOverlaySettings = async () => {
88089
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableMediaOverlays) {
88385
+ if (this.navigator.supports(NavigatorFeature.MediaOverlays)) {
88090
88386
  await this.mediaOverlaySettings?.resetMediaOverlaySettings();
88091
88387
  }
88092
88388
  };
88093
88389
  this.applyMediaOverlaySettings = async (settings) => {
88094
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableMediaOverlays) {
88390
+ if (this.navigator.supports(NavigatorFeature.MediaOverlays)) {
88095
88391
  await this.mediaOverlaySettings?.applyMediaOverlaySettings(settings);
88096
88392
  }
88097
88393
  };
@@ -88105,34 +88401,22 @@ var D2Reader = class _D2Reader {
88105
88401
  await this.navigator.goToPage(page);
88106
88402
  };
88107
88403
  this.fitToPage = () => {
88108
- if (isPDFNavigator(this.navigator)) {
88109
- this.navigator.fitToPage();
88110
- }
88404
+ this.navigator.fitToPage();
88111
88405
  };
88112
88406
  this.fitToWidth = () => {
88113
- if (isPDFNavigator(this.navigator)) {
88114
- this.navigator.fitToWidth();
88115
- }
88407
+ this.navigator.fitToWidth();
88116
88408
  };
88117
88409
  this.zoomIn = () => {
88118
- if (isPDFNavigator(this.navigator)) {
88119
- this.navigator.zoomIn();
88120
- }
88410
+ this.navigator.zoomIn();
88121
88411
  };
88122
88412
  this.zoomOut = () => {
88123
- if (isPDFNavigator(this.navigator)) {
88124
- this.navigator.zoomOut();
88125
- }
88413
+ this.navigator.zoomOut();
88126
88414
  };
88127
88415
  this.activateHand = () => {
88128
- if (isPDFNavigator(this.navigator)) {
88129
- this.navigator.activateHand();
88130
- }
88416
+ this.navigator.activateHand();
88131
88417
  };
88132
88418
  this.deactivateHand = () => {
88133
- if (isPDFNavigator(this.navigator)) {
88134
- this.navigator.deactivateHand();
88135
- }
88419
+ this.navigator.deactivateHand();
88136
88420
  };
88137
88421
  this.copyToClipboard = (text) => {
88138
88422
  this.contentProtectionModule?.copyToClipboard(text);
@@ -88150,18 +88434,14 @@ var D2Reader = class _D2Reader {
88150
88434
  this.navigator.previousPage();
88151
88435
  };
88152
88436
  this.snapToSelector = async (selector2) => {
88153
- if (this.navigator instanceof IFrameNavigator) {
88154
- this.navigator.snapToSelector(selector2);
88155
- }
88437
+ this.navigator.snapToSelector?.(selector2);
88156
88438
  };
88157
88439
  /**
88158
88440
  * You have attributes in the reader when you initialize it. You can set margin, navigationHeight etc...
88159
88441
  * This is in case you change the attributes after initializing the reader.
88160
88442
  */
88161
88443
  this.applyAttributes = (value) => {
88162
- if (this.navigator instanceof IFrameNavigator) {
88163
- this.navigator.applyAttributes(value);
88164
- }
88444
+ this.navigator.applyAttributes?.(value);
88165
88445
  };
88166
88446
  /**
88167
88447
  * Destructor:
@@ -88190,9 +88470,7 @@ var D2Reader = class _D2Reader {
88190
88470
  };
88191
88471
  }
88192
88472
  addEventListener(event, handler) {
88193
- if (this.navigator instanceof IFrameNavigator || isPDFNavigator(this.navigator)) {
88194
- this.navigator.addListener(event, handler);
88195
- }
88473
+ this.navigator.addListener(event, handler);
88196
88474
  }
88197
88475
  /**
88198
88476
  * The async builder.
@@ -88393,7 +88671,7 @@ var D2Reader = class _D2Reader {
88393
88671
  publication,
88394
88672
  ...initialConfig.consumption
88395
88673
  }) : void 0;
88396
- const navigator2 = await IFrameNavigator.create({
88674
+ const navigator2 = await EpubNavigator.create({
88397
88675
  mainElement,
88398
88676
  headerMenu,
88399
88677
  footerMenu,
@@ -88449,10 +88727,7 @@ var D2Reader = class _D2Reader {
88449
88727
  }
88450
88728
  }
88451
88729
  get hasMediaOverlays() {
88452
- if (this.navigator instanceof IFrameNavigator) {
88453
- return this.navigator.hasMediaOverlays;
88454
- }
88455
- return false;
88730
+ return this.navigator.publication.hasMediaOverlays ?? false;
88456
88731
  }
88457
88732
  /** Table of Contents */
88458
88733
  get tableOfContents() {
@@ -88496,7 +88771,7 @@ var D2Reader = class _D2Reader {
88496
88771
  return this.navigator.currentResource();
88497
88772
  }
88498
88773
  get mostRecentNavigatedTocItem() {
88499
- return this.navigator instanceof IFrameNavigator ? this.navigator.mostRecentNavigatedTocItem() : false;
88774
+ return this.navigator.mostRecentNavigatedTocItem?.() ?? void 0;
88500
88775
  }
88501
88776
  get totalResources() {
88502
88777
  return this.navigator.totalResources();
@@ -88527,10 +88802,10 @@ var D2Reader = class _D2Reader {
88527
88802
  return this.navigator.positions();
88528
88803
  }
88529
88804
  get atStart() {
88530
- return this.navigator instanceof IFrameNavigator ? this.navigator.atStart() : false;
88805
+ return this.navigator.atStart();
88531
88806
  }
88532
88807
  get atEnd() {
88533
- return this.navigator instanceof IFrameNavigator ? this.navigator.atEnd() : false;
88808
+ return this.navigator.atEnd();
88534
88809
  }
88535
88810
  async applyLineFocusSettings(userSettings) {
88536
88811
  if (userSettings.lines) {
@@ -88599,11 +88874,15 @@ function updateConfig(rights, publication) {
88599
88874
 
88600
88875
  // src/index.ts
88601
88876
  init_Events();
88877
+ init_VisualNavigator();
88602
88878
  var index_default = D2Reader;
88603
88879
  var load = D2Reader.load;
88604
88880
  export {
88605
88881
  AnnotationMarker,
88882
+ EpubNavigator,
88883
+ IFrameNavigator,
88606
88884
  Link,
88885
+ NavigatorFeature,
88607
88886
  ReaderEvent,
88608
88887
  index_default as default,
88609
88888
  load