customvidplayer 0.0.5 → 0.0.7
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/README.md +0 -0
- package/package.json +31 -36
- package/src/components/Section.jsx +16 -0
- package/src/components/ThemeProvider.jsx +17 -0
- package/src/components/VideoPlayer.jsx +66 -0
- package/src/index.js +3 -4
- package/src/styles/defaultTheme.css +30 -0
- package/src/types/index.d.ts +17 -0
- package/tsconfig.json +11 -18
- package/.babelrc +0 -7
- package/dist/@types/customvidplayer.d.ts +0 -6
- package/dist/CVPlayer.js +0 -69
- package/dist/ThemeProvider.js +0 -20
- package/dist/index.js +0 -20
- package/src/@types/customvidplayer.d.ts +0 -6
- package/src/CVPlayer.jsx +0 -51
- package/src/ThemeProvider.jsx +0 -16
- package/webpack.config.js +0 -32
- /package/{src/CVPlayer.css → LICENSE} +0 -0
package/README.md
ADDED
File without changes
|
package/package.json
CHANGED
@@ -1,36 +1,31 @@
|
|
1
|
-
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
"
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
"
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
"
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
"
|
30
|
-
"
|
31
|
-
|
32
|
-
"babel-loader": "^8.4.1",
|
33
|
-
"ts-loader": "^9.5.1",
|
34
|
-
"typescript": "^4.5.4"
|
35
|
-
}
|
36
|
-
}
|
1
|
+
{
|
2
|
+
"name": "customvidplayer",
|
3
|
+
"version": "0.0.7",
|
4
|
+
"description": "Customizable video player with section navigation and theming.",
|
5
|
+
"main": "dist/index.js",
|
6
|
+
"types": "dist/index.d.ts",
|
7
|
+
"scripts": {
|
8
|
+
"build": "tsc",
|
9
|
+
"start": "webpack serve",
|
10
|
+
"test": "jest"
|
11
|
+
},
|
12
|
+
"dependencies": {
|
13
|
+
"@types/react": "^18.3.12",
|
14
|
+
"prop-types": "^15.8.1",
|
15
|
+
"react": "^18.0.0"
|
16
|
+
},
|
17
|
+
"devDependencies": {
|
18
|
+
"jest": "^29.0.0",
|
19
|
+
"typescript": "^4.9.5",
|
20
|
+
"webpack": "^5.75.0"
|
21
|
+
},
|
22
|
+
"keywords": [
|
23
|
+
"video",
|
24
|
+
"player",
|
25
|
+
"react",
|
26
|
+
"typescript",
|
27
|
+
"customizable"
|
28
|
+
],
|
29
|
+
"license": "MIT",
|
30
|
+
"author": "Prewcioo"
|
31
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import React from "react";
|
2
|
+
import PropTypes from "prop-types";
|
3
|
+
|
4
|
+
const Section = ({ name, timestamp, onClick }) => (
|
5
|
+
<div className="section" onClick={() => onClick(timestamp)}>
|
6
|
+
{name}
|
7
|
+
</div>
|
8
|
+
);
|
9
|
+
|
10
|
+
Section.propTypes = {
|
11
|
+
name: PropTypes.string.isRequired,
|
12
|
+
timestamp: PropTypes.number.isRequired,
|
13
|
+
onClick: PropTypes.func.isRequired,
|
14
|
+
};
|
15
|
+
|
16
|
+
export default Section;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import React from "react";
|
2
|
+
import PropTypes from "prop-types";
|
3
|
+
|
4
|
+
const ThemeProvider = ({ theme, children }) => (
|
5
|
+
<div style={{ ...theme }}>{children}</div>
|
6
|
+
);
|
7
|
+
|
8
|
+
ThemeProvider.propTypes = {
|
9
|
+
theme: PropTypes.object,
|
10
|
+
children: PropTypes.node.isRequired,
|
11
|
+
};
|
12
|
+
|
13
|
+
ThemeProvider.defaultProps = {
|
14
|
+
theme: {},
|
15
|
+
};
|
16
|
+
|
17
|
+
export default ThemeProvider;
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import React, { useState, useRef } from "react";
|
2
|
+
import PropTypes from "prop-types";
|
3
|
+
import "./../styles/defaultTheme.css";
|
4
|
+
|
5
|
+
const VideoPlayer = ({ videoSrc, sections, onSectionChange, theme }) => {
|
6
|
+
const videoRef = useRef(null);
|
7
|
+
const [currentSectionIndex, setCurrentSectionIndex] = useState(0);
|
8
|
+
|
9
|
+
const skipToNextSection = () => {
|
10
|
+
if (currentSectionIndex < sections.length - 1) {
|
11
|
+
const nextSection = sections[currentSectionIndex + 1];
|
12
|
+
videoRef.current.currentTime = nextSection.timestamp;
|
13
|
+
setCurrentSectionIndex(currentSectionIndex + 1);
|
14
|
+
if (onSectionChange) onSectionChange(nextSection);
|
15
|
+
}
|
16
|
+
};
|
17
|
+
|
18
|
+
const handleTimeUpdate = () => {
|
19
|
+
const currentTime = videoRef.current.currentTime;
|
20
|
+
const currentSection = sections.find(
|
21
|
+
(section, index) =>
|
22
|
+
currentTime >= section.timestamp &&
|
23
|
+
(index === sections.length - 1 || currentTime < sections[index + 1].timestamp)
|
24
|
+
);
|
25
|
+
|
26
|
+
if (currentSection && sections[currentSectionIndex] !== currentSection) {
|
27
|
+
const newIndex = sections.indexOf(currentSection);
|
28
|
+
setCurrentSectionIndex(newIndex);
|
29
|
+
if (onSectionChange) onSectionChange(currentSection);
|
30
|
+
}
|
31
|
+
};
|
32
|
+
|
33
|
+
return (
|
34
|
+
<div className="video-player" style={{ ...theme }}>
|
35
|
+
<video
|
36
|
+
src={videoSrc}
|
37
|
+
controls
|
38
|
+
ref={videoRef}
|
39
|
+
onTimeUpdate={handleTimeUpdate}
|
40
|
+
className="video-element"
|
41
|
+
/>
|
42
|
+
<button onClick={skipToNextSection} className="skip-button">
|
43
|
+
Skip
|
44
|
+
</button>
|
45
|
+
</div>
|
46
|
+
);
|
47
|
+
};
|
48
|
+
|
49
|
+
VideoPlayer.propTypes = {
|
50
|
+
videoSrc: PropTypes.string.isRequired,
|
51
|
+
sections: PropTypes.arrayOf(
|
52
|
+
PropTypes.shape({
|
53
|
+
name: PropTypes.string.isRequired,
|
54
|
+
timestamp: PropTypes.number.isRequired,
|
55
|
+
})
|
56
|
+
).isRequired,
|
57
|
+
onSectionChange: PropTypes.func,
|
58
|
+
theme: PropTypes.object,
|
59
|
+
};
|
60
|
+
|
61
|
+
VideoPlayer.defaultProps = {
|
62
|
+
theme: {},
|
63
|
+
onSectionChange: null,
|
64
|
+
};
|
65
|
+
|
66
|
+
export default VideoPlayer;
|
package/src/index.js
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
export { CVPlayer, ThemeProvider };
|
1
|
+
export { default as VideoPlayer } from "./components/VideoPlayer";
|
2
|
+
export { default as Section } from "./components/Section";
|
3
|
+
export { default as ThemeProvider } from "./components/ThemeProvider";
|
@@ -0,0 +1,30 @@
|
|
1
|
+
.video-player {
|
2
|
+
position: relative;
|
3
|
+
width: 100%;
|
4
|
+
max-width: 800px;
|
5
|
+
margin: 0 auto;
|
6
|
+
}
|
7
|
+
|
8
|
+
.video-element {
|
9
|
+
width: 100%;
|
10
|
+
border-radius: 5px;
|
11
|
+
}
|
12
|
+
|
13
|
+
.skip-button {
|
14
|
+
position: absolute;
|
15
|
+
bottom: 10px;
|
16
|
+
right: 10px;
|
17
|
+
padding: 8px 12px;
|
18
|
+
background: #ff5722;
|
19
|
+
color: white;
|
20
|
+
border: none;
|
21
|
+
border-radius: 5px;
|
22
|
+
cursor: pointer;
|
23
|
+
}
|
24
|
+
|
25
|
+
.section {
|
26
|
+
cursor: pointer;
|
27
|
+
margin: 5px 0;
|
28
|
+
color: #007bff;
|
29
|
+
}
|
30
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { ReactNode } from "react";
|
2
|
+
|
3
|
+
export interface Section {
|
4
|
+
name: string;
|
5
|
+
timestamp: number;
|
6
|
+
}
|
7
|
+
|
8
|
+
export interface VideoPlayerProps {
|
9
|
+
videoSrc: string;
|
10
|
+
sections: Section[];
|
11
|
+
onSectionChange?: (section: Section) => void;
|
12
|
+
theme?: Record<string, string | number>;
|
13
|
+
}
|
14
|
+
|
15
|
+
declare const VideoPlayer: (props: VideoPlayerProps) => ReactNode;
|
16
|
+
|
17
|
+
export default VideoPlayer;
|
package/tsconfig.json
CHANGED
@@ -1,21 +1,14 @@
|
|
1
1
|
{
|
2
2
|
"compilerOptions": {
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
"declaration": true
|
3
|
+
"target": "es5",
|
4
|
+
"module": "commonjs",
|
5
|
+
"jsx": "react-jsx",
|
6
|
+
"strict": true,
|
7
|
+
"esModuleInterop": true,
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
9
|
+
"declaration": true,
|
10
|
+
"outDir": "./dist"
|
12
11
|
},
|
13
|
-
"include": [
|
14
|
-
|
15
|
-
|
16
|
-
],
|
17
|
-
"exclude": [
|
18
|
-
"node_modules",
|
19
|
-
"**/*.spec.ts"
|
20
|
-
]
|
21
|
-
}
|
12
|
+
"include": ["src/**/*"]
|
13
|
+
}
|
14
|
+
|
package/.babelrc
DELETED
package/dist/CVPlayer.js
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
|
3
|
-
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
4
|
-
Object.defineProperty(exports, "__esModule", {
|
5
|
-
value: true
|
6
|
-
});
|
7
|
-
exports["default"] = void 0;
|
8
|
-
var _react = _interopRequireWildcard(require("react"));
|
9
|
-
var _fa = require("react-icons/fa");
|
10
|
-
require("./CVPlayer.css");
|
11
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
12
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
|
13
|
-
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
14
|
-
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
15
|
-
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
16
|
-
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
17
|
-
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
18
|
-
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
19
|
-
// Add your CSS for styling
|
20
|
-
|
21
|
-
/**
|
22
|
-
* Custom Video Player Component
|
23
|
-
* @param {Object} props - Component properties
|
24
|
-
* @param {string} props.videoSrc - Source URL of the video
|
25
|
-
* @param {Array} props.sections - Array of section objects with timestamps
|
26
|
-
*/
|
27
|
-
var CVPlayer = function CVPlayer(_ref) {
|
28
|
-
var videoSrc = _ref.videoSrc,
|
29
|
-
sections = _ref.sections;
|
30
|
-
var _useState = (0, _react.useState)(false),
|
31
|
-
_useState2 = _slicedToArray(_useState, 2),
|
32
|
-
isPlaying = _useState2[0],
|
33
|
-
setIsPlaying = _useState2[1];
|
34
|
-
var videoRef = (0, _react.useRef)(null);
|
35
|
-
var togglePlayPause = function togglePlayPause() {
|
36
|
-
if (isPlaying) {
|
37
|
-
videoRef.current.pause();
|
38
|
-
} else {
|
39
|
-
videoRef.current.play();
|
40
|
-
}
|
41
|
-
setIsPlaying(!isPlaying);
|
42
|
-
};
|
43
|
-
var skipToSection = function skipToSection(timestamp) {
|
44
|
-
videoRef.current.currentTime = timestamp;
|
45
|
-
videoRef.current.play(); // Optionally play after skipping
|
46
|
-
};
|
47
|
-
return /*#__PURE__*/_react["default"].createElement("div", {
|
48
|
-
className: "cv-player"
|
49
|
-
}, /*#__PURE__*/_react["default"].createElement("video", {
|
50
|
-
ref: videoRef,
|
51
|
-
src: videoSrc,
|
52
|
-
onTimeUpdate: function onTimeUpdate() {
|
53
|
-
return setCurrentTime(videoRef.current.currentTime);
|
54
|
-
},
|
55
|
-
controls: true // Optional: adds default video controls
|
56
|
-
}), /*#__PURE__*/_react["default"].createElement("div", {
|
57
|
-
className: "controls"
|
58
|
-
}, /*#__PURE__*/_react["default"].createElement("button", {
|
59
|
-
onClick: togglePlayPause
|
60
|
-
}, isPlaying ? /*#__PURE__*/_react["default"].createElement(_fa.FaPause, null) : /*#__PURE__*/_react["default"].createElement(_fa.FaPlay, null)), sections.map(function (section, index) {
|
61
|
-
return /*#__PURE__*/_react["default"].createElement("button", {
|
62
|
-
key: index,
|
63
|
-
onClick: function onClick() {
|
64
|
-
return skipToSection(section.timestamp);
|
65
|
-
}
|
66
|
-
}, "Skip to ", section.name);
|
67
|
-
})));
|
68
|
-
};
|
69
|
-
var _default = exports["default"] = CVPlayer;
|
package/dist/ThemeProvider.js
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
4
|
-
value: true
|
5
|
-
});
|
6
|
-
exports["default"] = void 0;
|
7
|
-
var _react = _interopRequireDefault(require("react"));
|
8
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
9
|
-
/**
|
10
|
-
* Theme Provider for Custom Video Player
|
11
|
-
* @param {Object} props - Component properties
|
12
|
-
* @returns {JSX.Element}
|
13
|
-
*/
|
14
|
-
var ThemeProvider = function ThemeProvider(_ref) {
|
15
|
-
var children = _ref.children;
|
16
|
-
return /*#__PURE__*/_react["default"].createElement("div", {
|
17
|
-
className: "theme-provider"
|
18
|
-
}, children);
|
19
|
-
};
|
20
|
-
var _default = exports["default"] = ThemeProvider;
|
package/dist/index.js
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
4
|
-
value: true
|
5
|
-
});
|
6
|
-
Object.defineProperty(exports, "CVPlayer", {
|
7
|
-
enumerable: true,
|
8
|
-
get: function get() {
|
9
|
-
return _CVPlayer["default"];
|
10
|
-
}
|
11
|
-
});
|
12
|
-
Object.defineProperty(exports, "ThemeProvider", {
|
13
|
-
enumerable: true,
|
14
|
-
get: function get() {
|
15
|
-
return _ThemeProvider["default"];
|
16
|
-
}
|
17
|
-
});
|
18
|
-
var _CVPlayer = _interopRequireDefault(require("./CVPlayer"));
|
19
|
-
var _ThemeProvider = _interopRequireDefault(require("./ThemeProvider"));
|
20
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
package/src/CVPlayer.jsx
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
import React, { useState, useRef } from 'react';
|
2
|
-
import { FaPlay, FaPause } from 'react-icons/fa';
|
3
|
-
import './CVPlayer.css'; // Add your CSS for styling
|
4
|
-
|
5
|
-
/**
|
6
|
-
* Custom Video Player Component
|
7
|
-
* @param {Object} props - Component properties
|
8
|
-
* @param {string} props.videoSrc - Source URL of the video
|
9
|
-
* @param {Array} props.sections - Array of section objects with timestamps
|
10
|
-
*/
|
11
|
-
const CVPlayer = ({ videoSrc, sections }) => {
|
12
|
-
const [isPlaying, setIsPlaying] = useState(false);
|
13
|
-
const videoRef = useRef(null);
|
14
|
-
|
15
|
-
const togglePlayPause = () => {
|
16
|
-
if (isPlaying) {
|
17
|
-
videoRef.current.pause();
|
18
|
-
} else {
|
19
|
-
videoRef.current.play();
|
20
|
-
}
|
21
|
-
setIsPlaying(!isPlaying);
|
22
|
-
};
|
23
|
-
|
24
|
-
const skipToSection = (timestamp) => {
|
25
|
-
videoRef.current.currentTime = timestamp;
|
26
|
-
videoRef.current.play(); // Optionally play after skipping
|
27
|
-
};
|
28
|
-
|
29
|
-
return (
|
30
|
-
<div className="cv-player">
|
31
|
-
<video
|
32
|
-
ref={videoRef}
|
33
|
-
src={videoSrc}
|
34
|
-
onTimeUpdate={() => setCurrentTime(videoRef.current.currentTime)}
|
35
|
-
controls // Optional: adds default video controls
|
36
|
-
/>
|
37
|
-
<div className="controls">
|
38
|
-
<button onClick={togglePlayPause}>
|
39
|
-
{isPlaying ? <FaPause /> : <FaPlay />}
|
40
|
-
</button>
|
41
|
-
{sections.map((section, index) => (
|
42
|
-
<button key={index} onClick={() => skipToSection(section.timestamp)}>
|
43
|
-
Skip to {section.name}
|
44
|
-
</button>
|
45
|
-
))}
|
46
|
-
</div>
|
47
|
-
</div>
|
48
|
-
);
|
49
|
-
};
|
50
|
-
|
51
|
-
export default CVPlayer;
|
package/src/ThemeProvider.jsx
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
|
3
|
-
/**
|
4
|
-
* Theme Provider for Custom Video Player
|
5
|
-
* @param {Object} props - Component properties
|
6
|
-
* @returns {JSX.Element}
|
7
|
-
*/
|
8
|
-
const ThemeProvider = ({ children }) => {
|
9
|
-
return (
|
10
|
-
<div className="theme-provider">
|
11
|
-
{children}
|
12
|
-
</div>
|
13
|
-
);
|
14
|
-
};
|
15
|
-
|
16
|
-
export default ThemeProvider;
|
package/webpack.config.js
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
// webpack.config.js
|
2
|
-
const path = require('path');
|
3
|
-
|
4
|
-
module.exports = {
|
5
|
-
entry: './src/index.js', // Your main JavaScript file
|
6
|
-
output: {
|
7
|
-
path: path.resolve(__dirname, 'dist'),
|
8
|
-
filename: 'bundle.js',
|
9
|
-
},
|
10
|
-
module: {
|
11
|
-
rules: [
|
12
|
-
{
|
13
|
-
test: /\.(js|jsx)$/,
|
14
|
-
exclude: /node_modules/,
|
15
|
-
use: {
|
16
|
-
loader: 'babel-loader',
|
17
|
-
options: {
|
18
|
-
presets: ['@babel/preset-env', '@babel/preset-react']
|
19
|
-
}
|
20
|
-
}
|
21
|
-
},
|
22
|
-
{
|
23
|
-
test: /\.tsx?$/,
|
24
|
-
exclude: /node_modules/,
|
25
|
-
use: 'ts-loader'
|
26
|
-
}
|
27
|
-
],
|
28
|
-
},
|
29
|
-
resolve: {
|
30
|
-
extensions: ['.js', '.jsx', '.ts', '.tsx']
|
31
|
-
}
|
32
|
-
};
|
File without changes
|