@videojs/html 10.0.0-beta.1 → 10.0.0-beta.10

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 (410) hide show
  1. package/cdn/audio-minimal.dev.d.ts +1 -0
  2. package/cdn/audio-minimal.dev.js +112 -0
  3. package/cdn/audio-minimal.dev.js.map +1 -0
  4. package/cdn/audio-minimal.js +2 -0
  5. package/cdn/audio-minimal.js.map +1 -0
  6. package/cdn/audio.dev.d.ts +1 -0
  7. package/cdn/audio.dev.js +103 -0
  8. package/cdn/audio.dev.js.map +1 -0
  9. package/cdn/audio.js +2 -0
  10. package/cdn/audio.js.map +1 -0
  11. package/cdn/background.dev.d.ts +1 -0
  12. package/cdn/background.dev.js +159 -0
  13. package/cdn/background.dev.js.map +1 -0
  14. package/cdn/background.js +2 -0
  15. package/cdn/background.js.map +1 -0
  16. package/cdn/context-C_e06fGU.js +13 -0
  17. package/cdn/context-C_e06fGU.js.map +1 -0
  18. package/cdn/context-DTY0nOpS.js +98 -0
  19. package/cdn/context-DTY0nOpS.js.map +1 -0
  20. package/cdn/create-player-BTIU8EwT.js +7 -0
  21. package/cdn/create-player-BTIU8EwT.js.map +1 -0
  22. package/cdn/create-player-Cwxvswyv.js +3218 -0
  23. package/cdn/create-player-Cwxvswyv.js.map +1 -0
  24. package/cdn/default-GgKND7a8.js +2 -0
  25. package/cdn/default-GgKND7a8.js.map +1 -0
  26. package/cdn/default-cLso8BHO.js +28 -0
  27. package/cdn/default-cLso8BHO.js.map +1 -0
  28. package/cdn/listen-BXAYCbZA.js +9 -0
  29. package/cdn/listen-BXAYCbZA.js.map +1 -0
  30. package/cdn/listen-DX5vU4s4.js +2 -0
  31. package/cdn/listen-DX5vU4s4.js.map +1 -0
  32. package/cdn/media/dash-video.dev.d.ts +1 -0
  33. package/cdn/media/dash-video.dev.js +39165 -0
  34. package/cdn/media/dash-video.dev.js.map +1 -0
  35. package/cdn/media/dash-video.js +21 -0
  36. package/cdn/media/dash-video.js.map +1 -0
  37. package/cdn/media/hls-video.dev.d.ts +1 -0
  38. package/cdn/media/hls-video.dev.js +28357 -0
  39. package/cdn/media/hls-video.dev.js.map +1 -0
  40. package/cdn/media/hls-video.js +41 -0
  41. package/cdn/media/hls-video.js.map +1 -0
  42. package/cdn/media/simple-hls-video.dev.d.ts +1 -0
  43. package/cdn/media/simple-hls-video.dev.js +3465 -0
  44. package/cdn/media/simple-hls-video.dev.js.map +1 -0
  45. package/cdn/media/simple-hls-video.js +2 -0
  46. package/cdn/media/simple-hls-video.js.map +1 -0
  47. package/cdn/media-attach-mixin-ChyNp2eK.js +44 -0
  48. package/cdn/media-attach-mixin-ChyNp2eK.js.map +1 -0
  49. package/cdn/media-attach-mixin-tFNcHnvo.js +2 -0
  50. package/cdn/media-attach-mixin-tFNcHnvo.js.map +1 -0
  51. package/cdn/minimal-BJfleQcQ.js +2 -0
  52. package/cdn/minimal-BJfleQcQ.js.map +1 -0
  53. package/cdn/minimal-DBMdC_0I.js +28 -0
  54. package/cdn/minimal-DBMdC_0I.js.map +1 -0
  55. package/cdn/player-BHhLXO-R.js +2 -0
  56. package/cdn/player-BHhLXO-R.js.map +1 -0
  57. package/cdn/player-DEfj0RU6.js +15 -0
  58. package/cdn/player-DEfj0RU6.js.map +1 -0
  59. package/cdn/poster-Dd0F1rRd.js +195 -0
  60. package/cdn/poster-Dd0F1rRd.js.map +1 -0
  61. package/cdn/poster-DwQ3RAch.js +2 -0
  62. package/cdn/poster-DwQ3RAch.js.map +1 -0
  63. package/cdn/predicate-BG-dj_kF.js +26 -0
  64. package/cdn/predicate-BG-dj_kF.js.map +1 -0
  65. package/cdn/predicate-Y9jDHLpX.js +2 -0
  66. package/cdn/predicate-Y9jDHLpX.js.map +1 -0
  67. package/cdn/proxy-2oO2ph3m.js +47 -0
  68. package/cdn/proxy-2oO2ph3m.js.map +1 -0
  69. package/cdn/proxy-6KS6wy69.js +2 -0
  70. package/cdn/proxy-6KS6wy69.js.map +1 -0
  71. package/cdn/proxy-XzDf9gyk.js +66 -0
  72. package/cdn/proxy-XzDf9gyk.js.map +1 -0
  73. package/cdn/proxy-dR7IDk37.js +349 -0
  74. package/cdn/proxy-dR7IDk37.js.map +1 -0
  75. package/cdn/safe-define-B8lHgj_K.js +9 -0
  76. package/cdn/safe-define-B8lHgj_K.js.map +1 -0
  77. package/cdn/safe-define-GrHW3P9e.js +2 -0
  78. package/cdn/safe-define-GrHW3P9e.js.map +1 -0
  79. package/cdn/video-minimal.dev.d.ts +1 -0
  80. package/cdn/video-minimal.dev.js +155 -0
  81. package/cdn/video-minimal.dev.js.map +1 -0
  82. package/cdn/video-minimal.js +2 -0
  83. package/cdn/video-minimal.js.map +1 -0
  84. package/cdn/video.dev.d.ts +1 -0
  85. package/cdn/video.dev.js +170 -0
  86. package/cdn/video.dev.js.map +1 -0
  87. package/cdn/video.js +2 -0
  88. package/cdn/video.js.map +1 -0
  89. package/cdn/volume-slider-DgJ0rAfC.js +2459 -0
  90. package/cdn/volume-slider-DgJ0rAfC.js.map +1 -0
  91. package/cdn/volume-slider-Pd0AMTCH.js +8 -0
  92. package/cdn/volume-slider-Pd0AMTCH.js.map +1 -0
  93. package/dist/default/_virtual/inline-css_src/define/audio/minimal-skin.js +1 -1
  94. package/dist/default/_virtual/inline-css_src/define/audio/minimal-skin.js.map +1 -1
  95. package/dist/default/_virtual/inline-css_src/define/audio/skin.js +1 -1
  96. package/dist/default/_virtual/inline-css_src/define/audio/skin.js.map +1 -1
  97. package/dist/default/_virtual/inline-css_src/define/background/skin.js +6 -0
  98. package/dist/default/_virtual/inline-css_src/define/background/skin.js.map +1 -0
  99. package/dist/default/_virtual/inline-css_src/define/base.js +6 -0
  100. package/dist/default/_virtual/inline-css_src/define/base.js.map +1 -0
  101. package/dist/default/_virtual/inline-css_src/define/shared.js +6 -0
  102. package/dist/default/_virtual/inline-css_src/define/shared.js.map +1 -0
  103. package/dist/default/_virtual/inline-css_src/define/video/minimal-skin.js +1 -1
  104. package/dist/default/_virtual/inline-css_src/define/video/minimal-skin.js.map +1 -1
  105. package/dist/default/_virtual/inline-css_src/define/video/skin.js +1 -1
  106. package/dist/default/_virtual/inline-css_src/define/video/skin.js.map +1 -1
  107. package/dist/default/define/audio/minimal-skin.css +237 -157
  108. package/dist/default/define/audio/minimal-skin.js +2 -79
  109. package/dist/default/define/audio/minimal-skin.js.map +1 -1
  110. package/dist/default/define/audio/minimal-skin.tailwind.js +5 -82
  111. package/dist/default/define/audio/minimal-skin.tailwind.js.map +1 -1
  112. package/dist/default/define/audio/skin.css +234 -153
  113. package/dist/default/define/audio/skin.js +2 -70
  114. package/dist/default/define/audio/skin.js.map +1 -1
  115. package/dist/default/define/audio/skin.tailwind.js +6 -75
  116. package/dist/default/define/audio/skin.tailwind.js.map +1 -1
  117. package/dist/default/define/background/skin.css +1 -1
  118. package/dist/default/define/background/skin.js +11 -5
  119. package/dist/default/define/background/skin.js.map +1 -1
  120. package/dist/default/define/base.css +23 -0
  121. package/dist/default/define/media/dash-video.js +14 -0
  122. package/dist/default/define/media/dash-video.js.map +1 -0
  123. package/dist/default/define/shared.css +13 -0
  124. package/dist/default/define/skin-mixin.js +16 -33
  125. package/dist/default/define/skin-mixin.js.map +1 -1
  126. package/dist/default/define/video/minimal-skin.css +486 -301
  127. package/dist/default/define/video/minimal-skin.js +3 -121
  128. package/dist/default/define/video/minimal-skin.js.map +1 -1
  129. package/dist/default/define/video/minimal-skin.tailwind.js +8 -136
  130. package/dist/default/define/video/minimal-skin.tailwind.js.map +1 -1
  131. package/dist/default/define/video/skin.css +484 -289
  132. package/dist/default/define/video/skin.js +3 -116
  133. package/dist/default/define/video/skin.js.map +1 -1
  134. package/dist/default/define/video/skin.tailwind.js +8 -128
  135. package/dist/default/define/video/skin.tailwind.js.map +1 -1
  136. package/dist/default/icons/dist/render/default/index.js +2 -1
  137. package/dist/default/icons/dist/render/default/index.js.map +1 -1
  138. package/dist/default/icons/dist/render/minimal/index.js +2 -1
  139. package/dist/default/icons/dist/render/minimal/index.js.map +1 -1
  140. package/dist/default/index.js +3 -2
  141. package/dist/default/media/background-video/index.js +6 -19
  142. package/dist/default/media/background-video/index.js.map +1 -1
  143. package/dist/default/media/container-element.js +5 -2
  144. package/dist/default/media/container-element.js.map +1 -1
  145. package/dist/default/media/dash-video/index.js +26 -0
  146. package/dist/default/media/dash-video/index.js.map +1 -0
  147. package/dist/default/media/hls-video/index.js +2 -1
  148. package/dist/default/media/hls-video/index.js.map +1 -1
  149. package/dist/default/media/simple-hls-video/index.js +3 -1
  150. package/dist/default/media/simple-hls-video/index.js.map +1 -1
  151. package/dist/default/player/context.js +6 -2
  152. package/dist/default/player/context.js.map +1 -1
  153. package/dist/default/player/create-player.js +11 -3
  154. package/dist/default/player/create-player.js.map +1 -1
  155. package/dist/default/skins/dist/default/default/tailwind/audio.tailwind.js +10 -26
  156. package/dist/default/skins/dist/default/default/tailwind/audio.tailwind.js.map +1 -1
  157. package/dist/default/skins/dist/default/default/tailwind/components/button.js +4 -3
  158. package/dist/default/skins/dist/default/default/tailwind/components/button.js.map +1 -1
  159. package/dist/default/skins/dist/default/default/tailwind/components/controls.js +1 -1
  160. package/dist/default/skins/dist/default/default/tailwind/components/controls.js.map +1 -1
  161. package/dist/default/skins/dist/default/default/tailwind/components/error.js +3 -3
  162. package/dist/default/skins/dist/default/default/tailwind/components/error.js.map +1 -1
  163. package/dist/default/skins/dist/default/default/tailwind/components/overlay.js +1 -1
  164. package/dist/default/skins/dist/default/default/tailwind/components/overlay.js.map +1 -1
  165. package/dist/default/skins/dist/default/default/tailwind/components/popup.js +3 -3
  166. package/dist/default/skins/dist/default/default/tailwind/components/popup.js.map +1 -1
  167. package/dist/default/skins/dist/default/default/tailwind/components/poster.js +16 -0
  168. package/dist/default/skins/dist/default/default/tailwind/components/poster.js.map +1 -0
  169. package/dist/default/skins/dist/default/default/tailwind/components/preview.js +13 -0
  170. package/dist/default/skins/dist/default/default/tailwind/components/preview.js.map +1 -0
  171. package/dist/default/skins/dist/default/default/tailwind/components/root.js +1 -1
  172. package/dist/default/skins/dist/default/default/tailwind/components/root.js.map +1 -1
  173. package/dist/default/skins/dist/default/default/tailwind/components/seek.js +1 -1
  174. package/dist/default/skins/dist/default/default/tailwind/components/seek.js.map +1 -1
  175. package/dist/default/skins/dist/default/default/tailwind/components/slider.js +1 -1
  176. package/dist/default/skins/dist/default/default/tailwind/components/slider.js.map +1 -1
  177. package/dist/default/skins/dist/default/default/tailwind/components/surface.js +1 -1
  178. package/dist/default/skins/dist/default/default/tailwind/components/surface.js.map +1 -1
  179. package/dist/default/skins/dist/default/default/tailwind/video.tailwind.js +27 -16
  180. package/dist/default/skins/dist/default/default/tailwind/video.tailwind.js.map +1 -1
  181. package/dist/default/skins/dist/default/minimal/tailwind/audio.tailwind.js +11 -24
  182. package/dist/default/skins/dist/default/minimal/tailwind/audio.tailwind.js.map +1 -1
  183. package/dist/default/skins/dist/default/minimal/tailwind/components/button.js +4 -3
  184. package/dist/default/skins/dist/default/minimal/tailwind/components/button.js.map +1 -1
  185. package/dist/default/skins/dist/default/minimal/tailwind/components/controls.js +1 -1
  186. package/dist/default/skins/dist/default/minimal/tailwind/components/controls.js.map +1 -1
  187. package/dist/default/skins/dist/default/minimal/tailwind/components/error.js +3 -3
  188. package/dist/default/skins/dist/default/minimal/tailwind/components/error.js.map +1 -1
  189. package/dist/default/skins/dist/default/minimal/tailwind/components/overlay.js +1 -1
  190. package/dist/default/skins/dist/default/minimal/tailwind/components/overlay.js.map +1 -1
  191. package/dist/default/skins/dist/default/minimal/tailwind/components/playback-rate.js +6 -0
  192. package/dist/default/skins/dist/default/minimal/tailwind/components/playback-rate.js.map +1 -0
  193. package/dist/default/skins/dist/default/minimal/tailwind/components/popup.js +4 -3
  194. package/dist/default/skins/dist/default/minimal/tailwind/components/popup.js.map +1 -1
  195. package/dist/default/skins/dist/default/minimal/tailwind/components/poster.js +16 -0
  196. package/dist/default/skins/dist/default/minimal/tailwind/components/poster.js.map +1 -0
  197. package/dist/default/skins/dist/default/minimal/tailwind/components/preview.js +14 -0
  198. package/dist/default/skins/dist/default/minimal/tailwind/components/preview.js.map +1 -0
  199. package/dist/default/skins/dist/default/minimal/tailwind/components/root.js +1 -1
  200. package/dist/default/skins/dist/default/minimal/tailwind/components/root.js.map +1 -1
  201. package/dist/default/skins/dist/default/minimal/tailwind/components/seek.js +1 -1
  202. package/dist/default/skins/dist/default/minimal/tailwind/components/seek.js.map +1 -1
  203. package/dist/default/skins/dist/default/minimal/tailwind/components/slider.js +1 -1
  204. package/dist/default/skins/dist/default/minimal/tailwind/components/slider.js.map +1 -1
  205. package/dist/default/skins/dist/default/minimal/tailwind/components/time.js +1 -1
  206. package/dist/default/skins/dist/default/minimal/tailwind/components/time.js.map +1 -1
  207. package/dist/default/skins/dist/default/minimal/tailwind/video.tailwind.js +33 -16
  208. package/dist/default/skins/dist/default/minimal/tailwind/video.tailwind.js.map +1 -1
  209. package/dist/default/skins/dist/default/{default/tailwind/components → shared/tailwind}/icon-state.js +6 -1
  210. package/dist/default/skins/dist/default/shared/tailwind/icon-state.js.map +1 -0
  211. package/dist/{dev/skins/dist/default/default/tailwind/components → default/skins/dist/default/shared/tailwind}/tooltip-state.js +1 -1
  212. package/dist/default/skins/dist/default/shared/tailwind/tooltip-state.js.map +1 -0
  213. package/dist/default/store/container-mixin.js +16 -60
  214. package/dist/default/store/container-mixin.js.map +1 -1
  215. package/dist/default/store/media-attach-mixin.js +45 -0
  216. package/dist/default/store/media-attach-mixin.js.map +1 -0
  217. package/dist/default/store/provider-mixin.js +99 -9
  218. package/dist/default/store/provider-mixin.js.map +1 -1
  219. package/dist/default/ui/popover/popover-element.js +54 -3
  220. package/dist/default/ui/popover/popover-element.js.map +1 -1
  221. package/dist/default/ui/time-slider/time-slider-element.js +1 -1
  222. package/dist/default/ui/time-slider/time-slider-element.js.map +1 -1
  223. package/dist/default/ui/tooltip/tooltip-element.js +53 -3
  224. package/dist/default/ui/tooltip/tooltip-element.js.map +1 -1
  225. package/dist/default/ui/tooltip/tooltip-group-element.js +4 -1
  226. package/dist/default/ui/tooltip/tooltip-group-element.js.map +1 -1
  227. package/dist/default/ui/volume-slider/volume-slider-element.js +3 -3
  228. package/dist/default/ui/volume-slider/volume-slider-element.js.map +1 -1
  229. package/dist/dev/_virtual/inline-css_src/define/audio/minimal-skin.js +1 -1
  230. package/dist/dev/_virtual/inline-css_src/define/audio/minimal-skin.js.map +1 -1
  231. package/dist/dev/_virtual/inline-css_src/define/audio/skin.js +1 -1
  232. package/dist/dev/_virtual/inline-css_src/define/audio/skin.js.map +1 -1
  233. package/dist/dev/_virtual/inline-css_src/define/background/skin.js +6 -0
  234. package/dist/dev/_virtual/inline-css_src/define/background/skin.js.map +1 -0
  235. package/dist/dev/_virtual/inline-css_src/define/base.js +6 -0
  236. package/dist/dev/_virtual/inline-css_src/define/base.js.map +1 -0
  237. package/dist/dev/_virtual/inline-css_src/define/shared.js +6 -0
  238. package/dist/dev/_virtual/inline-css_src/define/shared.js.map +1 -0
  239. package/dist/dev/_virtual/inline-css_src/define/video/minimal-skin.js +1 -1
  240. package/dist/dev/_virtual/inline-css_src/define/video/minimal-skin.js.map +1 -1
  241. package/dist/dev/_virtual/inline-css_src/define/video/skin.js +1 -1
  242. package/dist/dev/_virtual/inline-css_src/define/video/skin.js.map +1 -1
  243. package/dist/dev/define/audio/minimal-skin.css +237 -157
  244. package/dist/dev/define/audio/minimal-skin.d.ts.map +1 -1
  245. package/dist/dev/define/audio/minimal-skin.js +69 -64
  246. package/dist/dev/define/audio/minimal-skin.js.map +1 -1
  247. package/dist/dev/define/audio/minimal-skin.tailwind.d.ts.map +1 -1
  248. package/dist/dev/define/audio/minimal-skin.tailwind.js +73 -66
  249. package/dist/dev/define/audio/minimal-skin.tailwind.js.map +1 -1
  250. package/dist/dev/define/audio/skin.css +234 -153
  251. package/dist/dev/define/audio/skin.d.ts.map +1 -1
  252. package/dist/dev/define/audio/skin.js +61 -56
  253. package/dist/dev/define/audio/skin.js.map +1 -1
  254. package/dist/dev/define/audio/skin.tailwind.d.ts.map +1 -1
  255. package/dist/dev/define/audio/skin.tailwind.js +67 -61
  256. package/dist/dev/define/audio/skin.tailwind.js.map +1 -1
  257. package/dist/dev/define/background/skin.css +1 -1
  258. package/dist/dev/define/background/skin.d.ts.map +1 -1
  259. package/dist/dev/define/background/skin.js +13 -1
  260. package/dist/dev/define/background/skin.js.map +1 -1
  261. package/dist/dev/define/base.css +23 -0
  262. package/dist/dev/define/media/dash-video.d.ts +14 -0
  263. package/dist/dev/define/media/dash-video.d.ts.map +1 -0
  264. package/dist/dev/define/media/dash-video.js +14 -0
  265. package/dist/dev/define/media/dash-video.js.map +1 -0
  266. package/dist/dev/define/shared.css +13 -0
  267. package/dist/dev/define/skin-mixin.d.ts +2 -2
  268. package/dist/dev/define/skin-mixin.d.ts.map +1 -1
  269. package/dist/dev/define/skin-mixin.js +16 -33
  270. package/dist/dev/define/skin-mixin.js.map +1 -1
  271. package/dist/dev/define/video/minimal-skin.css +486 -301
  272. package/dist/dev/define/video/minimal-skin.d.ts.map +1 -1
  273. package/dist/dev/define/video/minimal-skin.js +110 -103
  274. package/dist/dev/define/video/minimal-skin.js.map +1 -1
  275. package/dist/dev/define/video/minimal-skin.tailwind.d.ts.map +1 -1
  276. package/dist/dev/define/video/minimal-skin.tailwind.js +123 -116
  277. package/dist/dev/define/video/minimal-skin.tailwind.js.map +1 -1
  278. package/dist/dev/define/video/skin.css +484 -289
  279. package/dist/dev/define/video/skin.d.ts.map +1 -1
  280. package/dist/dev/define/video/skin.js +105 -100
  281. package/dist/dev/define/video/skin.js.map +1 -1
  282. package/dist/dev/define/video/skin.tailwind.d.ts.map +1 -1
  283. package/dist/dev/define/video/skin.tailwind.js +114 -108
  284. package/dist/dev/define/video/skin.tailwind.js.map +1 -1
  285. package/dist/dev/icons/dist/render/default/index.js +2 -1
  286. package/dist/dev/icons/dist/render/default/index.js.map +1 -1
  287. package/dist/dev/icons/dist/render/minimal/index.js +2 -1
  288. package/dist/dev/icons/dist/render/minimal/index.js.map +1 -1
  289. package/dist/dev/index.d.ts +5 -4
  290. package/dist/dev/index.js +3 -2
  291. package/dist/dev/media/background-video/index.d.ts +8 -1
  292. package/dist/dev/media/background-video/index.d.ts.map +1 -1
  293. package/dist/dev/media/background-video/index.js +5 -1
  294. package/dist/dev/media/background-video/index.js.map +1 -1
  295. package/dist/dev/media/container-element.js +5 -2
  296. package/dist/dev/media/container-element.js.map +1 -1
  297. package/dist/dev/media/dash-video/index.d.ts +13 -0
  298. package/dist/dev/media/dash-video/index.d.ts.map +1 -0
  299. package/dist/dev/media/dash-video/index.js +26 -0
  300. package/dist/dev/media/dash-video/index.js.map +1 -0
  301. package/dist/dev/media/hls-video/index.d.ts +2 -1
  302. package/dist/dev/media/hls-video/index.d.ts.map +1 -1
  303. package/dist/dev/media/hls-video/index.js +2 -1
  304. package/dist/dev/media/hls-video/index.js.map +1 -1
  305. package/dist/dev/media/simple-hls-video/index.d.ts +2 -1
  306. package/dist/dev/media/simple-hls-video/index.d.ts.map +1 -1
  307. package/dist/dev/media/simple-hls-video/index.js +3 -1
  308. package/dist/dev/media/simple-hls-video/index.js.map +1 -1
  309. package/dist/dev/player/context.d.ts +16 -2
  310. package/dist/dev/player/context.d.ts.map +1 -1
  311. package/dist/dev/player/context.js +6 -2
  312. package/dist/dev/player/context.js.map +1 -1
  313. package/dist/dev/player/create-player.d.ts +1 -1
  314. package/dist/dev/player/create-player.js +11 -3
  315. package/dist/dev/player/create-player.js.map +1 -1
  316. package/dist/dev/skins/dist/default/default/tailwind/audio.tailwind.js +10 -26
  317. package/dist/dev/skins/dist/default/default/tailwind/audio.tailwind.js.map +1 -1
  318. package/dist/dev/skins/dist/default/default/tailwind/components/button.js +4 -3
  319. package/dist/dev/skins/dist/default/default/tailwind/components/button.js.map +1 -1
  320. package/dist/dev/skins/dist/default/default/tailwind/components/controls.js +1 -1
  321. package/dist/dev/skins/dist/default/default/tailwind/components/controls.js.map +1 -1
  322. package/dist/dev/skins/dist/default/default/tailwind/components/error.js +3 -3
  323. package/dist/dev/skins/dist/default/default/tailwind/components/error.js.map +1 -1
  324. package/dist/dev/skins/dist/default/default/tailwind/components/overlay.js +1 -1
  325. package/dist/dev/skins/dist/default/default/tailwind/components/overlay.js.map +1 -1
  326. package/dist/dev/skins/dist/default/default/tailwind/components/popup.js +3 -3
  327. package/dist/dev/skins/dist/default/default/tailwind/components/popup.js.map +1 -1
  328. package/dist/dev/skins/dist/default/default/tailwind/components/poster.js +16 -0
  329. package/dist/dev/skins/dist/default/default/tailwind/components/poster.js.map +1 -0
  330. package/dist/dev/skins/dist/default/default/tailwind/components/preview.js +13 -0
  331. package/dist/dev/skins/dist/default/default/tailwind/components/preview.js.map +1 -0
  332. package/dist/dev/skins/dist/default/default/tailwind/components/root.js +1 -1
  333. package/dist/dev/skins/dist/default/default/tailwind/components/root.js.map +1 -1
  334. package/dist/dev/skins/dist/default/default/tailwind/components/seek.js +1 -1
  335. package/dist/dev/skins/dist/default/default/tailwind/components/seek.js.map +1 -1
  336. package/dist/dev/skins/dist/default/default/tailwind/components/slider.js +1 -1
  337. package/dist/dev/skins/dist/default/default/tailwind/components/slider.js.map +1 -1
  338. package/dist/dev/skins/dist/default/default/tailwind/components/surface.js +1 -1
  339. package/dist/dev/skins/dist/default/default/tailwind/components/surface.js.map +1 -1
  340. package/dist/dev/skins/dist/default/default/tailwind/video.tailwind.js +27 -16
  341. package/dist/dev/skins/dist/default/default/tailwind/video.tailwind.js.map +1 -1
  342. package/dist/dev/skins/dist/default/minimal/tailwind/audio.tailwind.js +11 -24
  343. package/dist/dev/skins/dist/default/minimal/tailwind/audio.tailwind.js.map +1 -1
  344. package/dist/dev/skins/dist/default/minimal/tailwind/components/button.js +4 -3
  345. package/dist/dev/skins/dist/default/minimal/tailwind/components/button.js.map +1 -1
  346. package/dist/dev/skins/dist/default/minimal/tailwind/components/controls.js +1 -1
  347. package/dist/dev/skins/dist/default/minimal/tailwind/components/controls.js.map +1 -1
  348. package/dist/dev/skins/dist/default/minimal/tailwind/components/error.js +3 -3
  349. package/dist/dev/skins/dist/default/minimal/tailwind/components/error.js.map +1 -1
  350. package/dist/dev/skins/dist/default/minimal/tailwind/components/overlay.js +1 -1
  351. package/dist/dev/skins/dist/default/minimal/tailwind/components/overlay.js.map +1 -1
  352. package/dist/dev/skins/dist/default/minimal/tailwind/components/playback-rate.js +6 -0
  353. package/dist/dev/skins/dist/default/minimal/tailwind/components/playback-rate.js.map +1 -0
  354. package/dist/dev/skins/dist/default/minimal/tailwind/components/popup.js +4 -3
  355. package/dist/dev/skins/dist/default/minimal/tailwind/components/popup.js.map +1 -1
  356. package/dist/dev/skins/dist/default/minimal/tailwind/components/poster.js +16 -0
  357. package/dist/dev/skins/dist/default/minimal/tailwind/components/poster.js.map +1 -0
  358. package/dist/dev/skins/dist/default/minimal/tailwind/components/preview.js +14 -0
  359. package/dist/dev/skins/dist/default/minimal/tailwind/components/preview.js.map +1 -0
  360. package/dist/dev/skins/dist/default/minimal/tailwind/components/root.js +1 -1
  361. package/dist/dev/skins/dist/default/minimal/tailwind/components/root.js.map +1 -1
  362. package/dist/dev/skins/dist/default/minimal/tailwind/components/seek.js +1 -1
  363. package/dist/dev/skins/dist/default/minimal/tailwind/components/seek.js.map +1 -1
  364. package/dist/dev/skins/dist/default/minimal/tailwind/components/slider.js +1 -1
  365. package/dist/dev/skins/dist/default/minimal/tailwind/components/slider.js.map +1 -1
  366. package/dist/dev/skins/dist/default/minimal/tailwind/components/time.js +1 -1
  367. package/dist/dev/skins/dist/default/minimal/tailwind/components/time.js.map +1 -1
  368. package/dist/dev/skins/dist/default/minimal/tailwind/video.tailwind.js +33 -16
  369. package/dist/dev/skins/dist/default/minimal/tailwind/video.tailwind.js.map +1 -1
  370. package/dist/{default/skins/dist/default/minimal/tailwind/components → dev/skins/dist/default/shared/tailwind}/icon-state.js +6 -1
  371. package/dist/dev/skins/dist/default/shared/tailwind/icon-state.js.map +1 -0
  372. package/dist/dev/skins/dist/default/{minimal/tailwind/components → shared/tailwind}/tooltip-state.js +1 -1
  373. package/dist/dev/skins/dist/default/shared/tailwind/tooltip-state.js.map +1 -0
  374. package/dist/dev/store/container-mixin.d.ts +10 -5
  375. package/dist/dev/store/container-mixin.d.ts.map +1 -1
  376. package/dist/dev/store/container-mixin.js +16 -60
  377. package/dist/dev/store/container-mixin.js.map +1 -1
  378. package/dist/dev/store/media-attach-mixin.d.ts +19 -0
  379. package/dist/dev/store/media-attach-mixin.d.ts.map +1 -0
  380. package/dist/dev/store/media-attach-mixin.js +45 -0
  381. package/dist/dev/store/media-attach-mixin.js.map +1 -0
  382. package/dist/dev/store/provider-mixin.d.ts +19 -6
  383. package/dist/dev/store/provider-mixin.d.ts.map +1 -1
  384. package/dist/dev/store/provider-mixin.js +99 -9
  385. package/dist/dev/store/provider-mixin.js.map +1 -1
  386. package/dist/dev/ui/popover/popover-element.d.ts.map +1 -1
  387. package/dist/dev/ui/popover/popover-element.js +54 -3
  388. package/dist/dev/ui/popover/popover-element.js.map +1 -1
  389. package/dist/dev/ui/time-slider/time-slider-element.js +1 -1
  390. package/dist/dev/ui/time-slider/time-slider-element.js.map +1 -1
  391. package/dist/dev/ui/tooltip/tooltip-element.d.ts.map +1 -1
  392. package/dist/dev/ui/tooltip/tooltip-element.js +53 -3
  393. package/dist/dev/ui/tooltip/tooltip-element.js.map +1 -1
  394. package/dist/dev/ui/tooltip/tooltip-group-element.js +4 -1
  395. package/dist/dev/ui/tooltip/tooltip-group-element.js.map +1 -1
  396. package/dist/dev/ui/volume-slider/volume-slider-element.js +3 -3
  397. package/dist/dev/ui/volume-slider/volume-slider-element.js.map +1 -1
  398. package/package.json +24 -11
  399. package/dist/default/skins/dist/default/default/tailwind/components/icon-state.js.map +0 -1
  400. package/dist/default/skins/dist/default/default/tailwind/components/tooltip-state.js +0 -28
  401. package/dist/default/skins/dist/default/default/tailwind/components/tooltip-state.js.map +0 -1
  402. package/dist/default/skins/dist/default/minimal/tailwind/components/icon-state.js.map +0 -1
  403. package/dist/default/skins/dist/default/minimal/tailwind/components/tooltip-state.js +0 -28
  404. package/dist/default/skins/dist/default/minimal/tailwind/components/tooltip-state.js.map +0 -1
  405. package/dist/dev/skins/dist/default/default/tailwind/components/icon-state.js +0 -29
  406. package/dist/dev/skins/dist/default/default/tailwind/components/icon-state.js.map +0 -1
  407. package/dist/dev/skins/dist/default/default/tailwind/components/tooltip-state.js.map +0 -1
  408. package/dist/dev/skins/dist/default/minimal/tailwind/components/icon-state.js +0 -29
  409. package/dist/dev/skins/dist/default/minimal/tailwind/components/icon-state.js.map +0 -1
  410. package/dist/dev/skins/dist/default/minimal/tailwind/components/tooltip-state.js.map +0 -1
@@ -0,0 +1,3218 @@
1
+ import { a as isObject, o as isUndefined, r as isNull, t as isFunction } from "./predicate-BG-dj_kF.js";
2
+ import { t as listen } from "./listen-BXAYCbZA.js";
3
+ import { a as ContextRequestEvent, n as mediaContext, r as playerContext, t as containerContext } from "./context-DTY0nOpS.js";
4
+
5
+ //#region ../store/dist/dev/core/abort-controller-registry.js
6
+ var AbortControllerRegistry = class {
7
+ #base = new AbortController();
8
+ #keys = /* @__PURE__ */ new Map();
9
+ /** The attach-scoped signal. Aborts on detach or reattach. */
10
+ get base() {
11
+ return this.#base.signal;
12
+ }
13
+ /** Clears all keyed signals, leaving base intact. */
14
+ clear() {
15
+ for (const controller of this.#keys.values()) controller.abort();
16
+ this.#keys.clear();
17
+ }
18
+ /** Resets base and clears all keyed signals. */
19
+ reset() {
20
+ this.clear();
21
+ this.#base.abort();
22
+ this.#base = new AbortController();
23
+ }
24
+ /** Creates a new signal for the key, superseding any previous signal. */
25
+ supersede(key) {
26
+ this.#keys.get(key)?.abort();
27
+ const controller = new AbortController();
28
+ this.#keys.set(key, controller);
29
+ return AbortSignal.any([this.#base.signal, controller.signal]);
30
+ }
31
+ };
32
+
33
+ //#endregion
34
+ //#region ../store/dist/dev/core/combine.js
35
+ /**
36
+ * Combines multiple slices into a single slice.
37
+ *
38
+ * @param slices - The slices to combine.
39
+ * @returns A new slice that represents the combination of the input slices.
40
+ */
41
+ function combine(...slices) {
42
+ return {
43
+ state: (ctx) => {
44
+ const states = slices.map((slice) => slice.state(ctx));
45
+ return Object.assign({}, ...states);
46
+ },
47
+ attach: (ctx) => {
48
+ for (const slice of slices) try {
49
+ slice.attach?.(ctx);
50
+ } catch (err) {
51
+ ctx.reportError(err);
52
+ }
53
+ }
54
+ };
55
+ }
56
+
57
+ //#endregion
58
+ //#region ../store/dist/dev/core/errors.js
59
+ var StoreError = class extends Error {
60
+ code;
61
+ cause;
62
+ constructor(code, options) {
63
+ super(options?.message ?? code);
64
+ this.name = "StoreError";
65
+ this.code = code;
66
+ this.cause = options?.cause;
67
+ }
68
+ };
69
+ function throwNoTargetError() {
70
+ throw new StoreError("NO_TARGET");
71
+ }
72
+ function throwDestroyedError() {
73
+ throw new StoreError("DESTROYED");
74
+ }
75
+
76
+ //#endregion
77
+ //#region ../utils/dist/object/pick.js
78
+ /**
79
+ * Creates a new object with only the specified keys.
80
+ *
81
+ * @example
82
+ * const obj = { a: 1, b: 2, c: 3 };
83
+ * pick(obj, ['a', 'c']); // { a: 1, c: 3 }
84
+ */
85
+ function pick(obj, keys) {
86
+ const result = {};
87
+ for (const key of keys) result[key] = obj[key];
88
+ return result;
89
+ }
90
+
91
+ //#endregion
92
+ //#region ../store/dist/dev/core/selector.js
93
+ const stateContext = {
94
+ target: throwNoTargetError,
95
+ signals: new AbortControllerRegistry(),
96
+ set: throwNoTargetError
97
+ };
98
+ /**
99
+ * Create a type-safe selector for a slice's state.
100
+ *
101
+ * The selector returns the slice's state, or `undefined` if the slice
102
+ * is not configured in the store.
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * const selectPlayback = createSelector(playbackSlice);
107
+ * selectPlayback(store.state); // { paused, play, pause, ... } | undefined
108
+ * selectPlayback.displayName; // 'playback' (from slice name)
109
+ * ```
110
+ *
111
+ * @param slice - The slice to create a selector for.
112
+ */
113
+ function createSelector(slice) {
114
+ const initialState = slice.state(stateContext);
115
+ const keys = Object.keys(initialState);
116
+ const firstKey = keys[0];
117
+ if (!firstKey) return Object.assign(() => void 0, { displayName: slice.name });
118
+ return Object.assign((state) => {
119
+ if (!(firstKey in state)) return void 0;
120
+ return pick(state, keys);
121
+ }, { displayName: slice.name });
122
+ }
123
+
124
+ //#endregion
125
+ //#region ../store/dist/dev/core/shallow-equal.js
126
+ const hasOwn = Object.prototype.hasOwnProperty;
127
+ function shallowEqual(a, b) {
128
+ if (Object.is(a, b)) return true;
129
+ if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
130
+ const keysA = Object.keys(a);
131
+ const keysB = Object.keys(b);
132
+ if (keysA.length !== keysB.length) return false;
133
+ for (const key of keysA) if (!hasOwn.call(b, key) || !Object.is(a[key], b[key])) return false;
134
+ return true;
135
+ }
136
+
137
+ //#endregion
138
+ //#region ../store/dist/dev/core/slice.js
139
+ function defineSlice() {
140
+ return (config) => config;
141
+ }
142
+
143
+ //#endregion
144
+ //#region ../utils/dist/function/noop.js
145
+ function noop(..._args) {}
146
+
147
+ //#endregion
148
+ //#region ../utils/dist/function/throttle.js
149
+ /**
150
+ * Trailing-edge throttle: the first call schedules a timer; subsequent calls
151
+ * within the window update the arguments. The function fires once per `ms`
152
+ * window with the latest arguments.
153
+ */
154
+ function throttle(fn, ms) {
155
+ let timerId = null;
156
+ let latestArgs;
157
+ const throttled = (...args) => {
158
+ latestArgs = args;
159
+ if (timerId !== null) return;
160
+ timerId = setTimeout(() => {
161
+ timerId = null;
162
+ fn(...latestArgs);
163
+ }, ms);
164
+ };
165
+ throttled.cancel = () => {
166
+ if (timerId !== null) {
167
+ clearTimeout(timerId);
168
+ timerId = null;
169
+ }
170
+ };
171
+ return throttled;
172
+ }
173
+
174
+ //#endregion
175
+ //#region ../store/dist/dev/core/state.js
176
+ let isFlushScheduled = false;
177
+ function scheduleFlush() {
178
+ if (isFlushScheduled) return;
179
+ isFlushScheduled = true;
180
+ queueMicrotask(flush);
181
+ }
182
+ const pendingContainers = /* @__PURE__ */ new Set();
183
+ function flush() {
184
+ isFlushScheduled = false;
185
+ for (const container of pendingContainers) container.flush();
186
+ pendingContainers.clear();
187
+ }
188
+ const hasOwnProp = Object.prototype.hasOwnProperty;
189
+ var StateContainer = class {
190
+ #current;
191
+ #listeners = /* @__PURE__ */ new Set();
192
+ #pending = false;
193
+ constructor(initial) {
194
+ this.#current = Object.freeze({ ...initial });
195
+ }
196
+ get current() {
197
+ return this.#current;
198
+ }
199
+ patch(partial) {
200
+ const next = { ...this.#current };
201
+ let changed = false;
202
+ for (const key in partial) {
203
+ if (!hasOwnProp.call(partial, key)) continue;
204
+ const value = partial[key];
205
+ if (!Object.is(this.#current[key], value)) {
206
+ next[key] = value;
207
+ changed = true;
208
+ }
209
+ }
210
+ if (changed) {
211
+ this.#current = Object.freeze(next);
212
+ this.#markPending();
213
+ }
214
+ }
215
+ subscribe(callback, options) {
216
+ const signal = options?.signal;
217
+ if (signal?.aborted) return noop;
218
+ this.#listeners.add(callback);
219
+ if (!signal) return () => this.#listeners.delete(callback);
220
+ const onAbort = () => this.#listeners.delete(callback);
221
+ signal.addEventListener("abort", onAbort, { once: true });
222
+ return () => {
223
+ signal.removeEventListener("abort", onAbort);
224
+ this.#listeners.delete(callback);
225
+ };
226
+ }
227
+ flush() {
228
+ if (!this.#pending) return;
229
+ this.#pending = false;
230
+ for (const fn of this.#listeners) fn();
231
+ }
232
+ #markPending() {
233
+ this.#pending = true;
234
+ pendingContainers.add(this);
235
+ scheduleFlush();
236
+ }
237
+ };
238
+ function createState(initial) {
239
+ return new StateContainer(initial);
240
+ }
241
+
242
+ //#endregion
243
+ //#region ../store/dist/dev/core/store.js
244
+ const STORE_SYMBOL = Symbol("@videojs/store");
245
+ function createStore() {
246
+ return (slice, options = {}) => {
247
+ let target = null;
248
+ let destroyed = false;
249
+ const setupAbort = new AbortController();
250
+ const signals = new AbortControllerRegistry();
251
+ let state;
252
+ function validate() {
253
+ if (destroyed) throwDestroyedError();
254
+ if (!target) throwNoTargetError();
255
+ }
256
+ const initialState = slice.state({
257
+ target: () => {
258
+ validate();
259
+ return target;
260
+ },
261
+ signals,
262
+ set: (partial) => state.patch(partial)
263
+ });
264
+ state = createState(initialState);
265
+ const store = {
266
+ [STORE_SYMBOL]: true,
267
+ get $state() {
268
+ return state;
269
+ },
270
+ get target() {
271
+ return target;
272
+ },
273
+ get destroyed() {
274
+ return destroyed;
275
+ },
276
+ get state() {
277
+ return state.current;
278
+ },
279
+ attach,
280
+ destroy,
281
+ subscribe
282
+ };
283
+ for (const key of Object.keys(initialState)) Object.defineProperty(store, key, {
284
+ get: () => state.current[key],
285
+ enumerable: true
286
+ });
287
+ try {
288
+ options.onSetup?.({
289
+ store,
290
+ signal: setupAbort.signal
291
+ });
292
+ } catch (error) {
293
+ reportError(error);
294
+ }
295
+ return store;
296
+ function attach(newTarget) {
297
+ if (destroyed) throwDestroyedError();
298
+ signals.reset();
299
+ target = newTarget;
300
+ const attachContext = {
301
+ target: newTarget,
302
+ signal: signals.base,
303
+ get: () => state.current,
304
+ set: (partial) => state.patch(partial),
305
+ reportError,
306
+ store: {
307
+ get state() {
308
+ return state.current;
309
+ },
310
+ subscribe
311
+ }
312
+ };
313
+ try {
314
+ slice.attach?.(attachContext);
315
+ } catch (error) {
316
+ reportError(error);
317
+ }
318
+ try {
319
+ options.onAttach?.({
320
+ store,
321
+ target: newTarget,
322
+ signal: signals.base
323
+ });
324
+ } catch (error) {
325
+ reportError(error);
326
+ }
327
+ return detach;
328
+ }
329
+ function detach() {
330
+ if (isNull(target)) return;
331
+ signals.reset();
332
+ target = null;
333
+ state.patch(initialState);
334
+ }
335
+ function destroy() {
336
+ if (destroyed) return;
337
+ destroyed = true;
338
+ detach();
339
+ setupAbort.abort();
340
+ }
341
+ function subscribe(callback, options) {
342
+ return state.subscribe(callback, options);
343
+ }
344
+ function reportError(error) {
345
+ if (options.onError) options.onError({
346
+ store,
347
+ error
348
+ });
349
+ else console.error("[vjs-store]", error);
350
+ }
351
+ };
352
+ }
353
+ function isStore(value) {
354
+ return isObject(value) && STORE_SYMBOL in value;
355
+ }
356
+
357
+ //#endregion
358
+ //#region ../core/dist/dev/dom/feature.js
359
+ const definePlayerFeature = defineSlice();
360
+
361
+ //#endregion
362
+ //#region ../utils/dist/dom/event.js
363
+ function onEvent(target, type, options) {
364
+ return new Promise((resolve, reject) => {
365
+ const handleAbort = () => {
366
+ reject(options?.signal?.reason ?? "Aborted");
367
+ };
368
+ if (options?.signal?.aborted) {
369
+ handleAbort();
370
+ return;
371
+ }
372
+ options?.signal?.addEventListener("abort", handleAbort, { once: true });
373
+ target.addEventListener(type, (event) => {
374
+ options?.signal?.removeEventListener("abort", handleAbort);
375
+ resolve(event);
376
+ }, {
377
+ ...options,
378
+ once: true
379
+ });
380
+ });
381
+ }
382
+
383
+ //#endregion
384
+ //#region ../utils/dist/dom/supports.js
385
+ function supportsAnchorPositioning() {
386
+ return typeof CSS !== "undefined" && CSS.supports("anchor-name: --a");
387
+ }
388
+
389
+ //#endregion
390
+ //#region ../utils/dist/dom/popover.js
391
+ function tryShowPopover(el) {
392
+ try {
393
+ el?.showPopover?.();
394
+ } catch {}
395
+ }
396
+ function tryHidePopover(el) {
397
+ try {
398
+ el?.hidePopover?.();
399
+ } catch {}
400
+ }
401
+
402
+ //#endregion
403
+ //#region ../utils/dist/string/casing.js
404
+ function kebabCase(str) {
405
+ return str.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
406
+ }
407
+
408
+ //#endregion
409
+ //#region ../utils/dist/dom/style.js
410
+ function applyStyles(element, styles) {
411
+ for (const [prop, value] of Object.entries(styles)) if (typeof value === "string") {
412
+ const key = prop.startsWith("--") ? prop : kebabCase(prop);
413
+ element.style.setProperty(key, value);
414
+ }
415
+ }
416
+ function resolveCSSLength(el, value) {
417
+ const trimmed = value.trim();
418
+ if (!trimmed) return 0;
419
+ const parsed = Number.parseFloat(trimmed);
420
+ if (Number.isNaN(parsed)) return 0;
421
+ if (/^-?\d*\.?\d+$/.test(trimmed) || trimmed.endsWith("px")) return parsed;
422
+ const doc = el.ownerDocument;
423
+ const root = doc?.documentElement;
424
+ if (trimmed.endsWith("rem")) return parsed * (root ? Number.parseFloat(getComputedStyle(root).fontSize) || 16 : 16);
425
+ if (trimmed.endsWith("em")) return parsed * (el instanceof HTMLElement ? Number.parseFloat(getComputedStyle(el).fontSize) || 16 : 16);
426
+ if (!doc) return parsed;
427
+ const measurementEl = doc.createElement("div");
428
+ measurementEl.style.position = "absolute";
429
+ measurementEl.style.visibility = "hidden";
430
+ measurementEl.style.pointerEvents = "none";
431
+ measurementEl.style.inlineSize = trimmed;
432
+ measurementEl.style.blockSize = "0";
433
+ measurementEl.style.padding = "0";
434
+ measurementEl.style.border = "0";
435
+ measurementEl.style.inset = "0";
436
+ const parent = doc.body ?? doc.documentElement;
437
+ if (!parent) return parsed;
438
+ parent.appendChild(measurementEl);
439
+ const pixels = measurementEl.getBoundingClientRect().width;
440
+ measurementEl.remove();
441
+ return Number.isFinite(pixels) ? pixels : parsed;
442
+ }
443
+
444
+ //#endregion
445
+ //#region ../utils/dist/dom/text-track.js
446
+ /** Find the `<track>` element that owns the given `TextTrack`. */
447
+ function findTrackElement(media, track) {
448
+ for (const el of media.querySelectorAll?.("track") ?? []) if (el.track === track) return el;
449
+ return null;
450
+ }
451
+ function getTextTrackList(media, filterPred) {
452
+ if (!media?.textTracks) return [];
453
+ return Array.from(media.textTracks).filter(filterPred).sort(sortByTextTrackKind);
454
+ }
455
+ function sortByTextTrackKind(a, b) {
456
+ return a.kind >= b.kind ? 1 : -1;
457
+ }
458
+
459
+ //#endregion
460
+ //#region ../utils/dist/dom/time-ranges.js
461
+ /** Converts a TimeRanges object to an array of [start, end] tuples. */
462
+ function serializeTimeRanges(ranges) {
463
+ const result = [];
464
+ for (let i = 0; i < ranges.length; i++) result.push([ranges.start(i), ranges.end(i)]);
465
+ return result;
466
+ }
467
+
468
+ //#endregion
469
+ //#region ../core/dist/dev/dom/store/features/buffer.js
470
+ const bufferFeature = definePlayerFeature({
471
+ name: "buffer",
472
+ state: () => ({
473
+ buffered: [],
474
+ seekable: []
475
+ }),
476
+ attach({ target, signal, set }) {
477
+ const { media } = target;
478
+ const sync = () => set({
479
+ buffered: serializeTimeRanges(media.buffered),
480
+ seekable: serializeTimeRanges(media.seekable)
481
+ });
482
+ sync();
483
+ listen(media, "progress", sync, { signal });
484
+ listen(media, "emptied", sync, { signal });
485
+ }
486
+ });
487
+
488
+ //#endregion
489
+ //#region ../core/dist/dev/dom/store/features/controls.js
490
+ const IDLE_DELAY = 2e3;
491
+ const TAP_THRESHOLD = 250;
492
+ const controlsFeature = definePlayerFeature({
493
+ name: "controls",
494
+ state: () => ({
495
+ userActive: true,
496
+ controlsVisible: true
497
+ }),
498
+ attach({ target, signal, get, set }) {
499
+ const { media, container } = target;
500
+ if (isNull(container)) {
501
+ console.warn("[vjs] controlsFeature requires a container element for activity tracking.");
502
+ return;
503
+ }
504
+ function computeVisible(userActive) {
505
+ return userActive || media.paused;
506
+ }
507
+ let idleTimer;
508
+ function clearIdle() {
509
+ clearTimeout(idleTimer);
510
+ idleTimer = void 0;
511
+ }
512
+ function scheduleIdle() {
513
+ clearIdle();
514
+ idleTimer = setTimeout(setInactive, IDLE_DELAY);
515
+ }
516
+ function setActive() {
517
+ if (!get().userActive) set({
518
+ userActive: true,
519
+ controlsVisible: true
520
+ });
521
+ scheduleIdle();
522
+ }
523
+ function setInactive() {
524
+ clearIdle();
525
+ set({
526
+ userActive: false,
527
+ controlsVisible: computeVisible(false)
528
+ });
529
+ }
530
+ let pointerDownTime = 0;
531
+ function onPointerDown() {
532
+ pointerDownTime = Date.now();
533
+ }
534
+ function onPointerUp(event) {
535
+ if (event.pointerType === "touch" && Date.now() - pointerDownTime < TAP_THRESHOLD) {
536
+ const isMediaOrContainer = [media, container].includes(event.target);
537
+ if (get().controlsVisible && isMediaOrContainer) setInactive();
538
+ else setActive();
539
+ } else setActive();
540
+ }
541
+ function onPlaybackChange() {
542
+ const { userActive } = get();
543
+ set({ controlsVisible: computeVisible(userActive) });
544
+ if (!media.paused && userActive) scheduleIdle();
545
+ }
546
+ listen(container, "pointermove", setActive, { signal });
547
+ listen(container, "pointerdown", onPointerDown, { signal });
548
+ listen(container, "pointerup", onPointerUp, { signal });
549
+ listen(container, "keyup", setActive, { signal });
550
+ listen(container, "focusin", setActive, { signal });
551
+ listen(container, "mouseleave", setInactive, { signal });
552
+ listen(media, "play", onPlaybackChange, { signal });
553
+ listen(media, "pause", onPlaybackChange, { signal });
554
+ listen(media, "ended", onPlaybackChange, { signal });
555
+ signal.addEventListener("abort", clearIdle, { once: true });
556
+ scheduleIdle();
557
+ }
558
+ });
559
+
560
+ //#endregion
561
+ //#region ../core/dist/dev/dom/store/features/error.js
562
+ const errorFeature = definePlayerFeature({
563
+ name: "error",
564
+ state: ({ set }) => ({
565
+ error: null,
566
+ dismissError() {
567
+ set({ error: null });
568
+ }
569
+ }),
570
+ attach({ target, signal, set }) {
571
+ const { media } = target;
572
+ const syncError = () => set({ error: media.error });
573
+ listen(media, "error", syncError, { signal });
574
+ listen(media, "emptied", () => set({ error: null }), { signal });
575
+ }
576
+ });
577
+
578
+ //#endregion
579
+ //#region ../core/dist/dev/dom/presentation/fullscreen.js
580
+ /** Check if the Fullscreen API is supported on this platform. */
581
+ function isFullscreenEnabled() {
582
+ const doc = document;
583
+ if (doc.fullscreenEnabled || doc.webkitFullscreenEnabled) return true;
584
+ return isFunction(document.createElement("video").webkitEnterFullscreen);
585
+ }
586
+ /** Get the current fullscreen element from the document. */
587
+ function getFullscreenElement() {
588
+ const doc = document;
589
+ return doc.fullscreenElement ?? doc.webkitFullscreenElement ?? null;
590
+ }
591
+ /**
592
+ * Check if a specific element (or its media) is currently in fullscreen.
593
+ *
594
+ * Uses `:fullscreen` pseudo-class which works across Shadow DOM boundaries.
595
+ */
596
+ function isFullscreenElement(container, media) {
597
+ const video = media;
598
+ if (video.webkitDisplayingFullscreen && video.webkitPresentationMode === "fullscreen") return true;
599
+ const target = container ?? media;
600
+ if (getFullscreenElement() === target) return true;
601
+ try {
602
+ return target.matches(":fullscreen");
603
+ } catch {
604
+ return false;
605
+ }
606
+ }
607
+ /**
608
+ * Request fullscreen mode.
609
+ *
610
+ * Tries container first (to show custom UI), falls back to media element
611
+ * for platforms that only support video fullscreen (iOS Safari).
612
+ */
613
+ async function requestFullscreen(container, media) {
614
+ const doc = document;
615
+ const video = media;
616
+ if (container && (doc.fullscreenEnabled || doc.webkitFullscreenEnabled)) {
617
+ const el = container;
618
+ if (isFunction(el.requestFullscreen)) return el.requestFullscreen();
619
+ if (isFunction(el.webkitRequestFullscreen)) return el.webkitRequestFullscreen();
620
+ }
621
+ if (isFunction(video.webkitEnterFullscreen)) {
622
+ video.webkitEnterFullscreen();
623
+ return;
624
+ }
625
+ if (isFunction(media.requestFullscreen)) return media.requestFullscreen();
626
+ throw new DOMException("Fullscreen not supported", "NotSupportedError");
627
+ }
628
+ /** Exit fullscreen mode. */
629
+ async function exitFullscreen(media) {
630
+ const doc = document;
631
+ if (media) {
632
+ const video = media;
633
+ if (isFunction(video.webkitExitFullscreen) && video.webkitDisplayingFullscreen) {
634
+ video.webkitExitFullscreen();
635
+ return;
636
+ }
637
+ }
638
+ if (isFunction(doc.exitFullscreen)) return doc.exitFullscreen();
639
+ if (isFunction(doc.webkitExitFullscreen)) return doc.webkitExitFullscreen();
640
+ }
641
+
642
+ //#endregion
643
+ //#region ../core/dist/dev/dom/presentation/pip.js
644
+ function resolveMediaTarget(media) {
645
+ const target = media.target;
646
+ return target instanceof HTMLMediaElement ? target : media;
647
+ }
648
+ /**
649
+ * Check if Picture-in-Picture is supported on this platform.
650
+ *
651
+ * Note: Safari PWAs don't support PiP even though the API exists.
652
+ */
653
+ function isPictureInPictureEnabled() {
654
+ if (document.pictureInPictureEnabled) {
655
+ const isSafari = /.*Version\/.*Safari\/.*/.test(navigator.userAgent);
656
+ const isPWA = typeof matchMedia === "function" && matchMedia("(display-mode: standalone)").matches;
657
+ return !isSafari || !isPWA;
658
+ }
659
+ return isFunction(document.createElement("video").webkitSetPresentationMode);
660
+ }
661
+ /**
662
+ * Check if Picture-in-Picture is currently active for a media element.
663
+ */
664
+ function isPictureInPictureElement(media) {
665
+ const target = resolveMediaTarget(media);
666
+ if (document.pictureInPictureElement === target) return true;
667
+ return target.webkitPresentationMode === "picture-in-picture";
668
+ }
669
+ /**
670
+ * Request Picture-in-Picture mode.
671
+ *
672
+ * Uses standard API where available, falls back to iOS Safari's
673
+ * WebKit presentation mode.
674
+ */
675
+ async function requestPictureInPicture(media) {
676
+ const video = resolveMediaTarget(media);
677
+ if (isFunction(video.webkitSetPresentationMode)) {
678
+ video.webkitSetPresentationMode("picture-in-picture");
679
+ return;
680
+ }
681
+ if (isFunction(video.requestPictureInPicture)) {
682
+ await video.requestPictureInPicture();
683
+ return;
684
+ }
685
+ throw new DOMException("Picture-in-Picture not supported", "NotSupportedError");
686
+ }
687
+ /**
688
+ * Exit Picture-in-Picture mode.
689
+ *
690
+ * Uses standard API where available, falls back to iOS Safari's
691
+ * WebKit presentation mode.
692
+ */
693
+ async function exitPictureInPicture(media) {
694
+ if (media) {
695
+ const video = resolveMediaTarget(media);
696
+ if (isFunction(video.webkitSetPresentationMode) && video.webkitPresentationMode === "picture-in-picture") {
697
+ video.webkitSetPresentationMode("inline");
698
+ return;
699
+ }
700
+ }
701
+ if (isFunction(document.exitPictureInPicture)) return document.exitPictureInPicture();
702
+ }
703
+
704
+ //#endregion
705
+ //#region ../core/dist/dev/dom/store/features/fullscreen.js
706
+ const fullscreenFeature = definePlayerFeature({
707
+ name: "fullscreen",
708
+ state: ({ target }) => ({
709
+ fullscreen: false,
710
+ fullscreenAvailability: "unavailable",
711
+ async requestFullscreen() {
712
+ const { media, container } = target();
713
+ if (isPictureInPictureElement(media)) await exitPictureInPicture(media);
714
+ return requestFullscreen(container, media);
715
+ },
716
+ async exitFullscreen() {
717
+ const { media } = target();
718
+ return exitFullscreen(media);
719
+ }
720
+ }),
721
+ attach({ target, signal, set }) {
722
+ const { media, container } = target;
723
+ set({ fullscreenAvailability: isFullscreenEnabled() ? "available" : "unsupported" });
724
+ const sync = () => set({ fullscreen: isFullscreenElement(container, media) });
725
+ sync();
726
+ listen(document, "fullscreenchange", sync, { signal });
727
+ listen(document, "webkitfullscreenchange", sync, { signal });
728
+ if ("webkitPresentationMode" in media) listen(media, "webkitpresentationmodechanged", sync, { signal });
729
+ }
730
+ });
731
+
732
+ //#endregion
733
+ //#region ../core/dist/dev/dom/store/features/pip.js
734
+ const pipFeature = definePlayerFeature({
735
+ name: "pip",
736
+ state: ({ target }) => ({
737
+ pip: false,
738
+ pipAvailability: "unavailable",
739
+ async requestPictureInPicture() {
740
+ const { media, container } = target();
741
+ if (isFullscreenElement(container, media)) await exitFullscreen();
742
+ return requestPictureInPicture(media);
743
+ },
744
+ async exitPictureInPicture() {
745
+ const { media } = target();
746
+ return exitPictureInPicture(media);
747
+ }
748
+ }),
749
+ attach({ target, signal, set }) {
750
+ const { media } = target;
751
+ set({ pipAvailability: isPictureInPictureEnabled() ? "available" : "unsupported" });
752
+ const sync = () => set({ pip: isPictureInPictureElement(media) });
753
+ sync();
754
+ listen(media, "enterpictureinpicture", sync, { signal });
755
+ listen(media, "leavepictureinpicture", sync, { signal });
756
+ if ("webkitPresentationMode" in media) listen(media, "webkitpresentationmodechanged", sync, { signal });
757
+ }
758
+ });
759
+
760
+ //#endregion
761
+ //#region ../core/dist/dev/dom/store/features/playback.js
762
+ const playbackFeature = definePlayerFeature({
763
+ name: "playback",
764
+ state: ({ target }) => ({
765
+ paused: true,
766
+ ended: false,
767
+ started: false,
768
+ waiting: false,
769
+ play() {
770
+ return target().media.play();
771
+ },
772
+ pause() {
773
+ target().media.pause();
774
+ }
775
+ }),
776
+ attach({ target, signal, set }) {
777
+ const { media } = target;
778
+ const sync = () => set({
779
+ paused: media.paused,
780
+ ended: media.ended,
781
+ started: !media.paused || media.currentTime > 0,
782
+ waiting: media.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !media.paused
783
+ });
784
+ sync();
785
+ listen(media, "emptied", sync, { signal });
786
+ listen(media, "play", sync, { signal });
787
+ listen(media, "pause", sync, { signal });
788
+ listen(media, "ended", sync, { signal });
789
+ listen(media, "playing", sync, { signal });
790
+ listen(media, "waiting", sync, { signal });
791
+ listen(media, "seeked", sync, { signal });
792
+ }
793
+ });
794
+
795
+ //#endregion
796
+ //#region ../core/dist/dev/dom/store/features/playback-rate.js
797
+ const DEFAULT_RATES = [
798
+ 1,
799
+ 1.2,
800
+ 1.5,
801
+ 1.7,
802
+ 2
803
+ ];
804
+ const playbackRateFeature = definePlayerFeature({
805
+ name: "playbackRate",
806
+ state: ({ target }) => ({
807
+ playbackRates: DEFAULT_RATES,
808
+ playbackRate: 1,
809
+ setPlaybackRate(rate) {
810
+ target().media.playbackRate = rate;
811
+ }
812
+ }),
813
+ attach({ target, signal, set }) {
814
+ const { media } = target;
815
+ const sync = () => set({ playbackRate: media.playbackRate });
816
+ sync();
817
+ listen(media, "ratechange", sync, { signal });
818
+ }
819
+ });
820
+
821
+ //#endregion
822
+ //#region ../core/dist/dev/dom/store/features/source.js
823
+ const sourceFeature = definePlayerFeature({
824
+ name: "source",
825
+ state: ({ target, signals }) => ({
826
+ source: null,
827
+ canPlay: false,
828
+ loadSource(src) {
829
+ signals.clear();
830
+ const { media } = target();
831
+ media.src = src;
832
+ media.load();
833
+ return src;
834
+ }
835
+ }),
836
+ attach({ target, signal, set }) {
837
+ const { media } = target;
838
+ const sync = () => set({
839
+ source: media.currentSrc || media.src || null,
840
+ canPlay: media.readyState >= HTMLMediaElement.HAVE_ENOUGH_DATA
841
+ });
842
+ sync();
843
+ listen(media, "canplay", sync, { signal });
844
+ listen(media, "canplaythrough", sync, { signal });
845
+ listen(media, "loadstart", sync, { signal });
846
+ listen(media, "emptied", sync, { signal });
847
+ }
848
+ });
849
+
850
+ //#endregion
851
+ //#region ../core/dist/dev/dom/store/features/text-track.js
852
+ const textTrackFeature = definePlayerFeature({
853
+ name: "textTrack",
854
+ state: ({ target }) => ({
855
+ chaptersCues: [],
856
+ thumbnailCues: [],
857
+ thumbnailTrackSrc: null,
858
+ textTrackList: [],
859
+ subtitlesShowing: false,
860
+ toggleSubtitles(forceShow) {
861
+ const subtitlesTracks = getTextTrackList(target().media, (track) => track.kind === "subtitles" || track.kind === "captions");
862
+ if (!subtitlesTracks.length) return false;
863
+ const showing = subtitlesTracks.some((track) => track.mode === "showing");
864
+ const nextShowing = forceShow ?? !showing;
865
+ for (const track of subtitlesTracks) track.mode = nextShowing ? "showing" : "disabled";
866
+ return nextShowing;
867
+ }
868
+ }),
869
+ attach({ target, signal, set }) {
870
+ const { media } = target;
871
+ let trackCleanup = null;
872
+ function sync() {
873
+ trackCleanup?.abort();
874
+ trackCleanup = new AbortController();
875
+ let chaptersTrack = null;
876
+ let thumbnailTrack = null;
877
+ const textTrackList = [];
878
+ let subtitlesShowing = false;
879
+ for (let i = 0; i < media.textTracks.length; i++) {
880
+ const track = media.textTracks[i];
881
+ if (!chaptersTrack && track.kind === "chapters") chaptersTrack = track;
882
+ if (!thumbnailTrack && track.kind === "metadata" && track.label === "thumbnails") thumbnailTrack = track;
883
+ textTrackList.push({
884
+ kind: track.kind,
885
+ label: track.label,
886
+ language: track.language,
887
+ mode: track.mode
888
+ });
889
+ if ((track.kind === "captions" || track.kind === "subtitles") && track.mode === "showing") subtitlesShowing = true;
890
+ }
891
+ const chaptersCues = chaptersTrack?.cues ? Array.from(chaptersTrack.cues) : [];
892
+ const thumbnailCues = thumbnailTrack?.cues ? Array.from(thumbnailTrack.cues) : [];
893
+ let thumbnailTrackSrc = null;
894
+ if (thumbnailTrack) thumbnailTrackSrc = findTrackElement(media, thumbnailTrack)?.src ?? null;
895
+ for (const trackEl of media.querySelectorAll?.("track") ?? []) if (!trackEl.track?.cues?.length) listen(trackEl, "load", sync, { signal: trackCleanup.signal });
896
+ set({
897
+ chaptersCues,
898
+ thumbnailCues,
899
+ thumbnailTrackSrc,
900
+ textTrackList,
901
+ subtitlesShowing
902
+ });
903
+ }
904
+ sync();
905
+ listen(media.textTracks, "addtrack", sync, { signal });
906
+ listen(media.textTracks, "removetrack", sync, { signal });
907
+ listen(media.textTracks, "change", sync, { signal });
908
+ listen(media, "loadstart", sync, { signal });
909
+ signal.addEventListener("abort", () => trackCleanup?.abort(), { once: true });
910
+ }
911
+ });
912
+
913
+ //#endregion
914
+ //#region ../core/dist/dev/dom/media/predicate.js
915
+ function hasMetadata(media) {
916
+ return media.readyState >= HTMLMediaElement.HAVE_METADATA;
917
+ }
918
+
919
+ //#endregion
920
+ //#region ../core/dist/dev/dom/store/signal-keys.js
921
+ const signalKeys = { seek: Symbol.for("@videojs/seek") };
922
+
923
+ //#endregion
924
+ //#region ../core/dist/dev/dom/store/features/time.js
925
+ const timeFeature = definePlayerFeature({
926
+ name: "time",
927
+ state: ({ target, signals, set }) => ({
928
+ currentTime: 0,
929
+ duration: 0,
930
+ seeking: false,
931
+ async seek(time) {
932
+ const { media } = target(), signal = signals.supersede(signalKeys.seek);
933
+ if (!hasMetadata(media)) {
934
+ if (!await onEvent(media, "loadedmetadata", { signal }).catch(() => false)) return media.currentTime;
935
+ }
936
+ const clampedTime = Math.max(0, Math.min(time, media.duration || Infinity));
937
+ set({
938
+ currentTime: clampedTime,
939
+ seeking: true
940
+ });
941
+ media.currentTime = clampedTime;
942
+ await onEvent(media, "seeked", { signal }).catch(noop);
943
+ return media.currentTime;
944
+ }
945
+ }),
946
+ attach({ target, signal, set }) {
947
+ const { media } = target;
948
+ const sync = () => set({
949
+ currentTime: media.currentTime,
950
+ duration: Number.isFinite(media.duration) ? media.duration : 0,
951
+ seeking: media.seeking
952
+ });
953
+ sync();
954
+ listen(media, "timeupdate", sync, { signal });
955
+ listen(media, "durationchange", sync, { signal });
956
+ listen(media, "seeking", sync, { signal });
957
+ listen(media, "seeked", sync, { signal });
958
+ listen(media, "loadedmetadata", sync, { signal });
959
+ listen(media, "emptied", sync, { signal });
960
+ }
961
+ });
962
+
963
+ //#endregion
964
+ //#region ../core/dist/dev/dom/store/features/volume.js
965
+ /** Volume to restore when unmuting at zero. */
966
+ const UNMUTE_VOLUME = .25;
967
+ const volumeFeature = definePlayerFeature({
968
+ name: "volume",
969
+ state: ({ target }) => ({
970
+ volume: 1,
971
+ muted: false,
972
+ volumeAvailability: "unavailable",
973
+ setVolume(volume) {
974
+ const { media } = target();
975
+ const clamped = Math.max(0, Math.min(1, volume));
976
+ if (clamped > 0 && media.muted) media.muted = false;
977
+ media.volume = clamped;
978
+ return media.volume;
979
+ },
980
+ toggleMuted() {
981
+ const { media } = target();
982
+ if (media.muted || media.volume === 0) {
983
+ media.muted = false;
984
+ if (media.volume === 0) media.volume = UNMUTE_VOLUME;
985
+ } else media.muted = true;
986
+ return media.muted;
987
+ }
988
+ }),
989
+ attach({ target, signal, set }) {
990
+ const { media } = target;
991
+ set({ volumeAvailability: canSetVolume() });
992
+ const sync = () => set({
993
+ volume: media.volume,
994
+ muted: media.muted
995
+ });
996
+ sync();
997
+ listen(media, "volumechange", sync, { signal });
998
+ }
999
+ });
1000
+ /** Check if volume can be programmatically set (fails on iOS Safari). */
1001
+ function canSetVolume() {
1002
+ const video = document.createElement("video");
1003
+ try {
1004
+ video.volume = .5;
1005
+ return video.volume === .5 ? "available" : "unsupported";
1006
+ } catch {
1007
+ return "unsupported";
1008
+ }
1009
+ }
1010
+
1011
+ //#endregion
1012
+ //#region ../core/dist/dev/dom/store/features/presets.js
1013
+ const videoFeatures = [
1014
+ playbackFeature,
1015
+ playbackRateFeature,
1016
+ volumeFeature,
1017
+ timeFeature,
1018
+ sourceFeature,
1019
+ bufferFeature,
1020
+ fullscreenFeature,
1021
+ pipFeature,
1022
+ controlsFeature,
1023
+ textTrackFeature,
1024
+ errorFeature
1025
+ ];
1026
+ const audioFeatures = [
1027
+ playbackFeature,
1028
+ playbackRateFeature,
1029
+ volumeFeature,
1030
+ timeFeature,
1031
+ sourceFeature,
1032
+ bufferFeature,
1033
+ errorFeature
1034
+ ];
1035
+ const backgroundFeatures = [];
1036
+
1037
+ //#endregion
1038
+ //#region ../core/dist/dev/dom/store/selectors.js
1039
+ /** Select the buffer state (buffered ranges, percent buffered). */
1040
+ const selectBuffer = createSelector(bufferFeature);
1041
+ /** Select the controls state (controls visible, user-active). */
1042
+ const selectControls = createSelector(controlsFeature);
1043
+ /** Select the error state (error, dismissed, dismissError). */
1044
+ const selectError = createSelector(errorFeature);
1045
+ /** Select the fullscreen state (fullscreen active, availability). */
1046
+ const selectFullscreen = createSelector(fullscreenFeature);
1047
+ /** Select the PiP state (picture-in-picture active, availability). */
1048
+ const selectPiP = createSelector(pipFeature);
1049
+ /** Select the playback state (paused, ended, play, pause, toggle). */
1050
+ const selectPlayback = createSelector(playbackFeature);
1051
+ /** Select the playback rate state (playbackRate, playbackRates, setPlaybackRate). */
1052
+ const selectPlaybackRate = createSelector(playbackRateFeature);
1053
+ /** Select the source state (src, type). */
1054
+ const selectSource = createSelector(sourceFeature);
1055
+ /** Select the text track state (chapters cues, thumbnail cues). */
1056
+ const selectTextTrack = createSelector(textTrackFeature);
1057
+ /** Select the time state (currentTime, duration, seek). */
1058
+ const selectTime = createSelector(timeFeature);
1059
+ /** Select the volume state (volume, muted, setVolume, setMuted). */
1060
+ const selectVolume = createSelector(volumeFeature);
1061
+
1062
+ //#endregion
1063
+ //#region ../core/dist/dev/dom/ui/dismiss-layer.js
1064
+ function createDismissLayer(options) {
1065
+ const { transition } = options;
1066
+ const state = transition.state;
1067
+ const abort = new AbortController();
1068
+ let docAbort = null;
1069
+ function open() {
1070
+ if (abort.signal.aborted) return null;
1071
+ const { active, status } = state.current;
1072
+ if (active && status !== "ending") return null;
1073
+ if (status === "ending") transition.cancel();
1074
+ return transition.open();
1075
+ }
1076
+ function close(element) {
1077
+ const { active, status } = state.current;
1078
+ if (abort.signal.aborted || !active || status === "ending") return null;
1079
+ return transition.close(element);
1080
+ }
1081
+ function setupDocumentListeners() {
1082
+ cleanupDocumentListeners();
1083
+ if (typeof document === "undefined") return;
1084
+ docAbort = new AbortController();
1085
+ const { signal } = docAbort;
1086
+ listen(document, "keydown", handleKeydown, { signal });
1087
+ options.onDocumentActive?.(signal);
1088
+ }
1089
+ function cleanupDocumentListeners() {
1090
+ docAbort?.abort();
1091
+ docAbort = null;
1092
+ }
1093
+ function handleKeydown(event) {
1094
+ if (event.key !== "Escape") return;
1095
+ if (!state.current.active) return;
1096
+ if (!(options.closeOnEscape?.() ?? true)) return;
1097
+ options.onEscapeDismiss(event);
1098
+ }
1099
+ const unsubscribe = state.subscribe(() => {
1100
+ if (state.current.active) setupDocumentListeners();
1101
+ else cleanupDocumentListeners();
1102
+ });
1103
+ abort.signal.addEventListener("abort", () => {
1104
+ unsubscribe();
1105
+ transition.destroy();
1106
+ cleanupDocumentListeners();
1107
+ });
1108
+ function destroy() {
1109
+ if (abort.signal.aborted) return;
1110
+ abort.abort();
1111
+ }
1112
+ return {
1113
+ input: state,
1114
+ open,
1115
+ close,
1116
+ signal: abort.signal,
1117
+ destroy
1118
+ };
1119
+ }
1120
+
1121
+ //#endregion
1122
+ //#region ../core/dist/dev/dom/ui/button.js
1123
+ function createButton(options) {
1124
+ const { onActivate, isDisabled } = options;
1125
+ return {
1126
+ role: "button",
1127
+ tabIndex: 0,
1128
+ onClick(event) {
1129
+ if (isDisabled()) {
1130
+ event.preventDefault();
1131
+ return;
1132
+ }
1133
+ onActivate();
1134
+ },
1135
+ onPointerDown(event) {
1136
+ if (isDisabled()) event.preventDefault();
1137
+ },
1138
+ onMouseDown(event) {
1139
+ if (isDisabled()) event.preventDefault();
1140
+ },
1141
+ onKeyDown(event) {
1142
+ if (event.target !== event.currentTarget) return;
1143
+ if (isDisabled()) {
1144
+ if (event.key !== "Tab") event.preventDefault();
1145
+ return;
1146
+ }
1147
+ if (event.key === "Enter") {
1148
+ event.preventDefault();
1149
+ onActivate();
1150
+ } else if (event.key === " ") event.preventDefault();
1151
+ },
1152
+ onKeyUp(event) {
1153
+ if (event.target !== event.currentTarget) return;
1154
+ if (isDisabled()) return;
1155
+ if (event.key === " ") onActivate();
1156
+ }
1157
+ };
1158
+ }
1159
+
1160
+ //#endregion
1161
+ //#region ../core/dist/dev/dom/ui/popover/popover.js
1162
+ function createPopover(options) {
1163
+ const { onOpenChange, closeOnOutsideClick } = options;
1164
+ let triggerEl = null;
1165
+ let popupEl = null;
1166
+ let hoverTimeout = null;
1167
+ const capturedPointers = /* @__PURE__ */ new Set();
1168
+ const layer = createDismissLayer({
1169
+ transition: options.transition,
1170
+ closeOnEscape: options.closeOnEscape,
1171
+ onEscapeDismiss(event) {
1172
+ event.preventDefault();
1173
+ applyClose("escape", event);
1174
+ },
1175
+ onDocumentActive(signal) {
1176
+ listen(document, "pointerdown", handleDocumentPointerdown, {
1177
+ capture: true,
1178
+ signal
1179
+ });
1180
+ }
1181
+ });
1182
+ const state = layer.input;
1183
+ function clearHoverTimeout() {
1184
+ if (hoverTimeout !== null) {
1185
+ clearTimeout(hoverTimeout);
1186
+ hoverTimeout = null;
1187
+ }
1188
+ }
1189
+ function canHover() {
1190
+ return globalThis.matchMedia?.("(hover: hover)")?.matches ?? false;
1191
+ }
1192
+ function canOpenOnFocus() {
1193
+ if (!canHover()) return false;
1194
+ return globalThis.matchMedia?.("(pointer: fine)")?.matches ?? false;
1195
+ }
1196
+ function canToggleOnClick() {
1197
+ if (!options.openOnHover?.()) return true;
1198
+ return canHover();
1199
+ }
1200
+ /**
1201
+ * The transition handler manages animation lifecycle via `createState`:
1202
+ *
1203
+ * **Open:** `transition.open()` patches `{ active: true, status: 'starting' }`.
1204
+ * After one RAF it patches `{ status: 'idle' }` and the promise resolves.
1205
+ * Frameworks render `data-starting-style` / `data-ending-style` via
1206
+ * `getPopupAttrs(state)` — no imperative DOM mutation needed.
1207
+ *
1208
+ * **Close:** `transition.close(el)` patches `{ status: 'ending' }` (keeping
1209
+ * `active: true` so the element stays mounted). After a double-RAF it waits
1210
+ * for `getAnimations()` to settle, then patches `{ active: false, status: 'idle' }`.
1211
+ *
1212
+ * `onOpenChange` fires immediately (before animations).
1213
+ * `onOpenChangeComplete` fires after animations finish.
1214
+ */
1215
+ function applyOpen(reason, event) {
1216
+ const opening = layer.open();
1217
+ if (!opening) return;
1218
+ onOpenChange(true, event ? {
1219
+ reason,
1220
+ event
1221
+ } : { reason });
1222
+ opening.then(() => {
1223
+ if (layer.signal.aborted || !state.current.active) return;
1224
+ options.onOpenChangeComplete?.(true);
1225
+ });
1226
+ }
1227
+ function applyClose(reason, event) {
1228
+ const closing = layer.close(popupEl);
1229
+ if (!closing) return;
1230
+ onOpenChange(false, event ? {
1231
+ reason,
1232
+ event
1233
+ } : { reason });
1234
+ closing.then(() => {
1235
+ if (layer.signal.aborted) return;
1236
+ tryHidePopover(popupEl);
1237
+ options.onOpenChangeComplete?.(false);
1238
+ });
1239
+ }
1240
+ function open(reason = "click") {
1241
+ applyOpen(reason);
1242
+ }
1243
+ function close(reason = "click") {
1244
+ applyClose(reason);
1245
+ }
1246
+ function handleDocumentPointerdown(event) {
1247
+ if (!closeOnOutsideClick() || !state.current.active) return;
1248
+ const path = event.composedPath();
1249
+ if (triggerEl && path.includes(triggerEl) || popupEl && path.includes(popupEl)) return;
1250
+ applyClose("outside-click", event);
1251
+ }
1252
+ layer.signal.addEventListener("abort", () => {
1253
+ clearHoverTimeout();
1254
+ capturedPointers.clear();
1255
+ triggerEl = null;
1256
+ popupEl = null;
1257
+ });
1258
+ const triggerProps = {
1259
+ onClick(event) {
1260
+ if (!canToggleOnClick()) return;
1261
+ if (state.current.active && state.current.status !== "ending") applyClose("click", event);
1262
+ else applyOpen("click", event);
1263
+ },
1264
+ onPointerEnter(_event) {
1265
+ if (!options.openOnHover?.()) return;
1266
+ if (!canHover()) return;
1267
+ clearHoverTimeout();
1268
+ if (state.current.active) return;
1269
+ const delay = options.delay?.() ?? 300;
1270
+ hoverTimeout = setTimeout(() => applyOpen("hover"), delay);
1271
+ },
1272
+ onPointerLeave(_event) {
1273
+ if (!options.openOnHover?.()) return;
1274
+ if (!canHover()) return;
1275
+ clearHoverTimeout();
1276
+ if (!state.current.active) return;
1277
+ const closeDelay = options.closeDelay?.() ?? 0;
1278
+ hoverTimeout = setTimeout(() => applyClose("hover"), closeDelay);
1279
+ },
1280
+ onFocusIn(_event) {
1281
+ if (options.openOnHover?.()) {
1282
+ if (!canOpenOnFocus()) return;
1283
+ applyOpen("focus");
1284
+ }
1285
+ },
1286
+ onFocusOut(event) {
1287
+ const relatedTarget = event.relatedTarget;
1288
+ if (relatedTarget && (triggerEl?.contains(relatedTarget) || popupEl?.contains(relatedTarget))) return;
1289
+ if (options.openOnHover?.()) applyClose("blur");
1290
+ }
1291
+ };
1292
+ const popupProps = {
1293
+ onPointerEnter(_event) {
1294
+ if (!options.openOnHover?.()) return;
1295
+ clearHoverTimeout();
1296
+ },
1297
+ onPointerLeave(_event) {
1298
+ if (!options.openOnHover?.()) return;
1299
+ if (capturedPointers.size > 0) return;
1300
+ clearHoverTimeout();
1301
+ if (!state.current.active) return;
1302
+ const closeDelay = options.closeDelay?.() ?? 0;
1303
+ hoverTimeout = setTimeout(() => applyClose("hover"), closeDelay);
1304
+ },
1305
+ onGotPointerCapture(event) {
1306
+ capturedPointers.add(event.pointerId);
1307
+ },
1308
+ onLostPointerCapture(event) {
1309
+ capturedPointers.delete(event.pointerId);
1310
+ },
1311
+ onFocusOut(event) {
1312
+ const relatedTarget = event.relatedTarget;
1313
+ if (relatedTarget && (triggerEl?.contains(relatedTarget) || popupEl?.contains(relatedTarget))) return;
1314
+ applyClose("blur");
1315
+ }
1316
+ };
1317
+ function setTriggerElement(el) {
1318
+ triggerEl = el;
1319
+ }
1320
+ function setPopupElement(el) {
1321
+ if (!el && popupEl && state.current.active) tryHidePopover(popupEl);
1322
+ popupEl = el;
1323
+ if (el) {
1324
+ if (state.current.active) tryShowPopover(el);
1325
+ }
1326
+ }
1327
+ return {
1328
+ input: state,
1329
+ triggerProps,
1330
+ popupProps,
1331
+ get triggerElement() {
1332
+ return triggerEl;
1333
+ },
1334
+ setTriggerElement,
1335
+ setPopupElement,
1336
+ open,
1337
+ close,
1338
+ destroy: layer.destroy
1339
+ };
1340
+ }
1341
+
1342
+ //#endregion
1343
+ //#region ../core/dist/dev/core/ui/popover/popover-css-vars.js
1344
+ const PopoverCSSVars = {
1345
+ sideOffset: "--media-popover-side-offset",
1346
+ alignOffset: "--media-popover-align-offset",
1347
+ anchorWidth: "--media-popover-anchor-width",
1348
+ anchorHeight: "--media-popover-anchor-height",
1349
+ availableWidth: "--media-popover-available-width",
1350
+ availableHeight: "--media-popover-available-height"
1351
+ };
1352
+
1353
+ //#endregion
1354
+ //#region ../core/dist/dev/dom/ui/popover/popover-positioning.js
1355
+ const OPPOSITE_SIDE = {
1356
+ top: "bottom",
1357
+ bottom: "top",
1358
+ left: "right",
1359
+ right: "left"
1360
+ };
1361
+ /**
1362
+ * Get positioning styles for the popup element.
1363
+ *
1364
+ * When the browser supports CSS Anchor Positioning, returns native CSS properties
1365
+ * that reference the provided CSS var names for side/align offsets — no JS offset
1366
+ * values needed.
1367
+ *
1368
+ * When rects are provided and anchor positioning is unsupported, falls back to
1369
+ * manual JS-computed positioning. The caller must resolve offset CSS vars via
1370
+ * `getComputedStyle` and pass them as `offsets`.
1371
+ *
1372
+ * Returns camelCase keys for standard CSS properties and `--*` keys for
1373
+ * custom properties — compatible with both React's `style` prop and
1374
+ * `applyStyles()` from `@videojs/utils/dom`.
1375
+ */
1376
+ function getAnchorPositionStyle(anchorName, opts, triggerRect, popupRect, boundaryRect, offsets, cssVars = PopoverCSSVars) {
1377
+ if (supportsAnchorPositioning()) return getAnchorPositionCSS(anchorName, opts, cssVars);
1378
+ if (triggerRect && popupRect) return {
1379
+ ...getManualPositionStyle(triggerRect, popupRect, opts, offsets ?? {
1380
+ sideOffset: 0,
1381
+ alignOffset: 0
1382
+ }),
1383
+ ...boundaryRect ? getPositioningCSSVars(triggerRect, boundaryRect, opts.side, cssVars) : {},
1384
+ position: "fixed",
1385
+ inset: "auto",
1386
+ margin: "0"
1387
+ };
1388
+ return {};
1389
+ }
1390
+ /** Generate style to set on the trigger for CSS Anchor Positioning. */
1391
+ function getAnchorNameStyle(anchorName) {
1392
+ if (!supportsAnchorPositioning()) return {};
1393
+ return { anchorName: `--${anchorName}` };
1394
+ }
1395
+ function getAnchorPositionCSS(anchorName, opts, cssVars = PopoverCSSVars) {
1396
+ const SIDE_OFFSET_VAR = `var(${cssVars.sideOffset}, 0px)`;
1397
+ const ALIGN_OFFSET_VAR = `var(${cssVars.alignOffset}, 0px)`;
1398
+ const { side, align } = opts;
1399
+ const style = {
1400
+ positionAnchor: `--${anchorName}`,
1401
+ position: "fixed",
1402
+ inset: "auto",
1403
+ margin: "0",
1404
+ justifySelf: "normal",
1405
+ alignSelf: "normal",
1406
+ marginInlineStart: "0",
1407
+ marginBlockStart: "0"
1408
+ };
1409
+ const insetProp = OPPOSITE_SIDE[side];
1410
+ if (side === "top" || side === "bottom") {
1411
+ style[insetProp] = `calc(anchor(${side}) + ${SIDE_OFFSET_VAR})`;
1412
+ if (align === "start") style.left = `calc(anchor(left) + ${ALIGN_OFFSET_VAR})`;
1413
+ else if (align === "end") style.right = `calc(anchor(right) + ${ALIGN_OFFSET_VAR})`;
1414
+ else {
1415
+ style.justifySelf = "anchor-center";
1416
+ style.marginInlineStart = ALIGN_OFFSET_VAR;
1417
+ }
1418
+ } else {
1419
+ style[insetProp] = `calc(anchor(${side}) + ${SIDE_OFFSET_VAR})`;
1420
+ if (align === "start") style.top = `calc(anchor(top) + ${ALIGN_OFFSET_VAR})`;
1421
+ else if (align === "end") style.bottom = `calc(anchor(bottom) + ${ALIGN_OFFSET_VAR})`;
1422
+ else {
1423
+ style.alignSelf = "anchor-center";
1424
+ style.marginBlockStart = ALIGN_OFFSET_VAR;
1425
+ }
1426
+ }
1427
+ return style;
1428
+ }
1429
+ /**
1430
+ * Compute CSS variables for sizing constraints relative to the anchor/boundary.
1431
+ *
1432
+ * Accepts a `cssVars` map so the same logic works for both popover
1433
+ * (`--media-popover-*`) and tooltip (`--media-tooltip-*`) namespaces.
1434
+ */
1435
+ function getPositioningCSSVars(triggerRect, boundaryRect, side, cssVars = PopoverCSSVars) {
1436
+ const vars = {};
1437
+ vars[cssVars.anchorWidth] = `${triggerRect.width}px`;
1438
+ vars[cssVars.anchorHeight] = `${triggerRect.height}px`;
1439
+ if (side === "top" || side === "bottom") {
1440
+ vars[cssVars.availableHeight] = side === "top" ? `${triggerRect.top - boundaryRect.top}px` : `${boundaryRect.bottom - triggerRect.bottom}px`;
1441
+ vars[cssVars.availableWidth] = `${boundaryRect.width}px`;
1442
+ } else {
1443
+ vars[cssVars.availableWidth] = side === "left" ? `${triggerRect.left - boundaryRect.left}px` : `${boundaryRect.right - triggerRect.right}px`;
1444
+ vars[cssVars.availableHeight] = `${boundaryRect.height}px`;
1445
+ }
1446
+ return vars;
1447
+ }
1448
+ /**
1449
+ * Compute manual positioning when CSS Anchor Positioning is not supported.
1450
+ *
1451
+ * Returns inline `top`/`left` styles in **viewport coordinates** for use
1452
+ * with `position: fixed` (the popup is in the top layer). All rects from
1453
+ * `getBoundingClientRect()` are already viewport-relative.
1454
+ *
1455
+ * Offsets are resolved by the caller from CSS custom properties via
1456
+ * `getComputedStyle()` and passed as `offsets`.
1457
+ */
1458
+ function getManualPositionStyle(triggerRect, popupRect, opts, offsets = {
1459
+ sideOffset: 0,
1460
+ alignOffset: 0
1461
+ }) {
1462
+ const { side, align } = opts;
1463
+ const { sideOffset, alignOffset } = offsets;
1464
+ let top = 0;
1465
+ let left = 0;
1466
+ if (side === "top") top = triggerRect.top - popupRect.height - sideOffset;
1467
+ else if (side === "bottom") top = triggerRect.bottom + sideOffset;
1468
+ else if (side === "left") left = triggerRect.left - popupRect.width - sideOffset;
1469
+ else left = triggerRect.right + sideOffset;
1470
+ if (side === "top" || side === "bottom") if (align === "start") left = triggerRect.left + alignOffset;
1471
+ else if (align === "end") left = triggerRect.right - popupRect.width + alignOffset;
1472
+ else left = triggerRect.left + (triggerRect.width - popupRect.width) / 2 + alignOffset;
1473
+ else if (align === "start") top = triggerRect.top + alignOffset;
1474
+ else if (align === "end") top = triggerRect.bottom - popupRect.height + alignOffset;
1475
+ else top = triggerRect.top + (triggerRect.height - popupRect.height) / 2 + alignOffset;
1476
+ return {
1477
+ top: `${top}px`,
1478
+ left: `${left}px`
1479
+ };
1480
+ }
1481
+ /**
1482
+ * Read side-offset and align-offset CSS custom properties from the
1483
+ * popup element's computed style, returning numeric pixel values.
1484
+ */
1485
+ function resolveOffsets(el, cssVars = PopoverCSSVars) {
1486
+ const computed = getComputedStyle(el);
1487
+ return {
1488
+ sideOffset: resolveCSSLength(el, computed.getPropertyValue(cssVars.sideOffset)),
1489
+ alignOffset: resolveCSSLength(el, computed.getPropertyValue(cssVars.alignOffset))
1490
+ };
1491
+ }
1492
+ /**
1493
+ * Measure the popup's layout box for positioning.
1494
+ *
1495
+ * `getBoundingClientRect()` includes active transforms, which causes the
1496
+ * fallback position to drift while opening/closing animations scale the popup.
1497
+ * Using `offsetWidth`/`offsetHeight` preserves the untransformed size.
1498
+ */
1499
+ function getPopupPositionRect(el) {
1500
+ const rect = el.getBoundingClientRect();
1501
+ const width = el.offsetWidth || rect.width;
1502
+ const height = el.offsetHeight || rect.height;
1503
+ const adjustedRect = {
1504
+ ...rect,
1505
+ width,
1506
+ height,
1507
+ right: rect.left + width,
1508
+ bottom: rect.top + height
1509
+ };
1510
+ return {
1511
+ ...adjustedRect,
1512
+ toJSON: () => adjustedRect
1513
+ };
1514
+ }
1515
+
1516
+ //#endregion
1517
+ //#region ../utils/dist/number/number.js
1518
+ /** Clamp a value between min and max (inclusive). */
1519
+ function clamp(value, min, max) {
1520
+ return Math.max(min, Math.min(max, value));
1521
+ }
1522
+ /** Snap a value to the nearest step, offset from min. */
1523
+ function roundToStep(value, step, min) {
1524
+ const nearest = Math.round((value - min) / step) * step + min;
1525
+ const dot = `${step}`.indexOf(".");
1526
+ return dot === -1 ? nearest : Number(nearest.toFixed(`${step}`.length - dot - 1));
1527
+ }
1528
+
1529
+ //#endregion
1530
+ //#region ../core/dist/dev/dom/utils/pointer.js
1531
+ /** Convert a pointer event position to a 0–100 percent along an element's rect. */
1532
+ function getPercentFromPointerEvent(event, rect, orientation, isRTL) {
1533
+ let ratio;
1534
+ if (orientation === "vertical") ratio = 1 - (event.clientY - rect.top) / rect.height;
1535
+ else if (isRTL) ratio = (rect.right - event.clientX) / rect.width;
1536
+ else ratio = (event.clientX - rect.left) / rect.width;
1537
+ if (!Number.isFinite(ratio)) return 0;
1538
+ return clamp(ratio * 100, 0, 100);
1539
+ }
1540
+
1541
+ //#endregion
1542
+ //#region ../core/dist/dev/dom/ui/slider.js
1543
+ /** Intentional drag threshold — number of pointermove events before drag starts. */
1544
+ const DRAG_THRESHOLD = 2;
1545
+ function createSlider(options) {
1546
+ const input = createState({
1547
+ pointerPercent: 0,
1548
+ dragPercent: 0,
1549
+ dragging: false,
1550
+ pointing: false,
1551
+ focused: false
1552
+ });
1553
+ const abort = new AbortController();
1554
+ const commitThrottleMs = options.commitThrottle ?? 0;
1555
+ let isDragging = false, moveCount = 0, cachedRTL = false, cachedRect = null, capturedPointerId = null;
1556
+ const throttledCommit = commitThrottleMs > 0 ? throttle((percent) => options.onValueCommit?.(percent), commitThrottleMs) : null;
1557
+ function releaseCapture() {
1558
+ if (isNull(capturedPointerId)) return;
1559
+ const id = capturedPointerId;
1560
+ capturedPointerId = null;
1561
+ try {
1562
+ options.getElement().releasePointerCapture(id);
1563
+ } catch {}
1564
+ }
1565
+ function endDrag() {
1566
+ if (!isDragging) input.patch({ pointing: false });
1567
+ else {
1568
+ isDragging = false;
1569
+ input.patch({
1570
+ dragging: false,
1571
+ pointing: false
1572
+ });
1573
+ options.onDragEnd?.();
1574
+ }
1575
+ cleanup();
1576
+ }
1577
+ function cleanup() {
1578
+ throttledCommit?.cancel();
1579
+ capturedPointerId = null;
1580
+ cachedRect = null;
1581
+ }
1582
+ const rootProps = {
1583
+ onPointerDown(event) {
1584
+ if (options.isDisabled()) return;
1585
+ event.preventDefault();
1586
+ const el = options.getElement();
1587
+ cachedRect = el.getBoundingClientRect();
1588
+ cachedRTL = options.isRTL();
1589
+ moveCount = 0;
1590
+ releaseCapture();
1591
+ capturedPointerId = event.pointerId;
1592
+ el.setPointerCapture(event.pointerId);
1593
+ const percent = getPercentFromPointerEvent(event, cachedRect, options.getOrientation(), cachedRTL);
1594
+ input.patch({
1595
+ pointing: true,
1596
+ pointerPercent: percent,
1597
+ dragPercent: percent
1598
+ });
1599
+ options.onValueChange?.(percent);
1600
+ options.getThumbElement?.()?.focus({
1601
+ preventScroll: true,
1602
+ focusVisible: false
1603
+ });
1604
+ },
1605
+ onPointerMove(event) {
1606
+ if (options.isDisabled()) return;
1607
+ if (!isNull(capturedPointerId)) {
1608
+ if (event.pointerType !== "touch" && event.buttons === 0) {
1609
+ endDrag();
1610
+ return;
1611
+ }
1612
+ moveCount++;
1613
+ const percent = getPercentFromPointerEvent(event, cachedRect, options.getOrientation(), cachedRTL);
1614
+ if (!isDragging && moveCount >= DRAG_THRESHOLD) {
1615
+ isDragging = true;
1616
+ input.patch({
1617
+ dragging: true,
1618
+ dragPercent: percent,
1619
+ pointerPercent: percent
1620
+ });
1621
+ options.onDragStart?.();
1622
+ options.onValueChange?.(percent);
1623
+ throttledCommit?.(percent);
1624
+ } else if (isDragging) {
1625
+ input.patch({
1626
+ dragPercent: percent,
1627
+ pointerPercent: percent
1628
+ });
1629
+ options.onValueChange?.(percent);
1630
+ throttledCommit?.(percent);
1631
+ } else input.patch({ pointerPercent: percent });
1632
+ return;
1633
+ }
1634
+ const percent = getPercentFromPointerEvent(event, options.getElement().getBoundingClientRect(), options.getOrientation(), options.isRTL());
1635
+ input.patch({
1636
+ pointing: true,
1637
+ pointerPercent: percent
1638
+ });
1639
+ },
1640
+ onPointerUp(event) {
1641
+ if (isNull(capturedPointerId)) return;
1642
+ const percent = getPercentFromPointerEvent(event, cachedRect, options.getOrientation(), cachedRTL);
1643
+ throttledCommit?.cancel();
1644
+ options.onValueCommit?.(percent);
1645
+ },
1646
+ onPointerLeave() {
1647
+ if (!isNull(capturedPointerId)) return;
1648
+ input.patch({ pointing: false });
1649
+ },
1650
+ onLostPointerCapture() {
1651
+ endDrag();
1652
+ }
1653
+ };
1654
+ const thumbProps = {
1655
+ onKeyDown(event) {
1656
+ if (options.isDisabled()) {
1657
+ if (event.key !== "Tab") event.preventDefault();
1658
+ return;
1659
+ }
1660
+ const stepPercent = options.getStepPercent();
1661
+ const largeStepPercent = options.getLargeStepPercent();
1662
+ const rounded = roundToStep(options.getPercent(), stepPercent, 0);
1663
+ const horizontalSign = options.isRTL() ? -1 : 1;
1664
+ const step = event.shiftKey ? largeStepPercent : stepPercent;
1665
+ let newPercent = null;
1666
+ switch (event.key) {
1667
+ case "ArrowRight":
1668
+ newPercent = rounded + step * horizontalSign;
1669
+ break;
1670
+ case "ArrowLeft":
1671
+ newPercent = rounded - step * horizontalSign;
1672
+ break;
1673
+ case "ArrowUp":
1674
+ newPercent = rounded + step;
1675
+ break;
1676
+ case "ArrowDown":
1677
+ newPercent = rounded - step;
1678
+ break;
1679
+ case "PageUp":
1680
+ newPercent = rounded + largeStepPercent;
1681
+ break;
1682
+ case "PageDown":
1683
+ newPercent = rounded - largeStepPercent;
1684
+ break;
1685
+ case "Home":
1686
+ newPercent = 0;
1687
+ break;
1688
+ case "End":
1689
+ newPercent = 100;
1690
+ break;
1691
+ default:
1692
+ if (!event.metaKey && !event.ctrlKey && !event.altKey && event.key >= "0" && event.key <= "9") newPercent = Number(event.key) * 10;
1693
+ break;
1694
+ }
1695
+ if (newPercent !== null) {
1696
+ event.preventDefault();
1697
+ newPercent = clamp(newPercent, 0, 100);
1698
+ input.patch({
1699
+ pointerPercent: newPercent,
1700
+ dragPercent: newPercent
1701
+ });
1702
+ options.onValueChange?.(newPercent);
1703
+ options.onValueCommit?.(newPercent);
1704
+ }
1705
+ },
1706
+ onFocus() {
1707
+ input.patch({ focused: true });
1708
+ },
1709
+ onBlur() {
1710
+ input.patch({ focused: false });
1711
+ }
1712
+ };
1713
+ function adjustForAlignment(state) {
1714
+ if (!options.adjustPercent || state.thumbAlignment !== "edge") return state;
1715
+ const rootEl = options.getElement();
1716
+ const thumbEl = options.getThumbElement?.();
1717
+ if (!thumbEl) return state;
1718
+ const isHorizontal = state.orientation === "horizontal";
1719
+ const thumbSize = isHorizontal ? thumbEl.offsetWidth : thumbEl.offsetHeight;
1720
+ const trackSize = isHorizontal ? rootEl.offsetWidth : rootEl.offsetHeight;
1721
+ return {
1722
+ ...state,
1723
+ fillPercent: options.adjustPercent(state.fillPercent, thumbSize, trackSize),
1724
+ pointerPercent: options.adjustPercent(state.pointerPercent, thumbSize, trackSize)
1725
+ };
1726
+ }
1727
+ let resizeObserver = null;
1728
+ if (options.onResize) {
1729
+ resizeObserver = new ResizeObserver(() => options.onResize());
1730
+ resizeObserver.observe(options.getElement());
1731
+ }
1732
+ return {
1733
+ input,
1734
+ rootProps,
1735
+ rootStyle: {
1736
+ touchAction: "none",
1737
+ userSelect: "none"
1738
+ },
1739
+ thumbProps,
1740
+ adjustForAlignment,
1741
+ destroy() {
1742
+ if (abort.signal.aborted) return;
1743
+ abort.abort();
1744
+ resizeObserver?.disconnect();
1745
+ releaseCapture();
1746
+ cleanup();
1747
+ }
1748
+ };
1749
+ }
1750
+
1751
+ //#endregion
1752
+ //#region ../core/dist/dev/core/ui/slider/slider-css-vars.js
1753
+ /** CSS custom property names for slider visual state. */
1754
+ const SliderCSSVars = {
1755
+ fill: "--media-slider-fill",
1756
+ pointer: "--media-slider-pointer",
1757
+ buffer: "--media-slider-buffer"
1758
+ };
1759
+
1760
+ //#endregion
1761
+ //#region ../core/dist/dev/dom/ui/slider-css-vars.js
1762
+ function getSliderCSSVars(state) {
1763
+ return {
1764
+ [SliderCSSVars.fill]: `${state.fillPercent.toFixed(3)}%`,
1765
+ [SliderCSSVars.pointer]: `${state.pointerPercent.toFixed(3)}%`
1766
+ };
1767
+ }
1768
+ function getTimeSliderCSSVars(state) {
1769
+ return {
1770
+ ...getSliderCSSVars(state),
1771
+ [SliderCSSVars.buffer]: `${state.bufferPercent.toFixed(3)}%`
1772
+ };
1773
+ }
1774
+ /** Compute structural positioning styles for a slider preview element. */
1775
+ function getSliderPreviewStyle(width, overflow) {
1776
+ const halfWidth = width / 2;
1777
+ return {
1778
+ position: "absolute",
1779
+ left: overflow === "visible" ? `calc(var(${SliderCSSVars.pointer}) - ${halfWidth}px)` : `min(max(0px, calc(var(${SliderCSSVars.pointer}) - ${halfWidth}px)), calc(100% - ${width}px))`,
1780
+ width: "max-content",
1781
+ pointerEvents: "none"
1782
+ };
1783
+ }
1784
+
1785
+ //#endregion
1786
+ //#region ../core/dist/dev/core/ui/thumbnail/thumbnail-core.js
1787
+ var ThumbnailCore = class {
1788
+ findActiveThumbnail(thumbnails, time) {
1789
+ if (thumbnails.length === 0) return void 0;
1790
+ let low = 0;
1791
+ let high = thumbnails.length - 1;
1792
+ let result;
1793
+ while (low <= high) {
1794
+ const mid = low + high >>> 1;
1795
+ const image = thumbnails[mid];
1796
+ if (time >= image.startTime) {
1797
+ result = image;
1798
+ low = mid + 1;
1799
+ } else high = mid - 1;
1800
+ }
1801
+ return result;
1802
+ }
1803
+ /**
1804
+ * Parse CSS constraint strings into numeric `ThumbnailConstraints`.
1805
+ *
1806
+ * Accepts any object with string `minWidth`/`maxWidth`/`minHeight`/`maxHeight`
1807
+ * properties — `CSSStyleDeclaration` satisfies this structurally.
1808
+ */
1809
+ parseConstraints(raw) {
1810
+ const minW = parseFloat(raw.minWidth);
1811
+ const maxW = parseFloat(raw.maxWidth);
1812
+ const minH = parseFloat(raw.minHeight);
1813
+ const maxH = parseFloat(raw.maxHeight);
1814
+ return {
1815
+ minWidth: Number.isFinite(minW) ? minW : 0,
1816
+ maxWidth: Number.isFinite(maxW) ? maxW : Infinity,
1817
+ minHeight: Number.isFinite(minH) ? minH : 0,
1818
+ maxHeight: Number.isFinite(maxH) ? maxH : Infinity
1819
+ };
1820
+ }
1821
+ /**
1822
+ * Calculate a uniform scale factor that fits `tileWidth × tileHeight` within the
1823
+ * given CSS min/max constraints while preserving aspect ratio.
1824
+ *
1825
+ * - Scales down when the tile exceeds max constraints.
1826
+ * - Scales up when the tile is smaller than min constraints.
1827
+ * - Returns `1` when no scaling is needed.
1828
+ */
1829
+ calculateScale(tileWidth, tileHeight, constraints) {
1830
+ const { minWidth, maxWidth, minHeight, maxHeight } = constraints;
1831
+ const maxRatio = Math.min(maxWidth / tileWidth, maxHeight / tileHeight);
1832
+ const minRatio = Math.max(minWidth / tileWidth, minHeight / tileHeight);
1833
+ if (Number.isFinite(maxRatio) && maxRatio < 1) return maxRatio;
1834
+ if (Number.isFinite(minRatio) && minRatio > 1) return minRatio;
1835
+ return 1;
1836
+ }
1837
+ /**
1838
+ * Compute container and image dimensions for the current thumbnail, scaled to
1839
+ * fit within the element's CSS min/max constraints.
1840
+ *
1841
+ * The container clips the sprite sheet via `overflow: hidden`, and the image is
1842
+ * positioned with `transform: translate()` to show the correct tile.
1843
+ */
1844
+ resize(thumbnail, imgNaturalWidth, imgNaturalHeight, constraints) {
1845
+ const tileWidth = thumbnail.width ?? imgNaturalWidth;
1846
+ const tileHeight = thumbnail.height ?? imgNaturalHeight;
1847
+ if (!tileWidth || !tileHeight) return void 0;
1848
+ const scale = this.calculateScale(tileWidth, tileHeight, constraints);
1849
+ const coordX = thumbnail.coords?.x ?? 0;
1850
+ const coordY = thumbnail.coords?.y ?? 0;
1851
+ const inset = scale !== 1 ? 1 : 0;
1852
+ return {
1853
+ scale,
1854
+ containerWidth: Math.max(0, Math.floor(tileWidth * scale) - inset * 2),
1855
+ containerHeight: Math.max(0, Math.floor(tileHeight * scale) - inset * 2),
1856
+ imageWidth: Math.ceil(imgNaturalWidth * scale),
1857
+ imageHeight: Math.ceil(imgNaturalHeight * scale),
1858
+ offsetX: Math.ceil(coordX * scale) + inset,
1859
+ offsetY: Math.ceil(coordY * scale) + inset
1860
+ };
1861
+ }
1862
+ getState(loading, error, thumbnail) {
1863
+ return {
1864
+ loading,
1865
+ error,
1866
+ hidden: !loading && !thumbnail
1867
+ };
1868
+ }
1869
+ getAttrs(_state) {
1870
+ return {
1871
+ role: "img",
1872
+ "aria-hidden": "true"
1873
+ };
1874
+ }
1875
+ };
1876
+
1877
+ //#endregion
1878
+ //#region ../core/dist/dev/dom/ui/thumbnail.js
1879
+ function createThumbnail(options) {
1880
+ const { getContainer, getImg, onStateChange } = options;
1881
+ const core = new ThumbnailCore();
1882
+ const abort = new AbortController();
1883
+ const signal = abort.signal;
1884
+ let loading = false;
1885
+ let error = false;
1886
+ let naturalWidth = 0;
1887
+ let naturalHeight = 0;
1888
+ let lastSrc = "";
1889
+ let imgBound = false;
1890
+ let resizeObserver = null;
1891
+ function onImgLoad() {
1892
+ const img = getImg();
1893
+ if (img) {
1894
+ naturalWidth = img.naturalWidth;
1895
+ naturalHeight = img.naturalHeight;
1896
+ }
1897
+ loading = false;
1898
+ error = false;
1899
+ onStateChange();
1900
+ }
1901
+ function onImgError() {
1902
+ loading = false;
1903
+ error = true;
1904
+ onStateChange();
1905
+ }
1906
+ function bindImg(img) {
1907
+ listen(img, "load", onImgLoad, { signal });
1908
+ listen(img, "error", onImgError, { signal });
1909
+ }
1910
+ function ensureBindings() {
1911
+ if (!imgBound) {
1912
+ const img = getImg();
1913
+ if (img) {
1914
+ bindImg(img);
1915
+ imgBound = true;
1916
+ }
1917
+ }
1918
+ if (!resizeObserver) {
1919
+ const container = getContainer();
1920
+ if (container) {
1921
+ resizeObserver = new ResizeObserver(onStateChange);
1922
+ resizeObserver.observe(container);
1923
+ }
1924
+ }
1925
+ }
1926
+ function updateSrc(url) {
1927
+ ensureBindings();
1928
+ const src = url ?? "";
1929
+ if (src === lastSrc) return;
1930
+ lastSrc = src;
1931
+ if (src) {
1932
+ loading = true;
1933
+ error = false;
1934
+ } else {
1935
+ loading = false;
1936
+ error = false;
1937
+ naturalWidth = 0;
1938
+ naturalHeight = 0;
1939
+ }
1940
+ }
1941
+ function connect() {
1942
+ ensureBindings();
1943
+ const img = getImg();
1944
+ if (img?.complete && lastSrc) {
1945
+ if (img.naturalWidth > 0) {
1946
+ naturalWidth = img.naturalWidth;
1947
+ naturalHeight = img.naturalHeight;
1948
+ loading = false;
1949
+ error = false;
1950
+ } else {
1951
+ loading = false;
1952
+ error = true;
1953
+ }
1954
+ onStateChange();
1955
+ }
1956
+ }
1957
+ function destroy() {
1958
+ abort.abort();
1959
+ resizeObserver?.disconnect();
1960
+ resizeObserver = null;
1961
+ }
1962
+ return {
1963
+ get loading() {
1964
+ return loading;
1965
+ },
1966
+ get error() {
1967
+ return error;
1968
+ },
1969
+ get naturalWidth() {
1970
+ return naturalWidth;
1971
+ },
1972
+ get naturalHeight() {
1973
+ return naturalHeight;
1974
+ },
1975
+ readConstraints() {
1976
+ const el = getContainer();
1977
+ if (!el) return {
1978
+ minWidth: 0,
1979
+ maxWidth: Infinity,
1980
+ minHeight: 0,
1981
+ maxHeight: Infinity
1982
+ };
1983
+ return core.parseConstraints(getComputedStyle(el));
1984
+ },
1985
+ updateSrc,
1986
+ connect,
1987
+ destroy
1988
+ };
1989
+ }
1990
+
1991
+ //#endregion
1992
+ //#region ../core/dist/dev/dom/ui/tooltip/tooltip.js
1993
+ /** Map popover reasons to tooltip reasons, filtering out click/outside-click. */
1994
+ const REASON_MAP = {
1995
+ hover: "hover",
1996
+ focus: "focus",
1997
+ escape: "escape",
1998
+ blur: "blur"
1999
+ };
2000
+ function createTooltip(options) {
2001
+ const popoverOpts = {
2002
+ transition: options.transition,
2003
+ onOpenChange(open, details) {
2004
+ const reason = REASON_MAP[details.reason];
2005
+ if (!reason) return;
2006
+ const group = options.group?.();
2007
+ if (open) group?.notifyOpen();
2008
+ else group?.notifyClose();
2009
+ const tooltipDetails = details.event ? {
2010
+ reason,
2011
+ event: details.event
2012
+ } : { reason };
2013
+ options.onOpenChange(open, tooltipDetails);
2014
+ },
2015
+ closeOnEscape: () => true,
2016
+ closeOnOutsideClick: () => false,
2017
+ openOnHover: () => true,
2018
+ delay: () => {
2019
+ const group = options.group?.();
2020
+ if (group?.shouldSkipDelay()) return 0;
2021
+ return options.delay?.() ?? group?.delay ?? 600;
2022
+ },
2023
+ closeDelay: () => {
2024
+ const group = options.group?.();
2025
+ return options.closeDelay?.() ?? group?.closeDelay ?? 0;
2026
+ }
2027
+ };
2028
+ if (options.onOpenChangeComplete) popoverOpts.onOpenChangeComplete = options.onOpenChangeComplete;
2029
+ const popover = createPopover(popoverOpts);
2030
+ let isPointerDown = false;
2031
+ const { onClick: _, ...baseTriggerProps } = popover.triggerProps;
2032
+ const triggerProps = {
2033
+ ...baseTriggerProps,
2034
+ onPointerDown() {
2035
+ isPointerDown = true;
2036
+ },
2037
+ onPointerEnter(event) {
2038
+ if (options.disabled?.()) return;
2039
+ if (event.pointerType === "touch") return;
2040
+ baseTriggerProps.onPointerEnter(event);
2041
+ },
2042
+ onFocusIn(event) {
2043
+ if (options.disabled?.()) return;
2044
+ if (isPointerDown) {
2045
+ isPointerDown = false;
2046
+ return;
2047
+ }
2048
+ baseTriggerProps.onFocusIn(event);
2049
+ }
2050
+ };
2051
+ const popupProps = {
2052
+ ...popover.popupProps,
2053
+ onPointerEnter(event) {
2054
+ if (options.disableHoverablePopup?.()) return;
2055
+ popover.popupProps.onPointerEnter(event);
2056
+ }
2057
+ };
2058
+ return {
2059
+ ...popover,
2060
+ triggerProps,
2061
+ popupProps,
2062
+ get triggerElement() {
2063
+ return popover.triggerElement;
2064
+ },
2065
+ open: () => popover.open("hover"),
2066
+ close: () => popover.close("hover")
2067
+ };
2068
+ }
2069
+
2070
+ //#endregion
2071
+ //#region ../core/dist/dev/dom/ui/transition.js
2072
+ /**
2073
+ * Manages open/close transition lifecycle via `createState`.
2074
+ *
2075
+ * **Open:** patches `{ active: true, status: 'starting' }`, then after a
2076
+ * double-RAF patches `{ status: 'idle' }` so the browser paints the
2077
+ * initial ("from") state before transitioning.
2078
+ *
2079
+ * **Close:** patches `{ status: 'ending' }` (keeping `active: true` so the
2080
+ * element stays mounted), then after a double-RAF waits for
2081
+ * `getAnimations()` to settle before patching `{ active: false, status: 'idle' }`.
2082
+ */
2083
+ function createTransition() {
2084
+ const state = createState({
2085
+ active: false,
2086
+ status: "idle"
2087
+ });
2088
+ let destroyed = false;
2089
+ let rafId1 = 0;
2090
+ let rafId2 = 0;
2091
+ function open() {
2092
+ cancelAnimationFrame(rafId1);
2093
+ cancelAnimationFrame(rafId2);
2094
+ rafId1 = 0;
2095
+ rafId2 = 0;
2096
+ state.patch({
2097
+ active: true,
2098
+ status: "starting"
2099
+ });
2100
+ return new Promise((resolve) => {
2101
+ rafId1 = requestAnimationFrame(() => {
2102
+ rafId1 = 0;
2103
+ rafId2 = requestAnimationFrame(() => {
2104
+ rafId2 = 0;
2105
+ if (destroyed || !state.current.active) return resolve();
2106
+ state.patch({ status: "idle" });
2107
+ resolve();
2108
+ });
2109
+ });
2110
+ });
2111
+ }
2112
+ function close(el) {
2113
+ cancelAnimationFrame(rafId1);
2114
+ cancelAnimationFrame(rafId2);
2115
+ rafId1 = 0;
2116
+ rafId2 = 0;
2117
+ state.patch({ status: "ending" });
2118
+ return new Promise((resolve) => {
2119
+ rafId1 = requestAnimationFrame(() => {
2120
+ rafId1 = 0;
2121
+ rafId2 = requestAnimationFrame(() => {
2122
+ rafId2 = 0;
2123
+ if (destroyed) return resolve();
2124
+ waitForAnimations(el).finally(() => {
2125
+ if (destroyed || state.current.status !== "ending") return resolve();
2126
+ state.patch({
2127
+ active: false,
2128
+ status: "idle"
2129
+ });
2130
+ resolve();
2131
+ });
2132
+ });
2133
+ });
2134
+ });
2135
+ }
2136
+ function cancel() {
2137
+ cancelAnimationFrame(rafId1);
2138
+ cancelAnimationFrame(rafId2);
2139
+ rafId1 = 0;
2140
+ rafId2 = 0;
2141
+ if (state.current.status !== "idle") state.patch({ status: "idle" });
2142
+ }
2143
+ return {
2144
+ state,
2145
+ open,
2146
+ close,
2147
+ cancel,
2148
+ destroy() {
2149
+ if (destroyed) return;
2150
+ destroyed = true;
2151
+ cancel();
2152
+ }
2153
+ };
2154
+ }
2155
+ function waitForAnimations(el) {
2156
+ if (!el) return Promise.resolve();
2157
+ const animations = el.getAnimations?.() ?? [];
2158
+ if (animations.length === 0) return Promise.resolve();
2159
+ return Promise.all(animations.map((a) => a.finished)).then(noop, noop);
2160
+ }
2161
+
2162
+ //#endregion
2163
+ //#region ../core/dist/dev/dom/utils/element-props.js
2164
+ /**
2165
+ * Apply props to a DOM element.
2166
+ *
2167
+ * Handles both attributes and event listeners:
2168
+ * - Event props (onClick, onKeyDown, etc.) are attached as listeners
2169
+ * - Boolean props: `true` sets empty attribute, `false` removes
2170
+ * - `undefined` removes the attribute
2171
+ * - Other props are set as string attributes
2172
+ */
2173
+ function applyElementProps(element, props, options) {
2174
+ const signal = options?.signal;
2175
+ for (const [key, value] of Object.entries(props)) if (isFunction(value) && key.startsWith("on")) listen(element, key.slice(2).toLowerCase(), value, signal ? { signal } : void 0);
2176
+ else if (isUndefined(value) || value === false) element.removeAttribute(key);
2177
+ else if (value === true) element.setAttribute(key, "");
2178
+ else element.setAttribute(key, String(value));
2179
+ }
2180
+
2181
+ //#endregion
2182
+ //#region ../core/dist/dev/dom/utils/log.js
2183
+ const warned = /* @__PURE__ */ new Set();
2184
+ function logMissingFeature(displayName, featureName) {
2185
+ const key = `${displayName}:${featureName}`;
2186
+ if (warned.has(key)) return;
2187
+ warned.add(key);
2188
+ console.warn(`${displayName} requires ${featureName} feature`);
2189
+ }
2190
+
2191
+ //#endregion
2192
+ //#region ../core/dist/dev/dom/utils/state-data-attrs.js
2193
+ /**
2194
+ * Apply state as data attributes to an element.
2195
+ *
2196
+ * - `true` → sets `data-keyname=""`
2197
+ * - truthy string/number → sets `data-keyname="value"`
2198
+ * - falsy → removes the attribute
2199
+ *
2200
+ * @example
2201
+ * ```ts
2202
+ * const state = { paused: true, ended: false };
2203
+ * applyStateDataAttrs(element, state);
2204
+ * // element has data-paused="", data-ended is removed
2205
+ * ```
2206
+ */
2207
+ function applyStateDataAttrs(element, state, map) {
2208
+ for (const key in state) {
2209
+ if (map && !(key in map)) continue;
2210
+ const name = map?.[key] ?? toDataAttrName(key), value = state[key];
2211
+ if (value === true) element.setAttribute(name, "");
2212
+ else if (value) element.setAttribute(name, String(value));
2213
+ else element.removeAttribute(name);
2214
+ }
2215
+ }
2216
+ function toDataAttrName(key) {
2217
+ return `data-${key.toLowerCase()}`;
2218
+ }
2219
+
2220
+ //#endregion
2221
+ //#region ../../node_modules/.pnpm/@lit+context@1.1.6/node_modules/@lit/context/development/lib/controllers/context-consumer.js
2222
+ /**
2223
+ * @license
2224
+ * Copyright 2021 Google LLC
2225
+ * SPDX-License-Identifier: BSD-3-Clause
2226
+ */
2227
+ /**
2228
+ * A ReactiveController which adds context consuming behavior to a custom
2229
+ * element by dispatching `context-request` events.
2230
+ *
2231
+ * When the host element is connected to the document it will emit a
2232
+ * `context-request` event with its context key. When the context request
2233
+ * is satisfied the controller will invoke the callback, if present, and
2234
+ * trigger a host update so it can respond to the new value.
2235
+ *
2236
+ * It will also call the dispose method given by the provider when the
2237
+ * host element is disconnected.
2238
+ */
2239
+ var ContextConsumer = class {
2240
+ constructor(host, contextOrOptions, callback, subscribe) {
2241
+ this.subscribe = false;
2242
+ this.provided = false;
2243
+ this.value = void 0;
2244
+ this._callback = (value, unsubscribe) => {
2245
+ if (this.unsubscribe) {
2246
+ if (this.unsubscribe !== unsubscribe) {
2247
+ this.provided = false;
2248
+ this.unsubscribe();
2249
+ }
2250
+ if (!this.subscribe) this.unsubscribe();
2251
+ }
2252
+ this.value = value;
2253
+ this.host.requestUpdate();
2254
+ if (!this.provided || this.subscribe) {
2255
+ this.provided = true;
2256
+ if (this.callback) this.callback(value, unsubscribe);
2257
+ }
2258
+ this.unsubscribe = unsubscribe;
2259
+ };
2260
+ this.host = host;
2261
+ if (contextOrOptions.context !== void 0) {
2262
+ const options = contextOrOptions;
2263
+ this.context = options.context;
2264
+ this.callback = options.callback;
2265
+ this.subscribe = options.subscribe ?? false;
2266
+ } else {
2267
+ this.context = contextOrOptions;
2268
+ this.callback = callback;
2269
+ this.subscribe = subscribe ?? false;
2270
+ }
2271
+ this.host.addController(this);
2272
+ }
2273
+ hostConnected() {
2274
+ this.dispatchRequest();
2275
+ }
2276
+ hostDisconnected() {
2277
+ if (this.unsubscribe) {
2278
+ this.unsubscribe();
2279
+ this.unsubscribe = void 0;
2280
+ }
2281
+ }
2282
+ dispatchRequest() {
2283
+ this.host.dispatchEvent(new ContextRequestEvent(this.context, this.host, this._callback, this.subscribe));
2284
+ }
2285
+ };
2286
+
2287
+ //#endregion
2288
+ //#region ../../node_modules/.pnpm/@lit+context@1.1.6/node_modules/@lit/context/development/lib/value-notifier.js
2289
+ /**
2290
+ * @license
2291
+ * Copyright 2021 Google LLC
2292
+ * SPDX-License-Identifier: BSD-3-Clause
2293
+ */
2294
+ /**
2295
+ * A simple class which stores a value, and triggers registered callbacks when
2296
+ * the value is changed via its setter.
2297
+ *
2298
+ * An implementor might use other observable patterns such as MobX or Redux to
2299
+ * get behavior like this. But this is a pretty minimal approach that will
2300
+ * likely work for a number of use cases.
2301
+ */
2302
+ var ValueNotifier = class {
2303
+ get value() {
2304
+ return this._value;
2305
+ }
2306
+ set value(v) {
2307
+ this.setValue(v);
2308
+ }
2309
+ setValue(v, force = false) {
2310
+ const update = force || !Object.is(v, this._value);
2311
+ this._value = v;
2312
+ if (update) this.updateObservers();
2313
+ }
2314
+ constructor(defaultValue) {
2315
+ this.subscriptions = /* @__PURE__ */ new Map();
2316
+ this.updateObservers = () => {
2317
+ for (const [callback, { disposer }] of this.subscriptions) callback(this._value, disposer);
2318
+ };
2319
+ if (defaultValue !== void 0) this.value = defaultValue;
2320
+ }
2321
+ addCallback(callback, consumerHost, subscribe) {
2322
+ if (!subscribe) {
2323
+ callback(this.value);
2324
+ return;
2325
+ }
2326
+ if (!this.subscriptions.has(callback)) this.subscriptions.set(callback, {
2327
+ disposer: () => {
2328
+ this.subscriptions.delete(callback);
2329
+ },
2330
+ consumerHost
2331
+ });
2332
+ const { disposer } = this.subscriptions.get(callback);
2333
+ callback(this.value, disposer);
2334
+ }
2335
+ clearCallbacks() {
2336
+ this.subscriptions.clear();
2337
+ }
2338
+ };
2339
+
2340
+ //#endregion
2341
+ //#region ../../node_modules/.pnpm/@lit+context@1.1.6/node_modules/@lit/context/development/lib/controllers/context-provider.js
2342
+ /**
2343
+ * @license
2344
+ * Copyright 2021 Google LLC
2345
+ * SPDX-License-Identifier: BSD-3-Clause
2346
+ */
2347
+ var ContextProviderEvent = class extends Event {
2348
+ /**
2349
+ *
2350
+ * @param context the context which this provider can provide
2351
+ * @param contextTarget the original context target of the provider
2352
+ */
2353
+ constructor(context, contextTarget) {
2354
+ super("context-provider", {
2355
+ bubbles: true,
2356
+ composed: true
2357
+ });
2358
+ this.context = context;
2359
+ this.contextTarget = contextTarget;
2360
+ }
2361
+ };
2362
+ /**
2363
+ * A ReactiveController which adds context provider behavior to a
2364
+ * custom element.
2365
+ *
2366
+ * This controller simply listens to the `context-request` event when
2367
+ * the host is connected to the DOM and registers the received callbacks
2368
+ * against its observable Context implementation.
2369
+ *
2370
+ * The controller may also be attached to any HTML element in which case it's
2371
+ * up to the user to call hostConnected() when attached to the DOM. This is
2372
+ * done automatically for any custom elements implementing
2373
+ * ReactiveControllerHost.
2374
+ */
2375
+ var ContextProvider = class extends ValueNotifier {
2376
+ constructor(host, contextOrOptions, initialValue) {
2377
+ super(contextOrOptions.context !== void 0 ? contextOrOptions.initialValue : initialValue);
2378
+ this.onContextRequest = (ev) => {
2379
+ if (ev.context !== this.context) return;
2380
+ const consumerHost = ev.contextTarget ?? ev.composedPath()[0];
2381
+ if (consumerHost === this.host) return;
2382
+ ev.stopPropagation();
2383
+ this.addCallback(ev.callback, consumerHost, ev.subscribe);
2384
+ };
2385
+ /**
2386
+ * When we get a provider request event, that means a child of this element
2387
+ * has just woken up. If it's a provider of our context, then we may need to
2388
+ * re-parent our subscriptions, because is a more specific provider than us
2389
+ * for its subtree.
2390
+ */
2391
+ this.onProviderRequest = (ev) => {
2392
+ if (ev.context !== this.context) return;
2393
+ if ((ev.contextTarget ?? ev.composedPath()[0]) === this.host) return;
2394
+ const seen = /* @__PURE__ */ new Set();
2395
+ for (const [callback, { consumerHost }] of this.subscriptions) {
2396
+ if (seen.has(callback)) continue;
2397
+ seen.add(callback);
2398
+ consumerHost.dispatchEvent(new ContextRequestEvent(this.context, consumerHost, callback, true));
2399
+ }
2400
+ ev.stopPropagation();
2401
+ };
2402
+ this.host = host;
2403
+ if (contextOrOptions.context !== void 0) this.context = contextOrOptions.context;
2404
+ else this.context = contextOrOptions;
2405
+ this.attachListeners();
2406
+ this.host.addController?.(this);
2407
+ }
2408
+ attachListeners() {
2409
+ this.host.addEventListener("context-request", this.onContextRequest);
2410
+ this.host.addEventListener("context-provider", this.onProviderRequest);
2411
+ }
2412
+ hostConnected() {
2413
+ this.host.dispatchEvent(new ContextProviderEvent(this.context, this.host));
2414
+ }
2415
+ };
2416
+
2417
+ //#endregion
2418
+ //#region src/store/container-mixin.ts
2419
+ /**
2420
+ * Create a mixin that consumes player context and registers itself as the
2421
+ * container element with the provider via `containerContext`.
2422
+ *
2423
+ * @param config - Container configuration with player and container contexts.
2424
+ */
2425
+ function createContainerMixin(config) {
2426
+ return (BaseClass) => {
2427
+ class PlayerContainerElement extends BaseClass {
2428
+ #contextStore = null;
2429
+ #setContainer = null;
2430
+ constructor(...args) {
2431
+ super(...args);
2432
+ new ContextConsumer(this, {
2433
+ context: config.playerContext,
2434
+ callback: (value) => {
2435
+ this.#contextStore = value ?? null;
2436
+ },
2437
+ subscribe: true
2438
+ });
2439
+ new ContextConsumer(this, {
2440
+ context: config.containerContext,
2441
+ callback: (value) => {
2442
+ this.#setContainer = value?.setContainer ?? null;
2443
+ if (this.isConnected) this.#setContainer?.(this);
2444
+ },
2445
+ subscribe: true
2446
+ });
2447
+ }
2448
+ get store() {
2449
+ return this.#contextStore;
2450
+ }
2451
+ connectedCallback() {
2452
+ super.connectedCallback();
2453
+ this.#setContainer?.(this);
2454
+ }
2455
+ disconnectedCallback() {
2456
+ super.disconnectedCallback();
2457
+ this.#setContainer?.(null);
2458
+ }
2459
+ }
2460
+ return PlayerContainerElement;
2461
+ };
2462
+ }
2463
+
2464
+ //#endregion
2465
+ //#region ../element/dist/dev/destroy-mixin.js
2466
+ /**
2467
+ * Mixin that adds a deferred destruction lifecycle to a `ReactiveElement`.
2468
+ *
2469
+ * On disconnect, schedules destruction after two animation frames.
2470
+ * If the element reconnects before the frames fire (e.g. DOM shuffling,
2471
+ * framework reconciliation), the `isConnected` check prevents destruction.
2472
+ *
2473
+ * The `keep-alive` attribute prevents automatic destruction entirely —
2474
+ * call `destroy()` manually when done.
2475
+ *
2476
+ * Subclasses override `destroyCallback()` (calling `super.destroyCallback()`)
2477
+ * to release heavy resources like stores or imperative APIs.
2478
+ *
2479
+ * Mirrors `addController`/`removeController` to track controllers
2480
+ * (needed because `ReactiveElement.#controllers` is hard-private),
2481
+ * calls `hostDestroyed()` on all tracked controllers in `destroyCallback`,
2482
+ * and guards `performUpdate()` so no updates run after destruction.
2483
+ */
2484
+ function DestroyMixin(SuperClass) {
2485
+ class DestroyableElement extends SuperClass {
2486
+ #destroyed = false;
2487
+ #trackedControllers = /* @__PURE__ */ new Set();
2488
+ get destroyed() {
2489
+ return this.#destroyed;
2490
+ }
2491
+ destroy() {
2492
+ if (this.#destroyed) return;
2493
+ this.#destroyed = true;
2494
+ this.destroyCallback();
2495
+ }
2496
+ destroyCallback() {
2497
+ for (const c of this.#trackedControllers) c.hostDestroyed?.();
2498
+ }
2499
+ addController(controller) {
2500
+ super.addController(controller);
2501
+ this.#trackedControllers.add(controller);
2502
+ }
2503
+ removeController(controller) {
2504
+ super.removeController(controller);
2505
+ this.#trackedControllers.delete(controller);
2506
+ }
2507
+ connectedCallback() {
2508
+ if (this.#destroyed) return;
2509
+ super.connectedCallback();
2510
+ }
2511
+ disconnectedCallback() {
2512
+ super.disconnectedCallback();
2513
+ if (!this.#destroyed && !this.hasAttribute("keep-alive")) requestAnimationFrame(() => {
2514
+ requestAnimationFrame(() => {
2515
+ if (!this.isConnected) this.destroy();
2516
+ });
2517
+ });
2518
+ }
2519
+ performUpdate() {
2520
+ if (this.#destroyed) return;
2521
+ super.performUpdate();
2522
+ }
2523
+ }
2524
+ return DestroyableElement;
2525
+ }
2526
+
2527
+ //#endregion
2528
+ //#region ../element/dist/dev/reactive-element.js
2529
+ const cache = /* @__PURE__ */ new WeakMap();
2530
+ const propertyKeys = /* @__PURE__ */ new Map();
2531
+ /**
2532
+ * Lightweight reactive custom element base class.
2533
+ *
2534
+ * Drop-in subset of Lit's `ReactiveElement` — supports `static properties`,
2535
+ * attribute reflection, batched async updates, and reactive controllers.
2536
+ * No Shadow DOM, no `static styles`, no decorators.
2537
+ *
2538
+ * Updates are batched using the same Promise-based scheduling as Lit:
2539
+ * property changes enqueue a microtask, and the update is gated behind
2540
+ * `connectedCallback` so the first update only runs once the element
2541
+ * is in the document.
2542
+ *
2543
+ * Subclasses that extend another element with properties must spread them:
2544
+ *
2545
+ * @example
2546
+ * ```ts
2547
+ * class MyButton extends ReactiveElement {
2548
+ * static override properties = {
2549
+ * label: { type: String },
2550
+ * disabled: { type: Boolean },
2551
+ * };
2552
+ *
2553
+ * label = 'Click me';
2554
+ * disabled = false;
2555
+ *
2556
+ * protected override update(changed: PropertyValues): void {
2557
+ * super.update(changed);
2558
+ * this.textContent = this.label;
2559
+ * }
2560
+ * }
2561
+ *
2562
+ * // Inheritance — spread parent properties
2563
+ * class FancyButton extends MyButton {
2564
+ * static override properties = {
2565
+ * ...MyButton.properties,
2566
+ * variant: { type: String },
2567
+ * };
2568
+ *
2569
+ * variant = 'primary';
2570
+ * }
2571
+ * ```
2572
+ */
2573
+ var ReactiveElement = class extends HTMLElement {
2574
+ static {
2575
+ this.properties = {};
2576
+ }
2577
+ /**
2578
+ * Returns a list of attributes corresponding to the registered properties.
2579
+ */
2580
+ static get observedAttributes() {
2581
+ return [...resolve(this).attrToProp.keys()];
2582
+ }
2583
+ #controllers = /* @__PURE__ */ new Set();
2584
+ #changedProperties = /* @__PURE__ */ new Map();
2585
+ #instanceProperties;
2586
+ /**
2587
+ * Promise that gates the first update until `connectedCallback`. Also
2588
+ * used to serialize updates — each `#enqueueUpdate` awaits the previous
2589
+ * `#updatePromise`, so property changes are batched and updates never
2590
+ * overlap. Matches Lit's scheduling model.
2591
+ */
2592
+ #updatePromise;
2593
+ constructor() {
2594
+ super();
2595
+ this.isUpdatePending = false;
2596
+ this.hasUpdated = false;
2597
+ this.#updatePromise = new Promise((res) => this.enableUpdating = res);
2598
+ const { props } = resolve(this.constructor);
2599
+ for (const name of props.keys()) if (Object.hasOwn(this, name)) {
2600
+ (this.#instanceProperties ??= /* @__PURE__ */ new Map()).set(name, this[name]);
2601
+ delete this[name];
2602
+ }
2603
+ this.requestUpdate();
2604
+ }
2605
+ /**
2606
+ * Note, this method should be considered final and not overridden. It is
2607
+ * overridden on the element instance with a function that triggers the
2608
+ * first update.
2609
+ */
2610
+ enableUpdating(_requestedUpdate) {}
2611
+ /**
2612
+ * Registers a {@linkcode ReactiveController} to participate in the
2613
+ * element's reactive update cycle. The element automatically calls into
2614
+ * any registered controllers during its lifecycle callbacks.
2615
+ *
2616
+ * If the element is connected when `addController()` is called, the
2617
+ * controller's `hostConnected()` callback will be immediately called.
2618
+ */
2619
+ addController(controller) {
2620
+ this.#controllers.add(controller);
2621
+ if (this.isConnected) controller.hostConnected?.();
2622
+ }
2623
+ /** Removes a {@linkcode ReactiveController} from the element. */
2624
+ removeController(controller) {
2625
+ this.#controllers.delete(controller);
2626
+ }
2627
+ /**
2628
+ * On first connection, enables updating and notifies controllers.
2629
+ */
2630
+ connectedCallback() {
2631
+ this.enableUpdating(true);
2632
+ for (const c of this.#controllers) c.hostConnected?.();
2633
+ }
2634
+ disconnectedCallback() {
2635
+ for (const c of this.#controllers) c.hostDisconnected?.();
2636
+ }
2637
+ /**
2638
+ * Synchronizes property values when attributes change.
2639
+ *
2640
+ * Specifically, when an attribute is set, the corresponding property is
2641
+ * set. You should rarely need to implement this callback. If this method
2642
+ * is overridden, `super.attributeChangedCallback(name, _old, value)` must
2643
+ * be called.
2644
+ */
2645
+ attributeChangedCallback(attr, oldValue, newValue) {
2646
+ if (oldValue === newValue) return;
2647
+ const { props, attrToProp } = resolve(this.constructor);
2648
+ const propName = attrToProp.get(attr);
2649
+ if (!propName) return;
2650
+ const decl = props.get(propName);
2651
+ if (!decl) return;
2652
+ let value = newValue;
2653
+ if (decl.type === Boolean) value = newValue !== null;
2654
+ else if (decl.type === Number) value = newValue === null ? null : Number(newValue);
2655
+ this[propName] = value;
2656
+ }
2657
+ /**
2658
+ * Requests an update which is processed asynchronously. This should be
2659
+ * called when an element should update based on some state not triggered
2660
+ * by setting a reactive property. In this case, pass no arguments. It
2661
+ * should also be called when manually implementing a property setter. In
2662
+ * this case, pass the property `name` and `oldValue` to ensure that any
2663
+ * configured property options are honored.
2664
+ */
2665
+ requestUpdate(name, oldValue) {
2666
+ if (name !== void 0) this.#changedProperties.set(name, oldValue);
2667
+ if (this.isUpdatePending) return;
2668
+ this.#updatePromise = this.#enqueueUpdate();
2669
+ }
2670
+ /**
2671
+ * Sets up the element to asynchronously update. Awaits the previous
2672
+ * `#updatePromise` which both serializes updates and (on first update)
2673
+ * waits for `connectedCallback` to resolve the gate.
2674
+ */
2675
+ async #enqueueUpdate() {
2676
+ this.isUpdatePending = true;
2677
+ try {
2678
+ await this.#updatePromise;
2679
+ } catch (e) {
2680
+ Promise.reject(e);
2681
+ }
2682
+ const result = this.scheduleUpdate();
2683
+ if (result != null) await result;
2684
+ return !this.isUpdatePending;
2685
+ }
2686
+ /**
2687
+ * Schedules an element update. You can override this method to change the
2688
+ * timing of updates by returning a Promise. The update will await the
2689
+ * returned Promise, and you should resolve the Promise to allow the update
2690
+ * to proceed. If this method is overridden, `super.scheduleUpdate()` must
2691
+ * be called.
2692
+ *
2693
+ * For instance, to schedule updates to occur just before the next frame:
2694
+ *
2695
+ * ```ts
2696
+ * override protected async scheduleUpdate(): Promise<unknown> {
2697
+ * await new Promise((resolve) => requestAnimationFrame(() => resolve()));
2698
+ * super.scheduleUpdate();
2699
+ * }
2700
+ * ```
2701
+ */
2702
+ scheduleUpdate() {
2703
+ this.performUpdate();
2704
+ }
2705
+ /**
2706
+ * Performs an element update. Note, if an exception is thrown during the
2707
+ * update, `firstUpdated` and `updated` will not be called.
2708
+ *
2709
+ * Call `performUpdate()` to immediately process a pending update. This
2710
+ * should generally not be needed, but it can be done in rare cases when
2711
+ * you need to update synchronously.
2712
+ */
2713
+ performUpdate() {
2714
+ if (!this.isUpdatePending) return;
2715
+ if (!this.hasUpdated && this.#instanceProperties) {
2716
+ for (const [name, value] of this.#instanceProperties) this[name] = value;
2717
+ this.#instanceProperties = void 0;
2718
+ }
2719
+ const changed = this.#changedProperties;
2720
+ this.willUpdate(changed);
2721
+ for (const c of this.#controllers) c.hostUpdate?.();
2722
+ this.update(changed);
2723
+ this.#changedProperties = /* @__PURE__ */ new Map();
2724
+ this.isUpdatePending = false;
2725
+ for (const c of this.#controllers) c.hostUpdated?.();
2726
+ if (!this.hasUpdated) {
2727
+ this.hasUpdated = true;
2728
+ this.firstUpdated(changed);
2729
+ }
2730
+ this.updated(changed);
2731
+ }
2732
+ /**
2733
+ * Invoked before `update()` to compute values needed during the update.
2734
+ *
2735
+ * Implement `willUpdate` to compute property values that depend on other
2736
+ * properties and are used in the rest of the update process.
2737
+ *
2738
+ * ```ts
2739
+ * willUpdate(changed) {
2740
+ * if (changed.has('firstName') || changed.has('lastName')) {
2741
+ * this.sha = computeSHA(`${this.firstName} ${this.lastName}`);
2742
+ * }
2743
+ * }
2744
+ * ```
2745
+ */
2746
+ willUpdate(_changed) {}
2747
+ /**
2748
+ * Updates the element. This method reflects property values to attributes
2749
+ * and can be overridden to render and keep updated element DOM. Setting
2750
+ * properties inside this method will *not* trigger another update.
2751
+ */
2752
+ update(_changed) {}
2753
+ /**
2754
+ * Invoked when the element is first updated. Implement to perform one
2755
+ * time work on the element after update.
2756
+ *
2757
+ * Setting properties inside this method will trigger the element to
2758
+ * update again after this update cycle completes.
2759
+ */
2760
+ firstUpdated(_changed) {}
2761
+ /**
2762
+ * Invoked whenever the element is updated. Implement to perform
2763
+ * post-updating tasks via DOM APIs, for example, focusing an element.
2764
+ *
2765
+ * Setting properties inside this method will trigger the element to
2766
+ * update again after this update cycle completes.
2767
+ */
2768
+ updated(_changed) {}
2769
+ /**
2770
+ * Returns a Promise that resolves when the element has completed updating.
2771
+ * The Promise value is a boolean that is `true` if the element completed
2772
+ * the update without triggering another update. The Promise result is
2773
+ * `false` if a property was set inside `updated()`.
2774
+ */
2775
+ get updateComplete() {
2776
+ return this.#updatePromise;
2777
+ }
2778
+ };
2779
+ /**
2780
+ * Resolve `ctor.properties` into lookup Maps and install reactive accessors
2781
+ * on the prototype. Runs once per class, result is cached.
2782
+ *
2783
+ * Subclasses that need parent properties must spread them:
2784
+ * `static override properties = { ...Parent.properties, ... }`.
2785
+ */
2786
+ function resolve(ctor) {
2787
+ const existing = cache.get(ctor);
2788
+ if (existing) return existing;
2789
+ const props = /* @__PURE__ */ new Map();
2790
+ const attrToProp = /* @__PURE__ */ new Map();
2791
+ for (const [name, decl] of Object.entries(ctor.properties)) {
2792
+ props.set(name, decl);
2793
+ attrToProp.set(decl.attribute ?? name, name);
2794
+ if (!Object.getOwnPropertyDescriptor(ctor.prototype, name)?.get) {
2795
+ let key = propertyKeys.get(name);
2796
+ if (!key) {
2797
+ key = Symbol(name);
2798
+ propertyKeys.set(name, key);
2799
+ }
2800
+ Object.defineProperty(ctor.prototype, name, {
2801
+ get() {
2802
+ return this[key];
2803
+ },
2804
+ set(value) {
2805
+ const old = this[key];
2806
+ this[key] = value;
2807
+ if (!Object.is(old, value)) this.requestUpdate(name, old);
2808
+ },
2809
+ configurable: true,
2810
+ enumerable: true
2811
+ });
2812
+ }
2813
+ }
2814
+ const meta = {
2815
+ props,
2816
+ attrToProp
2817
+ };
2818
+ cache.set(ctor, meta);
2819
+ return meta;
2820
+ }
2821
+
2822
+ //#endregion
2823
+ //#region src/ui/media-element.ts
2824
+ /** Base class for interactive media UI elements. */
2825
+ var MediaElement = class extends DestroyMixin(ReactiveElement) {};
2826
+
2827
+ //#endregion
2828
+ //#region src/media/container-element.ts
2829
+ const ContainerMixin = createContainerMixin({
2830
+ playerContext,
2831
+ containerContext
2832
+ });
2833
+ var MediaContainerElement = class extends ContainerMixin(MediaElement) {
2834
+ static {
2835
+ this.tagName = "media-container";
2836
+ }
2837
+ };
2838
+
2839
+ //#endregion
2840
+ //#region src/store/provider-mixin.ts
2841
+ /**
2842
+ * Create a mixin that provides player context to descendant elements and
2843
+ * owns the `store.attach()` lifecycle.
2844
+ *
2845
+ * Media and container elements register themselves via media/container
2846
+ * contexts that carry both the current value and a setter. When a media
2847
+ * element is available, the provider calls `store.attach({ media, container })`.
2848
+ *
2849
+ * As a fallback for plain `<video>`/`<audio>` that can't consume context,
2850
+ * the provider queries its subtree after a microtask.
2851
+ *
2852
+ * @param config - Provider configuration with contexts and store factory.
2853
+ */
2854
+ function createProviderMixin(config) {
2855
+ return (BaseClass) => {
2856
+ class PlayerProviderElement extends BaseClass {
2857
+ #store = config.factory();
2858
+ #detach = null;
2859
+ #media = null;
2860
+ #container = null;
2861
+ #fallbackQueued = false;
2862
+ #setMedia = (media) => {
2863
+ if (this.#media === media) return;
2864
+ this.#media = media;
2865
+ this.#mediaProvider.setValue({
2866
+ media,
2867
+ setMedia: this.#setMedia
2868
+ });
2869
+ this.#tryAttach();
2870
+ };
2871
+ #setContainer = (container) => {
2872
+ if (this.#container === container) return;
2873
+ this.#container = container;
2874
+ this.#containerProvider.setValue({
2875
+ container,
2876
+ setContainer: this.#setContainer
2877
+ });
2878
+ this.#tryAttach();
2879
+ };
2880
+ #playerProvider = new ContextProvider(this, {
2881
+ context: config.playerContext,
2882
+ initialValue: this.store
2883
+ });
2884
+ #mediaProvider = new ContextProvider(this, {
2885
+ context: config.mediaContext,
2886
+ initialValue: {
2887
+ media: this.#media,
2888
+ setMedia: this.#setMedia
2889
+ }
2890
+ });
2891
+ #containerProvider = new ContextProvider(this, {
2892
+ context: config.containerContext,
2893
+ initialValue: {
2894
+ container: this.#container,
2895
+ setContainer: this.#setContainer
2896
+ }
2897
+ });
2898
+ get store() {
2899
+ if (isNull(this.#store)) this.#store = config.factory();
2900
+ return this.#store;
2901
+ }
2902
+ connectedCallback() {
2903
+ super.connectedCallback();
2904
+ this.#playerProvider.setValue(this.store);
2905
+ this.#mediaProvider.setValue({
2906
+ media: this.#media,
2907
+ setMedia: this.#setMedia
2908
+ });
2909
+ this.#containerProvider.setValue({
2910
+ container: this.#container,
2911
+ setContainer: this.#setContainer
2912
+ });
2913
+ this.#tryAttach();
2914
+ this.#queueFallbackDiscovery();
2915
+ }
2916
+ disconnectedCallback() {
2917
+ super.disconnectedCallback();
2918
+ this.#detachStore();
2919
+ }
2920
+ destroyCallback() {
2921
+ this.#detachStore();
2922
+ this.#store?.destroy();
2923
+ this.#store = null;
2924
+ super.destroyCallback();
2925
+ }
2926
+ #tryAttach() {
2927
+ const store = this.#store;
2928
+ if (!store) return;
2929
+ if (!this.#media) {
2930
+ this.#detachStore();
2931
+ return;
2932
+ }
2933
+ const target = {
2934
+ media: this.#media,
2935
+ container: this.#container
2936
+ };
2937
+ const hasMediaChanged = store.target?.media !== target.media;
2938
+ const hasContainerChanged = store.target?.container !== target.container;
2939
+ if (hasMediaChanged || hasContainerChanged) {
2940
+ this.#detachStore();
2941
+ this.#detach = store.attach(target);
2942
+ }
2943
+ }
2944
+ #detachStore() {
2945
+ this.#detach?.();
2946
+ this.#detach = null;
2947
+ }
2948
+ #queueFallbackDiscovery() {
2949
+ if (this.#media || this.#fallbackQueued) return;
2950
+ this.#fallbackQueued = true;
2951
+ queueMicrotask(() => {
2952
+ this.#fallbackQueued = false;
2953
+ if (this.#media) return;
2954
+ const media = this.querySelector("video, audio");
2955
+ if (media) this.#setMedia(media);
2956
+ });
2957
+ }
2958
+ }
2959
+ return PlayerProviderElement;
2960
+ };
2961
+ }
2962
+
2963
+ //#endregion
2964
+ //#region ../store/dist/dev/html/controllers/snapshot-controller.js
2965
+ /**
2966
+ * Subscribe to a `State<T>` container with optional selector.
2967
+ *
2968
+ * Without selector: returns full state, re-renders on any state change.
2969
+ * With selector: returns selected slice, re-renders only when the slice changes (shallowEqual).
2970
+ *
2971
+ * @example
2972
+ * ```ts
2973
+ * #state = new SnapshotController(this, sliderState, (s) => s.value);
2974
+ * ```
2975
+ */
2976
+ var SnapshotController = class {
2977
+ #host;
2978
+ #selector;
2979
+ #state;
2980
+ #cached;
2981
+ #unsubscribe = noop;
2982
+ constructor(host, state, selector) {
2983
+ this.#host = host;
2984
+ this.#state = state;
2985
+ this.#selector = selector;
2986
+ host.addController(this);
2987
+ }
2988
+ get value() {
2989
+ if (!this.#selector) return this.#state.current;
2990
+ this.#cached ??= this.#selector(this.#state.current);
2991
+ return this.#cached;
2992
+ }
2993
+ /** Switch to tracking a different state container. */
2994
+ track(state) {
2995
+ this.#state = state;
2996
+ this.#subscribe();
2997
+ }
2998
+ hostConnected() {
2999
+ this.#subscribe();
3000
+ }
3001
+ hostDisconnected() {
3002
+ this.#unsubscribe();
3003
+ this.#unsubscribe = noop;
3004
+ this.#cached = void 0;
3005
+ }
3006
+ #subscribe() {
3007
+ this.#unsubscribe();
3008
+ if (!this.#selector) {
3009
+ this.#unsubscribe = this.#state.subscribe(() => this.#host.requestUpdate());
3010
+ return;
3011
+ }
3012
+ const selector = this.#selector;
3013
+ this.#cached = selector(this.#state.current);
3014
+ this.#unsubscribe = this.#state.subscribe(() => {
3015
+ const next = selector(this.#state.current);
3016
+ if (!shallowEqual(this.#cached, next)) {
3017
+ this.#cached = next;
3018
+ this.#host.requestUpdate();
3019
+ }
3020
+ });
3021
+ }
3022
+ };
3023
+
3024
+ //#endregion
3025
+ //#region ../store/dist/dev/html/store-accessor.js
3026
+ /**
3027
+ * Resolves a store from either a direct instance or context.
3028
+ *
3029
+ * When given a direct store, provides immediate access.
3030
+ * When given a context, sets up a ContextConsumer to receive the store.
3031
+ *
3032
+ * @example Direct store
3033
+ * ```ts
3034
+ * const accessor = new StoreAccessor(host, store, (s) => console.log('available', s));
3035
+ * accessor.value; // Store (immediately available)
3036
+ * ```
3037
+ *
3038
+ * @example Context source
3039
+ * ```ts
3040
+ * const accessor = new StoreAccessor(host, context, (s) => console.log('available', s));
3041
+ * accessor.value; // null until context provides store
3042
+ * ```
3043
+ */
3044
+ var StoreAccessor = class {
3045
+ #onAvailable;
3046
+ #consumer;
3047
+ #directStore;
3048
+ constructor(host, source, onAvailable) {
3049
+ this.#onAvailable = onAvailable ?? noop;
3050
+ if (isStore(source)) {
3051
+ this.#directStore = source;
3052
+ this.#consumer = null;
3053
+ } else {
3054
+ this.#directStore = null;
3055
+ this.#consumer = new ContextConsumer(host, {
3056
+ context: source,
3057
+ callback: (store) => this.#onAvailable(store),
3058
+ subscribe: false
3059
+ });
3060
+ }
3061
+ host.addController(this);
3062
+ }
3063
+ /** Returns the store, or null if not yet available from context. */
3064
+ get value() {
3065
+ if (this.#consumer) return this.#consumer.value ?? null;
3066
+ return this.#directStore;
3067
+ }
3068
+ hostConnected() {
3069
+ if (this.#directStore) this.#onAvailable(this.#directStore);
3070
+ }
3071
+ };
3072
+
3073
+ //#endregion
3074
+ //#region ../store/dist/dev/html/controllers/store-controller.js
3075
+ /**
3076
+ * Access store state and actions.
3077
+ *
3078
+ * Without selector: Returns the store, does NOT subscribe to changes.
3079
+ * With selector: Returns selected state, triggers update when selected state changes (shallowEqual).
3080
+ *
3081
+ * @example
3082
+ * ```ts
3083
+ * // Store access (no subscription) - access actions
3084
+ * class Controls extends LitElement {
3085
+ * #store = new StoreController(this, storeSource);
3086
+ *
3087
+ * handleClick() {
3088
+ * this.#store.value.setVolume(0.5);
3089
+ * }
3090
+ * }
3091
+ *
3092
+ * // Selector-based subscription - re-renders when playback changes
3093
+ * class PlayButton extends LitElement {
3094
+ * #playback = new StoreController(this, storeSource, selectPlayback);
3095
+ *
3096
+ * render() {
3097
+ * const playback = this.#playback.value;
3098
+ * if (!playback) return nothing;
3099
+ * return html`<button @click=${playback.toggle}>
3100
+ * ${playback.paused ? 'Play' : 'Pause'}
3101
+ * </button>`;
3102
+ * }
3103
+ * }
3104
+ * ```
3105
+ */
3106
+ var StoreController = class {
3107
+ #host;
3108
+ #selector;
3109
+ #accessor;
3110
+ #snapshot = null;
3111
+ constructor(host, source, selector) {
3112
+ this.#host = host;
3113
+ this.#selector = selector;
3114
+ this.#accessor = new StoreAccessor(host, source, (store) => this.#connect(store));
3115
+ host.addController(this);
3116
+ }
3117
+ get value() {
3118
+ const store = this.#accessor.value;
3119
+ if (isNull(store)) throw new Error("Store not available");
3120
+ if (isUndefined(this.#selector)) return store;
3121
+ return this.#snapshot.value;
3122
+ }
3123
+ hostConnected() {}
3124
+ #connect(store) {
3125
+ if (isUndefined(this.#selector)) return;
3126
+ if (!this.#snapshot) this.#snapshot = new SnapshotController(this.#host, store.$state, this.#selector);
3127
+ else this.#snapshot.track(store.$state);
3128
+ }
3129
+ };
3130
+
3131
+ //#endregion
3132
+ //#region src/player/player-controller.ts
3133
+ /**
3134
+ * Reactive controller for accessing player store state.
3135
+ *
3136
+ * Without selector: Returns the store, does NOT subscribe to changes.
3137
+ * With selector: Returns selected state, subscribes with shallowEqual comparison.
3138
+ *
3139
+ * @example
3140
+ * ```ts
3141
+ * // Store access (no subscription)
3142
+ * class Controls extends MediaElement {
3143
+ * #player = new PlayerController(this, playerContext);
3144
+ *
3145
+ * handleClick() {
3146
+ * this.#player.value.setVolume(0.5);
3147
+ * }
3148
+ * }
3149
+ *
3150
+ * // Selector-based subscription
3151
+ * class PlayButton extends MediaElement {
3152
+ * #playback = new PlayerController(this, playerContext, selectPlayback);
3153
+ * }
3154
+ * ```
3155
+ */
3156
+ var PlayerController = class {
3157
+ #host;
3158
+ #selector;
3159
+ #consumer;
3160
+ #store = null;
3161
+ constructor(host, context, selector) {
3162
+ this.#host = host;
3163
+ this.#selector = selector;
3164
+ this.#consumer = new ContextConsumer(host, {
3165
+ context,
3166
+ callback: (ctx) => this.#connect(ctx),
3167
+ subscribe: true
3168
+ });
3169
+ host.addController(this);
3170
+ }
3171
+ get value() {
3172
+ const store = this.#consumer.value;
3173
+ if (!store) return void 0;
3174
+ if (!this.#selector) return store;
3175
+ return this.#store?.value;
3176
+ }
3177
+ get displayName() {
3178
+ return this.#selector?.displayName;
3179
+ }
3180
+ hostConnected() {
3181
+ const store = this.#consumer.value;
3182
+ if (store) this.#connect(store);
3183
+ }
3184
+ hostDisconnected() {
3185
+ this.#store = null;
3186
+ }
3187
+ #connect(store) {
3188
+ if (!this.#store && this.#selector) this.#store = new StoreController(this.#host, store, this.#selector);
3189
+ }
3190
+ };
3191
+
3192
+ //#endregion
3193
+ //#region src/player/create-player.ts
3194
+ function createPlayer(config) {
3195
+ const slice = combine(...config.features);
3196
+ function create() {
3197
+ return createStore()(slice);
3198
+ }
3199
+ return {
3200
+ context: playerContext,
3201
+ create,
3202
+ PlayerController,
3203
+ ProviderMixin: createProviderMixin({
3204
+ playerContext,
3205
+ mediaContext,
3206
+ containerContext,
3207
+ factory: create
3208
+ }),
3209
+ ContainerMixin: createContainerMixin({
3210
+ playerContext,
3211
+ containerContext
3212
+ })
3213
+ };
3214
+ }
3215
+
3216
+ //#endregion
3217
+ export { selectFullscreen as A, applyStyles as B, getAnchorPositionStyle as C, createButton as D, createPopover as E, selectTime as F, tryShowPopover as H, selectVolume as I, audioFeatures as L, selectPlayback as M, selectPlaybackRate as N, selectBuffer as O, selectTextTrack as P, backgroundFeatures as R, getAnchorNameStyle as S, resolveOffsets as T, supportsAnchorPositioning as U, tryHidePopover as V, createState as W, getSliderPreviewStyle as _, MediaElement as a, clamp as b, ContextConsumer as c, applyElementProps as d, createTransition as f, getSliderCSSVars as g, ThumbnailCore as h, MediaContainerElement as i, selectPiP as j, selectControls as k, applyStateDataAttrs as l, createThumbnail as m, PlayerController as n, ReactiveElement as o, createTooltip as p, SnapshotController as r, ContextProvider as s, createPlayer as t, logMissingFeature as u, getTimeSliderCSSVars as v, getPopupPositionRect as w, roundToStep as x, createSlider as y, videoFeatures as z };
3218
+ //# sourceMappingURL=create-player-Cwxvswyv.js.map