Learn / Kits: dashboards, ER & UML
Kits: dashboards, ER & UML
A kit turns plain data into a finished interactive diagram — entities in, an ER diagram with column-level ports out. Kits are functions returning specs, so they compose with everything else on this site.
The pattern
import { render, erDiagram } from '@grafloria/element';
const spec = erDiagram({ entities, relationships });
const api = render(spec, host); // render() runs the kit's finalize for you
In Vue: <GrafloriaDiagram :spec="spec" />. A kit spec is
{ nodes, edges, finalize } — regular nodes and edges plus a wiring step, so
everything else (layout, export, undo, collaboration) works on kit diagrams
unchanged.
ER — tables with real columns
const spec = erDiagram({
entities: [
{ id: 'CUSTOMER', name: 'Customer', position: { x: 60, y: 76 }, columns: [
{ name: 'id', type: 'int', pk: true },
{ name: 'email', type: 'varchar' },
]},
{ id: 'ORDER', name: 'Order', position: { x: 400, y: 64 }, columns: [
{ name: 'id', type: 'int', pk: true },
{ name: 'customer_id', type: 'int', fk: true },
]},
],
relationships: [
{ from: 'CUSTOMER', to: 'ORDER', label: 'places', cardinality: 'one-to-many' },
// attach at a COLUMN with ENTITY.column:
{ from: 'ORDER.customer_id', to: 'CUSTOMER.id' },
],
});
Rows are selectable (listen for axk:row-select), a fixed entity
height makes the column list scroll, and editable: true adds
rename/add/delete chrome where every edit is one undoable step.
UML — classes, stereotypes, markers
const spec = umlDiagram({
classes: [
{ id: 'Animal', abstract: true, position: { x: 380, y: 40 },
attributes: ['# name: String'], methods: ['+ speak(): void'] },
{ id: 'Dog', position: { x: 150, y: 320 }, methods: ['+ fetch(): void'] },
],
relationships: [
{ from: 'Dog', to: 'Animal', kind: 'inheritance' },
{ from: 'Owner', to: 'Dog', kind: 'aggregation', label: 'owns', multiplicity: ['1', '0..*'] },
],
});
Relationship kinds draw the correct UML markers: inheritance,
realization, association, directed-association,
aggregation, composition, dependency.
Both card kits also expose a typed handle façade for programmatic editing that rides the undo stack:
import { umlClass } from '@grafloria/element';
const animal = umlClass(api, 'Animal');
await animal.methods.add('+ move(): void');
await animal.setAbstract(true);
await animal.undo();
Dashboards — a drag-and-pack grid
import { render, dashboard } from '@grafloria/element';
const spec = dashboard({
columns: 12,
widgets: [
{ id: 'kpi-revenue', kind: 'kpi', span: 3,
data: { label: 'Total revenue', value: '$6.81M', delta: 12.4,
spark: [42, 45, 51, 55, 61, 71, 76] } },
{ id: 'trend', kind: 'line', span: 6, rows: 2, title: 'Revenue trend',
data: { series: [{ name: 'Revenue', values: [1.2, 1.4, 1.9, 2.3] }],
labels: ['Q1', 'Q2', 'Q3', 'Q4'] } },
{ id: 'mix', kind: 'donut', span: 3, rows: 2, title: 'By region',
data: { slices: [{ label: 'EMEA', value: 2.9, color: '#3B52D9' }] } },
],
});
render(spec, host);
spec.handle.addWidget({ id: 'later', kind: 'bar', span: 3, data: { bars: [] } });
Containers — widgets that hold widgets. A widget carrying
widgets mounts as a section: a locked slab in the board
with its own pack grid inside (own columns, default: its span).
Tiles drag across the boundary in both directions — the other grid adopts
them live — and one undo restores the whole gesture. A child resized past
the section's designed rows escalates: the section grows a row in
the board. toJSON() reports the nesting from live membership,
so a dragged-in tile serialises under its new parent. Tested to two levels
of nesting.
{ id: 'kpis', title: 'KPI section', span: 12, rows: 1, columns: 4,
widgets: [
{ id: 'k-rev', kind: 'kpi', span: 1, data: { label: 'Revenue', value: '$6.8M' } },
{ id: 'k-cust', kind: 'kpi', span: 1, data: { label: 'Customers', value: '1,284' } },
] }
Six built-in widget kinds render with zero code — kpi,
line, bar, donut, funnel,
table — and renderWidget (or React's
widgetTypes, Vue's #widget-<kind> slots, Angular's
ng-template grafloriaWidget) takes over for your own. Widgets drag and
pack live, gridstack-style; multiple views give you tabs; and
handle.toJSON() returns exactly what dashboard() accepts —
the layout round-trips by construction.
Where next
- vs GridStack-class libraries — where the dashboard kit sits.
- Commands & undo — why kit edits are undoable for free.