@therealtinhtute/baroiplayer 1.2.0 → 2.0.0-beta.1

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 (305) hide show
  1. package/README.md +91 -73
  2. package/dist/components/icons/index.d.ts +36 -0
  3. package/dist/components/icons/index.d.ts.map +1 -0
  4. package/dist/components/icons/svg-icons/ArrowLeftIcon.d.ts +4 -0
  5. package/dist/components/icons/svg-icons/ArrowLeftIcon.d.ts.map +1 -0
  6. package/dist/components/icons/svg-icons/ArrowRightIcon.d.ts +5 -0
  7. package/dist/components/icons/svg-icons/ArrowRightIcon.d.ts.map +1 -0
  8. package/dist/components/icons/svg-icons/AudioIcon.d.ts +5 -0
  9. package/dist/components/icons/svg-icons/AudioIcon.d.ts.map +1 -0
  10. package/dist/components/icons/svg-icons/BackwardIcon.d.ts +5 -0
  11. package/dist/components/icons/svg-icons/BackwardIcon.d.ts.map +1 -0
  12. package/dist/components/icons/svg-icons/CameraIcon.d.ts +5 -0
  13. package/dist/components/icons/svg-icons/CameraIcon.d.ts.map +1 -0
  14. package/dist/components/icons/svg-icons/CheckIcon.d.ts +5 -0
  15. package/dist/components/icons/svg-icons/CheckIcon.d.ts.map +1 -0
  16. package/dist/components/icons/svg-icons/EnablePiPIcon.d.ts +4 -0
  17. package/dist/components/icons/svg-icons/EnablePiPIcon.d.ts.map +1 -0
  18. package/dist/components/icons/svg-icons/ForwardIcon.d.ts +5 -0
  19. package/dist/components/icons/svg-icons/ForwardIcon.d.ts.map +1 -0
  20. package/dist/components/icons/svg-icons/FullscreenEnterIcon.d.ts +5 -0
  21. package/dist/components/icons/svg-icons/FullscreenEnterIcon.d.ts.map +1 -0
  22. package/dist/components/icons/svg-icons/FullscreenExitIcon.d.ts +5 -0
  23. package/dist/components/icons/svg-icons/FullscreenExitIcon.d.ts.map +1 -0
  24. package/dist/components/icons/svg-icons/LoadingIcon.d.ts +5 -0
  25. package/dist/components/icons/svg-icons/LoadingIcon.d.ts.map +1 -0
  26. package/dist/components/icons/svg-icons/PauseIcon.d.ts +5 -0
  27. package/dist/components/icons/svg-icons/PauseIcon.d.ts.map +1 -0
  28. package/dist/components/icons/svg-icons/PlayIcon.d.ts +5 -0
  29. package/dist/components/icons/svg-icons/PlayIcon.d.ts.map +1 -0
  30. package/dist/components/icons/svg-icons/PlaybackSpeedIcon.d.ts +5 -0
  31. package/dist/components/icons/svg-icons/PlaybackSpeedIcon.d.ts.map +1 -0
  32. package/dist/components/icons/svg-icons/QualityIcon.d.ts +5 -0
  33. package/dist/components/icons/svg-icons/QualityIcon.d.ts.map +1 -0
  34. package/dist/components/icons/svg-icons/SettingsIcon.d.ts +5 -0
  35. package/dist/components/icons/svg-icons/SettingsIcon.d.ts.map +1 -0
  36. package/dist/components/icons/svg-icons/SliderIcon.d.ts +5 -0
  37. package/dist/components/icons/svg-icons/SliderIcon.d.ts.map +1 -0
  38. package/dist/components/icons/svg-icons/SubtitleIcon.d.ts +5 -0
  39. package/dist/components/icons/svg-icons/SubtitleIcon.d.ts.map +1 -0
  40. package/dist/components/icons/svg-icons/SubtitleOffIcon.d.ts +5 -0
  41. package/dist/components/icons/svg-icons/SubtitleOffIcon.d.ts.map +1 -0
  42. package/dist/components/icons/svg-icons/UnPiPIcon.d.ts +4 -0
  43. package/dist/components/icons/svg-icons/UnPiPIcon.d.ts.map +1 -0
  44. package/dist/components/icons/svg-icons/VolumeMutedIcon.d.ts +5 -0
  45. package/dist/components/icons/svg-icons/VolumeMutedIcon.d.ts.map +1 -0
  46. package/dist/components/icons/svg-icons/VolumeOneIcon.d.ts +5 -0
  47. package/dist/components/icons/svg-icons/VolumeOneIcon.d.ts.map +1 -0
  48. package/dist/components/icons/svg-icons/VolumeThreeIcon.d.ts +5 -0
  49. package/dist/components/icons/svg-icons/VolumeThreeIcon.d.ts.map +1 -0
  50. package/dist/components/icons/svg-icons/VolumeTwoIcon.d.ts +5 -0
  51. package/dist/components/icons/svg-icons/VolumeTwoIcon.d.ts.map +1 -0
  52. package/dist/components/variants/gradient/gradient-audio.d.ts +13 -0
  53. package/dist/components/variants/gradient/gradient-audio.d.ts.map +1 -0
  54. package/dist/components/variants/gradient/gradient-controls.d.ts +4 -0
  55. package/dist/components/variants/gradient/gradient-controls.d.ts.map +1 -0
  56. package/dist/components/variants/gradient/gradient-glyphs.d.ts +30 -0
  57. package/dist/components/variants/gradient/gradient-glyphs.d.ts.map +1 -0
  58. package/dist/components/variants/gradient/gradient-video.d.ts +16 -0
  59. package/dist/components/variants/gradient/gradient-video.d.ts.map +1 -0
  60. package/dist/index.css +1 -1
  61. package/dist/index.d.ts +5 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +2 -112
  64. package/dist/index.js.map +1 -1
  65. package/dist/index.mjs +786 -6271
  66. package/dist/index.mjs.map +1 -1
  67. package/dist/package.json +3 -0
  68. package/package.json +110 -108
  69. package/src/components/variants/gradient/gradient-audio.tsx +47 -0
  70. package/src/components/variants/gradient/gradient-controls.tsx +254 -0
  71. package/src/components/variants/gradient/gradient-glyphs.test.tsx +69 -0
  72. package/src/components/variants/gradient/gradient-glyphs.tsx +129 -0
  73. package/src/components/variants/gradient/gradient-skin.css +211 -0
  74. package/src/components/variants/gradient/gradient-video.tsx +70 -0
  75. package/src/index.ts +5 -198
  76. package/src/test/accessibility-utils.ts +0 -59
  77. package/dist/context/media.js +0 -2
  78. package/dist/context/media.js.map +0 -1
  79. package/dist/context/media.mjs +0 -15
  80. package/dist/context/media.mjs.map +0 -1
  81. package/dist/context/store.js +0 -2
  82. package/dist/context/store.js.map +0 -1
  83. package/dist/context/store.mjs +0 -5
  84. package/dist/context/store.mjs.map +0 -1
  85. package/dist/context-BYwDoSRX.js +0 -1172
  86. package/dist/context-BYwDoSRX.js.map +0 -1
  87. package/dist/context-eNS62_ac.cjs +0 -23
  88. package/dist/context-eNS62_ac.cjs.map +0 -1
  89. package/dist/core-events-B1iM2F46.cjs +0 -2
  90. package/dist/core-events-B1iM2F46.cjs.map +0 -1
  91. package/dist/core-events-DunPHKRE.js +0 -484
  92. package/dist/core-events-DunPHKRE.js.map +0 -1
  93. package/dist/core-plugins-By-4-kGs.cjs +0 -2
  94. package/dist/core-plugins-By-4-kGs.cjs.map +0 -1
  95. package/dist/core-plugins-DSBWcTuX.js +0 -821
  96. package/dist/core-plugins-DSBWcTuX.js.map +0 -1
  97. package/dist/core.js +0 -37
  98. package/dist/core.js.map +0 -1
  99. package/dist/core.mjs +0 -1233
  100. package/dist/core.mjs.map +0 -1
  101. package/dist/enhanced-components-B_l3cist.js +0 -1142
  102. package/dist/enhanced-components-B_l3cist.js.map +0 -1
  103. package/dist/enhanced-components-BspFs9OO.cjs +0 -2
  104. package/dist/enhanced-components-BspFs9OO.cjs.map +0 -1
  105. package/dist/hooks-BXwI8QG6.cjs +0 -4
  106. package/dist/hooks-BXwI8QG6.cjs.map +0 -1
  107. package/dist/hooks-Bpi-jDiO.js +0 -1816
  108. package/dist/hooks-Bpi-jDiO.js.map +0 -1
  109. package/dist/minimal-components-C4z900Ro.js +0 -1926
  110. package/dist/minimal-components-C4z900Ro.js.map +0 -1
  111. package/dist/minimal-components-v4qBp6jv.cjs +0 -2
  112. package/dist/minimal-components-v4qBp6jv.cjs.map +0 -1
  113. package/dist/minimal-components.css +0 -1
  114. package/dist/mona-loading.gif +0 -0
  115. package/dist/performance-monitor-C5k6FDXw.js +0 -301
  116. package/dist/performance-monitor-C5k6FDXw.js.map +0 -1
  117. package/dist/performance-monitor-lJmuUjQQ.cjs +0 -2
  118. package/dist/performance-monitor-lJmuUjQQ.cjs.map +0 -1
  119. package/dist/utils-CFOue_9K.cjs +0 -9
  120. package/dist/utils-CFOue_9K.cjs.map +0 -1
  121. package/dist/utils-Dzpl2ArK.js +0 -2844
  122. package/dist/utils-Dzpl2ArK.js.map +0 -1
  123. package/dist/utils.js +0 -2
  124. package/dist/utils.js.map +0 -1
  125. package/dist/utils.mjs +0 -11
  126. package/dist/utils.mjs.map +0 -1
  127. package/src/adapters/videojs-adapter.tsx +0 -470
  128. package/src/assets/mona-loading.gif +0 -0
  129. package/src/components/AnimateLoading.tsx +0 -107
  130. package/src/components/LoadingState.tsx +0 -239
  131. package/src/components/__tests__/media-player-accessibility.test.tsx +0 -510
  132. package/src/components/__tests__/media-player-react19.test.tsx +0 -457
  133. package/src/components/accessibility/keyboard-help-overlay.tsx +0 -207
  134. package/src/components/audio-player.tsx +0 -85
  135. package/src/components/basic/index.ts +0 -37
  136. package/src/components/enhanced/advanced-features.tsx +0 -311
  137. package/src/components/enhanced/debug-panel.tsx +0 -448
  138. package/src/components/enhanced/enhanced-controls.tsx +0 -597
  139. package/src/components/enhanced/enhanced-media-player.tsx +0 -566
  140. package/src/components/enhanced/error-handling.tsx +0 -338
  141. package/src/components/enhanced/index.ts +0 -39
  142. package/src/components/enhanced/media-player-enhanced.tsx +0 -383
  143. package/src/components/examples/basic-video-player.tsx +0 -50
  144. package/src/components/examples/custom-controls-example.tsx +0 -63
  145. package/src/components/examples/enhanced-controls-example.tsx +0 -100
  146. package/src/components/examples/enhanced-media-player-example.tsx +0 -302
  147. package/src/components/examples/loading-states-demo.tsx +0 -142
  148. package/src/components/examples/react-19-demo.tsx +0 -353
  149. package/src/components/examples/volume-orientation-demo.tsx +0 -106
  150. package/src/components/icon-demo.tsx +0 -196
  151. package/src/components/legacy.tsx +0 -87
  152. package/src/components/media-metadata-display.tsx +0 -99
  153. package/src/components/media-player-audio.tsx +0 -39
  154. package/src/components/media-player-controls.tsx +0 -223
  155. package/src/components/media-player-error.tsx +0 -163
  156. package/src/components/media-player-fullscreen.tsx +0 -109
  157. package/src/components/media-player-hls.tsx +0 -111
  158. package/src/components/media-player-loading.tsx +0 -76
  159. package/src/components/media-player-play.tsx +0 -75
  160. package/src/components/media-player-root.tsx +0 -338
  161. package/src/components/media-player-seek.tsx +0 -168
  162. package/src/components/media-player-time.tsx +0 -99
  163. package/src/components/media-player-tooltip.tsx +0 -58
  164. package/src/components/media-player-video.tsx +0 -54
  165. package/src/components/media-player-volume.tsx +0 -155
  166. package/src/components/media-player.tsx +0 -292
  167. package/src/components/media-suspense.tsx +0 -344
  168. package/src/components/player-settings-form.tsx +0 -158
  169. package/src/components/react-player-wrapper.tsx +0 -651
  170. package/src/components/simple-video-player.tsx +0 -62
  171. package/src/components/ui/blur-poster.tsx +0 -93
  172. package/src/components/ui/empty-state.tsx +0 -91
  173. package/src/components/ui/enhanced-seek-bar.tsx +0 -254
  174. package/src/components/ui/error-state.tsx +0 -124
  175. package/src/components/ui/fullscreen-button.tsx +0 -81
  176. package/src/components/ui/loading-skeleton.tsx +0 -107
  177. package/src/components/ui/media-resource-preloader.tsx +0 -458
  178. package/src/components/ui/offline-message.tsx +0 -98
  179. package/src/components/ui/play-button.tsx +0 -99
  180. package/src/components/ui/seek-bar.tsx +0 -191
  181. package/src/components/ui/time-display.tsx +0 -61
  182. package/src/components/ui/volume-control.tsx +0 -190
  183. package/src/components/unified/base-media-player.tsx +0 -252
  184. package/src/components/unified/media-player.tsx +0 -75
  185. package/src/components/variants/minimal/AccessibleMinimalPlayer.tsx +0 -587
  186. package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.tsx +0 -573
  187. package/src/components/variants/minimal/MinimalControls.tsx +0 -124
  188. package/src/components/variants/minimal/MinimalLoading.tsx +0 -28
  189. package/src/components/variants/minimal/MinimalMediaPlayer.tsx +0 -318
  190. package/src/components/variants/minimal/MinimalOverlay.tsx +0 -58
  191. package/src/components/variants/minimal/MinimalPlayButton.tsx +0 -56
  192. package/src/components/variants/minimal/MinimalSeekBar.tsx +0 -140
  193. package/src/components/variants/minimal/MinimalVolumeControl.tsx +0 -75
  194. package/src/components/variants/minimal/SimpleMinimalPlayer.tsx +0 -206
  195. package/src/components/variants/minimal/components/CenterPlayButton.tsx +0 -22
  196. package/src/components/variants/minimal/components/ControlBar.tsx +0 -142
  197. package/src/components/variants/minimal/components/EnhancedSettingsMenu.tsx +0 -412
  198. package/src/components/variants/minimal/components/PlaybackControls.tsx +0 -46
  199. package/src/components/variants/minimal/components/RightControls.tsx +0 -164
  200. package/src/components/variants/minimal/components/SeekBar.tsx +0 -127
  201. package/src/components/variants/minimal/components/SettingsDropdown.tsx +0 -68
  202. package/src/components/variants/minimal/components/SubtitleDisplay.tsx +0 -21
  203. package/src/components/variants/minimal/components/TimeDisplay.tsx +0 -15
  204. package/src/components/variants/minimal/components/VideoElement.tsx +0 -33
  205. package/src/components/variants/minimal/components/VolumeControl.tsx +0 -220
  206. package/src/components/variants/minimal/index.ts +0 -23
  207. package/src/components/video-player.tsx +0 -100
  208. package/src/context/__tests__/media-store.test.ts +0 -509
  209. package/src/context/error-handling.ts +0 -398
  210. package/src/context/media-context.tsx +0 -254
  211. package/src/context/media-provider.tsx +0 -264
  212. package/src/context/media-store.ts +0 -387
  213. package/src/context/persistence.ts +0 -462
  214. package/src/core/events/event-system.ts +0 -448
  215. package/src/core/events/hooks.ts +0 -325
  216. package/src/core/events/index.ts +0 -22
  217. package/src/core/events/middleware.ts +0 -286
  218. package/src/core/index.ts +0 -22
  219. package/src/core/optimization/bundle-optimizer.tsx +0 -312
  220. package/src/core/performance/cicd.ts +0 -98
  221. package/src/core/performance/index.ts +0 -38
  222. package/src/core/performance/media-loading-optimizer.ts +0 -544
  223. package/src/core/performance/performance-budgets.ts +0 -437
  224. package/src/core/performance/performance-monitor.tsx +0 -488
  225. package/src/core/performance/performance-testing.ts +0 -461
  226. package/src/core/plugins/__tests__/registry.test.ts +0 -595
  227. package/src/core/plugins/base-plugin.ts +0 -225
  228. package/src/core/plugins/enhanced-plugin-system.ts +0 -435
  229. package/src/core/plugins/examples/analytics-plugin.ts +0 -241
  230. package/src/core/plugins/index.ts +0 -39
  231. package/src/core/plugins/registry.ts +0 -546
  232. package/src/core/plugins/types.ts +0 -169
  233. package/src/core/plugins/utils.ts +0 -317
  234. package/src/core/progressive-loading.tsx +0 -331
  235. package/src/core/providers/enhanced-hls-provider.ts +0 -307
  236. package/src/core/providers/lazy-provider.tsx +0 -14
  237. package/src/core/providers/service-provider.tsx +0 -164
  238. package/src/core/utils.tsx +0 -34
  239. package/src/features/media-session/media-session-manager.ts +0 -411
  240. package/src/features/picture-in-picture/pip-manager.ts +0 -428
  241. package/src/features/playlist/playlist-manager.ts +0 -626
  242. package/src/features/subtitles/subtitle-manager.ts +0 -435
  243. package/src/features/subtitles/subtitle-parser.ts +0 -284
  244. package/src/features/thumbnails/thumbnail-generator.ts +0 -528
  245. package/src/hooks/__tests__/currentTime-fix.test.ts +0 -149
  246. package/src/hooks/__tests__/use-media-player.test.ts +0 -712
  247. package/src/hooks/__tests__/use-media-state.test.tsx +0 -316
  248. package/src/hooks/accessibility/index.ts +0 -27
  249. package/src/hooks/accessibility/use-accessibility-preferences.ts +0 -190
  250. package/src/hooks/accessibility/use-focus-management.ts +0 -183
  251. package/src/hooks/accessibility/use-keyboard-shortcuts.ts +0 -152
  252. package/src/hooks/accessibility/use-screen-reader.ts +0 -212
  253. package/src/hooks/core/index.ts +0 -47
  254. package/src/hooks/legacy.ts +0 -21
  255. package/src/hooks/use-buffer-health.ts +0 -218
  256. package/src/hooks/use-enhanced-media-player.ts +0 -575
  257. package/src/hooks/use-focus-trap.tsx +0 -162
  258. package/src/hooks/use-intelligent-preloading.ts +0 -387
  259. package/src/hooks/use-keyboard-controls.ts +0 -115
  260. package/src/hooks/use-keyboard-shortcuts.ts +0 -255
  261. package/src/hooks/use-media-actions.ts +0 -184
  262. package/src/hooks/use-media-metadata.ts +0 -91
  263. package/src/hooks/use-media-optimistic.ts +0 -264
  264. package/src/hooks/use-media-player.ts +0 -343
  265. package/src/hooks/use-media-state.ts +0 -194
  266. package/src/hooks/use-memory-optimization.ts +0 -360
  267. package/src/hooks/use-network-status.ts +0 -124
  268. package/src/hooks/use-optimistic-controls.ts +0 -95
  269. package/src/hooks/use-optimized-media.ts +0 -283
  270. package/src/hooks/use-smart-preload.ts +0 -229
  271. package/src/hooks/use-touch-gestures.ts +0 -461
  272. package/src/hooks/useEnhancedSubtitles.ts +0 -258
  273. package/src/hooks/useKeyboardShortcuts.ts +0 -106
  274. package/src/hooks/useMediaControls.ts +0 -52
  275. package/src/hooks/useScreenshot.ts +0 -61
  276. package/src/hooks/useSubtitles.ts +0 -91
  277. package/src/hooks/useVideoPlayer.ts +0 -278
  278. package/src/icons/components/FullscreenIcon.tsx +0 -36
  279. package/src/icons/components/SettingsIcon.tsx +0 -37
  280. package/src/icons/components/animated/LoadingIcon.tsx +0 -27
  281. package/src/icons/components/animated/PlayPauseIcon.tsx +0 -42
  282. package/src/icons/components/media/PauseIcon.tsx +0 -38
  283. package/src/icons/components/media/PlayIcon.tsx +0 -37
  284. package/src/icons/components/volume/VolumeIcon.tsx +0 -38
  285. package/src/icons/components/volume/VolumeOffIcon.tsx +0 -38
  286. package/src/icons/index.ts +0 -56
  287. package/src/icons/provider.tsx +0 -58
  288. package/src/icons/types.ts +0 -60
  289. package/src/index-enhanced.ts +0 -35
  290. package/src/index-legacy.ts +0 -324
  291. package/src/index.css +0 -102
  292. package/src/lib/__tests__/async-utils.test.ts +0 -291
  293. package/src/lib/async-utils.ts +0 -194
  294. package/src/lib/deprecation.ts +0 -51
  295. package/src/lib/format-time.ts +0 -37
  296. package/src/lib/index.ts +0 -4
  297. package/src/lib/utils.ts +0 -6
  298. package/src/styles/globals.css +0 -462
  299. package/src/styles/minimal-player.css +0 -621
  300. package/src/styles/pixel-art.css +0 -41
  301. package/src/styles/videojs.css +0 -100
  302. package/src/types/events.ts +0 -47
  303. package/src/types/formats.ts +0 -79
  304. package/src/types/index.ts +0 -203
  305. package/src/types/videojs-plugins.d.ts +0 -14
@@ -1,412 +0,0 @@
1
- import React, { memo, useState, useCallback, useEffect } from "react"
2
- import { cn } from "../../../../lib/utils"
3
- import { defaultMinimalIcons } from "../../../icons"
4
-
5
- export interface SubtitleTrack {
6
- id: string
7
- label: string
8
- language?: string
9
- src?: string
10
- }
11
-
12
- interface EnhancedSettingsMenuProps {
13
- showSettings: boolean
14
- playbackRate: number
15
- subtitlesEnabled: boolean
16
- subtitleTracks: SubtitleTrack[]
17
- currentSubtitleTrack?: string
18
- subtitleFontSize: "small" | "medium" | "large"
19
- hasSubtitles: boolean
20
- subtitleLoadError?: boolean
21
- onToggleSettings: () => void
22
- onChangePlaybackRate: (rate: number) => void
23
- onToggleSubtitles: () => void
24
- onSelectSubtitleTrack?: (trackId: string | null) => void
25
- onChangeSubtitleFontSize: (size: "small" | "medium" | "large") => void
26
- }
27
-
28
- type MenuView = "main" | "subtitles" | "fontSize" | "speed"
29
-
30
- export const EnhancedSettingsMenu = function EnhancedSettingsMenu({
31
- showSettings,
32
- playbackRate,
33
- subtitlesEnabled,
34
- subtitleTracks,
35
- currentSubtitleTrack,
36
- subtitleFontSize = "medium",
37
- hasSubtitles,
38
- subtitleLoadError,
39
- onToggleSettings,
40
- onChangePlaybackRate,
41
- onToggleSubtitles,
42
- onSelectSubtitleTrack,
43
- onChangeSubtitleFontSize
44
- }: EnhancedSettingsMenuProps) {
45
- const [currentView, setCurrentView] = useState<MenuView>("main")
46
- const playbackRates = [0.5, 0.75, 1, 1.25, 1.5, 2]
47
- const fontSizes = [
48
- { value: "small", label: "Small", size: "12px" },
49
- { value: "medium", label: "Medium", size: "16px" },
50
- { value: "large", label: "Large", size: "20px" }
51
- ]
52
-
53
- // Reset to main menu when settings close
54
- useEffect(() => {
55
- if (!showSettings) {
56
- setCurrentView("main")
57
- }
58
- }, [showSettings])
59
-
60
- const handleSettingsClick = useCallback(
61
- (e: React.MouseEvent) => {
62
- e.stopPropagation()
63
- onToggleSettings()
64
- },
65
- [onToggleSettings]
66
- )
67
-
68
- const handleDropdownClick = useCallback((e: React.MouseEvent) => {
69
- e.stopPropagation()
70
- }, [])
71
-
72
- const handleBackClick = useCallback(() => {
73
- setCurrentView("main")
74
- }, [])
75
-
76
- const handleSelectSpeed = useCallback(
77
- (rate: number) => {
78
- onChangePlaybackRate(rate)
79
- setCurrentView("main")
80
- },
81
- [onChangePlaybackRate]
82
- )
83
-
84
- const handleSelectFontSize = useCallback(
85
- (size: "small" | "medium" | "large") => {
86
- onChangeSubtitleFontSize(size)
87
- setCurrentView("main")
88
- },
89
- [onChangeSubtitleFontSize]
90
- )
91
-
92
- const handleSelectSubtitle = useCallback(
93
- (trackId: string | null) => {
94
- if (trackId === null) {
95
- // Turn off subtitles
96
- if (subtitlesEnabled) {
97
- onToggleSubtitles()
98
- }
99
- } else {
100
- // Select track and enable if needed
101
- if (!subtitlesEnabled) {
102
- onToggleSubtitles()
103
- }
104
- onSelectSubtitleTrack?.(trackId)
105
- }
106
- setCurrentView("main")
107
- },
108
- [subtitlesEnabled, onToggleSubtitles, onSelectSubtitleTrack]
109
- )
110
-
111
- const renderMainMenu = () => (
112
- <>
113
- <div className="border-gray-700 border-b px-3 py-2 font-semibold text-gray-400 text-xs uppercase tracking-wider">
114
- Settings
115
- </div>
116
- <div className="py-1">
117
- {/* Subtitles Option */}
118
- <button
119
- className={cn(
120
- "flex w-full items-center justify-between px-3 py-2 text-left text-sm transition-colors hover:bg-gray-800",
121
- !hasSubtitles && "cursor-not-allowed opacity-50"
122
- )}
123
- onClick={() => hasSubtitles && setCurrentView("subtitles")}
124
- disabled={!hasSubtitles}>
125
- <div className="flex items-center gap-2">
126
- {defaultMinimalIcons.subtitle && <defaultMinimalIcons.subtitle size={16} />}
127
- <span>Subtitles</span>
128
- </div>
129
- <div className="flex items-center gap-1 text-gray-400 text-xs">
130
- {!hasSubtitles ? (
131
- <span className="text-gray-500">Unavailable</span>
132
- ) : subtitleLoadError ? (
133
- <span className="text-red-400">Error</span>
134
- ) : subtitlesEnabled ? (
135
- <span className="text-cyan-400">On</span>
136
- ) : (
137
- <span>Off</span>
138
- )}
139
- {hasSubtitles && (
140
- <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
141
- <path
142
- strokeLinecap="round"
143
- strokeLinejoin="round"
144
- strokeWidth={2}
145
- d="M9 5l7 7-7 7"
146
- />
147
- </svg>
148
- )}
149
- </div>
150
- </button>
151
-
152
- {/* Font Size Option - only show if subtitles are available */}
153
- {hasSubtitles && (
154
- <button
155
- className="flex w-full items-center justify-between px-3 py-2 text-left text-sm transition-colors hover:bg-gray-800"
156
- onClick={() => setCurrentView("fontSize")}>
157
- <div className="flex items-center gap-2">
158
- <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
159
- <path
160
- strokeLinecap="round"
161
- strokeLinejoin="round"
162
- strokeWidth={2}
163
- d="M4 7h16M4 7v10m0-10l4 10m8-10l4 10m-4-10v10"
164
- />
165
- </svg>
166
- <span>Font Size</span>
167
- </div>
168
- <div className="flex items-center gap-1 text-gray-400 text-xs">
169
- <span className="capitalize">{subtitleFontSize}</span>
170
- <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
171
- <path
172
- strokeLinecap="round"
173
- strokeLinejoin="round"
174
- strokeWidth={2}
175
- d="M9 5l7 7-7 7"
176
- />
177
- </svg>
178
- </div>
179
- </button>
180
- )}
181
-
182
- {/* Playback Speed Option */}
183
- <button
184
- className="flex w-full items-center justify-between px-3 py-2 text-left text-sm transition-colors hover:bg-gray-800"
185
- onClick={() => setCurrentView("speed")}>
186
- <div className="flex items-center gap-2">
187
- <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
188
- <path
189
- strokeLinecap="round"
190
- strokeLinejoin="round"
191
- strokeWidth={2}
192
- d="M13 10V3L4 14h7v7l9-11h-7z"
193
- />
194
- </svg>
195
- <span>Playback Speed</span>
196
- </div>
197
- <div className="flex items-center gap-1 text-gray-400 text-xs">
198
- <span>{playbackRate === 1 ? "Normal" : `${playbackRate}x`}</span>
199
- <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
200
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
201
- </svg>
202
- </div>
203
- </button>
204
- </div>
205
- </>
206
- )
207
-
208
- const renderSubtitlesMenu = () => (
209
- <>
210
- <div className="flex items-center justify-between border-gray-700 border-b px-3 py-2">
211
- <button
212
- onClick={handleBackClick}
213
- className="text-gray-400 transition-colors hover:text-white">
214
- <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
215
- <path
216
- strokeLinecap="round"
217
- strokeLinejoin="round"
218
- strokeWidth={2}
219
- d="M15 19l-7-7 7-7"
220
- />
221
- </svg>
222
- </button>
223
- <span className="font-semibold text-gray-300 text-sm">Subtitles</span>
224
- <div className="w-4" />
225
- </div>
226
- <div className="py-1">
227
- {/* Off option */}
228
- <button
229
- className={cn(
230
- "flex w-full items-center justify-between px-3 py-2 text-left text-sm transition-colors hover:bg-gray-800",
231
- !subtitlesEnabled && "bg-cyan-700/20 text-cyan-400"
232
- )}
233
- onClick={() => handleSelectSubtitle(null)}>
234
- <span>Off</span>
235
- {!subtitlesEnabled && (
236
- <svg className="h-4 w-4 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
237
- <path
238
- fillRule="evenodd"
239
- d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
240
- />
241
- </svg>
242
- )}
243
- </button>
244
-
245
- {/* Subtitle tracks */}
246
- {subtitleTracks.length > 0 ? (
247
- subtitleTracks.map((track) => (
248
- <button
249
- key={track.id}
250
- className={cn(
251
- "flex w-full items-center justify-between px-3 py-2 text-left text-sm transition-colors hover:bg-gray-800",
252
- subtitlesEnabled &&
253
- currentSubtitleTrack === track.id &&
254
- "bg-cyan-700/20 text-cyan-400"
255
- )}
256
- onClick={() => handleSelectSubtitle(track.id)}>
257
- <span>{track.label}</span>
258
- {subtitlesEnabled && currentSubtitleTrack === track.id && (
259
- <svg className="h-4 w-4 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
260
- <path
261
- fillRule="evenodd"
262
- d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
263
- />
264
- </svg>
265
- )}
266
- </button>
267
- ))
268
- ) : (
269
- <button
270
- className={cn(
271
- "flex w-full items-center justify-between px-3 py-2 text-left text-sm transition-colors hover:bg-gray-800",
272
- subtitlesEnabled && "bg-cyan-700/20 text-cyan-400"
273
- )}
274
- onClick={() => {
275
- if (!subtitlesEnabled) {
276
- onToggleSubtitles()
277
- }
278
- setCurrentView("main")
279
- }}>
280
- <span>Default</span>
281
- {subtitlesEnabled && (
282
- <svg className="h-4 w-4 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
283
- <path
284
- fillRule="evenodd"
285
- d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
286
- />
287
- </svg>
288
- )}
289
- </button>
290
- )}
291
- </div>
292
- </>
293
- )
294
-
295
- const renderFontSizeMenu = () => (
296
- <>
297
- <div className="flex items-center justify-between border-gray-700 border-b px-3 py-2">
298
- <button
299
- onClick={handleBackClick}
300
- className="text-gray-400 transition-colors hover:text-white">
301
- <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
302
- <path
303
- strokeLinecap="round"
304
- strokeLinejoin="round"
305
- strokeWidth={2}
306
- d="M15 19l-7-7 7-7"
307
- />
308
- </svg>
309
- </button>
310
- <span className="font-semibold text-gray-300 text-sm">Font Size</span>
311
- <div className="w-4" />
312
- </div>
313
- <div className="py-1">
314
- {fontSizes.map((size) => (
315
- <button
316
- key={size.value}
317
- className={cn(
318
- "flex w-full items-center justify-between px-3 py-2 text-left text-sm transition-colors hover:bg-gray-800",
319
- subtitleFontSize === size.value && "bg-cyan-700/20 text-cyan-400"
320
- )}
321
- onClick={() => handleSelectFontSize(size.value as "small" | "medium" | "large")}>
322
- <div className="flex items-center gap-3">
323
- <span className="text-gray-400" style={{ fontSize: size.size }}>
324
- Aa
325
- </span>
326
- <span>{size.label}</span>
327
- </div>
328
- {subtitleFontSize === size.value && (
329
- <svg className="h-4 w-4 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
330
- <path
331
- fillRule="evenodd"
332
- d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
333
- />
334
- </svg>
335
- )}
336
- </button>
337
- ))}
338
- </div>
339
- </>
340
- )
341
-
342
- const renderSpeedMenu = () => (
343
- <>
344
- <div className="flex items-center justify-between border-gray-700 border-b px-3 py-2">
345
- <button
346
- onClick={handleBackClick}
347
- className="text-gray-400 transition-colors hover:text-white">
348
- <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
349
- <path
350
- strokeLinecap="round"
351
- strokeLinejoin="round"
352
- strokeWidth={2}
353
- d="M15 19l-7-7 7-7"
354
- />
355
- </svg>
356
- </button>
357
- <span className="font-semibold text-gray-300 text-sm">Playback Speed</span>
358
- <div className="w-4" />
359
- </div>
360
- <div className="py-1">
361
- {playbackRates.map((rate) => (
362
- <button
363
- key={rate}
364
- className={cn(
365
- "flex w-full items-center justify-between px-3 py-2 text-left text-sm transition-colors hover:bg-gray-800",
366
- playbackRate === rate && "bg-cyan-700/20 text-cyan-400"
367
- )}
368
- onClick={() => handleSelectSpeed(rate)}>
369
- <span>{rate === 1 ? "Normal" : `${rate}x`}</span>
370
- {playbackRate === rate && (
371
- <svg className="h-4 w-4 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
372
- <path
373
- fillRule="evenodd"
374
- d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
375
- />
376
- </svg>
377
- )}
378
- </button>
379
- ))}
380
- </div>
381
- </>
382
- )
383
-
384
- return (
385
- <div className="relative" style={{ zIndex: showSettings ? 60 : "auto" }}>
386
- <button
387
- className={cn("minimal-btn h-9 w-9", showSettings && "text-cyan-500")}
388
- onClick={handleSettingsClick}
389
- aria-label="Settings"
390
- title="Settings">
391
- {defaultMinimalIcons.settings && <defaultMinimalIcons.settings size={18} />}
392
- </button>
393
-
394
- {showSettings && (
395
- <div
396
- className="absolute right-0 mb-2 min-w-[240px] overflow-hidden rounded-lg border border-gray-700 bg-gray-900 shadow-xl"
397
- style={{
398
- bottom: "100%",
399
- zIndex: 1000,
400
- maxHeight: "400px",
401
- overflowY: "auto"
402
- }}
403
- onClick={handleDropdownClick}>
404
- {currentView === "main" && renderMainMenu()}
405
- {currentView === "subtitles" && renderSubtitlesMenu()}
406
- {currentView === "fontSize" && renderFontSizeMenu()}
407
- {currentView === "speed" && renderSpeedMenu()}
408
- </div>
409
- )}
410
- </div>
411
- )
412
- }
@@ -1,46 +0,0 @@
1
- import React, { memo } from "react"
2
- import { MinimalBackward10Icon, MinimalForward10Icon, defaultMinimalIcons } from "../../../icons"
3
-
4
- interface PlaybackControlsProps {
5
- isPlaying: boolean
6
- onTogglePlay: () => void
7
- onSeekBackward: () => void
8
- onSeekForward: () => void
9
- }
10
-
11
- export const PlaybackControls = function PlaybackControls({
12
- isPlaying,
13
- onTogglePlay,
14
- onSeekBackward,
15
- onSeekForward
16
- }: PlaybackControlsProps) {
17
- const PlayIcon = defaultMinimalIcons.play
18
- const PauseIcon = defaultMinimalIcons.pause
19
-
20
- return (
21
- <div className="flex items-center gap-2">
22
- <button
23
- className="minimal-btn size-15"
24
- onClick={onTogglePlay}
25
- aria-label={isPlaying ? "Pause" : "Play"}>
26
- {isPlaying ? PauseIcon && <PauseIcon size={32} /> : PlayIcon && <PlayIcon size={32} />}
27
- </button>
28
-
29
- <button
30
- className="minimal-btn h-9 w-9"
31
- onClick={onSeekBackward}
32
- aria-label="Backward 10 seconds"
33
- title="Backward 10s (J)">
34
- <MinimalBackward10Icon size={18} />
35
- </button>
36
-
37
- <button
38
- className="minimal-btn h-9 w-9"
39
- onClick={onSeekForward}
40
- aria-label="Forward 10 seconds"
41
- title="Forward 10s (L)">
42
- <MinimalForward10Icon size={18} />
43
- </button>
44
- </div>
45
- )
46
- }
@@ -1,164 +0,0 @@
1
- import React, { memo, useState, useRef, useEffect } from "react"
2
- import { cn } from "../../../../lib/utils"
3
- import { MinimalScreenshotIcon, MinimalSubtitleIcon, defaultMinimalIcons } from "../../../icons"
4
- import { SettingsDropdown } from "./SettingsDropdown"
5
-
6
- interface RightControlsProps {
7
- subtitleSrc?: string
8
- subtitlesEnabled: boolean
9
- subtitleTracks?: Array<{
10
- id: string
11
- label: string
12
- language?: string
13
- src?: string
14
- }>
15
- currentTrackId?: string | null
16
- hasSubtitles?: boolean
17
- subtitleLoadError?: Error | null
18
- isFullscreen: boolean
19
- showSettings: boolean
20
- playbackRate: number
21
- onToggleSubtitles: () => void
22
- onSelectSubtitleTrack?: (trackId: string | null) => void
23
- onTakeScreenshot: (ctrlKey: boolean) => void
24
- onToggleFullscreen: () => void
25
- onToggleSettings: () => void
26
- onChangePlaybackRate: (rate: number) => void
27
- }
28
-
29
- export const RightControls = function RightControls({
30
- subtitleSrc,
31
- subtitlesEnabled,
32
- subtitleTracks,
33
- currentTrackId,
34
- hasSubtitles,
35
- subtitleLoadError,
36
- isFullscreen,
37
- showSettings,
38
- playbackRate,
39
- onToggleSubtitles,
40
- onSelectSubtitleTrack,
41
- onTakeScreenshot,
42
- onToggleFullscreen,
43
- onToggleSettings,
44
- onChangePlaybackRate
45
- }: RightControlsProps) {
46
- const [showSubtitleMenu, setShowSubtitleMenu] = useState(false)
47
- const subtitleMenuRef = useRef<HTMLDivElement>(null)
48
- const FullscreenIcon = defaultMinimalIcons.fullscreen
49
- const ExitFullscreenIcon = defaultMinimalIcons.exitFullscreen
50
-
51
- // Close subtitle menu when clicking outside
52
- useEffect(() => {
53
- const handleClickOutside = (event: MouseEvent) => {
54
- if (subtitleMenuRef.current && !subtitleMenuRef.current.contains(event.target as Node)) {
55
- setShowSubtitleMenu(false)
56
- }
57
- }
58
-
59
- if (showSubtitleMenu) {
60
- document.addEventListener("mousedown", handleClickOutside)
61
- return () => document.removeEventListener("mousedown", handleClickOutside)
62
- }
63
- }, [showSubtitleMenu])
64
-
65
- const handleSubtitleClick = () => {
66
- if (subtitleTracks && subtitleTracks.length > 0) {
67
- setShowSubtitleMenu(!showSubtitleMenu)
68
- } else {
69
- onToggleSubtitles()
70
- }
71
- }
72
-
73
- return (
74
- <div className="flex items-center gap-2">
75
- {/* Subtitle Button with Dropdown */}
76
- {hasSubtitles && (
77
- <div className="relative" ref={subtitleMenuRef}>
78
- <button
79
- className={cn(
80
- "minimal-btn h-9 w-9",
81
- subtitlesEnabled && "text-cyan-500",
82
- subtitleLoadError && "text-red-500"
83
- )}
84
- onClick={handleSubtitleClick}
85
- aria-label="Subtitles"
86
- title={subtitleLoadError ? "Subtitle Error" : "Subtitles (C)"}>
87
- <MinimalSubtitleIcon size={18} />
88
- </button>
89
-
90
- {/* Subtitle Track Selection Menu */}
91
- {showSubtitleMenu && subtitleTracks && subtitleTracks.length > 0 && (
92
- <div className="absolute right-0 bottom-full mb-2 w-48 rounded-md bg-gray-900/95 py-2 shadow-lg backdrop-blur-sm">
93
- <div className="px-3 py-1 font-semibold text-gray-400 text-xs">Subtitles</div>
94
-
95
- {/* Off Option */}
96
- <button
97
- className={cn(
98
- "flex w-full items-center px-3 py-1.5 text-gray-300 text-sm hover:bg-gray-800",
99
- !subtitlesEnabled && "bg-gray-800 text-cyan-500"
100
- )}
101
- onClick={() => {
102
- onSelectSubtitleTrack?.(null)
103
- setShowSubtitleMenu(false)
104
- }}>
105
- Off
106
- </button>
107
-
108
- {/* Track Options */}
109
- {subtitleTracks.map((track) => (
110
- <button
111
- key={track.id}
112
- className={cn(
113
- "flex w-full items-center px-3 py-1.5 text-gray-300 text-sm hover:bg-gray-800",
114
- currentTrackId === track.id && "bg-gray-800 text-cyan-500"
115
- )}
116
- onClick={() => {
117
- onSelectSubtitleTrack?.(track.id)
118
- setShowSubtitleMenu(false)
119
- }}>
120
- <span>{track.label}</span>
121
- {track.language && (
122
- <span className="ml-2 text-gray-500 text-xs">({track.language})</span>
123
- )}
124
- </button>
125
- ))}
126
-
127
- {/* Error Message */}
128
- {subtitleLoadError && (
129
- <div className="mt-2 border-gray-800 border-t px-3 py-2">
130
- <p className="text-red-400 text-xs">Failed to load subtitles</p>
131
- </div>
132
- )}
133
- </div>
134
- )}
135
- </div>
136
- )}
137
-
138
- <button
139
- className="minimal-btn h-9 w-9"
140
- onClick={(e) => onTakeScreenshot(e.ctrlKey || e.metaKey)}
141
- aria-label="Take Screenshot"
142
- title="Screenshot (S) - Ctrl+Click to copy">
143
- <MinimalScreenshotIcon size={18} />
144
- </button>
145
-
146
- <SettingsDropdown
147
- showSettings={showSettings}
148
- playbackRate={playbackRate}
149
- onToggleSettings={onToggleSettings}
150
- onChangePlaybackRate={onChangePlaybackRate}
151
- />
152
-
153
- <button
154
- className="minimal-btn h-9 w-9"
155
- onClick={onToggleFullscreen}
156
- aria-label={isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen"}
157
- title="Fullscreen (F)">
158
- {isFullscreen
159
- ? ExitFullscreenIcon && <ExitFullscreenIcon size={18} />
160
- : FullscreenIcon && <FullscreenIcon size={18} />}
161
- </button>
162
- </div>
163
- )
164
- }