softbuilders-react-video-player 1.1.8 → 1.1.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +126 -126
  3. package/dist/components/BigPlayButton/index.tsx +31 -31
  4. package/dist/components/BufferTracker/index.tsx +19 -19
  5. package/dist/components/ChapterTooltip/index.tsx +65 -65
  6. package/dist/components/ChaptersPanal/index.tsx +40 -40
  7. package/dist/components/ControlBar/index.d.ts +2 -1
  8. package/dist/components/ControlBar/index.js +19 -5
  9. package/dist/components/ControlBar/index.js.map +1 -1
  10. package/dist/components/ControlBar/index.tsx +149 -127
  11. package/dist/components/CreateNoteMenu/index.tsx +61 -61
  12. package/dist/components/CurrentTimeLabel/index.tsx +13 -13
  13. package/dist/components/CurrentTimeTracker/index.tsx +18 -18
  14. package/dist/components/Menu/index.tsx +49 -49
  15. package/dist/components/MenuButton/index.js +1 -1
  16. package/dist/components/MenuButton/index.js.map +1 -1
  17. package/dist/components/MenuButton/index.tsx +67 -67
  18. package/dist/components/NoteTooltip/index.tsx +46 -46
  19. package/dist/components/NotesPanal/index.tsx +34 -34
  20. package/dist/components/QualityMenu/index.js +2 -2
  21. package/dist/components/QualityMenu/index.js.map +1 -1
  22. package/dist/components/QualityMenu/index.tsx +122 -122
  23. package/dist/components/Slider/index.d.ts +1 -1
  24. package/dist/components/Slider/index.js +3 -3
  25. package/dist/components/Slider/index.js.map +1 -1
  26. package/dist/components/Slider/index.tsx +36 -37
  27. package/dist/components/Slider/style.css +49 -15
  28. package/dist/components/SoftBuildersVideoPlayer/index.js +1 -1
  29. package/dist/components/SoftBuildersVideoPlayer/index.js.map +1 -1
  30. package/dist/components/SoftBuildersVideoPlayer/index.tsx +110 -109
  31. package/dist/components/SubtitleMenu/index.js +2 -2
  32. package/dist/components/SubtitleMenu/index.js.map +1 -1
  33. package/dist/components/SubtitleMenu/index.tsx +107 -108
  34. package/dist/components/TimeSlider/index.js +13 -13
  35. package/dist/components/TimeSlider/index.tsx +107 -107
  36. package/dist/components/TimeSliderContainer/index.tsx +35 -35
  37. package/dist/components/Tooltip/index.tsx +16 -16
  38. package/dist/components/VideoPlayerComponent/index.d.ts +2 -1
  39. package/dist/components/VideoPlayerComponent/index.js +38 -36
  40. package/dist/components/VideoPlayerComponent/index.js.map +1 -1
  41. package/dist/components/VideoPlayerComponent/index.tsx +260 -249
  42. package/dist/components/VideoPlayerComponent/provider.tsx +82 -82
  43. package/dist/components/VideoPlayerComponent/style/style.css +36 -36
  44. package/dist/components/VolumeSlider/index.d.ts +4 -2
  45. package/dist/components/VolumeSlider/index.js +12 -2
  46. package/dist/components/VolumeSlider/index.js.map +1 -1
  47. package/dist/components/VolumeSlider/index.tsx +91 -52
  48. package/dist/components/icons/SubIcon.d.ts +3 -0
  49. package/dist/components/icons/SubIcon.js +4 -0
  50. package/dist/components/icons/SubIcon.js.map +1 -0
  51. package/dist/components/icons/SubIcon.tsx +28 -0
  52. package/dist/components/icons/index.d.ts +1 -0
  53. package/dist/components/icons/index.js +1 -0
  54. package/dist/components/icons/index.js.map +1 -1
  55. package/dist/components/icons/index.ts +15 -14
  56. package/dist/images/index.d.ts +1 -0
  57. package/dist/images/index.js +1 -0
  58. package/dist/images/index.js.map +1 -1
  59. package/dist/index.css +75 -3
  60. package/dist/index.mjs +253 -166
  61. package/dist/styles/tailwind.css +137 -87
  62. package/package.json +45 -45
@@ -1,249 +1,260 @@
1
- import React, { useEffect, useRef, useState } from "react";
2
- import ReactDOM from "react-dom/client";
3
- import videojs from "video.js";
4
- import Player from "video.js/dist/types/player";
5
- import "video.js/dist/video-js.css";
6
- import ControlBar from "../ControlBar";
7
- import {
8
- SoftBuildersVideoPlayerChapter,
9
- SoftBuildersVideoPlayerNote,
10
- SoftBuildersVideoPlayerOptions,
11
- } from "../../types";
12
-
13
- import "./style/style.css";
14
- import "../../styles/tailwind.css";
15
- import { SoftBuildersVideoPlayerProvider } from "./provider";
16
- import BigPlayButton from "../BigPlayButton";
17
-
18
- let bigPlayButtonRoot: {
19
- [key: string]: ReactDOM.Root | undefined;
20
- } = {};
21
-
22
- const renderBigPlayButton = (
23
- id: string,
24
- player: Player | undefined,
25
- isPaused: boolean,
26
- setIsPaused: React.Dispatch<React.SetStateAction<boolean>>
27
- ) => {
28
- const container = document.getElementById(`video-container-${id}`);
29
- if (container) {
30
- const element: any = container.querySelector(".vjs-big-play-button");
31
- if (element) {
32
- if (!bigPlayButtonRoot[id]) {
33
- // If bigPlayButtonRoot hasn't been created, create it
34
- bigPlayButtonRoot[id] = ReactDOM.createRoot(element as HTMLElement);
35
- }
36
-
37
- bigPlayButtonRoot[id].render(
38
- <BigPlayButton
39
- player={player}
40
- isPaused={isPaused}
41
- setIsPaused={setIsPaused}
42
- />
43
- );
44
- }
45
- }
46
- };
47
-
48
- let controlBarRoot: {
49
- [key: string]: ReactDOM.Root | undefined;
50
- } = {};
51
-
52
- const renderControlBar = <T,>(
53
- id: string,
54
- player: Player | undefined,
55
- isPaused: boolean,
56
- setIsPaused: React.Dispatch<React.SetStateAction<boolean>>,
57
- duration: number,
58
- notes: SoftBuildersVideoPlayerNote[],
59
- chapters: SoftBuildersVideoPlayerChapter[],
60
- seekStep: number = 5,
61
- handleSaveNoteAction?: (time: number, note: string) => Promise<T>
62
- ) => {
63
- const container = document.getElementById(`video-container-${id}`);
64
- if (container) {
65
- const element: any = container.querySelector(".vjs-control-bar");
66
- if (element) {
67
- if (!controlBarRoot[id]) {
68
- // If controlBarRoot hasn't been created, create it
69
- controlBarRoot[id] = ReactDOM.createRoot(element as HTMLElement);
70
- }
71
-
72
- element.style.display = "block";
73
- controlBarRoot[id].render(
74
- <SoftBuildersVideoPlayerProvider>
75
- <ControlBar
76
- player={player}
77
- isPaused={isPaused}
78
- setIsPaused={setIsPaused}
79
- duration={duration}
80
- notes={notes}
81
- chapters={chapters}
82
- seekStep={seekStep}
83
- handleSaveNoteAction={handleSaveNoteAction}
84
- />
85
- </SoftBuildersVideoPlayerProvider>
86
- );
87
- }
88
- }
89
- };
90
-
91
- export type Props<T = any> = {
92
- id: string;
93
- options: SoftBuildersVideoPlayerOptions;
94
- notes: SoftBuildersVideoPlayerNote[];
95
- chapters: SoftBuildersVideoPlayerChapter[];
96
- startTime?: number;
97
- handleSaveNoteAction?: (time: number, note: string) => Promise<T>;
98
- onPlay?: (time: number) => void;
99
- onPause?: (time: number) => void;
100
- };
101
-
102
- const VideoPlayerComponent = <T,>({
103
- id,
104
- options,
105
- notes,
106
- chapters,
107
- startTime = 0,
108
- handleSaveNoteAction,
109
- onPlay,
110
- onPause,
111
- }: Props<T>) => {
112
- const videoRef = useRef<any>(undefined);
113
- const playerRef = useRef<Player | undefined>(undefined);
114
-
115
- const [isReady, setIsReady] = useState(false);
116
- const [isPaused, setIsPaused] = useState(!options.autoplay);
117
- const [duration, setDuratoin] = useState(1);
118
-
119
- const onReady = (player: Player) => {
120
- if (playerRef) {
121
- playerRef.current = player;
122
- setIsReady(true);
123
-
124
- player.currentTime(startTime);
125
-
126
- player.on("waiting", () => {});
127
-
128
- player.on("dispose", () => {
129
- videojs.log("player will dispose");
130
- setIsReady(false);
131
- });
132
-
133
- player.on("loadedmetadata", () => {
134
- const d = player.duration() || 0;
135
- setDuratoin(d);
136
- });
137
- }
138
- };
139
-
140
- useEffect(() => {
141
- if (!playerRef.current) {
142
- const videoElement = document.createElement("video-js");
143
- videoElement.classList.add("vjs-big-play-centered");
144
- videoRef.current.appendChild(videoElement);
145
-
146
- playerRef.current = videojs(videoElement, options, () => {
147
- onReady(playerRef.current as Player);
148
- });
149
- }
150
-
151
- return () => {
152
- if (playerRef)
153
- if (playerRef.current) {
154
- // Dispose of the player properly on component unmount
155
- playerRef.current.dispose();
156
- playerRef.current = undefined;
157
-
158
- // Defer unmounting of big play button and control bar to avoid race conditions
159
- setTimeout(() => {
160
- if (bigPlayButtonRoot[id]) {
161
- bigPlayButtonRoot[id].unmount();
162
- bigPlayButtonRoot[id] = undefined;
163
- }
164
- if (controlBarRoot[id]) {
165
- controlBarRoot[id].unmount();
166
- controlBarRoot[id] = undefined;
167
- }
168
- }, 0);
169
- }
170
- };
171
- }, [options]);
172
-
173
- useEffect(() => {
174
- if (playerRef && playerRef?.current && isReady) {
175
- const currentTime = playerRef.current.currentTime() || 0;
176
-
177
- if (isPaused) {
178
- if (onPause) onPause(currentTime);
179
- } else {
180
- if (onPlay) onPlay(currentTime);
181
- }
182
- }
183
- }, [isPaused, isReady]);
184
-
185
- useEffect(() => {
186
- if (isReady) {
187
- const controlBarTimeout = setTimeout(() => {
188
- renderControlBar(
189
- id,
190
- playerRef.current,
191
- isPaused,
192
- setIsPaused,
193
- duration,
194
- notes,
195
- chapters,
196
- 5,
197
- handleSaveNoteAction
198
- );
199
- }, 500);
200
-
201
- return () => clearTimeout(controlBarTimeout); // Clean up the timeout
202
- }
203
- }, [
204
- id,
205
- playerRef,
206
- isPaused,
207
- setIsPaused,
208
- notes,
209
- chapters,
210
- isReady,
211
- handleSaveNoteAction,
212
- duration,
213
- ]);
214
-
215
- useEffect(() => {
216
- if (isReady && playerRef) {
217
- const playButtonTimeout = setTimeout(() => {
218
- renderBigPlayButton(id, playerRef.current, isPaused, setIsPaused);
219
- }, 500);
220
-
221
- return () => clearTimeout(playButtonTimeout); // Clean up the timeout
222
- }
223
- }, [id, isPaused, isReady]);
224
-
225
- useEffect(() => {
226
- if (playerRef) {
227
- if (playerRef.current) {
228
- const intervalId = setInterval(() => {
229
- if (playerRef.current) setIsPaused(playerRef.current.paused());
230
- }, 500);
231
-
232
- return () => clearInterval(intervalId);
233
- }
234
- }
235
- }, []);
236
-
237
- return (
238
- <div
239
- id={`video-container-${id}`}
240
- className="sb-relative sb-rounded-md sb-overflow-hidden"
241
- >
242
- <div data-vjs-player>
243
- <div ref={videoRef} />
244
- </div>
245
- </div>
246
- );
247
- };
248
-
249
- export default VideoPlayerComponent;
1
+ import React, { useEffect, useRef, useState } from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import videojs from "video.js";
4
+ import Player from "video.js/dist/types/player";
5
+ import "video.js/dist/video-js.css";
6
+ import ControlBar from "../ControlBar";
7
+ import {
8
+ SoftBuildersVideoPlayerChapter,
9
+ SoftBuildersVideoPlayerNote,
10
+ SoftBuildersVideoPlayerOptions,
11
+ } from "../../types";
12
+
13
+ import "./style/style.css";
14
+ import "../../styles/tailwind.css";
15
+ import { SoftBuildersVideoPlayerProvider } from "./provider";
16
+ import BigPlayButton from "../BigPlayButton";
17
+
18
+ let bigPlayButtonRoot: {
19
+ [key: string]: ReactDOM.Root | undefined;
20
+ } = {};
21
+
22
+ const renderBigPlayButton = (
23
+ id: string,
24
+ player: Player | undefined,
25
+ isPaused: boolean,
26
+ setIsPaused: React.Dispatch<React.SetStateAction<boolean>>
27
+ ) => {
28
+ const container = document.getElementById(`video-container-${id}`);
29
+ if (container) {
30
+ const element: any = container.querySelector(".vjs-big-play-button");
31
+ if (element) {
32
+ if (!bigPlayButtonRoot[id]) {
33
+ bigPlayButtonRoot[id] = ReactDOM.createRoot(element as HTMLElement);
34
+ }
35
+
36
+ bigPlayButtonRoot[id].render(
37
+ <BigPlayButton
38
+ player={player}
39
+ isPaused={isPaused}
40
+ setIsPaused={setIsPaused}
41
+ />
42
+ );
43
+ }
44
+ }
45
+ };
46
+
47
+ let controlBarRoot: {
48
+ [key: string]: ReactDOM.Root | undefined;
49
+ } = {};
50
+
51
+ const renderControlBar = <T,>(
52
+ id: string,
53
+ player: Player | undefined,
54
+ isPaused: boolean,
55
+ setIsPaused: React.Dispatch<React.SetStateAction<boolean>>,
56
+ duration: number,
57
+ notes: SoftBuildersVideoPlayerNote[],
58
+ chapters: SoftBuildersVideoPlayerChapter[],
59
+ seekStep: number = 5,
60
+ handleSaveNoteAction?: (time: number, note: string) => Promise<T>
61
+ ) => {
62
+ const container = document.getElementById(`video-container-${id}`);
63
+
64
+ if (container) {
65
+ const element: any = container.querySelector(".vjs-control-bar");
66
+ if (element) {
67
+ if (!controlBarRoot[id]) {
68
+ controlBarRoot[id] = ReactDOM.createRoot(element as HTMLElement);
69
+ }
70
+
71
+ element.style.display = "flex";
72
+ element.style.height = "100%";
73
+ element.style.alignItems = "flex-end";
74
+ controlBarRoot[id].render(
75
+ <SoftBuildersVideoPlayerProvider>
76
+ <ControlBar
77
+ id={id}
78
+ player={player}
79
+ isPaused={isPaused}
80
+ setIsPaused={setIsPaused}
81
+ duration={duration}
82
+ notes={notes}
83
+ chapters={chapters}
84
+ seekStep={seekStep}
85
+ handleSaveNoteAction={handleSaveNoteAction}
86
+ />
87
+ </SoftBuildersVideoPlayerProvider>
88
+ );
89
+ }
90
+ }
91
+ };
92
+
93
+ export type Props<T = any> = {
94
+ id: string;
95
+ options: SoftBuildersVideoPlayerOptions;
96
+ notes: SoftBuildersVideoPlayerNote[];
97
+ chapters: SoftBuildersVideoPlayerChapter[];
98
+ startTime?: number;
99
+ poster?: string; // Changed to string type for poster URL
100
+ handleSaveNoteAction?: (time: number, note: string) => Promise<T>;
101
+ onPlay?: (time: number) => void;
102
+ onPause?: (time: number) => void;
103
+ };
104
+
105
+ const VideoPlayerComponent = <T,>({
106
+ id,
107
+ options,
108
+ notes,
109
+ chapters,
110
+ startTime = 0,
111
+ handleSaveNoteAction,
112
+ poster,
113
+
114
+ onPlay,
115
+ onPause,
116
+ }: Props<T>) => {
117
+ const videoRef = useRef<any>(undefined);
118
+ const playerRef = useRef<Player | undefined>(undefined);
119
+
120
+ const [isReady, setIsReady] = useState(false);
121
+ const [isPaused, setIsPaused] = useState(!options.autoplay);
122
+ const [duration, setDuratoin] = useState(1);
123
+
124
+ const onReady = (player: Player) => {
125
+ if (playerRef) {
126
+ playerRef.current = player;
127
+ setIsReady(true);
128
+
129
+ player.currentTime(startTime);
130
+
131
+ player.on("waiting", () => {});
132
+
133
+ player.on("dispose", () => {
134
+ videojs.log("player will dispose");
135
+ setIsReady(false);
136
+ });
137
+
138
+ player.on("loadedmetadata", () => {
139
+ const d = player.duration() || 0;
140
+ setDuratoin(d);
141
+ });
142
+ }
143
+ };
144
+
145
+ useEffect(() => {
146
+ if (!playerRef.current) {
147
+ const videoElement = document.createElement("video-js");
148
+ videoElement.classList.add("vjs-big-play-centered");
149
+ // Set the poster attribute here
150
+
151
+ if (poster) {
152
+ videoElement.setAttribute("poster", poster);
153
+ }
154
+ videoRef.current.appendChild(videoElement);
155
+
156
+ playerRef.current = videojs(videoElement, options, () => {
157
+ onReady(playerRef.current as Player);
158
+ });
159
+ }
160
+
161
+ return () => {
162
+ if (playerRef.current) {
163
+ playerRef.current.dispose();
164
+ playerRef.current = undefined;
165
+
166
+ setTimeout(() => {
167
+ if (bigPlayButtonRoot[id]) {
168
+ bigPlayButtonRoot[id].unmount();
169
+ bigPlayButtonRoot[id] = undefined;
170
+ }
171
+ if (controlBarRoot[id]) {
172
+ controlBarRoot[id].unmount();
173
+ controlBarRoot[id] = undefined;
174
+ }
175
+ }, 0);
176
+ }
177
+ };
178
+ }, [options, poster]); // Added poster to dependency array
179
+
180
+ useEffect(() => {
181
+ if (playerRef.current && isReady) {
182
+ const currentTime = playerRef.current.currentTime() || 0;
183
+
184
+ if (isPaused) {
185
+ if (onPause) onPause(currentTime);
186
+ } else {
187
+ if (onPlay) onPlay(currentTime);
188
+ }
189
+ }
190
+ }, [isPaused, isReady]);
191
+
192
+ useEffect(() => {
193
+ if (isReady) {
194
+ const controlBarTimeout = setTimeout(() => {
195
+ renderControlBar(
196
+ id,
197
+ playerRef.current,
198
+ isPaused,
199
+ setIsPaused,
200
+ duration,
201
+ notes,
202
+ chapters,
203
+ 5,
204
+ handleSaveNoteAction
205
+ );
206
+ }, 500);
207
+
208
+ return () => clearTimeout(controlBarTimeout);
209
+ }
210
+ }, [
211
+ id,
212
+ playerRef,
213
+ isPaused,
214
+ setIsPaused,
215
+ notes,
216
+ chapters,
217
+ isReady,
218
+ handleSaveNoteAction,
219
+ duration,
220
+ ]);
221
+
222
+ useEffect(() => {
223
+ if (isReady) {
224
+ const playButtonTimeout = setTimeout(() => {
225
+ renderBigPlayButton(id, playerRef.current, isPaused, setIsPaused);
226
+ }, 500);
227
+
228
+ return () => clearTimeout(playButtonTimeout);
229
+ }
230
+ }, [id, isPaused, isReady]);
231
+
232
+ useEffect(() => {
233
+ if (playerRef.current) {
234
+ const intervalId = setInterval(() => {
235
+ if (playerRef.current) setIsPaused(playerRef.current.paused());
236
+ }, 500);
237
+
238
+ return () => clearInterval(intervalId);
239
+ }
240
+ }, []);
241
+
242
+ return (
243
+ <div
244
+ id={`video-container-${id}`}
245
+ className="sb-relative sb-rounded-md sb-overflow-hidden"
246
+ >
247
+ <div
248
+ data-vjs-player
249
+ style={{
250
+ height: "100%", // Adjust height as needed
251
+ position: "relative",
252
+ }}
253
+ >
254
+ <div ref={videoRef} />
255
+ </div>
256
+ </div>
257
+ );
258
+ };
259
+
260
+ export default VideoPlayerComponent;