softbuilders-react-video-player 1.1.54 → 1.1.56
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/components/SoftBuildersVideoPlayer/index.d.ts +2 -1
- package/dist/components/SoftBuildersVideoPlayer/index.js +4 -4
- package/dist/components/SoftBuildersVideoPlayer/index.js.map +1 -1
- package/dist/components/SoftBuildersVideoPlayer/index.tsx +69 -64
- package/dist/components/VideoPlayerComponent/index.d.ts +3 -1
- package/dist/components/VideoPlayerComponent/index.js +4 -4
- package/dist/components/VideoPlayerComponent/index.js.map +1 -1
- package/dist/components/VideoPlayerComponent/index.tsx +267 -261
- package/dist/index.d.mts +4 -3
- package/dist/index.mjs +342 -333
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { useEffect, useRef, useState } from "react";
|
1
|
+
import React, { forwardRef, useEffect, useRef, useState } from "react";
|
2
2
|
import ReactDOM from "react-dom/client";
|
3
3
|
import videojs from "video.js";
|
4
4
|
import Player from "video.js/dist/types/player";
|
@@ -111,70 +111,161 @@ export type Props<T = any> = {
|
|
111
111
|
onPlay?: (time: number) => void;
|
112
112
|
onPause?: (time: number) => void;
|
113
113
|
disableNote?: boolean;
|
114
|
+
childRef?: React.Ref<HTMLDivElement>;
|
114
115
|
};
|
115
|
-
const VideoPlayerComponent = <
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
116
|
+
const VideoPlayerComponent = forwardRef<HTMLDivElement, Props<any>>(
|
117
|
+
({
|
118
|
+
id,
|
119
|
+
options,
|
120
|
+
notes,
|
121
|
+
chapters,
|
122
|
+
startTime = 0,
|
123
|
+
handleSaveNoteAction,
|
124
|
+
poster,
|
125
|
+
onPlay,
|
126
|
+
onPause,
|
127
|
+
disableNote,
|
128
|
+
childRef,
|
129
|
+
}: Props) => {
|
130
|
+
const videoRef = useRef<any>(undefined);
|
131
|
+
const playerRef = useRef<Player | undefined>(undefined);
|
132
|
+
const [isReady, setIsReady] = useState(false);
|
133
|
+
const [isPaused, setIsPaused] = useState(!options.autoplay);
|
134
|
+
const [duration, setDuration] = useState(1);
|
135
|
+
const [opacity, setOpacity] = useState("0");
|
136
|
+
const [isControlBarPresent, setIsControlBarPresent] = useState(true);
|
137
|
+
const [bgColor, setBgColor] = useState("transparent");
|
138
|
+
const [isQualityMenuOpen, setIsQualityMenuOpen] = useState(false);
|
139
|
+
const [isSubtitleMenuOpen, setIsSubtitleMenuOpen] = useState(false);
|
140
|
+
const [isHovered, setIsHovered] = useState(false);
|
141
|
+
const onReady = (player: Player) => {
|
142
|
+
if (playerRef) {
|
143
|
+
playerRef.current = player;
|
144
|
+
setIsReady(true);
|
145
|
+
player?.currentTime(startTime);
|
146
|
+
player.on("waiting", () => {});
|
147
|
+
player.on("dispose", () => {
|
148
|
+
videojs.log("player will dispose");
|
149
|
+
setIsReady(false);
|
150
|
+
});
|
151
|
+
player.on("loadedmetadata", () => {
|
152
|
+
const d = player.duration() || 0;
|
153
|
+
setDuration(d);
|
154
|
+
});
|
155
|
+
}
|
156
|
+
};
|
157
|
+
useEffect(() => {
|
158
|
+
if (!playerRef.current) {
|
159
|
+
const videoElement = document.createElement("video-js");
|
160
|
+
|
161
|
+
videoElement.setAttribute("playsinline", "true");
|
157
162
|
|
158
|
-
|
163
|
+
videoElement.classList.add("vjs-big-play-centered");
|
164
|
+
// Set the poster attribute here
|
165
|
+
if (poster) {
|
166
|
+
videoElement.setAttribute("poster", poster);
|
167
|
+
}
|
168
|
+
videoRef.current.appendChild(videoElement);
|
169
|
+
videoElement.style.width = "100%";
|
170
|
+
videoElement.style.height = "100%";
|
171
|
+
videoElement.style.objectFit = "cover";
|
172
|
+
playerRef.current = videojs(videoElement, options, () => {
|
173
|
+
onReady(playerRef.current as Player);
|
174
|
+
});
|
175
|
+
}
|
176
|
+
return () => {
|
177
|
+
if (playerRef.current) {
|
178
|
+
playerRef.current.dispose();
|
179
|
+
playerRef.current = undefined;
|
180
|
+
setTimeout(() => {
|
181
|
+
if (bigPlayButtonRoot[id]) {
|
182
|
+
bigPlayButtonRoot[id].unmount();
|
183
|
+
bigPlayButtonRoot[id] = undefined;
|
184
|
+
}
|
185
|
+
if (controlBarRoot[id]) {
|
186
|
+
controlBarRoot[id].unmount();
|
187
|
+
controlBarRoot[id] = undefined;
|
188
|
+
}
|
189
|
+
}, 0);
|
190
|
+
}
|
191
|
+
};
|
192
|
+
}, [options, poster]); // Added poster to dependency array
|
193
|
+
useEffect(() => {
|
194
|
+
if (playerRef.current && isReady) {
|
195
|
+
const currentTime = playerRef.current.currentTime() || 0;
|
196
|
+
if (isPaused) {
|
197
|
+
if (onPause) onPause(currentTime);
|
198
|
+
} else {
|
199
|
+
if (onPlay) onPlay(currentTime);
|
200
|
+
}
|
201
|
+
}
|
202
|
+
}, [isPaused, isReady]);
|
159
203
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
204
|
+
useEffect(() => {
|
205
|
+
if (isReady) {
|
206
|
+
const controlBarTimeout = setTimeout(() => {
|
207
|
+
renderControlBar(
|
208
|
+
id,
|
209
|
+
playerRef.current,
|
210
|
+
isPaused,
|
211
|
+
setIsPaused,
|
212
|
+
duration,
|
213
|
+
notes,
|
214
|
+
chapters,
|
215
|
+
5,
|
216
|
+
handleSaveNoteAction,
|
217
|
+
opacity,
|
218
|
+
(e: any) => {
|
219
|
+
handlePlayerClick(e, true);
|
220
|
+
},
|
221
|
+
bgColor,
|
222
|
+
setIsQualityMenuOpen,
|
223
|
+
setIsSubtitleMenuOpen,
|
224
|
+
disableNote
|
225
|
+
);
|
226
|
+
}, 500);
|
227
|
+
return () => clearTimeout(controlBarTimeout);
|
164
228
|
}
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
229
|
+
}, [
|
230
|
+
id,
|
231
|
+
playerRef,
|
232
|
+
isPaused,
|
233
|
+
setIsPaused,
|
234
|
+
notes,
|
235
|
+
chapters,
|
236
|
+
isReady,
|
237
|
+
handleSaveNoteAction,
|
238
|
+
duration,
|
239
|
+
opacity,
|
240
|
+
]);
|
241
|
+
useEffect(() => {
|
242
|
+
if (isReady) {
|
243
|
+
const playButtonTimeout = setTimeout(() => {
|
244
|
+
renderBigPlayButton(
|
245
|
+
id,
|
246
|
+
playerRef.current,
|
247
|
+
isPaused,
|
248
|
+
setIsPaused,
|
249
|
+
opacity
|
250
|
+
);
|
251
|
+
}, 500);
|
252
|
+
return () => clearTimeout(playButtonTimeout);
|
253
|
+
}
|
254
|
+
}, [id, isPaused, isReady, opacity]);
|
255
|
+
useEffect(() => {
|
174
256
|
if (playerRef.current) {
|
175
|
-
|
176
|
-
|
177
|
-
|
257
|
+
const intervalId = setInterval(() => {
|
258
|
+
if (playerRef.current) setIsPaused(playerRef.current.paused());
|
259
|
+
}, 500);
|
260
|
+
return () => clearInterval(intervalId);
|
261
|
+
}
|
262
|
+
}, []);
|
263
|
+
useEffect(() => {
|
264
|
+
return () => {
|
265
|
+
if (playerRef.current) {
|
266
|
+
playerRef.current.dispose();
|
267
|
+
playerRef.current = undefined;
|
268
|
+
// Cleanup play button and control bar renders
|
178
269
|
if (bigPlayButtonRoot[id]) {
|
179
270
|
bigPlayButtonRoot[id].unmount();
|
180
271
|
bigPlayButtonRoot[id] = undefined;
|
@@ -183,234 +274,149 @@ const VideoPlayerComponent = <T,>({
|
|
183
274
|
controlBarRoot[id].unmount();
|
184
275
|
controlBarRoot[id] = undefined;
|
185
276
|
}
|
186
|
-
}, 0);
|
187
|
-
}
|
188
|
-
};
|
189
|
-
}, [options, poster]); // Added poster to dependency array
|
190
|
-
useEffect(() => {
|
191
|
-
if (playerRef.current && isReady) {
|
192
|
-
const currentTime = playerRef.current.currentTime() || 0;
|
193
|
-
if (isPaused) {
|
194
|
-
if (onPause) onPause(currentTime);
|
195
|
-
} else {
|
196
|
-
if (onPlay) onPlay(currentTime);
|
197
|
-
}
|
198
|
-
}
|
199
|
-
}, [isPaused, isReady]);
|
200
|
-
|
201
|
-
useEffect(() => {
|
202
|
-
if (isReady) {
|
203
|
-
const controlBarTimeout = setTimeout(() => {
|
204
|
-
renderControlBar(
|
205
|
-
id,
|
206
|
-
playerRef.current,
|
207
|
-
isPaused,
|
208
|
-
setIsPaused,
|
209
|
-
duration,
|
210
|
-
notes,
|
211
|
-
chapters,
|
212
|
-
5,
|
213
|
-
handleSaveNoteAction,
|
214
|
-
opacity,
|
215
|
-
(e: any) => {
|
216
|
-
handlePlayerClick(e, true);
|
217
|
-
},
|
218
|
-
bgColor,
|
219
|
-
setIsQualityMenuOpen,
|
220
|
-
setIsSubtitleMenuOpen,
|
221
|
-
disableNote
|
222
|
-
);
|
223
|
-
}, 500);
|
224
|
-
return () => clearTimeout(controlBarTimeout);
|
225
|
-
}
|
226
|
-
}, [
|
227
|
-
id,
|
228
|
-
playerRef,
|
229
|
-
isPaused,
|
230
|
-
setIsPaused,
|
231
|
-
notes,
|
232
|
-
chapters,
|
233
|
-
isReady,
|
234
|
-
handleSaveNoteAction,
|
235
|
-
duration,
|
236
|
-
opacity,
|
237
|
-
]);
|
238
|
-
useEffect(() => {
|
239
|
-
if (isReady) {
|
240
|
-
const playButtonTimeout = setTimeout(() => {
|
241
|
-
renderBigPlayButton(
|
242
|
-
id,
|
243
|
-
playerRef.current,
|
244
|
-
isPaused,
|
245
|
-
setIsPaused,
|
246
|
-
opacity
|
247
|
-
);
|
248
|
-
}, 500);
|
249
|
-
return () => clearTimeout(playButtonTimeout);
|
250
|
-
}
|
251
|
-
}, [id, isPaused, isReady, opacity]);
|
252
|
-
useEffect(() => {
|
253
|
-
if (playerRef.current) {
|
254
|
-
const intervalId = setInterval(() => {
|
255
|
-
if (playerRef.current) setIsPaused(playerRef.current.paused());
|
256
|
-
}, 500);
|
257
|
-
return () => clearInterval(intervalId);
|
258
|
-
}
|
259
|
-
}, []);
|
260
|
-
useEffect(() => {
|
261
|
-
return () => {
|
262
|
-
if (playerRef.current) {
|
263
|
-
playerRef.current.dispose();
|
264
|
-
playerRef.current = undefined;
|
265
|
-
// Cleanup play button and control bar renders
|
266
|
-
if (bigPlayButtonRoot[id]) {
|
267
|
-
bigPlayButtonRoot[id].unmount();
|
268
|
-
bigPlayButtonRoot[id] = undefined;
|
269
277
|
}
|
270
|
-
|
271
|
-
|
272
|
-
|
278
|
+
};
|
279
|
+
}, []);
|
280
|
+
const timeoutRef = useRef<any>(null);
|
281
|
+
useEffect(() => {
|
282
|
+
if (isQualityMenuOpen || isSubtitleMenuOpen) {
|
283
|
+
if (timeoutRef.current) {
|
284
|
+
clearTimeout(timeoutRef.current);
|
285
|
+
}
|
286
|
+
setOpacity("100");
|
287
|
+
} else {
|
288
|
+
if (timeoutRef.current) {
|
289
|
+
clearTimeout(timeoutRef.current);
|
273
290
|
}
|
291
|
+
setOpacity("0");
|
292
|
+
|
293
|
+
timeoutRef.current = setTimeout(() => {
|
294
|
+
setIsControlBarPresent(false);
|
295
|
+
}, 3000);
|
274
296
|
}
|
275
|
-
};
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
if (isQualityMenuOpen || isSubtitleMenuOpen) {
|
297
|
+
}, [isQualityMenuOpen, isSubtitleMenuOpen]);
|
298
|
+
|
299
|
+
const handlePlayerClick = async (e: any, isTimerOnly = false) => {
|
300
|
+
e.preventDefault();
|
280
301
|
if (timeoutRef.current) {
|
281
302
|
clearTimeout(timeoutRef.current);
|
282
303
|
}
|
283
304
|
setOpacity("100");
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
}
|
288
|
-
setOpacity("0");
|
289
|
-
|
305
|
+
setIsControlBarPresent(true);
|
306
|
+
// setBgColor("rgba(200, 200, 200, 0.5)");
|
307
|
+
// not using now
|
290
308
|
timeoutRef.current = setTimeout(() => {
|
309
|
+
setOpacity("0");
|
310
|
+
setBgColor("transparent");
|
291
311
|
setIsControlBarPresent(false);
|
292
312
|
}, 3000);
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
return;
|
312
|
-
}
|
313
|
-
if (!isControlBarPresent) {
|
314
|
-
return;
|
315
|
-
}
|
316
|
-
if (playerRef.current) {
|
317
|
-
if (playerRef.current.paused()) {
|
318
|
-
try {
|
319
|
-
await playerRef.current.play();
|
320
|
-
setIsPaused(false);
|
321
|
-
} catch (error) {
|
322
|
-
console.error("Failed to play video:", error);
|
313
|
+
if (isTimerOnly) {
|
314
|
+
return;
|
315
|
+
}
|
316
|
+
if (!isControlBarPresent) {
|
317
|
+
return;
|
318
|
+
}
|
319
|
+
if (playerRef.current) {
|
320
|
+
if (playerRef.current.paused()) {
|
321
|
+
try {
|
322
|
+
await playerRef.current.play();
|
323
|
+
setIsPaused(false);
|
324
|
+
} catch (error) {
|
325
|
+
console.error("Failed to play video:", error);
|
326
|
+
}
|
327
|
+
} else {
|
328
|
+
playerRef.current.pause();
|
329
|
+
setIsPaused(true);
|
330
|
+
if (onPause) onPause(playerRef.current.currentTime() || 0);
|
323
331
|
}
|
324
|
-
} else {
|
325
|
-
playerRef.current.pause();
|
326
|
-
setIsPaused(true);
|
327
|
-
if (onPause) onPause(playerRef.current.currentTime() || 0);
|
328
332
|
}
|
329
|
-
}
|
330
|
-
|
331
|
-
const videoRefs = useRef<HTMLDivElement>(null); // Create a reference for the element
|
333
|
+
};
|
334
|
+
const videoRefs = useRef<HTMLDivElement>(null); // Create a reference for the element
|
332
335
|
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
336
|
+
useEffect(() => {
|
337
|
+
const observer = new IntersectionObserver(
|
338
|
+
(entries) => {
|
339
|
+
entries.forEach((entry) => {
|
340
|
+
if (entry.isIntersecting === false) {
|
341
|
+
if (playerRef?.current?.paused() === false) {
|
342
|
+
try {
|
343
|
+
playerRef?.current?.pause();
|
344
|
+
setIsPaused(true);
|
345
|
+
} catch (error) {
|
346
|
+
console.error("Failed to play video:", error);
|
347
|
+
}
|
344
348
|
}
|
345
349
|
}
|
346
|
-
}
|
347
|
-
}
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
);
|
353
|
-
|
354
|
-
if (videoRefs.current) {
|
355
|
-
observer.observe(videoRefs.current); // Start observing the component
|
356
|
-
}
|
350
|
+
});
|
351
|
+
},
|
352
|
+
{
|
353
|
+
threshold: 0.1, // The amount of the component that must be visible (0.1 means 10% visible)
|
354
|
+
}
|
355
|
+
);
|
357
356
|
|
358
|
-
return () => {
|
359
357
|
if (videoRefs.current) {
|
360
|
-
observer.
|
358
|
+
observer.observe(videoRefs.current); // Start observing the component
|
361
359
|
}
|
362
|
-
};
|
363
|
-
}, []);
|
364
360
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
361
|
+
return () => {
|
362
|
+
if (videoRefs.current) {
|
363
|
+
observer.unobserve(videoRef.current); // Clean up the observer when the component unmounts
|
364
|
+
}
|
365
|
+
};
|
366
|
+
}, []);
|
371
367
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
368
|
+
const [timeSeeker, setTimeSeeker] = useState<string>("0");
|
369
|
+
useEffect(() => {
|
370
|
+
const updateTimeSeeker = () => {
|
371
|
+
if (playerRef?.current) {
|
372
|
+
const currentTime = playerRef.current?.currentTime?.();
|
373
|
+
const duration = playerRef.current?.duration?.();
|
374
|
+
|
375
|
+
if (duration && currentTime !== undefined) {
|
376
|
+
const value = `${(currentTime / duration) * 100}%`;
|
377
|
+
setTimeSeeker(value);
|
378
|
+
} else {
|
379
|
+
setTimeSeeker("0");
|
380
|
+
}
|
377
381
|
}
|
378
|
-
}
|
379
|
-
|
380
|
-
|
381
|
-
}, [playerRef?.current?.currentTime()]);
|
382
|
+
};
|
383
|
+
updateTimeSeeker();
|
384
|
+
}, [playerRef?.current?.currentTime()]);
|
382
385
|
|
383
|
-
|
384
|
-
<div
|
385
|
-
ref={videoRefs}
|
386
|
-
id={`video-container-${id}`}
|
387
|
-
onMouseMove={() => {
|
388
|
-
handlePlayerClick(event, true);
|
389
|
-
}}
|
390
|
-
className="sb-relative sb-overflow-hidden sb-w-full sb-h-full sb-bottom-2 "
|
391
|
-
onMouseEnter={() => setIsHovered(true)}
|
392
|
-
onMouseLeave={() => setIsHovered(false)}
|
393
|
-
>
|
386
|
+
return (
|
394
387
|
<div
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
width: timeSeeker,
|
388
|
+
ref={videoRefs}
|
389
|
+
id={`video-container-${id}`}
|
390
|
+
onMouseMove={() => {
|
391
|
+
handlePlayerClick(event, true);
|
400
392
|
}}
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
// Attach click event
|
405
|
-
data-vjs-player
|
393
|
+
className="sb-relative sb-rounded-md sb-overflow-hidden sb-w-full sb-h-full sb-bottom-2 "
|
394
|
+
onMouseEnter={() => setIsHovered(true)}
|
395
|
+
onMouseLeave={() => setIsHovered(false)}
|
406
396
|
>
|
407
397
|
<div
|
398
|
+
ref={childRef}
|
408
399
|
onClick={handlePlayerClick}
|
409
|
-
|
410
|
-
|
400
|
+
className={`sb-h-[3px] sb-transition-opacity sb-duration-500 sb-delay-400 sb-z-10 ease-in-out sb-border-spacing-x-2 sb-absolute sb-bg-[red] sb-bottom-0 ${
|
401
|
+
opacity == "100" ? "sb-opacity-0" : "sb-opacity-100"
|
402
|
+
}`}
|
403
|
+
style={{
|
404
|
+
width: timeSeeker,
|
405
|
+
}}
|
411
406
|
></div>
|
407
|
+
<div
|
408
|
+
className="hover:sb-cursor-pointer sb-w-full sb-h-full"
|
409
|
+
// Attach click event
|
410
|
+
data-vjs-player
|
411
|
+
>
|
412
|
+
<div
|
413
|
+
onClick={handlePlayerClick}
|
414
|
+
ref={videoRef}
|
415
|
+
className="sb-h-full sb-w-full sb-relative"
|
416
|
+
></div>
|
417
|
+
</div>
|
412
418
|
</div>
|
413
|
-
|
414
|
-
|
415
|
-
|
419
|
+
);
|
420
|
+
}
|
421
|
+
);
|
416
422
|
export default VideoPlayerComponent;
|
package/dist/index.d.mts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
import
|
2
|
-
import React from 'react';
|
1
|
+
import React$1 from 'react';
|
3
2
|
|
4
3
|
type SoftBuildersVideoPlayerSource = {
|
5
4
|
src: string;
|
@@ -25,6 +24,7 @@ type SoftBuildersVideoPlayerOptions = {
|
|
25
24
|
tracks?: SoftBuildersVideoPlayerTrack[];
|
26
25
|
width?: number;
|
27
26
|
height?: number;
|
27
|
+
childRef?: React.Ref<HTMLDivElement>;
|
28
28
|
};
|
29
29
|
interface SoftBuildersVideoPlayerNote {
|
30
30
|
time: number;
|
@@ -46,7 +46,8 @@ type Props<T = any> = {
|
|
46
46
|
onPause?: (time: number) => void;
|
47
47
|
isFocused?: boolean;
|
48
48
|
disableNote?: boolean;
|
49
|
+
childRef?: React$1.Ref<HTMLDivElement>;
|
49
50
|
};
|
50
|
-
declare const SoftBuildersVideoPlayer: React.MemoExoticComponent<
|
51
|
+
declare const SoftBuildersVideoPlayer: React$1.MemoExoticComponent<React$1.ForwardRefExoticComponent<Props<any> & React$1.RefAttributes<HTMLDivElement>>>;
|
51
52
|
|
52
53
|
export { type SoftBuildersVideoPlayerChapter, type SoftBuildersVideoPlayerNote, type SoftBuildersVideoPlayerOptions, type SoftBuildersVideoPlayerSource, type SoftBuildersVideoPlayerTrack, SoftBuildersVideoPlayer as default };
|