Import it from @grafloria/engine.
tsclass GroupModel extends DiagramEntity
Properties
| Name | Type | Default | Description |
|---|---|---|---|
name | string | ||
members | Set<string> | ||
isCollapsed | boolean | false | |
bounds? | { x: number; y: number; width: number; height: number } | ||
layoutType | LayoutType | 'none' | |
layoutConfig? | LayoutConfig | ||
position | { x: number; y: number } | ||
size? | { width: number; height: number; depth: number } | ||
parentGroupId? | string | ||
memberValidation? | MemberValidation | ||
isHovered | boolean | false | |
padding? | GroupPadding | ||
headerHeight | |||
zIndex | 0 | ||
fitMode | GroupFitMode | 'exact' | |
constrainChildren | false | ||
collapsedState? | CollapsedState | ||
subgraphLayout? | SubgraphGroupConfig | ||
laneConfig? | LaneConfig | ||
membershipRule? | MembershipRule | ||
capacity? | number |
Methods
constructor(config: { id?: string; name: string })canAddMember(candidateId: string, diagram?: DiagramModel): boolean— WhethercandidateIdmay legally join this group. Rejects self-membership, ancestor cycles (adding an ancestor group as a member would create a containment loop), and candidates failing the per-groupmemberValidationpredicate. Node candidates only run the predicate check (nodes can't form group cycles).getWipState(): { count: number; capacity?: number; state: 'unlimited' | 'under' | 'full' | 'over' }— WIP state for the capacity limit. 'under' = room to spare, 'full' = exactly at the limit (the visual warning threshold), 'over' = past it (only reachable by lowering capacity below the current count). Returns 'unlimited' when no capacity is set.isOverCapacity(): boolean— True when at or beyond the capacity limit (warning state).setCapacity(capacity: number | undefined): void— Set (or clear) the capacity / WIP limit, tracked for undo/diff.addMember(entityId: string, diagram?: DiagramModel): void— Add member to group.
When the member is itself a group, this establishes containment by setting
the child's parentGroupId (detaching it from any previous parent), which
keeps the nesting tree consistent for getAncestors/getDescendants. Members
that would create a cycle or fail memberValidation are rejected (no-op).
removeMember(entityId: string, diagram?: DiagramModel): boolean— Remove member from group. When the member is a group whose parent is this group, itsparentGroupIdback-pointer is cleared so the nesting tree stays consistent.setParent(newParentId: string | undefined, diagram?: DiagramModel): boolean— Reparent this group undernewParentId(or detach when undefined), keeping both theparentGroupIdpointer and the parents'memberssets consistent. Rejects cycles (a group cannot be nested under one of its own descendants) and returns false without mutating anything.setHovered(hovered: boolean): void— Set transient drag-hover highlight state and notify listeners. Renderers/canvas can subscribe to 'hover' to outline a drop target.expand(): void— Expand the groupcollapse(): void— Collapse the groupsetCollapsedState(state: CollapsedState | undefined): void— Set (or clear) the reversible collapse snapshot. Tracked as a change so the incremental diff-capture serializes it and undo/redo see it.setLayout(type: 'flexbox', config: FlexboxLayoutConfig): void— Set layout configurationsetLayout(type: 'grid', config: GridLayoutConfig): void— Set layout configurationsetLayout(type: 'flexbox' | 'grid', config: LayoutConfig): void— Set layout configurationclearLayout(): void— Clear layout configurationgetLayout(): { type: LayoutType; config?: LayoutConfig }— Get layout configurationhasLayout(): boolean— Check if group has layout configuredgetFlexboxLayout(): FlexboxLayoutConfig— Get layout as flexbox configgetGridLayout(): GridLayoutConfig— Get layout as grid configcalculateBounds(diagram: DiagramModel): void— Calculate bounds from member nodes using global boundsgetPadding(): { top: number; right: number; bottom: number; left: number }— Resolve {@link padding} to a full four-sided rectangle.undefined(the author never said) resolves to {@link DEFAULT_GROUP_PADDING}; an explicit value — including the 0 that loaders pin for legacy documents — is taken as written.getOuterBounds(): GroupRect— The group's outer frame rectangle in world coordinates. Prefers explicit geometry (position + size) and falls back to the derived memberbounds, matching how GroupMembershipService hit-tests a group.getInnerBounds(): GroupRect— The rectangle members must stay inside: the outer frame minus padding and minus the header band (which is reserved at the top). Never returns a negative width/height.fitToContents(diagram?: DiagramModel, options?: FitToContentsOptions): void— Auto-fit the group frame to its members' bounding box plus padding and the header band. This is the real consumer ofpadding/headerHeightthatcalculateBounds(a tight, padding-free box) never was.
Member groups contribute their own OUTER frame (so a parent fits around a
nested group's full extent, not just its raw member points). With
deepRecursive, descendant groups are fitted first (deepest first) so the
parent fits around already-fitted children.
The computed content rectangle is reconciled with the current frame per the
effective fit mode (grow-only / shrink-only / exact) and written to both
position/size (authoritative geometry) and bounds (hit-test rect). No-op with no positioned members (nothing to fit around).
setFrame(rect: GroupRect): void— Write a world rectangle into the group's authoritative geometry (position + size) and the derived hit-testbounds, keeping the existingdepthwhen present. Tracks a single 'bounds' change for undo/diff.clampChildToExtent(nodeId: string, diagram?: DiagramModel): boolean— Clamp a member node so it stays fully inside the group's inner extent. No-op unlessconstrainChildrenis set and the node is a direct member. Returns true when the node was actually moved. Absolute-coordinate model: this adjusts the node's world position directly.restoreGeometry(geo: { position: { x: number; y: number }; size?: { width: number; height: number; depth: number }; bounds?: GroupRect; }): void— Restore raw geometry (position + optional size + bounds) captured before a collapse. Unlike setFrame this permits size === undefined so a group that had no explicit frame is restored to exactly that.setZIndex(z: number): void— Set the group's stacking index (lower renders further back).bringToFront(diagram?: DiagramModel): void— Bring this group in front of every other group (highest zIndex + 1). Minimal z-order API — the renderer honors zIndex ordering.sendToBack(diagram?: DiagramModel): void— Send this group behind every other group (lowest zIndex - 1).isAutoLayoutEnabled(): boolean— Is push-driven reflow active for this container?
DEFAULT ON for any group that declares a layout — a container that says
"I am a 12-column grid" and then lets its children drift is not a layout
container. metadata('autoLayout') survives as the explicit override:
set it to false to freeze the children (useful while dragging, or for a
container whose positions are authored by hand). Setting it to true
remains valid and is now simply the default.
requestLayout(diagram?: DiagramModel): void— THE push entry point: "something changed, reflow if you are supposed to." Distinct from {@link applyLayout}, which is the unconditional PULL — an explicitapplyLayout()still works on an opted-out container.applyLayout(diagram?: DiagramModel): void— Apply layout to member nodes Positions child nodes based on flex or grid layout configurationserialize(): SerializedGroup— Serialize to JSONstatic fromJSON(data: SerializedGroup): GroupModel(static) — Deserialize from JSON
Was this page helpful?