@nikelroot/video-player 0.1.5 → 0.1.7
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/README.md +2 -0
- package/dist/index.cjs +95 -74
- package/dist/index.js +47 -26
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,9 @@ __export(index_exports, {
|
|
|
37
37
|
module.exports = __toCommonJS(index_exports);
|
|
38
38
|
|
|
39
39
|
// src/VideoPlayer.tsx
|
|
40
|
+
var import_react3 = require("react");
|
|
41
|
+
|
|
42
|
+
// src/controls.tsx
|
|
40
43
|
var import_react2 = require("react");
|
|
41
44
|
|
|
42
45
|
// src/styles.ts
|
|
@@ -286,6 +289,13 @@ var VideoPlayerStyles = import_styled_components.styled.div`
|
|
|
286
289
|
}
|
|
287
290
|
}
|
|
288
291
|
|
|
292
|
+
&:hover {
|
|
293
|
+
.video-right-bar {
|
|
294
|
+
background: rgba(0, 0, 0, 0.1);
|
|
295
|
+
opacity: 1;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
289
299
|
${(props) => (props.$showControl || props.$alwaysShowSegments) && import_styled_components.css`
|
|
290
300
|
.video-right-bar {
|
|
291
301
|
background: rgba(0, 0, 0, 0.1);
|
|
@@ -420,6 +430,7 @@ var createThrottledNumberFn = (fn, waitMs) => {
|
|
|
420
430
|
// src/controls.tsx
|
|
421
431
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
422
432
|
var SeekSlider = ({ playAction, duration, currentTime, seekSetTime }) => {
|
|
433
|
+
const ref = (0, import_react2.useRef)(null);
|
|
423
434
|
const clickHandler = (e) => {
|
|
424
435
|
e.preventDefault();
|
|
425
436
|
e.stopPropagation();
|
|
@@ -428,10 +439,14 @@ var SeekSlider = ({ playAction, duration, currentTime, seekSetTime }) => {
|
|
|
428
439
|
const safeCurrentTime = Math.max(0, Math.min(Number.isFinite(currentTime) ? currentTime : 0, safeDuration || Infinity));
|
|
429
440
|
const completeChange = () => {
|
|
430
441
|
void playAction();
|
|
442
|
+
if (ref.current) {
|
|
443
|
+
ref.current.blur();
|
|
444
|
+
}
|
|
431
445
|
};
|
|
432
446
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SeekSliderStyled, { onClick: clickHandler, className: "seek-slider", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
433
447
|
"input",
|
|
434
448
|
{
|
|
449
|
+
ref,
|
|
435
450
|
"aria-label": "Seek",
|
|
436
451
|
className: "seek-range",
|
|
437
452
|
disabled: safeDuration <= 0,
|
|
@@ -533,19 +548,6 @@ var VideoPlayerControls = (props) => {
|
|
|
533
548
|
} = props;
|
|
534
549
|
const [, isMobile] = useWindowWidth();
|
|
535
550
|
if (variant === "none") return null;
|
|
536
|
-
if (variant === "tiny") {
|
|
537
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoPlayerControlStyles, { $tiny: true, $isMobile: isMobile, onClick: stopControlClick, $showControl: showControl, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "video-player-control-row", children: [
|
|
538
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "full" }),
|
|
539
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SeekSlider, { playAction, duration, currentTime, seekSetTime })
|
|
540
|
-
] }) });
|
|
541
|
-
}
|
|
542
|
-
if (variant === "fullscreen-only") {
|
|
543
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoPlayerControlStyles, { $isMobile: isMobile, onClick: stopControlClick, $showControl: showControl, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "video-player-control-row", children: [
|
|
544
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "full" }),
|
|
545
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, { icon: muted ? "mute" : "sound", label: muted ? "Unmute" : "Mute", onClick: () => onMutedChange(!muted) }),
|
|
546
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, { disabled: !fullscreenAllowed, icon: "fullscreen", label: "Fullscreen", onClick: fullScreenAction })
|
|
547
|
-
] }) });
|
|
548
|
-
}
|
|
549
551
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoPlayerControlStyles, { $isMobile: isMobile, onClick: stopControlClick, $showControl: showControl, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "video-player-control-row", children: [
|
|
550
552
|
playing ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, { icon: "pause", label: "Pause", onClick: pauseAction }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, { icon: "play", label: "Play", onClick: playAction }),
|
|
551
553
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlButton, { icon: "back", label: "Back 15 seconds", onClick: () => seekPrevAction() }),
|
|
@@ -770,6 +772,10 @@ var assignRef = (ref, value) => {
|
|
|
770
772
|
}
|
|
771
773
|
ref.current = value;
|
|
772
774
|
};
|
|
775
|
+
var isEditableKeyTarget = (target) => {
|
|
776
|
+
if (!(target instanceof HTMLElement)) return false;
|
|
777
|
+
return target.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName);
|
|
778
|
+
};
|
|
773
779
|
var VideoPlayerBase = (props, ref) => {
|
|
774
780
|
const {
|
|
775
781
|
controlsVariant = "none",
|
|
@@ -822,40 +828,40 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
822
828
|
...videoProps
|
|
823
829
|
} = props;
|
|
824
830
|
const videoSrc = rawVideoSrc.replaceAll(" ", "%20").replaceAll("#", "%23");
|
|
825
|
-
const messages = (0,
|
|
831
|
+
const messages = (0, import_react3.useMemo)(() => ({ ...defaultMessages, ...messagesProp }), [messagesProp]);
|
|
826
832
|
const [, isMobile, mobileType] = useWindowWidth();
|
|
827
|
-
const videoRef = (0,
|
|
828
|
-
const hlsRef = (0,
|
|
829
|
-
const containerRef = (0,
|
|
830
|
-
const netRetryCount = (0,
|
|
831
|
-
const mediaRecoverCount = (0,
|
|
832
|
-
const fatalReloadCount = (0,
|
|
833
|
-
const reloadTimer = (0,
|
|
834
|
-
const stalledNudgeTimer = (0,
|
|
835
|
-
const liveStabilityMode = (0,
|
|
836
|
-
const liveStallEvents = (0,
|
|
837
|
-
const controlTime = (0,
|
|
838
|
-
const [playingState, setPlayingState] = (0,
|
|
839
|
-
const [mutedState, setMutedState] = (0,
|
|
840
|
-
const [durationState, setDurationState] = (0,
|
|
841
|
-
const [currentTimeState, setCurrentTimeState] = (0,
|
|
842
|
-
const [isFullscreen, setIsFullscreen] = (0,
|
|
843
|
-
const [showControl, setControlVisible] = (0,
|
|
844
|
-
const [errorState, setErrorState] = (0,
|
|
845
|
-
const [reloadToken, setReloadToken] = (0,
|
|
833
|
+
const videoRef = (0, import_react3.useRef)(null);
|
|
834
|
+
const hlsRef = (0, import_react3.useRef)(null);
|
|
835
|
+
const containerRef = (0, import_react3.useRef)(null);
|
|
836
|
+
const netRetryCount = (0, import_react3.useRef)(0);
|
|
837
|
+
const mediaRecoverCount = (0, import_react3.useRef)(0);
|
|
838
|
+
const fatalReloadCount = (0, import_react3.useRef)(0);
|
|
839
|
+
const reloadTimer = (0, import_react3.useRef)(null);
|
|
840
|
+
const stalledNudgeTimer = (0, import_react3.useRef)(null);
|
|
841
|
+
const liveStabilityMode = (0, import_react3.useRef)(false);
|
|
842
|
+
const liveStallEvents = (0, import_react3.useRef)([]);
|
|
843
|
+
const controlTime = (0, import_react3.useRef)(null);
|
|
844
|
+
const [playingState, setPlayingState] = (0, import_react3.useState)(!!defaultPlaying);
|
|
845
|
+
const [mutedState, setMutedState] = (0, import_react3.useState)(!!defaultMuted);
|
|
846
|
+
const [durationState, setDurationState] = (0, import_react3.useState)(0);
|
|
847
|
+
const [currentTimeState, setCurrentTimeState] = (0, import_react3.useState)(0);
|
|
848
|
+
const [isFullscreen, setIsFullscreen] = (0, import_react3.useState)(false);
|
|
849
|
+
const [showControl, setControlVisible] = (0, import_react3.useState)(true);
|
|
850
|
+
const [errorState, setErrorState] = (0, import_react3.useState)(null);
|
|
851
|
+
const [reloadToken, setReloadToken] = (0, import_react3.useState)(0);
|
|
846
852
|
const playing = playingProp != null ? playingProp : playingState;
|
|
847
853
|
const muted = mutedProp != null ? mutedProp : mutedState;
|
|
848
854
|
const duration = durationProp != null ? durationProp : durationState;
|
|
849
855
|
const currentTime = currentTimeProp != null ? currentTimeProp : currentTimeState;
|
|
850
856
|
const fullscreenAllowed = active != null ? active : true;
|
|
851
|
-
const setTimeD = (0,
|
|
857
|
+
const setTimeD = (0, import_react3.useRef)(
|
|
852
858
|
createThrottledNumberFn((value) => {
|
|
853
859
|
const v = videoRef.current;
|
|
854
860
|
if (!v) return;
|
|
855
861
|
v.currentTime = value;
|
|
856
862
|
}, 30)
|
|
857
863
|
);
|
|
858
|
-
const clearTimers = (0,
|
|
864
|
+
const clearTimers = (0, import_react3.useCallback)(() => {
|
|
859
865
|
if (reloadTimer.current) {
|
|
860
866
|
clearTimeout(reloadTimer.current);
|
|
861
867
|
reloadTimer.current = null;
|
|
@@ -869,14 +875,14 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
869
875
|
controlTime.current = null;
|
|
870
876
|
}
|
|
871
877
|
}, []);
|
|
872
|
-
const setNextPlaying = (0,
|
|
878
|
+
const setNextPlaying = (0, import_react3.useCallback)(
|
|
873
879
|
(value) => {
|
|
874
880
|
if (playingProp === void 0) setPlayingState(value);
|
|
875
881
|
onPlayingChange == null ? void 0 : onPlayingChange(value);
|
|
876
882
|
},
|
|
877
883
|
[onPlayingChange, playingProp]
|
|
878
884
|
);
|
|
879
|
-
const setNextMuted = (0,
|
|
885
|
+
const setNextMuted = (0, import_react3.useCallback)(
|
|
880
886
|
(value) => {
|
|
881
887
|
if (mutedProp === void 0) setMutedState(value);
|
|
882
888
|
const el = videoRef.current;
|
|
@@ -885,10 +891,10 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
885
891
|
},
|
|
886
892
|
[mutedProp, onMutedChange]
|
|
887
893
|
);
|
|
888
|
-
const clearErrorState = (0,
|
|
894
|
+
const clearErrorState = (0, import_react3.useCallback)(() => {
|
|
889
895
|
setErrorState((prev) => prev ? null : prev);
|
|
890
896
|
}, []);
|
|
891
|
-
const reportError = (0,
|
|
897
|
+
const reportError = (0, import_react3.useCallback)(
|
|
892
898
|
(error, data, message = messages.defaultError) => {
|
|
893
899
|
const details = formatPlaybackErrorDetails(error, data);
|
|
894
900
|
const code = getPlaybackErrorCodeText(error);
|
|
@@ -905,27 +911,27 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
905
911
|
},
|
|
906
912
|
[messages.defaultError, onPlaybackError, setNextPlaying]
|
|
907
913
|
);
|
|
908
|
-
const notifyActiveChange = (0,
|
|
914
|
+
const notifyActiveChange = (0, import_react3.useCallback)(
|
|
909
915
|
(video, reason) => {
|
|
910
916
|
onActiveChange == null ? void 0 : onActiveChange({ video, reason });
|
|
911
917
|
},
|
|
912
918
|
[onActiveChange]
|
|
913
919
|
);
|
|
914
|
-
const onTime = (0,
|
|
920
|
+
const onTime = (0, import_react3.useCallback)(() => {
|
|
915
921
|
const el = videoRef.current;
|
|
916
922
|
if (!el) return;
|
|
917
923
|
const nextTime = Number.isFinite(el.currentTime) ? el.currentTime : 0;
|
|
918
924
|
if (currentTimeProp === void 0) setCurrentTimeState(nextTime);
|
|
919
925
|
onTimeChange == null ? void 0 : onTimeChange(nextTime, el);
|
|
920
926
|
}, [currentTimeProp, onTimeChange]);
|
|
921
|
-
const onDur = (0,
|
|
927
|
+
const onDur = (0, import_react3.useCallback)(() => {
|
|
922
928
|
const el = videoRef.current;
|
|
923
929
|
if (!el) return;
|
|
924
930
|
const nextDuration = Number.isFinite(el.duration) ? el.duration : 0;
|
|
925
931
|
if (durationProp === void 0) setDurationState(nextDuration);
|
|
926
932
|
onDurationChange == null ? void 0 : onDurationChange(nextDuration, el);
|
|
927
933
|
}, [durationProp, onDurationChange]);
|
|
928
|
-
const setVideoEl = (0,
|
|
934
|
+
const setVideoEl = (0, import_react3.useCallback)(
|
|
929
935
|
(el) => {
|
|
930
936
|
const prev = videoRef.current;
|
|
931
937
|
if (prev === el) return;
|
|
@@ -944,7 +950,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
944
950
|
},
|
|
945
951
|
[externalVideoRef, muted, notifyActiveChange, onDur, onTime, onVideoRefChange]
|
|
946
952
|
);
|
|
947
|
-
const pauseOtherVideos = (0,
|
|
953
|
+
const pauseOtherVideos = (0, import_react3.useCallback)(
|
|
948
954
|
(el) => {
|
|
949
955
|
if (!exclusivePlayback) return;
|
|
950
956
|
if (typeof exclusivePlayback === "object") {
|
|
@@ -958,7 +964,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
958
964
|
},
|
|
959
965
|
[exclusivePlayback]
|
|
960
966
|
);
|
|
961
|
-
const playAction = (0,
|
|
967
|
+
const playAction = (0, import_react3.useCallback)(async () => {
|
|
962
968
|
const el = videoRef.current;
|
|
963
969
|
if (!el) return;
|
|
964
970
|
pauseOtherVideos(el);
|
|
@@ -984,14 +990,14 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
984
990
|
}
|
|
985
991
|
}
|
|
986
992
|
}, [clearErrorState, messages.playFailed, notifyActiveChange, pauseOtherVideos, reportError, scrollTo, setNextPlaying]);
|
|
987
|
-
const pauseAction = (0,
|
|
993
|
+
const pauseAction = (0, import_react3.useCallback)(() => {
|
|
988
994
|
const el = videoRef.current;
|
|
989
995
|
if (!el) return;
|
|
990
996
|
el.pause();
|
|
991
997
|
setNextPlaying(false);
|
|
992
998
|
notifyActiveChange(el, "pause");
|
|
993
999
|
}, [notifyActiveChange, setNextPlaying]);
|
|
994
|
-
const seekSetTime = (0,
|
|
1000
|
+
const seekSetTime = (0, import_react3.useCallback)(
|
|
995
1001
|
(value) => {
|
|
996
1002
|
const el = videoRef.current;
|
|
997
1003
|
if (!el) return;
|
|
@@ -1002,7 +1008,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1002
1008
|
},
|
|
1003
1009
|
[currentTimeProp, duration, notifyActiveChange]
|
|
1004
1010
|
);
|
|
1005
|
-
const seekPrevAction = (0,
|
|
1011
|
+
const seekPrevAction = (0, import_react3.useCallback)(
|
|
1006
1012
|
(sec = 15) => {
|
|
1007
1013
|
const el = videoRef.current;
|
|
1008
1014
|
if (!el) return;
|
|
@@ -1010,7 +1016,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1010
1016
|
},
|
|
1011
1017
|
[seekSetTime]
|
|
1012
1018
|
);
|
|
1013
|
-
const seekNextAction = (0,
|
|
1019
|
+
const seekNextAction = (0, import_react3.useCallback)(
|
|
1014
1020
|
(sec = 15) => {
|
|
1015
1021
|
const el = videoRef.current;
|
|
1016
1022
|
if (!el) return;
|
|
@@ -1018,7 +1024,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1018
1024
|
},
|
|
1019
1025
|
[seekSetTime]
|
|
1020
1026
|
);
|
|
1021
|
-
const toggleAction = (0,
|
|
1027
|
+
const toggleAction = (0, import_react3.useCallback)(
|
|
1022
1028
|
(force) => {
|
|
1023
1029
|
const el = videoRef.current;
|
|
1024
1030
|
if (!el) return;
|
|
@@ -1030,12 +1036,12 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1030
1036
|
},
|
|
1031
1037
|
[pauseAction, playAction]
|
|
1032
1038
|
);
|
|
1033
|
-
const nudgeOnStall = (0,
|
|
1039
|
+
const nudgeOnStall = (0, import_react3.useCallback)(() => {
|
|
1034
1040
|
const v = videoRef.current;
|
|
1035
1041
|
if (!v) return;
|
|
1036
1042
|
v.currentTime = Math.max(0, v.currentTime + 0.05);
|
|
1037
1043
|
}, []);
|
|
1038
|
-
const shouldSwitchLiveToStability = (0,
|
|
1044
|
+
const shouldSwitchLiveToStability = (0, import_react3.useCallback)(() => {
|
|
1039
1045
|
if (!live || liveStabilityMode.current) return false;
|
|
1040
1046
|
const now = Date.now();
|
|
1041
1047
|
liveStallEvents.current = [...liveStallEvents.current.filter((ts) => now - ts <= LIVE_STALL_WINDOW_MS), now];
|
|
@@ -1044,7 +1050,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1044
1050
|
liveStallEvents.current = [];
|
|
1045
1051
|
return true;
|
|
1046
1052
|
}, [live]);
|
|
1047
|
-
const resolvedHlsConfig = (0,
|
|
1053
|
+
const resolvedHlsConfig = (0, import_react3.useCallback)(() => {
|
|
1048
1054
|
const modeConfig = live ? liveHlsConfig : vodHlsConfig;
|
|
1049
1055
|
const base = live ? confLiveStability : confVod;
|
|
1050
1056
|
return withCredentialsConfig(
|
|
@@ -1056,7 +1062,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1056
1062
|
hlsCredentials
|
|
1057
1063
|
);
|
|
1058
1064
|
}, [hlsConfig, hlsCredentials, live, liveHlsConfig, vodHlsConfig]);
|
|
1059
|
-
const loadVideo = (0,
|
|
1065
|
+
const loadVideo = (0, import_react3.useCallback)(
|
|
1060
1066
|
async (startAt = initialTime) => {
|
|
1061
1067
|
const startVideoRef = videoRef.current;
|
|
1062
1068
|
if (!startVideoRef) return;
|
|
@@ -1193,14 +1199,14 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1193
1199
|
videoSrc
|
|
1194
1200
|
]
|
|
1195
1201
|
);
|
|
1196
|
-
const loadVideoNative = (0,
|
|
1202
|
+
const loadVideoNative = (0, import_react3.useCallback)(() => {
|
|
1197
1203
|
const video = videoRef.current;
|
|
1198
1204
|
if (!video) return;
|
|
1199
1205
|
video.src = videoSrc;
|
|
1200
1206
|
video.currentTime = initialTime;
|
|
1201
1207
|
if (autoPlay) void playAction();
|
|
1202
1208
|
}, [autoPlay, initialTime, playAction, videoSrc]);
|
|
1203
|
-
const loadVideoHls = (0,
|
|
1209
|
+
const loadVideoHls = (0, import_react3.useCallback)(async () => {
|
|
1204
1210
|
const video = videoRef.current;
|
|
1205
1211
|
const canNativeHls = !!(video == null ? void 0 : video.canPlayType) && video.canPlayType("application/vnd.apple.mpegurl") !== "";
|
|
1206
1212
|
let HlsCtor;
|
|
@@ -1221,7 +1227,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1221
1227
|
}
|
|
1222
1228
|
reportError(null, { type: "hls", src: videoSrc, reason: "HLS is not supported in this browser" }, messages.unsupported);
|
|
1223
1229
|
}, [initialTime, loadVideo, loadVideoNative, messages.streamLoadFailed, messages.unsupported, reportError, videoSrc]);
|
|
1224
|
-
const destroy = (0,
|
|
1230
|
+
const destroy = (0, import_react3.useCallback)(() => {
|
|
1225
1231
|
clearTimers();
|
|
1226
1232
|
if (hlsRef.current) {
|
|
1227
1233
|
hlsRef.current.destroy();
|
|
@@ -1252,12 +1258,12 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1252
1258
|
onVideoRefChange,
|
|
1253
1259
|
setNextPlaying
|
|
1254
1260
|
]);
|
|
1255
|
-
const videoClickHandler = (0,
|
|
1261
|
+
const videoClickHandler = (0, import_react3.useCallback)(() => {
|
|
1256
1262
|
if (!handleClick) return;
|
|
1257
1263
|
if (playOnClick) toggleAction();
|
|
1258
1264
|
onVideoClick == null ? void 0 : onVideoClick();
|
|
1259
1265
|
}, [handleClick, onVideoClick, playOnClick, toggleAction]);
|
|
1260
|
-
const fullScreenAction = (0,
|
|
1266
|
+
const fullScreenAction = (0, import_react3.useCallback)(() => {
|
|
1261
1267
|
if (typeof document === "undefined") return;
|
|
1262
1268
|
const doc = document;
|
|
1263
1269
|
const videoEl = videoRef.current;
|
|
@@ -1282,36 +1288,36 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1282
1288
|
else if (videoEl.webkitEnterFullscreen) void videoEl.webkitEnterFullscreen();
|
|
1283
1289
|
}
|
|
1284
1290
|
}, [fullscreenAllowed]);
|
|
1285
|
-
const videoDbClickHandler = (0,
|
|
1291
|
+
const videoDbClickHandler = (0, import_react3.useCallback)(() => {
|
|
1286
1292
|
if (!handleClick) return;
|
|
1287
1293
|
fullScreenAction();
|
|
1288
1294
|
onVideoDoubleClick == null ? void 0 : onVideoDoubleClick();
|
|
1289
1295
|
}, [fullScreenAction, handleClick, onVideoDoubleClick]);
|
|
1290
|
-
const showClickHandler = (0,
|
|
1296
|
+
const showClickHandler = (0, import_react3.useCallback)(() => {
|
|
1291
1297
|
setControlVisible((st) => !st);
|
|
1292
1298
|
}, []);
|
|
1293
|
-
const retryLoadHandler = (0,
|
|
1299
|
+
const retryLoadHandler = (0, import_react3.useCallback)(() => {
|
|
1294
1300
|
clearErrorState();
|
|
1295
1301
|
setReloadToken((value) => value + 1);
|
|
1296
1302
|
}, [clearErrorState]);
|
|
1297
|
-
const videoErrorHandler = (0,
|
|
1303
|
+
const videoErrorHandler = (0, import_react3.useCallback)(() => {
|
|
1298
1304
|
const video = videoRef.current;
|
|
1299
1305
|
const error = video == null ? void 0 : video.error;
|
|
1300
1306
|
const src = (video == null ? void 0 : video.currentSrc) || videoSrc;
|
|
1301
1307
|
if (hlsRef.current && src.startsWith("blob:")) return;
|
|
1302
1308
|
reportError(error, { type: "native", src }, getNativeVideoErrorMessage(error, messages));
|
|
1303
1309
|
}, [messages, reportError, videoSrc]);
|
|
1304
|
-
const videoLoadedHandler = (0,
|
|
1310
|
+
const videoLoadedHandler = (0, import_react3.useCallback)(() => {
|
|
1305
1311
|
clearErrorState();
|
|
1306
1312
|
}, [clearErrorState]);
|
|
1307
|
-
const mouseMoveHandler = (0,
|
|
1313
|
+
const mouseMoveHandler = (0, import_react3.useCallback)(() => {
|
|
1308
1314
|
if (controlTime.current) clearTimeout(controlTime.current);
|
|
1309
1315
|
setControlVisible(true);
|
|
1310
1316
|
controlTime.current = setTimeout(() => {
|
|
1311
1317
|
setControlVisible(false);
|
|
1312
1318
|
}, 1e3 * 10);
|
|
1313
1319
|
}, []);
|
|
1314
|
-
(0,
|
|
1320
|
+
(0, import_react3.useImperativeHandle)(
|
|
1315
1321
|
ref,
|
|
1316
1322
|
() => ({
|
|
1317
1323
|
play: playAction,
|
|
@@ -1322,24 +1328,24 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1322
1328
|
}),
|
|
1323
1329
|
[fullScreenAction, pauseAction, playAction, seekSetTime]
|
|
1324
1330
|
);
|
|
1325
|
-
(0,
|
|
1331
|
+
(0, import_react3.useEffect)(() => {
|
|
1326
1332
|
const el = videoRef.current;
|
|
1327
1333
|
if (!el) return;
|
|
1328
1334
|
el.muted = muted;
|
|
1329
1335
|
}, [muted]);
|
|
1330
|
-
(0,
|
|
1336
|
+
(0, import_react3.useEffect)(() => {
|
|
1331
1337
|
if (playingProp === void 0) return;
|
|
1332
1338
|
if (!canAttemptPlayback(videoRef.current)) return;
|
|
1333
1339
|
if (playingProp) void playAction();
|
|
1334
1340
|
else pauseAction();
|
|
1335
1341
|
}, [pauseAction, playAction, playingProp]);
|
|
1336
|
-
(0,
|
|
1342
|
+
(0, import_react3.useEffect)(() => {
|
|
1337
1343
|
const el = videoRef.current;
|
|
1338
1344
|
if (!el || currentTimeProp === void 0) return;
|
|
1339
1345
|
if (Math.abs(el.currentTime - currentTimeProp) < 0.25) return;
|
|
1340
1346
|
el.currentTime = clampTime(currentTimeProp, duration);
|
|
1341
1347
|
}, [currentTimeProp, duration]);
|
|
1342
|
-
(0,
|
|
1348
|
+
(0, import_react3.useEffect)(() => {
|
|
1343
1349
|
if (!videoRef.current) return;
|
|
1344
1350
|
clearErrorState();
|
|
1345
1351
|
fatalReloadCount.current = 0;
|
|
@@ -1375,12 +1381,27 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1375
1381
|
type,
|
|
1376
1382
|
videoSrc
|
|
1377
1383
|
]);
|
|
1378
|
-
(0,
|
|
1384
|
+
(0, import_react3.useEffect)(() => {
|
|
1379
1385
|
if (!autoPlay) return;
|
|
1380
1386
|
if (!canAttemptPlayback(videoRef.current)) return;
|
|
1381
1387
|
void playAction();
|
|
1382
1388
|
}, [autoPlay, playAction]);
|
|
1383
|
-
(0,
|
|
1389
|
+
(0, import_react3.useEffect)(() => {
|
|
1390
|
+
if (typeof document === "undefined") return;
|
|
1391
|
+
const handleKeyDown = (event) => {
|
|
1392
|
+
if (event.code !== "KeyF") return;
|
|
1393
|
+
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
|
|
1394
|
+
if (active !== true) return;
|
|
1395
|
+
if (isEditableKeyTarget(event.target)) return;
|
|
1396
|
+
event.preventDefault();
|
|
1397
|
+
fullScreenAction();
|
|
1398
|
+
};
|
|
1399
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
1400
|
+
return () => {
|
|
1401
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
1402
|
+
};
|
|
1403
|
+
}, [active, fullScreenAction]);
|
|
1404
|
+
(0, import_react3.useEffect)(() => {
|
|
1384
1405
|
if (typeof document === "undefined") return;
|
|
1385
1406
|
const doc = document;
|
|
1386
1407
|
const handleFsChange = () => {
|
|
@@ -1398,7 +1419,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1398
1419
|
document.removeEventListener("MSFullscreenChange", handleFsChange);
|
|
1399
1420
|
};
|
|
1400
1421
|
}, []);
|
|
1401
|
-
(0,
|
|
1422
|
+
(0, import_react3.useEffect)(() => {
|
|
1402
1423
|
return () => {
|
|
1403
1424
|
setTimeD.current.cancel();
|
|
1404
1425
|
destroy();
|
|
@@ -1483,7 +1504,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1483
1504
|
}
|
|
1484
1505
|
);
|
|
1485
1506
|
};
|
|
1486
|
-
var VideoPlayer = (0,
|
|
1507
|
+
var VideoPlayer = (0, import_react3.memo)((0, import_react3.forwardRef)(VideoPlayerBase));
|
|
1487
1508
|
var VideoPlayer_default = VideoPlayer;
|
|
1488
1509
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1489
1510
|
0 && (module.exports = {
|
package/dist/index.js
CHANGED
|
@@ -6,10 +6,13 @@ import {
|
|
|
6
6
|
useEffect,
|
|
7
7
|
useImperativeHandle,
|
|
8
8
|
useMemo as useMemo2,
|
|
9
|
-
useRef,
|
|
9
|
+
useRef as useRef2,
|
|
10
10
|
useState
|
|
11
11
|
} from "react";
|
|
12
12
|
|
|
13
|
+
// src/controls.tsx
|
|
14
|
+
import { useRef } from "react";
|
|
15
|
+
|
|
13
16
|
// src/styles.ts
|
|
14
17
|
import { css, styled } from "styled-components";
|
|
15
18
|
var VideoPlayerControlStyles = styled.div`
|
|
@@ -257,6 +260,13 @@ var VideoPlayerStyles = styled.div`
|
|
|
257
260
|
}
|
|
258
261
|
}
|
|
259
262
|
|
|
263
|
+
&:hover {
|
|
264
|
+
.video-right-bar {
|
|
265
|
+
background: rgba(0, 0, 0, 0.1);
|
|
266
|
+
opacity: 1;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
260
270
|
${(props) => (props.$showControl || props.$alwaysShowSegments) && css`
|
|
261
271
|
.video-right-bar {
|
|
262
272
|
background: rgba(0, 0, 0, 0.1);
|
|
@@ -391,6 +401,7 @@ var createThrottledNumberFn = (fn, waitMs) => {
|
|
|
391
401
|
// src/controls.tsx
|
|
392
402
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
393
403
|
var SeekSlider = ({ playAction, duration, currentTime, seekSetTime }) => {
|
|
404
|
+
const ref = useRef(null);
|
|
394
405
|
const clickHandler = (e) => {
|
|
395
406
|
e.preventDefault();
|
|
396
407
|
e.stopPropagation();
|
|
@@ -399,10 +410,14 @@ var SeekSlider = ({ playAction, duration, currentTime, seekSetTime }) => {
|
|
|
399
410
|
const safeCurrentTime = Math.max(0, Math.min(Number.isFinite(currentTime) ? currentTime : 0, safeDuration || Infinity));
|
|
400
411
|
const completeChange = () => {
|
|
401
412
|
void playAction();
|
|
413
|
+
if (ref.current) {
|
|
414
|
+
ref.current.blur();
|
|
415
|
+
}
|
|
402
416
|
};
|
|
403
417
|
return /* @__PURE__ */ jsx(SeekSliderStyled, { onClick: clickHandler, className: "seek-slider", children: /* @__PURE__ */ jsx(
|
|
404
418
|
"input",
|
|
405
419
|
{
|
|
420
|
+
ref,
|
|
406
421
|
"aria-label": "Seek",
|
|
407
422
|
className: "seek-range",
|
|
408
423
|
disabled: safeDuration <= 0,
|
|
@@ -504,19 +519,6 @@ var VideoPlayerControls = (props) => {
|
|
|
504
519
|
} = props;
|
|
505
520
|
const [, isMobile] = useWindowWidth();
|
|
506
521
|
if (variant === "none") return null;
|
|
507
|
-
if (variant === "tiny") {
|
|
508
|
-
return /* @__PURE__ */ jsx(VideoPlayerControlStyles, { $tiny: true, $isMobile: isMobile, onClick: stopControlClick, $showControl: showControl, children: /* @__PURE__ */ jsxs("div", { className: "video-player-control-row", children: [
|
|
509
|
-
/* @__PURE__ */ jsx("div", { className: "full" }),
|
|
510
|
-
/* @__PURE__ */ jsx(SeekSlider, { playAction, duration, currentTime, seekSetTime })
|
|
511
|
-
] }) });
|
|
512
|
-
}
|
|
513
|
-
if (variant === "fullscreen-only") {
|
|
514
|
-
return /* @__PURE__ */ jsx(VideoPlayerControlStyles, { $isMobile: isMobile, onClick: stopControlClick, $showControl: showControl, children: /* @__PURE__ */ jsxs("div", { className: "video-player-control-row", children: [
|
|
515
|
-
/* @__PURE__ */ jsx("div", { className: "full" }),
|
|
516
|
-
/* @__PURE__ */ jsx(ControlButton, { icon: muted ? "mute" : "sound", label: muted ? "Unmute" : "Mute", onClick: () => onMutedChange(!muted) }),
|
|
517
|
-
/* @__PURE__ */ jsx(ControlButton, { disabled: !fullscreenAllowed, icon: "fullscreen", label: "Fullscreen", onClick: fullScreenAction })
|
|
518
|
-
] }) });
|
|
519
|
-
}
|
|
520
522
|
return /* @__PURE__ */ jsx(VideoPlayerControlStyles, { $isMobile: isMobile, onClick: stopControlClick, $showControl: showControl, children: /* @__PURE__ */ jsxs("div", { className: "video-player-control-row", children: [
|
|
521
523
|
playing ? /* @__PURE__ */ jsx(ControlButton, { icon: "pause", label: "Pause", onClick: pauseAction }) : /* @__PURE__ */ jsx(ControlButton, { icon: "play", label: "Play", onClick: playAction }),
|
|
522
524
|
/* @__PURE__ */ jsx(ControlButton, { icon: "back", label: "Back 15 seconds", onClick: () => seekPrevAction() }),
|
|
@@ -741,6 +743,10 @@ var assignRef = (ref, value) => {
|
|
|
741
743
|
}
|
|
742
744
|
ref.current = value;
|
|
743
745
|
};
|
|
746
|
+
var isEditableKeyTarget = (target) => {
|
|
747
|
+
if (!(target instanceof HTMLElement)) return false;
|
|
748
|
+
return target.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName);
|
|
749
|
+
};
|
|
744
750
|
var VideoPlayerBase = (props, ref) => {
|
|
745
751
|
const {
|
|
746
752
|
controlsVariant = "none",
|
|
@@ -795,17 +801,17 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
795
801
|
const videoSrc = rawVideoSrc.replaceAll(" ", "%20").replaceAll("#", "%23");
|
|
796
802
|
const messages = useMemo2(() => ({ ...defaultMessages, ...messagesProp }), [messagesProp]);
|
|
797
803
|
const [, isMobile, mobileType] = useWindowWidth();
|
|
798
|
-
const videoRef =
|
|
799
|
-
const hlsRef =
|
|
800
|
-
const containerRef =
|
|
801
|
-
const netRetryCount =
|
|
802
|
-
const mediaRecoverCount =
|
|
803
|
-
const fatalReloadCount =
|
|
804
|
-
const reloadTimer =
|
|
805
|
-
const stalledNudgeTimer =
|
|
806
|
-
const liveStabilityMode =
|
|
807
|
-
const liveStallEvents =
|
|
808
|
-
const controlTime =
|
|
804
|
+
const videoRef = useRef2(null);
|
|
805
|
+
const hlsRef = useRef2(null);
|
|
806
|
+
const containerRef = useRef2(null);
|
|
807
|
+
const netRetryCount = useRef2(0);
|
|
808
|
+
const mediaRecoverCount = useRef2(0);
|
|
809
|
+
const fatalReloadCount = useRef2(0);
|
|
810
|
+
const reloadTimer = useRef2(null);
|
|
811
|
+
const stalledNudgeTimer = useRef2(null);
|
|
812
|
+
const liveStabilityMode = useRef2(false);
|
|
813
|
+
const liveStallEvents = useRef2([]);
|
|
814
|
+
const controlTime = useRef2(null);
|
|
809
815
|
const [playingState, setPlayingState] = useState(!!defaultPlaying);
|
|
810
816
|
const [mutedState, setMutedState] = useState(!!defaultMuted);
|
|
811
817
|
const [durationState, setDurationState] = useState(0);
|
|
@@ -819,7 +825,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
819
825
|
const duration = durationProp != null ? durationProp : durationState;
|
|
820
826
|
const currentTime = currentTimeProp != null ? currentTimeProp : currentTimeState;
|
|
821
827
|
const fullscreenAllowed = active != null ? active : true;
|
|
822
|
-
const setTimeD =
|
|
828
|
+
const setTimeD = useRef2(
|
|
823
829
|
createThrottledNumberFn((value) => {
|
|
824
830
|
const v = videoRef.current;
|
|
825
831
|
if (!v) return;
|
|
@@ -1351,6 +1357,21 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1351
1357
|
if (!canAttemptPlayback(videoRef.current)) return;
|
|
1352
1358
|
void playAction();
|
|
1353
1359
|
}, [autoPlay, playAction]);
|
|
1360
|
+
useEffect(() => {
|
|
1361
|
+
if (typeof document === "undefined") return;
|
|
1362
|
+
const handleKeyDown = (event) => {
|
|
1363
|
+
if (event.code !== "KeyF") return;
|
|
1364
|
+
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
|
|
1365
|
+
if (active !== true) return;
|
|
1366
|
+
if (isEditableKeyTarget(event.target)) return;
|
|
1367
|
+
event.preventDefault();
|
|
1368
|
+
fullScreenAction();
|
|
1369
|
+
};
|
|
1370
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
1371
|
+
return () => {
|
|
1372
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
1373
|
+
};
|
|
1374
|
+
}, [active, fullScreenAction]);
|
|
1354
1375
|
useEffect(() => {
|
|
1355
1376
|
if (typeof document === "undefined") return;
|
|
1356
1377
|
const doc = document;
|