@nikelroot/video-player 0.1.5 → 0.1.6

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/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() }),
@@ -822,40 +824,40 @@ var VideoPlayerBase = (props, ref) => {
822
824
  ...videoProps
823
825
  } = props;
824
826
  const videoSrc = rawVideoSrc.replaceAll(" ", "%20").replaceAll("#", "%23");
825
- const messages = (0, import_react2.useMemo)(() => ({ ...defaultMessages, ...messagesProp }), [messagesProp]);
827
+ const messages = (0, import_react3.useMemo)(() => ({ ...defaultMessages, ...messagesProp }), [messagesProp]);
826
828
  const [, isMobile, mobileType] = useWindowWidth();
827
- const videoRef = (0, import_react2.useRef)(null);
828
- const hlsRef = (0, import_react2.useRef)(null);
829
- const containerRef = (0, import_react2.useRef)(null);
830
- const netRetryCount = (0, import_react2.useRef)(0);
831
- const mediaRecoverCount = (0, import_react2.useRef)(0);
832
- const fatalReloadCount = (0, import_react2.useRef)(0);
833
- const reloadTimer = (0, import_react2.useRef)(null);
834
- const stalledNudgeTimer = (0, import_react2.useRef)(null);
835
- const liveStabilityMode = (0, import_react2.useRef)(false);
836
- const liveStallEvents = (0, import_react2.useRef)([]);
837
- const controlTime = (0, import_react2.useRef)(null);
838
- const [playingState, setPlayingState] = (0, import_react2.useState)(!!defaultPlaying);
839
- const [mutedState, setMutedState] = (0, import_react2.useState)(!!defaultMuted);
840
- const [durationState, setDurationState] = (0, import_react2.useState)(0);
841
- const [currentTimeState, setCurrentTimeState] = (0, import_react2.useState)(0);
842
- const [isFullscreen, setIsFullscreen] = (0, import_react2.useState)(false);
843
- const [showControl, setControlVisible] = (0, import_react2.useState)(true);
844
- const [errorState, setErrorState] = (0, import_react2.useState)(null);
845
- const [reloadToken, setReloadToken] = (0, import_react2.useState)(0);
829
+ const videoRef = (0, import_react3.useRef)(null);
830
+ const hlsRef = (0, import_react3.useRef)(null);
831
+ const containerRef = (0, import_react3.useRef)(null);
832
+ const netRetryCount = (0, import_react3.useRef)(0);
833
+ const mediaRecoverCount = (0, import_react3.useRef)(0);
834
+ const fatalReloadCount = (0, import_react3.useRef)(0);
835
+ const reloadTimer = (0, import_react3.useRef)(null);
836
+ const stalledNudgeTimer = (0, import_react3.useRef)(null);
837
+ const liveStabilityMode = (0, import_react3.useRef)(false);
838
+ const liveStallEvents = (0, import_react3.useRef)([]);
839
+ const controlTime = (0, import_react3.useRef)(null);
840
+ const [playingState, setPlayingState] = (0, import_react3.useState)(!!defaultPlaying);
841
+ const [mutedState, setMutedState] = (0, import_react3.useState)(!!defaultMuted);
842
+ const [durationState, setDurationState] = (0, import_react3.useState)(0);
843
+ const [currentTimeState, setCurrentTimeState] = (0, import_react3.useState)(0);
844
+ const [isFullscreen, setIsFullscreen] = (0, import_react3.useState)(false);
845
+ const [showControl, setControlVisible] = (0, import_react3.useState)(true);
846
+ const [errorState, setErrorState] = (0, import_react3.useState)(null);
847
+ const [reloadToken, setReloadToken] = (0, import_react3.useState)(0);
846
848
  const playing = playingProp != null ? playingProp : playingState;
847
849
  const muted = mutedProp != null ? mutedProp : mutedState;
848
850
  const duration = durationProp != null ? durationProp : durationState;
849
851
  const currentTime = currentTimeProp != null ? currentTimeProp : currentTimeState;
850
852
  const fullscreenAllowed = active != null ? active : true;
851
- const setTimeD = (0, import_react2.useRef)(
853
+ const setTimeD = (0, import_react3.useRef)(
852
854
  createThrottledNumberFn((value) => {
853
855
  const v = videoRef.current;
854
856
  if (!v) return;
855
857
  v.currentTime = value;
856
858
  }, 30)
857
859
  );
858
- const clearTimers = (0, import_react2.useCallback)(() => {
860
+ const clearTimers = (0, import_react3.useCallback)(() => {
859
861
  if (reloadTimer.current) {
860
862
  clearTimeout(reloadTimer.current);
861
863
  reloadTimer.current = null;
@@ -869,14 +871,14 @@ var VideoPlayerBase = (props, ref) => {
869
871
  controlTime.current = null;
870
872
  }
871
873
  }, []);
872
- const setNextPlaying = (0, import_react2.useCallback)(
874
+ const setNextPlaying = (0, import_react3.useCallback)(
873
875
  (value) => {
874
876
  if (playingProp === void 0) setPlayingState(value);
875
877
  onPlayingChange == null ? void 0 : onPlayingChange(value);
876
878
  },
877
879
  [onPlayingChange, playingProp]
878
880
  );
879
- const setNextMuted = (0, import_react2.useCallback)(
881
+ const setNextMuted = (0, import_react3.useCallback)(
880
882
  (value) => {
881
883
  if (mutedProp === void 0) setMutedState(value);
882
884
  const el = videoRef.current;
@@ -885,10 +887,10 @@ var VideoPlayerBase = (props, ref) => {
885
887
  },
886
888
  [mutedProp, onMutedChange]
887
889
  );
888
- const clearErrorState = (0, import_react2.useCallback)(() => {
890
+ const clearErrorState = (0, import_react3.useCallback)(() => {
889
891
  setErrorState((prev) => prev ? null : prev);
890
892
  }, []);
891
- const reportError = (0, import_react2.useCallback)(
893
+ const reportError = (0, import_react3.useCallback)(
892
894
  (error, data, message = messages.defaultError) => {
893
895
  const details = formatPlaybackErrorDetails(error, data);
894
896
  const code = getPlaybackErrorCodeText(error);
@@ -905,27 +907,27 @@ var VideoPlayerBase = (props, ref) => {
905
907
  },
906
908
  [messages.defaultError, onPlaybackError, setNextPlaying]
907
909
  );
908
- const notifyActiveChange = (0, import_react2.useCallback)(
910
+ const notifyActiveChange = (0, import_react3.useCallback)(
909
911
  (video, reason) => {
910
912
  onActiveChange == null ? void 0 : onActiveChange({ video, reason });
911
913
  },
912
914
  [onActiveChange]
913
915
  );
914
- const onTime = (0, import_react2.useCallback)(() => {
916
+ const onTime = (0, import_react3.useCallback)(() => {
915
917
  const el = videoRef.current;
916
918
  if (!el) return;
917
919
  const nextTime = Number.isFinite(el.currentTime) ? el.currentTime : 0;
918
920
  if (currentTimeProp === void 0) setCurrentTimeState(nextTime);
919
921
  onTimeChange == null ? void 0 : onTimeChange(nextTime, el);
920
922
  }, [currentTimeProp, onTimeChange]);
921
- const onDur = (0, import_react2.useCallback)(() => {
923
+ const onDur = (0, import_react3.useCallback)(() => {
922
924
  const el = videoRef.current;
923
925
  if (!el) return;
924
926
  const nextDuration = Number.isFinite(el.duration) ? el.duration : 0;
925
927
  if (durationProp === void 0) setDurationState(nextDuration);
926
928
  onDurationChange == null ? void 0 : onDurationChange(nextDuration, el);
927
929
  }, [durationProp, onDurationChange]);
928
- const setVideoEl = (0, import_react2.useCallback)(
930
+ const setVideoEl = (0, import_react3.useCallback)(
929
931
  (el) => {
930
932
  const prev = videoRef.current;
931
933
  if (prev === el) return;
@@ -944,7 +946,7 @@ var VideoPlayerBase = (props, ref) => {
944
946
  },
945
947
  [externalVideoRef, muted, notifyActiveChange, onDur, onTime, onVideoRefChange]
946
948
  );
947
- const pauseOtherVideos = (0, import_react2.useCallback)(
949
+ const pauseOtherVideos = (0, import_react3.useCallback)(
948
950
  (el) => {
949
951
  if (!exclusivePlayback) return;
950
952
  if (typeof exclusivePlayback === "object") {
@@ -958,7 +960,7 @@ var VideoPlayerBase = (props, ref) => {
958
960
  },
959
961
  [exclusivePlayback]
960
962
  );
961
- const playAction = (0, import_react2.useCallback)(async () => {
963
+ const playAction = (0, import_react3.useCallback)(async () => {
962
964
  const el = videoRef.current;
963
965
  if (!el) return;
964
966
  pauseOtherVideos(el);
@@ -984,14 +986,14 @@ var VideoPlayerBase = (props, ref) => {
984
986
  }
985
987
  }
986
988
  }, [clearErrorState, messages.playFailed, notifyActiveChange, pauseOtherVideos, reportError, scrollTo, setNextPlaying]);
987
- const pauseAction = (0, import_react2.useCallback)(() => {
989
+ const pauseAction = (0, import_react3.useCallback)(() => {
988
990
  const el = videoRef.current;
989
991
  if (!el) return;
990
992
  el.pause();
991
993
  setNextPlaying(false);
992
994
  notifyActiveChange(el, "pause");
993
995
  }, [notifyActiveChange, setNextPlaying]);
994
- const seekSetTime = (0, import_react2.useCallback)(
996
+ const seekSetTime = (0, import_react3.useCallback)(
995
997
  (value) => {
996
998
  const el = videoRef.current;
997
999
  if (!el) return;
@@ -1002,7 +1004,7 @@ var VideoPlayerBase = (props, ref) => {
1002
1004
  },
1003
1005
  [currentTimeProp, duration, notifyActiveChange]
1004
1006
  );
1005
- const seekPrevAction = (0, import_react2.useCallback)(
1007
+ const seekPrevAction = (0, import_react3.useCallback)(
1006
1008
  (sec = 15) => {
1007
1009
  const el = videoRef.current;
1008
1010
  if (!el) return;
@@ -1010,7 +1012,7 @@ var VideoPlayerBase = (props, ref) => {
1010
1012
  },
1011
1013
  [seekSetTime]
1012
1014
  );
1013
- const seekNextAction = (0, import_react2.useCallback)(
1015
+ const seekNextAction = (0, import_react3.useCallback)(
1014
1016
  (sec = 15) => {
1015
1017
  const el = videoRef.current;
1016
1018
  if (!el) return;
@@ -1018,7 +1020,7 @@ var VideoPlayerBase = (props, ref) => {
1018
1020
  },
1019
1021
  [seekSetTime]
1020
1022
  );
1021
- const toggleAction = (0, import_react2.useCallback)(
1023
+ const toggleAction = (0, import_react3.useCallback)(
1022
1024
  (force) => {
1023
1025
  const el = videoRef.current;
1024
1026
  if (!el) return;
@@ -1030,12 +1032,12 @@ var VideoPlayerBase = (props, ref) => {
1030
1032
  },
1031
1033
  [pauseAction, playAction]
1032
1034
  );
1033
- const nudgeOnStall = (0, import_react2.useCallback)(() => {
1035
+ const nudgeOnStall = (0, import_react3.useCallback)(() => {
1034
1036
  const v = videoRef.current;
1035
1037
  if (!v) return;
1036
1038
  v.currentTime = Math.max(0, v.currentTime + 0.05);
1037
1039
  }, []);
1038
- const shouldSwitchLiveToStability = (0, import_react2.useCallback)(() => {
1040
+ const shouldSwitchLiveToStability = (0, import_react3.useCallback)(() => {
1039
1041
  if (!live || liveStabilityMode.current) return false;
1040
1042
  const now = Date.now();
1041
1043
  liveStallEvents.current = [...liveStallEvents.current.filter((ts) => now - ts <= LIVE_STALL_WINDOW_MS), now];
@@ -1044,7 +1046,7 @@ var VideoPlayerBase = (props, ref) => {
1044
1046
  liveStallEvents.current = [];
1045
1047
  return true;
1046
1048
  }, [live]);
1047
- const resolvedHlsConfig = (0, import_react2.useCallback)(() => {
1049
+ const resolvedHlsConfig = (0, import_react3.useCallback)(() => {
1048
1050
  const modeConfig = live ? liveHlsConfig : vodHlsConfig;
1049
1051
  const base = live ? confLiveStability : confVod;
1050
1052
  return withCredentialsConfig(
@@ -1056,7 +1058,7 @@ var VideoPlayerBase = (props, ref) => {
1056
1058
  hlsCredentials
1057
1059
  );
1058
1060
  }, [hlsConfig, hlsCredentials, live, liveHlsConfig, vodHlsConfig]);
1059
- const loadVideo = (0, import_react2.useCallback)(
1061
+ const loadVideo = (0, import_react3.useCallback)(
1060
1062
  async (startAt = initialTime) => {
1061
1063
  const startVideoRef = videoRef.current;
1062
1064
  if (!startVideoRef) return;
@@ -1193,14 +1195,14 @@ var VideoPlayerBase = (props, ref) => {
1193
1195
  videoSrc
1194
1196
  ]
1195
1197
  );
1196
- const loadVideoNative = (0, import_react2.useCallback)(() => {
1198
+ const loadVideoNative = (0, import_react3.useCallback)(() => {
1197
1199
  const video = videoRef.current;
1198
1200
  if (!video) return;
1199
1201
  video.src = videoSrc;
1200
1202
  video.currentTime = initialTime;
1201
1203
  if (autoPlay) void playAction();
1202
1204
  }, [autoPlay, initialTime, playAction, videoSrc]);
1203
- const loadVideoHls = (0, import_react2.useCallback)(async () => {
1205
+ const loadVideoHls = (0, import_react3.useCallback)(async () => {
1204
1206
  const video = videoRef.current;
1205
1207
  const canNativeHls = !!(video == null ? void 0 : video.canPlayType) && video.canPlayType("application/vnd.apple.mpegurl") !== "";
1206
1208
  let HlsCtor;
@@ -1221,7 +1223,7 @@ var VideoPlayerBase = (props, ref) => {
1221
1223
  }
1222
1224
  reportError(null, { type: "hls", src: videoSrc, reason: "HLS is not supported in this browser" }, messages.unsupported);
1223
1225
  }, [initialTime, loadVideo, loadVideoNative, messages.streamLoadFailed, messages.unsupported, reportError, videoSrc]);
1224
- const destroy = (0, import_react2.useCallback)(() => {
1226
+ const destroy = (0, import_react3.useCallback)(() => {
1225
1227
  clearTimers();
1226
1228
  if (hlsRef.current) {
1227
1229
  hlsRef.current.destroy();
@@ -1252,12 +1254,12 @@ var VideoPlayerBase = (props, ref) => {
1252
1254
  onVideoRefChange,
1253
1255
  setNextPlaying
1254
1256
  ]);
1255
- const videoClickHandler = (0, import_react2.useCallback)(() => {
1257
+ const videoClickHandler = (0, import_react3.useCallback)(() => {
1256
1258
  if (!handleClick) return;
1257
1259
  if (playOnClick) toggleAction();
1258
1260
  onVideoClick == null ? void 0 : onVideoClick();
1259
1261
  }, [handleClick, onVideoClick, playOnClick, toggleAction]);
1260
- const fullScreenAction = (0, import_react2.useCallback)(() => {
1262
+ const fullScreenAction = (0, import_react3.useCallback)(() => {
1261
1263
  if (typeof document === "undefined") return;
1262
1264
  const doc = document;
1263
1265
  const videoEl = videoRef.current;
@@ -1282,36 +1284,36 @@ var VideoPlayerBase = (props, ref) => {
1282
1284
  else if (videoEl.webkitEnterFullscreen) void videoEl.webkitEnterFullscreen();
1283
1285
  }
1284
1286
  }, [fullscreenAllowed]);
1285
- const videoDbClickHandler = (0, import_react2.useCallback)(() => {
1287
+ const videoDbClickHandler = (0, import_react3.useCallback)(() => {
1286
1288
  if (!handleClick) return;
1287
1289
  fullScreenAction();
1288
1290
  onVideoDoubleClick == null ? void 0 : onVideoDoubleClick();
1289
1291
  }, [fullScreenAction, handleClick, onVideoDoubleClick]);
1290
- const showClickHandler = (0, import_react2.useCallback)(() => {
1292
+ const showClickHandler = (0, import_react3.useCallback)(() => {
1291
1293
  setControlVisible((st) => !st);
1292
1294
  }, []);
1293
- const retryLoadHandler = (0, import_react2.useCallback)(() => {
1295
+ const retryLoadHandler = (0, import_react3.useCallback)(() => {
1294
1296
  clearErrorState();
1295
1297
  setReloadToken((value) => value + 1);
1296
1298
  }, [clearErrorState]);
1297
- const videoErrorHandler = (0, import_react2.useCallback)(() => {
1299
+ const videoErrorHandler = (0, import_react3.useCallback)(() => {
1298
1300
  const video = videoRef.current;
1299
1301
  const error = video == null ? void 0 : video.error;
1300
1302
  const src = (video == null ? void 0 : video.currentSrc) || videoSrc;
1301
1303
  if (hlsRef.current && src.startsWith("blob:")) return;
1302
1304
  reportError(error, { type: "native", src }, getNativeVideoErrorMessage(error, messages));
1303
1305
  }, [messages, reportError, videoSrc]);
1304
- const videoLoadedHandler = (0, import_react2.useCallback)(() => {
1306
+ const videoLoadedHandler = (0, import_react3.useCallback)(() => {
1305
1307
  clearErrorState();
1306
1308
  }, [clearErrorState]);
1307
- const mouseMoveHandler = (0, import_react2.useCallback)(() => {
1309
+ const mouseMoveHandler = (0, import_react3.useCallback)(() => {
1308
1310
  if (controlTime.current) clearTimeout(controlTime.current);
1309
1311
  setControlVisible(true);
1310
1312
  controlTime.current = setTimeout(() => {
1311
1313
  setControlVisible(false);
1312
1314
  }, 1e3 * 10);
1313
1315
  }, []);
1314
- (0, import_react2.useImperativeHandle)(
1316
+ (0, import_react3.useImperativeHandle)(
1315
1317
  ref,
1316
1318
  () => ({
1317
1319
  play: playAction,
@@ -1322,24 +1324,24 @@ var VideoPlayerBase = (props, ref) => {
1322
1324
  }),
1323
1325
  [fullScreenAction, pauseAction, playAction, seekSetTime]
1324
1326
  );
1325
- (0, import_react2.useEffect)(() => {
1327
+ (0, import_react3.useEffect)(() => {
1326
1328
  const el = videoRef.current;
1327
1329
  if (!el) return;
1328
1330
  el.muted = muted;
1329
1331
  }, [muted]);
1330
- (0, import_react2.useEffect)(() => {
1332
+ (0, import_react3.useEffect)(() => {
1331
1333
  if (playingProp === void 0) return;
1332
1334
  if (!canAttemptPlayback(videoRef.current)) return;
1333
1335
  if (playingProp) void playAction();
1334
1336
  else pauseAction();
1335
1337
  }, [pauseAction, playAction, playingProp]);
1336
- (0, import_react2.useEffect)(() => {
1338
+ (0, import_react3.useEffect)(() => {
1337
1339
  const el = videoRef.current;
1338
1340
  if (!el || currentTimeProp === void 0) return;
1339
1341
  if (Math.abs(el.currentTime - currentTimeProp) < 0.25) return;
1340
1342
  el.currentTime = clampTime(currentTimeProp, duration);
1341
1343
  }, [currentTimeProp, duration]);
1342
- (0, import_react2.useEffect)(() => {
1344
+ (0, import_react3.useEffect)(() => {
1343
1345
  if (!videoRef.current) return;
1344
1346
  clearErrorState();
1345
1347
  fatalReloadCount.current = 0;
@@ -1375,12 +1377,12 @@ var VideoPlayerBase = (props, ref) => {
1375
1377
  type,
1376
1378
  videoSrc
1377
1379
  ]);
1378
- (0, import_react2.useEffect)(() => {
1380
+ (0, import_react3.useEffect)(() => {
1379
1381
  if (!autoPlay) return;
1380
1382
  if (!canAttemptPlayback(videoRef.current)) return;
1381
1383
  void playAction();
1382
1384
  }, [autoPlay, playAction]);
1383
- (0, import_react2.useEffect)(() => {
1385
+ (0, import_react3.useEffect)(() => {
1384
1386
  if (typeof document === "undefined") return;
1385
1387
  const doc = document;
1386
1388
  const handleFsChange = () => {
@@ -1398,7 +1400,7 @@ var VideoPlayerBase = (props, ref) => {
1398
1400
  document.removeEventListener("MSFullscreenChange", handleFsChange);
1399
1401
  };
1400
1402
  }, []);
1401
- (0, import_react2.useEffect)(() => {
1403
+ (0, import_react3.useEffect)(() => {
1402
1404
  return () => {
1403
1405
  setTimeD.current.cancel();
1404
1406
  destroy();
@@ -1483,7 +1485,7 @@ var VideoPlayerBase = (props, ref) => {
1483
1485
  }
1484
1486
  );
1485
1487
  };
1486
- var VideoPlayer = (0, import_react2.memo)((0, import_react2.forwardRef)(VideoPlayerBase));
1488
+ var VideoPlayer = (0, import_react3.memo)((0, import_react3.forwardRef)(VideoPlayerBase));
1487
1489
  var VideoPlayer_default = VideoPlayer;
1488
1490
  // Annotate the CommonJS export names for ESM import in node:
1489
1491
  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() }),
@@ -795,17 +797,17 @@ var VideoPlayerBase = (props, ref) => {
795
797
  const videoSrc = rawVideoSrc.replaceAll(" ", "%20").replaceAll("#", "%23");
796
798
  const messages = useMemo2(() => ({ ...defaultMessages, ...messagesProp }), [messagesProp]);
797
799
  const [, isMobile, mobileType] = useWindowWidth();
798
- const videoRef = useRef(null);
799
- const hlsRef = useRef(null);
800
- const containerRef = useRef(null);
801
- const netRetryCount = useRef(0);
802
- const mediaRecoverCount = useRef(0);
803
- const fatalReloadCount = useRef(0);
804
- const reloadTimer = useRef(null);
805
- const stalledNudgeTimer = useRef(null);
806
- const liveStabilityMode = useRef(false);
807
- const liveStallEvents = useRef([]);
808
- const controlTime = useRef(null);
800
+ const videoRef = useRef2(null);
801
+ const hlsRef = useRef2(null);
802
+ const containerRef = useRef2(null);
803
+ const netRetryCount = useRef2(0);
804
+ const mediaRecoverCount = useRef2(0);
805
+ const fatalReloadCount = useRef2(0);
806
+ const reloadTimer = useRef2(null);
807
+ const stalledNudgeTimer = useRef2(null);
808
+ const liveStabilityMode = useRef2(false);
809
+ const liveStallEvents = useRef2([]);
810
+ const controlTime = useRef2(null);
809
811
  const [playingState, setPlayingState] = useState(!!defaultPlaying);
810
812
  const [mutedState, setMutedState] = useState(!!defaultMuted);
811
813
  const [durationState, setDurationState] = useState(0);
@@ -819,7 +821,7 @@ var VideoPlayerBase = (props, ref) => {
819
821
  const duration = durationProp != null ? durationProp : durationState;
820
822
  const currentTime = currentTimeProp != null ? currentTimeProp : currentTimeState;
821
823
  const fullscreenAllowed = active != null ? active : true;
822
- const setTimeD = useRef(
824
+ const setTimeD = useRef2(
823
825
  createThrottledNumberFn((value) => {
824
826
  const v = videoRef.current;
825
827
  if (!v) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nikelroot/video-player",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Standalone React video player with HLS support.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",