@smartimpact-it/modern-video-embed 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 (51) hide show
  1. package/README.md +1205 -0
  2. package/dist/components/VimeoEmbed.d.ts +143 -0
  3. package/dist/components/VimeoEmbed.d.ts.map +1 -0
  4. package/dist/components/VimeoEmbed.js +1176 -0
  5. package/dist/components/VimeoEmbed.js.map +1 -0
  6. package/dist/components/VimeoEmbed.min.js +1 -0
  7. package/dist/components/YouTubeEmbed.d.ts +225 -0
  8. package/dist/components/YouTubeEmbed.d.ts.map +1 -0
  9. package/dist/components/YouTubeEmbed.js +1354 -0
  10. package/dist/components/YouTubeEmbed.js.map +1 -0
  11. package/dist/components/YouTubeEmbed.min.js +1 -0
  12. package/dist/css/components.css +349 -0
  13. package/dist/css/components.css.map +1 -0
  14. package/dist/css/components.min.css +1 -0
  15. package/dist/css/main.css +12210 -0
  16. package/dist/css/main.css.map +1 -0
  17. package/dist/css/main.min.css +7 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +4 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/index.min.js +1 -0
  23. package/dist/types/index.d.ts +7 -0
  24. package/dist/types/index.d.ts.map +1 -0
  25. package/dist/types/index.js +5 -0
  26. package/dist/types/index.js.map +1 -0
  27. package/dist/vimeo-only.d.ts +7 -0
  28. package/dist/vimeo-only.d.ts.map +1 -0
  29. package/dist/vimeo-only.js +8 -0
  30. package/dist/vimeo-only.js.map +1 -0
  31. package/dist/vimeo-only.min.js +1 -0
  32. package/dist/youtube-only.d.ts +7 -0
  33. package/dist/youtube-only.d.ts.map +1 -0
  34. package/dist/youtube-only.js +8 -0
  35. package/dist/youtube-only.js.map +1 -0
  36. package/dist/youtube-only.min.js +1 -0
  37. package/package.json +75 -0
  38. package/src/components/VimeoEmbed.ts +1340 -0
  39. package/src/components/YouTubeEmbed.ts +1568 -0
  40. package/src/index.ts +3 -0
  41. package/src/styles/README.md +56 -0
  42. package/src/styles/components.scss +7 -0
  43. package/src/styles/main.scss +10 -0
  44. package/src/styles/vimeo-embed.scss +255 -0
  45. package/src/styles/youtube-embed.scss +261 -0
  46. package/src/types/common.d.ts +198 -0
  47. package/src/types/index.ts +7 -0
  48. package/src/types/vimeo-embed.d.ts +80 -0
  49. package/src/types/youtube-embed.d.ts +83 -0
  50. package/src/vimeo-only.ts +9 -0
  51. package/src/youtube-only.ts +9 -0
@@ -0,0 +1,1176 @@
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 _VimeoEmbed_instances, _VimeoEmbed_url, _VimeoEmbed_videoId, _VimeoEmbed_autoplay, _VimeoEmbed_muted, _VimeoEmbed_controls, _VimeoEmbed_lazy, _VimeoEmbed_poster, _VimeoEmbed_playing, _VimeoEmbed_background, _VimeoEmbed_playerVars, _VimeoEmbed_reflectBooleanAttribute, _VimeoEmbed_updateBackgroundMode;
22
+ export class VimeoEmbed extends HTMLElement {
23
+ constructor() {
24
+ super(...arguments);
25
+ _VimeoEmbed_instances.add(this);
26
+ this.iframe = null;
27
+ this.player = null; // Vimeo Player instance
28
+ this.playerReady = false;
29
+ this.playPauseButton = null;
30
+ this.initialized = false;
31
+ this.setCustomControlState = null;
32
+ this.updatingAttribute = false;
33
+ this.updatingMutedState = false; // Flag to prevent sync from overwriting programmatic mute changes
34
+ /** The full Vimeo URL (e.g., "https://vimeo.com/...") */
35
+ _VimeoEmbed_url.set(this, "");
36
+ /** The Vimeo video ID (numeric). */
37
+ _VimeoEmbed_videoId.set(this, "");
38
+ /** Whether the video should autoplay when loaded. Requires `muted` to be true. */
39
+ _VimeoEmbed_autoplay.set(this, false);
40
+ /** Whether the video audio is muted. */
41
+ _VimeoEmbed_muted.set(this, false);
42
+ /** Whether to show the native Vimeo player controls. */
43
+ _VimeoEmbed_controls.set(this, false);
44
+ /** Whether to lazy-load the video, showing a poster image until interaction. */
45
+ _VimeoEmbed_lazy.set(this, false);
46
+ /** URL for a custom poster image. Defaults to Vimeo's thumbnail. */
47
+ _VimeoEmbed_poster.set(this, "");
48
+ /** Read-only property to check if the video is currently playing. */
49
+ _VimeoEmbed_playing.set(this, false);
50
+ /** Whether the video should act as a background, covering its container. */
51
+ _VimeoEmbed_background.set(this, false);
52
+ /** Extra parameters to pass to the Vimeo player. */
53
+ _VimeoEmbed_playerVars.set(this, {});
54
+ this.posterClickHandler = null;
55
+ this.keyboardHandler = null;
56
+ this.ariaLiveRegion = null;
57
+ this.apiLoadRetries = 0;
58
+ this.intersectionObserver = null;
59
+ this.hasLoadedVideo = false;
60
+ }
61
+ static get observedAttributes() {
62
+ return [
63
+ "url",
64
+ "video-id",
65
+ "autoplay",
66
+ "controls",
67
+ "lazy",
68
+ "muted",
69
+ "poster",
70
+ "background",
71
+ "player-vars",
72
+ "quality",
73
+ ];
74
+ }
75
+ attributeChangedCallback(name, oldValue, newValue) {
76
+ if (this.updatingAttribute) {
77
+ return;
78
+ }
79
+ this.log(`VimeoEmbed: Attribute changed - ${name}: ${oldValue} -> ${newValue}`);
80
+ switch (name) {
81
+ case "url":
82
+ __classPrivateFieldSet(this, _VimeoEmbed_url, newValue || "", "f");
83
+ __classPrivateFieldSet(this, _VimeoEmbed_videoId, this.extractVideoId(__classPrivateFieldGet(this, _VimeoEmbed_url, "f")), "f");
84
+ if (this.initialized) {
85
+ this.reinitializePlayer();
86
+ }
87
+ break;
88
+ case "video-id":
89
+ __classPrivateFieldSet(this, _VimeoEmbed_videoId, newValue || "", "f");
90
+ if (this.initialized) {
91
+ this.reinitializePlayer();
92
+ }
93
+ break;
94
+ case "autoplay":
95
+ __classPrivateFieldSet(this, _VimeoEmbed_autoplay, newValue !== null, "f");
96
+ if (!__classPrivateFieldGet(this, _VimeoEmbed_playing, "f") &&
97
+ __classPrivateFieldGet(this, _VimeoEmbed_autoplay, "f") &&
98
+ !__classPrivateFieldGet(this, _VimeoEmbed_lazy, "f") &&
99
+ this.initialized) {
100
+ this.play();
101
+ }
102
+ break;
103
+ case "controls":
104
+ __classPrivateFieldSet(this, _VimeoEmbed_controls, newValue !== null, "f");
105
+ if (this.initialized) {
106
+ this.reinitializePlayer();
107
+ }
108
+ break;
109
+ case "lazy":
110
+ __classPrivateFieldSet(this, _VimeoEmbed_lazy, newValue !== null, "f");
111
+ break;
112
+ case "muted":
113
+ __classPrivateFieldSet(this, _VimeoEmbed_muted, newValue !== null, "f");
114
+ if (this.player && this.playerReady) {
115
+ this.player.setVolume(__classPrivateFieldGet(this, _VimeoEmbed_muted, "f") ? 0 : 1);
116
+ }
117
+ break;
118
+ case "poster":
119
+ __classPrivateFieldSet(this, _VimeoEmbed_poster, newValue || "", "f");
120
+ if (__classPrivateFieldGet(this, _VimeoEmbed_lazy, "f") && !this.player) {
121
+ this.showPoster(__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f"));
122
+ }
123
+ break;
124
+ case "background":
125
+ __classPrivateFieldSet(this, _VimeoEmbed_background, newValue !== null, "f");
126
+ __classPrivateFieldGet(this, _VimeoEmbed_instances, "m", _VimeoEmbed_updateBackgroundMode).call(this);
127
+ break;
128
+ case "player-vars":
129
+ try {
130
+ __classPrivateFieldSet(this, _VimeoEmbed_playerVars, newValue ? JSON.parse(newValue) : {}, "f");
131
+ }
132
+ catch (e) {
133
+ this.error("VimeoEmbed: Invalid player-vars JSON:", e);
134
+ __classPrivateFieldSet(this, _VimeoEmbed_playerVars, {}, "f");
135
+ }
136
+ if (this.initialized) {
137
+ this.reinitializePlayer();
138
+ }
139
+ break;
140
+ case "quality":
141
+ if (newValue && this.player && this.playerReady) {
142
+ this.setQuality(newValue);
143
+ }
144
+ break;
145
+ }
146
+ }
147
+ // Getters and setters for attributes
148
+ get url() {
149
+ return __classPrivateFieldGet(this, _VimeoEmbed_url, "f");
150
+ }
151
+ set url(value) {
152
+ __classPrivateFieldSet(this, _VimeoEmbed_url, value, "f");
153
+ __classPrivateFieldSet(this, _VimeoEmbed_videoId, this.extractVideoId(value), "f");
154
+ if (this.initialized) {
155
+ this.reinitializePlayer();
156
+ }
157
+ }
158
+ get videoId() {
159
+ return __classPrivateFieldGet(this, _VimeoEmbed_videoId, "f");
160
+ }
161
+ set videoId(value) {
162
+ __classPrivateFieldSet(this, _VimeoEmbed_videoId, value, "f");
163
+ if (this.initialized) {
164
+ this.reinitializePlayer();
165
+ }
166
+ }
167
+ get autoplay() {
168
+ return __classPrivateFieldGet(this, _VimeoEmbed_autoplay, "f");
169
+ }
170
+ set autoplay(value) {
171
+ __classPrivateFieldSet(this, _VimeoEmbed_autoplay, value, "f");
172
+ __classPrivateFieldGet(this, _VimeoEmbed_instances, "m", _VimeoEmbed_reflectBooleanAttribute).call(this, "autoplay", value);
173
+ if (!__classPrivateFieldGet(this, _VimeoEmbed_playing, "f") && value && !__classPrivateFieldGet(this, _VimeoEmbed_lazy, "f") && this.initialized) {
174
+ this.play();
175
+ }
176
+ }
177
+ get controls() {
178
+ return __classPrivateFieldGet(this, _VimeoEmbed_controls, "f");
179
+ }
180
+ set controls(value) {
181
+ __classPrivateFieldSet(this, _VimeoEmbed_controls, value, "f");
182
+ __classPrivateFieldGet(this, _VimeoEmbed_instances, "m", _VimeoEmbed_reflectBooleanAttribute).call(this, "controls", value);
183
+ if (this.initialized) {
184
+ this.reinitializePlayer();
185
+ }
186
+ }
187
+ get lazy() {
188
+ return __classPrivateFieldGet(this, _VimeoEmbed_lazy, "f");
189
+ }
190
+ set lazy(value) {
191
+ __classPrivateFieldSet(this, _VimeoEmbed_lazy, value, "f");
192
+ __classPrivateFieldGet(this, _VimeoEmbed_instances, "m", _VimeoEmbed_reflectBooleanAttribute).call(this, "lazy", value);
193
+ }
194
+ get muted() {
195
+ return __classPrivateFieldGet(this, _VimeoEmbed_muted, "f");
196
+ }
197
+ set muted(value) {
198
+ __classPrivateFieldSet(this, _VimeoEmbed_muted, value, "f");
199
+ __classPrivateFieldGet(this, _VimeoEmbed_instances, "m", _VimeoEmbed_reflectBooleanAttribute).call(this, "muted", value);
200
+ if (this.player && this.playerReady) {
201
+ this.updatingMutedState = true;
202
+ this.player.setVolume(value ? 0 : 1);
203
+ // Reset flag after a short delay to allow Vimeo API to process
204
+ setTimeout(() => {
205
+ this.updatingMutedState = false;
206
+ }, 100);
207
+ }
208
+ }
209
+ get poster() {
210
+ return __classPrivateFieldGet(this, _VimeoEmbed_poster, "f");
211
+ }
212
+ set poster(value) {
213
+ __classPrivateFieldSet(this, _VimeoEmbed_poster, value, "f");
214
+ this.updatingAttribute = true;
215
+ if (value) {
216
+ this.setAttribute("poster", value);
217
+ }
218
+ else {
219
+ this.removeAttribute("poster");
220
+ }
221
+ this.updatingAttribute = false;
222
+ if (__classPrivateFieldGet(this, _VimeoEmbed_lazy, "f") && !this.player) {
223
+ this.showPoster(__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f"));
224
+ }
225
+ }
226
+ get playing() {
227
+ return __classPrivateFieldGet(this, _VimeoEmbed_playing, "f");
228
+ }
229
+ get background() {
230
+ return __classPrivateFieldGet(this, _VimeoEmbed_background, "f");
231
+ }
232
+ set background(value) {
233
+ __classPrivateFieldSet(this, _VimeoEmbed_background, value, "f");
234
+ __classPrivateFieldGet(this, _VimeoEmbed_instances, "m", _VimeoEmbed_reflectBooleanAttribute).call(this, "background", value);
235
+ __classPrivateFieldGet(this, _VimeoEmbed_instances, "m", _VimeoEmbed_updateBackgroundMode).call(this);
236
+ }
237
+ get playerVars() {
238
+ return __classPrivateFieldGet(this, _VimeoEmbed_playerVars, "f");
239
+ }
240
+ set playerVars(vars) {
241
+ __classPrivateFieldSet(this, _VimeoEmbed_playerVars, vars, "f");
242
+ this.setAttribute("player-vars", JSON.stringify(vars));
243
+ if (this.initialized) {
244
+ this.reinitializePlayer();
245
+ }
246
+ }
247
+ extractVideoId(url) {
248
+ if (!url)
249
+ return "";
250
+ // Handle various Vimeo URL formats
251
+ // https://vimeo.com/123456789
252
+ // https://player.vimeo.com/video/123456789
253
+ const regex = /(?:vimeo\.com\/(?:video\/)?|player\.vimeo\.com\/video\/)(\d+)/;
254
+ const match = url.match(regex);
255
+ if (match && match[1]) {
256
+ return match[1];
257
+ }
258
+ // If it's already just an ID (numeric)
259
+ if (/^\d+$/.test(url)) {
260
+ return url;
261
+ }
262
+ this.warn(`VimeoEmbed: Could not extract video ID from "${url}"`);
263
+ return "";
264
+ }
265
+ log(...args) {
266
+ if (VimeoEmbed.DEBUG) {
267
+ console.log("VimeoEmbed:", ...args);
268
+ }
269
+ }
270
+ warn(...args) {
271
+ console.warn(...args);
272
+ }
273
+ error(...args) {
274
+ console.error(...args);
275
+ }
276
+ dispatchCustomEvent(eventName, detail) {
277
+ this.dispatchEvent(new CustomEvent(eventName, {
278
+ detail,
279
+ bubbles: true,
280
+ composed: true,
281
+ }));
282
+ }
283
+ isValidPosterUrl(url) {
284
+ if (!url)
285
+ return false;
286
+ try {
287
+ new URL(url);
288
+ return true;
289
+ }
290
+ catch (_a) {
291
+ return false;
292
+ }
293
+ }
294
+ /**
295
+ * Setup fullscreen change event listener
296
+ */
297
+ setupFullscreenListener() {
298
+ const handleFullscreenChange = () => {
299
+ const isFullscreen = this.isFullscreen();
300
+ this.dispatchCustomEvent("fullscreenchange", { isFullscreen });
301
+ if (isFullscreen) {
302
+ this.classList.add("is-fullscreen");
303
+ }
304
+ else {
305
+ this.classList.remove("is-fullscreen");
306
+ }
307
+ };
308
+ document.addEventListener("fullscreenchange", handleFullscreenChange);
309
+ document.addEventListener("webkitfullscreenchange", handleFullscreenChange);
310
+ document.addEventListener("mozfullscreenchange", handleFullscreenChange);
311
+ document.addEventListener("MSFullscreenChange", handleFullscreenChange);
312
+ }
313
+ /**
314
+ * Setup keyboard event handlers for accessibility
315
+ */
316
+ setupKeyboardHandlers() {
317
+ this.keyboardHandler = (e) => {
318
+ var _a, _b;
319
+ // Only handle if player is ready and not in input element
320
+ if (!this.playerReady || ((_a = e.target) === null || _a === void 0 ? void 0 : _a.tagName) === "INPUT") {
321
+ return;
322
+ }
323
+ switch (e.key.toLowerCase()) {
324
+ case "k":
325
+ case " ":
326
+ // Play/Pause
327
+ e.preventDefault();
328
+ this.togglePlay();
329
+ this.announceToScreenReader(__classPrivateFieldGet(this, _VimeoEmbed_playing, "f") ? "Video playing" : "Video paused");
330
+ break;
331
+ case "m":
332
+ // Mute/Unmute
333
+ e.preventDefault();
334
+ this.toggleMute();
335
+ (_b = this.player) === null || _b === void 0 ? void 0 : _b.getMuted().then((muted) => {
336
+ this.announceToScreenReader(muted ? "Video muted" : "Video unmuted");
337
+ });
338
+ break;
339
+ case "f":
340
+ // Fullscreen toggle
341
+ e.preventDefault();
342
+ if (document.fullscreenElement) {
343
+ document.exitFullscreen();
344
+ this.announceToScreenReader("Exited fullscreen");
345
+ }
346
+ else if (this.enterFullscreen) {
347
+ this.enterFullscreen();
348
+ this.announceToScreenReader("Entered fullscreen");
349
+ }
350
+ break;
351
+ }
352
+ };
353
+ this.addEventListener("keydown", this.keyboardHandler);
354
+ }
355
+ /**
356
+ * Announce message to screen readers
357
+ */
358
+ announceToScreenReader(message) {
359
+ if (this.ariaLiveRegion) {
360
+ this.ariaLiveRegion.textContent = message;
361
+ // Clear after a brief delay
362
+ setTimeout(() => {
363
+ if (this.ariaLiveRegion) {
364
+ this.ariaLiveRegion.textContent = "";
365
+ }
366
+ }, 1000);
367
+ }
368
+ }
369
+ /**
370
+ * Add preconnect and dns-prefetch hints for Vimeo domains
371
+ */
372
+ addResourceHints() {
373
+ const hints = [
374
+ { rel: "preconnect", href: "https://player.vimeo.com" },
375
+ { rel: "preconnect", href: "https://i.vimeocdn.com" },
376
+ { rel: "dns-prefetch", href: "https://player.vimeo.com" },
377
+ { rel: "dns-prefetch", href: "https://i.vimeocdn.com" },
378
+ ];
379
+ hints.forEach(({ rel, href }) => {
380
+ if (!document.querySelector(`link[rel="${rel}"][href="${href}"]`)) {
381
+ const link = document.createElement("link");
382
+ link.rel = rel;
383
+ link.href = href;
384
+ if (rel === "preconnect") {
385
+ link.crossOrigin = "anonymous";
386
+ }
387
+ document.head.appendChild(link);
388
+ }
389
+ });
390
+ }
391
+ /**
392
+ * Setup Intersection Observer for lazy loading
393
+ */
394
+ setupIntersectionObserver() {
395
+ if (!("IntersectionObserver" in window)) {
396
+ // Fallback: load immediately if IntersectionObserver not supported
397
+ return;
398
+ }
399
+ const options = {
400
+ root: null,
401
+ rootMargin: "50px", // Start loading 50px before entering viewport
402
+ threshold: 0.01,
403
+ };
404
+ this.intersectionObserver = new IntersectionObserver((entries) => {
405
+ entries.forEach((entry) => {
406
+ if (entry.isIntersecting && !this.hasLoadedVideo) {
407
+ this.hasLoadedVideo = true;
408
+ this.log("VimeoEmbed: Video entering viewport, loading...");
409
+ // Check if poster was clicked before intersection
410
+ const shouldAutoplay = this.getAttribute("data-poster-autoplay") === "true";
411
+ if (!shouldAutoplay) {
412
+ // Just load the player, don't autoplay
413
+ this.initializePlayer(__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f"));
414
+ }
415
+ // Disconnect observer after loading
416
+ if (this.intersectionObserver) {
417
+ this.intersectionObserver.disconnect();
418
+ }
419
+ }
420
+ });
421
+ }, options);
422
+ this.intersectionObserver.observe(this);
423
+ }
424
+ /**
425
+ * Display error message to user with retry option
426
+ */
427
+ showErrorMessage(message) {
428
+ const errorDiv = document.createElement("div");
429
+ errorDiv.className = "vimeo-error-message";
430
+ errorDiv.setAttribute("role", "alert");
431
+ errorDiv.innerHTML = `
432
+ <div class="error-content">
433
+ <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
434
+ <circle cx="12" cy="12" r="10"></circle>
435
+ <line x1="12" y1="8" x2="12" y2="12"></line>
436
+ <line x1="12" y1="16" x2="12.01" y2="16"></line>
437
+ </svg>
438
+ <p class="error-message">${message}</p>
439
+ <button class="retry-button">Retry</button>
440
+ </div>
441
+ `;
442
+ const retryButton = errorDiv.querySelector(".retry-button");
443
+ if (retryButton) {
444
+ retryButton.addEventListener("click", () => {
445
+ this.apiLoadRetries = 0;
446
+ errorDiv.remove();
447
+ if (__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f")) {
448
+ this.initializePlayer(__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f"));
449
+ }
450
+ });
451
+ }
452
+ // Clear existing content
453
+ this.innerHTML = "";
454
+ this.appendChild(errorDiv);
455
+ }
456
+ connectedCallback() {
457
+ VimeoEmbed.instanceCount++;
458
+ this.log("VimeoEmbed: connectedCallback called, instance count:", VimeoEmbed.instanceCount);
459
+ // Add resource hints on first instance
460
+ if (VimeoEmbed.instanceCount === 1) {
461
+ this.addResourceHints();
462
+ }
463
+ const urlAttr = this.getAttribute("url");
464
+ const videoIdAttr = this.getAttribute("video-id");
465
+ if (urlAttr) {
466
+ __classPrivateFieldSet(this, _VimeoEmbed_url, urlAttr, "f");
467
+ __classPrivateFieldSet(this, _VimeoEmbed_videoId, this.extractVideoId(urlAttr), "f");
468
+ }
469
+ else if (videoIdAttr) {
470
+ __classPrivateFieldSet(this, _VimeoEmbed_videoId, videoIdAttr, "f");
471
+ }
472
+ __classPrivateFieldSet(this, _VimeoEmbed_autoplay, this.hasAttribute("autoplay"), "f");
473
+ __classPrivateFieldSet(this, _VimeoEmbed_controls, this.hasAttribute("controls"), "f");
474
+ __classPrivateFieldSet(this, _VimeoEmbed_lazy, this.hasAttribute("lazy"), "f");
475
+ __classPrivateFieldSet(this, _VimeoEmbed_muted, this.hasAttribute("muted"), "f");
476
+ __classPrivateFieldSet(this, _VimeoEmbed_background, this.hasAttribute("background"), "f");
477
+ __classPrivateFieldSet(this, _VimeoEmbed_poster, this.getAttribute("poster") || "", "f");
478
+ try {
479
+ const playerVarsAttr = this.getAttribute("player-vars");
480
+ __classPrivateFieldSet(this, _VimeoEmbed_playerVars, playerVarsAttr ? JSON.parse(playerVarsAttr) : {}, "f");
481
+ }
482
+ catch (e) {
483
+ this.error("VimeoEmbed: Invalid player-vars JSON on init:", e);
484
+ __classPrivateFieldSet(this, _VimeoEmbed_playerVars, {}, "f");
485
+ }
486
+ if (!__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f")) {
487
+ this.error("VimeoEmbed: Missing or invalid video ID");
488
+ this.dispatchCustomEvent("error", {
489
+ message: "Missing or invalid video ID",
490
+ });
491
+ return;
492
+ }
493
+ this.classList.add("vimeo-embed-wrapper");
494
+ // Add ARIA role and tabindex for accessibility
495
+ this.setAttribute("role", "region");
496
+ this.setAttribute("aria-label", "Video player");
497
+ if (!this.hasAttribute("tabindex")) {
498
+ this.setAttribute("tabindex", "0");
499
+ }
500
+ // Create ARIA live region for screen reader announcements
501
+ this.ariaLiveRegion = document.createElement("div");
502
+ this.ariaLiveRegion.setAttribute("aria-live", "polite");
503
+ this.ariaLiveRegion.setAttribute("aria-atomic", "true");
504
+ this.ariaLiveRegion.className = "sr-only";
505
+ this.ariaLiveRegion.style.cssText =
506
+ "position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden;";
507
+ this.appendChild(this.ariaLiveRegion);
508
+ // Setup keyboard event handlers
509
+ this.setupKeyboardHandlers();
510
+ // Setup fullscreen change listener
511
+ this.setupFullscreenListener();
512
+ __classPrivateFieldGet(this, _VimeoEmbed_instances, "m", _VimeoEmbed_updateBackgroundMode).call(this);
513
+ if (__classPrivateFieldGet(this, _VimeoEmbed_lazy, "f")) {
514
+ this.showPoster(__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f"));
515
+ // Setup Intersection Observer for better performance
516
+ this.setupIntersectionObserver();
517
+ }
518
+ else {
519
+ this.initializePlayer(__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f"));
520
+ }
521
+ this.initialized = true;
522
+ this.dispatchCustomEvent("connected");
523
+ }
524
+ disconnectedCallback() {
525
+ VimeoEmbed.instanceCount--;
526
+ this.log("VimeoEmbed: disconnectedCallback called, remaining instances:", VimeoEmbed.instanceCount);
527
+ if (this.player) {
528
+ try {
529
+ this.player.destroy();
530
+ this.log("VimeoEmbed: Player destroyed.");
531
+ }
532
+ catch (error) {
533
+ this.warn("VimeoEmbed: Error destroying player:", error);
534
+ }
535
+ this.player = null;
536
+ }
537
+ // Remove keyboard event handlers
538
+ if (this.keyboardHandler) {
539
+ this.removeEventListener("keydown", this.keyboardHandler);
540
+ this.keyboardHandler = null;
541
+ }
542
+ const poster = this.querySelector(".vimeo-poster");
543
+ const buttonOverlay = this.querySelector(".button-overlay");
544
+ if (poster && this.posterClickHandler) {
545
+ poster.removeEventListener("click", this.posterClickHandler);
546
+ this.posterClickHandler = null;
547
+ }
548
+ if (buttonOverlay && this.posterClickHandler) {
549
+ buttonOverlay.removeEventListener("click", this.posterClickHandler);
550
+ }
551
+ this.innerHTML = "";
552
+ this.classList.remove("vimeo-embed-wrapper", "vimeo-embed-container", "is-playing");
553
+ if (VimeoEmbed.instanceCount === 0) {
554
+ this.log("VimeoEmbed: Last instance, cleaning up global resources");
555
+ const script = document.querySelector('script[src="https://player.vimeo.com/api/player.js"]');
556
+ if (script) {
557
+ script.remove();
558
+ this.log("VimeoEmbed: Vimeo API script removed.");
559
+ }
560
+ VimeoEmbed.apiLoaded = false;
561
+ VimeoEmbed.apiReady = false;
562
+ }
563
+ this.iframe = null;
564
+ this.playPauseButton = null;
565
+ this.setCustomControlState = null;
566
+ this.dispatchCustomEvent("disconnected");
567
+ this.log("VimeoEmbed: Cleanup complete.");
568
+ }
569
+ reinitializePlayer() {
570
+ if (!this.initialized || !__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f")) {
571
+ return;
572
+ }
573
+ if (this.player) {
574
+ try {
575
+ this.player.destroy();
576
+ }
577
+ catch (error) {
578
+ this.warn("VimeoEmbed: Error destroying player:", error);
579
+ }
580
+ }
581
+ if (__classPrivateFieldGet(this, _VimeoEmbed_lazy, "f")) {
582
+ this.showPoster(__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f"));
583
+ }
584
+ else {
585
+ this.initializePlayer(__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f"));
586
+ }
587
+ }
588
+ showPoster(videoId) {
589
+ return __awaiter(this, void 0, void 0, function* () {
590
+ var _a;
591
+ let thumbnailUrl = __classPrivateFieldGet(this, _VimeoEmbed_poster, "f");
592
+ // Fetch Vimeo thumbnail if no custom poster
593
+ if (!this.isValidPosterUrl(__classPrivateFieldGet(this, _VimeoEmbed_poster, "f"))) {
594
+ try {
595
+ const response = yield fetch(`https://vimeo.com/api/v2/video/${videoId}.json`);
596
+ const data = yield response.json();
597
+ thumbnailUrl = ((_a = data[0]) === null || _a === void 0 ? void 0 : _a.thumbnail_large) || "";
598
+ }
599
+ catch (error) {
600
+ this.warn("VimeoEmbed: Could not fetch Vimeo thumbnail:", error);
601
+ thumbnailUrl = "";
602
+ }
603
+ }
604
+ this.log("VimeoEmbed: Using poster URL:", thumbnailUrl);
605
+ this.innerHTML = "";
606
+ if (this.posterClickHandler) {
607
+ this.posterClickHandler = null;
608
+ }
609
+ const poster = document.createElement("img");
610
+ poster.src = thumbnailUrl || "";
611
+ poster.alt = "Vimeo Video Thumbnail";
612
+ poster.classList.add("vimeo-poster", "video-poster");
613
+ poster.loading = "lazy";
614
+ poster.onerror = () => {
615
+ this.warn("VimeoEmbed: Poster failed to load, using white background.");
616
+ poster.style.display = "none";
617
+ this.style.backgroundColor = "#FFFFFF";
618
+ };
619
+ const buttonOverlay = document.createElement("div");
620
+ buttonOverlay.classList.add("button-overlay");
621
+ buttonOverlay.setAttribute("role", "button");
622
+ buttonOverlay.setAttribute("tabindex", "0");
623
+ buttonOverlay.setAttribute("aria-label", "Play video");
624
+ const button = document.createElement("div");
625
+ button.classList.add("button");
626
+ button.setAttribute("aria-hidden", "true");
627
+ buttonOverlay.appendChild(button);
628
+ const loadVideo = () => {
629
+ this.log("VimeoEmbed: Loading video from poster click");
630
+ this.setAttribute("data-poster-autoplay", "true");
631
+ try {
632
+ this.initializePlayer(videoId);
633
+ }
634
+ catch (error) {
635
+ this.error("VimeoEmbed: Error initializing player from poster:", error);
636
+ this.dispatchCustomEvent("error", { message: "Failed to load video" });
637
+ }
638
+ };
639
+ this.posterClickHandler = loadVideo;
640
+ // Add keyboard support
641
+ const keyboardActivate = (e) => {
642
+ if (e.key === "Enter" || e.key === " ") {
643
+ e.preventDefault();
644
+ loadVideo(e);
645
+ }
646
+ };
647
+ poster.addEventListener("click", loadVideo);
648
+ buttonOverlay.addEventListener("click", loadVideo);
649
+ buttonOverlay.addEventListener("keydown", keyboardActivate);
650
+ this.appendChild(poster);
651
+ this.appendChild(buttonOverlay);
652
+ this.log("VimeoEmbed: Poster displayed for lazy loading");
653
+ });
654
+ }
655
+ initializePlayer(videoId) {
656
+ return __awaiter(this, void 0, void 0, function* () {
657
+ this.log("VimeoEmbed: Initializing player for video ID:", videoId);
658
+ const isBackground = __classPrivateFieldGet(this, _VimeoEmbed_background, "f");
659
+ const autoplay = isBackground ||
660
+ this.hasAttribute("autoplay") ||
661
+ this.hasAttribute("data-poster-autoplay") ||
662
+ this.hasAttribute("data-should-autoplay");
663
+ const controls = isBackground ? false : this.hasAttribute("controls");
664
+ const mute = isBackground || autoplay;
665
+ if (this.hasAttribute("data-poster-autoplay")) {
666
+ this.removeAttribute("data-poster-autoplay");
667
+ }
668
+ if (this.hasAttribute("data-should-autoplay")) {
669
+ this.removeAttribute("data-should-autoplay");
670
+ }
671
+ this.log("VimeoEmbed: Creating iframe with autoplay:", autoplay, "controls:", controls);
672
+ this.iframe = document.createElement("iframe");
673
+ // Generate unique ID for Vimeo Player API
674
+ const iframeId = `vimeo-player-${videoId}-${Date.now()}`;
675
+ this.iframe.id = iframeId;
676
+ const params = new URLSearchParams(Object.assign({ autoplay: autoplay ? "1" : "0", controls: controls ? "1" : "0", muted: mute ? "1" : "0", playsinline: "1", dnt: "1" }, __classPrivateFieldGet(this, _VimeoEmbed_playerVars, "f")));
677
+ if (__classPrivateFieldGet(this, _VimeoEmbed_muted, "f")) {
678
+ params.set("muted", "1");
679
+ }
680
+ if (autoplay && !__classPrivateFieldGet(this, _VimeoEmbed_muted, "f")) {
681
+ __classPrivateFieldSet(this, _VimeoEmbed_muted, true, "f");
682
+ this.log("VimeoEmbed: Autoplay enabled, forcing muted state for compliance");
683
+ }
684
+ this.iframe.src = `https://player.vimeo.com/video/${videoId}?${params.toString()}`;
685
+ this.iframe.allow =
686
+ "autoplay; fullscreen; picture-in-picture; clipboard-write";
687
+ this.iframe.allowFullscreen = true;
688
+ this.iframe.style.position = "absolute";
689
+ this.iframe.style.border = "none";
690
+ if (__classPrivateFieldGet(this, _VimeoEmbed_background, "f")) {
691
+ this.iframe.style.pointerEvents = "none";
692
+ }
693
+ else {
694
+ this.iframe.style.top = "0";
695
+ this.iframe.style.left = "0";
696
+ this.iframe.style.width = "100%";
697
+ this.iframe.style.height = "100%";
698
+ }
699
+ this.log("VimeoEmbed: Iframe created with src:", this.iframe.src);
700
+ this.replaceChildren(this.iframe);
701
+ // Store reference to iframe before async operations
702
+ const iframe = this.iframe;
703
+ if (!controls) {
704
+ this.addCustomControls();
705
+ }
706
+ try {
707
+ yield VimeoEmbed.loadVimeoAPIWithRetry(this.apiLoadRetries);
708
+ // Check if component was disconnected during API load
709
+ if (!this.isConnected || !iframe.isConnected) {
710
+ this.log("VimeoEmbed: Component disconnected, skipping Player initialization");
711
+ return;
712
+ }
713
+ // Wait for iframe to be fully in DOM before initializing player
714
+ yield new Promise((resolve) => setTimeout(resolve, 100));
715
+ // @ts-ignore - Vimeo Player will be available after loading the API
716
+ // Use the iframe element directly since it's already in the DOM
717
+ this.player = new Vimeo.Player(iframe);
718
+ this.player.on("loaded", () => {
719
+ this.log("VimeoEmbed: Player is ready.");
720
+ this.playerReady = true;
721
+ if (__classPrivateFieldGet(this, _VimeoEmbed_muted, "f")) {
722
+ this.player.setVolume(0);
723
+ }
724
+ if (autoplay && this.setCustomControlState) {
725
+ this.setCustomControlState(true);
726
+ __classPrivateFieldSet(this, _VimeoEmbed_playing, true, "f");
727
+ }
728
+ this.dispatchCustomEvent("ready");
729
+ });
730
+ this.player.on("play", () => {
731
+ __classPrivateFieldSet(this, _VimeoEmbed_playing, true, "f");
732
+ if (this.setCustomControlState) {
733
+ this.setCustomControlState(true);
734
+ }
735
+ this.dispatchCustomEvent("play");
736
+ });
737
+ this.player.on("pause", () => {
738
+ __classPrivateFieldSet(this, _VimeoEmbed_playing, false, "f");
739
+ if (this.setCustomControlState) {
740
+ this.setCustomControlState(false);
741
+ }
742
+ this.dispatchCustomEvent("pause");
743
+ });
744
+ this.player.on("ended", () => {
745
+ __classPrivateFieldSet(this, _VimeoEmbed_playing, false, "f");
746
+ if (this.setCustomControlState) {
747
+ this.setCustomControlState(false);
748
+ }
749
+ this.dispatchCustomEvent("ended");
750
+ });
751
+ this.player.on("error", (error) => {
752
+ this.error("VimeoEmbed: Player encountered an error:", error);
753
+ this.dispatchCustomEvent("error", {
754
+ message: error.message || "Unknown error occurred",
755
+ name: error.name,
756
+ });
757
+ });
758
+ }
759
+ catch (error) {
760
+ this.error("VimeoEmbed: Failed to load Vimeo API", error);
761
+ this.showErrorMessage(error instanceof Error
762
+ ? error.message
763
+ : "Failed to load Vimeo player. Please refresh the page or check your connection.");
764
+ this.dispatchCustomEvent("error", {
765
+ message: error instanceof Error ? error.message : "API load failed",
766
+ code: "API_LOAD_ERROR",
767
+ retryable: true,
768
+ });
769
+ }
770
+ });
771
+ }
772
+ static loadVimeoAPI() {
773
+ return __awaiter(this, void 0, void 0, function* () {
774
+ return new Promise((resolve, reject) => {
775
+ if (this.apiReady) {
776
+ resolve();
777
+ return;
778
+ }
779
+ if (!this.apiLoaded) {
780
+ const script = document.createElement("script");
781
+ script.src = "https://player.vimeo.com/api/player.js";
782
+ script.onload = () => {
783
+ this.apiReady = true;
784
+ this.apiLoaded = true;
785
+ resolve();
786
+ };
787
+ script.onerror = () => {
788
+ reject(new Error("Failed to load Vimeo API script. Please check your network connection or disable ad blockers."));
789
+ };
790
+ document.head.appendChild(script);
791
+ this.apiLoaded = true;
792
+ }
793
+ else {
794
+ // Wait for API to be ready
795
+ const checkReady = setInterval(() => {
796
+ // @ts-ignore
797
+ if (typeof Vimeo !== "undefined") {
798
+ this.apiReady = true;
799
+ clearInterval(checkReady);
800
+ resolve();
801
+ }
802
+ }, 100);
803
+ setTimeout(() => {
804
+ clearInterval(checkReady);
805
+ reject(new Error("Vimeo API loading timeout. The API script may be blocked by an ad blocker or network issue."));
806
+ }, this.API_LOAD_TIMEOUT);
807
+ }
808
+ });
809
+ });
810
+ }
811
+ /**
812
+ * Load Vimeo API with retry mechanism
813
+ */
814
+ static loadVimeoAPIWithRetry() {
815
+ return __awaiter(this, arguments, void 0, function* (retries = 0) {
816
+ try {
817
+ yield this.loadVimeoAPI();
818
+ }
819
+ catch (error) {
820
+ if (retries < this.MAX_API_RETRIES) {
821
+ console.warn(`VimeoEmbed: API load failed, retrying (${retries + 1}/${this.MAX_API_RETRIES})...`);
822
+ yield new Promise((resolve) => setTimeout(resolve, this.API_RETRY_DELAY));
823
+ return this.loadVimeoAPIWithRetry(retries + 1);
824
+ }
825
+ throw error;
826
+ }
827
+ });
828
+ }
829
+ addCustomControls() {
830
+ this.classList.add("vimeo-embed-container");
831
+ const buttonOverlay = document.createElement("div");
832
+ buttonOverlay.classList.add("button-overlay");
833
+ this.playPauseButton = document.createElement("div");
834
+ this.playPauseButton.classList.add("button");
835
+ let isPlaying = false;
836
+ const setPlayingState = (playing) => {
837
+ isPlaying = playing;
838
+ if (playing) {
839
+ this.classList.add("is-playing");
840
+ }
841
+ else {
842
+ this.classList.remove("is-playing");
843
+ }
844
+ };
845
+ const togglePlayPause = () => {
846
+ if (isPlaying) {
847
+ if (this.player) {
848
+ this.player.pause();
849
+ }
850
+ setPlayingState(false);
851
+ }
852
+ else {
853
+ if (this.player) {
854
+ this.player.play();
855
+ }
856
+ setPlayingState(true);
857
+ }
858
+ };
859
+ this.setCustomControlState = setPlayingState;
860
+ buttonOverlay.addEventListener("click", togglePlayPause);
861
+ if (this.playPauseButton) {
862
+ buttonOverlay.appendChild(this.playPauseButton);
863
+ }
864
+ this.appendChild(buttonOverlay);
865
+ }
866
+ play() {
867
+ return __awaiter(this, void 0, void 0, function* () {
868
+ if (__classPrivateFieldGet(this, _VimeoEmbed_lazy, "f") && !this.player && !this.iframe) {
869
+ this.log("VimeoEmbed: Lazy video needs to be loaded first. Initializing...");
870
+ this.setAttribute("data-should-autoplay", "true");
871
+ yield this.initializePlayer(__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f"));
872
+ yield new Promise((resolve) => setTimeout(resolve, 1000));
873
+ }
874
+ if (!this.playerReady) {
875
+ this.warn("VimeoEmbed: Player is not ready. Waiting for initialization.");
876
+ yield new Promise((resolve) => {
877
+ const interval = setInterval(() => {
878
+ if (this.playerReady) {
879
+ clearInterval(interval);
880
+ resolve(null);
881
+ }
882
+ }, 100);
883
+ setTimeout(() => {
884
+ clearInterval(interval);
885
+ resolve(null);
886
+ }, 5000);
887
+ });
888
+ }
889
+ this.removeAttribute("data-should-autoplay");
890
+ if (this.player) {
891
+ this.player.play();
892
+ this.log("VimeoEmbed: Video playback started via API.");
893
+ }
894
+ __classPrivateFieldSet(this, _VimeoEmbed_playing, true, "f");
895
+ if (this.setCustomControlState) {
896
+ this.setCustomControlState(true);
897
+ }
898
+ this.dispatchCustomEvent("play");
899
+ });
900
+ }
901
+ pause() {
902
+ if (this.player) {
903
+ this.player.pause();
904
+ this.log("VimeoEmbed: Video paused via API.");
905
+ }
906
+ __classPrivateFieldSet(this, _VimeoEmbed_playing, false, "f");
907
+ if (this.setCustomControlState) {
908
+ this.setCustomControlState(false);
909
+ }
910
+ this.dispatchCustomEvent("pause");
911
+ }
912
+ stopVideo() {
913
+ if (this.player) {
914
+ this.player.pause();
915
+ this.player.setCurrentTime(0);
916
+ this.log("VimeoEmbed: Video stopped via API.");
917
+ }
918
+ __classPrivateFieldSet(this, _VimeoEmbed_playing, false, "f");
919
+ if (this.setCustomControlState) {
920
+ this.setCustomControlState(false);
921
+ }
922
+ this.dispatchCustomEvent("stop");
923
+ }
924
+ mute() {
925
+ this.muted = true;
926
+ }
927
+ unmute() {
928
+ this.muted = false;
929
+ }
930
+ togglePlay() {
931
+ if (__classPrivateFieldGet(this, _VimeoEmbed_playing, "f")) {
932
+ this.pause();
933
+ }
934
+ else {
935
+ this.play();
936
+ }
937
+ }
938
+ toggleMute() {
939
+ this.muted = !__classPrivateFieldGet(this, _VimeoEmbed_muted, "f");
940
+ }
941
+ static toggleDebug(forceState) {
942
+ VimeoEmbed.DEBUG =
943
+ forceState !== undefined ? forceState : !VimeoEmbed.DEBUG;
944
+ console.log(`VimeoEmbed: Debugging is now ${VimeoEmbed.DEBUG ? "ENABLED" : "DISABLED"}.`);
945
+ }
946
+ getPlayerState() {
947
+ let actualMutedState = __classPrivateFieldGet(this, _VimeoEmbed_muted, "f");
948
+ if (this.player && this.playerReady && !this.updatingMutedState) {
949
+ try {
950
+ this.player.getVolume().then((volume) => {
951
+ actualMutedState = volume === 0;
952
+ if (actualMutedState !== __classPrivateFieldGet(this, _VimeoEmbed_muted, "f") && !this.updatingMutedState) {
953
+ __classPrivateFieldSet(this, _VimeoEmbed_muted, actualMutedState, "f");
954
+ }
955
+ });
956
+ }
957
+ catch (error) {
958
+ this.warn("VimeoEmbed: Could not get muted state from player:", error);
959
+ }
960
+ }
961
+ return {
962
+ playing: __classPrivateFieldGet(this, _VimeoEmbed_playing, "f"),
963
+ muted: actualMutedState,
964
+ videoId: __classPrivateFieldGet(this, _VimeoEmbed_videoId, "f"),
965
+ ready: this.playerReady,
966
+ initialized: this.initialized,
967
+ };
968
+ }
969
+ isPlaying() {
970
+ return __classPrivateFieldGet(this, _VimeoEmbed_playing, "f");
971
+ }
972
+ isMuted() {
973
+ return __awaiter(this, void 0, void 0, function* () {
974
+ if (this.player && this.playerReady) {
975
+ try {
976
+ const volume = yield this.player.getVolume();
977
+ return volume === 0;
978
+ }
979
+ catch (error) {
980
+ this.warn("VimeoEmbed: Could not get muted state from player:", error);
981
+ }
982
+ }
983
+ return __classPrivateFieldGet(this, _VimeoEmbed_muted, "f");
984
+ });
985
+ }
986
+ getCurrentTime() {
987
+ return __awaiter(this, void 0, void 0, function* () {
988
+ if (this.player && this.playerReady) {
989
+ try {
990
+ return yield this.player.getCurrentTime();
991
+ }
992
+ catch (error) {
993
+ this.warn("VimeoEmbed: Could not get current time from player:", error);
994
+ }
995
+ }
996
+ return 0;
997
+ });
998
+ }
999
+ /**
1000
+ * Request fullscreen mode
1001
+ */
1002
+ enterFullscreen() {
1003
+ const elem = this;
1004
+ if (elem.requestFullscreen) {
1005
+ return elem.requestFullscreen();
1006
+ }
1007
+ else if (elem.webkitRequestFullscreen) {
1008
+ return elem.webkitRequestFullscreen();
1009
+ }
1010
+ else if (elem.mozRequestFullScreen) {
1011
+ return elem.mozRequestFullScreen();
1012
+ }
1013
+ else if (elem.msRequestFullscreen) {
1014
+ return elem.msRequestFullscreen();
1015
+ }
1016
+ return Promise.reject(new Error("Fullscreen API not supported"));
1017
+ }
1018
+ /**
1019
+ * Exit fullscreen mode
1020
+ */
1021
+ exitFullscreen() {
1022
+ const doc = document;
1023
+ if (doc.exitFullscreen) {
1024
+ return doc.exitFullscreen();
1025
+ }
1026
+ else if (doc.webkitExitFullscreen) {
1027
+ return doc.webkitExitFullscreen();
1028
+ }
1029
+ else if (doc.mozCancelFullScreen) {
1030
+ return doc.mozCancelFullScreen();
1031
+ }
1032
+ else if (doc.msExitFullscreen) {
1033
+ return doc.msExitFullscreen();
1034
+ }
1035
+ return Promise.reject(new Error("Fullscreen API not supported"));
1036
+ }
1037
+ /**
1038
+ * Toggle fullscreen mode
1039
+ */
1040
+ toggleFullscreen() {
1041
+ return __awaiter(this, void 0, void 0, function* () {
1042
+ if (this.isFullscreen()) {
1043
+ yield this.exitFullscreen();
1044
+ }
1045
+ else {
1046
+ yield this.enterFullscreen();
1047
+ }
1048
+ });
1049
+ }
1050
+ /**
1051
+ * Check if currently in fullscreen mode
1052
+ */
1053
+ isFullscreen() {
1054
+ const doc = document;
1055
+ return !!(doc.fullscreenElement ||
1056
+ doc.webkitFullscreenElement ||
1057
+ doc.mozFullScreenElement ||
1058
+ doc.msFullscreenElement);
1059
+ }
1060
+ /**
1061
+ * Get available quality levels for the current video
1062
+ * @returns Array of available quality levels
1063
+ */
1064
+ getAvailableQualities() {
1065
+ return __awaiter(this, void 0, void 0, function* () {
1066
+ if (this.player && this.playerReady) {
1067
+ try {
1068
+ return (yield this.player.getQualities()) || [];
1069
+ }
1070
+ catch (error) {
1071
+ this.warn("VimeoEmbed: Could not get available qualities:", error);
1072
+ }
1073
+ }
1074
+ return [];
1075
+ });
1076
+ }
1077
+ /**
1078
+ * Get the current playback quality
1079
+ * @returns Current quality level
1080
+ */
1081
+ getCurrentQuality() {
1082
+ return __awaiter(this, void 0, void 0, function* () {
1083
+ if (this.player && this.playerReady) {
1084
+ try {
1085
+ return (yield this.player.getQuality()) || "auto";
1086
+ }
1087
+ catch (error) {
1088
+ this.warn("VimeoEmbed: Could not get current quality:", error);
1089
+ }
1090
+ }
1091
+ return "auto";
1092
+ });
1093
+ }
1094
+ /**
1095
+ * Set the playback quality
1096
+ * @param quality The desired quality level
1097
+ */
1098
+ setQuality(quality) {
1099
+ return __awaiter(this, void 0, void 0, function* () {
1100
+ if (!this.player || !this.playerReady) {
1101
+ this.warn("VimeoEmbed: Player not ready for quality change");
1102
+ return;
1103
+ }
1104
+ try {
1105
+ const oldQuality = yield this.getCurrentQuality();
1106
+ yield this.player.setQuality(quality);
1107
+ // Dispatch quality change event
1108
+ const event = new CustomEvent("qualitychange", {
1109
+ detail: {
1110
+ oldQuality,
1111
+ newQuality: quality,
1112
+ availableQualities: yield this.getAvailableQualities(),
1113
+ },
1114
+ bubbles: true,
1115
+ composed: true,
1116
+ });
1117
+ this.dispatchEvent(event);
1118
+ }
1119
+ catch (error) {
1120
+ this.warn("VimeoEmbed: Could not set quality:", error);
1121
+ }
1122
+ });
1123
+ }
1124
+ loadVideo(videoIdOrUrl) {
1125
+ const extracted = this.extractVideoId(videoIdOrUrl);
1126
+ if (extracted) {
1127
+ __classPrivateFieldSet(this, _VimeoEmbed_url, videoIdOrUrl, "f");
1128
+ __classPrivateFieldSet(this, _VimeoEmbed_videoId, extracted, "f");
1129
+ }
1130
+ else {
1131
+ __classPrivateFieldSet(this, _VimeoEmbed_videoId, videoIdOrUrl, "f");
1132
+ }
1133
+ if (__classPrivateFieldGet(this, _VimeoEmbed_lazy, "f") && !this.player) {
1134
+ try {
1135
+ this.initializePlayer(__classPrivateFieldGet(this, _VimeoEmbed_videoId, "f"));
1136
+ }
1137
+ catch (error) {
1138
+ this.warn("VimeoEmbed: loadVideo failed to initialize player:", error);
1139
+ }
1140
+ return;
1141
+ }
1142
+ if (this.initialized) {
1143
+ this.reinitializePlayer();
1144
+ }
1145
+ }
1146
+ }
1147
+ _VimeoEmbed_url = new WeakMap(), _VimeoEmbed_videoId = new WeakMap(), _VimeoEmbed_autoplay = new WeakMap(), _VimeoEmbed_muted = new WeakMap(), _VimeoEmbed_controls = new WeakMap(), _VimeoEmbed_lazy = new WeakMap(), _VimeoEmbed_poster = new WeakMap(), _VimeoEmbed_playing = new WeakMap(), _VimeoEmbed_background = new WeakMap(), _VimeoEmbed_playerVars = new WeakMap(), _VimeoEmbed_instances = new WeakSet(), _VimeoEmbed_reflectBooleanAttribute = function _VimeoEmbed_reflectBooleanAttribute(name, value) {
1148
+ this.updatingAttribute = true;
1149
+ if (value) {
1150
+ this.setAttribute(name, "");
1151
+ }
1152
+ else {
1153
+ this.removeAttribute(name);
1154
+ }
1155
+ this.updatingAttribute = false;
1156
+ }, _VimeoEmbed_updateBackgroundMode = function _VimeoEmbed_updateBackgroundMode() {
1157
+ if (__classPrivateFieldGet(this, _VimeoEmbed_background, "f")) {
1158
+ this.classList.add("is-background");
1159
+ __classPrivateFieldSet(this, _VimeoEmbed_autoplay, true, "f");
1160
+ __classPrivateFieldSet(this, _VimeoEmbed_muted, true, "f");
1161
+ __classPrivateFieldSet(this, _VimeoEmbed_controls, false, "f");
1162
+ __classPrivateFieldSet(this, _VimeoEmbed_lazy, false, "f");
1163
+ }
1164
+ else {
1165
+ this.classList.remove("is-background");
1166
+ }
1167
+ };
1168
+ VimeoEmbed.apiLoaded = false;
1169
+ VimeoEmbed.apiReady = false;
1170
+ VimeoEmbed.instanceCount = 0;
1171
+ VimeoEmbed.DEBUG = false;
1172
+ VimeoEmbed.MAX_API_RETRIES = 3;
1173
+ VimeoEmbed.API_RETRY_DELAY = 2000;
1174
+ VimeoEmbed.API_LOAD_TIMEOUT = 10000;
1175
+ customElements.define("vimeo-embed", VimeoEmbed);
1176
+ //# sourceMappingURL=VimeoEmbed.js.map