l-min-components 1.0.523 → 1.0.528

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "l-min-components",
3
- "version": "1.0.523",
3
+ "version": "1.0.528",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src/assets",
@@ -25,6 +25,7 @@
25
25
  "moment": "^2.29.4",
26
26
  "npm": "^10.2.5",
27
27
  "prop-types": "^15.8.1",
28
+ "rc-pagination": "^4.0.4",
28
29
  "rc-progress": "^3.5.1",
29
30
  "rc-slider": "^10.1.1",
30
31
  "rc-tooltip": "^6.0.1",
@@ -41,6 +42,7 @@
41
42
  "react-lottie": "^1.2.4",
42
43
  "react-mic": "^12.4.6",
43
44
  "react-modal": "^3.16.1",
45
+ "react-player": "^2.14.1",
44
46
  "react-router-dom": "^6.8.2",
45
47
  "react-toastify": "^9.1.3",
46
48
  "react-tooltip": "^5.10.1",
@@ -35,5 +35,7 @@ export { default as InstructorAccountSwitcher } from "./instructorAccountSwitche
35
35
  export { default as InstructorRightBar } from "./fileRightBar/instructorRightBar";
36
36
 
37
37
  export { default as EnterpriseRightBar } from "./fileRightBar/enterpriseRightBar";
38
- export { default as FullPageLoader } from "./fullPageLoader"
39
- export { default as AdminAppMainLayout } from "./AdminAppMainLayout"
38
+ export { default as FullPageLoader } from "./fullPageLoader";
39
+ export { default as AdminAppMainLayout } from "./AdminAppMainLayout";
40
+ export { default as PaginationComponent } from "./paginate";
41
+ export { default as VideoPlayer } from "./video-player";
@@ -0,0 +1,100 @@
1
+ import { styled } from "styled-components";
2
+ import Pagination from "rc-pagination";
3
+
4
+ /**
5
+ *
6
+ * @param {object} props
7
+ * @param {number} props.current - Current page
8
+ * @param {number} props.totalPage - The number of items rendered in a page
9
+ * @param {number} props.totalItem -The complete total number of item
10
+ * @param {Function} props.onChange - A function that set the current page
11
+ * @param {React.CSSProperties} props.style
12
+ * @returns {JSX.Element}
13
+ */
14
+ const Paginate = ({ current, totalPage, totalItem, onChange, style }) => {
15
+ return (
16
+ <Container style={style}>
17
+ <Pagination
18
+ onChange={onChange}
19
+ current={current}
20
+ total={totalItem}
21
+ pageSize={totalPage || 1}
22
+ nextIcon={() => "Next"}
23
+ prevIcon={() => "Prev"}
24
+ jumpNextIcon={() => <More />}
25
+ showLessItems
26
+ jumpPrevIcon={() => <More />}
27
+ />
28
+ </Container>
29
+ );
30
+ };
31
+
32
+ const More = () => {
33
+ return (
34
+ <svg
35
+ width="11"
36
+ height="4"
37
+ viewBox="0 0 11 4"
38
+ fill="none"
39
+ xmlns="http://www.w3.org/2000/svg"
40
+ >
41
+ <path
42
+ d="M1.86 3.09C1.54 3.09 1.275 2.985 1.065 2.775C0.855 2.555 0.75 2.285 0.75 1.965C0.75 1.645 0.855 1.38 1.065 1.17C1.275 0.95 1.54 0.84 1.86 0.84C2.18 0.84 2.445 0.95 2.655 1.17C2.865 1.38 2.97 1.645 2.97 1.965C2.97 2.285 2.865 2.555 2.655 2.775C2.445 2.985 2.18 3.09 1.86 3.09ZM5.5807 3.09C5.2607 3.09 4.9957 2.985 4.7857 2.775C4.5757 2.555 4.4707 2.285 4.4707 1.965C4.4707 1.645 4.5757 1.38 4.7857 1.17C4.9957 0.95 5.2607 0.84 5.5807 0.84C5.9007 0.84 6.1657 0.95 6.3757 1.17C6.5857 1.38 6.6907 1.645 6.6907 1.965C6.6907 2.285 6.5857 2.555 6.3757 2.775C6.1657 2.985 5.9007 3.09 5.5807 3.09ZM9.30141 3.09C8.98141 3.09 8.71641 2.985 8.50641 2.775C8.29641 2.555 8.19141 2.285 8.19141 1.965C8.19141 1.645 8.29641 1.38 8.50641 1.17C8.71641 0.95 8.98141 0.84 9.30141 0.84C9.62141 0.84 9.88641 0.95 10.0964 1.17C10.3064 1.38 10.4114 1.645 10.4114 1.965C10.4114 2.285 10.3064 2.555 10.0964 2.775C9.88641 2.985 9.62141 3.09 9.30141 3.09Z"
43
+ fill="black"
44
+ />
45
+ </svg>
46
+ );
47
+ };
48
+
49
+ export default Paginate;
50
+
51
+ export const Container = styled.div`
52
+ width: 100%;
53
+ display: flex;
54
+ justify-content: center;
55
+ ul {
56
+ display: flex;
57
+ list-style: none;
58
+ gap: 17px;
59
+ li {
60
+ cursor: pointer;
61
+ display: flex;
62
+ width: 40px;
63
+ height: 40px;
64
+ justify-content: center;
65
+ align-items: center;
66
+ border-radius: 50px;
67
+ border: 1px solid #dfe5e5;
68
+ background: #f5f7f7;
69
+ font-size: 15px;
70
+ font-weight: 700;
71
+ color: #4a4d4d;
72
+
73
+ &.rc-pagination-prev,
74
+ &.rc-pagination-next {
75
+ width: 76px;
76
+ }
77
+ &.rc-pagination-item-active {
78
+ background: #febf10;
79
+ a {
80
+ color: #fff;
81
+ }
82
+ }
83
+ &.rc-pagination-jump-next,
84
+ &.rc-pagination-jump-prev {
85
+ background: transparent;
86
+ width: 12px;
87
+ border: none;
88
+ font-size: 15px;
89
+ font-weight: 700;
90
+ }
91
+ &.rc-pagination-disabled {
92
+ opacity: 0.5;
93
+ cursor: not-allowed;
94
+ }
95
+ &.rc-pagination-options {
96
+ display: none;
97
+ }
98
+ }
99
+ }
100
+ `;
@@ -1,4 +1,3 @@
1
- import React from "react";
2
1
  const PauseIcon = ({ fill, onClick }) => {
3
2
  return (
4
3
  <svg
@@ -1,4 +1,3 @@
1
- import React from "react";
2
1
  const PlayVideoIcon = () => {
3
2
  return (
4
3
  <svg
@@ -1,4 +1,3 @@
1
- import React from "react";
2
1
  const VideoScreenIcon = ({ onClick }) => {
3
2
  return (
4
3
  <svg
@@ -0,0 +1,238 @@
1
+ import React, { useState, useRef, useEffect, useContext } from "react";
2
+ import { OutletContext } from "../AppMainLayout";
3
+ import screenfull from "screenfull";
4
+ import {
5
+ LoadingScreen,
6
+ RangeContainer,
7
+ VideoController,
8
+ VideoPlayerContainer,
9
+ VideoPrompts,
10
+ } from "./index.styled";
11
+ import ReactPlayer from "react-player";
12
+ import VideoScreenIcon from "./icons/videoScreenIcon";
13
+ import PlayIcon from "./icons/playVideoIcon";
14
+ import PauseIcon from "./icons/pause";
15
+ // import LoaderCustom from "../loader";
16
+ import FullPageLoader from "../fullPageLoader";
17
+
18
+ /**
19
+ *
20
+ * @param {object} props
21
+ * @param {string} props.width - Width of the player in px
22
+ * @param {string} props.height - Height of the player in px
23
+ * @param {React.CSSProperties} props.style - Player container style
24
+ * @param {boolean} props.hideRange - To hide the range controller
25
+ * @param {boolean} props.showPrompts - show next and prev controller
26
+ * @param {string} props.src - Video source url
27
+ * @param {string} props.streamUrl - Stream video url
28
+ * @param {string} props.thumbnailSrc - Thumbnail url
29
+ * @returns {JSX.Element}
30
+ */
31
+ const VideoPlayer = ({
32
+ width,
33
+ height = "360px",
34
+ style,
35
+ hideRange,
36
+ showPrompts,
37
+ src,
38
+ streamUrl,
39
+ thumbnailSrc,
40
+ }) => {
41
+ const [isPlaying, setIsPlayering] = useState(false);
42
+ const [isSeeking, setIsSeeking] = useState(false);
43
+ const [progress, setProgress] = useState();
44
+ const [hideController, setHideController] = useState(false);
45
+ const [count, setCount] = useState(0);
46
+ const playContainerRef = useRef();
47
+ const [url, setUrl] = useState(null);
48
+ const [image, setImage] = useState(null);
49
+ const playerRef = useRef();
50
+ const { accessToken } = useContext(OutletContext);
51
+ const [isReady, setIsReady] = useState(false);
52
+ const [rangeProgress, setRangeProgress] = useState(0);
53
+
54
+ useEffect(() => {
55
+ if (src || streamUrl) {
56
+ setUrl(src ? src : `https://dev-117782726-api.learngual.com${streamUrl}`);
57
+ }
58
+ if (thumbnailSrc) {
59
+ setImage(thumbnailSrc);
60
+ }
61
+ }, [streamUrl, thumbnailSrc, src]);
62
+
63
+ const format = (secs) => {
64
+ const sec_num = parseInt(secs, 10);
65
+ const hours = Math.floor(sec_num / 3600);
66
+ const minutes = Math.floor(sec_num / 60) % 60;
67
+ const seconds = sec_num % 60;
68
+
69
+ return [hours, minutes, seconds]
70
+ .map((v) => (v < 10 ? "0" + v : v))
71
+ .join(":");
72
+ };
73
+
74
+ const handlePlayPause = () => {
75
+ setIsPlayering(!isPlaying);
76
+ setImage(null);
77
+ };
78
+
79
+ const handleFullScreen = () => {
80
+ screenfull.toggle(playContainerRef.current);
81
+ };
82
+
83
+ const handleProgress = (progress) => {
84
+ if (count > 3) {
85
+ setHideController(true);
86
+ setCount(0);
87
+ }
88
+ if (!hideController) {
89
+ setCount(count + 1);
90
+ }
91
+ if (!isSeeking) {
92
+ setRangeProgress(progress?.played);
93
+ setProgress(progress);
94
+ }
95
+ };
96
+
97
+ const handleSeekChange = (e) => {
98
+ const value = parseFloat(e.target.value) / 100;
99
+ setRangeProgress(value);
100
+ };
101
+
102
+ const handleSeekMouseUp = () => {
103
+ setIsSeeking(false);
104
+ playerRef.current?.seekTo(rangeProgress, "fraction");
105
+ };
106
+
107
+ const handleSeekMouseDown = () => {
108
+ setIsSeeking(true);
109
+ };
110
+
111
+ const handleMouseMove = () => {
112
+ setHideController(false);
113
+ setCount(0);
114
+ };
115
+
116
+ const calcShowPrompts = () => {
117
+ if (progress?.playedSeconds) {
118
+ return Math.floor(
119
+ (progress.playedSeconds * 100) / progress.loadedSeconds,
120
+ );
121
+ }
122
+ };
123
+
124
+ const currentTime = playerRef.current?.getCurrentTime()
125
+ ? format(playerRef.current?.getCurrentTime())
126
+ : "00:00:00";
127
+
128
+ const duration = playerRef.current?.getDuration()
129
+ ? format(playerRef.current?.getDuration())
130
+ : "00:00:00";
131
+
132
+ useEffect(() => {
133
+ if (progress?.loaded) {
134
+ setIsReady(true);
135
+ } else {
136
+ setIsReady(false);
137
+ }
138
+ }, [progress?.loaded]);
139
+
140
+ return (
141
+ <VideoPlayerContainer
142
+ ref={playContainerRef}
143
+ style={style}
144
+ width={width}
145
+ height={height}
146
+ onMouseMove={handleMouseMove}
147
+ >
148
+ {showPrompts && calcShowPrompts() > 80 && (
149
+ <VideoPrompts>
150
+ <div>
151
+ <p>Continue watching</p>
152
+ <p>Previuos Part (Lesson 1)</p>
153
+ </div>
154
+ <div>
155
+ <p>Continue watching</p>
156
+ <p>Next Part (Lesson 6)</p>
157
+ </div>
158
+ </VideoPrompts>
159
+ )}
160
+ {!isReady && !image && (
161
+ <LoadingScreen>
162
+ {/* <LoaderCustom zoom={0.5} /> */}
163
+ <FullPageLoader isSectionLoader loaderWidth={300} />
164
+ </LoadingScreen>
165
+ )}
166
+ <ReactPlayer
167
+ width="100%"
168
+ ref={playerRef}
169
+ height="100%"
170
+ url={url}
171
+ // muted={true}
172
+ step="any"
173
+ light={image}
174
+ playing={isPlaying}
175
+ onProgress={handleProgress}
176
+ onEnded={() => {
177
+ setIsPlayering(false);
178
+ setHideController(false);
179
+ setCount(0);
180
+ setProgress({ ...progress, played: 1 });
181
+ }}
182
+ config={
183
+ streamUrl
184
+ ? {
185
+ file: {
186
+ forceHLS: true,
187
+ hlsOptions: {
188
+ xhrSetup: function (xhr, url) {
189
+ if (accessToken) {
190
+ const modifiedURL = `${url}?_account=7d5529dcf5`;
191
+ xhr.open("GET", modifiedURL, true);
192
+ xhr.setRequestHeader(
193
+ "Authorization",
194
+ `Bearer ${accessToken}`,
195
+ );
196
+ }
197
+ },
198
+ },
199
+ },
200
+ hls: {
201
+ enableLowInitialLatency: true,
202
+ smoothQualityChange: true,
203
+ startLevel: 0,
204
+ },
205
+ }
206
+ : { file: null, hls: null }
207
+ }
208
+ />
209
+ <VideoController hide={hideController}>
210
+ {!hideRange && (!image || !isReady) && (
211
+ <RangeContainer>
212
+ <p>
213
+ {currentTime} / {duration}
214
+ </p>
215
+ <input
216
+ type="range"
217
+ min={0}
218
+ max={100}
219
+ className="range"
220
+ onChange={handleSeekChange}
221
+ onMouseDown={handleSeekMouseDown}
222
+ onMouseUp={handleSeekMouseUp}
223
+ value={rangeProgress * 100}
224
+ />
225
+ <VideoScreenIcon onClick={handleFullScreen} />
226
+ </RangeContainer>
227
+ )}
228
+ {(isReady || image) && (
229
+ <div className="play_pause_wrap" onClick={handlePlayPause}>
230
+ {isPlaying ? <PauseIcon fill="#fff" /> : <PlayIcon fill="#fff" />}
231
+ </div>
232
+ )}
233
+ </VideoController>
234
+ </VideoPlayerContainer>
235
+ );
236
+ };
237
+
238
+ export default VideoPlayer;
@@ -1,9 +1,10 @@
1
- import styled from "styled-components";
1
+ import { styled } from "styled-components";
2
2
 
3
3
  export const VideoPlayerContainer = styled.div`
4
4
  position: relative;
5
5
  border-radius: 24px;
6
6
  overflow: hidden;
7
+ /* background: #f5f7f7; */
7
8
  width: ${({ width }) => (width ? width : "auto")};
8
9
  height: ${({ height }) => (height ? height : "auto")};
9
10
  video {
@@ -146,3 +147,15 @@ export const VideoPrompts = styled.div`
146
147
  }
147
148
  }
148
149
  `;
150
+
151
+ export const LoadingScreen = styled.div`
152
+ position: absolute;
153
+ top: 0;
154
+ left: 0;
155
+ right: 0;
156
+ bottom: 0;
157
+ z-index: 40;
158
+ background-color: rgba(0, 0, 0, 0.05);
159
+ display: grid;
160
+ place-items: center;
161
+ `;
@@ -1,163 +0,0 @@
1
- import React from "react";
2
- import { useState, useRef } from "react";
3
- import screenfull from "screenfull";
4
- import {
5
- RangeContainer,
6
- VideoController,
7
- VideoPlayerContainer,
8
- VideoPrompts,
9
- } from "./index.styled";
10
- import ReactPlayer from "react-player";
11
- import VideoScreenIcon from "./icons/videoScreenIcon";
12
- import PlayIcon from "./icons/playVideoIcon";
13
- import PauseIcon from "./icons/pause";
14
-
15
- const VideoPlayer = ({
16
- width,
17
- height = "360px",
18
- style,
19
- src,
20
- hideRange,
21
- showPrompts,
22
- controlSize,
23
- }) => {
24
- const [isPlaying, setIsPlayering] = useState(false);
25
- const [isSeeking, setIsSeeking] = useState(false);
26
- const [progress, setProgress] = useState();
27
- const [hideController, setHideController] = useState(false);
28
- const [count, setCount] = useState(0);
29
- const playContainerRef = useRef();
30
- const playerRef = useRef();
31
-
32
- const format = (secs) => {
33
- const sec_num = parseInt(secs, 10);
34
- const hours = Math.floor(sec_num / 3600);
35
- const minutes = Math.floor(sec_num / 60) % 60;
36
- const seconds = sec_num % 60;
37
-
38
- return [hours, minutes, seconds]
39
- .map((v) => (v < 10 ? "0" + v : v))
40
- .join(":");
41
- };
42
-
43
- const handlePlayPause = () => {
44
- setIsPlayering(!isPlaying);
45
- };
46
-
47
- const handleFullScreen = () => {
48
- screenfull.toggle(playContainerRef.current);
49
- };
50
-
51
- const handleProgess = (changeState) => {
52
- if (count > 3) {
53
- setHideController(true);
54
- setCount(0);
55
- }
56
- if (!hideController) {
57
- setCount(count + 1);
58
- }
59
- if (isSeeking === false) {
60
- setProgress(changeState);
61
- }
62
- };
63
-
64
- const handleSeek = (e) => {
65
- setProgress({ ...progress, played: parseFloat(e.target?.value / 100) });
66
- };
67
- const handleSeekMouseDown = () => {
68
- setIsSeeking(true);
69
- };
70
- const handleSeekMouseUp = (e) => {
71
- setIsSeeking(true);
72
- playerRef.current?.seekTo(e.target?.value / 100);
73
- };
74
-
75
- const handleMouseMove = () => {
76
- setHideController(false);
77
- setCount(0);
78
- };
79
-
80
- const calcShowPrompts = () => {
81
- if (progress?.playedSeconds) {
82
- return Math.floor(
83
- (progress.playedSeconds * 100) / progress.loadedSeconds
84
- );
85
- }
86
- };
87
-
88
- const currentTime = playerRef.current
89
- ? format(playerRef.current?.getCurrentTime())
90
- : "00:00:00";
91
-
92
- const duration = playerRef.current
93
- ? format(playerRef.current?.getDuration())
94
- : "00:00:00";
95
-
96
- return (
97
- <VideoPlayerContainer
98
- ref={playContainerRef}
99
- style={style}
100
- width={width}
101
- height={height}
102
- onMouseMove={handleMouseMove}
103
- >
104
- {showPrompts && calcShowPrompts() > 80 && (
105
- <VideoPrompts>
106
- <div>
107
- <p>Continue watching</p>
108
- <p>Previuos Part (Lesson 1)</p>
109
- </div>
110
- <div>
111
- <p>Continue watching</p>
112
- <p>Next Part (Lesson 6)</p>
113
- </div>
114
- </VideoPrompts>
115
- )}
116
- <ReactPlayer
117
- width="100%"
118
- ref={playerRef}
119
- height="100%"
120
- url={
121
- src ||
122
- "https://joy1.videvo.net/videvo_files/video/free/video0474/small_watermarked/_import_61ea3dd6ab62a0.19123787_preview.mp4"
123
- }
124
- // muted={true}
125
- playing={isPlaying}
126
- onProgress={handleProgess}
127
- onEnded={() => {
128
- setIsPlayering(false);
129
- setHideController(false);
130
- setCount(0);
131
- setProgress({ ...progress, played: 1 });
132
- }}
133
- />
134
- <VideoController hide={hideController} size={controlSize}>
135
- {!hideRange && (
136
- <RangeContainer>
137
- <p>
138
- {currentTime} / {duration}
139
- </p>
140
- <input
141
- type="range"
142
- name=""
143
- id=""
144
- className="range"
145
- min={0}
146
- max={100}
147
- onChange={handleSeek}
148
- onMouseDown={handleSeekMouseDown}
149
- onMouseUp={handleSeekMouseUp}
150
- value={Math.round(progress?.played * 100)}
151
- />
152
- <VideoScreenIcon onClick={handleFullScreen} />
153
- </RangeContainer>
154
- )}
155
- <div className="play_pause_wrap" onClick={handlePlayPause}>
156
- {isPlaying ? <PauseIcon fill="#fff" /> : <PlayIcon fill="#fff" />}
157
- </div>
158
- </VideoController>
159
- </VideoPlayerContainer>
160
- );
161
- };
162
-
163
- export default VideoPlayer;