The Element System defines the core data model for all drawable entities in Excalidraw. This document covers the element type hierarchy, element lifecycle (creation, mutation, deletion), storage mechanisms, and high-level element relationships. For detailed information about specific subsystems, see:
All drawable entities in Excalidraw are represented by ExcalidrawElement objects. The type hierarchy consists of a base interface with common properties and specialized types for different shapes.
Base Properties (All Elements)
| Property | Type | Purpose |
|---|---|---|
id | string | Unique identifier |
type | "rectangle" | "ellipse" | "diamond" | "arrow" | "line" | "freedraw" | "text" | "image" | "frame" | "magicframe" | "embeddable" | "iframe" | Element shape type |
x, y | number | Top-left position in scene coordinates |
width, height | number | Element dimensions |
angle | Radians | Rotation angle |
version | number | Incremented on each mutation |
versionNonce | number | Random value changed on mutation |
isDeleted | boolean | Soft deletion flag |
index | FractionalIndex | Z-order position (see Fractional Indexing) |
groupIds | GroupId[] | Group membership |
frameId | string | null | Containing frame (see Frames) |
boundElements | BoundElement[] | null | Elements bound to this element (see Binding) |
updated | number | Timestamp of last update |
link | string | null | Hyperlink URL |
locked | boolean | Prevents editing |
Style Properties
| Property | Type |
|---|---|
strokeColor | string |
backgroundColor | string |
fillStyle | "solid" | "hachure" | "cross-hatch" |
strokeWidth | number |
strokeStyle | "solid" | "dashed" | "dotted" |
roughness | number (0-2) |
opacity | number (0-100) |
roundness | StrokeRoundness | null |
Sources: packages/excalidraw/types.ts247-270 packages/element/src/types.ts
Sources: packages/excalidraw/types.ts14-36 packages/element/src/types.ts
Elements follow an immutable update pattern. Direct mutation is prohibited; instead, updates create new element versions:
version: Monotonically increasing integer, incremented on every mutationversionNonce: Random integer regenerated on mutation, used for conflict detection in multiplayer scenariosupdated: Timestamp in milliseconds for tracking element freshnessThe mutateElement function is the primary mechanism for updating elements while maintaining immutability invariants.
Sources: packages/element/src/mutateElement.ts1-100 packages/excalidraw/components/App.tsx110-243
Constructor Functions
Element creation uses type-specific constructor functions located in the @excalidraw/element package:
| Function | Creates |
|---|---|
newElement() | Generic elements (rectangle, ellipse, diamond) |
newLinearElement() | Line elements |
newArrowElement() | Arrow elements |
newTextElement() | Text elements |
newImageElement() | Image elements |
newFreeDrawElement() | Freedraw elements |
newFrameElement() | Frame elements |
newMagicFrameElement() | Magic frame elements |
newIframeElement() | Iframe elements |
newEmbeddableElement() | Embeddable elements |
Each constructor:
id via randomId()x, y)width, height)version: 1, random versionNonce, and current updated timestamppoints for linear elements)Sources: packages/excalidraw/components/App.tsx110-243 packages/element/src/newElement.ts
High-Level Creation via convertToExcalidrawElements
For declarative element creation, use convertToExcalidrawElements which accepts simplified ExcalidrawElementSkeleton objects:
This function:
Sources: packages/excalidraw/data/transform.ts1-500 packages/excalidraw/data/transform.test.ts
mutateElement Function
The canonical way to update elements. Never modify element properties directly.
Behavior:
updates objectversionversionNonce (random integer)updated timestampThe informMutation parameter (default true) controls whether the mutation triggers observable change detection.
Sources: packages/element/src/mutateElement.ts40-150
newElementWith Helper
A lightweight alternative that creates a new element with updated properties without triggering mutation side effects:
Does not increment version or versionNonce, primarily used for temporary or ephemeral updates.
Sources: packages/element/src/mutateElement.ts20-38 packages/excalidraw/components/App.tsx110-243
Elements use soft deletion via the isDeleted flag. Deleted elements remain in the scene but are filtered out during rendering and most operations.
Benefits:
isDeleted: false)Hard deletion (removing from scene completely) is rare and typically only occurs during:
Sources: packages/element/src/typeChecks.ts packages/excalidraw/components/App.tsx232-239
Scene ClassThe Scene class manages the canonical collection of elements in the application.
Key Methods
| Method | Returns | Purpose |
|---|---|---|
getElementsIncludingDeleted() | ExcalidrawElement[] | All elements (including deleted) |
getNonDeletedElements() | OrderedExcalidrawElement[] | Only visible elements, sorted by z-order |
getNonDeletedElementsMap() | NonDeletedSceneElementsMap | Map of visible elements |
replaceAllElements(elements) | void | Replace entire element collection |
insertElementAtIndex(element, index) | void | Insert element at specific position |
getElement(id) | ExcalidrawElement | null | Retrieve element by ID |
The scene maintains cached sorted arrays and maps for performance. Caches are invalidated and rebuilt when elements change via triggerUpdate().
Sources: packages/element/src/Scene.ts1-400
SceneElementsMapA Map<string, ExcalidrawElement> used throughout the codebase for efficient element lookup by ID.
Helper functions:
arrayToMap(elements): Convert array to mapisNonDeletedElement(element): Type guard for non-deleted elementsSources: packages/element/src/types.ts packages/element/src/Scene.ts1-100
Store and Delta TrackingThe Store class captures observable element changes and emits them as delta events for history and collaboration.
Delta System
The delta system tracks incremental changes:
ElementsDelta: Captures added, removed, and updated elements
added: Map of newly created elementsremoved: Map of deleted elementsupdated: Map of element property changes (only changed properties included)AppStateDelta: Captures observable app state changes (selection, groups, etc.)
StoreDelta: Combines ElementsDelta + AppStateDelta
Store Commit Flow
Store.commit(elements, appState) calledsnapshotStoreDelta (only changed properties)DurableIncrement (for history) or EphemeralIncrement (transient, e.g., dragging)Sources: packages/element/src/store.ts1-300 packages/element/src/delta.ts1-400
Elements can be bound to each other to create relationships:
Binding information is stored bidirectionally:
startBinding / endBinding with target element IDboundElements arraySources: packages/element/src/binding.ts packages/excalidraw/components/App.tsx110-243
Elements can belong to multiple groups via the groupIds array property. Groups enable collective selection and manipulation.
Group operations:
getElementsInGroup(elements, groupId): Get all elements in a groupgetNonDeletedGroupIds(elements): Get all active group IDsselectGroupsForSelectedElements(): Auto-select parent groups when selecting grouped elementsSources: packages/element/src/groups.ts packages/excalidraw/components/App.tsx211-217
Frames provide spatial containment for elements (see Frames and Containment):
Frame-related operations:
getFrameChildren(scene, frameId): Get all elements in a frameelementOverlapsWithFrame(element, frame): Check spatial containmentgetContainingFrame(element, elementsMap): Find parent frameSources: packages/element/src/frame.ts packages/excalidraw/components/App.tsx176-190
Elements are ordered using fractional indices (see Fractional Indexing and Z-Order):
Key functions:
syncInvalidIndices(elements): Ensure valid fractional indicessyncMovedIndices(elements, indices): Update indices after reorderingorderByFractionalIndex(elements): Sort elements by indexThe fractional index system enables collaborative ordering without conflicts.
Sources: packages/element/src/fractionalIndex.ts packages/excalidraw/components/App.tsx218-219
duplicateElement
Creates a deep copy of a single element with a new ID:
Handles:
id generationduplicateElements
Bulk duplication with relationship preservation:
Advanced features:
Sources: packages/element/src/duplicate.ts1-400 packages/element/tests/duplicate.test.tsx
The convertToExcalidrawElements function transforms simplified element skeletons into full ExcalidrawElement objects:
Features
Example: Arrow with Bindings
Sources: packages/excalidraw/data/transform.ts1-800 packages/excalidraw/data/transform.test.ts1-500
Summary
The Element System provides:
Scene and SceneElementsMapThis architecture enables Excalidraw's core features: undo/redo, real-time collaboration, complex element interactions, and performant rendering.
Refresh this wiki