@windrun-huaiin/third-ui 5.14.0 → 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 +114 -10
- package/dist/fuma/mdx/index.js.map +1 -1
- package/dist/fuma/mdx/index.mjs +114 -10
- package/dist/fuma/mdx/index.mjs.map +1 -1
- package/dist/fuma/server.js.map +1 -1
- package/dist/fuma/server.mjs.map +1 -1
- package/package.json +1 -1
- package/src/fuma/mdx/mermaid.tsx +103 -10
package/package.json
CHANGED
package/src/fuma/mdx/mermaid.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { globalLucideIcons as icons } from '@base-ui/components/global-icon';
|
|
4
|
-
//
|
|
4
|
+
// Attention: do not use external dialog library, avoid react context conflict when building third-party applications
|
|
5
5
|
import type { MermaidConfig } from 'mermaid';
|
|
6
6
|
import { useTheme } from 'next-themes';
|
|
7
7
|
import { useCallback, useEffect, useId, useRef, useState } from 'react';
|
|
@@ -68,22 +68,24 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
68
68
|
// helpers for preview zoom
|
|
69
69
|
const clamp = (v: number, min: number, max: number) => Math.min(Math.max(v, min), max);
|
|
70
70
|
const resetTransform = useCallback(() => {
|
|
71
|
-
setScale(
|
|
71
|
+
setScale(4); // 400%
|
|
72
72
|
setTranslate({ x: 0, y: 0 });
|
|
73
73
|
}, []);
|
|
74
74
|
|
|
75
75
|
const zoomBy = useCallback((delta: number) => {
|
|
76
|
-
//
|
|
77
|
-
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));
|
|
78
78
|
}, []);
|
|
79
79
|
|
|
80
80
|
const onWheel = useCallback((e: React.WheelEvent<HTMLDivElement>) => {
|
|
81
|
-
// Cmd/Ctrl +
|
|
81
|
+
// Cmd/Ctrl + wheel zoom (around the center point), otherwise up and down panning
|
|
82
82
|
if (e.metaKey || e.ctrlKey) {
|
|
83
83
|
e.preventDefault();
|
|
84
|
+
e.stopPropagation();
|
|
84
85
|
const delta = e.deltaY > 0 ? -0.1 : 0.1;
|
|
85
|
-
setScale((prev) => clamp(prev + delta, 0.25,
|
|
86
|
+
setScale((prev) => clamp(prev + delta, 0.25, 10));
|
|
86
87
|
} else {
|
|
88
|
+
e.stopPropagation();
|
|
87
89
|
setTranslate((prev) => ({ x: prev.x, y: prev.y - e.deltaY }));
|
|
88
90
|
}
|
|
89
91
|
}, []);
|
|
@@ -106,6 +108,62 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
106
108
|
isPanningRef.current = false;
|
|
107
109
|
(e.currentTarget as HTMLDivElement).releasePointerCapture(e.pointerId);
|
|
108
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]);
|
|
109
167
|
|
|
110
168
|
return (
|
|
111
169
|
<div>
|
|
@@ -137,7 +195,12 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
137
195
|
aria-label={typeof title === 'string' ? title : 'Mermaid Preview'}
|
|
138
196
|
className="fixed inset-0 z-[9999] flex items-center justify-center"
|
|
139
197
|
>
|
|
140
|
-
<div
|
|
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
|
+
/>
|
|
141
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">
|
|
142
205
|
{/* Top bar */}
|
|
143
206
|
<div className="flex items-center justify-between px-3 py-2 border-b border-neutral-200 dark:border-neutral-700">
|
|
@@ -149,7 +212,7 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
149
212
|
<button
|
|
150
213
|
aria-label="Zoom out"
|
|
151
214
|
className="flex h-6 w-6 items-center justify-center rounded border border-neutral-300 dark:border-neutral-600 text-[13px]"
|
|
152
|
-
onClick={() => zoomBy(-0.
|
|
215
|
+
onClick={() => zoomBy(-0.5)}
|
|
153
216
|
>
|
|
154
217
|
-
|
|
155
218
|
</button>
|
|
@@ -157,10 +220,40 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
157
220
|
<button
|
|
158
221
|
aria-label="Zoom in"
|
|
159
222
|
className="flex h-6 w-6 items-center justify-center rounded border border-neutral-300 dark:border-neutral-600 text-[13px]"
|
|
160
|
-
onClick={() => zoomBy(0.
|
|
223
|
+
onClick={() => zoomBy(0.5)}
|
|
161
224
|
>
|
|
162
225
|
+
|
|
163
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>
|
|
164
257
|
<button
|
|
165
258
|
aria-label="Reset"
|
|
166
259
|
className="ml-1 flex h-6 w-6 items-center justify-center rounded text-purple-500 hover:text-purple-600"
|
|
@@ -180,7 +273,7 @@ export function Mermaid({ chart, title, watermarkEnabled, watermarkText, enableP
|
|
|
180
273
|
|
|
181
274
|
{/* Canvas */}
|
|
182
275
|
<div
|
|
183
|
-
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"
|
|
184
277
|
onWheel={onWheel}
|
|
185
278
|
onPointerDown={onPointerDown}
|
|
186
279
|
onPointerMove={onPointerMove}
|