@djangocfg/ui-nextjs 2.1.90 → 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 (161) hide show
  1. package/README.md +6 -15
  2. package/package.json +6 -25
  3. package/src/blocks/SplitHero/SplitHeroMedia.tsx +1 -1
  4. package/src/components/index.ts +0 -40
  5. package/src/hooks/index.ts +0 -6
  6. package/src/index.ts +2 -11
  7. package/src/components/button-download.tsx +0 -277
  8. package/src/components/markdown/MarkdownMessage.tsx +0 -340
  9. package/src/components/markdown/index.ts +0 -5
  10. package/src/components/menubar.tsx +0 -275
  11. package/src/components/multi-select-pro/async.tsx +0 -598
  12. package/src/components/multi-select-pro/helpers.tsx +0 -84
  13. package/src/components/multi-select-pro/index.tsx +0 -612
  14. package/src/components/navigation-menu.tsx +0 -154
  15. package/src/components/otp/index.tsx +0 -197
  16. package/src/components/otp/types.ts +0 -133
  17. package/src/components/otp/use-otp-input.ts +0 -225
  18. package/src/components/phone-input.tsx +0 -277
  19. package/src/components/sonner.tsx +0 -32
  20. package/src/hooks/useLocalStorage.ts +0 -300
  21. package/src/hooks/useSessionStorage.ts +0 -290
  22. package/src/lib/index.ts +0 -5
  23. package/src/lib/logger/index.ts +0 -10
  24. package/src/lib/logger/logStore.ts +0 -122
  25. package/src/lib/logger/logger.ts +0 -175
  26. package/src/lib/logger/types.ts +0 -82
  27. package/src/stores/index.ts +0 -8
  28. package/src/stores/mediaCache.ts +0 -534
  29. package/src/tools/AudioPlayer/README.md +0 -206
  30. package/src/tools/AudioPlayer/components/HybridAudioPlayer.tsx +0 -216
  31. package/src/tools/AudioPlayer/components/HybridSimplePlayer.tsx +0 -280
  32. package/src/tools/AudioPlayer/components/HybridWaveform.tsx +0 -279
  33. package/src/tools/AudioPlayer/components/ReactiveCover/AudioReactiveCover.tsx +0 -149
  34. package/src/tools/AudioPlayer/components/ReactiveCover/effects/GlowEffect.tsx +0 -110
  35. package/src/tools/AudioPlayer/components/ReactiveCover/effects/MeshEffect.tsx +0 -58
  36. package/src/tools/AudioPlayer/components/ReactiveCover/effects/OrbsEffect.tsx +0 -45
  37. package/src/tools/AudioPlayer/components/ReactiveCover/effects/SpotlightEffect.tsx +0 -82
  38. package/src/tools/AudioPlayer/components/ReactiveCover/effects/index.ts +0 -8
  39. package/src/tools/AudioPlayer/components/ReactiveCover/index.ts +0 -6
  40. package/src/tools/AudioPlayer/components/index.ts +0 -22
  41. package/src/tools/AudioPlayer/context/HybridAudioProvider.tsx +0 -158
  42. package/src/tools/AudioPlayer/context/index.ts +0 -16
  43. package/src/tools/AudioPlayer/effects/index.ts +0 -412
  44. package/src/tools/AudioPlayer/hooks/index.ts +0 -35
  45. package/src/tools/AudioPlayer/hooks/useHybridAudio.ts +0 -387
  46. package/src/tools/AudioPlayer/hooks/useHybridAudioAnalysis.ts +0 -95
  47. package/src/tools/AudioPlayer/hooks/useVisualization.tsx +0 -207
  48. package/src/tools/AudioPlayer/index.ts +0 -133
  49. package/src/tools/AudioPlayer/types/effects.ts +0 -73
  50. package/src/tools/AudioPlayer/types/index.ts +0 -27
  51. package/src/tools/AudioPlayer/utils/debug.ts +0 -14
  52. package/src/tools/AudioPlayer/utils/formatTime.ts +0 -10
  53. package/src/tools/AudioPlayer/utils/index.ts +0 -6
  54. package/src/tools/ImageViewer/@refactoring/00-PLAN.md +0 -71
  55. package/src/tools/ImageViewer/@refactoring/01-TYPES.md +0 -121
  56. package/src/tools/ImageViewer/@refactoring/02-UTILS.md +0 -143
  57. package/src/tools/ImageViewer/@refactoring/03-HOOKS.md +0 -261
  58. package/src/tools/ImageViewer/@refactoring/04-COMPONENTS.md +0 -427
  59. package/src/tools/ImageViewer/@refactoring/05-EXECUTION-CHECKLIST.md +0 -126
  60. package/src/tools/ImageViewer/README.md +0 -200
  61. package/src/tools/ImageViewer/components/ImageInfo.tsx +0 -44
  62. package/src/tools/ImageViewer/components/ImageToolbar.tsx +0 -150
  63. package/src/tools/ImageViewer/components/ImageViewer.tsx +0 -241
  64. package/src/tools/ImageViewer/components/index.ts +0 -7
  65. package/src/tools/ImageViewer/hooks/index.ts +0 -9
  66. package/src/tools/ImageViewer/hooks/useImageLoading.ts +0 -204
  67. package/src/tools/ImageViewer/hooks/useImageTransform.ts +0 -101
  68. package/src/tools/ImageViewer/index.ts +0 -60
  69. package/src/tools/ImageViewer/types.ts +0 -81
  70. package/src/tools/ImageViewer/utils/constants.ts +0 -59
  71. package/src/tools/ImageViewer/utils/debug.ts +0 -14
  72. package/src/tools/ImageViewer/utils/index.ts +0 -17
  73. package/src/tools/ImageViewer/utils/lqip.ts +0 -47
  74. package/src/tools/JsonForm/JsonSchemaForm.tsx +0 -197
  75. package/src/tools/JsonForm/examples/BotConfigExample.tsx +0 -249
  76. package/src/tools/JsonForm/examples/RealBotConfigExample.tsx +0 -161
  77. package/src/tools/JsonForm/index.ts +0 -46
  78. package/src/tools/JsonForm/templates/ArrayFieldItemTemplate.tsx +0 -47
  79. package/src/tools/JsonForm/templates/ArrayFieldTemplate.tsx +0 -74
  80. package/src/tools/JsonForm/templates/BaseInputTemplate.tsx +0 -107
  81. package/src/tools/JsonForm/templates/ErrorListTemplate.tsx +0 -35
  82. package/src/tools/JsonForm/templates/FieldTemplate.tsx +0 -62
  83. package/src/tools/JsonForm/templates/ObjectFieldTemplate.tsx +0 -116
  84. package/src/tools/JsonForm/templates/index.ts +0 -12
  85. package/src/tools/JsonForm/types.ts +0 -83
  86. package/src/tools/JsonForm/utils.ts +0 -213
  87. package/src/tools/JsonForm/widgets/CheckboxWidget.tsx +0 -37
  88. package/src/tools/JsonForm/widgets/ColorWidget.tsx +0 -219
  89. package/src/tools/JsonForm/widgets/NumberWidget.tsx +0 -89
  90. package/src/tools/JsonForm/widgets/SelectWidget.tsx +0 -97
  91. package/src/tools/JsonForm/widgets/SliderWidget.tsx +0 -148
  92. package/src/tools/JsonForm/widgets/SwitchWidget.tsx +0 -35
  93. package/src/tools/JsonForm/widgets/TextWidget.tsx +0 -96
  94. package/src/tools/JsonForm/widgets/index.ts +0 -14
  95. package/src/tools/JsonTree/index.tsx +0 -243
  96. package/src/tools/LottiePlayer/LottiePlayer.client.tsx +0 -213
  97. package/src/tools/LottiePlayer/index.tsx +0 -55
  98. package/src/tools/LottiePlayer/types.ts +0 -108
  99. package/src/tools/LottiePlayer/useLottie.ts +0 -164
  100. package/src/tools/Mermaid/Mermaid.client.tsx +0 -82
  101. package/src/tools/Mermaid/components/MermaidCodeViewer.tsx +0 -95
  102. package/src/tools/Mermaid/components/MermaidFullscreenModal.tsx +0 -103
  103. package/src/tools/Mermaid/hooks/index.ts +0 -4
  104. package/src/tools/Mermaid/hooks/useMermaidCleanup.ts +0 -73
  105. package/src/tools/Mermaid/hooks/useMermaidFullscreen.ts +0 -46
  106. package/src/tools/Mermaid/hooks/useMermaidRenderer.ts +0 -226
  107. package/src/tools/Mermaid/hooks/useMermaidValidation.ts +0 -29
  108. package/src/tools/Mermaid/index.tsx +0 -41
  109. package/src/tools/Mermaid/utils/mermaid-helpers.ts +0 -33
  110. package/src/tools/OpenapiViewer/components/EndpointInfo.tsx +0 -149
  111. package/src/tools/OpenapiViewer/components/EndpointsLibrary.tsx +0 -263
  112. package/src/tools/OpenapiViewer/components/PlaygroundLayout.tsx +0 -125
  113. package/src/tools/OpenapiViewer/components/PlaygroundStepper.tsx +0 -100
  114. package/src/tools/OpenapiViewer/components/RequestBuilder.tsx +0 -157
  115. package/src/tools/OpenapiViewer/components/RequestParametersForm.tsx +0 -253
  116. package/src/tools/OpenapiViewer/components/ResponseViewer.tsx +0 -173
  117. package/src/tools/OpenapiViewer/components/VersionSelector.tsx +0 -68
  118. package/src/tools/OpenapiViewer/components/index.ts +0 -14
  119. package/src/tools/OpenapiViewer/constants.ts +0 -39
  120. package/src/tools/OpenapiViewer/context/PlaygroundContext.tsx +0 -337
  121. package/src/tools/OpenapiViewer/hooks/index.ts +0 -8
  122. package/src/tools/OpenapiViewer/hooks/useMobile.ts +0 -10
  123. package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +0 -199
  124. package/src/tools/OpenapiViewer/index.tsx +0 -38
  125. package/src/tools/OpenapiViewer/types.ts +0 -151
  126. package/src/tools/OpenapiViewer/utils/apiKeyManager.ts +0 -149
  127. package/src/tools/OpenapiViewer/utils/formatters.ts +0 -71
  128. package/src/tools/OpenapiViewer/utils/index.ts +0 -9
  129. package/src/tools/OpenapiViewer/utils/versionManager.ts +0 -161
  130. package/src/tools/PrettyCode/PrettyCode.client.tsx +0 -208
  131. package/src/tools/PrettyCode/index.tsx +0 -45
  132. package/src/tools/VideoPlayer/@refactoring/00-PLAN.md +0 -91
  133. package/src/tools/VideoPlayer/@refactoring/01-TYPES.md +0 -284
  134. package/src/tools/VideoPlayer/@refactoring/02-UTILS.md +0 -141
  135. package/src/tools/VideoPlayer/@refactoring/03-HOOKS.md +0 -178
  136. package/src/tools/VideoPlayer/@refactoring/04-COMPONENTS.md +0 -95
  137. package/src/tools/VideoPlayer/@refactoring/05-EXECUTION-CHECKLIST.md +0 -139
  138. package/src/tools/VideoPlayer/README.md +0 -264
  139. package/src/tools/VideoPlayer/components/VideoControls.tsx +0 -138
  140. package/src/tools/VideoPlayer/components/VideoErrorFallback.tsx +0 -174
  141. package/src/tools/VideoPlayer/components/VideoPlayer.tsx +0 -201
  142. package/src/tools/VideoPlayer/components/index.ts +0 -14
  143. package/src/tools/VideoPlayer/context/VideoPlayerContext.tsx +0 -52
  144. package/src/tools/VideoPlayer/context/index.ts +0 -8
  145. package/src/tools/VideoPlayer/hooks/index.ts +0 -12
  146. package/src/tools/VideoPlayer/hooks/useVideoPlayerSettings.ts +0 -70
  147. package/src/tools/VideoPlayer/hooks/useVideoPositionCache.ts +0 -116
  148. package/src/tools/VideoPlayer/index.ts +0 -77
  149. package/src/tools/VideoPlayer/providers/NativeProvider.tsx +0 -284
  150. package/src/tools/VideoPlayer/providers/StreamProvider.tsx +0 -505
  151. package/src/tools/VideoPlayer/providers/VidstackProvider.tsx +0 -400
  152. package/src/tools/VideoPlayer/providers/index.ts +0 -8
  153. package/src/tools/VideoPlayer/types/index.ts +0 -38
  154. package/src/tools/VideoPlayer/types/player.ts +0 -116
  155. package/src/tools/VideoPlayer/types/provider.ts +0 -93
  156. package/src/tools/VideoPlayer/types/sources.ts +0 -97
  157. package/src/tools/VideoPlayer/utils/debug.ts +0 -14
  158. package/src/tools/VideoPlayer/utils/fileSource.ts +0 -78
  159. package/src/tools/VideoPlayer/utils/index.ts +0 -12
  160. package/src/tools/VideoPlayer/utils/resolvers.ts +0 -75
  161. package/src/tools/index.ts +0 -170
@@ -1,108 +0,0 @@
1
- /**
2
- * LottiePlayer Types
3
- *
4
- * Type definitions for the Lottie animation player component
5
- */
6
-
7
- export type LottieSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
8
-
9
- export type LottieSpeed = 0.5 | 1 | 1.5 | 2;
10
-
11
- export type LottieDirection = 1 | -1;
12
-
13
- export interface LottiePlayerProps {
14
- /**
15
- * Animation data (JSON object) or URL to load from
16
- */
17
- src: string | object;
18
-
19
- /**
20
- * Size preset for the player
21
- * @default 'md'
22
- */
23
- size?: LottieSize;
24
-
25
- /**
26
- * Custom width (overrides size preset)
27
- */
28
- width?: number | string;
29
-
30
- /**
31
- * Custom height (overrides size preset)
32
- */
33
- height?: number | string;
34
-
35
- /**
36
- * Autoplay animation
37
- * @default true
38
- */
39
- autoplay?: boolean;
40
-
41
- /**
42
- * Loop animation
43
- * @default true
44
- */
45
- loop?: boolean | number;
46
-
47
- /**
48
- * Playback speed
49
- * @default 1
50
- */
51
- speed?: LottieSpeed;
52
-
53
- /**
54
- * Direction (1 = forward, -1 = reverse)
55
- * @default 1
56
- */
57
- direction?: LottieDirection;
58
-
59
- /**
60
- * Show playback controls
61
- * @default false
62
- */
63
- controls?: boolean;
64
-
65
- /**
66
- * Background color
67
- */
68
- background?: string;
69
-
70
- /**
71
- * CSS class name
72
- */
73
- className?: string;
74
-
75
- /**
76
- * Show loading state
77
- * @default true
78
- */
79
- showLoading?: boolean;
80
-
81
- /**
82
- * Callback when animation completes
83
- */
84
- onComplete?: () => void;
85
-
86
- /**
87
- * Callback when animation loads
88
- */
89
- onLoad?: () => void;
90
-
91
- /**
92
- * Callback on error
93
- */
94
- onError?: (error: Error) => void;
95
- }
96
-
97
- export interface LottieAnimationData {
98
- v: string;
99
- fr: number;
100
- ip: number;
101
- op: number;
102
- w: number;
103
- h: number;
104
- nm: string;
105
- ddd: number;
106
- assets: any[];
107
- layers: any[];
108
- }
@@ -1,164 +0,0 @@
1
- /**
2
- * useLottie Hook
3
- *
4
- * Hook for loading and managing Lottie animation data
5
- */
6
-
7
- 'use client';
8
-
9
- import { useEffect, useRef, useState } from 'react';
10
-
11
- import { LottieAnimationData } from './types';
12
-
13
- export interface UseLottieOptions {
14
- /**
15
- * Animation data (JSON object) or URL to load from
16
- */
17
- src: string | object;
18
-
19
- /**
20
- * Enable caching of loaded animations
21
- * @default true
22
- */
23
- cache?: boolean;
24
- }
25
-
26
- export interface UseLottieReturn {
27
- /**
28
- * Loaded animation data
29
- */
30
- animationData: object | null;
31
-
32
- /**
33
- * Loading state
34
- */
35
- isLoading: boolean;
36
-
37
- /**
38
- * Error state
39
- */
40
- error: Error | null;
41
-
42
- /**
43
- * Retry loading the animation
44
- */
45
- retry: () => void;
46
- }
47
-
48
- // Simple in-memory cache for loaded animations
49
- const animationCache = new Map<string, object>();
50
-
51
- /**
52
- * Hook for loading Lottie animations from URLs or objects
53
- *
54
- * Features:
55
- * - Loads animations from URLs or accepts animation objects directly
56
- * - Caching support to prevent re-fetching the same animation
57
- * - Error handling with retry capability
58
- * - Loading states
59
- *
60
- * Usage:
61
- * ```tsx
62
- * const { animationData, isLoading, error, retry } = useLottie({
63
- * src: 'https://example.com/animation.json'
64
- * });
65
- *
66
- * if (isLoading) return <div>Loading...</div>;
67
- * if (error) return <div>Error: {error.message} <button onClick={retry}>Retry</button></div>;
68
- * if (!animationData) return null;
69
- *
70
- * return <LottiePlayer animationData={animationData} />;
71
- * ```
72
- */
73
- export function useLottie(options: UseLottieOptions): UseLottieReturn {
74
- const { src, cache = true } = options;
75
-
76
- const [animationData, setAnimationData] = useState<object | null>(null);
77
- const [isLoading, setIsLoading] = useState(false);
78
- const [error, setError] = useState<Error | null>(null);
79
- const [retryCount, setRetryCount] = useState(0);
80
-
81
- // Track if component is mounted to prevent state updates on unmounted component
82
- const isMountedRef = useRef(true);
83
-
84
- useEffect(() => {
85
- isMountedRef.current = true;
86
- return () => {
87
- isMountedRef.current = false;
88
- };
89
- }, []);
90
-
91
- useEffect(() => {
92
- // If src is already an object, use it directly
93
- if (typeof src === 'object' && src !== null) {
94
- setAnimationData(src);
95
- setIsLoading(false);
96
- setError(null);
97
- return;
98
- }
99
-
100
- // If src is a string (URL), fetch it
101
- if (typeof src === 'string') {
102
- const loadAnimation = async () => {
103
- // Check cache first
104
- if (cache && animationCache.has(src)) {
105
- if (isMountedRef.current) {
106
- setAnimationData(animationCache.get(src)!);
107
- setIsLoading(false);
108
- setError(null);
109
- }
110
- return;
111
- }
112
-
113
- // Load from URL
114
- if (isMountedRef.current) {
115
- setIsLoading(true);
116
- setError(null);
117
- }
118
-
119
- try {
120
- const response = await fetch(src);
121
-
122
- if (!response.ok) {
123
- throw new Error(`Failed to load animation: ${response.status} ${response.statusText}`);
124
- }
125
-
126
- const data = await response.json();
127
-
128
- // Validate that it's a valid Lottie animation
129
- if (!data || typeof data !== 'object' || !data.v || !data.layers) {
130
- throw new Error('Invalid Lottie animation data');
131
- }
132
-
133
- // Cache the loaded animation
134
- if (cache) {
135
- animationCache.set(src, data);
136
- }
137
-
138
- if (isMountedRef.current) {
139
- setAnimationData(data);
140
- setIsLoading(false);
141
- }
142
- } catch (err) {
143
- if (isMountedRef.current) {
144
- setError(err instanceof Error ? err : new Error('Failed to load animation'));
145
- setIsLoading(false);
146
- }
147
- }
148
- };
149
-
150
- loadAnimation();
151
- }
152
- }, [src, cache, retryCount]);
153
-
154
- const retry = () => {
155
- setRetryCount((prev) => prev + 1);
156
- };
157
-
158
- return {
159
- animationData,
160
- isLoading,
161
- error,
162
- retry,
163
- };
164
- }
@@ -1,82 +0,0 @@
1
- 'use client';
2
-
3
- import React from 'react';
4
-
5
- import { useResolvedTheme } from '../../hooks/useResolvedTheme';
6
- import { MermaidFullscreenModal } from './components/MermaidFullscreenModal';
7
- import { useMermaidFullscreen } from './hooks/useMermaidFullscreen';
8
- import { useMermaidRenderer } from './hooks/useMermaidRenderer';
9
-
10
- interface MermaidProps {
11
- chart: string;
12
- className?: string;
13
- isCompact?: boolean;
14
- }
15
-
16
- const Mermaid: React.FC<MermaidProps> = ({ chart, className = '', isCompact = false }) => {
17
- const theme = useResolvedTheme();
18
-
19
- // Rendering logic
20
- const { mermaidRef, svgContent, isVertical, isRendering } = useMermaidRenderer({
21
- chart,
22
- theme,
23
- isCompact,
24
- });
25
-
26
- // Fullscreen modal logic
27
- const {
28
- isFullscreen,
29
- fullscreenRef,
30
- openFullscreen,
31
- closeFullscreen,
32
- handleBackdropClick,
33
- } = useMermaidFullscreen();
34
-
35
- const handleClick = () => {
36
- if (svgContent) {
37
- openFullscreen();
38
- }
39
- };
40
-
41
- return (
42
- <>
43
- <div
44
- className={`relative bg-card rounded-sm border border-border overflow-hidden cursor-pointer hover:shadow-sm transition-shadow ${className}`}
45
- onClick={handleClick}
46
- >
47
- <div className="p-4 border-b border-border bg-muted/50">
48
- <h6 className="text-sm font-semibold text-foreground">Diagram</h6>
49
- <p className="text-xs text-muted-foreground mt-1">Click to view fullscreen</p>
50
- </div>
51
- <div className="relative p-4 overflow-hidden">
52
- <div
53
- ref={mermaidRef}
54
- className="flex justify-center items-center min-h-[200px]"
55
- style={{ isolation: 'isolate' }}
56
- />
57
- {isRendering && (
58
- <div className="absolute inset-0 flex items-center justify-center bg-background/50 backdrop-blur-sm">
59
- <div className="flex flex-col items-center gap-2">
60
- <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
61
- <p className="text-xs text-muted-foreground">Rendering diagram...</p>
62
- </div>
63
- </div>
64
- )}
65
- </div>
66
- </div>
67
-
68
- <MermaidFullscreenModal
69
- isOpen={isFullscreen}
70
- svgContent={svgContent}
71
- isVertical={isVertical}
72
- theme={theme}
73
- chart={chart}
74
- fullscreenRef={fullscreenRef}
75
- onClose={closeFullscreen}
76
- onBackdropClick={handleBackdropClick}
77
- />
78
- </>
79
- );
80
- };
81
-
82
- export default Mermaid;
@@ -1,95 +0,0 @@
1
- 'use client';
2
-
3
- import React, { useState } from 'react';
4
-
5
- interface MermaidCodeViewerProps {
6
- chart: string;
7
- renderPreview: () => React.ReactNode;
8
- }
9
-
10
- export const MermaidCodeViewer: React.FC<MermaidCodeViewerProps> = ({
11
- chart,
12
- renderPreview,
13
- }) => {
14
- const [activeTab, setActiveTab] = useState<'preview' | 'code'>('preview');
15
- const [copied, setCopied] = useState(false);
16
-
17
- const handleCopy = async () => {
18
- await navigator.clipboard.writeText(chart);
19
- setCopied(true);
20
- setTimeout(() => setCopied(false), 2000);
21
- };
22
-
23
- return (
24
- <div className="flex flex-col h-full">
25
- {/* Tabs */}
26
- <div className="flex items-center justify-between border-b border-border px-4">
27
- <div className="flex">
28
- <button
29
- onClick={() => setActiveTab('preview')}
30
- className={`px-4 py-3 text-sm font-medium transition-colors relative ${
31
- activeTab === 'preview'
32
- ? 'text-foreground'
33
- : 'text-muted-foreground hover:text-foreground'
34
- }`}
35
- >
36
- Preview
37
- {activeTab === 'preview' && (
38
- <div className="absolute bottom-0 left-0 right-0 h-0.5 bg-primary" />
39
- )}
40
- </button>
41
- <button
42
- onClick={() => setActiveTab('code')}
43
- className={`px-4 py-3 text-sm font-medium transition-colors relative ${
44
- activeTab === 'code'
45
- ? 'text-foreground'
46
- : 'text-muted-foreground hover:text-foreground'
47
- }`}
48
- >
49
- Code
50
- {activeTab === 'code' && (
51
- <div className="absolute bottom-0 left-0 right-0 h-0.5 bg-primary" />
52
- )}
53
- </button>
54
- </div>
55
-
56
- {/* Copy button - show only on Code tab */}
57
- {activeTab === 'code' && (
58
- <button
59
- onClick={handleCopy}
60
- className="flex items-center gap-2 px-3 py-1.5 text-xs font-medium bg-primary/10 hover:bg-primary/20 text-primary rounded transition-colors"
61
- >
62
- {copied ? (
63
- <>
64
- <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
65
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
66
- </svg>
67
- Copied!
68
- </>
69
- ) : (
70
- <>
71
- <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
72
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
73
- </svg>
74
- Copy
75
- </>
76
- )}
77
- </button>
78
- )}
79
- </div>
80
-
81
- {/* Content */}
82
- <div className="flex-1 overflow-auto">
83
- {activeTab === 'preview' ? (
84
- <div className="p-6 flex items-center justify-center min-h-full">
85
- {renderPreview()}
86
- </div>
87
- ) : (
88
- <pre className="p-6 text-sm font-mono text-foreground bg-muted/30 h-full overflow-auto">
89
- <code>{chart}</code>
90
- </pre>
91
- )}
92
- </div>
93
- </div>
94
- );
95
- };
@@ -1,103 +0,0 @@
1
- 'use client';
2
-
3
- import React, { useEffect } from 'react';
4
- import { createPortal } from 'react-dom';
5
-
6
- import { applyMermaidTextColors } from '../utils/mermaid-helpers';
7
- import { MermaidCodeViewer } from './MermaidCodeViewer';
8
-
9
- interface MermaidFullscreenModalProps {
10
- isOpen: boolean;
11
- svgContent: string;
12
- isVertical: boolean;
13
- theme: string;
14
- chart: string;
15
- fullscreenRef: React.RefObject<HTMLDivElement>;
16
- onClose: () => void;
17
- onBackdropClick: (e: React.MouseEvent) => void;
18
- }
19
-
20
- export const MermaidFullscreenModal: React.FC<MermaidFullscreenModalProps> = ({
21
- isOpen,
22
- svgContent,
23
- isVertical,
24
- theme,
25
- chart,
26
- fullscreenRef,
27
- onClose,
28
- onBackdropClick,
29
- }) => {
30
- // Apply text colors to fullscreen modal after render
31
- useEffect(() => {
32
- if (isOpen && fullscreenRef.current) {
33
- const getCSSVariable = (variable: string) => {
34
- if (typeof document === 'undefined') return '';
35
- const value = getComputedStyle(document.documentElement).getPropertyValue(variable).trim();
36
- return value ? `hsl(${value})` : '';
37
- };
38
-
39
- const textColor = theme === 'dark'
40
- ? getCSSVariable('--foreground') || 'hsl(0 0% 90%)'
41
- : getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)';
42
-
43
- applyMermaidTextColors(fullscreenRef.current, textColor);
44
-
45
- // Make SVG responsive
46
- const svgElement = fullscreenRef.current.querySelector('svg');
47
- if (svgElement) {
48
- svgElement.style.display = 'block';
49
- svgElement.style.height = 'auto';
50
- svgElement.style.maxWidth = '100%';
51
-
52
- // For vertical diagrams, limit width
53
- if (isVertical) {
54
- svgElement.style.maxWidth = '600px';
55
- svgElement.style.margin = '0 auto';
56
- }
57
- }
58
- }
59
- }, [isOpen, theme, isVertical, fullscreenRef]);
60
-
61
- if (!isOpen || typeof document === 'undefined') return null;
62
-
63
- return createPortal(
64
- <div
65
- className="fixed inset-0 z-9999 flex items-center justify-center p-4"
66
- style={{ backgroundColor: 'rgb(0 0 0 / 0.75)' }}
67
- onClick={onBackdropClick}
68
- >
69
- <div className={`relative bg-card rounded-sm shadow-xl max-h-[95vh] flex flex-col border border-border ${
70
- isVertical
71
- ? 'w-auto min-w-[400px] max-w-[600px]'
72
- : 'min-w-[600px] max-w-[90vw] w-auto'
73
- }`}>
74
- {/* Header */}
75
- <div className="flex items-center justify-between py-4 px-6 border-b border-border">
76
- <h3 className="text-sm font-medium text-foreground py-0 my-0">Diagram</h3>
77
- <button
78
- onClick={onClose}
79
- className="text-muted-foreground hover:text-foreground transition-colors"
80
- >
81
- <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
82
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
83
- </svg>
84
- </button>
85
- </div>
86
-
87
- {/* Content - Code Viewer with tabs */}
88
- <div className="flex-1 overflow-hidden">
89
- <MermaidCodeViewer
90
- chart={chart}
91
- renderPreview={() => (
92
- <div
93
- ref={fullscreenRef}
94
- dangerouslySetInnerHTML={{ __html: svgContent }}
95
- />
96
- )}
97
- />
98
- </div>
99
- </div>
100
- </div>,
101
- document.body
102
- );
103
- };
@@ -1,4 +0,0 @@
1
- export { useMermaidRenderer } from './useMermaidRenderer';
2
- export { useMermaidValidation } from './useMermaidValidation';
3
- export { useMermaidCleanup } from './useMermaidCleanup';
4
- export { useMermaidFullscreen } from './useMermaidFullscreen';
@@ -1,73 +0,0 @@
1
- /**
2
- * Hook for cleaning up orphaned Mermaid DOM nodes
3
- */
4
-
5
- import { useCallback, useEffect } from 'react';
6
-
7
- export function useMermaidCleanup() {
8
- const cleanupMermaidErrors = useCallback(() => {
9
- if (typeof document === 'undefined') return;
10
-
11
- // Remove all orphaned mermaid elements from body
12
- // Mermaid can append: SVGs, divs with errors, text nodes
13
-
14
- // 1. Remove elements with mermaid-* IDs directly in body
15
- document.querySelectorAll('[id^="mermaid-"]').forEach((node) => {
16
- if (node.parentNode === document.body) {
17
- node.remove();
18
- }
19
- });
20
-
21
- // 2. Remove elements with d prefix (mermaid diagram IDs) directly in body
22
- document.querySelectorAll('[id^="d"]').forEach((node) => {
23
- if (node.parentNode === document.body && node.id.match(/^d\d+$/)) {
24
- node.remove();
25
- }
26
- });
27
-
28
- // 3. Remove orphaned SVG elements that mermaid creates in body
29
- document.querySelectorAll('body > svg').forEach((node) => {
30
- // Check if it's a mermaid SVG (has mermaid classes or aria-roledescription)
31
- if (node.getAttribute('aria-roledescription') ||
32
- node.classList.contains('mermaid') ||
33
- node.querySelector('.mermaid') ||
34
- node.id?.includes('mermaid')) {
35
- node.remove();
36
- }
37
- });
38
-
39
- // 4. Remove any orphaned error divs with "Syntax error" text
40
- document.querySelectorAll('body > div').forEach((node) => {
41
- const text = node.textContent || '';
42
- if (text.includes('Syntax error in text') ||
43
- text.includes('mermaid version') ||
44
- node.id?.startsWith('mermaid-') ||
45
- node.id?.startsWith('d') && node.id.match(/^d\d+$/)) {
46
- node.remove();
47
- }
48
- });
49
-
50
- // 5. Remove orphaned pre elements with error info
51
- document.querySelectorAll('body > pre').forEach((node) => {
52
- const text = node.textContent || '';
53
- if (text.includes('Syntax error') || text.includes('mermaid')) {
54
- node.remove();
55
- }
56
- });
57
- }, []);
58
-
59
- // Cleanup on unmount
60
- useEffect(() => {
61
- return () => {
62
- cleanupMermaidErrors();
63
- };
64
- }, [cleanupMermaidErrors]);
65
-
66
- // Also run cleanup periodically to catch any stray elements
67
- useEffect(() => {
68
- const interval = setInterval(cleanupMermaidErrors, 1000);
69
- return () => clearInterval(interval);
70
- }, [cleanupMermaidErrors]);
71
-
72
- return { cleanupMermaidErrors };
73
- }
@@ -1,46 +0,0 @@
1
- /**
2
- * Hook for managing Mermaid fullscreen modal
3
- */
4
-
5
- import { useEffect, useRef, useState } from 'react';
6
-
7
- export function useMermaidFullscreen() {
8
- const [isFullscreen, setIsFullscreen] = useState(false);
9
- const fullscreenRef = useRef<HTMLDivElement>(null);
10
-
11
- const openFullscreen = () => setIsFullscreen(true);
12
- const closeFullscreen = () => setIsFullscreen(false);
13
-
14
- const handleBackdropClick = (e: React.MouseEvent) => {
15
- if (e.target === e.currentTarget) {
16
- closeFullscreen();
17
- }
18
- };
19
-
20
- // Handle ESC key
21
- useEffect(() => {
22
- const handleEscKey = (event: KeyboardEvent) => {
23
- if (event.key === 'Escape' && isFullscreen) {
24
- closeFullscreen();
25
- }
26
- };
27
-
28
- if (isFullscreen) {
29
- document.addEventListener('keydown', handleEscKey);
30
- document.body.style.overflow = 'hidden';
31
- }
32
-
33
- return () => {
34
- document.removeEventListener('keydown', handleEscKey);
35
- document.body.style.overflow = 'unset';
36
- };
37
- }, [isFullscreen]);
38
-
39
- return {
40
- isFullscreen,
41
- fullscreenRef,
42
- openFullscreen,
43
- closeFullscreen,
44
- handleBackdropClick,
45
- };
46
- }