@djangocfg/ui-tools 2.1.110 → 2.1.111
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/README.md +242 -49
- package/dist/JsonSchemaForm-65NLLK56.mjs +4 -0
- package/dist/JsonSchemaForm-65NLLK56.mjs.map +1 -0
- package/dist/JsonSchemaForm-PY6DH3HE.cjs +13 -0
- package/dist/JsonSchemaForm-PY6DH3HE.cjs.map +1 -0
- package/dist/JsonTree-6RYAOPSS.mjs +4 -0
- package/dist/JsonTree-6RYAOPSS.mjs.map +1 -0
- package/dist/JsonTree-7OH6CIHT.cjs +10 -0
- package/dist/JsonTree-7OH6CIHT.cjs.map +1 -0
- package/dist/MapContainer-GXQLP5WY.mjs +214 -0
- package/dist/MapContainer-GXQLP5WY.mjs.map +1 -0
- package/dist/MapContainer-RYG4HPH4.cjs +221 -0
- package/dist/MapContainer-RYG4HPH4.cjs.map +1 -0
- package/dist/{Mermaid.client-4OCKJ6QD.mjs → Mermaid.client-OKACITCW.mjs} +16 -7
- package/dist/Mermaid.client-OKACITCW.mjs.map +1 -0
- package/dist/{Mermaid.client-ZP6OE46Z.cjs → Mermaid.client-PNXEC6YL.cjs} +16 -7
- package/dist/Mermaid.client-PNXEC6YL.cjs.map +1 -0
- package/dist/{PlaygroundLayout-XXVBU4WZ.cjs → PlaygroundLayout-SYMEAG3J.cjs} +25 -24
- package/dist/PlaygroundLayout-SYMEAG3J.cjs.map +1 -0
- package/dist/{PlaygroundLayout-LMQTVXSP.mjs → PlaygroundLayout-UQRBU5RH.mjs} +4 -3
- package/dist/PlaygroundLayout-UQRBU5RH.mjs.map +1 -0
- package/dist/{PrettyCode.client-2CLSV2VD.cjs → PrettyCode.client-DANYYQYO.cjs} +11 -4
- package/dist/PrettyCode.client-DANYYQYO.cjs.map +1 -0
- package/dist/{PrettyCode.client-Y2BVON7R.mjs → PrettyCode.client-RS5ZTNBT.mjs} +11 -4
- package/dist/PrettyCode.client-RS5ZTNBT.mjs.map +1 -0
- package/dist/chunk-2DSR7V2L.mjs +561 -0
- package/dist/chunk-2DSR7V2L.mjs.map +1 -0
- package/dist/chunk-47T5ECYV.cjs +1357 -0
- package/dist/chunk-47T5ECYV.cjs.map +1 -0
- package/dist/chunk-5QT3QYFZ.cjs +189 -0
- package/dist/chunk-5QT3QYFZ.cjs.map +1 -0
- package/dist/chunk-7IIRYG4S.mjs +1057 -0
- package/dist/chunk-7IIRYG4S.mjs.map +1 -0
- package/dist/{chunk-FB5QBSI3.cjs → chunk-DI3HUXHK.cjs} +15 -195
- package/dist/chunk-DI3HUXHK.cjs.map +1 -0
- package/dist/chunk-EVGWYASL.cjs +1528 -0
- package/dist/chunk-EVGWYASL.cjs.map +1 -0
- package/dist/chunk-F2N7P5XU.cjs +30 -0
- package/dist/chunk-F2N7P5XU.cjs.map +1 -0
- package/dist/{chunk-L6UHASYQ.mjs → chunk-G6PRZP5I.mjs} +7 -186
- package/dist/chunk-G6PRZP5I.mjs.map +1 -0
- package/dist/chunk-JWB2EWQO.mjs +5 -0
- package/dist/chunk-JWB2EWQO.mjs.map +1 -0
- package/dist/chunk-LTJX2JXE.mjs +338 -0
- package/dist/chunk-LTJX2JXE.mjs.map +1 -0
- package/dist/chunk-OVNC4KW6.mjs +1494 -0
- package/dist/chunk-OVNC4KW6.mjs.map +1 -0
- package/dist/chunk-PNZSJN6T.cjs +1086 -0
- package/dist/chunk-PNZSJN6T.cjs.map +1 -0
- package/dist/chunk-TEFRA7GW.cjs +565 -0
- package/dist/chunk-TEFRA7GW.cjs.map +1 -0
- package/dist/chunk-UOMPPIED.mjs +1343 -0
- package/dist/chunk-UOMPPIED.mjs.map +1 -0
- package/dist/chunk-W6YHQI4F.mjs +187 -0
- package/dist/chunk-W6YHQI4F.mjs.map +1 -0
- package/dist/chunk-XTBRWVIV.cjs +346 -0
- package/dist/chunk-XTBRWVIV.cjs.map +1 -0
- package/dist/components-C7ZL7OMY.mjs +5 -0
- package/dist/components-C7ZL7OMY.mjs.map +1 -0
- package/dist/components-CJ2IB65O.cjs +27 -0
- package/dist/components-CJ2IB65O.cjs.map +1 -0
- package/dist/components-EASJYK45.mjs +6 -0
- package/dist/components-EASJYK45.mjs.map +1 -0
- package/dist/components-LDRFDV4A.cjs +22 -0
- package/dist/components-LDRFDV4A.cjs.map +1 -0
- package/dist/components-VZKUTDJK.mjs +5 -0
- package/dist/components-VZKUTDJK.mjs.map +1 -0
- package/dist/components-Y64GTIMQ.cjs +42 -0
- package/dist/components-Y64GTIMQ.cjs.map +1 -0
- package/dist/index.cjs +701 -4813
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1274 -1026
- package/dist/index.d.ts +1274 -1026
- package/dist/index.mjs +358 -4730
- package/dist/index.mjs.map +1 -1
- package/package.json +27 -4
- package/src/components/index.ts +17 -0
- package/src/components/lazy-wrapper.tsx +281 -0
- package/src/index.ts +92 -7
- package/src/tools/AudioPlayer/components/HybridAudioPlayer.tsx +14 -5
- package/src/tools/AudioPlayer/lazy.tsx +85 -0
- package/src/tools/Gallery/components/Gallery.tsx +182 -0
- package/src/tools/Gallery/components/GalleryCarousel.tsx +251 -0
- package/src/tools/Gallery/components/GalleryCompact.tsx +173 -0
- package/src/tools/Gallery/components/GalleryGrid.tsx +493 -0
- package/src/tools/Gallery/components/GalleryImage.tsx +66 -0
- package/src/tools/Gallery/components/GalleryLightbox.tsx +331 -0
- package/src/tools/Gallery/components/GalleryMedia.tsx +66 -0
- package/src/tools/Gallery/components/GalleryThumbnails.tsx +173 -0
- package/src/tools/Gallery/components/GalleryThumbnailsVirtual.tsx +138 -0
- package/src/tools/Gallery/components/GalleryVideo.tsx +222 -0
- package/src/tools/Gallery/components/index.ts +13 -0
- package/src/tools/Gallery/hooks/index.ts +23 -0
- package/src/tools/Gallery/hooks/useGallery.ts +137 -0
- package/src/tools/Gallery/hooks/useImageDimensions.ts +223 -0
- package/src/tools/Gallery/hooks/usePinchZoom.ts +234 -0
- package/src/tools/Gallery/hooks/usePreloadImages.ts +71 -0
- package/src/tools/Gallery/hooks/useSwipe.ts +86 -0
- package/src/tools/Gallery/hooks/useVirtualList.ts +129 -0
- package/src/tools/Gallery/hooks/useZoom.ts +316 -0
- package/src/tools/Gallery/index.ts +66 -0
- package/src/tools/Gallery/types.ts +183 -0
- package/src/tools/Gallery/utils/imageAnalysis.ts +52 -0
- package/src/tools/Gallery/utils/index.ts +11 -0
- package/src/tools/ImageViewer/components/ImageToolbar.tsx +20 -8
- package/src/tools/ImageViewer/components/ImageViewer.tsx +12 -4
- package/src/tools/ImageViewer/lazy.tsx +37 -0
- package/src/tools/JsonForm/lazy.tsx +43 -0
- package/src/tools/JsonForm/widgets/ColorWidget.tsx +4 -1
- package/src/tools/JsonTree/lazy.tsx +45 -0
- package/src/tools/LottiePlayer/lazy.tsx +57 -0
- package/src/tools/Map/components/CustomOverlay.tsx +54 -0
- package/src/tools/Map/components/DrawControl.tsx +36 -0
- package/src/tools/Map/components/GeocoderControl.tsx +70 -0
- package/src/tools/Map/components/LayerSwitcher.tsx +225 -0
- package/src/tools/Map/components/MapCluster.tsx +273 -0
- package/src/tools/Map/components/MapContainer.tsx +191 -0
- package/src/tools/Map/components/MapControls.tsx +44 -0
- package/src/tools/Map/components/MapLegend.tsx +161 -0
- package/src/tools/Map/components/MapMarker.tsx +102 -0
- package/src/tools/Map/components/MapPopup.tsx +46 -0
- package/src/tools/Map/components/MapSource.tsx +30 -0
- package/src/tools/Map/components/index.ts +20 -0
- package/src/tools/Map/context/MapContext.tsx +89 -0
- package/src/tools/Map/context/index.ts +2 -0
- package/src/tools/Map/hooks/index.ts +9 -0
- package/src/tools/Map/hooks/useMap.ts +11 -0
- package/src/tools/Map/hooks/useMapControl.ts +99 -0
- package/src/tools/Map/hooks/useMapEvents.ts +147 -0
- package/src/tools/Map/hooks/useMapLayers.ts +83 -0
- package/src/tools/Map/hooks/useMapViewport.ts +62 -0
- package/src/tools/Map/hooks/useMarkers.ts +85 -0
- package/src/tools/Map/index.ts +116 -0
- package/src/tools/Map/layers/cluster.ts +94 -0
- package/src/tools/Map/layers/index.ts +15 -0
- package/src/tools/Map/layers/line.ts +93 -0
- package/src/tools/Map/layers/point.ts +61 -0
- package/src/tools/Map/layers/polygon.ts +73 -0
- package/src/tools/Map/lazy.tsx +56 -0
- package/src/tools/Map/styles/index.ts +15 -0
- package/src/tools/Map/types.ts +259 -0
- package/src/tools/Map/utils/geo.ts +88 -0
- package/src/tools/Map/utils/index.ts +16 -0
- package/src/tools/Map/utils/transform.ts +107 -0
- package/src/tools/Mermaid/Mermaid.client.tsx +12 -4
- package/src/tools/Mermaid/components/MermaidFullscreenModal.tsx +6 -2
- package/src/tools/Mermaid/lazy.tsx +46 -0
- package/src/tools/OpenapiViewer/lazy.tsx +72 -0
- package/src/tools/PrettyCode/PrettyCode.client.tsx +10 -3
- package/src/tools/PrettyCode/lazy.tsx +64 -0
- package/src/tools/VideoPlayer/lazy.tsx +63 -0
- package/dist/Mermaid.client-4OCKJ6QD.mjs.map +0 -1
- package/dist/Mermaid.client-ZP6OE46Z.cjs.map +0 -1
- package/dist/PlaygroundLayout-LMQTVXSP.mjs.map +0 -1
- package/dist/PlaygroundLayout-XXVBU4WZ.cjs.map +0 -1
- package/dist/PrettyCode.client-2CLSV2VD.cjs.map +0 -1
- package/dist/PrettyCode.client-Y2BVON7R.mjs.map +0 -1
- package/dist/chunk-FB5QBSI3.cjs.map +0 -1
- package/dist/chunk-L6UHASYQ.mjs.map +0 -1
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkWGEGR3DF_cjs = require('./chunk-WGEGR3DF.cjs');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var Map = require('react-map-gl/maplibre');
|
|
6
|
+
var lucideReact = require('lucide-react');
|
|
7
|
+
var lib = require('@djangocfg/ui-core/lib');
|
|
8
|
+
require('maplibre-gl/dist/maplibre-gl.css');
|
|
9
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
10
|
+
|
|
11
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
|
|
13
|
+
var Map__default = /*#__PURE__*/_interopDefault(Map);
|
|
14
|
+
|
|
15
|
+
var MapContext = react.createContext(null);
|
|
16
|
+
var DEFAULT_VIEWPORT = {
|
|
17
|
+
longitude: 115.1889,
|
|
18
|
+
latitude: -8.4095,
|
|
19
|
+
zoom: 10,
|
|
20
|
+
bearing: 0,
|
|
21
|
+
pitch: 0
|
|
22
|
+
};
|
|
23
|
+
function MapProvider({ children, initialViewport }) {
|
|
24
|
+
const mapRef = react.useRef(null);
|
|
25
|
+
const initialViewportRef = react.useRef({
|
|
26
|
+
...DEFAULT_VIEWPORT,
|
|
27
|
+
...initialViewport
|
|
28
|
+
});
|
|
29
|
+
const [viewport, setViewportState] = react.useState(initialViewportRef.current);
|
|
30
|
+
const [markers, setMarkers] = react.useState([]);
|
|
31
|
+
const [selectedMarker, setSelectedMarker] = react.useState(null);
|
|
32
|
+
const [hoveredFeature, setHoveredFeature] = react.useState(null);
|
|
33
|
+
const [isLoaded, setIsLoaded] = react.useState(false);
|
|
34
|
+
const setViewport = react.useCallback((newViewport) => {
|
|
35
|
+
setViewportState((prev) => ({ ...prev, ...newViewport }));
|
|
36
|
+
}, []);
|
|
37
|
+
const resetToInitial = react.useCallback(() => {
|
|
38
|
+
const map = mapRef.current;
|
|
39
|
+
if (map) {
|
|
40
|
+
map.flyTo({
|
|
41
|
+
center: [initialViewportRef.current.longitude, initialViewportRef.current.latitude],
|
|
42
|
+
zoom: initialViewportRef.current.zoom,
|
|
43
|
+
bearing: initialViewportRef.current.bearing ?? 0,
|
|
44
|
+
pitch: initialViewportRef.current.pitch ?? 0,
|
|
45
|
+
duration: 1e3
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}, []);
|
|
49
|
+
const value = react.useMemo(
|
|
50
|
+
() => ({
|
|
51
|
+
mapRef,
|
|
52
|
+
viewport,
|
|
53
|
+
setViewport,
|
|
54
|
+
initialViewport: initialViewportRef.current,
|
|
55
|
+
resetToInitial,
|
|
56
|
+
markers,
|
|
57
|
+
setMarkers,
|
|
58
|
+
selectedMarker,
|
|
59
|
+
setSelectedMarker,
|
|
60
|
+
hoveredFeature,
|
|
61
|
+
setHoveredFeature,
|
|
62
|
+
isLoaded,
|
|
63
|
+
setIsLoaded
|
|
64
|
+
}),
|
|
65
|
+
[viewport, setViewport, resetToInitial, markers, selectedMarker, hoveredFeature, isLoaded]
|
|
66
|
+
);
|
|
67
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MapContext.Provider, { value, children });
|
|
68
|
+
}
|
|
69
|
+
chunkWGEGR3DF_cjs.__name(MapProvider, "MapProvider");
|
|
70
|
+
function useMapContext() {
|
|
71
|
+
const context = react.useContext(MapContext);
|
|
72
|
+
if (!context) {
|
|
73
|
+
throw new Error("useMapContext must be used within a MapProvider");
|
|
74
|
+
}
|
|
75
|
+
return context;
|
|
76
|
+
}
|
|
77
|
+
chunkWGEGR3DF_cjs.__name(useMapContext, "useMapContext");
|
|
78
|
+
|
|
79
|
+
// src/tools/Map/styles/index.ts
|
|
80
|
+
var MAP_STYLES = {
|
|
81
|
+
light: "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json",
|
|
82
|
+
dark: "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json",
|
|
83
|
+
streets: "https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json",
|
|
84
|
+
satellite: "https://api.maptiler.com/maps/satellite/style.json"
|
|
85
|
+
};
|
|
86
|
+
function MapInner({
|
|
87
|
+
children,
|
|
88
|
+
mapStyle = "light",
|
|
89
|
+
interactiveLayerIds,
|
|
90
|
+
style,
|
|
91
|
+
cursor,
|
|
92
|
+
attributionControl = true,
|
|
93
|
+
reuseMaps = true,
|
|
94
|
+
openInMapsUrl,
|
|
95
|
+
openInMapsLabel = "Open in Maps",
|
|
96
|
+
autoResetDelay = 0,
|
|
97
|
+
showResetButton = false
|
|
98
|
+
}) {
|
|
99
|
+
const { mapRef, viewport, setViewport, setIsLoaded, resetToInitial, initialViewport } = useMapContext();
|
|
100
|
+
const resetTimerRef = react.useRef(null);
|
|
101
|
+
const isInteractingRef = react.useRef(false);
|
|
102
|
+
const hasViewportChanged = Math.abs(viewport.longitude - initialViewport.longitude) > 1e-4 || Math.abs(viewport.latitude - initialViewport.latitude) > 1e-4 || Math.abs(viewport.zoom - initialViewport.zoom) > 0.1;
|
|
103
|
+
const handleMove = react.useCallback(
|
|
104
|
+
(evt) => {
|
|
105
|
+
setViewport({
|
|
106
|
+
longitude: evt.viewState.longitude,
|
|
107
|
+
latitude: evt.viewState.latitude,
|
|
108
|
+
zoom: evt.viewState.zoom,
|
|
109
|
+
bearing: evt.viewState.bearing,
|
|
110
|
+
pitch: evt.viewState.pitch
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
[setViewport]
|
|
114
|
+
);
|
|
115
|
+
const handleMoveStart = react.useCallback(() => {
|
|
116
|
+
isInteractingRef.current = true;
|
|
117
|
+
if (resetTimerRef.current) {
|
|
118
|
+
clearTimeout(resetTimerRef.current);
|
|
119
|
+
resetTimerRef.current = null;
|
|
120
|
+
}
|
|
121
|
+
}, []);
|
|
122
|
+
const handleMoveEnd = react.useCallback(() => {
|
|
123
|
+
isInteractingRef.current = false;
|
|
124
|
+
if (autoResetDelay > 0) {
|
|
125
|
+
resetTimerRef.current = setTimeout(() => {
|
|
126
|
+
if (!isInteractingRef.current) {
|
|
127
|
+
resetToInitial();
|
|
128
|
+
}
|
|
129
|
+
}, autoResetDelay);
|
|
130
|
+
}
|
|
131
|
+
}, [autoResetDelay, resetToInitial]);
|
|
132
|
+
const handleLoad = react.useCallback(() => {
|
|
133
|
+
setIsLoaded(true);
|
|
134
|
+
}, [setIsLoaded]);
|
|
135
|
+
react.useEffect(() => {
|
|
136
|
+
return () => {
|
|
137
|
+
if (resetTimerRef.current) {
|
|
138
|
+
clearTimeout(resetTimerRef.current);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}, []);
|
|
142
|
+
const resolvedStyle = mapStyle in MAP_STYLES ? MAP_STYLES[mapStyle] : mapStyle;
|
|
143
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
144
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
145
|
+
Map__default.default,
|
|
146
|
+
{
|
|
147
|
+
ref: mapRef,
|
|
148
|
+
...viewport,
|
|
149
|
+
onMove: handleMove,
|
|
150
|
+
onMoveStart: handleMoveStart,
|
|
151
|
+
onMoveEnd: handleMoveEnd,
|
|
152
|
+
onLoad: handleLoad,
|
|
153
|
+
mapStyle: resolvedStyle,
|
|
154
|
+
interactiveLayerIds,
|
|
155
|
+
attributionControl: attributionControl ? {} : false,
|
|
156
|
+
reuseMaps,
|
|
157
|
+
style: {
|
|
158
|
+
width: "100%",
|
|
159
|
+
height: "100%",
|
|
160
|
+
...style
|
|
161
|
+
},
|
|
162
|
+
cursor,
|
|
163
|
+
children
|
|
164
|
+
}
|
|
165
|
+
),
|
|
166
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-3 right-3 flex items-center gap-2", children: [
|
|
167
|
+
showResetButton && hasViewportChanged && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
168
|
+
"button",
|
|
169
|
+
{
|
|
170
|
+
type: "button",
|
|
171
|
+
onClick: resetToInitial,
|
|
172
|
+
className: lib.cn(
|
|
173
|
+
"inline-flex items-center gap-2 px-3 py-2 rounded-lg",
|
|
174
|
+
"bg-background/95 backdrop-blur-sm text-foreground text-sm font-medium",
|
|
175
|
+
"hover:bg-background transition-colors shadow-sm border border-border"
|
|
176
|
+
),
|
|
177
|
+
children: [
|
|
178
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { className: "w-4 h-4" }),
|
|
179
|
+
"Reset"
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
),
|
|
183
|
+
openInMapsUrl && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
184
|
+
"a",
|
|
185
|
+
{
|
|
186
|
+
href: openInMapsUrl,
|
|
187
|
+
target: "_blank",
|
|
188
|
+
rel: "noopener noreferrer",
|
|
189
|
+
className: lib.cn(
|
|
190
|
+
"inline-flex items-center gap-2 px-4 py-2 rounded-lg",
|
|
191
|
+
"bg-background/95 backdrop-blur-sm text-foreground text-sm font-medium",
|
|
192
|
+
"hover:bg-background transition-colors shadow-sm border border-border"
|
|
193
|
+
),
|
|
194
|
+
children: [
|
|
195
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "w-4 h-4" }),
|
|
196
|
+
openInMapsLabel
|
|
197
|
+
]
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
] })
|
|
201
|
+
] });
|
|
202
|
+
}
|
|
203
|
+
chunkWGEGR3DF_cjs.__name(MapInner, "MapInner");
|
|
204
|
+
function MapContainer({
|
|
205
|
+
children,
|
|
206
|
+
initialViewport,
|
|
207
|
+
className,
|
|
208
|
+
...props
|
|
209
|
+
}) {
|
|
210
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { width: "100%", height: "100%", position: "relative" }, children: /* @__PURE__ */ jsxRuntime.jsx(MapProvider, { initialViewport, children: /* @__PURE__ */ jsxRuntime.jsx(MapInner, { ...props, children }) }) });
|
|
211
|
+
}
|
|
212
|
+
chunkWGEGR3DF_cjs.__name(MapContainer, "MapContainer");
|
|
213
|
+
function MapView(props) {
|
|
214
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MapInner, { ...props });
|
|
215
|
+
}
|
|
216
|
+
chunkWGEGR3DF_cjs.__name(MapView, "MapView");
|
|
217
|
+
|
|
218
|
+
exports.MapContainer = MapContainer;
|
|
219
|
+
exports.MapView = MapView;
|
|
220
|
+
//# sourceMappingURL=MapContainer-RYG4HPH4.cjs.map
|
|
221
|
+
//# sourceMappingURL=MapContainer-RYG4HPH4.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tools/Map/context/MapContext.tsx","../src/tools/Map/styles/index.ts","../src/tools/Map/components/MapContainer.tsx"],"names":["createContext","useRef","useState","useCallback","useMemo","jsx","__name","useContext","useEffect","jsxs","Fragment","Map","cn","RotateCcw","ExternalLink"],"mappings":"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","file":"MapContainer-RYG4HPH4.cjs","sourcesContent":["'use client'\n\nimport {\n createContext,\n useContext,\n useState,\n useRef,\n useMemo,\n useCallback,\n type ReactNode,\n} from 'react'\nimport type { MapRef } from 'react-map-gl/maplibre'\nimport type { MapContextValue, MapViewport, MarkerData } from '../types'\n\nconst MapContext = createContext<MapContextValue | null>(null)\n\nexport interface MapProviderProps {\n children: ReactNode\n initialViewport?: Partial<MapViewport>\n}\n\nconst DEFAULT_VIEWPORT: MapViewport = {\n longitude: 115.1889,\n latitude: -8.4095,\n zoom: 10,\n bearing: 0,\n pitch: 0,\n}\n\nexport function MapProvider({ children, initialViewport }: MapProviderProps) {\n const mapRef = useRef<MapRef | null>(null)\n const initialViewportRef = useRef<MapViewport>({\n ...DEFAULT_VIEWPORT,\n ...initialViewport,\n })\n const [viewport, setViewportState] = useState<MapViewport>(initialViewportRef.current)\n const [markers, setMarkers] = useState<MarkerData[]>([])\n const [selectedMarker, setSelectedMarker] = useState<MarkerData | null>(null)\n const [hoveredFeature, setHoveredFeature] = useState<GeoJSON.Feature | null>(null)\n const [isLoaded, setIsLoaded] = useState(false)\n\n const setViewport = useCallback((newViewport: Partial<MapViewport>) => {\n setViewportState((prev) => ({ ...prev, ...newViewport }))\n }, [])\n\n const resetToInitial = useCallback(() => {\n const map = mapRef.current\n if (map) {\n map.flyTo({\n center: [initialViewportRef.current.longitude, initialViewportRef.current.latitude],\n zoom: initialViewportRef.current.zoom,\n bearing: initialViewportRef.current.bearing ?? 0,\n pitch: initialViewportRef.current.pitch ?? 0,\n duration: 1000,\n })\n }\n }, [])\n\n const value = useMemo<MapContextValue>(\n () => ({\n mapRef,\n viewport,\n setViewport,\n initialViewport: initialViewportRef.current,\n resetToInitial,\n markers,\n setMarkers,\n selectedMarker,\n setSelectedMarker,\n hoveredFeature,\n setHoveredFeature,\n isLoaded,\n setIsLoaded,\n }),\n [viewport, setViewport, resetToInitial, markers, selectedMarker, hoveredFeature, isLoaded]\n )\n\n return <MapContext.Provider value={value}>{children}</MapContext.Provider>\n}\n\nexport function useMapContext(): MapContextValue {\n const context = useContext(MapContext)\n if (!context) {\n throw new Error('useMapContext must be used within a MapProvider')\n }\n return context\n}\n\nexport { MapContext }\n","export const MAP_STYLES = {\n light: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',\n dark: 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',\n streets: 'https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json',\n satellite: 'https://api.maptiler.com/maps/satellite/style.json',\n} as const\n\nexport type MapStyleKey = keyof typeof MAP_STYLES\n\nexport function getMapStyle(key: MapStyleKey | string): string {\n if (key in MAP_STYLES) {\n return MAP_STYLES[key as MapStyleKey]\n }\n return key\n}\n","'use client'\n\nimport { useCallback, useEffect, useRef, type ReactNode } from 'react'\nimport Map, { type ViewStateChangeEvent } from 'react-map-gl/maplibre'\nimport { ExternalLink, RotateCcw } from 'lucide-react'\nimport { cn } from '@djangocfg/ui-core/lib'\nimport 'maplibre-gl/dist/maplibre-gl.css'\n\nimport { MapProvider, useMapContext } from '../context'\nimport { MAP_STYLES } from '../styles'\nimport type { MapViewport, MapStyleKey } from '../types'\n\nexport interface MapContainerProps {\n children?: ReactNode\n initialViewport?: Partial<MapViewport>\n mapStyle?: MapStyleKey | string\n interactiveLayerIds?: string[]\n className?: string\n style?: React.CSSProperties\n cursor?: string\n attributionControl?: boolean\n reuseMaps?: boolean\n /** URL to open in external maps app (shows \"Open in Maps\" button if provided) */\n openInMapsUrl?: string\n /** Label for the open in maps button */\n openInMapsLabel?: string\n /** Auto-reset to initial viewport after N ms of inactivity (0 = disabled) */\n autoResetDelay?: number\n /** Show reset button */\n showResetButton?: boolean\n}\n\ninterface MapInnerProps extends Omit<MapContainerProps, 'initialViewport'> {}\n\nfunction MapInner({\n children,\n mapStyle = 'light',\n interactiveLayerIds,\n style,\n cursor,\n attributionControl = true,\n reuseMaps = true,\n openInMapsUrl,\n openInMapsLabel = 'Open in Maps',\n autoResetDelay = 0,\n showResetButton = false,\n}: MapInnerProps) {\n const { mapRef, viewport, setViewport, setIsLoaded, resetToInitial, initialViewport } = useMapContext()\n const resetTimerRef = useRef<NodeJS.Timeout | null>(null)\n const isInteractingRef = useRef(false)\n\n // Check if viewport has changed from initial\n const hasViewportChanged =\n Math.abs(viewport.longitude - initialViewport.longitude) > 0.0001 ||\n Math.abs(viewport.latitude - initialViewport.latitude) > 0.0001 ||\n Math.abs(viewport.zoom - initialViewport.zoom) > 0.1\n\n const handleMove = useCallback(\n (evt: ViewStateChangeEvent) => {\n setViewport({\n longitude: evt.viewState.longitude,\n latitude: evt.viewState.latitude,\n zoom: evt.viewState.zoom,\n bearing: evt.viewState.bearing,\n pitch: evt.viewState.pitch,\n })\n },\n [setViewport]\n )\n\n const handleMoveStart = useCallback(() => {\n isInteractingRef.current = true\n // Clear any pending reset timer\n if (resetTimerRef.current) {\n clearTimeout(resetTimerRef.current)\n resetTimerRef.current = null\n }\n }, [])\n\n const handleMoveEnd = useCallback(() => {\n isInteractingRef.current = false\n // Start auto-reset timer if enabled\n if (autoResetDelay > 0) {\n resetTimerRef.current = setTimeout(() => {\n if (!isInteractingRef.current) {\n resetToInitial()\n }\n }, autoResetDelay)\n }\n }, [autoResetDelay, resetToInitial])\n\n const handleLoad = useCallback(() => {\n setIsLoaded(true)\n }, [setIsLoaded])\n\n // Cleanup timer on unmount\n useEffect(() => {\n return () => {\n if (resetTimerRef.current) {\n clearTimeout(resetTimerRef.current)\n }\n }\n }, [])\n\n const resolvedStyle = mapStyle in MAP_STYLES\n ? MAP_STYLES[mapStyle as MapStyleKey]\n : mapStyle\n\n return (\n <>\n <Map\n ref={mapRef}\n {...viewport}\n onMove={handleMove}\n onMoveStart={handleMoveStart}\n onMoveEnd={handleMoveEnd}\n onLoad={handleLoad}\n mapStyle={resolvedStyle}\n interactiveLayerIds={interactiveLayerIds}\n attributionControl={attributionControl ? {} : false}\n reuseMaps={reuseMaps}\n style={{\n width: '100%',\n height: '100%',\n ...style,\n }}\n cursor={cursor}\n >\n {children}\n </Map>\n\n {/* Map overlay buttons */}\n <div className=\"absolute bottom-3 right-3 flex items-center gap-2\">\n {/* Reset button */}\n {showResetButton && hasViewportChanged && (\n <button\n type=\"button\"\n onClick={resetToInitial}\n className={cn(\n 'inline-flex items-center gap-2 px-3 py-2 rounded-lg',\n 'bg-background/95 backdrop-blur-sm text-foreground text-sm font-medium',\n 'hover:bg-background transition-colors shadow-sm border border-border'\n )}\n >\n <RotateCcw className=\"w-4 h-4\" />\n Reset\n </button>\n )}\n\n {/* Open in Maps button */}\n {openInMapsUrl && (\n <a\n href={openInMapsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n 'inline-flex items-center gap-2 px-4 py-2 rounded-lg',\n 'bg-background/95 backdrop-blur-sm text-foreground text-sm font-medium',\n 'hover:bg-background transition-colors shadow-sm border border-border'\n )}\n >\n <ExternalLink className=\"w-4 h-4\" />\n {openInMapsLabel}\n </a>\n )}\n </div>\n </>\n )\n}\n\nexport function MapContainer({\n children,\n initialViewport,\n className,\n ...props\n}: MapContainerProps) {\n return (\n <div className={className} style={{ width: '100%', height: '100%', position: 'relative' }}>\n <MapProvider initialViewport={initialViewport}>\n <MapInner {...props}>{children}</MapInner>\n </MapProvider>\n </div>\n )\n}\n\n/**\n * Use this when you need the map inside an existing MapProvider\n */\nexport function MapView(props: Omit<MapContainerProps, 'initialViewport'>) {\n return <MapInner {...props} />\n}\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { __name } from './chunk-CGILA3WO.mjs';
|
|
2
|
+
import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
|
3
|
+
import { useTypedT } from '@djangocfg/i18n';
|
|
2
4
|
import { useResolvedTheme } from '@djangocfg/ui-core/hooks';
|
|
3
|
-
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
4
5
|
import { createPortal } from 'react-dom';
|
|
5
6
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
6
7
|
import mermaid from 'mermaid';
|
|
@@ -82,6 +83,8 @@ var MermaidFullscreenModal = /* @__PURE__ */ __name(({
|
|
|
82
83
|
onClose,
|
|
83
84
|
onBackdropClick
|
|
84
85
|
}) => {
|
|
86
|
+
const t = useTypedT();
|
|
87
|
+
const diagramTitle = useMemo(() => t("tools.diagram.title"), [t]);
|
|
85
88
|
useEffect(() => {
|
|
86
89
|
if (isOpen && fullscreenRef.current) {
|
|
87
90
|
const getCSSVariable = /* @__PURE__ */ __name((variable) => {
|
|
@@ -113,7 +116,7 @@ var MermaidFullscreenModal = /* @__PURE__ */ __name(({
|
|
|
113
116
|
onClick: onBackdropClick,
|
|
114
117
|
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
118
|
/* @__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:
|
|
119
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium text-foreground py-0 my-0", children: diagramTitle }),
|
|
117
120
|
/* @__PURE__ */ jsx(
|
|
118
121
|
"button",
|
|
119
122
|
{
|
|
@@ -409,7 +412,13 @@ function useMermaidRenderer({ chart, theme, isCompact = false }) {
|
|
|
409
412
|
}
|
|
410
413
|
__name(useMermaidRenderer, "useMermaidRenderer");
|
|
411
414
|
var Mermaid = /* @__PURE__ */ __name(({ chart, className = "", isCompact = false }) => {
|
|
415
|
+
const t = useTypedT();
|
|
412
416
|
const theme = useResolvedTheme();
|
|
417
|
+
const labels = useMemo(() => ({
|
|
418
|
+
title: t("tools.diagram.title"),
|
|
419
|
+
clickToView: t("tools.diagram.clickToView"),
|
|
420
|
+
loading: t("ui.form.loading")
|
|
421
|
+
}), [t]);
|
|
413
422
|
const { mermaidRef, svgContent, isVertical, isRendering } = useMermaidRenderer({
|
|
414
423
|
chart,
|
|
415
424
|
theme,
|
|
@@ -435,8 +444,8 @@ var Mermaid = /* @__PURE__ */ __name(({ chart, className = "", isCompact = false
|
|
|
435
444
|
onClick: handleClick,
|
|
436
445
|
children: [
|
|
437
446
|
/* @__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:
|
|
439
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children:
|
|
447
|
+
/* @__PURE__ */ jsx("h6", { className: "text-sm font-semibold text-foreground", children: labels.title }),
|
|
448
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: labels.clickToView })
|
|
440
449
|
] }),
|
|
441
450
|
/* @__PURE__ */ jsxs("div", { className: "relative p-4 overflow-hidden", children: [
|
|
442
451
|
/* @__PURE__ */ jsx(
|
|
@@ -449,7 +458,7 @@ var Mermaid = /* @__PURE__ */ __name(({ chart, className = "", isCompact = false
|
|
|
449
458
|
),
|
|
450
459
|
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
460
|
/* @__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:
|
|
461
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: labels.loading })
|
|
453
462
|
] }) })
|
|
454
463
|
] })
|
|
455
464
|
]
|
|
@@ -473,5 +482,5 @@ var Mermaid = /* @__PURE__ */ __name(({ chart, className = "", isCompact = false
|
|
|
473
482
|
var Mermaid_client_default = Mermaid;
|
|
474
483
|
|
|
475
484
|
export { Mermaid_client_default as default };
|
|
476
|
-
//# sourceMappingURL=Mermaid.client-
|
|
477
|
-
//# sourceMappingURL=Mermaid.client-
|
|
485
|
+
//# sourceMappingURL=Mermaid.client-OKACITCW.mjs.map
|
|
486
|
+
//# sourceMappingURL=Mermaid.client-OKACITCW.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","useTypedT","useMemo","Fragment"],"mappings":"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","file":"Mermaid.client-OKACITCW.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, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { useTypedT, type I18nTranslations } from '@djangocfg/i18n';\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 const t = useTypedT<I18nTranslations>();\n const diagramTitle = useMemo(() => t('tools.diagram.title'), [t]);\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\">{diagramTitle}</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, { useMemo } from 'react';\n\nimport { useTypedT, type I18nTranslations } from '@djangocfg/i18n';\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 t = useTypedT<I18nTranslations>();\n const theme = useResolvedTheme();\n\n const labels = useMemo(() => ({\n title: t('tools.diagram.title'),\n clickToView: t('tools.diagram.clickToView'),\n loading: t('ui.form.loading'),\n }), [t]);\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\">{labels.title}</h6>\n <p className=\"text-xs text-muted-foreground mt-1\">{labels.clickToView}</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\">{labels.loading}</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"]}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkWGEGR3DF_cjs = require('./chunk-WGEGR3DF.cjs');
|
|
4
|
-
var hooks = require('@djangocfg/ui-core/hooks');
|
|
5
4
|
var react = require('react');
|
|
5
|
+
var i18n = require('@djangocfg/i18n');
|
|
6
|
+
var hooks = require('@djangocfg/ui-core/hooks');
|
|
6
7
|
var reactDom = require('react-dom');
|
|
7
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
8
9
|
var mermaid = require('mermaid');
|
|
@@ -88,6 +89,8 @@ var MermaidFullscreenModal = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({
|
|
|
88
89
|
onClose,
|
|
89
90
|
onBackdropClick
|
|
90
91
|
}) => {
|
|
92
|
+
const t = i18n.useTypedT();
|
|
93
|
+
const diagramTitle = react.useMemo(() => t("tools.diagram.title"), [t]);
|
|
91
94
|
react.useEffect(() => {
|
|
92
95
|
if (isOpen && fullscreenRef.current) {
|
|
93
96
|
const getCSSVariable = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((variable) => {
|
|
@@ -119,7 +122,7 @@ var MermaidFullscreenModal = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({
|
|
|
119
122
|
onClick: onBackdropClick,
|
|
120
123
|
children: /* @__PURE__ */ jsxRuntime.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: [
|
|
121
124
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between py-4 px-6 border-b border-border", children: [
|
|
122
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-medium text-foreground py-0 my-0", children:
|
|
125
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-medium text-foreground py-0 my-0", children: diagramTitle }),
|
|
123
126
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
124
127
|
"button",
|
|
125
128
|
{
|
|
@@ -415,7 +418,13 @@ function useMermaidRenderer({ chart, theme, isCompact = false }) {
|
|
|
415
418
|
}
|
|
416
419
|
chunkWGEGR3DF_cjs.__name(useMermaidRenderer, "useMermaidRenderer");
|
|
417
420
|
var Mermaid = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ chart, className = "", isCompact = false }) => {
|
|
421
|
+
const t = i18n.useTypedT();
|
|
418
422
|
const theme = hooks.useResolvedTheme();
|
|
423
|
+
const labels = react.useMemo(() => ({
|
|
424
|
+
title: t("tools.diagram.title"),
|
|
425
|
+
clickToView: t("tools.diagram.clickToView"),
|
|
426
|
+
loading: t("ui.form.loading")
|
|
427
|
+
}), [t]);
|
|
419
428
|
const { mermaidRef, svgContent, isVertical, isRendering } = useMermaidRenderer({
|
|
420
429
|
chart,
|
|
421
430
|
theme,
|
|
@@ -441,8 +450,8 @@ var Mermaid = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ chart, className = "",
|
|
|
441
450
|
onClick: handleClick,
|
|
442
451
|
children: [
|
|
443
452
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border-b border-border bg-muted/50", children: [
|
|
444
|
-
/* @__PURE__ */ jsxRuntime.jsx("h6", { className: "text-sm font-semibold text-foreground", children:
|
|
445
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-1", children:
|
|
453
|
+
/* @__PURE__ */ jsxRuntime.jsx("h6", { className: "text-sm font-semibold text-foreground", children: labels.title }),
|
|
454
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-1", children: labels.clickToView })
|
|
446
455
|
] }),
|
|
447
456
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative p-4 overflow-hidden", children: [
|
|
448
457
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -455,7 +464,7 @@ var Mermaid = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ chart, className = "",
|
|
|
455
464
|
),
|
|
456
465
|
isRendering && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-background/50 backdrop-blur-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
457
466
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-primary" }),
|
|
458
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children:
|
|
467
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: labels.loading })
|
|
459
468
|
] }) })
|
|
460
469
|
] })
|
|
461
470
|
]
|
|
@@ -479,5 +488,5 @@ var Mermaid = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ chart, className = "",
|
|
|
479
488
|
var Mermaid_client_default = Mermaid;
|
|
480
489
|
|
|
481
490
|
module.exports = Mermaid_client_default;
|
|
482
|
-
//# sourceMappingURL=Mermaid.client-
|
|
483
|
-
//# sourceMappingURL=Mermaid.client-
|
|
491
|
+
//# sourceMappingURL=Mermaid.client-PNXEC6YL.cjs.map
|
|
492
|
+
//# sourceMappingURL=Mermaid.client-PNXEC6YL.cjs.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":["__name","useState","jsxs","jsx","Fragment","useTypedT","useMemo","useEffect","createPortal","useRef","useCallback","applyMermaidTextColors","mermaid","useResolvedTheme"],"mappings":"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","file":"Mermaid.client-PNXEC6YL.cjs","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, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { useTypedT, type I18nTranslations } from '@djangocfg/i18n';\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 const t = useTypedT<I18nTranslations>();\n const diagramTitle = useMemo(() => t('tools.diagram.title'), [t]);\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\">{diagramTitle}</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, { useMemo } from 'react';\n\nimport { useTypedT, type I18nTranslations } from '@djangocfg/i18n';\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 t = useTypedT<I18nTranslations>();\n const theme = useResolvedTheme();\n\n const labels = useMemo(() => ({\n title: t('tools.diagram.title'),\n clickToView: t('tools.diagram.clickToView'),\n loading: t('ui.form.loading'),\n }), [t]);\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\">{labels.title}</h6>\n <p className=\"text-xs text-muted-foreground mt-1\">{labels.clickToView}</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\">{labels.loading}</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"]}
|