API reference¶
Full reference for @sourcentis/bpmn-editor. For a quicker orientation, see
the Home page; for task-oriented walkthroughs, see the
guides.
createBpmnEditor(container, options?)¶
The package's single entry point.
function createBpmnEditor(
container: HTMLElement,
options?: BpmnEditorOptions
): BpmnEditorInstance;
container— an element already in the DOM. Its existing children are removed; the editor builds its own DOM inside it. Never assumes anything aboutcontainer's id or the surrounding page.- Nothing runs at import time — creating an instance is the only side
effect, and it's entirely scoped to
container(plus one shared, idempotently-injected<style>tag reused by every instance on the page). - Safe to call multiple times on different containers: instances don't
share state, and
destroy()on one never affects another.
BpmnEditorOptions¶
interface BpmnEditorOptions {
ui?: 'default' | 'none';
readOnly?: boolean;
provider?: BpmnObjectProvider;
persistence?: BpmnPersistence;
onNavigate?: (url: string) => void;
paletteRoot?: HTMLElement | null;
messages?: BpmnEditorMessages;
fontUrl?: string;
}
| Option | Type | Default | Notes |
|---|---|---|---|
ui |
'default' \| 'none' |
'default' |
'default' builds a toolbar (drag palette, zoom/undo/redo/save/import/export-BPMN/export-SVG) and a status bar inside container. 'none' builds only the canvas — the contextual per-element menu is still built in both modes, since it's core editing UX, not toolbar chrome. |
readOnly |
boolean |
false |
Disables editing; enables mouse-wheel zoom, cursor-becomes-pointer + click-to-navigate over elements with a url, and auto-resizes the container's height to fit the loaded diagram after loadXml(). With ui: 'default' this suppresses the toolbar/palette/file-input (there's nothing to edit with) but a status bar is still built. |
provider |
BpmnObjectProvider |
— | See Ports. Absent → the "insert cartography object" search action in the contextual menu is hidden and disabled; everything else works normally. |
persistence |
BpmnPersistence |
— | See Ports. Only consumed by the built-in ui: 'default' "Save" toolbar button — absent there, "Save" downloads a local .maxgraph file instead (the editor's own getXml() format — see the XML formats note; use the separate Export button for real BPMN 2.0 XML). Has no effect at all in ui: 'none' mode (there's no built-in Save button to call it); a ui: 'none' host wanting persistence should call its own BpmnPersistence implementation directly from its own button. |
onNavigate |
(url: string) => void |
— | Called (alongside the navigate event) when an element carrying a url is clicked in readOnly mode. Absent → clicking such an element is a no-op besides the event still firing (you can rely on on('navigate', …) alone if you prefer). |
paletteRoot |
HTMLElement \| null |
— | Only meaningful with ui: 'none'. Point it at a container whose descendants carry data-node-type attributes to reuse the built-in drag-to-insert mechanism with your own palette markup. Ignored with ui: 'default' (the built-in palette is used instead). Valid data-node-type values: task-node, state-node, gateway-node, data-node, lane-node, activities-node, annotation-node, conversation-node. |
messages |
BpmnEditorMessages |
bundled French | See Messages below and the i18n guide. |
fontUrl |
string |
bundled font (data URI) | Overrides the font used when embedding the BPMN glyph font into an SVG export (exportSvg() / the toolbar's SVG button). Does not affect on-canvas rendering, which always uses the bundled @font-face. |
BpmnEditorInstance¶
The object createBpmnEditor returns.
interface BpmnEditorInstance {
loadXml(xml: string): void;
getXml(): string;
importBpmnXml(xml: string): void;
exportBpmnXml(): string;
setEnabled(enabled: boolean): void;
exportSvg(filename?: string): Promise<void>;
zoomIn(): void;
zoomOut(): void;
fit(): void;
on<K extends BpmnEditorEventName>(event: K, handler: (payload: BpmnEditorEventMap[K]) => void): void;
off<K extends BpmnEditorEventName>(event: K, handler: (payload: BpmnEditorEventMap[K]) => void): void;
destroy(): void;
}
loadXml(xml: string): void¶
Replaces the current graph with the one described by xml (the format
getXml()/loadXml() round-trip — MaxGraph's own model serialization, the
same format Mercator stores diagrams in; not raw BPMN 2.0 XML — see the
assets/format note below). Fires change. Throws
(and emits error) if xml can't be parsed — the graph is left unchanged
in that case. In readOnly mode, also schedules the container's
auto-resize.
getXml(): string¶
Serializes the current graph. Never throws in practice (an empty graph serializes to an empty-but-valid document).
importBpmnXml(xml: string): void¶
Replaces the current graph by parsing standard BPMN 2.0 XML — the format
real BPMN modeling tools export, distinct from loadXml()'s format (see
the XML formats note). This is the same parser
the built-in ui: 'default' toolbar's file-input Import button uses
internally, exposed so a ui: 'none' host (or any other caller — a drag-and-drop
zone, a URL parameter, …) can trigger the same import programmatically.
Fires change on success. Throws (and emits error) if xml can't be
parsed — the graph is left unchanged in that case.
exportBpmnXml(): string¶
Serializes the current graph as standard BPMN 2.0 XML — the counterpart of
importBpmnXml(), producing the <definitions>/<process> (or
<collaboration>) / <bpmndi:BPMNShape>/<bpmndi:BPMNEdge> shape a real
BPMN modeling tool would read, not getXml()'s own format (see
the XML formats note). This is what the built-in
ui: 'default' toolbar's Export button (right next to Import) calls
internally to produce the downloaded .bpmn file, exposed so a ui: 'none'
host can wire its own button to it the same way it would exportSvg().
Never throws in practice (an empty graph exports to an empty-but-valid
document); a genuine failure still throws and emits error, matching every
other method here.
setEnabled(enabled: boolean): void¶
Toggles editing at runtime — the same switch readOnly flips at creation
time, exposed so you can change it after the fact (e.g. an edit/view toggle
button) without re-creating the instance. Note this only touches
editability; it does not add or remove the readOnly-mode extras
(wheel-zoom, click-to-navigate, auto-resize) that were wired in based on the
readOnly option at creation time.
exportSvg(filename?: string): Promise<void>¶
Exports the current graph as an SVG file (with the BPMN glyph font embedded
so it renders correctly outside the browser) and triggers a browser
download. filename defaults to "bpmn-export.svg". This is exactly what
the built-in ui: 'default' toolbar's SVG button calls — use it to wire
your own button when mounting with ui: 'none'.
zoomIn() / zoomOut() / fit()¶
Viewport controls, usable regardless of ui mode. fit() centers the
current view on the graph's contents.
on(event, handler) / off(event, handler)¶
Subscribe/unsubscribe. See Events below.
destroy(): void¶
Removes every listener the instance added — including ones on
window/document, not just inside container — and empties container.
Idempotent (safe to call more than once). After destroy(), the instance
should not be used further.
Events¶
interface BpmnEditorEventMap {
change: undefined;
select: Cell | null;
save: { id: number; name: string; type: string; content: string };
navigate: string;
error: Error;
}
| Event | Payload | Fires when |
|---|---|---|
change |
undefined |
The graph model changes: an edit, an undo/redo, or a loadXml() call. |
select |
Cell \| null (a @maxgraph/core Cell) |
The selection changes. null when nothing, or more than one thing, is selected. |
save |
BpmnPersistencePayload ({ id, name, type, content }) |
Right before the built-in ui: 'default' Save button calls persistence.save(payload) — an observation hook, not a place to short-circuit the save. |
navigate |
url: string |
A readOnly-mode click lands on an element carrying a url — fires alongside (not instead of) onNavigate. |
error |
Error |
An XML parse failure, a rejected provider/persistence call, or an exportSvg()/exportBpmnXml() failure. |
editor.on('select', (cell) => {
saveButton.disabled = cell === null;
});
Ports¶
Both ports are plain TypeScript interfaces — implement only what you need.
Neither is required; the editor degrades gracefully without them (see the
provider/persistence rows in the options table
above for exactly what's disabled/falls back).
BpmnObjectProvider¶
interface BpmnObjectProvider {
getGraphObjects(): Promise<BpmnElementDef[]>;
getInformationObjects(): Promise<BpmnElementDef[]>;
getActorObjects(): Promise<BpmnElementDef[]>;
getProcessObjects(): Promise<BpmnElementDef[]>;
}
type BpmnElementDef = {
id: string;
name: string;
glyph: string;
url?: string;
};
Each method backs the "insert cartography object" search for a different
selected-element kind (process/task element → getGraphObjects, data
object → getInformationObjects, lane → getActorObjects, conversation →
getProcessObjects). glyph is a short label rendered next to name in
the picker list (Mercator's own provider uses the first character of id;
any short string works).
Minimal in-memory example (see
examples/with-simulated-backend.html
for a runnable version):
const provider: BpmnObjectProvider = {
getGraphObjects: async () => [{ id: 'a1', name: 'Invoicing', glyph: 'A' }],
getInformationObjects: async () => [{ id: 'i1', name: 'Customer record', glyph: 'I' }],
getActorObjects: async () => [{ id: 'b1', name: 'Billing team', glyph: 'B' }],
getProcessObjects: async () => [{ id: 'p1', name: 'Order fulfillment', glyph: 'O' }],
};
A rejected promise from any of these is caught internally, surfaced via the
error event, and logged — it does not crash the editor.
BpmnPersistence¶
interface BpmnPersistence {
save(payload: BpmnPersistencePayload): Promise<BpmnPersistenceResult>;
}
interface BpmnPersistencePayload {
id: number;
name: string;
type: string;
content: string; // getXml() output
}
interface BpmnPersistenceResult {
id: number;
}
The built-in ui: 'default' Save button has no name/type fields of its
own, so it always calls save() with id: -1, name: '', type: '' — treat
id === -1 as "not yet saved" the way Mercator's own adapter does. A host
that needs real name/type metadata should mount with ui: 'none', own its
own Save button, and call its BpmnPersistence implementation directly
(bypassing options.persistence entirely) — see
Mercator's adapter
for exactly that pattern, including CSRF and reflecting a newly-assigned id
back into the page.
BpmnEditorMessages / i18n¶
Every key is optional; unset keys fall back to the bundled French defaults. See the i18n guide for a full English override example.
| Key | Default (French) | Used for |
|---|---|---|
welcome |
👋 Bienvenue ! Charge un fichier BPMN |
Status message shown once, on mount, in ui: 'default' non-readOnly mode. |
saveSuccess |
✓ Graphe sauvegardé |
Status message after a successful Save (download fallback or persistence.save()). |
saveError |
Erreur lors de la sauvegarde du graphe. |
Status message when persistence.save() rejects. |
loadSuccess |
✓ Fichier chargé avec succès |
Status message after successfully importing a file via the toolbar's file input. |
loadError |
✗ Erreur lors du chargement du fichier |
Status message when importing a file fails. |
exportError |
✗ Impossible de générer le BPMN |
Status message when getXml() fails or returns empty during Save, or when the toolbar's Export button's exportBpmnXml() call fails. |
exportBpmnSuccess |
✓ Fichier BPMN exporté |
Status message after the toolbar's Export button successfully downloads a .bpmn file. |
filterPlaceholder |
Filter... |
Placeholder text of the "insert cartography object" search input. |
filterAriaLabel |
Filter elements |
aria-label of that same input. |
noMatch |
No match. |
Shown in the object picker when the filter matches nothing. |
saveNameRequired |
Le nom du graphe est obligatoire. |
Not consumed by the editor itself — reserved for a host adapter that has its own name field and wants to reuse this message for its own validation. |
xmlParseError |
Erreur de parsing XML |
Not consumed by the editor itself — reserved the same way, for a host with its own raw-XML handling. |
A note on XML formats¶
The editor understands two different XML formats, each with its own pair of methods:
loadXml()/getXml()round-trip MaxGraph's ownGraphDataModelserialization — the format Mercator stores diagrams in, and the formatexamples/sample.maxgraphis written in.importBpmnXml()/exportBpmnXml()read and write actual BPMN 2.0 XML —<definitions>,<process>(or<collaboration>when there's more than one pool),<startEvent>,<sequenceFlow>,<bpmndi:BPMNShape>/<bpmndi:BPMNEdge>positions, etc. — the format real BPMN modeling tools read and write.importBpmnXml()is what the built-inui: 'default'toolbar's file-input Import button calls internally, and whatexamples/editor.htmluses to loadexamples/sample.bpmnon startup;exportBpmnXml()is its exact counterpart, called by the toolbar's Export button right next to it. A round-trip through the two (import, then export with no edits in between) reproduces the same diagram — same elements, same positions, same colors — though not necessarily byte-identical XML (ids not carried by the graph model may be regenerated; seebpmn-export.ts's header comment for exactly what's preserved).exportSvg()remains the option for a portable rendered (non-editable) output.
If you're generating diagrams programmatically to feed to loadXml()
(rather than importing an existing BPMN 2.0 file with importBpmnXml()),
use getXml()'s own output as your reference format — round-trip a diagram
you've built by hand in the editor once, and use that as a template.