@videojs/html 10.3.0 → 10.4.0

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 (272) hide show
  1. package/dist/default/define/audio/compat-skin.css +91 -38
  2. package/dist/default/define/audio/compat-skin2.js +1 -1
  3. package/dist/default/define/audio/neutral-skin.css +52 -31
  4. package/dist/default/define/audio/neutral-skin2.js +1 -1
  5. package/dist/default/define/audio/scaffold-skin.css +105 -40
  6. package/dist/default/define/audio/scaffold-skin2.js +1 -1
  7. package/dist/default/define/audio/skin.css +53 -31
  8. package/dist/default/define/audio/skin2.js +1 -1
  9. package/dist/default/define/live-audio/compat-skin.css +91 -38
  10. package/dist/default/define/live-audio/compat-skin2.js +1 -1
  11. package/dist/default/define/live-audio/neutral-skin.css +50 -29
  12. package/dist/default/define/live-audio/neutral-skin2.js +1 -1
  13. package/dist/default/define/live-audio/scaffold-skin.css +105 -40
  14. package/dist/default/define/live-audio/scaffold-skin2.js +1 -1
  15. package/dist/default/define/live-audio/skin.css +51 -29
  16. package/dist/default/define/live-audio/skin2.js +1 -1
  17. package/dist/default/define/live-video/compat-skin.css +142 -61
  18. package/dist/default/define/live-video/compat-skin2.js +1 -1
  19. package/dist/default/define/live-video/neutral-skin.css +241 -55
  20. package/dist/default/define/live-video/neutral-skin2.js +1 -1
  21. package/dist/default/define/live-video/scaffold-skin.css +159 -63
  22. package/dist/default/define/live-video/scaffold-skin2.js +1 -1
  23. package/dist/default/define/live-video/skin.css +245 -60
  24. package/dist/default/define/live-video/skin2.js +1 -1
  25. package/dist/default/define/ui/time-slider-markers.js +5 -0
  26. package/dist/default/define/video/compat-skin.css +150 -61
  27. package/dist/default/define/video/compat-skin2.js +1 -1
  28. package/dist/default/define/video/neutral-skin.css +322 -66
  29. package/dist/default/define/video/neutral-skin2.js +1 -1
  30. package/dist/default/define/video/scaffold-skin.css +168 -63
  31. package/dist/default/define/video/scaffold-skin2.js +1 -1
  32. package/dist/default/define/video/skin.css +348 -66
  33. package/dist/default/define/video/skin2.js +1 -1
  34. package/dist/default/index.js +3 -1
  35. package/dist/default/internal/skins/compat-audio/skin.css +91 -38
  36. package/dist/default/internal/skins/compat-live-audio/skin.css +91 -38
  37. package/dist/default/internal/skins/compat-live-video/skin.css +142 -61
  38. package/dist/default/internal/skins/compat-live-video/template.js +2 -0
  39. package/dist/default/internal/skins/compat-video/skin.css +150 -61
  40. package/dist/default/internal/skins/compat-video/template.js +2 -0
  41. package/dist/default/internal/skins/default-audio/skin.css +53 -31
  42. package/dist/default/internal/skins/default-live-audio/skin.css +51 -29
  43. package/dist/default/internal/skins/default-live-video/skin.css +245 -60
  44. package/dist/default/internal/skins/default-live-video/template.js +14 -0
  45. package/dist/default/internal/skins/default-video/register.js +3 -0
  46. package/dist/default/internal/skins/default-video/skin.css +348 -66
  47. package/dist/default/internal/skins/default-video/template.js +33 -5
  48. package/dist/default/internal/skins/neutral-audio/skin.css +52 -31
  49. package/dist/default/internal/skins/neutral-live-audio/skin.css +50 -29
  50. package/dist/default/internal/skins/neutral-live-video/skin.css +241 -55
  51. package/dist/default/internal/skins/neutral-live-video/template.js +14 -0
  52. package/dist/default/internal/skins/neutral-video/skin.css +322 -66
  53. package/dist/default/internal/skins/neutral-video/template.js +25 -11
  54. package/dist/default/internal/skins/scaffold-audio/skin.css +105 -40
  55. package/dist/default/internal/skins/scaffold-live-audio/skin.css +105 -40
  56. package/dist/default/internal/skins/scaffold-live-video/skin.css +159 -63
  57. package/dist/default/internal/skins/scaffold-live-video/template.js +2 -0
  58. package/dist/default/internal/skins/scaffold-video/skin.css +168 -63
  59. package/dist/default/internal/skins/scaffold-video/template.js +3 -1
  60. package/dist/default/media/background-video/adapter.js +13 -35
  61. package/dist/default/media/background-video/base.js +95 -0
  62. package/dist/default/media/background-video/template.js +13 -20
  63. package/dist/default/media/hls-background-video/adapter.js +16 -35
  64. package/dist/default/ui/captions-radio-group/element.js +14 -1
  65. package/dist/default/ui/controls/element.js +6 -3
  66. package/dist/default/ui/time-slider/markers.js +160 -0
  67. package/dist/default/version.js +1 -1
  68. package/dist/dev/define/audio/compat-skin.css +91 -38
  69. package/dist/dev/define/audio/compat-skin2.js +1 -1
  70. package/dist/dev/define/audio/compat-skin2.js.map +1 -1
  71. package/dist/dev/define/audio/neutral-skin.css +52 -31
  72. package/dist/dev/define/audio/neutral-skin2.js +1 -1
  73. package/dist/dev/define/audio/neutral-skin2.js.map +1 -1
  74. package/dist/dev/define/audio/scaffold-skin.css +105 -40
  75. package/dist/dev/define/audio/scaffold-skin2.js +1 -1
  76. package/dist/dev/define/audio/scaffold-skin2.js.map +1 -1
  77. package/dist/dev/define/audio/skin.css +53 -31
  78. package/dist/dev/define/audio/skin2.js +1 -1
  79. package/dist/dev/define/audio/skin2.js.map +1 -1
  80. package/dist/dev/define/live-audio/compat-skin.css +91 -38
  81. package/dist/dev/define/live-audio/compat-skin2.js +1 -1
  82. package/dist/dev/define/live-audio/compat-skin2.js.map +1 -1
  83. package/dist/dev/define/live-audio/neutral-skin.css +50 -29
  84. package/dist/dev/define/live-audio/neutral-skin2.js +1 -1
  85. package/dist/dev/define/live-audio/neutral-skin2.js.map +1 -1
  86. package/dist/dev/define/live-audio/scaffold-skin.css +105 -40
  87. package/dist/dev/define/live-audio/scaffold-skin2.js +1 -1
  88. package/dist/dev/define/live-audio/scaffold-skin2.js.map +1 -1
  89. package/dist/dev/define/live-audio/skin.css +51 -29
  90. package/dist/dev/define/live-audio/skin2.js +1 -1
  91. package/dist/dev/define/live-audio/skin2.js.map +1 -1
  92. package/dist/dev/define/live-video/compat-skin.css +142 -61
  93. package/dist/dev/define/live-video/compat-skin2.js +1 -1
  94. package/dist/dev/define/live-video/compat-skin2.js.map +1 -1
  95. package/dist/dev/define/live-video/neutral-skin.css +241 -55
  96. package/dist/dev/define/live-video/neutral-skin2.js +1 -1
  97. package/dist/dev/define/live-video/neutral-skin2.js.map +1 -1
  98. package/dist/dev/define/live-video/scaffold-skin.css +159 -63
  99. package/dist/dev/define/live-video/scaffold-skin2.js +1 -1
  100. package/dist/dev/define/live-video/scaffold-skin2.js.map +1 -1
  101. package/dist/dev/define/live-video/skin.css +245 -60
  102. package/dist/dev/define/live-video/skin2.js +1 -1
  103. package/dist/dev/define/live-video/skin2.js.map +1 -1
  104. package/dist/dev/define/ui/time-slider-markers.d.ts +8 -0
  105. package/dist/dev/define/ui/time-slider-markers.js +7 -0
  106. package/dist/dev/define/ui/time-slider-markers.js.map +1 -0
  107. package/dist/dev/define/video/compat-skin.css +150 -61
  108. package/dist/dev/define/video/compat-skin2.js +1 -1
  109. package/dist/dev/define/video/compat-skin2.js.map +1 -1
  110. package/dist/dev/define/video/neutral-skin.css +322 -66
  111. package/dist/dev/define/video/neutral-skin2.js +1 -1
  112. package/dist/dev/define/video/neutral-skin2.js.map +1 -1
  113. package/dist/dev/define/video/scaffold-skin.css +168 -63
  114. package/dist/dev/define/video/scaffold-skin2.js +1 -1
  115. package/dist/dev/define/video/scaffold-skin2.js.map +1 -1
  116. package/dist/dev/define/video/skin.css +348 -66
  117. package/dist/dev/define/video/skin2.js +1 -1
  118. package/dist/dev/define/video/skin2.js.map +1 -1
  119. package/dist/dev/index.d.ts +5 -4
  120. package/dist/dev/index.js +3 -1
  121. package/dist/dev/internal/skins/compat-audio/skin.css +91 -38
  122. package/dist/dev/internal/skins/compat-live-audio/skin.css +91 -38
  123. package/dist/dev/internal/skins/compat-live-video/skin.css +142 -61
  124. package/dist/dev/internal/skins/compat-live-video/template.js +2 -0
  125. package/dist/dev/internal/skins/compat-live-video/template.js.map +1 -1
  126. package/dist/dev/internal/skins/compat-video/skin.css +150 -61
  127. package/dist/dev/internal/skins/compat-video/template.js +2 -0
  128. package/dist/dev/internal/skins/compat-video/template.js.map +1 -1
  129. package/dist/dev/internal/skins/default-audio/skin.css +53 -31
  130. package/dist/dev/internal/skins/default-live-audio/skin.css +51 -29
  131. package/dist/dev/internal/skins/default-live-video/register.js.map +1 -1
  132. package/dist/dev/internal/skins/default-live-video/skin.css +245 -60
  133. package/dist/dev/internal/skins/default-live-video/template.js +14 -0
  134. package/dist/dev/internal/skins/default-live-video/template.js.map +1 -1
  135. package/dist/dev/internal/skins/default-video/register.d.ts +1 -0
  136. package/dist/dev/internal/skins/default-video/register.js +3 -0
  137. package/dist/dev/internal/skins/default-video/register.js.map +1 -1
  138. package/dist/dev/internal/skins/default-video/skin.css +348 -66
  139. package/dist/dev/internal/skins/default-video/template.js +33 -5
  140. package/dist/dev/internal/skins/default-video/template.js.map +1 -1
  141. package/dist/dev/internal/skins/neutral-audio/skin.css +52 -31
  142. package/dist/dev/internal/skins/neutral-live-audio/skin.css +50 -29
  143. package/dist/dev/internal/skins/neutral-live-video/register.js.map +1 -1
  144. package/dist/dev/internal/skins/neutral-live-video/skin.css +241 -55
  145. package/dist/dev/internal/skins/neutral-live-video/template.js +14 -0
  146. package/dist/dev/internal/skins/neutral-live-video/template.js.map +1 -1
  147. package/dist/dev/internal/skins/neutral-video/register.js.map +1 -1
  148. package/dist/dev/internal/skins/neutral-video/skin.css +322 -66
  149. package/dist/dev/internal/skins/neutral-video/template.js +25 -11
  150. package/dist/dev/internal/skins/neutral-video/template.js.map +1 -1
  151. package/dist/dev/internal/skins/scaffold-audio/skin.css +105 -40
  152. package/dist/dev/internal/skins/scaffold-live-audio/skin.css +105 -40
  153. package/dist/dev/internal/skins/scaffold-live-video/skin.css +159 -63
  154. package/dist/dev/internal/skins/scaffold-live-video/template.js +2 -0
  155. package/dist/dev/internal/skins/scaffold-live-video/template.js.map +1 -1
  156. package/dist/dev/internal/skins/scaffold-video/skin.css +168 -63
  157. package/dist/dev/internal/skins/scaffold-video/template.js +3 -1
  158. package/dist/dev/internal/skins/scaffold-video/template.js.map +1 -1
  159. package/dist/dev/media/background-video/adapter.d.ts +7 -13
  160. package/dist/dev/media/background-video/adapter.js +13 -35
  161. package/dist/dev/media/background-video/adapter.js.map +1 -1
  162. package/dist/dev/media/background-video/base.d.ts +44 -0
  163. package/dist/dev/media/background-video/base.js +97 -0
  164. package/dist/dev/media/background-video/base.js.map +1 -0
  165. package/dist/dev/media/background-video/template.d.ts +3 -0
  166. package/dist/dev/media/background-video/template.js +13 -20
  167. package/dist/dev/media/background-video/template.js.map +1 -1
  168. package/dist/dev/media/hls-background-video/adapter.d.ts +8 -18
  169. package/dist/dev/media/hls-background-video/adapter.js +16 -35
  170. package/dist/dev/media/hls-background-video/adapter.js.map +1 -1
  171. package/dist/dev/ui/captions-button/element.d.ts +2 -0
  172. package/dist/dev/ui/captions-radio-group/element.d.ts +2 -1
  173. package/dist/dev/ui/captions-radio-group/element.js +14 -1
  174. package/dist/dev/ui/captions-radio-group/element.js.map +1 -1
  175. package/dist/dev/ui/controls/element.d.ts +2 -2
  176. package/dist/dev/ui/controls/element.js +6 -3
  177. package/dist/dev/ui/controls/element.js.map +1 -1
  178. package/dist/dev/ui/time-slider/markers.d.ts +48 -0
  179. package/dist/dev/ui/time-slider/markers.js +165 -0
  180. package/dist/dev/ui/time-slider/markers.js.map +1 -0
  181. package/dist/dev/version.js +1 -1
  182. package/docs/README.md +1 -1
  183. package/docs/guides/autoplay.md +1 -1
  184. package/docs/guides/background-video.md +2 -4
  185. package/docs/guides/browser-support.md +22 -16
  186. package/docs/guides/cdn.md +9 -9
  187. package/docs/guides/customize-skins.md +3 -0
  188. package/docs/guides/installation-cdn.md +2 -2
  189. package/docs/guides/installation-shadcn.md +1 -1
  190. package/docs/guides/installation-svelte.md +2 -2
  191. package/docs/guides/installation-vue.md +2 -2
  192. package/docs/guides/installation.md +2 -2
  193. package/docs/guides/internationalization.md +5 -5
  194. package/docs/guides/keyboard-shortcuts.md +10 -0
  195. package/docs/guides/llms.txt +2 -1
  196. package/docs/guides/migrate-from-media-chrome.md +4 -4
  197. package/docs/guides/migrate-from-mux-player.md +6 -6
  198. package/docs/guides/migrate-from-plyr.md +7 -7
  199. package/docs/guides/migrate-from-video-js-8.md +6 -6
  200. package/docs/guides/migrate-from-vidstack.md +4 -4
  201. package/docs/guides/presets.md +4 -4
  202. package/docs/guides/self-hosting.md +5 -5
  203. package/docs/guides/skins.md +8 -7
  204. package/docs/guides/timed-metadata.md +318 -0
  205. package/docs/llms.txt +16 -2
  206. package/docs/reference/api/chapters-track.md +71 -0
  207. package/docs/reference/api/define-text-track.md +113 -0
  208. package/docs/reference/api/feature-text-cues.md +133 -0
  209. package/docs/reference/api/feature-text-tracks.md +11 -5
  210. package/docs/reference/api/get-active-text-cues.md +69 -0
  211. package/docs/reference/api/get-text-cues.md +69 -0
  212. package/docs/reference/api/get-text-tracks.md +41 -0
  213. package/docs/reference/api/hls-metadata-track.md +48 -0
  214. package/docs/reference/api/html-create-player.md +2 -2
  215. package/docs/reference/api/llms.txt +13 -1
  216. package/docs/reference/api/media-capabilities.md +4 -4
  217. package/docs/reference/api/player-store.md +9 -4
  218. package/docs/reference/api/preset-audio.md +3 -1
  219. package/docs/reference/api/preset-background.md +1 -1
  220. package/docs/reference/api/preset-live-audio.md +3 -1
  221. package/docs/reference/api/preset-live-video.md +2 -1
  222. package/docs/reference/api/preset-video.md +2 -1
  223. package/docs/reference/components/audio-compat-skin.md +1 -1
  224. package/docs/reference/components/audio-neutral-skin.md +1 -1
  225. package/docs/reference/components/audio-scaffold-skin.md +1 -1
  226. package/docs/reference/components/audio-skin.md +1 -1
  227. package/docs/reference/components/audio.md +19 -1
  228. package/docs/reference/components/background-video-skin.md +1 -1
  229. package/docs/reference/components/background-video.md +26 -11
  230. package/docs/reference/components/captions-radio-group.md +1 -1
  231. package/docs/reference/components/cloudflare-video.md +1 -1
  232. package/docs/reference/components/controls.md +16 -3
  233. package/docs/reference/components/dailymotion-video.md +2 -2
  234. package/docs/reference/components/dash-video.md +20 -3
  235. package/docs/reference/components/google-analytics.md +1 -1
  236. package/docs/reference/components/google-cast.md +1 -1
  237. package/docs/reference/components/hls-audio.md +56 -2
  238. package/docs/reference/components/hls-background-video.md +22 -5
  239. package/docs/reference/components/hls-video.md +99 -7
  240. package/docs/reference/components/hlsjs-video.md +52 -13
  241. package/docs/reference/components/live-audio-compat-skin.md +1 -1
  242. package/docs/reference/components/live-audio-neutral-skin.md +1 -1
  243. package/docs/reference/components/live-audio-scaffold-skin.md +1 -1
  244. package/docs/reference/components/live-audio-skin.md +1 -1
  245. package/docs/reference/components/live-video-compat-skin.md +5 -1
  246. package/docs/reference/components/live-video-neutral-skin.md +5 -1
  247. package/docs/reference/components/live-video-scaffold-skin.md +5 -1
  248. package/docs/reference/components/live-video-skin.md +5 -1
  249. package/docs/reference/components/llms.txt +2 -1
  250. package/docs/reference/components/mixcloud-audio.md +2 -2
  251. package/docs/reference/components/mux-audio.md +34 -3
  252. package/docs/reference/components/mux-background-video.md +1 -1
  253. package/docs/reference/components/mux-data.md +1 -1
  254. package/docs/reference/components/mux-video.md +17 -3
  255. package/docs/reference/components/native-hls-video.md +32 -3
  256. package/docs/reference/components/playerjs-video.md +2 -2
  257. package/docs/reference/components/shaka-video.md +2 -3
  258. package/docs/reference/components/soundcloud-audio.md +2 -2
  259. package/docs/reference/components/spotify-audio.md +2 -2
  260. package/docs/reference/components/tiktok-video.md +2 -2
  261. package/docs/reference/components/time-slider-markers.md +194 -0
  262. package/docs/reference/components/time-slider.md +14 -0
  263. package/docs/reference/components/twitch-video.md +1 -1
  264. package/docs/reference/components/video-compat-skin.md +5 -1
  265. package/docs/reference/components/video-neutral-skin.md +5 -1
  266. package/docs/reference/components/video-scaffold-skin.md +5 -1
  267. package/docs/reference/components/video-skin.md +5 -1
  268. package/docs/reference/components/video.md +19 -1
  269. package/docs/reference/components/vimeo-video.md +1 -2
  270. package/docs/reference/components/wistia-video.md +1 -1
  271. package/docs/reference/components/youtube-video.md +1 -2
  272. package/package.json +48 -48
@@ -955,6 +955,12 @@
955
955
  flex-shrink: 0;
956
956
  }
957
957
 
958
+ @container media-root (width < 15rem) {
959
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .media-settings-button {
960
+ display: none;
961
+ }
962
+ }
963
+
958
964
  :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .media-settings-button-label {
959
965
  clip-path: inset(50%);
960
966
  white-space: nowrap;
@@ -1231,6 +1237,12 @@
1231
1237
  display: block;
1232
1238
  }
1233
1239
 
1240
+ @container media-root (width < 15rem) {
1241
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .media-captions-button {
1242
+ display: none;
1243
+ }
1244
+ }
1245
+
1234
1246
  :where(.media-skin[data-theme="scaffold"][data-preset="video"]) :where(.media-captions-button)[data-active] .media-captions-button-off-icon, :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .media-captions-button-on-icon {
1235
1247
  display: none;
1236
1248
  }
@@ -1445,7 +1457,7 @@
1445
1457
  pointer-events: auto;
1446
1458
  align-items: center;
1447
1459
  gap: calc(var(--media-spacing) * 2);
1448
- display: none;
1460
+ display: flex;
1449
1461
  position: absolute;
1450
1462
  top: 50%;
1451
1463
  left: 50%;
@@ -1479,25 +1491,47 @@
1479
1491
  }
1480
1492
  }
1481
1493
 
1482
- @container media-root (width >= 22.5rem) {
1483
- :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center {
1484
- display: flex;
1485
- }
1486
- }
1487
-
1488
1494
  :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-button {
1489
- background-color: var(--media-background) !important;
1495
+ background-color: var(--media-popover) !important;
1490
1496
  margin: 0 !important;
1491
1497
  }
1492
1498
 
1499
+ @supports (color: color-mix(in lab, red, red)) {
1500
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-button {
1501
+ background-color: color-mix(in oklab, var(--media-popover) 40%, transparent) !important;
1502
+ }
1503
+ }
1504
+
1493
1505
  @media (hover: hover) {
1494
1506
  :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-button:hover {
1495
- background-color: var(--media-button-highlight) !important;
1507
+ background-color: var(--media-popover) !important;
1508
+ }
1509
+
1510
+ @supports (color: color-mix(in lab, red, red)) {
1511
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-button:hover {
1512
+ background-color: color-mix(in oklab, var(--media-popover) 60%, transparent) !important;
1513
+ }
1514
+ }
1515
+ }
1516
+
1517
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-button:focus-visible {
1518
+ background-color: var(--media-popover) !important;
1519
+ }
1520
+
1521
+ @supports (color: color-mix(in lab, red, red)) {
1522
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-button:focus-visible {
1523
+ background-color: color-mix(in oklab, var(--media-popover) 60%, transparent) !important;
1496
1524
  }
1497
1525
  }
1498
1526
 
1499
- :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-button:focus-visible, :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-button[aria-expanded="true"] {
1500
- background-color: var(--media-button-highlight) !important;
1527
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-button[aria-expanded="true"] {
1528
+ background-color: var(--media-popover) !important;
1529
+ }
1530
+
1531
+ @supports (color: color-mix(in lab, red, red)) {
1532
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-button[aria-expanded="true"] {
1533
+ background-color: color-mix(in oklab, var(--media-popover) 60%, transparent) !important;
1534
+ }
1501
1535
  }
1502
1536
 
1503
1537
  @media (forced-colors: active) {
@@ -1537,11 +1571,25 @@
1537
1571
  height: calc(var(--media-spacing) * 14.5) !important;
1538
1572
  }
1539
1573
 
1574
+ @container media-root (width < 22.5rem) {
1575
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-play {
1576
+ width: calc(var(--media-spacing) * 11) !important;
1577
+ height: calc(var(--media-spacing) * 11) !important;
1578
+ }
1579
+ }
1580
+
1540
1581
  :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-play-icon {
1541
1582
  width: calc(var(--media-spacing) * 7) !important;
1542
1583
  height: calc(var(--media-spacing) * 7) !important;
1543
1584
  }
1544
1585
 
1586
+ @container media-root (width < 22.5rem) {
1587
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-play-icon {
1588
+ width: calc(var(--media-spacing) * 5.5) !important;
1589
+ height: calc(var(--media-spacing) * 5.5) !important;
1590
+ }
1591
+ }
1592
+
1545
1593
  :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-content {
1546
1594
  pointer-events: none;
1547
1595
  z-index: 30;
@@ -1586,6 +1634,10 @@
1586
1634
  top: 0;
1587
1635
  }
1588
1636
 
1637
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-top:not([data-started]) {
1638
+ visibility: var(--media-controls-before-start, hidden);
1639
+ }
1640
+
1589
1641
  :where(:where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-content):not([data-visible]) .video-controls-top {
1590
1642
  pointer-events: none;
1591
1643
  opacity: 0;
@@ -1613,6 +1665,10 @@
1613
1665
  }
1614
1666
  }
1615
1667
 
1668
+ :where(:where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-content):not([data-started]) .video-controls-video-bottom {
1669
+ visibility: var(--media-controls-before-start, hidden);
1670
+ }
1671
+
1616
1672
  @media (forced-colors: active) {
1617
1673
  :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-video-bottom {
1618
1674
  inset-inline: 0;
@@ -1796,6 +1852,12 @@
1796
1852
  }
1797
1853
  }
1798
1854
 
1855
+ @container media-root (width < 15rem) {
1856
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .media-title {
1857
+ display: none;
1858
+ }
1859
+ }
1860
+
1799
1861
  :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-backdrop {
1800
1862
  pointer-events: none;
1801
1863
  background-image: linear-gradient(to top, #00000080, #0000 40% 60%, #0006);
@@ -1803,6 +1865,10 @@
1803
1865
  inset: 0;
1804
1866
  }
1805
1867
 
1868
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-backdrop:not([data-started]) {
1869
+ visibility: var(--media-controls-before-start, hidden);
1870
+ }
1871
+
1806
1872
  :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-backdrop:not([data-visible]) {
1807
1873
  display: none;
1808
1874
  }
@@ -1819,12 +1885,22 @@
1819
1885
  height: calc(var(--media-spacing) * 8) !important;
1820
1886
  }
1821
1887
 
1888
+ :where(:where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-content):not([data-started]) .video-controls-center-seek {
1889
+ display: none !important;
1890
+ }
1891
+
1822
1892
  @media (pointer: fine) {
1823
1893
  :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-seek {
1824
1894
  display: grid;
1825
1895
  }
1826
1896
  }
1827
1897
 
1898
+ @container media-root (width < 22.5rem) {
1899
+ :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-seek {
1900
+ display: none !important;
1901
+ }
1902
+ }
1903
+
1828
1904
  :where(.media-skin[data-theme="scaffold"][data-preset="video"]) .video-controls-center-seek-icon {
1829
1905
  width: calc(var(--media-spacing) * 4.5);
1830
1906
  height: calc(var(--media-spacing) * 4.5);
@@ -1874,29 +1950,29 @@
1874
1950
 
1875
1951
  @layer base.theme {
1876
1952
  .media-skin {
1877
- --media-background: oklch(0% 0 0);
1878
- --media-foreground: oklch(100% 0 0);
1879
- --media-controls: oklch(0% 0 0 / .35);
1953
+ --media-background: #000;
1954
+ --media-foreground: #fff;
1955
+ --media-controls: #00000059;
1880
1956
  --media-controls-foreground: var(--media-foreground);
1881
- --media-popover: oklch(100% 0 0 / .1);
1957
+ --media-popover: #ffffff1a;
1882
1958
  --media-popover-foreground: var(--media-foreground);
1883
1959
  --media-primary: var(--media-accent-color, var(--media-default-accent-color));
1884
1960
  --media-primary-foreground: var(--media-accent-text-color, var(--media-default-accent-text-color));
1885
- --media-accent: var(--media-accent-color, color-mix(in oklab, var(--media-default-accent-color) 10%, transparent));
1961
+ --media-accent: var(--media-accent-color, #ffffff1a);
1886
1962
  --media-accent-foreground: var(--media-accent-text-color, currentColor);
1887
- --media-muted: oklch(100% 0 0 / .15);
1888
- --media-muted-foreground: color-mix(in oklab, var(--media-foreground) 65%, transparent);
1889
- --media-border: oklch(0% 0 0 / .1);
1890
- --media-ring: oklch(100% 0 0);
1891
- --media-backdrop: oklch(0% 0 0);
1892
- --media-live-color: oklch(65% .22 27);
1893
- --media-shadow-surface: 0 1px 3px 0 oklch(0% 0 0 / .15), 0 1px 2px -1px oklch(0% 0 0 / .15);
1963
+ --media-muted: #ffffff26;
1964
+ --media-muted-foreground: #ffffffa6;
1965
+ --media-border: #0000001a;
1966
+ --media-ring: #fff;
1967
+ --media-backdrop: #000;
1968
+ --media-live-color: #f9423d;
1969
+ --media-shadow-surface: 0 1px 3px 0 #00000026, 0 1px 2px -1px #00000026;
1894
1970
  --media-shadow-surface-inset: inset 0 1px 0 0 #ffffff1a, inset 0 0 0 1px #ffffff0d;
1895
1971
  --media-shadow-thumb: 0 0 0 1px #0000001a, 0 1px 3px 0 #00000059, 0 1px 2px -1px #00000059;
1896
1972
  --media-shadow-tooltip: 0 0 0 1px var(--media-border), var(--media-shadow-surface);
1897
- --media-shadow-separator: 0 1px 0 0 oklch(100% 0 0 / .075);
1973
+ --media-shadow-separator: 0 1px 0 0 #ffffff13;
1898
1974
  --media-shadow-current-color: oklch(from currentColor 0 0 0 / clamp(0, calc((l - .5) * .5), .15));
1899
- --media-shadow-subtle-current-color: color-mix(in oklab, var(--media-shadow-current-color) 40%, transparent);
1975
+ --media-shadow-subtle-current-color: transparent;
1900
1976
  --media-text-shadow-dialog: 0 1px 0 #00000040;
1901
1977
  --media-backdrop-filter-surface: blur(16px) saturate(125%);
1902
1978
  --media-backdrop-filter-indicator: blur(8px);
@@ -1905,8 +1981,8 @@
1905
1981
  --media-control-radius: 99px;
1906
1982
  --media-control-size: calc(var(--media-spacing) * 9);
1907
1983
  --media-controls-radius: var(--media-control-radius);
1908
- --media-default-accent-color: oklch(100% 0 0);
1909
- --media-default-accent-text-color: oklch(0% 0 0);
1984
+ --media-default-accent-color: #fff;
1985
+ --media-default-accent-text-color: #000;
1910
1986
  --media-duration-instant: 50ms;
1911
1987
  --media-duration-fast: .1s;
1912
1988
  --media-duration: .15s;
@@ -1943,16 +2019,31 @@
1943
2019
  --media-slider-preview-label-offset: calc(var(--media-spacing) * 10.5);
1944
2020
  --media-video-border-radius: var(--media-border-radius, 28px);
1945
2021
  --media-scale: 1;
1946
- --media-scrollbar-thumb-color: color-mix(in oklab, currentColor 30%, transparent);
2022
+ --media-scrollbar-thumb-color: #80808080;
1947
2023
  --media-spacing: calc(var(--media-scale-unit, 16px) * var(--media-scale) / 4);
1948
2024
  scrollbar-color: var(--media-scrollbar-thumb-color) transparent;
1949
2025
  scrollbar-width: thin;
1950
2026
  }
1951
2027
 
2028
+ @supports (color: color-mix(in oklab, red, red)) {
2029
+ .media-skin {
2030
+ --media-accent: var(--media-accent-color, color-mix(in oklab, var(--media-default-accent-color) 10%, transparent));
2031
+ --media-muted-foreground: color-mix(in oklab, var(--media-foreground) 65%, transparent);
2032
+ --media-shadow-subtle-current-color: color-mix(in oklab, var(--media-shadow-current-color) 40%, transparent);
2033
+ --media-scrollbar-thumb-color: color-mix(in oklab, currentColor 30%, transparent);
2034
+ }
2035
+ }
2036
+
2037
+ @supports (color: oklch(0 0 0)) {
2038
+ .media-skin {
2039
+ --media-live-color: oklch(65% .22 27);
2040
+ }
2041
+ }
2042
+
1952
2043
  @supports (color: contrast-color(red)) {
1953
2044
  .media-skin {
1954
2045
  --media-primary-foreground: var(--media-accent-text-color, contrast-color(var(--media-primary)));
1955
- --media-accent-foreground: var(--media-accent-text-color, contrast-color(var(--media-accent-color, var(--media-internal-accent-text-fallback, oklch(0% 0 0)))));
2046
+ --media-accent-foreground: var(--media-accent-text-color, contrast-color(var(--media-accent-color, var(--media-internal-accent-text-fallback, #000))));
1956
2047
  }
1957
2048
  }
1958
2049
 
@@ -2002,24 +2093,48 @@
2002
2093
  --media-frame-border: var(--media-border-color, #0000001a);
2003
2094
  --media-controls-gradient-height: max(40%, calc(var(--media-spacing) * 40));
2004
2095
  --media-controls-bottom-gradient-height: max(50%, calc(var(--media-spacing) * 60));
2005
- --media-controls-gradient: linear-gradient(to top,
2006
- color-mix(in oklab, var(--media-backdrop) 60%, transparent),
2007
- color-mix(in oklab, var(--media-backdrop) 50.7%, transparent) 25%,
2008
- color-mix(in oklab, var(--media-backdrop) 30%, transparent) 50%,
2009
- color-mix(in oklab, var(--media-backdrop) 9.3%, transparent) 75%,
2010
- transparent);
2011
- --media-controls-top-gradient: linear-gradient(to bottom,
2012
- color-mix(in oklab, var(--media-backdrop) 55%, transparent),
2013
- color-mix(in oklab, var(--media-backdrop) 46.48%, transparent) 25%,
2014
- color-mix(in oklab, var(--media-backdrop) 27.5%, transparent) 50%,
2015
- color-mix(in oklab, var(--media-backdrop) 8.53%, transparent) 75%,
2016
- transparent);
2017
2096
  --media-caption-controls-y: calc(var(--media-spacing) * -16);
2018
2097
  --media-slider-preview-offset: calc(var(--media-spacing) * 9);
2019
- --media-thumbnail-gradient: linear-gradient(to top,
2020
- color-mix(in oklab, var(--media-backdrop) 50%, transparent),
2021
- color-mix(in oklab, var(--media-backdrop) 10%, transparent),
2022
- transparent);
2098
+ }
2099
+
2100
+ @supports (color: color-mix(in oklab, red, red)) {
2101
+ .media-skin:is([data-preset="video"], [data-preset="live-video"]) {
2102
+ --media-controls-gradient: linear-gradient(to top,
2103
+ color-mix(in oklab, var(--media-backdrop) 60%, transparent),
2104
+ color-mix(in oklab, var(--media-backdrop) 50.7%, transparent) 25%,
2105
+ color-mix(in oklab, var(--media-backdrop) 30%, transparent) 50%,
2106
+ color-mix(in oklab, var(--media-backdrop) 9.3%, transparent) 75%,
2107
+ transparent);
2108
+ --media-controls-top-gradient: linear-gradient(to bottom,
2109
+ color-mix(in oklab, var(--media-backdrop) 55%, transparent),
2110
+ color-mix(in oklab, var(--media-backdrop) 46.48%, transparent) 25%,
2111
+ color-mix(in oklab, var(--media-backdrop) 27.5%, transparent) 50%,
2112
+ color-mix(in oklab, var(--media-backdrop) 8.53%, transparent) 75%,
2113
+ transparent);
2114
+ --media-thumbnail-gradient: linear-gradient(to top,
2115
+ color-mix(in oklab, var(--media-backdrop) 50%, transparent),
2116
+ color-mix(in oklab, var(--media-backdrop) 10%, transparent),
2117
+ transparent);
2118
+ }
2119
+
2120
+ .media-skin:is([data-preset="video"], [data-preset="live-video"])[data-theme="neutral"] {
2121
+ --media-controls-gradient: linear-gradient(to top,
2122
+ color-mix(in oklab, var(--media-backdrop) 50%, transparent),
2123
+ color-mix(in oklab, var(--media-backdrop) 42.2%, transparent) 25%,
2124
+ color-mix(in oklab, var(--media-backdrop) 25%, transparent) 50%,
2125
+ color-mix(in oklab, var(--media-backdrop) 7.8%, transparent) 75%,
2126
+ transparent);
2127
+ --media-controls-top-gradient: linear-gradient(to bottom,
2128
+ color-mix(in oklab, var(--media-backdrop) 50%, transparent),
2129
+ color-mix(in oklab, var(--media-backdrop) 42.2%, transparent) 25%,
2130
+ color-mix(in oklab, var(--media-backdrop) 25%, transparent) 50%,
2131
+ color-mix(in oklab, var(--media-backdrop) 7.8%, transparent) 75%,
2132
+ transparent);
2133
+ --media-indicator-gradient: linear-gradient(to bottom,
2134
+ color-mix(in oklab, var(--media-backdrop) 35%, transparent),
2135
+ color-mix(in oklab, var(--media-backdrop) 20%, transparent) calc(var(--media-spacing) * 12),
2136
+ transparent);
2137
+ }
2023
2138
  }
2024
2139
 
2025
2140
  @supports (color: oklch(from red l c h)) and (background-image: linear-gradient(in oklab, red, red)) {
@@ -2051,23 +2166,7 @@
2051
2166
  .media-skin:is([data-preset="video"], [data-preset="live-video"])[data-theme="neutral"] {
2052
2167
  --media-frame-border: var(--media-border-color, #00000026);
2053
2168
  --media-controls-gradient-height: 40%;
2054
- --media-controls-bottom-gradient-height: 40%;
2055
- --media-controls-gradient: linear-gradient(to top,
2056
- color-mix(in oklab, var(--media-backdrop) 50%, transparent),
2057
- color-mix(in oklab, var(--media-backdrop) 42.2%, transparent) 25%,
2058
- color-mix(in oklab, var(--media-backdrop) 25%, transparent) 50%,
2059
- color-mix(in oklab, var(--media-backdrop) 7.8%, transparent) 75%,
2060
- transparent);
2061
- --media-controls-top-gradient: linear-gradient(to bottom,
2062
- color-mix(in oklab, var(--media-backdrop) 50%, transparent),
2063
- color-mix(in oklab, var(--media-backdrop) 42.2%, transparent) 25%,
2064
- color-mix(in oklab, var(--media-backdrop) 25%, transparent) 50%,
2065
- color-mix(in oklab, var(--media-backdrop) 7.8%, transparent) 75%,
2066
- transparent);
2067
- --media-indicator-gradient: linear-gradient(to bottom,
2068
- color-mix(in oklab, var(--media-backdrop) 35%, transparent),
2069
- color-mix(in oklab, var(--media-backdrop) 20%, transparent) calc(var(--media-spacing) * 12),
2070
- transparent);
2169
+ --media-controls-bottom-gradient-height: max(40%, calc(var(--media-spacing) * 44));
2071
2170
  --media-caption-controls-y: calc(var(--media-spacing) * -14);
2072
2171
  --media-slider-preview-offset: calc(var(--media-spacing) * 11);
2073
2172
  }
@@ -2225,7 +2324,7 @@
2225
2324
  @media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
2226
2325
  .media-skin {
2227
2326
  --media-popover: var(--media-background);
2228
- --media-scrollbar-thumb-color: color-mix(in oklab, currentColor 80%, transparent);
2327
+ --media-scrollbar-thumb-color: currentColor;
2229
2328
  --media-backdrop-filter-surface: none;
2230
2329
  --media-backdrop-filter-indicator: none;
2231
2330
  --media-backdrop-filter-dialog: none;
@@ -2233,6 +2332,12 @@
2233
2332
  scrollbar-width: auto;
2234
2333
  }
2235
2334
 
2335
+ @supports (color: color-mix(in oklab, red, red)) {
2336
+ .media-skin {
2337
+ --media-scrollbar-thumb-color: color-mix(in oklab, currentColor 80%, transparent);
2338
+ }
2339
+ }
2340
+
2236
2341
  @supports (color: oklch(from currentColor l c h)) {
2237
2342
  .media-skin {
2238
2343
  --media-scrollbar-thumb-color: oklch(from currentColor l c h / .8);
@@ -222,7 +222,7 @@ const template = createTemplate(`<media-container class="media-skin media-contai
222
222
  <media-tooltip-shortcut class="media-tooltip-shortcut">
223
223
  </media-tooltip-shortcut>
224
224
  </media-tooltip>
225
- <button commandfor="vjs-dexOLs_f-h-popup" class="media-button" id="vjs-HNl1fwKe-0-11-trigger">
225
+ <button commandfor="vjs-dexOLs_f-h-popup" class="media-button media-settings-button" id="vjs-HNl1fwKe-0-11-trigger">
226
226
  <media-icon family="scaffold" name="gear" class="media-button-icon">
227
227
  </media-icon>
228
228
  <media-text class="media-settings-button-label" token="menu.settings">Settings</media-text>
@@ -358,6 +358,8 @@ const template = createTemplate(`<media-container class="media-skin media-contai
358
358
  <media-menu-radio-item class="media-menu-radio-item">
359
359
  <span data-part="label">
360
360
  </span>
361
+ <span data-part="badge" class="media-menu-badge">
362
+ </span>
361
363
  <media-menu-item-indicator force-mount class="media-menu-indicator">
362
364
  <media-icon family="scaffold" name="check" class="media-menu-radio-icon">
363
365
  </media-icon>
@@ -1,46 +1,24 @@
1
- import { MediaAttachMixin } from "../../store/media-attach-mixin.js";
2
- import { getTemplateHTML } from "./template.js";
3
- import { namedNodeMapToObject } from "@videojs/utils/dom";
1
+ import { BackgroundVideoBase } from "./base.js";
4
2
  //#region src/media/background-video/adapter.ts
5
- const HTMLElementBase = globalThis.HTMLElement ?? class {};
6
- var BackgroundVideo = class extends MediaAttachMixin(HTMLElementBase) {
7
- static {
8
- this.shadowRootOptions = { mode: "open" };
9
- }
10
- static {
11
- this.getTemplateHTML = getTemplateHTML;
12
- }
13
- static get observedAttributes() {
14
- return ["src"];
15
- }
3
+ var BackgroundVideo = class extends BackgroundVideoBase {
16
4
  constructor() {
17
5
  super();
18
- if (!this.shadowRoot) {
19
- this.attachShadow(this.constructor.shadowRootOptions);
20
- const attrs = {
21
- ...namedNodeMapToObject(this.attributes),
22
- ...!this.hasAttribute("nomuted") && { muted: "" },
23
- ...!this.hasAttribute("noloop") && { loop: "" },
24
- ...!this.hasAttribute("noautoplay") && { autoplay: "" },
25
- playsinline: "",
26
- disableremoteplayback: "",
27
- disablepictureinpicture: ""
28
- };
29
- this.shadowRoot.innerHTML = getTemplateHTML(attrs);
30
- }
31
- this.target.muted = !this.hasAttribute("nomuted");
6
+ this.target?.addEventListener("error", () => this.dispatchEvent(new Event("error")));
32
7
  }
33
8
  getMediaTarget() {
34
9
  return this.target;
35
10
  }
36
- attributeChangedCallback(attrName, oldValue, newValue) {
37
- if (attrName === "src" && oldValue !== newValue) this.target.src = newValue ?? "";
11
+ /** URL of a video the browser can play directly. Assigning a new one restarts playback. */
12
+ get src() {
13
+ return this.target?.src ?? "";
14
+ }
15
+ set src(value) {
16
+ const target = this.target;
17
+ if (target) target.src = value;
38
18
  }
39
- get target() {
40
- const slotted = this.querySelector(":scope > [slot=media]");
41
- if (slotted instanceof HTMLVideoElement) return slotted;
42
- const video = this.querySelector("video") ?? this.shadowRoot?.querySelector("video");
43
- return video instanceof HTMLVideoElement ? video : null;
19
+ /** The inner video's `MediaError`, or `null`. */
20
+ get error() {
21
+ return this.target?.error ?? null;
44
22
  }
45
23
  };
46
24
  //#endregion
@@ -0,0 +1,95 @@
1
+ import { MediaAttachMixin } from "../../store/media-attach-mixin.js";
2
+ import { getTemplateHTML, getTemplateVideo } from "./template.js";
3
+ import { namedNodeMapToObject } from "@videojs/utils/dom";
4
+ import { pick } from "@videojs/utils/object";
5
+ //#region src/media/background-video/base.ts
6
+ const HTMLElementBase = globalThis.HTMLElement ?? class {};
7
+ const MediaAttachBase = MediaAttachMixin(HTMLElementBase);
8
+ const PLAYBACK_DEFAULTS = [
9
+ "muted",
10
+ "loop",
11
+ "autoplay"
12
+ ];
13
+ /**
14
+ * The shadow setup, `src` wiring, and `target` that `<background-video>` and `<hls-background-video>` share. Each
15
+ * subclass supplies its own `src` and declares which playback defaults authors may opt out of.
16
+ *
17
+ * @internal
18
+ */
19
+ var BackgroundVideoBase = class extends MediaAttachBase {
20
+ static {
21
+ this.shadowRootOptions = { mode: "open" };
22
+ }
23
+ static {
24
+ this.getTemplateHTML = getTemplateHTML;
25
+ }
26
+ static {
27
+ this.optOuts = [
28
+ "muted",
29
+ "loop",
30
+ "autoplay"
31
+ ];
32
+ }
33
+ static {
34
+ this.passthroughAttributes = [
35
+ "controls",
36
+ "controlslist",
37
+ "crossorigin",
38
+ "preload"
39
+ ];
40
+ }
41
+ static get observedAttributes() {
42
+ return [
43
+ "src",
44
+ ...this.optOuts,
45
+ ...this.optOuts.map((name) => `no${name}`),
46
+ ...this.passthroughAttributes
47
+ ];
48
+ }
49
+ constructor() {
50
+ super();
51
+ const ctor = this.constructor;
52
+ if (!this.shadowRoot) {
53
+ const attrs = {
54
+ ...pick(namedNodeMapToObject(this.attributes), ctor.passthroughAttributes),
55
+ playsinline: "",
56
+ disableremoteplayback: "",
57
+ disablepictureinpicture: ""
58
+ };
59
+ for (const name of PLAYBACK_DEFAULTS) if (this.#isDefaultOn(name)) attrs[name] = "";
60
+ this.attachShadow(ctor.shadowRootOptions);
61
+ this.shadowRoot.innerHTML = ctor.getTemplateHTML(attrs);
62
+ }
63
+ this.syncPlaybackDefaults();
64
+ }
65
+ /**
66
+ * Writes muted, loop, and autoplay onto the inner video as properties. The template's attributes only cover markup
67
+ * parsed with its attributes in place; an element created by script gets its `no*` attributes afterwards, and neither
68
+ * Chrome nor Firefox honor a `muted` attribute set after `document.createElement`.
69
+ */
70
+ syncPlaybackDefaults() {
71
+ const target = this.target;
72
+ if (!target) return;
73
+ for (const name of PLAYBACK_DEFAULTS) target[name] = this.#isDefaultOn(name);
74
+ }
75
+ /** On unless its `no*` attribute is set and allowed; an explicit attribute such as `muted` wins over its opt-out. */
76
+ #isDefaultOn(name) {
77
+ const { optOuts } = this.constructor;
78
+ return this.hasAttribute(name) || !optOuts.includes(name) || !this.hasAttribute(`no${name}`);
79
+ }
80
+ attributeChangedCallback(name, oldValue, newValue) {
81
+ if (oldValue === newValue) return;
82
+ const { passthroughAttributes } = this.constructor;
83
+ if (name === "src") this.src = newValue ?? "";
84
+ else if (passthroughAttributes.includes(name)) {
85
+ if (newValue === null) this.target?.removeAttribute(name);
86
+ else this.target?.setAttribute(name, newValue);
87
+ } else this.syncPlaybackDefaults();
88
+ }
89
+ /** The inner `<video>` in the shadow root: what plays, and what `play()` / `pause()` belong on. */
90
+ get target() {
91
+ return getTemplateVideo(this.shadowRoot);
92
+ }
93
+ };
94
+ //#endregion
95
+ export { BackgroundVideoBase };
@@ -1,32 +1,25 @@
1
1
  import { serializeAttributes } from "@videojs/utils/dom";
2
- import { pick } from "@videojs/utils/object";
3
2
  //#region src/media/background-video/template.ts
4
3
  /**
5
- * Attributes forwarded to the inner `<video>`. `src` is deliberately not one of them: each element decides what to do
6
- * with it, whether that is assigning the inner video or handing it to a playback engine, and serializing it into the
7
- * template would start a native load either way.
8
- */
9
- const VideoAttributes = [
10
- "autoplay",
11
- "controls",
12
- "controlslist",
13
- "crossorigin",
14
- "disablepictureinpicture",
15
- "disableremoteplayback",
16
- "loop",
17
- "muted",
18
- "playsinline",
19
- "preload"
20
- ];
21
- /**
22
4
  * The shadow template both background-video elements render: a `<slot>` for a placeholder image, and a `<video>`
23
5
  * stretched over the host.
24
6
  *
7
+ * `attrs` go onto the `<video>` as given; each element decides which of its own attributes to forward. `src` is never
8
+ * among them, since serializing it would start a native load before an engine could take it.
9
+ *
25
10
  * Shared so the two can't drift in presentation. `object-fit` and `object-position` are the only styling hooks — a
26
11
  * background video has no controls to theme.
27
12
  */
28
13
  function getTemplateHTML(attrs) {
29
- return `<style> :host { position: relative; } video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: var(--media-object-fit, inherit); object-position: var(--media-object-position, 50% 50%); } </style><slot></slot><video${serializeAttributes(pick(attrs, [...VideoAttributes]))}></video>`;
14
+ return `<style> :host { position: relative; } video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: var(--media-object-fit, inherit); object-position: var(--media-object-position, 50% 50%); } </style><slot></slot><video${serializeAttributes(attrs)}></video>`;
15
+ }
16
+ /**
17
+ * The `<video>` from `getTemplateHTML`. Always the shadow one: the template has no slot that would render a light-DOM
18
+ * `<video>`, so anything found there is either the placeholder or not displayed at all.
19
+ */
20
+ function getTemplateVideo(shadowRoot) {
21
+ const video = shadowRoot?.querySelector("video");
22
+ return video instanceof HTMLVideoElement ? video : null;
30
23
  }
31
24
  //#endregion
32
- export { VideoAttributes, getTemplateHTML };
25
+ export { getTemplateHTML, getTemplateVideo };