| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- import { PackageManagerTabs } from '@theme';
- # @flowgram.ai/free-stack-plugin
- A layer management plugin that provides z-index layer control functionality for nodes and connections in free layout canvas.
- ## Features
- - Intelligently calculates layer relationships between nodes and connections to avoid occlusion issues
- - Supports automatic top-level display for selected nodes
- - Supports highlighting of hovered nodes and connections
- - Customizable node sorting rules to control rendering order of nodes at the same level
- - Automatically handles parent-child node layer relationships
- - Supports intelligent layer management for connections, ensuring connection visibility
- - Real-time response to node selection, hover, and entity change events
- ## Quick Start
- 1. Installation
- <PackageManagerTabs command="install @flowgram.ai/free-stack-plugin" />
- 2. Register Plugin
- The plugin registration method is basically the same as other flowgram plugins. Just make sure not to create duplicates and finally pass it to the corresponding FreeLayoutEditorProvider.
- ```tsx
- import { createFreeStackPlugin } from '@flowgram.ai/free-stack-plugin';
- const editorProps = useMemo(() => ({
- plugins: () => [
- createFreeStackPlugin()
- ]
- }), []);
- return (
- <FreeLayoutEditorProvider {...editorProps}>
- <EditorRenderer />
- </FreeLayoutEditorProvider>
- )
- ```
- 3. Custom Node Sorting
- You can customize the sorting rules for nodes at the same level through the `sortNodes` function:
- ```tsx
- import { createFreeStackPlugin } from '@flowgram.ai/free-stack-plugin';
- import { WorkflowNodeType } from './nodes/constants';
- const editorProps = useMemo(() => ({
- plugins: () => [
- createFreeStackPlugin({
- sortNodes: (nodes) => {
- const commentNodes = [];
- const otherNodes = [];
- // Separate comment nodes from other nodes
- nodes.forEach((node) => {
- if (node.flowNodeType === WorkflowNodeType.Comment) {
- commentNodes.push(node);
- } else {
- otherNodes.push(node);
- }
- });
- // Comment nodes render at the bottom layer, other nodes at the top layer
- return [...commentNodes, ...otherNodes];
- },
- })
- ]
- }), []);
- ```
- ## Configuration Options
- ### FreeStackPluginOptions
- Plugin configuration options:
- ```typescript
- interface FreeStackPluginOptions {
- /** Custom node sorting function */
- sortNodes?: (nodes: WorkflowNodeEntity[]) => WorkflowNodeEntity[];
- }
- ```
- ### sortNodes Function
- Used to customize sorting rules for nodes at the same level:
- ```typescript
- type SortNodesFunction = (nodes: WorkflowNodeEntity[]) => WorkflowNodeEntity[];
- ```
- **Parameter Description:**
- - `nodes`: Array of nodes to be sorted
- - **Return Value**: Array of sorted nodes
- **Use Cases:**
- - Place specific types of nodes (like comments) at the bottom layer
- - Sort nodes by business priority
- - Sort by creation time or other attributes
- ## Layer Management Algorithm
- ### Basic Layer Calculation
- The plugin uses an intelligent algorithm to calculate the layer for each node and connection:
- 1. **Base Layer**: Starts calculation from `BASE_Z_INDEX` (default is 8)
- 2. **Node Layer**: Calculated based on node nesting relationships and sorting rules
- 3. **Connection Layer**: Ensures connections are not occluded by nodes while handling special cases
- ### Layer Elevation Rules
- The following situations will trigger layer elevation:
- - **Selected Nodes**: Selected nodes will be elevated to the top layer
- - **Hovered Elements**: Hovered nodes or connections will be highlighted
- - **Drawing Connections**: Connections being drawn will be placed at the top layer
- - **Parent-Child Relationship Connections**: Connections between parent-child nodes will be prioritized for display
- ### Layer Calculation Process
- 1. **Initialization**: Clear cache, calculate basic parameters
- 2. **Node Indexing**: Establish node index mapping
- 3. **Selected Node Processing**: Mark parent relationships of selected nodes
- 4. **Layer Assignment**: Recursively process node layers
- 5. **Connection Processing**: Calculate connection layers, ensure visibility
- 6. **Style Application**: Apply calculation results to DOM elements
- ## Advanced Usage
- ### Complex Sorting Rules
- You can implement complex node sorting logic:
- ```typescript
- const sortNodes = (nodes: WorkflowNodeEntity[]) => {
- return nodes.sort((a, b) => {
- // 1. Sort by node type priority
- const typeOrder = {
- [WorkflowNodeType.Comment]: 0,
- [WorkflowNodeType.Start]: 1,
- [WorkflowNodeType.End]: 2,
- // ... other types
- };
- const aOrder = typeOrder[a.flowNodeType] ?? 999;
- const bOrder = typeOrder[b.flowNodeType] ?? 999;
- if (aOrder !== bOrder) {
- return aOrder - bOrder;
- }
- // 2. Sort by creation time
- return a.createTime - b.createTime;
- });
- };
- ```
- ## FAQ
- ### Q: How to keep specific types of nodes always at the bottom layer?
- A: Place these nodes at the front of the array through the `sortNodes` function:
- ```typescript
- const sortNodes = (nodes) => {
- const backgroundNodes = nodes.filter(node =>
- node.flowNodeType === WorkflowNodeType.Comment
- );
- const foregroundNodes = nodes.filter(node =>
- node.flowNodeType !== WorkflowNodeType.Comment
- );
- return [...backgroundNodes, ...foregroundNodes];
- };
- ```
- ### Q: How to disable automatic layer management?
- A: Currently, the plugin does not provide a disable option. If you need complete custom layer management, it is recommended not to use this plugin and directly set z-index in node components.
- ### Q: Performance optimization suggestions?
- A: The plugin already has built-in performance optimizations:
- - Uses debounce mechanism to reduce calculation frequency
- - Only recalculates layers when necessary
- - Uses Map data structure to improve lookup efficiency
- For large canvases (over 1000 nodes), it is recommended to:
- - Simplify the logic of the `sortNodes` function
- - Avoid complex calculations in sorting functions
|