From 853ed6e099e6fa06b9ef3b6a8c1f37f23fbac30b Mon Sep 17 00:00:00 2001 From: danshuitaihejie <474182370@qq.com> Date: Tue, 10 Jun 2025 07:26:47 +0800 Subject: [PATCH 01/11] feat: enhance diagram interaction with cursor tracking and element highlighting --- index.html | 11 ++++- src/assets/tailwind.css | 4 ++ .../SeqDiagram/MessageLayer/MessageLabel.tsx | 40 ++++++++++++++++++- src/core.tsx | 21 ++++++++++ src/store/Store.ts | 4 +- 5 files changed, 76 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index e9ed36ce..6a34751e 100644 --- a/index.html +++ b/index.html @@ -89,9 +89,12 @@ singleCursorHeightPerLine: false, }); - const updateDiagram = debounce((content) => { + const updateDiagram = debounce((content, cursor) => { const config = createConfig({ onContentChange: (code) => editor.setValue(code), + cursor: cursor, + enableCurrentElementScrollIntoView: true, + enableCurrentElementHighlight: true, }); window.zenUml.render(content, config).then((r) => { @@ -105,13 +108,17 @@ waitUntil( () => window.zenUml, () => { - updateDiagram(cm.getValue()); + updateDiagram(cm.getValue(), cm.indexFromPos(cm.getCursor())); // Save to localStorage localStorage.setItem("zenuml-cm-code", cm.getValue()); }, ); }); + editor.on("cursorActivity", function (cm) { + updateDiagram(cm.getValue(), cm.indexFromPos(cm.getCursor())); + }); + // Load saved code from localStorage const savedCode = localStorage.getItem("zenuml-cm-code"); if (savedCode) { diff --git a/src/assets/tailwind.css b/src/assets/tailwind.css index 03feee66..f2c9a2c0 100644 --- a/src/assets/tailwind.css +++ b/src/assets/tailwind.css @@ -19,6 +19,10 @@ serif; } +.zenuml .highlight { + background-color: rgba(255, 255, 0, 0.3); +} + @layer base { :root { --color-bg-base: #ffffff; diff --git a/src/components/DiagramFrame/SeqDiagram/MessageLayer/MessageLabel.tsx b/src/components/DiagramFrame/SeqDiagram/MessageLayer/MessageLabel.tsx index 40dcde61..2c2e1acb 100644 --- a/src/components/DiagramFrame/SeqDiagram/MessageLayer/MessageLabel.tsx +++ b/src/components/DiagramFrame/SeqDiagram/MessageLayer/MessageLabel.tsx @@ -1,10 +1,18 @@ -import { codeAtom, modeAtom, onContentChangeAtom } from "@/store/Store"; +import { + codeAtom, + modeAtom, + onContentChangeAtom, + cursorAtom, + enableCurrentElementHighlightAtom, + enableCurrentElementScrollIntoViewAtom, +} from "@/store/Store"; import { cn } from "@/utils"; import { useAtom, useAtomValue } from "jotai"; import { formatText } from "@/utils/StringUtil"; import { useEditLabel, specialCharRegex } from "@/functions/useEditLabel"; import { RenderMode } from "@/store/Store"; import type { FocusEvent, KeyboardEvent, MouseEvent } from "react"; +import { useEffect, useRef } from "react"; export const MessageLabel = (props: { labelText: string; @@ -16,8 +24,36 @@ export const MessageLabel = (props: { }) => { const mode = useAtomValue(modeAtom); const [code, setCode] = useAtom(codeAtom); + const cursor = useAtomValue(cursorAtom); const onContentChange = useAtomValue(onContentChangeAtom); + const enableCurrentElementHighlight = useAtomValue( + enableCurrentElementHighlightAtom, + ); + const enableCurrentElementScrollIntoView = useAtomValue( + enableCurrentElementScrollIntoViewAtom, + ); const formattedLabelText = formatText(props.labelText); + const labelRef = useRef(null); + + const isCurrent = + cursor != null && + cursor >= props.labelPosition[0] && + cursor <= props.labelPosition[1] + 1; + + useEffect(() => { + if ( + isCurrent && + props.labelText && + labelRef.current && + enableCurrentElementScrollIntoView + ) { + labelRef.current.scrollIntoView({ + behavior: "smooth", + block: "center", + inline: "nearest", + }); + } + }, [isCurrent, props.labelText, enableCurrentElementScrollIntoView]); const replaceLabelText = (e: FocusEvent | KeyboardEvent | MouseEvent) => { e.preventDefault(); @@ -61,10 +97,12 @@ export const MessageLabel = (props: { return (