Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Theme
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Create API Key
Add Docs
Blazor Diagrams
https://github.com/blazor-diagrams/blazor.diagrams
Admin
Blazor Diagrams is a fully customizable and extensible all-purpose diagrams library for Blazor that
...
Tokens:
19,022
Snippets:
219
Trust Score:
6.3
Update:
1 week ago
Context
Skills
Chat
Benchmark
81.3
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Blazor Diagrams Blazor Diagrams (Z.Blazor.Diagrams) is a fully customizable and extensible all-purpose diagrams library for Blazor applications, supporting both Server Side and WebAssembly. It provides a complete solution for creating interactive diagrams with nodes, ports, links, and groups, featuring touch support, panning, zooming, virtualization, and customizable behaviors. The library separates the data layer (models) from the UI layer (widgets), making it easy to customize how diagrams look and behave. All default behaviors can be replaced with custom implementations, and the UI can be fully customized through Blazor components or CSS. The architecture emphasizes performance, especially for WebAssembly applications, by minimizing JavaScript interop calls. ## Installation ### Installing NuGet Packages ```bash # Install the main Blazor Diagrams package dotnet add package Z.Blazor.Diagrams # Optional: Install algorithms package for additional functionality dotnet add package Z.Blazor.Diagrams.Algorithms ``` ## Creating a Diagram ### BlazorDiagram Initialization The main entry point for creating diagrams is the `BlazorDiagram` class, which inherits from the abstract `Diagram` class and provides Blazor-specific functionality including component registration and rendering options. ```csharp @using Blazor.Diagrams @using Blazor.Diagrams.Core.Geometry @using Blazor.Diagrams.Core.Models @using Blazor.Diagrams.Components @using Blazor.Diagrams.Options <div style="width: 100%; height: 600px;"> <CascadingValue Value="BlazorDiagram"> <DiagramCanvas></DiagramCanvas> </CascadingValue> </div> @code { private BlazorDiagram BlazorDiagram { get; set; } = null!; protected override void OnInitialized() { var options = new BlazorDiagramOptions { AllowMultiSelection = true, AllowPanning = true, GridSize = 20, // Enable snap to grid Zoom = { Minimum = 0.25, Maximum = 2.0, Inverse = false }, Links = { EnableSnapping = true, SnappingRadius = 50, RequireTarget = true } }; BlazorDiagram = new BlazorDiagram(options); // Create nodes var node1 = BlazorDiagram.Nodes.Add(new NodeModel(new Point(50, 50))); var node2 = BlazorDiagram.Nodes.Add(new NodeModel(new Point(300, 100))); // Create link between nodes BlazorDiagram.Links.Add(new LinkModel(node1, node2)); } } ``` ## Node Management ### Adding and Configuring Nodes Nodes are the fundamental building blocks of diagrams. The `NodeModel` class represents a node with position, size, and ports. Nodes can be added individually or in batches through the `Nodes` layer. ```csharp // Create a basic node at a specific position var node = new NodeModel(new Point(100, 100)); node.Title = "My Node"; BlazorDiagram.Nodes.Add(node); // Create a node with a custom ID var namedNode = new NodeModel("custom-id", new Point(200, 200)); BlazorDiagram.Nodes.Add(namedNode); // Add multiple nodes at once (batched for performance) var nodes = new[] { new NodeModel(new Point(50, 50)), new NodeModel(new Point(150, 50)), new NodeModel(new Point(250, 50)) }; BlazorDiagram.Nodes.Add(nodes); // Remove a node (also removes connected links) BlazorDiagram.Nodes.Remove(node); // Clear all nodes BlazorDiagram.Nodes.Clear(); // Listen to node events node.SizeChanged += (n) => Console.WriteLine($"Node resized: {n.Size}"); node.Moving += (n) => Console.WriteLine($"Node moving to: {n.Position}"); // Lock a node to prevent user interaction node.Locked = true; // Check if a node is selected if (node.Selected) { Console.WriteLine("Node is selected"); } ``` ## Port Management ### Creating and Using Ports Ports are connection points on nodes where links can attach. They can be positioned on different sides of a node and support various alignments. ```csharp // Create a node and add ports with different alignments var node = new NodeModel(new Point(100, 100)); // Add ports using PortAlignment enum var topPort = node.AddPort(PortAlignment.Top); var rightPort = node.AddPort(PortAlignment.Right); var bottomPort = node.AddPort(PortAlignment.Bottom); var leftPort = node.AddPort(PortAlignment.Left); // Add a custom port model var customPort = new PortModel(node, PortAlignment.TopRight); node.AddPort(customPort); // Get a port by alignment var existingPort = node.GetPort(PortAlignment.Bottom); // Get port typed as custom port var typedPort = node.GetPort<CustomPortModel>(PortAlignment.Left); // Remove a port node.RemovePort(topPort); // Access all ports foreach (var port in node.Ports) { Console.WriteLine($"Port alignment: {port.Alignment}, Position: {port.Position}"); } // Access links connected to a port foreach (var link in bottomPort.Links) { Console.WriteLine($"Link: {link.Id}"); } // Check if a port can connect to another linkable if (port.CanAttachTo(otherPort)) { // Connection is allowed } BlazorDiagram.Nodes.Add(node); ``` ## Link Management ### Creating Links Between Nodes and Ports Links connect nodes or ports together. The library supports different types of anchors to determine where links attach to their source and target. ```csharp // Create a link between two ports var sourcePort = node1.AddPort(PortAlignment.Right); var targetPort = node2.AddPort(PortAlignment.Left); var portLink = new LinkModel(sourcePort, targetPort); BlazorDiagram.Links.Add(portLink); // Create a portless link between nodes (uses shape intersection) var nodeLink = new LinkModel(node1, node2); BlazorDiagram.Links.Add(nodeLink); // Create a link with custom ID var namedLink = new LinkModel("link-1", sourcePort, targetPort); BlazorDiagram.Links.Add(namedLink); // Configure link appearance nodeLink.Color = "#3498db"; nodeLink.SelectedColor = "#e74c3c"; nodeLink.Width = 3; // Add markers (arrows) to links nodeLink.SourceMarker = LinkMarker.Arrow; nodeLink.TargetMarker = LinkMarker.Circle; // Create custom-sized markers nodeLink.TargetMarker = LinkMarker.NewArrow(15, 10); // width, height nodeLink.SourceMarker = LinkMarker.NewCircle(5); // radius nodeLink.TargetMarker = LinkMarker.NewRectangle(10, 8); // width, height // Make link segmentable (allows adding vertices by clicking) nodeLink.Segmentable = true; // Add a vertex to a link var vertex = nodeLink.AddVertex(new Point(200, 150)); // Add a label to a link var label = nodeLink.AddLabel("Connection", distance: 0.5); // 0.5 = middle var offsetLabel = nodeLink.AddLabel("Offset", distance: 0.3, offset: new Point(0, -20)); // Listen to link events nodeLink.SourceChanged += (link, oldAnchor, newAnchor) => Console.WriteLine("Source changed"); nodeLink.TargetChanged += (link, oldAnchor, newAnchor) => Console.WriteLine("Target changed"); nodeLink.TargetAttached += (link) => Console.WriteLine("Link attached to target"); // Remove a link BlazorDiagram.Links.Remove(nodeLink); ``` ## Anchor Types ### Using Different Anchor Types for Links Anchors determine where links connect to nodes or ports. The library provides several anchor types for different use cases. ```csharp using Blazor.Diagrams.Core.Anchors; using Blazor.Diagrams.Core.Positions; // SinglePortAnchor - connects to a specific port var portAnchor = new SinglePortAnchor(port) { MiddleIfNoMarker = true, // Use port center if no marker UseShapeAndAlignment = true // Consider port shape and alignment }; // ShapeIntersectionAnchor - connects to node shape boundary var shapeAnchor = new ShapeIntersectionAnchor(node); // DynamicAnchor - chooses closest position from multiple providers var dynamicAnchor = new DynamicAnchor(node, new IPositionProvider[] { new BoundsBasedPositionProvider(0.5, 0), // Top center new BoundsBasedPositionProvider(1, 0.5), // Right center new BoundsBasedPositionProvider(0.5, 1), // Bottom center new BoundsBasedPositionProvider(0, 0.5) // Left center }); // PositionAnchor - connects to a fixed position var positionAnchor = new PositionAnchor(new Point(150, 200)); // LinkAnchor - connects to another link (link-to-link) var existingLink = BlazorDiagram.Links.First(); var linkAnchor = new LinkAnchor(existingLink, distance: 0.5); // Create link with custom anchors var customLink = new LinkModel(shapeAnchor, dynamicAnchor); BlazorDiagram.Links.Add(customLink); ``` ## Group Management ### Creating and Managing Node Groups Groups allow organizing multiple nodes together. When a group is moved, all its children move with it. Groups can be nested and have their own ports. ```csharp // Create nodes to group var node1 = BlazorDiagram.Nodes.Add(new NodeModel(new Point(50, 50))); var node2 = BlazorDiagram.Nodes.Add(new NodeModel(new Point(150, 50))); var node3 = BlazorDiagram.Nodes.Add(new NodeModel(new Point(100, 150))); // Create a group from selected nodes var group = BlazorDiagram.Groups.Group(node1, node2, node3); // Create a group with custom padding var customGroup = new GroupModel(new[] { node1, node2 }, padding: 40, autoSize: true); BlazorDiagram.Groups.Add(customGroup); // Add a child to an existing group group.AddChild(newNode); // Remove a child from a group group.RemoveChild(node1); // Access group children foreach (var child in group.Children) { Console.WriteLine($"Child node: {child.Id}"); } // Add ports to a group var groupPort = group.AddPort(PortAlignment.Right); // Ungroup - removes the group but keeps children group.Ungroup(); BlazorDiagram.Groups.Remove(group); // Delete group AND its children BlazorDiagram.Groups.Delete(group); // Keyboard shortcut: Ctrl+Shift+G toggles grouping/ungrouping ``` ## Routers and Path Generators ### Configuring Link Routing and Path Generation Routers determine the path a link takes between source and target. Path generators create the SVG path from the route points. ```csharp using Blazor.Diagrams.Core.Routers; using Blazor.Diagrams.Core.PathGenerators; // Configure default router and path generator in options var options = new BlazorDiagramOptions { Links = { DefaultRouter = new NormalRouter(), DefaultPathGenerator = new SmoothPathGenerator() } }; // NormalRouter - follows vertices in a straight line var normalRouter = new NormalRouter(); // OrthogonalRouter - creates right-angle paths avoiding nodes var orthogonalRouter = new OrthogonalRouter( shapeMargin: 10, // Margin around shapes globalMargin: 50, // Global pathfinding margin fallbackRouter: new NormalRouter() // Fallback if path not found ); // StraightPathGenerator - straight lines with optional rounded corners var straightPath = new StraightPathGenerator(radius: 10); // 0 = sharp corners // SmoothPathGenerator - bezier curves var smoothPath = new SmoothPathGenerator(margin: 125); // Curve control point margin // Set router/path generator per link var link = new LinkModel(node1, node2); link.Router = orthogonalRouter; link.PathGenerator = straightPath; BlazorDiagram.Links.Add(link); // Or set globally for all new links BlazorDiagram.Options.Links.DefaultRouter = orthogonalRouter; BlazorDiagram.Options.Links.DefaultPathGenerator = smoothPath; ``` ## Controls ### Adding Interactive Controls to Models Controls are interactive elements that appear on nodes or links, such as remove buttons or drag handles. ```csharp using Blazor.Diagrams.Core.Controls; using Blazor.Diagrams.Core.Controls.Default; using Blazor.Diagrams.Core.Positions; // Add controls container for a model var controls = BlazorDiagram.Controls.AddFor(node, ControlsType.OnSelection); // Add a remove control (X button) controls.Add(new RemoveControl(1, 0, 10, -10)); // x, y (0-1), offsetX, offsetY // Add remove control with custom position provider var removeControl = new RemoveControl( new BoundsBasedPositionProvider(1, 0, 10, -10) // Top-right corner with offset ); controls.Add(removeControl); // Add boundary control (shows selection rectangle) controls.Add(new BoundaryControl()); // Add drag-new-link control var dragLinkControl = new DragNewLinkControl(0.5, 1, 0, 10); // Bottom center controls.Add(dragLinkControl); // Add arrow head control for links (to change source/target) var linkControls = BlazorDiagram.Controls.AddFor(link); linkControls.Add(new ArrowHeadControl(isSource: true)); linkControls.Add(new ArrowHeadControl(isSource: false)); // Check if controls are visible if (BlazorDiagram.Controls.AreVisibleFor(node)) { Console.WriteLine("Controls are visible"); } // Get controls container for a model var existingControls = BlazorDiagram.Controls.GetFor(node); // Remove controls for a model BlazorDiagram.Controls.RemoveFor(node); // ControlsType options: // - OnSelection: Show when model is selected // - Always: Always visible // - OnHover: Show on mouse hover ``` ## Diagram Events ### Handling Diagram Events The diagram provides various events for responding to user interactions and model changes. ```csharp // Pointer events (work with mouse and touch) BlazorDiagram.PointerDown += (model, args) => { if (model is NodeModel node) Console.WriteLine($"Pointer down on node: {node.Id}"); }; BlazorDiagram.PointerMove += (model, args) => { var point = BlazorDiagram.GetRelativeMousePoint(args.ClientX, args.ClientY); Console.WriteLine($"Mouse at: {point}"); }; BlazorDiagram.PointerUp += (model, args) => Console.WriteLine("Pointer up"); BlazorDiagram.PointerClick += (model, args) => Console.WriteLine($"Clicked: {model?.GetType().Name ?? "Canvas"}"); BlazorDiagram.PointerDoubleClick += (model, args) => Console.WriteLine("Double clicked"); BlazorDiagram.PointerEnter += (model, args) => Console.WriteLine($"Entered: {model?.Id}"); BlazorDiagram.PointerLeave += (model, args) => Console.WriteLine($"Left: {model?.Id}"); // Keyboard events BlazorDiagram.KeyDown += (args) => Console.WriteLine($"Key pressed: {args.Key}"); // Wheel events (zoom) BlazorDiagram.Wheel += (args) => Console.WriteLine($"Wheel delta: {args.DeltaY}"); // Selection changes BlazorDiagram.SelectionChanged += (model) => Console.WriteLine($"Selection changed: {model.Id}, Selected: {model.Selected}"); // Pan and zoom changes BlazorDiagram.PanChanged += () => Console.WriteLine($"Pan: {BlazorDiagram.Pan}"); BlazorDiagram.ZoomChanged += () => Console.WriteLine($"Zoom: {BlazorDiagram.Zoom}"); // Container changes BlazorDiagram.ContainerChanged += () => Console.WriteLine($"Container: {BlazorDiagram.Container}"); // General diagram changes (triggers re-render) BlazorDiagram.Changed += () => Console.WriteLine("Diagram changed"); // Layer events BlazorDiagram.Nodes.Added += (node) => Console.WriteLine($"Node added: {node.Id}"); BlazorDiagram.Nodes.Removed += (node) => Console.WriteLine($"Node removed: {node.Id}"); BlazorDiagram.Links.Added += (link) => Console.WriteLine($"Link added: {link.Id}"); BlazorDiagram.Links.Removed += (link) => Console.WriteLine($"Link removed: {link.Id}"); ``` ## Selection and Navigation ### Managing Selection and Viewport Control diagram selection, panning, zooming, and viewport operations programmatically. ```csharp // Selection BlazorDiagram.SelectModel(node, unselectOthers: true); BlazorDiagram.UnselectModel(node); BlazorDiagram.UnselectAll(); // Get all selected models foreach (var model in BlazorDiagram.GetSelectedModels()) { Console.WriteLine($"Selected: {model.Id}"); } // Panning BlazorDiagram.SetPan(100, 50); // Set absolute pan position BlazorDiagram.UpdatePan(10, 10); // Relative pan adjustment // Zooming BlazorDiagram.SetZoom(1.5); // Set zoom level (1.0 = 100%) // Zoom to fit all nodes (or selected nodes if any are selected) BlazorDiagram.ZoomToFit(margin: 20); // Coordinate conversions var diagramPoint = BlazorDiagram.GetRelativeMousePoint(clientX, clientY); var screenPoint = BlazorDiagram.GetScreenPoint(diagramX, diagramY); var relativePoint = BlazorDiagram.GetRelativePoint(clientX, clientY); // Ordering (z-index) BlazorDiagram.SendToFront(node); BlazorDiagram.SendToBack(node); // Access ordered selectables foreach (var selectable in BlazorDiagram.OrderedSelectables) { Console.WriteLine($"Order: {selectable.Order}"); } // Batch operations (prevents multiple re-renders) BlazorDiagram.Batch(() => { BlazorDiagram.Nodes.Add(new NodeModel(new Point(0, 0))); BlazorDiagram.Nodes.Add(new NodeModel(new Point(100, 0))); BlazorDiagram.Nodes.Add(new NodeModel(new Point(200, 0))); }); // Suspend/resume refresh manually BlazorDiagram.SuspendRefresh = true; // ... make multiple changes ... BlazorDiagram.SuspendRefresh = false; BlazorDiagram.Refresh(); ``` ## Custom Components ### Registering Custom Node and Link Components Register custom Blazor components to render your own node and link designs. ```csharp // Create a custom node model public class CustomNode : NodeModel { public CustomNode(Point position) : base(position) { } public string Title { get; set; } = "Custom Node"; public string Description { get; set; } = ""; public string Color { get; set; } = "#3498db"; } // Create a custom node widget (Razor component) // CustomNodeWidget.razor @code { [Parameter] public CustomNode Node { get; set; } = null!; } <div class="custom-node @(Node.Selected ? "selected" : "")" style="background-color: @Node.Color"> <h4>@Node.Title</h4> <p>@Node.Description</p> </div> // Register the custom component BlazorDiagram.RegisterComponent<CustomNode, CustomNodeWidget>(); // Register with replacement (if already registered) BlazorDiagram.RegisterComponent<CustomNode, NewCustomNodeWidget>(replace: true); // Get component type for a model var componentType = BlazorDiagram.GetComponent<CustomNode>(); var componentType2 = BlazorDiagram.GetComponent(typeof(CustomNode)); var componentType3 = BlazorDiagram.GetComponent(node); // From instance // Usage var customNode = new CustomNode(new Point(100, 100)) { Title = "My Custom Node", Description = "This is a custom node", Color = "#e74c3c" }; BlazorDiagram.Nodes.Add(customNode); ``` ## Keyboard Shortcuts ### Configuring Keyboard Shortcuts The library provides a keyboard shortcuts system that can be customized or extended. ```csharp using Blazor.Diagrams.Core.Behaviors; // Get the keyboard shortcuts behavior var shortcuts = BlazorDiagram.GetBehavior<KeyboardShortcutsBehavior>(); // Default shortcuts: // - Delete: Delete selected models // - Ctrl+Shift+G: Group/Ungroup selected nodes // Add a custom shortcut shortcuts?.SetShortcut("s", ctrl: true, shift: false, alt: false, async (diagram) => { // Custom save action Console.WriteLine("Saving diagram..."); await SaveDiagram(diagram); }); // Add shortcut with modifiers shortcuts?.SetShortcut("z", ctrl: true, shift: false, alt: false, async (diagram) => { // Undo action Console.WriteLine("Undo"); }); // Remove a shortcut shortcuts?.RemoveShortcut("Delete", ctrl: false, shift: false, alt: false); // Use built-in default actions shortcuts?.SetShortcut("Backspace", false, false, false, KeyboardShortcutsDefaults.DeleteSelection); ``` ## Behaviors ### Managing and Customizing Diagram Behaviors Behaviors handle user interactions. You can register, unregister, or replace them with custom implementations. ```csharp using Blazor.Diagrams.Core.Behaviors; // Create diagram without default behaviors var diagram = new BlazorDiagram(options, registerDefaultBehaviors: false); // Register behaviors manually (control order) diagram.RegisterBehavior(new SelectionBehavior(diagram)); diagram.RegisterBehavior(new DragMovablesBehavior(diagram)); diagram.RegisterBehavior(new DragNewLinkBehavior(diagram)); diagram.RegisterBehavior(new PanBehavior(diagram)); diagram.RegisterBehavior(new ZoomBehavior(diagram)); diagram.RegisterBehavior(new KeyboardShortcutsBehavior(diagram)); // Get a specific behavior var zoomBehavior = diagram.GetBehavior<ZoomBehavior>(); var panBehavior = diagram.GetBehavior<PanBehavior>(); // Unregister a behavior diagram.UnregisterBehavior<ZoomBehavior>(); // Create a custom behavior public class CustomBehavior : Behavior { public CustomBehavior(Diagram diagram) : base(diagram) { Diagram.PointerDown += OnPointerDown; } private void OnPointerDown(Model? model, PointerEventArgs args) { // Custom logic } public override void Dispose() { Diagram.PointerDown -= OnPointerDown; } } // Register custom behavior diagram.RegisterBehavior(new CustomBehavior(diagram)); ``` ## Constraints ### Configuring Diagram Constraints Constraints control what actions users can perform, such as deleting nodes or links. ```csharp var options = new BlazorDiagramOptions { Constraints = { // Control node deletion ShouldDeleteNode = async (node) => { // Prevent deletion of locked or special nodes if (node.Locked) return false; if (node is SpecialNode) return false; return true; }, // Control link deletion ShouldDeleteLink = async (link) => { // Always allow link deletion return true; }, // Control group deletion ShouldDeleteGroup = async (group) => { // Confirm before deleting groups with many children if (group.Children.Count > 5) { // Could show confirmation dialog return await ConfirmDeletion(); } return true; } } }; ``` ## Widgets ### Using Built-in Diagram Widgets The library provides built-in widgets for common diagram features. ```razor @using Blazor.Diagrams.Components @using Blazor.Diagrams.Components.Widgets <div style="width: 100%; height: 600px;"> <CascadingValue Value="BlazorDiagram"> <DiagramCanvas> <Widgets> <!-- Navigator/Overview widget --> <NavigatorWidget Width="200" Height="150" Style="position: absolute; bottom: 10px; right: 10px;" FillColor="#f0f0f0" /> <!-- Selection box widget (drag to select multiple) --> <SelectionBoxWidget /> <!-- Grid background widget --> <GridWidget Size="20" Mode="GridMode.Line" BackgroundColor="#ffffff" GridColor="#e0e0e0" /> </Widgets> <!-- Additional custom SVG content --> <AdditionalSvg> <text x="10" y="20" fill="#999">My Diagram</text> </AdditionalSvg> <!-- Additional custom HTML content --> <AdditionalHtml> <div style="position: absolute; top: 10px; left: 10px;"> <button @onclick="ResetView">Reset View</button> </div> </AdditionalHtml> </DiagramCanvas> </CascadingValue> </div> @code { private void ResetView() { BlazorDiagram.SetPan(0, 0); BlazorDiagram.SetZoom(1); } } ``` ## Link Factory ### Customizing Link Creation Configure how links are created when users drag from ports or nodes. ```csharp var options = new BlazorDiagramOptions { Links = { // Custom link factory Factory = (diagram, source, targetAnchor) => { Anchor sourceAnchor = source switch { NodeModel node => new ShapeIntersectionAnchor(node), PortModel port => new SinglePortAnchor(port), _ => throw new NotImplementedException() }; var link = new LinkModel(sourceAnchor, targetAnchor) { Color = "#3498db", Width = 2, TargetMarker = LinkMarker.Arrow }; return link; }, // Custom target anchor factory TargetAnchorFactory = (diagram, link, model) => { return model switch { NodeModel node => new ShapeIntersectionAnchor(node), PortModel port => new SinglePortAnchor(port) { MiddleIfNoMarker = true }, _ => throw new ArgumentOutOfRangeException() }; } } }; ``` ## SVG Nodes ### Creating SVG-Based Nodes For nodes that need to render in the SVG layer (for better link connections), use `SvgNodeModel`. ```csharp using Blazor.Diagrams.Models; // Create an SVG node (renders in SVG layer instead of HTML) public class MySvgNode : SvgNodeModel { public MySvgNode(Point position) : base(position) { } public string Shape { get; set; } = "circle"; public string Fill { get; set; } = "#3498db"; } // Register SVG node component BlazorDiagram.RegisterComponent<MySvgNode, MySvgNodeWidget>(); // MySvgNodeWidget.razor - must render SVG elements @code { [Parameter] public MySvgNode Node { get; set; } = null!; } @if (Node.Shape == "circle") { <circle cx="@(Node.Size?.Width / 2)" cy="@(Node.Size?.Height / 2)" r="25" fill="@Node.Fill" /> } else { <rect width="50" height="50" fill="@Node.Fill" /> } ``` ## Summary Blazor Diagrams provides a comprehensive solution for building interactive diagram applications in Blazor. The primary use cases include workflow designers, database schema editors, flowcharts, mind maps, network topology visualizations, and any application requiring node-based visual editing. The library's separation of models and components makes it straightforward to create custom visualizations while maintaining consistent behavior. Integration typically follows a pattern of creating a `BlazorDiagram` instance with configured options, registering custom components for custom model types, adding the `DiagramCanvas` component to your page with a cascading value, and responding to events to implement application-specific logic. The layered architecture (Nodes, Links, Groups, Controls) provides clear organization, while behaviors and constraints offer fine-grained control over user interactions. For complex applications, the batch operation support and refresh suspension capabilities help maintain performance when making multiple changes.