{
  "$schema": "https://ai.syncfusion.com/schema/registry-item.json",
  "name": "diagram-mind-map",
  "framework": "vue",
  "type": "registry:component",
  "component": "Diagram",
  "variant": "mind-map",
  "dependencies": [
    "@syncfusion/ej2-data",
    "@syncfusion/ej2-vue-diagrams"
  ],
  "description": "Mind-map diagram with custom user handles to add, branch, and delete nodes.",
  "meta": {
    "essentialStudioRelease": "2026 Volume 2 (v34.1.29)",
    "license": "commercial-or-community",
    "licenseNote": "The Syncfusion package is licensed. The composition in this file is source you own and edit. See https://ai.syncfusion.com/licensing.md",
    "requiresLicenseKey": true,
    "requiresServerEndpoint": false,
    "platformIndex": "https://ai.syncfusion.com/vue/llms.txt",
    "skillPack": "syncfusion/vue-ui-components-skills",
    "docs": "https://ai.syncfusion.com/gallery/vue/diagram-mind-map.md"
  },
  "files": [
    {
      "target": "src/components/diagram-mind-map/Diagram.vue",
      "content": "<template>\n<div class=\"control-section\">\n    <div class=\"diagram-control\">\n        <ejs-diagram style='display:block' ref='diagramObj' id=\"diagram\" :width='width' :height='height' :constraints= 'constraints' :snapSettings='snapSettings' :tool='tool' :layout='layout' :selectionChange='selectionChange' :getNodeDefaults='getNodeDefaults' :selectedItems='selectedItems' :getConnectorDefaults='getConnectorDefaults' :dataSourceSettings='dataSourceSettings'\n        :getCustomTool='getCustomTool'></ejs-diagram>\n        <input id=\"palette\" style=\"visibility: hidden;position: absolute\" type=\"color\" name=\"favcolor\" value=\"#000000\">\n    </div>\n\n</div>\n</template>\n\n<style scoped>\n</style>\n\n<script>\nimport {\n  DiagramComponent,\n  Diagram,\n  Node,\n  ConnectorConstraints,\n  DiagramConstraints,\n  DataBinding,\n  PointPort,\n  randomId,\n  PortVisibility,\n  SelectorConstraints,\n  ToolBase,\n  SnapConstraints,\n  MindMap,\n  HierarchicalTree,\n  DiagramTools,\n  NodeConstraints,\n  \n} from \"@syncfusion/ej2-vue-diagrams\";\nimport { DataManager, Query } from \"@syncfusion/ej2-data\";\n\nconst mindMap = [\n    { id: 1, Label: \"Creativity\", fill: \"red\", branch: \"Root\" },\n    { id: 3, Label: \"Brainstorming\", parentId: 1, branch: \"Right\", fill: \"red\" },\n    { id: 4, Label: \"Complementing\", parentId: 1, branch: \"Left\", fill: \"red\" },\n    { id: 22, Label: \"Sessions\", parentId: 3, branch: \"subRight\", fill: \"red\" },\n    { id: 23, Label: \"Generate\", parentId: 3, branch: \"subRight\", fill: \"red\" },\n    { id: 25, Label: \"Local\", parentId: 22, branch: \"subRight\" },\n    { id: 26, Label: \"Remote\", parentId: 22, branch: \"subRight\" },\n    { id: 27, Label: \"Individual\", parentId: 22, branch: \"subRight\" },\n    { id: 28, Label: \"Teams\", parentId: 22, branch: \"subRight\" },\n    { id: 29, Label: \"Ideas\", parentId: 23, branch: \"subRight\" },\n    { id: 30, Label: \"Engagement\", parentId: 23, branch: \"subRight\" },\n    { id: 31, Label: \"Product\", parentId: 29, branch: \"subRight\" },\n    { id: 32, Label: \"Service\", parentId: 29, branch: \"subRight\" },\n    { id: 33, Label: \"Business Direction\", parentId: 29, branch: \"subRight\" },\n    { id: 34, Label: \"Empowering\", parentId: 30, branch: \"subRight\" },\n    { id: 35, Label: \"Ownership\", parentId: 30, branch: \"subRight\" },\n    { id: 50, Label: \"Information\", parentId: 4, branch: \"subLeft\" },\n    { id: 51, Label: \"Expectations\", parentId: 4, branch: \"subLeft\" },\n    { id: 53, Label: \"Competetors\", parentId: 50, branch: \"subLeft\" },\n    { id: 54, Label: \"Products\", parentId: 50, branch: \"subLeft\" },\n    { id: 55, Label: \"Features\", parentId: 50, branch: \"subLeft\" },\n    { id: 56, Label: \"Other Data\", parentId: 50, branch: \"subLeft\" },\n    { id: 59, Label: \"Organization\", parentId: 51, branch: \"subLeft\" },\n    { id: 60, Label: \"Customer\", parentId: 51, branch: \"subLeft\" },\n    { id: 61, Label: \"Staff\", parentId: 51, branch: \"subLeft\" },\n    { id: 62, Label: \"Stakeholders\", parentId: 51, branch: \"subLeft\" }\n];\n\n// Variables for diagram instance and data manager\nlet diagramInstance;\nlet items = new DataManager(\n  mindMap,\n  new Query().take(7)\n);\nexport default {\n  components: {\n    'ejs-diagram': DiagramComponent\n  },\n  data: function() {\n    return {\n      width: \"100%\",\n      height: \"550px\",\n      constraints: DiagramConstraints.Default & ~DiagramConstraints.UndoRedo,\n      snapSettings: { constraints: SnapConstraints.None },\n      tool: DiagramTools.SingleSelect,\n      layout: {\n        type: \"MindMap\",\n         orientation:\"Horizontal\",\n        getBranch: (node, nodes) => {\n          return ((node).data).branch;\n        },\n        horizontalSpacing: 50\n      },\n      //Selectionchange event for Node and connector\n      selectionChange: (arg) => {\n        if (arg.state === \"Changing\") {\n          if (\n            arg.newValue[0] instanceof Node &&\n            diagramInstance.selectedItems.userHandles\n          ) {\n            for (let handle of diagramInstance.selectedItems.userHandles) {\n              handle.visible = true;\n            }\n            if (\n              ((arg.newValue[0]).data).branch ===\n                \"Left\" ||\n              ((arg.newValue[0]).data).branch ===\n                \"subLeft\"\n            ) {\n              hideUserHandle(\"leftHandle\");\n              changeUserHandlePosition(\"leftHandle\");\n            } else if (\n              ((arg.newValue[0]).data).branch ===\n                \"Right\" ||\n              ((arg.newValue[0]).data).branch ===\n                \"subRight\"\n            ) {\n              hideUserHandle(\"rightHandle\");\n              changeUserHandlePosition(\"rightHandle\");\n            } else if (\n              ((arg.newValue[0]).data).branch === \"Root\"\n            ) {\n              hideUserHandle(\"delete\");\n            }\n          } else {\n            hideUserHandle(\"leftHandle\");\n            hideUserHandle(\"rightHandle\");\n            hideUserHandle(\"delete\");\n          }\n        }\n      },\n      selectedItems: {\n        constraints: SelectorConstraints.UserHandle,\n        userHandles: handle\n      },\n      dataSourceSettings: {\n        id: \"id\",\n        parentId: \"parentId\",\n        dataSource: items,\n        root: String(1)\n      },\n      //sets node default value\n      getNodeDefaults: (obj) => {\n        obj.constraints = NodeConstraints.Default & ~NodeConstraints.Drag;\n        if (\n          (obj.data).branch === \"Left\" ||\n          (obj.data).branch === \"Right\" ||\n          (obj.data).branch === \"Root\"\n        ) {\n          obj.shape = { type: \"Basic\", shape: \"Ellipse\" };\n          obj.borderColor = \"black\"; /* tslint:disable:no-string-literal */\n          obj.style = {\n            fill:\n              (obj.data).branch === \"Root\"\n                ? \"#E74C3C\"\n                : \"#F39C12\",\n            strokeColor: \"none\",\n            strokeWidth: 2\n          };\n          obj.annotations = [\n            {\n              content: (obj.data).Label,\n              margin: { left: 10, right: 10, top: 10, bottom: 10 },\n              style: { color: \"white\" }\n            }\n          ];\n          let port = getPort();\n          for (let i = 0; i < port.length; i++) {\n            obj.ports.push(new PointPort(obj, \"ports\", port[i], true));\n          }\n        } else {\n          let color; /* tslint:disable:no-string-literal */\n          if (\n            (obj.data).branch === \"Right\" ||\n            (obj.data).branch === \"subRight\"\n          ) {\n            color = \"#8E44AD\";\n          } else {\n            color = \"#3498DB\";\n          }\n          obj.shape = { type: \"Basic\", shape: \"Rectangle\" };\n          obj.style = { fill: color, strokeWidth: 0 };\n          obj.minWidth = 100;\n          obj.height = 4;\n          let port = getPort();\n          for (let i = 0; i < port.length; i++) {\n            obj.ports.push(new PointPort(obj, \"ports\", port[i], true));\n          }\n          obj.annotations = [\n            {\n              content: (obj.data).Label,\n              offset: { x: 0.5, y: 0 },\n              verticalAlignment: \"Bottom\"\n            }\n          ];\n          (obj.shape).margin = {\n            left: 0,\n            right: 0,\n            top: 0,\n            bottom: 0\n          };\n        }\n        return obj;\n      },\n      //sets connector default value\n      getConnectorDefaults: (connector,diagram) => {\n        connector.type = \"Bezier\";\n        connector.targetDecorator = { shape: \"None\" };\n        if (connector.sourceID && connector.targetID && connector.constraints) {\n          let sourceNode = diagram.getObject(connector.sourceID);\n          let targetNode = diagram.getObject(connector.targetID);\n          if (\n            (targetNode.data).branch === \"Right\" ||\n            (targetNode.data).branch === \"subRight\"\n          ) {\n            connector.sourcePortID = sourceNode.ports[0].id;\n            connector.targetPortID = targetNode.ports[1].id;\n            connector.style = { strokeWidth: 5, strokeColor: \"#8E44AD\" };\n          } else if (\n            (targetNode.data).branch === \"Left\" ||\n            (targetNode.data).branch === \"subLeft\"\n          ) {\n            connector.sourcePortID = sourceNode.ports[1].id;\n            connector.targetPortID = targetNode.ports[0].id;\n            connector.style = { strokeWidth: 5, strokeColor: \"#3498DB\" };\n          }\n          connector.constraints &= ~ConnectorConstraints.Select;\n        }\n        return connector;\n      },\n      getCustomTool: getTool\n    };\n  },\n  provide: {\n    diagram: [DataBinding, MindMap, HierarchicalTree]\n  },\n  mounted: function() {\n    diagramInstance = this.$refs.diagramObj.ej2Instances;\n    diagramInstance.fitToPage();\n  }\n}\n\n//Function to create ports for nodes\nfunction getPort() {\n  let port = [\n    {\n      id: \"port1\",\n      offset: { x: 0, y: 0.5 },\n      visibility: PortVisibility.Hidden,\n      style: { fill: \"black\" }\n    },\n    {\n      id: \"port2\",\n      offset: { x: 1, y: 0.5 },\n      visibility: PortVisibility.Hidden,\n      style: { fill: \"black\" }\n    }\n  ];\n  return port;\n}\n// Function to add a new node\nfunction addNode() {\n  let obj = {};\n  obj.id = randomId();\n  obj.data = {};\n  (obj.data).Label = \"Node\";\n  return obj;\n}\n// Function to add a new connector\nfunction addConnector(source, target) {\n  let connector = {};\n  connector.id = randomId();\n  connector.sourceID = source.id;\n  connector.targetID = target.id;\n  return connector;\n}\n// Function to get the tool for user handles\nfunction getTool(action) {\n  let tool;\n  if (action === \"leftHandle\") {\n    tool = new LeftExtendTool(diagramInstance.commandHandler);\n  } else if (action === \"rightHandle\") {\n    tool = new RightExtendTool(diagramInstance.commandHandler);\n  } else if (action === \"delete\") {\n    tool = new DeleteClick(diagramInstance.commandHandler);\n  }\n  return tool;\n}\n\n// Class definition for handling left extension tool\nclass LeftExtendTool extends ToolBase {\n   mouseDown(args) {\n    super.mouseDown(args);\n    this.inAction = true;\n  }\n   mouseUp(args) {\n    if (this.inAction) {\n      let selectedObject = this.commandHandler.getSelectedObject();\n      if (selectedObject[0]) {\n        if (selectedObject[0] instanceof Node) {\n          let node = addNode();\n          if ((selectedObject[0].data).branch === \"Root\") {\n            (node.data).branch = \"Right\";\n          } else if (\n            (selectedObject[0].data).branch === \"Right\" ||\n            (selectedObject[0].data).branch === \"subRight\"\n          ) {\n            (node.data).branch = \"subRight\";\n          }\n          getTextEditValue(selectedObject[0], node);\n        }\n      }\n    }\n  }\n}\n// Class definition for handling right extension tool\nclass RightExtendTool extends ToolBase {\n  //mouseDown event\n   mouseDown(args) {\n    super.mouseDown(args);\n    this.inAction = true;\n  }\n  //mouseDown event\n   mouseUp(args) {\n    if (this.inAction) {\n      let selectedObject = this.commandHandler.getSelectedObject();\n      if (selectedObject[0]) {\n        if (selectedObject[0] instanceof Node) {\n          let node = addNode();\n          if ((selectedObject[0].data).branch === \"Root\") {\n            (node.data ).branch = \"Left\";\n          } else if (\n            (selectedObject[0].data).branch === \"Left\" ||\n            (selectedObject[0].data).branch === \"subLeft\"\n          ) {\n            (node.data).branch = \"subLeft\";\n          }\n          getTextEditValue(selectedObject[0], node);\n        }\n      }\n    }\n  }\n}\n// Class definition for handling delete tool\nclass DeleteClick extends ToolBase {\n  //mouseDown event\n   mouseDown(args) {\n    super.mouseDown(args);\n    this.inAction = true;\n  }\n  //mouseup event\n   mouseUp(args) {\n    if (this.inAction) {\n      let selectedObject = this.commandHandler.getSelectedObject();\n      if (selectedObject[0]) {\n        if (selectedObject[0] instanceof Node) {\n          let node = selectedObject[0] ;\n          this.removeSubChild(node);\n        }\n        diagramInstance.doLayout();\n      }\n    }\n  }\n  //Remove the subchild Elements\n   removeSubChild(node) {\n    for (let i = node.outEdges.length - 1; i >= 0; i--) {\n      let connector = diagramInstance.getObject(\n        node.outEdges[i]\n      );\n      let childNode = diagramInstance.getObject(\n        connector.targetID\n      );\n      if (childNode.outEdges.length > 0) {\n        this.removeSubChild(childNode);\n      } else {\n        diagramInstance.remove(childNode);\n      }\n    }\n    diagramInstance.remove(node);\n  }\n}\n//Function to hide the require userhandle.\nfunction hideUserHandle(name) {\n  if (diagramInstance.selectedItems.userHandles) {\n    for (let handle of diagramInstance.selectedItems.userHandles) {\n      if (handle.name === name) {\n        handle.visible = false;\n      }\n    }\n  }\n}\n// Definitions for user handle icons\nlet leftarrow =\n  \"M11.924,6.202 L4.633,6.202 L4.633,9.266 L0,4.633 L4.632,0 L4.632,3.551 L11.923,3.551 L11.923,6.202Z\";\nlet rightarrow =\n  \"M0,3.063 L7.292,3.063 L7.292,0 L11.924,4.633 L7.292,9.266 L7.292,5.714 L0.001,5.714 L0.001,3.063Z\";\nlet deleteicon =\n  \"M 7.04 22.13 L 92.95 22.13 L 92.95 88.8 C 92.95 91.92 91.55 94.58 88.76\" +\n  \"96.74 C 85.97 98.91 82.55 100 78.52 100 L 21.48 100 C 17.45 100 14.03 98.91 11.24 96.74 C 8.45 94.58 7.04\" +\n  \"91.92 7.04 88.8 z M 32.22 0 L 67.78 0 L 75.17 5.47 L 100 5.47 L 100 16.67 L 0 16.67 L 0 5.47 L 24.83 5.47 z\";\n\nlet leftuserhandle = setUserHandle(\n  //it is in dedicated line here.\n  \"leftHandle\",\n  leftarrow,\n  \"Left\",\n  1,\n  { top: 0, bottom: 0, left: 0, right: 10 },\n  \"Left\",\n  \"Top\"\n);\nlet rightuserhandle = setUserHandle(\n  //it is in dedicated line here.\n  \"rightHandle\",\n  rightarrow,\n  \"Right\",\n  1,\n  { top: 0, bottom: 0, left: 10, right: 0 },\n  \"Right\",\n  \"Top\"\n);\nlet deleteuserhandle = setUserHandle(\n  //it is in dedicated line here.\n  \"delete\",\n  deleteicon,\n  \"Top\",\n  0.5,\n  { top: 0, bottom: 10, left: 0, right: 0 },\n  \"Center\",\n  \"Center\"\n);\nlet handle = [\n  leftuserhandle,\n  rightuserhandle,\n  deleteuserhandle\n];\n///Function to set and creation of the Userhandle.\nfunction setUserHandle( //it is in dedicated line here.\n  name,\n  pathData,\n  side,\n  offset,\n  margin,\n  horizontalAlignment,\n  verticalAlignment\n) {\n  let userhandle = {\n    name: name,\n    pathData: pathData,\n    backgroundColor: \"black\",\n    pathColor: \"white\",\n    side: side,\n    offset: offset,\n    margin: margin,\n    horizontalAlignment: horizontalAlignment,\n    verticalAlignment: verticalAlignment\n  };\n  return userhandle;\n}\n//Function to Change the Position of the UserHandle.\nfunction changeUserHandlePosition(change) {\n  if (diagramInstance.selectedItems.userHandles) {\n    for (let handle of diagramInstance.selectedItems.userHandles) {\n      if (handle.name === \"delete\" && change === \"leftHandle\") {\n        applyHandle(\n          handle,\n          \"Left\",\n          1,\n          { top: 0, bottom: 0, left: 0, right: 10 },\n          \"Left\",\n          \"Top\"\n        );\n      } else if (handle.name === \"delete\" && change === \"rightHandle\") {\n        applyHandle(\n          handle,\n          \"Right\",\n          1,\n          { top: 0, bottom: 0, left: 10, right: 0 },\n          \"Right\",\n          \"Top\"\n        );\n      }\n    }\n  }\n}\n//set the value for UserHandle element.\nfunction applyHandle( //it is in dedicated line here.\n  handle,\n  side,\n  offset,\n  margin,\n  horizontalAlignment,\n  verticalAlignment\n) {\n  handle.side = side;\n  handle.offset = offset;\n  handle.margin = margin;\n  handle.horizontalAlignment = horizontalAlignment;\n  handle.verticalAlignment = verticalAlignment;\n}\n// Handles node creation, connector addition, selection, layout, view, and text editing in the diagram.\nfunction getTextEditValue(selectObject, node){\n    var connector = addConnector(selectObject, node);\n   diagramInstance.clearSelection();\n   var newNode  = diagramInstance.add(node);\n   diagramInstance.add(connector);\n   diagramInstance.doLayout();\n   diagramInstance.bringIntoView(newNode.wrapper.bounds);\n   diagramInstance.select([diagramInstance.nameTable[newNode.id]]);\n   diagramInstance.startTextEdit(diagramInstance.selectedItems.nodes[0]);\n}\n</script>\n"
    },
    {
      "target": "src/components/diagram-mind-map/DiagramView.vue",
      "content": "<template>\n  <Diagram />\n</template>\n\n<script setup>\nimport Diagram from '../../components/Diagram.vue'\n</script>"
    }
  ]
}