@djangocfg/ui-tools 2.1.390 → 2.1.394

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 (184) hide show
  1. package/README.md +7 -10
  2. package/dist/chunk-PAWJFY3S.mjs +6 -0
  3. package/dist/{chunk-N2XQF2OL.mjs.map → chunk-PAWJFY3S.mjs.map} +1 -1
  4. package/dist/chunk-PK6SKIKE.cjs +8 -0
  5. package/dist/{chunk-OLISEQHS.cjs.map → chunk-PK6SKIKE.cjs.map} +1 -1
  6. package/dist/file-icon/index.cjs +6 -6
  7. package/dist/file-icon/index.d.cts +1 -1
  8. package/dist/file-icon/index.d.ts +1 -1
  9. package/dist/file-icon/index.mjs +1 -1
  10. package/dist/tree/index.cjs +1372 -143
  11. package/dist/tree/index.cjs.map +1 -1
  12. package/dist/tree/index.d.cts +2 -2
  13. package/dist/tree/index.d.ts +2 -2
  14. package/dist/tree/index.mjs +1322 -3
  15. package/dist/tree/index.mjs.map +1 -1
  16. package/dist/{types-CevSbyfD.d.cts → types-B_zhyAqR.d.cts} +1 -1
  17. package/dist/{types-CevSbyfD.d.ts → types-B_zhyAqR.d.ts} +1 -1
  18. package/package.json +6 -14
  19. package/src/tools/AudioPlayer/README.md +4 -4
  20. package/src/tools/Chat/README.md +6 -6
  21. package/src/tools/CronScheduler/index.tsx +1 -1
  22. package/src/tools/CronScheduler/lazy.tsx +1 -1
  23. package/src/tools/ImageViewer/README.md +1 -1
  24. package/src/tools/JsonForm/README.md +2 -2
  25. package/src/tools/MarkdownEditor/README.md +3 -3
  26. package/src/tools/MarkdownMessage/README.md +2 -2
  27. package/src/tools/OpenapiViewer/components/DocsLayout/grouping.ts +5 -1
  28. package/src/tools/PrettyCode/lazy.tsx +6 -0
  29. package/src/tools/SpeechRecognition/README.md +1 -1
  30. package/dist/ChatRoot-EFNXQXXN.cjs +0 -15
  31. package/dist/ChatRoot-EFNXQXXN.cjs.map +0 -1
  32. package/dist/ChatRoot-FITF5RVP.mjs +0 -6
  33. package/dist/ChatRoot-FITF5RVP.mjs.map +0 -1
  34. package/dist/ChatRoot-PNNGQCYF.css +0 -7
  35. package/dist/ChatRoot-PNNGQCYF.css.map +0 -1
  36. package/dist/CronScheduler.client-DLMXCPAJ.mjs +0 -67
  37. package/dist/CronScheduler.client-DLMXCPAJ.mjs.map +0 -1
  38. package/dist/CronScheduler.client-WEJF4PWQ.cjs +0 -72
  39. package/dist/CronScheduler.client-WEJF4PWQ.cjs.map +0 -1
  40. package/dist/DictationField-AS2F33WI.cjs +0 -13
  41. package/dist/DictationField-AS2F33WI.cjs.map +0 -1
  42. package/dist/DictationField-WPONUCYE.mjs +0 -4
  43. package/dist/DictationField-WPONUCYE.mjs.map +0 -1
  44. package/dist/DocsLayout-EKASBSP7.mjs +0 -3448
  45. package/dist/DocsLayout-EKASBSP7.mjs.map +0 -1
  46. package/dist/DocsLayout-MBFIB4NO.css +0 -7
  47. package/dist/DocsLayout-MBFIB4NO.css.map +0 -1
  48. package/dist/DocsLayout-OURFYWQE.cjs +0 -3455
  49. package/dist/DocsLayout-OURFYWQE.cjs.map +0 -1
  50. package/dist/JsonSchemaForm-DD7CLRIG.cjs +0 -13
  51. package/dist/JsonSchemaForm-DD7CLRIG.cjs.map +0 -1
  52. package/dist/JsonSchemaForm-XKUIVELK.mjs +0 -4
  53. package/dist/JsonSchemaForm-XKUIVELK.mjs.map +0 -1
  54. package/dist/JsonTree-43PQAJKY.mjs +0 -5
  55. package/dist/JsonTree-43PQAJKY.mjs.map +0 -1
  56. package/dist/JsonTree-MLET23ZA.css +0 -7
  57. package/dist/JsonTree-MLET23ZA.css.map +0 -1
  58. package/dist/JsonTree-X6W5YEVY.cjs +0 -11
  59. package/dist/JsonTree-X6W5YEVY.cjs.map +0 -1
  60. package/dist/LottiePlayer.client-2S7ISJ2S.cjs +0 -168
  61. package/dist/LottiePlayer.client-2S7ISJ2S.cjs.map +0 -1
  62. package/dist/LottiePlayer.client-5LDSSJWS.mjs +0 -161
  63. package/dist/LottiePlayer.client-5LDSSJWS.mjs.map +0 -1
  64. package/dist/MapContainer-AKIPABJK.mjs +0 -4
  65. package/dist/MapContainer-AKIPABJK.mjs.map +0 -1
  66. package/dist/MapContainer-STVDMC36.cjs +0 -17
  67. package/dist/MapContainer-STVDMC36.cjs.map +0 -1
  68. package/dist/Mermaid.client-DDXWXZXY.css +0 -7
  69. package/dist/Mermaid.client-DDXWXZXY.css.map +0 -1
  70. package/dist/Mermaid.client-NL4SVR7F.mjs +0 -481
  71. package/dist/Mermaid.client-NL4SVR7F.mjs.map +0 -1
  72. package/dist/Mermaid.client-NNTI6DFX.cjs +0 -487
  73. package/dist/Mermaid.client-NNTI6DFX.cjs.map +0 -1
  74. package/dist/Player-BRV7XTWR.mjs +0 -4
  75. package/dist/Player-BRV7XTWR.mjs.map +0 -1
  76. package/dist/Player-PM7F7DD7.cjs +0 -13
  77. package/dist/Player-PM7F7DD7.cjs.map +0 -1
  78. package/dist/Player-ZGQKKOWI.css +0 -66
  79. package/dist/Player-ZGQKKOWI.css.map +0 -1
  80. package/dist/PrettyCode.client-GWFAIVFN.css +0 -7
  81. package/dist/PrettyCode.client-GWFAIVFN.css.map +0 -1
  82. package/dist/PrettyCode.client-KOHDVPPN.cjs +0 -285
  83. package/dist/PrettyCode.client-KOHDVPPN.cjs.map +0 -1
  84. package/dist/PrettyCode.client-ZGYGKE7G.mjs +0 -283
  85. package/dist/PrettyCode.client-ZGYGKE7G.mjs.map +0 -1
  86. package/dist/TreeRoot-5COOOSWG.mjs +0 -4
  87. package/dist/TreeRoot-5COOOSWG.mjs.map +0 -1
  88. package/dist/TreeRoot-AABP2J6Y.cjs +0 -19
  89. package/dist/TreeRoot-AABP2J6Y.cjs.map +0 -1
  90. package/dist/chunk-2NG4SXEP.mjs +0 -743
  91. package/dist/chunk-2NG4SXEP.mjs.map +0 -1
  92. package/dist/chunk-4LFB7I5K.cjs +0 -1387
  93. package/dist/chunk-4LFB7I5K.cjs.map +0 -1
  94. package/dist/chunk-5D2OCOPQ.cjs +0 -222
  95. package/dist/chunk-5D2OCOPQ.cjs.map +0 -1
  96. package/dist/chunk-5I5QNGUG.cjs +0 -611
  97. package/dist/chunk-5I5QNGUG.cjs.map +0 -1
  98. package/dist/chunk-6ZX2G25W.mjs +0 -1361
  99. package/dist/chunk-6ZX2G25W.mjs.map +0 -1
  100. package/dist/chunk-76NNDZH6.cjs +0 -1061
  101. package/dist/chunk-76NNDZH6.cjs.map +0 -1
  102. package/dist/chunk-7CWGZPO3.mjs +0 -214
  103. package/dist/chunk-7CWGZPO3.mjs.map +0 -1
  104. package/dist/chunk-7EYHNP3E.cjs +0 -965
  105. package/dist/chunk-7EYHNP3E.cjs.map +0 -1
  106. package/dist/chunk-7IYXZUJO.cjs +0 -769
  107. package/dist/chunk-7IYXZUJO.cjs.map +0 -1
  108. package/dist/chunk-ADEN3UA4.cjs +0 -892
  109. package/dist/chunk-ADEN3UA4.cjs.map +0 -1
  110. package/dist/chunk-B6IR5KSC.mjs +0 -59
  111. package/dist/chunk-B6IR5KSC.mjs.map +0 -1
  112. package/dist/chunk-C6GXVH5J.mjs +0 -338
  113. package/dist/chunk-C6GXVH5J.mjs.map +0 -1
  114. package/dist/chunk-DMX7W4XZ.mjs +0 -1113
  115. package/dist/chunk-DMX7W4XZ.mjs.map +0 -1
  116. package/dist/chunk-ECONRHIG.mjs +0 -212
  117. package/dist/chunk-ECONRHIG.mjs.map +0 -1
  118. package/dist/chunk-FEN5S772.cjs +0 -1227
  119. package/dist/chunk-FEN5S772.cjs.map +0 -1
  120. package/dist/chunk-FP2RLYQZ.cjs +0 -187
  121. package/dist/chunk-FP2RLYQZ.cjs.map +0 -1
  122. package/dist/chunk-FVVF7VCD.cjs +0 -1325
  123. package/dist/chunk-FVVF7VCD.cjs.map +0 -1
  124. package/dist/chunk-GYIO7W7M.mjs +0 -1197
  125. package/dist/chunk-GYIO7W7M.mjs.map +0 -1
  126. package/dist/chunk-KNDLV4PI.cjs +0 -1356
  127. package/dist/chunk-KNDLV4PI.cjs.map +0 -1
  128. package/dist/chunk-KNEQRUBA.mjs +0 -181
  129. package/dist/chunk-KNEQRUBA.mjs.map +0 -1
  130. package/dist/chunk-N2XQF2OL.mjs +0 -14
  131. package/dist/chunk-N4MZYNR4.mjs +0 -1342
  132. package/dist/chunk-N4MZYNR4.mjs.map +0 -1
  133. package/dist/chunk-NTVBIIUD.mjs +0 -1439
  134. package/dist/chunk-NTVBIIUD.mjs.map +0 -1
  135. package/dist/chunk-OBRSGM64.mjs +0 -607
  136. package/dist/chunk-OBRSGM64.mjs.map +0 -1
  137. package/dist/chunk-ODO4GMW7.mjs +0 -79
  138. package/dist/chunk-ODO4GMW7.mjs.map +0 -1
  139. package/dist/chunk-OLISEQHS.cjs +0 -18
  140. package/dist/chunk-PVAX67JG.mjs +0 -1041
  141. package/dist/chunk-PVAX67JG.mjs.map +0 -1
  142. package/dist/chunk-QJ6GTUCO.cjs +0 -81
  143. package/dist/chunk-QJ6GTUCO.cjs.map +0 -1
  144. package/dist/chunk-T3MWM23F.cjs +0 -214
  145. package/dist/chunk-T3MWM23F.cjs.map +0 -1
  146. package/dist/chunk-TBSHZO5R.cjs +0 -1134
  147. package/dist/chunk-TBSHZO5R.cjs.map +0 -1
  148. package/dist/chunk-UNCS5V5F.mjs +0 -887
  149. package/dist/chunk-UNCS5V5F.mjs.map +0 -1
  150. package/dist/chunk-VWQ5WOIL.mjs +0 -2059
  151. package/dist/chunk-VWQ5WOIL.mjs.map +0 -1
  152. package/dist/chunk-W75B7Y6C.cjs +0 -1478
  153. package/dist/chunk-W75B7Y6C.cjs.map +0 -1
  154. package/dist/chunk-Y6UTOBF6.mjs +0 -938
  155. package/dist/chunk-Y6UTOBF6.mjs.map +0 -1
  156. package/dist/chunk-YDPDTOSP.cjs +0 -2061
  157. package/dist/chunk-YDPDTOSP.cjs.map +0 -1
  158. package/dist/chunk-YW5IVWHQ.cjs +0 -346
  159. package/dist/chunk-YW5IVWHQ.cjs.map +0 -1
  160. package/dist/chunk-YXZ6GU7H.cjs +0 -63
  161. package/dist/chunk-YXZ6GU7H.cjs.map +0 -1
  162. package/dist/chunk-ZL7FH4NW.mjs +0 -1274
  163. package/dist/chunk-ZL7FH4NW.mjs.map +0 -1
  164. package/dist/components-EHOGXATG.cjs +0 -22
  165. package/dist/components-EHOGXATG.cjs.map +0 -1
  166. package/dist/components-MQ6DR7TX.cjs +0 -26
  167. package/dist/components-MQ6DR7TX.cjs.map +0 -1
  168. package/dist/components-XRX7QGLB.mjs +0 -5
  169. package/dist/components-XRX7QGLB.mjs.map +0 -1
  170. package/dist/components-YATKRWLH.mjs +0 -5
  171. package/dist/components-YATKRWLH.mjs.map +0 -1
  172. package/dist/index.cjs +0 -3674
  173. package/dist/index.cjs.map +0 -1
  174. package/dist/index.css +0 -234
  175. package/dist/index.css.map +0 -1
  176. package/dist/index.d.cts +0 -4929
  177. package/dist/index.d.ts +0 -4929
  178. package/dist/index.mjs +0 -2912
  179. package/dist/index.mjs.map +0 -1
  180. package/dist/launcher-5Y42OBSN.mjs +0 -6
  181. package/dist/launcher-5Y42OBSN.mjs.map +0 -1
  182. package/dist/launcher-PMW2YB24.cjs +0 -59
  183. package/dist/launcher-PMW2YB24.cjs.map +0 -1
  184. package/src/index.ts +0 -157
@@ -1,1342 +0,0 @@
1
- import { useVideoCache, useMediaCacheStore, generateContentKey, useVideoPlayerSettings } from './chunk-C6GXVH5J.mjs';
2
- import { __name } from './chunk-N2XQF2OL.mjs';
3
- import { forwardRef, useRef, useState, useMemo, useEffect, useCallback, useImperativeHandle, createContext, useContext } from 'react';
4
- import '@vidstack/react/player/styles/base.css';
5
- import '@vidstack/react/player/styles/default/theme.css';
6
- import '@vidstack/react/player/styles/default/layouts/video.css';
7
- import { createMediaLogger, cn } from '@djangocfg/ui-core/lib';
8
- import { MediaPlayer, MediaProvider, Poster, useMediaStore, useMediaRemote } from '@vidstack/react';
9
- import { DefaultVideoLayout, defaultLayoutIcons } from '@vidstack/react/player/layouts/default';
10
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
11
- import { Preloader, AspectRatio } from '@djangocfg/ui-core';
12
- import { Play, Pause, VolumeX, Volume2, Minimize, Maximize, FileVideo, RefreshCw } from 'lucide-react';
13
- import { Button, DownloadButton } from '@djangocfg/ui-core/components';
14
- import '@djangocfg/ui-core/hooks';
15
-
16
- var videoDebug = createMediaLogger("VideoPlayer");
17
- function getVidstackSrc(source) {
18
- switch (source.type) {
19
- case "youtube":
20
- return `youtube/${source.id}`;
21
- case "vimeo":
22
- return `vimeo/${source.id}`;
23
- case "hls":
24
- return { src: source.url, type: "application/x-mpegurl" };
25
- case "dash":
26
- return { src: source.url, type: "application/dash+xml" };
27
- case "url":
28
- return source.url;
29
- default:
30
- return "";
31
- }
32
- }
33
- __name(getVidstackSrc, "getVidstackSrc");
34
- function DefaultErrorFallback({ error }) {
35
- return /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center gap-4 text-white bg-black", children: [
36
- /* @__PURE__ */ jsx(
37
- "svg",
38
- {
39
- className: "w-16 h-16 text-muted-foreground",
40
- fill: "none",
41
- stroke: "currentColor",
42
- viewBox: "0 0 24 24",
43
- children: /* @__PURE__ */ jsx(
44
- "path",
45
- {
46
- strokeLinecap: "round",
47
- strokeLinejoin: "round",
48
- strokeWidth: 2,
49
- d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"
50
- }
51
- )
52
- }
53
- ),
54
- /* @__PURE__ */ jsx("p", { className: "text-lg", children: error || "Video cannot be played" })
55
- ] });
56
- }
57
- __name(DefaultErrorFallback, "DefaultErrorFallback");
58
- var VidstackProvider = forwardRef(
59
- ({
60
- source,
61
- aspectRatio = 16 / 9,
62
- autoPlay = false,
63
- muted = false,
64
- loop = false,
65
- playsInline = true,
66
- controls = true,
67
- className,
68
- showInfo = false,
69
- theme = "default",
70
- errorFallback,
71
- onPlay,
72
- onPause,
73
- onEnded,
74
- onError,
75
- onLoadStart,
76
- onCanPlay,
77
- onTimeUpdate
78
- }, ref) => {
79
- const playerRef = useRef(null);
80
- const [hasError, setHasError] = useState(false);
81
- const [errorMessage, setErrorMessage] = useState("Video cannot be played");
82
- const lastSavedTimeRef = useRef(0);
83
- const hasRestoredPositionRef = useRef(false);
84
- const {
85
- getPosterUrl,
86
- cachePosterUrl,
87
- saveVideoPosition,
88
- getVideoPosition
89
- } = useVideoCache();
90
- const sourceKey = useMemo(() => {
91
- switch (source.type) {
92
- case "youtube":
93
- return `youtube:${source.id}`;
94
- case "vimeo":
95
- return `vimeo:${source.id}`;
96
- case "hls":
97
- case "dash":
98
- case "url":
99
- return `url:${source.url}`;
100
- default:
101
- return null;
102
- }
103
- }, [source]);
104
- const posterUrl = useMemo(() => {
105
- if (source.poster) return source.poster;
106
- if (!source.title) return void 0;
107
- const cached = getPosterUrl(source.title);
108
- if (cached) return cached;
109
- return void 0;
110
- }, [source.poster, source.title, getPosterUrl, cachePosterUrl]);
111
- const vidstackSrc = useMemo(() => getVidstackSrc(source), [source]);
112
- useEffect(() => {
113
- const srcString = typeof vidstackSrc === "string" ? vidstackSrc : vidstackSrc.src;
114
- videoDebug.load(srcString, source.type);
115
- }, [vidstackSrc, source.type]);
116
- const retry = useCallback(() => {
117
- setHasError(false);
118
- setErrorMessage("Video cannot be played");
119
- const player = playerRef.current;
120
- if (player) {
121
- player.currentTime = 0;
122
- player.play();
123
- }
124
- }, []);
125
- useImperativeHandle(
126
- ref,
127
- () => {
128
- const player = playerRef.current;
129
- return {
130
- play: /* @__PURE__ */ __name(() => player?.play(), "play"),
131
- pause: /* @__PURE__ */ __name(() => player?.pause(), "pause"),
132
- togglePlay: /* @__PURE__ */ __name(() => {
133
- if (player) {
134
- player.paused ? player.play() : player.pause();
135
- }
136
- }, "togglePlay"),
137
- seekTo: /* @__PURE__ */ __name((time) => {
138
- if (player) player.currentTime = time;
139
- }, "seekTo"),
140
- setVolume: /* @__PURE__ */ __name((volume) => {
141
- if (player) player.volume = Math.max(0, Math.min(1, volume));
142
- }, "setVolume"),
143
- toggleMute: /* @__PURE__ */ __name(() => {
144
- if (player) player.muted = !player.muted;
145
- }, "toggleMute"),
146
- enterFullscreen: /* @__PURE__ */ __name(() => player?.enterFullscreen(), "enterFullscreen"),
147
- exitFullscreen: /* @__PURE__ */ __name(() => player?.exitFullscreen(), "exitFullscreen"),
148
- get currentTime() {
149
- return player?.currentTime ?? 0;
150
- },
151
- get duration() {
152
- return player?.duration ?? 0;
153
- },
154
- get paused() {
155
- return player?.paused ?? true;
156
- }
157
- };
158
- },
159
- []
160
- );
161
- const handlePlay = /* @__PURE__ */ __name(() => onPlay?.(), "handlePlay");
162
- const handlePause = useCallback(() => {
163
- const player = playerRef.current;
164
- if (sourceKey && player && player.currentTime > 0) {
165
- saveVideoPosition(sourceKey, player.currentTime);
166
- lastSavedTimeRef.current = player.currentTime;
167
- }
168
- onPause?.();
169
- }, [sourceKey, saveVideoPosition, onPause]);
170
- const handleEnded = /* @__PURE__ */ __name(() => onEnded?.(), "handleEnded");
171
- const handleError = /* @__PURE__ */ __name((detail) => {
172
- const error = detail;
173
- const msg = error?.message || "Video playback error";
174
- videoDebug.error("Vidstack error", { message: msg });
175
- setHasError(true);
176
- setErrorMessage(msg);
177
- onError?.(msg);
178
- }, "handleError");
179
- const handleLoadStart = /* @__PURE__ */ __name(() => onLoadStart?.(), "handleLoadStart");
180
- const handleCanPlay = useCallback(() => {
181
- const player = playerRef.current;
182
- if (player) {
183
- videoDebug.state("canplay", { duration: player.duration });
184
- const mediaEl = player.provider?.media;
185
- if (mediaEl?.buffered) {
186
- videoDebug.buffer(mediaEl.buffered, player.duration);
187
- }
188
- }
189
- setHasError(false);
190
- if (sourceKey && player && !hasRestoredPositionRef.current) {
191
- const cachedPosition = getVideoPosition(sourceKey);
192
- if (cachedPosition && cachedPosition > 0) {
193
- const duration = player.duration;
194
- if (cachedPosition < duration - 1) {
195
- videoDebug.debug(`Restoring position: ${cachedPosition}s`);
196
- player.currentTime = cachedPosition;
197
- }
198
- }
199
- hasRestoredPositionRef.current = true;
200
- }
201
- onCanPlay?.();
202
- }, [sourceKey, getVideoPosition, onCanPlay]);
203
- const handleTimeUpdate = useCallback(() => {
204
- const player = playerRef.current;
205
- if (!player) return;
206
- if (sourceKey && player.currentTime > 0) {
207
- const timeSinceLastSave = player.currentTime - lastSavedTimeRef.current;
208
- if (timeSinceLastSave >= 5 || timeSinceLastSave < 0) {
209
- saveVideoPosition(sourceKey, player.currentTime);
210
- lastSavedTimeRef.current = player.currentTime;
211
- }
212
- }
213
- onTimeUpdate?.(player.currentTime, player.duration);
214
- }, [sourceKey, saveVideoPosition, onTimeUpdate]);
215
- useEffect(() => {
216
- hasRestoredPositionRef.current = false;
217
- lastSavedTimeRef.current = 0;
218
- }, [sourceKey]);
219
- useEffect(() => {
220
- const player = playerRef.current;
221
- if (!player) return;
222
- const handleSeeking = /* @__PURE__ */ __name(() => {
223
- videoDebug.event("seeking", { currentTime: player.currentTime });
224
- }, "handleSeeking");
225
- const handleSeeked = /* @__PURE__ */ __name(() => {
226
- videoDebug.event("seeked", { currentTime: player.currentTime });
227
- const mediaEl = player.provider?.media;
228
- if (mediaEl?.buffered) {
229
- videoDebug.buffer(mediaEl.buffered, player.duration);
230
- }
231
- }, "handleSeeked");
232
- const handleWaiting = /* @__PURE__ */ __name(() => {
233
- videoDebug.warn("WAITING - buffering...");
234
- const mediaEl = player.provider?.media;
235
- if (mediaEl?.buffered) {
236
- videoDebug.buffer(mediaEl.buffered, player.duration);
237
- }
238
- }, "handleWaiting");
239
- const handleStalled = /* @__PURE__ */ __name(() => {
240
- videoDebug.warn("STALLED - network issue");
241
- const mediaEl = player.provider?.media;
242
- if (mediaEl?.buffered) {
243
- videoDebug.buffer(mediaEl.buffered, player.duration);
244
- }
245
- }, "handleStalled");
246
- player.addEventListener("seeking", handleSeeking);
247
- player.addEventListener("seeked", handleSeeked);
248
- player.addEventListener("waiting", handleWaiting);
249
- player.addEventListener("stalled", handleStalled);
250
- return () => {
251
- player.removeEventListener("seeking", handleSeeking);
252
- player.removeEventListener("seeked", handleSeeked);
253
- player.removeEventListener("waiting", handleWaiting);
254
- player.removeEventListener("stalled", handleStalled);
255
- };
256
- }, [vidstackSrc]);
257
- const isFillMode = aspectRatio === "fill";
258
- const computedAspectRatio = aspectRatio === "auto" || aspectRatio === "fill" ? void 0 : aspectRatio;
259
- const renderErrorFallback = /* @__PURE__ */ __name(() => {
260
- const fallbackProps = { error: errorMessage, retry };
261
- if (typeof errorFallback === "function") {
262
- return errorFallback(fallbackProps);
263
- }
264
- if (errorFallback) {
265
- return errorFallback;
266
- }
267
- return /* @__PURE__ */ jsx(DefaultErrorFallback, { ...fallbackProps });
268
- }, "renderErrorFallback");
269
- const containerStyles = isFillMode ? { width: "100%", height: "100%" } : { aspectRatio: computedAspectRatio };
270
- return /* @__PURE__ */ jsxs("div", { className: cn(isFillMode ? "w-full h-full" : "w-full", className), children: [
271
- /* @__PURE__ */ jsx(
272
- "div",
273
- {
274
- className: cn(
275
- "relative w-full rounded-sm bg-black overflow-hidden",
276
- isFillMode && "h-full",
277
- theme === "minimal" && "rounded-none",
278
- theme === "modern" && "rounded-xl shadow-2xl"
279
- ),
280
- style: containerStyles,
281
- children: hasError ? renderErrorFallback() : /* @__PURE__ */ jsxs(
282
- MediaPlayer,
283
- {
284
- ref: playerRef,
285
- title: source.title || "Video",
286
- src: vidstackSrc,
287
- autoPlay,
288
- muted,
289
- loop,
290
- playsInline,
291
- onPlay: handlePlay,
292
- onPause: handlePause,
293
- onEnded: handleEnded,
294
- onError: handleError,
295
- onLoadStart: handleLoadStart,
296
- onCanPlay: handleCanPlay,
297
- onTimeUpdate: handleTimeUpdate,
298
- className: "w-full h-full",
299
- children: [
300
- /* @__PURE__ */ jsx(MediaProvider, {}),
301
- posterUrl && /* @__PURE__ */ jsx(
302
- Poster,
303
- {
304
- className: "vds-poster",
305
- src: posterUrl,
306
- alt: source.title || "Video poster",
307
- style: { objectFit: "cover" }
308
- }
309
- ),
310
- controls && /* @__PURE__ */ jsx(DefaultVideoLayout, { icons: defaultLayoutIcons, thumbnails: posterUrl })
311
- ]
312
- }
313
- )
314
- }
315
- ),
316
- showInfo && source.title && /* @__PURE__ */ jsx("div", { className: "mt-4 space-y-2", children: /* @__PURE__ */ jsx("h3", { className: "text-xl font-semibold text-foreground", children: source.title }) })
317
- ] });
318
- }
319
- );
320
- VidstackProvider.displayName = "VidstackProvider";
321
- function useVideoPlayerSettings2() {
322
- const { settings, saveSettings } = useVideoPlayerSettings();
323
- const updateVolume = useCallback(
324
- (volume) => {
325
- saveSettings({ volume: Math.max(0, Math.min(1, volume)) });
326
- },
327
- [saveSettings]
328
- );
329
- const updateLoop = useCallback(
330
- (isLooping) => {
331
- saveSettings({ isLooping });
332
- },
333
- [saveSettings]
334
- );
335
- const updateSettings = useCallback(
336
- (newSettings) => {
337
- saveSettings(newSettings);
338
- },
339
- [saveSettings]
340
- );
341
- return {
342
- settings,
343
- updateVolume,
344
- updateLoop,
345
- updateSettings
346
- };
347
- }
348
- __name(useVideoPlayerSettings2, "useVideoPlayerSettings");
349
- function getVideoUrl(source) {
350
- switch (source.type) {
351
- case "url":
352
- return source.url;
353
- case "data-url":
354
- return source.data;
355
- default:
356
- return "";
357
- }
358
- }
359
- __name(getVideoUrl, "getVideoUrl");
360
- var NativeProvider = forwardRef(
361
- ({
362
- source,
363
- aspectRatio = 16 / 9,
364
- autoPlay = true,
365
- muted = true,
366
- loop = true,
367
- playsInline = true,
368
- preload = "auto",
369
- controls = false,
370
- disableContextMenu = true,
371
- showPreloader = true,
372
- preloaderTimeout = 5e3,
373
- className,
374
- videoClassName,
375
- onPlay,
376
- onPause,
377
- onEnded,
378
- onError,
379
- onLoadStart,
380
- onCanPlay,
381
- onTimeUpdate
382
- }, ref) => {
383
- const [isLoading, setIsLoading] = useState(showPreloader);
384
- const videoRef = useRef(null);
385
- const { settings: savedSettings, updateVolume } = useVideoPlayerSettings2();
386
- const videoUrl = getVideoUrl(source);
387
- useEffect(() => {
388
- videoDebug.load(videoUrl, source.type);
389
- }, [videoUrl, source.type]);
390
- useImperativeHandle(
391
- ref,
392
- () => ({
393
- play: /* @__PURE__ */ __name(() => videoRef.current?.play(), "play"),
394
- pause: /* @__PURE__ */ __name(() => videoRef.current?.pause(), "pause"),
395
- togglePlay: /* @__PURE__ */ __name(() => {
396
- const video = videoRef.current;
397
- if (video) {
398
- video.paused ? video.play() : video.pause();
399
- }
400
- }, "togglePlay"),
401
- seekTo: /* @__PURE__ */ __name((time) => {
402
- if (videoRef.current) videoRef.current.currentTime = time;
403
- }, "seekTo"),
404
- setVolume: /* @__PURE__ */ __name((volume) => {
405
- if (videoRef.current) videoRef.current.volume = Math.max(0, Math.min(1, volume));
406
- }, "setVolume"),
407
- toggleMute: /* @__PURE__ */ __name(() => {
408
- if (videoRef.current) videoRef.current.muted = !videoRef.current.muted;
409
- }, "toggleMute"),
410
- enterFullscreen: /* @__PURE__ */ __name(() => videoRef.current?.requestFullscreen(), "enterFullscreen"),
411
- exitFullscreen: /* @__PURE__ */ __name(() => document.exitFullscreen(), "exitFullscreen"),
412
- get currentTime() {
413
- return videoRef.current?.currentTime ?? 0;
414
- },
415
- get duration() {
416
- return videoRef.current?.duration ?? 0;
417
- },
418
- get paused() {
419
- return videoRef.current?.paused ?? true;
420
- }
421
- }),
422
- []
423
- );
424
- useEffect(() => {
425
- if (!showPreloader) return;
426
- const video = videoRef.current;
427
- if (!video) return;
428
- if (video.readyState >= 3) {
429
- setIsLoading(false);
430
- return;
431
- }
432
- const hideLoader = /* @__PURE__ */ __name(() => setIsLoading(false), "hideLoader");
433
- video.addEventListener("canplay", hideLoader);
434
- video.addEventListener("loadeddata", hideLoader);
435
- video.addEventListener("playing", hideLoader);
436
- const timeout = setTimeout(hideLoader, preloaderTimeout);
437
- return () => {
438
- video.removeEventListener("canplay", hideLoader);
439
- video.removeEventListener("loadeddata", hideLoader);
440
- video.removeEventListener("playing", hideLoader);
441
- clearTimeout(timeout);
442
- };
443
- }, [showPreloader, preloaderTimeout]);
444
- useEffect(() => {
445
- const video = videoRef.current;
446
- if (!video) return;
447
- const handleLoadedMetadata = /* @__PURE__ */ __name(() => {
448
- videoDebug.state("loadedmetadata", { duration: video.duration });
449
- }, "handleLoadedMetadata");
450
- const handleCanPlayDebug = /* @__PURE__ */ __name(() => {
451
- videoDebug.state("canplay", { duration: video.duration, buffered: video.buffered.length });
452
- videoDebug.buffer(video.buffered, video.duration);
453
- video.volume = savedSettings.volume;
454
- }, "handleCanPlayDebug");
455
- const handleSeeking = /* @__PURE__ */ __name(() => {
456
- videoDebug.event("seeking", { currentTime: video.currentTime });
457
- }, "handleSeeking");
458
- const handleSeeked = /* @__PURE__ */ __name(() => {
459
- videoDebug.event("seeked", { currentTime: video.currentTime });
460
- videoDebug.buffer(video.buffered, video.duration);
461
- }, "handleSeeked");
462
- const handleWaiting = /* @__PURE__ */ __name(() => {
463
- videoDebug.warn("WAITING - buffering...");
464
- videoDebug.buffer(video.buffered, video.duration);
465
- }, "handleWaiting");
466
- const handleStalled = /* @__PURE__ */ __name(() => {
467
- videoDebug.warn("STALLED - network issue");
468
- videoDebug.buffer(video.buffered, video.duration);
469
- }, "handleStalled");
470
- video.addEventListener("loadedmetadata", handleLoadedMetadata);
471
- video.addEventListener("canplay", handleCanPlayDebug);
472
- video.addEventListener("seeking", handleSeeking);
473
- video.addEventListener("seeked", handleSeeked);
474
- video.addEventListener("waiting", handleWaiting);
475
- video.addEventListener("stalled", handleStalled);
476
- return () => {
477
- video.removeEventListener("loadedmetadata", handleLoadedMetadata);
478
- video.removeEventListener("canplay", handleCanPlayDebug);
479
- video.removeEventListener("seeking", handleSeeking);
480
- video.removeEventListener("seeked", handleSeeked);
481
- video.removeEventListener("waiting", handleWaiting);
482
- video.removeEventListener("stalled", handleStalled);
483
- };
484
- }, [savedSettings.volume]);
485
- useEffect(() => {
486
- const video = videoRef.current;
487
- if (!video) return;
488
- const handleVolumeChange = /* @__PURE__ */ __name(() => {
489
- updateVolume(video.volume);
490
- }, "handleVolumeChange");
491
- video.addEventListener("volumechange", handleVolumeChange);
492
- return () => video.removeEventListener("volumechange", handleVolumeChange);
493
- }, [updateVolume]);
494
- const handleContextMenu = /* @__PURE__ */ __name((e) => {
495
- if (disableContextMenu) {
496
- e.preventDefault();
497
- }
498
- }, "handleContextMenu");
499
- const handleError = /* @__PURE__ */ __name((e) => {
500
- const video = e.currentTarget;
501
- const errorMsg = video.error?.message || "Video playback error";
502
- videoDebug.error("Video error", { code: video.error?.code, message: errorMsg });
503
- setIsLoading(false);
504
- onError?.(errorMsg);
505
- }, "handleError");
506
- const handleTimeUpdate = /* @__PURE__ */ __name(() => {
507
- const video = videoRef.current;
508
- if (video && onTimeUpdate) {
509
- onTimeUpdate(video.currentTime, video.duration);
510
- }
511
- }, "handleTimeUpdate");
512
- const isFillMode = aspectRatio === "fill";
513
- const computedAspectRatio = aspectRatio === "auto" || aspectRatio === "fill" ? void 0 : aspectRatio;
514
- const videoContent = /* @__PURE__ */ jsxs(Fragment, { children: [
515
- showPreloader && isLoading && /* @__PURE__ */ jsx(
516
- "div",
517
- {
518
- className: cn(
519
- "absolute inset-0 flex items-center justify-center bg-muted/30 backdrop-blur-sm z-10"
520
- ),
521
- children: /* @__PURE__ */ jsx(Preloader, { size: "lg", spinnerClassName: "text-white" })
522
- }
523
- ),
524
- /* @__PURE__ */ jsx(
525
- "video",
526
- {
527
- ref: videoRef,
528
- className: cn("w-full h-full object-cover", videoClassName),
529
- src: videoUrl,
530
- autoPlay,
531
- muted,
532
- loop,
533
- playsInline,
534
- preload,
535
- controls,
536
- poster: source.poster,
537
- onContextMenu: handleContextMenu,
538
- onLoadStart,
539
- onCanPlay,
540
- onPlay,
541
- onPause,
542
- onPlaying: () => setIsLoading(false),
543
- onEnded,
544
- onError: handleError,
545
- onTimeUpdate: handleTimeUpdate
546
- }
547
- )
548
- ] });
549
- if (isFillMode) {
550
- return /* @__PURE__ */ jsx("div", { className: cn("relative w-full h-full overflow-hidden", className), children: videoContent });
551
- }
552
- return /* @__PURE__ */ jsx("div", { className: cn("relative overflow-hidden", className), children: /* @__PURE__ */ jsx(AspectRatio, { ratio: computedAspectRatio, children: videoContent }) });
553
- }
554
- );
555
- NativeProvider.displayName = "NativeProvider";
556
- function DefaultErrorFallback2({ error }) {
557
- return /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center gap-4 text-white", children: [
558
- /* @__PURE__ */ jsx(
559
- "svg",
560
- {
561
- className: "w-16 h-16 text-muted-foreground",
562
- fill: "none",
563
- stroke: "currentColor",
564
- viewBox: "0 0 24 24",
565
- children: /* @__PURE__ */ jsx(
566
- "path",
567
- {
568
- strokeLinecap: "round",
569
- strokeLinejoin: "round",
570
- strokeWidth: 2,
571
- d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"
572
- }
573
- )
574
- }
575
- ),
576
- /* @__PURE__ */ jsx("p", { className: "text-lg", children: error || "Video cannot be previewed" })
577
- ] });
578
- }
579
- __name(DefaultErrorFallback2, "DefaultErrorFallback");
580
- var StreamProvider = forwardRef(
581
- ({
582
- source,
583
- aspectRatio = 16 / 9,
584
- autoPlay = false,
585
- muted = false,
586
- loop = false,
587
- playsInline = true,
588
- preload = "metadata",
589
- controls = true,
590
- disableContextMenu = false,
591
- showPreloader = true,
592
- preloaderTimeout = 1e4,
593
- className,
594
- videoClassName,
595
- errorFallback,
596
- onPlay,
597
- onPause,
598
- onEnded,
599
- onError,
600
- onLoadStart,
601
- onCanPlay,
602
- onTimeUpdate,
603
- onBufferProgress
604
- }, ref) => {
605
- const [videoUrl, setVideoUrl] = useState(null);
606
- const [isLoading, setIsLoading] = useState(true);
607
- const [hasError, setHasError] = useState(false);
608
- const [errorMessage, setErrorMessage] = useState("Video cannot be previewed");
609
- const videoRef = useRef(null);
610
- const contentKeyRef = useRef(null);
611
- const lastSavedTimeRef = useRef(0);
612
- const getOrCreateBlobUrl = useMediaCacheStore.getState().getOrCreateBlobUrl;
613
- const releaseBlobUrl = useMediaCacheStore.getState().releaseBlobUrl;
614
- const getOrCreateStreamUrl = useMediaCacheStore.getState().getOrCreateStreamUrl;
615
- const saveVideoPosition = useMediaCacheStore.getState().saveVideoPosition;
616
- const getVideoPosition = useMediaCacheStore.getState().getVideoPosition;
617
- const { settings: savedSettings, updateVolume } = useVideoPlayerSettings2();
618
- const retry = useCallback(() => {
619
- setHasError(false);
620
- setIsLoading(true);
621
- if (source.type === "stream") {
622
- const streamSource = source;
623
- const freshUrl = streamSource.getStreamUrl(streamSource.sessionId, streamSource.path);
624
- setVideoUrl(freshUrl);
625
- return;
626
- }
627
- const video = videoRef.current;
628
- if (video && videoUrl) {
629
- video.load();
630
- }
631
- }, [source, videoUrl]);
632
- useImperativeHandle(
633
- ref,
634
- () => ({
635
- play: /* @__PURE__ */ __name(() => videoRef.current?.play(), "play"),
636
- pause: /* @__PURE__ */ __name(() => videoRef.current?.pause(), "pause"),
637
- togglePlay: /* @__PURE__ */ __name(() => {
638
- const video = videoRef.current;
639
- if (video) {
640
- video.paused ? video.play() : video.pause();
641
- }
642
- }, "togglePlay"),
643
- seekTo: /* @__PURE__ */ __name((time) => {
644
- if (videoRef.current) videoRef.current.currentTime = time;
645
- }, "seekTo"),
646
- setVolume: /* @__PURE__ */ __name((volume) => {
647
- if (videoRef.current) videoRef.current.volume = Math.max(0, Math.min(1, volume));
648
- }, "setVolume"),
649
- toggleMute: /* @__PURE__ */ __name(() => {
650
- if (videoRef.current) videoRef.current.muted = !videoRef.current.muted;
651
- }, "toggleMute"),
652
- enterFullscreen: /* @__PURE__ */ __name(() => videoRef.current?.requestFullscreen(), "enterFullscreen"),
653
- exitFullscreen: /* @__PURE__ */ __name(() => document.exitFullscreen(), "exitFullscreen"),
654
- get currentTime() {
655
- return videoRef.current?.currentTime ?? 0;
656
- },
657
- get duration() {
658
- return videoRef.current?.duration ?? 0;
659
- },
660
- get paused() {
661
- return videoRef.current?.paused ?? true;
662
- }
663
- }),
664
- []
665
- );
666
- const isMountedRef = useRef(true);
667
- useEffect(() => {
668
- isMountedRef.current = true;
669
- return () => {
670
- isMountedRef.current = false;
671
- if (contentKeyRef.current) {
672
- useMediaCacheStore.getState().releaseBlobUrl(contentKeyRef.current);
673
- contentKeyRef.current = null;
674
- }
675
- };
676
- }, []);
677
- useEffect(() => {
678
- if (contentKeyRef.current) {
679
- const newKey = source.type === "blob" ? generateContentKey(source.data) : null;
680
- if (newKey !== contentKeyRef.current) {
681
- releaseBlobUrl(contentKeyRef.current);
682
- contentKeyRef.current = null;
683
- }
684
- }
685
- setHasError(false);
686
- setIsLoading(true);
687
- switch (source.type) {
688
- case "stream": {
689
- const streamSource = source;
690
- const url = getOrCreateStreamUrl(
691
- streamSource.sessionId,
692
- streamSource.path,
693
- streamSource.getStreamUrl
694
- );
695
- videoDebug.load(url, "stream");
696
- setVideoUrl(url);
697
- break;
698
- }
699
- case "blob": {
700
- const blobSource = source;
701
- const contentKey = generateContentKey(blobSource.data);
702
- contentKeyRef.current = contentKey;
703
- const url = getOrCreateBlobUrl(
704
- contentKey,
705
- blobSource.data,
706
- blobSource.mimeType || "video/mp4"
707
- );
708
- videoDebug.load(url, "blob");
709
- setVideoUrl(url);
710
- break;
711
- }
712
- case "data-url": {
713
- const dataUrlSource = source;
714
- videoDebug.load(dataUrlSource.data.slice(0, 50) + "...", "data-url");
715
- setVideoUrl(dataUrlSource.data);
716
- break;
717
- }
718
- default:
719
- videoDebug.error("Invalid video source type", { type: source.type });
720
- setVideoUrl(null);
721
- setHasError(true);
722
- setErrorMessage("Invalid video source");
723
- }
724
- }, [source]);
725
- const getSourceKey = useCallback(() => {
726
- switch (source.type) {
727
- case "stream":
728
- return `stream:${source.sessionId}:${source.path}`;
729
- case "blob":
730
- return contentKeyRef.current ? `blob:${contentKeyRef.current}` : null;
731
- case "data-url":
732
- return `data:${source.data.slice(0, 50)}`;
733
- default:
734
- return null;
735
- }
736
- }, [source]);
737
- const handleCanPlay = useCallback(() => {
738
- const video = videoRef.current;
739
- if (video) {
740
- videoDebug.state("canplay", { duration: video.duration, buffered: video.buffered.length });
741
- videoDebug.buffer(video.buffered, video.duration);
742
- video.volume = savedSettings.volume;
743
- }
744
- setIsLoading(false);
745
- const sourceKey = getSourceKey();
746
- if (sourceKey && video) {
747
- const cachedPosition = getVideoPosition(sourceKey);
748
- if (cachedPosition && cachedPosition > 0) {
749
- const duration = video.duration;
750
- if (cachedPosition < duration - 1) {
751
- videoDebug.debug(`Restoring position: ${cachedPosition}s`);
752
- video.currentTime = cachedPosition;
753
- }
754
- }
755
- }
756
- onCanPlay?.();
757
- }, [getSourceKey, onCanPlay, savedSettings.volume]);
758
- const handleTimeUpdate = useCallback(() => {
759
- const video = videoRef.current;
760
- if (!video) return;
761
- const sourceKey = getSourceKey();
762
- if (sourceKey && video.currentTime > 0) {
763
- const timeSinceLastSave = video.currentTime - lastSavedTimeRef.current;
764
- if (timeSinceLastSave >= 5 || timeSinceLastSave < 0) {
765
- saveVideoPosition(sourceKey, video.currentTime);
766
- lastSavedTimeRef.current = video.currentTime;
767
- }
768
- }
769
- onTimeUpdate?.(video.currentTime, video.duration);
770
- }, [getSourceKey, onTimeUpdate]);
771
- const handlePause = useCallback(() => {
772
- const video = videoRef.current;
773
- const sourceKey = getSourceKey();
774
- if (sourceKey && video && video.currentTime > 0) {
775
- saveVideoPosition(sourceKey, video.currentTime);
776
- lastSavedTimeRef.current = video.currentTime;
777
- }
778
- onPause?.();
779
- }, [getSourceKey, onPause]);
780
- const handleProgress = useCallback(() => {
781
- const video = videoRef.current;
782
- if (!video || !onBufferProgress) return;
783
- if (video.buffered.length > 0) {
784
- const bufferedEnd = video.buffered.end(video.buffered.length - 1);
785
- const duration = video.duration;
786
- if (duration > 0 && !isNaN(bufferedEnd)) {
787
- onBufferProgress(bufferedEnd, duration);
788
- }
789
- }
790
- }, [onBufferProgress]);
791
- useEffect(() => {
792
- if (!showPreloader || !isLoading) return;
793
- const timeout = setTimeout(() => {
794
- setIsLoading(false);
795
- }, preloaderTimeout);
796
- return () => clearTimeout(timeout);
797
- }, [showPreloader, isLoading, preloaderTimeout]);
798
- const handleContextMenu = /* @__PURE__ */ __name((e) => {
799
- if (disableContextMenu) {
800
- e.preventDefault();
801
- }
802
- }, "handleContextMenu");
803
- const handleLoadedData = /* @__PURE__ */ __name(() => {
804
- setIsLoading(false);
805
- }, "handleLoadedData");
806
- const handleError = /* @__PURE__ */ __name(() => {
807
- const video = videoRef.current;
808
- if (video) {
809
- videoDebug.error("Video error", { code: video.error?.code, message: video.error?.message });
810
- }
811
- setIsLoading(false);
812
- setHasError(true);
813
- setErrorMessage("Failed to load video");
814
- onError?.("Video playback error");
815
- }, "handleError");
816
- useEffect(() => {
817
- const video = videoRef.current;
818
- if (!video) return;
819
- const handleLoadedMetadata = /* @__PURE__ */ __name(() => {
820
- videoDebug.state("loadedmetadata", { duration: video.duration });
821
- }, "handleLoadedMetadata");
822
- const handleSeeking = /* @__PURE__ */ __name(() => {
823
- videoDebug.event("seeking", { currentTime: video.currentTime });
824
- }, "handleSeeking");
825
- const handleSeeked = /* @__PURE__ */ __name(() => {
826
- videoDebug.event("seeked", { currentTime: video.currentTime });
827
- videoDebug.buffer(video.buffered, video.duration);
828
- }, "handleSeeked");
829
- const handleWaiting = /* @__PURE__ */ __name(() => {
830
- videoDebug.warn("WAITING - buffering...");
831
- videoDebug.buffer(video.buffered, video.duration);
832
- }, "handleWaiting");
833
- const handleStalled = /* @__PURE__ */ __name(() => {
834
- videoDebug.warn("STALLED - network issue");
835
- videoDebug.buffer(video.buffered, video.duration);
836
- }, "handleStalled");
837
- video.addEventListener("loadedmetadata", handleLoadedMetadata);
838
- video.addEventListener("seeking", handleSeeking);
839
- video.addEventListener("seeked", handleSeeked);
840
- video.addEventListener("waiting", handleWaiting);
841
- video.addEventListener("stalled", handleStalled);
842
- return () => {
843
- video.removeEventListener("loadedmetadata", handleLoadedMetadata);
844
- video.removeEventListener("seeking", handleSeeking);
845
- video.removeEventListener("seeked", handleSeeked);
846
- video.removeEventListener("waiting", handleWaiting);
847
- video.removeEventListener("stalled", handleStalled);
848
- };
849
- }, [videoUrl]);
850
- useEffect(() => {
851
- const video = videoRef.current;
852
- if (!video) return;
853
- const handleVolumeChange = /* @__PURE__ */ __name(() => {
854
- updateVolume(video.volume);
855
- }, "handleVolumeChange");
856
- video.addEventListener("volumechange", handleVolumeChange);
857
- return () => video.removeEventListener("volumechange", handleVolumeChange);
858
- }, [videoUrl, updateVolume]);
859
- const isFillMode = aspectRatio === "fill";
860
- const computedAspectRatio = aspectRatio === "auto" || aspectRatio === "fill" ? void 0 : aspectRatio;
861
- const renderErrorFallback = /* @__PURE__ */ __name(() => {
862
- const fallbackProps = { error: errorMessage, retry };
863
- if (typeof errorFallback === "function") {
864
- return errorFallback(fallbackProps);
865
- }
866
- if (errorFallback) {
867
- return errorFallback;
868
- }
869
- return /* @__PURE__ */ jsx(DefaultErrorFallback2, { ...fallbackProps });
870
- }, "renderErrorFallback");
871
- if (!videoUrl || hasError) {
872
- if (isFillMode) {
873
- return /* @__PURE__ */ jsx("div", { className: cn("relative w-full h-full overflow-hidden bg-black", className), children: renderErrorFallback() });
874
- }
875
- return /* @__PURE__ */ jsx("div", { className: cn("relative overflow-hidden bg-black", className), children: /* @__PURE__ */ jsx(AspectRatio, { ratio: computedAspectRatio, children: renderErrorFallback() }) });
876
- }
877
- const videoContent = /* @__PURE__ */ jsxs(Fragment, { children: [
878
- showPreloader && isLoading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black/50 z-10", children: /* @__PURE__ */ jsx(Preloader, { size: "lg", spinnerClassName: "text-white" }) }),
879
- /* @__PURE__ */ jsx(
880
- "video",
881
- {
882
- ref: videoRef,
883
- src: videoUrl,
884
- className: cn(
885
- "w-full h-full object-contain",
886
- isLoading && "opacity-0",
887
- videoClassName
888
- ),
889
- autoPlay,
890
- muted,
891
- loop,
892
- playsInline,
893
- preload,
894
- controls,
895
- crossOrigin: "anonymous",
896
- poster: source.poster,
897
- onContextMenu: handleContextMenu,
898
- onLoadStart,
899
- onCanPlay: handleCanPlay,
900
- onLoadedData: handleLoadedData,
901
- onPlay,
902
- onPause: handlePause,
903
- onEnded,
904
- onError: handleError,
905
- onTimeUpdate: handleTimeUpdate,
906
- onProgress: handleProgress
907
- }
908
- )
909
- ] });
910
- if (isFillMode) {
911
- return /* @__PURE__ */ jsx("div", { className: cn("relative w-full h-full overflow-hidden bg-black", className), children: videoContent });
912
- }
913
- return /* @__PURE__ */ jsx("div", { className: cn("relative overflow-hidden bg-black", className), children: /* @__PURE__ */ jsx(AspectRatio, { ratio: computedAspectRatio, children: videoContent }) });
914
- }
915
- );
916
- StreamProvider.displayName = "StreamProvider";
917
- var VideoPlayerContext = createContext(null);
918
- function VideoPlayerProvider({
919
- children,
920
- getStreamUrl,
921
- sessionId
922
- }) {
923
- const value = useMemo(
924
- () => ({ getStreamUrl, sessionId }),
925
- [getStreamUrl, sessionId]
926
- );
927
- return /* @__PURE__ */ jsx(VideoPlayerContext.Provider, { value, children });
928
- }
929
- __name(VideoPlayerProvider, "VideoPlayerProvider");
930
- function useVideoPlayerContext() {
931
- return useContext(VideoPlayerContext);
932
- }
933
- __name(useVideoPlayerContext, "useVideoPlayerContext");
934
-
935
- // src/tools/VideoPlayer/utils/resolvers.ts
936
- function resolvePlayerMode(source, mode = "auto") {
937
- if (mode !== "auto") {
938
- return mode;
939
- }
940
- switch (source.type) {
941
- case "youtube":
942
- case "vimeo":
943
- case "hls":
944
- case "dash":
945
- return "vidstack";
946
- case "stream":
947
- case "blob":
948
- return "streaming";
949
- case "data-url":
950
- case "url":
951
- default:
952
- return "native";
953
- }
954
- }
955
- __name(resolvePlayerMode, "resolvePlayerMode");
956
- function isSimpleStreamSource(source) {
957
- return source != null && source.type === "stream" && !("getStreamUrl" in source);
958
- }
959
- __name(isSimpleStreamSource, "isSimpleStreamSource");
960
- function resolveStreamSource(source, context) {
961
- if (!context?.getStreamUrl) {
962
- console.warn(
963
- "VideoPlayer: Stream source requires getStreamUrl. Either provide it in source or wrap with VideoPlayerProvider."
964
- );
965
- return null;
966
- }
967
- const sessionId = source.sessionId || context.sessionId;
968
- if (!sessionId) {
969
- console.warn("VideoPlayer: Stream source requires sessionId.");
970
- return null;
971
- }
972
- return {
973
- type: "stream",
974
- sessionId,
975
- path: source.path,
976
- getStreamUrl: context.getStreamUrl,
977
- mimeType: source.mimeType,
978
- title: source.title,
979
- poster: source.poster
980
- };
981
- }
982
- __name(resolveStreamSource, "resolveStreamSource");
983
-
984
- // src/tools/VideoPlayer/utils/fileSource.ts
985
- function resolveFileSource(options) {
986
- const {
987
- content,
988
- path,
989
- mimeType,
990
- sessionId,
991
- loadMethod,
992
- getStreamUrl,
993
- title,
994
- poster
995
- } = options;
996
- const contentSize = content ? typeof content === "string" ? content.length : content.byteLength : 0;
997
- const hasContent = contentSize > 0;
998
- if (loadMethod === "http_stream" && !hasContent && sessionId && getStreamUrl) {
999
- return {
1000
- type: "stream",
1001
- sessionId,
1002
- path,
1003
- getStreamUrl,
1004
- mimeType,
1005
- title,
1006
- poster
1007
- };
1008
- }
1009
- if (typeof content === "string" && hasContent) {
1010
- return {
1011
- type: "data-url",
1012
- data: content,
1013
- title,
1014
- poster
1015
- };
1016
- }
1017
- if (content instanceof ArrayBuffer && hasContent) {
1018
- return {
1019
- type: "blob",
1020
- data: content,
1021
- mimeType: mimeType || "video/mp4",
1022
- title,
1023
- poster
1024
- };
1025
- }
1026
- return null;
1027
- }
1028
- __name(resolveFileSource, "resolveFileSource");
1029
- var VideoPlayer = forwardRef(
1030
- ({
1031
- source: rawSource,
1032
- mode = "auto",
1033
- aspectRatio = 16 / 9,
1034
- autoPlay = false,
1035
- muted = false,
1036
- loop = false,
1037
- playsInline = true,
1038
- controls = true,
1039
- preload = "metadata",
1040
- theme = "default",
1041
- showInfo = false,
1042
- className,
1043
- videoClassName,
1044
- disableContextMenu = false,
1045
- showPreloader = true,
1046
- preloaderTimeout = 5e3,
1047
- errorFallback,
1048
- onPlay,
1049
- onPause,
1050
- onEnded,
1051
- onError,
1052
- onLoadStart,
1053
- onCanPlay,
1054
- onTimeUpdate
1055
- }, ref) => {
1056
- const context = useVideoPlayerContext();
1057
- const source = useMemo(() => {
1058
- if (isSimpleStreamSource(rawSource)) {
1059
- const resolved = resolveStreamSource(rawSource, context);
1060
- if (!resolved) {
1061
- return null;
1062
- }
1063
- return resolved;
1064
- }
1065
- return rawSource;
1066
- }, [rawSource, context]);
1067
- if (!source) {
1068
- const errorMessage = "Stream source requires VideoPlayerProvider with getStreamUrl and sessionId";
1069
- if (typeof errorFallback === "function") {
1070
- return /* @__PURE__ */ jsx("div", { className, style: { aspectRatio: aspectRatio === "fill" ? void 0 : aspectRatio }, children: errorFallback({ error: errorMessage }) });
1071
- }
1072
- if (errorFallback) {
1073
- return /* @__PURE__ */ jsx("div", { className, style: { aspectRatio: aspectRatio === "fill" ? void 0 : aspectRatio }, children: errorFallback });
1074
- }
1075
- return /* @__PURE__ */ jsx(
1076
- "div",
1077
- {
1078
- className,
1079
- style: {
1080
- aspectRatio: aspectRatio === "fill" ? void 0 : aspectRatio,
1081
- display: "flex",
1082
- alignItems: "center",
1083
- justifyContent: "center",
1084
- backgroundColor: "black",
1085
- color: "white"
1086
- },
1087
- children: /* @__PURE__ */ jsx("p", { children: errorMessage })
1088
- }
1089
- );
1090
- }
1091
- const resolvedMode = resolvePlayerMode(source, mode);
1092
- const commonProps = {
1093
- aspectRatio,
1094
- autoPlay,
1095
- muted,
1096
- loop,
1097
- playsInline,
1098
- controls,
1099
- preload,
1100
- className,
1101
- onPlay,
1102
- onPause,
1103
- onEnded,
1104
- onError,
1105
- onLoadStart,
1106
- onCanPlay,
1107
- onTimeUpdate
1108
- };
1109
- switch (resolvedMode) {
1110
- case "vidstack":
1111
- return /* @__PURE__ */ jsx(
1112
- VidstackProvider,
1113
- {
1114
- ref,
1115
- source,
1116
- theme,
1117
- showInfo,
1118
- errorFallback,
1119
- ...commonProps
1120
- }
1121
- );
1122
- case "streaming":
1123
- return /* @__PURE__ */ jsx(
1124
- StreamProvider,
1125
- {
1126
- ref,
1127
- source,
1128
- videoClassName,
1129
- disableContextMenu,
1130
- showPreloader,
1131
- preloaderTimeout,
1132
- errorFallback,
1133
- ...commonProps
1134
- }
1135
- );
1136
- case "native":
1137
- default:
1138
- return /* @__PURE__ */ jsx(
1139
- NativeProvider,
1140
- {
1141
- ref,
1142
- source,
1143
- videoClassName,
1144
- disableContextMenu,
1145
- showPreloader,
1146
- preloaderTimeout,
1147
- ...commonProps
1148
- }
1149
- );
1150
- }
1151
- }
1152
- );
1153
- VideoPlayer.displayName = "VideoPlayer";
1154
- function VideoControls({ player, className }) {
1155
- const store = useMediaStore(player);
1156
- const remote = useMediaRemote();
1157
- const isPaused = store.paused;
1158
- const isMuted = store.muted;
1159
- const isFullscreen = store.fullscreen;
1160
- const currentTime = store.currentTime;
1161
- const duration = store.duration;
1162
- const volume = store.volume;
1163
- const formatTime = /* @__PURE__ */ __name((seconds) => {
1164
- if (!seconds || seconds < 0) return "0:00";
1165
- const minutes = Math.floor(seconds / 60);
1166
- const secs = Math.floor(seconds % 60);
1167
- return `${minutes}:${secs.toString().padStart(2, "0")}`;
1168
- }, "formatTime");
1169
- const handleProgressClick = /* @__PURE__ */ __name((e) => {
1170
- if (!duration) return;
1171
- const rect = e.currentTarget.getBoundingClientRect();
1172
- const clickX = e.clientX - rect.left;
1173
- const percentage = clickX / rect.width;
1174
- const newTime = percentage * duration;
1175
- remote.seek(newTime);
1176
- }, "handleProgressClick");
1177
- const handleVolumeChange = /* @__PURE__ */ __name((e) => {
1178
- const rect = e.currentTarget.getBoundingClientRect();
1179
- const clickX = e.clientX - rect.left;
1180
- const percentage = Math.max(0, Math.min(1, clickX / rect.width));
1181
- remote.changeVolume(percentage);
1182
- if (percentage > 0 && isMuted) {
1183
- remote.toggleMuted();
1184
- }
1185
- }, "handleVolumeChange");
1186
- const progress = duration > 0 ? currentTime / duration * 100 : 0;
1187
- return /* @__PURE__ */ jsxs(
1188
- "div",
1189
- {
1190
- className: cn(
1191
- "absolute inset-0 flex flex-col justify-end transition-opacity duration-300",
1192
- "bg-gradient-to-t from-black/80 via-black/20 to-transparent",
1193
- "opacity-0 group-hover:opacity-100 focus-within:opacity-100",
1194
- "pointer-events-none group-hover:pointer-events-auto",
1195
- className
1196
- ),
1197
- children: [
1198
- /* @__PURE__ */ jsx("div", { className: "px-4 pb-2 pointer-events-auto", children: /* @__PURE__ */ jsx(
1199
- "div",
1200
- {
1201
- className: "h-1.5 bg-white/20 rounded-full cursor-pointer hover:h-2 transition-all group",
1202
- onClick: handleProgressClick,
1203
- children: /* @__PURE__ */ jsx(
1204
- "div",
1205
- {
1206
- className: "h-full bg-primary rounded-full transition-all relative group-hover:bg-primary/90",
1207
- style: { width: `${progress}%` },
1208
- children: /* @__PURE__ */ jsx("div", { className: "absolute right-0 top-1/2 -translate-y-1/2 w-3 h-3 bg-white rounded-full opacity-0 group-hover:opacity-100 transition-opacity" })
1209
- }
1210
- )
1211
- }
1212
- ) }),
1213
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 px-4 pb-4 pointer-events-auto", children: [
1214
- /* @__PURE__ */ jsx(
1215
- "button",
1216
- {
1217
- onClick: () => remote.togglePaused(),
1218
- className: "text-white hover:text-primary transition-colors p-1.5 hover:bg-white/10 rounded-full",
1219
- children: isPaused ? /* @__PURE__ */ jsx(Play, { className: "h-6 w-6" }) : /* @__PURE__ */ jsx(Pause, { className: "h-6 w-6" })
1220
- }
1221
- ),
1222
- /* @__PURE__ */ jsxs("div", { className: "text-white text-sm font-medium", children: [
1223
- formatTime(currentTime),
1224
- " / ",
1225
- formatTime(duration)
1226
- ] }),
1227
- /* @__PURE__ */ jsx("div", { className: "flex-1" }),
1228
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 group/volume", children: [
1229
- /* @__PURE__ */ jsx(
1230
- "button",
1231
- {
1232
- onClick: () => remote.toggleMuted(),
1233
- className: "text-white hover:text-primary transition-colors p-1.5 hover:bg-white/10 rounded-full",
1234
- children: isMuted || volume === 0 ? /* @__PURE__ */ jsx(VolumeX, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx(Volume2, { className: "h-5 w-5" })
1235
- }
1236
- ),
1237
- /* @__PURE__ */ jsx(
1238
- "div",
1239
- {
1240
- className: "w-0 group-hover/volume:w-20 transition-all overflow-hidden",
1241
- children: /* @__PURE__ */ jsx(
1242
- "div",
1243
- {
1244
- className: "h-1.5 bg-white/20 rounded-full cursor-pointer hover:h-2 transition-all",
1245
- onClick: handleVolumeChange,
1246
- children: /* @__PURE__ */ jsx(
1247
- "div",
1248
- {
1249
- className: "h-full bg-white rounded-full transition-all",
1250
- style: { width: `${volume * 100}%` }
1251
- }
1252
- )
1253
- }
1254
- )
1255
- }
1256
- )
1257
- ] }),
1258
- /* @__PURE__ */ jsx(
1259
- "button",
1260
- {
1261
- onClick: () => isFullscreen ? remote.exitFullscreen() : remote.enterFullscreen(),
1262
- className: "text-white hover:text-primary transition-colors p-1.5 hover:bg-white/10 rounded-full",
1263
- children: isFullscreen ? /* @__PURE__ */ jsx(Minimize, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx(Maximize, { className: "h-5 w-5" })
1264
- }
1265
- )
1266
- ] })
1267
- ]
1268
- }
1269
- );
1270
- }
1271
- __name(VideoControls, "VideoControls");
1272
- function VideoErrorFallback({
1273
- error,
1274
- retry,
1275
- downloadUrl,
1276
- downloadFilename,
1277
- fileSize,
1278
- showRetry = true,
1279
- className,
1280
- icon,
1281
- title,
1282
- description
1283
- }) {
1284
- const displayTitle = title || error || "Video cannot be previewed";
1285
- return /* @__PURE__ */ jsxs(
1286
- "div",
1287
- {
1288
- className: cn(
1289
- "absolute inset-0 flex flex-col items-center justify-center gap-4 bg-black/90 text-white p-6",
1290
- className
1291
- ),
1292
- children: [
1293
- icon || /* @__PURE__ */ jsx(FileVideo, { className: "w-16 h-16 text-muted-foreground" }),
1294
- /* @__PURE__ */ jsx("p", { className: "text-lg font-medium text-center", children: displayTitle }),
1295
- (description || fileSize) && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground text-center", children: description || fileSize }),
1296
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mt-2", children: [
1297
- showRetry && retry && /* @__PURE__ */ jsxs(
1298
- Button,
1299
- {
1300
- variant: "outline",
1301
- size: "sm",
1302
- onClick: retry,
1303
- className: "gap-2",
1304
- children: [
1305
- /* @__PURE__ */ jsx(RefreshCw, { className: "w-4 h-4" }),
1306
- "Retry"
1307
- ]
1308
- }
1309
- ),
1310
- downloadUrl && /* @__PURE__ */ jsx(
1311
- DownloadButton,
1312
- {
1313
- url: downloadUrl,
1314
- filename: downloadFilename,
1315
- variant: "default",
1316
- size: "sm",
1317
- children: "Download to view"
1318
- }
1319
- )
1320
- ] })
1321
- ]
1322
- }
1323
- );
1324
- }
1325
- __name(VideoErrorFallback, "VideoErrorFallback");
1326
- function createVideoErrorFallback(options) {
1327
- return (props, source) => /* @__PURE__ */ jsx(
1328
- VideoErrorFallback,
1329
- {
1330
- ...props,
1331
- downloadUrl: options.getDownloadUrl?.(source),
1332
- downloadFilename: options.getFilename?.(source),
1333
- fileSize: options.getFileSize?.(source),
1334
- showRetry: options.showRetry
1335
- }
1336
- );
1337
- }
1338
- __name(createVideoErrorFallback, "createVideoErrorFallback");
1339
-
1340
- export { NativeProvider, StreamProvider, VideoControls, VideoErrorFallback, VideoPlayer, VideoPlayerProvider, VidstackProvider, createVideoErrorFallback, isSimpleStreamSource, resolveFileSource, resolvePlayerMode, resolveStreamSource, useVideoPlayerContext };
1341
- //# sourceMappingURL=chunk-N4MZYNR4.mjs.map
1342
- //# sourceMappingURL=chunk-N4MZYNR4.mjs.map