@mieweb/ui 0.6.1-dev.166 → 0.6.1-dev.168

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.
@@ -36,7 +36,7 @@ function CopyablePre({
36
36
  type: "button",
37
37
  onClick: onCopy,
38
38
  "aria-label": copied ? "Copied" : "Copy code",
39
- className: "absolute top-2 right-2 rounded-md bg-neutral-700/80 px-2 py-1 text-xs text-neutral-100 opacity-0 transition-opacity group-hover:opacity-100 hover:bg-neutral-600 focus-visible:opacity-100",
39
+ className: "absolute top-2 right-2 rounded-md border border-neutral-300 bg-white/80 px-2 py-1 text-xs text-neutral-700 opacity-0 shadow-sm transition-opacity group-hover:opacity-100 hover:bg-neutral-100 focus-visible:opacity-100 dark:border-neutral-600 dark:bg-neutral-700/80 dark:text-neutral-100 dark:hover:bg-neutral-600",
40
40
  children: copied ? "Copied" : "Copy"
41
41
  }
42
42
  ),
@@ -47,7 +47,9 @@ function CopyablePre({
47
47
  ref,
48
48
  tabIndex: 0,
49
49
  className: cn(
50
- "overflow-x-auto rounded-lg bg-neutral-900 p-3 text-sm text-neutral-100 dark:bg-neutral-950",
50
+ // Background/text follow the theme so light mode matches the
51
+ // atom-one-light hljs palette (dark background looked out of place).
52
+ "overflow-x-auto rounded-lg border border-neutral-200 bg-neutral-50 p-3 text-sm text-neutral-800 dark:border-transparent dark:bg-neutral-900 dark:text-neutral-100",
51
53
  props.className
52
54
  )
53
55
  }
@@ -342,6 +344,23 @@ function createGenUIPlugin(registry) {
342
344
  };
343
345
  }
344
346
  var MERMAID_TAG = "mermaid-diagram";
347
+ var MERMAID_DECLARATION_RE = /^\s*(?:flowchart|graph|sequenceDiagram|classDiagram|stateDiagram(?:-v2)?|erDiagram|journey|gantt|pie|mindmap|timeline|gitGraph|quadrantChart|requirementDiagram|block-beta|xychart-beta)\b/;
348
+ var FENCE_LINE_RE = /^\s*```[\w-]*\s*$/;
349
+ var MERMAID_DIRECTIVE_RE = /^\s*%%/;
350
+ function normalizeMermaidSource(code) {
351
+ const lines = code.split(/\r?\n/);
352
+ const stripped = lines.filter((line) => !FENCE_LINE_RE.test(line));
353
+ const declarationIdx = stripped.findIndex(
354
+ (line) => MERMAID_DECLARATION_RE.test(line)
355
+ );
356
+ if (declarationIdx < 0) return stripped.join("\n").trim();
357
+ const preamble = [];
358
+ for (let i = 0; i < declarationIdx; i += 1) {
359
+ const line = stripped[i];
360
+ if (MERMAID_DIRECTIVE_RE.test(line)) preamble.push(line);
361
+ }
362
+ return [...preamble, ...stripped.slice(declarationIdx)].join("\n").trim();
363
+ }
345
364
  function textOf2(node) {
346
365
  if (node.type === "text") return node.value ?? "";
347
366
  return (node.children ?? []).map(textOf2).join("");
@@ -409,6 +428,23 @@ function InertFallback2({ raw }) {
409
428
  }
410
429
  var mermaidReady = null;
411
430
  var mermaidTheme = null;
431
+ async function renderMermaidWithRecovery(mermaid, id, source) {
432
+ const lines = source.split(/\r?\n/).map((line) => line.trimEnd());
433
+ let lastError;
434
+ for (let end = lines.length; end >= 1; end -= 1) {
435
+ const candidate = lines.slice(0, end).join("\n").trim();
436
+ if (!candidate) continue;
437
+ try {
438
+ return await mermaid.render(id, candidate);
439
+ } catch (error) {
440
+ lastError = error;
441
+ }
442
+ }
443
+ if (lastError instanceof Error) throw lastError;
444
+ throw new Error(
445
+ typeof lastError === "string" ? lastError : `Failed to parse mermaid diagram: ${String(lastError)}`
446
+ );
447
+ }
412
448
  function loadMermaid(dark) {
413
449
  const theme = dark ? "dark" : "default";
414
450
  if (!mermaidReady || mermaidTheme !== theme) {
@@ -417,27 +453,55 @@ function loadMermaid(dark) {
417
453
  mermaid.initialize({
418
454
  startOnLoad: false,
419
455
  securityLevel: "strict",
420
- theme
456
+ theme,
457
+ flowchart: { useMaxWidth: false },
458
+ themeVariables: { fontSize: "16px" }
421
459
  });
422
460
  return mermaid;
423
461
  });
424
462
  }
425
463
  return mermaidReady;
426
464
  }
465
+ function isDarkMode() {
466
+ if (typeof document === "undefined") return false;
467
+ const root = document.documentElement;
468
+ return root.classList.contains("dark") || root.getAttribute("data-theme") === "dark";
469
+ }
470
+ function useIsDarkMode() {
471
+ const [dark, setDark] = React2.useState(isDarkMode);
472
+ React2.useEffect(() => {
473
+ if (typeof document === "undefined") return;
474
+ const root = document.documentElement;
475
+ const update = () => setDark(isDarkMode());
476
+ update();
477
+ const observer = new MutationObserver(update);
478
+ observer.observe(root, {
479
+ attributes: true,
480
+ attributeFilter: ["class", "data-theme"]
481
+ });
482
+ return () => observer.disconnect();
483
+ }, []);
484
+ return dark;
485
+ }
427
486
  var mermaidSeq = 0;
428
487
  function MermaidDiagram({ code }) {
429
488
  const { streaming } = useTextRenderContext();
489
+ const dark = useIsDarkMode();
430
490
  const [svg, setSvg] = React2.useState(null);
431
491
  const [failed, setFailed] = React2.useState(false);
432
- const idRef = React2.useRef(`superchat-mermaid-${mermaidSeq += 1}`);
433
- const source = code.trim();
492
+ const idRef = React2.useRef(null);
493
+ if (idRef.current === null) {
494
+ mermaidSeq += 1;
495
+ idRef.current = `superchat-mermaid-${mermaidSeq}`;
496
+ }
497
+ const id = idRef.current;
498
+ const source = React2.useMemo(() => normalizeMermaidSource(code), [code]);
434
499
  React2.useEffect(() => {
435
500
  if (streaming || !source) return;
436
501
  let active = true;
437
502
  setSvg(null);
438
503
  setFailed(false);
439
- const dark = typeof document !== "undefined" && document.documentElement.classList.contains("dark");
440
- void loadMermaid(dark).then((mermaid) => mermaid.render(idRef.current, source)).then(({ svg: rendered }) => {
504
+ void loadMermaid(dark).then((mermaid) => renderMermaidWithRecovery(mermaid, id, source)).then(({ svg: rendered }) => {
441
505
  if (active) setSvg(rendered);
442
506
  }).catch(() => {
443
507
  if (active) setFailed(true);
@@ -445,7 +509,7 @@ function MermaidDiagram({ code }) {
445
509
  return () => {
446
510
  active = false;
447
511
  };
448
- }, [source, streaming]);
512
+ }, [source, streaming, dark, id]);
449
513
  if (!source && !streaming) return /* @__PURE__ */ jsx(InertFallback2, { raw: code });
450
514
  if (failed) return /* @__PURE__ */ jsx(InertFallback2, { raw: code });
451
515
  if (streaming || svg === null) {
@@ -455,7 +519,7 @@ function MermaidDiagram({ code }) {
455
519
  "div",
456
520
  {
457
521
  "data-slot": "superchat-mermaid",
458
- className: "my-2 overflow-x-auto",
522
+ className: "my-2 overflow-x-auto [&_svg]:h-auto [&_svg]:max-w-none",
459
523
  dangerouslySetInnerHTML: { __html: svg }
460
524
  }
461
525
  );