@remotion/player 4.0.186 → 4.0.188

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.
@@ -1,5 +1,12 @@
1
1
  import React from 'react';
2
+ import type { RenderVolumeSlider } from './render-volume-slider.js';
2
3
  export declare const VOLUME_SLIDER_WIDTH = 100;
4
+ export type RenderMuteButton = (props: {
5
+ muted: boolean;
6
+ volume: number;
7
+ }) => React.ReactNode;
3
8
  export declare const MediaVolumeSlider: React.FC<{
4
- displayVerticalVolumeSlider: Boolean;
9
+ readonly displayVerticalVolumeSlider: boolean;
10
+ readonly renderMuteButton: RenderMuteButton | null;
11
+ readonly renderVolumeSlider: RenderVolumeSlider | null;
5
12
  }>;
@@ -1,62 +1,29 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  Object.defineProperty(exports, "__esModule", { value: true });
26
3
  exports.MediaVolumeSlider = exports.VOLUME_SLIDER_WIDTH = void 0;
27
4
  const jsx_runtime_1 = require("react/jsx-runtime");
28
- const react_1 = __importStar(require("react"));
5
+ const react_1 = require("react");
29
6
  const remotion_1 = require("remotion");
30
7
  const icons_js_1 = require("./icons.js");
8
+ const render_volume_slider_js_1 = require("./render-volume-slider.js");
31
9
  const use_hover_state_js_1 = require("./use-hover-state.js");
32
- const BAR_HEIGHT = 5;
33
- const KNOB_SIZE = 12;
34
10
  exports.VOLUME_SLIDER_WIDTH = 100;
35
- const MediaVolumeSlider = ({ displayVerticalVolumeSlider }) => {
11
+ const MediaVolumeSlider = ({ displayVerticalVolumeSlider, renderMuteButton, renderVolumeSlider }) => {
36
12
  const [mediaMuted, setMediaMuted] = remotion_1.Internals.useMediaMutedState();
37
13
  const [mediaVolume, setMediaVolume] = remotion_1.Internals.useMediaVolumeState();
38
14
  const [focused, setFocused] = (0, react_1.useState)(false);
39
15
  const parentDivRef = (0, react_1.useRef)(null);
40
16
  const inputRef = (0, react_1.useRef)(null);
41
17
  const hover = (0, use_hover_state_js_1.useHoverState)(parentDivRef, false);
42
- // Need to import it from React to fix React 17 ESM support.
43
- const randomId =
44
- // eslint-disable-next-line react-hooks/rules-of-hooks
45
- typeof react_1.default.useId === 'undefined' ? 'volume-slider' : react_1.default.useId();
46
- const [randomClass] = (0, react_1.useState)(() => `__remotion-volume-slider-${(0, remotion_1.random)(randomId)}`.replace('.', ''));
47
- const isMutedOrZero = mediaMuted || mediaVolume === 0;
48
- const onVolumeChange = (0, react_1.useCallback)((e) => {
49
- setMediaVolume(parseFloat(e.target.value));
50
- }, [setMediaVolume]);
51
- const onBlur = () => {
18
+ const onBlur = (0, react_1.useCallback)(() => {
52
19
  setTimeout(() => {
53
20
  // We need a small delay to check which element was focused next,
54
21
  // and if it wasn't the volume slider, we hide it
55
- if (document.activeElement !== inputRef.current) {
22
+ if (inputRef.current && document.activeElement !== inputRef.current) {
56
23
  setFocused(false);
57
24
  }
58
25
  }, 10);
59
- };
26
+ }, []);
60
27
  const isVolume0 = mediaVolume === 0;
61
28
  const onClick = (0, react_1.useCallback)(() => {
62
29
  if (isVolume0) {
@@ -89,68 +56,34 @@ const MediaVolumeSlider = ({ displayVerticalVolumeSlider }) => {
89
56
  padding: 0,
90
57
  };
91
58
  }, []);
92
- const sliderContainer = (0, react_1.useMemo)(() => {
93
- const paddingLeft = 5;
94
- const common = {
95
- paddingLeft,
96
- height: icons_js_1.ICON_SIZE,
97
- width: exports.VOLUME_SLIDER_WIDTH,
98
- };
99
- if (displayVerticalVolumeSlider) {
100
- return {
101
- ...common,
102
- position: 'absolute',
103
- transform: `rotate(-90deg) translateX(${exports.VOLUME_SLIDER_WIDTH / 2 + icons_js_1.ICON_SIZE / 2}px)`,
104
- };
105
- }
106
- return {
107
- ...common,
108
- };
109
- }, [displayVerticalVolumeSlider]);
110
- const inputStyle = (0, react_1.useMemo)(() => {
111
- const commonStyle = {
112
- WebkitAppearance: 'none',
113
- backgroundColor: 'rgba(255, 255, 255, 0.5)',
114
- borderRadius: BAR_HEIGHT / 2,
115
- cursor: 'pointer',
116
- height: BAR_HEIGHT,
117
- width: exports.VOLUME_SLIDER_WIDTH,
118
- backgroundImage: `linear-gradient(
119
- to right,
120
- white ${mediaVolume * 100}%, rgba(255, 255, 255, 0) ${mediaVolume * 100}%
121
- )`,
122
- };
123
- if (displayVerticalVolumeSlider) {
124
- return {
125
- ...commonStyle,
126
- bottom: icons_js_1.ICON_SIZE + exports.VOLUME_SLIDER_WIDTH / 2,
127
- };
128
- }
129
- return commonStyle;
130
- }, [displayVerticalVolumeSlider, mediaVolume]);
131
- const sliderStyle = `
132
- .${randomClass}::-webkit-slider-thumb {
133
- -webkit-appearance: none;
134
- background-color: white;
135
- border-radius: ${KNOB_SIZE / 2}px;
136
- box-shadow: 0 0 2px black;
137
- height: ${KNOB_SIZE}px;
138
- width: ${KNOB_SIZE}px;
139
- }
140
-
141
- .${randomClass}::-moz-range-thumb {
142
- -webkit-appearance: none;
143
- background-color: white;
144
- border-radius: ${KNOB_SIZE / 2}px;
145
- box-shadow: 0 0 2px black;
146
- height: ${KNOB_SIZE}px;
147
- width: ${KNOB_SIZE}px;
148
- }
149
- `;
150
- return ((0, jsx_runtime_1.jsxs)("div", { ref: parentDivRef, style: parentDivStyle, children: [(0, jsx_runtime_1.jsx)("style", {
151
- // eslint-disable-next-line react/no-danger
152
- dangerouslySetInnerHTML: {
153
- __html: sliderStyle,
154
- } }), (0, jsx_runtime_1.jsx)("button", { "aria-label": isMutedOrZero ? 'Unmute sound' : 'Mute sound', title: isMutedOrZero ? 'Unmute sound' : 'Mute sound', onClick: onClick, onBlur: onBlur, onFocus: () => setFocused(true), style: volumeContainer, type: "button", children: isMutedOrZero ? (0, jsx_runtime_1.jsx)(icons_js_1.VolumeOffIcon, {}) : (0, jsx_runtime_1.jsx)(icons_js_1.VolumeOnIcon, {}) }), (focused || hover) && !mediaMuted && !remotion_1.Internals.isIosSafari() ? ((0, jsx_runtime_1.jsx)("div", { style: sliderContainer, children: (0, jsx_runtime_1.jsx)("input", { ref: inputRef, "aria-label": "Change volume", className: randomClass, max: 1, min: 0, onBlur: () => setFocused(false), onChange: onVolumeChange, step: 0.01, type: "range", value: mediaVolume, style: inputStyle }) })) : null] }));
59
+ const renderDefaultMuteButton = (0, react_1.useCallback)(({ muted, volume }) => {
60
+ const isMutedOrZero = muted || volume === 0;
61
+ return ((0, jsx_runtime_1.jsx)("button", { "aria-label": isMutedOrZero ? 'Unmute sound' : 'Mute sound', title: isMutedOrZero ? 'Unmute sound' : 'Mute sound', onClick: onClick, onBlur: onBlur, onFocus: () => setFocused(true), style: volumeContainer, type: "button", children: isMutedOrZero ? (0, jsx_runtime_1.jsx)(icons_js_1.VolumeOffIcon, {}) : (0, jsx_runtime_1.jsx)(icons_js_1.VolumeOnIcon, {}) }));
62
+ }, [onBlur, onClick, volumeContainer]);
63
+ const muteButton = (0, react_1.useMemo)(() => {
64
+ return renderMuteButton
65
+ ? renderMuteButton({ muted: mediaMuted, volume: mediaVolume })
66
+ : renderDefaultMuteButton({ muted: mediaMuted, volume: mediaVolume });
67
+ }, [mediaMuted, mediaVolume, renderDefaultMuteButton, renderMuteButton]);
68
+ const volumeSlider = (0, react_1.useMemo)(() => {
69
+ return (focused || hover) && !mediaMuted && !remotion_1.Internals.isIosSafari()
70
+ ? (renderVolumeSlider !== null && renderVolumeSlider !== void 0 ? renderVolumeSlider : render_volume_slider_js_1.renderDefaultVolumeSlider)({
71
+ isVertical: displayVerticalVolumeSlider,
72
+ volume: mediaVolume,
73
+ onBlur: () => setFocused(false),
74
+ inputRef,
75
+ setVolume: setMediaVolume,
76
+ })
77
+ : null;
78
+ }, [
79
+ displayVerticalVolumeSlider,
80
+ focused,
81
+ hover,
82
+ mediaMuted,
83
+ mediaVolume,
84
+ renderVolumeSlider,
85
+ setMediaVolume,
86
+ ]);
87
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: parentDivRef, style: parentDivStyle, children: [muteButton, volumeSlider] }));
155
88
  };
156
89
  exports.MediaVolumeSlider = MediaVolumeSlider;
@@ -2,9 +2,11 @@ import type { ComponentType } from 'react';
2
2
  import React from 'react';
3
3
  import type { CompProps } from 'remotion';
4
4
  import type { AnyZodObject } from 'zod';
5
+ import type { RenderMuteButton } from './MediaVolumeSlider.js';
5
6
  import type { RenderFullscreenButton, RenderPlayPauseButton } from './PlayerControls.js';
6
7
  import type { PosterFillMode, RenderLoading, RenderPoster } from './PlayerUI.js';
7
8
  import type { PlayerRef } from './player-methods.js';
9
+ import type { RenderVolumeSlider } from './render-volume-slider.js';
8
10
  import type { PropsIfHasProps } from './utils/props-if-has-props.js';
9
11
  export type ErrorFallback = (info: {
10
12
  error: Error;
@@ -40,6 +42,8 @@ export type PlayerProps<Schema extends AnyZodObject, Props extends Record<string
40
42
  readonly initiallyShowControls?: number | boolean;
41
43
  readonly renderPlayPauseButton?: RenderPlayPauseButton;
42
44
  readonly renderFullscreenButton?: RenderFullscreenButton;
45
+ readonly renderMuteButton?: RenderMuteButton;
46
+ readonly renderVolumeSlider?: RenderVolumeSlider;
43
47
  readonly alwaysShowControls?: boolean;
44
48
  readonly schema?: Schema;
45
49
  readonly initiallyMuted?: boolean;
@@ -22,7 +22,7 @@ const componentOrNullIfLazy = (props) => {
22
22
  return null;
23
23
  };
24
24
  exports.componentOrNullIfLazy = componentOrNullIfLazy;
25
- const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps, inputProps, style, controls = false, loop = false, autoPlay = false, showVolumeControls = true, allowFullscreen = true, clickToPlay, doubleClickToFullscreen = false, spaceKeyToPlayOrPause = true, moveToBeginningWhenEnded = true, numberOfSharedAudioTags = 5, errorFallback = () => '⚠️', playbackRate = 1, renderLoading, className, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, showPosterWhenBuffering, initialFrame, renderPoster, inFrame, outFrame, initiallyShowControls, renderFullscreenButton, renderPlayPauseButton, alwaysShowControls = false, initiallyMuted = false, showPlaybackRateControl = false, posterFillMode = 'player-size', bufferStateDelayInMilliseconds, hideControlsWhenPointerDoesntMove = true, overflowVisible = false, ...componentProps }, ref) => {
25
+ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps, inputProps, style, controls = false, loop = false, autoPlay = false, showVolumeControls = true, allowFullscreen = true, clickToPlay, doubleClickToFullscreen = false, spaceKeyToPlayOrPause = true, moveToBeginningWhenEnded = true, numberOfSharedAudioTags = 5, errorFallback = () => '⚠️', playbackRate = 1, renderLoading, className, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, showPosterWhenBuffering, initialFrame, renderPoster, inFrame, outFrame, initiallyShowControls, renderFullscreenButton, renderPlayPauseButton, renderVolumeSlider, alwaysShowControls = false, initiallyMuted = false, showPlaybackRateControl = false, posterFillMode = 'player-size', bufferStateDelayInMilliseconds, hideControlsWhenPointerDoesntMove = true, overflowVisible = false, renderMuteButton, ...componentProps }, ref) => {
26
26
  if (typeof window !== 'undefined') {
27
27
  // eslint-disable-next-line react-hooks/rules-of-hooks
28
28
  (0, react_1.useLayoutEffect)(() => {
@@ -140,7 +140,7 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
140
140
  const actualInputProps = (0, react_1.useMemo)(() => inputProps !== null && inputProps !== void 0 ? inputProps : {}, [inputProps]);
141
141
  return ((0, jsx_runtime_1.jsx)(remotion_1.Internals.IsPlayerContextProvider, { children: (0, jsx_runtime_1.jsx)(SharedPlayerContext_js_1.SharedPlayerContexts, { timelineContext: timelineContextValue, component: component, compositionHeight: compositionHeight, compositionWidth: compositionWidth, durationInFrames: durationInFrames, fps: fps, numberOfSharedAudioTags: numberOfSharedAudioTags, initiallyMuted: initiallyMuted, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.Timeline.SetTimelineContext.Provider, { value: setTimelineContextValue, children: (0, jsx_runtime_1.jsx)(EmitterProvider_js_1.PlayerEmitterProvider, { currentPlaybackRate: currentPlaybackRate, children: (0, jsx_runtime_1.jsx)(PlayerUI_js_1.default, { ref: rootRef, posterFillMode: posterFillMode, renderLoading: renderLoading, autoPlay: Boolean(autoPlay), loop: Boolean(loop), controls: Boolean(controls), errorFallback: errorFallback, style: style, inputProps: actualInputProps, allowFullscreen: Boolean(allowFullscreen), moveToBeginningWhenEnded: Boolean(moveToBeginningWhenEnded), clickToPlay: typeof clickToPlay === 'boolean'
142
142
  ? clickToPlay
143
- : Boolean(controls), showVolumeControls: Boolean(showVolumeControls), doubleClickToFullscreen: Boolean(doubleClickToFullscreen), spaceKeyToPlayOrPause: Boolean(spaceKeyToPlayOrPause), playbackRate: currentPlaybackRate, className: className !== null && className !== void 0 ? className : undefined, showPosterWhenUnplayed: Boolean(showPosterWhenUnplayed), showPosterWhenEnded: Boolean(showPosterWhenEnded), showPosterWhenPaused: Boolean(showPosterWhenPaused), showPosterWhenBuffering: Boolean(showPosterWhenBuffering), renderPoster: renderPoster, inFrame: inFrame !== null && inFrame !== void 0 ? inFrame : null, outFrame: outFrame !== null && outFrame !== void 0 ? outFrame : null, initiallyShowControls: initiallyShowControls !== null && initiallyShowControls !== void 0 ? initiallyShowControls : true, renderFullscreen: renderFullscreenButton !== null && renderFullscreenButton !== void 0 ? renderFullscreenButton : null, renderPlayPauseButton: renderPlayPauseButton !== null && renderPlayPauseButton !== void 0 ? renderPlayPauseButton : null, alwaysShowControls: alwaysShowControls, showPlaybackRateControl: showPlaybackRateControl, bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds !== null && bufferStateDelayInMilliseconds !== void 0 ? bufferStateDelayInMilliseconds : 300, hideControlsWhenPointerDoesntMove: hideControlsWhenPointerDoesntMove, overflowVisible: overflowVisible }) }) }) }) }));
143
+ : Boolean(controls), showVolumeControls: Boolean(showVolumeControls), doubleClickToFullscreen: Boolean(doubleClickToFullscreen), spaceKeyToPlayOrPause: Boolean(spaceKeyToPlayOrPause), playbackRate: currentPlaybackRate, className: className !== null && className !== void 0 ? className : undefined, showPosterWhenUnplayed: Boolean(showPosterWhenUnplayed), showPosterWhenEnded: Boolean(showPosterWhenEnded), showPosterWhenPaused: Boolean(showPosterWhenPaused), showPosterWhenBuffering: Boolean(showPosterWhenBuffering), renderPoster: renderPoster, inFrame: inFrame !== null && inFrame !== void 0 ? inFrame : null, outFrame: outFrame !== null && outFrame !== void 0 ? outFrame : null, initiallyShowControls: initiallyShowControls !== null && initiallyShowControls !== void 0 ? initiallyShowControls : true, renderFullscreen: renderFullscreenButton !== null && renderFullscreenButton !== void 0 ? renderFullscreenButton : null, renderPlayPauseButton: renderPlayPauseButton !== null && renderPlayPauseButton !== void 0 ? renderPlayPauseButton : null, renderMuteButton: renderMuteButton !== null && renderMuteButton !== void 0 ? renderMuteButton : null, renderVolumeSlider: renderVolumeSlider !== null && renderVolumeSlider !== void 0 ? renderVolumeSlider : null, alwaysShowControls: alwaysShowControls, showPlaybackRateControl: showPlaybackRateControl, bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds !== null && bufferStateDelayInMilliseconds !== void 0 ? bufferStateDelayInMilliseconds : 300, hideControlsWhenPointerDoesntMove: hideControlsWhenPointerDoesntMove, overflowVisible: overflowVisible }) }) }) }) }));
144
144
  };
145
145
  const forward = react_1.forwardRef;
146
146
  /**
@@ -1,5 +1,7 @@
1
1
  import type { MouseEventHandler, ReactNode, SyntheticEvent } from 'react';
2
2
  import React from 'react';
3
+ import type { RenderMuteButton } from './MediaVolumeSlider.js';
4
+ import type { RenderVolumeSlider } from './render-volume-slider.js';
3
5
  import type { usePlayer } from './use-player.js';
4
6
  import type { Size } from './utils/use-element-size.js';
5
7
  export type RenderPlayPauseButton = (props: {
@@ -34,4 +36,6 @@ export declare const Controls: React.FC<{
34
36
  readonly hideControlsWhenPointerDoesntMove: boolean | number;
35
37
  readonly onPointerDown: ((ev: PointerEvent | SyntheticEvent) => void) | undefined;
36
38
  readonly onDoubleClick: MouseEventHandler<HTMLDivElement> | undefined;
39
+ readonly renderMuteButton: RenderMuteButton | null;
40
+ readonly renderVolumeSlider: RenderVolumeSlider | null;
37
41
  }>;
@@ -66,7 +66,7 @@ const flex1 = {
66
66
  flex: 1,
67
67
  };
68
68
  const fullscreen = {};
69
- const Controls = ({ durationInFrames, isFullscreen, fps, player, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, onSeekEnd, onSeekStart, inFrame, outFrame, initiallyShowControls, canvasSize, renderPlayPauseButton, renderFullscreenButton, alwaysShowControls, showPlaybackRateControl, containerRef, buffering, hideControlsWhenPointerDoesntMove, onPointerDown, onDoubleClick, }) => {
69
+ const Controls = ({ durationInFrames, isFullscreen, fps, player, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, onSeekEnd, onSeekStart, inFrame, outFrame, initiallyShowControls, canvasSize, renderPlayPauseButton, renderFullscreenButton, alwaysShowControls, showPlaybackRateControl, containerRef, buffering, hideControlsWhenPointerDoesntMove, onPointerDown, onDoubleClick, renderMuteButton, renderVolumeSlider, }) => {
70
70
  var _a, _b;
71
71
  const playButtonRef = (0, react_1.useRef)(null);
72
72
  const frame = remotion_1.Internals.Timeline.useTimelinePosition();
@@ -177,7 +177,7 @@ const Controls = ({ durationInFrames, isFullscreen, fps, player, showVolumeContr
177
177
  return ((0, jsx_runtime_1.jsxs)("div", { ref: ref, style: containerCss, onPointerDown: onPointerDownIfContainer, onDoubleClick: onDoubleClickIfContainer, children: [(0, jsx_runtime_1.jsxs)("div", { ref: flexRef, style: controlsRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: leftPartStyle, children: [(0, jsx_runtime_1.jsx)("button", { ref: playButtonRef, type: "button", style: PlaybackrateControl_js_1.playerButtonStyle, onClick: player.playing ? player.pause : player.play, "aria-label": player.playing ? 'Pause video' : 'Play video', title: player.playing ? 'Pause video' : 'Play video', children: renderPlayPauseButton === null ? ((0, jsx_runtime_1.jsx)(DefaultPlayPauseButton_js_1.DefaultPlayPauseButton, { buffering: buffering, playing: player.playing })) : ((_b = renderPlayPauseButton({
178
178
  playing: player.playing,
179
179
  isBuffering: buffering,
180
- })) !== null && _b !== void 0 ? _b : ((0, jsx_runtime_1.jsx)(DefaultPlayPauseButton_js_1.DefaultPlayPauseButton, { buffering: buffering, playing: player.playing }))) }), showVolumeControls ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: xSpacer }), (0, jsx_runtime_1.jsx)(MediaVolumeSlider_js_1.MediaVolumeSlider, { displayVerticalVolumeSlider: displayVerticalVolumeSlider })] })) : null, (0, jsx_runtime_1.jsx)("div", { style: xSpacer }), (0, jsx_runtime_1.jsxs)("div", { style: timeLabel, children: [(0, format_time_js_1.formatTime)(frame / fps), " / ", (0, format_time_js_1.formatTime)(durationInFrames / fps)] }), (0, jsx_runtime_1.jsx)("div", { style: xSpacer })] }), (0, jsx_runtime_1.jsx)("div", { style: flex1 }), playbackRates && canvasSize && ((0, jsx_runtime_1.jsx)(PlaybackrateControl_js_1.PlaybackrateControl, { canvasSize: canvasSize, playbackRates: playbackRates })), playbackRates && supportsFullscreen && allowFullscreen ? ((0, jsx_runtime_1.jsx)("div", { style: xSpacer })) : null, (0, jsx_runtime_1.jsx)("div", { style: fullscreen, children: supportsFullscreen && allowFullscreen ? ((0, jsx_runtime_1.jsx)("button", { type: "button", "aria-label": isFullscreen ? 'Exit fullscreen' : 'Enter Fullscreen', title: isFullscreen ? 'Exit fullscreen' : 'Enter Fullscreen', style: PlaybackrateControl_js_1.playerButtonStyle, onClick: isFullscreen
180
+ })) !== null && _b !== void 0 ? _b : ((0, jsx_runtime_1.jsx)(DefaultPlayPauseButton_js_1.DefaultPlayPauseButton, { buffering: buffering, playing: player.playing }))) }), showVolumeControls ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: xSpacer }), (0, jsx_runtime_1.jsx)(MediaVolumeSlider_js_1.MediaVolumeSlider, { renderMuteButton: renderMuteButton, renderVolumeSlider: renderVolumeSlider, displayVerticalVolumeSlider: displayVerticalVolumeSlider })] })) : null, (0, jsx_runtime_1.jsx)("div", { style: xSpacer }), (0, jsx_runtime_1.jsxs)("div", { style: timeLabel, children: [(0, format_time_js_1.formatTime)(frame / fps), " / ", (0, format_time_js_1.formatTime)(durationInFrames / fps)] }), (0, jsx_runtime_1.jsx)("div", { style: xSpacer })] }), (0, jsx_runtime_1.jsx)("div", { style: flex1 }), playbackRates && canvasSize && ((0, jsx_runtime_1.jsx)(PlaybackrateControl_js_1.PlaybackrateControl, { canvasSize: canvasSize, playbackRates: playbackRates })), playbackRates && supportsFullscreen && allowFullscreen ? ((0, jsx_runtime_1.jsx)("div", { style: xSpacer })) : null, (0, jsx_runtime_1.jsx)("div", { style: fullscreen, children: supportsFullscreen && allowFullscreen ? ((0, jsx_runtime_1.jsx)("button", { type: "button", "aria-label": isFullscreen ? 'Exit fullscreen' : 'Enter Fullscreen', title: isFullscreen ? 'Exit fullscreen' : 'Enter Fullscreen', style: PlaybackrateControl_js_1.playerButtonStyle, onClick: isFullscreen
181
181
  ? onExitFullscreenButtonClick
182
182
  : onFullscreenButtonClick, children: renderFullscreenButton === null ? ((0, jsx_runtime_1.jsx)(icons_js_1.FullscreenIcon, { isFullscreen: isFullscreen })) : (renderFullscreenButton({ isFullscreen })) })) : null })] }), (0, jsx_runtime_1.jsx)("div", { style: ySpacer }), (0, jsx_runtime_1.jsx)(PlayerSeekBar_js_1.PlayerSeekBar, { onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, durationInFrames: durationInFrames, inFrame: inFrame, outFrame: outFrame })] }));
183
183
  };
@@ -1,6 +1,8 @@
1
1
  import React from 'react';
2
+ import type { RenderMuteButton } from './MediaVolumeSlider.js';
2
3
  import type { RenderFullscreenButton, RenderPlayPauseButton } from './PlayerControls.js';
3
4
  import type { PlayerRef } from './player-methods.js';
5
+ import type { RenderVolumeSlider } from './render-volume-slider.js';
4
6
  export type ErrorFallback = (info: {
5
7
  error: Error;
6
8
  }) => React.ReactNode;
@@ -37,6 +39,8 @@ declare const _default: React.ForwardRefExoticComponent<{
37
39
  readonly initiallyShowControls: number | boolean;
38
40
  readonly renderPlayPauseButton: RenderPlayPauseButton | null;
39
41
  readonly renderFullscreen: RenderFullscreenButton | null;
42
+ readonly renderMuteButton: RenderMuteButton | null;
43
+ readonly renderVolumeSlider: RenderVolumeSlider | null;
40
44
  readonly alwaysShowControls: boolean;
41
45
  readonly showPlaybackRateControl: boolean | number[];
42
46
  readonly posterFillMode: PosterFillMode;
@@ -40,7 +40,7 @@ if (reactVersion === '0') {
40
40
  throw new Error(`Version ${reactVersion} of "react" is not supported by Remotion`);
41
41
  }
42
42
  const doesReactVersionSupportSuspense = parseInt(reactVersion, 10) >= 18;
43
- const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps, clickToPlay, showVolumeControls, doubleClickToFullscreen, spaceKeyToPlayOrPause, errorFallback, playbackRate, renderLoading, renderPoster, className, moveToBeginningWhenEnded, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, showPosterWhenBuffering, inFrame, outFrame, initiallyShowControls, renderFullscreen: renderFullscreenButton, renderPlayPauseButton, alwaysShowControls, showPlaybackRateControl, posterFillMode, bufferStateDelayInMilliseconds, hideControlsWhenPointerDoesntMove, overflowVisible, }, ref) => {
43
+ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps, clickToPlay, showVolumeControls, doubleClickToFullscreen, spaceKeyToPlayOrPause, errorFallback, playbackRate, renderLoading, renderPoster, className, moveToBeginningWhenEnded, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, showPosterWhenBuffering, inFrame, outFrame, initiallyShowControls, renderFullscreen: renderFullscreenButton, renderPlayPauseButton, renderMuteButton, renderVolumeSlider, alwaysShowControls, showPlaybackRateControl, posterFillMode, bufferStateDelayInMilliseconds, hideControlsWhenPointerDoesntMove, overflowVisible, }, ref) => {
44
44
  var _a, _b, _c;
45
45
  const config = remotion_1.Internals.useUnsafeVideoConfig();
46
46
  const video = remotion_1.Internals.useVideo();
@@ -404,7 +404,7 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
404
404
  ...outerWithoutScale,
405
405
  width: config.width,
406
406
  height: config.height,
407
- }, onPointerDown: clickToPlay ? handlePointerDown : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null] }) }), shouldShowPoster && posterFillMode === 'player-size' ? ((0, jsx_runtime_1.jsx)("div", { style: outer, onPointerDown: clickToPlay ? handlePointerDown : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null, controls ? ((0, jsx_runtime_1.jsx)(PlayerControls_js_1.Controls, { fps: config.fps, durationInFrames: config.durationInFrames, player: player, containerRef: container, onFullscreenButtonClick: onFullscreenButtonClick, isFullscreen: isFullscreen, allowFullscreen: allowFullscreen, showVolumeControls: showVolumeControls, onExitFullscreenButtonClick: onExitFullscreenButtonClick, spaceKeyToPlayOrPause: spaceKeyToPlayOrPause, onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, inFrame: inFrame, outFrame: outFrame, initiallyShowControls: initiallyShowControls, canvasSize: canvasSize, renderFullscreenButton: renderFullscreenButton, renderPlayPauseButton: renderPlayPauseButton, alwaysShowControls: alwaysShowControls, showPlaybackRateControl: showPlaybackRateControl, buffering: showBufferIndicator, hideControlsWhenPointerDoesntMove: hideControlsWhenPointerDoesntMove, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, onPointerDown: clickToPlay ? handlePointerDown : undefined })) : null] }));
407
+ }, onPointerDown: clickToPlay ? handlePointerDown : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null] }) }), shouldShowPoster && posterFillMode === 'player-size' ? ((0, jsx_runtime_1.jsx)("div", { style: outer, onPointerDown: clickToPlay ? handlePointerDown : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null, controls ? ((0, jsx_runtime_1.jsx)(PlayerControls_js_1.Controls, { fps: config.fps, durationInFrames: config.durationInFrames, player: player, containerRef: container, onFullscreenButtonClick: onFullscreenButtonClick, isFullscreen: isFullscreen, allowFullscreen: allowFullscreen, showVolumeControls: showVolumeControls, onExitFullscreenButtonClick: onExitFullscreenButtonClick, spaceKeyToPlayOrPause: spaceKeyToPlayOrPause, onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, inFrame: inFrame, outFrame: outFrame, initiallyShowControls: initiallyShowControls, canvasSize: canvasSize, renderFullscreenButton: renderFullscreenButton, renderPlayPauseButton: renderPlayPauseButton, alwaysShowControls: alwaysShowControls, showPlaybackRateControl: showPlaybackRateControl, buffering: showBufferIndicator, hideControlsWhenPointerDoesntMove: hideControlsWhenPointerDoesntMove, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, onPointerDown: clickToPlay ? handlePointerDown : undefined, renderMuteButton: renderMuteButton, renderVolumeSlider: renderVolumeSlider })) : null] }));
408
408
  if (is_node_js_1.IS_NODE && !doesReactVersionSupportSuspense) {
409
409
  return ((0, jsx_runtime_1.jsx)("div", { ref: container, style: outerStyle, className: className, children: content }));
410
410
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const react_1 = require("react");
4
+ if (typeof react_1.createContext !== 'function') {
5
+ const err = [
6
+ 'Remotion requires React.createContext, but it is "undefined".',
7
+ 'If you are in a React Server Component, turn it into a client component by adding "use client" at the top of the file.',
8
+ '',
9
+ 'Before:',
10
+ ' import {Player} from "@remotion/player";',
11
+ '',
12
+ 'After:',
13
+ ' "use client";',
14
+ ' import {Player} from "@remotion/player";',
15
+ ];
16
+ throw new Error(err.join('\n'));
17
+ }
@@ -1,11 +1,13 @@
1
1
  /// <reference types="react" />
2
2
  import type { CallbackListener, PlayerEventTypes } from './event-emitter.js';
3
3
  import { PlayerEmitter } from './event-emitter.js';
4
+ export type { RenderMuteButton } from './MediaVolumeSlider.js';
4
5
  export type { PlayerMethods, PlayerRef, ThumbnailMethods, ThumbnailRef, } from './player-methods.js';
5
6
  export { Player } from './Player.js';
6
7
  export type { PlayerProps, PlayerPropsWithoutZod } from './Player.js';
7
8
  export type { RenderFullscreenButton, RenderPlayPauseButton, } from './PlayerControls.js';
8
9
  export type { ErrorFallback, RenderLoading, RenderPoster } from './PlayerUI.js';
10
+ export type { RenderVolumeSlider } from './render-volume-slider.js';
9
11
  export { Thumbnail } from './Thumbnail.js';
10
12
  export type { ThumbnailProps, ThumbnailPropsWithoutZod } from './Thumbnail.js';
11
13
  export type { Size } from './utils/use-element-size.js';
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ type RenderVolumeSliderProps = {
3
+ readonly volume: number;
4
+ readonly isVertical: boolean;
5
+ readonly onBlur: () => void;
6
+ readonly inputRef: React.RefObject<HTMLInputElement>;
7
+ readonly setVolume: (u: number) => void;
8
+ };
9
+ export type RenderVolumeSlider = (props: RenderVolumeSliderProps) => React.ReactNode;
10
+ export declare const renderDefaultVolumeSlider: RenderVolumeSlider;
11
+ export {};
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.renderDefaultVolumeSlider = void 0;
27
+ const jsx_runtime_1 = require("react/jsx-runtime");
28
+ const react_1 = __importStar(require("react"));
29
+ const remotion_1 = require("remotion");
30
+ const MediaVolumeSlider_1 = require("./MediaVolumeSlider");
31
+ const icons_1 = require("./icons");
32
+ const KNOB_SIZE = 12;
33
+ const BAR_HEIGHT = 5;
34
+ const DefaultVolumeSlider = ({ volume, isVertical, onBlur, inputRef, setVolume, }) => {
35
+ const sliderContainer = (0, react_1.useMemo)(() => {
36
+ const paddingLeft = 5;
37
+ const common = {
38
+ paddingLeft,
39
+ height: icons_1.ICON_SIZE,
40
+ width: MediaVolumeSlider_1.VOLUME_SLIDER_WIDTH,
41
+ display: 'inline-flex',
42
+ alignItems: 'center',
43
+ };
44
+ if (isVertical) {
45
+ return {
46
+ ...common,
47
+ position: 'absolute',
48
+ transform: `rotate(-90deg) translateX(${MediaVolumeSlider_1.VOLUME_SLIDER_WIDTH / 2 + icons_1.ICON_SIZE / 2}px)`,
49
+ };
50
+ }
51
+ return {
52
+ ...common,
53
+ };
54
+ }, [isVertical]);
55
+ // Need to import it from React to fix React 17 ESM support.
56
+ const randomId =
57
+ // eslint-disable-next-line react-hooks/rules-of-hooks
58
+ typeof react_1.default.useId === 'undefined' ? 'volume-slider' : react_1.default.useId();
59
+ const [randomClass] = (0, react_1.useState)(() => `__remotion-volume-slider-${(0, remotion_1.random)(randomId)}`.replace('.', ''));
60
+ const onVolumeChange = (0, react_1.useCallback)((e) => {
61
+ setVolume(parseFloat(e.target.value));
62
+ }, [setVolume]);
63
+ const inputStyle = (0, react_1.useMemo)(() => {
64
+ const commonStyle = {
65
+ WebkitAppearance: 'none',
66
+ backgroundColor: 'rgba(255, 255, 255, 0.5)',
67
+ borderRadius: BAR_HEIGHT / 2,
68
+ cursor: 'pointer',
69
+ height: BAR_HEIGHT,
70
+ width: MediaVolumeSlider_1.VOLUME_SLIDER_WIDTH,
71
+ backgroundImage: `linear-gradient(
72
+ to right,
73
+ white ${volume * 100}%, rgba(255, 255, 255, 0) ${volume * 100}%
74
+ )`,
75
+ };
76
+ if (isVertical) {
77
+ return {
78
+ ...commonStyle,
79
+ bottom: icons_1.ICON_SIZE + MediaVolumeSlider_1.VOLUME_SLIDER_WIDTH / 2,
80
+ };
81
+ }
82
+ return commonStyle;
83
+ }, [isVertical, volume]);
84
+ const sliderStyle = `
85
+ .${randomClass}::-webkit-slider-thumb {
86
+ -webkit-appearance: none;
87
+ background-color: white;
88
+ border-radius: ${KNOB_SIZE / 2}px;
89
+ box-shadow: 0 0 2px black;
90
+ height: ${KNOB_SIZE}px;
91
+ width: ${KNOB_SIZE}px;
92
+ }
93
+
94
+ .${randomClass}::-moz-range-thumb {
95
+ -webkit-appearance: none;
96
+ background-color: white;
97
+ border-radius: ${KNOB_SIZE / 2}px;
98
+ box-shadow: 0 0 2px black;
99
+ height: ${KNOB_SIZE}px;
100
+ width: ${KNOB_SIZE}px;
101
+ }
102
+ `;
103
+ return ((0, jsx_runtime_1.jsxs)("div", { style: sliderContainer, children: [(0, jsx_runtime_1.jsx)("style", {
104
+ // eslint-disable-next-line react/no-danger
105
+ dangerouslySetInnerHTML: {
106
+ __html: sliderStyle,
107
+ } }), (0, jsx_runtime_1.jsx)("input", { ref: inputRef, "aria-label": "Change volume", className: randomClass, max: 1, min: 0, onBlur: onBlur, onChange: onVolumeChange, step: 0.01, type: "range", value: volume, style: inputStyle })] }));
108
+ };
109
+ const renderDefaultVolumeSlider = (props) => {
110
+ return (0, jsx_runtime_1.jsx)(DefaultVolumeSlider, { ...props });
111
+ };
112
+ exports.renderDefaultVolumeSlider = renderDefaultVolumeSlider;