@eluvio/elv-player-js 1.0.140 → 2.0.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.
Files changed (102) hide show
  1. package/README.md +35 -6
  2. package/dist/.vite/manifest.json +67 -0
  3. package/dist/Analytics-HWXR7tWt.mjs +2028 -0
  4. package/dist/Analytics-IUVysdzU.js +29 -0
  5. package/dist/dash.all.min-1QS9Xbir.js +25 -0
  6. package/dist/dash.all.min-9V1xYBRv.mjs +19428 -0
  7. package/dist/elv-player-js.cjs.js +1 -0
  8. package/dist/elv-player-js.css +1 -0
  9. package/dist/elv-player-js.es.js +5 -0
  10. package/dist/hls-1eCRapWm.mjs +15461 -0
  11. package/dist/hls-6O5SV1FQ.js +26 -0
  12. package/dist/index-6cMQneJf.mjs +2273 -0
  13. package/dist/index-C8mwW09z.js +23 -0
  14. package/dist/index-J4QpmTkA.js +367 -0
  15. package/dist/index-hvQzQ6UX.mjs +67432 -0
  16. package/lib/index.js +7 -0
  17. package/{src → lib/player}/Analytics.js +9 -8
  18. package/lib/player/Controls.js +913 -0
  19. package/{src → lib/player}/FairPlay.js +2 -0
  20. package/lib/player/Player.js +881 -0
  21. package/lib/player/PlayerParameters.js +173 -0
  22. package/lib/static/icons/Icons.js +29 -0
  23. package/lib/static/icons/svgs/backward-circle.svg +5 -0
  24. package/lib/static/icons/svgs/backward.svg +4 -0
  25. package/lib/static/icons/svgs/captions-off.svg +7 -0
  26. package/lib/static/icons/svgs/captions.svg +6 -0
  27. package/lib/static/icons/svgs/check.svg +1 -0
  28. package/lib/static/icons/svgs/chevron-left.svg +1 -0
  29. package/lib/static/icons/svgs/chevron-right.svg +1 -0
  30. package/lib/static/icons/svgs/forward-circle.svg +5 -0
  31. package/lib/static/icons/svgs/forward.svg +4 -0
  32. package/{src/static/icons/media/Full Screen icon.svg → lib/static/icons/svgs/full-screen.svg} +1 -1
  33. package/lib/static/icons/svgs/large-play-circle.svg +4 -0
  34. package/lib/static/icons/svgs/list.svg +1 -0
  35. package/{src/static/icons → lib/static/icons/svgs}/minimize.svg +1 -1
  36. package/{src/static/icons/media/Pause icon.svg → lib/static/icons/svgs/pause-circle.svg} +3 -3
  37. package/lib/static/icons/svgs/pause.svg +1 -0
  38. package/{src/static/icons/media/Play icon.svg → lib/static/icons/svgs/play-circle.svg} +1 -1
  39. package/lib/static/icons/svgs/play.svg +1 -0
  40. package/lib/static/icons/svgs/rotate-cw.svg +1 -0
  41. package/lib/static/icons/svgs/settings.svg +11 -0
  42. package/{src/static/icons/media/skip back icon.svg → lib/static/icons/svgs/skip-backward.svg} +2 -3
  43. package/{src/static/icons/media/Skip forward icon.svg → lib/static/icons/svgs/skip-forward.svg} +2 -3
  44. package/{src/static/icons/media/Volume icon.svg → lib/static/icons/svgs/volume-high.svg} +3 -3
  45. package/lib/static/icons/svgs/volume-low.svg +10 -0
  46. package/{src/static/icons/media/low volume icon.svg → lib/static/icons/svgs/volume-medium.svg} +2 -2
  47. package/{src/static/icons/media/no volume icon.svg → lib/static/icons/svgs/volume-off.svg} +3 -3
  48. package/lib/static/stylesheets/common.module.scss +486 -0
  49. package/lib/static/stylesheets/controls-tv.module.scss +488 -0
  50. package/lib/static/stylesheets/controls-web.module.scss +422 -0
  51. package/lib/static/stylesheets/player-profile-form.module.scss +141 -0
  52. package/lib/static/stylesheets/player.module.scss +92 -0
  53. package/lib/static/stylesheets/reset.module.scss +79 -0
  54. package/lib/static/stylesheets/ticket-form.module.scss +123 -0
  55. package/lib/ui/BuildIcons.cjs +44 -0
  56. package/lib/ui/Common.js +210 -0
  57. package/lib/ui/Components.jsx +342 -0
  58. package/lib/ui/Observers.js +449 -0
  59. package/lib/ui/PlayerProfileForm.jsx +106 -0
  60. package/lib/ui/PlayerUI.jsx +317 -0
  61. package/lib/ui/TVControls.jsx +337 -0
  62. package/lib/ui/TicketForm.jsx +147 -0
  63. package/lib/ui/WebControls.jsx +290 -0
  64. package/package.json +35 -47
  65. package/dist/index.js +0 -2
  66. package/dist/index.js.LICENSE.txt +0 -80
  67. package/src/BuildIcons.js +0 -27
  68. package/src/PlayerControls.js +0 -1478
  69. package/src/index.js +0 -1417
  70. package/src/static/icons/Icons.js +0 -15
  71. package/src/static/icons/Settings icon.svg +0 -4
  72. package/src/static/icons/chat icon collapse.svg +0 -1
  73. package/src/static/icons/chat icon.svg +0 -11
  74. package/src/static/icons/chat send.svg +0 -1
  75. package/src/static/icons/full screen.svg +0 -1
  76. package/src/static/icons/media/LargePlayIcon.svg +0 -4
  77. package/src/static/icons/media/Settings icon.svg +0 -4
  78. package/src/static/icons/media/Skip backward icon.svg +0 -4
  79. package/src/static/icons/media/list.svg +0 -1
  80. package/src/static/icons/media/loop icon.svg +0 -12
  81. package/src/static/icons/media/shuffle icon.svg +0 -13
  82. package/src/static/icons/muted.svg +0 -11
  83. package/src/static/icons/pause.svg +0 -1
  84. package/src/static/icons/play circle.svg +0 -1
  85. package/src/static/icons/play.svg +0 -1
  86. package/src/static/icons/settings.svg +0 -1
  87. package/src/static/icons/slider circle.svg +0 -1
  88. package/src/static/icons/unmuted.svg +0 -10
  89. package/src/static/images/ELUV.IO logo embed player.png +0 -0
  90. package/src/static/images/ELUV.IO logo embed player.svg +0 -1
  91. package/src/static/images/ELUV.IO white 20 px V2.png +0 -0
  92. package/src/static/images/ELUVIO white.svg +0 -26
  93. package/src/static/images/Logo.png +0 -0
  94. package/src/static/stylesheets/player.scss +0 -1065
  95. package/webpack.config.js +0 -152
  96. /package/{src/static/icons → lib/static/icons/svgs}/arrow-left.svg +0 -0
  97. /package/{src/static/icons/live icon.svg → lib/static/icons/svgs/live.svg} +0 -0
  98. /package/{src/static/icons → lib/static/icons/svgs}/multiview.svg +0 -0
  99. /package/{src/static/icons/media → lib/static/icons/svgs}/next.svg +0 -0
  100. /package/{src/static/icons/media → lib/static/icons/svgs}/previous.svg +0 -0
  101. /package/{src/static/icons → lib/static/icons/svgs}/x.svg +0 -0
  102. /package/{dist/5897e28fa3e8ac0a2fae.png → lib/static/images/Logo.png} +0 -0
@@ -0,0 +1,123 @@
1
+ .ticket-form-container {
2
+ height: 100%;
3
+ inset: 0;
4
+ position: absolute;
5
+ width: 100%;
6
+ }
7
+
8
+ .ticket-form-overlay {
9
+ align-items: center;
10
+ backdrop-filter: blur(10px);
11
+ background: rgba(0, 0, 0, 50%);
12
+ display: flex;
13
+ height: 100%;
14
+ justify-content: center;
15
+ width: 100%;
16
+
17
+ .spinner {
18
+ height: 50px;
19
+ width: 50px;
20
+ }
21
+ }
22
+
23
+ .ticket-form {
24
+ backdrop-filter: blur(10px);
25
+ background: rgba(255, 255, 255, 10%);
26
+ border-radius: 5px;
27
+ color: #FFF;
28
+ display: grid;
29
+ max-width: MIN(600px, 100%);
30
+ padding: 40px 50px 50px;
31
+ position: relative;
32
+ }
33
+
34
+ .text {
35
+ display: grid;
36
+ gap: 8px;
37
+ text-align: center;
38
+ }
39
+
40
+ .title {
41
+ font-size: 20px;
42
+ }
43
+
44
+ .description {
45
+ font-size: 14px;
46
+ }
47
+
48
+ .inputs {
49
+ display: grid;
50
+ gap: 10px;
51
+ justify-content: center;
52
+ margin-top: 20px;
53
+ }
54
+
55
+ .input {
56
+ background: #FFF;
57
+ border-radius: 5px;
58
+ color: #000;
59
+ display: block;
60
+ font-size: 20px;
61
+ font-weight: 600;
62
+ height: 35px;
63
+ letter-spacing: 2px;
64
+ max-width: 250px;
65
+ padding: 0 20px;
66
+ text-align: center;
67
+ width: 100%;
68
+
69
+ &::placeholder {
70
+ font-size: 16px;
71
+ font-weight: 500;
72
+ letter-spacing: initial;
73
+ }
74
+
75
+ &:disabled {
76
+ cursor: default;
77
+ }
78
+ }
79
+
80
+ .submit {
81
+ background: rgba(255, 255, 255, 20%);
82
+ border-radius: 5px;
83
+ height: 40px;
84
+ padding: 10px 0;
85
+ user-select: none;
86
+
87
+ &:disabled {
88
+ opacity: 0.75;
89
+ }
90
+ }
91
+
92
+ .error-message {
93
+ bottom: 15px;
94
+ color: #F00;
95
+ display: block;
96
+ font-size: 14px;
97
+ font-weight: 600;
98
+ left: 0;
99
+ margin: 0 auto;
100
+ padding: 0 20px;
101
+ position: absolute;
102
+ right: 0;
103
+ text-align: center;
104
+ }
105
+
106
+ .size-md,
107
+ .size-sm {
108
+ .ticket-form {
109
+ align-content: center;
110
+ align-items: center;
111
+ background: transparent;
112
+ border-radius: 0;
113
+ height: 100%;
114
+ padding-inline: 20px;
115
+ width: 100%;
116
+ }
117
+
118
+ .error-message {
119
+ height: 20px;
120
+ margin-top: 20px;
121
+ position: unset;
122
+ }
123
+ }
@@ -0,0 +1,44 @@
1
+ console.log("Building UI Icons...\n")
2
+
3
+ const fs = require("fs");
4
+ const Path = require("path");
5
+
6
+ const iconSource = {
7
+ CenterPlayCircleIcon: Path.resolve(__dirname, "../static/icons/svgs/large-play-circle.svg"),
8
+ PlayIcon: Path.resolve(__dirname, "../static/icons/svgs/play.svg"),
9
+ PlayCircleIcon: Path.resolve(__dirname, "../static/icons/svgs/play-circle.svg"),
10
+ PauseIcon: Path.resolve(__dirname, "../static/icons/svgs/pause.svg"),
11
+ PauseCircleIcon: Path.resolve(__dirname, "../static/icons/svgs/pause-circle.svg"),
12
+ FullscreenIcon: Path.resolve(__dirname, "../static/icons/svgs/full-screen.svg"),
13
+ ExitFullscreenIcon: Path.resolve(__dirname, "../static/icons/svgs/minimize.svg"),
14
+ SettingsIcon: Path.resolve(__dirname, "../static/icons/svgs/settings.svg"),
15
+ CloseIcon: Path.resolve(__dirname, "../static/icons/svgs/x.svg"),
16
+ MutedIcon: Path.resolve(__dirname, "../static/icons/svgs/volume-off.svg"),
17
+ VolumeLowIcon: Path.resolve(__dirname, "../static/icons/svgs/volume-low.svg"),
18
+ VolumeMediumIcon: Path.resolve(__dirname, "../static/icons/svgs/volume-medium.svg"),
19
+ VolumeHighIcon: Path.resolve(__dirname, "../static/icons/svgs/volume-high.svg"),
20
+ MultiViewIcon: Path.resolve(__dirname, "../static/icons/svgs/multiview.svg"),
21
+ LeftArrowIcon: Path.resolve(__dirname, "../static/icons/svgs/arrow-left.svg"),
22
+ BackwardIcon: Path.resolve(__dirname, "../static/icons/svgs/backward.svg"),
23
+ BackwardCircleIcon: Path.resolve(__dirname, "../static/icons/svgs/backward-circle.svg"),
24
+ ForwardIcon: Path.resolve(__dirname, "../static/icons/svgs/forward.svg"),
25
+ ForwardCircleIcon: Path.resolve(__dirname, "../static/icons/svgs/forward-circle.svg"),
26
+ PreviousTrackIcon: Path.resolve(__dirname, "../static/icons/svgs/skip-backward.svg"),
27
+ NextTrackIcon: Path.resolve(__dirname, "../static/icons/svgs/skip-forward.svg"),
28
+ CollectionIcon: Path.resolve(__dirname, "../static/icons/svgs/list.svg"),
29
+ ChevronLeftIcon: Path.resolve(__dirname, "../static/icons/svgs/chevron-left.svg"),
30
+ ChevronRightIcon: Path.resolve(__dirname, "../static/icons/svgs/chevron-right.svg"),
31
+ CheckmarkIcon: Path.resolve(__dirname, "../static/icons/svgs/check.svg"),
32
+ CaptionsIcon: Path.resolve(__dirname, "../static/icons/svgs/captions.svg"),
33
+ CaptionsOffIcon: Path.resolve(__dirname, "../static/icons/svgs/captions-off.svg")
34
+ };
35
+
36
+ let iconFile = "// Built using `npm run build-icons`\n\n";
37
+ Object.keys(iconSource).map(iconName => {
38
+ iconFile += `export const ${iconName} = "${fs.readFileSync(iconSource[iconName]).toString("utf8").replaceAll("\n", "").replaceAll("\"", "\\\"")}";\n`;
39
+ });
40
+
41
+ fs.writeFileSync(
42
+ Path.resolve(__dirname, "../static/icons/Icons.js"),
43
+ iconFile
44
+ );
@@ -0,0 +1,210 @@
1
+ import {DefaultParameters} from "../player/PlayerParameters";
2
+
3
+ export const ACTIONS = {
4
+ PLAY: "play",
5
+ PAUSE: "pause",
6
+ MUTE: "muted",
7
+ UNMUTE: "unmuted",
8
+ VOLUME_UP: "volumeup",
9
+ VOLUME_DOWN: "volumedown",
10
+ SEEK_BACK: "seekback",
11
+ SEEK_FORWARD: "seekforward",
12
+ PLAYBACK_RATE_UP: "playbackrateup",
13
+ PLAYBACK_RATE_DOWN: "playbackratedown",
14
+ SUBTITLES_ON: "subtitleson",
15
+ SUBTITLES_OFF: "subtitlesoff",
16
+ PLAY_NEXT: "playnext",
17
+ PLAY_PREVIOUS: "playprevious",
18
+ };
19
+
20
+ // Handlers
21
+
22
+ // Player click handler is a closure so it can keep track of click timing to differentiate between single and double click
23
+ export const PlayerClick = ({player, setRecentUserAction, sideClickRatio=0.1, doubleClickDelay=300}) => {
24
+ let lastClicked, singleClickTimeout, lastFocused, currentFocused;
25
+
26
+ // Keep track of which element has focus - we don't want to play/pause on click if the click was to focus on the player
27
+ // Note that double click to fullscreen *will* still work regardless of focus
28
+ window.addEventListener("focus", () => {
29
+ lastFocused = currentFocused || document.activeElement;
30
+ currentFocused = document.activeElement;
31
+ }, true);
32
+
33
+ // Extra wrapper function so it can be stored as react state
34
+ return () =>
35
+ event => {
36
+ clearTimeout(singleClickTimeout);
37
+
38
+ if(
39
+ // Only react to clicks on this element specifically, not other control elements
40
+ event.target === event.currentTarget &&
41
+ // Player was not previously focused - ignore click
42
+ event.currentTarget.contains(lastFocused) &&
43
+ // Menu open - click will close menu instead of changing pause state
44
+ !event.currentTarget.classList.contains("menu-active")
45
+ ) {
46
+ if(Date.now() - lastClicked < doubleClickDelay) {
47
+ // Double click
48
+
49
+ // If clicked on far left or right side of the player, seek
50
+ const rect = event.target.getBoundingClientRect();
51
+ const xRatio = (event.clientX - rect.left) / rect.width;
52
+
53
+ if(xRatio <= sideClickRatio) {
54
+ player.controls.Seek({relativeSeconds: -10});
55
+ setRecentUserAction({action: ACTIONS.SEEK_BACK, text: "10 seconds"});
56
+ } else if(xRatio >= 1 - sideClickRatio) {
57
+ player.controls.Seek({relativeSeconds: 10});
58
+ setRecentUserAction({action: ACTIONS.SEEK_FORWARD, text: "10 seconds"});
59
+ } else {
60
+ // Otherwise, fullscreen
61
+ player.controls.ToggleFullscreen();
62
+ }
63
+ } else {
64
+ // Single click
65
+ singleClickTimeout = setTimeout(() => {
66
+ const playing = player.controls.TogglePlay();
67
+ setRecentUserAction({action: playing ? ACTIONS.PLAY : ACTIONS.PAUSE});
68
+ }, doubleClickDelay);
69
+ }
70
+ }
71
+
72
+ lastFocused = event.target;
73
+ lastClicked = Date.now();
74
+ };
75
+ };
76
+
77
+ // Seek slider handler is a closure so it can keep track of the number of repeat events to seek faster
78
+ export const SeekSliderKeyDown = (player, setRecentUserAction) => {
79
+ let updates = 0;
80
+ // Extra wrapper function so it can be stored as react state
81
+ return () =>
82
+ event => {
83
+ if(!event.repeat) {
84
+ updates = 0;
85
+ }
86
+
87
+ const seekAmount = updates < 5 ? 5 :
88
+ updates < 15 ? 10 :
89
+ updates < 40 ? 30 :
90
+ 60;
91
+ switch (event.key) {
92
+ case "ArrowLeft":
93
+ event.preventDefault();
94
+ player.controls.Seek({relativeSeconds: -seekAmount});
95
+ setRecentUserAction({action: ACTIONS.SEEK_BACK, text: `${seekAmount} seconds`});
96
+ break;
97
+ case "ArrowRight":
98
+ event.preventDefault();
99
+ player.controls.Seek({relativeSeconds: seekAmount});
100
+ setRecentUserAction({action: ACTIONS.SEEK_FORWARD, text: `${seekAmount} seconds`});
101
+ break;
102
+ default:
103
+ return;
104
+ }
105
+
106
+ updates += 1;
107
+ };
108
+ };
109
+
110
+ export const VolumeSliderKeydown = player =>
111
+ event => {
112
+ switch(event.key) {
113
+ case "ArrowLeft":
114
+ event.preventDefault();
115
+ player.controls.SetVolume({relativeFraction: -0.05});
116
+ break;
117
+ case "ArrowRight":
118
+ event.preventDefault();
119
+ if(player.controls.IsMuted()) {
120
+ player.controls.SetVolume({fraction: 0.05});
121
+ } else {
122
+ player.controls.SetVolume({relativeFraction: 0.05});
123
+ }
124
+ break;
125
+ }
126
+ };
127
+
128
+ // Misc
129
+
130
+ export const Time = (time, total) => {
131
+ if(isNaN(total) || !isFinite(total) || total === 0) {
132
+ return "00:00";
133
+ }
134
+
135
+ const useHours = total > 60 * 60;
136
+
137
+ const hours = Math.floor(time / 60 / 60);
138
+ const minutes = Math.floor(time / 60 % 60);
139
+ const seconds = Math.floor(time % 60);
140
+
141
+ let string = `${minutes.toString().padStart(useHours && hours > 0 ? 2 : 1, "0")}:${seconds.toString().padStart(2, "0")}`;
142
+
143
+ if(useHours) {
144
+ string = `${hours.toString()}:${string}`;
145
+ }
146
+
147
+ return string;
148
+ };
149
+
150
+ export const ImageUrl = async ({player, pathOrUrl="", width}) => {
151
+ if(typeof pathOrUrl === "string" && (pathOrUrl.startsWith("http://") || pathOrUrl.startsWith("https://"))) {
152
+ return pathOrUrl;
153
+ } else if(pathOrUrl && pathOrUrl.url) {
154
+ return pathOrUrl.url;
155
+ }
156
+
157
+ const client = await player.__Client();
158
+ let versionHash;
159
+
160
+ const {mediaCatalogObjectId, mediaCatalogVersionHash} = (player.sourceOptions && player.sourceOptions.mediaCollectionOptions) || {};
161
+ const playoutParameters = player.sourceOptions && player.sourceOptions.playoutParameters || {};
162
+ if(mediaCatalogVersionHash) {
163
+ versionHash = mediaCatalogVersionHash;
164
+ } else if(mediaCatalogObjectId) {
165
+ versionHash = await client.LatestVersionHash({objectId: mediaCatalogObjectId});
166
+ } else if(playoutParameters.versionHash) {
167
+ versionHash = playoutParameters.versionHash;
168
+ } else {
169
+ versionHash = await client.LatestVersionHash({objectId: playoutParameters.objectId});
170
+ }
171
+
172
+ if(!versionHash) { return ""; }
173
+
174
+ pathOrUrl = pathOrUrl && pathOrUrl.toString().trim().replace(/^\./, "").replace(/\/+/, "");
175
+
176
+ if(pathOrUrl.startsWith("files")) {
177
+ return await client.FileUrl({
178
+ versionHash,
179
+ filePath: pathOrUrl.replace(/^files/, ""),
180
+ queryParams: width ? {width} : {},
181
+ authorizationToken: playoutParameters.authorizationToken
182
+ });
183
+ } else {
184
+ return await client.LinkUrl({
185
+ versionHash,
186
+ linkPath: pathOrUrl,
187
+ queryParams: width ? {width} : {},
188
+ authorizationToken: playoutParameters.authorizationToken
189
+ });
190
+ }
191
+ };
192
+
193
+ // Merge defaults with provided parameters. Any parameters not specified in defaults will be ignored.
194
+ export const MergeParameters = (defaults, parameters) => {
195
+ let merged = {};
196
+ Object.keys(defaults).forEach(key => {
197
+ if(typeof defaults[key] === "object" && !Array.isArray(defaults[key])) {
198
+ merged[key] = MergeParameters(defaults[key], (parameters || {})[key]);
199
+ } else {
200
+ const value = (parameters || {})[key];
201
+ merged[key] = typeof value !== "undefined" ? value : defaults[key];
202
+ }
203
+ });
204
+
205
+ return merged;
206
+ };
207
+
208
+ export const MergeDefaultParameters = parameters => {
209
+ return MergeParameters(DefaultParameters, parameters);
210
+ };