@videojs/html 10.0.0-beta.15 → 10.0.0-beta.17

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 (377) hide show
  1. package/cdn/{abort-CzqmAxxH.js → abort-BL-SGV3o.js} +1 -1
  2. package/cdn/{abort-CzqmAxxH.js.map → abort-BL-SGV3o.js.map} +1 -1
  3. package/cdn/{abort-KaHR4JO1.js → abort-DGNIECLn.js} +1 -1
  4. package/cdn/{abort-KaHR4JO1.js.map → abort-DGNIECLn.js.map} +1 -1
  5. package/cdn/audio-minimal-ui.dev.js +4 -5
  6. package/cdn/audio-minimal-ui.js +1 -1
  7. package/cdn/audio-minimal.dev.js +7 -8
  8. package/cdn/audio-minimal.dev.js.map +1 -1
  9. package/cdn/audio-minimal.js +1 -1
  10. package/cdn/audio-minimal.js.map +1 -1
  11. package/cdn/audio-ui.dev.js +4 -5
  12. package/cdn/audio-ui.js +1 -1
  13. package/cdn/audio.dev.js +22 -7
  14. package/cdn/audio.dev.js.map +1 -1
  15. package/cdn/audio.js +1 -1
  16. package/cdn/audio.js.map +1 -1
  17. package/cdn/background.dev.js +3 -3
  18. package/cdn/background.js +1 -1
  19. package/cdn/background.js.map +1 -1
  20. package/cdn/compounds-Df_1JbZD.js +8 -0
  21. package/cdn/compounds-Df_1JbZD.js.map +1 -0
  22. package/cdn/{volume-slider-Co5X4Z1t.js → compounds-VFPcCeRV.js} +2439 -946
  23. package/cdn/compounds-VFPcCeRV.js.map +1 -0
  24. package/cdn/context-C-IpVHEt.js +14 -0
  25. package/cdn/context-C-IpVHEt.js.map +1 -0
  26. package/cdn/{context-BjrbhiSk.js → context-CvJ83xGk.js} +2 -83
  27. package/cdn/context-CvJ83xGk.js.map +1 -0
  28. package/cdn/{create-player-p9xCO0yC.js → create-player-CyG77t-m.js} +778 -1955
  29. package/cdn/create-player-CyG77t-m.js.map +1 -0
  30. package/cdn/create-player-Gom2ZZe3.js +7 -0
  31. package/cdn/create-player-Gom2ZZe3.js.map +1 -0
  32. package/cdn/{hls-26YJVjvD.js → hls-BAbdl84H.js} +3 -3
  33. package/cdn/{hls-26YJVjvD.js.map → hls-BAbdl84H.js.map} +1 -1
  34. package/cdn/{hls-BriQI4q1.js → hls-BrzPpueW.js} +9 -12
  35. package/cdn/{hls-BriQI4q1.js.map → hls-BrzPpueW.js.map} +1 -1
  36. package/cdn/hotkey-element-DR3ZAqKa.js +2 -0
  37. package/cdn/hotkey-element-DR3ZAqKa.js.map +1 -0
  38. package/cdn/hotkey-element-Dlta37Be.js +369 -0
  39. package/cdn/hotkey-element-Dlta37Be.js.map +1 -0
  40. package/cdn/media/dash-video.dev.js +3 -4
  41. package/cdn/media/dash-video.dev.js.map +1 -1
  42. package/cdn/media/dash-video.js +2 -2
  43. package/cdn/media/hls-video.dev.js +4 -5
  44. package/cdn/media/hls-video.dev.js.map +1 -1
  45. package/cdn/media/hls-video.js +1 -1
  46. package/cdn/media/hls-video.js.map +1 -1
  47. package/cdn/media/mux-audio.dev.d.ts +1 -0
  48. package/cdn/media/mux-audio.dev.js +29 -0
  49. package/cdn/media/mux-audio.dev.js.map +1 -0
  50. package/cdn/media/mux-audio.js +2 -0
  51. package/cdn/media/mux-audio.js.map +1 -0
  52. package/cdn/media/mux-video.dev.js +5 -3099
  53. package/cdn/media/mux-video.dev.js.map +1 -1
  54. package/cdn/media/mux-video.js +1 -24
  55. package/cdn/media/mux-video.js.map +1 -1
  56. package/cdn/media/native-hls-video.dev.js +4 -4
  57. package/cdn/media/native-hls-video.js +1 -1
  58. package/cdn/media/simple-hls-video.dev.js +966 -681
  59. package/cdn/media/simple-hls-video.dev.js.map +1 -1
  60. package/cdn/media/simple-hls-video.js +6 -6
  61. package/cdn/media/simple-hls-video.js.map +1 -1
  62. package/cdn/{media-attach-mixin-DfKkofgF.js → media-attach-mixin-CMH1ziXP.js} +2 -2
  63. package/cdn/{media-attach-mixin-DfKkofgF.js.map → media-attach-mixin-CMH1ziXP.js.map} +1 -1
  64. package/cdn/{media-attach-mixin-Dv2D43tb.js → media-attach-mixin-DUzmXEJ3.js} +2 -2
  65. package/cdn/{media-attach-mixin-Dv2D43tb.js.map → media-attach-mixin-DUzmXEJ3.js.map} +1 -1
  66. package/cdn/{media-props-mixin-Dc5dpCV4.js → media-props-mixin-hheRmkup.js} +92 -8
  67. package/cdn/media-props-mixin-hheRmkup.js.map +1 -0
  68. package/cdn/media-props-mixin-yRWj8yXF.js +47 -0
  69. package/cdn/media-props-mixin-yRWj8yXF.js.map +1 -0
  70. package/cdn/{minimal-BUUGNZK7.js → minimal-D9Dw-L2P.js} +1 -1
  71. package/cdn/{minimal-BUUGNZK7.js.map → minimal-D9Dw-L2P.js.map} +1 -1
  72. package/cdn/{minimal-CJGOJ6pE.js → minimal-Dc5nNl_-.js} +1 -1
  73. package/cdn/{minimal-CJGOJ6pE.js.map → minimal-Dc5nNl_-.js.map} +1 -1
  74. package/cdn/minimal-ui-B3BBK5nX.js +2 -0
  75. package/cdn/minimal-ui-B3BBK5nX.js.map +1 -0
  76. package/cdn/minimal-ui-CPRSYky_.js +28 -0
  77. package/cdn/minimal-ui-CPRSYky_.js.map +1 -0
  78. package/cdn/minimal-ui-Cnaig4X6.js +22 -0
  79. package/cdn/minimal-ui-Cnaig4X6.js.map +1 -0
  80. package/cdn/minimal-ui-DOePmQfq.js +2 -0
  81. package/cdn/minimal-ui-DOePmQfq.js.map +1 -0
  82. package/cdn/mux-DGgCyz_A.js +3102 -0
  83. package/cdn/mux-DGgCyz_A.js.map +1 -0
  84. package/cdn/mux-fYfPUpq3.js +25 -0
  85. package/cdn/mux-fYfPUpq3.js.map +1 -0
  86. package/cdn/{native-hls-D2rfyyyW.js → native-hls-BuCYu7Rd.js} +2 -3
  87. package/cdn/{native-hls-D2rfyyyW.js.map → native-hls-BuCYu7Rd.js.map} +1 -1
  88. package/cdn/native-hls-DnqJ-0zL.js +2 -0
  89. package/cdn/{native-hls-CjRvSXAJ.js.map → native-hls-DnqJ-0zL.js.map} +1 -1
  90. package/cdn/player-Cu5_r0Gk.js +2 -0
  91. package/cdn/{player-Cz9-_j7J.js.map → player-Cu5_r0Gk.js.map} +1 -1
  92. package/cdn/player-DIOgBqQf.js +382 -0
  93. package/cdn/player-DIOgBqQf.js.map +1 -0
  94. package/cdn/{player-D0bhjT8X.js → player-DxBoqZVw.js} +4 -3
  95. package/cdn/{player-D0bhjT8X.js.map → player-DxBoqZVw.js.map} +1 -1
  96. package/cdn/player-eEH-XjnF.js +2 -0
  97. package/cdn/player-eEH-XjnF.js.map +1 -0
  98. package/cdn/{shallow-equal-uPuCQhnd.js → shallow-equal-1KBb-lrM.js} +1 -1
  99. package/cdn/{shallow-equal-uPuCQhnd.js.map → shallow-equal-1KBb-lrM.js.map} +1 -1
  100. package/cdn/{shallow-equal-C8Fs4TTE.js → shallow-equal-Ca0qjpLJ.js} +1 -1
  101. package/cdn/{shallow-equal-C8Fs4TTE.js.map → shallow-equal-Ca0qjpLJ.js.map} +1 -1
  102. package/cdn/{skin-element-zakTHELS.js → skin-element-BTPr5DoY.js} +2 -2
  103. package/cdn/{skin-element-zakTHELS.js.map → skin-element-BTPr5DoY.js.map} +1 -1
  104. package/cdn/{skin-element-DB-cKAAx.js → skin-element-u6pdmSSs.js} +2 -2
  105. package/cdn/{skin-element-DB-cKAAx.js.map → skin-element-u6pdmSSs.js.map} +1 -1
  106. package/cdn/ui-34pkHFdT.js +25 -0
  107. package/cdn/ui-34pkHFdT.js.map +1 -0
  108. package/cdn/ui-DWoV_Da1.js +2 -0
  109. package/cdn/ui-DWoV_Da1.js.map +1 -0
  110. package/cdn/ui-DXtTKomo.js +2 -0
  111. package/cdn/ui-DXtTKomo.js.map +1 -0
  112. package/cdn/ui-X5WOdCCw.js +31 -0
  113. package/cdn/ui-X5WOdCCw.js.map +1 -0
  114. package/cdn/video-minimal-ui.dev.js +4 -5
  115. package/cdn/video-minimal-ui.js +1 -1
  116. package/cdn/video-minimal.dev.js +7 -8
  117. package/cdn/video-minimal.dev.js.map +1 -1
  118. package/cdn/video-minimal.js +1 -1
  119. package/cdn/video-minimal.js.map +1 -1
  120. package/cdn/video-ui.dev.js +4 -5
  121. package/cdn/video-ui.js +1 -1
  122. package/cdn/video.dev.js +32 -7
  123. package/cdn/video.dev.js.map +1 -1
  124. package/cdn/video.js +1 -1
  125. package/cdn/video.js.map +1 -1
  126. package/dist/default/_virtual/inline-css_src/define/audio/minimal-skin.js +1 -1
  127. package/dist/default/_virtual/inline-css_src/define/audio/minimal-skin.js.map +1 -1
  128. package/dist/default/_virtual/inline-css_src/define/audio/skin.js +1 -1
  129. package/dist/default/_virtual/inline-css_src/define/audio/skin.js.map +1 -1
  130. package/dist/default/_virtual/inline-css_src/define/video/minimal-skin.js +1 -1
  131. package/dist/default/_virtual/inline-css_src/define/video/minimal-skin.js.map +1 -1
  132. package/dist/default/_virtual/inline-css_src/define/video/skin.js +1 -1
  133. package/dist/default/_virtual/inline-css_src/define/video/skin.js.map +1 -1
  134. package/dist/default/define/audio/minimal-skin.css +23 -0
  135. package/dist/default/define/audio/minimal-ui.js +28 -12
  136. package/dist/default/define/audio/minimal-ui.js.map +1 -0
  137. package/dist/default/define/audio/skin.css +23 -0
  138. package/dist/default/define/audio/skin.js +1 -1
  139. package/dist/default/define/audio/skin.js.map +1 -1
  140. package/dist/default/define/audio/ui.js +32 -12
  141. package/dist/default/define/audio/ui.js.map +1 -0
  142. package/dist/default/define/background/skin.js +1 -1
  143. package/dist/default/define/media/mux-audio.js +13 -0
  144. package/dist/default/define/media/mux-audio.js.map +1 -0
  145. package/dist/default/define/skin-element.js +1 -1
  146. package/dist/default/define/ui/compounds.js +62 -0
  147. package/dist/default/define/ui/compounds.js.map +1 -0
  148. package/dist/default/define/ui/controls.js +2 -5
  149. package/dist/default/define/ui/controls.js.map +1 -1
  150. package/dist/default/define/ui/error-dialog.js +2 -9
  151. package/dist/default/define/ui/error-dialog.js.map +1 -1
  152. package/dist/default/define/ui/hotkey.js +7 -0
  153. package/dist/default/define/ui/hotkey.js.map +1 -0
  154. package/dist/default/define/ui/slider.js +2 -13
  155. package/dist/default/define/ui/slider.js.map +1 -1
  156. package/dist/default/define/ui/time-slider.js +2 -17
  157. package/dist/default/define/ui/time-slider.js.map +1 -1
  158. package/dist/default/define/ui/time.js +2 -7
  159. package/dist/default/define/ui/time.js.map +1 -1
  160. package/dist/default/define/ui/volume-slider.js +2 -13
  161. package/dist/default/define/ui/volume-slider.js.map +1 -1
  162. package/dist/default/define/video/minimal-skin.css +23 -0
  163. package/dist/default/define/video/minimal-ui.js +39 -18
  164. package/dist/default/define/video/minimal-ui.js.map +1 -0
  165. package/dist/default/define/video/skin.css +23 -0
  166. package/dist/default/define/video/skin.js +1 -1
  167. package/dist/default/define/video/skin.js.map +1 -1
  168. package/dist/default/define/video/ui.js +43 -18
  169. package/dist/default/define/video/ui.js.map +1 -0
  170. package/dist/default/index.js +6 -1
  171. package/dist/default/media/container-element.js +16 -0
  172. package/dist/default/media/container-element.js.map +1 -1
  173. package/dist/default/media/mux-audio/index.js +18 -0
  174. package/dist/default/media/mux-audio/index.js.map +1 -0
  175. package/dist/default/player/context.js.map +1 -1
  176. package/dist/default/ui/alert-dialog/alert-dialog-element.js +1 -0
  177. package/dist/default/ui/alert-dialog/alert-dialog-element.js.map +1 -1
  178. package/dist/default/ui/buffering-indicator/buffering-indicator-element.js +1 -0
  179. package/dist/default/ui/buffering-indicator/buffering-indicator-element.js.map +1 -1
  180. package/dist/default/ui/captions-button/captions-button-element.js +1 -0
  181. package/dist/default/ui/captions-button/captions-button-element.js.map +1 -1
  182. package/dist/default/ui/error-dialog/error-dialog-element.js +1 -0
  183. package/dist/default/ui/error-dialog/error-dialog-element.js.map +1 -1
  184. package/dist/default/ui/fullscreen-button/fullscreen-button-element.js +1 -0
  185. package/dist/default/ui/fullscreen-button/fullscreen-button-element.js.map +1 -1
  186. package/dist/default/ui/gesture/gesture-element.js +84 -0
  187. package/dist/default/ui/gesture/gesture-element.js.map +1 -0
  188. package/dist/default/ui/hotkey/aria-key-shortcuts-controller.js +28 -0
  189. package/dist/default/ui/hotkey/aria-key-shortcuts-controller.js.map +1 -0
  190. package/dist/default/ui/hotkey/hotkey-element.js +81 -0
  191. package/dist/default/ui/hotkey/hotkey-element.js.map +1 -0
  192. package/dist/default/ui/media-button-element.js +9 -1
  193. package/dist/default/ui/media-button-element.js.map +1 -1
  194. package/dist/default/ui/mute-button/mute-button-element.js +1 -0
  195. package/dist/default/ui/mute-button/mute-button-element.js.map +1 -1
  196. package/dist/default/ui/pip-button/pip-button-element.js +1 -0
  197. package/dist/default/ui/pip-button/pip-button-element.js.map +1 -1
  198. package/dist/default/ui/play-button/play-button-element.js +1 -0
  199. package/dist/default/ui/play-button/play-button-element.js.map +1 -1
  200. package/dist/default/ui/popover/popover-element.js +7 -55
  201. package/dist/default/ui/popover/popover-element.js.map +1 -1
  202. package/dist/default/ui/position-controller.js +76 -0
  203. package/dist/default/ui/position-controller.js.map +1 -0
  204. package/dist/default/ui/slider/slider-element.js +1 -1
  205. package/dist/default/ui/slider/slider-preview-element.js +1 -1
  206. package/dist/default/ui/time-slider/time-slider-element.js +5 -5
  207. package/dist/default/ui/time-slider/time-slider-element.js.map +1 -1
  208. package/dist/default/ui/tooltip/tooltip-element.js +8 -54
  209. package/dist/default/ui/tooltip/tooltip-element.js.map +1 -1
  210. package/dist/default/ui/volume-slider/volume-slider-element.js +1 -1
  211. package/dist/dev/_virtual/inline-css_src/define/audio/minimal-skin.js +1 -1
  212. package/dist/dev/_virtual/inline-css_src/define/audio/minimal-skin.js.map +1 -1
  213. package/dist/dev/_virtual/inline-css_src/define/audio/skin.js +1 -1
  214. package/dist/dev/_virtual/inline-css_src/define/audio/skin.js.map +1 -1
  215. package/dist/dev/_virtual/inline-css_src/define/video/minimal-skin.js +1 -1
  216. package/dist/dev/_virtual/inline-css_src/define/video/minimal-skin.js.map +1 -1
  217. package/dist/dev/_virtual/inline-css_src/define/video/skin.js +1 -1
  218. package/dist/dev/_virtual/inline-css_src/define/video/skin.js.map +1 -1
  219. package/dist/dev/define/audio/minimal-skin.css +23 -0
  220. package/dist/dev/define/audio/minimal-ui.js +28 -12
  221. package/dist/dev/define/audio/minimal-ui.js.map +1 -0
  222. package/dist/dev/define/audio/skin.css +23 -0
  223. package/dist/dev/define/audio/skin.d.ts.map +1 -1
  224. package/dist/dev/define/audio/skin.js +16 -0
  225. package/dist/dev/define/audio/skin.js.map +1 -1
  226. package/dist/dev/define/audio/ui.js +32 -12
  227. package/dist/dev/define/audio/ui.js.map +1 -0
  228. package/dist/dev/define/background/skin.js +1 -1
  229. package/dist/dev/define/media/mux-audio.d.ts +14 -0
  230. package/dist/dev/define/media/mux-audio.d.ts.map +1 -0
  231. package/dist/dev/define/media/mux-audio.js +13 -0
  232. package/dist/dev/define/media/mux-audio.js.map +1 -0
  233. package/dist/dev/define/skin-element.d.ts +1 -1
  234. package/dist/dev/define/skin-element.js +1 -1
  235. package/dist/dev/define/ui/compounds.d.ts +12 -0
  236. package/dist/dev/define/ui/compounds.d.ts.map +1 -0
  237. package/dist/dev/define/ui/compounds.js +62 -0
  238. package/dist/dev/define/ui/compounds.js.map +1 -0
  239. package/dist/dev/define/ui/controls.d.ts +2 -0
  240. package/dist/dev/define/ui/controls.d.ts.map +1 -1
  241. package/dist/dev/define/ui/controls.js +2 -5
  242. package/dist/dev/define/ui/controls.js.map +1 -1
  243. package/dist/dev/define/ui/error-dialog.d.ts +6 -0
  244. package/dist/dev/define/ui/error-dialog.d.ts.map +1 -1
  245. package/dist/dev/define/ui/error-dialog.js +2 -9
  246. package/dist/dev/define/ui/error-dialog.js.map +1 -1
  247. package/dist/dev/define/ui/hotkey.d.ts +9 -0
  248. package/dist/dev/define/ui/hotkey.d.ts.map +1 -0
  249. package/dist/dev/define/ui/hotkey.js +7 -0
  250. package/dist/dev/define/ui/hotkey.js.map +1 -0
  251. package/dist/dev/define/ui/slider.d.ts +10 -0
  252. package/dist/dev/define/ui/slider.d.ts.map +1 -1
  253. package/dist/dev/define/ui/slider.js +2 -13
  254. package/dist/dev/define/ui/slider.js.map +1 -1
  255. package/dist/dev/define/ui/time-slider.d.ts +14 -0
  256. package/dist/dev/define/ui/time-slider.d.ts.map +1 -1
  257. package/dist/dev/define/ui/time-slider.js +2 -17
  258. package/dist/dev/define/ui/time-slider.js.map +1 -1
  259. package/dist/dev/define/ui/time.d.ts +4 -0
  260. package/dist/dev/define/ui/time.d.ts.map +1 -1
  261. package/dist/dev/define/ui/time.js +2 -7
  262. package/dist/dev/define/ui/time.js.map +1 -1
  263. package/dist/dev/define/ui/volume-slider.d.ts +10 -0
  264. package/dist/dev/define/ui/volume-slider.d.ts.map +1 -1
  265. package/dist/dev/define/ui/volume-slider.js +2 -13
  266. package/dist/dev/define/ui/volume-slider.js.map +1 -1
  267. package/dist/dev/define/video/minimal-skin.css +23 -0
  268. package/dist/dev/define/video/minimal-ui.js +39 -18
  269. package/dist/dev/define/video/minimal-ui.js.map +1 -0
  270. package/dist/dev/define/video/skin.css +23 -0
  271. package/dist/dev/define/video/skin.d.ts.map +1 -1
  272. package/dist/dev/define/video/skin.js +26 -0
  273. package/dist/dev/define/video/skin.js.map +1 -1
  274. package/dist/dev/define/video/ui.js +43 -18
  275. package/dist/dev/define/video/ui.js.map +1 -0
  276. package/dist/dev/index.d.ts +7 -2
  277. package/dist/dev/index.js +6 -1
  278. package/dist/dev/media/container-element.d.ts +3 -0
  279. package/dist/dev/media/container-element.d.ts.map +1 -1
  280. package/dist/dev/media/container-element.js +16 -0
  281. package/dist/dev/media/container-element.js.map +1 -1
  282. package/dist/dev/media/mux-audio/index.d.ts +11 -0
  283. package/dist/dev/media/mux-audio/index.d.ts.map +1 -0
  284. package/dist/dev/media/mux-audio/index.js +18 -0
  285. package/dist/dev/media/mux-audio/index.js.map +1 -0
  286. package/dist/dev/player/context.d.ts +4 -2
  287. package/dist/dev/player/context.d.ts.map +1 -1
  288. package/dist/dev/player/context.js.map +1 -1
  289. package/dist/dev/ui/alert-dialog/alert-dialog-element.d.ts.map +1 -1
  290. package/dist/dev/ui/alert-dialog/alert-dialog-element.js +1 -0
  291. package/dist/dev/ui/alert-dialog/alert-dialog-element.js.map +1 -1
  292. package/dist/dev/ui/buffering-indicator/buffering-indicator-element.d.ts.map +1 -1
  293. package/dist/dev/ui/buffering-indicator/buffering-indicator-element.js +1 -0
  294. package/dist/dev/ui/buffering-indicator/buffering-indicator-element.js.map +1 -1
  295. package/dist/dev/ui/captions-button/captions-button-element.d.ts +1 -0
  296. package/dist/dev/ui/captions-button/captions-button-element.d.ts.map +1 -1
  297. package/dist/dev/ui/captions-button/captions-button-element.js +1 -0
  298. package/dist/dev/ui/captions-button/captions-button-element.js.map +1 -1
  299. package/dist/dev/ui/context-part-element.d.ts +1 -1
  300. package/dist/dev/ui/error-dialog/error-dialog-element.d.ts.map +1 -1
  301. package/dist/dev/ui/error-dialog/error-dialog-element.js +1 -0
  302. package/dist/dev/ui/error-dialog/error-dialog-element.js.map +1 -1
  303. package/dist/dev/ui/fullscreen-button/fullscreen-button-element.d.ts +1 -0
  304. package/dist/dev/ui/fullscreen-button/fullscreen-button-element.d.ts.map +1 -1
  305. package/dist/dev/ui/fullscreen-button/fullscreen-button-element.js +1 -0
  306. package/dist/dev/ui/fullscreen-button/fullscreen-button-element.js.map +1 -1
  307. package/dist/dev/ui/gesture/gesture-element.d.ts +22 -0
  308. package/dist/dev/ui/gesture/gesture-element.d.ts.map +1 -0
  309. package/dist/dev/ui/gesture/gesture-element.js +84 -0
  310. package/dist/dev/ui/gesture/gesture-element.js.map +1 -0
  311. package/dist/dev/ui/hotkey/aria-key-shortcuts-controller.d.ts +15 -0
  312. package/dist/dev/ui/hotkey/aria-key-shortcuts-controller.d.ts.map +1 -0
  313. package/dist/dev/ui/hotkey/aria-key-shortcuts-controller.js +28 -0
  314. package/dist/dev/ui/hotkey/aria-key-shortcuts-controller.js.map +1 -0
  315. package/dist/dev/ui/hotkey/hotkey-element.d.ts +21 -0
  316. package/dist/dev/ui/hotkey/hotkey-element.d.ts.map +1 -0
  317. package/dist/dev/ui/hotkey/hotkey-element.js +81 -0
  318. package/dist/dev/ui/hotkey/hotkey-element.js.map +1 -0
  319. package/dist/dev/ui/media-button-element.d.ts +2 -0
  320. package/dist/dev/ui/media-button-element.d.ts.map +1 -1
  321. package/dist/dev/ui/media-button-element.js +9 -1
  322. package/dist/dev/ui/media-button-element.js.map +1 -1
  323. package/dist/dev/ui/mute-button/mute-button-element.d.ts +1 -0
  324. package/dist/dev/ui/mute-button/mute-button-element.d.ts.map +1 -1
  325. package/dist/dev/ui/mute-button/mute-button-element.js +1 -0
  326. package/dist/dev/ui/mute-button/mute-button-element.js.map +1 -1
  327. package/dist/dev/ui/pip-button/pip-button-element.d.ts +1 -0
  328. package/dist/dev/ui/pip-button/pip-button-element.d.ts.map +1 -1
  329. package/dist/dev/ui/pip-button/pip-button-element.js +1 -0
  330. package/dist/dev/ui/pip-button/pip-button-element.js.map +1 -1
  331. package/dist/dev/ui/play-button/play-button-element.d.ts +1 -0
  332. package/dist/dev/ui/play-button/play-button-element.d.ts.map +1 -1
  333. package/dist/dev/ui/play-button/play-button-element.js +1 -0
  334. package/dist/dev/ui/play-button/play-button-element.js.map +1 -1
  335. package/dist/dev/ui/popover/popover-element.d.ts.map +1 -1
  336. package/dist/dev/ui/popover/popover-element.js +7 -55
  337. package/dist/dev/ui/popover/popover-element.js.map +1 -1
  338. package/dist/dev/ui/position-controller.js +76 -0
  339. package/dist/dev/ui/position-controller.js.map +1 -0
  340. package/dist/dev/ui/slider/slider-element.js +1 -1
  341. package/dist/dev/ui/slider/slider-preview-element.d.ts +21 -0
  342. package/dist/dev/ui/slider/slider-preview-element.d.ts.map +1 -0
  343. package/dist/dev/ui/slider/slider-preview-element.js +1 -1
  344. package/dist/dev/ui/time-slider/time-slider-element.d.ts +2 -2
  345. package/dist/dev/ui/time-slider/time-slider-element.js +5 -5
  346. package/dist/dev/ui/time-slider/time-slider-element.js.map +1 -1
  347. package/dist/dev/ui/tooltip/tooltip-element.d.ts.map +1 -1
  348. package/dist/dev/ui/tooltip/tooltip-element.js +8 -54
  349. package/dist/dev/ui/tooltip/tooltip-element.js.map +1 -1
  350. package/dist/dev/ui/volume-slider/volume-slider-element.js +1 -1
  351. package/package.json +8 -8
  352. package/cdn/context-BjrbhiSk.js.map +0 -1
  353. package/cdn/context-CdkhXQEw.js +0 -14
  354. package/cdn/context-CdkhXQEw.js.map +0 -1
  355. package/cdn/create-player-BqU8r8H4.js +0 -7
  356. package/cdn/create-player-BqU8r8H4.js.map +0 -1
  357. package/cdn/create-player-p9xCO0yC.js.map +0 -1
  358. package/cdn/delegate-B626t_Va.js +0 -2
  359. package/cdn/delegate-B626t_Va.js.map +0 -1
  360. package/cdn/delegate-BCw-LjP_.js +0 -56
  361. package/cdn/delegate-BCw-LjP_.js.map +0 -1
  362. package/cdn/media-props-mixin-Bd_N2HWy.js +0 -47
  363. package/cdn/media-props-mixin-Bd_N2HWy.js.map +0 -1
  364. package/cdn/media-props-mixin-Dc5dpCV4.js.map +0 -1
  365. package/cdn/minimal-ui-BL9eBXck.js +0 -0
  366. package/cdn/minimal-ui-a1UOKF79.js +0 -0
  367. package/cdn/native-hls-CjRvSXAJ.js +0 -2
  368. package/cdn/player-Cz9-_j7J.js +0 -2
  369. package/cdn/poster-2FPYTjyv.js +0 -2
  370. package/cdn/poster-2FPYTjyv.js.map +0 -1
  371. package/cdn/poster-gVT-J1-z.js +0 -215
  372. package/cdn/poster-gVT-J1-z.js.map +0 -1
  373. package/cdn/ui-CFIgmrlA.js +0 -0
  374. package/cdn/ui-Ccp_LyCf.js +0 -0
  375. package/cdn/volume-slider-Co5X4Z1t.js.map +0 -1
  376. package/cdn/volume-slider-D18sXnIA.js +0 -8
  377. package/cdn/volume-slider-D18sXnIA.js.map +0 -1
@@ -1,9 +1,14 @@
1
1
  import { t as listen } from "./listen-w-Aun0yN.js";
2
- import { a as ContextRequestEvent, n as mediaContext, r as playerContext, t as containerContext } from "./context-BjrbhiSk.js";
3
- import { t as anyAbortSignal } from "./abort-CzqmAxxH.js";
4
- import { t as shallowEqual } from "./shallow-equal-C8Fs4TTE.js";
2
+ import { a as ContextRequestEvent, n as mediaContext, r as playerContext, t as containerContext } from "./context-CvJ83xGk.js";
3
+ import { t as anyAbortSignal } from "./abort-BL-SGV3o.js";
4
+ import { t as shallowEqual } from "./shallow-equal-Ca0qjpLJ.js";
5
5
 
6
6
  //#region ../utils/dist/dom/event.js
7
+ /** Resolve the deepest event target, preferring composedPath for shadow DOM. */
8
+ function resolveEventTarget(event) {
9
+ const path = event.composedPath();
10
+ return path.length > 0 ? path[0] : event.target;
11
+ }
7
12
  function onEvent(target, type, options) {
8
13
  return new Promise((resolve, reject) => {
9
14
  const handleAbort = () => {
@@ -25,64 +30,35 @@ function onEvent(target, type, options) {
25
30
  }
26
31
 
27
32
  //#endregion
28
- //#region ../utils/dist/dom/supports.js
29
- function supportsAnchorPositioning() {
30
- return typeof CSS !== "undefined" && CSS.supports("anchor-name: --a");
31
- }
32
-
33
- //#endregion
34
- //#region ../utils/dist/dom/popover.js
35
- function tryShowPopover(el) {
36
- try {
37
- el?.showPopover?.();
38
- } catch {}
39
- }
40
- function tryHidePopover(el) {
41
- try {
42
- el?.hidePopover?.();
43
- } catch {}
44
- }
45
-
46
- //#endregion
47
- //#region ../utils/dist/string/casing.js
48
- function kebabCase(str) {
49
- return str.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
33
+ //#region ../utils/dist/dom/predicates.js
34
+ const EDITABLE_INPUT_TYPES = new Set([
35
+ "text",
36
+ "search",
37
+ "url",
38
+ "tel",
39
+ "email",
40
+ "password",
41
+ "number"
42
+ ]);
43
+ function isEditableElement(el) {
44
+ if (el instanceof HTMLTextAreaElement) return true;
45
+ if (el instanceof HTMLSelectElement) return true;
46
+ if (el instanceof HTMLInputElement) return EDITABLE_INPUT_TYPES.has(el.type.toLowerCase());
47
+ if (!(el instanceof HTMLElement)) return false;
48
+ const editable = el.getAttribute("contenteditable");
49
+ return editable !== null && editable !== "false";
50
50
  }
51
-
52
- //#endregion
53
- //#region ../utils/dist/dom/style.js
54
- function applyStyles(element, styles) {
55
- for (const [prop, value] of Object.entries(styles)) if (typeof value === "string") {
56
- const key = prop.startsWith("--") ? prop : kebabCase(prop);
57
- element.style.setProperty(key, value);
58
- }
51
+ /** Whether the keyboard event target is an editable element (input, textarea, etc). */
52
+ function isEditableTarget(event) {
53
+ const target = resolveEventTarget(event);
54
+ return target instanceof Element && isEditableElement(target);
59
55
  }
60
- function resolveCSSLength(el, value) {
61
- const trimmed = value.trim();
62
- if (!trimmed) return 0;
63
- const parsed = Number.parseFloat(trimmed);
64
- if (Number.isNaN(parsed)) return 0;
65
- if (/^-?\d*\.?\d+$/.test(trimmed) || trimmed.endsWith("px")) return parsed;
66
- const doc = el.ownerDocument;
67
- const root = doc?.documentElement;
68
- if (trimmed.endsWith("rem")) return parsed * (root ? Number.parseFloat(getComputedStyle(root).fontSize) || 16 : 16);
69
- if (trimmed.endsWith("em")) return parsed * (el instanceof HTMLElement ? Number.parseFloat(getComputedStyle(el).fontSize) || 16 : 16);
70
- if (!doc) return parsed;
71
- const measurementEl = doc.createElement("div");
72
- measurementEl.style.position = "absolute";
73
- measurementEl.style.visibility = "hidden";
74
- measurementEl.style.pointerEvents = "none";
75
- measurementEl.style.inlineSize = trimmed;
76
- measurementEl.style.blockSize = "0";
77
- measurementEl.style.padding = "0";
78
- measurementEl.style.border = "0";
79
- measurementEl.style.inset = "0";
80
- const parent = doc.body ?? doc.documentElement;
81
- if (!parent) return parsed;
82
- parent.appendChild(measurementEl);
83
- const pixels = measurementEl.getBoundingClientRect().width;
84
- measurementEl.remove();
85
- return Number.isFinite(pixels) ? pixels : parsed;
56
+ const INTERACTIVE_SELECTOR = "button, input, select, textarea, [role=\"button\"], [role=\"slider\"]";
57
+ /** Whether the event originated from an interactive control (button, slider, etc). */
58
+ function isInteractiveTarget(event) {
59
+ const target = resolveEventTarget(event);
60
+ if (!(target instanceof Element)) return false;
61
+ return target.closest(INTERACTIVE_SELECTOR) !== null;
86
62
  }
87
63
 
88
64
  //#endregion
@@ -97,7 +73,7 @@ function getTextTrackList(media, filterPred) {
97
73
  return Array.from(media.textTracks).filter(filterPred).sort(sortByTextTrackKind);
98
74
  }
99
75
  function sortByTextTrackKind(a, b) {
100
- return a.kind >= b.kind ? 1 : -1;
76
+ return a.kind > b.kind ? 1 : a.kind < b.kind ? -1 : 0;
101
77
  }
102
78
 
103
79
  //#endregion
@@ -468,190 +444,398 @@ function resolve(ctor) {
468
444
  }
469
445
 
470
446
  //#endregion
471
- //#region ../utils/dist/predicate/predicate.js
472
- function isNumber(value) {
473
- return typeof value === "number";
474
- }
475
- function isFunction(value) {
476
- return typeof value === "function";
477
- }
478
- function isNull(value) {
479
- return value === null;
480
- }
481
- function isUndefined(value) {
482
- return typeof value === "undefined";
483
- }
447
+ //#region ../../node_modules/.pnpm/@lit+context@1.1.6/node_modules/@lit/context/development/lib/controllers/context-consumer.js
484
448
  /**
485
- * Check if a value is an object, excluding null.
449
+ * @license
450
+ * Copyright 2021 Google LLC
451
+ * SPDX-License-Identifier: BSD-3-Clause
486
452
  */
487
- function isObject(value) {
488
- return value !== null && typeof value === "object";
489
- }
490
-
491
- //#endregion
492
- //#region ../store/dist/dev/core/abort-controller-registry.js
493
- var AbortControllerRegistry = class {
494
- #base = new AbortController();
495
- #keys = /* @__PURE__ */ new Map();
496
- /** The attach-scoped signal. Aborts on detach or reattach. */
497
- get base() {
498
- return this.#base.signal;
453
+ /**
454
+ * A ReactiveController which adds context consuming behavior to a custom
455
+ * element by dispatching `context-request` events.
456
+ *
457
+ * When the host element is connected to the document it will emit a
458
+ * `context-request` event with its context key. When the context request
459
+ * is satisfied the controller will invoke the callback, if present, and
460
+ * trigger a host update so it can respond to the new value.
461
+ *
462
+ * It will also call the dispose method given by the provider when the
463
+ * host element is disconnected.
464
+ */
465
+ var ContextConsumer = class {
466
+ constructor(host, contextOrOptions, callback, subscribe) {
467
+ this.subscribe = false;
468
+ this.provided = false;
469
+ this.value = void 0;
470
+ this._callback = (value, unsubscribe) => {
471
+ if (this.unsubscribe) {
472
+ if (this.unsubscribe !== unsubscribe) {
473
+ this.provided = false;
474
+ this.unsubscribe();
475
+ }
476
+ if (!this.subscribe) this.unsubscribe();
477
+ }
478
+ this.value = value;
479
+ this.host.requestUpdate();
480
+ if (!this.provided || this.subscribe) {
481
+ this.provided = true;
482
+ if (this.callback) this.callback(value, unsubscribe);
483
+ }
484
+ this.unsubscribe = unsubscribe;
485
+ };
486
+ this.host = host;
487
+ if (contextOrOptions.context !== void 0) {
488
+ const options = contextOrOptions;
489
+ this.context = options.context;
490
+ this.callback = options.callback;
491
+ this.subscribe = options.subscribe ?? false;
492
+ } else {
493
+ this.context = contextOrOptions;
494
+ this.callback = callback;
495
+ this.subscribe = subscribe ?? false;
496
+ }
497
+ this.host.addController(this);
499
498
  }
500
- /** Clears all keyed signals, leaving base intact. */
501
- clear() {
502
- for (const controller of this.#keys.values()) controller.abort();
503
- this.#keys.clear();
499
+ hostConnected() {
500
+ this.dispatchRequest();
504
501
  }
505
- /** Resets base and clears all keyed signals. */
506
- reset() {
507
- this.clear();
508
- this.#base.abort();
509
- this.#base = new AbortController();
502
+ hostDisconnected() {
503
+ if (this.unsubscribe) {
504
+ this.unsubscribe();
505
+ this.unsubscribe = void 0;
506
+ }
510
507
  }
511
- /** Creates a new signal for the key, superseding any previous signal. */
512
- supersede(key) {
513
- this.#keys.get(key)?.abort();
514
- const controller = new AbortController();
515
- this.#keys.set(key, controller);
516
- return anyAbortSignal([this.#base.signal, controller.signal]);
508
+ dispatchRequest() {
509
+ this.host.dispatchEvent(new ContextRequestEvent(this.context, this.host, this._callback, this.subscribe));
517
510
  }
518
511
  };
519
512
 
520
513
  //#endregion
521
- //#region ../store/dist/dev/core/combine.js
514
+ //#region ../../node_modules/.pnpm/@lit+context@1.1.6/node_modules/@lit/context/development/lib/value-notifier.js
522
515
  /**
523
- * Combines multiple slices into a single slice.
516
+ * @license
517
+ * Copyright 2021 Google LLC
518
+ * SPDX-License-Identifier: BSD-3-Clause
519
+ */
520
+ /**
521
+ * A simple class which stores a value, and triggers registered callbacks when
522
+ * the value is changed via its setter.
524
523
  *
525
- * @param slices - The slices to combine.
526
- * @returns A new slice that represents the combination of the input slices.
524
+ * An implementor might use other observable patterns such as MobX or Redux to
525
+ * get behavior like this. But this is a pretty minimal approach that will
526
+ * likely work for a number of use cases.
527
527
  */
528
- function combine(...slices) {
529
- return {
530
- state: (ctx) => {
531
- const states = slices.map((slice) => slice.state(ctx));
532
- return Object.assign({}, ...states);
533
- },
534
- attach: (ctx) => {
535
- for (const slice of slices) try {
536
- slice.attach?.(ctx);
537
- } catch (err) {
538
- ctx.reportError(err);
539
- }
528
+ var ValueNotifier = class {
529
+ get value() {
530
+ return this._value;
531
+ }
532
+ set value(v) {
533
+ this.setValue(v);
534
+ }
535
+ setValue(v, force = false) {
536
+ const update = force || !Object.is(v, this._value);
537
+ this._value = v;
538
+ if (update) this.updateObservers();
539
+ }
540
+ constructor(defaultValue) {
541
+ this.subscriptions = /* @__PURE__ */ new Map();
542
+ this.updateObservers = () => {
543
+ for (const [callback, { disposer }] of this.subscriptions) callback(this._value, disposer);
544
+ };
545
+ if (defaultValue !== void 0) this.value = defaultValue;
546
+ }
547
+ addCallback(callback, consumerHost, subscribe) {
548
+ if (!subscribe) {
549
+ callback(this.value);
550
+ return;
540
551
  }
541
- };
542
- }
543
-
544
- //#endregion
545
- //#region ../store/dist/dev/core/errors.js
546
- var StoreError = class extends Error {
547
- code;
548
- cause;
549
- constructor(code, options) {
550
- super(options?.message ?? code);
551
- this.name = "StoreError";
552
- this.code = code;
553
- this.cause = options?.cause;
552
+ if (!this.subscriptions.has(callback)) this.subscriptions.set(callback, {
553
+ disposer: () => {
554
+ this.subscriptions.delete(callback);
555
+ },
556
+ consumerHost
557
+ });
558
+ const { disposer } = this.subscriptions.get(callback);
559
+ callback(this.value, disposer);
560
+ }
561
+ clearCallbacks() {
562
+ this.subscriptions.clear();
554
563
  }
555
564
  };
556
- function throwNoTargetError() {
557
- throw new StoreError("NO_TARGET");
558
- }
559
- function throwDestroyedError() {
560
- throw new StoreError("DESTROYED");
561
- }
562
565
 
563
566
  //#endregion
564
- //#region ../utils/dist/object/pick.js
567
+ //#region ../../node_modules/.pnpm/@lit+context@1.1.6/node_modules/@lit/context/development/lib/controllers/context-provider.js
565
568
  /**
566
- * Creates a new object with only the specified keys.
567
- *
568
- * @example
569
- * const obj = { a: 1, b: 2, c: 3 };
570
- * pick(obj, ['a', 'c']); // { a: 1, c: 3 }
569
+ * @license
570
+ * Copyright 2021 Google LLC
571
+ * SPDX-License-Identifier: BSD-3-Clause
571
572
  */
572
- function pick(obj, keys) {
573
- const result = {};
574
- for (const key of keys) result[key] = obj[key];
575
- return result;
576
- }
577
-
578
- //#endregion
579
- //#region ../store/dist/dev/core/selector.js
580
- const stateContext = {
581
- target: throwNoTargetError,
582
- signals: new AbortControllerRegistry(),
583
- set: throwNoTargetError
573
+ var ContextProviderEvent = class extends Event {
574
+ /**
575
+ *
576
+ * @param context the context which this provider can provide
577
+ * @param contextTarget the original context target of the provider
578
+ */
579
+ constructor(context, contextTarget) {
580
+ super("context-provider", {
581
+ bubbles: true,
582
+ composed: true
583
+ });
584
+ this.context = context;
585
+ this.contextTarget = contextTarget;
586
+ }
584
587
  };
585
588
  /**
586
- * Create a type-safe selector for a slice's state.
587
- *
588
- * The selector returns the slice's state, or `undefined` if the slice
589
- * is not configured in the store.
589
+ * A ReactiveController which adds context provider behavior to a
590
+ * custom element.
590
591
  *
591
- * @example
592
- * ```ts
593
- * const selectPlayback = createSelector(playbackSlice);
594
- * selectPlayback(store.state); // { paused, play, pause, ... } | undefined
595
- * selectPlayback.displayName; // 'playback' (from slice name)
596
- * ```
592
+ * This controller simply listens to the `context-request` event when
593
+ * the host is connected to the DOM and registers the received callbacks
594
+ * against its observable Context implementation.
597
595
  *
598
- * @param slice - The slice to create a selector for.
599
- */
600
- function createSelector(slice) {
601
- const initialState = slice.state(stateContext);
602
- const keys = Object.keys(initialState);
603
- const firstKey = keys[0];
604
- if (!firstKey) return Object.assign(() => void 0, { displayName: slice.name });
605
- return Object.assign((state) => {
606
- if (!(firstKey in state)) return void 0;
607
- return pick(state, keys);
608
- }, { displayName: slice.name });
609
- }
610
-
611
- //#endregion
612
- //#region ../store/dist/dev/core/slice.js
613
- function defineSlice() {
614
- return (config) => config;
615
- }
616
-
617
- //#endregion
618
- //#region ../utils/dist/function/noop.js
619
- function noop(..._args) {}
620
-
621
- //#endregion
622
- //#region ../utils/dist/function/throttle.js
623
- /**
624
- * Trailing-edge throttle: the first call schedules a timer; subsequent calls
625
- * within the window update the arguments. The function fires once per `ms`
626
- * window with the latest arguments.
596
+ * The controller may also be attached to any HTML element in which case it's
597
+ * up to the user to call hostConnected() when attached to the DOM. This is
598
+ * done automatically for any custom elements implementing
599
+ * ReactiveControllerHost.
627
600
  */
628
- function throttle(fn, ms) {
629
- let timerId = null;
630
- let latestArgs;
631
- const throttled = (...args) => {
632
- latestArgs = args;
633
- if (timerId !== null) return;
634
- timerId = setTimeout(() => {
635
- timerId = null;
636
- fn(...latestArgs);
637
- }, ms);
638
- };
639
- throttled.cancel = () => {
640
- if (timerId !== null) {
641
- clearTimeout(timerId);
642
- timerId = null;
643
- }
644
- };
645
- return throttled;
646
- }
647
-
648
- //#endregion
649
- //#region ../store/dist/dev/core/state.js
650
- let isFlushScheduled = false;
651
- function scheduleFlush() {
652
- if (isFlushScheduled) return;
653
- isFlushScheduled = true;
654
- queueMicrotask(flush);
601
+ var ContextProvider = class extends ValueNotifier {
602
+ constructor(host, contextOrOptions, initialValue) {
603
+ super(contextOrOptions.context !== void 0 ? contextOrOptions.initialValue : initialValue);
604
+ this.onContextRequest = (ev) => {
605
+ if (ev.context !== this.context) return;
606
+ const consumerHost = ev.contextTarget ?? ev.composedPath()[0];
607
+ if (consumerHost === this.host) return;
608
+ ev.stopPropagation();
609
+ this.addCallback(ev.callback, consumerHost, ev.subscribe);
610
+ };
611
+ /**
612
+ * When we get a provider request event, that means a child of this element
613
+ * has just woken up. If it's a provider of our context, then we may need to
614
+ * re-parent our subscriptions, because is a more specific provider than us
615
+ * for its subtree.
616
+ */
617
+ this.onProviderRequest = (ev) => {
618
+ if (ev.context !== this.context) return;
619
+ if ((ev.contextTarget ?? ev.composedPath()[0]) === this.host) return;
620
+ const seen = /* @__PURE__ */ new Set();
621
+ for (const [callback, { consumerHost }] of this.subscriptions) {
622
+ if (seen.has(callback)) continue;
623
+ seen.add(callback);
624
+ consumerHost.dispatchEvent(new ContextRequestEvent(this.context, consumerHost, callback, true));
625
+ }
626
+ ev.stopPropagation();
627
+ };
628
+ this.host = host;
629
+ if (contextOrOptions.context !== void 0) this.context = contextOrOptions.context;
630
+ else this.context = contextOrOptions;
631
+ this.attachListeners();
632
+ this.host.addController?.(this);
633
+ }
634
+ attachListeners() {
635
+ this.host.addEventListener("context-request", this.onContextRequest);
636
+ this.host.addEventListener("context-provider", this.onProviderRequest);
637
+ }
638
+ hostConnected() {
639
+ this.host.dispatchEvent(new ContextProviderEvent(this.context, this.host));
640
+ }
641
+ };
642
+
643
+ //#endregion
644
+ //#region src/store/container-mixin.ts
645
+ /**
646
+ * Create a mixin that consumes player context and registers itself as the
647
+ * container element with the provider via `containerContext`.
648
+ *
649
+ * @param config - Container configuration with player and container contexts.
650
+ */
651
+ function createContainerMixin(config) {
652
+ return (BaseClass) => {
653
+ class PlayerContainerElement extends BaseClass {
654
+ #contextStore = null;
655
+ #setContainer = null;
656
+ constructor(...args) {
657
+ super(...args);
658
+ new ContextConsumer(this, {
659
+ context: config.playerContext,
660
+ callback: (value) => {
661
+ this.#contextStore = value ?? null;
662
+ },
663
+ subscribe: true
664
+ });
665
+ new ContextConsumer(this, {
666
+ context: config.containerContext,
667
+ callback: (value) => {
668
+ this.#setContainer = value?.setContainer ?? null;
669
+ if (this.isConnected) this.#setContainer?.(this);
670
+ },
671
+ subscribe: true
672
+ });
673
+ }
674
+ get store() {
675
+ return this.#contextStore;
676
+ }
677
+ connectedCallback() {
678
+ super.connectedCallback();
679
+ this.#setContainer?.(this);
680
+ }
681
+ disconnectedCallback() {
682
+ super.disconnectedCallback();
683
+ this.#setContainer?.(null);
684
+ }
685
+ }
686
+ return PlayerContainerElement;
687
+ };
688
+ }
689
+
690
+ //#endregion
691
+ //#region src/ui/media-element.ts
692
+ /** Base class for interactive media UI elements. */
693
+ var MediaElement = class extends DestroyMixin(ReactiveElement) {};
694
+
695
+ //#endregion
696
+ //#region src/media/container-element.ts
697
+ const ContainerMixin = createContainerMixin({
698
+ playerContext,
699
+ containerContext
700
+ });
701
+ var MediaContainerElement = class extends ContainerMixin(MediaElement) {
702
+ static {
703
+ this.tagName = "media-container";
704
+ }
705
+ #disconnect = null;
706
+ connectedCallback() {
707
+ super.connectedCallback();
708
+ if (!this.hasAttribute("tabindex")) this.setAttribute("tabindex", "0");
709
+ this.#disconnect = new AbortController();
710
+ listen(this, "pointerup", this.#onPointerUp, { signal: this.#disconnect.signal });
711
+ }
712
+ disconnectedCallback() {
713
+ super.disconnectedCallback();
714
+ this.#disconnect?.abort();
715
+ this.#disconnect = null;
716
+ }
717
+ #onPointerUp = () => {
718
+ if (!this.contains(document.activeElement) || document.activeElement === document.body) this.focus({ preventScroll: true });
719
+ };
720
+ };
721
+
722
+ //#endregion
723
+ //#region ../utils/dist/predicate/predicate.js
724
+ function isNumber(value) {
725
+ return typeof value === "number";
726
+ }
727
+ function isFunction(value) {
728
+ return typeof value === "function";
729
+ }
730
+ function isNull(value) {
731
+ return value === null;
732
+ }
733
+ function isUndefined(value) {
734
+ return typeof value === "undefined";
735
+ }
736
+ /**
737
+ * Check if a value is an object, excluding null.
738
+ */
739
+ function isObject(value) {
740
+ return value !== null && typeof value === "object";
741
+ }
742
+
743
+ //#endregion
744
+ //#region ../store/dist/dev/core/abort-controller-registry.js
745
+ var AbortControllerRegistry = class {
746
+ #base = new AbortController();
747
+ #keys = /* @__PURE__ */ new Map();
748
+ /** The attach-scoped signal. Aborts on detach or reattach. */
749
+ get base() {
750
+ return this.#base.signal;
751
+ }
752
+ /** Clears all keyed signals, leaving base intact. */
753
+ clear() {
754
+ for (const controller of this.#keys.values()) controller.abort();
755
+ this.#keys.clear();
756
+ }
757
+ /** Resets base and clears all keyed signals. */
758
+ reset() {
759
+ this.clear();
760
+ this.#base.abort();
761
+ this.#base = new AbortController();
762
+ }
763
+ /** Creates a new signal for the key, superseding any previous signal. */
764
+ supersede(key) {
765
+ this.#keys.get(key)?.abort();
766
+ const controller = new AbortController();
767
+ this.#keys.set(key, controller);
768
+ return anyAbortSignal([this.#base.signal, controller.signal]);
769
+ }
770
+ };
771
+
772
+ //#endregion
773
+ //#region ../store/dist/dev/core/combine.js
774
+ /**
775
+ * Combines multiple slices into a single slice.
776
+ *
777
+ * @param slices - The slices to combine.
778
+ * @returns A new slice that represents the combination of the input slices.
779
+ */
780
+ function combine(...slices) {
781
+ return {
782
+ state: (ctx) => {
783
+ const states = slices.map((slice) => slice.state(ctx));
784
+ {
785
+ const seen = /* @__PURE__ */ new Set();
786
+ for (const state of states) for (const key of Object.keys(state)) {
787
+ if (seen.has(key)) console.warn(`[vjs-store] combine(): duplicate state key "${key}" — later slice overwrites earlier one`);
788
+ seen.add(key);
789
+ }
790
+ }
791
+ return Object.assign({}, ...states);
792
+ },
793
+ attach: (ctx) => {
794
+ for (const slice of slices) try {
795
+ slice.attach?.(ctx);
796
+ } catch (err) {
797
+ ctx.reportError(err);
798
+ }
799
+ }
800
+ };
801
+ }
802
+
803
+ //#endregion
804
+ //#region ../store/dist/dev/core/errors.js
805
+ var StoreError = class extends Error {
806
+ code;
807
+ cause;
808
+ constructor(code, options) {
809
+ super(options?.message ?? code);
810
+ this.name = "StoreError";
811
+ this.code = code;
812
+ this.cause = options?.cause;
813
+ }
814
+ };
815
+ function throwNoTargetError() {
816
+ throw new StoreError("NO_TARGET");
817
+ }
818
+ function throwDestroyedError() {
819
+ throw new StoreError("DESTROYED");
820
+ }
821
+
822
+ //#endregion
823
+ //#region ../store/dist/dev/core/slice.js
824
+ function defineSlice() {
825
+ return (config) => config;
826
+ }
827
+
828
+ //#endregion
829
+ //#region ../utils/dist/function/noop.js
830
+ function noop(..._args) {}
831
+
832
+ //#endregion
833
+ //#region ../store/dist/dev/core/state.js
834
+ let isFlushScheduled = false;
835
+ function scheduleFlush() {
836
+ if (isFlushScheduled) return;
837
+ isFlushScheduled = true;
838
+ queueMicrotask(flush);
655
839
  }
656
840
  const pendingContainers = /* @__PURE__ */ new Set();
657
841
  function flush() {
@@ -733,6 +917,7 @@ function createStore() {
733
917
  return target;
734
918
  },
735
919
  signals,
920
+ get: () => state.current,
736
921
  set: (partial) => state.patch(partial)
737
922
  });
738
923
  state = createState(initialState);
@@ -852,15 +1037,152 @@ const bufferFeature = definePlayerFeature({
852
1037
  }
853
1038
  });
854
1039
 
1040
+ //#endregion
1041
+ //#region ../core/dist/dev/dom/gesture/region.js
1042
+ /**
1043
+ * Determine which named region a pointer position falls into.
1044
+ *
1045
+ * Regions divide the container width equally based on how many are active:
1046
+ * - `left` + `right` → halves (50% / 50%)
1047
+ * - `left` + `center` + `right` → thirds (33% / 34% / 33%)
1048
+ *
1049
+ * Single region: `left` covers the left half, `right` the right half,
1050
+ * and `center` covers the full surface. Partial two-region combos
1051
+ * (e.g. `left` + `center`) use the same natural zones — positions outside
1052
+ * all active zones return `null` so full-surface gestures can handle them.
1053
+ */
1054
+ function resolveRegion(clientX, containerRect, activeRegions) {
1055
+ if (activeRegions.size === 0) return null;
1056
+ const relativeX = clientX - containerRect.left;
1057
+ const width = containerRect.width;
1058
+ if (width === 0) return null;
1059
+ const ratio = relativeX / width;
1060
+ if (activeRegions.size === 2 && activeRegions.has("left") && activeRegions.has("right")) return ratio < .5 ? "left" : "right";
1061
+ if (activeRegions.size === 3) {
1062
+ if (ratio < 1 / 3) return "left";
1063
+ if (ratio < 2 / 3) return "center";
1064
+ return "right";
1065
+ }
1066
+ if (activeRegions.has("left") && ratio < .5) return "left";
1067
+ if (activeRegions.has("right") && ratio >= .5) return "right";
1068
+ if (activeRegions.has("center")) {
1069
+ if (activeRegions.size === 1) return "center";
1070
+ if (ratio >= 1 / 3 && ratio < 2 / 3) return "center";
1071
+ }
1072
+ return null;
1073
+ }
1074
+
1075
+ //#endregion
1076
+ //#region ../core/dist/dev/dom/gesture/coordinator.js
1077
+ const TAP_THRESHOLD$1 = 250;
1078
+ var GestureCoordinator = class {
1079
+ #target;
1080
+ #bindings = [];
1081
+ #recognizers = /* @__PURE__ */ new Set();
1082
+ #disconnect = null;
1083
+ constructor(target) {
1084
+ this.#target = target;
1085
+ }
1086
+ get bindings() {
1087
+ return this.#bindings;
1088
+ }
1089
+ add(binding) {
1090
+ this.#bindings.push(binding);
1091
+ this.#recognizers.add(binding.recognizer);
1092
+ this.#connect();
1093
+ let removed = false;
1094
+ return () => {
1095
+ if (removed) return;
1096
+ removed = true;
1097
+ const idx = this.#bindings.indexOf(binding);
1098
+ if (idx !== -1) this.#bindings.splice(idx, 1);
1099
+ this.#maybeDisconnect();
1100
+ };
1101
+ }
1102
+ #connect() {
1103
+ if (this.#disconnect) return;
1104
+ this.#disconnect = new AbortController();
1105
+ const { signal } = this.#disconnect;
1106
+ let pointerDownTime = 0;
1107
+ listen(this.#target, "pointerdown", () => {
1108
+ pointerDownTime = Date.now();
1109
+ }, { signal });
1110
+ listen(this.#target, "pointerup", (event) => {
1111
+ if (Date.now() - pointerDownTime > TAP_THRESHOLD$1) return;
1112
+ if (isInteractiveTarget(event)) return;
1113
+ const pointerType = event.pointerType;
1114
+ const clientX = event.clientX;
1115
+ const target = this.#target;
1116
+ const bindings = this.#bindings;
1117
+ const matches = { resolve: (type) => matchBindings(bindings, type, pointerType, clientX, target) };
1118
+ for (const recognizer of this.#recognizers) recognizer.handleUp(matches, event);
1119
+ }, { signal });
1120
+ }
1121
+ #maybeDisconnect() {
1122
+ if (this.#bindings.length > 0) return;
1123
+ for (const recognizer of this.#recognizers) recognizer.reset();
1124
+ this.#recognizers.clear();
1125
+ this.#disconnect?.abort();
1126
+ this.#disconnect = null;
1127
+ }
1128
+ };
1129
+ const coordinators = /* @__PURE__ */ new WeakMap();
1130
+ /** Look up the gesture coordinator for a target element, if one exists. */
1131
+ function findGestureCoordinator(target) {
1132
+ return coordinators.get(target);
1133
+ }
1134
+ function getGestureCoordinator(target) {
1135
+ let coordinator = coordinators.get(target);
1136
+ if (!coordinator) {
1137
+ coordinator = new GestureCoordinator(target);
1138
+ coordinators.set(target, coordinator);
1139
+ }
1140
+ return coordinator;
1141
+ }
1142
+ function matchBindings(bindings, type, pointerType, clientX, target) {
1143
+ const rect = target.getBoundingClientRect();
1144
+ const activeRegions = getActiveRegions(bindings, type, pointerType);
1145
+ const region = activeRegions.size > 0 ? resolveRegion(clientX, rect, activeRegions) : null;
1146
+ const matches = [];
1147
+ for (const binding of bindings) {
1148
+ if (binding.disabled) continue;
1149
+ if (binding.type !== type) continue;
1150
+ if (binding.pointer && binding.pointer !== pointerType) continue;
1151
+ if (binding.region) {
1152
+ if (binding.region !== region) continue;
1153
+ } else if (region !== null) continue;
1154
+ matches.push(binding);
1155
+ }
1156
+ return matches;
1157
+ }
1158
+ function getActiveRegions(bindings, type, pointerType) {
1159
+ const regions = /* @__PURE__ */ new Set();
1160
+ for (const binding of bindings) {
1161
+ if (binding.disabled) continue;
1162
+ if (binding.type !== type) continue;
1163
+ if (binding.pointer && binding.pointer !== pointerType) continue;
1164
+ if (binding.region) regions.add(binding.region);
1165
+ }
1166
+ return regions;
1167
+ }
1168
+
855
1169
  //#endregion
856
1170
  //#region ../core/dist/dev/dom/store/features/controls.js
857
1171
  const IDLE_DELAY = 2e3;
858
1172
  const TAP_THRESHOLD = 250;
859
1173
  const controlsFeature = definePlayerFeature({
860
1174
  name: "controls",
861
- state: () => ({
1175
+ state: ({ get, set }) => ({
862
1176
  userActive: true,
863
- controlsVisible: true
1177
+ controlsVisible: true,
1178
+ toggleControls() {
1179
+ const next = !get().userActive;
1180
+ set({
1181
+ userActive: next,
1182
+ controlsVisible: next
1183
+ });
1184
+ return next;
1185
+ }
864
1186
  }),
865
1187
  attach({ target, signal, get, set }) {
866
1188
  const { media, container } = target;
@@ -894,12 +1216,18 @@ const controlsFeature = definePlayerFeature({
894
1216
  controlsVisible: computeVisible(false)
895
1217
  });
896
1218
  }
1219
+ set({ toggleControls() {
1220
+ if (get().controlsVisible) setInactive();
1221
+ else setActive();
1222
+ return get().controlsVisible;
1223
+ } });
897
1224
  let pointerDownTime = 0;
898
1225
  function onPointerDown() {
899
1226
  pointerDownTime = Date.now();
900
1227
  }
901
1228
  function onPointerUp(event) {
902
1229
  if (event.pointerType === "touch" && Date.now() - pointerDownTime < TAP_THRESHOLD) {
1230
+ if (findGestureCoordinator(container)?.bindings.some((b) => b.type === "tap" && b.action === "toggleControls" && (!b.pointer || b.pointer === "touch"))) return;
903
1231
  const isMediaOrContainer = [media, container].includes(event.target);
904
1232
  if (get().controlsVisible && isMediaOrContainer) setInactive();
905
1233
  else setActive();
@@ -1083,6 +1411,12 @@ const fullscreenFeature = definePlayerFeature({
1083
1411
  async exitFullscreen() {
1084
1412
  const { media } = target();
1085
1413
  return exitFullscreen(media);
1414
+ },
1415
+ async toggleFullscreen() {
1416
+ const { media, container } = target();
1417
+ if (isFullscreenElement(container, media)) return exitFullscreen(media);
1418
+ if (isPictureInPictureElement(media)) await exitPictureInPicture(media);
1419
+ return requestFullscreen(container, media);
1086
1420
  }
1087
1421
  }),
1088
1422
  attach({ target, signal, set }) {
@@ -1111,6 +1445,12 @@ const pipFeature = definePlayerFeature({
1111
1445
  async exitPictureInPicture() {
1112
1446
  const { media } = target();
1113
1447
  return exitPictureInPicture(media);
1448
+ },
1449
+ async togglePictureInPicture() {
1450
+ const { media, container } = target();
1451
+ if (isPictureInPictureElement(media)) return exitPictureInPicture(media);
1452
+ if (isFullscreenElement(container, media)) await exitFullscreen();
1453
+ return requestPictureInPicture(media);
1114
1454
  }
1115
1455
  }),
1116
1456
  attach({ target, signal, set }) {
@@ -1138,6 +1478,15 @@ const playbackFeature = definePlayerFeature({
1138
1478
  },
1139
1479
  pause() {
1140
1480
  target().media.pause();
1481
+ },
1482
+ togglePaused() {
1483
+ const media = target().media;
1484
+ if (media.paused) {
1485
+ media.play();
1486
+ return true;
1487
+ }
1488
+ media.pause();
1489
+ return false;
1141
1490
  }
1142
1491
  }),
1143
1492
  attach({ target, signal, set }) {
@@ -1162,6 +1511,9 @@ const playbackFeature = definePlayerFeature({
1162
1511
  //#endregion
1163
1512
  //#region ../core/dist/dev/dom/store/features/playback-rate.js
1164
1513
  const DEFAULT_RATES = [
1514
+ .2,
1515
+ .5,
1516
+ .7,
1165
1517
  1,
1166
1518
  1.2,
1167
1519
  1.5,
@@ -1312,15 +1664,19 @@ const timeFeature = definePlayerFeature({
1312
1664
  return media.currentTime;
1313
1665
  }
1314
1666
  }),
1315
- attach({ target, signal, set }) {
1667
+ attach({ target, signal, set, get }) {
1316
1668
  const { media } = target;
1317
1669
  const sync = () => set({
1318
1670
  currentTime: media.currentTime,
1319
1671
  duration: Number.isFinite(media.duration) ? media.duration : 0,
1320
1672
  seeking: media.seeking
1321
1673
  });
1674
+ const onTimeUpdate = () => {
1675
+ if (get().seeking) return;
1676
+ sync();
1677
+ };
1322
1678
  sync();
1323
- listen(media, "timeupdate", sync, { signal });
1679
+ listen(media, "timeupdate", onTimeUpdate, { signal });
1324
1680
  listen(media, "durationchange", sync, { signal });
1325
1681
  listen(media, "seeking", sync, { signal });
1326
1682
  listen(media, "seeked", sync, { signal });
@@ -1404,1535 +1760,231 @@ const audioFeatures = [
1404
1760
  const backgroundFeatures = [];
1405
1761
 
1406
1762
  //#endregion
1407
- //#region ../core/dist/dev/dom/store/selectors.js
1408
- /** Select the buffer state (buffered ranges, percent buffered). */
1409
- const selectBuffer = createSelector(bufferFeature);
1410
- /** Select the controls state (controls visible, user-active). */
1411
- const selectControls = createSelector(controlsFeature);
1412
- /** Select the error state (error, dismissed, dismissError). */
1413
- const selectError = createSelector(errorFeature);
1414
- /** Select the fullscreen state (fullscreen active, availability). */
1415
- const selectFullscreen = createSelector(fullscreenFeature);
1416
- /** Select the PiP state (picture-in-picture active, availability). */
1417
- const selectPiP = createSelector(pipFeature);
1418
- /** Select the playback state (paused, ended, play, pause, toggle). */
1419
- const selectPlayback = createSelector(playbackFeature);
1420
- /** Select the playback rate state (playbackRate, playbackRates, setPlaybackRate). */
1421
- const selectPlaybackRate = createSelector(playbackRateFeature);
1422
- /** Select the source state (src, type). */
1423
- const selectSource = createSelector(sourceFeature);
1424
- /** Select the text track state (chapters cues, thumbnail cues). */
1425
- const selectTextTrack = createSelector(textTrackFeature);
1426
- /** Select the time state (currentTime, duration, seek). */
1427
- const selectTime = createSelector(timeFeature);
1428
- /** Select the volume state (volume, muted, setVolume, setMuted). */
1429
- const selectVolume = createSelector(volumeFeature);
1430
-
1431
- //#endregion
1432
- //#region ../core/dist/dev/dom/ui/dismiss-layer.js
1433
- function createDismissLayer(options) {
1434
- const { transition } = options;
1435
- const state = transition.state;
1436
- const abort = new AbortController();
1437
- let docAbort = null;
1438
- function open() {
1439
- if (abort.signal.aborted) return null;
1440
- const { active, status } = state.current;
1441
- if (active && status !== "ending") return null;
1442
- if (status === "ending") transition.cancel();
1443
- return transition.open();
1444
- }
1445
- function close(element) {
1446
- const { active, status } = state.current;
1447
- if (abort.signal.aborted || !active || status === "ending") return null;
1448
- return transition.close(element);
1449
- }
1450
- function setupDocumentListeners() {
1451
- cleanupDocumentListeners();
1452
- if (typeof document === "undefined") return;
1453
- docAbort = new AbortController();
1454
- const { signal } = docAbort;
1455
- listen(document, "keydown", handleKeydown, { signal });
1456
- options.onDocumentActive?.(signal);
1457
- }
1458
- function cleanupDocumentListeners() {
1459
- docAbort?.abort();
1460
- docAbort = null;
1461
- }
1462
- function handleKeydown(event) {
1463
- if (event.key !== "Escape") return;
1464
- if (!state.current.active) return;
1465
- if (!(options.closeOnEscape?.() ?? true)) return;
1466
- options.onEscapeDismiss(event);
1467
- }
1468
- const unsubscribe = state.subscribe(() => {
1469
- if (state.current.active) setupDocumentListeners();
1470
- else cleanupDocumentListeners();
1471
- });
1472
- abort.signal.addEventListener("abort", () => {
1473
- unsubscribe();
1474
- transition.destroy();
1475
- cleanupDocumentListeners();
1476
- });
1477
- function destroy() {
1478
- if (abort.signal.aborted) return;
1479
- abort.abort();
1480
- }
1481
- return {
1482
- input: state,
1483
- open,
1484
- close,
1485
- signal: abort.signal,
1486
- destroy
1487
- };
1488
- }
1489
-
1490
- //#endregion
1491
- //#region ../core/dist/dev/dom/ui/alert-dialog.js
1492
- function createAlertDialog(options) {
1493
- const { onOpenChange } = options;
1494
- let element = null;
1495
- let previousFocus = null;
1496
- let elementAbort = null;
1497
- const layer = createDismissLayer({
1498
- transition: options.transition,
1499
- closeOnEscape: options.closeOnEscape,
1500
- onEscapeDismiss(event) {
1501
- event.stopPropagation();
1502
- applyClose();
1503
- }
1504
- });
1505
- const state = layer.input;
1506
- function applyOpen() {
1507
- previousFocus = document.activeElement;
1508
- const opening = layer.open();
1509
- if (!opening) return;
1510
- onOpenChange(true);
1511
- requestAnimationFrame(() => {
1512
- if (layer.signal.aborted || !state.current.active) return;
1513
- element?.focus();
1514
- });
1515
- opening.then(() => {
1516
- if (layer.signal.aborted || !state.current.active) return;
1517
- options.onOpenChangeComplete?.(true);
1518
- });
1519
- }
1520
- function applyClose() {
1521
- const closing = layer.close(element);
1522
- if (!closing) return;
1523
- onOpenChange(false);
1524
- closing.then(() => {
1525
- if (layer.signal.aborted) return;
1526
- if (previousFocus) {
1527
- previousFocus.focus();
1528
- previousFocus = null;
1529
- }
1530
- options.onOpenChangeComplete?.(false);
1531
- });
1763
+ //#region ../store/dist/dev/html/controllers/snapshot-controller.js
1764
+ /**
1765
+ * Subscribe to a `State<T>` container with optional selector.
1766
+ *
1767
+ * Without selector: returns full state, re-renders on any state change.
1768
+ * With selector: returns selected slice, re-renders only when the slice changes (shallowEqual).
1769
+ *
1770
+ * @example
1771
+ * ```ts
1772
+ * #state = new SnapshotController(this, sliderState, (s) => s.value);
1773
+ * ```
1774
+ */
1775
+ var SnapshotController = class {
1776
+ #host;
1777
+ #selector;
1778
+ #state;
1779
+ #cached;
1780
+ #unsubscribe = noop;
1781
+ constructor(host, state, selector) {
1782
+ this.#host = host;
1783
+ this.#state = state;
1784
+ this.#selector = selector;
1785
+ host.addController(this);
1532
1786
  }
1533
- function setupElementListeners() {
1534
- cleanupElementListeners();
1535
- if (!element) return;
1536
- elementAbort = new AbortController();
1537
- const { signal } = elementAbort;
1538
- listen(element, "click", handleElementClick, { signal });
1787
+ get value() {
1788
+ if (!this.#selector) return this.#state.current;
1789
+ this.#cached ??= this.#selector(this.#state.current);
1790
+ return this.#cached;
1539
1791
  }
1540
- function cleanupElementListeners() {
1541
- elementAbort?.abort();
1542
- elementAbort = null;
1792
+ /** Switch to tracking a different state container. */
1793
+ track(state) {
1794
+ this.#state = state;
1795
+ this.#subscribe();
1543
1796
  }
1544
- function handleElementClick(event) {
1545
- if (event.target instanceof HTMLButtonElement) applyClose();
1797
+ hostConnected() {
1798
+ this.#subscribe();
1546
1799
  }
1547
- function setElement(el) {
1548
- element = el;
1549
- setupElementListeners();
1800
+ hostDisconnected() {
1801
+ this.#unsubscribe();
1802
+ this.#unsubscribe = noop;
1803
+ this.#cached = void 0;
1550
1804
  }
1551
- layer.signal.addEventListener("abort", () => {
1552
- cleanupElementListeners();
1553
- element = null;
1554
- previousFocus = null;
1555
- });
1556
- return {
1557
- input: state,
1558
- open: applyOpen,
1559
- close: applyClose,
1560
- setElement,
1561
- destroy: layer.destroy
1562
- };
1563
- }
1564
-
1565
- //#endregion
1566
- //#region ../core/dist/dev/dom/ui/button.js
1567
- function createButton(options) {
1568
- const { onActivate, isDisabled } = options;
1569
- return {
1570
- role: "button",
1571
- tabIndex: 0,
1572
- onClick(event) {
1573
- if (isDisabled()) {
1574
- event.preventDefault();
1575
- return;
1576
- }
1577
- onActivate();
1578
- },
1579
- onPointerDown(event) {
1580
- if (isDisabled()) event.preventDefault();
1581
- },
1582
- onMouseDown(event) {
1583
- if (isDisabled()) event.preventDefault();
1584
- },
1585
- onKeyDown(event) {
1586
- if (event.target !== event.currentTarget) return;
1587
- if (isDisabled()) {
1588
- if (event.key !== "Tab") event.preventDefault();
1589
- return;
1590
- }
1591
- if (event.key === "Enter") {
1592
- event.preventDefault();
1593
- onActivate();
1594
- } else if (event.key === " ") event.preventDefault();
1595
- },
1596
- onKeyUp(event) {
1597
- if (event.target !== event.currentTarget) return;
1598
- if (isDisabled()) return;
1599
- if (event.key === " ") onActivate();
1805
+ #subscribe() {
1806
+ this.#unsubscribe();
1807
+ if (!this.#selector) {
1808
+ this.#unsubscribe = this.#state.subscribe(() => this.#host.requestUpdate());
1809
+ return;
1600
1810
  }
1601
- };
1602
- }
1811
+ const selector = this.#selector;
1812
+ this.#cached = selector(this.#state.current);
1813
+ this.#unsubscribe = this.#state.subscribe(() => {
1814
+ const next = selector(this.#state.current);
1815
+ if (!shallowEqual(this.#cached, next)) {
1816
+ this.#cached = next;
1817
+ this.#host.requestUpdate();
1818
+ }
1819
+ });
1820
+ }
1821
+ };
1603
1822
 
1604
1823
  //#endregion
1605
- //#region ../core/dist/dev/dom/ui/popover/popover.js
1606
- function createPopover(options) {
1607
- const { onOpenChange, closeOnOutsideClick } = options;
1608
- let triggerEl = null;
1609
- let popupEl = null;
1610
- let hoverTimeout = null;
1611
- const capturedPointers = /* @__PURE__ */ new Set();
1612
- const layer = createDismissLayer({
1613
- transition: options.transition,
1614
- closeOnEscape: options.closeOnEscape,
1615
- onEscapeDismiss(event) {
1616
- event.preventDefault();
1617
- applyClose("escape", event);
1618
- },
1619
- onDocumentActive(signal) {
1620
- listen(document, "pointerdown", handleDocumentPointerdown, {
1621
- capture: true,
1622
- signal
1824
+ //#region ../store/dist/dev/html/store-accessor.js
1825
+ /**
1826
+ * Resolves a store from either a direct instance or context.
1827
+ *
1828
+ * When given a direct store, provides immediate access.
1829
+ * When given a context, sets up a ContextConsumer to receive the store.
1830
+ *
1831
+ * @example Direct store
1832
+ * ```ts
1833
+ * const accessor = new StoreAccessor(host, store, (s) => console.log('available', s));
1834
+ * accessor.value; // Store (immediately available)
1835
+ * ```
1836
+ *
1837
+ * @example Context source
1838
+ * ```ts
1839
+ * const accessor = new StoreAccessor(host, context, (s) => console.log('available', s));
1840
+ * accessor.value; // null until context provides store
1841
+ * ```
1842
+ */
1843
+ var StoreAccessor = class {
1844
+ #onAvailable;
1845
+ #consumer;
1846
+ #directStore;
1847
+ constructor(host, source, onAvailable) {
1848
+ this.#onAvailable = onAvailable ?? noop;
1849
+ if (isStore(source)) {
1850
+ this.#directStore = source;
1851
+ this.#consumer = null;
1852
+ } else {
1853
+ this.#directStore = null;
1854
+ this.#consumer = new ContextConsumer(host, {
1855
+ context: source,
1856
+ callback: (store) => this.#onAvailable(store),
1857
+ subscribe: false
1623
1858
  });
1624
1859
  }
1625
- });
1626
- const state = layer.input;
1627
- function clearHoverTimeout() {
1628
- if (hoverTimeout !== null) {
1629
- clearTimeout(hoverTimeout);
1630
- hoverTimeout = null;
1631
- }
1632
- }
1633
- function canHover() {
1634
- return globalThis.matchMedia?.("(hover: hover)")?.matches ?? false;
1635
- }
1636
- function canOpenOnFocus() {
1637
- if (!canHover()) return false;
1638
- return globalThis.matchMedia?.("(pointer: fine)")?.matches ?? false;
1639
- }
1640
- function canToggleOnClick() {
1641
- if (!options.openOnHover?.()) return true;
1642
- return canHover();
1643
- }
1644
- /**
1645
- * The transition handler manages animation lifecycle via `createState`:
1646
- *
1647
- * **Open:** `transition.open()` patches `{ active: true, status: 'starting' }`.
1648
- * After one RAF it patches `{ status: 'idle' }` and the promise resolves.
1649
- * Frameworks render `data-starting-style` / `data-ending-style` via
1650
- * `getPopupAttrs(state)` — no imperative DOM mutation needed.
1651
- *
1652
- * **Close:** `transition.close(el)` patches `{ status: 'ending' }` (keeping
1653
- * `active: true` so the element stays mounted). After a double-RAF it waits
1654
- * for `getAnimations()` to settle, then patches `{ active: false, status: 'idle' }`.
1655
- *
1656
- * `onOpenChange` fires immediately (before animations).
1657
- * `onOpenChangeComplete` fires after animations finish.
1658
- */
1659
- function applyOpen(reason, event) {
1660
- const opening = layer.open();
1661
- if (!opening) return;
1662
- onOpenChange(true, event ? {
1663
- reason,
1664
- event
1665
- } : { reason });
1666
- opening.then(() => {
1667
- if (layer.signal.aborted || !state.current.active) return;
1668
- options.onOpenChangeComplete?.(true);
1669
- });
1670
- }
1671
- function applyClose(reason, event) {
1672
- const closing = layer.close(popupEl);
1673
- if (!closing) return;
1674
- onOpenChange(false, event ? {
1675
- reason,
1676
- event
1677
- } : { reason });
1678
- closing.then(() => {
1679
- if (layer.signal.aborted) return;
1680
- tryHidePopover(popupEl);
1681
- options.onOpenChangeComplete?.(false);
1682
- });
1683
- }
1684
- function open(reason = "click") {
1685
- applyOpen(reason);
1686
- }
1687
- function close(reason = "click") {
1688
- applyClose(reason);
1860
+ host.addController(this);
1689
1861
  }
1690
- function handleDocumentPointerdown(event) {
1691
- if (!closeOnOutsideClick() || !state.current.active) return;
1692
- const path = event.composedPath();
1693
- if (triggerEl && path.includes(triggerEl) || popupEl && path.includes(popupEl)) return;
1694
- applyClose("outside-click", event);
1862
+ /** Returns the store, or null if not yet available from context. */
1863
+ get value() {
1864
+ if (this.#consumer) return this.#consumer.value ?? null;
1865
+ return this.#directStore;
1695
1866
  }
1696
- layer.signal.addEventListener("abort", () => {
1697
- clearHoverTimeout();
1698
- capturedPointers.clear();
1699
- triggerEl = null;
1700
- popupEl = null;
1701
- });
1702
- const triggerProps = {
1703
- onClick(event) {
1704
- if (!canToggleOnClick()) return;
1705
- if (state.current.active && state.current.status !== "ending") applyClose("click", event);
1706
- else applyOpen("click", event);
1707
- },
1708
- onPointerEnter(_event) {
1709
- if (!options.openOnHover?.()) return;
1710
- if (!canHover()) return;
1711
- clearHoverTimeout();
1712
- if (state.current.active) return;
1713
- const delay = options.delay?.() ?? 300;
1714
- hoverTimeout = setTimeout(() => applyOpen("hover"), delay);
1715
- },
1716
- onPointerLeave(_event) {
1717
- if (!options.openOnHover?.()) return;
1718
- if (!canHover()) return;
1719
- clearHoverTimeout();
1720
- if (!state.current.active) return;
1721
- const closeDelay = options.closeDelay?.() ?? 0;
1722
- hoverTimeout = setTimeout(() => applyClose("hover"), closeDelay);
1723
- },
1724
- onFocusIn(_event) {
1725
- if (options.openOnHover?.()) {
1726
- if (!canOpenOnFocus()) return;
1727
- applyOpen("focus");
1728
- }
1729
- },
1730
- onFocusOut(event) {
1731
- const relatedTarget = event.relatedTarget;
1732
- if (relatedTarget && (triggerEl?.contains(relatedTarget) || popupEl?.contains(relatedTarget))) return;
1733
- if (options.openOnHover?.()) applyClose("blur");
1734
- }
1735
- };
1736
- const popupProps = {
1737
- onPointerEnter(_event) {
1738
- if (!options.openOnHover?.()) return;
1739
- clearHoverTimeout();
1740
- },
1741
- onPointerLeave(_event) {
1742
- if (!options.openOnHover?.()) return;
1743
- if (capturedPointers.size > 0) return;
1744
- clearHoverTimeout();
1745
- if (!state.current.active) return;
1746
- const closeDelay = options.closeDelay?.() ?? 0;
1747
- hoverTimeout = setTimeout(() => applyClose("hover"), closeDelay);
1748
- },
1749
- onGotPointerCapture(event) {
1750
- capturedPointers.add(event.pointerId);
1751
- },
1752
- onLostPointerCapture(event) {
1753
- capturedPointers.delete(event.pointerId);
1754
- },
1755
- onFocusOut(event) {
1756
- const relatedTarget = event.relatedTarget;
1757
- if (relatedTarget && (triggerEl?.contains(relatedTarget) || popupEl?.contains(relatedTarget))) return;
1758
- applyClose("blur");
1759
- }
1760
- };
1761
- function setTriggerElement(el) {
1762
- triggerEl = el;
1763
- }
1764
- function setPopupElement(el) {
1765
- if (!el && popupEl && state.current.active) tryHidePopover(popupEl);
1766
- popupEl = el;
1767
- if (el) {
1768
- if (state.current.active) tryShowPopover(el);
1769
- }
1867
+ hostConnected() {
1868
+ if (this.#directStore) this.#onAvailable(this.#directStore);
1770
1869
  }
1771
- return {
1772
- input: state,
1773
- triggerProps,
1774
- popupProps,
1775
- get triggerElement() {
1776
- return triggerEl;
1777
- },
1778
- setTriggerElement,
1779
- setPopupElement,
1780
- open,
1781
- close,
1782
- destroy: layer.destroy
1783
- };
1784
- }
1785
-
1786
- //#endregion
1787
- //#region ../core/dist/dev/core/ui/popover/popover-css-vars.js
1788
- const PopoverCSSVars = {
1789
- sideOffset: "--media-popover-side-offset",
1790
- alignOffset: "--media-popover-align-offset",
1791
- anchorWidth: "--media-popover-anchor-width",
1792
- anchorHeight: "--media-popover-anchor-height",
1793
- availableWidth: "--media-popover-available-width",
1794
- availableHeight: "--media-popover-available-height"
1795
1870
  };
1796
1871
 
1797
1872
  //#endregion
1798
- //#region ../core/dist/dev/dom/ui/popover/popover-positioning.js
1799
- const OPPOSITE_SIDE = {
1800
- top: "bottom",
1801
- bottom: "top",
1802
- left: "right",
1803
- right: "left"
1804
- };
1873
+ //#region ../store/dist/dev/html/controllers/store-controller.js
1805
1874
  /**
1806
- * Get positioning styles for the popup element.
1875
+ * Access store state and actions.
1876
+ *
1877
+ * Without selector: Returns the store, does NOT subscribe to changes.
1878
+ * With selector: Returns selected state, triggers update when selected state changes (shallowEqual).
1879
+ *
1880
+ * @example
1881
+ * ```ts
1882
+ * // Store access (no subscription) - access actions
1883
+ * class Controls extends LitElement {
1884
+ * #store = new StoreController(this, storeSource);
1807
1885
  *
1808
- * When the browser supports CSS Anchor Positioning, returns native CSS properties
1809
- * that reference the provided CSS var names for side/align offsets — no JS offset
1810
- * values needed.
1886
+ * handleClick() {
1887
+ * this.#store.value.setVolume(0.5);
1888
+ * }
1889
+ * }
1811
1890
  *
1812
- * When rects are provided and anchor positioning is unsupported, falls back to
1813
- * manual JS-computed positioning. The caller must resolve offset CSS vars via
1814
- * `getComputedStyle` and pass them as `offsets`.
1891
+ * // Selector-based subscription - re-renders when playback changes
1892
+ * class PlayButton extends LitElement {
1893
+ * #playback = new StoreController(this, storeSource, selectPlayback);
1815
1894
  *
1816
- * Returns camelCase keys for standard CSS properties and `--*` keys for
1817
- * custom properties — compatible with both React's `style` prop and
1818
- * `applyStyles()` from `@videojs/utils/dom`.
1895
+ * render() {
1896
+ * const playback = this.#playback.value;
1897
+ * if (!playback) return nothing;
1898
+ * return html`<button @click=${playback.toggle}>
1899
+ * ${playback.paused ? 'Play' : 'Pause'}
1900
+ * </button>`;
1901
+ * }
1902
+ * }
1903
+ * ```
1819
1904
  */
1820
- function getAnchorPositionStyle(anchorName, opts, triggerRect, popupRect, boundaryRect, offsets, cssVars = PopoverCSSVars) {
1821
- if (supportsAnchorPositioning()) return getAnchorPositionCSS(anchorName, opts, cssVars);
1822
- if (triggerRect && popupRect) return {
1823
- ...getManualPositionStyle(triggerRect, popupRect, opts, offsets ?? {
1824
- sideOffset: 0,
1825
- alignOffset: 0
1826
- }),
1827
- ...boundaryRect ? getPositioningCSSVars(triggerRect, boundaryRect, opts.side, cssVars) : {},
1828
- position: "fixed",
1829
- inset: "auto",
1830
- margin: "0"
1831
- };
1832
- return {};
1833
- }
1834
- /** Generate style to set on the trigger for CSS Anchor Positioning. */
1835
- function getAnchorNameStyle(anchorName) {
1836
- if (!supportsAnchorPositioning()) return {};
1837
- return { anchorName: `--${anchorName}` };
1838
- }
1839
- function getAnchorPositionCSS(anchorName, opts, cssVars = PopoverCSSVars) {
1840
- const SIDE_OFFSET_VAR = `var(${cssVars.sideOffset}, 0px)`;
1841
- const ALIGN_OFFSET_VAR = `var(${cssVars.alignOffset}, 0px)`;
1842
- const { side, align } = opts;
1843
- const style = {
1844
- positionAnchor: `--${anchorName}`,
1845
- position: "fixed",
1846
- inset: "auto",
1847
- margin: "0",
1848
- justifySelf: "normal",
1849
- alignSelf: "normal",
1850
- marginInlineStart: "0",
1851
- marginBlockStart: "0"
1852
- };
1853
- const insetProp = OPPOSITE_SIDE[side];
1854
- if (side === "top" || side === "bottom") {
1855
- style[insetProp] = `calc(anchor(${side}) + ${SIDE_OFFSET_VAR})`;
1856
- if (align === "start") style.left = `calc(anchor(left) + ${ALIGN_OFFSET_VAR})`;
1857
- else if (align === "end") style.right = `calc(anchor(right) + ${ALIGN_OFFSET_VAR})`;
1858
- else {
1859
- style.justifySelf = "anchor-center";
1860
- style.marginInlineStart = ALIGN_OFFSET_VAR;
1861
- }
1862
- } else {
1863
- style[insetProp] = `calc(anchor(${side}) + ${SIDE_OFFSET_VAR})`;
1864
- if (align === "start") style.top = `calc(anchor(top) + ${ALIGN_OFFSET_VAR})`;
1865
- else if (align === "end") style.bottom = `calc(anchor(bottom) + ${ALIGN_OFFSET_VAR})`;
1866
- else {
1867
- style.alignSelf = "anchor-center";
1868
- style.marginBlockStart = ALIGN_OFFSET_VAR;
1869
- }
1905
+ var StoreController = class {
1906
+ #host;
1907
+ #selector;
1908
+ #accessor;
1909
+ #snapshot = null;
1910
+ constructor(host, source, selector) {
1911
+ this.#host = host;
1912
+ this.#selector = selector;
1913
+ this.#accessor = new StoreAccessor(host, source, (store) => this.#connect(store));
1914
+ host.addController(this);
1870
1915
  }
1871
- return style;
1872
- }
1916
+ get value() {
1917
+ const store = this.#accessor.value;
1918
+ if (isNull(store)) throw new Error("Store not available");
1919
+ if (isUndefined(this.#selector)) return store;
1920
+ return this.#snapshot.value;
1921
+ }
1922
+ hostConnected() {}
1923
+ #connect(store) {
1924
+ if (isUndefined(this.#selector)) return;
1925
+ if (!this.#snapshot) this.#snapshot = new SnapshotController(this.#host, store.$state, this.#selector);
1926
+ else this.#snapshot.track(store.$state);
1927
+ }
1928
+ };
1929
+
1930
+ //#endregion
1931
+ //#region src/player/player-controller.ts
1873
1932
  /**
1874
- * Compute CSS variables for sizing constraints relative to the anchor/boundary.
1933
+ * Reactive controller for accessing player store state.
1875
1934
  *
1876
- * Accepts a `cssVars` map so the same logic works for both popover
1877
- * (`--media-popover-*`) and tooltip (`--media-tooltip-*`) namespaces.
1878
- */
1879
- function getPositioningCSSVars(triggerRect, boundaryRect, side, cssVars = PopoverCSSVars) {
1880
- const vars = {};
1881
- vars[cssVars.anchorWidth] = `${triggerRect.width}px`;
1882
- vars[cssVars.anchorHeight] = `${triggerRect.height}px`;
1883
- if (side === "top" || side === "bottom") {
1884
- vars[cssVars.availableHeight] = side === "top" ? `${triggerRect.top - boundaryRect.top}px` : `${boundaryRect.bottom - triggerRect.bottom}px`;
1885
- vars[cssVars.availableWidth] = `${boundaryRect.width}px`;
1886
- } else {
1887
- vars[cssVars.availableWidth] = side === "left" ? `${triggerRect.left - boundaryRect.left}px` : `${boundaryRect.right - triggerRect.right}px`;
1888
- vars[cssVars.availableHeight] = `${boundaryRect.height}px`;
1889
- }
1890
- return vars;
1891
- }
1892
- /**
1893
- * Compute manual positioning when CSS Anchor Positioning is not supported.
1935
+ * Without selector: Returns the store, does NOT subscribe to changes.
1936
+ * With selector: Returns selected state, subscribes with shallowEqual comparison.
1894
1937
  *
1895
- * Returns inline `top`/`left` styles in **viewport coordinates** for use
1896
- * with `position: fixed` (the popup is in the top layer). All rects from
1897
- * `getBoundingClientRect()` are already viewport-relative.
1938
+ * @example
1939
+ * ```ts
1940
+ * // Store access (no subscription)
1941
+ * class Controls extends MediaElement {
1942
+ * #player = new PlayerController(this, playerContext);
1898
1943
  *
1899
- * Offsets are resolved by the caller from CSS custom properties via
1900
- * `getComputedStyle()` and passed as `offsets`.
1901
- */
1902
- function getManualPositionStyle(triggerRect, popupRect, opts, offsets = {
1903
- sideOffset: 0,
1904
- alignOffset: 0
1905
- }) {
1906
- const { side, align } = opts;
1907
- const { sideOffset, alignOffset } = offsets;
1908
- let top = 0;
1909
- let left = 0;
1910
- if (side === "top") top = triggerRect.top - popupRect.height - sideOffset;
1911
- else if (side === "bottom") top = triggerRect.bottom + sideOffset;
1912
- else if (side === "left") left = triggerRect.left - popupRect.width - sideOffset;
1913
- else left = triggerRect.right + sideOffset;
1914
- if (side === "top" || side === "bottom") if (align === "start") left = triggerRect.left + alignOffset;
1915
- else if (align === "end") left = triggerRect.right - popupRect.width + alignOffset;
1916
- else left = triggerRect.left + (triggerRect.width - popupRect.width) / 2 + alignOffset;
1917
- else if (align === "start") top = triggerRect.top + alignOffset;
1918
- else if (align === "end") top = triggerRect.bottom - popupRect.height + alignOffset;
1919
- else top = triggerRect.top + (triggerRect.height - popupRect.height) / 2 + alignOffset;
1920
- return {
1921
- top: `${top}px`,
1922
- left: `${left}px`
1923
- };
1924
- }
1925
- /**
1926
- * Read side-offset and align-offset CSS custom properties from the
1927
- * popup element's computed style, returning numeric pixel values.
1928
- */
1929
- function resolveOffsets(el, cssVars = PopoverCSSVars) {
1930
- const computed = getComputedStyle(el);
1931
- return {
1932
- sideOffset: resolveCSSLength(el, computed.getPropertyValue(cssVars.sideOffset)),
1933
- alignOffset: resolveCSSLength(el, computed.getPropertyValue(cssVars.alignOffset))
1934
- };
1935
- }
1936
- /**
1937
- * Measure the popup's layout box for positioning.
1944
+ * handleClick() {
1945
+ * this.#player.value.setVolume(0.5);
1946
+ * }
1947
+ * }
1938
1948
  *
1939
- * `getBoundingClientRect()` includes active transforms, which causes the
1940
- * fallback position to drift while opening/closing animations scale the popup.
1941
- * Using `offsetWidth`/`offsetHeight` preserves the untransformed size.
1942
- */
1943
- function getPopupPositionRect(el) {
1944
- const rect = el.getBoundingClientRect();
1945
- const width = el.offsetWidth || rect.width;
1946
- const height = el.offsetHeight || rect.height;
1947
- const adjustedRect = {
1948
- ...rect,
1949
- width,
1950
- height,
1951
- right: rect.left + width,
1952
- bottom: rect.top + height
1953
- };
1954
- return {
1955
- ...adjustedRect,
1956
- toJSON: () => adjustedRect
1957
- };
1958
- }
1959
-
1960
- //#endregion
1961
- //#region ../utils/dist/number/number.js
1962
- /** Clamp a value between min and max (inclusive). */
1963
- function clamp(value, min, max) {
1964
- return Math.max(min, Math.min(max, value));
1965
- }
1966
- /** Snap a value to the nearest step, offset from min. */
1967
- function roundToStep(value, step, min) {
1968
- const nearest = Math.round((value - min) / step) * step + min;
1969
- const dot = `${step}`.indexOf(".");
1970
- return dot === -1 ? nearest : Number(nearest.toFixed(`${step}`.length - dot - 1));
1971
- }
1972
-
1973
- //#endregion
1974
- //#region ../core/dist/dev/dom/utils/pointer.js
1975
- /** Convert a pointer event position to a 0–100 percent along an element's rect. */
1976
- function getPercentFromPointerEvent(event, rect, orientation, isRTL) {
1977
- let ratio;
1978
- if (orientation === "vertical") ratio = 1 - (event.clientY - rect.top) / rect.height;
1979
- else if (isRTL) ratio = (rect.right - event.clientX) / rect.width;
1980
- else ratio = (event.clientX - rect.left) / rect.width;
1981
- if (!Number.isFinite(ratio)) return 0;
1982
- return clamp(ratio * 100, 0, 100);
1983
- }
1984
-
1985
- //#endregion
1986
- //#region ../core/dist/dev/dom/ui/slider.js
1987
- /** Intentional drag threshold — number of pointermove events before drag starts. */
1988
- const DRAG_THRESHOLD = 2;
1989
- function createSlider(options) {
1990
- const input = createState({
1991
- pointerPercent: 0,
1992
- dragPercent: 0,
1993
- dragging: false,
1994
- pointing: false,
1995
- focused: false
1996
- });
1997
- const abort = new AbortController();
1998
- const commitThrottleMs = options.commitThrottle ?? 0;
1999
- let isDragging = false, moveCount = 0, cachedRTL = false, cachedRect = null, capturedPointerId = null;
2000
- const throttledCommit = commitThrottleMs > 0 ? throttle((percent) => options.onValueCommit?.(percent), commitThrottleMs) : null;
2001
- function releaseCapture() {
2002
- if (isNull(capturedPointerId)) return;
2003
- const id = capturedPointerId;
2004
- capturedPointerId = null;
2005
- try {
2006
- options.getElement().releasePointerCapture(id);
2007
- } catch {}
2008
- }
2009
- function endDrag() {
2010
- if (!isDragging) input.patch({ pointing: false });
2011
- else {
2012
- isDragging = false;
2013
- input.patch({
2014
- dragging: false,
2015
- pointing: false
2016
- });
2017
- options.onDragEnd?.();
2018
- }
2019
- cleanup();
2020
- }
2021
- function cleanup() {
2022
- throttledCommit?.cancel();
2023
- capturedPointerId = null;
2024
- cachedRect = null;
2025
- }
2026
- const rootProps = {
2027
- onPointerDown(event) {
2028
- if (options.isDisabled()) return;
2029
- event.preventDefault();
2030
- const el = options.getElement();
2031
- cachedRect = el.getBoundingClientRect();
2032
- cachedRTL = options.isRTL();
2033
- moveCount = 0;
2034
- releaseCapture();
2035
- capturedPointerId = event.pointerId;
2036
- el.setPointerCapture(event.pointerId);
2037
- const percent = getPercentFromPointerEvent(event, cachedRect, options.getOrientation(), cachedRTL);
2038
- input.patch({
2039
- pointing: true,
2040
- pointerPercent: percent,
2041
- dragPercent: percent
2042
- });
2043
- options.onValueChange?.(percent);
2044
- options.getThumbElement?.()?.focus({
2045
- preventScroll: true,
2046
- focusVisible: false
2047
- });
2048
- },
2049
- onPointerMove(event) {
2050
- if (options.isDisabled()) return;
2051
- if (!isNull(capturedPointerId)) {
2052
- if (event.pointerType !== "touch" && event.buttons === 0) {
2053
- endDrag();
2054
- return;
2055
- }
2056
- moveCount++;
2057
- const percent = getPercentFromPointerEvent(event, cachedRect, options.getOrientation(), cachedRTL);
2058
- if (!isDragging && moveCount >= DRAG_THRESHOLD) {
2059
- isDragging = true;
2060
- input.patch({
2061
- dragging: true,
2062
- dragPercent: percent,
2063
- pointerPercent: percent
2064
- });
2065
- options.onDragStart?.();
2066
- options.onValueChange?.(percent);
2067
- throttledCommit?.(percent);
2068
- } else if (isDragging) {
2069
- input.patch({
2070
- dragPercent: percent,
2071
- pointerPercent: percent
2072
- });
2073
- options.onValueChange?.(percent);
2074
- throttledCommit?.(percent);
2075
- } else input.patch({ pointerPercent: percent });
2076
- return;
2077
- }
2078
- const percent = getPercentFromPointerEvent(event, options.getElement().getBoundingClientRect(), options.getOrientation(), options.isRTL());
2079
- input.patch({
2080
- pointing: true,
2081
- pointerPercent: percent
2082
- });
2083
- },
2084
- onPointerUp(event) {
2085
- if (isNull(capturedPointerId)) return;
2086
- const percent = getPercentFromPointerEvent(event, cachedRect, options.getOrientation(), cachedRTL);
2087
- throttledCommit?.cancel();
2088
- options.onValueCommit?.(percent);
2089
- },
2090
- onPointerLeave() {
2091
- if (!isNull(capturedPointerId)) return;
2092
- input.patch({ pointing: false });
2093
- },
2094
- onLostPointerCapture() {
2095
- endDrag();
2096
- }
2097
- };
2098
- const thumbProps = {
2099
- onKeyDown(event) {
2100
- if (options.isDisabled()) {
2101
- if (event.key !== "Tab") event.preventDefault();
2102
- return;
2103
- }
2104
- const stepPercent = options.getStepPercent();
2105
- const largeStepPercent = options.getLargeStepPercent();
2106
- const rounded = roundToStep(options.getPercent(), stepPercent, 0);
2107
- const horizontalSign = options.isRTL() ? -1 : 1;
2108
- const step = event.shiftKey ? largeStepPercent : stepPercent;
2109
- let newPercent = null;
2110
- switch (event.key) {
2111
- case "ArrowRight":
2112
- newPercent = rounded + step * horizontalSign;
2113
- break;
2114
- case "ArrowLeft":
2115
- newPercent = rounded - step * horizontalSign;
2116
- break;
2117
- case "ArrowUp":
2118
- newPercent = rounded + step;
2119
- break;
2120
- case "ArrowDown":
2121
- newPercent = rounded - step;
2122
- break;
2123
- case "PageUp":
2124
- newPercent = rounded + largeStepPercent;
2125
- break;
2126
- case "PageDown":
2127
- newPercent = rounded - largeStepPercent;
2128
- break;
2129
- case "Home":
2130
- newPercent = 0;
2131
- break;
2132
- case "End":
2133
- newPercent = 100;
2134
- break;
2135
- default:
2136
- if (!event.metaKey && !event.ctrlKey && !event.altKey && event.key >= "0" && event.key <= "9") newPercent = Number(event.key) * 10;
2137
- break;
2138
- }
2139
- if (newPercent !== null) {
2140
- event.preventDefault();
2141
- newPercent = clamp(newPercent, 0, 100);
2142
- input.patch({
2143
- pointerPercent: newPercent,
2144
- dragPercent: newPercent
2145
- });
2146
- options.onValueChange?.(newPercent);
2147
- options.onValueCommit?.(newPercent);
2148
- }
2149
- },
2150
- onFocus() {
2151
- input.patch({ focused: true });
2152
- },
2153
- onBlur() {
2154
- input.patch({ focused: false });
2155
- }
2156
- };
2157
- function adjustForAlignment(state) {
2158
- if (!options.adjustPercent || state.thumbAlignment !== "edge") return state;
2159
- const rootEl = options.getElement();
2160
- const thumbEl = options.getThumbElement?.();
2161
- if (!thumbEl) return state;
2162
- const isHorizontal = state.orientation === "horizontal";
2163
- const thumbSize = isHorizontal ? thumbEl.offsetWidth : thumbEl.offsetHeight;
2164
- const trackSize = isHorizontal ? rootEl.offsetWidth : rootEl.offsetHeight;
2165
- return {
2166
- ...state,
2167
- fillPercent: options.adjustPercent(state.fillPercent, thumbSize, trackSize),
2168
- pointerPercent: options.adjustPercent(state.pointerPercent, thumbSize, trackSize)
2169
- };
2170
- }
2171
- let resizeObserver = null;
2172
- if (options.onResize) {
2173
- resizeObserver = new ResizeObserver(() => options.onResize());
2174
- resizeObserver.observe(options.getElement());
2175
- }
2176
- return {
2177
- input,
2178
- rootProps,
2179
- rootStyle: {
2180
- touchAction: "none",
2181
- userSelect: "none"
2182
- },
2183
- thumbProps,
2184
- adjustForAlignment,
2185
- destroy() {
2186
- if (abort.signal.aborted) return;
2187
- abort.abort();
2188
- resizeObserver?.disconnect();
2189
- releaseCapture();
2190
- cleanup();
2191
- }
2192
- };
2193
- }
2194
-
2195
- //#endregion
2196
- //#region ../core/dist/dev/core/ui/slider/slider-css-vars.js
2197
- /** CSS custom property names for slider visual state. */
2198
- const SliderCSSVars = {
2199
- fill: "--media-slider-fill",
2200
- pointer: "--media-slider-pointer",
2201
- buffer: "--media-slider-buffer"
2202
- };
2203
-
2204
- //#endregion
2205
- //#region ../core/dist/dev/dom/ui/slider-css-vars.js
2206
- function getSliderCSSVars(state) {
2207
- return {
2208
- [SliderCSSVars.fill]: `${state.fillPercent.toFixed(3)}%`,
2209
- [SliderCSSVars.pointer]: `${state.pointerPercent.toFixed(3)}%`
2210
- };
2211
- }
2212
- function getTimeSliderCSSVars(state) {
2213
- return {
2214
- ...getSliderCSSVars(state),
2215
- [SliderCSSVars.buffer]: `${state.bufferPercent.toFixed(3)}%`
2216
- };
2217
- }
2218
- /** Compute structural positioning styles for a slider preview element. */
2219
- function getSliderPreviewStyle(width, overflow) {
2220
- const halfWidth = width / 2;
2221
- return {
2222
- position: "absolute",
2223
- left: overflow === "visible" ? `calc(var(${SliderCSSVars.pointer}) - ${halfWidth}px)` : `min(max(0px, calc(var(${SliderCSSVars.pointer}) - ${halfWidth}px)), calc(100% - ${width}px))`,
2224
- width: "max-content",
2225
- pointerEvents: "none"
2226
- };
2227
- }
2228
-
2229
- //#endregion
2230
- //#region ../core/dist/dev/core/ui/thumbnail/thumbnail-core.js
2231
- var ThumbnailCore = class {
2232
- findActiveThumbnail(thumbnails, time) {
2233
- if (thumbnails.length === 0) return void 0;
2234
- let low = 0;
2235
- let high = thumbnails.length - 1;
2236
- let result;
2237
- while (low <= high) {
2238
- const mid = low + high >>> 1;
2239
- const image = thumbnails[mid];
2240
- if (time >= image.startTime) {
2241
- result = image;
2242
- low = mid + 1;
2243
- } else high = mid - 1;
2244
- }
2245
- return result;
2246
- }
2247
- /**
2248
- * Parse CSS constraint strings into numeric `ThumbnailConstraints`.
2249
- *
2250
- * Accepts any object with string `minWidth`/`maxWidth`/`minHeight`/`maxHeight`
2251
- * properties — `CSSStyleDeclaration` satisfies this structurally.
2252
- */
2253
- parseConstraints(raw) {
2254
- const minW = parseFloat(raw.minWidth);
2255
- const maxW = parseFloat(raw.maxWidth);
2256
- const minH = parseFloat(raw.minHeight);
2257
- const maxH = parseFloat(raw.maxHeight);
2258
- return {
2259
- minWidth: Number.isFinite(minW) ? minW : 0,
2260
- maxWidth: Number.isFinite(maxW) ? maxW : Infinity,
2261
- minHeight: Number.isFinite(minH) ? minH : 0,
2262
- maxHeight: Number.isFinite(maxH) ? maxH : Infinity
2263
- };
2264
- }
2265
- /**
2266
- * Calculate a uniform scale factor that fits `tileWidth × tileHeight` within the
2267
- * given CSS min/max constraints while preserving aspect ratio.
2268
- *
2269
- * - Scales down when the tile exceeds max constraints.
2270
- * - Scales up when the tile is smaller than min constraints.
2271
- * - Returns `1` when no scaling is needed.
2272
- */
2273
- calculateScale(tileWidth, tileHeight, constraints) {
2274
- const { minWidth, maxWidth, minHeight, maxHeight } = constraints;
2275
- const maxRatio = Math.min(maxWidth / tileWidth, maxHeight / tileHeight);
2276
- const minRatio = Math.max(minWidth / tileWidth, minHeight / tileHeight);
2277
- if (Number.isFinite(maxRatio) && maxRatio < 1) return maxRatio;
2278
- if (Number.isFinite(minRatio) && minRatio > 1) return minRatio;
2279
- return 1;
2280
- }
2281
- /**
2282
- * Compute container and image dimensions for the current thumbnail, scaled to
2283
- * fit within the element's CSS min/max constraints.
2284
- *
2285
- * The container clips the sprite sheet via `overflow: hidden`, and the image is
2286
- * positioned with `transform: translate()` to show the correct tile.
2287
- */
2288
- resize(thumbnail, imgNaturalWidth, imgNaturalHeight, constraints) {
2289
- const tileWidth = thumbnail.width ?? imgNaturalWidth;
2290
- const tileHeight = thumbnail.height ?? imgNaturalHeight;
2291
- if (!tileWidth || !tileHeight) return void 0;
2292
- const scale = this.calculateScale(tileWidth, tileHeight, constraints);
2293
- const coordX = thumbnail.coords?.x ?? 0;
2294
- const coordY = thumbnail.coords?.y ?? 0;
2295
- const inset = scale !== 1 ? 1 : 0;
2296
- return {
2297
- scale,
2298
- containerWidth: Math.max(0, Math.floor(tileWidth * scale) - inset * 2),
2299
- containerHeight: Math.max(0, Math.floor(tileHeight * scale) - inset * 2),
2300
- imageWidth: Math.ceil(imgNaturalWidth * scale),
2301
- imageHeight: Math.ceil(imgNaturalHeight * scale),
2302
- offsetX: Math.ceil(coordX * scale) + inset,
2303
- offsetY: Math.ceil(coordY * scale) + inset
2304
- };
2305
- }
2306
- getState(loading, error, thumbnail) {
2307
- return {
2308
- loading,
2309
- error,
2310
- hidden: !loading && !thumbnail
2311
- };
2312
- }
2313
- getAttrs(_state) {
2314
- return {
2315
- role: "img",
2316
- "aria-hidden": "true"
2317
- };
2318
- }
2319
- };
2320
-
2321
- //#endregion
2322
- //#region ../core/dist/dev/dom/ui/thumbnail.js
2323
- function createThumbnail(options) {
2324
- const { getContainer, getImg, onStateChange } = options;
2325
- const core = new ThumbnailCore();
2326
- const abort = new AbortController();
2327
- const signal = abort.signal;
2328
- let loading = false;
2329
- let error = false;
2330
- let naturalWidth = 0;
2331
- let naturalHeight = 0;
2332
- let lastSrc = "";
2333
- let imgBound = false;
2334
- let resizeObserver = null;
2335
- function onImgLoad() {
2336
- const img = getImg();
2337
- if (img) {
2338
- naturalWidth = img.naturalWidth;
2339
- naturalHeight = img.naturalHeight;
2340
- }
2341
- loading = false;
2342
- error = false;
2343
- onStateChange();
2344
- }
2345
- function onImgError() {
2346
- loading = false;
2347
- error = true;
2348
- onStateChange();
2349
- }
2350
- function bindImg(img) {
2351
- listen(img, "load", onImgLoad, { signal });
2352
- listen(img, "error", onImgError, { signal });
2353
- }
2354
- function ensureBindings() {
2355
- if (!imgBound) {
2356
- const img = getImg();
2357
- if (img) {
2358
- bindImg(img);
2359
- imgBound = true;
2360
- }
2361
- }
2362
- if (!resizeObserver) {
2363
- const container = getContainer();
2364
- if (container) {
2365
- resizeObserver = new ResizeObserver(onStateChange);
2366
- resizeObserver.observe(container);
2367
- }
2368
- }
2369
- }
2370
- function updateSrc(url) {
2371
- ensureBindings();
2372
- const src = url ?? "";
2373
- if (src === lastSrc) return;
2374
- lastSrc = src;
2375
- if (src) {
2376
- loading = true;
2377
- error = false;
2378
- } else {
2379
- loading = false;
2380
- error = false;
2381
- naturalWidth = 0;
2382
- naturalHeight = 0;
2383
- }
2384
- }
2385
- function connect() {
2386
- ensureBindings();
2387
- const img = getImg();
2388
- if (img?.complete && lastSrc) {
2389
- if (img.naturalWidth > 0) {
2390
- naturalWidth = img.naturalWidth;
2391
- naturalHeight = img.naturalHeight;
2392
- loading = false;
2393
- error = false;
2394
- } else {
2395
- loading = false;
2396
- error = true;
2397
- }
2398
- onStateChange();
2399
- }
2400
- }
2401
- function destroy() {
2402
- abort.abort();
2403
- resizeObserver?.disconnect();
2404
- resizeObserver = null;
2405
- }
2406
- return {
2407
- get loading() {
2408
- return loading;
2409
- },
2410
- get error() {
2411
- return error;
2412
- },
2413
- get naturalWidth() {
2414
- return naturalWidth;
2415
- },
2416
- get naturalHeight() {
2417
- return naturalHeight;
2418
- },
2419
- readConstraints() {
2420
- const el = getContainer();
2421
- if (!el) return {
2422
- minWidth: 0,
2423
- maxWidth: Infinity,
2424
- minHeight: 0,
2425
- maxHeight: Infinity
2426
- };
2427
- return core.parseConstraints(getComputedStyle(el));
2428
- },
2429
- updateSrc,
2430
- connect,
2431
- destroy
2432
- };
2433
- }
2434
-
2435
- //#endregion
2436
- //#region ../core/dist/dev/dom/ui/tooltip/tooltip.js
2437
- /** Map popover reasons to tooltip reasons, filtering out click/outside-click. */
2438
- const REASON_MAP = {
2439
- hover: "hover",
2440
- focus: "focus",
2441
- escape: "escape",
2442
- blur: "blur"
2443
- };
2444
- function createTooltip(options) {
2445
- const popoverOpts = {
2446
- transition: options.transition,
2447
- onOpenChange(open, details) {
2448
- const reason = REASON_MAP[details.reason];
2449
- if (!reason) return;
2450
- const group = options.group?.();
2451
- if (open) group?.notifyOpen();
2452
- else group?.notifyClose();
2453
- const tooltipDetails = details.event ? {
2454
- reason,
2455
- event: details.event
2456
- } : { reason };
2457
- options.onOpenChange(open, tooltipDetails);
2458
- },
2459
- closeOnEscape: () => true,
2460
- closeOnOutsideClick: () => false,
2461
- openOnHover: () => true,
2462
- delay: () => {
2463
- const group = options.group?.();
2464
- if (group?.shouldSkipDelay()) return 0;
2465
- return options.delay?.() ?? group?.delay ?? 600;
2466
- },
2467
- closeDelay: () => {
2468
- const group = options.group?.();
2469
- return options.closeDelay?.() ?? group?.closeDelay ?? 0;
2470
- }
2471
- };
2472
- if (options.onOpenChangeComplete) popoverOpts.onOpenChangeComplete = options.onOpenChangeComplete;
2473
- const popover = createPopover(popoverOpts);
2474
- let isPointerDown = false;
2475
- const { onClick: _, ...baseTriggerProps } = popover.triggerProps;
2476
- const triggerProps = {
2477
- ...baseTriggerProps,
2478
- onPointerDown() {
2479
- isPointerDown = true;
2480
- },
2481
- onPointerEnter(event) {
2482
- if (options.disabled?.()) return;
2483
- if (event.pointerType === "touch") return;
2484
- baseTriggerProps.onPointerEnter(event);
2485
- },
2486
- onFocusIn(event) {
2487
- if (options.disabled?.()) return;
2488
- if (isPointerDown) {
2489
- isPointerDown = false;
2490
- return;
2491
- }
2492
- baseTriggerProps.onFocusIn(event);
2493
- }
2494
- };
2495
- const popupProps = {
2496
- ...popover.popupProps,
2497
- onPointerEnter(event) {
2498
- if (options.disableHoverablePopup?.()) return;
2499
- popover.popupProps.onPointerEnter(event);
2500
- }
2501
- };
2502
- return {
2503
- ...popover,
2504
- triggerProps,
2505
- popupProps,
2506
- get triggerElement() {
2507
- return popover.triggerElement;
2508
- },
2509
- open: () => popover.open("hover"),
2510
- close: () => popover.close("hover")
2511
- };
2512
- }
2513
-
2514
- //#endregion
2515
- //#region ../core/dist/dev/dom/ui/transition.js
2516
- /**
2517
- * Manages open/close transition lifecycle via `createState`.
2518
- *
2519
- * **Open:** patches `{ active: true, status: 'starting' }`, then after a
2520
- * double-RAF patches `{ status: 'idle' }` so the browser paints the
2521
- * initial ("from") state before transitioning.
2522
- *
2523
- * **Close:** patches `{ status: 'ending' }` (keeping `active: true` so the
2524
- * element stays mounted), then after a double-RAF waits for
2525
- * `getAnimations()` to settle before patching `{ active: false, status: 'idle' }`.
2526
- */
2527
- function createTransition() {
2528
- const state = createState({
2529
- active: false,
2530
- status: "idle"
2531
- });
2532
- let destroyed = false;
2533
- let rafId1 = 0;
2534
- let rafId2 = 0;
2535
- function open() {
2536
- cancelAnimationFrame(rafId1);
2537
- cancelAnimationFrame(rafId2);
2538
- rafId1 = 0;
2539
- rafId2 = 0;
2540
- state.patch({
2541
- active: true,
2542
- status: "starting"
2543
- });
2544
- return new Promise((resolve) => {
2545
- rafId1 = requestAnimationFrame(() => {
2546
- rafId1 = 0;
2547
- rafId2 = requestAnimationFrame(() => {
2548
- rafId2 = 0;
2549
- if (destroyed || !state.current.active) return resolve();
2550
- state.patch({ status: "idle" });
2551
- resolve();
2552
- });
2553
- });
2554
- });
2555
- }
2556
- function close(el) {
2557
- cancelAnimationFrame(rafId1);
2558
- cancelAnimationFrame(rafId2);
2559
- rafId1 = 0;
2560
- rafId2 = 0;
2561
- state.patch({ status: "ending" });
2562
- return new Promise((resolve) => {
2563
- rafId1 = requestAnimationFrame(() => {
2564
- rafId1 = 0;
2565
- rafId2 = requestAnimationFrame(() => {
2566
- rafId2 = 0;
2567
- if (destroyed) return resolve();
2568
- waitForAnimations(el).finally(() => {
2569
- if (destroyed || state.current.status !== "ending") return resolve();
2570
- state.patch({
2571
- active: false,
2572
- status: "idle"
2573
- });
2574
- resolve();
2575
- });
2576
- });
2577
- });
2578
- });
2579
- }
2580
- function cancel() {
2581
- cancelAnimationFrame(rafId1);
2582
- cancelAnimationFrame(rafId2);
2583
- rafId1 = 0;
2584
- rafId2 = 0;
2585
- if (state.current.status !== "idle") state.patch({ status: "idle" });
2586
- }
2587
- return {
2588
- state,
2589
- open,
2590
- close,
2591
- cancel,
2592
- destroy() {
2593
- if (destroyed) return;
2594
- destroyed = true;
2595
- cancel();
2596
- }
2597
- };
2598
- }
2599
- function waitForAnimations(el) {
2600
- if (!el) return Promise.resolve();
2601
- const animations = el.getAnimations?.() ?? [];
2602
- if (animations.length === 0) return Promise.resolve();
2603
- return Promise.all(animations.map((a) => a.finished)).then(noop, noop);
2604
- }
2605
-
2606
- //#endregion
2607
- //#region ../core/dist/dev/dom/ui/wheel-step.js
2608
- function createWheelStep(options) {
2609
- return { onWheel(event) {
2610
- if (options.isDisabled()) return;
2611
- const direction = Math.sign(event.deltaY);
2612
- if (direction === 0) return;
2613
- event.preventDefault();
2614
- const stepPercent = options.getStepPercent();
2615
- const newPercent = clamp(options.getPercent() - direction * stepPercent, 0, 100);
2616
- options.onValueChange?.(newPercent);
2617
- } };
2618
- }
2619
-
2620
- //#endregion
2621
- //#region ../core/dist/dev/dom/utils/element-props.js
2622
- /**
2623
- * Apply props to a DOM element.
2624
- *
2625
- * Handles both attributes and event listeners:
2626
- * - Event props (onClick, onKeyDown, etc.) are attached as listeners
2627
- * - Boolean props: `true` sets empty attribute, `false` removes
2628
- * - `undefined` removes the attribute
2629
- * - Other props are set as string attributes
2630
- */
2631
- function applyElementProps(element, props, options) {
2632
- const signal = options?.signal;
2633
- 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);
2634
- else if (isUndefined(value) || value === false) element.removeAttribute(key);
2635
- else if (value === true) element.setAttribute(key, "");
2636
- else element.setAttribute(key, String(value));
2637
- }
2638
-
2639
- //#endregion
2640
- //#region ../core/dist/dev/dom/utils/log.js
2641
- const warned = /* @__PURE__ */ new Set();
2642
- function logMissingFeature(displayName, featureName) {
2643
- const key = `${displayName}:${featureName}`;
2644
- if (warned.has(key)) return;
2645
- warned.add(key);
2646
- console.warn(`${displayName} requires ${featureName} feature`);
2647
- }
2648
-
2649
- //#endregion
2650
- //#region ../core/dist/dev/dom/utils/state-data-attrs.js
2651
- /**
2652
- * Apply state as data attributes to an element.
2653
- *
2654
- * - `true` → sets `data-keyname=""`
2655
- * - truthy string/number → sets `data-keyname="value"`
2656
- * - falsy → removes the attribute
2657
- *
2658
- * @example
2659
- * ```ts
2660
- * const state = { paused: true, ended: false };
2661
- * applyStateDataAttrs(element, state);
2662
- * // element has data-paused="", data-ended is removed
1949
+ * // Selector-based subscription
1950
+ * class PlayButton extends MediaElement {
1951
+ * #playback = new PlayerController(this, playerContext, selectPlayback);
1952
+ * }
2663
1953
  * ```
2664
1954
  */
2665
- function applyStateDataAttrs(element, state, map) {
2666
- for (const key in state) {
2667
- if (map && !(key in map)) continue;
2668
- const name = map?.[key] ?? toDataAttrName(key), value = state[key];
2669
- if (value === true) element.setAttribute(name, "");
2670
- else if (value) element.setAttribute(name, String(value));
2671
- else element.removeAttribute(name);
2672
- }
2673
- }
2674
- function toDataAttrName(key) {
2675
- return `data-${key.toLowerCase()}`;
2676
- }
2677
-
2678
- //#endregion
2679
- //#region ../../node_modules/.pnpm/@lit+context@1.1.6/node_modules/@lit/context/development/lib/controllers/context-consumer.js
2680
- /**
2681
- * @license
2682
- * Copyright 2021 Google LLC
2683
- * SPDX-License-Identifier: BSD-3-Clause
2684
- */
2685
- /**
2686
- * A ReactiveController which adds context consuming behavior to a custom
2687
- * element by dispatching `context-request` events.
2688
- *
2689
- * When the host element is connected to the document it will emit a
2690
- * `context-request` event with its context key. When the context request
2691
- * is satisfied the controller will invoke the callback, if present, and
2692
- * trigger a host update so it can respond to the new value.
2693
- *
2694
- * It will also call the dispose method given by the provider when the
2695
- * host element is disconnected.
2696
- */
2697
- var ContextConsumer = class {
2698
- constructor(host, contextOrOptions, callback, subscribe) {
2699
- this.subscribe = false;
2700
- this.provided = false;
2701
- this.value = void 0;
2702
- this._callback = (value, unsubscribe) => {
2703
- if (this.unsubscribe) {
2704
- if (this.unsubscribe !== unsubscribe) {
2705
- this.provided = false;
2706
- this.unsubscribe();
2707
- }
2708
- if (!this.subscribe) this.unsubscribe();
2709
- }
2710
- this.value = value;
2711
- this.host.requestUpdate();
2712
- if (!this.provided || this.subscribe) {
2713
- this.provided = true;
2714
- if (this.callback) this.callback(value, unsubscribe);
2715
- }
2716
- this.unsubscribe = unsubscribe;
2717
- };
2718
- this.host = host;
2719
- if (contextOrOptions.context !== void 0) {
2720
- const options = contextOrOptions;
2721
- this.context = options.context;
2722
- this.callback = options.callback;
2723
- this.subscribe = options.subscribe ?? false;
2724
- } else {
2725
- this.context = contextOrOptions;
2726
- this.callback = callback;
2727
- this.subscribe = subscribe ?? false;
2728
- }
2729
- this.host.addController(this);
2730
- }
2731
- hostConnected() {
2732
- this.dispatchRequest();
2733
- }
2734
- hostDisconnected() {
2735
- if (this.unsubscribe) {
2736
- this.unsubscribe();
2737
- this.unsubscribe = void 0;
2738
- }
2739
- }
2740
- dispatchRequest() {
2741
- this.host.dispatchEvent(new ContextRequestEvent(this.context, this.host, this._callback, this.subscribe));
2742
- }
2743
- };
2744
-
2745
- //#endregion
2746
- //#region ../../node_modules/.pnpm/@lit+context@1.1.6/node_modules/@lit/context/development/lib/value-notifier.js
2747
- /**
2748
- * @license
2749
- * Copyright 2021 Google LLC
2750
- * SPDX-License-Identifier: BSD-3-Clause
2751
- */
2752
- /**
2753
- * A simple class which stores a value, and triggers registered callbacks when
2754
- * the value is changed via its setter.
2755
- *
2756
- * An implementor might use other observable patterns such as MobX or Redux to
2757
- * get behavior like this. But this is a pretty minimal approach that will
2758
- * likely work for a number of use cases.
2759
- */
2760
- var ValueNotifier = class {
2761
- get value() {
2762
- return this._value;
2763
- }
2764
- set value(v) {
2765
- this.setValue(v);
2766
- }
2767
- setValue(v, force = false) {
2768
- const update = force || !Object.is(v, this._value);
2769
- this._value = v;
2770
- if (update) this.updateObservers();
2771
- }
2772
- constructor(defaultValue) {
2773
- this.subscriptions = /* @__PURE__ */ new Map();
2774
- this.updateObservers = () => {
2775
- for (const [callback, { disposer }] of this.subscriptions) callback(this._value, disposer);
2776
- };
2777
- if (defaultValue !== void 0) this.value = defaultValue;
2778
- }
2779
- addCallback(callback, consumerHost, subscribe) {
2780
- if (!subscribe) {
2781
- callback(this.value);
2782
- return;
2783
- }
2784
- if (!this.subscriptions.has(callback)) this.subscriptions.set(callback, {
2785
- disposer: () => {
2786
- this.subscriptions.delete(callback);
2787
- },
2788
- consumerHost
2789
- });
2790
- const { disposer } = this.subscriptions.get(callback);
2791
- callback(this.value, disposer);
2792
- }
2793
- clearCallbacks() {
2794
- this.subscriptions.clear();
2795
- }
2796
- };
2797
-
2798
- //#endregion
2799
- //#region ../../node_modules/.pnpm/@lit+context@1.1.6/node_modules/@lit/context/development/lib/controllers/context-provider.js
2800
- /**
2801
- * @license
2802
- * Copyright 2021 Google LLC
2803
- * SPDX-License-Identifier: BSD-3-Clause
2804
- */
2805
- var ContextProviderEvent = class extends Event {
2806
- /**
2807
- *
2808
- * @param context the context which this provider can provide
2809
- * @param contextTarget the original context target of the provider
2810
- */
2811
- constructor(context, contextTarget) {
2812
- super("context-provider", {
2813
- bubbles: true,
2814
- composed: true
2815
- });
2816
- this.context = context;
2817
- this.contextTarget = contextTarget;
2818
- }
2819
- };
2820
- /**
2821
- * A ReactiveController which adds context provider behavior to a
2822
- * custom element.
2823
- *
2824
- * This controller simply listens to the `context-request` event when
2825
- * the host is connected to the DOM and registers the received callbacks
2826
- * against its observable Context implementation.
2827
- *
2828
- * The controller may also be attached to any HTML element in which case it's
2829
- * up to the user to call hostConnected() when attached to the DOM. This is
2830
- * done automatically for any custom elements implementing
2831
- * ReactiveControllerHost.
2832
- */
2833
- var ContextProvider = class extends ValueNotifier {
2834
- constructor(host, contextOrOptions, initialValue) {
2835
- super(contextOrOptions.context !== void 0 ? contextOrOptions.initialValue : initialValue);
2836
- this.onContextRequest = (ev) => {
2837
- if (ev.context !== this.context) return;
2838
- const consumerHost = ev.contextTarget ?? ev.composedPath()[0];
2839
- if (consumerHost === this.host) return;
2840
- ev.stopPropagation();
2841
- this.addCallback(ev.callback, consumerHost, ev.subscribe);
2842
- };
2843
- /**
2844
- * When we get a provider request event, that means a child of this element
2845
- * has just woken up. If it's a provider of our context, then we may need to
2846
- * re-parent our subscriptions, because is a more specific provider than us
2847
- * for its subtree.
2848
- */
2849
- this.onProviderRequest = (ev) => {
2850
- if (ev.context !== this.context) return;
2851
- if ((ev.contextTarget ?? ev.composedPath()[0]) === this.host) return;
2852
- const seen = /* @__PURE__ */ new Set();
2853
- for (const [callback, { consumerHost }] of this.subscriptions) {
2854
- if (seen.has(callback)) continue;
2855
- seen.add(callback);
2856
- consumerHost.dispatchEvent(new ContextRequestEvent(this.context, consumerHost, callback, true));
2857
- }
2858
- ev.stopPropagation();
2859
- };
2860
- this.host = host;
2861
- if (contextOrOptions.context !== void 0) this.context = contextOrOptions.context;
2862
- else this.context = contextOrOptions;
2863
- this.attachListeners();
2864
- this.host.addController?.(this);
2865
- }
2866
- attachListeners() {
2867
- this.host.addEventListener("context-request", this.onContextRequest);
2868
- this.host.addEventListener("context-provider", this.onProviderRequest);
2869
- }
2870
- hostConnected() {
2871
- this.host.dispatchEvent(new ContextProviderEvent(this.context, this.host));
2872
- }
2873
- };
2874
-
2875
- //#endregion
2876
- //#region src/store/container-mixin.ts
2877
- /**
2878
- * Create a mixin that consumes player context and registers itself as the
2879
- * container element with the provider via `containerContext`.
2880
- *
2881
- * @param config - Container configuration with player and container contexts.
2882
- */
2883
- function createContainerMixin(config) {
2884
- return (BaseClass) => {
2885
- class PlayerContainerElement extends BaseClass {
2886
- #contextStore = null;
2887
- #setContainer = null;
2888
- constructor(...args) {
2889
- super(...args);
2890
- new ContextConsumer(this, {
2891
- context: config.playerContext,
2892
- callback: (value) => {
2893
- this.#contextStore = value ?? null;
2894
- },
2895
- subscribe: true
2896
- });
2897
- new ContextConsumer(this, {
2898
- context: config.containerContext,
2899
- callback: (value) => {
2900
- this.#setContainer = value?.setContainer ?? null;
2901
- if (this.isConnected) this.#setContainer?.(this);
2902
- },
2903
- subscribe: true
2904
- });
2905
- }
2906
- get store() {
2907
- return this.#contextStore;
2908
- }
2909
- connectedCallback() {
2910
- super.connectedCallback();
2911
- this.#setContainer?.(this);
2912
- }
2913
- disconnectedCallback() {
2914
- super.disconnectedCallback();
2915
- this.#setContainer?.(null);
2916
- }
2917
- }
2918
- return PlayerContainerElement;
2919
- };
2920
- }
2921
-
2922
- //#endregion
2923
- //#region src/ui/media-element.ts
2924
- /** Base class for interactive media UI elements. */
2925
- var MediaElement = class extends DestroyMixin(ReactiveElement) {};
2926
-
2927
- //#endregion
2928
- //#region src/media/container-element.ts
2929
- const ContainerMixin = createContainerMixin({
2930
- playerContext,
2931
- containerContext
2932
- });
2933
- var MediaContainerElement = class extends ContainerMixin(MediaElement) {
2934
- static {
2935
- this.tagName = "media-container";
1955
+ var PlayerController = class {
1956
+ #host;
1957
+ #selector;
1958
+ #consumer;
1959
+ #store = null;
1960
+ constructor(host, context, selector) {
1961
+ this.#host = host;
1962
+ this.#selector = selector;
1963
+ this.#consumer = new ContextConsumer(host, {
1964
+ context,
1965
+ callback: (ctx) => this.#connect(ctx),
1966
+ subscribe: true
1967
+ });
1968
+ host.addController(this);
1969
+ }
1970
+ get value() {
1971
+ const store = this.#consumer.value;
1972
+ if (!store) return void 0;
1973
+ if (!this.#selector) return store;
1974
+ return this.#store?.value;
1975
+ }
1976
+ get displayName() {
1977
+ return this.#selector?.displayName;
1978
+ }
1979
+ hostConnected() {
1980
+ const store = this.#consumer.value;
1981
+ if (store) this.#connect(store);
1982
+ }
1983
+ hostDisconnected() {
1984
+ this.#store = null;
1985
+ }
1986
+ #connect(store) {
1987
+ if (!this.#store && this.#selector) this.#store = new StoreController(this.#host, store, this.#selector);
2936
1988
  }
2937
1989
  };
2938
1990
 
@@ -3060,235 +2112,6 @@ function createProviderMixin(config) {
3060
2112
  };
3061
2113
  }
3062
2114
 
3063
- //#endregion
3064
- //#region ../store/dist/dev/html/controllers/snapshot-controller.js
3065
- /**
3066
- * Subscribe to a `State<T>` container with optional selector.
3067
- *
3068
- * Without selector: returns full state, re-renders on any state change.
3069
- * With selector: returns selected slice, re-renders only when the slice changes (shallowEqual).
3070
- *
3071
- * @example
3072
- * ```ts
3073
- * #state = new SnapshotController(this, sliderState, (s) => s.value);
3074
- * ```
3075
- */
3076
- var SnapshotController = class {
3077
- #host;
3078
- #selector;
3079
- #state;
3080
- #cached;
3081
- #unsubscribe = noop;
3082
- constructor(host, state, selector) {
3083
- this.#host = host;
3084
- this.#state = state;
3085
- this.#selector = selector;
3086
- host.addController(this);
3087
- }
3088
- get value() {
3089
- if (!this.#selector) return this.#state.current;
3090
- this.#cached ??= this.#selector(this.#state.current);
3091
- return this.#cached;
3092
- }
3093
- /** Switch to tracking a different state container. */
3094
- track(state) {
3095
- this.#state = state;
3096
- this.#subscribe();
3097
- }
3098
- hostConnected() {
3099
- this.#subscribe();
3100
- }
3101
- hostDisconnected() {
3102
- this.#unsubscribe();
3103
- this.#unsubscribe = noop;
3104
- this.#cached = void 0;
3105
- }
3106
- #subscribe() {
3107
- this.#unsubscribe();
3108
- if (!this.#selector) {
3109
- this.#unsubscribe = this.#state.subscribe(() => this.#host.requestUpdate());
3110
- return;
3111
- }
3112
- const selector = this.#selector;
3113
- this.#cached = selector(this.#state.current);
3114
- this.#unsubscribe = this.#state.subscribe(() => {
3115
- const next = selector(this.#state.current);
3116
- if (!shallowEqual(this.#cached, next)) {
3117
- this.#cached = next;
3118
- this.#host.requestUpdate();
3119
- }
3120
- });
3121
- }
3122
- };
3123
-
3124
- //#endregion
3125
- //#region ../store/dist/dev/html/store-accessor.js
3126
- /**
3127
- * Resolves a store from either a direct instance or context.
3128
- *
3129
- * When given a direct store, provides immediate access.
3130
- * When given a context, sets up a ContextConsumer to receive the store.
3131
- *
3132
- * @example Direct store
3133
- * ```ts
3134
- * const accessor = new StoreAccessor(host, store, (s) => console.log('available', s));
3135
- * accessor.value; // Store (immediately available)
3136
- * ```
3137
- *
3138
- * @example Context source
3139
- * ```ts
3140
- * const accessor = new StoreAccessor(host, context, (s) => console.log('available', s));
3141
- * accessor.value; // null until context provides store
3142
- * ```
3143
- */
3144
- var StoreAccessor = class {
3145
- #onAvailable;
3146
- #consumer;
3147
- #directStore;
3148
- constructor(host, source, onAvailable) {
3149
- this.#onAvailable = onAvailable ?? noop;
3150
- if (isStore(source)) {
3151
- this.#directStore = source;
3152
- this.#consumer = null;
3153
- } else {
3154
- this.#directStore = null;
3155
- this.#consumer = new ContextConsumer(host, {
3156
- context: source,
3157
- callback: (store) => this.#onAvailable(store),
3158
- subscribe: false
3159
- });
3160
- }
3161
- host.addController(this);
3162
- }
3163
- /** Returns the store, or null if not yet available from context. */
3164
- get value() {
3165
- if (this.#consumer) return this.#consumer.value ?? null;
3166
- return this.#directStore;
3167
- }
3168
- hostConnected() {
3169
- if (this.#directStore) this.#onAvailable(this.#directStore);
3170
- }
3171
- };
3172
-
3173
- //#endregion
3174
- //#region ../store/dist/dev/html/controllers/store-controller.js
3175
- /**
3176
- * Access store state and actions.
3177
- *
3178
- * Without selector: Returns the store, does NOT subscribe to changes.
3179
- * With selector: Returns selected state, triggers update when selected state changes (shallowEqual).
3180
- *
3181
- * @example
3182
- * ```ts
3183
- * // Store access (no subscription) - access actions
3184
- * class Controls extends LitElement {
3185
- * #store = new StoreController(this, storeSource);
3186
- *
3187
- * handleClick() {
3188
- * this.#store.value.setVolume(0.5);
3189
- * }
3190
- * }
3191
- *
3192
- * // Selector-based subscription - re-renders when playback changes
3193
- * class PlayButton extends LitElement {
3194
- * #playback = new StoreController(this, storeSource, selectPlayback);
3195
- *
3196
- * render() {
3197
- * const playback = this.#playback.value;
3198
- * if (!playback) return nothing;
3199
- * return html`<button @click=${playback.toggle}>
3200
- * ${playback.paused ? 'Play' : 'Pause'}
3201
- * </button>`;
3202
- * }
3203
- * }
3204
- * ```
3205
- */
3206
- var StoreController = class {
3207
- #host;
3208
- #selector;
3209
- #accessor;
3210
- #snapshot = null;
3211
- constructor(host, source, selector) {
3212
- this.#host = host;
3213
- this.#selector = selector;
3214
- this.#accessor = new StoreAccessor(host, source, (store) => this.#connect(store));
3215
- host.addController(this);
3216
- }
3217
- get value() {
3218
- const store = this.#accessor.value;
3219
- if (isNull(store)) throw new Error("Store not available");
3220
- if (isUndefined(this.#selector)) return store;
3221
- return this.#snapshot.value;
3222
- }
3223
- hostConnected() {}
3224
- #connect(store) {
3225
- if (isUndefined(this.#selector)) return;
3226
- if (!this.#snapshot) this.#snapshot = new SnapshotController(this.#host, store.$state, this.#selector);
3227
- else this.#snapshot.track(store.$state);
3228
- }
3229
- };
3230
-
3231
- //#endregion
3232
- //#region src/player/player-controller.ts
3233
- /**
3234
- * Reactive controller for accessing player store state.
3235
- *
3236
- * Without selector: Returns the store, does NOT subscribe to changes.
3237
- * With selector: Returns selected state, subscribes with shallowEqual comparison.
3238
- *
3239
- * @example
3240
- * ```ts
3241
- * // Store access (no subscription)
3242
- * class Controls extends MediaElement {
3243
- * #player = new PlayerController(this, playerContext);
3244
- *
3245
- * handleClick() {
3246
- * this.#player.value.setVolume(0.5);
3247
- * }
3248
- * }
3249
- *
3250
- * // Selector-based subscription
3251
- * class PlayButton extends MediaElement {
3252
- * #playback = new PlayerController(this, playerContext, selectPlayback);
3253
- * }
3254
- * ```
3255
- */
3256
- var PlayerController = class {
3257
- #host;
3258
- #selector;
3259
- #consumer;
3260
- #store = null;
3261
- constructor(host, context, selector) {
3262
- this.#host = host;
3263
- this.#selector = selector;
3264
- this.#consumer = new ContextConsumer(host, {
3265
- context,
3266
- callback: (ctx) => this.#connect(ctx),
3267
- subscribe: true
3268
- });
3269
- host.addController(this);
3270
- }
3271
- get value() {
3272
- const store = this.#consumer.value;
3273
- if (!store) return void 0;
3274
- if (!this.#selector) return store;
3275
- return this.#store?.value;
3276
- }
3277
- get displayName() {
3278
- return this.#selector?.displayName;
3279
- }
3280
- hostConnected() {
3281
- const store = this.#consumer.value;
3282
- if (store) this.#connect(store);
3283
- }
3284
- hostDisconnected() {
3285
- this.#store = null;
3286
- }
3287
- #connect(store) {
3288
- if (!this.#store && this.#selector) this.#store = new StoreController(this.#host, store, this.#selector);
3289
- }
3290
- };
3291
-
3292
2115
  //#endregion
3293
2116
  //#region src/player/create-player.ts
3294
2117
  function createPlayer(config) {
@@ -3314,5 +2137,5 @@ function createPlayer(config) {
3314
2137
  }
3315
2138
 
3316
2139
  //#endregion
3317
- export { selectControls as A, backgroundFeatures as B, getAnchorPositionStyle as C, createButton as D, createPopover as E, selectPlaybackRate as F, isUndefined as G, createState as H, selectTextTrack as I, tryHidePopover as J, ReactiveElement as K, selectTime as L, selectFullscreen as M, selectPiP as N, createAlertDialog as O, selectPlayback as P, selectVolume as R, getAnchorNameStyle as S, resolveOffsets as T, isFunction as U, videoFeatures as V, isNumber as W, supportsAnchorPositioning as X, tryShowPopover as Y, getSliderPreviewStyle as _, MediaElement as a, clamp as b, applyStateDataAttrs as c, createWheelStep as d, createTransition as f, getSliderCSSVars as g, ThumbnailCore as h, MediaContainerElement as i, selectError as j, selectBuffer as k, logMissingFeature as l, createThumbnail as m, PlayerController as n, ContextProvider as o, createTooltip as p, applyStyles as q, SnapshotController as r, ContextConsumer as s, createPlayer as t, applyElementProps as u, getTimeSliderCSSVars as v, getPopupPositionRect as w, roundToStep as x, createSlider as y, audioFeatures as z };
3318
- //# sourceMappingURL=create-player-p9xCO0yC.js.map
2140
+ export { ContextConsumer as A, isFunction as C, MediaContainerElement as D, isUndefined as E, isEditableTarget as M, resolveEventTarget as N, MediaElement as O, AbortControllerRegistry as S, isNumber as T, getGestureCoordinator as _, backgroundFeatures as a, noop as b, timeFeature as c, playbackRateFeature as d, playbackFeature as f, controlsFeature as g, errorFeature as h, audioFeatures as i, ReactiveElement as j, ContextProvider as k, textTrackFeature as l, fullscreenFeature as m, PlayerController as n, videoFeatures as o, pipFeature as p, SnapshotController as r, volumeFeature as s, createPlayer as t, sourceFeature as u, bufferFeature as v, isNull as w, throwNoTargetError as x, createState as y };
2141
+ //# sourceMappingURL=create-player-CyG77t-m.js.map