@edrlab/thorium-web 1.2.1 → 1.3.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 (97) hide show
  1. package/dist/{ThPreferencesAdapter-DrZ5_6Dv.d.mts → ThPreferencesAdapter-D0rzsGRl.d.mts} +50 -13
  2. package/dist/{ThSettingsWrapper-8Kx0SnH4.d.mts → ThSettingsWrapper-BXuRgdqp.d.mts} +42 -4
  3. package/dist/{actions-D2CHvCHu.d.mts → actions-BLAr0oaM.d.mts} +16 -4
  4. package/dist/{actionsReducer-kc-S130w.d.mts → actionsReducer-BhG1wicI.d.mts} +37 -12
  5. package/dist/chunk-3GDQP6AS.mjs +14 -0
  6. package/dist/chunk-3GDQP6AS.mjs.map +1 -0
  7. package/dist/{chunk-72XCX5TD.mjs → chunk-3LDWKC5N.mjs} +13 -8
  8. package/dist/chunk-3LDWKC5N.mjs.map +1 -0
  9. package/dist/{chunk-NYZBHYW2.mjs → chunk-4ODYHZKD.mjs} +343 -38
  10. package/dist/chunk-4ODYHZKD.mjs.map +1 -0
  11. package/dist/{chunk-QPE574OW.mjs → chunk-4TVEDX7L.mjs} +23 -32
  12. package/dist/chunk-4TVEDX7L.mjs.map +1 -0
  13. package/dist/chunk-7CGMWOZN.mjs +20 -0
  14. package/dist/chunk-7CGMWOZN.mjs.map +1 -0
  15. package/dist/{chunk-7NEQAW7J.mjs → chunk-C236BQQB.mjs} +656 -917
  16. package/dist/chunk-C236BQQB.mjs.map +1 -0
  17. package/dist/{chunk-PXAUQJEU.mjs → chunk-D7MFLHXV.mjs} +2267 -1599
  18. package/dist/chunk-D7MFLHXV.mjs.map +1 -0
  19. package/dist/{chunk-47AIIJFO.mjs → chunk-ITDBOMY5.mjs} +3 -3
  20. package/dist/{chunk-47AIIJFO.mjs.map → chunk-ITDBOMY5.mjs.map} +1 -1
  21. package/dist/{chunk-XVSFXHYB.mjs → chunk-L4XGZAZ5.mjs} +23 -20
  22. package/dist/chunk-L4XGZAZ5.mjs.map +1 -0
  23. package/dist/chunk-OWHP7ONM.mjs +134 -0
  24. package/dist/chunk-OWHP7ONM.mjs.map +1 -0
  25. package/dist/{chunk-P4V3LA5R.mjs → chunk-RRVLWDT3.mjs} +10 -7
  26. package/dist/chunk-RRVLWDT3.mjs.map +1 -0
  27. package/dist/chunk-T2E6MRVP.mjs +862 -0
  28. package/dist/chunk-T2E6MRVP.mjs.map +1 -0
  29. package/dist/chunk-TEZB4ULX.mjs +57 -0
  30. package/dist/chunk-TEZB4ULX.mjs.map +1 -0
  31. package/dist/chunk-UCTMVCW7.mjs +833 -0
  32. package/dist/chunk-UCTMVCW7.mjs.map +1 -0
  33. package/dist/chunk-WECWPYZB.mjs +1950 -0
  34. package/dist/chunk-WECWPYZB.mjs.map +1 -0
  35. package/dist/{chunk-4VHEHMJN.mjs → chunk-XBZWGRDM.mjs} +228 -94
  36. package/dist/chunk-XBZWGRDM.mjs.map +1 -0
  37. package/dist/{chunk-K3K7TUWM.mjs → chunk-YZ3KCMKY.mjs} +237 -83
  38. package/dist/chunk-YZ3KCMKY.mjs.map +1 -0
  39. package/dist/components/Audio/index.css +1858 -0
  40. package/dist/components/Audio/index.css.map +1 -0
  41. package/dist/components/Audio/index.d.mts +103 -0
  42. package/dist/components/Audio/index.mjs +23 -0
  43. package/dist/components/Audio/index.mjs.map +1 -0
  44. package/dist/components/Epub/index.css +365 -9
  45. package/dist/components/Epub/index.css.map +1 -1
  46. package/dist/components/Epub/index.d.mts +17 -19
  47. package/dist/components/Epub/index.mjs +15 -10
  48. package/dist/components/Misc/index.css +5 -2
  49. package/dist/components/Misc/index.css.map +1 -1
  50. package/dist/components/Misc/index.mjs +4 -132
  51. package/dist/components/Misc/index.mjs.map +1 -1
  52. package/dist/components/Reader/index.css +1022 -183
  53. package/dist/components/Reader/index.css.map +1 -1
  54. package/dist/components/Reader/index.d.mts +16 -16
  55. package/dist/components/Reader/index.mjs +121 -22
  56. package/dist/components/Reader/index.mjs.map +1 -1
  57. package/dist/components/WebPub/index.css +365 -9
  58. package/dist/components/WebPub/index.css.map +1 -1
  59. package/dist/components/WebPub/index.d.mts +16 -16
  60. package/dist/components/WebPub/index.mjs +15 -10
  61. package/dist/core/Components/index.d.mts +64 -15
  62. package/dist/core/Components/index.mjs +2 -1
  63. package/dist/core/Helpers/index.d.mts +2 -2
  64. package/dist/core/Helpers/index.mjs +4 -2
  65. package/dist/core/Hooks/index.d.mts +7 -8
  66. package/dist/core/Hooks/index.mjs +3 -1
  67. package/dist/i18n/index.mjs +4 -5
  68. package/dist/lib/index.d.mts +159 -15
  69. package/dist/lib/index.mjs +4 -2
  70. package/dist/lib-M3PPQDJJ.mjs +6548 -0
  71. package/dist/lib-M3PPQDJJ.mjs.map +1 -0
  72. package/dist/locales/en/thorium-web.json +22 -0
  73. package/dist/next-lib/index.mjs +2 -0
  74. package/dist/next-lib/index.mjs.map +1 -1
  75. package/dist/preferences/index.d.mts +111 -13
  76. package/dist/preferences/index.mjs +6 -3
  77. package/dist/{settingsReducer-C1wwCAMv.d.mts → settingsReducer-Bu1zeveu.d.mts} +1 -1
  78. package/dist/{ui-CamWuqOo.d.mts → ui-nBv8gfr0.d.mts} +20 -1
  79. package/dist/useAudioNavigator-C5aW4-eT.d.mts +133 -0
  80. package/dist/{useContrast-D6sjPjxy.d.mts → useContrast-2t429O9O.d.mts} +16 -8
  81. package/dist/usePreferences-VaBf46eP.d.mts +230 -0
  82. package/dist/useReaderTransitions-JDzlBFsu.d.mts +530 -0
  83. package/dist/{useTimeline-DyMx_aWY.d.mts → useTimeline-DCZ1qoCO.d.mts} +4 -2
  84. package/package.json +15 -11
  85. package/dist/chunk-4VHEHMJN.mjs.map +0 -1
  86. package/dist/chunk-72XCX5TD.mjs.map +0 -1
  87. package/dist/chunk-7NEQAW7J.mjs.map +0 -1
  88. package/dist/chunk-K3K7TUWM.mjs.map +0 -1
  89. package/dist/chunk-NYZBHYW2.mjs.map +0 -1
  90. package/dist/chunk-P4V3LA5R.mjs.map +0 -1
  91. package/dist/chunk-PXAUQJEU.mjs.map +0 -1
  92. package/dist/chunk-QPE574OW.mjs.map +0 -1
  93. package/dist/chunk-XVSFXHYB.mjs.map +0 -1
  94. package/dist/useEpubNavigator-CwHJfoiV.d.mts +0 -42
  95. package/dist/usePreferences-BXFJbval.d.mts +0 -43
  96. package/dist/useReaderTransitions-guT-eA-Q.d.mts +0 -365
  97. package/dist/useWebPubNavigator-CuSNQKMw.d.mts +0 -39
@@ -1,11 +1,7 @@
1
- import { propsToCSSVars } from './chunk-XVSFXHYB.mjs';
2
- import { useBreakpoints, useForcedColors, useMonochrome, useReducedMotion, useReducedTransparency } from './chunk-GFSLVQIG.mjs';
3
- import { useColorScheme, useContrast } from './chunk-NQ2ZSGCX.mjs';
4
1
  import { isSupportedLocale, supportedLocales } from './chunk-B3WDMWCT.mjs';
5
2
  import fontStacks from '@readium/css/css/vars/fontStacks.json';
6
3
  import ReadiumCSSColors from '@readium/css/css/vars/colors.json';
7
- import { createContext, useMemo, useState, useCallback, useEffect, useContext, useRef } from 'react';
8
- import { jsx } from 'react/jsx-runtime';
4
+ import { createContext, useContext } from 'react';
9
5
 
10
6
  // src/preferences/models/actions.ts
11
7
  var ThActionsKeys = /* @__PURE__ */ ((ThActionsKeys3) => {
@@ -30,6 +26,8 @@ var ThDockingTypes = /* @__PURE__ */ ((ThDockingTypes2) => {
30
26
  })(ThDockingTypes || {});
31
27
  var ThSheetTypes = /* @__PURE__ */ ((ThSheetTypes3) => {
32
28
  ThSheetTypes3["popover"] = "popover";
29
+ ThSheetTypes3["compactPopover"] = "compactPopover";
30
+ ThSheetTypes3["modal"] = "modal";
33
31
  ThSheetTypes3["fullscreen"] = "fullscreen";
34
32
  ThSheetTypes3["dockedStart"] = "docked start";
35
33
  ThSheetTypes3["dockedEnd"] = "docked end";
@@ -108,123 +106,307 @@ var defaultJumpToPositionAction = {
108
106
  }
109
107
  };
110
108
 
111
- // src/preferences/helpers/buildThemeObject.ts
112
- var buildThemeObject = ({
113
- theme,
114
- themeKeys,
115
- systemThemes,
116
- colorScheme
117
- }) => {
118
- if (!theme) {
119
- return {};
120
- }
121
- if (theme === "auto" && colorScheme && systemThemes) {
122
- theme = colorScheme === "dark" /* dark */ ? systemThemes.dark : systemThemes.light;
123
- }
124
- let themeProps = {};
125
- const themeToken = themeKeys[theme];
126
- if (themeToken) {
127
- themeProps = {
128
- backgroundColor: themeToken.background,
129
- textColor: themeToken.text,
130
- linkColor: themeToken.link,
131
- selectionBackgroundColor: themeToken.select,
132
- selectionTextColor: themeToken.onSelect,
133
- visitedColor: themeToken.visited
134
- };
135
- } else {
136
- console.warn(`Theme key "${String(theme)}" not found in themeKeys.`);
137
- themeProps = {
138
- backgroundColor: null,
139
- textColor: null,
140
- linkColor: null,
141
- selectionBackgroundColor: null,
142
- selectionTextColor: null,
143
- visitedColor: null
144
- };
109
+ // src/preferences/models/settings.ts
110
+ var ThSettingsKeys = /* @__PURE__ */ ((ThSettingsKeys2) => {
111
+ ThSettingsKeys2["columns"] = "columns";
112
+ ThSettingsKeys2["fontFamily"] = "fontFamily";
113
+ ThSettingsKeys2["fontWeight"] = "fontWeight";
114
+ ThSettingsKeys2["hyphens"] = "hyphens";
115
+ ThSettingsKeys2["layout"] = "layout";
116
+ ThSettingsKeys2["letterSpacing"] = "letterSpacing";
117
+ ThSettingsKeys2["lineHeight"] = "lineHeight";
118
+ ThSettingsKeys2["paragraphIndent"] = "paragraphIndent";
119
+ ThSettingsKeys2["paragraphSpacing"] = "paragraphSpacing";
120
+ ThSettingsKeys2["publisherStyles"] = "publisherStyles";
121
+ ThSettingsKeys2["spacingGroup"] = "spacingGroup";
122
+ ThSettingsKeys2["spacingPresets"] = "spacingPresets";
123
+ ThSettingsKeys2["textAlign"] = "textAlign";
124
+ ThSettingsKeys2["textGroup"] = "textGroup";
125
+ ThSettingsKeys2["textNormalize"] = "textNormalize";
126
+ ThSettingsKeys2["theme"] = "theme";
127
+ ThSettingsKeys2["wordSpacing"] = "wordSpacing";
128
+ ThSettingsKeys2["zoom"] = "zoom";
129
+ return ThSettingsKeys2;
130
+ })(ThSettingsKeys || {});
131
+ var ThTextSettingsKeys = /* @__PURE__ */ ((ThTextSettingsKeys3) => {
132
+ ThTextSettingsKeys3["fontFamily"] = "fontFamily";
133
+ ThTextSettingsKeys3["fontWeight"] = "fontWeight";
134
+ ThTextSettingsKeys3["hyphens"] = "hyphens";
135
+ ThTextSettingsKeys3["textAlign"] = "textAlign";
136
+ ThTextSettingsKeys3["textNormalize"] = "textNormalize";
137
+ return ThTextSettingsKeys3;
138
+ })(ThTextSettingsKeys || {});
139
+ var ThSpacingSettingsKeys = /* @__PURE__ */ ((ThSpacingSettingsKeys3) => {
140
+ ThSpacingSettingsKeys3["letterSpacing"] = "letterSpacing";
141
+ ThSpacingSettingsKeys3["lineHeight"] = "lineHeight";
142
+ ThSpacingSettingsKeys3["paragraphIndent"] = "paragraphIndent";
143
+ ThSpacingSettingsKeys3["paragraphSpacing"] = "paragraphSpacing";
144
+ ThSpacingSettingsKeys3["publisherStyles"] = "publisherStyles";
145
+ ThSpacingSettingsKeys3["spacingPresets"] = "spacingPresets";
146
+ ThSpacingSettingsKeys3["wordSpacing"] = "wordSpacing";
147
+ return ThSpacingSettingsKeys3;
148
+ })(ThSpacingSettingsKeys || {});
149
+ var ThSettingsContainerKeys = /* @__PURE__ */ ((ThSettingsContainerKeys2) => {
150
+ ThSettingsContainerKeys2["initial"] = "initial";
151
+ ThSettingsContainerKeys2["text"] = "text";
152
+ ThSettingsContainerKeys2["spacing"] = "spacing";
153
+ return ThSettingsContainerKeys2;
154
+ })(ThSettingsContainerKeys || {});
155
+ var ThSettingsRangeVariant = /* @__PURE__ */ ((ThSettingsRangeVariant2) => {
156
+ ThSettingsRangeVariant2["slider"] = "slider";
157
+ ThSettingsRangeVariant2["incrementedSlider"] = "incrementedSlider";
158
+ ThSettingsRangeVariant2["numberField"] = "numberField";
159
+ ThSettingsRangeVariant2["sliderWithPresets"] = "sliderWithPresets";
160
+ ThSettingsRangeVariant2["presetsGroup"] = "presetsGroup";
161
+ return ThSettingsRangeVariant2;
162
+ })(ThSettingsRangeVariant || {});
163
+ var ThSettingsRangePlaceholder = /* @__PURE__ */ ((ThSettingsRangePlaceholder2) => {
164
+ ThSettingsRangePlaceholder2["range"] = "range";
165
+ ThSettingsRangePlaceholder2["none"] = "none";
166
+ return ThSettingsRangePlaceholder2;
167
+ })(ThSettingsRangePlaceholder || {});
168
+ var ThSpacingPresetKeys = /* @__PURE__ */ ((ThSpacingPresetKeys3) => {
169
+ ThSpacingPresetKeys3["publisher"] = "publisher";
170
+ ThSpacingPresetKeys3["tight"] = "tight";
171
+ ThSpacingPresetKeys3["balanced"] = "balanced";
172
+ ThSpacingPresetKeys3["loose"] = "loose";
173
+ ThSpacingPresetKeys3["accessible"] = "accessible";
174
+ ThSpacingPresetKeys3["custom"] = "custom";
175
+ return ThSpacingPresetKeys3;
176
+ })(ThSpacingPresetKeys || {});
177
+ var ThLayoutOptions = /* @__PURE__ */ ((ThLayoutOptions2) => {
178
+ ThLayoutOptions2["scroll"] = "scroll_option";
179
+ ThLayoutOptions2["paginated"] = "page_option";
180
+ return ThLayoutOptions2;
181
+ })(ThLayoutOptions || {});
182
+ var ThTextAlignOptions = /* @__PURE__ */ ((ThTextAlignOptions2) => {
183
+ ThTextAlignOptions2["publisher"] = "publisher";
184
+ ThTextAlignOptions2["start"] = "start";
185
+ ThTextAlignOptions2["justify"] = "justify";
186
+ return ThTextAlignOptions2;
187
+ })(ThTextAlignOptions || {});
188
+ var ThLineHeightOptions = /* @__PURE__ */ ((ThLineHeightOptions3) => {
189
+ ThLineHeightOptions3["publisher"] = "publisher";
190
+ ThLineHeightOptions3["small"] = "small";
191
+ ThLineHeightOptions3["medium"] = "medium";
192
+ ThLineHeightOptions3["large"] = "large";
193
+ return ThLineHeightOptions3;
194
+ })(ThLineHeightOptions || {});
195
+ var defaultTextSettingsMain = ["fontFamily" /* fontFamily */];
196
+ var defaultTextSettingsSubpanel = [
197
+ "fontFamily" /* fontFamily */,
198
+ "textAlign" /* textAlign */,
199
+ "hyphens" /* hyphens */,
200
+ "fontWeight" /* fontWeight */,
201
+ "textNormalize" /* textNormalize */
202
+ ];
203
+ var defaultSpacingSettingsMain = [
204
+ "spacingPresets" /* spacingPresets */
205
+ ];
206
+ var defaultSpacingSettingsSubpanel = [
207
+ "spacingPresets" /* spacingPresets */,
208
+ "lineHeight" /* lineHeight */,
209
+ "paragraphSpacing" /* paragraphSpacing */,
210
+ "paragraphIndent" /* paragraphIndent */,
211
+ "wordSpacing" /* wordSpacing */,
212
+ "letterSpacing" /* letterSpacing */
213
+ ];
214
+ var defaultSpacingPresetsOrder = [
215
+ "publisher" /* publisher */,
216
+ "accessible" /* accessible */,
217
+ "custom" /* custom */,
218
+ "tight" /* tight */,
219
+ "balanced" /* balanced */,
220
+ "loose" /* loose */
221
+ ];
222
+ var defaultParagraphSpacing = {
223
+ variant: "numberField" /* numberField */,
224
+ placeholder: "range" /* range */,
225
+ range: [0, 3],
226
+ step: 0.25
227
+ };
228
+ var defaultParagraphIndent = {
229
+ variant: "numberField" /* numberField */,
230
+ placeholder: "range" /* range */,
231
+ range: [0, 2],
232
+ step: 0.25
233
+ };
234
+ var defaultWordSpacing = {
235
+ variant: "numberField" /* numberField */,
236
+ placeholder: "range" /* range */,
237
+ range: [0, 1],
238
+ step: 0.1
239
+ };
240
+ var defaultLetterSpacing = {
241
+ variant: "numberField" /* numberField */,
242
+ placeholder: "range" /* range */,
243
+ range: [0, 0.5],
244
+ step: 0.05
245
+ };
246
+ var defaultLineHeights = {
247
+ ["small" /* small */]: 1.35,
248
+ ["medium" /* medium */]: 1.5,
249
+ ["large" /* large */]: 1.75
250
+ };
251
+ var defaultZoom = {
252
+ variant: "numberField" /* numberField */,
253
+ placeholder: "range" /* range */,
254
+ range: [0.7, 4],
255
+ step: 0.05
256
+ };
257
+ var defaultSpacingPresets = {
258
+ ["tight" /* tight */]: {
259
+ ["lineHeight" /* lineHeight */]: "small" /* small */,
260
+ ["paragraphSpacing" /* paragraphSpacing */]: 0.25,
261
+ ["paragraphIndent" /* paragraphIndent */]: 1
262
+ },
263
+ ["balanced" /* balanced */]: {
264
+ ["lineHeight" /* lineHeight */]: "medium" /* medium */,
265
+ ["paragraphSpacing" /* paragraphSpacing */]: 1,
266
+ ["paragraphIndent" /* paragraphIndent */]: 1
267
+ },
268
+ ["loose" /* loose */]: {
269
+ ["lineHeight" /* lineHeight */]: "large" /* large */,
270
+ ["paragraphSpacing" /* paragraphSpacing */]: 1.5,
271
+ ["paragraphIndent" /* paragraphIndent */]: 1
272
+ },
273
+ ["accessible" /* accessible */]: {
274
+ ["lineHeight" /* lineHeight */]: "large" /* large */,
275
+ ["paragraphSpacing" /* paragraphSpacing */]: 2.5,
276
+ ["paragraphIndent" /* paragraphIndent */]: 1,
277
+ ["letterSpacing" /* letterSpacing */]: 0.1,
278
+ ["wordSpacing" /* wordSpacing */]: 0.3
145
279
  }
146
- return themeProps;
147
280
  };
148
281
 
149
- // src/preferences/helpers/fontPref/bunnyFonts.ts
150
- var DEFAULT_FALLBACK = "sans-serif";
151
- var createDefinitionsFromBunnyFonts = (params) => {
152
- const { cssUrl, options } = params;
153
- const { fallbacks, order, labels } = options || {};
154
- const processedUrl = cssUrl.includes("@import") ? cssUrl.match(/@import\s+url\(['"]?([^'")]+)['"]?\)/i)?.[1] || cssUrl : cssUrl.includes("href=") ? cssUrl.match(/href=["']([^"']+)["']/)?.[1] || cssUrl : cssUrl;
155
- const url = new URL(processedUrl);
156
- if (!url.hostname.includes("fonts.bunny.net")) {
157
- throw new Error("Invalid Bunny Fonts URL");
158
- }
159
- const familyParam = url.searchParams.get("family");
160
- if (!familyParam) {
161
- throw new Error("No family parameter found in Bunny Fonts URL");
162
- }
163
- const fontEntries = familyParam.split("|").map((familyStr) => {
164
- const [familyName, weightsStr = ""] = familyStr.split(":");
165
- if (!familyName) {
166
- throw new Error(`Invalid font family format: ${familyStr}`);
282
+ // src/preferences/models/audio.ts
283
+ var ThAudioActionKeys = /* @__PURE__ */ ((ThAudioActionKeys2) => {
284
+ ThAudioActionKeys2["toc"] = "audio.toc";
285
+ ThAudioActionKeys2["volume"] = "audio.volume";
286
+ ThAudioActionKeys2["playbackRate"] = "audio.playbackRate";
287
+ ThAudioActionKeys2["sleepTimer"] = "audio.sleepTimer";
288
+ ThAudioActionKeys2["remotePlayback"] = "audio.remotePlayback";
289
+ return ThAudioActionKeys2;
290
+ })(ThAudioActionKeys || {});
291
+ var ThAudioKeys = /* @__PURE__ */ ((ThAudioKeys2) => {
292
+ ThAudioKeys2["theme"] = "theme";
293
+ ThAudioKeys2["volume"] = "volume";
294
+ ThAudioKeys2["playbackRate"] = "playbackRate";
295
+ ThAudioKeys2["skipBackwardInterval"] = "skipBackwardInterval";
296
+ ThAudioKeys2["skipForwardInterval"] = "skipForwardInterval";
297
+ ThAudioKeys2["skipInterval"] = "skipInterval";
298
+ ThAudioKeys2["autoPlay"] = "autoPlay";
299
+ ThAudioKeys2["sleepTimer"] = "sleepTimer";
300
+ return ThAudioKeys2;
301
+ })(ThAudioKeys || {});
302
+ var ThSettingsTimerVariant = /* @__PURE__ */ ((ThSettingsTimerVariant2) => {
303
+ ThSettingsTimerVariant2["presetList"] = "presetList";
304
+ ThSettingsTimerVariant2["durationField"] = "durationField";
305
+ return ThSettingsTimerVariant2;
306
+ })(ThSettingsTimerVariant || {});
307
+ var defaultAudioVolume = {
308
+ variant: "slider" /* slider */,
309
+ range: [0, 1],
310
+ step: 0.1,
311
+ placeholder: "range" /* range */
312
+ };
313
+ var defaultAudioPlaybackRate = {
314
+ variant: "sliderWithPresets" /* sliderWithPresets */,
315
+ range: [0.5, 4],
316
+ step: 0.05,
317
+ placeholder: "range" /* range */,
318
+ presets: [0.75, 1, 1.25, 1.5, 1.75, 2]
319
+ };
320
+ var defaultAudioSkipBackwardInterval = {
321
+ variant: "presetsGroup" /* presetsGroup */,
322
+ range: [5, 60],
323
+ step: 5,
324
+ placeholder: "range" /* range */,
325
+ presets: [5, 10, 30]
326
+ };
327
+ var defaultAudioSkipForwardInterval = {
328
+ variant: "presetsGroup" /* presetsGroup */,
329
+ range: [5, 60],
330
+ step: 5,
331
+ placeholder: "range" /* range */,
332
+ presets: [5, 10, 30]
333
+ };
334
+ var defaultAudioSkipInterval = {
335
+ variant: "presetsGroup" /* presetsGroup */,
336
+ range: [5, 60],
337
+ step: 5,
338
+ placeholder: "range" /* range */,
339
+ presets: [5, 10, 30]
340
+ };
341
+ var defaultAudioSleepTimer = {
342
+ variant: "durationField" /* durationField */,
343
+ maxHours: 23
344
+ };
345
+ var defaultAudioSleepTimerPresetList = {
346
+ variant: "presetList" /* presetList */,
347
+ presets: [15, 30, 45, 60, 90, "endOfFragment", "endOfResource"]
348
+ };
349
+ var defaultAudioVolumeAction = {
350
+ visibility: "always" /* always */,
351
+ shortcut: null,
352
+ sheet: {
353
+ defaultSheet: "compactPopover" /* compactPopover */,
354
+ breakpoints: {}
355
+ },
356
+ docked: { dockable: "none" /* none */ }
357
+ };
358
+ var defaultAudioPlaybackRateAction = {
359
+ visibility: "always" /* always */,
360
+ shortcut: null,
361
+ sheet: {
362
+ defaultSheet: "compactPopover" /* compactPopover */,
363
+ breakpoints: { ["compact" /* compact */]: "bottomSheet" /* bottomSheet */ }
364
+ },
365
+ snapped: {
366
+ minHeight: "content-height"
367
+ },
368
+ docked: { dockable: "none" /* none */ }
369
+ };
370
+ var defaultAudioSleepTimerAction = {
371
+ visibility: "partially" /* partially */,
372
+ shortcut: null,
373
+ sheet: {
374
+ defaultSheet: "modal" /* modal */,
375
+ breakpoints: {
376
+ ["compact" /* compact */]: "bottomSheet" /* bottomSheet */,
377
+ ["medium" /* medium */]: "bottomSheet" /* bottomSheet */
167
378
  }
168
- const weightStyles = /* @__PURE__ */ new Map();
169
- if (weightsStr) {
170
- weightsStr.split(",").forEach((weightStr) => {
171
- const isItalic = weightStr.endsWith("i");
172
- const weightValue = parseInt(isItalic ? weightStr.slice(0, -1) : weightStr, 10);
173
- if (!isNaN(weightValue)) {
174
- if (!weightStyles.has(weightValue)) {
175
- weightStyles.set(weightValue, /* @__PURE__ */ new Set());
176
- }
177
- weightStyles.get(weightValue)?.add(isItalic ? "italic" : "normal");
178
- }
179
- });
379
+ },
380
+ snapped: {
381
+ minHeight: "content-height"
382
+ },
383
+ docked: { dockable: "none" /* none */ }
384
+ };
385
+ var defaultAudioRemotePlaybackAction = {
386
+ visibility: "always" /* always */,
387
+ shortcut: null
388
+ };
389
+ var defaultAudioTocAction = {
390
+ visibility: "partially" /* partially */,
391
+ shortcut: null,
392
+ sheet: {
393
+ defaultSheet: "modal" /* modal */,
394
+ breakpoints: {
395
+ ["compact" /* compact */]: "fullscreen" /* fullscreen */,
396
+ ["medium" /* medium */]: "fullscreen" /* fullscreen */
180
397
  }
181
- const weights = Array.from(weightStyles.keys()).sort((a, b) => a - b);
182
- const hasItalic = Array.from(weightStyles.values()).some((styles2) => styles2.has("italic"));
183
- const styles = hasItalic ? ["normal", "italic"] : ["normal"];
184
- const fontId = familyName;
185
- const familyDisplayName = familyName.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
186
- return [
187
- fontId,
188
- {
189
- id: fontId,
190
- name: familyDisplayName,
191
- ...labels?.[fontId] && { label: labels[fontId] },
192
- source: {
193
- type: "custom",
194
- provider: "bunny"
195
- },
196
- spec: {
197
- family: familyDisplayName,
198
- fallbacks: fallbacks?.[fontId] || [DEFAULT_FALLBACK],
199
- weights: {
200
- type: "static",
201
- values: weights.length ? weights : [400]
202
- },
203
- styles
204
- }
205
- }
206
- ];
207
- });
208
- const result = Object.fromEntries(fontEntries);
209
- if (order && order.length > 0) {
210
- const orderedResult = {};
211
- order.forEach((fontId) => {
212
- if (result[fontId]) {
213
- orderedResult[fontId] = result[fontId];
214
- }
215
- });
216
- Object.entries(result).forEach(([fontId, definition]) => {
217
- if (!orderedResult[fontId]) {
218
- orderedResult[fontId] = definition;
219
- }
220
- });
221
- return orderedResult;
398
+ },
399
+ docked: {
400
+ dockable: "both" /* both */,
401
+ dragIndicator: false,
402
+ width: 360,
403
+ minWidth: 320,
404
+ maxWidth: 450
222
405
  }
223
- return result;
224
406
  };
225
407
 
226
408
  // src/preferences/helpers/fontPref/googleFonts.ts
227
- var DEFAULT_FALLBACK2 = "sans-serif";
409
+ var DEFAULT_FALLBACK = "sans-serif";
228
410
  var DEFAULT_WIDTH_STEP = 20;
229
411
  var DEFAULT_WEIGHT_STEP = 20;
230
412
  var createDefinitionsFromGoogleFonts = (params) => {
@@ -322,7 +504,7 @@ var createDefinitionsFromGoogleFonts = (params) => {
322
504
  source: { type: "custom", provider: "google" },
323
505
  spec: {
324
506
  family: family.name,
325
- fallbacks: fallbacks?.[fontId] || [DEFAULT_FALLBACK2],
507
+ fallbacks: fallbacks?.[fontId] || [DEFAULT_FALLBACK],
326
508
  weights: family.weights,
327
509
  styles: family.styles,
328
510
  ...family.widths && { widths: family.widths },
@@ -384,7 +566,31 @@ var createDefinitionFromStaticFonts = (params) => {
384
566
  };
385
567
  };
386
568
 
387
- // src/preferences/models/fonts.ts
569
+ // src/preferences/helpers/validateObjectKeys.ts
570
+ var validateObjectKeys = (orderArrays, keysObj, context, specialCase, fallback) => {
571
+ const allOrders = new Set(
572
+ orderArrays.flatMap((arr) => {
573
+ if (!specialCase) return arr;
574
+ return arr.filter((k) => {
575
+ if (Array.isArray(specialCase)) {
576
+ return !specialCase.includes(k);
577
+ } else {
578
+ return k !== specialCase;
579
+ }
580
+ });
581
+ })
582
+ );
583
+ const availableKeys = Object.keys(keysObj);
584
+ allOrders.forEach((key) => {
585
+ if (!availableKeys.includes(key)) {
586
+ if (fallback) keysObj[key] = fallback;
587
+ console.warn(
588
+ `Key "${key}" in ${context} order arrays not found in ${context}.keys.${fallback ? `
589
+ Using fallback: ${JSON.stringify(fallback)}` : ""}`
590
+ );
591
+ }
592
+ });
593
+ };
388
594
  var readiumCSSFontCollection = {
389
595
  oldStyle: {
390
596
  id: "oldStyle",
@@ -532,16 +738,44 @@ var resolveContentProtectionConfig = (contentProtection, t) => {
532
738
  protectCopy: contentProtection.protectCopy,
533
739
  disableContextMenu: contentProtection.disableContextMenu,
534
740
  disableDragAndDrop: contentProtection.disableDragAndDrop,
535
- protectPrinting: contentProtection.protectPrinting ? {
536
- disable: contentProtection.protectPrinting.disable,
741
+ protectPrinting: contentProtection.protectPrinting?.disable ? {
742
+ disable: true,
537
743
  watermark: resolvedWatermark
538
744
  } : void 0,
539
745
  disableSelectAll: contentProtection.disableSelectAll,
540
746
  disableSave: contentProtection.disableSave,
541
747
  monitorDevTools: contentProtection.monitorDevTools
748
+ // TODO: When we implement it in non-audio navigators, uncomment
749
+ // disableRemotePlayback: contentProtection.disableRemotePlayback
542
750
  };
543
751
  return resolved;
544
752
  };
753
+ var resolveAudioContentProtectionConfig = (contentProtection, t) => {
754
+ if (!contentProtection) return void 0;
755
+ let resolvedWatermark;
756
+ if (contentProtection.protectPrinting?.watermark) {
757
+ if (typeof contentProtection.protectPrinting.watermark === "object" && "key" in contentProtection.protectPrinting.watermark) {
758
+ resolvedWatermark = t(contentProtection.protectPrinting.watermark.key, {
759
+ defaultValue: contentProtection.protectPrinting.watermark.fallback
760
+ });
761
+ } else if (typeof contentProtection.protectPrinting.watermark === "string") {
762
+ resolvedWatermark = t(contentProtection.protectPrinting.watermark);
763
+ }
764
+ }
765
+ return {
766
+ protectCopy: contentProtection.protectCopy,
767
+ disableContextMenu: contentProtection.disableContextMenu,
768
+ disableDragAndDrop: contentProtection.disableDragAndDrop,
769
+ protectPrinting: contentProtection.protectPrinting?.disable ? {
770
+ disable: true,
771
+ watermark: resolvedWatermark
772
+ } : void 0,
773
+ disableSelectAll: contentProtection.disableSelectAll,
774
+ disableSave: contentProtection.disableSave,
775
+ monitorDevTools: contentProtection.monitorDevTools,
776
+ disableRemotePlayback: contentProtection.disableRemotePlayback
777
+ };
778
+ };
545
779
  var defaultContentProtectionConfig = {
546
780
  protectCopy: false,
547
781
  disableContextMenu: false,
@@ -554,187 +788,30 @@ var defaultContentProtectionConfig = {
554
788
  disableSave: false,
555
789
  monitorDevTools: false
556
790
  };
557
- var devContentProtectionConfig = {
791
+ var defaultAudioContentProtectionConfig = {
558
792
  protectCopy: false,
559
793
  disableContextMenu: false,
560
794
  disableDragAndDrop: false,
561
795
  protectPrinting: {
562
- disable: false
796
+ disable: false,
797
+ watermark: "reader.app.printingDisabled"
563
798
  },
564
799
  disableSelectAll: false,
565
800
  disableSave: false,
566
- monitorDevTools: false
567
- };
568
-
569
- // src/preferences/models/settings.ts
570
- var ThSettingsKeys = /* @__PURE__ */ ((ThSettingsKeys2) => {
571
- ThSettingsKeys2["columns"] = "columns";
572
- ThSettingsKeys2["fontFamily"] = "fontFamily";
573
- ThSettingsKeys2["fontWeight"] = "fontWeight";
574
- ThSettingsKeys2["hyphens"] = "hyphens";
575
- ThSettingsKeys2["layout"] = "layout";
576
- ThSettingsKeys2["letterSpacing"] = "letterSpacing";
577
- ThSettingsKeys2["lineHeight"] = "lineHeight";
578
- ThSettingsKeys2["paragraphIndent"] = "paragraphIndent";
579
- ThSettingsKeys2["paragraphSpacing"] = "paragraphSpacing";
580
- ThSettingsKeys2["publisherStyles"] = "publisherStyles";
581
- ThSettingsKeys2["spacingGroup"] = "spacingGroup";
582
- ThSettingsKeys2["spacingPresets"] = "spacingPresets";
583
- ThSettingsKeys2["textAlign"] = "textAlign";
584
- ThSettingsKeys2["textGroup"] = "textGroup";
585
- ThSettingsKeys2["textNormalize"] = "textNormalize";
586
- ThSettingsKeys2["theme"] = "theme";
587
- ThSettingsKeys2["wordSpacing"] = "wordSpacing";
588
- ThSettingsKeys2["zoom"] = "zoom";
589
- return ThSettingsKeys2;
590
- })(ThSettingsKeys || {});
591
- var ThTextSettingsKeys = /* @__PURE__ */ ((ThTextSettingsKeys3) => {
592
- ThTextSettingsKeys3["fontFamily"] = "fontFamily";
593
- ThTextSettingsKeys3["fontWeight"] = "fontWeight";
594
- ThTextSettingsKeys3["hyphens"] = "hyphens";
595
- ThTextSettingsKeys3["textAlign"] = "textAlign";
596
- ThTextSettingsKeys3["textNormalize"] = "textNormalize";
597
- return ThTextSettingsKeys3;
598
- })(ThTextSettingsKeys || {});
599
- var ThSpacingSettingsKeys = /* @__PURE__ */ ((ThSpacingSettingsKeys3) => {
600
- ThSpacingSettingsKeys3["letterSpacing"] = "letterSpacing";
601
- ThSpacingSettingsKeys3["lineHeight"] = "lineHeight";
602
- ThSpacingSettingsKeys3["paragraphIndent"] = "paragraphIndent";
603
- ThSpacingSettingsKeys3["paragraphSpacing"] = "paragraphSpacing";
604
- ThSpacingSettingsKeys3["publisherStyles"] = "publisherStyles";
605
- ThSpacingSettingsKeys3["spacingPresets"] = "spacingPresets";
606
- ThSpacingSettingsKeys3["wordSpacing"] = "wordSpacing";
607
- return ThSpacingSettingsKeys3;
608
- })(ThSpacingSettingsKeys || {});
609
- var ThSettingsContainerKeys = /* @__PURE__ */ ((ThSettingsContainerKeys2) => {
610
- ThSettingsContainerKeys2["initial"] = "initial";
611
- ThSettingsContainerKeys2["text"] = "text";
612
- ThSettingsContainerKeys2["spacing"] = "spacing";
613
- return ThSettingsContainerKeys2;
614
- })(ThSettingsContainerKeys || {});
615
- var ThSettingsRangeVariant = /* @__PURE__ */ ((ThSettingsRangeVariant2) => {
616
- ThSettingsRangeVariant2["slider"] = "slider";
617
- ThSettingsRangeVariant2["incrementedSlider"] = "incrementedSlider";
618
- ThSettingsRangeVariant2["numberField"] = "numberField";
619
- return ThSettingsRangeVariant2;
620
- })(ThSettingsRangeVariant || {});
621
- var ThSettingsRangePlaceholder = /* @__PURE__ */ ((ThSettingsRangePlaceholder2) => {
622
- ThSettingsRangePlaceholder2["range"] = "range";
623
- ThSettingsRangePlaceholder2["none"] = "none";
624
- return ThSettingsRangePlaceholder2;
625
- })(ThSettingsRangePlaceholder || {});
626
- var ThSpacingPresetKeys = /* @__PURE__ */ ((ThSpacingPresetKeys4) => {
627
- ThSpacingPresetKeys4["publisher"] = "publisher";
628
- ThSpacingPresetKeys4["tight"] = "tight";
629
- ThSpacingPresetKeys4["balanced"] = "balanced";
630
- ThSpacingPresetKeys4["loose"] = "loose";
631
- ThSpacingPresetKeys4["accessible"] = "accessible";
632
- ThSpacingPresetKeys4["custom"] = "custom";
633
- return ThSpacingPresetKeys4;
634
- })(ThSpacingPresetKeys || {});
635
- var ThLayoutOptions = /* @__PURE__ */ ((ThLayoutOptions2) => {
636
- ThLayoutOptions2["scroll"] = "scroll_option";
637
- ThLayoutOptions2["paginated"] = "page_option";
638
- return ThLayoutOptions2;
639
- })(ThLayoutOptions || {});
640
- var ThTextAlignOptions = /* @__PURE__ */ ((ThTextAlignOptions2) => {
641
- ThTextAlignOptions2["publisher"] = "publisher";
642
- ThTextAlignOptions2["start"] = "start";
643
- ThTextAlignOptions2["justify"] = "justify";
644
- return ThTextAlignOptions2;
645
- })(ThTextAlignOptions || {});
646
- var ThLineHeightOptions = /* @__PURE__ */ ((ThLineHeightOptions3) => {
647
- ThLineHeightOptions3["publisher"] = "publisher";
648
- ThLineHeightOptions3["small"] = "small";
649
- ThLineHeightOptions3["medium"] = "medium";
650
- ThLineHeightOptions3["large"] = "large";
651
- return ThLineHeightOptions3;
652
- })(ThLineHeightOptions || {});
653
- var defaultTextSettingsMain = ["fontFamily" /* fontFamily */];
654
- var defaultTextSettingsSubpanel = [
655
- "fontFamily" /* fontFamily */,
656
- "textAlign" /* textAlign */,
657
- "hyphens" /* hyphens */,
658
- "fontWeight" /* fontWeight */,
659
- "textNormalize" /* textNormalize */
660
- ];
661
- var defaultSpacingSettingsMain = [
662
- "spacingPresets" /* spacingPresets */
663
- ];
664
- var defaultSpacingSettingsSubpanel = [
665
- "spacingPresets" /* spacingPresets */,
666
- "lineHeight" /* lineHeight */,
667
- "paragraphSpacing" /* paragraphSpacing */,
668
- "paragraphIndent" /* paragraphIndent */,
669
- "wordSpacing" /* wordSpacing */,
670
- "letterSpacing" /* letterSpacing */
671
- ];
672
- var defaultSpacingPresetsOrder = [
673
- "publisher" /* publisher */,
674
- "accessible" /* accessible */,
675
- "custom" /* custom */,
676
- "tight" /* tight */,
677
- "balanced" /* balanced */,
678
- "loose" /* loose */
679
- ];
680
- var defaultParagraphSpacing = {
681
- variant: "numberField" /* numberField */,
682
- placeholder: "range" /* range */,
683
- range: [0, 3],
684
- step: 0.25
685
- };
686
- var defaultParagraphIndent = {
687
- variant: "numberField" /* numberField */,
688
- placeholder: "range" /* range */,
689
- range: [0, 2],
690
- step: 0.25
801
+ monitorDevTools: false,
802
+ disableRemotePlayback: false
691
803
  };
692
- var defaultWordSpacing = {
693
- variant: "numberField" /* numberField */,
694
- placeholder: "range" /* range */,
695
- range: [0, 1],
696
- step: 0.1
697
- };
698
- var defaultLetterSpacing = {
699
- variant: "numberField" /* numberField */,
700
- placeholder: "range" /* range */,
701
- range: [0, 0.5],
702
- step: 0.05
703
- };
704
- var defaultLineHeights = {
705
- ["small" /* small */]: 1.3,
706
- ["medium" /* medium */]: 1.5,
707
- ["large" /* large */]: 1.75
708
- };
709
- var defaultZoom = {
710
- variant: "numberField" /* numberField */,
711
- placeholder: "range" /* range */,
712
- range: [0.7, 4],
713
- step: 0.05
714
- };
715
- var defaultSpacingPresets = {
716
- ["tight" /* tight */]: {
717
- ["lineHeight" /* lineHeight */]: "small" /* small */,
718
- ["paragraphSpacing" /* paragraphSpacing */]: 0,
719
- ["paragraphIndent" /* paragraphIndent */]: 1
720
- },
721
- ["balanced" /* balanced */]: {
722
- ["lineHeight" /* lineHeight */]: "medium" /* medium */,
723
- ["paragraphSpacing" /* paragraphSpacing */]: 0.75,
724
- ["paragraphIndent" /* paragraphIndent */]: 0
725
- },
726
- ["loose" /* loose */]: {
727
- ["lineHeight" /* lineHeight */]: "large" /* large */,
728
- ["paragraphSpacing" /* paragraphSpacing */]: 1.75,
729
- ["paragraphIndent" /* paragraphIndent */]: 0
730
- },
731
- ["accessible" /* accessible */]: {
732
- ["lineHeight" /* lineHeight */]: "large" /* large */,
733
- ["paragraphSpacing" /* paragraphSpacing */]: 2.5,
734
- ["paragraphIndent" /* paragraphIndent */]: 0,
735
- ["letterSpacing" /* letterSpacing */]: 0.1,
736
- ["wordSpacing" /* wordSpacing */]: 0.3
737
- }
804
+ var devContentProtectionConfig = {
805
+ protectCopy: false,
806
+ disableContextMenu: false,
807
+ disableDragAndDrop: false,
808
+ protectPrinting: {
809
+ disable: false
810
+ },
811
+ disableSelectAll: false,
812
+ disableSave: false,
813
+ monitorDevTools: false,
814
+ disableRemotePlayback: false
738
815
  };
739
816
  var ThThemeKeys = /* @__PURE__ */ ((ThThemeKeys3) => {
740
817
  ThThemeKeys3["light"] = "light";
@@ -865,6 +942,239 @@ var contrast3Theme = {
865
942
  immerse: "0.45"
866
943
  };
867
944
 
945
+ // src/preferences/audioPreferences.ts
946
+ var ThAudioAffordance = /* @__PURE__ */ ((ThAudioAffordance2) => {
947
+ ThAudioAffordance2["timeline"] = "timeline";
948
+ ThAudioAffordance2["readingOrder"] = "readingOrder";
949
+ ThAudioAffordance2["toc"] = "toc";
950
+ return ThAudioAffordance2;
951
+ })(ThAudioAffordance || {});
952
+ var validateRangePresets = (pref, context) => {
953
+ if (pref.variant !== "sliderWithPresets" /* sliderWithPresets */ || !pref.presets?.length) return;
954
+ const [min, max] = [Math.min(...pref.range), Math.max(...pref.range)];
955
+ const step = pref.step;
956
+ const tolerance = step * 1e-9;
957
+ const invalid = pref.presets.filter((p) => {
958
+ if (p < min || p > max) return true;
959
+ const offset = (p - min) / step;
960
+ return Math.abs(offset - Math.round(offset)) > tolerance;
961
+ });
962
+ if (invalid.length > 0) {
963
+ console.warn(
964
+ `${context}: presets [${invalid.join(", ")}] are not reachable with range=[${min}, ${max}] and step=${step}.`
965
+ );
966
+ }
967
+ };
968
+ var createAudioPreferences = (params) => {
969
+ if (params.actions?.secondary) {
970
+ validateObjectKeys(
971
+ [params.actions.secondary.displayOrder],
972
+ params.actions.secondary.keys,
973
+ "actions.secondary"
974
+ );
975
+ }
976
+ if (params.settings?.order) {
977
+ const order = params.settings.order;
978
+ const hasSkipInterval = order.includes("skipInterval" /* skipInterval */);
979
+ const hasSplitIntervals = order.includes("skipBackwardInterval" /* skipBackwardInterval */) || order.includes("skipForwardInterval" /* skipForwardInterval */);
980
+ if (hasSkipInterval && hasSplitIntervals) {
981
+ console.warn(
982
+ `settings.order contains both "${"skipInterval" /* skipInterval */}" and split interval keys. Use one or the other.`
983
+ );
984
+ }
985
+ }
986
+ if (params.theming?.themes) {
987
+ validateObjectKeys(
988
+ [params.theming.themes.audioOrder],
989
+ params.theming.themes.keys,
990
+ "theming.themes",
991
+ "auto"
992
+ );
993
+ }
994
+ if (params.theming?.layout?.publicationMetadata?.order) {
995
+ const order = params.theming.layout.publicationMetadata.order;
996
+ const titleVariants = [
997
+ "title" /* title */,
998
+ "titleWithSubtitle" /* titleWithSubtitle */,
999
+ "subtitleWithTitle" /* subtitleWithTitle */
1000
+ ];
1001
+ const titleVariantsInOrder = order.filter((c) => titleVariants.includes(c));
1002
+ if (titleVariantsInOrder.length > 1) {
1003
+ console.warn(
1004
+ `publicationMetadata.order contains multiple title variants [${titleVariantsInOrder.join(", ")}]. Using first one only.`
1005
+ );
1006
+ const firstTitleIndex = order.findIndex((c) => titleVariants.includes(c));
1007
+ params.theming.layout.publicationMetadata.order = order.filter((component, index) => {
1008
+ if (component === "authors" /* authors */) return true;
1009
+ return index === firstTitleIndex;
1010
+ });
1011
+ }
1012
+ }
1013
+ Object.entries(params.settings?.keys ?? {}).forEach(([key, pref]) => {
1014
+ if (pref && typeof pref === "object" && "variant" in pref) {
1015
+ validateRangePresets(pref, `settings.keys.${key}`);
1016
+ }
1017
+ });
1018
+ return params;
1019
+ };
1020
+
1021
+ // src/preferences/defaultAudioPreferences.ts
1022
+ var defaultAudioPreferences = createAudioPreferences({
1023
+ theming: {
1024
+ header: {
1025
+ backLink: {
1026
+ variant: "arrow" /* arrow */,
1027
+ visibility: "partially",
1028
+ href: "/"
1029
+ }
1030
+ },
1031
+ icon: {
1032
+ size: 24,
1033
+ tooltipOffset: 10
1034
+ },
1035
+ layout: {
1036
+ compact: {
1037
+ order: [
1038
+ "cover" /* cover */,
1039
+ "metadata" /* metadata */,
1040
+ "playbackControls" /* playbackControls */,
1041
+ "progressBar" /* progressBar */,
1042
+ "mediaActions" /* mediaActions */
1043
+ ]
1044
+ },
1045
+ expanded: {
1046
+ start: [
1047
+ "cover" /* cover */,
1048
+ "metadata" /* metadata */
1049
+ ],
1050
+ end: [
1051
+ "playbackControls" /* playbackControls */,
1052
+ "progressBar" /* progressBar */,
1053
+ "mediaActions" /* mediaActions */
1054
+ ]
1055
+ },
1056
+ publicationMetadata: {
1057
+ order: [
1058
+ "titleWithSubtitle" /* titleWithSubtitle */
1059
+ ]
1060
+ },
1061
+ radius: 5,
1062
+ spacing: 20,
1063
+ progressBar: {
1064
+ variant: "segmented" /* segmented */
1065
+ },
1066
+ defaults: {
1067
+ dockingWidth: 340,
1068
+ scrim: "rgba(0, 0, 0, 0.2)"
1069
+ },
1070
+ constraints: {
1071
+ ["bottomSheet" /* bottomSheet */]: 600,
1072
+ ["popover" /* popover */]: 600,
1073
+ ["modal" /* modal */]: 600,
1074
+ cover: 300
1075
+ }
1076
+ },
1077
+ breakpoints: {
1078
+ ["compact" /* compact */]: 600,
1079
+ ["medium" /* medium */]: 840,
1080
+ ["expanded" /* expanded */]: 1200,
1081
+ ["large" /* large */]: 1600,
1082
+ ["xLarge" /* xLarge */]: null
1083
+ },
1084
+ themes: {
1085
+ audioOrder: [
1086
+ "auto",
1087
+ "light" /* light */,
1088
+ "dark" /* dark */
1089
+ ],
1090
+ systemThemes: {
1091
+ light: "light" /* light */,
1092
+ dark: "dark" /* dark */
1093
+ },
1094
+ keys: {
1095
+ ["light" /* light */]: lightTheme,
1096
+ ["dark" /* dark */]: darkTheme
1097
+ }
1098
+ }
1099
+ },
1100
+ actions: {
1101
+ primary: {
1102
+ displayOrder: [
1103
+ "audio.volume" /* volume */,
1104
+ "audio.playbackRate" /* playbackRate */,
1105
+ "audio.toc" /* toc */,
1106
+ "audio.sleepTimer" /* sleepTimer */
1107
+ ],
1108
+ keys: {
1109
+ ["audio.volume" /* volume */]: defaultAudioVolumeAction,
1110
+ ["audio.playbackRate" /* playbackRate */]: defaultAudioPlaybackRateAction,
1111
+ ["audio.toc" /* toc */]: defaultAudioTocAction,
1112
+ ["audio.sleepTimer" /* sleepTimer */]: defaultAudioSleepTimerAction
1113
+ }
1114
+ },
1115
+ secondary: {
1116
+ displayOrder: [
1117
+ "audio.remotePlayback" /* remotePlayback */,
1118
+ "settings" /* settings */
1119
+ ],
1120
+ collapse: {
1121
+ ["compact" /* compact */]: 2,
1122
+ ["medium" /* medium */]: 3
1123
+ },
1124
+ keys: {
1125
+ ["audio.remotePlayback" /* remotePlayback */]: defaultAudioRemotePlaybackAction,
1126
+ ["settings" /* settings */]: defaultSettingsAction
1127
+ }
1128
+ }
1129
+ },
1130
+ settings: {
1131
+ order: [
1132
+ "theme" /* theme */,
1133
+ "skipBackwardInterval" /* skipBackwardInterval */,
1134
+ "skipForwardInterval" /* skipForwardInterval */,
1135
+ "autoPlay" /* autoPlay */
1136
+ ],
1137
+ keys: {
1138
+ ["volume" /* volume */]: defaultAudioVolume,
1139
+ ["playbackRate" /* playbackRate */]: defaultAudioPlaybackRate,
1140
+ ["skipBackwardInterval" /* skipBackwardInterval */]: defaultAudioSkipBackwardInterval,
1141
+ ["skipForwardInterval" /* skipForwardInterval */]: defaultAudioSkipForwardInterval,
1142
+ ["sleepTimer" /* sleepTimer */]: defaultAudioSleepTimer
1143
+ }
1144
+ },
1145
+ contentProtection: defaultAudioContentProtectionConfig,
1146
+ affordances: {
1147
+ previous: "toc" /* toc */,
1148
+ next: "toc" /* toc */
1149
+ },
1150
+ shortcuts: {
1151
+ representation: "symbol" /* symbol */,
1152
+ joiner: "+"
1153
+ },
1154
+ docking: {
1155
+ displayOrder: [
1156
+ "dockingTransient" /* transient */,
1157
+ "dockingStart" /* start */,
1158
+ "dockingEnd" /* end */
1159
+ ],
1160
+ // Only toc is dockable; others have dockable:none so dock panels are TOC-only
1161
+ dock: {},
1162
+ collapse: true,
1163
+ keys: {
1164
+ ["dockingStart" /* start */]: { visibility: "overflow" /* overflow */, shortcut: null },
1165
+ ["dockingEnd" /* end */]: { visibility: "overflow" /* overflow */, shortcut: null },
1166
+ ["dockingTransient" /* transient */]: { visibility: "overflow" /* overflow */, shortcut: null }
1167
+ }
1168
+ }
1169
+ });
1170
+ var ThAudioPreferencesContext = createContext(null);
1171
+ var defaultAudioPreferencesContextValue = {
1172
+ preferences: defaultAudioPreferences,
1173
+ updatePreferences: () => {
1174
+ throw new Error("updatePreferences must be used within a ThAudioPreferencesProvider");
1175
+ }
1176
+ };
1177
+
868
1178
  // src/preferences/preferences.ts
869
1179
  var createPreferences = (params) => {
870
1180
  if (params.locale) {
@@ -874,29 +1184,13 @@ var createPreferences = (params) => {
874
1184
  params.locale = void 0;
875
1185
  }
876
1186
  }
877
- const validateObjectKeys = (orderArrays, keysObj, context, specialCase, fallback) => {
878
- const allOrders = new Set(
879
- orderArrays.flatMap((arr) => {
880
- if (!specialCase) return arr;
881
- return arr.filter((k) => {
882
- if (Array.isArray(specialCase)) {
883
- return !specialCase.includes(k);
884
- } else {
885
- return k !== specialCase;
886
- }
887
- });
888
- })
889
- );
890
- const availableKeys = Object.keys(keysObj);
891
- allOrders.forEach((key) => {
892
- if (!availableKeys.includes(key)) {
893
- console.warn(`Key "${key}" in ${context} order arrays not found in ${context}.keys.${""}`);
894
- }
895
- });
896
- };
897
1187
  if (params.actions) {
898
1188
  validateObjectKeys(
899
- [params.actions.reflowOrder, params.actions.fxlOrder, params.actions.webPubOrder],
1189
+ [
1190
+ params.actions.reflowOrder,
1191
+ params.actions.fxlOrder,
1192
+ params.actions.webPubOrder
1193
+ ],
900
1194
  params.actions.keys,
901
1195
  "actions"
902
1196
  );
@@ -1004,6 +1298,25 @@ var createPreferences = (params) => {
1004
1298
  }
1005
1299
  });
1006
1300
  }
1301
+ const validateRangePresets2 = (pref, context) => {
1302
+ if (pref.variant !== "sliderWithPresets" /* sliderWithPresets */ || !pref.presets?.length) return;
1303
+ const [min, max] = [Math.min(...pref.range), Math.max(...pref.range)];
1304
+ const step = pref.step;
1305
+ const tolerance = step * 1e-9;
1306
+ const invalid = pref.presets.filter((p) => {
1307
+ if (p < min || p > max) return true;
1308
+ const offset = (p - min) / step;
1309
+ return Math.abs(offset - Math.round(offset)) > tolerance;
1310
+ });
1311
+ if (invalid.length > 0) {
1312
+ console.warn(`${context}: presets [${invalid.join(", ")}] are not reachable with range=[${min}, ${max}] and step=${step}.`);
1313
+ }
1314
+ };
1315
+ Object.entries(params.settings?.keys ?? {}).forEach(([key, pref]) => {
1316
+ if (pref && typeof pref === "object" && "variant" in pref) {
1317
+ validateRangePresets2(pref, `settings.keys.${key}`);
1318
+ }
1319
+ });
1007
1320
  return params;
1008
1321
  };
1009
1322
 
@@ -1165,8 +1478,12 @@ var defaultPreferences = createPreferences({
1165
1478
  // Max-width of all bottom sheets
1166
1479
  ["popover" /* popover */]: 600,
1167
1480
  // Max-width of all popover sheets
1168
- pagination: 1024
1481
+ ["modal" /* modal */]: 600,
1482
+ // Max-width of all modal sheets
1483
+ pagination: 1024,
1169
1484
  // Max-width of pagination component
1485
+ dropdown: 250
1486
+ // Max-height of main UI dropdowns
1170
1487
  }
1171
1488
  },
1172
1489
  breakpoints: {
@@ -1367,8 +1684,6 @@ var defaultPreferences = createPreferences({
1367
1684
  }
1368
1685
  }
1369
1686
  });
1370
-
1371
- // src/preferences/ThPreferencesContext.ts
1372
1687
  var ThPreferencesContext = createContext(null);
1373
1688
  var defaultPreferencesContextValue = {
1374
1689
  preferences: defaultPreferences,
@@ -1376,611 +1691,35 @@ var defaultPreferencesContextValue = {
1376
1691
  throw new Error("updatePreferences must be used within a ThPreferencesProvider with an adapter");
1377
1692
  }
1378
1693
  };
1379
-
1380
- // src/preferences/adapters/ThMemoryPreferencesAdapter.ts
1381
- var ThMemoryPreferencesAdapter = class {
1382
- currentPreferences;
1383
- listeners = /* @__PURE__ */ new Set();
1384
- constructor(initialPreferences) {
1385
- this.currentPreferences = { ...initialPreferences };
1386
- }
1387
- getPreferences() {
1388
- return { ...this.currentPreferences };
1389
- }
1390
- setPreferences(prefs) {
1391
- this.currentPreferences = { ...prefs };
1392
- this.notifyListeners(this.currentPreferences);
1393
- }
1394
- subscribe(listener) {
1395
- this.listeners.add(listener);
1396
- }
1397
- unsubscribe(listener) {
1398
- this.listeners.delete(listener);
1399
- }
1400
- notifyListeners(prefs) {
1401
- this.listeners.forEach((listener) => listener({ ...prefs }));
1402
- }
1403
- };
1404
- var ThDirectionSetter = ({
1405
- direction,
1406
- children
1407
- }) => {
1408
- useEffect(() => {
1409
- if (direction) document.documentElement.dir = direction;
1410
- }, [direction]);
1411
- return children;
1412
- };
1413
- function ThPreferencesProvider({
1414
- adapter,
1415
- initialPreferences,
1416
- devMode,
1417
- children
1418
- }) {
1419
- const effectiveAdapter = useMemo(() => {
1420
- let fallbackPreferences = defaultPreferencesContextValue.preferences;
1421
- if (devMode && !initialPreferences) {
1422
- fallbackPreferences = {
1423
- ...fallbackPreferences,
1424
- contentProtection: devContentProtectionConfig
1425
- };
1426
- }
1427
- return adapter || new ThMemoryPreferencesAdapter(
1428
- initialPreferences || fallbackPreferences
1429
- );
1430
- }, [adapter, initialPreferences, devMode]);
1431
- const [preferences, setPreferences] = useState(
1432
- (() => {
1433
- let fallbackPreferences = defaultPreferencesContextValue.preferences;
1434
- if (devMode && !initialPreferences) {
1435
- fallbackPreferences = {
1436
- ...fallbackPreferences,
1437
- contentProtection: devContentProtectionConfig
1438
- };
1439
- }
1440
- return initialPreferences || fallbackPreferences;
1441
- })()
1442
- );
1443
- const handlePreferenceChange = useCallback((newPrefs) => {
1444
- setPreferences((prev) => {
1445
- return JSON.stringify(prev) === JSON.stringify(newPrefs) ? prev : newPrefs;
1446
- });
1447
- }, []);
1448
- useEffect(() => {
1449
- effectiveAdapter.subscribe(handlePreferenceChange);
1450
- return () => {
1451
- effectiveAdapter.unsubscribe(handlePreferenceChange);
1452
- };
1453
- }, [effectiveAdapter, handlePreferenceChange]);
1454
- const contextValue = useMemo(() => ({
1455
- preferences,
1456
- updatePreferences: (newPrefs) => {
1457
- effectiveAdapter.setPreferences(newPrefs);
1458
- }
1459
- }), [preferences, effectiveAdapter]);
1460
- return /* @__PURE__ */ jsx(ThPreferencesContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(ThDirectionSetter, { direction: preferences.direction, children }) });
1461
- }
1462
-
1463
- // src/preferences/services/createBunnyFontResources.ts
1464
- var buildBunnyFontsUrl = ({
1465
- family,
1466
- weights,
1467
- styles = ["normal"]
1468
- }) => {
1469
- if (weights.type !== "static") {
1470
- throw new Error("Bunny Fonts only supports static fonts");
1471
- }
1472
- const weightValues = weights.values;
1473
- const variants = /* @__PURE__ */ new Set();
1474
- for (const weight of weightValues) {
1475
- variants.add(weight.toString());
1476
- if (styles.includes("italic")) {
1477
- variants.add(`${weight}i`);
1478
- }
1479
- }
1480
- const variantList = Array.from(variants).sort();
1481
- const familyParam = family.replace(/ /g, "-").toLowerCase();
1482
- const variantParam = variantList.join(",");
1483
- return `https://fonts.bunny.net/css?family=${familyParam}:${variantParam}`;
1484
- };
1485
- var createBunnyFontResources = (font) => {
1486
- if (font.source.type !== "custom" || font.source.provider !== "bunny" || font.spec.weights.type !== "static") {
1487
- return null;
1488
- }
1489
- const { family, weights, styles } = font.spec;
1490
- const url = buildBunnyFontsUrl({
1491
- family,
1492
- weights,
1493
- styles
1494
- });
1495
- return {
1496
- as: "link",
1497
- rel: "stylesheet",
1498
- url
1499
- };
1500
- };
1501
-
1502
- // src/preferences/services/createGoogleFontResources.ts
1503
- var buildGoogleFontsV2Url = ({
1504
- family,
1505
- weights,
1506
- styles = ["normal"],
1507
- widths,
1508
- display = "block",
1509
- text
1510
- }) => {
1511
- if (text) {
1512
- return `https://fonts.googleapis.com/css2?family=${family.replace(/ /g, "+")}&text=${encodeURIComponent(text)}`;
1513
- }
1514
- const hasItalic = styles.includes("italic");
1515
- const hasWidth = !!widths;
1516
- const weightValues = weights.type === "static" ? weights.values.join(",") : `${weights.min}..${weights.max}`;
1517
- const widthValues = hasWidth && widths ? `${widths.min}..${widths.max}` : void 0;
1518
- const familyParam = family.replace(/ /g, "+");
1519
- let axesParam;
1520
- if (hasItalic && hasWidth) {
1521
- const variants = [
1522
- `0,${widthValues},${weightValues}`,
1523
- // normal
1524
- `1,${widthValues},${weightValues}`
1525
- // italic
1526
- ];
1527
- axesParam = `:ital,wdth,wght@${variants.join(";")}`;
1528
- } else if (hasItalic) {
1529
- const variants = [
1530
- `0,${weightValues}`,
1531
- // normal
1532
- `1,${weightValues}`
1533
- // italic
1534
- ];
1535
- axesParam = `:ital,wght@${variants.join(";")}`;
1536
- } else if (hasWidth) {
1537
- axesParam = `:wdth,wght@${widthValues},${weightValues}`;
1538
- } else {
1539
- axesParam = `:wght@${weightValues}`;
1540
- }
1541
- const displayParam = display ? `&display=${display}` : "";
1542
- return `https://fonts.googleapis.com/css2?family=${familyParam}${axesParam}${displayParam}`;
1543
- };
1544
- var createGoogleFontResources = (font, text) => {
1545
- if (font.source.type !== "custom" || font.source.provider !== "google") {
1546
- return null;
1547
- }
1548
- const { family, weights, display, styles, widths } = font.spec;
1549
- const url = buildGoogleFontsV2Url({
1550
- family,
1551
- weights,
1552
- display,
1553
- styles,
1554
- widths,
1555
- text
1556
- });
1557
- return {
1558
- as: "link",
1559
- rel: "stylesheet",
1560
- url
1561
- };
1562
- };
1563
-
1564
- // src/preferences/services/createLocalFontResources.ts
1565
- var getFontFormat = (path) => {
1566
- const ext = path.split(".").pop()?.toLowerCase();
1567
- switch (ext) {
1568
- case "woff":
1569
- return "woff";
1570
- case "woff2":
1571
- return "woff2";
1572
- case "ttf":
1573
- return "truetype";
1574
- case "otf":
1575
- return "opentype";
1576
- case "eot":
1577
- return "embedded-opentype";
1578
- case "svg":
1579
- return "svg";
1580
- default:
1581
- return "woff2";
1582
- }
1583
- };
1584
- var createLocalFontResources = (font) => {
1585
- if (font.source.type !== "custom" || font.source.provider !== "local") {
1586
- return null;
1587
- }
1588
- const { family, weights, display, widths } = font.spec;
1589
- const fontFiles = font.source.files || [];
1590
- const cssContent = fontFiles.map((fontFile) => {
1591
- const format = getFontFormat(fontFile.path);
1592
- const fontUrl = new URL(fontFile.path, window.location.origin).toString();
1593
- const isVariable = font.source.type === "custom" && font.source.provider === "local" && "variant" in font.source && font.source.variant === "variable";
1594
- const rules = [
1595
- `@font-face {`,
1596
- ` font-family: "${family}";`,
1597
- ` src: url("${fontUrl}") format("${format}");`
1598
- ];
1599
- if (isVariable && weights.type === "variable") {
1600
- rules.push(` font-weight: ${weights.min} ${weights.max};`);
1601
- } else if ("weight" in fontFile) {
1602
- rules.push(` font-weight: ${fontFile.weight};`);
1603
- }
1604
- if ("style" in fontFile) {
1605
- rules.push(` font-style: ${fontFile.style};`);
1606
- }
1607
- if (isVariable && widths) {
1608
- rules.push(` font-stretch: ${widths.min}% ${widths.max}%;`);
1609
- }
1610
- if (display) {
1611
- rules.push(` font-display: ${display};`);
1612
- } else {
1613
- rules.push(` font-display: block;`);
1614
- }
1615
- return rules.join("\n") + "\n}";
1616
- }).filter(Boolean).join("\n\n");
1617
- const blob = new Blob([cssContent], { type: "text/css" });
1618
- return {
1619
- as: "link",
1620
- rel: "stylesheet",
1621
- blob
1622
- };
1623
- };
1624
-
1625
- // src/preferences/services/fonts.ts
1626
- var createFontService = (fontFamilyPref) => {
1627
- const allSupportedLanguages = [];
1628
- const parsedFonts = /* @__PURE__ */ new Map();
1629
- const bunnyFonts = /* @__PURE__ */ new Map();
1630
- const googleFonts = /* @__PURE__ */ new Map();
1631
- const localFonts = /* @__PURE__ */ new Map();
1632
- const resolveFontLanguage = (bcp47Tag, direction = "ltr") => {
1633
- if (!bcp47Tag) return "default";
1634
- if (allSupportedLanguages.includes(bcp47Tag)) {
1635
- return bcp47Tag;
1636
- }
1637
- const parts = bcp47Tag.split(/[-_]/);
1638
- const language = parts[0].toLowerCase();
1639
- const scriptOrRegion = parts[1]?.toLowerCase();
1640
- if (scriptOrRegion) {
1641
- const langScriptOrRegion = `${language}-${scriptOrRegion}`;
1642
- if (allSupportedLanguages.includes(langScriptOrRegion)) {
1643
- return langScriptOrRegion;
1644
- }
1645
- }
1646
- if (language === "ja" && !scriptOrRegion) {
1647
- if (direction === "rtl" && allSupportedLanguages.includes("ja-v")) {
1648
- return "ja-v";
1649
- }
1650
- if (allSupportedLanguages.includes("ja")) {
1651
- return "ja";
1652
- }
1653
- }
1654
- const shouldFilter = language === "mn" && (scriptOrRegion === "mong" || scriptOrRegion === "cyrl") || language === "zh" && (scriptOrRegion === "hant" || scriptOrRegion === "tw" || scriptOrRegion === "hk");
1655
- if (!shouldFilter && allSupportedLanguages.includes(language)) {
1656
- return language;
1657
- }
1658
- return "default";
1659
- };
1660
- Object.entries(fontFamilyPref).forEach(([collectionName, collectionData]) => {
1661
- const fontCollection = "fonts" in collectionData ? collectionData.fonts : collectionData;
1662
- if ("supportedLanguages" in collectionData) {
1663
- const reducedLanguages = collectionData.supportedLanguages.map((lang) => {
1664
- const parts = lang.split(/[-_]/);
1665
- const language = parts[0].toLowerCase();
1666
- const scriptOrRegion = parts[1]?.toLowerCase();
1667
- return scriptOrRegion ? `${language}-${scriptOrRegion}` : language;
1668
- });
1669
- allSupportedLanguages.push(...reducedLanguages);
1670
- }
1671
- bunnyFonts.set(collectionName, []);
1672
- googleFonts.set(collectionName, []);
1673
- localFonts.set(collectionName, []);
1674
- const collectionBunnyFonts = bunnyFonts.get(collectionName);
1675
- const collectionGoogleFonts = googleFonts.get(collectionName);
1676
- const collectionLocalFonts = localFonts.get(collectionName);
1677
- Object.entries(fontCollection).forEach(([id, font]) => {
1678
- const fontFamily = font.spec.family;
1679
- let fontStack = fontFamily;
1680
- if (font.source.type === "custom") {
1681
- switch (font.source.provider) {
1682
- case "bunny":
1683
- collectionBunnyFonts.push(font);
1684
- break;
1685
- case "google":
1686
- collectionGoogleFonts.push(font);
1687
- break;
1688
- case "local":
1689
- collectionLocalFonts.push(font);
1690
- break;
1691
- }
1692
- }
1693
- const wrapIfNeeded = (name) => {
1694
- const trimmed = name.trim();
1695
- if (!trimmed) return "";
1696
- if (trimmed.includes(" ") && !/^['"].*['"]$/.test(trimmed)) {
1697
- return `"${trimmed}"`;
1698
- }
1699
- return trimmed;
1700
- };
1701
- const wrappedFontFamily = wrapIfNeeded(fontFamily);
1702
- if (font.spec.fallbacks?.length) {
1703
- const uniqueFallbacks = [...new Set(
1704
- font.spec.fallbacks.filter((fallback) => fallback.toLowerCase() !== fontFamily.toLowerCase()).map(wrapIfNeeded)
1705
- )];
1706
- if (uniqueFallbacks.length > 0) {
1707
- fontStack = [wrappedFontFamily, ...uniqueFallbacks].join(", ");
1708
- }
1709
- }
1710
- parsedFonts.set(id, {
1711
- fontStack: fontStack || wrappedFontFamily,
1712
- fontFamily: wrappedFontFamily,
1713
- weights: font.spec.weights || null,
1714
- widths: font.spec.widths || null
1715
- });
1716
- });
1717
- });
1718
- const defaultBunnyFonts = bunnyFonts.get("default") || [];
1719
- const defaultGoogleFonts = googleFonts.get("default") || [];
1720
- const defaultLocalFonts = localFonts.get("default") || [];
1721
- const processFonts = (bunnyFontsList, googleFontsList, localFontsList, optimize = false) => {
1722
- const result = {
1723
- allowedDomains: [],
1724
- prepend: [],
1725
- append: []
1726
- };
1727
- const bunnyResources = bunnyFontsList.map((font) => createBunnyFontResources(font)).filter((resource) => resource !== null);
1728
- if (bunnyResources.length > 0) {
1729
- result.allowedDomains.push(
1730
- "https://fonts.bunny.net"
1731
- );
1732
- result.prepend.push(
1733
- {
1734
- as: "link",
1735
- rel: "preconnect",
1736
- url: "https://fonts.bunny.net"
1737
- }
1738
- );
1739
- result.append.push(...bunnyResources);
1740
- }
1741
- const googleResources = googleFontsList.map((font) => createGoogleFontResources(font, optimize ? font.name : void 0)).filter((resource) => resource !== null);
1742
- if (googleResources.length > 0) {
1743
- result.allowedDomains.push(
1744
- "https://fonts.googleapis.com",
1745
- "https://fonts.gstatic.com"
1746
- );
1747
- result.prepend.push(
1748
- {
1749
- as: "link",
1750
- rel: "preconnect",
1751
- url: "https://fonts.googleapis.com"
1752
- },
1753
- {
1754
- as: "link",
1755
- rel: "preconnect",
1756
- url: "https://fonts.gstatic.com",
1757
- attributes: { crossOrigin: "anonymous" }
1758
- }
1759
- );
1760
- result.append.push(...googleResources);
1761
- }
1762
- const localResources = localFontsList.map(createLocalFontResources).filter((resource) => resource !== null);
1763
- if (localResources.length > 0) {
1764
- result.allowedDomains.push(window.location.origin);
1765
- result.append.push(...localResources);
1766
- }
1767
- return result.append.length > 0 ? result : null;
1768
- };
1769
- const getInjectables = (options, optimize = false) => {
1770
- if (options && "key" in options) {
1771
- const { key } = options;
1772
- if (!key || !(key in fontFamilyPref)) {
1773
- return null;
1774
- }
1775
- return processFonts(bunnyFonts.get(key) || [], googleFonts.get(key) || [], localFonts.get(key) || [], optimize);
1776
- }
1777
- if (options && "language" in options) {
1778
- const { language: publicationLanguage } = options;
1779
- for (const [collectionName, collectionData] of Object.entries(fontFamilyPref)) {
1780
- if (collectionName === "default") continue;
1781
- const supportedLangs = "supportedLanguages" in collectionData ? collectionData.supportedLanguages : null;
1782
- if (supportedLangs && Array.isArray(supportedLangs) && publicationLanguage && supportedLangs.includes(publicationLanguage)) {
1783
- return processFonts(bunnyFonts.get(collectionName) || [], googleFonts.get(collectionName) || [], localFonts.get(collectionName) || [], optimize);
1784
- }
1785
- }
1786
- }
1787
- return processFonts(defaultBunnyFonts, defaultGoogleFonts, defaultLocalFonts, optimize);
1788
- };
1789
- const getFontMetadata = (fontId) => {
1790
- const parsed = parsedFonts.get(fontId);
1791
- return parsed || { fontStack: null, fontFamily: null, weights: null, widths: null };
1792
- };
1793
- const getFontCollection = (options) => {
1794
- if (options && "key" in options) {
1795
- const { key } = options;
1796
- if (!key || !(key in fontFamilyPref)) {
1797
- return fontFamilyPref.default;
1798
- }
1799
- if (key === "default") {
1800
- return fontFamilyPref.default;
1801
- }
1802
- const prefRecord = fontFamilyPref;
1803
- const collection = prefRecord[key];
1804
- if (collection && "fonts" in collection) {
1805
- return collection.fonts;
1806
- }
1807
- return fontFamilyPref.default;
1808
- }
1809
- if (options && "language" in options) {
1810
- const { language: publicationLanguage } = options;
1811
- for (const [collectionName, collectionData] of Object.entries(fontFamilyPref)) {
1812
- if (collectionName === "default") continue;
1813
- const collection = "fonts" in collectionData ? collectionData : { fonts: collectionData };
1814
- const supportedLangs = "supportedLanguages" in collection ? collection.supportedLanguages : null;
1815
- if (supportedLangs?.includes(publicationLanguage)) {
1816
- return collection.fonts;
1817
- }
1818
- }
1819
- return fontFamilyPref.default;
1820
- }
1821
- return fontFamilyPref.default;
1822
- };
1823
- return {
1824
- getInjectables,
1825
- getFontMetadata,
1826
- getFontCollection,
1827
- resolveFontLanguage
1828
- };
1829
- };
1830
-
1831
- // src/preferences/hooks/usePreferences.ts
1832
- function usePreferences() {
1833
- const context = useContext(ThPreferencesContext);
1834
- if (!context) {
1835
- throw new Error("usePreferences must be used within a ThPreferencesProvider");
1836
- }
1837
- const fontService = createFontService(context.preferences.settings.keys.fontFamily);
1838
- return {
1839
- preferences: context.preferences,
1840
- updatePreferences: context.updatePreferences,
1841
- getFontInjectables: (options, optimize) => {
1842
- return fontService.getInjectables(options, optimize);
1843
- },
1844
- getFontsList: (options) => {
1845
- return fontService.getFontCollection(options);
1846
- },
1847
- getFontMetadata: (fontId) => {
1848
- return fontService.getFontMetadata(fontId);
1849
- },
1850
- resolveFontLanguage: (bcp47Tag, direction) => {
1851
- return fontService.resolveFontLanguage(bcp47Tag, direction);
1852
- }
1853
- };
1854
- }
1855
-
1856
- // src/preferences/hooks/usePreferenceKeys.ts
1857
- var usePreferenceKeys = () => {
1858
- const { preferences } = usePreferences();
1859
- const reflowActionKeys = preferences.actions.reflowOrder;
1860
- const fxlActionKeys = preferences.actions.fxlOrder;
1861
- const webPubActionKeys = preferences.actions.webPubOrder;
1862
- const reflowThemeKeys = preferences.theming.themes.reflowOrder;
1863
- const fxlThemeKeys = preferences.theming.themes.fxlOrder;
1864
- const reflowSettingsKeys = preferences.settings.reflowOrder;
1865
- const fxlSettingsKeys = preferences.settings.fxlOrder;
1866
- const webPubSettingsKeys = preferences.settings.webPubOrder;
1867
- const mainTextSettingsKeys = preferences.settings.text?.main ?? defaultTextSettingsMain;
1868
- const subPanelTextSettingsKeys = preferences.settings.text?.subPanel ?? defaultTextSettingsSubpanel;
1869
- const mainSpacingSettingsKeys = preferences.settings.spacing?.main ?? defaultSpacingSettingsMain;
1870
- const subPanelSpacingSettingsKeys = preferences.settings.spacing?.subPanel ?? defaultSpacingSettingsSubpanel;
1871
- const reflowSpacingPresetKeys = preferences.settings.spacing?.presets?.reflowOrder ?? defaultSpacingPresetsOrder;
1872
- const fxlSpacingPresetKeys = [];
1873
- const webPubSpacingPresetKeys = preferences.settings.spacing?.presets?.webPubOrder ?? defaultSpacingPresetsOrder;
1694
+ var useSharedPreferences = () => {
1695
+ const audioCtx = useContext(ThAudioPreferencesContext);
1696
+ const readerCtx = useContext(ThPreferencesContext);
1697
+ const ctx = audioCtx ?? readerCtx;
1698
+ if (!ctx) throw new Error("useSharedPreferences must be used within a ThPreferencesProvider or ThAudioPreferencesProvider");
1699
+ const prefs = ctx.preferences;
1874
1700
  return {
1875
- reflowActionKeys,
1876
- fxlActionKeys,
1877
- webPubActionKeys,
1878
- reflowThemeKeys,
1879
- fxlThemeKeys,
1880
- reflowSettingsKeys,
1881
- fxlSettingsKeys,
1882
- webPubSettingsKeys,
1883
- mainTextSettingsKeys,
1884
- subPanelTextSettingsKeys,
1885
- mainSpacingSettingsKeys,
1886
- subPanelSpacingSettingsKeys,
1887
- reflowSpacingPresetKeys,
1888
- fxlSpacingPresetKeys,
1889
- webPubSpacingPresetKeys
1890
- };
1891
- };
1892
-
1893
- // src/core/Helpers/prefixString.ts
1894
- var PREFIXES = {
1895
- short: "th",
1896
- full: "thorium_web"
1897
- };
1898
- var prefixString = (str, variant = "short") => {
1899
- return `${PREFIXES[variant]}-${str}`;
1900
- };
1901
-
1902
- // src/preferences/hooks/useTheming.ts
1903
- var useTheming = ({
1904
- theme,
1905
- systemKeys,
1906
- themeKeys,
1907
- breakpointsMap,
1908
- initProps,
1909
- onBreakpointChange,
1910
- onColorSchemeChange,
1911
- onContrastChange,
1912
- onForcedColorsChange,
1913
- onMonochromeChange,
1914
- onReducedMotionChange,
1915
- onReducedTransparencyChange
1916
- }) => {
1917
- const breakpoints = useBreakpoints(breakpointsMap, onBreakpointChange);
1918
- const colorScheme = useColorScheme(onColorSchemeChange);
1919
- const colorSchemeRef = useRef(colorScheme);
1920
- const contrast = useContrast(onContrastChange);
1921
- const forcedColors = useForcedColors(onForcedColorsChange);
1922
- const monochrome = useMonochrome(onMonochromeChange);
1923
- const reducedMotion = useReducedMotion(onReducedMotionChange);
1924
- const reducedTransparency = useReducedTransparency(onReducedTransparencyChange);
1925
- const updateThemeColorMetaTag = useCallback((color) => {
1926
- if (typeof document === "undefined") return;
1927
- let metaTag = document.querySelector("meta[name='theme-color']");
1928
- if (!metaTag) {
1929
- metaTag = document.createElement("meta");
1930
- metaTag.setAttribute("name", "theme-color");
1931
- document.head.appendChild(metaTag);
1932
- }
1933
- metaTag.setAttribute("content", color);
1934
- }, []);
1935
- const inferThemeAuto = useCallback(() => {
1936
- return colorSchemeRef.current === "dark" /* dark */ ? systemKeys?.dark : systemKeys?.light;
1937
- }, [systemKeys]);
1938
- const initThemingCustomProps = useCallback(() => {
1939
- for (let p in initProps) {
1940
- document.documentElement.style.setProperty(p, initProps[p]);
1941
- }
1942
- }, [initProps]);
1943
- const setThemeCustomProps = useCallback((t) => {
1944
- if (!t) {
1945
- return;
1946
- }
1947
- if (t === "auto") {
1948
- const autoTheme = inferThemeAuto();
1949
- if (!autoTheme) {
1950
- return;
1951
- }
1952
- t = autoTheme;
1953
- }
1954
- const themeTokens = themeKeys[t];
1955
- if (!themeTokens) {
1956
- return;
1957
- }
1958
- const props = propsToCSSVars(themeTokens, { prefix: prefixString("theme") });
1959
- for (let p in props) {
1960
- document.documentElement.style.setProperty(p, props[p]);
1701
+ direction: prefs.direction,
1702
+ locale: prefs.locale,
1703
+ shortcuts: prefs.shortcuts,
1704
+ docking: prefs.docking,
1705
+ theming: {
1706
+ icon: prefs.theming.icon,
1707
+ header: prefs.theming.header ? { backLink: prefs.theming.header.backLink } : void 0,
1708
+ themes: {
1709
+ systemThemes: prefs.theming.themes.systemThemes,
1710
+ keys: prefs.theming.themes.keys,
1711
+ audioOrder: audioCtx?.preferences.theming.themes.audioOrder,
1712
+ reflowOrder: readerCtx?.preferences.theming.themes.reflowOrder,
1713
+ fxlOrder: readerCtx?.preferences.theming.themes.fxlOrder
1714
+ },
1715
+ layout: {
1716
+ defaults: prefs.theming.layout.defaults
1717
+ },
1718
+ breakpoints: prefs.theming.breakpoints
1961
1719
  }
1962
- updateThemeColorMetaTag(themeTokens.background);
1963
- }, [inferThemeAuto, updateThemeColorMetaTag, themeKeys]);
1964
- useEffect(() => {
1965
- initThemingCustomProps();
1966
- }, [initThemingCustomProps]);
1967
- useEffect(() => {
1968
- colorSchemeRef.current = colorScheme;
1969
- setThemeCustomProps(theme);
1970
- }, [setThemeCustomProps, theme, colorScheme]);
1971
- return {
1972
- inferThemeAuto,
1973
- theme,
1974
- breakpoints,
1975
- colorScheme,
1976
- contrast,
1977
- forcedColors,
1978
- monochrome,
1979
- reducedMotion,
1980
- reducedTransparency
1981
1720
  };
1982
1721
  };
1983
1722
 
1984
- export { ThActionsKeys, ThDockingKeys, ThDockingTypes, ThLayoutOptions, ThLineHeightOptions, ThMemoryPreferencesAdapter, ThPreferencesContext, ThPreferencesProvider, ThSettingsContainerKeys, ThSettingsKeys, ThSettingsRangePlaceholder, ThSettingsRangeVariant, ThSheetHeaderVariant, ThSheetTypes, ThSpacingPresetKeys, ThSpacingSettingsKeys, ThTextAlignOptions, ThTextSettingsKeys, ThThemeKeys, buildThemeObject, contrast1Theme, contrast2Theme, contrast3Theme, createDefinitionFromStaticFonts, createDefinitionsFromBunnyFonts, createDefinitionsFromGoogleFonts, createPreferences, darkTheme, defaultActionKeysObject, defaultContentProtectionConfig, defaultFontCollection, defaultFullscreenAction, defaultJumpToPositionAction, defaultLetterSpacing, defaultLineHeights, defaultParagraphIndent, defaultParagraphSpacing, defaultPreferences, defaultPreferencesContextValue, defaultSettingsAction, defaultSpacingPresets, defaultSpacingPresetsOrder, defaultSpacingSettingsMain, defaultSpacingSettingsSubpanel, defaultTextSettingsMain, defaultTextSettingsSubpanel, defaultTocAction, defaultWordSpacing, defaultZoom, devContentProtectionConfig, lightTheme, paperTheme, prefixString, readiumCSSFontCollection, resolveContentProtectionConfig, sepiaTheme, tamilCollection, usePreferenceKeys, usePreferences, useTheming };
1985
- //# sourceMappingURL=chunk-7NEQAW7J.mjs.map
1986
- //# sourceMappingURL=chunk-7NEQAW7J.mjs.map
1723
+ export { ThActionsKeys, ThAudioActionKeys, ThAudioAffordance, ThAudioKeys, ThAudioPreferencesContext, ThDockingKeys, ThDockingTypes, ThLayoutOptions, ThLineHeightOptions, ThPreferencesContext, ThSettingsContainerKeys, ThSettingsKeys, ThSettingsRangePlaceholder, ThSettingsRangeVariant, ThSettingsTimerVariant, ThSheetHeaderVariant, ThSheetTypes, ThSpacingPresetKeys, ThSpacingSettingsKeys, ThTextAlignOptions, ThTextSettingsKeys, ThThemeKeys, contrast1Theme, contrast2Theme, contrast3Theme, createAudioPreferences, createDefinitionFromStaticFonts, createDefinitionsFromGoogleFonts, createPreferences, darkTheme, defaultActionKeysObject, defaultAudioContentProtectionConfig, defaultAudioPlaybackRate, defaultAudioPlaybackRateAction, defaultAudioPreferences, defaultAudioPreferencesContextValue, defaultAudioRemotePlaybackAction, defaultAudioSkipBackwardInterval, defaultAudioSkipForwardInterval, defaultAudioSkipInterval, defaultAudioSleepTimer, defaultAudioSleepTimerAction, defaultAudioSleepTimerPresetList, defaultAudioTocAction, defaultAudioVolume, defaultAudioVolumeAction, defaultContentProtectionConfig, defaultFontCollection, defaultFullscreenAction, defaultJumpToPositionAction, defaultLetterSpacing, defaultLineHeights, defaultParagraphIndent, defaultParagraphSpacing, defaultPreferences, defaultPreferencesContextValue, defaultSettingsAction, defaultSpacingPresets, defaultSpacingPresetsOrder, defaultSpacingSettingsMain, defaultSpacingSettingsSubpanel, defaultTextSettingsMain, defaultTextSettingsSubpanel, defaultTocAction, defaultWordSpacing, defaultZoom, devContentProtectionConfig, lightTheme, paperTheme, readiumCSSFontCollection, resolveAudioContentProtectionConfig, resolveContentProtectionConfig, sepiaTheme, tamilCollection, useSharedPreferences, validateObjectKeys };
1724
+ //# sourceMappingURL=chunk-C236BQQB.mjs.map
1725
+ //# sourceMappingURL=chunk-C236BQQB.mjs.map