@@ -58,12 +58,16 @@ minimap, and more.
5858 - [ Connection Labels] ( #connection-labels )
5959- [ Annotations] ( #annotations )
6060 - [ Built-in Annotation Types] ( #built-in-annotation-types )
61+ - [ Group Annotations] ( #group-annotations )
6162 - [ Custom Annotations] ( #custom-annotations )
6263 - [ Following Nodes] ( #following-nodes )
64+ - [ Visibility] ( #visibility )
65+ - [ Node Visibility] ( #node-visibility )
66+ - [ Annotation Visibility] ( #annotation-visibility )
6367- [ Interactive Features] ( #interactive-features )
6468 - [ Event System] ( #event-system )
6569 - [ Keyboard Shortcuts] ( #keyboard-shortcuts )
66- - [ Feature Toggles ] ( #feature-toggles )
70+ - [ Behavior Modes ] ( #behavior-modes )
6771- [ Minimap] ( #minimap )
6872- [ Read-Only Viewer] ( #read-only-viewer )
6973- [ Serialization] ( #serialization )
@@ -303,6 +307,8 @@ NodeFlowTheme
303307├── gridTheme → Grid background appearance
304308├── selectionTheme → Selection rectangle styling
305309├── cursorTheme → Mouse cursor styles
310+ ├── minimapTheme → Minimap overlay appearance
311+ ├── resizerTheme → Resize handle appearance
306312├── backgroundColor → Canvas background color
307313└── connectionAnimationDuration → Animation timing
308314```
@@ -586,6 +592,103 @@ CursorTheme(
586592
587593</details >
588594
595+ <details >
596+ <summary ><strong >MinimapTheme - Minimap Overlay</strong ></summary >
597+
598+ Controls the appearance and position of the minimap navigation widget.
599+
600+ ``` dart
601+ MinimapTheme(
602+ // Position and size
603+ position: MinimapPosition.bottomRight, // Corner placement
604+ margin: 20.0, // Distance from edge
605+ size: Size(200, 150), // Minimap dimensions
606+
607+ // Colors
608+ backgroundColor: Color(0xFFF5F5F5), // Container background
609+ nodeColor: Color(0xFF1976D2), // Node representation color
610+ viewportColor: Color(0xFF1976D2), // Viewport indicator color
611+ borderColor: Color(0xFFBDBDBD), // Container border color
612+
613+ // Viewport indicator
614+ showViewport: true, // Show visible area indicator
615+ viewportFillOpacity: 0.1, // Viewport fill transparency
616+ viewportBorderOpacity: 0.4, // Viewport border transparency
617+
618+ // Styling
619+ borderWidth: 1.0, // Container border width
620+ borderRadius: 4.0, // Container corner radius
621+ nodeBorderRadius: 2.0, // Node rectangle corner radius
622+ padding: EdgeInsets.all(4.0), // Internal padding
623+ )
624+ ```
625+
626+ ** Built-in presets:**
627+
628+ ``` dart
629+ // Light theme minimap (default)
630+ MinimapTheme.light
631+
632+ // Dark theme minimap
633+ MinimapTheme.dark
634+
635+ // Custom minimap matching your theme
636+ final customTheme = NodeFlowTheme.light.copyWith(
637+ minimapTheme: MinimapTheme.light.copyWith(
638+ position: MinimapPosition.topLeft,
639+ size: const Size(250, 180),
640+ nodeColor: Colors.purple,
641+ ),
642+ );
643+ ```
644+
645+ ** Position options:**
646+ - ` MinimapPosition.topLeft `
647+ - ` MinimapPosition.topRight `
648+ - ` MinimapPosition.bottomLeft `
649+ - ` MinimapPosition.bottomRight ` (default)
650+
651+ </details >
652+
653+ <details >
654+ <summary ><strong >ResizerTheme - Resize Handles</strong ></summary >
655+
656+ Controls the appearance of resize handles on resizable elements like group annotations.
657+
658+ ``` dart
659+ ResizerTheme(
660+ handleSize: 10.0, // Width and height of handles
661+ color: Colors.white, // Handle fill color
662+ borderColor: Colors.blue, // Handle border color
663+ borderWidth: 1.0, // Handle border thickness
664+ snapDistance: 4.0, // Extra hit area around handles
665+ )
666+ ```
667+
668+ ** Built-in presets:**
669+
670+ ``` dart
671+ // Light theme handles (white fill, blue border)
672+ ResizerTheme.light
673+
674+ // Dark theme handles (dark fill, light blue border)
675+ ResizerTheme.dark
676+
677+ // Custom resize handles
678+ final customTheme = NodeFlowTheme.light.copyWith(
679+ resizerTheme: ResizerTheme.light.copyWith(
680+ handleSize: 12.0,
681+ borderColor: Colors.purple,
682+ snapDistance: 6.0, // Larger hit area for touch devices
683+ ),
684+ );
685+ ```
686+
687+ > [ !TIP] Increase ` snapDistance ` for touch-friendly interfaces. This makes
688+ > handles easier to grab without changing their visual size.
689+
690+ </details >
691+
589692### Theming Cascade
590693
591694Properties are resolved using a cascade from most specific to most general:
@@ -2201,6 +2304,137 @@ controller.addAnnotation(annotation);
22012304
22022305</details >
22032306
2307+ ### Group Annotations
2308+
2309+ Group annotations allow you to visually organize related nodes together. Groups
2310+ can be resized, styled, and configured with different behavior modes that
2311+ control how nodes interact with the group.
2312+
2313+ <details >
2314+ <summary ><strong >Creating Group Annotations</strong ></summary >
2315+
2316+ ``` dart
2317+ // Create a group at a specific position and size
2318+ controller.createGroupAnnotation(
2319+ title: 'Input Processing',
2320+ position: const Offset(50, 50),
2321+ size: const Size(400, 300),
2322+ color: Colors.blue.withOpacity(0.2),
2323+ );
2324+
2325+ // Create a group around existing nodes
2326+ controller.createGroupAnnotationAroundNodes(
2327+ title: 'Data Pipeline',
2328+ nodeIds: {'node-1', 'node-2', 'node-3'},
2329+ padding: const EdgeInsets.all(30),
2330+ color: Colors.green.withOpacity(0.2),
2331+ );
2332+ ```
2333+
2334+ </details >
2335+
2336+ <details >
2337+ <summary ><strong >Group Behavior Modes</strong ></summary >
2338+
2339+ Groups support three behavior modes that control how nodes interact with the group:
2340+
2341+ | Mode | Membership | Size | Node Movement |
2342+ | ------| ------------| ------| ---------------|
2343+ | ` bounds ` | Spatial (nodes inside bounds) | Manual (resizable) | Nodes can escape by dragging out |
2344+ | ` explicit ` | Explicit (node ID set) | Auto-computed (fits members) | Group resizes to contain nodes |
2345+ | ` parent ` | Explicit (node ID set) | Manual (resizable) | Nodes move with group, can leave bounds |
2346+
2347+ ``` dart
2348+ // Bounds mode (default) - spatial containment
2349+ final boundsGroup = GroupAnnotation(
2350+ id: 'group-1',
2351+ title: 'Bounds Group',
2352+ position: const Offset(100, 100),
2353+ size: const Size(300, 200),
2354+ behavior: GroupBehavior.bounds, // Nodes inside move with group
2355+ );
2356+
2357+ // Explicit mode - auto-sizing group
2358+ final explicitGroup = GroupAnnotation(
2359+ id: 'group-2',
2360+ title: 'Explicit Group',
2361+ position: const Offset(100, 100),
2362+ size: const Size(300, 200),
2363+ behavior: GroupBehavior.explicit,
2364+ nodeIds: {'node-1', 'node-2'}, // Group auto-fits these nodes
2365+ );
2366+
2367+ // Parent mode - linked but flexible
2368+ final parentGroup = GroupAnnotation(
2369+ id: 'group-3',
2370+ title: 'Parent Group',
2371+ position: const Offset(100, 100),
2372+ size: const Size(300, 200),
2373+ behavior: GroupBehavior.parent,
2374+ nodeIds: {'node-1', 'node-2'}, // Nodes move with group but can leave bounds
2375+ );
2376+
2377+ controller.addAnnotation(boundsGroup);
2378+ ```
2379+
2380+ ** Command+Drag to Add/Remove Nodes** : Hold Command (Mac) or Ctrl (Windows/Linux)
2381+ while dragging a node to add it to or remove it from a group when using ` bounds `
2382+ behavior. The group will highlight when a node can be added.
2383+
2384+ </details >
2385+
2386+ ---
2387+
2388+ ## Visibility
2389+
2390+ Nodes and annotations support visibility toggling, allowing you to hide elements
2391+ without removing them from the graph. Hidden elements remain in the data model
2392+ and can be shown again at any time.
2393+
2394+ ### Node Visibility
2395+
2396+ ``` dart
2397+ // Hide a node
2398+ controller.getNode('node-1')?.isVisible = false;
2399+
2400+ // Show a node
2401+ controller.getNode('node-1')?.isVisible = true;
2402+
2403+ // Check visibility
2404+ if (controller.getNode('node-1')?.isVisible ?? false) {
2405+ print('Node is visible');
2406+ }
2407+
2408+ // Create a node that starts hidden
2409+ controller.addNode(Node<String>(
2410+ id: 'hidden-node',
2411+ type: 'process',
2412+ position: const Offset(100, 100),
2413+ data: 'Hidden by default',
2414+ visible: false, // Start hidden
2415+ ));
2416+ ```
2417+
2418+ > [ !NOTE] Hidden nodes are not rendered on the canvas and their ports cannot
2419+ > participate in new connections. Existing connections to hidden nodes remain
2420+ > in the graph data but are visually hidden.
2421+
2422+ ### Annotation Visibility
2423+
2424+ ``` dart
2425+ // Hide all annotations
2426+ controller.hideAllAnnotations();
2427+
2428+ // Show all annotations
2429+ controller.showAllAnnotations();
2430+
2431+ // Toggle individual annotation visibility
2432+ final annotation = controller.getAnnotation('group-1');
2433+ if (annotation != null) {
2434+ annotation.isVisible = !annotation.isVisible;
2435+ }
2436+ ```
2437+
22042438---
22052439
22062440## Interactive Features
0 commit comments