Skip to content
D
Documentation

DiagramModel

reference
7 min readUpdated

Import it from @grafloria/engine.

Also has every member of DiagramEntity, listed on its own entry.

ts
class DiagramModel extends DiagramEntity

Properties

NameTypeDefaultDescription
namestring'Untitled Diagram'
nodesMap<string, NodeModel>
linksMap<string, LinkModel>
groupsMap<string, GroupModel>
strokesMap<string, StrokeModel>Freehand ink strokes. See StrokeModel for why these are not nodes.
linkIntegrityOwner'model' | 'external''model'Who owns the invariant "a link whose node is gone is not a link"?
viewport

Methods

  • get comments(): CommentRegisterTree — The comment register tree. Read-only in spirit: write through writeCommentRegister. The landing pad for applyOp's whole-tree write (remote ops, replay, load).
  • set comments(next: CommentRegisterTree) — The comment register tree. Read-only in spirit: write through writeCommentRegister. The landing pad for applyOp's whole-tree write (remote ops, replay, load).
  • writeCommentRegister(path: string, value: unknown): boolean — Write ONE comment register — t1.status, t1.messages.m3 — and nothing else.
  • readCommentRegister(path: string): unknown — Read one register. Returns undefined for any missing segment — never throws.
  • constructor( name?: string, options?: { lodConfig?: LODConfig; id?: string; uuid?: string } )
  • refreshLinkBounds(link: LinkModel): void — Re-index a link after its geometry changed WITHOUT a change:points event.
  • isReadonly(): boolean — Is this document locked against edits?
  • setReadonly(value: boolean): void — Lock / unlock the document. Normally driven by DiagramEngine.setMode() — VIEW and PRESENTATION lock, DESIGNER unlocks — so DiagramMode finally means something. Can also be set directly for a host that has no mode concept.
  • blocksDocumentWrite(): boolean — True when a document mutation must be refused right now.
  • inSystemWrite(): boolean — True while a SYSTEM write is in flight. Read by the PER-NODE geometry lock (NodeState.locked) so it exempts measured writes exactly as the document lock does — see readonly-lock.ts.
  • runSystemWrite<T>(fn: () => T): T — Run a SYSTEM write — a derived/measured value (auto-size, portal placement) the engine needs in order to render the document as it already is. Permitted even while locked. NOT reachable from user input; see readonly-lock.ts.
  • addNode(node: NodeModel): void
  • removeNode(nodeId: string): NodeModel | undefined — Remove node from diagram — AND every link attached to it.
  • replaceNode(next: NodeModel): void — Swap the live model under next.id for next, KEEPING the links attached to it. (An id not on the canvas is simply added.)
  • getLinksForNode(nodeId: string): LinkModel[] — Every link with an endpoint on nodeId (either end, including a self-loop).
  • restoreNode(data: any): NodeModel | undefined — Restore node from serialized data
  • getNode(nodeId: string): NodeModel | undefined — Get node by ID
  • getNodes(): NodeModel[] — Get all nodes
  • getNodeByPortId(portId: string): NodeModel | undefined — Get node that owns a specific port Used for connection group validation and other port-based queries. O(1) via the portIndex (was an O(nodes×ports) linear scan).
  • getPortById(portId: string): PortModel | undefined — Get the port model for a port id, O(1) via the portIndex. Companion to getNodeByPortId for callers that need the port itself.
  • getDetachedAnchor(nodeId: string): DetachedParentAnchor | undefined — The last-known anchor of a REMOVED node, or undefined if the id is live, was never here, or the anchor was wholesale-cleared. The tolerant readers in NodeModel (getWorldPosition / getGlobalPosition / getGlobalTransformMatrix / setGlobalPosition) resolve an unresolvable parent through this so orphaned relative children freeze in place instead of jumping to their raw offsets. See {@link detachedAnchors} and the design argument on {@link removeNode}.
  • clearNodes(): void — Clear all nodes
  • addLink(link: LinkModel): void — Add link to diagram
  • removeLink(linkId: string): LinkModel | undefined — Remove link from diagram
  • restoreLink(data: any): LinkModel | undefined — Restore link from serialized data
  • getLink(linkId: string): LinkModel | undefined — Get link by ID
  • getLinks(): LinkModel[] — Get all links
  • getLinksForPort(portId: string): LinkModel[] — Get all links connected to a specific port
  • clearLinks(): void — Clear all links
  • createSmartLink( sourceNode: NodeModel, targetNode: NodeModel, pathType: 'direct' | 'orthogonal' | 'smooth' | 'bezier' = 'smooth' ): LinkModel | undefined — Create a smart link with automatic port selection
  • connectNodes( sourceNode: NodeModel, targetNode: NodeModel, pathType: 'direct' | 'orthogonal' | 'smooth' | 'bezier' = 'smooth' ): boolean — High-level API to connect two nodes
  • getNodeConnections(node: NodeModel): { incoming: LinkModel[]; outgoing: LinkModel[]; all: LinkModel[]; } — Get all connections for a node
  • disconnectNodes(sourceNode: NodeModel, targetNode: NodeModel): number — Disconnect two nodes
  • addGroup(group: GroupModel): void — Add group
  • removeGroup(groupId: string): GroupModel | undefined — Remove group
  • restoreGroup(data: any): GroupModel | undefined — Restore group from serialized data
  • getGroup(groupId: string): GroupModel | undefined — Get group by ID
  • getGroups(): GroupModel[] — Get all groups
  • getGroupsInRenderOrder(): GroupModel[] — Groups in deterministic back-to-front stacking order — ascending zIndex, ties broken by Map insertion order (a STABLE sort keeps it). This is the model-level z-order story that replaces "stacking == Map insertion order" as the only determinant; a renderer paints groups in this order (behind their members) instead of relying on iteration order.
  • getProxyNodeForGroup(groupId: string): NodeModel | undefined — The placeholder "group-as-node" for a collapsed group, if present. Placeholder nodes are ordinary NodeModels tagged with the group id so callers can filter them out of exports / counts.
  • isProxyNode(node: NodeModel): boolean — Is this node a collapsed-group placeholder?
  • clearGroups(): void — Clear all groups
  • addStroke(stroke: StrokeModel): void
  • removeStroke(strokeId: string): StrokeModel | undefined
  • restoreStroke(data: SerializedStroke): StrokeModel | undefined
  • getStroke(strokeId: string): StrokeModel | undefined
  • getStrokes(): StrokeModel[]
  • clearStrokes(): void
  • getVisibleStrokes(viewport: Rectangle): StrokeModel[] — Strokes whose bounds overlap viewport. The ink layer's culling query.
  • getStrokesAlongSegment(a: Point, b: Point, tolerance = 0): StrokeModel[] — Every stroke the pointer swept across travelling a→b. THE ERASER'S QUERY.
  • getAncestors(groupId: string): GroupModel[] — Get a group's ancestor chain (nearest parent first), walking parentGroupId upward. Robust against malformed self/looping pointers.
  • getDescendants(groupId: string): GroupModel[] — Get every group nested (directly or transitively) inside groupId. Breadth-first over the parentGroupId back-pointers.
  • getDepth(groupId: string): number — Nesting depth of a group: number of ancestors (0 for a top-level group).
  • getSelectedNodes(): NodeModel[] — Get all selected nodes
  • selectNode(node: NodeModel): void — Select a single node (clears previous selection)
  • addToSelection(node: NodeModel): void — Add node to selection (multi-select)
  • removeFromSelection(node: NodeModel): void — Remove node from selection
  • toggleNodeSelection(node: NodeModel): void — Toggle node selection (add if not selected, remove if selected)
  • clearSelection(): void — Clear all selections
  • selectAll(): void — Select all nodes
  • deleteSelected(): number — Delete all selected nodes and their connected links
  • getNodeAtPosition(x: number, y: number): NodeModel | undefined — Get node at position (for click detection) Returns the topmost node at the given position
  • isPointCoveredAbove(x: number, y: number, nodeId: string): boolean — Is (x, y) inside any node ABOVE nodeId in z-order?
  • lockSelected(): number — Option 3: Lock/pin selected nodes Locked nodes will not move during layout operations
  • unlockSelected(): number — Option 3: Unlock selected nodes
  • getLockedNodes(): NodeModel[] — Option 3: Get locked nodes
  • unlockAll(): number — Option 3: Unlock all nodes
  • setViewport(x: number, y: number, width: number, height: number, zoom?: number): void — Set viewport
  • getViewport(): { x: number; y: number; width: number; height: number; zoom: number } — Get current viewport
  • pan(dx: number, dy: number): void — Pan viewport
  • zoom(delta: number, center?: Point): void — Zoom viewport (relative adjustment)
  • setZoom(level: number, center?: Point): void — Set absolute zoom level Option B: Pan/Zoom controls
  • fitToView(padding: number = 100): void — Fit viewport to show all nodes (without changing zoom level) Option B: Pan/Zoom controls
  • zoomToFit(targetWidth: number, targetHeight: number, padding: number = 100): void — Fit viewport to show all nodes AND adjust zoom to fit screen Option B: Pan/Zoom controls
  • clear(): void — Clear all nodes, links, and groups
  • getVisibleNodes(viewport: Rectangle): NodeModel[] — Get nodes visible in viewport This enables viewport virtualization - only render visible nodes
  • getVisibleLinks(viewport: Rectangle): LinkModel[] — Get links visible in viewport This enables viewport virtualization - only render visible links
  • findNearestPort( point: Point, options?: NearestPortOptions ): NearestPortHit | null — The nearest port to a world point, served BY THE SPATIAL INDEX.
  • getVisibleBounds(viewport: Rectangle): Rectangle | null — Get bounding box of all visible entities Useful for "fit to viewport" operations
  • getDirtyNodes(): NodeModel[] — Get all dirty nodes Returns nodes that need re-rendering
  • getDirtyLinks(): LinkModel[] — Get all dirty links Returns links that need re-rendering
  • getDirtyGroups(): GroupModel[] — Get all dirty groups Returns groups that need re-rendering
  • markAllClean(): void — Mark all entities as clean Call this after rendering to reset dirty flags
  • getDirtyCount(): number — Get total count of dirty entities Useful for monitoring render performance
  • getVisibleDirtyNodes(viewport: Rectangle): NodeModel[] — Get visible dirty nodes Combines viewport virtualization with dirty marking Only returns nodes that are both visible AND need re-rendering
  • getVisibleDirtyLinks(viewport: Rectangle): LinkModel[] — Get visible dirty links Combines viewport virtualization with dirty marking Only returns links that are both visible AND need re-rendering
  • getLODLevel(zoom: number): LODLevel — Get LOD level based on zoom
  • shouldRender(feature: LODFeature, lod: LODLevel): boolean — Single feature gate that reads the active LOD tier's feature set. Renderers call this instead of hardcoding lod === 'high' checks, so custom tiers work automatically.
  • getLODConfig(): LODConfig — Get the current Level-of-Detail policy.
  • setLODConfig(config: LODConfig): void — Replace the Level-of-Detail policy wholesale. Apps use this to define their own tiers (names, breakpoints and feature sets).
  • registerLODTier(tier: LODTier): void — Register (or replace, by name) a single LOD tier. Lets apps extend the default policy with an extra tier without rebuilding the whole config.
  • getNodesWithLOD(viewport: Rectangle, zoom: number): EntityWithLOD<NodeModel>[] — Get visible nodes with LOD information Combines viewport virtualization with Level of Detail
  • getLinksWithLOD(viewport: Rectangle, zoom: number): EntityWithLOD<LinkModel>[] — Get visible links with LOD information Combines viewport virtualization with Level of Detail
  • shouldRenderLabels(lod: LODLevel): boolean — Check if labels should be rendered at this LOD level Now reads the LOD tier's feature set.
  • shouldRenderIcons(lod: LODLevel): boolean — Check if icons should be rendered at this LOD level Now reads the LOD tier's feature set.
  • shouldRenderBorders(lod: LODLevel): boolean — Check if borders should be rendered at this LOD level Now reads the LOD tier's feature set.
  • shouldRenderShadows(lod: LODLevel): boolean — Check if shadows should be rendered at this LOD level Now reads the LOD tier's feature set.
  • getLayoutManager(): LayoutManager — Get the layout manager for this diagram
  • setLayoutAlgorithm(type: LayoutAlgorithmType, config?: LayoutConfiguration): void — Set layout algorithm
  • getLayoutAlgorithm(): LayoutAlgorithmType — Get current layout algorithm type
  • configureLayout(config: LayoutConfiguration): void — Configure current layout algorithm
  • getLayoutConfiguration(): LayoutConfiguration — Get layout configuration
  • setAutoLayout(enabled: boolean): void — Enable or disable automatic layout for new nodes When enabled, newly added nodes will be automatically positioned using the current layout algorithm
  • isAutoLayoutEnabled(): boolean — Check if auto-layout is enabled
  • async reLayout(config?: LayoutConfiguration): Promise<void> — Re-layout all nodes using current algorithm This will recalculate positions for all nodes in the diagram
  • override endBatch(): void — Override: End batch update mode Fires accumulated events when all batches complete
  • serialize(): SerializedDiagram — Serialize to JSON
  • reconcilePortConnections(): Array<{ linkId: string; portId: string; end: 'source' | 'target' }> — Rebuild the derived port-connection registries from the diagram's links.
  • applyIncremental(patch: DiagramIncremental): void — Apply an incremental patch (see serialization/Incremental.ts) — the receive side of toIncremental/apply. Added entities are installed through the SAME unified restore path as document load (fully wired); modified entities are updated IN PLACE so object identity is preserved for renderers holding references; normal change events fire (an applied patch IS a mutation, unlike a document load).
  • static fromJSON(data: SerializedDiagram, options?: DiagramLoadOptions): DiagramModel (static) — Deserialize from JSON — THE document load path.
  • override dispose(): void — Dispose diagram and all child entities Prevents memory leaks by: - Disposing all nodes, links, and groups - Breaking circular references - Clearing spatial indices - Calling parent dispose()

Was this page helpful?