paginar 0.3.5 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.es.js CHANGED
@@ -9957,9 +9957,9 @@ const state$6 = reactive({
9957
9957
  fontSize: 16,
9958
9958
  columns: 'double',
9959
9959
  mode: 'light',
9960
- blocked: false,
9961
- readingProgressAvailable: false,
9962
- readingProgressEnabled: false,
9960
+ blocked: false,
9961
+ readingProgressAvailable: false,
9962
+ readingProgressEnabled: false,
9963
9963
 
9964
9964
  bookTitle: null,
9965
9965
  chapterTitle: null,
@@ -9972,25 +9972,25 @@ const fontSize = computed(() => state$6.fontSize);
9972
9972
  const fontsOptions = computed(() => state$6.fontsOptions);
9973
9973
  const columns = computed(() => state$6.columns);
9974
9974
  const mode = computed(() => state$6.mode);
9975
- const blocked = computed(() => state$6.blocked);
9976
- const readingProgressAvailable = computed(() => state$6.readingProgressAvailable);
9977
- const readingProgressEnabled = computed(() => state$6.readingProgressEnabled);
9975
+ const blocked = computed(() => state$6.blocked);
9976
+ const readingProgressAvailable = computed(() => state$6.readingProgressAvailable);
9977
+ const readingProgressEnabled = computed(() => state$6.readingProgressEnabled);
9978
9978
 
9979
9979
  const bookTitle = computed(() => state$6.bookTitle);
9980
9980
  const chapterTitle = computed(() => state$6.chapterTitle);
9981
9981
  const homeUrl = computed(() => state$6.homeUrl);
9982
9982
 
9983
9983
  watch(
9984
- [baseFont, textFont, fontSize, columns, mode, readingProgressEnabled],
9984
+ [baseFont, textFont, fontSize, columns, mode, readingProgressEnabled],
9985
9985
  () => saveSettings()
9986
9986
  );
9987
9987
 
9988
- async function initSettings(settingsString) {
9989
- const settings = settingsString
9990
- ? JSON.parse(settingsString)
9991
- : null;
9992
- state$6.readingProgressAvailable = false;
9993
- state$6.readingProgressEnabled = false;
9988
+ async function initSettings(settingsString) {
9989
+ const settings = settingsString
9990
+ ? JSON.parse(settingsString)
9991
+ : null;
9992
+ state$6.readingProgressAvailable = false;
9993
+ state$6.readingProgressEnabled = false;
9994
9994
 
9995
9995
  if (settings?.baseFont)
9996
9996
  state$6.baseFont = settings.baseFont;
@@ -10026,51 +10026,51 @@ async function initSettings(settingsString) {
10026
10026
  if (settings?.chapterTitle)
10027
10027
  state$6.chapterTitle = settings.chapterTitle;
10028
10028
 
10029
- if (settings?.homeUrl)
10030
- state$6.homeUrl = settings.homeUrl;
10031
-
10032
- if (settings?.readingProgress &&
10033
- typeof settings.readingProgress === 'object' &&
10034
- !Array.isArray(settings.readingProgress)
10035
- ) {
10036
- state$6.readingProgressAvailable = true;
10037
- state$6.readingProgressEnabled = settings.readingProgress.enabled !== false;
10038
- }
10029
+ if (settings?.homeUrl)
10030
+ state$6.homeUrl = settings.homeUrl;
10031
+
10032
+ if (settings?.readingProgress &&
10033
+ typeof settings.readingProgress === 'object' &&
10034
+ !Array.isArray(settings.readingProgress)
10035
+ ) {
10036
+ state$6.readingProgressAvailable = true;
10037
+ state$6.readingProgressEnabled = settings.readingProgress.enabled !== false;
10038
+ }
10039
10039
 
10040
10040
  loadSavedSettings(settings);
10041
10041
  }
10042
10042
 
10043
- function loadSavedSettings(settings) {
10044
- let hasSettings = null;
10045
- try {
10046
- hasSettings = localStorage.getItem('readerSettings');
10047
- } catch (error) {
10048
- return
10049
- }
10050
-
10051
- if (hasSettings) {
10052
- let savedSettings = null;
10053
- try {
10054
- savedSettings = JSON.parse(hasSettings);
10055
- } catch (error) {
10056
- return
10057
- }
10043
+ function loadSavedSettings(settings) {
10044
+ let hasSettings = null;
10045
+ try {
10046
+ hasSettings = localStorage.getItem('readerSettings');
10047
+ } catch (error) {
10048
+ return
10049
+ }
10050
+
10051
+ if (hasSettings) {
10052
+ let savedSettings = null;
10053
+ try {
10054
+ savedSettings = JSON.parse(hasSettings);
10055
+ } catch (error) {
10056
+ return
10057
+ }
10058
10058
 
10059
10059
  state$6.fontSize = savedSettings.fontSize;
10060
10060
  state$6.columns = savedSettings.columns;
10061
10061
  state$6.mode = savedSettings.mode;
10062
10062
 
10063
- if (settings?.fontsOptions &&
10063
+ if (settings?.fontsOptions &&
10064
10064
  settings?.fontsOptions?.find(item => item.name === savedSettings.textFont)
10065
10065
  ) {
10066
10066
  state$6.textFont = savedSettings.textFont;
10067
- }
10068
-
10069
- if (state$6.readingProgressAvailable &&
10070
- typeof savedSettings.readingProgressEnabled === 'boolean'
10071
- ) {
10072
- state$6.readingProgressEnabled = savedSettings.readingProgressEnabled;
10073
- }
10067
+ }
10068
+
10069
+ if (state$6.readingProgressAvailable &&
10070
+ typeof savedSettings.readingProgressEnabled === 'boolean'
10071
+ ) {
10072
+ state$6.readingProgressEnabled = savedSettings.readingProgressEnabled;
10073
+ }
10074
10074
 
10075
10075
  if (savedSettings.mode === 'dark') {
10076
10076
  const htmlRoot = document.querySelector('html');
@@ -10094,14 +10094,14 @@ function setFontSize(value) {
10094
10094
  state$6.fontSize = value;
10095
10095
  }
10096
10096
 
10097
- function setBlocked(value) {
10098
- state$6.blocked = value;
10099
- }
10100
-
10101
- function setReadingProgressEnabled(value) {
10102
- if (state$6.readingProgressAvailable)
10103
- state$6.readingProgressEnabled = Boolean(value);
10104
- }
10097
+ function setBlocked(value) {
10098
+ state$6.blocked = value;
10099
+ }
10100
+
10101
+ function setReadingProgressEnabled(value) {
10102
+ if (state$6.readingProgressAvailable)
10103
+ state$6.readingProgressEnabled = Boolean(value);
10104
+ }
10105
10105
 
10106
10106
  function setMode(value) {
10107
10107
  state$6.mode = value;
@@ -10119,24 +10119,24 @@ function setMode(value) {
10119
10119
  }
10120
10120
  }
10121
10121
 
10122
- function saveSettings() {
10123
- try {
10124
- localStorage.setItem(
10125
- 'readerSettings',
10126
- JSON.stringify({
10127
- textFont: textFont.value,
10128
- fontSize: fontSize.value,
10129
- columns: columns.value,
10130
- mode: mode.value,
10131
- ...(readingProgressAvailable.value
10132
- ? { readingProgressEnabled: readingProgressEnabled.value }
10133
- : {})
10134
- })
10135
- );
10136
- } catch (error) {
10137
- // Settings remain available for the current session.
10138
- }
10139
- }
10122
+ function saveSettings() {
10123
+ try {
10124
+ localStorage.setItem(
10125
+ 'readerSettings',
10126
+ JSON.stringify({
10127
+ textFont: textFont.value,
10128
+ fontSize: fontSize.value,
10129
+ columns: columns.value,
10130
+ mode: mode.value,
10131
+ ...(readingProgressAvailable.value
10132
+ ? { readingProgressEnabled: readingProgressEnabled.value }
10133
+ : {})
10134
+ })
10135
+ );
10136
+ } catch (error) {
10137
+ // Settings remain available for the current session.
10138
+ }
10139
+ }
10140
10140
 
10141
10141
  const useReaderSettings = {
10142
10142
  baseFont,
@@ -10150,11 +10150,11 @@ const useReaderSettings = {
10150
10150
  setFontSize,
10151
10151
  setBlocked,
10152
10152
  mode,
10153
- blocked,
10154
- readingProgressAvailable,
10155
- readingProgressEnabled,
10156
- setMode,
10157
- setReadingProgressEnabled,
10153
+ blocked,
10154
+ readingProgressAvailable,
10155
+ readingProgressEnabled,
10156
+ setMode,
10157
+ setReadingProgressEnabled,
10158
10158
  saveSettings,
10159
10159
 
10160
10160
  bookTitle,
@@ -10351,36 +10351,36 @@ const useFootnotes = {
10351
10351
  showFootnotes
10352
10352
  };
10353
10353
 
10354
- const state$3 = reactive({
10355
- summary: null,
10356
- content: null,
10357
- activeChapter: 0
10354
+ const state$3 = reactive({
10355
+ summary: null,
10356
+ content: null,
10357
+ activeChapter: 0
10358
10358
  });
10359
10359
 
10360
10360
  const content = computed(() => state$3.content);
10361
10361
  const summary = computed(() => state$3.summary);
10362
- const context = computed(() => {
10363
- const chapters = state$3.summary || [];
10364
- const linkedChapter = chapters.findIndex(
10365
- chapter => window.location.href.includes(chapter.link)
10366
- );
10367
- const current = linkedChapter >= 0 ? linkedChapter : state$3.activeChapter;
10368
- return {
10369
- chapter: chapters[current],
10370
- surround: {
10371
- before: current - 1 >= 0
10372
- ? chapters[current - 1]
10373
- : null,
10374
- after: current + 1 < chapters.length
10375
- ? chapters[current + 1]
10376
- : null,
10377
- }
10378
- }
10379
- });
10380
- const contextId = computed(() => {
10381
- const chapter = context.value.chapter;
10382
- return chapter?.file || chapter?.link || chapter?.title || window.location.pathname
10383
- });
10362
+ const context = computed(() => {
10363
+ const chapters = state$3.summary || [];
10364
+ const linkedChapter = chapters.findIndex(
10365
+ chapter => window.location.href.includes(chapter.link)
10366
+ );
10367
+ const current = linkedChapter >= 0 ? linkedChapter : state$3.activeChapter;
10368
+ return {
10369
+ chapter: chapters[current],
10370
+ surround: {
10371
+ before: current - 1 >= 0
10372
+ ? chapters[current - 1]
10373
+ : null,
10374
+ after: current + 1 < chapters.length
10375
+ ? chapters[current + 1]
10376
+ : null,
10377
+ }
10378
+ }
10379
+ });
10380
+ const contextId = computed(() => {
10381
+ const chapter = context.value.chapter;
10382
+ return chapter?.file || chapter?.link || chapter?.title || window.location.pathname
10383
+ });
10384
10384
 
10385
10385
  async function initContent(contentString, contentWrapper) {
10386
10386
  const { setReferences, applyReferences } = useReferences;
@@ -10434,12 +10434,12 @@ async function getContent(location) {
10434
10434
  }
10435
10435
  }
10436
10436
 
10437
- function applyContent(text, chapter = null) {
10438
- const { applyReferences } = useReferences;
10439
- const newContent = applyReferences(text);
10440
- if (chapter)
10441
- state$3.activeChapter = state$3.summary.findIndex(item => item === chapter);
10442
- state$3.content = newContent;
10437
+ function applyContent(text, chapter = null) {
10438
+ const { applyReferences } = useReferences;
10439
+ const newContent = applyReferences(text);
10440
+ if (chapter)
10441
+ state$3.activeChapter = state$3.summary.findIndex(item => item === chapter);
10442
+ state$3.content = newContent;
10443
10443
  }
10444
10444
 
10445
10445
  function listenToClicks(contentWrapper) {
@@ -10464,9 +10464,9 @@ const useTextContent = {
10464
10464
  initContent,
10465
10465
  getContent,
10466
10466
  applyContent,
10467
- listenToClicks,
10468
- context,
10469
- contextId
10467
+ listenToClicks,
10468
+ context,
10469
+ contextId
10470
10470
  };
10471
10471
 
10472
10472
  const state$2 = reactive({
@@ -10516,214 +10516,216 @@ const useBrowser = {
10516
10516
  isApple
10517
10517
  };
10518
10518
 
10519
- const STORAGE_KEY = 'paginar:reading-progress:v1';
10520
-
10521
- const state$1 = reactive({
10522
- bookId: null,
10523
- contextKey: null,
10524
- restored: false,
10525
- suspended: false,
10526
- currentPage: 1,
10527
- totalPages: 1
10528
- });
10529
-
10530
- const available = computed(() => useReaderSettings.readingProgressAvailable.value);
10531
- const enabled = computed(() => useReaderSettings.readingProgressEnabled.value);
10532
-
10533
- function init$1(settingsString, fallbackTitle) {
10534
- let settings = null;
10535
- state$1.bookId = null;
10536
- state$1.contextKey = null;
10537
- state$1.restored = false;
10538
-
10539
- try {
10540
- settings = settingsString ? JSON.parse(settingsString) : null;
10541
- } catch (error) {
10542
- return
10543
- }
10544
-
10545
- if (!settings?.readingProgress ||
10546
- typeof settings.readingProgress !== 'object' ||
10547
- Array.isArray(settings.readingProgress)
10548
- )
10549
- return
10550
-
10551
- const configuredId = settings.readingProgress.id;
10552
- state$1.bookId = typeof configuredId === 'string' && configuredId.trim()
10553
- ? configuredId.trim()
10554
- : fallbackTitle || window.location.pathname;
10555
- }
10556
-
10557
- function getContextKey() {
10558
- if (!state$1.bookId)
10559
- return null
10560
-
10561
- const chapter = useTextContent.contextId.value || window.location.pathname;
10562
- return `${state$1.bookId}::${chapter}`
10563
- }
10564
-
10565
- function readStore() {
10566
- try {
10567
- const saved = JSON.parse(localStorage.getItem(STORAGE_KEY));
10568
- return saved?.version === 1 && saved.entries && typeof saved.entries === 'object'
10569
- ? saved
10570
- : { version: 1, entries: {} }
10571
- } catch (error) {
10572
- return { version: 1, entries: {} }
10573
- }
10574
- }
10575
-
10576
- function writeStore(store) {
10577
- try {
10578
- localStorage.setItem(STORAGE_KEY, JSON.stringify(store));
10579
- } catch (error) {
10580
- // Reading continues normally when storage is unavailable.
10581
- }
10582
- }
10583
-
10584
- function percentageFor(page, total) {
10585
- if (total <= 1)
10586
- return 0
10587
-
10588
- return Math.min(1, Math.max(0, (page - 1) / (total - 1)))
10589
- }
10590
-
10591
- function pageFor(percentage, total) {
10592
- return Math.min(total, Math.max(1, Math.round(percentage * (total - 1)) + 1))
10593
- }
10594
-
10595
- function repaginate(page, previousTotal, nextTotal) {
10596
- const key = getContextKey();
10597
- if (!available.value || !enabled.value || !state$1.restored ||
10598
- !key || key !== state$1.contextKey || previousTotal < 1 || nextTotal < 1
10599
- )
10600
- return null
10601
-
10602
- const percentage = percentageFor(page, previousTotal);
10603
- return pageFor(percentage, nextTotal)
10604
- }
10605
-
10606
- function save(page, total) {
10607
- const key = getContextKey();
10608
- if (!available.value || !enabled.value || !state$1.restored || state$1.suspended ||
10609
- !key || key !== state$1.contextKey || total < 1
10610
- )
10611
- return
10612
-
10613
- const store = readStore();
10614
- store.entries[key] = percentageFor(page, total);
10615
- writeStore(store);
10616
- }
10617
-
10618
- function suspend() {
10619
- state$1.suspended = true;
10620
- }
10621
-
10622
- function resume() {
10623
- state$1.suspended = false;
10624
- }
10625
-
10626
- function remove() {
10627
- const key = getContextKey();
10628
- if (!key)
10629
- return
10630
-
10631
- const store = readStore();
10632
- delete store.entries[key];
10633
- writeStore(store);
10634
- }
10635
-
10636
- function sync(page, total, allowRestore = false) {
10637
- state$1.currentPage = page;
10638
- state$1.totalPages = total;
10639
- const key = getContextKey();
10640
- if (!available.value || !enabled.value || !key)
10641
- return
10642
-
10643
- if (state$1.contextKey !== key) {
10644
- state$1.contextKey = key;
10645
- state$1.restored = false;
10646
- }
10647
-
10648
- if (!state$1.restored) {
10649
- if (!allowRestore)
10650
- return
10651
-
10652
- const percentage = readStore().entries[key];
10653
- if (Number.isFinite(percentage) && percentage >= 0 && percentage <= 1) {
10654
- if (total <= 1 && percentage > 0)
10655
- return
10656
-
10657
- state$1.restored = true;
10658
- const targetPage = pageFor(percentage, total);
10659
- if (targetPage !== page)
10660
- return targetPage
10661
- return
10662
- }
10663
-
10664
- state$1.restored = true;
10665
- }
10666
-
10667
- save(page, total);
10668
- }
10669
-
10670
- function setEnabled(value) {
10671
- useReaderSettings.setReadingProgressEnabled(value);
10672
- state$1.restored = true;
10673
-
10674
- if (value)
10675
- save(state$1.currentPage, state$1.totalPages);
10676
- else
10677
- remove();
10678
- }
10679
-
10680
- const useReadingProgress = {
10681
- available,
10682
- enabled,
10683
- init: init$1,
10684
- remove,
10685
- repaginate,
10686
- resume,
10687
- save,
10688
- setEnabled,
10689
- suspend,
10690
- sync
10519
+ const STORAGE_KEY = 'paginar:reading-progress:v1';
10520
+
10521
+ const state$1 = reactive({
10522
+ bookId: null,
10523
+ contextKey: null,
10524
+ restored: false,
10525
+ suspended: false,
10526
+ currentPage: 1,
10527
+ totalPages: 1
10528
+ });
10529
+
10530
+ const available = computed(() => useReaderSettings.readingProgressAvailable.value);
10531
+ const enabled = computed(() => useReaderSettings.readingProgressEnabled.value);
10532
+
10533
+ function init$1(settingsString, fallbackTitle) {
10534
+ let settings = null;
10535
+ state$1.bookId = null;
10536
+ state$1.contextKey = null;
10537
+ state$1.restored = false;
10538
+
10539
+ try {
10540
+ settings = settingsString ? JSON.parse(settingsString) : null;
10541
+ } catch (error) {
10542
+ return
10543
+ }
10544
+
10545
+ if (!settings?.readingProgress ||
10546
+ typeof settings.readingProgress !== 'object' ||
10547
+ Array.isArray(settings.readingProgress)
10548
+ )
10549
+ return
10550
+
10551
+ const configuredId = settings.readingProgress.id;
10552
+ state$1.bookId = typeof configuredId === 'string' && configuredId.trim()
10553
+ ? configuredId.trim()
10554
+ : fallbackTitle || window.location.pathname;
10555
+ }
10556
+
10557
+ function getContextKey() {
10558
+ if (!state$1.bookId)
10559
+ return null
10560
+
10561
+ const chapter = useTextContent.contextId.value || window.location.pathname;
10562
+ return `${state$1.bookId}::${chapter}`
10563
+ }
10564
+
10565
+ function readStore() {
10566
+ try {
10567
+ const saved = JSON.parse(localStorage.getItem(STORAGE_KEY));
10568
+ return saved?.version === 1 && saved.entries && typeof saved.entries === 'object'
10569
+ ? saved
10570
+ : { version: 1, entries: {} }
10571
+ } catch (error) {
10572
+ return { version: 1, entries: {} }
10573
+ }
10574
+ }
10575
+
10576
+ function writeStore(store) {
10577
+ try {
10578
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(store));
10579
+ } catch (error) {
10580
+ // Reading continues normally when storage is unavailable.
10581
+ }
10582
+ }
10583
+
10584
+ function percentageFor(page, total) {
10585
+ if (total <= 1)
10586
+ return 0
10587
+
10588
+ return Math.min(1, Math.max(0, (page - 1) / (total - 1)))
10589
+ }
10590
+
10591
+ function pageFor(percentage, total) {
10592
+ return Math.min(total, Math.max(1, Math.round(percentage * (total - 1)) + 1))
10593
+ }
10594
+
10595
+ function repaginate(page, previousTotal, nextTotal) {
10596
+ const key = getContextKey();
10597
+ if (!available.value || !enabled.value || !state$1.restored ||
10598
+ !key || key !== state$1.contextKey || previousTotal < 1 || nextTotal < 1
10599
+ )
10600
+ return null
10601
+
10602
+ const percentage = percentageFor(page, previousTotal);
10603
+ return pageFor(percentage, nextTotal)
10604
+ }
10605
+
10606
+ function save(page, total) {
10607
+ const key = getContextKey();
10608
+ if (!available.value || !enabled.value || !state$1.restored || state$1.suspended ||
10609
+ !key || key !== state$1.contextKey || total < 1
10610
+ )
10611
+ return
10612
+
10613
+ const store = readStore();
10614
+ store.entries[key] = percentageFor(page, total);
10615
+ writeStore(store);
10616
+ }
10617
+
10618
+ function suspend() {
10619
+ state$1.suspended = true;
10620
+ }
10621
+
10622
+ function resume() {
10623
+ state$1.suspended = false;
10624
+ }
10625
+
10626
+ function remove() {
10627
+ const key = getContextKey();
10628
+ if (!key)
10629
+ return
10630
+
10631
+ const store = readStore();
10632
+ delete store.entries[key];
10633
+ writeStore(store);
10634
+ }
10635
+
10636
+ function sync(page, total, allowRestore = false) {
10637
+ state$1.currentPage = page;
10638
+ state$1.totalPages = total;
10639
+ const key = getContextKey();
10640
+ if (!available.value || !enabled.value || !key)
10641
+ return
10642
+
10643
+ if (state$1.contextKey !== key) {
10644
+ state$1.contextKey = key;
10645
+ state$1.restored = false;
10646
+ }
10647
+
10648
+ if (!state$1.restored) {
10649
+ if (!allowRestore)
10650
+ return
10651
+
10652
+ const percentage = readStore().entries[key];
10653
+ if (Number.isFinite(percentage) && percentage >= 0 && percentage <= 1) {
10654
+ if (total <= 1 && percentage > 0)
10655
+ return
10656
+
10657
+ state$1.restored = true;
10658
+ const targetPage = pageFor(percentage, total);
10659
+ if (targetPage !== page)
10660
+ return targetPage
10661
+ return
10662
+ }
10663
+
10664
+ state$1.restored = true;
10665
+ }
10666
+
10667
+ save(page, total);
10668
+ }
10669
+
10670
+ function setEnabled(value) {
10671
+ useReaderSettings.setReadingProgressEnabled(value);
10672
+ state$1.restored = true;
10673
+
10674
+ if (value)
10675
+ save(state$1.currentPage, state$1.totalPages);
10676
+ else
10677
+ remove();
10678
+ }
10679
+
10680
+ const useReadingProgress = {
10681
+ available,
10682
+ enabled,
10683
+ init: init$1,
10684
+ remove,
10685
+ repaginate,
10686
+ resume,
10687
+ save,
10688
+ setEnabled,
10689
+ suspend,
10690
+ sync
10691
10691
  };
10692
10692
 
10693
- const state = reactive({
10694
- currentPage: 1,
10693
+ const state = reactive({
10694
+ currentPage: 1,
10695
+ changeSource: 'initial',
10695
10696
  nextTry: 0,
10696
10697
  prevTry: 0,
10697
10698
  willRedirect: false
10698
10699
  });
10699
10700
 
10700
- const currentPage = computed(() => state.currentPage);
10701
+ const currentPage = computed(() => state.currentPage);
10702
+ const changeSource = computed(() => state.changeSource);
10701
10703
  const totalPages = computed(() => useEstimatePages.totalPages.value);
10702
10704
 
10703
- function init(viewport, content, estimate = null) {
10704
- const updatePages = estimate || (() => useEstimatePages.estimate(viewport, content));
10705
- // Measure immediately, but let the parent restore progress only after child
10706
- // controls (notably the page slider) have finished their mount cycle.
10707
- useEstimatePages.estimate(viewport, content);
10705
+ function init(viewport, content, estimate = null) {
10706
+ const updatePages = estimate || (() => useEstimatePages.estimate(viewport, content));
10707
+ // Measure immediately, but let the parent restore progress only after child
10708
+ // controls (notably the page slider) have finished their mount cycle.
10709
+ useEstimatePages.estimate(viewport, content);
10708
10710
 
10709
10711
  // check if there is a query string for oring, and
10710
10712
  // if previews chapter was the next one. If so,
10711
10713
  // start from the end, as we are coming backwards
10712
10714
  const urlParams = new URLSearchParams(window.location.search);
10713
10715
  const origin = urlParams.get('origin');
10714
- if (origin && origin === 'next') {
10715
- setTimeout(() => {
10716
- set(totalPages.value);
10717
- }, 200);
10716
+ if (origin && origin === 'next') {
10717
+ setTimeout(() => {
10718
+ set(totalPages.value);
10719
+ }, 200);
10718
10720
  }
10719
10721
 
10720
10722
  if (!useBrowser.isApple && !useBrowser.isSafari) {
10721
10723
  addEventListener('wheel', onWheel);
10722
10724
  }
10723
10725
 
10724
- setInterval(() => {
10725
- updatePages();
10726
- }, 5000);
10726
+ setInterval(() => {
10727
+ updatePages();
10728
+ }, 5000);
10727
10729
  }
10728
10730
 
10729
10731
  // when resizing the viewport, totalPages change
@@ -10735,10 +10737,10 @@ watch(totalPages, () => {
10735
10737
  });
10736
10738
 
10737
10739
  // navigate by increase/decrease value
10738
- function next(usingScroll = false) {
10740
+ function next(usingScroll = false, source = 'next') {
10739
10741
  if (!useReaderSettings.blocked.value) {
10740
- if ((state.currentPage + 1) <= totalPages.value) {
10741
- set(state.currentPage + 1);
10742
+ if ((state.currentPage + 1) <= totalPages.value) {
10743
+ set(state.currentPage + 1, source);
10742
10744
  } else {
10743
10745
  // prevent going too fast to next chapter on
10744
10746
  // stronger scroll
@@ -10757,22 +10759,22 @@ function next(usingScroll = false) {
10757
10759
  }
10758
10760
  }
10759
10761
  }
10760
- onKeyStroke('ArrowRight', (e) => {
10761
- e.preventDefault();
10762
- next();
10762
+ onKeyStroke('ArrowRight', (e) => {
10763
+ e.preventDefault();
10764
+ next(false, 'keyboard');
10763
10765
  });
10764
10766
 
10765
10767
  function onWheel(event) {
10766
10768
  if (event.wheelDelta < 0) {
10767
- next(true);
10768
- } else {
10769
- prev(true);
10769
+ next(true, 'wheel');
10770
+ } else {
10771
+ prev(true, 'wheel');
10770
10772
  }
10771
10773
  }
10772
- function prev(usingScroll = false) {
10774
+ function prev(usingScroll = false, source = 'previous') {
10773
10775
  if (!useReaderSettings.blocked.value) {
10774
- if ((state.currentPage - 1) > 0) {
10775
- set(state.currentPage - 1);
10776
+ if ((state.currentPage - 1) > 0) {
10777
+ set(state.currentPage - 1, source);
10776
10778
  } else {
10777
10779
  // prevent going too fast to prev chapter on
10778
10780
  // stronger scroll
@@ -10793,25 +10795,29 @@ function prev(usingScroll = false) {
10793
10795
  }
10794
10796
  onKeyStroke('ArrowLeft', (e) => {
10795
10797
  e.preventDefault();
10796
- prev();
10798
+ prev(false, 'keyboard');
10797
10799
  });
10798
10800
 
10799
10801
  // navigate to specific page
10800
- function set(val) {
10802
+ function set(val, source = 'go-to-page') {
10801
10803
  const page = Math.min(totalPages.value, Math.max(1, Number(val) || 1));
10804
+ state.changeSource = source;
10802
10805
  state.currentPage = page;
10803
- useReadingProgress.save(page, totalPages.value);
10804
- }
10806
+ useReadingProgress.save(page, totalPages.value);
10807
+ }
10805
10808
 
10806
10809
  const usePagination = {
10807
10810
  currentPage,
10808
- totalPages,
10811
+ totalPages,
10812
+ changeSource,
10809
10813
  next,
10810
10814
  prev,
10811
10815
  init,
10812
10816
  set
10813
10817
  };
10814
10818
 
10819
+ const publicEventKey = Symbol('paginarPublicEvent');
10820
+
10815
10821
  const _hoisted_1$o = ["role"];
10816
10822
  const _hoisted_2$c = { class: "summary-menu-dropdown-item-title" };
10817
10823
  const _hoisted_3$4 = {
@@ -10822,14 +10828,16 @@ const _hoisted_3$4 = {
10822
10828
  const _sfc_main$q = {
10823
10829
  __name: 'SummaryDropdown',
10824
10830
  setup(__props) {
10825
-
10831
+
10826
10832
  const { summary } = useTextContent;
10827
-
10828
- async function getChapter(item) {
10829
- const text = await useTextContent.getContent(item.file);
10830
- useTextContent.applyContent(text, item);
10831
- usePagination.set(1);
10832
- }
10833
+ const publicEvent = inject(publicEventKey, () => {});
10834
+
10835
+ async function getChapter(item) {
10836
+ const text = await useTextContent.getContent(item.file);
10837
+ useTextContent.applyContent(text, item);
10838
+ usePagination.set(1, 'summary');
10839
+ publicEvent('chapter-change', { chapter: { ...item } });
10840
+ }
10833
10841
 
10834
10842
  return (_ctx, _cache) => {
10835
10843
  return (openBlock(), createElementBlock("div", {
@@ -10880,15 +10888,18 @@ const show = ref(false);
10880
10888
  const button = ref(null);
10881
10889
 
10882
10890
  const { homeUrl } = useReaderSettings;
10891
+ const publicEvent = inject(publicEventKey, () => {});
10883
10892
 
10884
10893
  const toggleSummary = () => {
10885
10894
  show.value = !show.value;
10886
10895
  useReaderSettings.setBlocked(show.value);
10896
+ publicEvent('summary-toggle', { open: show.value });
10887
10897
  };
10888
10898
  const hide = () => {
10889
- if (!useReaderSettings.blocked.value) {
10899
+ if (show.value && !useReaderSettings.blocked.value) {
10890
10900
  show.value = false;
10891
10901
  useReaderSettings.setBlocked(false);
10902
+ publicEvent('summary-toggle', { open: false });
10892
10903
  }
10893
10904
  };
10894
10905
 
@@ -11271,13 +11282,13 @@ return (_ctx, _cache) => {
11271
11282
 
11272
11283
  const _hoisted_1$c = { class: "w-full border-t border-areia mt-5 pt-5" };
11273
11284
  const _hoisted_2$8 = ["aria-checked"];
11274
-
11285
+
11275
11286
 
11276
11287
  const _sfc_main$c = {
11277
11288
  __name: 'OptionsReadingProgress',
11278
11289
  setup(__props) {
11279
-
11280
- const { enabled, setEnabled } = useReadingProgress;
11290
+
11291
+ const { enabled, setEnabled } = useReadingProgress;
11281
11292
 
11282
11293
  return (_ctx, _cache) => {
11283
11294
  return (openBlock(), createElementBlock("div", _hoisted_1$c, [
@@ -11374,10 +11385,15 @@ const _sfc_main$a = {
11374
11385
  const show = ref(false);
11375
11386
  const button = ref(null);
11376
11387
 
11377
- const toggleSummary = () => show.value = !show.value;
11388
+ const publicEvent = inject(publicEventKey, () => {});
11389
+ const toggleSummary = () => {
11390
+ show.value = !show.value;
11391
+ publicEvent('options-toggle', { open: show.value });
11392
+ };
11378
11393
  const hide = () => {
11379
- if (!useReaderSettings.blocked.value) {
11380
- show.value = false;
11394
+ if (show.value && !useReaderSettings.blocked.value) {
11395
+ show.value = false;
11396
+ publicEvent('options-toggle', { open: false });
11381
11397
  }
11382
11398
  };
11383
11399
 
@@ -11596,12 +11612,12 @@ return (_ctx, _cache) => {
11596
11612
  createBaseVNode("div", _hoisted_2$3, [
11597
11613
  createVNode(NavigationButton, {
11598
11614
  target: "prev",
11599
- onClicked: _cache[0] || (_cache[0] = $event => (unref(prev)()))
11615
+ onClicked: _cache[0] || (_cache[0] = $event => (unref(prev)(false, 'previous-button')))
11600
11616
  }),
11601
11617
  renderSlot(_ctx.$slots, "default"),
11602
11618
  createVNode(NavigationButton, {
11603
11619
  target: "next",
11604
- onClicked: _cache[1] || (_cache[1] = $event => (unref(next)()))
11620
+ onClicked: _cache[1] || (_cache[1] = $event => (unref(next)(false, 'next-button')))
11605
11621
  })
11606
11622
  ])
11607
11623
  ]))
@@ -11625,10 +11641,10 @@ const { distanceX } = usePointerSwipe(el, {
11625
11641
  onSwipeEnd() {
11626
11642
  if (width.value < 600) {
11627
11643
  if (distanceX.value > 100) {
11628
- usePagination.next();
11644
+ usePagination.next(false, 'swipe');
11629
11645
  }
11630
11646
  if (distanceX.value < -100) {
11631
- usePagination.prev();
11647
+ usePagination.prev(false, 'swipe');
11632
11648
  }
11633
11649
  }
11634
11650
  }
@@ -11731,7 +11747,7 @@ return (_ctx, _cache) => {
11731
11747
  ]),
11732
11748
  createVNode(unref(m), {
11733
11749
  modelValue: unref(currentPage),
11734
- "onUpdate:modelValue": _cache[0] || (_cache[0] = $event => (unref(set)(Math.round($event)))),
11750
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = $event => (unref(set)(Math.round($event), 'slider'))),
11735
11751
  min: 1,
11736
11752
  max: unref(totalPages),
11737
11753
  step: -1,
@@ -11889,144 +11905,222 @@ const _style_1 = "/* In your Vue component's <style> section */\n:host {\n -web
11889
11905
 
11890
11906
  const _hoisted_1 = { class: "text-white text-center text-sm" };
11891
11907
  const _hoisted_2 = { class: "text-white text-center text-xs" };
11892
-
11908
+
11893
11909
 
11894
11910
  const _sfc_main = {
11895
11911
  __name: 'App.ce',
11896
- props: {
11897
- bookTitle: String,
11898
- bookContent: String,
11899
- readerSettings: String,
11900
- readerBlocked: Boolean,
11901
- rootClass: {
11902
- type: String,
11903
- default: ''
11904
- },
11905
- cssFile: String,
11906
- cssString: String
11912
+ props: {
11913
+ bookTitle: String,
11914
+ bookContent: String,
11915
+ readerSettings: String,
11916
+ readerBlocked: Boolean,
11917
+ rootClass: {
11918
+ type: String,
11919
+ default: ''
11920
+ },
11921
+ cssFile: String,
11922
+ cssString: String
11907
11923
  },
11908
11924
  setup(__props) {
11909
-
11910
- const props = __props;
11911
-
11912
- const { baseFont, bookTitle, chapterTitle, textFont, fontSize, columns, setColumns, mode } = useReaderSettings;
11913
- const { currentPage, totalPages } = usePagination;
11914
- const { content, listenToClicks } = useTextContent;
11915
- const { width, height } = useWindowSize();
11916
-
11917
- const readerComponent = ref(null);
11918
- const contentArea = ref(null);
11919
- const rootComponent = ref(null);
11925
+
11926
+ const props = __props;
11927
+
11928
+ const { baseFont, bookTitle, chapterTitle, textFont, fontSize, columns, setColumns, mode } = useReaderSettings;
11929
+ const { currentPage, totalPages, changeSource } = usePagination;
11930
+ const { content, listenToClicks } = useTextContent;
11931
+ const { width, height } = useWindowSize();
11932
+
11933
+ const readerComponent = ref(null);
11934
+ const contentArea = ref(null);
11935
+ const rootComponent = ref(null);
11920
11936
  let paginationRevision = 0;
11937
+ let hostElement = null;
11921
11938
 
11922
- function syncReadingProgress(allowRestore = false) {
11923
- const targetPage = useReadingProgress.sync(
11924
- currentPage.value,
11925
- totalPages.value,
11926
- allowRestore
11927
- );
11928
- if (targetPage)
11929
- usePagination.set(targetPage);
11930
- }
11931
-
11932
- function estimatePagesAndSyncProgress() {
11933
- const revision = ++paginationRevision;
11934
- const previousPage = currentPage.value;
11935
- const previousTotal = totalPages.value;
11936
- useReadingProgress.suspend();
11937
- const nextTotal = useEstimatePages.estimate(readerComponent, contentArea);
11938
-
11939
- nextTick(() => requestAnimationFrame(() => {
11940
- if (revision !== paginationRevision)
11941
- return
11942
-
11943
- const targetPage = useReadingProgress.repaginate(
11944
- previousPage,
11945
- previousTotal,
11946
- nextTotal
11947
- );
11948
-
11949
- if (targetPage)
11950
- usePagination.set(targetPage);
11951
- else
11952
- syncReadingProgress(true);
11953
-
11954
- useReadingProgress.resume();
11955
- useReadingProgress.save(currentPage.value, nextTotal);
11956
- }));
11939
+ function getState() {
11940
+ const currentChapter = useTextContent.context.value.chapter;
11941
+ return {
11942
+ pagination: {
11943
+ currentPage: currentPage.value,
11944
+ totalPages: totalPages.value,
11945
+ progress: totalPages.value > 1
11946
+ ? (currentPage.value - 1) / (totalPages.value - 1)
11947
+ : 0
11948
+ },
11949
+ settings: {
11950
+ baseFont: baseFont.value,
11951
+ textFont: textFont.value,
11952
+ fontSize: fontSize.value,
11953
+ columns: columns.value,
11954
+ mode: mode.value,
11955
+ blocked: useReaderSettings.blocked.value,
11956
+ readingProgressEnabled: useReaderSettings.readingProgressEnabled.value
11957
+ },
11958
+ content: {
11959
+ bookTitle: props.bookTitle || bookTitle.value,
11960
+ chapterTitle: chapterTitle.value,
11961
+ chapter: currentChapter ? { ...currentChapter } : null
11962
+ }
11963
+ }
11957
11964
  }
11958
11965
 
11959
- function saveCurrentReadingProgress() {
11960
- useReadingProgress.save(currentPage.value, totalPages.value);
11961
- }
11966
+ function dispatchPublicEvent(name, detail = {}) {
11967
+ if (!hostElement)
11968
+ return
11962
11969
 
11963
- function saveReadingProgressWhenHidden() {
11964
- if (document.visibilityState === 'hidden')
11965
- saveCurrentReadingProgress();
11970
+ hostElement.dispatchEvent(new CustomEvent(`paginar:${name}`, {
11971
+ bubbles: true,
11972
+ composed: true,
11973
+ detail: { ...detail, state: getState() }
11974
+ }));
11966
11975
  }
11967
11976
 
11977
+ provide(publicEventKey, dispatchPublicEvent);
11978
+
11979
+ function syncReadingProgress(allowRestore = false) {
11980
+ const targetPage = useReadingProgress.sync(
11981
+ currentPage.value,
11982
+ totalPages.value,
11983
+ allowRestore
11984
+ );
11985
+ if (targetPage)
11986
+ usePagination.set(targetPage, 'reading-progress');
11987
+ }
11988
+
11989
+ function estimatePagesAndSyncProgress() {
11990
+ const revision = ++paginationRevision;
11991
+ const previousPage = currentPage.value;
11992
+ const previousTotal = totalPages.value;
11993
+ useReadingProgress.suspend();
11994
+ const nextTotal = useEstimatePages.estimate(readerComponent, contentArea);
11995
+
11996
+ nextTick(() => requestAnimationFrame(() => {
11997
+ if (revision !== paginationRevision)
11998
+ return
11999
+
12000
+ const targetPage = useReadingProgress.repaginate(
12001
+ previousPage,
12002
+ previousTotal,
12003
+ nextTotal
12004
+ );
12005
+
12006
+ if (targetPage)
12007
+ usePagination.set(targetPage, 'repagination');
12008
+ else
12009
+ syncReadingProgress(true);
12010
+
12011
+ useReadingProgress.resume();
12012
+ useReadingProgress.save(currentPage.value, nextTotal);
12013
+ }));
12014
+ }
12015
+
12016
+ function saveCurrentReadingProgress() {
12017
+ useReadingProgress.save(currentPage.value, totalPages.value);
12018
+ }
12019
+
12020
+ function saveReadingProgressWhenHidden() {
12021
+ if (document.visibilityState === 'hidden')
12022
+ saveCurrentReadingProgress();
12023
+ }
12024
+
11968
12025
  onMounted(async () => {
11969
- useReaderSettings.initSettings(props.readerSettings);
11970
- useReadingProgress.init(
11971
- props.readerSettings,
11972
- props.bookTitle || bookTitle.value
11973
- );
11974
- usePagination.init(readerComponent, contentArea, estimatePagesAndSyncProgress);
11975
- requestAnimationFrame(() => {
11976
- estimatePagesAndSyncProgress();
11977
- });
11978
- useStyles.initStyles(props, rootComponent);
11979
- window.addEventListener('pagehide', saveCurrentReadingProgress);
11980
- document.addEventListener('visibilitychange', saveReadingProgressWhenHidden);
11981
-
12026
+ hostElement = rootComponent.value?.getRootNode()?.host || null;
12027
+ if (hostElement) {
12028
+ hostElement.getState = getState;
12029
+ hostElement.goToPage = page => usePagination.set(page, 'api');
12030
+ hostElement.nextPage = () => usePagination.next(false, 'api');
12031
+ hostElement.previousPage = () => usePagination.prev(false, 'api');
12032
+ }
12033
+ useReaderSettings.initSettings(props.readerSettings);
12034
+ useReadingProgress.init(
12035
+ props.readerSettings,
12036
+ props.bookTitle || bookTitle.value
12037
+ );
12038
+ usePagination.init(readerComponent, contentArea, estimatePagesAndSyncProgress);
12039
+ requestAnimationFrame(() => {
12040
+ estimatePagesAndSyncProgress();
12041
+ });
12042
+ useStyles.initStyles(props, rootComponent);
12043
+ window.addEventListener('pagehide', saveCurrentReadingProgress);
12044
+ document.addEventListener('visibilitychange', saveReadingProgressWhenHidden);
12045
+
11982
12046
  if (['string', 'boolean'].includes(typeof props.readerBlocked)) {
11983
- useReaderSettings.setBlocked(props.readerBlocked);
12047
+ useReaderSettings.setBlocked(props.readerBlocked);
11984
12048
  }
11985
-
11986
- });
11987
-
12049
+ nextTick(() => requestAnimationFrame(() => dispatchPublicEvent('ready')));
12050
+
12051
+ });
12052
+
11988
12053
  onBeforeUnmount(() => {
11989
- window.removeEventListener('pagehide', saveCurrentReadingProgress);
12054
+ window.removeEventListener('pagehide', saveCurrentReadingProgress);
11990
12055
  document.removeEventListener('visibilitychange', saveReadingProgressWhenHidden);
11991
- });
11992
-
11993
- watch(
11994
- props,
11995
- () => {
11996
- if (props.hasOwnProperty('readerBlocked')) {
11997
- const readerBlocked = typeof props.readerBlocked === 'boolean'
11998
- ? props.readerBlocked
11999
- : props.readerBlocked === 'true';
12000
- useReaderSettings.setBlocked(readerBlocked);
12001
- }
12056
+ if (hostElement) {
12057
+ delete hostElement.getState;
12058
+ delete hostElement.goToPage;
12059
+ delete hostElement.nextPage;
12060
+ delete hostElement.previousPage;
12002
12061
  }
12003
- );
12004
-
12005
- watchDebounced(
12006
- [width, height, content, columns, fontSize, textFont],
12007
- () => {
12008
- if (width.value < 1024 && columns.value === 'double')
12009
- setColumns('single');
12010
- else {
12011
- requestAnimationFrame(() => {
12012
- estimatePagesAndSyncProgress();
12013
- });
12014
- }
12015
- },
12016
- { debounce: 125, maxWait: 250 }
12017
- );
12018
-
12062
+ hostElement = null;
12063
+ });
12064
+
12065
+ watch(
12066
+ props,
12067
+ () => {
12068
+ if (props.hasOwnProperty('readerBlocked')) {
12069
+ const readerBlocked = typeof props.readerBlocked === 'boolean'
12070
+ ? props.readerBlocked
12071
+ : props.readerBlocked === 'true';
12072
+ useReaderSettings.setBlocked(readerBlocked);
12073
+ }
12074
+ }
12075
+ );
12076
+
12077
+ watchDebounced(
12078
+ [width, height, content, columns, fontSize, textFont],
12079
+ () => {
12080
+ if (width.value < 1024 && columns.value === 'double')
12081
+ setColumns('single');
12082
+ else {
12083
+ requestAnimationFrame(() => {
12084
+ estimatePagesAndSyncProgress();
12085
+ });
12086
+ }
12087
+ },
12088
+ { debounce: 125, maxWait: 250 }
12089
+ );
12090
+
12019
12091
  watch(
12020
12092
  currentPage,
12021
- () => syncReadingProgress(),
12093
+ (value, previousValue) => {
12094
+ syncReadingProgress();
12095
+ dispatchPublicEvent('page-change', {
12096
+ page: value,
12097
+ previousPage: previousValue,
12098
+ source: changeSource.value
12099
+ });
12100
+ },
12022
12101
  { flush: 'sync' }
12023
12102
  );
12024
12103
 
12025
- watchDebounced(content,
12026
- () => listenToClicks(contentArea),
12027
- { debounce: 125, maxWait: 250 }
12104
+ watch(
12105
+ [baseFont, textFont, fontSize, columns, mode, useReaderSettings.readingProgressEnabled],
12106
+ (values, previousValues) => {
12107
+ const names = ['baseFont', 'textFont', 'fontSize', 'columns', 'mode', 'readingProgressEnabled'];
12108
+ const changes = names.reduce((result, name, index) => {
12109
+ if (values[index] !== previousValues[index])
12110
+ result[name] = { previous: previousValues[index], value: values[index] };
12111
+ return result
12112
+ }, {});
12113
+ if (Object.keys(changes).length)
12114
+ dispatchPublicEvent('settings-change', { changes });
12115
+ },
12116
+ { flush: 'post' }
12028
12117
  );
12029
-
12118
+
12119
+ watchDebounced(content,
12120
+ () => listenToClicks(contentArea),
12121
+ { debounce: 125, maxWait: 250 }
12122
+ );
12123
+
12030
12124
 
12031
12125
  return (_ctx, _cache) => {
12032
12126
  return (openBlock(), createElementBlock("div", {
@@ -12036,11 +12130,11 @@ return (_ctx, _cache) => {
12036
12130
  id: "rootComponent",
12037
12131
  ref_key: "rootComponent",
12038
12132
  ref: rootComponent,
12039
- class: normalizeClass(unref(mode)
12040
- .concat(` ${props.rootClass}`)
12041
- .concat(` currentPage-${unref(currentPage)}`)
12042
- .concat(` totalPages-${unref(totalPages)}`)
12043
- .concat(` columns-${unref(columns)}`)
12133
+ class: normalizeClass(unref(mode)
12134
+ .concat(` ${props.rootClass}`)
12135
+ .concat(` currentPage-${unref(currentPage)}`)
12136
+ .concat(` totalPages-${unref(totalPages)}`)
12137
+ .concat(` columns-${unref(columns)}`)
12044
12138
  ),
12045
12139
  style: normalizeStyle(`font-family: ${unref(baseFont)}`)
12046
12140
  }, [