@locpd/vidstack 1.12.14

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 (242) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +22 -0
  3. package/analyze.json.d.ts +8 -0
  4. package/bundle.d.ts +1 -0
  5. package/cdn/chunks/vidstack-2f5gzOW6.js +1 -0
  6. package/cdn/chunks/vidstack-BYgY9wmd.js +1 -0
  7. package/cdn/chunks/vidstack-BfBBPhXV.js +1 -0
  8. package/cdn/chunks/vidstack-Bjo5esRp.js +1 -0
  9. package/cdn/chunks/vidstack-BuL67v3q.js +1 -0
  10. package/cdn/chunks/vidstack-C0msPRTd.js +3 -0
  11. package/cdn/chunks/vidstack-CJNLoJPa.js +1 -0
  12. package/cdn/chunks/vidstack-CQSpZ7X8.js +16 -0
  13. package/cdn/chunks/vidstack-C_AxqLKV.js +1 -0
  14. package/cdn/chunks/vidstack-CioT3Yw2.js +1 -0
  15. package/cdn/chunks/vidstack-CrqkytHl.js +1 -0
  16. package/cdn/chunks/vidstack-D0M8R0ZU.js +1 -0
  17. package/cdn/chunks/vidstack-D40FSa5B.js +3 -0
  18. package/cdn/chunks/vidstack-DD2JwFVU.js +1 -0
  19. package/cdn/chunks/vidstack-DRH_1tFW.js +1 -0
  20. package/cdn/chunks/vidstack-DfDZuHNP.js +1 -0
  21. package/cdn/chunks/vidstack-DiNS2Vx5.js +1 -0
  22. package/cdn/chunks/vidstack-xjJ-ui_l.js +1 -0
  23. package/cdn/providers/vidstack-audio-2Dt_Ivbp.js +1 -0
  24. package/cdn/providers/vidstack-dash-CUtD4e6q.js +1 -0
  25. package/cdn/providers/vidstack-google-cast-BdORATUX.js +1 -0
  26. package/cdn/providers/vidstack-hls-R25Kb6DP.js +1 -0
  27. package/cdn/providers/vidstack-html-DaAUJYsD.js +1 -0
  28. package/cdn/providers/vidstack-video-Csvox7SO.js +1 -0
  29. package/cdn/providers/vidstack-vimeo-D4Z96kg2.js +1 -0
  30. package/cdn/providers/vidstack-youtube-DiND6h3s.js +1 -0
  31. package/cdn/vidstack.js +1 -0
  32. package/cdn/with-layouts/chunks/vidstack-2f5gzOW6.js +1 -0
  33. package/cdn/with-layouts/chunks/vidstack-45yH5los.js +1 -0
  34. package/cdn/with-layouts/chunks/vidstack-BBVMdOnf.js +1 -0
  35. package/cdn/with-layouts/chunks/vidstack-BB_ulI_T.js +1 -0
  36. package/cdn/with-layouts/chunks/vidstack-BcAewM33.js +1 -0
  37. package/cdn/with-layouts/chunks/vidstack-BfBBPhXV.js +1 -0
  38. package/cdn/with-layouts/chunks/vidstack-Bxv1Qnxe.js +1 -0
  39. package/cdn/with-layouts/chunks/vidstack-C2ZbG62f.js +3 -0
  40. package/cdn/with-layouts/chunks/vidstack-CCYIOKgL.js +1 -0
  41. package/cdn/with-layouts/chunks/vidstack-CL6PeIO1.js +1 -0
  42. package/cdn/with-layouts/chunks/vidstack-C_AxqLKV.js +1 -0
  43. package/cdn/with-layouts/chunks/vidstack-CifDkwDH.js +795 -0
  44. package/cdn/with-layouts/chunks/vidstack-Cry7aD59.js +3 -0
  45. package/cdn/with-layouts/chunks/vidstack-D065okCn.js +1 -0
  46. package/cdn/with-layouts/chunks/vidstack-DGuMoXmI.js +1 -0
  47. package/cdn/with-layouts/chunks/vidstack-DRH_1tFW.js +1 -0
  48. package/cdn/with-layouts/chunks/vidstack-DVBs1XoQ.js +1 -0
  49. package/cdn/with-layouts/chunks/vidstack-Dge3KT8k.js +1 -0
  50. package/cdn/with-layouts/chunks/vidstack-DiNS2Vx5.js +1 -0
  51. package/cdn/with-layouts/chunks/vidstack-HvYfJoen.js +1 -0
  52. package/cdn/with-layouts/providers/vidstack-audio-DE5vKIzW.js +1 -0
  53. package/cdn/with-layouts/providers/vidstack-dash-CA2agUuZ.js +1 -0
  54. package/cdn/with-layouts/providers/vidstack-google-cast-CGs-t8HM.js +1 -0
  55. package/cdn/with-layouts/providers/vidstack-hls-BHMbMFFR.js +1 -0
  56. package/cdn/with-layouts/providers/vidstack-html-Dm9gmNk6.js +1 -0
  57. package/cdn/with-layouts/providers/vidstack-video-C5it_Lbl.js +1 -0
  58. package/cdn/with-layouts/providers/vidstack-vimeo-BabLn9sy.js +1 -0
  59. package/cdn/with-layouts/providers/vidstack-youtube-D8UlccUL.js +1 -0
  60. package/cdn/with-layouts/vidstack.js +1 -0
  61. package/dev/chunks/vidstack-B7Zi3v_O.js +104 -0
  62. package/dev/chunks/vidstack-BFg1ZqiG.js +91 -0
  63. package/dev/chunks/vidstack-BGB2pa9s.js +58 -0
  64. package/dev/chunks/vidstack-BaIbHZE3.js +1519 -0
  65. package/dev/chunks/vidstack-Bb2rASIc.js +5188 -0
  66. package/dev/chunks/vidstack-Bcmx8pmK.js +224 -0
  67. package/dev/chunks/vidstack-Bl4b0Nen.js +29 -0
  68. package/dev/chunks/vidstack-Bo5OTJ06.js +58 -0
  69. package/dev/chunks/vidstack-BoAGnlRt.js +58 -0
  70. package/dev/chunks/vidstack-Bpr4fI4n.js +7 -0
  71. package/dev/chunks/vidstack-Bt8MP2DK.js +204 -0
  72. package/dev/chunks/vidstack-Bu2kfzUd.js +1637 -0
  73. package/dev/chunks/vidstack-C-ffXlSV.js +2995 -0
  74. package/dev/chunks/vidstack-C-ztJq-f.js +109 -0
  75. package/dev/chunks/vidstack-CFNlaVTR.js +55 -0
  76. package/dev/chunks/vidstack-C_l97D5j.js +254 -0
  77. package/dev/chunks/vidstack-CjhKISI0.js +114 -0
  78. package/dev/chunks/vidstack-CofXIJAy.js +57 -0
  79. package/dev/chunks/vidstack-CwTj4H1w.js +18 -0
  80. package/dev/chunks/vidstack-DDwbYVHV.js +66 -0
  81. package/dev/chunks/vidstack-DFImIcIL.js +11 -0
  82. package/dev/chunks/vidstack-DGDvUbvO.js +33 -0
  83. package/dev/chunks/vidstack-DO0kqA99.js +107 -0
  84. package/dev/chunks/vidstack-DXxIKXmd.js +50 -0
  85. package/dev/chunks/vidstack-DajrMUR0.js +297 -0
  86. package/dev/chunks/vidstack-DbBJlz7I.js +10 -0
  87. package/dev/chunks/vidstack-Dihypf8P.js +11 -0
  88. package/dev/chunks/vidstack-DlAhl87f.js +1193 -0
  89. package/dev/chunks/vidstack-Dm1xEU9Q.js +34 -0
  90. package/dev/chunks/vidstack-Dv_LIPFu.js +14 -0
  91. package/dev/chunks/vidstack-igYn0Apa.js +254 -0
  92. package/dev/chunks/vidstack-krOAtKMi.js +32 -0
  93. package/dev/chunks/vidstack-qh1N5_f_.js +26 -0
  94. package/dev/chunks/vidstack-rB-wqXw1.js +107 -0
  95. package/dev/chunks/vidstack-zG6PIeGg.js +66 -0
  96. package/dev/define/plyr-layout.js +51 -0
  97. package/dev/define/templates/plyr-layout.js +571 -0
  98. package/dev/define/templates/vidstack-audio-layout.js +167 -0
  99. package/dev/define/templates/vidstack-video-layout.js +390 -0
  100. package/dev/define/vidstack-icons.js +1 -0
  101. package/dev/define/vidstack-player-default-layout.js +21 -0
  102. package/dev/define/vidstack-player-layouts.js +25 -0
  103. package/dev/define/vidstack-player-ui.js +70 -0
  104. package/dev/define/vidstack-player.js +19 -0
  105. package/dev/global/plyr.js +501 -0
  106. package/dev/global/vidstack-player.js +129 -0
  107. package/dev/providers/vidstack-audio.js +35 -0
  108. package/dev/providers/vidstack-dash.js +516 -0
  109. package/dev/providers/vidstack-google-cast.js +474 -0
  110. package/dev/providers/vidstack-hls.js +408 -0
  111. package/dev/providers/vidstack-html.js +567 -0
  112. package/dev/providers/vidstack-video.js +207 -0
  113. package/dev/providers/vidstack-vimeo.js +554 -0
  114. package/dev/providers/vidstack-youtube.js +286 -0
  115. package/dev/vidstack-elements.js +36 -0
  116. package/dev/vidstack.js +91 -0
  117. package/dom.d.ts +91 -0
  118. package/elements.d.ts +1433 -0
  119. package/empty.vtt +1 -0
  120. package/global/player.d.ts +52 -0
  121. package/global/plyr.d.ts +343 -0
  122. package/google-cast.d.ts +1422 -0
  123. package/icons.d.ts +1 -0
  124. package/index.d.ts +402 -0
  125. package/package.json +199 -0
  126. package/player/index.d.ts +3 -0
  127. package/player/layouts/default.d.ts +3 -0
  128. package/player/layouts/index.d.ts +3 -0
  129. package/player/layouts/plyr.d.ts +3 -0
  130. package/player/styles/base.css +153 -0
  131. package/player/styles/default/buffering.css +55 -0
  132. package/player/styles/default/buttons.css +175 -0
  133. package/player/styles/default/captions.css +181 -0
  134. package/player/styles/default/chapter-title.css +26 -0
  135. package/player/styles/default/controls.css +56 -0
  136. package/player/styles/default/gestures.css +19 -0
  137. package/player/styles/default/icons.css +6 -0
  138. package/player/styles/default/keyboard.css +148 -0
  139. package/player/styles/default/layouts/audio.css +417 -0
  140. package/player/styles/default/layouts/video.css +590 -0
  141. package/player/styles/default/menus.css +959 -0
  142. package/player/styles/default/poster.css +52 -0
  143. package/player/styles/default/sliders.css +391 -0
  144. package/player/styles/default/theme.css +2461 -0
  145. package/player/styles/default/thumbnail.css +40 -0
  146. package/player/styles/default/time.css +45 -0
  147. package/player/styles/default/tooltips.css +141 -0
  148. package/player/styles/plyr/theme.css +1237 -0
  149. package/player/ui.d.ts +3 -0
  150. package/plugins.d.ts +19 -0
  151. package/plugins.js +13 -0
  152. package/prod/chunks/vidstack-B01xzxC4.js +7 -0
  153. package/prod/chunks/vidstack-BCeb7ryV.js +201 -0
  154. package/prod/chunks/vidstack-BGSTndAW.js +1590 -0
  155. package/prod/chunks/vidstack-BPitBBjh.js +1519 -0
  156. package/prod/chunks/vidstack-BQlOPwOu.js +45 -0
  157. package/prod/chunks/vidstack-BSDzlwxO.js +4778 -0
  158. package/prod/chunks/vidstack-BT0m6zEi.js +109 -0
  159. package/prod/chunks/vidstack-BTigPj2h.js +55 -0
  160. package/prod/chunks/vidstack-BiyXcJ_M.js +107 -0
  161. package/prod/chunks/vidstack-BoVf5n1M.js +2985 -0
  162. package/prod/chunks/vidstack-Bq6c3Bam.js +58 -0
  163. package/prod/chunks/vidstack-ByLCIBtB.js +297 -0
  164. package/prod/chunks/vidstack-C2US-gSO.js +248 -0
  165. package/prod/chunks/vidstack-C9vIqaYT.js +10 -0
  166. package/prod/chunks/vidstack-CF6fixCQ.js +1193 -0
  167. package/prod/chunks/vidstack-CTojmhKq.js +66 -0
  168. package/prod/chunks/vidstack-ChQTHmIQ.js +77 -0
  169. package/prod/chunks/vidstack-Cm6_unwd.js +246 -0
  170. package/prod/chunks/vidstack-CwTj4H1w.js +18 -0
  171. package/prod/chunks/vidstack-D3ltXc3a.js +33 -0
  172. package/prod/chunks/vidstack-D5EzK014.js +14 -0
  173. package/prod/chunks/vidstack-DDXt6fpN.js +58 -0
  174. package/prod/chunks/vidstack-DJDnh4xT.js +11 -0
  175. package/prod/chunks/vidstack-DXxIKXmd.js +50 -0
  176. package/prod/chunks/vidstack-D_-9AA6_.js +29 -0
  177. package/prod/chunks/vidstack-DbkZGjSn.js +107 -0
  178. package/prod/chunks/vidstack-Dihypf8P.js +11 -0
  179. package/prod/chunks/vidstack-Dm1xEU9Q.js +34 -0
  180. package/prod/chunks/vidstack-Dq5Yu0Vr.js +205 -0
  181. package/prod/chunks/vidstack-DqAw8m9J.js +26 -0
  182. package/prod/chunks/vidstack-DsPOyKtl.js +57 -0
  183. package/prod/chunks/vidstack-krOAtKMi.js +32 -0
  184. package/prod/chunks/vidstack-nLyr4NEP.js +58 -0
  185. package/prod/chunks/vidstack-xMS8dnYq.js +114 -0
  186. package/prod/chunks/vidstack-yEGTpgeA.js +104 -0
  187. package/prod/define/plyr-layout.js +51 -0
  188. package/prod/define/templates/plyr-layout.js +571 -0
  189. package/prod/define/templates/vidstack-audio-layout.js +167 -0
  190. package/prod/define/templates/vidstack-video-layout.js +390 -0
  191. package/prod/define/vidstack-icons.js +1 -0
  192. package/prod/define/vidstack-player-default-layout.js +21 -0
  193. package/prod/define/vidstack-player-layouts.js +25 -0
  194. package/prod/define/vidstack-player-ui.js +70 -0
  195. package/prod/define/vidstack-player.js +19 -0
  196. package/prod/global/plyr.js +493 -0
  197. package/prod/global/vidstack-player.js +129 -0
  198. package/prod/providers/vidstack-audio.js +35 -0
  199. package/prod/providers/vidstack-dash.js +501 -0
  200. package/prod/providers/vidstack-google-cast.js +468 -0
  201. package/prod/providers/vidstack-hls.js +393 -0
  202. package/prod/providers/vidstack-html.js +555 -0
  203. package/prod/providers/vidstack-video.js +204 -0
  204. package/prod/providers/vidstack-vimeo.js +548 -0
  205. package/prod/providers/vidstack-youtube.js +286 -0
  206. package/prod/vidstack-elements.js +36 -0
  207. package/prod/vidstack.js +158 -0
  208. package/server/chunks/vidstack-6juFdkKy.js +29 -0
  209. package/server/chunks/vidstack-B7iHmv7_.js +307 -0
  210. package/server/chunks/vidstack-BmxyML9v.js +1619 -0
  211. package/server/chunks/vidstack-BskfxwD3.js +566 -0
  212. package/server/chunks/vidstack-BvLV0SMz.js +4642 -0
  213. package/server/chunks/vidstack-BvWwluXZ.js +205 -0
  214. package/server/chunks/vidstack-C-413dj2.js +8 -0
  215. package/server/chunks/vidstack-C26K8z_-.js +55 -0
  216. package/server/chunks/vidstack-CJJiksDz.js +107 -0
  217. package/server/chunks/vidstack-CUNv52x1.js +141 -0
  218. package/server/chunks/vidstack-CqyBCODe.js +295 -0
  219. package/server/chunks/vidstack-CwTj4H1w.js +18 -0
  220. package/server/chunks/vidstack-DHAyGSOl.js +1502 -0
  221. package/server/chunks/vidstack-DLU3cjcp.js +381 -0
  222. package/server/chunks/vidstack-DXxIKXmd.js +50 -0
  223. package/server/chunks/vidstack-DbtDXDS2.js +104 -0
  224. package/server/chunks/vidstack-Dm1xEU9Q.js +34 -0
  225. package/server/chunks/vidstack-DzTHw_bw.js +207 -0
  226. package/server/chunks/vidstack-Wn3NH5Sg.js +1566 -0
  227. package/server/chunks/vidstack-krOAtKMi.js +32 -0
  228. package/server/chunks/vidstack-wNViAkr4.js +3045 -0
  229. package/server/define/plyr-layout.js +16 -0
  230. package/server/define/vidstack-icons.js +1 -0
  231. package/server/define/vidstack-player-default-layout.js +13 -0
  232. package/server/define/vidstack-player-layouts.js +16 -0
  233. package/server/define/vidstack-player-ui.js +11 -0
  234. package/server/define/vidstack-player.js +6 -0
  235. package/server/global/plyr.js +322 -0
  236. package/server/global/vidstack-player.js +58 -0
  237. package/server/vidstack-elements.js +46 -0
  238. package/server/vidstack.js +148 -0
  239. package/tailwind.cjs +101 -0
  240. package/tailwind.d.cts +15 -0
  241. package/types/vidstack-BOvzfZjK.d.ts +1269 -0
  242. package/types/vidstack-Cttpg6GU.d.ts +7474 -0
@@ -0,0 +1,555 @@
1
+ import { IS_SAFARI, IS_IOS, isHLSSrc, isMediaStream } from '../chunks/vidstack-xMS8dnYq.js';
2
+ import { signal, EventsController, effect, onDispose, peek, isNil, listenEvent, DOMEvent, createScope, setAttribute, isString } from '../chunks/vidstack-BGSTndAW.js';
3
+ import { RAFLoop } from '../chunks/vidstack-DqAw8m9J.js';
4
+ import { getNumberOfDecimalPlaces } from '../chunks/vidstack-Dihypf8P.js';
5
+ import { ListSymbol } from '../chunks/vidstack-D5EzK014.js';
6
+
7
+ let audioContext = null, gainNodes = [], elAudioSources = [];
8
+ function getOrCreateAudioCtx() {
9
+ return audioContext ??= new AudioContext();
10
+ }
11
+ function createGainNode() {
12
+ const audioCtx = getOrCreateAudioCtx(), gainNode = audioCtx.createGain();
13
+ gainNode.connect(audioCtx.destination);
14
+ gainNodes.push(gainNode);
15
+ return gainNode;
16
+ }
17
+ function createElementSource(el, gainNode) {
18
+ const audioCtx = getOrCreateAudioCtx(), src = audioCtx.createMediaElementSource(el);
19
+ if (gainNode) {
20
+ src.connect(gainNode);
21
+ }
22
+ elAudioSources.push(src);
23
+ return src;
24
+ }
25
+ function destroyGainNode(node) {
26
+ const idx = gainNodes.indexOf(node);
27
+ if (idx !== -1) {
28
+ gainNodes.splice(idx, 1);
29
+ node.disconnect();
30
+ freeAudioCtxWhenAllResourcesFreed();
31
+ }
32
+ }
33
+ function destroyElementSource(src) {
34
+ const idx = elAudioSources.indexOf(src);
35
+ if (idx !== -1) {
36
+ elAudioSources.splice(idx, 1);
37
+ src.disconnect();
38
+ freeAudioCtxWhenAllResourcesFreed();
39
+ }
40
+ }
41
+ function freeAudioCtxWhenAllResourcesFreed() {
42
+ if (audioContext && gainNodes.length === 0 && elAudioSources.length === 0) {
43
+ audioContext.close().then(() => {
44
+ audioContext = null;
45
+ });
46
+ }
47
+ }
48
+
49
+ class AudioGain {
50
+ #media;
51
+ #onChange;
52
+ #gainNode = null;
53
+ #srcAudioNode = null;
54
+ get currentGain() {
55
+ return this.#gainNode?.gain?.value ?? null;
56
+ }
57
+ get supported() {
58
+ return true;
59
+ }
60
+ constructor(media, onChange) {
61
+ this.#media = media;
62
+ this.#onChange = onChange;
63
+ }
64
+ setGain(gain) {
65
+ const currGain = this.currentGain;
66
+ if (gain === this.currentGain) {
67
+ return;
68
+ }
69
+ if (gain === 1 && currGain !== 1) {
70
+ this.removeGain();
71
+ return;
72
+ }
73
+ if (!this.#gainNode) {
74
+ this.#gainNode = createGainNode();
75
+ if (this.#srcAudioNode) {
76
+ this.#srcAudioNode.connect(this.#gainNode);
77
+ }
78
+ }
79
+ if (!this.#srcAudioNode) {
80
+ this.#srcAudioNode = createElementSource(this.#media, this.#gainNode);
81
+ }
82
+ this.#gainNode.gain.value = gain;
83
+ this.#onChange(gain);
84
+ }
85
+ removeGain() {
86
+ if (!this.#gainNode) return;
87
+ if (this.#srcAudioNode) {
88
+ this.#srcAudioNode.connect(getOrCreateAudioCtx().destination);
89
+ }
90
+ this.#destroyGainNode();
91
+ this.#onChange(null);
92
+ }
93
+ destroy() {
94
+ this.#destroySrcNode();
95
+ this.#destroyGainNode();
96
+ }
97
+ #destroySrcNode() {
98
+ if (!this.#srcAudioNode) return;
99
+ try {
100
+ destroyElementSource(this.#srcAudioNode);
101
+ } catch (e) {
102
+ } finally {
103
+ this.#srcAudioNode = null;
104
+ }
105
+ }
106
+ #destroyGainNode() {
107
+ if (!this.#gainNode) return;
108
+ try {
109
+ destroyGainNode(this.#gainNode);
110
+ } catch (e) {
111
+ } finally {
112
+ this.#gainNode = null;
113
+ }
114
+ }
115
+ }
116
+
117
+ const PAGE_EVENTS = ["focus", "blur", "visibilitychange", "pageshow", "pagehide"];
118
+ class PageVisibility {
119
+ #state = signal(determinePageState());
120
+ #visibility = signal(document.visibilityState);
121
+ #safariBeforeUnloadTimeout;
122
+ connect() {
123
+ const events = new EventsController(window), handlePageEvent = this.#handlePageEvent.bind(this);
124
+ for (const eventType of PAGE_EVENTS) {
125
+ events.add(eventType, handlePageEvent);
126
+ }
127
+ if (IS_SAFARI) {
128
+ events.add("beforeunload", (event) => {
129
+ this.#safariBeforeUnloadTimeout = setTimeout(() => {
130
+ if (!(event.defaultPrevented || event.returnValue.length > 0)) {
131
+ this.#state.set("hidden");
132
+ this.#visibility.set("hidden");
133
+ }
134
+ }, 0);
135
+ });
136
+ }
137
+ }
138
+ /**
139
+ * The current page state. Important to note we only account for a subset of page states, as
140
+ * the rest aren't valuable to the player at the moment.
141
+ *
142
+ * - **active:** A page is in the active state if it is visible and has input focus.
143
+ * - **passive:** A page is in the passive state if it is visible and does not have input focus.
144
+ * - **hidden:** A page is in the hidden state if it is not visible.
145
+ *
146
+ * @see https://developers.google.com/web/updates/2018/07/page-lifecycle-api#states
147
+ */
148
+ get pageState() {
149
+ return this.#state();
150
+ }
151
+ /**
152
+ * The current document visibility state.
153
+ *
154
+ * - **visible:** The page content may be at least partially visible. In practice, this means that
155
+ * the page is the foreground tab of a non-minimized window.
156
+ * - **hidden:** The page content is not visible to the user. In practice this means that the
157
+ * document is either a background tab or part of a minimized window, or the OS screen lock is
158
+ * active.
159
+ *
160
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilityState
161
+ */
162
+ get visibility() {
163
+ return this.#visibility();
164
+ }
165
+ #handlePageEvent(event) {
166
+ if (IS_SAFARI) window.clearTimeout(this.#safariBeforeUnloadTimeout);
167
+ if (event.type !== "blur" || this.#state() === "active") {
168
+ this.#state.set(determinePageState(event));
169
+ this.#visibility.set(document.visibilityState == "hidden" ? "hidden" : "visible");
170
+ }
171
+ }
172
+ }
173
+ function determinePageState(event) {
174
+ if (event?.type === "blur" || document.visibilityState === "hidden") return "hidden";
175
+ if (document.hasFocus()) return "active";
176
+ return "passive";
177
+ }
178
+
179
+ class HTMLMediaEvents {
180
+ #provider;
181
+ #ctx;
182
+ #waiting = false;
183
+ #attachedLoadStart = false;
184
+ #attachedCanPlay = false;
185
+ #timeRAF = new RAFLoop(this.#onAnimationFrame.bind(this));
186
+ #pageVisibility = new PageVisibility();
187
+ #events;
188
+ get #media() {
189
+ return this.#provider.media;
190
+ }
191
+ constructor(provider, ctx) {
192
+ this.#provider = provider;
193
+ this.#ctx = ctx;
194
+ this.#events = new EventsController(provider.media);
195
+ this.#attachInitialListeners();
196
+ this.#pageVisibility.connect();
197
+ effect(this.#attachTimeUpdate.bind(this));
198
+ onDispose(this.#onDispose.bind(this));
199
+ }
200
+ #onDispose() {
201
+ this.#attachedLoadStart = false;
202
+ this.#attachedCanPlay = false;
203
+ this.#timeRAF.stop();
204
+ this.#events.abort();
205
+ this.#devHandlers?.clear();
206
+ }
207
+ /**
208
+ * The `timeupdate` event fires surprisingly infrequently during playback, meaning your progress
209
+ * bar (or whatever else is synced to the currentTime) moves in a choppy fashion. This helps
210
+ * resolve that by retrieving time updates in a request animation frame loop.
211
+ */
212
+ #lastSeenTime = 0;
213
+ #seekedTo = -1;
214
+ #onAnimationFrame() {
215
+ const newTime = this.#media.currentTime;
216
+ const didStutter = IS_SAFARI && newTime - this.#seekedTo < 0.35;
217
+ if (!didStutter && this.#lastSeenTime !== newTime) {
218
+ this.#updateCurrentTime(newTime);
219
+ this.#lastSeenTime = newTime;
220
+ }
221
+ }
222
+ #attachInitialListeners() {
223
+ this.#attachEventListener("loadstart", this.#onLoadStart);
224
+ this.#attachEventListener("abort", this.#onAbort);
225
+ this.#attachEventListener("emptied", this.#onEmptied);
226
+ this.#attachEventListener("error", this.#onError);
227
+ this.#attachEventListener("volumechange", this.#onVolumeChange);
228
+ }
229
+ #attachLoadStartListeners() {
230
+ if (this.#attachedLoadStart) return;
231
+ this.#attachEventListener("loadeddata", this.#onLoadedData);
232
+ this.#attachEventListener("loadedmetadata", this.#onLoadedMetadata);
233
+ this.#attachEventListener("canplay", this.#onCanPlay);
234
+ this.#attachEventListener("canplaythrough", this.#onCanPlayThrough);
235
+ this.#attachEventListener("durationchange", this.#onDurationChange);
236
+ this.#attachEventListener("play", this.#onPlay);
237
+ this.#attachEventListener("progress", this.#onProgress);
238
+ this.#attachEventListener("stalled", this.#onStalled);
239
+ this.#attachEventListener("suspend", this.#onSuspend);
240
+ this.#attachEventListener("ratechange", this.#onRateChange);
241
+ this.#attachedLoadStart = true;
242
+ }
243
+ #attachCanPlayListeners() {
244
+ if (this.#attachedCanPlay) return;
245
+ this.#attachEventListener("pause", this.#onPause);
246
+ this.#attachEventListener("playing", this.#onPlaying);
247
+ this.#attachEventListener("seeked", this.#onSeeked);
248
+ this.#attachEventListener("seeking", this.#onSeeking);
249
+ this.#attachEventListener("ended", this.#onEnded);
250
+ this.#attachEventListener("waiting", this.#onWaiting);
251
+ this.#attachedCanPlay = true;
252
+ }
253
+ #devHandlers = void 0;
254
+ #handleDevEvent = void 0;
255
+ #attachEventListener(eventType, handler) {
256
+ this.#events.add(eventType, handler.bind(this));
257
+ }
258
+ #onDevEvent(event2) {
259
+ return;
260
+ }
261
+ #updateCurrentTime(time, trigger) {
262
+ const newTime = Math.min(time, this.#ctx.$state.seekableEnd());
263
+ this.#ctx.notify("time-change", newTime, trigger);
264
+ }
265
+ #onLoadStart(event2) {
266
+ if (this.#media.networkState === 3) {
267
+ this.#onAbort(event2);
268
+ return;
269
+ }
270
+ this.#attachLoadStartListeners();
271
+ this.#ctx.notify("load-start", void 0, event2);
272
+ }
273
+ #onAbort(event2) {
274
+ this.#ctx.notify("abort", void 0, event2);
275
+ }
276
+ #onEmptied() {
277
+ this.#ctx.notify("emptied", void 0, event);
278
+ }
279
+ #onLoadedData(event2) {
280
+ this.#ctx.notify("loaded-data", void 0, event2);
281
+ }
282
+ #onLoadedMetadata(event2) {
283
+ this.#lastSeenTime = 0;
284
+ this.#seekedTo = -1;
285
+ this.#attachCanPlayListeners();
286
+ this.#ctx.notify("loaded-metadata", void 0, event2);
287
+ if (IS_IOS || IS_SAFARI && isHLSSrc(this.#ctx.$state.source())) {
288
+ this.#ctx.delegate.ready(this.#getCanPlayDetail(), event2);
289
+ }
290
+ }
291
+ #getCanPlayDetail() {
292
+ return {
293
+ provider: peek(this.#ctx.$provider),
294
+ duration: this.#media.duration,
295
+ buffered: this.#media.buffered,
296
+ seekable: this.#media.seekable
297
+ };
298
+ }
299
+ #onPlay(event2) {
300
+ if (!this.#ctx.$state.canPlay) return;
301
+ this.#ctx.notify("play", void 0, event2);
302
+ }
303
+ #onPause(event2) {
304
+ if (this.#media.readyState === 1 && !this.#waiting) return;
305
+ this.#waiting = false;
306
+ this.#timeRAF.stop();
307
+ this.#ctx.notify("pause", void 0, event2);
308
+ }
309
+ #onCanPlay(event2) {
310
+ this.#ctx.delegate.ready(this.#getCanPlayDetail(), event2);
311
+ }
312
+ #onCanPlayThrough(event2) {
313
+ if (this.#ctx.$state.started()) return;
314
+ this.#ctx.notify("can-play-through", this.#getCanPlayDetail(), event2);
315
+ }
316
+ #onPlaying(event2) {
317
+ if (this.#media.paused) return;
318
+ this.#waiting = false;
319
+ this.#ctx.notify("playing", void 0, event2);
320
+ this.#timeRAF.start();
321
+ }
322
+ #onStalled(event2) {
323
+ this.#ctx.notify("stalled", void 0, event2);
324
+ if (this.#media.readyState < 3) {
325
+ this.#waiting = true;
326
+ this.#ctx.notify("waiting", void 0, event2);
327
+ }
328
+ }
329
+ #onWaiting(event2) {
330
+ if (this.#media.readyState < 3) {
331
+ this.#waiting = true;
332
+ this.#ctx.notify("waiting", void 0, event2);
333
+ }
334
+ }
335
+ #onEnded(event2) {
336
+ this.#timeRAF.stop();
337
+ this.#updateCurrentTime(this.#media.duration, event2);
338
+ this.#ctx.notify("end", void 0, event2);
339
+ if (this.#ctx.$state.loop()) {
340
+ const hasCustomControls = isNil(this.#media.controls);
341
+ if (hasCustomControls) this.#media.controls = false;
342
+ }
343
+ }
344
+ #attachTimeUpdate() {
345
+ const isPaused = this.#ctx.$state.paused(), isPageHidden = this.#pageVisibility.visibility === "hidden", shouldListenToTimeUpdates = isPaused || isPageHidden;
346
+ if (shouldListenToTimeUpdates) {
347
+ listenEvent(this.#media, "timeupdate", this.#onTimeUpdate.bind(this));
348
+ }
349
+ }
350
+ #onTimeUpdate(event2) {
351
+ this.#updateCurrentTime(this.#media.currentTime, event2);
352
+ }
353
+ #onDurationChange(event2) {
354
+ if (this.#ctx.$state.ended()) {
355
+ this.#updateCurrentTime(this.#media.duration, event2);
356
+ }
357
+ this.#ctx.notify("duration-change", this.#media.duration, event2);
358
+ }
359
+ #onVolumeChange(event2) {
360
+ const detail = {
361
+ volume: this.#media.volume,
362
+ muted: this.#media.muted
363
+ };
364
+ this.#ctx.notify("volume-change", detail, event2);
365
+ }
366
+ #onSeeked(event2) {
367
+ this.#seekedTo = this.#media.currentTime;
368
+ this.#updateCurrentTime(this.#media.currentTime, event2);
369
+ this.#ctx.notify("seeked", this.#media.currentTime, event2);
370
+ if (Math.trunc(this.#media.currentTime) === Math.trunc(this.#media.duration) && getNumberOfDecimalPlaces(this.#media.duration) > getNumberOfDecimalPlaces(this.#media.currentTime)) {
371
+ this.#updateCurrentTime(this.#media.duration, event2);
372
+ if (!this.#media.ended) {
373
+ this.#ctx.player.dispatch(
374
+ new DOMEvent("media-play-request", {
375
+ trigger: event2
376
+ })
377
+ );
378
+ }
379
+ }
380
+ }
381
+ #onSeeking(event2) {
382
+ this.#ctx.notify("seeking", this.#media.currentTime, event2);
383
+ }
384
+ #onProgress(event2) {
385
+ const detail = {
386
+ buffered: this.#media.buffered,
387
+ seekable: this.#media.seekable
388
+ };
389
+ this.#ctx.notify("progress", detail, event2);
390
+ }
391
+ #onSuspend(event2) {
392
+ this.#ctx.notify("suspend", void 0, event2);
393
+ }
394
+ #onRateChange(event2) {
395
+ this.#ctx.notify("rate-change", this.#media.playbackRate, event2);
396
+ }
397
+ #onError(event2) {
398
+ const error = this.#media.error;
399
+ if (!error) return;
400
+ const detail = {
401
+ message: error.message,
402
+ code: error.code,
403
+ mediaError: error
404
+ };
405
+ this.#ctx.notify("error", detail, event2);
406
+ }
407
+ }
408
+
409
+ class NativeAudioTracks {
410
+ #provider;
411
+ #ctx;
412
+ get #nativeTracks() {
413
+ return this.#provider.media.audioTracks;
414
+ }
415
+ constructor(provider, ctx) {
416
+ this.#provider = provider;
417
+ this.#ctx = ctx;
418
+ this.#nativeTracks.onaddtrack = this.#onAddNativeTrack.bind(this);
419
+ this.#nativeTracks.onremovetrack = this.#onRemoveNativeTrack.bind(this);
420
+ this.#nativeTracks.onchange = this.#onChangeNativeTrack.bind(this);
421
+ listenEvent(this.#ctx.audioTracks, "change", this.#onChangeTrack.bind(this));
422
+ }
423
+ #onAddNativeTrack(event) {
424
+ const nativeTrack = event.track;
425
+ if (nativeTrack.label === "") return;
426
+ const id = nativeTrack.id.toString() || `native-audio-${this.#ctx.audioTracks.length}`, audioTrack = {
427
+ id,
428
+ label: nativeTrack.label,
429
+ language: nativeTrack.language,
430
+ kind: nativeTrack.kind,
431
+ selected: false
432
+ };
433
+ this.#ctx.audioTracks[ListSymbol.add](audioTrack, event);
434
+ if (nativeTrack.enabled) audioTrack.selected = true;
435
+ }
436
+ #onRemoveNativeTrack(event) {
437
+ const track = this.#ctx.audioTracks.getById(event.track.id);
438
+ if (track) this.#ctx.audioTracks[ListSymbol.remove](track, event);
439
+ }
440
+ #onChangeNativeTrack(event) {
441
+ let enabledTrack = this.#getEnabledNativeTrack();
442
+ if (!enabledTrack) return;
443
+ const track = this.#ctx.audioTracks.getById(enabledTrack.id);
444
+ if (track) this.#ctx.audioTracks[ListSymbol.select](track, true, event);
445
+ }
446
+ #getEnabledNativeTrack() {
447
+ return Array.from(this.#nativeTracks).find((track) => track.enabled);
448
+ }
449
+ #onChangeTrack(event) {
450
+ const { current } = event.detail;
451
+ if (!current) return;
452
+ const track = this.#nativeTracks.getTrackById(current.id);
453
+ if (track) {
454
+ const prev = this.#getEnabledNativeTrack();
455
+ if (prev) prev.enabled = false;
456
+ track.enabled = true;
457
+ }
458
+ }
459
+ }
460
+
461
+ class HTMLMediaProvider {
462
+ constructor(media, ctx) {
463
+ this.media = media;
464
+ this.ctx = ctx;
465
+ this.audioGain = new AudioGain(media, (gain) => {
466
+ this.ctx.notify("audio-gain-change", gain);
467
+ });
468
+ }
469
+ scope = createScope();
470
+ currentSrc = null;
471
+ audioGain;
472
+ setup() {
473
+ new HTMLMediaEvents(this, this.ctx);
474
+ if ("audioTracks" in this.media) new NativeAudioTracks(this, this.ctx);
475
+ onDispose(() => {
476
+ this.audioGain.destroy();
477
+ this.media.srcObject = null;
478
+ this.media.removeAttribute("src");
479
+ for (const source of this.media.querySelectorAll("source")) source.remove();
480
+ this.media.load();
481
+ });
482
+ }
483
+ get type() {
484
+ return "";
485
+ }
486
+ setPlaybackRate(rate) {
487
+ this.media.playbackRate = rate;
488
+ }
489
+ async play() {
490
+ return this.media.play();
491
+ }
492
+ async pause() {
493
+ return this.media.pause();
494
+ }
495
+ setMuted(muted) {
496
+ this.media.muted = muted;
497
+ }
498
+ setVolume(volume) {
499
+ this.media.volume = volume;
500
+ }
501
+ setCurrentTime(time) {
502
+ this.media.currentTime = time;
503
+ }
504
+ setPlaysInline(inline) {
505
+ setAttribute(this.media, "playsinline", inline);
506
+ }
507
+ async loadSource({ src, type }, preload) {
508
+ this.media.preload = preload || "";
509
+ if (isMediaStream(src)) {
510
+ this.removeSource();
511
+ this.media.srcObject = src;
512
+ } else {
513
+ this.media.srcObject = null;
514
+ if (isString(src)) {
515
+ if (type !== "?") {
516
+ this.appendSource({ src, type });
517
+ } else {
518
+ this.removeSource();
519
+ this.media.src = this.#appendMediaFragment(src);
520
+ }
521
+ } else {
522
+ this.removeSource();
523
+ this.media.src = window.URL.createObjectURL(src);
524
+ }
525
+ }
526
+ this.media.load();
527
+ this.currentSrc = { src, type };
528
+ }
529
+ /**
530
+ * Append source so it works when requesting AirPlay since hls.js will remove it.
531
+ */
532
+ appendSource(src, defaultType) {
533
+ const prevSource = this.media.querySelector("source[data-vds]"), source = prevSource ?? document.createElement("source");
534
+ setAttribute(source, "src", this.#appendMediaFragment(src.src));
535
+ setAttribute(source, "type", src.type !== "?" ? src.type : defaultType);
536
+ setAttribute(source, "data-vds", "");
537
+ if (!prevSource) this.media.append(source);
538
+ }
539
+ removeSource() {
540
+ this.media.querySelector("source[data-vds]")?.remove();
541
+ }
542
+ #appendMediaFragment(src) {
543
+ const { clipStartTime, clipEndTime } = this.ctx.$state, startTime = clipStartTime(), endTime = clipEndTime();
544
+ if (startTime > 0 && endTime > 0) {
545
+ return `${src}#t=${startTime},${endTime}`;
546
+ } else if (startTime > 0) {
547
+ return `${src}#t=${startTime}`;
548
+ } else if (endTime > 0) {
549
+ return `${src}#t=0,${endTime}`;
550
+ }
551
+ return src;
552
+ }
553
+ }
554
+
555
+ export { HTMLMediaProvider };