@docyrus/ui-pro-ai-assistant 0.6.2 → 0.6.4

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.
@@ -4,5 +4,5 @@ interface MermaidDiagramProps {
4
4
  mermaidNotation: string;
5
5
  state?: string;
6
6
  }
7
- export declare function MermaidDiagram({ title, description, mermaidNotation, state }: MermaidDiagramProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function MermaidDiagram({ title, description, mermaidNotation }: MermaidDiagramProps): import("react/jsx-runtime").JSX.Element;
8
8
  export {};
package/dist/index.js CHANGED
@@ -12377,10 +12377,23 @@ function GenerativeActionButton({
12377
12377
  }
12378
12378
  );
12379
12379
  }
12380
+ var STREAMING_DEBOUNCE_MS = 250;
12381
+ var mermaidPromise = null;
12382
+ var loadMermaid = () => {
12383
+ if (!mermaidPromise) {
12384
+ mermaidPromise = import('mermaid').then((mod) => {
12385
+ mod.default.initialize({ startOnLoad: false, securityLevel: "loose" });
12386
+ return mod.default;
12387
+ });
12388
+ }
12389
+ return mermaidPromise;
12390
+ };
12380
12391
  function MermaidRender({ content, className }) {
12381
12392
  const containerRef = useRef(null);
12382
- const svgRef = useRef(null);
12383
- const [svg, setSvg] = useState("");
12393
+ const svgHostRef = useRef(null);
12394
+ const sandboxRef = useRef(null);
12395
+ const [status, setStatus] = useState("idle");
12396
+ const [errorMessage, setErrorMessage] = useState(null);
12384
12397
  const [zoom, setZoom] = useState(1);
12385
12398
  const [pan, setPan] = useState({ x: 0, y: 0 });
12386
12399
  const isDragging = useRef(false);
@@ -12388,20 +12401,34 @@ function MermaidRender({ content, className }) {
12388
12401
  useEffect(() => {
12389
12402
  if (!content) return;
12390
12403
  let cancelled = false;
12391
- const render = async () => {
12404
+ const debounce = window.setTimeout(async () => {
12392
12405
  try {
12393
- const { default: mermaid } = await import('mermaid');
12394
- mermaid.initialize({ startOnLoad: false, securityLevel: "loose" });
12406
+ const mermaid = await loadMermaid();
12407
+ if (cancelled) return;
12408
+ const valid = await mermaid.parse(content, { suppressErrors: true });
12409
+ if (cancelled) return;
12410
+ if (!valid) {
12411
+ setErrorMessage("Invalid mermaid syntax");
12412
+ setStatus("error");
12413
+ return;
12414
+ }
12395
12415
  const id = `mermaid-${Math.random().toString(36).slice(2)}`;
12396
- const { svg: rendered } = await mermaid.render(id, content);
12397
- if (!cancelled) setSvg(rendered);
12416
+ const sandbox = sandboxRef.current ?? void 0;
12417
+ const { svg } = await mermaid.render(id, content, sandbox);
12418
+ if (cancelled) return;
12419
+ if (svgHostRef.current) svgHostRef.current.innerHTML = svg;
12420
+ setErrorMessage(null);
12421
+ setStatus("rendered");
12398
12422
  } catch (err) {
12423
+ if (cancelled) return;
12399
12424
  console.error("Mermaid render error:", err);
12425
+ setErrorMessage("Failed to render diagram");
12426
+ setStatus("error");
12400
12427
  }
12401
- };
12402
- render();
12428
+ }, STREAMING_DEBOUNCE_MS);
12403
12429
  return () => {
12404
12430
  cancelled = true;
12431
+ window.clearTimeout(debounce);
12405
12432
  };
12406
12433
  }, [content]);
12407
12434
  const zoomIn = () => setZoom((z) => Math.min(z + 0.15, 4));
@@ -12410,10 +12437,16 @@ function MermaidRender({ content, className }) {
12410
12437
  setZoom(1);
12411
12438
  setPan({ x: 0, y: 0 });
12412
12439
  };
12413
- const onWheel = useCallback((e) => {
12414
- e.preventDefault();
12415
- const delta = e.deltaY > 0 ? -0.1 : 0.1;
12416
- setZoom((z) => Math.min(Math.max(z + delta, 0.2), 4));
12440
+ useEffect(() => {
12441
+ const el = containerRef.current;
12442
+ if (!el) return;
12443
+ const handleWheel = (e) => {
12444
+ e.preventDefault();
12445
+ const delta = e.deltaY > 0 ? -0.1 : 0.1;
12446
+ setZoom((z) => Math.min(Math.max(z + delta, 0.2), 4));
12447
+ };
12448
+ el.addEventListener("wheel", handleWheel, { passive: false });
12449
+ return () => el.removeEventListener("wheel", handleWheel);
12417
12450
  }, []);
12418
12451
  const onMouseDown = useCallback((e) => {
12419
12452
  isDragging.current = true;
@@ -12438,19 +12471,18 @@ function MermaidRender({ content, className }) {
12438
12471
  "bg-[radial-gradient(circle,_#94a3b8_1px,_transparent_1px)] bg-[size:22px_22px] bg-slate-50",
12439
12472
  className
12440
12473
  ),
12441
- onWheel,
12442
12474
  onMouseDown,
12443
12475
  onMouseMove,
12444
12476
  onMouseUp,
12445
12477
  onMouseLeave: onMouseUp,
12446
12478
  children: [
12447
- /* @__PURE__ */ jsx(
12479
+ /* @__PURE__ */ jsx("div", { ref: sandboxRef, "aria-hidden": true, className: "absolute -left-[99999px] top-0 h-0 w-0 overflow-hidden" }),
12480
+ status === "error" ? /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center p-4 text-xs text-muted-foreground", children: errorMessage }) : /* @__PURE__ */ jsx(
12448
12481
  "div",
12449
12482
  {
12450
- ref: svgRef,
12483
+ ref: svgHostRef,
12451
12484
  className: "absolute inset-0 flex items-center justify-center",
12452
- style: { transform: `translate(${pan.x}px, ${pan.y}px) scale(${zoom})`, transformOrigin: "center" },
12453
- dangerouslySetInnerHTML: { __html: svg }
12485
+ style: { transform: `translate(${pan.x}px, ${pan.y}px) scale(${zoom})`, transformOrigin: "center" }
12454
12486
  }
12455
12487
  ),
12456
12488
  /* @__PURE__ */ jsxs("div", { className: "absolute bottom-3 left-3 z-10 flex gap-1", children: [
@@ -12465,11 +12497,10 @@ function MermaidRender({ content, className }) {
12465
12497
  function MermaidDiagram({
12466
12498
  title,
12467
12499
  description,
12468
- mermaidNotation,
12469
- state
12500
+ mermaidNotation
12470
12501
  }) {
12471
12502
  const [modalOpen, setModalOpen] = useState(false);
12472
- if (state !== "output-available") {
12503
+ if (!mermaidNotation) {
12473
12504
  return /* @__PURE__ */ jsx("div", { className: "w-full h-[400px] rounded-lg border bg-muted/30 animate-pulse" });
12474
12505
  }
12475
12506
  return /* @__PURE__ */ jsxs(Fragment, { children: [