@edrlab/thorium-web 1.5.7 → 1.6.0

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 (66) hide show
  1. package/dist/{ThPreferencesAdapter-GepvYoaL.d.mts → ThPreferencesAdapter-B39cxwAo.d.mts} +4 -22
  2. package/dist/{ThSettingsWrapper-DyYC678Q.d.mts → ThSettingsWrapper-DBrfTO6I.d.mts} +1 -1
  3. package/dist/{actions-CTg9C4C-.d.mts → actions-CN51OeyO.d.mts} +29 -6
  4. package/dist/{actionsReducer-Cnd7Cdh9.d.mts → actionsReducer-D3Ujx25n.d.mts} +5 -13
  5. package/dist/{chunk-C6LWEQL2.mjs → chunk-7X5KT42Z.mjs} +336 -310
  6. package/dist/chunk-7X5KT42Z.mjs.map +1 -0
  7. package/dist/{chunk-I765HTBI.mjs → chunk-GC7ENGE2.mjs} +49 -76
  8. package/dist/chunk-GC7ENGE2.mjs.map +1 -0
  9. package/dist/{chunk-MBWYHA4U.mjs → chunk-GGNTMKHK.mjs} +8 -8
  10. package/dist/chunk-GGNTMKHK.mjs.map +1 -0
  11. package/dist/{chunk-TNXLY2ZQ.mjs → chunk-GWL53CI4.mjs} +9 -9
  12. package/dist/chunk-GWL53CI4.mjs.map +1 -0
  13. package/dist/{chunk-JXHRUQKP.mjs → chunk-OOAZZ3IZ.mjs} +9 -9
  14. package/dist/chunk-OOAZZ3IZ.mjs.map +1 -0
  15. package/dist/{chunk-2YS5JTIR.mjs → chunk-QME5CNAT.mjs} +5 -5
  16. package/dist/{chunk-2YS5JTIR.mjs.map → chunk-QME5CNAT.mjs.map} +1 -1
  17. package/dist/{chunk-6DR4EAK3.mjs → chunk-WA35SQJK.mjs} +2 -2
  18. package/dist/chunk-WA35SQJK.mjs.map +1 -0
  19. package/dist/components/Audio/index.css +1 -1
  20. package/dist/components/Audio/index.css.map +1 -1
  21. package/dist/components/Audio/index.d.mts +9 -9
  22. package/dist/components/Audio/index.mjs +4 -4
  23. package/dist/components/Epub/index.css +1 -1
  24. package/dist/components/Epub/index.css.map +1 -1
  25. package/dist/components/Epub/index.d.mts +9 -9
  26. package/dist/components/Epub/index.mjs +5 -5
  27. package/dist/components/Reader/index.css +1 -1
  28. package/dist/components/Reader/index.css.map +1 -1
  29. package/dist/components/Reader/index.d.mts +8 -8
  30. package/dist/components/Reader/index.mjs +9 -9
  31. package/dist/components/WebPub/index.css +1 -1
  32. package/dist/components/WebPub/index.css.map +1 -1
  33. package/dist/components/WebPub/index.d.mts +9 -9
  34. package/dist/components/WebPub/index.mjs +5 -5
  35. package/dist/core/Components/index.d.mts +5 -5
  36. package/dist/core/Hooks/index.d.mts +4 -4
  37. package/dist/lib/index.d.mts +7 -7
  38. package/dist/lib/index.mjs +1 -1
  39. package/dist/locales/ar/thorium-shared.json +109 -14
  40. package/dist/locales/ar/thorium-web.json +67 -7
  41. package/dist/locales/en/thorium-shared.json +3 -0
  42. package/dist/locales/en/thorium-web.json +1 -2
  43. package/dist/locales/es/thorium-shared.json +2 -2
  44. package/dist/locales/es/thorium-web.json +1 -1
  45. package/dist/locales/et/thorium-shared.json +3 -0
  46. package/dist/locales/fi/thorium-shared.json +3 -0
  47. package/dist/locales/fr/thorium-shared.json +1 -1
  48. package/dist/locales/it/thorium-shared.json +3 -0
  49. package/dist/locales/lt/thorium-shared.json +6 -3
  50. package/dist/locales/pl/thorium-shared.json +6 -0
  51. package/dist/locales/sl/thorium-shared.json +380 -0
  52. package/dist/locales/sv/thorium-shared.json +6 -0
  53. package/dist/locales/sv/thorium-web.json +2 -2
  54. package/dist/preferences/index.d.mts +8 -8
  55. package/dist/preferences/index.mjs +1 -1
  56. package/dist/{settingsReducer-DRWEq8Cm.d.mts → settingsReducer-flD_zs4E.d.mts} +1 -1
  57. package/dist/{useContrast-Unp3534Z.d.mts → useContrast-BJlYqbPP.d.mts} +1 -1
  58. package/dist/{usePreferences-Bi-ptif0.d.mts → usePreferences-DZX-xVu2.d.mts} +4 -4
  59. package/dist/{useReaderTransitions-B9fOF61y.d.mts → useReaderTransitions-CIbMYwzs.d.mts} +7 -7
  60. package/package.json +3 -3
  61. package/dist/chunk-6DR4EAK3.mjs.map +0 -1
  62. package/dist/chunk-C6LWEQL2.mjs.map +0 -1
  63. package/dist/chunk-I765HTBI.mjs.map +0 -1
  64. package/dist/chunk-JXHRUQKP.mjs.map +0 -1
  65. package/dist/chunk-MBWYHA4U.mjs.map +0 -1
  66. package/dist/chunk-TNXLY2ZQ.mjs.map +0 -1
@@ -1,13 +1,13 @@
1
1
  import { makeBreakpointsMap, isKeyboardTriggered, isActiveElement } from './chunk-3R5JARA2.mjs';
2
2
  import { useFullscreen, useLocalStorage, useEpubNavigator } from './chunk-CXKDZVAV.mjs';
3
- import { setFullscreen, setReaderProfile, 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, collapseDockPanel, expandDockPanel, activateDockPanel, deactivateDockPanel, setDockPanelWidth } from './chunk-I765HTBI.mjs';
3
+ import { setFullscreen, setReaderProfile, 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, setDockPanelWidth, setImmersive, setOverflow, setUserNavigated, activateDockPanel, deactivateDockPanel } from './chunk-GC7ENGE2.mjs';
4
4
  import { setPositionsList, setScriptMode, setRTL, setFXL, setHasDisplayTransformability, setTocTree, buildTocTreeFromTimeline, setTocEntry, findTocItemByHref, findTocItemById } from './chunk-7SMOXFAF.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-6DR4EAK3.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-WA35SQJK.mjs';
6
6
  import { metaKeys } from './chunk-X63WSMOH.mjs';
7
7
  import { useAppDispatch, useAppSelector } from './chunk-MFVZ5AEN.mjs';
8
8
  import { isIOSish } from './chunk-KQ3KS5O5.mjs';
9
9
  import { ErrorHandler } from './chunk-RRDEPGBK.mjs';
10
- import { ThMenuItem, ThActionButton, ThMenu, ThCollapsibleActionsBar, ThPopover, ThContainerHeader, ThNavigationButton, ThContainerBody, ThModal, ThBottomSheet, ThCloseButton, ThDockedPanel, useFirstFocusable, ThTypedComponentRenderer, useActions, ThForm, ThFormNumberField, ThSettingsWrapper, ThRadioGroup, ThDropdown, ThSwitch, ThNumberField, ThSlider, ThSliderWithPresets, ThLink, ThLibrary, ThHome, ThBackArrow, ThFormSearchField } from './chunk-ES2Y5MC7.mjs';
10
+ import { ThMenuItem, ThActionButton, ThMenu, ThCollapsibleActionsBar, ThPopover, ThContainerHeader, ThNavigationButton, ThContainerBody, ThModal, ThBottomSheet, ThCloseButton, ThDockedPanel, useFirstFocusable, ThTypedComponentRenderer, ThForm, ThFormNumberField, ThSettingsWrapper, ThRadioGroup, ThDropdown, ThSwitch, ThNumberField, ThSlider, ThSliderWithPresets, ThLink, ThLibrary, ThHome, ThBackArrow, useActions, ThFormSearchField } from './chunk-ES2Y5MC7.mjs';
11
11
  import { usePrevious } from './chunk-YZ73DHRU.mjs';
12
12
  import { useI18n } from './chunk-2NCN2AG2.mjs';
13
13
  import React23, { createContext, useContext, useState, useEffect, useMemo, useCallback, useRef } from 'react';
@@ -19,7 +19,7 @@ import { Link, HttpFetcher, Manifest, Publication, ReadingProgression, Layout, F
19
19
  import { getScriptMode, lineHeightRangeConfig, TextAlignment } from '@readium/navigator';
20
20
  import i18nData from '@readium/css/css/vars/i18n.json';
21
21
  import { useStore } from 'react-redux';
22
- import { PanelGroup, Panel, PanelResizeHandle } from 'react-resizable-panels';
22
+ import { Group, Panel, Separator } from 'react-resizable-panels';
23
23
 
24
24
  // src/components/Plugins/PluginRegistry.ts
25
25
  var pluginsStore = [];
@@ -748,30 +748,61 @@ var SvgDockToRight = (props) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.
748
748
  var dock_to_right_default = SvgDockToRight;
749
749
  var SvgDockToLeft = (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: "M200-120q-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-120H200Zm440-80h120v-560H640v560Zm-80 0v-560H200v560h360Zm80 0h120-120Z" }) });
750
750
  var dock_to_left_default = SvgDockToLeft;
751
- var StatefulDockStart = ({ variant, associatedKey }) => {
751
+
752
+ // src/components/Docking/helpers/dockReservation.ts
753
+ var isReservedByPref = (actionPref) => {
754
+ const isDockedByDefault = actionPref?.sheet?.defaultSheet === "docked start" /* dockedStart */ || actionPref?.sheet?.defaultSheet === "docked end" /* dockedEnd */;
755
+ return !!actionPref?.docked?.reserved && isDockedByDefault;
756
+ };
757
+
758
+ // src/components/Docking/hooks/useDockReservation.ts
759
+ var useDockReservation = (key) => {
752
760
  const preferences = useActionsPreferences();
753
- const { t } = useI18n();
754
- const direction = useAppSelector((state) => state.reader.direction);
761
+ const profile = useAppSelector((state) => state.reader.profile);
762
+ const dock = useAppSelector((state) => profile ? state.actions.dock[profile] : void 0);
763
+ const actionPref = preferences.actionsKeys[key];
764
+ const reserved = isReservedByPref(actionPref);
765
+ const isSlotLockedByOther = useCallback((slot) => {
766
+ return !!dock?.[slot]?.reserved && dock?.[slot]?.actionKey !== key;
767
+ }, [dock, key]);
768
+ return {
769
+ dock,
770
+ reserved,
771
+ isSlotLockedByOther
772
+ };
773
+ };
774
+
775
+ // src/components/Docking/hooks/useDockTrigger.ts
776
+ var useDockTrigger = (slot, associatedKey) => {
755
777
  const profile = useAppSelector((state) => state.reader.profile);
756
778
  const actionsMap = useAppSelector((state) => profile ? state.actions.keys[profile] : void 0);
757
779
  const actions = useActions(actionsMap || {});
758
- const isRTL = direction === "rtl" /* rtl */;
759
- const translationKey = isRTL ? "reader.app.docker.dockToRight" : "reader.app.docker.dockToLeft";
760
- const localeKey = {
761
- trigger: t(`${translationKey}.trigger`),
762
- tooltip: t(`${translationKey}.tooltip`)
763
- };
764
- const isDisabled = actions.whichDocked(associatedKey) === "dockingStart" /* start */;
780
+ const { reserved, isSlotLockedByOther } = useDockReservation(associatedKey ?? "");
765
781
  const dispatch = useAppDispatch();
782
+ const isDisabled = actions.whichDocked(associatedKey) === slot || isSlotLockedByOther(slot);
766
783
  const handlePress = useCallback(() => {
767
784
  if (associatedKey && profile) {
768
785
  dispatch(dockAction({
769
786
  key: associatedKey,
770
- dockingKey: "dockingStart" /* start */,
771
- profile
787
+ dockingKey: slot,
788
+ profile,
789
+ reserved
772
790
  }));
773
791
  }
774
- }, [dispatch, associatedKey, profile]);
792
+ }, [dispatch, associatedKey, profile, reserved, slot]);
793
+ return { isDisabled, handlePress };
794
+ };
795
+ var StatefulDockStart = ({ variant, associatedKey }) => {
796
+ const preferences = useActionsPreferences();
797
+ const { t } = useI18n();
798
+ const direction = useAppSelector((state) => state.reader.direction);
799
+ const { isDisabled, handlePress } = useDockTrigger("dockingStart" /* start */, associatedKey);
800
+ const isRTL = direction === "rtl" /* rtl */;
801
+ const translationKey = isRTL ? "reader.app.docker.dockToRight" : "reader.app.docker.dockToLeft";
802
+ const localeKey = {
803
+ trigger: t(`${translationKey}.trigger`),
804
+ tooltip: t(`${translationKey}.tooltip`)
805
+ };
775
806
  return /* @__PURE__ */ jsx(Fragment, { children: variant && variant === "menuItem" /* menu */ ? /* @__PURE__ */ jsx(
776
807
  StatefulOverflowMenuItem,
777
808
  {
@@ -799,26 +830,13 @@ var StatefulDockEnd = ({ variant, associatedKey }) => {
799
830
  const preferences = useActionsPreferences();
800
831
  const { t } = useI18n();
801
832
  const direction = useAppSelector((state) => state.reader.direction);
802
- const profile = useAppSelector((state) => state.reader.profile);
803
- const actionsMap = useAppSelector((state) => profile ? state.actions.keys[profile] : void 0);
804
- const actions = useActions(actionsMap || {});
833
+ const { isDisabled, handlePress } = useDockTrigger("dockingEnd" /* end */, associatedKey);
805
834
  const isRTL = direction === "rtl" /* rtl */;
806
835
  const translationKey = isRTL ? "reader.app.docker.dockToLeft" : "reader.app.docker.dockToRight";
807
836
  const localeKey = {
808
837
  trigger: t(`${translationKey}.trigger`),
809
838
  tooltip: t(`${translationKey}.tooltip`)
810
839
  };
811
- const isDisabled = actions.whichDocked(associatedKey) === "dockingEnd" /* end */;
812
- const dispatch = useAppDispatch();
813
- const handlePress = useCallback(() => {
814
- if (associatedKey && profile) {
815
- dispatch(dockAction({
816
- key: associatedKey,
817
- dockingKey: "dockingEnd" /* end */,
818
- profile
819
- }));
820
- }
821
- }, [dispatch, associatedKey, profile]);
822
840
  return /* @__PURE__ */ jsx(Fragment, { children: variant && variant === "menuItem" /* menu */ ? /* @__PURE__ */ jsx(
823
841
  StatefulOverflowMenuItem,
824
842
  {
@@ -1564,12 +1582,17 @@ var StatefulDockedSheet = ({
1564
1582
  focusWithinRef
1565
1583
  }) => {
1566
1584
  const { t } = useI18n();
1567
- const dockPortal = flow && document.getElementById(flow);
1568
1585
  const dockedSheetRef = useRef(null);
1569
1586
  const dockedSheetHeaderRef = useRef(null);
1570
1587
  const dockedSheetBodyRef = useRef(null);
1571
1588
  const dockedSheetCloseRef = useRef(null);
1589
+ const [dockPortal, setDockPortal] = useState(null);
1572
1590
  const direction = useAppSelector((state) => state.reader.direction);
1591
+ const profile = useAppSelector((state) => state.reader.profile);
1592
+ const isSlotActive = useAppSelector((state) => profile && flow ? !!state.actions.dock[profile]?.[flow]?.active : false);
1593
+ useEffect(() => {
1594
+ setDockPortal(flow ? document.getElementById(flow) : null);
1595
+ }, [flow, isSlotActive, isOpen]);
1573
1596
  useEffect(() => {
1574
1597
  if (isOpen && dockedSheetRef.current && dockedSheetHeaderRef.current) {
1575
1598
  dockedSheetRef.current.style.setProperty(
@@ -1741,42 +1764,39 @@ var StatefulSheetWrapper = ({
1741
1764
  }
1742
1765
  );
1743
1766
  };
1744
- var dockingMap = null;
1767
+ var isDockedType = (type) => type === "docked start" /* dockedStart */ || type === "docked end" /* dockedEnd */;
1745
1768
  var useDocking = (key) => {
1746
1769
  const preferences = useActionsPreferences();
1747
1770
  const breakpoint = useAppSelector((state) => state.theming.breakpoint);
1748
1771
  const profile = useAppSelector((state) => state.reader.profile);
1749
1772
  const actionsMap = useAppSelector((state) => profile ? state.actions.keys[profile] : void 0);
1750
1773
  const actionState = actionsMap?.[key];
1751
- const dock = useAppSelector((state) => profile ? state.actions.dock[profile] : void 0);
1774
+ const { dock, reserved, isSlotLockedByOther } = useDockReservation(key);
1752
1775
  const dispatch = useAppDispatch();
1753
- const actions = useActions(actionsMap || {});
1754
- const startActionKey = dock?.["dockingStart" /* start */]?.actionKey;
1755
- const endActionKey = dock?.["dockingEnd" /* end */]?.actionKey;
1756
- const startStatus = useActionComponentStatus({ actionKey: startActionKey || "" });
1757
- const endStatus = useActionComponentStatus({ actionKey: endActionKey || "" });
1758
- if (!dockingMap) {
1759
- dockingMap = makeBreakpointsMap({
1760
- defaultValue: "both" /* both */,
1761
- fromEnum: ThDockingTypes,
1762
- pref: preferences.docking.dock,
1763
- disabledValue: "none" /* none */
1764
- });
1765
- }
1776
+ const dockingPref = preferences.docking.dock;
1777
+ const dockingMap = useMemo(() => makeBreakpointsMap({
1778
+ defaultValue: "both" /* both */,
1779
+ fromEnum: ThDockingTypes,
1780
+ pref: dockingPref,
1781
+ disabledValue: "none" /* none */
1782
+ }), [dockingPref]);
1766
1783
  const currentDockConfig = breakpoint && dockingMap[breakpoint];
1767
- const dockablePref = preferences.actionsKeys[key]?.docked?.dockable || "none" /* none */;
1768
- const defaultSheet = preferences.actionsKeys[key]?.sheet?.defaultSheet || "popover" /* popover */;
1769
- const sheetMap = makeBreakpointsMap({
1770
- defaultValue: preferences.actionsKeys[key]?.sheet?.defaultSheet || "popover" /* popover */,
1784
+ const actionPref = preferences.actionsKeys[key];
1785
+ const dockablePref = actionPref?.docked?.dockable || "none" /* none */;
1786
+ const reopenOnLoadPref = !!actionPref?.docked?.reopenOnLoad;
1787
+ const defaultSheet = actionPref?.sheet?.defaultSheet || "popover" /* popover */;
1788
+ const fallbackSheet = actionPref?.sheet?.fallbackSheet || "modal" /* modal */;
1789
+ const safeDefaultSheet = isDockedType(defaultSheet) ? fallbackSheet : defaultSheet;
1790
+ const sheetBreakpointsPref = actionPref?.sheet?.breakpoints;
1791
+ const sheetMap = useMemo(() => makeBreakpointsMap({
1792
+ defaultValue: defaultSheet,
1771
1793
  fromEnum: ThSheetTypes,
1772
- pref: preferences.actionsKeys[key]?.sheet?.breakpoints
1773
- });
1794
+ pref: sheetBreakpointsPref
1795
+ }), [defaultSheet, sheetBreakpointsPref]);
1774
1796
  const sheetPref = breakpoint && sheetMap[breakpoint] || defaultSheet;
1775
- const [sheetType, setSheetType] = useState(defaultSheet);
1776
- const previousSheetType = usePrevious(sheetType);
1777
1797
  const canBeDocked = useCallback((slot) => {
1778
- return (currentDockConfig === slot || currentDockConfig === "both" /* both */) && (dockablePref === slot || dockablePref === "both" /* both */);
1779
- }, [currentDockConfig, dockablePref]);
1798
+ return (currentDockConfig === slot || currentDockConfig === "both" /* both */) && (dockablePref === slot || dockablePref === "both" /* both */) && !isSlotLockedByOther(slot === "start" /* start */ ? "dockingStart" /* start */ : "dockingEnd" /* end */);
1799
+ }, [currentDockConfig, dockablePref, isSlotLockedByOther]);
1780
1800
  const isDockedSheetPref = useCallback((type) => {
1781
1801
  if (type) {
1782
1802
  return sheetPref === type;
@@ -1784,73 +1804,51 @@ var useDocking = (key) => {
1784
1804
  return sheetPref === "docked start" /* dockedStart */ || sheetPref === "docked end" /* dockedEnd */;
1785
1805
  }
1786
1806
  }, [sheetPref]);
1787
- const getDocker = useCallback(() => {
1788
- if (dockablePref === "none" /* none */) return [];
1789
- if (currentDockConfig === "none" /* none */) return [];
1790
- if (sheetPref === "fullscreen" /* fullscreen */ || sheetPref === "bottomSheet" /* bottomSheet */) return [];
1791
- let dockerKeys = [];
1792
- preferences.docking.displayOrder.forEach((dockingKey) => {
1793
- switch (dockingKey) {
1794
- case "dockingTransient" /* transient */:
1795
- dockerKeys.push(dockingKey);
1796
- break;
1797
- case "dockingStart" /* start */:
1798
- if (canBeDocked("start" /* start */)) {
1799
- dockerKeys.push(dockingKey);
1800
- }
1801
- break;
1802
- case "dockingEnd" /* end */:
1803
- if (canBeDocked("end" /* end */)) {
1804
- dockerKeys.push(dockingKey);
1805
- }
1806
- break;
1807
- }
1808
- });
1809
- if (dockerKeys.length === 1 && dockerKeys[0] === "dockingTransient" /* transient */) return [];
1810
- return dockerKeys;
1811
- }, [preferences.docking.displayOrder, currentDockConfig, sheetPref, dockablePref, canBeDocked]);
1812
- const getSheetType = useCallback(() => {
1807
+ const usableSheetPref = useCallback(() => {
1808
+ if (sheetPref === "docked start" /* dockedStart */ && !canBeDocked("start" /* start */)) return safeDefaultSheet;
1809
+ if (sheetPref === "docked end" /* dockedEnd */ && !canBeDocked("end" /* end */)) return safeDefaultSheet;
1810
+ return sheetPref;
1811
+ }, [sheetPref, canBeDocked, safeDefaultSheet]);
1812
+ const hasStaleTransient = actionState?.docking === "dockingTransient" /* transient */ && reserved;
1813
+ const effectiveDocking = hasStaleTransient ? void 0 : actionState?.docking;
1814
+ const nonDockedSheetPref = isDockedType(sheetPref) ? safeDefaultSheet : sheetPref;
1815
+ const sheetType = useMemo(() => {
1813
1816
  if (!breakpoint) {
1814
- return sheetType;
1817
+ return safeDefaultSheet;
1815
1818
  }
1816
1819
  if (dockablePref === "none" /* none */) {
1817
1820
  if (isDockedSheetPref()) {
1818
- return defaultSheet;
1821
+ return safeDefaultSheet;
1819
1822
  } else {
1820
- return sheetPref;
1823
+ return usableSheetPref();
1821
1824
  }
1822
1825
  }
1823
- switch (actionState?.docking) {
1824
- // if action.docking is transient we need to check the pref,
1826
+ switch (effectiveDocking) {
1827
+ // if action.docking is transient we need to check the pref,
1825
1828
  // it can be docked and in that case we need to pick the default
1826
1829
  case "dockingTransient" /* transient */:
1827
1830
  if (isDockedSheetPref()) {
1828
- return defaultSheet;
1831
+ return safeDefaultSheet;
1829
1832
  } else {
1830
- return sheetPref;
1833
+ return usableSheetPref();
1831
1834
  }
1832
- // If action.docking is set to start/end then we check the docking slot is available
1835
+ // The chosen slot may not be the one the static pref names, so
1836
+ // usableSheetPref (keyed to sheetPref's own slot) can't be reused here.
1837
+ // Unavailable: an explicit per-breakpoint non-docked sheet wins,
1838
+ // otherwise fall to fallbackSheet
1833
1839
  case "dockingStart" /* start */:
1834
1840
  if (canBeDocked("start" /* start */)) {
1835
1841
  return "docked start" /* dockedStart */;
1836
1842
  } else {
1837
- if (!isDockedSheetPref("docked start" /* dockedStart */)) {
1838
- return sheetPref;
1839
- } else {
1840
- return defaultSheet;
1841
- }
1843
+ return nonDockedSheetPref;
1842
1844
  }
1843
1845
  case "dockingEnd" /* end */:
1844
1846
  if (canBeDocked("end" /* end */)) {
1845
1847
  return "docked end" /* dockedEnd */;
1846
1848
  } else {
1847
- if (!isDockedSheetPref("docked end" /* dockedEnd */)) {
1848
- return sheetPref;
1849
- } else {
1850
- return defaultSheet;
1851
- }
1849
+ return nonDockedSheetPref;
1852
1850
  }
1853
- // If action.docking is null or undefined then we rely on pref
1851
+ // If action.docking is null or undefined then we rely on pref
1854
1852
  // as it means the user did not pick another option
1855
1853
  case null:
1856
1854
  case void 0:
@@ -1858,138 +1856,127 @@ var useDocking = (key) => {
1858
1856
  if (canBeDocked("start" /* start */)) {
1859
1857
  return "docked start" /* dockedStart */;
1860
1858
  } else {
1861
- return defaultSheet;
1859
+ return safeDefaultSheet;
1862
1860
  }
1863
1861
  } else if (isDockedSheetPref("docked end" /* dockedEnd */)) {
1864
1862
  if (canBeDocked("end" /* end */)) {
1865
1863
  return "docked end" /* dockedEnd */;
1866
1864
  } else {
1867
- return defaultSheet;
1865
+ return safeDefaultSheet;
1868
1866
  }
1869
1867
  } else {
1870
- return sheetPref;
1868
+ return usableSheetPref();
1871
1869
  }
1872
1870
  default:
1873
- return defaultSheet;
1871
+ return safeDefaultSheet;
1874
1872
  }
1875
- }, [dockablePref, sheetPref, defaultSheet, actionState?.docking, canBeDocked, isDockedSheetPref, breakpoint, sheetType]);
1876
- useEffect(() => {
1877
- setSheetType(getSheetType());
1878
- }, [sheetPref, currentDockConfig, actionState?.docking, getSheetType]);
1879
- useEffect(() => {
1880
- if (actionState?.docking === "dockingTransient" /* transient */) return;
1881
- if (sheetType !== "docked start" /* dockedStart */ && sheetType !== "docked end" /* dockedEnd */) {
1882
- if (previousSheetType === "docked start" /* dockedStart */ || previousSheetType === "docked end" /* dockedEnd */) {
1883
- if (profile) {
1884
- dispatch(setActionOpen({
1885
- key,
1886
- isOpen: false,
1887
- profile
1888
- }));
1889
- }
1873
+ }, [dockablePref, safeDefaultSheet, effectiveDocking, canBeDocked, isDockedSheetPref, usableSheetPref, nonDockedSheetPref, breakpoint]);
1874
+ const previousSheetType = usePrevious(sheetType);
1875
+ const getDocker = useCallback(() => {
1876
+ if (dockablePref === "none" /* none */) return [];
1877
+ if (currentDockConfig === "none" /* none */) return [];
1878
+ if (sheetPref === "fullscreen" /* fullscreen */ || sheetPref === "bottomSheet" /* bottomSheet */) return [];
1879
+ let dockerKeys = [];
1880
+ preferences.docking.displayOrder.forEach((dockingKey) => {
1881
+ switch (dockingKey) {
1882
+ case "dockingTransient" /* transient */:
1883
+ if (!reserved) {
1884
+ dockerKeys.push(dockingKey);
1885
+ }
1886
+ break;
1887
+ case "dockingStart" /* start */:
1888
+ if (canBeDocked("start" /* start */)) {
1889
+ dockerKeys.push(dockingKey);
1890
+ }
1891
+ break;
1892
+ case "dockingEnd" /* end */:
1893
+ if (canBeDocked("end" /* end */)) {
1894
+ dockerKeys.push(dockingKey);
1895
+ }
1896
+ break;
1890
1897
  }
1891
- }
1892
- }, [dispatch, key, sheetType, previousSheetType, actionState?.docking, profile]);
1898
+ });
1899
+ if (dockerKeys.length === 1 && dockerKeys[0] === "dockingTransient" /* transient */) return [];
1900
+ return dockerKeys;
1901
+ }, [preferences.docking.displayOrder, currentDockConfig, sheetPref, dockablePref, reserved, canBeDocked]);
1893
1902
  useEffect(() => {
1894
- if (actionState?.isOpen == null && profile) {
1895
- if (sheetType === "docked start" /* dockedStart */) {
1896
- dispatch(dockAction({
1897
- key,
1898
- dockingKey: "dockingStart" /* start */,
1899
- profile
1900
- }));
1903
+ if (!profile) return;
1904
+ if (!isDockedType(sheetType)) {
1905
+ if (previousSheetType == null && (actionState?.docking === "dockingStart" /* start */ || actionState?.docking === "dockingEnd" /* end */) && actionState?.isOpen) {
1901
1906
  dispatch(setActionOpen({
1902
1907
  key,
1903
- isOpen: true,
1904
- profile
1905
- }));
1906
- } else if (sheetType === "docked end" /* dockedEnd */) {
1907
- dispatch(dockAction({
1908
- key,
1909
- dockingKey: "dockingEnd" /* end */,
1910
- profile
1911
- }));
1912
- dispatch(setActionOpen({
1913
- key,
1914
- isOpen: true,
1908
+ isOpen: false,
1915
1909
  profile
1916
1910
  }));
1917
1911
  }
1912
+ return;
1918
1913
  }
1919
- }, [actionState?.isOpen, sheetType, key, dispatch, profile]);
1920
- useEffect(() => {
1921
- if (actionState?.isOpen != null && actionState?.docking == null && profile) {
1922
- if (sheetType === "docked start" /* dockedStart */) {
1923
- const dockingKey = actions.whichDocked(key);
1924
- if (dockingKey !== "dockingStart" /* start */) {
1925
- dispatch(dockAction({
1926
- key,
1927
- dockingKey: "dockingStart" /* start */,
1928
- profile
1929
- }));
1930
- }
1931
- } else if (sheetType === "docked end" /* dockedEnd */) {
1932
- const dockingKey = actions.whichDocked(key);
1933
- if (dockingKey !== "dockingEnd" /* end */) {
1934
- dispatch(dockAction({
1935
- key,
1936
- dockingKey: "dockingEnd" /* end */,
1937
- profile
1938
- }));
1939
- }
1940
- }
1914
+ if (effectiveDocking == null) {
1915
+ dispatch(dockAction({
1916
+ key,
1917
+ dockingKey: sheetType === "docked start" /* dockedStart */ ? "dockingStart" /* start */ : "dockingEnd" /* end */,
1918
+ profile,
1919
+ reserved
1920
+ }));
1941
1921
  }
1942
- }, [dispatch, key, sheetType, actionState?.isOpen, actionState?.docking, actions, profile]);
1922
+ if (actionState?.isOpen == null || hasStaleTransient) {
1923
+ dispatch(setActionOpen({
1924
+ key,
1925
+ isOpen: reopenOnLoadPref,
1926
+ profile
1927
+ }));
1928
+ }
1929
+ }, [effectiveDocking, hasStaleTransient, actionState?.isOpen, actionState?.docking, sheetType, previousSheetType, key, dispatch, profile, reserved, reopenOnLoadPref]);
1943
1930
  useEffect(() => {
1944
- if (profile && dock) {
1945
- const isDockedInStart = dock["dockingStart" /* start */]?.actionKey === key;
1946
- const isDockedInEnd = dock["dockingEnd" /* end */]?.actionKey === key;
1947
- if (isDockedInStart && actionState?.docking !== "dockingStart" /* start */) {
1948
- dispatch(dockAction({
1931
+ if (effectiveDocking === "dockingTransient" /* transient */) return;
1932
+ if (effectiveDocking === "dockingStart" /* start */ && !isSlotLockedByOther("dockingStart" /* start */)) return;
1933
+ if (effectiveDocking === "dockingEnd" /* end */ && !isSlotLockedByOther("dockingEnd" /* end */)) return;
1934
+ if (!previousSheetType || !isDockedType(previousSheetType) || isDockedType(sheetType)) return;
1935
+ if (!breakpoint || !profile) return;
1936
+ dispatch(setActionOpen({
1937
+ key,
1938
+ isOpen: false,
1939
+ profile
1940
+ }));
1941
+ }, [dispatch, key, sheetType, previousSheetType, breakpoint, profile, effectiveDocking, isSlotLockedByOther]);
1942
+ useEffect(() => {
1943
+ if (!profile || !dock) return;
1944
+ const startSlot = dock["dockingStart" /* start */];
1945
+ const endSlot = dock["dockingEnd" /* end */];
1946
+ const isDockedInStart = startSlot?.actionKey === key;
1947
+ const isDockedInEnd = endSlot?.actionKey === key;
1948
+ const wasAlreadyDockedInStart = actionState?.docking === "dockingStart" /* start */;
1949
+ const wasAlreadyDockedInEnd = actionState?.docking === "dockingEnd" /* end */;
1950
+ if (isDockedInStart && (!wasAlreadyDockedInStart || startSlot?.reserved !== reserved)) {
1951
+ dispatch(dockAction({
1952
+ key,
1953
+ dockingKey: "dockingStart" /* start */,
1954
+ profile,
1955
+ reserved
1956
+ }));
1957
+ if (!wasAlreadyDockedInStart && actionState?.isOpen == null && reopenOnLoadPref) {
1958
+ dispatch(setActionOpen({
1949
1959
  key,
1950
- dockingKey: "dockingStart" /* start */,
1960
+ isOpen: true,
1951
1961
  profile
1952
1962
  }));
1953
- if (actionState?.isOpen === false) {
1954
- dispatch(setActionOpen({
1955
- key,
1956
- isOpen: true,
1957
- profile
1958
- }));
1959
- }
1960
- } else if (isDockedInEnd && actionState?.docking !== "dockingEnd" /* end */) {
1961
- dispatch(dockAction({
1963
+ }
1964
+ } else if (isDockedInEnd && (!wasAlreadyDockedInEnd || endSlot?.reserved !== reserved)) {
1965
+ dispatch(dockAction({
1966
+ key,
1967
+ dockingKey: "dockingEnd" /* end */,
1968
+ profile,
1969
+ reserved
1970
+ }));
1971
+ if (!wasAlreadyDockedInEnd && actionState?.isOpen == null && reopenOnLoadPref) {
1972
+ dispatch(setActionOpen({
1962
1973
  key,
1963
- dockingKey: "dockingEnd" /* end */,
1974
+ isOpen: true,
1964
1975
  profile
1965
1976
  }));
1966
- if (actionState?.isOpen === false) {
1967
- dispatch(setActionOpen({
1968
- key,
1969
- isOpen: true,
1970
- profile
1971
- }));
1972
- }
1973
1977
  }
1974
1978
  }
1975
- }, [profile, dock, actionState?.docking, actionState?.isOpen, key, dispatch]);
1976
- useEffect(() => {
1977
- if (!profile || !dock) return;
1978
- if (startActionKey && !startStatus.isComponentRegistered) {
1979
- dispatch(dockAction({
1980
- key: startActionKey,
1981
- dockingKey: "dockingTransient" /* transient */,
1982
- profile
1983
- }));
1984
- }
1985
- if (endActionKey && !endStatus.isComponentRegistered) {
1986
- dispatch(dockAction({
1987
- key: endActionKey,
1988
- dockingKey: "dockingTransient" /* transient */,
1989
- profile
1990
- }));
1991
- }
1992
- }, [profile, dock, startActionKey, endActionKey, startStatus.isComponentRegistered, endStatus.isComponentRegistered, dispatch]);
1979
+ }, [profile, dock, actionState?.docking, actionState?.isOpen, key, dispatch, reserved, reopenOnLoadPref]);
1993
1980
  return {
1994
1981
  getDocker,
1995
1982
  sheetType
@@ -4896,7 +4883,7 @@ var createDefaultPlugin = () => {
4896
4883
  id: "core",
4897
4884
  name: "Core Components",
4898
4885
  description: "Default components for Thorium Web Epub StatefulReader",
4899
- version: "1.5.7",
4886
+ version: "1.6.0",
4900
4887
  components: {
4901
4888
  actions: {
4902
4889
  ["fullscreen" /* fullscreen */]: {
@@ -6170,7 +6157,7 @@ var createAudioDefaultPlugin = () => {
6170
6157
  id: "audio-core",
6171
6158
  name: "Audio Core Components",
6172
6159
  description: "Default components for Thorium Web Audio StatefulReader",
6173
- version: "1.5.7",
6160
+ version: "1.6.0",
6174
6161
  components: {
6175
6162
  actions: {
6176
6163
  ["settings" /* settings */]: {
@@ -6288,6 +6275,14 @@ var thorium_web_reader_app_default = {
6288
6275
  loading: "thorium_web_reader_app_loading",
6289
6276
  srOnly: "thorium_web_reader_app_srOnly"
6290
6277
  };
6278
+ var isNumericSize = (value) => {
6279
+ return typeof value === "number";
6280
+ };
6281
+ var toPixels = (value) => {
6282
+ if (isNumericSize(value)) return value;
6283
+ if (typeof value === "string" && value.endsWith("px")) return parseFloat(value);
6284
+ return void 0;
6285
+ };
6291
6286
  var useResizablePanel = (panel) => {
6292
6287
  const preferences = useActionsPreferences();
6293
6288
  const { theming } = useSharedPreferences();
@@ -6298,62 +6293,50 @@ var useResizablePanel = (panel) => {
6298
6293
  const profile = useAppSelector((state) => state.reader.profile);
6299
6294
  const actionsMap = useAppSelector((state) => profile ? state.actions.keys[profile] : void 0);
6300
6295
  const actions = useActions(actionsMap || {});
6301
- const previouslyCollapsed = usePrevious(panel?.collapsed);
6302
6296
  const previousWidth = actions.getDockedWidth(panel?.actionKey) || null;
6303
- const width = pref?.width || defaultWidth;
6304
- const minWidth = pref?.minWidth && pref.minWidth < width ? pref.minWidth : defaultWidth < width ? defaultWidth : width;
6305
- const maxWidth = pref?.maxWidth && pref.maxWidth > width ? pref.maxWidth : defaultWidth > width ? defaultWidth : width;
6297
+ const width = pref?.width ?? defaultWidth;
6298
+ const widthPx = toPixels(width);
6299
+ const defaultWidthPx = toPixels(defaultWidth);
6300
+ const minWidthPx = toPixels(pref?.minWidth);
6301
+ const minWidth = widthPx !== void 0 && minWidthPx !== void 0 && minWidthPx < widthPx ? minWidthPx : pref?.minWidth !== void 0 && minWidthPx === void 0 ? pref.minWidth : widthPx !== void 0 && defaultWidthPx !== void 0 && defaultWidthPx < widthPx ? defaultWidth : pref?.minWidth ?? width;
6302
+ const maxWidthPx = toPixels(pref?.maxWidth);
6303
+ const maxWidth = widthPx !== void 0 && maxWidthPx !== void 0 && maxWidthPx > widthPx ? maxWidthPx : pref?.maxWidth !== void 0 && maxWidthPx === void 0 ? pref.maxWidth : widthPx !== void 0 && defaultWidthPx !== void 0 && defaultWidthPx > widthPx ? defaultWidth : pref?.maxWidth ?? width;
6306
6304
  const isPopulated = () => {
6307
6305
  return !!(panel?.active && actions.isOpen(panel?.actionKey));
6308
6306
  };
6309
- const isCollapsed = () => {
6310
- return !!panel?.collapsed;
6311
- };
6312
- const forceExpand = () => {
6313
- return !!(isPopulated() && previouslyCollapsed && !panel?.collapsed);
6314
- };
6315
6307
  const currentKey = () => {
6316
6308
  return panel?.actionKey ?? null;
6317
6309
  };
6318
6310
  const isResizable = () => {
6319
- return isPopulated() ? Math.round(width) > Math.round(minWidth) && Math.round(width) < Math.round(maxWidth) : false;
6311
+ if (!panel?.actionKey) return false;
6312
+ return isNumericSize(width) && isNumericSize(minWidth) && isNumericSize(maxWidth) ? Math.round(width) > Math.round(minWidth) && Math.round(width) < Math.round(maxWidth) : minWidth !== maxWidth;
6320
6313
  };
6321
6314
  const hasDragIndicator = () => {
6322
6315
  return pref?.dragIndicator || false;
6323
6316
  };
6324
- const getWidth = useCallback(() => {
6325
- return previousWidth ? Math.round(previousWidth / window.innerWidth * 100) : Math.round(width / window.innerWidth * 100);
6326
- }, [previousWidth, width]);
6327
- const getMinWidth = useCallback(() => {
6328
- return Math.round(minWidth / window.innerWidth * 100);
6329
- }, [minWidth]);
6330
- const getMaxWidth = useCallback(() => {
6331
- return Math.round(maxWidth / window.innerWidth * 100);
6332
- }, [maxWidth]);
6333
- const getCurrentPxWidth = useCallback((percentage) => {
6334
- let current = Math.round(percentage * window.innerWidth / 100);
6335
- if (current < minWidth) {
6336
- current = minWidth;
6337
- }
6338
- if (current > maxWidth) {
6339
- current = maxWidth;
6340
- }
6341
- return current;
6342
- }, [minWidth, maxWidth]);
6317
+ const getTargetWidth = () => {
6318
+ if (previousWidth == null) return width;
6319
+ if (isNumericSize(minWidth) && previousWidth < minWidth) return minWidth;
6320
+ if (isNumericSize(maxWidth) && previousWidth > maxWidth) return maxWidth;
6321
+ return previousWidth;
6322
+ };
6323
+ const getMinWidth = () => {
6324
+ return minWidth;
6325
+ };
6326
+ const getMaxWidth = () => {
6327
+ return maxWidth;
6328
+ };
6343
6329
  useEffect(() => {
6344
6330
  setPref(panel?.actionKey ? preferences.actionsKeys[panel.actionKey]?.docked || null : null);
6345
6331
  }, [panel?.actionKey, preferences]);
6346
6332
  return {
6347
6333
  currentKey,
6348
6334
  isPopulated,
6349
- isCollapsed,
6350
- forceExpand,
6351
6335
  isResizable,
6352
6336
  hasDragIndicator,
6353
- getWidth,
6337
+ getTargetWidth,
6354
6338
  getMinWidth,
6355
- getMaxWidth,
6356
- getCurrentPxWidth
6339
+ getMaxWidth
6357
6340
  };
6358
6341
  };
6359
6342
  var useDockCleanup = (profile) => {
@@ -6363,8 +6346,10 @@ var useDockCleanup = (profile) => {
6363
6346
  const endActionKey = dock?.["dockingEnd" /* end */]?.actionKey;
6364
6347
  const startStatus = useActionComponentStatus({ actionKey: startActionKey || "" });
6365
6348
  const endStatus = useActionComponentStatus({ actionKey: endActionKey || "" });
6349
+ const { actionsComponentsMap, primaryAudioActionsMap } = usePlugins();
6350
+ const isRegistryPopulated = Object.keys(actionsComponentsMap || {}).length > 0 || Object.keys(primaryAudioActionsMap || {}).length > 0;
6366
6351
  useEffect(() => {
6367
- if (!profile || !dock) return;
6352
+ if (!profile || !dock || !isRegistryPopulated) return;
6368
6353
  if (startActionKey && !startStatus.isComponentRegistered) {
6369
6354
  dispatch(dockAction({
6370
6355
  key: startActionKey,
@@ -6379,12 +6364,11 @@ var useDockCleanup = (profile) => {
6379
6364
  profile
6380
6365
  }));
6381
6366
  }
6382
- }, [profile, dock, startActionKey, endActionKey, startStatus.isComponentRegistered, endStatus.isComponentRegistered, dispatch]);
6367
+ }, [profile, dock, isRegistryPopulated, startActionKey, endActionKey, startStatus.isComponentRegistered, endStatus.isComponentRegistered, dispatch]);
6383
6368
  };
6384
6369
  var DockHandle = ({
6385
6370
  flow,
6386
6371
  isResizable,
6387
- isPopulated,
6388
6372
  hasDragIndicator
6389
6373
  }) => {
6390
6374
  const handleID = `${flow}-resize-handle`;
@@ -6397,12 +6381,11 @@ var DockHandle = ({
6397
6381
  }
6398
6382
  }, [flow, direction]);
6399
6383
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
6400
- PanelResizeHandle,
6384
+ Separator,
6401
6385
  {
6402
6386
  id: handleID,
6403
6387
  className: thorium_web_docking_default.resizeHandle,
6404
6388
  disabled: !isResizable,
6405
- tabIndex: isPopulated ? 0 : -1,
6406
6389
  children: isResizable && hasDragIndicator && /* @__PURE__ */ jsx("div", { className: classNames4(thorium_web_docking_default.resizeHandleGrab, classFromFlow()) })
6407
6390
  }
6408
6391
  ) });
@@ -6410,18 +6393,20 @@ var DockHandle = ({
6410
6393
  var DockPanel = ({
6411
6394
  actionKey,
6412
6395
  flow,
6396
+ dockConfig,
6413
6397
  sizes,
6398
+ targetWidth,
6414
6399
  isResizable,
6415
6400
  isPopulated,
6416
- isCollapsed,
6417
- forceExpand,
6418
6401
  hasDragIndicator,
6419
- profile
6402
+ profile,
6403
+ panelRef
6420
6404
  }) => {
6421
6405
  const { t } = useI18n();
6422
- const panelRef = useRef(null);
6423
6406
  const direction = useAppSelector((state) => state.reader.direction);
6424
6407
  const dispatch = useAppDispatch();
6408
+ const targetWidthRef = useRef(targetWidth);
6409
+ targetWidthRef.current = targetWidth;
6425
6410
  const dockClassName = flow === "dockingEnd" /* end */ && direction === "ltr" /* ltr */ ? thorium_web_reader_app_default.rightDock : thorium_web_reader_app_default.leftDock;
6426
6411
  const makeDockLabel = useCallback(() => {
6427
6412
  let label = "";
@@ -6433,26 +6418,26 @@ var DockPanel = ({
6433
6418
  if (actionKey) {
6434
6419
  if (!isPopulated) {
6435
6420
  label += ` \u2013 ${t("reader.app.docking.dockingClosed", { action: t(`reader.${actionKey}.heading`) })}`;
6436
- } else if (isCollapsed) {
6437
- label += ` \u2013 ${t("reader.app.docking.dockingCollapsed", { action: t(`reader.${actionKey}.heading`) })}`;
6438
6421
  }
6439
6422
  } else {
6440
6423
  label += ` \u2013 ${t("reader.app.docking.dockingEmpty")}`;
6441
6424
  }
6442
6425
  return label;
6443
- }, [flow, direction, isPopulated, isCollapsed, actionKey, t]);
6426
+ }, [flow, direction, isPopulated, actionKey, t]);
6444
6427
  const collapsePanel = useCallback(() => {
6445
- if (panelRef.current) {
6446
- panelRef.current.collapse();
6447
- dispatch(collapseDockPanel({ slot: flow, profile }));
6428
+ try {
6429
+ panelRef.current?.collapse();
6430
+ } catch (error) {
6431
+ console.warn(`Failed to collapse ${flow} dock panel`, error);
6448
6432
  }
6449
- }, [dispatch, flow, profile]);
6433
+ }, [panelRef, flow]);
6450
6434
  const expandPanel = useCallback(() => {
6451
- if (panelRef.current) {
6452
- panelRef.current.expand();
6453
- dispatch(expandDockPanel({ slot: flow, profile }));
6435
+ try {
6436
+ panelRef.current?.resize(targetWidthRef.current);
6437
+ } catch (error) {
6438
+ console.warn(`Failed to expand ${flow} dock panel`, error);
6454
6439
  }
6455
- }, [dispatch, flow, profile]);
6440
+ }, [panelRef, flow]);
6456
6441
  useEffect(() => {
6457
6442
  dispatch(activateDockPanel({ slot: flow, profile }));
6458
6443
  return () => {
@@ -6460,15 +6445,17 @@ var DockPanel = ({
6460
6445
  };
6461
6446
  }, [dispatch, flow, profile]);
6462
6447
  useEffect(() => {
6463
- isPopulated || forceExpand ? expandPanel() : collapsePanel();
6464
- }, [isPopulated, forceExpand, collapsePanel, expandPanel]);
6448
+ const raf = requestAnimationFrame(() => {
6449
+ isPopulated ? expandPanel() : collapsePanel();
6450
+ });
6451
+ return () => cancelAnimationFrame(raf);
6452
+ }, [isPopulated, dockConfig, collapsePanel, expandPanel]);
6465
6453
  return /* @__PURE__ */ jsxs(Fragment, { children: [
6466
6454
  flow === "dockingEnd" /* end */ && /* @__PURE__ */ jsx(
6467
6455
  DockHandle,
6468
6456
  {
6469
6457
  flow: "dockingEnd" /* end */,
6470
6458
  isResizable,
6471
- isPopulated,
6472
6459
  hasDragIndicator
6473
6460
  }
6474
6461
  ),
@@ -6476,21 +6463,14 @@ var DockPanel = ({
6476
6463
  Panel,
6477
6464
  {
6478
6465
  id: `${flow}-panel`,
6479
- order: flow === "dockingEnd" /* end */ ? 3 : 1,
6480
6466
  collapsible: true,
6481
6467
  collapsedSize: 0,
6482
- ref: panelRef,
6483
- defaultSize: isPopulated ? sizes.width : 0,
6468
+ panelRef,
6469
+ defaultSize: 0,
6484
6470
  minSize: sizes.minWidth,
6485
6471
  maxSize: sizes.maxWidth,
6486
- onCollapse: collapsePanel,
6487
- onExpand: expandPanel,
6488
- onResize: (size) => size !== 0 && dispatch(setDockPanelWidth({
6489
- key: flow,
6490
- width: sizes.getCurrentPxWidth(size),
6491
- profile
6492
- })),
6493
- inert: isCollapsed,
6472
+ groupResizeBehavior: "preserve-pixel-size",
6473
+ inert: !isPopulated,
6494
6474
  children: /* @__PURE__ */ jsx(
6495
6475
  "div",
6496
6476
  {
@@ -6506,7 +6486,6 @@ var DockPanel = ({
6506
6486
  {
6507
6487
  flow: "dockingStart" /* start */,
6508
6488
  isResizable,
6509
- isPopulated,
6510
6489
  hasDragIndicator
6511
6490
  }
6512
6491
  )
@@ -6517,60 +6496,104 @@ var StatefulDockingWrapper = ({
6517
6496
  }) => {
6518
6497
  const preferences = useActionsPreferences();
6519
6498
  const profile = useAppSelector((state) => state.reader.profile);
6499
+ const dispatch = useAppDispatch();
6520
6500
  useDockCleanup(profile);
6521
6501
  const dockingStart = useAppSelector((state) => profile && state.actions.dock[profile] ? state.actions.dock[profile]["dockingStart" /* start */] : void 0);
6522
6502
  const dockingEnd = useAppSelector((state) => profile && state.actions.dock[profile] ? state.actions.dock[profile]["dockingEnd" /* end */] : void 0);
6523
6503
  const startPanel = useResizablePanel(dockingStart);
6524
6504
  const endPanel = useResizablePanel(dockingEnd);
6505
+ const startPanelRef = useRef(null);
6506
+ const endPanelRef = useRef(null);
6507
+ const startActionKey = startPanel.currentKey();
6508
+ const endActionKey = endPanel.currentKey();
6509
+ const isStartPopulated = startPanel.isPopulated();
6510
+ const isEndPopulated = endPanel.isPopulated();
6511
+ const handleLayoutChanged = useCallback((_layout, meta) => {
6512
+ if (!profile) return;
6513
+ [
6514
+ ["dockingStart" /* start */, startPanelRef, startActionKey, isStartPopulated],
6515
+ ["dockingEnd" /* end */, endPanelRef, endActionKey, isEndPopulated]
6516
+ ].forEach(([flow, ref, actionKey, isPopulated]) => {
6517
+ const panel = ref.current;
6518
+ if (!panel) return;
6519
+ let inPixels;
6520
+ try {
6521
+ inPixels = panel.getSize().inPixels;
6522
+ } catch (error) {
6523
+ console.warn(`Failed to read ${flow} dock panel size`, error);
6524
+ return;
6525
+ }
6526
+ if (!meta.isUserInteraction) {
6527
+ if (!isPopulated && inPixels !== 0) {
6528
+ try {
6529
+ panel.collapse();
6530
+ } catch (error) {
6531
+ console.warn(`Failed to collapse ${flow} dock panel`, error);
6532
+ }
6533
+ }
6534
+ return;
6535
+ }
6536
+ if (!actionKey) return;
6537
+ if (inPixels === 0) {
6538
+ dispatch(setActionOpen({ key: actionKey, isOpen: false, profile }));
6539
+ return;
6540
+ }
6541
+ if (!isPopulated) {
6542
+ dispatch(setActionOpen({ key: actionKey, isOpen: true, profile }));
6543
+ }
6544
+ dispatch(setDockPanelWidth({ key: flow, width: inPixels, profile }));
6545
+ });
6546
+ }, [profile, dispatch, startActionKey, endActionKey, isStartPopulated, isEndPopulated]);
6525
6547
  const breakpoint = useAppSelector((state) => state.theming.breakpoint);
6548
+ const dockingPref = preferences.docking.dock;
6549
+ const dockingMap = useMemo(() => makeBreakpointsMap({
6550
+ defaultValue: "both" /* both */,
6551
+ fromEnum: ThDockingTypes,
6552
+ pref: dockingPref,
6553
+ disabledValue: "none" /* none */
6554
+ }), [dockingPref]);
6555
+ const dockConfig = breakpoint && dockingMap[breakpoint] || "both" /* both */;
6556
+ const hasStartSlot = dockConfig === "both" /* both */ || dockConfig === "start" /* start */;
6557
+ const hasEndSlot = dockConfig === "both" /* both */ || dockConfig === "end" /* end */;
6526
6558
  if (!preferences.docking.dock) {
6527
6559
  return /* @__PURE__ */ jsx(Fragment, { children });
6528
6560
  } else {
6529
- const dockingMap2 = makeBreakpointsMap({
6530
- defaultValue: "both" /* both */,
6531
- fromEnum: ThDockingTypes,
6532
- pref: preferences.docking.dock,
6533
- disabledValue: "none" /* none */
6534
- });
6535
- const dockConfig = breakpoint && dockingMap2[breakpoint] || "both" /* both */;
6536
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(PanelGroup, { direction: "horizontal", children: [
6537
- (dockConfig === "both" /* both */ || dockConfig === "start" /* start */) && profile && /* @__PURE__ */ jsx(
6561
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Group, { id: "docking-panel-group", orientation: "horizontal", onLayoutChanged: handleLayoutChanged, children: [
6562
+ hasStartSlot && profile && /* @__PURE__ */ jsx(
6538
6563
  DockPanel,
6539
6564
  {
6540
- actionKey: startPanel.currentKey(),
6565
+ actionKey: startActionKey,
6541
6566
  flow: "dockingStart" /* start */,
6567
+ dockConfig,
6542
6568
  sizes: {
6543
- width: startPanel.getWidth(),
6544
6569
  minWidth: startPanel.getMinWidth(),
6545
- maxWidth: startPanel.getMaxWidth(),
6546
- getCurrentPxWidth: startPanel.getCurrentPxWidth
6570
+ maxWidth: startPanel.getMaxWidth()
6547
6571
  },
6572
+ targetWidth: startPanel.getTargetWidth(),
6548
6573
  isResizable: startPanel.isResizable(),
6549
- isPopulated: startPanel.isPopulated(),
6550
- isCollapsed: startPanel.isCollapsed(),
6551
- forceExpand: startPanel.forceExpand(),
6574
+ isPopulated: isStartPopulated,
6552
6575
  hasDragIndicator: startPanel.hasDragIndicator(),
6553
- profile
6576
+ profile,
6577
+ panelRef: startPanelRef
6554
6578
  }
6555
6579
  ),
6556
- /* @__PURE__ */ jsx(Panel, { id: "main-panel", order: 2, children }),
6557
- (dockConfig === "both" /* both */ || dockConfig === "end" /* end */) && profile && /* @__PURE__ */ jsx(
6580
+ /* @__PURE__ */ jsx(Panel, { id: "main-panel", children }),
6581
+ hasEndSlot && profile && /* @__PURE__ */ jsx(
6558
6582
  DockPanel,
6559
6583
  {
6560
- actionKey: endPanel.currentKey(),
6584
+ actionKey: endActionKey,
6561
6585
  flow: "dockingEnd" /* end */,
6586
+ dockConfig,
6562
6587
  sizes: {
6563
- width: endPanel.getWidth(),
6564
6588
  minWidth: endPanel.getMinWidth(),
6565
- maxWidth: endPanel.getMaxWidth(),
6566
- getCurrentPxWidth: endPanel.getCurrentPxWidth
6589
+ maxWidth: endPanel.getMaxWidth()
6567
6590
  },
6591
+ targetWidth: endPanel.getTargetWidth(),
6568
6592
  isResizable: endPanel.isResizable(),
6569
- isPopulated: endPanel.isPopulated(),
6570
- isCollapsed: endPanel.isCollapsed(),
6571
- forceExpand: endPanel.forceExpand(),
6593
+ isPopulated: isEndPopulated,
6572
6594
  hasDragIndicator: endPanel.hasDragIndicator(),
6573
- profile
6595
+ profile,
6596
+ panelRef: endPanelRef
6574
6597
  }
6575
6598
  )
6576
6599
  ] }) });
@@ -6586,18 +6609,21 @@ var useFocusedDockableKey = () => {
6586
6609
  if (!dockable || dockable === "none" /* none */) return false;
6587
6610
  return dockingKey === "dockingTransient" /* transient */ || dockingKey === "dockingStart" /* start */ && (dockable === "start" /* start */ || dockable === "both" /* both */) || dockingKey === "dockingEnd" /* end */ && (dockable === "end" /* end */ || dockable === "both" /* both */);
6588
6611
  };
6612
+ const resolve = (key) => {
6613
+ return { key, reserved: isReservedByPref(actionsKeys[key]) };
6614
+ };
6589
6615
  let el = active;
6590
6616
  while (el) {
6591
6617
  const id = el.getAttribute("id");
6592
6618
  if (id) {
6593
- if (checkKey(id)) return id;
6619
+ if (checkKey(id)) return resolve(id);
6594
6620
  const keyFromId = Object.keys(actionsKeys).find((k) => id.startsWith(`${k}-`));
6595
- if (keyFromId && checkKey(keyFromId)) return keyFromId;
6621
+ if (keyFromId && checkKey(keyFromId)) return resolve(keyFromId);
6596
6622
  }
6597
6623
  const dataKey = el.getAttribute("data-key");
6598
6624
  if (dataKey) {
6599
6625
  const key = dataKey.slice(dataKey.lastIndexOf("-") + 1);
6600
- if (key && checkKey(key)) return key;
6626
+ if (key && checkKey(key)) return resolve(key);
6601
6627
  }
6602
6628
  el = el.parentElement;
6603
6629
  }
@@ -6833,5 +6859,5 @@ var useReaderHeaderBase = (actionKeys) => {
6833
6859
  };
6834
6860
 
6835
6861
  export { NavPeripheralType, NavigatorProvider, ORDERED_LINE_HEIGHT_OPTIONS, 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, ThPluginProvider, ThPluginRegistry, UnstableStatefulFontWeight, ZOOM_IN_KEY_COMBOS, ZOOM_OUT_KEY_COMBOS, createAudioDefaultPlugin, createDefaultPlugin, fromActionPeripheralType, fromDockingPeripheralType, thorium_web_button_default, thorium_web_overflow_default, thorium_web_reader_app_default, thorium_web_reader_header_default, toActionPeripheralType, toDockingPeripheralType, useActionComponentStatus, useDocking, useEffectiveRange, useFocusedDockableKey, useGridNavigation, useGridTemplate, useIsScroll, useLineHeight, useNavigator, usePlaceholder, usePlugins, usePositionStorage, usePublication, useReaderHeaderBase, useReaderSetting, useReaderTransitions, useSettingsComponentStatus, useSpacingPresets, useTocEntryTracking, useTocTreeBuilder };
6836
- //# sourceMappingURL=chunk-C6LWEQL2.mjs.map
6837
- //# sourceMappingURL=chunk-C6LWEQL2.mjs.map
6862
+ //# sourceMappingURL=chunk-7X5KT42Z.mjs.map
6863
+ //# sourceMappingURL=chunk-7X5KT42Z.mjs.map