@hanifhan1f/vidstack-react 1.12.13

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 (284) hide show
  1. package/.templates/sandbox/document.css +27 -0
  2. package/.templates/sandbox/favicon-32x32.png +0 -0
  3. package/.templates/sandbox/index.html +21 -0
  4. package/.templates/sandbox/main.tsx +12 -0
  5. package/.templates/sandbox/player.css +39 -0
  6. package/.templates/sandbox/player.tsx +121 -0
  7. package/.templates/sandbox/tracks.ts +23 -0
  8. package/LICENSE +21 -0
  9. package/README.md +23 -0
  10. package/analyze.config.ts +7 -0
  11. package/build/build-icons.js +62 -0
  12. package/npm/analyze.json.d.ts +7 -0
  13. package/package.json +162 -0
  14. package/rollup.config.ts +256 -0
  15. package/src/components/announcer.tsx +47 -0
  16. package/src/components/layouts/default/audio-layout.tsx +231 -0
  17. package/src/components/layouts/default/context.ts +28 -0
  18. package/src/components/layouts/default/hooks.ts +13 -0
  19. package/src/components/layouts/default/icons.tsx +225 -0
  20. package/src/components/layouts/default/index.ts +11 -0
  21. package/src/components/layouts/default/media-layout.tsx +259 -0
  22. package/src/components/layouts/default/slots.tsx +98 -0
  23. package/src/components/layouts/default/ui/announcer.tsx +22 -0
  24. package/src/components/layouts/default/ui/buttons.tsx +301 -0
  25. package/src/components/layouts/default/ui/captions.tsx +16 -0
  26. package/src/components/layouts/default/ui/controls.tsx +12 -0
  27. package/src/components/layouts/default/ui/keyboard-display.tsx +132 -0
  28. package/src/components/layouts/default/ui/menus/accessibility-menu.tsx +100 -0
  29. package/src/components/layouts/default/ui/menus/audio-menu.tsx +167 -0
  30. package/src/components/layouts/default/ui/menus/captions-menu.tsx +61 -0
  31. package/src/components/layouts/default/ui/menus/chapters-menu.tsx +132 -0
  32. package/src/components/layouts/default/ui/menus/font-menu.tsx +331 -0
  33. package/src/components/layouts/default/ui/menus/items/menu-checkbox.tsx +72 -0
  34. package/src/components/layouts/default/ui/menus/items/menu-items.tsx +135 -0
  35. package/src/components/layouts/default/ui/menus/items/menu-slider.tsx +92 -0
  36. package/src/components/layouts/default/ui/menus/playback-menu.tsx +232 -0
  37. package/src/components/layouts/default/ui/menus/settings-menu.tsx +114 -0
  38. package/src/components/layouts/default/ui/menus/utils.ts +12 -0
  39. package/src/components/layouts/default/ui/sliders.tsx +136 -0
  40. package/src/components/layouts/default/ui/time.tsx +73 -0
  41. package/src/components/layouts/default/ui/title.tsx +24 -0
  42. package/src/components/layouts/default/ui/tooltip.tsx +27 -0
  43. package/src/components/layouts/default/ui.ts +8 -0
  44. package/src/components/layouts/default/video-layout.tsx +344 -0
  45. package/src/components/layouts/plyr/context.ts +26 -0
  46. package/src/components/layouts/plyr/icons/plyr-airplay.js +1 -0
  47. package/src/components/layouts/plyr/icons/plyr-captions-off.js +1 -0
  48. package/src/components/layouts/plyr/icons/plyr-captions-on.js +1 -0
  49. package/src/components/layouts/plyr/icons/plyr-download.js +1 -0
  50. package/src/components/layouts/plyr/icons/plyr-enter-fullscreen.js +1 -0
  51. package/src/components/layouts/plyr/icons/plyr-exit-fullscreen.js +1 -0
  52. package/src/components/layouts/plyr/icons/plyr-fast-forward.js +1 -0
  53. package/src/components/layouts/plyr/icons/plyr-muted.js +1 -0
  54. package/src/components/layouts/plyr/icons/plyr-pause.js +1 -0
  55. package/src/components/layouts/plyr/icons/plyr-pip.js +1 -0
  56. package/src/components/layouts/plyr/icons/plyr-play.js +1 -0
  57. package/src/components/layouts/plyr/icons/plyr-restart.js +1 -0
  58. package/src/components/layouts/plyr/icons/plyr-rewind.js +1 -0
  59. package/src/components/layouts/plyr/icons/plyr-settings.js +1 -0
  60. package/src/components/layouts/plyr/icons/plyr-volume.js +1 -0
  61. package/src/components/layouts/plyr/icons.tsx +71 -0
  62. package/src/components/layouts/plyr/index.ts +11 -0
  63. package/src/components/layouts/plyr/layout.tsx +1024 -0
  64. package/src/components/layouts/plyr/props.ts +104 -0
  65. package/src/components/layouts/plyr/slots.tsx +52 -0
  66. package/src/components/layouts/remotion-ui.ts +13 -0
  67. package/src/components/layouts/utils.ts +17 -0
  68. package/src/components/player-callbacks.ts +67 -0
  69. package/src/components/player.tsx +67 -0
  70. package/src/components/primitives/instances.ts +92 -0
  71. package/src/components/primitives/nodes.tsx +58 -0
  72. package/src/components/primitives/slot.tsx +132 -0
  73. package/src/components/provider.tsx +187 -0
  74. package/src/components/text-track.tsx +106 -0
  75. package/src/components/ui/buttons/airplay-button.tsx +53 -0
  76. package/src/components/ui/buttons/caption-button.tsx +55 -0
  77. package/src/components/ui/buttons/fullscreen-button.tsx +55 -0
  78. package/src/components/ui/buttons/google-cast-button.tsx +53 -0
  79. package/src/components/ui/buttons/live-button.tsx +56 -0
  80. package/src/components/ui/buttons/mute-button.tsx +60 -0
  81. package/src/components/ui/buttons/pip-button.tsx +54 -0
  82. package/src/components/ui/buttons/play-button.tsx +53 -0
  83. package/src/components/ui/buttons/seek-button.tsx +55 -0
  84. package/src/components/ui/buttons/toggle-button.tsx +51 -0
  85. package/src/components/ui/caption.tsx +70 -0
  86. package/src/components/ui/captions.tsx +41 -0
  87. package/src/components/ui/chapter-title.tsx +40 -0
  88. package/src/components/ui/controls.tsx +90 -0
  89. package/src/components/ui/gesture.tsx +43 -0
  90. package/src/components/ui/menu.tsx +251 -0
  91. package/src/components/ui/poster.tsx +101 -0
  92. package/src/components/ui/radio-group.tsx +88 -0
  93. package/src/components/ui/sliders/audio-gain-slider.tsx +55 -0
  94. package/src/components/ui/sliders/quality-slider.tsx +54 -0
  95. package/src/components/ui/sliders/slider-callbacks.ts +14 -0
  96. package/src/components/ui/sliders/slider-value.tsx +13 -0
  97. package/src/components/ui/sliders/slider.tsx +254 -0
  98. package/src/components/ui/sliders/speed-slider.tsx +54 -0
  99. package/src/components/ui/sliders/time-slider.tsx +379 -0
  100. package/src/components/ui/sliders/volume-slider.tsx +55 -0
  101. package/src/components/ui/spinner.tsx +105 -0
  102. package/src/components/ui/thumbnail.tsx +82 -0
  103. package/src/components/ui/time.tsx +77 -0
  104. package/src/components/ui/title.tsx +32 -0
  105. package/src/components/ui/tooltip.tsx +135 -0
  106. package/src/globals.d.ts +3 -0
  107. package/src/hooks/create-text-track.ts +22 -0
  108. package/src/hooks/options/use-audio-gain-options.ts +75 -0
  109. package/src/hooks/options/use-audio-options.ts +71 -0
  110. package/src/hooks/options/use-caption-options.ts +95 -0
  111. package/src/hooks/options/use-chapter-options.ts +97 -0
  112. package/src/hooks/options/use-playback-rate-options.ts +75 -0
  113. package/src/hooks/options/use-video-quality-options.ts +123 -0
  114. package/src/hooks/use-active-text-cues.ts +28 -0
  115. package/src/hooks/use-active-text-track.ts +19 -0
  116. package/src/hooks/use-chapter-title.ts +12 -0
  117. package/src/hooks/use-dom.ts +121 -0
  118. package/src/hooks/use-media-context.ts +6 -0
  119. package/src/hooks/use-media-player.ts +19 -0
  120. package/src/hooks/use-media-provider.ts +31 -0
  121. package/src/hooks/use-media-remote.ts +37 -0
  122. package/src/hooks/use-media-state.ts +58 -0
  123. package/src/hooks/use-signals.ts +24 -0
  124. package/src/hooks/use-slider-preview.ts +126 -0
  125. package/src/hooks/use-slider-state.ts +63 -0
  126. package/src/hooks/use-state.ts +47 -0
  127. package/src/hooks/use-text-cues.ts +33 -0
  128. package/src/hooks/use-thumbnails.ts +69 -0
  129. package/src/icon.ts +37 -0
  130. package/src/icons.ts +754 -0
  131. package/src/index.ts +181 -0
  132. package/src/providers/remotion/index.ts +10 -0
  133. package/src/providers/remotion/layout-engine.ts +123 -0
  134. package/src/providers/remotion/loader.ts +35 -0
  135. package/src/providers/remotion/playback-engine.ts +142 -0
  136. package/src/providers/remotion/provider.tsx +514 -0
  137. package/src/providers/remotion/type-check.ts +13 -0
  138. package/src/providers/remotion/types.ts +94 -0
  139. package/src/providers/remotion/ui/context.tsx +120 -0
  140. package/src/providers/remotion/ui/error-boundary.tsx +57 -0
  141. package/src/providers/remotion/ui/poster.tsx +33 -0
  142. package/src/providers/remotion/ui/slider-thumbnail.tsx +41 -0
  143. package/src/providers/remotion/ui/thumbnail.tsx +166 -0
  144. package/src/providers/remotion/validate.ts +220 -0
  145. package/src/source.ts +5 -0
  146. package/src/utils.ts +27 -0
  147. package/tsconfig.build.json +10 -0
  148. package/tsconfig.json +11 -0
  149. package/types/react/src/components/announcer.d.ts +16 -0
  150. package/types/react/src/components/layouts/default/audio-layout.d.ts +27 -0
  151. package/types/react/src/components/layouts/default/context.d.ts +14 -0
  152. package/types/react/src/components/layouts/default/hooks.d.ts +2 -0
  153. package/types/react/src/components/layouts/default/icons.d.ts +95 -0
  154. package/types/react/src/components/layouts/default/index.d.ts +5 -0
  155. package/types/react/src/components/layouts/default/media-layout.d.ts +133 -0
  156. package/types/react/src/components/layouts/default/slots.d.ts +22 -0
  157. package/types/react/src/components/layouts/default/ui/announcer.d.ts +6 -0
  158. package/types/react/src/components/layouts/default/ui/buttons.d.ts +54 -0
  159. package/types/react/src/components/layouts/default/ui/captions.d.ts +6 -0
  160. package/types/react/src/components/layouts/default/ui/controls.d.ts +6 -0
  161. package/types/react/src/components/layouts/default/ui/keyboard-display.d.ts +8 -0
  162. package/types/react/src/components/layouts/default/ui/menus/accessibility-menu.d.ts +10 -0
  163. package/types/react/src/components/layouts/default/ui/menus/audio-menu.d.ts +10 -0
  164. package/types/react/src/components/layouts/default/ui/menus/captions-menu.d.ts +10 -0
  165. package/types/react/src/components/layouts/default/ui/menus/chapters-menu.d.ts +7 -0
  166. package/types/react/src/components/layouts/default/ui/menus/font-menu.d.ts +6 -0
  167. package/types/react/src/components/layouts/default/ui/menus/items/menu-checkbox.d.ts +13 -0
  168. package/types/react/src/components/layouts/default/ui/menus/items/menu-items.d.ts +49 -0
  169. package/types/react/src/components/layouts/default/ui/menus/items/menu-slider.d.ts +26 -0
  170. package/types/react/src/components/layouts/default/ui/menus/playback-menu.d.ts +10 -0
  171. package/types/react/src/components/layouts/default/ui/menus/settings-menu.d.ts +15 -0
  172. package/types/react/src/components/layouts/default/ui/menus/utils.d.ts +1 -0
  173. package/types/react/src/components/layouts/default/ui/sliders.d.ts +24 -0
  174. package/types/react/src/components/layouts/default/ui/time.d.ts +30 -0
  175. package/types/react/src/components/layouts/default/ui/title.d.ts +6 -0
  176. package/types/react/src/components/layouts/default/ui/tooltip.d.ts +12 -0
  177. package/types/react/src/components/layouts/default/ui.d.ts +8 -0
  178. package/types/react/src/components/layouts/default/video-layout.d.ts +47 -0
  179. package/types/react/src/components/layouts/plyr/context.d.ts +12 -0
  180. package/types/react/src/components/layouts/plyr/icons/plyr-airplay.d.ts +2 -0
  181. package/types/react/src/components/layouts/plyr/icons/plyr-captions-off.d.ts +2 -0
  182. package/types/react/src/components/layouts/plyr/icons/plyr-captions-on.d.ts +2 -0
  183. package/types/react/src/components/layouts/plyr/icons/plyr-download.d.ts +2 -0
  184. package/types/react/src/components/layouts/plyr/icons/plyr-enter-fullscreen.d.ts +2 -0
  185. package/types/react/src/components/layouts/plyr/icons/plyr-exit-fullscreen.d.ts +2 -0
  186. package/types/react/src/components/layouts/plyr/icons/plyr-fast-forward.d.ts +2 -0
  187. package/types/react/src/components/layouts/plyr/icons/plyr-muted.d.ts +2 -0
  188. package/types/react/src/components/layouts/plyr/icons/plyr-pause.d.ts +2 -0
  189. package/types/react/src/components/layouts/plyr/icons/plyr-pip.d.ts +2 -0
  190. package/types/react/src/components/layouts/plyr/icons/plyr-play.d.ts +2 -0
  191. package/types/react/src/components/layouts/plyr/icons/plyr-restart.d.ts +2 -0
  192. package/types/react/src/components/layouts/plyr/icons/plyr-rewind.d.ts +2 -0
  193. package/types/react/src/components/layouts/plyr/icons/plyr-settings.d.ts +2 -0
  194. package/types/react/src/components/layouts/plyr/icons/plyr-volume.d.ts +2 -0
  195. package/types/react/src/components/layouts/plyr/icons.d.ts +25 -0
  196. package/types/react/src/components/layouts/plyr/index.d.ts +6 -0
  197. package/types/react/src/components/layouts/plyr/layout.d.ts +17 -0
  198. package/types/react/src/components/layouts/plyr/props.d.ts +71 -0
  199. package/types/react/src/components/layouts/plyr/slots.d.ts +9 -0
  200. package/types/react/src/components/layouts/remotion-ui.d.ts +3 -0
  201. package/types/react/src/components/layouts/utils.d.ts +1 -0
  202. package/types/react/src/components/player-callbacks.d.ts +6 -0
  203. package/types/react/src/components/player.d.ts +32 -0
  204. package/types/react/src/components/primitives/instances.d.ts +83 -0
  205. package/types/react/src/components/primitives/nodes.d.ts +15 -0
  206. package/types/react/src/components/primitives/slot.d.ts +11 -0
  207. package/types/react/src/components/provider.d.ts +26 -0
  208. package/types/react/src/components/text-track.d.ts +100 -0
  209. package/types/react/src/components/ui/buttons/airplay-button.d.ts +22 -0
  210. package/types/react/src/components/ui/buttons/caption-button.d.ts +24 -0
  211. package/types/react/src/components/ui/buttons/fullscreen-button.d.ts +24 -0
  212. package/types/react/src/components/ui/buttons/google-cast-button.d.ts +22 -0
  213. package/types/react/src/components/ui/buttons/live-button.d.ts +26 -0
  214. package/types/react/src/components/ui/buttons/mute-button.d.ts +30 -0
  215. package/types/react/src/components/ui/buttons/pip-button.d.ts +24 -0
  216. package/types/react/src/components/ui/buttons/play-button.d.ts +23 -0
  217. package/types/react/src/components/ui/buttons/seek-button.d.ts +25 -0
  218. package/types/react/src/components/ui/buttons/toggle-button.d.ts +22 -0
  219. package/types/react/src/components/ui/caption.d.ts +11 -0
  220. package/types/react/src/components/ui/captions.d.ts +20 -0
  221. package/types/react/src/components/ui/chapter-title.d.ts +20 -0
  222. package/types/react/src/components/ui/controls.d.ts +40 -0
  223. package/types/react/src/components/ui/gesture.d.ts +20 -0
  224. package/types/react/src/components/ui/menu.d.ts +102 -0
  225. package/types/react/src/components/ui/poster.d.ts +25 -0
  226. package/types/react/src/components/ui/radio-group.d.ts +39 -0
  227. package/types/react/src/components/ui/sliders/audio-gain-slider.d.ts +29 -0
  228. package/types/react/src/components/ui/sliders/quality-slider.d.ts +28 -0
  229. package/types/react/src/components/ui/sliders/slider-callbacks.d.ts +6 -0
  230. package/types/react/src/components/ui/sliders/slider-value.d.ts +9 -0
  231. package/types/react/src/components/ui/sliders/slider.d.ts +134 -0
  232. package/types/react/src/components/ui/sliders/speed-slider.d.ts +28 -0
  233. package/types/react/src/components/ui/sliders/time-slider.d.ts +124 -0
  234. package/types/react/src/components/ui/sliders/volume-slider.d.ts +29 -0
  235. package/types/react/src/components/ui/spinner.d.ts +31 -0
  236. package/types/react/src/components/ui/thumbnail.d.ts +26 -0
  237. package/types/react/src/components/ui/time.d.ts +20 -0
  238. package/types/react/src/components/ui/title.d.ts +15 -0
  239. package/types/react/src/components/ui/tooltip.d.ts +63 -0
  240. package/types/react/src/hooks/create-text-track.d.ts +7 -0
  241. package/types/react/src/hooks/options/use-audio-gain-options.d.ts +22 -0
  242. package/types/react/src/hooks/options/use-audio-options.d.ts +17 -0
  243. package/types/react/src/hooks/options/use-caption-options.d.ts +24 -0
  244. package/types/react/src/hooks/options/use-chapter-options.d.ts +18 -0
  245. package/types/react/src/hooks/options/use-playback-rate-options.d.ts +22 -0
  246. package/types/react/src/hooks/options/use-video-quality-options.d.ts +35 -0
  247. package/types/react/src/hooks/use-active-text-cues.d.ts +6 -0
  248. package/types/react/src/hooks/use-active-text-track.d.ts +5 -0
  249. package/types/react/src/hooks/use-chapter-title.d.ts +4 -0
  250. package/types/react/src/hooks/use-dom.d.ts +9 -0
  251. package/types/react/src/hooks/use-media-context.d.ts +1 -0
  252. package/types/react/src/hooks/use-media-player.d.ts +7 -0
  253. package/types/react/src/hooks/use-media-provider.d.ts +7 -0
  254. package/types/react/src/hooks/use-media-remote.d.ts +12 -0
  255. package/types/react/src/hooks/use-media-state.d.ts +15 -0
  256. package/types/react/src/hooks/use-signals.d.ts +5 -0
  257. package/types/react/src/hooks/use-slider-preview.d.ts +27 -0
  258. package/types/react/src/hooks/use-slider-state.d.ts +16 -0
  259. package/types/react/src/hooks/use-state.d.ts +18 -0
  260. package/types/react/src/hooks/use-text-cues.d.ts +6 -0
  261. package/types/react/src/hooks/use-thumbnails.d.ts +16 -0
  262. package/types/react/src/icon.d.ts +17 -0
  263. package/types/react/src/icons.d.ts +215 -0
  264. package/types/react/src/index.d.ts +78 -0
  265. package/types/react/src/providers/remotion/index.d.ts +7 -0
  266. package/types/react/src/providers/remotion/layout-engine.d.ts +8 -0
  267. package/types/react/src/providers/remotion/loader.d.ts +9 -0
  268. package/types/react/src/providers/remotion/playback-engine.d.ts +11 -0
  269. package/types/react/src/providers/remotion/provider.d.ts +26 -0
  270. package/types/react/src/providers/remotion/type-check.d.ts +6 -0
  271. package/types/react/src/providers/remotion/types.d.ts +91 -0
  272. package/types/react/src/providers/remotion/ui/context.d.ts +17 -0
  273. package/types/react/src/providers/remotion/ui/error-boundary.d.ts +21 -0
  274. package/types/react/src/providers/remotion/ui/poster.d.ts +18 -0
  275. package/types/react/src/providers/remotion/ui/slider-thumbnail.d.ts +17 -0
  276. package/types/react/src/providers/remotion/ui/thumbnail.d.ts +32 -0
  277. package/types/react/src/providers/remotion/validate.d.ts +12 -0
  278. package/types/react/src/source.d.ts +3 -0
  279. package/types/react/src/utils.d.ts +3 -0
  280. package/types/vidstack/src/core/api/src-types.d.ts +50 -0
  281. package/types/vidstack/src/utils/mime.d.ts +15 -0
  282. package/types/vidstack/src/utils/network.d.ts +17 -0
  283. package/types/vidstack/src/utils/support.d.ts +72 -0
  284. package/vite.config.ts +23 -0
@@ -0,0 +1,256 @@
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+
4
+ import { nodeResolve } from '@rollup/plugin-node-resolve';
5
+ import fs from 'fs-extra';
6
+ import { defineConfig, type Plugin, type RollupOptions } from 'rollup';
7
+ import dts from 'rollup-plugin-dts';
8
+
9
+ import { copyPkgFiles } from '../../.build/copy-pkg-files.js';
10
+ import { buildDefaultTheme, watchStyles } from '../vidstack/build/build-styles.js';
11
+ import { decorators } from '../vidstack/build/rollup-decorators';
12
+ import typescript from '../vidstack/build/rollup-ts';
13
+
14
+ const MODE_WATCH = process.argv.includes('-w'),
15
+ MODE_TYPES = process.argv.includes('--config-types');
16
+
17
+ const DIRNAME = path.dirname(fileURLToPath(import.meta.url)),
18
+ ROOT_DIR = path.resolve(DIRNAME, '.'),
19
+ DIST_NPM_DIR = path.resolve(ROOT_DIR, 'dist-npm');
20
+
21
+ const VIDSTACK_PKG_DIR = path.resolve(ROOT_DIR, 'node_modules/vidstack');
22
+
23
+ const NPM_EXTERNAL_PACKAGES = [
24
+ 'react',
25
+ 'react-dom',
26
+ 'media-icons',
27
+ 'media-captions',
28
+ 'hls.js',
29
+ 'dashjs',
30
+ /^@floating-ui/,
31
+ /^remotion/,
32
+ ],
33
+ NPM_BUNDLES = [
34
+ defineNPMBundle({ type: 'server' }),
35
+ defineNPMBundle({ type: 'dev' }),
36
+ defineNPMBundle({ type: 'prod' }),
37
+ ],
38
+ TYPES_BUNDLES = defineTypesBundle();
39
+
40
+ if (!MODE_TYPES) {
41
+ if (MODE_WATCH) {
42
+ watchStyles();
43
+ }
44
+ }
45
+
46
+ export default defineConfig(
47
+ MODE_WATCH ? [...TYPES_BUNDLES, ...NPM_BUNDLES] : MODE_TYPES ? TYPES_BUNDLES : NPM_BUNDLES,
48
+ );
49
+
50
+ function defineTypesBundle(): RollupOptions[] {
51
+ return [
52
+ {
53
+ input: {
54
+ index: 'types/react/src/index.d.ts',
55
+ icons: 'types/react/src/icons.d.ts',
56
+ 'player/remotion': 'types/react/src/providers/remotion/index.d.ts',
57
+ 'player/layouts/default': 'types/react/src/components/layouts/default/index.d.ts',
58
+ 'player/layouts/plyr': 'types/react/src/components/layouts/plyr/index.d.ts',
59
+ },
60
+ output: {
61
+ dir: 'dist-npm',
62
+ compact: false,
63
+ minifyInternalExports: false,
64
+ chunkFileNames: 'types/[name].d.ts',
65
+ manualChunks(id) {
66
+ if (id.includes('primitives/instances')) return 'vidstack-instances';
67
+ if (id.includes('react/src')) return 'vidstack-react';
68
+ if (id.includes('vidstack')) return 'vidstack';
69
+ },
70
+ },
71
+ external: NPM_EXTERNAL_PACKAGES,
72
+ plugins: [
73
+ resolveVidstackTypes(),
74
+ dts({
75
+ respectExternal: true,
76
+ }),
77
+ resolveGlobalTypes(),
78
+ ],
79
+ },
80
+ ];
81
+ }
82
+
83
+ function resolveVidstackTypes(): Plugin {
84
+ return {
85
+ name: 'resolve-vidstack-types',
86
+ resolveId(id) {
87
+ if (id === 'vidstack') {
88
+ return '../vidstack/types/index.d.ts';
89
+ }
90
+
91
+ if (id.startsWith('vidstack')) {
92
+ return id.replace('vidstack', '../vidstack/types').replace('.ts', '.d.ts');
93
+ }
94
+ },
95
+ };
96
+ }
97
+
98
+ function resolveGlobalTypes(): Plugin {
99
+ return {
100
+ name: 'globals',
101
+ generateBundle(_, bundle) {
102
+ const indexFile = Object.values(bundle).find((file) => file.fileName === 'index.d.ts'),
103
+ globalFiles = ['dom.d.ts', 'google-cast.d.ts'],
104
+ references = globalFiles.map((path) => `/// <reference path="./${path}" />`).join('\n');
105
+
106
+ if (!fs.existsSync('dist-npm')) {
107
+ fs.mkdirSync('dist-npm');
108
+ }
109
+
110
+ for (const file of globalFiles) {
111
+ fs.copyFileSync(path.resolve(`../vidstack/npm/${file}`), `dist-npm/${file}`);
112
+ }
113
+
114
+ if (indexFile?.type === 'chunk') {
115
+ indexFile.code = references + `\n\n${indexFile.code}`;
116
+ }
117
+ },
118
+ };
119
+ }
120
+
121
+ interface NPMBundleOptions {
122
+ type: 'dev' | 'prod' | 'server';
123
+ }
124
+
125
+ function defineNPMBundle({ type }: NPMBundleOptions): RollupOptions {
126
+ const isProd = type === 'prod',
127
+ isServer = type === 'server';
128
+
129
+ let input = {
130
+ vidstack: 'src/index.ts',
131
+ 'player/vidstack-remotion': 'src/providers/remotion/index.ts',
132
+ 'player/vidstack-default-layout': 'src/components/layouts/default/index.ts',
133
+ 'player/vidstack-plyr-layout': 'src/components/layouts/plyr/index.ts',
134
+ 'player/vidstack-plyr-icons': 'src/components/layouts/plyr/icons.tsx',
135
+ 'player/vidstack-default-components': 'src/components/layouts/default/ui.ts',
136
+ 'player/vidstack-default-icons': 'src/components/layouts/default/icons.tsx',
137
+ };
138
+
139
+ if (isProd) {
140
+ input['vidstack-icons'] = 'src/icons.ts';
141
+ }
142
+
143
+ return {
144
+ input,
145
+ treeshake: true,
146
+ preserveEntrySignatures: 'allow-extension',
147
+ maxParallelFileOps: isProd ? 1 : 20,
148
+ external: NPM_EXTERNAL_PACKAGES,
149
+ output: {
150
+ format: 'esm',
151
+ compact: false,
152
+ minifyInternalExports: false,
153
+ dir: `dist-npm/${type}`,
154
+ chunkFileNames: `chunks/vidstack-[hash].js`,
155
+ manualChunks(id) {
156
+ if (id.includes('node_modules')) return 'vidstack-deps';
157
+ },
158
+ },
159
+ plugins: [
160
+ env(),
161
+ nodeResolve({
162
+ exportConditions: isServer
163
+ ? ['node', 'default', 'development']
164
+ : isProd
165
+ ? ['production', 'default']
166
+ : ['development', 'production', 'default'],
167
+ }),
168
+ decorators(),
169
+ typescript({
170
+ loader: 'tsx',
171
+ platform: isServer ? 'node' : 'browser',
172
+ define: {
173
+ __DEV__: !isProd && !isServer ? 'true' : 'false',
174
+ __SERVER__: isServer ? 'true' : 'false',
175
+ },
176
+ }),
177
+ rscDirectives(),
178
+ isProd && copyAssets(),
179
+ ],
180
+ };
181
+ }
182
+
183
+ function env(): Plugin {
184
+ return {
185
+ name: 'virtual-env',
186
+ resolveId(id) {
187
+ if (id === ':virtual/env') {
188
+ return id;
189
+ }
190
+ },
191
+ load(id) {
192
+ if (id === ':virtual/env') {
193
+ return 'export const IS_SERVER = typeof document === "undefined";';
194
+ }
195
+ },
196
+ transform(code) {
197
+ if (code.includes('__SERVER__')) {
198
+ code = code.replace(/__SERVER__/g, 'IS_SERVER');
199
+ return "import { IS_SERVER } from ':virtual/env';\n" + code;
200
+ }
201
+ },
202
+ };
203
+ }
204
+
205
+ function rscDirectives(): Plugin {
206
+ return {
207
+ name: 'rsc-directives',
208
+ resolveId(id) {
209
+ if (id.startsWith('maverick.js')) {
210
+ return this.resolve('maverick.js/rsc', '', { skipSelf: true });
211
+ }
212
+ },
213
+ generateBundle(_, bundle) {
214
+ const serverChunks = new Set(),
215
+ neutralChunks = new Set(['vidstack-icons.js']);
216
+
217
+ for (const fileName of Object.keys(bundle)) {
218
+ const chunk = bundle[fileName];
219
+
220
+ if (chunk.type !== 'chunk') continue;
221
+
222
+ if (serverChunks.has(chunk.fileName)) {
223
+ chunk.code = `"use server"\n\n` + chunk.code;
224
+ } else if (!neutralChunks.has(fileName)) {
225
+ chunk.code = `"use client"\n\n` + chunk.code;
226
+ }
227
+ }
228
+ },
229
+ };
230
+ }
231
+
232
+ function copyAssets(): Plugin {
233
+ return {
234
+ name: 'copy-assets',
235
+ async buildEnd() {
236
+ copyPkgFiles();
237
+ await copyStyles();
238
+ await copyTailwind();
239
+ await buildDefaultTheme();
240
+ await fs.copy('npm', 'dist-npm');
241
+ },
242
+ };
243
+ }
244
+
245
+ async function copyStyles() {
246
+ const from = path.resolve(VIDSTACK_PKG_DIR, 'styles/player'),
247
+ to = path.resolve(DIST_NPM_DIR, 'player/styles');
248
+ await fs.copy(from, to);
249
+ }
250
+
251
+ async function copyTailwind() {
252
+ const tailwindFilePath = path.resolve(VIDSTACK_PKG_DIR, 'npm/tailwind.cjs'),
253
+ tailwindDTSFilePath = path.resolve(VIDSTACK_PKG_DIR, 'npm/tailwind.d.cts');
254
+ await fs.copyFile(tailwindFilePath, path.resolve(DIST_NPM_DIR, 'tailwind.cjs'));
255
+ await fs.copyFile(tailwindDTSFilePath, path.resolve(DIST_NPM_DIR, 'tailwind.d.cts'));
256
+ }
@@ -0,0 +1,47 @@
1
+ import * as React from 'react';
2
+
3
+ import { composeRefs, createReactComponent, type ReactElementProps } from 'maverick.js/react';
4
+
5
+ import { MediaAnnouncerInstance } from './primitives/instances';
6
+ import { Primitive } from './primitives/nodes';
7
+
8
+ /* -------------------------------------------------------------------------------------------------
9
+ * MediaAnnouncer
10
+ * -----------------------------------------------------------------------------------------------*/
11
+
12
+ const MediaAnnouncerBridge = createReactComponent(MediaAnnouncerInstance, {
13
+ events: ['onChange'],
14
+ });
15
+
16
+ export interface MediaAnnouncerProps extends ReactElementProps<MediaAnnouncerInstance> {
17
+ ref?: React.Ref<HTMLElement>;
18
+ }
19
+
20
+ /**
21
+ *
22
+ * @docs {@link https://www.vidstack.io/docs/player/components/display/announcer}
23
+ * @example
24
+ * ```tsx
25
+ * <MediaAnnouncer />
26
+ * ```
27
+ */
28
+ const MediaAnnouncer = React.forwardRef<HTMLElement, MediaAnnouncerProps>(
29
+ ({ style, children, ...props }, forwardRef) => {
30
+ return (
31
+ <MediaAnnouncerBridge {...(props as Omit<MediaAnnouncerProps, 'ref'>)}>
32
+ {(props) => (
33
+ <Primitive.div
34
+ {...props}
35
+ style={{ display: 'contents', ...style }}
36
+ ref={composeRefs(props.ref as React.Ref<any>, forwardRef as React.Ref<any>)}
37
+ >
38
+ {children}
39
+ </Primitive.div>
40
+ )}
41
+ </MediaAnnouncerBridge>
42
+ );
43
+ },
44
+ );
45
+
46
+ MediaAnnouncer.displayName = 'MediaAnnouncer';
47
+ export { MediaAnnouncer };
@@ -0,0 +1,231 @@
1
+ import * as React from 'react';
2
+
3
+ import { useSignal } from 'maverick.js/react';
4
+ import { listenEvent, toggleClass } from 'maverick.js/std';
5
+
6
+ import { useChapterTitle } from '../../../hooks/use-chapter-title';
7
+ import { useResizeObserver, useTransitionActive } from '../../../hooks/use-dom';
8
+ import { useMediaContext } from '../../../hooks/use-media-context';
9
+ import { useMediaState } from '../../../hooks/use-media-state';
10
+ import { createComputed } from '../../../hooks/use-signals';
11
+ import * as Controls from '../../ui/controls';
12
+ import { useLayoutName } from '../utils';
13
+ import { i18n, useDefaultLayoutContext } from './context';
14
+ import { createDefaultMediaLayout, type DefaultLayoutProps } from './media-layout';
15
+ import {
16
+ slot,
17
+ useDefaultAudioLayoutSlots,
18
+ type DefaultAudioLayoutSlots,
19
+ type DefaultLayoutMenuSlotName,
20
+ type Slots,
21
+ } from './slots';
22
+ import { DefaultAnnouncer } from './ui/announcer';
23
+ import {
24
+ DefaultCaptionButton,
25
+ DefaultDownloadButton,
26
+ DefaultPlayButton,
27
+ DefaultSeekButton,
28
+ } from './ui/buttons';
29
+ import { DefaultCaptions } from './ui/captions';
30
+ import { DefaultControlsSpacer } from './ui/controls';
31
+ import { DefaultChaptersMenu } from './ui/menus/chapters-menu';
32
+ import { DefaultSettingsMenu } from './ui/menus/settings-menu';
33
+ import { DefaultTimeSlider, DefaultVolumePopup } from './ui/sliders';
34
+ import { DefaultTimeInvert } from './ui/time';
35
+
36
+ /* -------------------------------------------------------------------------------------------------
37
+ * DefaultAudioLayout
38
+ * -----------------------------------------------------------------------------------------------*/
39
+
40
+ const MediaLayout = createDefaultMediaLayout({
41
+ type: 'audio',
42
+ smLayoutWhen({ width }) {
43
+ return width < 576;
44
+ },
45
+ renderLayout: () => <AudioLayout />,
46
+ });
47
+
48
+ export interface DefaultAudioLayoutProps extends DefaultLayoutProps<DefaultAudioLayoutSlots> {}
49
+
50
+ /**
51
+ * The audio layout is our production-ready UI that's displayed when the media view type is set to
52
+ * 'audio'. It includes support for audio tracks, slider chapters, captions, live streams
53
+ * and more out of the box.
54
+ *
55
+ * @attr data-match - Whether this layout is being used.
56
+ * @attr data-sm - The small layout is active
57
+ * @attr data-lg - The large layout is active.
58
+ * @attr data-size - The active layout size (sm or lg).
59
+ * @example
60
+ * ```tsx
61
+ * <MediaPlayer src="audio.mp3">
62
+ * <MediaProvider />
63
+ * <DefaultAudioLayout icons={defaultLayoutIcons} />
64
+ * </MediaPlayer>
65
+ * ```
66
+ */
67
+ function DefaultAudioLayout(props: DefaultAudioLayoutProps) {
68
+ const [scrubbing, setScrubbing] = React.useState(false),
69
+ $pointer = useMediaState('pointer');
70
+
71
+ const onStartScrubbing = React.useCallback((event: React.SyntheticEvent) => {
72
+ const { target } = event,
73
+ hasTimeSlider = !!(target instanceof HTMLElement && target.closest('.vds-time-slider'));
74
+ if (!hasTimeSlider) return;
75
+ event.nativeEvent.stopImmediatePropagation();
76
+ setScrubbing(true);
77
+ }, []);
78
+
79
+ const onStopScrubbing = React.useCallback(() => {
80
+ setScrubbing(false);
81
+ }, []);
82
+
83
+ React.useEffect(() => {
84
+ if (scrubbing) return listenEvent(window, 'pointerdown', onStopScrubbing);
85
+ }, [scrubbing, onStopScrubbing]);
86
+
87
+ return (
88
+ <MediaLayout
89
+ {...props}
90
+ data-scrubbing={scrubbing ? '' : null}
91
+ onPointerDown={scrubbing ? (e) => e.stopPropagation() : undefined}
92
+ onPointerDownCapture={$pointer === 'coarse' && !scrubbing ? onStartScrubbing : undefined}
93
+ />
94
+ );
95
+ }
96
+
97
+ DefaultAudioLayout.displayName = 'DefaultAudioLayout';
98
+ export { DefaultAudioLayout };
99
+
100
+ /* -------------------------------------------------------------------------------------------------
101
+ * AudioLayout
102
+ * -----------------------------------------------------------------------------------------------*/
103
+
104
+ function AudioLayout() {
105
+ const slots = useDefaultAudioLayoutSlots();
106
+
107
+ useLayoutName('audio');
108
+
109
+ return (
110
+ <>
111
+ <DefaultAnnouncer />
112
+ <DefaultCaptions />
113
+ <Controls.Root className="vds-controls">
114
+ <Controls.Group className="vds-controls-group">
115
+ {slot(slots, 'seekBackwardButton', <DefaultSeekButton backward tooltip="top start" />)}
116
+ {slot(slots, 'playButton', <DefaultPlayButton tooltip="top center" />)}
117
+ {slot(slots, 'seekForwardButton', <DefaultSeekButton tooltip="top center" />)}
118
+ <DefaultAudioTitle />
119
+ {slot(slots, 'timeSlider', <DefaultTimeSlider />)}
120
+ <DefaultTimeInvert slots={slots} />
121
+ <DefaultVolumePopup orientation="vertical" tooltip="top" slots={slots} />
122
+ {slot(slots, 'captionButton', <DefaultCaptionButton tooltip="top center" />)}
123
+ {slot(slots, 'downloadButton', <DefaultDownloadButton />)}
124
+ <DefaultAudioMenus slots={slots} />
125
+ </Controls.Group>
126
+ </Controls.Root>
127
+ </>
128
+ );
129
+ }
130
+
131
+ AudioLayout.displayName = 'AudioLayout';
132
+
133
+ /* -------------------------------------------------------------------------------------------------
134
+ * DefaultAudioMenus
135
+ * -----------------------------------------------------------------------------------------------*/
136
+
137
+ function DefaultAudioMenus({ slots }: { slots?: Slots<DefaultLayoutMenuSlotName> }) {
138
+ const { isSmallLayout, noModal } = useDefaultLayoutContext(),
139
+ placement = noModal ? 'top end' : !isSmallLayout ? 'top end' : null;
140
+ return (
141
+ <>
142
+ {slot(
143
+ slots,
144
+ 'chaptersMenu',
145
+ <DefaultChaptersMenu tooltip="top" placement={placement} portalClass="vds-audio-layout" />,
146
+ )}
147
+ {slot(
148
+ slots,
149
+ 'settingsMenu',
150
+ <DefaultSettingsMenu
151
+ tooltip="top end"
152
+ placement={placement}
153
+ portalClass="vds-audio-layout"
154
+ slots={slots}
155
+ />,
156
+ )}
157
+ </>
158
+ );
159
+ }
160
+
161
+ DefaultAudioMenus.displayName = 'DefaultAudioMenus';
162
+
163
+ /* -------------------------------------------------------------------------------------------------
164
+ * DefaultAudioTitle
165
+ * -----------------------------------------------------------------------------------------------*/
166
+
167
+ function DefaultAudioTitle() {
168
+ const [rootEl, setRootEl] = React.useState<HTMLElement | null>(null),
169
+ media = useMediaContext(),
170
+ { translations } = useDefaultLayoutContext(),
171
+ [isTextOverflowing, setIsTextOverflowing] = React.useState(false);
172
+
173
+ const isContinued = createComputed(() => {
174
+ const { started, currentTime } = media.$state;
175
+ return started() || currentTime() > 0;
176
+ });
177
+
178
+ const $title = useSignal(
179
+ createComputed(() => {
180
+ const { title, ended } = media.$state;
181
+ if (!title()) return '';
182
+ const word = ended() ? 'Replay' : isContinued() ? 'Continue' : 'Play';
183
+ return `${i18n(translations, word)}: ${title()}`;
184
+ }),
185
+ );
186
+
187
+ const chapterTitle = useChapterTitle(),
188
+ $isContinued = useSignal(isContinued),
189
+ $chapterTitle = $isContinued ? chapterTitle : '',
190
+ isTransitionActive = useTransitionActive(rootEl);
191
+
192
+ React.useEffect(() => {
193
+ if (isTransitionActive && document.activeElement === document.body) {
194
+ media.player.el?.focus({ preventScroll: true });
195
+ }
196
+ }, []);
197
+
198
+ const onResize = React.useCallback(() => {
199
+ const el = rootEl,
200
+ isOverflowing = !!el && !isTransitionActive && el.clientWidth < el.children[0]!.clientWidth;
201
+ if (el) toggleClass(el, 'vds-marquee', isOverflowing);
202
+ setIsTextOverflowing(isOverflowing);
203
+ }, [rootEl, isTransitionActive]);
204
+
205
+ useResizeObserver(rootEl, onResize);
206
+
207
+ return $title ? (
208
+ <span className="vds-title" title={$title} ref={setRootEl}>
209
+ <AudioTitle title={$title} chapterTitle={$chapterTitle} />
210
+ {isTextOverflowing && !isTransitionActive ? (
211
+ <AudioTitle title={$title} chapterTitle={$chapterTitle} />
212
+ ) : null}
213
+ </span>
214
+ ) : (
215
+ <DefaultControlsSpacer />
216
+ );
217
+ }
218
+
219
+ DefaultAudioTitle.displayName = 'DefaultAudioTitle';
220
+
221
+ function AudioTitle({ title, chapterTitle }: { title: string; chapterTitle: string }) {
222
+ const slots = useDefaultAudioLayoutSlots();
223
+ return (
224
+ <span className="vds-title-text">
225
+ {slot(slots, 'title', title)}
226
+ {slot(slots, 'chapterTitle', <span className="vds-chapter-title">{chapterTitle}</span>)}
227
+ </span>
228
+ );
229
+ }
230
+
231
+ AudioTitle.displayName = 'AudioTitle';
@@ -0,0 +1,28 @@
1
+ import * as React from 'react';
2
+
3
+ import type { ReadSignal, WriteSignal } from 'maverick.js';
4
+
5
+ import type { DefaultLayoutProps } from './media-layout';
6
+
7
+ export const DefaultLayoutContext = React.createContext<DefaultLayoutContext>({} as any);
8
+ DefaultLayoutContext.displayName = 'DefaultLayoutContext';
9
+
10
+ interface DefaultLayoutContext extends DefaultLayoutProps {
11
+ layoutEl: ReadSignal<HTMLElement | null>;
12
+ isSmallLayout: boolean;
13
+ userPrefersAnnouncements: WriteSignal<boolean>;
14
+ userPrefersKeyboardAnimations: WriteSignal<boolean>;
15
+ }
16
+
17
+ export function useDefaultLayoutContext() {
18
+ return React.useContext(DefaultLayoutContext);
19
+ }
20
+
21
+ export function useDefaultLayoutWord(word: string) {
22
+ const { translations } = useDefaultLayoutContext();
23
+ return i18n(translations, word);
24
+ }
25
+
26
+ export function i18n(translations: any, word: string) {
27
+ return translations?.[word] ?? word;
28
+ }
@@ -0,0 +1,13 @@
1
+ import { useColorSchemePreference } from '../../../hooks/use-dom';
2
+ import type { DefaultLayoutProps } from './media-layout';
3
+
4
+ export function useColorSchemeClass(colorScheme: DefaultLayoutProps['colorScheme']) {
5
+ const systemColorPreference = useColorSchemePreference();
6
+ if (colorScheme === 'default') {
7
+ return null;
8
+ } else if (colorScheme === 'system') {
9
+ return systemColorPreference;
10
+ } else {
11
+ return colorScheme;
12
+ }
13
+ }