@d-i-t-a/reader 3.0.0-alpha.7 → 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 (38) hide show
  1. package/dist/esm/index.js +845 -339
  2. package/dist/esm/index.js.map +4 -4
  3. package/dist/injectables/style/mo.css +42 -0
  4. package/dist/reader.js +59 -59
  5. package/dist/reader.js.map +4 -4
  6. package/dist/types/index.d.ts +6 -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 +4 -3
  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 +4 -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/Events.d.ts +108 -0
  33. package/dist/types/utils/KeyboardEventHandler.d.ts +3 -3
  34. package/dist/types/utils/TouchEventHandler.d.ts +3 -3
  35. package/dist/types/views/BookView.d.ts +14 -2
  36. package/dist/types/views/FixedBookView.d.ts +3 -3
  37. package/dist/types/views/ReflowableBookView.d.ts +3 -3
  38. package/package.json +1 -1
package/dist/esm/index.js CHANGED
@@ -12860,6 +12860,69 @@ var require_debounce = __commonJS({
12860
12860
  }
12861
12861
  });
12862
12862
 
12863
+ // src/utils/Events.ts
12864
+ var ReaderEvent;
12865
+ var init_Events = __esm({
12866
+ "src/utils/Events.ts"() {
12867
+ init_polyfills();
12868
+ ReaderEvent = {
12869
+ // Resource lifecycle
12870
+ ResourceReady: "resource.ready",
12871
+ ResourceStart: "resource.start",
12872
+ ResourceEnd: "resource.end",
12873
+ ResourceFits: "resource.fits",
12874
+ ResourceError: "resource.error",
12875
+ // Navigation info
12876
+ Direction: "direction",
12877
+ ChapterInfo: "chapterinfo",
12878
+ PositionInfo: "positioninfo",
12879
+ LocationChanged: "location.changed",
12880
+ // User interaction
12881
+ Click: "click",
12882
+ KeyDown: "keydown",
12883
+ // Error
12884
+ Error: "error",
12885
+ // TTS / Read Aloud
12886
+ ReadAloudStarted: "readaloud.started",
12887
+ ReadAloudStopped: "readaloud.stopped",
12888
+ ReadAloudPaused: "readaloud.paused",
12889
+ ReadAloudResumed: "readaloud.resumed",
12890
+ ReadAloudFinished: "readaloud.finished",
12891
+ // Media Overlays / Read Along
12892
+ ReadAlongStarted: "readalong.started",
12893
+ ReadAlongStopped: "readalong.stopped",
12894
+ ReadAlongPaused: "readalong.paused",
12895
+ ReadAlongResumed: "readalong.resumed",
12896
+ ReadAlongFinished: "readalong.finished",
12897
+ // Bookmarks
12898
+ BookmarkCreated: "bookmark.created",
12899
+ BookmarkDeleted: "bookmark.deleted",
12900
+ // Annotations
12901
+ AnnotationCreated: "annotation.created",
12902
+ AnnotationDeleted: "annotation.deleted",
12903
+ AnnotationUpdated: "annotation.updated",
12904
+ AnnotationSelected: "annotation.selected",
12905
+ AnnotationCommentAdded: "annotation.comment.added",
12906
+ // Text selection / Toolbox
12907
+ ToolboxOpened: "toolbox.opened",
12908
+ ToolboxClosed: "toolbox.closed",
12909
+ TextSelected: "text.selected",
12910
+ // Definitions
12911
+ DefinitionSuccess: "definition.success",
12912
+ DefinitionClick: "definition.click",
12913
+ DefinitionVisible: "definition.visible",
12914
+ // Citation
12915
+ CitationCreated: "citation.created",
12916
+ CitationFailed: "citation.failed",
12917
+ // Content Protection
12918
+ InspectDetected: "inspect.detected",
12919
+ // Consumption tracking
12920
+ ActionTracked: "consumption.action",
12921
+ IdleSince: "consumption.idle"
12922
+ };
12923
+ }
12924
+ });
12925
+
12863
12926
  // node_modules/cssesc/cssesc.js
12864
12927
  var require_cssesc = __commonJS({
12865
12928
  "node_modules/cssesc/cssesc.js"(exports, module) {
@@ -29881,24 +29944,6 @@ var require_jscrypto = __commonJS({
29881
29944
  }
29882
29945
  });
29883
29946
 
29884
- // src/utils/HTMLTemplates.ts
29885
- var readerLoading, readerError;
29886
- var init_HTMLTemplates = __esm({
29887
- "src/utils/HTMLTemplates.ts"() {
29888
- init_polyfills();
29889
- init_IconLib();
29890
- readerLoading = `${icons.loading}`;
29891
- readerError = `
29892
- <span>
29893
- ${icons.error}
29894
- </span>
29895
- <span>There was an error loading this page.</span>
29896
- <button class="go-back">Go back</button>
29897
- <button class="try-again">Try again</button>
29898
- `;
29899
- }
29900
- });
29901
-
29902
29947
  // node_modules/eventemitter3/index.js
29903
29948
  var require_eventemitter3 = __commonJS({
29904
29949
  "node_modules/eventemitter3/index.js"(exports, module) {
@@ -30072,6 +30117,264 @@ var init_eventemitter3 = __esm({
30072
30117
  }
30073
30118
  });
30074
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
+
30075
30378
  // node_modules/pdfjs-dist/build/pdf.mjs
30076
30379
  function setVerbosityLevel(level) {
30077
30380
  if (Number.isInteger(level)) {
@@ -65208,138 +65511,6 @@ var init_pdf_viewer = __esm({
65208
65511
  }
65209
65512
  });
65210
65513
 
65211
- // src/utils/GrabToPan.ts
65212
- var CSS_CLASS_GRAB, GrabToPan;
65213
- var init_GrabToPan = __esm({
65214
- "src/utils/GrabToPan.ts"() {
65215
- init_polyfills();
65216
- CSS_CLASS_GRAB = "grab-to-pan-grab";
65217
- GrabToPan = class {
65218
- /**
65219
- * Construct a GrabToPan instance for a given HTML element.
65220
- * @param {Element} options.element
65221
- * @param {function} [options.ignoreTarget] - See `ignoreTarget(node)`.
65222
- * @param {function(boolean)} [options.onActiveChanged] - Called when
65223
- * grab-to-pan is (de)activated. The first argument is a boolean that
65224
- * shows whether grab-to-pan is activated.
65225
- */
65226
- constructor(options) {
65227
- this.element = options.element;
65228
- this.document = options.element.ownerDocument;
65229
- if (typeof options.ignoreTarget === "function") {
65230
- this.ignoreTarget = options.ignoreTarget;
65231
- }
65232
- this.onActiveChanged = options.onActiveChanged;
65233
- this.activate = this.activate.bind(this);
65234
- this.deactivate = this.deactivate.bind(this);
65235
- this.toggle = this.toggle.bind(this);
65236
- this._onMouseDown = this.#onMouseDown.bind(this);
65237
- this._onMouseMove = this.#onMouseMove.bind(this);
65238
- this._endPan = this.#endPan.bind(this);
65239
- const overlay = this.overlay = document.createElement("div");
65240
- overlay.className = "grab-to-pan-grabbing";
65241
- }
65242
- /**
65243
- * Bind a mousedown event to the element to enable grab-detection.
65244
- */
65245
- activate() {
65246
- if (!this.active) {
65247
- this.active = true;
65248
- this.element.addEventListener("mousedown", this._onMouseDown, true);
65249
- this.element.classList.add(CSS_CLASS_GRAB);
65250
- this.onActiveChanged?.(true);
65251
- }
65252
- }
65253
- /**
65254
- * Removes all events. Any pending pan session is immediately stopped.
65255
- */
65256
- deactivate() {
65257
- if (this.active) {
65258
- this.active = false;
65259
- this.element.removeEventListener("mousedown", this._onMouseDown, true);
65260
- this._endPan();
65261
- this.element.classList.remove(CSS_CLASS_GRAB);
65262
- this.onActiveChanged?.(false);
65263
- }
65264
- }
65265
- toggle() {
65266
- if (this.active) {
65267
- this.deactivate();
65268
- } else {
65269
- this.activate();
65270
- }
65271
- }
65272
- /**
65273
- * Whether to not pan if the target element is clicked.
65274
- * Override this method to change the default behaviour.
65275
- *
65276
- * @param {Element} node - The target of the event.
65277
- * @returns {boolean} Whether to not react to the click event.
65278
- */
65279
- ignoreTarget(node) {
65280
- return node.matches(
65281
- "a[href], a[href] *, input, textarea, button, button *, select, option"
65282
- );
65283
- }
65284
- #onMouseDown(event) {
65285
- if (event.button !== 0 || this.ignoreTarget(event.target)) {
65286
- return;
65287
- }
65288
- if (event.originalTarget) {
65289
- try {
65290
- event.originalTarget.tagName;
65291
- } catch (e7) {
65292
- return;
65293
- }
65294
- }
65295
- this.scrollLeftStart = this.element.scrollLeft;
65296
- this.scrollTopStart = this.element.scrollTop;
65297
- this.clientXStart = event.clientX;
65298
- this.clientYStart = event.clientY;
65299
- this.document.addEventListener("mousemove", this._onMouseMove, true);
65300
- this.document.addEventListener("mouseup", this._endPan, true);
65301
- this.element.addEventListener("scroll", this._endPan, true);
65302
- event.preventDefault();
65303
- event.stopPropagation();
65304
- const focusedElement = document.activeElement;
65305
- if (focusedElement && !focusedElement.contains(event.target)) {
65306
- focusedElement.blur();
65307
- }
65308
- }
65309
- #onMouseMove(event) {
65310
- this.element.removeEventListener("scroll", this._endPan, true);
65311
- if (!(event.buttons & 1)) {
65312
- this._endPan();
65313
- return;
65314
- }
65315
- const xDiff = event.clientX - this.clientXStart;
65316
- const yDiff = event.clientY - this.clientYStart;
65317
- const scrollTop = this.scrollTopStart - yDiff;
65318
- const scrollLeft = this.scrollLeftStart - xDiff;
65319
- if (this.element.scrollTo) {
65320
- this.element.scrollTo({
65321
- top: scrollTop,
65322
- left: scrollLeft,
65323
- behavior: "instant"
65324
- });
65325
- } else {
65326
- this.element.scrollTop = scrollTop;
65327
- this.element.scrollLeft = scrollLeft;
65328
- }
65329
- if (!this.overlay.parentNode) {
65330
- document.body.append(this.overlay);
65331
- }
65332
- }
65333
- #endPan() {
65334
- this.element.removeEventListener("scroll", this._endPan, true);
65335
- this.document.removeEventListener("mousemove", this._onMouseMove, true);
65336
- this.document.removeEventListener("mouseup", this._endPan, true);
65337
- this.overlay.remove();
65338
- }
65339
- };
65340
- }
65341
- });
65342
-
65343
65514
  // src/navigator/PDFNavigator.ts
65344
65515
  var PDFNavigator_exports = {};
65345
65516
  __export(PDFNavigator_exports, {
@@ -65354,7 +65525,8 @@ var init_PDFNavigator = __esm({
65354
65525
  "src/navigator/PDFNavigator.ts"() {
65355
65526
  init_polyfills();
65356
65527
  import_debounce8 = __toESM(require_debounce());
65357
- init_eventemitter3();
65528
+ init_VisualNavigator();
65529
+ init_Events();
65358
65530
  init_pdf();
65359
65531
  init_pdf_viewer();
65360
65532
  init_EventHandler();
@@ -65366,7 +65538,7 @@ var init_PDFNavigator = __esm({
65366
65538
  ScaleType2[ScaleType2["Width"] = 1] = "Width";
65367
65539
  return ScaleType2;
65368
65540
  })(ScaleType || {});
65369
- _PDFNavigator = class _PDFNavigator extends eventemitter3_default {
65541
+ _PDFNavigator = class _PDFNavigator extends VisualNavigator {
65370
65542
  constructor(settings, publication, api, workerSrc, annotator, initialLastReadingPosition, viewStore) {
65371
65543
  super();
65372
65544
  this.isPDF = true;
@@ -65395,6 +65567,20 @@ var init_PDFNavigator = __esm({
65395
65567
  this.initialLastReadingPosition = initialLastReadingPosition;
65396
65568
  this.viewStore = viewStore;
65397
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
+ }
65398
65584
  // ── Factory ────────────────────────────────────────────────────────────────
65399
65585
  static async create(config2) {
65400
65586
  const nav = new this(
@@ -65476,10 +65662,14 @@ var init_PDFNavigator = __esm({
65476
65662
  this.saveLastReadingPosition();
65477
65663
  if (this.atStart()) {
65478
65664
  this.api?.resourceAtStart?.();
65479
- this.emit("resource.start");
65665
+ this.emit(ReaderEvent.ResourceStart, {
65666
+ href: this.publication.readingOrder[0]?.href
65667
+ });
65480
65668
  } else if (this.atEnd()) {
65481
65669
  this.api?.resourceAtEnd?.();
65482
- this.emit("resource.end");
65670
+ this.emit(ReaderEvent.ResourceEnd, {
65671
+ href: this.publication.readingOrder[0]?.href
65672
+ });
65483
65673
  }
65484
65674
  }
65485
65675
  );
@@ -65489,7 +65679,9 @@ var init_PDFNavigator = __esm({
65489
65679
  this._numPages = pagesCount;
65490
65680
  this.hideLoading();
65491
65681
  this.api?.resourceReady?.();
65492
- this.emit("resource.ready");
65682
+ this.emit(ReaderEvent.ResourceReady, {
65683
+ href: this.publication.readingOrder[0]?.href
65684
+ });
65493
65685
  if (!this._positionRestored) {
65494
65686
  this._positionRestored = true;
65495
65687
  await this.restoreLastReadingPosition();
@@ -65590,7 +65782,7 @@ var init_PDFNavigator = __esm({
65590
65782
  const error = err instanceof Error ? err : new Error(String(err));
65591
65783
  console.error("PDFNavigator: failed to load document", url, error);
65592
65784
  this.api?.onError?.(error);
65593
- this.emit("resource.error", error);
65785
+ this.emit(ReaderEvent.ResourceError, error);
65594
65786
  }
65595
65787
  }
65596
65788
  // ── Navigator interface ────────────────────────────────────────────────────
@@ -66027,6 +66219,7 @@ var init_PDFNavigator = __esm({
66027
66219
  } else {
66028
66220
  this.annotator.saveLastReadingPosition(position);
66029
66221
  }
66222
+ this.emit(ReaderEvent.LocationChanged, position);
66030
66223
  }
66031
66224
  async restoreLastReadingPosition() {
66032
66225
  if (this.initialLastReadingPosition) {
@@ -68738,7 +68931,7 @@ var Publication = class _Publication {
68738
68931
  // ── Layout detection ─────────────────────────────────────────
68739
68932
  get isFixedLayout() {
68740
68933
  if (this.metadata?.layout === "fixed") return true;
68741
- const renditionLayout = this.metadata?.otherMetadata?.["rendition:layout"];
68934
+ const renditionLayout = this.metadata?.otherMetadata?.["rendition:layout"] ?? this.metadata?.otherMetadata?.rendition?.layout;
68742
68935
  return renditionLayout === "pre-paginated" || renditionLayout === "fixed";
68743
68936
  }
68744
68937
  get isReflowable() {
@@ -69253,6 +69446,8 @@ var ReflowableBookView = class {
69253
69446
  if (html) {
69254
69447
  html.style.setProperty("--USER__scroll", "readium-scroll-on");
69255
69448
  }
69449
+ const spacer = doc.getElementById("r2d2bc-column-spacer");
69450
+ if (spacer) spacer.remove();
69256
69451
  }
69257
69452
  this.setSize();
69258
69453
  this.setIframeHeight(this.iframe);
@@ -69274,8 +69469,8 @@ var ReflowableBookView = class {
69274
69469
  this.setSize();
69275
69470
  this.padOddColumns();
69276
69471
  }
69277
- if (this.navigator.rights.enableContentProtection) {
69278
- this.navigator.contentProtectionModule?.recalculate();
69472
+ if (this.host.isContentProtectionEnabled()) {
69473
+ this.host.recalculateContentProtection();
69279
69474
  }
69280
69475
  }
69281
69476
  start() {
@@ -69383,8 +69578,8 @@ var ReflowableBookView = class {
69383
69578
  let roundedLeftWidth = Math.floor(left / width) * width;
69384
69579
  element.style.height = originalHeight;
69385
69580
  this.setLeftColumnsWidth(roundedLeftWidth);
69386
- if (this.navigator.rights.enableContentProtection) {
69387
- this.navigator.contentProtectionModule?.recalculate(0);
69581
+ if (this.host.isContentProtectionEnabled()) {
69582
+ this.host.recalculateContentProtection(0);
69388
69583
  }
69389
69584
  }
69390
69585
  }
@@ -69408,8 +69603,8 @@ var ReflowableBookView = class {
69408
69603
  }
69409
69604
  element.style.height = originalHeight;
69410
69605
  this.setLeftColumnsWidth(roundedLeftWidth);
69411
- if (this.navigator.rights.enableContentProtection) {
69412
- this.navigator.contentProtectionModule?.recalculate(200);
69606
+ if (this.host.isContentProtectionEnabled()) {
69607
+ this.host.recalculateContentProtection(200);
69413
69608
  }
69414
69609
  }
69415
69610
  }
@@ -69466,10 +69661,10 @@ var ReflowableBookView = class {
69466
69661
  } else {
69467
69662
  this.setLeftColumnsWidth(0);
69468
69663
  }
69469
- this.navigator.checkResourcePosition();
69664
+ this.host.checkResourcePosition();
69470
69665
  }
69471
- if (this.navigator.rights.enableContentProtection) {
69472
- this.navigator.contentProtectionModule?.recalculate();
69666
+ if (this.host.isContentProtectionEnabled()) {
69667
+ this.host.recalculateContentProtection();
69473
69668
  }
69474
69669
  }
69475
69670
  goToNextPage() {
@@ -69497,10 +69692,10 @@ var ReflowableBookView = class {
69497
69692
  } else {
69498
69693
  this.setLeftColumnsWidth(scrollWidth);
69499
69694
  }
69500
- this.navigator.checkResourcePosition();
69695
+ this.host.checkResourcePosition();
69501
69696
  }
69502
- if (this.navigator.rights.enableContentProtection) {
69503
- this.navigator.contentProtectionModule?.recalculate();
69697
+ if (this.host.isContentProtectionEnabled()) {
69698
+ this.host.recalculateContentProtection();
69504
69699
  }
69505
69700
  }
69506
69701
  // doesn't exist in scroll mode
@@ -70146,7 +70341,7 @@ var _UserSettings = class _UserSettings {
70146
70341
  if (html) {
70147
70342
  const rootElement = findElement(document, "#root") || document.documentElement;
70148
70343
  const body = findElement(html, "body");
70149
- if (this.view?.navigator.publication.isReflowable) {
70344
+ if (this.view?.host?.isReflowable()) {
70150
70345
  if (await this.getProperty(ReadiumCSS.FONT_SIZE_KEY)) {
70151
70346
  html.style.setProperty(
70152
70347
  ReadiumCSS.FONT_SIZE_KEY,
@@ -70172,7 +70367,7 @@ var _UserSettings = class _UserSettings {
70172
70367
  this.userProperties.getByRef(ReadiumCSS.COLUMN_COUNT_REF)?.toString() ?? null
70173
70368
  );
70174
70369
  }
70175
- if (this.view?.navigator.publication.isReflowable) {
70370
+ if (this.view?.host?.isReflowable()) {
70176
70371
  if (await this.getProperty(ReadiumCSS.TEXT_ALIGNMENT_KEY)) {
70177
70372
  if (this.userProperties.getByRef(ReadiumCSS.TEXT_ALIGNMENT_REF)?.toString() === "auto") {
70178
70373
  html.style.removeProperty(ReadiumCSS.TEXT_ALIGNMENT_KEY);
@@ -70259,14 +70454,14 @@ var _UserSettings = class _UserSettings {
70259
70454
  setAttr(rootElement, "data-viewer-theme", "day");
70260
70455
  if (body) setAttr(body, "data-viewer-theme", "day");
70261
70456
  }
70262
- if (this.view?.navigator.publication.isFixedLayout) {
70457
+ if (this.view?.host?.isFixedLayout()) {
70263
70458
  if (await this.getProperty(ReadiumCSS.DIRECTION_KEY)) {
70264
70459
  let value = this.userProperties.getByRef(ReadiumCSS.DIRECTION_REF)?.toString() ?? null;
70265
70460
  html.style.setProperty(ReadiumCSS.DIRECTION_KEY, value);
70266
- this.view.navigator.setDirection(value);
70461
+ this.view.host?.setDirection(value);
70267
70462
  }
70268
70463
  }
70269
- if (this.view?.navigator.publication.isReflowable) {
70464
+ if (this.view?.host?.isReflowable()) {
70270
70465
  if (await this.getProperty(ReadiumCSS.FONT_FAMILY_KEY)) {
70271
70466
  html.style.setProperty(
70272
70467
  ReadiumCSS.FONT_FAMILY_KEY,
@@ -71612,6 +71807,9 @@ var import_debounce2 = __toESM(require_debounce());
71612
71807
  // src/modules/highlight/common/highlight.ts
71613
71808
  init_polyfills();
71614
71809
 
71810
+ // src/modules/highlight/TextHighlighter.ts
71811
+ init_Events();
71812
+
71615
71813
  // src/modules/highlight/common/rect-utils.ts
71616
71814
  init_polyfills();
71617
71815
  var import_loglevel3 = __toESM(require_loglevel());
@@ -72578,18 +72776,25 @@ var TextHighlighter = class _TextHighlighter {
72578
72776
  if (!this.isSelectionMenuOpen) {
72579
72777
  this.isSelectionMenuOpen = true;
72580
72778
  if (this.api?.selectionMenuOpen) this.api?.selectionMenuOpen();
72581
- this.navigator.emit("toolbox.opened", "opened");
72779
+ const doc = this.navigator.iframes[0].contentDocument;
72780
+ const sel = doc ? this.dom(doc.body)?.getSelection() : null;
72781
+ const text = sel && !sel.isCollapsed ? sel.toString() : void 0;
72782
+ this.navigator.emit(ReaderEvent.ToolboxOpened, "opened", { text });
72783
+ if (text && sel) {
72784
+ if (this.api?.selection) this.api.selection(text, sel);
72785
+ this.navigator.emit(ReaderEvent.TextSelected, { text, selection: sel });
72786
+ }
72582
72787
  }
72583
72788
  }, 100);
72584
72789
  this.selectionMenuClosed = (0, import_debounce2.default)(() => {
72585
72790
  if (this.isSelectionMenuOpen) {
72586
72791
  this.isSelectionMenuOpen = false;
72587
72792
  if (this.api?.selectionMenuClose) this.api?.selectionMenuClose();
72588
- this.navigator.emit("toolbox.closed", "closed");
72793
+ this.navigator.emit(ReaderEvent.ToolboxClosed, "closed");
72589
72794
  }
72590
72795
  }, 100);
72591
- this.selection = (0, import_debounce2.default)((text, selection) => {
72592
- if (this.api?.selection) this.api?.selection(text, selection);
72796
+ /** @deprecated Selection callback now fires from selectionMenuOpened */
72797
+ this.selection = (0, import_debounce2.default)((_text, _selection) => {
72593
72798
  }, 100);
72594
72799
  this.getScrollingElement = (doc) => {
72595
72800
  if (doc?.scrollingElement) {
@@ -73569,6 +73774,10 @@ var TextHighlighter = class _TextHighlighter {
73569
73774
  if (menuItem?.note) {
73570
73775
  if (anno.highlight) {
73571
73776
  self3.navigator.annotationModule?.api?.addCommentToAnnotation(anno).then((result) => {
73777
+ self3.navigator.emit(
73778
+ ReaderEvent.AnnotationCommentAdded,
73779
+ result
73780
+ );
73572
73781
  self3.navigator.annotationModule?.updateAnnotation(result).then(async () => {
73573
73782
  import_loglevel5.default.log(
73574
73783
  "update highlight " + result.id
@@ -74361,6 +74570,7 @@ var TextHighlighter = class _TextHighlighter {
74361
74570
  if (payload.highlight.type === 0 /* Annotation */) {
74362
74571
  this.navigator.annotationModule?.api?.selectedAnnotation(anno).then(async () => {
74363
74572
  });
74573
+ this.navigator.emit(ReaderEvent.AnnotationSelected, anno);
74364
74574
  }
74365
74575
  if (anno?.id) {
74366
74576
  import_loglevel5.default.log("selected highlight " + anno.id);
@@ -74372,6 +74582,10 @@ var TextHighlighter = class _TextHighlighter {
74372
74582
  if (getComputedStyle(toolbox).display === "none") {
74373
74583
  let noteH = function() {
74374
74584
  self2.navigator.annotationModule?.api?.addCommentToAnnotation(anno).then((result) => {
74585
+ self2.navigator.emit(
74586
+ ReaderEvent.AnnotationCommentAdded,
74587
+ result
74588
+ );
74375
74589
  self2.navigator.annotationModule?.updateAnnotation(result).then(async () => {
74376
74590
  import_loglevel5.default.log("update highlight " + result.id);
74377
74591
  if (toolbox) {
@@ -74474,7 +74688,11 @@ var TextHighlighter = class _TextHighlighter {
74474
74688
  lodash.omit(result, "callbacks"),
74475
74689
  lodash.omit(foundHighlight, "definition")
74476
74690
  );
74477
- this.navigator.emit("definition.click", result, foundHighlight);
74691
+ this.navigator.emit(
74692
+ ReaderEvent.DefinitionClick,
74693
+ result,
74694
+ foundHighlight
74695
+ );
74478
74696
  }
74479
74697
  }
74480
74698
  }
@@ -75041,6 +75259,7 @@ var TextHighlighter = class _TextHighlighter {
75041
75259
  );
75042
75260
  self2.navigator.annotationModule?.api?.selectedAnnotation(anno).then(async () => {
75043
75261
  });
75262
+ self2.navigator.emit(ReaderEvent.AnnotationSelected, anno);
75044
75263
  } else if (self2.navigator.rights.enableBookmarks) {
75045
75264
  anno = await self2.navigator.bookmarkModule?.getAnnotationByID(
75046
75265
  highlight.id
@@ -75259,6 +75478,7 @@ var import_loglevel8 = __toESM(require_loglevel());
75259
75478
 
75260
75479
  // src/modules/consumption/ConsumptionModule.ts
75261
75480
  init_polyfills();
75481
+ init_Events();
75262
75482
  var import_loglevel7 = __toESM(require_loglevel());
75263
75483
  var ConsumptionModule = class {
75264
75484
  constructor(publication, properties, api) {
@@ -75309,6 +75529,7 @@ var ConsumptionModule = class {
75309
75529
  }
75310
75530
  trackAction(locator, action) {
75311
75531
  this.api?.actionTracked(locator, action);
75532
+ this.navigator.emit(ReaderEvent.ActionTracked, { locator, action });
75312
75533
  }
75313
75534
  startReadingSession(locator) {
75314
75535
  if (this.firstReadingLocator && this.lastReadingLocator) {
@@ -75400,6 +75621,7 @@ var ConsumptionModule = class {
75400
75621
  this.currSeconds++;
75401
75622
  if (this.currSeconds === this.properties.idleTimeout) {
75402
75623
  this.api?.idleSince(this.currSeconds);
75624
+ this.navigator.emit(ReaderEvent.IdleSince, this.currSeconds);
75403
75625
  if (this.startResearchTimer !== void 0) {
75404
75626
  this.updateResearchSession();
75405
75627
  } else {
@@ -75421,6 +75643,7 @@ var ConsumptionModule = class {
75421
75643
  };
75422
75644
 
75423
75645
  // src/modules/AnnotationModule.ts
75646
+ init_Events();
75424
75647
  var AnnotationModule = class _AnnotationModule {
75425
75648
  constructor(annotator, rights, publication, initialAnnotations, properties, highlighter, api, headerMenu) {
75426
75649
  this.hide = findElement(
@@ -75631,9 +75854,11 @@ var AnnotationModule = class _AnnotationModule {
75631
75854
  }
75632
75855
  async deleteAnnotation(highlight) {
75633
75856
  await this.deleteLocalHighlight(highlight.id);
75857
+ this.navigator.emit(ReaderEvent.AnnotationDeleted, highlight);
75634
75858
  }
75635
75859
  async addAnnotation(highlight) {
75636
75860
  await this.annotator?.saveAnnotation(highlight);
75861
+ this.navigator.emit(ReaderEvent.AnnotationCreated, highlight);
75637
75862
  await this.showHighlights();
75638
75863
  await this.drawHighlights();
75639
75864
  }
@@ -75641,27 +75866,33 @@ var AnnotationModule = class _AnnotationModule {
75641
75866
  if (this.api?.deleteAnnotation) {
75642
75867
  this.api?.deleteAnnotation(highlight).then(async () => {
75643
75868
  this.deleteLocalHighlight(highlight.id);
75869
+ this.navigator.emit(ReaderEvent.AnnotationDeleted, highlight);
75644
75870
  });
75645
75871
  } else {
75646
75872
  this.deleteLocalHighlight(highlight.id);
75873
+ this.navigator.emit(ReaderEvent.AnnotationDeleted, highlight);
75647
75874
  }
75648
75875
  }
75649
75876
  async deleteSelectedHighlight(highlight) {
75650
75877
  if (this.api?.deleteAnnotation) {
75651
75878
  this.api.deleteAnnotation(highlight).then(async () => {
75652
75879
  this.deleteLocalHighlight(highlight.id);
75880
+ this.navigator.emit(ReaderEvent.AnnotationDeleted, highlight);
75653
75881
  });
75654
75882
  } else {
75655
75883
  this.deleteLocalHighlight(highlight.id);
75884
+ this.navigator.emit(ReaderEvent.AnnotationDeleted, highlight);
75656
75885
  }
75657
75886
  }
75658
75887
  async updateAnnotation(highlight) {
75659
75888
  if (this.api?.updateAnnotation) {
75660
75889
  this.api.updateAnnotation(highlight).then(async () => {
75661
75890
  this.updateLocalHighlight(highlight);
75891
+ this.navigator.emit(ReaderEvent.AnnotationUpdated, highlight);
75662
75892
  });
75663
75893
  } else {
75664
75894
  this.updateLocalHighlight(highlight);
75895
+ this.navigator.emit(ReaderEvent.AnnotationUpdated, highlight);
75665
75896
  }
75666
75897
  }
75667
75898
  async saveAnnotation(highlight) {
@@ -75739,6 +75970,7 @@ var AnnotationModule = class _AnnotationModule {
75739
75970
  try {
75740
75971
  let result = await this.api.addAnnotation(annotation);
75741
75972
  const saved = await this.annotator.saveAnnotation(result);
75973
+ this.navigator.emit(ReaderEvent.AnnotationCreated, saved);
75742
75974
  await this.showHighlights();
75743
75975
  await this.drawHighlights();
75744
75976
  return new Promise((resolve) => resolve(saved));
@@ -75748,6 +75980,7 @@ var AnnotationModule = class _AnnotationModule {
75748
75980
  }
75749
75981
  } else {
75750
75982
  const saved = await this.annotator.saveAnnotation(annotation);
75983
+ this.navigator.emit(ReaderEvent.AnnotationCreated, saved);
75751
75984
  await this.showHighlights();
75752
75985
  await this.drawHighlights();
75753
75986
  return new Promise((resolve) => resolve(saved));
@@ -76248,6 +76481,7 @@ init_HTMLUtilities();
76248
76481
  init_EventHandler();
76249
76482
  init_IconLib();
76250
76483
  var import_loglevel9 = __toESM(require_loglevel());
76484
+ init_Events();
76251
76485
  var BookmarkModule = class _BookmarkModule {
76252
76486
  static async create(config2) {
76253
76487
  const module = new this(
@@ -76333,12 +76567,14 @@ var BookmarkModule = class _BookmarkModule {
76333
76567
  await this.api?.deleteBookmark(bookmark);
76334
76568
  let deleted = await this.annotator.deleteBookmark(bookmark);
76335
76569
  import_loglevel9.default.log("Bookmark deleted " + JSON.stringify(deleted));
76570
+ this.navigator.emit(ReaderEvent.BookmarkDeleted, bookmark);
76336
76571
  await this.showBookmarks();
76337
76572
  await this.drawBookmarks();
76338
76573
  return deleted;
76339
76574
  } else {
76340
76575
  let deleted = await this.annotator.deleteBookmark(bookmark);
76341
76576
  import_loglevel9.default.log("Bookmark deleted " + JSON.stringify(deleted));
76577
+ this.navigator.emit(ReaderEvent.BookmarkDeleted, bookmark);
76342
76578
  await this.showBookmarks();
76343
76579
  await this.drawBookmarks();
76344
76580
  return deleted;
@@ -76413,12 +76649,14 @@ var BookmarkModule = class _BookmarkModule {
76413
76649
  import_loglevel9.default.log(bookmark);
76414
76650
  let saved = this.annotator.saveBookmark(bookmark);
76415
76651
  import_loglevel9.default.log("Bookmark added " + JSON.stringify(saved));
76652
+ this.navigator.emit(ReaderEvent.BookmarkCreated, bookmark);
76416
76653
  this.showBookmarks();
76417
76654
  await this.drawBookmarks();
76418
76655
  return saved;
76419
76656
  } else {
76420
76657
  let saved = this.annotator.saveBookmark(bookmark);
76421
76658
  import_loglevel9.default.log("Bookmark added " + JSON.stringify(saved));
76659
+ this.navigator.emit(ReaderEvent.BookmarkCreated, bookmark);
76422
76660
  this.showBookmarks();
76423
76661
  await this.drawBookmarks();
76424
76662
  return saved;
@@ -76613,11 +76851,13 @@ var BookmarkModule = class _BookmarkModule {
76613
76851
  if (this.api?.addBookmark) {
76614
76852
  let result = await this.api.addBookmark(annotation);
76615
76853
  const saved = await this.annotator.saveAnnotation(result);
76854
+ this.navigator.emit(ReaderEvent.BookmarkCreated, annotation);
76616
76855
  await this.showBookmarks();
76617
76856
  await this.drawBookmarks();
76618
76857
  return new Promise((resolve) => resolve(saved));
76619
76858
  } else {
76620
76859
  const saved = await this.annotator.saveAnnotation(annotation);
76860
+ this.navigator.emit(ReaderEvent.BookmarkCreated, annotation);
76621
76861
  await this.showBookmarks();
76622
76862
  await this.drawBookmarks();
76623
76863
  return new Promise((resolve) => resolve(saved));
@@ -76907,6 +77147,7 @@ var BookmarkModule = class _BookmarkModule {
76907
77147
 
76908
77148
  // src/modules/mediaoverlays/MediaOverlayModule.ts
76909
77149
  init_polyfills();
77150
+ init_Events();
76910
77151
 
76911
77152
  // src/model/v3/MediaOverlayNode.ts
76912
77153
  init_polyfills();
@@ -77352,6 +77593,7 @@ var MediaOverlayModule = class {
77352
77593
  config2.settings,
77353
77594
  config2
77354
77595
  );
77596
+ mediaOverlay.api = config2.api;
77355
77597
  mediaOverlay.start();
77356
77598
  return mediaOverlay;
77357
77599
  }
@@ -77422,10 +77664,28 @@ var MediaOverlayModule = class {
77422
77664
  await this.playLink();
77423
77665
  } else {
77424
77666
  if (this.settings.autoTurn && this.settings.playing) {
77425
- if (this.audioElement) {
77426
- await this.audioElement.pause();
77667
+ const currentLink = this.currentLinks[this.currentLinkIndex];
77668
+ const nextLink = currentLink ? this.publication.getNextSpineItem(
77669
+ this.publication.getAbsoluteHref(currentLink.href)
77670
+ ) : void 0;
77671
+ if (nextLink) {
77672
+ if (this.audioElement) {
77673
+ await this.audioElement.pause();
77674
+ }
77675
+ this.navigator.nextResource();
77676
+ } else {
77677
+ await this.stopReadAloud();
77678
+ if (this.api?.finished) this.api.finished();
77679
+ this.navigator.emit(ReaderEvent.ReadAlongFinished, "finished", {
77680
+ href: this.currentLinks[this.currentLinkIndex]?.href
77681
+ });
77427
77682
  }
77428
- this.navigator.nextResource();
77683
+ } else if (this.settings.playing) {
77684
+ await this.stopReadAloud();
77685
+ if (this.api?.stopped) this.api.stopped();
77686
+ this.navigator.emit(ReaderEvent.ReadAlongStopped, "stopped", {
77687
+ href: this.currentLinks[this.currentLinkIndex]?.href
77688
+ });
77429
77689
  } else {
77430
77690
  await this.stopReadAloud();
77431
77691
  }
@@ -77538,6 +77798,10 @@ var MediaOverlayModule = class {
77538
77798
  if (this.play) this.play.style.display = "none";
77539
77799
  if (this.pause) this.pause.style.removeProperty("display");
77540
77800
  this.bindClickHandler();
77801
+ if (this.api?.started) this.api.started();
77802
+ this.navigator.emit(ReaderEvent.ReadAlongStarted, "started", {
77803
+ href: this.currentLinks[this.currentLinkIndex]?.href
77804
+ });
77541
77805
  }
77542
77806
  }
77543
77807
  async stopReadAloud() {
@@ -77555,6 +77819,10 @@ var MediaOverlayModule = class {
77555
77819
  this.audioElement.pause();
77556
77820
  if (this.play) this.play.style.removeProperty("display");
77557
77821
  if (this.pause) this.pause.style.display = "none";
77822
+ if (this.api?.paused) this.api.paused();
77823
+ this.navigator.emit(ReaderEvent.ReadAlongPaused, "paused", {
77824
+ href: this.currentLinks[this.currentLinkIndex]?.href
77825
+ });
77558
77826
  }
77559
77827
  }
77560
77828
  async resumeReadAloud() {
@@ -77563,6 +77831,10 @@ var MediaOverlayModule = class {
77563
77831
  await this.audioElement.play();
77564
77832
  if (this.play) this.play.style.display = "none";
77565
77833
  if (this.pause) this.pause.style.removeProperty("display");
77834
+ if (this.api?.resumed) this.api.resumed();
77835
+ this.navigator.emit(ReaderEvent.ReadAlongResumed, "resumed", {
77836
+ href: this.currentLinks[this.currentLinkIndex]?.href
77837
+ });
77566
77838
  }
77567
77839
  }
77568
77840
  findDepthFirstTextAudioPair(textHref, mo, textFragmentIDChain) {
@@ -77673,8 +77945,25 @@ var MediaOverlayModule = class {
77673
77945
  } else {
77674
77946
  this.audioElement.pause();
77675
77947
  if (this.settings.autoTurn && this.settings.playing) {
77676
- this.audioElement.pause();
77677
- this.navigator.nextResource();
77948
+ const currentLink = this.currentLinks[this.currentLinkIndex];
77949
+ const nextLink = currentLink ? this.publication.getNextSpineItem(
77950
+ this.publication.getAbsoluteHref(currentLink.href)
77951
+ ) : void 0;
77952
+ if (nextLink) {
77953
+ this.navigator.nextResource();
77954
+ } else {
77955
+ this.stopReadAloud();
77956
+ if (this.api?.finished) this.api.finished();
77957
+ this.navigator.emit(ReaderEvent.ReadAlongFinished, "finished", {
77958
+ href: this.currentLinks[this.currentLinkIndex]?.href
77959
+ });
77960
+ }
77961
+ } else if (this.settings.playing) {
77962
+ this.stopReadAloud();
77963
+ if (this.api?.stopped) this.api.stopped();
77964
+ this.navigator.emit(ReaderEvent.ReadAlongStopped, "stopped", {
77965
+ href: this.currentLinks[this.currentLinkIndex]?.href
77966
+ });
77678
77967
  } else {
77679
77968
  this.stopReadAloud();
77680
77969
  }
@@ -81804,8 +82093,10 @@ var TTSSettings = class {
81804
82093
  }
81805
82094
  };
81806
82095
 
81807
- // src/navigator/IFrameNavigator.ts
82096
+ // src/navigator/EpubNavigator.ts
81808
82097
  init_polyfills();
82098
+ init_VisualNavigator();
82099
+ init_Events();
81809
82100
  init_EventHandler();
81810
82101
  init_HTMLUtilities();
81811
82102
  init_HTMLTemplates();
@@ -82284,6 +82575,7 @@ var PageBreakModule = class {
82284
82575
 
82285
82576
  // src/modules/TTS/TTSModule2.ts
82286
82577
  init_polyfills();
82578
+ init_Events();
82287
82579
  init_HTMLUtilities();
82288
82580
  init_EventHandler();
82289
82581
  var import_sanitize_html2 = __toESM(require_sanitize_html());
@@ -82454,9 +82746,11 @@ var TTSModule2 = class {
82454
82746
  });
82455
82747
  }
82456
82748
  cancel(api = true) {
82457
- if (api) {
82749
+ if (api && this.speaking) {
82458
82750
  if (this.api?.stopped) this.api?.stopped();
82459
- this.navigator.emit("readaloud.stopped", "stopped");
82751
+ this.navigator.emit(ReaderEvent.ReadAloudStopped, "stopped", {
82752
+ locator: this.navigator.currentLocator()
82753
+ });
82460
82754
  }
82461
82755
  this.userScrolled = false;
82462
82756
  this.speaking = false;
@@ -82475,7 +82769,9 @@ var TTSModule2 = class {
82475
82769
  }
82476
82770
  }
82477
82771
  if (this.api?.started) this.api?.started();
82478
- this.navigator.emit("readaloud.started", "started");
82772
+ this.navigator.emit(ReaderEvent.ReadAloudStarted, "started", {
82773
+ locator: this.navigator.currentLocator()
82774
+ });
82479
82775
  const self2 = this;
82480
82776
  this.userScrolled = false;
82481
82777
  this.cancel(false);
@@ -82644,14 +82940,18 @@ var TTSModule2 = class {
82644
82940
  import_loglevel18.default.log("utterance ended");
82645
82941
  self2.highlighter.doneSpeaking();
82646
82942
  self2.api?.finished();
82647
- self2.navigator.emit("readaloud.finished", "finished");
82943
+ self2.navigator.emit(ReaderEvent.ReadAloudFinished, "finished", {
82944
+ locator: this.navigator.currentLocator()
82945
+ });
82648
82946
  }
82649
82947
  }
82650
82948
  } else {
82651
82949
  import_loglevel18.default.log("utterance ended");
82652
82950
  self2.highlighter.doneSpeaking();
82653
82951
  self2.api?.finished();
82654
- self2.navigator.emit("readaloud.finished", "finished");
82952
+ self2.navigator.emit(ReaderEvent.ReadAloudFinished, "finished", {
82953
+ locator: this.navigator.currentLocator()
82954
+ });
82655
82955
  }
82656
82956
  };
82657
82957
  }
@@ -82758,7 +83058,9 @@ var TTSModule2 = class {
82758
83058
  this.scrollPartial = true;
82759
83059
  this.cancel(false);
82760
83060
  if (this.api?.started) this.api?.started();
82761
- this.navigator.emit("readaloud.started", "started");
83061
+ this.navigator.emit(ReaderEvent.ReadAloudStarted, "started", {
83062
+ locator: this.navigator.currentLocator()
83063
+ });
82762
83064
  let self2 = this;
82763
83065
  let iframe = document.querySelector(
82764
83066
  "main#iframe-wrapper iframe"
@@ -82818,7 +83120,9 @@ var TTSModule2 = class {
82818
83120
  speakPause() {
82819
83121
  if (window.speechSynthesis.speaking) {
82820
83122
  if (this.api?.paused) this.api?.paused();
82821
- this.navigator.emit("readaloud.paused", "paused");
83123
+ this.navigator.emit(ReaderEvent.ReadAloudPaused, "paused", {
83124
+ locator: this.navigator.currentLocator()
83125
+ });
82822
83126
  this.userScrolled = false;
82823
83127
  window.speechSynthesis.pause();
82824
83128
  this.speaking = false;
@@ -82831,7 +83135,9 @@ var TTSModule2 = class {
82831
83135
  speakResume() {
82832
83136
  if (window.speechSynthesis.speaking) {
82833
83137
  if (this.api?.resumed) this.api?.resumed();
82834
- this.navigator.emit("readaloud.resumed", "resumed");
83138
+ this.navigator.emit(ReaderEvent.ReadAloudResumed, "resumed", {
83139
+ locator: this.navigator.currentLocator()
83140
+ });
82835
83141
  this.userScrolled = false;
82836
83142
  window.speechSynthesis.resume();
82837
83143
  this.speaking = true;
@@ -83269,6 +83575,7 @@ function getTtsQueueItemRefText(obj) {
83269
83575
  // src/modules/search/DefinitionsModule.ts
83270
83576
  init_polyfills();
83271
83577
  var lodash3 = __toESM(require_lodash());
83578
+ init_Events();
83272
83579
  var import_debounce6 = __toESM(require_debounce());
83273
83580
  var import_loglevel19 = __toESM(require_loglevel());
83274
83581
  var DefinitionsModule = class {
@@ -83361,7 +83668,9 @@ var DefinitionsModule = class {
83361
83668
  await this.searchAndPaint(item, async (result) => {
83362
83669
  if (this.api?.success) {
83363
83670
  this.api?.success(lodash3.omit(item, "callbacks"), result);
83364
- this.navigator.emit("definition.success", result);
83671
+ if (result && result.length > 0) {
83672
+ this.navigator.emit(ReaderEvent.DefinitionSuccess, result);
83673
+ }
83365
83674
  if (this.api?.visible) {
83366
83675
  result.forEach((highlight) => {
83367
83676
  let highlightParent = this.navigator.iframes[0].contentDocument?.querySelector(
@@ -83378,7 +83687,11 @@ var DefinitionsModule = class {
83378
83687
  lodash3.omit(item, "callbacks"),
83379
83688
  lodash3.omit(highlight, "definition")
83380
83689
  );
83381
- this.navigator.emit("definition.visible", item, highlight);
83690
+ this.navigator.emit(
83691
+ ReaderEvent.DefinitionVisible,
83692
+ item,
83693
+ highlight
83694
+ );
83382
83695
  }
83383
83696
  });
83384
83697
  },
@@ -83449,9 +83762,6 @@ var DefinitionsModule = class {
83449
83762
  }
83450
83763
  };
83451
83764
 
83452
- // src/navigator/IFrameNavigator.ts
83453
- init_eventemitter3();
83454
-
83455
83765
  // src/modules/linefocus/LineFocusModule.ts
83456
83766
  init_polyfills();
83457
83767
  init_HTMLUtilities();
@@ -84115,6 +84425,7 @@ var HistoryModule = class {
84115
84425
  // src/modules/citation/CitationModule.ts
84116
84426
  init_polyfills();
84117
84427
  var import_loglevel22 = __toESM(require_loglevel());
84428
+ init_Events();
84118
84429
  var CitationStyle = /* @__PURE__ */ ((CitationStyle2) => {
84119
84430
  CitationStyle2[CitationStyle2["Chicago"] = 0] = "Chicago";
84120
84431
  CitationStyle2[CitationStyle2["MLA"] = 1] = "MLA";
@@ -84160,7 +84471,13 @@ var CitationModule = class {
84160
84471
  tmp.innerHTML = textToClipboard;
84161
84472
  const plainText = tmp.textContent ?? tmp.innerText ?? textToClipboard;
84162
84473
  navigator.clipboard.writeText(plainText).then(
84163
- () => this.api?.citationCreated("The text was copied to the clipboard!"),
84474
+ () => {
84475
+ this.api?.citationCreated("The text was copied to the clipboard!");
84476
+ this.navigator.emit(
84477
+ ReaderEvent.CitationCreated,
84478
+ "The text was copied to the clipboard!"
84479
+ );
84480
+ },
84164
84481
  () => this.legacyCopyToClipboard(textToClipboard)
84165
84482
  );
84166
84483
  } else {
@@ -84187,8 +84504,16 @@ var CitationModule = class {
84187
84504
  document.body.removeChild(forExecElement);
84188
84505
  if (success) {
84189
84506
  this.api?.citationCreated("The text was copied to the clipboard!");
84507
+ this.navigator.emit(
84508
+ ReaderEvent.CitationCreated,
84509
+ "The text was copied to the clipboard!"
84510
+ );
84190
84511
  } else {
84191
84512
  this.api?.citationFailed("Your browser doesn't allow clipboard access!");
84513
+ this.navigator.emit(
84514
+ ReaderEvent.CitationFailed,
84515
+ "Your browser doesn't allow clipboard access!"
84516
+ );
84192
84517
  }
84193
84518
  }
84194
84519
  selectContent(element) {
@@ -84424,12 +84749,31 @@ var CitationModule = class {
84424
84749
  }
84425
84750
  };
84426
84751
 
84427
- // src/navigator/IFrameNavigator.ts
84752
+ // src/navigator/EpubNavigator.ts
84428
84753
  var import_loglevel23 = __toESM(require_loglevel());
84429
- var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84754
+ init_GrabToPan();
84755
+ var EpubNavigator = class _EpubNavigator extends VisualNavigator {
84430
84756
  constructor(settings, annotator = void 0, initialLastReadingPosition = void 0, publication, api, rights, tts, injectables, attributes, services, sample, requestConfig, highlighter, modules) {
84431
84757
  super();
84432
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
+ };
84433
84777
  this.sideNavExpanded = false;
84434
84778
  this.currentChapterLink = { href: "" };
84435
84779
  this.currentSpreadLinks = {};
@@ -84450,6 +84794,8 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84450
84794
  enableCitations: false
84451
84795
  };
84452
84796
  this.didInitKeyboardEventHandler = false;
84797
+ this.fxlContentWidth = 0;
84798
+ this.fxlContentHeight = 0;
84453
84799
  this.onResize = () => {
84454
84800
  clearTimeout(this.timeout);
84455
84801
  this.timeout = setTimeout(this.handleResize.bind(this), 200);
@@ -84477,13 +84823,19 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84477
84823
  this.checkResourcePosition = (0, import_debounce7.default)(() => {
84478
84824
  if (this.view?.atStart() && this.view?.atEnd()) {
84479
84825
  if (this.api?.resourceFitsScreen) this.api?.resourceFitsScreen();
84480
- this.emit("resource.fits");
84826
+ this.emit(ReaderEvent.ResourceFits, {
84827
+ href: this.currentChapterLink.href
84828
+ });
84481
84829
  } else if (this.view?.atEnd()) {
84482
84830
  if (this.api?.resourceAtEnd) this.api?.resourceAtEnd();
84483
- this.emit("resource.end");
84831
+ this.emit(ReaderEvent.ResourceEnd, {
84832
+ href: this.currentChapterLink.href
84833
+ });
84484
84834
  } else if (this.view?.atStart()) {
84485
84835
  if (this.api?.resourceAtStart) this.api?.resourceAtStart();
84486
- this.emit("resource.start");
84836
+ this.emit(ReaderEvent.ResourceStart, {
84837
+ href: this.currentChapterLink.href
84838
+ });
84487
84839
  }
84488
84840
  }, 200);
84489
84841
  this.highlighter = highlighter;
@@ -84525,7 +84877,14 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84525
84877
  this.annotator = annotator;
84526
84878
  this.view = settings.view;
84527
84879
  this.view.attributes = attributes;
84528
- 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
+ };
84529
84888
  this.eventHandler = new EventHandler(this);
84530
84889
  this.touchEventHandler = new TouchEventHandler(this);
84531
84890
  this.keyboardEventHandler = new KeyboardEventHandler(this);
@@ -84556,6 +84915,117 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84556
84915
  this.requestConfig = requestConfig;
84557
84916
  this.sampleReadEventHandler = new SampleReadEventHandler(this);
84558
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
+ }
84559
85029
  static async create(config2) {
84560
85030
  const navigator2 = new this(
84561
85031
  config2.settings,
@@ -84620,7 +85090,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84620
85090
  removeEventListenerOptional(
84621
85091
  this.goBackButton,
84622
85092
  "click",
84623
- _IFrameNavigator.goBack.bind(this)
85093
+ _EpubNavigator.goBack.bind(this)
84624
85094
  );
84625
85095
  removeEventListenerOptional(
84626
85096
  this.espandMenuIcon,
@@ -84636,15 +85106,18 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84636
85106
  }
84637
85107
  setDirection(direction) {
84638
85108
  let dir = "";
84639
- if (direction === "rtl" || direction === "ltr") dir = direction;
84640
- if (direction === "auto")
84641
- dir = this.publication.metadata?.readingProgression;
84642
- if (dir) {
84643
- if (dir === "rtl") this.spreads.style.flexDirection = "row-reverse";
84644
- 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
+ }
84645
85118
  this.keyboardEventHandler.rtl = dir === "rtl";
84646
85119
  if (this.api?.direction) this.api?.direction(dir);
84647
- this.emit("direction", dir);
85120
+ this.emit(ReaderEvent.Direction, dir);
84648
85121
  }
84649
85122
  }
84650
85123
  async start(mainElement, headerMenu, footerMenu) {
@@ -84680,11 +85153,33 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84680
85153
  this.spreads = document.createElement("div");
84681
85154
  this.firstSpread = document.createElement("div");
84682
85155
  this.spreads.style.display = "flex";
84683
- this.spreads.style.alignItems = "center";
84684
- this.spreads.style.justifyContent = "center";
85156
+ this.spreads.style.transformOrigin = "0 0";
84685
85157
  this.spreads.appendChild(this.firstSpread);
84686
85158
  this.firstSpread.appendChild(this.iframes[0]);
84687
- 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();
84688
85183
  let dir = "";
84689
85184
  switch (this.settings.direction) {
84690
85185
  case 0:
@@ -84732,13 +85227,23 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84732
85227
  }
84733
85228
  }
84734
85229
  if (this.publication.isFixedLayout) {
84735
- const minHeight = wrapper.clientHeight;
84736
- var iframeParent = this.iframes[0].parentElement?.parentElement;
84737
- iframeParent.style.height = minHeight + 40 + "px";
84738
85230
  } else {
84739
85231
  if (this.iframes.length === 2) {
84740
85232
  this.iframes.pop();
84741
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);
84742
85247
  }
84743
85248
  this.loadingMessage = findElement(
84744
85249
  mainElement,
@@ -84934,7 +85439,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
84934
85439
  if (menuSearch)
84935
85440
  menuSearch.parentElement?.style.setProperty("display", "none");
84936
85441
  }
84937
- if (menuSearch && this.view?.navigator.publication.isFixedLayout) {
85442
+ if (menuSearch && this.publication.isFixedLayout) {
84938
85443
  menuSearch.parentElement?.style.setProperty("display", "none");
84939
85444
  }
84940
85445
  if (this.hasMediaOverlays) {
@@ -85008,7 +85513,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85008
85513
  addEventListenerOptional(
85009
85514
  this.goBackButton,
85010
85515
  "click",
85011
- _IFrameNavigator.goBack.bind(this)
85516
+ _EpubNavigator.goBack.bind(this)
85012
85517
  );
85013
85518
  addEventListenerOptional(
85014
85519
  this.espandMenuIcon,
@@ -85421,12 +85926,12 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85421
85926
  this.chapterTitle.innerHTML = "(" + this.currentChapterLink.title + ")";
85422
85927
  if (this.api?.chapterInfo)
85423
85928
  this.api.chapterInfo(this.currentChapterLink.title);
85424
- this.emit("chapterinfo", this.currentChapterLink.title);
85929
+ this.emit(ReaderEvent.ChapterInfo, this.currentChapterLink.title);
85425
85930
  } else {
85426
85931
  if (this.chapterTitle)
85427
85932
  this.chapterTitle.innerHTML = "(Current Chapter)";
85428
85933
  if (this.api?.chapterInfo) this.api.chapterInfo(void 0);
85429
- this.emit("chapterinfo", void 0);
85934
+ this.emit(ReaderEvent.ChapterInfo, void 0);
85430
85935
  }
85431
85936
  await this.injectInjectablesIntoIframeHead(iframe);
85432
85937
  if (this.view?.layout !== "fixed" && this.highlighter !== void 0) {
@@ -85450,6 +85955,12 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85450
85955
  this.didInitKeyboardEventHandler = true;
85451
85956
  }
85452
85957
  }
85958
+ if (this.publication.isFixedLayout && iframe.contentDocument) {
85959
+ iframe.contentDocument.addEventListener(
85960
+ "keydown",
85961
+ this.fxlZoomKeyHandler
85962
+ );
85963
+ }
85453
85964
  if (this.view?.layout !== "fixed") {
85454
85965
  if (this.view?.isScrollMode()) {
85455
85966
  iframe.height = "0";
@@ -85514,6 +86025,9 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85514
86025
  setTimeout(() => {
85515
86026
  if (this.mediaOverlayModule) {
85516
86027
  this.mediaOverlayModule.settings.resourceReady = true;
86028
+ if (this.mediaOverlayModule.settings.playing) {
86029
+ this.mediaOverlayModule.bindClickHandler();
86030
+ }
85517
86031
  }
85518
86032
  }, 300);
85519
86033
  }, 200);
@@ -85543,7 +86057,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85543
86057
  const bases = iframe.contentDocument.getElementsByTagName("base");
85544
86058
  if (bases.length === 0) {
85545
86059
  head.insertBefore(
85546
- _IFrameNavigator.createBase(this.currentChapterLink.href),
86060
+ _EpubNavigator.createBase(this.currentChapterLink.href),
85547
86061
  head.firstChild
85548
86062
  );
85549
86063
  }
@@ -85552,32 +86066,32 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85552
86066
  if (injectable.fontFamily) {
85553
86067
  this.settings.initAddedFont();
85554
86068
  if (!injectable.systemFont && injectable.url) {
85555
- const link = _IFrameNavigator.createCssLink(injectable.url);
86069
+ const link = _EpubNavigator.createCssLink(injectable.url);
85556
86070
  head.appendChild(link);
85557
86071
  addLoadingInjectable(link);
85558
86072
  }
85559
86073
  } else if (injectable.r2before && injectable.url) {
85560
- const link = _IFrameNavigator.createCssLink(injectable.url);
86074
+ const link = _EpubNavigator.createCssLink(injectable.url);
85561
86075
  head.insertBefore(link, head.firstChild);
85562
86076
  addLoadingInjectable(link);
85563
86077
  } else if (injectable.r2default && injectable.url) {
85564
- const link = _IFrameNavigator.createCssLink(injectable.url);
86078
+ const link = _EpubNavigator.createCssLink(injectable.url);
85565
86079
  head.insertBefore(link, head.childNodes[1]);
85566
86080
  addLoadingInjectable(link);
85567
86081
  } else if (injectable.r2after && injectable.url) {
85568
86082
  if (injectable.appearance) {
85569
86083
  this.settings.initAddedAppearance();
85570
86084
  }
85571
- const link = _IFrameNavigator.createCssLink(injectable.url);
86085
+ const link = _EpubNavigator.createCssLink(injectable.url);
85572
86086
  head.appendChild(link);
85573
86087
  addLoadingInjectable(link);
85574
86088
  } else if (injectable.url) {
85575
- const link = _IFrameNavigator.createCssLink(injectable.url);
86089
+ const link = _EpubNavigator.createCssLink(injectable.url);
85576
86090
  head.appendChild(link);
85577
86091
  addLoadingInjectable(link);
85578
86092
  }
85579
86093
  } else if (injectable.type === "script" && injectable.url) {
85580
- const script = _IFrameNavigator.createJavascriptLink(
86094
+ const script = _EpubNavigator.createJavascriptLink(
85581
86095
  injectable.url,
85582
86096
  injectable.async ?? false
85583
86097
  );
@@ -85596,8 +86110,9 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85596
86110
  */
85597
86111
  abortOnError(e7) {
85598
86112
  if (this.api?.onError) {
85599
- 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.");
85600
86114
  this.api.onError(trueError);
86115
+ this.emit(ReaderEvent.Error, trueError);
85601
86116
  } else {
85602
86117
  if (this.errorMessage) this.errorMessage.style.display = "block";
85603
86118
  if (this.isLoading) {
@@ -85621,7 +86136,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85621
86136
  const bases = doc.getElementsByTagName("base");
85622
86137
  if (bases.length === 0) {
85623
86138
  doc.head.insertBefore(
85624
- _IFrameNavigator.createBase(href),
86139
+ _EpubNavigator.createBase(href),
85625
86140
  doc.head.firstChild
85626
86141
  );
85627
86142
  }
@@ -85641,7 +86156,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85641
86156
  const bases = doc.getElementsByTagName("base");
85642
86157
  if (bases.length === 0) {
85643
86158
  doc.head.insertBefore(
85644
- _IFrameNavigator.createBase(href),
86159
+ _EpubNavigator.createBase(href),
85645
86160
  doc.head.firstChild
85646
86161
  );
85647
86162
  }
@@ -85993,13 +86508,15 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
85993
86508
  }
85994
86509
  }
85995
86510
  }
85996
- var iframeParent = index2 === 0 && this.iframes.length === 2 ? this.iframes[1].parentElement?.parentElement : this.iframes[0].parentElement?.parentElement;
85997
- if (iframeParent && width) {
86511
+ if (width) {
86512
+ if (!this.fxlScrollContainer) return;
85998
86513
  const fxlMargin = this.attributes?.fixedLayoutMargin ?? 100;
85999
- var widthRatio = (parseInt(getComputedStyle(iframeParent).width) - fxlMargin) / (this.iframes.length === 2 ? parseInt(width.toString().replace("px", "")) * 2 + fxlMargin * 2 : parseInt(width.toString().replace("px", "")));
86000
- 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;
86001
86518
  var scale = Math.min(widthRatio, heightRatio);
86002
- iframeParent.style.transform = "scale(" + scale + ")";
86519
+ this.spreads.style.transform = "scale(" + scale + ")";
86003
86520
  for (const iframe of this.iframes) {
86004
86521
  iframe.style.height = height;
86005
86522
  iframe.style.width = width;
@@ -86007,6 +86524,9 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86007
86524
  iframe.parentElement.style.height = height;
86008
86525
  }
86009
86526
  }
86527
+ this.fxlContentWidth = this.iframes.length === 2 ? contentW * 2 : contentW;
86528
+ this.fxlContentHeight = contentH;
86529
+ this.updateFxlZoomContainer(scale);
86010
86530
  }
86011
86531
  }, 400);
86012
86532
  }
@@ -86058,7 +86578,11 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86058
86578
  }
86059
86579
  stopReadAlong() {
86060
86580
  if (this.rights.enableMediaOverlays && this.mediaOverlayModule !== void 0 && this.hasMediaOverlays) {
86581
+ const wasPlaying = this.mediaOverlayModule.settings.playing;
86061
86582
  this.mediaOverlayModule?.stopReadAloud();
86583
+ if (wasPlaying) {
86584
+ this.emit(ReaderEvent.ReadAlongStopped, "stopped");
86585
+ }
86062
86586
  }
86063
86587
  }
86064
86588
  pauseReadAloud() {
@@ -86294,7 +86818,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86294
86818
  }
86295
86819
  handleClickThrough(event) {
86296
86820
  if (this.api?.clickThrough) this.api?.clickThrough(event);
86297
- this.emit("click", event);
86821
+ this.emit(ReaderEvent.Click, event);
86298
86822
  }
86299
86823
  handleInternalLink(event) {
86300
86824
  const element = event.target;
@@ -86365,10 +86889,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86365
86889
  }
86366
86890
  if (this.publication.isFixedLayout) {
86367
86891
  var index2 = this.publication.getSpineIndex(this.currentChapterLink.href);
86368
- const minHeight = getHeight() - 40 - (this.attributes?.margin ?? 0);
86369
- var iframeParent = index2 === 0 && this.iframes.length === 2 ? this.iframes[1].parentElement?.parentElement : this.iframes[0].parentElement?.parentElement;
86370
- if (iframeParent) {
86371
- iframeParent.style.height = minHeight + 40 + "px";
86892
+ if (this.fxlScrollContainer) {
86372
86893
  let height, width;
86373
86894
  let doc;
86374
86895
  if (index2 === 0 && this.iframes?.length === 2) {
@@ -86406,14 +86927,14 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86406
86927
  }
86407
86928
  }
86408
86929
  const fxlMargin = this.attributes?.fixedLayoutMargin ?? 100;
86409
- var widthRatio = (parseInt(getComputedStyle(iframeParent).width) - fxlMargin) / (this.iframes.length === 2 ? parseInt(
86930
+ const contentW = parseInt(
86410
86931
  width.toString().endsWith("px") ? width?.replace("px", "") : width
86411
- ) * 2 + fxlMargin * 2 : parseInt(
86412
- width.toString().endsWith("px") ? width?.replace("px", "") : width
86413
- ));
86414
- 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;
86415
86936
  var scale = Math.min(widthRatio, heightRatio);
86416
- iframeParent.style.transform = "scale(" + scale + ")";
86937
+ this.spreads.style.transform = "scale(" + scale + ")";
86417
86938
  for (const iframe of this.iframes) {
86418
86939
  iframe.style.height = height;
86419
86940
  iframe.style.width = width;
@@ -86421,6 +86942,9 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86421
86942
  iframe.parentElement.style.height = height;
86422
86943
  }
86423
86944
  }
86945
+ this.fxlContentWidth = this.iframes.length === 2 ? contentW * 2 : contentW;
86946
+ this.fxlContentHeight = contentH;
86947
+ this.updateFxlZoomContainer(scale);
86424
86948
  }
86425
86949
  }
86426
86950
  const oldPosition = this.view?.getCurrentPosition();
@@ -86493,7 +87017,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86493
87017
  if (this.api?.positionInfo) {
86494
87018
  this.api.positionInfo(locator);
86495
87019
  }
86496
- this.emit("positioninfo", locator);
87020
+ this.emit(ReaderEvent.PositionInfo, locator);
86497
87021
  }
86498
87022
  } else {
86499
87023
  if (this.chapterPosition) this.chapterPosition.innerHTML = "";
@@ -86577,7 +87101,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86577
87101
  }
86578
87102
  handleKeydownFallthrough(event) {
86579
87103
  if (this.api?.keydownFallthrough) this.api?.keydownFallthrough(event);
86580
- this.emit("keydown", event);
87104
+ this.emit(ReaderEvent.KeyDown, event);
86581
87105
  }
86582
87106
  hideView() {
86583
87107
  if (this.view?.layout !== "fixed") {
@@ -86737,12 +87261,12 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86737
87261
  this.chapterTitle.innerHTML = "(" + this.currentChapterLink.title + ")";
86738
87262
  if (this.api?.chapterInfo)
86739
87263
  this.api.chapterInfo(this.currentChapterLink.title);
86740
- this.emit("chapterinfo", this.currentChapterLink.title);
87264
+ this.emit(ReaderEvent.ChapterInfo, this.currentChapterLink.title);
86741
87265
  } else {
86742
87266
  if (this.chapterTitle)
86743
87267
  this.chapterTitle.innerHTML = "(Current Chapter)";
86744
87268
  if (this.api?.chapterInfo) this.api.chapterInfo(void 0);
86745
- this.emit("chapterinfo", void 0);
87269
+ this.emit(ReaderEvent.ChapterInfo, void 0);
86746
87270
  }
86747
87271
  await this.updatePositionInfo();
86748
87272
  } else {
@@ -86801,7 +87325,9 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86801
87325
  if (this.previousChapterTopAnchorElement)
86802
87326
  this.previousChapterTopAnchorElement.style.display = "none";
86803
87327
  if (this.api?.resourceFitsScreen) this.api?.resourceFitsScreen();
86804
- this.emit("resource.fits");
87328
+ this.emit(ReaderEvent.ResourceFits, {
87329
+ href: this.currentChapterLink.href
87330
+ });
86805
87331
  } else {
86806
87332
  this.settings.isPaginated().then((paginated) => {
86807
87333
  if (!paginated) {
@@ -86888,17 +87414,25 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86888
87414
  this.view?.padOddColumns?.();
86889
87415
  if (this.view?.atStart() && this.view?.atEnd()) {
86890
87416
  if (this.api?.resourceFitsScreen) this.api?.resourceFitsScreen();
86891
- this.emit("resource.fits");
87417
+ this.emit(ReaderEvent.ResourceFits, {
87418
+ href: this.currentChapterLink.href
87419
+ });
86892
87420
  } else if (this.view?.atEnd()) {
86893
87421
  if (this.api?.resourceAtEnd) this.api?.resourceAtEnd();
86894
- this.emit("resource.end");
87422
+ this.emit(ReaderEvent.ResourceEnd, {
87423
+ href: this.currentChapterLink.href
87424
+ });
86895
87425
  } else if (this.view?.atStart()) {
86896
87426
  if (this.api?.resourceAtStart) this.api?.resourceAtStart();
86897
- this.emit("resource.start");
87427
+ this.emit(ReaderEvent.ResourceStart, {
87428
+ href: this.currentChapterLink.href
87429
+ });
86898
87430
  }
86899
87431
  }
86900
87432
  if (this.api?.resourceReady) this.api?.resourceReady();
86901
- this.emit("resource.ready");
87433
+ this.emit(ReaderEvent.ResourceReady, {
87434
+ href: this.currentChapterLink.href
87435
+ });
86902
87436
  }, 150);
86903
87437
  }
86904
87438
  saveCurrentReadingPosition() {
@@ -86967,6 +87501,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
86967
87501
  import_loglevel23.default.log("save last reading position", position);
86968
87502
  this.annotator.saveLastReadingPosition(position);
86969
87503
  }
87504
+ this.emit(ReaderEvent.LocationChanged, position);
86970
87505
  if (this.consumptionModule) {
86971
87506
  this.consumptionModule.continueReadingSession(position);
86972
87507
  }
@@ -87099,6 +87634,7 @@ var IFrameNavigator = class _IFrameNavigator extends eventemitter3_default {
87099
87634
  }
87100
87635
  }
87101
87636
  };
87637
+ var IFrameNavigator = EpubNavigator;
87102
87638
 
87103
87639
  // src/store/LocalAnnotator.ts
87104
87640
  init_polyfills();
@@ -87588,6 +88124,7 @@ var LayerSettings = class {
87588
88124
  };
87589
88125
 
87590
88126
  // src/reader.ts
88127
+ init_VisualNavigator();
87591
88128
  var _PDFNavigatorClass;
87592
88129
  async function loadPDFNavigator() {
87593
88130
  if (!_PDFNavigatorClass) {
@@ -87624,54 +88161,38 @@ var D2Reader = class _D2Reader {
87624
88161
  */
87625
88162
  /** Start TTS Read Aloud */
87626
88163
  this.startReadAloud = () => {
87627
- if (this.navigator instanceof IFrameNavigator) {
87628
- this.navigator.startReadAloud();
87629
- }
88164
+ this.navigator.startReadAloud();
87630
88165
  };
87631
- /** Start TTS Read Aloud */
88166
+ /** Stop TTS Read Aloud */
87632
88167
  this.stopReadAloud = () => {
87633
- if (this.navigator instanceof IFrameNavigator) {
87634
- this.navigator.stopReadAloud();
87635
- }
88168
+ this.navigator.stopReadAloud();
87636
88169
  };
87637
- /** Start TTS Read Aloud */
88170
+ /** Pause TTS Read Aloud */
87638
88171
  this.pauseReadAloud = () => {
87639
- if (this.navigator instanceof IFrameNavigator) {
87640
- this.navigator.pauseReadAloud();
87641
- }
88172
+ this.navigator.pauseReadAloud();
87642
88173
  };
87643
- /** Start TTS Read Aloud */
88174
+ /** Resume TTS Read Aloud */
87644
88175
  this.resumeReadAloud = () => {
87645
- if (this.navigator instanceof IFrameNavigator) {
87646
- this.navigator.resumeReadAloud();
87647
- }
88176
+ this.navigator.resumeReadAloud();
87648
88177
  };
87649
88178
  /**
87650
88179
  * Read Along
87651
88180
  */
87652
88181
  /** Start Media Overlay Read Along */
87653
88182
  this.startReadAlong = () => {
87654
- if (this.navigator instanceof IFrameNavigator) {
87655
- this.navigator.startReadAlong();
87656
- }
88183
+ this.navigator.startReadAlong();
87657
88184
  };
87658
88185
  /** Stop Media Overlay Read Along */
87659
88186
  this.stopReadAlong = () => {
87660
- if (this.navigator instanceof IFrameNavigator) {
87661
- this.navigator.stopReadAlong();
87662
- }
88187
+ this.navigator.stopReadAlong();
87663
88188
  };
87664
88189
  /** Pause Media Overlay Read Along */
87665
88190
  this.pauseReadAlong = () => {
87666
- if (this.navigator instanceof IFrameNavigator) {
87667
- this.navigator.pauseReadAlong();
87668
- }
88191
+ this.navigator.pauseReadAlong();
87669
88192
  };
87670
88193
  /** Resume Media Overlay Read Along */
87671
88194
  this.resumeReadAlong = () => {
87672
- if (this.navigator instanceof IFrameNavigator) {
87673
- this.navigator.resumeReadAlong();
87674
- }
88195
+ this.navigator.resumeReadAlong();
87675
88196
  };
87676
88197
  /**
87677
88198
  * Bookmarks and annotations
@@ -87720,20 +88241,20 @@ var D2Reader = class _D2Reader {
87720
88241
  };
87721
88242
  /** Hide Layer */
87722
88243
  this.hideLayer = (layer) => {
87723
- return this.navigator instanceof IFrameNavigator ? this.navigator?.hideLayer(layer) : false;
88244
+ this.navigator.hideLayer(layer);
87724
88245
  };
87725
88246
  /** Show Layer */
87726
88247
  this.showLayer = (layer) => {
87727
- return this.navigator instanceof IFrameNavigator ? this.navigator?.showLayer(layer) : false;
88248
+ this.navigator.showLayer(layer);
87728
88249
  };
87729
88250
  /** Activate Marker <br>
87730
88251
  * Activated Marker will be used for active annotation creation */
87731
88252
  this.activateMarker = (id2, position) => {
87732
- return this.navigator instanceof IFrameNavigator ? this.navigator?.activateMarker(id2, position) : false;
88253
+ this.navigator.activateMarker(id2, position);
87733
88254
  };
87734
88255
  /** Deactivate Marker */
87735
88256
  this.deactivateMarker = () => {
87736
- return this.navigator instanceof IFrameNavigator ? this.navigator?.deactivateMarker() : false;
88257
+ this.navigator.deactivateMarker();
87737
88258
  };
87738
88259
  /**
87739
88260
  * Definitions
@@ -87764,17 +88285,17 @@ var D2Reader = class _D2Reader {
87764
88285
  return await this.searchModule?.search(term, current) ?? [];
87765
88286
  };
87766
88287
  this.goToSearchIndex = async (href, index2, current) => {
87767
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableSearch) {
88288
+ if (this.navigator.supports(NavigatorFeature.Search)) {
87768
88289
  await this.searchModule?.goToSearchIndex(href, index2, current);
87769
88290
  }
87770
88291
  };
87771
88292
  this.goToSearchID = async (href, index2, current) => {
87772
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableSearch) {
88293
+ if (this.navigator.supports(NavigatorFeature.Search)) {
87773
88294
  await this.searchModule?.goToSearchID(href, index2, current);
87774
88295
  }
87775
88296
  };
87776
88297
  this.clearSearch = async () => {
87777
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableSearch) {
88298
+ if (this.navigator.supports(NavigatorFeature.Search)) {
87778
88299
  await this.searchModule?.clearSearch();
87779
88300
  }
87780
88301
  };
@@ -87791,16 +88312,16 @@ var D2Reader = class _D2Reader {
87791
88312
  return await this.settings.scroll(value);
87792
88313
  };
87793
88314
  /**
87794
- * Used to increase anything that can be increased,
87795
- * such as pitch, rate, volume, fontSize
87796
- */
88315
+ * Used to increase anything that can be increased,
88316
+ * such as pitch, rate, volume, fontSize
88317
+ */
87797
88318
  this.increase = async (incremental) => {
87798
88319
  if (this.isTTSIncrementable(incremental)) {
87799
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableTTS) {
88320
+ if (this.navigator.supports(NavigatorFeature.TTS)) {
87800
88321
  await this.ttsSettings?.increase(incremental);
87801
88322
  }
87802
88323
  } else if (this.isMOIncrementable(incremental)) {
87803
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableMediaOverlays) {
88324
+ if (this.navigator.supports(NavigatorFeature.MediaOverlays)) {
87804
88325
  await this.mediaOverlaySettings?.increase(incremental);
87805
88326
  }
87806
88327
  } else {
@@ -87813,11 +88334,11 @@ var D2Reader = class _D2Reader {
87813
88334
  */
87814
88335
  this.decrease = async (incremental) => {
87815
88336
  if (this.isTTSIncrementable(incremental)) {
87816
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableTTS) {
88337
+ if (this.navigator.supports(NavigatorFeature.TTS)) {
87817
88338
  await this.ttsSettings?.decrease(incremental);
87818
88339
  }
87819
88340
  } else if (this.isMOIncrementable(incremental)) {
87820
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableMediaOverlays) {
88341
+ if (this.navigator.supports(NavigatorFeature.MediaOverlays)) {
87821
88342
  await this.mediaOverlaySettings?.decrease(incremental);
87822
88343
  }
87823
88344
  } else {
@@ -87835,12 +88356,12 @@ var D2Reader = class _D2Reader {
87835
88356
  * TTS Settings
87836
88357
  */
87837
88358
  this.resetTTSSettings = () => {
87838
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableTTS) {
88359
+ if (this.navigator.supports(NavigatorFeature.TTS)) {
87839
88360
  this.ttsSettings?.resetTTSSettings();
87840
88361
  }
87841
88362
  };
87842
88363
  this.applyTTSSettings = async (ttsSettings) => {
87843
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableTTS) {
88364
+ if (this.navigator.supports(NavigatorFeature.TTS)) {
87844
88365
  await this.ttsSettings?.applyTTSSettings(ttsSettings);
87845
88366
  }
87846
88367
  };
@@ -87853,7 +88374,7 @@ var D2Reader = class _D2Reader {
87853
88374
  // }
87854
88375
  // };
87855
88376
  this.applyPreferredVoice = async (value) => {
87856
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableTTS) {
88377
+ if (this.navigator.supports(NavigatorFeature.TTS)) {
87857
88378
  await this.ttsSettings?.applyPreferredVoice(value);
87858
88379
  }
87859
88380
  };
@@ -87861,12 +88382,12 @@ var D2Reader = class _D2Reader {
87861
88382
  * Media Overlay Settings
87862
88383
  */
87863
88384
  this.resetMediaOverlaySettings = async () => {
87864
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableMediaOverlays) {
88385
+ if (this.navigator.supports(NavigatorFeature.MediaOverlays)) {
87865
88386
  await this.mediaOverlaySettings?.resetMediaOverlaySettings();
87866
88387
  }
87867
88388
  };
87868
88389
  this.applyMediaOverlaySettings = async (settings) => {
87869
- if (this.navigator instanceof IFrameNavigator && this.navigator.rights.enableMediaOverlays) {
88390
+ if (this.navigator.supports(NavigatorFeature.MediaOverlays)) {
87870
88391
  await this.mediaOverlaySettings?.applyMediaOverlaySettings(settings);
87871
88392
  }
87872
88393
  };
@@ -87880,34 +88401,22 @@ var D2Reader = class _D2Reader {
87880
88401
  await this.navigator.goToPage(page);
87881
88402
  };
87882
88403
  this.fitToPage = () => {
87883
- if (isPDFNavigator(this.navigator)) {
87884
- this.navigator.fitToPage();
87885
- }
88404
+ this.navigator.fitToPage();
87886
88405
  };
87887
88406
  this.fitToWidth = () => {
87888
- if (isPDFNavigator(this.navigator)) {
87889
- this.navigator.fitToWidth();
87890
- }
88407
+ this.navigator.fitToWidth();
87891
88408
  };
87892
88409
  this.zoomIn = () => {
87893
- if (isPDFNavigator(this.navigator)) {
87894
- this.navigator.zoomIn();
87895
- }
88410
+ this.navigator.zoomIn();
87896
88411
  };
87897
88412
  this.zoomOut = () => {
87898
- if (isPDFNavigator(this.navigator)) {
87899
- this.navigator.zoomOut();
87900
- }
88413
+ this.navigator.zoomOut();
87901
88414
  };
87902
88415
  this.activateHand = () => {
87903
- if (isPDFNavigator(this.navigator)) {
87904
- this.navigator.activateHand();
87905
- }
88416
+ this.navigator.activateHand();
87906
88417
  };
87907
88418
  this.deactivateHand = () => {
87908
- if (isPDFNavigator(this.navigator)) {
87909
- this.navigator.deactivateHand();
87910
- }
88419
+ this.navigator.deactivateHand();
87911
88420
  };
87912
88421
  this.copyToClipboard = (text) => {
87913
88422
  this.contentProtectionModule?.copyToClipboard(text);
@@ -87925,18 +88434,14 @@ var D2Reader = class _D2Reader {
87925
88434
  this.navigator.previousPage();
87926
88435
  };
87927
88436
  this.snapToSelector = async (selector2) => {
87928
- if (this.navigator instanceof IFrameNavigator) {
87929
- this.navigator.snapToSelector(selector2);
87930
- }
88437
+ this.navigator.snapToSelector?.(selector2);
87931
88438
  };
87932
88439
  /**
87933
88440
  * You have attributes in the reader when you initialize it. You can set margin, navigationHeight etc...
87934
88441
  * This is in case you change the attributes after initializing the reader.
87935
88442
  */
87936
88443
  this.applyAttributes = (value) => {
87937
- if (this.navigator instanceof IFrameNavigator) {
87938
- this.navigator.applyAttributes(value);
87939
- }
88444
+ this.navigator.applyAttributes?.(value);
87940
88445
  };
87941
88446
  /**
87942
88447
  * Destructor:
@@ -87965,9 +88470,7 @@ var D2Reader = class _D2Reader {
87965
88470
  };
87966
88471
  }
87967
88472
  addEventListener(event, handler) {
87968
- if (this.navigator instanceof IFrameNavigator || isPDFNavigator(this.navigator)) {
87969
- this.navigator.addListener(event, handler);
87970
- }
88473
+ this.navigator.addListener(event, handler);
87971
88474
  }
87972
88475
  /**
87973
88476
  * The async builder.
@@ -88168,7 +88671,7 @@ var D2Reader = class _D2Reader {
88168
88671
  publication,
88169
88672
  ...initialConfig.consumption
88170
88673
  }) : void 0;
88171
- const navigator2 = await IFrameNavigator.create({
88674
+ const navigator2 = await EpubNavigator.create({
88172
88675
  mainElement,
88173
88676
  headerMenu,
88174
88677
  footerMenu,
@@ -88224,10 +88727,7 @@ var D2Reader = class _D2Reader {
88224
88727
  }
88225
88728
  }
88226
88729
  get hasMediaOverlays() {
88227
- if (this.navigator instanceof IFrameNavigator) {
88228
- return this.navigator.hasMediaOverlays;
88229
- }
88230
- return false;
88730
+ return this.navigator.publication.hasMediaOverlays ?? false;
88231
88731
  }
88232
88732
  /** Table of Contents */
88233
88733
  get tableOfContents() {
@@ -88271,7 +88771,7 @@ var D2Reader = class _D2Reader {
88271
88771
  return this.navigator.currentResource();
88272
88772
  }
88273
88773
  get mostRecentNavigatedTocItem() {
88274
- return this.navigator instanceof IFrameNavigator ? this.navigator.mostRecentNavigatedTocItem() : false;
88774
+ return this.navigator.mostRecentNavigatedTocItem?.() ?? void 0;
88275
88775
  }
88276
88776
  get totalResources() {
88277
88777
  return this.navigator.totalResources();
@@ -88302,10 +88802,10 @@ var D2Reader = class _D2Reader {
88302
88802
  return this.navigator.positions();
88303
88803
  }
88304
88804
  get atStart() {
88305
- return this.navigator instanceof IFrameNavigator ? this.navigator.atStart() : false;
88805
+ return this.navigator.atStart();
88306
88806
  }
88307
88807
  get atEnd() {
88308
- return this.navigator instanceof IFrameNavigator ? this.navigator.atEnd() : false;
88808
+ return this.navigator.atEnd();
88309
88809
  }
88310
88810
  async applyLineFocusSettings(userSettings) {
88311
88811
  if (userSettings.lines) {
@@ -88373,11 +88873,17 @@ function updateConfig(rights, publication) {
88373
88873
  }
88374
88874
 
88375
88875
  // src/index.ts
88876
+ init_Events();
88877
+ init_VisualNavigator();
88376
88878
  var index_default = D2Reader;
88377
88879
  var load = D2Reader.load;
88378
88880
  export {
88379
88881
  AnnotationMarker,
88882
+ EpubNavigator,
88883
+ IFrameNavigator,
88380
88884
  Link,
88885
+ NavigatorFeature,
88886
+ ReaderEvent,
88381
88887
  index_default as default,
88382
88888
  load
88383
88889
  };