@t-yamauchi/wireflow
v1.2.12
Published
DSL-based interactive flow, ER, component, class, and sequence diagram renderer.
Readme
Wireflow
Wireflow is a DSL-based JavaScript diagram renderer for flow diagrams, screen flows, ER diagrams, component diagrams, class diagrams, and sequence diagrams.
It can be used from npm, CDN, or a local bundled file.
Official site: https://wireflow.jp/
Install
npm install @t-yamauchi/wireflowimport { Wireflow } from "@t-yamauchi/wireflow";
const wf = new Wireflow("#canvas", {
autoFit: true,
});
wf.render(`
layout:
mode: horizontal
auto-fit: true
Start:
Start
---
kind: start
Review:
Review
---
kind: process
Done:
Done
---
kind: end
Start -> Review
Review -> Done
`);You can also load DSL from a text-like file. Markdown files render the first
fenced code block tagged wireflow.
const wf = new Wireflow("#canvas", { autoFit: true });
await wf.render("./flows/checkout.md");CDN
<div data-wireflow-viewport style="height: 420px">
<div id="canvas"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/@t-yamauchi/wireflow/dist/wireflow.min.js"></script>
<script>
const WF = window.WireflowLib;
const wf = new WF.Wireflow("#canvas", {
autoFit: true,
});
wf.render(`
layout:
mode: horizontal
auto-fit: true
Input:
Input
---
kind: screen
state: accent
Validate:
Validate
---
kind: decision
Save:
Save
---
kind: process
Input -> Validate
Validate -> Save:
on-success: true
`);
</script>unpkg is also supported:
<script src="https://unpkg.com/@t-yamauchi/wireflow/dist/wireflow.min.js"></script>DSL Basics
Wireflow currently uses a YAML-like DSL.
layout:
mode: horizontal
auto-fit: true
Home:
Home
---
kind: screen
state: accent
payload:
title: Home
desc: |
Node details
Detail:
Detail
---
kind: screen
Home:right -> Detail:left:
label: openThe text above --- is rendered as the node label. The lines below --- are attributes.
Supported Diagram Types
- Flow diagrams
- Screen flows
- ER diagrams
- Component diagrams
- Class diagrams
- Sequence diagrams
- Notes / comments
Node Attributes
Common node attributes:
| Attribute | Example | Description |
|---|---|---|
| kind | kind: screen | Node kind such as screen, process, decision, start, end, entity, note |
| state | state: success | Visual preset: accent, success, warning, danger, muted |
| lane | lane: customer | Swimlane name |
| x, y | x: 120 | Manual position |
| dx, dy | dx: 16 | Position fine tuning |
| payload | payload: + nested YAML-style fields | Data passed to interaction events. Nodes and edges with payload open the default popup by default |
| popup | popup: CustomPopup | Optional explicit popup id override |
| link | link: https://example.com | Opens a URL on click |
| target | target: _blank | Link target |
| flow-ref | flow-ref: checkout/main | Subflow reference badge and event |
Edge Syntax
A -> B
A --> B
A - B
A -- B
A:right! -> B:left!:
label: forced portsCommon edge attributes:
| Attribute | Example | Description |
|---|---|---|
| label | label: submit | Edge label |
| stroke | stroke: #15803d | Edge color |
| stroke-width | stroke-width: 4 | Edge width |
| marker-end | marker-end: none | Removes arrow marker |
| route | route: perimeter | Route strategy |
| on-success | on-success: true | Success path styling |
| on-failure | on-failure: true | Failure path styling |
| from-anchor-offset | from-anchor-offset: 8 | Moves the source anchor along the selected node side. from-offset is kept as a compatible alias. |
| to-anchor-offset | to-anchor-offset: -6 | Moves the target anchor along the selected node side. to-offset is kept as a compatible alias. |
| from-anchor-dx, from-anchor-dy | from-anchor-dy: 12 | Force-shifts the source anchor point by X/Y pixels. Useful when several lines share one side. |
| to-anchor-dx, to-anchor-dy | to-anchor-dx: -10 | Force-shifts the target anchor point by X/Y pixels. |
| parallel-group | parallel-group: stream-1 | Parallel edge separation |
| bus | bus: api-bus | Shared bus routing |
Example:
Landing:right! -> Login:left!:
label: Login
from-anchor-dy: 12
to-anchor-dy: -8ER Diagram
layout:
mode: horizontal
auto-fit: true
User:
PK id bigint
email varchar(255) UNIQUE NOT NULL
---
kind: entity
Order:
PK id bigint
FK user_id bigint NOT NULL
status varchar(20) NOT NULL
---
kind: entity
User 1--0< Order: "orders"Field mapping can be written with repeated key: lines.
Order 1--0< OrderLog "audit":
key: id--order_id
key: user_id--user_idComponent Diagram
layout:
mode: horizontal
auto-fit: true
component Order:
Order
---
x: 80
y: 170
component Product:
Product
---
x: 560
y: 80
component Account:
Account
---
x: 560
y: 300
Order:right! -|o- Product:left!:
Item Code
Order:bottom! -|--o- Account:left!:
Account Details-|o- renders a provided interface connection. -|--o- renders an assembly-style connection where the middle segment is dashed.
Sequence Diagram
sequence:
User:
User
---
kind: actor
App:
App
API:
API
User -> App: Submit
App -> API: POST /orders
API --> App: 201 Created
App --> User: DoneNotes
Input:
Input
---
kind: screen
Validate:
Validate
---
kind: process
note Rule:
Required fields and format checks
---
target: Validate
state: warning
Input -> ValidatePublic API
import {
Wireflow,
renderWireflow,
parseDsl,
injectWireflowStyles,
createPopup,
createDefaultPopupRenderer,
popupHtml,
escapeHtml,
parseMdWireflow,
createFlowNavigator,
} from "@t-yamauchi/wireflow";Browser global:
const {
Wireflow,
renderWireflow,
parseDsl,
injectWireflowStyles,
createPopup,
createDefaultPopupRenderer,
popupHtml,
escapeHtml,
} = window.WireflowLib;Popup
For the shortest setup, let the static helper create the instance, inject styles, attach the default popup, and render immediately:
Wireflow.render("#canvas", dsl);Disable the default popup only when you need full custom handling:
Wireflow.render("#canvas", dsl, { popup: false });
const wf = new Wireflow("#canvas", { defaultPopup: false });The default popup reads payload fields such as title, desc, note, image, html, and imageAlt.
If image or html is true, Wireflow derives the file name from the element/popup id in lowercase:
Test:
Test
---
payload:
image: true
# -> images/test.svg
Review:
Review
---
payload:
html: true
# -> htmls/review.htmlIf both image: true and html: true are set, html wins and the image is not shown.
Explicit media file names are also supported:
payload:
title: Preview
image: dashboard.svg
htmlUrl: review.htmlYou can change those folders at initialization time:
Wireflow.render("#canvas", dsl, {
popup: {
imageBasePath: "/assets/images/",
htmlBasePath: "/assets/htmls/",
imageExtension: ".png",
htmlExtension: ".html",
},
});createPopup("#canvas", {
render: ({ id, data, html }) => html`
<h2>${data.title ?? id}</h2>
<p>${data.desc ?? ""}</p>
`,
});data is the normalized object payload, and html escapes interpolated values automatically.
If you need raw HTML, return an Element instead.
Nodes with a payload emit popup events automatically.
Use popup: CustomPopup only when you want to override the popup id.
Editor History
Wireflow supports undo/redo for DSL-changing interactions.
- Undo:
Ctrl + Z/Cmd + Z - Redo:
Ctrl + Y/Cmd + Y/Ctrl + Shift + Z - Change event:
wireflow:dsl-change
License
MIT
