ts-video-player 0.1.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 (251) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +438 -0
  3. package/dist/cdn.d.ts +10 -0
  4. package/dist/cdn.d.ts.map +1 -0
  5. package/dist/cdn.min.js +1046 -0
  6. package/dist/cdn.min.js.map +54 -0
  7. package/dist/cdn.test.d.ts +2 -0
  8. package/dist/cdn.test.d.ts.map +1 -0
  9. package/dist/chunk-36x4yhjn.js +765 -0
  10. package/dist/chunk-36x4yhjn.js.map +12 -0
  11. package/dist/chunk-eajts2jv.js +4243 -0
  12. package/dist/chunk-eajts2jv.js.map +42 -0
  13. package/dist/chunk-z1ehbz9f.js +380 -0
  14. package/dist/chunk-z1ehbz9f.js.map +19 -0
  15. package/dist/config.d.ts +9 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/core/audio-gain.d.ts +67 -0
  18. package/dist/core/audio-gain.d.ts.map +1 -0
  19. package/dist/core/caption-styles.d.ts +121 -0
  20. package/dist/core/caption-styles.d.ts.map +1 -0
  21. package/dist/core/chapters.d.ts +150 -0
  22. package/dist/core/chapters.d.ts.map +1 -0
  23. package/dist/core/error-overlay.d.ts +71 -0
  24. package/dist/core/error-overlay.d.ts.map +1 -0
  25. package/dist/core/events.d.ts +119 -0
  26. package/dist/core/events.d.ts.map +1 -0
  27. package/dist/core/features.d.ts +64 -0
  28. package/dist/core/features.d.ts.map +1 -0
  29. package/dist/core/i18n.d.ts +132 -0
  30. package/dist/core/i18n.d.ts.map +1 -0
  31. package/dist/core/index.d.ts +37 -0
  32. package/dist/core/index.d.ts.map +1 -0
  33. package/dist/core/live.d.ts +130 -0
  34. package/dist/core/live.d.ts.map +1 -0
  35. package/dist/core/media-session.d.ts +38 -0
  36. package/dist/core/media-session.d.ts.map +1 -0
  37. package/dist/core/orientation.d.ts +22 -0
  38. package/dist/core/orientation.d.ts.map +1 -0
  39. package/dist/core/popover.d.ts +42 -0
  40. package/dist/core/popover.d.ts.map +1 -0
  41. package/dist/core/remote-playback.d.ts +195 -0
  42. package/dist/core/remote-playback.d.ts.map +1 -0
  43. package/dist/core/settings-menu.d.ts +132 -0
  44. package/dist/core/settings-menu.d.ts.map +1 -0
  45. package/dist/core/spinner.d.ts +67 -0
  46. package/dist/core/spinner.d.ts.map +1 -0
  47. package/dist/core/state.d.ts +142 -0
  48. package/dist/core/state.d.ts.map +1 -0
  49. package/dist/core/text-tracks.d.ts +162 -0
  50. package/dist/core/text-tracks.d.ts.map +1 -0
  51. package/dist/core/themes.d.ts +213 -0
  52. package/dist/core/themes.d.ts.map +1 -0
  53. package/dist/core/thumbnails.d.ts +124 -0
  54. package/dist/core/thumbnails.d.ts.map +1 -0
  55. package/dist/core/tooltips.d.ts +100 -0
  56. package/dist/core/tooltips.d.ts.map +1 -0
  57. package/dist/elements/base.d.ts +3 -0
  58. package/dist/elements/base.d.ts.map +1 -0
  59. package/dist/elements/index.d.ts +33 -0
  60. package/dist/elements/index.d.ts.map +1 -0
  61. package/dist/elements/index.js +55 -0
  62. package/dist/elements/index.js.map +9 -0
  63. package/dist/elements/media-airplay-button.d.ts +13 -0
  64. package/dist/elements/media-airplay-button.d.ts.map +1 -0
  65. package/dist/elements/media-error-display.d.ts +13 -0
  66. package/dist/elements/media-error-display.d.ts.map +1 -0
  67. package/dist/elements/media-fullscreen-button.d.ts +13 -0
  68. package/dist/elements/media-fullscreen-button.d.ts.map +1 -0
  69. package/dist/elements/media-live-button.d.ts +13 -0
  70. package/dist/elements/media-live-button.d.ts.map +1 -0
  71. package/dist/elements/media-mute-button.d.ts +13 -0
  72. package/dist/elements/media-mute-button.d.ts.map +1 -0
  73. package/dist/elements/media-pip-button.d.ts +13 -0
  74. package/dist/elements/media-pip-button.d.ts.map +1 -0
  75. package/dist/elements/media-play-button.d.ts +14 -0
  76. package/dist/elements/media-play-button.d.ts.map +1 -0
  77. package/dist/elements/media-playback-rate-button.d.ts +10 -0
  78. package/dist/elements/media-playback-rate-button.d.ts.map +1 -0
  79. package/dist/elements/media-preview-time.d.ts +18 -0
  80. package/dist/elements/media-preview-time.d.ts.map +1 -0
  81. package/dist/elements/media-progress-bar.d.ts +16 -0
  82. package/dist/elements/media-progress-bar.d.ts.map +1 -0
  83. package/dist/elements/media-remote-playback-button.d.ts +16 -0
  84. package/dist/elements/media-remote-playback-button.d.ts.map +1 -0
  85. package/dist/elements/media-seek-button.d.ts +9 -0
  86. package/dist/elements/media-seek-button.d.ts.map +1 -0
  87. package/dist/elements/media-settings-menu.d.ts +32 -0
  88. package/dist/elements/media-settings-menu.d.ts.map +1 -0
  89. package/dist/elements/media-time-display.d.ts +21 -0
  90. package/dist/elements/media-time-display.d.ts.map +1 -0
  91. package/dist/elements/media-time-group.d.ts +22 -0
  92. package/dist/elements/media-time-group.d.ts.map +1 -0
  93. package/dist/elements/media-time-separator.d.ts +13 -0
  94. package/dist/elements/media-time-separator.d.ts.map +1 -0
  95. package/dist/elements/media-volume-slider.d.ts +16 -0
  96. package/dist/elements/media-volume-slider.d.ts.map +1 -0
  97. package/dist/elements/utils.d.ts +27 -0
  98. package/dist/elements/utils.d.ts.map +1 -0
  99. package/dist/elements/video-player.d.ts +23 -0
  100. package/dist/elements/video-player.d.ts.map +1 -0
  101. package/dist/elements/video-skin.d.ts +23 -0
  102. package/dist/elements/video-skin.d.ts.map +1 -0
  103. package/dist/features/captions.d.ts +8 -0
  104. package/dist/features/captions.d.ts.map +1 -0
  105. package/dist/features/create-player.d.ts +45 -0
  106. package/dist/features/create-player.d.ts.map +1 -0
  107. package/dist/features/fullscreen.d.ts +8 -0
  108. package/dist/features/fullscreen.d.ts.map +1 -0
  109. package/dist/features/gestures.d.ts +8 -0
  110. package/dist/features/gestures.d.ts.map +1 -0
  111. package/dist/features/index.d.ts +26 -0
  112. package/dist/features/index.d.ts.map +1 -0
  113. package/dist/features/index.js +31 -0
  114. package/dist/features/index.js.map +9 -0
  115. package/dist/features/keyboard.d.ts +8 -0
  116. package/dist/features/keyboard.d.ts.map +1 -0
  117. package/dist/features/pip.d.ts +8 -0
  118. package/dist/features/pip.d.ts.map +1 -0
  119. package/dist/features/playback.d.ts +8 -0
  120. package/dist/features/playback.d.ts.map +1 -0
  121. package/dist/features/quality.d.ts +8 -0
  122. package/dist/features/quality.d.ts.map +1 -0
  123. package/dist/features/types.d.ts +26 -0
  124. package/dist/features/types.d.ts.map +1 -0
  125. package/dist/features/volume.d.ts +8 -0
  126. package/dist/features/volume.d.ts.map +1 -0
  127. package/dist/index.d.ts +84 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +8149 -0
  130. package/dist/index.js.map +31 -0
  131. package/dist/layouts/index.d.ts +58 -0
  132. package/dist/layouts/index.d.ts.map +1 -0
  133. package/dist/player.d.ts +90 -0
  134. package/dist/player.d.ts.map +1 -0
  135. package/dist/plugins/ads.d.ts +311 -0
  136. package/dist/plugins/ads.d.ts.map +1 -0
  137. package/dist/plugins/analytics.d.ts +203 -0
  138. package/dist/plugins/analytics.d.ts.map +1 -0
  139. package/dist/plugins/end-screen.d.ts +184 -0
  140. package/dist/plugins/end-screen.d.ts.map +1 -0
  141. package/dist/plugins/index.d.ts +13 -0
  142. package/dist/plugins/index.d.ts.map +1 -0
  143. package/dist/plugins/index.js +20 -0
  144. package/dist/plugins/index.js.map +9 -0
  145. package/dist/plugins/skip-segments.d.ts +159 -0
  146. package/dist/plugins/skip-segments.d.ts.map +1 -0
  147. package/dist/plugins/watermark.d.ts +157 -0
  148. package/dist/plugins/watermark.d.ts.map +1 -0
  149. package/dist/providers/base.d.ts +56 -0
  150. package/dist/providers/base.d.ts.map +1 -0
  151. package/dist/providers/dash.d.ts +94 -0
  152. package/dist/providers/dash.d.ts.map +1 -0
  153. package/dist/providers/hls.d.ts +182 -0
  154. package/dist/providers/hls.d.ts.map +1 -0
  155. package/dist/providers/html5.d.ts +64 -0
  156. package/dist/providers/html5.d.ts.map +1 -0
  157. package/dist/providers/index.d.ts +41 -0
  158. package/dist/providers/index.d.ts.map +1 -0
  159. package/dist/providers/vimeo.d.ts +157 -0
  160. package/dist/providers/vimeo.d.ts.map +1 -0
  161. package/dist/providers/youtube.d.ts +134 -0
  162. package/dist/providers/youtube.d.ts.map +1 -0
  163. package/dist/stx/index.d.ts +59 -0
  164. package/dist/stx/index.d.ts.map +1 -0
  165. package/dist/stx/index.js +480 -0
  166. package/dist/stx/index.js.map +11 -0
  167. package/dist/types.d.ts +724 -0
  168. package/dist/types.d.ts.map +1 -0
  169. package/dist/ui/components.d.ts +121 -0
  170. package/dist/ui/components.d.ts.map +1 -0
  171. package/dist/ui/index.d.ts +9 -0
  172. package/dist/ui/index.d.ts.map +1 -0
  173. package/dist/ui/index.js +16 -0
  174. package/dist/ui/index.js.map +9 -0
  175. package/package.json +109 -0
  176. package/src/cdn.test.ts +10 -0
  177. package/src/cdn.ts +60 -0
  178. package/src/config.ts +25 -0
  179. package/src/core/audio-gain.ts +171 -0
  180. package/src/core/caption-styles.ts +568 -0
  181. package/src/core/chapters.ts +551 -0
  182. package/src/core/error-overlay.ts +354 -0
  183. package/src/core/events.ts +552 -0
  184. package/src/core/features.ts +287 -0
  185. package/src/core/i18n.ts +590 -0
  186. package/src/core/index.ts +249 -0
  187. package/src/core/live.ts +472 -0
  188. package/src/core/media-session.ts +137 -0
  189. package/src/core/orientation.ts +57 -0
  190. package/src/core/popover.ts +143 -0
  191. package/src/core/remote-playback.ts +661 -0
  192. package/src/core/settings-menu.ts +630 -0
  193. package/src/core/spinner.ts +310 -0
  194. package/src/core/state.ts +476 -0
  195. package/src/core/text-tracks.ts +599 -0
  196. package/src/core/themes.ts +607 -0
  197. package/src/core/thumbnails.ts +457 -0
  198. package/src/core/tooltips.ts +370 -0
  199. package/src/elements/base.ts +2 -0
  200. package/src/elements/index.ts +82 -0
  201. package/src/elements/media-airplay-button.ts +78 -0
  202. package/src/elements/media-error-display.ts +47 -0
  203. package/src/elements/media-fullscreen-button.ts +72 -0
  204. package/src/elements/media-live-button.ts +65 -0
  205. package/src/elements/media-mute-button.ts +69 -0
  206. package/src/elements/media-pip-button.ts +66 -0
  207. package/src/elements/media-play-button.ts +69 -0
  208. package/src/elements/media-playback-rate-button.ts +59 -0
  209. package/src/elements/media-preview-time.ts +75 -0
  210. package/src/elements/media-progress-bar.ts +200 -0
  211. package/src/elements/media-remote-playback-button.ts +108 -0
  212. package/src/elements/media-seek-button.ts +50 -0
  213. package/src/elements/media-settings-menu.ts +302 -0
  214. package/src/elements/media-time-display.ts +99 -0
  215. package/src/elements/media-time-group.ts +41 -0
  216. package/src/elements/media-time-separator.ts +35 -0
  217. package/src/elements/media-volume-slider.ts +140 -0
  218. package/src/elements/utils.ts +82 -0
  219. package/src/elements/video-player.ts +175 -0
  220. package/src/elements/video-skin.ts +127 -0
  221. package/src/features/captions.ts +56 -0
  222. package/src/features/create-player.ts +91 -0
  223. package/src/features/fullscreen.ts +44 -0
  224. package/src/features/gestures.ts +44 -0
  225. package/src/features/index.ts +44 -0
  226. package/src/features/keyboard.ts +89 -0
  227. package/src/features/pip.ts +47 -0
  228. package/src/features/playback.ts +68 -0
  229. package/src/features/quality.ts +19 -0
  230. package/src/features/types.ts +28 -0
  231. package/src/features/volume.ts +46 -0
  232. package/src/index.ts +635 -0
  233. package/src/layouts/index.ts +672 -0
  234. package/src/player.ts +821 -0
  235. package/src/plugins/ads.ts +1045 -0
  236. package/src/plugins/analytics.ts +673 -0
  237. package/src/plugins/end-screen.ts +793 -0
  238. package/src/plugins/index.ts +61 -0
  239. package/src/plugins/skip-segments.ts +537 -0
  240. package/src/plugins/watermark.ts +537 -0
  241. package/src/providers/base.ts +197 -0
  242. package/src/providers/dash.ts +588 -0
  243. package/src/providers/hls.ts +624 -0
  244. package/src/providers/html5.ts +473 -0
  245. package/src/providers/index.ts +97 -0
  246. package/src/providers/vimeo.ts +533 -0
  247. package/src/providers/youtube.ts +542 -0
  248. package/src/stx/index.ts +606 -0
  249. package/src/types.ts +874 -0
  250. package/src/ui/components.ts +910 -0
  251. package/src/ui/index.ts +29 -0
package/src/types.ts ADDED
@@ -0,0 +1,874 @@
1
+ /**
2
+ * ts-video-player Types
3
+ *
4
+ * Core type definitions for the video player library.
5
+ *
6
+ * @module types
7
+ */
8
+
9
+ // =============================================================================
10
+ // Media Source Types
11
+ // =============================================================================
12
+
13
+ /**
14
+ * Supported media source types
15
+ */
16
+ export type MediaType = 'video' | 'audio' | 'unknown'
17
+
18
+ /**
19
+ * Stream types
20
+ */
21
+ export type StreamType = 'on-demand' | 'live' | 'live:dvr' | 'll-live' | 'unknown'
22
+
23
+ /**
24
+ * Provider types
25
+ */
26
+ export type ProviderType = 'video' | 'audio' | 'hls' | 'dash' | 'youtube' | 'vimeo' | 'unknown'
27
+
28
+ /**
29
+ * Media source
30
+ */
31
+ export interface MediaSource {
32
+ /** Source URL */
33
+ src: string
34
+ /** MIME type (e.g., 'video/mp4', 'application/x-mpegURL') */
35
+ type?: string
36
+ /** Source quality label */
37
+ quality?: string
38
+ /** Source width */
39
+ width?: number
40
+ /** Source height */
41
+ height?: number
42
+ /** Bitrate in bps */
43
+ bitrate?: number
44
+ /** Codec string */
45
+ codec?: string
46
+ }
47
+
48
+ /**
49
+ * YouTube source configuration
50
+ */
51
+ export interface YouTubeSource {
52
+ src: string
53
+ type: 'youtube'
54
+ /** Video ID extracted from URL */
55
+ videoId?: string
56
+ /** Start time in seconds */
57
+ startTime?: number
58
+ /** End time in seconds */
59
+ endTime?: number
60
+ }
61
+
62
+ /**
63
+ * Vimeo source configuration
64
+ */
65
+ export interface VimeoSource {
66
+ src: string
67
+ type: 'vimeo'
68
+ /** Video ID extracted from URL */
69
+ videoId?: string
70
+ /** Hash for private videos */
71
+ hash?: string
72
+ }
73
+
74
+ /**
75
+ * HLS source configuration
76
+ */
77
+ export interface HLSSource {
78
+ src: string
79
+ type: 'application/x-mpegURL' | 'application/vnd.apple.mpegurl'
80
+ /** HLS.js configuration overrides */
81
+ config?: Record<string, unknown>
82
+ }
83
+
84
+ export interface DRMConfig {
85
+ widevine?: { url: string, headers?: Record<string, string> }
86
+ playready?: { url: string, headers?: Record<string, string> }
87
+ fairplay?: { url: string, certificateUrl: string, headers?: Record<string, string> }
88
+ }
89
+
90
+ /**
91
+ * DASH source configuration
92
+ */
93
+ export interface DASHSource {
94
+ src: string
95
+ type: 'application/dash+xml'
96
+ /** dash.js configuration overrides */
97
+ config?: Record<string, unknown>
98
+ /** License endpoints for encrypted DASH content. */
99
+ drm?: DRMConfig
100
+ }
101
+
102
+ /**
103
+ * Any supported source type
104
+ */
105
+ export type Src = string | MediaSource | YouTubeSource | VimeoSource | HLSSource | DASHSource
106
+
107
+ // =============================================================================
108
+ // Player State Types
109
+ // =============================================================================
110
+
111
+ /**
112
+ * Preload strategy
113
+ */
114
+ export type PreloadStrategy = 'none' | 'metadata' | 'auto'
115
+
116
+ /**
117
+ * Crossorigin attribute
118
+ */
119
+ export type CrossOrigin = 'anonymous' | 'use-credentials' | ''
120
+
121
+ /**
122
+ * Loading state
123
+ */
124
+ export type LoadingState = 'idle' | 'loading' | 'loaded' | 'error'
125
+
126
+ /**
127
+ * Playback state
128
+ */
129
+ export type PlaybackState = 'idle' | 'buffering' | 'playing' | 'paused' | 'ended'
130
+
131
+ /**
132
+ * Feature availability state.
133
+ * - 'available': Feature is supported and can be used right now
134
+ * - 'unavailable': Feature could work but isn't ready yet (e.g., waiting for media to load)
135
+ * - 'unsupported': Feature is not supported on this platform/browser
136
+ */
137
+ export type FeatureAvailability = 'available' | 'unavailable' | 'unsupported'
138
+
139
+ /**
140
+ * Time range representation
141
+ */
142
+ export interface TimeRange {
143
+ start: number
144
+ end: number
145
+ }
146
+
147
+ /**
148
+ * Video quality representation
149
+ */
150
+ export interface VideoQuality {
151
+ id: string
152
+ width: number
153
+ height: number
154
+ bitrate: number
155
+ codec?: string
156
+ selected: boolean
157
+ }
158
+
159
+ /**
160
+ * Audio track representation
161
+ */
162
+ export interface AudioTrack {
163
+ id: string
164
+ label: string
165
+ language: string
166
+ kind: string
167
+ selected: boolean
168
+ }
169
+
170
+ /**
171
+ * Text track/caption representation
172
+ */
173
+ export interface TextTrack {
174
+ id: string
175
+ kind: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata'
176
+ label: string
177
+ language: string
178
+ src?: string
179
+ default?: boolean
180
+ mode: 'disabled' | 'hidden' | 'showing'
181
+ cues: TextTrackCue[]
182
+ }
183
+
184
+ export interface TextTrackSource {
185
+ src: string
186
+ kind: TextTrack['kind']
187
+ label?: string
188
+ language?: string
189
+ default?: boolean
190
+ }
191
+
192
+ /**
193
+ * Text track cue
194
+ */
195
+ export interface TextTrackCue {
196
+ id: string
197
+ startTime: number
198
+ endTime: number
199
+ text: string
200
+ position?: 'auto' | number
201
+ line?: 'auto' | number
202
+ align?: 'start' | 'center' | 'end' | 'left' | 'right'
203
+ }
204
+
205
+ /**
206
+ * Player state
207
+ */
208
+ export interface PlayerState {
209
+ // === Source ===
210
+ /** Current source */
211
+ src: Src | null
212
+ /** All available sources */
213
+ sources: Src[]
214
+ /** Current source index */
215
+ currentSourceIndex: number
216
+ /** Media type (video/audio) */
217
+ mediaType: MediaType
218
+ /** Stream type (on-demand/live) */
219
+ streamType: StreamType
220
+ /** Provider type */
221
+ providerType: ProviderType
222
+
223
+ // === Loading ===
224
+ /** Loading state */
225
+ loadingState: LoadingState
226
+ /** Preload strategy */
227
+ preload: PreloadStrategy
228
+ /** Whether media can play */
229
+ canPlay: boolean
230
+ /** Whether media can play through without buffering */
231
+ canPlayThrough: boolean
232
+ /** Error if any */
233
+ error: MediaError | null
234
+
235
+ // === Playback ===
236
+ /** Playback state */
237
+ playbackState: PlaybackState
238
+ /** Whether media is paused */
239
+ paused: boolean
240
+ /** Whether media is playing */
241
+ playing: boolean
242
+ /** Whether playback has started at least once */
243
+ started: boolean
244
+ /** Whether media has ended */
245
+ ended: boolean
246
+ /** Whether media is seeking */
247
+ seeking: boolean
248
+ /** Whether media is waiting/buffering */
249
+ waiting: boolean
250
+ /** Current time in seconds */
251
+ currentTime: number
252
+ /** Duration in seconds */
253
+ duration: number
254
+ /** Playback rate (1.0 = normal) */
255
+ playbackRate: number
256
+ /** Whether to loop playback */
257
+ loop: boolean
258
+ /** Whether to autoplay */
259
+ autoplay: boolean
260
+ /** Whether to play inline on mobile */
261
+ playsinline: boolean
262
+
263
+ // === Volume ===
264
+ /** Whether muted */
265
+ muted: boolean
266
+ /** Volume (0-1) */
267
+ volume: number
268
+
269
+ // === Buffering ===
270
+ /** Buffered time ranges */
271
+ buffered: TimeRange[]
272
+ /** Total buffered percentage (0-1) */
273
+ bufferedAmount: number
274
+ /** Seekable time ranges */
275
+ seekable: TimeRange[]
276
+
277
+ // === Dimensions ===
278
+ /** Video width */
279
+ videoWidth: number
280
+ /** Video height */
281
+ videoHeight: number
282
+ /** Aspect ratio */
283
+ aspectRatio: number
284
+
285
+ // === Tracks ===
286
+ /** Available qualities */
287
+ qualities: VideoQuality[]
288
+ /** Auto quality selection enabled */
289
+ autoQuality: boolean
290
+ /** Available audio tracks */
291
+ audioTracks: AudioTrack[]
292
+ /** Available text tracks */
293
+ textTracks: TextTrack[]
294
+
295
+ // === Fullscreen/PiP ===
296
+ /** Whether in fullscreen */
297
+ fullscreen: boolean
298
+ /** Whether Picture-in-Picture is active */
299
+ pictureInPicture: boolean
300
+ /** @deprecated Use fullscreenAvailability instead */
301
+ canFullscreen: boolean
302
+ /** @deprecated Use pipAvailability instead */
303
+ canPictureInPicture: boolean
304
+
305
+ // === Feature Availability ===
306
+ /** Volume control availability (iOS Safari silently ignores volume changes) */
307
+ volumeAvailability: FeatureAvailability
308
+ /** Fullscreen API availability */
309
+ fullscreenAvailability: FeatureAvailability
310
+ /** Picture-in-Picture availability */
311
+ pipAvailability: FeatureAvailability
312
+
313
+ // === UI ===
314
+ /** Whether controls are visible */
315
+ controlsVisible: boolean
316
+ /** Whether user is interacting */
317
+ userActive: boolean
318
+ /** Whether pointer is over player */
319
+ pointerOver: boolean
320
+
321
+ // === Metadata ===
322
+ /** Video title */
323
+ title: string
324
+ /** Poster image URL */
325
+ poster: string
326
+ }
327
+
328
+ // =============================================================================
329
+ // Player Options
330
+ // =============================================================================
331
+
332
+ /**
333
+ * Player initialization options
334
+ */
335
+ export interface PlayerOptions {
336
+ // === Source ===
337
+ /** Media source(s) */
338
+ src?: Src | Src[]
339
+ /** Media type */
340
+ mediaType?: MediaType
341
+ /** Poster image URL */
342
+ poster?: string
343
+ /** Video title for accessibility */
344
+ title?: string
345
+ /** External captions, subtitles, chapters, and metadata tracks */
346
+ tracks?: TextTrackSource[]
347
+
348
+ // === Playback ===
349
+ /** Autoplay on load */
350
+ autoplay?: boolean
351
+ /** Loop playback */
352
+ loop?: boolean
353
+ /** Mute audio */
354
+ muted?: boolean
355
+ /** Initial volume (0-1) */
356
+ volume?: number
357
+ /** Playback rate */
358
+ playbackRate?: number
359
+ /** Play inline on mobile */
360
+ playsinline?: boolean
361
+ /** Preload strategy */
362
+ preload?: PreloadStrategy
363
+ /** Crossorigin attribute */
364
+ crossorigin?: CrossOrigin
365
+ /** Native media controls restrictions */
366
+ controlsList?: Array<'nodownload' | 'nofullscreen' | 'noremoteplayback'>
367
+ /** Disable native Picture-in-Picture */
368
+ disablePictureInPicture?: boolean
369
+
370
+ // === Controls ===
371
+ /** Show native controls */
372
+ controls?: boolean
373
+ /** Custom control configuration */
374
+ controlsConfig?: ControlsConfig
375
+ /** Keyboard shortcuts */
376
+ keyboard?: boolean | KeyboardConfig
377
+ /** Auto-hide controls timeout in ms */
378
+ controlsTimeout?: number
379
+
380
+ // === Accessibility ===
381
+ /** Language for accessibility */
382
+ language?: string
383
+ /** Enable/disable captions by default */
384
+ captions?: boolean
385
+ /** Screen reader announcements */
386
+ announcements?: boolean
387
+
388
+ // === Fullscreen ===
389
+ /** Fullscreen container element */
390
+ fullscreenContainer?: HTMLElement
391
+ /** Preferred fullscreen mode */
392
+ fullscreenMode?: 'native' | 'fallback'
393
+
394
+ // === Providers ===
395
+ /** HLS.js configuration */
396
+ hlsConfig?: Record<string, unknown>
397
+ /** Custom HLS.js CDN URL (overrides default jsdelivr URL) */
398
+ hlsCdnUrl?: string
399
+ /** dash.js configuration */
400
+ dashConfig?: Record<string, unknown>
401
+ /** Custom dash.js CDN URL (overrides default dashjs.org URL) */
402
+ dashCdnUrl?: string
403
+ /** YouTube player parameters */
404
+ youtubeParams?: Record<string, string | number | boolean>
405
+ /** Vimeo player parameters */
406
+ vimeoParams?: Record<string, string | number | boolean>
407
+
408
+ // === Media Session ===
409
+ /** Media Session API integration for lock screen / notification controls */
410
+ mediaSession?: boolean | MediaSessionConfig
411
+
412
+ // === Orientation ===
413
+ /** Lock orientation to landscape when entering fullscreen on mobile */
414
+ fullscreenOrientationLock?: boolean
415
+
416
+ // === Events ===
417
+ /** Event listeners */
418
+ on?: Partial<PlayerEventMap>
419
+
420
+ // === Storage ===
421
+ /** Persist volume/muted state */
422
+ storage?: boolean | StorageConfig
423
+ }
424
+
425
+ /**
426
+ * Media Session configuration
427
+ */
428
+ export interface MediaSessionConfig {
429
+ /** Title to display on lock screen */
430
+ title?: string
431
+ /** Artist name */
432
+ artist?: string
433
+ /** Album name */
434
+ album?: string
435
+ /** Artwork images for lock screen */
436
+ artwork?: MediaImage[]
437
+ }
438
+
439
+ /**
440
+ * Controls configuration
441
+ */
442
+ export interface ControlsConfig {
443
+ /** Show play button */
444
+ play?: boolean
445
+ /** Show progress/seek bar */
446
+ progress?: boolean
447
+ /** Show current time */
448
+ currentTime?: boolean
449
+ /** Show duration */
450
+ duration?: boolean
451
+ /** Show volume slider */
452
+ volume?: boolean
453
+ /** Show mute button */
454
+ mute?: boolean
455
+ /** Show captions button */
456
+ captions?: boolean
457
+ /** Show settings menu */
458
+ settings?: boolean
459
+ /** Show fullscreen button */
460
+ fullscreen?: boolean
461
+ /** Show PiP button */
462
+ pip?: boolean
463
+ /** Show playback speed selector */
464
+ speed?: boolean
465
+ /** Show quality selector */
466
+ quality?: boolean
467
+ /** Custom controls to add */
468
+ custom?: CustomControl[]
469
+ }
470
+
471
+ /**
472
+ * Custom control definition
473
+ */
474
+ export interface CustomControl {
475
+ /** Control name/id */
476
+ name: string
477
+ /** Position in controls bar */
478
+ position: 'left' | 'center' | 'right'
479
+ /** Control HTML or render function */
480
+ content: string | (() => HTMLElement)
481
+ /** Click handler */
482
+ onClick?: (player: Player) => void
483
+ }
484
+
485
+ /**
486
+ * Keyboard configuration
487
+ */
488
+ export interface KeyboardConfig {
489
+ /** Enable global keyboard shortcuts */
490
+ global?: boolean
491
+ /** Seek step in seconds */
492
+ seekStep?: number
493
+ /** Volume step (0-1) */
494
+ volumeStep?: number
495
+ /** Custom key bindings */
496
+ // eslint-disable-next-line pickier/no-unused-vars
497
+ bindings?: Record<string, string | ((player: Player) => void)>
498
+ }
499
+
500
+ /**
501
+ * Storage configuration
502
+ */
503
+ export interface StorageConfig {
504
+ /** Storage key prefix */
505
+ prefix?: string
506
+ /** Storage type */
507
+ type?: 'local' | 'session'
508
+ /** Properties to persist */
509
+ persist?: ('volume' | 'muted' | 'playbackRate' | 'quality' | 'captions')[]
510
+ }
511
+
512
+ // =============================================================================
513
+ // Provider Types
514
+ // =============================================================================
515
+
516
+ /**
517
+ * Provider interface for different media sources
518
+ */
519
+ export interface Provider {
520
+ /** Provider name */
521
+ readonly name: string
522
+ /** Provider type */
523
+ readonly type: ProviderType
524
+ /** Current media element */
525
+ readonly mediaElement: HTMLVideoElement | HTMLAudioElement | HTMLIFrameElement | null
526
+ /** Whether provider is ready */
527
+ readonly ready: boolean
528
+
529
+ // === Lifecycle ===
530
+ /** Setup the provider */
531
+ setup(container: HTMLElement, options: PlayerOptions): Promise<void>
532
+ /** Destroy the provider */
533
+ destroy(): void
534
+
535
+ // === Loading ===
536
+ /** Load a source */
537
+ load(src: Src | Src[]): Promise<void>
538
+ /** Check if provider can play source */
539
+ canPlay(src: Src): boolean
540
+
541
+ // === Playback ===
542
+ /** Play media */
543
+ play(): Promise<void>
544
+ /** Pause media */
545
+ pause(): void
546
+ /** Stop media (reset) */
547
+ stop(): void
548
+
549
+ // === Seeking ===
550
+ /** Seek to time */
551
+ seekTo(time: number): void
552
+ /** Get current time */
553
+ getCurrentTime(): number
554
+ /** Get duration */
555
+ getDuration(): number
556
+
557
+ // === Volume ===
558
+ /** Set volume */
559
+ setVolume(volume: number): void
560
+ /** Get volume */
561
+ getVolume(): number
562
+ /** Set muted */
563
+ setMuted(muted: boolean): void
564
+ /** Get muted */
565
+ getMuted(): boolean
566
+
567
+ // === Playback Rate ===
568
+ /** Set playback rate */
569
+ setPlaybackRate(rate: number): void
570
+ /** Get playback rate */
571
+ getPlaybackRate(): number
572
+
573
+ // === Quality ===
574
+ /** Get available qualities */
575
+ getQualities(): VideoQuality[]
576
+ /** Set quality */
577
+ setQuality(quality: VideoQuality | 'auto'): void
578
+
579
+ // === Tracks ===
580
+ /** Get text tracks */
581
+ getTextTracks(): TextTrack[]
582
+ /** Set text track mode */
583
+ setTextTrackMode(trackId: string, mode: 'disabled' | 'hidden' | 'showing'): void
584
+ /** Get audio tracks */
585
+ getAudioTracks(): AudioTrack[]
586
+ /** Set audio track */
587
+ setAudioTrack(trackId: string): void
588
+
589
+ // === Fullscreen/PiP ===
590
+ /** Enter fullscreen */
591
+ enterFullscreen(): Promise<void>
592
+ /** Exit fullscreen */
593
+ exitFullscreen(): Promise<void>
594
+ /** Enter Picture-in-Picture */
595
+ enterPiP(): Promise<void>
596
+ /** Exit Picture-in-Picture */
597
+ exitPiP(): Promise<void>
598
+
599
+ // === Feature Availability ===
600
+ /** Check feature availability */
601
+ getFeatureAvailability(feature: 'volume' | 'fullscreen' | 'pip'): FeatureAvailability
602
+
603
+ // === Events ===
604
+ /** Add event listener */
605
+ on<K extends keyof ProviderEventMap>(event: K, handler: ProviderEventMap[K]): void
606
+ /** Remove event listener */
607
+ off<K extends keyof ProviderEventMap>(event: K, handler: ProviderEventMap[K]): void
608
+ }
609
+
610
+ /**
611
+ * Provider loader interface
612
+ */
613
+ export interface ProviderLoader {
614
+ /** Loader name */
615
+ name: string
616
+ /** Provider type this loader creates */
617
+ type: ProviderType
618
+ /** Check if loader can play source */
619
+ canPlay(src: Src): boolean
620
+ /** Detect media type from source */
621
+ mediaType(src: Src): MediaType
622
+ /** Preconnect hint URLs */
623
+ preconnect?(): string[]
624
+ /** Load/create the provider */
625
+ load(container: HTMLElement, options: PlayerOptions): Promise<Provider>
626
+ }
627
+
628
+ // =============================================================================
629
+ // Event Types
630
+ // =============================================================================
631
+
632
+ /**
633
+ * Media error
634
+ */
635
+ export interface MediaError {
636
+ code: number
637
+ message: string
638
+ details?: unknown
639
+ }
640
+
641
+ /**
642
+ * Provider event map (internal events)
643
+ */
644
+ export interface ProviderEventMap {
645
+ ready: () => void
646
+ loadstart: () => void
647
+ loadedmetadata: () => void
648
+ loadeddata: () => void
649
+ canplay: () => void
650
+ canplaythrough: () => void
651
+ play: () => void
652
+ pause: () => void
653
+ playing: () => void
654
+ waiting: () => void
655
+ seeking: () => void
656
+ seeked: () => void
657
+ timeupdate: (time: number) => void
658
+ durationchange: (duration: number) => void
659
+ volumechange: (volume: number, muted: boolean) => void
660
+ ratechange: (rate: number) => void
661
+ progress: (buffered: TimeRange[]) => void
662
+ ended: () => void
663
+ error: (error: MediaError) => void
664
+ statechange: (state: Partial<PlayerState>) => void
665
+ qualitychange: (quality: VideoQuality | null) => void
666
+ audiotrackchange: (track: AudioTrack | null) => void
667
+ texttrackchange: (track: TextTrack | null) => void
668
+ fullscreenchange: (fullscreen: boolean) => void
669
+ pipchange: (pip: boolean) => void
670
+ availabilitychange: (feature: string, availability: FeatureAvailability) => void
671
+ }
672
+
673
+ /**
674
+ * Player event map (public events)
675
+ */
676
+ export interface PlayerEventMap extends ProviderEventMap {
677
+ init: () => void
678
+ destroy: () => void
679
+ sourceschange: (sources: Src[]) => void
680
+ providerchange: (provider: Provider | null) => void
681
+ controlschange: (visible: boolean) => void
682
+ useractivitychange: (active: boolean) => void
683
+ }
684
+
685
+ // =============================================================================
686
+ // UI Component Types
687
+ // =============================================================================
688
+
689
+ /**
690
+ * UI component interface
691
+ */
692
+ export interface UIComponent {
693
+ /** Component name */
694
+ name: string
695
+ /** Render the component */
696
+ render(player: Player): HTMLElement
697
+ /** Update the component */
698
+ update?(state: PlayerState): void
699
+ /** Destroy the component */
700
+ destroy?(): void
701
+ }
702
+
703
+ /**
704
+ * Tooltip options
705
+ */
706
+ export interface TooltipOptions {
707
+ content: string | (() => string)
708
+ position?: 'top' | 'bottom' | 'left' | 'right'
709
+ delay?: number
710
+ }
711
+
712
+ /**
713
+ * Menu item
714
+ */
715
+ export interface MenuItem {
716
+ id: string
717
+ label: string
718
+ value?: unknown
719
+ checked?: boolean
720
+ disabled?: boolean
721
+ icon?: string
722
+ children?: MenuItem[]
723
+ }
724
+
725
+ /**
726
+ * Slider options
727
+ */
728
+ export interface SliderOptions {
729
+ min: number
730
+ max: number
731
+ step: number
732
+ value: number
733
+ orientation?: 'horizontal' | 'vertical'
734
+ disabled?: boolean
735
+ onChange?: (value: number) => void
736
+ onInput?: (value: number) => void
737
+ }
738
+
739
+ // =============================================================================
740
+ // Player Class Forward Declaration
741
+ // =============================================================================
742
+
743
+ /**
744
+ * Player instance (forward declaration for circular refs)
745
+ */
746
+ export interface Player {
747
+ // Properties
748
+ readonly el: HTMLElement
749
+ readonly state: PlayerState
750
+ readonly provider: Provider | null
751
+ readonly ready: boolean
752
+
753
+ // Lifecycle
754
+ destroy(): void
755
+
756
+ // Source
757
+ setSrc(src: Src | Src[]): void
758
+ getSrc(): Src | null
759
+
760
+ // Playback
761
+ play(): Promise<void>
762
+ pause(): void
763
+ togglePlay(): void
764
+ stop(): void
765
+
766
+ // Seeking
767
+ seekTo(time: number): void
768
+ seekBy(offset: number): void
769
+
770
+ // Volume
771
+ setVolume(volume: number): void
772
+ setMuted(muted: boolean): void
773
+ toggleMute(): void
774
+
775
+ // Playback Rate
776
+ setPlaybackRate(rate: number): void
777
+
778
+ // Fullscreen/PiP
779
+ enterFullscreen(): Promise<void>
780
+ exitFullscreen(): Promise<void>
781
+ toggleFullscreen(): Promise<void>
782
+ enterPiP(): Promise<void>
783
+ exitPiP(): Promise<void>
784
+ togglePiP(): Promise<void>
785
+
786
+ // Tracks
787
+ setQuality(quality: VideoQuality | 'auto'): void
788
+ setTextTrack(trackId: string, mode: 'disabled' | 'hidden' | 'showing'): void
789
+ setAudioTrack(trackId: string): void
790
+
791
+ // State Subscription
792
+ subscribe(
793
+ // eslint-disable-next-line pickier/no-unused-vars
794
+ keyOrListener: keyof PlayerState | '*' | ((state: PlayerState, key?: keyof PlayerState) => void),
795
+ listener?: (state: PlayerState, key?: keyof PlayerState) => void,
796
+ ): () => void
797
+
798
+ // Events
799
+ on<K extends keyof PlayerEventMap>(event: K, handler: PlayerEventMap[K]): void
800
+ off<K extends keyof PlayerEventMap>(event: K, handler: PlayerEventMap[K]): void
801
+ once<K extends keyof PlayerEventMap>(event: K, handler: PlayerEventMap[K]): void
802
+ }
803
+
804
+ // =============================================================================
805
+ // stx Integration Types
806
+ // =============================================================================
807
+
808
+ /**
809
+ * Video component props for stx
810
+ */
811
+ export interface VideoComponentProps {
812
+ /** Media source(s) */
813
+ src: Src | Src[]
814
+ /** Poster image */
815
+ poster?: string
816
+ /** Video title */
817
+ title?: string
818
+ /** CSS class */
819
+ class?: string
820
+ /** CSS style */
821
+ style?: string
822
+ /** Element ID */
823
+ id?: string
824
+ /** Width */
825
+ width?: number | string
826
+ /** Height */
827
+ height?: number | string
828
+ /** Player options */
829
+ options?: Partial<PlayerOptions>
830
+ /** Lazy load */
831
+ lazy?: boolean
832
+ /** Autoplay */
833
+ autoplay?: boolean
834
+ /** Loop */
835
+ loop?: boolean
836
+ /** Muted */
837
+ muted?: boolean
838
+ /** Controls */
839
+ controls?: boolean
840
+ /** Playsinline */
841
+ playsinline?: boolean
842
+ /** Preload */
843
+ preload?: PreloadStrategy
844
+ /** Cross-origin mode */
845
+ crossorigin?: CrossOrigin
846
+ /** Native media controls restrictions */
847
+ controlsList?: Array<'nodownload' | 'nofullscreen' | 'noremoteplayback'>
848
+ /** Disable native Picture-in-Picture */
849
+ disablePictureInPicture?: boolean
850
+ /** Theme */
851
+ theme?: 'default' | 'minimal' | 'modern' | string
852
+ }
853
+
854
+ /**
855
+ * Video directive options for stx
856
+ */
857
+ export interface VideoDirectiveOptions extends VideoComponentProps {
858
+ /** Placeholder strategy */
859
+ placeholder?: 'blur' | 'color' | 'none'
860
+ /** Placeholder color */
861
+ placeholderColor?: string
862
+ }
863
+
864
+ /**
865
+ * Render result for stx
866
+ */
867
+ export interface VideoRenderResult {
868
+ /** HTML output */
869
+ html: string
870
+ /** CSS to inject */
871
+ css?: string
872
+ /** JavaScript to inject */
873
+ script?: string
874
+ }