react-super-mermaid 0.3.0 â 0.4.2
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 +6 -5
- package/dist/index.cjs +409 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -11
- package/dist/index.d.ts +45 -11
- package/dist/index.js +408 -59
- package/dist/index.js.map +1 -1
- package/llms.txt +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -166,7 +166,7 @@ gitGraph
|
|
|
166
166
|
- đ **In-diagram search** â highlight + pan to matches (`/` or `Ctrl/Cmd+F`).
|
|
167
167
|
- đī¸ **Pan & zoom** â fit, actual size, keyboard `+ - 0 1 w` (via `svg-pan-zoom`).
|
|
168
168
|
- âļ **Fullscreen modal** â open the diagram in a viewport-filling, RWD-friendly popup (`f` / `Esc`); body scroll locked, auto re-fit.
|
|
169
|
-
- âĻ **Background
|
|
169
|
+
- âĻ **Background picker** â a swatch popover to set the canvas **surface** (preset colors + a custom color well) and an independent **pattern** (none / dots / grid lines, cycle with `b`). Surface + pattern combine freely and carry through to exports.
|
|
170
170
|
- đ¤ **Export** â SVG and high-res PNG/JPEG/WebP (1Ã/2Ã/4Ã, optional transparent background).
|
|
171
171
|
- đĒļ **Lightweight & decoupled** â `mermaid`, `svg-pan-zoom`, `react` are **optional peer deps**, never bundled. No Tailwind, no app coupling.
|
|
172
172
|
- đ **Load external mermaid** â inject an instance, dynamic-import the peer, or pull from a CDN. Your bundle doesn't carry mermaid.
|
|
@@ -248,8 +248,9 @@ Resolution order is **injected â peer import â CDN**, memoized so mermaid lo
|
|
|
248
248
|
| `panZoom` | `boolean` | `true` | |
|
|
249
249
|
| `search` | `boolean` | `true` | toolbar search |
|
|
250
250
|
| `exportable` | `boolean` | `true` | toolbar SVG/PNG export |
|
|
251
|
-
| `background` | `boolean` | `true` |
|
|
252
|
-
| `
|
|
251
|
+
| `background` | `boolean` | `true` | show the background picker (surface swatches + custom color + pattern toggle) |
|
|
252
|
+
| `pattern` | `'none' \| 'dots' \| 'grid'` | `'dots'` | initial / controlled overlay pattern |
|
|
253
|
+
| `solidColor` | `string \| null` | `null` (transparent) | initial / controlled canvas surface color (hex); `null` follows the page |
|
|
253
254
|
| `fullscreen` | `boolean` | `true` | toolbar fullscreen button â opens a viewport-filling modal (RWD) |
|
|
254
255
|
| `onFullscreenChange` | `(fullscreen: boolean) => void` | â | fired on enter / exit fullscreen |
|
|
255
256
|
| `keyboard` | `boolean` | `true` | shortcuts when the viewer is focused |
|
|
@@ -281,7 +282,7 @@ await ref.current?.downloadPng('diagram.png', { scale: 4 });
|
|
|
281
282
|
const svgString = ref.current?.exportSvg();
|
|
282
283
|
```
|
|
283
284
|
|
|
284
|
-
Handle: `zoomIn / zoomOut / fit / reset / actualSize / getZoomPercent / search / next / prev / clearSearch / exportSvg / exportPng / downloadSvg / downloadPng / getSvg / enterFullscreen / exitFullscreen / toggleFullscreen / isFullscreen /
|
|
285
|
+
Handle: `zoomIn / zoomOut / fit / reset / actualSize / getZoomPercent / search / next / prev / clearSearch / exportSvg / exportPng / downloadSvg / downloadPng / getSvg / enterFullscreen / exitFullscreen / toggleFullscreen / isFullscreen / setPattern / cyclePattern / getPattern / setSolidColor / getSolidColor`.
|
|
285
286
|
|
|
286
287
|
## Themes & the sketch font
|
|
287
288
|
|
|
@@ -307,7 +308,7 @@ Styles are injected automatically (`injectStyles` default `true`) â no CSS imp
|
|
|
307
308
|
|
|
308
309
|
## Keyboard shortcuts
|
|
309
310
|
|
|
310
|
-
Focus the viewer, then: `/` or `Ctrl/Cmd+F` search ¡ `+`/`-` zoom ¡ `0` fit ¡ `1` actual size ¡ `w` fit width ¡ `f` toggle fullscreen ¡ `b` cycle background ¡ `Esc` close search / exit fullscreen.
|
|
311
|
+
Focus the viewer, then: `/` or `Ctrl/Cmd+F` search ¡ `+`/`-` zoom ¡ `0` fit ¡ `1` actual size ¡ `w` fit width ¡ `f` toggle fullscreen ¡ `b` cycle background pattern (none / dots / grid) ¡ `Esc` close search / exit fullscreen.
|
|
311
312
|
|
|
312
313
|
## Next.js / SSR
|
|
313
314
|
|
package/dist/index.cjs
CHANGED
|
@@ -107,8 +107,13 @@ var RSM_CSS = `
|
|
|
107
107
|
--rsm-accent: #2563eb;
|
|
108
108
|
--rsm-hover: #f3f4f6;
|
|
109
109
|
--rsm-surface: #ffffff;
|
|
110
|
+
/* --rsm-paper = \u756B\u5E03\u5E95\u8272,\u5C0D\u9F4A VS Code \u64F4\u5145\u5957\u4EF6\u7684 editor-background(\u4EAE)\u3002 */
|
|
111
|
+
--rsm-paper: #ffffff;
|
|
110
112
|
--rsm-canvas-bg: transparent;
|
|
111
|
-
|
|
113
|
+
/* \u9EDE\u9663\u683C\u7DDA:\u5C0D\u9F4A VS Code \u7684 color-mix(foreground 9%) \u516C\u5F0F\u3002 */
|
|
114
|
+
--rsm-grid-dot: color-mix(in srgb, var(--rsm-fg) 9%, transparent);
|
|
115
|
+
/* \u7DB2\u683C\u7DDA:\u6BD4\u7DB2\u9EDE\u518D\u6DE1\u4E00\u9EDE,\u907F\u514D\u7DDA\u689D\u6436\u904E\u5716\u8868\u3002 */
|
|
116
|
+
--rsm-grid-line: color-mix(in srgb, var(--rsm-fg) 7%, transparent);
|
|
112
117
|
--rsm-radius: 8px;
|
|
113
118
|
display: flex;
|
|
114
119
|
flex-direction: column;
|
|
@@ -170,6 +175,14 @@ var RSM_CSS = `
|
|
|
170
175
|
}
|
|
171
176
|
.rsm-btn:disabled { opacity: 0.6; cursor: default; }
|
|
172
177
|
|
|
178
|
+
/* \u5DE5\u5177\u5217\u63A7\u5236\u9805\u9AD8\u5EA6\u4E00\u81F4(\u6A23\u5F0F\u4E0B\u62C9 / \u4E00\u822C\u9215 / \u7E2E\u653E\u7FA4 / \u80CC\u666F\u9215),\u907F\u514D\u9AD8\u4F4E\u4E0D\u9F4A\u3002 */
|
|
179
|
+
.rsm-toolbar .rsm-btn,
|
|
180
|
+
.rsm-toolbar .rsm-select,
|
|
181
|
+
.rsm-toolbar .rsm-zoom { min-height: 30px; }
|
|
182
|
+
.rsm-toolbar .rsm-btn,
|
|
183
|
+
.rsm-toolbar .rsm-select { align-items: center; }
|
|
184
|
+
.rsm-toolbar .rsm-zoom > button { display: inline-flex; align-items: center; justify-content: center; }
|
|
185
|
+
|
|
173
186
|
.rsm-zoom {
|
|
174
187
|
display: inline-flex;
|
|
175
188
|
align-items: stretch;
|
|
@@ -215,7 +228,8 @@ var RSM_CSS = `
|
|
|
215
228
|
flex: 1 1 auto;
|
|
216
229
|
min-height: 0;
|
|
217
230
|
overflow: hidden;
|
|
218
|
-
|
|
231
|
+
/* \u5E95\u8272\u7531 --rsm-canvas-bg \u63A7\u5236(\u9810\u8A2D\u900F\u660E,\u8DDF\u96A8\u9801\u9762);\u5716\u6A23\u758A\u5728\u5176\u4E0A(background-image)\u3002 */
|
|
232
|
+
background-color: var(--rsm-canvas-bg, transparent);
|
|
219
233
|
}
|
|
220
234
|
.rsm-stage { width: 100%; height: 100%; }
|
|
221
235
|
.rsm-root svg { cursor: grab; user-select: none; }
|
|
@@ -240,23 +254,172 @@ var RSM_CSS = `
|
|
|
240
254
|
.rsm-root .rsm-hit { filter: drop-shadow(0 0 5px #f59e0b) drop-shadow(0 0 1.5px #f59e0b); }
|
|
241
255
|
|
|
242
256
|
.rsm-root.rsm-dark {
|
|
243
|
-
|
|
244
|
-
--rsm-
|
|
245
|
-
--rsm-
|
|
246
|
-
--rsm-
|
|
247
|
-
--rsm-
|
|
248
|
-
--rsm-
|
|
249
|
-
--rsm-
|
|
257
|
+
/* \u6697\u8272\u9762\u677F\u5C0D\u9F4A VS Code Dark+ / Dark Modern \u7684\u4E2D\u6027\u7070(\u975E\u85CD\u8ABF)\u3002 */
|
|
258
|
+
--rsm-border: #3c3c3c;
|
|
259
|
+
--rsm-fg: #cccccc;
|
|
260
|
+
--rsm-muted: #9d9d9d;
|
|
261
|
+
--rsm-accent: #3794ff;
|
|
262
|
+
--rsm-hover: #2a2d2e;
|
|
263
|
+
--rsm-surface: #252526;
|
|
264
|
+
/* \u756B\u5E03\u5E95\u8272 = VS Code editor-background(\u6697);grid-dot \u7531 --rsm-fg 9% \u81EA\u52D5\u63A8\u5C0E\u3002 */
|
|
265
|
+
--rsm-paper: #1e1e1e;
|
|
250
266
|
}
|
|
251
267
|
|
|
252
|
-
/* \u2500\u2500 \u80CC\u666F
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
268
|
+
/* \u2500\u2500 \u80CC\u666F \u2500\u2500 \u5E95\u8272 + \u758A\u52A0\u5716\u6A23,\u5169\u8005\u7368\u7ACB\u3002
|
|
269
|
+
* \u5E95\u8272:--rsm-canvas-bg(\u7531\u8272\u7968 / \u81EA\u8A02\u8272 inline \u8986\u5BEB;\u672A\u8A2D = \u900F\u660E\u8DDF\u96A8\u9801\u9762)\u3002
|
|
270
|
+
* \u5716\u6A23:.rsm-pattern-dots(\u7DB2\u9EDE) / .rsm-pattern-grid(\u7DB2\u683C\u7DDA),\u758A\u5728\u5E95\u8272\u4E4B\u4E0A\u3002 */
|
|
271
|
+
.rsm-root.rsm-pattern-dots .rsm-canvas {
|
|
256
272
|
background-image: radial-gradient(var(--rsm-grid-dot) 1px, transparent 1px);
|
|
257
273
|
background-size: 18px 18px;
|
|
258
274
|
background-position: -9px -9px;
|
|
259
275
|
}
|
|
276
|
+
.rsm-root.rsm-pattern-grid .rsm-canvas {
|
|
277
|
+
background-image:
|
|
278
|
+
linear-gradient(to right, var(--rsm-grid-line) 1px, transparent 1px),
|
|
279
|
+
linear-gradient(to bottom, var(--rsm-grid-line) 1px, transparent 1px);
|
|
280
|
+
background-size: 22px 22px;
|
|
281
|
+
background-position: -1px -1px;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* \u2500\u2500 \u80CC\u666F\u9078\u64C7\u5668(toolbar \u5167\u7684\u8272\u4E95\u6309\u9215 + \u5F48\u51FA\u9762\u677F)\u2500\u2500 */
|
|
285
|
+
.rsm-bg { position: relative; display: inline-flex; }
|
|
286
|
+
|
|
287
|
+
/* \u89F8\u767C\u9215\u5DE6\u5074\u7684\u300C\u8272\u4E95\u300D:\u53CD\u6620\u76EE\u524D\u5E95\u8272;\u900F\u660E / \u9810\u8A2D\u6642\u756B\u4E00\u9053\u659C\u7DDA\u8868\u793A\u300C\u4E0D\u8986\u5BEB\u300D\u3002 */
|
|
288
|
+
.rsm-bg-well {
|
|
289
|
+
width: 16px;
|
|
290
|
+
height: 16px;
|
|
291
|
+
border-radius: 4px;
|
|
292
|
+
border: 1px solid color-mix(in srgb, var(--rsm-fg) 28%, transparent);
|
|
293
|
+
background-color: var(--rsm-well-color, transparent);
|
|
294
|
+
}
|
|
295
|
+
.rsm-bg-well[data-empty="true"] {
|
|
296
|
+
background-color: var(--rsm-surface);
|
|
297
|
+
background-image: linear-gradient(
|
|
298
|
+
to top right,
|
|
299
|
+
transparent calc(50% - 1px),
|
|
300
|
+
#ef4444 calc(50% - 1px),
|
|
301
|
+
#ef4444 calc(50% + 1px),
|
|
302
|
+
transparent calc(50% + 1px)
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/* \u5F48\u51FA\u9762\u677F:\u5361\u7247\u5F0F\u3001\u8F15\u9670\u5F71\u3001\u6DE1\u5165\u3002 */
|
|
307
|
+
.rsm-bg-pop {
|
|
308
|
+
position: absolute;
|
|
309
|
+
top: calc(100% + 8px);
|
|
310
|
+
left: 0;
|
|
311
|
+
z-index: 50;
|
|
312
|
+
display: flex;
|
|
313
|
+
flex-direction: column;
|
|
314
|
+
gap: 12px;
|
|
315
|
+
padding: 12px;
|
|
316
|
+
min-width: 260px;
|
|
317
|
+
border: 1px solid var(--rsm-border);
|
|
318
|
+
border-radius: 12px;
|
|
319
|
+
background: var(--rsm-surface);
|
|
320
|
+
color: var(--rsm-fg);
|
|
321
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.16), 0 2px 6px rgba(0, 0, 0, 0.08);
|
|
322
|
+
animation: rsm-pop-in 0.13s ease-out;
|
|
323
|
+
}
|
|
324
|
+
@keyframes rsm-pop-in {
|
|
325
|
+
from { opacity: 0; transform: translateY(-5px); }
|
|
326
|
+
to { opacity: 1; transform: none; }
|
|
327
|
+
}
|
|
328
|
+
.rsm-bg-section { display: flex; flex-direction: column; gap: 8px; }
|
|
329
|
+
.rsm-bg-section-label {
|
|
330
|
+
font-size: 11px;
|
|
331
|
+
font-weight: 600;
|
|
332
|
+
letter-spacing: 0.03em;
|
|
333
|
+
color: var(--rsm-muted);
|
|
334
|
+
}
|
|
335
|
+
.rsm-bg-swatches { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
336
|
+
|
|
337
|
+
/* \u8272\u7968:\u5713\u89D2\u5C0F\u65B9\u584A;\u9078\u4E2D\u52A0\u540C\u8272\u5916\u74B0\u3002 */
|
|
338
|
+
.rsm-swatch {
|
|
339
|
+
position: relative;
|
|
340
|
+
width: 26px;
|
|
341
|
+
height: 26px;
|
|
342
|
+
padding: 0;
|
|
343
|
+
border: 1px solid color-mix(in srgb, var(--rsm-fg) 16%, transparent);
|
|
344
|
+
border-radius: 7px;
|
|
345
|
+
cursor: pointer;
|
|
346
|
+
transition: transform 0.1s ease, box-shadow 0.1s ease;
|
|
347
|
+
}
|
|
348
|
+
.rsm-swatch:hover { transform: scale(1.12); }
|
|
349
|
+
.rsm-swatch:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--rsm-accent); }
|
|
350
|
+
.rsm-swatch.rsm-selected { outline: 2px solid var(--rsm-accent); outline-offset: 2px; }
|
|
351
|
+
.rsm-swatch[data-empty="true"] {
|
|
352
|
+
background-color: var(--rsm-surface);
|
|
353
|
+
background-image: linear-gradient(
|
|
354
|
+
to top right,
|
|
355
|
+
transparent calc(50% - 1px),
|
|
356
|
+
#ef4444 calc(50% - 1px),
|
|
357
|
+
#ef4444 calc(50% + 1px),
|
|
358
|
+
transparent calc(50% + 1px)
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/* \u81EA\u8A02\u8272\u7968:\u8986\u4E00\u500B\u96B1\u5F62\u7684\u539F\u751F color input,\u672A\u9078\u6642\u986F\u793A \u{1F3A8}\u3002 */
|
|
363
|
+
.rsm-swatch-custom {
|
|
364
|
+
display: inline-flex;
|
|
365
|
+
align-items: center;
|
|
366
|
+
justify-content: center;
|
|
367
|
+
overflow: hidden;
|
|
368
|
+
background:
|
|
369
|
+
conic-gradient(from 180deg, #f87171, #fbbf24, #34d399, #60a5fa, #a78bfa, #f87171);
|
|
370
|
+
}
|
|
371
|
+
.rsm-swatch-custom.rsm-has-color { background: none; }
|
|
372
|
+
.rsm-swatch-custom input[type="color"] {
|
|
373
|
+
position: absolute;
|
|
374
|
+
inset: 0;
|
|
375
|
+
width: 100%;
|
|
376
|
+
height: 100%;
|
|
377
|
+
margin: 0;
|
|
378
|
+
padding: 0;
|
|
379
|
+
border: 0;
|
|
380
|
+
opacity: 0;
|
|
381
|
+
cursor: pointer;
|
|
382
|
+
}
|
|
383
|
+
.rsm-swatch-custom-icon {
|
|
384
|
+
font-size: 12px;
|
|
385
|
+
line-height: 1;
|
|
386
|
+
pointer-events: none;
|
|
387
|
+
filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.35));
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/* \u5716\u6A23\u5207\u63DB:\u5206\u6BB5\u5F0F\u6309\u9215(\u7121 / \u7DB2\u9EDE / \u7DB2\u683C)\u3002 */
|
|
391
|
+
.rsm-seg {
|
|
392
|
+
display: inline-flex;
|
|
393
|
+
align-self: flex-start;
|
|
394
|
+
border: 1px solid var(--rsm-border);
|
|
395
|
+
border-radius: 8px;
|
|
396
|
+
overflow: hidden;
|
|
397
|
+
}
|
|
398
|
+
.rsm-seg > button {
|
|
399
|
+
flex: 1 1 0;
|
|
400
|
+
min-width: 58px;
|
|
401
|
+
display: inline-flex;
|
|
402
|
+
align-items: center;
|
|
403
|
+
justify-content: center;
|
|
404
|
+
gap: 5px;
|
|
405
|
+
border: 0;
|
|
406
|
+
background: var(--rsm-surface);
|
|
407
|
+
color: var(--rsm-fg);
|
|
408
|
+
padding: 6px 11px;
|
|
409
|
+
font-size: 12px;
|
|
410
|
+
line-height: 1.3;
|
|
411
|
+
white-space: nowrap;
|
|
412
|
+
cursor: pointer;
|
|
413
|
+
transition: background 0.1s ease, color 0.1s ease;
|
|
414
|
+
}
|
|
415
|
+
.rsm-seg > button + button { border-left: 1px solid var(--rsm-border); }
|
|
416
|
+
.rsm-seg > button:hover { background: var(--rsm-hover); }
|
|
417
|
+
.rsm-seg > button[aria-pressed="true"] {
|
|
418
|
+
background: color-mix(in srgb, var(--rsm-accent) 14%, transparent);
|
|
419
|
+
color: var(--rsm-accent);
|
|
420
|
+
font-weight: 600;
|
|
421
|
+
}
|
|
422
|
+
.rsm-seg-glyph { font-size: 13px; line-height: 1; }
|
|
260
423
|
|
|
261
424
|
/* \u2500\u2500 \u5168\u87A2\u5E55\u8DF3\u7A97 \u2500\u2500 position:fixed \u8986\u84CB\u6574\u500B\u8996\u7A97,RWD \u53CB\u5584\u3002 */
|
|
262
425
|
.rsm-root.rsm-fullscreen {
|
|
@@ -312,6 +475,25 @@ var RSM_CSS = `
|
|
|
312
475
|
.rsm-zoom > button { padding: 4px 8px; font-size: 12px; }
|
|
313
476
|
.rsm-input { flex-basis: 150px; }
|
|
314
477
|
}
|
|
478
|
+
|
|
479
|
+
/* \u2500\u2500 \u6A19\u7C64\u5B57\u91CD(\u91CF\u6E2C\u968E\u6BB5\u5C31\u751F\u6548)\u2500\u2500
|
|
480
|
+
* boostLegibility \u5728\u300C\u6E32\u67D3\u5F8C\u300D\u624D\u628A\u6A19\u7C64\u5B57\u91CD\u52A0\u5230 600/700,\u4F46 mermaid \u662F\u5728\u300C\u6E32\u67D3\u4E2D\u300D
|
|
481
|
+
* \u91CF\u6E2C\u6587\u5B57\u5BEC\u5EA6\u4F86\u6C7A\u5B9A foreignObject / \u7BC0\u9EDE\u5916\u6846\u7684\u5927\u5C0F\u3002\u82E5\u53EA\u5728\u4E8B\u5F8C\u52A0\u7C97,\u7C97\u9AD4\u5B57\u6703\u6BD4\u5DF2\u91CF\u597D\u7684
|
|
482
|
+
* \u6846\u66F4\u5BEC \u2192 foreignObject \u628A\u5C3E\u5B57\u88C1\u6389(\u5FC3\u667A\u5716\u7BC0\u9EDE\u300Creact-super-mermaid\u300D\u5C3E\u5DF4\u7684 d \u4E0D\u898B\u5C31\u662F\u9019\u500B)\u3002
|
|
483
|
+
* \u89E3\u6CD5:\u628A\u540C\u6A23\u7684\u5B57\u91CD\u7528 CSS \u63D0\u524D\u5BA3\u544A,\u4E14\u300C\u4E0D\u300Dscope \u5728 .rsm-root \u4E4B\u4E0B,\u800C\u662F scope \u5728 mermaid
|
|
484
|
+
* \u7684\u6E32\u67D3 id(svg[id^="rsm-"])\u2014\u2014\u56E0\u70BA\u91CF\u6E2C\u6642\u90A3\u9846\u66AB\u6642\u7684 svg \u9084\u5728 <body> \u4E0B\u3001\u5C1A\u672A\u639B\u9032 .rsm-root\u3002
|
|
485
|
+
* \u9019\u6A23 mermaid \u91CF\u5230\u7684\u5C31\u662F\u7C97\u9AD4\u5BEC\u5EA6,\u6846\u6703\u525B\u597D\u5BB9\u7D0D,\u4E8B\u5F8C boostLegibility \u8A2D\u540C\u503C\u4E0D\u518D\u6490\u7834\u3002
|
|
486
|
+
* \u53EA scope \u6211\u5011\u81EA\u5DF1\u6E32\u67D3\u51FA\u7684 svg,\u6545\u4E0D\u6703\u6C61\u67D3 host \u9801\u9762\u5176\u5B83 mermaid\u3002 */
|
|
487
|
+
svg[id^="rsm-"] g.node text,
|
|
488
|
+
svg[id^="rsm-"] g.node tspan,
|
|
489
|
+
svg[id^="rsm-"] g.node .nodeLabel,
|
|
490
|
+
svg[id^="rsm-"] g.mindmap-node text,
|
|
491
|
+
svg[id^="rsm-"] g.mindmap-node .nodeLabel,
|
|
492
|
+
svg[id^="rsm-"] g[class*="timeline-node"] text,
|
|
493
|
+
svg[id^="rsm-"] text.actor { font-weight: 600 !important; }
|
|
494
|
+
svg[id^="rsm-"] .cluster-label text,
|
|
495
|
+
svg[id^="rsm-"] .cluster-label .nodeLabel,
|
|
496
|
+
svg[id^="rsm-"] text.pieTitleText { font-weight: 700 !important; }
|
|
315
497
|
`;
|
|
316
498
|
|
|
317
499
|
// src/core/ensure-styles.ts
|
|
@@ -319,7 +501,11 @@ function ensureStyles() {
|
|
|
319
501
|
if (typeof document === "undefined") {
|
|
320
502
|
return;
|
|
321
503
|
}
|
|
322
|
-
|
|
504
|
+
const existing = document.getElementById(RSM_STYLE_ID);
|
|
505
|
+
if (existing) {
|
|
506
|
+
if (existing.textContent !== RSM_CSS) {
|
|
507
|
+
existing.textContent = RSM_CSS;
|
|
508
|
+
}
|
|
323
509
|
return;
|
|
324
510
|
}
|
|
325
511
|
const style = document.createElement("style");
|
|
@@ -1430,7 +1616,7 @@ async function rasterizeToBlob(prepared, opts = {}) {
|
|
|
1430
1616
|
throw new Error("\u53D6\u4E0D\u5230 Canvas 2D context\u3002");
|
|
1431
1617
|
}
|
|
1432
1618
|
if (!transparent || mime === "image/jpeg") {
|
|
1433
|
-
ctx.fillStyle = opts.background ?? (opts.dark ? "#
|
|
1619
|
+
ctx.fillStyle = opts.background ?? (opts.dark ? "#1e1e1e" : "#ffffff");
|
|
1434
1620
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
1435
1621
|
}
|
|
1436
1622
|
ctx.scale(scale, scale);
|
|
@@ -1671,11 +1857,19 @@ function useMermaidViewer(opts) {
|
|
|
1671
1857
|
getSvg
|
|
1672
1858
|
};
|
|
1673
1859
|
}
|
|
1674
|
-
var
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
}
|
|
1860
|
+
var BACKGROUND_PRESETS = [
|
|
1861
|
+
{ value: null, label: "\u9810\u8A2D / \u900F\u660E" },
|
|
1862
|
+
{ value: "#FFFFFF", label: "\u767D" },
|
|
1863
|
+
{ value: "#F3F4F6", label: "\u6DFA\u7070" },
|
|
1864
|
+
{ value: "#EFF6FF", label: "\u6DFA\u85CD" },
|
|
1865
|
+
{ value: "#FEFCE8", label: "\u6DFA\u9EC3" },
|
|
1866
|
+
{ value: "#FDF2F8", label: "\u6DFA\u73AB\u7470" }
|
|
1867
|
+
];
|
|
1868
|
+
var PATTERN_OPTIONS = [
|
|
1869
|
+
{ value: "none", glyph: "\u25A2", label: "\u7121" },
|
|
1870
|
+
{ value: "dots", glyph: "\u283F", label: "\u7DB2\u9EDE" },
|
|
1871
|
+
{ value: "grid", glyph: "\u229E", label: "\u7DB2\u683C" }
|
|
1872
|
+
];
|
|
1679
1873
|
var DEFAULT_THEME_OPTIONS = [
|
|
1680
1874
|
{ value: "colorful", label: "Colorful" },
|
|
1681
1875
|
{ value: "sketch", label: "Excalidraw" },
|
|
@@ -1685,6 +1879,126 @@ var DEFAULT_THEME_OPTIONS = [
|
|
|
1685
1879
|
{ value: "neutral", label: "Neutral" },
|
|
1686
1880
|
{ value: "forest", label: "Forest" }
|
|
1687
1881
|
];
|
|
1882
|
+
var HEX6 = /^#[0-9a-fA-F]{6}$/;
|
|
1883
|
+
function isSameColor(a, b) {
|
|
1884
|
+
if (a === null || b === null) {
|
|
1885
|
+
return a === b;
|
|
1886
|
+
}
|
|
1887
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
1888
|
+
}
|
|
1889
|
+
function BackgroundPicker(props) {
|
|
1890
|
+
const [open, setOpen] = react.useState(false);
|
|
1891
|
+
const rootRef = react.useRef(null);
|
|
1892
|
+
react.useEffect(() => {
|
|
1893
|
+
if (!open) {
|
|
1894
|
+
return void 0;
|
|
1895
|
+
}
|
|
1896
|
+
const onDocPointer = (e) => {
|
|
1897
|
+
if (rootRef.current && !rootRef.current.contains(e.target)) {
|
|
1898
|
+
setOpen(false);
|
|
1899
|
+
}
|
|
1900
|
+
};
|
|
1901
|
+
const onKey = (e) => {
|
|
1902
|
+
if (e.key === "Escape") {
|
|
1903
|
+
setOpen(false);
|
|
1904
|
+
}
|
|
1905
|
+
};
|
|
1906
|
+
document.addEventListener("mousedown", onDocPointer);
|
|
1907
|
+
document.addEventListener("keydown", onKey);
|
|
1908
|
+
return () => {
|
|
1909
|
+
document.removeEventListener("mousedown", onDocPointer);
|
|
1910
|
+
document.removeEventListener("keydown", onKey);
|
|
1911
|
+
};
|
|
1912
|
+
}, [open]);
|
|
1913
|
+
const isPreset = BACKGROUND_PRESETS.some((p) => isSameColor(p.value, props.surface));
|
|
1914
|
+
const customActive = props.surface !== null && !isPreset;
|
|
1915
|
+
const customInputValue = props.surface && HEX6.test(props.surface) ? props.surface : "#1e293b";
|
|
1916
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rsm-bg", ref: rootRef, children: [
|
|
1917
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1918
|
+
"button",
|
|
1919
|
+
{
|
|
1920
|
+
type: "button",
|
|
1921
|
+
className: "rsm-btn rsm-bg-trigger",
|
|
1922
|
+
"aria-expanded": open,
|
|
1923
|
+
"aria-haspopup": "dialog",
|
|
1924
|
+
onClick: () => setOpen((o) => !o),
|
|
1925
|
+
title: "\u756B\u5E03\u80CC\u666F\uFF08\u5E95\u8272 + \u7DB2\u9EDE / \u7DB2\u683C\uFF0CB\uFF09",
|
|
1926
|
+
children: [
|
|
1927
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1928
|
+
"span",
|
|
1929
|
+
{
|
|
1930
|
+
className: "rsm-bg-well",
|
|
1931
|
+
"data-empty": props.surface === null ? "true" : void 0,
|
|
1932
|
+
style: props.surface ? { ["--rsm-well-color"]: props.surface } : void 0
|
|
1933
|
+
}
|
|
1934
|
+
),
|
|
1935
|
+
"\u80CC\u666F"
|
|
1936
|
+
]
|
|
1937
|
+
}
|
|
1938
|
+
),
|
|
1939
|
+
open ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rsm-bg-pop", role: "dialog", "aria-label": "\u756B\u5E03\u80CC\u666F\u8A2D\u5B9A", children: [
|
|
1940
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rsm-bg-section", children: [
|
|
1941
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rsm-bg-section-label", children: "\u5E95\u8272" }),
|
|
1942
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rsm-bg-swatches", children: [
|
|
1943
|
+
BACKGROUND_PRESETS.map((preset) => {
|
|
1944
|
+
const selected = isSameColor(preset.value, props.surface);
|
|
1945
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1946
|
+
"button",
|
|
1947
|
+
{
|
|
1948
|
+
type: "button",
|
|
1949
|
+
className: `rsm-swatch${selected ? " rsm-selected" : ""}`,
|
|
1950
|
+
"data-empty": preset.value === null ? "true" : void 0,
|
|
1951
|
+
style: preset.value ? { backgroundColor: preset.value } : void 0,
|
|
1952
|
+
title: preset.label,
|
|
1953
|
+
"aria-label": `\u5E95\u8272\uFF1A${preset.label}`,
|
|
1954
|
+
"aria-pressed": selected,
|
|
1955
|
+
onClick: () => props.onSurfaceChange(preset.value)
|
|
1956
|
+
},
|
|
1957
|
+
preset.label
|
|
1958
|
+
);
|
|
1959
|
+
}),
|
|
1960
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1961
|
+
"span",
|
|
1962
|
+
{
|
|
1963
|
+
className: `rsm-swatch rsm-swatch-custom${customActive ? " rsm-has-color rsm-selected" : ""}`,
|
|
1964
|
+
style: customActive ? { backgroundColor: props.surface } : void 0,
|
|
1965
|
+
title: "\u81EA\u8A02\u984F\u8272",
|
|
1966
|
+
children: [
|
|
1967
|
+
!customActive ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rsm-swatch-custom-icon", children: "\u{1F3A8}" }) : null,
|
|
1968
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1969
|
+
"input",
|
|
1970
|
+
{
|
|
1971
|
+
type: "color",
|
|
1972
|
+
value: customInputValue,
|
|
1973
|
+
"aria-label": "\u81EA\u8A02\u5E95\u8272",
|
|
1974
|
+
onChange: (e) => props.onSurfaceChange(e.target.value)
|
|
1975
|
+
}
|
|
1976
|
+
)
|
|
1977
|
+
]
|
|
1978
|
+
}
|
|
1979
|
+
)
|
|
1980
|
+
] })
|
|
1981
|
+
] }),
|
|
1982
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rsm-bg-section", children: [
|
|
1983
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rsm-bg-section-label", children: "\u5716\u6A23" }),
|
|
1984
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rsm-seg", role: "group", "aria-label": "\u80CC\u666F\u5716\u6A23", children: PATTERN_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1985
|
+
"button",
|
|
1986
|
+
{
|
|
1987
|
+
type: "button",
|
|
1988
|
+
"aria-pressed": props.pattern === opt.value,
|
|
1989
|
+
title: opt.label,
|
|
1990
|
+
onClick: () => props.onPatternChange(opt.value),
|
|
1991
|
+
children: [
|
|
1992
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "rsm-seg-glyph", "aria-hidden": "true", children: opt.glyph }),
|
|
1993
|
+
opt.label
|
|
1994
|
+
]
|
|
1995
|
+
},
|
|
1996
|
+
opt.value
|
|
1997
|
+
)) })
|
|
1998
|
+
] })
|
|
1999
|
+
] }) : null
|
|
2000
|
+
] });
|
|
2001
|
+
}
|
|
1688
2002
|
function Toolbar(props) {
|
|
1689
2003
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rsm-toolbar", children: [
|
|
1690
2004
|
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "rsm-label", children: [
|
|
@@ -1699,18 +2013,13 @@ function Toolbar(props) {
|
|
|
1699
2013
|
}
|
|
1700
2014
|
)
|
|
1701
2015
|
] }),
|
|
1702
|
-
props.backgroundEnabled ? /* @__PURE__ */ jsxRuntime.
|
|
1703
|
-
|
|
2016
|
+
props.backgroundEnabled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2017
|
+
BackgroundPicker,
|
|
1704
2018
|
{
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
children: [
|
|
1710
|
-
BACKGROUND_LABELS[props.background].icon,
|
|
1711
|
-
" \u80CC\u666F\uFF1A",
|
|
1712
|
-
BACKGROUND_LABELS[props.background].label
|
|
1713
|
-
]
|
|
2019
|
+
surface: props.surface,
|
|
2020
|
+
onSurfaceChange: props.onSurfaceChange,
|
|
2021
|
+
pattern: props.pattern,
|
|
2022
|
+
onPatternChange: props.onPatternChange
|
|
1714
2023
|
}
|
|
1715
2024
|
) : null,
|
|
1716
2025
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rsm-toolbar-spacer" }),
|
|
@@ -1780,7 +2089,24 @@ function Toolbar(props) {
|
|
|
1780
2089
|
) : null
|
|
1781
2090
|
] });
|
|
1782
2091
|
}
|
|
1783
|
-
var
|
|
2092
|
+
var PATTERN_CYCLE = ["none", "dots", "grid"];
|
|
2093
|
+
function defaultSolidColor(dark) {
|
|
2094
|
+
return dark ? "#1e1e1e" : "#ffffff";
|
|
2095
|
+
}
|
|
2096
|
+
function patternInk(surface, dark) {
|
|
2097
|
+
const m = surface ? /^#([0-9a-fA-F]{6})$/.exec(surface) : null;
|
|
2098
|
+
let lightCanvas;
|
|
2099
|
+
if (m) {
|
|
2100
|
+
const r = parseInt(m[1].slice(0, 2), 16);
|
|
2101
|
+
const g = parseInt(m[1].slice(2, 4), 16);
|
|
2102
|
+
const b = parseInt(m[1].slice(4, 6), 16);
|
|
2103
|
+
lightCanvas = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255 > 0.5;
|
|
2104
|
+
} else {
|
|
2105
|
+
lightCanvas = !dark;
|
|
2106
|
+
}
|
|
2107
|
+
const ink = lightCanvas ? "15, 23, 42" : "226, 232, 240";
|
|
2108
|
+
return { dot: `rgba(${ink}, 0.34)`, line: `rgba(${ink}, 0.2)` };
|
|
2109
|
+
}
|
|
1784
2110
|
function usePrefersDark(explicit) {
|
|
1785
2111
|
const [autoDark, setAutoDark] = react.useState(false);
|
|
1786
2112
|
react.useEffect(() => {
|
|
@@ -1830,14 +2156,18 @@ var MermaidViewer = react.forwardRef(
|
|
|
1830
2156
|
const [query, setQuery] = react.useState("");
|
|
1831
2157
|
const [matchInfo, setMatchInfo] = react.useState({ current: 0, total: 0 });
|
|
1832
2158
|
const [exporting, setExporting] = react.useState(false);
|
|
1833
|
-
const [
|
|
1834
|
-
|
|
1835
|
-
|
|
2159
|
+
const [pattern, setPatternState] = react.useState(props.pattern ?? "dots");
|
|
2160
|
+
react.useEffect(() => {
|
|
2161
|
+
if (props.pattern) {
|
|
2162
|
+
setPatternState(props.pattern);
|
|
2163
|
+
}
|
|
2164
|
+
}, [props.pattern]);
|
|
2165
|
+
const [solidColor, setSolidColorState] = react.useState(props.solidColor ?? null);
|
|
1836
2166
|
react.useEffect(() => {
|
|
1837
|
-
if (props.
|
|
1838
|
-
|
|
2167
|
+
if (props.solidColor !== void 0) {
|
|
2168
|
+
setSolidColorState(props.solidColor);
|
|
1839
2169
|
}
|
|
1840
|
-
}, [props.
|
|
2170
|
+
}, [props.solidColor]);
|
|
1841
2171
|
const [isFullscreen, setIsFullscreen] = react.useState(false);
|
|
1842
2172
|
const rootRef = react.useRef(null);
|
|
1843
2173
|
const searchInputRef = react.useRef(null);
|
|
@@ -1894,21 +2224,27 @@ var MermaidViewer = react.forwardRef(
|
|
|
1894
2224
|
const exportPng = react.useCallback(async () => {
|
|
1895
2225
|
setExporting(true);
|
|
1896
2226
|
try {
|
|
1897
|
-
|
|
2227
|
+
const paper = solidColor ?? defaultSolidColor(dark);
|
|
2228
|
+
const transparent = solidColor === null && pattern === "none";
|
|
2229
|
+
const bgOpt = transparent ? { transparent: true } : { background: paper };
|
|
2230
|
+
await vm.downloadPng("diagram.png", { scale: 2, ...bgOpt });
|
|
1898
2231
|
} catch (e) {
|
|
1899
2232
|
onError?.(e instanceof Error ? e : new Error(String(e)));
|
|
1900
2233
|
} finally {
|
|
1901
2234
|
setExporting(false);
|
|
1902
2235
|
}
|
|
1903
|
-
}, [vm, onError]);
|
|
1904
|
-
const
|
|
1905
|
-
|
|
1906
|
-
const i =
|
|
1907
|
-
return
|
|
2236
|
+
}, [vm, onError, pattern, solidColor, dark]);
|
|
2237
|
+
const cyclePattern = react.useCallback(() => {
|
|
2238
|
+
setPatternState((prev) => {
|
|
2239
|
+
const i = PATTERN_CYCLE.indexOf(prev);
|
|
2240
|
+
return PATTERN_CYCLE[(i + 1) % PATTERN_CYCLE.length];
|
|
1908
2241
|
});
|
|
1909
2242
|
}, []);
|
|
1910
|
-
const
|
|
1911
|
-
|
|
2243
|
+
const setPattern = react.useCallback((next) => {
|
|
2244
|
+
setPatternState(next);
|
|
2245
|
+
}, []);
|
|
2246
|
+
const setSolidColor = react.useCallback((color) => {
|
|
2247
|
+
setSolidColorState(color);
|
|
1912
2248
|
}, []);
|
|
1913
2249
|
const enterFullscreen = react.useCallback(() => {
|
|
1914
2250
|
setIsFullscreen((prev) => {
|
|
@@ -2028,7 +2364,7 @@ var MermaidViewer = react.forwardRef(
|
|
|
2028
2364
|
toggleFullscreen();
|
|
2029
2365
|
} else if (backgroundEnabled && (e.key === "b" || e.key === "B")) {
|
|
2030
2366
|
e.preventDefault();
|
|
2031
|
-
|
|
2367
|
+
cyclePattern();
|
|
2032
2368
|
}
|
|
2033
2369
|
};
|
|
2034
2370
|
root.addEventListener("keydown", onKey);
|
|
@@ -2042,7 +2378,7 @@ var MermaidViewer = react.forwardRef(
|
|
|
2042
2378
|
isFullscreen,
|
|
2043
2379
|
exitFullscreen,
|
|
2044
2380
|
toggleFullscreen,
|
|
2045
|
-
|
|
2381
|
+
cyclePattern,
|
|
2046
2382
|
fullscreenEnabled,
|
|
2047
2383
|
backgroundEnabled
|
|
2048
2384
|
]);
|
|
@@ -2068,9 +2404,11 @@ var MermaidViewer = react.forwardRef(
|
|
|
2068
2404
|
exitFullscreen,
|
|
2069
2405
|
toggleFullscreen,
|
|
2070
2406
|
isFullscreen: () => isFullscreen,
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2407
|
+
setPattern,
|
|
2408
|
+
cyclePattern,
|
|
2409
|
+
getPattern: () => pattern,
|
|
2410
|
+
setSolidColor,
|
|
2411
|
+
getSolidColor: () => solidColor
|
|
2074
2412
|
}),
|
|
2075
2413
|
[
|
|
2076
2414
|
vm,
|
|
@@ -2078,9 +2416,11 @@ var MermaidViewer = react.forwardRef(
|
|
|
2078
2416
|
exitFullscreen,
|
|
2079
2417
|
toggleFullscreen,
|
|
2080
2418
|
isFullscreen,
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2419
|
+
setPattern,
|
|
2420
|
+
cyclePattern,
|
|
2421
|
+
pattern,
|
|
2422
|
+
setSolidColor,
|
|
2423
|
+
solidColor
|
|
2084
2424
|
]
|
|
2085
2425
|
);
|
|
2086
2426
|
let countText = "";
|
|
@@ -2092,16 +2432,23 @@ var MermaidViewer = react.forwardRef(
|
|
|
2092
2432
|
const rootClassName = [
|
|
2093
2433
|
"rsm-root",
|
|
2094
2434
|
dark ? "rsm-dark" : "",
|
|
2095
|
-
`rsm-
|
|
2435
|
+
`rsm-pattern-${pattern}`,
|
|
2096
2436
|
isFullscreen ? "rsm-fullscreen" : "",
|
|
2097
2437
|
className ?? ""
|
|
2098
2438
|
].filter(Boolean).join(" ");
|
|
2439
|
+
const ink = patternInk(solidColor, dark);
|
|
2440
|
+
const rootStyle = {
|
|
2441
|
+
...style ?? {},
|
|
2442
|
+
["--rsm-grid-dot"]: ink.dot,
|
|
2443
|
+
["--rsm-grid-line"]: ink.line,
|
|
2444
|
+
...solidColor ? { ["--rsm-canvas-bg"]: solidColor } : {}
|
|
2445
|
+
};
|
|
2099
2446
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2100
2447
|
"div",
|
|
2101
2448
|
{
|
|
2102
2449
|
ref: rootRef,
|
|
2103
2450
|
className: rootClassName,
|
|
2104
|
-
style,
|
|
2451
|
+
style: rootStyle,
|
|
2105
2452
|
tabIndex: keyboard ? 0 : void 0,
|
|
2106
2453
|
children: [
|
|
2107
2454
|
toolbar ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2123,8 +2470,10 @@ var MermaidViewer = react.forwardRef(
|
|
|
2123
2470
|
onExportSvg: exportSvg,
|
|
2124
2471
|
onExportPng: exportPng,
|
|
2125
2472
|
backgroundEnabled,
|
|
2126
|
-
|
|
2127
|
-
|
|
2473
|
+
surface: solidColor,
|
|
2474
|
+
onSurfaceChange: setSolidColor,
|
|
2475
|
+
pattern,
|
|
2476
|
+
onPatternChange: setPattern,
|
|
2128
2477
|
fullscreenEnabled,
|
|
2129
2478
|
fullscreen: isFullscreen,
|
|
2130
2479
|
onToggleFullscreen: toggleFullscreen
|
|
@@ -2191,10 +2540,12 @@ var MermaidDiagram = react.forwardRef(
|
|
|
2191
2540
|
}
|
|
2192
2541
|
);
|
|
2193
2542
|
|
|
2543
|
+
exports.BACKGROUND_PRESETS = BACKGROUND_PRESETS;
|
|
2194
2544
|
exports.DEFAULT_THEME_OPTIONS = DEFAULT_THEME_OPTIONS;
|
|
2195
2545
|
exports.DEFAULT_VIRGIL_FONT_URL = DEFAULT_VIRGIL_FONT_URL;
|
|
2196
2546
|
exports.MermaidDiagram = MermaidDiagram;
|
|
2197
2547
|
exports.MermaidViewer = MermaidViewer;
|
|
2548
|
+
exports.PATTERN_OPTIONS = PATTERN_OPTIONS;
|
|
2198
2549
|
exports.SKETCH_FONT = SKETCH_FONT;
|
|
2199
2550
|
exports.Toolbar = Toolbar;
|
|
2200
2551
|
exports.boostLegibility = boostLegibility;
|