@videojs/html 10.0.0-beta.6 → 10.0.0-beta.7

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 (326) hide show
  1. package/cdn/audio-minimal.css +1 -1
  2. package/cdn/audio-minimal.dev.d.ts +1 -0
  3. package/cdn/audio-minimal.dev.js +9 -5336
  4. package/cdn/audio-minimal.dev.js.map +1 -1
  5. package/cdn/audio-minimal.js +1 -24
  6. package/cdn/audio-minimal.js.map +1 -1
  7. package/cdn/audio.css +1 -1
  8. package/cdn/audio.dev.d.ts +1 -0
  9. package/cdn/audio.dev.js +9 -5336
  10. package/cdn/audio.dev.js.map +1 -1
  11. package/cdn/audio.js +1 -24
  12. package/cdn/audio.js.map +1 -1
  13. package/cdn/background.css +1 -1
  14. package/cdn/background.dev.d.ts +1 -0
  15. package/cdn/background.dev.js +100 -2026
  16. package/cdn/background.dev.js.map +1 -1
  17. package/cdn/background.js +1 -18
  18. package/cdn/background.js.map +1 -1
  19. package/cdn/context-C_e06fGU.js +13 -0
  20. package/cdn/context-C_e06fGU.js.map +1 -0
  21. package/cdn/context-DTY0nOpS.js +98 -0
  22. package/cdn/context-DTY0nOpS.js.map +1 -0
  23. package/cdn/create-player-Dv7K1Ezk.js +3214 -0
  24. package/cdn/create-player-Dv7K1Ezk.js.map +1 -0
  25. package/cdn/create-player-QjiNZlh7.js +7 -0
  26. package/cdn/create-player-QjiNZlh7.js.map +1 -0
  27. package/cdn/default-GgKND7a8.js +2 -0
  28. package/cdn/default-GgKND7a8.js.map +1 -0
  29. package/cdn/default-cLso8BHO.js +28 -0
  30. package/cdn/default-cLso8BHO.js.map +1 -0
  31. package/cdn/listen-BXAYCbZA.js +9 -0
  32. package/cdn/listen-BXAYCbZA.js.map +1 -0
  33. package/cdn/listen-DX5vU4s4.js +2 -0
  34. package/cdn/listen-DX5vU4s4.js.map +1 -0
  35. package/cdn/media/dash-video.dev.d.ts +1 -0
  36. package/cdn/media/dash-video.dev.js +39165 -0
  37. package/cdn/media/dash-video.dev.js.map +1 -0
  38. package/cdn/media/dash-video.js +21 -0
  39. package/cdn/media/dash-video.js.map +1 -0
  40. package/cdn/media/hls-video.dev.d.ts +1 -0
  41. package/cdn/media/hls-video.dev.js +6 -378
  42. package/cdn/media/hls-video.dev.js.map +1 -1
  43. package/cdn/media/hls-video.js +21 -65
  44. package/cdn/media/hls-video.js.map +1 -1
  45. package/cdn/media/simple-hls-video.dev.d.ts +1 -0
  46. package/cdn/media/simple-hls-video.dev.js +6 -377
  47. package/cdn/media/simple-hls-video.dev.js.map +1 -1
  48. package/cdn/media/simple-hls-video.js +1 -45
  49. package/cdn/media/simple-hls-video.js.map +1 -1
  50. package/cdn/media-attach-mixin-ChyNp2eK.js +44 -0
  51. package/cdn/media-attach-mixin-ChyNp2eK.js.map +1 -0
  52. package/cdn/media-attach-mixin-tFNcHnvo.js +2 -0
  53. package/cdn/media-attach-mixin-tFNcHnvo.js.map +1 -0
  54. package/cdn/minimal-BJfleQcQ.js +2 -0
  55. package/cdn/minimal-BJfleQcQ.js.map +1 -0
  56. package/cdn/minimal-DBMdC_0I.js +28 -0
  57. package/cdn/minimal-DBMdC_0I.js.map +1 -0
  58. package/cdn/player-CztIlNio.js +2 -0
  59. package/cdn/player-CztIlNio.js.map +1 -0
  60. package/cdn/player-Dvj38jlr.js +15 -0
  61. package/cdn/player-Dvj38jlr.js.map +1 -0
  62. package/cdn/poster-C4WHg3BH.js +2 -0
  63. package/cdn/poster-C4WHg3BH.js.map +1 -0
  64. package/cdn/poster-O0SI05LC.js +195 -0
  65. package/cdn/poster-O0SI05LC.js.map +1 -0
  66. package/cdn/predicate-BG-dj_kF.js +26 -0
  67. package/cdn/predicate-BG-dj_kF.js.map +1 -0
  68. package/cdn/predicate-Y9jDHLpX.js +2 -0
  69. package/cdn/predicate-Y9jDHLpX.js.map +1 -0
  70. package/cdn/proxy-2oO2ph3m.js +47 -0
  71. package/cdn/proxy-2oO2ph3m.js.map +1 -0
  72. package/cdn/proxy-6KS6wy69.js +2 -0
  73. package/cdn/proxy-6KS6wy69.js.map +1 -0
  74. package/cdn/proxy-XzDf9gyk.js +66 -0
  75. package/cdn/proxy-XzDf9gyk.js.map +1 -0
  76. package/cdn/proxy-dR7IDk37.js +349 -0
  77. package/cdn/proxy-dR7IDk37.js.map +1 -0
  78. package/cdn/safe-define-B8lHgj_K.js +9 -0
  79. package/cdn/safe-define-B8lHgj_K.js.map +1 -0
  80. package/cdn/safe-define-GrHW3P9e.js +2 -0
  81. package/cdn/safe-define-GrHW3P9e.js.map +1 -0
  82. package/cdn/video-minimal.css +1 -1
  83. package/cdn/video-minimal.dev.d.ts +1 -0
  84. package/cdn/video-minimal.dev.js +16 -5650
  85. package/cdn/video-minimal.dev.js.map +1 -1
  86. package/cdn/video-minimal.js +1 -24
  87. package/cdn/video-minimal.js.map +1 -1
  88. package/cdn/video.css +1 -1
  89. package/cdn/video.dev.d.ts +1 -0
  90. package/cdn/video.dev.js +24 -5709
  91. package/cdn/video.dev.js.map +1 -1
  92. package/cdn/video.js +1 -24
  93. package/cdn/video.js.map +1 -1
  94. package/cdn/volume-slider-BqzTytgB.js +8 -0
  95. package/cdn/volume-slider-BqzTytgB.js.map +1 -0
  96. package/cdn/volume-slider-CfhOO9RM.js +2453 -0
  97. package/cdn/volume-slider-CfhOO9RM.js.map +1 -0
  98. package/dist/default/_virtual/inline-css_src/define/audio/minimal-skin.js +1 -1
  99. package/dist/default/_virtual/inline-css_src/define/audio/minimal-skin.js.map +1 -1
  100. package/dist/default/_virtual/inline-css_src/define/audio/skin.js +1 -1
  101. package/dist/default/_virtual/inline-css_src/define/audio/skin.js.map +1 -1
  102. package/dist/default/_virtual/inline-css_src/define/base.js +1 -1
  103. package/dist/default/_virtual/inline-css_src/define/base.js.map +1 -1
  104. package/dist/default/_virtual/inline-css_src/define/shared.js +6 -0
  105. package/dist/default/_virtual/inline-css_src/define/shared.js.map +1 -0
  106. package/dist/default/_virtual/inline-css_src/define/video/minimal-skin.js +1 -1
  107. package/dist/default/_virtual/inline-css_src/define/video/minimal-skin.js.map +1 -1
  108. package/dist/default/_virtual/inline-css_src/define/video/skin.js +1 -1
  109. package/dist/default/_virtual/inline-css_src/define/video/skin.js.map +1 -1
  110. package/dist/default/define/audio/minimal-skin.css +22 -20
  111. package/dist/default/define/audio/minimal-skin.js +1 -1
  112. package/dist/default/define/audio/minimal-skin.js.map +1 -1
  113. package/dist/default/define/audio/minimal-skin.tailwind.js +1 -1
  114. package/dist/default/define/audio/minimal-skin.tailwind.js.map +1 -1
  115. package/dist/default/define/audio/skin.css +19 -22
  116. package/dist/default/define/audio/skin.js +1 -1
  117. package/dist/default/define/audio/skin.js.map +1 -1
  118. package/dist/default/define/audio/skin.tailwind.js +3 -4
  119. package/dist/default/define/audio/skin.tailwind.js.map +1 -1
  120. package/dist/default/define/background/skin.css +1 -1
  121. package/dist/default/define/background/skin.js +1 -1
  122. package/dist/default/define/background/skin.js.map +1 -1
  123. package/dist/default/define/base.css +7 -7
  124. package/dist/default/define/media/dash-video.js +14 -0
  125. package/dist/default/define/media/dash-video.js.map +1 -0
  126. package/dist/default/define/shared.css +6 -0
  127. package/dist/default/define/skin-mixin.js +8 -3
  128. package/dist/default/define/skin-mixin.js.map +1 -1
  129. package/dist/default/define/video/minimal-skin.css +101 -71
  130. package/dist/default/define/video/minimal-skin.js +2 -1
  131. package/dist/default/define/video/minimal-skin.js.map +1 -1
  132. package/dist/default/define/video/minimal-skin.tailwind.js +4 -2
  133. package/dist/default/define/video/minimal-skin.tailwind.js.map +1 -1
  134. package/dist/default/define/video/skin.css +98 -72
  135. package/dist/default/define/video/skin.js +2 -1
  136. package/dist/default/define/video/skin.js.map +1 -1
  137. package/dist/default/define/video/skin.tailwind.js +4 -2
  138. package/dist/default/define/video/skin.tailwind.js.map +1 -1
  139. package/dist/default/icons/dist/render/default/index.js +2 -1
  140. package/dist/default/icons/dist/render/default/index.js.map +1 -1
  141. package/dist/default/icons/dist/render/minimal/index.js +2 -1
  142. package/dist/default/icons/dist/render/minimal/index.js.map +1 -1
  143. package/dist/default/index.js +3 -2
  144. package/dist/default/media/background-video/index.js +5 -1
  145. package/dist/default/media/background-video/index.js.map +1 -1
  146. package/dist/default/media/container-element.js +5 -2
  147. package/dist/default/media/container-element.js.map +1 -1
  148. package/dist/default/media/dash-video/index.js +26 -0
  149. package/dist/default/media/dash-video/index.js.map +1 -0
  150. package/dist/default/media/hls-video/index.js +2 -1
  151. package/dist/default/media/hls-video/index.js.map +1 -1
  152. package/dist/default/media/simple-hls-video/index.js +2 -1
  153. package/dist/default/media/simple-hls-video/index.js.map +1 -1
  154. package/dist/default/player/context.js +6 -2
  155. package/dist/default/player/context.js.map +1 -1
  156. package/dist/default/player/create-player.js +11 -3
  157. package/dist/default/player/create-player.js.map +1 -1
  158. package/dist/default/skins/dist/default/default/tailwind/audio.tailwind.js +6 -5
  159. package/dist/default/skins/dist/default/default/tailwind/audio.tailwind.js.map +1 -1
  160. package/dist/default/skins/dist/default/default/tailwind/components/controls.js +1 -1
  161. package/dist/default/skins/dist/default/default/tailwind/components/controls.js.map +1 -1
  162. package/dist/default/skins/dist/default/default/tailwind/components/error.js +1 -1
  163. package/dist/default/skins/dist/default/default/tailwind/components/error.js.map +1 -1
  164. package/dist/default/skins/dist/default/default/tailwind/components/poster.js +16 -0
  165. package/dist/default/skins/dist/default/default/tailwind/components/poster.js.map +1 -0
  166. package/dist/default/skins/dist/default/default/tailwind/video.tailwind.js +6 -5
  167. package/dist/default/skins/dist/default/default/tailwind/video.tailwind.js.map +1 -1
  168. package/dist/default/skins/dist/default/minimal/tailwind/audio.tailwind.js +1 -1
  169. package/dist/default/skins/dist/default/minimal/tailwind/audio.tailwind.js.map +1 -1
  170. package/dist/default/skins/dist/default/minimal/tailwind/components/controls.js +1 -1
  171. package/dist/default/skins/dist/default/minimal/tailwind/components/controls.js.map +1 -1
  172. package/dist/default/skins/dist/default/minimal/tailwind/components/playback-rate.js +6 -0
  173. package/dist/default/skins/dist/default/minimal/tailwind/components/playback-rate.js.map +1 -0
  174. package/dist/default/skins/dist/default/minimal/tailwind/components/poster.js +16 -0
  175. package/dist/default/skins/dist/default/minimal/tailwind/components/poster.js.map +1 -0
  176. package/dist/default/skins/dist/default/minimal/tailwind/components/time.js +1 -1
  177. package/dist/default/skins/dist/default/minimal/tailwind/components/time.js.map +1 -1
  178. package/dist/default/skins/dist/default/minimal/tailwind/video.tailwind.js +6 -4
  179. package/dist/default/skins/dist/default/minimal/tailwind/video.tailwind.js.map +1 -1
  180. package/dist/default/skins/dist/default/shared/tailwind/icon-state.js +5 -0
  181. package/dist/default/skins/dist/default/shared/tailwind/icon-state.js.map +1 -1
  182. package/dist/default/store/container-mixin.js +16 -72
  183. package/dist/default/store/container-mixin.js.map +1 -1
  184. package/dist/default/store/media-attach-mixin.js +45 -0
  185. package/dist/default/store/media-attach-mixin.js.map +1 -0
  186. package/dist/default/store/provider-mixin.js +99 -9
  187. package/dist/default/store/provider-mixin.js.map +1 -1
  188. package/dist/default/ui/popover/popover-element.js +54 -3
  189. package/dist/default/ui/popover/popover-element.js.map +1 -1
  190. package/dist/default/ui/time-slider/time-slider-element.js +1 -1
  191. package/dist/default/ui/time-slider/time-slider-element.js.map +1 -1
  192. package/dist/default/ui/tooltip/tooltip-element.js +53 -3
  193. package/dist/default/ui/tooltip/tooltip-element.js.map +1 -1
  194. package/dist/default/ui/volume-slider/volume-slider-element.js +3 -3
  195. package/dist/default/ui/volume-slider/volume-slider-element.js.map +1 -1
  196. package/dist/dev/_virtual/inline-css_src/define/audio/minimal-skin.js +1 -1
  197. package/dist/dev/_virtual/inline-css_src/define/audio/minimal-skin.js.map +1 -1
  198. package/dist/dev/_virtual/inline-css_src/define/audio/skin.js +1 -1
  199. package/dist/dev/_virtual/inline-css_src/define/audio/skin.js.map +1 -1
  200. package/dist/dev/_virtual/inline-css_src/define/base.js +1 -1
  201. package/dist/dev/_virtual/inline-css_src/define/base.js.map +1 -1
  202. package/dist/dev/_virtual/inline-css_src/define/shared.js +6 -0
  203. package/dist/dev/_virtual/inline-css_src/define/shared.js.map +1 -0
  204. package/dist/dev/_virtual/inline-css_src/define/video/minimal-skin.js +1 -1
  205. package/dist/dev/_virtual/inline-css_src/define/video/minimal-skin.js.map +1 -1
  206. package/dist/dev/_virtual/inline-css_src/define/video/skin.js +1 -1
  207. package/dist/dev/_virtual/inline-css_src/define/video/skin.js.map +1 -1
  208. package/dist/dev/define/audio/minimal-skin.css +22 -20
  209. package/dist/dev/define/audio/minimal-skin.d.ts.map +1 -1
  210. package/dist/dev/define/audio/minimal-skin.js +2 -0
  211. package/dist/dev/define/audio/minimal-skin.js.map +1 -1
  212. package/dist/dev/define/audio/minimal-skin.tailwind.d.ts.map +1 -1
  213. package/dist/dev/define/audio/minimal-skin.tailwind.js +3 -1
  214. package/dist/dev/define/audio/minimal-skin.tailwind.js.map +1 -1
  215. package/dist/dev/define/audio/skin.css +19 -22
  216. package/dist/dev/define/audio/skin.d.ts.map +1 -1
  217. package/dist/dev/define/audio/skin.js +2 -0
  218. package/dist/dev/define/audio/skin.js.map +1 -1
  219. package/dist/dev/define/audio/skin.tailwind.d.ts.map +1 -1
  220. package/dist/dev/define/audio/skin.tailwind.js +5 -4
  221. package/dist/dev/define/audio/skin.tailwind.js.map +1 -1
  222. package/dist/dev/define/background/skin.css +1 -1
  223. package/dist/dev/define/background/skin.d.ts.map +1 -1
  224. package/dist/dev/define/background/skin.js +3 -1
  225. package/dist/dev/define/background/skin.js.map +1 -1
  226. package/dist/dev/define/base.css +7 -7
  227. package/dist/dev/define/media/dash-video.d.ts +14 -0
  228. package/dist/dev/define/media/dash-video.d.ts.map +1 -0
  229. package/dist/dev/define/media/dash-video.js +14 -0
  230. package/dist/dev/define/media/dash-video.js.map +1 -0
  231. package/dist/dev/define/shared.css +6 -0
  232. package/dist/dev/define/skin-mixin.d.ts.map +1 -1
  233. package/dist/dev/define/skin-mixin.js +8 -3
  234. package/dist/dev/define/skin-mixin.js.map +1 -1
  235. package/dist/dev/define/video/minimal-skin.css +101 -71
  236. package/dist/dev/define/video/minimal-skin.d.ts.map +1 -1
  237. package/dist/dev/define/video/minimal-skin.js +10 -2
  238. package/dist/dev/define/video/minimal-skin.js.map +1 -1
  239. package/dist/dev/define/video/minimal-skin.tailwind.d.ts.map +1 -1
  240. package/dist/dev/define/video/minimal-skin.tailwind.js +13 -4
  241. package/dist/dev/define/video/minimal-skin.tailwind.js.map +1 -1
  242. package/dist/dev/define/video/skin.css +98 -72
  243. package/dist/dev/define/video/skin.d.ts.map +1 -1
  244. package/dist/dev/define/video/skin.js +9 -1
  245. package/dist/dev/define/video/skin.js.map +1 -1
  246. package/dist/dev/define/video/skin.tailwind.d.ts.map +1 -1
  247. package/dist/dev/define/video/skin.tailwind.js +13 -4
  248. package/dist/dev/define/video/skin.tailwind.js.map +1 -1
  249. package/dist/dev/icons/dist/render/default/index.js +2 -1
  250. package/dist/dev/icons/dist/render/default/index.js.map +1 -1
  251. package/dist/dev/icons/dist/render/minimal/index.js +2 -1
  252. package/dist/dev/icons/dist/render/minimal/index.js.map +1 -1
  253. package/dist/dev/index.d.ts +5 -4
  254. package/dist/dev/index.js +3 -2
  255. package/dist/dev/media/background-video/index.d.ts +8 -1
  256. package/dist/dev/media/background-video/index.d.ts.map +1 -1
  257. package/dist/dev/media/background-video/index.js +5 -1
  258. package/dist/dev/media/background-video/index.js.map +1 -1
  259. package/dist/dev/media/container-element.js +5 -2
  260. package/dist/dev/media/container-element.js.map +1 -1
  261. package/dist/dev/media/dash-video/index.d.ts +13 -0
  262. package/dist/dev/media/dash-video/index.d.ts.map +1 -0
  263. package/dist/dev/media/dash-video/index.js +26 -0
  264. package/dist/dev/media/dash-video/index.js.map +1 -0
  265. package/dist/dev/media/hls-video/index.d.ts +2 -1
  266. package/dist/dev/media/hls-video/index.d.ts.map +1 -1
  267. package/dist/dev/media/hls-video/index.js +2 -1
  268. package/dist/dev/media/hls-video/index.js.map +1 -1
  269. package/dist/dev/media/simple-hls-video/index.d.ts +2 -1
  270. package/dist/dev/media/simple-hls-video/index.d.ts.map +1 -1
  271. package/dist/dev/media/simple-hls-video/index.js +2 -1
  272. package/dist/dev/media/simple-hls-video/index.js.map +1 -1
  273. package/dist/dev/player/context.d.ts +16 -2
  274. package/dist/dev/player/context.d.ts.map +1 -1
  275. package/dist/dev/player/context.js +6 -2
  276. package/dist/dev/player/context.js.map +1 -1
  277. package/dist/dev/player/create-player.d.ts +1 -1
  278. package/dist/dev/player/create-player.js +11 -3
  279. package/dist/dev/player/create-player.js.map +1 -1
  280. package/dist/dev/skins/dist/default/default/tailwind/audio.tailwind.js +6 -5
  281. package/dist/dev/skins/dist/default/default/tailwind/audio.tailwind.js.map +1 -1
  282. package/dist/dev/skins/dist/default/default/tailwind/components/controls.js +1 -1
  283. package/dist/dev/skins/dist/default/default/tailwind/components/controls.js.map +1 -1
  284. package/dist/dev/skins/dist/default/default/tailwind/components/error.js +1 -1
  285. package/dist/dev/skins/dist/default/default/tailwind/components/error.js.map +1 -1
  286. package/dist/dev/skins/dist/default/default/tailwind/components/poster.js +16 -0
  287. package/dist/dev/skins/dist/default/default/tailwind/components/poster.js.map +1 -0
  288. package/dist/dev/skins/dist/default/default/tailwind/video.tailwind.js +6 -5
  289. package/dist/dev/skins/dist/default/default/tailwind/video.tailwind.js.map +1 -1
  290. package/dist/dev/skins/dist/default/minimal/tailwind/audio.tailwind.js +1 -1
  291. package/dist/dev/skins/dist/default/minimal/tailwind/audio.tailwind.js.map +1 -1
  292. package/dist/dev/skins/dist/default/minimal/tailwind/components/controls.js +1 -1
  293. package/dist/dev/skins/dist/default/minimal/tailwind/components/controls.js.map +1 -1
  294. package/dist/dev/skins/dist/default/minimal/tailwind/components/playback-rate.js +6 -0
  295. package/dist/dev/skins/dist/default/minimal/tailwind/components/playback-rate.js.map +1 -0
  296. package/dist/dev/skins/dist/default/minimal/tailwind/components/poster.js +16 -0
  297. package/dist/dev/skins/dist/default/minimal/tailwind/components/poster.js.map +1 -0
  298. package/dist/dev/skins/dist/default/minimal/tailwind/components/time.js +1 -1
  299. package/dist/dev/skins/dist/default/minimal/tailwind/components/time.js.map +1 -1
  300. package/dist/dev/skins/dist/default/minimal/tailwind/video.tailwind.js +6 -4
  301. package/dist/dev/skins/dist/default/minimal/tailwind/video.tailwind.js.map +1 -1
  302. package/dist/dev/skins/dist/default/shared/tailwind/icon-state.js +5 -0
  303. package/dist/dev/skins/dist/default/shared/tailwind/icon-state.js.map +1 -1
  304. package/dist/dev/store/container-mixin.d.ts +10 -5
  305. package/dist/dev/store/container-mixin.d.ts.map +1 -1
  306. package/dist/dev/store/container-mixin.js +16 -72
  307. package/dist/dev/store/container-mixin.js.map +1 -1
  308. package/dist/dev/store/media-attach-mixin.d.ts +19 -0
  309. package/dist/dev/store/media-attach-mixin.d.ts.map +1 -0
  310. package/dist/dev/store/media-attach-mixin.js +45 -0
  311. package/dist/dev/store/media-attach-mixin.js.map +1 -0
  312. package/dist/dev/store/provider-mixin.d.ts +19 -6
  313. package/dist/dev/store/provider-mixin.d.ts.map +1 -1
  314. package/dist/dev/store/provider-mixin.js +99 -9
  315. package/dist/dev/store/provider-mixin.js.map +1 -1
  316. package/dist/dev/ui/popover/popover-element.d.ts.map +1 -1
  317. package/dist/dev/ui/popover/popover-element.js +54 -3
  318. package/dist/dev/ui/popover/popover-element.js.map +1 -1
  319. package/dist/dev/ui/time-slider/time-slider-element.js +1 -1
  320. package/dist/dev/ui/time-slider/time-slider-element.js.map +1 -1
  321. package/dist/dev/ui/tooltip/tooltip-element.d.ts.map +1 -1
  322. package/dist/dev/ui/tooltip/tooltip-element.js +53 -3
  323. package/dist/dev/ui/tooltip/tooltip-element.js.map +1 -1
  324. package/dist/dev/ui/volume-slider/volume-slider-element.js +3 -3
  325. package/dist/dev/ui/volume-slider/volume-slider-element.js.map +1 -1
  326. package/package.json +20 -9
@@ -0,0 +1,19 @@
1
+ import { MediaContext } from "../player/context.js";
2
+ import { AnyConstructor } from "@videojs/utils/types";
3
+
4
+ //#region src/store/media-attach-mixin.d.ts
5
+ type MediaAttachMixin = <Class extends AnyConstructor<HTMLElement>>(BaseClass: Class) => Class;
6
+ /**
7
+ * Create a mixin that consumes `mediaContext` and registers the
8
+ * element as the media with the provider.
9
+ *
10
+ * Uses the raw context-request protocol so it works with any
11
+ * `HTMLElement` subclass — no `ReactiveControllerHost` required.
12
+ *
13
+ * @param context - The media context to consume.
14
+ */
15
+ declare function createMediaAttachMixin(context: MediaContext): MediaAttachMixin;
16
+ declare const MediaAttachMixin: MediaAttachMixin;
17
+ //#endregion
18
+ export { MediaAttachMixin, createMediaAttachMixin };
19
+ //# sourceMappingURL=media-attach-mixin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-attach-mixin.d.ts","names":[],"sources":["../../../src/store/media-attach-mixin.ts"],"mappings":";;;;KAMY,gBAAA,kBAAkC,cAAA,CAAe,WAAA,GAAc,SAAA,EAAW,KAAA,KAAU,KAAA;;AAAhG;;;;;;;;iBAWgB,sBAAA,CAAuB,OAAA,EAAS,YAAA,GAAe,gBAAA;AAAA,cA0ClD,gBAAA,EAAgB,gBAAA"}
@@ -0,0 +1,45 @@
1
+ import { mediaContext } from "../player/context.js";
2
+ import { ContextEvent } from "@videojs/element/context";
3
+
4
+ //#region src/store/media-attach-mixin.ts
5
+ /**
6
+ * Create a mixin that consumes `mediaContext` and registers the
7
+ * element as the media with the provider.
8
+ *
9
+ * Uses the raw context-request protocol so it works with any
10
+ * `HTMLElement` subclass — no `ReactiveControllerHost` required.
11
+ *
12
+ * @param context - The media context to consume.
13
+ */
14
+ function createMediaAttachMixin(context) {
15
+ return (BaseClass) => {
16
+ class MediaAttachElement extends BaseClass {
17
+ #setMedia = null;
18
+ #unsubscribe = null;
19
+ getMediaTarget() {
20
+ return this;
21
+ }
22
+ connectedCallback() {
23
+ super.connectedCallback?.();
24
+ this.dispatchEvent(new ContextEvent(context, this, (value, unsubscribe) => {
25
+ if (unsubscribe) this.#unsubscribe = unsubscribe;
26
+ this.#setMedia = value?.setMedia ?? null;
27
+ if (this.isConnected) this.#setMedia?.(this.getMediaTarget());
28
+ }, true));
29
+ }
30
+ disconnectedCallback() {
31
+ super.disconnectedCallback?.();
32
+ this.#setMedia?.(null);
33
+ this.#unsubscribe?.();
34
+ this.#unsubscribe = null;
35
+ this.#setMedia = null;
36
+ }
37
+ }
38
+ return MediaAttachElement;
39
+ };
40
+ }
41
+ const MediaAttachMixin = createMediaAttachMixin(mediaContext);
42
+
43
+ //#endregion
44
+ export { MediaAttachMixin, createMediaAttachMixin };
45
+ //# sourceMappingURL=media-attach-mixin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-attach-mixin.js","names":["#unsubscribe","#setMedia"],"sources":["../../../src/store/media-attach-mixin.ts"],"sourcesContent":["import type { Media } from '@videojs/core/dom';\nimport { ContextEvent } from '@videojs/element/context';\nimport type { CustomElement } from '@videojs/utils/dom';\nimport type { AnyConstructor, Constructor } from '@videojs/utils/types';\nimport { type MediaContext, mediaContext } from '../player/context';\n\nexport type MediaAttachMixin = <Class extends AnyConstructor<HTMLElement>>(BaseClass: Class) => Class;\n\n/**\n * Create a mixin that consumes `mediaContext` and registers the\n * element as the media with the provider.\n *\n * Uses the raw context-request protocol so it works with any\n * `HTMLElement` subclass — no `ReactiveControllerHost` required.\n *\n * @param context - The media context to consume.\n */\nexport function createMediaAttachMixin(context: MediaContext): MediaAttachMixin {\n return <Class extends AnyConstructor<HTMLElement>>(BaseClass: Class) => {\n class MediaAttachElement extends (BaseClass as unknown as Constructor<CustomElement>) {\n #setMedia: ((media: Media | null) => void) | null = null;\n #unsubscribe: (() => void) | null = null;\n\n getMediaTarget(): Media | null {\n return this as unknown as Media;\n }\n\n override connectedCallback() {\n super.connectedCallback?.();\n\n this.dispatchEvent(\n new ContextEvent(\n context,\n this,\n (value, unsubscribe) => {\n if (unsubscribe) this.#unsubscribe = unsubscribe;\n this.#setMedia = value?.setMedia ?? null;\n if (this.isConnected) {\n this.#setMedia?.(this.getMediaTarget());\n }\n },\n true\n )\n );\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback?.();\n this.#setMedia?.(null);\n this.#unsubscribe?.();\n this.#unsubscribe = null;\n this.#setMedia = null;\n }\n }\n\n return MediaAttachElement as unknown as Class;\n };\n}\n\nexport const MediaAttachMixin = createMediaAttachMixin(mediaContext);\n"],"mappings":";;;;;;;;;;;;;AAiBA,SAAgB,uBAAuB,SAAyC;AAC9E,SAAmD,cAAqB;EACtE,MAAM,2BAA4B,UAAoD;GACpF,YAAoD;GACpD,eAAoC;GAEpC,iBAA+B;AAC7B,WAAO;;GAGT,AAAS,oBAAoB;AAC3B,UAAM,qBAAqB;AAE3B,SAAK,cACH,IAAI,aACF,SACA,OACC,OAAO,gBAAgB;AACtB,SAAI,YAAa,OAAKA,cAAe;AACrC,WAAKC,WAAY,OAAO,YAAY;AACpC,SAAI,KAAK,YACP,OAAKA,WAAY,KAAK,gBAAgB,CAAC;OAG3C,KACD,CACF;;GAGH,AAAS,uBAAuB;AAC9B,UAAM,wBAAwB;AAC9B,UAAKA,WAAY,KAAK;AACtB,UAAKD,eAAgB;AACrB,UAAKA,cAAe;AACpB,UAAKC,WAAY;;;AAIrB,SAAO;;;AAIX,MAAa,mBAAmB,uBAAuB,aAAa"}
@@ -1,17 +1,30 @@
1
- import { PlayerContext } from "../player/context.js";
1
+ import { ContainerContext, MediaContext, PlayerContext } from "../player/context.js";
2
2
  import { MediaElementConstructor } from "../ui/media-element.js";
3
3
  import { PlayerProviderConstructor } from "./types.js";
4
4
  import { PlayerStore } from "@videojs/core/dom";
5
5
 
6
6
  //#region src/store/provider-mixin.d.ts
7
+ interface ProviderMixinConfig<Store extends PlayerStore> {
8
+ playerContext: PlayerContext<Store>;
9
+ mediaContext: MediaContext;
10
+ containerContext: ContainerContext;
11
+ factory: () => Store;
12
+ }
7
13
  type ProviderMixin<Store extends PlayerStore> = <Class extends MediaElementConstructor>(BaseClass: Class) => Class & PlayerProviderConstructor<Store>;
8
14
  /**
9
- * Create a mixin that provides player context to descendant elements.
15
+ * Create a mixin that provides player context to descendant elements and
16
+ * owns the `store.attach()` lifecycle.
10
17
  *
11
- * @param context - Player context to provide to descendants.
12
- * @param factory - Factory function that creates a store instance.
18
+ * Media and container elements register themselves via media/container
19
+ * contexts that carry both the current value and a setter. When a media
20
+ * element is available, the provider calls `store.attach({ media, container })`.
21
+ *
22
+ * As a fallback for plain `<video>`/`<audio>` that can't consume context,
23
+ * the provider queries its subtree after a microtask.
24
+ *
25
+ * @param config - Provider configuration with contexts and store factory.
13
26
  */
14
- declare function createProviderMixin<Store extends PlayerStore>(context: PlayerContext<Store>, factory: () => Store): ProviderMixin<Store>;
27
+ declare function createProviderMixin<Store extends PlayerStore>(config: ProviderMixinConfig<Store>): ProviderMixin<Store>;
15
28
  //#endregion
16
- export { ProviderMixin, createProviderMixin };
29
+ export { ProviderMixin, ProviderMixinConfig, createProviderMixin };
17
30
  //# sourceMappingURL=provider-mixin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider-mixin.d.ts","names":[],"sources":["../../../src/store/provider-mixin.ts"],"mappings":";;;;;;KAOY,aAAA,eAA4B,WAAA,mBAA8B,uBAAA,EACpE,SAAA,EAAW,KAAA,KACR,KAAA,GAAQ,yBAAA,CAA0B,KAAA;;AAFvC;;;;;iBAUgB,mBAAA,eAAkC,WAAA,CAAA,CAChD,OAAA,EAAS,aAAA,CAAc,KAAA,GACvB,OAAA,QAAe,KAAA,GACd,aAAA,CAAc,KAAA"}
1
+ {"version":3,"file":"provider-mixin.d.ts","names":[],"sources":["../../../src/store/provider-mixin.ts"],"mappings":";;;;;;UAOiB,mBAAA,eAAkC,WAAA;EACjD,aAAA,EAAe,aAAA,CAAc,KAAA;EAC7B,YAAA,EAAc,YAAA;EACd,gBAAA,EAAkB,gBAAA;EAClB,OAAA,QAAe,KAAA;AAAA;AAAA,KAGL,aAAA,eAA4B,WAAA,mBAA8B,uBAAA,EACpE,SAAA,EAAW,KAAA,KACR,KAAA,GAAQ,yBAAA,CAA0B,KAAA;;;;;;;;;;;;;;iBAevB,mBAAA,eAAkC,WAAA,CAAA,CAChD,MAAA,EAAQ,mBAAA,CAAoB,KAAA,IAC3B,aAAA,CAAc,KAAA"}
@@ -3,32 +3,122 @@ import { isNull } from "@videojs/utils/predicate";
3
3
 
4
4
  //#region src/store/provider-mixin.ts
5
5
  /**
6
- * Create a mixin that provides player context to descendant elements.
6
+ * Create a mixin that provides player context to descendant elements and
7
+ * owns the `store.attach()` lifecycle.
7
8
  *
8
- * @param context - Player context to provide to descendants.
9
- * @param factory - Factory function that creates a store instance.
9
+ * Media and container elements register themselves via media/container
10
+ * contexts that carry both the current value and a setter. When a media
11
+ * element is available, the provider calls `store.attach({ media, container })`.
12
+ *
13
+ * As a fallback for plain `<video>`/`<audio>` that can't consume context,
14
+ * the provider queries its subtree after a microtask.
15
+ *
16
+ * @param config - Provider configuration with contexts and store factory.
10
17
  */
11
- function createProviderMixin(context, factory) {
18
+ function createProviderMixin(config) {
12
19
  return (BaseClass) => {
13
20
  class PlayerProviderElement extends BaseClass {
14
- #store = factory();
15
- #provider = new ContextProvider(this, {
16
- context,
21
+ #store = config.factory();
22
+ #detach = null;
23
+ #media = null;
24
+ #container = null;
25
+ #fallbackQueued = false;
26
+ #setMedia = (media) => {
27
+ if (this.#media === media) return;
28
+ this.#media = media;
29
+ this.#mediaProvider.setValue({
30
+ media,
31
+ setMedia: this.#setMedia
32
+ });
33
+ this.#tryAttach();
34
+ };
35
+ #setContainer = (container) => {
36
+ if (this.#container === container) return;
37
+ this.#container = container;
38
+ this.#containerProvider.setValue({
39
+ container,
40
+ setContainer: this.#setContainer
41
+ });
42
+ this.#tryAttach();
43
+ };
44
+ #playerProvider = new ContextProvider(this, {
45
+ context: config.playerContext,
17
46
  initialValue: this.store
18
47
  });
48
+ #mediaProvider = new ContextProvider(this, {
49
+ context: config.mediaContext,
50
+ initialValue: {
51
+ media: this.#media,
52
+ setMedia: this.#setMedia
53
+ }
54
+ });
55
+ #containerProvider = new ContextProvider(this, {
56
+ context: config.containerContext,
57
+ initialValue: {
58
+ container: this.#container,
59
+ setContainer: this.#setContainer
60
+ }
61
+ });
19
62
  get store() {
20
- if (isNull(this.#store)) this.#store = factory();
63
+ if (isNull(this.#store)) this.#store = config.factory();
21
64
  return this.#store;
22
65
  }
23
66
  connectedCallback() {
24
67
  super.connectedCallback();
25
- this.#provider.setValue(this.store);
68
+ this.#playerProvider.setValue(this.store);
69
+ this.#mediaProvider.setValue({
70
+ media: this.#media,
71
+ setMedia: this.#setMedia
72
+ });
73
+ this.#containerProvider.setValue({
74
+ container: this.#container,
75
+ setContainer: this.#setContainer
76
+ });
77
+ this.#tryAttach();
78
+ this.#queueFallbackDiscovery();
79
+ }
80
+ disconnectedCallback() {
81
+ super.disconnectedCallback();
82
+ this.#detachStore();
26
83
  }
27
84
  destroyCallback() {
85
+ this.#detachStore();
28
86
  this.#store?.destroy();
29
87
  this.#store = null;
30
88
  super.destroyCallback();
31
89
  }
90
+ #tryAttach() {
91
+ const store = this.#store;
92
+ if (!store) return;
93
+ if (!this.#media) {
94
+ this.#detachStore();
95
+ return;
96
+ }
97
+ const target = {
98
+ media: this.#media,
99
+ container: this.#container
100
+ };
101
+ const hasMediaChanged = store.target?.media !== target.media;
102
+ const hasContainerChanged = store.target?.container !== target.container;
103
+ if (hasMediaChanged || hasContainerChanged) {
104
+ this.#detachStore();
105
+ this.#detach = store.attach(target);
106
+ }
107
+ }
108
+ #detachStore() {
109
+ this.#detach?.();
110
+ this.#detach = null;
111
+ }
112
+ #queueFallbackDiscovery() {
113
+ if (this.#media || this.#fallbackQueued) return;
114
+ this.#fallbackQueued = true;
115
+ queueMicrotask(() => {
116
+ this.#fallbackQueued = false;
117
+ if (this.#media) return;
118
+ const media = this.querySelector("video, audio");
119
+ if (media) this.#setMedia(media);
120
+ });
121
+ }
32
122
  }
33
123
  return PlayerProviderElement;
34
124
  };
@@ -1 +1 @@
1
- {"version":3,"file":"provider-mixin.js","names":["#store","#provider"],"sources":["../../../src/store/provider-mixin.ts"],"sourcesContent":["import type { PlayerStore } from '@videojs/core/dom';\nimport { ContextProvider } from '@videojs/element/context';\nimport { isNull } from '@videojs/utils/predicate';\nimport type { MediaElementConstructor } from '@/ui/media-element';\nimport type { PlayerContext } from '../player/context';\nimport type { PlayerProvider, PlayerProviderConstructor } from './types';\n\nexport type ProviderMixin<Store extends PlayerStore> = <Class extends MediaElementConstructor>(\n BaseClass: Class\n) => Class & PlayerProviderConstructor<Store>;\n\n/**\n * Create a mixin that provides player context to descendant elements.\n *\n * @param context - Player context to provide to descendants.\n * @param factory - Factory function that creates a store instance.\n */\nexport function createProviderMixin<Store extends PlayerStore>(\n context: PlayerContext<Store>,\n factory: () => Store\n): ProviderMixin<Store> {\n return <Class extends MediaElementConstructor>(BaseClass: Class) => {\n class PlayerProviderElement extends BaseClass implements PlayerProvider<Store> {\n #store: Store | null = factory();\n\n #provider = new ContextProvider(this, {\n context,\n initialValue: this.store,\n });\n\n get store(): Store {\n if (isNull(this.#store)) {\n this.#store = factory();\n }\n\n return this.#store;\n }\n\n override connectedCallback() {\n super.connectedCallback();\n this.#provider.setValue(this.store);\n }\n\n override destroyCallback() {\n this.#store?.destroy();\n this.#store = null;\n super.destroyCallback();\n }\n }\n\n return PlayerProviderElement;\n };\n}\n"],"mappings":";;;;;;;;;;AAiBA,SAAgB,oBACd,SACA,SACsB;AACtB,SAA+C,cAAqB;EAClE,MAAM,8BAA8B,UAA2C;GAC7E,SAAuB,SAAS;GAEhC,YAAY,IAAI,gBAAgB,MAAM;IACpC;IACA,cAAc,KAAK;IACpB,CAAC;GAEF,IAAI,QAAe;AACjB,QAAI,OAAO,MAAKA,MAAO,CACrB,OAAKA,QAAS,SAAS;AAGzB,WAAO,MAAKA;;GAGd,AAAS,oBAAoB;AAC3B,UAAM,mBAAmB;AACzB,UAAKC,SAAU,SAAS,KAAK,MAAM;;GAGrC,AAAS,kBAAkB;AACzB,UAAKD,OAAQ,SAAS;AACtB,UAAKA,QAAS;AACd,UAAM,iBAAiB;;;AAI3B,SAAO"}
1
+ {"version":3,"file":"provider-mixin.js","names":["#media","#mediaProvider","#setMedia","#tryAttach","#container","#containerProvider","#setContainer","#store","#playerProvider","#queueFallbackDiscovery","#detachStore","#detach","#fallbackQueued"],"sources":["../../../src/store/provider-mixin.ts"],"sourcesContent":["import type { Media, MediaContainer, PlayerStore, PlayerTarget } from '@videojs/core/dom';\nimport { ContextProvider } from '@videojs/element/context';\nimport { isNull } from '@videojs/utils/predicate';\nimport type { MediaElementConstructor } from '@/ui/media-element';\nimport type { ContainerContext, MediaContext, PlayerContext } from '../player/context';\nimport type { PlayerProvider, PlayerProviderConstructor } from './types';\n\nexport interface ProviderMixinConfig<Store extends PlayerStore> {\n playerContext: PlayerContext<Store>;\n mediaContext: MediaContext;\n containerContext: ContainerContext;\n factory: () => Store;\n}\n\nexport type ProviderMixin<Store extends PlayerStore> = <Class extends MediaElementConstructor>(\n BaseClass: Class\n) => Class & PlayerProviderConstructor<Store>;\n\n/**\n * Create a mixin that provides player context to descendant elements and\n * owns the `store.attach()` lifecycle.\n *\n * Media and container elements register themselves via media/container\n * contexts that carry both the current value and a setter. When a media\n * element is available, the provider calls `store.attach({ media, container })`.\n *\n * As a fallback for plain `<video>`/`<audio>` that can't consume context,\n * the provider queries its subtree after a microtask.\n *\n * @param config - Provider configuration with contexts and store factory.\n */\nexport function createProviderMixin<Store extends PlayerStore>(\n config: ProviderMixinConfig<Store>\n): ProviderMixin<Store> {\n return <Class extends MediaElementConstructor>(BaseClass: Class) => {\n class PlayerProviderElement extends BaseClass implements PlayerProvider<Store> {\n #store: Store | null = config.factory();\n #detach: (() => void) | null = null;\n #media: Media | null = null;\n #container: MediaContainer | null = null;\n #fallbackQueued = false;\n\n #setMedia = (media: Media | null): void => {\n if (this.#media === media) return;\n this.#media = media;\n this.#mediaProvider.setValue({ media, setMedia: this.#setMedia });\n this.#tryAttach();\n };\n\n #setContainer = (container: MediaContainer | null): void => {\n if (this.#container === container) return;\n this.#container = container;\n this.#containerProvider.setValue({ container, setContainer: this.#setContainer });\n this.#tryAttach();\n };\n\n #playerProvider = new ContextProvider(this, {\n context: config.playerContext,\n initialValue: this.store,\n });\n\n #mediaProvider = new ContextProvider(this, {\n context: config.mediaContext,\n initialValue: { media: this.#media, setMedia: this.#setMedia },\n });\n\n #containerProvider = new ContextProvider(this, {\n context: config.containerContext,\n initialValue: { container: this.#container, setContainer: this.#setContainer },\n });\n\n get store(): Store {\n if (isNull(this.#store)) {\n this.#store = config.factory();\n }\n\n return this.#store;\n }\n\n override connectedCallback() {\n super.connectedCallback();\n this.#playerProvider.setValue(this.store);\n this.#mediaProvider.setValue({ media: this.#media, setMedia: this.#setMedia });\n this.#containerProvider.setValue({ container: this.#container, setContainer: this.#setContainer });\n this.#tryAttach();\n this.#queueFallbackDiscovery();\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.#detachStore();\n }\n\n override destroyCallback() {\n this.#detachStore();\n this.#store?.destroy();\n this.#store = null;\n super.destroyCallback();\n }\n\n #tryAttach(): void {\n const store = this.#store;\n if (!store) return;\n\n if (!this.#media) {\n this.#detachStore();\n return;\n }\n\n const target: PlayerTarget = {\n media: this.#media,\n container: this.#container,\n };\n\n const hasMediaChanged = store.target?.media !== target.media;\n const hasContainerChanged = store.target?.container !== target.container;\n\n if (hasMediaChanged || hasContainerChanged) {\n this.#detachStore();\n this.#detach = store.attach(target);\n }\n }\n\n #detachStore(): void {\n this.#detach?.();\n this.#detach = null;\n }\n\n #queueFallbackDiscovery(): void {\n if (this.#media || this.#fallbackQueued) return;\n this.#fallbackQueued = true;\n\n queueMicrotask(() => {\n this.#fallbackQueued = false;\n\n // Context already registered media — skip fallback.\n if (this.#media) return;\n\n const media = this.querySelector<HTMLMediaElement>('video, audio');\n if (media) {\n this.#setMedia(media);\n }\n });\n }\n }\n\n return PlayerProviderElement;\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA+BA,SAAgB,oBACd,QACsB;AACtB,SAA+C,cAAqB;EAClE,MAAM,8BAA8B,UAA2C;GAC7E,SAAuB,OAAO,SAAS;GACvC,UAA+B;GAC/B,SAAuB;GACvB,aAAoC;GACpC,kBAAkB;GAElB,aAAa,UAA8B;AACzC,QAAI,MAAKA,UAAW,MAAO;AAC3B,UAAKA,QAAS;AACd,UAAKC,cAAe,SAAS;KAAE;KAAO,UAAU,MAAKC;KAAW,CAAC;AACjE,UAAKC,WAAY;;GAGnB,iBAAiB,cAA2C;AAC1D,QAAI,MAAKC,cAAe,UAAW;AACnC,UAAKA,YAAa;AAClB,UAAKC,kBAAmB,SAAS;KAAE;KAAW,cAAc,MAAKC;KAAe,CAAC;AACjF,UAAKH,WAAY;;GAGnB,kBAAkB,IAAI,gBAAgB,MAAM;IAC1C,SAAS,OAAO;IAChB,cAAc,KAAK;IACpB,CAAC;GAEF,iBAAiB,IAAI,gBAAgB,MAAM;IACzC,SAAS,OAAO;IAChB,cAAc;KAAE,OAAO,MAAKH;KAAQ,UAAU,MAAKE;KAAW;IAC/D,CAAC;GAEF,qBAAqB,IAAI,gBAAgB,MAAM;IAC7C,SAAS,OAAO;IAChB,cAAc;KAAE,WAAW,MAAKE;KAAY,cAAc,MAAKE;KAAe;IAC/E,CAAC;GAEF,IAAI,QAAe;AACjB,QAAI,OAAO,MAAKC,MAAO,CACrB,OAAKA,QAAS,OAAO,SAAS;AAGhC,WAAO,MAAKA;;GAGd,AAAS,oBAAoB;AAC3B,UAAM,mBAAmB;AACzB,UAAKC,eAAgB,SAAS,KAAK,MAAM;AACzC,UAAKP,cAAe,SAAS;KAAE,OAAO,MAAKD;KAAQ,UAAU,MAAKE;KAAW,CAAC;AAC9E,UAAKG,kBAAmB,SAAS;KAAE,WAAW,MAAKD;KAAY,cAAc,MAAKE;KAAe,CAAC;AAClG,UAAKH,WAAY;AACjB,UAAKM,wBAAyB;;GAGhC,AAAS,uBAAuB;AAC9B,UAAM,sBAAsB;AAC5B,UAAKC,aAAc;;GAGrB,AAAS,kBAAkB;AACzB,UAAKA,aAAc;AACnB,UAAKH,OAAQ,SAAS;AACtB,UAAKA,QAAS;AACd,UAAM,iBAAiB;;GAGzB,aAAmB;IACjB,MAAM,QAAQ,MAAKA;AACnB,QAAI,CAAC,MAAO;AAEZ,QAAI,CAAC,MAAKP,OAAQ;AAChB,WAAKU,aAAc;AACnB;;IAGF,MAAM,SAAuB;KAC3B,OAAO,MAAKV;KACZ,WAAW,MAAKI;KACjB;IAED,MAAM,kBAAkB,MAAM,QAAQ,UAAU,OAAO;IACvD,MAAM,sBAAsB,MAAM,QAAQ,cAAc,OAAO;AAE/D,QAAI,mBAAmB,qBAAqB;AAC1C,WAAKM,aAAc;AACnB,WAAKC,SAAU,MAAM,OAAO,OAAO;;;GAIvC,eAAqB;AACnB,UAAKA,UAAW;AAChB,UAAKA,SAAU;;GAGjB,0BAAgC;AAC9B,QAAI,MAAKX,SAAU,MAAKY,eAAiB;AACzC,UAAKA,iBAAkB;AAEvB,yBAAqB;AACnB,WAAKA,iBAAkB;AAGvB,SAAI,MAAKZ,MAAQ;KAEjB,MAAM,QAAQ,KAAK,cAAgC,eAAe;AAClE,SAAI,MACF,OAAKE,SAAU,MAAM;MAEvB;;;AAIN,SAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"popover-element.d.ts","names":[],"sources":["../../../../src/ui/popover/popover-element.ts"],"mappings":";;;;;;cAkBa,cAAA,SAAuB,YAAA;EAAA;kBAClB,OAAA;EAAA,OAEA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAahB,IAAA;EACA,WAAA;EACA,IAAA,iBAAI,WAAA;EACJ,KAAA,EADI,cAAA,CACC,YAAA;EACL,KAAA,EAAO,YAAA;EACP,aAAA;EACA,mBAAA;EACA,WAAA;EACA,KAAA;EACA,UAAA;EAWS,iBAAA,CAAA;EAAA,UAmCU,YAAA,CAAa,OAAA,EAAS,cAAA;EAUhC,oBAAA,CAAA;EAMA,eAAA,CAAA;EAAA,UAMU,UAAA,CAAW,OAAA,EAAS,cAAA;EAAA,UAiBpB,MAAA,CAAO,QAAA,EAAU,cAAA;AAAA"}
1
+ {"version":3,"file":"popover-element.d.ts","names":[],"sources":["../../../../src/ui/popover/popover-element.ts"],"mappings":";;;;;;cAmBa,cAAA,SAAuB,YAAA;EAAA;kBAClB,OAAA;EAAA,OAEA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAahB,IAAA;EACA,WAAA;EACA,IAAA,iBAAI,WAAA;EACJ,KAAA,EADI,cAAA,CACC,YAAA;EACL,KAAA,EAAO,YAAA;EACP,aAAA;EACA,mBAAA;EACA,WAAA;EACA,KAAA;EACA,UAAA;EAeS,iBAAA,CAAA;EAAA,UAmCU,YAAA,CAAa,OAAA,EAAS,cAAA;EAUhC,oBAAA,CAAA;EAOA,eAAA,CAAA;EAAA,UAOU,UAAA,CAAW,OAAA,EAAS,cAAA;EAAA,UAiBpB,MAAA,CAAO,QAAA,EAAU,cAAA;AAAA"}
@@ -1,5 +1,5 @@
1
1
  import { MediaElement } from "../media-element.js";
2
- import { applyElementProps, applyStateDataAttrs, createPopover, createTransition, getAnchorNameStyle, getAnchorPositionStyle, resolveOffsets } from "@videojs/core/dom";
2
+ import { applyElementProps, applyStateDataAttrs, createPopover, createTransition, getAnchorNameStyle, getAnchorPositionStyle, getPopupPositionRect, resolveOffsets } from "@videojs/core/dom";
3
3
  import { SnapshotController } from "@videojs/store/html";
4
4
  import { PopoverCore, PopoverDataAttrs } from "@videojs/core";
5
5
  import { applyStyles, supportsAnchorPositioning, tryHidePopover, tryShowPopover } from "@videojs/utils/dom";
@@ -57,6 +57,10 @@ var PopoverElement = class extends MediaElement {
57
57
  #disconnect = null;
58
58
  #triggerAbort = null;
59
59
  #currentTrigger = null;
60
+ #positionAbort = null;
61
+ #positionFrame = 0;
62
+ #resizeObserver = null;
63
+ #positionTrigger = null;
60
64
  connectedCallback() {
61
65
  super.connectedCallback();
62
66
  if (this.destroyed) return;
@@ -87,10 +91,12 @@ var PopoverElement = class extends MediaElement {
87
91
  }
88
92
  disconnectedCallback() {
89
93
  super.disconnectedCallback();
94
+ this.#cleanupPositioning();
90
95
  this.#disconnect?.abort();
91
96
  this.#disconnect = null;
92
97
  }
93
98
  destroyCallback() {
99
+ this.#cleanupPositioning();
94
100
  this.#cleanupTrigger();
95
101
  this.#popover?.destroy();
96
102
  super.destroyCallback();
@@ -120,7 +126,10 @@ var PopoverElement = class extends MediaElement {
120
126
  applyElementProps(this.#currentTrigger, this.#core.getTriggerAttrs(state, this.id));
121
127
  applyStyles(this.#currentTrigger, getAnchorNameStyle(this.id));
122
128
  }
123
- if (!state.open) return;
129
+ if (!state.open) {
130
+ this.#cleanupPositioning();
131
+ return;
132
+ }
124
133
  const posOpts = {
125
134
  side: state.side,
126
135
  align: state.align
@@ -128,11 +137,12 @@ var PopoverElement = class extends MediaElement {
128
137
  if (supportsAnchorPositioning()) applyStyles(this, getAnchorPositionStyle(this.id, posOpts));
129
138
  else {
130
139
  const triggerRect = this.#currentTrigger?.getBoundingClientRect();
131
- const selfRect = this.getBoundingClientRect();
140
+ const selfRect = getPopupPositionRect(this);
132
141
  const boundaryRect = document.documentElement.getBoundingClientRect();
133
142
  const offsets = resolveOffsets(this);
134
143
  applyStyles(this, getAnchorPositionStyle(this.id, posOpts, triggerRect, selfRect, boundaryRect, offsets));
135
144
  }
145
+ this.#syncPositioning();
136
146
  }
137
147
  #findTrigger() {
138
148
  if (!this.id) return null;
@@ -140,6 +150,7 @@ var PopoverElement = class extends MediaElement {
140
150
  }
141
151
  #syncTrigger(triggerEl) {
142
152
  if (triggerEl === this.#currentTrigger) return;
153
+ this.#cleanupPositioning();
143
154
  this.#cleanupTrigger();
144
155
  this.#currentTrigger = triggerEl;
145
156
  this.#popover?.setTriggerElement(triggerEl);
@@ -161,6 +172,46 @@ var PopoverElement = class extends MediaElement {
161
172
  this.#triggerAbort = null;
162
173
  this.#currentTrigger = null;
163
174
  }
175
+ #syncPositioning() {
176
+ if (supportsAnchorPositioning()) return;
177
+ const triggerEl = this.#currentTrigger;
178
+ if (!triggerEl) return;
179
+ if (this.#positionAbort && this.#positionTrigger === triggerEl) return;
180
+ this.#cleanupPositioning();
181
+ this.#positionAbort = new AbortController();
182
+ this.#positionTrigger = triggerEl;
183
+ const { signal } = this.#positionAbort;
184
+ const reposition = () => {
185
+ cancelAnimationFrame(this.#positionFrame);
186
+ this.#positionFrame = requestAnimationFrame(() => {
187
+ if (signal.aborted) return;
188
+ this.requestUpdate();
189
+ });
190
+ };
191
+ window.addEventListener("scroll", reposition, {
192
+ capture: true,
193
+ passive: true,
194
+ signal
195
+ });
196
+ window.addEventListener("resize", reposition, { signal });
197
+ if (typeof ResizeObserver === "function") {
198
+ this.#resizeObserver = new ResizeObserver(() => {
199
+ reposition();
200
+ });
201
+ this.#resizeObserver.observe(triggerEl);
202
+ this.#resizeObserver.observe(this);
203
+ }
204
+ reposition();
205
+ }
206
+ #cleanupPositioning() {
207
+ this.#positionAbort?.abort();
208
+ this.#positionAbort = null;
209
+ this.#positionTrigger = null;
210
+ cancelAnimationFrame(this.#positionFrame);
211
+ this.#positionFrame = 0;
212
+ this.#resizeObserver?.disconnect();
213
+ this.#resizeObserver = null;
214
+ }
164
215
  };
165
216
 
166
217
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"popover-element.js","names":["#core","#disconnect","#popover","#snapshot","#cleanupTrigger","#findTrigger","#syncTrigger","#currentTrigger","#triggerAbort"],"sources":["../../../../src/ui/popover/popover-element.ts"],"sourcesContent":["import { PopoverCore, PopoverDataAttrs, type PopoverInput, type PopoverProps } from '@videojs/core';\nimport {\n applyElementProps,\n applyStateDataAttrs,\n createPopover,\n createTransition,\n getAnchorNameStyle,\n getAnchorPositionStyle,\n type PopoverApi,\n type PopoverChangeDetails,\n resolveOffsets,\n} from '@videojs/core/dom';\nimport type { PropertyDeclarationMap, PropertyValues } from '@videojs/element';\nimport { SnapshotController } from '@videojs/store/html';\nimport { applyStyles, supportsAnchorPositioning, tryHidePopover, tryShowPopover } from '@videojs/utils/dom';\n\nimport { MediaElement } from '../media-element';\n\nexport class PopoverElement extends MediaElement {\n static readonly tagName = 'media-popover';\n\n static override properties = {\n open: { type: Boolean },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n side: { type: String },\n align: { type: String },\n modal: { type: Boolean },\n closeOnEscape: { type: Boolean, attribute: 'close-on-escape' },\n closeOnOutsideClick: { type: Boolean, attribute: 'close-on-outside-click' },\n openOnHover: { type: Boolean, attribute: 'open-on-hover' },\n delay: { type: Number },\n closeDelay: { type: Number, attribute: 'close-delay' },\n } satisfies PropertyDeclarationMap<keyof PopoverCore.Props>;\n\n open = PopoverCore.defaultProps.open;\n defaultOpen = PopoverCore.defaultProps.defaultOpen;\n side = PopoverCore.defaultProps.side;\n align = PopoverCore.defaultProps.align;\n modal: PopoverProps['modal'] = PopoverCore.defaultProps.modal;\n closeOnEscape = PopoverCore.defaultProps.closeOnEscape;\n closeOnOutsideClick = PopoverCore.defaultProps.closeOnOutsideClick;\n openOnHover = PopoverCore.defaultProps.openOnHover;\n delay = PopoverCore.defaultProps.delay;\n closeDelay = PopoverCore.defaultProps.closeDelay;\n\n readonly #core = new PopoverCore();\n #popover: PopoverApi | null = null;\n #snapshot: SnapshotController<PopoverInput> | null = null;\n\n // Cleanup controllers\n #disconnect: AbortController | null = null;\n #triggerAbort: AbortController | null = null;\n #currentTrigger: HTMLElement | null = null;\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (this.destroyed) return;\n\n this.#disconnect = new AbortController();\n\n this.#popover = createPopover({\n transition: createTransition(),\n onOpenChange: (nextOpen: boolean, details: PopoverChangeDetails) => {\n this.open = nextOpen;\n this.dispatchEvent(new CustomEvent('open-change', { detail: { open: nextOpen, ...details } }));\n },\n closeOnEscape: () => this.closeOnEscape,\n closeOnOutsideClick: () => this.closeOnOutsideClick,\n openOnHover: () => this.openOnHover,\n delay: () => this.delay,\n closeDelay: () => this.closeDelay,\n });\n\n // Register self as the popup element — the element IS the popup.\n this.#popover.setPopupElement(this);\n\n // Apply popup event handlers (pointerenter/leave, focusout) to self.\n applyElementProps(this, this.#popover.popupProps, { signal: this.#disconnect.signal });\n\n // Subscribe to interaction state for reactive updates.\n // Reuse the controller across connect/disconnect cycles to avoid\n // leaking stale controllers in the host's controller set.\n if (this.#snapshot) {\n this.#snapshot.track(this.#popover.input);\n } else {\n this.#snapshot = new SnapshotController(this, this.#popover.input);\n }\n }\n\n protected override firstUpdated(changed: PropertyValues): void {\n super.firstUpdated(changed);\n\n // Uncontrolled mode: open if `defaultOpen` is set. Controlled `open`\n // is already synced by `willUpdate` on the first render cycle.\n if (this.defaultOpen && !this.open) {\n this.#popover?.open();\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#disconnect?.abort();\n this.#disconnect = null;\n }\n\n override destroyCallback(): void {\n this.#cleanupTrigger();\n this.#popover?.destroy();\n super.destroyCallback();\n }\n\n protected override willUpdate(changed: PropertyValues): void {\n super.willUpdate(changed);\n this.#core.setProps(this);\n\n // Sync controlled open state\n if (this.#popover && changed.has('open')) {\n const { active: interactionOpen } = this.#popover.input.current;\n if (this.open !== interactionOpen) {\n if (this.open) {\n this.#popover.open();\n } else {\n this.#popover.close();\n }\n }\n }\n }\n\n protected override update(_changed: PropertyValues): void {\n super.update(_changed);\n if (!this.#popover) return;\n\n // Discover trigger via commandfor linkage.\n const triggerEl = this.#findTrigger();\n this.#syncTrigger(triggerEl);\n\n // Derive state from core + input.\n const input = this.#popover.input.current;\n this.#core.setInput(input);\n const state = this.#core.getState();\n\n // Apply popup ARIA and data attributes to self.\n applyElementProps(this, this.#core.getPopupAttrs(state));\n applyStateDataAttrs(this, state, PopoverDataAttrs);\n\n // Show/hide via Popover API AFTER data attributes are applied so\n // `data-starting-style` is present before the first visible frame.\n if (state.open) {\n tryShowPopover(this);\n } else {\n tryHidePopover(this);\n }\n\n // Apply trigger ARIA and anchor-name to the discovered trigger.\n if (this.#currentTrigger) {\n applyElementProps(this.#currentTrigger, this.#core.getTriggerAttrs(state, this.id));\n applyStyles(this.#currentTrigger, getAnchorNameStyle(this.id));\n }\n\n // Skip positioning when closed — no rects to measure.\n if (!state.open) return;\n\n // Apply positioning styles to self.\n const posOpts = { side: state.side, align: state.align };\n\n if (supportsAnchorPositioning()) {\n // Native CSS Anchor Positioning — no JS rect measurements needed.\n applyStyles(this, getAnchorPositionStyle(this.id, posOpts));\n } else {\n // JS fallback: measure rects and resolve CSS var offsets.\n const triggerRect = this.#currentTrigger?.getBoundingClientRect();\n const selfRect = this.getBoundingClientRect();\n const boundaryRect = document.documentElement.getBoundingClientRect();\n const offsets = resolveOffsets(this);\n applyStyles(this, getAnchorPositionStyle(this.id, posOpts, triggerRect, selfRect, boundaryRect, offsets));\n }\n }\n\n // --- Trigger discovery ---\n\n #findTrigger(): HTMLElement | null {\n if (!this.id) return null;\n const root = this.getRootNode() as Document | ShadowRoot;\n return root.querySelector<HTMLElement>(`[commandfor=\"${this.id}\"]`);\n }\n\n #syncTrigger(triggerEl: HTMLElement | null): void {\n if (triggerEl === this.#currentTrigger) return;\n\n this.#cleanupTrigger();\n this.#currentTrigger = triggerEl;\n this.#popover?.setTriggerElement(triggerEl);\n\n if (triggerEl && this.#popover) {\n this.#triggerAbort = new AbortController();\n applyElementProps(triggerEl, this.#popover.triggerProps, { signal: this.#triggerAbort.signal });\n }\n }\n\n #cleanupTrigger(): void {\n if (this.#currentTrigger) {\n // Remove ARIA attributes and anchor-name style from the old trigger.\n applyElementProps(this.#currentTrigger, {\n 'aria-expanded': undefined,\n 'aria-haspopup': undefined,\n 'aria-controls': undefined,\n });\n this.#currentTrigger.style.removeProperty('anchor-name');\n }\n\n this.#triggerAbort?.abort();\n this.#triggerAbort = null;\n this.#currentTrigger = null;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"popover-element.js","names":["#core","#disconnect","#popover","#snapshot","#cleanupPositioning","#cleanupTrigger","#findTrigger","#syncTrigger","#currentTrigger","#syncPositioning","#triggerAbort","#positionAbort","#positionTrigger","#positionFrame","#resizeObserver"],"sources":["../../../../src/ui/popover/popover-element.ts"],"sourcesContent":["import { PopoverCore, PopoverDataAttrs, type PopoverInput, type PopoverProps } from '@videojs/core';\nimport {\n applyElementProps,\n applyStateDataAttrs,\n createPopover,\n createTransition,\n getAnchorNameStyle,\n getAnchorPositionStyle,\n getPopupPositionRect,\n type PopoverApi,\n type PopoverChangeDetails,\n resolveOffsets,\n} from '@videojs/core/dom';\nimport type { PropertyDeclarationMap, PropertyValues } from '@videojs/element';\nimport { SnapshotController } from '@videojs/store/html';\nimport { applyStyles, supportsAnchorPositioning, tryHidePopover, tryShowPopover } from '@videojs/utils/dom';\n\nimport { MediaElement } from '../media-element';\n\nexport class PopoverElement extends MediaElement {\n static readonly tagName = 'media-popover';\n\n static override properties = {\n open: { type: Boolean },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n side: { type: String },\n align: { type: String },\n modal: { type: Boolean },\n closeOnEscape: { type: Boolean, attribute: 'close-on-escape' },\n closeOnOutsideClick: { type: Boolean, attribute: 'close-on-outside-click' },\n openOnHover: { type: Boolean, attribute: 'open-on-hover' },\n delay: { type: Number },\n closeDelay: { type: Number, attribute: 'close-delay' },\n } satisfies PropertyDeclarationMap<keyof PopoverCore.Props>;\n\n open = PopoverCore.defaultProps.open;\n defaultOpen = PopoverCore.defaultProps.defaultOpen;\n side = PopoverCore.defaultProps.side;\n align = PopoverCore.defaultProps.align;\n modal: PopoverProps['modal'] = PopoverCore.defaultProps.modal;\n closeOnEscape = PopoverCore.defaultProps.closeOnEscape;\n closeOnOutsideClick = PopoverCore.defaultProps.closeOnOutsideClick;\n openOnHover = PopoverCore.defaultProps.openOnHover;\n delay = PopoverCore.defaultProps.delay;\n closeDelay = PopoverCore.defaultProps.closeDelay;\n\n readonly #core = new PopoverCore();\n #popover: PopoverApi | null = null;\n #snapshot: SnapshotController<PopoverInput> | null = null;\n\n // Cleanup controllers\n #disconnect: AbortController | null = null;\n #triggerAbort: AbortController | null = null;\n #currentTrigger: HTMLElement | null = null;\n #positionAbort: AbortController | null = null;\n #positionFrame = 0;\n #resizeObserver: ResizeObserver | null = null;\n #positionTrigger: HTMLElement | null = null;\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (this.destroyed) return;\n\n this.#disconnect = new AbortController();\n\n this.#popover = createPopover({\n transition: createTransition(),\n onOpenChange: (nextOpen: boolean, details: PopoverChangeDetails) => {\n this.open = nextOpen;\n this.dispatchEvent(new CustomEvent('open-change', { detail: { open: nextOpen, ...details } }));\n },\n closeOnEscape: () => this.closeOnEscape,\n closeOnOutsideClick: () => this.closeOnOutsideClick,\n openOnHover: () => this.openOnHover,\n delay: () => this.delay,\n closeDelay: () => this.closeDelay,\n });\n\n // Register self as the popup element — the element IS the popup.\n this.#popover.setPopupElement(this);\n\n // Apply popup event handlers (pointerenter/leave, focusout) to self.\n applyElementProps(this, this.#popover.popupProps, { signal: this.#disconnect.signal });\n\n // Subscribe to interaction state for reactive updates.\n // Reuse the controller across connect/disconnect cycles to avoid\n // leaking stale controllers in the host's controller set.\n if (this.#snapshot) {\n this.#snapshot.track(this.#popover.input);\n } else {\n this.#snapshot = new SnapshotController(this, this.#popover.input);\n }\n }\n\n protected override firstUpdated(changed: PropertyValues): void {\n super.firstUpdated(changed);\n\n // Uncontrolled mode: open if `defaultOpen` is set. Controlled `open`\n // is already synced by `willUpdate` on the first render cycle.\n if (this.defaultOpen && !this.open) {\n this.#popover?.open();\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#cleanupPositioning();\n this.#disconnect?.abort();\n this.#disconnect = null;\n }\n\n override destroyCallback(): void {\n this.#cleanupPositioning();\n this.#cleanupTrigger();\n this.#popover?.destroy();\n super.destroyCallback();\n }\n\n protected override willUpdate(changed: PropertyValues): void {\n super.willUpdate(changed);\n this.#core.setProps(this);\n\n // Sync controlled open state\n if (this.#popover && changed.has('open')) {\n const { active: interactionOpen } = this.#popover.input.current;\n if (this.open !== interactionOpen) {\n if (this.open) {\n this.#popover.open();\n } else {\n this.#popover.close();\n }\n }\n }\n }\n\n protected override update(_changed: PropertyValues): void {\n super.update(_changed);\n if (!this.#popover) return;\n\n // Discover trigger via commandfor linkage.\n const triggerEl = this.#findTrigger();\n this.#syncTrigger(triggerEl);\n\n // Derive state from core + input.\n const input = this.#popover.input.current;\n this.#core.setInput(input);\n const state = this.#core.getState();\n\n // Apply popup ARIA and data attributes to self.\n applyElementProps(this, this.#core.getPopupAttrs(state));\n applyStateDataAttrs(this, state, PopoverDataAttrs);\n\n // Show/hide via Popover API AFTER data attributes are applied so\n // `data-starting-style` is present before the first visible frame.\n if (state.open) {\n tryShowPopover(this);\n } else {\n tryHidePopover(this);\n }\n\n // Apply trigger ARIA and anchor-name to the discovered trigger.\n if (this.#currentTrigger) {\n applyElementProps(this.#currentTrigger, this.#core.getTriggerAttrs(state, this.id));\n applyStyles(this.#currentTrigger, getAnchorNameStyle(this.id));\n }\n\n // Skip positioning when closed — no rects to measure.\n if (!state.open) {\n this.#cleanupPositioning();\n return;\n }\n\n // Apply positioning styles to self.\n const posOpts = { side: state.side, align: state.align };\n\n if (supportsAnchorPositioning()) {\n // Native CSS Anchor Positioning — no JS rect measurements needed.\n applyStyles(this, getAnchorPositionStyle(this.id, posOpts));\n } else {\n // JS fallback: measure rects and resolve CSS var offsets.\n const triggerRect = this.#currentTrigger?.getBoundingClientRect();\n const selfRect = getPopupPositionRect(this);\n const boundaryRect = document.documentElement.getBoundingClientRect();\n const offsets = resolveOffsets(this);\n applyStyles(this, getAnchorPositionStyle(this.id, posOpts, triggerRect, selfRect, boundaryRect, offsets));\n }\n\n this.#syncPositioning();\n }\n\n // --- Trigger discovery ---\n\n #findTrigger(): HTMLElement | null {\n if (!this.id) return null;\n const root = this.getRootNode() as Document | ShadowRoot;\n return root.querySelector<HTMLElement>(`[commandfor=\"${this.id}\"]`);\n }\n\n #syncTrigger(triggerEl: HTMLElement | null): void {\n if (triggerEl === this.#currentTrigger) return;\n\n this.#cleanupPositioning();\n this.#cleanupTrigger();\n this.#currentTrigger = triggerEl;\n this.#popover?.setTriggerElement(triggerEl);\n\n if (triggerEl && this.#popover) {\n this.#triggerAbort = new AbortController();\n applyElementProps(triggerEl, this.#popover.triggerProps, { signal: this.#triggerAbort.signal });\n }\n }\n\n #cleanupTrigger(): void {\n if (this.#currentTrigger) {\n // Remove ARIA attributes and anchor-name style from the old trigger.\n applyElementProps(this.#currentTrigger, {\n 'aria-expanded': undefined,\n 'aria-haspopup': undefined,\n 'aria-controls': undefined,\n });\n this.#currentTrigger.style.removeProperty('anchor-name');\n }\n\n this.#triggerAbort?.abort();\n this.#triggerAbort = null;\n this.#currentTrigger = null;\n }\n\n #syncPositioning(): void {\n if (supportsAnchorPositioning()) return;\n\n const triggerEl = this.#currentTrigger;\n\n if (!triggerEl) return;\n if (this.#positionAbort && this.#positionTrigger === triggerEl) return;\n\n this.#cleanupPositioning();\n this.#positionAbort = new AbortController();\n this.#positionTrigger = triggerEl;\n const { signal } = this.#positionAbort;\n\n const reposition = () => {\n cancelAnimationFrame(this.#positionFrame);\n this.#positionFrame = requestAnimationFrame(() => {\n if (signal.aborted) return;\n this.requestUpdate();\n });\n };\n\n window.addEventListener('scroll', reposition, { capture: true, passive: true, signal });\n window.addEventListener('resize', reposition, { signal });\n\n if (typeof ResizeObserver === 'function') {\n this.#resizeObserver = new ResizeObserver(() => {\n reposition();\n });\n this.#resizeObserver.observe(triggerEl);\n this.#resizeObserver.observe(this);\n }\n\n reposition();\n }\n\n #cleanupPositioning(): void {\n this.#positionAbort?.abort();\n this.#positionAbort = null;\n this.#positionTrigger = null;\n cancelAnimationFrame(this.#positionFrame);\n this.#positionFrame = 0;\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = null;\n }\n}\n"],"mappings":";;;;;;;AAmBA,IAAa,iBAAb,cAAoC,aAAa;;;cAgBxC,YAAY,aAAa;qBAClB,YAAY,aAAa;cAChC,YAAY,aAAa;eACxB,YAAY,aAAa;eACF,YAAY,aAAa;uBACxC,YAAY,aAAa;6BACnB,YAAY,aAAa;qBACjC,YAAY,aAAa;eAC/B,YAAY,aAAa;oBACpB,YAAY,aAAa;;;iBAxBZ;;;oBAEG;GAC3B,MAAM,EAAE,MAAM,SAAS;GACvB,aAAa;IAAE,MAAM;IAAS,WAAW;IAAgB;GACzD,MAAM,EAAE,MAAM,QAAQ;GACtB,OAAO,EAAE,MAAM,QAAQ;GACvB,OAAO,EAAE,MAAM,SAAS;GACxB,eAAe;IAAE,MAAM;IAAS,WAAW;IAAmB;GAC9D,qBAAqB;IAAE,MAAM;IAAS,WAAW;IAA0B;GAC3E,aAAa;IAAE,MAAM;IAAS,WAAW;IAAiB;GAC1D,OAAO,EAAE,MAAM,QAAQ;GACvB,YAAY;IAAE,MAAM;IAAQ,WAAW;IAAe;GACvD;;CAaD,CAASA,OAAQ,IAAI,aAAa;CAClC,WAA8B;CAC9B,YAAqD;CAGrD,cAAsC;CACtC,gBAAwC;CACxC,kBAAsC;CACtC,iBAAyC;CACzC,iBAAiB;CACjB,kBAAyC;CACzC,mBAAuC;CAEvC,AAAS,oBAA0B;AACjC,QAAM,mBAAmB;AACzB,MAAI,KAAK,UAAW;AAEpB,QAAKC,aAAc,IAAI,iBAAiB;AAExC,QAAKC,UAAW,cAAc;GAC5B,YAAY,kBAAkB;GAC9B,eAAe,UAAmB,YAAkC;AAClE,SAAK,OAAO;AACZ,SAAK,cAAc,IAAI,YAAY,eAAe,EAAE,QAAQ;KAAE,MAAM;KAAU,GAAG;KAAS,EAAE,CAAC,CAAC;;GAEhG,qBAAqB,KAAK;GAC1B,2BAA2B,KAAK;GAChC,mBAAmB,KAAK;GACxB,aAAa,KAAK;GAClB,kBAAkB,KAAK;GACxB,CAAC;AAGF,QAAKA,QAAS,gBAAgB,KAAK;AAGnC,oBAAkB,MAAM,MAAKA,QAAS,YAAY,EAAE,QAAQ,MAAKD,WAAY,QAAQ,CAAC;AAKtF,MAAI,MAAKE,SACP,OAAKA,SAAU,MAAM,MAAKD,QAAS,MAAM;MAEzC,OAAKC,WAAY,IAAI,mBAAmB,MAAM,MAAKD,QAAS,MAAM;;CAItE,AAAmB,aAAa,SAA+B;AAC7D,QAAM,aAAa,QAAQ;AAI3B,MAAI,KAAK,eAAe,CAAC,KAAK,KAC5B,OAAKA,SAAU,MAAM;;CAIzB,AAAS,uBAA6B;AACpC,QAAM,sBAAsB;AAC5B,QAAKE,oBAAqB;AAC1B,QAAKH,YAAa,OAAO;AACzB,QAAKA,aAAc;;CAGrB,AAAS,kBAAwB;AAC/B,QAAKG,oBAAqB;AAC1B,QAAKC,gBAAiB;AACtB,QAAKH,SAAU,SAAS;AACxB,QAAM,iBAAiB;;CAGzB,AAAmB,WAAW,SAA+B;AAC3D,QAAM,WAAW,QAAQ;AACzB,QAAKF,KAAM,SAAS,KAAK;AAGzB,MAAI,MAAKE,WAAY,QAAQ,IAAI,OAAO,EAAE;GACxC,MAAM,EAAE,QAAQ,oBAAoB,MAAKA,QAAS,MAAM;AACxD,OAAI,KAAK,SAAS,gBAChB,KAAI,KAAK,KACP,OAAKA,QAAS,MAAM;OAEpB,OAAKA,QAAS,OAAO;;;CAM7B,AAAmB,OAAO,UAAgC;AACxD,QAAM,OAAO,SAAS;AACtB,MAAI,CAAC,MAAKA,QAAU;EAGpB,MAAM,YAAY,MAAKI,aAAc;AACrC,QAAKC,YAAa,UAAU;EAG5B,MAAM,QAAQ,MAAKL,QAAS,MAAM;AAClC,QAAKF,KAAM,SAAS,MAAM;EAC1B,MAAM,QAAQ,MAAKA,KAAM,UAAU;AAGnC,oBAAkB,MAAM,MAAKA,KAAM,cAAc,MAAM,CAAC;AACxD,sBAAoB,MAAM,OAAO,iBAAiB;AAIlD,MAAI,MAAM,KACR,gBAAe,KAAK;MAEpB,gBAAe,KAAK;AAItB,MAAI,MAAKQ,gBAAiB;AACxB,qBAAkB,MAAKA,gBAAiB,MAAKR,KAAM,gBAAgB,OAAO,KAAK,GAAG,CAAC;AACnF,eAAY,MAAKQ,gBAAiB,mBAAmB,KAAK,GAAG,CAAC;;AAIhE,MAAI,CAAC,MAAM,MAAM;AACf,SAAKJ,oBAAqB;AAC1B;;EAIF,MAAM,UAAU;GAAE,MAAM,MAAM;GAAM,OAAO,MAAM;GAAO;AAExD,MAAI,2BAA2B,CAE7B,aAAY,MAAM,uBAAuB,KAAK,IAAI,QAAQ,CAAC;OACtD;GAEL,MAAM,cAAc,MAAKI,gBAAiB,uBAAuB;GACjE,MAAM,WAAW,qBAAqB,KAAK;GAC3C,MAAM,eAAe,SAAS,gBAAgB,uBAAuB;GACrE,MAAM,UAAU,eAAe,KAAK;AACpC,eAAY,MAAM,uBAAuB,KAAK,IAAI,SAAS,aAAa,UAAU,cAAc,QAAQ,CAAC;;AAG3G,QAAKC,iBAAkB;;CAKzB,eAAmC;AACjC,MAAI,CAAC,KAAK,GAAI,QAAO;AAErB,SADa,KAAK,aAAa,CACnB,cAA2B,gBAAgB,KAAK,GAAG,IAAI;;CAGrE,aAAa,WAAqC;AAChD,MAAI,cAAc,MAAKD,eAAiB;AAExC,QAAKJ,oBAAqB;AAC1B,QAAKC,gBAAiB;AACtB,QAAKG,iBAAkB;AACvB,QAAKN,SAAU,kBAAkB,UAAU;AAE3C,MAAI,aAAa,MAAKA,SAAU;AAC9B,SAAKQ,eAAgB,IAAI,iBAAiB;AAC1C,qBAAkB,WAAW,MAAKR,QAAS,cAAc,EAAE,QAAQ,MAAKQ,aAAc,QAAQ,CAAC;;;CAInG,kBAAwB;AACtB,MAAI,MAAKF,gBAAiB;AAExB,qBAAkB,MAAKA,gBAAiB;IACtC,iBAAiB;IACjB,iBAAiB;IACjB,iBAAiB;IAClB,CAAC;AACF,SAAKA,eAAgB,MAAM,eAAe,cAAc;;AAG1D,QAAKE,cAAe,OAAO;AAC3B,QAAKA,eAAgB;AACrB,QAAKF,iBAAkB;;CAGzB,mBAAyB;AACvB,MAAI,2BAA2B,CAAE;EAEjC,MAAM,YAAY,MAAKA;AAEvB,MAAI,CAAC,UAAW;AAChB,MAAI,MAAKG,iBAAkB,MAAKC,oBAAqB,UAAW;AAEhE,QAAKR,oBAAqB;AAC1B,QAAKO,gBAAiB,IAAI,iBAAiB;AAC3C,QAAKC,kBAAmB;EACxB,MAAM,EAAE,WAAW,MAAKD;EAExB,MAAM,mBAAmB;AACvB,wBAAqB,MAAKE,cAAe;AACzC,SAAKA,gBAAiB,4BAA4B;AAChD,QAAI,OAAO,QAAS;AACpB,SAAK,eAAe;KACpB;;AAGJ,SAAO,iBAAiB,UAAU,YAAY;GAAE,SAAS;GAAM,SAAS;GAAM;GAAQ,CAAC;AACvF,SAAO,iBAAiB,UAAU,YAAY,EAAE,QAAQ,CAAC;AAEzD,MAAI,OAAO,mBAAmB,YAAY;AACxC,SAAKC,iBAAkB,IAAI,qBAAqB;AAC9C,gBAAY;KACZ;AACF,SAAKA,eAAgB,QAAQ,UAAU;AACvC,SAAKA,eAAgB,QAAQ,KAAK;;AAGpC,cAAY;;CAGd,sBAA4B;AAC1B,QAAKH,eAAgB,OAAO;AAC5B,QAAKA,gBAAiB;AACtB,QAAKC,kBAAmB;AACxB,uBAAqB,MAAKC,cAAe;AACzC,QAAKA,gBAAiB;AACtB,QAAKC,gBAAiB,YAAY;AAClC,QAAKA,iBAAkB"}
@@ -69,7 +69,7 @@ var TimeSliderElement = class extends MediaElement {
69
69
  getLargeStepPercent: () => this.#core.getLargeStepPercent(),
70
70
  onValueCommit: (percent) => {
71
71
  const media = this.#timeState.value;
72
- if (media) media.seek(this.#core.valueFromPercent(percent));
72
+ if (media) media.seek(this.#core.rawValueFromPercent(percent));
73
73
  },
74
74
  commitThrottle: this.commitThrottle,
75
75
  onDragStart: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"time-slider-element.js","names":["#core","#provider","#timeState","#bufferState","#disconnect","#slider"],"sources":["../../../../src/ui/time-slider/time-slider-element.ts"],"sourcesContent":["import { TimeSliderCore, TimeSliderDataAttrs } from '@videojs/core';\nimport {\n applyElementProps,\n applyStateDataAttrs,\n createSlider,\n getTimeSliderCSSVars,\n logMissingFeature,\n type SliderApi,\n selectBuffer,\n selectTime,\n} from '@videojs/core/dom';\nimport type { PropertyDeclarationMap, PropertyValues } from '@videojs/element';\nimport { ContextProvider } from '@videojs/element/context';\nimport { applyStyles, isRTL } from '@videojs/utils/dom';\nimport { formatTime } from '@videojs/utils/time';\n\nimport { playerContext } from '../../player/context';\nimport { PlayerController } from '../../player/player-controller';\nimport { MediaElement } from '../media-element';\nimport { sliderContext } from '../slider/context';\n\nexport class TimeSliderElement extends MediaElement {\n static readonly tagName = 'media-time-slider';\n\n static override properties = {\n label: { type: String },\n commitThrottle: { type: Number, attribute: 'commit-throttle' },\n step: { type: Number },\n largeStep: { type: Number, attribute: 'large-step' },\n orientation: { type: String },\n disabled: { type: Boolean },\n thumbAlignment: { type: String, attribute: 'thumb-alignment' },\n } satisfies PropertyDeclarationMap<Exclude<keyof TimeSliderCore.Props, 'value' | 'min' | 'max'>>;\n\n label = TimeSliderCore.defaultProps.label;\n commitThrottle = TimeSliderCore.defaultProps.commitThrottle;\n step = TimeSliderCore.defaultProps.step;\n largeStep = TimeSliderCore.defaultProps.largeStep;\n orientation = TimeSliderCore.defaultProps.orientation;\n disabled = TimeSliderCore.defaultProps.disabled;\n thumbAlignment = TimeSliderCore.defaultProps.thumbAlignment;\n\n readonly #core = new TimeSliderCore();\n readonly #provider = new ContextProvider(this, { context: sliderContext });\n readonly #timeState = new PlayerController(this, playerContext, selectTime);\n readonly #bufferState = new PlayerController(this, playerContext, selectBuffer);\n\n #slider: SliderApi | null = null;\n #disconnect: AbortController | null = null;\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (this.destroyed) return;\n\n this.#disconnect = new AbortController();\n const signal = this.#disconnect.signal;\n\n this.#slider = createSlider({\n getElement: () => this,\n getThumbElement: () => this.querySelector<HTMLElement>('media-slider-thumb'),\n getOrientation: () => this.orientation,\n isRTL: () => isRTL(this),\n isDisabled: () => this.disabled || !this.#timeState.value,\n getPercent: () => {\n const media = this.#timeState.value;\n if (!media) return 0;\n return this.#core.percentFromValue(media.currentTime);\n },\n getStepPercent: () => this.#core.getStepPercent(),\n getLargeStepPercent: () => this.#core.getLargeStepPercent(),\n onValueCommit: (percent) => {\n const media = this.#timeState.value;\n if (media) media.seek(this.#core.valueFromPercent(percent));\n },\n commitThrottle: this.commitThrottle,\n onDragStart: () => {\n this.dispatchEvent(new CustomEvent('drag-start', { bubbles: true }));\n },\n onDragEnd: () => {\n this.dispatchEvent(new CustomEvent('drag-end', { bubbles: true }));\n },\n adjustPercent: (raw, thumbSize, trackSize) => this.#core.adjustPercentForAlignment(raw, thumbSize, trackSize),\n onResize: () => this.requestUpdate(),\n });\n\n applyElementProps(this, this.#slider.rootProps, { signal });\n applyStyles(this, this.#slider.rootStyle);\n this.#slider.input.subscribe(() => this.requestUpdate(), { signal });\n\n if (__DEV__ && !this.#timeState.value) {\n logMissingFeature(this.localName, this.#timeState.displayName!);\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#disconnect?.abort();\n this.#disconnect = null;\n }\n\n override destroyCallback(): void {\n this.#slider?.destroy();\n super.destroyCallback();\n }\n\n protected override willUpdate(_changed: PropertyValues): void {\n super.willUpdate(_changed);\n this.#core.setProps(this);\n }\n\n protected override update(_changed: PropertyValues): void {\n super.update(_changed);\n if (!this.#slider) return;\n\n const time = this.#timeState.value;\n const buffer = this.#bufferState.value;\n if (!time) return;\n\n this.#core.setInput(this.#slider.input.current);\n const media = { ...time, ...(buffer ?? { buffered: [], seekable: [] }) };\n this.#core.setMedia(media);\n const state = this.#core.getState();\n\n const cssVars = getTimeSliderCSSVars(this.#slider.adjustForAlignment(state));\n\n applyStyles(this, cssVars);\n\n // Domain-specific data attributes on root (includes data-seeking).\n applyStateDataAttrs(this, state, TimeSliderDataAttrs);\n\n // Provide context to child elements with base slider data attrs.\n this.#provider.setValue({\n state,\n stateAttrMap: TimeSliderDataAttrs,\n pointerValue: this.#core.valueFromPercent(state.pointerPercent),\n thumbAttrs: this.#core.getAttrs(state),\n thumbProps: this.#slider.thumbProps,\n formatValue: (value) => formatTime(value, state.duration),\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"time-slider-element.js","names":["#core","#provider","#timeState","#bufferState","#disconnect","#slider"],"sources":["../../../../src/ui/time-slider/time-slider-element.ts"],"sourcesContent":["import { TimeSliderCore, TimeSliderDataAttrs } from '@videojs/core';\nimport {\n applyElementProps,\n applyStateDataAttrs,\n createSlider,\n getTimeSliderCSSVars,\n logMissingFeature,\n type SliderApi,\n selectBuffer,\n selectTime,\n} from '@videojs/core/dom';\nimport type { PropertyDeclarationMap, PropertyValues } from '@videojs/element';\nimport { ContextProvider } from '@videojs/element/context';\nimport { applyStyles, isRTL } from '@videojs/utils/dom';\nimport { formatTime } from '@videojs/utils/time';\n\nimport { playerContext } from '../../player/context';\nimport { PlayerController } from '../../player/player-controller';\nimport { MediaElement } from '../media-element';\nimport { sliderContext } from '../slider/context';\n\nexport class TimeSliderElement extends MediaElement {\n static readonly tagName = 'media-time-slider';\n\n static override properties = {\n label: { type: String },\n commitThrottle: { type: Number, attribute: 'commit-throttle' },\n step: { type: Number },\n largeStep: { type: Number, attribute: 'large-step' },\n orientation: { type: String },\n disabled: { type: Boolean },\n thumbAlignment: { type: String, attribute: 'thumb-alignment' },\n } satisfies PropertyDeclarationMap<Exclude<keyof TimeSliderCore.Props, 'value' | 'min' | 'max'>>;\n\n label = TimeSliderCore.defaultProps.label;\n commitThrottle = TimeSliderCore.defaultProps.commitThrottle;\n step = TimeSliderCore.defaultProps.step;\n largeStep = TimeSliderCore.defaultProps.largeStep;\n orientation = TimeSliderCore.defaultProps.orientation;\n disabled = TimeSliderCore.defaultProps.disabled;\n thumbAlignment = TimeSliderCore.defaultProps.thumbAlignment;\n\n readonly #core = new TimeSliderCore();\n readonly #provider = new ContextProvider(this, { context: sliderContext });\n readonly #timeState = new PlayerController(this, playerContext, selectTime);\n readonly #bufferState = new PlayerController(this, playerContext, selectBuffer);\n\n #slider: SliderApi | null = null;\n #disconnect: AbortController | null = null;\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (this.destroyed) return;\n\n this.#disconnect = new AbortController();\n const signal = this.#disconnect.signal;\n\n this.#slider = createSlider({\n getElement: () => this,\n getThumbElement: () => this.querySelector<HTMLElement>('media-slider-thumb'),\n getOrientation: () => this.orientation,\n isRTL: () => isRTL(this),\n isDisabled: () => this.disabled || !this.#timeState.value,\n getPercent: () => {\n const media = this.#timeState.value;\n if (!media) return 0;\n return this.#core.percentFromValue(media.currentTime);\n },\n getStepPercent: () => this.#core.getStepPercent(),\n getLargeStepPercent: () => this.#core.getLargeStepPercent(),\n onValueCommit: (percent) => {\n const media = this.#timeState.value;\n if (media) media.seek(this.#core.rawValueFromPercent(percent));\n },\n commitThrottle: this.commitThrottle,\n onDragStart: () => {\n this.dispatchEvent(new CustomEvent('drag-start', { bubbles: true }));\n },\n onDragEnd: () => {\n this.dispatchEvent(new CustomEvent('drag-end', { bubbles: true }));\n },\n adjustPercent: (raw, thumbSize, trackSize) => this.#core.adjustPercentForAlignment(raw, thumbSize, trackSize),\n onResize: () => this.requestUpdate(),\n });\n\n applyElementProps(this, this.#slider.rootProps, { signal });\n applyStyles(this, this.#slider.rootStyle);\n this.#slider.input.subscribe(() => this.requestUpdate(), { signal });\n\n if (__DEV__ && !this.#timeState.value) {\n logMissingFeature(this.localName, this.#timeState.displayName!);\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#disconnect?.abort();\n this.#disconnect = null;\n }\n\n override destroyCallback(): void {\n this.#slider?.destroy();\n super.destroyCallback();\n }\n\n protected override willUpdate(_changed: PropertyValues): void {\n super.willUpdate(_changed);\n this.#core.setProps(this);\n }\n\n protected override update(_changed: PropertyValues): void {\n super.update(_changed);\n if (!this.#slider) return;\n\n const time = this.#timeState.value;\n const buffer = this.#bufferState.value;\n if (!time) return;\n\n this.#core.setInput(this.#slider.input.current);\n const media = { ...time, ...(buffer ?? { buffered: [], seekable: [] }) };\n this.#core.setMedia(media);\n const state = this.#core.getState();\n\n const cssVars = getTimeSliderCSSVars(this.#slider.adjustForAlignment(state));\n\n applyStyles(this, cssVars);\n\n // Domain-specific data attributes on root (includes data-seeking).\n applyStateDataAttrs(this, state, TimeSliderDataAttrs);\n\n // Provide context to child elements with base slider data attrs.\n this.#provider.setValue({\n state,\n stateAttrMap: TimeSliderDataAttrs,\n pointerValue: this.#core.valueFromPercent(state.pointerPercent),\n thumbAttrs: this.#core.getAttrs(state),\n thumbProps: this.#slider.thumbProps,\n formatValue: (value) => formatTime(value, state.duration),\n });\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip-element.d.ts","names":[],"sources":["../../../../src/ui/tooltip/tooltip-element.ts"],"mappings":";;;;;cAoBa,cAAA,SAAuB,YAAA;EAAA;kBAClB,OAAA;EAAA,OAEA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWhB,IAAA;EACA,WAAA;EACA,IAAA,iBAAI,WAAA;EACJ,KAAA,EADI,cAAA,CACC,YAAA;EACL,KAAA;EACA,UAAA;EACA,qBAAA;EACA,QAAA;EAYS,iBAAA,CAAA;EAAA,UAgCU,YAAA,CAAa,OAAA,EAAS,cAAA;EAUhC,oBAAA,CAAA;EAAA,UASU,UAAA,CAAW,OAAA,EAAS,cAAA;EAAA,UAiBpB,MAAA,CAAO,QAAA,EAAU,cAAA;AAAA"}
1
+ {"version":3,"file":"tooltip-element.d.ts","names":[],"sources":["../../../../src/ui/tooltip/tooltip-element.ts"],"mappings":";;;;;cAqBa,cAAA,SAAuB,YAAA;EAAA;kBAClB,OAAA;EAAA,OAEA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWhB,IAAA;EACA,WAAA;EACA,IAAA,iBAAI,WAAA;EACJ,KAAA,EADI,cAAA,CACC,YAAA;EACL,KAAA;EACA,UAAA;EACA,qBAAA;EACA,QAAA;EAgBS,iBAAA,CAAA;EAAA,UAgCU,YAAA,CAAa,OAAA,EAAS,cAAA;EAUhC,oBAAA,CAAA;EAAA,UAUU,UAAA,CAAW,OAAA,EAAS,cAAA;EAAA,UAiBpB,MAAA,CAAO,QAAA,EAAU,cAAA;AAAA"}
@@ -1,6 +1,6 @@
1
1
  import { MediaElement } from "../media-element.js";
2
2
  import { tooltipGroupContext } from "./context.js";
3
- import { applyElementProps, applyStateDataAttrs, createTooltip, createTransition, getAnchorNameStyle, getAnchorPositionStyle, resolveOffsets } from "@videojs/core/dom";
3
+ import { applyElementProps, applyStateDataAttrs, createTooltip, createTransition, getAnchorNameStyle, getAnchorPositionStyle, getPopupPositionRect, resolveOffsets } from "@videojs/core/dom";
4
4
  import { ContextConsumer } from "@videojs/element/context";
5
5
  import { SnapshotController } from "@videojs/store/html";
6
6
  import { TooltipCSSVars, TooltipCore, TooltipDataAttrs } from "@videojs/core";
@@ -50,6 +50,10 @@ var TooltipElement = class extends MediaElement {
50
50
  #disconnect = null;
51
51
  #triggerAbort = null;
52
52
  #currentTrigger = null;
53
+ #positionAbort = null;
54
+ #positionFrame = 0;
55
+ #resizeObserver = null;
56
+ #positionTrigger = null;
53
57
  connectedCallback() {
54
58
  super.connectedCallback();
55
59
  this.#disconnect = new AbortController();
@@ -79,6 +83,7 @@ var TooltipElement = class extends MediaElement {
79
83
  }
80
84
  disconnectedCallback() {
81
85
  super.disconnectedCallback();
86
+ this.#cleanupPositioning();
82
87
  this.#cleanupTrigger();
83
88
  this.#tooltip?.destroy();
84
89
  this.#tooltip = null;
@@ -110,7 +115,10 @@ var TooltipElement = class extends MediaElement {
110
115
  applyElementProps(this.#currentTrigger, this.#core.getTriggerAttrs(state, this.id));
111
116
  applyStyles(this.#currentTrigger, getAnchorNameStyle(this.id));
112
117
  }
113
- if (!state.open) return;
118
+ if (!state.open) {
119
+ this.#cleanupPositioning();
120
+ return;
121
+ }
114
122
  const posOpts = {
115
123
  side: state.side,
116
124
  align: state.align
@@ -118,11 +126,12 @@ var TooltipElement = class extends MediaElement {
118
126
  if (supportsAnchorPositioning()) applyStyles(this, getAnchorPositionStyle(this.id, posOpts, void 0, void 0, void 0, void 0, TooltipCSSVars));
119
127
  else {
120
128
  const triggerRect = this.#currentTrigger?.getBoundingClientRect();
121
- const selfRect = this.getBoundingClientRect();
129
+ const selfRect = getPopupPositionRect(this);
122
130
  const boundaryRect = document.documentElement.getBoundingClientRect();
123
131
  const offsets = resolveOffsets(this, TooltipCSSVars);
124
132
  applyStyles(this, getAnchorPositionStyle(this.id, posOpts, triggerRect, selfRect, boundaryRect, offsets, TooltipCSSVars));
125
133
  }
134
+ this.#syncPositioning();
126
135
  }
127
136
  #findTrigger() {
128
137
  if (!this.id) return null;
@@ -130,6 +139,7 @@ var TooltipElement = class extends MediaElement {
130
139
  }
131
140
  #syncTrigger(triggerEl) {
132
141
  if (triggerEl === this.#currentTrigger) return;
142
+ this.#cleanupPositioning();
133
143
  this.#cleanupTrigger();
134
144
  this.#currentTrigger = triggerEl;
135
145
  this.#tooltip?.setTriggerElement(triggerEl);
@@ -147,6 +157,46 @@ var TooltipElement = class extends MediaElement {
147
157
  this.#triggerAbort = null;
148
158
  this.#currentTrigger = null;
149
159
  }
160
+ #syncPositioning() {
161
+ if (supportsAnchorPositioning()) return;
162
+ const triggerEl = this.#currentTrigger;
163
+ if (!triggerEl) return;
164
+ if (this.#positionAbort && this.#positionTrigger === triggerEl) return;
165
+ this.#cleanupPositioning();
166
+ this.#positionAbort = new AbortController();
167
+ this.#positionTrigger = triggerEl;
168
+ const { signal } = this.#positionAbort;
169
+ const reposition = () => {
170
+ cancelAnimationFrame(this.#positionFrame);
171
+ this.#positionFrame = requestAnimationFrame(() => {
172
+ if (signal.aborted) return;
173
+ this.requestUpdate();
174
+ });
175
+ };
176
+ window.addEventListener("scroll", reposition, {
177
+ capture: true,
178
+ passive: true,
179
+ signal
180
+ });
181
+ window.addEventListener("resize", reposition, { signal });
182
+ if (typeof ResizeObserver === "function") {
183
+ this.#resizeObserver = new ResizeObserver(() => {
184
+ reposition();
185
+ });
186
+ this.#resizeObserver.observe(triggerEl);
187
+ this.#resizeObserver.observe(this);
188
+ }
189
+ reposition();
190
+ }
191
+ #cleanupPositioning() {
192
+ this.#positionAbort?.abort();
193
+ this.#positionAbort = null;
194
+ this.#positionTrigger = null;
195
+ cancelAnimationFrame(this.#positionFrame);
196
+ this.#positionFrame = 0;
197
+ this.#resizeObserver?.disconnect();
198
+ this.#resizeObserver = null;
199
+ }
150
200
  };
151
201
 
152
202
  //#endregion