@miragon/dmn-modeler
The reference for developers who embed the DMN modeler of the Miragon BPMN Modeler in their own web app. @miragon/dmn-modeler is built on dmn-js: one createModeler(container, options) call stands up a modeler with the decision requirements diagram, decision tables, literal expressions, a properties panel and a decision simulation.
Install
npm install @miragon/dmn-modelerThe dmn-js stack (dmn-js, diagram-js, dmn-js-properties-panel and others) ships as regular dependencies, so one install pulls everything the modeler needs.
Usage
import { createModeler } from "@miragon/dmn-modeler";
// The stock dmn-js component styles (needed to render at all):
import "@miragon/dmn-modeler/styles.css";
const canvas = document.querySelector( "#canvas" )!;
const panel = document.querySelector( "#properties" )!;
const modeler = await createModeler( canvas, {
propertiesPanel: { parent: panel },
} );
await modeler.loadDiagram( existingDmnXml );
const xml = await modeler.exportDiagram();Theming
Theming is per-instance and needs no extra <link>: importing @miragon/dmn-modeler/styles.css (above) already ships both looks. The modeler toggles a data-dmn-theme="light" | "dark" attribute on its container and properties-panel parent, and the dark rules are scoped under [data-dmn-theme="dark"], so two modelers on one page can hold different themes. theme defaults to "automatic" (follows prefers-color-scheme live); pass theme: "light" / "dark" to pin one, or call modeler.setTheme(...) later.
const modeler = await createModeler( canvas, {
propertiesPanel: { parent: panel },
theme: "automatic", // "automatic" (default) | "light" | "dark"
} );Legacy #theme-link fallback. If you still link a theme stylesheet tagged id="theme-link", the modeler keeps swapping its href between @miragon/dmn-modeler/light-theme.css and .../dark-theme.css as before — a permanent, page-global compatibility path. It is optional; a missing #theme-link is a silent no-op. Because it is page-global, it cannot express per-instance themes — prefer the attribute mechanism (i.e. just styles.css).
Caveat: setting
data-dmn-themeon a page root element (<html>) themes everything below it. Mixing that with two instances that hold different per-instance themes would let the root value leak; a single-instance page or one that never sets the root attribute is unaffected.
Locale
The dmn-js UI is translated through the shared @miragon/bpmn-modeler-i18n dictionaries. Pass an initial locale to createModeler, or switch it live with setLocale(...):
const modeler = await createModeler( canvas, {
propertiesPanel: { parent: panel },
locale: "de", // any locale the shared library ships; unknown codes fall back to "en"
} );
await modeler.setLocale( "en" ); // re-translate liveThe locale is page-global — the i18n instance is a singleton, so locale / setLocale set the language for every modeler on the page (there is no per-instance locale). Switching a running modeler re-opens its active view so the already rendered labels re-translate; that resets the view's undo history and re-fires onViewChanged (the DRD viewbox is preserved). setLocale is a no-op when the resolved locale is unchanged.
Views
A loaded document exposes its views (getViews), the active view (getActiveView), and lets you switch between them (openView). Each view is a DRD, decision table, literal expression, or boxed expression editor.
const views = modeler.getViews();
await modeler.openView( views.find( ( v ) => v.type === "decisionTable" )! );Escape hatch
modeler.getService(name) reaches into the active dmn-js viewer's dependency-injection graph by service name. The names and returned shapes are not covered by this facade's API and may change without a major bump — prefer a typed option or method where one exists.
const eventBus = modeler.getService( "eventBus" );Caveats
bpmn.io watermark. dmn-js renders the bpmn.io logo. Per the bpmn.io license you must keep it visible unless you hold a commercial bpmn.io license. Do not hide it in CSS.
Locale is page-global in this release (the i18n instance is a singleton); theming is per-instance via the
data-dmn-themeattribute (see Theming).Yarn Berry installs. This package pins
diagram-jsexactly, but the dmn-js packages declare it with caret ranges. Yarn 2+ resolves each range to the newest matching version, so once diagram-js publishes a release newer than this package's pin, a second copy is nested under dmn-js and the modeler splits across two versions. npm and pnpm reuse the pinned version. With Yarn, pin it in your rootpackage.jsonto the version thatnode_modules/@miragon/dmn-modeler/package.jsondeclares, and update it whenever you upgrade@miragon/dmn-modeler:json{ "resolutions": { "diagram-js": "<pin from @miragon/dmn-modeler>" } }Bundler dedupe. The modeler and its plugins must share single copies of
infernoand the properties-panel / CodeMirror stack. If you build with Vite, add these toresolve.dedupe:tsresolve: { dedupe: [ "inferno", "@bpmn-io/properties-panel", "@codemirror/state", "@codemirror/view", "@codemirror/language", "@codemirror/autocomplete", "@codemirror/commands", "@codemirror/lint", "@codemirror/search", "@lezer/common", "@lezer/highlight", "@lezer/lr", ], }