softbuilders-react-video-player 1.1.8 → 1.1.10
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/LICENSE +21 -21
- package/README.md +126 -126
- package/dist/components/BigPlayButton/index.js +1 -1
- package/dist/components/BigPlayButton/index.js.map +1 -1
- package/dist/components/BigPlayButton/index.tsx +33 -31
- package/dist/components/BufferTracker/index.tsx +19 -19
- package/dist/components/ChapterTooltip/index.tsx +65 -65
- package/dist/components/ChaptersPanal/index.tsx +40 -40
- package/dist/components/ControlBar/index.d.ts +2 -1
- package/dist/components/ControlBar/index.js +21 -6
- package/dist/components/ControlBar/index.js.map +1 -1
- package/dist/components/ControlBar/index.tsx +150 -127
- package/dist/components/CreateNoteMenu/index.tsx +61 -61
- package/dist/components/CurrentTimeLabel/index.tsx +13 -13
- package/dist/components/CurrentTimeTracker/index.tsx +18 -18
- package/dist/components/Menu/index.tsx +49 -49
- package/dist/components/MenuButton/index.js +1 -1
- package/dist/components/MenuButton/index.js.map +1 -1
- package/dist/components/MenuButton/index.tsx +67 -67
- package/dist/components/NoteTooltip/index.tsx +46 -46
- package/dist/components/NotesPanal/index.tsx +34 -34
- package/dist/components/QualityMenu/index.js +2 -2
- package/dist/components/QualityMenu/index.js.map +1 -1
- package/dist/components/QualityMenu/index.tsx +122 -122
- package/dist/components/Slider/index.d.ts +1 -1
- package/dist/components/Slider/index.js +3 -3
- package/dist/components/Slider/index.js.map +1 -1
- package/dist/components/Slider/index.tsx +36 -37
- package/dist/components/Slider/style.css +49 -15
- package/dist/components/SoftBuildersVideoPlayer/index.js +1 -1
- package/dist/components/SoftBuildersVideoPlayer/index.js.map +1 -1
- package/dist/components/SoftBuildersVideoPlayer/index.tsx +110 -109
- package/dist/components/SubtitleMenu/index.js +2 -2
- package/dist/components/SubtitleMenu/index.js.map +1 -1
- package/dist/components/SubtitleMenu/index.tsx +107 -108
- package/dist/components/TimeSlider/index.js +13 -13
- package/dist/components/TimeSlider/index.tsx +107 -107
- package/dist/components/TimeSliderContainer/index.tsx +35 -35
- package/dist/components/Tooltip/index.tsx +16 -16
- package/dist/components/VideoPlayerComponent/index.d.ts +2 -1
- package/dist/components/VideoPlayerComponent/index.js +54 -38
- package/dist/components/VideoPlayerComponent/index.js.map +1 -1
- package/dist/components/VideoPlayerComponent/index.tsx +271 -249
- package/dist/components/VideoPlayerComponent/provider.tsx +82 -82
- package/dist/components/VideoPlayerComponent/style/style.css +36 -36
- package/dist/components/VolumeSlider/index.d.ts +4 -2
- package/dist/components/VolumeSlider/index.js +12 -2
- package/dist/components/VolumeSlider/index.js.map +1 -1
- package/dist/components/VolumeSlider/index.tsx +91 -52
- package/dist/components/icons/SubIcon.d.ts +3 -0
- package/dist/components/icons/SubIcon.js +4 -0
- package/dist/components/icons/SubIcon.js.map +1 -0
- package/dist/components/icons/SubIcon.tsx +28 -0
- package/dist/components/icons/index.d.ts +1 -0
- package/dist/components/icons/index.js +1 -0
- package/dist/components/icons/index.js.map +1 -1
- package/dist/components/icons/index.ts +15 -14
- package/dist/images/index.d.ts +1 -0
- package/dist/images/index.js +1 -0
- package/dist/images/index.js.map +1 -1
- package/dist/index.css +78 -3
- package/dist/index.mjs +276 -169
- package/dist/styles/tailwind.css +140 -87
- package/package.json +45 -45
@@ -1,5 +1,5 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
-
import { useEffect } from "react";
|
2
|
+
import { useEffect, useState } from "react";
|
3
3
|
import CurrentTimeLabel from "../CurrentTimeLabel";
|
4
4
|
import { durationFormater } from "../../utils";
|
5
5
|
import VolumeSlider from "../VolumeSlider";
|
@@ -10,14 +10,29 @@ import BufferTracker from "../BufferTracker";
|
|
10
10
|
import CurrentTimeTracker from "../CurrentTimeTracker";
|
11
11
|
import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
|
12
12
|
import SubtitleMenu from "../SubtitleMenu";
|
13
|
-
import { BackwardIcon, ForwardIcon, FullScreenIcon, PauseIcon, PlayIcon } from "../../images";
|
14
|
-
const ControlBar = ({ player, isPaused, setIsPaused, duration, notes, chapters, seekStep = 5, handleSaveNoteAction, }) => {
|
13
|
+
import { BackwardIcon, ForwardIcon, FullScreenIcon, PauseIcon, PlayIcon, } from "../../images";
|
14
|
+
const ControlBar = ({ player, isPaused, setIsPaused, duration, notes, chapters, seekStep = 5, id, handleSaveNoteAction, }) => {
|
15
15
|
const { setPlayer, setDuration } = useSoftBuildersVideoPlayerContext();
|
16
|
+
const [width, setwidth] = useState(null);
|
16
17
|
const seek = (duration) => {
|
17
18
|
const currentTime = Number((player === null || player === void 0 ? void 0 : player.currentTime()) || 0);
|
18
19
|
player === null || player === void 0 ? void 0 : player.currentTime(currentTime + duration);
|
19
20
|
};
|
20
|
-
const
|
21
|
+
const container = document.getElementById(`video-container-${id}`);
|
22
|
+
function handleWidthChange(width) {
|
23
|
+
setwidth(width);
|
24
|
+
console.log(width);
|
25
|
+
}
|
26
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
27
|
+
for (let entry of entries) {
|
28
|
+
const currentWidth = entry.contentRect.width;
|
29
|
+
handleWidthChange(currentWidth); // Call the action when width changes
|
30
|
+
}
|
31
|
+
});
|
32
|
+
// Start observing the element
|
33
|
+
resizeObserver.observe(container);
|
34
|
+
const togglePlay = (e) => {
|
35
|
+
e.stopPropagation();
|
21
36
|
if (isPaused)
|
22
37
|
player === null || player === void 0 ? void 0 : player.play();
|
23
38
|
else
|
@@ -30,11 +45,11 @@ const ControlBar = ({ player, isPaused, setIsPaused, duration, notes, chapters,
|
|
30
45
|
useEffect(() => {
|
31
46
|
setDuration(duration);
|
32
47
|
}, [duration]);
|
33
|
-
return (_jsxs("div", { className: "
|
48
|
+
return (_jsxs("div", { className: " sb-px-2 sb-flex sb-justify-center sb-gap-3 sb-w-full sb-h-full sb-items-end pb-2", children: [_jsx(BufferTracker, {}), _jsx(CurrentTimeTracker, {}), _jsx("button", { onClick: () => {
|
34
49
|
seek(-seekStep);
|
35
50
|
}, children: _jsx(BackwardIcon, { className: "sb-w-3 sb-h-3" }) }), _jsx("button", { onClick: togglePlay, children: isPaused ? (_jsx(PlayIcon, { className: "sb-w-3 sb-h-3" })) : (_jsx(PauseIcon, { className: "sb-w-3 sb-h-3" })) }), _jsx("button", { onClick: () => {
|
36
51
|
seek(seekStep);
|
37
|
-
}, children: _jsx(ForwardIcon, { className: "sb-w-3 sb-h-3" }) }), _jsx(CurrentTimeLabel, {}), _jsx("div", { className: "sb-w-[30%] hover:sb-w-[45%] sb-transition-all sb-ease-in-out sb-duration-500", children: _jsx(TimeSliderContainer, { chapters: chapters, notes: notes }) }), _jsx("p", { children: durationFormater(duration) }), _jsx("div", { className: "sb-
|
52
|
+
}, children: _jsx(ForwardIcon, { className: "sb-w-3 sb-h-3" }) }), _jsx(CurrentTimeLabel, {}), _jsx("div", { className: "sb-w-[30%] hover:sb-w-[45%] sb-transition-all sb-ease-in-out sb-duration-500", children: _jsx(TimeSliderContainer, { chapters: chapters, notes: notes }) }), _jsx("p", { children: durationFormater(duration) }), _jsx("div", { className: "sb-h-full", children: _jsx(VolumeSlider, { width: width }) }), _jsx(QualityMenu, {}), _jsx("button", { onClick: () => {
|
38
53
|
if (player === null || player === void 0 ? void 0 : player.isFullscreen()) {
|
39
54
|
player === null || player === void 0 ? void 0 : player.exitFullscreen();
|
40
55
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ControlBar/index.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ControlBar/index.tsx"],"names":[],"mappings":"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"}
|
@@ -1,127 +1,150 @@
|
|
1
|
-
import React, { useEffect } from "react";
|
2
|
-
|
3
|
-
import Player from "video.js/dist/types/player";
|
4
|
-
import CurrentTimeLabel from "../CurrentTimeLabel";
|
5
|
-
import { durationFormater } from "../../utils";
|
6
|
-
import VolumeSlider from "../VolumeSlider";
|
7
|
-
import QualityMenu from "../QualityMenu";
|
8
|
-
|
9
|
-
import CreateNoteMenu from "../CreateNoteMenu";
|
10
|
-
import TimeSliderContainer from "../TimeSliderContainer";
|
11
|
-
import BufferTracker from "../BufferTracker";
|
12
|
-
import CurrentTimeTracker from "../CurrentTimeTracker";
|
13
|
-
import {
|
14
|
-
SoftBuildersVideoPlayerChapter,
|
15
|
-
SoftBuildersVideoPlayerNote,
|
16
|
-
} from "../../types";
|
17
|
-
import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
|
18
|
-
import SubtitleMenu from "../SubtitleMenu";
|
19
|
-
import {
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
<
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
1
|
+
import React, { useEffect, useState } from "react";
|
2
|
+
|
3
|
+
import Player from "video.js/dist/types/player";
|
4
|
+
import CurrentTimeLabel from "../CurrentTimeLabel";
|
5
|
+
import { durationFormater } from "../../utils";
|
6
|
+
import VolumeSlider from "../VolumeSlider";
|
7
|
+
import QualityMenu from "../QualityMenu";
|
8
|
+
|
9
|
+
import CreateNoteMenu from "../CreateNoteMenu";
|
10
|
+
import TimeSliderContainer from "../TimeSliderContainer";
|
11
|
+
import BufferTracker from "../BufferTracker";
|
12
|
+
import CurrentTimeTracker from "../CurrentTimeTracker";
|
13
|
+
import {
|
14
|
+
SoftBuildersVideoPlayerChapter,
|
15
|
+
SoftBuildersVideoPlayerNote,
|
16
|
+
} from "../../types";
|
17
|
+
import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
|
18
|
+
import SubtitleMenu from "../SubtitleMenu";
|
19
|
+
import {
|
20
|
+
BackwardIcon,
|
21
|
+
ForwardIcon,
|
22
|
+
FullScreenIcon,
|
23
|
+
PauseIcon,
|
24
|
+
PlayIcon,
|
25
|
+
} from "../../images";
|
26
|
+
|
27
|
+
type Props<T> = {
|
28
|
+
player: Player | undefined;
|
29
|
+
isPaused: boolean;
|
30
|
+
setIsPaused: React.Dispatch<React.SetStateAction<boolean>>;
|
31
|
+
duration: number;
|
32
|
+
notes: SoftBuildersVideoPlayerNote[];
|
33
|
+
chapters: SoftBuildersVideoPlayerChapter[];
|
34
|
+
seekStep?: number;
|
35
|
+
id?: string;
|
36
|
+
handleSaveNoteAction?: (time: number, note: string) => Promise<T>;
|
37
|
+
};
|
38
|
+
const ControlBar = <T,>({
|
39
|
+
player,
|
40
|
+
isPaused,
|
41
|
+
setIsPaused,
|
42
|
+
duration,
|
43
|
+
notes,
|
44
|
+
chapters,
|
45
|
+
seekStep = 5,
|
46
|
+
id,
|
47
|
+
handleSaveNoteAction,
|
48
|
+
}: Props<T>) => {
|
49
|
+
const { setPlayer, setDuration } = useSoftBuildersVideoPlayerContext();
|
50
|
+
const [width, setwidth] = useState(null);
|
51
|
+
|
52
|
+
const seek = (duration: number) => {
|
53
|
+
const currentTime = Number(player?.currentTime() || 0);
|
54
|
+
player?.currentTime(currentTime + duration);
|
55
|
+
};
|
56
|
+
const container = document.getElementById(`video-container-${id}`);
|
57
|
+
function handleWidthChange(width) {
|
58
|
+
setwidth(width);
|
59
|
+
console.log(width);
|
60
|
+
}
|
61
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
62
|
+
for (let entry of entries) {
|
63
|
+
const currentWidth = entry.contentRect.width;
|
64
|
+
handleWidthChange(currentWidth); // Call the action when width changes
|
65
|
+
}
|
66
|
+
});
|
67
|
+
|
68
|
+
// Start observing the element
|
69
|
+
resizeObserver.observe(container);
|
70
|
+
const togglePlay = (e) => {
|
71
|
+
e.stopPropagation();
|
72
|
+
if (isPaused) player?.play();
|
73
|
+
else player?.pause();
|
74
|
+
|
75
|
+
setIsPaused(!isPaused);
|
76
|
+
};
|
77
|
+
|
78
|
+
useEffect(() => {
|
79
|
+
setPlayer(player);
|
80
|
+
}, [player]);
|
81
|
+
|
82
|
+
useEffect(() => {
|
83
|
+
setDuration(duration);
|
84
|
+
}, [duration]);
|
85
|
+
|
86
|
+
return (
|
87
|
+
<div className=" sb-px-2 sb-flex sb-justify-center sb-gap-3 sb-w-full sb-h-full sb-items-end pb-2">
|
88
|
+
{/* Doesn't display anything, just set the downloaded buffer persentage */}
|
89
|
+
<BufferTracker />
|
90
|
+
{/* Doesn't display anything, just set the current time */}
|
91
|
+
<CurrentTimeTracker />
|
92
|
+
|
93
|
+
<button
|
94
|
+
onClick={() => {
|
95
|
+
seek(-seekStep);
|
96
|
+
}}
|
97
|
+
>
|
98
|
+
<BackwardIcon className="sb-w-3 sb-h-3" />
|
99
|
+
</button>
|
100
|
+
<button onClick={togglePlay}>
|
101
|
+
{isPaused ? (
|
102
|
+
<PlayIcon className="sb-w-3 sb-h-3" />
|
103
|
+
) : (
|
104
|
+
<PauseIcon className="sb-w-3 sb-h-3" />
|
105
|
+
)}
|
106
|
+
</button>
|
107
|
+
<button
|
108
|
+
onClick={() => {
|
109
|
+
seek(seekStep);
|
110
|
+
}}
|
111
|
+
>
|
112
|
+
<ForwardIcon className="sb-w-3 sb-h-3" />
|
113
|
+
</button>
|
114
|
+
|
115
|
+
<CurrentTimeLabel />
|
116
|
+
|
117
|
+
<div className="sb-w-[30%] hover:sb-w-[45%] sb-transition-all sb-ease-in-out sb-duration-500">
|
118
|
+
<TimeSliderContainer chapters={chapters} notes={notes} />
|
119
|
+
</div>
|
120
|
+
|
121
|
+
<p>{durationFormater(duration)}</p>
|
122
|
+
|
123
|
+
<div className="sb-h-full">
|
124
|
+
<VolumeSlider width={width} />
|
125
|
+
</div>
|
126
|
+
|
127
|
+
<QualityMenu />
|
128
|
+
|
129
|
+
<button
|
130
|
+
onClick={() => {
|
131
|
+
if (player?.isFullscreen()) {
|
132
|
+
player?.exitFullscreen();
|
133
|
+
} else {
|
134
|
+
player?.requestFullscreen();
|
135
|
+
}
|
136
|
+
}}
|
137
|
+
>
|
138
|
+
<FullScreenIcon className="sb-w-3 sb-h-3" />
|
139
|
+
</button>
|
140
|
+
|
141
|
+
{handleSaveNoteAction && (
|
142
|
+
<CreateNoteMenu handleSaveNoteAction={handleSaveNoteAction} />
|
143
|
+
)}
|
144
|
+
|
145
|
+
<SubtitleMenu />
|
146
|
+
</div>
|
147
|
+
);
|
148
|
+
};
|
149
|
+
|
150
|
+
export default ControlBar;
|
@@ -1,61 +1,61 @@
|
|
1
|
-
import React, { useState } from "react";
|
2
|
-
import MenuButton from "../MenuButton";
|
3
|
-
import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
|
4
|
-
import { ClosedNoteIcon } from "../../images";
|
5
|
-
|
6
|
-
type Props<T> = {
|
7
|
-
handleSaveNoteAction?: (time: number, note: string) => Promise<T>;
|
8
|
-
};
|
9
|
-
const CreateNoteMenu = <T,>({ handleSaveNoteAction }: Props<T>) => {
|
10
|
-
const { player } = useSoftBuildersVideoPlayerContext();
|
11
|
-
|
12
|
-
const [note, setNote] = useState("");
|
13
|
-
|
14
|
-
const handleSaveNote = () => {
|
15
|
-
if (handleSaveNoteAction) {
|
16
|
-
const time = player?.currentTime() || 0;
|
17
|
-
handleSaveNoteAction(time, note).then((response) => {
|
18
|
-
setNote("");
|
19
|
-
});
|
20
|
-
} else {
|
21
|
-
window.alert(
|
22
|
-
"Video Player, there is no implementation for the handleSaveNoteAction function"
|
23
|
-
);
|
24
|
-
}
|
25
|
-
};
|
26
|
-
|
27
|
-
return (
|
28
|
-
<MenuButton
|
29
|
-
buttonContent={<ClosedNoteIcon className="sb-w-3 sb-h-3" />}
|
30
|
-
menuContent={
|
31
|
-
<div className="sb-rounded-md sb-bg-[#303030] sb-bg-opacity-50 sb-py-5 sb-w-[220px]">
|
32
|
-
<div className="sb-flex sb-flex-col sb-gap-3">
|
33
|
-
<h3 className="sb-px-5">Add Note</h3>
|
34
|
-
|
35
|
-
<div className="sb-w-full sb-h-[.1px] sb-bg-[#AAAAAA] sb-bg-opacity-70" />
|
36
|
-
|
37
|
-
<div className="sb-px-5 sb-flex sb-flex-col sb-gap-4 sb-items-start">
|
38
|
-
<input
|
39
|
-
name="note"
|
40
|
-
type="text"
|
41
|
-
placeholder="Add a note"
|
42
|
-
value={note}
|
43
|
-
onChange={(e) => setNote(e.target.value)}
|
44
|
-
required
|
45
|
-
className="sb-text-white placeholder:sb-text-white sb-w-full sb-bg-transparent sb-px-4 sb-py-3 sb-border sb-border-[#AAAAAA] sb-rounded-md"
|
46
|
-
/>
|
47
|
-
|
48
|
-
<button className="sb-w-full" onClick={handleSaveNote}>
|
49
|
-
<div className="sb-px-4 sb-py-3 sb-text-center sb-font-bold sb-bg-orange-500 sb-rounded-md">
|
50
|
-
Save
|
51
|
-
</div>
|
52
|
-
</button>
|
53
|
-
</div>
|
54
|
-
</div>
|
55
|
-
</div>
|
56
|
-
}
|
57
|
-
/>
|
58
|
-
);
|
59
|
-
};
|
60
|
-
|
61
|
-
export default CreateNoteMenu;
|
1
|
+
import React, { useState } from "react";
|
2
|
+
import MenuButton from "../MenuButton";
|
3
|
+
import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
|
4
|
+
import { ClosedNoteIcon } from "../../images";
|
5
|
+
|
6
|
+
type Props<T> = {
|
7
|
+
handleSaveNoteAction?: (time: number, note: string) => Promise<T>;
|
8
|
+
};
|
9
|
+
const CreateNoteMenu = <T,>({ handleSaveNoteAction }: Props<T>) => {
|
10
|
+
const { player } = useSoftBuildersVideoPlayerContext();
|
11
|
+
|
12
|
+
const [note, setNote] = useState("");
|
13
|
+
|
14
|
+
const handleSaveNote = () => {
|
15
|
+
if (handleSaveNoteAction) {
|
16
|
+
const time = player?.currentTime() || 0;
|
17
|
+
handleSaveNoteAction(time, note).then((response) => {
|
18
|
+
setNote("");
|
19
|
+
});
|
20
|
+
} else {
|
21
|
+
window.alert(
|
22
|
+
"Video Player, there is no implementation for the handleSaveNoteAction function"
|
23
|
+
);
|
24
|
+
}
|
25
|
+
};
|
26
|
+
|
27
|
+
return (
|
28
|
+
<MenuButton
|
29
|
+
buttonContent={<ClosedNoteIcon className="sb-w-3 sb-h-3" />}
|
30
|
+
menuContent={
|
31
|
+
<div className="sb-rounded-md sb-bg-[#303030] sb-bg-opacity-50 sb-py-5 sb-w-[220px]">
|
32
|
+
<div className="sb-flex sb-flex-col sb-gap-3">
|
33
|
+
<h3 className="sb-px-5">Add Note</h3>
|
34
|
+
|
35
|
+
<div className="sb-w-full sb-h-[.1px] sb-bg-[#AAAAAA] sb-bg-opacity-70" />
|
36
|
+
|
37
|
+
<div className="sb-px-5 sb-flex sb-flex-col sb-gap-4 sb-items-start">
|
38
|
+
<input
|
39
|
+
name="note"
|
40
|
+
type="text"
|
41
|
+
placeholder="Add a note"
|
42
|
+
value={note}
|
43
|
+
onChange={(e) => setNote(e.target.value)}
|
44
|
+
required
|
45
|
+
className="sb-text-white placeholder:sb-text-white sb-w-full sb-bg-transparent sb-px-4 sb-py-3 sb-border sb-border-[#AAAAAA] sb-rounded-md"
|
46
|
+
/>
|
47
|
+
|
48
|
+
<button className="sb-w-full" onClick={handleSaveNote}>
|
49
|
+
<div className="sb-px-4 sb-py-3 sb-text-center sb-font-bold sb-bg-orange-500 sb-rounded-md">
|
50
|
+
Save
|
51
|
+
</div>
|
52
|
+
</button>
|
53
|
+
</div>
|
54
|
+
</div>
|
55
|
+
</div>
|
56
|
+
}
|
57
|
+
/>
|
58
|
+
);
|
59
|
+
};
|
60
|
+
|
61
|
+
export default CreateNoteMenu;
|
@@ -1,13 +1,13 @@
|
|
1
|
-
"use client";
|
2
|
-
import React, { useEffect } from "react";
|
3
|
-
import { durationFormater } from "../../utils";
|
4
|
-
import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
|
5
|
-
type Props = {};
|
6
|
-
|
7
|
-
const CurrentTimeLabel = ({}: Props) => {
|
8
|
-
const { currentTime } = useSoftBuildersVideoPlayerContext();
|
9
|
-
|
10
|
-
return <p>{durationFormater(currentTime)}</p>;
|
11
|
-
};
|
12
|
-
|
13
|
-
export default CurrentTimeLabel;
|
1
|
+
"use client";
|
2
|
+
import React, { useEffect } from "react";
|
3
|
+
import { durationFormater } from "../../utils";
|
4
|
+
import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
|
5
|
+
type Props = {};
|
6
|
+
|
7
|
+
const CurrentTimeLabel = ({}: Props) => {
|
8
|
+
const { currentTime } = useSoftBuildersVideoPlayerContext();
|
9
|
+
|
10
|
+
return <p>{durationFormater(currentTime)}</p>;
|
11
|
+
};
|
12
|
+
|
13
|
+
export default CurrentTimeLabel;
|
@@ -1,18 +1,18 @@
|
|
1
|
-
import React, { useEffect } from "react";
|
2
|
-
import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
|
3
|
-
|
4
|
-
const CurrentTimeTracker = () => {
|
5
|
-
const { setCurrentTime, player } = useSoftBuildersVideoPlayerContext();
|
6
|
-
|
7
|
-
useEffect(() => {
|
8
|
-
const intervalId = setInterval(() => {
|
9
|
-
setCurrentTime(player?.currentTime() || 0);
|
10
|
-
}, 500);
|
11
|
-
|
12
|
-
// Cleanup function to clear the interval
|
13
|
-
return () => clearInterval(intervalId);
|
14
|
-
}, [player]);
|
15
|
-
return <></>;
|
16
|
-
};
|
17
|
-
|
18
|
-
export default CurrentTimeTracker;
|
1
|
+
import React, { useEffect } from "react";
|
2
|
+
import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
|
3
|
+
|
4
|
+
const CurrentTimeTracker = () => {
|
5
|
+
const { setCurrentTime, player } = useSoftBuildersVideoPlayerContext();
|
6
|
+
|
7
|
+
useEffect(() => {
|
8
|
+
const intervalId = setInterval(() => {
|
9
|
+
setCurrentTime(player?.currentTime() || 0);
|
10
|
+
}, 500);
|
11
|
+
|
12
|
+
// Cleanup function to clear the interval
|
13
|
+
return () => clearInterval(intervalId);
|
14
|
+
}, [player]);
|
15
|
+
return <></>;
|
16
|
+
};
|
17
|
+
|
18
|
+
export default CurrentTimeTracker;
|
@@ -1,49 +1,49 @@
|
|
1
|
-
import React from "react";
|
2
|
-
|
3
|
-
type Props = {
|
4
|
-
name: string;
|
5
|
-
};
|
6
|
-
|
7
|
-
const Menu = ({ name }: Props) => {
|
8
|
-
return (
|
9
|
-
<div className="absolute right-0 z-10 w-48 mt-2 origin-top-right bg-white border border-gray-300 rounded-md shadow-lg focus:outline-none">
|
10
|
-
<div
|
11
|
-
className="py-1"
|
12
|
-
role="menu"
|
13
|
-
aria-orientation="vertical"
|
14
|
-
aria-labelledby={`${name}-button`}
|
15
|
-
>
|
16
|
-
<a
|
17
|
-
href="#"
|
18
|
-
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
19
|
-
role="menuitem"
|
20
|
-
>
|
21
|
-
Dashboard
|
22
|
-
</a>
|
23
|
-
<a
|
24
|
-
href="#"
|
25
|
-
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
26
|
-
role="menuitem"
|
27
|
-
>
|
28
|
-
Settings
|
29
|
-
</a>
|
30
|
-
<a
|
31
|
-
href="#"
|
32
|
-
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
33
|
-
role="menuitem"
|
34
|
-
>
|
35
|
-
Profile
|
36
|
-
</a>
|
37
|
-
<a
|
38
|
-
href="#"
|
39
|
-
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
40
|
-
role="menuitem"
|
41
|
-
>
|
42
|
-
Logout
|
43
|
-
</a>
|
44
|
-
</div>
|
45
|
-
</div>
|
46
|
-
);
|
47
|
-
};
|
48
|
-
|
49
|
-
export default Menu;
|
1
|
+
import React from "react";
|
2
|
+
|
3
|
+
type Props = {
|
4
|
+
name: string;
|
5
|
+
};
|
6
|
+
|
7
|
+
const Menu = ({ name }: Props) => {
|
8
|
+
return (
|
9
|
+
<div className="absolute right-0 z-10 w-48 mt-2 origin-top-right bg-white border border-gray-300 rounded-md shadow-lg focus:outline-none">
|
10
|
+
<div
|
11
|
+
className="py-1"
|
12
|
+
role="menu"
|
13
|
+
aria-orientation="vertical"
|
14
|
+
aria-labelledby={`${name}-button`}
|
15
|
+
>
|
16
|
+
<a
|
17
|
+
href="#"
|
18
|
+
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
19
|
+
role="menuitem"
|
20
|
+
>
|
21
|
+
Dashboard
|
22
|
+
</a>
|
23
|
+
<a
|
24
|
+
href="#"
|
25
|
+
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
26
|
+
role="menuitem"
|
27
|
+
>
|
28
|
+
Settings
|
29
|
+
</a>
|
30
|
+
<a
|
31
|
+
href="#"
|
32
|
+
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
33
|
+
role="menuitem"
|
34
|
+
>
|
35
|
+
Profile
|
36
|
+
</a>
|
37
|
+
<a
|
38
|
+
href="#"
|
39
|
+
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
40
|
+
role="menuitem"
|
41
|
+
>
|
42
|
+
Logout
|
43
|
+
</a>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
);
|
47
|
+
};
|
48
|
+
|
49
|
+
export default Menu;
|
@@ -24,7 +24,7 @@ const MenuButton = ({ buttonContent, menuContent, close }) => {
|
|
24
24
|
if (close)
|
25
25
|
close(closeMenu);
|
26
26
|
}, [close, closeMenu]);
|
27
|
-
return (_jsxs("div", { className: "sb-relative", children: [_jsx("button", { ref: buttonRef, onClick: toggleMenu, "aria-haspopup": "true", "aria-expanded": isOpen, "aria-label": "Open menu", children: buttonContent }), isOpen && (_jsx("div", { ref: menuRef, role: "menu", "aria-orientation": "vertical", "aria-labelledby": "Open menu", className: "sb-absolute sb-shadow-lg sb-right-0 sb-bottom-10", children: menuContent }))] }));
|
27
|
+
return (_jsxs("div", { className: "sb-relative sb-flex sb-items-end", children: [_jsx("button", { ref: buttonRef, onClick: toggleMenu, "aria-haspopup": "true", "aria-expanded": isOpen, "aria-label": "Open menu", children: buttonContent }), isOpen && (_jsx("div", { ref: menuRef, role: "menu", "aria-orientation": "vertical", "aria-labelledby": "Open menu", className: "sb-absolute sb-shadow-lg sb-right-0 sb-bottom-10", children: menuContent }))] }));
|
28
28
|
};
|
29
29
|
export default MenuButton;
|
30
30
|
//# sourceMappingURL=index.js.map
|