@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,477 @@
|
|
|
1
|
+
import { __name } from './chunk-37ZI6VD4.mjs';
|
|
2
|
+
import { useResolvedTheme } from '@djangocfg/ui-core/hooks';
|
|
3
|
+
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
6
|
+
import mermaid from 'mermaid';
|
|
7
|
+
|
|
8
|
+
// src/tools/Mermaid/utils/mermaid-helpers.ts
|
|
9
|
+
var applyMermaidTextColors = /* @__PURE__ */ __name((container, textColor) => {
|
|
10
|
+
const svgElement = container.querySelector("svg");
|
|
11
|
+
if (svgElement) {
|
|
12
|
+
svgElement.querySelectorAll("text").forEach((el) => {
|
|
13
|
+
el.style.fill = textColor;
|
|
14
|
+
});
|
|
15
|
+
svgElement.querySelectorAll(".nodeLabel, .edgeLabel").forEach((el) => {
|
|
16
|
+
el.style.color = textColor;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}, "applyMermaidTextColors");
|
|
20
|
+
var MermaidCodeViewer = /* @__PURE__ */ __name(({
|
|
21
|
+
chart,
|
|
22
|
+
renderPreview
|
|
23
|
+
}) => {
|
|
24
|
+
const [activeTab, setActiveTab] = useState("preview");
|
|
25
|
+
const [copied, setCopied] = useState(false);
|
|
26
|
+
const handleCopy = /* @__PURE__ */ __name(async () => {
|
|
27
|
+
await navigator.clipboard.writeText(chart);
|
|
28
|
+
setCopied(true);
|
|
29
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
30
|
+
}, "handleCopy");
|
|
31
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
32
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-border px-4", children: [
|
|
33
|
+
/* @__PURE__ */ jsxs("div", { className: "flex", children: [
|
|
34
|
+
/* @__PURE__ */ jsxs(
|
|
35
|
+
"button",
|
|
36
|
+
{
|
|
37
|
+
onClick: () => setActiveTab("preview"),
|
|
38
|
+
className: `px-4 py-3 text-sm font-medium transition-colors relative ${activeTab === "preview" ? "text-foreground" : "text-muted-foreground hover:text-foreground"}`,
|
|
39
|
+
children: [
|
|
40
|
+
"Preview",
|
|
41
|
+
activeTab === "preview" && /* @__PURE__ */ jsx("div", { className: "absolute bottom-0 left-0 right-0 h-0.5 bg-primary" })
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
),
|
|
45
|
+
/* @__PURE__ */ jsxs(
|
|
46
|
+
"button",
|
|
47
|
+
{
|
|
48
|
+
onClick: () => setActiveTab("code"),
|
|
49
|
+
className: `px-4 py-3 text-sm font-medium transition-colors relative ${activeTab === "code" ? "text-foreground" : "text-muted-foreground hover:text-foreground"}`,
|
|
50
|
+
children: [
|
|
51
|
+
"Code",
|
|
52
|
+
activeTab === "code" && /* @__PURE__ */ jsx("div", { className: "absolute bottom-0 left-0 right-0 h-0.5 bg-primary" })
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
] }),
|
|
57
|
+
activeTab === "code" && /* @__PURE__ */ jsx(
|
|
58
|
+
"button",
|
|
59
|
+
{
|
|
60
|
+
onClick: handleCopy,
|
|
61
|
+
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",
|
|
62
|
+
children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
63
|
+
/* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
|
|
64
|
+
"Copied!"
|
|
65
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
66
|
+
/* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("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" }) }),
|
|
67
|
+
"Copy"
|
|
68
|
+
] })
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
] }),
|
|
72
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto", children: activeTab === "preview" ? /* @__PURE__ */ jsx("div", { className: "p-6 flex items-center justify-center min-h-full", children: renderPreview() }) : /* @__PURE__ */ jsx("pre", { className: "p-6 text-sm font-mono text-foreground bg-muted/30 h-full overflow-auto", children: /* @__PURE__ */ jsx("code", { children: chart }) }) })
|
|
73
|
+
] });
|
|
74
|
+
}, "MermaidCodeViewer");
|
|
75
|
+
var MermaidFullscreenModal = /* @__PURE__ */ __name(({
|
|
76
|
+
isOpen,
|
|
77
|
+
svgContent,
|
|
78
|
+
isVertical,
|
|
79
|
+
theme,
|
|
80
|
+
chart,
|
|
81
|
+
fullscreenRef,
|
|
82
|
+
onClose,
|
|
83
|
+
onBackdropClick
|
|
84
|
+
}) => {
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (isOpen && fullscreenRef.current) {
|
|
87
|
+
const getCSSVariable = /* @__PURE__ */ __name((variable) => {
|
|
88
|
+
if (typeof document === "undefined") return "";
|
|
89
|
+
const value = getComputedStyle(document.documentElement).getPropertyValue(variable).trim();
|
|
90
|
+
return value ? `hsl(${value})` : "";
|
|
91
|
+
}, "getCSSVariable");
|
|
92
|
+
const textColor = theme === "dark" ? getCSSVariable("--foreground") || "hsl(0 0% 90%)" : getCSSVariable("--foreground") || "hsl(222.2 84% 4.9%)";
|
|
93
|
+
applyMermaidTextColors(fullscreenRef.current, textColor);
|
|
94
|
+
const svgElement = fullscreenRef.current.querySelector("svg");
|
|
95
|
+
if (svgElement) {
|
|
96
|
+
svgElement.style.display = "block";
|
|
97
|
+
svgElement.style.height = "auto";
|
|
98
|
+
svgElement.style.maxWidth = "100%";
|
|
99
|
+
if (isVertical) {
|
|
100
|
+
svgElement.style.maxWidth = "600px";
|
|
101
|
+
svgElement.style.margin = "0 auto";
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}, [isOpen, theme, isVertical, fullscreenRef]);
|
|
106
|
+
if (!isOpen || typeof document === "undefined") return null;
|
|
107
|
+
return createPortal(
|
|
108
|
+
/* @__PURE__ */ jsx(
|
|
109
|
+
"div",
|
|
110
|
+
{
|
|
111
|
+
className: "fixed inset-0 z-9999 flex items-center justify-center p-4",
|
|
112
|
+
style: { backgroundColor: "rgb(0 0 0 / 0.75)" },
|
|
113
|
+
onClick: onBackdropClick,
|
|
114
|
+
children: /* @__PURE__ */ jsxs("div", { className: `relative bg-card rounded-sm shadow-xl max-h-[95vh] flex flex-col border border-border ${isVertical ? "w-auto min-w-[400px] max-w-[600px]" : "min-w-[600px] max-w-[90vw] w-auto"}`, children: [
|
|
115
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between py-4 px-6 border-b border-border", children: [
|
|
116
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium text-foreground py-0 my-0", children: "Diagram" }),
|
|
117
|
+
/* @__PURE__ */ jsx(
|
|
118
|
+
"button",
|
|
119
|
+
{
|
|
120
|
+
onClick: onClose,
|
|
121
|
+
className: "text-muted-foreground hover:text-foreground transition-colors",
|
|
122
|
+
children: /* @__PURE__ */ jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
] }),
|
|
126
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
127
|
+
MermaidCodeViewer,
|
|
128
|
+
{
|
|
129
|
+
chart,
|
|
130
|
+
renderPreview: () => /* @__PURE__ */ jsx(
|
|
131
|
+
"div",
|
|
132
|
+
{
|
|
133
|
+
ref: fullscreenRef,
|
|
134
|
+
dangerouslySetInnerHTML: { __html: svgContent }
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
) })
|
|
139
|
+
] })
|
|
140
|
+
}
|
|
141
|
+
),
|
|
142
|
+
document.body
|
|
143
|
+
);
|
|
144
|
+
}, "MermaidFullscreenModal");
|
|
145
|
+
function useMermaidFullscreen() {
|
|
146
|
+
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
147
|
+
const fullscreenRef = useRef(null);
|
|
148
|
+
const openFullscreen = /* @__PURE__ */ __name(() => setIsFullscreen(true), "openFullscreen");
|
|
149
|
+
const closeFullscreen = /* @__PURE__ */ __name(() => setIsFullscreen(false), "closeFullscreen");
|
|
150
|
+
const handleBackdropClick = /* @__PURE__ */ __name((e) => {
|
|
151
|
+
if (e.target === e.currentTarget) {
|
|
152
|
+
closeFullscreen();
|
|
153
|
+
}
|
|
154
|
+
}, "handleBackdropClick");
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
const handleEscKey = /* @__PURE__ */ __name((event) => {
|
|
157
|
+
if (event.key === "Escape" && isFullscreen) {
|
|
158
|
+
closeFullscreen();
|
|
159
|
+
}
|
|
160
|
+
}, "handleEscKey");
|
|
161
|
+
if (isFullscreen) {
|
|
162
|
+
document.addEventListener("keydown", handleEscKey);
|
|
163
|
+
document.body.style.overflow = "hidden";
|
|
164
|
+
}
|
|
165
|
+
return () => {
|
|
166
|
+
document.removeEventListener("keydown", handleEscKey);
|
|
167
|
+
document.body.style.overflow = "unset";
|
|
168
|
+
};
|
|
169
|
+
}, [isFullscreen]);
|
|
170
|
+
return {
|
|
171
|
+
isFullscreen,
|
|
172
|
+
fullscreenRef,
|
|
173
|
+
openFullscreen,
|
|
174
|
+
closeFullscreen,
|
|
175
|
+
handleBackdropClick
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
__name(useMermaidFullscreen, "useMermaidFullscreen");
|
|
179
|
+
function useMermaidCleanup() {
|
|
180
|
+
const cleanupMermaidErrors = useCallback(() => {
|
|
181
|
+
if (typeof document === "undefined") return;
|
|
182
|
+
document.querySelectorAll('[id^="mermaid-"]').forEach((node) => {
|
|
183
|
+
if (node.parentNode === document.body) {
|
|
184
|
+
node.remove();
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
document.querySelectorAll('[id^="d"]').forEach((node) => {
|
|
188
|
+
if (node.parentNode === document.body && node.id.match(/^d\d+$/)) {
|
|
189
|
+
node.remove();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
document.querySelectorAll("body > svg").forEach((node) => {
|
|
193
|
+
if (node.getAttribute("aria-roledescription") || node.classList.contains("mermaid") || node.querySelector(".mermaid") || node.id?.includes("mermaid")) {
|
|
194
|
+
node.remove();
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
document.querySelectorAll("body > div").forEach((node) => {
|
|
198
|
+
const text = node.textContent || "";
|
|
199
|
+
if (text.includes("Syntax error in text") || text.includes("mermaid version") || node.id?.startsWith("mermaid-") || node.id?.startsWith("d") && node.id.match(/^d\d+$/)) {
|
|
200
|
+
node.remove();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
document.querySelectorAll("body > pre").forEach((node) => {
|
|
204
|
+
const text = node.textContent || "";
|
|
205
|
+
if (text.includes("Syntax error") || text.includes("mermaid")) {
|
|
206
|
+
node.remove();
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}, []);
|
|
210
|
+
useEffect(() => {
|
|
211
|
+
return () => {
|
|
212
|
+
cleanupMermaidErrors();
|
|
213
|
+
};
|
|
214
|
+
}, [cleanupMermaidErrors]);
|
|
215
|
+
useEffect(() => {
|
|
216
|
+
const interval = setInterval(cleanupMermaidErrors, 1e3);
|
|
217
|
+
return () => clearInterval(interval);
|
|
218
|
+
}, [cleanupMermaidErrors]);
|
|
219
|
+
return { cleanupMermaidErrors };
|
|
220
|
+
}
|
|
221
|
+
__name(useMermaidCleanup, "useMermaidCleanup");
|
|
222
|
+
|
|
223
|
+
// src/tools/Mermaid/hooks/useMermaidValidation.ts
|
|
224
|
+
function useMermaidValidation() {
|
|
225
|
+
const isMermaidCodeComplete = /* @__PURE__ */ __name((code) => {
|
|
226
|
+
if (!code || code.trim().length === 0) return false;
|
|
227
|
+
const trimmed = code.trim();
|
|
228
|
+
const lines = trimmed.split("\n");
|
|
229
|
+
if (lines.length < 2) return false;
|
|
230
|
+
const lastLine = lines[lines.length - 1].trim();
|
|
231
|
+
if (lastLine.match(/-->?\s*$/)) return false;
|
|
232
|
+
if (lastLine.match(/-->\|[^|]*\|\s*$/)) return false;
|
|
233
|
+
if (lastLine.match(/[\[({]\s*$/)) return false;
|
|
234
|
+
return true;
|
|
235
|
+
}, "isMermaidCodeComplete");
|
|
236
|
+
return { isMermaidCodeComplete };
|
|
237
|
+
}
|
|
238
|
+
__name(useMermaidValidation, "useMermaidValidation");
|
|
239
|
+
|
|
240
|
+
// src/tools/Mermaid/hooks/useMermaidRenderer.ts
|
|
241
|
+
var applyMermaidTextColors2 = /* @__PURE__ */ __name((container, textColor) => {
|
|
242
|
+
const svgElement = container.querySelector("svg");
|
|
243
|
+
if (svgElement) {
|
|
244
|
+
svgElement.querySelectorAll("text").forEach((el) => {
|
|
245
|
+
el.style.fill = textColor;
|
|
246
|
+
});
|
|
247
|
+
svgElement.querySelectorAll(".nodeLabel, .edgeLabel").forEach((el) => {
|
|
248
|
+
el.style.color = textColor;
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}, "applyMermaidTextColors");
|
|
252
|
+
var isVerticalDiagram = /* @__PURE__ */ __name((svgElement) => {
|
|
253
|
+
const viewBox = svgElement.getAttribute("viewBox");
|
|
254
|
+
if (viewBox) {
|
|
255
|
+
const [, , width, height] = viewBox.split(" ").map(Number);
|
|
256
|
+
return height > width * 1.5;
|
|
257
|
+
}
|
|
258
|
+
const bbox = svgElement.getBBox?.();
|
|
259
|
+
if (bbox) {
|
|
260
|
+
return bbox.height > bbox.width * 1.5;
|
|
261
|
+
}
|
|
262
|
+
return false;
|
|
263
|
+
}, "isVerticalDiagram");
|
|
264
|
+
function useMermaidRenderer({ chart, theme, isCompact = false }) {
|
|
265
|
+
const mermaidRef = useRef(null);
|
|
266
|
+
const renderTimerRef = useRef(null);
|
|
267
|
+
const [svgContent, setSvgContent] = useState("");
|
|
268
|
+
const [isVertical, setIsVertical] = useState(false);
|
|
269
|
+
const [isRendering, setIsRendering] = useState(false);
|
|
270
|
+
const { isMermaidCodeComplete } = useMermaidValidation();
|
|
271
|
+
const { cleanupMermaidErrors } = useMermaidCleanup();
|
|
272
|
+
useEffect(() => {
|
|
273
|
+
const getCSSVariable = /* @__PURE__ */ __name((variable) => {
|
|
274
|
+
if (typeof document === "undefined") return "";
|
|
275
|
+
const value = getComputedStyle(document.documentElement).getPropertyValue(variable).trim();
|
|
276
|
+
return value ? `hsl(${value})` : "";
|
|
277
|
+
}, "getCSSVariable");
|
|
278
|
+
const diagramFontSize = isCompact ? "12px" : "14px";
|
|
279
|
+
const themeVariables = theme === "dark" ? {
|
|
280
|
+
primaryColor: getCSSVariable("--primary") || "hsl(221.2 83.2% 53.3%)",
|
|
281
|
+
primaryTextColor: getCSSVariable("--foreground") || "hsl(210 40% 98%)",
|
|
282
|
+
primaryBorderColor: getCSSVariable("--primary") || "hsl(221.2 83.2% 53.3%)",
|
|
283
|
+
secondaryColor: getCSSVariable("--muted") || "hsl(217.2 32.6% 17.5%)",
|
|
284
|
+
secondaryTextColor: getCSSVariable("--foreground") || "hsl(210 40% 98%)",
|
|
285
|
+
secondaryBorderColor: getCSSVariable("--border") || "hsl(217.2 32.6% 27.5%)",
|
|
286
|
+
tertiaryColor: getCSSVariable("--accent") || "hsl(217.2 32.6% 20%)",
|
|
287
|
+
tertiaryTextColor: getCSSVariable("--foreground") || "hsl(210 40% 98%)",
|
|
288
|
+
tertiaryBorderColor: getCSSVariable("--border") || "hsl(217.2 32.6% 27.5%)",
|
|
289
|
+
mainBkg: getCSSVariable("--card") || "hsl(222.2 84% 8%)",
|
|
290
|
+
textColor: getCSSVariable("--foreground") || "hsl(210 40% 98%)",
|
|
291
|
+
nodeBorder: getCSSVariable("--border") || "hsl(217.2 32.6% 27.5%)",
|
|
292
|
+
nodeTextColor: getCSSVariable("--foreground") || "hsl(210 40% 98%)",
|
|
293
|
+
secondBkg: getCSSVariable("--muted") || "hsl(217.2 32.6% 17.5%)",
|
|
294
|
+
lineColor: getCSSVariable("--primary") || "hsl(221.2 83.2% 53.3%)",
|
|
295
|
+
edgeLabelBackground: getCSSVariable("--card") || "hsl(222.2 84% 8%)",
|
|
296
|
+
clusterBkg: getCSSVariable("--muted") || "hsl(217.2 32.6% 12%)",
|
|
297
|
+
clusterBorder: getCSSVariable("--primary") || "hsl(221.2 83.2% 53.3%)",
|
|
298
|
+
background: getCSSVariable("--background") || "hsl(222.2 84% 4.9%)",
|
|
299
|
+
labelBackground: getCSSVariable("--card") || "hsl(222.2 84% 8%)",
|
|
300
|
+
labelTextColor: getCSSVariable("--foreground") || "hsl(210 40% 98%)",
|
|
301
|
+
errorBkgColor: getCSSVariable("--destructive") || "hsl(0 62.8% 30.6%)",
|
|
302
|
+
errorTextColor: "hsl(210 40% 98%)",
|
|
303
|
+
fontSize: diagramFontSize,
|
|
304
|
+
fontFamily: "Inter, system-ui, sans-serif"
|
|
305
|
+
} : {
|
|
306
|
+
primaryColor: getCSSVariable("--primary") || "hsl(221.2 83.2% 53.3%)",
|
|
307
|
+
primaryTextColor: getCSSVariable("--foreground") || "hsl(222.2 84% 4.9%)",
|
|
308
|
+
primaryBorderColor: getCSSVariable("--primary") || "hsl(221.2 83.2% 53.3%)",
|
|
309
|
+
secondaryColor: getCSSVariable("--secondary") || "hsl(210 40% 96.1%)",
|
|
310
|
+
secondaryTextColor: getCSSVariable("--foreground") || "hsl(222.2 84% 4.9%)",
|
|
311
|
+
secondaryBorderColor: getCSSVariable("--border") || "hsl(214.3 31.8% 91.4%)",
|
|
312
|
+
tertiaryColor: getCSSVariable("--muted") || "hsl(210 40% 96.1%)",
|
|
313
|
+
tertiaryTextColor: getCSSVariable("--foreground") || "hsl(222.2 84% 4.9%)",
|
|
314
|
+
tertiaryBorderColor: getCSSVariable("--border") || "hsl(214.3 31.8% 91.4%)",
|
|
315
|
+
mainBkg: getCSSVariable("--card") || "hsl(0 0% 100%)",
|
|
316
|
+
textColor: getCSSVariable("--foreground") || "hsl(222.2 84% 4.9%)",
|
|
317
|
+
nodeBorder: getCSSVariable("--border") || "hsl(214.3 31.8% 91.4%)",
|
|
318
|
+
nodeTextColor: getCSSVariable("--foreground") || "hsl(222.2 84% 4.9%)",
|
|
319
|
+
secondBkg: getCSSVariable("--muted") || "hsl(210 40% 96.1%)",
|
|
320
|
+
lineColor: getCSSVariable("--primary") || "hsl(221.2 83.2% 53.3%)",
|
|
321
|
+
edgeLabelBackground: getCSSVariable("--card") || "hsl(0 0% 100%)",
|
|
322
|
+
clusterBkg: getCSSVariable("--accent") || "hsl(210 40% 98%)",
|
|
323
|
+
clusterBorder: getCSSVariable("--primary") || "hsl(221.2 83.2% 53.3%)",
|
|
324
|
+
background: getCSSVariable("--background") || "hsl(0 0% 100%)",
|
|
325
|
+
labelBackground: getCSSVariable("--card") || "hsl(0 0% 100%)",
|
|
326
|
+
labelTextColor: getCSSVariable("--foreground") || "hsl(222.2 84% 4.9%)",
|
|
327
|
+
errorBkgColor: getCSSVariable("--destructive") || "hsl(0 84.2% 60.2%)",
|
|
328
|
+
errorTextColor: "hsl(210 40% 98%)",
|
|
329
|
+
fontSize: diagramFontSize,
|
|
330
|
+
fontFamily: "Inter, system-ui, sans-serif"
|
|
331
|
+
};
|
|
332
|
+
mermaid.initialize({
|
|
333
|
+
startOnLoad: false,
|
|
334
|
+
theme: "base",
|
|
335
|
+
securityLevel: "loose",
|
|
336
|
+
suppressErrorRendering: true,
|
|
337
|
+
// Prevent mermaid from appending errors to body
|
|
338
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
339
|
+
flowchart: {
|
|
340
|
+
useMaxWidth: true,
|
|
341
|
+
htmlLabels: true,
|
|
342
|
+
curve: "basis"
|
|
343
|
+
},
|
|
344
|
+
themeVariables
|
|
345
|
+
});
|
|
346
|
+
const renderChart = /* @__PURE__ */ __name(async () => {
|
|
347
|
+
if (!mermaidRef.current || !chart) return;
|
|
348
|
+
if (!isMermaidCodeComplete(chart)) {
|
|
349
|
+
setIsRendering(true);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
try {
|
|
353
|
+
setIsRendering(true);
|
|
354
|
+
if (mermaidRef.current) {
|
|
355
|
+
mermaidRef.current.innerHTML = "";
|
|
356
|
+
}
|
|
357
|
+
const id = `mermaid-${Math.random().toString(36).substring(2, 9)}`;
|
|
358
|
+
const { svg } = await mermaid.render(id, chart);
|
|
359
|
+
if (mermaidRef.current) {
|
|
360
|
+
const textColor = theme === "dark" ? getCSSVariable("--foreground") || "hsl(0 0% 90%)" : getCSSVariable("--foreground") || "hsl(222.2 84% 4.9%)";
|
|
361
|
+
const processedSvg = svg.replace(
|
|
362
|
+
/<svg /,
|
|
363
|
+
`<svg style="--mermaid-text-color: ${textColor};" `
|
|
364
|
+
);
|
|
365
|
+
mermaidRef.current.innerHTML = processedSvg;
|
|
366
|
+
setSvgContent(processedSvg);
|
|
367
|
+
applyMermaidTextColors2(mermaidRef.current, textColor);
|
|
368
|
+
const svgElement = mermaidRef.current.querySelector("svg");
|
|
369
|
+
if (svgElement) {
|
|
370
|
+
svgElement.style.maxWidth = "100%";
|
|
371
|
+
svgElement.style.height = "auto";
|
|
372
|
+
svgElement.style.display = "block";
|
|
373
|
+
setIsVertical(isVerticalDiagram(svgElement));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
setIsRendering(false);
|
|
377
|
+
} catch (error) {
|
|
378
|
+
console.error("Mermaid rendering error:", error);
|
|
379
|
+
setIsRendering(false);
|
|
380
|
+
cleanupMermaidErrors();
|
|
381
|
+
if (mermaidRef.current) {
|
|
382
|
+
mermaidRef.current.innerHTML = `
|
|
383
|
+
<div class="p-4 text-destructive bg-destructive/10 border border-destructive/20 rounded-sm">
|
|
384
|
+
<p class="font-semibold">Mermaid Diagram Error</p>
|
|
385
|
+
<p class="text-sm">${error instanceof Error ? error.message : "Unknown error"}</p>
|
|
386
|
+
</div>
|
|
387
|
+
`;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}, "renderChart");
|
|
391
|
+
if (renderTimerRef.current) {
|
|
392
|
+
clearTimeout(renderTimerRef.current);
|
|
393
|
+
}
|
|
394
|
+
renderTimerRef.current = setTimeout(() => {
|
|
395
|
+
renderChart();
|
|
396
|
+
}, 500);
|
|
397
|
+
return () => {
|
|
398
|
+
if (renderTimerRef.current) {
|
|
399
|
+
clearTimeout(renderTimerRef.current);
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
}, [chart, theme, isCompact, isMermaidCodeComplete, cleanupMermaidErrors]);
|
|
403
|
+
return {
|
|
404
|
+
mermaidRef,
|
|
405
|
+
svgContent,
|
|
406
|
+
isVertical,
|
|
407
|
+
isRendering
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
__name(useMermaidRenderer, "useMermaidRenderer");
|
|
411
|
+
var Mermaid = /* @__PURE__ */ __name(({ chart, className = "", isCompact = false }) => {
|
|
412
|
+
const theme = useResolvedTheme();
|
|
413
|
+
const { mermaidRef, svgContent, isVertical, isRendering } = useMermaidRenderer({
|
|
414
|
+
chart,
|
|
415
|
+
theme,
|
|
416
|
+
isCompact
|
|
417
|
+
});
|
|
418
|
+
const {
|
|
419
|
+
isFullscreen,
|
|
420
|
+
fullscreenRef,
|
|
421
|
+
openFullscreen,
|
|
422
|
+
closeFullscreen,
|
|
423
|
+
handleBackdropClick
|
|
424
|
+
} = useMermaidFullscreen();
|
|
425
|
+
const handleClick = /* @__PURE__ */ __name(() => {
|
|
426
|
+
if (svgContent) {
|
|
427
|
+
openFullscreen();
|
|
428
|
+
}
|
|
429
|
+
}, "handleClick");
|
|
430
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
431
|
+
/* @__PURE__ */ jsxs(
|
|
432
|
+
"div",
|
|
433
|
+
{
|
|
434
|
+
className: `relative bg-card rounded-sm border border-border overflow-hidden cursor-pointer hover:shadow-sm transition-shadow ${className}`,
|
|
435
|
+
onClick: handleClick,
|
|
436
|
+
children: [
|
|
437
|
+
/* @__PURE__ */ jsxs("div", { className: "p-4 border-b border-border bg-muted/50", children: [
|
|
438
|
+
/* @__PURE__ */ jsx("h6", { className: "text-sm font-semibold text-foreground", children: "Diagram" }),
|
|
439
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: "Click to view fullscreen" })
|
|
440
|
+
] }),
|
|
441
|
+
/* @__PURE__ */ jsxs("div", { className: "relative p-4 overflow-hidden", children: [
|
|
442
|
+
/* @__PURE__ */ jsx(
|
|
443
|
+
"div",
|
|
444
|
+
{
|
|
445
|
+
ref: mermaidRef,
|
|
446
|
+
className: "flex justify-center items-center min-h-[200px]",
|
|
447
|
+
style: { isolation: "isolate" }
|
|
448
|
+
}
|
|
449
|
+
),
|
|
450
|
+
isRendering && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-background/50 backdrop-blur-sm", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
451
|
+
/* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-primary" }),
|
|
452
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Rendering diagram..." })
|
|
453
|
+
] }) })
|
|
454
|
+
] })
|
|
455
|
+
]
|
|
456
|
+
}
|
|
457
|
+
),
|
|
458
|
+
/* @__PURE__ */ jsx(
|
|
459
|
+
MermaidFullscreenModal,
|
|
460
|
+
{
|
|
461
|
+
isOpen: isFullscreen,
|
|
462
|
+
svgContent,
|
|
463
|
+
isVertical,
|
|
464
|
+
theme,
|
|
465
|
+
chart,
|
|
466
|
+
fullscreenRef,
|
|
467
|
+
onClose: closeFullscreen,
|
|
468
|
+
onBackdropClick: handleBackdropClick
|
|
469
|
+
}
|
|
470
|
+
)
|
|
471
|
+
] });
|
|
472
|
+
}, "Mermaid");
|
|
473
|
+
var Mermaid_client_default = Mermaid;
|
|
474
|
+
|
|
475
|
+
export { Mermaid_client_default as default };
|
|
476
|
+
//# sourceMappingURL=Mermaid.client-4TU2TSH3.mjs.map
|
|
477
|
+
//# sourceMappingURL=Mermaid.client-4TU2TSH3.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tools/Mermaid/utils/mermaid-helpers.ts","../src/tools/Mermaid/components/MermaidCodeViewer.tsx","../src/tools/Mermaid/components/MermaidFullscreenModal.tsx","../src/tools/Mermaid/hooks/useMermaidFullscreen.ts","../src/tools/Mermaid/hooks/useMermaidCleanup.ts","../src/tools/Mermaid/hooks/useMermaidValidation.ts","../src/tools/Mermaid/hooks/useMermaidRenderer.ts","../src/tools/Mermaid/Mermaid.client.tsx"],"names":["jsx","jsxs","useState","useEffect","applyMermaidTextColors","useRef","Fragment"],"mappings":"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","file":"Mermaid.client-4TU2TSH3.mjs","sourcesContent":["/**\n * Helper utilities for Mermaid diagram rendering\n */\n\n// Utility function to apply text colors to Mermaid SVG\nexport const applyMermaidTextColors = (container: HTMLElement, textColor: string) => {\n const svgElement = container.querySelector('svg');\n if (svgElement) {\n // SVG text elements use 'fill'\n svgElement.querySelectorAll('text').forEach((el) => {\n (el as SVGElement).style.fill = textColor;\n });\n\n // HTML elements inside foreignObject use 'color'\n svgElement.querySelectorAll('.nodeLabel, .edgeLabel').forEach((el) => {\n (el as HTMLElement).style.color = textColor;\n });\n }\n};\n\n// Detect if diagram is vertical (tall and narrow)\nexport const isVerticalDiagram = (svgElement: SVGSVGElement): boolean => {\n const viewBox = svgElement.getAttribute('viewBox');\n if (viewBox) {\n const [, , width, height] = viewBox.split(' ').map(Number);\n return height > width * 1.5;\n }\n const bbox = svgElement.getBBox?.();\n if (bbox) {\n return bbox.height > bbox.width * 1.5;\n }\n return false;\n};\n","'use client';\n\nimport React, { useState } from 'react';\n\ninterface MermaidCodeViewerProps {\n chart: string;\n renderPreview: () => React.ReactNode;\n}\n\nexport const MermaidCodeViewer: React.FC<MermaidCodeViewerProps> = ({\n chart,\n renderPreview,\n}) => {\n const [activeTab, setActiveTab] = useState<'preview' | 'code'>('preview');\n const [copied, setCopied] = useState(false);\n\n const handleCopy = async () => {\n await navigator.clipboard.writeText(chart);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n };\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Tabs */}\n <div className=\"flex items-center justify-between border-b border-border px-4\">\n <div className=\"flex\">\n <button\n onClick={() => setActiveTab('preview')}\n className={`px-4 py-3 text-sm font-medium transition-colors relative ${\n activeTab === 'preview'\n ? 'text-foreground'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n >\n Preview\n {activeTab === 'preview' && (\n <div className=\"absolute bottom-0 left-0 right-0 h-0.5 bg-primary\" />\n )}\n </button>\n <button\n onClick={() => setActiveTab('code')}\n className={`px-4 py-3 text-sm font-medium transition-colors relative ${\n activeTab === 'code'\n ? 'text-foreground'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n >\n Code\n {activeTab === 'code' && (\n <div className=\"absolute bottom-0 left-0 right-0 h-0.5 bg-primary\" />\n )}\n </button>\n </div>\n\n {/* Copy button - show only on Code tab */}\n {activeTab === 'code' && (\n <button\n onClick={handleCopy}\n 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\"\n >\n {copied ? (\n <>\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n Copied!\n </>\n ) : (\n <>\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <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\" />\n </svg>\n Copy\n </>\n )}\n </button>\n )}\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-auto\">\n {activeTab === 'preview' ? (\n <div className=\"p-6 flex items-center justify-center min-h-full\">\n {renderPreview()}\n </div>\n ) : (\n <pre className=\"p-6 text-sm font-mono text-foreground bg-muted/30 h-full overflow-auto\">\n <code>{chart}</code>\n </pre>\n )}\n </div>\n </div>\n );\n};\n","'use client';\n\nimport React, { useEffect } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { applyMermaidTextColors } from '../utils/mermaid-helpers';\nimport { MermaidCodeViewer } from './MermaidCodeViewer';\n\ninterface MermaidFullscreenModalProps {\n isOpen: boolean;\n svgContent: string;\n isVertical: boolean;\n theme: string;\n chart: string;\n fullscreenRef: React.RefObject<HTMLDivElement>;\n onClose: () => void;\n onBackdropClick: (e: React.MouseEvent) => void;\n}\n\nexport const MermaidFullscreenModal: React.FC<MermaidFullscreenModalProps> = ({\n isOpen,\n svgContent,\n isVertical,\n theme,\n chart,\n fullscreenRef,\n onClose,\n onBackdropClick,\n}) => {\n // Apply text colors to fullscreen modal after render\n useEffect(() => {\n if (isOpen && fullscreenRef.current) {\n const getCSSVariable = (variable: string) => {\n if (typeof document === 'undefined') return '';\n const value = getComputedStyle(document.documentElement).getPropertyValue(variable).trim();\n return value ? `hsl(${value})` : '';\n };\n\n const textColor = theme === 'dark'\n ? getCSSVariable('--foreground') || 'hsl(0 0% 90%)'\n : getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)';\n\n applyMermaidTextColors(fullscreenRef.current, textColor);\n\n // Make SVG responsive\n const svgElement = fullscreenRef.current.querySelector('svg');\n if (svgElement) {\n svgElement.style.display = 'block';\n svgElement.style.height = 'auto';\n svgElement.style.maxWidth = '100%';\n\n // For vertical diagrams, limit width\n if (isVertical) {\n svgElement.style.maxWidth = '600px';\n svgElement.style.margin = '0 auto';\n }\n }\n }\n }, [isOpen, theme, isVertical, fullscreenRef]);\n\n if (!isOpen || typeof document === 'undefined') return null;\n\n return createPortal(\n <div\n className=\"fixed inset-0 z-9999 flex items-center justify-center p-4\"\n style={{ backgroundColor: 'rgb(0 0 0 / 0.75)' }}\n onClick={onBackdropClick}\n >\n <div className={`relative bg-card rounded-sm shadow-xl max-h-[95vh] flex flex-col border border-border ${\n isVertical\n ? 'w-auto min-w-[400px] max-w-[600px]'\n : 'min-w-[600px] max-w-[90vw] w-auto'\n }`}>\n {/* Header */}\n <div className=\"flex items-center justify-between py-4 px-6 border-b border-border\">\n <h3 className=\"text-sm font-medium text-foreground py-0 my-0\">Diagram</h3>\n <button\n onClick={onClose}\n className=\"text-muted-foreground hover:text-foreground transition-colors\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {/* Content - Code Viewer with tabs */}\n <div className=\"flex-1 overflow-hidden\">\n <MermaidCodeViewer\n chart={chart}\n renderPreview={() => (\n <div\n ref={fullscreenRef}\n dangerouslySetInnerHTML={{ __html: svgContent }}\n />\n )}\n />\n </div>\n </div>\n </div>,\n document.body\n );\n};\n","/**\n * Hook for managing Mermaid fullscreen modal\n */\n\nimport { useEffect, useRef, useState } from 'react';\n\nexport function useMermaidFullscreen() {\n const [isFullscreen, setIsFullscreen] = useState(false);\n const fullscreenRef = useRef<HTMLDivElement>(null);\n\n const openFullscreen = () => setIsFullscreen(true);\n const closeFullscreen = () => setIsFullscreen(false);\n\n const handleBackdropClick = (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n closeFullscreen();\n }\n };\n\n // Handle ESC key\n useEffect(() => {\n const handleEscKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && isFullscreen) {\n closeFullscreen();\n }\n };\n\n if (isFullscreen) {\n document.addEventListener('keydown', handleEscKey);\n document.body.style.overflow = 'hidden';\n }\n\n return () => {\n document.removeEventListener('keydown', handleEscKey);\n document.body.style.overflow = 'unset';\n };\n }, [isFullscreen]);\n\n return {\n isFullscreen,\n fullscreenRef,\n openFullscreen,\n closeFullscreen,\n handleBackdropClick,\n };\n}\n","/**\n * Hook for cleaning up orphaned Mermaid DOM nodes\n */\n\nimport { useCallback, useEffect } from 'react';\n\nexport function useMermaidCleanup() {\n const cleanupMermaidErrors = useCallback(() => {\n if (typeof document === 'undefined') return;\n\n // Remove all orphaned mermaid elements from body\n // Mermaid can append: SVGs, divs with errors, text nodes\n\n // 1. Remove elements with mermaid-* IDs directly in body\n document.querySelectorAll('[id^=\"mermaid-\"]').forEach((node) => {\n if (node.parentNode === document.body) {\n node.remove();\n }\n });\n\n // 2. Remove elements with d prefix (mermaid diagram IDs) directly in body\n document.querySelectorAll('[id^=\"d\"]').forEach((node) => {\n if (node.parentNode === document.body && node.id.match(/^d\\d+$/)) {\n node.remove();\n }\n });\n\n // 3. Remove orphaned SVG elements that mermaid creates in body\n document.querySelectorAll('body > svg').forEach((node) => {\n // Check if it's a mermaid SVG (has mermaid classes or aria-roledescription)\n if (node.getAttribute('aria-roledescription') ||\n node.classList.contains('mermaid') ||\n node.querySelector('.mermaid') ||\n node.id?.includes('mermaid')) {\n node.remove();\n }\n });\n\n // 4. Remove any orphaned error divs with \"Syntax error\" text\n document.querySelectorAll('body > div').forEach((node) => {\n const text = node.textContent || '';\n if (text.includes('Syntax error in text') ||\n text.includes('mermaid version') ||\n node.id?.startsWith('mermaid-') ||\n node.id?.startsWith('d') && node.id.match(/^d\\d+$/)) {\n node.remove();\n }\n });\n\n // 5. Remove orphaned pre elements with error info\n document.querySelectorAll('body > pre').forEach((node) => {\n const text = node.textContent || '';\n if (text.includes('Syntax error') || text.includes('mermaid')) {\n node.remove();\n }\n });\n }, []);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n cleanupMermaidErrors();\n };\n }, [cleanupMermaidErrors]);\n\n // Also run cleanup periodically to catch any stray elements\n useEffect(() => {\n const interval = setInterval(cleanupMermaidErrors, 1000);\n return () => clearInterval(interval);\n }, [cleanupMermaidErrors]);\n\n return { cleanupMermaidErrors };\n}\n","/**\n * Hook for validating Mermaid code completeness\n */\n\nexport function useMermaidValidation() {\n const isMermaidCodeComplete = (code: string): boolean => {\n if (!code || code.trim().length === 0) return false;\n\n const trimmed = code.trim();\n\n // Check if code has basic structure\n const lines = trimmed.split('\\n');\n if (lines.length < 2) return false; // Need at least diagram type + one element\n\n // Check for common incomplete patterns\n const lastLine = lines[lines.length - 1].trim();\n\n // Incomplete if last line ends with arrow without destination\n if (lastLine.match(/-->?\\s*$/)) return false;\n if (lastLine.match(/-->\\|[^|]*\\|\\s*$/)) return false;\n\n // Incomplete if last line ends with opening bracket/parenthesis\n if (lastLine.match(/[\\[({]\\s*$/)) return false;\n\n return true;\n };\n\n return { isMermaidCodeComplete };\n}\n","/**\n * Hook for rendering Mermaid diagrams with debounce and validation\n */\n\nimport mermaid from 'mermaid';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { useMermaidCleanup } from './useMermaidCleanup';\nimport { useMermaidValidation } from './useMermaidValidation';\n\ninterface UseMermaidRendererProps {\n chart: string;\n theme: string;\n isCompact?: boolean;\n}\n\ninterface MermaidRenderResult {\n mermaidRef: React.RefObject<HTMLDivElement>;\n svgContent: string;\n isVertical: boolean;\n isRendering: boolean;\n}\n\n// Utility function to apply text colors to Mermaid SVG\nconst applyMermaidTextColors = (container: HTMLElement, textColor: string) => {\n const svgElement = container.querySelector('svg');\n if (svgElement) {\n // SVG text elements use 'fill'\n svgElement.querySelectorAll('text').forEach((el) => {\n (el as SVGElement).style.fill = textColor;\n });\n\n // HTML elements inside foreignObject use 'color'\n svgElement.querySelectorAll('.nodeLabel, .edgeLabel').forEach((el) => {\n (el as HTMLElement).style.color = textColor;\n });\n }\n};\n\n// Detect if diagram is vertical (tall and narrow)\nconst isVerticalDiagram = (svgElement: SVGSVGElement): boolean => {\n const viewBox = svgElement.getAttribute('viewBox');\n if (viewBox) {\n const [, , width, height] = viewBox.split(' ').map(Number);\n return height > width * 1.5;\n }\n const bbox = svgElement.getBBox?.();\n if (bbox) {\n return bbox.height > bbox.width * 1.5;\n }\n return false;\n};\n\nexport function useMermaidRenderer({ chart, theme, isCompact = false }: UseMermaidRendererProps): MermaidRenderResult {\n const mermaidRef = useRef<HTMLDivElement>(null);\n const renderTimerRef = useRef<NodeJS.Timeout | null>(null);\n const [svgContent, setSvgContent] = useState<string>('');\n const [isVertical, setIsVertical] = useState(false);\n const [isRendering, setIsRendering] = useState(false);\n\n const { isMermaidCodeComplete } = useMermaidValidation();\n const { cleanupMermaidErrors } = useMermaidCleanup();\n\n useEffect(() => {\n // Get CSS variables for semantic colors\n const getCSSVariable = (variable: string) => {\n if (typeof document === 'undefined') return '';\n const value = getComputedStyle(document.documentElement).getPropertyValue(variable).trim();\n return value ? `hsl(${value})` : '';\n };\n\n const diagramFontSize = isCompact ? '12px' : '14px';\n\n const themeVariables = theme === 'dark' ? {\n primaryColor: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',\n primaryTextColor: getCSSVariable('--foreground') || 'hsl(210 40% 98%)',\n primaryBorderColor: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',\n secondaryColor: getCSSVariable('--muted') || 'hsl(217.2 32.6% 17.5%)',\n secondaryTextColor: getCSSVariable('--foreground') || 'hsl(210 40% 98%)',\n secondaryBorderColor: getCSSVariable('--border') || 'hsl(217.2 32.6% 27.5%)',\n tertiaryColor: getCSSVariable('--accent') || 'hsl(217.2 32.6% 20%)',\n tertiaryTextColor: getCSSVariable('--foreground') || 'hsl(210 40% 98%)',\n tertiaryBorderColor: getCSSVariable('--border') || 'hsl(217.2 32.6% 27.5%)',\n mainBkg: getCSSVariable('--card') || 'hsl(222.2 84% 8%)',\n textColor: getCSSVariable('--foreground') || 'hsl(210 40% 98%)',\n nodeBorder: getCSSVariable('--border') || 'hsl(217.2 32.6% 27.5%)',\n nodeTextColor: getCSSVariable('--foreground') || 'hsl(210 40% 98%)',\n secondBkg: getCSSVariable('--muted') || 'hsl(217.2 32.6% 17.5%)',\n lineColor: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',\n edgeLabelBackground: getCSSVariable('--card') || 'hsl(222.2 84% 8%)',\n clusterBkg: getCSSVariable('--muted') || 'hsl(217.2 32.6% 12%)',\n clusterBorder: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',\n background: getCSSVariable('--background') || 'hsl(222.2 84% 4.9%)',\n labelBackground: getCSSVariable('--card') || 'hsl(222.2 84% 8%)',\n labelTextColor: getCSSVariable('--foreground') || 'hsl(210 40% 98%)',\n errorBkgColor: getCSSVariable('--destructive') || 'hsl(0 62.8% 30.6%)',\n errorTextColor: 'hsl(210 40% 98%)',\n fontSize: diagramFontSize,\n fontFamily: 'Inter, system-ui, sans-serif',\n } : {\n primaryColor: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',\n primaryTextColor: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)',\n primaryBorderColor: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',\n secondaryColor: getCSSVariable('--secondary') || 'hsl(210 40% 96.1%)',\n secondaryTextColor: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)',\n secondaryBorderColor: getCSSVariable('--border') || 'hsl(214.3 31.8% 91.4%)',\n tertiaryColor: getCSSVariable('--muted') || 'hsl(210 40% 96.1%)',\n tertiaryTextColor: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)',\n tertiaryBorderColor: getCSSVariable('--border') || 'hsl(214.3 31.8% 91.4%)',\n mainBkg: getCSSVariable('--card') || 'hsl(0 0% 100%)',\n textColor: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)',\n nodeBorder: getCSSVariable('--border') || 'hsl(214.3 31.8% 91.4%)',\n nodeTextColor: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)',\n secondBkg: getCSSVariable('--muted') || 'hsl(210 40% 96.1%)',\n lineColor: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',\n edgeLabelBackground: getCSSVariable('--card') || 'hsl(0 0% 100%)',\n clusterBkg: getCSSVariable('--accent') || 'hsl(210 40% 98%)',\n clusterBorder: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',\n background: getCSSVariable('--background') || 'hsl(0 0% 100%)',\n labelBackground: getCSSVariable('--card') || 'hsl(0 0% 100%)',\n labelTextColor: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)',\n errorBkgColor: getCSSVariable('--destructive') || 'hsl(0 84.2% 60.2%)',\n errorTextColor: 'hsl(210 40% 98%)',\n fontSize: diagramFontSize,\n fontFamily: 'Inter, system-ui, sans-serif',\n };\n\n mermaid.initialize({\n startOnLoad: false,\n theme: 'base',\n securityLevel: 'loose',\n suppressErrorRendering: true, // Prevent mermaid from appending errors to body\n fontFamily: 'Inter, system-ui, sans-serif',\n flowchart: {\n useMaxWidth: true,\n htmlLabels: true,\n curve: 'basis',\n },\n themeVariables,\n });\n\n const renderChart = async () => {\n if (!mermaidRef.current || !chart) return;\n\n // Validate code completeness\n if (!isMermaidCodeComplete(chart)) {\n setIsRendering(true);\n return;\n }\n\n try {\n setIsRendering(true);\n\n // Clear container\n if (mermaidRef.current) {\n mermaidRef.current.innerHTML = '';\n }\n\n const id = `mermaid-${Math.random().toString(36).substring(2, 9)}`;\n const { svg } = await mermaid.render(id, chart);\n\n if (mermaidRef.current) {\n const textColor = theme === 'dark'\n ? getCSSVariable('--foreground') || 'hsl(0 0% 90%)'\n : getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)';\n\n const processedSvg = svg.replace(\n /<svg /,\n `<svg style=\"--mermaid-text-color: ${textColor};\" `\n );\n\n mermaidRef.current.innerHTML = processedSvg;\n setSvgContent(processedSvg);\n\n applyMermaidTextColors(mermaidRef.current, textColor);\n\n const svgElement = mermaidRef.current.querySelector('svg');\n if (svgElement) {\n svgElement.style.maxWidth = '100%';\n svgElement.style.height = 'auto';\n svgElement.style.display = 'block';\n setIsVertical(isVerticalDiagram(svgElement));\n }\n }\n\n setIsRendering(false);\n } catch (error) {\n console.error('Mermaid rendering error:', error);\n setIsRendering(false);\n cleanupMermaidErrors();\n\n if (mermaidRef.current) {\n mermaidRef.current.innerHTML = `\n <div class=\"p-4 text-destructive bg-destructive/10 border border-destructive/20 rounded-sm\">\n <p class=\"font-semibold\">Mermaid Diagram Error</p>\n <p class=\"text-sm\">${error instanceof Error ? error.message : 'Unknown error'}</p>\n </div>\n `;\n }\n }\n };\n\n // Clear previous timer\n if (renderTimerRef.current) {\n clearTimeout(renderTimerRef.current);\n }\n\n // Debounce: wait 500ms after last update\n renderTimerRef.current = setTimeout(() => {\n renderChart();\n }, 500);\n\n return () => {\n if (renderTimerRef.current) {\n clearTimeout(renderTimerRef.current);\n }\n };\n }, [chart, theme, isCompact, isMermaidCodeComplete, cleanupMermaidErrors]);\n\n return {\n mermaidRef,\n svgContent,\n isVertical,\n isRendering,\n };\n}\n","'use client';\n\nimport React from 'react';\n\nimport { useResolvedTheme } from '@djangocfg/ui-core/hooks';\nimport { MermaidFullscreenModal } from './components/MermaidFullscreenModal';\nimport { useMermaidFullscreen } from './hooks/useMermaidFullscreen';\nimport { useMermaidRenderer } from './hooks/useMermaidRenderer';\n\ninterface MermaidProps {\n chart: string;\n className?: string;\n isCompact?: boolean;\n}\n\nconst Mermaid: React.FC<MermaidProps> = ({ chart, className = '', isCompact = false }) => {\n const theme = useResolvedTheme();\n\n // Rendering logic\n const { mermaidRef, svgContent, isVertical, isRendering } = useMermaidRenderer({\n chart,\n theme,\n isCompact,\n });\n\n // Fullscreen modal logic\n const {\n isFullscreen,\n fullscreenRef,\n openFullscreen,\n closeFullscreen,\n handleBackdropClick,\n } = useMermaidFullscreen();\n\n const handleClick = () => {\n if (svgContent) {\n openFullscreen();\n }\n };\n\n return (\n <>\n <div\n className={`relative bg-card rounded-sm border border-border overflow-hidden cursor-pointer hover:shadow-sm transition-shadow ${className}`}\n onClick={handleClick}\n >\n <div className=\"p-4 border-b border-border bg-muted/50\">\n <h6 className=\"text-sm font-semibold text-foreground\">Diagram</h6>\n <p className=\"text-xs text-muted-foreground mt-1\">Click to view fullscreen</p>\n </div>\n <div className=\"relative p-4 overflow-hidden\">\n <div\n ref={mermaidRef}\n className=\"flex justify-center items-center min-h-[200px]\"\n style={{ isolation: 'isolate' }}\n />\n {isRendering && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-background/50 backdrop-blur-sm\">\n <div className=\"flex flex-col items-center gap-2\">\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-primary\"></div>\n <p className=\"text-xs text-muted-foreground\">Rendering diagram...</p>\n </div>\n </div>\n )}\n </div>\n </div>\n\n <MermaidFullscreenModal\n isOpen={isFullscreen}\n svgContent={svgContent}\n isVertical={isVertical}\n theme={theme}\n chart={chart}\n fullscreenRef={fullscreenRef}\n onClose={closeFullscreen}\n onBackdropClick={handleBackdropClick}\n />\n </>\n );\n};\n\nexport default Mermaid;\n"]}
|