vidply 1.1.4 → 1.1.6

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 CHANGED
@@ -8,7 +8,7 @@ A modern, feature-rich media player authored in strict TypeScript and shipped as
8
8
  ![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue.svg)
9
9
  ![ESM](https://img.shields.io/badge/ESM-Module-yellow.svg)
10
10
  ![WCAG](https://img.shields.io/badge/WCAG-2.2%20AA-green.svg)
11
- ![Version](https://img.shields.io/badge/version-1.1.3-brightgreen.svg)
11
+ ![Version](https://img.shields.io/badge/version-1.1.6-brightgreen.svg)
12
12
 
13
13
  ## Live Demos
14
14
 
@@ -81,7 +81,14 @@ Try VidPly in action:
81
81
  - **Volume Control** - 0-100% with mute
82
82
  - **Loop Playback** - Single or playlist loop
83
83
  - **Fullscreen Mode** - Native fullscreen API with smart playlist overlay
84
- - **Picture-in-Picture** - PiP support
84
+ - **Picture-in-Picture** - Native browser PiP support (toggled via the standard PiP button)
85
+ - **Custom Floating Player (Miniplayer)** - Optional in-page floating window that
86
+ - automatically floats when the original player scrolls out of the viewport and docks back when it scrolls in
87
+ - can be pinned/unpinned manually via the PiP button (manual pin overrides scroll behavior)
88
+ - is fully draggable and resizable, with persistent geometry per player
89
+ - keeps VidPly captions, transport controls and fullscreen working inside the floating shell
90
+ - suppresses native browser PiP automatically while enabled
91
+ - is desktop-only (disabled below 768 px viewport width by default)
85
92
 
86
93
  ### Internationalization
87
94
  Built-in support for 5 languages:
@@ -258,6 +265,43 @@ const player = new Player('#my-video', {
258
265
  });
259
266
  ```
260
267
 
268
+ ### Custom Floating Player (Miniplayer)
269
+
270
+ Enable the in-page floating player ("own PiP"). When the original video scrolls
271
+ out of the viewport, VidPly pops up a draggable, resizable floating shell in the
272
+ chosen corner; when the original scrolls back in, it docks again. Users can also
273
+ manually pin/unpin the floating player via the PiP button in the control bar.
274
+ The native browser Picture-in-Picture API is automatically suppressed while
275
+ floating is enabled, so users get a single, consistent experience.
276
+
277
+ Enable via the `data-vidply-options` JSON blob:
278
+
279
+ ```html
280
+ <video
281
+ data-vidply
282
+ data-vidply-options='{"floating": true, "floatingPosition": "bottom-right", "floatingMinViewportWidth": 768}'
283
+ src="video.mp4"
284
+ width="800" height="450">
285
+ <track kind="subtitles" src="captions.vtt" srclang="en" label="English">
286
+ </video>
287
+ ```
288
+
289
+ Or programmatically:
290
+
291
+ ```javascript
292
+ const player = new Player('#my-video', {
293
+ floating: true,
294
+ floatingPosition: 'bottom-right', // or 'bottom-left' | 'top-right' | 'top-left'
295
+ floatingMinViewportWidth: 768 // disable feature below this viewport width
296
+ });
297
+ ```
298
+
299
+ Notes:
300
+ - Audio-only players (`<audio>`) ignore the floating option.
301
+ - Closing the floating window pauses playback and prevents auto-float again until the next user-initiated `play`.
302
+ - The floating window persists its size/position per player via local storage.
303
+ - Below `floatingMinViewportWidth` (default 768 px) the PiP button is hidden and the floating feature is disabled.
304
+
261
305
  ### DASH + HLS + MP4 Fallback
262
306
 
263
307
  For maximum device compatibility, provide all three formats:
@@ -312,6 +356,11 @@ const player = new Player('#video', {
312
356
  downloadButton: false, // Show a download button in the control bar
313
357
  downloadUrl: null, // Optional explicit download URL (falls back to current src)
314
358
 
359
+ // Custom Floating Player (in-page miniplayer / "own PiP")
360
+ floating: false, // Enable the custom floating player; also disables native browser PiP
361
+ floatingPosition: 'bottom-right', // 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
362
+ floatingMinViewportWidth: 768, // Floating feature is hidden below this viewport width (px)
363
+
315
364
  // Captions
316
365
  captions: true,
317
366
  captionsDefault: false,
@@ -341,7 +341,6 @@ var FloatingPlayerManager = class {
341
341
  className: `${this.classPrefix}-floating-resize-handle ${this.classPrefix}-floating-resize-${dir}`,
342
342
  attributes: {
343
343
  "data-direction": dir,
344
- "data-vidply-managed-resize": "true",
345
344
  "aria-hidden": "true"
346
345
  }
347
346
  }));
@@ -512,4 +511,4 @@ var FloatingPlayerManager = class {
512
511
  export {
513
512
  FloatingPlayerManager
514
513
  };
515
- //# sourceMappingURL=vidply.FloatingPlayerManager-5EA4BYSR.js.map
514
+ //# sourceMappingURL=vidply.FloatingPlayerManager-AEMEBLF7.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/core/FloatingPlayerManager.ts"],
4
- "sourcesContent": ["/**\n * Floating Player Manager\n *\n * Custom in-page Picture-in-Picture. Moves the entire player.container\n * into a position:fixed, draggable and resizable shell that lives outside\n * the document flow (appended to document.body). A transparent placeholder\n * preserves layout and, while floating, serves as the IntersectionObserver\n * sentinel so scroll-based auto-float/redock decisions stay anchored to\n * the original slot.\n *\n * Triggers:\n * - pinned: the user clicks the control-bar PiP button (only when\n * options.floating is true; otherwise the button uses native PiP).\n * Pinned floating ignores scroll-based docking.\n * - auto: the video is playing and the original slot has scrolled out\n * of the viewport. Auto-float redocks automatically when the slot\n * scrolls back in.\n *\n * Close button: pauses playback, exits the floating shell and marks the\n * current play session as dismissed so auto-float will not re-trigger\n * until the user presses play again (matches YouTube miniplayer UX).\n *\n * Only one player is allowed to float at a time across a page; enter()\n * broadcasts a 'vidply:floating-claim' CustomEvent that other managers\n * listen for and auto-exit on.\n */\n\nimport { DOMUtils } from '../utils/DOMUtils.js';\nimport { DraggableResizable } from '../utils/DraggableResizable.js';\nimport { createIconElement } from '../icons/Icons.js';\nimport { i18n } from '../i18n/i18n.js';\nimport type { Player } from './Player.js';\n\ntype FloatingState = 'pinned' | 'auto';\ntype ExitReason = 'manual' | 'auto' | 'dismiss' | 'claim' | 'destroy';\n\nconst FLOATING_CLAIM_EVENT = 'vidply:floating-claim';\nconst DEFAULT_WIDTH = 400;\nconst MIN_WIDTH = 240;\nconst EDGE_MARGIN = 16;\n\ninterface FloatingPrefs {\n width?: number;\n height?: number;\n left?: number;\n top?: number;\n}\n\nexport class FloatingPlayerManager {\n player: Player;\n classPrefix: string;\n\n shell: HTMLElement | null;\n dragHandle: HTMLElement | null;\n closeButton: HTMLButtonElement | null;\n resizeHandles: HTMLElement[];\n placeholder: HTMLElement | null;\n draggable: DraggableResizable | null;\n\n originalParent: HTMLElement | null;\n originalNextSibling: Node | null;\n\n intersectionObserver: IntersectionObserver | null;\n observerTarget: HTMLElement | null;\n lastRatio: number;\n\n _autoDismissedThisPlay: boolean;\n _playListenerAttached: boolean;\n _onPlayAfterDismiss: (() => void) | null;\n _onClaim: ((event: Event) => void) | null;\n _onResize: (() => void) | null;\n _onKeyDown: ((event: KeyboardEvent) => void) | null;\n _onEnterFullscreen: (() => void) | null;\n _destroyed: boolean;\n _triggerFocusEl: HTMLElement | null;\n _claimId: string;\n\n constructor(player: Player) {\n this.player = player;\n this.classPrefix = player.options.classPrefix || 'vidply';\n\n this.shell = null;\n this.dragHandle = null;\n this.closeButton = null;\n this.resizeHandles = [];\n this.placeholder = null;\n this.draggable = null;\n\n this.originalParent = null;\n this.originalNextSibling = null;\n\n this.intersectionObserver = null;\n this.observerTarget = null;\n this.lastRatio = 1;\n\n this._autoDismissedThisPlay = false;\n this._playListenerAttached = false;\n this._onPlayAfterDismiss = null;\n this._onClaim = null;\n this._onResize = null;\n this._onKeyDown = null;\n this._onEnterFullscreen = null;\n this._destroyed = false;\n this._triggerFocusEl = null;\n this._claimId = `floating-${player.instanceId}-${Date.now()}`;\n\n this._setupClaimListener();\n this._setupFullscreenGuard();\n this._startObserving();\n }\n\n // ---------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------\n\n togglePinned(triggerEl?: HTMLElement | null) {\n if (this._destroyed) return;\n if (this.player.state.floating === 'pinned') {\n // Manual unpin: suppress auto-float for the remainder of the\n // current play session so scrolling doesn't immediately re-pop\n // the floating shell. A fresh 'play' event clears the flag.\n this._autoDismissedThisPlay = true;\n this._armPlayListenerToClearDismiss();\n this.exit('manual');\n return;\n }\n // If the user pins while in 'auto' mode, that's an explicit request\n // to float; any previous auto-dismiss flag should be cleared so the\n // pinned state behaves naturally.\n this._autoDismissedThisPlay = false;\n this._triggerFocusEl = triggerEl || this._activeElement();\n this.enter('pinned');\n }\n\n enter(reason: FloatingState) {\n if (this._destroyed) return;\n if (this.player.state.floating === reason) return;\n\n if (!this._canFloat(reason)) {\n return;\n }\n\n // Upgrade 'auto' -> 'pinned' without rebuilding the shell\n if (this.player.state.floating && this.player.state.floating !== reason) {\n this.player.state.floating = reason;\n this.player.emit('floatingchange', reason);\n return;\n }\n\n this._claimSingleton();\n\n this._ensureShell();\n this._mountIntoShell();\n this._applyInitialGeometry();\n\n this.player.state.floating = reason;\n this.player.emit('floatingchange', reason);\n\n // Focus the close button after a microtask so screen readers announce\n // the dialog opening.\n queueMicrotask(() => {\n if (this.closeButton && this.player.state.floating) {\n try { this.closeButton.focus({ preventScroll: true }); } catch { /* ignore */ }\n }\n });\n }\n\n exit(reason: ExitReason = 'manual') {\n if (this._destroyed && reason !== 'destroy') return;\n if (!this.player.state.floating) return;\n\n this._unmountFromShell();\n this._teardownShell();\n\n const priorTrigger = this._triggerFocusEl;\n this._triggerFocusEl = null;\n\n this.player.state.floating = null;\n this.player.emit('floatingchange', null);\n\n // Restore focus to the element that triggered floating (pinned flow).\n // For scroll-based exits we leave focus untouched.\n if ((reason === 'manual' || reason === 'dismiss') && priorTrigger) {\n try { priorTrigger.focus({ preventScroll: true }); } catch { /* ignore */ }\n }\n }\n\n /**\n * Close button: pause, dismiss, and prevent auto-float until the next\n * user-initiated play event.\n */\n dismiss() {\n if (this._destroyed) return;\n this._autoDismissedThisPlay = true;\n this._armPlayListenerToClearDismiss();\n\n try {\n this.player.pause();\n } catch { /* ignore */ }\n\n this.exit('dismiss');\n }\n\n destroy() {\n if (this._destroyed) return;\n this._destroyed = true;\n\n if (this.player.state && this.player.state.floating) {\n try { this.exit('destroy'); } catch { /* ignore */ }\n }\n\n if (this.intersectionObserver) {\n try { this.intersectionObserver.disconnect(); } catch { /* ignore */ }\n this.intersectionObserver = null;\n }\n this.observerTarget = null;\n\n if (this._onClaim) {\n window.removeEventListener(FLOATING_CLAIM_EVENT, this._onClaim as EventListener);\n this._onClaim = null;\n }\n if (this._onResize) {\n window.removeEventListener('resize', this._onResize);\n this._onResize = null;\n }\n if (this._onEnterFullscreen) {\n this.player.off('enterfullscreen', this._onEnterFullscreen as any);\n this._onEnterFullscreen = null;\n }\n if (this._onPlayAfterDismiss && this._playListenerAttached) {\n this.player.off('play', this._onPlayAfterDismiss as any);\n this._playListenerAttached = false;\n this._onPlayAfterDismiss = null;\n }\n }\n\n // ---------------------------------------------------------------\n // Internal: guards\n // ---------------------------------------------------------------\n\n _canFloat(reason: FloatingState): boolean {\n if (!this.player.options.floating) return false;\n if (!this.player.container) return false;\n if (!this.player.element || this.player.element.tagName !== 'VIDEO') return false;\n if (this.player.state.fullscreen) return false;\n\n // Playlist players move through multiple tracks and manage their own\n // UI; floating support for playlists is out of scope for this v1.\n if (this.player.playlistManager) return false;\n\n const minWidth = this.player.options.floatingMinViewportWidth ?? 768;\n if (window.innerWidth < minWidth) return false;\n\n // Auto-float only engages when the user is actively watching.\n if (reason === 'auto') {\n if (this._autoDismissedThisPlay) return false;\n if (this.player.state.paused) return false;\n // Never auto-float before the user has started playback; stops\n // auto-entry from firing while the page is still below the fold\n // on initial load.\n if (!this.player.state.hasStartedPlayback) return false;\n }\n\n return true;\n }\n\n _claimSingleton() {\n try {\n window.dispatchEvent(new CustomEvent(FLOATING_CLAIM_EVENT, {\n detail: { claimId: this._claimId }\n }));\n } catch { /* ignore (older browsers) */ }\n }\n\n _setupClaimListener() {\n this._onClaim = (event: Event) => {\n const detail = (event as CustomEvent).detail;\n if (!detail || detail.claimId === this._claimId) return;\n if (this.player.state.floating) {\n this.exit('claim');\n }\n };\n window.addEventListener(FLOATING_CLAIM_EVENT, this._onClaim as EventListener);\n\n this._onResize = () => {\n const minWidth = this.player.options.floatingMinViewportWidth ?? 768;\n if (this.player.state.floating && window.innerWidth < minWidth) {\n this.exit('auto');\n }\n };\n window.addEventListener('resize', this._onResize);\n }\n\n _setupFullscreenGuard() {\n this._onEnterFullscreen = () => {\n if (this.player.state.floating) {\n this.exit('manual');\n }\n };\n this.player.on('enterfullscreen', this._onEnterFullscreen as any);\n }\n\n _armPlayListenerToClearDismiss() {\n if (this._playListenerAttached) return;\n this._onPlayAfterDismiss = () => {\n this._autoDismissedThisPlay = false;\n if (this._onPlayAfterDismiss) {\n this.player.off('play', this._onPlayAfterDismiss as any);\n }\n this._playListenerAttached = false;\n this._onPlayAfterDismiss = null;\n };\n this.player.on('play', this._onPlayAfterDismiss as any);\n this._playListenerAttached = true;\n }\n\n // ---------------------------------------------------------------\n // Internal: IntersectionObserver for scroll-triggered auto-float\n // ---------------------------------------------------------------\n\n _startObserving() {\n if (!('IntersectionObserver' in window)) return;\n if (!this.player.container) return;\n\n this.observerTarget = this.player.container;\n this.intersectionObserver = new IntersectionObserver((entries) => {\n const entry = entries[entries.length - 1];\n if (!entry) return;\n this.lastRatio = entry.intersectionRatio;\n\n if (this.player.options.debug) {\n try {\n console.log('[vidply:floating] intersection', {\n ratio: Number(entry.intersectionRatio.toFixed(3)),\n state: this.player.state.floating,\n paused: this.player.state.paused,\n hasStartedPlayback: this.player.state.hasStartedPlayback,\n dismissed: this._autoDismissedThisPlay\n });\n } catch { /* ignore */ }\n }\n\n if (this.player.state.floating === 'auto') {\n if (entry.intersectionRatio > 0.5) {\n this.exit('auto');\n }\n return;\n }\n\n // Pinned state: scroll is a no-op, the user has taken control.\n if (this.player.state.floating === 'pinned') {\n return;\n }\n\n if (entry.intersectionRatio < 0.1 && this._canFloat('auto')) {\n this.enter('auto');\n }\n }, { threshold: [0, 0.1, 0.5, 0.9] });\n\n this.intersectionObserver.observe(this.observerTarget);\n }\n\n _retargetObserver(target: HTMLElement) {\n if (!this.intersectionObserver) return;\n if (this.observerTarget) {\n try { this.intersectionObserver.unobserve(this.observerTarget); } catch { /* ignore */ }\n }\n this.observerTarget = target;\n try { this.intersectionObserver.observe(target); } catch { /* ignore */ }\n }\n\n // ---------------------------------------------------------------\n // Internal: shell DOM\n // ---------------------------------------------------------------\n\n _ensureShell() {\n if (this.shell) return;\n\n this.shell = DOMUtils.createElement('div', {\n className: `${this.classPrefix}-floating-shell`,\n attributes: {\n 'role': 'dialog',\n 'aria-modal': 'false',\n 'aria-label': i18n.t('player.floatingPlayer'),\n 'data-vidply-floating': 'true',\n 'tabindex': '-1'\n }\n });\n\n this.dragHandle = DOMUtils.createElement('div', {\n className: `${this.classPrefix}-floating-drag-handle`,\n attributes: { 'aria-hidden': 'true' }\n });\n this.shell.appendChild(this.dragHandle);\n\n this.closeButton = DOMUtils.createElement('button', {\n className: `${this.classPrefix}-floating-close`,\n attributes: {\n 'type': 'button',\n 'aria-label': i18n.t('player.floatingPlayerClose'),\n 'title': i18n.t('player.floatingPlayerClose')\n }\n }) as HTMLButtonElement;\n this.closeButton.appendChild(createIconElement('close'));\n this.closeButton.addEventListener('click', (event) => {\n event.stopPropagation();\n this.dismiss();\n });\n this.shell.appendChild(this.closeButton);\n\n this._createResizeHandles();\n this.resizeHandles.forEach(handle => this.shell!.appendChild(handle));\n\n this._onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n event.stopPropagation();\n this.dismiss();\n }\n };\n this.shell.addEventListener('keydown', this._onKeyDown as EventListener);\n }\n\n _createResizeHandles() {\n const dirs = ['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'];\n this.resizeHandles = dirs.map(dir => DOMUtils.createElement('div', {\n className: `${this.classPrefix}-floating-resize-handle ${this.classPrefix}-floating-resize-${dir}`,\n attributes: {\n 'data-direction': dir,\n 'data-vidply-managed-resize': 'true',\n 'aria-hidden': 'true'\n }\n }));\n }\n\n _teardownShell() {\n if (this.draggable) {\n try { this.draggable.destroy(); } catch { /* ignore */ }\n this.draggable = null;\n }\n if (this.shell) {\n if (this._onKeyDown) {\n this.shell.removeEventListener('keydown', this._onKeyDown as EventListener);\n this._onKeyDown = null;\n }\n if (this.shell.parentNode) {\n this.shell.parentNode.removeChild(this.shell);\n }\n }\n this.shell = null;\n this.dragHandle = null;\n this.closeButton = null;\n this.resizeHandles = [];\n }\n\n // ---------------------------------------------------------------\n // Internal: mount / unmount the player.container\n // ---------------------------------------------------------------\n\n _mountIntoShell() {\n const container = this.player.container;\n if (!container || !container.parentNode) return;\n if (!this.shell) return;\n\n const rect = container.getBoundingClientRect();\n this.originalParent = container.parentNode as HTMLElement;\n this.originalNextSibling = container.nextSibling;\n\n this.placeholder = DOMUtils.createElement('div', {\n className: `${this.classPrefix}-floating-placeholder`,\n attributes: { 'aria-hidden': 'true' }\n });\n this.placeholder.style.width = `${Math.max(1, rect.width)}px`;\n this.placeholder.style.height = `${Math.max(1, rect.height)}px`;\n\n this.originalParent.insertBefore(this.placeholder, container);\n\n this.shell.appendChild(container);\n document.body.appendChild(this.shell);\n\n container.classList.add(`${this.classPrefix}-is-floating`);\n\n // Observe the placeholder while floating so scroll-back decisions are\n // anchored to the original slot instead of the moved container.\n this._retargetObserver(this.placeholder);\n }\n\n _unmountFromShell() {\n const container = this.player.container;\n\n if (container) {\n container.classList.remove(`${this.classPrefix}-is-floating`);\n // Clear inline sizes applied while floating\n container.style.removeProperty('width');\n container.style.removeProperty('height');\n }\n\n if (this.placeholder && this.placeholder.parentNode) {\n if (container) {\n this.placeholder.parentNode.insertBefore(container, this.placeholder);\n }\n this.placeholder.parentNode.removeChild(this.placeholder);\n } else if (container && this.originalParent) {\n if (this.originalNextSibling && this.originalNextSibling.parentNode === this.originalParent) {\n this.originalParent.insertBefore(container, this.originalNextSibling);\n } else {\n this.originalParent.appendChild(container);\n }\n }\n\n this.placeholder = null;\n this.originalParent = null;\n this.originalNextSibling = null;\n\n // Retarget the observer to the docked container\n if (container) {\n this._retargetObserver(container);\n }\n }\n\n // ---------------------------------------------------------------\n // Internal: initial geometry + drag/resize wiring\n // ---------------------------------------------------------------\n\n _applyInitialGeometry() {\n if (!this.shell) return;\n\n const prefs = (this.player.storage?.getFloatingPreferences?.() || {}) as FloatingPrefs;\n\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n let width = prefs.width && prefs.width >= MIN_WIDTH ? prefs.width : DEFAULT_WIDTH;\n width = Math.min(width, Math.max(MIN_WIDTH, vw - EDGE_MARGIN * 2));\n\n // If we know the source container's aspect ratio, match it by default.\n const containerRect = this.player.container?.getBoundingClientRect();\n const aspect = containerRect && containerRect.height > 0\n ? containerRect.width / containerRect.height\n : 16 / 9;\n const defaultHeight = Math.round(width / aspect);\n let height = prefs.height && prefs.height >= 100 ? prefs.height : defaultHeight;\n height = Math.min(height, Math.max(100, vh - EDGE_MARGIN * 2));\n\n let left: number;\n let top: number;\n\n if (typeof prefs.left === 'number' && typeof prefs.top === 'number') {\n left = Math.max(EDGE_MARGIN, Math.min(prefs.left, vw - width - EDGE_MARGIN));\n top = Math.max(EDGE_MARGIN, Math.min(prefs.top, vh - height - EDGE_MARGIN));\n } else {\n const pos = this.player.options.floatingPosition || 'bottom-right';\n switch (pos) {\n case 'bottom-left':\n left = EDGE_MARGIN;\n top = vh - height - EDGE_MARGIN;\n break;\n case 'top-right':\n left = vw - width - EDGE_MARGIN;\n top = EDGE_MARGIN;\n break;\n case 'top-left':\n left = EDGE_MARGIN;\n top = EDGE_MARGIN;\n break;\n case 'bottom-right':\n default:\n left = vw - width - EDGE_MARGIN;\n top = vh - height - EDGE_MARGIN;\n break;\n }\n }\n\n this.shell.style.width = `${width}px`;\n this.shell.style.height = `${height}px`;\n this.shell.style.left = `${left}px`;\n this.shell.style.top = `${top}px`;\n\n this._initDraggable();\n }\n\n _initDraggable() {\n if (!this.shell) return;\n if (this.draggable) return;\n\n this.draggable = new DraggableResizable(this.shell, {\n dragHandle: this.dragHandle,\n resizeHandles: this.resizeHandles,\n constrainToViewport: true,\n maintainAspectRatio: true,\n minWidth: MIN_WIDTH,\n minHeight: 100,\n maxWidth: () => Math.max(MIN_WIDTH, window.innerWidth - EDGE_MARGIN * 2),\n maxHeight: () => Math.max(100, window.innerHeight - EDGE_MARGIN * 2),\n classPrefix: `${this.classPrefix}-floating`,\n keyboardDragKey: 'd',\n keyboardResizeKey: 'r',\n keyboardStep: 10,\n keyboardStepLarge: 50,\n pointerResizeIndicatorText: i18n.t('player.floatingPlayerDialog'),\n onDragEnd: () => this._savePrefs(),\n onResizeEnd: () => this._savePrefs(),\n onDragStart: (event: Event) => {\n const target = event.target as HTMLElement;\n if (!target) return true;\n // Don't start drag when interacting with the close button or\n // with any control inside the embedded player (play/pause,\n // captions menu, etc.).\n if (target.closest(`.${this.classPrefix}-floating-close`)) return false;\n if (target.closest(`.${this.classPrefix}-controls`)) return false;\n if (target.closest(`.${this.classPrefix}-floating-resize-handle`)) return false;\n return true;\n }\n });\n }\n\n _savePrefs() {\n if (!this.shell || !this.player.storage?.saveFloatingPreferences) return;\n const rect = this.shell.getBoundingClientRect();\n this.player.storage.saveFloatingPreferences({\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n left: Math.round(rect.left),\n top: Math.round(rect.top)\n });\n }\n\n _activeElement(): HTMLElement | null {\n const active = document.activeElement;\n return active && active instanceof HTMLElement ? active : null;\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Floating Player Manager\n *\n * Custom in-page Picture-in-Picture. Moves the entire player.container\n * into a position:fixed, draggable and resizable shell that lives outside\n * the document flow (appended to document.body). A transparent placeholder\n * preserves layout and, while floating, serves as the IntersectionObserver\n * sentinel so scroll-based auto-float/redock decisions stay anchored to\n * the original slot.\n *\n * Triggers:\n * - pinned: the user clicks the control-bar PiP button (only when\n * options.floating is true; otherwise the button uses native PiP).\n * Pinned floating ignores scroll-based docking.\n * - auto: the video is playing and the original slot has scrolled out\n * of the viewport. Auto-float redocks automatically when the slot\n * scrolls back in.\n *\n * Close button: pauses playback, exits the floating shell and marks the\n * current play session as dismissed so auto-float will not re-trigger\n * until the user presses play again (matches YouTube miniplayer UX).\n *\n * Only one player is allowed to float at a time across a page; enter()\n * broadcasts a 'vidply:floating-claim' CustomEvent that other managers\n * listen for and auto-exit on.\n */\n\nimport { DOMUtils } from '../utils/DOMUtils.js';\nimport { DraggableResizable } from '../utils/DraggableResizable.js';\nimport { createIconElement } from '../icons/Icons.js';\nimport { i18n } from '../i18n/i18n.js';\nimport type { Player } from './Player.js';\n\ntype FloatingState = 'pinned' | 'auto';\ntype ExitReason = 'manual' | 'auto' | 'dismiss' | 'claim' | 'destroy';\n\nconst FLOATING_CLAIM_EVENT = 'vidply:floating-claim';\nconst DEFAULT_WIDTH = 400;\nconst MIN_WIDTH = 240;\nconst EDGE_MARGIN = 16;\n\ninterface FloatingPrefs {\n width?: number;\n height?: number;\n left?: number;\n top?: number;\n}\n\nexport class FloatingPlayerManager {\n player: Player;\n classPrefix: string;\n\n shell: HTMLElement | null;\n dragHandle: HTMLElement | null;\n closeButton: HTMLButtonElement | null;\n resizeHandles: HTMLElement[];\n placeholder: HTMLElement | null;\n draggable: DraggableResizable | null;\n\n originalParent: HTMLElement | null;\n originalNextSibling: Node | null;\n\n intersectionObserver: IntersectionObserver | null;\n observerTarget: HTMLElement | null;\n lastRatio: number;\n\n _autoDismissedThisPlay: boolean;\n _playListenerAttached: boolean;\n _onPlayAfterDismiss: (() => void) | null;\n _onClaim: ((event: Event) => void) | null;\n _onResize: (() => void) | null;\n _onKeyDown: ((event: KeyboardEvent) => void) | null;\n _onEnterFullscreen: (() => void) | null;\n _destroyed: boolean;\n _triggerFocusEl: HTMLElement | null;\n _claimId: string;\n\n constructor(player: Player) {\n this.player = player;\n this.classPrefix = player.options.classPrefix || 'vidply';\n\n this.shell = null;\n this.dragHandle = null;\n this.closeButton = null;\n this.resizeHandles = [];\n this.placeholder = null;\n this.draggable = null;\n\n this.originalParent = null;\n this.originalNextSibling = null;\n\n this.intersectionObserver = null;\n this.observerTarget = null;\n this.lastRatio = 1;\n\n this._autoDismissedThisPlay = false;\n this._playListenerAttached = false;\n this._onPlayAfterDismiss = null;\n this._onClaim = null;\n this._onResize = null;\n this._onKeyDown = null;\n this._onEnterFullscreen = null;\n this._destroyed = false;\n this._triggerFocusEl = null;\n this._claimId = `floating-${player.instanceId}-${Date.now()}`;\n\n this._setupClaimListener();\n this._setupFullscreenGuard();\n this._startObserving();\n }\n\n // ---------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------\n\n togglePinned(triggerEl?: HTMLElement | null) {\n if (this._destroyed) return;\n if (this.player.state.floating === 'pinned') {\n // Manual unpin: suppress auto-float for the remainder of the\n // current play session so scrolling doesn't immediately re-pop\n // the floating shell. A fresh 'play' event clears the flag.\n this._autoDismissedThisPlay = true;\n this._armPlayListenerToClearDismiss();\n this.exit('manual');\n return;\n }\n // If the user pins while in 'auto' mode, that's an explicit request\n // to float; any previous auto-dismiss flag should be cleared so the\n // pinned state behaves naturally.\n this._autoDismissedThisPlay = false;\n this._triggerFocusEl = triggerEl || this._activeElement();\n this.enter('pinned');\n }\n\n enter(reason: FloatingState) {\n if (this._destroyed) return;\n if (this.player.state.floating === reason) return;\n\n if (!this._canFloat(reason)) {\n return;\n }\n\n // Upgrade 'auto' -> 'pinned' without rebuilding the shell\n if (this.player.state.floating && this.player.state.floating !== reason) {\n this.player.state.floating = reason;\n this.player.emit('floatingchange', reason);\n return;\n }\n\n this._claimSingleton();\n\n this._ensureShell();\n this._mountIntoShell();\n this._applyInitialGeometry();\n\n this.player.state.floating = reason;\n this.player.emit('floatingchange', reason);\n\n // Focus the close button after a microtask so screen readers announce\n // the dialog opening.\n queueMicrotask(() => {\n if (this.closeButton && this.player.state.floating) {\n try { this.closeButton.focus({ preventScroll: true }); } catch { /* ignore */ }\n }\n });\n }\n\n exit(reason: ExitReason = 'manual') {\n if (this._destroyed && reason !== 'destroy') return;\n if (!this.player.state.floating) return;\n\n this._unmountFromShell();\n this._teardownShell();\n\n const priorTrigger = this._triggerFocusEl;\n this._triggerFocusEl = null;\n\n this.player.state.floating = null;\n this.player.emit('floatingchange', null);\n\n // Restore focus to the element that triggered floating (pinned flow).\n // For scroll-based exits we leave focus untouched.\n if ((reason === 'manual' || reason === 'dismiss') && priorTrigger) {\n try { priorTrigger.focus({ preventScroll: true }); } catch { /* ignore */ }\n }\n }\n\n /**\n * Close button: pause, dismiss, and prevent auto-float until the next\n * user-initiated play event.\n */\n dismiss() {\n if (this._destroyed) return;\n this._autoDismissedThisPlay = true;\n this._armPlayListenerToClearDismiss();\n\n try {\n this.player.pause();\n } catch { /* ignore */ }\n\n this.exit('dismiss');\n }\n\n destroy() {\n if (this._destroyed) return;\n this._destroyed = true;\n\n if (this.player.state && this.player.state.floating) {\n try { this.exit('destroy'); } catch { /* ignore */ }\n }\n\n if (this.intersectionObserver) {\n try { this.intersectionObserver.disconnect(); } catch { /* ignore */ }\n this.intersectionObserver = null;\n }\n this.observerTarget = null;\n\n if (this._onClaim) {\n window.removeEventListener(FLOATING_CLAIM_EVENT, this._onClaim as EventListener);\n this._onClaim = null;\n }\n if (this._onResize) {\n window.removeEventListener('resize', this._onResize);\n this._onResize = null;\n }\n if (this._onEnterFullscreen) {\n this.player.off('enterfullscreen', this._onEnterFullscreen as any);\n this._onEnterFullscreen = null;\n }\n if (this._onPlayAfterDismiss && this._playListenerAttached) {\n this.player.off('play', this._onPlayAfterDismiss as any);\n this._playListenerAttached = false;\n this._onPlayAfterDismiss = null;\n }\n }\n\n // ---------------------------------------------------------------\n // Internal: guards\n // ---------------------------------------------------------------\n\n _canFloat(reason: FloatingState): boolean {\n if (!this.player.options.floating) return false;\n if (!this.player.container) return false;\n if (!this.player.element || this.player.element.tagName !== 'VIDEO') return false;\n if (this.player.state.fullscreen) return false;\n\n // Playlist players move through multiple tracks and manage their own\n // UI; floating support for playlists is out of scope for this v1.\n if (this.player.playlistManager) return false;\n\n const minWidth = this.player.options.floatingMinViewportWidth ?? 768;\n if (window.innerWidth < minWidth) return false;\n\n // Auto-float only engages when the user is actively watching.\n if (reason === 'auto') {\n if (this._autoDismissedThisPlay) return false;\n if (this.player.state.paused) return false;\n // Never auto-float before the user has started playback; stops\n // auto-entry from firing while the page is still below the fold\n // on initial load.\n if (!this.player.state.hasStartedPlayback) return false;\n }\n\n return true;\n }\n\n _claimSingleton() {\n try {\n window.dispatchEvent(new CustomEvent(FLOATING_CLAIM_EVENT, {\n detail: { claimId: this._claimId }\n }));\n } catch { /* ignore (older browsers) */ }\n }\n\n _setupClaimListener() {\n this._onClaim = (event: Event) => {\n const detail = (event as CustomEvent).detail;\n if (!detail || detail.claimId === this._claimId) return;\n if (this.player.state.floating) {\n this.exit('claim');\n }\n };\n window.addEventListener(FLOATING_CLAIM_EVENT, this._onClaim as EventListener);\n\n this._onResize = () => {\n const minWidth = this.player.options.floatingMinViewportWidth ?? 768;\n if (this.player.state.floating && window.innerWidth < minWidth) {\n this.exit('auto');\n }\n };\n window.addEventListener('resize', this._onResize);\n }\n\n _setupFullscreenGuard() {\n this._onEnterFullscreen = () => {\n if (this.player.state.floating) {\n this.exit('manual');\n }\n };\n this.player.on('enterfullscreen', this._onEnterFullscreen as any);\n }\n\n _armPlayListenerToClearDismiss() {\n if (this._playListenerAttached) return;\n this._onPlayAfterDismiss = () => {\n this._autoDismissedThisPlay = false;\n if (this._onPlayAfterDismiss) {\n this.player.off('play', this._onPlayAfterDismiss as any);\n }\n this._playListenerAttached = false;\n this._onPlayAfterDismiss = null;\n };\n this.player.on('play', this._onPlayAfterDismiss as any);\n this._playListenerAttached = true;\n }\n\n // ---------------------------------------------------------------\n // Internal: IntersectionObserver for scroll-triggered auto-float\n // ---------------------------------------------------------------\n\n _startObserving() {\n if (!('IntersectionObserver' in window)) return;\n if (!this.player.container) return;\n\n this.observerTarget = this.player.container;\n this.intersectionObserver = new IntersectionObserver((entries) => {\n const entry = entries[entries.length - 1];\n if (!entry) return;\n this.lastRatio = entry.intersectionRatio;\n\n if (this.player.options.debug) {\n try {\n console.log('[vidply:floating] intersection', {\n ratio: Number(entry.intersectionRatio.toFixed(3)),\n state: this.player.state.floating,\n paused: this.player.state.paused,\n hasStartedPlayback: this.player.state.hasStartedPlayback,\n dismissed: this._autoDismissedThisPlay\n });\n } catch { /* ignore */ }\n }\n\n if (this.player.state.floating === 'auto') {\n if (entry.intersectionRatio > 0.5) {\n this.exit('auto');\n }\n return;\n }\n\n // Pinned state: scroll is a no-op, the user has taken control.\n if (this.player.state.floating === 'pinned') {\n return;\n }\n\n if (entry.intersectionRatio < 0.1 && this._canFloat('auto')) {\n this.enter('auto');\n }\n }, { threshold: [0, 0.1, 0.5, 0.9] });\n\n this.intersectionObserver.observe(this.observerTarget);\n }\n\n _retargetObserver(target: HTMLElement) {\n if (!this.intersectionObserver) return;\n if (this.observerTarget) {\n try { this.intersectionObserver.unobserve(this.observerTarget); } catch { /* ignore */ }\n }\n this.observerTarget = target;\n try { this.intersectionObserver.observe(target); } catch { /* ignore */ }\n }\n\n // ---------------------------------------------------------------\n // Internal: shell DOM\n // ---------------------------------------------------------------\n\n _ensureShell() {\n if (this.shell) return;\n\n this.shell = DOMUtils.createElement('div', {\n className: `${this.classPrefix}-floating-shell`,\n attributes: {\n 'role': 'dialog',\n 'aria-modal': 'false',\n 'aria-label': i18n.t('player.floatingPlayer'),\n 'data-vidply-floating': 'true',\n 'tabindex': '-1'\n }\n });\n\n this.dragHandle = DOMUtils.createElement('div', {\n className: `${this.classPrefix}-floating-drag-handle`,\n attributes: { 'aria-hidden': 'true' }\n });\n this.shell.appendChild(this.dragHandle);\n\n this.closeButton = DOMUtils.createElement('button', {\n className: `${this.classPrefix}-floating-close`,\n attributes: {\n 'type': 'button',\n 'aria-label': i18n.t('player.floatingPlayerClose'),\n 'title': i18n.t('player.floatingPlayerClose')\n }\n }) as HTMLButtonElement;\n this.closeButton.appendChild(createIconElement('close'));\n this.closeButton.addEventListener('click', (event) => {\n event.stopPropagation();\n this.dismiss();\n });\n this.shell.appendChild(this.closeButton);\n\n this._createResizeHandles();\n this.resizeHandles.forEach(handle => this.shell!.appendChild(handle));\n\n this._onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n event.stopPropagation();\n this.dismiss();\n }\n };\n this.shell.addEventListener('keydown', this._onKeyDown as EventListener);\n }\n\n _createResizeHandles() {\n // Resize handles are always-on for the floating shell. Do NOT set\n // `data-vidply-managed-resize=\"true\"`: that flag is used by the\n // transcript / sign-language overlays to gate the handles behind\n // an \"R\" keypress, and DraggableResizable hides managed handles\n // during init() — which would leave the shell with no visible or\n // hittable edges/corners.\n const dirs = ['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'];\n this.resizeHandles = dirs.map(dir => DOMUtils.createElement('div', {\n className: `${this.classPrefix}-floating-resize-handle ${this.classPrefix}-floating-resize-${dir}`,\n attributes: {\n 'data-direction': dir,\n 'aria-hidden': 'true'\n }\n }));\n }\n\n _teardownShell() {\n if (this.draggable) {\n try { this.draggable.destroy(); } catch { /* ignore */ }\n this.draggable = null;\n }\n if (this.shell) {\n if (this._onKeyDown) {\n this.shell.removeEventListener('keydown', this._onKeyDown as EventListener);\n this._onKeyDown = null;\n }\n if (this.shell.parentNode) {\n this.shell.parentNode.removeChild(this.shell);\n }\n }\n this.shell = null;\n this.dragHandle = null;\n this.closeButton = null;\n this.resizeHandles = [];\n }\n\n // ---------------------------------------------------------------\n // Internal: mount / unmount the player.container\n // ---------------------------------------------------------------\n\n _mountIntoShell() {\n const container = this.player.container;\n if (!container || !container.parentNode) return;\n if (!this.shell) return;\n\n const rect = container.getBoundingClientRect();\n this.originalParent = container.parentNode as HTMLElement;\n this.originalNextSibling = container.nextSibling;\n\n this.placeholder = DOMUtils.createElement('div', {\n className: `${this.classPrefix}-floating-placeholder`,\n attributes: { 'aria-hidden': 'true' }\n });\n this.placeholder.style.width = `${Math.max(1, rect.width)}px`;\n this.placeholder.style.height = `${Math.max(1, rect.height)}px`;\n\n this.originalParent.insertBefore(this.placeholder, container);\n\n this.shell.appendChild(container);\n document.body.appendChild(this.shell);\n\n container.classList.add(`${this.classPrefix}-is-floating`);\n\n // Observe the placeholder while floating so scroll-back decisions are\n // anchored to the original slot instead of the moved container.\n this._retargetObserver(this.placeholder);\n }\n\n _unmountFromShell() {\n const container = this.player.container;\n\n if (container) {\n container.classList.remove(`${this.classPrefix}-is-floating`);\n // Clear inline sizes applied while floating\n container.style.removeProperty('width');\n container.style.removeProperty('height');\n }\n\n if (this.placeholder && this.placeholder.parentNode) {\n if (container) {\n this.placeholder.parentNode.insertBefore(container, this.placeholder);\n }\n this.placeholder.parentNode.removeChild(this.placeholder);\n } else if (container && this.originalParent) {\n if (this.originalNextSibling && this.originalNextSibling.parentNode === this.originalParent) {\n this.originalParent.insertBefore(container, this.originalNextSibling);\n } else {\n this.originalParent.appendChild(container);\n }\n }\n\n this.placeholder = null;\n this.originalParent = null;\n this.originalNextSibling = null;\n\n // Retarget the observer to the docked container\n if (container) {\n this._retargetObserver(container);\n }\n }\n\n // ---------------------------------------------------------------\n // Internal: initial geometry + drag/resize wiring\n // ---------------------------------------------------------------\n\n _applyInitialGeometry() {\n if (!this.shell) return;\n\n const prefs = (this.player.storage?.getFloatingPreferences?.() || {}) as FloatingPrefs;\n\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n let width = prefs.width && prefs.width >= MIN_WIDTH ? prefs.width : DEFAULT_WIDTH;\n width = Math.min(width, Math.max(MIN_WIDTH, vw - EDGE_MARGIN * 2));\n\n // If we know the source container's aspect ratio, match it by default.\n const containerRect = this.player.container?.getBoundingClientRect();\n const aspect = containerRect && containerRect.height > 0\n ? containerRect.width / containerRect.height\n : 16 / 9;\n const defaultHeight = Math.round(width / aspect);\n let height = prefs.height && prefs.height >= 100 ? prefs.height : defaultHeight;\n height = Math.min(height, Math.max(100, vh - EDGE_MARGIN * 2));\n\n let left: number;\n let top: number;\n\n if (typeof prefs.left === 'number' && typeof prefs.top === 'number') {\n left = Math.max(EDGE_MARGIN, Math.min(prefs.left, vw - width - EDGE_MARGIN));\n top = Math.max(EDGE_MARGIN, Math.min(prefs.top, vh - height - EDGE_MARGIN));\n } else {\n const pos = this.player.options.floatingPosition || 'bottom-right';\n switch (pos) {\n case 'bottom-left':\n left = EDGE_MARGIN;\n top = vh - height - EDGE_MARGIN;\n break;\n case 'top-right':\n left = vw - width - EDGE_MARGIN;\n top = EDGE_MARGIN;\n break;\n case 'top-left':\n left = EDGE_MARGIN;\n top = EDGE_MARGIN;\n break;\n case 'bottom-right':\n default:\n left = vw - width - EDGE_MARGIN;\n top = vh - height - EDGE_MARGIN;\n break;\n }\n }\n\n this.shell.style.width = `${width}px`;\n this.shell.style.height = `${height}px`;\n this.shell.style.left = `${left}px`;\n this.shell.style.top = `${top}px`;\n\n this._initDraggable();\n }\n\n _initDraggable() {\n if (!this.shell) return;\n if (this.draggable) return;\n\n this.draggable = new DraggableResizable(this.shell, {\n dragHandle: this.dragHandle,\n resizeHandles: this.resizeHandles,\n constrainToViewport: true,\n maintainAspectRatio: true,\n minWidth: MIN_WIDTH,\n minHeight: 100,\n maxWidth: () => Math.max(MIN_WIDTH, window.innerWidth - EDGE_MARGIN * 2),\n maxHeight: () => Math.max(100, window.innerHeight - EDGE_MARGIN * 2),\n classPrefix: `${this.classPrefix}-floating`,\n keyboardDragKey: 'd',\n keyboardResizeKey: 'r',\n keyboardStep: 10,\n keyboardStepLarge: 50,\n pointerResizeIndicatorText: i18n.t('player.floatingPlayerDialog'),\n onDragEnd: () => this._savePrefs(),\n onResizeEnd: () => this._savePrefs(),\n onDragStart: (event: Event) => {\n const target = event.target as HTMLElement;\n if (!target) return true;\n // Don't start drag when interacting with the close button or\n // with any control inside the embedded player (play/pause,\n // captions menu, etc.).\n if (target.closest(`.${this.classPrefix}-floating-close`)) return false;\n if (target.closest(`.${this.classPrefix}-controls`)) return false;\n if (target.closest(`.${this.classPrefix}-floating-resize-handle`)) return false;\n return true;\n }\n });\n }\n\n _savePrefs() {\n if (!this.shell || !this.player.storage?.saveFloatingPreferences) return;\n const rect = this.shell.getBoundingClientRect();\n this.player.storage.saveFloatingPreferences({\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n left: Math.round(rect.left),\n top: Math.round(rect.top)\n });\n }\n\n _activeElement(): HTMLElement | null {\n const active = document.activeElement;\n return active && active instanceof HTMLElement ? active : null;\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -2831,7 +2831,8 @@ var ControlBar = class {
2831
2831
  iconName = "volumeHigh";
2832
2832
  }
2833
2833
  icon.innerHTML = createIconElement(iconName).innerHTML;
2834
- const newMuteAriaLabel = this.player.state.muted ? i18n.t("player.unmute") : i18n.t("player.mute");
2834
+ const volumePercent = this.player.state.muted ? 0 : Math.round(percent);
2835
+ const newMuteAriaLabel = this.isTouchDevice() ? this.player.state.muted ? i18n.t("player.unmute") : i18n.t("player.mute") : `${i18n.t("player.volume")} ${volumePercent}%`;
2835
2836
  this.controls.mute.setAttribute("aria-label", newMuteAriaLabel);
2836
2837
  DOMUtils.attachTooltip(this.controls.mute, newMuteAriaLabel, this.player.options.classPrefix);
2837
2838
  }
@@ -3630,7 +3631,7 @@ async function loadSignLanguageManager() {
3630
3631
  }
3631
3632
  async function loadFloatingPlayerManager() {
3632
3633
  if (!FloatingPlayerManagerModule) {
3633
- const module = await import("./vidply.FloatingPlayerManager-5EA4BYSR.js");
3634
+ const module = await import("./vidply.FloatingPlayerManager-AEMEBLF7.js");
3634
3635
  FloatingPlayerManagerModule = module.FloatingPlayerManager;
3635
3636
  }
3636
3637
  return FloatingPlayerManagerModule;