@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,208 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Highlight, Language, themes } from 'prism-react-renderer';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
import { CopyButton } from '@djangocfg/ui-core/components';
|
|
7
|
+
|
|
8
|
+
import { useResolvedTheme } from '@djangocfg/ui-core/hooks';
|
|
9
|
+
|
|
10
|
+
interface PrettyCodeProps {
|
|
11
|
+
data: string | object;
|
|
12
|
+
language: Language;
|
|
13
|
+
className?: string;
|
|
14
|
+
mode?: 'dark' | 'light';
|
|
15
|
+
inline?: boolean;
|
|
16
|
+
customBg?: string; // Custom background class
|
|
17
|
+
isCompact?: boolean; // Compact mode for smaller font sizes
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const PrettyCode = ({ data, language, className, mode, inline = false, customBg, isCompact = false }: PrettyCodeProps) => {
|
|
21
|
+
const detectedTheme = useResolvedTheme();
|
|
22
|
+
|
|
23
|
+
// Font size based on compact mode
|
|
24
|
+
const fontSize = isCompact ? '0.75rem' : '0.875rem'; // 12px vs 14px
|
|
25
|
+
|
|
26
|
+
// Use provided mode or fall back to detected theme
|
|
27
|
+
const currentTheme = mode || detectedTheme;
|
|
28
|
+
const isDarkMode = currentTheme === 'dark';
|
|
29
|
+
|
|
30
|
+
// Select the Prism theme based on the current theme
|
|
31
|
+
const prismTheme = isDarkMode ? themes.vsDark : themes.vsLight;
|
|
32
|
+
|
|
33
|
+
// Convert form object to JSON string with proper formatting
|
|
34
|
+
const contentJson = typeof data === 'string' ? data : JSON.stringify(data || {}, null, 2);
|
|
35
|
+
|
|
36
|
+
// Handle empty content
|
|
37
|
+
if (!contentJson || contentJson.trim() === '') {
|
|
38
|
+
const bgClass = customBg || 'bg-muted dark:bg-zinc-900';
|
|
39
|
+
return (
|
|
40
|
+
<div className={`relative h-full ${bgClass} rounded-sm border border-border dark:border-zinc-700 ${className || ''}`}>
|
|
41
|
+
<div className="h-full overflow-auto p-4">
|
|
42
|
+
<p className="text-muted-foreground text-sm italic">No content available</p>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Get display name for language badge
|
|
49
|
+
const getLanguageDisplayName = (lang: string): string => {
|
|
50
|
+
switch (lang.toLowerCase()) {
|
|
51
|
+
case 'bash':
|
|
52
|
+
case 'shell':
|
|
53
|
+
return 'Bash';
|
|
54
|
+
case 'python':
|
|
55
|
+
case 'py':
|
|
56
|
+
return 'Python';
|
|
57
|
+
case 'javascript':
|
|
58
|
+
case 'js':
|
|
59
|
+
return 'JavaScript';
|
|
60
|
+
case 'typescript':
|
|
61
|
+
case 'ts':
|
|
62
|
+
return 'TypeScript';
|
|
63
|
+
case 'json':
|
|
64
|
+
return 'JSON';
|
|
65
|
+
case 'yaml':
|
|
66
|
+
case 'yml':
|
|
67
|
+
return 'YAML';
|
|
68
|
+
case 'html':
|
|
69
|
+
return 'HTML';
|
|
70
|
+
case 'css':
|
|
71
|
+
return 'CSS';
|
|
72
|
+
case 'sql':
|
|
73
|
+
return 'SQL';
|
|
74
|
+
case 'xml':
|
|
75
|
+
return 'XML';
|
|
76
|
+
case 'markdown':
|
|
77
|
+
case 'md':
|
|
78
|
+
return 'Markdown';
|
|
79
|
+
case 'plaintext':
|
|
80
|
+
case 'text':
|
|
81
|
+
return 'Text';
|
|
82
|
+
case 'mermaid':
|
|
83
|
+
return 'Mermaid';
|
|
84
|
+
default:
|
|
85
|
+
return lang.charAt(0).toUpperCase() + lang.slice(1);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Normalize language for Prism - use only basic supported languages
|
|
90
|
+
const normalizedLanguage = (() => {
|
|
91
|
+
const lang = language.toLowerCase();
|
|
92
|
+
|
|
93
|
+
// Try basic languages that are definitely supported
|
|
94
|
+
switch (lang) {
|
|
95
|
+
case 'javascript':
|
|
96
|
+
case 'js':
|
|
97
|
+
return 'javascript';
|
|
98
|
+
case 'typescript':
|
|
99
|
+
case 'ts':
|
|
100
|
+
return 'typescript'; // Try TypeScript first
|
|
101
|
+
case 'python':
|
|
102
|
+
case 'py':
|
|
103
|
+
return 'python';
|
|
104
|
+
case 'json':
|
|
105
|
+
return 'json';
|
|
106
|
+
case 'css':
|
|
107
|
+
return 'css';
|
|
108
|
+
case 'html':
|
|
109
|
+
return 'markup';
|
|
110
|
+
case 'xml':
|
|
111
|
+
return 'markup';
|
|
112
|
+
case 'bash':
|
|
113
|
+
case 'shell':
|
|
114
|
+
return 'bash';
|
|
115
|
+
case 'sql':
|
|
116
|
+
return 'sql';
|
|
117
|
+
case 'yaml':
|
|
118
|
+
case 'yml':
|
|
119
|
+
return 'yaml';
|
|
120
|
+
case 'markdown':
|
|
121
|
+
case 'md':
|
|
122
|
+
return 'markdown';
|
|
123
|
+
case 'mermaid':
|
|
124
|
+
return 'text'; // Mermaid is handled separately in MarkdownMessage
|
|
125
|
+
default:
|
|
126
|
+
// For unknown languages, try to use the original name first
|
|
127
|
+
// If it doesn't work, Prism will fallback to plain text
|
|
128
|
+
return lang || 'text';
|
|
129
|
+
}
|
|
130
|
+
})();
|
|
131
|
+
|
|
132
|
+
const displayLanguage = getLanguageDisplayName(language);
|
|
133
|
+
|
|
134
|
+
if (inline) {
|
|
135
|
+
const inlineBgClass = customBg || 'bg-muted dark:bg-[#1e1e1e]';
|
|
136
|
+
return (
|
|
137
|
+
<Highlight theme={prismTheme} code={contentJson} language={normalizedLanguage as Language}>
|
|
138
|
+
{({ className, style, tokens, getTokenProps }) => (
|
|
139
|
+
<code
|
|
140
|
+
className={`${className} ${inlineBgClass} px-2 py-1 rounded ${isCompact ? 'text-xs' : 'text-sm'} font-mono inline-block`}
|
|
141
|
+
style={{
|
|
142
|
+
...style,
|
|
143
|
+
fontSize,
|
|
144
|
+
fontFamily: 'monospace',
|
|
145
|
+
}}
|
|
146
|
+
>
|
|
147
|
+
{tokens.map((line) => (
|
|
148
|
+
line.map((token, key) => (
|
|
149
|
+
<span key={key} {...getTokenProps({ token })} />
|
|
150
|
+
))
|
|
151
|
+
))}
|
|
152
|
+
</code>
|
|
153
|
+
)}
|
|
154
|
+
</Highlight>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const bgClass = customBg || 'bg-muted dark:bg-[#1e1e1e]';
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<div className={`relative h-full ${bgClass} rounded-sm border border-border dark:border-zinc-800 dark:shadow-sm ${className || ''}`}>
|
|
162
|
+
{/* Header with language badge and copy button */}
|
|
163
|
+
<div className="absolute top-2 left-3 right-3 z-10 flex items-center justify-between">
|
|
164
|
+
<span className="inline-flex items-center px-2 py-1 rounded text-xs font-medium bg-background/80 text-muted-foreground border border-border/50 backdrop-blur-sm">
|
|
165
|
+
{displayLanguage}
|
|
166
|
+
</span>
|
|
167
|
+
<CopyButton
|
|
168
|
+
value={contentJson}
|
|
169
|
+
variant="ghost"
|
|
170
|
+
className="h-7 w-7 bg-background/80 border border-border/50 backdrop-blur-sm"
|
|
171
|
+
iconClassName="h-3.5 w-3.5"
|
|
172
|
+
title="Copy code"
|
|
173
|
+
/>
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
<div className="h-full overflow-auto">
|
|
177
|
+
<Highlight theme={prismTheme} code={contentJson} language={normalizedLanguage as Language}>
|
|
178
|
+
{({ className, style, tokens, getLineProps, getTokenProps }) => (
|
|
179
|
+
<pre
|
|
180
|
+
className={`${className}`}
|
|
181
|
+
style={{
|
|
182
|
+
...style,
|
|
183
|
+
margin: 0,
|
|
184
|
+
padding: '2.5rem 1rem 1rem 1rem', // Extra top padding for language badge
|
|
185
|
+
fontSize,
|
|
186
|
+
lineHeight: isCompact ? 1.4 : 1.5,
|
|
187
|
+
fontFamily: 'monospace',
|
|
188
|
+
whiteSpace: 'pre-wrap',
|
|
189
|
+
wordBreak: 'break-word',
|
|
190
|
+
overflowWrap: 'break-word',
|
|
191
|
+
}}
|
|
192
|
+
>
|
|
193
|
+
{tokens.map((line, i) => (
|
|
194
|
+
<div key={i} {...getLineProps({ line })}>
|
|
195
|
+
{line.map((token, key) => (
|
|
196
|
+
<span key={key} {...getTokenProps({ token })} />
|
|
197
|
+
))}
|
|
198
|
+
</div>
|
|
199
|
+
))}
|
|
200
|
+
</pre>
|
|
201
|
+
)}
|
|
202
|
+
</Highlight>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
);
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
export default PrettyCode;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PrettyCode Component - Dynamic Import Wrapper
|
|
3
|
+
*
|
|
4
|
+
* Lazy loads the heavy Prism library (~500KB) only when needed.
|
|
5
|
+
* This significantly reduces the initial bundle size.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use client';
|
|
9
|
+
|
|
10
|
+
import React, { lazy, Suspense } from 'react';
|
|
11
|
+
import type { Language } from 'prism-react-renderer';
|
|
12
|
+
|
|
13
|
+
// Lazy load the client component
|
|
14
|
+
const PrettyCodeClient = lazy(() => import('./PrettyCode.client'));
|
|
15
|
+
|
|
16
|
+
// Loading fallback component
|
|
17
|
+
const LoadingFallback = () => (
|
|
18
|
+
<div className="relative rounded-sm border border-border overflow-hidden bg-muted dark:bg-zinc-900">
|
|
19
|
+
<div className="p-4">
|
|
20
|
+
<div className="flex items-center gap-2">
|
|
21
|
+
<div className="animate-pulse h-4 w-4 rounded-full bg-muted-foreground/20"></div>
|
|
22
|
+
<span className="text-xs text-muted-foreground">Loading code...</span>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
interface PrettyCodeProps {
|
|
29
|
+
data: string | object;
|
|
30
|
+
language: Language;
|
|
31
|
+
className?: string;
|
|
32
|
+
mode?: 'dark' | 'light';
|
|
33
|
+
inline?: boolean;
|
|
34
|
+
customBg?: string;
|
|
35
|
+
isCompact?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const PrettyCode: React.FC<PrettyCodeProps> = (props) => {
|
|
39
|
+
return (
|
|
40
|
+
<Suspense fallback={<LoadingFallback />}>
|
|
41
|
+
<PrettyCodeClient {...props} />
|
|
42
|
+
</Suspense>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default PrettyCode;
|
|
47
|
+
export type { Language };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# VideoPlayer Refactoring Plan
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The VideoPlayer is already reasonably well-organized with a `providers/` subfolder. This refactoring focuses on incremental improvements rather than major restructuring.
|
|
6
|
+
|
|
7
|
+
**Total: 2,024 lines across 10 files**
|
|
8
|
+
|
|
9
|
+
## Current Structure (Before)
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
VideoPlayer/
|
|
13
|
+
├── index.ts (68 lines) # Public exports
|
|
14
|
+
├── types.ts (369 lines) # All types + helper functions ⚠️
|
|
15
|
+
├── VideoPlayer.tsx (202 lines) # Main orchestrator
|
|
16
|
+
├── VideoPlayerContext.tsx (125 lines) # Streaming context
|
|
17
|
+
├── VideoControls.tsx (139 lines) # Vidstack controls
|
|
18
|
+
├── VideoErrorFallback.tsx (174 lines) # Error UI
|
|
19
|
+
├── README.md
|
|
20
|
+
└── providers/
|
|
21
|
+
├── index.ts (8 lines)
|
|
22
|
+
├── VidstackProvider.tsx (332 lines) # YouTube/Vimeo/HLS/DASH
|
|
23
|
+
├── NativeProvider.tsx (206 lines) # HTML5 <video>
|
|
24
|
+
└── StreamProvider.tsx (401 lines) # HTTP Range + Blob ⚠️
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Issues Identified:**
|
|
28
|
+
1. `types.ts` (369 lines) - Contains types AND helper functions
|
|
29
|
+
2. `StreamProvider.tsx` (401 lines) - Largest file, multiple concerns
|
|
30
|
+
3. Position caching logic duplicated in VidstackProvider & StreamProvider
|
|
31
|
+
4. No dedicated hooks/ folder
|
|
32
|
+
|
|
33
|
+
## Target Structure (After)
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
VideoPlayer/
|
|
37
|
+
├── index.ts # Public API
|
|
38
|
+
├── README.md
|
|
39
|
+
├── types/
|
|
40
|
+
│ ├── index.ts # Re-exports all types
|
|
41
|
+
│ ├── sources.ts # Source type definitions
|
|
42
|
+
│ ├── player.ts # Player props and config types
|
|
43
|
+
│ └── provider.ts # Provider-specific types
|
|
44
|
+
├── hooks/
|
|
45
|
+
│ ├── index.ts
|
|
46
|
+
│ └── useVideoPositionCache.ts # Extracted caching logic
|
|
47
|
+
├── utils/
|
|
48
|
+
│ ├── index.ts
|
|
49
|
+
│ ├── resolvers.ts # resolvePlayerMode, resolveFileSource
|
|
50
|
+
│ └── stream.ts # Stream URL generation helpers
|
|
51
|
+
├── components/
|
|
52
|
+
│ ├── index.ts
|
|
53
|
+
│ ├── VideoPlayer.tsx # Main component
|
|
54
|
+
│ ├── VideoControls.tsx # Vidstack controls
|
|
55
|
+
│ └── VideoErrorFallback.tsx # Error UI
|
|
56
|
+
├── context/
|
|
57
|
+
│ ├── index.ts
|
|
58
|
+
│ └── VideoPlayerContext.tsx
|
|
59
|
+
└── providers/
|
|
60
|
+
├── index.ts
|
|
61
|
+
├── VidstackProvider.tsx
|
|
62
|
+
├── NativeProvider.tsx
|
|
63
|
+
└── StreamProvider.tsx
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Benefits
|
|
67
|
+
|
|
68
|
+
1. **DRY Principle** - Extract duplicated position caching logic
|
|
69
|
+
2. **Separation of Concerns** - Types split by domain
|
|
70
|
+
3. **Consistent Structure** - Matches AudioPlayer/ImageViewer patterns
|
|
71
|
+
4. **Maintainability** - Easier to find and modify specific functionality
|
|
72
|
+
5. **Testability** - Hooks and utils can be unit tested
|
|
73
|
+
|
|
74
|
+
## Execution Phases
|
|
75
|
+
|
|
76
|
+
| Phase | Description | Files |
|
|
77
|
+
|-------|-------------|-------|
|
|
78
|
+
| 1 | Create folder structure | types/, hooks/, utils/, components/, context/ |
|
|
79
|
+
| 2 | Split types | sources.ts, player.ts, provider.ts |
|
|
80
|
+
| 3 | Extract utils | resolvers.ts, stream.ts |
|
|
81
|
+
| 4 | Extract hooks | useVideoPositionCache.ts |
|
|
82
|
+
| 5 | Move components | VideoPlayer.tsx, VideoControls.tsx, VideoErrorFallback.tsx |
|
|
83
|
+
| 6 | Move context | VideoPlayerContext.tsx |
|
|
84
|
+
| 7 | Update exports | index.ts |
|
|
85
|
+
| 8 | Cleanup and verify | Delete old files, run pnpm check |
|
|
86
|
+
|
|
87
|
+
## Risk Assessment
|
|
88
|
+
|
|
89
|
+
- **Low Risk**: Incremental changes, no logic modifications
|
|
90
|
+
- **Testing**: Run `pnpm check` after each phase
|
|
91
|
+
- **Providers**: Already well-organized, minimal changes needed
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# Phase 1: Types Split
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Split the 369-line `types.ts` into domain-specific files and move helper functions to utils.
|
|
6
|
+
|
|
7
|
+
## Current Structure
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
// types.ts (369 lines)
|
|
11
|
+
// Contains:
|
|
12
|
+
// 1. Source types (UrlSource, YouTubeSource, VimeoSource, HLSSource, etc.)
|
|
13
|
+
// 2. Player types (PlayerMode, AspectRatioValue, VideoPlayerProps, etc.)
|
|
14
|
+
// 3. Provider types (VidstackProviderProps, NativeProviderProps, etc.)
|
|
15
|
+
// 4. Helper functions (resolvePlayerMode, resolveFileSource, isSimpleStreamSource)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Target Files
|
|
19
|
+
|
|
20
|
+
### types/sources.ts (~120 lines)
|
|
21
|
+
|
|
22
|
+
All source type definitions:
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
/**
|
|
26
|
+
* Video source type definitions
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
// URL source (direct video URL)
|
|
30
|
+
export interface UrlSource {
|
|
31
|
+
type: 'url';
|
|
32
|
+
url: string;
|
|
33
|
+
mimeType?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// YouTube embed
|
|
37
|
+
export interface YouTubeSource {
|
|
38
|
+
type: 'youtube';
|
|
39
|
+
videoId: string;
|
|
40
|
+
startTime?: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Vimeo embed
|
|
44
|
+
export interface VimeoSource {
|
|
45
|
+
type: 'vimeo';
|
|
46
|
+
videoId: string;
|
|
47
|
+
startTime?: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// HLS streaming
|
|
51
|
+
export interface HLSSource {
|
|
52
|
+
type: 'hls';
|
|
53
|
+
url: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// DASH streaming
|
|
57
|
+
export interface DASHSource {
|
|
58
|
+
type: 'dash';
|
|
59
|
+
url: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// HTTP Range streaming with auth
|
|
63
|
+
export interface StreamSource {
|
|
64
|
+
type: 'stream';
|
|
65
|
+
streamKey: string;
|
|
66
|
+
fileName: string;
|
|
67
|
+
fileSize?: number;
|
|
68
|
+
mimeType?: string;
|
|
69
|
+
getStreamUrl: (streamKey: string) => Promise<string>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Simple stream (resolved via context)
|
|
73
|
+
export interface SimpleStreamSource {
|
|
74
|
+
type: 'stream';
|
|
75
|
+
streamKey: string;
|
|
76
|
+
fileName: string;
|
|
77
|
+
fileSize?: number;
|
|
78
|
+
mimeType?: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Blob (ArrayBuffer)
|
|
82
|
+
export interface BlobSource {
|
|
83
|
+
type: 'blob';
|
|
84
|
+
data: ArrayBuffer;
|
|
85
|
+
mimeType?: string;
|
|
86
|
+
fileName?: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Data URL (base64)
|
|
90
|
+
export interface DataUrlSource {
|
|
91
|
+
type: 'data-url';
|
|
92
|
+
dataUrl: string;
|
|
93
|
+
mimeType?: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Union of all sources
|
|
97
|
+
export type VideoSourceUnion =
|
|
98
|
+
| UrlSource
|
|
99
|
+
| YouTubeSource
|
|
100
|
+
| VimeoSource
|
|
101
|
+
| HLSSource
|
|
102
|
+
| DASHSource
|
|
103
|
+
| StreamSource
|
|
104
|
+
| BlobSource
|
|
105
|
+
| DataUrlSource;
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### types/player.ts (~100 lines)
|
|
109
|
+
|
|
110
|
+
Player configuration and main component types:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
/**
|
|
114
|
+
* Player configuration types
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
import type { ReactNode, CSSProperties } from 'react';
|
|
118
|
+
import type { VideoSourceUnion } from './sources';
|
|
119
|
+
|
|
120
|
+
// Player mode
|
|
121
|
+
export type PlayerMode = 'auto' | 'vidstack' | 'native' | 'streaming';
|
|
122
|
+
|
|
123
|
+
// Aspect ratio
|
|
124
|
+
export type AspectRatioValue = number | 'auto' | 'fill';
|
|
125
|
+
|
|
126
|
+
// Common settings
|
|
127
|
+
export interface CommonPlayerSettings {
|
|
128
|
+
autoPlay?: boolean;
|
|
129
|
+
muted?: boolean;
|
|
130
|
+
loop?: boolean;
|
|
131
|
+
playsInline?: boolean;
|
|
132
|
+
controls?: boolean;
|
|
133
|
+
preload?: 'none' | 'metadata' | 'auto';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Common events
|
|
137
|
+
export interface CommonPlayerEvents {
|
|
138
|
+
onPlay?: () => void;
|
|
139
|
+
onPause?: () => void;
|
|
140
|
+
onEnded?: () => void;
|
|
141
|
+
onTimeUpdate?: (currentTime: number) => void;
|
|
142
|
+
onError?: (error: Error) => void;
|
|
143
|
+
onLoadStart?: () => void;
|
|
144
|
+
onCanPlay?: () => void;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Error fallback props
|
|
148
|
+
export interface ErrorFallbackProps {
|
|
149
|
+
error: Error | null;
|
|
150
|
+
source: VideoSourceUnion;
|
|
151
|
+
retry?: () => void;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Main component props
|
|
155
|
+
export interface VideoPlayerProps extends CommonPlayerSettings, CommonPlayerEvents {
|
|
156
|
+
source: VideoSourceUnion;
|
|
157
|
+
mode?: PlayerMode;
|
|
158
|
+
aspectRatio?: AspectRatioValue;
|
|
159
|
+
poster?: string;
|
|
160
|
+
className?: string;
|
|
161
|
+
style?: CSSProperties;
|
|
162
|
+
errorFallback?: (props: ErrorFallbackProps) => ReactNode;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Ref API
|
|
166
|
+
export interface VideoPlayerRef {
|
|
167
|
+
play: () => Promise<void>;
|
|
168
|
+
pause: () => void;
|
|
169
|
+
seek: (time: number) => void;
|
|
170
|
+
setVolume: (volume: number) => void;
|
|
171
|
+
setMuted: (muted: boolean) => void;
|
|
172
|
+
requestFullscreen: () => Promise<void>;
|
|
173
|
+
exitFullscreen: () => Promise<void>;
|
|
174
|
+
readonly currentTime: number;
|
|
175
|
+
readonly duration: number;
|
|
176
|
+
readonly paused: boolean;
|
|
177
|
+
readonly muted: boolean;
|
|
178
|
+
readonly volume: number;
|
|
179
|
+
readonly isFullscreen: boolean;
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### types/provider.ts (~80 lines)
|
|
184
|
+
|
|
185
|
+
Provider-specific types:
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
/**
|
|
189
|
+
* Provider-specific types
|
|
190
|
+
*/
|
|
191
|
+
|
|
192
|
+
import type { ReactNode } from 'react';
|
|
193
|
+
import type { VideoSourceUnion, StreamSource, BlobSource, DataUrlSource } from './sources';
|
|
194
|
+
import type { CommonPlayerSettings, CommonPlayerEvents, AspectRatioValue, ErrorFallbackProps } from './player';
|
|
195
|
+
|
|
196
|
+
// Vidstack provider props
|
|
197
|
+
export interface VidstackProviderProps extends CommonPlayerSettings, CommonPlayerEvents {
|
|
198
|
+
source: VideoSourceUnion;
|
|
199
|
+
aspectRatio?: AspectRatioValue;
|
|
200
|
+
poster?: string;
|
|
201
|
+
className?: string;
|
|
202
|
+
errorFallback?: (props: ErrorFallbackProps) => ReactNode;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Native provider props
|
|
206
|
+
export interface NativeProviderProps extends CommonPlayerSettings, CommonPlayerEvents {
|
|
207
|
+
source: VideoSourceUnion;
|
|
208
|
+
aspectRatio?: AspectRatioValue;
|
|
209
|
+
poster?: string;
|
|
210
|
+
className?: string;
|
|
211
|
+
disableContextMenu?: boolean;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Stream provider props
|
|
215
|
+
export interface StreamProviderProps extends CommonPlayerSettings, CommonPlayerEvents {
|
|
216
|
+
source: StreamSource | BlobSource | DataUrlSource;
|
|
217
|
+
aspectRatio?: AspectRatioValue;
|
|
218
|
+
poster?: string;
|
|
219
|
+
className?: string;
|
|
220
|
+
errorFallback?: (props: ErrorFallbackProps) => ReactNode;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// File source resolution options
|
|
224
|
+
export interface ResolveFileSourceOptions {
|
|
225
|
+
fileName: string;
|
|
226
|
+
content: string | ArrayBuffer;
|
|
227
|
+
mimeType?: string;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Context value
|
|
231
|
+
export interface VideoPlayerContextValue {
|
|
232
|
+
getStreamUrl?: (streamKey: string) => Promise<string>;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export interface VideoPlayerProviderProps {
|
|
236
|
+
getStreamUrl: (streamKey: string) => Promise<string>;
|
|
237
|
+
children: ReactNode;
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### types/index.ts
|
|
242
|
+
|
|
243
|
+
Re-export all types:
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
/**
|
|
247
|
+
* VideoPlayer types - Public API
|
|
248
|
+
*/
|
|
249
|
+
|
|
250
|
+
// Source types
|
|
251
|
+
export type {
|
|
252
|
+
UrlSource,
|
|
253
|
+
YouTubeSource,
|
|
254
|
+
VimeoSource,
|
|
255
|
+
HLSSource,
|
|
256
|
+
DASHSource,
|
|
257
|
+
StreamSource,
|
|
258
|
+
SimpleStreamSource,
|
|
259
|
+
BlobSource,
|
|
260
|
+
DataUrlSource,
|
|
261
|
+
VideoSourceUnion,
|
|
262
|
+
} from './sources';
|
|
263
|
+
|
|
264
|
+
// Player types
|
|
265
|
+
export type {
|
|
266
|
+
PlayerMode,
|
|
267
|
+
AspectRatioValue,
|
|
268
|
+
CommonPlayerSettings,
|
|
269
|
+
CommonPlayerEvents,
|
|
270
|
+
ErrorFallbackProps,
|
|
271
|
+
VideoPlayerProps,
|
|
272
|
+
VideoPlayerRef,
|
|
273
|
+
} from './player';
|
|
274
|
+
|
|
275
|
+
// Provider types
|
|
276
|
+
export type {
|
|
277
|
+
VidstackProviderProps,
|
|
278
|
+
NativeProviderProps,
|
|
279
|
+
StreamProviderProps,
|
|
280
|
+
ResolveFileSourceOptions,
|
|
281
|
+
VideoPlayerContextValue,
|
|
282
|
+
VideoPlayerProviderProps,
|
|
283
|
+
} from './provider';
|
|
284
|
+
```
|