@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.
Files changed (61) hide show
  1. package/package.json +41 -0
  2. package/src/index.d.ts +87 -0
  3. package/src/index.js +547 -0
  4. package/src/index.js.map +1 -0
  5. package/src/lib/dashboard-kit/dashboard.d.ts +345 -0
  6. package/src/lib/dashboard-kit/dashboard.js +594 -0
  7. package/src/lib/dashboard-kit/dashboard.js.map +1 -0
  8. package/src/lib/dashboard-kit/grid-binder.d.ts +277 -0
  9. package/src/lib/dashboard-kit/grid-binder.js +1635 -0
  10. package/src/lib/dashboard-kit/grid-binder.js.map +1 -0
  11. package/src/lib/dashboard-kit/grid-mapping.d.ts +141 -0
  12. package/src/lib/dashboard-kit/grid-mapping.js +176 -0
  13. package/src/lib/dashboard-kit/grid-mapping.js.map +1 -0
  14. package/src/lib/dashboard-kit/index.d.ts +5 -0
  15. package/src/lib/dashboard-kit/index.js +33 -0
  16. package/src/lib/dashboard-kit/index.js.map +1 -0
  17. package/src/lib/dashboard-kit/styles.d.ts +25 -0
  18. package/src/lib/dashboard-kit/styles.js +203 -0
  19. package/src/lib/dashboard-kit/styles.js.map +1 -0
  20. package/src/lib/dashboard-kit/widgets.d.ts +112 -0
  21. package/src/lib/dashboard-kit/widgets.js +389 -0
  22. package/src/lib/dashboard-kit/widgets.js.map +1 -0
  23. package/src/lib/diagram-kit/card.d.ts +75 -0
  24. package/src/lib/diagram-kit/card.js +209 -0
  25. package/src/lib/diagram-kit/card.js.map +1 -0
  26. package/src/lib/diagram-kit/editing.d.ts +54 -0
  27. package/src/lib/diagram-kit/editing.js +289 -0
  28. package/src/lib/diagram-kit/editing.js.map +1 -0
  29. package/src/lib/diagram-kit/er.d.ts +73 -0
  30. package/src/lib/diagram-kit/er.js +163 -0
  31. package/src/lib/diagram-kit/er.js.map +1 -0
  32. package/src/lib/diagram-kit/handles.d.ts +181 -0
  33. package/src/lib/diagram-kit/handles.js +325 -0
  34. package/src/lib/diagram-kit/handles.js.map +1 -0
  35. package/src/lib/diagram-kit/index.d.ts +8 -0
  36. package/src/lib/diagram-kit/index.js +38 -0
  37. package/src/lib/diagram-kit/index.js.map +1 -0
  38. package/src/lib/diagram-kit/rows.d.ts +53 -0
  39. package/src/lib/diagram-kit/rows.js +147 -0
  40. package/src/lib/diagram-kit/rows.js.map +1 -0
  41. package/src/lib/diagram-kit/styles.d.ts +18 -0
  42. package/src/lib/diagram-kit/styles.js +114 -0
  43. package/src/lib/diagram-kit/styles.js.map +1 -0
  44. package/src/lib/diagram-kit/uml.d.ts +59 -0
  45. package/src/lib/diagram-kit/uml.js +138 -0
  46. package/src/lib/diagram-kit/uml.js.map +1 -0
  47. package/src/lib/diagram-kit/update.d.ts +133 -0
  48. package/src/lib/diagram-kit/update.js +251 -0
  49. package/src/lib/diagram-kit/update.js.map +1 -0
  50. package/src/lib/grafloria-flow-element.d.ts +48 -0
  51. package/src/lib/grafloria-flow-element.js +271 -0
  52. package/src/lib/grafloria-flow-element.js.map +1 -0
  53. package/src/lib/grafloria.d.ts +61 -0
  54. package/src/lib/grafloria.js +72 -0
  55. package/src/lib/grafloria.js.map +1 -0
  56. package/src/lib/load.d.ts +72 -0
  57. package/src/lib/load.js +255 -0
  58. package/src/lib/load.js.map +1 -0
  59. package/src/lib/node-type-registry.d.ts +39 -0
  60. package/src/lib/node-type-registry.js +50 -0
  61. package/src/lib/node-type-registry.js.map +1 -0
@@ -0,0 +1,271 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GrafloriaFlowElement = exports.GRAFLORIA_EVENTS = void 0;
4
+ exports.defineGrafloriaFlow = defineGrafloriaFlow;
5
+ const renderer_1 = require("@grafloria/renderer");
6
+ const node_type_registry_1 = require("./node-type-registry");
7
+ /**
8
+ * `<grafloria-flow>` — the universal embed.
9
+ *
10
+ * React Flow serves React. ngx-vflow serves Angular. Each is a wall around one
11
+ * framework. A custom element has no wall: Vue, Svelte, Solid, Lit, Alpine,
12
+ * plain HTML, a CMS block, a Jupyter/Observable cell and a static site all speak
13
+ * "HTML element with attributes and events". This is the piece that lets Grafloria
14
+ * reach the long tail those libraries cannot.
15
+ *
16
+ * ```html
17
+ * <grafloria-flow theme="dark" fit-view
18
+ * nodes='[{"id":"a","position":{"x":0,"y":0},"label":"A"}]'
19
+ * edges='[{"source":"a","target":"b"}]'>
20
+ * <template data-node-type="card">
21
+ * <div class="card"><h4 data-field="title"></h4></div>
22
+ * </template>
23
+ * </grafloria-flow>
24
+ *
25
+ * <script>
26
+ * document.querySelector('grafloria-flow')
27
+ * .addEventListener('grafloria-connect', e => console.log(e.detail.link));
28
+ * </script>
29
+ * ```
30
+ *
31
+ * Rich data goes in as PROPERTIES (`el.nodes = [...]`) and simple data as
32
+ * ATTRIBUTES (JSON strings) — the standard custom-element contract that every
33
+ * framework's template binding already targets:
34
+ * `:nodes` in Vue, `nodes={...}` in Svelte/Solid, `[attr.nodes]` in Angular.
35
+ *
36
+ * Everything it does is delegation. There is no diagram logic in this file.
37
+ */
38
+ const THEMES = {
39
+ light: renderer_1.LIGHT_THEME,
40
+ dark: renderer_1.DARK_THEME,
41
+ };
42
+ /** Events emitted on the element. All bubble and cross shadow boundaries. */
43
+ exports.GRAFLORIA_EVENTS = {
44
+ ready: 'grafloria-ready',
45
+ nodesChange: 'grafloria-nodes-change',
46
+ edgesChange: 'grafloria-edges-change',
47
+ selectionChange: 'grafloria-selection-change',
48
+ connect: 'grafloria-connect',
49
+ nodeClick: 'grafloria-node-click',
50
+ edgeClick: 'grafloria-edge-click',
51
+ viewportChange: 'grafloria-viewport-change',
52
+ };
53
+ // wave11/gallery BUG FIX — worker-safe base class.
54
+ //
55
+ // `class GrafloriaFlowElement extends HTMLElement` evaluates `HTMLElement` at MODULE
56
+ // LOAD, so merely IMPORTING this package threw `HTMLElement is not defined` in any
57
+ // context without a DOM — a Web Worker, or Node. The package doc already promised
58
+ // the import is "a no-op on the server", and `defineGrafloriaFlow()` guards
59
+ // `customElements`; but the class declaration itself did not, so the promise was
60
+ // only half true. It matters concretely: the off-thread-layout demo runs the
61
+ // engine's `serveLayout` INSIDE a real Worker by importing this very bundle, which
62
+ // is impossible if the top-level class reference throws. The element only ever
63
+ // EXTENDS the real HTMLElement in a browser (a worker never instantiates it), so a
64
+ // guarded base is behaviourally identical on the client and merely importable off it.
65
+ const HTMLElementBase = typeof HTMLElement !== 'undefined'
66
+ ? HTMLElement
67
+ : class {
68
+ };
69
+ class GrafloriaFlowElement extends HTMLElementBase {
70
+ constructor() {
71
+ super(...arguments);
72
+ this.instance = null;
73
+ this.canvas = null;
74
+ this._nodes = [];
75
+ this._edges = [];
76
+ this.connected = false;
77
+ }
78
+ static get observedAttributes() {
79
+ return [
80
+ 'nodes',
81
+ 'edges',
82
+ 'theme',
83
+ 'fit-view',
84
+ 'readonly',
85
+ 'zoom',
86
+ 'min-zoom',
87
+ 'max-zoom',
88
+ 'pan',
89
+ 'wheel-zoom',
90
+ ];
91
+ }
92
+ // -- properties (the rich path) ---------------------------------------------
93
+ get nodes() {
94
+ return this._nodes;
95
+ }
96
+ set nodes(value) {
97
+ var _a;
98
+ this._nodes = value !== null && value !== void 0 ? value : [];
99
+ (_a = this.instance) === null || _a === void 0 ? void 0 : _a.setNodes(this._nodes);
100
+ }
101
+ get edges() {
102
+ return this._edges;
103
+ }
104
+ set edges(value) {
105
+ var _a;
106
+ this._edges = value !== null && value !== void 0 ? value : [];
107
+ (_a = this.instance) === null || _a === void 0 ? void 0 : _a.setEdges(this._edges);
108
+ }
109
+ /** The headless instance — the escape hatch to everything else. */
110
+ get diagram() {
111
+ return this.instance;
112
+ }
113
+ // -- lifecycle ---------------------------------------------------------------
114
+ connectedCallback() {
115
+ if (this.connected)
116
+ return;
117
+ this.connected = true;
118
+ // Attributes may have been parsed before we upgraded.
119
+ this.readAttributeModel();
120
+ // Light DOM, not shadow DOM: the diagram's stylesheet is injected into
121
+ // <head> and its CSS variables cascade — a shadow root would cut both off,
122
+ // and hosts routinely want to style nodes from their own stylesheet.
123
+ this.canvas = document.createElement('div');
124
+ this.canvas.className = 'grafloria-flow-canvas';
125
+ this.canvas.setAttribute('style', 'position:relative;width:100%;height:100%');
126
+ this.appendChild(this.canvas);
127
+ if (!this.style.display)
128
+ this.style.display = 'block';
129
+ this.instance = (0, renderer_1.createDiagram)(this.canvas, this.buildOptions());
130
+ this.wireEvents(this.instance);
131
+ }
132
+ disconnectedCallback() {
133
+ var _a, _b;
134
+ this.connected = false;
135
+ (_a = this.instance) === null || _a === void 0 ? void 0 : _a.dispose();
136
+ this.instance = null;
137
+ (_b = this.canvas) === null || _b === void 0 ? void 0 : _b.remove();
138
+ this.canvas = null;
139
+ }
140
+ attributeChangedCallback(name, previous, next) {
141
+ var _a, _b;
142
+ if (previous === next)
143
+ return;
144
+ switch (name) {
145
+ case 'nodes':
146
+ this._nodes = parseJsonAttribute(next, []);
147
+ (_a = this.instance) === null || _a === void 0 ? void 0 : _a.setNodes(this._nodes);
148
+ return;
149
+ case 'edges':
150
+ this._edges = parseJsonAttribute(next, []);
151
+ (_b = this.instance) === null || _b === void 0 ? void 0 : _b.setEdges(this._edges);
152
+ return;
153
+ case 'theme':
154
+ if (this.instance)
155
+ this.instance.setTheme(this.resolveTheme());
156
+ return;
157
+ case 'fit-view':
158
+ if (this.instance && next !== null)
159
+ this.instance.fitView();
160
+ return;
161
+ case 'zoom':
162
+ if (this.instance && next !== null)
163
+ this.instance.viewport.setZoom(Number(next));
164
+ return;
165
+ default:
166
+ // pan / wheel-zoom / readonly / min-zoom / max-zoom are read at mount:
167
+ // they configure the event binder, which is created once. Changing them
168
+ // afterwards is rare enough that we do not tear the instance down.
169
+ return;
170
+ }
171
+ }
172
+ // -- API ---------------------------------------------------------------------
173
+ fitView(padding) {
174
+ var _a;
175
+ (_a = this.instance) === null || _a === void 0 ? void 0 : _a.fitView(padding);
176
+ }
177
+ // -- internals ---------------------------------------------------------------
178
+ buildOptions() {
179
+ return {
180
+ nodes: this._nodes,
181
+ edges: this._edges,
182
+ theme: this.resolveTheme(),
183
+ fitView: this.hasAttribute('fit-view'),
184
+ readonly: this.hasAttribute('readonly'),
185
+ enablePan: this.getAttribute('pan') !== 'false',
186
+ enableZoom: this.getAttribute('wheel-zoom') !== 'false',
187
+ zoom: this.hasAttribute('zoom') ? Number(this.getAttribute('zoom')) : undefined,
188
+ minZoom: this.hasAttribute('min-zoom')
189
+ ? Number(this.getAttribute('min-zoom'))
190
+ : undefined,
191
+ maxZoom: this.hasAttribute('max-zoom')
192
+ ? Number(this.getAttribute('max-zoom'))
193
+ : undefined,
194
+ renderCustomNode: (node, element) => this.renderCustomNode(node, element),
195
+ };
196
+ }
197
+ /**
198
+ * Custom nodes, two ways and no framework: a registered renderer
199
+ * (`Grafloria.registerNodeType`), or a slotted `<template data-node-type="…">`.
200
+ */
201
+ renderCustomNode(node, element) {
202
+ const renderer = (0, node_type_registry_1.getNodeType)(node.type);
203
+ if (renderer) {
204
+ renderer(node, element);
205
+ return;
206
+ }
207
+ const template = this.querySelector(`template[data-node-type="${cssEscape(node.type)}"]`);
208
+ if (template) {
209
+ (0, node_type_registry_1.renderFromTemplate)(template, node, element);
210
+ return;
211
+ }
212
+ // Nothing registered: leave the host empty rather than throwing inside a
213
+ // render. The node still exists, is selectable and is draggable.
214
+ }
215
+ resolveTheme() {
216
+ var _a, _b;
217
+ return (_b = THEMES[(_a = this.getAttribute('theme')) !== null && _a !== void 0 ? _a : 'light']) !== null && _b !== void 0 ? _b : renderer_1.LIGHT_THEME;
218
+ }
219
+ readAttributeModel() {
220
+ if (this._nodes.length === 0 && this.hasAttribute('nodes')) {
221
+ this._nodes = parseJsonAttribute(this.getAttribute('nodes'), []);
222
+ }
223
+ if (this._edges.length === 0 && this.hasAttribute('edges')) {
224
+ this._edges = parseJsonAttribute(this.getAttribute('edges'), []);
225
+ }
226
+ }
227
+ /** Instance events → DOM CustomEvents. `composed` so they escape a shadow root. */
228
+ wireEvents(instance) {
229
+ const forward = (type, detail) => {
230
+ this.dispatchEvent(new CustomEvent(type, { detail, bubbles: true, composed: true }));
231
+ };
232
+ instance.on('ready', () => forward(exports.GRAFLORIA_EVENTS.ready, { diagram: instance }));
233
+ instance.on('nodes:change', (payload) => forward(exports.GRAFLORIA_EVENTS.nodesChange, payload));
234
+ instance.on('edges:change', (payload) => forward(exports.GRAFLORIA_EVENTS.edgesChange, payload));
235
+ instance.on('selection:change', (payload) => forward(exports.GRAFLORIA_EVENTS.selectionChange, payload));
236
+ instance.on('connect', (payload) => forward(exports.GRAFLORIA_EVENTS.connect, payload));
237
+ instance.on('node:click', (payload) => forward(exports.GRAFLORIA_EVENTS.nodeClick, payload));
238
+ instance.on('edge:click', (payload) => forward(exports.GRAFLORIA_EVENTS.edgeClick, payload));
239
+ instance.on('viewport:change', (payload) => forward(exports.GRAFLORIA_EVENTS.viewportChange, payload));
240
+ }
241
+ }
242
+ exports.GrafloriaFlowElement = GrafloriaFlowElement;
243
+ /** JSON attribute → value. A malformed attribute must not take the page down. */
244
+ function parseJsonAttribute(raw, fallback) {
245
+ if (!raw)
246
+ return fallback;
247
+ try {
248
+ return JSON.parse(raw);
249
+ }
250
+ catch (_a) {
251
+ console.warn('[grafloria-flow] ignoring malformed JSON attribute:', raw);
252
+ return fallback;
253
+ }
254
+ }
255
+ /** Minimal CSS.escape for the attribute selector (jsdom/older browsers lack it). */
256
+ function cssEscape(value) {
257
+ return value.replace(/["\\]/g, '\\$&');
258
+ }
259
+ /**
260
+ * Register the element. Idempotent, and safe to call on the server (where
261
+ * `customElements` does not exist) — which is what lets a bundle be imported
262
+ * from an SSR entry point without a `typeof window` dance at every call site.
263
+ */
264
+ function defineGrafloriaFlow(tagName = 'grafloria-flow') {
265
+ if (typeof customElements === 'undefined')
266
+ return;
267
+ if (customElements.get(tagName))
268
+ return;
269
+ customElements.define(tagName, GrafloriaFlowElement);
270
+ }
271
+ //# sourceMappingURL=grafloria-flow-element.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grafloria-flow-element.js","sourceRoot":"","sources":["../../../../../libs/element/src/lib/grafloria-flow-element.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import type { CreateDiagramOptions, DiagramInstance, EdgeSpec, NodeSpec, StaticRenderOptions, StaticRenderResult } from '@grafloria/renderer';
2
+ import { defineGrafloriaFlow } from './grafloria-flow-element';
3
+ import { registerNodeType, registeredNodeTypes } from './node-type-registry';
4
+ import type { NodeTypeRenderer } from './node-type-registry';
5
+ /**
6
+ * `Grafloria` — the Mermaid-shaped top-level API.
7
+ *
8
+ * Mermaid's moat is not its renderer, it is `mermaid.render(id, text)`: one
9
+ * function, no build step, no framework. That is why it shows up in GitHub
10
+ * comments, in docs sites, in notebooks and in every CMS. This is the same
11
+ * surface for a diagram that is *interactive*:
12
+ *
13
+ * ```html
14
+ * <script type="module">
15
+ * import { Grafloria } from 'https://esm.sh/@grafloria/element';
16
+ *
17
+ * Grafloria.registerNodeType('card', (node, el) => {
18
+ * el.innerHTML = `<div class="card">${node.data.title}</div>`;
19
+ * });
20
+ *
21
+ * const diagram = Grafloria.render(
22
+ * { nodes: [...], edges: [...] },
23
+ * document.getElementById('chart')
24
+ * );
25
+ * diagram.on('connect', ({ link }) => save(link));
26
+ * </script>
27
+ * ```
28
+ *
29
+ * `render()` returns the same `DiagramInstance` every wrapper binds to, so the
30
+ * "tiny API" is not a lesser one — it is the whole engine, addressed in one call.
31
+ */
32
+ /** What `Grafloria.render()` accepts: an object spec, or the JSON string of one. */
33
+ export interface DiagramSpec {
34
+ nodes?: NodeSpec[];
35
+ edges?: EdgeSpec[];
36
+ }
37
+ export type RenderSpec = DiagramSpec | string;
38
+ export type RenderOptions = Omit<CreateDiagramOptions, 'nodes' | 'edges'>;
39
+ /**
40
+ * Mount `spec` into `target` and return the live instance.
41
+ *
42
+ * `target` may be an element or a CSS selector. Custom nodes (`custom: true`)
43
+ * are rendered by the types registered with {@link registerNodeType}.
44
+ *
45
+ * SCOPE, stated plainly: `spec` is data (an object or its JSON), not a Mermaid-
46
+ * style text DSL. The engine does have a DSL, but wiring it in is a separate
47
+ * card — `render()` is the embedding surface, not a parser.
48
+ */
49
+ export declare function render(spec: RenderSpec, target: HTMLElement | string, options?: RenderOptions): DiagramInstance;
50
+ /** Server-side render (Card 6). Re-exported so the tiny API is self-contained. */
51
+ export declare function renderStatic(options?: StaticRenderOptions): StaticRenderResult;
52
+ /** The namespace object, for `import { Grafloria }` and for `<script>` globals. */
53
+ export declare const Grafloria: {
54
+ render: typeof render;
55
+ renderStatic: typeof renderStatic;
56
+ registerNodeType: typeof registerNodeType;
57
+ registeredNodeTypes: typeof registeredNodeTypes;
58
+ /** Register `<grafloria-flow>` (called for you when you import this package). */
59
+ define: typeof defineGrafloriaFlow;
60
+ };
61
+ export type { NodeTypeRenderer };
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Grafloria = void 0;
4
+ exports.render = render;
5
+ exports.renderStatic = renderStatic;
6
+ const renderer_1 = require("@grafloria/renderer");
7
+ const grafloria_flow_element_1 = require("./grafloria-flow-element");
8
+ const node_type_registry_1 = require("./node-type-registry");
9
+ /**
10
+ * Mount `spec` into `target` and return the live instance.
11
+ *
12
+ * `target` may be an element or a CSS selector. Custom nodes (`custom: true`)
13
+ * are rendered by the types registered with {@link registerNodeType}.
14
+ *
15
+ * SCOPE, stated plainly: `spec` is data (an object or its JSON), not a Mermaid-
16
+ * style text DSL. The engine does have a DSL, but wiring it in is a separate
17
+ * card — `render()` is the embedding surface, not a parser.
18
+ */
19
+ function render(spec, target, options = {}) {
20
+ var _a, _b, _c, _d;
21
+ const element = typeof target === 'string'
22
+ ? document.querySelector(target)
23
+ : target;
24
+ if (!element) {
25
+ throw new Error(`Grafloria.render: no element matched ${JSON.stringify(target)}`);
26
+ }
27
+ const parsed = typeof spec === 'string' ? parseSpec(spec) : spec;
28
+ const instance = (0, renderer_1.createDiagram)(element, Object.assign(Object.assign({}, options), { nodes: (_a = parsed.nodes) !== null && _a !== void 0 ? _a : [], edges: (_b = parsed.edges) !== null && _b !== void 0 ? _b : [],
29
+ // Wire the global registry in, so `registerNodeType` works for the tiny API
30
+ // exactly as it does for `<grafloria-flow>` — unless the caller supplies their
31
+ // own. A KIT SPEC may also carry its own painter (dashboard() does: every
32
+ // widget is a custom HTML node), and it must be honoured — otherwise the
33
+ // documented one-liner `render(dashboard({…}), host)` mounts a board whose
34
+ // widgets never paint. Precedence: explicit option > spec > registry.
35
+ renderCustomNode: (_d = (_c = options.renderCustomNode) !== null && _c !== void 0 ? _c : parsed.renderCustomNode) !== null && _d !== void 0 ? _d : ((node, host) => { var _a; return (_a = (0, node_type_registry_1.getNodeType)(node.type)) === null || _a === void 0 ? void 0 : _a(node, host); }) }));
36
+ // Diagram-kit specs (erDiagram/umlDiagram) carry a `finalize(api)` for the
37
+ // post-render wiring that needs the LIVE instance — row interactions,
38
+ // multiplicity chips. Auto-run it so a kit diagram is fully wired from one
39
+ // render() call; finalize is idempotent, so a caller may still call it too.
40
+ const maybeFinalize = spec.finalize;
41
+ if (typeof maybeFinalize === 'function') {
42
+ try {
43
+ maybeFinalize(instance);
44
+ }
45
+ catch (_e) {
46
+ /* a kit's finalize must never break the mount */
47
+ }
48
+ }
49
+ return instance;
50
+ }
51
+ /** Server-side render (Card 6). Re-exported so the tiny API is self-contained. */
52
+ function renderStatic(options = {}) {
53
+ return (0, renderer_1.renderToStaticSVG)(options);
54
+ }
55
+ function parseSpec(spec) {
56
+ try {
57
+ return JSON.parse(spec);
58
+ }
59
+ catch (error) {
60
+ throw new Error(`Grafloria.render: spec must be an object or a JSON string (${error.message})`);
61
+ }
62
+ }
63
+ /** The namespace object, for `import { Grafloria }` and for `<script>` globals. */
64
+ exports.Grafloria = {
65
+ render,
66
+ renderStatic,
67
+ registerNodeType: node_type_registry_1.registerNodeType,
68
+ registeredNodeTypes: node_type_registry_1.registeredNodeTypes,
69
+ /** Register `<grafloria-flow>` (called for you when you import this package). */
70
+ define: grafloria_flow_element_1.defineGrafloriaFlow,
71
+ };
72
+ //# sourceMappingURL=grafloria.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grafloria.js","sourceRoot":"","sources":["../../../../../libs/element/src/lib/grafloria.ts"],"names":[],"mappings":";;;AA6DA,wBA8CC;AAGD,oCAEC;AAhHD,kDAAuE;AASvE,qEAA+D;AAC/D,6DAA0F;AAyC1F;;;;;;;;;GASG;AACH,SAAgB,MAAM,CACpB,IAAgB,EAChB,MAA4B,EAC5B,UAAyB,EAAE;;IAE3B,MAAM,OAAO,GACX,OAAO,MAAM,KAAK,QAAQ;QACxB,CAAC,CAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAwB;QACxD,CAAC,CAAC,MAAM,CAAC;IAEb,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,MAAM,GAAgB,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE9E,MAAM,QAAQ,GAAG,IAAA,wBAAa,EAAC,OAAO,kCACjC,OAAO,KACV,KAAK,EAAE,MAAA,MAAM,CAAC,KAAK,mCAAI,EAAE,EACzB,KAAK,EAAE,MAAA,MAAM,CAAC,KAAK,mCAAI,EAAE;QACzB,4EAA4E;QAC5E,+EAA+E;QAC/E,0EAA0E;QAC1E,yEAAyE;QACzE,2EAA2E;QAC3E,sEAAsE;QACtE,gBAAgB,EACd,MAAA,MAAA,OAAO,CAAC,gBAAgB,mCACvB,MAAmE,CAAC,gBAAgB,mCACrF,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,WAAC,OAAA,MAAA,IAAA,gCAAW,EAAC,IAAI,CAAC,IAAI,CAAC,0CAAG,IAAI,EAAE,IAAI,CAAC,CAAA,EAAA,CAAC,IACxD,CAAC;IAEH,2EAA2E;IAC3E,sEAAsE;IACtE,2EAA2E;IAC3E,4EAA4E;IAC5E,MAAM,aAAa,GAAI,IAA8C,CAAC,QAAQ,CAAC;IAC/E,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;QAAC,WAAM,CAAC;YACP,iDAAiD;QACnD,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,kFAAkF;AAClF,SAAgB,YAAY,CAAC,UAA+B,EAAE;IAC5D,OAAO,IAAA,4BAAiB,EAAC,OAAO,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAC;IACzC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,8DAA+D,KAAe,CAAC,OAAO,GAAG,CAC1F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,mFAAmF;AACtE,QAAA,SAAS,GAAG;IACvB,MAAM;IACN,YAAY;IACZ,gBAAgB,EAAhB,qCAAgB;IAChB,mBAAmB,EAAnB,wCAAmB;IACnB,iFAAiF;IACjF,MAAM,EAAE,4CAAmB;CAC5B,CAAC"}
@@ -0,0 +1,72 @@
1
+ import type { DiagramDocumentEnvelope, DiagramModel, LinkModel, NodeModel, SerializedDiagramData } from '@grafloria/engine';
2
+ import { type DashboardGridHandle } from './dashboard-kit/grid-binder';
3
+ import { type WidgetRenderer } from './dashboard-kit/widgets';
4
+ import { type DashboardHandle } from './dashboard-kit/dashboard';
5
+ /** Anything `DiagramSerializer.deserialize()` accepts, or the JSON string of it. */
6
+ export type SavedDiagram = SerializedDiagramData | DiagramDocumentEnvelope | Record<string, unknown> | string;
7
+ export interface FromDocumentOptions {
8
+ /**
9
+ * The app's own widget painter — the same function it passed to
10
+ * `dashboard({ renderWidget })`. A board authored with a custom painter must
11
+ * be RELOADED with it, or the reload silently drops the app's chrome.
12
+ */
13
+ renderWidget?: WidgetRenderer;
14
+ /** Full override of the custom-node painter. Outranks everything. */
15
+ renderCustomNode?: (node: NodeModel, host: HTMLElement) => void;
16
+ /**
17
+ * Re-attach kit interaction wiring (row selection, in-canvas editing, the
18
+ * dashboard grid binder). Default true — a loaded diagram should behave like
19
+ * the one that was saved. Pass false for a read-only viewer.
20
+ */
21
+ interactive?: boolean;
22
+ }
23
+ /** What {@link fromDocument} returns: a `render()` spec, plus the way back in. */
24
+ export interface LoadedDiagramSpec {
25
+ nodes: NodeModel[];
26
+ edges: LinkModel[];
27
+ renderCustomNode: (node: NodeModel, host: HTMLElement) => void;
28
+ finalize: (api: unknown) => void;
29
+ /** The deserialized model — the escape hatch, available before any render. */
30
+ readonly model: DiagramModel;
31
+ /**
32
+ * Live grid binders for the boards `finalize()` re-attached, keyed by group
33
+ * id. Empty for a document that is not a dashboard.
34
+ *
35
+ * This is the SAME Map instance the handle drives (`handle.binderOf` returns
36
+ * from it), so the two can never disagree — `boards` is now derived from the
37
+ * handle's own binders rather than a parallel copy.
38
+ */
39
+ readonly boards: Map<string, DashboardGridHandle>;
40
+ /**
41
+ * The dashboard toolbar handle over the reloaded board(s) — the SAME
42
+ * `DashboardHandle` `dashboard()` returns, built by the one shared builder so
43
+ * it cannot drift from the authoring surface: addWidget/showView/setSizing/
44
+ * setColumns/toJSON/exportIds and the widget handles, all live on the reload.
45
+ *
46
+ * INERT (empty `views`, every op a no-op) for a document that is not a
47
+ * dashboard — an ER/UML load carries no board, so an honest empty handle
48
+ * beats one that pretends a class card is a widget.
49
+ *
50
+ * Two carried limits, both because the datum is not in the document:
51
+ * - `responsive` is a runtime seam, never serialised, so a reloaded board is
52
+ * fixed at its saved column count until `setColumns`/`responsive` is
53
+ * re-supplied; `toJSON()` therefore omits it.
54
+ * - `renderWidget`/`onLayoutChange` are functions and cannot serialise —
55
+ * pass `renderWidget` to `fromDocument({ renderWidget })` to reattach the
56
+ * app's own painter, exactly as `dashboard({ renderWidget })` did.
57
+ */
58
+ readonly handle: DashboardHandle;
59
+ }
60
+ /**
61
+ * Turn a saved document back into something `render()` can mount.
62
+ *
63
+ * ```ts
64
+ * const json = JSON.stringify(new DiagramSerializer().serialize(api.getModel()));
65
+ * // …later, in a fresh page:
66
+ * render(fromDocument(json), host);
67
+ * ```
68
+ *
69
+ * Accepts the flat serializer form, the portable envelope, or the JSON string
70
+ * of either.
71
+ */
72
+ export declare function fromDocument(document: SavedDiagram, options?: FromDocumentOptions): LoadedDiagramSpec;