@remotion/promo-pages 4.0.260 → 5.0.0-canary.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/Homepage.js +2 -4
  2. package/package.json +52 -48
  3. package/.turbo/turbo-lint.log +0 -5
  4. package/.turbo/turbo-make.log +0 -8
  5. package/LICENSE.md +0 -49
  6. package/bundle.ts +0 -46
  7. package/eslint.config.mjs +0 -7
  8. package/index.html +0 -13
  9. package/public/fire.mp3 +0 -0
  10. package/public/img/cluster.png +0 -0
  11. package/public/img/code-sample-new.png +0 -0
  12. package/public/img/freelancers/alex.jpeg +0 -0
  13. package/public/img/freelancers/antoine.jpeg +0 -0
  14. package/public/img/freelancers/ayush.png +0 -0
  15. package/public/img/freelancers/benjamin.jpeg +0 -0
  16. package/public/img/freelancers/default.png +0 -0
  17. package/public/img/freelancers/florent.jpeg +0 -0
  18. package/public/img/freelancers/karel.jpeg +0 -0
  19. package/public/img/freelancers/lorenzo.jpeg +0 -0
  20. package/public/img/freelancers/mickael.jpeg +0 -0
  21. package/public/img/freelancers/mohit.jpeg +0 -0
  22. package/public/img/freelancers/pramod.jpg +0 -0
  23. package/public/img/freelancers/pranav.jpg +0 -0
  24. package/public/img/freelancers/rahul.png +0 -0
  25. package/public/img/freelancers/ray.jpeg +0 -0
  26. package/public/img/freelancers/stephen.png +0 -0
  27. package/public/img/freelancers/umungo.png +0 -0
  28. package/public/img/freelancers/yehor.jpeg +0 -0
  29. package/public/img/gt-planar-black.woff2 +0 -0
  30. package/public/img/gt-planar-bold.woff2 +0 -0
  31. package/public/img/gt-planar-medium.woff2 +0 -0
  32. package/public/img/gt-planar-regular.woff2 +0 -0
  33. package/public/img/logo-small.png +0 -0
  34. package/public/img/mp4.png +0 -0
  35. package/public/img/player-demo.mp4 +0 -0
  36. package/public/img/player-example-dark.png +0 -0
  37. package/public/img/player-example.png +0 -0
  38. package/public/img/writeinreact.png +0 -0
  39. package/public/partyhorn.mp3 +0 -0
  40. package/public/sad.mp3 +0 -0
  41. package/src/cn.ts +0 -6
  42. package/src/components/Homepage.tsx +0 -88
  43. package/src/components/homepage/BackgroundAnimation.tsx +0 -108
  44. package/src/components/homepage/ChooseTemplate.tsx +0 -57
  45. package/src/components/homepage/CodeExample.tsx +0 -89
  46. package/src/components/homepage/CommunityStats.tsx +0 -54
  47. package/src/components/homepage/CommunityStatsItems.tsx +0 -304
  48. package/src/components/homepage/Counter.tsx +0 -110
  49. package/src/components/homepage/Demo/Card.tsx +0 -273
  50. package/src/components/homepage/Demo/Cards.tsx +0 -129
  51. package/src/components/homepage/Demo/Comp.tsx +0 -157
  52. package/src/components/homepage/Demo/CurrentCountry.tsx +0 -97
  53. package/src/components/homepage/Demo/DemoError.tsx +0 -18
  54. package/src/components/homepage/Demo/DemoErrorIcon.tsx +0 -32
  55. package/src/components/homepage/Demo/DemoRender.tsx +0 -166
  56. package/src/components/homepage/Demo/DigitWheel.tsx +0 -179
  57. package/src/components/homepage/Demo/DisplayedEmoji.tsx +0 -81
  58. package/src/components/homepage/Demo/DoneCheckmark.tsx +0 -39
  59. package/src/components/homepage/Demo/DownloadNudge.tsx +0 -62
  60. package/src/components/homepage/Demo/DragAndDropNudge.tsx +0 -57
  61. package/src/components/homepage/Demo/EmojiCard.tsx +0 -198
  62. package/src/components/homepage/Demo/Minus.tsx +0 -21
  63. package/src/components/homepage/Demo/PlayPauseButton.tsx +0 -66
  64. package/src/components/homepage/Demo/PlayerControls.tsx +0 -48
  65. package/src/components/homepage/Demo/PlayerSeekBar.tsx +0 -325
  66. package/src/components/homepage/Demo/PlayerVolume.tsx +0 -83
  67. package/src/components/homepage/Demo/Progress.tsx +0 -38
  68. package/src/components/homepage/Demo/Spinner.tsx +0 -60
  69. package/src/components/homepage/Demo/Switcher.tsx +0 -54
  70. package/src/components/homepage/Demo/Temperature.tsx +0 -44
  71. package/src/components/homepage/Demo/TemperatureNumber.tsx +0 -68
  72. package/src/components/homepage/Demo/ThemeNudge.tsx +0 -72
  73. package/src/components/homepage/Demo/TimeDisplay.tsx +0 -43
  74. package/src/components/homepage/Demo/TrendingRepos.tsx +0 -106
  75. package/src/components/homepage/Demo/icons.tsx +0 -114
  76. package/src/components/homepage/Demo/index.tsx +0 -158
  77. package/src/components/homepage/Demo/math.ts +0 -43
  78. package/src/components/homepage/Demo/types.ts +0 -6
  79. package/src/components/homepage/Editor.tsx +0 -67
  80. package/src/components/homepage/EvaluateRemotion.tsx +0 -92
  81. package/src/components/homepage/FreePricing.tsx +0 -295
  82. package/src/components/homepage/GetStartedStrip.tsx +0 -77
  83. package/src/components/homepage/GitHubButton.tsx +0 -23
  84. package/src/components/homepage/IconForTemplate.tsx +0 -154
  85. package/src/components/homepage/IfYouKnowReact.tsx +0 -29
  86. package/src/components/homepage/InfoTooltip.tsx +0 -25
  87. package/src/components/homepage/MoreTemplatesButton.tsx +0 -29
  88. package/src/components/homepage/MuxVideo.tsx +0 -68
  89. package/src/components/homepage/NewsletterButton.tsx +0 -88
  90. package/src/components/homepage/Pricing.tsx +0 -49
  91. package/src/components/homepage/PricingBulletPoint.tsx +0 -50
  92. package/src/components/homepage/RealMp4Videos.tsx +0 -50
  93. package/src/components/homepage/Spacer.tsx +0 -5
  94. package/src/components/homepage/TemplateIcon.tsx +0 -36
  95. package/src/components/homepage/TextInput.tsx +0 -62
  96. package/src/components/homepage/TrustedByBanner.tsx +0 -194
  97. package/src/components/homepage/VideoApps.tsx +0 -231
  98. package/src/components/homepage/VideoAppsShowcase.tsx +0 -276
  99. package/src/components/homepage/VideoAppsTitle.tsx +0 -24
  100. package/src/components/homepage/VideoPlayerWithControls.tsx +0 -188
  101. package/src/components/homepage/WriteInReact.tsx +0 -34
  102. package/src/components/homepage/YouAreHere.tsx +0 -30
  103. package/src/components/homepage/custom.css +0 -57
  104. package/src/components/homepage/layout/Button.tsx +0 -93
  105. package/src/components/homepage/layout/colors.ts +0 -17
  106. package/src/components/homepage/layout/use-color-mode.tsx +0 -44
  107. package/src/components/homepage/layout/use-el-size.ts +0 -51
  108. package/src/components/homepage/layout/use-mobile-layout.ts +0 -8
  109. package/src/components/homepage/video-player.css +0 -24
  110. package/src/components/icons/blank.tsx +0 -13
  111. package/src/components/icons/clone.tsx +0 -10
  112. package/src/components/icons/code-hike.tsx +0 -15
  113. package/src/components/icons/cubes.tsx +0 -13
  114. package/src/components/icons/js.tsx +0 -17
  115. package/src/components/icons/next.tsx +0 -64
  116. package/src/components/icons/overlay.tsx +0 -24
  117. package/src/components/icons/remix.tsx +0 -24
  118. package/src/components/icons/skia.tsx +0 -13
  119. package/src/components/icons/stargazer.tsx +0 -13
  120. package/src/components/icons/still.tsx +0 -13
  121. package/src/components/icons/tailwind.tsx +0 -22
  122. package/src/components/icons/tiktok.tsx +0 -13
  123. package/src/components/icons/ts.tsx +0 -18
  124. package/src/components/icons/tts.tsx +0 -13
  125. package/src/components/icons/undo.tsx +0 -11
  126. package/src/components/icons/waveform.tsx +0 -13
  127. package/src/fonts.css +0 -30
  128. package/src/index.css +0 -74
  129. package/src/main.tsx +0 -12
  130. package/tsconfig.json +0 -15
  131. package/vite.config.ts +0 -9
@@ -1,198 +0,0 @@
1
- import type {EmojiName} from '@remotion/animated-emoji';
2
- import React, {
3
- forwardRef,
4
- useCallback,
5
- useEffect,
6
- useImperativeHandle,
7
- useRef,
8
- } from 'react';
9
- import {AbsoluteFill, getRemotionEnvironment} from 'remotion';
10
- import {DisplayedEmoji} from './DisplayedEmoji';
11
-
12
- export type EmojiCardRef = {
13
- onLeft: () => void;
14
- onRight: () => void;
15
- };
16
-
17
- type Transforms = [number, number, number];
18
-
19
- type Anim = {
20
- ref1: HTMLDivElement;
21
- ref2: HTMLDivElement;
22
- ref3: HTMLDivElement;
23
- transforms: Transforms;
24
- };
25
-
26
- const applyTransforms = ({ref1, ref2, ref3, transforms}: Anim) => {
27
- ref1.style.transform = `translateX(${transforms[0]}%)`;
28
- ref2.style.transform = `translateX(${transforms[1]}%)`;
29
- ref3.style.transform = `translateX(${transforms[2]}%)`;
30
- };
31
-
32
- const waitForRaq = async () => {
33
- await new Promise((resolve) => {
34
- requestAnimationFrame(resolve);
35
- });
36
- };
37
-
38
- const moveLeft = async ({ref1, ref2, ref3, transforms}: Anim) => {
39
- for (let i = 0; i < 20; i++) {
40
- for (const idx in transforms) {
41
- transforms[idx] -= 5;
42
- if (transforms[idx] <= -200) {
43
- transforms[idx] += 300;
44
- }
45
- }
46
-
47
- applyTransforms({ref1, ref2, ref3, transforms});
48
- await waitForRaq();
49
- }
50
- };
51
-
52
- const moveRight = async ({ref1, ref2, ref3, transforms}: Anim) => {
53
- for (let i = 0; i < 20; i++) {
54
- for (const idx in transforms) {
55
- transforms[idx] += 5;
56
- if (transforms[idx] >= 100) {
57
- transforms[idx] -= 300;
58
- }
59
- }
60
-
61
- applyTransforms({ref1, ref2, ref3, transforms});
62
- await waitForRaq();
63
- }
64
- };
65
-
66
- const emojiStyle: React.CSSProperties = {
67
- width: '100%',
68
- position: 'absolute',
69
- top: 'calc(50% - 50px)',
70
- };
71
-
72
- export type EmojiCardProps = {
73
- readonly emojiIndex: EmojiName;
74
- };
75
-
76
- const EmojiCardRefFn: React.ForwardRefRenderFunction<
77
- EmojiCardRef,
78
- EmojiCardProps
79
- > = ({emojiIndex}, ref) => {
80
- const ref1 = useRef<HTMLDivElement>(null);
81
- const ref2 = useRef<HTMLDivElement>(null);
82
- const ref3 = useRef<HTMLDivElement>(null);
83
- const transforms = useRef<Transforms>([-100, 0, 100]);
84
-
85
- const onLeft = useCallback(() => {
86
- if (!ref1.current || !ref2.current || !ref3.current) {
87
- return;
88
- }
89
-
90
- moveLeft({
91
- ref1: ref1.current,
92
- ref2: ref2.current,
93
- ref3: ref3.current,
94
- transforms: transforms.current,
95
- });
96
- }, []);
97
-
98
- const onRight = useCallback(() => {
99
- if (!ref1.current || !ref2.current || !ref3.current) {
100
- return;
101
- }
102
-
103
- moveRight({
104
- ref1: ref1.current,
105
- ref2: ref2.current,
106
- ref3: ref3.current,
107
- transforms: transforms.current,
108
- });
109
- }, []);
110
-
111
- useEffect(() => {
112
- if (!ref1.current || !ref2.current || !ref3.current) {
113
- return;
114
- }
115
-
116
- applyTransforms({
117
- ref1: ref1.current,
118
- ref2: ref2.current,
119
- ref3: ref3.current,
120
- transforms: transforms.current,
121
- });
122
- }, []);
123
-
124
- useImperativeHandle(ref, () => {
125
- return {
126
- onLeft,
127
- onRight,
128
- };
129
- }, [onLeft, onRight]);
130
-
131
- useEffect(() => {
132
- if (!ref1.current || !ref2.current || !ref3.current) {
133
- return;
134
- }
135
-
136
- applyTransforms({
137
- ref1: ref1.current,
138
- ref2: ref2.current,
139
- ref3: ref3.current,
140
- transforms: transforms.current,
141
- });
142
- }, []);
143
-
144
- return (
145
- <AbsoluteFill
146
- style={{
147
- justifyContent: 'center',
148
- alignItems: 'center',
149
- overflow: 'hidden',
150
- }}
151
- >
152
- <div
153
- style={{
154
- color: '#0b84f3',
155
- fontFamily: 'GTPlanar',
156
- fontWeight: '500',
157
- fontSize: 13,
158
- textAlign: 'center',
159
- position: 'absolute',
160
- marginTop: -90,
161
- }}
162
- >
163
- Choose an emoji
164
- </div>
165
- <div
166
- style={{
167
- position: 'absolute',
168
- width: '100%',
169
- display: 'flex',
170
- whiteSpace: 'nowrap',
171
- height: '100%',
172
- }}
173
- >
174
- {getRemotionEnvironment().isRendering ? (
175
- <div style={emojiStyle}>
176
- <DisplayedEmoji emoji={emojiIndex} />
177
- </div>
178
- ) : (
179
- <>
180
- <div ref={ref1} style={emojiStyle}>
181
- <DisplayedEmoji emoji={'melting'} />
182
- </div>
183
- <div ref={ref2} style={emojiStyle}>
184
- <DisplayedEmoji emoji={'partying-face'} />
185
- </div>
186
- <div ref={ref3} style={emojiStyle}>
187
- <DisplayedEmoji emoji={'fire'} />
188
- </div>
189
- </>
190
- )}
191
- </div>
192
- </AbsoluteFill>
193
- );
194
- };
195
-
196
- export const EmojiCard = forwardRef<EmojiCardRef, EmojiCardProps>(
197
- EmojiCardRefFn,
198
- );
@@ -1,21 +0,0 @@
1
- import React from 'react';
2
-
3
- export const Minus: React.FC<{
4
- readonly leftOffset: number;
5
- readonly minusSignOpacity: number;
6
- }> = ({leftOffset, minusSignOpacity}) => {
7
- return (
8
- <div
9
- style={{
10
- position: 'relative',
11
- marginLeft: -40 - leftOffset,
12
- marginTop: 5,
13
- width: 40,
14
- opacity: minusSignOpacity,
15
- textAlign: 'right',
16
- }}
17
- >
18
- -
19
- </div>
20
- );
21
- };
@@ -1,66 +0,0 @@
1
- import type {PlayerRef} from '@remotion/player';
2
- import React, {useCallback, useEffect} from 'react';
3
- import {PALETTE} from '../layout/colors';
4
- import {PausedIcon, PlayingIcon} from './icons';
5
-
6
- const playerButtonStyle: React.CSSProperties = {
7
- appearance: 'none',
8
- border: 'none',
9
- borderRadius: 0,
10
- background: 'none',
11
- display: 'flex',
12
- justifyContent: 'center',
13
- alignItems: 'center',
14
- paddingRight: 20,
15
- paddingLeft: 20,
16
- cursor: 'pointer',
17
- height: 50,
18
- color: PALETTE.TEXT_COLOR,
19
- };
20
-
21
- export const PlayPauseButton: React.FC<{
22
- readonly playerRef: React.RefObject<PlayerRef | null>;
23
- }> = ({playerRef}) => {
24
- const [playing, setPlaying] = React.useState(true);
25
-
26
- useEffect(() => {
27
- const {current} = playerRef;
28
- if (!current) {
29
- return;
30
- }
31
-
32
- const onPlay = () => {
33
- setPlaying(true);
34
- };
35
-
36
- const onPause = () => {
37
- setPlaying(false);
38
- };
39
-
40
- current.addEventListener('play', onPlay);
41
- current.addEventListener('pause', onPause);
42
-
43
- return () => {
44
- current.removeEventListener('play', onPlay);
45
- current.removeEventListener('pause', onPause);
46
- };
47
- }, [playerRef]);
48
-
49
- const onToggle = useCallback(() => {
50
- playerRef.current?.toggle();
51
- }, [playerRef]);
52
-
53
- const playPauseIconStyle: React.CSSProperties = {
54
- width: 15,
55
- };
56
-
57
- return (
58
- <button type="button" style={playerButtonStyle} onClick={onToggle}>
59
- {playing ? (
60
- <PlayingIcon style={playPauseIconStyle} />
61
- ) : (
62
- <PausedIcon style={playPauseIconStyle} />
63
- )}
64
- </button>
65
- );
66
- };
@@ -1,48 +0,0 @@
1
- import type {PlayerRef} from '@remotion/player';
2
- import React from 'react';
3
- import {PALETTE} from '../layout/colors';
4
- import {PlayerSeekBar} from './PlayerSeekBar';
5
- import {PlayerVolume} from './PlayerVolume';
6
- import {PlayPauseButton} from './PlayPauseButton';
7
- import {TimeDisplay} from './TimeDisplay';
8
-
9
- const Separator: React.FC = () => {
10
- return (
11
- <div
12
- style={{
13
- borderRight: `2px solid ${PALETTE.BOX_STROKE}`,
14
- height: 50,
15
- }}
16
- />
17
- );
18
- };
19
-
20
- export const PlayerControls: React.FC<{
21
- readonly playerRef: React.RefObject<PlayerRef | null>;
22
- readonly durationInFrames: number;
23
- readonly fps: number;
24
- readonly children: React.ReactNode;
25
- }> = ({playerRef, durationInFrames, fps, children}) => {
26
- return (
27
- <div className={'flex flex-row items-center bg-pane'}>
28
- <PlayPauseButton playerRef={playerRef} />
29
- <Separator />
30
- <PlayerVolume playerRef={playerRef} />
31
- <Separator />
32
- <div style={{width: 15}} />
33
- <TimeDisplay playerRef={playerRef} fps={fps} />
34
- <div style={{width: 15}} />
35
- <PlayerSeekBar
36
- durationInFrames={durationInFrames}
37
- playerRef={playerRef}
38
- inFrame={null}
39
- outFrame={null}
40
- onSeekEnd={() => undefined}
41
- onSeekStart={() => undefined}
42
- />
43
- <div style={{width: 20}} />
44
- <Separator />
45
- {children}
46
- </div>
47
- );
48
- };
@@ -1,325 +0,0 @@
1
- import type {PlayerRef} from '@remotion/player';
2
- import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
3
- import {interpolate} from 'remotion';
4
- import {useElementSize} from '../layout/use-el-size';
5
-
6
- const getFrameFromX = (
7
- clientX: number,
8
- durationInFrames: number,
9
- width: number,
10
- ) => {
11
- const pos = clientX;
12
- const frame = Math.round(
13
- interpolate(pos, [0, width], [0, durationInFrames - 1], {
14
- extrapolateLeft: 'clamp',
15
- extrapolateRight: 'clamp',
16
- }),
17
- );
18
- return frame;
19
- };
20
-
21
- const BAR_HEIGHT = 5;
22
- const KNOB_SIZE = 12;
23
- const VERTICAL_PADDING = 4;
24
-
25
- const containerStyle: React.CSSProperties = {
26
- userSelect: 'none',
27
- WebkitUserSelect: 'none',
28
- paddingTop: VERTICAL_PADDING,
29
- paddingBottom: VERTICAL_PADDING,
30
- boxSizing: 'border-box',
31
- cursor: 'pointer',
32
- position: 'relative',
33
- touchAction: 'none',
34
- flex: 1,
35
- };
36
-
37
- const barBackground: React.CSSProperties = {
38
- height: BAR_HEIGHT,
39
- backgroundColor: 'rgba(0, 0, 0, 0.25)',
40
- width: '100%',
41
- borderRadius: BAR_HEIGHT / 2,
42
- };
43
-
44
- const findBodyInWhichDivIsLocated = (div: HTMLElement) => {
45
- let current = div;
46
-
47
- while (current.parentElement) {
48
- current = current.parentElement;
49
- }
50
-
51
- return current;
52
- };
53
-
54
- export const useHoverState = (
55
- ref: React.RefObject<HTMLDivElement | null>,
56
- hideControlsWhenPointerDoesntMove: boolean | number,
57
- ) => {
58
- const [hovered, setHovered] = useState(false);
59
-
60
- useEffect(() => {
61
- const {current} = ref;
62
- if (!current) {
63
- return;
64
- }
65
-
66
- let hoverTimeout: Timer;
67
- const addHoverTimeout = () => {
68
- if (hideControlsWhenPointerDoesntMove) {
69
- clearTimeout(hoverTimeout);
70
- hoverTimeout = setTimeout(
71
- () => {
72
- setHovered(false);
73
- },
74
- hideControlsWhenPointerDoesntMove === true
75
- ? 3000
76
- : hideControlsWhenPointerDoesntMove,
77
- );
78
- }
79
- };
80
-
81
- const onHover = () => {
82
- setHovered(true);
83
- addHoverTimeout();
84
- };
85
-
86
- const onLeave = () => {
87
- setHovered(false);
88
- clearTimeout(hoverTimeout);
89
- };
90
-
91
- const onMove = () => {
92
- setHovered(true);
93
- addHoverTimeout();
94
- };
95
-
96
- current.addEventListener('mouseenter', onHover);
97
- current.addEventListener('mouseleave', onLeave);
98
- current.addEventListener('mousemove', onMove);
99
-
100
- return () => {
101
- current.removeEventListener('mouseenter', onHover);
102
- current.removeEventListener('mouseleave', onLeave);
103
- current.removeEventListener('mousemove', onMove);
104
- clearTimeout(hoverTimeout);
105
- };
106
- }, [hideControlsWhenPointerDoesntMove, ref]);
107
- return hovered;
108
- };
109
-
110
- export const PlayerSeekBar: React.FC<{
111
- readonly durationInFrames: number;
112
- readonly onSeekStart: () => void;
113
- readonly onSeekEnd: () => void;
114
- readonly inFrame: number | null;
115
- readonly outFrame: number | null;
116
- readonly playerRef: React.RefObject<PlayerRef | null>;
117
- }> = ({
118
- durationInFrames,
119
- onSeekEnd,
120
- onSeekStart,
121
- inFrame,
122
- outFrame,
123
- playerRef,
124
- }) => {
125
- const containerRef = useRef<HTMLDivElement>(null);
126
- const barHovered = useHoverState(containerRef, false);
127
- const size = useElementSize(containerRef.current);
128
- const [playing, setPlaying] = useState(false);
129
-
130
- const [frame, setFrame] = useState(0);
131
-
132
- useEffect(() => {
133
- const {current} = playerRef;
134
- if (!current) {
135
- return;
136
- }
137
-
138
- const onFrameUpdate = () => {
139
- setFrame(playerRef.current!.getCurrentFrame());
140
- };
141
-
142
- current.addEventListener('frameupdate', onFrameUpdate);
143
-
144
- return () => {
145
- current.removeEventListener('frameupdate', onFrameUpdate);
146
- };
147
- }, [playerRef]);
148
-
149
- useEffect(() => {
150
- const {current} = playerRef;
151
- if (!current) {
152
- return;
153
- }
154
-
155
- const onPlay = () => {
156
- setPlaying(true);
157
- };
158
-
159
- const onPause = () => {
160
- setPlaying(false);
161
- };
162
-
163
- current.addEventListener('play', onPlay);
164
- current.addEventListener('pause', onPause);
165
-
166
- return () => {
167
- current.removeEventListener('play', onPlay);
168
- current.removeEventListener('pause', onPause);
169
- };
170
- }, [playerRef]);
171
-
172
- const [dragging, setDragging] = useState<
173
- | {
174
- dragging: false;
175
- }
176
- | {
177
- dragging: true;
178
- wasPlaying: boolean;
179
- }
180
- >({
181
- dragging: false,
182
- });
183
-
184
- const width = size?.width ?? 0;
185
-
186
- const onPointerDown = useCallback(
187
- (e: React.PointerEvent<HTMLDivElement>) => {
188
- if (e.button !== 0) {
189
- return;
190
- }
191
-
192
- const posLeft = containerRef.current?.getBoundingClientRect()
193
- .left as number;
194
-
195
- const _frame = getFrameFromX(
196
- e.clientX - posLeft,
197
- durationInFrames,
198
- width,
199
- );
200
- playerRef.current!.pause();
201
- playerRef.current!.seekTo(_frame);
202
- setDragging({
203
- dragging: true,
204
- wasPlaying: playing,
205
- });
206
- onSeekStart();
207
- },
208
- [durationInFrames, width, playerRef, playing, onSeekStart],
209
- );
210
-
211
- const onPointerMove = useCallback(
212
- (e: PointerEvent) => {
213
- if (!size) {
214
- throw new Error('Player has no size');
215
- }
216
-
217
- if (!dragging.dragging) {
218
- return;
219
- }
220
-
221
- const posLeft = containerRef.current?.getBoundingClientRect()
222
- .left as number;
223
-
224
- const _frame = getFrameFromX(
225
- e.clientX - posLeft,
226
- durationInFrames,
227
- size.width,
228
- );
229
- playerRef.current!.seekTo(_frame);
230
- },
231
- [dragging.dragging, durationInFrames, playerRef, size],
232
- );
233
-
234
- const onPointerUp = useCallback(() => {
235
- setDragging({
236
- dragging: false,
237
- });
238
- if (!dragging.dragging) {
239
- return;
240
- }
241
-
242
- if (dragging.wasPlaying) {
243
- playerRef.current!.play();
244
- } else {
245
- playerRef.current!.pause();
246
- }
247
-
248
- onSeekEnd();
249
- }, [dragging, onSeekEnd, playerRef]);
250
-
251
- useEffect(() => {
252
- if (!dragging.dragging) {
253
- return;
254
- }
255
-
256
- const body = findBodyInWhichDivIsLocated(
257
- containerRef.current as HTMLElement,
258
- );
259
-
260
- body.addEventListener('pointermove', onPointerMove);
261
- body.addEventListener('pointerup', onPointerUp);
262
- return () => {
263
- body.removeEventListener('pointermove', onPointerMove);
264
- body.removeEventListener('pointerup', onPointerUp);
265
- };
266
- }, [dragging.dragging, onPointerMove, onPointerUp]);
267
-
268
- const knobStyle: React.CSSProperties = useMemo(() => {
269
- return {
270
- height: KNOB_SIZE,
271
- width: KNOB_SIZE,
272
- borderRadius: KNOB_SIZE / 2,
273
- position: 'absolute',
274
- top: VERTICAL_PADDING - KNOB_SIZE / 2 + 5 / 2,
275
- backgroundColor: 'var(--ifm-font-color-base)',
276
- left: Math.max(
277
- 0,
278
- (frame / Math.max(1, durationInFrames - 1)) * width - KNOB_SIZE / 2,
279
- ),
280
- outline: '2px solid var(--ifm-background-color)',
281
- opacity: Number(barHovered),
282
- transition: 'opacity 0.s ease',
283
- };
284
- }, [barHovered, durationInFrames, frame, width]);
285
-
286
- const fillStyle: React.CSSProperties = useMemo(() => {
287
- return {
288
- height: BAR_HEIGHT,
289
- backgroundColor: 'var(--ifm-font-color-base)',
290
- width: ((frame - (inFrame ?? 0)) / (durationInFrames - 1)) * 100 + '%',
291
- marginLeft: ((inFrame ?? 0) / (durationInFrames - 1)) * 100 + '%',
292
- borderRadius: BAR_HEIGHT / 2,
293
- };
294
- }, [durationInFrames, frame, inFrame]);
295
-
296
- const active: React.CSSProperties = useMemo(() => {
297
- return {
298
- height: BAR_HEIGHT,
299
- backgroundColor: 'var(--ifm-font-color-base)',
300
- opacity: 0.2,
301
- width:
302
- (((outFrame ?? durationInFrames - 1) - (inFrame ?? 0)) /
303
- (durationInFrames - 1)) *
304
- 100 +
305
- '%',
306
- marginLeft: ((inFrame ?? 0) / (durationInFrames - 1)) * 100 + '%',
307
- borderRadius: BAR_HEIGHT / 2,
308
- position: 'absolute',
309
- };
310
- }, [durationInFrames, inFrame, outFrame]);
311
-
312
- return (
313
- <div
314
- ref={containerRef}
315
- onPointerDown={onPointerDown}
316
- style={containerStyle}
317
- >
318
- <div style={barBackground}>
319
- <div style={active} />
320
- <div style={fillStyle} />
321
- </div>
322
- <div style={knobStyle} />
323
- </div>
324
- );
325
- };