@djangocfg/ui-nextjs 1.4.45
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/LICENSE +21 -0
- package/README.md +152 -0
- package/package.json +110 -0
- package/src/animations/AnimatedBackground.tsx +645 -0
- package/src/animations/index.ts +2 -0
- package/src/blocks/ArticleCard.tsx +94 -0
- package/src/blocks/ArticleList.tsx +95 -0
- package/src/blocks/CTASection.tsx +136 -0
- package/src/blocks/FeatureSection.tsx +104 -0
- package/src/blocks/Hero.tsx +102 -0
- package/src/blocks/NewsletterSection.tsx +119 -0
- package/src/blocks/StatsSection.tsx +103 -0
- package/src/blocks/SuperHero.tsx +328 -0
- package/src/blocks/TestimonialSection.tsx +122 -0
- package/src/blocks/index.ts +9 -0
- package/src/components/README.md +2018 -0
- package/src/components/breadcrumb-navigation.tsx +127 -0
- package/src/components/breadcrumb.tsx +132 -0
- package/src/components/button-download.tsx +275 -0
- package/src/components/dropdown-menu.tsx +219 -0
- package/src/components/index.ts +86 -0
- package/src/components/markdown/MarkdownMessage.tsx +338 -0
- package/src/components/markdown/index.ts +5 -0
- package/src/components/menubar.tsx +274 -0
- package/src/components/multi-select-pro/async.tsx +608 -0
- package/src/components/multi-select-pro/helpers.tsx +84 -0
- package/src/components/multi-select-pro/index.tsx +622 -0
- package/src/components/navigation-menu.tsx +153 -0
- package/src/components/pagination-static.tsx +348 -0
- package/src/components/pagination.tsx +138 -0
- package/src/components/phone-input.tsx +276 -0
- package/src/components/sidebar.tsx +866 -0
- package/src/components/sonner.tsx +31 -0
- package/src/components/ssr-pagination.tsx +237 -0
- package/src/hooks/index.ts +19 -0
- package/src/hooks/useCfgRouter.ts +153 -0
- package/src/hooks/useLocalStorage.ts +221 -0
- package/src/hooks/useQueryParams.ts +73 -0
- package/src/hooks/useSessionStorage.ts +188 -0
- package/src/hooks/useTheme.ts +57 -0
- package/src/index.ts +24 -0
- package/src/lib/index.ts +2 -0
- package/src/styles/index.css +2 -0
- package/src/theme/ForceTheme.tsx +115 -0
- package/src/theme/ThemeProvider.tsx +82 -0
- package/src/theme/ThemeToggle.tsx +52 -0
- package/src/theme/index.ts +3 -0
- package/src/tools/JsonForm/JsonSchemaForm.tsx +199 -0
- package/src/tools/JsonForm/examples/BotConfigExample.tsx +245 -0
- package/src/tools/JsonForm/examples/RealBotConfigExample.tsx +157 -0
- package/src/tools/JsonForm/index.ts +46 -0
- package/src/tools/JsonForm/templates/ArrayFieldItemTemplate.tsx +46 -0
- package/src/tools/JsonForm/templates/ArrayFieldTemplate.tsx +73 -0
- package/src/tools/JsonForm/templates/BaseInputTemplate.tsx +106 -0
- package/src/tools/JsonForm/templates/ErrorListTemplate.tsx +34 -0
- package/src/tools/JsonForm/templates/FieldTemplate.tsx +61 -0
- package/src/tools/JsonForm/templates/ObjectFieldTemplate.tsx +43 -0
- package/src/tools/JsonForm/templates/index.ts +12 -0
- package/src/tools/JsonForm/types.ts +83 -0
- package/src/tools/JsonForm/utils.ts +212 -0
- package/src/tools/JsonForm/widgets/CheckboxWidget.tsx +36 -0
- package/src/tools/JsonForm/widgets/NumberWidget.tsx +88 -0
- package/src/tools/JsonForm/widgets/SelectWidget.tsx +100 -0
- package/src/tools/JsonForm/widgets/SwitchWidget.tsx +34 -0
- package/src/tools/JsonForm/widgets/TextWidget.tsx +95 -0
- package/src/tools/JsonForm/widgets/index.ts +12 -0
- package/src/tools/JsonTree/index.tsx +252 -0
- package/src/tools/LottiePlayer/LottiePlayer.client.tsx +212 -0
- package/src/tools/LottiePlayer/index.tsx +54 -0
- package/src/tools/LottiePlayer/types.ts +108 -0
- package/src/tools/LottiePlayer/useLottie.ts +163 -0
- package/src/tools/Mermaid/Mermaid.client.tsx +341 -0
- package/src/tools/Mermaid/index.tsx +40 -0
- package/src/tools/OpenapiViewer/components/EndpointInfo.tsx +144 -0
- package/src/tools/OpenapiViewer/components/EndpointsLibrary.tsx +255 -0
- package/src/tools/OpenapiViewer/components/PlaygroundLayout.tsx +123 -0
- package/src/tools/OpenapiViewer/components/PlaygroundStepper.tsx +98 -0
- package/src/tools/OpenapiViewer/components/RequestBuilder.tsx +164 -0
- package/src/tools/OpenapiViewer/components/RequestParametersForm.tsx +253 -0
- package/src/tools/OpenapiViewer/components/ResponseViewer.tsx +169 -0
- package/src/tools/OpenapiViewer/components/VersionSelector.tsx +64 -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 +338 -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 +203 -0
- package/src/tools/OpenapiViewer/index.tsx +36 -0
- package/src/tools/OpenapiViewer/types.ts +152 -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 +217 -0
- package/src/tools/PrettyCode/index.tsx +43 -0
- package/src/tools/VideoPlayer/README.md +239 -0
- package/src/tools/VideoPlayer/VideoControls.tsx +138 -0
- package/src/tools/VideoPlayer/VideoPlayer.tsx +230 -0
- package/src/tools/VideoPlayer/index.ts +9 -0
- package/src/tools/VideoPlayer/types.ts +62 -0
- package/src/tools/index.ts +43 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Professional VideoPlayer - Vidstack Implementation
|
|
4
|
+
* Supports YouTube, Vimeo, MP4, HLS and more with custom controls
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use client';
|
|
8
|
+
|
|
9
|
+
import React, { forwardRef, useImperativeHandle, useRef, useMemo } from 'react';
|
|
10
|
+
import { MediaPlayer, MediaProvider, Poster } from '@vidstack/react';
|
|
11
|
+
import { defaultLayoutIcons, DefaultVideoLayout } from '@vidstack/react/player/layouts/default';
|
|
12
|
+
import type { MediaPlayerInstance } from '@vidstack/react';
|
|
13
|
+
import { cn } from '@djangocfg/ui-core/lib';
|
|
14
|
+
import { generateOgImageUrl } from '@djangocfg/ui-core/lib';
|
|
15
|
+
import { type VideoPlayerProps, type VideoPlayerRef } from './types';
|
|
16
|
+
|
|
17
|
+
// Import Vidstack base styles
|
|
18
|
+
import '@vidstack/react/player/styles/base.css';
|
|
19
|
+
// Import default theme
|
|
20
|
+
import '@vidstack/react/player/styles/default/theme.css';
|
|
21
|
+
import '@vidstack/react/player/styles/default/layouts/video.css';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Custom error class for invalid video URLs
|
|
25
|
+
*/
|
|
26
|
+
export class VideoUrlError extends Error {
|
|
27
|
+
constructor(
|
|
28
|
+
message: string,
|
|
29
|
+
public readonly url: string,
|
|
30
|
+
public readonly suggestion?: string
|
|
31
|
+
) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = 'VideoUrlError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Validates and normalizes video URL for Vidstack
|
|
39
|
+
* @throws {VideoUrlError} If URL format is invalid for the detected provider
|
|
40
|
+
*/
|
|
41
|
+
function normalizeVideoUrl(url: string): string {
|
|
42
|
+
if (!url || typeof url !== 'string') {
|
|
43
|
+
throw new VideoUrlError('Video URL is required', url || '');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const trimmedUrl = url.trim();
|
|
47
|
+
|
|
48
|
+
// Already in correct format (youtube/ID, vimeo/ID, or direct URL)
|
|
49
|
+
if (trimmedUrl.startsWith('youtube/') || trimmedUrl.startsWith('vimeo/')) {
|
|
50
|
+
return trimmedUrl;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// YouTube URL patterns - auto-convert to youtube/ID format
|
|
54
|
+
const youtubePatterns = [
|
|
55
|
+
/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/,
|
|
56
|
+
/youtube\.com\/shorts\/([a-zA-Z0-9_-]{11})/,
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
for (const pattern of youtubePatterns) {
|
|
60
|
+
const match = trimmedUrl.match(pattern);
|
|
61
|
+
if (match) {
|
|
62
|
+
// Auto-convert YouTube URL to youtube/ID format
|
|
63
|
+
const videoId = match[1];
|
|
64
|
+
return `youtube/${videoId}`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Vimeo URL patterns - auto-convert to vimeo/ID format
|
|
69
|
+
const vimeoPattern = /vimeo\.com\/(\d+)/;
|
|
70
|
+
const vimeoMatch = trimmedUrl.match(vimeoPattern);
|
|
71
|
+
if (vimeoMatch) {
|
|
72
|
+
const videoId = vimeoMatch[1];
|
|
73
|
+
return `vimeo/${videoId}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Direct video URLs (mp4, webm, etc.) - allow as-is
|
|
77
|
+
if (/\.(mp4|webm|ogg|m3u8|mpd)(\?.*)?$/i.test(trimmedUrl)) {
|
|
78
|
+
return trimmedUrl;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// HLS/DASH streams
|
|
82
|
+
if (trimmedUrl.includes('.m3u8') || trimmedUrl.includes('.mpd')) {
|
|
83
|
+
return trimmedUrl;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Unknown format - return as-is
|
|
87
|
+
return trimmedUrl;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export const VideoPlayer = forwardRef<VideoPlayerRef, VideoPlayerProps>(({
|
|
91
|
+
source,
|
|
92
|
+
aspectRatio = 16 / 9,
|
|
93
|
+
autoplay = false,
|
|
94
|
+
muted = false,
|
|
95
|
+
playsInline = true,
|
|
96
|
+
controls = true,
|
|
97
|
+
className,
|
|
98
|
+
showInfo = false,
|
|
99
|
+
theme = 'default',
|
|
100
|
+
onPlay,
|
|
101
|
+
onPause,
|
|
102
|
+
onEnded,
|
|
103
|
+
onError,
|
|
104
|
+
}, ref) => {
|
|
105
|
+
const playerRef = useRef<MediaPlayerInstance | null>(null);
|
|
106
|
+
|
|
107
|
+
// Auto-generate poster if not provided (uses OG Image API)
|
|
108
|
+
const posterUrl = useMemo(() => {
|
|
109
|
+
if (source.poster) return source.poster;
|
|
110
|
+
if (!source.title) return undefined;
|
|
111
|
+
return generateOgImageUrl({ title: source.title, description: source.description });
|
|
112
|
+
}, [source.poster, source.title, source.description]);
|
|
113
|
+
|
|
114
|
+
// Validate and normalize URL - throws VideoUrlError if invalid
|
|
115
|
+
const normalizedUrl = useMemo(() => {
|
|
116
|
+
try {
|
|
117
|
+
return normalizeVideoUrl(source.url);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
if (error instanceof VideoUrlError) {
|
|
120
|
+
// Call onError callback and re-throw
|
|
121
|
+
onError?.(error.message + (error.suggestion ? ` Use: "${error.suggestion}"` : ''));
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
}, [source.url, onError]);
|
|
127
|
+
|
|
128
|
+
// Expose player methods via ref
|
|
129
|
+
useImperativeHandle(ref, () => {
|
|
130
|
+
const player = playerRef.current;
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
play: () => player?.play(),
|
|
134
|
+
pause: () => player?.pause(),
|
|
135
|
+
togglePlay: () => {
|
|
136
|
+
if (player) {
|
|
137
|
+
player.paused ? player.play() : player.pause();
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
seekTo: (time: number) => {
|
|
141
|
+
if (player) player.currentTime = time;
|
|
142
|
+
},
|
|
143
|
+
setVolume: (volume: number) => {
|
|
144
|
+
if (player) player.volume = Math.max(0, Math.min(1, volume));
|
|
145
|
+
},
|
|
146
|
+
toggleMute: () => {
|
|
147
|
+
if (player) player.muted = !player.muted;
|
|
148
|
+
},
|
|
149
|
+
enterFullscreen: () => player?.enterFullscreen(),
|
|
150
|
+
exitFullscreen: () => player?.exitFullscreen(),
|
|
151
|
+
};
|
|
152
|
+
}, []);
|
|
153
|
+
|
|
154
|
+
const handlePlay = () => {
|
|
155
|
+
onPlay?.();
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const handlePause = () => {
|
|
159
|
+
onPause?.();
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const handleEnded = () => {
|
|
163
|
+
onEnded?.();
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const handleError = (detail: any) => {
|
|
167
|
+
onError?.(detail?.message || 'Video playback error');
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<div className={cn("w-full", className)}>
|
|
172
|
+
{/* Video Player */}
|
|
173
|
+
<div
|
|
174
|
+
className={cn(
|
|
175
|
+
"relative w-full rounded-sm bg-black overflow-hidden",
|
|
176
|
+
theme === 'minimal' && "rounded-none",
|
|
177
|
+
theme === 'modern' && "rounded-xl shadow-2xl"
|
|
178
|
+
)}
|
|
179
|
+
style={{ aspectRatio: aspectRatio }}
|
|
180
|
+
>
|
|
181
|
+
<MediaPlayer
|
|
182
|
+
ref={playerRef}
|
|
183
|
+
title={source.title || 'Video'}
|
|
184
|
+
src={normalizedUrl}
|
|
185
|
+
autoPlay={autoplay}
|
|
186
|
+
muted={muted}
|
|
187
|
+
playsInline={playsInline}
|
|
188
|
+
onPlay={handlePlay}
|
|
189
|
+
onPause={handlePause}
|
|
190
|
+
onEnded={handleEnded}
|
|
191
|
+
onError={handleError}
|
|
192
|
+
className="w-full h-full"
|
|
193
|
+
>
|
|
194
|
+
<MediaProvider />
|
|
195
|
+
|
|
196
|
+
{/* Poster with proper aspect ratio handling */}
|
|
197
|
+
{source.poster && (
|
|
198
|
+
<Poster
|
|
199
|
+
className="vds-poster"
|
|
200
|
+
src={source.poster}
|
|
201
|
+
alt={source.title || 'Video poster'}
|
|
202
|
+
style={{ objectFit: 'cover' }}
|
|
203
|
+
/>
|
|
204
|
+
)}
|
|
205
|
+
|
|
206
|
+
{/* Use Vidstack's built-in default layout */}
|
|
207
|
+
{controls && (
|
|
208
|
+
<DefaultVideoLayout
|
|
209
|
+
icons={defaultLayoutIcons}
|
|
210
|
+
thumbnails={source.poster}
|
|
211
|
+
/>
|
|
212
|
+
)}
|
|
213
|
+
</MediaPlayer>
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
{/* Video Info */}
|
|
217
|
+
{showInfo && source.title && (
|
|
218
|
+
<div className="mt-4 space-y-2">
|
|
219
|
+
<h3 className="text-xl font-semibold text-foreground">{source.title}</h3>
|
|
220
|
+
{source.description && (
|
|
221
|
+
<p className="text-muted-foreground">{source.description}</p>
|
|
222
|
+
)}
|
|
223
|
+
</div>
|
|
224
|
+
)}
|
|
225
|
+
</div>
|
|
226
|
+
);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
VideoPlayer.displayName = 'VideoPlayer';
|
|
230
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Professional VideoPlayer - Vidstack Implementation
|
|
3
|
+
* Export all components and types
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { VideoPlayer, VideoUrlError } from './VideoPlayer';
|
|
7
|
+
export { VideoControls } from './VideoControls';
|
|
8
|
+
export type { VideoSource, VideoPlayerProps, VideoPlayerRef } from './types';
|
|
9
|
+
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VideoPlayer Types - Professional Vidstack Implementation
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface VideoSource {
|
|
6
|
+
/** Video URL - supports YouTube, Vimeo, MP4, HLS, etc. */
|
|
7
|
+
url: string;
|
|
8
|
+
/** Video title */
|
|
9
|
+
title?: string;
|
|
10
|
+
/** Video description */
|
|
11
|
+
description?: string;
|
|
12
|
+
/** Custom poster/thumbnail URL */
|
|
13
|
+
poster?: string;
|
|
14
|
+
/** Video duration in seconds */
|
|
15
|
+
duration?: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface VideoPlayerProps {
|
|
19
|
+
/** Video source configuration */
|
|
20
|
+
source: VideoSource;
|
|
21
|
+
/** Aspect ratio (default: 16/9) */
|
|
22
|
+
aspectRatio?: number;
|
|
23
|
+
/** Auto-play video */
|
|
24
|
+
autoplay?: boolean;
|
|
25
|
+
/** Mute video by default */
|
|
26
|
+
muted?: boolean;
|
|
27
|
+
/** Play video inline on mobile */
|
|
28
|
+
playsInline?: boolean;
|
|
29
|
+
/** Show custom controls */
|
|
30
|
+
controls?: boolean;
|
|
31
|
+
/** Custom CSS class */
|
|
32
|
+
className?: string;
|
|
33
|
+
/** Show video info */
|
|
34
|
+
showInfo?: boolean;
|
|
35
|
+
/** Player theme */
|
|
36
|
+
theme?: 'default' | 'minimal' | 'modern';
|
|
37
|
+
/** Event callbacks */
|
|
38
|
+
onPlay?: () => void;
|
|
39
|
+
onPause?: () => void;
|
|
40
|
+
onEnded?: () => void;
|
|
41
|
+
onError?: (error: string) => void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface VideoPlayerRef {
|
|
45
|
+
/** Play video */
|
|
46
|
+
play: () => void;
|
|
47
|
+
/** Pause video */
|
|
48
|
+
pause: () => void;
|
|
49
|
+
/** Toggle play/pause */
|
|
50
|
+
togglePlay: () => void;
|
|
51
|
+
/** Seek to time */
|
|
52
|
+
seekTo: (time: number) => void;
|
|
53
|
+
/** Set volume (0-1) */
|
|
54
|
+
setVolume: (volume: number) => void;
|
|
55
|
+
/** Toggle mute */
|
|
56
|
+
toggleMute: () => void;
|
|
57
|
+
/** Enter fullscreen */
|
|
58
|
+
enterFullscreen: () => void;
|
|
59
|
+
/** Exit fullscreen */
|
|
60
|
+
exitFullscreen: () => void;
|
|
61
|
+
}
|
|
62
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tools - Heavy components with dynamic imports
|
|
3
|
+
*
|
|
4
|
+
* All components are lazy-loaded to reduce initial bundle size:
|
|
5
|
+
* - Mermaid: ~800KB (diagram rendering)
|
|
6
|
+
* - PrettyCode: ~500KB (code syntax highlighting)
|
|
7
|
+
* - JsonTree: ~100KB (JSON visualization)
|
|
8
|
+
* - LottiePlayer: ~200KB (Lottie animation player)
|
|
9
|
+
* - JsonForm: ~300KB (JSON Schema form generator)
|
|
10
|
+
* - OpenapiViewer: ~400KB (OpenAPI schema viewer & playground)
|
|
11
|
+
* - VideoPlayer: ~150KB (Professional video player with Vidstack)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// Export tools as named exports (all use dynamic imports internally)
|
|
15
|
+
export { default as JsonTree } from './JsonTree';
|
|
16
|
+
export type { JsonTreeConfig } from './JsonTree';
|
|
17
|
+
export { default as Mermaid } from './Mermaid';
|
|
18
|
+
export { default as PrettyCode } from './PrettyCode';
|
|
19
|
+
export type { Language } from './PrettyCode';
|
|
20
|
+
export { LottiePlayer, useLottie } from './LottiePlayer';
|
|
21
|
+
export type {
|
|
22
|
+
LottiePlayerProps,
|
|
23
|
+
LottieSize,
|
|
24
|
+
LottieSpeed,
|
|
25
|
+
LottieDirection,
|
|
26
|
+
UseLottieOptions,
|
|
27
|
+
UseLottieReturn,
|
|
28
|
+
} from './LottiePlayer';
|
|
29
|
+
|
|
30
|
+
// Export JsonForm components
|
|
31
|
+
export { JsonSchemaForm } from './JsonForm';
|
|
32
|
+
export type { JsonSchemaFormProps } from './JsonForm';
|
|
33
|
+
export * from './JsonForm/widgets';
|
|
34
|
+
export * from './JsonForm/templates';
|
|
35
|
+
export * from './JsonForm/utils';
|
|
36
|
+
|
|
37
|
+
// Export OpenapiViewer
|
|
38
|
+
export { default as OpenapiViewer } from './OpenapiViewer';
|
|
39
|
+
export type { PlaygroundConfig, SchemaSource, PlaygroundProps } from './OpenapiViewer';
|
|
40
|
+
|
|
41
|
+
// Export VideoPlayer
|
|
42
|
+
export { VideoPlayer, VideoUrlError, VideoControls } from './VideoPlayer';
|
|
43
|
+
export type { VideoSource, VideoPlayerProps, VideoPlayerRef } from './VideoPlayer';
|