@edrlab/thorium-web 1.3.1 → 1.4.1

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 (124) hide show
  1. package/dist/{ThPreferencesAdapter-D0rzsGRl.d.mts → ThPreferencesAdapter-_5AePKHa.d.mts} +26 -7
  2. package/dist/{ThSettingsWrapper-BXuRgdqp.d.mts → ThSettingsWrapper-B_9klYXH.d.mts} +1 -1
  3. package/dist/{actions-BLAr0oaM.d.mts → actions-CuRRM3rp.d.mts} +5 -2
  4. package/dist/{actionsReducer-XWTGGNUd.d.mts → actionsReducer-VFR42qgL.d.mts} +1 -1
  5. package/dist/{chunk-6EHFW43Y.mjs → chunk-2NCN2AG2.mjs} +5 -4
  6. package/dist/chunk-2NCN2AG2.mjs.map +1 -0
  7. package/dist/{chunk-L4XGZAZ5.mjs → chunk-2YRT7RNW.mjs} +20 -3
  8. package/dist/chunk-2YRT7RNW.mjs.map +1 -0
  9. package/dist/{chunk-5LUMM7FW.mjs → chunk-44PEO3DS.mjs} +2 -2
  10. package/dist/{chunk-5LUMM7FW.mjs.map → chunk-44PEO3DS.mjs.map} +1 -1
  11. package/dist/chunk-A575ZW4A.mjs +10 -0
  12. package/dist/chunk-A575ZW4A.mjs.map +1 -0
  13. package/dist/chunk-AE6P4KJB.mjs +13 -0
  14. package/dist/chunk-AE6P4KJB.mjs.map +1 -0
  15. package/dist/chunk-AQSJDL63.mjs +193 -0
  16. package/dist/chunk-AQSJDL63.mjs.map +1 -0
  17. package/dist/{chunk-NKO3K3QS.mjs → chunk-DQDOOTCE.mjs} +5 -5
  18. package/dist/chunk-DQDOOTCE.mjs.map +1 -0
  19. package/dist/{chunk-SAUOY37Q.mjs → chunk-E2JEGVVE.mjs} +15 -15
  20. package/dist/chunk-E2JEGVVE.mjs.map +1 -0
  21. package/dist/{chunk-DETZMFZ7.mjs → chunk-ETLIGONP.mjs} +39 -33
  22. package/dist/chunk-ETLIGONP.mjs.map +1 -0
  23. package/dist/chunk-GNROODJB.mjs +9 -0
  24. package/dist/chunk-GNROODJB.mjs.map +1 -0
  25. package/dist/{chunk-6BUN7DEA.mjs → chunk-KGSFTRCH.mjs} +69 -84
  26. package/dist/chunk-KGSFTRCH.mjs.map +1 -0
  27. package/dist/{chunk-LP3JFZ4A.mjs → chunk-MSHUPSBI.mjs} +718 -466
  28. package/dist/chunk-MSHUPSBI.mjs.map +1 -0
  29. package/dist/chunk-OD75GC5N.mjs +3953 -0
  30. package/dist/chunk-OD75GC5N.mjs.map +1 -0
  31. package/dist/{chunk-I4BKU5NN.mjs → chunk-RBEPH5E5.mjs} +100 -30
  32. package/dist/chunk-RBEPH5E5.mjs.map +1 -0
  33. package/dist/{chunk-DMZFSOHK.mjs → chunk-SI4FBFHM.mjs} +135 -46
  34. package/dist/chunk-SI4FBFHM.mjs.map +1 -0
  35. package/dist/{chunk-A3FZBEUL.mjs → chunk-SZAVAQ6S.mjs} +30 -6
  36. package/dist/chunk-SZAVAQ6S.mjs.map +1 -0
  37. package/dist/{chunk-ITDBOMY5.mjs → chunk-VENFFPK2.mjs} +3 -3
  38. package/dist/{chunk-ITDBOMY5.mjs.map → chunk-VENFFPK2.mjs.map} +1 -1
  39. package/dist/{chunk-2ORXUOH3.mjs → chunk-WF2UOYO7.mjs} +4 -4
  40. package/dist/{chunk-2ORXUOH3.mjs.map → chunk-WF2UOYO7.mjs.map} +1 -1
  41. package/dist/{chunk-EZG6SBSO.mjs → chunk-YEVLT3AV.mjs} +104 -29
  42. package/dist/chunk-YEVLT3AV.mjs.map +1 -0
  43. package/dist/components/Audio/index.css +2 -1
  44. package/dist/components/Audio/index.css.map +1 -1
  45. package/dist/components/Audio/index.d.mts +16 -15
  46. package/dist/components/Audio/index.mjs +16 -16
  47. package/dist/components/Epub/index.css +5 -4
  48. package/dist/components/Epub/index.css.map +1 -1
  49. package/dist/components/Epub/index.d.mts +13 -13
  50. package/dist/components/Epub/index.mjs +17 -17
  51. package/dist/components/Misc/index.mjs +5 -5
  52. package/dist/components/Reader/index.css +5 -4
  53. package/dist/components/Reader/index.css.map +1 -1
  54. package/dist/components/Reader/index.d.mts +11 -11
  55. package/dist/components/Reader/index.mjs +34 -30
  56. package/dist/components/Reader/index.mjs.map +1 -1
  57. package/dist/components/WebPub/index.css +5 -4
  58. package/dist/components/WebPub/index.css.map +1 -1
  59. package/dist/components/WebPub/index.d.mts +13 -13
  60. package/dist/components/WebPub/index.mjs +17 -17
  61. package/dist/core/Components/index.d.mts +12 -22
  62. package/dist/core/Components/index.mjs +2 -2
  63. package/dist/core/Helpers/index.d.mts +1 -1
  64. package/dist/core/Helpers/index.mjs +3 -4
  65. package/dist/core/Hooks/index.d.mts +12 -8
  66. package/dist/core/Hooks/index.mjs +1 -1
  67. package/dist/i18n/index.mjs +4 -7
  68. package/dist/lib/index.d.mts +56 -20
  69. package/dist/lib/index.mjs +3 -2
  70. package/dist/locales/da/thorium-shared.json +3 -0
  71. package/dist/locales/da/thorium-web.json +37 -2
  72. package/dist/locales/en/thorium-shared.json +24 -2
  73. package/dist/locales/en/thorium-web.json +2 -2
  74. package/dist/locales/es/thorium-shared.json +364 -0
  75. package/dist/locales/es/thorium-web.json +130 -0
  76. package/dist/locales/et/thorium-shared.json +121 -9
  77. package/dist/locales/et/thorium-web.json +32 -1
  78. package/dist/locales/fi/thorium-shared.json +42 -4
  79. package/dist/locales/fi/thorium-web.json +36 -2
  80. package/dist/locales/fr/thorium-shared.json +108 -1
  81. package/dist/locales/fr/thorium-web.json +121 -86
  82. package/dist/locales/it/thorium-shared.json +108 -1
  83. package/dist/locales/it/thorium-web.json +15 -2
  84. package/dist/locales/lt/thorium-web.json +36 -2
  85. package/dist/locales/pl/thorium-web.json +1 -1
  86. package/dist/locales/pt-BR/thorium-shared.json +6 -0
  87. package/dist/locales/pt-BR/thorium-web.json +88 -88
  88. package/dist/locales/pt-PT/thorium-shared.json +91 -0
  89. package/dist/locales/pt-PT/thorium-web.json +15 -3
  90. package/dist/locales/sv/thorium-shared.json +108 -2
  91. package/dist/locales/sv/thorium-web.json +15 -3
  92. package/dist/locales/tr/thorium-shared.json +42 -0
  93. package/dist/next-lib/index.mjs +1 -1
  94. package/dist/next-lib/index.mjs.map +1 -1
  95. package/dist/preferences/index.d.mts +59 -13
  96. package/dist/preferences/index.mjs +7 -7
  97. package/dist/{settingsReducer-Bu1zeveu.d.mts → settingsReducer-VqBhLq50.d.mts} +14 -2
  98. package/dist/{ui-nBv8gfr0.d.mts → ui-DnZZhozX.d.mts} +1 -1
  99. package/dist/{useAudioNavigator-C5aW4-eT.d.mts → useAudioNavigator-CWXyNWq1.d.mts} +3 -1
  100. package/dist/{useContrast-2t429O9O.d.mts → useContrast-Cbso7N1l.d.mts} +5 -1
  101. package/dist/{usePreferences-VaBf46eP.d.mts → usePreferences-9ZvbcbLW.d.mts} +6 -8
  102. package/dist/{useReaderTransitions-IBGdE7qi.d.mts → useReaderTransitions-0hKGCvMm.d.mts} +64 -12
  103. package/package.json +10 -9
  104. package/dist/chunk-6BUN7DEA.mjs.map +0 -1
  105. package/dist/chunk-6EHFW43Y.mjs.map +0 -1
  106. package/dist/chunk-7CGMWOZN.mjs +0 -20
  107. package/dist/chunk-7CGMWOZN.mjs.map +0 -1
  108. package/dist/chunk-A3FZBEUL.mjs.map +0 -1
  109. package/dist/chunk-B3WDMWCT.mjs +0 -9
  110. package/dist/chunk-B3WDMWCT.mjs.map +0 -1
  111. package/dist/chunk-DETZMFZ7.mjs.map +0 -1
  112. package/dist/chunk-DMZFSOHK.mjs.map +0 -1
  113. package/dist/chunk-DTPO3J2C.mjs +0 -1732
  114. package/dist/chunk-DTPO3J2C.mjs.map +0 -1
  115. package/dist/chunk-EZG6SBSO.mjs.map +0 -1
  116. package/dist/chunk-GPWW5OML.mjs +0 -1955
  117. package/dist/chunk-GPWW5OML.mjs.map +0 -1
  118. package/dist/chunk-I4BKU5NN.mjs.map +0 -1
  119. package/dist/chunk-L4XGZAZ5.mjs.map +0 -1
  120. package/dist/chunk-LP3JFZ4A.mjs.map +0 -1
  121. package/dist/chunk-MLEYTQGK.mjs +0 -60
  122. package/dist/chunk-MLEYTQGK.mjs.map +0 -1
  123. package/dist/chunk-NKO3K3QS.mjs.map +0 -1
  124. package/dist/chunk-SAUOY37Q.mjs.map +0 -1
@@ -1,21 +1,21 @@
1
- import { ErrorHandler } from './chunk-RRDEPGBK.mjs';
2
- import { useFullscreen, useEpubNavigator, useLocalStorage } from './chunk-A3FZBEUL.mjs';
3
- import { useAppDispatch, setFullscreen, useAppSelector, setActionOpen, dockAction, setHovering, setSettingsContainer, debounce, setColumnCount, setWebPubFontFamily, setFontFamily, setWebPubFontWeight, setFontWeight, setWebPubHyphens, setHyphens, setScroll, setWebPubLetterSpacing, setLetterSpacing, setWebPubLineHeight, setLineHeight, setWebPubParagraphIndent, setParagraphIndent, setWebPubParagraphSpacing, setParagraphSpacing, setWebPubWordSpacing, setWordSpacing, setWebPubSpacingPreset, setWebPubPublisherStyles, setSpacingPreset, setPublisherStyles, setWebPubTextAlign, setTextAlign, setWebPubTextNormalization, setTextNormalization, setTheme, setWebPubZoom, setFontSize, setSkipBackwardInterval, setSkipForwardInterval, setSkipInterval, setAutoPlay, toggleActionOpen, setVolume, setPlaybackRate, setSleepTimerRemainingSeconds, setSleepTimerOnTrackEnd, setSleepTimerOnFragmentEnd, setRemotePlaybackState, ThReduxPreferencesAdapter, setReaderProfile, setPositionsList, setTocTree, setRTL, setFXL, setHasDisplayTransformability, setImmersive, setOverflow, setUserNavigated, setTocEntry, collapseDockPanel, expandDockPanel, activateDockPanel, deactivateDockPanel, setDockPanelWidth } from './chunk-EZG6SBSO.mjs';
1
+ import { makeBreakpointsMap, isKeyboardTriggered, isActiveElement } from './chunk-VENFFPK2.mjs';
2
+ import { useFullscreen, useLocalStorage, useEpubNavigator } from './chunk-SZAVAQ6S.mjs';
3
+ import { setFullscreen, setReaderProfile, setPositionsList, setTocTree, setScriptMode, setRTL, setFXL, setHasDisplayTransformability, setActionOpen, dockAction, setHovering, setSettingsContainer, debounce, setColumnCount, initialWebPubSettingsState, initialSettingsState, setWebPubFontFamily, setFontFamily, setWebPubFontWeight, setFontWeight, setWebPubHyphens, setHyphens, setScroll, setWebPubLetterSpacing, setLetterSpacing, setWebPubLineHeight, setLineHeight, setWebPubParagraphIndent, setParagraphIndent, setWebPubParagraphSpacing, setParagraphSpacing, setWebPubWordSpacing, setWordSpacing, setWebPubSpacingPreset, setWebPubPublisherStyles, setSpacingPreset, setPublisherStyles, setWebPubTextAlign, setTextAlign, setWebPubTextNormalization, setTextNormalization, setWebPubLigatures, setLigatures, setWebPubNoRuby, setNoRuby, setTheme, setWebPubZoom, setFontSize, setSkipBackwardInterval, setSkipForwardInterval, setSkipInterval, setAutoPlay, toggleActionOpen, setVolume, setPlaybackRate, setSleepTimerRemainingSeconds, setSleepTimerOnTrackEnd, setSleepTimerOnFragmentEnd, setRemotePlaybackState, ThReduxPreferencesAdapter, ThReduxGlobalPreferencesAdapter, setImmersive, setOverflow, setUserNavigated, setTocEntry, collapseDockPanel, expandDockPanel, activateDockPanel, deactivateDockPanel, setDockPanelWidth } from './chunk-YEVLT3AV.mjs';
4
4
  import { buildTocTree, findTocItemById } from './chunk-TEZB4ULX.mjs';
5
- import { useActionsPreferences, prefixString, useAudioPreferences, usePreferences, usePreferenceKeys, buildThemeObject, ThPreferencesProvider } from './chunk-GPWW5OML.mjs';
6
- import { useI18n } from './chunk-6EHFW43Y.mjs';
7
- import { useSharedPreferences, ThDockingTypes, ThSheetTypes, defaultSpacingSettingsSubpanel, defaultSpacingSettingsMain, defaultTextSettingsSubpanel, defaultTextSettingsMain, ThTextSettingsKeys, ThSpacingSettingsKeys, defaultAudioSkipBackwardInterval, defaultAudioSkipForwardInterval, defaultAudioSkipInterval, defaultPreferences } from './chunk-DTPO3J2C.mjs';
8
- import { ThMenuItem, ThActionButton, ThMenu, ThCollapsibleActionsBar, ThPopover, ThContainerHeader, ThNavigationButton, ThContainerBody, ThModal, ThBottomSheet, ThCloseButton, ThDockedPanel, useFirstFocusable, ThTypedComponentRenderer, useActions, useActionComponentStatus, ThForm, ThFormNumberField, usePlugins, ThSettingsWrapper, ThRadioGroup, ThDropdown, ThSwitch, ThNumberField, ThSlider, ThSliderWithPresets, ThLink, ThLibrary, ThHome, ThBackArrow, ThFormSearchField } from './chunk-DETZMFZ7.mjs';
5
+ import { useSharedPreferences, useActionsPreferences, prefixString, ThDockingTypes, ThSheetTypes, useAudioPreferences, usePreferences, useFilteredPreferenceKeys, defaultSpacingSettingsSubpanel, defaultSpacingSettingsMain, defaultTextSettingsSubpanel, defaultTextSettingsMain, ThTextSettingsKeys, ThSpacingSettingsKeys, buildThemeObject, defaultAudioSkipBackwardInterval, defaultAudioSkipForwardInterval, defaultAudioSkipInterval, defaultPreferences, ThPreferencesProvider, ThGlobalPreferencesProvider } from './chunk-OD75GC5N.mjs';
6
+ import { useAppDispatch, useAppSelector } from './chunk-A575ZW4A.mjs';
7
+ import { isIOSish, buildShortcut, metaKeys } from './chunk-44PEO3DS.mjs';
8
+ import { ErrorHandler } from './chunk-RRDEPGBK.mjs';
9
+ import { ThMenuItem, ThActionButton, ThMenu, ThCollapsibleActionsBar, ThPopover, ThContainerHeader, ThNavigationButton, ThContainerBody, ThModal, ThBottomSheet, ThCloseButton, ThDockedPanel, useFirstFocusable, ThTypedComponentRenderer, useActions, useActionComponentStatus, ThForm, ThFormNumberField, usePlugins, ThSettingsWrapper, ThRadioGroup, ThDropdown, ThSwitch, ThNumberField, ThSlider, ThSliderWithPresets, ThLink, ThLibrary, ThHome, ThBackArrow, ThFormSearchField } from './chunk-ETLIGONP.mjs';
9
10
  import { usePrevious } from './chunk-YZ73DHRU.mjs';
10
- import { makeBreakpointsMap, isKeyboardTriggered, isActiveElement } from './chunk-ITDBOMY5.mjs';
11
- import { isIOSish, buildShortcut, metaKeys } from './chunk-5LUMM7FW.mjs';
11
+ import { useI18n } from './chunk-2NCN2AG2.mjs';
12
12
  import { Text, Popover, Dialog, ListBox, ListBoxItem, Radio, Button, Keyboard, Toolbar, useFilter, Tree, TreeItem, TreeItemContent, Collection } from 'react-aria-components';
13
13
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
14
- import { useObjectRef, useNumberFormatter, FocusScope, useFocusWithin } from 'react-aria';
14
+ import { useObjectRef, useNumberFormatter, FocusScope, useLocale, useFocusWithin } from 'react-aria';
15
15
  import classNames4 from 'classnames';
16
- import React24, { createContext, useCallback, useRef, useContext, useMemo, useEffect, useState } from 'react';
16
+ import React22, { createContext, useCallback, useRef, useMemo, useContext, useState, useEffect } from 'react';
17
17
  import { Link, HttpFetcher, Manifest, Publication, ReadingProgression, Layout, Feature, Profile } from '@readium/shared';
18
- import { TextAlignment } from '@readium/navigator';
18
+ import { getScriptMode, TextAlignment } from '@readium/navigator';
19
19
  import { useStore } from 'react-redux';
20
20
  import { PanelGroup, Panel, PanelResizeHandle } from 'react-resizable-panels';
21
21
 
@@ -219,6 +219,7 @@ var StatefulFullscreenTrigger = ({ variant }) => {
219
219
  };
220
220
  var SvgMoreVert = (props) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", fill: "inherit", ...props, children: /* @__PURE__ */ jsx("path", { d: "M480-160q-33 0-56.5-23.5T400-240q0-33 23.5-56.5T480-320q33 0 56.5 23.5T560-240q0 33-23.5 56.5T480-160Zm0-240q-33 0-56.5-23.5T400-480q0-33 23.5-56.5T480-560q33 0 56.5 23.5T560-480q0 33-23.5 56.5T480-400Zm0-240q-33 0-56.5-23.5T400-720q0-33 23.5-56.5T480-800q33 0 56.5 23.5T560-720q0 33-23.5 56.5T480-640Z" }) });
221
221
  var more_vert_default = SvgMoreVert;
222
+ var MENU_DEPENDENCIES = ["Trigger"];
222
223
  var StatefulOverflowMenu = ({
223
224
  id,
224
225
  className,
@@ -241,7 +242,7 @@ var StatefulOverflowMenu = ({
241
242
  triggerRef,
242
243
  selectionMode: "none",
243
244
  className: thorium_web_overflow_default.menu,
244
- dependencies: ["Trigger"],
245
+ dependencies: MENU_DEPENDENCIES,
245
246
  items,
246
247
  compounds: {
247
248
  menuTrigger: {
@@ -274,7 +275,18 @@ var StatefulCollapsibleActionsBar = ({
274
275
  ...props
275
276
  }) => {
276
277
  const ref = useRef(null);
277
- const breakpoint = useAppSelector((state) => state.theming.breakpoint);
278
+ const breakpoint = useAppSelector((state) => state.theming.containerBreakpoint);
279
+ const compounds = useMemo(() => ({
280
+ menu: /* @__PURE__ */ jsx(
281
+ StatefulOverflowMenu,
282
+ {
283
+ id,
284
+ triggerRef: ref,
285
+ className: overflowMenuClassName,
286
+ items: []
287
+ }
288
+ )
289
+ }), [id, overflowMenuClassName]);
278
290
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
279
291
  ThCollapsibleActionsBar,
280
292
  {
@@ -282,17 +294,7 @@ var StatefulCollapsibleActionsBar = ({
282
294
  id,
283
295
  items,
284
296
  breakpoint,
285
- compounds: {
286
- menu: /* @__PURE__ */ jsx(
287
- StatefulOverflowMenu,
288
- {
289
- id,
290
- triggerRef: ref,
291
- className: overflowMenuClassName,
292
- items: []
293
- }
294
- )
295
- },
297
+ compounds,
296
298
  ...props
297
299
  }
298
300
  ) });
@@ -357,6 +359,12 @@ var useNavigator = () => {
357
359
  return callback?.(false);
358
360
  },
359
361
  isVisual: () => isVisual,
362
+ getScriptMode: () => {
363
+ if (isVisual && navigator.getScriptMode) {
364
+ return navigator.getScriptMode?.();
365
+ }
366
+ return void 0;
367
+ },
360
368
  getCframes: isVisual ? navigator.getCframes?.bind(navigator) : void 0,
361
369
  underlying: navigator
362
370
  };
@@ -387,6 +395,223 @@ var useNavigator = () => {
387
395
  }), [visualMemo, mediaMemo, unified]);
388
396
  };
389
397
 
398
+ // src/hooks/useIsScroll.ts
399
+ var useIsScroll = () => {
400
+ const profile = useAppSelector((state) => state.reader.profile);
401
+ const scroll = useAppSelector((state) => state.settings.scroll);
402
+ const isFXL = useAppSelector((state) => state.publication.isFXL);
403
+ const scriptMode = useAppSelector((state) => state.publication.scriptMode);
404
+ if (profile === "webPub") return true;
405
+ return (scroll || scriptMode === "cjk-vertical" || scriptMode === "mongolian-vertical") && !isFXL;
406
+ };
407
+
408
+ // src/hooks/useReaderTransitions.ts
409
+ var useReaderTransitions = () => {
410
+ const isImmersive = useAppSelector((state) => state.reader.isImmersive);
411
+ const isFullscreen = useAppSelector((state) => state.reader.isFullscreen);
412
+ const hasUserNavigated = useAppSelector((state) => state.reader.hasUserNavigated);
413
+ const isScroll = useIsScroll();
414
+ const wasImmersive = usePrevious(isImmersive) ?? false;
415
+ const wasFullscreen = usePrevious(isFullscreen) ?? false;
416
+ const wasScroll = usePrevious(isScroll) ?? false;
417
+ const wasUserNavigated = usePrevious(hasUserNavigated) ?? false;
418
+ const fromImmersive = wasImmersive && !isImmersive;
419
+ const toImmersive = !wasImmersive && isImmersive;
420
+ const fromFullscreen = wasFullscreen && !isFullscreen;
421
+ const toFullscreen = !wasFullscreen && isFullscreen;
422
+ const fromScroll = wasScroll && !isScroll;
423
+ const toScroll = !wasScroll && isScroll;
424
+ const fromUserNavigation = wasUserNavigated && !hasUserNavigated;
425
+ const toUserNavigation = !wasUserNavigated && hasUserNavigated;
426
+ return {
427
+ // Current states
428
+ isImmersive,
429
+ isFullscreen,
430
+ isScroll,
431
+ hasUserNavigated,
432
+ // Previous states
433
+ wasImmersive,
434
+ wasFullscreen,
435
+ wasScroll,
436
+ wasUserNavigated,
437
+ // State transitions
438
+ fromImmersive,
439
+ toImmersive,
440
+ fromFullscreen,
441
+ toFullscreen,
442
+ fromScroll,
443
+ toScroll,
444
+ fromUserNavigation,
445
+ toUserNavigation
446
+ };
447
+ };
448
+
449
+ // src/helpers/deserializePositions.ts
450
+ var deserializePositions = (positionsList) => {
451
+ return positionsList?.map((locator) => ({
452
+ href: locator.href,
453
+ type: locator.type,
454
+ locations: {
455
+ position: locator.locations.position,
456
+ progression: locator.locations.progression,
457
+ totalProgression: locator.locations.totalProgression
458
+ }
459
+ }));
460
+ };
461
+
462
+ // src/hooks/usePublication.ts
463
+ var detectProfile = (manifest) => {
464
+ const metadata = manifest.metadata;
465
+ if (!metadata) return "webPub";
466
+ const conformsTo = metadata.conformsTo;
467
+ if (!conformsTo) return "webPub";
468
+ const profiles = Array.isArray(conformsTo) ? conformsTo : [conformsTo];
469
+ if (profiles.some(
470
+ (profile) => profile === Profile.AUDIOBOOK
471
+ )) {
472
+ return "audio";
473
+ }
474
+ if (profiles.some(
475
+ (profile) => profile === Profile.EPUB
476
+ )) {
477
+ return "epub";
478
+ }
479
+ return "webPub";
480
+ };
481
+ var usePublication = ({
482
+ url,
483
+ onError = () => {
484
+ },
485
+ fetcher: customFetcher
486
+ }) => {
487
+ const dispatch = useAppDispatch();
488
+ const [isLoading, setIsLoading] = useState(true);
489
+ const [error, setError] = useState(null);
490
+ const [manifest, setManifest] = useState(null);
491
+ const [selfLink, setSelfLink] = useState(null);
492
+ const [localDataKey, setLocalDataKey] = useState(null);
493
+ const [publication, setPublication] = useState(null);
494
+ const [profile, setProfile] = useState(null);
495
+ const [isRTL, setIsRTL] = useState(false);
496
+ const [isFXL, setIsFXL] = useState(false);
497
+ const [hasDisplayTransformability, setHasDisplayTransformabilityState] = useState(false);
498
+ const handleManifestError = (error2, context) => {
499
+ console.error(`${context}:`, error2);
500
+ const processedError = ErrorHandler.process(error2, context);
501
+ setError(processedError);
502
+ setIsLoading(false);
503
+ };
504
+ useEffect(() => {
505
+ if (!url) {
506
+ const validationError = ErrorHandler.process(new Error("Manifest URL is required"), "Validation");
507
+ setError(validationError);
508
+ setIsLoading(false);
509
+ return;
510
+ }
511
+ setIsLoading(true);
512
+ setError(null);
513
+ const decodedUrl = decodeURIComponent(url);
514
+ const manifestLink = new Link({ href: decodedUrl });
515
+ const fetcher = customFetcher || new HttpFetcher(void 0);
516
+ try {
517
+ const fetched = fetcher.get(manifestLink);
518
+ fetched.link().then(async (link) => {
519
+ try {
520
+ const selfHref = link.toURL(decodedUrl);
521
+ setSelfLink(selfHref || null);
522
+ if (selfHref) {
523
+ setLocalDataKey(`${selfHref}-current-location`);
524
+ const manifestFetcher = customFetcher || new HttpFetcher(void 0, selfHref);
525
+ const manifestFetched = manifestFetcher.get(manifestLink);
526
+ const manifestData = await manifestFetched.readAsJSON();
527
+ setManifest(manifestData);
528
+ const manifestObj = Manifest.deserialize(manifestData);
529
+ manifestObj.setSelfLink(selfHref);
530
+ const detectedProfile = detectProfile(manifestObj);
531
+ setProfile(detectedProfile);
532
+ dispatch(setReaderProfile(detectedProfile));
533
+ const pub = new Publication({
534
+ manifest: manifestObj,
535
+ fetcher: manifestFetcher
536
+ });
537
+ if (detectedProfile === "epub") {
538
+ try {
539
+ const rawPositions = await pub.positionsFromManifest();
540
+ const positionsList = deserializePositions(rawPositions);
541
+ dispatch(setPositionsList(positionsList));
542
+ } catch (error2) {
543
+ console.error("Failed to fetch positions:", error2);
544
+ dispatch(setPositionsList([]));
545
+ }
546
+ }
547
+ if (detectedProfile === "audio") {
548
+ const tocLinks = manifestObj.toc?.items && manifestObj.toc.items.length > 0 ? manifestObj.toc.items : manifestObj.readingOrder?.items || [];
549
+ const publicationTitle = manifestObj.metadata.title.getTranslation("en");
550
+ let idCounter = 0;
551
+ const idGenerator = () => `toc-${++idCounter}`;
552
+ dispatch(setTocTree(buildTocTree(tocLinks, idGenerator, void 0, publicationTitle)));
553
+ }
554
+ setPublication(pub);
555
+ setIsLoading(false);
556
+ }
557
+ } catch (error2) {
558
+ handleManifestError(error2, "Error loading manifest");
559
+ }
560
+ });
561
+ } catch (error2) {
562
+ handleManifestError(error2, "Error loading manifest");
563
+ }
564
+ }, [url, customFetcher, dispatch]);
565
+ useEffect(() => {
566
+ if (!publication) return;
567
+ const mode = getScriptMode(publication.metadata);
568
+ dispatch(setScriptMode(mode));
569
+ const rtl = publication.metadata.effectiveReadingProgression === ReadingProgression.rtl;
570
+ setIsRTL(rtl);
571
+ dispatch(setRTL(rtl));
572
+ if (profile === "epub") {
573
+ const fxl = publication.metadata.effectiveLayout === Layout.fixed;
574
+ setIsFXL(fxl);
575
+ dispatch(setFXL(fxl));
576
+ }
577
+ const displayTransformability = publication.metadata.accessibility?.feature?.some(
578
+ (feature) => feature && feature.value === Feature.DISPLAY_TRANSFORMABILITY.value
579
+ ) || false;
580
+ setHasDisplayTransformabilityState(displayTransformability);
581
+ dispatch(setHasDisplayTransformability(displayTransformability));
582
+ if (profile === "epub" && publication) {
583
+ const fetchPositions = async () => {
584
+ try {
585
+ const positionsList = await publication.positionsFromManifest();
586
+ const deserializedPositionsList = deserializePositions(positionsList);
587
+ dispatch(setPositionsList(deserializedPositionsList));
588
+ } catch (error2) {
589
+ console.error("Failed to fetch positions:", error2);
590
+ dispatch(setPositionsList([]));
591
+ }
592
+ };
593
+ fetchPositions();
594
+ }
595
+ }, [publication, profile, dispatch]);
596
+ useEffect(() => {
597
+ if (error) {
598
+ onError(error);
599
+ }
600
+ }, [error, onError]);
601
+ return {
602
+ isLoading,
603
+ error,
604
+ publication,
605
+ manifest,
606
+ selfLink,
607
+ localDataKey,
608
+ profile,
609
+ isRTL,
610
+ isFXL,
611
+ hasDisplayTransformability
612
+ };
613
+ };
614
+
390
615
  // src/components/Sheets/assets/styles/thorium-web.sheets.module.css
391
616
  var thorium_web_sheets_default = {
392
617
  fullscreen: "thorium_web_sheets_fullscreen",
@@ -624,28 +849,58 @@ var StatefulDocker = ({
624
849
  )
625
850
  ] }) });
626
851
  };
852
+ var usePositionStorage = (key, customStorage) => {
853
+ const localStorageData = useLocalStorage(key);
854
+ const [customData, setCustomData] = useState(
855
+ () => customStorage ? customStorage.get() || null : null
856
+ );
857
+ if (customStorage) {
858
+ const set = (newValue) => {
859
+ if (newValue) {
860
+ customStorage.set(newValue);
861
+ }
862
+ setCustomData(newValue);
863
+ };
864
+ const get = () => customData;
865
+ return {
866
+ setLocalData: set,
867
+ getLocalData: get,
868
+ localData: customData
869
+ };
870
+ }
871
+ return localStorageData;
872
+ };
873
+
874
+ // src/components/Sheets/hooks/useWebkitPatch.ts
627
875
  var useWebkitPatch = (isOpen) => {
628
- const profile = useAppSelector((state) => state.reader.profile);
629
- const isWebPub = profile === "webPub";
630
- const scroll = useAppSelector((state) => state.settings.scroll);
631
- const isFXL = useAppSelector((state) => state.publication.isFXL);
632
- const isScroll = isWebPub || scroll && !isFXL;
876
+ const isScroll = useIsScroll();
877
+ const scriptMode = useAppSelector((state) => state.publication.scriptMode);
878
+ const isHorizontalScroll = scriptMode === "cjk-vertical" || scriptMode === "mongolian-vertical";
633
879
  const prevIsOpen = usePrevious(isOpen);
634
880
  let getCframes;
635
881
  try {
636
882
  const visual = useNavigator().visual;
637
883
  getCframes = visual.getCframes;
638
- } catch (e) {
884
+ } catch (_e) {
639
885
  getCframes = void 0;
640
886
  }
641
887
  useEffect(() => {
642
888
  if (isScroll && prevIsOpen && !isOpen && getCframes) {
643
889
  const container = document.getElementById("thorium-web-container");
644
890
  if (!container) return;
645
- const currentHeight = container.offsetHeight;
646
- container.style.height = `${currentHeight - 1}px`;
891
+ if (isHorizontalScroll) {
892
+ const currentWidth = container.offsetWidth;
893
+ container.style.width = `${currentWidth - 1}px`;
894
+ } else {
895
+ const currentHeight = container.offsetHeight;
896
+ container.style.height = `${currentHeight - 1}px`;
897
+ }
647
898
  setTimeout(() => {
648
- container.style.height = "";
899
+ if (isHorizontalScroll) {
900
+ container.style.width = "";
901
+ } else {
902
+ container.style.height = "";
903
+ }
649
904
  if (!getCframes) return;
650
905
  const frames = getCframes();
651
906
  if (!frames || !Array.isArray(frames) || frames.length === 0) return;
@@ -654,19 +909,26 @@ var useWebkitPatch = (isOpen) => {
654
909
  try {
655
910
  frameWindow = frame?.window;
656
911
  if (!frameWindow?.document?.scrollingElement) return;
657
- } catch (e) {
912
+ } catch (_e) {
658
913
  return;
659
914
  }
660
- const currentScrollTop = frameWindow.document.scrollingElement.scrollTop;
661
- if (currentScrollTop > 1) {
662
- frameWindow.document.scrollingElement.scrollTop = currentScrollTop - 1;
915
+ if (isHorizontalScroll) {
916
+ const currentScrollLeft = frameWindow.document.scrollingElement.scrollLeft;
917
+ const nudge = currentScrollLeft <= 0 ? -1 : 1;
918
+ frameWindow.document.scrollingElement.scrollLeft = currentScrollLeft + nudge;
919
+ frameWindow.document.scrollingElement.scrollLeft = currentScrollLeft;
663
920
  } else {
664
- frameWindow.document.scrollingElement.scrollTop = currentScrollTop + 1;
921
+ const currentScrollTop = frameWindow.document.scrollingElement.scrollTop;
922
+ if (currentScrollTop > 1) {
923
+ frameWindow.document.scrollingElement.scrollTop = currentScrollTop - 1;
924
+ } else {
925
+ frameWindow.document.scrollingElement.scrollTop = currentScrollTop + 1;
926
+ }
927
+ frameWindow.document.scrollingElement.scrollTop = currentScrollTop;
665
928
  }
666
- frameWindow.document.scrollingElement.scrollTop = currentScrollTop;
667
929
  }, 0);
668
930
  }
669
- }, [isScroll, isOpen, prevIsOpen, getCframes]);
931
+ }, [isScroll, isHorizontalScroll, isOpen, prevIsOpen, getCframes]);
670
932
  };
671
933
  var StatefulPopoverSheet = ({
672
934
  id,
@@ -702,7 +964,7 @@ var StatefulPopoverSheet = ({
702
964
  }
703
965
  }, [isOpen]);
704
966
  useWebkitPatch(!!isOpen);
705
- if (React24.Children.toArray(children).length > 0) {
967
+ if (React22.Children.toArray(children).length > 0) {
706
968
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
707
969
  ThPopover,
708
970
  {
@@ -811,7 +1073,7 @@ var StatefulModalBase = ({
811
1073
  }
812
1074
  }, [isOpen]);
813
1075
  useWebkitPatch(!!isOpen);
814
- if (React24.Children.toArray(children).length > 0) {
1076
+ if (React22.Children.toArray(children).length > 0) {
815
1077
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
816
1078
  ThModal,
817
1079
  {
@@ -1070,7 +1332,7 @@ var StatefulBottomSheet = ({
1070
1332
  return "default";
1071
1333
  }
1072
1334
  };
1073
- if (React24.Children.toArray(children).length > 0) {
1335
+ if (React22.Children.toArray(children).length > 0) {
1074
1336
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
1075
1337
  ThBottomSheet,
1076
1338
  {
@@ -1197,8 +1459,7 @@ var StatefulDockedSheet = ({
1197
1459
  children,
1198
1460
  resetFocus,
1199
1461
  focusSelector,
1200
- focusWithinRef,
1201
- scrollTopOnFocus
1462
+ focusWithinRef
1202
1463
  }) => {
1203
1464
  const { t } = useI18n();
1204
1465
  const dockPortal = flow && document.getElementById(flow);
@@ -1222,7 +1483,7 @@ var StatefulDockedSheet = ({
1222
1483
  return direction === "ltr" /* ltr */ ? thorium_web_sheets_default.dockedRightBorder : thorium_web_sheets_default.dockedLeftBorder;
1223
1484
  }
1224
1485
  }, [flow, direction]);
1225
- if (React24.Children.toArray(children).length > 0) {
1486
+ if (React22.Children.toArray(children).length > 0) {
1226
1487
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
1227
1488
  ThDockedPanel,
1228
1489
  {
@@ -1292,7 +1553,6 @@ var StatefulDockedSheet = ({
1292
1553
  }
1293
1554
  };
1294
1555
  var StatefulCompactPopoverSheet = ({
1295
- id,
1296
1556
  triggerRef,
1297
1557
  heading,
1298
1558
  className,
@@ -1322,7 +1582,7 @@ var StatefulCompactPopoverSheet = ({
1322
1582
  updateState: resetFocus
1323
1583
  });
1324
1584
  useWebkitPatch(!!isOpen);
1325
- if (React24.Children.toArray(children).length > 0) {
1585
+ if (React22.Children.toArray(children).length > 0) {
1326
1586
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
1327
1587
  Popover,
1328
1588
  {
@@ -1974,6 +2234,7 @@ var StatefulSpacingGroup = () => {
1974
2234
  const { preferences } = usePreferences();
1975
2235
  const { t } = useI18n();
1976
2236
  const { spacingSettingsComponentsMap } = usePlugins();
2237
+ const { mainSpacingSettingsKeys, subPanelSpacingSettingsKeys } = useFilteredPreferenceKeys();
1977
2238
  const dispatch = useAppDispatch();
1978
2239
  const setSpacingContainer = useCallback(() => {
1979
2240
  dispatch(setSettingsContainer("spacing" /* spacing */));
@@ -1986,7 +2247,11 @@ var StatefulSpacingGroup = () => {
1986
2247
  moreTooltip: t("reader.settings.spacing.advanced.tooltip"),
1987
2248
  onPressMore: setSpacingContainer,
1988
2249
  componentsMap: spacingSettingsComponentsMap,
1989
- prefs: preferences.settings.spacing,
2250
+ prefs: {
2251
+ main: mainSpacingSettingsKeys,
2252
+ subPanel: preferences.settings.spacing?.subPanel === null ? null : subPanelSpacingSettingsKeys,
2253
+ header: preferences.settings.spacing?.header
2254
+ },
1990
2255
  defaultPrefs: {
1991
2256
  main: defaultSpacingSettingsMain,
1992
2257
  subPanel: defaultSpacingSettingsSubpanel
@@ -1995,10 +2260,9 @@ var StatefulSpacingGroup = () => {
1995
2260
  ) });
1996
2261
  };
1997
2262
  var StatefulSpacingGroupContainer = () => {
1998
- const { preferences } = usePreferences();
1999
- const displayOrder = preferences.settings.spacing?.subPanel || defaultSpacingSettingsSubpanel;
2263
+ const { subPanelSpacingSettingsKeys } = useFilteredPreferenceKeys();
2000
2264
  const { spacingSettingsComponentsMap } = usePlugins();
2001
- return /* @__PURE__ */ jsx(Fragment, { children: displayOrder.map((key) => {
2265
+ return /* @__PURE__ */ jsx(Fragment, { children: subPanelSpacingSettingsKeys.map((key) => {
2002
2266
  const match = spacingSettingsComponentsMap[key];
2003
2267
  if (!match) {
2004
2268
  console.warn(`Setting key "${key}" not found in the plugin registry while present in preferences.`);
@@ -2011,6 +2275,7 @@ var StatefulTextGroup = () => {
2011
2275
  const { preferences } = usePreferences();
2012
2276
  const { t } = useI18n();
2013
2277
  const { textSettingsComponentsMap } = usePlugins();
2278
+ const { mainTextSettingsKeys, subPanelTextSettingsKeys } = useFilteredPreferenceKeys();
2014
2279
  const dispatch = useAppDispatch();
2015
2280
  const setTextContainer = useCallback(() => {
2016
2281
  dispatch(setSettingsContainer("text" /* text */));
@@ -2023,7 +2288,11 @@ var StatefulTextGroup = () => {
2023
2288
  moreTooltip: t("reader.settings.text.advanced.tooltip"),
2024
2289
  onPressMore: setTextContainer,
2025
2290
  componentsMap: textSettingsComponentsMap,
2026
- prefs: preferences.settings.text,
2291
+ prefs: {
2292
+ main: mainTextSettingsKeys,
2293
+ subPanel: preferences.settings.text?.subPanel === null ? null : subPanelTextSettingsKeys,
2294
+ header: preferences.settings.text?.header
2295
+ },
2027
2296
  defaultPrefs: {
2028
2297
  main: defaultTextSettingsMain,
2029
2298
  subPanel: defaultTextSettingsSubpanel
@@ -2032,10 +2301,9 @@ var StatefulTextGroup = () => {
2032
2301
  ) });
2033
2302
  };
2034
2303
  var StatefulTextGroupContainer = () => {
2035
- const { preferences } = usePreferences();
2036
- const displayOrder = preferences.settings.text?.subPanel || defaultTextSettingsSubpanel;
2304
+ const { subPanelTextSettingsKeys } = useFilteredPreferenceKeys();
2037
2305
  const { textSettingsComponentsMap } = usePlugins();
2038
- return /* @__PURE__ */ jsx(Fragment, { children: displayOrder.map((key) => {
2306
+ return /* @__PURE__ */ jsx(Fragment, { children: subPanelTextSettingsKeys.map((key) => {
2039
2307
  const match = textSettingsComponentsMap[key];
2040
2308
  if (!match) {
2041
2309
  console.warn(`Action key "${key}" not found in the plugin registry while present in preferences.`);
@@ -2055,7 +2323,7 @@ var StatefulVisualSettingsContainer = ({
2055
2323
  subPanelSpacingSettingsKeys,
2056
2324
  subPanelTextSettingsKeys,
2057
2325
  webPubSettingsKeys
2058
- } = usePreferenceKeys();
2326
+ } = useFilteredPreferenceKeys();
2059
2327
  const { preferences } = usePreferences();
2060
2328
  const { t } = useI18n();
2061
2329
  const { settingsComponentsMap } = usePlugins();
@@ -2344,6 +2612,7 @@ var TocContent = ({
2344
2612
  selectedKeys: tocEntry ? [tocEntry] : [],
2345
2613
  expandedKeys,
2346
2614
  onExpandedChange,
2615
+ dir: isRTL ? "rtl" : "ltr",
2347
2616
  children: function renderItem(item) {
2348
2617
  return /* @__PURE__ */ jsxs(
2349
2618
  TreeItem,
@@ -2382,12 +2651,11 @@ var StatefulTocContainer = ({ triggerRef }) => {
2382
2651
  const tocEntry = unstableTimeline?.toc?.currentEntry ?? void 0;
2383
2652
  const tocEntryId = tocEntry?.id;
2384
2653
  const tocTree = unstableTimeline?.toc?.tree;
2385
- const direction = useAppSelector((state) => state.reader.direction);
2386
- const isRTL = direction === "rtl" /* rtl */;
2654
+ const { goLink, getScriptMode: getScriptMode2 } = useNavigator().unified;
2655
+ const isRTL = getScriptMode2() === "rtl";
2387
2656
  const profile = useAppSelector((state) => state.reader.profile);
2388
2657
  const actionState = useAppSelector((state) => profile ? state.actions.keys[profile]["toc" /* toc */] : void 0);
2389
2658
  const dispatch = useAppDispatch();
2390
- const { goLink } = useNavigator().unified;
2391
2659
  const docking = useDocking("toc" /* toc */);
2392
2660
  const sheetType = docking.sheetType;
2393
2661
  const setOpen = useCallback((value) => {
@@ -2536,7 +2804,7 @@ var useGridNavigation = ({
2536
2804
  onFocus
2537
2805
  }) => {
2538
2806
  const visibleColumns = useGridTemplate(containerRef, "columns");
2539
- const onKeyDown = React24.useCallback((e) => {
2807
+ const onKeyDown = React22.useCallback((e) => {
2540
2808
  const columns = visibleColumns || 1;
2541
2809
  if (columns <= 1 || !items.current?.length) return;
2542
2810
  const currentIdx = items.current.findIndex((val) => {
@@ -2657,6 +2925,25 @@ var StatefulRadioGroup = ({
2657
2925
  }
2658
2926
  ) });
2659
2927
  };
2928
+
2929
+ // src/components/Settings/helpers/settingsKeyMapping.ts
2930
+ var SETTINGS_KEY_TO_PREFERENCE = {
2931
+ ["columns" /* columns */]: "columnCount",
2932
+ ["fontFamily" /* fontFamily */]: "fontFamily",
2933
+ ["fontWeight" /* fontWeight */]: "fontWeight",
2934
+ ["hyphens" /* hyphens */]: "hyphens",
2935
+ ["layout" /* layout */]: "scroll",
2936
+ ["letterSpacing" /* letterSpacing */]: "letterSpacing",
2937
+ ["ligatures" /* ligatures */]: "ligatures",
2938
+ ["lineHeight" /* lineHeight */]: "lineHeight",
2939
+ ["paragraphIndent" /* paragraphIndent */]: "paragraphIndent",
2940
+ ["paragraphSpacing" /* paragraphSpacing */]: "paragraphSpacing",
2941
+ ["textAlign" /* textAlign */]: "textAlign",
2942
+ ["textNormalize" /* textNormalize */]: "textNormalization",
2943
+ ["noRuby" /* noRuby */]: "noRuby",
2944
+ ["wordSpacing" /* wordSpacing */]: "wordSpacing",
2945
+ ["zoom" /* zoom */]: "zoom"
2946
+ };
2660
2947
  var SvgDocumentScanner = (props) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", fill: "inherit", ...props, children: /* @__PURE__ */ jsx("path", { d: "M80-720v-200h200v80H160v120H80Zm720 0v-120H680v-80h200v200h-80ZM80-40v-200h80v120h120v80H80Zm600 0v-80h120v-120h80v200H680ZM280-240h400v-480H280v480Zm0 80q-33 0-56.5-23.5T200-240v-480q0-33 23.5-56.5T280-800h400q33 0 56.5 23.5T760-720v480q0 33-23.5 56.5T680-160H280Zm80-400h240v-80H360v80Zm0 120h240v-80H360v80Zm0 120h240v-80H360v80Zm-80 80v-480 480Z" }) });
2661
2948
  var document_scanner_default = SvgDocumentScanner;
2662
2949
  var SvgArticle = (props) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", fill: "inherit", ...props, children: /* @__PURE__ */ jsx("path", { d: "M280-280h280v-80H280v80Zm0-160h400v-80H280v80Zm0-160h400v-80H280v80Zm-80 480q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm0-560v560-560Z" }) });
@@ -2665,9 +2952,7 @@ var SvgMenuBook = (props) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.
2665
2952
  var menu_book_default = SvgMenuBook;
2666
2953
  var StatefulColumns = () => {
2667
2954
  const { t } = useI18n();
2668
- const scroll = useAppSelector((state) => state.settings.scroll);
2669
- const isFXL = useAppSelector((state) => state.publication.isFXL);
2670
- const isScroll = scroll && !isFXL;
2955
+ const isScroll = useIsScroll();
2671
2956
  const columnCount = useAppSelector((state) => state.settings.columnCount) || "auto";
2672
2957
  const [effectiveValue, setEffectiveValue] = useState(columnCount);
2673
2958
  const fontSize = useAppSelector((state) => state.settings.fontSize);
@@ -2686,6 +2971,7 @@ var StatefulColumns = () => {
2686
2971
  }, [fontSize, fontFamily, wordSpacing, letterSpacing, publisherStyles]);
2687
2972
  const dispatch = useAppDispatch();
2688
2973
  const { submitPreferences, getSetting } = useEpubNavigator();
2974
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["columns" /* columns */];
2689
2975
  const items = useMemo(() => [
2690
2976
  {
2691
2977
  id: "auto",
@@ -2716,12 +3002,12 @@ var StatefulColumns = () => {
2716
3002
  }, []);
2717
3003
  const updatePreference = useCallback(async (value) => {
2718
3004
  const colCount = value === "auto" ? null : Number(value);
2719
- await submitPreferences({ columnCount: colCount });
2720
- updateEffectiveValue(value, getSetting("columnCount"));
3005
+ await submitPreferences({ [prefKey]: colCount });
3006
+ updateEffectiveValue(value, getSetting(prefKey));
2721
3007
  dispatch(setColumnCount(value));
2722
- }, [submitPreferences, getSetting, updateEffectiveValue, dispatch]);
3008
+ }, [prefKey, submitPreferences, getSetting, updateEffectiveValue, dispatch]);
2723
3009
  const debouncedUpdate = useCallback(() => {
2724
- const update = () => updateEffectiveValue(columnCount, getSetting("columnCount"));
3010
+ const update = () => updateEffectiveValue(columnCount, getSetting(prefKey));
2725
3011
  debounce(update, 50)();
2726
3012
  }, [columnCount, layoutSettings, getSetting, updateEffectiveValue]);
2727
3013
  useEffect(() => {
@@ -2766,7 +3052,7 @@ var StatefulDropdown = ({
2766
3052
  className: thorium_web_reader_settings_default.label,
2767
3053
  ...compounds?.label || {}
2768
3054
  },
2769
- ...React24.isValidElement(compounds?.button) ? { button: compounds.button } : {
3055
+ ...React22.isValidElement(compounds?.button) ? { button: compounds.button } : {
2770
3056
  button: {
2771
3057
  className: thorium_web_reader_settings_default.dropdownButton,
2772
3058
  ...compounds?.button || {}
@@ -2777,7 +3063,7 @@ var StatefulDropdown = ({
2777
3063
  placement: "bottom",
2778
3064
  ...compounds?.popover || {}
2779
3065
  },
2780
- ...React24.isValidElement(compounds?.listbox) ? { listbox: compounds.listbox } : {
3066
+ ...React22.isValidElement(compounds?.listbox) ? { listbox: compounds.listbox } : {
2781
3067
  listbox: {
2782
3068
  className: thorium_web_reader_settings_default.dropdownListbox,
2783
3069
  ...compounds?.listbox || {}
@@ -2791,6 +3077,27 @@ var StatefulDropdown = ({
2791
3077
  }
2792
3078
  );
2793
3079
  };
3080
+
3081
+ // src/components/Settings/hooks/useReaderSetting.ts
3082
+ function useReaderSetting(key) {
3083
+ return useAppSelector((state) => {
3084
+ const isWebPub = state.reader.profile === "webPub";
3085
+ if (key === "zoom") {
3086
+ if (isWebPub) {
3087
+ const val3 = state.webPubSettings.zoom;
3088
+ return val3 !== void 0 ? val3 : initialWebPubSettingsState.zoom;
3089
+ }
3090
+ const val2 = state.settings.fontSize;
3091
+ return val2 !== void 0 ? val2 : initialSettingsState.fontSize;
3092
+ }
3093
+ if (isWebPub) {
3094
+ const val2 = state.webPubSettings[key];
3095
+ return val2 !== void 0 ? val2 : initialWebPubSettingsState[key];
3096
+ }
3097
+ const val = state.settings[key];
3098
+ return val !== void 0 ? val : initialSettingsState[key];
3099
+ });
3100
+ }
2794
3101
  var StatefulFontFamily = ({ standalone = true }) => {
2795
3102
  const { getFontMetadata, getFontsList } = usePreferences();
2796
3103
  const { t } = useI18n();
@@ -2810,10 +3117,8 @@ var StatefulFontFamily = ({ standalone = true }) => {
2810
3117
  const isWebPub = profile === "webPub";
2811
3118
  const fontLanguage = useAppSelector((state) => state.publication.fontLanguage) || "default";
2812
3119
  const fontPreferences = getFontsList({ language: fontLanguage });
2813
- const fontFamily = useAppSelector((state) => {
2814
- const fontSettings = isWebPub ? state.webPubSettings.fontFamily : state.settings.fontFamily;
2815
- return fontSettings[fontLanguage] ?? "publisher";
2816
- });
3120
+ const fontFamilySettings = useReaderSetting("fontFamily");
3121
+ const fontFamily = fontFamilySettings[fontLanguage] ?? "publisher";
2817
3122
  const availableFontIds = /* @__PURE__ */ new Set([
2818
3123
  "publisher",
2819
3124
  ...Object.keys(fontPreferences)
@@ -2836,12 +3141,13 @@ var StatefulFontFamily = ({ standalone = true }) => {
2836
3141
  ]);
2837
3142
  const dispatch = useAppDispatch();
2838
3143
  const { getSetting, submitPreferences } = useNavigator().visual;
3144
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["fontFamily" /* fontFamily */];
2839
3145
  const updatePreference = useCallback(async (key) => {
2840
3146
  if (!key || key === fontFamily) return;
2841
3147
  const selectedOption = fontFamilyOptions.current.find((option) => option.id === key);
2842
3148
  if (selectedOption) {
2843
- await submitPreferences({ fontFamily: selectedOption.value });
2844
- const currentSetting = getSetting("fontFamily");
3149
+ await submitPreferences({ [prefKey]: selectedOption.value });
3150
+ const currentSetting = getSetting(prefKey);
2845
3151
  if (currentSetting === null) {
2846
3152
  if (isWebPub) {
2847
3153
  dispatch(setWebPubFontFamily({ key: fontLanguage, value: "publisher" }));
@@ -2863,7 +3169,7 @@ var StatefulFontFamily = ({ standalone = true }) => {
2863
3169
  }
2864
3170
  }
2865
3171
  }
2866
- }, [isWebPub, fontLanguage, fontFamily, submitPreferences, getSetting, fontPreferences, getFontMetadata, dispatch]);
3172
+ }, [prefKey, isWebPub, fontLanguage, fontFamily, submitPreferences, getSetting, fontPreferences, getFontMetadata, dispatch]);
2867
3173
  return /* @__PURE__ */ jsx(
2868
3174
  StatefulDropdown,
2869
3175
  {
@@ -2902,9 +3208,10 @@ var UnstableStatefulFontWeight = ({ standalone = true }) => {
2902
3208
  const { t } = useI18n();
2903
3209
  const profile = useAppSelector((state) => state.reader.profile);
2904
3210
  const isWebPub = profile === "webPub";
2905
- const fontWeight = useAppSelector((state) => isWebPub ? state.webPubSettings.fontWeight : state.settings.fontWeight) ?? 400;
3211
+ const fontWeight = useReaderSetting("fontWeight");
2906
3212
  const dispatch = useAppDispatch();
2907
3213
  const { getSetting, submitPreferences } = useNavigator().visual;
3214
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["fontWeight" /* fontWeight */];
2908
3215
  const items = [
2909
3216
  {
2910
3217
  id: "default",
@@ -2929,14 +3236,14 @@ var UnstableStatefulFontWeight = ({ standalone = true }) => {
2929
3236
  }, [fontWeight]);
2930
3237
  const updatePreference = useCallback(async (value) => {
2931
3238
  const fontWeightValue = value === "default" ? 400 : 700;
2932
- await submitPreferences({ fontWeight: fontWeightValue });
2933
- const effectiveSetting = getSetting("fontWeight");
3239
+ await submitPreferences({ [prefKey]: fontWeightValue });
3240
+ const effectiveSetting = getSetting(prefKey);
2934
3241
  if (isWebPub) {
2935
3242
  dispatch(setWebPubFontWeight(effectiveSetting));
2936
3243
  } else {
2937
3244
  dispatch(setFontWeight(effectiveSetting));
2938
3245
  }
2939
- }, [isWebPub, submitPreferences, getSetting, dispatch]);
3246
+ }, [prefKey, isWebPub, submitPreferences, getSetting, dispatch]);
2940
3247
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
2941
3248
  StatefulRadioGroup,
2942
3249
  {
@@ -2980,19 +3287,20 @@ var StatefulHyphens = ({ standalone = true }) => {
2980
3287
  const { t } = useI18n();
2981
3288
  const profile = useAppSelector((state) => state.reader.profile);
2982
3289
  const isWebPub = profile === "webPub";
2983
- const hyphens = useAppSelector((state) => isWebPub ? state.webPubSettings.hyphens : state.settings.hyphens) ?? false;
2984
- const textAlign = useAppSelector((state) => isWebPub ? state.webPubSettings.textAlign : state.settings.textAlign) ?? "publisher" /* publisher */;
3290
+ const hyphens = useReaderSetting("hyphens");
3291
+ const textAlign = useReaderSetting("textAlign");
2985
3292
  const dispatch = useAppDispatch();
2986
3293
  const { getSetting, submitPreferences } = useNavigator().visual;
3294
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["hyphens" /* hyphens */];
2987
3295
  const updatePreference = useCallback(async (value) => {
2988
- await submitPreferences({ hyphens: value });
2989
- const effectiveSetting = getSetting("hyphens");
3296
+ await submitPreferences({ [prefKey]: value });
3297
+ const effectiveSetting = getSetting(prefKey);
2990
3298
  if (isWebPub) {
2991
3299
  dispatch(setWebPubHyphens(effectiveSetting));
2992
3300
  } else {
2993
3301
  dispatch(setHyphens(effectiveSetting));
2994
3302
  }
2995
- }, [isWebPub, submitPreferences, getSetting, dispatch]);
3303
+ }, [prefKey, isWebPub, submitPreferences, getSetting, dispatch]);
2996
3304
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
2997
3305
  StatefulSwitch,
2998
3306
  {
@@ -3011,9 +3319,7 @@ var SvgDocs = (props) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/
3011
3319
  var docs_default = SvgDocs;
3012
3320
  var StatefulLayout = () => {
3013
3321
  const { t } = useI18n();
3014
- const scroll = useAppSelector((state) => state.settings.scroll);
3015
- const isFXL = useAppSelector((state) => state.publication.isFXL);
3016
- const isScroll = scroll && !isFXL;
3322
+ const isScroll = useIsScroll();
3017
3323
  const dispatch = useAppDispatch();
3018
3324
  const { getSetting, submitPreferences } = useEpubNavigator();
3019
3325
  const items = [
@@ -3030,11 +3336,12 @@ var StatefulLayout = () => {
3030
3336
  value: "scroll_option" /* scroll */
3031
3337
  }
3032
3338
  ];
3339
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["layout" /* layout */];
3033
3340
  const updatePreference = useCallback(async (value) => {
3034
3341
  const derivedValue = value === "scroll_option" /* scroll */;
3035
- await submitPreferences({ scroll: derivedValue });
3036
- dispatch(setScroll(getSetting("scroll")));
3037
- }, [submitPreferences, getSetting, dispatch]);
3342
+ await submitPreferences({ [prefKey]: derivedValue });
3343
+ dispatch(setScroll(getSetting(prefKey)));
3344
+ }, [prefKey, submitPreferences, getSetting, dispatch]);
3038
3345
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
3039
3346
  StatefulRadioGroup,
3040
3347
  {
@@ -3177,32 +3484,25 @@ var StatefulSlider = ({
3177
3484
  ) });
3178
3485
  };
3179
3486
  function useSettingsComponentStatus(options) {
3180
- const { settingsKey, publicationType, componentType, additionalCondition = true } = options;
3487
+ const { settingsKey, publicationType, additionalCondition = true } = options;
3181
3488
  const { spacingSettingsComponentsMap, textSettingsComponentsMap, settingsComponentsMap } = usePlugins();
3182
- const { preferences } = usePreferences();
3489
+ const { reflowSettingsKeys, fxlSettingsKeys, webPubSettingsKeys, mainTextSettingsKeys, subPanelTextSettingsKeys, mainSpacingSettingsKeys, subPanelSpacingSettingsKeys } = useFilteredPreferenceKeys();
3183
3490
  return useMemo(() => {
3184
3491
  const isComponentRegistered = !!(settingsComponentsMap?.[settingsKey] || spacingSettingsComponentsMap?.[settingsKey] || textSettingsComponentsMap?.[settingsKey]);
3185
3492
  let isInOrder = false;
3186
3493
  switch (publicationType) {
3187
3494
  case "reflow":
3188
- isInOrder = preferences.settings?.reflowOrder?.includes(settingsKey) || false;
3495
+ isInOrder = reflowSettingsKeys.includes(settingsKey) || false;
3189
3496
  break;
3190
3497
  case "fxl":
3191
- isInOrder = preferences.settings?.fxlOrder?.includes(settingsKey) || false;
3498
+ isInOrder = fxlSettingsKeys.includes(settingsKey) || false;
3192
3499
  break;
3193
3500
  case "webpub":
3194
- isInOrder = preferences.settings?.webPubOrder?.includes(settingsKey) || false;
3501
+ isInOrder = webPubSettingsKeys.includes(settingsKey) || false;
3195
3502
  break;
3196
3503
  }
3197
- let isInMainPanel = false;
3198
- let isInSubPanel = false;
3199
- if (componentType === "text") {
3200
- isInMainPanel = preferences.settings?.text?.main?.includes(settingsKey) || false;
3201
- isInSubPanel = preferences.settings?.text?.subPanel?.includes(settingsKey) || false;
3202
- } else if (componentType === "spacing") {
3203
- isInMainPanel = preferences.settings?.spacing?.main?.includes(settingsKey) || false;
3204
- isInSubPanel = preferences.settings?.spacing?.subPanel?.includes(settingsKey) || false;
3205
- }
3504
+ const isInMainPanel = mainTextSettingsKeys.includes(settingsKey) || mainSpacingSettingsKeys.includes(settingsKey) || false;
3505
+ const isInSubPanel = subPanelTextSettingsKeys.includes(settingsKey) || subPanelSpacingSettingsKeys.includes(settingsKey) || false;
3206
3506
  const isDisplayed = isInOrder || (isInMainPanel || isInSubPanel) && additionalCondition;
3207
3507
  const isComponentUsed = isComponentRegistered && isDisplayed;
3208
3508
  return {
@@ -3215,29 +3515,25 @@ function useSettingsComponentStatus(options) {
3215
3515
  }, [
3216
3516
  settingsKey,
3217
3517
  publicationType,
3218
- componentType,
3219
3518
  additionalCondition,
3220
- preferences,
3519
+ reflowSettingsKeys,
3520
+ fxlSettingsKeys,
3521
+ webPubSettingsKeys,
3522
+ mainTextSettingsKeys,
3523
+ subPanelTextSettingsKeys,
3524
+ mainSpacingSettingsKeys,
3525
+ subPanelSpacingSettingsKeys,
3221
3526
  spacingSettingsComponentsMap,
3222
3527
  textSettingsComponentsMap,
3223
3528
  settingsComponentsMap
3224
3529
  ]);
3225
3530
  }
3226
-
3227
- // src/components/Settings/Spacing/hooks/useSpacingPresets.ts
3228
3531
  var useSpacingPresets = () => {
3229
3532
  const readerProfile = useAppSelector((state) => state.reader.profile);
3230
3533
  const isWebPub = readerProfile === "webPub";
3231
3534
  const isFXL = useAppSelector((state) => state.publication.isFXL);
3232
- const settings = useAppSelector(
3233
- (state) => isWebPub ? state.webPubSettings : state.settings
3234
- );
3235
- const spacing = settings?.spacing || {
3236
- preset: "publisher" /* publisher */,
3237
- custom: {},
3238
- baseline: {}
3239
- };
3240
- const { reflowSpacingPresetKeys, fxlSpacingPresetKeys, webPubSpacingPresetKeys } = usePreferenceKeys();
3535
+ const spacing = useReaderSetting("spacing");
3536
+ const { reflowSpacingPresetKeys, fxlSpacingPresetKeys, webPubSpacingPresetKeys } = useFilteredPreferenceKeys();
3241
3537
  const { preferences } = usePreferences();
3242
3538
  const dispatch = useAppDispatch();
3243
3539
  const spacingKeys = useMemo(() => {
@@ -3246,16 +3542,13 @@ var useSpacingPresets = () => {
3246
3542
  const { isComponentUsed: shouldApplyPresets } = useSettingsComponentStatus({
3247
3543
  settingsKey: "spacingPresets" /* spacingPresets */,
3248
3544
  publicationType: isWebPub ? "webpub" : isFXL ? "fxl" : "reflow",
3249
- componentType: "spacing",
3250
3545
  additionalCondition: spacingKeys.length > 0
3251
3546
  });
3252
- const {
3253
- letterSpacing,
3254
- lineHeight,
3255
- paragraphIndent,
3256
- paragraphSpacing,
3257
- wordSpacing
3258
- } = settings || {};
3547
+ const letterSpacing = useReaderSetting("letterSpacing");
3548
+ const lineHeight = useReaderSetting("lineHeight");
3549
+ const paragraphIndent = useReaderSetting("paragraphIndent");
3550
+ const paragraphSpacing = useReaderSetting("paragraphSpacing");
3551
+ const wordSpacing = useReaderSetting("wordSpacing");
3259
3552
  const getBaseReduxValue = (key) => {
3260
3553
  switch (key) {
3261
3554
  case "letterSpacing" /* letterSpacing */:
@@ -3450,24 +3743,6 @@ var useSpacingPresets = () => {
3450
3743
  setPublisherStyles: setPublisherStylesAction
3451
3744
  };
3452
3745
  };
3453
- var useEffectiveRange = (preferred, supportedRange, presets) => {
3454
- return useMemo(() => {
3455
- let range;
3456
- if (!supportedRange) {
3457
- range = preferred;
3458
- } else {
3459
- const prefMin = Math.min(...preferred);
3460
- const prefMax = Math.max(...preferred);
3461
- const supMin = Math.min(...supportedRange);
3462
- const supMax = Math.max(...supportedRange);
3463
- range = prefMin >= supMin && prefMax <= supMax ? preferred : supportedRange;
3464
- }
3465
- if (!presets) return { range };
3466
- const [min, max] = [Math.min(...range), Math.max(...range)];
3467
- const effectivePresets = presets.filter((p) => p >= min && p <= max);
3468
- return { range, presets: effectivePresets };
3469
- }, [preferred, supportedRange, presets]);
3470
- };
3471
3746
 
3472
3747
  // src/components/Settings/hooks/usePlaceholder.ts
3473
3748
  var usePlaceholder = (placeholder, range, format) => {
@@ -3506,6 +3781,24 @@ var usePlaceholder = (placeholder, range, format) => {
3506
3781
  }
3507
3782
  return void 0;
3508
3783
  };
3784
+ var useEffectiveRange = (preferred, supportedRange, presets) => {
3785
+ return useMemo(() => {
3786
+ let range;
3787
+ if (!supportedRange) {
3788
+ range = preferred;
3789
+ } else {
3790
+ const prefMin = Math.min(...preferred);
3791
+ const prefMax = Math.max(...preferred);
3792
+ const supMin = Math.min(...supportedRange);
3793
+ const supMax = Math.max(...supportedRange);
3794
+ range = prefMin >= supMin && prefMax <= supMax ? preferred : supportedRange;
3795
+ }
3796
+ if (!presets) return { range };
3797
+ const [min, max] = [Math.min(...range), Math.max(...range)];
3798
+ const effectivePresets = presets.filter((p) => p >= min && p <= max);
3799
+ return { range, presets: effectivePresets };
3800
+ }, [preferred, supportedRange, presets]);
3801
+ };
3509
3802
  var StatefulLetterSpacing = ({ standalone = true }) => {
3510
3803
  const { preferences } = usePreferences();
3511
3804
  const { t } = useI18n();
@@ -3521,12 +3814,13 @@ var StatefulLetterSpacing = ({ standalone = true }) => {
3521
3814
  const placeholderText = usePlaceholder(letterSpacingRangeConfig.placeholder, letterSpacingRangeConfig.range, "percent");
3522
3815
  const { getEffectiveSpacingValue, setLetterSpacing: setLetterSpacing2, canBeReset } = useSpacingPresets();
3523
3816
  const letterSpacing = getEffectiveSpacingValue("letterSpacing" /* letterSpacing */);
3817
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["letterSpacing" /* letterSpacing */];
3524
3818
  const updatePreference = useCallback(async (value) => {
3525
3819
  await submitPreferences({
3526
- letterSpacing: Array.isArray(value) ? value[0] : value
3820
+ [prefKey]: Array.isArray(value) ? value[0] : value
3527
3821
  });
3528
- setLetterSpacing2(getSetting("letterSpacing"));
3529
- }, [submitPreferences, getSetting, setLetterSpacing2]);
3822
+ setLetterSpacing2(getSetting(prefKey));
3823
+ }, [prefKey, submitPreferences, getSetting, setLetterSpacing2]);
3530
3824
  return /* @__PURE__ */ jsx(Fragment, { children: letterSpacingRangeConfig.variant === "numberField" /* numberField */ ? /* @__PURE__ */ jsx(
3531
3825
  StatefulNumberField,
3532
3826
  {
@@ -3586,8 +3880,9 @@ var StatefulLineHeight = ({ standalone = true }) => {
3586
3880
  const { preferences } = usePreferences();
3587
3881
  const profile = useAppSelector((state) => state.reader.profile);
3588
3882
  const isWebPub = profile === "webPub";
3589
- const publisherStyles = useAppSelector((state) => isWebPub ? state.webPubSettings.publisherStyles : state.settings.publisherStyles) ?? true;
3883
+ const publisherStyles = useReaderSetting("publisherStyles");
3590
3884
  const { getSetting, submitPreferences, preferencesEditor } = useNavigator().visual;
3885
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["lineHeight" /* lineHeight */];
3591
3886
  const { getEffectiveSpacingValue, setLineHeight: setLineHeight2 } = useSpacingPresets();
3592
3887
  const lineHeight = getEffectiveSpacingValue("lineHeight" /* lineHeight */);
3593
3888
  const lineHeightOptions = useLineHeight();
@@ -3637,12 +3932,12 @@ var StatefulLineHeight = ({ standalone = true }) => {
3637
3932
  const updatePreference = useCallback(async (value) => {
3638
3933
  const computedValue = value === "publisher" /* publisher */ ? null : lineHeightOptions[value];
3639
3934
  await submitPreferences({
3640
- lineHeight: computedValue
3935
+ [prefKey]: computedValue
3641
3936
  });
3642
- const currentLineHeight = getSetting("lineHeight");
3643
- const currentDisplayLineHeightOption = Object.entries(lineHeightOptions).find(([key, value2]) => value2 === currentLineHeight)?.[0];
3937
+ const currentLineHeight = getSetting(prefKey);
3938
+ const currentDisplayLineHeightOption = Object.entries(lineHeightOptions).find(([_key, value2]) => value2 === currentLineHeight)?.[0];
3644
3939
  setLineHeight2(currentDisplayLineHeightOption);
3645
- }, [submitPreferences, getSetting, setLineHeight2, lineHeightOptions]);
3940
+ }, [prefKey, submitPreferences, getSetting, setLineHeight2, lineHeightOptions]);
3646
3941
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
3647
3942
  StatefulRadioGroup,
3648
3943
  {
@@ -3670,12 +3965,13 @@ var StatefulParagraphIndent = ({ standalone = true }) => {
3670
3965
  const placeholderText = usePlaceholder(paragraphIndentRangeConfig.placeholder, paragraphIndentRangeConfig.range, "multiplier");
3671
3966
  const { getEffectiveSpacingValue, setParagraphIndent: setParagraphIndent2, canBeReset } = useSpacingPresets();
3672
3967
  const paragraphIndent = getEffectiveSpacingValue("paragraphIndent" /* paragraphIndent */);
3968
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["paragraphIndent" /* paragraphIndent */];
3673
3969
  const updatePreference = useCallback(async (value) => {
3674
3970
  await submitPreferences({
3675
- paragraphIndent: Array.isArray(value) ? value[0] : value
3971
+ [prefKey]: Array.isArray(value) ? value[0] : value
3676
3972
  });
3677
- setParagraphIndent2(getSetting("paragraphIndent"));
3678
- }, [submitPreferences, getSetting, setParagraphIndent2]);
3973
+ setParagraphIndent2(getSetting(prefKey));
3974
+ }, [prefKey, submitPreferences, getSetting, setParagraphIndent2]);
3679
3975
  return /* @__PURE__ */ jsx(Fragment, { children: paragraphIndentRangeConfig.variant === "numberField" /* numberField */ ? /* @__PURE__ */ jsx(
3680
3976
  StatefulNumberField,
3681
3977
  {
@@ -3736,12 +4032,13 @@ var StatefulParagraphSpacing = ({ standalone = true }) => {
3736
4032
  const placeholderText = usePlaceholder(paragraphSpacingRangeConfig.placeholder, paragraphSpacingRangeConfig.range, "multiplier");
3737
4033
  const { getEffectiveSpacingValue, setParagraphSpacing: setParagraphSpacing2, canBeReset } = useSpacingPresets();
3738
4034
  const paragraphSpacing = getEffectiveSpacingValue("paragraphSpacing" /* paragraphSpacing */);
4035
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["paragraphSpacing" /* paragraphSpacing */];
3739
4036
  const updatePreference = useCallback(async (value) => {
3740
4037
  await submitPreferences({
3741
- paragraphSpacing: Array.isArray(value) ? value[0] : value
4038
+ [prefKey]: Array.isArray(value) ? value[0] : value
3742
4039
  });
3743
- setParagraphSpacing2(getSetting("paragraphSpacing"));
3744
- }, [submitPreferences, getSetting, setParagraphSpacing2]);
4040
+ setParagraphSpacing2(getSetting(prefKey));
4041
+ }, [prefKey, submitPreferences, getSetting, setParagraphSpacing2]);
3745
4042
  return /* @__PURE__ */ jsx(Fragment, { children: paragraphSpacingRangeConfig.variant === "numberField" /* numberField */ ? /* @__PURE__ */ jsx(
3746
4043
  StatefulNumberField,
3747
4044
  {
@@ -3789,8 +4086,28 @@ var StatefulParagraphSpacing = ({ standalone = true }) => {
3789
4086
  };
3790
4087
  var StatefulPublisherStyles = ({ standalone = true }) => {
3791
4088
  const { t } = useI18n();
3792
- const publisherStyles = useAppSelector((state) => state.settings.publisherStyles);
4089
+ const publisherStyles = useReaderSetting("publisherStyles");
3793
4090
  const { getEffectiveSpacingValue, setPublisherStyles: setPublisherStyles2 } = useSpacingPresets();
4091
+ const { isComponentUsed: isLineHeightUsed } = useSettingsComponentStatus({
4092
+ settingsKey: "lineHeight" /* lineHeight */,
4093
+ publicationType: "reflow"
4094
+ });
4095
+ const { isComponentUsed: isParagraphIndentUsed } = useSettingsComponentStatus({
4096
+ settingsKey: "paragraphIndent" /* paragraphIndent */,
4097
+ publicationType: "reflow"
4098
+ });
4099
+ const { isComponentUsed: isParagraphSpacingUsed } = useSettingsComponentStatus({
4100
+ settingsKey: "paragraphSpacing" /* paragraphSpacing */,
4101
+ publicationType: "reflow"
4102
+ });
4103
+ const { isComponentUsed: isLetterSpacingUsed } = useSettingsComponentStatus({
4104
+ settingsKey: "letterSpacing" /* letterSpacing */,
4105
+ publicationType: "reflow"
4106
+ });
4107
+ const { isComponentUsed: isWordSpacingUsed } = useSettingsComponentStatus({
4108
+ settingsKey: "wordSpacing" /* wordSpacing */,
4109
+ publicationType: "reflow"
4110
+ });
3794
4111
  const lineHeight = getEffectiveSpacingValue("lineHeight" /* lineHeight */);
3795
4112
  const paragraphIndent = getEffectiveSpacingValue("paragraphIndent" /* paragraphIndent */);
3796
4113
  const paragraphSpacing = getEffectiveSpacingValue("paragraphSpacing" /* paragraphSpacing */);
@@ -3798,23 +4115,49 @@ var StatefulPublisherStyles = ({ standalone = true }) => {
3798
4115
  const wordSpacing = getEffectiveSpacingValue("wordSpacing" /* wordSpacing */);
3799
4116
  const lineHeightOptions = useLineHeight();
3800
4117
  const { submitPreferences } = useNavigator().visual;
4118
+ const lineHeightPrefKey = SETTINGS_KEY_TO_PREFERENCE["lineHeight" /* lineHeight */];
4119
+ const paragraphIndentPrefKey = SETTINGS_KEY_TO_PREFERENCE["paragraphIndent" /* paragraphIndent */];
4120
+ const paragraphSpacingPrefKey = SETTINGS_KEY_TO_PREFERENCE["paragraphSpacing" /* paragraphSpacing */];
4121
+ const letterSpacingPrefKey = SETTINGS_KEY_TO_PREFERENCE["letterSpacing" /* letterSpacing */];
4122
+ const wordSpacingPrefKey = SETTINGS_KEY_TO_PREFERENCE["wordSpacing" /* wordSpacing */];
3801
4123
  const updatePreference = useCallback(async (isSelected) => {
3802
- const values = isSelected ? {
3803
- lineHeight: null,
3804
- paragraphIndent: null,
3805
- paragraphSpacing: null,
3806
- letterSpacing: null,
3807
- wordSpacing: null
3808
- } : {
3809
- lineHeight: lineHeight === "publisher" /* publisher */ ? null : lineHeightOptions[lineHeight],
3810
- paragraphIndent,
3811
- paragraphSpacing,
3812
- letterSpacing,
3813
- wordSpacing
3814
- };
4124
+ const values = {};
4125
+ if (isSelected) {
4126
+ if (isLineHeightUsed) {
4127
+ values[lineHeightPrefKey] = null;
4128
+ }
4129
+ if (isParagraphIndentUsed) {
4130
+ values[paragraphIndentPrefKey] = null;
4131
+ }
4132
+ if (isParagraphSpacingUsed) {
4133
+ values[paragraphSpacingPrefKey] = null;
4134
+ }
4135
+ if (isLetterSpacingUsed) {
4136
+ values[letterSpacingPrefKey] = null;
4137
+ }
4138
+ if (isWordSpacingUsed) {
4139
+ values[wordSpacingPrefKey] = null;
4140
+ }
4141
+ } else {
4142
+ if (isLineHeightUsed) {
4143
+ values[lineHeightPrefKey] = lineHeight === "publisher" /* publisher */ ? null : lineHeightOptions[lineHeight];
4144
+ }
4145
+ if (isParagraphIndentUsed) {
4146
+ values[paragraphIndentPrefKey] = paragraphIndent;
4147
+ }
4148
+ if (isParagraphSpacingUsed) {
4149
+ values[paragraphSpacingPrefKey] = paragraphSpacing;
4150
+ }
4151
+ if (isLetterSpacingUsed) {
4152
+ values[letterSpacingPrefKey] = letterSpacing;
4153
+ }
4154
+ if (isWordSpacingUsed) {
4155
+ values[wordSpacingPrefKey] = wordSpacing;
4156
+ }
4157
+ }
3815
4158
  await submitPreferences(values);
3816
4159
  setPublisherStyles2(isSelected ? true : false);
3817
- }, [submitPreferences, setPublisherStyles2, lineHeight, paragraphIndent, paragraphSpacing, letterSpacing, wordSpacing, lineHeightOptions]);
4160
+ }, [submitPreferences, setPublisherStyles2, lineHeight, paragraphIndent, paragraphSpacing, letterSpacing, wordSpacing, lineHeightOptions, lineHeightPrefKey, paragraphIndentPrefKey, paragraphSpacingPrefKey, letterSpacingPrefKey, wordSpacingPrefKey, isLineHeightUsed, isParagraphIndentUsed, isParagraphSpacingUsed, isLetterSpacingUsed, isWordSpacingUsed]);
3818
4161
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
3819
4162
  StatefulSwitch,
3820
4163
  {
@@ -3851,15 +4194,41 @@ var iconMap = {
3851
4194
  };
3852
4195
  var StatefulSpacingPresets = ({ standalone }) => {
3853
4196
  const { t } = useI18n();
3854
- const { reflowSpacingPresetKeys, fxlSpacingPresetKeys, webPubSpacingPresetKeys, subPanelSpacingSettingsKeys } = usePreferenceKeys();
4197
+ const { reflowSpacingPresetKeys, fxlSpacingPresetKeys, webPubSpacingPresetKeys, subPanelSpacingSettingsKeys } = useFilteredPreferenceKeys();
3855
4198
  const profile = useAppSelector((state) => state.reader.profile);
3856
4199
  const isWebPub = profile === "webPub";
3857
- const spacing = useAppSelector((state) => isWebPub ? state.webPubSettings.spacing : state.settings.spacing);
4200
+ const spacing = useReaderSetting("spacing");
3858
4201
  const isFXL = useAppSelector((state) => state.publication.isFXL);
3859
4202
  const dispatch = useAppDispatch();
3860
4203
  const { submitPreferences } = useNavigator().visual;
4204
+ const letterSpacingPrefKey = SETTINGS_KEY_TO_PREFERENCE["letterSpacing" /* letterSpacing */];
4205
+ const lineHeightPrefKey = SETTINGS_KEY_TO_PREFERENCE["lineHeight" /* lineHeight */];
4206
+ const paragraphIndentPrefKey = SETTINGS_KEY_TO_PREFERENCE["paragraphIndent" /* paragraphIndent */];
4207
+ const paragraphSpacingPrefKey = SETTINGS_KEY_TO_PREFERENCE["paragraphSpacing" /* paragraphSpacing */];
4208
+ const wordSpacingPrefKey = SETTINGS_KEY_TO_PREFERENCE["wordSpacing" /* wordSpacing */];
3861
4209
  const lineHeightOptions = useLineHeight();
3862
4210
  const { getPresetValues } = useSpacingPresets();
4211
+ const publicationType = isWebPub ? "webpub" : isFXL ? "fxl" : "reflow";
4212
+ const { isComponentUsed: isLetterSpacingUsed } = useSettingsComponentStatus({
4213
+ settingsKey: "letterSpacing" /* letterSpacing */,
4214
+ publicationType
4215
+ });
4216
+ const { isComponentUsed: isLineHeightUsed } = useSettingsComponentStatus({
4217
+ settingsKey: "lineHeight" /* lineHeight */,
4218
+ publicationType
4219
+ });
4220
+ const { isComponentUsed: isParagraphIndentUsed } = useSettingsComponentStatus({
4221
+ settingsKey: "paragraphIndent" /* paragraphIndent */,
4222
+ publicationType
4223
+ });
4224
+ const { isComponentUsed: isParagraphSpacingUsed } = useSettingsComponentStatus({
4225
+ settingsKey: "paragraphSpacing" /* paragraphSpacing */,
4226
+ publicationType
4227
+ });
4228
+ const { isComponentUsed: isWordSpacingUsed } = useSettingsComponentStatus({
4229
+ settingsKey: "wordSpacing" /* wordSpacing */,
4230
+ publicationType
4231
+ });
3863
4232
  const updatePreference = useCallback(async (value) => {
3864
4233
  const spacingKey = value;
3865
4234
  const presetValues = getPresetValues(spacingKey);
@@ -3872,13 +4241,22 @@ var StatefulSpacingPresets = ({ standalone }) => {
3872
4241
  };
3873
4242
  const lineHeightValue = reduxValues["lineHeight" /* lineHeight */];
3874
4243
  const lineHeightValueNumber = lineHeightValue && lineHeightValue !== "publisher" /* publisher */ ? lineHeightOptions[lineHeightValue] : null;
3875
- const preferencesToSubmit = {
3876
- ["letterSpacing" /* letterSpacing */]: reduxValues["letterSpacing" /* letterSpacing */],
3877
- ["lineHeight" /* lineHeight */]: lineHeightValueNumber,
3878
- ["paragraphIndent" /* paragraphIndent */]: reduxValues["paragraphIndent" /* paragraphIndent */],
3879
- ["paragraphSpacing" /* paragraphSpacing */]: reduxValues["paragraphSpacing" /* paragraphSpacing */],
3880
- ["wordSpacing" /* wordSpacing */]: reduxValues["wordSpacing" /* wordSpacing */]
3881
- };
4244
+ const preferencesToSubmit = {};
4245
+ if (isLetterSpacingUsed) {
4246
+ preferencesToSubmit[letterSpacingPrefKey] = reduxValues["letterSpacing" /* letterSpacing */];
4247
+ }
4248
+ if (isLineHeightUsed) {
4249
+ preferencesToSubmit[lineHeightPrefKey] = lineHeightValueNumber;
4250
+ }
4251
+ if (isParagraphIndentUsed) {
4252
+ preferencesToSubmit[paragraphIndentPrefKey] = reduxValues["paragraphIndent" /* paragraphIndent */];
4253
+ }
4254
+ if (isParagraphSpacingUsed) {
4255
+ preferencesToSubmit[paragraphSpacingPrefKey] = reduxValues["paragraphSpacing" /* paragraphSpacing */];
4256
+ }
4257
+ if (isWordSpacingUsed) {
4258
+ preferencesToSubmit[wordSpacingPrefKey] = reduxValues["wordSpacing" /* wordSpacing */];
4259
+ }
3882
4260
  await submitPreferences(preferencesToSubmit);
3883
4261
  if (isWebPub) {
3884
4262
  dispatch(setWebPubSpacingPreset({
@@ -3891,7 +4269,7 @@ var StatefulSpacingPresets = ({ standalone }) => {
3891
4269
  values: reduxValues
3892
4270
  }));
3893
4271
  }
3894
- }, [isWebPub, dispatch, submitPreferences, getPresetValues, lineHeightOptions]);
4272
+ }, [isWebPub, dispatch, submitPreferences, getPresetValues, lineHeightOptions, letterSpacingPrefKey, lineHeightPrefKey, paragraphIndentPrefKey, paragraphSpacingPrefKey, wordSpacingPrefKey, isLetterSpacingUsed, isLineHeightUsed, isParagraphIndentUsed, isParagraphSpacingUsed, isWordSpacingUsed]);
3895
4273
  const spacingKeys = useMemo(() => {
3896
4274
  const baseKeys = isWebPub ? webPubSpacingPresetKeys : isFXL ? fxlSpacingPresetKeys : reflowSpacingPresetKeys;
3897
4275
  const subPanelKeys = subPanelSpacingSettingsKeys || [];
@@ -3936,9 +4314,17 @@ var StatefulTextAlign = ({ standalone = true }) => {
3936
4314
  const profile = useAppSelector((state) => state.reader.profile);
3937
4315
  const isWebPub = profile === "webPub";
3938
4316
  const isRTL = useAppSelector((state) => state.publication.isRTL);
3939
- const textAlign = useAppSelector((state) => isWebPub ? state.webPubSettings.textAlign : state.settings.textAlign) ?? "publisher" /* publisher */;
4317
+ const textAlign = useReaderSetting("textAlign");
4318
+ const hyphens = useReaderSetting("hyphens");
3940
4319
  const dispatch = useAppDispatch();
3941
4320
  const { getSetting, submitPreferences } = useNavigator().visual;
4321
+ const hyphensPrefKey = SETTINGS_KEY_TO_PREFERENCE["hyphens" /* hyphens */];
4322
+ const textAlignPrefKey = SETTINGS_KEY_TO_PREFERENCE["textAlign" /* textAlign */];
4323
+ const publicationType = isWebPub ? "webpub" : "reflow";
4324
+ const { isComponentUsed: isHyphensUsed } = useSettingsComponentStatus({
4325
+ settingsKey: "hyphens" /* hyphens */,
4326
+ publicationType
4327
+ });
3942
4328
  const items = [
3943
4329
  {
3944
4330
  id: "publisher" /* publisher */,
@@ -3960,60 +4346,133 @@ var StatefulTextAlign = ({ standalone = true }) => {
3960
4346
  }
3961
4347
  ];
3962
4348
  const updatePreference = useCallback(async (value) => {
3963
- const textAlign2 = value === "publisher" /* publisher */ ? null : value === "start" /* start */ ? TextAlignment.start : TextAlignment.justify;
3964
- const currentHyphens = getSetting("hyphens");
3965
- const hyphens = textAlign2 === null ? null : currentHyphens ?? textAlign2 === TextAlignment.justify;
3966
- await submitPreferences({
3967
- textAlign: textAlign2,
3968
- hyphens
3969
- });
3970
- const textAlignSetting = getSetting("textAlign");
4349
+ const oldTextAlign = textAlign;
4350
+ const navigatorTextAlign = value === "publisher" /* publisher */ ? null : value === "start" /* start */ ? TextAlignment.start : TextAlignment.justify;
4351
+ const preferencesToSubmit = {
4352
+ [textAlignPrefKey]: navigatorTextAlign
4353
+ };
4354
+ await submitPreferences(preferencesToSubmit);
4355
+ const textAlignSetting = getSetting(textAlignPrefKey);
3971
4356
  const textAlignValue = textAlignSetting === null ? "publisher" /* publisher */ : textAlignSetting;
3972
- const effectiveHyphens = getSetting("hyphens");
3973
4357
  if (isWebPub) {
3974
- dispatch(setWebPubTextAlign(textAlignValue));
3975
- dispatch(setWebPubHyphens(effectiveHyphens));
4358
+ dispatch(setWebPubTextAlign(textAlignValue));
4359
+ } else {
4360
+ dispatch(setTextAlign(textAlignValue));
4361
+ }
4362
+ if (isHyphensUsed) {
4363
+ if (navigatorTextAlign === null) {
4364
+ await submitPreferences({ [hyphensPrefKey]: null });
4365
+ } else {
4366
+ const wasPublisher = oldTextAlign === "publisher" /* publisher */;
4367
+ let hyphensToSubmit;
4368
+ if (wasPublisher && hyphens === null) {
4369
+ hyphensToSubmit = navigatorTextAlign === TextAlignment.justify;
4370
+ } else {
4371
+ hyphensToSubmit = hyphens;
4372
+ }
4373
+ await submitPreferences({ [hyphensPrefKey]: hyphensToSubmit });
4374
+ const effectiveHyphens = getSetting(hyphensPrefKey);
4375
+ if (isWebPub) {
4376
+ dispatch(setWebPubHyphens(effectiveHyphens));
4377
+ } else {
4378
+ dispatch(setHyphens(effectiveHyphens));
4379
+ }
4380
+ }
4381
+ }
4382
+ }, [hyphensPrefKey, textAlignPrefKey, isWebPub, getSetting, submitPreferences, dispatch, isHyphensUsed, hyphens, textAlign]);
4383
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
4384
+ StatefulRadioGroup,
4385
+ {
4386
+ standalone,
4387
+ label: t("reader.preferences.textAlign.title"),
4388
+ orientation: "horizontal",
4389
+ value: textAlign,
4390
+ onChange: async (val) => await updatePreference(val),
4391
+ items
4392
+ }
4393
+ ) });
4394
+ };
4395
+ var StatefulTextNormalize = ({ standalone = true }) => {
4396
+ const { t } = useI18n();
4397
+ const profile = useAppSelector((state) => state.reader.profile);
4398
+ const isWebPub = profile === "webPub";
4399
+ const textNormalization = useReaderSetting("textNormalization");
4400
+ const dispatch = useAppDispatch();
4401
+ const { getSetting, submitPreferences } = useNavigator().visual;
4402
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["textNormalize" /* textNormalize */];
4403
+ const updatePreference = useCallback(async (value) => {
4404
+ await submitPreferences({ [prefKey]: value });
4405
+ const effectiveSetting = getSetting(prefKey);
4406
+ if (isWebPub) {
4407
+ dispatch(setWebPubTextNormalization(effectiveSetting));
4408
+ } else {
4409
+ dispatch(setTextNormalization(effectiveSetting));
4410
+ }
4411
+ }, [prefKey, isWebPub, submitPreferences, getSetting, dispatch]);
4412
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
4413
+ StatefulSwitch,
4414
+ {
4415
+ standalone,
4416
+ heading: t("reader.preferences.textNormalization.title"),
4417
+ label: t("reader.preferences.textNormalization.label"),
4418
+ onChange: async (isSelected) => await updatePreference(isSelected),
4419
+ isSelected: textNormalization ?? false
4420
+ }
4421
+ ) });
4422
+ };
4423
+ var StatefulLigatures = ({ standalone = true }) => {
4424
+ const { t } = useI18n();
4425
+ const profile = useAppSelector((state) => state.reader.profile);
4426
+ const isWebPub = profile === "webPub";
4427
+ const ligatures = useReaderSetting("ligatures");
4428
+ const dispatch = useAppDispatch();
4429
+ const { getSetting, submitPreferences } = useNavigator().visual;
4430
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["ligatures" /* ligatures */];
4431
+ const updatePreference = useCallback(async (value) => {
4432
+ await submitPreferences({ [prefKey]: value });
4433
+ const effectiveSetting = getSetting(prefKey);
4434
+ if (isWebPub) {
4435
+ dispatch(setWebPubLigatures(effectiveSetting));
3976
4436
  } else {
3977
- dispatch(setTextAlign(textAlignValue));
3978
- dispatch(setHyphens(effectiveHyphens));
4437
+ dispatch(setLigatures(effectiveSetting));
3979
4438
  }
3980
- }, [isWebPub, getSetting, submitPreferences, dispatch]);
4439
+ }, [prefKey, isWebPub, submitPreferences, getSetting, dispatch]);
3981
4440
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
3982
- StatefulRadioGroup,
4441
+ StatefulSwitch,
3983
4442
  {
3984
4443
  standalone,
3985
- label: t("reader.preferences.textAlign.title"),
3986
- orientation: "horizontal",
3987
- value: textAlign,
3988
- onChange: async (val) => await updatePreference(val),
3989
- items
4444
+ heading: t("reader.preferences.ligatures.title"),
4445
+ label: t("reader.preferences.ligatures.label"),
4446
+ onChange: async (isSelected) => await updatePreference(isSelected),
4447
+ isSelected: ligatures ?? true
3990
4448
  }
3991
4449
  ) });
3992
4450
  };
3993
- var StatefulTextNormalize = ({ standalone = true }) => {
4451
+ var StatefulNoRuby = ({ standalone = true }) => {
3994
4452
  const { t } = useI18n();
3995
4453
  const profile = useAppSelector((state) => state.reader.profile);
3996
4454
  const isWebPub = profile === "webPub";
3997
- const textNormalization = useAppSelector((state) => isWebPub ? state.webPubSettings.textNormalization : state.settings.textNormalization) ?? false;
4455
+ const noRuby = useReaderSetting("noRuby");
3998
4456
  const dispatch = useAppDispatch();
3999
4457
  const { getSetting, submitPreferences } = useNavigator().visual;
4458
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["noRuby" /* noRuby */];
4000
4459
  const updatePreference = useCallback(async (value) => {
4001
- await submitPreferences({ textNormalization: value });
4002
- const effectiveSetting = getSetting("textNormalization");
4460
+ await submitPreferences({ [prefKey]: value });
4461
+ const effectiveSetting = getSetting(prefKey);
4003
4462
  if (isWebPub) {
4004
- dispatch(setWebPubTextNormalization(effectiveSetting));
4463
+ dispatch(setWebPubNoRuby(effectiveSetting));
4005
4464
  } else {
4006
- dispatch(setTextNormalization(effectiveSetting));
4465
+ dispatch(setNoRuby(effectiveSetting));
4007
4466
  }
4008
- }, [isWebPub, submitPreferences, getSetting, dispatch]);
4467
+ }, [prefKey, isWebPub, submitPreferences, getSetting, dispatch]);
4009
4468
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
4010
4469
  StatefulSwitch,
4011
4470
  {
4012
4471
  standalone,
4013
- heading: t("reader.preferences.textNormalization.title"),
4014
- label: t("reader.preferences.textNormalization.label"),
4472
+ heading: t("reader.preferences.noRuby.title"),
4473
+ label: t("reader.preferences.noRuby.label"),
4015
4474
  onChange: async (isSelected) => await updatePreference(isSelected),
4016
- isSelected: textNormalization ?? false
4475
+ isSelected: noRuby ?? false
4017
4476
  }
4018
4477
  ) });
4019
4478
  };
@@ -4163,12 +4622,13 @@ var StatefulWordSpacing = ({ standalone = true }) => {
4163
4622
  const placeholderText = usePlaceholder(wordSpacingRangeConfig.placeholder, wordSpacingRangeConfig.range, "percent");
4164
4623
  const { getEffectiveSpacingValue, setWordSpacing: setWordSpacing2, canBeReset } = useSpacingPresets();
4165
4624
  const wordSpacing = getEffectiveSpacingValue("wordSpacing" /* wordSpacing */);
4625
+ const prefKey = SETTINGS_KEY_TO_PREFERENCE["wordSpacing" /* wordSpacing */];
4166
4626
  const updatePreference = useCallback(async (value) => {
4167
4627
  await submitPreferences({
4168
- wordSpacing: Array.isArray(value) ? value[0] : value
4628
+ [prefKey]: Array.isArray(value) ? value[0] : value
4169
4629
  });
4170
- setWordSpacing2(getSetting("wordSpacing"));
4171
- }, [submitPreferences, getSetting, setWordSpacing2]);
4630
+ setWordSpacing2(getSetting(prefKey));
4631
+ }, [prefKey, submitPreferences, getSetting, setWordSpacing2]);
4172
4632
  return /* @__PURE__ */ jsx(Fragment, { children: wordSpacingRangeConfig.variant === "numberField" /* numberField */ ? /* @__PURE__ */ jsx(
4173
4633
  StatefulNumberField,
4174
4634
  {
@@ -4219,9 +4679,7 @@ var StatefulZoom = () => {
4219
4679
  const { t } = useI18n();
4220
4680
  const readerProfile = useAppSelector((state) => state.reader.profile);
4221
4681
  const isFXL = useAppSelector((state) => state.publication.isFXL);
4222
- const fontSize = useAppSelector((state) => state.settings.fontSize) || 1;
4223
- const webPubZoom = useAppSelector((state) => state.webPubSettings.zoom) || 1;
4224
- const derivedState = readerProfile === "webPub" ? webPubZoom : fontSize;
4682
+ const derivedState = useReaderSetting("zoom");
4225
4683
  const dispatch = useAppDispatch();
4226
4684
  const {
4227
4685
  getSetting,
@@ -4229,15 +4687,16 @@ var StatefulZoom = () => {
4229
4687
  preferencesEditor
4230
4688
  } = useNavigator().visual;
4231
4689
  const preferenceEditorProperty = readerProfile === "webPub" ? preferencesEditor?.zoom : isFXL ? preferencesEditor?.zoom : preferencesEditor?.fontSize;
4690
+ const prefKey = readerProfile === "webPub" ? SETTINGS_KEY_TO_PREFERENCE["zoom" /* zoom */] : "fontSize";
4232
4691
  const updatePreference = useCallback(async (value) => {
4692
+ const normalizedValue = Array.isArray(value) ? value[0] : value;
4693
+ await submitPreferences({ [prefKey]: normalizedValue });
4233
4694
  if (readerProfile === "webPub") {
4234
- await submitPreferences({ zoom: Array.isArray(value) ? value[0] : value });
4235
- dispatch(setWebPubZoom(getSetting("zoom")));
4695
+ dispatch(setWebPubZoom(getSetting(prefKey)));
4236
4696
  } else {
4237
- await submitPreferences({ fontSize: Array.isArray(value) ? value[0] : value });
4238
- dispatch(setFontSize(getSetting("fontSize")));
4697
+ dispatch(setFontSize(getSetting(prefKey)));
4239
4698
  }
4240
- }, [readerProfile, submitPreferences, getSetting, dispatch]);
4699
+ }, [readerProfile, prefKey, submitPreferences, getSetting, dispatch]);
4241
4700
  const zoomConfig = preferences.settings.keys["zoom" /* zoom */];
4242
4701
  const { range: effectiveRange } = useEffectiveRange(zoomConfig.range, preferenceEditorProperty?.supportedRange);
4243
4702
  const zoomRangeConfig = {
@@ -4291,7 +4750,7 @@ var createDefaultPlugin = () => {
4291
4750
  id: "core",
4292
4751
  name: "Core Components",
4293
4752
  description: "Default components for Thorium Web Epub StatefulReader",
4294
- version: "1.3.1",
4753
+ version: "1.4.0",
4295
4754
  components: {
4296
4755
  actions: {
4297
4756
  ["fullscreen" /* fullscreen */]: {
@@ -4367,6 +4826,14 @@ var createDefaultPlugin = () => {
4367
4826
  Comp: StatefulTextNormalize,
4368
4827
  type: "text"
4369
4828
  },
4829
+ ["ligatures" /* ligatures */]: {
4830
+ Comp: StatefulLigatures,
4831
+ type: "text"
4832
+ },
4833
+ ["noRuby" /* noRuby */]: {
4834
+ Comp: StatefulNoRuby,
4835
+ type: "text"
4836
+ },
4370
4837
  ["theme" /* theme */]: {
4371
4838
  Comp: StatefulTheme
4372
4839
  },
@@ -4395,7 +4862,8 @@ var StatefulSliderWithPresets = ({
4395
4862
  ...props
4396
4863
  }) => {
4397
4864
  const { t } = useI18n();
4398
- const { theming, direction } = useSharedPreferences();
4865
+ const { theming } = useSharedPreferences();
4866
+ const isRTL = useAppSelector((state) => state.publication.isRTL);
4399
4867
  const numberFormatter = useNumberFormatter(props.formatOptions);
4400
4868
  const resolvedFormatValue = formatValue ?? (props.formatOptions ? (v) => numberFormatter.format(v) : void 0);
4401
4869
  const tooltipDelay = theming.icon.tooltipDelay;
@@ -4408,7 +4876,7 @@ var StatefulSliderWithPresets = ({
4408
4876
  items: presetsRef,
4409
4877
  currentValue: currentScalarValue,
4410
4878
  onChange: (v) => props.onChange?.([v]),
4411
- isRTL: direction === "rtl" /* rtl */,
4879
+ isRTL,
4412
4880
  onEscape,
4413
4881
  onFocus: (v) => {
4414
4882
  const el = presetsListRef.current?.querySelector(`input[value="${v}"]`);
@@ -4891,6 +5359,7 @@ var StatefulAudioVolumeTrigger = ({ ref }) => {
4891
5359
  if (volume <= max / 3 * 2) return volume_down_default;
4892
5360
  return volume_up_default;
4893
5361
  }, [volume, range]);
5362
+ if (isIOSish()) return null;
4894
5363
  return /* @__PURE__ */ jsx(
4895
5364
  StatefulActionIcon,
4896
5365
  {
@@ -4931,6 +5400,7 @@ var StatefulAudioVolumeContainer = ({ triggerRef, placement = "top" }) => {
4931
5400
  dispatch(setActionOpen({ key: "audio.volume" /* volume */, isOpen: open, profile }));
4932
5401
  }
4933
5402
  }, [dispatch, profile]);
5403
+ if (isIOSish()) return null;
4934
5404
  return /* @__PURE__ */ jsx(
4935
5405
  StatefulSheetWrapper,
4936
5406
  {
@@ -5124,8 +5594,7 @@ var StatefulAudioTocContainer = ({ triggerRef }) => {
5124
5594
  const tocEntry = unstableTimeline?.toc?.currentEntry ?? void 0;
5125
5595
  const tocEntryId = tocEntry?.id;
5126
5596
  const tocTree = unstableTimeline?.toc?.tree;
5127
- const direction = useAppSelector((state) => state.reader.direction);
5128
- const isRTL = direction === "rtl" /* rtl */;
5597
+ const isRTL = useAppSelector((state) => state.publication.isRTL);
5129
5598
  const docking = useDocking("audio.toc" /* toc */);
5130
5599
  const sheetType = docking.sheetType;
5131
5600
  const setOpen = useCallback((value) => {
@@ -5545,7 +6014,7 @@ var createAudioDefaultPlugin = () => {
5545
6014
  id: "audio-core",
5546
6015
  name: "Audio Core Components",
5547
6016
  description: "Default components for Thorium Web Audio StatefulReader",
5548
- version: "1.3.1",
6017
+ version: "1.4.0",
5549
6018
  components: {
5550
6019
  actions: {
5551
6020
  ["settings" /* settings */]: {
@@ -5599,233 +6068,16 @@ var StatefulPreferencesProvider = ({
5599
6068
  }, [store, initialPreferences]);
5600
6069
  return /* @__PURE__ */ jsx(ThPreferencesProvider, { adapter, children });
5601
6070
  };
5602
-
5603
- // src/hooks/useReaderTransitions.ts
5604
- var useReaderTransitions = () => {
5605
- const isImmersive = useAppSelector((state) => state.reader.isImmersive);
5606
- const isFullscreen = useAppSelector((state) => state.reader.isFullscreen);
5607
- const hasUserNavigated = useAppSelector((state) => state.reader.hasUserNavigated);
5608
- const scroll = useAppSelector((state) => state.settings.scroll);
5609
- const isFXL = useAppSelector((state) => state.publication.isFXL);
5610
- const isScroll = scroll && !isFXL;
5611
- const wasImmersive = usePrevious(isImmersive) ?? false;
5612
- const wasFullscreen = usePrevious(isFullscreen) ?? false;
5613
- const wasScroll = usePrevious(isScroll) ?? false;
5614
- const wasUserNavigated = usePrevious(hasUserNavigated) ?? false;
5615
- const fromImmersive = wasImmersive && !isImmersive;
5616
- const toImmersive = !wasImmersive && isImmersive;
5617
- const fromFullscreen = wasFullscreen && !isFullscreen;
5618
- const toFullscreen = !wasFullscreen && isFullscreen;
5619
- const fromScroll = wasScroll && !isScroll;
5620
- const toScroll = !wasScroll && isScroll;
5621
- const fromUserNavigation = wasUserNavigated && !hasUserNavigated;
5622
- const toUserNavigation = !wasUserNavigated && hasUserNavigated;
5623
- return {
5624
- // Current states
5625
- isImmersive,
5626
- isFullscreen,
5627
- isScroll,
5628
- hasUserNavigated,
5629
- // Previous states
5630
- wasImmersive,
5631
- wasFullscreen,
5632
- wasScroll,
5633
- wasUserNavigated,
5634
- // State transitions
5635
- fromImmersive,
5636
- toImmersive,
5637
- fromFullscreen,
5638
- toFullscreen,
5639
- fromScroll,
5640
- toScroll,
5641
- fromUserNavigation,
5642
- toUserNavigation
5643
- };
5644
- };
5645
-
5646
- // src/helpers/deserializePositions.ts
5647
- var deserializePositions = (positionsList) => {
5648
- return positionsList?.map((locator) => ({
5649
- href: locator.href,
5650
- type: locator.type,
5651
- locations: {
5652
- position: locator.locations.position,
5653
- progression: locator.locations.progression,
5654
- totalProgression: locator.locations.totalProgression
5655
- }
5656
- }));
5657
- };
5658
-
5659
- // src/hooks/usePublication.ts
5660
- var detectProfile = (manifest) => {
5661
- const metadata = manifest.metadata;
5662
- if (!metadata) return "webPub";
5663
- const conformsTo = metadata.conformsTo;
5664
- if (!conformsTo) return "webPub";
5665
- const profiles = Array.isArray(conformsTo) ? conformsTo : [conformsTo];
5666
- if (profiles.some(
5667
- (profile) => profile === Profile.AUDIOBOOK
5668
- )) {
5669
- return "audio";
5670
- }
5671
- if (profiles.some(
5672
- (profile) => profile === Profile.EPUB
5673
- )) {
5674
- return "epub";
5675
- }
5676
- return "webPub";
5677
- };
5678
- var usePublication = ({
5679
- url,
5680
- onError = () => {
5681
- },
5682
- fetcher: customFetcher
6071
+ var StatefulGlobalPreferencesProvider = ({
6072
+ children,
6073
+ initialPreferences = {}
5683
6074
  }) => {
5684
- const dispatch = useAppDispatch();
5685
- const [isLoading, setIsLoading] = useState(true);
5686
- const [error, setError] = useState(null);
5687
- const [manifest, setManifest] = useState(null);
5688
- const [selfLink, setSelfLink] = useState(null);
5689
- const [localDataKey, setLocalDataKey] = useState(null);
5690
- const [publication, setPublication] = useState(null);
5691
- const [profile, setProfile] = useState(null);
5692
- const [isRTL, setIsRTL] = useState(false);
5693
- const [isFXL, setIsFXL] = useState(false);
5694
- const [hasDisplayTransformability, setHasDisplayTransformabilityState] = useState(false);
5695
- const handleManifestError = (error2, context) => {
5696
- console.error(`${context}:`, error2);
5697
- const processedError = ErrorHandler.process(error2, context);
5698
- setError(processedError);
5699
- setIsLoading(false);
5700
- };
5701
- useEffect(() => {
5702
- if (!url) {
5703
- const validationError = ErrorHandler.process(new Error("Manifest URL is required"), "Validation");
5704
- setError(validationError);
5705
- setIsLoading(false);
5706
- return;
5707
- }
5708
- setIsLoading(true);
5709
- setError(null);
5710
- const decodedUrl = decodeURIComponent(url);
5711
- const manifestLink = new Link({ href: decodedUrl });
5712
- const fetcher = customFetcher || new HttpFetcher(void 0);
5713
- try {
5714
- const fetched = fetcher.get(manifestLink);
5715
- fetched.link().then(async (link) => {
5716
- try {
5717
- const selfHref = link.toURL(decodedUrl);
5718
- setSelfLink(selfHref || null);
5719
- if (selfHref) {
5720
- setLocalDataKey(`${selfHref}-current-location`);
5721
- const manifestFetcher = customFetcher || new HttpFetcher(void 0, selfHref);
5722
- const manifestFetched = manifestFetcher.get(manifestLink);
5723
- const manifestData = await manifestFetched.readAsJSON();
5724
- setManifest(manifestData);
5725
- const manifestObj = Manifest.deserialize(manifestData);
5726
- manifestObj.setSelfLink(selfHref);
5727
- const detectedProfile = detectProfile(manifestObj);
5728
- setProfile(detectedProfile);
5729
- dispatch(setReaderProfile(detectedProfile));
5730
- const pub = new Publication({
5731
- manifest: manifestObj,
5732
- fetcher: manifestFetcher
5733
- });
5734
- if (detectedProfile === "epub") {
5735
- try {
5736
- const rawPositions = await pub.positionsFromManifest();
5737
- const positionsList = deserializePositions(rawPositions);
5738
- dispatch(setPositionsList(positionsList));
5739
- } catch (error2) {
5740
- console.error("Failed to fetch positions:", error2);
5741
- dispatch(setPositionsList([]));
5742
- }
5743
- }
5744
- if (detectedProfile === "audio") {
5745
- const tocLinks = manifestObj.toc?.items && manifestObj.toc.items.length > 0 ? manifestObj.toc.items : manifestObj.readingOrder?.items || [];
5746
- const publicationTitle = manifestObj.metadata.title.getTranslation("en");
5747
- let idCounter = 0;
5748
- const idGenerator = () => `toc-${++idCounter}`;
5749
- dispatch(setTocTree(buildTocTree(tocLinks, idGenerator, void 0, publicationTitle)));
5750
- }
5751
- setPublication(pub);
5752
- setIsLoading(false);
5753
- }
5754
- } catch (error2) {
5755
- handleManifestError(error2, "Error loading manifest");
5756
- }
5757
- });
5758
- } catch (error2) {
5759
- handleManifestError(error2, "Error loading manifest");
5760
- }
5761
- }, [url, customFetcher, dispatch]);
5762
- useEffect(() => {
5763
- if (!publication) return;
5764
- const rtl = publication.metadata.effectiveReadingProgression === ReadingProgression.rtl;
5765
- setIsRTL(rtl);
5766
- dispatch(setRTL(rtl));
5767
- if (profile === "epub") {
5768
- const fxl = publication.metadata.effectiveLayout === Layout.fixed;
5769
- setIsFXL(fxl);
5770
- dispatch(setFXL(fxl));
5771
- }
5772
- const displayTransformability = publication.metadata.accessibility?.feature?.some(
5773
- (feature) => feature && feature.value === Feature.DISPLAY_TRANSFORMABILITY.value
5774
- ) || false;
5775
- setHasDisplayTransformabilityState(displayTransformability);
5776
- dispatch(setHasDisplayTransformability(displayTransformability));
5777
- if (profile === "epub" && publication) {
5778
- const fetchPositions = async () => {
5779
- try {
5780
- const positionsList = await publication.positionsFromManifest();
5781
- const deserializedPositionsList = deserializePositions(positionsList);
5782
- dispatch(setPositionsList(deserializedPositionsList));
5783
- } catch (error2) {
5784
- console.error("Failed to fetch positions:", error2);
5785
- dispatch(setPositionsList([]));
5786
- }
5787
- };
5788
- fetchPositions();
5789
- }
5790
- }, [publication, profile, dispatch]);
5791
- useEffect(() => {
5792
- if (error) {
5793
- onError(error);
5794
- }
5795
- }, [error, onError]);
5796
- return {
5797
- isLoading,
5798
- error,
5799
- publication,
5800
- manifest,
5801
- selfLink,
5802
- localDataKey,
5803
- profile,
5804
- isRTL,
5805
- isFXL,
5806
- hasDisplayTransformability
5807
- };
5808
- };
5809
- var usePositionStorage = (key, customStorage) => {
5810
- const localStorageData = useLocalStorage(key);
5811
- const [customData, setCustomData] = useState(
5812
- () => customStorage ? customStorage.get() || null : null
6075
+ const store = useStore();
6076
+ const adapter = useMemo(
6077
+ () => new ThReduxGlobalPreferencesAdapter(store, initialPreferences),
6078
+ [store, initialPreferences]
5813
6079
  );
5814
- if (customStorage) {
5815
- const set = (newValue) => {
5816
- if (newValue) {
5817
- customStorage.set(newValue);
5818
- }
5819
- setCustomData(newValue);
5820
- };
5821
- const get = () => customData;
5822
- return {
5823
- setLocalData: set,
5824
- getLocalData: get,
5825
- localData: customData
5826
- };
5827
- }
5828
- return localStorageData;
6080
+ return /* @__PURE__ */ jsx(ThGlobalPreferencesProvider, { adapter, initialPreferences, children });
5829
6081
  };
5830
6082
 
5831
6083
  // src/components/assets/styles/thorium-web.reader.app.module.css
@@ -6148,10 +6400,11 @@ var StatefulBackLink = ({
6148
6400
  className
6149
6401
  }) => {
6150
6402
  const { t } = useI18n();
6151
- const { direction, theming } = useSharedPreferences();
6403
+ const { theming } = useSharedPreferences();
6404
+ const { direction } = useLocale();
6152
6405
  const backLinkPref = theming.header?.backLink;
6153
6406
  const tooltipDelay = theming.icon.tooltipDelay;
6154
- const isRTL = direction === "rtl" /* rtl */;
6407
+ const isRTL = direction === "rtl";
6155
6408
  const variant = backLinkPref?.variant || "arrow" /* arrow */;
6156
6409
  const href = backLinkPref?.href;
6157
6410
  const content = backLinkPref?.content;
@@ -6215,7 +6468,7 @@ var StatefulBackLink = ({
6215
6468
  for (const { name, value } of Array.from(svgElement.attributes)) {
6216
6469
  attributes[name] = value;
6217
6470
  }
6218
- contentNode = React24.createElement("svg", {
6471
+ contentNode = React22.createElement("svg", {
6219
6472
  ...attributes,
6220
6473
  "aria-hidden": "true",
6221
6474
  focusable: "false",
@@ -6242,9 +6495,8 @@ var useReaderHeaderBase = (actionKeys) => {
6242
6495
  const headerRef = useRef(null);
6243
6496
  const { t } = useI18n();
6244
6497
  const { actionsComponentsMap } = usePlugins();
6245
- useAppSelector((state) => state.actions.keys);
6246
6498
  const overflowMap = useAppSelector((state) => state.actions.overflow);
6247
- const isScroll = useAppSelector((state) => state.settings.scroll);
6499
+ const isScroll = useIsScroll();
6248
6500
  const isImmersive = useAppSelector((state) => state.reader.isImmersive);
6249
6501
  const isHovering = useAppSelector((state) => state.reader.isHovering);
6250
6502
  const hasScrollAffordance = useAppSelector((state) => state.reader.hasScrollAffordance);
@@ -6320,6 +6572,6 @@ var useReaderHeaderBase = (actionKeys) => {
6320
6572
  };
6321
6573
  };
6322
6574
 
6323
- export { NavigatorProvider, StatefulActionIcon, StatefulAudioAutoPlay, StatefulAudioPlaybackRateContainer, StatefulAudioPlaybackRateTrigger, StatefulAudioRemotePlaybackTrigger, StatefulAudioSettingsContainer, StatefulAudioSkipBackwardInterval, StatefulAudioSkipForwardInterval, StatefulAudioSkipInterval, StatefulAudioSleepTimerContainer, StatefulAudioSleepTimerTrigger, StatefulAudioTocContainer, StatefulAudioTocTrigger, StatefulAudioVolumeContainer, StatefulAudioVolumeTrigger, StatefulBackLink, StatefulBottomSheet, StatefulCollapsibleActionsBar, StatefulColumns, StatefulCompactPopoverSheet, StatefulDockedSheet, StatefulDockingWrapper, StatefulDropdown, StatefulFontFamily, StatefulFullScreenSheet, StatefulFullscreenTrigger, StatefulGroupWrapper, StatefulHyphens, StatefulJumpToPositionContainer, StatefulJumpToPositionTrigger, StatefulLayout, StatefulLetterSpacing, StatefulLineHeight, StatefulModalBase, StatefulModalSheet, StatefulNumberField, StatefulOverflowMenu, StatefulOverflowMenuItem, StatefulParagraphIndent, StatefulParagraphSpacing, StatefulPopoverSheet, StatefulPreferencesProvider, StatefulPublisherStyles, StatefulRadioGroup, StatefulSettingsTrigger, StatefulSettingsWrapper, StatefulSheetWrapper, StatefulSlider, StatefulSliderWithPresets, StatefulSpacingGroup, StatefulSpacingGroupContainer, StatefulSpacingPresets, StatefulSwitch, StatefulTextAlign, StatefulTextGroup, StatefulTextGroupContainer, StatefulTextNormalize, StatefulTheme, StatefulTocContainer, StatefulTocTrigger, StatefulVisualSettingsContainer, StatefulWordSpacing, StatefulZoom, UnstableStatefulFontWeight, createAudioDefaultPlugin, createDefaultPlugin, thorium_web_button_default, thorium_web_overflow_default, thorium_web_reader_app_default, thorium_web_reader_header_default, useDocking, useEffectiveRange, useGridNavigation, useGridTemplate, useLineHeight, useNavigator, usePositionStorage, usePublication, useReaderHeaderBase, useReaderTransitions, useSettingsComponentStatus, useSpacingPresets };
6324
- //# sourceMappingURL=chunk-LP3JFZ4A.mjs.map
6325
- //# sourceMappingURL=chunk-LP3JFZ4A.mjs.map
6575
+ export { NavigatorProvider, StatefulActionIcon, StatefulAudioAutoPlay, StatefulAudioPlaybackRateContainer, StatefulAudioPlaybackRateTrigger, StatefulAudioRemotePlaybackTrigger, StatefulAudioSettingsContainer, StatefulAudioSkipBackwardInterval, StatefulAudioSkipForwardInterval, StatefulAudioSkipInterval, StatefulAudioSleepTimerContainer, StatefulAudioSleepTimerTrigger, StatefulAudioTocContainer, StatefulAudioTocTrigger, StatefulAudioVolumeContainer, StatefulAudioVolumeTrigger, StatefulBackLink, StatefulBottomSheet, StatefulCollapsibleActionsBar, StatefulColumns, StatefulCompactPopoverSheet, StatefulDockedSheet, StatefulDockingWrapper, StatefulDropdown, StatefulFontFamily, StatefulFullScreenSheet, StatefulFullscreenTrigger, StatefulGlobalPreferencesProvider, StatefulGroupWrapper, StatefulHyphens, StatefulJumpToPositionContainer, StatefulJumpToPositionTrigger, StatefulLayout, StatefulLetterSpacing, StatefulLigatures, StatefulLineHeight, StatefulModalBase, StatefulModalSheet, StatefulNoRuby, StatefulNumberField, StatefulOverflowMenu, StatefulOverflowMenuItem, StatefulParagraphIndent, StatefulParagraphSpacing, StatefulPopoverSheet, StatefulPreferencesProvider, StatefulPublisherStyles, StatefulRadioGroup, StatefulSettingsTrigger, StatefulSettingsWrapper, StatefulSheetWrapper, StatefulSlider, StatefulSliderWithPresets, StatefulSpacingGroup, StatefulSpacingGroupContainer, StatefulSpacingPresets, StatefulSwitch, StatefulTextAlign, StatefulTextGroup, StatefulTextGroupContainer, StatefulTextNormalize, StatefulTheme, StatefulTocContainer, StatefulTocTrigger, StatefulVisualSettingsContainer, StatefulWordSpacing, StatefulZoom, UnstableStatefulFontWeight, createAudioDefaultPlugin, createDefaultPlugin, thorium_web_button_default, thorium_web_overflow_default, thorium_web_reader_app_default, thorium_web_reader_header_default, useDocking, useEffectiveRange, useGridNavigation, useGridTemplate, useIsScroll, useLineHeight, useNavigator, usePlaceholder, usePositionStorage, usePublication, useReaderHeaderBase, useReaderSetting, useReaderTransitions, useSettingsComponentStatus, useSpacingPresets };
6576
+ //# sourceMappingURL=chunk-MSHUPSBI.mjs.map
6577
+ //# sourceMappingURL=chunk-MSHUPSBI.mjs.map