소스 검색

feat: 添加基础图形部分的图形

liaojiaxing 7 달 전
부모
커밋
f11cac6550

+ 118 - 18
apps/designer/src/components/basic/CodeBlock.tsx

@@ -1,39 +1,139 @@
+import { CompoundedComponent } from "@/types";
 import { register } from "@antv/x6-react-shape";
-import { Node } from "@antv/x6";
-import { ports, defaultData } from "./data";
+import { Graph, Node } from "@antv/x6";
+import { defaultData } from "../data";
 import { useSizeHook } from "@/hooks";
-const component = ({ node }: { node: Node }) => {
-  const { fill, stroke, opacity } = node.getData();
+import { rosePineDawn } from "thememirror";
+import CodeMirror from "@uiw/react-codemirror";
+
+import { javascript } from "@codemirror/lang-javascript";
+import { css } from "@codemirror/lang-css";
+import { go } from "@codemirror/lang-go";
+import { html } from "@codemirror/lang-html";
+import { java } from "@codemirror/lang-java";
+import { php } from "@codemirror/lang-php";
+import { python } from "@codemirror/lang-python";
+import { rust } from "@codemirror/lang-rust";
+import { sql } from "@codemirror/lang-sql";
+import { vue } from "@codemirror/lang-vue";
+import { xml } from "@codemirror/lang-xml";
+import { yaml } from "@codemirror/lang-yaml";
+import { Button, message, Select, Tooltip } from "antd";
+import { useState } from "react";
+
+const langMap = {
+  javascript: javascript(),
+  css: css(),
+  go: go(),
+  html: html(),
+  java: java(),
+  php: php(),
+  python: python(),
+  rust: rust(),
+  sql: sql(),
+  vue: vue(),
+  xml: xml(),
+  yaml: yaml(),
+};
+
+const component = ({ node, graph }: { node: Node, graph: Graph }) => {
+  const { code, language } = node.getData<{
+    language:
+      | "javascript"
+      | "css"
+      | "go"
+      | "html"
+      | "java"
+      | "php"
+      | "python"
+      | "rust"
+      | "sql"
+      | "vue"
+      | "xml"
+      | "yaml";
+    code: string;
+  }>();
+
   const { size, ref } = useSizeHook();
+  const [showSetting, setShowSetting] = useState(false);
+
+  const languageOptions = [
+    { value: "javascript", label: "JavaScript" },
+    { value: "css", label: "CSS" },
+    { value: "go", label: "Go" },
+    { value: "html", label: "HTML" },
+    { value: "java", label: "Java" },
+    { value: "php", label: "PHP" },
+    { value: "python", label: "Python" },
+    { value: "rust", label: "Rust" },
+    { value: "sql", label: "SQL" },
+    { value: "typescript", label: "TypeScript" },
+    { value: "xml", label: "XML" },
+    { value: "yaml", label: "YAML" },
+  ]
+
+  const handleCopy = () => {
+    navigator.clipboard.writeText(code).then(() => {
+      message.success("复制成功");
+    })
+  }
+
+  graph.on("node:selected", (args) => {
+    setShowSetting(graph.getSelectedCells().length === 1 && node.id === args.node.id);
+  });
+  graph.on("node:unselected", () => {
+    setShowSetting(false);
+  });
 
   return (
     <>
-      <div
-        className="relative text-0 w-full h-full"
-        ref={ref}
-        style={{ opacity: opacity / 100 }}
-      >
-        
+      <div className="relative w-full h-full" ref={ref} autoFocus onFocus={() => setShowSetting(true)}>
+        {
+          showSetting && (
+            <div className="absolute" style={{ left: 0, top: -35, zIndex: 1 }}>
+              <Tooltip title="切换代码语言">
+                <Select style={{ width: 120 }} value={language} options={languageOptions} onChange={(l) => node.setData({ language: l})}/>
+              </Tooltip>
+              <Tooltip title="复制内容">
+                <Button icon={<i className="iconfont icon-fuzhi"/>} onClick={handleCopy}></Button>
+              </Tooltip>
+            </div>
+          )
+        }
+        <CodeMirror
+          value={code}
+          height={size.height + "px"}
+          width={size.width + "px"}
+          extensions={[rosePineDawn, langMap[language]]}
+          onChange={(val) => {
+            node.setData({ code: val });
+          }}
+        />
       </div>
     </>
   );
 };
 
 register({
-  shape: "custom-react-code",
-  width: 100,
-  height: 100,
+  shape: "custom-react-codeBlock",
+  width: 420,
+  height: 355,
   effect: ["data"],
   component: component,
 });
 
-const codeBlock = {
-    shape: "custom-react-code",
+const codeBlock: CompoundedComponent = {
+  name: "代码块",
+  icon: require("./image/code.svg").default,
+  node: {
+    shape: "custom-react-codeBlock",
     data: {
-      label: "",
+      isCode: true,
+      code: ``,
+      language: "javascript",
       ...defaultData,
     },
-    ports,
-  };
+  },
+};
 
 export default codeBlock;

+ 83 - 0
apps/designer/src/components/basic/braces.tsx

@@ -0,0 +1,83 @@
+import { CompoundedComponent } from "@/types";
+import { register } from "@antv/x6-react-shape";
+import { Node } from "@antv/x6";
+import { ports, defaultData } from "../data";
+import CustomInput from "../CustomInput";
+import { useSizeHook, useShapeProps } from "@/hooks";
+const component = ({ node }: { node: Node }) => {
+  const { label, text, fill, stroke, opacity } = node.getData();
+  const { size, ref } = useSizeHook();
+  const {
+    fillContent,
+    defsContent,
+    strokeColor,
+    strokeWidth,
+    strokeDasharray,
+  } = useShapeProps(fill, size, stroke);
+
+  const { width: w, height: h } = size;
+
+  return (
+    <>
+      <div
+        className="relative text-0 w-full h-full"
+        ref={ref}
+        style={{ opacity: opacity / 100 }}
+      >
+        <CustomInput value={label} styles={text} node={node} />
+        <svg
+          className="w-full h-full"
+          viewBox={`0 0 ${size?.width} ${size?.height}`}
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <defs>{defsContent}</defs>
+          <path
+            d={`
+              M ${Math.min(w*0.2,18)},${strokeWidth}
+              Q ${Math.min(w*0.1,9)},${strokeWidth} ${Math.min(w*0.1,9)},${Math.min(h*0.1,9)}
+              L ${Math.min(w*0.1,9)},${h*0.5-Math.min(h*0.1,9)}
+              Q ${Math.min(w*0.1,9)},${h/2} ${strokeWidth},${h/2}
+              Q ${Math.min(w*0.1,9)},${h/2} ${Math.min(w*0.1,9)},${h*0.5+Math.min(h*0.1,9)}
+              L ${Math.min(w*0.1,9)},${h-Math.min(h*0.1,9)}
+              Q ${Math.min(w*0.1,9)},${h} ${Math.min(w*0.2,18)},${h - strokeWidth}
+              M ${w-Math.min(w*0.2,18)},${strokeWidth}
+              Q ${w-Math.min(w*0.1,9)},${strokeWidth} ${w-Math.min(w*0.1,9)},${Math.min(h*0.1,9)}
+              L ${w-Math.min(w*0.1,9)},${h*0.5-Math.min(h*0.1,9)}
+              Q ${w-Math.min(w*0.1,9)},${h/2} ${w-strokeWidth},${h/2}
+              Q ${w-Math.min(w*0.1,9)},${h/2} ${w-Math.min(w*0.1,9)},${h*0.5+Math.min(h*0.1,9)}
+              L ${w-Math.min(w*0.1,9)},${h-Math.min(h*0.1,9)}
+              Q ${w-Math.min(w*0.1,9)},${h} ${w-Math.min(w*0.2,18)},${h - strokeWidth}
+            `}
+            fill={fillContent}
+            stroke={strokeColor}
+            strokeDasharray={strokeDasharray}
+            strokeWidth={strokeWidth}
+          />
+        </svg>
+      </div>
+    </>
+  );
+};
+
+register({
+  shape: "custom-react-braces",
+  width: 200,
+  height: 140,
+  effect: ["data"],
+  component: component,
+});
+
+const braces: CompoundedComponent = {
+  name: "大括号",
+  icon: require("./image/braces.png"),
+  node: {
+    shape: "custom-react-braces",
+    data: {
+      label: "",
+      ...defaultData,
+    },
+    ports,
+  },
+};
+
+export default braces;

+ 81 - 0
apps/designer/src/components/basic/doubleHorizontalArrow.tsx

@@ -0,0 +1,81 @@
+import { CompoundedComponent } from "@/types";
+import { register } from "@antv/x6-react-shape";
+import { Node } from "@antv/x6";
+import { ports, defaultData } from "../data";
+import CustomInput from "../CustomInput";
+import { useSizeHook, useShapeProps } from "@/hooks";
+const component = ({ node }: { node: Node }) => {
+  const { label, text, fill, stroke, opacity } = node.getData();
+  const { size, ref } = useSizeHook();
+  const {
+    fillContent,
+    defsContent,
+    strokeColor,
+    strokeWidth,
+    strokeDasharray,
+  } = useShapeProps(fill, size, stroke);
+
+  const { width: w, height: h } = size;
+
+  return (
+    <>
+      <div
+        className="relative text-0 w-full h-full"
+        ref={ref}
+        style={{ opacity: opacity / 100 }}
+      >
+        <CustomInput value={label} styles={text} node={node} />
+        <svg
+          className="w-full h-full"
+          viewBox={`0 0 ${size?.width} ${size?.height}`}
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <defs>{defsContent}</defs>
+          <path
+            d={`
+              M ${strokeWidth},${h/2}
+              L ${Math.min(0.5*h,0.45*w)},${strokeWidth}
+              L ${Math.min(0.5*h,0.45*w)},${h*0.33}
+              L ${w-Math.min(h*0.5,w*0.45)},${h*0.33}
+              L ${w-Math.min(h*0.5,w*0.45)},${strokeWidth}
+              L ${w-strokeWidth},${h/2}
+              L ${w-Math.min(h*0.5,w*0.45)},${h-strokeWidth}
+              L ${w-Math.min(h*0.5,w*0.45)},${h*0.67}
+              L ${Math.min(h*0.5,w*0.45)},${h*0.67}
+              L ${Math.min(h*0.5,w*0.45)},${h-strokeWidth}
+              L ${strokeWidth},${h/2}
+              Z
+            `}
+            fill={fillContent}
+            stroke={strokeColor}
+            strokeDasharray={strokeDasharray}
+            strokeWidth={strokeWidth}
+          />
+        </svg>
+      </div>
+    </>
+  );
+};
+
+register({
+  shape: "custom-react-doubleHorizontalArrow",
+  width: 90,
+  height: 60,
+  effect: ["data"],
+  component: component,
+});
+
+const doubleHorizontalArrow: CompoundedComponent = {
+  name: "左右箭头",
+  icon: require("./image/doubleHorizontalArrow.png"),
+  node: {
+    shape: "custom-react-doubleHorizontalArrow",
+    data: {
+      label: "",
+      ...defaultData,
+    },
+    ports,
+  },
+};
+
+export default doubleHorizontalArrow;

+ 80 - 0
apps/designer/src/components/basic/doubleVerticalArrow.tsx

@@ -0,0 +1,80 @@
+import { CompoundedComponent } from "@/types";
+import { register } from "@antv/x6-react-shape";
+import { Node } from "@antv/x6";
+import { ports, defaultData } from "../data";
+import CustomInput from "../CustomInput";
+import { useSizeHook, useShapeProps } from "@/hooks";
+const component = ({ node }: { node: Node }) => {
+  const { label, text, fill, stroke, opacity } = node.getData();
+  const { size, ref } = useSizeHook();
+  const {
+    fillContent,
+    defsContent,
+    strokeColor,
+    strokeWidth,
+    strokeDasharray,
+  } = useShapeProps(fill, size, stroke);
+
+  const { width: w, height: h } = size;
+
+  return (
+    <>
+      <div
+        className="relative text-0 w-full h-full"
+        ref={ref}
+        style={{ opacity: opacity / 100 }}
+      >
+        <CustomInput value={label} styles={text} node={node} />
+        <svg
+          className="w-full h-full"
+          viewBox={`0 0 ${size?.width} ${size?.height}`}
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <defs>{defsContent}</defs>
+          <path
+            d={`
+              M ${w/2},${strokeWidth}
+              L ${w-strokeWidth},${Math.min(w*0.5,h*0.45)}
+              L ${w*0.67},${Math.min(w*0.5,h*0.45)}
+              L ${w*0.67},${h-Math.min(w*0.5,h*0.45)}
+              L ${w-strokeWidth},${h-Math.min(w*0.5,h*0.45)}
+              L ${w/2},${h-strokeWidth}
+              L ${strokeWidth},${h-Math.min(w*0.5,h*0.45)}
+              L ${w*0.33},${h-Math.min(w*0.5,h*0.45)}
+              L ${w*0.33},${Math.min(w*0.5,h*0.45)}
+              L ${strokeWidth},${Math.min(w*0.5,h*0.45)}
+              Z
+            `}
+            fill={fillContent}
+            stroke={strokeColor}
+            strokeDasharray={strokeDasharray}
+            strokeWidth={strokeWidth}
+          />
+        </svg>
+      </div>
+    </>
+  );
+};
+
+register({
+  shape: "custom-react-doubleVerticalArrow",
+  width: 60,
+  height: 90,
+  effect: ["data"],
+  component: component,
+});
+
+const doubleVerticalArrow: CompoundedComponent = {
+  name: "上下箭头",
+  icon: require("./image/doubleVerticalArrow.png"),
+  node: {
+    shape: "custom-react-doubleVerticalArrow",
+    data: {
+      label: "",
+      ...defaultData,
+    },
+    ports,
+  },
+};
+
+export default doubleVerticalArrow;

+ 20 - 0
apps/designer/src/components/basic/index.ts

@@ -18,9 +18,20 @@ import Comment from "./comment";
 import Apqc from "./apqc";
 import Cross from "./cross";
 import Corner from "./corner";
+import CodeBlock from "./CodeBlock";
+import Node from "./note";
+import SingleLeftArrow from "./sigleLeftArrow";
+import SingleRightArrow from "./sigleRightArrow";
+import DoubleHorizontalArrow from "./doubleHorizontalArrow";
+import SingleUpArrow from "./sigleUpArrow";
+import SingleDownArrow from "./sigleDownArrow";
+import DoubleVerticalArrow from "./doubleVerticalArrow";
+import Parentheses from "./parentheses";
+import Braces from "./braces";
 
 export const basic = [
   Text,
+  Node,
   Circle,
   Start,
   Rectangle,
@@ -40,4 +51,13 @@ export const basic = [
   Apqc,
   Cross,
   Corner,
+  CodeBlock,
+  SingleLeftArrow,
+  SingleRightArrow,
+  DoubleHorizontalArrow,
+  SingleUpArrow,
+  SingleDownArrow,
+  DoubleVerticalArrow,
+  Parentheses,
+  Braces,
 ];

+ 96 - 0
apps/designer/src/components/basic/note.tsx

@@ -0,0 +1,96 @@
+import { CompoundedComponent } from "@/types";
+import { register } from "@antv/x6-react-shape";
+import { Node } from "@antv/x6";
+import { ports, defaultData } from "../data";
+import CustomInput from "../CustomInput";
+import { useSizeHook, useShapeProps } from "@/hooks";
+const component = ({ node }: { node: Node }) => {
+  const { label, text, fill, stroke, opacity } = node.getData();
+  const { size, ref } = useSizeHook();
+  const {
+    fillContent,
+    defsContent,
+    strokeColor,
+    strokeWidth,
+    strokeDasharray,
+  } = useShapeProps(fill, size, stroke);
+
+  const { width: w, height: h } = size;
+
+  return (
+    <>
+      <div
+        className="relative text-0 w-full h-full"
+        ref={ref}
+        style={{ opacity: opacity / 100 }}
+      >
+        <CustomInput value={label} styles={text} node={node} />
+        <svg
+          className="w-full h-full"
+          viewBox={`0 0 ${size?.width} ${size?.height}`}
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <defs>{defsContent}</defs>
+          <path
+            d={`
+              M ${strokeWidth},${strokeWidth}
+              L ${w-12},${strokeWidth}
+              L ${w-strokeWidth},${12}
+              L ${w-strokeWidth},${h-strokeWidth}
+              L ${strokeWidth},${h-strokeWidth}
+              L ${strokeWidth},${strokeWidth}
+              Z
+            `}
+            fill={fillContent}
+            stroke={strokeColor}
+            strokeDasharray={strokeDasharray}
+            strokeWidth={strokeWidth}
+          />
+          <path
+            d={`
+              M ${w-12},${strokeWidth}
+              L ${w-12},${12}
+              L ${w-strokeWidth},${12}
+              L ${w-12},${strokeWidth} Z
+            `}
+            fill='#e4d089'
+            stroke={strokeColor}
+            strokeDasharray={strokeDasharray}
+            strokeWidth={strokeWidth}
+          />
+        </svg>
+      </div>
+    </>
+  );
+};
+
+register({
+  shape: "custom-react-note",
+  width: 100,
+  height: 100,
+  effect: ["data"],
+  component: component,
+});
+
+const note: CompoundedComponent = {
+  name: "备注",
+  icon: require("./image/note.svg").default,
+  node: {
+    shape: "custom-react-note",
+    data: {
+      label: "",
+      ...defaultData,
+      fill: {
+        ...defaultData.fill,
+        color1: "#FFF7BC",
+      },
+      stroke: {
+        ...defaultData.stroke,
+        width: 0
+      }
+    },
+    ports,
+  },
+};
+
+export default note;

+ 77 - 0
apps/designer/src/components/basic/parentheses.tsx

@@ -0,0 +1,77 @@
+import { CompoundedComponent } from "@/types";
+import { register } from "@antv/x6-react-shape";
+import { Node } from "@antv/x6";
+import { ports, defaultData } from "../data";
+import CustomInput from "../CustomInput";
+import { useSizeHook, useShapeProps } from "@/hooks";
+const component = ({ node }: { node: Node }) => {
+  const { label, text, fill, stroke, opacity } = node.getData();
+  const { size, ref } = useSizeHook();
+  const {
+    fillContent,
+    defsContent,
+    strokeColor,
+    strokeWidth,
+    strokeDasharray,
+  } = useShapeProps(fill, size, stroke);
+
+  const { width: w, height: h } = size;
+
+  return (
+    <>
+      <div
+        className="relative text-0 w-full h-full"
+        ref={ref}
+        style={{ opacity: opacity / 100 }}
+      >
+        <CustomInput value={label} styles={text} node={node} />
+        <svg
+          className="w-full h-full"
+          viewBox={`0 0 ${size?.width} ${size?.height}`}
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <defs>{defsContent}</defs>
+          <path
+            d={`
+              M ${Math.min(w*0.1,18)},${strokeWidth}
+              L ${strokeWidth},${Math.min(h*0.1,15)}
+              L ${strokeWidth},${h-Math.min(h*0.1,15)}
+              L ${Math.min(w*0.1,18)},${h-strokeWidth}
+              M ${w-Math.min(w*0.1,18)},${strokeWidth}
+              L ${w-strokeWidth},${Math.min(h*0.1,15)}
+              L ${w-strokeWidth},${h-Math.min(h*0.1,15)}
+              L ${w-Math.min(w*0.1,18)},${h-strokeWidth}
+            `}
+            fill={fillContent}
+            stroke={strokeColor}
+            strokeDasharray={strokeDasharray}
+            strokeWidth={strokeWidth}
+          />
+        </svg>
+      </div>
+    </>
+  );
+};
+
+register({
+  shape: "custom-react-parentheses",
+  width: 200,
+  height: 140,
+  effect: ["data"],
+  component: component,
+});
+
+const parentheses: CompoundedComponent = {
+  name: "中括号",
+  icon: require("./image/parentheses.png"),
+  node: {
+    shape: "custom-react-parentheses",
+    data: {
+      label: "",
+      ...defaultData,
+    },
+    ports,
+  },
+};
+
+export default parentheses;

+ 77 - 0
apps/designer/src/components/basic/sigleDownArrow.tsx

@@ -0,0 +1,77 @@
+import { CompoundedComponent } from "@/types";
+import { register } from "@antv/x6-react-shape";
+import { Node } from "@antv/x6";
+import { ports, defaultData } from "../data";
+import CustomInput from "../CustomInput";
+import { useSizeHook, useShapeProps } from "@/hooks";
+const component = ({ node }: { node: Node }) => {
+  const { label, text, fill, stroke, opacity } = node.getData();
+  const { size, ref } = useSizeHook();
+  const {
+    fillContent,
+    defsContent,
+    strokeColor,
+    strokeWidth,
+    strokeDasharray,
+  } = useShapeProps(fill, size, stroke);
+
+  const { width: w, height: h } = size;
+
+  return (
+    <>
+      <div
+        className="relative text-0 w-full h-full"
+        ref={ref}
+        style={{ opacity: opacity / 100 }}
+      >
+        <CustomInput value={label} styles={text} node={node} />
+        <svg
+          className="w-full h-full"
+          viewBox={`0 0 ${size?.width} ${size?.height}`}
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <defs>{defsContent}</defs>
+          <path
+            d={`
+              M ${w*0.67},${strokeWidth}
+              L ${w*0.67},${h-Math.min(w*0.5,h*0.45)}
+              L ${w-strokeWidth},${h-Math.min(w*0.5,h*0.45)}
+              L ${w/2},${h-strokeWidth}
+              L ${strokeWidth},${h-Math.min(w*0.5,h*0.45)}
+              L ${w*0.33},${h-Math.min(w*0.5,h*0.45)}
+              L ${w*0.33},${strokeWidth}
+              Z
+            `}
+            fill={fillContent}
+            stroke={strokeColor}
+            strokeDasharray={strokeDasharray}
+            strokeWidth={strokeWidth}
+          />
+        </svg>
+      </div>
+    </>
+  );
+};
+
+register({
+  shape: "custom-react-singleDownArrow",
+  width: 60,
+  height: 90,
+  effect: ["data"],
+  component: component,
+});
+
+const singleDownArrow: CompoundedComponent = {
+  name: "下箭头",
+  icon: require("./image/singleDownArrow.png"),
+  node: {
+    shape: "custom-react-singleDownArrow",
+    data: {
+      label: "",
+      ...defaultData,
+    },
+    ports,
+  },
+};
+
+export default singleDownArrow;

+ 78 - 0
apps/designer/src/components/basic/sigleLeftArrow.tsx

@@ -0,0 +1,78 @@
+import { CompoundedComponent } from "@/types";
+import { register } from "@antv/x6-react-shape";
+import { Node } from "@antv/x6";
+import { ports, defaultData } from "../data";
+import CustomInput from "../CustomInput";
+import { useSizeHook, useShapeProps } from "@/hooks";
+const component = ({ node }: { node: Node }) => {
+  const { label, text, fill, stroke, opacity } = node.getData();
+  const { size, ref } = useSizeHook();
+  const {
+    fillContent,
+    defsContent,
+    strokeColor,
+    strokeWidth,
+    strokeDasharray,
+  } = useShapeProps(fill, size, stroke);
+
+  const { width: w, height: h } = size;
+
+  return (
+    <>
+      <div
+        className="relative text-0 w-full h-full"
+        ref={ref}
+        style={{ opacity: opacity / 100 }}
+      >
+        <CustomInput value={label} styles={text} node={node} />
+        <svg
+          className="w-full h-full"
+          viewBox={`0 0 ${size?.width} ${size?.height}`}
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <defs>{defsContent}</defs>
+          <path
+            d={`
+              M ${strokeWidth},${h/2}
+              L ${Math.min(0.5*h,0.45*w)},${strokeWidth}
+              L ${Math.min(0.5*h,0.45*w)},${h*0.33}
+              L ${w-strokeWidth},${h*0.33}
+              L ${w-strokeWidth},${h*0.67}
+              L ${Math.min(0.5*h,0.45*w)},${h*0.67}
+              L ${Math.min(0.5*h,0.45*w)},${h-strokeWidth}
+              L ${strokeWidth},${h/2}
+              Z
+            `}
+            fill={fillContent}
+            stroke={strokeColor}
+            strokeDasharray={strokeDasharray}
+            strokeWidth={strokeWidth}
+          />
+        </svg>
+      </div>
+    </>
+  );
+};
+
+register({
+  shape: "custom-react-singleLeftArrow",
+  width: 90,
+  height: 60,
+  effect: ["data"],
+  component: component,
+});
+
+const singleLeftArrow: CompoundedComponent = {
+  name: "左箭头",
+  icon: require("./image/singleLeftArrow.png"),
+  node: {
+    shape: "custom-react-singleLeftArrow",
+    data: {
+      label: "",
+      ...defaultData,
+    },
+    ports,
+  },
+};
+
+export default singleLeftArrow;

+ 78 - 0
apps/designer/src/components/basic/sigleRightArrow.tsx

@@ -0,0 +1,78 @@
+import { CompoundedComponent } from "@/types";
+import { register } from "@antv/x6-react-shape";
+import { Node } from "@antv/x6";
+import { ports, defaultData } from "../data";
+import CustomInput from "../CustomInput";
+import { useSizeHook, useShapeProps } from "@/hooks";
+const component = ({ node }: { node: Node }) => {
+  const { label, text, fill, stroke, opacity } = node.getData();
+  const { size, ref } = useSizeHook();
+  const {
+    fillContent,
+    defsContent,
+    strokeColor,
+    strokeWidth,
+    strokeDasharray,
+  } = useShapeProps(fill, size, stroke);
+
+  const { width: w, height: h } = size;
+
+  return (
+    <>
+      <div
+        className="relative text-0 w-full h-full"
+        ref={ref}
+        style={{ opacity: opacity / 100 }}
+      >
+        <CustomInput value={label} styles={text} node={node} />
+        <svg
+          className="w-full h-full"
+          viewBox={`0 0 ${size?.width} ${size?.height}`}
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <defs>{defsContent}</defs>
+          <path
+            d={`
+              M ${strokeWidth},${h*0.33}
+              L ${w-Math.min(h*0.5,w*0.45)},${h*0.33}
+              L ${w-Math.min(h*0.5,w*0.45)},${strokeWidth}
+              L ${w-strokeWidth},${h/2}
+              L ${w-Math.min(h*0.5,w*0.45)},${h-strokeWidth}
+              L ${w-Math.min(h*0.5,w*0.45)},${h*0.67}
+              L ${strokeWidth},${h*0.67}
+              L ${strokeWidth},${h*0.33}
+              Z
+            `}
+            fill={fillContent}
+            stroke={strokeColor}
+            strokeDasharray={strokeDasharray}
+            strokeWidth={strokeWidth}
+          />
+        </svg>
+      </div>
+    </>
+  );
+};
+
+register({
+  shape: "custom-react-singleRightArrow",
+  width: 90,
+  height: 60,
+  effect: ["data"],
+  component: component,
+});
+
+const singleRightArrow: CompoundedComponent = {
+  name: "右箭头",
+  icon: require("./image/singleRightArrow.png"),
+  node: {
+    shape: "custom-react-singleRightArrow",
+    data: {
+      label: "",
+      ...defaultData,
+    },
+    ports,
+  },
+};
+
+export default singleRightArrow;

+ 78 - 0
apps/designer/src/components/basic/sigleUpArrow.tsx

@@ -0,0 +1,78 @@
+import { CompoundedComponent } from "@/types";
+import { register } from "@antv/x6-react-shape";
+import { Node } from "@antv/x6";
+import { ports, defaultData } from "../data";
+import CustomInput from "../CustomInput";
+import { useSizeHook, useShapeProps } from "@/hooks";
+const component = ({ node }: { node: Node }) => {
+  const { label, text, fill, stroke, opacity } = node.getData();
+  const { size, ref } = useSizeHook();
+  const {
+    fillContent,
+    defsContent,
+    strokeColor,
+    strokeWidth,
+    strokeDasharray,
+  } = useShapeProps(fill, size, stroke);
+
+  const { width: w, height: h } = size;
+
+  return (
+    <>
+      <div
+        className="relative text-0 w-full h-full"
+        ref={ref}
+        style={{ opacity: opacity / 100 }}
+      >
+        <CustomInput value={label} styles={text} node={node} />
+        <svg
+          className="w-full h-full"
+          viewBox={`0 0 ${size?.width} ${size?.height}`}
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <defs>{defsContent}</defs>
+          <path
+            d={`
+              M ${w/2},${strokeWidth}
+              L ${w-strokeWidth},${Math.min(w*0.5,h*0.45)}
+              L ${w*0.67},${Math.min(w*0.5,h*0.45)}
+              L ${w*0.67},${h-strokeWidth}
+              L ${w*0.33},${h-strokeWidth}
+              L ${w*0.33},${Math.min(w*0.5,h*0.45)}
+              L ${strokeWidth},${Math.min(w*0.5,h*0.45)}
+              L ${w/2},${strokeWidth}
+              Z
+            `}
+            fill={fillContent}
+            stroke={strokeColor}
+            strokeDasharray={strokeDasharray}
+            strokeWidth={strokeWidth}
+          />
+        </svg>
+      </div>
+    </>
+  );
+};
+
+register({
+  shape: "custom-react-singleUpArrow",
+  width: 60,
+  height: 90,
+  effect: ["data"],
+  component: component,
+});
+
+const singleUpArrow: CompoundedComponent = {
+  name: "上箭头",
+  icon: require("./image/singleUpArrow.png"),
+  node: {
+    shape: "custom-react-singleUpArrow",
+    data: {
+      label: "",
+      ...defaultData,
+    },
+    ports,
+  },
+};
+
+export default singleUpArrow;

+ 16 - 1
package.json

@@ -30,14 +30,29 @@
     "@antv/x6-plugin-snapline": "^2.1.7",
     "@antv/x6-plugin-transform": "^2.1.8",
     "@antv/x6-react-shape": "^2.2.3",
+    "@codemirror/lang-angular": "^0.1.3",
+    "@codemirror/lang-css": "^6.3.0",
+    "@codemirror/lang-go": "^6.0.1",
+    "@codemirror/lang-html": "^6.4.9",
+    "@codemirror/lang-java": "^6.0.1",
+    "@codemirror/lang-javascript": "^6.2.2",
+    "@codemirror/lang-json": "^6.0.1",
+    "@codemirror/lang-php": "^6.0.1",
+    "@codemirror/lang-python": "^6.1.6",
+    "@codemirror/lang-rust": "^6.0.1",
+    "@codemirror/lang-sql": "^6.7.1",
+    "@codemirror/lang-vue": "^0.1.3",
+    "@codemirror/lang-xml": "^6.1.0",
+    "@codemirror/lang-yaml": "^6.1.1",
     "@emotion/css": "^11.13.0",
+    "@uiw/react-codemirror": "^4.23.3",
     "@unocss/cli": "^0.62.3",
     "ahooks": "^3.8.1",
     "antd": "^5.20.5",
     "axios": "^1.7.7",
-    "codemirror": "^6.0.1",
     "insert-css": "^2.0.0",
     "lodash-es": "^4.17.21",
+    "thememirror": "^2.0.1",
     "umi": "^4.3.18",
     "unocss": "^0.62.3"
   }

+ 522 - 4
pnpm-lock.yaml

@@ -44,9 +44,54 @@ importers:
       '@antv/x6-react-shape':
         specifier: ^2.2.3
         version: 2.2.3(@antv/x6@2.18.1)(react-dom@18.3.1)(react@18.3.1)
+      '@codemirror/lang-angular':
+        specifier: ^0.1.3
+        version: 0.1.3
+      '@codemirror/lang-css':
+        specifier: ^6.3.0
+        version: 6.3.0(@codemirror/view@6.34.1)
+      '@codemirror/lang-go':
+        specifier: ^6.0.1
+        version: 6.0.1(@codemirror/view@6.34.1)
+      '@codemirror/lang-html':
+        specifier: ^6.4.9
+        version: 6.4.9
+      '@codemirror/lang-java':
+        specifier: ^6.0.1
+        version: 6.0.1
+      '@codemirror/lang-javascript':
+        specifier: ^6.2.2
+        version: 6.2.2
+      '@codemirror/lang-json':
+        specifier: ^6.0.1
+        version: 6.0.1
+      '@codemirror/lang-php':
+        specifier: ^6.0.1
+        version: 6.0.1
+      '@codemirror/lang-python':
+        specifier: ^6.1.6
+        version: 6.1.6(@codemirror/view@6.34.1)
+      '@codemirror/lang-rust':
+        specifier: ^6.0.1
+        version: 6.0.1
+      '@codemirror/lang-sql':
+        specifier: ^6.7.1
+        version: 6.7.1(@codemirror/view@6.34.1)
+      '@codemirror/lang-vue':
+        specifier: ^0.1.3
+        version: 0.1.3
+      '@codemirror/lang-xml':
+        specifier: ^6.1.0
+        version: 6.1.0
+      '@codemirror/lang-yaml':
+        specifier: ^6.1.1
+        version: 6.1.1(@codemirror/view@6.34.1)
       '@emotion/css':
         specifier: ^11.13.0
         version: 11.13.0
+      '@uiw/react-codemirror':
+        specifier: ^4.23.3
+        version: 4.23.3(@babel/runtime@7.25.6)(@codemirror/autocomplete@6.18.1)(@codemirror/language@6.10.3)(@codemirror/lint@6.8.2)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.34.1)(codemirror@6.0.1)(react-dom@18.3.1)(react@18.3.1)
       '@unocss/cli':
         specifier: ^0.62.3
         version: 0.62.3
@@ -59,18 +104,18 @@ importers:
       axios:
         specifier: ^1.7.7
         version: 1.7.7
-      codemirror:
-        specifier: ^6.0.1
-        version: 6.0.1(@lezer/common@1.2.1)
       insert-css:
         specifier: ^2.0.0
         version: 2.0.0
       lodash-es:
         specifier: ^4.17.21
         version: 4.17.21
+      thememirror:
+        specifier: ^2.0.1
+        version: 2.0.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)
       umi:
         specifier: ^4.3.18
-        version: 4.3.19(@babel/core@7.25.2)(@types/react@18.3.5)(eslint@8.57.0)(prettier@3.3.3)(react-dom@18.3.1)(react@18.3.1)(stylelint@14.16.1)(typescript@5.5.4)(webpack@5.94.0)
+        version: 4.3.19(@babel/core@7.25.2)(eslint@8.57.0)(prettier@3.3.3)(react-dom@18.3.1)(react@18.3.1)(stylelint@14.16.1)(typescript@5.5.4)(webpack@5.94.0)
       unocss:
         specifier: ^0.62.3
         version: 0.62.3(postcss@8.4.45)(vite@5.4.3)
@@ -1306,6 +1351,158 @@ packages:
       '@lezer/common': 1.2.1
     dev: false
 
+  /@codemirror/lang-angular@0.1.3:
+    resolution: {integrity: sha512-xgeWGJQQl1LyStvndWtruUvb4SnBZDAu/gvFH/ZU+c0W25tQR8e5hq7WTwiIY2dNxnf+49mRiGI/9yxIwB6f5w==}
+    dependencies:
+      '@codemirror/lang-html': 6.4.9
+      '@codemirror/lang-javascript': 6.2.2
+      '@codemirror/language': 6.10.3
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
+  /@codemirror/lang-css@6.3.0(@codemirror/view@6.34.1):
+    resolution: {integrity: sha512-CyR4rUNG9OYcXDZwMPvJdtb6PHbBDKUc/6Na2BIwZ6dKab1JQqKa4di+RNRY9Myn7JB81vayKwJeQ7jEdmNVDA==}
+    dependencies:
+      '@codemirror/autocomplete': 6.18.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)(@lezer/common@1.2.1)
+      '@codemirror/language': 6.10.3
+      '@codemirror/state': 6.4.1
+      '@lezer/common': 1.2.1
+      '@lezer/css': 1.1.9
+    transitivePeerDependencies:
+      - '@codemirror/view'
+    dev: false
+
+  /@codemirror/lang-go@6.0.1(@codemirror/view@6.34.1):
+    resolution: {integrity: sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==}
+    dependencies:
+      '@codemirror/autocomplete': 6.18.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)(@lezer/common@1.2.1)
+      '@codemirror/language': 6.10.3
+      '@codemirror/state': 6.4.1
+      '@lezer/common': 1.2.1
+      '@lezer/go': 1.0.0
+    transitivePeerDependencies:
+      - '@codemirror/view'
+    dev: false
+
+  /@codemirror/lang-html@6.4.9:
+    resolution: {integrity: sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==}
+    dependencies:
+      '@codemirror/autocomplete': 6.18.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)(@lezer/common@1.2.1)
+      '@codemirror/lang-css': 6.3.0(@codemirror/view@6.34.1)
+      '@codemirror/lang-javascript': 6.2.2
+      '@codemirror/language': 6.10.3
+      '@codemirror/state': 6.4.1
+      '@codemirror/view': 6.34.1
+      '@lezer/common': 1.2.1
+      '@lezer/css': 1.1.9
+      '@lezer/html': 1.3.10
+    dev: false
+
+  /@codemirror/lang-java@6.0.1:
+    resolution: {integrity: sha512-OOnmhH67h97jHzCuFaIEspbmsT98fNdhVhmA3zCxW0cn7l8rChDhZtwiwJ/JOKXgfm4J+ELxQihxaI7bj7mJRg==}
+    dependencies:
+      '@codemirror/language': 6.10.3
+      '@lezer/java': 1.1.2
+    dev: false
+
+  /@codemirror/lang-javascript@6.2.2:
+    resolution: {integrity: sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==}
+    dependencies:
+      '@codemirror/autocomplete': 6.18.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)(@lezer/common@1.2.1)
+      '@codemirror/language': 6.10.3
+      '@codemirror/lint': 6.8.2
+      '@codemirror/state': 6.4.1
+      '@codemirror/view': 6.34.1
+      '@lezer/common': 1.2.1
+      '@lezer/javascript': 1.4.18
+    dev: false
+
+  /@codemirror/lang-json@6.0.1:
+    resolution: {integrity: sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==}
+    dependencies:
+      '@codemirror/language': 6.10.3
+      '@lezer/json': 1.0.2
+    dev: false
+
+  /@codemirror/lang-php@6.0.1:
+    resolution: {integrity: sha512-ublojMdw/PNWa7qdN5TMsjmqkNuTBD3k6ndZ4Z0S25SBAiweFGyY68AS3xNcIOlb6DDFDvKlinLQ40vSLqf8xA==}
+    dependencies:
+      '@codemirror/lang-html': 6.4.9
+      '@codemirror/language': 6.10.3
+      '@codemirror/state': 6.4.1
+      '@lezer/common': 1.2.1
+      '@lezer/php': 1.0.2
+    dev: false
+
+  /@codemirror/lang-python@6.1.6(@codemirror/view@6.34.1):
+    resolution: {integrity: sha512-ai+01WfZhWqM92UqjnvorkxosZ2aq2u28kHvr+N3gu012XqY2CThD67JPMHnGceRfXPDBmn1HnyqowdpF57bNg==}
+    dependencies:
+      '@codemirror/autocomplete': 6.18.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)(@lezer/common@1.2.1)
+      '@codemirror/language': 6.10.3
+      '@codemirror/state': 6.4.1
+      '@lezer/common': 1.2.1
+      '@lezer/python': 1.1.14
+    transitivePeerDependencies:
+      - '@codemirror/view'
+    dev: false
+
+  /@codemirror/lang-rust@6.0.1:
+    resolution: {integrity: sha512-344EMWFBzWArHWdZn/NcgkwMvZIWUR1GEBdwG8FEp++6o6vT6KL9V7vGs2ONsKxxFUPXKI0SPcWhyYyl2zPYxQ==}
+    dependencies:
+      '@codemirror/language': 6.10.3
+      '@lezer/rust': 1.0.2
+    dev: false
+
+  /@codemirror/lang-sql@6.7.1(@codemirror/view@6.34.1):
+    resolution: {integrity: sha512-flQa7zemrLKk0TIrOJnpeyH/b29BcVybtsTeZMgAo40O6kGbrnUSCgwI3TF5iJY3O9VXJKKCA+i0CBVvDfr88w==}
+    dependencies:
+      '@codemirror/autocomplete': 6.18.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)(@lezer/common@1.2.1)
+      '@codemirror/language': 6.10.3
+      '@codemirror/state': 6.4.1
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    transitivePeerDependencies:
+      - '@codemirror/view'
+    dev: false
+
+  /@codemirror/lang-vue@0.1.3:
+    resolution: {integrity: sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==}
+    dependencies:
+      '@codemirror/lang-html': 6.4.9
+      '@codemirror/lang-javascript': 6.2.2
+      '@codemirror/language': 6.10.3
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
+  /@codemirror/lang-xml@6.1.0:
+    resolution: {integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==}
+    dependencies:
+      '@codemirror/autocomplete': 6.18.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)(@lezer/common@1.2.1)
+      '@codemirror/language': 6.10.3
+      '@codemirror/state': 6.4.1
+      '@codemirror/view': 6.34.1
+      '@lezer/common': 1.2.1
+      '@lezer/xml': 1.0.5
+    dev: false
+
+  /@codemirror/lang-yaml@6.1.1(@codemirror/view@6.34.1):
+    resolution: {integrity: sha512-HV2NzbK9bbVnjWxwObuZh5FuPCowx51mEfoFT9y3y+M37fA3+pbxx4I7uePuygFzDsAmCTwQSc/kXh/flab4uw==}
+    dependencies:
+      '@codemirror/autocomplete': 6.18.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)(@lezer/common@1.2.1)
+      '@codemirror/language': 6.10.3
+      '@codemirror/state': 6.4.1
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/yaml': 1.0.3
+    transitivePeerDependencies:
+      - '@codemirror/view'
+    dev: false
+
   /@codemirror/language@6.10.3:
     resolution: {integrity: sha512-kDqEU5sCP55Oabl6E7m5N+vZRoc0iWqgDVhEKifcHzPzjqCegcO4amfrYVL9PmPZpl4G0yjkpTpUO/Ui8CzO8A==}
     dependencies:
@@ -1337,6 +1534,15 @@ packages:
     resolution: {integrity: sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==}
     dev: false
 
+  /@codemirror/theme-one-dark@6.1.2:
+    resolution: {integrity: sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==}
+    dependencies:
+      '@codemirror/language': 6.10.3
+      '@codemirror/state': 6.4.1
+      '@codemirror/view': 6.34.1
+      '@lezer/highlight': 1.2.1
+    dev: false
+
   /@codemirror/view@6.34.1:
     resolution: {integrity: sha512-t1zK/l9UiRqwUNPm+pdIT0qzJlzuVckbTEMVNFhfWkGiBQClstzg+78vedCvLSX0xJEZ6lwZbPpnljL7L6iwMQ==}
     dependencies:
@@ -2490,6 +2696,20 @@ packages:
       - react-dom
     dev: false
 
+  /@floating-ui/react-dom-interactions@0.3.1(react-dom@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-tP2KEh7EHJr5hokSBHcPGojb+AorDNUf0NYfZGg/M+FsMvCOOsSEeEF0O1NDfETIzDnpbHnCs0DuvCFhSMSStg==}
+    deprecated: Package renamed to @floating-ui/react
+    dependencies:
+      '@floating-ui/react-dom': 0.6.3(react-dom@18.3.1)(react@18.3.1)
+      aria-hidden: 1.2.4
+      point-in-polygon: 1.1.0
+      use-isomorphic-layout-effect: 1.1.2(react@18.3.1)
+    transitivePeerDependencies:
+      - '@types/react'
+      - react
+      - react-dom
+    dev: false
+
   /@floating-ui/react-dom@0.6.3(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-hC+pS5D6AgS2wWjbmSQ6UR6Kpy+drvWGJIri6e1EDGADTPsCaa4KzCgmCczHrQeInx9tqs81EyDmbKJYY2swKg==}
     peerDependencies:
@@ -2504,6 +2724,20 @@ packages:
       - '@types/react'
     dev: false
 
+  /@floating-ui/react-dom@0.6.3(react-dom@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-hC+pS5D6AgS2wWjbmSQ6UR6Kpy+drvWGJIri6e1EDGADTPsCaa4KzCgmCczHrQeInx9tqs81EyDmbKJYY2swKg==}
+    peerDependencies:
+      react: '>=16.8.0'
+      react-dom: '>=16.8.0'
+    dependencies:
+      '@floating-ui/dom': 0.4.5
+      react: 18.3.1
+      react-dom: 18.3.1(react@18.3.1)
+      use-isomorphic-layout-effect: 1.1.2(react@18.3.1)
+    transitivePeerDependencies:
+      - '@types/react'
+    dev: false
+
   /@formatjs/intl-displaynames@1.2.10:
     resolution: {integrity: sha512-GROA2RP6+7Ouu0WnHFF78O5XIU7pBfI19WM1qm93l6MFWibUk67nCfVCK3VAYJkLy8L8ZxjkYT11VIAfvSz8wg==}
     dependencies:
@@ -2721,18 +2955,106 @@ packages:
     resolution: {integrity: sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==}
     dev: false
 
+  /@lezer/css@1.1.9:
+    resolution: {integrity: sha512-TYwgljcDv+YrV0MZFFvYFQHCfGgbPMR6nuqLabBdmZoFH3EP1gvw8t0vae326Ne3PszQkbXfVBjCnf3ZVCr0bA==}
+    dependencies:
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
+  /@lezer/go@1.0.0:
+    resolution: {integrity: sha512-co9JfT3QqX1YkrMmourYw2Z8meGC50Ko4d54QEcQbEYpvdUvN4yb0NBZdn/9ertgvjsySxHsKzH3lbm3vqJ4Jw==}
+    dependencies:
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
   /@lezer/highlight@1.2.1:
     resolution: {integrity: sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==}
     dependencies:
       '@lezer/common': 1.2.1
     dev: false
 
+  /@lezer/html@1.3.10:
+    resolution: {integrity: sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==}
+    dependencies:
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
+  /@lezer/java@1.1.2:
+    resolution: {integrity: sha512-3j8X70JvYf0BZt8iSRLXLkt0Ry1hVUgH6wT32yBxH/Xi55nW2VMhc1Az4SKwu4YGSmxCm1fsqDDcHTuFjC8pmg==}
+    dependencies:
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
+  /@lezer/javascript@1.4.18:
+    resolution: {integrity: sha512-Y8BeHOt4LtcxJgXwadtfSeWPrh0XzklcCHnCVT+vOsxqH4gWmunP2ykX+VVOlM/dusyVyiNfG3lv0f10UK+mgA==}
+    dependencies:
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
+  /@lezer/json@1.0.2:
+    resolution: {integrity: sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==}
+    dependencies:
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
   /@lezer/lr@1.4.2:
     resolution: {integrity: sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==}
     dependencies:
       '@lezer/common': 1.2.1
     dev: false
 
+  /@lezer/php@1.0.2:
+    resolution: {integrity: sha512-GN7BnqtGRpFyeoKSEqxvGvhJQiI4zkgmYnDk/JIyc7H7Ifc1tkPnUn/R2R8meH3h/aBf5rzjvU8ZQoyiNDtDrA==}
+    dependencies:
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
+  /@lezer/python@1.1.14:
+    resolution: {integrity: sha512-ykDOb2Ti24n76PJsSa4ZoDF0zH12BSw1LGfQXCYJhJyOGiFTfGaX0Du66Ze72R+u/P35U+O6I9m8TFXov1JzsA==}
+    dependencies:
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
+  /@lezer/rust@1.0.2:
+    resolution: {integrity: sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==}
+    dependencies:
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
+  /@lezer/xml@1.0.5:
+    resolution: {integrity: sha512-VFouqOzmUWfIg+tfmpcdV33ewtK+NSwd4ngSe1aG7HFb4BN0ExyY1b8msp+ndFrnlG4V4iC8yXacjFtrwERnaw==}
+    dependencies:
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
+  /@lezer/yaml@1.0.3:
+    resolution: {integrity: sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==}
+    dependencies:
+      '@lezer/common': 1.2.1
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+    dev: false
+
   /@loadable/component@5.15.2(react@18.3.1):
     resolution: {integrity: sha512-ryFAZOX5P2vFkUdzaAtTG88IGnr9qxSdvLRvJySXcUA4B4xVWurUNADu3AnKPksxOZajljqTrDEDcYjeL4lvLw==}
     engines: {node: '>=8'}
@@ -4132,6 +4454,53 @@ packages:
       eslint-visitor-keys: 3.4.3
     dev: true
 
+  /@uiw/codemirror-extensions-basic-setup@4.23.3(@codemirror/autocomplete@6.18.1)(@codemirror/commands@6.6.2)(@codemirror/language@6.10.3)(@codemirror/lint@6.8.2)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1):
+    resolution: {integrity: sha512-nEMjgbCyeLx+UQgOGAAoUWYFE34z5TlyaKNszuig/BddYFDb0WKcgmC37bDFxR2dZssf3K/lwGWLpXnGKXePbA==}
+    peerDependencies:
+      '@codemirror/autocomplete': '>=6.0.0'
+      '@codemirror/commands': '>=6.0.0'
+      '@codemirror/language': '>=6.0.0'
+      '@codemirror/lint': '>=6.0.0'
+      '@codemirror/search': '>=6.0.0'
+      '@codemirror/state': '>=6.0.0'
+      '@codemirror/view': '>=6.0.0'
+    dependencies:
+      '@codemirror/autocomplete': 6.18.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)(@lezer/common@1.2.1)
+      '@codemirror/commands': 6.6.2
+      '@codemirror/language': 6.10.3
+      '@codemirror/lint': 6.8.2
+      '@codemirror/search': 6.5.6
+      '@codemirror/state': 6.4.1
+      '@codemirror/view': 6.34.1
+    dev: false
+
+  /@uiw/react-codemirror@4.23.3(@babel/runtime@7.25.6)(@codemirror/autocomplete@6.18.1)(@codemirror/language@6.10.3)(@codemirror/lint@6.8.2)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.34.1)(codemirror@6.0.1)(react-dom@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-TBBLUbeqXmfQSfO+f3rPNOAb+QXbSm7KPB64FHQWLGg2WJNbpOhjLOWMyL+C4ZP3aSCNc2Y5aftEK1vp3wCKTA==}
+    peerDependencies:
+      '@babel/runtime': '>=7.11.0'
+      '@codemirror/state': '>=6.0.0'
+      '@codemirror/theme-one-dark': '>=6.0.0'
+      '@codemirror/view': '>=6.0.0'
+      codemirror: '>=6.0.0'
+      react: '>=16.8.0'
+      react-dom: '>=16.8.0'
+    dependencies:
+      '@babel/runtime': 7.25.6
+      '@codemirror/commands': 6.6.2
+      '@codemirror/state': 6.4.1
+      '@codemirror/theme-one-dark': 6.1.2
+      '@codemirror/view': 6.34.1
+      '@uiw/codemirror-extensions-basic-setup': 4.23.3(@codemirror/autocomplete@6.18.1)(@codemirror/commands@6.6.2)(@codemirror/language@6.10.3)(@codemirror/lint@6.8.2)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)
+      codemirror: 6.0.1(@lezer/common@1.2.1)
+      react: 18.3.1
+      react-dom: 18.3.1(react@18.3.1)
+    transitivePeerDependencies:
+      - '@codemirror/autocomplete'
+      - '@codemirror/language'
+      - '@codemirror/lint'
+      - '@codemirror/search'
+    dev: false
+
   /@umijs/ast@4.3.19:
     resolution: {integrity: sha512-R/h/H5NR7FXm3qguB7dV4i182OtkZ4dDYj2s+LHSRQ9O9OaxGoPssoTh3fxqi+/NRBG4JzNk7gY8/Hbv0AumSQ==}
     dependencies:
@@ -4610,6 +4979,66 @@ packages:
       - webpack-plugin-serve
     dev: false
 
+  /@umijs/preset-umi@4.3.19(typescript@5.5.4)(webpack@5.94.0):
+    resolution: {integrity: sha512-un/1R06c92nv9uuTRRChDOu3wjFwUU4YhTvXnlvzzj5BmqLaUF/miHapvTn0CTviDVl0UTEL/wEZ8bmDnqTj1Q==}
+    dependencies:
+      '@iconify/utils': 2.1.1
+      '@svgr/core': 6.5.1
+      '@umijs/ast': 4.3.19
+      '@umijs/babel-preset-umi': 4.3.19
+      '@umijs/bundler-esbuild': 4.3.19
+      '@umijs/bundler-mako': 0.8.8
+      '@umijs/bundler-utils': 4.3.19
+      '@umijs/bundler-vite': 4.3.19(postcss@8.4.45)
+      '@umijs/bundler-webpack': 4.3.19(typescript@5.5.4)(webpack@5.94.0)
+      '@umijs/core': 4.3.19
+      '@umijs/did-you-know': 1.0.3
+      '@umijs/es-module-parser': 0.0.7
+      '@umijs/history': 5.3.1
+      '@umijs/mfsu': 4.3.19
+      '@umijs/plugin-run': 4.3.19
+      '@umijs/renderer-react': 4.3.19(react-dom@18.3.1)(react@18.3.1)
+      '@umijs/server': 4.3.19
+      '@umijs/ui': 3.0.1
+      '@umijs/utils': 4.3.19
+      '@umijs/zod2ts': 4.3.19
+      babel-plugin-dynamic-import-node: 2.3.3
+      babel-plugin-react-compiler: 0.0.0-experimental-c23de8d-20240515
+      click-to-react-component: 1.1.0(react-dom@18.3.1)(react@18.3.1)
+      core-js: 3.34.0
+      current-script-polyfill: 1.0.0
+      enhanced-resolve: 5.9.3
+      fast-glob: 3.2.12
+      html-webpack-plugin: 5.5.0(webpack@5.94.0)
+      less-plugin-resolve: 1.0.2
+      path-to-regexp: 1.7.0
+      postcss: 8.4.45
+      postcss-prefix-selector: 1.16.0(postcss@8.4.45)
+      react: 18.3.1
+      react-dom: 18.3.1(react@18.3.1)
+      react-router: 6.3.0(react@18.3.1)
+      react-router-dom: 6.3.0(react-dom@18.3.1)(react@18.3.1)
+      regenerator-runtime: 0.13.11
+    transitivePeerDependencies:
+      - '@types/node'
+      - '@types/react'
+      - '@types/webpack'
+      - lightningcss
+      - rollup
+      - sass
+      - sockjs-client
+      - stylus
+      - sugarss
+      - supports-color
+      - terser
+      - type-fest
+      - typescript
+      - webpack
+      - webpack-dev-server
+      - webpack-hot-middleware
+      - webpack-plugin-serve
+    dev: false
+
   /@umijs/react-refresh-webpack-plugin@0.5.11(react-refresh@0.14.0)(webpack@5.94.0):
     resolution: {integrity: sha512-RtFvB+/GmjRhpHcqNgnw8iWZpTlxOnmNxi8eDcecxMmxmSgeDj25LV0jr4Q6rOhv3GTIfVGBhkwz+khGT5tfmg==}
     engines: {node: '>= 10.13'}
@@ -6145,6 +6574,20 @@ packages:
       - react-dom
     dev: false
 
+  /click-to-react-component@1.1.0(react-dom@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-/DjZemufS1BkxyRgZL3r7HXVVOFRWVQi5Xd4EBnjxZMwrHEh0OlUVA2N9CjXkZ0x8zMf8dL1cKnnx+xUWUg4VA==}
+    peerDependencies:
+      react: '>=16.8.0'
+    dependencies:
+      '@floating-ui/react-dom-interactions': 0.3.1(react-dom@18.3.1)(react@18.3.1)
+      htm: 3.1.1
+      react: 18.3.1
+      react-merge-refs: 1.1.0
+    transitivePeerDependencies:
+      - '@types/react'
+      - react-dom
+    dev: false
+
   /client-only@0.0.1:
     resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
 
@@ -13468,6 +13911,18 @@ packages:
   /text-table@0.2.0:
     resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
 
+  /thememirror@2.0.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1):
+    resolution: {integrity: sha512-d5i6FVvWWPkwrm4cHLI3t9AT1OrkAt7Ig8dtdYSofgF7C/eiyNuq6zQzSTusWTde3jpW9WLvA9J/fzNKMUsd0w==}
+    peerDependencies:
+      '@codemirror/language': ^6.0.0
+      '@codemirror/state': ^6.0.0
+      '@codemirror/view': ^6.0.0
+    dependencies:
+      '@codemirror/language': 6.10.3
+      '@codemirror/state': 6.4.1
+      '@codemirror/view': 6.34.1
+    dev: false
+
   /thread-stream@0.15.2:
     resolution: {integrity: sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==}
     dependencies:
@@ -13876,6 +14331,57 @@ packages:
       - webpack-plugin-serve
     dev: false
 
+  /umi@4.3.19(@babel/core@7.25.2)(eslint@8.57.0)(prettier@3.3.3)(react-dom@18.3.1)(react@18.3.1)(stylelint@14.16.1)(typescript@5.5.4)(webpack@5.94.0):
+    resolution: {integrity: sha512-RXIn3+NokatSuqB7jw1XXk0kQlKz8tRcIuv0gQ0CKAc/ltyseMnePEg7DgBFazvBS7s23oVIP8e4oTHHiLO+KA==}
+    engines: {node: '>=14'}
+    hasBin: true
+    dependencies:
+      '@babel/runtime': 7.23.6
+      '@umijs/bundler-utils': 4.3.19
+      '@umijs/bundler-webpack': 4.3.19(typescript@5.5.4)(webpack@5.94.0)
+      '@umijs/core': 4.3.19
+      '@umijs/lint': 4.3.19(eslint@8.57.0)(stylelint@14.16.1)(typescript@5.5.4)
+      '@umijs/preset-umi': 4.3.19(typescript@5.5.4)(webpack@5.94.0)
+      '@umijs/renderer-react': 4.3.19(react-dom@18.3.1)(react@18.3.1)
+      '@umijs/server': 4.3.19
+      '@umijs/test': 4.3.19(@babel/core@7.25.2)
+      '@umijs/utils': 4.3.19
+      prettier-plugin-organize-imports: 3.2.4(prettier@3.3.3)(typescript@5.5.4)
+      prettier-plugin-packagejson: 2.4.3(prettier@3.3.3)
+    transitivePeerDependencies:
+      - '@babel/core'
+      - '@types/node'
+      - '@types/react'
+      - '@types/webpack'
+      - '@volar/vue-language-plugin-pug'
+      - '@volar/vue-typescript'
+      - eslint
+      - jest
+      - lightningcss
+      - postcss-html
+      - postcss-jsx
+      - postcss-less
+      - postcss-markdown
+      - postcss-scss
+      - prettier
+      - react
+      - react-dom
+      - rollup
+      - sass
+      - sockjs-client
+      - stylelint
+      - stylus
+      - sugarss
+      - supports-color
+      - terser
+      - type-fest
+      - typescript
+      - webpack
+      - webpack-dev-server
+      - webpack-hot-middleware
+      - webpack-plugin-serve
+    dev: false
+
   /unbox-primitive@1.0.2:
     resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
     dependencies:
@@ -14014,6 +14520,18 @@ packages:
       react: 18.3.1
     dev: false
 
+  /use-isomorphic-layout-effect@1.1.2(react@18.3.1):
+    resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+    dependencies:
+      react: 18.3.1
+    dev: false
+
   /use-sync-external-store@1.2.0(react@18.3.1):
     resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
     peerDependencies: