softbuilders-react-video-player 1.1.16 → 1.1.18

Sign up to get free protection for your applications and to get access to all the features.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 masri-softbuilders
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2024 masri-softbuilders
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,126 +1,126 @@
1
- # Usage
2
-
3
- ## install the package
4
-
5
- ```bash
6
- npm i softbuilders-video-player
7
- ```
8
-
9
- ## How to use
10
-
11
- ```typescript
12
- import SoftBuildersVideoPlayer, {
13
- SoftBuildersVideoPlayerOptions,
14
- SoftBuildersVideoPlayerChapter,
15
- SoftBuildersVideoPlayerNote,
16
- } from "softbuilders-video-player";
17
-
18
- const options: SoftBuildersVideoPlayerOptions = {
19
- autoplay: false,
20
- controls: true,
21
- muted: true,
22
- fluid: true,
23
- poster: "http://example.com/thumbnail.png", // thumbnail preview image
24
- height: 420,
25
- width: 720,
26
- sources: [
27
- {
28
- src: "https://upload.wikimedia.org/wikipedia/commons/transcoded/a/ab/Caminandes_3_-_Llamigos_-_Blender_Animated_Short.webm/Caminandes_3_-_Llamigos_-_Blender_Animated_Short.webm.360p.vp9.webm",
29
- type: "video/webm",
30
- label: "360p",
31
- },
32
- {
33
- src: "https://upload.wikimedia.org/wikipedia/commons/transcoded/a/ab/Caminandes_3_-_Llamigos_-_Blender_Animated_Short.webm/Caminandes_3_-_Llamigos_-_Blender_Animated_Short.webm.1080p.vp9.webm",
34
- type: "video/webm",
35
- label: "1080P",
36
- },
37
- ],
38
- tracks: [
39
- {
40
- kind: "captions",
41
- src: "https://raw.githubusercontent.com/brenopolanski/html5-video-webvtt-example/master/MIB2-subtitles-pt-BR.vtt",
42
- srclang: "en",
43
- label: "English",
44
- memeType: "text/vtt", // text/vtt or text/srt
45
- default: true,
46
- },
47
- {
48
- kind: "captions",
49
- src: "https://gist.githubusercontent.com/samdutton/ca37f3adaf4e23679957b8083e061177/raw/e19399fbccbc069a2af4266e5120ae6bad62699a/sample.vtt",
50
- srclang: "es",
51
- label: "Espaniol",
52
- memeType: "text/vtt", // text/vtt or text/srt
53
- },
54
- ], // only vtt suptitilers are supported for now
55
- };
56
-
57
- const initNotes: SoftBuildersVideoPlayerNote[] = [
58
- {
59
- time: 5,
60
- label: "Start",
61
- },
62
- {
63
- time: 30,
64
- label: "Say Hello",
65
- },
66
- {
67
- time: 69,
68
- label: "Go deep",
69
- },
70
- {
71
- time: 99,
72
- label: "Details ...",
73
- },
74
- {
75
- time: 140,
76
- label: "End",
77
- },
78
- ];
79
-
80
- const initChapters: SoftBuildersVideoPlayerChapter[] = [
81
- {
82
- startTime: 25,
83
- endTime: 50,
84
- title: "01 Note: **** Important ****",
85
- },
86
- {
87
- startTime: 70,
88
- endTime: 100,
89
- title: "02 Note: To Do",
90
- },
91
- { startTime: 110, endTime: 120, title: "03 Note: DIY (Do it yourself)" },
92
- {
93
- startTime: 125,
94
- endTime: 140,
95
- title: "05 Note: Conclusion ",
96
- },
97
- ];
98
-
99
- const Component = () => {
100
- const handleSaveNoteAction = (time: number, note: string) => {
101
- return new Promise((resolve) => {
102
- resolve(true);
103
- });
104
- };
105
-
106
- const onPause = (time: number) => {
107
- console.log(`Video has been Paused at time (${time} sec)`);
108
- };
109
- const onPlay = (time: number) => {
110
- console.log(`Video has been Played at time (${time} sec)`);
111
- };
112
-
113
- return (
114
- <SoftBuildersVideoPlayer
115
- options={options}
116
- chapters={initChapters}
117
- notes={initNotes}
118
- handleSaveNoteAction={handleSaveNoteAction}
119
- onPause={onPause}
120
- onPlay={onPlay}
121
- />
122
- );
123
- };
124
-
125
- export default Component;
126
- ```
1
+ # Usage
2
+
3
+ ## install the package
4
+
5
+ ```bash
6
+ npm i softbuilders-video-player
7
+ ```
8
+
9
+ ## How to use
10
+
11
+ ```typescript
12
+ import SoftBuildersVideoPlayer, {
13
+ SoftBuildersVideoPlayerOptions,
14
+ SoftBuildersVideoPlayerChapter,
15
+ SoftBuildersVideoPlayerNote,
16
+ } from "softbuilders-video-player";
17
+
18
+ const options: SoftBuildersVideoPlayerOptions = {
19
+ autoplay: false,
20
+ controls: true,
21
+ muted: true,
22
+ fluid: true,
23
+ poster: "http://example.com/thumbnail.png", // thumbnail preview image
24
+ height: 420,
25
+ width: 720,
26
+ sources: [
27
+ {
28
+ src: "https://upload.wikimedia.org/wikipedia/commons/transcoded/a/ab/Caminandes_3_-_Llamigos_-_Blender_Animated_Short.webm/Caminandes_3_-_Llamigos_-_Blender_Animated_Short.webm.360p.vp9.webm",
29
+ type: "video/webm",
30
+ label: "360p",
31
+ },
32
+ {
33
+ src: "https://upload.wikimedia.org/wikipedia/commons/transcoded/a/ab/Caminandes_3_-_Llamigos_-_Blender_Animated_Short.webm/Caminandes_3_-_Llamigos_-_Blender_Animated_Short.webm.1080p.vp9.webm",
34
+ type: "video/webm",
35
+ label: "1080P",
36
+ },
37
+ ],
38
+ tracks: [
39
+ {
40
+ kind: "captions",
41
+ src: "https://raw.githubusercontent.com/brenopolanski/html5-video-webvtt-example/master/MIB2-subtitles-pt-BR.vtt",
42
+ srclang: "en",
43
+ label: "English",
44
+ memeType: "text/vtt", // text/vtt or text/srt
45
+ default: true,
46
+ },
47
+ {
48
+ kind: "captions",
49
+ src: "https://gist.githubusercontent.com/samdutton/ca37f3adaf4e23679957b8083e061177/raw/e19399fbccbc069a2af4266e5120ae6bad62699a/sample.vtt",
50
+ srclang: "es",
51
+ label: "Espaniol",
52
+ memeType: "text/vtt", // text/vtt or text/srt
53
+ },
54
+ ], // only vtt suptitilers are supported for now
55
+ };
56
+
57
+ const initNotes: SoftBuildersVideoPlayerNote[] = [
58
+ {
59
+ time: 5,
60
+ label: "Start",
61
+ },
62
+ {
63
+ time: 30,
64
+ label: "Say Hello",
65
+ },
66
+ {
67
+ time: 69,
68
+ label: "Go deep",
69
+ },
70
+ {
71
+ time: 99,
72
+ label: "Details ...",
73
+ },
74
+ {
75
+ time: 140,
76
+ label: "End",
77
+ },
78
+ ];
79
+
80
+ const initChapters: SoftBuildersVideoPlayerChapter[] = [
81
+ {
82
+ startTime: 25,
83
+ endTime: 50,
84
+ title: "01 Note: **** Important ****",
85
+ },
86
+ {
87
+ startTime: 70,
88
+ endTime: 100,
89
+ title: "02 Note: To Do",
90
+ },
91
+ { startTime: 110, endTime: 120, title: "03 Note: DIY (Do it yourself)" },
92
+ {
93
+ startTime: 125,
94
+ endTime: 140,
95
+ title: "05 Note: Conclusion ",
96
+ },
97
+ ];
98
+
99
+ const Component = () => {
100
+ const handleSaveNoteAction = (time: number, note: string) => {
101
+ return new Promise((resolve) => {
102
+ resolve(true);
103
+ });
104
+ };
105
+
106
+ const onPause = (time: number) => {
107
+ console.log(`Video has been Paused at time (${time} sec)`);
108
+ };
109
+ const onPlay = (time: number) => {
110
+ console.log(`Video has been Played at time (${time} sec)`);
111
+ };
112
+
113
+ return (
114
+ <SoftBuildersVideoPlayer
115
+ options={options}
116
+ chapters={initChapters}
117
+ notes={initNotes}
118
+ handleSaveNoteAction={handleSaveNoteAction}
119
+ onPause={onPause}
120
+ onPlay={onPlay}
121
+ />
122
+ );
123
+ };
124
+
125
+ export default Component;
126
+ ```
@@ -1,19 +1,19 @@
1
- import React, { useEffect } from "react";
2
- import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
3
-
4
- const BufferTracker = () => {
5
- const { player, setDownloadedBufferTimeufferTime } =
6
- useSoftBuildersVideoPlayerContext();
7
-
8
- useEffect(() => {
9
- const intervalId = setInterval(() => {
10
- if (player) setDownloadedBufferTimeufferTime(player.bufferedEnd());
11
- }, 1000);
12
-
13
- // Cleanup function to clear the interval
14
- return () => clearInterval(intervalId);
15
- }, [player]);
16
- return <></>;
17
- };
18
-
19
- export default BufferTracker;
1
+ import React, { useEffect } from "react";
2
+ import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
3
+
4
+ const BufferTracker = () => {
5
+ const { player, setDownloadedBufferTimeufferTime } =
6
+ useSoftBuildersVideoPlayerContext();
7
+
8
+ useEffect(() => {
9
+ const intervalId = setInterval(() => {
10
+ if (player) setDownloadedBufferTimeufferTime(player.bufferedEnd());
11
+ }, 1000);
12
+
13
+ // Cleanup function to clear the interval
14
+ return () => clearInterval(intervalId);
15
+ }, [player]);
16
+ return <></>;
17
+ };
18
+
19
+ export default BufferTracker;
@@ -1,65 +1,65 @@
1
- import React, { useEffect, useState } from "react";
2
- import Tooltip from "../Tooltip";
3
- import { durationFormater } from "../../utils";
4
- import { SoftBuildersVideoPlayerChapter } from "../../types";
5
- import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
6
- type Chapter = SoftBuildersVideoPlayerChapter & {
7
- startPercentage: number;
8
- endPercentage: number;
9
- };
10
- type Props = {
11
- chapter: Chapter;
12
- };
13
- const ChapterTooltip = ({ chapter }: Props) => {
14
- const { player } = useSoftBuildersVideoPlayerContext();
15
-
16
- const [open, setOpen] = useState(false);
17
- const { currentTime } = useSoftBuildersVideoPlayerContext();
18
-
19
- useEffect(() => {
20
- if (currentTime === Math.floor(chapter.startTime)) {
21
- setOpen(true);
22
-
23
- setTimeout(() => {
24
- setOpen(false);
25
- }, 5000);
26
- }
27
- }, [currentTime, chapter.startTime]);
28
-
29
- const handleClickChapter = () => {
30
- player?.currentTime(chapter.startTime);
31
- };
32
-
33
- return (
34
- <div
35
- id={`ii-section-${chapter.title}`}
36
- className="sb-flex sb-items-center sb-w-full sb-h-full sb-absolute sb-z-20"
37
- style={{
38
- left: `${chapter.startPercentage}%`,
39
- width: `${chapter.endPercentage - chapter.startPercentage}%`,
40
- }}
41
- onMouseEnter={() => setOpen(true)}
42
- onMouseLeave={() => setOpen(false)}
43
- >
44
- <button
45
- id={`section-${chapter.title}`}
46
- className="sb-h-full sb-w-full"
47
- onClick={handleClickChapter}
48
- >
49
- <div className="sb-relative sb-flex sb-h-full sb-w-full sb-justify-between sb-items-center">
50
- <Tooltip open={open}>
51
- <div className="sb-flex sb-flex-col sb-gap-2 sb-items-center">
52
- <p>{chapter.title}</p>
53
- <p className="sb-p-2 sb-bg-[#303030] sb-bg-opacity-50 sb-rounded-md">
54
- {durationFormater(chapter.startTime)} -{" "}
55
- {durationFormater(chapter.endTime)}
56
- </p>
57
- </div>
58
- </Tooltip>
59
- </div>
60
- </button>
61
- </div>
62
- );
63
- };
64
-
65
- export default ChapterTooltip;
1
+ import React, { useEffect, useState } from "react";
2
+ import Tooltip from "../Tooltip";
3
+ import { durationFormater } from "../../utils";
4
+ import { SoftBuildersVideoPlayerChapter } from "../../types";
5
+ import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
6
+ type Chapter = SoftBuildersVideoPlayerChapter & {
7
+ startPercentage: number;
8
+ endPercentage: number;
9
+ };
10
+ type Props = {
11
+ chapter: Chapter;
12
+ };
13
+ const ChapterTooltip = ({ chapter }: Props) => {
14
+ const { player } = useSoftBuildersVideoPlayerContext();
15
+
16
+ const [open, setOpen] = useState(false);
17
+ const { currentTime } = useSoftBuildersVideoPlayerContext();
18
+
19
+ useEffect(() => {
20
+ if (currentTime === Math.floor(chapter.startTime)) {
21
+ setOpen(true);
22
+
23
+ setTimeout(() => {
24
+ setOpen(false);
25
+ }, 5000);
26
+ }
27
+ }, [currentTime, chapter.startTime]);
28
+
29
+ const handleClickChapter = () => {
30
+ player?.currentTime(chapter.startTime);
31
+ };
32
+
33
+ return (
34
+ <div
35
+ id={`ii-section-${chapter.title}`}
36
+ className="sb-flex sb-items-center sb-w-full sb-h-full sb-absolute sb-z-20"
37
+ style={{
38
+ left: `${chapter.startPercentage}%`,
39
+ width: `${chapter.endPercentage - chapter.startPercentage}%`,
40
+ }}
41
+ onMouseEnter={() => setOpen(true)}
42
+ onMouseLeave={() => setOpen(false)}
43
+ >
44
+ <button
45
+ id={`section-${chapter.title}`}
46
+ className="sb-h-full sb-w-full"
47
+ onClick={handleClickChapter}
48
+ >
49
+ <div className="sb-relative sb-flex sb-h-full sb-w-full sb-justify-between sb-items-center">
50
+ <Tooltip open={open}>
51
+ <div className="sb-flex sb-flex-col sb-gap-2 sb-items-center">
52
+ <p>{chapter.title}</p>
53
+ <p className="sb-p-2 sb-bg-[#303030] sb-bg-opacity-50 sb-rounded-md">
54
+ {durationFormater(chapter.startTime)} -{" "}
55
+ {durationFormater(chapter.endTime)}
56
+ </p>
57
+ </div>
58
+ </Tooltip>
59
+ </div>
60
+ </button>
61
+ </div>
62
+ );
63
+ };
64
+
65
+ export default ChapterTooltip;
@@ -1,40 +1,40 @@
1
- import React, { useEffect, useState } from "react";
2
-
3
- import ChapterTooltip from "../ChapterTooltip";
4
- import { SoftBuildersVideoPlayerChapter } from "../../types";
5
- import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
6
-
7
- type Chapter = SoftBuildersVideoPlayerChapter & {
8
- startPercentage: number;
9
- endPercentage: number;
10
- };
11
- type Props = {
12
- chapters: SoftBuildersVideoPlayerChapter[];
13
- };
14
- const ChaptersPanal = ({ chapters }: Props) => {
15
- const [cs, setCs] = useState<Chapter[]>([]);
16
- const { duration } = useSoftBuildersVideoPlayerContext();
17
-
18
- useEffect(() => {
19
- const newCs = chapters.map((c) => {
20
- const startPercentage = Math.floor((c.startTime * 100) / duration);
21
- const endPercentage = Math.floor((c.endTime * 100) / duration);
22
- return {
23
- ...c,
24
- startPercentage,
25
- endPercentage,
26
- };
27
- });
28
- setCs(newCs);
29
- }, [chapters, duration]);
30
-
31
- return (
32
- <div id="chapters-panal" className="sb-w-full sb-h-full sb-relative ">
33
- {cs.map((c, i) => (
34
- <ChapterTooltip key={`chapter-${i}-${c.startTime}`} chapter={c} />
35
- ))}
36
- </div>
37
- );
38
- };
39
-
40
- export default ChaptersPanal;
1
+ import React, { useEffect, useState } from "react";
2
+
3
+ import ChapterTooltip from "../ChapterTooltip";
4
+ import { SoftBuildersVideoPlayerChapter } from "../../types";
5
+ import { useSoftBuildersVideoPlayerContext } from "../VideoPlayerComponent/provider";
6
+
7
+ type Chapter = SoftBuildersVideoPlayerChapter & {
8
+ startPercentage: number;
9
+ endPercentage: number;
10
+ };
11
+ type Props = {
12
+ chapters: SoftBuildersVideoPlayerChapter[];
13
+ };
14
+ const ChaptersPanal = ({ chapters }: Props) => {
15
+ const [cs, setCs] = useState<Chapter[]>([]);
16
+ const { duration } = useSoftBuildersVideoPlayerContext();
17
+
18
+ useEffect(() => {
19
+ const newCs = chapters.map((c) => {
20
+ const startPercentage = Math.floor((c.startTime * 100) / duration);
21
+ const endPercentage = Math.floor((c.endTime * 100) / duration);
22
+ return {
23
+ ...c,
24
+ startPercentage,
25
+ endPercentage,
26
+ };
27
+ });
28
+ setCs(newCs);
29
+ }, [chapters, duration]);
30
+
31
+ return (
32
+ <div id="chapters-panal" className="sb-w-full sb-h-full sb-relative ">
33
+ {cs.map((c, i) => (
34
+ <ChapterTooltip key={`chapter-${i}-${c.startTime}`} chapter={c} />
35
+ ))}
36
+ </div>
37
+ );
38
+ };
39
+
40
+ export default ChaptersPanal;
@@ -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;