@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,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"}