vidply 1.0.32 → 1.0.33
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 +7 -7
- package/dist/dev/{vidply.HLSRenderer-5MJZR4D2.js → vidply.HLSRenderer-LIFBU6UD.js} +48 -3
- package/dist/dev/vidply.HLSRenderer-LIFBU6UD.js.map +7 -0
- package/dist/dev/{vidply.HTML5Renderer-FXBZQL6Y.js → vidply.HTML5Renderer-YWMVYWFS.js} +2 -2
- package/dist/dev/{vidply.TranscriptManager-T677KF4N.js → vidply.TranscriptManager-R7NJRU7E.js} +2 -2
- package/dist/dev/{vidply.chunk-GS2JX5RQ.js → vidply.chunk-PMRKJBGH.js} +5 -2
- package/dist/dev/vidply.chunk-PMRKJBGH.js.map +7 -0
- package/dist/dev/{vidply.chunk-W2LSBD6Y.js → vidply.chunk-UVO24MXU.js} +33 -3
- package/dist/dev/vidply.chunk-UVO24MXU.js.map +7 -0
- package/dist/dev/{vidply.de-SNL6AJ4D.js → vidply.de-CEGBLV67.js} +4 -1
- package/dist/dev/vidply.de-CEGBLV67.js.map +7 -0
- package/dist/dev/vidply.esm.js +364 -63
- package/dist/dev/vidply.esm.js.map +2 -2
- package/dist/legacy/vidply.js +459 -63
- package/dist/legacy/vidply.js.map +3 -3
- package/dist/legacy/vidply.min.js +1 -1
- package/dist/legacy/vidply.min.meta.json +15 -15
- package/dist/prod/vidply.HLSRenderer-ESR6NAMI.min.js +6 -0
- package/dist/prod/{vidply.HTML5Renderer-KKW3OLHM.min.js → vidply.HTML5Renderer-6ROXQSQY.min.js} +1 -1
- package/dist/prod/{vidply.TranscriptManager-WFZSW6NR.min.js → vidply.TranscriptManager-B65LKXGG.min.js} +1 -1
- package/dist/prod/vidply.chunk-7HVHEUHH.min.js +6 -0
- package/dist/prod/vidply.chunk-IQKD4GUB.min.js +6 -0
- package/dist/prod/vidply.de-IHKC573T.min.js +6 -0
- package/dist/prod/vidply.esm.min.js +4 -4
- package/dist/vidply.esm.min.meta.json +33 -33
- package/package.json +1 -1
- package/src/controls/ControlBar.js +104 -70
- package/src/core/Player.js +217 -3
- package/src/features/PlaylistManager.js +175 -17
- package/src/i18n/languages/de.js +3 -0
- package/src/i18n/languages/en.js +3 -0
- package/src/renderers/HLSRenderer.js +60 -1
- package/src/renderers/HTML5Renderer.js +43 -5
- package/dist/dev/vidply.HLSRenderer-5MJZR4D2.js.map +0 -7
- package/dist/dev/vidply.chunk-GS2JX5RQ.js.map +0 -7
- package/dist/dev/vidply.chunk-W2LSBD6Y.js.map +0 -7
- package/dist/dev/vidply.de-SNL6AJ4D.js.map +0 -7
- package/dist/prod/vidply.HLSRenderer-VWNJD2CB.min.js +0 -6
- package/dist/prod/vidply.chunk-34RH2THY.min.js +0 -6
- package/dist/prod/vidply.chunk-LGTJRPUL.min.js +0 -6
- package/dist/prod/vidply.de-FR3XX54P.min.js +0 -6
- /package/dist/dev/{vidply.HTML5Renderer-FXBZQL6Y.js.map → vidply.HTML5Renderer-YWMVYWFS.js.map} +0 -0
- /package/dist/dev/{vidply.TranscriptManager-T677KF4N.js.map → vidply.TranscriptManager-R7NJRU7E.js.map} +0 -0
|
@@ -8,6 +8,8 @@ export class HLSRenderer {
|
|
|
8
8
|
this.player = player;
|
|
9
9
|
this.media = player.element;
|
|
10
10
|
this.hls = null;
|
|
11
|
+
this._hlsSourceLoaded = false;
|
|
12
|
+
this._pendingSrc = null;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
async init() {
|
|
@@ -67,6 +69,8 @@ export class HLSRenderer {
|
|
|
67
69
|
// Create hls.js instance with better error recovery
|
|
68
70
|
this.hls = new window.Hls({
|
|
69
71
|
debug: this.player.options.debug,
|
|
72
|
+
// When deferLoad is enabled, do not start loading until the first play().
|
|
73
|
+
autoStartLoad: !this.player.options.deferLoad,
|
|
70
74
|
enableWorker: true,
|
|
71
75
|
lowLatencyMode: false,
|
|
72
76
|
backBufferLength: 90,
|
|
@@ -112,7 +116,13 @@ export class HLSRenderer {
|
|
|
112
116
|
throw new Error('No HLS source found');
|
|
113
117
|
}
|
|
114
118
|
|
|
115
|
-
this.
|
|
119
|
+
if (this.player.options.deferLoad) {
|
|
120
|
+
// Defer manifest/segment loading until first play()
|
|
121
|
+
this._pendingSrc = src;
|
|
122
|
+
} else {
|
|
123
|
+
this.hls.loadSource(src);
|
|
124
|
+
this._hlsSourceLoaded = true;
|
|
125
|
+
}
|
|
116
126
|
|
|
117
127
|
// Attach events
|
|
118
128
|
this.attachHlsEvents();
|
|
@@ -261,10 +271,59 @@ export class HLSRenderer {
|
|
|
261
271
|
}
|
|
262
272
|
}
|
|
263
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Ensure the HLS manifest/initial loading is started without starting playback.
|
|
276
|
+
* This makes playlist selection behave more like single-video initialization.
|
|
277
|
+
*/
|
|
278
|
+
ensureLoaded() {
|
|
279
|
+
if (!this.player.options.deferLoad) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Native HLS path delegates to HTML5Renderer; if we got here and have no hls.js instance,
|
|
284
|
+
// there's nothing to do.
|
|
285
|
+
if (!this.hls) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (this._hlsSourceLoaded) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const src = this._pendingSrc || this.player._pendingSource || this.player.currentSource;
|
|
294
|
+
if (!src) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
this.hls.loadSource(src);
|
|
300
|
+
this._hlsSourceLoaded = true;
|
|
301
|
+
// Start loading so manifest is parsed and levels/tracks become available.
|
|
302
|
+
// Note: this may fetch initial fragments depending on stream/config.
|
|
303
|
+
this.hls.startLoad();
|
|
304
|
+
} catch (e) {
|
|
305
|
+
// ignore
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
264
309
|
play() {
|
|
265
310
|
// Save scroll position to prevent browser from scrolling to video
|
|
266
311
|
const scrollX = window.scrollX;
|
|
267
312
|
const scrollY = window.scrollY;
|
|
313
|
+
|
|
314
|
+
// If deferLoad is enabled, start HLS loading only on the first user play request.
|
|
315
|
+
if (this.player.options.deferLoad && this.hls && !this._hlsSourceLoaded) {
|
|
316
|
+
const src = this._pendingSrc || this.player.currentSource;
|
|
317
|
+
if (src) {
|
|
318
|
+
try {
|
|
319
|
+
this.hls.loadSource(src);
|
|
320
|
+
this.hls.startLoad();
|
|
321
|
+
this._hlsSourceLoaded = true;
|
|
322
|
+
} catch (e) {
|
|
323
|
+
// ignore and let media.play() surface errors if any
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
268
327
|
|
|
269
328
|
const promise = this.media.play();
|
|
270
329
|
|
|
@@ -6,6 +6,7 @@ export class HTML5Renderer {
|
|
|
6
6
|
constructor(player) {
|
|
7
7
|
this.player = player;
|
|
8
8
|
this.media = player.element;
|
|
9
|
+
this._didDeferredLoad = false;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
async init() {
|
|
@@ -15,11 +16,16 @@ export class HTML5Renderer {
|
|
|
15
16
|
|
|
16
17
|
this.attachEvents();
|
|
17
18
|
|
|
18
|
-
// Set preload
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
// Set preload + optionally defer network loading until user play
|
|
20
|
+
if (this.player.options.deferLoad) {
|
|
21
|
+
// Allow metadata preload while still avoiding an explicit load() call.
|
|
22
|
+
// Note: browsers may still fetch metadata automatically when preload="metadata".
|
|
23
|
+
this.media.preload = this.player.options.preload || 'none';
|
|
24
|
+
} else {
|
|
25
|
+
this.media.preload = this.player.options.preload;
|
|
26
|
+
// Load media (eager)
|
|
27
|
+
this.media.load();
|
|
28
|
+
}
|
|
23
29
|
|
|
24
30
|
// Show VidPly controls (remove external controls class if present)
|
|
25
31
|
if (this.player.container) {
|
|
@@ -157,6 +163,19 @@ export class HTML5Renderer {
|
|
|
157
163
|
// Save scroll position to prevent browser from scrolling to video
|
|
158
164
|
const scrollX = window.scrollX;
|
|
159
165
|
const scrollY = window.scrollY;
|
|
166
|
+
|
|
167
|
+
// If deferLoad is enabled, trigger load only on the first user play request.
|
|
168
|
+
if (this.player.options.deferLoad && !this._didDeferredLoad) {
|
|
169
|
+
try {
|
|
170
|
+
// Only call load() if browser hasn't loaded anything yet.
|
|
171
|
+
if (this.media.readyState === 0) {
|
|
172
|
+
this.media.load();
|
|
173
|
+
}
|
|
174
|
+
} catch (e) {
|
|
175
|
+
// ignore
|
|
176
|
+
}
|
|
177
|
+
this._didDeferredLoad = true;
|
|
178
|
+
}
|
|
160
179
|
|
|
161
180
|
const promise = this.media.play();
|
|
162
181
|
|
|
@@ -185,6 +204,25 @@ export class HTML5Renderer {
|
|
|
185
204
|
}
|
|
186
205
|
}
|
|
187
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Ensure the media element has been loaded at least once (metadata/initial state)
|
|
209
|
+
* without starting playback. Useful for playlists to behave like single videos.
|
|
210
|
+
*/
|
|
211
|
+
ensureLoaded() {
|
|
212
|
+
if (!this.player.options.deferLoad || this._didDeferredLoad) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
if (this.media.readyState === 0) {
|
|
218
|
+
this.media.load();
|
|
219
|
+
}
|
|
220
|
+
} catch (e) {
|
|
221
|
+
// ignore
|
|
222
|
+
}
|
|
223
|
+
this._didDeferredLoad = true;
|
|
224
|
+
}
|
|
225
|
+
|
|
188
226
|
pause() {
|
|
189
227
|
this.media.pause();
|
|
190
228
|
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/renderers/HLSRenderer.js"],
|
|
4
|
-
"sourcesContent": ["/**\r\n * HLS Streaming Renderer\r\n * Uses hls.js for browsers that don't natively support HLS\r\n */\r\n\r\nexport class HLSRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.media = player.element;\r\n this.hls = null;\r\n }\r\n\r\n async init() {\r\n // Check if browser natively supports HLS (Safari)\r\n if (this.canPlayNatively()) {\r\n this.player.log('Using native HLS support');\r\n await this.initNative();\r\n } else {\r\n this.player.log('Using hls.js for HLS support');\r\n await this.initHlsJs();\r\n }\r\n }\r\n\r\n canPlayNatively() {\r\n // Only use native HLS on Safari/iOS where it actually works properly\r\n // Chrome reports it can play HLS but doesn't have proper quality switching\r\n const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\r\n const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;\r\n \r\n if (!isSafari && !isIOS) {\r\n // Force hls.js on non-Safari browsers for proper quality switching\r\n return false;\r\n }\r\n \r\n const video = document.createElement('video');\r\n return video.canPlayType('application/vnd.apple.mpegurl') !== '';\r\n }\r\n\r\n async initNative() {\r\n // Use HTML5 renderer for native HLS support\r\n const HTML5Renderer = (await import('./HTML5Renderer.js')).HTML5Renderer;\r\n const renderer = new HTML5Renderer(this.player);\r\n await renderer.init();\r\n \r\n // Copy methods\r\n Object.getOwnPropertyNames(Object.getPrototypeOf(renderer)).forEach(method => {\r\n if (method !== 'constructor' && typeof renderer[method] === 'function') {\r\n this[method] = renderer[method].bind(renderer);\r\n }\r\n });\r\n }\r\n\r\n async initHlsJs() {\r\n // Hide native controls\r\n this.media.controls = false;\r\n this.media.removeAttribute('controls');\r\n \r\n // Load hls.js if not already loaded\r\n if (!window.Hls) {\r\n await this.loadHlsJs();\r\n }\r\n\r\n if (!window.Hls.isSupported()) {\r\n throw new Error('HLS is not supported in this browser');\r\n }\r\n\r\n // Create hls.js instance with better error recovery\r\n this.hls = new window.Hls({\r\n debug: this.player.options.debug,\r\n enableWorker: true,\r\n lowLatencyMode: false,\r\n backBufferLength: 90,\r\n maxBufferLength: 30,\r\n maxMaxBufferLength: 600,\r\n maxBufferSize: 60 * 1000 * 1000,\r\n maxBufferHole: 0.5,\r\n // Network retry settings\r\n manifestLoadingTimeOut: 10000,\r\n manifestLoadingMaxRetry: 4,\r\n manifestLoadingRetryDelay: 1000,\r\n manifestLoadingMaxRetryTimeout: 64000,\r\n levelLoadingTimeOut: 10000,\r\n levelLoadingMaxRetry: 4,\r\n levelLoadingRetryDelay: 1000,\r\n levelLoadingMaxRetryTimeout: 64000,\r\n fragLoadingTimeOut: 20000,\r\n fragLoadingMaxRetry: 6,\r\n fragLoadingRetryDelay: 1000,\r\n fragLoadingMaxRetryTimeout: 64000\r\n });\r\n\r\n // Attach media element\r\n this.hls.attachMedia(this.media);\r\n\r\n // Load source - use currentSource for external renderers, or get from attribute\r\n let src = this.player.currentSource;\r\n \r\n if (!src) {\r\n const sourceElement = this.player.element.querySelector('source');\r\n if (sourceElement) {\r\n // Use getAttribute to get the original URL, not the blob-converted one\r\n src = sourceElement.getAttribute('src');\r\n } else {\r\n // Fallback to element's src attribute\r\n src = this.player.element.getAttribute('src') || this.player.element.src;\r\n }\r\n }\r\n \r\n this.player.log(`Loading HLS source: ${src}`, 'log');\r\n \r\n if (!src) {\r\n throw new Error('No HLS source found');\r\n }\r\n \r\n this.hls.loadSource(src);\r\n\r\n // Attach events\r\n this.attachHlsEvents();\r\n this.attachMediaEvents();\r\n }\r\n\r\n async loadHlsJs() {\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = 'https://cdn.jsdelivr.net/npm/hls.js@latest';\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error('Failed to load hls.js'));\r\n document.head.appendChild(script);\r\n });\r\n }\r\n\r\n attachHlsEvents() {\r\n this.hls.on(window.Hls.Events.MANIFEST_PARSED, (event, data) => {\r\n this.player.log('HLS manifest loaded, found ' + data.levels.length + ' quality levels');\r\n this.player.emit('hlsmanifestparsed', data);\r\n \r\n // Show VidPly controls (remove external controls class if present)\r\n if (this.player.container) {\r\n this.player.container.classList.remove('vidply-external-controls');\r\n }\r\n });\r\n\r\n this.hls.on(window.Hls.Events.LEVEL_SWITCHED, (event, data) => {\r\n this.player.log('HLS level switched to ' + data.level);\r\n this.player.emit('hlslevelswitched', data);\r\n });\r\n\r\n this.hls.on(window.Hls.Events.ERROR, (event, data) => {\r\n this.handleHlsError(data);\r\n });\r\n\r\n this.hls.on(window.Hls.Events.FRAG_BUFFERED, () => {\r\n this.player.state.buffering = false;\r\n });\r\n }\r\n\r\n attachMediaEvents() {\r\n // Use same events as HTML5 renderer\r\n this.media.addEventListener('loadedmetadata', () => {\r\n this.player.state.duration = this.media.duration;\r\n this.player.emit('loadedmetadata');\r\n });\r\n\r\n this.media.addEventListener('play', () => {\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.emit('play');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n });\r\n\r\n this.media.addEventListener('pause', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n });\r\n\r\n this.media.addEventListener('ended', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n if (this.player.options.loop) {\r\n this.player.seek(0);\r\n this.player.play();\r\n }\r\n });\r\n\r\n this.media.addEventListener('timeupdate', () => {\r\n this.player.state.currentTime = this.media.currentTime;\r\n this.player.emit('timeupdate', this.media.currentTime);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, this.media.currentTime);\r\n }\r\n });\r\n\r\n this.media.addEventListener('volumechange', () => {\r\n this.player.state.volume = this.media.volume;\r\n this.player.state.muted = this.media.muted;\r\n this.player.emit('volumechange', this.media.volume);\r\n });\r\n\r\n this.media.addEventListener('waiting', () => {\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n });\r\n\r\n this.media.addEventListener('canplay', () => {\r\n this.player.state.buffering = false;\r\n this.player.emit('canplay');\r\n });\r\n\r\n this.media.addEventListener('error', () => {\r\n this.player.handleError(this.media.error);\r\n });\r\n }\r\n\r\n handleHlsError(data) {\r\n // Log detailed error info\r\n this.player.log(`HLS Error - Type: ${data.type}, Details: ${data.details}, Fatal: ${data.fatal}`, 'warn');\r\n if (data.response) {\r\n this.player.log(`Response code: ${data.response.code}, URL: ${data.response.url}`, 'warn');\r\n }\r\n \r\n if (data.fatal) {\r\n switch (data.type) {\r\n case window.Hls.ErrorTypes.NETWORK_ERROR:\r\n this.player.log('Fatal network error, trying to recover...', 'error');\r\n this.player.log(`Network error details: ${data.details}`, 'error');\r\n setTimeout(() => {\r\n this.hls.startLoad();\r\n }, 1000);\r\n break;\r\n \r\n case window.Hls.ErrorTypes.MEDIA_ERROR:\r\n this.player.log('Fatal media error, trying to recover...', 'error');\r\n this.hls.recoverMediaError();\r\n break;\r\n \r\n default:\r\n this.player.log('Fatal error, cannot recover', 'error');\r\n this.player.handleError(new Error(`HLS Error: ${data.type} - ${data.details}`));\r\n this.hls.destroy();\r\n break;\r\n }\r\n } else {\r\n this.player.log('Non-fatal HLS error: ' + data.details, 'warn');\r\n }\r\n }\r\n\r\n play() {\r\n // Save scroll position to prevent browser from scrolling to video\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n \r\n const promise = this.media.play();\r\n \r\n // Restore scroll position immediately to prevent auto-scroll\r\n window.scrollTo(scrollX, scrollY);\r\n \r\n if (promise !== undefined) {\r\n promise.catch(error => {\r\n this.player.log('Play failed:', error, 'warn');\r\n });\r\n }\r\n }\r\n\r\n pause() {\r\n this.media.pause();\r\n }\r\n\r\n seek(time) {\r\n this.media.currentTime = time;\r\n }\r\n\r\n setVolume(volume) {\r\n this.media.volume = volume;\r\n }\r\n\r\n setMuted(muted) {\r\n this.media.muted = muted;\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n this.media.playbackRate = speed;\r\n }\r\n\r\n switchQuality(levelIndex) {\r\n if (this.hls) {\r\n this.hls.currentLevel = levelIndex;\r\n }\r\n }\r\n\r\n getQualities() {\r\n if (this.hls && this.hls.levels) {\r\n return this.hls.levels.map((level, index) => {\r\n const height = Number(level.height) || 0;\r\n const bitrate = Number(level.bitrate) || 0;\r\n const kb = bitrate > 0 ? Math.round(bitrate / 1000) : 0;\r\n\r\n // Video HLS typically has height -> show \"720p\".\r\n // Audio-only HLS often has height=0 -> show bitrate label instead.\r\n const name = height > 0 ? `${height}p` : (kb > 0 ? `${kb} kb` : 'Auto');\r\n\r\n return {\r\n index,\r\n height: level.height,\r\n width: level.width,\r\n bitrate: level.bitrate,\r\n name\r\n };\r\n });\r\n }\r\n return [];\r\n }\r\n\r\n getCurrentQuality() {\r\n if (this.hls) {\r\n return this.hls.currentLevel;\r\n }\r\n return -1;\r\n }\r\n\r\n destroy() {\r\n if (this.hls) {\r\n this.hls.destroy();\r\n this.hls = null;\r\n }\r\n }\r\n}\r\n\r\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/utils/DOMUtils.js", "../../src/i18n/languages/en.js", "../../src/i18n/translations.js", "../../src/i18n/i18n.js", "../../src/utils/TimeUtils.js", "../../src/icons/Icons.js", "../../src/utils/FocusUtils.js", "../../src/utils/StorageManager.js", "../../src/utils/DraggableResizable.js", "../../src/utils/MenuUtils.js", "../../src/utils/FormUtils.js"],
|
|
4
|
-
"sourcesContent": ["/**\r\n * DOM manipulation utilities\r\n * Optimized for performance with CSS transitions\r\n */\r\n\r\nexport const DOMUtils = {\r\n /**\r\n * Create an element with options\r\n * @param {string} tag - HTML tag name\r\n * @param {Object} options - Element options\r\n * @returns {HTMLElement}\r\n */\r\n createElement(tag, options = {}) {\r\n const element = document.createElement(tag);\r\n \r\n if (options.className) {\r\n element.className = options.className;\r\n }\r\n \r\n if (options.attributes) {\r\n for (const [key, value] of Object.entries(options.attributes)) {\r\n element.setAttribute(key, value);\r\n }\r\n }\r\n \r\n if (options.innerHTML) {\r\n element.innerHTML = options.innerHTML;\r\n }\r\n \r\n if (options.textContent) {\r\n element.textContent = options.textContent;\r\n }\r\n \r\n if (options.style) {\r\n Object.assign(element.style, options.style);\r\n }\r\n \r\n if (options.children) {\r\n for (const child of options.children) {\r\n if (child) element.appendChild(child);\r\n }\r\n }\r\n \r\n return element;\r\n },\r\n\r\n /**\r\n * Show element (remove display:none)\r\n * @param {HTMLElement} element\r\n */\r\n show(element) {\r\n element?.style && (element.style.display = '');\r\n },\r\n\r\n /**\r\n * Hide element\r\n * @param {HTMLElement} element\r\n */\r\n hide(element) {\r\n element?.style && (element.style.display = 'none');\r\n },\r\n\r\n /**\r\n * Fade in element using CSS transitions (GPU accelerated)\r\n * @param {HTMLElement} element\r\n * @param {number} duration - Duration in ms\r\n * @param {Function} [onComplete] - Callback when complete\r\n */\r\n fadeIn(element, duration = 300, onComplete) {\r\n if (!element) return;\r\n \r\n // Set up initial state\r\n element.style.opacity = '0';\r\n element.style.display = '';\r\n element.style.transition = `opacity ${duration}ms ease`;\r\n \r\n // Force reflow to ensure transition works\r\n element.offsetHeight;\r\n \r\n // Trigger transition\r\n element.style.opacity = '1';\r\n \r\n // Cleanup after transition\r\n if (onComplete) {\r\n const cleanup = () => {\r\n element.removeEventListener('transitionend', cleanup);\r\n onComplete();\r\n };\r\n element.addEventListener('transitionend', cleanup, { once: true });\r\n // Fallback timeout in case transitionend doesn't fire\r\n setTimeout(cleanup, duration + 50);\r\n }\r\n },\r\n\r\n /**\r\n * Fade out element using CSS transitions (GPU accelerated)\r\n * @param {HTMLElement} element\r\n * @param {number} duration - Duration in ms\r\n * @param {Function} [onComplete] - Callback when complete\r\n */\r\n fadeOut(element, duration = 300, onComplete) {\r\n if (!element) return;\r\n \r\n element.style.transition = `opacity ${duration}ms ease`;\r\n element.style.opacity = '0';\r\n \r\n const cleanup = () => {\r\n element.removeEventListener('transitionend', cleanup);\r\n element.style.display = 'none';\r\n if (onComplete) onComplete();\r\n };\r\n \r\n element.addEventListener('transitionend', cleanup, { once: true });\r\n // Fallback timeout in case transitionend doesn't fire\r\n setTimeout(cleanup, duration + 50);\r\n },\r\n\r\n /**\r\n * Get element's offset position and dimensions\r\n * @param {HTMLElement} element\r\n * @returns {Object} { top, left, width, height }\r\n */\r\n offset(element) {\r\n if (!element) return { top: 0, left: 0, width: 0, height: 0 };\r\n \r\n const rect = element.getBoundingClientRect();\r\n return {\r\n top: rect.top + window.scrollY,\r\n left: rect.left + window.scrollX,\r\n width: rect.width,\r\n height: rect.height\r\n };\r\n },\r\n\r\n /**\r\n * Escape HTML special characters\r\n * @param {string} str - String to escape\r\n * @returns {string} Escaped string\r\n */\r\n escapeHTML(str) {\r\n const escapeMap = {\r\n '&': '&',\r\n '<': '<',\r\n '>': '>',\r\n '\"': '"',\r\n \"'\": '''\r\n };\r\n return str.replace(/[&<>\"']/g, char => escapeMap[char]);\r\n },\r\n\r\n /**\r\n * Basic HTML sanitization for VTT captions\r\n * Allows safe formatting tags, removes dangerous content\r\n * @param {string} html - HTML string to sanitize\r\n * @returns {string} Sanitized HTML\r\n */\r\n sanitizeHTML(html) {\r\n // Remove dangerous content\r\n const safeHtml = html\r\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\r\n .replace(/<iframe\\b[^<]*(?:(?!<\\/iframe>)<[^<]*)*<\\/iframe>/gi, '')\r\n .replace(/on\\w+\\s*=/gi, '') // Event handlers\r\n .replace(/javascript:/gi, ''); // javascript: protocol\r\n \r\n // Use DOM parser for final sanitization\r\n const temp = document.createElement('div');\r\n temp.innerHTML = safeHtml;\r\n return temp.innerHTML;\r\n },\r\n\r\n /**\r\n * Create a tooltip element (aria-hidden)\r\n * @param {string} text - Tooltip text\r\n * @param {string} classPrefix - Class prefix\r\n * @returns {HTMLElement}\r\n */\r\n createTooltip(text, classPrefix = 'vidply') {\r\n return this.createElement('span', {\r\n className: `${classPrefix}-tooltip`,\r\n textContent: text,\r\n attributes: { 'aria-hidden': 'true' }\r\n });\r\n },\r\n\r\n /**\r\n * Attach a tooltip to an element with hover/focus behavior\r\n * @param {HTMLElement} element - Target element\r\n * @param {string} text - Tooltip text\r\n * @param {string} classPrefix - Class prefix\r\n */\r\n attachTooltip(element, text, classPrefix = 'vidply') {\r\n if (!element || !text) return;\r\n \r\n // Remove existing tooltip\r\n element.querySelector(`.${classPrefix}-tooltip`)?.remove();\r\n \r\n const tooltip = this.createTooltip(text, classPrefix);\r\n element.appendChild(tooltip);\r\n \r\n const visibleClass = `${classPrefix}-tooltip-visible`;\r\n const show = () => tooltip.classList.add(visibleClass);\r\n const hide = () => tooltip.classList.remove(visibleClass);\r\n \r\n element.addEventListener('mouseenter', show);\r\n element.addEventListener('mouseleave', hide);\r\n element.addEventListener('focus', show);\r\n element.addEventListener('blur', hide);\r\n },\r\n\r\n /**\r\n * Create button text element (visible when CSS disabled)\r\n * @param {string} text - Button text\r\n * @param {string} classPrefix - Class prefix\r\n * @returns {HTMLElement}\r\n */\r\n createButtonText(text, classPrefix = 'vidply') {\r\n return this.createElement('span', {\r\n className: `${classPrefix}-button-text`,\r\n textContent: text,\r\n attributes: { 'aria-hidden': 'true' }\r\n });\r\n },\r\n\r\n /**\r\n * Add class to element (null-safe)\r\n * @param {HTMLElement} element\r\n * @param {string} className\r\n */\r\n addClass(element, className) {\r\n element?.classList?.add(className);\r\n },\r\n\r\n /**\r\n * Remove class from element (null-safe)\r\n * @param {HTMLElement} element\r\n * @param {string} className\r\n */\r\n removeClass(element, className) {\r\n element?.classList?.remove(className);\r\n },\r\n\r\n /**\r\n * Toggle class on element (null-safe)\r\n * @param {HTMLElement} element\r\n * @param {string} className\r\n */\r\n toggleClass(element, className) {\r\n element?.classList?.toggle(className);\r\n },\r\n\r\n /**\r\n * Check if element has class (null-safe)\r\n * @param {HTMLElement} element\r\n * @param {string} className\r\n * @returns {boolean}\r\n */\r\n hasClass(element, className) {\r\n return element?.classList?.contains(className) ?? false;\r\n }\r\n};\r\n", "/**\r\n * English translations for VidPly\r\n */\r\n\r\nexport const en = {\r\n player: {\r\n label: 'Video Player',\r\n play: 'Play',\r\n pause: 'Pause',\r\n stop: 'Stop',\r\n restart: 'Restart from beginning',\r\n rewind: 'Rewind',\r\n forward: 'Forward',\r\n rewindSeconds: 'Rewind {seconds} seconds',\r\n forwardSeconds: 'Forward {seconds} seconds',\r\n previous: 'Previous track',\r\n next: 'Next track',\r\n playlist: 'Toggle playlist',\r\n volume: 'Volume',\r\n mute: 'Mute',\r\n unmute: 'Unmute',\r\n fullscreen: 'Fullscreen',\r\n exitFullscreen: 'Exit Fullscreen',\r\n captions: 'Captions',\r\n chapters: 'Chapters',\r\n quality: 'Quality',\r\n captionStyling: 'Caption styling',\r\n transcript: 'Toggle transcript',\r\n audioDescription: 'Audio description',\r\n signLanguage: 'Sign language video',\r\n settings: 'Settings',\r\n speed: 'Playback Speed',\r\n pip: 'Picture in Picture',\r\n currentTime: 'Current time',\r\n duration: 'Duration',\r\n progress: 'Progress',\r\n seekForward: 'Seek forward {seconds} seconds',\r\n seekBackward: 'Seek backward {seconds} seconds',\r\n volumeUp: 'Volume up',\r\n volumeDown: 'Volume down',\r\n loading: 'Loading...',\r\n loadingChapters: 'Loading chapters...',\r\n error: 'Error loading media',\r\n buffering: 'Buffering...',\r\n signLanguageVideo: 'Sign Language Video',\r\n closeSignLanguage: 'Close sign language video',\r\n signLanguageSettings: 'Sign language settings',\r\n noChapters: 'No chapters available',\r\n noCaptions: 'No captions available',\r\n auto: 'Auto',\r\n autoQuality: 'Auto (no quality selection available)',\r\n noQuality: 'Quality selection not available',\r\n signLanguageDragResize: 'Sign Language Video - Press D to drag with keyboard, R to resize',\r\n signLanguageDragActive: 'Sign Language Video - Drag mode active. Use arrow keys to move, Escape to exit.',\r\n signLanguageResizeActive: 'Sign Language Video - Resize mode active. Use left/right arrow keys to resize, Escape to exit.',\r\n enableSignDragMode: 'Enable drag mode. Shortcut: D key',\r\n disableSignDragMode: 'Disable drag mode. Shortcut: D key',\r\n enableSignDragModeAria: 'Enable toggle keyboard drag mode with arrow keys. Shortcut: D key',\r\n disableSignDragModeAria: 'Disable toggle keyboard drag mode with arrow keys. Shortcut: D key',\r\n enableSignResizeMode: 'Enable resize mode. Shortcut: R key',\r\n disableSignResizeMode: 'Disable resize mode. Shortcut: R key',\r\n enableSignResizeModeAria: 'Enable keyboard resize mode with arrow keys. Shortcut: R key',\r\n disableSignResizeModeAria: 'Disable keyboard resize mode with arrow keys. Shortcut: R key',\r\n resizeHandle: 'Resize {direction} corner',\r\n moreOptions: 'More options',\r\n noMoreOptions: 'No additional options available'\r\n },\r\n captions: {\r\n off: 'Off',\r\n select: 'Select captions',\r\n fontSize: 'Font Size',\r\n fontFamily: 'Font Family',\r\n color: 'Text Color',\r\n backgroundColor: 'Background Color',\r\n opacity: 'Opacity'\r\n },\r\n fontSizes: {\r\n small: 'Small',\r\n normal: 'Normal',\r\n large: 'Large',\r\n xlarge: 'X-Large'\r\n },\r\n fontFamilies: {\r\n sansSerif: 'Sans-serif',\r\n serif: 'Serif',\r\n monospace: 'Monospace'\r\n },\r\n styleLabels: {\r\n textColor: 'Text Color',\r\n background: 'Background',\r\n font: 'Font',\r\n fontSize: 'Font Size',\r\n opacity: 'Opacity'\r\n },\r\n audioDescription: {\r\n enable: 'Enable audio description',\r\n disable: 'Disable audio description'\r\n },\r\n signLanguage: {\r\n show: 'Show sign language video',\r\n hide: 'Hide sign language video'\r\n },\r\n transcript: {\r\n title: 'Transcript',\r\n ariaLabel: 'Video Transcript',\r\n close: 'Close transcript',\r\n loading: 'Loading transcript...',\r\n noTranscript: 'No transcript available for this video.',\r\n settings: 'Transcript settings. Press Enter to open menu, or D to enable drag mode',\r\n keyboardDragMode: 'Toggle keyboard drag mode with arrow keys. Shortcut: D key',\r\n keyboardDragActive: '⌨️ Keyboard Drag Mode Active (Arrow keys to move, Shift+Arrows for large steps, D or ESC to exit)',\r\n dragResizePrompt: 'Press D to drag or R to resize. Use Home to reset position, Esc to close.',\r\n dragModeEnabled: 'Keyboard drag mode enabled. Use arrow keys to move, Shift+Arrow for larger steps. Press D or Esc to exit.',\r\n dragModeDisabled: 'Keyboard drag mode disabled.',\r\n enableDragMode: 'Enable drag mode. Shortcut: D key',\r\n disableDragMode: 'Disable drag mode. Shortcut: D key',\r\n enableDragModeAria: 'Enable toggle keyboard drag mode with arrow keys. Shortcut: D key',\r\n disableDragModeAria: 'Disable toggle keyboard drag mode with arrow keys. Shortcut: D key',\r\n resizeWindow: 'Resize Window',\r\n disableResizeWindow: 'Disable Resize Mode',\r\n enableResizeMode: 'Enable resize mode. Shortcut: R key',\r\n disableResizeMode: 'Disable resize mode. Shortcut: R key',\r\n enableResizeModeAria: 'Enable keyboard resize mode with arrow keys. Shortcut: R key',\r\n disableResizeModeAria: 'Disable keyboard resize mode with arrow keys. Shortcut: R key',\r\n resizeModeHint: 'Resize handles enabled. Drag edges or corners to adjust. Press Esc or R to exit.',\r\n resizeModeEnabled: 'Resize mode enabled. Drag edges or corners to adjust. Press Esc or R to exit.',\r\n resizeModeDisabled: 'Resize mode disabled.',\r\n positionReset: 'Transcript position reset.',\r\n styleTranscript: 'Open transcript style settings',\r\n closeMenu: 'Close Menu',\r\n styleTitle: 'Transcript Style',\r\n autoscroll: 'Autoscroll',\r\n settingsMenu: 'Transcript dialog settings',\r\n showTimestamps: 'Show timestamps',\r\n hideTimestamps: 'Hide timestamps',\r\n showTimestampsAria: 'Show timestamps in transcript',\r\n hideTimestampsAria: 'Hide timestamps in transcript'\r\n },\r\n settings: {\r\n title: 'Settings',\r\n quality: 'Quality',\r\n speed: 'Speed',\r\n captions: 'Captions',\r\n language: 'Language',\r\n reset: 'Reset to defaults',\r\n close: 'Close'\r\n },\r\n speeds: {\r\n normal: 'Normal'\r\n },\r\n time: {\r\n display: 'Time display',\r\n durationPrefix: 'Duration: ',\r\n of: 'of',\r\n hour: '{count} hour',\r\n hours: '{count} hours',\r\n minute: '{count} minute',\r\n minutes: '{count} minutes',\r\n second: '{count} second',\r\n seconds: '{count} seconds'\r\n },\r\n playlist: {\r\n title: 'Playlist',\r\n trackOf: 'Track {current} of {total}',\r\n nowPlaying: 'Now playing: Track {current} of {total}. {title}{artist}',\r\n by: ' by ',\r\n untitled: 'Untitled',\r\n trackUntitled: 'Track {number}',\r\n currentlyPlaying: 'Currently playing',\r\n notPlaying: 'Not playing',\r\n pressEnterPlay: 'Press Enter to play',\r\n pressEnterRestart: 'Press Enter to restart',\r\n keyboardInstructions: 'Playlist navigation: Use Up and Down arrow keys to move between tracks. Press Page Up or Page Down to skip 5 tracks. Press Home to go to first track, End to go to last track. Press Enter or Space to play the selected track.',\r\n endOfPlaylist: 'End of playlist. {current} of {total}.',\r\n beginningOfPlaylist: 'Beginning of playlist. 1 of {total}.',\r\n jumpedToLastTrack: 'Jumped to last track. {current} of {total}.',\r\n jumpedToFirstTrack: 'Jumped to first track. 1 of {total}.',\r\n firstTrack: 'First track. 1 of {total}.',\r\n lastTrack: 'Last track. {current} of {total}.'\r\n }\r\n};\r\n\r\n", "/**\r\n * Translation strings for VidPly\r\n * Lazily loads built-in language files to keep the base bundle small.\r\n */\r\n\r\nimport { en } from './languages/en.js';\r\n\r\nconst builtInLanguageLoaders = {\r\n de: () => import('./languages/de.js'),\r\n es: () => import('./languages/es.js'),\r\n fr: () => import('./languages/fr.js'),\r\n ja: () => import('./languages/ja.js')\r\n};\r\n\r\n/**\r\n * Returns the base translations that are always available in the bundle.\r\n * Currently this is English-only to minimize bundle size.\r\n */\r\nexport function getBaseTranslations() {\r\n return { en };\r\n}\r\n\r\n/**\r\n * Expose built-in language loaders so they can be loaded on demand.\r\n */\r\nexport function getBuiltInLanguageLoaders() {\r\n return builtInLanguageLoaders;\r\n}\r\n\r\n/**\r\n * Load a single built-in language asynchronously.\r\n * @param {string} lang Language code to load\r\n * @returns {Promise<Object|null>} Loaded translation object or null if unavailable\r\n */\r\nexport async function loadBuiltInTranslation(lang) {\r\n const loader = builtInLanguageLoaders[lang];\r\n if (!loader) return null;\r\n\r\n const module = await loader();\r\n return module[lang] || module.default || null;\r\n}\r\n\r\n/**\r\n * Legacy export for backwards compatibility (keeps API surface stable)\r\n * Note: Only English is included by default; other languages are loaded on demand.\r\n */\r\nexport const translations = getBaseTranslations();\r\n\r\n", "/**\r\n * Internationalization system\r\n */\r\n\r\nimport { getBaseTranslations, getBuiltInLanguageLoaders, loadBuiltInTranslation } from './translations.js';\r\n\r\nclass I18n {\r\n constructor() {\r\n this.currentLanguage = 'en';\r\n this.translations = getBaseTranslations();\r\n this.loadingPromises = new Map(); // Cache for loading promises\r\n this.builtInLanguageLoaders = getBuiltInLanguageLoaders();\r\n }\r\n\r\n setLanguage(lang) {\r\n if (this.translations[lang]) {\r\n this.currentLanguage = lang;\r\n } else {\r\n console.warn(`Language \"${lang}\" not found, falling back to English`);\r\n this.currentLanguage = 'en';\r\n }\r\n }\r\n\r\n getLanguage() {\r\n return this.currentLanguage;\r\n }\r\n\r\n /**\r\n * Ensure a language is available, loading built-ins on demand.\r\n * @param {string} lang Language code\r\n * @returns {Promise<string|null>} Normalized language code if available\r\n */\r\n async ensureLanguage(lang) {\r\n const normalizedLang = (lang || '').toLowerCase();\r\n if (!normalizedLang) return this.currentLanguage;\r\n\r\n if (this.translations[normalizedLang]) {\r\n return normalizedLang;\r\n }\r\n\r\n if (this.loadingPromises.has(normalizedLang)) {\r\n await this.loadingPromises.get(normalizedLang);\r\n return this.translations[normalizedLang] ? normalizedLang : null;\r\n }\r\n\r\n if (!this.builtInLanguageLoaders[normalizedLang]) {\r\n return null;\r\n }\r\n\r\n const loadPromise = (async () => {\r\n try {\r\n const loaded = await loadBuiltInTranslation(normalizedLang);\r\n if (loaded) {\r\n this.translations[normalizedLang] = loaded;\r\n }\r\n } catch (error) {\r\n console.warn(`Language \"${normalizedLang}\" failed to load:`, error);\r\n } finally {\r\n this.loadingPromises.delete(normalizedLang);\r\n }\r\n })();\r\n\r\n this.loadingPromises.set(normalizedLang, loadPromise);\r\n await loadPromise;\r\n\r\n return this.translations[normalizedLang] ? normalizedLang : null;\r\n }\r\n\r\n t(key, replacements = {}) {\r\n const keys = key.split('.');\r\n let value = this.translations[this.currentLanguage];\r\n \r\n for (const k of keys) {\r\n if (value && typeof value === 'object' && k in value) {\r\n value = value[k];\r\n } else {\r\n // Fallback to English\r\n value = this.translations.en;\r\n for (const fallbackKey of keys) {\r\n if (value && typeof value === 'object' && fallbackKey in value) {\r\n value = value[fallbackKey];\r\n } else {\r\n return key; // Return key if not found\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n \r\n // Replace placeholders\r\n if (typeof value === 'string') {\r\n Object.entries(replacements).forEach(([placeholder, replacement]) => {\r\n value = value.replace(new RegExp(`{${placeholder}}`, 'g'), replacement);\r\n });\r\n }\r\n \r\n return value;\r\n }\r\n\r\n addTranslation(lang, translations) {\r\n if (!this.translations[lang]) {\r\n this.translations[lang] = {};\r\n }\r\n Object.assign(this.translations[lang], translations);\r\n }\r\n\r\n /**\r\n * Load a language file from a URL (JSON or YAML)\r\n * @param {string} langCode - Language code (e.g., 'pt', 'it')\r\n * @param {string} url - URL to the language file (JSON or YAML)\r\n * @returns {Promise<void>}\r\n */\r\n async loadLanguageFromUrl(langCode, url) {\r\n // Return cached promise if already loading\r\n if (this.loadingPromises.has(url)) {\r\n return this.loadingPromises.get(url);\r\n }\r\n\r\n const loadPromise = (async () => {\r\n try {\r\n const response = await fetch(url);\r\n if (!response.ok) {\r\n throw new Error(`Failed to load language file: ${response.statusText}`);\r\n }\r\n\r\n const contentType = response.headers.get('content-type') || '';\r\n let translations;\r\n\r\n const buffer = await response.arrayBuffer();\r\n const utf8Text = new TextDecoder('utf-8').decode(buffer);\r\n\r\n if (contentType.includes('application/json') || url.endsWith('.json')) {\r\n translations = JSON.parse(utf8Text);\r\n } else if (contentType.includes('text/yaml') || contentType.includes('application/x-yaml') || url.endsWith('.yaml') || url.endsWith('.yml')) {\r\n // For YAML, we'll need to parse it\r\n // Note: This requires a YAML parser library in production\r\n // For now, we'll try to parse as JSON first, then show a warning\r\n try {\r\n // Try JSON first (in case server sends JSON with YAML content-type)\r\n translations = JSON.parse(utf8Text);\r\n } catch (e) {\r\n // If JSON parsing fails, try to use a YAML parser if available\r\n if (typeof window !== 'undefined' && window.jsyaml) {\r\n translations = window.jsyaml.load(utf8Text);\r\n } else {\r\n console.warn('YAML parsing requires js-yaml library. Please include it or use JSON format.');\r\n throw new Error('YAML parsing not available. Please use JSON format or include js-yaml library.');\r\n }\r\n }\r\n } else {\r\n // Try to parse as JSON by default\r\n translations = JSON.parse(utf8Text);\r\n }\r\n\r\n this.addTranslation(langCode, translations);\r\n return translations;\r\n } catch (error) {\r\n console.error(`Error loading language file from ${url}:`, error);\r\n throw error;\r\n } finally {\r\n // Remove from cache after loading completes\r\n this.loadingPromises.delete(url);\r\n }\r\n })();\r\n\r\n this.loadingPromises.set(url, loadPromise);\r\n return loadPromise;\r\n }\r\n\r\n /**\r\n * Load multiple language files from URLs\r\n * @param {Object} languageMap - Object mapping language codes to URLs\r\n * @returns {Promise<void>}\r\n */\r\n async loadLanguagesFromUrls(languageMap) {\r\n const promises = Object.entries(languageMap).map(([langCode, url]) =>\r\n this.loadLanguageFromUrl(langCode, url)\r\n );\r\n await Promise.all(promises);\r\n }\r\n}\r\n\r\nexport const i18n = new I18n();\r\n\r\n", "/**\r\n * Time formatting and conversion utilities\r\n */\r\n\r\nimport {i18n} from '../i18n/i18n.js';\r\n\r\nexport const TimeUtils = {\r\n /**\r\n * Format seconds to time string (HH:MM:SS or MM:SS)\r\n */\r\n formatTime(seconds, alwaysShowHours = false) {\r\n if (!isFinite(seconds) || seconds < 0) {\r\n return alwaysShowHours ? '00:00:00' : '00:00';\r\n }\r\n \r\n const hours = Math.floor(seconds / 3600);\r\n const minutes = Math.floor((seconds % 3600) / 60);\r\n const secs = Math.floor(seconds % 60);\r\n \r\n const pad = (num) => String(num).padStart(2, '0');\r\n \r\n if (hours > 0 || alwaysShowHours) {\r\n return `${pad(hours)}:${pad(minutes)}:${pad(secs)}`;\r\n }\r\n \r\n return `${pad(minutes)}:${pad(secs)}`;\r\n },\r\n\r\n /**\r\n * Parse time string to seconds\r\n */\r\n parseTime(timeString) {\r\n const parts = timeString.split(':').map(p => parseInt(p, 10));\r\n \r\n if (parts.length === 3) {\r\n // HH:MM:SS\r\n return parts[0] * 3600 + parts[1] * 60 + parts[2];\r\n } else if (parts.length === 2) {\r\n // MM:SS\r\n return parts[0] * 60 + parts[1];\r\n } else if (parts.length === 1) {\r\n // SS\r\n return parts[0];\r\n }\r\n \r\n return 0;\r\n },\r\n\r\n /**\r\n * Format seconds to readable duration\r\n */\r\n formatDuration(seconds) {\r\n if (!isFinite(seconds) || seconds < 0) {\r\n return i18n.t('time.seconds', { count: 0 });\r\n }\r\n \r\n const hours = Math.floor(seconds / 3600);\r\n const minutes = Math.floor((seconds % 3600) / 60);\r\n const secs = Math.floor(seconds % 60);\r\n \r\n const parts = [];\r\n \r\n if (hours > 0) {\r\n const key = hours === 1 ? 'time.hour' : 'time.hours';\r\n parts.push(i18n.t(key, { count: hours }));\r\n }\r\n if (minutes > 0) {\r\n const key = minutes === 1 ? 'time.minute' : 'time.minutes';\r\n parts.push(i18n.t(key, { count: minutes }));\r\n }\r\n if (secs > 0 || parts.length === 0) {\r\n const key = secs === 1 ? 'time.second' : 'time.seconds';\r\n parts.push(i18n.t(key, { count: secs }));\r\n }\r\n \r\n return parts.join(', ');\r\n },\r\n\r\n /**\r\n * Format percentage\r\n */\r\n formatPercentage(value, total) {\r\n if (total === 0) return 0;\r\n return Math.round((value / total) * 100);\r\n }\r\n};\r\n\r\n", "/**\r\n * SVG Icon Library for VidPly\r\n * Optimized with common viewBox and fill attributes\r\n */\r\n\r\n// SVG paths only (viewBox and fill added by wrapper)\r\nconst iconPaths = {\r\n play: `<path d=\"M8 5v14l11-7z\"/>`,\r\n\r\n pause: `<path d=\"M6 4h4v16H6V4zm8 0h4v16h-4V4z\"/>`,\r\n\r\n stop: `<rect x=\"6\" y=\"6\" width=\"12\" height=\"12\"/>`,\r\n\r\n rewind: `<path d=\"M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z\"/>`,\r\n\r\n forward: `<path d=\"M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z\"/>`,\r\n\r\n skipPrevious: `<path d=\"M6 6h2v12H6V6zm3 6l8.5 6V6L9 12z\"/>`,\r\n\r\n skipNext: `<path d=\"M16 6h2v12h-2V6zM6 6l8.5 6L6 18V6z\"/>`,\r\n\r\n restart: `<path d=\"M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z\"/>`,\r\n\r\n volumeHigh: `<path d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"/>`,\r\n\r\n volumeMedium: `<path d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z\"/>`,\r\n\r\n volumeLow: `<path d=\"M7 9v6h4l5 5V4l-5 5H7z\"/>`,\r\n\r\n volumeMuted: `<path d=\"M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z\"/>`,\r\n\r\n fullscreen: `<path d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"/>`,\r\n\r\n fullscreenExit: `<path d=\"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z\"/>`,\r\n\r\n settings: `<path d=\"M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94L14.4 2.81c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z\"/>`,\r\n\r\n captions: `<path d=\"M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z\"/>`,\r\n\r\n captionsOff: `<path d=\"M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z\"/><path d=\"M0 0h24v24H0z\" fill=\"none\"/>`,\r\n\r\n pip: `<path d=\"M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03z\"/>`,\r\n\r\n speed: `<path d=\"M20.38 8.57l-1.23 1.85a8 8 0 0 1-.22 7.58H5.07A8 8 0 0 1 15.58 6.85l1.85-1.23A10 10 0 0 0 3.35 19a2 2 0 0 0 1.72 1h13.85a2 2 0 0 0 1.74-1 10 10 0 0 0-.27-10.44z\"/><path d=\"M10.59 15.41a2 2 0 0 0 2.83 0l5.66-8.49-8.49 5.66a2 2 0 0 0 0 2.83z\"/>`,\r\n\r\n close: `<path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/>`,\r\n\r\n check: `<path d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"/>`,\r\n\r\n loading: `<path d=\"M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z\"/>`,\r\n\r\n error: `<path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/>`,\r\n\r\n playlist: `<path d=\"M15 6H3v2h12V6zm0 4H3v2h12v-2zM3 16h8v-2H3v2zM17 6v8.18c-.31-.11-.65-.18-1-.18-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3V8h3V6h-5z\"/>`,\r\n\r\n hd: `<path d=\"M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-8 12H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11v6zm7-1c0 .55-.45 1-1 1h-.75v1.5h-1.5V15H14c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v4zm-3.5-.5h2v-3h-2v3z\"/>`,\r\n\r\n transcript: `<path d=\"M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z\"/>`,\r\n\r\n chapters: `<path d=\"M3 5h2v2H3V5zm0 4h2v2H3V9zm0 4h2v2H3v-2zm0 4h2v2H3v-2zM7 5h14v2H7V5zm0 4h14v2H7V9zm0 4h14v2H7v-2zm0 4h14v2H7v-2z\"/>`,\r\n\r\n audioDescription: `<rect x=\"2\" y=\"5\" width=\"20\" height=\"14\" rx=\"2\" fill=\"#ffffff\" stroke=\"#ffffff\" stroke-width=\"2\"/><text x=\"12\" y=\"16\" font-family=\"Arial, sans-serif\" font-size=\"10\" font-weight=\"bold\" text-anchor=\"middle\" fill=\"#1a1a1a\">AD</text>`,\r\n \r\n audioDescriptionOn: `<rect x=\"2\" y=\"5\" width=\"20\" height=\"14\" rx=\"2\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"/><text x=\"12\" y=\"16\" font-family=\"Arial, sans-serif\" font-size=\"10\" font-weight=\"bold\" text-anchor=\"middle\" fill=\"currentColor\">AD</text>`,\r\n\r\n signLanguage: `<g transform=\"scale(1.5)\"><path d=\"M16 11.3c-.1-.9-4.8 1.3-5.4 1.1-2.6-1 5.8-1.3 5.1-2.9s-5.1 1.5-6 1.4C6.5 9.4 16.5 9.1 13.5 8c-1.9-.6-8.8 2.9-6.8.4.7-.6.7-1.9-.7-1.7-9.7 7.2-.7 12.2 8.8 7 0-1.3-3.5.4-4.1.4-2.6 0 5.6-2 5.4-3ZM3.9 7.8c3.2-4.2 3.7 1.2 6 .1s.2-.2.2-.3c.7-2.7 2.5-7.5-1.5-1.3-1.6 0 1.1-4 1-4.6C8.9-1 7.3 4.4 7.2 4.9c-1.6.7-.9-1.4-.7-1.5 3-6-.6-3.1-.9.4-2.5 1.8 0-2.8 0-3.5C2.8-.9 4 9.4 1.1 4.9S.1 4.6 0 5c-.4 2.7 2.6 7.2 3.9 2.8Z\"/></g>`,\r\n\r\n signLanguageOn: `<g transform=\"scale(1.5)\"><path d=\"M16 11.3c-.1-.9-4.8 1.3-5.4 1.1-2.6-1 5.8-1.3 5.1-2.9s-5.1 1.5-6 1.4C6.5 9.4 16.5 9.1 13.5 8c-1.9-.6-8.8 2.9-6.8.4.7-.6.7-1.9-.7-1.7-9.7 7.2-.7 12.2 8.8 7 0-1.3-3.5.4-4.1.4-2.6 0 5.6-2 5.4-3ZM3.9 7.8c3.2-4.2 3.7 1.2 6 .1s.2-.2.2-.3c.7-2.7 2.5-7.5-1.5-1.3-1.6 0 1.1-4 1-4.6C8.9-1 7.3 4.4 7.2 4.9c-1.6.7-.9-1.4-.7-1.5 3-6-.6-3.1-.9.4-2.5 1.8 0-2.8 0-3.5C2.8-.9 4 9.4 1.1 4.9S.1 4.6 0 5c-.4 2.7 2.6 7.2 3.9 2.8Z\"/></g>`,\r\n\r\n music: `<path d=\"M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7zm-1.5 16c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z\"/>`,\r\n\r\n moreVertical: `<path d=\"M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z\"/>`,\r\n\r\n move: `<path d=\"M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z\"/>`,\r\n\r\n resize: `<path d=\"M21.71 11.29l-9-9c-.39-.39-1.02-.39-1.41 0l-9 9c-.39.39-.39 1.02 0 1.41l9 9c.39.39 1.02.39 1.41 0l9-9c.39-.38.39-1.01 0-1.41zM14 14.5V12h-4v2.5L7 11l3-3.5V10h4V7.5l3 3.5-3 3.5z\"/>`,\r\n\r\n clock: `<path d=\"M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z\"/><path d=\"M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z\"/>`\r\n};\r\n\r\n// Optimized wrapper that adds common SVG attributes\r\nconst svgWrapper = (paths) => `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\">${paths}</svg>`;\r\n\r\n// Export Icons object with SVG wrappers\r\nexport const Icons = Object.fromEntries(\r\n Object.entries(iconPaths).map(([key, value]) => [key, svgWrapper(value)])\r\n);\r\n\r\nexport function getIcon(name) {\r\n return Icons[name] || Icons.play;\r\n}\r\n\r\nexport function createIconElement(name, className = '') {\r\n const wrapper = document.createElement('span');\r\n wrapper.className = `vidply-icon ${className}`.trim();\r\n wrapper.innerHTML = getIcon(name);\r\n wrapper.setAttribute('aria-hidden', 'true');\r\n return wrapper;\r\n}\r\n\r\n/**\r\n * Create the large centered play button overlay (complete SVG)\r\n * @returns {SVGElement} Complete SVG element with circle background and play icon\r\n */\r\nexport function createPlayOverlay() {\r\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\r\n svg.setAttribute('class', 'vidply-play-overlay');\r\n svg.setAttribute('viewBox', '0 0 80 80');\r\n svg.setAttribute('width', '80');\r\n svg.setAttribute('height', '80');\r\n svg.setAttribute('aria-hidden', 'true');\r\n svg.setAttribute('role', 'presentation');\r\n svg.style.cursor = 'pointer';\r\n\r\n // Create filter for drop shadow\r\n const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\r\n const filterId = `vidply-play-shadow-${Math.random().toString(36).substr(2, 9)}`;\r\n const filter = document.createElementNS('http://www.w3.org/2000/svg', 'filter');\r\n filter.setAttribute('id', filterId);\r\n filter.setAttribute('x', '-50%');\r\n filter.setAttribute('y', '-50%');\r\n filter.setAttribute('width', '200%');\r\n filter.setAttribute('height', '200%');\r\n\r\n const feGaussianBlur = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');\r\n feGaussianBlur.setAttribute('in', 'SourceAlpha');\r\n feGaussianBlur.setAttribute('stdDeviation', '3');\r\n\r\n const feOffset = document.createElementNS('http://www.w3.org/2000/svg', 'feOffset');\r\n feOffset.setAttribute('dx', '0');\r\n feOffset.setAttribute('dy', '2');\r\n feOffset.setAttribute('result', 'offsetblur');\r\n\r\n const feComponentTransfer = document.createElementNS('http://www.w3.org/2000/svg', 'feComponentTransfer');\r\n const feFuncA = document.createElementNS('http://www.w3.org/2000/svg', 'feFuncA');\r\n feFuncA.setAttribute('type', 'linear');\r\n feFuncA.setAttribute('slope', '0.3');\r\n feComponentTransfer.appendChild(feFuncA);\r\n\r\n const feMerge = document.createElementNS('http://www.w3.org/2000/svg', 'feMerge');\r\n const feMergeNode1 = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');\r\n const feMergeNode2 = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');\r\n feMergeNode2.setAttribute('in', 'SourceGraphic');\r\n feMerge.appendChild(feMergeNode1);\r\n feMerge.appendChild(feMergeNode2);\r\n\r\n filter.appendChild(feGaussianBlur);\r\n filter.appendChild(feOffset);\r\n filter.appendChild(feComponentTransfer);\r\n filter.appendChild(feMerge);\r\n defs.appendChild(filter);\r\n svg.appendChild(defs);\r\n\r\n // White circle background\r\n const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n circle.setAttribute('cx', '40');\r\n circle.setAttribute('cy', '40');\r\n circle.setAttribute('r', '40');\r\n circle.setAttribute('fill', 'rgba(255, 255, 255, 0.95)');\r\n circle.setAttribute('filter', `url(#${filterId})`);\r\n circle.setAttribute('class', 'vidply-play-overlay-bg');\r\n svg.appendChild(circle);\r\n\r\n // Play icon triangle (centered with optical adjustment)\r\n const playTriangle = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');\r\n playTriangle.setAttribute('points', '32,28 32,52 54,40');\r\n playTriangle.setAttribute('fill', '#0a406e');\r\n playTriangle.setAttribute('class', 'vidply-play-overlay-icon');\r\n svg.appendChild(playTriangle);\r\n\r\n return svg;\r\n}\r\n\r\n", "/**\r\n * Focus management utilities\r\n */\r\n\r\n/**\r\n * Safely focus an element after DOM updates\r\n * @param {HTMLElement} element - Element to focus\r\n * @param {Object} options - Focus options\r\n * @param {number} options.delay - Delay in milliseconds (default: 0)\r\n * @param {boolean} options.preventScroll - Prevent scroll on focus (default: true)\r\n */\r\nexport function focusElement(element, { delay = 0, preventScroll = true } = {}) {\r\n if (!element) return;\r\n \r\n requestAnimationFrame(() => {\r\n setTimeout(() => {\r\n if (element && document.contains(element)) {\r\n element.focus({ preventScroll });\r\n }\r\n }, delay);\r\n });\r\n}\r\n\r\n/**\r\n * Focus first element matching selector in container\r\n * @param {HTMLElement} container - Container to search in\r\n * @param {string} selector - CSS selector\r\n * @param {Object} options - Focus options\r\n */\r\nexport function focusFirstElement(container, selector, options = {}) {\r\n if (!container) return;\r\n const element = container.querySelector(selector);\r\n if (element) {\r\n focusElement(element, options);\r\n }\r\n}\r\n\r\n", "/**\r\n * StorageManager - Handles persistent storage of user preferences\r\n */\r\n\r\nexport class StorageManager {\r\n constructor(namespace = 'vidply') {\r\n this.namespace = namespace;\r\n this.storage = this.isStorageAvailable() ? localStorage : null;\r\n }\r\n\r\n /**\r\n * Check if localStorage is available\r\n */\r\n isStorageAvailable() {\r\n try {\r\n const test = '__storage_test__';\r\n localStorage.setItem(test, test);\r\n localStorage.removeItem(test);\r\n return true;\r\n } catch (e) {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Get a namespaced key\r\n */\r\n getKey(key) {\r\n return `${this.namespace}_${key}`;\r\n }\r\n\r\n /**\r\n * Save a value to storage\r\n */\r\n set(key, value) {\r\n if (!this.storage) return false;\r\n \r\n try {\r\n const namespacedKey = this.getKey(key);\r\n this.storage.setItem(namespacedKey, JSON.stringify(value));\r\n return true;\r\n } catch (e) {\r\n console.warn('Failed to save to localStorage:', e);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Get a value from storage\r\n */\r\n get(key, defaultValue = null) {\r\n if (!this.storage) return defaultValue;\r\n \r\n try {\r\n const namespacedKey = this.getKey(key);\r\n const value = this.storage.getItem(namespacedKey);\r\n return value ? JSON.parse(value) : defaultValue;\r\n } catch (e) {\r\n console.warn('Failed to read from localStorage:', e);\r\n return defaultValue;\r\n }\r\n }\r\n\r\n /**\r\n * Remove a value from storage\r\n */\r\n remove(key) {\r\n if (!this.storage) return false;\r\n \r\n try {\r\n const namespacedKey = this.getKey(key);\r\n this.storage.removeItem(namespacedKey);\r\n return true;\r\n } catch (e) {\r\n console.warn('Failed to remove from localStorage:', e);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all namespaced values\r\n */\r\n clear() {\r\n if (!this.storage) return false;\r\n \r\n try {\r\n const keys = Object.keys(this.storage);\r\n keys.forEach(key => {\r\n if (key.startsWith(this.namespace)) {\r\n this.storage.removeItem(key);\r\n }\r\n });\r\n return true;\r\n } catch (e) {\r\n console.warn('Failed to clear localStorage:', e);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Save transcript preferences\r\n */\r\n saveTranscriptPreferences(preferences) {\r\n return this.set('transcript_preferences', preferences);\r\n }\r\n\r\n /**\r\n * Get transcript preferences\r\n */\r\n getTranscriptPreferences() {\r\n return this.get('transcript_preferences', null);\r\n }\r\n\r\n /**\r\n * Save caption preferences\r\n */\r\n saveCaptionPreferences(preferences) {\r\n return this.set('caption_preferences', preferences);\r\n }\r\n\r\n /**\r\n * Get caption preferences\r\n */\r\n getCaptionPreferences() {\r\n return this.get('caption_preferences', null);\r\n }\r\n\r\n /**\r\n * Save player preferences (volume, speed, etc.)\r\n */\r\n savePlayerPreferences(preferences) {\r\n return this.set('player_preferences', preferences);\r\n }\r\n\r\n /**\r\n * Get player preferences\r\n */\r\n getPlayerPreferences() {\r\n return this.get('player_preferences', null);\r\n }\r\n\r\n /**\r\n * Save sign language preferences (position and size)\r\n */\r\n saveSignLanguagePreferences(preferences) {\r\n return this.set('sign_language_preferences', preferences);\r\n }\r\n\r\n /**\r\n * Get sign language preferences\r\n */\r\n getSignLanguagePreferences() {\r\n return this.get('sign_language_preferences', null);\r\n }\r\n}\r\n\r\n", "/**\r\n * DraggableResizable Utility\r\n * Provides shared drag and resize functionality for floating windows/elements\r\n */\r\n\r\nexport class DraggableResizable {\r\n constructor(element, options = {}) {\r\n this.element = element;\r\n this.options = {\r\n dragHandle: null, // Element to use as drag handle (defaults to element itself)\r\n resizeHandles: [], // Array of resize handle elements\r\n onDragStart: null,\r\n onDrag: null,\r\n onDragEnd: null,\r\n onResizeStart: null,\r\n onResize: null,\r\n onResizeEnd: null,\r\n constrainToViewport: true, // Allow movement outside viewport?\r\n minWidth: 150,\r\n minHeight: 100,\r\n maintainAspectRatio: false,\r\n keyboardDragKey: 'd',\r\n keyboardResizeKey: 'r',\r\n keyboardStep: 5,\r\n keyboardStepLarge: 10,\r\n maxWidth: null,\r\n maxHeight: null,\r\n pointerResizeIndicatorText: null,\r\n onPointerResizeToggle: null,\r\n classPrefix: 'draggable',\r\n storage: null, // StorageManager instance for saving position/size\r\n storageKey: null, // Key for localStorage (if storage is provided)\r\n ...options\r\n };\r\n\r\n // State\r\n this.isDragging = false;\r\n this.isResizing = false;\r\n this.resizeDirection = null;\r\n this.dragOffsetX = 0;\r\n this.dragOffsetY = 0;\r\n this.positionOffsetX = 0;\r\n this.positionOffsetY = 0;\r\n this.initialMouseX = 0;\r\n this.initialMouseY = 0;\r\n this.needsPositionConversion = false;\r\n this.resizeStartX = 0;\r\n this.resizeStartY = 0;\r\n this.resizeStartWidth = 0;\r\n this.resizeStartHeight = 0;\r\n this.resizeStartLeft = 0;\r\n this.resizeStartTop = 0;\r\n this.keyboardDragMode = false;\r\n this.keyboardResizeMode = false;\r\n this.pointerResizeMode = false;\r\n this.manuallyPositioned = false; // Flag to track if user has manually moved/resized\r\n this.resizeHandlesManaged = new Map();\r\n this.resizeIndicatorElement = null;\r\n\r\n // Event handlers\r\n this.handlers = {\r\n mousedown: this.onMouseDown.bind(this),\r\n mousemove: this.onMouseMove.bind(this),\r\n mouseup: this.onMouseUp.bind(this),\r\n touchstart: this.onTouchStart.bind(this),\r\n touchmove: this.onTouchMove.bind(this),\r\n touchend: this.onTouchEnd.bind(this),\r\n keydown: this.onKeyDown.bind(this),\r\n resizeHandleMousedown: this.onResizeHandleMouseDown.bind(this)\r\n };\r\n\r\n this.init();\r\n }\r\n\r\n hasManagedResizeHandles() {\r\n return Array.from(this.resizeHandlesManaged.values()).some(Boolean);\r\n }\r\n\r\n storeOriginalHandleDisplay(handle) {\r\n if (!handle.dataset.originalDisplay) {\r\n handle.dataset.originalDisplay = handle.style.display || '';\r\n }\r\n }\r\n\r\n hideResizeHandle(handle) {\r\n handle.style.display = 'none';\r\n handle.setAttribute('aria-hidden', 'true');\r\n }\r\n\r\n showResizeHandle(handle) {\r\n const original = handle.dataset.originalDisplay !== undefined ? handle.dataset.originalDisplay : '';\r\n handle.style.display = original;\r\n handle.removeAttribute('aria-hidden');\r\n }\r\n\r\n setManagedHandlesVisible(visible) {\r\n if (!this.options.resizeHandles || this.options.resizeHandles.length === 0) {\r\n return;\r\n }\r\n\r\n this.options.resizeHandles.forEach(handle => {\r\n if (!this.resizeHandlesManaged.get(handle)) {\r\n return;\r\n }\r\n\r\n if (visible) {\r\n this.showResizeHandle(handle);\r\n } else {\r\n this.hideResizeHandle(handle);\r\n }\r\n });\r\n }\r\n\r\n init() {\r\n const dragHandle = this.options.dragHandle || this.element;\r\n \r\n // Drag events\r\n dragHandle.addEventListener('mousedown', this.handlers.mousedown);\r\n dragHandle.addEventListener('touchstart', this.handlers.touchstart);\r\n \r\n // Document-level move/up events\r\n document.addEventListener('mousemove', this.handlers.mousemove);\r\n document.addEventListener('mouseup', this.handlers.mouseup);\r\n document.addEventListener('touchmove', this.handlers.touchmove, { passive: false });\r\n document.addEventListener('touchend', this.handlers.touchend);\r\n \r\n // Keyboard events\r\n this.element.addEventListener('keydown', this.handlers.keydown);\r\n \r\n // Resize handles\r\n if (this.options.resizeHandles && this.options.resizeHandles.length > 0) {\r\n this.options.resizeHandles.forEach(handle => {\r\n handle.addEventListener('mousedown', this.handlers.resizeHandleMousedown);\r\n handle.addEventListener('touchstart', this.handlers.resizeHandleMousedown);\r\n\r\n const managed = handle.dataset.vidplyManagedResize === 'true';\r\n this.resizeHandlesManaged.set(handle, managed);\r\n if (managed) {\r\n this.storeOriginalHandleDisplay(handle);\r\n this.hideResizeHandle(handle);\r\n }\r\n });\r\n }\r\n }\r\n\r\n onMouseDown(e) {\r\n // Don't drag if clicking on resize handle\r\n if (e.target.classList.contains(`${this.options.classPrefix}-resize-handle`)) {\r\n return;\r\n }\r\n \r\n // Call custom handler if provided\r\n if (this.options.onDragStart && !this.options.onDragStart(e)) {\r\n return;\r\n }\r\n\r\n this.startDragging(e.clientX, e.clientY);\r\n e.preventDefault();\r\n }\r\n\r\n onTouchStart(e) {\r\n // Don't drag if touching resize handle\r\n if (e.target.classList.contains(`${this.options.classPrefix}-resize-handle`)) {\r\n return;\r\n }\r\n \r\n // Call custom handler if provided\r\n if (this.options.onDragStart && !this.options.onDragStart(e)) {\r\n return;\r\n }\r\n\r\n const touch = e.touches[0];\r\n this.startDragging(touch.clientX, touch.clientY);\r\n }\r\n\r\n onResizeHandleMouseDown(e) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n \r\n const handle = e.target;\r\n this.resizeDirection = handle.getAttribute('data-direction');\r\n \r\n const clientX = e.clientX || e.touches?.[0]?.clientX;\r\n const clientY = e.clientY || e.touches?.[0]?.clientY;\r\n \r\n this.startResizing(clientX, clientY);\r\n }\r\n\r\n onMouseMove(e) {\r\n if (this.isDragging) {\r\n this.drag(e.clientX, e.clientY);\r\n e.preventDefault();\r\n } else if (this.isResizing) {\r\n this.resize(e.clientX, e.clientY);\r\n e.preventDefault();\r\n }\r\n }\r\n\r\n onTouchMove(e) {\r\n if (this.isDragging || this.isResizing) {\r\n const touch = e.touches[0];\r\n if (this.isDragging) {\r\n this.drag(touch.clientX, touch.clientY);\r\n } else {\r\n this.resize(touch.clientX, touch.clientY);\r\n }\r\n e.preventDefault();\r\n }\r\n }\r\n\r\n onMouseUp() {\r\n if (this.isDragging) {\r\n this.stopDragging();\r\n } else if (this.isResizing) {\r\n this.stopResizing();\r\n }\r\n }\r\n\r\n onTouchEnd() {\r\n if (this.isDragging) {\r\n this.stopDragging();\r\n } else if (this.isResizing) {\r\n this.stopResizing();\r\n }\r\n }\r\n\r\n onKeyDown(e) {\r\n // Toggle drag mode\r\n if (e.key.toLowerCase() === this.options.keyboardDragKey.toLowerCase()) {\r\n e.preventDefault();\r\n this.toggleKeyboardDragMode();\r\n return;\r\n }\r\n\r\n // Toggle resize mode\r\n if (e.key.toLowerCase() === this.options.keyboardResizeKey.toLowerCase()) {\r\n e.preventDefault();\r\n if (this.hasManagedResizeHandles()) {\r\n this.togglePointerResizeMode();\r\n } else {\r\n this.toggleKeyboardResizeMode();\r\n }\r\n return;\r\n }\r\n\r\n // Exit modes with Escape\r\n if (e.key === 'Escape') {\r\n if (this.pointerResizeMode) {\r\n e.preventDefault();\r\n this.disablePointerResizeMode();\r\n return;\r\n }\r\n if (this.keyboardDragMode || this.keyboardResizeMode) {\r\n e.preventDefault();\r\n this.disableKeyboardDragMode();\r\n this.disableKeyboardResizeMode();\r\n return;\r\n }\r\n }\r\n\r\n // Arrow keys for drag/resize\r\n if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.key)) {\r\n if (this.keyboardDragMode) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.keyboardDrag(e.key, e.shiftKey);\r\n } else if (this.keyboardResizeMode) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.keyboardResize(e.key, e.shiftKey);\r\n }\r\n }\r\n\r\n // Home key to reset position\r\n if (e.key === 'Home' && (this.keyboardDragMode || this.keyboardResizeMode)) {\r\n e.preventDefault();\r\n this.resetPosition();\r\n }\r\n }\r\n\r\n startDragging(clientX, clientY) {\r\n // Get current rendered position BEFORE any changes\r\n const rect = this.element.getBoundingClientRect();\r\n \r\n // Convert position to left/top IMMEDIATELY (before setting any state)\r\n // Check if element is using right/bottom/transform positioning\r\n const computedStyle = window.getComputedStyle(this.element);\r\n const needsConversion = computedStyle.right !== 'auto' || \r\n computedStyle.bottom !== 'auto' || \r\n computedStyle.transform !== 'none';\r\n \r\n this.positionOffsetX = 0;\r\n this.positionOffsetY = 0;\r\n\r\n if (needsConversion) {\r\n // Determine the correct left/top values based on position type\r\n let targetLeft, targetTop;\r\n \r\n if (computedStyle.position === 'absolute') {\r\n // position: absolute uses container-relative coordinates\r\n const offsetParent = this.element.offsetParent || document.body;\r\n const parentRect = offsetParent.getBoundingClientRect();\r\n targetLeft = rect.left - parentRect.left;\r\n targetTop = rect.top - parentRect.top;\r\n this.positionOffsetX = parentRect.left;\r\n this.positionOffsetY = parentRect.top;\r\n } else if (computedStyle.position === 'fixed') {\r\n const parsedLeft = parseFloat(computedStyle.left);\r\n const parsedTop = parseFloat(computedStyle.top);\r\n const hasLeft = Number.isFinite(parsedLeft);\r\n const hasTop = Number.isFinite(parsedTop);\r\n targetLeft = hasLeft ? parsedLeft : rect.left;\r\n targetTop = hasTop ? parsedTop : rect.top;\r\n this.positionOffsetX = rect.left - targetLeft;\r\n this.positionOffsetY = rect.top - targetTop;\r\n } else {\r\n // fallback: treat as viewport-relative\r\n targetLeft = rect.left;\r\n targetTop = rect.top;\r\n this.positionOffsetX = rect.left - targetLeft;\r\n this.positionOffsetY = rect.top - targetTop;\r\n }\r\n \r\n // Build complete style update atomically\r\n const currentCssText = this.element.style.cssText;\r\n let newCssText = currentCssText\r\n .split(';')\r\n .filter(rule => {\r\n const trimmed = rule.trim();\r\n // Filter out empty rules\r\n if (!trimmed) return false;\r\n \r\n const colonIndex = trimmed.indexOf(':');\r\n if (colonIndex === -1) return false;\r\n \r\n const property = trimmed.substring(0, colonIndex).trim();\r\n const value = trimmed.substring(colonIndex + 1).trim();\r\n \r\n // Skip if value is empty or just whitespace (this catches empty border properties)\r\n if (!value || value === '') return false;\r\n \r\n // Skip positioning properties\r\n if (property === 'right' || property === 'bottom' || property === 'transform' ||\r\n property === 'left' || property === 'top' || property === 'inset') {\r\n return false;\r\n }\r\n \r\n // Skip border-image properties (these can have empty values that cause parse errors)\r\n if (property.startsWith('border-image')) {\r\n return false;\r\n }\r\n \r\n return true;\r\n })\r\n .join('; ');\r\n \r\n if (newCssText) newCssText += '; ';\r\n newCssText += `left: ${targetLeft}px; top: ${targetTop}px; right: auto; bottom: auto; transform: none`;\r\n \r\n // Apply all at once\r\n this.element.style.cssText = newCssText;\r\n }\r\n \r\n // Now calculate offsets based on CURRENT position (after conversion)\r\n // Re-get rect after potential position change\r\n const finalRect = this.element.getBoundingClientRect();\r\n this.dragOffsetX = clientX - finalRect.left;\r\n this.dragOffsetY = clientY - finalRect.top;\r\n \r\n this.isDragging = true;\r\n this.element.classList.add(`${this.options.classPrefix}-dragging`);\r\n document.body.style.cursor = 'grabbing';\r\n document.body.style.userSelect = 'none';\r\n }\r\n\r\n drag(clientX, clientY) {\r\n if (!this.isDragging) return;\r\n\r\n // Calculate new position: current mouse position minus the offset where user clicked\r\n let newX = clientX - this.dragOffsetX - this.positionOffsetX;\r\n let newY = clientY - this.dragOffsetY - this.positionOffsetY;\r\n \r\n // Constrain to viewport if needed\r\n if (this.options.constrainToViewport) {\r\n const rect = this.element.getBoundingClientRect();\r\n const viewportWidth = document.documentElement.clientWidth;\r\n const viewportHeight = document.documentElement.clientHeight;\r\n \r\n // Keep at least 100px visible\r\n const minVisible = 100;\r\n const minX = -(rect.width - minVisible);\r\n const minY = -(rect.height - minVisible);\r\n const maxX = viewportWidth - minVisible;\r\n const maxY = viewportHeight - minVisible;\r\n \r\n newX = Math.max(minX, Math.min(newX, maxX));\r\n newY = Math.max(minY, Math.min(newY, maxY));\r\n }\r\n \r\n this.element.style.left = `${newX}px`;\r\n this.element.style.top = `${newY}px`;\r\n \r\n // Call custom handler if provided\r\n if (this.options.onDrag) {\r\n this.options.onDrag({ x: newX, y: newY });\r\n }\r\n }\r\n\r\n stopDragging() {\r\n this.isDragging = false;\r\n this.element.classList.remove(`${this.options.classPrefix}-dragging`);\r\n document.body.style.cursor = '';\r\n document.body.style.userSelect = '';\r\n \r\n // Mark as manually positioned\r\n this.manuallyPositioned = true;\r\n \r\n // Call custom handler if provided\r\n if (this.options.onDragEnd) {\r\n this.options.onDragEnd();\r\n }\r\n }\r\n\r\n startResizing(clientX, clientY) {\r\n this.isResizing = true;\r\n this.resizeStartX = clientX;\r\n this.resizeStartY = clientY;\r\n \r\n const rect = this.element.getBoundingClientRect();\r\n this.resizeStartWidth = rect.width;\r\n this.resizeStartHeight = rect.height;\r\n this.resizeStartLeft = rect.left;\r\n this.resizeStartTop = rect.top;\r\n \r\n this.element.classList.add(`${this.options.classPrefix}-resizing`);\r\n document.body.style.userSelect = 'none';\r\n \r\n // Call custom handler if provided\r\n if (this.options.onResizeStart) {\r\n this.options.onResizeStart();\r\n }\r\n }\r\n\r\n resize(clientX, clientY) {\r\n if (!this.isResizing) return;\r\n\r\n const deltaX = clientX - this.resizeStartX;\r\n const deltaY = clientY - this.resizeStartY;\r\n \r\n let newWidth = this.resizeStartWidth;\r\n let newHeight = this.resizeStartHeight;\r\n let newLeft = this.resizeStartLeft;\r\n let newTop = this.resizeStartTop;\r\n\r\n // Handle horizontal resizing\r\n if (this.resizeDirection.includes('e')) {\r\n newWidth = Math.max(this.options.minWidth, this.resizeStartWidth + deltaX);\r\n }\r\n if (this.resizeDirection.includes('w')) {\r\n const proposedWidth = Math.max(this.options.minWidth, this.resizeStartWidth - deltaX);\r\n newLeft = this.resizeStartLeft + (this.resizeStartWidth - proposedWidth);\r\n newWidth = proposedWidth;\r\n }\r\n\r\n const maxWidthOption = typeof this.options.maxWidth === 'function'\r\n ? this.options.maxWidth()\r\n : this.options.maxWidth;\r\n if (Number.isFinite(maxWidthOption)) {\r\n const clampedWidth = Math.min(newWidth, maxWidthOption);\r\n if (clampedWidth !== newWidth && this.resizeDirection.includes('w')) {\r\n newLeft += newWidth - clampedWidth;\r\n }\r\n newWidth = clampedWidth;\r\n }\r\n\r\n // Handle vertical resizing (if not maintaining aspect ratio)\r\n if (!this.options.maintainAspectRatio) {\r\n if (this.resizeDirection.includes('s')) {\r\n newHeight = Math.max(this.options.minHeight, this.resizeStartHeight + deltaY);\r\n }\r\n if (this.resizeDirection.includes('n')) {\r\n const proposedHeight = Math.max(this.options.minHeight, this.resizeStartHeight - deltaY);\r\n newTop = this.resizeStartTop + (this.resizeStartHeight - proposedHeight);\r\n newHeight = proposedHeight;\r\n }\r\n\r\n const maxHeightOption = typeof this.options.maxHeight === 'function'\r\n ? this.options.maxHeight()\r\n : this.options.maxHeight;\r\n if (Number.isFinite(maxHeightOption)) {\r\n const clampedHeight = Math.min(newHeight, maxHeightOption);\r\n if (clampedHeight !== newHeight && this.resizeDirection.includes('n')) {\r\n newTop += newHeight - clampedHeight;\r\n }\r\n newHeight = clampedHeight;\r\n }\r\n }\r\n\r\n // Apply new dimensions\r\n this.element.style.width = `${newWidth}px`;\r\n if (!this.options.maintainAspectRatio) {\r\n this.element.style.height = `${newHeight}px`;\r\n } else {\r\n this.element.style.height = 'auto';\r\n }\r\n \r\n // Apply new position if resizing from west or north\r\n if (this.resizeDirection.includes('w')) {\r\n this.element.style.left = `${newLeft}px`;\r\n }\r\n if (this.resizeDirection.includes('n') && !this.options.maintainAspectRatio) {\r\n this.element.style.top = `${newTop}px`;\r\n }\r\n \r\n // Call custom handler if provided\r\n if (this.options.onResize) {\r\n this.options.onResize({ width: newWidth, height: newHeight, left: newLeft, top: newTop });\r\n }\r\n }\r\n\r\n stopResizing() {\r\n this.isResizing = false;\r\n this.resizeDirection = null;\r\n this.element.classList.remove(`${this.options.classPrefix}-resizing`);\r\n document.body.style.userSelect = '';\r\n \r\n // Mark as manually positioned\r\n this.manuallyPositioned = true;\r\n \r\n // Call custom handler if provided\r\n if (this.options.onResizeEnd) {\r\n this.options.onResizeEnd();\r\n }\r\n }\r\n\r\n toggleKeyboardDragMode() {\r\n if (this.keyboardDragMode) {\r\n this.disableKeyboardDragMode();\r\n } else {\r\n this.enableKeyboardDragMode();\r\n }\r\n }\r\n\r\n enableKeyboardDragMode() {\r\n this.keyboardDragMode = true;\r\n this.keyboardResizeMode = false;\r\n this.element.classList.add(`${this.options.classPrefix}-keyboard-drag`);\r\n this.element.classList.remove(`${this.options.classPrefix}-keyboard-resize`);\r\n this.focusElement();\r\n }\r\n\r\n disableKeyboardDragMode() {\r\n this.keyboardDragMode = false;\r\n this.element.classList.remove(`${this.options.classPrefix}-keyboard-drag`);\r\n }\r\n\r\n toggleKeyboardResizeMode() {\r\n if (this.keyboardResizeMode) {\r\n this.disableKeyboardResizeMode();\r\n } else {\r\n this.enableKeyboardResizeMode();\r\n }\r\n }\r\n\r\n enableKeyboardResizeMode() {\r\n this.keyboardResizeMode = true;\r\n this.keyboardDragMode = false;\r\n this.element.classList.add(`${this.options.classPrefix}-keyboard-resize`);\r\n this.element.classList.remove(`${this.options.classPrefix}-keyboard-drag`);\r\n this.focusElement();\r\n }\r\n\r\n disableKeyboardResizeMode() {\r\n this.keyboardResizeMode = false;\r\n this.element.classList.remove(`${this.options.classPrefix}-keyboard-resize`);\r\n }\r\n\r\n enablePointerResizeMode({ focus = true } = {}) {\r\n if (!this.hasManagedResizeHandles()) {\r\n this.enableKeyboardResizeMode();\r\n return;\r\n }\r\n\r\n if (this.pointerResizeMode) {\r\n return;\r\n }\r\n\r\n this.pointerResizeMode = true;\r\n this.setManagedHandlesVisible(true);\r\n this.element.classList.add(`${this.options.classPrefix}-resizable`);\r\n this.enableKeyboardResizeMode();\r\n\r\n if (focus) {\r\n this.focusElement();\r\n }\r\n\r\n if (typeof this.options.onPointerResizeToggle === 'function') {\r\n this.options.onPointerResizeToggle(true);\r\n }\r\n }\r\n\r\n disablePointerResizeMode({ focus = false } = {}) {\r\n if (!this.pointerResizeMode) {\r\n return;\r\n }\r\n\r\n this.pointerResizeMode = false;\r\n this.setManagedHandlesVisible(false);\r\n this.element.classList.remove(`${this.options.classPrefix}-resizable`);\r\n this.disableKeyboardResizeMode();\r\n\r\n if (focus) {\r\n this.focusElement();\r\n }\r\n\r\n if (typeof this.options.onPointerResizeToggle === 'function') {\r\n this.options.onPointerResizeToggle(false);\r\n }\r\n }\r\n\r\n togglePointerResizeMode() {\r\n if (this.pointerResizeMode) {\r\n this.disablePointerResizeMode();\r\n } else {\r\n this.enablePointerResizeMode();\r\n }\r\n return this.pointerResizeMode;\r\n }\r\n\r\n focusElement() {\r\n if (typeof this.element.focus === 'function') {\r\n try {\r\n this.element.focus({ preventScroll: true });\r\n } catch (e) {\r\n // Some browsers do not support the preventScroll option; fallback without it\r\n this.element.focus();\r\n }\r\n }\r\n }\r\n\r\n keyboardDrag(key, shiftKey) {\r\n const step = shiftKey ? this.options.keyboardStepLarge : this.options.keyboardStep;\r\n \r\n // Get current position\r\n let currentLeft = parseFloat(this.element.style.left) || 0;\r\n let currentTop = parseFloat(this.element.style.top) || 0;\r\n \r\n // If element is still centered with transform, convert to absolute position first\r\n const computedStyle = window.getComputedStyle(this.element);\r\n if (computedStyle.transform !== 'none') {\r\n const rect = this.element.getBoundingClientRect();\r\n currentLeft = rect.left;\r\n currentTop = rect.top;\r\n this.element.style.transform = 'none';\r\n this.element.style.left = `${currentLeft}px`;\r\n this.element.style.top = `${currentTop}px`;\r\n }\r\n \r\n // Calculate new position\r\n let newX = currentLeft;\r\n let newY = currentTop;\r\n\r\n switch(key) {\r\n case 'ArrowLeft':\r\n newX -= step;\r\n break;\r\n case 'ArrowRight':\r\n newX += step;\r\n break;\r\n case 'ArrowUp':\r\n newY -= step;\r\n break;\r\n case 'ArrowDown':\r\n newY += step;\r\n break;\r\n }\r\n\r\n // Apply position\r\n this.element.style.left = `${newX}px`;\r\n this.element.style.top = `${newY}px`;\r\n \r\n // Call custom handler if provided\r\n if (this.options.onDrag) {\r\n this.options.onDrag({ x: newX, y: newY });\r\n }\r\n }\r\n\r\n keyboardResize(key, shiftKey) {\r\n const step = shiftKey ? this.options.keyboardStepLarge : this.options.keyboardStep;\r\n const rect = this.element.getBoundingClientRect();\r\n \r\n let width = rect.width;\r\n let height = rect.height;\r\n\r\n // Adjust width/height based on arrow key\r\n switch(key) {\r\n case 'ArrowLeft':\r\n width -= step;\r\n break;\r\n case 'ArrowRight':\r\n width += step;\r\n break;\r\n case 'ArrowUp':\r\n if (this.options.maintainAspectRatio) {\r\n width += step;\r\n } else {\r\n height -= step;\r\n }\r\n break;\r\n case 'ArrowDown':\r\n if (this.options.maintainAspectRatio) {\r\n width -= step;\r\n } else {\r\n height += step;\r\n }\r\n break;\r\n }\r\n\r\n // Constrain to minimum dimensions\r\n width = Math.max(this.options.minWidth, width);\r\n height = Math.max(this.options.minHeight, height);\r\n\r\n // Apply new dimensions\r\n this.element.style.width = `${width}px`;\r\n if (!this.options.maintainAspectRatio) {\r\n this.element.style.height = `${height}px`;\r\n } else {\r\n this.element.style.height = 'auto';\r\n }\r\n \r\n // Call custom handler if provided\r\n if (this.options.onResize) {\r\n this.options.onResize({ width, height });\r\n }\r\n }\r\n\r\n resetPosition() {\r\n this.element.style.left = '50%';\r\n this.element.style.top = '50%';\r\n this.element.style.transform = 'translate(-50%, -50%)';\r\n this.element.style.right = '';\r\n this.element.style.bottom = '';\r\n \r\n // Clear manual positioning flag\r\n this.manuallyPositioned = false;\r\n \r\n // Call custom handler if provided\r\n if (this.options.onDrag) {\r\n this.options.onDrag({ centered: true });\r\n }\r\n }\r\n\r\n destroy() {\r\n const dragHandle = this.options.dragHandle || this.element;\r\n \r\n this.disablePointerResizeMode();\r\n \r\n // Remove drag events\r\n dragHandle.removeEventListener('mousedown', this.handlers.mousedown);\r\n dragHandle.removeEventListener('touchstart', this.handlers.touchstart);\r\n \r\n // Remove document-level events\r\n document.removeEventListener('mousemove', this.handlers.mousemove);\r\n document.removeEventListener('mouseup', this.handlers.mouseup);\r\n document.removeEventListener('touchmove', this.handlers.touchmove);\r\n document.removeEventListener('touchend', this.handlers.touchend);\r\n \r\n // Remove keyboard events\r\n this.element.removeEventListener('keydown', this.handlers.keydown);\r\n \r\n // Remove resize handle events\r\n if (this.options.resizeHandles && this.options.resizeHandles.length > 0) {\r\n this.options.resizeHandles.forEach(handle => {\r\n handle.removeEventListener('mousedown', this.handlers.resizeHandleMousedown);\r\n handle.removeEventListener('touchstart', this.handlers.resizeHandleMousedown);\r\n });\r\n }\r\n \r\n // Clean up classes\r\n this.element.classList.remove(\r\n `${this.options.classPrefix}-dragging`,\r\n `${this.options.classPrefix}-resizing`,\r\n `${this.options.classPrefix}-keyboard-drag`,\r\n `${this.options.classPrefix}-keyboard-resize`\r\n );\r\n }\r\n}\r\n\r\n", "/**\r\n * Menu creation and management utilities\r\n */\r\n\r\nimport { DOMUtils } from './DOMUtils.js';\r\nimport { createIconElement } from '../icons/Icons.js';\r\nimport { i18n } from '../i18n/i18n.js';\r\nimport { focusElement } from './FocusUtils.js';\r\n\r\n/**\r\n * Create a menu item button with icon and text\r\n * @param {Object} options - Menu item options\r\n * @param {string} options.classPrefix - Class prefix\r\n * @param {string} options.itemClass - Menu item class name\r\n * @param {string} options.icon - Icon name\r\n * @param {string} options.label - Button label (i18n key or text)\r\n * @param {string} options.ariaLabel - ARIA label (optional, uses label if not provided)\r\n * @param {Function} options.onClick - Click handler\r\n * @param {boolean} options.hasTextClass - Whether to add text class to span\r\n * @returns {HTMLElement} Menu item button\r\n */\r\nexport function createMenuItem({ classPrefix, itemClass, icon, label, ariaLabel, onClick, hasTextClass = false }) {\r\n // Check if label is an i18n key for aria-label\r\n const isI18nKeyForAria = typeof label === 'string' && (label.startsWith('transcript.') || label.startsWith('player.') || label.startsWith('settings.'));\r\n const ariaLabelText = ariaLabel || (isI18nKeyForAria ? (i18n.t(label) || label) : label);\r\n \r\n const button = DOMUtils.createElement('button', {\r\n className: itemClass,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': ariaLabelText,\r\n 'tabindex': '-1'\r\n }\r\n });\r\n \r\n if (icon) {\r\n button.appendChild(createIconElement(icon));\r\n }\r\n \r\n // Check if label is an i18n key (starts with common prefixes)\r\n const isI18nKey = typeof label === 'string' && (label.startsWith('transcript.') || label.startsWith('player.') || label.startsWith('settings.'));\r\n const textContent = isI18nKey ? (i18n.t(label) || label) : label;\r\n \r\n const text = DOMUtils.createElement('span', {\r\n textContent: textContent,\r\n className: hasTextClass ? `${classPrefix}-settings-text` : undefined,\r\n attributes: {\r\n 'aria-hidden': 'true'\r\n }\r\n });\r\n button.appendChild(text);\r\n \r\n if (onClick) {\r\n button.addEventListener('click', onClick);\r\n }\r\n \r\n return button;\r\n}\r\n\r\n/**\r\n * Setup keyboard navigation for menu items\r\n * @param {HTMLElement} menu - Menu container\r\n * @param {HTMLElement} button - Trigger button\r\n * @param {string} itemSelector - Selector for menu items\r\n * @param {Function} onClose - Function to close menu\r\n */\r\nexport function attachMenuKeyboardNavigation(menu, button, itemSelector, onClose) {\r\n if (!menu) return;\r\n \r\n const menuItems = Array.from(menu.querySelectorAll(itemSelector));\r\n if (menuItems.length === 0) return;\r\n\r\n const handleKeyDown = (e) => {\r\n const currentIndex = menuItems.indexOf(document.activeElement);\r\n \r\n switch (e.key) {\r\n case 'ArrowDown':\r\n e.preventDefault();\r\n e.stopPropagation();\r\n const nextIndex = (currentIndex + 1) % menuItems.length;\r\n menuItems.forEach((item, idx) => {\r\n item.setAttribute('tabindex', idx === nextIndex ? '0' : '-1');\r\n });\r\n menuItems[nextIndex].focus({ preventScroll: false });\r\n menuItems[nextIndex].scrollIntoView({ behavior: 'smooth', block: 'nearest' });\r\n break;\r\n \r\n case 'ArrowUp':\r\n e.preventDefault();\r\n e.stopPropagation();\r\n const prevIndex = (currentIndex - 1 + menuItems.length) % menuItems.length;\r\n menuItems.forEach((item, idx) => {\r\n item.setAttribute('tabindex', idx === prevIndex ? '0' : '-1');\r\n });\r\n menuItems[prevIndex].focus({ preventScroll: false });\r\n menuItems[prevIndex].scrollIntoView({ behavior: 'smooth', block: 'nearest' });\r\n break;\r\n \r\n case 'Home':\r\n e.preventDefault();\r\n e.stopPropagation();\r\n menuItems.forEach((item, idx) => {\r\n item.setAttribute('tabindex', idx === 0 ? '0' : '-1');\r\n });\r\n menuItems[0].focus({ preventScroll: false });\r\n menuItems[0].scrollIntoView({ behavior: 'smooth', block: 'nearest' });\r\n break;\r\n \r\n case 'End':\r\n e.preventDefault();\r\n e.stopPropagation();\r\n const lastIndex = menuItems.length - 1;\r\n menuItems.forEach((item, idx) => {\r\n item.setAttribute('tabindex', idx === lastIndex ? '0' : '-1');\r\n });\r\n menuItems[lastIndex].focus({ preventScroll: false });\r\n menuItems[lastIndex].scrollIntoView({ behavior: 'smooth', block: 'nearest' });\r\n break;\r\n \r\n case 'Enter':\r\n case ' ':\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (document.activeElement && menuItems.includes(document.activeElement)) {\r\n document.activeElement.click();\r\n if (onClose) {\r\n setTimeout(() => {\r\n if (button && document.contains(button)) {\r\n button.focus();\r\n }\r\n }, 0);\r\n }\r\n }\r\n break;\r\n \r\n case 'Escape':\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (onClose) {\r\n onClose();\r\n }\r\n break;\r\n }\r\n };\r\n\r\n menu.addEventListener('keydown', handleKeyDown, true); // Use capture phase\r\n return handleKeyDown; // Return handler for cleanup\r\n}\r\n\r\n/**\r\n * Focus first menu item and set tabindex\r\n * @param {HTMLElement} menu - Menu container\r\n * @param {string} itemSelector - Selector for menu items\r\n * @param {number} delay - Delay in milliseconds\r\n */\r\nexport function focusFirstMenuItem(menu, itemSelector, delay = 0) {\r\n if (!menu) return;\r\n \r\n setTimeout(() => {\r\n const menuItems = Array.from(menu.querySelectorAll(itemSelector));\r\n if (menuItems.length > 0) {\r\n menuItems.forEach((item, index) => {\r\n item.setAttribute('tabindex', index === 0 ? '0' : '-1');\r\n });\r\n focusElement(menuItems[0], { delay: 0 });\r\n // Scroll into view for keyboard users\r\n menuItems[0].scrollIntoView({ behavior: 'smooth', block: 'nearest' });\r\n }\r\n }, delay);\r\n}\r\n\r\n", "/**\r\n * Form element creation utilities\r\n */\r\n\r\nimport { DOMUtils } from './DOMUtils.js';\r\nimport { i18n } from '../i18n/i18n.js';\r\n\r\n/**\r\n * Create a labeled select element with proper accessibility\r\n * @param {Object} options - Options for creating the labeled select\r\n * @param {string} options.classPrefix - Class prefix for styling\r\n * @param {string} options.labelClass - CSS class for the label\r\n * @param {string} options.selectClass - CSS class for the select\r\n * @param {string} options.labelText - Label text (i18n key or plain text)\r\n * @param {string} options.selectId - ID for the select element\r\n * @param {boolean} options.hidden - Whether to hide the label and select initially\r\n * @param {Function} options.onChange - Change event handler\r\n * @param {Array} options.options - Array of option objects {value, text, selected}\r\n * @returns {Object} Object with label and select elements\r\n */\r\nexport function createLabeledSelect({\r\n classPrefix,\r\n labelClass,\r\n selectClass,\r\n labelText,\r\n selectId,\r\n hidden = false,\r\n onChange = null,\r\n options = []\r\n}) {\r\n // Check if labelText is an i18n key\r\n const isI18nKey = typeof labelText === 'string' && \r\n (labelText.startsWith('transcript.') || \r\n labelText.startsWith('player.') || \r\n labelText.startsWith('settings.') ||\r\n labelText.startsWith('captions.'));\r\n const labelTextContent = isI18nKey ? (i18n.t(labelText) || labelText) : labelText;\r\n\r\n const label = DOMUtils.createElement('label', {\r\n className: labelClass,\r\n textContent: labelTextContent,\r\n attributes: {\r\n 'for': selectId,\r\n 'style': hidden ? 'display: none;' : undefined\r\n }\r\n });\r\n\r\n const select = DOMUtils.createElement('select', {\r\n className: selectClass,\r\n attributes: {\r\n 'id': selectId,\r\n 'style': hidden ? 'display: none;' : undefined\r\n }\r\n });\r\n\r\n // Add options\r\n options.forEach(opt => {\r\n const option = DOMUtils.createElement('option', {\r\n textContent: opt.text,\r\n attributes: {\r\n 'value': opt.value,\r\n 'selected': opt.selected ? 'selected' : undefined\r\n }\r\n });\r\n select.appendChild(option);\r\n });\r\n\r\n // Add change handler if provided\r\n if (onChange) {\r\n select.addEventListener('change', onChange);\r\n }\r\n\r\n return { label, select };\r\n}\r\n\r\n/**\r\n * Show or hide a labeled select element\r\n * @param {HTMLElement} label - Label element\r\n * @param {HTMLElement} select - Select element\r\n * @param {boolean} show - Whether to show (true) or hide (false)\r\n */\r\nexport function toggleLabeledSelect(label, select, show) {\r\n if (label) {\r\n label.style.display = show ? 'block' : 'none';\r\n }\r\n if (select) {\r\n select.style.display = show ? 'block' : 'none';\r\n }\r\n}\r\n\r\n/**\r\n * Prevent drag on element and its children\r\n * @param {HTMLElement} element - Element to prevent drag on\r\n */\r\nexport function preventDragOnElement(element) {\r\n if (!element) return;\r\n \r\n ['mousedown', 'click'].forEach(eventType => {\r\n element.addEventListener(eventType, (e) => {\r\n e.stopPropagation();\r\n });\r\n });\r\n}\r\n\r\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["translations"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/renderers/HTML5Renderer.js"],
|
|
4
|
-
"sourcesContent": ["/**\r\n * HTML5 Media Renderer\r\n */\r\n\r\nexport class HTML5Renderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.media = player.element;\r\n }\r\n\r\n async init() {\r\n // Hide native controls\r\n this.media.controls = false;\r\n this.media.removeAttribute('controls');\r\n \r\n this.attachEvents();\r\n \r\n // Set preload\r\n this.media.preload = this.player.options.preload;\r\n \r\n // Load media\r\n this.media.load();\r\n \r\n // Show VidPly controls (remove external controls class if present)\r\n if (this.player.container) {\r\n this.player.container.classList.remove('vidply-external-controls');\r\n }\r\n }\r\n\r\n attachEvents() {\r\n // Playback events\r\n this.media.addEventListener('loadedmetadata', () => {\r\n this.player.state.duration = this.media.duration;\r\n this.player.emit('loadedmetadata');\r\n \r\n // Auto-generate poster if none exists (for HTML5 video only)\r\n if (this.media.tagName === 'VIDEO') {\r\n this.player.autoGeneratePoster().catch(error => {\r\n this.player.log('Failed to auto-generate poster:', error, 'warn');\r\n });\r\n }\r\n });\r\n\r\n this.media.addEventListener('play', () => {\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.emit('play');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n \r\n // Pause other players if enabled\r\n if (this.player.options.pauseOthersOnPlay) {\r\n this.pauseOtherPlayers();\r\n }\r\n });\r\n\r\n this.media.addEventListener('pause', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n });\r\n\r\n this.media.addEventListener('ended', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n // Handle loop\r\n if (this.player.options.loop) {\r\n this.player.seek(0);\r\n this.player.play();\r\n }\r\n });\r\n\r\n this.media.addEventListener('timeupdate', () => {\r\n this.player.state.currentTime = this.media.currentTime;\r\n this.player.emit('timeupdate', this.media.currentTime);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, this.media.currentTime);\r\n }\r\n });\r\n\r\n this.media.addEventListener('volumechange', () => {\r\n this.player.state.volume = this.media.volume;\r\n this.player.state.muted = this.media.muted;\r\n this.player.emit('volumechange', this.media.volume);\r\n \r\n if (this.player.options.onVolumeChange) {\r\n this.player.options.onVolumeChange.call(this.player, this.media.volume);\r\n }\r\n });\r\n\r\n this.media.addEventListener('seeking', () => {\r\n this.player.state.seeking = true;\r\n this.player.emit('seeking');\r\n });\r\n\r\n this.media.addEventListener('seeked', () => {\r\n this.player.state.seeking = false;\r\n this.player.emit('seeked');\r\n });\r\n\r\n this.media.addEventListener('waiting', () => {\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n });\r\n\r\n this.media.addEventListener('canplay', () => {\r\n this.player.state.buffering = false;\r\n this.player.emit('canplay');\r\n });\r\n\r\n this.media.addEventListener('progress', () => {\r\n if (this.media.buffered.length > 0) {\r\n const buffered = this.media.buffered.end(this.media.buffered.length - 1);\r\n this.player.emit('progress', buffered);\r\n }\r\n });\r\n\r\n this.media.addEventListener('error', (e) => {\r\n this.player.handleError(this.media.error);\r\n });\r\n\r\n this.media.addEventListener('ratechange', () => {\r\n this.player.state.playbackSpeed = this.media.playbackRate;\r\n this.player.emit('ratechange', this.media.playbackRate);\r\n });\r\n }\r\n\r\n pauseOtherPlayers() {\r\n // Pause other VidPly instances\r\n const allPlayers = document.querySelectorAll('.vidply-player');\r\n allPlayers.forEach(playerEl => {\r\n if (playerEl !== this.player.container) {\r\n const video = playerEl.querySelector('video, audio');\r\n if (video && !video.paused) {\r\n video.pause();\r\n }\r\n }\r\n });\r\n }\r\n\r\n play() {\r\n // Save scroll position to prevent browser from scrolling to video\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n \r\n const promise = this.media.play();\r\n \r\n // Restore scroll position immediately to prevent auto-scroll\r\n window.scrollTo(scrollX, scrollY);\r\n \r\n if (promise !== undefined) {\r\n promise.catch(error => {\r\n this.player.log('Play failed:', error, 'warn');\r\n \r\n // If autoplay failed, try muted autoplay\r\n if (this.player.options.autoplay && !this.player.state.muted) {\r\n this.player.log('Retrying play with muted audio', 'info');\r\n this.media.muted = true;\r\n \r\n // Save scroll position again for retry\r\n const retryScrollX = window.scrollX;\r\n const retryScrollY = window.scrollY;\r\n this.media.play().then(() => {\r\n window.scrollTo(retryScrollX, retryScrollY);\r\n }).catch(err => {\r\n this.player.handleError(err);\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n pause() {\r\n this.media.pause();\r\n }\r\n\r\n seek(time) {\r\n this.media.currentTime = time;\r\n }\r\n\r\n setVolume(volume) {\r\n this.media.volume = volume;\r\n }\r\n\r\n setMuted(muted) {\r\n this.media.muted = muted;\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n this.media.playbackRate = speed;\r\n }\r\n\r\n /**\r\n * Get available quality levels from source elements\r\n * @returns {Array} Array of quality objects with index, height, width, and src\r\n */\r\n getQualities() {\r\n const sources = Array.from(this.media.querySelectorAll('source'));\r\n \r\n if (sources.length <= 1) {\r\n return [];\r\n }\r\n\r\n return sources.map((source, index) => {\r\n // Try to extract quality from data attributes or label\r\n const label = source.getAttribute('data-quality') || source.getAttribute('label') || '';\r\n const height = source.getAttribute('data-height') || this.extractHeightFromLabel(label);\r\n const width = source.getAttribute('data-width') || '';\r\n \r\n return {\r\n index,\r\n height: height ? parseInt(height) : 0,\r\n width: width ? parseInt(width) : 0,\r\n src: source.src,\r\n type: source.type,\r\n name: label || (height ? `${height}p` : `Quality ${index + 1}`)\r\n };\r\n }).filter(q => q.height > 0); // Only return qualities with valid height\r\n }\r\n\r\n /**\r\n * Extract height from quality label (e.g., \"1080p\" -> 1080)\r\n * @param {string} label \r\n * @returns {number}\r\n */\r\n extractHeightFromLabel(label) {\r\n const match = label.match(/(\\d+)p/i);\r\n return match ? parseInt(match[1]) : 0;\r\n }\r\n\r\n /**\r\n * Switch to a specific quality level\r\n * @param {number} qualityIndex - Index of the quality level (-1 for auto, not applicable for HTML5)\r\n */\r\n switchQuality(qualityIndex) {\r\n const qualities = this.getQualities();\r\n \r\n if (qualityIndex < 0 || qualityIndex >= qualities.length) {\r\n this.player.log('Invalid quality index', 'warn');\r\n return;\r\n }\r\n\r\n const quality = qualities[qualityIndex];\r\n const currentTime = this.media.currentTime;\r\n const wasPlaying = !this.media.paused;\r\n\r\n // Store the current source for comparison\r\n const currentSrc = this.media.currentSrc;\r\n \r\n // Don't switch if already at this quality\r\n if (currentSrc === quality.src) {\r\n this.player.log('Already at this quality level', 'info');\r\n return;\r\n }\r\n\r\n this.player.log(`Switching to quality: ${quality.name}`, 'info');\r\n\r\n // Update the src\r\n this.media.src = quality.src;\r\n \r\n // Wait for the new source to load, then restore playback state\r\n const onLoadedMetadata = () => {\r\n this.media.removeEventListener('loadedmetadata', onLoadedMetadata);\r\n \r\n // Restore playback position\r\n this.media.currentTime = currentTime;\r\n \r\n // Resume playback if it was playing\r\n if (wasPlaying) {\r\n this.media.play().catch(err => {\r\n this.player.log('Failed to resume playback after quality switch', 'warn');\r\n });\r\n }\r\n \r\n // Emit quality change event\r\n this.player.emit('qualitychange', { quality: quality.name, index: qualityIndex });\r\n };\r\n\r\n this.media.addEventListener('loadedmetadata', onLoadedMetadata);\r\n this.media.load();\r\n }\r\n\r\n /**\r\n * Get current quality index\r\n * @returns {number}\r\n */\r\n getCurrentQuality() {\r\n const qualities = this.getQualities();\r\n const currentSrc = this.media.currentSrc;\r\n \r\n for (let i = 0; i < qualities.length; i++) {\r\n if (qualities[i].src === currentSrc) {\r\n return i;\r\n }\r\n }\r\n \r\n return 0; // Default to first quality if not found\r\n }\r\n\r\n destroy() {\r\n // Remove event listeners\r\n this.media.removeEventListener('loadedmetadata', () => {});\r\n this.media.removeEventListener('play', () => {});\r\n this.media.removeEventListener('pause', () => {});\r\n // ... (other listeners would be removed in a real implementation)\r\n }\r\n}\r\n\r\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/i18n/languages/de.js"],
|
|
4
|
-
"sourcesContent": ["/**\r\n * German translations for VidPly\r\n */\r\n\r\nexport const de = {\r\n player: {\r\n label: 'Videoplayer',\r\n play: 'Abspielen',\r\n pause: 'Pause',\r\n stop: 'Stopp',\r\n restart: 'Von vorne beginnen',\r\n rewind: 'Zurückspulen',\r\n forward: 'Vorspulen',\r\n rewindSeconds: '{seconds} Sekunden zurückspulen',\r\n forwardSeconds: '{seconds} Sekunden vorspulen',\r\n previous: 'Vorheriger Titel',\r\n next: 'Nächster Titel',\r\n playlist: 'Wiedergabeliste umschalten',\r\n volume: 'Lautstärke',\r\n mute: 'Stumm',\r\n unmute: 'Ton ein',\r\n fullscreen: 'Vollbild',\r\n exitFullscreen: 'Vollbild beenden',\r\n captions: 'Untertitel',\r\n chapters: 'Kapitel',\r\n quality: 'Qualität',\r\n captionStyling: 'Untertitel-Stil',\r\n transcript: 'Transkript umschalten',\r\n audioDescription: 'Audiodeskription',\r\n signLanguage: 'Gebärdensprache-Video',\r\n settings: 'Einstellungen',\r\n speed: 'Wiedergabegeschwindigkeit',\r\n pip: 'Bild-in-Bild',\r\n currentTime: 'Aktuelle Zeit',\r\n duration: 'Dauer',\r\n progress: 'Fortschritt',\r\n seekForward: '{seconds} Sekunden vorspulen',\r\n seekBackward: '{seconds} Sekunden zurückspulen',\r\n volumeUp: 'Lauter',\r\n volumeDown: 'Leiser',\r\n loading: 'Lädt...',\r\n loadingChapters: 'Kapitel werden geladen...',\r\n error: 'Fehler beim Laden',\r\n buffering: 'Puffern...',\r\n signLanguageVideo: 'Gebärdensprache-Video',\r\n closeSignLanguage: 'Gebärdensprache-Video schließen',\r\n signLanguageSettings: 'Gebärdensprache-Einstellungen',\r\n noChapters: 'Keine Kapitel verfügbar',\r\n noCaptions: 'Keine Untertitel verfügbar',\r\n auto: 'Automatisch',\r\n autoQuality: 'Automatisch (keine Qualitätsauswahl verfügbar)',\r\n noQuality: 'Qualitätsauswahl nicht verfügbar',\r\n signLanguageDragResize: 'Gebärdensprache-Video - Drücken Sie D zum Verschieben per Tastatur, R zum Ändern der Größe',\r\n signLanguageDragActive: 'Gebärdensprache-Video - Verschiebemodus aktiv. Pfeiltasten zum Bewegen, Escape zum Beenden.',\r\n signLanguageResizeActive: 'Gebärdensprache-Video - Größenänderungsmodus aktiv. Links-/Rechts-Pfeiltasten zum Ändern der Größe, Escape zum Beenden.',\r\n enableSignDragMode: 'Verschiebemodus aktivieren. Tastenkombination: D-Taste',\r\n disableSignDragMode: 'Verschiebemodus deaktivieren. Tastenkombination: D-Taste',\r\n enableSignDragModeAria: 'Tastatur-Verschiebemodus mit Pfeiltasten aktivieren. Tastenkombination: D-Taste',\r\n disableSignDragModeAria: 'Tastatur-Verschiebemodus mit Pfeiltasten deaktivieren. Tastenkombination: D-Taste',\r\n enableSignResizeMode: 'Größenänderungsmodus aktivieren. Tastenkombination: R-Taste',\r\n disableSignResizeMode: 'Größenänderungsmodus deaktivieren. Tastenkombination: R-Taste',\r\n enableSignResizeModeAria: 'Tastatur-Größenänderungsmodus mit Pfeiltasten aktivieren. Tastenkombination: R-Taste',\r\n disableSignResizeModeAria: 'Tastatur-Größenänderungsmodus mit Pfeiltasten deaktivieren. Tastenkombination: R-Taste',\r\n resizeHandle: 'Größenänderung {direction}-Ecke',\r\n moreOptions: 'Weitere Optionen',\r\n noMoreOptions: 'Keine weiteren Optionen verfügbar'\r\n },\r\n captions: {\r\n off: 'Aus',\r\n select: 'Untertitel auswählen',\r\n fontSize: 'Schriftgröße',\r\n fontFamily: 'Schriftart',\r\n color: 'Textfarbe',\r\n backgroundColor: 'Hintergrundfarbe',\r\n opacity: 'Deckkraft'\r\n },\r\n fontSizes: {\r\n small: 'Klein',\r\n normal: 'Normal',\r\n large: 'Groß',\r\n xlarge: 'Sehr groß'\r\n },\r\n fontFamilies: {\r\n sansSerif: 'Sans-serif',\r\n serif: 'Serif',\r\n monospace: 'Monospace'\r\n },\r\n styleLabels: {\r\n textColor: 'Textfarbe',\r\n background: 'Hintergrund',\r\n font: 'Schrift',\r\n fontSize: 'Schriftgröße',\r\n opacity: 'Deckkraft'\r\n },\r\n audioDescription: {\r\n enable: 'Audiodeskription aktivieren',\r\n disable: 'Audiodeskription deaktivieren'\r\n },\r\n signLanguage: {\r\n show: 'Gebärdensprache-Video anzeigen',\r\n hide: 'Gebärdensprache-Video ausblenden'\r\n },\r\n transcript: {\r\n title: 'Transkript',\r\n ariaLabel: 'Video-Transkript',\r\n close: 'Transkript schließen',\r\n loading: 'Transkript wird geladen...',\r\n noTranscript: 'Kein Transkript für dieses Video verfügbar.',\r\n settings: 'Transkript-Einstellungen. Eingabetaste zum Öffnen des Menüs drücken oder D zum Aktivieren des Verschiebemodus',\r\n keyboardDragMode: 'Tastatur-Verschiebemodus mit Pfeiltasten umschalten. Tastenkombination: D-Taste',\r\n keyboardDragActive: '⌨️ Tastatur-Verschiebemodus aktiv (Pfeiltasten zum Bewegen, Umschalt+Pfeiltasten für große Schritte, D oder ESC zum Beenden)',\r\n dragResizePrompt: 'Drücken Sie D zum Verschieben oder R zur Größenänderung. Home setzt die Position zurück, Esc schließt.',\r\n dragModeEnabled: 'Tastatur-Verschiebemodus aktiviert. Pfeiltasten zum Bewegen, Umschalt+Pfeiltasten für größere Schritte. D oder Esc zum Beenden.',\r\n dragModeDisabled: 'Tastatur-Verschiebemodus deaktiviert.',\r\n enableDragMode: 'Verschiebemodus aktivieren. Tastenkombination: D-Taste',\r\n disableDragMode: 'Verschiebemodus deaktivieren. Tastenkombination: D-Taste',\r\n enableDragModeAria: 'Tastatur-Verschiebemodus mit Pfeiltasten aktivieren. Tastenkombination: D-Taste',\r\n disableDragModeAria: 'Tastatur-Verschiebemodus mit Pfeiltasten deaktivieren. Tastenkombination: D-Taste',\r\n resizeWindow: 'Fenster vergrößern/verkleinern',\r\n disableResizeWindow: 'Resize-Modus deaktivieren',\r\n enableResizeMode: 'Größenänderungsmodus aktivieren. Tastenkombination: R-Taste',\r\n disableResizeMode: 'Größenänderungsmodus deaktivieren. Tastenkombination: R-Taste',\r\n enableResizeModeAria: 'Tastatur-Größenänderungsmodus mit Pfeiltasten aktivieren. Tastenkombination: R-Taste',\r\n disableResizeModeAria: 'Tastatur-Größenänderungsmodus mit Pfeiltasten deaktivieren. Tastenkombination: R-Taste',\r\n resizeModeHint: 'Griffe aktiviert. Ziehen Sie Kanten oder Ecken zum Anpassen. Esc oder R zum Beenden.',\r\n resizeModeEnabled: 'Resize-Modus aktiviert. Kanten oder Ecken ziehen; Esc oder R beendet.',\r\n resizeModeDisabled: 'Resize-Modus deaktiviert.',\r\n positionReset: 'Transkriptposition zurückgesetzt.',\r\n styleTranscript: 'Transkript-Stileinstellungen öffnen',\r\n closeMenu: 'Menü schließen',\r\n styleTitle: 'Transkript-Stil',\r\n autoscroll: 'Auto-Scroll',\r\n settingsMenu: 'Transkript-Dialog-Einstellungen',\r\n showTimestamps: 'Zeitstempel anzeigen',\r\n hideTimestamps: 'Zeitstempel ausblenden',\r\n showTimestampsAria: 'Zeitstempel im Transkript anzeigen',\r\n hideTimestampsAria: 'Zeitstempel im Transkript ausblenden'\r\n },\r\n settings: {\r\n title: 'Einstellungen',\r\n quality: 'Qualität',\r\n speed: 'Geschwindigkeit',\r\n captions: 'Untertitel',\r\n language: 'Sprache',\r\n reset: 'Zurücksetzen',\r\n close: 'Schließen'\r\n },\r\n speeds: {\r\n normal: 'Normal'\r\n },\r\n time: {\r\n display: 'Zeitanzeige',\r\n durationPrefix: 'Dauer: ',\r\n of: 'von',\r\n hour: '{count} Stunde',\r\n hours: '{count} Stunden',\r\n minute: '{count} Minute',\r\n minutes: '{count} Minuten',\r\n second: '{count} Sekunde',\r\n seconds: '{count} Sekunden'\r\n },\r\n playlist: {\r\n title: 'Wiedergabeliste',\r\n trackOf: 'Titel {current} von {total}',\r\n nowPlaying: 'Läuft gerade: Titel {current} von {total}. {title}{artist}',\r\n by: ' von ',\r\n untitled: 'Ohne Titel',\r\n trackUntitled: 'Titel {number}',\r\n currentlyPlaying: 'Wird gerade abgespielt',\r\n notPlaying: 'Nicht aktiv',\r\n pressEnterPlay: 'Eingabetaste zum Abspielen',\r\n pressEnterRestart: 'Eingabetaste zum Neustart',\r\n keyboardInstructions: 'Wiedergabelisten-Navigation: Verwenden Sie die Pfeiltasten nach oben und unten, um zwischen Titeln zu wechseln. Drücken Sie Bild auf oder Bild ab, um 5 Titel zu überspringen. Drücken Sie Pos1, um zum ersten Titel zu springen, Ende für den letzten Titel. Drücken Sie die Eingabetaste oder Leertaste, um den ausgewählten Titel abzuspielen.',\r\n endOfPlaylist: 'Ende der Wiedergabeliste. {current} von {total}.',\r\n beginningOfPlaylist: 'Anfang der Wiedergabeliste. 1 von {total}.',\r\n jumpedToLastTrack: 'Zum letzten Titel gesprungen. {current} von {total}.',\r\n jumpedToFirstTrack: 'Zum ersten Titel gesprungen. 1 von {total}.',\r\n firstTrack: 'Erster Titel. 1 von {total}.',\r\n lastTrack: 'Letzter Titel. {current} von {total}.'\r\n }\r\n};\r\n\r\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Universal, Accessible Video Player
|
|
3
|
-
* (c) 2025 Matthias Peltzer
|
|
4
|
-
* Released under GPL-2.0-or-later License
|
|
5
|
-
*/
|
|
6
|
-
var a=class{constructor(e){this.player=e,this.media=e.element,this.hls=null}async init(){this.canPlayNatively()?(this.player.log("Using native HLS support"),await this.initNative()):(this.player.log("Using hls.js for HLS support"),await this.initHlsJs())}canPlayNatively(){let e=/^((?!chrome|android).)*safari/i.test(navigator.userAgent),t=/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream;return!e&&!t?!1:document.createElement("video").canPlayType("application/vnd.apple.mpegurl")!==""}async initNative(){let e=(await import("./vidply.HTML5Renderer-KKW3OLHM.min.js")).HTML5Renderer,t=new e(this.player);await t.init(),Object.getOwnPropertyNames(Object.getPrototypeOf(t)).forEach(i=>{i!=="constructor"&&typeof t[i]=="function"&&(this[i]=t[i].bind(t))})}async initHlsJs(){if(this.media.controls=!1,this.media.removeAttribute("controls"),window.Hls||await this.loadHlsJs(),!window.Hls.isSupported())throw new Error("HLS is not supported in this browser");this.hls=new window.Hls({debug:this.player.options.debug,enableWorker:!0,lowLatencyMode:!1,backBufferLength:90,maxBufferLength:30,maxMaxBufferLength:600,maxBufferSize:60*1e3*1e3,maxBufferHole:.5,manifestLoadingTimeOut:1e4,manifestLoadingMaxRetry:4,manifestLoadingRetryDelay:1e3,manifestLoadingMaxRetryTimeout:64e3,levelLoadingTimeOut:1e4,levelLoadingMaxRetry:4,levelLoadingRetryDelay:1e3,levelLoadingMaxRetryTimeout:64e3,fragLoadingTimeOut:2e4,fragLoadingMaxRetry:6,fragLoadingRetryDelay:1e3,fragLoadingMaxRetryTimeout:64e3}),this.hls.attachMedia(this.media);let e=this.player.currentSource;if(!e){let t=this.player.element.querySelector("source");t?e=t.getAttribute("src"):e=this.player.element.getAttribute("src")||this.player.element.src}if(this.player.log(`Loading HLS source: ${e}`,"log"),!e)throw new Error("No HLS source found");this.hls.loadSource(e),this.attachHlsEvents(),this.attachMediaEvents()}async loadHlsJs(){return new Promise((e,t)=>{let i=document.createElement("script");i.src="https://cdn.jsdelivr.net/npm/hls.js@latest",i.onload=()=>e(),i.onerror=()=>t(new Error("Failed to load hls.js")),document.head.appendChild(i)})}attachHlsEvents(){this.hls.on(window.Hls.Events.MANIFEST_PARSED,(e,t)=>{this.player.log("HLS manifest loaded, found "+t.levels.length+" quality levels"),this.player.emit("hlsmanifestparsed",t),this.player.container&&this.player.container.classList.remove("vidply-external-controls")}),this.hls.on(window.Hls.Events.LEVEL_SWITCHED,(e,t)=>{this.player.log("HLS level switched to "+t.level),this.player.emit("hlslevelswitched",t)}),this.hls.on(window.Hls.Events.ERROR,(e,t)=>{this.handleHlsError(t)}),this.hls.on(window.Hls.Events.FRAG_BUFFERED,()=>{this.player.state.buffering=!1})}attachMediaEvents(){this.media.addEventListener("loadedmetadata",()=>{this.player.state.duration=this.media.duration,this.player.emit("loadedmetadata")}),this.media.addEventListener("play",()=>{this.player.state.playing=!0,this.player.state.paused=!1,this.player.state.ended=!1,this.player.emit("play"),this.player.options.onPlay&&this.player.options.onPlay.call(this.player)}),this.media.addEventListener("pause",()=>{this.player.state.playing=!1,this.player.state.paused=!0,this.player.emit("pause"),this.player.options.onPause&&this.player.options.onPause.call(this.player)}),this.media.addEventListener("ended",()=>{this.player.state.playing=!1,this.player.state.paused=!0,this.player.state.ended=!0,this.player.emit("ended"),this.player.options.onEnded&&this.player.options.onEnded.call(this.player),this.player.options.loop&&(this.player.seek(0),this.player.play())}),this.media.addEventListener("timeupdate",()=>{this.player.state.currentTime=this.media.currentTime,this.player.emit("timeupdate",this.media.currentTime),this.player.options.onTimeUpdate&&this.player.options.onTimeUpdate.call(this.player,this.media.currentTime)}),this.media.addEventListener("volumechange",()=>{this.player.state.volume=this.media.volume,this.player.state.muted=this.media.muted,this.player.emit("volumechange",this.media.volume)}),this.media.addEventListener("waiting",()=>{this.player.state.buffering=!0,this.player.emit("waiting")}),this.media.addEventListener("canplay",()=>{this.player.state.buffering=!1,this.player.emit("canplay")}),this.media.addEventListener("error",()=>{this.player.handleError(this.media.error)})}handleHlsError(e){if(this.player.log(`HLS Error - Type: ${e.type}, Details: ${e.details}, Fatal: ${e.fatal}`,"warn"),e.response&&this.player.log(`Response code: ${e.response.code}, URL: ${e.response.url}`,"warn"),e.fatal)switch(e.type){case window.Hls.ErrorTypes.NETWORK_ERROR:this.player.log("Fatal network error, trying to recover...","error"),this.player.log(`Network error details: ${e.details}`,"error"),setTimeout(()=>{this.hls.startLoad()},1e3);break;case window.Hls.ErrorTypes.MEDIA_ERROR:this.player.log("Fatal media error, trying to recover...","error"),this.hls.recoverMediaError();break;default:this.player.log("Fatal error, cannot recover","error"),this.player.handleError(new Error(`HLS Error: ${e.type} - ${e.details}`)),this.hls.destroy();break}else this.player.log("Non-fatal HLS error: "+e.details,"warn")}play(){let e=window.scrollX,t=window.scrollY,i=this.media.play();window.scrollTo(e,t),i!==void 0&&i.catch(s=>{this.player.log("Play failed:",s,"warn")})}pause(){this.media.pause()}seek(e){this.media.currentTime=e}setVolume(e){this.media.volume=e}setMuted(e){this.media.muted=e}setPlaybackSpeed(e){this.media.playbackRate=e}switchQuality(e){this.hls&&(this.hls.currentLevel=e)}getQualities(){return this.hls&&this.hls.levels?this.hls.levels.map((e,t)=>{let i=Number(e.height)||0,s=Number(e.bitrate)||0,r=s>0?Math.round(s/1e3):0,l=i>0?`${i}p`:r>0?`${r} kb`:"Auto";return{index:t,height:e.height,width:e.width,bitrate:e.bitrate,name:l}}):[]}getCurrentQuality(){return this.hls?this.hls.currentLevel:-1}destroy(){this.hls&&(this.hls.destroy(),this.hls=null)}};export{a as HLSRenderer};
|