@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.
Files changed (174) hide show
  1. package/dist/LottiePlayer.client-LBEC2JKY.mjs +161 -0
  2. package/dist/LottiePlayer.client-LBEC2JKY.mjs.map +1 -0
  3. package/dist/LottiePlayer.client-WFMG2OOW.cjs +168 -0
  4. package/dist/LottiePlayer.client-WFMG2OOW.cjs.map +1 -0
  5. package/dist/Mermaid.client-4TU2TSH3.mjs +477 -0
  6. package/dist/Mermaid.client-4TU2TSH3.mjs.map +1 -0
  7. package/dist/Mermaid.client-SBYY364Q.cjs +483 -0
  8. package/dist/Mermaid.client-SBYY364Q.cjs.map +1 -0
  9. package/dist/PlaygroundLayout-3YVSAEAF.cjs +1003 -0
  10. package/dist/PlaygroundLayout-3YVSAEAF.cjs.map +1 -0
  11. package/dist/PlaygroundLayout-4DYBORAS.mjs +996 -0
  12. package/dist/PlaygroundLayout-4DYBORAS.mjs.map +1 -0
  13. package/dist/PrettyCode.client-LCBPPTIX.mjs +152 -0
  14. package/dist/PrettyCode.client-LCBPPTIX.mjs.map +1 -0
  15. package/dist/PrettyCode.client-PNPLXRH6.cjs +154 -0
  16. package/dist/PrettyCode.client-PNPLXRH6.cjs.map +1 -0
  17. package/dist/chunk-37ZI6VD4.mjs +12 -0
  18. package/dist/chunk-37ZI6VD4.mjs.map +1 -0
  19. package/dist/chunk-3HK2OE62.cjs +81 -0
  20. package/dist/chunk-3HK2OE62.cjs.map +1 -0
  21. package/dist/chunk-7DGDQVQW.cjs +591 -0
  22. package/dist/chunk-7DGDQVQW.cjs.map +1 -0
  23. package/dist/chunk-M6P2FU7L.mjs +572 -0
  24. package/dist/chunk-M6P2FU7L.mjs.map +1 -0
  25. package/dist/chunk-UQ3XI5MY.cjs +15 -0
  26. package/dist/chunk-UQ3XI5MY.cjs.map +1 -0
  27. package/dist/chunk-YFRNE2IR.mjs +79 -0
  28. package/dist/chunk-YFRNE2IR.mjs.map +1 -0
  29. package/dist/index.cjs +5042 -0
  30. package/dist/index.cjs.map +1 -0
  31. package/dist/index.d.cts +1591 -0
  32. package/dist/index.d.ts +1591 -0
  33. package/dist/index.mjs +4941 -0
  34. package/dist/index.mjs.map +1 -0
  35. package/package.json +86 -0
  36. package/src/components/markdown/MarkdownMessage.tsx +340 -0
  37. package/src/components/markdown/index.ts +5 -0
  38. package/src/index.ts +26 -0
  39. package/src/stores/index.ts +9 -0
  40. package/src/stores/mediaCache.ts +534 -0
  41. package/src/tools/AudioPlayer/README.md +206 -0
  42. package/src/tools/AudioPlayer/components/HybridAudioPlayer.tsx +216 -0
  43. package/src/tools/AudioPlayer/components/HybridSimplePlayer.tsx +280 -0
  44. package/src/tools/AudioPlayer/components/HybridWaveform.tsx +279 -0
  45. package/src/tools/AudioPlayer/components/ReactiveCover/AudioReactiveCover.tsx +149 -0
  46. package/src/tools/AudioPlayer/components/ReactiveCover/effects/GlowEffect.tsx +110 -0
  47. package/src/tools/AudioPlayer/components/ReactiveCover/effects/MeshEffect.tsx +58 -0
  48. package/src/tools/AudioPlayer/components/ReactiveCover/effects/OrbsEffect.tsx +45 -0
  49. package/src/tools/AudioPlayer/components/ReactiveCover/effects/SpotlightEffect.tsx +82 -0
  50. package/src/tools/AudioPlayer/components/ReactiveCover/effects/index.ts +8 -0
  51. package/src/tools/AudioPlayer/components/ReactiveCover/index.ts +6 -0
  52. package/src/tools/AudioPlayer/components/index.ts +22 -0
  53. package/src/tools/AudioPlayer/context/HybridAudioProvider.tsx +158 -0
  54. package/src/tools/AudioPlayer/context/index.ts +16 -0
  55. package/src/tools/AudioPlayer/effects/index.ts +412 -0
  56. package/src/tools/AudioPlayer/hooks/index.ts +35 -0
  57. package/src/tools/AudioPlayer/hooks/useHybridAudio.ts +387 -0
  58. package/src/tools/AudioPlayer/hooks/useHybridAudioAnalysis.ts +95 -0
  59. package/src/tools/AudioPlayer/hooks/useVisualization.tsx +207 -0
  60. package/src/tools/AudioPlayer/index.ts +133 -0
  61. package/src/tools/AudioPlayer/types/effects.ts +73 -0
  62. package/src/tools/AudioPlayer/types/index.ts +27 -0
  63. package/src/tools/AudioPlayer/utils/debug.ts +14 -0
  64. package/src/tools/AudioPlayer/utils/formatTime.ts +10 -0
  65. package/src/tools/AudioPlayer/utils/index.ts +6 -0
  66. package/src/tools/ImageViewer/@refactoring/00-PLAN.md +71 -0
  67. package/src/tools/ImageViewer/@refactoring/01-TYPES.md +121 -0
  68. package/src/tools/ImageViewer/@refactoring/02-UTILS.md +143 -0
  69. package/src/tools/ImageViewer/@refactoring/03-HOOKS.md +261 -0
  70. package/src/tools/ImageViewer/@refactoring/04-COMPONENTS.md +427 -0
  71. package/src/tools/ImageViewer/@refactoring/05-EXECUTION-CHECKLIST.md +126 -0
  72. package/src/tools/ImageViewer/README.md +200 -0
  73. package/src/tools/ImageViewer/components/ImageInfo.tsx +44 -0
  74. package/src/tools/ImageViewer/components/ImageToolbar.tsx +145 -0
  75. package/src/tools/ImageViewer/components/ImageViewer.tsx +241 -0
  76. package/src/tools/ImageViewer/components/index.ts +7 -0
  77. package/src/tools/ImageViewer/hooks/index.ts +9 -0
  78. package/src/tools/ImageViewer/hooks/useImageLoading.ts +204 -0
  79. package/src/tools/ImageViewer/hooks/useImageTransform.ts +101 -0
  80. package/src/tools/ImageViewer/index.ts +60 -0
  81. package/src/tools/ImageViewer/types.ts +81 -0
  82. package/src/tools/ImageViewer/utils/constants.ts +59 -0
  83. package/src/tools/ImageViewer/utils/debug.ts +14 -0
  84. package/src/tools/ImageViewer/utils/index.ts +17 -0
  85. package/src/tools/ImageViewer/utils/lqip.ts +47 -0
  86. package/src/tools/JsonForm/JsonSchemaForm.tsx +197 -0
  87. package/src/tools/JsonForm/examples/BotConfigExample.tsx +249 -0
  88. package/src/tools/JsonForm/examples/RealBotConfigExample.tsx +161 -0
  89. package/src/tools/JsonForm/index.ts +46 -0
  90. package/src/tools/JsonForm/templates/ArrayFieldItemTemplate.tsx +47 -0
  91. package/src/tools/JsonForm/templates/ArrayFieldTemplate.tsx +74 -0
  92. package/src/tools/JsonForm/templates/BaseInputTemplate.tsx +107 -0
  93. package/src/tools/JsonForm/templates/ErrorListTemplate.tsx +35 -0
  94. package/src/tools/JsonForm/templates/FieldTemplate.tsx +62 -0
  95. package/src/tools/JsonForm/templates/ObjectFieldTemplate.tsx +116 -0
  96. package/src/tools/JsonForm/templates/index.ts +12 -0
  97. package/src/tools/JsonForm/types.ts +83 -0
  98. package/src/tools/JsonForm/utils.ts +213 -0
  99. package/src/tools/JsonForm/widgets/CheckboxWidget.tsx +37 -0
  100. package/src/tools/JsonForm/widgets/ColorWidget.tsx +219 -0
  101. package/src/tools/JsonForm/widgets/NumberWidget.tsx +89 -0
  102. package/src/tools/JsonForm/widgets/SelectWidget.tsx +97 -0
  103. package/src/tools/JsonForm/widgets/SliderWidget.tsx +148 -0
  104. package/src/tools/JsonForm/widgets/SwitchWidget.tsx +35 -0
  105. package/src/tools/JsonForm/widgets/TextWidget.tsx +96 -0
  106. package/src/tools/JsonForm/widgets/index.ts +14 -0
  107. package/src/tools/JsonTree/index.tsx +243 -0
  108. package/src/tools/LottiePlayer/LottiePlayer.client.tsx +213 -0
  109. package/src/tools/LottiePlayer/index.tsx +56 -0
  110. package/src/tools/LottiePlayer/types.ts +108 -0
  111. package/src/tools/LottiePlayer/useLottie.ts +164 -0
  112. package/src/tools/Mermaid/Mermaid.client.tsx +82 -0
  113. package/src/tools/Mermaid/components/MermaidCodeViewer.tsx +95 -0
  114. package/src/tools/Mermaid/components/MermaidFullscreenModal.tsx +103 -0
  115. package/src/tools/Mermaid/hooks/index.ts +4 -0
  116. package/src/tools/Mermaid/hooks/useMermaidCleanup.ts +73 -0
  117. package/src/tools/Mermaid/hooks/useMermaidFullscreen.ts +46 -0
  118. package/src/tools/Mermaid/hooks/useMermaidRenderer.ts +226 -0
  119. package/src/tools/Mermaid/hooks/useMermaidValidation.ts +29 -0
  120. package/src/tools/Mermaid/index.tsx +44 -0
  121. package/src/tools/Mermaid/utils/mermaid-helpers.ts +33 -0
  122. package/src/tools/OpenapiViewer/components/EndpointInfo.tsx +149 -0
  123. package/src/tools/OpenapiViewer/components/EndpointsLibrary.tsx +263 -0
  124. package/src/tools/OpenapiViewer/components/PlaygroundLayout.tsx +125 -0
  125. package/src/tools/OpenapiViewer/components/PlaygroundStepper.tsx +100 -0
  126. package/src/tools/OpenapiViewer/components/RequestBuilder.tsx +157 -0
  127. package/src/tools/OpenapiViewer/components/RequestParametersForm.tsx +253 -0
  128. package/src/tools/OpenapiViewer/components/ResponseViewer.tsx +173 -0
  129. package/src/tools/OpenapiViewer/components/VersionSelector.tsx +68 -0
  130. package/src/tools/OpenapiViewer/components/index.ts +14 -0
  131. package/src/tools/OpenapiViewer/constants.ts +39 -0
  132. package/src/tools/OpenapiViewer/context/PlaygroundContext.tsx +337 -0
  133. package/src/tools/OpenapiViewer/hooks/index.ts +8 -0
  134. package/src/tools/OpenapiViewer/hooks/useMobile.ts +10 -0
  135. package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +199 -0
  136. package/src/tools/OpenapiViewer/index.tsx +37 -0
  137. package/src/tools/OpenapiViewer/types.ts +151 -0
  138. package/src/tools/OpenapiViewer/utils/apiKeyManager.ts +149 -0
  139. package/src/tools/OpenapiViewer/utils/formatters.ts +71 -0
  140. package/src/tools/OpenapiViewer/utils/index.ts +9 -0
  141. package/src/tools/OpenapiViewer/utils/versionManager.ts +161 -0
  142. package/src/tools/PrettyCode/PrettyCode.client.tsx +208 -0
  143. package/src/tools/PrettyCode/index.tsx +47 -0
  144. package/src/tools/VideoPlayer/@refactoring/00-PLAN.md +91 -0
  145. package/src/tools/VideoPlayer/@refactoring/01-TYPES.md +284 -0
  146. package/src/tools/VideoPlayer/@refactoring/02-UTILS.md +141 -0
  147. package/src/tools/VideoPlayer/@refactoring/03-HOOKS.md +178 -0
  148. package/src/tools/VideoPlayer/@refactoring/04-COMPONENTS.md +95 -0
  149. package/src/tools/VideoPlayer/@refactoring/05-EXECUTION-CHECKLIST.md +139 -0
  150. package/src/tools/VideoPlayer/README.md +264 -0
  151. package/src/tools/VideoPlayer/components/VideoControls.tsx +138 -0
  152. package/src/tools/VideoPlayer/components/VideoErrorFallback.tsx +172 -0
  153. package/src/tools/VideoPlayer/components/VideoPlayer.tsx +201 -0
  154. package/src/tools/VideoPlayer/components/index.ts +14 -0
  155. package/src/tools/VideoPlayer/context/VideoPlayerContext.tsx +52 -0
  156. package/src/tools/VideoPlayer/context/index.ts +8 -0
  157. package/src/tools/VideoPlayer/hooks/index.ts +12 -0
  158. package/src/tools/VideoPlayer/hooks/useVideoPlayerSettings.ts +70 -0
  159. package/src/tools/VideoPlayer/hooks/useVideoPositionCache.ts +116 -0
  160. package/src/tools/VideoPlayer/index.ts +77 -0
  161. package/src/tools/VideoPlayer/providers/NativeProvider.tsx +284 -0
  162. package/src/tools/VideoPlayer/providers/StreamProvider.tsx +505 -0
  163. package/src/tools/VideoPlayer/providers/VidstackProvider.tsx +400 -0
  164. package/src/tools/VideoPlayer/providers/index.ts +8 -0
  165. package/src/tools/VideoPlayer/types/index.ts +38 -0
  166. package/src/tools/VideoPlayer/types/player.ts +116 -0
  167. package/src/tools/VideoPlayer/types/provider.ts +93 -0
  168. package/src/tools/VideoPlayer/types/sources.ts +97 -0
  169. package/src/tools/VideoPlayer/utils/debug.ts +14 -0
  170. package/src/tools/VideoPlayer/utils/fileSource.ts +78 -0
  171. package/src/tools/VideoPlayer/utils/index.ts +12 -0
  172. package/src/tools/VideoPlayer/utils/resolvers.ts +75 -0
  173. package/src/tools/_shared.ts +29 -0
  174. 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,8 @@
1
+ /**
2
+ * VideoPlayer context - Public API
3
+ */
4
+
5
+ export {
6
+ VideoPlayerProvider,
7
+ useVideoPlayerContext,
8
+ } from './VideoPlayerContext';
@@ -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';