@grafloria/element 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +41 -0
- package/src/index.d.ts +87 -0
- package/src/index.js +547 -0
- package/src/index.js.map +1 -0
- package/src/lib/dashboard-kit/dashboard.d.ts +345 -0
- package/src/lib/dashboard-kit/dashboard.js +594 -0
- package/src/lib/dashboard-kit/dashboard.js.map +1 -0
- package/src/lib/dashboard-kit/grid-binder.d.ts +277 -0
- package/src/lib/dashboard-kit/grid-binder.js +1635 -0
- package/src/lib/dashboard-kit/grid-binder.js.map +1 -0
- package/src/lib/dashboard-kit/grid-mapping.d.ts +141 -0
- package/src/lib/dashboard-kit/grid-mapping.js +176 -0
- package/src/lib/dashboard-kit/grid-mapping.js.map +1 -0
- package/src/lib/dashboard-kit/index.d.ts +5 -0
- package/src/lib/dashboard-kit/index.js +33 -0
- package/src/lib/dashboard-kit/index.js.map +1 -0
- package/src/lib/dashboard-kit/styles.d.ts +25 -0
- package/src/lib/dashboard-kit/styles.js +203 -0
- package/src/lib/dashboard-kit/styles.js.map +1 -0
- package/src/lib/dashboard-kit/widgets.d.ts +112 -0
- package/src/lib/dashboard-kit/widgets.js +389 -0
- package/src/lib/dashboard-kit/widgets.js.map +1 -0
- package/src/lib/diagram-kit/card.d.ts +75 -0
- package/src/lib/diagram-kit/card.js +209 -0
- package/src/lib/diagram-kit/card.js.map +1 -0
- package/src/lib/diagram-kit/editing.d.ts +54 -0
- package/src/lib/diagram-kit/editing.js +289 -0
- package/src/lib/diagram-kit/editing.js.map +1 -0
- package/src/lib/diagram-kit/er.d.ts +73 -0
- package/src/lib/diagram-kit/er.js +163 -0
- package/src/lib/diagram-kit/er.js.map +1 -0
- package/src/lib/diagram-kit/handles.d.ts +181 -0
- package/src/lib/diagram-kit/handles.js +325 -0
- package/src/lib/diagram-kit/handles.js.map +1 -0
- package/src/lib/diagram-kit/index.d.ts +8 -0
- package/src/lib/diagram-kit/index.js +38 -0
- package/src/lib/diagram-kit/index.js.map +1 -0
- package/src/lib/diagram-kit/rows.d.ts +53 -0
- package/src/lib/diagram-kit/rows.js +147 -0
- package/src/lib/diagram-kit/rows.js.map +1 -0
- package/src/lib/diagram-kit/styles.d.ts +18 -0
- package/src/lib/diagram-kit/styles.js +114 -0
- package/src/lib/diagram-kit/styles.js.map +1 -0
- package/src/lib/diagram-kit/uml.d.ts +59 -0
- package/src/lib/diagram-kit/uml.js +138 -0
- package/src/lib/diagram-kit/uml.js.map +1 -0
- package/src/lib/diagram-kit/update.d.ts +133 -0
- package/src/lib/diagram-kit/update.js +251 -0
- package/src/lib/diagram-kit/update.js.map +1 -0
- package/src/lib/grafloria-flow-element.d.ts +48 -0
- package/src/lib/grafloria-flow-element.js +271 -0
- package/src/lib/grafloria-flow-element.js.map +1 -0
- package/src/lib/grafloria.d.ts +61 -0
- package/src/lib/grafloria.js +72 -0
- package/src/lib/grafloria.js.map +1 -0
- package/src/lib/load.d.ts +72 -0
- package/src/lib/load.js +255 -0
- package/src/lib/load.js.map +1 -0
- package/src/lib/node-type-registry.d.ts +39 -0
- package/src/lib/node-type-registry.js +50 -0
- package/src/lib/node-type-registry.js.map +1 -0
package/src/lib/load.js
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fromDocument = fromDocument;
|
|
4
|
+
/**
|
|
5
|
+
* `fromDocument()` — the LOAD front door.
|
|
6
|
+
*
|
|
7
|
+
* ---------------------------------------------------------------------------
|
|
8
|
+
* THE GAP THIS CLOSES
|
|
9
|
+
* ---------------------------------------------------------------------------
|
|
10
|
+
* Saving was never the problem. `DiagramSerializer.serialize()` already emits a
|
|
11
|
+
* document that round-trips byte-identically, carrying nodes, links, ports,
|
|
12
|
+
* groups and every scrap of kit metadata. LOADING was the problem, in three
|
|
13
|
+
* layers:
|
|
14
|
+
*
|
|
15
|
+
* 1. THERE WAS NO FRONT DOOR. `CreateDiagramOptions` takes `nodes`/`edges`;
|
|
16
|
+
* nothing took a saved document. `deserialize()` handed back a
|
|
17
|
+
* `DiagramModel` that no entry point would render.
|
|
18
|
+
* 2. THE KITS' POST-RENDER WIRING NEVER RAN. `erDiagram()`/`umlDiagram()` do
|
|
19
|
+
* their interaction wiring in `finalize(api)` — row selection, in-canvas
|
|
20
|
+
* editing, the suppressed resize handles. A document has no `finalize`, so
|
|
21
|
+
* a "successfully loaded" ERD was a PICTURE of an ERD: it looked right and
|
|
22
|
+
* did nothing.
|
|
23
|
+
* 3. CUSTOM NODES HAD NO PAINTER. `renderCustomNode` is a function; functions
|
|
24
|
+
* do not serialize. A loaded dashboard mounted 14 widget hosts and painted
|
|
25
|
+
* into none of them.
|
|
26
|
+
*
|
|
27
|
+
* ---------------------------------------------------------------------------
|
|
28
|
+
* WHY THE NODES GO BACK IN AS LIVE MODELS
|
|
29
|
+
* ---------------------------------------------------------------------------
|
|
30
|
+
* The obvious implementation projects every loaded `NodeModel` back down into a
|
|
31
|
+
* `NodeSpec` and lets `buildNode()` rebuild it. That is a LOSSY detour, and it
|
|
32
|
+
* loses exactly the things a saved diagram is made of: `toNodeSpec()` carries
|
|
33
|
+
* id/position/size/data/label/shape and nothing else — no ports, no metadata,
|
|
34
|
+
* no behavior. An ER card would come back with four default side ports instead
|
|
35
|
+
* of its field ports, and every FK→PK edge would silently reroute.
|
|
36
|
+
*
|
|
37
|
+
* It is also unnecessary. `applyNodes()`/`applyEdges()` have always accepted a
|
|
38
|
+
* live `NodeModel`/`LinkModel` and pass it through untouched — the documented
|
|
39
|
+
* "mix data with your own model" seam. So the loaded models ARE the input, and
|
|
40
|
+
* nothing is projected, converted or lost.
|
|
41
|
+
*
|
|
42
|
+
* ---------------------------------------------------------------------------
|
|
43
|
+
* HOW PAINTERS COME BACK
|
|
44
|
+
* ---------------------------------------------------------------------------
|
|
45
|
+
* ER and UML need NOTHING: their card is `metadata.html`, a structured tree the
|
|
46
|
+
* renderer paints itself, and metadata round-trips. Measured, not assumed — a
|
|
47
|
+
* loaded ER document paints byte-identical cards with no painter in sight.
|
|
48
|
+
*
|
|
49
|
+
* Dashboard widgets are custom HTML nodes and do need one. The kit REBUILDS the
|
|
50
|
+
* widget spec from the node's own metadata (`widgetKind` / `widgetSpec` /
|
|
51
|
+
* `widgetTitle`) and hands it to the same `defaultWidgetRenderer` the authoring
|
|
52
|
+
* path uses, so a loaded board is drawn by the identical code.
|
|
53
|
+
*
|
|
54
|
+
* Precedence, and why:
|
|
55
|
+
*
|
|
56
|
+
* caller's `renderCustomNode` — an explicit override outranks everything.
|
|
57
|
+
* caller's `renderWidget` — the app's own chart painter; a board that was
|
|
58
|
+
* authored with one must be reloaded with it.
|
|
59
|
+
* the kit's own painter — but ONLY for nodes the kit actually stamped.
|
|
60
|
+
* {@link getNodeType} registry — everything else, exactly as `render()` does.
|
|
61
|
+
*
|
|
62
|
+
* The kit claims a node by its METADATA, never by `type === 'widget'` alone.
|
|
63
|
+
* Hijacking a type name would mean any unrelated diagram with a node called
|
|
64
|
+
* "widget" got dashboard chrome painted over it; requiring the stamp the kit
|
|
65
|
+
* itself wrote keeps the registry the general seam it is meant to be.
|
|
66
|
+
*/
|
|
67
|
+
const engine_1 = require("@grafloria/engine");
|
|
68
|
+
const node_type_registry_1 = require("./node-type-registry");
|
|
69
|
+
const rows_1 = require("./diagram-kit/rows");
|
|
70
|
+
const editing_1 = require("./diagram-kit/editing");
|
|
71
|
+
const styles_1 = require("./diagram-kit/styles");
|
|
72
|
+
const grid_binder_1 = require("./dashboard-kit/grid-binder");
|
|
73
|
+
const styles_2 = require("./dashboard-kit/styles");
|
|
74
|
+
const widgets_1 = require("./dashboard-kit/widgets");
|
|
75
|
+
const dashboard_1 = require("./dashboard-kit/dashboard");
|
|
76
|
+
/** True when the node is an ER entity card or a UML class card. */
|
|
77
|
+
function isDiagramKitCard(node) {
|
|
78
|
+
return node.getMetadata('kitEntity') !== undefined || node.getMetadata('kitClass') !== undefined;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Rebuild the widget spec the kit's renderers eat, from the node's own metadata.
|
|
82
|
+
* Returns null for a node the dashboard kit did not stamp — see the header on
|
|
83
|
+
* why the type name alone is not enough.
|
|
84
|
+
*/
|
|
85
|
+
function widgetSpecOf(node) {
|
|
86
|
+
var _a;
|
|
87
|
+
const kind = node.getMetadata('widgetKind');
|
|
88
|
+
if (kind === undefined)
|
|
89
|
+
return null;
|
|
90
|
+
const title = node.getMetadata('widgetTitle');
|
|
91
|
+
return Object.assign(Object.assign({ id: node.id, kind: kind }, (typeof title === 'string' ? { title } : {})), { data: ((_a = node.getMetadata('widgetSpec')) !== null && _a !== void 0 ? _a : {}), span: node.getMetadata('columnSpan'), rows: node.getMetadata('rowSpan') });
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Turn a saved document back into something `render()` can mount.
|
|
95
|
+
*
|
|
96
|
+
* ```ts
|
|
97
|
+
* const json = JSON.stringify(new DiagramSerializer().serialize(api.getModel()));
|
|
98
|
+
* // …later, in a fresh page:
|
|
99
|
+
* render(fromDocument(json), host);
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* Accepts the flat serializer form, the portable envelope, or the JSON string
|
|
103
|
+
* of either.
|
|
104
|
+
*/
|
|
105
|
+
function fromDocument(document, options = {}) {
|
|
106
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
107
|
+
const parsed = typeof document === 'string' ? parseDocument(document) : document;
|
|
108
|
+
const model = new engine_1.DiagramSerializer().deserialize(parsed);
|
|
109
|
+
const nodes = model.getNodes();
|
|
110
|
+
const groups = model.getGroups();
|
|
111
|
+
const boards = new Map();
|
|
112
|
+
// The kits inject their stylesheet from their builder; a load never calls one,
|
|
113
|
+
// so an un-styled card would come back as unstyled divs. Only for documents
|
|
114
|
+
// that actually contain that kit's nodes.
|
|
115
|
+
if (nodes.some(isDiagramKitCard))
|
|
116
|
+
(0, styles_1.ensureDiagramKitStyles)();
|
|
117
|
+
if (nodes.some((n) => widgetSpecOf(n) !== null))
|
|
118
|
+
(0, styles_2.ensureDashboardKitStyles)();
|
|
119
|
+
const paintWidget = (_a = options.renderWidget) !== null && _a !== void 0 ? _a : widgets_1.defaultWidgetRenderer;
|
|
120
|
+
// -- reconstruct the dashboard handle's context from the loaded model -------
|
|
121
|
+
// Every board group carries `dashboardBoard` geometry; its widget members
|
|
122
|
+
// carry `widgetSpec`/title/span/rows — the canonical, lossless source for
|
|
123
|
+
// widgets (the load.ts principle that non-widget nodes go back as LIVE models
|
|
124
|
+
// is untouched; only widgets are rebuilt from metadata, exactly as the
|
|
125
|
+
// renderCustomNode painter already does). That is enough to build the SAME
|
|
126
|
+
// handle dashboard() does, through the SAME builder — no drifting twin.
|
|
127
|
+
const dashGroups = groups.filter((g) => g.getMetadata('dashboardBoard') !== undefined);
|
|
128
|
+
const specById = new Map();
|
|
129
|
+
const viewOfWidget = new Map();
|
|
130
|
+
const ctxViews = dashGroups.map((g) => {
|
|
131
|
+
var _a, _b, _c;
|
|
132
|
+
const board = g.getMetadata('dashboardBoard');
|
|
133
|
+
const widgets = [];
|
|
134
|
+
for (const memberId of (_a = g.members) !== null && _a !== void 0 ? _a : []) {
|
|
135
|
+
const node = model.getNode(memberId);
|
|
136
|
+
const ws = node ? widgetSpecOf(node) : null;
|
|
137
|
+
if (!ws)
|
|
138
|
+
continue; // non-widget members (e.g. a nested slab group) are not widgets
|
|
139
|
+
specById.set(ws.id, ws);
|
|
140
|
+
viewOfWidget.set(ws.id, g.id);
|
|
141
|
+
widgets.push(ws);
|
|
142
|
+
}
|
|
143
|
+
return { id: g.id, name: g.name, widgets, columns: board.columns, width: (_b = g.size) === null || _b === void 0 ? void 0 : _b.width, height: (_c = g.size) === null || _c === void 0 ? void 0 : _c.height };
|
|
144
|
+
});
|
|
145
|
+
const firstBoard = (_b = dashGroups[0]) === null || _b === void 0 ? void 0 : _b.getMetadata('dashboardBoard');
|
|
146
|
+
// The active view is the one the save left ON camera (x≈0); the others were
|
|
147
|
+
// parked far off-screen by showView. Falls back to the first board when
|
|
148
|
+
// positions are ambiguous (e.g. a single view, or positions not restored).
|
|
149
|
+
const activeGroup = (_c = dashGroups.find((g) => g.position.x > -1000)) !== null && _c !== void 0 ? _c : dashGroups[0];
|
|
150
|
+
const ctx = {
|
|
151
|
+
views: ctxViews,
|
|
152
|
+
groups: new Map(dashGroups.map((g) => [g.id, g])),
|
|
153
|
+
// The SAME map the LoadedDiagramSpec exposes as `boards` — derived, not a copy.
|
|
154
|
+
binders: boards,
|
|
155
|
+
specById,
|
|
156
|
+
viewOfWidget,
|
|
157
|
+
hosts: new Map(),
|
|
158
|
+
renderWidget: paintWidget,
|
|
159
|
+
columns: (_d = firstBoard === null || firstBoard === void 0 ? void 0 : firstBoard.columns) !== null && _d !== void 0 ? _d : 12,
|
|
160
|
+
gap: (_e = firstBoard === null || firstBoard === void 0 ? void 0 : firstBoard.gap) !== null && _e !== void 0 ? _e : 8,
|
|
161
|
+
rowHeight: (_f = firstBoard === null || firstBoard === void 0 ? void 0 : firstBoard.baseRowHeight) !== null && _f !== void 0 ? _f : 130,
|
|
162
|
+
boardW: (_j = (_h = (_g = dashGroups[0]) === null || _g === void 0 ? void 0 : _g.size) === null || _h === void 0 ? void 0 : _h.width) !== null && _j !== void 0 ? _j : 1180,
|
|
163
|
+
boardH: (_m = (_l = (_k = dashGroups[0]) === null || _k === void 0 ? void 0 : _k.size) === null || _l === void 0 ? void 0 : _l.height) !== null && _m !== void 0 ? _m : 660,
|
|
164
|
+
// responsive is NOT in the document (a runtime seam), so it is deliberately
|
|
165
|
+
// absent from the round-trip; width/height/columns/gap/sizing/float/rtl are.
|
|
166
|
+
optionsBase: firstBoard
|
|
167
|
+
? {
|
|
168
|
+
columns: firstBoard.columns,
|
|
169
|
+
gap: firstBoard.gap,
|
|
170
|
+
rowHeight: firstBoard.baseRowHeight,
|
|
171
|
+
sizing: firstBoard.sizing,
|
|
172
|
+
float: firstBoard.float,
|
|
173
|
+
rtl: firstBoard.rtl,
|
|
174
|
+
width: (_p = (_o = dashGroups[0]) === null || _o === void 0 ? void 0 : _o.size) === null || _p === void 0 ? void 0 : _p.width,
|
|
175
|
+
height: (_r = (_q = dashGroups[0]) === null || _q === void 0 ? void 0 : _q.size) === null || _r === void 0 ? void 0 : _r.height,
|
|
176
|
+
}
|
|
177
|
+
: {},
|
|
178
|
+
active: (_s = activeGroup === null || activeGroup === void 0 ? void 0 : activeGroup.id) !== null && _s !== void 0 ? _s : 'main',
|
|
179
|
+
apiRef: null,
|
|
180
|
+
};
|
|
181
|
+
const handle = (0, dashboard_1.createDashboardHandle)(ctx);
|
|
182
|
+
const renderCustomNode = (node, host) => {
|
|
183
|
+
var _a, _b;
|
|
184
|
+
if (options.renderCustomNode)
|
|
185
|
+
return options.renderCustomNode(node, host);
|
|
186
|
+
// Prefer the ctx spec object so a later handle.update()/repaint() mutates the
|
|
187
|
+
// SAME object this initial paint used; fall back to a fresh rebuild for a
|
|
188
|
+
// loose widget node that belongs to no reconstructed board.
|
|
189
|
+
const widget = (_a = specById.get(node.id)) !== null && _a !== void 0 ? _a : widgetSpecOf(node);
|
|
190
|
+
if (widget) {
|
|
191
|
+
ctx.hosts.set(node.id, host); // captured so update()/repaint() can find the host
|
|
192
|
+
return paintWidget(widget, host);
|
|
193
|
+
}
|
|
194
|
+
(_b = (0, node_type_registry_1.getNodeType)(node.type)) === null || _b === void 0 ? void 0 : _b(node, host);
|
|
195
|
+
};
|
|
196
|
+
const finalize = (api) => {
|
|
197
|
+
var _a, _b, _c, _d;
|
|
198
|
+
const a = api;
|
|
199
|
+
if (!a)
|
|
200
|
+
return;
|
|
201
|
+
// -- groups ---------------------------------------------------------------
|
|
202
|
+
// Groups are not part of `nodes`/`edges`, so nothing else would carry them
|
|
203
|
+
// across. A dashboard without its view group is a set of loose widgets: no
|
|
204
|
+
// board frame, and nothing for the grid binder to bind to.
|
|
205
|
+
const live = (_a = a.getModel) === null || _a === void 0 ? void 0 : _a.call(a);
|
|
206
|
+
if (live) {
|
|
207
|
+
for (const group of groups) {
|
|
208
|
+
if (!((_b = live.getGroup) === null || _b === void 0 ? void 0 : _b.call(live, group.id)))
|
|
209
|
+
(_c = live.addGroup) === null || _c === void 0 ? void 0 : _c.call(live, group);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (options.interactive === false)
|
|
213
|
+
return;
|
|
214
|
+
// -- ER / UML -------------------------------------------------------------
|
|
215
|
+
const cards = nodes.filter(isDiagramKitCard);
|
|
216
|
+
if (cards.length > 0 && a.container) {
|
|
217
|
+
for (const node of cards) {
|
|
218
|
+
// The card draws its own selection ring; the node's resize handles would
|
|
219
|
+
// frame it a second time. `erDiagram().finalize` does this on the live
|
|
220
|
+
// model for the same reason — and behaviour is NOT in the document.
|
|
221
|
+
(_d = node.setBehavior) === null || _d === void 0 ? void 0 : _d.call(node, { resizable: false });
|
|
222
|
+
}
|
|
223
|
+
// `rowSelection: false` is recorded only when it is the non-default, so an
|
|
224
|
+
// ordinary document stays byte-identical to what it always was.
|
|
225
|
+
if (!cards.some((n) => n.getMetadata('kitRowSelection') === false)) {
|
|
226
|
+
(0, rows_1.bindRowInteractions)(a);
|
|
227
|
+
}
|
|
228
|
+
if (cards.some((n) => n.getMetadata('kitEditable') === true)) {
|
|
229
|
+
(0, editing_1.bindCardEditing)(a);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// -- dashboard boards -----------------------------------------------------
|
|
233
|
+
// Wire the render API into the handle's boxed cell, then bind each board.
|
|
234
|
+
// `bindDashboardGrid` sync()s on construction, so the handle's cellOf/toJSON
|
|
235
|
+
// work immediately — no camera move, no showView, so the paint is byte-for-
|
|
236
|
+
// byte what a boards-only load produced.
|
|
237
|
+
ctx.apiRef = a;
|
|
238
|
+
for (const group of groups) {
|
|
239
|
+
const board = group.getMetadata('dashboardBoard');
|
|
240
|
+
if (!board)
|
|
241
|
+
continue;
|
|
242
|
+
boards.set(group.id, (0, grid_binder_1.bindDashboardGrid)(a, group, Object.assign({}, board)));
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
return { nodes, edges: model.getLinks(), renderCustomNode, finalize, model, boards, handle };
|
|
246
|
+
}
|
|
247
|
+
function parseDocument(json) {
|
|
248
|
+
try {
|
|
249
|
+
return JSON.parse(json);
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
throw new Error(`fromDocument: not a saved diagram (${error.message})`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../../../../../libs/element/src/lib/load.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { NodeModel } from '@grafloria/engine';
|
|
2
|
+
/**
|
|
3
|
+
* The framework-free custom-node registry behind `<grafloria-flow>` and
|
|
4
|
+
* `Grafloria.registerNodeType()`.
|
|
5
|
+
*
|
|
6
|
+
* A "node type" is just a function that fills a host element the core handed us:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* Grafloria.registerNodeType('card', (node, el) => {
|
|
10
|
+
* el.innerHTML = `<div class="card">${node.data.title}</div>`;
|
|
11
|
+
* });
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* There is a second, zero-JavaScript path: a `<template data-node-type="card">`
|
|
15
|
+
* slotted inside the `<grafloria-flow>` element. The template is cloned per node and
|
|
16
|
+
* `[data-field="title"]` elements are filled from `node.data` — which is what
|
|
17
|
+
* lets a CMS, a notebook or a plain HTML page ship a custom node with no build
|
|
18
|
+
* step at all.
|
|
19
|
+
*/
|
|
20
|
+
/** Fills `element` with the visual for `node`. Called once per mounted node. */
|
|
21
|
+
export type NodeTypeRenderer = (node: NodeModel, element: HTMLElement) => void;
|
|
22
|
+
/** Register (or replace) a node type globally. */
|
|
23
|
+
export declare function registerNodeType(type: string, renderer: NodeTypeRenderer): void;
|
|
24
|
+
export declare function getNodeType(type: string): NodeTypeRenderer | undefined;
|
|
25
|
+
export declare function hasNodeType(type: string): boolean;
|
|
26
|
+
/** Drop a registration (mostly for tests). */
|
|
27
|
+
export declare function unregisterNodeType(type: string): void;
|
|
28
|
+
/** Every registered type name. */
|
|
29
|
+
export declare function registeredNodeTypes(): string[];
|
|
30
|
+
/**
|
|
31
|
+
* Render a node from a slotted `<template data-node-type="...">`.
|
|
32
|
+
*
|
|
33
|
+
* Clones the template's content into `element` and substitutes `node.data` into
|
|
34
|
+
* every `[data-field="key"]` descendant's text. Values are written with
|
|
35
|
+
* `textContent`, never `innerHTML`: a diagram's `data` is frequently
|
|
36
|
+
* user-supplied, and a template engine that injected raw HTML here would be an
|
|
37
|
+
* XSS vector in every host that embeds us.
|
|
38
|
+
*/
|
|
39
|
+
export declare function renderFromTemplate(template: HTMLTemplateElement, node: NodeModel, element: HTMLElement): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerNodeType = registerNodeType;
|
|
4
|
+
exports.getNodeType = getNodeType;
|
|
5
|
+
exports.hasNodeType = hasNodeType;
|
|
6
|
+
exports.unregisterNodeType = unregisterNodeType;
|
|
7
|
+
exports.registeredNodeTypes = registeredNodeTypes;
|
|
8
|
+
exports.renderFromTemplate = renderFromTemplate;
|
|
9
|
+
const registry = new Map();
|
|
10
|
+
/** Register (or replace) a node type globally. */
|
|
11
|
+
function registerNodeType(type, renderer) {
|
|
12
|
+
registry.set(type, renderer);
|
|
13
|
+
}
|
|
14
|
+
function getNodeType(type) {
|
|
15
|
+
return registry.get(type);
|
|
16
|
+
}
|
|
17
|
+
function hasNodeType(type) {
|
|
18
|
+
return registry.has(type);
|
|
19
|
+
}
|
|
20
|
+
/** Drop a registration (mostly for tests). */
|
|
21
|
+
function unregisterNodeType(type) {
|
|
22
|
+
registry.delete(type);
|
|
23
|
+
}
|
|
24
|
+
/** Every registered type name. */
|
|
25
|
+
function registeredNodeTypes() {
|
|
26
|
+
return [...registry.keys()];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Render a node from a slotted `<template data-node-type="...">`.
|
|
30
|
+
*
|
|
31
|
+
* Clones the template's content into `element` and substitutes `node.data` into
|
|
32
|
+
* every `[data-field="key"]` descendant's text. Values are written with
|
|
33
|
+
* `textContent`, never `innerHTML`: a diagram's `data` is frequently
|
|
34
|
+
* user-supplied, and a template engine that injected raw HTML here would be an
|
|
35
|
+
* XSS vector in every host that embeds us.
|
|
36
|
+
*/
|
|
37
|
+
function renderFromTemplate(template, node, element) {
|
|
38
|
+
const fragment = template.content.cloneNode(true);
|
|
39
|
+
const fields = fragment.querySelectorAll('[data-field]');
|
|
40
|
+
for (const field of Array.from(fields)) {
|
|
41
|
+
const key = field.getAttribute('data-field');
|
|
42
|
+
if (!key)
|
|
43
|
+
continue;
|
|
44
|
+
const value = key === 'id' ? node.id : node.data[key];
|
|
45
|
+
field.textContent = value === undefined || value === null ? '' : String(value);
|
|
46
|
+
}
|
|
47
|
+
element.textContent = '';
|
|
48
|
+
element.appendChild(fragment);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=node-type-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-type-registry.js","sourceRoot":"","sources":["../../../../../libs/element/src/lib/node-type-registry.ts"],"names":[],"mappings":";;AA2BA,4CAEC;AAED,kCAEC;AAED,kCAEC;AAGD,gDAEC;AAGD,kDAEC;AAWD,gDAiBC;AAnDD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA4B,CAAC;AAErD,kDAAkD;AAClD,SAAgB,gBAAgB,CAAC,IAAY,EAAE,QAA0B;IACvE,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,SAAgB,WAAW,CAAC,IAAY;IACtC,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,SAAgB,WAAW,CAAC,IAAY;IACtC,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,8CAA8C;AAC9C,SAAgB,kBAAkB,CAAC,IAAY;IAC7C,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,kCAAkC;AAClC,SAAgB,mBAAmB;IACjC,OAAO,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,kBAAkB,CAChC,QAA6B,EAC7B,IAAe,EACf,OAAoB;IAEpB,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAqB,CAAC;IAEtE,MAAM,MAAM,GAAG,QAAQ,CAAC,gBAAgB,CAAc,cAAc,CAAC,CAAC;IACtE,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QAC7C,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,KAAK,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAE,IAAI,CAAC,IAAgC,CAAC,GAAG,CAAC,CAAC;QACnF,KAAK,CAAC,WAAW,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjF,CAAC;IAED,OAAO,CAAC,WAAW,GAAG,EAAE,CAAC;IACzB,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC"}
|