@hanifhan1f/vidstack-react 1.12.25 → 1.12.30

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 (46) hide show
  1. package/dev/chunks/vidstack-BalWqr4j.js +1422 -0
  2. package/dev/chunks/vidstack-CKsUl4ll.js +1384 -0
  3. package/dev/chunks/vidstack-CqNX679o.js +669 -0
  4. package/dev/chunks/vidstack-D3ZXOE4d.js +643 -0
  5. package/dev/chunks/vidstack-DjqYvkVp.js +84 -0
  6. package/dev/chunks/vidstack-DqaqkU4T.js +9 -0
  7. package/dev/chunks/vidstack-FuCbl228.js +226 -0
  8. package/dev/chunks/vidstack-PREbBNMG.js +125 -0
  9. package/dev/chunks/vidstack-gqKBE4xH.js +376 -0
  10. package/dev/player/vidstack-default-components.js +9 -8
  11. package/dev/player/vidstack-default-icons.js +1 -1
  12. package/dev/player/vidstack-default-layout.js +9 -8
  13. package/dev/player/vidstack-plyr-layout.js +77 -63
  14. package/dev/player/vidstack-remotion.js +6 -6
  15. package/dev/vidstack.js +22 -133
  16. package/package.json +1 -1
  17. package/prod/chunks/vidstack-BCBskRpc.js +664 -0
  18. package/prod/chunks/vidstack-BZVrgeRF.js +9 -0
  19. package/prod/chunks/vidstack-CKapDFwB.js +376 -0
  20. package/prod/chunks/vidstack-CYK75vJF.js +1382 -0
  21. package/prod/chunks/vidstack-CtxjO6HG.js +84 -0
  22. package/prod/chunks/vidstack-D91K36KQ.js +206 -0
  23. package/prod/chunks/vidstack-DJThTSEm.js +125 -0
  24. package/prod/chunks/vidstack-DXSNXDnS.js +1384 -0
  25. package/prod/chunks/vidstack-DdiGCJVp.js +504 -0
  26. package/prod/player/vidstack-default-components.js +9 -8
  27. package/prod/player/vidstack-default-icons.js +1 -1
  28. package/prod/player/vidstack-default-layout.js +9 -8
  29. package/prod/player/vidstack-plyr-layout.js +77 -63
  30. package/prod/player/vidstack-remotion.js +6 -6
  31. package/prod/vidstack.js +22 -204
  32. package/server/chunks/vidstack-B4rJ1ZKK.js +376 -0
  33. package/server/chunks/vidstack-BTdEfKqV.js +84 -0
  34. package/server/chunks/vidstack-D4t_SZbb.js +1416 -0
  35. package/server/chunks/vidstack-DOIUveQF.js +504 -0
  36. package/server/chunks/vidstack-DbNoKLjz.js +664 -0
  37. package/server/chunks/vidstack-DeS67_gx.js +9 -0
  38. package/server/chunks/vidstack-DiHlnSws.js +1384 -0
  39. package/server/chunks/vidstack-DnoqxmOs.js +125 -0
  40. package/server/chunks/vidstack-SkX-mSrw.js +206 -0
  41. package/server/player/vidstack-default-components.js +9 -8
  42. package/server/player/vidstack-default-icons.js +1 -1
  43. package/server/player/vidstack-default-layout.js +9 -8
  44. package/server/player/vidstack-plyr-layout.js +77 -63
  45. package/server/player/vidstack-remotion.js +6 -6
  46. package/server/vidstack.js +22 -204
@@ -0,0 +1,1384 @@
1
+ "use client"
2
+
3
+ import * as React from 'react';
4
+ import { useSignal, composeRefs, isBoolean, uppercaseFirstChar, isUndefined, isString, isArray, camelToKebabCase, isKeyboardClick, listenEvent, toggleClass, useContext } from './vidstack-CYK75vJF.js';
5
+ import { createComputed, createSignal, MediaAnnouncer, Root, Trigger, Content, GoogleCastButton, Captions, useChapterOptions, Root$1 as Root$5, Root$2 as Root$6, Root$3 as Root$7, useScoped, Root$4 as Root$a, Group, useChapterTitle, createEffect, useActiveTextTrack, ChapterTitle as ChapterTitle$1, Title, Root$5 as Root$b, Track as Track$1, TrackFill as TrackFill$1 } from './vidstack-CKapDFwB.js';
6
+ import { useColorSchemePreference, useActive, useResizeObserver, useLayoutName, useTransitionActive } from './vidstack-CtxjO6HG.js';
7
+ import { useMediaContext, MuteButton, SeekButton, LiveButton, PlayButton, CaptionButton, appendParamsToURL, PIPButton, FullscreenButton, AirPlayButton, Items, Root$3 as Root$1, Item, Root as Root$2, Img, Root$2 as Root$3, Button, Portal, Track, TrackFill, Thumb, Steps, useMediaPlayer, Root$5 as Root$4, useAudioOptions, useCaptionOptions, Root$4 as Root$8, Preview, Value, Root$1 as Root$9, Chapters, Progress, Thumbnail, ChapterTitle, Time, Gesture } from './vidstack-BCBskRpc.js';
8
+ import { useMediaState, isRemotionSrc, Primitive } from './vidstack-D91K36KQ.js';
9
+ import { isTrackCaptionKind, getDownloadFile, sortVideoQualities, mediaContext } from 'vidstack';
10
+ import { flushSync } from 'react-dom';
11
+ import { RemotionThumbnail, RemotionSliderThumbnail } from './vidstack-BZVrgeRF.js';
12
+ import { FONT_FAMILY_OPTION, FONT_SIZE_OPTION, FONT_COLOR_OPTION, FONT_TEXT_SHADOW_OPTION, FONT_OPACITY_OPTION, onFontReset, FONT_SIGNALS, updateFontCssVars } from 'vidstack/exports/font.ts';
13
+
14
+ const DefaultLayoutContext = React.createContext({});
15
+ DefaultLayoutContext.displayName = "DefaultLayoutContext";
16
+ function useDefaultLayoutContext() {
17
+ return React.useContext(DefaultLayoutContext);
18
+ }
19
+ function useDefaultLayoutWord(word) {
20
+ const { translations } = useDefaultLayoutContext();
21
+ return i18n(translations, word);
22
+ }
23
+ function i18n(translations, word) {
24
+ return translations?.[word] ?? word;
25
+ }
26
+
27
+ function useColorSchemeClass(colorScheme) {
28
+ const systemColorPreference = useColorSchemePreference();
29
+ if (colorScheme === "default") {
30
+ return null;
31
+ } else if (colorScheme === "system") {
32
+ return systemColorPreference;
33
+ } else {
34
+ return colorScheme;
35
+ }
36
+ }
37
+
38
+ function createDefaultMediaLayout({
39
+ type,
40
+ smLayoutWhen,
41
+ renderLayout
42
+ }) {
43
+ const Layout = React.forwardRef(
44
+ ({
45
+ children,
46
+ className,
47
+ disableTimeSlider = false,
48
+ hideQualityBitrate = false,
49
+ icons,
50
+ colorScheme = "system",
51
+ download = null,
52
+ menuContainer = null,
53
+ menuGroup = "bottom",
54
+ noAudioGain = false,
55
+ audioGains = { min: 0, max: 300, step: 25 },
56
+ noGestures = false,
57
+ noKeyboardAnimations = false,
58
+ noModal = false,
59
+ noScrubGesture,
60
+ playbackRates = { min: 0, max: 2, step: 0.25 },
61
+ seekStep = 10,
62
+ episodes = null,
63
+ episodesTitle = "Episodes",
64
+ showMenuDelay,
65
+ showTooltipDelay = 700,
66
+ sliderChaptersMinWidth = 325,
67
+ slots,
68
+ smallLayoutWhen = smLayoutWhen,
69
+ thumbnails = null,
70
+ translations,
71
+ ...props
72
+ }, forwardRef) => {
73
+ const media = useMediaContext(), $load = useSignal(media.$props.load), $canLoad = useMediaState("canLoad"), $viewType = useMediaState("viewType"), $streamType = useMediaState("streamType"), $smallWhen = createComputed(() => {
74
+ return isBoolean(smallLayoutWhen) ? smallLayoutWhen : smallLayoutWhen(media.player.state);
75
+ }, [smallLayoutWhen]), userPrefersAnnouncements = createSignal(true), userPrefersKeyboardAnimations = createSignal(true), isMatch = $viewType === type, isSmallLayout = $smallWhen(), isForcedLayout = isBoolean(smallLayoutWhen), isLoadLayout = $load === "play" && !$canLoad, canRender = $canLoad || isForcedLayout || isLoadLayout, colorSchemeClass = useColorSchemeClass(colorScheme), layoutEl = createSignal(null);
76
+ useSignal($smallWhen);
77
+ return /* @__PURE__ */ React.createElement(
78
+ "div",
79
+ {
80
+ ...props,
81
+ className: `vds-${type}-layout` + (colorSchemeClass ? ` ${colorSchemeClass}` : "") + (className ? ` ${className}` : ""),
82
+ "data-match": isMatch ? "" : null,
83
+ "data-sm": isSmallLayout ? "" : null,
84
+ "data-lg": !isSmallLayout ? "" : null,
85
+ "data-size": isSmallLayout ? "sm" : "lg",
86
+ "data-no-scrub-gesture": noScrubGesture ? "" : null,
87
+ ref: composeRefs(layoutEl.set, forwardRef)
88
+ },
89
+ canRender && isMatch ? /* @__PURE__ */ React.createElement(
90
+ DefaultLayoutContext.Provider,
91
+ {
92
+ value: {
93
+ disableTimeSlider,
94
+ hideQualityBitrate,
95
+ icons,
96
+ colorScheme,
97
+ download,
98
+ isSmallLayout,
99
+ menuContainer,
100
+ menuGroup,
101
+ noAudioGain,
102
+ audioGains,
103
+ layoutEl,
104
+ noGestures,
105
+ noKeyboardAnimations,
106
+ noModal,
107
+ noScrubGesture,
108
+ showMenuDelay,
109
+ showTooltipDelay,
110
+ sliderChaptersMinWidth,
111
+ slots,
112
+ seekStep,
113
+ episodes,
114
+ episodesTitle,
115
+ playbackRates,
116
+ thumbnails,
117
+ translations,
118
+ userPrefersAnnouncements,
119
+ userPrefersKeyboardAnimations
120
+ }
121
+ },
122
+ renderLayout({ streamType: $streamType, isSmallLayout, isLoadLayout }),
123
+ children
124
+ ) : null
125
+ );
126
+ }
127
+ );
128
+ Layout.displayName = "DefaultMediaLayout";
129
+ return Layout;
130
+ }
131
+
132
+ function useDefaultAudioLayoutSlots() {
133
+ return React.useContext(DefaultLayoutContext).slots;
134
+ }
135
+ function useDefaultVideoLayoutSlots() {
136
+ return React.useContext(DefaultLayoutContext).slots;
137
+ }
138
+ function slot(slots, name, defaultValue) {
139
+ const slot2 = slots?.[name], capitalizedName = uppercaseFirstChar(name);
140
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, slots?.[`before${capitalizedName}`], isUndefined(slot2) ? defaultValue : slot2, slots?.[`after${capitalizedName}`]);
141
+ }
142
+
143
+ function DefaultAnnouncer() {
144
+ const { userPrefersAnnouncements, translations } = useDefaultLayoutContext(), $userPrefersAnnouncements = useSignal(userPrefersAnnouncements);
145
+ if (!$userPrefersAnnouncements) return null;
146
+ return /* @__PURE__ */ React.createElement(MediaAnnouncer, { translations });
147
+ }
148
+ DefaultAnnouncer.displayName = "DefaultAnnouncer";
149
+
150
+ function DefaultTooltip({ content, placement, children }) {
151
+ const { showTooltipDelay } = useDefaultLayoutContext();
152
+ return /* @__PURE__ */ React.createElement(Root, { showDelay: showTooltipDelay }, /* @__PURE__ */ React.createElement(Trigger, { asChild: true }, children), /* @__PURE__ */ React.createElement(Content, { className: "vds-tooltip-content", placement }, content));
153
+ }
154
+ DefaultTooltip.displayName = "DefaultTooltip";
155
+
156
+ function DefaultPlayButton({ tooltip }) {
157
+ const { icons: Icons } = useDefaultLayoutContext(), playText = useDefaultLayoutWord("Play"), pauseText = useDefaultLayoutWord("Pause"), $paused = useMediaState("paused"), $ended = useMediaState("ended");
158
+ return /* @__PURE__ */ React.createElement(DefaultTooltip, { content: $paused ? playText : pauseText, placement: tooltip }, /* @__PURE__ */ React.createElement(PlayButton, { className: "vds-play-button vds-button", "aria-label": playText }, $ended ? /* @__PURE__ */ React.createElement(Icons.PlayButton.Replay, { className: "vds-icon" }) : $paused ? /* @__PURE__ */ React.createElement(Icons.PlayButton.Play, { className: "vds-icon" }) : /* @__PURE__ */ React.createElement(Icons.PlayButton.Pause, { className: "vds-icon" })));
159
+ }
160
+ DefaultPlayButton.displayName = "DefaultPlayButton";
161
+ const DefaultMuteButton = React.forwardRef(
162
+ ({ tooltip }, forwardRef) => {
163
+ const { icons: Icons } = useDefaultLayoutContext(), muteText = useDefaultLayoutWord("Mute"), unmuteText = useDefaultLayoutWord("Unmute"), $muted = useMediaState("muted"), $volume = useMediaState("volume");
164
+ return /* @__PURE__ */ React.createElement(DefaultTooltip, { content: $muted ? unmuteText : muteText, placement: tooltip }, /* @__PURE__ */ React.createElement(MuteButton, { className: "vds-mute-button vds-button", "aria-label": muteText, ref: forwardRef }, $muted || $volume == 0 ? /* @__PURE__ */ React.createElement(Icons.MuteButton.Mute, { className: "vds-icon" }) : $volume < 0.5 ? /* @__PURE__ */ React.createElement(Icons.MuteButton.VolumeLow, { className: "vds-icon" }) : /* @__PURE__ */ React.createElement(Icons.MuteButton.VolumeHigh, { className: "vds-icon" })));
165
+ }
166
+ );
167
+ DefaultMuteButton.displayName = "DefaultMuteButton";
168
+ function DefaultCaptionButton({ tooltip }) {
169
+ const { icons: Icons } = useDefaultLayoutContext(), captionsText = useDefaultLayoutWord("Captions"), onText = useDefaultLayoutWord("Closed-Captions On"), offText = useDefaultLayoutWord("Closed-Captions Off"), $track = useMediaState("textTrack"), isOn = $track && isTrackCaptionKind($track);
170
+ return /* @__PURE__ */ React.createElement(DefaultTooltip, { content: isOn ? onText : offText, placement: tooltip }, /* @__PURE__ */ React.createElement(CaptionButton, { className: "vds-caption-button vds-button", "aria-label": captionsText }, isOn ? /* @__PURE__ */ React.createElement(Icons.CaptionButton.On, { className: "vds-icon" }) : /* @__PURE__ */ React.createElement(Icons.CaptionButton.Off, { className: "vds-icon" })));
171
+ }
172
+ DefaultCaptionButton.displayName = "DefaultCaptionButton";
173
+ function DefaultPIPButton({ tooltip }) {
174
+ const { icons: Icons } = useDefaultLayoutContext(), pipText = useDefaultLayoutWord("PiP"), enterText = useDefaultLayoutWord("Enter PiP"), exitText = useDefaultLayoutWord("Exit PiP"), $pip = useMediaState("pictureInPicture");
175
+ return /* @__PURE__ */ React.createElement(DefaultTooltip, { content: $pip ? exitText : enterText, placement: tooltip }, /* @__PURE__ */ React.createElement(PIPButton, { className: "vds-pip-button vds-button", "aria-label": pipText }, $pip ? /* @__PURE__ */ React.createElement(Icons.PIPButton.Exit, { className: "vds-icon" }) : /* @__PURE__ */ React.createElement(Icons.PIPButton.Enter, { className: "vds-icon" })));
176
+ }
177
+ DefaultPIPButton.displayName = "DefaultPIPButton";
178
+ function DefaultFullscreenButton({ tooltip }) {
179
+ const { icons: Icons } = useDefaultLayoutContext(), fullscreenText = useDefaultLayoutWord("Fullscreen"), enterText = useDefaultLayoutWord("Enter Fullscreen"), exitText = useDefaultLayoutWord("Exit Fullscreen"), $fullscreen = useMediaState("fullscreen");
180
+ return /* @__PURE__ */ React.createElement(DefaultTooltip, { content: $fullscreen ? exitText : enterText, placement: tooltip }, /* @__PURE__ */ React.createElement(FullscreenButton, { className: "vds-fullscreen-button vds-button", "aria-label": fullscreenText }, $fullscreen ? /* @__PURE__ */ React.createElement(Icons.FullscreenButton.Exit, { className: "vds-icon" }) : /* @__PURE__ */ React.createElement(Icons.FullscreenButton.Enter, { className: "vds-icon" })));
181
+ }
182
+ DefaultFullscreenButton.displayName = "DefaultFullscreenButton";
183
+ function DefaultSeekButton({
184
+ backward,
185
+ tooltip
186
+ }) {
187
+ const { icons: Icons, seekStep } = useDefaultLayoutContext(), seekForwardText = useDefaultLayoutWord("Seek Forward"), seekBackwardText = useDefaultLayoutWord("Seek Backward"), seconds = (backward ? -1 : 1) * seekStep, label = seconds >= 0 ? seekForwardText : seekBackwardText;
188
+ return /* @__PURE__ */ React.createElement(DefaultTooltip, { content: label, placement: tooltip }, /* @__PURE__ */ React.createElement(SeekButton, { className: "vds-seek-button vds-button", seconds, "aria-label": label }, seconds >= 0 ? /* @__PURE__ */ React.createElement(Icons.SeekButton.Forward, { className: "vds-icon" }) : /* @__PURE__ */ React.createElement(Icons.SeekButton.Backward, { className: "vds-icon" })));
189
+ }
190
+ DefaultSeekButton.displayName = "DefaultSeekButton";
191
+ function DefaultEpisodeButton({ tooltip, onPress }) {
192
+ const { icons: Icons } = useDefaultLayoutContext(), episodesText = useDefaultLayoutWord("Episodes");
193
+ return /* @__PURE__ */ React.createElement(DefaultTooltip, { content: episodesText, placement: tooltip }, /* @__PURE__ */ React.createElement(
194
+ "button",
195
+ {
196
+ type: "button",
197
+ className: "vds-episode-button vds-button",
198
+ "aria-label": episodesText,
199
+ onPointerUp: (event) => {
200
+ event.stopPropagation();
201
+ onPress?.(event);
202
+ }
203
+ },
204
+ /* @__PURE__ */ React.createElement(Icons.Menu.Chapters, { className: "vds-icon" })
205
+ ));
206
+ }
207
+ DefaultEpisodeButton.displayName = "DefaultEpisodeButton";
208
+ function DefaultAirPlayButton({ tooltip }) {
209
+ const { icons: Icons } = useDefaultLayoutContext(), airPlayText = useDefaultLayoutWord("AirPlay"), $state = useMediaState("remotePlaybackState"), stateText = useDefaultLayoutWord(uppercaseFirstChar($state)), label = `${airPlayText} ${stateText}`, Icon = ($state === "connecting" ? Icons.AirPlayButton.Connecting : $state === "connected" ? Icons.AirPlayButton.Connected : null) ?? Icons.AirPlayButton.Default;
210
+ return /* @__PURE__ */ React.createElement(DefaultTooltip, { content: airPlayText, placement: tooltip }, /* @__PURE__ */ React.createElement(AirPlayButton, { className: "vds-airplay-button vds-button", "aria-label": label }, /* @__PURE__ */ React.createElement(Icon, { className: "vds-icon" })));
211
+ }
212
+ DefaultAirPlayButton.displayName = "DefaultAirPlayButton";
213
+ function DefaultGoogleCastButton({ tooltip }) {
214
+ const { icons: Icons } = useDefaultLayoutContext(), googleCastText = useDefaultLayoutWord("Google Cast"), $state = useMediaState("remotePlaybackState"), stateText = useDefaultLayoutWord(uppercaseFirstChar($state)), label = `${googleCastText} ${stateText}`, Icon = ($state === "connecting" ? Icons.GoogleCastButton.Connecting : $state === "connected" ? Icons.GoogleCastButton.Connected : null) ?? Icons.GoogleCastButton.Default;
215
+ return /* @__PURE__ */ React.createElement(DefaultTooltip, { content: googleCastText, placement: tooltip }, /* @__PURE__ */ React.createElement(GoogleCastButton, { className: "vds-google-cast-button vds-button", "aria-label": label }, /* @__PURE__ */ React.createElement(Icon, { className: "vds-icon" })));
216
+ }
217
+ DefaultGoogleCastButton.displayName = "DefaultGoogleCastButton";
218
+ function DefaultLiveButton() {
219
+ const $live = useMediaState("live"), label = useDefaultLayoutWord("Skip To Live"), liveText = useDefaultLayoutWord("LIVE");
220
+ return $live ? /* @__PURE__ */ React.createElement(LiveButton, { className: "vds-live-button", "aria-label": label }, /* @__PURE__ */ React.createElement("span", { className: "vds-live-button-text" }, liveText)) : null;
221
+ }
222
+ DefaultLiveButton.displayName = "DefaultLiveButton";
223
+ function DefaultDownloadButton() {
224
+ const { download, icons: Icons } = useDefaultLayoutContext(), $src = useMediaState("source"), $title = useMediaState("title"), file = getDownloadFile({
225
+ title: $title,
226
+ src: $src,
227
+ download
228
+ }), downloadText = useDefaultLayoutWord("Download");
229
+ return isString(file?.url) ? /* @__PURE__ */ React.createElement(DefaultTooltip, { content: downloadText, placement: "top" }, /* @__PURE__ */ React.createElement(
230
+ "a",
231
+ {
232
+ role: "button",
233
+ className: "vds-download-button vds-button",
234
+ "aria-label": downloadText,
235
+ href: appendParamsToURL(file.url, { download: file.name }),
236
+ download: file.name,
237
+ target: "_blank"
238
+ },
239
+ Icons.DownloadButton ? /* @__PURE__ */ React.createElement(Icons.DownloadButton.Default, { className: "vds-icon" }) : null
240
+ )) : null;
241
+ }
242
+ DefaultDownloadButton.displayName = "DefaultDownloadButton";
243
+
244
+ function DefaultCaptions() {
245
+ const exampleText = useDefaultLayoutWord("Captions look like this");
246
+ return /* @__PURE__ */ React.createElement(Captions, { className: "vds-captions", exampleText });
247
+ }
248
+ DefaultCaptions.displayName = "DefaultCaptions";
249
+
250
+ function DefaultControlsSpacer() {
251
+ return /* @__PURE__ */ React.createElement("div", { className: "vds-controls-spacer" });
252
+ }
253
+ DefaultControlsSpacer.displayName = "DefaultControlsSpacer";
254
+
255
+ function useParentDialogEl() {
256
+ const { layoutEl } = useDefaultLayoutContext(), $layoutEl = useSignal(layoutEl);
257
+ return React.useMemo(() => $layoutEl?.closest("dialog"), [$layoutEl]);
258
+ }
259
+
260
+ function DefaultChaptersMenu({ tooltip, placement, portalClass = "" }) {
261
+ const {
262
+ showMenuDelay,
263
+ noModal,
264
+ isSmallLayout,
265
+ icons: Icons,
266
+ menuGroup,
267
+ menuContainer,
268
+ colorScheme
269
+ } = useDefaultLayoutContext(), chaptersText = useDefaultLayoutWord("Chapters"), options = useChapterOptions(), disabled = !options.length, { thumbnails } = useDefaultLayoutContext(), $src = useMediaState("currentSrc"), $viewType = useMediaState("viewType"), $offset = !isSmallLayout && menuGroup === "bottom" && $viewType === "video" ? 26 : 0, $RemotionThumbnail = useSignal(RemotionThumbnail), colorSchemeClass = useColorSchemeClass(colorScheme), [isOpen, setIsOpen] = React.useState(false), dialogEl = useParentDialogEl();
270
+ if (disabled) return null;
271
+ function onOpen() {
272
+ flushSync(() => {
273
+ setIsOpen(true);
274
+ });
275
+ }
276
+ function onClose() {
277
+ setIsOpen(false);
278
+ }
279
+ const Content = /* @__PURE__ */ React.createElement(
280
+ Items,
281
+ {
282
+ className: "vds-chapters-menu-items vds-menu-items",
283
+ placement,
284
+ offset: $offset
285
+ },
286
+ isOpen ? /* @__PURE__ */ React.createElement(
287
+ Root$1,
288
+ {
289
+ className: "vds-chapters-radio-group vds-radio-group",
290
+ value: options.selectedValue,
291
+ "data-thumbnails": thumbnails ? "" : null
292
+ },
293
+ options.map(
294
+ ({ cue, label, value, startTimeText, durationText, select, setProgressVar }) => /* @__PURE__ */ React.createElement(
295
+ Item,
296
+ {
297
+ className: "vds-chapter-radio vds-radio",
298
+ value,
299
+ key: value,
300
+ onSelect: select,
301
+ ref: setProgressVar
302
+ },
303
+ thumbnails ? /* @__PURE__ */ React.createElement(Root$2, { src: thumbnails, className: "vds-thumbnail", time: cue.startTime }, /* @__PURE__ */ React.createElement(Img, null)) : $RemotionThumbnail && isRemotionSrc($src) ? /* @__PURE__ */ React.createElement($RemotionThumbnail, { className: "vds-thumbnail", frame: cue.startTime * $src.fps }) : null,
304
+ /* @__PURE__ */ React.createElement("div", { className: "vds-chapter-radio-content" }, /* @__PURE__ */ React.createElement("span", { className: "vds-chapter-radio-label" }, label), /* @__PURE__ */ React.createElement("span", { className: "vds-chapter-radio-start-time" }, startTimeText), /* @__PURE__ */ React.createElement("span", { className: "vds-chapter-radio-duration" }, durationText))
305
+ )
306
+ )
307
+ ) : null
308
+ );
309
+ return /* @__PURE__ */ React.createElement(
310
+ Root$3,
311
+ {
312
+ className: "vds-chapters-menu vds-menu",
313
+ showDelay: showMenuDelay,
314
+ onOpen,
315
+ onClose
316
+ },
317
+ /* @__PURE__ */ React.createElement(DefaultTooltip, { content: chaptersText, placement: tooltip }, /* @__PURE__ */ React.createElement(
318
+ Button,
319
+ {
320
+ className: "vds-menu-button vds-button",
321
+ disabled,
322
+ "aria-label": chaptersText
323
+ },
324
+ /* @__PURE__ */ React.createElement(Icons.Menu.Chapters, { className: "vds-icon" })
325
+ )),
326
+ noModal || !isSmallLayout ? Content : /* @__PURE__ */ React.createElement(
327
+ Portal,
328
+ {
329
+ container: menuContainer ?? dialogEl,
330
+ className: portalClass + (colorSchemeClass ? ` ${colorSchemeClass}` : ""),
331
+ disabled: "fullscreen",
332
+ "data-sm": isSmallLayout ? "" : null,
333
+ "data-lg": !isSmallLayout ? "" : null,
334
+ "data-size": isSmallLayout ? "sm" : "lg"
335
+ },
336
+ Content
337
+ )
338
+ );
339
+ }
340
+ DefaultChaptersMenu.displayName = "DefaultChaptersMenu";
341
+
342
+ function DefaultMenuSection({ label, value, children }) {
343
+ const id = React.useId();
344
+ if (!label) {
345
+ return /* @__PURE__ */ React.createElement("div", { className: "vds-menu-section" }, /* @__PURE__ */ React.createElement("div", { className: "vds-menu-section-body" }, children));
346
+ }
347
+ return /* @__PURE__ */ React.createElement("section", { className: "vds-menu-section", role: "group", "aria-labelledby": id }, /* @__PURE__ */ React.createElement("div", { className: "vds-menu-section-title" }, /* @__PURE__ */ React.createElement("header", { id }, label), value ? /* @__PURE__ */ React.createElement("div", { className: "vds-menu-section-value" }, value) : null), /* @__PURE__ */ React.createElement("div", { className: "vds-menu-section-body" }, children));
348
+ }
349
+ DefaultMenuSection.displayName = "DefaultMenuSection";
350
+ function DefaultMenuButton({ label, hint = "", Icon, disabled = false }) {
351
+ const { icons: Icons } = React.useContext(DefaultLayoutContext);
352
+ return /* @__PURE__ */ React.createElement(Button, { className: "vds-menu-item", disabled }, /* @__PURE__ */ React.createElement(Icons.Menu.ArrowLeft, { className: "vds-menu-close-icon vds-icon" }), Icon ? /* @__PURE__ */ React.createElement(Icon, { className: "vds-menu-item-icon vds-icon" }) : null, /* @__PURE__ */ React.createElement("span", { className: "vds-menu-item-label" }, label), /* @__PURE__ */ React.createElement("span", { className: "vds-menu-item-hint" }, hint), /* @__PURE__ */ React.createElement(Icons.Menu.ArrowRight, { className: "vds-menu-open-icon vds-icon" }));
353
+ }
354
+ DefaultMenuButton.displayName = "DefaultMenuButton";
355
+ function DefaultMenuItem({ label, children }) {
356
+ return /* @__PURE__ */ React.createElement("div", { className: "vds-menu-item" }, /* @__PURE__ */ React.createElement("div", { className: "vds-menu-item-label" }, label), children);
357
+ }
358
+ DefaultMenuItem.displayName = "DefaultMenuItem";
359
+ function DefaultMenuRadioGroup({ value, options, onChange }) {
360
+ const { icons: Icons } = useDefaultLayoutContext();
361
+ return /* @__PURE__ */ React.createElement(Root$1, { className: "vds-radio-group", value, onChange }, options.map((option) => /* @__PURE__ */ React.createElement(Item, { className: "vds-radio", value: option.value, key: option.value }, /* @__PURE__ */ React.createElement(Icons.Menu.RadioCheck, { className: "vds-icon" }), /* @__PURE__ */ React.createElement("span", { className: "vds-radio-label", "data-part": "label" }, option.label))));
362
+ }
363
+ DefaultMenuRadioGroup.displayName = "DefaultMenuRadioGroup";
364
+ function createRadioOptions(entries) {
365
+ return React.useMemo(
366
+ () => isArray(entries) ? entries.map((entry) => ({ label: entry, value: entry.toLowerCase() })) : Object.keys(entries).map((label) => ({ label, value: entries[label] })),
367
+ [entries]
368
+ );
369
+ }
370
+
371
+ function DefaultMenuSliderItem({
372
+ label,
373
+ value,
374
+ UpIcon,
375
+ DownIcon,
376
+ children,
377
+ isMin,
378
+ isMax
379
+ }) {
380
+ const hasTitle = label || value, Content = /* @__PURE__ */ React.createElement(React.Fragment, null, DownIcon ? /* @__PURE__ */ React.createElement(DownIcon, { className: "vds-icon down" }) : null, children, UpIcon ? /* @__PURE__ */ React.createElement(UpIcon, { className: "vds-icon up" }) : null);
381
+ return /* @__PURE__ */ React.createElement(
382
+ "div",
383
+ {
384
+ className: `vds-menu-item vds-menu-slider-item${hasTitle ? " group" : ""}`,
385
+ "data-min": isMin ? "" : null,
386
+ "data-max": isMax ? "" : null
387
+ },
388
+ hasTitle ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "vds-menu-slider-title" }, label ? /* @__PURE__ */ React.createElement("div", null, label) : null, value ? /* @__PURE__ */ React.createElement("div", null, value) : null), /* @__PURE__ */ React.createElement("div", { className: "vds-menu-slider-body" }, Content)) : Content
389
+ );
390
+ }
391
+ DefaultMenuSliderItem.displayName = "DefaultMenuSliderItem";
392
+ function DefaultSliderParts() {
393
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Track, { className: "vds-slider-track" }), /* @__PURE__ */ React.createElement(TrackFill, { className: "vds-slider-track-fill vds-slider-track" }), /* @__PURE__ */ React.createElement(Thumb, { className: "vds-slider-thumb" }));
394
+ }
395
+ DefaultSliderParts.displayName = "DefaultSliderParts";
396
+ function DefaultSliderSteps() {
397
+ return /* @__PURE__ */ React.createElement(Steps, { className: "vds-slider-steps" }, (step) => /* @__PURE__ */ React.createElement("div", { className: "vds-slider-step", key: String(step) }));
398
+ }
399
+ DefaultSliderSteps.displayName = "DefaultSliderSteps";
400
+
401
+ function DefaultFontMenu() {
402
+ const label = useDefaultLayoutWord("Caption Styles"), $hasCaptions = useMediaState("hasCaptions"), fontSectionLabel = useDefaultLayoutWord("Font"), textSectionLabel = useDefaultLayoutWord("Text"), textBgSectionLabel = useDefaultLayoutWord("Text Background"), displayBgSectionLabel = useDefaultLayoutWord("Display Background");
403
+ if (!$hasCaptions) return null;
404
+ return /* @__PURE__ */ React.createElement(Root$3, { className: "vds-font-menu vds-menu" }, /* @__PURE__ */ React.createElement(DefaultMenuButton, { label }), /* @__PURE__ */ React.createElement(Items, { className: "vds-font-style-items vds-menu-items" }, /* @__PURE__ */ React.createElement(DefaultMenuSection, { label: fontSectionLabel }, /* @__PURE__ */ React.createElement(DefaultFontFamilyMenu, null), /* @__PURE__ */ React.createElement(DefaultFontSizeSlider, null)), /* @__PURE__ */ React.createElement(DefaultMenuSection, { label: textSectionLabel }, /* @__PURE__ */ React.createElement(DefaultTextColorInput, null), /* @__PURE__ */ React.createElement(DefaultTextShadowMenu, null), /* @__PURE__ */ React.createElement(DefaultTextOpacitySlider, null)), /* @__PURE__ */ React.createElement(DefaultMenuSection, { label: textBgSectionLabel }, /* @__PURE__ */ React.createElement(DefaultTextBgInput, null), /* @__PURE__ */ React.createElement(DefaultTextBgOpacitySlider, null)), /* @__PURE__ */ React.createElement(DefaultMenuSection, { label: displayBgSectionLabel }, /* @__PURE__ */ React.createElement(DefaultDisplayBgInput, null), /* @__PURE__ */ React.createElement(DefaultDisplayBgOpacitySlider, null)), /* @__PURE__ */ React.createElement(DefaultMenuSection, null, /* @__PURE__ */ React.createElement(DefaultResetMenuItem, null))));
405
+ }
406
+ DefaultFontMenu.displayName = "DefaultFontMenu";
407
+ function DefaultFontFamilyMenu() {
408
+ return /* @__PURE__ */ React.createElement(DefaultFontSetting, { label: "Family", type: "fontFamily", option: FONT_FAMILY_OPTION });
409
+ }
410
+ DefaultFontFamilyMenu.displayName = "DefaultFontFamilyMenu";
411
+ function DefaultFontSizeSlider() {
412
+ const { icons: Icons } = useDefaultLayoutContext(), option = {
413
+ ...FONT_SIZE_OPTION,
414
+ upIcon: Icons.Menu.FontSizeUp,
415
+ downIcon: Icons.Menu.FontSizeDown
416
+ };
417
+ return /* @__PURE__ */ React.createElement(DefaultFontSetting, { label: "Size", type: "fontSize", option });
418
+ }
419
+ DefaultFontSizeSlider.displayName = "DefaultFontSizeSlider";
420
+ function DefaultTextColorInput() {
421
+ return /* @__PURE__ */ React.createElement(DefaultFontSetting, { label: "Color", type: "textColor", option: FONT_COLOR_OPTION });
422
+ }
423
+ DefaultTextColorInput.displayName = "DefaultTextColorInput";
424
+ function DefaultTextOpacitySlider() {
425
+ const { icons: Icons } = useDefaultLayoutContext(), option = {
426
+ ...FONT_OPACITY_OPTION,
427
+ upIcon: Icons.Menu.OpacityUp,
428
+ downIcon: Icons.Menu.OpacityDown
429
+ };
430
+ return /* @__PURE__ */ React.createElement(DefaultFontSetting, { label: "Opacity", type: "textOpacity", option });
431
+ }
432
+ DefaultTextOpacitySlider.displayName = "DefaultTextOpacitySlider";
433
+ function DefaultTextShadowMenu() {
434
+ return /* @__PURE__ */ React.createElement(DefaultFontSetting, { label: "Shadow", type: "textShadow", option: FONT_TEXT_SHADOW_OPTION });
435
+ }
436
+ DefaultTextShadowMenu.displayName = "DefaultTextShadowMenu";
437
+ function DefaultTextBgInput() {
438
+ return /* @__PURE__ */ React.createElement(DefaultFontSetting, { label: "Color", type: "textBg", option: FONT_COLOR_OPTION });
439
+ }
440
+ DefaultTextBgInput.displayName = "DefaultTextBgInput";
441
+ function DefaultTextBgOpacitySlider() {
442
+ const { icons: Icons } = useDefaultLayoutContext(), option = {
443
+ ...FONT_OPACITY_OPTION,
444
+ upIcon: Icons.Menu.OpacityUp,
445
+ downIcon: Icons.Menu.OpacityDown
446
+ };
447
+ return /* @__PURE__ */ React.createElement(DefaultFontSetting, { label: "Opacity", type: "textBgOpacity", option });
448
+ }
449
+ DefaultTextBgOpacitySlider.displayName = "DefaultTextBgOpacitySlider";
450
+ function DefaultDisplayBgInput() {
451
+ return /* @__PURE__ */ React.createElement(DefaultFontSetting, { label: "Color", type: "displayBg", option: FONT_COLOR_OPTION });
452
+ }
453
+ DefaultDisplayBgInput.displayName = "DefaultDisplayBgInput";
454
+ function DefaultDisplayBgOpacitySlider() {
455
+ const { icons: Icons } = useDefaultLayoutContext(), option = {
456
+ ...FONT_OPACITY_OPTION,
457
+ upIcon: Icons.Menu.OpacityUp,
458
+ downIcon: Icons.Menu.OpacityDown
459
+ };
460
+ return /* @__PURE__ */ React.createElement(DefaultFontSetting, { label: "Opacity", type: "displayBgOpacity", option });
461
+ }
462
+ DefaultDisplayBgOpacitySlider.displayName = "DefaultDisplayBgOpacitySlider";
463
+ function DefaultFontSetting({ label, option, type }) {
464
+ const player = useMediaPlayer(), $currentValue = FONT_SIGNALS[type], $value = useSignal($currentValue), translatedLabel = useDefaultLayoutWord(label);
465
+ const notify = React.useCallback(() => {
466
+ player?.dispatchEvent(new Event("vds-font-change"));
467
+ }, [player]);
468
+ const onChange = React.useCallback(
469
+ (newValue) => {
470
+ $currentValue.set(newValue);
471
+ notify();
472
+ },
473
+ [$currentValue, notify]
474
+ );
475
+ if (option.type === "color") {
476
+ let onColorChange2 = function(event) {
477
+ onChange(event.target.value);
478
+ };
479
+ return /* @__PURE__ */ React.createElement(DefaultMenuItem, { label: translatedLabel }, /* @__PURE__ */ React.createElement("input", { className: "vds-color-picker", type: "color", value: $value, onChange: onColorChange2 }));
480
+ }
481
+ if (option.type === "slider") {
482
+ let onSliderValueChange2 = function(value) {
483
+ onChange(value + "%");
484
+ };
485
+ const { min, max, step, upIcon, downIcon } = option;
486
+ return /* @__PURE__ */ React.createElement(
487
+ DefaultMenuSliderItem,
488
+ {
489
+ label: translatedLabel,
490
+ value: $value,
491
+ UpIcon: upIcon,
492
+ DownIcon: downIcon,
493
+ isMin: $value === min + "%",
494
+ isMax: $value === max + "%"
495
+ },
496
+ /* @__PURE__ */ React.createElement(
497
+ Root$4,
498
+ {
499
+ className: "vds-slider",
500
+ min,
501
+ max,
502
+ step,
503
+ keyStep: step,
504
+ value: parseInt($value),
505
+ "aria-label": translatedLabel,
506
+ onValueChange: onSliderValueChange2,
507
+ onDragValueChange: onSliderValueChange2
508
+ },
509
+ /* @__PURE__ */ React.createElement(DefaultSliderParts, null),
510
+ /* @__PURE__ */ React.createElement(DefaultSliderSteps, null)
511
+ )
512
+ );
513
+ }
514
+ if (option.type === "radio") {
515
+ return /* @__PURE__ */ React.createElement(
516
+ DefaultFontRadioGroup,
517
+ {
518
+ id: camelToKebabCase(type),
519
+ label: translatedLabel,
520
+ value: $value,
521
+ values: option.values,
522
+ onChange
523
+ }
524
+ );
525
+ }
526
+ return null;
527
+ }
528
+ DefaultFontSetting.displayName = "DefaultFontSetting";
529
+ function DefaultFontRadioGroup({ id, label, value, values, onChange }) {
530
+ const radioOptions = createRadioOptions(values), { translations } = useDefaultLayoutContext(), hint = React.useMemo(() => {
531
+ const label2 = radioOptions.find((radio) => radio.value === value)?.label || "";
532
+ return i18n(translations, label2);
533
+ }, [value, radioOptions]);
534
+ return /* @__PURE__ */ React.createElement(Root$3, { className: `vds-${id}-menu vds-menu` }, /* @__PURE__ */ React.createElement(DefaultMenuButton, { label, hint }), /* @__PURE__ */ React.createElement(Items, { className: "vds-menu-items" }, /* @__PURE__ */ React.createElement(DefaultMenuRadioGroup, { value, options: radioOptions, onChange })));
535
+ }
536
+ DefaultFontRadioGroup.displayName = "DefaultFontRadioGroup";
537
+ function DefaultResetMenuItem() {
538
+ const resetText = useDefaultLayoutWord("Reset");
539
+ return /* @__PURE__ */ React.createElement("button", { className: "vds-menu-item", role: "menuitem", onClick: onFontReset }, /* @__PURE__ */ React.createElement("span", { className: "vds-menu-item-label" }, resetText));
540
+ }
541
+ DefaultResetMenuItem.displayName = "DefaultResetMenuItem";
542
+
543
+ function DefaultMenuCheckbox({
544
+ label,
545
+ checked,
546
+ storageKey,
547
+ defaultChecked = false,
548
+ onChange
549
+ }) {
550
+ const [isChecked, setIsChecked] = React.useState(defaultChecked), [isActive, setIsActive] = React.useState(false);
551
+ React.useEffect(() => {
552
+ const savedValue = storageKey ? localStorage.getItem(storageKey) : null, checked2 = !!(savedValue ?? defaultChecked);
553
+ setIsChecked(checked2);
554
+ onChange?.(checked2);
555
+ }, []);
556
+ React.useEffect(() => {
557
+ if (isBoolean(checked)) setIsChecked(checked);
558
+ }, [checked]);
559
+ function onPress(event) {
560
+ if (event && "button" in event && event?.button === 1) return;
561
+ const toggledCheck = !isChecked;
562
+ setIsChecked(toggledCheck);
563
+ if (storageKey) localStorage.setItem(storageKey, toggledCheck ? "1" : "");
564
+ onChange?.(toggledCheck, event?.nativeEvent);
565
+ setIsActive(false);
566
+ }
567
+ function onActive(event) {
568
+ if (event.button !== 0) return;
569
+ setIsActive(true);
570
+ }
571
+ function onKeyDown(event) {
572
+ if (isKeyboardClick(event.nativeEvent)) onPress();
573
+ }
574
+ return /* @__PURE__ */ React.createElement(
575
+ "div",
576
+ {
577
+ className: "vds-menu-checkbox",
578
+ role: "menuitemcheckbox",
579
+ tabIndex: 0,
580
+ "aria-label": label,
581
+ "aria-checked": isChecked ? "true" : "false",
582
+ "data-active": isActive ? "" : null,
583
+ onPointerUp: onPress,
584
+ onPointerDown: onActive,
585
+ onKeyDown
586
+ }
587
+ );
588
+ }
589
+ DefaultMenuCheckbox.displayName = "DefaultMenuCheckbox";
590
+
591
+ function DefaultAccessibilityMenu({ slots }) {
592
+ const label = useDefaultLayoutWord("Accessibility"), { icons: Icons } = useDefaultLayoutContext();
593
+ return /* @__PURE__ */ React.createElement(Root$3, { className: "vds-accessibility-menu vds-menu" }, /* @__PURE__ */ React.createElement(DefaultMenuButton, { label, Icon: Icons.Menu.Accessibility }), /* @__PURE__ */ React.createElement(Items, { className: "vds-menu-items" }, slot(slots, "accessibilityMenuItemsStart", null), /* @__PURE__ */ React.createElement(DefaultMenuSection, null, /* @__PURE__ */ React.createElement(DefaultAnnouncementsMenuCheckbox, null), /* @__PURE__ */ React.createElement(DefaultKeyboardAnimationsMenuCheckbox, null)), /* @__PURE__ */ React.createElement(DefaultMenuSection, null, /* @__PURE__ */ React.createElement(DefaultFontMenu, null)), slot(slots, "accessibilityMenuItemsEnd", null)));
594
+ }
595
+ DefaultAccessibilityMenu.displayName = "DefaultAccessibilityMenu";
596
+ function DefaultAnnouncementsMenuCheckbox() {
597
+ const { userPrefersAnnouncements } = useDefaultLayoutContext(), label = useDefaultLayoutWord("Announcements");
598
+ function onChange(checked) {
599
+ userPrefersAnnouncements.set(checked);
600
+ }
601
+ return /* @__PURE__ */ React.createElement(DefaultMenuItem, { label }, /* @__PURE__ */ React.createElement(
602
+ DefaultMenuCheckbox,
603
+ {
604
+ label,
605
+ defaultChecked: true,
606
+ storageKey: "vds-player::announcements",
607
+ onChange
608
+ }
609
+ ));
610
+ }
611
+ DefaultAnnouncementsMenuCheckbox.displayName = "DefaultAnnouncementsMenuCheckbox";
612
+ function DefaultKeyboardAnimationsMenuCheckbox() {
613
+ const $viewType = useMediaState("viewType"), { userPrefersKeyboardAnimations, noKeyboardAnimations } = useDefaultLayoutContext(), label = useDefaultLayoutWord("Keyboard Animations");
614
+ if ($viewType !== "video" || noKeyboardAnimations) return null;
615
+ function onChange(checked) {
616
+ userPrefersKeyboardAnimations.set(checked);
617
+ }
618
+ return /* @__PURE__ */ React.createElement(DefaultMenuItem, { label }, /* @__PURE__ */ React.createElement(
619
+ DefaultMenuCheckbox,
620
+ {
621
+ label,
622
+ defaultChecked: true,
623
+ storageKey: "vds-player::keyboard-animations",
624
+ onChange
625
+ }
626
+ ));
627
+ }
628
+ DefaultKeyboardAnimationsMenuCheckbox.displayName = "DefaultKeyboardAnimationsMenuCheckbox";
629
+
630
+ function DefaultAudioMenu({ slots }) {
631
+ const label = useDefaultLayoutWord("Audio"), $canSetAudioGain = useMediaState("canSetAudioGain"), $audioTracks = useMediaState("audioTracks"), { noAudioGain, icons: Icons } = useDefaultLayoutContext(), hasGainSlider = $canSetAudioGain && !noAudioGain, $disabled = !hasGainSlider && $audioTracks.length <= 1;
632
+ if ($disabled) return null;
633
+ return /* @__PURE__ */ React.createElement(Root$3, { className: "vds-audio-menu vds-menu" }, /* @__PURE__ */ React.createElement(DefaultMenuButton, { label, Icon: Icons.Menu.Audio }), /* @__PURE__ */ React.createElement(Items, { className: "vds-menu-items" }, slot(slots, "audioMenuItemsStart", null), /* @__PURE__ */ React.createElement(DefaultAudioTracksMenu, null), hasGainSlider ? /* @__PURE__ */ React.createElement(DefaultAudioBoostMenuSection, null) : null, slot(slots, "audioMenuItemsEnd", null)));
634
+ }
635
+ DefaultAudioMenu.displayName = "DefaultAudioMenu";
636
+ function DefaultAudioBoostMenuSection() {
637
+ const $audioGain = useMediaState("audioGain"), label = useDefaultLayoutWord("Boost"), value = Math.round((($audioGain ?? 1) - 1) * 100) + "%", $canSetAudioGain = useMediaState("canSetAudioGain"), { noAudioGain, icons: Icons } = useDefaultLayoutContext(), $disabled = !$canSetAudioGain || noAudioGain, min = useGainMin(), max = useGainMax();
638
+ if ($disabled) return null;
639
+ return /* @__PURE__ */ React.createElement(DefaultMenuSection, { label, value }, /* @__PURE__ */ React.createElement(
640
+ DefaultMenuSliderItem,
641
+ {
642
+ UpIcon: Icons.Menu.AudioBoostUp,
643
+ DownIcon: Icons.Menu.AudioBoostDown,
644
+ isMin: (($audioGain ?? 1) - 1) * 100 <= min,
645
+ isMax: (($audioGain ?? 1) - 1) * 100 === max
646
+ },
647
+ /* @__PURE__ */ React.createElement(DefaultAudioGainSlider, null)
648
+ ));
649
+ }
650
+ DefaultAudioBoostMenuSection.displayName = "DefaultAudioBoostMenuSection";
651
+ function useGainMin() {
652
+ const { audioGains } = useDefaultLayoutContext(), min = isArray(audioGains) ? audioGains[0] : audioGains?.min;
653
+ return min ?? 0;
654
+ }
655
+ function useGainMax() {
656
+ const { audioGains } = useDefaultLayoutContext(), max = isArray(audioGains) ? audioGains[audioGains.length - 1] : audioGains?.max;
657
+ return max ?? 300;
658
+ }
659
+ function useGainStep() {
660
+ const { audioGains } = useDefaultLayoutContext(), step = isArray(audioGains) ? audioGains[1] - audioGains[0] : audioGains?.step;
661
+ return step || 25;
662
+ }
663
+ function DefaultAudioGainSlider() {
664
+ const label = useDefaultLayoutWord("Audio Boost"), min = useGainMin(), max = useGainMax(), step = useGainStep();
665
+ return /* @__PURE__ */ React.createElement(
666
+ Root$5,
667
+ {
668
+ className: "vds-audio-gain-slider vds-slider",
669
+ "aria-label": label,
670
+ min,
671
+ max,
672
+ step,
673
+ keyStep: step
674
+ },
675
+ /* @__PURE__ */ React.createElement(DefaultSliderParts, null),
676
+ /* @__PURE__ */ React.createElement(DefaultSliderSteps, null)
677
+ );
678
+ }
679
+ DefaultAudioGainSlider.displayName = "DefaultAudioGainSlider";
680
+ function DefaultAudioTracksMenu() {
681
+ const { icons: Icons } = useDefaultLayoutContext(), label = useDefaultLayoutWord("Track"), defaultText = useDefaultLayoutWord("Default"), $track = useMediaState("audioTrack"), options = useAudioOptions();
682
+ if (options.disabled) return null;
683
+ return /* @__PURE__ */ React.createElement(Root$3, { className: "vds-audio-track-menu vds-menu" }, /* @__PURE__ */ React.createElement(
684
+ DefaultMenuButton,
685
+ {
686
+ label,
687
+ hint: $track?.label ?? defaultText,
688
+ disabled: options.disabled,
689
+ Icon: Icons.Menu.Audio
690
+ }
691
+ ), /* @__PURE__ */ React.createElement(Items, { className: "vds-menu-items" }, /* @__PURE__ */ React.createElement(
692
+ Root$1,
693
+ {
694
+ className: "vds-audio-radio-group vds-radio-group",
695
+ value: options.selectedValue
696
+ },
697
+ options.map(({ label: label2, value, select }) => /* @__PURE__ */ React.createElement(
698
+ Item,
699
+ {
700
+ className: "vds-audio-radio vds-radio",
701
+ value,
702
+ onSelect: select,
703
+ key: value
704
+ },
705
+ /* @__PURE__ */ React.createElement(Icons.Menu.RadioCheck, { className: "vds-icon" }),
706
+ /* @__PURE__ */ React.createElement("span", { className: "vds-radio-label" }, label2)
707
+ ))
708
+ )));
709
+ }
710
+ DefaultAudioTracksMenu.displayName = "DefaultAudioTracksMenu";
711
+
712
+ function DefaultCaptionMenu({ slots }) {
713
+ const { icons: Icons } = useDefaultLayoutContext(), label = useDefaultLayoutWord("Captions"), offText = useDefaultLayoutWord("Off"), options = useCaptionOptions({ off: offText }), hint = options.selectedTrack?.label ?? offText;
714
+ if (options.disabled) return null;
715
+ return /* @__PURE__ */ React.createElement(Root$3, { className: "vds-captions-menu vds-menu" }, /* @__PURE__ */ React.createElement(
716
+ DefaultMenuButton,
717
+ {
718
+ label,
719
+ hint,
720
+ disabled: options.disabled,
721
+ Icon: Icons.Menu.Captions
722
+ }
723
+ ), /* @__PURE__ */ React.createElement(Items, { className: "vds-menu-items" }, slot(slots, "captionsMenuItemsStart", null), /* @__PURE__ */ React.createElement(
724
+ Root$1,
725
+ {
726
+ className: "vds-captions-radio-group vds-radio-group",
727
+ value: options.selectedValue
728
+ },
729
+ options.map(({ label: label2, value, select }) => /* @__PURE__ */ React.createElement(
730
+ Item,
731
+ {
732
+ className: "vds-caption-radio vds-radio",
733
+ value,
734
+ onSelect: select,
735
+ key: value
736
+ },
737
+ /* @__PURE__ */ React.createElement(Icons.Menu.RadioCheck, { className: "vds-icon" }),
738
+ /* @__PURE__ */ React.createElement("span", { className: "vds-radio-label" }, label2)
739
+ ))
740
+ ), slot(slots, "captionsMenuItemsEnd", null)));
741
+ }
742
+ DefaultCaptionMenu.displayName = "DefaultCaptionMenu";
743
+
744
+ function DefaultPlaybackMenu({ slots }) {
745
+ const label = useDefaultLayoutWord("Playback"), { icons: Icons } = useDefaultLayoutContext();
746
+ return /* @__PURE__ */ React.createElement(Root$3, { className: "vds-playback-menu vds-menu" }, /* @__PURE__ */ React.createElement(DefaultMenuButton, { label, Icon: Icons.Menu.Playback }), /* @__PURE__ */ React.createElement(Items, { className: "vds-menu-items" }, slot(slots, "playbackMenuItemsStart", null), /* @__PURE__ */ React.createElement(DefaultMenuSection, null, slot(slots, "playbackMenuLoop", /* @__PURE__ */ React.createElement(DefaultLoopMenuCheckbox, null))), /* @__PURE__ */ React.createElement(DefaultSpeedMenuSection, null), /* @__PURE__ */ React.createElement(DefaultQualityMenuSection, null), slot(slots, "playbackMenuItemsEnd", null)));
747
+ }
748
+ DefaultPlaybackMenu.displayName = "DefaultPlaybackMenu";
749
+ function DefaultLoopMenuCheckbox() {
750
+ const { remote } = useMediaContext(), label = useDefaultLayoutWord("Loop");
751
+ function onChange(checked, trigger) {
752
+ remote.userPrefersLoopChange(checked, trigger);
753
+ }
754
+ return /* @__PURE__ */ React.createElement(DefaultMenuItem, { label }, /* @__PURE__ */ React.createElement(DefaultMenuCheckbox, { label, storageKey: "vds-player::user-loop", onChange }));
755
+ }
756
+ DefaultLoopMenuCheckbox.displayName = "DefaultLoopMenuCheckbox";
757
+ function DefaultAutoQualityMenuCheckbox() {
758
+ const { remote, qualities } = useMediaContext(), $autoQuality = useMediaState("autoQuality"), label = useDefaultLayoutWord("Auto");
759
+ function onChange(checked, trigger) {
760
+ if (checked) {
761
+ remote.requestAutoQuality(trigger);
762
+ } else {
763
+ remote.changeQuality(qualities.selectedIndex, trigger);
764
+ }
765
+ }
766
+ return /* @__PURE__ */ React.createElement(DefaultMenuItem, { label }, /* @__PURE__ */ React.createElement(
767
+ DefaultMenuCheckbox,
768
+ {
769
+ label,
770
+ checked: $autoQuality,
771
+ onChange,
772
+ defaultChecked: $autoQuality
773
+ }
774
+ ));
775
+ }
776
+ DefaultAutoQualityMenuCheckbox.displayName = "DefaultAutoQualityMenuCheckbox";
777
+ function DefaultQualityMenuSection() {
778
+ const { hideQualityBitrate, icons: Icons } = useDefaultLayoutContext(), $canSetQuality = useMediaState("canSetQuality"), $qualities = useMediaState("qualities"), $quality = useMediaState("quality"), label = useDefaultLayoutWord("Quality"), autoText = useDefaultLayoutWord("Auto"), sortedQualities = React.useMemo(() => sortVideoQualities($qualities), [$qualities]);
779
+ if (!$canSetQuality || $qualities.length <= 1) return null;
780
+ const height = $quality?.height, bitrate = !hideQualityBitrate ? $quality?.bitrate : null, bitrateText = bitrate && bitrate > 0 ? `${(bitrate / 1e6).toFixed(2)} Mbps` : null, value = height ? `${height}p${bitrateText ? ` (${bitrateText})` : ""}` : autoText, isMin = sortedQualities[0] === $quality, isMax = sortedQualities.at(-1) === $quality;
781
+ return /* @__PURE__ */ React.createElement(DefaultMenuSection, { label, value }, /* @__PURE__ */ React.createElement(
782
+ DefaultMenuSliderItem,
783
+ {
784
+ UpIcon: Icons.Menu.QualityUp,
785
+ DownIcon: Icons.Menu.QualityDown,
786
+ isMin,
787
+ isMax
788
+ },
789
+ /* @__PURE__ */ React.createElement(DefaultQualitySlider, null)
790
+ ), /* @__PURE__ */ React.createElement(DefaultAutoQualityMenuCheckbox, null));
791
+ }
792
+ DefaultQualityMenuSection.displayName = "DefaultQualityMenuSection";
793
+ function DefaultQualitySlider() {
794
+ const label = useDefaultLayoutWord("Quality");
795
+ return /* @__PURE__ */ React.createElement(Root$7, { className: "vds-quality-slider vds-slider", "aria-label": label }, /* @__PURE__ */ React.createElement(DefaultSliderParts, null), /* @__PURE__ */ React.createElement(DefaultSliderSteps, null));
796
+ }
797
+ DefaultQualitySlider.displayName = "DefaultQualitySlider";
798
+ function DefaultSpeedMenuSection() {
799
+ const { icons: Icons } = useDefaultLayoutContext(), $playbackRate = useMediaState("playbackRate"), $canSetPlaybackRate = useMediaState("canSetPlaybackRate"), label = useDefaultLayoutWord("Speed"), normalText = useDefaultLayoutWord("Normal"), min = useSpeedMin(), max = useSpeedMax(), value = $playbackRate === 1 ? normalText : $playbackRate + "x";
800
+ if (!$canSetPlaybackRate) return null;
801
+ return /* @__PURE__ */ React.createElement(DefaultMenuSection, { label, value }, /* @__PURE__ */ React.createElement(
802
+ DefaultMenuSliderItem,
803
+ {
804
+ UpIcon: Icons.Menu.SpeedUp,
805
+ DownIcon: Icons.Menu.SpeedDown,
806
+ isMin: $playbackRate === min,
807
+ isMax: $playbackRate === max
808
+ },
809
+ /* @__PURE__ */ React.createElement(DefaultSpeedSlider, null)
810
+ ));
811
+ }
812
+ function useSpeedMin() {
813
+ const { playbackRates } = useDefaultLayoutContext(), rates = playbackRates;
814
+ return (isArray(rates) ? rates[0] : rates?.min) ?? 0;
815
+ }
816
+ function useSpeedMax() {
817
+ const { playbackRates } = useDefaultLayoutContext(), rates = playbackRates;
818
+ return (isArray(rates) ? rates[rates.length - 1] : rates?.max) ?? 2;
819
+ }
820
+ function useSpeedStep() {
821
+ const { playbackRates } = useDefaultLayoutContext(), rates = playbackRates;
822
+ return (isArray(rates) ? rates[1] - rates[0] : rates?.step) || 0.25;
823
+ }
824
+ function DefaultSpeedSlider() {
825
+ const label = useDefaultLayoutWord("Speed"), min = useSpeedMin(), max = useSpeedMax(), step = useSpeedStep();
826
+ return /* @__PURE__ */ React.createElement(
827
+ Root$6,
828
+ {
829
+ className: "vds-speed-slider vds-slider",
830
+ "aria-label": label,
831
+ min,
832
+ max,
833
+ step,
834
+ keyStep: step
835
+ },
836
+ /* @__PURE__ */ React.createElement(DefaultSliderParts, null),
837
+ /* @__PURE__ */ React.createElement(DefaultSliderSteps, null)
838
+ );
839
+ }
840
+ DefaultSpeedSlider.displayName = "DefaultSpeedSlider";
841
+
842
+ function DefaultSettingsMenu({
843
+ tooltip,
844
+ placement,
845
+ portalClass = "",
846
+ slots
847
+ }) {
848
+ const {
849
+ showMenuDelay,
850
+ icons: Icons,
851
+ isSmallLayout,
852
+ menuContainer,
853
+ menuGroup,
854
+ noModal,
855
+ colorScheme
856
+ } = useDefaultLayoutContext(), settingsText = useDefaultLayoutWord("Settings"), $viewType = useMediaState("viewType"), $offset = !isSmallLayout && menuGroup === "bottom" && $viewType === "video" ? 26 : 0, colorSchemeClass = useColorSchemeClass(colorScheme), [isOpen, setIsOpen] = React.useState(false), dialogEl = useParentDialogEl();
857
+ useScoped(updateFontCssVars);
858
+ function onOpen() {
859
+ flushSync(() => {
860
+ setIsOpen(true);
861
+ });
862
+ }
863
+ function onClose() {
864
+ setIsOpen(false);
865
+ }
866
+ const Content = /* @__PURE__ */ React.createElement(
867
+ Items,
868
+ {
869
+ className: "vds-settings-menu-items vds-menu-items",
870
+ placement,
871
+ offset: $offset
872
+ },
873
+ isOpen ? /* @__PURE__ */ React.createElement(React.Fragment, null, slot(slots, "settingsMenuItemsStart", null), slot(slots, "settingsMenuStartItems", null), /* @__PURE__ */ React.createElement(DefaultPlaybackMenu, { slots }), /* @__PURE__ */ React.createElement(DefaultAccessibilityMenu, { slots }), /* @__PURE__ */ React.createElement(DefaultAudioMenu, { slots }), /* @__PURE__ */ React.createElement(DefaultCaptionMenu, { slots }), slot(slots, "settingsMenuEndItems", null), slot(slots, "settingsMenuItemsEnd", null)) : null
874
+ );
875
+ return /* @__PURE__ */ React.createElement(
876
+ Root$3,
877
+ {
878
+ className: "vds-settings-menu vds-menu",
879
+ showDelay: showMenuDelay,
880
+ onOpen,
881
+ onClose
882
+ },
883
+ /* @__PURE__ */ React.createElement(DefaultTooltip, { content: settingsText, placement: tooltip }, /* @__PURE__ */ React.createElement(Button, { className: "vds-menu-button vds-button", "aria-label": settingsText }, /* @__PURE__ */ React.createElement(Icons.Menu.Settings, { className: "vds-icon vds-rotate-icon" }))),
884
+ noModal || !isSmallLayout ? Content : /* @__PURE__ */ React.createElement(
885
+ Portal,
886
+ {
887
+ className: portalClass + (colorSchemeClass ? ` ${colorSchemeClass}` : ""),
888
+ container: menuContainer ?? dialogEl,
889
+ disabled: "fullscreen",
890
+ "data-sm": isSmallLayout ? "" : null,
891
+ "data-lg": !isSmallLayout ? "" : null,
892
+ "data-size": isSmallLayout ? "sm" : "lg",
893
+ "data-view-type": $viewType
894
+ },
895
+ Content
896
+ )
897
+ );
898
+ }
899
+ DefaultSettingsMenu.displayName = "DefaultSettingsMenu";
900
+
901
+ function DefaultVolumePopup({ tooltip, orientation, slots }) {
902
+ const $pointer = useMediaState("pointer"), $muted = useMediaState("muted"), $canSetVolume = useMediaState("canSetVolume"), [rootEl, setRootEl] = React.useState(null), isRootActive = useActive(rootEl), muteButton = slot(slots, "muteButton", /* @__PURE__ */ React.createElement(DefaultMuteButton, { tooltip }));
903
+ if (!$canSetVolume) {
904
+ return muteButton;
905
+ }
906
+ return $pointer === "coarse" && !$muted ? null : /* @__PURE__ */ React.createElement("div", { className: "vds-volume", "data-active": isRootActive ? "" : null, ref: setRootEl }, muteButton, /* @__PURE__ */ React.createElement("div", { className: "vds-volume-popup" }, slot(slots, "volumeSlider", /* @__PURE__ */ React.createElement(DefaultVolumeSlider, { orientation }))));
907
+ }
908
+ DefaultVolumePopup.displayName = "DefaultVolumePopup";
909
+ function DefaultVolumeSlider(props) {
910
+ const label = useDefaultLayoutWord("Volume");
911
+ return /* @__PURE__ */ React.createElement(Root$8, { className: "vds-volume-slider vds-slider", "aria-label": label, ...props }, /* @__PURE__ */ React.createElement(Track, { className: "vds-slider-track" }), /* @__PURE__ */ React.createElement(TrackFill, { className: "vds-slider-track-fill vds-slider-track" }), /* @__PURE__ */ React.createElement(Thumb, { className: "vds-slider-thumb" }), /* @__PURE__ */ React.createElement(Preview, { className: "vds-slider-preview", noClamp: true }, /* @__PURE__ */ React.createElement(Value, { className: "vds-slider-value" })));
912
+ }
913
+ DefaultVolumeSlider.displayName = "DefaultVolumeSlider";
914
+ function DefaultTimeSlider() {
915
+ const [instance, setInstance] = React.useState(null), [width, setWidth] = React.useState(0), $src = useMediaState("currentSrc"), { thumbnails, sliderChaptersMinWidth, disableTimeSlider, seekStep, noScrubGesture } = useDefaultLayoutContext(), label = useDefaultLayoutWord("Seek"), $RemotionSliderThumbnail = useSignal(RemotionSliderThumbnail);
916
+ const onResize = React.useCallback(() => {
917
+ const el = instance?.el;
918
+ el && setWidth(el.clientWidth);
919
+ }, [instance]);
920
+ useResizeObserver(instance?.el, onResize);
921
+ return /* @__PURE__ */ React.createElement(
922
+ Root$9,
923
+ {
924
+ className: "vds-time-slider vds-slider",
925
+ "aria-label": label,
926
+ disabled: disableTimeSlider,
927
+ noSwipeGesture: noScrubGesture,
928
+ keyStep: seekStep,
929
+ ref: setInstance
930
+ },
931
+ /* @__PURE__ */ React.createElement(
932
+ Chapters,
933
+ {
934
+ className: "vds-slider-chapters",
935
+ disabled: width < sliderChaptersMinWidth
936
+ },
937
+ (cues, forwardRef) => cues.map((cue) => /* @__PURE__ */ React.createElement("div", { className: "vds-slider-chapter", key: cue.startTime, ref: forwardRef }, /* @__PURE__ */ React.createElement(Track, { className: "vds-slider-track" }), /* @__PURE__ */ React.createElement(TrackFill, { className: "vds-slider-track-fill vds-slider-track" }), /* @__PURE__ */ React.createElement(Progress, { className: "vds-slider-progress vds-slider-track" })))
938
+ ),
939
+ /* @__PURE__ */ React.createElement(Thumb, { className: "vds-slider-thumb" }),
940
+ /* @__PURE__ */ React.createElement(Preview, { className: "vds-slider-preview" }, thumbnails ? /* @__PURE__ */ React.createElement(
941
+ Thumbnail.Root,
942
+ {
943
+ src: thumbnails,
944
+ className: "vds-slider-thumbnail vds-thumbnail"
945
+ },
946
+ /* @__PURE__ */ React.createElement(Thumbnail.Img, null)
947
+ ) : $RemotionSliderThumbnail && isRemotionSrc($src) ? /* @__PURE__ */ React.createElement($RemotionSliderThumbnail, { className: "vds-slider-thumbnail vds-thumbnail" }) : null, /* @__PURE__ */ React.createElement(ChapterTitle, { className: "vds-slider-chapter-title" }), /* @__PURE__ */ React.createElement(Value, { className: "vds-slider-value" }))
948
+ );
949
+ }
950
+ DefaultTimeSlider.displayName = "DefaultTimeSlider";
951
+
952
+ function DefaultTimeGroup({ slots }) {
953
+ const $duration = useMediaState("duration");
954
+ if (!$duration) return null;
955
+ return /* @__PURE__ */ React.createElement("div", { className: "vds-time-group" }, slot(slots, "currentTime", /* @__PURE__ */ React.createElement(Time, { className: "vds-time", type: "current" })), slot(slots, "timeDivider", /* @__PURE__ */ React.createElement("div", { className: "vds-time-divider" }, "/")), slot(slots, "endTime", /* @__PURE__ */ React.createElement(Time, { className: "vds-time", type: "duration" })));
956
+ }
957
+ DefaultTimeGroup.displayName = "DefaultTimeGroup";
958
+ function DefaultTimeInfo({ slots }) {
959
+ const $live = useMediaState("live");
960
+ return $live ? slot(slots, "liveButton", /* @__PURE__ */ React.createElement(DefaultLiveButton, null)) : /* @__PURE__ */ React.createElement(DefaultTimeGroup, { slots });
961
+ }
962
+ DefaultTimeInfo.displayName = "DefaultTimeInfo";
963
+ function DefaultTimeInvert({ slots }) {
964
+ const $live = useMediaState("live"), $duration = useMediaState("duration");
965
+ return $live ? slot(slots, "liveButton", /* @__PURE__ */ React.createElement(DefaultLiveButton, null)) : slot(
966
+ slots,
967
+ "endTime",
968
+ $duration ? /* @__PURE__ */ React.createElement(Time, { className: "vds-time", type: "current", toggle: true, remainder: true }) : null
969
+ );
970
+ }
971
+ DefaultTimeInvert.displayName = "DefaultTimeInvert";
972
+
973
+ const MediaLayout$1 = createDefaultMediaLayout({
974
+ type: "audio",
975
+ smLayoutWhen({ width }) {
976
+ return width < 576;
977
+ },
978
+ renderLayout: () => /* @__PURE__ */ React.createElement(AudioLayout, null)
979
+ });
980
+ function DefaultAudioLayout(props) {
981
+ const [scrubbing, setScrubbing] = React.useState(false), $pointer = useMediaState("pointer");
982
+ const onStartScrubbing = React.useCallback((event) => {
983
+ const { target } = event, hasTimeSlider = !!(target instanceof HTMLElement && target.closest(".vds-time-slider"));
984
+ if (!hasTimeSlider) return;
985
+ event.nativeEvent.stopImmediatePropagation();
986
+ setScrubbing(true);
987
+ }, []);
988
+ const onStopScrubbing = React.useCallback(() => {
989
+ setScrubbing(false);
990
+ }, []);
991
+ React.useEffect(() => {
992
+ if (scrubbing) return listenEvent(window, "pointerdown", onStopScrubbing);
993
+ }, [scrubbing, onStopScrubbing]);
994
+ return /* @__PURE__ */ React.createElement(
995
+ MediaLayout$1,
996
+ {
997
+ ...props,
998
+ "data-scrubbing": scrubbing ? "" : null,
999
+ onPointerDown: scrubbing ? (e) => e.stopPropagation() : void 0,
1000
+ onPointerDownCapture: $pointer === "coarse" && !scrubbing ? onStartScrubbing : void 0
1001
+ }
1002
+ );
1003
+ }
1004
+ DefaultAudioLayout.displayName = "DefaultAudioLayout";
1005
+ function AudioLayout() {
1006
+ const slots = useDefaultAudioLayoutSlots();
1007
+ useLayoutName("audio");
1008
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(DefaultAnnouncer, null), /* @__PURE__ */ React.createElement(DefaultCaptions, null), /* @__PURE__ */ React.createElement(Root$a, { className: "vds-controls" }, /* @__PURE__ */ React.createElement(Group, { className: "vds-controls-group" }, slot(slots, "seekBackwardButton", /* @__PURE__ */ React.createElement(DefaultSeekButton, { backward: true, tooltip: "top start" })), slot(slots, "playButton", /* @__PURE__ */ React.createElement(DefaultPlayButton, { tooltip: "top center" })), slot(slots, "seekForwardButton", /* @__PURE__ */ React.createElement(DefaultSeekButton, { tooltip: "top center" })), /* @__PURE__ */ React.createElement(DefaultAudioTitle, null), slot(slots, "timeSlider", /* @__PURE__ */ React.createElement(DefaultTimeSlider, null)), /* @__PURE__ */ React.createElement(DefaultTimeInvert, { slots }), /* @__PURE__ */ React.createElement(DefaultVolumePopup, { orientation: "vertical", tooltip: "top", slots }), slot(slots, "captionButton", /* @__PURE__ */ React.createElement(DefaultCaptionButton, { tooltip: "top center" })), slot(slots, "downloadButton", /* @__PURE__ */ React.createElement(DefaultDownloadButton, null)), /* @__PURE__ */ React.createElement(DefaultAudioMenus, { slots }))));
1009
+ }
1010
+ AudioLayout.displayName = "AudioLayout";
1011
+ function DefaultAudioMenus({ slots }) {
1012
+ const { isSmallLayout, noModal } = useDefaultLayoutContext(), placement = noModal ? "top end" : !isSmallLayout ? "top end" : null;
1013
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, slot(
1014
+ slots,
1015
+ "chaptersMenu",
1016
+ /* @__PURE__ */ React.createElement(DefaultChaptersMenu, { tooltip: "top", placement, portalClass: "vds-audio-layout" })
1017
+ ), slot(
1018
+ slots,
1019
+ "settingsMenu",
1020
+ /* @__PURE__ */ React.createElement(
1021
+ DefaultSettingsMenu,
1022
+ {
1023
+ tooltip: "top end",
1024
+ placement,
1025
+ portalClass: "vds-audio-layout",
1026
+ slots
1027
+ }
1028
+ )
1029
+ ));
1030
+ }
1031
+ DefaultAudioMenus.displayName = "DefaultAudioMenus";
1032
+ function DefaultAudioTitle() {
1033
+ const [rootEl, setRootEl] = React.useState(null), media = useMediaContext(), { translations } = useDefaultLayoutContext(), [isTextOverflowing, setIsTextOverflowing] = React.useState(false);
1034
+ const isContinued = createComputed(() => {
1035
+ const { started, currentTime } = media.$state;
1036
+ return started() || currentTime() > 0;
1037
+ });
1038
+ const $title = useSignal(
1039
+ createComputed(() => {
1040
+ const { title, ended } = media.$state;
1041
+ if (!title()) return "";
1042
+ const word = ended() ? "Replay" : isContinued() ? "Continue" : "Play";
1043
+ return `${i18n(translations, word)}: ${title()}`;
1044
+ })
1045
+ );
1046
+ const chapterTitle = useChapterTitle(), $isContinued = useSignal(isContinued), $chapterTitle = $isContinued ? chapterTitle : "", isTransitionActive = useTransitionActive(rootEl);
1047
+ React.useEffect(() => {
1048
+ if (isTransitionActive && document.activeElement === document.body) {
1049
+ media.player.el?.focus({ preventScroll: true });
1050
+ }
1051
+ }, []);
1052
+ const onResize = React.useCallback(() => {
1053
+ const el = rootEl, isOverflowing = !!el && !isTransitionActive && el.clientWidth < el.children[0].clientWidth;
1054
+ if (el) toggleClass(el, "vds-marquee", isOverflowing);
1055
+ setIsTextOverflowing(isOverflowing);
1056
+ }, [rootEl, isTransitionActive]);
1057
+ useResizeObserver(rootEl, onResize);
1058
+ return $title ? /* @__PURE__ */ React.createElement("span", { className: "vds-title", title: $title, ref: setRootEl }, /* @__PURE__ */ React.createElement(AudioTitle, { title: $title, chapterTitle: $chapterTitle }), isTextOverflowing && !isTransitionActive ? /* @__PURE__ */ React.createElement(AudioTitle, { title: $title, chapterTitle: $chapterTitle }) : null) : /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null);
1059
+ }
1060
+ DefaultAudioTitle.displayName = "DefaultAudioTitle";
1061
+ function AudioTitle({ title, chapterTitle }) {
1062
+ const slots = useDefaultAudioLayoutSlots();
1063
+ return /* @__PURE__ */ React.createElement("span", { className: "vds-title-text" }, slot(slots, "title", title), slot(slots, "chapterTitle", /* @__PURE__ */ React.createElement("span", { className: "vds-chapter-title" }, chapterTitle)));
1064
+ }
1065
+ AudioTitle.displayName = "AudioTitle";
1066
+
1067
+ const DefaultKeyboardDisplay = React.forwardRef(
1068
+ ({ icons: Icons, ...props }, forwardRef) => {
1069
+ const [visible, setVisible] = React.useState(false), [Icon, setIcon] = React.useState(null), [count, setCount] = React.useState(0), $lastKeyboardAction = useMediaState("lastKeyboardAction");
1070
+ React.useEffect(() => {
1071
+ setCount((n) => n + 1);
1072
+ }, [$lastKeyboardAction]);
1073
+ const actionDataAttr = React.useMemo(() => {
1074
+ const action = $lastKeyboardAction?.action;
1075
+ return action && visible ? camelToKebabCase(action) : null;
1076
+ }, [visible, $lastKeyboardAction]);
1077
+ const className = React.useMemo(
1078
+ () => `vds-kb-action${!visible ? " hidden" : ""}${props.className ? ` ${props.className}` : ""}`,
1079
+ [visible]
1080
+ );
1081
+ const $$text = createComputed(getText), $text = useSignal($$text);
1082
+ createEffect(() => {
1083
+ const Icon2 = getIcon(Icons);
1084
+ setIcon(() => Icon2);
1085
+ }, [Icons]);
1086
+ React.useEffect(() => {
1087
+ setVisible(!!$lastKeyboardAction);
1088
+ const id = setTimeout(() => setVisible(false), 500);
1089
+ return () => {
1090
+ setVisible(false);
1091
+ window.clearTimeout(id);
1092
+ };
1093
+ }, [$lastKeyboardAction]);
1094
+ return Icon ? /* @__PURE__ */ React.createElement(
1095
+ Primitive.div,
1096
+ {
1097
+ ...props,
1098
+ className,
1099
+ "data-action": actionDataAttr,
1100
+ ref: forwardRef
1101
+ },
1102
+ /* @__PURE__ */ React.createElement("div", { className: "vds-kb-text-wrapper" }, /* @__PURE__ */ React.createElement("div", { className: "vds-kb-text" }, $text)),
1103
+ /* @__PURE__ */ React.createElement("div", { className: "vds-kb-bezel", key: count }, /* @__PURE__ */ React.createElement("div", { className: "vds-kb-icon" }, /* @__PURE__ */ React.createElement(Icon, null)))
1104
+ ) : null;
1105
+ }
1106
+ );
1107
+ DefaultKeyboardDisplay.displayName = "DefaultKeyboardDisplay";
1108
+ function getText() {
1109
+ const { $state } = useContext(mediaContext), action = $state.lastKeyboardAction()?.action, audioGain = $state.audioGain() ?? 1;
1110
+ switch (action) {
1111
+ case "toggleMuted":
1112
+ return $state.muted() ? "0%" : getVolumeText($state.volume(), audioGain);
1113
+ case "volumeUp":
1114
+ case "volumeDown":
1115
+ return getVolumeText($state.volume(), audioGain);
1116
+ default:
1117
+ return "";
1118
+ }
1119
+ }
1120
+ function getVolumeText(volume, gain) {
1121
+ return `${Math.round(volume * gain * 100)}%`;
1122
+ }
1123
+ function getIcon(Icons) {
1124
+ const { $state } = useContext(mediaContext), action = $state.lastKeyboardAction()?.action;
1125
+ switch (action) {
1126
+ case "togglePaused":
1127
+ return !$state.paused() ? Icons.Play : Icons.Pause;
1128
+ case "toggleMuted":
1129
+ return $state.muted() || $state.volume() === 0 ? Icons.Mute : $state.volume() >= 0.5 ? Icons.VolumeUp : Icons.VolumeDown;
1130
+ case "toggleFullscreen":
1131
+ return $state.fullscreen() ? Icons.EnterFullscreen : Icons.ExitFullscreen;
1132
+ case "togglePictureInPicture":
1133
+ return $state.pictureInPicture() ? Icons.EnterPiP : Icons.ExitPiP;
1134
+ case "toggleCaptions":
1135
+ return $state.hasCaptions() ? $state.textTrack() ? Icons.CaptionsOn : Icons.CaptionsOff : null;
1136
+ case "volumeUp":
1137
+ return Icons.VolumeUp;
1138
+ case "volumeDown":
1139
+ return Icons.VolumeDown;
1140
+ case "seekForward":
1141
+ return Icons.SeekForward;
1142
+ case "seekBackward":
1143
+ return Icons.SeekBackward;
1144
+ default:
1145
+ return null;
1146
+ }
1147
+ }
1148
+
1149
+ function DefaultTitle() {
1150
+ const $started = useMediaState("started"), $title = useMediaState("title"), $hasChapters = useActiveTextTrack("chapters");
1151
+ return $hasChapters && ($started || !$title) ? /* @__PURE__ */ React.createElement(ChapterTitle$1, { className: "vds-chapter-title" }) : /* @__PURE__ */ React.createElement(Title, { className: "vds-chapter-title" });
1152
+ }
1153
+ DefaultTitle.displayName = "DefaultTitle";
1154
+
1155
+ const MediaLayout = createDefaultMediaLayout({
1156
+ type: "video",
1157
+ smLayoutWhen({ width, height }) {
1158
+ return width < 576 || height < 380;
1159
+ },
1160
+ renderLayout(props) {
1161
+ return /* @__PURE__ */ React.createElement(VideoLayout, { ...props });
1162
+ }
1163
+ });
1164
+ function DefaultVideoLayout(props) {
1165
+ return /* @__PURE__ */ React.createElement(MediaLayout, { ...props });
1166
+ }
1167
+ DefaultVideoLayout.displayName = "DefaultVideoLayout";
1168
+ function VideoLayout({ streamType, isLoadLayout, isSmallLayout }) {
1169
+ useLayoutName("video");
1170
+ return isLoadLayout ? /* @__PURE__ */ React.createElement(DefaultVideoLoadLayout, null) : streamType === "unknown" ? /* @__PURE__ */ React.createElement(DefaultBufferingIndicator, null) : isSmallLayout ? /* @__PURE__ */ React.createElement(DefaultVideoSmallLayout, null) : /* @__PURE__ */ React.createElement(DefaultVideoLargeLayout, null);
1171
+ }
1172
+ VideoLayout.displayName = "VideoLayout";
1173
+ function DefaultVideoLargeLayout() {
1174
+ const { menuGroup, episodes, episodesTitle, isSmallLayout } = useDefaultLayoutContext(), baseSlots = useDefaultVideoLayoutSlots(), slots = { ...baseSlots, ...baseSlots?.largeLayout }, $fullscreen = useMediaState("fullscreen"), [episodesOpen, setEpisodesOpen] = React.useState(false), list = episodes ?? [];
1175
+ React.useEffect(() => {
1176
+ if (!$fullscreen) setEpisodesOpen(false);
1177
+ }, [$fullscreen]);
1178
+ const canOpenEpisodes = $fullscreen && list.length > 0;
1179
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(DefaultAnnouncer, null), /* @__PURE__ */ React.createElement(DefaultVideoGestures, null), /* @__PURE__ */ React.createElement(DefaultVideoKeyboardDisplay, null), slot(slots, "bufferingIndicator", /* @__PURE__ */ React.createElement(DefaultBufferingIndicator, null)), slot(slots, "captions", /* @__PURE__ */ React.createElement(DefaultCaptions, null)), /* @__PURE__ */ React.createElement(Root$a, { className: "vds-controls" }, /* @__PURE__ */ React.createElement(Group, { className: "vds-controls-group" }, slot(slots, "topControlsGroupStart", null), /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null), slot(slots, "topControlsGroupCenter", null), /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null), slot(slots, "topControlsGroupEnd", null), menuGroup === "top" && /* @__PURE__ */ React.createElement(DefaultVideoMenus, { slots })), /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null), /* @__PURE__ */ React.createElement(Group, { className: "vds-controls-group" }, slot(slots, "centerControlsGroupStart", null), /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null), slot(slots, "centerControlsGroupCenter", null), /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null), slot(slots, "centerControlsGroupEnd", null)), /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null), /* @__PURE__ */ React.createElement(Group, { className: "vds-controls-group" }, slot(slots, "timeSlider", /* @__PURE__ */ React.createElement(DefaultTimeSlider, null))), /* @__PURE__ */ React.createElement(Group, { className: "vds-controls-group" }, slot(slots, "playButton", /* @__PURE__ */ React.createElement(DefaultPlayButton, { tooltip: "top start" })), /* @__PURE__ */ React.createElement(DefaultSeekButton, { backward: true, tooltip: "top" }), /* @__PURE__ */ React.createElement(DefaultSeekButton, { tooltip: "top" }), /* @__PURE__ */ React.createElement(DefaultVolumePopup, { orientation: "horizontal", tooltip: "top", slots }), /* @__PURE__ */ React.createElement(DefaultTimeInfo, { slots }), slot(slots, "chapterTitle", /* @__PURE__ */ React.createElement(DefaultTitle, null)), canOpenEpisodes ? /* @__PURE__ */ React.createElement(DefaultEpisodeButton, { tooltip: "top", onPress: () => setEpisodesOpen((open) => !open) }) : null, slot(slots, "captionButton", /* @__PURE__ */ React.createElement(DefaultCaptionButton, { tooltip: "top" })), menuGroup === "bottom" && /* @__PURE__ */ React.createElement(DefaultVideoMenus, { slots }), slot(slots, "airPlayButton", /* @__PURE__ */ React.createElement(DefaultAirPlayButton, { tooltip: "top" })), slot(slots, "googleCastButton", /* @__PURE__ */ React.createElement(DefaultGoogleCastButton, { tooltip: "top" })), slot(slots, "downloadButton", /* @__PURE__ */ React.createElement(DefaultDownloadButton, null)), slot(slots, "pipButton", /* @__PURE__ */ React.createElement(DefaultPIPButton, { tooltip: "top" })), slot(slots, "fullscreenButton", /* @__PURE__ */ React.createElement(DefaultFullscreenButton, { tooltip: "top end" })))), /* @__PURE__ */ React.createElement(
1180
+ DefaultEpisodesSidebar,
1181
+ {
1182
+ open: episodesOpen,
1183
+ onClose: () => setEpisodesOpen(false),
1184
+ episodes: list,
1185
+ episodesTitle: episodesTitle ?? "Episodes"
1186
+ }
1187
+ ));
1188
+ }
1189
+ DefaultVideoLargeLayout.displayName = "DefaultVideoLargeLayout";
1190
+ function DefaultVideoSmallLayout() {
1191
+ const { episodes, episodesTitle, isSmallLayout } = useDefaultLayoutContext(), baseSlots = useDefaultVideoLayoutSlots(), slots = { ...baseSlots, ...baseSlots?.smallLayout }, $fullscreen = useMediaState("fullscreen"), [episodesOpen, setEpisodesOpen] = React.useState(false), list = episodes ?? [];
1192
+ React.useEffect(() => {
1193
+ if (!$fullscreen) setEpisodesOpen(false);
1194
+ }, [$fullscreen]);
1195
+ const canOpenEpisodes = $fullscreen && list.length > 0;
1196
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(DefaultAnnouncer, null), /* @__PURE__ */ React.createElement(DefaultVideoGestures, null), /* @__PURE__ */ React.createElement(DefaultVideoKeyboardDisplay, null), slot(slots, "bufferingIndicator", /* @__PURE__ */ React.createElement(DefaultBufferingIndicator, null)), slot(slots, "captions", /* @__PURE__ */ React.createElement(DefaultCaptions, null)), /* @__PURE__ */ React.createElement(Root$a, { className: "vds-controls" }, /* @__PURE__ */ React.createElement(Group, { className: "vds-controls-group" }, slot(slots, "topControlsGroupStart", null), slot(slots, "airPlayButton", /* @__PURE__ */ React.createElement(DefaultAirPlayButton, { tooltip: "top start" })), slot(slots, "googleCastButton", /* @__PURE__ */ React.createElement(DefaultGoogleCastButton, { tooltip: "top start" })), /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null), slot(slots, "topControlsGroupCenter", null), /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null), slot(slots, "captionButton", /* @__PURE__ */ React.createElement(DefaultCaptionButton, { tooltip: "bottom" })), slot(slots, "downloadButton", /* @__PURE__ */ React.createElement(DefaultDownloadButton, null)), /* @__PURE__ */ React.createElement(DefaultVideoMenus, { slots }), /* @__PURE__ */ React.createElement(DefaultVolumePopup, { orientation: "vertical", tooltip: "bottom end", slots }), slot(slots, "topControlsGroupEnd", null)), /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null), /* @__PURE__ */ React.createElement(Group, { className: "vds-controls-group" }, slot(slots, "centerControlsGroupStart", null), /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null), /* @__PURE__ */ React.createElement(DefaultSeekButton, { backward: true, tooltip: "top" }), slot(slots, "centerControlsGroupCenter", null), slot(slots, "playButton", /* @__PURE__ */ React.createElement(DefaultPlayButton, { tooltip: "top" })), /* @__PURE__ */ React.createElement(DefaultSeekButton, { tooltip: "top" }), canOpenEpisodes ? /* @__PURE__ */ React.createElement(DefaultEpisodeButton, { tooltip: "top", onPress: () => setEpisodesOpen((open) => !open) }) : null, /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null), slot(slots, "centerControlsGroupEnd", null)), /* @__PURE__ */ React.createElement(DefaultControlsSpacer, null), /* @__PURE__ */ React.createElement(Group, { className: "vds-controls-group" }, /* @__PURE__ */ React.createElement(DefaultTimeInfo, { slots }), slot(slots, "chapterTitle", /* @__PURE__ */ React.createElement(DefaultTitle, null)), slot(slots, "fullscreenButton", /* @__PURE__ */ React.createElement(DefaultFullscreenButton, { tooltip: "top end" }))), /* @__PURE__ */ React.createElement(Group, { className: "vds-controls-group" }, slot(slots, "timeSlider", /* @__PURE__ */ React.createElement(DefaultTimeSlider, null)))), slot(slots, "startDuration", /* @__PURE__ */ React.createElement(DefaultVideoStartDuration, null)), /* @__PURE__ */ React.createElement(
1197
+ DefaultEpisodesSidebar,
1198
+ {
1199
+ open: episodesOpen,
1200
+ onClose: () => setEpisodesOpen(false),
1201
+ episodes: list,
1202
+ episodesTitle: episodesTitle ?? "Episodes"
1203
+ }
1204
+ ));
1205
+ }
1206
+ DefaultVideoSmallLayout.displayName = "DefaultVideoSmallLayout";
1207
+ function DefaultVideoStartDuration() {
1208
+ const $duration = useMediaState("duration");
1209
+ if ($duration === 0) return null;
1210
+ return /* @__PURE__ */ React.createElement("div", { className: "vds-start-duration" }, /* @__PURE__ */ React.createElement(Time, { className: "vds-time", type: "duration" }));
1211
+ }
1212
+ DefaultVideoStartDuration.displayName = "DefaultVideoStartDuration";
1213
+ function DefaultVideoGestures() {
1214
+ const { noGestures } = useDefaultLayoutContext();
1215
+ if (noGestures) return null;
1216
+ return /* @__PURE__ */ React.createElement("div", { className: "vds-gestures" }, /* @__PURE__ */ React.createElement(Gesture, { className: "vds-gesture", event: "pointerup", action: "toggle:paused" }), /* @__PURE__ */ React.createElement(Gesture, { className: "vds-gesture", event: "pointerup", action: "toggle:controls" }), /* @__PURE__ */ React.createElement(Gesture, { className: "vds-gesture", event: "dblpointerup", action: "toggle:fullscreen" }), /* @__PURE__ */ React.createElement(Gesture, { className: "vds-gesture", event: "dblpointerup", action: "seek:-10" }), /* @__PURE__ */ React.createElement(Gesture, { className: "vds-gesture", event: "dblpointerup", action: "seek:10" }));
1217
+ }
1218
+ DefaultVideoGestures.displayName = "DefaultVideoGestures";
1219
+ function DefaultBufferingIndicator() {
1220
+ return /* @__PURE__ */ React.createElement("div", { className: "vds-buffering-indicator" }, /* @__PURE__ */ React.createElement(Root$b, { className: "vds-buffering-spinner" }, /* @__PURE__ */ React.createElement(Track$1, { className: "vds-buffering-track" }), /* @__PURE__ */ React.createElement(TrackFill$1, { className: "vds-buffering-track-fill" })));
1221
+ }
1222
+ DefaultBufferingIndicator.displayName = "DefaultBufferingIndicator";
1223
+ function DefaultVideoMenus({ slots }) {
1224
+ const { isSmallLayout, noModal, menuGroup } = useDefaultLayoutContext(), side = menuGroup === "top" || isSmallLayout ? "bottom" : "top", tooltip = `${side} end`, placement = noModal ? `${side} end` : !isSmallLayout ? `${side} end` : null;
1225
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, slot(
1226
+ slots,
1227
+ "chaptersMenu",
1228
+ /* @__PURE__ */ React.createElement(
1229
+ DefaultChaptersMenu,
1230
+ {
1231
+ tooltip,
1232
+ placement,
1233
+ portalClass: "vds-video-layout"
1234
+ }
1235
+ )
1236
+ ), slot(
1237
+ slots,
1238
+ "settingsMenu",
1239
+ /* @__PURE__ */ React.createElement(
1240
+ DefaultSettingsMenu,
1241
+ {
1242
+ tooltip,
1243
+ placement,
1244
+ portalClass: "vds-video-layout",
1245
+ slots
1246
+ }
1247
+ )
1248
+ ));
1249
+ }
1250
+ DefaultVideoMenus.displayName = "DefaultVideoMenus";
1251
+ function formatMinutesLeftLabel(secondsLeft) {
1252
+ if (secondsLeft <= 0) return null;
1253
+ if (secondsLeft < 60) return "<1m left";
1254
+ const m = Math.floor(secondsLeft / 60);
1255
+ return `${m}m left`;
1256
+ }
1257
+ function DefaultEpisodesSidebar({
1258
+ open,
1259
+ onClose,
1260
+ episodes,
1261
+ episodesTitle
1262
+ }) {
1263
+ const $fullscreen = useMediaState("fullscreen"), currentTime = useMediaState("currentTime"), duration = useMediaState("duration"), listRef = React.useRef(null), wasEpisodesOpenRef = React.useRef(false);
1264
+ React.useLayoutEffect(() => {
1265
+ const justOpened = open && !wasEpisodesOpenRef.current;
1266
+ wasEpisodesOpenRef.current = open;
1267
+ if (!justOpened || !$fullscreen) return;
1268
+ const root = listRef.current;
1269
+ if (!root) return;
1270
+ requestAnimationFrame(() => {
1271
+ root.querySelector('[data-active="true"]')?.scrollIntoView({
1272
+ block: "nearest",
1273
+ behavior: "smooth"
1274
+ });
1275
+ });
1276
+ }, [open, $fullscreen]);
1277
+ if (!$fullscreen || episodes.length === 0) return null;
1278
+ return /* @__PURE__ */ React.createElement(
1279
+ "div",
1280
+ {
1281
+ className: "vds-episodes-backdrop",
1282
+ "data-open": open ? "true" : "false",
1283
+ onPointerUp: (event) => {
1284
+ if (event.target === event.currentTarget) onClose();
1285
+ }
1286
+ },
1287
+ /* @__PURE__ */ React.createElement(
1288
+ "aside",
1289
+ {
1290
+ className: "vds-episodes-panel",
1291
+ "data-open": open ? "true" : "false",
1292
+ onKeyDown: (event) => {
1293
+ if (event.key === "Escape") onClose();
1294
+ }
1295
+ },
1296
+ /* @__PURE__ */ React.createElement("header", { className: "vds-episodes-panel-header" }, /* @__PURE__ */ React.createElement("h3", { className: "vds-episodes-panel-title" }, episodesTitle), /* @__PURE__ */ React.createElement(
1297
+ "button",
1298
+ {
1299
+ type: "button",
1300
+ className: "vds-episodes-close-btn",
1301
+ "aria-label": "Close episodes",
1302
+ onPointerUp: (event) => {
1303
+ event.stopPropagation();
1304
+ onClose();
1305
+ }
1306
+ },
1307
+ /* @__PURE__ */ React.createElement("span", { "aria-hidden": "true" }, "\u2715")
1308
+ )),
1309
+ /* @__PURE__ */ React.createElement("div", { ref: listRef, className: "vds-episodes-list", role: "list" }, episodes.map((episode, index) => {
1310
+ const episodeName = episode.episodeTitle || `Episode ${episode.episodeNumber ?? index + 1}`;
1311
+ const seasonEpLabel = episode.seasonNumber != null && episode.episodeNumber != null ? `S${String(episode.seasonNumber).padStart(2, "0")} \xB7 E${String(episode.episodeNumber).padStart(2, "0")}` : episodeName;
1312
+ const isActive = !!episode.isActive;
1313
+ const onEpisodeSelect = (event) => {
1314
+ event.stopPropagation();
1315
+ if (isActive) return;
1316
+ event.currentTarget.dispatchEvent(
1317
+ new CustomEvent("vds-episode-select", {
1318
+ bubbles: true,
1319
+ composed: true,
1320
+ detail: { episode, index }
1321
+ })
1322
+ );
1323
+ onClose();
1324
+ };
1325
+ let runtimeText = null;
1326
+ if (isActive && duration > 0) {
1327
+ const secsLeft = Math.max(0, duration - currentTime);
1328
+ runtimeText = formatMinutesLeftLabel(secsLeft);
1329
+ } else if (episode.timeLeft != null && episode.timeLeft > 0) {
1330
+ runtimeText = `${episode.timeLeft}m left`;
1331
+ } else if (Number.isFinite(episode.runtime) && (episode.runtime ?? 0) > 0) {
1332
+ runtimeText = `${episode.runtime}m`;
1333
+ }
1334
+ let progressPct = 0;
1335
+ if (isActive && duration > 0) {
1336
+ progressPct = Math.min(100, currentTime / duration * 100);
1337
+ } else if (episode.progressPercent != null && episode.progressPercent > 0) {
1338
+ progressPct = Math.min(100, episode.progressPercent);
1339
+ }
1340
+ const showSubtitle = !!episode.episodeTitle && episode.episodeTitle.trim() !== "" && episode.episodeTitle !== episode.title;
1341
+ return /* @__PURE__ */ React.createElement(
1342
+ "article",
1343
+ {
1344
+ key: `${episode.episodeNumber ?? index}-${episode.title ?? ""}`,
1345
+ className: "vds-episode-item",
1346
+ "data-active": isActive ? "true" : "false",
1347
+ "aria-current": isActive ? "true" : void 0,
1348
+ role: "button",
1349
+ tabIndex: 0,
1350
+ "aria-label": episode.title || episodeName,
1351
+ onPointerUp: onEpisodeSelect,
1352
+ onKeyDown: (event) => {
1353
+ if (event.key === "Enter" || event.key === " ") onEpisodeSelect(event);
1354
+ }
1355
+ },
1356
+ /* @__PURE__ */ React.createElement("div", { className: "vds-episode-thumb-wrap" }, episode.thumbnail ? /* @__PURE__ */ React.createElement(
1357
+ "img",
1358
+ {
1359
+ className: "vds-episode-thumb",
1360
+ src: episode.thumbnail,
1361
+ alt: episode.title || episodeName,
1362
+ loading: "lazy",
1363
+ decoding: "async"
1364
+ }
1365
+ ) : /* @__PURE__ */ React.createElement("div", { className: "vds-episode-thumb vds-episode-thumb-placeholder" }), progressPct > 0 ? /* @__PURE__ */ React.createElement("div", { className: "vds-episode-progress-track", "aria-hidden": "true" }, /* @__PURE__ */ React.createElement("div", { className: "vds-episode-progress-fill", style: { width: `${progressPct}%` } })) : null),
1366
+ /* @__PURE__ */ React.createElement("div", { className: "vds-episode-body" }, /* @__PURE__ */ React.createElement("div", { className: "vds-episode-meta-row" }, /* @__PURE__ */ React.createElement("div", { className: "vds-episode-meta-primary" }, isActive ? /* @__PURE__ */ React.createElement("span", { className: "vds-episode-now-chip" }, "Playing") : null, /* @__PURE__ */ React.createElement("span", { className: "vds-episode-label" }, seasonEpLabel)), runtimeText ? /* @__PURE__ */ React.createElement("span", { className: "vds-episode-runtime" }, runtimeText) : null), /* @__PURE__ */ React.createElement("h4", { className: "vds-episode-title", title: episode.title || "" }, episode.title || "-"), showSubtitle ? /* @__PURE__ */ React.createElement("p", { className: "vds-episode-subtitle", title: episode.episodeTitle }, episode.episodeTitle) : null, episode.overview ? /* @__PURE__ */ React.createElement("p", { className: "vds-episode-desc", title: episode.overview }, episode.overview) : null)
1367
+ );
1368
+ }))
1369
+ )
1370
+ );
1371
+ }
1372
+ function DefaultVideoLoadLayout() {
1373
+ const { isSmallLayout } = useDefaultLayoutContext(), baseSlots = useDefaultVideoLayoutSlots(), slots = { ...baseSlots, ...baseSlots?.[isSmallLayout ? "smallLayout" : "largeLayout"] };
1374
+ return /* @__PURE__ */ React.createElement("div", { className: "vds-load-container" }, slot(slots, "bufferingIndicator", /* @__PURE__ */ React.createElement(DefaultBufferingIndicator, null)), slot(slots, "loadButton", /* @__PURE__ */ React.createElement(DefaultPlayButton, { tooltip: "top" })));
1375
+ }
1376
+ DefaultVideoLoadLayout.displayName = "DefaultVideoLoadLayout";
1377
+ function DefaultVideoKeyboardDisplay() {
1378
+ const { noKeyboardAnimations, icons, userPrefersKeyboardAnimations } = useDefaultLayoutContext(), $userPrefersKeyboardAnimations = useSignal(userPrefersKeyboardAnimations), disabled = noKeyboardAnimations || !$userPrefersKeyboardAnimations;
1379
+ if (disabled || !icons.KeyboardDisplay) return null;
1380
+ return /* @__PURE__ */ React.createElement(DefaultKeyboardDisplay, { icons: icons.KeyboardDisplay });
1381
+ }
1382
+ DefaultVideoKeyboardDisplay.displayName = "DefaultVideoKeyboardDisplay";
1383
+
1384
+ export { DefaultAudioLayout, DefaultBufferingIndicator, DefaultKeyboardDisplay, DefaultLayoutContext, DefaultMenuButton, DefaultMenuCheckbox, DefaultMenuItem, DefaultMenuRadioGroup, DefaultMenuSection, DefaultMenuSliderItem, DefaultSliderParts, DefaultSliderSteps, DefaultTooltip, DefaultVideoGestures, DefaultVideoLargeLayout, DefaultVideoLayout, DefaultVideoSmallLayout, createRadioOptions, i18n, useDefaultLayoutContext, useDefaultLayoutWord };