@windrun-huaiin/third-ui 5.13.6 → 5.14.1
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/fuma/mdx/index.js +534 -2677
- package/dist/fuma/mdx/index.js.map +1 -1
- package/dist/fuma/mdx/index.mjs +533 -2676
- package/dist/fuma/mdx/index.mjs.map +1 -1
- package/dist/fuma/server.js +206 -2465
- package/dist/fuma/server.js.map +1 -1
- package/dist/fuma/server.mjs +203 -2462
- package/dist/fuma/server.mjs.map +1 -1
- package/package.json +1 -1
- package/src/fuma/mdx/mermaid.tsx +115 -21
package/package.json
CHANGED
package/src/fuma/mdx/mermaid.tsx
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { globalLucideIcons as icons } from '@base-ui/components/global-icon';
|
|
4
|
-
|
|
5
|
-
AlertDialog,
|
|
6
|
-
AlertDialogContent,
|
|
7
|
-
AlertDialogTitle,
|
|
8
|
-
} from '@base-ui/ui/alert-dialog';
|
|
4
|
+
// Attention: do not use external dialog library, avoid react context conflict when building third-party applications
|
|
9
5
|
import type { MermaidConfig } from 'mermaid';
|
|
10
6
|
import { useTheme } from 'next-themes';
|
|
11
7
|
import { useCallback, useEffect, useId, useRef, useState } from 'react';
|
|
@@ -72,22 +68,24 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
72
68
|
// helpers for preview zoom
|
|
73
69
|
const clamp = (v: number, min: number, max: number) => Math.min(Math.max(v, min), max);
|
|
74
70
|
const resetTransform = useCallback(() => {
|
|
75
|
-
setScale(
|
|
71
|
+
setScale(4); // 400%
|
|
76
72
|
setTranslate({ x: 0, y: 0 });
|
|
77
73
|
}, []);
|
|
78
74
|
|
|
79
75
|
const zoomBy = useCallback((delta: number) => {
|
|
80
|
-
//
|
|
81
|
-
setScale((prev) => clamp(prev + delta, 0.25,
|
|
76
|
+
// zoom by center: keep the zoom center at the center of the canvas, without introducing displacement
|
|
77
|
+
setScale((prev) => clamp(prev + delta, 0.25, 10));
|
|
82
78
|
}, []);
|
|
83
79
|
|
|
84
80
|
const onWheel = useCallback((e: React.WheelEvent<HTMLDivElement>) => {
|
|
85
|
-
// Cmd/Ctrl +
|
|
81
|
+
// Cmd/Ctrl + wheel zoom (around the center point), otherwise up and down panning
|
|
86
82
|
if (e.metaKey || e.ctrlKey) {
|
|
87
83
|
e.preventDefault();
|
|
84
|
+
e.stopPropagation();
|
|
88
85
|
const delta = e.deltaY > 0 ? -0.1 : 0.1;
|
|
89
|
-
setScale((prev) => clamp(prev + delta, 0.25,
|
|
86
|
+
setScale((prev) => clamp(prev + delta, 0.25, 10));
|
|
90
87
|
} else {
|
|
88
|
+
e.stopPropagation();
|
|
91
89
|
setTranslate((prev) => ({ x: prev.x, y: prev.y - e.deltaY }));
|
|
92
90
|
}
|
|
93
91
|
}, []);
|
|
@@ -110,6 +108,62 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
110
108
|
isPanningRef.current = false;
|
|
111
109
|
(e.currentTarget as HTMLDivElement).releasePointerCapture(e.pointerId);
|
|
112
110
|
}, []);
|
|
111
|
+
|
|
112
|
+
// prevent browser-level zoom (touchpad pinch/shortcut) from taking effect when the dialog is open
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
if (!open) return;
|
|
115
|
+
// 初次打开时,默认放大到 400%
|
|
116
|
+
resetTransform();
|
|
117
|
+
const onGlobalWheel = (ev: WheelEvent) => {
|
|
118
|
+
if (ev.ctrlKey || ev.metaKey) {
|
|
119
|
+
ev.preventDefault();
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const onKeyDown = (ev: KeyboardEvent) => {
|
|
123
|
+
if (!(ev.ctrlKey || ev.metaKey)) return;
|
|
124
|
+
const k = ev.key;
|
|
125
|
+
if (k === '=' || k === '+') {
|
|
126
|
+
ev.preventDefault();
|
|
127
|
+
setScale((prev) => clamp(prev + 0.2, 0.25, 10));
|
|
128
|
+
} else if (k === '-') {
|
|
129
|
+
ev.preventDefault();
|
|
130
|
+
setScale((prev) => clamp(prev - 0.2, 0.25, 10));
|
|
131
|
+
} else if (k === '0') {
|
|
132
|
+
ev.preventDefault();
|
|
133
|
+
resetTransform();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
window.addEventListener('wheel', onGlobalWheel, { passive: false, capture: true });
|
|
137
|
+
window.addEventListener('keydown', onKeyDown, { capture: true });
|
|
138
|
+
return () => {
|
|
139
|
+
window.removeEventListener('wheel', onGlobalWheel, true);
|
|
140
|
+
window.removeEventListener('keydown', onKeyDown, true);
|
|
141
|
+
};
|
|
142
|
+
}, [open, resetTransform]);
|
|
143
|
+
|
|
144
|
+
// Lock background scroll when dialog is open
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
if (!open) return;
|
|
147
|
+
const previousPosition = document.body.style.position;
|
|
148
|
+
const previousTop = document.body.style.top;
|
|
149
|
+
const previousLeft = document.body.style.left;
|
|
150
|
+
const previousRight = document.body.style.right;
|
|
151
|
+
const previousWidth = document.body.style.width;
|
|
152
|
+
const scrollY = window.scrollY;
|
|
153
|
+
document.body.style.position = 'fixed';
|
|
154
|
+
document.body.style.top = `-${scrollY}px`;
|
|
155
|
+
document.body.style.left = '0';
|
|
156
|
+
document.body.style.right = '0';
|
|
157
|
+
document.body.style.width = '100%';
|
|
158
|
+
return () => {
|
|
159
|
+
document.body.style.position = previousPosition;
|
|
160
|
+
document.body.style.top = previousTop;
|
|
161
|
+
document.body.style.left = previousLeft;
|
|
162
|
+
document.body.style.right = previousRight;
|
|
163
|
+
document.body.style.width = previousWidth;
|
|
164
|
+
window.scrollTo(0, scrollY);
|
|
165
|
+
};
|
|
166
|
+
}, [open]);
|
|
113
167
|
|
|
114
168
|
return (
|
|
115
169
|
<div>
|
|
@@ -133,11 +187,21 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
133
187
|
</div>
|
|
134
188
|
)}
|
|
135
189
|
|
|
136
|
-
{/* Preview Dialog */}
|
|
137
|
-
{enablePreview && (
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
|
|
190
|
+
{/* Preview Dialog (custom minimal dialog) */}
|
|
191
|
+
{enablePreview && open && (
|
|
192
|
+
<div
|
|
193
|
+
role="dialog"
|
|
194
|
+
aria-modal="true"
|
|
195
|
+
aria-label={typeof title === 'string' ? title : 'Mermaid Preview'}
|
|
196
|
+
className="fixed inset-0 z-[9999] flex items-center justify-center"
|
|
197
|
+
>
|
|
198
|
+
<div
|
|
199
|
+
className="absolute inset-0 bg-black/60"
|
|
200
|
+
onClick={() => { setOpen(false); resetTransform(); }}
|
|
201
|
+
onWheel={(e) => { e.preventDefault(); e.stopPropagation(); }}
|
|
202
|
+
onTouchMove={(e) => { e.preventDefault(); e.stopPropagation(); }}
|
|
203
|
+
/>
|
|
204
|
+
<div className="relative z-[1] max-w-[95vw] w-[95vw] h-[88vh] p-0 bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-700 rounded-md shadow-2xl overflow-hidden">
|
|
141
205
|
{/* Top bar */}
|
|
142
206
|
<div className="flex items-center justify-between px-3 py-2 border-b border-neutral-200 dark:border-neutral-700">
|
|
143
207
|
<div className="flex items-center gap-2 text-sm text-neutral-600 dark:text-neutral-300">
|
|
@@ -148,7 +212,7 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
148
212
|
<button
|
|
149
213
|
aria-label="Zoom out"
|
|
150
214
|
className="flex h-6 w-6 items-center justify-center rounded border border-neutral-300 dark:border-neutral-600 text-[13px]"
|
|
151
|
-
onClick={() => zoomBy(-0.
|
|
215
|
+
onClick={() => zoomBy(-0.5)}
|
|
152
216
|
>
|
|
153
217
|
-
|
|
154
218
|
</button>
|
|
@@ -156,10 +220,40 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
156
220
|
<button
|
|
157
221
|
aria-label="Zoom in"
|
|
158
222
|
className="flex h-6 w-6 items-center justify-center rounded border border-neutral-300 dark:border-neutral-600 text-[13px]"
|
|
159
|
-
onClick={() => zoomBy(0.
|
|
223
|
+
onClick={() => zoomBy(0.5)}
|
|
160
224
|
>
|
|
161
225
|
+
|
|
162
226
|
</button>
|
|
227
|
+
{/* quick zoom shortcuts */}
|
|
228
|
+
<div className="mx-1 h-4 w-px bg-neutral-300 dark:bg-neutral-700" />
|
|
229
|
+
<button
|
|
230
|
+
aria-label="Zoom 100%"
|
|
231
|
+
className="inline-flex h-6 min-w-8 items-center justify-center rounded border border-neutral-300 dark:border-neutral-600 px-1.5 text-[12px]"
|
|
232
|
+
onClick={() => setScale(1)}
|
|
233
|
+
>
|
|
234
|
+
X1
|
|
235
|
+
</button>
|
|
236
|
+
<button
|
|
237
|
+
aria-label="Zoom 200%"
|
|
238
|
+
className="ml-1 inline-flex h-6 min-w-8 items-center justify-center rounded border border-neutral-300 dark:border-neutral-600 px-1.5 text-[12px]"
|
|
239
|
+
onClick={() => setScale(2)}
|
|
240
|
+
>
|
|
241
|
+
X2
|
|
242
|
+
</button>
|
|
243
|
+
<button
|
|
244
|
+
aria-label="Zoom 300%"
|
|
245
|
+
className="ml-1 inline-flex h-6 min-w-8 items-center justify-center rounded border border-neutral-300 dark:border-neutral-600 px-1.5 text-[12px]"
|
|
246
|
+
onClick={() => setScale(3)}
|
|
247
|
+
>
|
|
248
|
+
X3
|
|
249
|
+
</button>
|
|
250
|
+
<button
|
|
251
|
+
aria-label="Zoom 1000%"
|
|
252
|
+
className="ml-1 inline-flex h-6 min-w-10 items-center justify-center rounded border border-neutral-300 dark:border-neutral-600 px-1.5 text-[12px]"
|
|
253
|
+
onClick={() => setScale(10)}
|
|
254
|
+
>
|
|
255
|
+
X10
|
|
256
|
+
</button>
|
|
163
257
|
<button
|
|
164
258
|
aria-label="Reset"
|
|
165
259
|
className="ml-1 flex h-6 w-6 items-center justify-center rounded text-purple-500 hover:text-purple-600"
|
|
@@ -170,7 +264,7 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
170
264
|
<button
|
|
171
265
|
aria-label="Close"
|
|
172
266
|
className="ml-1 flex h-6 w-6 items-center justify-center rounded text-purple-500 hover:text-purple-600"
|
|
173
|
-
onClick={() => setOpen(false)}
|
|
267
|
+
onClick={() => { setOpen(false); resetTransform(); }}
|
|
174
268
|
>
|
|
175
269
|
<icons.X className="h-3.5 w-3.5" />
|
|
176
270
|
</button>
|
|
@@ -179,7 +273,7 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
179
273
|
|
|
180
274
|
{/* Canvas */}
|
|
181
275
|
<div
|
|
182
|
-
className="relative h-[calc(88vh-40px)] w-full overflow-hidden bg-white dark:bg-neutral-900"
|
|
276
|
+
className="relative h-[calc(88vh-40px)] w-full overflow-hidden bg-white dark:bg-neutral-900 touch-none overscroll-contain"
|
|
183
277
|
onWheel={onWheel}
|
|
184
278
|
onPointerDown={onPointerDown}
|
|
185
279
|
onPointerMove={onPointerMove}
|
|
@@ -199,8 +293,8 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
199
293
|
Drag to pan, hold Cmd/Ctrl + scroll to zoom
|
|
200
294
|
</div>
|
|
201
295
|
</div>
|
|
202
|
-
</
|
|
203
|
-
</
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
204
298
|
)}
|
|
205
299
|
</div>
|
|
206
300
|
);
|