@videojs/html 10.0.0-beta.2 → 10.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/cdn/audio-minimal.css +1 -1
  2. package/cdn/audio-minimal.dev.js +197 -126
  3. package/cdn/audio-minimal.dev.js.map +1 -1
  4. package/cdn/audio-minimal.js +5 -5
  5. package/cdn/audio-minimal.js.map +1 -1
  6. package/cdn/audio.css +1 -1
  7. package/cdn/audio.dev.js +191 -120
  8. package/cdn/audio.dev.js.map +1 -1
  9. package/cdn/audio.js +5 -5
  10. package/cdn/audio.js.map +1 -1
  11. package/cdn/background.dev.js +40 -25
  12. package/cdn/background.dev.js.map +1 -1
  13. package/cdn/background.js +4 -4
  14. package/cdn/background.js.map +1 -1
  15. package/cdn/media/hls-video.dev.js +0 -1
  16. package/cdn/media/hls-video.dev.js.map +1 -1
  17. package/cdn/media/hls-video.js +1 -1
  18. package/cdn/media/hls-video.js.map +1 -1
  19. package/cdn/media/simple-hls-video.dev.js +178 -158
  20. package/cdn/media/simple-hls-video.dev.js.map +1 -1
  21. package/cdn/media/simple-hls-video.js +1 -1
  22. package/cdn/media/simple-hls-video.js.map +1 -1
  23. package/cdn/video-minimal.css +1 -1
  24. package/cdn/video-minimal.dev.js +220 -161
  25. package/cdn/video-minimal.dev.js.map +1 -1
  26. package/cdn/video-minimal.js +5 -5
  27. package/cdn/video-minimal.js.map +1 -1
  28. package/cdn/video.css +1 -1
  29. package/cdn/video.dev.js +217 -158
  30. package/cdn/video.dev.js.map +1 -1
  31. package/cdn/video.js +4 -4
  32. package/cdn/video.js.map +1 -1
  33. package/dist/default/_virtual/inline-css_src/define/audio/minimal-skin.js +1 -1
  34. package/dist/default/_virtual/inline-css_src/define/audio/minimal-skin.js.map +1 -1
  35. package/dist/default/_virtual/inline-css_src/define/audio/skin.js +1 -1
  36. package/dist/default/_virtual/inline-css_src/define/audio/skin.js.map +1 -1
  37. package/dist/default/_virtual/inline-css_src/define/base.js +6 -0
  38. package/dist/default/_virtual/inline-css_src/define/base.js.map +1 -0
  39. package/dist/default/_virtual/inline-css_src/define/video/minimal-skin.js +1 -1
  40. package/dist/default/_virtual/inline-css_src/define/video/minimal-skin.js.map +1 -1
  41. package/dist/default/_virtual/inline-css_src/define/video/skin.js +1 -1
  42. package/dist/default/_virtual/inline-css_src/define/video/skin.js.map +1 -1
  43. package/dist/default/define/audio/minimal-skin.css +8 -2
  44. package/dist/default/define/audio/minimal-skin.js +2 -1
  45. package/dist/default/define/audio/minimal-skin.js.map +1 -1
  46. package/dist/default/define/audio/minimal-skin.tailwind.js +5 -2
  47. package/dist/default/define/audio/minimal-skin.tailwind.js.map +1 -1
  48. package/dist/default/define/audio/skin.css +7 -5
  49. package/dist/default/define/audio/skin.js +2 -1
  50. package/dist/default/define/audio/skin.js.map +1 -1
  51. package/dist/default/define/audio/skin.tailwind.js +5 -2
  52. package/dist/default/define/audio/skin.tailwind.js.map +1 -1
  53. package/dist/default/define/base.css +25 -0
  54. package/dist/default/define/shared.css +3 -0
  55. package/dist/default/define/skin-mixin.js +10 -18
  56. package/dist/default/define/skin-mixin.js.map +1 -1
  57. package/dist/default/define/video/minimal-skin.css +35 -73
  58. package/dist/default/define/video/minimal-skin.js +2 -1
  59. package/dist/default/define/video/minimal-skin.js.map +1 -1
  60. package/dist/default/define/video/minimal-skin.tailwind.js +4 -4
  61. package/dist/default/define/video/minimal-skin.tailwind.js.map +1 -1
  62. package/dist/default/define/video/skin.css +32 -71
  63. package/dist/default/define/video/skin.js +2 -1
  64. package/dist/default/define/video/skin.js.map +1 -1
  65. package/dist/default/define/video/skin.tailwind.js +5 -4
  66. package/dist/default/define/video/skin.tailwind.js.map +1 -1
  67. package/dist/default/skins/dist/default/default/tailwind/audio.tailwind.js +3 -21
  68. package/dist/default/skins/dist/default/default/tailwind/audio.tailwind.js.map +1 -1
  69. package/dist/default/skins/dist/default/default/tailwind/components/overlay.js +1 -1
  70. package/dist/default/skins/dist/default/default/tailwind/components/overlay.js.map +1 -1
  71. package/dist/default/skins/dist/default/default/tailwind/components/root.js +1 -1
  72. package/dist/default/skins/dist/default/default/tailwind/components/root.js.map +1 -1
  73. package/dist/default/skins/dist/default/default/tailwind/video.tailwind.js +8 -5
  74. package/dist/default/skins/dist/default/default/tailwind/video.tailwind.js.map +1 -1
  75. package/dist/default/skins/dist/default/minimal/tailwind/audio.tailwind.js +3 -22
  76. package/dist/default/skins/dist/default/minimal/tailwind/audio.tailwind.js.map +1 -1
  77. package/dist/default/skins/dist/default/minimal/tailwind/components/overlay.js +1 -1
  78. package/dist/default/skins/dist/default/minimal/tailwind/components/overlay.js.map +1 -1
  79. package/dist/default/skins/dist/default/minimal/tailwind/components/popup.js +1 -1
  80. package/dist/default/skins/dist/default/minimal/tailwind/components/popup.js.map +1 -1
  81. package/dist/default/skins/dist/default/minimal/tailwind/video.tailwind.js +6 -4
  82. package/dist/default/skins/dist/default/minimal/tailwind/video.tailwind.js.map +1 -1
  83. package/dist/default/skins/dist/default/{default/tailwind/components → shared/tailwind}/icon-state.js +1 -1
  84. package/dist/default/skins/dist/default/shared/tailwind/icon-state.js.map +1 -0
  85. package/dist/{dev/skins/dist/default/default/tailwind/components → default/skins/dist/default/shared/tailwind}/tooltip-state.js +1 -1
  86. package/dist/default/skins/dist/default/shared/tailwind/tooltip-state.js.map +1 -0
  87. package/dist/default/store/container-mixin.js +22 -10
  88. package/dist/default/store/container-mixin.js.map +1 -1
  89. package/dist/default/ui/tooltip/tooltip-group-element.js +4 -1
  90. package/dist/default/ui/tooltip/tooltip-group-element.js.map +1 -1
  91. package/dist/dev/_virtual/inline-css_src/define/audio/minimal-skin.js +1 -1
  92. package/dist/dev/_virtual/inline-css_src/define/audio/minimal-skin.js.map +1 -1
  93. package/dist/dev/_virtual/inline-css_src/define/audio/skin.js +1 -1
  94. package/dist/dev/_virtual/inline-css_src/define/audio/skin.js.map +1 -1
  95. package/dist/dev/_virtual/inline-css_src/define/base.js +6 -0
  96. package/dist/dev/_virtual/inline-css_src/define/base.js.map +1 -0
  97. package/dist/dev/_virtual/inline-css_src/define/video/minimal-skin.js +1 -1
  98. package/dist/dev/_virtual/inline-css_src/define/video/minimal-skin.js.map +1 -1
  99. package/dist/dev/_virtual/inline-css_src/define/video/skin.js +1 -1
  100. package/dist/dev/_virtual/inline-css_src/define/video/skin.js.map +1 -1
  101. package/dist/dev/define/audio/minimal-skin.css +8 -2
  102. package/dist/dev/define/audio/minimal-skin.d.ts.map +1 -1
  103. package/dist/dev/define/audio/minimal-skin.js +67 -64
  104. package/dist/dev/define/audio/minimal-skin.js.map +1 -1
  105. package/dist/dev/define/audio/minimal-skin.tailwind.d.ts.map +1 -1
  106. package/dist/dev/define/audio/minimal-skin.tailwind.js +71 -66
  107. package/dist/dev/define/audio/minimal-skin.tailwind.js.map +1 -1
  108. package/dist/dev/define/audio/skin.css +7 -5
  109. package/dist/dev/define/audio/skin.d.ts.map +1 -1
  110. package/dist/dev/define/audio/skin.js +59 -56
  111. package/dist/dev/define/audio/skin.js.map +1 -1
  112. package/dist/dev/define/audio/skin.tailwind.d.ts.map +1 -1
  113. package/dist/dev/define/audio/skin.tailwind.js +64 -59
  114. package/dist/dev/define/audio/skin.tailwind.js.map +1 -1
  115. package/dist/dev/define/base.css +25 -0
  116. package/dist/dev/define/shared.css +3 -0
  117. package/dist/dev/define/skin-mixin.d.ts +2 -2
  118. package/dist/dev/define/skin-mixin.d.ts.map +1 -1
  119. package/dist/dev/define/skin-mixin.js +10 -32
  120. package/dist/dev/define/skin-mixin.js.map +1 -1
  121. package/dist/dev/define/video/minimal-skin.css +35 -73
  122. package/dist/dev/define/video/minimal-skin.d.ts.map +1 -1
  123. package/dist/dev/define/video/minimal-skin.js +92 -101
  124. package/dist/dev/define/video/minimal-skin.js.map +1 -1
  125. package/dist/dev/define/video/minimal-skin.tailwind.d.ts.map +1 -1
  126. package/dist/dev/define/video/minimal-skin.tailwind.js +98 -108
  127. package/dist/dev/define/video/minimal-skin.tailwind.js.map +1 -1
  128. package/dist/dev/define/video/skin.css +32 -71
  129. package/dist/dev/define/video/skin.d.ts.map +1 -1
  130. package/dist/dev/define/video/skin.js +82 -91
  131. package/dist/dev/define/video/skin.js.map +1 -1
  132. package/dist/dev/define/video/skin.tailwind.d.ts.map +1 -1
  133. package/dist/dev/define/video/skin.tailwind.js +93 -102
  134. package/dist/dev/define/video/skin.tailwind.js.map +1 -1
  135. package/dist/dev/skins/dist/default/default/tailwind/audio.tailwind.js +3 -21
  136. package/dist/dev/skins/dist/default/default/tailwind/audio.tailwind.js.map +1 -1
  137. package/dist/dev/skins/dist/default/default/tailwind/components/overlay.js +1 -1
  138. package/dist/dev/skins/dist/default/default/tailwind/components/overlay.js.map +1 -1
  139. package/dist/dev/skins/dist/default/default/tailwind/components/root.js +1 -1
  140. package/dist/dev/skins/dist/default/default/tailwind/components/root.js.map +1 -1
  141. package/dist/dev/skins/dist/default/default/tailwind/video.tailwind.js +8 -5
  142. package/dist/dev/skins/dist/default/default/tailwind/video.tailwind.js.map +1 -1
  143. package/dist/dev/skins/dist/default/minimal/tailwind/audio.tailwind.js +3 -22
  144. package/dist/dev/skins/dist/default/minimal/tailwind/audio.tailwind.js.map +1 -1
  145. package/dist/dev/skins/dist/default/minimal/tailwind/components/overlay.js +1 -1
  146. package/dist/dev/skins/dist/default/minimal/tailwind/components/overlay.js.map +1 -1
  147. package/dist/dev/skins/dist/default/minimal/tailwind/components/popup.js +1 -1
  148. package/dist/dev/skins/dist/default/minimal/tailwind/components/popup.js.map +1 -1
  149. package/dist/dev/skins/dist/default/minimal/tailwind/video.tailwind.js +6 -4
  150. package/dist/dev/skins/dist/default/minimal/tailwind/video.tailwind.js.map +1 -1
  151. package/dist/dev/skins/dist/default/{default/tailwind/components → shared/tailwind}/icon-state.js +1 -1
  152. package/dist/dev/skins/dist/default/shared/tailwind/icon-state.js.map +1 -0
  153. package/dist/{default/skins/dist/default/minimal/tailwind/components → dev/skins/dist/default/shared/tailwind}/tooltip-state.js +1 -1
  154. package/dist/dev/skins/dist/default/shared/tailwind/tooltip-state.js.map +1 -0
  155. package/dist/dev/store/container-mixin.js +22 -10
  156. package/dist/dev/store/container-mixin.js.map +1 -1
  157. package/dist/dev/ui/tooltip/tooltip-group-element.js +4 -1
  158. package/dist/dev/ui/tooltip/tooltip-group-element.js.map +1 -1
  159. package/package.json +7 -7
  160. package/dist/default/skins/dist/default/default/tailwind/components/icon-state.js.map +0 -1
  161. package/dist/default/skins/dist/default/default/tailwind/components/tooltip-state.js +0 -28
  162. package/dist/default/skins/dist/default/default/tailwind/components/tooltip-state.js.map +0 -1
  163. package/dist/default/skins/dist/default/minimal/tailwind/components/error.js +0 -15
  164. package/dist/default/skins/dist/default/minimal/tailwind/components/error.js.map +0 -1
  165. package/dist/default/skins/dist/default/minimal/tailwind/components/icon-state.js +0 -29
  166. package/dist/default/skins/dist/default/minimal/tailwind/components/icon-state.js.map +0 -1
  167. package/dist/default/skins/dist/default/minimal/tailwind/components/tooltip-state.js.map +0 -1
  168. package/dist/dev/skins/dist/default/default/tailwind/components/icon-state.js.map +0 -1
  169. package/dist/dev/skins/dist/default/default/tailwind/components/tooltip-state.js.map +0 -1
  170. package/dist/dev/skins/dist/default/minimal/tailwind/components/error.js +0 -15
  171. package/dist/dev/skins/dist/default/minimal/tailwind/components/error.js.map +0 -1
  172. package/dist/dev/skins/dist/default/minimal/tailwind/components/icon-state.js +0 -29
  173. package/dist/dev/skins/dist/default/minimal/tailwind/components/icon-state.js.map +0 -1
  174. package/dist/dev/skins/dist/default/minimal/tailwind/components/tooltip-state.js +0 -28
  175. package/dist/dev/skins/dist/default/minimal/tailwind/components/tooltip-state.js.map +0 -1
package/cdn/video.dev.js CHANGED
@@ -556,14 +556,11 @@ const controlsFeature = definePlayerFeature({
556
556
  pointerDownTime = Date.now();
557
557
  }
558
558
  function onPointerUp(event) {
559
- if (event.pointerType === "touch" && Date.now() - pointerDownTime < TAP_THRESHOLD) if (get().controlsVisible) {
560
- clearIdle();
561
- set({
562
- userActive: false,
563
- controlsVisible: computeVisible(false)
564
- });
559
+ if (event.pointerType === "touch" && Date.now() - pointerDownTime < TAP_THRESHOLD) {
560
+ const isMediaOrContainer = [media, container].includes(event.target);
561
+ if (get().controlsVisible && isMediaOrContainer) setInactive();
562
+ else setActive();
565
563
  } else setActive();
566
- else setActive();
567
564
  }
568
565
  function onPlaybackChange() {
569
566
  const { userActive } = get();
@@ -575,7 +572,7 @@ const controlsFeature = definePlayerFeature({
575
572
  listen(container, "pointerup", onPointerUp, { signal });
576
573
  listen(container, "keyup", setActive, { signal });
577
574
  listen(container, "focusin", setActive, { signal });
578
- listen(container, "pointerleave", setInactive, { signal });
575
+ listen(container, "mouseleave", setInactive, { signal });
579
576
  listen(media, "play", onPlaybackChange, { signal });
580
577
  listen(media, "pause", onPlaybackChange, { signal });
581
578
  listen(media, "ended", onPlaybackChange, { signal });
@@ -667,6 +664,10 @@ async function exitFullscreen() {
667
664
 
668
665
  //#endregion
669
666
  //#region ../core/dist/dev/dom/presentation/pip.js
667
+ function resolveMediaTarget(media) {
668
+ const target = media.target;
669
+ return target instanceof HTMLMediaElement ? target : media;
670
+ }
670
671
  /**
671
672
  * Check if Picture-in-Picture is supported on this platform.
672
673
  *
@@ -684,8 +685,9 @@ function isPictureInPictureEnabled() {
684
685
  * Check if Picture-in-Picture is currently active for a media element.
685
686
  */
686
687
  function isPictureInPictureElement(media) {
687
- if (document.pictureInPictureElement === media) return true;
688
- return media.webkitPresentationMode === "picture-in-picture";
688
+ const target = resolveMediaTarget(media);
689
+ if (document.pictureInPictureElement === target) return true;
690
+ return target.webkitPresentationMode === "picture-in-picture";
689
691
  }
690
692
  /**
691
693
  * Request Picture-in-Picture mode.
@@ -694,7 +696,7 @@ function isPictureInPictureElement(media) {
694
696
  * WebKit presentation mode.
695
697
  */
696
698
  async function requestPictureInPicture(media) {
697
- const video = media;
699
+ const video = resolveMediaTarget(media);
698
700
  if (isFunction(video.requestPictureInPicture)) {
699
701
  await video.requestPictureInPicture();
700
702
  return;
@@ -712,13 +714,14 @@ async function requestPictureInPicture(media) {
712
714
  * WebKit presentation mode.
713
715
  */
714
716
  async function exitPictureInPicture(media) {
715
- if (document.pictureInPictureElement && isFunction(document.exitPictureInPicture)) {
717
+ if (isFunction(document.exitPictureInPicture)) try {
716
718
  await document.exitPictureInPicture();
717
719
  return;
718
- }
720
+ } catch {}
719
721
  if (media) {
720
- const video = media;
721
- if (video.webkitPresentationMode === "picture-in-picture" && isFunction(video.webkitSetPresentationMode)) {
722
+ const video = resolveMediaTarget(media);
723
+ const mode = video.webkitPresentationMode;
724
+ if (isFunction(video.webkitSetPresentationMode) && (!mode || mode === "picture-in-picture")) {
722
725
  video.webkitSetPresentationMode("inline");
723
726
  return;
724
727
  }
@@ -2493,13 +2496,13 @@ function createContainerMixin(context) {
2493
2496
  connectedCallback() {
2494
2497
  super.connectedCallback();
2495
2498
  this.#observer = new MutationObserver((records) => {
2496
- if (records.some(hasMediaNode)) this.#attachMedia();
2499
+ if (records.some(hasMediaElement)) this.#attachMedia();
2497
2500
  });
2498
2501
  this.#observer.observe(this, {
2499
2502
  childList: true,
2500
2503
  subtree: true,
2501
2504
  attributes: true,
2502
- attributeFilter: ["data-media-element"]
2505
+ attributeFilter: ["name"]
2503
2506
  });
2504
2507
  this.addEventListener("slotchange", this.#onSlotChange);
2505
2508
  this.#attachMedia();
@@ -2517,18 +2520,24 @@ function createContainerMixin(context) {
2517
2520
  #getSlottedMedia() {
2518
2521
  const slot = this.querySelector("slot[name=\"media\"]");
2519
2522
  if (!slot) return null;
2520
- for (const el of slot.assignedElements({ flatten: true })) if (el instanceof HTMLMediaElement) return el;
2523
+ for (const el of slot.assignedElements({ flatten: true })) if (isMediaElement(el)) return el;
2524
+ return null;
2525
+ }
2526
+ #findMediaElement() {
2527
+ const media = Array.from(this.children).find(isMediaElement);
2528
+ if (media) return media;
2521
2529
  return null;
2522
2530
  }
2523
2531
  #attachMedia() {
2524
2532
  const store = this.#contextStore ?? this.store;
2525
2533
  if (!store) return;
2526
- const media = this.querySelector("video, audio, [data-media-element]") ?? this.#getSlottedMedia();
2534
+ const media = this.querySelector("video, audio") ?? this.#findMediaElement() ?? this.#getSlottedMedia();
2527
2535
  if (!media) {
2528
2536
  this.#detach();
2529
2537
  this.#detach = noop;
2530
2538
  return;
2531
2539
  }
2540
+ if (isCustomMediaElement(media)) globalThis.customElements?.upgrade?.(media);
2532
2541
  const target = {
2533
2542
  media,
2534
2543
  container: this
@@ -2543,13 +2552,19 @@ function createContainerMixin(context) {
2543
2552
  return PlayerContainerElement;
2544
2553
  };
2545
2554
  }
2546
- function isMediaNode(node) {
2547
- return node instanceof HTMLMediaElement || node instanceof Element && node.hasAttribute("data-media-element");
2555
+ function isMediaElement(node) {
2556
+ return node instanceof HTMLMediaElement || isCustomMediaElement(node);
2557
+ }
2558
+ function isCustomMediaElement(node) {
2559
+ return node instanceof HTMLElement && (node.localName.endsWith("-audio") || node.localName.endsWith("-video"));
2548
2560
  }
2549
- function hasMediaNode(record) {
2550
- if (record.type === "attributes" && record.target instanceof Element) return record.target.hasAttribute("data-media-element");
2551
- for (const node of record.addedNodes) if (isMediaNode(node)) return true;
2552
- for (const node of record.removedNodes) if (isMediaNode(node)) return true;
2561
+ function isMediaSlotElement(node) {
2562
+ return node instanceof HTMLSlotElement && node.name === "media";
2563
+ }
2564
+ function hasMediaElement(record) {
2565
+ if (isMediaSlotElement(record.target)) return true;
2566
+ for (const node of record.addedNodes) if (isMediaElement(node) || isMediaSlotElement(node)) return true;
2567
+ for (const node of record.removedNodes) if (isMediaElement(node) || isMediaSlotElement(node)) return true;
2553
2568
  return false;
2554
2569
  }
2555
2570
 
@@ -3248,36 +3263,17 @@ function renderIcon(name, attrs) {
3248
3263
  }
3249
3264
 
3250
3265
  //#endregion
3251
- //#region src/define/skin-mixin.ts
3252
- /**
3253
- * Light DOM stylesheet that bridges CSS custom properties set by skins
3254
- * to native WebKit text track pseudo-elements on the slotted `<video>`.
3255
- *
3256
- * `::slotted(video)::-webkit-media-text-track-container` is invalid per
3257
- * CSS spec, so this bridge lives in light DOM where it can directly
3258
- * target the video element's pseudo-elements.
3259
- */
3260
- const NATIVE_CAPTION_BRIDGE_CSS = `
3261
- .media-skin > video::-webkit-media-text-track-container {
3262
- transition: transform var(--media-caption-track-duration, 150ms) ease-out;
3263
- transition-delay: var(--media-caption-track-delay, 600ms);
3264
- transform: translateY(var(--media-caption-track-y, 0)) scale(0.98);
3265
- z-index: var(--media-caption-track-z, 1);
3266
- font-family: inherit;
3267
- }
3266
+ //#region inline-css:src/define/base.js
3267
+ var base_default = "video-player {\n display: contents;\n}\n\nvideo-player video,\nvideo-player hls-video,\nvideo-player simple-hls-video {\n display: block;\n width: 100%;\n height: 100%;\n}\n\nvideo-player video::-webkit-media-text-track-container {\n transition: transform var(--media-caption-track-duration, 150ms) ease-out;\n transition-delay: var(--media-caption-track-delay, 600ms);\n transform: translateY(var(--media-caption-track-y, 0)) scale(0.98);\n z-index: var(--media-caption-track-z, 1);\n font-family: inherit;\n}\n\n@media (prefers-reduced-motion: reduce) {\n video-player video::-webkit-media-text-track-container {\n transition-duration: 50ms;\n }\n}\n";
3268
3268
 
3269
- @media (prefers-reduced-motion: reduce) {
3270
- .media-skin > video::-webkit-media-text-track-container {
3271
- transition-duration: 50ms;
3272
- }
3273
- }
3274
- `;
3275
- const BRIDGE_ID = "media-caption-bridge";
3276
- function ensureCaptionBridge() {
3277
- if (document.getElementById(BRIDGE_ID)) return;
3269
+ //#endregion
3270
+ //#region src/define/skin-mixin.ts
3271
+ const STYLES_ID = "__media-styles";
3272
+ function ensureStyles() {
3273
+ if (document.getElementById(STYLES_ID)) return;
3278
3274
  const style = document.createElement("style");
3279
- style.id = BRIDGE_ID;
3280
- style.textContent = NATIVE_CAPTION_BRIDGE_CSS;
3275
+ style.id = STYLES_ID;
3276
+ style.textContent = base_default;
3281
3277
  document.head.appendChild(style);
3282
3278
  }
3283
3279
  /**
@@ -3285,8 +3281,8 @@ function ensureCaptionBridge() {
3285
3281
  * `getTemplateHTML` method into a shadow root. Native `<slot>` elements
3286
3282
  * handle light DOM projection automatically.
3287
3283
  *
3288
- * When `static styles` is set, the stylesheet is adopted into the shadow
3289
- * root via `adoptedStyleSheets`.
3284
+ * When `static styles` is set, the stylesheet is adopted into the
3285
+ * shadow root via `adoptedStyleSheets`.
3290
3286
  */
3291
3287
  function SkinMixin(BaseClass) {
3292
3288
  class SkinElement extends BaseClass {
@@ -3295,8 +3291,7 @@ function SkinMixin(BaseClass) {
3295
3291
  }
3296
3292
  constructor(...args) {
3297
3293
  super(...args);
3298
- this.classList.add("media-skin");
3299
- ensureCaptionBridge();
3294
+ ensureStyles();
3300
3295
  if (!this.shadowRoot) {
3301
3296
  const ctor = this.constructor;
3302
3297
  this.attachShadow(ctor.shadowRootOptions);
@@ -3316,7 +3311,7 @@ function createStyles(css) {
3316
3311
 
3317
3312
  //#endregion
3318
3313
  //#region inline-css:src/define/video/skin.js
3319
- var skin_default = "/* ==========================================================================\n Icon State Visibility for Video Skins\n\n Data-attribute-driven visibility rules for multi-state icon buttons.\n Uses :is() with both element selectors (for HTML custom element wrappers)\n and class selectors (for React rendered SVG elements).\n ========================================================================== */\n\n/* --- All icons hidden by default --- */\n\n.media-button--play .media-icon--restart,\n.media-button--play .media-icon--play,\n.media-button--play .media-icon--pause,\n.media-button--mute .media-icon--volume-off,\n.media-button--mute .media-icon--volume-low,\n.media-button--mute .media-icon--volume-high,\n.media-button--fullscreen .media-icon--fullscreen-enter,\n.media-button--fullscreen .media-icon--fullscreen-exit,\n.media-button--captions .media-icon--captions-off,\n.media-button--captions .media-icon--captions-on {\n display: none;\n opacity: 0;\n}\n\n/* --- Active icon per state --- */\n\n/* Play: ended → restart */\n.media-button--play[data-ended] .media-icon--restart,\n/* Play: paused (not ended) → play */\n.media-button--play:not([data-ended])[data-paused] .media-icon--play,\n/* Play: playing (not paused, not ended) → pause */\n.media-button--play:not([data-paused]):not([data-ended]) .media-icon--pause,\n/* Mute: muted → volume off */\n.media-button--mute[data-muted] .media-icon--volume-off,\n/* Mute: volume low (not muted) → volume low */\n.media-button--mute:not([data-muted])[data-volume-level=\"low\"] .media-icon--volume-low,\n/* Mute: volume high (not muted, not low) → volume high */\n.media-button--mute:not([data-muted]):not([data-volume-level=\"low\"]) .media-icon--volume-high,\n/* Fullscreen: not fullscreen → enter */\n.media-button--fullscreen:not([data-fullscreen]) .media-icon--fullscreen-enter,\n/* Fullscreen: fullscreen → exit */\n.media-button--fullscreen[data-fullscreen] .media-icon--fullscreen-exit,\n/* Captions: not active → captions off */\n.media-button--captions:not([data-active]) .media-icon--captions-off,\n/* Captions: active → captions on */\n.media-button--captions[data-active] .media-icon--captions-on {\n display: block;\n opacity: 1;\n}\n\n/* ==========================================================================\n Tooltip Label State Visibility for Video Skins\n\n Data-attribute-driven visibility rules for multi-state tooltip labels.\n Uses adjacent sibling selectors to match button state → tooltip content.\n ========================================================================== */\n\n/* --- All multi-state labels hidden by default --- */\n\n.media-tooltip-label {\n display: none;\n}\n\n/* --- Active label per state --- */\n\n/* Play: ended → replay */\n.media-button--play[data-ended] + .media-tooltip .media-tooltip-label--replay,\n/* Play: paused (not ended) → play */\n .media-button--play:not([data-ended])[data-paused] + .media-tooltip\n .media-tooltip-label--play,\n/* Play: playing (not paused, not ended) → pause */\n .media-button--play:not([data-paused]):not([data-ended]) + .media-tooltip\n .media-tooltip-label--pause,\n/* Fullscreen: not fullscreen → enter */\n .media-button--fullscreen:not([data-fullscreen]) + .media-tooltip\n .media-tooltip-label--enter-fullscreen,\n/* Fullscreen: fullscreen → exit */\n .media-button--fullscreen[data-fullscreen] + .media-tooltip\n .media-tooltip-label--exit-fullscreen,\n/* Captions: not active → enable */\n .media-button--captions:not([data-active]) + .media-tooltip\n .media-tooltip-label--enable-captions,\n/* Captions: active → disable */\n .media-button--captions[data-active] + .media-tooltip\n .media-tooltip-label--disable-captions,\n/* PiP: not in pip → enter */\n .media-button--pip:not([data-pip]) + .media-tooltip\n .media-tooltip-label--enter-pip,\n/* PiP: in pip → exit */\n .media-button--pip[data-pip] + .media-tooltip\n .media-tooltip-label--exit-pip {\n display: block;\n}\n\n/* ==========================================================================\n Reset\n ========================================================================== */\n\n.media-default-skin *,\n.media-default-skin *::before,\n.media-default-skin *::after {\n box-sizing: border-box;\n margin: 0;\n}\n.media-default-skin img,\n.media-default-skin video,\n.media-default-skin svg {\n display: block;\n max-width: 100%;\n}\n.media-default-skin button {\n font: inherit;\n}\n@media (prefers-reduced-motion: no-preference) {\n .media-default-skin {\n interpolate-size: allow-keywords;\n }\n}\n\n/* ==========================================================================\n Root Container\n ========================================================================== */\n\n.media-default-skin {\n position: relative;\n isolation: isolate;\n display: block;\n container: media-root / inline-size;\n border-radius: var(--media-border-radius, 2rem);\n font-family:\n Inter Variable,\n Inter,\n ui-sans-serif,\n system-ui,\n sans-serif;\n font-size: 0.8125rem;\n line-height: 1.5;\n letter-spacing: normal;\n -webkit-font-smoothing: auto;\n -moz-osx-font-smoothing: auto;\n\n &:fullscreen {\n border-radius: 0;\n }\n}\n\n/* ==========================================================================\n Surface (shared glass effect for tooltips, popovers, controls)\n ========================================================================== */\n\n.media-default-skin .media-surface {\n background-color: var(--media-surface-background-color);\n backdrop-filter: var(--media-surface-backdrop-filter);\n box-shadow:\n inset 0 0 0 1px var(--media-surface-inner-border-color),\n 0 1px 3px 0 var(--media-surface-shadow-color),\n 0 1px 2px -1px var(--media-surface-shadow-color);\n\n /* Inner border ring */\n &::after {\n content: \"\";\n position: absolute;\n inset: 0;\n z-index: 10;\n border-radius: inherit;\n box-shadow: 0 0 0 1px var(--media-surface-outer-border-color);\n pointer-events: none;\n }\n\n @media (prefers-reduced-transparency: reduce) {\n background-color: oklch(from var(--media-surface-background-color) l c h / 0.7);\n }\n\n @media (prefers-contrast: more) {\n background-color: oklch(from var(--media-surface-background-color) l c h / 0.9);\n }\n}\n\n/* ==========================================================================\n Media Element\n ========================================================================== */\n\n.media-default-skin ::slotted(video),\n.media-default-skin video {\n display: block;\n width: 100%;\n height: 100%;\n border-radius: var(--media-border-radius, 2rem);\n}\n\n/* ==========================================================================\n Poster Image\n ========================================================================== */\n\n.media-default-skin > img {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n border-radius: inherit;\n object-fit: cover;\n transition: opacity 0.25s;\n pointer-events: none;\n\n &:not([data-visible]) {\n opacity: 0;\n }\n}\n\n/* ==========================================================================\n Overlay / Scrim\n ========================================================================== */\n\n.media-default-skin .media-overlay {\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background-image: linear-gradient(to top, oklch(0 0 0 / 0.5), oklch(0 0 0 / 0.3), oklch(0 0 0 / 0));\n backdrop-filter: blur(0) saturate(1.2) brightness(0.9);\n opacity: 0;\n transition-property: opacity, backdrop-filter;\n transition-duration: 300ms;\n transition-delay: 500ms;\n transition-timing-function: ease-out;\n pointer-events: none;\n\n @media (prefers-reduced-motion: reduce) {\n transition-duration: 100ms;\n }\n}\n\n.media-default-skin .media-controls[data-visible] ~ .media-overlay,\n.media-default-skin .media-error[data-open] ~ .media-overlay {\n opacity: 1;\n transition-duration: 150ms;\n transition-delay: 0ms;\n}\n\n.media-default-skin .media-error[data-open] ~ .media-overlay {\n backdrop-filter: blur(8px) saturate(1.2) brightness(0.9);\n}\n\n/* ==========================================================================\n Buffering Indicator\n ========================================================================== */\n\n.media-default-skin .media-buffering-indicator {\n position: absolute;\n inset: 0;\n display: none;\n align-items: center;\n justify-content: center;\n color: oklch(1 0 0);\n pointer-events: none;\n\n &[data-visible] {\n display: flex;\n }\n\n .media-surface {\n padding: 0.25rem;\n border-radius: 100%;\n }\n}\n\n/* ==========================================================================\n Error Dialog\n ========================================================================== */\n\n.media-default-skin .media-error {\n position: absolute;\n inset: 0;\n z-index: 20;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.media-default-skin .media-error__dialog {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n max-width: 18rem;\n padding: 0.75rem;\n border-radius: 1.75rem;\n color: oklch(1 0 0);\n font-size: 0.875rem;\n transition-property: opacity, transform;\n transition-duration: 500ms;\n transition-delay: 100ms;\n transition-timing-function: linear(\n 0,\n 0.034 1.5%,\n 0.763 9.7%,\n 1.066 13.9%,\n 1.198 19.9%,\n 1.184 21.8%,\n 0.963 37.5%,\n 0.997 50.9%,\n 1\n );\n\n /* Simple, fast transition for reduced motion users */\n @media (prefers-reduced-motion: reduce) {\n transition-duration: 100ms;\n transition-delay: 0ms;\n transition-timing-function: ease-out;\n }\n}\n\n.media-default-skin .media-error[data-starting-style] .media-error__dialog,\n.media-default-skin .media-error[data-ending-style] .media-error__dialog {\n opacity: 0;\n transform: scale(0.5);\n}\n\n.media-default-skin .media-error__content {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n padding: 0.5rem 0.5rem 0.375rem;\n}\n\n.media-default-skin .media-error__title {\n font-weight: 600;\n line-height: 1.25;\n}\n\n.media-default-skin .media-error__description {\n opacity: 0.7;\n}\n\n.media-default-skin .media-error__actions {\n display: flex;\n gap: 0.5rem;\n\n & > * {\n flex: 1;\n }\n}\n\n/* ==========================================================================\n Controls\n ========================================================================== */\n\n.media-default-skin .media-controls {\n container: media-controls / inline-size;\n display: flex;\n align-items: center;\n gap: 0.075rem;\n padding: 0.175rem;\n border-radius: calc(infinity * 1px);\n --media-controls-current-shadow-color: oklch(from currentColor 0 0 0 / clamp(0, calc((l - 0.5) * 0.5), 0.25));\n --media-controls-current-shadow-color-subtle: oklch(\n from var(--media-controls-current-shadow-color) l c h /\n calc(alpha * 0.4)\n );\n text-shadow: 0 0 1px var(--media-controls-current-shadow-color);\n\n @container media-root (width > 40rem) {\n gap: 0.125rem;\n padding: 0.25rem;\n }\n}\n\n/* ==========================================================================\n Time Display\n ========================================================================== */\n\n.media-default-skin .media-time {\n container: media-time / inline-size;\n display: flex;\n align-items: center;\n flex: 1;\n gap: 0.75rem;\n padding-inline: 0.5rem;\n\n & .media-time__value:first-child {\n display: none;\n\n @container media-time (width > 18rem) {\n display: block;\n }\n }\n}\n\n.media-default-skin .media-time__value {\n font-variant-numeric: tabular-nums;\n}\n\n/* ==========================================================================\n Buttons\n ========================================================================== */\n\n/* Base button */\n.media-default-skin .media-button {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n padding: 0.5rem 1rem;\n background: oklch(1 0 0);\n border: none;\n border-radius: calc(infinity * 1px);\n outline: 2px solid transparent;\n outline-offset: -2px;\n color: oklch(0 0 0);\n font-weight: 500;\n text-align: center;\n transition-property: background-color, color, outline-offset, transform;\n transition-duration: 150ms;\n transition-timing-function: ease-out;\n cursor: pointer;\n user-select: none;\n\n &:focus-visible {\n outline-color: oklch(62.3% 0.214 259.815);\n outline-offset: 2px;\n }\n\n &[disabled] {\n opacity: 0.5;\n filter: grayscale(1);\n cursor: not-allowed;\n }\n\n &[data-availability=\"unavailable\"] {\n display: none;\n }\n}\n\n/* Icon button variant */\n.media-default-skin .media-button--icon {\n display: grid;\n width: 2.125rem;\n padding: 0;\n aspect-ratio: 1;\n background: transparent;\n color: inherit;\n text-shadow: inherit;\n\n &:hover,\n &:focus-visible,\n &[aria-expanded=\"true\"] {\n background-color: oklch(from currentColor l c h / 0.1);\n text-decoration: none;\n }\n\n &:active {\n transform: scale(0.9);\n }\n\n & .media-icon {\n filter: drop-shadow(0 1px 0 var(--media-controls-current-shadow-color, oklch(0 0 0 / 0.25)));\n }\n}\n\n/* Seek button */\n.media-default-skin .media-button--seek {\n & .media-icon__label {\n position: absolute;\n right: -1px;\n bottom: -3px;\n font-size: 0.75em;\n font-weight: 480;\n font-variant-numeric: tabular-nums;\n }\n\n &:has(.media-icon--flipped) .media-icon__label {\n right: unset;\n left: -1px;\n }\n\n @container media-controls (width < 28rem) {\n display: none;\n }\n}\n\n/* Playback rate button */\n.media-default-skin .media-button--playback-rate {\n padding: 0;\n\n &::after {\n content: attr(data-rate) \"\\00D7\";\n width: 4ch;\n font-variant-numeric: tabular-nums;\n }\n}\n\n/* ==========================================================================\n Icons\n ========================================================================== */\n\n.media-default-skin .media-icon__container {\n position: relative;\n}\n.media-default-skin .media-icon {\n display: block;\n flex-shrink: 0;\n grid-area: 1 / 1;\n width: 18px;\n height: 18px;\n transition-behavior: allow-discrete;\n transition-property: display, opacity;\n transition-duration: 150ms;\n transition-timing-function: ease-out;\n}\n.media-default-skin .media-icon--flipped {\n scale: -1 1;\n}\n\n/* ==========================================================================\n Slider\n ========================================================================== */\n\n.media-default-skin .media-slider {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n border-radius: calc(infinity * 1px);\n outline: none;\n\n &[data-orientation=\"horizontal\"] {\n min-width: 5rem;\n width: 100%;\n height: 1.25rem;\n }\n\n &[data-orientation=\"vertical\"] {\n width: 1.25rem;\n height: 5rem;\n }\n}\n\n/* Track */\n.media-default-skin .media-slider__track {\n position: relative;\n isolation: isolate;\n overflow: hidden;\n border-radius: inherit;\n user-select: none;\n\n &[data-orientation=\"horizontal\"] {\n width: 100%;\n height: 0.25rem;\n }\n\n &[data-orientation=\"vertical\"] {\n width: 0.25rem;\n height: 100%;\n }\n}\n\n/* Thumb */\n.media-default-skin .media-slider__thumb {\n z-index: 10;\n position: absolute;\n transform: translate(-50%, -50%);\n width: 0.625rem;\n height: 0.625rem;\n background-color: currentColor;\n border-radius: calc(infinity * 1px);\n box-shadow:\n 0 0 0 1px var(--media-controls-current-shadow-color-subtle, oklch(0 0 0 / 0.1)),\n 0 1px 3px 0 oklch(0 0 0 / 0.15),\n 0 1px 2px -1px oklch(0 0 0 / 0.15);\n opacity: 0;\n transition-property: opacity, height, width, outline-offset;\n transition-duration: 150ms;\n transition-timing-function: ease-out;\n user-select: none;\n outline: 4px solid transparent;\n outline-offset: -4px;\n\n &[data-orientation=\"horizontal\"] {\n top: 50%;\n left: var(--media-slider-fill);\n }\n\n &[data-orientation=\"vertical\"] {\n left: 50%;\n top: calc(100% - var(--media-slider-fill));\n }\n\n &:hover,\n &:focus {\n outline-color: oklch(from currentColor l c h / 0.25);\n outline-offset: 0;\n }\n}\n\n.media-default-skin .media-slider:active .media-slider__thumb,\n.media-default-skin .media-slider__thumb--persistent {\n width: 0.75rem;\n height: 0.75rem;\n}\n\n.media-default-skin .media-slider:hover .media-slider__thumb,\n.media-default-skin .media-slider__thumb:focus-visible,\n.media-default-skin .media-slider__thumb--persistent {\n opacity: 1;\n}\n\n/* Shared track fills */\n.media-default-skin .media-slider__buffer,\n.media-default-skin .media-slider__fill {\n position: absolute;\n border-radius: inherit;\n pointer-events: none;\n}\n\n.media-default-skin .media-slider__buffer[data-orientation=\"horizontal\"],\n.media-default-skin .media-slider__fill[data-orientation=\"horizontal\"] {\n inset-block: 0;\n left: 0;\n}\n\n.media-default-skin .media-slider__buffer[data-orientation=\"vertical\"],\n.media-default-skin .media-slider__fill[data-orientation=\"vertical\"] {\n inset-inline: 0;\n bottom: 0;\n}\n\n/* Buffer */\n.media-default-skin .media-slider__buffer {\n background-color: oklch(from currentColor l c h / 0.2);\n transition-duration: 0.25s;\n transition-timing-function: ease-out;\n\n &[data-orientation=\"horizontal\"] {\n width: var(--media-slider-buffer);\n transition-property: width;\n }\n\n &[data-orientation=\"vertical\"] {\n height: var(--media-slider-buffer);\n transition-property: height;\n }\n}\n\n/* Fill */\n.media-default-skin .media-slider__fill {\n background-color: currentColor;\n\n &[data-orientation=\"horizontal\"] {\n width: var(--media-slider-fill);\n }\n\n &[data-orientation=\"vertical\"] {\n height: var(--media-slider-fill);\n }\n}\n\n/* Time display within slider */\n.media-default-skin .media-slider__time-display {\n font-variant-numeric: tabular-nums;\n}\n\n/* ==========================================================================\n Popups & Tooltips\n ========================================================================== */\n\n.media-default-skin .media-popover,\n.media-default-skin .media-tooltip {\n margin: 0;\n border: 0;\n color: inherit;\n overflow: visible;\n transition-property: transform, scale, opacity, filter;\n transition-duration: 200ms;\n\n &[data-starting-style],\n &[data-ending-style] {\n opacity: 0;\n transform: scale(0);\n filter: blur(8px);\n }\n\n &[data-instant] {\n transition-duration: 0ms;\n }\n\n &[data-side=\"top\"] {\n transform-origin: bottom;\n }\n &[data-side=\"bottom\"] {\n transform-origin: top;\n }\n &[data-side=\"left\"] {\n transform-origin: right;\n }\n &[data-side=\"right\"] {\n transform-origin: left;\n }\n}\n\n.media-default-skin .media-popover {\n --media-popover-side-offset: 0.5rem;\n}\n.media-default-skin .media-popover--volume {\n padding: 0.625rem 0.25rem;\n border-radius: calc(infinity * 1px);\n}\n\n.media-default-skin .media-tooltip {\n padding: 0.25rem 0.625rem;\n border-radius: calc(infinity * 1px);\n font-size: 0.75rem;\n white-space: nowrap;\n --media-tooltip-side-offset: 0.5rem;\n}\n\n/* ==========================================================================\n Captions\n ========================================================================== */\n\n.media-default-skin .media-captions {\n position: absolute;\n inset: auto 1rem 1.5rem 1rem;\n z-index: 20;\n font-size: 1rem;\n text-wrap: balance;\n pointer-events: none;\n\n @container media-root (width > 20rem) {\n font-size: 1.5rem;\n }\n\n @container media-root (width > 48rem) {\n font-size: 1.875rem;\n }\n\n @container media-root (width > 80rem) {\n font-size: 2.25rem;\n }\n}\n\n.media-default-skin .media-captions__container {\n display: flex;\n flex-direction: column;\n align-items: center;\n max-width: 42ch;\n margin: 0 auto;\n text-align: center;\n}\n\n.media-default-skin .media-captions__text {\n display: block;\n padding: 0.125rem 0.5rem;\n color: oklch(1 0 0);\n text-shadow:\n 0 0 1px oklch(0 0 0 / 0.7),\n 0 0 8px oklch(0 0 0 / 0.7);\n text-align: center;\n white-space: pre-wrap;\n line-height: 1.2;\n\n @media (prefers-contrast: more) {\n background: oklch(0 0 0 / 0.7);\n text-shadow: none;\n box-decoration-break: clone;\n }\n\n & > * {\n display: inline;\n }\n}\n\n/* Caption shifting styles (custom and native) */\n.media-default-skin {\n --media-caption-track-delay: 600ms;\n --media-caption-track-y: -0.5rem;\n\n &:has(.media-controls[data-visible]) {\n --media-caption-track-delay: 25ms;\n --media-caption-track-y: -3.5rem;\n }\n}\n\n.media-default-skin .media-captions,\n.media-default-skin video::-webkit-media-text-track-container {\n /* NOTE: The delay must account for the controls delay/duration */\n transition: transform 150ms ease-out;\n transition-delay: var(--media-caption-track-delay);\n}\n\n.media-default-skin video::-webkit-media-text-track-container {\n transform: translateY(var(--media-caption-track-y)) scale(0.98);\n z-index: 1;\n font-family: inherit;\n}\n\n/* When controls are visible, shift captions up to avoid overlap */\n.media-default-skin .media-controls[data-visible] ~ .media-captions {\n transform: translateY(calc(var(--media-caption-track-y) - 0.5rem));\n}\n\n@media (prefers-reduced-motion: reduce) {\n .media-default-skin .media-captions,\n .media-default-skin video::-webkit-media-text-track-container {\n transition-duration: 50ms;\n }\n}\n\n\n/* ==========================================================================\n Root\n ========================================================================== */\n\n.media-default-skin--video {\n background: oklch(0 0 0);\n --media-border-color: oklch(0 0 0 / 0.1);\n --media-surface-background-color: oklch(1 0 0 / 0.1);\n --media-surface-inner-border-color: oklch(1 0 0 / 0.05);\n --media-surface-outer-border-color: oklch(0 0 0 / 0.1);\n --media-surface-shadow-color: oklch(0 0 0 / 0.15);\n --media-surface-backdrop-filter: blur(64px) brightness(0.9) saturate(1.5);\n\n @media (prefers-color-scheme: dark) {\n --media-border-color: oklch(1 0 0 / 0.1);\n }\n\n /* Inner border ring */\n &::after {\n content: \"\";\n position: absolute;\n inset: 0;\n z-index: 10;\n border-radius: inherit;\n box-shadow: inset 0 0 0 1px var(--media-border-color);\n pointer-events: none;\n }\n}\n\n/* ==========================================================================\n Controls (hide/show behavior)\n ========================================================================== */\n\n.media-default-skin--video .media-controls {\n position: absolute;\n bottom: 0.75rem;\n inset-inline: 0.75rem;\n z-index: 10;\n will-change: scale, transform, filter, opacity;\n transition-property: scale, transform, filter, opacity;\n transition-duration: 100ms;\n transition-delay: 0ms;\n transition-timing-function: ease-out;\n transform-origin: bottom;\n color: oklch(1 0 0);\n\n &:not([data-visible]) {\n opacity: 0;\n scale: 0.9;\n filter: blur(8px);\n transition-duration: 300ms;\n transition-delay: 500ms;\n pointer-events: none;\n\n @media (prefers-reduced-motion: reduce) {\n scale: 1;\n filter: blur(0);\n transition-duration: 100ms;\n }\n }\n}\n\n/* ==========================================================================\n Sliders\n ========================================================================== */\n\n.media-default-skin--video .media-slider__track {\n background-color: oklch(1 0 0 / 0.2);\n box-shadow: 0 0 0 1px oklch(0 0 0 / 0.05);\n}\n\n";
3314
+ var skin_default = "/* ==========================================================================\n Icon State Visibility for Video Skins\n\n Data-attribute-driven visibility rules for multi-state icon buttons.\n Uses :is() with both element selectors (for HTML custom element wrappers)\n and class selectors (for React rendered SVG elements).\n ========================================================================== */\n\n/* --- All icons hidden by default --- */\n\n.media-button--play .media-icon--restart,\n.media-button--play .media-icon--play,\n.media-button--play .media-icon--pause,\n.media-button--mute .media-icon--volume-off,\n.media-button--mute .media-icon--volume-low,\n.media-button--mute .media-icon--volume-high,\n.media-button--fullscreen .media-icon--fullscreen-enter,\n.media-button--fullscreen .media-icon--fullscreen-exit,\n.media-button--captions .media-icon--captions-off,\n.media-button--captions .media-icon--captions-on {\n display: none;\n opacity: 0;\n}\n\n/* --- Active icon per state --- */\n\n/* Play: ended → restart */\n.media-button--play[data-ended] .media-icon--restart,\n/* Play: paused (not ended) → play */\n.media-button--play:not([data-ended])[data-paused] .media-icon--play,\n/* Play: playing (not paused, not ended) → pause */\n.media-button--play:not([data-paused]):not([data-ended]) .media-icon--pause,\n/* Mute: muted → volume off */\n.media-button--mute[data-muted] .media-icon--volume-off,\n/* Mute: volume low (not muted) → volume low */\n.media-button--mute:not([data-muted])[data-volume-level=\"low\"] .media-icon--volume-low,\n/* Mute: volume high (not muted, not low) → volume high */\n.media-button--mute:not([data-muted]):not([data-volume-level=\"low\"]) .media-icon--volume-high,\n/* Fullscreen: not fullscreen → enter */\n.media-button--fullscreen:not([data-fullscreen]) .media-icon--fullscreen-enter,\n/* Fullscreen: fullscreen → exit */\n.media-button--fullscreen[data-fullscreen] .media-icon--fullscreen-exit,\n/* Captions: not active → captions off */\n.media-button--captions:not([data-active]) .media-icon--captions-off,\n/* Captions: active → captions on */\n.media-button--captions[data-active] .media-icon--captions-on {\n display: block;\n opacity: 1;\n}\n\n/* ==========================================================================\n Tooltip Label State Visibility for Video Skins\n\n Data-attribute-driven visibility rules for multi-state tooltip labels.\n Uses adjacent sibling selectors to match button state → tooltip content.\n ========================================================================== */\n\n/* --- All multi-state labels hidden by default --- */\n\n.media-tooltip-label {\n display: none;\n}\n\n/* --- Active label per state --- */\n\n/* Play: ended → replay */\n.media-button--play[data-ended] + .media-tooltip .media-tooltip-label--replay,\n/* Play: paused (not ended) → play */\n .media-button--play:not([data-ended])[data-paused] + .media-tooltip\n .media-tooltip-label--play,\n/* Play: playing (not paused, not ended) → pause */\n .media-button--play:not([data-paused]):not([data-ended]) + .media-tooltip\n .media-tooltip-label--pause,\n/* Fullscreen: not fullscreen → enter */\n .media-button--fullscreen:not([data-fullscreen]) + .media-tooltip\n .media-tooltip-label--enter-fullscreen,\n/* Fullscreen: fullscreen → exit */\n .media-button--fullscreen[data-fullscreen] + .media-tooltip\n .media-tooltip-label--exit-fullscreen,\n/* Captions: not active → enable */\n .media-button--captions:not([data-active]) + .media-tooltip\n .media-tooltip-label--enable-captions,\n/* Captions: active → disable */\n .media-button--captions[data-active] + .media-tooltip\n .media-tooltip-label--disable-captions,\n/* PiP: not in pip → enter */\n .media-button--pip:not([data-pip]) + .media-tooltip\n .media-tooltip-label--enter-pip,\n/* PiP: in pip → exit */\n .media-button--pip[data-pip] + .media-tooltip\n .media-tooltip-label--exit-pip {\n display: block;\n}\n\n/* ==========================================================================\n Reset\n ========================================================================== */\n\n.media-default-skin *,\n.media-default-skin *::before,\n.media-default-skin *::after {\n box-sizing: border-box;\n margin: 0;\n}\n.media-default-skin img,\n.media-default-skin video,\n.media-default-skin svg {\n display: block;\n max-width: 100%;\n}\n.media-default-skin button {\n font: inherit;\n}\n@media (prefers-reduced-motion: no-preference) {\n .media-default-skin {\n interpolate-size: allow-keywords;\n }\n}\n\n/* ==========================================================================\n Root Container\n ========================================================================== */\n\n.media-default-skin {\n position: relative;\n isolation: isolate;\n display: block;\n height: 100%;\n width: 100%;\n container: media-root / inline-size;\n border-radius: var(--media-border-radius, 2rem);\n font-family:\n Inter Variable,\n Inter,\n ui-sans-serif,\n system-ui,\n sans-serif;\n font-size: 0.8125rem;\n line-height: 1.5;\n letter-spacing: normal;\n -webkit-font-smoothing: auto;\n -moz-osx-font-smoothing: auto;\n}\n\n/* ==========================================================================\n Surface (shared glass effect for tooltips, popovers, controls)\n ========================================================================== */\n\n.media-default-skin .media-surface {\n background-color: var(--media-surface-background-color);\n backdrop-filter: var(--media-surface-backdrop-filter);\n box-shadow:\n inset 0 0 0 1px var(--media-surface-inner-border-color),\n 0 1px 3px 0 var(--media-surface-shadow-color),\n 0 1px 2px -1px var(--media-surface-shadow-color);\n\n /* Inner border ring */\n &::after {\n content: \"\";\n position: absolute;\n inset: 0;\n z-index: 10;\n border-radius: inherit;\n box-shadow: 0 0 0 1px var(--media-surface-outer-border-color);\n pointer-events: none;\n }\n\n @media (prefers-reduced-transparency: reduce) {\n background-color: oklch(from var(--media-surface-background-color) l c h / 0.7);\n }\n\n @media (prefers-contrast: more) {\n background-color: oklch(from var(--media-surface-background-color) l c h / 0.9);\n }\n}\n\n/* ==========================================================================\n Media Element\n ========================================================================== */\n\n.media-default-skin ::slotted(video),\n.media-default-skin video {\n display: block;\n width: 100%;\n height: 100%;\n}\n.media-default-skin ::slotted(video) {\n border-radius: var(--media-border-radius, 2rem);\n}\n.media-default-skin video {\n border-radius: inherit;\n}\n\n/* ==========================================================================\n Poster Image\n ========================================================================== */\n\n.media-default-skin > img {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n border-radius: inherit;\n object-fit: cover;\n transition: opacity 0.25s;\n pointer-events: none;\n\n &:not([data-visible]) {\n opacity: 0;\n }\n}\n\n/* ==========================================================================\n Fullscreen\n ========================================================================== */\n\n.media-default-skin:fullscreen video,\n.media-default-skin:fullscreen ::slotted(video),\n.media-default-skin > img {\n object-fit: contain;\n}\n.media-default-skin:fullscreen ::slotted(video) {\n border-radius: 0;\n}\n\n/* ==========================================================================\n Overlay / Scrim\n ========================================================================== */\n\n.media-default-skin .media-overlay {\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background-image: linear-gradient(to top, oklch(0 0 0 / 0.5), oklch(0 0 0 / 0.3), oklch(0 0 0 / 0));\n backdrop-filter: blur(0) saturate(1.5);\n opacity: 0;\n transition-property: opacity, backdrop-filter;\n transition-duration: 300ms;\n transition-delay: 500ms;\n transition-timing-function: ease-out;\n pointer-events: none;\n\n @media (prefers-reduced-motion: reduce) {\n transition-duration: 100ms;\n }\n}\n\n.media-default-skin .media-controls[data-visible] ~ .media-overlay,\n.media-default-skin .media-error[data-open] ~ .media-overlay {\n opacity: 1;\n transition-duration: 150ms;\n transition-delay: 0ms;\n}\n\n.media-default-skin .media-error[data-open] ~ .media-overlay {\n backdrop-filter: blur(16px) saturate(1.5);\n}\n\n/* ==========================================================================\n Buffering Indicator\n ========================================================================== */\n\n.media-default-skin .media-buffering-indicator {\n position: absolute;\n inset: 0;\n display: none;\n align-items: center;\n justify-content: center;\n color: oklch(1 0 0);\n pointer-events: none;\n\n &[data-visible] {\n display: flex;\n }\n\n .media-surface {\n padding: 0.25rem;\n border-radius: 100%;\n }\n}\n\n/* ==========================================================================\n Error Dialog\n ========================================================================== */\n\n.media-default-skin .media-error {\n position: absolute;\n inset: 0;\n z-index: 20;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.media-default-skin .media-error__dialog {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n max-width: 18rem;\n padding: 0.75rem;\n border-radius: 1.75rem;\n color: oklch(1 0 0);\n font-size: 0.875rem;\n transition-property: opacity, transform;\n transition-duration: 500ms;\n transition-delay: 100ms;\n transition-timing-function: linear(\n 0,\n 0.034 1.5%,\n 0.763 9.7%,\n 1.066 13.9%,\n 1.198 19.9%,\n 1.184 21.8%,\n 0.963 37.5%,\n 0.997 50.9%,\n 1\n );\n\n /* Simple, fast transition for reduced motion users */\n @media (prefers-reduced-motion: reduce) {\n transition-duration: 100ms;\n transition-delay: 0ms;\n transition-timing-function: ease-out;\n }\n}\n\n.media-default-skin .media-error[data-starting-style] .media-error__dialog,\n.media-default-skin .media-error[data-ending-style] .media-error__dialog {\n opacity: 0;\n transform: scale(0.5);\n}\n\n.media-default-skin .media-error__content {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n padding: 0.5rem 0.5rem 0.375rem;\n}\n\n.media-default-skin .media-error__title {\n font-weight: 600;\n line-height: 1.25;\n}\n\n.media-default-skin .media-error__description {\n opacity: 0.7;\n}\n\n.media-default-skin .media-error__actions {\n display: flex;\n gap: 0.5rem;\n\n & > * {\n flex: 1;\n }\n}\n\n/* ==========================================================================\n Controls\n ========================================================================== */\n\n.media-default-skin .media-controls {\n container: media-controls / inline-size;\n display: flex;\n align-items: center;\n gap: 0.075rem;\n padding: 0.175rem;\n border-radius: calc(infinity * 1px);\n --media-controls-current-shadow-color: oklch(from currentColor 0 0 0 / clamp(0, calc((l - 0.5) * 0.5), 0.25));\n --media-controls-current-shadow-color-subtle: oklch(\n from var(--media-controls-current-shadow-color) l c h /\n calc(alpha * 0.4)\n );\n text-shadow: 0 0 1px var(--media-controls-current-shadow-color);\n\n @container media-root (width > 40rem) {\n gap: 0.125rem;\n padding: 0.25rem;\n }\n}\n\n/* ==========================================================================\n Time Display\n ========================================================================== */\n\n.media-default-skin .media-time {\n container: media-time / inline-size;\n display: flex;\n align-items: center;\n flex: 1;\n gap: 0.75rem;\n padding-inline: 0.5rem;\n\n & .media-time__value:first-child {\n display: none;\n\n @container media-time (width > 18rem) {\n display: block;\n }\n }\n}\n\n.media-default-skin .media-time__value {\n font-variant-numeric: tabular-nums;\n}\n\n/* ==========================================================================\n Buttons\n ========================================================================== */\n\n/* Base button */\n.media-default-skin .media-button {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n padding: 0.5rem 1rem;\n background: oklch(1 0 0);\n border: none;\n border-radius: calc(infinity * 1px);\n outline: 2px solid transparent;\n outline-offset: -2px;\n color: oklch(0 0 0);\n font-weight: 500;\n text-align: center;\n transition-property: background-color, color, outline-offset, transform;\n transition-duration: 150ms;\n transition-timing-function: ease-out;\n cursor: pointer;\n user-select: none;\n\n &:focus-visible {\n outline-color: oklch(62.3% 0.214 259.815);\n outline-offset: 2px;\n }\n\n &[disabled] {\n opacity: 0.5;\n filter: grayscale(1);\n cursor: not-allowed;\n }\n\n &[data-availability=\"unavailable\"] {\n display: none;\n }\n}\n\n/* Icon button variant */\n.media-default-skin .media-button--icon {\n display: grid;\n width: 2.125rem;\n padding: 0;\n aspect-ratio: 1;\n background: transparent;\n color: inherit;\n text-shadow: inherit;\n\n &:hover,\n &:focus-visible,\n &[aria-expanded=\"true\"] {\n background-color: oklch(from currentColor l c h / 0.1);\n text-decoration: none;\n }\n\n &:active {\n transform: scale(0.9);\n }\n\n & .media-icon {\n filter: drop-shadow(0 1px 0 var(--media-controls-current-shadow-color, oklch(0 0 0 / 0.25)));\n }\n}\n\n/* Seek button */\n.media-default-skin .media-button--seek {\n & .media-icon__label {\n position: absolute;\n right: -1px;\n bottom: -3px;\n font-size: 0.75em;\n font-weight: 480;\n font-variant-numeric: tabular-nums;\n }\n\n &:has(.media-icon--flipped) .media-icon__label {\n right: unset;\n left: -1px;\n }\n\n @container media-controls (width < 28rem) {\n display: none;\n }\n}\n\n/* Playback rate button */\n.media-default-skin .media-button--playback-rate {\n padding: 0;\n\n &::after {\n content: attr(data-rate) \"\\00D7\";\n width: 4ch;\n font-variant-numeric: tabular-nums;\n }\n}\n\n/* ==========================================================================\n Icons\n ========================================================================== */\n\n.media-default-skin .media-icon__container {\n position: relative;\n}\n.media-default-skin .media-icon {\n display: block;\n flex-shrink: 0;\n grid-area: 1 / 1;\n width: 18px;\n height: 18px;\n transition-behavior: allow-discrete;\n transition-property: display, opacity;\n transition-duration: 150ms;\n transition-timing-function: ease-out;\n}\n.media-default-skin .media-icon--flipped {\n scale: -1 1;\n}\n\n/* ==========================================================================\n Slider\n ========================================================================== */\n\n.media-default-skin .media-slider {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n border-radius: calc(infinity * 1px);\n outline: none;\n\n &[data-orientation=\"horizontal\"] {\n min-width: 5rem;\n width: 100%;\n height: 1.25rem;\n }\n\n &[data-orientation=\"vertical\"] {\n width: 1.25rem;\n height: 5rem;\n }\n}\n\n/* Track */\n.media-default-skin .media-slider__track {\n position: relative;\n isolation: isolate;\n overflow: hidden;\n border-radius: inherit;\n user-select: none;\n\n &[data-orientation=\"horizontal\"] {\n width: 100%;\n height: 0.25rem;\n }\n\n &[data-orientation=\"vertical\"] {\n width: 0.25rem;\n height: 100%;\n }\n}\n\n/* Thumb */\n.media-default-skin .media-slider__thumb {\n z-index: 10;\n position: absolute;\n transform: translate(-50%, -50%);\n width: 0.625rem;\n height: 0.625rem;\n background-color: currentColor;\n border-radius: calc(infinity * 1px);\n box-shadow:\n 0 0 0 1px var(--media-controls-current-shadow-color-subtle, oklch(0 0 0 / 0.1)),\n 0 1px 3px 0 oklch(0 0 0 / 0.15),\n 0 1px 2px -1px oklch(0 0 0 / 0.15);\n opacity: 0;\n transition-property: opacity, height, width, outline-offset;\n transition-duration: 150ms;\n transition-timing-function: ease-out;\n user-select: none;\n outline: 4px solid transparent;\n outline-offset: -4px;\n\n &[data-orientation=\"horizontal\"] {\n top: 50%;\n left: var(--media-slider-fill);\n }\n\n &[data-orientation=\"vertical\"] {\n left: 50%;\n top: calc(100% - var(--media-slider-fill));\n }\n\n &:hover,\n &:focus {\n outline-color: oklch(from currentColor l c h / 0.25);\n outline-offset: 0;\n }\n}\n\n.media-default-skin .media-slider:active .media-slider__thumb,\n.media-default-skin .media-slider__thumb--persistent {\n width: 0.75rem;\n height: 0.75rem;\n}\n\n.media-default-skin .media-slider:hover .media-slider__thumb,\n.media-default-skin .media-slider__thumb:focus-visible,\n.media-default-skin .media-slider__thumb--persistent {\n opacity: 1;\n}\n\n/* Shared track fills */\n.media-default-skin .media-slider__buffer,\n.media-default-skin .media-slider__fill {\n position: absolute;\n border-radius: inherit;\n pointer-events: none;\n}\n\n.media-default-skin .media-slider__buffer[data-orientation=\"horizontal\"],\n.media-default-skin .media-slider__fill[data-orientation=\"horizontal\"] {\n inset-block: 0;\n left: 0;\n}\n\n.media-default-skin .media-slider__buffer[data-orientation=\"vertical\"],\n.media-default-skin .media-slider__fill[data-orientation=\"vertical\"] {\n inset-inline: 0;\n bottom: 0;\n}\n\n/* Buffer */\n.media-default-skin .media-slider__buffer {\n background-color: oklch(from currentColor l c h / 0.2);\n transition-duration: 0.25s;\n transition-timing-function: ease-out;\n\n &[data-orientation=\"horizontal\"] {\n width: var(--media-slider-buffer);\n transition-property: width;\n }\n\n &[data-orientation=\"vertical\"] {\n height: var(--media-slider-buffer);\n transition-property: height;\n }\n}\n\n/* Fill */\n.media-default-skin .media-slider__fill {\n background-color: currentColor;\n\n &[data-orientation=\"horizontal\"] {\n width: var(--media-slider-fill);\n }\n\n &[data-orientation=\"vertical\"] {\n height: var(--media-slider-fill);\n }\n}\n\n/* Time display within slider */\n.media-default-skin .media-slider__time-display {\n font-variant-numeric: tabular-nums;\n}\n\n/* ==========================================================================\n Popups & Tooltips\n ========================================================================== */\n\n.media-default-skin .media-popover,\n.media-default-skin .media-tooltip {\n margin: 0;\n border: 0;\n color: inherit;\n overflow: visible;\n transition-property: transform, scale, opacity, filter;\n transition-duration: 200ms;\n\n &[data-starting-style],\n &[data-ending-style] {\n opacity: 0;\n transform: scale(0);\n filter: blur(8px);\n }\n\n &[data-instant] {\n transition-duration: 0ms;\n }\n\n &[data-side=\"top\"] {\n transform-origin: bottom;\n }\n &[data-side=\"bottom\"] {\n transform-origin: top;\n }\n &[data-side=\"left\"] {\n transform-origin: right;\n }\n &[data-side=\"right\"] {\n transform-origin: left;\n }\n}\n\n.media-default-skin .media-popover {\n --media-popover-side-offset: 0.5rem;\n}\n.media-default-skin .media-popover--volume {\n padding: 0.625rem 0.25rem;\n border-radius: calc(infinity * 1px);\n}\n\n.media-default-skin .media-tooltip {\n padding: 0.25rem 0.625rem;\n border-radius: calc(infinity * 1px);\n font-size: 0.75rem;\n white-space: nowrap;\n --media-tooltip-side-offset: 0.5rem;\n}\n\n/* ==========================================================================\n Native Caption Track\n ========================================================================== */\n\n.media-default-skin {\n --media-caption-track-delay: 600ms;\n --media-caption-track-y: -0.5rem;\n\n &:has(.media-controls[data-visible]) {\n --media-caption-track-delay: 25ms;\n --media-caption-track-y: -3.5rem;\n }\n}\n\n.media-default-skin video::-webkit-media-text-track-container {\n /* NOTE: The delay must account for the controls delay/duration */\n transition: transform 150ms ease-out;\n transition-delay: var(--media-caption-track-delay);\n transform: translateY(var(--media-caption-track-y)) scale(0.98);\n z-index: 1;\n font-family: inherit;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .media-default-skin video::-webkit-media-text-track-container {\n transition-duration: 50ms;\n }\n}\n\n\n/* ==========================================================================\n Root\n ========================================================================== */\n\n.media-default-skin--video {\n background: oklch(0 0 0);\n --media-border-color: oklch(0 0 0 / 0.1);\n --media-surface-background-color: oklch(1 0 0 / 0.1);\n --media-surface-inner-border-color: oklch(1 0 0 / 0.05);\n --media-surface-outer-border-color: oklch(0 0 0 / 0.1);\n --media-surface-shadow-color: oklch(0 0 0 / 0.15);\n --media-surface-backdrop-filter: blur(16px) saturate(1.5);\n\n @media (prefers-color-scheme: dark) {\n --media-border-color: oklch(1 0 0 / 0.1);\n }\n\n /* Inner border ring */\n &::after {\n content: \"\";\n position: absolute;\n inset: 0;\n z-index: 10;\n border-radius: inherit;\n box-shadow: inset 0 0 0 1px var(--media-border-color);\n pointer-events: none;\n }\n\n &:fullscreen {\n border-radius: 0;\n }\n}\n\n/* ==========================================================================\n Controls (hide/show behavior)\n ========================================================================== */\n\n.media-default-skin--video .media-controls {\n position: absolute;\n bottom: 0.75rem;\n inset-inline: 0.75rem;\n z-index: 10;\n will-change: scale, transform, filter, opacity;\n transition-property: scale, transform, filter, opacity;\n transition-duration: 100ms;\n transition-delay: 0ms;\n transition-timing-function: ease-out;\n transform-origin: bottom;\n color: oklch(1 0 0);\n\n &:not([data-visible]) {\n opacity: 0;\n scale: 0.9;\n filter: blur(8px);\n transition-duration: 300ms;\n transition-delay: 500ms;\n pointer-events: none;\n\n @media (prefers-reduced-motion: reduce) {\n scale: 1;\n filter: blur(0);\n transition-duration: 100ms;\n }\n }\n}\n\n/* ==========================================================================\n Sliders\n ========================================================================== */\n\n.media-default-skin--video .media-slider__track {\n background-color: oklch(1 0 0 / 0.2);\n box-shadow: 0 0 0 1px oklch(0 0 0 / 0.05);\n}\n\nmedia-tooltip-group {\n display: contents;\n}\n\n";
3320
3315
 
3321
3316
  //#endregion
3322
3317
  //#region src/define/media/container.ts
@@ -4313,6 +4308,42 @@ const TooltipDataAttrs = {
4313
4308
  transitionEnding: "data-ending-style"
4314
4309
  };
4315
4310
 
4311
+ //#endregion
4312
+ //#region ../core/dist/dev/core/ui/tooltip/tooltip-group-core.js
4313
+ var TooltipGroupCore = class TooltipGroupCore {
4314
+ static defaultProps = {
4315
+ delay: 600,
4316
+ closeDelay: 0,
4317
+ timeout: 400
4318
+ };
4319
+ #props = { ...TooltipGroupCore.defaultProps };
4320
+ #lastCloseTime = 0;
4321
+ #isOpen = false;
4322
+ constructor(props) {
4323
+ if (props) this.setProps(props);
4324
+ }
4325
+ setProps(props) {
4326
+ this.#props = defaults(props, TooltipGroupCore.defaultProps);
4327
+ }
4328
+ get delay() {
4329
+ return this.#props.delay;
4330
+ }
4331
+ get closeDelay() {
4332
+ return this.#props.closeDelay;
4333
+ }
4334
+ shouldSkipDelay() {
4335
+ if (this.#isOpen) return true;
4336
+ return Date.now() - this.#lastCloseTime < this.#props.timeout;
4337
+ }
4338
+ notifyOpen() {
4339
+ this.#isOpen = true;
4340
+ }
4341
+ notifyClose() {
4342
+ this.#isOpen = false;
4343
+ this.#lastCloseTime = Date.now();
4344
+ }
4345
+ };
4346
+
4316
4347
  //#endregion
4317
4348
  //#region ../core/dist/dev/core/ui/volume-slider/volume-slider-core.js
4318
4349
  /** Volume-domain slider: maps media volume/mute state to slider state. */
@@ -5523,6 +5554,44 @@ var TooltipElement = class extends MediaElement {
5523
5554
  //#region src/define/ui/tooltip.ts
5524
5555
  safeDefine(TooltipElement);
5525
5556
 
5557
+ //#endregion
5558
+ //#region src/ui/tooltip/tooltip-group-element.ts
5559
+ var TooltipGroupElement = class extends MediaElement {
5560
+ constructor(..._args) {
5561
+ super(..._args);
5562
+ this.delay = TooltipGroupCore.defaultProps.delay;
5563
+ this.closeDelay = TooltipGroupCore.defaultProps.closeDelay;
5564
+ this.timeout = TooltipGroupCore.defaultProps.timeout;
5565
+ }
5566
+ static {
5567
+ this.tagName = "media-tooltip-group";
5568
+ }
5569
+ static {
5570
+ this.properties = {
5571
+ delay: { type: Number },
5572
+ closeDelay: {
5573
+ type: Number,
5574
+ attribute: "close-delay"
5575
+ },
5576
+ timeout: { type: Number }
5577
+ };
5578
+ }
5579
+ #core = new TooltipGroupCore();
5580
+ #provider = new ContextProvider(this, {
5581
+ context: tooltipGroupContext,
5582
+ initialValue: this.#core
5583
+ });
5584
+ update(_changed) {
5585
+ super.update(_changed);
5586
+ this.#core.setProps(this);
5587
+ this.#provider.setValue(this.#core);
5588
+ }
5589
+ };
5590
+
5591
+ //#endregion
5592
+ //#region src/define/ui/tooltip-group.ts
5593
+ safeDefine(TooltipGroupElement);
5594
+
5526
5595
  //#endregion
5527
5596
  //#region src/ui/volume-slider/volume-slider-element.ts
5528
5597
  var VolumeSliderElement = class extends MediaElement {
@@ -5658,107 +5727,97 @@ function getTemplateHTML() {
5658
5727
  </div>
5659
5728
  </media-buffering-indicator>
5660
5729
 
5661
- <!--<div class="media-error" role="alertdialog" aria-labelledby="media-error-title" aria-describedby="media-error-description">
5662
- <div class="media-error__dialog media-surface">
5663
- <div class="media-error__content">
5664
- <p id="media-error-title" class="media-error__title">Something went wrong.</p>
5665
- <p id="media-error-description" class="media-error__description">An error occurred while trying to play the video. Please try again.</p>
5666
- </div>
5667
- <div class="media-error__actions">
5668
- <button type="button" class="media-button">OK</button>
5669
- </div>
5670
- </div>
5671
- </div>-->
5672
-
5673
5730
  <media-controls class="media-surface media-controls">
5674
- <media-play-button commandfor="play-tooltip" class="media-button media-button--icon media-button--play">
5675
- ${renderIcon("restart", { class: "media-icon media-icon--restart" })}
5676
- ${renderIcon("play", { class: "media-icon media-icon--play" })}
5677
- ${renderIcon("pause", { class: "media-icon media-icon--pause" })}
5678
- </media-play-button>
5679
- <media-tooltip id="play-tooltip" side="top" class="media-surface media-tooltip">
5680
- <span class="media-tooltip-label media-tooltip-label--replay">Replay</span>
5681
- <span class="media-tooltip-label media-tooltip-label--play">Play</span>
5682
- <span class="media-tooltip-label media-tooltip-label--pause">Pause</span>
5683
- </media-tooltip>
5684
-
5685
- <media-seek-button commandfor="seek-backward-tooltip" seconds="${-SEEK_TIME}" class="media-button media-button--icon media-button--seek">
5686
- <span class="media-icon__container">
5687
- ${renderIcon("seek", { class: "media-icon media-icon--flipped" })}
5688
- <span class="media-icon__label">${SEEK_TIME}</span>
5689
- </span>
5690
- </media-seek-button>
5691
- <media-tooltip id="seek-backward-tooltip" side="top" class="media-surface media-tooltip">
5692
- Seek backward ${SEEK_TIME} seconds
5693
- </media-tooltip>
5694
-
5695
- <media-seek-button commandfor="seek-forward-tooltip" seconds="${SEEK_TIME}" class="media-button media-button--icon media-button--seek">
5696
- <span class="media-icon__container">
5697
- ${renderIcon("seek", { class: "media-icon" })}
5698
- <span class="media-icon__label">${SEEK_TIME}</span>
5699
- </span>
5700
- </media-seek-button>
5701
- <media-tooltip id="seek-forward-tooltip" side="top" class="media-surface media-tooltip">
5702
- Seek forward ${SEEK_TIME} seconds
5703
- </media-tooltip>
5704
-
5705
- <media-time-group class="media-time">
5706
- <media-time type="current" class="media-time__value"></media-time>
5707
- <media-time-slider class="media-slider">
5708
- <media-slider-track class="media-slider__track">
5709
- <media-slider-fill class="media-slider__fill"></media-slider-fill>
5710
- <media-slider-buffer class="media-slider__buffer"></media-slider-buffer>
5711
- </media-slider-track>
5712
- <media-slider-thumb class="media-slider__thumb"></media-slider-thumb>
5713
- </media-time-slider>
5714
- <media-time type="duration" class="media-time__value"></media-time>
5715
- </media-time-group>
5716
-
5717
- <media-playback-rate-button commandfor="playback-rate-tooltip" class="media-button media-button--icon media-button--playback-rate"></media-playback-rate-button>
5718
- <media-tooltip id="playback-rate-tooltip" side="top" class="media-surface media-tooltip">
5719
- Toggle playback rate
5720
- </media-tooltip>
5721
-
5722
- <media-mute-button commandfor="video-volume-popover" class="media-button media-button--icon media-button--mute">
5723
- ${renderIcon("volume-off", { class: "media-icon media-icon--volume-off" })}
5724
- ${renderIcon("volume-low", { class: "media-icon media-icon--volume-low" })}
5725
- ${renderIcon("volume-high", { class: "media-icon media-icon--volume-high" })}
5726
- </media-mute-button>
5727
-
5728
- <media-popover id="video-volume-popover" open-on-hover delay="200" close-delay="100" side="top" class="media-surface media-popover media-popover--volume">
5729
- <media-volume-slider class="media-slider" orientation="vertical" thumb-alignment="edge">
5730
- <media-slider-track class="media-slider__track">
5731
- <media-slider-fill class="media-slider__fill"></media-slider-fill>
5732
- </media-slider-track>
5733
- <media-slider-thumb class="media-slider__thumb media-slider__thumb--persistent"></media-slider-thumb>
5734
- </media-volume-slider>
5735
- </media-popover>
5736
-
5737
- <media-captions-button commandfor="captions-tooltip" class="media-button media-button--icon media-button--captions">
5738
- ${renderIcon("captions-off", { class: "media-icon media-icon--captions-off" })}
5739
- ${renderIcon("captions-on", { class: "media-icon media-icon--captions-on" })}
5740
- </media-captions-button>
5741
- <media-tooltip id="captions-tooltip" side="top" class="media-surface media-tooltip">
5742
- <span class="media-tooltip-label media-tooltip-label--enable-captions">Enable captions</span>
5743
- <span class="media-tooltip-label media-tooltip-label--disable-captions">Disable captions</span>
5744
- </media-tooltip>
5745
-
5746
- <media-pip-button commandfor="pip-tooltip" class="media-button media-button--icon">
5747
- ${renderIcon("pip", { class: "media-icon" })}
5748
- </media-pip-button>
5749
- <media-tooltip id="pip-tooltip" side="top" class="media-surface media-tooltip">
5750
- <span class="media-tooltip-label media-tooltip-label--enter-pip">Enter picture-in-picture</span>
5751
- <span class="media-tooltip-label media-tooltip-label--exit-pip">Exit picture-in-picture</span>
5752
- </media-tooltip>
5753
-
5754
- <media-fullscreen-button commandfor="fullscreen-tooltip" class="media-button media-button--icon media-button--fullscreen">
5755
- ${renderIcon("fullscreen-enter", { class: "media-icon media-icon--fullscreen-enter" })}
5756
- ${renderIcon("fullscreen-exit", { class: "media-icon media-icon--fullscreen-exit" })}
5757
- </media-fullscreen-button>
5758
- <media-tooltip id="fullscreen-tooltip" side="top" class="media-surface media-tooltip">
5759
- <span class="media-tooltip-label media-tooltip-label--enter-fullscreen">Enter fullscreen</span>
5760
- <span class="media-tooltip-label media-tooltip-label--exit-fullscreen">Exit fullscreen</span>
5761
- </media-tooltip>
5731
+ <media-tooltip-group>
5732
+ <media-play-button commandfor="play-tooltip" class="media-button media-button--icon media-button--play">
5733
+ ${renderIcon("restart", { class: "media-icon media-icon--restart" })}
5734
+ ${renderIcon("play", { class: "media-icon media-icon--play" })}
5735
+ ${renderIcon("pause", { class: "media-icon media-icon--pause" })}
5736
+ </media-play-button>
5737
+ <media-tooltip id="play-tooltip" side="top" class="media-surface media-tooltip">
5738
+ <span class="media-tooltip-label media-tooltip-label--replay">Replay</span>
5739
+ <span class="media-tooltip-label media-tooltip-label--play">Play</span>
5740
+ <span class="media-tooltip-label media-tooltip-label--pause">Pause</span>
5741
+ </media-tooltip>
5742
+
5743
+ <media-seek-button commandfor="seek-backward-tooltip" seconds="${-SEEK_TIME}" class="media-button media-button--icon media-button--seek">
5744
+ <span class="media-icon__container">
5745
+ ${renderIcon("seek", { class: "media-icon media-icon--flipped" })}
5746
+ <span class="media-icon__label">${SEEK_TIME}</span>
5747
+ </span>
5748
+ </media-seek-button>
5749
+ <media-tooltip id="seek-backward-tooltip" side="top" class="media-surface media-tooltip">
5750
+ Seek backward ${SEEK_TIME} seconds
5751
+ </media-tooltip>
5752
+
5753
+ <media-seek-button commandfor="seek-forward-tooltip" seconds="${SEEK_TIME}" class="media-button media-button--icon media-button--seek">
5754
+ <span class="media-icon__container">
5755
+ ${renderIcon("seek", { class: "media-icon" })}
5756
+ <span class="media-icon__label">${SEEK_TIME}</span>
5757
+ </span>
5758
+ </media-seek-button>
5759
+ <media-tooltip id="seek-forward-tooltip" side="top" class="media-surface media-tooltip">
5760
+ Seek forward ${SEEK_TIME} seconds
5761
+ </media-tooltip>
5762
+
5763
+ <media-time-group class="media-time">
5764
+ <media-time type="current" class="media-time__value"></media-time>
5765
+ <media-time-slider class="media-slider">
5766
+ <media-slider-track class="media-slider__track">
5767
+ <media-slider-fill class="media-slider__fill"></media-slider-fill>
5768
+ <media-slider-buffer class="media-slider__buffer"></media-slider-buffer>
5769
+ </media-slider-track>
5770
+ <media-slider-thumb class="media-slider__thumb"></media-slider-thumb>
5771
+ </media-time-slider>
5772
+ <media-time type="duration" class="media-time__value"></media-time>
5773
+ </media-time-group>
5774
+
5775
+ <media-playback-rate-button commandfor="playback-rate-tooltip" class="media-button media-button--icon media-button--playback-rate"></media-playback-rate-button>
5776
+ <media-tooltip id="playback-rate-tooltip" side="top" class="media-surface media-tooltip">
5777
+ Toggle playback rate
5778
+ </media-tooltip>
5779
+
5780
+ <media-mute-button commandfor="video-volume-popover" class="media-button media-button--icon media-button--mute">
5781
+ ${renderIcon("volume-off", { class: "media-icon media-icon--volume-off" })}
5782
+ ${renderIcon("volume-low", { class: "media-icon media-icon--volume-low" })}
5783
+ ${renderIcon("volume-high", { class: "media-icon media-icon--volume-high" })}
5784
+ </media-mute-button>
5785
+
5786
+ <media-popover id="video-volume-popover" open-on-hover delay="200" close-delay="100" side="top" class="media-surface media-popover media-popover--volume">
5787
+ <media-volume-slider class="media-slider" orientation="vertical" thumb-alignment="edge">
5788
+ <media-slider-track class="media-slider__track">
5789
+ <media-slider-fill class="media-slider__fill"></media-slider-fill>
5790
+ </media-slider-track>
5791
+ <media-slider-thumb class="media-slider__thumb media-slider__thumb--persistent"></media-slider-thumb>
5792
+ </media-volume-slider>
5793
+ </media-popover>
5794
+
5795
+ <media-captions-button commandfor="captions-tooltip" class="media-button media-button--icon media-button--captions">
5796
+ ${renderIcon("captions-off", { class: "media-icon media-icon--captions-off" })}
5797
+ ${renderIcon("captions-on", { class: "media-icon media-icon--captions-on" })}
5798
+ </media-captions-button>
5799
+ <media-tooltip id="captions-tooltip" side="top" class="media-surface media-tooltip">
5800
+ <span class="media-tooltip-label media-tooltip-label--enable-captions">Enable captions</span>
5801
+ <span class="media-tooltip-label media-tooltip-label--disable-captions">Disable captions</span>
5802
+ </media-tooltip>
5803
+
5804
+ <media-pip-button commandfor="pip-tooltip" class="media-button media-button--icon media-button--pip">
5805
+ ${renderIcon("pip", { class: "media-icon" })}
5806
+ </media-pip-button>
5807
+ <media-tooltip id="pip-tooltip" side="top" class="media-surface media-tooltip">
5808
+ <span class="media-tooltip-label media-tooltip-label--enter-pip">Enter picture-in-picture</span>
5809
+ <span class="media-tooltip-label media-tooltip-label--exit-pip">Exit picture-in-picture</span>
5810
+ </media-tooltip>
5811
+
5812
+ <media-fullscreen-button commandfor="fullscreen-tooltip" class="media-button media-button--icon media-button--fullscreen">
5813
+ ${renderIcon("fullscreen-enter", { class: "media-icon media-icon--fullscreen-enter" })}
5814
+ ${renderIcon("fullscreen-exit", { class: "media-icon media-icon--fullscreen-exit" })}
5815
+ </media-fullscreen-button>
5816
+ <media-tooltip id="fullscreen-tooltip" side="top" class="media-surface media-tooltip">
5817
+ <span class="media-tooltip-label media-tooltip-label--enter-fullscreen">Enter fullscreen</span>
5818
+ <span class="media-tooltip-label media-tooltip-label--exit-fullscreen">Exit fullscreen</span>
5819
+ </media-tooltip>
5820
+ </media-tooltip-group>
5762
5821
  </media-controls>
5763
5822
 
5764
5823
  <div class="media-overlay"></div>