@vidispine/vdt-videojs 21.3.0 → 22.1.0-pre.1
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 +4 -4
- package/deprecated-app/README.md +21 -0
- package/{demo.html → deprecated-app/index.html} +1 -1
- package/{demo.js → deprecated-app/index.js} +69 -41
- package/{samples → deprecated-app/samples}/birds-es.vvt +0 -0
- package/{samples → deprecated-app/samples}/birds.vvt +0 -0
- package/{tests.js → deprecated-app/tests.js} +87 -54
- package/{lib/style.css → dist/index.css} +755 -55
- package/dist/index.es.js +2099 -0
- package/dist/index.js +2112 -0
- package/dist/index.umd.js +2115 -0
- package/package.json +29 -85
- package/rollup.config.js +54 -0
- package/src/constants.js +1 -1
- package/src/externalControls.js +14 -18
- package/src/helpOverlay.js +12 -16
- package/src/helpers.js +3 -3
- package/src/index.js +3 -9
- package/src/index.stories.mdx +59 -0
- package/src/menu.api.stories.mdx +59 -0
- package/src/menu.js +23 -19
- package/src/{menu.example.md → menu.usage.stories.mdx} +31 -21
- package/src/osd.js +24 -18
- package/src/player.api.stories.mdx +120 -0
- package/src/player.js +157 -108
- package/src/player.scss +2 -0
- package/src/{player.example.md → player.usage.stories.mdx} +18 -8
- package/src/seekBar.js +85 -48
- package/src/timeCodeDisplay.js +39 -31
- package/src/videoTime.js +4 -4
- package/build.js +0 -233
- package/lib/index.cjs.js +0 -3240
- package/lib/index.esm.js +0 -3227
- package/lib/index.umd.js +0 -3243
- package/lib/package.json +0 -13
- package/lib/src/constants.js +0 -51
- package/lib/src/externalControls.js +0 -307
- package/lib/src/helpOverlay.js +0 -106
- package/lib/src/helpers.js +0 -34
- package/lib/src/index.js +0 -13
- package/lib/src/menu.js +0 -365
- package/lib/src/osd.js +0 -91
- package/lib/src/player.js +0 -943
- package/lib/src/seekBar.js +0 -833
- package/lib/src/timeCodeDisplay.js +0 -253
- package/lib/src/videoTime.js +0 -66
- package/log.js +0 -24
- package/src/_index.stories.js +0 -24
- package/src/externalControls.stories.js +0 -6
- package/src/helpOverlay.stories.js +0 -6
- package/src/menu.classMethods.md +0 -47
- package/src/player.classMethods.md +0 -108
- package/src/player.stories.js +0 -14
- package/src/seekBar.stories.js +0 -8
- package/tmp/player.css +0 -1
package/package.json
CHANGED
|
@@ -1,101 +1,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vidispine/vdt-videojs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "22.1.0-pre.1",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"private": false,
|
|
6
|
-
"main": "
|
|
7
|
-
"module": "
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.es.js",
|
|
8
|
+
"browser": "dist/index.umd.js",
|
|
8
9
|
"author": "Oto Inša <otoinsa@bertelsmann.de>",
|
|
9
10
|
"scripts": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"build:watch": "node ./build.js --watch",
|
|
15
|
-
"build:demo": "rm -rf ./demo/ && parcel build ./demo.html --out-file index.html --out-dir ./demo --no-source-maps --public-url ./",
|
|
16
|
-
"docs": "jsdoc ./src/player.js -d ./docs/"
|
|
17
|
-
},
|
|
18
|
-
"devDependencies": {
|
|
19
|
-
"@babel/core": "^7.7.7",
|
|
20
|
-
"babel-plugin-transform-runtime": "^6.23.0",
|
|
21
|
-
"chokidar": "^3.3.1",
|
|
22
|
-
"colors": "^1.4.0",
|
|
23
|
-
"parcel-bundler": "^1.12.4",
|
|
24
|
-
"rollup": "^2.20.0",
|
|
25
|
-
"rollup-plugin-json": "^4.0.0",
|
|
26
|
-
"sass": "^1.24.3",
|
|
27
|
-
"strip-comments": "^2.0.1"
|
|
11
|
+
"build": "rm -rf dist/ && rollup -c",
|
|
12
|
+
"build:watch": "rm -rf dist/*.js* && rollup -c -w --environment DEVELOPMENT",
|
|
13
|
+
"lint": "eslint \"./{src/**/*,*}.{js,md}\"",
|
|
14
|
+
"lint:fix": "yarn lint --fix"
|
|
28
15
|
},
|
|
29
16
|
"dependencies": {
|
|
30
17
|
"mousetrap": "^1.6.3",
|
|
31
18
|
"video.js": "^7.6.6"
|
|
32
19
|
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@babel/core": "^7.17.0",
|
|
22
|
+
"@rollup/plugin-babel": "^5.3.0",
|
|
23
|
+
"@rollup/plugin-commonjs": "^21.0.1",
|
|
24
|
+
"@rollup/plugin-json": "^4.1.0",
|
|
25
|
+
"@rollup/plugin-node-resolve": "^13.1.3",
|
|
26
|
+
"@vidispine/eslint-config-base": "^22.1.0-pre.1",
|
|
27
|
+
"@vidispine/eslint-config-storybook": "*",
|
|
28
|
+
"babel-plugin-transform-runtime": "^6.23.0",
|
|
29
|
+
"rollup": "^2.67.0",
|
|
30
|
+
"rollup-plugin-cleanup": "^3.2.1",
|
|
31
|
+
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
32
|
+
"rollup-plugin-sass": "^1.2.10"
|
|
33
|
+
},
|
|
33
34
|
"browserslist": [
|
|
34
35
|
"since 2017-06"
|
|
35
36
|
],
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"Borrowed styling ideas from a popular online video platform",
|
|
41
|
-
"Visual feedback gizmo as hotkey feedback",
|
|
42
|
-
"Subtitle support (VVT)",
|
|
43
|
-
"Persistance - volume level",
|
|
44
|
-
"Custom timecode display (SMPTE)",
|
|
45
|
-
"Frame forward / frame backward 6unctionality"
|
|
46
|
-
],
|
|
47
|
-
"0.1.3": [
|
|
48
|
-
"Renamed 'subtitles off' to just 'off'",
|
|
49
|
-
"Timecode SMPTE - current time in SMPTE with input capabilities",
|
|
50
|
-
"Timecode SMPTE - total video duration timecode (read-only)",
|
|
51
|
-
"Settings persistance - storing wether subtitles should be on and the selected language as well"
|
|
52
|
-
],
|
|
53
|
-
"0.1.4": [
|
|
54
|
-
"Subtitles toggle hotkey - c",
|
|
55
|
-
"Now accepts Blob as subtitles source file",
|
|
56
|
-
"Timecode input improvements",
|
|
57
|
-
"Screenshot button with currentTime callback",
|
|
58
|
-
"Moved OSD in its own class"
|
|
59
|
-
],
|
|
60
|
-
"0.1.6": [
|
|
61
|
-
"Help overlay for keyboard controls",
|
|
62
|
-
"External player controls component (js, React)",
|
|
63
|
-
"External seek-bar component (js, React)"
|
|
64
|
-
],
|
|
65
|
-
"0.1.7": [
|
|
66
|
-
"In / Out markers for seek bar"
|
|
67
|
-
],
|
|
68
|
-
"0.1.8": [
|
|
69
|
-
"External TimeCodeDisplay support for player"
|
|
70
|
-
],
|
|
71
|
-
"0.1.9": [
|
|
72
|
-
"Multiple regions with annotations for SeekBar"
|
|
73
|
-
],
|
|
74
|
-
"0.2.2": [
|
|
75
|
-
"Overall version bump (improvements)"
|
|
76
|
-
],
|
|
77
|
-
"0.3.0": [
|
|
78
|
-
"controlsBelowPlayer - reactive option",
|
|
79
|
-
"onDark - used in conjuction with controlsBelowPlayer for dark backgrounds",
|
|
80
|
-
"Bug fixes, convenience class methods"
|
|
81
|
-
],
|
|
82
|
-
"0.3.1": [
|
|
83
|
-
"SeekBar - Seek animation, dark mode improvements",
|
|
84
|
-
"Bug fixes, refactor & code sharing improvements"
|
|
85
|
-
],
|
|
86
|
-
"0.5.3": [
|
|
87
|
-
"vdt-videojs now provides a commonjs module with named exports"
|
|
88
|
-
],
|
|
89
|
-
"0.6.1": [
|
|
90
|
-
"Internal refactor before splitting main features into videojs plugins",
|
|
91
|
-
"More bugfixes"
|
|
37
|
+
"eslintConfig": {
|
|
38
|
+
"extends": [
|
|
39
|
+
"@vidispine/eslint-config-base",
|
|
40
|
+
"@vidispine/eslint-config-storybook"
|
|
92
41
|
]
|
|
93
42
|
},
|
|
94
|
-
"
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
"backlog": [
|
|
98
|
-
"External player controls component",
|
|
99
|
-
"Check for hijacked hotkeys and player focus"
|
|
100
|
-
]
|
|
101
|
-
}
|
|
43
|
+
"prettier": "@vidispine/prettier-config",
|
|
44
|
+
"gitHead": "9e1d15560719544a68e6bc881e1a40901fe9f786"
|
|
45
|
+
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { babel } from '@rollup/plugin-babel';
|
|
2
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
3
|
+
import json from '@rollup/plugin-json';
|
|
4
|
+
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
5
|
+
import cleanup from 'rollup-plugin-cleanup';
|
|
6
|
+
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
|
|
7
|
+
import sass from 'rollup-plugin-sass';
|
|
8
|
+
|
|
9
|
+
import pkg from './package.json';
|
|
10
|
+
|
|
11
|
+
const isDevelopment = !!process.env.DEVELOPMENT;
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
external: Object.keys(pkg.dependencies || {}).map(
|
|
15
|
+
(packageName) => new RegExp(`^${packageName}(/.*)?`),
|
|
16
|
+
),
|
|
17
|
+
input: 'src/index.js',
|
|
18
|
+
output: [
|
|
19
|
+
{
|
|
20
|
+
file: pkg.main,
|
|
21
|
+
format: 'cjs',
|
|
22
|
+
sourcemap: isDevelopment,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
file: pkg.module,
|
|
26
|
+
format: 'esm',
|
|
27
|
+
sourcemap: isDevelopment,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
file: pkg.browser,
|
|
31
|
+
format: 'umd',
|
|
32
|
+
sourcemap: isDevelopment,
|
|
33
|
+
name: 'vdtVideojs',
|
|
34
|
+
globals: { mousetrap: 'mousetrap', 'video.js/dist/alt/video.core.min': 'videojs' },
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
plugins: [
|
|
38
|
+
json(),
|
|
39
|
+
sass({
|
|
40
|
+
output: 'dist/index.css',
|
|
41
|
+
}),
|
|
42
|
+
peerDepsExternal(),
|
|
43
|
+
nodeResolve(),
|
|
44
|
+
commonjs(),
|
|
45
|
+
babel({
|
|
46
|
+
babelHelpers: 'runtime',
|
|
47
|
+
exclude: /^(.+\/)?node_modules\/.+$/,
|
|
48
|
+
presets: ['@babel/preset-env'],
|
|
49
|
+
plugins: ['@babel/plugin-transform-runtime'],
|
|
50
|
+
compact: isDevelopment ? false : 'auto',
|
|
51
|
+
}),
|
|
52
|
+
...(isDevelopment ? [] : [cleanup()]),
|
|
53
|
+
],
|
|
54
|
+
};
|
package/src/constants.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import pkgInfo from '../package.json';
|
|
2
2
|
|
|
3
3
|
export const defaults = Object.freeze({
|
|
4
|
-
frameRate:
|
|
4
|
+
frameRate: 30000 / 1001,
|
|
5
5
|
jumpSeconds: 10,
|
|
6
6
|
inactivityTimeout: 1200, // hide player controls if user inactive for this duration
|
|
7
7
|
audioInactivityTimeout: 0,
|
package/src/externalControls.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
/* eslint-disable no-plusplus */
|
|
2
|
-
/* eslint-disable no-unused-expressions */
|
|
3
|
-
import { reactiveSetters } from './helpers';
|
|
4
1
|
import { classNames, colors } from './constants';
|
|
2
|
+
import { reactiveSetters } from './helpers';
|
|
5
3
|
|
|
6
4
|
const buttonNames = Object.freeze({
|
|
7
5
|
play: 'play-pause',
|
|
@@ -11,7 +9,8 @@ const buttonNames = Object.freeze({
|
|
|
11
9
|
end: 'end',
|
|
12
10
|
});
|
|
13
11
|
|
|
14
|
-
const buttons = [
|
|
12
|
+
const buttons = [
|
|
13
|
+
// order matters
|
|
15
14
|
buttonNames.start,
|
|
16
15
|
buttonNames.fb,
|
|
17
16
|
buttonNames.play,
|
|
@@ -217,10 +216,10 @@ class ExternalControls {
|
|
|
217
216
|
}
|
|
218
217
|
|
|
219
218
|
handlePress(buttonName) {
|
|
220
|
-
if (this.props.player) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
player.osd
|
|
219
|
+
if (this.props.player) {
|
|
220
|
+
// control a vdt player instance directly
|
|
221
|
+
const { player } = this.props;
|
|
222
|
+
if (player.osd) player.osd.disable(); // temporarily disable OSD
|
|
224
223
|
|
|
225
224
|
switch (buttonName) {
|
|
226
225
|
case buttonNames.start:
|
|
@@ -243,27 +242,25 @@ class ExternalControls {
|
|
|
243
242
|
break;
|
|
244
243
|
}
|
|
245
244
|
|
|
246
|
-
player.osd
|
|
245
|
+
if (player.osd) player.osd.enable(); // re-enable OSD
|
|
247
246
|
} else {
|
|
248
247
|
switch (buttonName) {
|
|
249
248
|
case buttonNames.start:
|
|
250
|
-
this.props.onPrev
|
|
249
|
+
if (this.props.onPrev) this.props.onPrev();
|
|
251
250
|
break;
|
|
252
251
|
case buttonNames.fb:
|
|
253
|
-
this.props.onFB
|
|
252
|
+
if (this.props.onFB) this.props.onFB();
|
|
254
253
|
break;
|
|
255
254
|
case buttonNames.play:
|
|
256
255
|
if (this.playing) {
|
|
257
|
-
this.props.onPause
|
|
258
|
-
} else
|
|
259
|
-
this.props.onPlay && this.props.onPlay();
|
|
260
|
-
}
|
|
256
|
+
if (this.props.onPause) this.props.onPause();
|
|
257
|
+
} else if (this.props.onPlay) this.props.onPlay();
|
|
261
258
|
break;
|
|
262
259
|
case buttonNames.ff:
|
|
263
|
-
this.props.onFF
|
|
260
|
+
if (this.props.onFF) this.props.onFF();
|
|
264
261
|
break;
|
|
265
262
|
case buttonNames.end:
|
|
266
|
-
this.props.onNext
|
|
263
|
+
if (this.props.onNext) this.props.onNext();
|
|
267
264
|
break;
|
|
268
265
|
default:
|
|
269
266
|
// do nothing
|
|
@@ -318,5 +315,4 @@ class ExternalControls {
|
|
|
318
315
|
|
|
319
316
|
ExternalControls.buttonNames = buttonNames;
|
|
320
317
|
|
|
321
|
-
|
|
322
318
|
export default ExternalControls;
|
package/src/helpOverlay.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/* eslint-disable no-plusplus */
|
|
2
|
-
/* eslint-disable no-unused-expressions */
|
|
3
|
-
|
|
4
1
|
import mousetrap from 'mousetrap';
|
|
5
2
|
|
|
6
3
|
export default class HelpOverlay {
|
|
@@ -18,12 +15,13 @@ export default class HelpOverlay {
|
|
|
18
15
|
this.hide();
|
|
19
16
|
};
|
|
20
17
|
|
|
21
|
-
this.props.target
|
|
18
|
+
if (this.props.target) this.props.target.appendChild(this.container);
|
|
22
19
|
|
|
23
20
|
this.draw();
|
|
24
21
|
}
|
|
25
22
|
|
|
26
|
-
draw() {
|
|
23
|
+
draw() {
|
|
24
|
+
// draws keyboard controls
|
|
27
25
|
let tableRowMarkup = ''; // will insert a DOM string here
|
|
28
26
|
const rows = [
|
|
29
27
|
['⎵', 'Play / Pause'],
|
|
@@ -41,23 +39,19 @@ export default class HelpOverlay {
|
|
|
41
39
|
['H', 'Toggle this help overlay'],
|
|
42
40
|
];
|
|
43
41
|
|
|
44
|
-
|
|
45
42
|
// split the data for 2 columns
|
|
46
43
|
const halfpointIndex = Math.round(rows.length / 2);
|
|
47
|
-
const columns = [
|
|
48
|
-
rows.slice(0, halfpointIndex),
|
|
49
|
-
rows.slice(halfpointIndex, rows.length),
|
|
50
|
-
];
|
|
44
|
+
const columns = [rows.slice(0, halfpointIndex), rows.slice(halfpointIndex, rows.length)];
|
|
51
45
|
|
|
52
46
|
// table will niceley auto adjust td's according to length
|
|
53
|
-
for (let i = 0; i < halfpointIndex; i
|
|
47
|
+
for (let i = 0; i < halfpointIndex; i += 1) {
|
|
54
48
|
tableRowMarkup += `
|
|
55
49
|
<tr>
|
|
56
50
|
<td><div>${columns[0][i][0]}</div></td>
|
|
57
51
|
<td>- ${columns[0][i][1]}</td>
|
|
58
52
|
|
|
59
|
-
<td>${
|
|
60
|
-
<td>${
|
|
53
|
+
<td>${columns[1][i] ? `<div>${columns[1][i][0]}</div>` : ''}</td>
|
|
54
|
+
<td>${columns[1][i] ? `- ${columns[1][i][1]}` : ''}</td>
|
|
61
55
|
</tr>
|
|
62
56
|
`;
|
|
63
57
|
}
|
|
@@ -87,9 +81,11 @@ export default class HelpOverlay {
|
|
|
87
81
|
this.container.classList.add('active');
|
|
88
82
|
this.state.active = true;
|
|
89
83
|
|
|
90
|
-
mousetrap.bind('esc', () => {
|
|
84
|
+
mousetrap.bind('esc', () => {
|
|
85
|
+
this.hide();
|
|
86
|
+
});
|
|
91
87
|
|
|
92
|
-
this.props.onToggle
|
|
88
|
+
if (this.props.onToggle) this.props.onToggle(true);
|
|
93
89
|
}
|
|
94
90
|
}
|
|
95
91
|
|
|
@@ -100,7 +96,7 @@ export default class HelpOverlay {
|
|
|
100
96
|
|
|
101
97
|
mousetrap.unbind('esc');
|
|
102
98
|
|
|
103
|
-
this.props.onToggle
|
|
99
|
+
if (this.props.onToggle) this.props.onToggle(false);
|
|
104
100
|
}
|
|
105
101
|
}
|
|
106
102
|
|
package/src/helpers.js
CHANGED
|
@@ -3,7 +3,6 @@ export function truncate(input, len) {
|
|
|
3
3
|
return input;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
/*
|
|
8
7
|
Make certain component props React-ive
|
|
9
8
|
by being able to call respective component .handleNewProps()
|
|
@@ -20,7 +19,8 @@ export function reactiveSetters() {
|
|
|
20
19
|
// check for own setters / getters
|
|
21
20
|
const descriptor = Object.getOwnPropertyDescriptor(proto, key);
|
|
22
21
|
|
|
23
|
-
if (descriptor && descriptor.set) {
|
|
22
|
+
if (descriptor && descriptor.set) {
|
|
23
|
+
// if a setter is defined, apply the prop
|
|
24
24
|
this[key] = props[key];
|
|
25
25
|
}
|
|
26
26
|
});
|
|
@@ -32,7 +32,7 @@ export function reactiveSetters() {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// an elegant way to prevent xss attacks
|
|
35
|
-
export function sanitize(str) {
|
|
35
|
+
export function sanitize(str) {
|
|
36
36
|
const temp = document.createElement('div');
|
|
37
37
|
temp.textContent = str;
|
|
38
38
|
return temp.innerHTML;
|
package/src/index.js
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
import Player from './player';
|
|
2
|
-
import TimeCodeDisplay from './timeCodeDisplay';
|
|
3
1
|
import ExternalControls from './externalControls';
|
|
2
|
+
import Player from './player';
|
|
4
3
|
import SeekBar from './seekBar';
|
|
4
|
+
import TimeCodeDisplay from './timeCodeDisplay';
|
|
5
5
|
import VideoTime from './videoTime';
|
|
6
6
|
|
|
7
|
-
export {
|
|
8
|
-
TimeCodeDisplay,
|
|
9
|
-
ExternalControls,
|
|
10
|
-
SeekBar,
|
|
11
|
-
Player,
|
|
12
|
-
VideoTime,
|
|
13
|
-
};
|
|
7
|
+
export { TimeCodeDisplay, ExternalControls, SeekBar, Player, VideoTime };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Meta, Description } from '@storybook/addon-docs';
|
|
2
|
+
|
|
3
|
+
import pkgJson from '../package.json';
|
|
4
|
+
import playerReadme from '../README.md';
|
|
5
|
+
|
|
6
|
+
<Meta
|
|
7
|
+
title="vdt-videojs/Introduction"
|
|
8
|
+
parameters={{
|
|
9
|
+
viewMode: 'docs',
|
|
10
|
+
previewTabs: {
|
|
11
|
+
canvas: { hidden: true },
|
|
12
|
+
},
|
|
13
|
+
}}
|
|
14
|
+
/>
|
|
15
|
+
|
|
16
|
+
export const changelogMd = () => {
|
|
17
|
+
let mdChangeLog = '';
|
|
18
|
+
Object.keys(pkgJson.changelog)
|
|
19
|
+
.reverse()
|
|
20
|
+
.forEach((changelogKey) => {
|
|
21
|
+
mdChangeLog += `### ${changelogKey}:\n\n`;
|
|
22
|
+
pkgJson.changelog[changelogKey].forEach((entry) => {
|
|
23
|
+
mdChangeLog += `- ${entry}\n`;
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
return mdChangeLog;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
# Introduction
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
┌───────────┐ ┌───────┐
|
|
33
|
+
│ vdt-react ---------------- ( hooks, providers, wrappers ) --> │ │
|
|
34
|
+
└───────────┘ │ │
|
|
35
|
+
┌─────────┐ │ │
|
|
36
|
+
│ vdt-api ------------------------- ( API js Promises ) ------> │ │
|
|
37
|
+
└─────────┘ │ │
|
|
38
|
+
┌────────────────┐ │ │
|
|
39
|
+
│ vdt-materialui -- (Customized Material UI React library) ---> │ │
|
|
40
|
+
└────────────────┘ │ Your │
|
|
41
|
+
┌─── player components ──┐ │ SPA │
|
|
42
|
+
│┌───────────────────────┐ │ │
|
|
43
|
+
open-source player packages --> ││ vdt-videojs-react ---> │ │
|
|
44
|
+
│└───────────────────────┘ │ │
|
|
45
|
+
┌─────────────┐ │┌───────────────────────┐ │ │
|
|
46
|
+
│ vdt-videojs ------------------> ││ vdt-videojs-vue (?) ---> │ │
|
|
47
|
+
└─────────────┘ │└───────────────────────┘ └───────┘
|
|
48
|
+
(pure js) └ wrapped for frameworks ┘
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
vdt-videojs sets out to build a pure javascript video player on top of [video.js](https://videojs.com) and delivers more features with a "familiar" user interface / experience. There is an every-so-often manually deployed [live demo here](https://vdt-js-player.netlify.app/).
|
|
53
|
+
|
|
54
|
+
vdt-videojs is written in ES6 Javascript and has minimal dependencies; It's wrapable for supported frameworks.
|
|
55
|
+
|
|
56
|
+
Additionally vdt-videojs package exports other pure js components closely related to Player (SeekBar, TimeCodeDisplay, ExternalControls and others) for
|
|
57
|
+
use with react / other frameworks within their respective wrappers.
|
|
58
|
+
|
|
59
|
+
See the [vdt-videojs-react](./?path=/story/vdt-videojs-react-videoplayer--basic) package for use with React.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Meta } from '@storybook/addon-docs';
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="vdt-videojs/Player Menu/Class Methods"
|
|
5
|
+
parameters={{
|
|
6
|
+
viewMode: 'docs',
|
|
7
|
+
previewTabs: {
|
|
8
|
+
canvas: { hidden: true },
|
|
9
|
+
},
|
|
10
|
+
}}
|
|
11
|
+
/>
|
|
12
|
+
|
|
13
|
+
## Class Methods
|
|
14
|
+
|
|
15
|
+
Menu is initialized at `player.menu`, so you can access
|
|
16
|
+
the Menu class instance methods via `player.menu.methodName()`.
|
|
17
|
+
|
|
18
|
+
<br />
|
|
19
|
+
<table>
|
|
20
|
+
<thead>
|
|
21
|
+
<tr>
|
|
22
|
+
<th>Method</th>
|
|
23
|
+
<th>Description</th>
|
|
24
|
+
<th>Associated hotkey</th>
|
|
25
|
+
</tr>
|
|
26
|
+
</thead>
|
|
27
|
+
<tbody>
|
|
28
|
+
<tr>
|
|
29
|
+
<td>.open()</td>
|
|
30
|
+
<td>Open menu</td>
|
|
31
|
+
<td>N</td>
|
|
32
|
+
</tr>
|
|
33
|
+
<tr>
|
|
34
|
+
<td>.close()</td>
|
|
35
|
+
<td>Close menu</td>
|
|
36
|
+
<td>ESC, N</td>
|
|
37
|
+
</tr>
|
|
38
|
+
<tr>
|
|
39
|
+
<td>.toggle()</td>
|
|
40
|
+
<td>Toggle open / close</td>
|
|
41
|
+
<td>N</td>
|
|
42
|
+
</tr>
|
|
43
|
+
<tr>
|
|
44
|
+
<td>.up()</td>
|
|
45
|
+
<td>Go up to main level</td>
|
|
46
|
+
<td />
|
|
47
|
+
</tr>
|
|
48
|
+
<tr>
|
|
49
|
+
<td>.render()</td>
|
|
50
|
+
<td>Update selected items in main level</td>
|
|
51
|
+
<td />
|
|
52
|
+
</tr>
|
|
53
|
+
<tr>
|
|
54
|
+
<td>.opened</td>
|
|
55
|
+
<td>Getter property (bool) - use this to get the state of menu</td>
|
|
56
|
+
<td />
|
|
57
|
+
</tr>
|
|
58
|
+
</tbody>
|
|
59
|
+
</table>
|
package/src/menu.js
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
/* eslint-disable max-classes-per-file */
|
|
5
5
|
import mousetrap from 'mousetrap';
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
const constants = Object.freeze({
|
|
9
8
|
className: 'vdt-menu',
|
|
10
9
|
menuClassName: 'menu',
|
|
@@ -21,7 +20,6 @@ const constants = Object.freeze({
|
|
|
21
20
|
},
|
|
22
21
|
});
|
|
23
22
|
|
|
24
|
-
|
|
25
23
|
const CSS = () => `
|
|
26
24
|
.${constants.menuClassName}{
|
|
27
25
|
position: relative;
|
|
@@ -149,19 +147,19 @@ class MenuDisplayItem {
|
|
|
149
147
|
this.container = document.createElement('tr');
|
|
150
148
|
this.container.className = classNames.join(' ');
|
|
151
149
|
|
|
152
|
-
|
|
153
|
-
this.props.target && this.props.target.appendChild(this.container);
|
|
150
|
+
if (this.props.target) this.props.target.appendChild(this.container);
|
|
154
151
|
|
|
155
152
|
// bind click
|
|
156
153
|
this.container.onclick = (event) => {
|
|
157
|
-
this.props.onClick
|
|
154
|
+
if (this.props.onClick) this.props.onClick(event);
|
|
158
155
|
};
|
|
159
156
|
|
|
160
157
|
this.render();
|
|
161
158
|
}
|
|
162
159
|
|
|
163
160
|
render() {
|
|
164
|
-
if (this.props.items) {
|
|
161
|
+
if (this.props.items) {
|
|
162
|
+
// will transition to 2nd level
|
|
165
163
|
this.container.innerHTML = `
|
|
166
164
|
<td class="title"></td>
|
|
167
165
|
<td class="subtitle"></td>
|
|
@@ -174,10 +172,12 @@ class MenuDisplayItem {
|
|
|
174
172
|
}
|
|
175
173
|
|
|
176
174
|
const titleNode = this.container.getElementsByClassName('title')[0];
|
|
177
|
-
const subtitleNode =
|
|
175
|
+
const subtitleNode = this.props.items
|
|
176
|
+
? this.container.getElementsByClassName('subtitle')[0]
|
|
177
|
+
: false;
|
|
178
178
|
|
|
179
179
|
titleNode.textContent = this.props.title;
|
|
180
|
-
|
|
180
|
+
if (subtitleNode) subtitleNode.textContent = this.props.subtitle;
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
|
|
@@ -213,8 +213,7 @@ export default class Menu {
|
|
|
213
213
|
|
|
214
214
|
// shadow node encapsulates style and prevents css collisions
|
|
215
215
|
this.shadow = this.container.attachShadow({ mode: 'open' });
|
|
216
|
-
this.props.target
|
|
217
|
-
|
|
216
|
+
if (this.props.target) this.props.target.appendChild(this.container);
|
|
218
217
|
|
|
219
218
|
// node for menu itself
|
|
220
219
|
this.menuContainer = document.createElement('div');
|
|
@@ -230,7 +229,8 @@ export default class Menu {
|
|
|
230
229
|
}
|
|
231
230
|
}
|
|
232
231
|
|
|
233
|
-
draw() {
|
|
232
|
+
draw() {
|
|
233
|
+
// first draw
|
|
234
234
|
const mainDiv = document.createElement('div');
|
|
235
235
|
mainDiv.className = 'level-1';
|
|
236
236
|
this.mainLevel = document.createElement('table');
|
|
@@ -240,12 +240,13 @@ export default class Menu {
|
|
|
240
240
|
const subDiv = document.createElement('div');
|
|
241
241
|
subDiv.className = 'level-2';
|
|
242
242
|
this.subLvlTitle = document.createElement('h3');
|
|
243
|
-
this.subLvlTitle.onclick = () => {
|
|
243
|
+
this.subLvlTitle.onclick = () => {
|
|
244
|
+
this.up();
|
|
245
|
+
};
|
|
244
246
|
subDiv.appendChild(this.subLvlTitle);
|
|
245
247
|
this.secondaryLevel = document.createElement('table');
|
|
246
248
|
subDiv.appendChild(this.secondaryLevel);
|
|
247
249
|
|
|
248
|
-
|
|
249
250
|
this.menuContainer.appendChild(mainDiv);
|
|
250
251
|
this.menuContainer.appendChild(subDiv);
|
|
251
252
|
|
|
@@ -269,11 +270,12 @@ export default class Menu {
|
|
|
269
270
|
this.render();
|
|
270
271
|
|
|
271
272
|
this.menuContainer.classList.add('open');
|
|
272
|
-
this.props.onOpen
|
|
273
|
+
if (this.props.onOpen) this.props.onOpen();
|
|
273
274
|
this.state.opened = true;
|
|
274
275
|
|
|
275
276
|
// close the menu when user clicks outside it
|
|
276
277
|
if (!this.handleClicksWhenMenuOpened) {
|
|
278
|
+
// eslint-disable-next-line func-names
|
|
277
279
|
this.handleClicksWhenMenuOpened = function (event) {
|
|
278
280
|
if (this.state.opened) {
|
|
279
281
|
event.stopPropagation();
|
|
@@ -295,10 +297,11 @@ export default class Menu {
|
|
|
295
297
|
this.menuContainer.classList.remove('open');
|
|
296
298
|
this.state.opened = false;
|
|
297
299
|
|
|
298
|
-
|
|
300
|
+
if (this.handleClicksWhenMenuOpenedTimeout)
|
|
301
|
+
clearTimeout(this.handleClicksWhenMenuOpenedTimeout);
|
|
299
302
|
document.removeEventListener('click', this.handleClicksWhenMenuOpened);
|
|
300
303
|
|
|
301
|
-
this.props.onClose
|
|
304
|
+
if (this.props.onClose) this.props.onClose();
|
|
302
305
|
|
|
303
306
|
mousetrap.unbind('esc');
|
|
304
307
|
}
|
|
@@ -311,7 +314,8 @@ export default class Menu {
|
|
|
311
314
|
}
|
|
312
315
|
}
|
|
313
316
|
|
|
314
|
-
up() {
|
|
317
|
+
up() {
|
|
318
|
+
// go to level 1
|
|
315
319
|
this.menuContainer.classList.remove(constants.subLvlClassName);
|
|
316
320
|
this.render();
|
|
317
321
|
}
|
|
@@ -333,7 +337,7 @@ export default class Menu {
|
|
|
333
337
|
onClick: (event) => {
|
|
334
338
|
this.handleSubItemSelected(event, menuItem);
|
|
335
339
|
},
|
|
336
|
-
selected:
|
|
340
|
+
selected: index === activeIndex, // mark selected
|
|
337
341
|
});
|
|
338
342
|
|
|
339
343
|
subItemRefs.push(displayItem);
|
|
@@ -344,7 +348,7 @@ export default class Menu {
|
|
|
344
348
|
|
|
345
349
|
handleSubItemSelected(event, item) {
|
|
346
350
|
this.close();
|
|
347
|
-
item.onClick
|
|
351
|
+
if (item.onClick) item.onClick(event, item);
|
|
348
352
|
this.up();
|
|
349
353
|
}
|
|
350
354
|
|