@remotion/player 4.0.0-alpha10 → 4.0.0-alpha11
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.
- package/dist/cjs/MediaVolumeSlider.js +0 -1
- package/dist/cjs/PlaybackrateControl.d.ts +5 -0
- package/dist/cjs/PlaybackrateControl.js +136 -0
- package/dist/cjs/Player.d.ts +1 -0
- package/dist/cjs/Player.js +13 -9
- package/dist/cjs/PlayerControls.d.ts +1 -0
- package/dist/cjs/PlayerControls.js +21 -3
- package/dist/cjs/PlayerUI.d.ts +1 -0
- package/dist/cjs/PlayerUI.js +2 -2
- package/dist/cjs/icons.d.ts +3 -0
- package/dist/cjs/icons.js +5 -1
- package/dist/cjs/utils/use-component-visible.d.ts +6 -0
- package/dist/cjs/utils/use-component-visible.js +21 -0
- package/dist/esm/PlaybackrateControl.d.ts +5 -0
- package/dist/esm/Player.d.ts +1 -0
- package/dist/esm/PlayerControls.d.ts +1 -0
- package/dist/esm/PlayerUI.d.ts +1 -0
- package/dist/esm/icons.d.ts +3 -0
- package/dist/esm/index.mjs +180 -15
- package/dist/esm/utils/use-component-visible.d.ts +5 -0
- package/dist/tsconfig-esm.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PlaybackrateControl = exports.Checkmark = void 0;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const remotion_1 = require("remotion");
|
|
10
|
+
const icons_js_1 = require("./icons.js");
|
|
11
|
+
const use_component_visible_js_1 = __importDefault(require("./utils/use-component-visible.js"));
|
|
12
|
+
const playbackPopup = {
|
|
13
|
+
position: 'absolute',
|
|
14
|
+
right: 0,
|
|
15
|
+
width: 125,
|
|
16
|
+
bottom: 35,
|
|
17
|
+
background: '#fff',
|
|
18
|
+
borderRadius: 4,
|
|
19
|
+
overflow: 'hidden',
|
|
20
|
+
color: 'black',
|
|
21
|
+
textAlign: 'left',
|
|
22
|
+
};
|
|
23
|
+
const rateDiv = {
|
|
24
|
+
height: 30,
|
|
25
|
+
paddingRight: 15,
|
|
26
|
+
paddingLeft: 12,
|
|
27
|
+
display: 'flex',
|
|
28
|
+
flexDirection: 'row',
|
|
29
|
+
alignItems: 'center',
|
|
30
|
+
};
|
|
31
|
+
const checkmarkContainer = {
|
|
32
|
+
width: 22,
|
|
33
|
+
display: 'flex',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
};
|
|
36
|
+
const checkmarkStyle = {
|
|
37
|
+
width: 14,
|
|
38
|
+
height: 14,
|
|
39
|
+
color: 'black',
|
|
40
|
+
};
|
|
41
|
+
const Checkmark = () => ((0, jsx_runtime_1.jsx)("svg", { viewBox: "0 0 512 512", style: checkmarkStyle, children: (0, jsx_runtime_1.jsx)("path", { fill: "currentColor", d: "M435.848 83.466L172.804 346.51l-96.652-96.652c-4.686-4.686-12.284-4.686-16.971 0l-28.284 28.284c-4.686 4.686-4.686 12.284 0 16.971l133.421 133.421c4.686 4.686 12.284 4.686 16.971 0l299.813-299.813c4.686-4.686 4.686-12.284 0-16.971l-28.284-28.284c-4.686-4.686-12.284-4.686-16.97 0z" }) }));
|
|
42
|
+
exports.Checkmark = Checkmark;
|
|
43
|
+
const PlaybackPopup = ({ setIsComponentVisible, playbackRates }) => {
|
|
44
|
+
const { setPlaybackRate, playbackRate } = (0, react_1.useContext)(remotion_1.Internals.Timeline.TimelineContext);
|
|
45
|
+
const [keyboardSelectedRate, setKeyboardSelectedRate] = (0, react_1.useState)(playbackRate);
|
|
46
|
+
(0, react_1.useEffect)(() => {
|
|
47
|
+
const listener = (e) => {
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
if (e.key === 'ArrowUp') {
|
|
50
|
+
const currentIndex = playbackRates.findIndex((rate) => rate === keyboardSelectedRate);
|
|
51
|
+
if (currentIndex === 0) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (currentIndex === -1) {
|
|
55
|
+
setKeyboardSelectedRate(playbackRates[0]);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
setKeyboardSelectedRate(playbackRates[currentIndex - 1]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else if (e.key === 'ArrowDown') {
|
|
62
|
+
const currentIndex = playbackRates.findIndex((rate) => rate === keyboardSelectedRate);
|
|
63
|
+
if (currentIndex === playbackRates.length - 1) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (currentIndex === -1) {
|
|
67
|
+
setKeyboardSelectedRate(playbackRates[playbackRates.length - 1]);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
setKeyboardSelectedRate(playbackRates[currentIndex + 1]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else if (e.key === 'Enter') {
|
|
74
|
+
setPlaybackRate(keyboardSelectedRate);
|
|
75
|
+
setIsComponentVisible(false);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
window.addEventListener('keydown', listener);
|
|
79
|
+
return () => {
|
|
80
|
+
window.removeEventListener('keydown', listener);
|
|
81
|
+
};
|
|
82
|
+
}, [
|
|
83
|
+
playbackRates,
|
|
84
|
+
keyboardSelectedRate,
|
|
85
|
+
setPlaybackRate,
|
|
86
|
+
setIsComponentVisible,
|
|
87
|
+
]);
|
|
88
|
+
const onSelect = (0, react_1.useCallback)((rate) => {
|
|
89
|
+
setPlaybackRate(rate);
|
|
90
|
+
setIsComponentVisible(false);
|
|
91
|
+
}, [setIsComponentVisible, setPlaybackRate]);
|
|
92
|
+
return ((0, jsx_runtime_1.jsx)("div", { style: playbackPopup, children: playbackRates.map((rate) => {
|
|
93
|
+
return ((0, jsx_runtime_1.jsx)(PlaybackrateOption, { selectedRate: playbackRate, onSelect: onSelect, rate: rate, keyboardSelectedRate: keyboardSelectedRate }, rate));
|
|
94
|
+
}) }));
|
|
95
|
+
};
|
|
96
|
+
const PlaybackrateOption = ({ rate, onSelect, selectedRate, keyboardSelectedRate }) => {
|
|
97
|
+
const onClick = (0, react_1.useCallback)((e) => {
|
|
98
|
+
e.stopPropagation();
|
|
99
|
+
e.preventDefault();
|
|
100
|
+
onSelect(rate);
|
|
101
|
+
}, [onSelect, rate]);
|
|
102
|
+
const [hovered, setHovered] = (0, react_1.useState)(false);
|
|
103
|
+
const onMouseEnter = (0, react_1.useCallback)(() => {
|
|
104
|
+
setHovered(true);
|
|
105
|
+
}, []);
|
|
106
|
+
const onMouseLeave = (0, react_1.useCallback)(() => {
|
|
107
|
+
setHovered(false);
|
|
108
|
+
}, []);
|
|
109
|
+
const actualStyle = (0, react_1.useMemo)(() => {
|
|
110
|
+
return {
|
|
111
|
+
...rateDiv,
|
|
112
|
+
backgroundColor: hovered || keyboardSelectedRate === rate ? '#eee' : 'transparent',
|
|
113
|
+
};
|
|
114
|
+
}, [hovered, keyboardSelectedRate, rate]);
|
|
115
|
+
return ((0, jsx_runtime_1.jsxs)("div", { onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, tabIndex: 0, style: actualStyle, onClick: onClick, children: [(0, jsx_runtime_1.jsx)("div", { style: checkmarkContainer, children: rate === selectedRate ? (0, jsx_runtime_1.jsx)(exports.Checkmark, {}) : null }), rate.toFixed(1), "x"] }, rate));
|
|
116
|
+
};
|
|
117
|
+
const playbackButton = {
|
|
118
|
+
position: 'relative',
|
|
119
|
+
display: 'inline-flex',
|
|
120
|
+
alignItems: 'center',
|
|
121
|
+
padding: '6px 0 6px 0',
|
|
122
|
+
border: 'none',
|
|
123
|
+
background: 'none',
|
|
124
|
+
height: 36,
|
|
125
|
+
cursor: 'pointer',
|
|
126
|
+
};
|
|
127
|
+
const PlaybackrateControl = ({ playbackRates }) => {
|
|
128
|
+
const { ref, isComponentVisible, setIsComponentVisible } = (0, use_component_visible_js_1.default)(false);
|
|
129
|
+
const onClick = (0, react_1.useCallback)((e) => {
|
|
130
|
+
e.stopPropagation();
|
|
131
|
+
e.preventDefault();
|
|
132
|
+
setIsComponentVisible(!isComponentVisible);
|
|
133
|
+
}, [isComponentVisible, setIsComponentVisible]);
|
|
134
|
+
return ((0, jsx_runtime_1.jsx)("div", { ref: ref, children: (0, jsx_runtime_1.jsxs)("button", { type: "button", "aria-label": "Change playback rate", style: playbackButton, onClick: onClick, children: [(0, jsx_runtime_1.jsx)(icons_js_1.SettingsIcon, { iconSize: 22 }), isComponentVisible && ((0, jsx_runtime_1.jsx)(PlaybackPopup, { playbackRates: playbackRates, setIsComponentVisible: setIsComponentVisible }))] }) }));
|
|
135
|
+
};
|
|
136
|
+
exports.PlaybackrateControl = PlaybackrateControl;
|
package/dist/cjs/Player.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export declare type PlayerProps<Schema extends AnyZodObject, Props> = {
|
|
|
42
42
|
alwaysShowControls?: boolean;
|
|
43
43
|
schema?: Schema;
|
|
44
44
|
initiallyMuted?: boolean;
|
|
45
|
+
showPlaybackRateControl?: boolean | number[];
|
|
45
46
|
} & CompProps<Props> & PropsIfHasProps<Schema, Props>;
|
|
46
47
|
export declare const componentOrNullIfLazy: <Props>(props: CompProps<Props>) => ComponentType<Props> | null;
|
|
47
48
|
/**
|
package/dist/cjs/Player.js
CHANGED
|
@@ -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, initialFrame, renderPoster, inFrame, outFrame, initiallyShowControls, renderFullscreenButton, renderPlayPauseButton, alwaysShowControls = false, initiallyMuted = 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, initialFrame, renderPoster, inFrame, outFrame, initiallyShowControls, renderFullscreenButton, renderPlayPauseButton, alwaysShowControls = false, initiallyMuted = false, showPlaybackRateControl = false, ...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)(() => {
|
|
@@ -50,6 +50,7 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
50
50
|
const rootRef = (0, react_1.useRef)(null);
|
|
51
51
|
const audioAndVideoTags = (0, react_1.useRef)([]);
|
|
52
52
|
const imperativePlaying = (0, react_1.useRef)(false);
|
|
53
|
+
const [currentPlaybackRate, setCurrentPlaybackRate] = (0, react_1.useState)(playbackRate);
|
|
53
54
|
if (typeof compositionHeight !== 'number') {
|
|
54
55
|
throw new TypeError(`'compositionHeight' must be a number but got '${typeof compositionHeight}' instead`);
|
|
55
56
|
}
|
|
@@ -105,10 +106,13 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
105
106
|
numberOfSharedAudioTags < 0) {
|
|
106
107
|
throw new TypeError(`'numberOfSharedAudioTags' must be an integer but got '${numberOfSharedAudioTags}' instead`);
|
|
107
108
|
}
|
|
108
|
-
(0, validate_playbackrate_js_1.validatePlaybackRate)(
|
|
109
|
+
(0, validate_playbackrate_js_1.validatePlaybackRate)(currentPlaybackRate);
|
|
109
110
|
(0, react_1.useEffect)(() => {
|
|
110
|
-
emitter.dispatchRateChange(
|
|
111
|
-
}, [emitter,
|
|
111
|
+
emitter.dispatchRateChange(currentPlaybackRate);
|
|
112
|
+
}, [emitter, currentPlaybackRate]);
|
|
113
|
+
(0, react_1.useEffect)(() => {
|
|
114
|
+
setCurrentPlaybackRate(playbackRate);
|
|
115
|
+
}, [playbackRate]);
|
|
112
116
|
(0, react_1.useImperativeHandle)(ref, () => rootRef.current, []);
|
|
113
117
|
const timelineContextValue = (0, react_1.useMemo)(() => {
|
|
114
118
|
return {
|
|
@@ -116,14 +120,14 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
116
120
|
playing,
|
|
117
121
|
rootId,
|
|
118
122
|
shouldRegisterSequences: false,
|
|
119
|
-
playbackRate,
|
|
123
|
+
playbackRate: currentPlaybackRate,
|
|
120
124
|
imperativePlaying,
|
|
121
|
-
setPlaybackRate: () => {
|
|
122
|
-
|
|
125
|
+
setPlaybackRate: (rate) => {
|
|
126
|
+
setCurrentPlaybackRate(rate);
|
|
123
127
|
},
|
|
124
128
|
audioAndVideoTags,
|
|
125
129
|
};
|
|
126
|
-
}, [frame,
|
|
130
|
+
}, [frame, currentPlaybackRate, playing, rootId]);
|
|
127
131
|
const setTimelineContextValue = (0, react_1.useMemo)(() => {
|
|
128
132
|
return {
|
|
129
133
|
setFrame,
|
|
@@ -143,7 +147,7 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
143
147
|
const actualInputProps = (0, react_1.useMemo)(() => inputProps !== null && inputProps !== void 0 ? inputProps : {}, [inputProps]);
|
|
144
148
|
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, inputProps: actualInputProps, numberOfSharedAudioTags: numberOfSharedAudioTags, initiallyMuted: initiallyMuted, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.Timeline.SetTimelineContext.Provider, { value: setTimelineContextValue, children: (0, jsx_runtime_1.jsx)(emitter_context_js_1.PlayerEventEmitterContext.Provider, { value: emitter, children: (0, jsx_runtime_1.jsx)(PlayerUI_js_1.default, { ref: rootRef, renderLoading: renderLoading, autoPlay: Boolean(autoPlay), loop: Boolean(loop), controls: Boolean(controls), errorFallback: errorFallback, style: style, inputProps: passedInputProps, allowFullscreen: Boolean(allowFullscreen), moveToBeginningWhenEnded: Boolean(moveToBeginningWhenEnded), clickToPlay: typeof clickToPlay === 'boolean'
|
|
145
149
|
? clickToPlay
|
|
146
|
-
: Boolean(controls), showVolumeControls: Boolean(showVolumeControls), doubleClickToFullscreen: Boolean(doubleClickToFullscreen), spaceKeyToPlayOrPause: Boolean(spaceKeyToPlayOrPause), playbackRate:
|
|
150
|
+
: 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), 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 }) }) }) }) }));
|
|
147
151
|
};
|
|
148
152
|
const forward = react_1.forwardRef;
|
|
149
153
|
/**
|
|
@@ -7,6 +7,7 @@ const remotion_1 = require("remotion");
|
|
|
7
7
|
const format_time_js_1 = require("./format-time.js");
|
|
8
8
|
const icons_js_1 = require("./icons.js");
|
|
9
9
|
const MediaVolumeSlider_js_1 = require("./MediaVolumeSlider.js");
|
|
10
|
+
const PlaybackrateControl_js_1 = require("./PlaybackrateControl.js");
|
|
10
11
|
const PlayerSeekBar_js_1 = require("./PlayerSeekBar.js");
|
|
11
12
|
const use_video_controls_resize_js_1 = require("./use-video-controls-resize.js");
|
|
12
13
|
const gradientSteps = [
|
|
@@ -66,7 +67,7 @@ const leftPartStyle = {
|
|
|
66
67
|
alignItems: 'center',
|
|
67
68
|
};
|
|
68
69
|
const xSpacer = {
|
|
69
|
-
width:
|
|
70
|
+
width: 12,
|
|
70
71
|
};
|
|
71
72
|
const ySpacer = {
|
|
72
73
|
height: 8,
|
|
@@ -76,7 +77,7 @@ const flex1 = {
|
|
|
76
77
|
};
|
|
77
78
|
const fullscreen = {};
|
|
78
79
|
const PlayPauseButton = ({ playing }) => playing ? (0, jsx_runtime_1.jsx)(icons_js_1.PauseIcon, {}) : (0, jsx_runtime_1.jsx)(icons_js_1.PlayIcon, {});
|
|
79
|
-
const Controls = ({ durationInFrames, hovered, isFullscreen, fps, player, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, onSeekEnd, onSeekStart, inFrame, outFrame, initiallyShowControls, playerWidth, renderPlayPauseButton, renderFullscreenButton, alwaysShowControls, }) => {
|
|
80
|
+
const Controls = ({ durationInFrames, hovered, isFullscreen, fps, player, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, onSeekEnd, onSeekStart, inFrame, outFrame, initiallyShowControls, playerWidth, renderPlayPauseButton, renderFullscreenButton, alwaysShowControls, showPlaybackRateControl, }) => {
|
|
80
81
|
const playButtonRef = (0, react_1.useRef)(null);
|
|
81
82
|
const frame = remotion_1.Internals.Timeline.useTimelinePosition();
|
|
82
83
|
const [supportsFullscreen, setSupportsFullscreen] = (0, react_1.useState)(false);
|
|
@@ -146,7 +147,24 @@ const Controls = ({ durationInFrames, hovered, isFullscreen, fps, player, showVo
|
|
|
146
147
|
textOverflow: 'ellipsis',
|
|
147
148
|
};
|
|
148
149
|
}, [maxTimeLabelWidth]);
|
|
149
|
-
|
|
150
|
+
const playbackRates = (0, react_1.useMemo)(() => {
|
|
151
|
+
if (showPlaybackRateControl === true) {
|
|
152
|
+
return [0.5, 0.8, 1, 1.2, 1.5, 1.8, 2, 2.5, 3];
|
|
153
|
+
}
|
|
154
|
+
if (Array.isArray(showPlaybackRateControl)) {
|
|
155
|
+
for (const rate of showPlaybackRateControl) {
|
|
156
|
+
if (typeof rate !== 'number') {
|
|
157
|
+
throw new Error('Every item in showPlaybackRateControl must be a number');
|
|
158
|
+
}
|
|
159
|
+
if (rate <= 0) {
|
|
160
|
+
throw new Error('Every item in showPlaybackRateControl must be positive');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return showPlaybackRateControl;
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
}, [showPlaybackRateControl]);
|
|
167
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: containerCss, children: [(0, jsx_runtime_1.jsxs)("div", { style: controlsRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: leftPartStyle, children: [(0, jsx_runtime_1.jsx)("button", { ref: playButtonRef, type: "button", style: buttonStyle, 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)(PlayPauseButton, { playing: player.playing })) : (renderPlayPauseButton({ 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 && (0, jsx_runtime_1.jsx)(PlaybackrateControl_js_1.PlaybackrateControl, { 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: buttonStyle, onClick: isFullscreen
|
|
150
168
|
? onExitFullscreenButtonClick
|
|
151
169
|
: 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 })] }));
|
|
152
170
|
};
|
package/dist/cjs/PlayerUI.d.ts
CHANGED
|
@@ -35,5 +35,6 @@ declare const _default: React.ForwardRefExoticComponent<{
|
|
|
35
35
|
renderPlayPauseButton: RenderPlayPauseButton | null;
|
|
36
36
|
renderFullscreen: RenderFullscreenButton | null;
|
|
37
37
|
alwaysShowControls: boolean;
|
|
38
|
+
showPlaybackRateControl: boolean | number[];
|
|
38
39
|
} & React.RefAttributes<PlayerRef>>;
|
|
39
40
|
export default _default;
|
package/dist/cjs/PlayerUI.js
CHANGED
|
@@ -41,7 +41,7 @@ if (reactVersion === '0') {
|
|
|
41
41
|
throw new Error(`Version ${reactVersion} of "react" is not supported by Remotion`);
|
|
42
42
|
}
|
|
43
43
|
const doesReactVersionSupportSuspense = parseInt(reactVersion, 10) >= 18;
|
|
44
|
-
const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps, clickToPlay, showVolumeControls, doubleClickToFullscreen, spaceKeyToPlayOrPause, errorFallback, playbackRate, renderLoading, renderPoster, className, moveToBeginningWhenEnded, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, inFrame, outFrame, initiallyShowControls, renderFullscreen: renderFullscreenButton, renderPlayPauseButton, alwaysShowControls, }, ref) => {
|
|
44
|
+
const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps, clickToPlay, showVolumeControls, doubleClickToFullscreen, spaceKeyToPlayOrPause, errorFallback, playbackRate, renderLoading, renderPoster, className, moveToBeginningWhenEnded, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, inFrame, outFrame, initiallyShowControls, renderFullscreen: renderFullscreenButton, renderPlayPauseButton, alwaysShowControls, showPlaybackRateControl, }, ref) => {
|
|
45
45
|
var _a, _b, _c, _d;
|
|
46
46
|
const config = remotion_1.Internals.useUnsafeVideoConfig();
|
|
47
47
|
const video = remotion_1.Internals.useVideo();
|
|
@@ -317,7 +317,7 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
317
317
|
showPosterWhenEnded && player.isLastFrame && !player.isPlaying(),
|
|
318
318
|
showPosterWhenUnplayed && !player.hasPlayed && !player.isPlaying(),
|
|
319
319
|
].some(Boolean);
|
|
320
|
-
const content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: outer, onClick: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: (0, jsx_runtime_1.jsx)("div", { style: containerStyle, className: player_css_classname_js_1.PLAYER_CSS_CLASSNAME, children: VideoComponent ? ((0, jsx_runtime_1.jsx)(error_boundary_js_1.ErrorBoundary, { onError: onError, errorFallback: errorFallback, children: (0, jsx_runtime_1.jsx)(VideoComponent, { ...((_c = video === null || video === void 0 ? void 0 : video.defaultProps) !== null && _c !== void 0 ? _c : {}), ...(inputProps !== null && inputProps !== void 0 ? inputProps : {}) }) })) : null }) }), shouldShowPoster ? ((0, jsx_runtime_1.jsx)("div", { style: outer, onClick: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null, controls ? ((0, jsx_runtime_1.jsx)(PlayerControls_js_1.Controls, { fps: config.fps, durationInFrames: config.durationInFrames, hovered: hovered, player: player, onFullscreenButtonClick: onFullscreenButtonClick, isFullscreen: isFullscreen, allowFullscreen: allowFullscreen, showVolumeControls: showVolumeControls, onExitFullscreenButtonClick: onExitFullscreenButtonClick, spaceKeyToPlayOrPause: spaceKeyToPlayOrPause, onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, inFrame: inFrame, outFrame: outFrame, initiallyShowControls: initiallyShowControls, playerWidth: (_d = canvasSize === null || canvasSize === void 0 ? void 0 : canvasSize.width) !== null && _d !== void 0 ? _d : 0, renderFullscreenButton: renderFullscreenButton, renderPlayPauseButton: renderPlayPauseButton, alwaysShowControls: alwaysShowControls })) : null] }));
|
|
320
|
+
const content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: outer, onClick: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: (0, jsx_runtime_1.jsx)("div", { style: containerStyle, className: player_css_classname_js_1.PLAYER_CSS_CLASSNAME, children: VideoComponent ? ((0, jsx_runtime_1.jsx)(error_boundary_js_1.ErrorBoundary, { onError: onError, errorFallback: errorFallback, children: (0, jsx_runtime_1.jsx)(VideoComponent, { ...((_c = video === null || video === void 0 ? void 0 : video.defaultProps) !== null && _c !== void 0 ? _c : {}), ...(inputProps !== null && inputProps !== void 0 ? inputProps : {}) }) })) : null }) }), shouldShowPoster ? ((0, jsx_runtime_1.jsx)("div", { style: outer, onClick: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null, controls ? ((0, jsx_runtime_1.jsx)(PlayerControls_js_1.Controls, { fps: config.fps, durationInFrames: config.durationInFrames, hovered: hovered, player: player, onFullscreenButtonClick: onFullscreenButtonClick, isFullscreen: isFullscreen, allowFullscreen: allowFullscreen, showVolumeControls: showVolumeControls, onExitFullscreenButtonClick: onExitFullscreenButtonClick, spaceKeyToPlayOrPause: spaceKeyToPlayOrPause, onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, inFrame: inFrame, outFrame: outFrame, initiallyShowControls: initiallyShowControls, playerWidth: (_d = canvasSize === null || canvasSize === void 0 ? void 0 : canvasSize.width) !== null && _d !== void 0 ? _d : 0, renderFullscreenButton: renderFullscreenButton, renderPlayPauseButton: renderPlayPauseButton, alwaysShowControls: alwaysShowControls, showPlaybackRateControl: showPlaybackRateControl })) : null] }));
|
|
321
321
|
if (is_node_js_1.IS_NODE && !doesReactVersionSupportSuspense) {
|
|
322
322
|
return ((0, jsx_runtime_1.jsx)("div", { ref: container, style: outerStyle, className: className, children: content }));
|
|
323
323
|
}
|
package/dist/cjs/icons.d.ts
CHANGED
package/dist/cjs/icons.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VolumeOnIcon = exports.VolumeOffIcon = exports.FullscreenIcon = exports.PauseIcon = exports.PlayIcon = exports.fullscreenIconSize = exports.ICON_SIZE = void 0;
|
|
3
|
+
exports.SettingsIcon = exports.VolumeOnIcon = exports.VolumeOffIcon = exports.FullscreenIcon = exports.PauseIcon = exports.PlayIcon = exports.fullscreenIconSize = exports.ICON_SIZE = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
exports.ICON_SIZE = 25;
|
|
6
6
|
exports.fullscreenIconSize = 16;
|
|
@@ -48,3 +48,7 @@ const VolumeOnIcon = () => {
|
|
|
48
48
|
return ((0, jsx_runtime_1.jsx)("svg", { width: exports.ICON_SIZE, height: exports.ICON_SIZE, viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { d: "M3 10v4c0 .55.45 1 1 1h3l3.29 3.29c.63.63 1.71.18 1.71-.71V6.41c0-.89-1.08-1.34-1.71-.71L7 9H4c-.55 0-1 .45-1 1zm13.5 2A4.5 4.5 0 0014 7.97v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 4.45v.2c0 .38.25.71.6.85C17.18 6.53 19 9.06 19 12s-1.82 5.47-4.4 6.5c-.36.14-.6.47-.6.85v.2c0 .63.63 1.07 1.21.85C18.6 19.11 21 15.84 21 12s-2.4-7.11-5.79-8.4c-.58-.23-1.21.22-1.21.85z", fill: "#fff" }) }));
|
|
49
49
|
};
|
|
50
50
|
exports.VolumeOnIcon = VolumeOnIcon;
|
|
51
|
+
const SettingsIcon = ({ iconSize }) => {
|
|
52
|
+
return ((0, jsx_runtime_1.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", height: iconSize !== null && iconSize !== void 0 ? iconSize : exports.ICON_SIZE, viewBox: "0 0 512 512", style: { fill: '#fff' }, children: (0, jsx_runtime_1.jsx)("path", { d: "M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z" }) }));
|
|
53
|
+
};
|
|
54
|
+
exports.SettingsIcon = SettingsIcon;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export default function useComponentVisible(initialIsVisible: boolean): {
|
|
3
|
+
ref: import("react").RefObject<HTMLDivElement>;
|
|
4
|
+
isComponentVisible: boolean;
|
|
5
|
+
setIsComponentVisible: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
6
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const react_1 = require("react");
|
|
4
|
+
// hook to hide a popup/modal when clicked outside
|
|
5
|
+
function useComponentVisible(initialIsVisible) {
|
|
6
|
+
const [isComponentVisible, setIsComponentVisible] = (0, react_1.useState)(initialIsVisible);
|
|
7
|
+
const ref = (0, react_1.useRef)(null);
|
|
8
|
+
(0, react_1.useEffect)(() => {
|
|
9
|
+
const handleClickOutside = (event) => {
|
|
10
|
+
if (ref.current && !ref.current.contains(event.target)) {
|
|
11
|
+
setIsComponentVisible(false);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
document.addEventListener('pointerup', handleClickOutside, true);
|
|
15
|
+
return () => {
|
|
16
|
+
document.removeEventListener('pointerup', handleClickOutside, true);
|
|
17
|
+
};
|
|
18
|
+
}, []);
|
|
19
|
+
return { ref, isComponentVisible, setIsComponentVisible };
|
|
20
|
+
}
|
|
21
|
+
exports.default = useComponentVisible;
|
package/dist/esm/Player.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export declare type PlayerProps<Schema extends AnyZodObject, Props> = {
|
|
|
42
42
|
alwaysShowControls?: boolean;
|
|
43
43
|
schema?: Schema;
|
|
44
44
|
initiallyMuted?: boolean;
|
|
45
|
+
showPlaybackRateControl?: boolean | number[];
|
|
45
46
|
} & CompProps<Props> & PropsIfHasProps<Schema, Props>;
|
|
46
47
|
export declare const componentOrNullIfLazy: <Props>(props: CompProps<Props>) => ComponentType<Props> | null;
|
|
47
48
|
/**
|
package/dist/esm/PlayerUI.d.ts
CHANGED
|
@@ -35,5 +35,6 @@ declare const _default: React.ForwardRefExoticComponent<{
|
|
|
35
35
|
renderPlayPauseButton: RenderPlayPauseButton | null;
|
|
36
36
|
renderFullscreen: RenderFullscreenButton | null;
|
|
37
37
|
alwaysShowControls: boolean;
|
|
38
|
+
showPlaybackRateControl: boolean | number[];
|
|
38
39
|
} & React.RefAttributes<PlayerRef>>;
|
|
39
40
|
export default _default;
|