analytica-frontend-lib 1.1.10 → 1.1.12
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/VideoPlayer/index.js +367 -183
- package/dist/VideoPlayer/index.js.map +1 -1
- package/dist/VideoPlayer/index.mjs +373 -184
- package/dist/VideoPlayer/index.mjs.map +1 -1
- package/dist/index.css +10 -3
- package/dist/index.css.map +1 -1
- package/dist/index.js +367 -183
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +373 -184
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +10 -3
- package/dist/styles.css.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -6772,7 +6772,12 @@ var NotFound = ({
|
|
|
6772
6772
|
var NotFound_default = NotFound;
|
|
6773
6773
|
|
|
6774
6774
|
// src/components/VideoPlayer/VideoPlayer.tsx
|
|
6775
|
-
import {
|
|
6775
|
+
import {
|
|
6776
|
+
useRef as useRef9,
|
|
6777
|
+
useState as useState13,
|
|
6778
|
+
useEffect as useEffect11,
|
|
6779
|
+
useCallback
|
|
6780
|
+
} from "react";
|
|
6776
6781
|
import {
|
|
6777
6782
|
Play as Play2,
|
|
6778
6783
|
Pause,
|
|
@@ -6784,12 +6789,93 @@ import {
|
|
|
6784
6789
|
DotsThreeVertical as DotsThreeVertical2
|
|
6785
6790
|
} from "phosphor-react";
|
|
6786
6791
|
import { jsx as jsx36, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
6792
|
+
var CONTROLS_HIDE_TIMEOUT = 3e3;
|
|
6793
|
+
var LEAVE_HIDE_TIMEOUT = 1e3;
|
|
6787
6794
|
var formatTime = (seconds) => {
|
|
6788
6795
|
if (!seconds || isNaN(seconds)) return "0:00";
|
|
6789
6796
|
const mins = Math.floor(seconds / 60);
|
|
6790
6797
|
const secs = Math.floor(seconds % 60);
|
|
6791
6798
|
return `${mins}:${secs.toString().padStart(2, "0")}`;
|
|
6792
6799
|
};
|
|
6800
|
+
var ProgressBar2 = ({
|
|
6801
|
+
currentTime,
|
|
6802
|
+
duration,
|
|
6803
|
+
progressPercentage,
|
|
6804
|
+
onSeek
|
|
6805
|
+
}) => /* @__PURE__ */ jsx36("div", { className: "px-4 pb-2", children: /* @__PURE__ */ jsx36(
|
|
6806
|
+
"input",
|
|
6807
|
+
{
|
|
6808
|
+
type: "range",
|
|
6809
|
+
min: 0,
|
|
6810
|
+
max: duration || 100,
|
|
6811
|
+
value: currentTime,
|
|
6812
|
+
onChange: (e) => onSeek(parseFloat(e.target.value)),
|
|
6813
|
+
className: "w-full h-1 bg-neutral-600 rounded-full appearance-none cursor-pointer slider:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-primary-500",
|
|
6814
|
+
"aria-label": "Video progress",
|
|
6815
|
+
style: {
|
|
6816
|
+
background: `linear-gradient(to right, var(--color-primary-700) ${progressPercentage}%, var(--color-secondary-300) ${progressPercentage}%)`
|
|
6817
|
+
}
|
|
6818
|
+
}
|
|
6819
|
+
) });
|
|
6820
|
+
var VolumeControls = ({
|
|
6821
|
+
volume,
|
|
6822
|
+
isMuted,
|
|
6823
|
+
onVolumeChange,
|
|
6824
|
+
onToggleMute
|
|
6825
|
+
}) => /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2", children: [
|
|
6826
|
+
/* @__PURE__ */ jsx36(
|
|
6827
|
+
IconButton_default,
|
|
6828
|
+
{
|
|
6829
|
+
icon: isMuted ? /* @__PURE__ */ jsx36(SpeakerSlash, { size: 24 }) : /* @__PURE__ */ jsx36(SpeakerHigh2, { size: 24 }),
|
|
6830
|
+
onClick: onToggleMute,
|
|
6831
|
+
"aria-label": isMuted ? "Unmute" : "Mute",
|
|
6832
|
+
className: "!bg-transparent !text-white hover:!bg-white/20"
|
|
6833
|
+
}
|
|
6834
|
+
),
|
|
6835
|
+
/* @__PURE__ */ jsx36(
|
|
6836
|
+
"input",
|
|
6837
|
+
{
|
|
6838
|
+
type: "range",
|
|
6839
|
+
min: 0,
|
|
6840
|
+
max: 100,
|
|
6841
|
+
value: Math.round(volume * 100),
|
|
6842
|
+
onChange: (e) => onVolumeChange(parseInt(e.target.value)),
|
|
6843
|
+
className: "w-20 h-1 bg-neutral-600 rounded-full appearance-none cursor-pointer focus:outline-none focus:ring-2 focus:ring-primary-500",
|
|
6844
|
+
"aria-label": "Volume control",
|
|
6845
|
+
style: {
|
|
6846
|
+
background: `linear-gradient(to right, var(--color-primary-700) ${volume * 100}%, var(--color-secondary-300) ${volume * 100}%)`
|
|
6847
|
+
}
|
|
6848
|
+
}
|
|
6849
|
+
)
|
|
6850
|
+
] });
|
|
6851
|
+
var SpeedMenu = ({
|
|
6852
|
+
showSpeedMenu,
|
|
6853
|
+
playbackRate,
|
|
6854
|
+
onToggleMenu,
|
|
6855
|
+
onSpeedChange
|
|
6856
|
+
}) => /* @__PURE__ */ jsxs30("div", { className: "relative", children: [
|
|
6857
|
+
/* @__PURE__ */ jsx36(
|
|
6858
|
+
IconButton_default,
|
|
6859
|
+
{
|
|
6860
|
+
icon: /* @__PURE__ */ jsx36(DotsThreeVertical2, { size: 24 }),
|
|
6861
|
+
onClick: onToggleMenu,
|
|
6862
|
+
"aria-label": "Playback speed",
|
|
6863
|
+
className: "!bg-transparent !text-white hover:!bg-white/20"
|
|
6864
|
+
}
|
|
6865
|
+
),
|
|
6866
|
+
showSpeedMenu && /* @__PURE__ */ jsx36("div", { className: "absolute bottom-12 right-0 bg-black/90 rounded-lg p-2 min-w-20", children: [0.5, 0.75, 1, 1.25, 1.5, 2].map((speed) => /* @__PURE__ */ jsxs30(
|
|
6867
|
+
"button",
|
|
6868
|
+
{
|
|
6869
|
+
onClick: () => onSpeedChange(speed),
|
|
6870
|
+
className: `block w-full text-left px-3 py-1 text-sm rounded hover:bg-white/20 transition-colors ${playbackRate === speed ? "text-primary-400" : "text-white"}`,
|
|
6871
|
+
children: [
|
|
6872
|
+
speed,
|
|
6873
|
+
"x"
|
|
6874
|
+
]
|
|
6875
|
+
},
|
|
6876
|
+
speed
|
|
6877
|
+
)) })
|
|
6878
|
+
] });
|
|
6793
6879
|
var VideoPlayer = ({
|
|
6794
6880
|
src,
|
|
6795
6881
|
poster,
|
|
@@ -6814,10 +6900,68 @@ var VideoPlayer = ({
|
|
|
6814
6900
|
const [showControls, setShowControls] = useState13(true);
|
|
6815
6901
|
const [hasCompleted, setHasCompleted] = useState13(false);
|
|
6816
6902
|
const [showCaptions, setShowCaptions] = useState13(false);
|
|
6903
|
+
useEffect11(() => {
|
|
6904
|
+
setHasCompleted(false);
|
|
6905
|
+
}, [src]);
|
|
6817
6906
|
const [playbackRate, setPlaybackRate] = useState13(1);
|
|
6818
6907
|
const [showSpeedMenu, setShowSpeedMenu] = useState13(false);
|
|
6819
6908
|
const lastSaveTimeRef = useRef9(0);
|
|
6820
6909
|
const trackRef = useRef9(null);
|
|
6910
|
+
const controlsTimeoutRef = useRef9(null);
|
|
6911
|
+
const lastMousePositionRef = useRef9({ x: 0, y: 0 });
|
|
6912
|
+
const mouseMoveTimeoutRef = useRef9(null);
|
|
6913
|
+
const isUserInteracting = useCallback(() => {
|
|
6914
|
+
if (showSpeedMenu) return true;
|
|
6915
|
+
const activeElement = document.activeElement;
|
|
6916
|
+
const videoContainer = videoRef.current?.parentElement;
|
|
6917
|
+
if (activeElement && videoContainer?.contains(activeElement)) {
|
|
6918
|
+
const isControl = activeElement.matches("button, input, [tabindex]");
|
|
6919
|
+
if (isControl) return true;
|
|
6920
|
+
}
|
|
6921
|
+
return false;
|
|
6922
|
+
}, [showSpeedMenu]);
|
|
6923
|
+
const clearControlsTimeout = useCallback(() => {
|
|
6924
|
+
if (controlsTimeoutRef.current) {
|
|
6925
|
+
clearTimeout(controlsTimeoutRef.current);
|
|
6926
|
+
controlsTimeoutRef.current = null;
|
|
6927
|
+
}
|
|
6928
|
+
}, []);
|
|
6929
|
+
const clearMouseMoveTimeout = useCallback(() => {
|
|
6930
|
+
if (mouseMoveTimeoutRef.current) {
|
|
6931
|
+
clearTimeout(mouseMoveTimeoutRef.current);
|
|
6932
|
+
mouseMoveTimeoutRef.current = null;
|
|
6933
|
+
}
|
|
6934
|
+
}, []);
|
|
6935
|
+
const showControlsWithTimer = useCallback(() => {
|
|
6936
|
+
setShowControls(true);
|
|
6937
|
+
clearControlsTimeout();
|
|
6938
|
+
if (isPlaying) {
|
|
6939
|
+
controlsTimeoutRef.current = window.setTimeout(() => {
|
|
6940
|
+
setShowControls(false);
|
|
6941
|
+
}, CONTROLS_HIDE_TIMEOUT);
|
|
6942
|
+
}
|
|
6943
|
+
}, [isPlaying, clearControlsTimeout]);
|
|
6944
|
+
const handleMouseMove = useCallback(
|
|
6945
|
+
(event) => {
|
|
6946
|
+
const currentX = event.clientX;
|
|
6947
|
+
const currentY = event.clientY;
|
|
6948
|
+
const lastPos = lastMousePositionRef.current;
|
|
6949
|
+
const hasMoved = Math.abs(currentX - lastPos.x) > 5 || Math.abs(currentY - lastPos.y) > 5;
|
|
6950
|
+
if (hasMoved) {
|
|
6951
|
+
lastMousePositionRef.current = { x: currentX, y: currentY };
|
|
6952
|
+
showControlsWithTimer();
|
|
6953
|
+
}
|
|
6954
|
+
},
|
|
6955
|
+
[showControlsWithTimer]
|
|
6956
|
+
);
|
|
6957
|
+
const handleMouseLeave = useCallback(() => {
|
|
6958
|
+
clearControlsTimeout();
|
|
6959
|
+
if (isPlaying && !isUserInteracting()) {
|
|
6960
|
+
controlsTimeoutRef.current = window.setTimeout(() => {
|
|
6961
|
+
setShowControls(false);
|
|
6962
|
+
}, LEAVE_HIDE_TIMEOUT);
|
|
6963
|
+
}
|
|
6964
|
+
}, [isPlaying, clearControlsTimeout, isUserInteracting]);
|
|
6821
6965
|
useEffect11(() => {
|
|
6822
6966
|
if (videoRef.current) {
|
|
6823
6967
|
videoRef.current.volume = volume;
|
|
@@ -6825,84 +6969,129 @@ var VideoPlayer = ({
|
|
|
6825
6969
|
}
|
|
6826
6970
|
}, [volume, isMuted]);
|
|
6827
6971
|
useEffect11(() => {
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
const
|
|
6831
|
-
const
|
|
6832
|
-
const
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6972
|
+
const video = videoRef.current;
|
|
6973
|
+
if (!video) return;
|
|
6974
|
+
const onPlay = () => setIsPlaying(true);
|
|
6975
|
+
const onPause = () => setIsPlaying(false);
|
|
6976
|
+
const onEnded = () => setIsPlaying(false);
|
|
6977
|
+
video.addEventListener("play", onPlay);
|
|
6978
|
+
video.addEventListener("pause", onPause);
|
|
6979
|
+
video.addEventListener("ended", onEnded);
|
|
6980
|
+
return () => {
|
|
6981
|
+
video.removeEventListener("play", onPlay);
|
|
6982
|
+
video.removeEventListener("pause", onPause);
|
|
6983
|
+
video.removeEventListener("ended", onEnded);
|
|
6984
|
+
};
|
|
6985
|
+
}, []);
|
|
6986
|
+
useEffect11(() => {
|
|
6987
|
+
if (isPlaying) {
|
|
6988
|
+
showControlsWithTimer();
|
|
6838
6989
|
} else {
|
|
6839
|
-
|
|
6990
|
+
clearControlsTimeout();
|
|
6991
|
+
setShowControls(true);
|
|
6992
|
+
}
|
|
6993
|
+
}, [isPlaying, showControlsWithTimer, clearControlsTimeout]);
|
|
6994
|
+
useEffect11(() => {
|
|
6995
|
+
const handleFullscreenChange = () => {
|
|
6996
|
+
const isCurrentlyFullscreen = !!document.fullscreenElement;
|
|
6997
|
+
setIsFullscreen(isCurrentlyFullscreen);
|
|
6998
|
+
if (isCurrentlyFullscreen) {
|
|
6999
|
+
showControlsWithTimer();
|
|
7000
|
+
}
|
|
7001
|
+
};
|
|
7002
|
+
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
7003
|
+
return () => {
|
|
7004
|
+
document.removeEventListener("fullscreenchange", handleFullscreenChange);
|
|
7005
|
+
};
|
|
7006
|
+
}, [showControlsWithTimer]);
|
|
7007
|
+
const getInitialTime = useCallback(() => {
|
|
7008
|
+
if (!autoSave || !storageKey) {
|
|
7009
|
+
return Number.isFinite(initialTime) && initialTime >= 0 ? initialTime : void 0;
|
|
6840
7010
|
}
|
|
7011
|
+
const saved = Number(localStorage.getItem(`${storageKey}-${src}`) || NaN);
|
|
7012
|
+
const hasValidInitial = Number.isFinite(initialTime) && initialTime >= 0;
|
|
7013
|
+
const hasValidSaved = Number.isFinite(saved) && saved >= 0;
|
|
7014
|
+
if (hasValidInitial) return initialTime;
|
|
7015
|
+
if (hasValidSaved) return saved;
|
|
7016
|
+
return void 0;
|
|
7017
|
+
}, [autoSave, storageKey, src, initialTime]);
|
|
7018
|
+
useEffect11(() => {
|
|
7019
|
+
const start = getInitialTime();
|
|
6841
7020
|
if (start !== void 0 && videoRef.current) {
|
|
6842
7021
|
videoRef.current.currentTime = start;
|
|
6843
7022
|
setCurrentTime(start);
|
|
6844
7023
|
}
|
|
6845
|
-
}, [
|
|
6846
|
-
const saveProgress = useCallback(
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
}, [autoSave, storageKey, src, currentTime]);
|
|
6854
|
-
const togglePlayPause = useCallback(() => {
|
|
6855
|
-
if (videoRef.current) {
|
|
6856
|
-
if (isPlaying) {
|
|
6857
|
-
videoRef.current.pause();
|
|
6858
|
-
} else {
|
|
6859
|
-
videoRef.current.play();
|
|
7024
|
+
}, [getInitialTime]);
|
|
7025
|
+
const saveProgress = useCallback(
|
|
7026
|
+
(time) => {
|
|
7027
|
+
if (!autoSave || !storageKey) return;
|
|
7028
|
+
const now = Date.now();
|
|
7029
|
+
if (now - lastSaveTimeRef.current > 5e3) {
|
|
7030
|
+
localStorage.setItem(`${storageKey}-${src}`, time.toString());
|
|
7031
|
+
lastSaveTimeRef.current = now;
|
|
6860
7032
|
}
|
|
6861
|
-
|
|
7033
|
+
},
|
|
7034
|
+
[autoSave, storageKey, src]
|
|
7035
|
+
);
|
|
7036
|
+
const togglePlayPause = useCallback(async () => {
|
|
7037
|
+
const video = videoRef.current;
|
|
7038
|
+
if (!video) return;
|
|
7039
|
+
if (!video.paused) {
|
|
7040
|
+
video.pause();
|
|
7041
|
+
return;
|
|
7042
|
+
}
|
|
7043
|
+
try {
|
|
7044
|
+
await video.play();
|
|
7045
|
+
} catch {
|
|
6862
7046
|
}
|
|
6863
|
-
}, [
|
|
7047
|
+
}, []);
|
|
6864
7048
|
const handleVolumeChange = useCallback(
|
|
6865
7049
|
(newVolume) => {
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
7050
|
+
const video = videoRef.current;
|
|
7051
|
+
if (!video) return;
|
|
7052
|
+
const volumeValue = newVolume / 100;
|
|
7053
|
+
video.volume = volumeValue;
|
|
7054
|
+
setVolume(volumeValue);
|
|
7055
|
+
const shouldMute = volumeValue === 0;
|
|
7056
|
+
const shouldUnmute = volumeValue > 0 && isMuted;
|
|
7057
|
+
if (shouldMute) {
|
|
7058
|
+
video.muted = true;
|
|
7059
|
+
setIsMuted(true);
|
|
7060
|
+
} else if (shouldUnmute) {
|
|
7061
|
+
video.muted = false;
|
|
7062
|
+
setIsMuted(false);
|
|
6877
7063
|
}
|
|
6878
7064
|
},
|
|
6879
7065
|
[isMuted]
|
|
6880
7066
|
);
|
|
6881
7067
|
const toggleMute = useCallback(() => {
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
7068
|
+
const video = videoRef.current;
|
|
7069
|
+
if (!video) return;
|
|
7070
|
+
if (isMuted) {
|
|
7071
|
+
const restoreVolume = volume > 0 ? volume : 0.5;
|
|
7072
|
+
video.volume = restoreVolume;
|
|
7073
|
+
video.muted = false;
|
|
7074
|
+
setVolume(restoreVolume);
|
|
7075
|
+
setIsMuted(false);
|
|
7076
|
+
} else {
|
|
7077
|
+
video.muted = true;
|
|
7078
|
+
setIsMuted(true);
|
|
6893
7079
|
}
|
|
6894
7080
|
}, [isMuted, volume]);
|
|
7081
|
+
const handleSeek = useCallback((newTime) => {
|
|
7082
|
+
const video = videoRef.current;
|
|
7083
|
+
if (video) {
|
|
7084
|
+
video.currentTime = newTime;
|
|
7085
|
+
}
|
|
7086
|
+
}, []);
|
|
6895
7087
|
const toggleFullscreen = useCallback(() => {
|
|
6896
7088
|
const container = videoRef.current?.parentElement;
|
|
6897
7089
|
if (!container) return;
|
|
6898
|
-
if (!isFullscreen) {
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
}
|
|
6902
|
-
} else if (document.exitFullscreen) {
|
|
7090
|
+
if (!isFullscreen && container.requestFullscreen) {
|
|
7091
|
+
container.requestFullscreen();
|
|
7092
|
+
} else if (isFullscreen && document.exitFullscreen) {
|
|
6903
7093
|
document.exitFullscreen();
|
|
6904
7094
|
}
|
|
6905
|
-
setIsFullscreen(!isFullscreen);
|
|
6906
7095
|
}, [isFullscreen]);
|
|
6907
7096
|
const handleSpeedChange = useCallback((speed) => {
|
|
6908
7097
|
if (videoRef.current) {
|
|
@@ -6920,29 +7109,28 @@ var VideoPlayer = ({
|
|
|
6920
7109
|
setShowCaptions(newShowCaptions);
|
|
6921
7110
|
trackRef.current.track.mode = newShowCaptions && subtitles ? "showing" : "hidden";
|
|
6922
7111
|
}, [showCaptions, subtitles]);
|
|
6923
|
-
const
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
onTimeUpdate?.(current);
|
|
6929
|
-
if (duration > 0) {
|
|
6930
|
-
const progressPercent = current / duration * 100;
|
|
6931
|
-
onProgress?.(progressPercent);
|
|
6932
|
-
if (progressPercent >= 95 && !hasCompleted) {
|
|
6933
|
-
setHasCompleted(true);
|
|
6934
|
-
onVideoComplete?.();
|
|
6935
|
-
}
|
|
7112
|
+
const checkVideoCompletion = useCallback(
|
|
7113
|
+
(progressPercent) => {
|
|
7114
|
+
if (progressPercent >= 95 && !hasCompleted) {
|
|
7115
|
+
setHasCompleted(true);
|
|
7116
|
+
onVideoComplete?.();
|
|
6936
7117
|
}
|
|
7118
|
+
},
|
|
7119
|
+
[hasCompleted, onVideoComplete]
|
|
7120
|
+
);
|
|
7121
|
+
const handleTimeUpdate = useCallback(() => {
|
|
7122
|
+
const video = videoRef.current;
|
|
7123
|
+
if (!video) return;
|
|
7124
|
+
const current = video.currentTime;
|
|
7125
|
+
setCurrentTime(current);
|
|
7126
|
+
saveProgress(current);
|
|
7127
|
+
onTimeUpdate?.(current);
|
|
7128
|
+
if (duration > 0) {
|
|
7129
|
+
const progressPercent = current / duration * 100;
|
|
7130
|
+
onProgress?.(progressPercent);
|
|
7131
|
+
checkVideoCompletion(progressPercent);
|
|
6937
7132
|
}
|
|
6938
|
-
}, [
|
|
6939
|
-
duration,
|
|
6940
|
-
saveProgress,
|
|
6941
|
-
onTimeUpdate,
|
|
6942
|
-
onProgress,
|
|
6943
|
-
onVideoComplete,
|
|
6944
|
-
hasCompleted
|
|
6945
|
-
]);
|
|
7133
|
+
}, [duration, saveProgress, onTimeUpdate, onProgress, checkVideoCompletion]);
|
|
6946
7134
|
const handleLoadedMetadata = useCallback(() => {
|
|
6947
7135
|
if (videoRef.current) {
|
|
6948
7136
|
setDuration(videoRef.current.duration);
|
|
@@ -6971,9 +7159,78 @@ var VideoPlayer = ({
|
|
|
6971
7159
|
return () => {
|
|
6972
7160
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
6973
7161
|
window.removeEventListener("blur", handleBlur);
|
|
7162
|
+
clearControlsTimeout();
|
|
7163
|
+
clearMouseMoveTimeout();
|
|
6974
7164
|
};
|
|
6975
|
-
}, [isPlaying]);
|
|
7165
|
+
}, [isPlaying, clearControlsTimeout, clearMouseMoveTimeout]);
|
|
6976
7166
|
const progressPercentage = duration > 0 ? currentTime / duration * 100 : 0;
|
|
7167
|
+
const getTopControlsOpacity = useCallback(() => {
|
|
7168
|
+
if (isFullscreen) {
|
|
7169
|
+
return showControls ? "opacity-100" : "opacity-0";
|
|
7170
|
+
}
|
|
7171
|
+
return !isPlaying || showControls ? "opacity-100" : "opacity-0 group-hover:opacity-100";
|
|
7172
|
+
}, [isFullscreen, showControls, isPlaying]);
|
|
7173
|
+
const getBottomControlsOpacity = useCallback(() => {
|
|
7174
|
+
if (isFullscreen) {
|
|
7175
|
+
return showControls ? "opacity-100" : "opacity-0";
|
|
7176
|
+
}
|
|
7177
|
+
return !isPlaying || showControls ? "opacity-100" : "opacity-0 group-hover:opacity-100";
|
|
7178
|
+
}, [isFullscreen, showControls, isPlaying]);
|
|
7179
|
+
const handleVideoKeyDown = useCallback(
|
|
7180
|
+
(e) => {
|
|
7181
|
+
if (e.key) {
|
|
7182
|
+
e.stopPropagation();
|
|
7183
|
+
showControlsWithTimer();
|
|
7184
|
+
}
|
|
7185
|
+
switch (e.key) {
|
|
7186
|
+
case " ":
|
|
7187
|
+
case "Enter":
|
|
7188
|
+
e.preventDefault();
|
|
7189
|
+
togglePlayPause();
|
|
7190
|
+
break;
|
|
7191
|
+
case "ArrowLeft":
|
|
7192
|
+
e.preventDefault();
|
|
7193
|
+
if (videoRef.current) {
|
|
7194
|
+
videoRef.current.currentTime -= 10;
|
|
7195
|
+
}
|
|
7196
|
+
break;
|
|
7197
|
+
case "ArrowRight":
|
|
7198
|
+
e.preventDefault();
|
|
7199
|
+
if (videoRef.current) {
|
|
7200
|
+
videoRef.current.currentTime += 10;
|
|
7201
|
+
}
|
|
7202
|
+
break;
|
|
7203
|
+
case "ArrowUp":
|
|
7204
|
+
e.preventDefault();
|
|
7205
|
+
handleVolumeChange(Math.min(100, volume * 100 + 10));
|
|
7206
|
+
break;
|
|
7207
|
+
case "ArrowDown":
|
|
7208
|
+
e.preventDefault();
|
|
7209
|
+
handleVolumeChange(Math.max(0, volume * 100 - 10));
|
|
7210
|
+
break;
|
|
7211
|
+
case "m":
|
|
7212
|
+
case "M":
|
|
7213
|
+
e.preventDefault();
|
|
7214
|
+
toggleMute();
|
|
7215
|
+
break;
|
|
7216
|
+
case "f":
|
|
7217
|
+
case "F":
|
|
7218
|
+
e.preventDefault();
|
|
7219
|
+
toggleFullscreen();
|
|
7220
|
+
break;
|
|
7221
|
+
default:
|
|
7222
|
+
break;
|
|
7223
|
+
}
|
|
7224
|
+
},
|
|
7225
|
+
[
|
|
7226
|
+
showControlsWithTimer,
|
|
7227
|
+
togglePlayPause,
|
|
7228
|
+
handleVolumeChange,
|
|
7229
|
+
volume,
|
|
7230
|
+
toggleMute,
|
|
7231
|
+
toggleFullscreen
|
|
7232
|
+
]
|
|
7233
|
+
);
|
|
6977
7234
|
return /* @__PURE__ */ jsxs30("div", { className: cn("flex flex-col", className), children: [
|
|
6978
7235
|
(title || subtitleText) && /* @__PURE__ */ jsx36("div", { className: "bg-subject-1 rounded-t-xl px-8 py-4 flex items-end justify-between min-h-20", children: /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-1", children: [
|
|
6979
7236
|
title && /* @__PURE__ */ jsx36(
|
|
@@ -7000,12 +7257,18 @@ var VideoPlayer = ({
|
|
|
7000
7257
|
)
|
|
7001
7258
|
] }) }),
|
|
7002
7259
|
/* @__PURE__ */ jsxs30(
|
|
7003
|
-
"
|
|
7260
|
+
"section",
|
|
7004
7261
|
{
|
|
7005
7262
|
className: cn(
|
|
7006
7263
|
"relative w-full bg-background overflow-hidden group",
|
|
7007
|
-
title || subtitleText ? "rounded-b-xl" : "rounded-xl"
|
|
7264
|
+
title || subtitleText ? "rounded-b-xl" : "rounded-xl",
|
|
7265
|
+
// Hide cursor when controls are hidden and video is playing
|
|
7266
|
+
isPlaying && !showControls ? "cursor-none group-hover:cursor-default" : "cursor-default"
|
|
7008
7267
|
),
|
|
7268
|
+
"aria-label": title ? `Video player: ${title}` : "Video player",
|
|
7269
|
+
onMouseMove: handleMouseMove,
|
|
7270
|
+
onMouseEnter: showControlsWithTimer,
|
|
7271
|
+
onMouseLeave: handleMouseLeave,
|
|
7009
7272
|
children: [
|
|
7010
7273
|
/* @__PURE__ */ jsx36(
|
|
7011
7274
|
"video",
|
|
@@ -7018,39 +7281,7 @@ var VideoPlayer = ({
|
|
|
7018
7281
|
onTimeUpdate: handleTimeUpdate,
|
|
7019
7282
|
onLoadedMetadata: handleLoadedMetadata,
|
|
7020
7283
|
onClick: togglePlayPause,
|
|
7021
|
-
onKeyDown:
|
|
7022
|
-
if (e.key) {
|
|
7023
|
-
setShowControls(true);
|
|
7024
|
-
}
|
|
7025
|
-
if (e.key === " " || e.key === "Enter") {
|
|
7026
|
-
e.preventDefault();
|
|
7027
|
-
togglePlayPause();
|
|
7028
|
-
}
|
|
7029
|
-
if (e.key === "ArrowLeft" && videoRef.current) {
|
|
7030
|
-
e.preventDefault();
|
|
7031
|
-
videoRef.current.currentTime -= 10;
|
|
7032
|
-
}
|
|
7033
|
-
if (e.key === "ArrowRight" && videoRef.current) {
|
|
7034
|
-
e.preventDefault();
|
|
7035
|
-
videoRef.current.currentTime += 10;
|
|
7036
|
-
}
|
|
7037
|
-
if (e.key === "ArrowUp") {
|
|
7038
|
-
e.preventDefault();
|
|
7039
|
-
handleVolumeChange(Math.min(100, volume * 100 + 10));
|
|
7040
|
-
}
|
|
7041
|
-
if (e.key === "ArrowDown") {
|
|
7042
|
-
e.preventDefault();
|
|
7043
|
-
handleVolumeChange(Math.max(0, volume * 100 - 10));
|
|
7044
|
-
}
|
|
7045
|
-
if (e.key === "m" || e.key === "M") {
|
|
7046
|
-
e.preventDefault();
|
|
7047
|
-
toggleMute();
|
|
7048
|
-
}
|
|
7049
|
-
if (e.key === "f" || e.key === "F") {
|
|
7050
|
-
e.preventDefault();
|
|
7051
|
-
toggleFullscreen();
|
|
7052
|
-
}
|
|
7053
|
-
},
|
|
7284
|
+
onKeyDown: handleVideoKeyDown,
|
|
7054
7285
|
tabIndex: 0,
|
|
7055
7286
|
"aria-label": title ? `Video: ${title}` : "Video player",
|
|
7056
7287
|
children: /* @__PURE__ */ jsx36(
|
|
@@ -7080,9 +7311,9 @@ var VideoPlayer = ({
|
|
|
7080
7311
|
{
|
|
7081
7312
|
className: cn(
|
|
7082
7313
|
"absolute top-0 left-0 right-0 p-4 bg-gradient-to-b from-black/70 to-transparent transition-opacity",
|
|
7083
|
-
|
|
7314
|
+
getTopControlsOpacity()
|
|
7084
7315
|
),
|
|
7085
|
-
children: /* @__PURE__ */ jsx36("div", { className: "
|
|
7316
|
+
children: /* @__PURE__ */ jsx36("div", { className: "flex justify-start", children: /* @__PURE__ */ jsx36(
|
|
7086
7317
|
IconButton_default,
|
|
7087
7318
|
{
|
|
7088
7319
|
icon: isFullscreen ? /* @__PURE__ */ jsx36(ArrowsInSimple, { size: 24 }) : /* @__PURE__ */ jsx36(ArrowsOutSimple, { size: 24 }),
|
|
@@ -7098,29 +7329,18 @@ var VideoPlayer = ({
|
|
|
7098
7329
|
{
|
|
7099
7330
|
className: cn(
|
|
7100
7331
|
"absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/90 to-transparent transition-opacity",
|
|
7101
|
-
|
|
7332
|
+
getBottomControlsOpacity()
|
|
7102
7333
|
),
|
|
7103
7334
|
children: [
|
|
7104
|
-
/* @__PURE__ */ jsx36(
|
|
7105
|
-
|
|
7335
|
+
/* @__PURE__ */ jsx36(
|
|
7336
|
+
ProgressBar2,
|
|
7106
7337
|
{
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
onChange: (e) => {
|
|
7112
|
-
const newTime = parseFloat(e.target.value);
|
|
7113
|
-
if (videoRef.current) {
|
|
7114
|
-
videoRef.current.currentTime = newTime;
|
|
7115
|
-
}
|
|
7116
|
-
},
|
|
7117
|
-
className: "w-full h-1 bg-neutral-600 rounded-full appearance-none cursor-pointer slider:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-primary-500",
|
|
7118
|
-
"aria-label": "Video progress",
|
|
7119
|
-
style: {
|
|
7120
|
-
background: `linear-gradient(to right, #2271C4 ${progressPercentage}%, #D5D4D4 ${progressPercentage}%)`
|
|
7121
|
-
}
|
|
7338
|
+
currentTime,
|
|
7339
|
+
duration,
|
|
7340
|
+
progressPercentage,
|
|
7341
|
+
onSeek: handleSeek
|
|
7122
7342
|
}
|
|
7123
|
-
)
|
|
7343
|
+
),
|
|
7124
7344
|
/* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-between px-4 pb-4", children: [
|
|
7125
7345
|
/* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-4", children: [
|
|
7126
7346
|
/* @__PURE__ */ jsx36(
|
|
@@ -7132,32 +7352,15 @@ var VideoPlayer = ({
|
|
|
7132
7352
|
className: "!bg-transparent !text-white hover:!bg-white/20"
|
|
7133
7353
|
}
|
|
7134
7354
|
),
|
|
7135
|
-
/* @__PURE__ */
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
),
|
|
7145
|
-
/* @__PURE__ */ jsx36(
|
|
7146
|
-
"input",
|
|
7147
|
-
{
|
|
7148
|
-
type: "range",
|
|
7149
|
-
min: 0,
|
|
7150
|
-
max: 100,
|
|
7151
|
-
value: Math.round(volume * 100),
|
|
7152
|
-
onChange: (e) => handleVolumeChange(parseInt(e.target.value)),
|
|
7153
|
-
className: "w-20 h-1 bg-neutral-600 rounded-full appearance-none cursor-pointer focus:outline-none focus:ring-2 focus:ring-primary-500",
|
|
7154
|
-
"aria-label": "Volume control",
|
|
7155
|
-
style: {
|
|
7156
|
-
background: `linear-gradient(to right, #2271C4 ${volume * 100}%, #D5D4D4 ${volume * 100}%)`
|
|
7157
|
-
}
|
|
7158
|
-
}
|
|
7159
|
-
)
|
|
7160
|
-
] }),
|
|
7355
|
+
/* @__PURE__ */ jsx36(
|
|
7356
|
+
VolumeControls,
|
|
7357
|
+
{
|
|
7358
|
+
volume,
|
|
7359
|
+
isMuted,
|
|
7360
|
+
onVolumeChange: handleVolumeChange,
|
|
7361
|
+
onToggleMute: toggleMute
|
|
7362
|
+
}
|
|
7363
|
+
),
|
|
7161
7364
|
subtitles && /* @__PURE__ */ jsx36(
|
|
7162
7365
|
IconButton_default,
|
|
7163
7366
|
{
|
|
@@ -7176,29 +7379,15 @@ var VideoPlayer = ({
|
|
|
7176
7379
|
formatTime(duration)
|
|
7177
7380
|
] })
|
|
7178
7381
|
] }),
|
|
7179
|
-
/* @__PURE__ */ jsx36("div", { className: "flex items-center gap-4", children: /* @__PURE__ */
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
),
|
|
7189
|
-
showSpeedMenu && /* @__PURE__ */ jsx36("div", { className: "absolute bottom-12 right-0 bg-black/90 rounded-lg p-2 min-w-20", children: [0.5, 0.75, 1, 1.25, 1.5, 2].map((speed) => /* @__PURE__ */ jsxs30(
|
|
7190
|
-
"button",
|
|
7191
|
-
{
|
|
7192
|
-
onClick: () => handleSpeedChange(speed),
|
|
7193
|
-
className: `block w-full text-left px-3 py-1 text-sm rounded hover:bg-white/20 transition-colors ${playbackRate === speed ? "text-primary-400" : "text-white"}`,
|
|
7194
|
-
children: [
|
|
7195
|
-
speed,
|
|
7196
|
-
"x"
|
|
7197
|
-
]
|
|
7198
|
-
},
|
|
7199
|
-
speed
|
|
7200
|
-
)) })
|
|
7201
|
-
] }) })
|
|
7382
|
+
/* @__PURE__ */ jsx36("div", { className: "flex items-center gap-4", children: /* @__PURE__ */ jsx36(
|
|
7383
|
+
SpeedMenu,
|
|
7384
|
+
{
|
|
7385
|
+
showSpeedMenu,
|
|
7386
|
+
playbackRate,
|
|
7387
|
+
onToggleMenu: toggleSpeedMenu,
|
|
7388
|
+
onSpeedChange: handleSpeedChange
|
|
7389
|
+
}
|
|
7390
|
+
) })
|
|
7202
7391
|
] })
|
|
7203
7392
|
]
|
|
7204
7393
|
}
|