{
  "$schema": "https://ai.syncfusion.com/schema/registry-item.json",
  "name": "diagram-mindmap",
  "framework": "blazor",
  "type": "registry:component",
  "component": "Diagram",
  "variant": "mindmap",
  "dependencies": [
    "Syncfusion.Blazor.Diagram"
  ],
  "description": "Mind map diagram configures custom tools, node and connector creation, selection events, and interactive diagram constraints.",
  "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/blazor/llms.txt",
    "skillPack": "syncfusion/blazor-ui-components-skills",
    "docs": "https://ai.syncfusion.com/gallery/blazor/diagram-mindmap.md"
  },
  "files": [
    {
      "target": "src/components/diagram-mindmap/Diagram.razor",
      "content": "@page \"/diagram/mindmap\"\n@using System.Collections.ObjectModel\n@using Syncfusion.Blazor.Diagram\n@using NodeShape = Syncfusion.Blazor.Diagram.NodeShapes\n\n<div class=\"content-wrapper\">\n    <div class=\"col-lg-9 control-section\" style=\"border-right: 1px solid #D7D7D7;height: 640px\">\n        <SfDiagramComponent @ref=\"@DiagramInstance\" InteractionController=\"@InteractionController\" Height=\"600px\" GetCustomTool=\"@GetCustomTool\" NodeCreating=\"@NodeCreating\" ConnectorCreating=\"@ConnectorCreating\" SelectionSettings=\"@DiagramSelectionSettings\" SelectionChanging=\"OnSelectionChanging\" Created=\"OnCreated\" Constraints=\"@_diagramConstraints\">\n            <ScrollSettings @bind-ScrollLimit=\"@ScrollLimit\"></ScrollSettings>\n            <Layout FixedNode=\"1\" HorizontalSpacing=\"@HorizontalSpacing\" VerticalSpacing=\"@VerticalSpacing\" Type=\"LayoutType.MindMap\" GetBranch=\"@GetBranch\"></Layout>\n            <SnapSettings Constraints=\"@SnapConstraints.None\"></SnapSettings>\n            <DataSourceSettings ID=\"Id\" ParentID=\"ParentId\" DataSource=\"@DataSource\">\n            </DataSourceSettings>\n        </SfDiagramComponent>\n    </div>\n</div>\n@code\n{\n    static List<MindMapDetails>? MindmapData { get; set; } = new List<MindMapDetails>();\n    ScrollLimitMode ScrollLimit { get; set; } = ScrollLimitMode.Diagram;\n    SfDiagramComponent? DiagramInstance { get; set; }\n    DiagramInteractions InteractionController { get; set; } = DiagramInteractions.SingleSelect;\n    private DiagramConstraints _diagramConstraints = DiagramConstraints.Default & ~DiagramConstraints.UndoRedo;\n    int VerticalSpacing { get; set; } = 20;\n    int HorizontalSpacing { get; set; } = 80;\n    int? HorizontalValue { get; set; } = 80;\n    int? VerticalValue { get; set; } = 20;\n    DiagramSelectionSettings? DiagramSelectionSettings { get; set; } = new DiagramSelectionSettings();\n    DiagramObjectCollection<UserHandle> Handles { get; set; } = new DiagramObjectCollection<UserHandle>();\n    private BranchType GetBranch(IDiagramObject obj)\n    {\n        BranchType Branch = ((obj as Node)!.Data as MindMapDetails)!.Branch;\n        return Branch;\n    }\n    private void OnCreated()\n    {\n        DiagramInstance!.Select(new ObservableCollection<IDiagramObject>() { DiagramInstance.Nodes![0] });\n    }\n    private void OnHorizontalSpaceChange(Syncfusion.Blazor.Inputs.ChangeEventArgs<int?> args)\n    {\n        HorizontalValue = (int)args.Value!;\n        HorizontalSpacing = int.Parse(args.Value.ToString()!);\n    }\n    private void OnVerticalSpaceChange(Syncfusion.Blazor.Inputs.ChangeEventArgs<int?> args)\n    {\n        VerticalValue = (int)args.Value!;\n        VerticalSpacing = int.Parse(args.Value.ToString()!);\n    }\n    // Method to customize the tool\n    public InteractionControllerBase GetCustomTool(DiagramElementAction action, string id)\n    {\n        InteractionControllerBase? tool = null;\n        if (id == \"AddLeft\")\n        {\n            tool = new AddRightTool(DiagramInstance!);\n        }\n        else if(id == \"AddRight\")\n        {\n            tool = new AddLeftTool(DiagramInstance!);\n        }\n        else\n        {\n            tool = new DeleteTool(DiagramInstance!);\n        }\n        return tool;\n    }\n    // Custom tool to add the node.\n    public class AddLeftTool : InteractionControllerBase\n    {\n        SfDiagramComponent DiagramInstance;\n        public AddLeftTool(SfDiagramComponent Diagram) : base(Diagram)\n        {\n            DiagramInstance = Diagram;\n        }\n        public override async void OnMouseDown(DiagramMouseEventArgs args)\n        {\n            int newChildID = DiagramInstance.Nodes!.Count + 1;\n            string newchildColor = \"\";\n            BranchType? type = (DiagramInstance.SelectionSettings!.Nodes![0].Data as MindMapDetails)!.Branch;\n            BranchType childType = BranchType.Left;\n            switch (type.ToString())\n            {\n                case \"Root\":\n                    childType = BranchType.Left;\n                    break;\n                case \"Left\":\n                    childType = BranchType.SubLeft;\n                    break;\n                case \"SubLeft\":\n                    childType = BranchType.SubLeft;\n                    break;\n            }\n            if (DiagramInstance.SelectionSettings.Nodes[0].Style!.Fill == \"#034d6d\")\n            {\n                newchildColor = \"#1b80c6\";\n            }\n            else\n            {\n                newchildColor = \"#3dbfc9\";\n            }\n            MindMapDetails childNode = new MindMapDetails()\n            {\n                Id = newChildID.ToString(),\n                ParentId = (DiagramInstance.SelectionSettings.Nodes[0].Data as MindMapDetails)!.Id,\n                Fill = newchildColor,\n                Branch = childType,\n                Label = \"New Child\"\n            };\n            DiagramInstance.BeginUpdate();\n            await UpdatePortConnection(childNode, DiagramInstance);\n            await DiagramInstance.EndUpdateAsync();\n            MindmapData!.Add(childNode);\n            DiagramInstance.ClearSelection();\n            base.OnMouseDown(args);\n            DiagramInstance.Select(new ObservableCollection<IDiagramObject>() { DiagramInstance.Nodes[DiagramInstance.Nodes.Count - 1] });\n            DiagramInstance.StartTextEdit(DiagramInstance.Nodes[DiagramInstance.Nodes.Count - 1]);\n            this.InAction = true;\n        }\n    }\n    private static async Task UpdatePortConnection(MindMapDetails childNode,SfDiagramComponent DiagramInstance)\n    {\n        Node node = new Node()\n        {\n            Data = childNode,\n        };\n        Connector connector = new Connector()\n        {\n            TargetID = node.ID,\n            SourceID = DiagramInstance.SelectionSettings!.Nodes![0].ID\n        };\n        await DiagramInstance.AddDiagramElementsAsync(new DiagramObjectCollection<NodeBase>() { node, connector });\n        Node? sourceNode = DiagramInstance.GetObject((connector as Connector).SourceID!) as Node;\n        Node? targetNode = DiagramInstance.GetObject((connector as Connector).TargetID!) as Node;\n        if (targetNode != null && targetNode.Data != null)\n        {\n            MindMapDetails? nodeInfo = (targetNode.Data as MindMapDetails);\n            if (nodeInfo!.Branch == BranchType.Right || nodeInfo.Branch == BranchType.SubRight)\n            {\n                (connector as Connector).SourcePortID = sourceNode!.Ports![0].ID;\n                (connector as Connector).TargetPortID = targetNode.Ports![1].ID;\n            }\n            else if (nodeInfo.Branch == BranchType.Left || nodeInfo.Branch == BranchType.SubLeft)\n            {\n                (connector as Connector).SourcePortID = sourceNode!.Ports![1].ID;\n                (connector as Connector).TargetPortID = targetNode.Ports![0].ID;\n            }\n        }\n        await DiagramInstance.DoLayoutAsync();\n    }\n    // Custom tool to add the node.\n    public class AddRightTool : InteractionControllerBase\n    {\n        SfDiagramComponent DiagramInstance;\n        public AddRightTool(SfDiagramComponent Diagram) : base(Diagram)\n        {\n            DiagramInstance = Diagram;\n        }\n        public override async void OnMouseDown(DiagramMouseEventArgs args)\n        {\n            int newChildID = DiagramInstance.Nodes!.Count + 1;\n            string newchildColor = \"\";\n            BranchType type = (DiagramInstance.SelectionSettings!.Nodes![0].Data as MindMapDetails)!.Branch;\n            BranchType childType = BranchType.Left;\n            switch (type.ToString())\n            {\n                case \"Root\":\n                    childType = BranchType.Right;\n                    break;\n                case \"Right\":\n                    childType = BranchType.SubRight;\n                    break;\n                case \"SubRight\":\n                    childType = BranchType.SubRight;\n                    break;\n            }\n            if (DiagramInstance.SelectionSettings.Nodes[0].Style!.Fill == \"#034d6d\")\n            {\n                newchildColor = \"#1b80c6\";\n            }\n            else\n            {\n                newchildColor = \"#3dbfc9\";\n            }\n            MindMapDetails childNode = new MindMapDetails()\n            {\n                Id = newChildID.ToString(),\n                ParentId = (DiagramInstance.SelectionSettings.Nodes[0].Data as MindMapDetails)!.Id,\n                Fill = newchildColor,\n                Branch = childType,\n                Label = \"New Child\"\n            };\n            DiagramInstance.BeginUpdate();\n            await UpdatePortConnection(childNode, DiagramInstance);\n            await DiagramInstance.EndUpdateAsync();\n            MindmapData!.Add(childNode);\n            DiagramInstance.ClearSelection();\n            base.OnMouseDown(args);\n            DiagramInstance.Select(new ObservableCollection<IDiagramObject>() { DiagramInstance.Nodes[DiagramInstance.Nodes.Count - 1] });\n            DiagramInstance.StartTextEdit(DiagramInstance.Nodes[DiagramInstance.Nodes.Count - 1]);\n            this.InAction = true;\n        }\n    }\n    public class DeleteTool : InteractionControllerBase\n    {\n        SfDiagramComponent sfDiagram;\n        Node? deleteObject = null;\n        public DeleteTool(SfDiagramComponent Diagram) : base(Diagram)\n        {\n            sfDiagram = Diagram;\n        }\n        public override void OnMouseDown(DiagramMouseEventArgs args)\n        {\n            deleteObject = (sfDiagram.SelectionSettings!.Nodes![0]) as Node;\n        }\n        public override void OnMouseUp(DiagramMouseEventArgs? args)\n        {\n            if (deleteObject != null)\n            {\n                RemoveData(deleteObject, sfDiagram);\n                sfDiagram.Nodes!.Remove(deleteObject);\n                _ = sfDiagram.EndUpdateAsync();\n                _ = sfDiagram.DoLayoutAsync();\n            }\n            base.OnMouseUp(args);\n            this.InAction = true;\n        }\n    }\n    private static void RemoveData(Node node, SfDiagramComponent DiagramInstance)\n    {\n        if (node == null || DiagramInstance == null) return;\n        if (node.OutEdges != null && node.OutEdges.Count > 0)\n        {\n            for (int i = node.OutEdges.Count - 1; i >= 0; i--)\n            {\n                var connector = DiagramInstance.GetObject(node.OutEdges[i]) as Connector;\n                if (connector == null) continue;\n                Node? targetNode = DiagramInstance.GetObject(connector!.TargetID!) as Node;\n                if (targetNode != null)\n                {\n                    RemoveData(targetNode, DiagramInstance);\n                    if (DiagramInstance.Nodes != null && DiagramInstance.Nodes.Contains(targetNode))\n                        DiagramInstance.Nodes.Remove(targetNode);\n                }\n                if (DiagramInstance.Connectors != null && DiagramInstance.Connectors.Contains(connector))\n                    DiagramInstance.Connectors.Remove(connector);\n            }\n        }\n        if (node.Data is MindMapDetails details)\n        {\n            MindmapData?.Remove(details);\n        }\n    }\n    private void OnSelectionChanging(SelectionChangingEventArgs args)\n    {\n        if (args.NewValue!.Count > 0)\n        {\n            if (args.NewValue[0] is Node && (args.NewValue[0] as Node)!.Data != null)\n            {\n                BranchType type = ((args.NewValue[0] as Node)!.Data as MindMapDetails)!.Branch;\n                if (type == BranchType.Root)\n                {\n                    DiagramSelectionSettings!.UserHandles![0].Visible = false;\n                    DiagramSelectionSettings.UserHandles[1].Visible = false;\n                    DiagramSelectionSettings.UserHandles[2].Visible = true;\n                    DiagramSelectionSettings.UserHandles[3].Visible = true;\n                }\n                else if(type==BranchType.Left||type==BranchType.SubLeft)\n                {\n                    DiagramSelectionSettings!.UserHandles![0].Visible = false;\n                    DiagramSelectionSettings.UserHandles[1].Visible = true;\n                    DiagramSelectionSettings.UserHandles[2].Visible = true;\n                    DiagramSelectionSettings.UserHandles[3].Visible = false;\n                }\n                else if (type == BranchType.Right || type == BranchType.SubRight)\n                {\n                    DiagramSelectionSettings!.UserHandles![0].Visible = true;\n                    DiagramSelectionSettings.UserHandles[1].Visible = false;\n                    DiagramSelectionSettings.UserHandles[2].Visible = false;\n                    DiagramSelectionSettings.UserHandles[3].Visible = true;\n                }\n            }\n        }\n    }\n    private void NodeCreating(IDiagramObject obj)\n    {\n        Node? node = obj as Node;\n        //node.Constraints = NodeConstraints.Default & ~NodeConstraints.Drag;\n        MindMapDetails? hierarchicalData = null;\n        if (node!.Data != null)\n        {\n            if (node.Data is System.Text.Json.JsonElement)\n            {\n                node.Data = System.Text.Json.JsonSerializer.Deserialize<MindMapDetails>(node.Data.ToString()!);\n            }\n            hierarchicalData = node.Data as MindMapDetails;\n        }\n        node.Height = 50;\n        node.Width = 100;\n        node.Shape = new BasicShape() { Type = NodeShape.Basic, Shape = NodeBasicShapes.Ellipse };\n        PointPort port21 = new PointPort()\n        {\n            ID = \"left\",\n            Offset = new DiagramPoint() { X = 0, Y = 0.5 },\n            Height = 10,\n            Width = 10,\n        };\n        PointPort port22 = new PointPort()\n        {\n            ID = \"right\",\n            Offset = new DiagramPoint() { X = 1, Y = 0.5 },\n            Height = 10,\n            Width = 10,\n        };\n        if (node.Data != null)\n        {\n            node.Style!.Fill = hierarchicalData!.Fill;\n            node.Style.StrokeColor = hierarchicalData.Fill;\n            node.Ports = new DiagramObjectCollection<PointPort>()\n            {\n                port21,port22\n            };\n        }\n        string name = \"\";\n        if (hierarchicalData != null)\n        {\n            name = hierarchicalData.Label!;\n        }\n        else\n        {\n            name = \"New Child\";\n        }\n        node.Annotations = new DiagramObjectCollection<ShapeAnnotation>()\n        {\n            new ShapeAnnotation()\n            {\n                Content = name,\n                Style=new TextStyle(){Color=\"White\",FontSize = 12,FontFamily=\"Segoe UI\"},\n                Offset=new DiagramPoint(){X=0.5,Y=0.5}\n            }\n        };\n        node.Constraints &= ~NodeConstraints.Rotate;\n    }\n    private void ConnectorCreating(IDiagramObject connector)\n    {\n        (connector as Connector)!.Type = ConnectorSegmentType.Bezier;\n        (connector as Connector)!.BezierConnectorSettings = new BezierConnectorSettings() { AllowSegmentsReset = false };\n        (connector as Connector)!.Constraints = ConnectorConstraints.Default & ~ConnectorConstraints.Select;\n        (connector as Connector)!.Style = new ShapeStyle() { StrokeColor = \"#4f4f4f\", StrokeWidth = 1 };\n        (connector as Connector)!.TargetDecorator = new DecoratorSettings() { Shape = DecoratorShape.None };\n        (connector as Connector)!.SourceDecorator!.Shape = DecoratorShape.None;\n        Node? sourceNode = DiagramInstance!.GetObject((connector as Connector)!.SourceID!) as Node;\n        Node? targetNode = DiagramInstance.GetObject((connector as Connector)!.TargetID!) as Node;\n        if (targetNode != null && targetNode.Data != null)\n        {\n            MindMapDetails nodeInfo = (targetNode.Data as MindMapDetails)!;\n            if (nodeInfo.Branch == BranchType.Right || nodeInfo.Branch == BranchType.SubRight)\n            {\n                (connector as Connector)!.SourcePortID = sourceNode!.Ports![0].ID;\n                (connector as Connector)!.TargetPortID = targetNode.Ports![1].ID;\n            }\n            else if (nodeInfo.Branch == BranchType.Left || nodeInfo.Branch == BranchType.SubLeft)\n            {\n                (connector as Connector)!.SourcePortID = sourceNode!.Ports![1].ID;\n                (connector as Connector)!.TargetPortID = targetNode.Ports![0].ID;\n            }\n        }\n    }\n    private void UpdateHandle()\n    {\n        UserHandle deleteLeftHandle = AddHandle(\"DeleteRight\", \"delete\", Direction.Right);\n        UserHandle addRightHandle = AddHandle(\"AddLeft\", \"add\", Direction.Left);\n        UserHandle addLeftHandle = AddHandle(\"AddRight\", \"add\", Direction.Right);\n        UserHandle deleteRightHandle = AddHandle(\"DeleteLeft\", \"delete\", Direction.Left);\n        Handles.Add(deleteLeftHandle);\n        Handles.Add(deleteRightHandle);\n        Handles.Add(addLeftHandle);\n        Handles.Add(addRightHandle);\n        DiagramSelectionSettings!.UserHandles = Handles;\n    }\n    private UserHandle AddHandle(string name, string path, Direction direction)\n    {\n        UserHandle handle = new UserHandle()\n        {\n            Name = name,\n            Visible = true,\n            Offset = 0.5,\n            Side = direction,\n            Margin = new DiagramThickness() { Top = 0, Bottom = 0, Left = 0, Right = 0 }\n        };\n        if (path == \"delete\")\n        {\n            handle.PathData = \"M1.0000023,3 L7.0000024,3 7.0000024,8.75 C7.0000024,9.4399996 6.4400025,10 5.7500024,10 L2.2500024,10 C1.5600024,10 1.0000023,9.4399996 1.0000023,8.75 z M2.0699998,0 L5.9300004,0 6.3420029,0.99999994 8.0000001,0.99999994 8.0000001,2 0,2 0,0.99999994 1.6580048,0.99999994 z\";\n        }\n        else\n        {\n            handle.PathData = \"M4.0000001,0 L6,0 6,4.0000033 10,4.0000033 10,6.0000033 6,6.0000033 6,10 4.0000001,10 4.0000001,6.0000033 0,6.0000033 0,4.0000033 4.0000001,4.0000033 z\";\n        }\n        return handle;\n    }\n    public class MindMapDetails\n    {\n        public string? Id { get; set; }\n        public string? Label { get; set; }\n        public string? ParentId { get; set; }\n        public BranchType Branch { get; set; }\n        public string? Fill { get; set; }\n    }\n    public object? DataSource;\n    protected override void OnInitialized()\n    {\n        DiagramSelectionSettings!.Constraints &= ~(SelectorConstraints.ResizeAll | SelectorConstraints.Rotate);\n        MindmapData = new List<MindMapDetails>()\n        {\n            new MindMapDetails(){Id=\"1\",Label=\"Business Planning\",ParentId =\"\",Branch= BranchType.Root, Fill=\"#034d6d\" },\n            new MindMapDetails(){Id=\"3\",Label= \"Requirements\", ParentId=\"1\",Branch= BranchType.Right,Fill= \"#1b80c6\" },\n            new MindMapDetails(){Id=\"4\",Label= \"Marketing\", ParentId=\"1\",Branch= BranchType.Left,Fill= \"#1b80c6\" },\n            new MindMapDetails(){Id=\"5\",Label= \"Budgets\",ParentId= \"1\",Branch= BranchType.Right,Fill= \"#1b80c6\" },\n            new MindMapDetails() { Id = \"10\", Label=\"Customer Groups\", ParentId= \"4\", Branch = BranchType.SubLeft,Fill= \"#3dbfc9\" },\n            new MindMapDetails() { Id = \"11\", Label= \"Branding\", ParentId= \"4\", Branch = BranchType.SubLeft, Fill= \"#3dbfc9\" },\n        };\n        DataSource = MindmapData;\n        UpdateHandle();\n    }\n}"
    }
  ]
}