@djangocfg/ui-tools 2.1.91
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.
- package/dist/LottiePlayer.client-LBEC2JKY.mjs +161 -0
- package/dist/LottiePlayer.client-LBEC2JKY.mjs.map +1 -0
- package/dist/LottiePlayer.client-WFMG2OOW.cjs +168 -0
- package/dist/LottiePlayer.client-WFMG2OOW.cjs.map +1 -0
- package/dist/Mermaid.client-4TU2TSH3.mjs +477 -0
- package/dist/Mermaid.client-4TU2TSH3.mjs.map +1 -0
- package/dist/Mermaid.client-SBYY364Q.cjs +483 -0
- package/dist/Mermaid.client-SBYY364Q.cjs.map +1 -0
- package/dist/PlaygroundLayout-3YVSAEAF.cjs +1003 -0
- package/dist/PlaygroundLayout-3YVSAEAF.cjs.map +1 -0
- package/dist/PlaygroundLayout-4DYBORAS.mjs +996 -0
- package/dist/PlaygroundLayout-4DYBORAS.mjs.map +1 -0
- package/dist/PrettyCode.client-LCBPPTIX.mjs +152 -0
- package/dist/PrettyCode.client-LCBPPTIX.mjs.map +1 -0
- package/dist/PrettyCode.client-PNPLXRH6.cjs +154 -0
- package/dist/PrettyCode.client-PNPLXRH6.cjs.map +1 -0
- package/dist/chunk-37ZI6VD4.mjs +12 -0
- package/dist/chunk-37ZI6VD4.mjs.map +1 -0
- package/dist/chunk-3HK2OE62.cjs +81 -0
- package/dist/chunk-3HK2OE62.cjs.map +1 -0
- package/dist/chunk-7DGDQVQW.cjs +591 -0
- package/dist/chunk-7DGDQVQW.cjs.map +1 -0
- package/dist/chunk-M6P2FU7L.mjs +572 -0
- package/dist/chunk-M6P2FU7L.mjs.map +1 -0
- package/dist/chunk-UQ3XI5MY.cjs +15 -0
- package/dist/chunk-UQ3XI5MY.cjs.map +1 -0
- package/dist/chunk-YFRNE2IR.mjs +79 -0
- package/dist/chunk-YFRNE2IR.mjs.map +1 -0
- package/dist/index.cjs +5042 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1591 -0
- package/dist/index.d.ts +1591 -0
- package/dist/index.mjs +4941 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +86 -0
- package/src/components/markdown/MarkdownMessage.tsx +340 -0
- package/src/components/markdown/index.ts +5 -0
- package/src/index.ts +26 -0
- package/src/stores/index.ts +9 -0
- package/src/stores/mediaCache.ts +534 -0
- package/src/tools/AudioPlayer/README.md +206 -0
- package/src/tools/AudioPlayer/components/HybridAudioPlayer.tsx +216 -0
- package/src/tools/AudioPlayer/components/HybridSimplePlayer.tsx +280 -0
- package/src/tools/AudioPlayer/components/HybridWaveform.tsx +279 -0
- package/src/tools/AudioPlayer/components/ReactiveCover/AudioReactiveCover.tsx +149 -0
- package/src/tools/AudioPlayer/components/ReactiveCover/effects/GlowEffect.tsx +110 -0
- package/src/tools/AudioPlayer/components/ReactiveCover/effects/MeshEffect.tsx +58 -0
- package/src/tools/AudioPlayer/components/ReactiveCover/effects/OrbsEffect.tsx +45 -0
- package/src/tools/AudioPlayer/components/ReactiveCover/effects/SpotlightEffect.tsx +82 -0
- package/src/tools/AudioPlayer/components/ReactiveCover/effects/index.ts +8 -0
- package/src/tools/AudioPlayer/components/ReactiveCover/index.ts +6 -0
- package/src/tools/AudioPlayer/components/index.ts +22 -0
- package/src/tools/AudioPlayer/context/HybridAudioProvider.tsx +158 -0
- package/src/tools/AudioPlayer/context/index.ts +16 -0
- package/src/tools/AudioPlayer/effects/index.ts +412 -0
- package/src/tools/AudioPlayer/hooks/index.ts +35 -0
- package/src/tools/AudioPlayer/hooks/useHybridAudio.ts +387 -0
- package/src/tools/AudioPlayer/hooks/useHybridAudioAnalysis.ts +95 -0
- package/src/tools/AudioPlayer/hooks/useVisualization.tsx +207 -0
- package/src/tools/AudioPlayer/index.ts +133 -0
- package/src/tools/AudioPlayer/types/effects.ts +73 -0
- package/src/tools/AudioPlayer/types/index.ts +27 -0
- package/src/tools/AudioPlayer/utils/debug.ts +14 -0
- package/src/tools/AudioPlayer/utils/formatTime.ts +10 -0
- package/src/tools/AudioPlayer/utils/index.ts +6 -0
- package/src/tools/ImageViewer/@refactoring/00-PLAN.md +71 -0
- package/src/tools/ImageViewer/@refactoring/01-TYPES.md +121 -0
- package/src/tools/ImageViewer/@refactoring/02-UTILS.md +143 -0
- package/src/tools/ImageViewer/@refactoring/03-HOOKS.md +261 -0
- package/src/tools/ImageViewer/@refactoring/04-COMPONENTS.md +427 -0
- package/src/tools/ImageViewer/@refactoring/05-EXECUTION-CHECKLIST.md +126 -0
- package/src/tools/ImageViewer/README.md +200 -0
- package/src/tools/ImageViewer/components/ImageInfo.tsx +44 -0
- package/src/tools/ImageViewer/components/ImageToolbar.tsx +145 -0
- package/src/tools/ImageViewer/components/ImageViewer.tsx +241 -0
- package/src/tools/ImageViewer/components/index.ts +7 -0
- package/src/tools/ImageViewer/hooks/index.ts +9 -0
- package/src/tools/ImageViewer/hooks/useImageLoading.ts +204 -0
- package/src/tools/ImageViewer/hooks/useImageTransform.ts +101 -0
- package/src/tools/ImageViewer/index.ts +60 -0
- package/src/tools/ImageViewer/types.ts +81 -0
- package/src/tools/ImageViewer/utils/constants.ts +59 -0
- package/src/tools/ImageViewer/utils/debug.ts +14 -0
- package/src/tools/ImageViewer/utils/index.ts +17 -0
- package/src/tools/ImageViewer/utils/lqip.ts +47 -0
- package/src/tools/JsonForm/JsonSchemaForm.tsx +197 -0
- package/src/tools/JsonForm/examples/BotConfigExample.tsx +249 -0
- package/src/tools/JsonForm/examples/RealBotConfigExample.tsx +161 -0
- package/src/tools/JsonForm/index.ts +46 -0
- package/src/tools/JsonForm/templates/ArrayFieldItemTemplate.tsx +47 -0
- package/src/tools/JsonForm/templates/ArrayFieldTemplate.tsx +74 -0
- package/src/tools/JsonForm/templates/BaseInputTemplate.tsx +107 -0
- package/src/tools/JsonForm/templates/ErrorListTemplate.tsx +35 -0
- package/src/tools/JsonForm/templates/FieldTemplate.tsx +62 -0
- package/src/tools/JsonForm/templates/ObjectFieldTemplate.tsx +116 -0
- package/src/tools/JsonForm/templates/index.ts +12 -0
- package/src/tools/JsonForm/types.ts +83 -0
- package/src/tools/JsonForm/utils.ts +213 -0
- package/src/tools/JsonForm/widgets/CheckboxWidget.tsx +37 -0
- package/src/tools/JsonForm/widgets/ColorWidget.tsx +219 -0
- package/src/tools/JsonForm/widgets/NumberWidget.tsx +89 -0
- package/src/tools/JsonForm/widgets/SelectWidget.tsx +97 -0
- package/src/tools/JsonForm/widgets/SliderWidget.tsx +148 -0
- package/src/tools/JsonForm/widgets/SwitchWidget.tsx +35 -0
- package/src/tools/JsonForm/widgets/TextWidget.tsx +96 -0
- package/src/tools/JsonForm/widgets/index.ts +14 -0
- package/src/tools/JsonTree/index.tsx +243 -0
- package/src/tools/LottiePlayer/LottiePlayer.client.tsx +213 -0
- package/src/tools/LottiePlayer/index.tsx +56 -0
- package/src/tools/LottiePlayer/types.ts +108 -0
- package/src/tools/LottiePlayer/useLottie.ts +164 -0
- package/src/tools/Mermaid/Mermaid.client.tsx +82 -0
- package/src/tools/Mermaid/components/MermaidCodeViewer.tsx +95 -0
- package/src/tools/Mermaid/components/MermaidFullscreenModal.tsx +103 -0
- package/src/tools/Mermaid/hooks/index.ts +4 -0
- package/src/tools/Mermaid/hooks/useMermaidCleanup.ts +73 -0
- package/src/tools/Mermaid/hooks/useMermaidFullscreen.ts +46 -0
- package/src/tools/Mermaid/hooks/useMermaidRenderer.ts +226 -0
- package/src/tools/Mermaid/hooks/useMermaidValidation.ts +29 -0
- package/src/tools/Mermaid/index.tsx +44 -0
- package/src/tools/Mermaid/utils/mermaid-helpers.ts +33 -0
- package/src/tools/OpenapiViewer/components/EndpointInfo.tsx +149 -0
- package/src/tools/OpenapiViewer/components/EndpointsLibrary.tsx +263 -0
- package/src/tools/OpenapiViewer/components/PlaygroundLayout.tsx +125 -0
- package/src/tools/OpenapiViewer/components/PlaygroundStepper.tsx +100 -0
- package/src/tools/OpenapiViewer/components/RequestBuilder.tsx +157 -0
- package/src/tools/OpenapiViewer/components/RequestParametersForm.tsx +253 -0
- package/src/tools/OpenapiViewer/components/ResponseViewer.tsx +173 -0
- package/src/tools/OpenapiViewer/components/VersionSelector.tsx +68 -0
- package/src/tools/OpenapiViewer/components/index.ts +14 -0
- package/src/tools/OpenapiViewer/constants.ts +39 -0
- package/src/tools/OpenapiViewer/context/PlaygroundContext.tsx +337 -0
- package/src/tools/OpenapiViewer/hooks/index.ts +8 -0
- package/src/tools/OpenapiViewer/hooks/useMobile.ts +10 -0
- package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +199 -0
- package/src/tools/OpenapiViewer/index.tsx +37 -0
- package/src/tools/OpenapiViewer/types.ts +151 -0
- package/src/tools/OpenapiViewer/utils/apiKeyManager.ts +149 -0
- package/src/tools/OpenapiViewer/utils/formatters.ts +71 -0
- package/src/tools/OpenapiViewer/utils/index.ts +9 -0
- package/src/tools/OpenapiViewer/utils/versionManager.ts +161 -0
- package/src/tools/PrettyCode/PrettyCode.client.tsx +208 -0
- package/src/tools/PrettyCode/index.tsx +47 -0
- package/src/tools/VideoPlayer/@refactoring/00-PLAN.md +91 -0
- package/src/tools/VideoPlayer/@refactoring/01-TYPES.md +284 -0
- package/src/tools/VideoPlayer/@refactoring/02-UTILS.md +141 -0
- package/src/tools/VideoPlayer/@refactoring/03-HOOKS.md +178 -0
- package/src/tools/VideoPlayer/@refactoring/04-COMPONENTS.md +95 -0
- package/src/tools/VideoPlayer/@refactoring/05-EXECUTION-CHECKLIST.md +139 -0
- package/src/tools/VideoPlayer/README.md +264 -0
- package/src/tools/VideoPlayer/components/VideoControls.tsx +138 -0
- package/src/tools/VideoPlayer/components/VideoErrorFallback.tsx +172 -0
- package/src/tools/VideoPlayer/components/VideoPlayer.tsx +201 -0
- package/src/tools/VideoPlayer/components/index.ts +14 -0
- package/src/tools/VideoPlayer/context/VideoPlayerContext.tsx +52 -0
- package/src/tools/VideoPlayer/context/index.ts +8 -0
- package/src/tools/VideoPlayer/hooks/index.ts +12 -0
- package/src/tools/VideoPlayer/hooks/useVideoPlayerSettings.ts +70 -0
- package/src/tools/VideoPlayer/hooks/useVideoPositionCache.ts +116 -0
- package/src/tools/VideoPlayer/index.ts +77 -0
- package/src/tools/VideoPlayer/providers/NativeProvider.tsx +284 -0
- package/src/tools/VideoPlayer/providers/StreamProvider.tsx +505 -0
- package/src/tools/VideoPlayer/providers/VidstackProvider.tsx +400 -0
- package/src/tools/VideoPlayer/providers/index.ts +8 -0
- package/src/tools/VideoPlayer/types/index.ts +38 -0
- package/src/tools/VideoPlayer/types/player.ts +116 -0
- package/src/tools/VideoPlayer/types/provider.ts +93 -0
- package/src/tools/VideoPlayer/types/sources.ts +97 -0
- package/src/tools/VideoPlayer/utils/debug.ts +14 -0
- package/src/tools/VideoPlayer/utils/fileSource.ts +78 -0
- package/src/tools/VideoPlayer/utils/index.ts +12 -0
- package/src/tools/VideoPlayer/utils/resolvers.ts +75 -0
- package/src/tools/_shared.ts +29 -0
- package/src/tools/index.ts +172 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VideoPlayer - Unified Video Player Component
|
|
3
|
+
*
|
|
4
|
+
* Supports multiple modes:
|
|
5
|
+
* - vidstack: Full-featured player (YouTube, Vimeo, HLS, DASH)
|
|
6
|
+
* - native: Lightweight HTML5 player
|
|
7
|
+
* - streaming: HTTP Range streaming with auth / Blob sources
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // YouTube video
|
|
11
|
+
* <VideoPlayer source={{ type: 'youtube', id: 'dQw4w9WgXcQ' }} />
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // HLS stream
|
|
15
|
+
* <VideoPlayer source={{ type: 'hls', url: 'https://example.com/video.m3u8' }} />
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // HTTP Range streaming with auth (full source)
|
|
19
|
+
* <VideoPlayer
|
|
20
|
+
* source={{
|
|
21
|
+
* type: 'stream',
|
|
22
|
+
* sessionId: 'abc123',
|
|
23
|
+
* path: '/videos/movie.mp4',
|
|
24
|
+
* getStreamUrl: (id, path) => `/api/stream/${id}?path=${path}&token=${token}`
|
|
25
|
+
* }}
|
|
26
|
+
* />
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // HTTP Range streaming (simplified, using VideoPlayerProvider context)
|
|
30
|
+
* <VideoPlayerProvider sessionId={sessionId} getStreamUrl={getStreamUrl}>
|
|
31
|
+
* <VideoPlayer source={{ type: 'stream', path: '/videos/movie.mp4' }} />
|
|
32
|
+
* </VideoPlayerProvider>
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // Blob/ArrayBuffer
|
|
36
|
+
* <VideoPlayer source={{ type: 'blob', data: arrayBuffer, mimeType: 'video/mp4' }} />
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
'use client';
|
|
40
|
+
|
|
41
|
+
import React, { forwardRef, useMemo } from 'react';
|
|
42
|
+
|
|
43
|
+
import { VidstackProvider, NativeProvider, StreamProvider } from '../providers';
|
|
44
|
+
import { useVideoPlayerContext } from '../context';
|
|
45
|
+
import { resolvePlayerMode, isSimpleStreamSource, resolveStreamSource } from '../utils';
|
|
46
|
+
|
|
47
|
+
import type { VideoPlayerProps, VideoPlayerRef, VideoSourceUnion, VidstackProviderProps, NativeProviderProps, StreamProviderProps, SimpleStreamSource } from '../types';
|
|
48
|
+
|
|
49
|
+
export const VideoPlayer = forwardRef<VideoPlayerRef, VideoPlayerProps & { source: VideoSourceUnion | SimpleStreamSource }>(
|
|
50
|
+
(
|
|
51
|
+
{
|
|
52
|
+
source: rawSource,
|
|
53
|
+
mode = 'auto',
|
|
54
|
+
aspectRatio = 16 / 9,
|
|
55
|
+
autoPlay = false,
|
|
56
|
+
muted = false,
|
|
57
|
+
loop = false,
|
|
58
|
+
playsInline = true,
|
|
59
|
+
controls = true,
|
|
60
|
+
preload = 'metadata',
|
|
61
|
+
theme = 'default',
|
|
62
|
+
showInfo = false,
|
|
63
|
+
className,
|
|
64
|
+
videoClassName,
|
|
65
|
+
disableContextMenu = false,
|
|
66
|
+
showPreloader = true,
|
|
67
|
+
preloaderTimeout = 5000,
|
|
68
|
+
errorFallback,
|
|
69
|
+
onPlay,
|
|
70
|
+
onPause,
|
|
71
|
+
onEnded,
|
|
72
|
+
onError,
|
|
73
|
+
onLoadStart,
|
|
74
|
+
onCanPlay,
|
|
75
|
+
onTimeUpdate,
|
|
76
|
+
},
|
|
77
|
+
ref
|
|
78
|
+
) => {
|
|
79
|
+
// Get context for simplified stream sources
|
|
80
|
+
const context = useVideoPlayerContext();
|
|
81
|
+
|
|
82
|
+
// Resolve simplified stream source to full source using context
|
|
83
|
+
const source = useMemo(() => {
|
|
84
|
+
if (isSimpleStreamSource(rawSource)) {
|
|
85
|
+
const resolved = resolveStreamSource(rawSource, context);
|
|
86
|
+
if (!resolved) {
|
|
87
|
+
// Return a special error source that will trigger error fallback
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
return resolved;
|
|
91
|
+
}
|
|
92
|
+
return rawSource;
|
|
93
|
+
}, [rawSource, context]);
|
|
94
|
+
|
|
95
|
+
// Handle unresolved source
|
|
96
|
+
if (!source) {
|
|
97
|
+
// Render error state
|
|
98
|
+
const errorMessage = 'Stream source requires VideoPlayerProvider with getStreamUrl and sessionId';
|
|
99
|
+
|
|
100
|
+
if (typeof errorFallback === 'function') {
|
|
101
|
+
return (
|
|
102
|
+
<div className={className} style={{ aspectRatio: aspectRatio === 'fill' ? undefined : aspectRatio }}>
|
|
103
|
+
{errorFallback({ error: errorMessage })}
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (errorFallback) {
|
|
109
|
+
return (
|
|
110
|
+
<div className={className} style={{ aspectRatio: aspectRatio === 'fill' ? undefined : aspectRatio }}>
|
|
111
|
+
{errorFallback}
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Default error UI
|
|
117
|
+
return (
|
|
118
|
+
<div
|
|
119
|
+
className={className}
|
|
120
|
+
style={{
|
|
121
|
+
aspectRatio: aspectRatio === 'fill' ? undefined : aspectRatio,
|
|
122
|
+
display: 'flex',
|
|
123
|
+
alignItems: 'center',
|
|
124
|
+
justifyContent: 'center',
|
|
125
|
+
backgroundColor: 'black',
|
|
126
|
+
color: 'white',
|
|
127
|
+
}}
|
|
128
|
+
>
|
|
129
|
+
<p>{errorMessage}</p>
|
|
130
|
+
</div>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Determine which provider to use
|
|
135
|
+
const resolvedMode = resolvePlayerMode(source, mode);
|
|
136
|
+
|
|
137
|
+
// Common props for all providers
|
|
138
|
+
const commonProps = {
|
|
139
|
+
aspectRatio,
|
|
140
|
+
autoPlay,
|
|
141
|
+
muted,
|
|
142
|
+
loop,
|
|
143
|
+
playsInline,
|
|
144
|
+
controls,
|
|
145
|
+
preload,
|
|
146
|
+
className,
|
|
147
|
+
onPlay,
|
|
148
|
+
onPause,
|
|
149
|
+
onEnded,
|
|
150
|
+
onError,
|
|
151
|
+
onLoadStart,
|
|
152
|
+
onCanPlay,
|
|
153
|
+
onTimeUpdate,
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// Render appropriate provider
|
|
157
|
+
switch (resolvedMode) {
|
|
158
|
+
case 'vidstack':
|
|
159
|
+
return (
|
|
160
|
+
<VidstackProvider
|
|
161
|
+
ref={ref}
|
|
162
|
+
source={source as VidstackProviderProps['source']}
|
|
163
|
+
theme={theme}
|
|
164
|
+
showInfo={showInfo}
|
|
165
|
+
errorFallback={errorFallback}
|
|
166
|
+
{...commonProps}
|
|
167
|
+
/>
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
case 'streaming':
|
|
171
|
+
return (
|
|
172
|
+
<StreamProvider
|
|
173
|
+
ref={ref}
|
|
174
|
+
source={source as StreamProviderProps['source']}
|
|
175
|
+
videoClassName={videoClassName}
|
|
176
|
+
disableContextMenu={disableContextMenu}
|
|
177
|
+
showPreloader={showPreloader}
|
|
178
|
+
preloaderTimeout={preloaderTimeout}
|
|
179
|
+
errorFallback={errorFallback}
|
|
180
|
+
{...commonProps}
|
|
181
|
+
/>
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
case 'native':
|
|
185
|
+
default:
|
|
186
|
+
return (
|
|
187
|
+
<NativeProvider
|
|
188
|
+
ref={ref}
|
|
189
|
+
source={source as NativeProviderProps['source']}
|
|
190
|
+
videoClassName={videoClassName}
|
|
191
|
+
disableContextMenu={disableContextMenu}
|
|
192
|
+
showPreloader={showPreloader}
|
|
193
|
+
preloaderTimeout={preloaderTimeout}
|
|
194
|
+
{...commonProps}
|
|
195
|
+
/>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
VideoPlayer.displayName = 'VideoPlayer';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VideoPlayer components - Public API
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { VideoPlayer } from './VideoPlayer';
|
|
6
|
+
export { VideoControls } from './VideoControls';
|
|
7
|
+
export {
|
|
8
|
+
VideoErrorFallback,
|
|
9
|
+
createVideoErrorFallback,
|
|
10
|
+
} from './VideoErrorFallback';
|
|
11
|
+
export type {
|
|
12
|
+
VideoErrorFallbackProps,
|
|
13
|
+
CreateVideoErrorFallbackOptions,
|
|
14
|
+
} from './VideoErrorFallback';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VideoPlayerContext - Context for streaming configuration
|
|
3
|
+
* Simplifies streaming API by providing getStreamUrl globally
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use client';
|
|
7
|
+
|
|
8
|
+
import React, { createContext, useContext, useMemo } from 'react';
|
|
9
|
+
|
|
10
|
+
import type { VideoPlayerContextValue, VideoPlayerProviderProps } from '../types';
|
|
11
|
+
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Context
|
|
14
|
+
// =============================================================================
|
|
15
|
+
|
|
16
|
+
const VideoPlayerContext = createContext<VideoPlayerContextValue | null>(null);
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Provider for VideoPlayer streaming configuration
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // In your app layout or FileWorkspace
|
|
23
|
+
* <VideoPlayerProvider
|
|
24
|
+
* sessionId={sessionId}
|
|
25
|
+
* getStreamUrl={terminalClient.terminal_media.streamStreamRetrieveUrl}
|
|
26
|
+
* >
|
|
27
|
+
* <VideoPlayer source={{ type: 'stream', path: '/video.mp4' }} />
|
|
28
|
+
* </VideoPlayerProvider>
|
|
29
|
+
*/
|
|
30
|
+
export function VideoPlayerProvider({
|
|
31
|
+
children,
|
|
32
|
+
getStreamUrl,
|
|
33
|
+
sessionId,
|
|
34
|
+
}: VideoPlayerProviderProps) {
|
|
35
|
+
const value = useMemo(
|
|
36
|
+
() => ({ getStreamUrl, sessionId }),
|
|
37
|
+
[getStreamUrl, sessionId]
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<VideoPlayerContext.Provider value={value}>
|
|
42
|
+
{children}
|
|
43
|
+
</VideoPlayerContext.Provider>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Hook to access VideoPlayer context
|
|
49
|
+
*/
|
|
50
|
+
export function useVideoPlayerContext(): VideoPlayerContextValue | null {
|
|
51
|
+
return useContext(VideoPlayerContext);
|
|
52
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VideoPlayer hooks - Public API
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { useVideoPositionCache } from './useVideoPositionCache';
|
|
6
|
+
export type {
|
|
7
|
+
UseVideoPositionCacheOptions,
|
|
8
|
+
UseVideoPositionCacheReturn,
|
|
9
|
+
} from './useVideoPositionCache';
|
|
10
|
+
|
|
11
|
+
export { useVideoPlayerSettings } from './useVideoPlayerSettings';
|
|
12
|
+
export type { VideoPlayerSettingsReturn } from './useVideoPlayerSettings';
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* useVideoPlayerSettings - Hook for persisted video player settings
|
|
5
|
+
*
|
|
6
|
+
* Provides volume and loop settings that persist in localStorage.
|
|
7
|
+
* Use this hook in video player providers to apply saved settings.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const { settings, updateVolume, updateLoop } = useVideoPlayerSettings();
|
|
11
|
+
*
|
|
12
|
+
* // Apply to video element
|
|
13
|
+
* videoRef.current.volume = settings.volume;
|
|
14
|
+
* videoRef.current.loop = settings.isLooping;
|
|
15
|
+
*
|
|
16
|
+
* // Save when user changes
|
|
17
|
+
* const handleVolumeChange = (vol: number) => {
|
|
18
|
+
* videoRef.current.volume = vol;
|
|
19
|
+
* updateVolume(vol);
|
|
20
|
+
* };
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { useCallback } from 'react';
|
|
24
|
+
import { useVideoPlayerSettings as useSettings } from '../../../stores/mediaCache';
|
|
25
|
+
|
|
26
|
+
export interface VideoPlayerSettingsReturn {
|
|
27
|
+
/** Current settings */
|
|
28
|
+
settings: {
|
|
29
|
+
volume: number;
|
|
30
|
+
isLooping: boolean;
|
|
31
|
+
};
|
|
32
|
+
/** Update volume (0-1) */
|
|
33
|
+
updateVolume: (volume: number) => void;
|
|
34
|
+
/** Update loop setting */
|
|
35
|
+
updateLoop: (isLooping: boolean) => void;
|
|
36
|
+
/** Update multiple settings at once */
|
|
37
|
+
updateSettings: (settings: { volume?: number; isLooping?: boolean }) => void;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function useVideoPlayerSettings(): VideoPlayerSettingsReturn {
|
|
41
|
+
const { settings, saveSettings } = useSettings();
|
|
42
|
+
|
|
43
|
+
const updateVolume = useCallback(
|
|
44
|
+
(volume: number) => {
|
|
45
|
+
saveSettings({ volume: Math.max(0, Math.min(1, volume)) });
|
|
46
|
+
},
|
|
47
|
+
[saveSettings]
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const updateLoop = useCallback(
|
|
51
|
+
(isLooping: boolean) => {
|
|
52
|
+
saveSettings({ isLooping });
|
|
53
|
+
},
|
|
54
|
+
[saveSettings]
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const updateSettings = useCallback(
|
|
58
|
+
(newSettings: { volume?: number; isLooping?: boolean }) => {
|
|
59
|
+
saveSettings(newSettings);
|
|
60
|
+
},
|
|
61
|
+
[saveSettings]
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
settings,
|
|
66
|
+
updateVolume,
|
|
67
|
+
updateLoop,
|
|
68
|
+
updateSettings,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* useVideoPositionCache - Manages video playback position caching
|
|
5
|
+
*
|
|
6
|
+
* Saves position periodically during playback and restores on load.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { useRef, useEffect, useCallback } from 'react';
|
|
10
|
+
import { useMediaCacheStore } from '../../../stores/mediaCache';
|
|
11
|
+
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// TYPES
|
|
14
|
+
// =============================================================================
|
|
15
|
+
|
|
16
|
+
export interface UseVideoPositionCacheOptions {
|
|
17
|
+
/** Unique key for caching (e.g., video URL or stream key) */
|
|
18
|
+
cacheKey: string | null;
|
|
19
|
+
/** Current playback time in seconds */
|
|
20
|
+
currentTime: number;
|
|
21
|
+
/** Video duration in seconds */
|
|
22
|
+
duration: number;
|
|
23
|
+
/** Whether video is currently playing */
|
|
24
|
+
isPlaying: boolean;
|
|
25
|
+
/** Whether video is ready to play */
|
|
26
|
+
isReady: boolean;
|
|
27
|
+
/** Callback to seek to a specific time */
|
|
28
|
+
onSeek: (time: number) => void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface UseVideoPositionCacheReturn {
|
|
32
|
+
/** Manually save current position */
|
|
33
|
+
savePosition: () => void;
|
|
34
|
+
/** Clear saved position */
|
|
35
|
+
clearPosition: () => void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// =============================================================================
|
|
39
|
+
// CONSTANTS
|
|
40
|
+
// =============================================================================
|
|
41
|
+
|
|
42
|
+
/** Save interval in seconds */
|
|
43
|
+
const SAVE_INTERVAL = 5;
|
|
44
|
+
|
|
45
|
+
/** Minimum offset from end to restore (avoid restoring at the very end) */
|
|
46
|
+
const END_BUFFER = 1;
|
|
47
|
+
|
|
48
|
+
// =============================================================================
|
|
49
|
+
// HOOK
|
|
50
|
+
// =============================================================================
|
|
51
|
+
|
|
52
|
+
export function useVideoPositionCache(
|
|
53
|
+
options: UseVideoPositionCacheOptions
|
|
54
|
+
): UseVideoPositionCacheReturn {
|
|
55
|
+
const { cacheKey, currentTime, duration, isPlaying, isReady, onSeek } = options;
|
|
56
|
+
|
|
57
|
+
// Get stable function references from store
|
|
58
|
+
const saveVideoPosition = useMediaCacheStore.getState().saveVideoPosition;
|
|
59
|
+
const getVideoPosition = useMediaCacheStore.getState().getVideoPosition;
|
|
60
|
+
|
|
61
|
+
const lastSavedTimeRef = useRef<number>(0);
|
|
62
|
+
const hasRestoredRef = useRef<boolean>(false);
|
|
63
|
+
|
|
64
|
+
// Restore position when ready
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
if (!isReady || !cacheKey || hasRestoredRef.current) return;
|
|
67
|
+
|
|
68
|
+
const savedPosition = getVideoPosition(cacheKey);
|
|
69
|
+
if (savedPosition && savedPosition > 0 && duration > 0) {
|
|
70
|
+
// Only restore if position is valid (not at the end)
|
|
71
|
+
if (savedPosition < duration - END_BUFFER) {
|
|
72
|
+
onSeek(savedPosition);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
hasRestoredRef.current = true;
|
|
76
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
77
|
+
}, [isReady, cacheKey, duration, onSeek]);
|
|
78
|
+
|
|
79
|
+
// Reset restored flag when cache key changes
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
hasRestoredRef.current = false;
|
|
82
|
+
lastSavedTimeRef.current = 0;
|
|
83
|
+
}, [cacheKey]);
|
|
84
|
+
|
|
85
|
+
// Save position periodically during playback
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (!cacheKey || !isPlaying || currentTime <= 0) return;
|
|
88
|
+
|
|
89
|
+
const timeSinceLastSave = currentTime - lastSavedTimeRef.current;
|
|
90
|
+
if (timeSinceLastSave >= SAVE_INTERVAL || timeSinceLastSave < 0) {
|
|
91
|
+
saveVideoPosition(cacheKey, currentTime);
|
|
92
|
+
lastSavedTimeRef.current = currentTime;
|
|
93
|
+
}
|
|
94
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
95
|
+
}, [cacheKey, isPlaying, currentTime]);
|
|
96
|
+
|
|
97
|
+
const savePosition = useCallback(() => {
|
|
98
|
+
if (cacheKey && currentTime > 0) {
|
|
99
|
+
saveVideoPosition(cacheKey, currentTime);
|
|
100
|
+
lastSavedTimeRef.current = currentTime;
|
|
101
|
+
}
|
|
102
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
103
|
+
}, [cacheKey, currentTime]);
|
|
104
|
+
|
|
105
|
+
const clearPosition = useCallback(() => {
|
|
106
|
+
if (cacheKey) {
|
|
107
|
+
saveVideoPosition(cacheKey, 0);
|
|
108
|
+
}
|
|
109
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
110
|
+
}, [cacheKey]);
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
savePosition,
|
|
114
|
+
clearPosition,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VideoPlayer - Unified Video Player
|
|
3
|
+
* Supports Vidstack (YouTube, Vimeo, HLS, DASH), Native HTML5, and HTTP Streaming
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Main component
|
|
7
|
+
export { VideoPlayer } from './components';
|
|
8
|
+
|
|
9
|
+
// Controls (can be used standalone with Vidstack)
|
|
10
|
+
export { VideoControls } from './components';
|
|
11
|
+
|
|
12
|
+
// Error Fallback
|
|
13
|
+
export {
|
|
14
|
+
VideoErrorFallback,
|
|
15
|
+
createVideoErrorFallback,
|
|
16
|
+
} from './components';
|
|
17
|
+
export type {
|
|
18
|
+
VideoErrorFallbackProps,
|
|
19
|
+
CreateVideoErrorFallbackOptions,
|
|
20
|
+
} from './components';
|
|
21
|
+
|
|
22
|
+
// Providers (for advanced usage)
|
|
23
|
+
export { VidstackProvider, NativeProvider, StreamProvider } from './providers';
|
|
24
|
+
|
|
25
|
+
// Context (for streaming configuration)
|
|
26
|
+
export {
|
|
27
|
+
VideoPlayerProvider,
|
|
28
|
+
useVideoPlayerContext,
|
|
29
|
+
} from './context';
|
|
30
|
+
|
|
31
|
+
// Hooks
|
|
32
|
+
export { useVideoPositionCache } from './hooks';
|
|
33
|
+
export type {
|
|
34
|
+
UseVideoPositionCacheOptions,
|
|
35
|
+
UseVideoPositionCacheReturn,
|
|
36
|
+
} from './hooks';
|
|
37
|
+
|
|
38
|
+
// Utils
|
|
39
|
+
export {
|
|
40
|
+
resolvePlayerMode,
|
|
41
|
+
resolveFileSource,
|
|
42
|
+
isSimpleStreamSource,
|
|
43
|
+
resolveStreamSource,
|
|
44
|
+
} from './utils';
|
|
45
|
+
|
|
46
|
+
// Types
|
|
47
|
+
export type {
|
|
48
|
+
// Source types
|
|
49
|
+
VideoSourceUnion,
|
|
50
|
+
UrlSource,
|
|
51
|
+
YouTubeSource,
|
|
52
|
+
VimeoSource,
|
|
53
|
+
HLSSource,
|
|
54
|
+
DASHSource,
|
|
55
|
+
StreamSource,
|
|
56
|
+
BlobSource,
|
|
57
|
+
DataUrlSource,
|
|
58
|
+
// Player types
|
|
59
|
+
PlayerMode,
|
|
60
|
+
AspectRatioValue,
|
|
61
|
+
VideoPlayerProps,
|
|
62
|
+
VideoPlayerRef,
|
|
63
|
+
ErrorFallbackProps,
|
|
64
|
+
// Provider props (internal)
|
|
65
|
+
VidstackProviderProps,
|
|
66
|
+
NativeProviderProps,
|
|
67
|
+
StreamProviderProps,
|
|
68
|
+
// Common types
|
|
69
|
+
CommonPlayerSettings,
|
|
70
|
+
CommonPlayerEvents,
|
|
71
|
+
// File source helper types
|
|
72
|
+
ResolveFileSourceOptions,
|
|
73
|
+
// Context types
|
|
74
|
+
VideoPlayerContextValue,
|
|
75
|
+
VideoPlayerProviderProps,
|
|
76
|
+
SimpleStreamSource,
|
|
77
|
+
} from './types';
|