@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
@@ -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"));
2560
+ }
2561
+ function isMediaSlotElement(node) {
2562
+ return node instanceof HTMLSlotElement && node.name === "media";
2548
2563
  }
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;
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/minimal-skin.js
3319
- var minimal_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-minimal-skin *,\n.media-minimal-skin *::before,\n.media-minimal-skin *::after {\n box-sizing: border-box;\n margin: 0;\n}\n.media-minimal-skin img,\n.media-minimal-skin video,\n.media-minimal-skin svg {\n display: block;\n max-width: 100%;\n}\n.media-minimal-skin button {\n font: inherit;\n}\n@media (prefers-reduced-motion: no-preference) {\n .media-minimal-skin {\n interpolate-size: allow-keywords;\n }\n}\n\n/* ==========================================================================\n Root Container\n ========================================================================== */\n\n.media-minimal-skin {\n position: relative;\n isolation: isolate;\n display: block;\n container: media-root / inline-size;\n border-radius: var(--media-border-radius, 0.75rem);\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 Media Element\n ========================================================================== */\n\n.media-minimal-skin ::slotted(video),\n.media-minimal-skin video {\n display: block;\n width: 100%;\n height: 100%;\n border-radius: var(--media-border-radius, 0.75rem);\n}\n\n/* ==========================================================================\n Poster Image\n ========================================================================== */\n\n.media-minimal-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-minimal-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.7), oklch(0 0 0 / 0.5) 7.5rem, 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: 500ms;\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-minimal-skin .media-controls[data-visible] ~ .media-overlay,\n.media-minimal-skin .media-error[data-open] ~ .media-overlay {\n opacity: 1;\n transition-duration: 150ms;\n transition-delay: 0ms;\n}\n\n.media-minimal-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-minimal-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\n/* ==========================================================================\n Error Dialog\n ========================================================================== */\n\n.media-minimal-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 pointer-events: none;\n}\n\n.media-minimal-skin .media-error__dialog {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n max-width: 16rem;\n padding: 1rem;\n color: oklch(1 0 0);\n font-size: 0.875rem;\n text-shadow: 0 1px 0 oklch(0 0 0 / 0.5);\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-minimal-skin .media-error[data-starting-style] .media-error__dialog,\n.media-minimal-skin .media-error[data-ending-style] .media-error__dialog {\n opacity: 0;\n transform: scale(0.5);\n}\n\n.media-minimal-skin .media-error__content {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n padding: 0.375rem 0;\n}\n\n.media-minimal-skin .media-error__title {\n font-weight: 600;\n line-height: 1.25;\n}\n\n.media-minimal-skin .media-error__description {\n opacity: 0.7;\n}\n\n.media-minimal-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-minimal-skin .media-controls {\n container: media-controls / inline-size;\n display: flex;\n align-items: center;\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\n/* ==========================================================================\n Time Controls & Display\n ========================================================================== */\n\n.media-minimal-skin .media-time-controls {\n display: flex;\n flex-direction: row-reverse;\n align-items: center;\n flex: 1;\n gap: 0.75rem;\n}\n.media-minimal-skin .media-time {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n.media-minimal-skin .media-time__value {\n font-variant-numeric: tabular-nums;\n}\n.media-minimal-skin .media-time__value--current,\n.media-minimal-skin .media-time__separator {\n display: none;\n}\n@container media-controls (width > 28rem) {\n .media-minimal-skin .media-time-controls {\n flex-direction: row;\n }\n .media-minimal-skin .media-time__value--duration,\n .media-minimal-skin .media-time__separator {\n color: oklch(from currentColor l c h / 0.6);\n }\n .media-minimal-skin .media-time__value--current,\n .media-minimal-skin .media-time__separator {\n display: inline;\n }\n}\n\n/* ==========================================================================\n Button Groups\n ========================================================================== */\n\n.media-minimal-skin .media-button-group {\n display: flex;\n align-items: center;\n gap: 0.075rem;\n\n @container media-root (width > 40rem) {\n gap: 0.125rem;\n }\n}\n\n/* ==========================================================================\n Buttons\n ========================================================================== */\n\n/* Base button */\n.media-minimal-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: 0.5rem;\n outline: 2px solid transparent;\n outline-offset: -2px;\n color: oklch(0 0 0);\n font-weight: 500;\n text-align: center;\n text-shadow: inherit;\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: currentColor;\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-minimal-skin .media-button--icon {\n display: grid;\n width: 2.375rem;\n padding: 0;\n aspect-ratio: 1;\n background: transparent;\n color: inherit;\n\n &:hover,\n &:focus-visible,\n &[aria-expanded=\"true\"] {\n color: oklch(from currentColor l c h / 0.8);\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-minimal-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-minimal-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-minimal-skin .media-icon__container {\n position: relative;\n}\n.media-minimal-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-minimal-skin .media-icon--flipped {\n scale: -1 1;\n}\n\n/* ==========================================================================\n Slider\n ========================================================================== */\n\n.media-minimal-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: 4.5rem;\n }\n}\n\n/* Track */\n.media-minimal-skin .media-slider__track {\n position: relative;\n isolation: isolate;\n overflow: hidden;\n border-radius: inherit;\n user-select: none;\n background-color: oklch(from currentColor l c h / 0.2);\n\n &[data-orientation=\"horizontal\"] {\n width: 100%;\n height: 0.1875rem;\n }\n\n &[data-orientation=\"vertical\"] {\n width: 0.1875rem;\n height: 100%;\n }\n}\n\n/* Thumb */\n.media-minimal-skin .media-slider__thumb {\n position: absolute;\n transform: translate(-50%, -50%);\n z-index: 10;\n width: 0.75rem;\n height: 0.75rem;\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 scale: 0.7;\n transform-origin: center;\n transition-property: opacity, scale, outline-offset;\n transition-duration: 150ms;\n transition-timing-function: ease-out;\n user-select: none;\n outline: 2px solid transparent;\n outline-offset: -2px;\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 &:focus-visible {\n outline-color: currentColor;\n outline-offset: 2px;\n }\n}\n\n.media-minimal-skin .media-slider:hover .media-slider__thumb,\n.media-minimal-skin .media-slider:focus-within .media-slider__thumb,\n.media-minimal-skin .media-slider__thumb--persistent {\n opacity: 1;\n scale: 1;\n}\n\n/* Shared track fills */\n.media-minimal-skin .media-slider__buffer,\n.media-minimal-skin .media-slider__fill {\n position: absolute;\n border-radius: inherit;\n pointer-events: none;\n}\n\n.media-minimal-skin .media-slider__buffer[data-orientation=\"horizontal\"],\n.media-minimal-skin .media-slider__fill[data-orientation=\"horizontal\"] {\n inset-block: 0;\n left: 0;\n}\n\n.media-minimal-skin .media-slider__buffer[data-orientation=\"vertical\"],\n.media-minimal-skin .media-slider__fill[data-orientation=\"vertical\"] {\n inset-inline: 0;\n bottom: 0;\n}\n\n/* Buffer */\n.media-minimal-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-minimal-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-minimal-skin .media-slider__time-display {\n font-variant-numeric: tabular-nums;\n}\n\n/* ==========================================================================\n Popups & Animations\n ========================================================================== */\n\n.media-minimal-skin .media-popover,\n.media-minimal-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-minimal-skin .media-tooltip {\n padding: 0.25rem 0.5rem;\n border-radius: 0.25rem;\n background-color: oklch(1 0 0 / 0.1);\n backdrop-filter: blur(64px) brightness(0.9) saturate(1.5);\n box-shadow:\n 0 4px 6px -1px oklch(0 0 0 / 0.1),\n 0 2px 4px -2px oklch(0 0 0 / 0.1);\n font-size: 0.75rem;\n white-space: nowrap;\n --media-tooltip-side-offset: 0.5rem;\n\n @media (prefers-reduced-transparency: reduce) {\n background-color: oklch(0 0 0 / 0.7);\n }\n\n @media (prefers-contrast: more) {\n background-color: oklch(0 0 0 / 0.9);\n }\n}\n\n/* ==========================================================================\n Captions\n ========================================================================== */\n\n.media-minimal-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-minimal-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-minimal-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-minimal-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: -3rem;\n }\n}\n\n.media-minimal-skin .media-captions,\n.media-minimal-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-minimal-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-minimal-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-minimal-skin .media-captions,\n .media-minimal-skin video::-webkit-media-text-track-container {\n transition-duration: 50ms;\n }\n}\n\n\n/* ==========================================================================\n Root\n ========================================================================== */\n\n.media-minimal-skin--video {\n background: oklch(0 0 0);\n\n /* 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 oklch(0 0 0 / 0.15);\n pointer-events: none;\n\n @media (prefers-color-scheme: dark) {\n box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.15);\n }\n }\n\n /* Fullscreen */\n &:fullscreen {\n border-radius: 0;\n }\n}\n\n/* ==========================================================================\n Controls (hide/show behavior)\n ========================================================================== */\n\n.media-minimal-skin--video .media-controls {\n position: absolute;\n bottom: 0;\n inset-inline: 0;\n z-index: 10;\n gap: 0.5rem;\n padding: 2rem 0.375rem 0.375rem 0.375rem;\n will-change: transform, filter, opacity;\n transition-property: transform, filter, opacity;\n transition-duration: 75ms;\n transition-delay: 0ms;\n transition-timing-function: ease-out;\n color: oklch(1 0 0);\n\n @container media-root (width > 40rem) {\n gap: 0.875rem;\n padding: 2.5rem 0.75rem 0.75rem 0.75rem;\n }\n\n &:not([data-visible]) {\n opacity: 0;\n transform: translateY(100%);\n filter: blur(8px);\n transition-duration: 500ms;\n transition-delay: 500ms;\n pointer-events: none;\n\n @media (prefers-reduced-motion: reduce) {\n scale: 1;\n transform: translateY(0);\n filter: blur(0);\n transition-duration: 100ms;\n }\n }\n}\n\n/* ==========================================================================\n Sliders\n ========================================================================== */\n\n.media-minimal-skin--video .media-slider__track {\n box-shadow: 0 0 0 1px oklch(0 0 0 / 0.05);\n}\n\n/* ==========================================================================\n Popups & Animations\n ========================================================================== */\n\n.media-minimal-skin--video .media-popover--volume {\n --media-popover-side-offset: 0.5rem;\n background: transparent;\n padding: 0.25rem;\n}\n\n";
3314
+ var minimal_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-minimal-skin *,\n.media-minimal-skin *::before,\n.media-minimal-skin *::after {\n box-sizing: border-box;\n margin: 0;\n}\n.media-minimal-skin img,\n.media-minimal-skin video,\n.media-minimal-skin svg {\n display: block;\n max-width: 100%;\n}\n.media-minimal-skin button {\n font: inherit;\n}\n@media (prefers-reduced-motion: no-preference) {\n .media-minimal-skin {\n interpolate-size: allow-keywords;\n }\n}\n\n/* ==========================================================================\n Root Container\n ========================================================================== */\n\n.media-minimal-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, 0.75rem);\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 Media Element\n ========================================================================== */\n\n.media-minimal-skin ::slotted(video),\n.media-minimal-skin video {\n display: block;\n width: 100%;\n height: 100%;\n}\n.media-minimal-skin ::slotted(video) {\n border-radius: var(--media-border-radius, 0.75rem);\n}\n.media-minimal-skin video {\n border-radius: inherit;\n}\n\n/* ==========================================================================\n Poster Image\n ========================================================================== */\n\n.media-minimal-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-minimal-skin:fullscreen video,\n.media-minimal-skin:fullscreen ::slotted(video),\n.media-minimal-skin > img {\n object-fit: contain;\n}\n.media-minimal-skin:fullscreen ::slotted(video) {\n border-radius: 0;\n}\n\n/* ==========================================================================\n Overlay / Scrim\n ========================================================================== */\n\n.media-minimal-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.7), oklch(0 0 0 / 0.5) 7.5rem, 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: 500ms;\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-minimal-skin .media-controls[data-visible] ~ .media-overlay,\n.media-minimal-skin .media-error[data-open] ~ .media-overlay {\n opacity: 1;\n transition-duration: 150ms;\n transition-delay: 0ms;\n}\n\n.media-minimal-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-minimal-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\n/* ==========================================================================\n Error Dialog\n ========================================================================== */\n\n.media-minimal-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 pointer-events: none;\n}\n\n.media-minimal-skin .media-error__dialog {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n max-width: 16rem;\n padding: 1rem;\n color: oklch(1 0 0);\n font-size: 0.875rem;\n text-shadow: 0 1px 0 oklch(0 0 0 / 0.5);\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-minimal-skin .media-error[data-starting-style] .media-error__dialog,\n.media-minimal-skin .media-error[data-ending-style] .media-error__dialog {\n opacity: 0;\n transform: scale(0.5);\n}\n\n.media-minimal-skin .media-error__content {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n padding: 0.375rem 0;\n}\n\n.media-minimal-skin .media-error__title {\n font-weight: 600;\n line-height: 1.25;\n}\n\n.media-minimal-skin .media-error__description {\n opacity: 0.7;\n}\n\n.media-minimal-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-minimal-skin .media-controls {\n container: media-controls / inline-size;\n display: flex;\n align-items: center;\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\n/* ==========================================================================\n Time Controls & Display\n ========================================================================== */\n\n.media-minimal-skin .media-time-controls {\n display: flex;\n flex-direction: row-reverse;\n align-items: center;\n flex: 1;\n gap: 0.75rem;\n}\n.media-minimal-skin .media-time {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n.media-minimal-skin .media-time__value {\n font-variant-numeric: tabular-nums;\n}\n.media-minimal-skin .media-time__value--current,\n.media-minimal-skin .media-time__separator {\n display: none;\n}\n@container media-controls (width > 28rem) {\n .media-minimal-skin .media-time-controls {\n flex-direction: row;\n }\n .media-minimal-skin .media-time__value--duration,\n .media-minimal-skin .media-time__separator {\n color: oklch(from currentColor l c h / 0.6);\n }\n .media-minimal-skin .media-time__value--current,\n .media-minimal-skin .media-time__separator {\n display: inline;\n }\n}\n\n/* ==========================================================================\n Button Groups\n ========================================================================== */\n\n.media-minimal-skin .media-button-group {\n display: flex;\n align-items: center;\n gap: 0.075rem;\n\n @container media-root (width > 40rem) {\n gap: 0.125rem;\n }\n}\n\n/* ==========================================================================\n Buttons\n ========================================================================== */\n\n/* Base button */\n.media-minimal-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: 0.5rem;\n outline: 2px solid transparent;\n outline-offset: -2px;\n color: oklch(0 0 0);\n font-weight: 500;\n text-align: center;\n text-shadow: inherit;\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: currentColor;\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-minimal-skin .media-button--icon {\n display: grid;\n width: 2.375rem;\n padding: 0;\n aspect-ratio: 1;\n background: transparent;\n color: inherit;\n\n &:hover,\n &:focus-visible,\n &[aria-expanded=\"true\"] {\n color: oklch(from currentColor l c h / 0.8);\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-minimal-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-minimal-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-minimal-skin .media-icon__container {\n position: relative;\n}\n.media-minimal-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-minimal-skin .media-icon--flipped {\n scale: -1 1;\n}\n\n/* ==========================================================================\n Slider\n ========================================================================== */\n\n.media-minimal-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: 4.5rem;\n }\n}\n\n/* Track */\n.media-minimal-skin .media-slider__track {\n position: relative;\n isolation: isolate;\n overflow: hidden;\n border-radius: inherit;\n user-select: none;\n background-color: oklch(from currentColor l c h / 0.2);\n\n &[data-orientation=\"horizontal\"] {\n width: 100%;\n height: 0.1875rem;\n }\n\n &[data-orientation=\"vertical\"] {\n width: 0.1875rem;\n height: 100%;\n }\n}\n\n/* Thumb */\n.media-minimal-skin .media-slider__thumb {\n position: absolute;\n transform: translate(-50%, -50%);\n z-index: 10;\n width: 0.75rem;\n height: 0.75rem;\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 scale: 0.7;\n transform-origin: center;\n transition-property: opacity, scale, outline-offset;\n transition-duration: 150ms;\n transition-timing-function: ease-out;\n user-select: none;\n outline: 2px solid transparent;\n outline-offset: -2px;\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 &:focus-visible {\n outline-color: currentColor;\n outline-offset: 2px;\n }\n}\n\n.media-minimal-skin .media-slider:hover .media-slider__thumb,\n.media-minimal-skin .media-slider:focus-within .media-slider__thumb,\n.media-minimal-skin .media-slider__thumb--persistent {\n opacity: 1;\n scale: 1;\n}\n\n/* Shared track fills */\n.media-minimal-skin .media-slider__buffer,\n.media-minimal-skin .media-slider__fill {\n position: absolute;\n border-radius: inherit;\n pointer-events: none;\n}\n\n.media-minimal-skin .media-slider__buffer[data-orientation=\"horizontal\"],\n.media-minimal-skin .media-slider__fill[data-orientation=\"horizontal\"] {\n inset-block: 0;\n left: 0;\n}\n\n.media-minimal-skin .media-slider__buffer[data-orientation=\"vertical\"],\n.media-minimal-skin .media-slider__fill[data-orientation=\"vertical\"] {\n inset-inline: 0;\n bottom: 0;\n}\n\n/* Buffer */\n.media-minimal-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-minimal-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-minimal-skin .media-slider__time-display {\n font-variant-numeric: tabular-nums;\n}\n\n/* ==========================================================================\n Popups & Animations\n ========================================================================== */\n\n.media-minimal-skin .media-popover,\n.media-minimal-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-minimal-skin .media-tooltip {\n padding: 0.25rem 0.5rem;\n border-radius: 0.25rem;\n background-color: oklch(1 0 0 / 0.1);\n backdrop-filter: blur(16px) saturate(1.5);\n box-shadow:\n 0 4px 6px -1px oklch(0 0 0 / 0.1),\n 0 2px 4px -2px oklch(0 0 0 / 0.1);\n font-size: 0.75rem;\n white-space: nowrap;\n --media-tooltip-side-offset: 0.5rem;\n\n @media (prefers-reduced-transparency: reduce) {\n background-color: oklch(0 0 0 / 0.7);\n }\n\n @media (prefers-contrast: more) {\n background-color: oklch(0 0 0 / 0.9);\n }\n}\n\n/* ==========================================================================\n Native Caption Track\n ========================================================================== */\n\n.media-minimal-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: -3rem;\n }\n}\n\n.media-minimal-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-minimal-skin video::-webkit-media-text-track-container {\n transition-duration: 50ms;\n }\n}\n\n\n/* ==========================================================================\n Root\n ========================================================================== */\n\n.media-minimal-skin--video {\n background: oklch(0 0 0);\n --media-border-color: oklch(0 0 0 / 0.15);\n\n @media (prefers-color-scheme: dark) {\n --media-border-color: oklch(1 0 0 / 0.15);\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 &:fullscreen {\n border-radius: 0;\n }\n}\n\n/* ==========================================================================\n Controls (hide/show behavior)\n ========================================================================== */\n\n.media-minimal-skin--video .media-controls {\n position: absolute;\n bottom: 0;\n inset-inline: 0;\n z-index: 10;\n gap: 0.5rem;\n padding: 2rem 0.375rem 0.375rem 0.375rem;\n will-change: transform, filter, opacity;\n transition-property: transform, filter, opacity;\n transition-duration: 75ms;\n transition-delay: 0ms;\n transition-timing-function: ease-out;\n color: oklch(1 0 0);\n\n @container media-root (width > 40rem) {\n gap: 0.875rem;\n padding: 2.5rem 0.75rem 0.75rem 0.75rem;\n }\n\n &:not([data-visible]) {\n opacity: 0;\n transform: translateY(100%);\n filter: blur(8px);\n transition-duration: 500ms;\n transition-delay: 500ms;\n pointer-events: none;\n\n @media (prefers-reduced-motion: reduce) {\n scale: 1;\n transform: translateY(0);\n filter: blur(0);\n transition-duration: 100ms;\n }\n }\n}\n\n/* ==========================================================================\n Sliders\n ========================================================================== */\n\n.media-minimal-skin--video .media-slider__track {\n box-shadow: 0 0 0 1px oklch(0 0 0 / 0.05);\n}\n\n/* ==========================================================================\n Popups & Animations\n ========================================================================== */\n\n.media-minimal-skin--video .media-popover--volume {\n --media-popover-side-offset: 0.5rem;\n background: transparent;\n padding: 0.25rem;\n}\n\nmedia-tooltip-group {\n display: contents;\n}\n\n";
3320
3315
 
3321
3316
  //#endregion
3322
3317
  //#region src/define/media/container.ts
@@ -4261,6 +4256,42 @@ const TooltipDataAttrs = {
4261
4256
  transitionEnding: "data-ending-style"
4262
4257
  };
4263
4258
 
4259
+ //#endregion
4260
+ //#region ../core/dist/dev/core/ui/tooltip/tooltip-group-core.js
4261
+ var TooltipGroupCore = class TooltipGroupCore {
4262
+ static defaultProps = {
4263
+ delay: 600,
4264
+ closeDelay: 0,
4265
+ timeout: 400
4266
+ };
4267
+ #props = { ...TooltipGroupCore.defaultProps };
4268
+ #lastCloseTime = 0;
4269
+ #isOpen = false;
4270
+ constructor(props) {
4271
+ if (props) this.setProps(props);
4272
+ }
4273
+ setProps(props) {
4274
+ this.#props = defaults(props, TooltipGroupCore.defaultProps);
4275
+ }
4276
+ get delay() {
4277
+ return this.#props.delay;
4278
+ }
4279
+ get closeDelay() {
4280
+ return this.#props.closeDelay;
4281
+ }
4282
+ shouldSkipDelay() {
4283
+ if (this.#isOpen) return true;
4284
+ return Date.now() - this.#lastCloseTime < this.#props.timeout;
4285
+ }
4286
+ notifyOpen() {
4287
+ this.#isOpen = true;
4288
+ }
4289
+ notifyClose() {
4290
+ this.#isOpen = false;
4291
+ this.#lastCloseTime = Date.now();
4292
+ }
4293
+ };
4294
+
4264
4295
  //#endregion
4265
4296
  //#region ../core/dist/dev/core/ui/volume-slider/volume-slider-core.js
4266
4297
  /** Volume-domain slider: maps media volume/mute state to slider state. */
@@ -5450,6 +5481,44 @@ var TooltipElement = class extends MediaElement {
5450
5481
  //#region src/define/ui/tooltip.ts
5451
5482
  safeDefine(TooltipElement);
5452
5483
 
5484
+ //#endregion
5485
+ //#region src/ui/tooltip/tooltip-group-element.ts
5486
+ var TooltipGroupElement = class extends MediaElement {
5487
+ constructor(..._args) {
5488
+ super(..._args);
5489
+ this.delay = TooltipGroupCore.defaultProps.delay;
5490
+ this.closeDelay = TooltipGroupCore.defaultProps.closeDelay;
5491
+ this.timeout = TooltipGroupCore.defaultProps.timeout;
5492
+ }
5493
+ static {
5494
+ this.tagName = "media-tooltip-group";
5495
+ }
5496
+ static {
5497
+ this.properties = {
5498
+ delay: { type: Number },
5499
+ closeDelay: {
5500
+ type: Number,
5501
+ attribute: "close-delay"
5502
+ },
5503
+ timeout: { type: Number }
5504
+ };
5505
+ }
5506
+ #core = new TooltipGroupCore();
5507
+ #provider = new ContextProvider(this, {
5508
+ context: tooltipGroupContext,
5509
+ initialValue: this.#core
5510
+ });
5511
+ update(_changed) {
5512
+ super.update(_changed);
5513
+ this.#core.setProps(this);
5514
+ this.#provider.setValue(this.#core);
5515
+ }
5516
+ };
5517
+
5518
+ //#endregion
5519
+ //#region src/define/ui/tooltip-group.ts
5520
+ safeDefine(TooltipGroupElement);
5521
+
5453
5522
  //#endregion
5454
5523
  //#region src/ui/volume-slider/volume-slider-element.ts
5455
5524
  var VolumeSliderElement = class extends MediaElement {
@@ -5583,114 +5652,104 @@ function getTemplateHTML() {
5583
5652
  ${renderIcon("spinner", { class: "media-icon" })}
5584
5653
  </media-buffering-indicator>
5585
5654
 
5586
- <!--<div class="media-error" role="alertdialog" aria-labelledby="media-error-title" aria-describedby="media-error-description">
5587
- <div class="media-error__dialog">
5588
- <div class="media-error__content">
5589
- <p id="media-error-title" class="media-error__title">Something went wrong.</p>
5590
- <p id="media-error-description" class="media-error__description">An error occurred while trying to play the video. Please try again.</p>
5591
- </div>
5592
- <div class="media-error__actions">
5593
- <button type="button" class="media-button">OK</button>
5655
+ <media-controls class="media-controls">
5656
+ <media-tooltip-group>
5657
+ <div class="media-button-group">
5658
+ <media-play-button commandfor="play-tooltip" class="media-button media-button--icon media-button--play">
5659
+ ${renderIcon("restart", { class: "media-icon media-icon--restart" })}
5660
+ ${renderIcon("play", { class: "media-icon media-icon--play" })}
5661
+ ${renderIcon("pause", { class: "media-icon media-icon--pause" })}
5662
+ </media-play-button>
5663
+ <media-tooltip id="play-tooltip" side="top" class="media-tooltip">
5664
+ <span class="media-tooltip-label media-tooltip-label--replay">Replay</span>
5665
+ <span class="media-tooltip-label media-tooltip-label--play">Play</span>
5666
+ <span class="media-tooltip-label media-tooltip-label--pause">Pause</span>
5667
+ </media-tooltip>
5668
+
5669
+ <media-seek-button commandfor="seek-backward-tooltip" seconds="${-SEEK_TIME}" class="media-button media-button--icon media-button--seek">
5670
+ <span class="media-icon__container">
5671
+ ${renderIcon("seek", { class: "media-icon media-icon--flipped" })}
5672
+ <span class="media-icon__label">${SEEK_TIME}</span>
5673
+ </span>
5674
+ </media-seek-button>
5675
+ <media-tooltip id="seek-backward-tooltip" side="top" class="media-tooltip">
5676
+ Seek backward ${SEEK_TIME} seconds
5677
+ </media-tooltip>
5678
+
5679
+ <media-seek-button commandfor="seek-forward-tooltip" seconds="${SEEK_TIME}" class="media-button media-button--icon media-button--seek">
5680
+ <span class="media-icon__container">
5681
+ ${renderIcon("seek", { class: "media-icon" })}
5682
+ <span class="media-icon__label">${SEEK_TIME}</span>
5683
+ </span>
5684
+ </media-seek-button>
5685
+ <media-tooltip id="seek-forward-tooltip" side="top" class="media-tooltip">
5686
+ Seek forward ${SEEK_TIME} seconds
5687
+ </media-tooltip>
5594
5688
  </div>
5595
- </div>
5596
- </div>-->
5597
5689
 
5598
- <media-controls class="media-controls">
5599
- <span class="media-button-group">
5600
- <media-play-button commandfor="play-tooltip" class="media-button media-button--icon media-button--play">
5601
- ${renderIcon("restart", { class: "media-icon media-icon--restart" })}
5602
- ${renderIcon("play", { class: "media-icon media-icon--play" })}
5603
- ${renderIcon("pause", { class: "media-icon media-icon--pause" })}
5604
- </media-play-button>
5605
- <media-tooltip id="play-tooltip" side="top" class="media-tooltip">
5606
- <span class="media-tooltip-label media-tooltip-label--replay">Replay</span>
5607
- <span class="media-tooltip-label media-tooltip-label--play">Play</span>
5608
- <span class="media-tooltip-label media-tooltip-label--pause">Pause</span>
5609
- </media-tooltip>
5610
-
5611
- <media-seek-button commandfor="seek-backward-tooltip" seconds="${-SEEK_TIME}" class="media-button media-button--icon media-button--seek">
5612
- <span class="media-icon__container">
5613
- ${renderIcon("seek", { class: "media-icon media-icon--flipped" })}
5614
- <span class="media-icon__label">${SEEK_TIME}</span>
5615
- </span>
5616
- </media-seek-button>
5617
- <media-tooltip id="seek-backward-tooltip" side="top" class="media-tooltip">
5618
- Seek backward ${SEEK_TIME} seconds
5619
- </media-tooltip>
5620
-
5621
- <media-seek-button commandfor="seek-forward-tooltip" seconds="${SEEK_TIME}" class="media-button media-button--icon media-button--seek">
5622
- <span class="media-icon__container">
5623
- ${renderIcon("seek", { class: "media-icon" })}
5624
- <span class="media-icon__label">${SEEK_TIME}</span>
5625
- </span>
5626
- </media-seek-button>
5627
- <media-tooltip id="seek-forward-tooltip" side="top" class="media-tooltip">
5628
- Seek forward ${SEEK_TIME} seconds
5629
- </media-tooltip>
5630
- </span>
5631
-
5632
- <span class="media-time-controls">
5633
- <media-time-group class="media-time">
5634
- <media-time type="current" class="media-time__value media-time__value--current"></media-time>
5635
- <media-time-separator class="media-time__separator"></media-time-separator>
5636
- <media-time type="duration" class="media-time__value media-time__value--duration"></media-time>
5637
- </media-time-group>
5638
-
5639
- <media-time-slider class="media-slider">
5640
- <media-slider-track class="media-slider__track">
5641
- <media-slider-fill class="media-slider__fill"></media-slider-fill>
5642
- <media-slider-buffer class="media-slider__buffer"></media-slider-buffer>
5643
- </media-slider-track>
5644
- <media-slider-thumb class="media-slider__thumb"></media-slider-thumb>
5645
- </media-time-slider>
5646
- </span>
5647
-
5648
- <span class="media-button-group">
5649
- <media-playback-rate-button commandfor="playback-rate-tooltip" class="media-button media-button--icon media-button--playback-rate"></media-playback-rate-button>
5650
- <media-tooltip id="playback-rate-tooltip" side="top" class="media-tooltip">
5651
- Toggle playback rate
5652
- </media-tooltip>
5653
-
5654
- <media-mute-button commandfor="video-volume-popover" class="media-button media-button--icon media-button--mute">
5655
- ${renderIcon("volume-off", { class: "media-icon media-icon--volume-off" })}
5656
- ${renderIcon("volume-low", { class: "media-icon media-icon--volume-low" })}
5657
- ${renderIcon("volume-high", { class: "media-icon media-icon--volume-high" })}
5658
- </media-mute-button>
5659
-
5660
- <media-popover id="video-volume-popover" open-on-hover delay="200" close-delay="100" side="top" class="media-popover media-popover--volume">
5661
- <media-volume-slider class="media-slider" orientation="vertical" thumb-alignment="edge">
5690
+ <div class="media-time-controls">
5691
+ <media-time-group class="media-time">
5692
+ <media-time type="current" class="media-time__value media-time__value--current"></media-time>
5693
+ <media-time-separator class="media-time__separator"></media-time-separator>
5694
+ <media-time type="duration" class="media-time__value media-time__value--duration"></media-time>
5695
+ </media-time-group>
5696
+
5697
+ <media-time-slider class="media-slider">
5662
5698
  <media-slider-track class="media-slider__track">
5663
5699
  <media-slider-fill class="media-slider__fill"></media-slider-fill>
5700
+ <media-slider-buffer class="media-slider__buffer"></media-slider-buffer>
5664
5701
  </media-slider-track>
5665
- <media-slider-thumb class="media-slider__thumb media-slider__thumb--persistent"></media-slider-thumb>
5666
- </media-volume-slider>
5667
- </media-popover>
5668
-
5669
- <media-captions-button commandfor="captions-tooltip" class="media-button media-button--icon media-button--captions">
5670
- ${renderIcon("captions-off", { class: "media-icon media-icon--captions-off" })}
5671
- ${renderIcon("captions-on", { class: "media-icon media-icon--captions-on" })}
5672
- </media-captions-button>
5673
- <media-tooltip id="captions-tooltip" side="top" class="media-tooltip">
5674
- Toggle captions
5675
- </media-tooltip>
5676
-
5677
- <media-pip-button commandfor="pip-tooltip" class="media-button media-button--icon">
5678
- ${renderIcon("pip", { class: "media-icon" })}
5679
- </media-pip-button>
5680
- <media-tooltip id="pip-tooltip" side="top" class="media-tooltip">
5681
- <span class="media-tooltip-label media-tooltip-label--enter-pip">Enter picture-in-picture</span>
5682
- <span class="media-tooltip-label media-tooltip-label--exit-pip">Exit picture-in-picture</span>
5683
- </media-tooltip>
5684
-
5685
- <media-fullscreen-button commandfor="fullscreen-tooltip" class="media-button media-button--icon media-button--fullscreen">
5686
- ${renderIcon("fullscreen-enter", { class: "media-icon media-icon--fullscreen-enter" })}
5687
- ${renderIcon("fullscreen-exit", { class: "media-icon media-icon--fullscreen-exit" })}
5688
- </media-fullscreen-button>
5689
- <media-tooltip id="fullscreen-tooltip" side="top" class="media-tooltip">
5690
- <span class="media-tooltip-label media-tooltip-label--enter-fullscreen">Enter fullscreen</span>
5691
- <span class="media-tooltip-label media-tooltip-label--exit-fullscreen">Exit fullscreen</span>
5692
- </media-tooltip>
5693
- </span>
5702
+ <media-slider-thumb class="media-slider__thumb"></media-slider-thumb>
5703
+ </media-time-slider>
5704
+ </div>
5705
+
5706
+ <div class="media-button-group">
5707
+ <media-playback-rate-button commandfor="playback-rate-tooltip" class="media-button media-button--icon media-button--playback-rate"></media-playback-rate-button>
5708
+ <media-tooltip id="playback-rate-tooltip" side="top" class="media-tooltip">
5709
+ Toggle playback rate
5710
+ </media-tooltip>
5711
+
5712
+ <media-mute-button commandfor="video-volume-popover" class="media-button media-button--icon media-button--mute">
5713
+ ${renderIcon("volume-off", { class: "media-icon media-icon--volume-off" })}
5714
+ ${renderIcon("volume-low", { class: "media-icon media-icon--volume-low" })}
5715
+ ${renderIcon("volume-high", { class: "media-icon media-icon--volume-high" })}
5716
+ </media-mute-button>
5717
+
5718
+ <media-popover id="video-volume-popover" open-on-hover delay="200" close-delay="100" side="top" class="media-popover media-popover--volume">
5719
+ <media-volume-slider class="media-slider" orientation="vertical" thumb-alignment="edge">
5720
+ <media-slider-track class="media-slider__track">
5721
+ <media-slider-fill class="media-slider__fill"></media-slider-fill>
5722
+ </media-slider-track>
5723
+ <media-slider-thumb class="media-slider__thumb media-slider__thumb--persistent"></media-slider-thumb>
5724
+ </media-volume-slider>
5725
+ </media-popover>
5726
+
5727
+ <media-captions-button commandfor="captions-tooltip" class="media-button media-button--icon media-button--captions">
5728
+ ${renderIcon("captions-off", { class: "media-icon media-icon--captions-off" })}
5729
+ ${renderIcon("captions-on", { class: "media-icon media-icon--captions-on" })}
5730
+ </media-captions-button>
5731
+ <media-tooltip id="captions-tooltip" side="top" class="media-tooltip">
5732
+ Toggle captions
5733
+ </media-tooltip>
5734
+
5735
+ <media-pip-button commandfor="pip-tooltip" class="media-button media-button--icon">
5736
+ ${renderIcon("pip", { class: "media-icon" })}
5737
+ </media-pip-button>
5738
+ <media-tooltip id="pip-tooltip" side="top" class="media-tooltip">
5739
+ <span class="media-tooltip-label media-tooltip-label--enter-pip">Enter picture-in-picture</span>
5740
+ <span class="media-tooltip-label media-tooltip-label--exit-pip">Exit picture-in-picture</span>
5741
+ </media-tooltip>
5742
+
5743
+ <media-fullscreen-button commandfor="fullscreen-tooltip" class="media-button media-button--icon media-button--fullscreen">
5744
+ ${renderIcon("fullscreen-enter", { class: "media-icon media-icon--fullscreen-enter" })}
5745
+ ${renderIcon("fullscreen-exit", { class: "media-icon media-icon--fullscreen-exit" })}
5746
+ </media-fullscreen-button>
5747
+ <media-tooltip id="fullscreen-tooltip" side="top" class="media-tooltip">
5748
+ <span class="media-tooltip-label media-tooltip-label--enter-fullscreen">Enter fullscreen</span>
5749
+ <span class="media-tooltip-label media-tooltip-label--exit-fullscreen">Exit fullscreen</span>
5750
+ </media-tooltip>
5751
+ </div>
5752
+ </media-tooltip-group>
5694
5753
  </media-controls>
5695
5754
 
5696
5755
  <div class="media-overlay"></div>