softbuilders-react-video-player 1.1.7 → 1.1.9

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 (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 +37 -34
  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
- 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;