paginar 0.3.4 → 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.
Files changed (60) hide show
  1. package/README.md +288 -236
  2. package/dist/index.es.js +684 -244
  3. package/dist/index.es.js.map +1 -1
  4. package/dist/style.css +63 -0
  5. package/package.json +6 -3
  6. package/.editorconfig +0 -13
  7. package/.env +0 -1
  8. package/.vscode/extensions.json +0 -3
  9. package/demo/slot/slot-chapter1.html +0 -384
  10. package/demo/slot/slot-chapter2.html +0 -366
  11. package/demo/slot/slot-chapter3.html +0 -265
  12. package/demo/summary/_content/1chapter.html +0 -100
  13. package/demo/summary/_content/2chapter.html +0 -311
  14. package/demo/summary/_content/3chapter.html +0 -211
  15. package/demo/summary/index.html +0 -134
  16. package/index.html +0 -18
  17. package/postcss.config.js +0 -7
  18. package/public/favicon.ico +0 -0
  19. package/src/App.ce.vue +0 -166
  20. package/src/assets/main.css +0 -392
  21. package/src/components/BookContent.vue +0 -23
  22. package/src/components/EngineWrapper.vue +0 -15
  23. package/src/components/FooterSlot.vue +0 -32
  24. package/src/components/FootnotesAside.vue +0 -123
  25. package/src/components/HeaderSlot/HeaderSlot.vue +0 -30
  26. package/src/components/HeaderSlot/OptionsButton/OptionsButton.vue +0 -67
  27. package/src/components/HeaderSlot/OptionsButton/OptionsColor.vue +0 -28
  28. package/src/components/HeaderSlot/OptionsButton/OptionsColumns.vue +0 -51
  29. package/src/components/HeaderSlot/OptionsButton/OptionsDropdown.vue +0 -59
  30. package/src/components/HeaderSlot/OptionsButton/OptionsFontFamily.vue +0 -17
  31. package/src/components/HeaderSlot/OptionsButton/OptionsFontSize.vue +0 -17
  32. package/src/components/HeaderSlot/SummaryButton/SummaryButton.vue +0 -74
  33. package/src/components/HeaderSlot/SummaryButton/SummaryDropdown.vue +0 -30
  34. package/src/components/NavigationButton.vue +0 -34
  35. package/src/components/ReaderWrapper.vue +0 -37
  36. package/src/components/ReferencePopup.vue +0 -36
  37. package/src/components/icons/Close.vue +0 -6
  38. package/src/components/icons/DoubleColumn.vue +0 -15
  39. package/src/components/icons/Expand.vue +0 -7
  40. package/src/components/icons/Eye.vue +0 -9
  41. package/src/components/icons/Footnote.vue +0 -5
  42. package/src/components/icons/Home.vue +0 -6
  43. package/src/components/icons/Moon.vue +0 -5
  44. package/src/components/icons/Notes.vue +0 -5
  45. package/src/components/icons/SingleColumn.vue +0 -3
  46. package/src/components/icons/Summary.vue +0 -10
  47. package/src/components/icons/Sun.vue +0 -5
  48. package/src/components/icons/ThreeDots.vue +0 -8
  49. package/src/composables/useBrowser.js +0 -16
  50. package/src/composables/useEstimatePages.js +0 -31
  51. package/src/composables/useFootnotes.js +0 -50
  52. package/src/composables/usePagination.js +0 -125
  53. package/src/composables/useReaderSettings.js +0 -174
  54. package/src/composables/useReferences.js +0 -67
  55. package/src/composables/useStyles.js +0 -60
  56. package/src/composables/useTextContent.js +0 -113
  57. package/src/main.js +0 -19
  58. package/src/tailwind.css +0 -1082
  59. package/tailwind.config.js +0 -16
  60. package/vite.config.js +0 -36
package/dist/index.es.js CHANGED
@@ -19,7 +19,7 @@ const isOn = (key) => key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 &&
19
19
  (key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97);
20
20
  const isModelListener = (key) => key.startsWith("onUpdate:");
21
21
  const extend = Object.assign;
22
- const remove = (arr, el) => {
22
+ const remove$1 = (arr, el) => {
23
23
  const i = arr.indexOf(el);
24
24
  if (i > -1) {
25
25
  arr.splice(i, 1);
@@ -1863,7 +1863,7 @@ function watch$1(source, cb, options = EMPTY_OBJ) {
1863
1863
  const watchHandle = () => {
1864
1864
  effect.stop();
1865
1865
  if (scope && scope.active) {
1866
- remove(scope.effects, effect);
1866
+ remove$1(scope.effects, effect);
1867
1867
  }
1868
1868
  };
1869
1869
  if (once && cb) {
@@ -3157,7 +3157,7 @@ function setRef(rawRef, oldRawRef, parentSuspense, vnode, isUnmount = false) {
3157
3157
  if (rawRef.f) {
3158
3158
  const existing = _isString ? canSetSetupRef(ref) ? setupState[ref] : refs[ref] : canSetRef(ref) || !rawRef.k ? ref.value : refs[rawRef.k];
3159
3159
  if (isUnmount) {
3160
- isArray(existing) && remove(existing, refValue);
3160
+ isArray(existing) && remove$1(existing, refValue);
3161
3161
  } else {
3162
3162
  if (!isArray(existing)) {
3163
3163
  if (_isString) {
@@ -3258,7 +3258,7 @@ function injectToKeepAliveRoot(hook, type, target, keepAliveRoot) {
3258
3258
  /* prepend */
3259
3259
  );
3260
3260
  onUnmounted(() => {
3261
- remove(keepAliveRoot[type], injected);
3261
+ remove$1(keepAliveRoot[type], injected);
3262
3262
  }, target);
3263
3263
  }
3264
3264
 
@@ -9945,7 +9945,7 @@ const useStyles = {
9945
9945
  applyStylesheet
9946
9946
  };
9947
9947
 
9948
- const state$5 = reactive({
9948
+ const state$6 = reactive({
9949
9949
  baseFont: 'Arial, sans-serif',
9950
9950
  textFont: 'Times New Roman, serif',
9951
9951
  fontsOptions: [
@@ -9958,26 +9958,30 @@ const state$5 = reactive({
9958
9958
  columns: 'double',
9959
9959
  mode: 'light',
9960
9960
  blocked: false,
9961
+ readingProgressAvailable: false,
9962
+ readingProgressEnabled: false,
9961
9963
 
9962
9964
  bookTitle: null,
9963
9965
  chapterTitle: null,
9964
9966
  homeUrl: null,
9965
9967
  });
9966
9968
 
9967
- const baseFont = computed(() => state$5.baseFont);
9968
- const textFont = computed(() => state$5.textFont);
9969
- const fontSize = computed(() => state$5.fontSize);
9970
- const fontsOptions = computed(() => state$5.fontsOptions);
9971
- const columns = computed(() => state$5.columns);
9972
- const mode = computed(() => state$5.mode);
9973
- const blocked = computed(() => state$5.blocked);
9969
+ const baseFont = computed(() => state$6.baseFont);
9970
+ const textFont = computed(() => state$6.textFont);
9971
+ const fontSize = computed(() => state$6.fontSize);
9972
+ const fontsOptions = computed(() => state$6.fontsOptions);
9973
+ const columns = computed(() => state$6.columns);
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);
9974
9978
 
9975
- const bookTitle = computed(() => state$5.bookTitle);
9976
- const chapterTitle = computed(() => state$5.chapterTitle);
9977
- const homeUrl = computed(() => state$5.homeUrl);
9979
+ const bookTitle = computed(() => state$6.bookTitle);
9980
+ const chapterTitle = computed(() => state$6.chapterTitle);
9981
+ const homeUrl = computed(() => state$6.homeUrl);
9978
9982
 
9979
9983
  watch(
9980
- [baseFont, textFont, fontSize, columns, mode],
9984
+ [baseFont, textFont, fontSize, columns, mode, readingProgressEnabled],
9981
9985
  () => saveSettings()
9982
9986
  );
9983
9987
 
@@ -9985,18 +9989,20 @@ async function initSettings(settingsString) {
9985
9989
  const settings = settingsString
9986
9990
  ? JSON.parse(settingsString)
9987
9991
  : null;
9992
+ state$6.readingProgressAvailable = false;
9993
+ state$6.readingProgressEnabled = false;
9988
9994
 
9989
9995
  if (settings?.baseFont)
9990
- state$5.baseFont = settings.baseFont;
9996
+ state$6.baseFont = settings.baseFont;
9991
9997
 
9992
9998
  if (settings?.textFont)
9993
- state$5.textFont = settings.textFont;
9999
+ state$6.textFont = settings.textFont;
9994
10000
 
9995
10001
  if (settings?.fontSize)
9996
- state$5.fontSize = Number(settings.fontSize);
10002
+ state$6.fontSize = Number(settings.fontSize);
9997
10003
 
9998
10004
  if (settings?.fontsOptions) {
9999
- state$5.fontsOptions = settings.fontsOptions;
10005
+ state$6.fontsOptions = settings.fontsOptions;
10000
10006
  useStyles.fontLoader(settings.fontsOptions);
10001
10007
 
10002
10008
  // baseFont
@@ -10004,42 +10010,66 @@ async function initSettings(settingsString) {
10004
10010
  item => item.defaultBaseFont
10005
10011
  );
10006
10012
  if (defaultBaseFont)
10007
- state$5.baseFont = defaultBaseFont.name;
10013
+ state$6.baseFont = defaultBaseFont.name;
10008
10014
 
10009
10015
  // textFont
10010
10016
  const defaultTextFont = settings.fontsOptions.find(
10011
10017
  item => item.defaultTextFont
10012
10018
  );
10013
10019
  if (defaultTextFont)
10014
- state$5.textFont = defaultTextFont.name;
10020
+ state$6.textFont = defaultTextFont.name;
10015
10021
  }
10016
10022
 
10017
10023
  if (settings?.bookTitle)
10018
- state$5.bookTitle = settings.bookTitle;
10024
+ state$6.bookTitle = settings.bookTitle;
10019
10025
 
10020
10026
  if (settings?.chapterTitle)
10021
- state$5.chapterTitle = settings.chapterTitle;
10027
+ state$6.chapterTitle = settings.chapterTitle;
10022
10028
 
10023
10029
  if (settings?.homeUrl)
10024
- state$5.homeUrl = 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
+ }
10025
10039
 
10026
10040
  loadSavedSettings(settings);
10027
10041
  }
10028
10042
 
10029
10043
  function loadSavedSettings(settings) {
10030
- const hasSettings = localStorage.getItem('readerSettings');
10044
+ let hasSettings = null;
10045
+ try {
10046
+ hasSettings = localStorage.getItem('readerSettings');
10047
+ } catch (error) {
10048
+ return
10049
+ }
10031
10050
 
10032
10051
  if (hasSettings) {
10033
- const savedSettings = JSON.parse(hasSettings);
10052
+ let savedSettings = null;
10053
+ try {
10054
+ savedSettings = JSON.parse(hasSettings);
10055
+ } catch (error) {
10056
+ return
10057
+ }
10034
10058
 
10035
- state$5.fontSize = savedSettings.fontSize;
10036
- state$5.columns = savedSettings.columns;
10037
- state$5.mode = savedSettings.mode;
10059
+ state$6.fontSize = savedSettings.fontSize;
10060
+ state$6.columns = savedSettings.columns;
10061
+ state$6.mode = savedSettings.mode;
10038
10062
 
10039
10063
  if (settings?.fontsOptions &&
10040
10064
  settings?.fontsOptions?.find(item => item.name === savedSettings.textFont)
10041
10065
  ) {
10042
- state$5.textFont = savedSettings.textFont;
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;
10043
10073
  }
10044
10074
 
10045
10075
  if (savedSettings.mode === 'dark') {
@@ -10053,23 +10083,28 @@ function loadSavedSettings(settings) {
10053
10083
  }
10054
10084
 
10055
10085
  function setColumns(value) {
10056
- state$5.columns = value;
10086
+ state$6.columns = value;
10057
10087
  }
10058
10088
 
10059
10089
  function setTextFont(value) {
10060
- state$5.textFont = value;
10090
+ state$6.textFont = value;
10061
10091
  }
10062
10092
 
10063
10093
  function setFontSize(value) {
10064
- state$5.fontSize = value;
10094
+ state$6.fontSize = value;
10065
10095
  }
10066
10096
 
10067
10097
  function setBlocked(value) {
10068
- state$5.blocked = value;
10098
+ state$6.blocked = value;
10099
+ }
10100
+
10101
+ function setReadingProgressEnabled(value) {
10102
+ if (state$6.readingProgressAvailable)
10103
+ state$6.readingProgressEnabled = Boolean(value);
10069
10104
  }
10070
10105
 
10071
10106
  function setMode(value) {
10072
- state$5.mode = value;
10107
+ state$6.mode = value;
10073
10108
 
10074
10109
  const htmlRoot = document.querySelector('html');
10075
10110
  if (htmlRoot) {
@@ -10085,15 +10120,22 @@ function setMode(value) {
10085
10120
  }
10086
10121
 
10087
10122
  function saveSettings() {
10088
- localStorage.setItem(
10089
- 'readerSettings',
10090
- JSON.stringify({
10123
+ try {
10124
+ localStorage.setItem(
10125
+ 'readerSettings',
10126
+ JSON.stringify({
10091
10127
  textFont: textFont.value,
10092
10128
  fontSize: fontSize.value,
10093
10129
  columns: columns.value,
10094
- mode: mode.value
10095
- })
10096
- );
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
+ }
10097
10139
  }
10098
10140
 
10099
10141
  const useReaderSettings = {
@@ -10109,7 +10151,10 @@ const useReaderSettings = {
10109
10151
  setBlocked,
10110
10152
  mode,
10111
10153
  blocked,
10154
+ readingProgressAvailable,
10155
+ readingProgressEnabled,
10112
10156
  setMode,
10157
+ setReadingProgressEnabled,
10113
10158
  saveSettings,
10114
10159
 
10115
10160
  bookTitle,
@@ -10125,9 +10170,9 @@ const _export_sfc = (sfc, props) => {
10125
10170
  return target;
10126
10171
  };
10127
10172
 
10128
- const _sfc_main$s = {};
10173
+ const _sfc_main$t = {};
10129
10174
 
10130
- const _hoisted_1$q = {
10175
+ const _hoisted_1$r = {
10131
10176
  fill: "none",
10132
10177
  stroke: "currentColor",
10133
10178
  viewBox: "0 0 20 22",
@@ -10135,7 +10180,7 @@ const _hoisted_1$q = {
10135
10180
  };
10136
10181
 
10137
10182
  function _sfc_render$c(_ctx, _cache) {
10138
- return (openBlock(), createElementBlock("svg", _hoisted_1$q, [...(_cache[0] || (_cache[0] = [
10183
+ return (openBlock(), createElementBlock("svg", _hoisted_1$r, [...(_cache[0] || (_cache[0] = [
10139
10184
  createBaseVNode("path", {
10140
10185
  d: "M1 8L10 1L19 8V19C19 19.5304 18.7893 20.0391 18.4142 20.4142C18.0391 20.7893 17.5304 21 17 21H3C2.46957 21 1.96086 20.7893 1.58579 20.4142C1.21071 20.0391 1 19.5304 1 19V8Z",
10141
10186
  "stroke-width": "2",
@@ -10150,11 +10195,11 @@ function _sfc_render$c(_ctx, _cache) {
10150
10195
  }, null, -1)
10151
10196
  ]))]))
10152
10197
  }
10153
- const IconHome = /*#__PURE__*/_export_sfc(_sfc_main$s, [['render',_sfc_render$c]]);
10198
+ const IconHome = /*#__PURE__*/_export_sfc(_sfc_main$t, [['render',_sfc_render$c]]);
10154
10199
 
10155
- const _sfc_main$r = {};
10200
+ const _sfc_main$s = {};
10156
10201
 
10157
- const _hoisted_1$p = {
10202
+ const _hoisted_1$q = {
10158
10203
  fill: "none",
10159
10204
  stroke: "currentColor",
10160
10205
  viewBox: "0 0 24 24",
@@ -10162,7 +10207,7 @@ const _hoisted_1$p = {
10162
10207
  };
10163
10208
 
10164
10209
  function _sfc_render$b(_ctx, _cache) {
10165
- return (openBlock(), createElementBlock("svg", _hoisted_1$p, [...(_cache[0] || (_cache[0] = [
10210
+ return (openBlock(), createElementBlock("svg", _hoisted_1$q, [...(_cache[0] || (_cache[0] = [
10166
10211
  createBaseVNode("path", {
10167
10212
  "stroke-linecap": "round",
10168
10213
  "stroke-linejoin": "round",
@@ -10171,11 +10216,11 @@ function _sfc_render$b(_ctx, _cache) {
10171
10216
  }, null, -1)
10172
10217
  ]))]))
10173
10218
  }
10174
- const IconClose = /*#__PURE__*/_export_sfc(_sfc_main$r, [['render',_sfc_render$b]]);
10219
+ const IconClose = /*#__PURE__*/_export_sfc(_sfc_main$s, [['render',_sfc_render$b]]);
10175
10220
 
10176
- const _sfc_main$q = {};
10221
+ const _sfc_main$r = {};
10177
10222
 
10178
- const _hoisted_1$o = {
10223
+ const _hoisted_1$p = {
10179
10224
  width: "24",
10180
10225
  height: "19",
10181
10226
  viewBox: "0 0 24 19",
@@ -10185,34 +10230,34 @@ const _hoisted_1$o = {
10185
10230
  };
10186
10231
 
10187
10232
  function _sfc_render$a(_ctx, _cache) {
10188
- return (openBlock(), createElementBlock("svg", _hoisted_1$o, [...(_cache[0] || (_cache[0] = [
10233
+ return (openBlock(), createElementBlock("svg", _hoisted_1$p, [...(_cache[0] || (_cache[0] = [
10189
10234
  createStaticVNode("<line x1=\"5\" y1=\"1.08447\" x2=\"1\" y2=\"1.08447\" stroke-width=\"2\" stroke-linecap=\"round\"></line><line x1=\"23\" y1=\"1.04248\" x2=\"11\" y2=\"1.04248\" stroke-width=\"2\" stroke-linecap=\"round\"></line><line x1=\"23\" y1=\"9.08447\" x2=\"14\" y2=\"9.08447\" stroke-width=\"2\" stroke-linecap=\"round\"></line><line x1=\"8\" y1=\"9.14905\" x2=\"4\" y2=\"9.14905\" stroke-width=\"2\" stroke-linecap=\"round\"></line><line x1=\"23\" y1=\"17.149\" x2=\"10.9993\" y2=\"17.149\" stroke-width=\"2\" stroke-linecap=\"round\"></line><line x1=\"5\" y1=\"17.2429\" x2=\"1\" y2=\"17.2429\" stroke-width=\"2\" stroke-linecap=\"round\"></line>", 6)
10190
10235
  ]))]))
10191
10236
  }
10192
- const IconSummary = /*#__PURE__*/_export_sfc(_sfc_main$q, [['render',_sfc_render$a]]);
10237
+ const IconSummary = /*#__PURE__*/_export_sfc(_sfc_main$r, [['render',_sfc_render$a]]);
10193
10238
 
10194
- const state$4 = reactive({
10239
+ const state$5 = reactive({
10195
10240
  references: [],
10196
10241
  reference: null
10197
10242
  });
10198
10243
 
10199
- const references = computed(() => state$4.references);
10244
+ const references = computed(() => state$5.references);
10200
10245
 
10201
10246
  function setReferences(references) {
10202
- state$4.references = references;
10247
+ state$5.references = references;
10203
10248
  }
10204
10249
 
10205
- const reference = computed(() => state$4.reference);
10250
+ const reference = computed(() => state$5.reference);
10206
10251
 
10207
10252
  function setHighlightedReference(reference) {
10208
- state$4.reference = reference;
10253
+ state$5.reference = reference;
10209
10254
  }
10210
10255
 
10211
10256
  function applyReferences(contentRaw) {
10212
- if (state$4.references.length === 0 || !contentRaw)
10257
+ if (state$5.references.length === 0 || !contentRaw)
10213
10258
  return contentRaw
10214
10259
 
10215
- return state$4.references.reduce((content, reference) => {
10260
+ return state$5.references.reduce((content, reference) => {
10216
10261
  if (!content) return content
10217
10262
 
10218
10263
  if (content.includes(reference.cit)) {
@@ -10238,11 +10283,11 @@ function applyReference(event) {
10238
10283
  const target = classList.find(item => item.startsWith('reference-'));
10239
10284
 
10240
10285
  if (target) {
10241
- const ref = state$4.references.find(
10286
+ const ref = state$5.references.find(
10242
10287
  item => target && item.cit.replaceAll(' ', '') === target.replace('reference-', '')
10243
10288
  );
10244
10289
  if (ref) {
10245
- state$4.reference = ref;
10290
+ state$5.reference = ref;
10246
10291
  }
10247
10292
  }
10248
10293
 
@@ -10257,25 +10302,25 @@ const useReferences = {
10257
10302
  applyReferences,
10258
10303
  };
10259
10304
 
10260
- const state$3 = reactive({
10305
+ const state$4 = reactive({
10261
10306
  footnotes: [],
10262
10307
  showFootnotes: false,
10263
10308
  footnote: null
10264
10309
  });
10265
10310
 
10266
- const footnotes = computed(() => state$3.footnotes);
10311
+ const footnotes = computed(() => state$4.footnotes);
10267
10312
  function setFootnotes(footnotes) {
10268
- state$3.footnotes = footnotes;
10313
+ state$4.footnotes = footnotes;
10269
10314
  }
10270
10315
 
10271
- const showFootnotes = computed(() => state$3.showFootnotes);
10316
+ const showFootnotes = computed(() => state$4.showFootnotes);
10272
10317
  function setShowFootnotes(value) {
10273
- state$3.showFootnotes = value;
10318
+ state$4.showFootnotes = value;
10274
10319
  }
10275
10320
 
10276
- const footnote = computed(() => state$3.footnote);
10321
+ const footnote = computed(() => state$4.footnote);
10277
10322
  function setHighlightedFootnote(footnote) {
10278
- state$3.footnote = footnote;
10323
+ state$4.footnote = footnote;
10279
10324
  }
10280
10325
 
10281
10326
  function applyFootnote(event) {
@@ -10289,9 +10334,9 @@ function applyFootnote(event) {
10289
10334
  );
10290
10335
 
10291
10336
  if (footnoteTarget) {
10292
- const ref = state$3.footnotes.find(item => item.id === footnoteTarget);
10337
+ const ref = state$4.footnotes.find(item => item.id === footnoteTarget);
10293
10338
  if (ref) {
10294
- state$3.footnote = ref;
10339
+ state$4.footnote = ref;
10295
10340
  }
10296
10341
  }
10297
10342
  }
@@ -10306,29 +10351,36 @@ const useFootnotes = {
10306
10351
  showFootnotes
10307
10352
  };
10308
10353
 
10309
- const state$2 = reactive({
10354
+ const state$3 = reactive({
10310
10355
  summary: null,
10311
- content: null
10356
+ content: null,
10357
+ activeChapter: 0
10312
10358
  });
10313
10359
 
10314
- const content = computed(() => state$2.content);
10315
- const summary = computed(() => state$2.summary);
10360
+ const content = computed(() => state$3.content);
10361
+ const summary = computed(() => state$3.summary);
10316
10362
  const context = computed(() => {
10317
- const current = state$2.summary.findIndex(
10363
+ const chapters = state$3.summary || [];
10364
+ const linkedChapter = chapters.findIndex(
10318
10365
  chapter => window.location.href.includes(chapter.link)
10319
10366
  );
10367
+ const current = linkedChapter >= 0 ? linkedChapter : state$3.activeChapter;
10320
10368
  return {
10321
- chapter: state$2.summary[current],
10369
+ chapter: chapters[current],
10322
10370
  surround: {
10323
10371
  before: current - 1 >= 0
10324
- ? state$2.summary[current - 1]
10372
+ ? chapters[current - 1]
10325
10373
  : null,
10326
- after: current + 1 <= state$2.summary.length
10327
- ? state$2.summary[current + 1]
10374
+ after: current + 1 < chapters.length
10375
+ ? chapters[current + 1]
10328
10376
  : null,
10329
10377
  }
10330
10378
  }
10331
10379
  });
10380
+ const contextId = computed(() => {
10381
+ const chapter = context.value.chapter;
10382
+ return chapter?.file || chapter?.link || chapter?.title || window.location.pathname
10383
+ });
10332
10384
 
10333
10385
  async function initContent(contentString, contentWrapper) {
10334
10386
  const { setReferences, applyReferences } = useReferences;
@@ -10339,7 +10391,7 @@ async function initContent(contentString, contentWrapper) {
10339
10391
  : null;
10340
10392
 
10341
10393
  if (content?.summary)
10342
- state$2.summary = content.summary;
10394
+ state$3.summary = content.summary;
10343
10395
 
10344
10396
  if (content?.references)
10345
10397
  setReferences(content.references);
@@ -10353,7 +10405,7 @@ async function initContent(contentString, contentWrapper) {
10353
10405
  const newContent = content.applyReferences
10354
10406
  ? applyReferences(text)
10355
10407
  : text;
10356
- state$2.content = newContent;
10408
+ state$3.content = newContent;
10357
10409
 
10358
10410
  // else if content comes from slot, apply references to slot
10359
10411
  } else {
@@ -10378,14 +10430,16 @@ async function getContent(location) {
10378
10430
  return text
10379
10431
  } catch (err) {
10380
10432
  console.log({ err });
10381
- state$2.content = 'Ops, não foi possível carregar o arquivo solicitado.';
10433
+ state$3.content = 'Ops, não foi possível carregar o arquivo solicitado.';
10382
10434
  }
10383
10435
  }
10384
10436
 
10385
- function applyContent(text) {
10437
+ function applyContent(text, chapter = null) {
10386
10438
  const { applyReferences } = useReferences;
10387
10439
  const newContent = applyReferences(text);
10388
- state$2.content = newContent;
10440
+ if (chapter)
10441
+ state$3.activeChapter = state$3.summary.findIndex(item => item === chapter);
10442
+ state$3.content = newContent;
10389
10443
  }
10390
10444
 
10391
10445
  function listenToClicks(contentWrapper) {
@@ -10411,10 +10465,11 @@ const useTextContent = {
10411
10465
  getContent,
10412
10466
  applyContent,
10413
10467
  listenToClicks,
10414
- context
10468
+ context,
10469
+ contextId
10415
10470
  };
10416
10471
 
10417
- const state$1 = reactive({
10472
+ const state$2 = reactive({
10418
10473
  totalPages: 1
10419
10474
  });
10420
10475
 
@@ -10424,20 +10479,20 @@ function estimate(viewport, content) {
10424
10479
  const { width: contentWidth } = content.value.getBoundingClientRect();
10425
10480
 
10426
10481
  if (contentWidth > viewportWidth) {
10427
- state$1.totalPages = Math.ceil(contentWidth / viewportWidth);
10482
+ state$2.totalPages = Math.ceil(contentWidth / viewportWidth);
10428
10483
  return Math.ceil(contentWidth / viewportWidth)
10429
10484
 
10430
10485
  } else {
10431
- state$1.totalPages = 1;
10486
+ state$2.totalPages = 1;
10432
10487
  return 1
10433
10488
  }
10434
10489
  } else {
10435
- state$1.totalPages = 1;
10490
+ state$2.totalPages = 1;
10436
10491
  return 1
10437
10492
  }
10438
10493
  }
10439
10494
 
10440
- const totalPages$1 = computed(() => state$1.totalPages);
10495
+ const totalPages$1 = computed(() => state$2.totalPages);
10441
10496
 
10442
10497
  const useEstimatePages = {
10443
10498
  totalPages: totalPages$1,
@@ -10461,17 +10516,196 @@ const useBrowser = {
10461
10516
  isApple
10462
10517
  };
10463
10518
 
10464
- const state = reactive({
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,
10465
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
+ };
10692
+
10693
+ const state = reactive({
10694
+ currentPage: 1,
10695
+ changeSource: 'initial',
10466
10696
  nextTry: 0,
10467
10697
  prevTry: 0,
10468
10698
  willRedirect: false
10469
10699
  });
10470
10700
 
10471
- const currentPage = computed(() => state.currentPage);
10701
+ const currentPage = computed(() => state.currentPage);
10702
+ const changeSource = computed(() => state.changeSource);
10472
10703
  const totalPages = computed(() => useEstimatePages.totalPages.value);
10473
10704
 
10474
- function init(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.
10475
10709
  useEstimatePages.estimate(viewport, content);
10476
10710
 
10477
10711
  // check if there is a query string for oring, and
@@ -10481,7 +10715,7 @@ function init(viewport, content) {
10481
10715
  const origin = urlParams.get('origin');
10482
10716
  if (origin && origin === 'next') {
10483
10717
  setTimeout(() => {
10484
- state.currentPage = totalPages.value;
10718
+ set(totalPages.value);
10485
10719
  }, 200);
10486
10720
  }
10487
10721
 
@@ -10490,7 +10724,7 @@ function init(viewport, content) {
10490
10724
  }
10491
10725
 
10492
10726
  setInterval(() => {
10493
- useEstimatePages.estimate(viewport, content);
10727
+ updatePages();
10494
10728
  }, 5000);
10495
10729
  }
10496
10730
 
@@ -10503,10 +10737,10 @@ watch(totalPages, () => {
10503
10737
  });
10504
10738
 
10505
10739
  // navigate by increase/decrease value
10506
- function next(usingScroll = false) {
10740
+ function next(usingScroll = false, source = 'next') {
10507
10741
  if (!useReaderSettings.blocked.value) {
10508
10742
  if ((state.currentPage + 1) <= totalPages.value) {
10509
- state.currentPage = state.currentPage + 1;
10743
+ set(state.currentPage + 1, source);
10510
10744
  } else {
10511
10745
  // prevent going too fast to next chapter on
10512
10746
  // stronger scroll
@@ -10525,22 +10759,22 @@ function next(usingScroll = false) {
10525
10759
  }
10526
10760
  }
10527
10761
  }
10528
- onKeyStroke('ArrowRight', (e) => {
10529
- e.preventDefault();
10530
- next();
10762
+ onKeyStroke('ArrowRight', (e) => {
10763
+ e.preventDefault();
10764
+ next(false, 'keyboard');
10531
10765
  });
10532
10766
 
10533
10767
  function onWheel(event) {
10534
10768
  if (event.wheelDelta < 0) {
10535
- next(true);
10536
- } else {
10537
- prev(true);
10769
+ next(true, 'wheel');
10770
+ } else {
10771
+ prev(true, 'wheel');
10538
10772
  }
10539
10773
  }
10540
- function prev(usingScroll = false) {
10774
+ function prev(usingScroll = false, source = 'previous') {
10541
10775
  if (!useReaderSettings.blocked.value) {
10542
10776
  if ((state.currentPage - 1) > 0) {
10543
- state.currentPage = state.currentPage - 1;
10777
+ set(state.currentPage - 1, source);
10544
10778
  } else {
10545
10779
  // prevent going too fast to prev chapter on
10546
10780
  // stronger scroll
@@ -10561,41 +10795,49 @@ function prev(usingScroll = false) {
10561
10795
  }
10562
10796
  onKeyStroke('ArrowLeft', (e) => {
10563
10797
  e.preventDefault();
10564
- prev();
10798
+ prev(false, 'keyboard');
10565
10799
  });
10566
10800
 
10567
10801
  // navigate to specific page
10568
- function set(val) {
10569
- state.currentPage = val;
10802
+ function set(val, source = 'go-to-page') {
10803
+ const page = Math.min(totalPages.value, Math.max(1, Number(val) || 1));
10804
+ state.changeSource = source;
10805
+ state.currentPage = page;
10806
+ useReadingProgress.save(page, totalPages.value);
10570
10807
  }
10571
10808
 
10572
10809
  const usePagination = {
10573
10810
  currentPage,
10574
- totalPages,
10811
+ totalPages,
10812
+ changeSource,
10575
10813
  next,
10576
10814
  prev,
10577
10815
  init,
10578
10816
  set
10579
10817
  };
10580
10818
 
10581
- const _hoisted_1$n = ["role"];
10582
- const _hoisted_2$b = { class: "summary-menu-dropdown-item-title" };
10819
+ const publicEventKey = Symbol('paginarPublicEvent');
10820
+
10821
+ const _hoisted_1$o = ["role"];
10822
+ const _hoisted_2$c = { class: "summary-menu-dropdown-item-title" };
10583
10823
  const _hoisted_3$4 = {
10584
10824
  key: 0,
10585
10825
  class: "summary-menu-dropdown-item-author"
10586
10826
  };
10587
10827
 
10588
- const _sfc_main$p = {
10828
+ const _sfc_main$q = {
10589
10829
  __name: 'SummaryDropdown',
10590
10830
  setup(__props) {
10591
-
10831
+
10592
10832
  const { summary } = useTextContent;
10593
-
10594
- async function getChapter(item) {
10595
- const text = await useTextContent.getContent(item.file);
10596
- useTextContent.applyContent(text);
10597
- usePagination.set(1);
10598
- }
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
+ }
10599
10841
 
10600
10842
  return (_ctx, _cache) => {
10601
10843
  return (openBlock(), createElementBlock("div", {
@@ -10616,7 +10858,7 @@ return (_ctx, _cache) => {
10616
10858
  onClick: $event => (item.file ? getChapter(item) : null)
10617
10859
  }, {
10618
10860
  default: withCtx(() => [
10619
- createBaseVNode("span", _hoisted_2$b, toDisplayString(item.title), 1),
10861
+ createBaseVNode("span", _hoisted_2$c, toDisplayString(item.title), 1),
10620
10862
  (item.author)
10621
10863
  ? (openBlock(), createElementBlock("span", _hoisted_3$4, toDisplayString(item.author), 1))
10622
10864
  : createCommentVNode("", true)
@@ -10626,19 +10868,19 @@ return (_ctx, _cache) => {
10626
10868
  }), 128)),
10627
10869
  renderSlot(_ctx.$slots, "summaryBottom")
10628
10870
  ])
10629
- ], 8, _hoisted_1$n))
10871
+ ], 8, _hoisted_1$o))
10630
10872
  }
10631
10873
  }
10632
10874
 
10633
10875
  };
10634
10876
 
10635
- const _hoisted_1$m = { class: "flex" };
10636
- const _hoisted_2$a = ["href"];
10877
+ const _hoisted_1$n = { class: "flex" };
10878
+ const _hoisted_2$b = ["href"];
10637
10879
  const _hoisted_3$3 = { class: "position-relative" };
10638
10880
  const _hoisted_4$2 = ["aria-expanded"];
10639
10881
 
10640
10882
 
10641
- const _sfc_main$o = {
10883
+ const _sfc_main$p = {
10642
10884
  __name: 'SummaryButton',
10643
10885
  setup(__props) {
10644
10886
 
@@ -10646,15 +10888,18 @@ const show = ref(false);
10646
10888
  const button = ref(null);
10647
10889
 
10648
10890
  const { homeUrl } = useReaderSettings;
10891
+ const publicEvent = inject(publicEventKey, () => {});
10649
10892
 
10650
10893
  const toggleSummary = () => {
10651
10894
  show.value = !show.value;
10652
10895
  useReaderSettings.setBlocked(show.value);
10896
+ publicEvent('summary-toggle', { open: show.value });
10653
10897
  };
10654
10898
  const hide = () => {
10655
- if (!useReaderSettings.blocked.value) {
10899
+ if (show.value && !useReaderSettings.blocked.value) {
10656
10900
  show.value = false;
10657
10901
  useReaderSettings.setBlocked(false);
10902
+ publicEvent('summary-toggle', { open: false });
10658
10903
  }
10659
10904
  };
10660
10905
 
@@ -10668,7 +10913,7 @@ return (_ctx, _cache) => {
10668
10913
  ref: button,
10669
10914
  class: "relative"
10670
10915
  }, [
10671
- createBaseVNode("div", _hoisted_1$m, [
10916
+ createBaseVNode("div", _hoisted_1$n, [
10672
10917
  (unref(homeUrl))
10673
10918
  ? (openBlock(), createElementBlock("a", {
10674
10919
  key: 0,
@@ -10678,7 +10923,7 @@ return (_ctx, _cache) => {
10678
10923
  class: "hidden md:flex items-center border p-3 shadow mr-3 border-white text-white"
10679
10924
  }, [
10680
10925
  createVNode(IconHome, { class: "w-6 h-6" })
10681
- ], 8, _hoisted_2$a))
10926
+ ], 8, _hoisted_2$b))
10682
10927
  : createCommentVNode("", true),
10683
10928
  createBaseVNode("div", _hoisted_3$3, [
10684
10929
  createBaseVNode("button", {
@@ -10706,7 +10951,7 @@ return (_ctx, _cache) => {
10706
10951
  }, {
10707
10952
  default: withCtx(() => [
10708
10953
  (show.value)
10709
- ? (openBlock(), createBlock(_sfc_main$p, { key: 0 }, {
10954
+ ? (openBlock(), createBlock(_sfc_main$q, { key: 0 }, {
10710
10955
  summaryTop: withCtx(() => [
10711
10956
  renderSlot(_ctx.$slots, "summaryTop")
10712
10957
  ]),
@@ -10727,9 +10972,9 @@ return (_ctx, _cache) => {
10727
10972
 
10728
10973
  };
10729
10974
 
10730
- const _sfc_main$n = {};
10975
+ const _sfc_main$o = {};
10731
10976
 
10732
- const _hoisted_1$l = {
10977
+ const _hoisted_1$m = {
10733
10978
  fill: "none",
10734
10979
  stroke: "currentColor",
10735
10980
  viewBox: "0 0 24 24",
@@ -10737,7 +10982,7 @@ const _hoisted_1$l = {
10737
10982
  };
10738
10983
 
10739
10984
  function _sfc_render$9(_ctx, _cache) {
10740
- return (openBlock(), createElementBlock("svg", _hoisted_1$l, [...(_cache[0] || (_cache[0] = [
10985
+ return (openBlock(), createElementBlock("svg", _hoisted_1$m, [...(_cache[0] || (_cache[0] = [
10741
10986
  createBaseVNode("path", {
10742
10987
  "stroke-linecap": "round",
10743
10988
  "stroke-linejoin": "round",
@@ -10746,11 +10991,11 @@ function _sfc_render$9(_ctx, _cache) {
10746
10991
  }, null, -1)
10747
10992
  ]))]))
10748
10993
  }
10749
- const IconThreeDots = /*#__PURE__*/_export_sfc(_sfc_main$n, [['render',_sfc_render$9]]);
10994
+ const IconThreeDots = /*#__PURE__*/_export_sfc(_sfc_main$o, [['render',_sfc_render$9]]);
10750
10995
 
10751
- const _sfc_main$m = {};
10996
+ const _sfc_main$n = {};
10752
10997
 
10753
- const _hoisted_1$k = {
10998
+ const _hoisted_1$l = {
10754
10999
  fill: "none",
10755
11000
  stroke: "currentColor",
10756
11001
  viewBox: "0 0 24 24",
@@ -10758,7 +11003,7 @@ const _hoisted_1$k = {
10758
11003
  };
10759
11004
 
10760
11005
  function _sfc_render$8(_ctx, _cache) {
10761
- return (openBlock(), createElementBlock("svg", _hoisted_1$k, [...(_cache[0] || (_cache[0] = [
11006
+ return (openBlock(), createElementBlock("svg", _hoisted_1$l, [...(_cache[0] || (_cache[0] = [
10762
11007
  createBaseVNode("path", {
10763
11008
  "stroke-linecap": "round",
10764
11009
  "stroke-linejoin": "round",
@@ -10767,11 +11012,11 @@ function _sfc_render$8(_ctx, _cache) {
10767
11012
  }, null, -1)
10768
11013
  ]))]))
10769
11014
  }
10770
- const IconExpand = /*#__PURE__*/_export_sfc(_sfc_main$m, [['render',_sfc_render$8]]);
11015
+ const IconExpand = /*#__PURE__*/_export_sfc(_sfc_main$n, [['render',_sfc_render$8]]);
10771
11016
 
10772
- const _sfc_main$l = {};
11017
+ const _sfc_main$m = {};
10773
11018
 
10774
- const _hoisted_1$j = {
11019
+ const _hoisted_1$k = {
10775
11020
  fill: "none",
10776
11021
  stroke: "currentColor",
10777
11022
  viewBox: "0 0 24 24",
@@ -10779,7 +11024,7 @@ const _hoisted_1$j = {
10779
11024
  };
10780
11025
 
10781
11026
  function _sfc_render$7(_ctx, _cache) {
10782
- return (openBlock(), createElementBlock("svg", _hoisted_1$j, [...(_cache[0] || (_cache[0] = [
11027
+ return (openBlock(), createElementBlock("svg", _hoisted_1$k, [...(_cache[0] || (_cache[0] = [
10783
11028
  createBaseVNode("path", {
10784
11029
  "stroke-linecap": "round",
10785
11030
  "stroke-linejoin": "round",
@@ -10794,11 +11039,11 @@ function _sfc_render$7(_ctx, _cache) {
10794
11039
  }, null, -1)
10795
11040
  ]))]))
10796
11041
  }
10797
- const IconEye = /*#__PURE__*/_export_sfc(_sfc_main$l, [['render',_sfc_render$7]]);
11042
+ const IconEye = /*#__PURE__*/_export_sfc(_sfc_main$m, [['render',_sfc_render$7]]);
10798
11043
 
10799
- const _sfc_main$k = {};
11044
+ const _sfc_main$l = {};
10800
11045
 
10801
- const _hoisted_1$i = {
11046
+ const _hoisted_1$j = {
10802
11047
  fill: "none",
10803
11048
  stroke: "currentColor",
10804
11049
  viewBox: "0 0 24 24",
@@ -10806,7 +11051,7 @@ const _hoisted_1$i = {
10806
11051
  };
10807
11052
 
10808
11053
  function _sfc_render$6(_ctx, _cache) {
10809
- return (openBlock(), createElementBlock("svg", _hoisted_1$i, [...(_cache[0] || (_cache[0] = [
11054
+ return (openBlock(), createElementBlock("svg", _hoisted_1$j, [...(_cache[0] || (_cache[0] = [
10810
11055
  createBaseVNode("path", {
10811
11056
  "stroke-linecap": "round",
10812
11057
  "stroke-linejoin": "round",
@@ -10815,43 +11060,43 @@ function _sfc_render$6(_ctx, _cache) {
10815
11060
  }, null, -1)
10816
11061
  ]))]))
10817
11062
  }
10818
- const IconFootnote = /*#__PURE__*/_export_sfc(_sfc_main$k, [['render',_sfc_render$6]]);
11063
+ const IconFootnote = /*#__PURE__*/_export_sfc(_sfc_main$l, [['render',_sfc_render$6]]);
10819
11064
 
10820
- const _sfc_main$j = {};
11065
+ const _sfc_main$k = {};
10821
11066
 
10822
- const _hoisted_1$h = {
11067
+ const _hoisted_1$i = {
10823
11068
  viewBox: "0 0 341.5 441.2",
10824
11069
  fill: "currentColor"
10825
11070
  };
10826
11071
 
10827
11072
  function _sfc_render$5(_ctx, _cache) {
10828
- return (openBlock(), createElementBlock("svg", _hoisted_1$h, [...(_cache[0] || (_cache[0] = [
11073
+ return (openBlock(), createElementBlock("svg", _hoisted_1$i, [...(_cache[0] || (_cache[0] = [
10829
11074
  createStaticVNode("<rect data-v-acadaaca=\"\" x=\"73.2\" y=\"143.7\" width=\"195.2\" height=\"20\"></rect><rect data-v-acadaaca=\"\" x=\"73.2\" y=\"82.7\" width=\"195.2\" height=\"20\"></rect><rect data-v-acadaaca=\"\" x=\"73.2\" y=\"203.7\" width=\"195.2\" height=\"20\"></rect><rect data-v-acadaaca=\"\" x=\"73.2\" y=\"263.7\" width=\"195.2\" height=\"20\"></rect><rect data-v-acadaaca=\"\" x=\"73.2\" y=\"319\" width=\"195.2\" height=\"20\"></rect><rect data-v-acadaaca=\"\" x=\"0\" y=\"-0.6\" width=\"332.3\" height=\"15\"></rect><rect data-v-acadaaca=\"\" x=\"0\" y=\"426.2\" width=\"332.3\" height=\"15\"></rect><rect data-v-acadaaca=\"\" x=\"-209.4\" y=\"216.2\" transform=\"matrix(6.123234e-17 -1 1 6.123234e-17 -216.2339 231.2339)\" width=\"433.7\" height=\"15\"></rect><rect data-v-acadaaca=\"\" x=\"108\" y=\"211.9\" transform=\"matrix(6.123234e-17 -1 1 6.123234e-17 105.4808 544.1859)\" width=\"433.7\" height=\"15\"></rect>", 9)
10830
11075
  ]))]))
10831
11076
  }
10832
- const SingleColumn = /*#__PURE__*/_export_sfc(_sfc_main$j, [['render',_sfc_render$5]]);
11077
+ const SingleColumn = /*#__PURE__*/_export_sfc(_sfc_main$k, [['render',_sfc_render$5]]);
10833
11078
 
10834
- const _sfc_main$i = {};
11079
+ const _sfc_main$j = {};
10835
11080
 
10836
- const _hoisted_1$g = {
11081
+ const _hoisted_1$h = {
10837
11082
  viewBox: "0 0 653 441.2",
10838
11083
  fill: "currentColor"
10839
11084
  };
10840
11085
 
10841
11086
  function _sfc_render$4(_ctx, _cache) {
10842
- return (openBlock(), createElementBlock("svg", _hoisted_1$g, [...(_cache[0] || (_cache[0] = [
11087
+ return (openBlock(), createElementBlock("svg", _hoisted_1$h, [...(_cache[0] || (_cache[0] = [
10843
11088
  createStaticVNode("<rect x=\"73.2\" y=\"143.7\" width=\"195.2\" height=\"20\"></rect><rect x=\"73.2\" y=\"82.7\" width=\"195.2\" height=\"20\"></rect><rect x=\"73.2\" y=\"203.7\" width=\"195.2\" height=\"20\"></rect><rect x=\"73.2\" y=\"263.7\" width=\"195.2\" height=\"20\"></rect><rect x=\"73.2\" y=\"319\" width=\"195.2\" height=\"20\"></rect><rect x=\"384.7\" y=\"143.7\" width=\"195.2\" height=\"20\"></rect><rect x=\"384.7\" y=\"82.7\" width=\"195.2\" height=\"20\"></rect><rect x=\"384.7\" y=\"203.7\" width=\"195.2\" height=\"20\"></rect><rect x=\"384.7\" y=\"263.7\" width=\"195.2\" height=\"20\"></rect><rect x=\"384.7\" y=\"319\" width=\"195.2\" height=\"20\"></rect><path d=\"M0-0.6v7.5v7.5v411.8v14.4v0.6h653v-5v-10V14.4V2.5v-3.1H0z M638,426.2H15V14.4h623V426.2z\"></path>", 11)
10844
11089
  ]))]))
10845
11090
  }
10846
- const DoubleColumn = /*#__PURE__*/_export_sfc(_sfc_main$i, [['render',_sfc_render$4]]);
11091
+ const DoubleColumn = /*#__PURE__*/_export_sfc(_sfc_main$j, [['render',_sfc_render$4]]);
10847
11092
 
10848
- const _hoisted_1$f = {
11093
+ const _hoisted_1$g = {
10849
11094
  id: "columns-menu",
10850
11095
  class: "w-full hidden md:grid grid-cols-3 gap-2 mt-3"
10851
11096
  };
10852
- const _hoisted_2$9 = ["title"];
11097
+ const _hoisted_2$a = ["title"];
10853
11098
 
10854
- const _sfc_main$h = {
11099
+ const _sfc_main$i = {
10855
11100
  __name: 'OptionsColumns',
10856
11101
  setup(__props) {
10857
11102
 
@@ -10865,7 +11110,7 @@ const isSafari = computed(() => {
10865
11110
 
10866
11111
 
10867
11112
  return (_ctx, _cache) => {
10868
- return (openBlock(), createElementBlock("div", _hoisted_1$f, [
11113
+ return (openBlock(), createElementBlock("div", _hoisted_1$g, [
10869
11114
  createBaseVNode("button", {
10870
11115
  id: "single-column-button",
10871
11116
  class: normalizeClass(["col-span-1 text-primary text-center cursor-pointer py-3 rounded-sm border", {
@@ -10878,7 +11123,7 @@ return (_ctx, _cache) => {
10878
11123
  title: isSafari.value ? 'O navegador Safari não aceita visualização de coluna única.' : 'Coluna única'
10879
11124
  }, [
10880
11125
  createVNode(SingleColumn, { class: "mx-auto h-10 opacity-75" })
10881
- ], 10, _hoisted_2$9),
11126
+ ], 10, _hoisted_2$a),
10882
11127
  createBaseVNode("button", {
10883
11128
  id: "double-column-button",
10884
11129
  class: normalizeClass(["col-span-2 text-primary text-center cursor-pointer py-3 rounded-sm border", {
@@ -10901,13 +11146,13 @@ return (_ctx, _cache) => {
10901
11146
 
10902
11147
  };
10903
11148
 
10904
- const _hoisted_1$e = {
11149
+ const _hoisted_1$f = {
10905
11150
  id: "font-family-menu",
10906
11151
  class: "w-full grid grid-cols-4 gap-2 my-3"
10907
11152
  };
10908
- const _hoisted_2$8 = ["onClick", "title"];
11153
+ const _hoisted_2$9 = ["onClick", "title"];
10909
11154
 
10910
- const _sfc_main$g = {
11155
+ const _sfc_main$h = {
10911
11156
  __name: 'OptionsFontFamily',
10912
11157
  setup(__props) {
10913
11158
 
@@ -10915,7 +11160,7 @@ const { textFont, fontsOptions, setTextFont } = useReaderSettings;
10915
11160
 
10916
11161
 
10917
11162
  return (_ctx, _cache) => {
10918
- return (openBlock(), createElementBlock("div", _hoisted_1$e, [
11163
+ return (openBlock(), createElementBlock("div", _hoisted_1$f, [
10919
11164
  (openBlock(true), createElementBlock(Fragment, null, renderList(unref(fontsOptions), (font) => {
10920
11165
  return (openBlock(), createElementBlock("button", {
10921
11166
  key: font.name,
@@ -10925,7 +11170,7 @@ return (_ctx, _cache) => {
10925
11170
  }]),
10926
11171
  style: normalizeStyle(`font-family: ${font.name}`),
10927
11172
  title: font.label ?? font.name
10928
- }, " Ff ", 14, _hoisted_2$8))
11173
+ }, " Ff ", 14, _hoisted_2$9))
10929
11174
  }), 128))
10930
11175
  ]))
10931
11176
  }
@@ -10933,7 +11178,7 @@ return (_ctx, _cache) => {
10933
11178
 
10934
11179
  };
10935
11180
 
10936
- const _sfc_main$f = {
11181
+ const _sfc_main$g = {
10937
11182
  __name: 'OptionsFontSize',
10938
11183
  setup(__props) {
10939
11184
 
@@ -10958,9 +11203,9 @@ return (_ctx, _cache) => {
10958
11203
 
10959
11204
  };
10960
11205
 
10961
- const _sfc_main$e = {};
11206
+ const _sfc_main$f = {};
10962
11207
 
10963
- const _hoisted_1$d = {
11208
+ const _hoisted_1$e = {
10964
11209
  fill: "none",
10965
11210
  stroke: "currentColor",
10966
11211
  viewBox: "0 0 24 24",
@@ -10968,7 +11213,7 @@ const _hoisted_1$d = {
10968
11213
  };
10969
11214
 
10970
11215
  function _sfc_render$3(_ctx, _cache) {
10971
- return (openBlock(), createElementBlock("svg", _hoisted_1$d, [...(_cache[0] || (_cache[0] = [
11216
+ return (openBlock(), createElementBlock("svg", _hoisted_1$e, [...(_cache[0] || (_cache[0] = [
10972
11217
  createBaseVNode("path", {
10973
11218
  "stroke-linecap": "round",
10974
11219
  "stroke-linejoin": "round",
@@ -10977,11 +11222,11 @@ function _sfc_render$3(_ctx, _cache) {
10977
11222
  }, null, -1)
10978
11223
  ]))]))
10979
11224
  }
10980
- const IconSun = /*#__PURE__*/_export_sfc(_sfc_main$e, [['render',_sfc_render$3]]);
11225
+ const IconSun = /*#__PURE__*/_export_sfc(_sfc_main$f, [['render',_sfc_render$3]]);
10981
11226
 
10982
- const _sfc_main$d = {};
11227
+ const _sfc_main$e = {};
10983
11228
 
10984
- const _hoisted_1$c = {
11229
+ const _hoisted_1$d = {
10985
11230
  fill: "none",
10986
11231
  stroke: "currentColor",
10987
11232
  viewBox: "0 0 24 24",
@@ -10989,7 +11234,7 @@ const _hoisted_1$c = {
10989
11234
  };
10990
11235
 
10991
11236
  function _sfc_render$2(_ctx, _cache) {
10992
- return (openBlock(), createElementBlock("svg", _hoisted_1$c, [...(_cache[0] || (_cache[0] = [
11237
+ return (openBlock(), createElementBlock("svg", _hoisted_1$d, [...(_cache[0] || (_cache[0] = [
10993
11238
  createBaseVNode("path", {
10994
11239
  "stroke-linecap": "round",
10995
11240
  "stroke-linejoin": "round",
@@ -10998,9 +11243,9 @@ function _sfc_render$2(_ctx, _cache) {
10998
11243
  }, null, -1)
10999
11244
  ]))]))
11000
11245
  }
11001
- const IconMoon = /*#__PURE__*/_export_sfc(_sfc_main$d, [['render',_sfc_render$2]]);
11246
+ const IconMoon = /*#__PURE__*/_export_sfc(_sfc_main$e, [['render',_sfc_render$2]]);
11002
11247
 
11003
- const _sfc_main$c = {
11248
+ const _sfc_main$d = {
11004
11249
  __name: 'OptionsColor',
11005
11250
  setup(__props) {
11006
11251
 
@@ -11035,6 +11280,45 @@ return (_ctx, _cache) => {
11035
11280
 
11036
11281
  };
11037
11282
 
11283
+ const _hoisted_1$c = { class: "w-full border-t border-areia mt-5 pt-5" };
11284
+ const _hoisted_2$8 = ["aria-checked"];
11285
+
11286
+
11287
+ const _sfc_main$c = {
11288
+ __name: 'OptionsReadingProgress',
11289
+ setup(__props) {
11290
+
11291
+ const { enabled, setEnabled } = useReadingProgress;
11292
+
11293
+ return (_ctx, _cache) => {
11294
+ return (openBlock(), createElementBlock("div", _hoisted_1$c, [
11295
+ createBaseVNode("button", {
11296
+ id: "reading-progress-button",
11297
+ class: "w-full flex items-center justify-between py-2 px-1 text-left",
11298
+ type: "button",
11299
+ role: "switch",
11300
+ "aria-checked": unref(enabled),
11301
+ onClick: _cache[0] || (_cache[0] = withModifiers($event => (unref(setEnabled)(!unref(enabled))), ["prevent"]))
11302
+ }, [
11303
+ _cache[1] || (_cache[1] = createBaseVNode("span", null, [
11304
+ createBaseVNode("span", { class: "block text-primary lowercase" }, "Retomar leitura"),
11305
+ createBaseVNode("span", { class: "block text-xs text-gray-500 mt-1" }, "Continuar de onde parou")
11306
+ ], -1)),
11307
+ createBaseVNode("span", {
11308
+ class: normalizeClass(["relative inline-flex h-6 w-11 flex-shrink-0 rounded-full border-2 border-transparent transition-colors", unref(enabled) ? 'bg-primary' : 'bg-gray-300']),
11309
+ "aria-hidden": "true"
11310
+ }, [
11311
+ createBaseVNode("span", {
11312
+ class: normalizeClass(["inline-block h-5 w-5 rounded-full bg-white shadow transition-transform", unref(enabled) ? 'translate-x-5' : 'translate-x-0'])
11313
+ }, null, 2)
11314
+ ], 2)
11315
+ ], 8, _hoisted_2$8)
11316
+ ]))
11317
+ }
11318
+ }
11319
+
11320
+ };
11321
+
11038
11322
  const _hoisted_1$b = {
11039
11323
  class: "absolute top-14 py-4 px-3 shadow-lg w-60 md:w-104 text-areia -right-2 md:right-16 z-10 bg-white",
11040
11324
  role: "Opções",
@@ -11072,12 +11356,15 @@ return (_ctx, _cache) => {
11072
11356
  createVNode(IconEye, { class: "w-6 h-6" }),
11073
11357
  _cache[3] || (_cache[3] = createBaseVNode("span", { class: "ml-4" }, "Visualização", -1))
11074
11358
  ]),
11359
+ createVNode(_sfc_main$i),
11075
11360
  createVNode(_sfc_main$h),
11076
- createVNode(_sfc_main$g),
11077
11361
  createBaseVNode("div", _hoisted_4$1, [
11078
- createVNode(_sfc_main$f),
11079
- createVNode(_sfc_main$c)
11362
+ createVNode(_sfc_main$g),
11363
+ createVNode(_sfc_main$d)
11080
11364
  ]),
11365
+ (unref(useReadingProgress).available.value)
11366
+ ? (openBlock(), createBlock(_sfc_main$c, { key: 0 }))
11367
+ : createCommentVNode("", true),
11081
11368
  _cache[4] || (_cache[4] = createBaseVNode("div", { class: "hidden w-full border-b border-areia my-8" }, null, -1)),
11082
11369
  renderSlot(_ctx.$slots, "optionsBottom")
11083
11370
  ])
@@ -11098,10 +11385,15 @@ const _sfc_main$a = {
11098
11385
  const show = ref(false);
11099
11386
  const button = ref(null);
11100
11387
 
11101
- 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
+ };
11102
11393
  const hide = () => {
11103
- if (!useReaderSettings.blocked.value) {
11104
- show.value = false;
11394
+ if (show.value && !useReaderSettings.blocked.value) {
11395
+ show.value = false;
11396
+ publicEvent('options-toggle', { open: false });
11105
11397
  }
11106
11398
  };
11107
11399
 
@@ -11185,7 +11477,7 @@ const _sfc_main$9 = {
11185
11477
 
11186
11478
  return (_ctx, _cache) => {
11187
11479
  return (openBlock(), createElementBlock("header", _hoisted_1$9, [
11188
- createVNode(_sfc_main$o, null, {
11480
+ createVNode(_sfc_main$p, null, {
11189
11481
  summaryTop: withCtx(() => [
11190
11482
  renderSlot(_ctx.$slots, "summaryTop")
11191
11483
  ]),
@@ -11320,12 +11612,12 @@ return (_ctx, _cache) => {
11320
11612
  createBaseVNode("div", _hoisted_2$3, [
11321
11613
  createVNode(NavigationButton, {
11322
11614
  target: "prev",
11323
- onClicked: _cache[0] || (_cache[0] = $event => (unref(prev)()))
11615
+ onClicked: _cache[0] || (_cache[0] = $event => (unref(prev)(false, 'previous-button')))
11324
11616
  }),
11325
11617
  renderSlot(_ctx.$slots, "default"),
11326
11618
  createVNode(NavigationButton, {
11327
11619
  target: "next",
11328
- onClicked: _cache[1] || (_cache[1] = $event => (unref(next)()))
11620
+ onClicked: _cache[1] || (_cache[1] = $event => (unref(next)(false, 'next-button')))
11329
11621
  })
11330
11622
  ])
11331
11623
  ]))
@@ -11349,10 +11641,10 @@ const { distanceX } = usePointerSwipe(el, {
11349
11641
  onSwipeEnd() {
11350
11642
  if (width.value < 600) {
11351
11643
  if (distanceX.value > 100) {
11352
- usePagination.next();
11644
+ usePagination.next(false, 'swipe');
11353
11645
  }
11354
11646
  if (distanceX.value < -100) {
11355
- usePagination.prev();
11647
+ usePagination.prev(false, 'swipe');
11356
11648
  }
11357
11649
  }
11358
11650
  }
@@ -11455,7 +11747,7 @@ return (_ctx, _cache) => {
11455
11747
  ]),
11456
11748
  createVNode(unref(m), {
11457
11749
  modelValue: unref(currentPage),
11458
- "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'))),
11459
11751
  min: 1,
11460
11752
  max: unref(totalPages),
11461
11753
  step: -1,
@@ -11613,74 +11905,222 @@ const _style_1 = "/* In your Vue component's <style> section */\n:host {\n -web
11613
11905
 
11614
11906
  const _hoisted_1 = { class: "text-white text-center text-sm" };
11615
11907
  const _hoisted_2 = { class: "text-white text-center text-xs" };
11616
-
11908
+
11617
11909
 
11618
11910
  const _sfc_main = {
11619
11911
  __name: 'App.ce',
11620
- props: {
11621
- bookTitle: String,
11622
- bookContent: String,
11623
- readerSettings: String,
11624
- readerBlocked: Boolean,
11625
- rootClass: {
11626
- type: String,
11627
- default: ''
11628
- },
11629
- cssFile: String,
11630
- 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
11631
11923
  },
11632
11924
  setup(__props) {
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);
11936
+ let paginationRevision = 0;
11937
+ let hostElement = null;
11938
+
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
+ }
11964
+ }
11633
11965
 
11634
- const props = __props;
11635
-
11636
- const { baseFont, bookTitle, chapterTitle, textFont, fontSize, columns, setColumns, mode } = useReaderSettings;
11637
- const { currentPage, totalPages } = usePagination;
11638
- const { content, listenToClicks } = useTextContent;
11639
- const { width, height } = useWindowSize();
11966
+ function dispatchPublicEvent(name, detail = {}) {
11967
+ if (!hostElement)
11968
+ return
11640
11969
 
11641
- const readerComponent = ref(null);
11642
- const contentArea = ref(null);
11643
- const rootComponent = ref(null);
11970
+ hostElement.dispatchEvent(new CustomEvent(`paginar:${name}`, {
11971
+ bubbles: true,
11972
+ composed: true,
11973
+ detail: { ...detail, state: getState() }
11974
+ }));
11975
+ }
11644
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
+
11645
12025
  onMounted(async () => {
11646
- usePagination.init(readerComponent, contentArea);
11647
- useReaderSettings.initSettings(props.readerSettings);
11648
- useStyles.initStyles(props, rootComponent);
11649
-
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
+
11650
12046
  if (['string', 'boolean'].includes(typeof props.readerBlocked)) {
11651
- useReaderSettings.setBlocked(props.readerBlocked);
12047
+ useReaderSettings.setBlocked(props.readerBlocked);
11652
12048
  }
11653
-
11654
- });
11655
-
11656
- watch(
11657
- props,
11658
- () => {
11659
- if (props.hasOwnProperty('readerBlocked')) {
11660
- const readerBlocked = typeof props.readerBlocked === 'boolean'
11661
- ? props.readerBlocked
11662
- : props.readerBlocked === 'true';
11663
- useReaderSettings.setBlocked(readerBlocked);
11664
- }
12049
+ nextTick(() => requestAnimationFrame(() => dispatchPublicEvent('ready')));
12050
+
12051
+ });
12052
+
12053
+ onBeforeUnmount(() => {
12054
+ window.removeEventListener('pagehide', saveCurrentReadingProgress);
12055
+ document.removeEventListener('visibilitychange', saveReadingProgressWhenHidden);
12056
+ if (hostElement) {
12057
+ delete hostElement.getState;
12058
+ delete hostElement.goToPage;
12059
+ delete hostElement.nextPage;
12060
+ delete hostElement.previousPage;
11665
12061
  }
11666
- );
11667
-
11668
- watchDebounced(
11669
- [width, height, content, columns, fontSize, textFont],
11670
- () => {
11671
- if (width.value < 1024 && columns.value === 'double')
11672
- setColumns('single');
11673
- else
11674
- useEstimatePages.estimate(readerComponent, contentArea);
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
+
12091
+ watch(
12092
+ currentPage,
12093
+ (value, previousValue) => {
12094
+ syncReadingProgress();
12095
+ dispatchPublicEvent('page-change', {
12096
+ page: value,
12097
+ previousPage: previousValue,
12098
+ source: changeSource.value
12099
+ });
11675
12100
  },
11676
- { debounce: 125, maxWait: 250 }
12101
+ { flush: 'sync' }
11677
12102
  );
11678
12103
 
11679
- watchDebounced(content,
11680
- () => listenToClicks(contentArea),
11681
- { 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' }
11682
12117
  );
11683
-
12118
+
12119
+ watchDebounced(content,
12120
+ () => listenToClicks(contentArea),
12121
+ { debounce: 125, maxWait: 250 }
12122
+ );
12123
+
11684
12124
 
11685
12125
  return (_ctx, _cache) => {
11686
12126
  return (openBlock(), createElementBlock("div", {
@@ -11690,11 +12130,11 @@ return (_ctx, _cache) => {
11690
12130
  id: "rootComponent",
11691
12131
  ref_key: "rootComponent",
11692
12132
  ref: rootComponent,
11693
- class: normalizeClass(unref(mode)
11694
- .concat(` ${props.rootClass}`)
11695
- .concat(` currentPage-${unref(currentPage)}`)
11696
- .concat(` totalPages-${unref(totalPages)}`)
11697
- .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)}`)
11698
12138
  ),
11699
12139
  style: normalizeStyle(`font-family: ${unref(baseFont)}`)
11700
12140
  }, [
@@ -11762,7 +12202,7 @@ return (_ctx, _cache) => {
11762
12202
  };
11763
12203
  const App = /*#__PURE__*/_export_sfc(_sfc_main, [['styles',[_style_0,_style_1]]]);
11764
12204
 
11765
- const tailwindStyles = "*, ::before, ::after {\n --tw-border-spacing-x: 0;\n --tw-border-spacing-y: 0;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-rotate: 0;\n --tw-skew-x: 0;\n --tw-skew-y: 0;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-pan-x: ;\n --tw-pan-y: ;\n --tw-pinch-zoom: ;\n --tw-scroll-snap-strictness: proximity;\n --tw-gradient-from-position: ;\n --tw-gradient-via-position: ;\n --tw-gradient-to-position: ;\n --tw-ordinal: ;\n --tw-slashed-zero: ;\n --tw-numeric-figure: ;\n --tw-numeric-spacing: ;\n --tw-numeric-fraction: ;\n --tw-ring-inset: ;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-color: rgb(59 130 246 / 0.5);\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n --tw-blur: ;\n --tw-brightness: ;\n --tw-contrast: ;\n --tw-grayscale: ;\n --tw-hue-rotate: ;\n --tw-invert: ;\n --tw-saturate: ;\n --tw-sepia: ;\n --tw-drop-shadow: ;\n --tw-backdrop-blur: ;\n --tw-backdrop-brightness: ;\n --tw-backdrop-contrast: ;\n --tw-backdrop-grayscale: ;\n --tw-backdrop-hue-rotate: ;\n --tw-backdrop-invert: ;\n --tw-backdrop-opacity: ;\n --tw-backdrop-saturate: ;\n --tw-backdrop-sepia: ;\n --tw-contain-size: ;\n --tw-contain-layout: ;\n --tw-contain-paint: ;\n --tw-contain-style: ;\n}\n\n::backdrop {\n --tw-border-spacing-x: 0;\n --tw-border-spacing-y: 0;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-rotate: 0;\n --tw-skew-x: 0;\n --tw-skew-y: 0;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-pan-x: ;\n --tw-pan-y: ;\n --tw-pinch-zoom: ;\n --tw-scroll-snap-strictness: proximity;\n --tw-gradient-from-position: ;\n --tw-gradient-via-position: ;\n --tw-gradient-to-position: ;\n --tw-ordinal: ;\n --tw-slashed-zero: ;\n --tw-numeric-figure: ;\n --tw-numeric-spacing: ;\n --tw-numeric-fraction: ;\n --tw-ring-inset: ;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-color: rgb(59 130 246 / 0.5);\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n --tw-blur: ;\n --tw-brightness: ;\n --tw-contrast: ;\n --tw-grayscale: ;\n --tw-hue-rotate: ;\n --tw-invert: ;\n --tw-saturate: ;\n --tw-sepia: ;\n --tw-drop-shadow: ;\n --tw-backdrop-blur: ;\n --tw-backdrop-brightness: ;\n --tw-backdrop-contrast: ;\n --tw-backdrop-grayscale: ;\n --tw-backdrop-hue-rotate: ;\n --tw-backdrop-invert: ;\n --tw-backdrop-opacity: ;\n --tw-backdrop-saturate: ;\n --tw-backdrop-sepia: ;\n --tw-contain-size: ;\n --tw-contain-layout: ;\n --tw-contain-paint: ;\n --tw-contain-style: ;\n}\n\n/*\n! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com\n*/\n\n/*\n1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)\n2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)\n*/\n\n*,\n::before,\n::after {\n box-sizing: border-box;\n /* 1 */\n border-width: 0;\n /* 2 */\n border-style: solid;\n /* 2 */\n border-color: #e5e7eb;\n /* 2 */\n}\n\n::before,\n::after {\n --tw-content: '';\n}\n\n/*\n1. Use a consistent sensible line-height in all browsers.\n2. Prevent adjustments of font size after orientation changes in iOS.\n3. Use a more readable tab size.\n4. Use the user's configured `sans` font-family by default.\n5. Use the user's configured `sans` font-feature-settings by default.\n6. Use the user's configured `sans` font-variation-settings by default.\n7. Disable tap highlights on iOS\n*/\n\nhtml,\n:host {\n line-height: 1.5;\n /* 1 */\n -webkit-text-size-adjust: 100%;\n /* 2 */\n -moz-tab-size: 4;\n /* 3 */\n -o-tab-size: 4;\n tab-size: 4;\n /* 3 */\n font-family: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n /* 4 */\n font-feature-settings: normal;\n /* 5 */\n font-variation-settings: normal;\n /* 6 */\n -webkit-tap-highlight-color: transparent;\n /* 7 */\n}\n\n/*\n1. Remove the margin in all browsers.\n2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.\n*/\n\nbody {\n margin: 0;\n /* 1 */\n line-height: inherit;\n /* 2 */\n}\n\n/*\n1. Add the correct height in Firefox.\n2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)\n3. Ensure horizontal rules are visible by default.\n*/\n\nhr {\n height: 0;\n /* 1 */\n color: inherit;\n /* 2 */\n border-top-width: 1px;\n /* 3 */\n}\n\n/*\nAdd the correct text decoration in Chrome, Edge, and Safari.\n*/\n\nabbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n}\n\n/*\nRemove the default font size and weight for headings.\n*/\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n font-size: inherit;\n font-weight: inherit;\n}\n\n/*\nReset links to optimize for opt-in styling instead of opt-out.\n*/\n\na {\n color: inherit;\n text-decoration: inherit;\n}\n\n/*\nAdd the correct font weight in Edge and Safari.\n*/\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/*\n1. Use the user's configured `mono` font-family by default.\n2. Use the user's configured `mono` font-feature-settings by default.\n3. Use the user's configured `mono` font-variation-settings by default.\n4. Correct the odd `em` font sizing in all browsers.\n*/\n\ncode,\nkbd,\nsamp,\npre {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n /* 1 */\n font-feature-settings: normal;\n /* 2 */\n font-variation-settings: normal;\n /* 3 */\n font-size: 1em;\n /* 4 */\n}\n\n/*\nAdd the correct font size in all browsers.\n*/\n\nsmall {\n font-size: 80%;\n}\n\n/*\nPrevent `sub` and `sup` elements from affecting the line height in all browsers.\n*/\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/*\n1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)\n2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)\n3. Remove gaps between table borders by default.\n*/\n\ntable {\n text-indent: 0;\n /* 1 */\n border-color: inherit;\n /* 2 */\n border-collapse: collapse;\n /* 3 */\n}\n\n/*\n1. Change the font styles in all browsers.\n2. Remove the margin in Firefox and Safari.\n3. Remove default padding in all browsers.\n*/\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit;\n /* 1 */\n font-feature-settings: inherit;\n /* 1 */\n font-variation-settings: inherit;\n /* 1 */\n font-size: 100%;\n /* 1 */\n font-weight: inherit;\n /* 1 */\n line-height: inherit;\n /* 1 */\n letter-spacing: inherit;\n /* 1 */\n color: inherit;\n /* 1 */\n margin: 0;\n /* 2 */\n padding: 0;\n /* 3 */\n}\n\n/*\nRemove the inheritance of text transform in Edge and Firefox.\n*/\n\nbutton,\nselect {\n text-transform: none;\n}\n\n/*\n1. Correct the inability to style clickable types in iOS and Safari.\n2. Remove default button styles.\n*/\n\nbutton,\ninput:where([type='button']),\ninput:where([type='reset']),\ninput:where([type='submit']) {\n -webkit-appearance: button;\n /* 1 */\n background-color: transparent;\n /* 2 */\n background-image: none;\n /* 2 */\n}\n\n/*\nUse the modern Firefox focus style for all focusable elements.\n*/\n\n:-moz-focusring {\n outline: auto;\n}\n\n/*\nRemove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)\n*/\n\n:-moz-ui-invalid {\n box-shadow: none;\n}\n\n/*\nAdd the correct vertical alignment in Chrome and Firefox.\n*/\n\nprogress {\n vertical-align: baseline;\n}\n\n/*\nCorrect the cursor style of increment and decrement buttons in Safari.\n*/\n\n::-webkit-inner-spin-button,\n::-webkit-outer-spin-button {\n height: auto;\n}\n\n/*\n1. Correct the odd appearance in Chrome and Safari.\n2. Correct the outline style in Safari.\n*/\n\n[type='search'] {\n -webkit-appearance: textfield;\n /* 1 */\n outline-offset: -2px;\n /* 2 */\n}\n\n/*\nRemove the inner padding in Chrome and Safari on macOS.\n*/\n\n::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/*\n1. Correct the inability to style clickable types in iOS and Safari.\n2. Change font properties to `inherit` in Safari.\n*/\n\n::-webkit-file-upload-button {\n -webkit-appearance: button;\n /* 1 */\n font: inherit;\n /* 2 */\n}\n\n/*\nAdd the correct display in Chrome and Safari.\n*/\n\nsummary {\n display: list-item;\n}\n\n/*\nRemoves the default spacing and border for appropriate elements.\n*/\n\nblockquote,\ndl,\ndd,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\nhr,\nfigure,\np,\npre {\n margin: 0;\n}\n\nfieldset {\n margin: 0;\n padding: 0;\n}\n\nlegend {\n padding: 0;\n}\n\nol,\nul,\nmenu {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n/*\nReset default styling for dialogs.\n*/\n\ndialog {\n padding: 0;\n}\n\n/*\nPrevent resizing textareas horizontally by default.\n*/\n\ntextarea {\n resize: vertical;\n}\n\n/*\n1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)\n2. Set the default placeholder color to the user's configured gray 400 color.\n*/\n\ninput::-moz-placeholder, textarea::-moz-placeholder {\n opacity: 1;\n /* 1 */\n color: #9ca3af;\n /* 2 */\n}\n\ninput::placeholder,\ntextarea::placeholder {\n opacity: 1;\n /* 1 */\n color: #9ca3af;\n /* 2 */\n}\n\n/*\nSet the default cursor for buttons.\n*/\n\nbutton,\n[role=\"button\"] {\n cursor: pointer;\n}\n\n/*\nMake sure disabled buttons don't get the pointer cursor.\n*/\n\n:disabled {\n cursor: default;\n}\n\n/*\n1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)\n2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)\n This can trigger a poorly considered lint error in some tools but is included by design.\n*/\n\nimg,\nsvg,\nvideo,\ncanvas,\naudio,\niframe,\nembed,\nobject {\n display: block;\n /* 1 */\n vertical-align: middle;\n /* 2 */\n}\n\n/*\nConstrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)\n*/\n\nimg,\nvideo {\n max-width: 100%;\n height: auto;\n}\n\n/* Make elements with the HTML hidden attribute stay hidden by default */\n\n[hidden]:where(:not([hidden=\"until-found\"])) {\n display: none;\n}\n\n.fixed {\n position: fixed;\n}\n\n.absolute {\n position: absolute;\n}\n\n.relative {\n position: relative;\n}\n\n.-right-2 {\n right: -0.5rem;\n}\n\n.bottom-0 {\n bottom: 0px;\n}\n\n.right-0 {\n right: 0px;\n}\n\n.right-8 {\n right: 2rem;\n}\n\n.top-0 {\n top: 0px;\n}\n\n.top-14 {\n top: 3.5rem;\n}\n\n.top-4 {\n top: 1rem;\n}\n\n.z-10 {\n z-index: 10;\n}\n\n.z-20 {\n z-index: 20;\n}\n\n.z-40 {\n z-index: 40;\n}\n\n.col-span-1 {\n grid-column: span 1 / span 1;\n}\n\n.col-span-2 {\n grid-column: span 2 / span 2;\n}\n\n.mx-auto {\n margin-left: auto;\n margin-right: auto;\n}\n\n.my-3 {\n margin-top: 0.75rem;\n margin-bottom: 0.75rem;\n}\n\n.my-8 {\n margin-top: 2rem;\n margin-bottom: 2rem;\n}\n\n.mb-2 {\n margin-bottom: 0.5rem;\n}\n\n.mb-6 {\n margin-bottom: 1.5rem;\n}\n\n.ml-10 {\n margin-left: 2.5rem;\n}\n\n.ml-3 {\n margin-left: 0.75rem;\n}\n\n.ml-4 {\n margin-left: 1rem;\n}\n\n.mr-3 {\n margin-right: 0.75rem;\n}\n\n.mt-3 {\n margin-top: 0.75rem;\n}\n\n.block {\n display: block;\n}\n\n.inline-block {\n display: inline-block;\n}\n\n.flex {\n display: flex;\n}\n\n.grid {\n display: grid;\n}\n\n.hidden {\n display: none;\n}\n\n.h-10 {\n height: 2.5rem;\n}\n\n.h-5 {\n height: 1.25rem;\n}\n\n.h-6 {\n height: 1.5rem;\n}\n\n.h-8 {\n height: 2rem;\n}\n\n.h-full {\n height: 100%;\n}\n\n.h-screen {\n height: 100vh;\n}\n\n.w-4\\/5 {\n width: 80%;\n}\n\n.w-5 {\n width: 1.25rem;\n}\n\n.w-6 {\n width: 1.5rem;\n}\n\n.w-60 {\n width: 15rem;\n}\n\n.w-8 {\n width: 2rem;\n}\n\n.w-96 {\n width: 24rem;\n}\n\n.w-full {\n width: 100%;\n}\n\n.flex-shrink-0 {\n flex-shrink: 0;\n}\n\n.scale-100 {\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n\n.scale-95 {\n --tw-scale-x: .95;\n --tw-scale-y: .95;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n\n.transform {\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n\n.cursor-default {\n cursor: default;\n}\n\n.cursor-pointer {\n cursor: pointer;\n}\n\n.grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n\n.grid-cols-4 {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n}\n\n.items-center {\n align-items: center;\n}\n\n.justify-center {\n justify-content: center;\n}\n\n.justify-between {\n justify-content: space-between;\n}\n\n.gap-2 {\n gap: 0.5rem;\n}\n\n.divide-opacity-75 > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-opacity: 0.75;\n}\n\n.self-end {\n align-self: flex-end;\n}\n\n.overflow-auto {\n overflow: auto;\n}\n\n.overflow-hidden {\n overflow: hidden;\n}\n\n.overflow-x-hidden {\n overflow-x: hidden;\n}\n\n.rounded {\n border-radius: 0.25rem;\n}\n\n.rounded-sm {\n border-radius: 0.125rem;\n}\n\n.border {\n border-width: 1px;\n}\n\n.border-2 {\n border-width: 2px;\n}\n\n.border-b {\n border-bottom-width: 1px;\n}\n\n.border-gray-300 {\n --tw-border-opacity: 1;\n border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));\n}\n\n.border-white {\n --tw-border-opacity: 1;\n border-color: rgb(255 255 255 / var(--tw-border-opacity, 1));\n}\n\n.border-b-white\\/25 {\n border-bottom-color: rgb(255 255 255 / 0.25);\n}\n\n.bg-gray-800 {\n --tw-bg-opacity: 1;\n background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));\n}\n\n.bg-white {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\n}\n\n.p-10 {\n padding: 2.5rem;\n}\n\n.p-3 {\n padding: 0.75rem;\n}\n\n.p-4 {\n padding: 1rem;\n}\n\n.px-10 {\n padding-left: 2.5rem;\n padding-right: 2.5rem;\n}\n\n.px-2 {\n padding-left: 0.5rem;\n padding-right: 0.5rem;\n}\n\n.px-3 {\n padding-left: 0.75rem;\n padding-right: 0.75rem;\n}\n\n.py-2 {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n\n.py-3 {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n}\n\n.py-4 {\n padding-top: 1rem;\n padding-bottom: 1rem;\n}\n\n.pl-4 {\n padding-left: 1rem;\n}\n\n.pt-10 {\n padding-top: 2.5rem;\n}\n\n.text-left {\n text-align: left;\n}\n\n.text-center {\n text-align: center;\n}\n\n.text-base {\n font-size: 1rem;\n line-height: 1.5rem;\n}\n\n.text-lg {\n font-size: 1.125rem;\n line-height: 1.75rem;\n}\n\n.text-sm {\n font-size: 0.875rem;\n line-height: 1.25rem;\n}\n\n.text-xs {\n font-size: 0.75rem;\n line-height: 1rem;\n}\n\n.font-light {\n font-weight: 300;\n}\n\n.lowercase {\n text-transform: lowercase;\n}\n\n.tracking-wide {\n letter-spacing: 0.025em;\n}\n\n.text-black {\n --tw-text-opacity: 1;\n color: rgb(0 0 0 / var(--tw-text-opacity, 1));\n}\n\n.text-gray-700 {\n --tw-text-opacity: 1;\n color: rgb(55 65 81 / var(--tw-text-opacity, 1));\n}\n\n.text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n}\n\n.opacity-0 {\n opacity: 0;\n}\n\n.opacity-100 {\n opacity: 1;\n}\n\n.opacity-30 {\n opacity: 0.3;\n}\n\n.opacity-50 {\n opacity: 0.5;\n}\n\n.opacity-75 {\n opacity: 0.75;\n}\n\n.shadow {\n --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n\n.shadow-2xl {\n --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n\n.shadow-lg {\n --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n\n.filter {\n filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);\n}\n\n.transition {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n\n.transition-colors {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n\n.transition-opacity {\n transition-property: opacity;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n\n.duration-100 {\n transition-duration: 100ms;\n}\n\n.duration-200 {\n transition-duration: 200ms;\n}\n\n.duration-75 {\n transition-duration: 75ms;\n}\n\n.ease-in {\n transition-timing-function: cubic-bezier(0.4, 0, 1, 1);\n}\n\n.ease-out {\n transition-timing-function: cubic-bezier(0, 0, 0.2, 1);\n}\n\n.last\\:border-transparent:last-child {\n border-color: transparent;\n}\n\n.hover\\:bg-gray-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n\n@media (min-width: 768px) {\n .md\\:bottom-14 {\n bottom: 3.5rem;\n }\n\n .md\\:right-16 {\n right: 4rem;\n }\n\n .md\\:right-3 {\n right: 0.75rem;\n }\n\n .md\\:flex {\n display: flex;\n }\n\n .md\\:grid {\n display: grid;\n }\n\n .md\\:w-2\\/5 {\n width: 40%;\n }\n\n .md\\:w-\\[40em\\] {\n width: 40em;\n }\n\n .md\\:px-24 {\n padding-left: 6rem;\n padding-right: 6rem;\n }\n}\n\n@media (prefers-color-scheme: dark) {\n .dark\\:text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n }\n}";
12205
+ const tailwindStyles = "*, ::before, ::after {\n --tw-border-spacing-x: 0;\n --tw-border-spacing-y: 0;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-rotate: 0;\n --tw-skew-x: 0;\n --tw-skew-y: 0;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-pan-x: ;\n --tw-pan-y: ;\n --tw-pinch-zoom: ;\n --tw-scroll-snap-strictness: proximity;\n --tw-gradient-from-position: ;\n --tw-gradient-via-position: ;\n --tw-gradient-to-position: ;\n --tw-ordinal: ;\n --tw-slashed-zero: ;\n --tw-numeric-figure: ;\n --tw-numeric-spacing: ;\n --tw-numeric-fraction: ;\n --tw-ring-inset: ;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-color: rgb(59 130 246 / 0.5);\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n --tw-blur: ;\n --tw-brightness: ;\n --tw-contrast: ;\n --tw-grayscale: ;\n --tw-hue-rotate: ;\n --tw-invert: ;\n --tw-saturate: ;\n --tw-sepia: ;\n --tw-drop-shadow: ;\n --tw-backdrop-blur: ;\n --tw-backdrop-brightness: ;\n --tw-backdrop-contrast: ;\n --tw-backdrop-grayscale: ;\n --tw-backdrop-hue-rotate: ;\n --tw-backdrop-invert: ;\n --tw-backdrop-opacity: ;\n --tw-backdrop-saturate: ;\n --tw-backdrop-sepia: ;\n --tw-contain-size: ;\n --tw-contain-layout: ;\n --tw-contain-paint: ;\n --tw-contain-style: ;\n}\n\n::backdrop {\n --tw-border-spacing-x: 0;\n --tw-border-spacing-y: 0;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-rotate: 0;\n --tw-skew-x: 0;\n --tw-skew-y: 0;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-pan-x: ;\n --tw-pan-y: ;\n --tw-pinch-zoom: ;\n --tw-scroll-snap-strictness: proximity;\n --tw-gradient-from-position: ;\n --tw-gradient-via-position: ;\n --tw-gradient-to-position: ;\n --tw-ordinal: ;\n --tw-slashed-zero: ;\n --tw-numeric-figure: ;\n --tw-numeric-spacing: ;\n --tw-numeric-fraction: ;\n --tw-ring-inset: ;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-color: rgb(59 130 246 / 0.5);\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n --tw-blur: ;\n --tw-brightness: ;\n --tw-contrast: ;\n --tw-grayscale: ;\n --tw-hue-rotate: ;\n --tw-invert: ;\n --tw-saturate: ;\n --tw-sepia: ;\n --tw-drop-shadow: ;\n --tw-backdrop-blur: ;\n --tw-backdrop-brightness: ;\n --tw-backdrop-contrast: ;\n --tw-backdrop-grayscale: ;\n --tw-backdrop-hue-rotate: ;\n --tw-backdrop-invert: ;\n --tw-backdrop-opacity: ;\n --tw-backdrop-saturate: ;\n --tw-backdrop-sepia: ;\n --tw-contain-size: ;\n --tw-contain-layout: ;\n --tw-contain-paint: ;\n --tw-contain-style: ;\n}\n\n/*\n! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com\n*/\n\n/*\n1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)\n2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)\n*/\n\n*,\n::before,\n::after {\n box-sizing: border-box;\n /* 1 */\n border-width: 0;\n /* 2 */\n border-style: solid;\n /* 2 */\n border-color: #e5e7eb;\n /* 2 */\n}\n\n::before,\n::after {\n --tw-content: '';\n}\n\n/*\n1. Use a consistent sensible line-height in all browsers.\n2. Prevent adjustments of font size after orientation changes in iOS.\n3. Use a more readable tab size.\n4. Use the user's configured `sans` font-family by default.\n5. Use the user's configured `sans` font-feature-settings by default.\n6. Use the user's configured `sans` font-variation-settings by default.\n7. Disable tap highlights on iOS\n*/\n\nhtml,\n:host {\n line-height: 1.5;\n /* 1 */\n -webkit-text-size-adjust: 100%;\n /* 2 */\n -moz-tab-size: 4;\n /* 3 */\n -o-tab-size: 4;\n tab-size: 4;\n /* 3 */\n font-family: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n /* 4 */\n font-feature-settings: normal;\n /* 5 */\n font-variation-settings: normal;\n /* 6 */\n -webkit-tap-highlight-color: transparent;\n /* 7 */\n}\n\n/*\n1. Remove the margin in all browsers.\n2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.\n*/\n\nbody {\n margin: 0;\n /* 1 */\n line-height: inherit;\n /* 2 */\n}\n\n/*\n1. Add the correct height in Firefox.\n2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)\n3. Ensure horizontal rules are visible by default.\n*/\n\nhr {\n height: 0;\n /* 1 */\n color: inherit;\n /* 2 */\n border-top-width: 1px;\n /* 3 */\n}\n\n/*\nAdd the correct text decoration in Chrome, Edge, and Safari.\n*/\n\nabbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n}\n\n/*\nRemove the default font size and weight for headings.\n*/\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n font-size: inherit;\n font-weight: inherit;\n}\n\n/*\nReset links to optimize for opt-in styling instead of opt-out.\n*/\n\na {\n color: inherit;\n text-decoration: inherit;\n}\n\n/*\nAdd the correct font weight in Edge and Safari.\n*/\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/*\n1. Use the user's configured `mono` font-family by default.\n2. Use the user's configured `mono` font-feature-settings by default.\n3. Use the user's configured `mono` font-variation-settings by default.\n4. Correct the odd `em` font sizing in all browsers.\n*/\n\ncode,\nkbd,\nsamp,\npre {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n /* 1 */\n font-feature-settings: normal;\n /* 2 */\n font-variation-settings: normal;\n /* 3 */\n font-size: 1em;\n /* 4 */\n}\n\n/*\nAdd the correct font size in all browsers.\n*/\n\nsmall {\n font-size: 80%;\n}\n\n/*\nPrevent `sub` and `sup` elements from affecting the line height in all browsers.\n*/\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/*\n1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)\n2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)\n3. Remove gaps between table borders by default.\n*/\n\ntable {\n text-indent: 0;\n /* 1 */\n border-color: inherit;\n /* 2 */\n border-collapse: collapse;\n /* 3 */\n}\n\n/*\n1. Change the font styles in all browsers.\n2. Remove the margin in Firefox and Safari.\n3. Remove default padding in all browsers.\n*/\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit;\n /* 1 */\n font-feature-settings: inherit;\n /* 1 */\n font-variation-settings: inherit;\n /* 1 */\n font-size: 100%;\n /* 1 */\n font-weight: inherit;\n /* 1 */\n line-height: inherit;\n /* 1 */\n letter-spacing: inherit;\n /* 1 */\n color: inherit;\n /* 1 */\n margin: 0;\n /* 2 */\n padding: 0;\n /* 3 */\n}\n\n/*\nRemove the inheritance of text transform in Edge and Firefox.\n*/\n\nbutton,\nselect {\n text-transform: none;\n}\n\n/*\n1. Correct the inability to style clickable types in iOS and Safari.\n2. Remove default button styles.\n*/\n\nbutton,\ninput:where([type='button']),\ninput:where([type='reset']),\ninput:where([type='submit']) {\n -webkit-appearance: button;\n /* 1 */\n background-color: transparent;\n /* 2 */\n background-image: none;\n /* 2 */\n}\n\n/*\nUse the modern Firefox focus style for all focusable elements.\n*/\n\n:-moz-focusring {\n outline: auto;\n}\n\n/*\nRemove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)\n*/\n\n:-moz-ui-invalid {\n box-shadow: none;\n}\n\n/*\nAdd the correct vertical alignment in Chrome and Firefox.\n*/\n\nprogress {\n vertical-align: baseline;\n}\n\n/*\nCorrect the cursor style of increment and decrement buttons in Safari.\n*/\n\n::-webkit-inner-spin-button,\n::-webkit-outer-spin-button {\n height: auto;\n}\n\n/*\n1. Correct the odd appearance in Chrome and Safari.\n2. Correct the outline style in Safari.\n*/\n\n[type='search'] {\n -webkit-appearance: textfield;\n /* 1 */\n outline-offset: -2px;\n /* 2 */\n}\n\n/*\nRemove the inner padding in Chrome and Safari on macOS.\n*/\n\n::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/*\n1. Correct the inability to style clickable types in iOS and Safari.\n2. Change font properties to `inherit` in Safari.\n*/\n\n::-webkit-file-upload-button {\n -webkit-appearance: button;\n /* 1 */\n font: inherit;\n /* 2 */\n}\n\n/*\nAdd the correct display in Chrome and Safari.\n*/\n\nsummary {\n display: list-item;\n}\n\n/*\nRemoves the default spacing and border for appropriate elements.\n*/\n\nblockquote,\ndl,\ndd,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\nhr,\nfigure,\np,\npre {\n margin: 0;\n}\n\nfieldset {\n margin: 0;\n padding: 0;\n}\n\nlegend {\n padding: 0;\n}\n\nol,\nul,\nmenu {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n/*\nReset default styling for dialogs.\n*/\n\ndialog {\n padding: 0;\n}\n\n/*\nPrevent resizing textareas horizontally by default.\n*/\n\ntextarea {\n resize: vertical;\n}\n\n/*\n1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)\n2. Set the default placeholder color to the user's configured gray 400 color.\n*/\n\ninput::-moz-placeholder, textarea::-moz-placeholder {\n opacity: 1;\n /* 1 */\n color: #9ca3af;\n /* 2 */\n}\n\ninput::placeholder,\ntextarea::placeholder {\n opacity: 1;\n /* 1 */\n color: #9ca3af;\n /* 2 */\n}\n\n/*\nSet the default cursor for buttons.\n*/\n\nbutton,\n[role=\"button\"] {\n cursor: pointer;\n}\n\n/*\nMake sure disabled buttons don't get the pointer cursor.\n*/\n\n:disabled {\n cursor: default;\n}\n\n/*\n1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)\n2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)\n This can trigger a poorly considered lint error in some tools but is included by design.\n*/\n\nimg,\nsvg,\nvideo,\ncanvas,\naudio,\niframe,\nembed,\nobject {\n display: block;\n /* 1 */\n vertical-align: middle;\n /* 2 */\n}\n\n/*\nConstrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)\n*/\n\nimg,\nvideo {\n max-width: 100%;\n height: auto;\n}\n\n/* Make elements with the HTML hidden attribute stay hidden by default */\n\n[hidden]:where(:not([hidden=\"until-found\"])) {\n display: none;\n}\n\n.fixed {\n position: fixed;\n}\n\n.absolute {\n position: absolute;\n}\n\n.relative {\n position: relative;\n}\n\n.-right-2 {\n right: -0.5rem;\n}\n\n.bottom-0 {\n bottom: 0px;\n}\n\n.right-0 {\n right: 0px;\n}\n\n.right-8 {\n right: 2rem;\n}\n\n.top-0 {\n top: 0px;\n}\n\n.top-14 {\n top: 3.5rem;\n}\n\n.top-4 {\n top: 1rem;\n}\n\n.z-10 {\n z-index: 10;\n}\n\n.z-20 {\n z-index: 20;\n}\n\n.z-40 {\n z-index: 40;\n}\n\n.col-span-1 {\n grid-column: span 1 / span 1;\n}\n\n.col-span-2 {\n grid-column: span 2 / span 2;\n}\n\n.mx-auto {\n margin-left: auto;\n margin-right: auto;\n}\n\n.my-3 {\n margin-top: 0.75rem;\n margin-bottom: 0.75rem;\n}\n\n.my-8 {\n margin-top: 2rem;\n margin-bottom: 2rem;\n}\n\n.mb-2 {\n margin-bottom: 0.5rem;\n}\n\n.mb-6 {\n margin-bottom: 1.5rem;\n}\n\n.ml-10 {\n margin-left: 2.5rem;\n}\n\n.ml-3 {\n margin-left: 0.75rem;\n}\n\n.ml-4 {\n margin-left: 1rem;\n}\n\n.mr-3 {\n margin-right: 0.75rem;\n}\n\n.mt-1 {\n margin-top: 0.25rem;\n}\n\n.mt-3 {\n margin-top: 0.75rem;\n}\n\n.mt-5 {\n margin-top: 1.25rem;\n}\n\n.block {\n display: block;\n}\n\n.inline-block {\n display: inline-block;\n}\n\n.flex {\n display: flex;\n}\n\n.inline-flex {\n display: inline-flex;\n}\n\n.grid {\n display: grid;\n}\n\n.hidden {\n display: none;\n}\n\n.h-10 {\n height: 2.5rem;\n}\n\n.h-5 {\n height: 1.25rem;\n}\n\n.h-6 {\n height: 1.5rem;\n}\n\n.h-8 {\n height: 2rem;\n}\n\n.h-full {\n height: 100%;\n}\n\n.h-screen {\n height: 100vh;\n}\n\n.w-11 {\n width: 2.75rem;\n}\n\n.w-4\\/5 {\n width: 80%;\n}\n\n.w-5 {\n width: 1.25rem;\n}\n\n.w-6 {\n width: 1.5rem;\n}\n\n.w-60 {\n width: 15rem;\n}\n\n.w-8 {\n width: 2rem;\n}\n\n.w-96 {\n width: 24rem;\n}\n\n.w-full {\n width: 100%;\n}\n\n.flex-shrink-0 {\n flex-shrink: 0;\n}\n\n.translate-x-0 {\n --tw-translate-x: 0px;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n\n.translate-x-5 {\n --tw-translate-x: 1.25rem;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n\n.scale-100 {\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n\n.scale-95 {\n --tw-scale-x: .95;\n --tw-scale-y: .95;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n\n.transform {\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n\n.cursor-default {\n cursor: default;\n}\n\n.cursor-pointer {\n cursor: pointer;\n}\n\n.grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n\n.grid-cols-4 {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n}\n\n.items-center {\n align-items: center;\n}\n\n.justify-center {\n justify-content: center;\n}\n\n.justify-between {\n justify-content: space-between;\n}\n\n.gap-2 {\n gap: 0.5rem;\n}\n\n.divide-opacity-75 > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-opacity: 0.75;\n}\n\n.self-end {\n align-self: flex-end;\n}\n\n.overflow-auto {\n overflow: auto;\n}\n\n.overflow-hidden {\n overflow: hidden;\n}\n\n.overflow-x-hidden {\n overflow-x: hidden;\n}\n\n.rounded {\n border-radius: 0.25rem;\n}\n\n.rounded-full {\n border-radius: 9999px;\n}\n\n.rounded-sm {\n border-radius: 0.125rem;\n}\n\n.border {\n border-width: 1px;\n}\n\n.border-2 {\n border-width: 2px;\n}\n\n.border-b {\n border-bottom-width: 1px;\n}\n\n.border-t {\n border-top-width: 1px;\n}\n\n.border-gray-300 {\n --tw-border-opacity: 1;\n border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));\n}\n\n.border-transparent {\n border-color: transparent;\n}\n\n.border-white {\n --tw-border-opacity: 1;\n border-color: rgb(255 255 255 / var(--tw-border-opacity, 1));\n}\n\n.border-b-white\\/25 {\n border-bottom-color: rgb(255 255 255 / 0.25);\n}\n\n.bg-gray-300 {\n --tw-bg-opacity: 1;\n background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1));\n}\n\n.bg-gray-800 {\n --tw-bg-opacity: 1;\n background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));\n}\n\n.bg-white {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\n}\n\n.p-10 {\n padding: 2.5rem;\n}\n\n.p-3 {\n padding: 0.75rem;\n}\n\n.p-4 {\n padding: 1rem;\n}\n\n.px-1 {\n padding-left: 0.25rem;\n padding-right: 0.25rem;\n}\n\n.px-10 {\n padding-left: 2.5rem;\n padding-right: 2.5rem;\n}\n\n.px-2 {\n padding-left: 0.5rem;\n padding-right: 0.5rem;\n}\n\n.px-3 {\n padding-left: 0.75rem;\n padding-right: 0.75rem;\n}\n\n.py-2 {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n\n.py-3 {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n}\n\n.py-4 {\n padding-top: 1rem;\n padding-bottom: 1rem;\n}\n\n.pl-4 {\n padding-left: 1rem;\n}\n\n.pt-10 {\n padding-top: 2.5rem;\n}\n\n.pt-5 {\n padding-top: 1.25rem;\n}\n\n.text-left {\n text-align: left;\n}\n\n.text-center {\n text-align: center;\n}\n\n.text-base {\n font-size: 1rem;\n line-height: 1.5rem;\n}\n\n.text-lg {\n font-size: 1.125rem;\n line-height: 1.75rem;\n}\n\n.text-sm {\n font-size: 0.875rem;\n line-height: 1.25rem;\n}\n\n.text-xs {\n font-size: 0.75rem;\n line-height: 1rem;\n}\n\n.font-light {\n font-weight: 300;\n}\n\n.lowercase {\n text-transform: lowercase;\n}\n\n.tracking-wide {\n letter-spacing: 0.025em;\n}\n\n.text-black {\n --tw-text-opacity: 1;\n color: rgb(0 0 0 / var(--tw-text-opacity, 1));\n}\n\n.text-gray-500 {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n}\n\n.text-gray-700 {\n --tw-text-opacity: 1;\n color: rgb(55 65 81 / var(--tw-text-opacity, 1));\n}\n\n.text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n}\n\n.opacity-0 {\n opacity: 0;\n}\n\n.opacity-100 {\n opacity: 1;\n}\n\n.opacity-30 {\n opacity: 0.3;\n}\n\n.opacity-50 {\n opacity: 0.5;\n}\n\n.opacity-75 {\n opacity: 0.75;\n}\n\n.shadow {\n --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n\n.shadow-2xl {\n --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n\n.shadow-lg {\n --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n\n.filter {\n filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);\n}\n\n.transition {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n\n.transition-colors {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n\n.transition-opacity {\n transition-property: opacity;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n\n.transition-transform {\n transition-property: transform;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n\n.duration-100 {\n transition-duration: 100ms;\n}\n\n.duration-200 {\n transition-duration: 200ms;\n}\n\n.duration-75 {\n transition-duration: 75ms;\n}\n\n.ease-in {\n transition-timing-function: cubic-bezier(0.4, 0, 1, 1);\n}\n\n.ease-out {\n transition-timing-function: cubic-bezier(0, 0, 0.2, 1);\n}\n\n.last\\:border-transparent:last-child {\n border-color: transparent;\n}\n\n.hover\\:bg-gray-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n\n@media (min-width: 768px) {\n .md\\:bottom-14 {\n bottom: 3.5rem;\n }\n\n .md\\:right-16 {\n right: 4rem;\n }\n\n .md\\:right-3 {\n right: 0.75rem;\n }\n\n .md\\:flex {\n display: flex;\n }\n\n .md\\:grid {\n display: grid;\n }\n\n .md\\:w-2\\/5 {\n width: 40%;\n }\n\n .md\\:w-\\[40em\\] {\n width: 40em;\n }\n\n .md\\:px-24 {\n padding-left: 6rem;\n padding-right: 6rem;\n }\n}\n\n@media (prefers-color-scheme: dark) {\n .dark\\:text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n }\n}";
11766
12206
 
11767
12207
  // https://maximomussini.com/posts/vue-custom-elements
11768
12208