@skodaflow/web-library 8.3.2 → 8.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (308) hide show
  1. package/cjs/components/advancedTable/agGrid.js +1 -1
  2. package/cjs/components/advancedTable/agGrid.js.map +1 -1
  3. package/cjs/components/advancedTable/agGridSkodaTheme.d.ts +3 -0
  4. package/cjs/components/advancedTable/agGridSkodaTheme.js +1 -1
  5. package/cjs/components/advancedTable/agGridSkodaTheme.js.map +1 -1
  6. package/cjs/components/advancedTable/agGridUniformRowHeight.d.ts +36 -0
  7. package/cjs/components/advancedTable/agGridUniformRowHeight.js +2 -0
  8. package/cjs/components/advancedTable/agGridUniformRowHeight.js.map +1 -0
  9. package/cjs/components/advancedTable/agGridVariables.js +1 -1
  10. package/cjs/components/advancedTable/agGridVariables.js.map +1 -1
  11. package/cjs/components/advancedTable/index.d.ts +1 -0
  12. package/cjs/components/alert/AlertIconButton.d.ts +8 -0
  13. package/cjs/components/alert/AlertIconButton.js +2 -0
  14. package/cjs/components/alert/AlertIconButton.js.map +1 -0
  15. package/cjs/components/alert/index.d.ts +1 -0
  16. package/cjs/components/carousel/Autoplay.js.map +1 -1
  17. package/cjs/components/carousel/Carousel.js +1 -1
  18. package/cjs/components/carousel/Carousel.js.map +1 -1
  19. package/cjs/components/carousel/Navigation.js +1 -1
  20. package/cjs/components/carousel/Navigation.js.map +1 -1
  21. package/cjs/components/carousel/Pagination.js +1 -1
  22. package/cjs/components/carousel/Pagination.js.map +1 -1
  23. package/cjs/components/copyButton/CopyButton.d.ts +39 -0
  24. package/cjs/components/copyButton/CopyButton.js +2 -0
  25. package/cjs/components/copyButton/CopyButton.js.map +1 -0
  26. package/cjs/components/copyButton/CopyIconButton.d.ts +8 -0
  27. package/cjs/components/copyButton/CopyIconButton.js +2 -0
  28. package/cjs/components/copyButton/CopyIconButton.js.map +1 -0
  29. package/cjs/components/copyButton/index.d.ts +3 -0
  30. package/cjs/components/copyButton/useCopyAction.d.ts +31 -0
  31. package/cjs/components/copyButton/useCopyAction.js +2 -0
  32. package/cjs/components/copyButton/useCopyAction.js.map +1 -0
  33. package/cjs/components/footer/FooterMenuCollapse.js +1 -1
  34. package/cjs/components/footer/FooterMenuCollapse.js.map +1 -1
  35. package/cjs/components/header/Header.js +1 -1
  36. package/cjs/components/header/Header.js.map +1 -1
  37. package/cjs/components/header/HeaderNavigationHero.js +1 -1
  38. package/cjs/components/header/HeaderNavigationHero.js.map +1 -1
  39. package/cjs/components/header/HeaderNavigationMenu.js +1 -1
  40. package/cjs/components/header/HeaderNavigationMenu.js.map +1 -1
  41. package/cjs/components/hotspotCard/HotspotCard.js +1 -1
  42. package/cjs/components/hotspotCard/HotspotCard.js.map +1 -1
  43. package/cjs/components/icon/stroke/EmissionLabelIcon.js.map +1 -1
  44. package/cjs/components/image/Image.d.ts +38 -14
  45. package/cjs/components/image/Image.js +1 -1
  46. package/cjs/components/image/Image.js.map +1 -1
  47. package/cjs/components/index.d.ts +2 -0
  48. package/cjs/components/label/Label.js.map +1 -1
  49. package/cjs/components/overlay/Overlay.js +1 -1
  50. package/cjs/components/overlay/Overlay.js.map +1 -1
  51. package/cjs/components/video/Video.d.ts +9 -8
  52. package/cjs/components/video/Video.js +1 -1
  53. package/cjs/components/video/Video.js.map +1 -1
  54. package/cjs/components/video/index.d.ts +5 -1
  55. package/cjs/components/video/useVideoFullscreen.d.ts +13 -0
  56. package/cjs/components/video/useVideoFullscreen.js +2 -0
  57. package/cjs/components/video/useVideoFullscreen.js.map +1 -0
  58. package/cjs/components/video/useVideoPlayPause.d.ts +13 -0
  59. package/cjs/components/video/useVideoPlayPause.js +2 -0
  60. package/cjs/components/video/useVideoPlayPause.js.map +1 -0
  61. package/cjs/components/video/useVideoReady.d.ts +6 -0
  62. package/cjs/components/video/useVideoReady.js +2 -0
  63. package/cjs/components/video/useVideoReady.js.map +1 -0
  64. package/cjs/components/video/useVideoSoundControls.d.ts +17 -0
  65. package/cjs/components/video/useVideoSoundControls.js +2 -0
  66. package/cjs/components/video/useVideoSoundControls.js.map +1 -0
  67. package/cjs/components/video/useVideoTime.d.ts +22 -0
  68. package/cjs/components/video/useVideoTime.js +2 -0
  69. package/cjs/components/video/useVideoTime.js.map +1 -0
  70. package/cjs/components/videoPlayer/VideoPlayer.d.ts +125 -0
  71. package/cjs/components/videoPlayer/VideoPlayer.js +2 -0
  72. package/cjs/components/videoPlayer/VideoPlayer.js.map +1 -0
  73. package/cjs/components/videoPlayer/VideoPlayerFullscreenButton.d.ts +31 -0
  74. package/cjs/components/videoPlayer/VideoPlayerFullscreenButton.js +2 -0
  75. package/cjs/components/videoPlayer/VideoPlayerFullscreenButton.js.map +1 -0
  76. package/cjs/components/videoPlayer/VideoPlayerIconButton.d.ts +16 -0
  77. package/cjs/components/videoPlayer/VideoPlayerIconButton.js +2 -0
  78. package/cjs/components/videoPlayer/VideoPlayerIconButton.js.map +1 -0
  79. package/cjs/components/videoPlayer/VideoPlayerPlayPauseButton.d.ts +31 -0
  80. package/cjs/components/videoPlayer/VideoPlayerPlayPauseButton.js +2 -0
  81. package/cjs/components/videoPlayer/VideoPlayerPlayPauseButton.js.map +1 -0
  82. package/cjs/components/videoPlayer/VideoPlayerSkipButton.d.ts +23 -0
  83. package/cjs/components/videoPlayer/VideoPlayerSkipButton.js +2 -0
  84. package/cjs/components/videoPlayer/VideoPlayerSkipButton.js.map +1 -0
  85. package/cjs/components/videoPlayer/VideoPlayerSlider.d.ts +12 -0
  86. package/cjs/components/videoPlayer/VideoPlayerSlider.js +2 -0
  87. package/cjs/components/videoPlayer/VideoPlayerSlider.js.map +1 -0
  88. package/cjs/components/videoPlayer/VideoPlayerSoundButton.d.ts +31 -0
  89. package/cjs/components/videoPlayer/VideoPlayerSoundButton.js +2 -0
  90. package/cjs/components/videoPlayer/VideoPlayerSoundButton.js.map +1 -0
  91. package/cjs/components/videoPlayer/VideoPlayerTime.d.ts +17 -0
  92. package/cjs/components/videoPlayer/VideoPlayerTime.js +2 -0
  93. package/cjs/components/videoPlayer/VideoPlayerTime.js.map +1 -0
  94. package/cjs/components/videoPlayer/formatVideoTime.d.ts +5 -0
  95. package/cjs/components/videoPlayer/formatVideoTime.js +2 -0
  96. package/cjs/components/videoPlayer/formatVideoTime.js.map +1 -0
  97. package/cjs/components/videoPlayer/index.d.ts +10 -0
  98. package/cjs/components/videoPlayer/useVideoPlayerVisibility.d.ts +24 -0
  99. package/cjs/components/videoPlayer/useVideoPlayerVisibility.js +2 -0
  100. package/cjs/components/videoPlayer/useVideoPlayerVisibility.js.map +1 -0
  101. package/cjs/index.js +1 -1
  102. package/cjs/materialui/accordion/AccordionSummaryExpandWrapper.d.ts +5 -1
  103. package/cjs/materialui/accordion/AccordionSummaryExpandWrapper.js +1 -1
  104. package/cjs/materialui/accordion/AccordionSummaryExpandWrapper.js.map +1 -1
  105. package/cjs/materialui/alert/alert.theme.js +1 -1
  106. package/cjs/materialui/alert/alert.theme.js.map +1 -1
  107. package/cjs/materialui/alert/alertTitle.theme.js +1 -1
  108. package/cjs/materialui/alert/alertTitle.theme.js.map +1 -1
  109. package/cjs/materialui/card/Card.js.map +1 -1
  110. package/cjs/materialui/card/card.theme.js +1 -1
  111. package/cjs/materialui/card/card.theme.js.map +1 -1
  112. package/cjs/materialui/datepicker/datecalendar.theme.d.ts +102 -102
  113. package/cjs/materialui/datepicker/digitalclock.theme.d.ts +102 -102
  114. package/cjs/materialui/divider/divider.theme.js +1 -1
  115. package/cjs/materialui/divider/divider.theme.js.map +1 -1
  116. package/cjs/materialui/iconButton/iconButton.theme.js.map +1 -1
  117. package/cjs/materialui/skeleton/skeleton.theme.js +1 -1
  118. package/cjs/materialui/skeleton/skeleton.theme.js.map +1 -1
  119. package/cjs/materialui/slider/slider.theme.js +1 -1
  120. package/cjs/materialui/slider/slider.theme.js.map +1 -1
  121. package/cjs/materialui/table/tablePagination.theme.js.map +1 -1
  122. package/cjs/materialui/tabs/Tab.d.ts +1 -0
  123. package/cjs/materialui/tabs/Tab.js +1 -1
  124. package/cjs/materialui/tabs/Tab.js.map +1 -1
  125. package/cjs/materialui/tabs/TabsScrollButton.d.ts +3 -1
  126. package/cjs/materialui/tabs/TabsScrollButton.js +1 -1
  127. package/cjs/materialui/tabs/TabsScrollButton.js.map +1 -1
  128. package/cjs/materialui/textfield/FormControl.js +1 -1
  129. package/cjs/materialui/textfield/FormControl.js.map +1 -1
  130. package/cjs/materialui/textfield/FormHelperText.js +1 -1
  131. package/cjs/materialui/textfield/FormHelperText.js.map +1 -1
  132. package/cjs/materialui/theme/sxConfig.js.map +1 -1
  133. package/cjs/materialui/theme/theme.extensions.d.ts +40 -1
  134. package/cjs/materialui/typography/typography.theme.js +1 -1
  135. package/cjs/materialui/typography/typography.theme.js.map +1 -1
  136. package/cjs/node_modules/swiper/modules/a11y.js +2 -0
  137. package/cjs/node_modules/swiper/modules/a11y.js.map +1 -0
  138. package/cjs/node_modules/swiper/modules/autoplay.js +1 -1
  139. package/cjs/node_modules/swiper/modules/autoplay.js.map +1 -1
  140. package/cjs/node_modules/swiper/modules/effect-fade.js +1 -1
  141. package/cjs/node_modules/swiper/modules/effect-fade.js.map +1 -1
  142. package/cjs/node_modules/swiper/modules/keyboard.js +1 -1
  143. package/cjs/node_modules/swiper/modules/keyboard.js.map +1 -1
  144. package/cjs/node_modules/swiper/modules/parallax.js +1 -1
  145. package/cjs/node_modules/swiper/modules/parallax.js.map +1 -1
  146. package/cjs/node_modules/swiper/shared/classes-to-selector.js +2 -0
  147. package/cjs/node_modules/swiper/shared/classes-to-selector.js.map +1 -0
  148. package/cjs/node_modules/swiper/shared/effect-init.js +1 -1
  149. package/cjs/node_modules/swiper/shared/effect-init.js.map +1 -1
  150. package/cjs/node_modules/swiper/shared/effect-target.js +1 -1
  151. package/cjs/node_modules/swiper/shared/effect-target.js.map +1 -1
  152. package/cjs/node_modules/swiper/shared/effect-virtual-transition-end.js +1 -1
  153. package/cjs/node_modules/swiper/shared/effect-virtual-transition-end.js.map +1 -1
  154. package/cjs/node_modules/swiper/shared/swiper-core.js +1 -1
  155. package/cjs/node_modules/swiper/shared/swiper-core.js.map +1 -1
  156. package/cjs/node_modules/swiper/shared/update-on-virtual-data.js +1 -1
  157. package/cjs/node_modules/swiper/shared/update-on-virtual-data.js.map +1 -1
  158. package/cjs/node_modules/swiper/shared/update-swiper.js +1 -1
  159. package/cjs/node_modules/swiper/shared/update-swiper.js.map +1 -1
  160. package/cjs/node_modules/swiper/shared/utils.js +1 -1
  161. package/cjs/node_modules/swiper/shared/utils.js.map +1 -1
  162. package/cjs/node_modules/swiper/swiper-react.js +1 -1
  163. package/cjs/node_modules/swiper/swiper-react.js.map +1 -1
  164. package/cjs/package.json +1 -0
  165. package/components/advancedTable/agGrid.js +1 -1
  166. package/components/advancedTable/agGrid.js.map +1 -1
  167. package/components/advancedTable/agGridSkodaTheme.d.ts +3 -0
  168. package/components/advancedTable/agGridSkodaTheme.js +1 -1
  169. package/components/advancedTable/agGridSkodaTheme.js.map +1 -1
  170. package/components/advancedTable/agGridUniformRowHeight.d.ts +36 -0
  171. package/components/advancedTable/agGridUniformRowHeight.js +2 -0
  172. package/components/advancedTable/agGridUniformRowHeight.js.map +1 -0
  173. package/components/advancedTable/agGridVariables.js +1 -1
  174. package/components/advancedTable/agGridVariables.js.map +1 -1
  175. package/components/advancedTable/index.d.ts +1 -0
  176. package/components/alert/AlertIconButton.d.ts +8 -0
  177. package/components/alert/AlertIconButton.js +2 -0
  178. package/components/alert/AlertIconButton.js.map +1 -0
  179. package/components/alert/index.d.ts +1 -0
  180. package/components/carousel/Autoplay.js.map +1 -1
  181. package/components/carousel/Carousel.js +1 -1
  182. package/components/carousel/Carousel.js.map +1 -1
  183. package/components/carousel/Navigation.js +1 -1
  184. package/components/carousel/Navigation.js.map +1 -1
  185. package/components/carousel/Pagination.js +1 -1
  186. package/components/carousel/Pagination.js.map +1 -1
  187. package/components/copyButton/CopyButton.d.ts +39 -0
  188. package/components/copyButton/CopyButton.js +2 -0
  189. package/components/copyButton/CopyButton.js.map +1 -0
  190. package/components/copyButton/CopyIconButton.d.ts +8 -0
  191. package/components/copyButton/CopyIconButton.js +2 -0
  192. package/components/copyButton/CopyIconButton.js.map +1 -0
  193. package/components/copyButton/index.d.ts +3 -0
  194. package/components/copyButton/useCopyAction.d.ts +31 -0
  195. package/components/copyButton/useCopyAction.js +2 -0
  196. package/components/copyButton/useCopyAction.js.map +1 -0
  197. package/components/footer/FooterMenuCollapse.js +1 -1
  198. package/components/footer/FooterMenuCollapse.js.map +1 -1
  199. package/components/header/Header.js +1 -1
  200. package/components/header/Header.js.map +1 -1
  201. package/components/header/HeaderNavigationHero.js +1 -1
  202. package/components/header/HeaderNavigationHero.js.map +1 -1
  203. package/components/header/HeaderNavigationMenu.js +1 -1
  204. package/components/header/HeaderNavigationMenu.js.map +1 -1
  205. package/components/hotspotCard/HotspotCard.js +1 -1
  206. package/components/hotspotCard/HotspotCard.js.map +1 -1
  207. package/components/icon/stroke/EmissionLabelIcon.js.map +1 -1
  208. package/components/image/Image.d.ts +38 -14
  209. package/components/image/Image.js +1 -1
  210. package/components/image/Image.js.map +1 -1
  211. package/components/index.d.ts +2 -0
  212. package/components/label/Label.js.map +1 -1
  213. package/components/overlay/Overlay.js +1 -1
  214. package/components/overlay/Overlay.js.map +1 -1
  215. package/components/video/Video.d.ts +9 -8
  216. package/components/video/Video.js +1 -1
  217. package/components/video/Video.js.map +1 -1
  218. package/components/video/index.d.ts +5 -1
  219. package/components/video/useVideoFullscreen.d.ts +13 -0
  220. package/components/video/useVideoFullscreen.js +2 -0
  221. package/components/video/useVideoFullscreen.js.map +1 -0
  222. package/components/video/useVideoPlayPause.d.ts +13 -0
  223. package/components/video/useVideoPlayPause.js +2 -0
  224. package/components/video/useVideoPlayPause.js.map +1 -0
  225. package/components/video/useVideoReady.d.ts +6 -0
  226. package/components/video/useVideoReady.js +2 -0
  227. package/components/video/useVideoReady.js.map +1 -0
  228. package/components/video/useVideoSoundControls.d.ts +17 -0
  229. package/components/video/useVideoSoundControls.js +2 -0
  230. package/components/video/useVideoSoundControls.js.map +1 -0
  231. package/components/video/useVideoTime.d.ts +22 -0
  232. package/components/video/useVideoTime.js +2 -0
  233. package/components/video/useVideoTime.js.map +1 -0
  234. package/components/videoPlayer/VideoPlayer.d.ts +125 -0
  235. package/components/videoPlayer/VideoPlayer.js +2 -0
  236. package/components/videoPlayer/VideoPlayer.js.map +1 -0
  237. package/components/videoPlayer/VideoPlayerFullscreenButton.d.ts +31 -0
  238. package/components/videoPlayer/VideoPlayerFullscreenButton.js +2 -0
  239. package/components/videoPlayer/VideoPlayerFullscreenButton.js.map +1 -0
  240. package/components/videoPlayer/VideoPlayerIconButton.d.ts +16 -0
  241. package/components/videoPlayer/VideoPlayerIconButton.js +2 -0
  242. package/components/videoPlayer/VideoPlayerIconButton.js.map +1 -0
  243. package/components/videoPlayer/VideoPlayerPlayPauseButton.d.ts +31 -0
  244. package/components/videoPlayer/VideoPlayerPlayPauseButton.js +2 -0
  245. package/components/videoPlayer/VideoPlayerPlayPauseButton.js.map +1 -0
  246. package/components/videoPlayer/VideoPlayerSkipButton.d.ts +23 -0
  247. package/components/videoPlayer/VideoPlayerSkipButton.js +2 -0
  248. package/components/videoPlayer/VideoPlayerSkipButton.js.map +1 -0
  249. package/components/videoPlayer/VideoPlayerSlider.d.ts +12 -0
  250. package/components/videoPlayer/VideoPlayerSlider.js +2 -0
  251. package/components/videoPlayer/VideoPlayerSlider.js.map +1 -0
  252. package/components/videoPlayer/VideoPlayerSoundButton.d.ts +31 -0
  253. package/components/videoPlayer/VideoPlayerSoundButton.js +2 -0
  254. package/components/videoPlayer/VideoPlayerSoundButton.js.map +1 -0
  255. package/components/videoPlayer/VideoPlayerTime.d.ts +17 -0
  256. package/components/videoPlayer/VideoPlayerTime.js +2 -0
  257. package/components/videoPlayer/VideoPlayerTime.js.map +1 -0
  258. package/components/videoPlayer/formatVideoTime.d.ts +5 -0
  259. package/components/videoPlayer/formatVideoTime.js +2 -0
  260. package/components/videoPlayer/formatVideoTime.js.map +1 -0
  261. package/components/videoPlayer/index.d.ts +10 -0
  262. package/components/videoPlayer/useVideoPlayerVisibility.d.ts +24 -0
  263. package/components/videoPlayer/useVideoPlayerVisibility.js +2 -0
  264. package/components/videoPlayer/useVideoPlayerVisibility.js.map +1 -0
  265. package/index.js +1 -1
  266. package/materialui/accordion/AccordionSummaryExpandWrapper.d.ts +5 -1
  267. package/materialui/accordion/AccordionSummaryExpandWrapper.js +1 -1
  268. package/materialui/accordion/AccordionSummaryExpandWrapper.js.map +1 -1
  269. package/materialui/alert/alert.theme.js +1 -1
  270. package/materialui/alert/alert.theme.js.map +1 -1
  271. package/materialui/alert/alertTitle.theme.js +1 -1
  272. package/materialui/alert/alertTitle.theme.js.map +1 -1
  273. package/materialui/card/Card.js.map +1 -1
  274. package/materialui/card/card.theme.js +1 -1
  275. package/materialui/card/card.theme.js.map +1 -1
  276. package/materialui/datepicker/datecalendar.theme.d.ts +102 -102
  277. package/materialui/datepicker/digitalclock.theme.d.ts +102 -102
  278. package/materialui/divider/divider.theme.js +1 -1
  279. package/materialui/divider/divider.theme.js.map +1 -1
  280. package/materialui/iconButton/iconButton.theme.js.map +1 -1
  281. package/materialui/skeleton/skeleton.theme.js +1 -1
  282. package/materialui/skeleton/skeleton.theme.js.map +1 -1
  283. package/materialui/slider/slider.theme.js +1 -1
  284. package/materialui/slider/slider.theme.js.map +1 -1
  285. package/materialui/table/tablePagination.theme.js.map +1 -1
  286. package/materialui/tabs/Tab.d.ts +1 -0
  287. package/materialui/tabs/Tab.js +1 -1
  288. package/materialui/tabs/Tab.js.map +1 -1
  289. package/materialui/tabs/TabsScrollButton.d.ts +3 -1
  290. package/materialui/tabs/TabsScrollButton.js +1 -1
  291. package/materialui/tabs/TabsScrollButton.js.map +1 -1
  292. package/materialui/textfield/FormControl.js +1 -1
  293. package/materialui/textfield/FormControl.js.map +1 -1
  294. package/materialui/textfield/FormHelperText.js +1 -1
  295. package/materialui/textfield/FormHelperText.js.map +1 -1
  296. package/materialui/theme/sxConfig.js.map +1 -1
  297. package/materialui/theme/theme.extensions.d.ts +40 -1
  298. package/materialui/typography/typography.theme.js +1 -1
  299. package/materialui/typography/typography.theme.js.map +1 -1
  300. package/package.json +1 -1
  301. package/cjs/components/video/hooks.d.ts +0 -43
  302. package/cjs/components/video/hooks.js +0 -2
  303. package/cjs/components/video/hooks.js.map +0 -1
  304. package/cjs/node_modules/swiper/shared/ssr-window.esm.js +0 -2
  305. package/cjs/node_modules/swiper/shared/ssr-window.esm.js.map +0 -1
  306. package/components/video/hooks.d.ts +0 -43
  307. package/components/video/hooks.js +0 -2
  308. package/components/video/hooks.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVideoPlayPause.js","sources":["../../../src/components/video/useVideoPlayPause.ts"],"sourcesContent":["import { useCallback, useEffect, useState, type RefObject } from 'react';\n\ninterface PlayPause {\n /** Whether the video is currently playing */\n isPlaying: boolean;\n /** Toggles play/pause */\n handlePlayPause: () => void;\n}\n\n/**\n * Manages play/pause state for a video element\n * @param videoRef - A reference to the video element.\n */\nexport const useVideoPlayPause = (videoRef: RefObject<HTMLVideoElement>): PlayPause => {\n const [isPlaying, setIsPlaying] = useState(!videoRef.current?.paused);\n\n useEffect(() => {\n const video = videoRef?.current;\n\n if (video && isPlaying === undefined) {\n setIsPlaying(!video?.paused);\n }\n\n const handlePlay = () => {\n // prevent playing state when autoplay triggers play event on re-entering viewport after video ended\n !(video.autoplay && video.ended) && setIsPlaying(true);\n };\n const handlePause = () => setIsPlaying(false);\n\n if (video) {\n video.addEventListener('pause', handlePause);\n\n // Set initial state (not enough without event listeners due to autoPlay and paused race conditions)\n setIsPlaying(!video.paused);\n\n video.addEventListener('play', handlePlay);\n\n return () => {\n video.removeEventListener('play', handlePlay);\n video.removeEventListener('pause', handlePause);\n };\n }\n }, [videoRef]);\n\n const handlePlayPause = useCallback(() => {\n if (videoRef?.current) {\n if (isPlaying) {\n videoRef.current.pause();\n } else {\n videoRef.current.play().catch(() => {});\n }\n setIsPlaying((prevIsPlaying) => !prevIsPlaying);\n }\n }, [isPlaying, videoRef]);\n\n return {\n isPlaying,\n handlePlayPause,\n };\n};\n"],"names":["useVideoPlayPause","videoRef","isPlaying","setIsPlaying","useState","current","paused","useEffect","video","undefined","handlePlay","autoplay","ended","handlePause","addEventListener","removeEventListener","handlePlayPause","useCallback","pause","play","catch","prevIsPlaying"],"mappings":"iEAaO,MAAMA,EAAqBC,IAChC,MAAOC,EAAWC,GAAgBC,GAAUH,EAASI,SAASC,QAE9DC,EAAU,KACR,MAAMC,EAAQP,GAAUI,QAEpBG,QAAuBC,IAAdP,GACXC,GAAcK,GAAOF,QAGvB,MAAMI,EAAa,OAEfF,EAAMG,WAAYH,EAAMI,QAAUT,GAAa,IAE7CU,EAAc,IAAMV,GAAa,GAEvC,GAAIK,EAQF,OAPAA,EAAMM,iBAAiB,QAASD,GAGhCV,GAAcK,EAAMF,QAEpBE,EAAMM,iBAAiB,OAAQJ,GAExB,KACLF,EAAMO,oBAAoB,OAAQL,GAClCF,EAAMO,oBAAoB,QAASF,KAGtC,CAACZ,IAEJ,MAAMe,EAAkBC,EAAY,KAC9BhB,GAAUI,UACRH,EACFD,EAASI,QAAQa,QAEjBjB,EAASI,QAAQc,OAAOC,MAAM,QAEhCjB,EAAckB,IAAmBA,KAElC,CAACnB,EAAWD,IAEf,MAAO,CACLC,YACAc"}
@@ -0,0 +1,6 @@
1
+ import { type RefObject } from 'react';
2
+ /**
3
+ * Reports whether the video has loaded its metadata without an error, false while loading or after a failure
4
+ * @param videoRef - A reference to the video element.
5
+ */
6
+ export declare const useVideoReady: (videoRef: RefObject<HTMLVideoElement>) => boolean;
@@ -0,0 +1,2 @@
1
+ import{useState as e,useEffect as t}from"react";const r=r=>{const[n,d]=e(!1);return t(()=>{const e=r?.current;if(!e)return;const t=()=>d(e.readyState>=HTMLMediaElement.HAVE_METADATA&&!e.error);return t(),e.addEventListener("loadedmetadata",t),e.addEventListener("emptied",t),e.addEventListener("error",t),()=>{e.removeEventListener("loadedmetadata",t),e.removeEventListener("emptied",t),e.removeEventListener("error",t)}},[r]),n};export{r as useVideoReady};
2
+ //# sourceMappingURL=useVideoReady.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVideoReady.js","sources":["../../../src/components/video/useVideoReady.ts"],"sourcesContent":["import { useEffect, useState, type RefObject } from 'react';\n\n/**\n * Reports whether the video has loaded its metadata without an error, false while loading or after a failure\n * @param videoRef - A reference to the video element.\n */\nexport const useVideoReady = (videoRef: RefObject<HTMLVideoElement>): boolean => {\n // not ready on the server and before the first check, so the controls never flash over a broken video\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n const video = videoRef?.current;\n if (!video) {\n return;\n }\n // a failed <source> keeps readyState at HAVE_NOTHING, a failed src or a network error sets video.error\n const update = () => setReady(video.readyState >= HTMLMediaElement.HAVE_METADATA && !video.error);\n\n // the video may have loaded before hydration\n update();\n video.addEventListener('loadedmetadata', update);\n video.addEventListener('emptied', update);\n video.addEventListener('error', update);\n\n return () => {\n video.removeEventListener('loadedmetadata', update);\n video.removeEventListener('emptied', update);\n video.removeEventListener('error', update);\n };\n }, [videoRef]);\n\n return ready;\n};\n"],"names":["useVideoReady","videoRef","ready","setReady","useState","useEffect","video","current","update","readyState","HTMLMediaElement","HAVE_METADATA","error","addEventListener","removeEventListener"],"mappings":"gDAMO,MAAMA,EAAiBC,IAE5B,MAAOC,EAAOC,GAAYC,GAAS,GAuBnC,OArBAC,EAAU,KACR,MAAMC,EAAQL,GAAUM,QACxB,IAAKD,EACH,OAGF,MAAME,EAAS,IAAML,EAASG,EAAMG,YAAcC,iBAAiBC,gBAAkBL,EAAMM,OAQ3F,OALAJ,IACAF,EAAMO,iBAAiB,iBAAkBL,GACzCF,EAAMO,iBAAiB,UAAWL,GAClCF,EAAMO,iBAAiB,QAASL,GAEzB,KACLF,EAAMQ,oBAAoB,iBAAkBN,GAC5CF,EAAMQ,oBAAoB,UAAWN,GACrCF,EAAMQ,oBAAoB,QAASN,KAEpC,CAACP,IAEGC"}
@@ -0,0 +1,17 @@
1
+ import { type RefObject } from 'react';
2
+ interface SoundControls {
3
+ /** Whether the video is muted */
4
+ isMuted: boolean;
5
+ /** Toggles mute on/off */
6
+ handleMuteToggle: () => void;
7
+ /** Current volume level, 0 to 1 */
8
+ volume: number;
9
+ /** Sets the volume level */
10
+ handleVolumeChange: (newVolume: number) => void;
11
+ }
12
+ /**
13
+ * Manages mute and volume for a video element
14
+ * @param videoRef - A reference to the video element.
15
+ */
16
+ export declare const useVideoSoundControls: (videoRef: RefObject<HTMLVideoElement>) => SoundControls;
17
+ export {};
@@ -0,0 +1,2 @@
1
+ import{useState as e,useEffect as t,useCallback as r}from"react";const u=u=>{const[n,o]=e(u.current?.muted),[c,m]=e(1);t(()=>{const e=u?.current;e&&(void 0===n&&o(e?.muted),u.current.muted=n,u.current.volume=c)},[n,c,u]);const d=r(()=>{o(e=>!e)},[]),l=r(e=>{m(e)},[]);return{isMuted:n,handleMuteToggle:d,volume:c,handleVolumeChange:l}};export{u as useVideoSoundControls};
2
+ //# sourceMappingURL=useVideoSoundControls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVideoSoundControls.js","sources":["../../../src/components/video/useVideoSoundControls.ts"],"sourcesContent":["import { useCallback, useEffect, useState, type RefObject } from 'react';\n\ninterface SoundControls {\n /** Whether the video is muted */\n isMuted: boolean;\n /** Toggles mute on/off */\n handleMuteToggle: () => void;\n /** Current volume level, 0 to 1 */\n volume: number;\n /** Sets the volume level */\n handleVolumeChange: (newVolume: number) => void;\n}\n\n/**\n * Manages mute and volume for a video element\n * @param videoRef - A reference to the video element.\n */\nexport const useVideoSoundControls = (videoRef: RefObject<HTMLVideoElement>): SoundControls => {\n const [isMuted, setIsMuted] = useState(videoRef.current?.muted);\n const [volume, setVolume] = useState(1);\n\n useEffect(() => {\n const video = videoRef?.current;\n if (video) {\n if (isMuted === undefined) {\n setIsMuted(video?.muted);\n }\n\n videoRef.current.muted = isMuted;\n videoRef.current.volume = volume;\n }\n }, [isMuted, volume, videoRef]);\n\n const handleMuteToggle = useCallback(() => {\n setIsMuted((prevMuted) => !prevMuted);\n }, []);\n\n const handleVolumeChange = useCallback((newVolume: number) => {\n setVolume(newVolume);\n }, []);\n\n return {\n isMuted,\n handleMuteToggle,\n volume,\n handleVolumeChange,\n };\n};\n"],"names":["useVideoSoundControls","videoRef","isMuted","setIsMuted","useState","current","muted","volume","setVolume","useEffect","video","undefined","handleMuteToggle","useCallback","prevMuted","handleVolumeChange","newVolume"],"mappings":"iEAiBO,MAAMA,EAAyBC,IACpC,MAAOC,EAASC,GAAcC,EAASH,EAASI,SAASC,QAClDC,EAAQC,GAAaJ,EAAS,GAErCK,EAAU,KACR,MAAMC,EAAQT,GAAUI,QACpBK,SACcC,IAAZT,GACFC,EAAWO,GAAOJ,OAGpBL,EAASI,QAAQC,MAAQJ,EACzBD,EAASI,QAAQE,OAASA,IAE3B,CAACL,EAASK,EAAQN,IAErB,MAAMW,EAAmBC,EAAY,KACnCV,EAAYW,IAAeA,IAC1B,IAEGC,EAAqBF,EAAaG,IACtCR,EAAUQ,IACT,IAEH,MAAO,CACLd,UACAU,mBACAL,SACAQ"}
@@ -0,0 +1,22 @@
1
+ import { type RefObject } from 'react';
2
+ export interface VideoTimeOptions {
3
+ /**
4
+ * Updates the current time every animation frame while playing, instead of the ~250ms `timeupdate` interval
5
+ */
6
+ smooth?: boolean;
7
+ }
8
+ interface VideoTime {
9
+ /** Current playback time, in seconds */
10
+ currentTime: number;
11
+ /** Total video duration, in seconds */
12
+ duration: number;
13
+ /** Seeks to a specific time */
14
+ handleSeek: (newTime: number) => void;
15
+ }
16
+ /**
17
+ * Synchronizes playback time and duration with component state
18
+ * @param videoRef - A reference to the video element.
19
+ * @param options - Additional options.
20
+ */
21
+ export declare const useVideoTime: (videoRef: RefObject<HTMLVideoElement>, { smooth }?: VideoTimeOptions) => VideoTime;
22
+ export {};
@@ -0,0 +1,2 @@
1
+ import{useState as e,useCallback as t,useEffect as r}from"react";const n=(n,{smooth:a}={})=>{const[i,u]=e(0),[o,c]=e(n.current?.duration),m=t(()=>{n.current&&u(n.current.currentTime)},[n]),d=t(e=>{n.current&&(n.current.currentTime=e),u(e)},[n]),s=t(()=>{n.current?.duration&&c(n.current.duration)},[n]);return r(()=>{const e=n?.current;if(e)return e.addEventListener("loadedmetadata",s),e.addEventListener("timeupdate",m),()=>{e.removeEventListener("loadedmetadata",s),e.removeEventListener("timeupdate",m)}},[s,m,n]),r(()=>{const e=n?.current;if(!a||!e)return;let t;const r=()=>{u(e.currentTime),t=requestAnimationFrame(r)},i=()=>{cancelAnimationFrame(t),t=requestAnimationFrame(r)},o=()=>cancelAnimationFrame(t);return e.paused||i(),e.addEventListener("play",i),e.addEventListener("pause",o),()=>{o(),e.removeEventListener("play",i),e.removeEventListener("pause",o)}},[a,n]),{currentTime:i,duration:o,handleSeek:d}};export{n as useVideoTime};
2
+ //# sourceMappingURL=useVideoTime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVideoTime.js","sources":["../../../src/components/video/useVideoTime.ts"],"sourcesContent":["import { useCallback, useEffect, useState, type RefObject } from 'react';\n\nexport interface VideoTimeOptions {\n /**\n * Updates the current time every animation frame while playing, instead of the ~250ms `timeupdate` interval\n */\n smooth?: boolean;\n}\n\ninterface VideoTime {\n /** Current playback time, in seconds */\n currentTime: number;\n /** Total video duration, in seconds */\n duration: number;\n /** Seeks to a specific time */\n handleSeek: (newTime: number) => void;\n}\n\n/**\n * Synchronizes playback time and duration with component state\n * @param videoRef - A reference to the video element.\n * @param options - Additional options.\n */\nexport const useVideoTime = (videoRef: RefObject<HTMLVideoElement>, { smooth }: VideoTimeOptions = {}): VideoTime => {\n const [currentTime, setCurrentTime] = useState(0);\n const [duration, setDuration] = useState(videoRef.current?.duration);\n\n const handleTimeUpdate = useCallback(() => {\n if (videoRef.current) {\n setCurrentTime(videoRef.current.currentTime);\n }\n }, [videoRef]);\n\n const handleSeek = useCallback(\n (newTime: number) => {\n if (videoRef.current) {\n videoRef.current.currentTime = newTime;\n }\n setCurrentTime(newTime);\n },\n [videoRef],\n );\n\n const handleLoadedMetadata = useCallback(() => {\n if (videoRef.current?.duration) {\n setDuration(videoRef.current.duration);\n }\n }, [videoRef]);\n\n useEffect(() => {\n const video = videoRef?.current;\n if (video) {\n video.addEventListener('loadedmetadata', handleLoadedMetadata);\n video.addEventListener('timeupdate', handleTimeUpdate);\n\n return () => {\n video.removeEventListener('loadedmetadata', handleLoadedMetadata);\n video.removeEventListener('timeupdate', handleTimeUpdate);\n };\n }\n }, [handleLoadedMetadata, handleTimeUpdate, videoRef]);\n\n useEffect(() => {\n const video = videoRef?.current;\n if (!smooth || !video) {\n return;\n }\n let frame: number;\n const update = () => {\n setCurrentTime(video.currentTime);\n frame = requestAnimationFrame(update);\n };\n const start = () => {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(update);\n };\n const stop = () => cancelAnimationFrame(frame);\n\n if (!video.paused) {\n start();\n }\n video.addEventListener('play', start);\n video.addEventListener('pause', stop);\n\n return () => {\n stop();\n video.removeEventListener('play', start);\n video.removeEventListener('pause', stop);\n };\n }, [smooth, videoRef]);\n\n return {\n currentTime,\n duration,\n handleSeek,\n };\n};\n"],"names":["useVideoTime","videoRef","smooth","currentTime","setCurrentTime","useState","duration","setDuration","current","handleTimeUpdate","useCallback","handleSeek","newTime","handleLoadedMetadata","useEffect","video","addEventListener","removeEventListener","frame","update","requestAnimationFrame","start","cancelAnimationFrame","stop","paused"],"mappings":"iEAuBO,MAAMA,EAAe,CAACC,GAAyCC,UAA6B,CAAA,KACjG,MAAOC,EAAaC,GAAkBC,EAAS,IACxCC,EAAUC,GAAeF,EAASJ,EAASO,SAASF,UAErDG,EAAmBC,EAAY,KAC/BT,EAASO,SACXJ,EAAeH,EAASO,QAAQL,cAEjC,CAACF,IAEEU,EAAaD,EAChBE,IACKX,EAASO,UACXP,EAASO,QAAQL,YAAcS,GAEjCR,EAAeQ,IAEjB,CAACX,IAGGY,EAAuBH,EAAY,KACnCT,EAASO,SAASF,UACpBC,EAAYN,EAASO,QAAQF,WAE9B,CAACL,IA4CJ,OA1CAa,EAAU,KACR,MAAMC,EAAQd,GAAUO,QACxB,GAAIO,EAIF,OAHAA,EAAMC,iBAAiB,iBAAkBH,GACzCE,EAAMC,iBAAiB,aAAcP,GAE9B,KACLM,EAAME,oBAAoB,iBAAkBJ,GAC5CE,EAAME,oBAAoB,aAAcR,KAG3C,CAACI,EAAsBJ,EAAkBR,IAE5Ca,EAAU,KACR,MAAMC,EAAQd,GAAUO,QACxB,IAAKN,IAAWa,EACd,OAEF,IAAIG,EACJ,MAAMC,EAAS,KACbf,EAAeW,EAAMZ,aACrBe,EAAQE,sBAAsBD,IAE1BE,EAAQ,KACZC,qBAAqBJ,GACrBA,EAAQE,sBAAsBD,IAE1BI,EAAO,IAAMD,qBAAqBJ,GAQxC,OANKH,EAAMS,QACTH,IAEFN,EAAMC,iBAAiB,OAAQK,GAC/BN,EAAMC,iBAAiB,QAASO,GAEzB,KACLA,IACAR,EAAME,oBAAoB,OAAQI,GAClCN,EAAME,oBAAoB,QAASM,KAEpC,CAACrB,EAAQD,IAEL,CACLE,cACAG,WACAK"}
@@ -0,0 +1,125 @@
1
+ import React, { ElementType, type ReactNode } from 'react';
2
+ import { BoxProps } from '@mui/material';
3
+ import { OverlayProps } from '../overlay/Overlay';
4
+ import { VideoPlayerPlayPauseButtonProps } from './VideoPlayerPlayPauseButton';
5
+ import { VideoPlayerSkipButtonProps } from './VideoPlayerSkipButton';
6
+ import { VideoPlayerSoundButtonProps } from './VideoPlayerSoundButton';
7
+ import { VideoPlayerFullscreenButtonProps } from './VideoPlayerFullscreenButton';
8
+ import { VideoPlayerSliderProps } from './VideoPlayerSlider';
9
+ import { VideoPlayerTimeProps } from './VideoPlayerTime';
10
+ export interface VideoPlayerProps extends BoxProps<ElementType> {
11
+ /**
12
+ * Video component to be controlled
13
+ */
14
+ children: ReactNode;
15
+ /**
16
+ * Inactivity in ms after which the controls hide while the video is playing
17
+ * @default 3000
18
+ */
19
+ hideDelay?: number;
20
+ /**
21
+ * Inactivity in ms after which the controls hide while the video is playing in fullscreen
22
+ * @default 1000
23
+ */
24
+ fullscreenHideDelay?: number;
25
+ /**
26
+ * Keeps the controls always visible
27
+ */
28
+ disableAutoHide?: boolean;
29
+ /**
30
+ * Callback of the skip-previous button, the button is hidden when not provided
31
+ */
32
+ onSkipPrevious?: () => void;
33
+ /**
34
+ * Callback of the skip-next button, the button is hidden when not provided
35
+ */
36
+ onSkipNext?: () => void;
37
+ /**
38
+ * Hides the sound button
39
+ */
40
+ disableSound?: boolean;
41
+ /**
42
+ * Hides the play/pause button
43
+ */
44
+ disablePlayPause?: boolean;
45
+ /**
46
+ * Hides the current time and duration
47
+ */
48
+ disableTime?: boolean;
49
+ /**
50
+ * Hides the seek slider
51
+ */
52
+ disableSlider?: boolean;
53
+ /**
54
+ * Hides the fullscreen button and disables fullscreen on double click
55
+ */
56
+ disableFullscreen?: boolean;
57
+ /**
58
+ * ReactNode that renders custom buttons between the playback and sound buttons. If multiple buttons are needed, wrap them in React.Fragment
59
+ */
60
+ startButtons?: ReactNode;
61
+ /**
62
+ * ReactNode that renders custom buttons before the fullscreen button. If multiple buttons are needed, wrap them in React.Fragment
63
+ */
64
+ endButtons?: ReactNode;
65
+ /**
66
+ * Properties passed to the Overlay component
67
+ */
68
+ overlayProps?: Omit<OverlayProps, 'overlayContent' | 'wrapperProps' | 'children'>;
69
+ /**
70
+ * Properties passed to the VideoPlayerPlayPauseButton component
71
+ */
72
+ playPauseButtonProps?: Omit<VideoPlayerPlayPauseButtonProps, 'videoRef'>;
73
+ /**
74
+ * Properties passed to the skip-previous VideoPlayerSkipButton component
75
+ */
76
+ skipPreviousButtonProps?: Omit<VideoPlayerSkipButtonProps, 'direction'>;
77
+ /**
78
+ * Properties passed to the skip-next VideoPlayerSkipButton component
79
+ */
80
+ skipNextButtonProps?: Omit<VideoPlayerSkipButtonProps, 'direction'>;
81
+ /**
82
+ * Properties passed to the VideoPlayerSoundButton component
83
+ */
84
+ soundButtonProps?: Omit<VideoPlayerSoundButtonProps, 'videoRef'>;
85
+ /**
86
+ * Properties passed to the VideoPlayerFullscreenButton component
87
+ */
88
+ fullscreenButtonProps?: Omit<VideoPlayerFullscreenButtonProps, 'containerRef'>;
89
+ /**
90
+ * Properties passed to the VideoPlayerSlider component
91
+ */
92
+ sliderProps?: Omit<VideoPlayerSliderProps, 'videoRef'>;
93
+ /**
94
+ * Properties passed to the VideoPlayerTime component
95
+ */
96
+ timeProps?: Omit<VideoPlayerTimeProps, 'videoRef'>;
97
+ /**
98
+ * Properties applied to the wrapper of playback buttons centered over the video on mobile
99
+ */
100
+ centerWrapperProps?: BoxProps<ElementType>;
101
+ /**
102
+ * Properties applied to the bar at the bottom, wrapping the slider and the toolbar
103
+ */
104
+ barProps?: BoxProps<ElementType>;
105
+ /**
106
+ * Properties applied to the toolbar below the slider
107
+ */
108
+ toolbarProps?: BoxProps<ElementType>;
109
+ /**
110
+ * Properties applied to the wrapper of playback buttons in the toolbar on desktop
111
+ */
112
+ playbackWrapperProps?: BoxProps<ElementType>;
113
+ /**
114
+ * Properties applied to the wrapper of buttons at the start of the toolbar
115
+ */
116
+ startButtonsWrapperProps?: BoxProps<ElementType>;
117
+ /**
118
+ * Properties applied to the wrapper of buttons at the end of the toolbar, filling its free space
119
+ */
120
+ endButtonsWrapperProps?: BoxProps<ElementType>;
121
+ }
122
+ /**
123
+ * Video player controls with play/pause, sound, seek and fullscreen buttons over the Video component
124
+ */
125
+ export declare const VideoPlayer: React.FC<VideoPlayerProps>;
@@ -0,0 +1,2 @@
1
+ import{jsxs as e,jsx as t,Fragment as o}from"react/jsx-runtime";import{forwardRef as i,useRef as r,useCallback as n}from"react";import{useForkRef as s,Box as a}from"@mui/material";import{sxOverride as l}from"../../utils/sxOverride/sxOverride.js";import{Overlay as d}from"../overlay/Overlay.js";import{VideoPlayerPlayPauseButton as p}from"./VideoPlayerPlayPauseButton.js";import{VideoPlayerSkipButton as u}from"./VideoPlayerSkipButton.js";import{VideoPlayerSoundButton as c}from"./VideoPlayerSoundButton.js";import{VideoPlayerFullscreenButton as m}from"./VideoPlayerFullscreenButton.js";import{VideoPlayerSlider as y}from"./VideoPlayerSlider.js";import{VideoPlayerTime as P}from"./VideoPlayerTime.js";import{useVideoPlayerVisibility as f}from"./useVideoPlayerVisibility.js";import{useVideoReady as x}from"../video/useVideoReady.js";import{useVideoFullscreen as b}from"../video/useVideoFullscreen.js";import{ControlsPlayFilledIcon as v}from"../icon/filled/ControlsPlayFilledIcon.js";import{ControlsPauseFilledIcon as V}from"../icon/filled/ControlsPauseFilledIcon.js";const h=i(({children:i,hideDelay:h=3e3,fullscreenHideDelay:k=1e3,disableAutoHide:j,onSkipPrevious:C,onSkipNext:g,disableSound:B,disablePlayPause:S,disableTime:D,disableSlider:I,disableFullscreen:F,startButtons:R,endButtons:E,overlayProps:T,playPauseButtonProps:w,skipPreviousButtonProps:z,skipNextButtonProps:W,soundButtonProps:L,fullscreenButtonProps:O,sliderProps:A,timeProps:H,centerWrapperProps:K,barProps:M,toolbarProps:N,playbackWrapperProps:q,startButtonsWrapperProps:G,endButtonsWrapperProps:J,onClick:Q,onDoubleClick:U,onPointerMove:X,onPointerDown:Y,onPointerLeave:Z,onKeyDown:$,sx:_,...ee},te)=>{const oe=r(null),ie=r(null),re=n(e=>{oe.current=e,ie.current=e?.querySelector("video")??null},[]),ne=s(re,te),{isFullscreen:se,handleFullscreenToggle:ae}=b(oe),{visible:le,handleActivity:de,handleLeave:pe}=f(ie,{hideDelay:se?k:h,disabled:j}),ue=x(ie),ce=({target:e,currentTarget:t})=>e===ie.current||e instanceof Element&&e.parentElement===t,me=r(!1),{sx:ye,...Pe}=T??{},{sx:fe,...xe}=K??{},{sx:be,...ve}=M??{},{sx:Ve,...he}=N??{},{sx:ke,...je}=q??{},{sx:Ce,...ge}=G??{},{sx:Be,...Se}=J??{},{sx:De,...Ie}=H??{},Fe=i=>e(o,{children:[C&&t(u,{direction:"previous",size:"medium",...z,onClick:e=>{z?.onClick?.(e),C()}}),!S&&t(p,{videoRef:ie,size:"medium",...i&&{PlayIconComponent:v,PauseIconComponent:V},...w}),g&&t(u,{direction:"next",size:"medium",...W,onClick:e=>{W?.onClick?.(e),g()}})]});return e(d,{"data-testid":"VideoPlayer.overlay","data-visible":le,overlayContent:i,wrapperProps:{ref:ne,"data-testid":"VideoPlayer",sx:l({...!le&&{cursor:"none"}},_),onClick:e=>{Q?.(e);const t=ie.current;t&&ue&&ce(e)&&!me.current&&(t.paused?t.play().catch(()=>{}):t.pause())},onDoubleClick:e=>{U?.(e),!F&&ue&&ce(e)&&ae()},onPointerMove:e=>{X?.(e),de()},onPointerDown:e=>{Y?.(e),me.current="touch"===e.pointerType&&!le,de()},onKeyDown:e=>{$?.(e),de()},onPointerLeave:e=>{Z?.(e),"mouse"===e.pointerType&&pe()},...ee},sx:l({transition:"opacity 0.3s ease-out",backgroundRepeat:"no-repeat",backgroundPosition:"bottom",backgroundSize:{xs:"100% 100%",md:"100% 136px"},...!le&&{opacity:"0",pointerEvents:"none","&:has(:focus-visible)":{opacity:"1",pointerEvents:"auto"}},...!ue&&{display:"none"}},ye),...Pe,children:[t(a,{"data-testid":"VideoPlayer.center",sx:l({position:"absolute",inset:"0",display:{xs:"flex",md:"none"},alignItems:"center",justifyContent:"center",gap:2,'&:has(+ * :is([data-testid="VideoPlayerSeekSlider"], [data-testid="VideoPlayer.start"] > :not([data-testid="VideoPlayer.playback"]), [data-testid="VideoPlayer.end"] > *))':{mb:4,"@media (orientation: portrait)":{"*:fullscreen &":{mb:0}}},pointerEvents:"none","& > *":{pointerEvents:"auto"}},fe),...xe,children:Fe(!0)}),e(a,{"data-testid":"VideoPlayer.bar",sx:l({position:"absolute",insetInline:"0",bottom:"0",display:"flex",flexDirection:"column",alignItems:"stretch",justifyContent:"flex-start",px:{xs:2,md:3},pb:{xs:.5,md:1}},be),...ve,children:[!I&&t(y,{videoRef:ie,...A}),e(a,{"data-testid":"VideoPlayer.toolbar",sx:l({display:"flex",alignItems:"center",justifyContent:"flex-start",gap:{xs:.5,md:1}},Ve),...he,children:[e(a,{"data-testid":"VideoPlayer.start",sx:l({display:"flex",alignItems:"center",justifyContent:"flex-start",gap:"inherit"},Ce),...ge,children:[t(a,{"data-testid":"VideoPlayer.playback",sx:l({display:{xs:"none",md:"contents"}},ke),...je,children:Fe(!1)}),R,!B&&t(c,{videoRef:ie,...L}),!D&&t(P,{videoRef:ie,sx:l({order:{xs:"-1",md:"0"}},De),...Ie})]}),e(a,{"data-testid":"VideoPlayer.end",sx:l({flex:"1",display:"flex",alignItems:"center",justifyContent:"flex-end",gap:"inherit"},Be),...Se,children:[E,!F&&t(m,{containerRef:oe,...O})]})]})]})]})});export{h as VideoPlayer};
2
+ //# sourceMappingURL=VideoPlayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoPlayer.js","sources":["../../../src/components/videoPlayer/VideoPlayer.tsx"],"sourcesContent":["import React, {\n ElementType,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n type PointerEvent as ReactPointerEvent,\n type ReactNode,\n useCallback,\n useRef,\n} from 'react';\nimport { Box, BoxProps, useForkRef } from '@mui/material';\nimport { sxOverride } from '@/src/utils/sxOverride';\nimport { Overlay, OverlayProps } from '@/src/components/overlay/Overlay';\nimport { VideoPlayerPlayPauseButton, VideoPlayerPlayPauseButtonProps } from './VideoPlayerPlayPauseButton';\nimport { VideoPlayerSkipButton, VideoPlayerSkipButtonProps } from './VideoPlayerSkipButton';\nimport { VideoPlayerSoundButton, VideoPlayerSoundButtonProps } from './VideoPlayerSoundButton';\nimport { VideoPlayerFullscreenButton, VideoPlayerFullscreenButtonProps } from './VideoPlayerFullscreenButton';\nimport { VideoPlayerSlider, VideoPlayerSliderProps } from './VideoPlayerSlider';\nimport { VideoPlayerTime, VideoPlayerTimeProps } from './VideoPlayerTime';\nimport { useVideoPlayerVisibility } from './useVideoPlayerVisibility';\nimport { useVideoReady } from '@/src/components/video/useVideoReady';\nimport { useVideoFullscreen } from '@/src/components/video/useVideoFullscreen';\nimport { ControlsPlayFilledIcon } from '@/src/components/icon/filled/ControlsPlayFilledIcon';\nimport { ControlsPauseFilledIcon } from '@/src/components/icon/filled/ControlsPauseFilledIcon';\n\nexport interface VideoPlayerProps extends BoxProps<ElementType> {\n /**\n * Video component to be controlled\n */\n children: ReactNode;\n /**\n * Inactivity in ms after which the controls hide while the video is playing\n * @default 3000\n */\n hideDelay?: number;\n /**\n * Inactivity in ms after which the controls hide while the video is playing in fullscreen\n * @default 1000\n */\n fullscreenHideDelay?: number;\n /**\n * Keeps the controls always visible\n */\n disableAutoHide?: boolean;\n /**\n * Callback of the skip-previous button, the button is hidden when not provided\n */\n onSkipPrevious?: () => void;\n /**\n * Callback of the skip-next button, the button is hidden when not provided\n */\n onSkipNext?: () => void;\n /**\n * Hides the sound button\n */\n disableSound?: boolean;\n /**\n * Hides the play/pause button\n */\n disablePlayPause?: boolean;\n /**\n * Hides the current time and duration\n */\n disableTime?: boolean;\n /**\n * Hides the seek slider\n */\n disableSlider?: boolean;\n /**\n * Hides the fullscreen button and disables fullscreen on double click\n */\n disableFullscreen?: boolean;\n /**\n * ReactNode that renders custom buttons between the playback and sound buttons. If multiple buttons are needed, wrap them in React.Fragment\n */\n startButtons?: ReactNode;\n /**\n * ReactNode that renders custom buttons before the fullscreen button. If multiple buttons are needed, wrap them in React.Fragment\n */\n endButtons?: ReactNode;\n /**\n * Properties passed to the Overlay component\n */\n overlayProps?: Omit<OverlayProps, 'overlayContent' | 'wrapperProps' | 'children'>;\n /**\n * Properties passed to the VideoPlayerPlayPauseButton component\n */\n playPauseButtonProps?: Omit<VideoPlayerPlayPauseButtonProps, 'videoRef'>;\n /**\n * Properties passed to the skip-previous VideoPlayerSkipButton component\n */\n skipPreviousButtonProps?: Omit<VideoPlayerSkipButtonProps, 'direction'>;\n /**\n * Properties passed to the skip-next VideoPlayerSkipButton component\n */\n skipNextButtonProps?: Omit<VideoPlayerSkipButtonProps, 'direction'>;\n /**\n * Properties passed to the VideoPlayerSoundButton component\n */\n soundButtonProps?: Omit<VideoPlayerSoundButtonProps, 'videoRef'>;\n /**\n * Properties passed to the VideoPlayerFullscreenButton component\n */\n fullscreenButtonProps?: Omit<VideoPlayerFullscreenButtonProps, 'containerRef'>;\n /**\n * Properties passed to the VideoPlayerSlider component\n */\n sliderProps?: Omit<VideoPlayerSliderProps, 'videoRef'>;\n /**\n * Properties passed to the VideoPlayerTime component\n */\n timeProps?: Omit<VideoPlayerTimeProps, 'videoRef'>;\n /**\n * Properties applied to the wrapper of playback buttons centered over the video on mobile\n */\n centerWrapperProps?: BoxProps<ElementType>;\n /**\n * Properties applied to the bar at the bottom, wrapping the slider and the toolbar\n */\n barProps?: BoxProps<ElementType>;\n /**\n * Properties applied to the toolbar below the slider\n */\n toolbarProps?: BoxProps<ElementType>;\n /**\n * Properties applied to the wrapper of playback buttons in the toolbar on desktop\n */\n playbackWrapperProps?: BoxProps<ElementType>;\n /**\n * Properties applied to the wrapper of buttons at the start of the toolbar\n */\n startButtonsWrapperProps?: BoxProps<ElementType>;\n /**\n * Properties applied to the wrapper of buttons at the end of the toolbar, filling its free space\n */\n endButtonsWrapperProps?: BoxProps<ElementType>;\n}\n\n/**\n * Video player controls with play/pause, sound, seek and fullscreen buttons over the Video component\n */\nexport const VideoPlayer: React.FC<VideoPlayerProps> = forwardRef(\n (\n {\n children,\n // common inactivity before players hide their controls\n hideDelay = 3000,\n // shorter in fullscreen, where the controls cover the whole screen\n fullscreenHideDelay = 1000,\n disableAutoHide,\n onSkipPrevious,\n onSkipNext,\n disableSound,\n disablePlayPause,\n disableTime,\n disableSlider,\n disableFullscreen,\n startButtons,\n endButtons,\n overlayProps,\n playPauseButtonProps,\n skipPreviousButtonProps,\n skipNextButtonProps,\n soundButtonProps,\n fullscreenButtonProps,\n sliderProps,\n timeProps,\n centerWrapperProps,\n barProps,\n toolbarProps,\n playbackWrapperProps,\n startButtonsWrapperProps,\n endButtonsWrapperProps,\n onClick,\n onDoubleClick,\n onPointerMove,\n onPointerDown,\n onPointerLeave,\n onKeyDown,\n sx,\n ...rest\n },\n ref,\n ) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const videoRef = useRef<HTMLVideoElement | null>(null);\n\n // refs attach before any effect runs, so the parts subscribe to the video passed as children\n const handleContainerRef = useCallback((node: HTMLDivElement | null) => {\n containerRef.current = node;\n videoRef.current = node?.querySelector('video') ?? null;\n }, []);\n const handleRef = useForkRef(handleContainerRef, ref);\n\n const { isFullscreen, handleFullscreenToggle } = useVideoFullscreen(containerRef);\n\n const { visible, handleActivity, handleLeave } = useVideoPlayerVisibility(videoRef, {\n hideDelay: isFullscreen ? fullscreenHideDelay : hideDelay,\n disabled: disableAutoHide,\n });\n\n const ready = useVideoReady(videoRef);\n\n // only the video or the overlay above it react to clicks, not the controls\n const isVideoArea = ({ target, currentTarget }: MouseEvent<HTMLDivElement>) =>\n target === videoRef.current || (target instanceof Element && target.parentElement === currentTarget);\n\n // a touch tap on hidden controls only shows them, pointerdown already shows them before the click arrives\n const revealTapRef = useRef(false);\n\n const handleClick = (event: MouseEvent<HTMLDivElement>) => {\n onClick?.(event);\n const video = videoRef.current;\n if (!video || !ready || !isVideoArea(event) || revealTapRef.current) {\n return;\n }\n if (video.paused) {\n video.play().catch(() => {});\n } else {\n video.pause();\n }\n };\n\n const { sx: overlaySx, ...restOverlay } = overlayProps ?? {};\n const { sx: centerWrapperSx, ...restCenterWrapper } = centerWrapperProps ?? {};\n const { sx: barSx, ...restBar } = barProps ?? {};\n const { sx: toolbarSx, ...restToolbar } = toolbarProps ?? {};\n const { sx: playbackWrapperSx, ...restPlaybackWrapper } = playbackWrapperProps ?? {};\n const { sx: startButtonsWrapperSx, ...restStartButtonsWrapper } = startButtonsWrapperProps ?? {};\n const { sx: endButtonsWrapperSx, ...restEndButtonsWrapper } = endButtonsWrapperProps ?? {};\n const { sx: timeSx, ...restTime } = timeProps ?? {};\n\n // playback buttons keep the medium size on mobile, where they are centered over the video\n const renderPlaybackButtons = (centered: boolean) => (\n <>\n {onSkipPrevious && (\n <VideoPlayerSkipButton\n direction=\"previous\"\n size=\"medium\"\n {...skipPreviousButtonProps}\n onClick={(event: MouseEvent<HTMLButtonElement>) => {\n skipPreviousButtonProps?.onClick?.(event);\n onSkipPrevious();\n }}\n />\n )}\n {!disablePlayPause && (\n <VideoPlayerPlayPauseButton\n videoRef={videoRef}\n size=\"medium\"\n // the centered button over the video on mobile has filled icons\n {...(centered && {\n PlayIconComponent: ControlsPlayFilledIcon,\n PauseIconComponent: ControlsPauseFilledIcon,\n })}\n {...playPauseButtonProps}\n />\n )}\n {onSkipNext && (\n <VideoPlayerSkipButton\n direction=\"next\"\n size=\"medium\"\n {...skipNextButtonProps}\n onClick={(event: MouseEvent<HTMLButtonElement>) => {\n skipNextButtonProps?.onClick?.(event);\n onSkipNext();\n }}\n />\n )}\n </>\n );\n\n return (\n <Overlay\n data-testid=\"VideoPlayer.overlay\"\n data-visible={visible}\n overlayContent={children}\n wrapperProps={{\n ref: handleRef,\n 'data-testid': 'VideoPlayer',\n sx: sxOverride(\n {\n ...(!visible && {\n cursor: 'none',\n }),\n },\n sx,\n ),\n onClick: handleClick,\n onDoubleClick: (event: MouseEvent<HTMLDivElement>) => {\n onDoubleClick?.(event);\n if (!disableFullscreen && ready && isVideoArea(event)) {\n handleFullscreenToggle();\n }\n },\n onPointerMove: (event: ReactPointerEvent<HTMLDivElement>) => {\n onPointerMove?.(event);\n handleActivity();\n },\n onPointerDown: (event: ReactPointerEvent<HTMLDivElement>) => {\n onPointerDown?.(event);\n revealTapRef.current = event.pointerType === 'touch' && !visible;\n handleActivity();\n },\n onKeyDown: (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n handleActivity();\n },\n onPointerLeave: (event: ReactPointerEvent<HTMLDivElement>) => {\n onPointerLeave?.(event);\n // touch fires pointerleave right after each tap, only a mouse can actually leave\n if (event.pointerType === 'mouse') {\n handleLeave();\n }\n },\n ...rest,\n }}\n sx={sxOverride(\n {\n transition: 'opacity 0.3s ease-out',\n backgroundRepeat: 'no-repeat',\n backgroundPosition: 'bottom',\n // twice the height of the bar (68px) on desktop, mobile keeps it over the whole video for centered buttons\n backgroundSize: { xs: '100% 100%', md: '100% 136px' },\n ...(!visible && {\n opacity: '0',\n // pointer reaches the video, any activity over it shows the controls again\n pointerEvents: 'none',\n // keyboard focus keeps the controls shown, focus after a mouse click is not visible\n '&:has(:focus-visible)': {\n opacity: '1',\n pointerEvents: 'auto',\n },\n }),\n // no controls over a loading or broken video, display none also keeps them out of keyboard focus\n ...(!ready && {\n display: 'none',\n }),\n },\n overlaySx,\n )}\n {...restOverlay}\n >\n <Box\n data-testid=\"VideoPlayer.center\"\n sx={sxOverride(\n {\n // on mobile playback buttons are centered over the video\n position: 'absolute',\n inset: '0',\n display: { xs: 'flex', md: 'none' },\n alignItems: 'center',\n justifyContent: 'center',\n gap: 2,\n // lifted above the bar only when it shows the slider or a toolbar item, the hidden playback wrapper does not count\n '&:has(+ * :is([data-testid=\"VideoPlayerSeekSlider\"], [data-testid=\"VideoPlayer.start\"] > :not([data-testid=\"VideoPlayer.playback\"]), [data-testid=\"VideoPlayer.end\"] > *))':\n {\n mb: 4,\n // portrait fullscreen letterboxes the video, the bar sits below it and nothing overlaps,\n // the fullscreen player is the viewport, so the media query matches its own orientation\n '@media (orientation: portrait)': {\n '*:fullscreen &': {\n mb: 0,\n },\n },\n },\n // keep the video clickable around the buttons\n pointerEvents: 'none',\n '& > *': {\n pointerEvents: 'auto',\n },\n },\n centerWrapperSx,\n )}\n {...restCenterWrapper}\n >\n {renderPlaybackButtons(true)}\n </Box>\n <Box\n data-testid=\"VideoPlayer.bar\"\n sx={sxOverride(\n {\n position: 'absolute',\n insetInline: '0',\n bottom: '0',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'stretch',\n justifyContent: 'flex-start',\n px: { xs: 2, md: 3 },\n // the slider has its own space above the track\n pb: { xs: 0.5, md: 1 },\n },\n barSx,\n )}\n {...restBar}\n >\n {!disableSlider && <VideoPlayerSlider videoRef={videoRef} {...sliderProps} />}\n <Box\n data-testid=\"VideoPlayer.toolbar\"\n sx={sxOverride(\n {\n // no padding, the toolbar collapses on mobile when nothing but centered playback buttons is in it\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-start',\n gap: { xs: 0.5, md: 1 },\n },\n toolbarSx,\n )}\n {...restToolbar}\n >\n <Box\n data-testid=\"VideoPlayer.start\"\n sx={sxOverride(\n { display: 'flex', alignItems: 'center', justifyContent: 'flex-start', gap: 'inherit' },\n startButtonsWrapperSx,\n )}\n {...restStartButtonsWrapper}\n >\n <Box\n data-testid=\"VideoPlayer.playback\"\n sx={sxOverride({ display: { xs: 'none', md: 'contents' } }, playbackWrapperSx)}\n {...restPlaybackWrapper}\n >\n {renderPlaybackButtons(false)}\n </Box>\n {startButtons}\n {!disableSound && <VideoPlayerSoundButton videoRef={videoRef} {...soundButtonProps} />}\n {!disableTime && (\n <VideoPlayerTime\n videoRef={videoRef}\n sx={sxOverride(\n {\n // on mobile the time comes first, before the start and sound buttons\n order: { xs: '-1', md: '0' },\n },\n timeSx,\n )}\n {...restTime}\n />\n )}\n </Box>\n <Box\n data-testid=\"VideoPlayer.end\"\n sx={sxOverride(\n {\n // pushes the end buttons to the right side, while also wrapping them\n flex: '1',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end',\n gap: 'inherit',\n },\n endButtonsWrapperSx,\n )}\n {...restEndButtonsWrapper}\n >\n {endButtons}\n {!disableFullscreen && (\n <VideoPlayerFullscreenButton containerRef={containerRef} {...fullscreenButtonProps} />\n )}\n </Box>\n </Box>\n </Box>\n </Overlay>\n );\n },\n);\n"],"names":["VideoPlayer","forwardRef","children","hideDelay","fullscreenHideDelay","disableAutoHide","onSkipPrevious","onSkipNext","disableSound","disablePlayPause","disableTime","disableSlider","disableFullscreen","startButtons","endButtons","overlayProps","playPauseButtonProps","skipPreviousButtonProps","skipNextButtonProps","soundButtonProps","fullscreenButtonProps","sliderProps","timeProps","centerWrapperProps","barProps","toolbarProps","playbackWrapperProps","startButtonsWrapperProps","endButtonsWrapperProps","onClick","onDoubleClick","onPointerMove","onPointerDown","onPointerLeave","onKeyDown","sx","rest","ref","containerRef","useRef","videoRef","handleContainerRef","useCallback","node","current","querySelector","handleRef","useForkRef","isFullscreen","handleFullscreenToggle","useVideoFullscreen","visible","handleActivity","handleLeave","useVideoPlayerVisibility","disabled","ready","useVideoReady","isVideoArea","target","currentTarget","Element","parentElement","revealTapRef","overlaySx","restOverlay","centerWrapperSx","restCenterWrapper","barSx","restBar","toolbarSx","restToolbar","playbackWrapperSx","restPlaybackWrapper","startButtonsWrapperSx","restStartButtonsWrapper","endButtonsWrapperSx","restEndButtonsWrapper","timeSx","restTime","renderPlaybackButtons","centered","_jsxs","_Fragment","_jsx","VideoPlayerSkipButton","direction","size","event","VideoPlayerPlayPauseButton","PlayIconComponent","ControlsPlayFilledIcon","PauseIconComponent","ControlsPauseFilledIcon","Overlay","overlayContent","wrapperProps","sxOverride","cursor","video","paused","play","catch","pause","pointerType","transition","backgroundRepeat","backgroundPosition","backgroundSize","xs","md","opacity","pointerEvents","display","Box","position","inset","alignItems","justifyContent","gap","mb","insetInline","bottom","flexDirection","px","pb","VideoPlayerSlider","VideoPlayerSoundButton","VideoPlayerTime","order","flex","VideoPlayerFullscreenButton"],"mappings":"+iCA6IaA,EAA0CC,EACrD,EAEIC,WAEAC,YAAY,IAEZC,sBAAsB,IACtBC,kBACAC,iBACAC,aACAC,eACAC,mBACAC,cACAC,gBACAC,oBACAC,eACAC,aACAC,eACAC,uBACAC,0BACAC,sBACAC,mBACAC,wBACAC,cACAC,YACAC,qBACAC,WACAC,eACAC,uBACAC,2BACAC,yBACAC,UACAC,gBACAC,gBACAC,gBACAC,iBACAC,YACAC,QACGC,IAELC,MAEA,MAAMC,GAAeC,EAA8B,MAC7CC,GAAWD,EAAgC,MAG3CE,GAAqBC,EAAaC,IACtCL,GAAaM,QAAUD,EACvBH,GAASI,QAAUD,GAAME,cAAc,UAAY,MAClD,IACGC,GAAYC,EAAWN,GAAoBJ,KAE3CW,aAAEA,GAAYC,uBAAEA,IAA2BC,EAAmBZ,KAE9Da,QAAEA,GAAOC,eAAEA,GAAcC,YAAEA,IAAgBC,EAAyBd,GAAU,CAClFrC,UAAW6C,GAAe5C,EAAsBD,EAChDoD,SAAUlD,IAGNmD,GAAQC,EAAcjB,IAGtBkB,GAAc,EAAGC,SAAQC,mBAC7BD,IAAWnB,GAASI,SAAYe,aAAkBE,SAAWF,EAAOG,gBAAkBF,EAGlFG,GAAexB,GAAO,IAepBJ,GAAI6B,MAAcC,IAAgBlD,GAAgB,CAAA,GAClDoB,GAAI+B,MAAoBC,IAAsB5C,GAAsB,CAAA,GACpEY,GAAIiC,MAAUC,IAAY7C,GAAY,CAAA,GACtCW,GAAImC,MAAcC,IAAgB9C,GAAgB,CAAA,GAClDU,GAAIqC,MAAsBC,IAAwB/C,GAAwB,CAAA,GAC1ES,GAAIuC,MAA0BC,IAA4BhD,GAA4B,CAAA,GACtFQ,GAAIyC,MAAwBC,IAA0BjD,GAA0B,CAAA,GAChFO,GAAI2C,MAAWC,IAAazD,GAAa,CAAA,EAG3C0D,GAAyBC,GAC7BC,EAAAC,EAAA,CAAAjF,SAAA,CACGI,GACC8E,EAACC,EAAqB,CACpBC,UAAU,WACVC,KAAK,YACDtE,EACJY,QAAU2D,IACRvE,GAAyBY,UAAU2D,GACnClF,QAIJG,GACA2E,EAACK,EAA0B,CACzBjD,SAAUA,GACV+C,KAAK,YAEAN,GAAY,CACfS,kBAAmBC,EACnBC,mBAAoBC,MAElB7E,IAGPT,GACC6E,EAACC,EAAqB,CACpBC,UAAU,OACVC,KAAK,YACDrE,EACJW,QAAU2D,IACRtE,GAAqBW,UAAU2D,GAC/BjF,UAOV,OACE2E,EAACY,EAAO,CAAA,cACM,sBAAqB,eACnB3C,GACd4C,eAAgB7F,EAChB8F,aAAc,CACZ3D,IAAKS,GACL,cAAe,cACfX,GAAI8D,EACF,KACO9C,IAAW,CACd+C,OAAQ,SAGZ/D,GAEFN,QA9Ee2D,IACnB3D,IAAU2D,GACV,MAAMW,EAAQ3D,GAASI,QAClBuD,GAAU3C,IAAUE,GAAY8B,KAAUzB,GAAanB,UAGxDuD,EAAMC,OACRD,EAAME,OAAOC,MAAM,QAEnBH,EAAMI,UAsEJzE,cAAgB0D,IACd1D,IAAgB0D,IACX5E,GAAqB4C,IAASE,GAAY8B,IAC7CvC,MAGJlB,cAAgByD,IACdzD,IAAgByD,GAChBpC,MAEFpB,cAAgBwD,IACdxD,IAAgBwD,GAChBzB,GAAanB,QAAgC,UAAtB4C,EAAMgB,cAA4BrD,GACzDC,MAEFlB,UAAYsD,IACVtD,IAAYsD,GACZpC,MAEFnB,eAAiBuD,IACfvD,IAAiBuD,GAES,UAAtBA,EAAMgB,aACRnD,SAGDjB,IAELD,GAAI8D,EACF,CACEQ,WAAY,wBACZC,iBAAkB,YAClBC,mBAAoB,SAEpBC,eAAgB,CAAEC,GAAI,YAAaC,GAAI,kBAClC3D,IAAW,CACd4D,QAAS,IAETC,cAAe,OAEf,wBAAyB,CACvBD,QAAS,IACTC,cAAe,aAIdxD,IAAS,CACZyD,QAAS,SAGbjD,OAEEC,GAAW/D,SAAA,CAEfkF,EAAC8B,EAAG,CAAA,cACU,qBACZ/E,GAAI8D,EACF,CAEEkB,SAAU,WACVC,MAAO,IACPH,QAAS,CAAEJ,GAAI,OAAQC,GAAI,QAC3BO,WAAY,SACZC,eAAgB,SAChBC,IAAK,EAEL,6KACE,CACEC,GAAI,EAGJ,iCAAkC,CAChC,iBAAkB,CAChBA,GAAI,KAKZR,cAAe,OACf,QAAS,CACPA,cAAe,SAGnB9C,OAEEC,GAAiBjE,SAEpB8E,IAAsB,KAEzBE,EAACgC,EAAG,CAAA,cACU,kBACZ/E,GAAI8D,EACF,CACEkB,SAAU,WACVM,YAAa,IACbC,OAAQ,IACRT,QAAS,OACTU,cAAe,SACfN,WAAY,UACZC,eAAgB,aAChBM,GAAI,CAAEf,GAAI,EAAGC,GAAI,GAEjBe,GAAI,CAAEhB,GAAI,GAAKC,GAAI,IAErB1C,OAEEC,GAAOnE,SAAA,EAETS,GAAiByE,EAAC0C,EAAiB,CAACtF,SAAUA,MAAcnB,IAC9D6D,EAACgC,EAAG,CAAA,cACU,sBACZ/E,GAAI8D,EACF,CAEEgB,QAAS,OACTI,WAAY,SACZC,eAAgB,aAChBC,IAAK,CAAEV,GAAI,GAAKC,GAAI,IAEtBxC,OAEEC,aAEJW,EAACgC,EAAG,CAAA,cACU,oBACZ/E,GAAI8D,EACF,CAAEgB,QAAS,OAAQI,WAAY,SAAUC,eAAgB,aAAcC,IAAK,WAC5E7C,OAEEC,GAAuBzE,SAAA,CAE3BkF,EAAC8B,EAAG,CAAA,cACU,uBACZ/E,GAAI8D,EAAW,CAAEgB,QAAS,CAAEJ,GAAI,OAAQC,GAAI,aAAgBtC,OACxDC,GAAmBvE,SAEtB8E,IAAsB,KAExBnE,GACCL,GAAgB4E,EAAC2C,EAAsB,CAACvF,SAAUA,MAAcrB,KAChET,GACA0E,EAAC4C,GACCxF,SAAUA,GACVL,GAAI8D,EACF,CAEEgC,MAAO,CAAEpB,GAAI,KAAMC,GAAI,MAEzBhC,OAEEC,QAIVG,EAACgC,iBACa,kBACZ/E,GAAI8D,EACF,CAEEiC,KAAM,IACNjB,QAAS,OACTI,WAAY,SACZC,eAAgB,WAChBC,IAAK,WAEP3C,OAEEC,GAAqB3E,SAAA,CAExBY,GACCF,GACAwE,EAAC+C,GAA4B7F,aAAcA,MAAkBlB"}
@@ -0,0 +1,31 @@
1
+ import React, { ComponentType, type RefObject } from 'react';
2
+ import { SvgIconProps } from '@mui/material';
3
+ import { VideoPlayerIconButtonProps } from './VideoPlayerIconButton';
4
+ export interface VideoPlayerFullscreenButtonProps extends Omit<VideoPlayerIconButtonProps, 'title'> {
5
+ /**
6
+ * Ref to the element shown in fullscreen
7
+ */
8
+ containerRef: RefObject<HTMLElement>;
9
+ /**
10
+ * Custom component for the icon shown while not fullscreen
11
+ */
12
+ EnterIconComponent?: ComponentType<SvgIconProps>;
13
+ /**
14
+ * Custom component for the icon shown while fullscreen
15
+ */
16
+ ExitIconComponent?: ComponentType<SvgIconProps>;
17
+ /**
18
+ * Tooltip and aria-label while not fullscreen
19
+ * @default Enter fullscreen
20
+ */
21
+ enterTitle?: string;
22
+ /**
23
+ * Tooltip and aria-label while fullscreen
24
+ * @default Exit fullscreen
25
+ */
26
+ exitTitle?: string;
27
+ }
28
+ /**
29
+ * Button that toggles fullscreen of the container
30
+ */
31
+ export declare const VideoPlayerFullscreenButton: React.FC<VideoPlayerFullscreenButtonProps>;
@@ -0,0 +1,2 @@
1
+ import{jsx as e}from"react/jsx-runtime";import{forwardRef as r}from"react";import{FullscreenEnterIcon as o}from"../icon/stroke/FullscreenEnterIcon.js";import{FullscreenExitIcon as t}from"../icon/stroke/FullscreenExitIcon.js";import{useVideoFullscreen as n}from"../video/useVideoFullscreen.js";import{VideoPlayerIconButton as l}from"./VideoPlayerIconButton.js";const i=r(({containerRef:r,EnterIconComponent:i,ExitIconComponent:c,enterTitle:s="Enter fullscreen",exitTitle:m="Exit fullscreen",onClick:u,...a},d)=>{const{isFullscreen:f,handleFullscreenToggle:p}=n(r);return e(l,{ref:d,"data-testid":"VideoPlayerFullscreen",title:f?m:s,onClick:e=>{u?.(e),p()},...a,children:e(f?c??t:i??o,{"data-testid":f?"VideoPlayerFullscreenExitIcon":"VideoPlayerFullscreenEnterIcon"})})});export{i as VideoPlayerFullscreenButton};
2
+ //# sourceMappingURL=VideoPlayerFullscreenButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoPlayerFullscreenButton.js","sources":["../../../src/components/videoPlayer/VideoPlayerFullscreenButton.tsx"],"sourcesContent":["import React, { ComponentType, forwardRef, type MouseEvent, type RefObject } from 'react';\nimport { SvgIconProps } from '@mui/material';\nimport { FullscreenEnterIcon } from '@/src/components/icon/stroke/FullscreenEnterIcon';\nimport { FullscreenExitIcon } from '@/src/components/icon/stroke/FullscreenExitIcon';\nimport { useVideoFullscreen } from '@/src/components/video/useVideoFullscreen';\nimport { VideoPlayerIconButton, VideoPlayerIconButtonProps } from './VideoPlayerIconButton';\n\nexport interface VideoPlayerFullscreenButtonProps extends Omit<VideoPlayerIconButtonProps, 'title'> {\n /**\n * Ref to the element shown in fullscreen\n */\n containerRef: RefObject<HTMLElement>;\n /**\n * Custom component for the icon shown while not fullscreen\n */\n EnterIconComponent?: ComponentType<SvgIconProps>;\n /**\n * Custom component for the icon shown while fullscreen\n */\n ExitIconComponent?: ComponentType<SvgIconProps>;\n /**\n * Tooltip and aria-label while not fullscreen\n * @default Enter fullscreen\n */\n enterTitle?: string;\n /**\n * Tooltip and aria-label while fullscreen\n * @default Exit fullscreen\n */\n exitTitle?: string;\n}\n\n/**\n * Button that toggles fullscreen of the container\n */\nexport const VideoPlayerFullscreenButton: React.FC<VideoPlayerFullscreenButtonProps> = forwardRef(\n (\n {\n containerRef,\n EnterIconComponent,\n ExitIconComponent,\n enterTitle = 'Enter fullscreen',\n exitTitle = 'Exit fullscreen',\n onClick,\n ...rest\n },\n ref,\n ) => {\n const { isFullscreen, handleFullscreenToggle } = useVideoFullscreen(containerRef);\n const Icon = isFullscreen ? (ExitIconComponent ?? FullscreenExitIcon) : (EnterIconComponent ?? FullscreenEnterIcon);\n\n return (\n <VideoPlayerIconButton\n ref={ref}\n data-testid=\"VideoPlayerFullscreen\"\n title={isFullscreen ? exitTitle : enterTitle}\n onClick={(event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n handleFullscreenToggle();\n }}\n {...rest}\n >\n <Icon data-testid={isFullscreen ? 'VideoPlayerFullscreenExitIcon' : 'VideoPlayerFullscreenEnterIcon'} />\n </VideoPlayerIconButton>\n );\n },\n);\n"],"names":["VideoPlayerFullscreenButton","forwardRef","containerRef","EnterIconComponent","ExitIconComponent","enterTitle","exitTitle","onClick","rest","ref","isFullscreen","handleFullscreenToggle","useVideoFullscreen","_jsx","VideoPlayerIconButton","title","event","children","FullscreenExitIcon","FullscreenEnterIcon"],"mappings":"wWAmCO,MAAMA,EAA0EC,EACrF,EAEIC,eACAC,qBACAC,oBACAC,aAAa,mBACbC,YAAY,kBACZC,aACGC,GAELC,KAEA,MAAMC,aAAEA,EAAYC,uBAAEA,GAA2BC,EAAmBV,GAGpE,OACEW,EAACC,EAAqB,CACpBL,IAAKA,EAAG,cACI,wBACZM,MAAOL,EAAeJ,EAAYD,EAClCE,QAAUS,IACRT,IAAUS,GACVL,QAEEH,EAAIS,SAERJ,EAbSH,EAAgBN,GAAqBc,EAAuBf,GAAsBgB,EAatF,CAAA,cAAcT,EAAe,gCAAkC"}
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { IconButtonProps } from '@mui/material';
3
+ export interface VideoPlayerIconButtonProps extends IconButtonProps {
4
+ /**
5
+ * Text shown in the tooltip and used as aria-label
6
+ */
7
+ title: string;
8
+ /**
9
+ * Fixed size on all screens, small on mobile and medium on desktop when not set
10
+ */
11
+ size?: IconButtonProps['size'];
12
+ }
13
+ /**
14
+ * IconButton with a tooltip, base of the VideoPlayer buttons
15
+ */
16
+ export declare const VideoPlayerIconButton: React.FC<VideoPlayerIconButtonProps>;
@@ -0,0 +1,2 @@
1
+ import{jsx as o}from"react/jsx-runtime";import{forwardRef as t}from"react";import{Tooltip as e,IconButton as i}from"@mui/material";import{sxOverride as r}from"../../utils/sxOverride/sxOverride.js";const m=t(({title:t,size:m,sx:p,...s},a)=>o(e,{title:t,placement:"top","data-tooltip-mode":"dark",slotProps:{popper:{modifiers:[{name:"offset",options:{offset:[0,2]}}]}},children:o(i,{ref:a,color:"white",size:m??"medium","aria-label":t,sx:m?p:r(o=>({[o.breakpoints.down("md")]:{width:"32px",height:"32px","& .MuiSvgIcon-root":{fontSize:"17px"}}}),p),...s})}));export{m as VideoPlayerIconButton};
2
+ //# sourceMappingURL=VideoPlayerIconButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoPlayerIconButton.js","sources":["../../../src/components/videoPlayer/VideoPlayerIconButton.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { IconButton, IconButtonProps, Tooltip } from '@mui/material';\nimport { sxOverride } from '@/src/utils/sxOverride';\n\nexport interface VideoPlayerIconButtonProps extends IconButtonProps {\n /**\n * Text shown in the tooltip and used as aria-label\n */\n title: string;\n /**\n * Fixed size on all screens, small on mobile and medium on desktop when not set\n */\n size?: IconButtonProps['size'];\n}\n\n/**\n * IconButton with a tooltip, base of the VideoPlayer buttons\n */\nexport const VideoPlayerIconButton: React.FC<VideoPlayerIconButtonProps> = forwardRef(\n ({ title, size, sx, ...rest }, ref) => (\n <Tooltip\n title={title}\n placement=\"top\"\n // dark mode tooltip is white, keeps it white over the video regardless of the theme\n data-tooltip-mode=\"dark\"\n // tooltip closer to the button than the default offset\n slotProps={{ popper: { modifiers: [{ name: 'offset', options: { offset: [0, 2] } }] } }}\n >\n <IconButton\n ref={ref}\n color=\"white\"\n size={size ?? 'medium'}\n aria-label={title}\n sx={\n size\n ? sx\n : sxOverride(\n (theme) => ({\n // sizes of size=\"small\" on mobile, a media query instead of the prop keeps it right on the server\n [theme.breakpoints.down('md')]: {\n width: '32px',\n height: '32px',\n '& .MuiSvgIcon-root': {\n fontSize: '17px',\n },\n },\n }),\n sx,\n )\n }\n {...rest}\n />\n </Tooltip>\n ),\n);\n"],"names":["VideoPlayerIconButton","forwardRef","title","size","sx","rest","ref","_jsx","Tooltip","placement","slotProps","popper","modifiers","name","options","offset","IconButton","color","sxOverride","theme","breakpoints","down","width","height","fontSize"],"mappings":"qMAkBO,MAAMA,EAA8DC,EACzE,EAAGC,QAAOC,OAAMC,QAAOC,GAAQC,IAC7BC,EAACC,EAAO,CACNN,MAAOA,EACPO,UAAU,0BAEQ,OAElBC,UAAW,CAAEC,OAAQ,CAAEC,UAAW,CAAC,CAAEC,KAAM,SAAUC,QAAS,CAAEC,OAAQ,CAAC,EAAG,iBAE5ER,EAACS,GACCV,IAAKA,EACLW,MAAM,QACNd,KAAMA,GAAQ,sBACFD,EACZE,GACED,EACIC,EACAc,EACGC,IAAK,CAEJ,CAACA,EAAMC,YAAYC,KAAK,OAAQ,CAC9BC,MAAO,OACPC,OAAQ,OACR,qBAAsB,CACpBC,SAAU,WAIhBpB,MAGJC"}
@@ -0,0 +1,31 @@
1
+ import React, { ComponentType, type RefObject } from 'react';
2
+ import { SvgIconProps } from '@mui/material';
3
+ import { VideoPlayerIconButtonProps } from './VideoPlayerIconButton';
4
+ export interface VideoPlayerPlayPauseButtonProps extends Omit<VideoPlayerIconButtonProps, 'title'> {
5
+ /**
6
+ * Ref to the controlled <video> element
7
+ */
8
+ videoRef: RefObject<HTMLVideoElement>;
9
+ /**
10
+ * Custom component for the icon shown while the video is paused
11
+ */
12
+ PlayIconComponent?: ComponentType<SvgIconProps>;
13
+ /**
14
+ * Custom component for the icon shown while the video is playing
15
+ */
16
+ PauseIconComponent?: ComponentType<SvgIconProps>;
17
+ /**
18
+ * Tooltip and aria-label while the video is paused
19
+ * @default Play video
20
+ */
21
+ playTitle?: string;
22
+ /**
23
+ * Tooltip and aria-label while the video is playing
24
+ * @default Pause video
25
+ */
26
+ pauseTitle?: string;
27
+ }
28
+ /**
29
+ * Button that toggles play/pause of the video
30
+ */
31
+ export declare const VideoPlayerPlayPauseButton: React.FC<VideoPlayerPlayPauseButtonProps>;
@@ -0,0 +1,2 @@
1
+ import{jsx as o}from"react/jsx-runtime";import{forwardRef as e}from"react";import{sxOverride as t}from"../../utils/sxOverride/sxOverride.js";import{ControlsPlayIcon as i}from"../icon/stroke/ControlsPlayIcon.js";import{ControlsPauseIcon as r}from"../icon/stroke/ControlsPauseIcon.js";import{useVideoPlayPause as s}from"../video/useVideoPlayPause.js";import{VideoPlayerIconButton as a}from"./VideoPlayerIconButton.js";const n=e(({videoRef:e,PlayIconComponent:n,PauseIconComponent:l,playTitle:d="Play video",pauseTitle:P="Pause video",onClick:m,sx:c,...p},u)=>{const{isPlaying:y,handlePlayPause:f}=s(e),x=y?l??r:n??i;return o(a,{ref:u,"data-testid":"VideoPlayerPlayPause",title:y?P:d,onClick:o=>{m?.(o),f()},sx:t(o=>({[o.breakpoints.down("md")]:{width:"52px",height:"52px","& .MuiSvgIcon-root":{fontSize:"32px"}}}),c),...p,children:o(x,{"data-testid":y?"VideoPlayerPauseIcon":"VideoPlayerPlayIcon"})})});export{n as VideoPlayerPlayPauseButton};
2
+ //# sourceMappingURL=VideoPlayerPlayPauseButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoPlayerPlayPauseButton.js","sources":["../../../src/components/videoPlayer/VideoPlayerPlayPauseButton.tsx"],"sourcesContent":["import React, { ComponentType, forwardRef, type MouseEvent, type RefObject } from 'react';\nimport { SvgIconProps } from '@mui/material';\nimport { sxOverride } from '@/src/utils/sxOverride';\nimport { ControlsPlayIcon } from '@/src/components/icon/stroke/ControlsPlayIcon';\nimport { ControlsPauseIcon } from '@/src/components/icon/stroke/ControlsPauseIcon';\nimport { useVideoPlayPause } from '@/src/components/video/useVideoPlayPause';\nimport { VideoPlayerIconButton, VideoPlayerIconButtonProps } from './VideoPlayerIconButton';\n\nexport interface VideoPlayerPlayPauseButtonProps extends Omit<VideoPlayerIconButtonProps, 'title'> {\n /**\n * Ref to the controlled <video> element\n */\n videoRef: RefObject<HTMLVideoElement>;\n /**\n * Custom component for the icon shown while the video is paused\n */\n PlayIconComponent?: ComponentType<SvgIconProps>;\n /**\n * Custom component for the icon shown while the video is playing\n */\n PauseIconComponent?: ComponentType<SvgIconProps>;\n /**\n * Tooltip and aria-label while the video is paused\n * @default Play video\n */\n playTitle?: string;\n /**\n * Tooltip and aria-label while the video is playing\n * @default Pause video\n */\n pauseTitle?: string;\n}\n\n/**\n * Button that toggles play/pause of the video\n */\nexport const VideoPlayerPlayPauseButton: React.FC<VideoPlayerPlayPauseButtonProps> = forwardRef(\n (\n {\n videoRef,\n PlayIconComponent,\n PauseIconComponent,\n playTitle = 'Play video',\n pauseTitle = 'Pause video',\n onClick,\n sx,\n ...rest\n },\n ref,\n ) => {\n const { isPlaying, handlePlayPause } = useVideoPlayPause(videoRef);\n const Icon = isPlaying ? (PauseIconComponent ?? ControlsPauseIcon) : (PlayIconComponent ?? ControlsPlayIcon);\n\n return (\n <VideoPlayerIconButton\n ref={ref}\n data-testid=\"VideoPlayerPlayPause\"\n title={isPlaying ? pauseTitle : playTitle}\n onClick={(event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n handlePlayPause();\n }}\n sx={sxOverride(\n (theme) => ({\n // larger button on mobile, where it is centered over the video\n [theme.breakpoints.down('md')]: {\n width: '52px',\n height: '52px',\n '& .MuiSvgIcon-root': {\n fontSize: '32px',\n },\n },\n }),\n sx,\n )}\n {...rest}\n >\n <Icon data-testid={isPlaying ? 'VideoPlayerPauseIcon' : 'VideoPlayerPlayIcon'} />\n </VideoPlayerIconButton>\n );\n },\n);\n"],"names":["VideoPlayerPlayPauseButton","forwardRef","videoRef","PlayIconComponent","PauseIconComponent","playTitle","pauseTitle","onClick","sx","rest","ref","isPlaying","handlePlayPause","useVideoPlayPause","Icon","ControlsPauseIcon","ControlsPlayIcon","_jsx","VideoPlayerIconButton","title","event","sxOverride","theme","breakpoints","down","width","height","fontSize","children"],"mappings":"gaAoCO,MAAMA,EAAwEC,EACnF,EAEIC,WACAC,oBACAC,qBACAC,YAAY,aACZC,aAAa,cACbC,UACAC,QACGC,GAELC,KAEA,MAAMC,UAAEA,EAASC,gBAAEA,GAAoBC,EAAkBX,GACnDY,EAAOH,EAAaP,GAAsBW,EAAsBZ,GAAqBa,EAE3F,OACEC,EAACC,EAAqB,CACpBR,IAAKA,EAAG,cACI,uBACZS,MAAOR,EAAYL,EAAaD,EAChCE,QAAUa,IACRb,IAAUa,GACVR,KAEFJ,GAAIa,EACDC,IAAK,CAEJ,CAACA,EAAMC,YAAYC,KAAK,OAAQ,CAC9BC,MAAO,OACPC,OAAQ,OACR,qBAAsB,CACpBC,SAAU,WAIhBnB,MAEEC,EAAImB,SAERX,EAACH,EAAI,CAAA,cAAcH,EAAY,uBAAyB"}
@@ -0,0 +1,23 @@
1
+ import React, { ComponentType } from 'react';
2
+ import { SvgIconProps } from '@mui/material';
3
+ import { VideoPlayerIconButtonProps } from './VideoPlayerIconButton';
4
+ export interface VideoPlayerSkipButtonProps extends Omit<VideoPlayerIconButtonProps, 'title'> {
5
+ /**
6
+ * Tooltip and aria-label of the button
7
+ * @default Previous video or Next video based on direction
8
+ */
9
+ title?: string;
10
+ /**
11
+ * Direction of the skip
12
+ * @default next
13
+ */
14
+ direction?: 'previous' | 'next';
15
+ /**
16
+ * Custom component to be used for the icon
17
+ */
18
+ IconComponent?: ComponentType<SvgIconProps>;
19
+ }
20
+ /**
21
+ * Button that skips to the previous or next video
22
+ */
23
+ export declare const VideoPlayerSkipButton: React.FC<VideoPlayerSkipButtonProps>;
@@ -0,0 +1,2 @@
1
+ import{jsx as o}from"react/jsx-runtime";import{forwardRef as e}from"react";import{ControlsSkipPreviousIcon as t}from"../icon/stroke/ControlsSkipPreviousIcon.js";import{ControlsSkipNextIcon as i}from"../icon/stroke/ControlsSkipNextIcon.js";import{VideoPlayerIconButton as r}from"./VideoPlayerIconButton.js";const n=e(({direction:e="next",IconComponent:n,title:s,...c},p)=>{const d="previous"===e;return o(r,{ref:p,"data-testid":d?"VideoPlayerSkipPrevious":"VideoPlayerSkipNext",title:s??(d?"Previous video":"Next video"),...c,children:o(n??(d?t:i),{"data-testid":d?"VideoPlayerSkipPreviousIcon":"VideoPlayerSkipNextIcon"})})});export{n as VideoPlayerSkipButton};
2
+ //# sourceMappingURL=VideoPlayerSkipButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoPlayerSkipButton.js","sources":["../../../src/components/videoPlayer/VideoPlayerSkipButton.tsx"],"sourcesContent":["import React, { ComponentType, forwardRef } from 'react';\nimport { SvgIconProps } from '@mui/material';\nimport { ControlsSkipPreviousIcon } from '@/src/components/icon/stroke/ControlsSkipPreviousIcon';\nimport { ControlsSkipNextIcon } from '@/src/components/icon/stroke/ControlsSkipNextIcon';\nimport { VideoPlayerIconButton, VideoPlayerIconButtonProps } from './VideoPlayerIconButton';\n\nexport interface VideoPlayerSkipButtonProps extends Omit<VideoPlayerIconButtonProps, 'title'> {\n /**\n * Tooltip and aria-label of the button\n * @default Previous video or Next video based on direction\n */\n title?: string;\n /**\n * Direction of the skip\n * @default next\n */\n direction?: 'previous' | 'next';\n /**\n * Custom component to be used for the icon\n */\n IconComponent?: ComponentType<SvgIconProps>;\n}\n\n/**\n * Button that skips to the previous or next video\n */\nexport const VideoPlayerSkipButton: React.FC<VideoPlayerSkipButtonProps> = forwardRef(\n ({ direction = 'next', IconComponent, title, ...rest }, ref) => {\n const isPrevious = direction === 'previous';\n const Icon = IconComponent ?? (isPrevious ? ControlsSkipPreviousIcon : ControlsSkipNextIcon);\n\n return (\n <VideoPlayerIconButton\n ref={ref}\n data-testid={isPrevious ? 'VideoPlayerSkipPrevious' : 'VideoPlayerSkipNext'}\n title={title ?? (isPrevious ? 'Previous video' : 'Next video')}\n {...rest}\n >\n <Icon data-testid={isPrevious ? 'VideoPlayerSkipPreviousIcon' : 'VideoPlayerSkipNextIcon'} />\n </VideoPlayerIconButton>\n );\n },\n);\n"],"names":["VideoPlayerSkipButton","forwardRef","direction","IconComponent","title","rest","ref","isPrevious","_jsx","VideoPlayerIconButton","children","ControlsSkipPreviousIcon","ControlsSkipNextIcon"],"mappings":"wTA0BaA,EAA8DC,EACzE,EAAGC,YAAY,OAAQC,gBAAeC,WAAUC,GAAQC,KACtD,MAAMC,EAA2B,aAAdL,EAGnB,OACEM,EAACC,EAAqB,CACpBH,IAAKA,EAAG,cACKC,EAAa,0BAA4B,sBACtDH,MAAOA,IAAUG,EAAa,iBAAmB,iBAC7CF,EAAIK,SAERF,EATSL,IAAkBI,EAAaI,EAA2BC,GAS9D,CAAA,cAAcL,EAAa,8BAAgC"}
@@ -0,0 +1,12 @@
1
+ import React, { type RefObject } from 'react';
2
+ import { SliderProps } from '@mui/material';
3
+ export interface VideoPlayerSliderProps extends SliderProps {
4
+ /**
5
+ * Ref to the controlled <video> element
6
+ */
7
+ videoRef: RefObject<HTMLVideoElement>;
8
+ }
9
+ /**
10
+ * Seek slider showing the playback progress of the video
11
+ */
12
+ export declare const VideoPlayerSlider: React.FC<VideoPlayerSliderProps>;
@@ -0,0 +1,2 @@
1
+ import{jsx as e}from"react/jsx-runtime";import{forwardRef as r}from"react";import{Slider as o}from"@mui/material";import{sxOverride as i}from"../../utils/sxOverride/sxOverride.js";import{useVideoTime as a}from"../video/useVideoTime.js";import{useVideoPlayPause as t}from"../video/useVideoPlayPause.js";import{formatVideoTime as d}from"./formatVideoTime.js";const m=r(({videoRef:r,onChange:m,onKeyDown:n,sx:s,...l},u)=>{const{currentTime:p,duration:x,handleSeek:f}=a(r,{smooth:!0}),{handlePlayPause:h}=t(r);return e(o,{ref:u,"data-testid":"VideoPlayerSeekSlider",value:p,min:0,max:x||0,valueLabelDisplay:"off",onChange:(e,r,o)=>{m?.(e,r,o),f(r)},"aria-label":"Seek video",getAriaValueText:e=>d(e,x),onKeyDown:e=>{n?.(e)," "===e.key&&(e.preventDefault(),h())},sx:i({height:"4px",py:"6px","@media (pointer: coarse)":{py:"6px"},"& .MuiSlider-rail":{color:"common.white",borderRadius:"16px"},"& .MuiSlider-track":{color:"brand.secondary",borderRadius:"16px",transition:"none"},"& .MuiSlider-thumb":{width:"16px",height:"16px",borderRadius:"50%"}},s),...l})});export{m as VideoPlayerSlider};
2
+ //# sourceMappingURL=VideoPlayerSlider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoPlayerSlider.js","sources":["../../../src/components/videoPlayer/VideoPlayerSlider.tsx"],"sourcesContent":["import React, { forwardRef, type KeyboardEvent, type RefObject } from 'react';\nimport { Slider, SliderProps } from '@mui/material';\nimport { sxOverride } from '@/src/utils/sxOverride';\nimport { useVideoTime } from '@/src/components/video/useVideoTime';\nimport { useVideoPlayPause } from '@/src/components/video/useVideoPlayPause';\nimport { formatVideoTime } from './formatVideoTime';\n\nexport interface VideoPlayerSliderProps extends SliderProps {\n /**\n * Ref to the controlled <video> element\n */\n videoRef: RefObject<HTMLVideoElement>;\n}\n\n/**\n * Seek slider showing the playback progress of the video\n */\nexport const VideoPlayerSlider: React.FC<VideoPlayerSliderProps> = forwardRef(\n ({ videoRef, onChange, onKeyDown, sx, ...rest }, ref) => {\n const { currentTime, duration, handleSeek } = useVideoTime(videoRef, { smooth: true });\n const { handlePlayPause } = useVideoPlayPause(videoRef);\n\n const handleKeyDown = (event: KeyboardEvent<HTMLSpanElement>) => {\n onKeyDown?.(event);\n // space toggles playback like on the play button, keyboard users don't have to leave the slider\n if (event.key === ' ') {\n event.preventDefault();\n handlePlayPause();\n }\n };\n\n return (\n <Slider\n ref={ref}\n data-testid=\"VideoPlayerSeekSlider\"\n value={currentTime}\n min={0}\n max={duration || 0}\n valueLabelDisplay=\"off\"\n onChange={(event, newValue: number, activeThumb) => {\n onChange?.(event, newValue, activeThumb);\n handleSeek(newValue);\n }}\n aria-label=\"Seek video\"\n getAriaValueText={(value) => formatVideoTime(value, duration)}\n onKeyDown={handleKeyDown}\n sx={sxOverride(\n {\n height: '4px',\n // symmetric padding keeps the track centered and serves as its hitbox,\n // Figma sits the track directly on the toolbar, the space keeps icon buttons focus ring from overlapping the slider\n py: '6px',\n // the theme sets its padding again for touch devices, the plain py would lose to it there\n '@media (pointer: coarse)': {\n py: '6px',\n },\n '& .MuiSlider-rail': {\n color: 'common.white',\n borderRadius: '16px',\n },\n '& .MuiSlider-track': {\n color: 'brand.secondary',\n borderRadius: '16px',\n // updated every frame, the default width transition would only make it lag behind\n transition: 'none',\n },\n '& .MuiSlider-thumb': {\n width: '16px',\n height: '16px',\n borderRadius: '50%',\n },\n },\n sx,\n )}\n {...rest}\n />\n );\n },\n);\n"],"names":["VideoPlayerSlider","forwardRef","videoRef","onChange","onKeyDown","sx","rest","ref","currentTime","duration","handleSeek","useVideoTime","smooth","handlePlayPause","useVideoPlayPause","_jsx","Slider","value","min","max","valueLabelDisplay","event","newValue","activeThumb","getAriaValueText","formatVideoTime","key","preventDefault","sxOverride","height","py","color","borderRadius","transition","width"],"mappings":"2WAiBaA,EAAsDC,EACjE,EAAGC,WAAUC,WAAUC,YAAWC,QAAOC,GAAQC,KAC/C,MAAMC,YAAEA,EAAWC,SAAEA,EAAQC,WAAEA,GAAeC,EAAaT,EAAU,CAAEU,QAAQ,KACzEC,gBAAEA,GAAoBC,EAAkBZ,GAW9C,OACEa,EAACC,EAAM,CACLT,IAAKA,EAAG,cACI,wBACZU,MAAOT,EACPU,IAAK,EACLC,IAAKV,GAAY,EACjBW,kBAAkB,MAClBjB,SAAU,CAACkB,EAAOC,EAAkBC,KAClCpB,IAAWkB,EAAOC,EAAUC,GAC5Bb,EAAWY,IACZ,aACU,aACXE,iBAAmBP,GAAUQ,EAAgBR,EAAOR,GACpDL,UAvBmBiB,IACrBjB,IAAYiB,GAEM,MAAdA,EAAMK,MACRL,EAAMM,iBACNd,MAmBAR,GAAIuB,EACF,CACEC,OAAQ,MAGRC,GAAI,MAEJ,2BAA4B,CAC1BA,GAAI,OAEN,oBAAqB,CACnBC,MAAO,eACPC,aAAc,QAEhB,qBAAsB,CACpBD,MAAO,kBACPC,aAAc,OAEdC,WAAY,QAEd,qBAAsB,CACpBC,MAAO,OACPL,OAAQ,OACRG,aAAc,QAGlB3B,MAEEC"}
@@ -0,0 +1,31 @@
1
+ import React, { ComponentType, type RefObject } from 'react';
2
+ import { SvgIconProps } from '@mui/material';
3
+ import { VideoPlayerIconButtonProps } from './VideoPlayerIconButton';
4
+ export interface VideoPlayerSoundButtonProps extends Omit<VideoPlayerIconButtonProps, 'title'> {
5
+ /**
6
+ * Ref to the controlled <video> element
7
+ */
8
+ videoRef: RefObject<HTMLVideoElement>;
9
+ /**
10
+ * Custom component for the icon shown while the video is not muted
11
+ */
12
+ SoundIconComponent?: ComponentType<SvgIconProps>;
13
+ /**
14
+ * Custom component for the icon shown while the video is muted
15
+ */
16
+ MuteIconComponent?: ComponentType<SvgIconProps>;
17
+ /**
18
+ * Tooltip and aria-label while the video is not muted
19
+ * @default Mute video
20
+ */
21
+ muteTitle?: string;
22
+ /**
23
+ * Tooltip and aria-label while the video is muted
24
+ * @default Unmute video
25
+ */
26
+ unmuteTitle?: string;
27
+ }
28
+ /**
29
+ * Button that toggles mute of the video
30
+ */
31
+ export declare const VideoPlayerSoundButton: React.FC<VideoPlayerSoundButtonProps>;
@@ -0,0 +1,2 @@
1
+ import{jsx as o}from"react/jsx-runtime";import{forwardRef as e}from"react";import{AudioMidIcon as t}from"../icon/stroke/AudioMidIcon.js";import{AudioMuteIcon as i}from"../icon/stroke/AudioMuteIcon.js";import{useVideoSoundControls as n}from"../video/useVideoSoundControls.js";import{VideoPlayerIconButton as r}from"./VideoPlayerIconButton.js";const d=e(({videoRef:e,SoundIconComponent:d,MuteIconComponent:u,muteTitle:m="Mute video",unmuteTitle:c="Unmute video",onClick:s,...l},a)=>{const{isMuted:p,handleMuteToggle:f}=n(e);return o(r,{ref:a,"data-testid":"VideoPlayerSound",title:p?c:m,onClick:o=>{s?.(o),f()},...l,children:o(p?u??i:d??t,{"data-testid":p?"VideoPlayerMuteIcon":"VideoPlayerSoundIcon"})})});export{d as VideoPlayerSoundButton};
2
+ //# sourceMappingURL=VideoPlayerSoundButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoPlayerSoundButton.js","sources":["../../../src/components/videoPlayer/VideoPlayerSoundButton.tsx"],"sourcesContent":["import React, { ComponentType, forwardRef, type MouseEvent, type RefObject } from 'react';\nimport { SvgIconProps } from '@mui/material';\nimport { AudioMidIcon } from '@/src/components/icon/stroke/AudioMidIcon';\nimport { AudioMuteIcon } from '@/src/components/icon/stroke/AudioMuteIcon';\nimport { useVideoSoundControls } from '@/src/components/video/useVideoSoundControls';\nimport { VideoPlayerIconButton, VideoPlayerIconButtonProps } from './VideoPlayerIconButton';\n\nexport interface VideoPlayerSoundButtonProps extends Omit<VideoPlayerIconButtonProps, 'title'> {\n /**\n * Ref to the controlled <video> element\n */\n videoRef: RefObject<HTMLVideoElement>;\n /**\n * Custom component for the icon shown while the video is not muted\n */\n SoundIconComponent?: ComponentType<SvgIconProps>;\n /**\n * Custom component for the icon shown while the video is muted\n */\n MuteIconComponent?: ComponentType<SvgIconProps>;\n /**\n * Tooltip and aria-label while the video is not muted\n * @default Mute video\n */\n muteTitle?: string;\n /**\n * Tooltip and aria-label while the video is muted\n * @default Unmute video\n */\n unmuteTitle?: string;\n}\n\n/**\n * Button that toggles mute of the video\n */\nexport const VideoPlayerSoundButton: React.FC<VideoPlayerSoundButtonProps> = forwardRef(\n (\n {\n videoRef,\n SoundIconComponent,\n MuteIconComponent,\n muteTitle = 'Mute video',\n unmuteTitle = 'Unmute video',\n onClick,\n ...rest\n },\n ref,\n ) => {\n const { isMuted, handleMuteToggle } = useVideoSoundControls(videoRef);\n const Icon = isMuted ? (MuteIconComponent ?? AudioMuteIcon) : (SoundIconComponent ?? AudioMidIcon);\n\n return (\n <VideoPlayerIconButton\n ref={ref}\n data-testid=\"VideoPlayerSound\"\n title={isMuted ? unmuteTitle : muteTitle}\n onClick={(event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n handleMuteToggle();\n }}\n {...rest}\n >\n <Icon data-testid={isMuted ? 'VideoPlayerMuteIcon' : 'VideoPlayerSoundIcon'} />\n </VideoPlayerIconButton>\n );\n },\n);\n"],"names":["VideoPlayerSoundButton","forwardRef","videoRef","SoundIconComponent","MuteIconComponent","muteTitle","unmuteTitle","onClick","rest","ref","isMuted","handleMuteToggle","useVideoSoundControls","_jsx","VideoPlayerIconButton","title","event","children","AudioMuteIcon","AudioMidIcon"],"mappings":"sVAmCO,MAAMA,EAAgEC,EAC3E,EAEIC,WACAC,qBACAC,oBACAC,YAAY,aACZC,cAAc,eACdC,aACGC,GAELC,KAEA,MAAMC,QAAEA,EAAOC,iBAAEA,GAAqBC,EAAsBV,GAG5D,OACEW,EAACC,EAAqB,CACpBL,IAAKA,EAAG,cACI,mBACZM,MAAOL,EAAUJ,EAAcD,EAC/BE,QAAUS,IACRT,IAAUS,GACVL,QAEEH,EAAIS,SAERJ,EAbSH,EAAWN,GAAqBc,EAAkBf,GAAsBgB,EAa5E,CAAA,cAAcT,EAAU,sBAAwB"}
@@ -0,0 +1,17 @@
1
+ import React, { ElementType, type ReactNode, type RefObject } from 'react';
2
+ import { TypographyProps } from '@mui/material';
3
+ export interface VideoPlayerTimeProps extends TypographyProps<ElementType> {
4
+ /**
5
+ * Ref to the controlled <video> element
6
+ */
7
+ videoRef: RefObject<HTMLVideoElement>;
8
+ /**
9
+ * Formats the label from current time and duration in seconds
10
+ * @default `m:ss / m:ss`, or `h:mm:ss / h:mm:ss` for videos of one hour and more
11
+ */
12
+ formatTime?: (currentTime: number, duration: number) => ReactNode;
13
+ }
14
+ /**
15
+ * Current time and duration of the video
16
+ */
17
+ export declare const VideoPlayerTime: React.FC<VideoPlayerTimeProps>;
@@ -0,0 +1,2 @@
1
+ import{jsx as e}from"react/jsx-runtime";import{forwardRef as t}from"react";import{Typography as i}from"@mui/material";import{sxOverride as r}from"../../utils/sxOverride/sxOverride.js";import{useVideoTime as o}from"../video/useVideoTime.js";import{formatVideoTime as m}from"./formatVideoTime.js";const n=(e,t)=>`${m(e,t)} / ${m(t)}`,s=t(({videoRef:t,formatTime:m=n,sx:s,...a},p)=>{const{currentTime:x,duration:d}=o(t);return e(i,{ref:p,"data-testid":"VideoPlayerTime",component:"span",variant:"body",sx:r({display:"flex",alignItems:"center",justifyContent:"flex-start",minHeight:"44px",color:"common.white",whiteSpace:"nowrap",userSelect:"none",fontWeight:{xs:"400"},fontSize:{xs:"12px",md:"16px"},lineHeight:{xs:"12px",md:"21px"},letterSpacing:{xs:"0.002em"}},s),...a,children:m(x,d??0)})});export{s as VideoPlayerTime};
2
+ //# sourceMappingURL=VideoPlayerTime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoPlayerTime.js","sources":["../../../src/components/videoPlayer/VideoPlayerTime.tsx"],"sourcesContent":["import React, { ElementType, forwardRef, type ReactNode, type RefObject } from 'react';\nimport { Typography, TypographyProps } from '@mui/material';\nimport { sxOverride } from '@/src/utils/sxOverride';\nimport { useVideoTime } from '@/src/components/video/useVideoTime';\nimport { formatVideoTime } from './formatVideoTime';\n\nexport interface VideoPlayerTimeProps extends TypographyProps<ElementType> {\n /**\n * Ref to the controlled <video> element\n */\n videoRef: RefObject<HTMLVideoElement>;\n /**\n * Formats the label from current time and duration in seconds\n * @default `m:ss / m:ss`, or `h:mm:ss / h:mm:ss` for videos of one hour and more\n */\n formatTime?: (currentTime: number, duration: number) => ReactNode;\n}\n\n/**\n * Formats current time and duration with the same segments\n */\nconst defaultFormatTime = (currentTime: number, duration: number): string =>\n `${formatVideoTime(currentTime, duration)} / ${formatVideoTime(duration)}`;\n\n/**\n * Current time and duration of the video\n */\nexport const VideoPlayerTime: React.FC<VideoPlayerTimeProps> = forwardRef<HTMLSpanElement, VideoPlayerTimeProps>(\n ({ videoRef, formatTime = defaultFormatTime, sx, ...rest }, ref) => {\n const { currentTime, duration } = useVideoTime(videoRef);\n\n return (\n <Typography\n ref={ref}\n data-testid=\"VideoPlayerTime\"\n component=\"span\"\n variant=\"body\"\n sx={sxOverride(\n {\n // same height as the icon buttons, keeps the toolbar height when the label is alone\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-start',\n minHeight: '44px',\n color: 'common.white',\n whiteSpace: 'nowrap',\n userSelect: 'none',\n // custom font according to Figma\n fontWeight: { xs: '400' },\n fontSize: { xs: '12px', md: '16px' },\n lineHeight: { xs: '12px', md: '21px' },\n letterSpacing: { xs: '0.002em' },\n },\n sx,\n )}\n {...rest}\n >\n {formatTime(currentTime, duration ?? 0)}\n </Typography>\n );\n },\n);\n"],"names":["defaultFormatTime","currentTime","duration","formatVideoTime","VideoPlayerTime","forwardRef","videoRef","formatTime","sx","rest","ref","useVideoTime","_jsx","Typography","component","variant","sxOverride","display","alignItems","justifyContent","minHeight","color","whiteSpace","userSelect","fontWeight","xs","fontSize","md","lineHeight","letterSpacing"],"mappings":"uSAqBA,MAAMA,EAAoB,CAACC,EAAqBC,IAC9C,GAAGC,EAAgBF,EAAaC,QAAeC,EAAgBD,KAKpDE,EAAkDC,EAC7D,EAAGC,WAAUC,aAAaP,EAAmBQ,QAAOC,GAAQC,KAC1D,MAAMT,YAAEA,EAAWC,SAAEA,GAAaS,EAAaL,GAE/C,OACEM,EAACC,EAAU,CACTH,IAAKA,gBACO,kBACZI,UAAU,OACVC,QAAQ,OACRP,GAAIQ,EACF,CAEEC,QAAS,OACTC,WAAY,SACZC,eAAgB,aAChBC,UAAW,OACXC,MAAO,eACPC,WAAY,SACZC,WAAY,OAEZC,WAAY,CAAEC,GAAI,OAClBC,SAAU,CAAED,GAAI,OAAQE,GAAI,QAC5BC,WAAY,CAAEH,GAAI,OAAQE,GAAI,QAC9BE,cAAe,CAAEJ,GAAI,YAEvBjB,MAEEC,WAEHF,EAAWN,EAAaC,GAAY"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Formats seconds as `m:ss`, or `h:mm:ss` when the time or the provided duration reaches one hour,
3
+ * falling back to zero for negative/non-finite input
4
+ */
5
+ export declare const formatVideoTime: (seconds: number, duration?: number) => string;
@@ -0,0 +1,2 @@
1
+ const t=3600,o=(o,r)=>{const a=Number.isFinite(o)&&o>0?Math.floor(o):0,n=(""+a%60).padStart(2,"0");if(Math.max(a,r||0)>=t){const o=`${Math.floor(a%t/60)}`.padStart(2,"0");return`${Math.floor(a/t)}:${o}:${n}`}return`${Math.floor(a/60)}:${n}`};export{o as formatVideoTime};
2
+ //# sourceMappingURL=formatVideoTime.js.map