Skip to content

BlockSuite API Documentation / @blocksuite/affine-gfx-mindmap

@blocksuite/affine-gfx-mindmap ​

Classes ​

Extension ​

MindMapDragExtension ​

Understanding Extensions ​

Extensions provide a way to extend the functionality of a system using dependency injection. They allow you to register services, implementations, and factories in the DI container, which can then be retrieved and used by different parts of the application.

Extensions are particularly useful for:

  • Registering different implementations for different types
  • Creating pluggable architecture where components can be added or removed
  • Managing dependencies between different parts of the application

Usage Example: Fruit Processing System ​

Let's consider a fruit processing system where different types of fruits need different processing methods. We'll show how to implement this using extensions.

Step 1: Define the interfaces ​

ts
interface FruitProcessor {
  process(fruit: Fruit): void;
}

interface Fruit {
  type: string;
  // other properties
}

Step 2: Create a service identifier ​

ts
import { createIdentifier } from '@blocksuite/global/di';

const FruitProcessorProvider = createIdentifier<FruitProcessor>('fruit-processor-provider');

Step 3: Create implementations ​

ts
class AppleProcessor implements FruitProcessor {
  process(fruit: Fruit): void {
    console.log('Slicing apple');
    // Apple-specific processing
  }
}

class BananaProcessor implements FruitProcessor {
  process(fruit: Fruit): void {
    console.log('Peeling banana');
    // Banana-specific processing
  }
}

Step 4: Create an extension factory ​

ts
const FruitProcessorExtension = (
  fruitType: string,
  implementation: new () => FruitProcessor
): ExtensionType => {
  return {
    setup: di => {
      di.addImpl(FruitProcessorProvider(fruitType), implementation);
    }
  };
};

Step 5: Create concrete extensions ​

ts
export const AppleProcessorExtension = FruitProcessorExtension('apple', AppleProcessor);
export const BananaProcessorExtension = FruitProcessorExtension('banana', BananaProcessor);

Step 6: Use the extensions ​

ts
import { Container } from '@blocksuite/global/di';

class FruitProcessingSystem {
  provider: ServiceProvider;

  constructor(extensions: ExtensionType[]) {
    const container = new Container();

    // Set up all extensions
    extensions.forEach(ext => ext.setup(container));

    // Create a provider from the container
    this.provider = container.provider();
  }

  processFruit(fruit: Fruit) {
    // Get the appropriate processor based on fruit type
    const processor = this.provider.get(FruitProcessorProvider(fruit.type));

    // Process the fruit
    processor.process(fruit);
  }
}

// Initialize the system with extensions
const system = new FruitProcessingSystem([
  AppleProcessorExtension,
  BananaProcessorExtension
]);

// Use the system
system.processFruit({ type: 'apple' });  // Output: Slicing apple
system.processFruit({ type: 'banana' }); // Output: Peeling banana

Note: We deliberately used a non-block specific example here. In BlockSuite, the extension pattern can be applied to any entity that can be configured by third parties, not just blocks. This includes different tools in the whiteboard, different column types in database blocks, and many other extensible components. The pattern remains the same regardless of what you're extending.

Extends ​
Constructors ​
Properties ​
key ​

static key: string = 'mind-map-drag'

Overrides ​

InteractivityExtension.key

Accessors ​
Methods ​
mounted() ​

mounted(): void

Returns ​

void

Overrides ​

InteractivityExtension.mounted

Other ​

MindMapIndicatorOverlay ​

An overlay is a layer covered on top of elements, can be used for rendering non-CRDT state indicators.

Extends ​
Constructors ​
Properties ​
currentDragPos ​

currentDragPos: IVec | null = null

direction ​

direction: LEFT | RIGHT = LayoutType.RIGHT

dragNodeImage ​

dragNodeImage: HTMLCanvasElement | null = null

dragNodePos ​

dragNodePos: IVec

mode ​

mode: ConnectorMode = ConnectorMode.Straight

parentBound ​

parentBound: Bound | null = null

pathGen ​

pathGen: PathGenerator

targetBound ​

targetBound: Bound | null = null

INDICATOR_SIZE ​

static INDICATOR_SIZE: number[]

overlayName ​

static overlayName: string = 'mindmap-indicator'

Overrides ​

Overlay.overlayName

Accessors ​
themeService ​
Get Signature ​

get themeService(): ThemeService

Returns ​

ThemeService

Methods ​
clear() ​

clear(): void

Returns ​

void

Overrides ​

Overlay.clear

render() ​

render(ctx): void

Parameters ​
ctx ​

CanvasRenderingContext2D

Returns ​

void

Overrides ​

Overlay.render

setIndicatorInfo() ​

setIndicatorInfo(options): void

Parameters ​
options ​
insertPosition ​

{ layoutDir: LEFT | RIGHT; position: "next" | "prev"; type: "sibling"; } | { layoutDir: LEFT | RIGHT; type: "child"; }

parent ​

MindmapNode

parentChildren ​

MindmapNode[]

path ​

number[]

target ​

MindmapNode

targetMindMap ​

MindmapElementModel

Returns ​

void


MindMapView ​

The methods that a graphic element should implement. It is already included in the GfxCompatibleInterface interface.

Extends ​
Constructors ​
Properties ​
type ​

static type: string = 'mindmap'

Overrides ​

GfxElementModelView.type

Accessors ​
Methods ​
getCollapseButton() ​

getCollapseButton(node): LocalShapeElementModel | undefined

Parameters ​
node ​

string | MindmapNode

The mindmap node or its id to get the collapse button

Returns ​

LocalShapeElementModel | undefined

onBoxSelected() ​

onBoxSelected(context): boolean

When the element is selected by box selection, return false to prevent the default selection behavior.

Parameters ​
context ​

BoxSelectionContext

Returns ​

boolean

Overrides ​

GfxElementModelView.onBoxSelected

onCreated() ​

onCreated(): void

Returns ​

void

Overrides ​

GfxElementModelView.onCreated

onDestroyed() ​

onDestroyed(): void

Called when the view is destroyed. Override this method requires calling super.onDestroyed().

Returns ​

void

Overrides ​

GfxElementModelView.onDestroyed

Variables ​

mindmap ​

const mindmap: ElementRenderer<MindmapElementModel>


MindmapDomRendererExtension ​

const MindmapDomRendererExtension: ExtensionType


MindmapElementRendererExtension ​

const MindmapElementRendererExtension: ExtensionType & object

Type Declaration ​

identifier ​

identifier: ServiceIdentifier<ElementRenderer<MindmapElementModel>>


MindMapInteraction ​

const MindMapInteraction: ExtensionType


mindMapSeniorTool ​

const mindMapSeniorTool: ExtensionType


MindmapStyleFour ​

const MindmapStyleFour: TemplateResult<1>


MindmapStyleOne ​

const MindmapStyleOne: TemplateResult<1>


MindmapStyleThree ​

const MindmapStyleThree: TemplateResult<1>


MindmapStyleTwo ​

const MindmapStyleTwo: TemplateResult<1>


mindmapToMarkdownAdapterMatcher ​

const mindmapToMarkdownAdapterMatcher: ExtensionType & object

Type Declaration ​

identifier ​

identifier: ServiceIdentifier<ElementToMarkdownAdapterMatcher>


mindmapToolbarConfig ​

const mindmapToolbarConfig: object

Type Declaration ​

actions ​

readonly actions: [{ id: "a.style"; content: TemplateResult<1> | null; }, { id: "b.layout"; content: TemplateResult<1> | null; }]

when ​

readonly when: (ctx) => boolean

Parameters ​
ctx ​

ToolbarContext

Returns ​

boolean


mindmapToolbarExtension ​

const mindmapToolbarExtension: ExtensionType


mindmapToPlainTextAdapterMatcher ​

const mindmapToPlainTextAdapterMatcher: ExtensionType & object

Type Declaration ​

identifier ​

identifier: ServiceIdentifier<ElementToPlainTextAdapterMatcher>


NODE_FIRST_LEVEL_HORIZONTAL_SPACING ​

const NODE_FIRST_LEVEL_HORIZONTAL_SPACING: 200 = 200


NODE_HORIZONTAL_SPACING ​

const NODE_HORIZONTAL_SPACING: 110 = 110


NODE_VERTICAL_SPACING ​

const NODE_VERTICAL_SPACING: 45 = 45


shapeMindmapToolbarConfig ​

const shapeMindmapToolbarConfig: object

Type Declaration ​

actions ​

readonly actions: [{ id: "a.mindmap-style"; content: TemplateResult<1> | null; when: boolean; }, { id: "b.mindmap-layout"; content: TemplateResult<1> | null; when: boolean; }]

when ​

readonly when: (ctx) => boolean

Parameters ​
ctx ​

ToolbarContext

Returns ​

boolean


shapeMindmapToolbarExtension ​

const shapeMindmapToolbarExtension: ExtensionType

Functions ​

addNode() ​

addNode(mindmap, parent, node, targetIndex?): void

Parameters ​

mindmap ​

MindmapElementModel

the mind map to add the node to

parent ​

string | MindmapNode

the parent node or the parent node id

node ​

MindmapNode

the node must be an detached node

targetIndex? ​

number

the index to insert the node at

Returns ​

void


addTree() ​

addTree(mindmap, parent, tree, sibling?): MindmapNode | null | undefined

Parameters ​

mindmap ​

MindmapElementModel

parent ​

string | MindmapNode

tree ​

MindmapNode | Node

sibling? ​

string | number

sibling indicates where to insert a subtree among peer elements. If it's a string, it represents a peer element's ID; if it's a number, it represents its index. The subtree will be inserted before the sibling element.

Returns ​

MindmapNode | null | undefined


applyStyle() ​

applyStyle(mindmap, shouldFitContent?): void

Parameters ​

mindmap ​

MindmapElementModel

shouldFitContent? ​

boolean = false

Returns ​

void


containsNode() ​

containsNode(mindmap, targetNode, searchParent?): boolean

Check if the mind map contains the target node.

Parameters ​

mindmap ​

MindmapElementModel

Mind map to check

targetNode ​

MindmapNode

Node to check

searchParent? ​

MindmapNode

If provided, check if the node is a descendant of the parent node. Otherwise, check the whole mind map.

Returns ​

boolean


createFromTree() ​

createFromTree(tree, style, layoutType, surface): MindmapElementModel

Parameters ​

tree ​

MindmapNode

style ​

MindmapStyle

layoutType ​

LayoutType

surface ​

SurfaceBlockModel

Returns ​

MindmapElementModel


createMindmapLayoutActionMenu() ​

createMindmapLayoutActionMenu(ctx, models): TemplateResult<1>

Parameters ​

ctx ​

ToolbarContext

models ​

MindmapElementModel[]

Returns ​

TemplateResult<1>


createMindmapStyleActionMenu() ​

createMindmapStyleActionMenu(ctx, models): TemplateResult<1>

Parameters ​

ctx ​

ToolbarContext

models ​

MindmapElementModel[]

Returns ​

TemplateResult<1>


detachMindmap() ​

detachMindmap(mindmap, subtree): MindmapNode | undefined

Detach a mindmap node or subtree. It is similar to removeChild but it does not delete the node.

So the node can be used to create a new mind map or merge into other mind map

Parameters ​

mindmap ​

MindmapElementModel

the mind map that the subtree belongs to

subtree ​

string | MindmapNode

the subtree to detach

Returns ​

MindmapNode | undefined


findTargetNode() ​

findTargetNode(mindmap, position): MindmapNode | null

Parameters ​

mindmap ​

MindmapElementModel

position ​

IVec

Returns ​

MindmapNode | null


getHoveredArea() ​

getHoveredArea(target, position, layoutDir): "top-left" | "top-right" | "bottom-left" | "bottom-right"

Parameters ​

target ​

ShapeElementModel

position ​

[number, number]

layoutDir ​

LayoutType

Returns ​

"top-left" | "top-right" | "bottom-left" | "bottom-right"


getNearestTranslation() ​

getNearestTranslation(viewport, element, padding?): number[]

Parameters ​

viewport ​

Viewport

element ​

GfxModel

padding? ​

[number, number] = ...

Returns ​

number[]


handleLayout() ​

handleLayout(mindmap, tree?, shouldApplyStyle?, layoutType?): void

Parameters ​

mindmap ​

MindmapElementModel

tree? ​

MindmapNode | MindmapRoot

shouldApplyStyle? ​

boolean = true

layoutType? ​

LayoutType

Returns ​

void


hideNodeConnector() ​

hideNodeConnector(mindmap, target): (() => void) | undefined

Hide the connector between the target node and its parent

Parameters ​

mindmap ​

MindmapElementModel

target ​

MindmapNode

The mind map node which's connector will be hide

Returns ​

(() => void) | undefined


isElementOutsideViewport() ​

isElementOutsideViewport(viewport, element, padding?): boolean

Parameters ​

viewport ​

Viewport

element ​

GfxModel

padding? ​

[number, number] = ...

Returns ​

boolean


isMindmapNode() ​

isMindmapNode(element): boolean

Parameters ​

element ​

GfxModel | GfxBlockElementModel<GfxCompatibleProps> | null

Returns ​

boolean


isSingleMindMapNode() ​

isSingleMindMapNode(els): boolean

Parameters ​

els ​

GfxModel[]

Returns ​

boolean


layout() ​

layout(root, mindmap, layoutDir, path): void

Parameters ​

root ​

MindmapNode

mindmap ​

MindmapElementModel

layoutDir ​

LayoutType | null

path ​

number[]

Returns ​

void


moveNode() ​

moveNode(from, subtree, to, parent, index): void | MindmapNode

Move a subtree from one mind map to another

Parameters ​

from ​

MindmapElementModel

the mind map that the subtree belongs to

subtree ​

MindmapNode

the subtree to move

to ​

MindmapElementModel

the mind map to move the subtree to

parent ​

string | MindmapNode

the new parent node to attach the subtree to

index ​

number

the index to insert the subtree at

Returns ​

void | MindmapNode


tryMoveNode() ​

tryMoveNode(targetMindMap, target, sourceMindMap, source, position, callback): { abort: () => void; merge: () => void; } | null

Try to move a node to another mind map. It will show a merge indicator if the node can be merged to the target mind map.

Parameters ​

targetMindMap ​

MindmapElementModel

target ​

MindmapNode

sourceMindMap ​

MindmapElementModel

source ​

MindmapNode

position ​

IVec

callback ​

(option) => () => void

Returns ​

{ abort: () => void; merge: () => void; } | null

return two functions, abort and merge. abort will cancel the operation and merge will merge the node to the target mind map.