@smartimpact-it/modern-video-embed 2.0.5 → 2.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 +322 -71
- package/dist/components/BaseVideoEmbed.d.ts +91 -0
- package/dist/components/BaseVideoEmbed.d.ts.map +1 -0
- package/dist/components/BaseVideoEmbed.js +275 -0
- package/dist/components/BaseVideoEmbed.js.map +1 -0
- package/dist/components/VideoEmbed.d.ts +68 -0
- package/dist/components/VideoEmbed.d.ts.map +1 -0
- package/dist/components/VideoEmbed.js +786 -0
- package/dist/components/VideoEmbed.js.map +1 -0
- package/dist/components/VimeoEmbed.d.ts +26 -36
- package/dist/components/VimeoEmbed.d.ts.map +1 -1
- package/dist/components/VimeoEmbed.js +231 -326
- package/dist/components/VimeoEmbed.js.map +1 -1
- package/dist/components/VimeoEmbed.min.js +1 -1
- package/dist/components/YouTubeEmbed.d.ts +108 -42
- package/dist/components/YouTubeEmbed.d.ts.map +1 -1
- package/dist/components/YouTubeEmbed.js +361 -375
- package/dist/components/YouTubeEmbed.js.map +1 -1
- package/dist/components/YouTubeEmbed.min.js +1 -1
- package/dist/css/components.css +285 -68
- package/dist/css/components.css.map +1 -1
- package/dist/css/components.min.css +1 -1
- package/dist/css/main.css +285 -68
- package/dist/css/main.css.map +1 -1
- package/dist/css/main.min.css +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/video-only.d.ts +7 -0
- package/dist/video-only.d.ts.map +1 -0
- package/dist/video-only.js +8 -0
- package/dist/video-only.js.map +1 -0
- package/dist/vimeo-only.d.ts +2 -2
- package/dist/vimeo-only.d.ts.map +1 -1
- package/dist/vimeo-only.js +2 -2
- package/dist/vimeo-only.js.map +1 -1
- package/dist/vimeo-only.min.js +1 -1
- package/dist/youtube-only.d.ts +2 -2
- package/dist/youtube-only.d.ts.map +1 -1
- package/dist/youtube-only.js +2 -2
- package/dist/youtube-only.js.map +1 -1
- package/dist/youtube-only.min.js +1 -1
- package/package.json +6 -5
- package/src/components/BaseVideoEmbed.ts +335 -0
- package/src/components/VideoEmbed.ts +870 -0
- package/src/components/VideoEmbed.ts.backup +1051 -0
- package/src/components/VimeoEmbed.ts +258 -395
- package/src/components/YouTubeEmbed.ts +378 -432
- package/src/index.ts +1 -0
- package/src/styles/_embed-base.scss +275 -0
- package/src/styles/_shared-functions.scss +56 -0
- package/src/styles/components.scss +4 -3
- package/src/styles/main.scss +7 -5
- package/src/styles/video-embed.scss +55 -0
- package/src/styles/vimeo-embed.scss +8 -248
- package/src/styles/youtube-embed.scss +8 -254
- package/src/types/index.ts +1 -0
- package/src/types/video-embed.d.ts +90 -0
- package/src/video-only.ts +9 -0
- package/src/vimeo-only.ts +2 -2
- package/src/youtube-only.ts +2 -2
|
@@ -0,0 +1,786 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
11
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
12
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
13
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
14
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
15
|
+
};
|
|
16
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
17
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
18
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
19
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
20
|
+
};
|
|
21
|
+
var _VideoEmbed_url, _VideoEmbed_loop, _VideoEmbed_preload;
|
|
22
|
+
import { BaseVideoEmbed } from "./BaseVideoEmbed.js";
|
|
23
|
+
export class VideoEmbed extends BaseVideoEmbed {
|
|
24
|
+
constructor() {
|
|
25
|
+
super(...arguments);
|
|
26
|
+
this.video = null;
|
|
27
|
+
// Video-specific properties
|
|
28
|
+
_VideoEmbed_url.set(this, "");
|
|
29
|
+
_VideoEmbed_loop.set(this, false);
|
|
30
|
+
_VideoEmbed_preload.set(this, "metadata");
|
|
31
|
+
}
|
|
32
|
+
static get observedAttributes() {
|
|
33
|
+
return [
|
|
34
|
+
"url",
|
|
35
|
+
"autoplay",
|
|
36
|
+
"controls",
|
|
37
|
+
"lazy",
|
|
38
|
+
"muted",
|
|
39
|
+
"poster",
|
|
40
|
+
"background",
|
|
41
|
+
"loop",
|
|
42
|
+
"preload",
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
getComponentName() {
|
|
46
|
+
return "VideoEmbed";
|
|
47
|
+
}
|
|
48
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
49
|
+
if (this.updatingAttribute) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.log(`Attribute changed - ${name}: ${oldValue} -> ${newValue}`);
|
|
53
|
+
switch (name) {
|
|
54
|
+
case "url":
|
|
55
|
+
__classPrivateFieldSet(this, _VideoEmbed_url, newValue || "", "f");
|
|
56
|
+
if (this.initialized) {
|
|
57
|
+
this.reinitializePlayer();
|
|
58
|
+
}
|
|
59
|
+
break;
|
|
60
|
+
case "autoplay":
|
|
61
|
+
this._autoplay = newValue !== null;
|
|
62
|
+
if (!this._playing &&
|
|
63
|
+
this._autoplay &&
|
|
64
|
+
!this._lazy &&
|
|
65
|
+
this.initialized) {
|
|
66
|
+
this.play();
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
case "controls":
|
|
70
|
+
this._controls = newValue !== null;
|
|
71
|
+
if (this.video) {
|
|
72
|
+
this.video.controls = this._controls;
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
case "lazy":
|
|
76
|
+
this._lazy = newValue !== null;
|
|
77
|
+
break;
|
|
78
|
+
case "muted":
|
|
79
|
+
this._muted = newValue !== null;
|
|
80
|
+
if (this.video) {
|
|
81
|
+
this.video.muted = this._muted;
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
case "poster":
|
|
85
|
+
this._poster = newValue || "";
|
|
86
|
+
if (this._lazy && !this.video) {
|
|
87
|
+
this.showPoster();
|
|
88
|
+
}
|
|
89
|
+
else if (this.video) {
|
|
90
|
+
this.video.poster = this._poster;
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
case "background":
|
|
94
|
+
this._background = newValue !== null;
|
|
95
|
+
this.updateBackgroundMode();
|
|
96
|
+
break;
|
|
97
|
+
case "loop":
|
|
98
|
+
__classPrivateFieldSet(this, _VideoEmbed_loop, newValue !== null, "f");
|
|
99
|
+
if (this.video) {
|
|
100
|
+
this.video.loop = __classPrivateFieldGet(this, _VideoEmbed_loop, "f");
|
|
101
|
+
}
|
|
102
|
+
break;
|
|
103
|
+
case "preload":
|
|
104
|
+
const validPreloadValues = [
|
|
105
|
+
"none",
|
|
106
|
+
"metadata",
|
|
107
|
+
"auto",
|
|
108
|
+
"",
|
|
109
|
+
];
|
|
110
|
+
__classPrivateFieldSet(this, _VideoEmbed_preload, validPreloadValues.indexOf(newValue) !== -1
|
|
111
|
+
? newValue
|
|
112
|
+
: "metadata", "f");
|
|
113
|
+
if (this.video) {
|
|
114
|
+
this.video.preload = __classPrivateFieldGet(this, _VideoEmbed_preload, "f");
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Getters and setters
|
|
120
|
+
get url() {
|
|
121
|
+
return __classPrivateFieldGet(this, _VideoEmbed_url, "f");
|
|
122
|
+
}
|
|
123
|
+
set url(value) {
|
|
124
|
+
__classPrivateFieldSet(this, _VideoEmbed_url, value, "f");
|
|
125
|
+
this.reflectAttribute("url", value);
|
|
126
|
+
if (this.initialized) {
|
|
127
|
+
this.reinitializePlayer();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
get autoplay() {
|
|
131
|
+
return this._autoplay;
|
|
132
|
+
}
|
|
133
|
+
set autoplay(value) {
|
|
134
|
+
this._autoplay = value;
|
|
135
|
+
this.reflectBooleanAttribute("autoplay", value);
|
|
136
|
+
if (!this._playing && value && !this._lazy && this.initialized) {
|
|
137
|
+
this.play();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
get controls() {
|
|
141
|
+
return this._controls;
|
|
142
|
+
}
|
|
143
|
+
set controls(value) {
|
|
144
|
+
// Background mode videos must not have controls
|
|
145
|
+
if (this._background && value) {
|
|
146
|
+
this.warn("Cannot enable controls on background video");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this._controls = value;
|
|
150
|
+
this.reflectBooleanAttribute("controls", value);
|
|
151
|
+
if (this.video) {
|
|
152
|
+
this.video.controls = value;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
get lazy() {
|
|
156
|
+
return this._lazy;
|
|
157
|
+
}
|
|
158
|
+
set lazy(value) {
|
|
159
|
+
this._lazy = value;
|
|
160
|
+
this.reflectBooleanAttribute("lazy", value);
|
|
161
|
+
}
|
|
162
|
+
get muted() {
|
|
163
|
+
return this._muted;
|
|
164
|
+
}
|
|
165
|
+
set muted(value) {
|
|
166
|
+
// Background mode videos must be muted
|
|
167
|
+
if (this._background && !value) {
|
|
168
|
+
this.warn("Cannot unmute background video");
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
this._muted = value;
|
|
172
|
+
this.reflectBooleanAttribute("muted", value);
|
|
173
|
+
if (this.video) {
|
|
174
|
+
this.video.muted = value;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
get poster() {
|
|
178
|
+
return this._poster;
|
|
179
|
+
}
|
|
180
|
+
set poster(value) {
|
|
181
|
+
this._poster = value;
|
|
182
|
+
this.reflectAttribute("poster", value);
|
|
183
|
+
if (this._lazy && !this.video) {
|
|
184
|
+
this.showPoster();
|
|
185
|
+
}
|
|
186
|
+
else if (this.video) {
|
|
187
|
+
this.video.poster = value;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
get playing() {
|
|
191
|
+
return this._playing;
|
|
192
|
+
}
|
|
193
|
+
get background() {
|
|
194
|
+
return this._background;
|
|
195
|
+
}
|
|
196
|
+
set background(value) {
|
|
197
|
+
this._background = value;
|
|
198
|
+
this.reflectBooleanAttribute("background", value);
|
|
199
|
+
this.updateBackgroundMode();
|
|
200
|
+
}
|
|
201
|
+
get loop() {
|
|
202
|
+
return __classPrivateFieldGet(this, _VideoEmbed_loop, "f");
|
|
203
|
+
}
|
|
204
|
+
set loop(value) {
|
|
205
|
+
__classPrivateFieldSet(this, _VideoEmbed_loop, value, "f");
|
|
206
|
+
this.reflectBooleanAttribute("loop", value);
|
|
207
|
+
if (this.video) {
|
|
208
|
+
this.video.loop = value;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
get preload() {
|
|
212
|
+
return __classPrivateFieldGet(this, _VideoEmbed_preload, "f");
|
|
213
|
+
}
|
|
214
|
+
set preload(value) {
|
|
215
|
+
__classPrivateFieldSet(this, _VideoEmbed_preload, value, "f");
|
|
216
|
+
this.reflectAttribute("preload", value);
|
|
217
|
+
if (this.video) {
|
|
218
|
+
this.video.preload = value;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// Implement abstract methods
|
|
222
|
+
handlePlay() {
|
|
223
|
+
if (this.video) {
|
|
224
|
+
this.video.play().catch((error) => {
|
|
225
|
+
this.warn("Play failed:", error);
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
handlePause() {
|
|
230
|
+
if (this.video) {
|
|
231
|
+
this.video.pause();
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
handleRetry() {
|
|
235
|
+
if (__classPrivateFieldGet(this, _VideoEmbed_url, "f")) {
|
|
236
|
+
this.initializePlayer();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
setupFullscreenListener() {
|
|
240
|
+
const handleFullscreenChange = (event) => {
|
|
241
|
+
if (!event.isTrusted)
|
|
242
|
+
return;
|
|
243
|
+
const doc = document;
|
|
244
|
+
const fullscreenElement = doc.fullscreenElement ||
|
|
245
|
+
doc.webkitFullscreenElement ||
|
|
246
|
+
doc.mozFullScreenElement ||
|
|
247
|
+
doc.msFullscreenElement;
|
|
248
|
+
const isFullscreen = fullscreenElement === this || fullscreenElement === this.video;
|
|
249
|
+
const wasFullscreen = this.classList.contains("is-fullscreen");
|
|
250
|
+
if (isFullscreen !== wasFullscreen) {
|
|
251
|
+
this.dispatchEvent(new CustomEvent("fullscreenchange", {
|
|
252
|
+
detail: { isFullscreen },
|
|
253
|
+
bubbles: false,
|
|
254
|
+
composed: false,
|
|
255
|
+
}));
|
|
256
|
+
if (isFullscreen) {
|
|
257
|
+
this.classList.add("is-fullscreen");
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
this.classList.remove("is-fullscreen");
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
265
|
+
document.addEventListener("webkitfullscreenchange", handleFullscreenChange);
|
|
266
|
+
document.addEventListener("mozfullscreenchange", handleFullscreenChange);
|
|
267
|
+
document.addEventListener("MSFullscreenChange", handleFullscreenChange);
|
|
268
|
+
}
|
|
269
|
+
setupKeyboardHandlers() {
|
|
270
|
+
this.keyboardHandler = (e) => {
|
|
271
|
+
var _a;
|
|
272
|
+
if (!this.playerReady || ((_a = e.target) === null || _a === void 0 ? void 0 : _a.tagName) === "INPUT") {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
switch (e.key.toLowerCase()) {
|
|
276
|
+
case "k":
|
|
277
|
+
case " ":
|
|
278
|
+
e.preventDefault();
|
|
279
|
+
this.togglePlay();
|
|
280
|
+
this.announceToScreenReader(this._playing ? "Video playing" : "Video paused");
|
|
281
|
+
break;
|
|
282
|
+
case "m":
|
|
283
|
+
e.preventDefault();
|
|
284
|
+
this.toggleMute();
|
|
285
|
+
this.announceToScreenReader(this._muted ? "Video muted" : "Video unmuted");
|
|
286
|
+
break;
|
|
287
|
+
case "f":
|
|
288
|
+
e.preventDefault();
|
|
289
|
+
if (document.fullscreenElement) {
|
|
290
|
+
document.exitFullscreen().catch((error) => {
|
|
291
|
+
this.warn("Exit fullscreen failed:", error);
|
|
292
|
+
});
|
|
293
|
+
this.announceToScreenReader("Exited fullscreen");
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
this.enterFullscreen()
|
|
297
|
+
.then(() => {
|
|
298
|
+
this.announceToScreenReader("Entered fullscreen");
|
|
299
|
+
})
|
|
300
|
+
.catch((error) => {
|
|
301
|
+
this.warn("Enter fullscreen failed:", error);
|
|
302
|
+
this.announceToScreenReader("Fullscreen not available");
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
this.addEventListener("keydown", this.keyboardHandler);
|
|
309
|
+
}
|
|
310
|
+
showPoster() {
|
|
311
|
+
const posterUrl = this._poster || "";
|
|
312
|
+
this.log("Using poster URL:", posterUrl);
|
|
313
|
+
this.innerHTML = "";
|
|
314
|
+
// Create poster image if URL is provided
|
|
315
|
+
if (posterUrl) {
|
|
316
|
+
const poster = document.createElement("img");
|
|
317
|
+
poster.src = posterUrl;
|
|
318
|
+
poster.alt = "Video thumbnail";
|
|
319
|
+
poster.classList.add("video-poster");
|
|
320
|
+
poster.loading = "lazy";
|
|
321
|
+
// Add error handling for poster loading
|
|
322
|
+
poster.onerror = () => {
|
|
323
|
+
this.warn("VideoEmbed: Poster failed to load.");
|
|
324
|
+
poster.style.display = "none";
|
|
325
|
+
this.style.backgroundColor = "#000000";
|
|
326
|
+
};
|
|
327
|
+
this.appendChild(poster);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
// Create a placeholder div if no poster URL
|
|
331
|
+
const poster = document.createElement("div");
|
|
332
|
+
poster.classList.add("video-poster");
|
|
333
|
+
poster.setAttribute("role", "img");
|
|
334
|
+
poster.setAttribute("aria-label", "Video thumbnail");
|
|
335
|
+
poster.style.backgroundColor = "#000000";
|
|
336
|
+
this.appendChild(poster);
|
|
337
|
+
}
|
|
338
|
+
const buttonOverlay = document.createElement("div");
|
|
339
|
+
buttonOverlay.classList.add("button-overlay");
|
|
340
|
+
buttonOverlay.setAttribute("role", "button");
|
|
341
|
+
buttonOverlay.setAttribute("tabindex", "0");
|
|
342
|
+
buttonOverlay.setAttribute("aria-label", "Play video");
|
|
343
|
+
const button = document.createElement("div");
|
|
344
|
+
button.classList.add("button");
|
|
345
|
+
button.setAttribute("aria-hidden", "true");
|
|
346
|
+
buttonOverlay.appendChild(button);
|
|
347
|
+
const loadVideo = () => {
|
|
348
|
+
this.log("Loading video from poster click");
|
|
349
|
+
this.setAttribute("data-poster-autoplay", "true");
|
|
350
|
+
try {
|
|
351
|
+
this.initializePlayer();
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
this.error("Error initializing player from poster:", error);
|
|
355
|
+
this.dispatchCustomEvent("error", { message: "Failed to load video" });
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
this.posterClickHandler = loadVideo;
|
|
359
|
+
const keyboardActivate = (e) => {
|
|
360
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
361
|
+
e.preventDefault();
|
|
362
|
+
loadVideo(e);
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
const posterElement = this.querySelector(".video-poster");
|
|
366
|
+
if (posterElement) {
|
|
367
|
+
posterElement.addEventListener("click", loadVideo);
|
|
368
|
+
}
|
|
369
|
+
buttonOverlay.addEventListener("click", loadVideo);
|
|
370
|
+
buttonOverlay.addEventListener("keydown", keyboardActivate);
|
|
371
|
+
this.appendChild(buttonOverlay);
|
|
372
|
+
this.log("Poster displayed for lazy loading");
|
|
373
|
+
}
|
|
374
|
+
initializePlayer() {
|
|
375
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
376
|
+
this.log("Initializing player for URL:", __classPrivateFieldGet(this, _VideoEmbed_url, "f"));
|
|
377
|
+
const isBackground = this._background;
|
|
378
|
+
const autoplay = isBackground ||
|
|
379
|
+
this.hasAttribute("autoplay") ||
|
|
380
|
+
this.hasAttribute("data-poster-autoplay") ||
|
|
381
|
+
this.hasAttribute("data-should-autoplay");
|
|
382
|
+
const controls = isBackground ? false : this.hasAttribute("controls");
|
|
383
|
+
const mute = isBackground || autoplay;
|
|
384
|
+
if (this.hasAttribute("data-poster-autoplay")) {
|
|
385
|
+
this.removeAttribute("data-poster-autoplay");
|
|
386
|
+
}
|
|
387
|
+
if (this.hasAttribute("data-should-autoplay")) {
|
|
388
|
+
this.removeAttribute("data-should-autoplay");
|
|
389
|
+
}
|
|
390
|
+
if (autoplay && !this._muted) {
|
|
391
|
+
this._muted = true;
|
|
392
|
+
this.log("Autoplay enabled, forcing muted state for compliance");
|
|
393
|
+
}
|
|
394
|
+
this.innerHTML = "";
|
|
395
|
+
this.video = document.createElement("video");
|
|
396
|
+
this.video.style.objectFit = this._background ? "cover" : "contain";
|
|
397
|
+
this.video.src = __classPrivateFieldGet(this, _VideoEmbed_url, "f");
|
|
398
|
+
this.video.controls = controls;
|
|
399
|
+
this.video.autoplay = autoplay;
|
|
400
|
+
this.video.muted = mute || this._muted;
|
|
401
|
+
this.video.loop = __classPrivateFieldGet(this, _VideoEmbed_loop, "f");
|
|
402
|
+
this.video.preload = __classPrivateFieldGet(this, _VideoEmbed_preload, "f");
|
|
403
|
+
this.video.playsInline = true;
|
|
404
|
+
if (this._poster) {
|
|
405
|
+
this.video.poster = this._poster;
|
|
406
|
+
}
|
|
407
|
+
this.setupVideoEvents();
|
|
408
|
+
this.appendChild(this.video);
|
|
409
|
+
if (!controls) {
|
|
410
|
+
this.addCustomControls("video-embed-container");
|
|
411
|
+
}
|
|
412
|
+
this.playerReady = true;
|
|
413
|
+
this.dispatchCustomEvent("ready", {
|
|
414
|
+
url: __classPrivateFieldGet(this, _VideoEmbed_url, "f"),
|
|
415
|
+
muted: this._muted,
|
|
416
|
+
});
|
|
417
|
+
if (autoplay) {
|
|
418
|
+
this.video.play().catch((error) => {
|
|
419
|
+
this.warn("Autoplay failed:", error);
|
|
420
|
+
this.dispatchCustomEvent("error", {
|
|
421
|
+
message: "Autoplay failed",
|
|
422
|
+
error,
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
reinitializePlayer() {
|
|
429
|
+
if (!this.initialized || !__classPrivateFieldGet(this, _VideoEmbed_url, "f")) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
if (this.video) {
|
|
433
|
+
this.video.pause();
|
|
434
|
+
this.video.remove();
|
|
435
|
+
this.video = null;
|
|
436
|
+
}
|
|
437
|
+
this.playerReady = false;
|
|
438
|
+
this._playing = false;
|
|
439
|
+
this.classList.remove("is-playing");
|
|
440
|
+
if (this._lazy) {
|
|
441
|
+
this.showPoster();
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
this.initializePlayer();
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
destroyPlayer() {
|
|
448
|
+
if (this.video) {
|
|
449
|
+
this.video.pause();
|
|
450
|
+
this.video.src = "";
|
|
451
|
+
this.video.load();
|
|
452
|
+
this.video = null;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
setupVideoEvents() {
|
|
456
|
+
if (!this.video)
|
|
457
|
+
return;
|
|
458
|
+
this.video.addEventListener("play", () => {
|
|
459
|
+
var _a;
|
|
460
|
+
this._playing = true;
|
|
461
|
+
this.classList.add("is-playing");
|
|
462
|
+
if (this.setCustomControlState) {
|
|
463
|
+
this.setCustomControlState(true);
|
|
464
|
+
}
|
|
465
|
+
this.dispatchCustomEvent("play", {
|
|
466
|
+
url: __classPrivateFieldGet(this, _VideoEmbed_url, "f"),
|
|
467
|
+
currentTime: ((_a = this.video) === null || _a === void 0 ? void 0 : _a.currentTime) || 0,
|
|
468
|
+
});
|
|
469
|
+
});
|
|
470
|
+
this.video.addEventListener("pause", () => {
|
|
471
|
+
var _a;
|
|
472
|
+
this._playing = false;
|
|
473
|
+
this.classList.remove("is-playing");
|
|
474
|
+
if (this.setCustomControlState) {
|
|
475
|
+
this.setCustomControlState(false);
|
|
476
|
+
}
|
|
477
|
+
this.dispatchCustomEvent("pause", {
|
|
478
|
+
url: __classPrivateFieldGet(this, _VideoEmbed_url, "f"),
|
|
479
|
+
currentTime: ((_a = this.video) === null || _a === void 0 ? void 0 : _a.currentTime) || 0,
|
|
480
|
+
});
|
|
481
|
+
});
|
|
482
|
+
this.video.addEventListener("ended", () => {
|
|
483
|
+
this._playing = false;
|
|
484
|
+
this.classList.remove("is-playing");
|
|
485
|
+
if (this.setCustomControlState) {
|
|
486
|
+
this.setCustomControlState(false);
|
|
487
|
+
}
|
|
488
|
+
this.dispatchCustomEvent("ended", {
|
|
489
|
+
url: __classPrivateFieldGet(this, _VideoEmbed_url, "f"),
|
|
490
|
+
});
|
|
491
|
+
});
|
|
492
|
+
this.video.addEventListener("timeupdate", () => {
|
|
493
|
+
var _a, _b;
|
|
494
|
+
this.dispatchCustomEvent("timeupdate", {
|
|
495
|
+
url: __classPrivateFieldGet(this, _VideoEmbed_url, "f"),
|
|
496
|
+
currentTime: ((_a = this.video) === null || _a === void 0 ? void 0 : _a.currentTime) || 0,
|
|
497
|
+
duration: ((_b = this.video) === null || _b === void 0 ? void 0 : _b.duration) || 0,
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
this.video.addEventListener("volumechange", () => {
|
|
501
|
+
var _a, _b;
|
|
502
|
+
this._muted = ((_a = this.video) === null || _a === void 0 ? void 0 : _a.muted) || false;
|
|
503
|
+
this.dispatchCustomEvent("volumechange", {
|
|
504
|
+
muted: this._muted,
|
|
505
|
+
volume: ((_b = this.video) === null || _b === void 0 ? void 0 : _b.volume) || 0,
|
|
506
|
+
});
|
|
507
|
+
});
|
|
508
|
+
this.video.addEventListener("error", (e) => {
|
|
509
|
+
this.error("Video error:", e);
|
|
510
|
+
this.dispatchCustomEvent("error", {
|
|
511
|
+
message: "Video playback error",
|
|
512
|
+
error: e,
|
|
513
|
+
});
|
|
514
|
+
this.showErrorMessage("Failed to load video. Please check the URL or try again later.", "video-error-message");
|
|
515
|
+
});
|
|
516
|
+
this.video.addEventListener("loadedmetadata", () => {
|
|
517
|
+
var _a, _b, _c;
|
|
518
|
+
const width = ((_a = this.video) === null || _a === void 0 ? void 0 : _a.videoWidth) || 0;
|
|
519
|
+
const height = ((_b = this.video) === null || _b === void 0 ? void 0 : _b.videoHeight) || 0;
|
|
520
|
+
// Automatically set aspect ratio CSS custom properties
|
|
521
|
+
if (width > 0 && height > 0) {
|
|
522
|
+
this.setAspectRatio(width, height);
|
|
523
|
+
}
|
|
524
|
+
this.dispatchCustomEvent("loadedmetadata", {
|
|
525
|
+
duration: ((_c = this.video) === null || _c === void 0 ? void 0 : _c.duration) || 0,
|
|
526
|
+
videoWidth: width,
|
|
527
|
+
videoHeight: height,
|
|
528
|
+
});
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
connectedCallback() {
|
|
532
|
+
super.connectedCallback();
|
|
533
|
+
const urlAttr = this.getAttribute("url");
|
|
534
|
+
if (urlAttr) {
|
|
535
|
+
__classPrivateFieldSet(this, _VideoEmbed_url, urlAttr, "f");
|
|
536
|
+
}
|
|
537
|
+
this._autoplay = this.hasAttribute("autoplay");
|
|
538
|
+
this._controls = this.hasAttribute("controls");
|
|
539
|
+
this._lazy = this.hasAttribute("lazy");
|
|
540
|
+
this._muted = this.hasAttribute("muted");
|
|
541
|
+
this._background = this.hasAttribute("background");
|
|
542
|
+
__classPrivateFieldSet(this, _VideoEmbed_loop, this.hasAttribute("loop"), "f");
|
|
543
|
+
this._poster = this.getAttribute("poster") || "";
|
|
544
|
+
const preloadAttr = this.getAttribute("preload");
|
|
545
|
+
__classPrivateFieldSet(this, _VideoEmbed_preload, preloadAttr === "none" ||
|
|
546
|
+
preloadAttr === "metadata" ||
|
|
547
|
+
preloadAttr === "auto"
|
|
548
|
+
? preloadAttr
|
|
549
|
+
: "metadata", "f");
|
|
550
|
+
if (!__classPrivateFieldGet(this, _VideoEmbed_url, "f")) {
|
|
551
|
+
this.error("Missing video URL");
|
|
552
|
+
this.dispatchCustomEvent("error", {
|
|
553
|
+
message: "Missing video URL",
|
|
554
|
+
});
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
this.classList.add("video-embed-wrapper");
|
|
558
|
+
this.setAttribute("role", "region");
|
|
559
|
+
this.setAttribute("aria-label", "Video player");
|
|
560
|
+
if (!this.hasAttribute("tabindex")) {
|
|
561
|
+
this.setAttribute("tabindex", "0");
|
|
562
|
+
}
|
|
563
|
+
this.ariaLiveRegion = document.createElement("div");
|
|
564
|
+
this.ariaLiveRegion.setAttribute("aria-live", "polite");
|
|
565
|
+
this.ariaLiveRegion.setAttribute("aria-atomic", "true");
|
|
566
|
+
this.ariaLiveRegion.className = "sr-only";
|
|
567
|
+
this.ariaLiveRegion.style.cssText =
|
|
568
|
+
"position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden;";
|
|
569
|
+
this.appendChild(this.ariaLiveRegion);
|
|
570
|
+
this.setupKeyboardHandlers();
|
|
571
|
+
this.setupFullscreenListener();
|
|
572
|
+
this.updateBackgroundMode();
|
|
573
|
+
if (this._lazy) {
|
|
574
|
+
this.showPoster();
|
|
575
|
+
this.setupLazyLoading(() => {
|
|
576
|
+
const shouldAutoplay = this.getAttribute("data-poster-autoplay") === "true";
|
|
577
|
+
if (!shouldAutoplay) {
|
|
578
|
+
this.initializePlayer();
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
this.initializePlayer();
|
|
584
|
+
}
|
|
585
|
+
this.initialized = true;
|
|
586
|
+
}
|
|
587
|
+
disconnectedCallback() {
|
|
588
|
+
super.disconnectedCallback();
|
|
589
|
+
const poster = this.querySelector(".video-poster");
|
|
590
|
+
const buttonOverlay = this.querySelector(".button-overlay");
|
|
591
|
+
if (poster && this.posterClickHandler) {
|
|
592
|
+
poster.removeEventListener("click", this.posterClickHandler);
|
|
593
|
+
}
|
|
594
|
+
if (buttonOverlay && this.posterClickHandler) {
|
|
595
|
+
buttonOverlay.removeEventListener("click", this.posterClickHandler);
|
|
596
|
+
}
|
|
597
|
+
this.innerHTML = "";
|
|
598
|
+
this.classList.remove("video-embed-wrapper", "video-embed-container", "is-playing");
|
|
599
|
+
this.log("Cleanup complete.");
|
|
600
|
+
}
|
|
601
|
+
// Public API methods
|
|
602
|
+
play() {
|
|
603
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
604
|
+
if (this._lazy && !this.video) {
|
|
605
|
+
this.log("Lazy video needs to be loaded first. Initializing...");
|
|
606
|
+
this.setAttribute("data-should-autoplay", "true");
|
|
607
|
+
yield this.initializePlayer();
|
|
608
|
+
yield new Promise((resolve) => setTimeout(resolve, 500));
|
|
609
|
+
}
|
|
610
|
+
this.removeAttribute("data-should-autoplay");
|
|
611
|
+
if (this.video) {
|
|
612
|
+
try {
|
|
613
|
+
yield this.video.play();
|
|
614
|
+
this.log("Video playback started.");
|
|
615
|
+
}
|
|
616
|
+
catch (error) {
|
|
617
|
+
this.warn("Play failed:", error);
|
|
618
|
+
this.dispatchCustomEvent("error", {
|
|
619
|
+
message: "Failed to play video",
|
|
620
|
+
error,
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
pause() {
|
|
627
|
+
if (this.video) {
|
|
628
|
+
this.video.pause();
|
|
629
|
+
this.log("Video paused.");
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
stopVideo() {
|
|
633
|
+
if (this.video) {
|
|
634
|
+
this.video.pause();
|
|
635
|
+
this.video.currentTime = 0;
|
|
636
|
+
this.log("Video stopped.");
|
|
637
|
+
this.dispatchCustomEvent("stop", {
|
|
638
|
+
url: __classPrivateFieldGet(this, _VideoEmbed_url, "f"),
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
mute() {
|
|
643
|
+
this._muted = true;
|
|
644
|
+
this.reflectBooleanAttribute("muted", true);
|
|
645
|
+
if (this.video) {
|
|
646
|
+
this.video.muted = true;
|
|
647
|
+
}
|
|
648
|
+
this.log("Video muted.");
|
|
649
|
+
}
|
|
650
|
+
unmute() {
|
|
651
|
+
this._muted = false;
|
|
652
|
+
this.reflectBooleanAttribute("muted", false);
|
|
653
|
+
if (this.video) {
|
|
654
|
+
this.video.muted = false;
|
|
655
|
+
}
|
|
656
|
+
this.log("Video unmuted.");
|
|
657
|
+
}
|
|
658
|
+
togglePlay() {
|
|
659
|
+
if (this._playing) {
|
|
660
|
+
this.pause();
|
|
661
|
+
}
|
|
662
|
+
else {
|
|
663
|
+
this.play();
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
toggleMute() {
|
|
667
|
+
if (this._muted) {
|
|
668
|
+
this.unmute();
|
|
669
|
+
}
|
|
670
|
+
else {
|
|
671
|
+
this.mute();
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
loadVideo(url) {
|
|
675
|
+
if (url) {
|
|
676
|
+
__classPrivateFieldSet(this, _VideoEmbed_url, url, "f");
|
|
677
|
+
this.reflectAttribute("url", url);
|
|
678
|
+
}
|
|
679
|
+
if (this._lazy && !this.video) {
|
|
680
|
+
this.initializePlayer();
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
if (this.initialized) {
|
|
684
|
+
this.reinitializePlayer();
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
getPlayerState() {
|
|
688
|
+
return {
|
|
689
|
+
playing: this._playing,
|
|
690
|
+
muted: this._muted,
|
|
691
|
+
url: __classPrivateFieldGet(this, _VideoEmbed_url, "f"),
|
|
692
|
+
ready: this.playerReady,
|
|
693
|
+
initialized: this.initialized,
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
getCurrentTime() {
|
|
697
|
+
var _a;
|
|
698
|
+
return ((_a = this.video) === null || _a === void 0 ? void 0 : _a.currentTime) || 0;
|
|
699
|
+
}
|
|
700
|
+
getDuration() {
|
|
701
|
+
var _a;
|
|
702
|
+
return ((_a = this.video) === null || _a === void 0 ? void 0 : _a.duration) || 0;
|
|
703
|
+
}
|
|
704
|
+
setCurrentTime(time) {
|
|
705
|
+
if (this.video) {
|
|
706
|
+
this.video.currentTime = time;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
setVolume(volume) {
|
|
710
|
+
if (this.video) {
|
|
711
|
+
this.video.volume = Math.max(0, Math.min(1, volume));
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
getVolume() {
|
|
715
|
+
var _a;
|
|
716
|
+
return ((_a = this.video) === null || _a === void 0 ? void 0 : _a.volume) || 0;
|
|
717
|
+
}
|
|
718
|
+
isPlaying() {
|
|
719
|
+
return this._playing;
|
|
720
|
+
}
|
|
721
|
+
isMuted() {
|
|
722
|
+
return this._muted;
|
|
723
|
+
}
|
|
724
|
+
enterFullscreen() {
|
|
725
|
+
const elem = (this.video || this);
|
|
726
|
+
if (elem.requestFullscreen) {
|
|
727
|
+
return elem.requestFullscreen();
|
|
728
|
+
}
|
|
729
|
+
else if (elem.webkitRequestFullscreen) {
|
|
730
|
+
return elem.webkitRequestFullscreen();
|
|
731
|
+
}
|
|
732
|
+
else if (elem.mozRequestFullScreen) {
|
|
733
|
+
return elem.mozRequestFullScreen();
|
|
734
|
+
}
|
|
735
|
+
else if (elem.msRequestFullscreen) {
|
|
736
|
+
return elem.msRequestFullscreen();
|
|
737
|
+
}
|
|
738
|
+
return Promise.reject(new Error("Fullscreen API not supported"));
|
|
739
|
+
}
|
|
740
|
+
exitFullscreen() {
|
|
741
|
+
const doc = document;
|
|
742
|
+
if (doc.exitFullscreen) {
|
|
743
|
+
return doc.exitFullscreen();
|
|
744
|
+
}
|
|
745
|
+
else if (doc.webkitExitFullscreen) {
|
|
746
|
+
return doc.webkitExitFullscreen();
|
|
747
|
+
}
|
|
748
|
+
else if (doc.mozCancelFullScreen) {
|
|
749
|
+
return doc.mozCancelFullScreen();
|
|
750
|
+
}
|
|
751
|
+
else if (doc.msExitFullscreen) {
|
|
752
|
+
return doc.msExitFullscreen();
|
|
753
|
+
}
|
|
754
|
+
return Promise.reject(new Error("Fullscreen API not supported"));
|
|
755
|
+
}
|
|
756
|
+
toggleFullscreen() {
|
|
757
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
758
|
+
try {
|
|
759
|
+
if (this.isFullscreen()) {
|
|
760
|
+
yield this.exitFullscreen();
|
|
761
|
+
}
|
|
762
|
+
else {
|
|
763
|
+
yield this.enterFullscreen();
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
catch (error) {
|
|
767
|
+
this.warn("Toggle fullscreen failed:", error);
|
|
768
|
+
throw error;
|
|
769
|
+
}
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
isFullscreen() {
|
|
773
|
+
const doc = document;
|
|
774
|
+
const fullscreenElement = doc.fullscreenElement ||
|
|
775
|
+
doc.webkitFullscreenElement ||
|
|
776
|
+
doc.mozFullScreenElement ||
|
|
777
|
+
doc.msFullscreenElement;
|
|
778
|
+
return fullscreenElement === this || fullscreenElement === this.video;
|
|
779
|
+
}
|
|
780
|
+
static toggleDebug(forceState) {
|
|
781
|
+
BaseVideoEmbed.toggleDebug(forceState);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
_VideoEmbed_url = new WeakMap(), _VideoEmbed_loop = new WeakMap(), _VideoEmbed_preload = new WeakMap();
|
|
785
|
+
customElements.define("video-embed", VideoEmbed);
|
|
786
|
+
//# sourceMappingURL=VideoEmbed.js.map
|