@cloudnest/redxplyr 1.0.0
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/.editorconfig +10 -0
- package/.gitpod.yml +6 -0
- package/.node-version +1 -0
- package/.prettierrc +7 -0
- package/.stickler.yml +5 -0
- package/.stylelintrc.json +26 -0
- package/CHANGELOG.md +16 -0
- package/CONTRIBUTING.md +34 -0
- package/CONTROLS.md +49 -0
- package/Dockerfile +32 -0
- package/LICENSE.md +22 -0
- package/README.md +194 -0
- package/cspell.json +48 -0
- package/dist/redxplyr.css +1 -0
- package/dist/redxplyr.js +8801 -0
- package/dist/redxplyr.min.js +2 -0
- package/dist/redxplyr.min.js.map +1 -0
- package/dist/redxplyr.min.mjs +1 -0
- package/dist/redxplyr.min.mjs.map +1 -0
- package/dist/redxplyr.mjs +8793 -0
- package/dist/redxplyr.polyfilled.js +9294 -0
- package/dist/redxplyr.polyfilled.min.js +2 -0
- package/dist/redxplyr.polyfilled.min.js.map +1 -0
- package/dist/redxplyr.polyfilled.min.mjs +1 -0
- package/dist/redxplyr.polyfilled.min.mjs.map +1 -0
- package/dist/redxplyr.polyfilled.mjs +9286 -0
- package/dist/redxplyr.svg +1 -0
- package/eslint.config.mjs +39 -0
- package/gulpfile.js +8 -0
- package/package.json +114 -0
- package/pnpm-workspace.yaml +8 -0
- package/src/js/captions.js +411 -0
- package/src/js/config/defaults.js +459 -0
- package/src/js/config/states.js +10 -0
- package/src/js/config/types.js +34 -0
- package/src/js/console.js +28 -0
- package/src/js/controls.js +1870 -0
- package/src/js/fullscreen.js +305 -0
- package/src/js/html5.js +148 -0
- package/src/js/listeners.js +854 -0
- package/src/js/media.js +61 -0
- package/src/js/plugins/ads.js +647 -0
- package/src/js/plugins/preview-thumbnails.js +706 -0
- package/src/js/plugins/vimeo.js +443 -0
- package/src/js/plugins/youtube.js +451 -0
- package/src/js/plyr.d.ts +729 -0
- package/src/js/plyr.js +1291 -0
- package/src/js/plyr.polyfilled.js +13 -0
- package/src/js/source.js +155 -0
- package/src/js/storage.js +70 -0
- package/src/js/support.js +100 -0
- package/src/js/ui.js +297 -0
- package/src/js/utils/animation.js +33 -0
- package/src/js/utils/arrays.js +23 -0
- package/src/js/utils/browser.js +21 -0
- package/src/js/utils/elements.js +263 -0
- package/src/js/utils/events.js +116 -0
- package/src/js/utils/fetch.js +45 -0
- package/src/js/utils/i18n.js +47 -0
- package/src/js/utils/is.js +81 -0
- package/src/js/utils/load-image.js +19 -0
- package/src/js/utils/load-script.js +14 -0
- package/src/js/utils/load-sprite.js +77 -0
- package/src/js/utils/numbers.js +17 -0
- package/src/js/utils/objects.js +43 -0
- package/src/js/utils/promise.js +14 -0
- package/src/js/utils/strings.js +80 -0
- package/src/js/utils/style.js +148 -0
- package/src/js/utils/time.js +36 -0
- package/src/js/utils/urls.js +40 -0
- package/src/sass/base.scss +69 -0
- package/src/sass/components/badges.scss +12 -0
- package/src/sass/components/captions.scss +58 -0
- package/src/sass/components/control.scss +52 -0
- package/src/sass/components/controls.scss +65 -0
- package/src/sass/components/menus.scss +205 -0
- package/src/sass/components/poster.scss +27 -0
- package/src/sass/components/progress.scss +107 -0
- package/src/sass/components/sliders.scss +99 -0
- package/src/sass/components/times.scss +20 -0
- package/src/sass/components/tooltips.scss +91 -0
- package/src/sass/components/volume.scss +18 -0
- package/src/sass/lib/animation.scss +31 -0
- package/src/sass/lib/css-vars.scss +103 -0
- package/src/sass/lib/functions.scss +3 -0
- package/src/sass/lib/mixins.scss +82 -0
- package/src/sass/plugins/ads.scss +53 -0
- package/src/sass/plugins/preview-thumbnails/index.scss +121 -0
- package/src/sass/plugins/preview-thumbnails/settings.scss +17 -0
- package/src/sass/plyr.scss +46 -0
- package/src/sass/settings/badges.scss +7 -0
- package/src/sass/settings/breakpoints.scss +9 -0
- package/src/sass/settings/captions.scss +10 -0
- package/src/sass/settings/colors.scss +18 -0
- package/src/sass/settings/controls.scss +30 -0
- package/src/sass/settings/cosmetics.scss +5 -0
- package/src/sass/settings/helpers.scss +7 -0
- package/src/sass/settings/menus.scss +13 -0
- package/src/sass/settings/progress.scss +18 -0
- package/src/sass/settings/sliders.scss +39 -0
- package/src/sass/settings/tooltips.scss +11 -0
- package/src/sass/settings/type.scss +16 -0
- package/src/sass/states/fullscreen.scss +15 -0
- package/src/sass/types/audio.scss +61 -0
- package/src/sass/types/video.scss +170 -0
- package/src/sass/utils/animation.scss +7 -0
- package/src/sass/utils/hidden.scss +28 -0
- package/src/sprite/plyr-airplay.svg +8 -0
- package/src/sprite/plyr-captions-off.svg +7 -0
- package/src/sprite/plyr-captions-on.svg +7 -0
- package/src/sprite/plyr-download.svg +8 -0
- package/src/sprite/plyr-enter-fullscreen.svg +4 -0
- package/src/sprite/plyr-exit-fullscreen.svg +4 -0
- package/src/sprite/plyr-fast-forward.svg +3 -0
- package/src/sprite/plyr-logo-vimeo.svg +6 -0
- package/src/sprite/plyr-logo-youtube.svg +6 -0
- package/src/sprite/plyr-muted.svg +8 -0
- package/src/sprite/plyr-pause.svg +8 -0
- package/src/sprite/plyr-pip.svg +6 -0
- package/src/sprite/plyr-play.svg +5 -0
- package/src/sprite/plyr-restart.svg +5 -0
- package/src/sprite/plyr-rewind.svg +3 -0
- package/src/sprite/plyr-settings.svg +5 -0
- package/src/sprite/plyr-volume.svg +11 -0
- package/tasks/build.js +226 -0
- package/tasks/deploy.js +216 -0
- package/tasks/utils/publish.js +34 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a number whose value is limited to the given range.
|
|
3
|
+
*
|
|
4
|
+
* Example: limit the output of this computation to between 0 and 255
|
|
5
|
+
* (x * 255).clamp(0, 255)
|
|
6
|
+
*
|
|
7
|
+
* @param {number} input
|
|
8
|
+
* @param {number} min The lower boundary of the output range
|
|
9
|
+
* @param {number} max The upper boundary of the output range
|
|
10
|
+
* @returns A number within the bounds of min and max
|
|
11
|
+
* @type Number
|
|
12
|
+
*/
|
|
13
|
+
export function clamp(input = 0, min = 0, max = 255) {
|
|
14
|
+
return Math.min(Math.max(input, min), max);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default { clamp };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// Object utils
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
import is from './is';
|
|
6
|
+
|
|
7
|
+
// Clone nested objects
|
|
8
|
+
export function cloneDeep(object) {
|
|
9
|
+
return JSON.parse(JSON.stringify(object));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Get a nested value in an object
|
|
13
|
+
export function getDeep(object, path) {
|
|
14
|
+
return path.split('.').reduce((obj, key) => obj && obj[key], object);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Deep extend destination object with N more objects
|
|
18
|
+
export function extend(target = {}, ...sources) {
|
|
19
|
+
if (!sources.length) {
|
|
20
|
+
return target;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const source = sources.shift();
|
|
24
|
+
|
|
25
|
+
if (!is.object(source)) {
|
|
26
|
+
return target;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Object.keys(source).forEach((key) => {
|
|
30
|
+
if (is.object(source[key])) {
|
|
31
|
+
if (!Object.keys(target).includes(key)) {
|
|
32
|
+
Object.assign(target, { [key]: {} });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
extend(target[key], source[key]);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
Object.assign(target, { [key]: source[key] });
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return extend(target, ...sources);
|
|
43
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import is from './is';
|
|
2
|
+
/**
|
|
3
|
+
* Silence a Promise-like object.
|
|
4
|
+
* This is useful for avoiding non-harmful, but potentially confusing "uncaught
|
|
5
|
+
* play promise" rejection error messages.
|
|
6
|
+
* @param {object} value An object that may or may not be `Promise`-like.
|
|
7
|
+
*/
|
|
8
|
+
export function silencePromise(value) {
|
|
9
|
+
if (is.promise(value)) {
|
|
10
|
+
value.then(null, () => {});
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default { silencePromise };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// String utils
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
import is from './is';
|
|
6
|
+
|
|
7
|
+
// Generate a random ID
|
|
8
|
+
export function generateId(prefix) {
|
|
9
|
+
return `${prefix}-${Math.floor(Math.random() * 10000)}`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Format string
|
|
13
|
+
export function format(input, ...args) {
|
|
14
|
+
if (is.empty(input)) return input;
|
|
15
|
+
|
|
16
|
+
return input.toString().replace(/\{(\d+)\}/g, (_, i) => args[i].toString());
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Get percentage
|
|
20
|
+
export function getPercentage(current, max) {
|
|
21
|
+
if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return ((current / max) * 100).toFixed(2);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Replace all occurrences of a string in a string
|
|
29
|
+
export function replaceAll(input = '', find = '', replace = '') {
|
|
30
|
+
return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString());
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Convert to title case
|
|
34
|
+
export function toTitleCase(input = '') {
|
|
35
|
+
return input.toString().replace(/\w\S*/g, text => text.charAt(0).toUpperCase() + text.slice(1).toLowerCase());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Convert string to pascalCase
|
|
39
|
+
export function toPascalCase(input = '') {
|
|
40
|
+
let string = input.toString();
|
|
41
|
+
|
|
42
|
+
// Convert kebab case
|
|
43
|
+
string = replaceAll(string, '-', ' ');
|
|
44
|
+
|
|
45
|
+
// Convert snake case
|
|
46
|
+
string = replaceAll(string, '_', ' ');
|
|
47
|
+
|
|
48
|
+
// Convert to title case
|
|
49
|
+
string = toTitleCase(string);
|
|
50
|
+
|
|
51
|
+
// Convert to pascal case
|
|
52
|
+
return replaceAll(string, ' ', '');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Convert string to pascalCase
|
|
56
|
+
export function toCamelCase(input = '') {
|
|
57
|
+
let string = input.toString();
|
|
58
|
+
|
|
59
|
+
// Convert to pascal case
|
|
60
|
+
string = toPascalCase(string);
|
|
61
|
+
|
|
62
|
+
// Convert first character to lowercase
|
|
63
|
+
return string.charAt(0).toLowerCase() + string.slice(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Remove HTML from a string
|
|
67
|
+
export function stripHTML(source) {
|
|
68
|
+
const fragment = document.createDocumentFragment();
|
|
69
|
+
const element = document.createElement('div');
|
|
70
|
+
fragment.appendChild(element);
|
|
71
|
+
element.innerHTML = source;
|
|
72
|
+
return fragment.firstChild.textContent;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Like outerHTML, but also works for DocumentFragment
|
|
76
|
+
export function getHTML(element) {
|
|
77
|
+
const wrapper = document.createElement('div');
|
|
78
|
+
wrapper.appendChild(element);
|
|
79
|
+
return wrapper.innerHTML;
|
|
80
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// Style utils
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
import { closest } from './arrays';
|
|
6
|
+
import is from './is';
|
|
7
|
+
|
|
8
|
+
// Check support for a CSS declaration
|
|
9
|
+
export function supportsCSS(declaration) {
|
|
10
|
+
if (!window || !window.CSS) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return window.CSS.supports(declaration);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Standard/common aspect ratios
|
|
18
|
+
const standardRatios = [
|
|
19
|
+
[1, 1],
|
|
20
|
+
[4, 3],
|
|
21
|
+
[3, 4],
|
|
22
|
+
[5, 4],
|
|
23
|
+
[4, 5],
|
|
24
|
+
[3, 2],
|
|
25
|
+
[2, 3],
|
|
26
|
+
[16, 10],
|
|
27
|
+
[10, 16],
|
|
28
|
+
[16, 9],
|
|
29
|
+
[9, 16],
|
|
30
|
+
[21, 9],
|
|
31
|
+
[9, 21],
|
|
32
|
+
[32, 9],
|
|
33
|
+
[9, 32],
|
|
34
|
+
].reduce((out, [x, y]) => ({ ...out, [x / y]: [x, y] }), {});
|
|
35
|
+
|
|
36
|
+
// Validate an aspect ratio
|
|
37
|
+
export function validateAspectRatio(input) {
|
|
38
|
+
if (!is.array(input) && (!is.string(input) || !input.includes(':'))) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const ratio = is.array(input) ? input : input.split(':');
|
|
43
|
+
|
|
44
|
+
return ratio.map(Number).every(is.number);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Reduce an aspect ratio to it's lowest form
|
|
48
|
+
export function reduceAspectRatio(ratio) {
|
|
49
|
+
if (!is.array(ratio) || !ratio.every(is.number)) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const [width, height] = ratio;
|
|
54
|
+
const getDivider = (w, h) => (h === 0 ? w : getDivider(h, w % h));
|
|
55
|
+
const divider = getDivider(width, height);
|
|
56
|
+
|
|
57
|
+
return [width / divider, height / divider];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Calculate an aspect ratio
|
|
61
|
+
export function getAspectRatio(input) {
|
|
62
|
+
const parse = ratio => (validateAspectRatio(ratio) ? ratio.split(':').map(Number) : null);
|
|
63
|
+
// Try provided ratio
|
|
64
|
+
let ratio = parse(input);
|
|
65
|
+
|
|
66
|
+
// Get from config
|
|
67
|
+
if (ratio === null) {
|
|
68
|
+
ratio = parse(this.config.ratio);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Get from embed
|
|
72
|
+
if (ratio === null && !is.empty(this.embed) && is.array(this.embed.ratio)) {
|
|
73
|
+
({ ratio } = this.embed);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Get from HTML5 video
|
|
77
|
+
if (ratio === null && this.isHTML5) {
|
|
78
|
+
const { videoWidth, videoHeight } = this.media;
|
|
79
|
+
ratio = [videoWidth, videoHeight];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return reduceAspectRatio(ratio);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Set aspect ratio for responsive container
|
|
86
|
+
export function setAspectRatio(input) {
|
|
87
|
+
if (!this.isVideo) {
|
|
88
|
+
return {};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const { wrapper } = this.elements;
|
|
92
|
+
const ratio = getAspectRatio.call(this, input);
|
|
93
|
+
|
|
94
|
+
if (!is.array(ratio)) {
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const [x, y] = reduceAspectRatio(ratio);
|
|
99
|
+
const useNative = supportsCSS(`aspect-ratio: ${x}/${y}`);
|
|
100
|
+
const padding = (100 / x) * y;
|
|
101
|
+
|
|
102
|
+
if (useNative) {
|
|
103
|
+
wrapper.style.aspectRatio = `${x}/${y}`;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
wrapper.style.paddingBottom = `${padding}%`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// For Vimeo we have an extra <div> to hide the standard controls and UI
|
|
110
|
+
if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
|
|
111
|
+
const height = (100 / this.media.offsetWidth) * Number.parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
|
|
112
|
+
const offset = (height - padding) / (height / 50);
|
|
113
|
+
|
|
114
|
+
if (this.fullscreen.active) {
|
|
115
|
+
wrapper.style.paddingBottom = null;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
this.media.style.transform = `translateY(-${offset}%)`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else if (this.isHTML5) {
|
|
122
|
+
wrapper.classList.add(this.config.classNames.videoFixedRatio);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return { padding, ratio };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Round an aspect ratio to closest standard ratio
|
|
129
|
+
export function roundAspectRatio(x, y, tolerance = 0.05) {
|
|
130
|
+
const ratio = x / y;
|
|
131
|
+
const closestRatio = closest(Object.keys(standardRatios), ratio);
|
|
132
|
+
|
|
133
|
+
// Check match is within tolerance
|
|
134
|
+
if (Math.abs(closestRatio - ratio) <= tolerance) {
|
|
135
|
+
return standardRatios[closestRatio];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// No match
|
|
139
|
+
return [x, y];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Get the size of the viewport
|
|
143
|
+
// https://stackoverflow.com/questions/1248081/how-to-get-the-browser-viewport-dimensions
|
|
144
|
+
export function getViewportSize() {
|
|
145
|
+
const width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
|
|
146
|
+
const height = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
|
|
147
|
+
return [width, height];
|
|
148
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// Time utils
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
import is from './is';
|
|
6
|
+
|
|
7
|
+
// Time helpers
|
|
8
|
+
export const getHours = value => Math.trunc((value / 60 / 60) % 60, 10);
|
|
9
|
+
export const getMinutes = value => Math.trunc((value / 60) % 60, 10);
|
|
10
|
+
export const getSeconds = value => Math.trunc(value % 60, 10);
|
|
11
|
+
|
|
12
|
+
// Format time to UI friendly string
|
|
13
|
+
export function formatTime(time = 0, displayHours = false, inverted = false) {
|
|
14
|
+
// Bail if the value isn't a number
|
|
15
|
+
if (!is.number(time)) {
|
|
16
|
+
return formatTime(undefined, displayHours, inverted);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Format time component to add leading zero
|
|
20
|
+
const format = value => `0${value}`.slice(-2);
|
|
21
|
+
// Breakdown to hours, mins, secs
|
|
22
|
+
let hours = getHours(time);
|
|
23
|
+
const mins = getMinutes(time);
|
|
24
|
+
const secs = getSeconds(time);
|
|
25
|
+
|
|
26
|
+
// Do we need to display hours?
|
|
27
|
+
if (displayHours || hours > 0) {
|
|
28
|
+
hours = `${hours}:`;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
hours = '';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Render
|
|
35
|
+
return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;
|
|
36
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// URL utils
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
import is from './is';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Parse a string to a URL object
|
|
9
|
+
* @param {string} input - the URL to be parsed
|
|
10
|
+
* @param {boolean} safe - failsafe parsing
|
|
11
|
+
*/
|
|
12
|
+
export function parseUrl(input, safe = true) {
|
|
13
|
+
let url = input;
|
|
14
|
+
|
|
15
|
+
if (safe) {
|
|
16
|
+
const parser = document.createElement('a');
|
|
17
|
+
parser.href = url;
|
|
18
|
+
url = parser.href;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
return new URL(url);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Convert object to URLSearchParams
|
|
30
|
+
export function buildUrlParams(input) {
|
|
31
|
+
const params = new URLSearchParams();
|
|
32
|
+
|
|
33
|
+
if (is.object(input)) {
|
|
34
|
+
Object.entries(input).forEach(([key, value]) => {
|
|
35
|
+
params.set(key, value);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return params;
|
|
40
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// --------------------------------------------------------------
|
|
2
|
+
// Base styling
|
|
3
|
+
// --------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
// Base
|
|
6
|
+
.plyr {
|
|
7
|
+
@include plyr-font-smoothing($plyr-font-smoothing);
|
|
8
|
+
|
|
9
|
+
align-items: center;
|
|
10
|
+
direction: ltr;
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
font-family: $plyr-font-family;
|
|
14
|
+
font-variant-numeric: tabular-nums; // Force monosace-esque number widths
|
|
15
|
+
font-weight: $plyr-font-weight-regular;
|
|
16
|
+
line-height: $plyr-line-height;
|
|
17
|
+
max-width: 100%;
|
|
18
|
+
min-width: 200px;
|
|
19
|
+
position: relative;
|
|
20
|
+
text-shadow: none;
|
|
21
|
+
transition: box-shadow 0.3s ease;
|
|
22
|
+
z-index: 0; // Force any border radius
|
|
23
|
+
|
|
24
|
+
// Media elements
|
|
25
|
+
video,
|
|
26
|
+
audio,
|
|
27
|
+
iframe {
|
|
28
|
+
display: block;
|
|
29
|
+
height: 100%;
|
|
30
|
+
width: 100%;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
button {
|
|
34
|
+
font: inherit;
|
|
35
|
+
line-height: inherit;
|
|
36
|
+
width: auto;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Ignore focus
|
|
40
|
+
&:focus {
|
|
41
|
+
outline: 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// border-box everything
|
|
46
|
+
// http://paulirish.com/2012/box-sizing-border-box-ftw/
|
|
47
|
+
@if $plyr-border-box {
|
|
48
|
+
.plyr--full-ui {
|
|
49
|
+
box-sizing: border-box;
|
|
50
|
+
|
|
51
|
+
*,
|
|
52
|
+
*::after,
|
|
53
|
+
*::before {
|
|
54
|
+
box-sizing: inherit;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Fix 300ms delay
|
|
60
|
+
@if $plyr-touch-action {
|
|
61
|
+
.plyr--full-ui {
|
|
62
|
+
a,
|
|
63
|
+
button,
|
|
64
|
+
input,
|
|
65
|
+
label {
|
|
66
|
+
touch-action: manipulation;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// --------------------------------------------------------------
|
|
2
|
+
// Badges
|
|
3
|
+
// --------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
.plyr__badge {
|
|
6
|
+
background: $plyr-badge-background;
|
|
7
|
+
border-radius: $plyr-badge-border-radius;
|
|
8
|
+
color: $plyr-badge-text-color;
|
|
9
|
+
font-size: $plyr-font-size-badge;
|
|
10
|
+
line-height: 1;
|
|
11
|
+
padding: 3px 4px;
|
|
12
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// --------------------------------------------------------------
|
|
2
|
+
// Captions
|
|
3
|
+
// --------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
// Hide default captions
|
|
6
|
+
.plyr--full-ui ::-webkit-media-text-track-container {
|
|
7
|
+
display: none;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.plyr__captions {
|
|
11
|
+
animation: plyr-fade-in 0.3s ease;
|
|
12
|
+
bottom: 0;
|
|
13
|
+
display: none;
|
|
14
|
+
font-size: $plyr-font-size-captions-small;
|
|
15
|
+
left: 0;
|
|
16
|
+
padding: $plyr-control-spacing;
|
|
17
|
+
position: absolute;
|
|
18
|
+
text-align: center;
|
|
19
|
+
transition: transform 0.4s ease-in-out;
|
|
20
|
+
width: 100%;
|
|
21
|
+
|
|
22
|
+
span:empty {
|
|
23
|
+
display: none;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@media (min-width: $plyr-bp-sm) {
|
|
27
|
+
font-size: $plyr-font-size-captions-base;
|
|
28
|
+
padding: calc(#{$plyr-control-spacing} * 2);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@media (min-width: $plyr-bp-md) {
|
|
32
|
+
font-size: $plyr-font-size-captions-medium;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.plyr--captions-active .plyr__captions {
|
|
37
|
+
display: block;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// If the lower controls are shown and not empty
|
|
41
|
+
.plyr:not(.plyr--hide-controls) .plyr__controls:not(:empty) ~ .plyr__captions {
|
|
42
|
+
transform: translateY(calc(#{$plyr-control-spacing} * -4));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.plyr__caption {
|
|
46
|
+
background: $plyr-captions-background;
|
|
47
|
+
border-radius: 4px;
|
|
48
|
+
box-decoration-break: clone;
|
|
49
|
+
color: $plyr-captions-text-color;
|
|
50
|
+
line-height: 185%;
|
|
51
|
+
padding: 0.2em 0.5em;
|
|
52
|
+
white-space: pre-wrap;
|
|
53
|
+
|
|
54
|
+
// Firefox adds a <div> when using getCueAsHTML()
|
|
55
|
+
div {
|
|
56
|
+
display: inline;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// --------------------------------------------------------------
|
|
2
|
+
// Control buttons
|
|
3
|
+
// --------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
.plyr__control {
|
|
6
|
+
background: transparent;
|
|
7
|
+
border: 0;
|
|
8
|
+
border-radius: $plyr-control-radius;
|
|
9
|
+
color: inherit;
|
|
10
|
+
cursor: pointer;
|
|
11
|
+
flex-shrink: 0;
|
|
12
|
+
overflow: visible; // IE11
|
|
13
|
+
padding: $plyr-control-padding;
|
|
14
|
+
position: relative;
|
|
15
|
+
transition: all 0.1s ease-in-out;
|
|
16
|
+
|
|
17
|
+
svg {
|
|
18
|
+
display: block;
|
|
19
|
+
fill: currentColor;
|
|
20
|
+
height: $plyr-control-icon-size;
|
|
21
|
+
pointer-events: none;
|
|
22
|
+
width: $plyr-control-icon-size;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Default focus
|
|
26
|
+
&:focus {
|
|
27
|
+
outline: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Tab focus
|
|
31
|
+
&:focus-visible {
|
|
32
|
+
@include plyr-focus-visible;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Remove any link styling
|
|
37
|
+
a.plyr__control {
|
|
38
|
+
text-decoration: none;
|
|
39
|
+
|
|
40
|
+
&::after,
|
|
41
|
+
&::before {
|
|
42
|
+
display: none;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Change icons on state change
|
|
47
|
+
.plyr__control:not(.plyr__control--pressed) .icon--pressed,
|
|
48
|
+
.plyr__control.plyr__control--pressed .icon--not-pressed,
|
|
49
|
+
.plyr__control:not(.plyr__control--pressed) .label--pressed,
|
|
50
|
+
.plyr__control.plyr__control--pressed .label--not-pressed {
|
|
51
|
+
display: none;
|
|
52
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// --------------------------------------------------------------
|
|
2
|
+
// Controls
|
|
3
|
+
// --------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
// Hide native controls
|
|
6
|
+
.plyr--full-ui ::-webkit-media-controls {
|
|
7
|
+
display: none;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Playback controls
|
|
11
|
+
.plyr__controls {
|
|
12
|
+
align-items: center;
|
|
13
|
+
display: flex;
|
|
14
|
+
justify-content: flex-end;
|
|
15
|
+
text-align: center;
|
|
16
|
+
|
|
17
|
+
.plyr__progress__container {
|
|
18
|
+
flex: 1;
|
|
19
|
+
min-width: 0; // Fix for Edge issue where content would overflow
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Spacing
|
|
23
|
+
.plyr__controls__item {
|
|
24
|
+
margin-left: calc(#{$plyr-control-spacing} / 4);
|
|
25
|
+
|
|
26
|
+
&:first-child {
|
|
27
|
+
margin-left: 0;
|
|
28
|
+
margin-right: auto;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&.plyr__progress__container {
|
|
32
|
+
padding-left: calc(#{$plyr-control-spacing} / 4);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&.plyr__time {
|
|
36
|
+
padding: 0 calc(#{$plyr-control-spacing} / 2);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&.plyr__progress__container:first-child,
|
|
40
|
+
&.plyr__time:first-child,
|
|
41
|
+
&.plyr__time + .plyr__time {
|
|
42
|
+
padding-left: 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Hide empty controls
|
|
47
|
+
&:empty {
|
|
48
|
+
display: none;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Some options are hidden by default
|
|
53
|
+
.plyr [data-plyr='captions'],
|
|
54
|
+
.plyr [data-plyr='pip'],
|
|
55
|
+
.plyr [data-plyr='airplay'],
|
|
56
|
+
.plyr [data-plyr='fullscreen'] {
|
|
57
|
+
display: none;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.plyr--captions-enabled [data-plyr='captions'],
|
|
61
|
+
.plyr--pip-supported [data-plyr='pip'],
|
|
62
|
+
.plyr--airplay-supported [data-plyr='airplay'],
|
|
63
|
+
.plyr--fullscreen-enabled [data-plyr='fullscreen'] {
|
|
64
|
+
display: inline-block;
|
|
65
|
+
}
|