@videojs/react 0.1.0-preview.10

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.
@@ -0,0 +1,796 @@
1
+ import { a as useMediaStore, i as useMediaSelector } from "./store-BYodyXVF.js";
2
+ import { currentTimeDisplayStateDefinition, durationDisplayStateDefinition, fullscreenButtonStateDefinition, muteButtonStateDefinition, playButtonStateDefinition, previewTimeDisplayStateDefinition, timeSliderStateDefinition, volumeSliderStateDefinition } from "@videojs/core/store";
3
+ import { formatDisplayTime, shallowEqual } from "@videojs/utils";
4
+ import * as React$1 from "react";
5
+ import { Children, cloneElement, createContext, forwardRef, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
6
+ import { Fragment, jsx } from "react/jsx-runtime";
7
+ import { Popover, TimeSlider, Tooltip, VolumeSlider } from "@videojs/core";
8
+
9
+ //#region src/utils/component-factory.tsx
10
+ const Context$1 = createContext(null);
11
+ /**
12
+ * Generic factory function to create connected components following the hooks pattern
13
+ * inspired by Adobe React Spectrum and Base UI architectures.
14
+ *
15
+ * @param useStateHook - Hook that provides component state
16
+ * @param usePropsHook - Hook that enhances props with state-derived values
17
+ * @param defaultRender - Default render function for the component
18
+ * @param displayName - Display name for React DevTools
19
+ * @returns Connected component with customizable render prop
20
+ */
21
+ function toConnectedComponent(useStateHook, usePropsHook, defaultRender, displayName) {
22
+ const ConnectedComponent = forwardRef(({ render = defaultRender,...props }, ref) => {
23
+ const propsWithRef = ref ? {
24
+ ...props,
25
+ ref
26
+ } : props;
27
+ const connectedState = useStateHook(propsWithRef);
28
+ const connectedProps = usePropsHook(propsWithRef, connectedState);
29
+ return /* @__PURE__ */ jsx(Context$1.Provider, {
30
+ value: connectedState,
31
+ children: render(connectedProps, connectedState)
32
+ });
33
+ });
34
+ ConnectedComponent.displayName = displayName;
35
+ return ConnectedComponent;
36
+ }
37
+ /**
38
+ * Factory function to create context-based components that don't use toConnectedComponent
39
+ * These components rely on context provided by a parent component.
40
+ *
41
+ * @param usePropsHook - Hook that enhances props with context-derived values
42
+ * @param defaultRender - Default render function for the component
43
+ * @param displayName - Display name for React DevTools
44
+ * @returns Context-based component with customizable render prop
45
+ */
46
+ function toContextComponent(usePropsHook, defaultRender, displayName) {
47
+ const ContextComponent = forwardRef(({ render = defaultRender,...props }, ref) => {
48
+ const context = useContext(Context$1);
49
+ return render(usePropsHook(ref ? {
50
+ ...props,
51
+ ref
52
+ } : props, context), context);
53
+ });
54
+ ContextComponent.displayName = displayName;
55
+ return ContextComponent;
56
+ }
57
+ /**
58
+ * Hook that manages a CoreClass instance and triggers re-renders when state changes.
59
+ * Uses useSyncExternalStore for optimal performance with external state subscriptions.
60
+ */
61
+ function useCore(CoreClass, state) {
62
+ const coreRef = useRef(null);
63
+ const snapshotRef = useRef(null);
64
+ if (!coreRef.current) {
65
+ coreRef.current = new CoreClass();
66
+ snapshotRef.current = coreRef.current.getState();
67
+ }
68
+ useEffect(() => {
69
+ coreRef.current?.setState(state);
70
+ }, [...Object.values(state)]);
71
+ useSyncExternalStore(useCallback((onStoreChange) => {
72
+ if (!coreRef.current) return () => {};
73
+ return coreRef.current.subscribe((newState) => {
74
+ snapshotRef.current = newState;
75
+ onStoreChange();
76
+ });
77
+ }, []), useCallback(() => {
78
+ return snapshotRef.current;
79
+ }, []), () => null);
80
+ return coreRef.current.getState();
81
+ }
82
+
83
+ //#endregion
84
+ //#region src/components/CurrentTimeDisplay.tsx
85
+ function useCurrentTimeDisplayState(_props) {
86
+ /** @TODO Fix type issues with hooks (CJP) */
87
+ const mediaState = useMediaSelector(currentTimeDisplayStateDefinition.stateTransform, shallowEqual);
88
+ return {
89
+ currentTime: mediaState.currentTime ?? 0,
90
+ duration: mediaState.duration ?? 0
91
+ };
92
+ }
93
+ function useCurrentTimeDisplayProps(props, _state) {
94
+ return { ...props };
95
+ }
96
+ function renderCurrentTimeDisplay(props, state) {
97
+ const { showRemaining,...restProps } = props;
98
+ /** @TODO Should this live here or elsewhere? (CJP) */
99
+ const timeLabel = showRemaining && state.duration != null && state.currentTime != null ? formatDisplayTime(-(state.duration - state.currentTime)) : formatDisplayTime(state.currentTime);
100
+ return /* @__PURE__ */ jsx("span", {
101
+ ...restProps,
102
+ children: timeLabel
103
+ });
104
+ }
105
+ const CurrentTimeDisplay = toConnectedComponent(useCurrentTimeDisplayState, useCurrentTimeDisplayProps, renderCurrentTimeDisplay, "CurrentTimeDisplay");
106
+
107
+ //#endregion
108
+ //#region src/components/DurationDisplay.tsx
109
+ function useDurationDisplayState(_props) {
110
+ return { duration: useMediaSelector(durationDisplayStateDefinition.stateTransform, shallowEqual).duration ?? 0 };
111
+ }
112
+ function useDurationDisplayProps(props) {
113
+ return { ...props };
114
+ }
115
+ function renderDurationDisplay(props, state) {
116
+ return /* @__PURE__ */ jsx("span", {
117
+ ...props,
118
+ children: formatDisplayTime(state.duration)
119
+ });
120
+ }
121
+ const DurationDisplay = toConnectedComponent(useDurationDisplayState, useDurationDisplayProps, renderDurationDisplay, "DurationDisplay");
122
+
123
+ //#endregion
124
+ //#region src/components/FullscreenButton.tsx
125
+ function useFullscreenButtonState(_props) {
126
+ const mediaStore = useMediaStore();
127
+ const mediaState = useMediaSelector(fullscreenButtonStateDefinition.stateTransform, shallowEqual);
128
+ const methods = useMemo(() => fullscreenButtonStateDefinition.createRequestMethods(mediaStore.dispatch), [mediaStore]);
129
+ return {
130
+ fullscreen: mediaState.fullscreen,
131
+ requestEnterFullscreen: methods.requestEnterFullscreen,
132
+ requestExitFullscreen: methods.requestExitFullscreen
133
+ };
134
+ }
135
+ function getFullscreenButtonProps(props, state) {
136
+ const baseProps = {
137
+ role: "button",
138
+ "aria-label": state.fullscreen ? "exit fullscreen" : "enter fullscreen",
139
+ "data-tooltip": state.fullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
140
+ ...props
141
+ };
142
+ if (state.fullscreen) baseProps["data-fullscreen"] = "";
143
+ return baseProps;
144
+ }
145
+ function renderFullscreenButton(props, state) {
146
+ return /* @__PURE__ */ jsx("button", {
147
+ type: "button",
148
+ ...props,
149
+ onClick: () => {
150
+ if (props.disabled) return;
151
+ if (state.fullscreen) state.requestExitFullscreen();
152
+ else state.requestEnterFullscreen();
153
+ },
154
+ children: props.children
155
+ });
156
+ }
157
+ const FullscreenButton = toConnectedComponent(useFullscreenButtonState, getFullscreenButtonProps, renderFullscreenButton, "FullscreenButton");
158
+
159
+ //#endregion
160
+ //#region src/utils/use-composed-refs.ts
161
+ /**
162
+ * Set a given ref to a given value
163
+ * This utility takes care of different types of refs: callback refs and RefObject(s)
164
+ */
165
+ function setRef(ref, value) {
166
+ if (typeof ref === "function") return ref(value);
167
+ else if (ref !== null && ref !== void 0) ref.current = value;
168
+ }
169
+ /**
170
+ * A utility to compose multiple refs together
171
+ * Accepts callback refs and RefObject(s)
172
+ */
173
+ function composeRefs(...refs) {
174
+ return (node) => {
175
+ let hasCleanup = false;
176
+ const cleanups = refs.map((ref) => {
177
+ const cleanup = setRef(ref, node);
178
+ if (!hasCleanup && typeof cleanup == "function") hasCleanup = true;
179
+ return cleanup;
180
+ });
181
+ if (hasCleanup) return () => {
182
+ for (let i = 0; i < cleanups.length; i++) {
183
+ const cleanup = cleanups[i];
184
+ if (typeof cleanup == "function") cleanup();
185
+ else setRef(refs[i], null);
186
+ }
187
+ };
188
+ };
189
+ }
190
+ /**
191
+ * A custom hook that composes multiple refs
192
+ * Accepts callback refs and RefObject(s)
193
+ */
194
+ function useComposedRefs(...refs) {
195
+ return React$1.useCallback(composeRefs(...refs), refs);
196
+ }
197
+
198
+ //#endregion
199
+ //#region src/components/MediaContainer.tsx
200
+ /**
201
+ * Hook to associate a React element as the fullscreen container for the media store.
202
+ * This is equivalent to Media Chrome's useMediaFullscreenRef but for VJS-10.
203
+ *
204
+ * The ref callback will register the element as the container state owner
205
+ * in the media store, enabling fullscreen functionality.
206
+ *
207
+ * @example
208
+ * import { useMediaContainerRef } from '@videojs/react';
209
+ *
210
+ * const PlayerContainer = ({ children }) => {
211
+ * const containerRef = useMediaContainerRef();
212
+ * return <div ref={containerRef}>{children}</div>;
213
+ * };
214
+ */
215
+ function useMediaContainerRef() {
216
+ const mediaStore = useMediaStore();
217
+ return useCallback((containerElement) => {
218
+ if (!mediaStore) return;
219
+ mediaStore.dispatch({
220
+ type: "containerstateownerchangerequest",
221
+ detail: containerElement
222
+ });
223
+ }, [mediaStore]);
224
+ }
225
+ /**
226
+ * MediaContainer component that automatically registers itself as the fullscreen container.
227
+ * This provides a simple wrapper component for fullscreen functionality.
228
+ *
229
+ * @example
230
+ * import { MediaContainer } from '@videojs/react';
231
+ *
232
+ * const MyPlayer = () => (
233
+ * <MediaContainer>
234
+ * <video src="video.mp4" />
235
+ * <div>Controls here</div>
236
+ * </MediaContainer>
237
+ * );
238
+ */
239
+ const MediaContainer = forwardRef(({ children,...props }, ref) => {
240
+ const composedRef = useComposedRefs(ref, useMediaContainerRef());
241
+ const mediaStore = useMediaStore();
242
+ const mediaState = useMediaSelector(playButtonStateDefinition.stateTransform, shallowEqual);
243
+ const methods = useMemo(() => playButtonStateDefinition.createRequestMethods(mediaStore.dispatch), [mediaStore]);
244
+ return /* @__PURE__ */ jsx("div", {
245
+ ref: composedRef,
246
+ onClick: useCallback((event) => {
247
+ if (!["video", "audio"].includes(event.target.localName || "")) return;
248
+ if (mediaState.paused) methods.requestPlay();
249
+ else methods.requestPause();
250
+ }, [mediaState.paused, methods]),
251
+ "data-media-container": true,
252
+ ...props,
253
+ children
254
+ });
255
+ });
256
+
257
+ //#endregion
258
+ //#region src/components/MuteButton.tsx
259
+ function useMuteButtonState(_props) {
260
+ const mediaStore = useMediaStore();
261
+ const mediaState = useMediaSelector(muteButtonStateDefinition.stateTransform, shallowEqual);
262
+ const methods = useMemo(() => muteButtonStateDefinition.createRequestMethods(mediaStore.dispatch), [mediaStore]);
263
+ return {
264
+ volumeLevel: mediaState.volumeLevel,
265
+ muted: mediaState.muted,
266
+ requestMute: methods.requestMute,
267
+ requestUnmute: methods.requestUnmute
268
+ };
269
+ }
270
+ function getMuteButtonProps(props, state) {
271
+ const baseProps = {
272
+ "data-volume-level": state.volumeLevel,
273
+ role: "button",
274
+ "aria-label": state.muted ? "unmute" : "mute",
275
+ "data-tooltip": state.muted ? "Unmute" : "Mute",
276
+ ...props
277
+ };
278
+ if (state.muted) baseProps["data-muted"] = "";
279
+ return baseProps;
280
+ }
281
+ function renderMuteButton(props, state) {
282
+ return /* @__PURE__ */ jsx("button", {
283
+ type: "button",
284
+ ...props,
285
+ onClick: () => {
286
+ if (props.disabled) return;
287
+ if (state.volumeLevel === "off") state.requestUnmute();
288
+ else state.requestMute();
289
+ },
290
+ children: props.children
291
+ });
292
+ }
293
+ const MuteButton = toConnectedComponent(useMuteButtonState, getMuteButtonProps, renderMuteButton, "MuteButton");
294
+ var MuteButton_default = MuteButton;
295
+
296
+ //#endregion
297
+ //#region src/components/PlayButton.tsx
298
+ function usePlayButtonState(_props) {
299
+ const mediaStore = useMediaStore();
300
+ const mediaState = useMediaSelector(playButtonStateDefinition.stateTransform, shallowEqual);
301
+ const methods = useMemo(() => playButtonStateDefinition.createRequestMethods(mediaStore.dispatch), [mediaStore]);
302
+ return {
303
+ paused: mediaState.paused,
304
+ requestPlay: methods.requestPlay,
305
+ requestPause: methods.requestPause
306
+ };
307
+ }
308
+ function getPlayButtonProps(props, state) {
309
+ const baseProps = {
310
+ role: "button",
311
+ "aria-label": state.paused ? "play" : "pause",
312
+ "data-tooltip": state.paused ? "Play" : "Pause",
313
+ ...props
314
+ };
315
+ if (state.paused) baseProps["data-paused"] = "";
316
+ return baseProps;
317
+ }
318
+ function renderPlayButton(props, state) {
319
+ return /* @__PURE__ */ jsx("button", {
320
+ type: "button",
321
+ ...props,
322
+ onClick: () => {
323
+ if (props.disabled) return;
324
+ if (state.paused) state.requestPlay();
325
+ else state.requestPause();
326
+ },
327
+ children: props.children
328
+ });
329
+ }
330
+ const PlayButton = toConnectedComponent(usePlayButtonState, getPlayButtonProps, renderPlayButton, "PlayButton");
331
+ var PlayButton_default = PlayButton;
332
+
333
+ //#endregion
334
+ //#region src/utils/use-mutation-observer.ts
335
+ /**
336
+ * Custom React hook for observing DOM mutations using MutationObserver
337
+ *
338
+ * @param target - Element to observe (ref or element)
339
+ * @param callback - Function called when mutations occur
340
+ * @param options - MutationObserver options
341
+ */
342
+ function useMutationObserver(target, callback, options = {
343
+ attributes: true,
344
+ childList: true,
345
+ subtree: true
346
+ }) {
347
+ const callbackRef = useRef(callback);
348
+ useEffect(() => {
349
+ callbackRef.current = callback;
350
+ }, [callback]);
351
+ useEffect(() => {
352
+ const element = target && "current" in target ? target.current : target;
353
+ if (!element || !(element instanceof Element)) return;
354
+ const observer = new MutationObserver((mutations, obs) => {
355
+ callbackRef.current(mutations, obs);
356
+ });
357
+ observer.observe(element, options);
358
+ return () => {
359
+ observer.disconnect();
360
+ };
361
+ }, [target, options]);
362
+ }
363
+
364
+ //#endregion
365
+ //#region src/components/Popover.tsx
366
+ function usePopoverRootState(props) {
367
+ const { openOnHover = false, delay = 0, closeDelay = 0 } = props;
368
+ const [placement, setPlacement] = useState("top");
369
+ const [sideOffset, setSideOffset] = useState(5);
370
+ const [collisionPadding, setCollisionPadding] = useState(0);
371
+ const popupId = useId().replace(/^:([^:]+):$/, "«$1»");
372
+ const coreState = useCore(Popover, {
373
+ openOnHover,
374
+ delay,
375
+ closeDelay,
376
+ placement,
377
+ sideOffset,
378
+ collisionPadding
379
+ });
380
+ const updatePositioning = useCallback((newPlacement, newSideOffset, newCollisionPadding) => {
381
+ setPlacement(newPlacement);
382
+ setSideOffset(newSideOffset);
383
+ setCollisionPadding(newCollisionPadding);
384
+ }, []);
385
+ return {
386
+ ...coreState,
387
+ popupId,
388
+ updatePositioning
389
+ };
390
+ }
391
+ function usePopoverRootProps(props, _state) {
392
+ return { children: props.children };
393
+ }
394
+ function renderPopoverRoot(props) {
395
+ return /* @__PURE__ */ jsx(Fragment, { children: props.children });
396
+ }
397
+ const PopoverRoot = toConnectedComponent(usePopoverRootState, usePopoverRootProps, renderPopoverRoot, "Popover.Root");
398
+ function usePopoverTriggerProps(props, context) {
399
+ const { children } = props;
400
+ const { _setTriggerElement, _open, popupId } = context;
401
+ const child = Children.only(children);
402
+ const existingStyle = child.props?.style || {};
403
+ return {
404
+ child,
405
+ triggerProps: {
406
+ ref: _setTriggerElement,
407
+ "data-popup-open": _open ? "" : void 0,
408
+ commandfor: popupId ?? void 0,
409
+ style: {
410
+ ...existingStyle,
411
+ ...popupId ? { anchorName: `--${popupId}` } : {}
412
+ }
413
+ }
414
+ };
415
+ }
416
+ function renderPopoverTrigger(props) {
417
+ return cloneElement(props.child, props.triggerProps);
418
+ }
419
+ const PopoverTrigger = toContextComponent(usePopoverTriggerProps, renderPopoverTrigger, "Popover.Trigger");
420
+ function usePopoverPositionerProps(props, context) {
421
+ const { side = "top", sideOffset = 5, collisionPadding = 0, collisionBoundary, children } = props;
422
+ const { updatePositioning, _setCollisionBoundaryElement } = context;
423
+ useEffect(() => {
424
+ updatePositioning(side, sideOffset, collisionPadding);
425
+ }, [
426
+ side,
427
+ sideOffset,
428
+ collisionPadding,
429
+ updatePositioning
430
+ ]);
431
+ useEffect(() => {
432
+ if (collisionBoundary) _setCollisionBoundaryElement(collisionBoundary);
433
+ }, [collisionBoundary, _setCollisionBoundaryElement]);
434
+ return { children };
435
+ }
436
+ function renderPopoverPositioner(props) {
437
+ return /* @__PURE__ */ jsx(Fragment, { children: props.children });
438
+ }
439
+ const PopoverPositioner = toContextComponent(usePopoverPositionerProps, renderPopoverPositioner, "Popover.Positioner");
440
+ function usePopoverPopupProps(props, context) {
441
+ const { className, style, children, id } = props;
442
+ const { _setPopoverElement, _transitionStatus, placement, popupId, _popoverStyle, _triggerElement, _popoverElement, _setCollisionBoundaryElement, _collisionBoundaryElement } = context;
443
+ useEffect(() => {
444
+ if (!_popoverElement) return;
445
+ if (!_collisionBoundaryElement) _setCollisionBoundaryElement(_popoverElement.closest("[data-media-container]"));
446
+ }, [
447
+ _popoverElement,
448
+ _collisionBoundaryElement,
449
+ _setCollisionBoundaryElement
450
+ ]);
451
+ const [dataAttrs, setDataAttrs] = useState(() => getDataAttributes(_triggerElement));
452
+ useEffect(() => {
453
+ setDataAttrs(getDataAttributes(_triggerElement));
454
+ }, [_triggerElement]);
455
+ useMutationObserver(_triggerElement, () => {
456
+ setDataAttrs(getDataAttributes(_triggerElement));
457
+ }, { attributes: true });
458
+ return {
459
+ ref: _setPopoverElement,
460
+ id: id ?? popupId ?? void 0,
461
+ className,
462
+ popover: "manual",
463
+ style: {
464
+ ..._popoverStyle,
465
+ ...style
466
+ },
467
+ ...dataAttrs,
468
+ "data-side": placement,
469
+ "data-starting-style": _transitionStatus === "initial" ? "" : void 0,
470
+ "data-open": _transitionStatus === "initial" || _transitionStatus === "open" ? "" : void 0,
471
+ "data-ending-style": _transitionStatus === "close" || _transitionStatus === "unmounted" ? "" : void 0,
472
+ "data-closed": _transitionStatus === "close" || _transitionStatus === "unmounted" ? "" : void 0,
473
+ children
474
+ };
475
+ }
476
+ function getDataAttributes(element) {
477
+ if (!element) return void 0;
478
+ return Object.fromEntries(Array.from(element.attributes).filter((attr) => attr.name.startsWith("data-")).map((attr) => [attr.name, attr.value]));
479
+ }
480
+ function renderPopoverPopup(props) {
481
+ return /* @__PURE__ */ jsx("div", { ...props });
482
+ }
483
+ const PopoverPopup = toContextComponent(usePopoverPopupProps, renderPopoverPopup, "Popover.Popup");
484
+ const Popover$1 = Object.assign({}, {
485
+ Root: PopoverRoot,
486
+ Trigger: PopoverTrigger,
487
+ Positioner: PopoverPositioner,
488
+ Popup: PopoverPopup
489
+ });
490
+ var Popover_default = Popover$1;
491
+
492
+ //#endregion
493
+ //#region src/components/PreviewTimeDisplay.tsx
494
+ function usePreviewTimeDisplayState(_props) {
495
+ return { previewTime: useMediaSelector(previewTimeDisplayStateDefinition.stateTransform, shallowEqual).previewTime ?? 0 };
496
+ }
497
+ function getPreviewTimeDisplayProps(props, _state) {
498
+ return { ...props };
499
+ }
500
+ function renderPreviewTimeDisplay(props, state) {
501
+ const { showRemaining,...restProps } = props;
502
+ /** @TODO Should this live here or elsewhere? (CJP) */
503
+ const timeLabel = formatDisplayTime(state.previewTime);
504
+ return /* @__PURE__ */ jsx("span", {
505
+ ...restProps,
506
+ children: timeLabel
507
+ });
508
+ }
509
+ const PreviewTimeDisplay = toConnectedComponent(usePreviewTimeDisplayState, getPreviewTimeDisplayProps, renderPreviewTimeDisplay, "PreviewTimeDisplay");
510
+ var PreviewTimeDisplay_default = PreviewTimeDisplay;
511
+
512
+ //#endregion
513
+ //#region src/components/TimeSlider.tsx
514
+ function useTimeSliderRootState(props) {
515
+ const { orientation = "horizontal" } = props;
516
+ const mediaStore = useMediaStore();
517
+ const mediaState = useMediaSelector(timeSliderStateDefinition.stateTransform, shallowEqual);
518
+ const mediaMethods = useMemo(() => timeSliderStateDefinition.createRequestMethods(mediaStore.dispatch), [mediaStore]);
519
+ return {
520
+ ...useCore(TimeSlider, {
521
+ ...mediaState,
522
+ ...mediaMethods
523
+ }),
524
+ orientation
525
+ };
526
+ }
527
+ function useTimeSliderRootProps(props, state) {
528
+ const { children, className, id, style, orientation = "horizontal", ref } = props;
529
+ return {
530
+ ref: useComposedRefs(ref, state._setRootElement),
531
+ id,
532
+ role: "slider",
533
+ tabIndex: 0,
534
+ "aria-label": "Seek",
535
+ "aria-valuemin": 0,
536
+ "aria-valuemax": Math.round(state.duration),
537
+ "aria-valuenow": Math.round(state.currentTime),
538
+ "aria-valuetext": `${state._currentTimeText} of ${state._durationText}`,
539
+ "aria-orientation": orientation,
540
+ "data-orientation": orientation,
541
+ "data-current-time": state.currentTime,
542
+ "data-duration": state.duration,
543
+ className,
544
+ style: {
545
+ ...style,
546
+ "--slider-fill": `${state._fillWidth.toFixed(3)}%`,
547
+ "--slider-pointer": `${(state._pointerWidth * 100).toFixed(3)}%`
548
+ },
549
+ children
550
+ };
551
+ }
552
+ function renderTimeSliderRoot(props) {
553
+ return /* @__PURE__ */ jsx("div", { ...props });
554
+ }
555
+ const TimeSliderRoot = toConnectedComponent(useTimeSliderRootState, useTimeSliderRootProps, renderTimeSliderRoot, "TimeSlider.Root");
556
+ function useTimeSliderTrackProps(props, context) {
557
+ return {
558
+ ref: context._setTrackElement,
559
+ "data-orientation": context.orientation,
560
+ ...props,
561
+ style: {
562
+ ...props.style,
563
+ [context.orientation === "horizontal" ? "width" : "height"]: "100%"
564
+ }
565
+ };
566
+ }
567
+ function renderTimeSliderTrack(props) {
568
+ return /* @__PURE__ */ jsx("div", { ...props });
569
+ }
570
+ const TimeSliderTrack = toContextComponent(useTimeSliderTrackProps, renderTimeSliderTrack, "TimeSlider.Track");
571
+ function getTimeSliderThumbProps(props, context) {
572
+ return {
573
+ "data-orientation": context.orientation,
574
+ ...props,
575
+ style: {
576
+ ...props.style,
577
+ [context.orientation === "horizontal" ? "insetInlineStart" : "insetBlockEnd"]: "var(--slider-fill)",
578
+ [context.orientation === "horizontal" ? "top" : "left"]: "50%",
579
+ translate: context.orientation === "horizontal" ? "-50% -50%" : "-50% 50%",
580
+ position: "absolute"
581
+ }
582
+ };
583
+ }
584
+ function renderTimeSliderThumb(props) {
585
+ return /* @__PURE__ */ jsx("div", { ...props });
586
+ }
587
+ const TimeSliderThumb = toContextComponent(getTimeSliderThumbProps, renderTimeSliderThumb, "TimeSlider.Thumb");
588
+ function getTimeSliderPointerProps(props, context) {
589
+ return {
590
+ "data-orientation": context.orientation,
591
+ ...props,
592
+ style: {
593
+ ...props.style,
594
+ [context.orientation === "horizontal" ? "width" : "height"]: "var(--slider-pointer, 0%)",
595
+ [context.orientation === "horizontal" ? "height" : "width"]: "100%",
596
+ position: "absolute"
597
+ }
598
+ };
599
+ }
600
+ function renderTimeSliderPointer(props) {
601
+ return /* @__PURE__ */ jsx("div", { ...props });
602
+ }
603
+ const TimeSliderPointer = toContextComponent(getTimeSliderPointerProps, renderTimeSliderPointer, "TimeSlider.Pointer");
604
+ function getTimeSliderProgressProps(props, context) {
605
+ return {
606
+ "data-orientation": context.orientation,
607
+ ...props,
608
+ style: {
609
+ ...props.style,
610
+ [context.orientation === "horizontal" ? "width" : "height"]: "var(--slider-fill, 0%)",
611
+ [context.orientation === "horizontal" ? "height" : "width"]: "100%",
612
+ [context.orientation === "horizontal" ? "top" : "bottom"]: "0",
613
+ position: "absolute"
614
+ }
615
+ };
616
+ }
617
+ function renderTimeSliderProgress(props) {
618
+ return /* @__PURE__ */ jsx("div", { ...props });
619
+ }
620
+ const TimeSliderProgress = toContextComponent(getTimeSliderProgressProps, renderTimeSliderProgress, "TimeSlider.Progress");
621
+ const TimeSlider$1 = Object.assign({}, {
622
+ Root: TimeSliderRoot,
623
+ Track: TimeSliderTrack,
624
+ Thumb: TimeSliderThumb,
625
+ Pointer: TimeSliderPointer,
626
+ Progress: TimeSliderProgress
627
+ });
628
+
629
+ //#endregion
630
+ //#region src/components/Tooltip.tsx
631
+ function useTooltipRootState(props) {
632
+ const { delay = 0, closeDelay = 0, trackCursorAxis } = props;
633
+ const [placement, setPlacement] = useState("top");
634
+ const [sideOffset, setSideOffset] = useState(0);
635
+ const [collisionPadding, setCollisionPadding] = useState(0);
636
+ const popupId = useId().replace(/^:([^:]+):$/, "«$1»");
637
+ const coreState = useCore(Tooltip, {
638
+ delay,
639
+ closeDelay,
640
+ placement,
641
+ sideOffset,
642
+ collisionPadding,
643
+ trackCursorAxis
644
+ });
645
+ const updatePositioning = useCallback((newPlacement, newSideOffset, newCollisionPadding) => {
646
+ setPlacement(newPlacement);
647
+ setSideOffset(newSideOffset);
648
+ setCollisionPadding(newCollisionPadding);
649
+ }, []);
650
+ return {
651
+ ...coreState,
652
+ popupId,
653
+ updatePositioning
654
+ };
655
+ }
656
+ function useTooltipRootProps(props, _state) {
657
+ return { children: props.children };
658
+ }
659
+ function renderTooltipRoot(props) {
660
+ return /* @__PURE__ */ jsx(Fragment, { children: props.children });
661
+ }
662
+ const TooltipRoot = toConnectedComponent(useTooltipRootState, useTooltipRootProps, renderTooltipRoot, "Tooltip.Root");
663
+ function useTooltipTriggerProps(props, context) {
664
+ return usePopoverTriggerProps(props, context);
665
+ }
666
+ function renderTooltipTrigger(props) {
667
+ return cloneElement(props.child, props.triggerProps);
668
+ }
669
+ const TooltipTrigger = toContextComponent(useTooltipTriggerProps, renderTooltipTrigger, "Tooltip.Trigger");
670
+ function useTooltipPositionerProps(props, context) {
671
+ return usePopoverPositionerProps(props, context);
672
+ }
673
+ function renderTooltipPositioner(props) {
674
+ return /* @__PURE__ */ jsx(Fragment, { children: props.children });
675
+ }
676
+ const TooltipPositioner = toContextComponent(useTooltipPositionerProps, renderTooltipPositioner, "Tooltip.Positioner");
677
+ function useTooltipPopupProps(props, context) {
678
+ return usePopoverPopupProps(props, context);
679
+ }
680
+ function renderTooltipPopup(props) {
681
+ return /* @__PURE__ */ jsx("div", { ...props });
682
+ }
683
+ const TooltipPopup = toContextComponent(useTooltipPopupProps, renderTooltipPopup, "Tooltip.Popup");
684
+ const Tooltip$1 = Object.assign({}, {
685
+ Root: TooltipRoot,
686
+ Trigger: TooltipTrigger,
687
+ Positioner: TooltipPositioner,
688
+ Popup: TooltipPopup
689
+ });
690
+ var Tooltip_default = Tooltip$1;
691
+
692
+ //#endregion
693
+ //#region src/components/VolumeSlider.tsx
694
+ function useVolumeSliderRootState(props) {
695
+ const { orientation = "horizontal" } = props;
696
+ const mediaStore = useMediaStore();
697
+ const mediaState = useMediaSelector(volumeSliderStateDefinition.stateTransform, shallowEqual);
698
+ const mediaMethods = useMemo(() => volumeSliderStateDefinition.createRequestMethods(mediaStore.dispatch), [mediaStore]);
699
+ return {
700
+ ...useCore(VolumeSlider, {
701
+ ...mediaState,
702
+ ...mediaMethods
703
+ }),
704
+ orientation
705
+ };
706
+ }
707
+ function useVolumeSliderRootProps(props, state) {
708
+ const { children, className, id, style, orientation = "horizontal", ref } = props;
709
+ return {
710
+ ref: useComposedRefs(ref, state._setRootElement),
711
+ id,
712
+ role: "slider",
713
+ tabIndex: 0,
714
+ "aria-label": "Volume",
715
+ "aria-valuemin": 0,
716
+ "aria-valuemax": 100,
717
+ "aria-valuenow": Math.round(state.volume * 100),
718
+ "aria-valuetext": state._volumeText,
719
+ "aria-orientation": orientation,
720
+ "data-orientation": orientation,
721
+ "data-muted": state.muted,
722
+ "data-volume-level": state.volumeLevel,
723
+ "data-volume": state.volume,
724
+ className,
725
+ style: {
726
+ ...style,
727
+ "--slider-fill": `${state._fillWidth.toFixed(3)}%`,
728
+ "--slider-pointer": `${(state._pointerWidth * 100).toFixed(3)}%`
729
+ },
730
+ children
731
+ };
732
+ }
733
+ function renderVolumeSliderRoot(props) {
734
+ return /* @__PURE__ */ jsx("div", { ...props });
735
+ }
736
+ const VolumeSliderRoot = toConnectedComponent(useVolumeSliderRootState, useVolumeSliderRootProps, renderVolumeSliderRoot, "VolumeSlider.Root");
737
+ function useVolumeSliderTrackProps(props, context) {
738
+ return {
739
+ ref: context._setTrackElement,
740
+ "data-orientation": context.orientation,
741
+ ...props,
742
+ style: {
743
+ ...props.style,
744
+ [context.orientation === "horizontal" ? "width" : "height"]: "100%"
745
+ }
746
+ };
747
+ }
748
+ function renderVolumeSliderTrack(props) {
749
+ return /* @__PURE__ */ jsx("div", { ...props });
750
+ }
751
+ const VolumeSliderTrack = toContextComponent(useVolumeSliderTrackProps, renderVolumeSliderTrack, "VolumeSlider.Track");
752
+ function getVolumeSliderThumbProps(props, context) {
753
+ return {
754
+ "data-orientation": context.orientation,
755
+ ...props,
756
+ style: {
757
+ ...props.style,
758
+ [context.orientation === "horizontal" ? "insetInlineStart" : "insetBlockEnd"]: "var(--slider-fill)",
759
+ [context.orientation === "horizontal" ? "top" : "left"]: "50%",
760
+ translate: context.orientation === "horizontal" ? "-50% -50%" : "-50% 50%",
761
+ position: "absolute"
762
+ }
763
+ };
764
+ }
765
+ function renderVolumeSliderThumb(props) {
766
+ return /* @__PURE__ */ jsx("div", { ...props });
767
+ }
768
+ const VolumeSliderThumb = toContextComponent(getVolumeSliderThumbProps, renderVolumeSliderThumb, "VolumeSlider.Thumb");
769
+ function getVolumeSliderProgressProps(props, context) {
770
+ return {
771
+ "data-orientation": context.orientation,
772
+ ...props,
773
+ style: {
774
+ ...props.style,
775
+ [context.orientation === "horizontal" ? "width" : "height"]: "var(--slider-fill, 0%)",
776
+ [context.orientation === "horizontal" ? "height" : "width"]: "100%",
777
+ [context.orientation === "horizontal" ? "top" : "bottom"]: "0",
778
+ position: "absolute"
779
+ }
780
+ };
781
+ }
782
+ function renderVolumeSliderProgress(props) {
783
+ return /* @__PURE__ */ jsx("div", { ...props });
784
+ }
785
+ const VolumeSliderProgress = toContextComponent(getVolumeSliderProgressProps, renderVolumeSliderProgress, "VolumeSlider.Progress");
786
+ const VolumeSlider$1 = Object.assign({}, {
787
+ Root: VolumeSliderRoot,
788
+ Track: VolumeSliderTrack,
789
+ Thumb: VolumeSliderThumb,
790
+ Progress: VolumeSliderProgress
791
+ });
792
+ var VolumeSlider_default = VolumeSlider$1;
793
+
794
+ //#endregion
795
+ export { DurationDisplay as _, TimeSlider$1 as a, Popover$1 as c, PlayButton_default as d, MuteButton as f, FullscreenButton as g, useMediaContainerRef as h, Tooltip_default as i, Popover_default as l, MediaContainer as m, VolumeSlider_default as n, PreviewTimeDisplay as o, MuteButton_default as p, Tooltip$1 as r, PreviewTimeDisplay_default as s, VolumeSlider$1 as t, PlayButton as u, CurrentTimeDisplay as v };
796
+ //# sourceMappingURL=VolumeSlider-BSyqpW7V.js.map