@grafloria/element 0.3.23 → 0.4.1
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/README.md +9 -7
- package/package.json +7 -9
- package/src/index.d.ts +16 -16
- package/src/index.js +58 -339
- package/src/lib/dashboard-kit/dashboard.d.ts +1 -1
- package/src/lib/dashboard-kit/dashboard.js +22 -26
- package/src/lib/dashboard-kit/grid-binder.d.ts +1 -1
- package/src/lib/dashboard-kit/grid-binder.js +62 -65
- package/src/lib/dashboard-kit/grid-mapping.js +14 -26
- package/src/lib/dashboard-kit/index.d.ts +5 -5
- package/src/lib/dashboard-kit/index.js +5 -30
- package/src/lib/dashboard-kit/styles.js +4 -8
- package/src/lib/dashboard-kit/widgets.d.ts +1 -1
- package/src/lib/dashboard-kit/widgets.js +16 -26
- package/src/lib/diagram-kit/card.d.ts +2 -2
- package/src/lib/diagram-kit/card.js +22 -32
- package/src/lib/diagram-kit/editing.js +15 -20
- package/src/lib/diagram-kit/er.d.ts +1 -1
- package/src/lib/diagram-kit/er.js +15 -18
- package/src/lib/diagram-kit/handles.d.ts +4 -4
- package/src/lib/diagram-kit/handles.js +16 -29
- package/src/lib/diagram-kit/index.d.ts +10 -10
- package/src/lib/diagram-kit/index.js +10 -50
- package/src/lib/diagram-kit/join-guidance.js +9 -18
- package/src/lib/diagram-kit/rows.js +1 -4
- package/src/lib/diagram-kit/styles.js +4 -8
- package/src/lib/diagram-kit/uml.js +10 -13
- package/src/lib/diagram-kit/update.d.ts +1 -1
- package/src/lib/diagram-kit/update.js +19 -26
- package/src/lib/grafloria-flow-element.js +19 -24
- package/src/lib/grafloria.d.ts +4 -4
- package/src/lib/grafloria.js +12 -17
- package/src/lib/load.d.ts +3 -3
- package/src/lib/load.js +19 -22
- package/src/lib/node-type-registry.js +6 -14
- package/src/lib/stencil-kit/builders.js +4 -10
- package/src/lib/stencil-kit/card-builders.js +14 -17
- package/src/lib/stencil-kit/index.d.ts +7 -7
- package/src/lib/stencil-kit/index.js +6 -16
- package/src/lib/stencil-kit/palette.js +14 -17
- package/src/lib/stencil-kit/shape-data.js +25 -28
- package/src/lib/stencil-kit/styles.js +1 -4
- package/esm/src/index.js +0 -295
- package/esm/src/lib/dashboard-kit/dashboard.js +0 -590
- package/esm/src/lib/dashboard-kit/grid-binder.js +0 -1633
- package/esm/src/lib/dashboard-kit/grid-mapping.js +0 -164
- package/esm/src/lib/dashboard-kit/index.js +0 -8
- package/esm/src/lib/dashboard-kit/styles.js +0 -205
- package/esm/src/lib/dashboard-kit/widgets.js +0 -379
- package/esm/src/lib/diagram-kit/card.js +0 -199
- package/esm/src/lib/diagram-kit/editing.js +0 -448
- package/esm/src/lib/diagram-kit/er.js +0 -160
- package/esm/src/lib/diagram-kit/handles.js +0 -312
- package/esm/src/lib/diagram-kit/index.js +0 -15
- package/esm/src/lib/diagram-kit/join-guidance.js +0 -322
- package/esm/src/lib/diagram-kit/rows.js +0 -144
- package/esm/src/lib/diagram-kit/styles.js +0 -118
- package/esm/src/lib/diagram-kit/uml.js +0 -135
- package/esm/src/lib/diagram-kit/update.js +0 -244
- package/esm/src/lib/grafloria-flow-element.js +0 -266
- package/esm/src/lib/grafloria.js +0 -69
- package/esm/src/lib/load.js +0 -252
- package/esm/src/lib/node-type-registry.js +0 -42
- package/esm/src/lib/stencil-kit/builders.js +0 -18
- package/esm/src/lib/stencil-kit/card-builders.js +0 -105
- package/esm/src/lib/stencil-kit/index.js +0 -9
- package/esm/src/lib/stencil-kit/palette.js +0 -427
- package/esm/src/lib/stencil-kit/shape-data.js +0 -537
- package/esm/src/lib/stencil-kit/styles.js +0 -126
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Row interactions — "select a column / field" on kit cards (P1 of the
|
|
3
|
-
* ER/UML editing track).
|
|
4
|
-
*
|
|
5
|
-
* Kit cards are `interactive: true` (their rows are real DOM targets — the
|
|
6
|
-
* binder's node click/drag resolution is geometric, so dragging and selecting
|
|
7
|
-
* the TABLE keeps working; proven live before this was built). This module is
|
|
8
|
-
* the runtime the kit's `finalize(api)` binds once per diagram:
|
|
9
|
-
*
|
|
10
|
-
* - click a row → it becomes THE selected row (one per diagram), painted with
|
|
11
|
-
* `.axk-row-selected`; click again or click anywhere else → deselected;
|
|
12
|
-
* - every row click dispatches `axk:row-click` on the container, and every
|
|
13
|
-
* selection CHANGE dispatches `axk:row-select` — both bubbling
|
|
14
|
-
* CustomEvents, matching the element package's "DOM events out" contract;
|
|
15
|
-
* - the selected row survives card re-renders: the renderer keys the
|
|
16
|
-
* foreignObject by content hash, so an html edit swaps the subtree and
|
|
17
|
-
* drops the class — a MutationObserver re-applies it by (nodeId, rowIndex);
|
|
18
|
-
* - selection is EPHEMERAL view state, exactly like node selection: never
|
|
19
|
-
* serialized, never in the op log, not undoable.
|
|
20
|
-
*
|
|
21
|
-
* Row identity: `rowIndex` is the position among the card's rows (ER columns,
|
|
22
|
-
* or UML members across both compartments); `name` resolves from the spec the
|
|
23
|
-
* kit stored in node metadata (`kitEntity` / `kitClass`), falling back to the
|
|
24
|
-
* row's text.
|
|
25
|
-
*/
|
|
26
|
-
const ROW_SELECTOR = '.axk-row, .axk-member';
|
|
27
|
-
const SELECTED_CLASS = 'axk-row-selected';
|
|
28
|
-
/** One binding per container — rebinding disposes the previous one. */
|
|
29
|
-
const bindings = new WeakMap();
|
|
30
|
-
function rowsOfNode(container, nodeId) {
|
|
31
|
-
const esc = (window.CSS && CSS.escape) ? CSS.escape(nodeId) : nodeId.replace(/"/g, '\\"');
|
|
32
|
-
const group = container.querySelector(`[data-node-id="${esc}"]`);
|
|
33
|
-
return group ? Array.from(group.querySelectorAll(ROW_SELECTOR)) : [];
|
|
34
|
-
}
|
|
35
|
-
function resolveRef(container, api, rowEl) {
|
|
36
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
37
|
-
const group = rowEl.closest('[data-node-id]');
|
|
38
|
-
if (!group)
|
|
39
|
-
return null;
|
|
40
|
-
const nodeId = group.getAttribute('data-node-id');
|
|
41
|
-
const rows = Array.from(group.querySelectorAll(ROW_SELECTOR));
|
|
42
|
-
const rowIndex = rows.indexOf(rowEl);
|
|
43
|
-
if (rowIndex === -1)
|
|
44
|
-
return null;
|
|
45
|
-
const kind = rowEl.classList.contains('axk-member') ? 'uml' : 'er';
|
|
46
|
-
const node = (_c = (_a = api.getModel) === null || _a === void 0 ? void 0 : (_b = _a.call(api)).getNode) === null || _c === void 0 ? void 0 : _c.call(_b, nodeId);
|
|
47
|
-
const meta = (key) => { var _a; return (_a = node === null || node === void 0 ? void 0 : node.getMetadata) === null || _a === void 0 ? void 0 : _a.call(node, key); };
|
|
48
|
-
if (kind === 'er') {
|
|
49
|
-
const entity = meta('kitEntity');
|
|
50
|
-
const name = (_h = (_f = (_e = (_d = entity === null || entity === void 0 ? void 0 : entity.columns) === null || _d === void 0 ? void 0 : _d[rowIndex]) === null || _e === void 0 ? void 0 : _e.name) !== null && _f !== void 0 ? _f : (_g = rowEl.querySelector('.axk-col')) === null || _g === void 0 ? void 0 : _g.textContent) !== null && _h !== void 0 ? _h : undefined;
|
|
51
|
-
return { nodeId, rowIndex, name: name !== null && name !== void 0 ? name : undefined, kind };
|
|
52
|
-
}
|
|
53
|
-
const cls = meta('kitClass');
|
|
54
|
-
const attrCount = (_k = (_j = cls === null || cls === void 0 ? void 0 : cls.attributes) === null || _j === void 0 ? void 0 : _j.length) !== null && _k !== void 0 ? _k : countFirstCompartment(rowEl);
|
|
55
|
-
const section = rowIndex < attrCount ? 'attributes' : 'methods';
|
|
56
|
-
const name = (_q = (_o = (section === 'attributes' ? (_l = cls === null || cls === void 0 ? void 0 : cls.attributes) === null || _l === void 0 ? void 0 : _l[rowIndex] : (_m = cls === null || cls === void 0 ? void 0 : cls.methods) === null || _m === void 0 ? void 0 : _m[rowIndex - attrCount])) !== null && _o !== void 0 ? _o : (_p = rowEl.textContent) === null || _p === void 0 ? void 0 : _p.trim()) !== null && _q !== void 0 ? _q : undefined;
|
|
57
|
-
return { nodeId, rowIndex, name, kind, section };
|
|
58
|
-
}
|
|
59
|
-
/** Without spec metadata, the first compartment's member count splits sections. */
|
|
60
|
-
function countFirstCompartment(rowEl) {
|
|
61
|
-
const card = rowEl.closest('.axk-uml');
|
|
62
|
-
const firstComp = card === null || card === void 0 ? void 0 : card.querySelector('.axk-uml-comp');
|
|
63
|
-
return firstComp ? firstComp.querySelectorAll('.axk-member').length : Number.MAX_SAFE_INTEGER;
|
|
64
|
-
}
|
|
65
|
-
export function bindRowInteractions(api) {
|
|
66
|
-
var _a;
|
|
67
|
-
const container = api.container;
|
|
68
|
-
(_a = bindings.get(container)) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
69
|
-
let selected = null;
|
|
70
|
-
const paint = () => {
|
|
71
|
-
var _a;
|
|
72
|
-
for (const el of Array.from(container.querySelectorAll(`.${SELECTED_CLASS}`))) {
|
|
73
|
-
el.classList.remove(SELECTED_CLASS);
|
|
74
|
-
}
|
|
75
|
-
if (selected)
|
|
76
|
-
(_a = rowsOfNode(container, selected.nodeId)[selected.rowIndex]) === null || _a === void 0 ? void 0 : _a.classList.add(SELECTED_CLASS);
|
|
77
|
-
};
|
|
78
|
-
const emitSelect = () => {
|
|
79
|
-
container.dispatchEvent(new CustomEvent('axk:row-select', { bubbles: true, detail: { selected } }));
|
|
80
|
-
};
|
|
81
|
-
const setSelected = (next) => {
|
|
82
|
-
const same = (next === null && selected === null) ||
|
|
83
|
-
(next !== null && selected !== null && next.nodeId === selected.nodeId && next.rowIndex === selected.rowIndex);
|
|
84
|
-
if (same)
|
|
85
|
-
return;
|
|
86
|
-
selected = next;
|
|
87
|
-
paint();
|
|
88
|
-
emitSelect();
|
|
89
|
-
};
|
|
90
|
-
const onClick = (event) => {
|
|
91
|
-
var _a;
|
|
92
|
-
const target = event.target instanceof Element ? event.target : null;
|
|
93
|
-
const rowEl = (_a = target === null || target === void 0 ? void 0 : target.closest) === null || _a === void 0 ? void 0 : _a.call(target, ROW_SELECTOR);
|
|
94
|
-
if (!rowEl || !container.contains(rowEl)) {
|
|
95
|
-
setSelected(null);
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const ref = resolveRef(container, api, rowEl);
|
|
99
|
-
if (!ref)
|
|
100
|
-
return;
|
|
101
|
-
container.dispatchEvent(new CustomEvent('axk:row-click', { bubbles: true, detail: Object.assign({}, ref) }));
|
|
102
|
-
const isReclick = selected && selected.nodeId === ref.nodeId && selected.rowIndex === ref.rowIndex;
|
|
103
|
-
setSelected(isReclick ? null : ref);
|
|
104
|
-
};
|
|
105
|
-
// Card re-renders replace the foreignObject subtree (content-hash keyed) and
|
|
106
|
-
// lose the class — re-apply whenever the selected row's paint went missing.
|
|
107
|
-
const observer = new MutationObserver(() => {
|
|
108
|
-
if (!selected)
|
|
109
|
-
return;
|
|
110
|
-
const el = rowsOfNode(container, selected.nodeId)[selected.rowIndex];
|
|
111
|
-
if (el && !el.classList.contains(SELECTED_CLASS))
|
|
112
|
-
paint();
|
|
113
|
-
else if (!el) {
|
|
114
|
-
// The row (or its node) is gone — the selection dies with it.
|
|
115
|
-
setSelected(null);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
container.addEventListener('click', onClick);
|
|
119
|
-
observer.observe(container, { childList: true, subtree: true });
|
|
120
|
-
const handle = {
|
|
121
|
-
getSelected: () => (selected ? Object.assign({}, selected) : null),
|
|
122
|
-
select: (ref) => {
|
|
123
|
-
if (ref === null) {
|
|
124
|
-
setSelected(null);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
const el = rowsOfNode(container, ref.nodeId)[ref.rowIndex];
|
|
128
|
-
if (!el)
|
|
129
|
-
return;
|
|
130
|
-
const resolved = resolveRef(container, api, el);
|
|
131
|
-
if (resolved)
|
|
132
|
-
setSelected(resolved);
|
|
133
|
-
},
|
|
134
|
-
dispose: () => {
|
|
135
|
-
container.removeEventListener('click', onClick);
|
|
136
|
-
observer.disconnect();
|
|
137
|
-
if (bindings.get(container) === handle)
|
|
138
|
-
bindings.delete(container);
|
|
139
|
-
},
|
|
140
|
-
};
|
|
141
|
-
bindings.set(container, handle);
|
|
142
|
-
return handle;
|
|
143
|
-
}
|
|
144
|
-
//# sourceMappingURL=rows.js.map
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Diagram-kit stylesheet — injected once, on first use of any kit builder.
|
|
3
|
-
*
|
|
4
|
-
* Everything is prefixed `axk-` and the selection overrides are scoped with
|
|
5
|
-
* `:has(...)` to kit cards only, so embedding the kit can never restyle a
|
|
6
|
-
* host's own nodes. The rules encode the lessons the diagrams/* demos learned
|
|
7
|
-
* the hard way:
|
|
8
|
-
* - the card fills the node and draws the ONLY border (the node's own rect is
|
|
9
|
-
* hidden by the builders, and suppressed again on selection because the
|
|
10
|
-
* theme paints `.selected` with an accent stroke that overrides inline
|
|
11
|
-
* transparency);
|
|
12
|
-
* - the default `.selection-highlight` outline (a dashed rect a few px
|
|
13
|
-
* OUTSIDE the node) reads as a second floating box around a bordered card —
|
|
14
|
-
* the kit hides it and rings the card itself instead.
|
|
15
|
-
*/
|
|
16
|
-
export const DIAGRAM_KIT_STYLE_ID = 'grafloria-diagram-kit-styles';
|
|
17
|
-
const CSS = `
|
|
18
|
-
/* ===== ER entity (table) cards ===== */
|
|
19
|
-
.axk-entity { font: 12px/1.5 system-ui, sans-serif; border: 1px solid #64748b;
|
|
20
|
-
border-radius: 6px; overflow: hidden; background: #fff;
|
|
21
|
-
width: 100%; height: 100%; box-sizing: border-box;
|
|
22
|
-
display: flex; flex-direction: column; }
|
|
23
|
-
.axk-entity-body { flex: 1; min-height: 0; overflow-y: hidden; }
|
|
24
|
-
.axk-entity-body.axk-scroll { overflow-y: auto; scrollbar-width: thin; }
|
|
25
|
-
.axk-entity-head { background: #334155; color: #fff; font-weight: 600;
|
|
26
|
-
letter-spacing: .3px; padding: 5px 10px; text-transform: uppercase; font-size: 11px; }
|
|
27
|
-
.axk-row { display: flex; align-items: center; gap: 8px; padding: 3px 10px;
|
|
28
|
-
border-top: 1px solid #e2e8f0; }
|
|
29
|
-
.axk-key { width: 22px; font-size: 9px; font-weight: 700; color: #b45309; }
|
|
30
|
-
.axk-key.axk-fk { color: #6d28d9; }
|
|
31
|
-
.axk-col { flex: 1; color: #0f172a; }
|
|
32
|
-
.axk-ty {
|
|
33
|
-
color: #64748b; font-size: 11px;
|
|
34
|
-
/* A new column starts with an EMPTY type, which collapsed the cell to zero
|
|
35
|
-
width — there was nothing to double-click, so a type could never be set on
|
|
36
|
-
a field you just added. Reserve a target and hint that it is editable. */
|
|
37
|
-
min-width: 52px; text-align: right; cursor: text;
|
|
38
|
-
}
|
|
39
|
-
.axk-ty:empty::before { content: 'type'; color: #cbd5e1; font-style: italic; }
|
|
40
|
-
.axk-ty:hover { color: #0f172a; }
|
|
41
|
-
.axk-row.axk-pk .axk-col { font-weight: 600; }
|
|
42
|
-
|
|
43
|
-
/* ===== UML class cards ===== */
|
|
44
|
-
.axk-uml { font: 12px/1.5 system-ui, sans-serif; border: 1px solid #475569;
|
|
45
|
-
border-radius: 4px; overflow: hidden; background: #fff;
|
|
46
|
-
width: 100%; height: 100%; box-sizing: border-box;
|
|
47
|
-
display: flex; flex-direction: column; }
|
|
48
|
-
.axk-uml-body { flex: 1; min-height: 0; overflow-y: hidden; }
|
|
49
|
-
.axk-uml-body.axk-scroll { overflow-y: auto; scrollbar-width: thin; }
|
|
50
|
-
.axk-uml-name { text-align: center; font-weight: 700; padding: 5px 10px;
|
|
51
|
-
background: #eef2ff; color: #1e1b4b; }
|
|
52
|
-
.axk-uml-name.axk-abstract { font-style: italic; }
|
|
53
|
-
.axk-uml-stereo { display: block; font-size: 10px; font-weight: 500; opacity: .8; }
|
|
54
|
-
.axk-uml-comp { border-top: 1px solid #475569; padding: 3px 0; }
|
|
55
|
-
.axk-uml-comp.axk-empty { min-height: 8px; }
|
|
56
|
-
.axk-member { padding: 1px 10px; font: 11px/1.5 ui-monospace, Menlo, monospace;
|
|
57
|
-
color: #0f172a; white-space: nowrap; }
|
|
58
|
-
|
|
59
|
-
/* ===== Row interactivity (cards are interactive; drag stays geometric) ===== */
|
|
60
|
-
.axk-entity, .axk-uml { user-select: none; -webkit-user-select: none; }
|
|
61
|
-
.axk-row:hover { background: rgba(37, 99, 235, .07); }
|
|
62
|
-
.axk-member:hover { background: rgba(79, 70, 229, .07); }
|
|
63
|
-
.axk-row-selected, .axk-row-selected:hover { background: rgba(37, 99, 235, .16);
|
|
64
|
-
box-shadow: inset 2px 0 0 #2563eb; }
|
|
65
|
-
.axk-member.axk-row-selected, .axk-member.axk-row-selected:hover {
|
|
66
|
-
background: rgba(79, 70, 229, .16); box-shadow: inset 2px 0 0 #4f46e5; }
|
|
67
|
-
|
|
68
|
-
/* ===== Selection: ring the CARD, never a detached rectangle ===== */
|
|
69
|
-
g.node-group:has(.axk-entity) .selection-highlight,
|
|
70
|
-
g.node-group:has(.axk-uml) .selection-highlight { display: none; }
|
|
71
|
-
g.node-group[data-selected="true"] .axk-entity {
|
|
72
|
-
border-color: #2563eb; box-shadow: 0 0 0 2px rgba(37, 99, 235, .45); }
|
|
73
|
-
g.node-group[data-selected="true"] .axk-uml {
|
|
74
|
-
border-color: #4f46e5; box-shadow: 0 0 0 2px rgba(79, 70, 229, .45); }
|
|
75
|
-
g.node-group[data-selected="true"]:has(.axk-entity) rect.diagram-node,
|
|
76
|
-
g.node-group[data-selected="true"]:has(.axk-uml) rect.diagram-node {
|
|
77
|
-
stroke: transparent !important; fill: none !important; }
|
|
78
|
-
|
|
79
|
-
/* ===== In-canvas editing chrome (only present when editable) ===== */
|
|
80
|
-
.axk-col-del { width: 14px; text-align: center; color: #94a3b8; cursor: pointer;
|
|
81
|
-
font-weight: 700; opacity: 0; transition: opacity .1s; flex: 0 0 auto; }
|
|
82
|
-
.axk-row:hover .axk-col-del, .axk-member:hover .axk-col-del { opacity: 1; }
|
|
83
|
-
.axk-col-del:hover { color: #dc2626; }
|
|
84
|
-
/* Only editable members (which wrap their text in .axk-mtext) go flex — a
|
|
85
|
-
read-only member stays a plain text div, so its golden never shifts. */
|
|
86
|
-
.axk-member:has(.axk-mtext) { display: flex; align-items: center; }
|
|
87
|
-
.axk-member .axk-mtext { flex: 1; }
|
|
88
|
-
.axk-entity-add, .axk-uml-add { padding: 3px 10px; font-size: 11px; font-weight: 600;
|
|
89
|
-
color: #2563eb; cursor: pointer; border-top: 1px dashed #cbd5e1; user-select: none; }
|
|
90
|
-
.axk-uml-add { color: #4f46e5; border-top: 1px dashed #c7d2fe; text-align: left; }
|
|
91
|
-
.axk-entity-add:hover, .axk-uml-add:hover { background: rgba(37, 99, 235, .08); }
|
|
92
|
-
.axk-edit-input { font: 12px/1.4 system-ui, sans-serif; box-sizing: border-box;
|
|
93
|
-
border: 1px solid #2563eb; border-radius: 3px; padding: 1px 6px; margin: 0;
|
|
94
|
-
background: #fff; color: #0f172a; outline: none; box-shadow: 0 1px 4px rgba(0,0,0,.2); }
|
|
95
|
-
|
|
96
|
-
/* ===== Dark mode ===== */
|
|
97
|
-
@media (prefers-color-scheme: dark) {
|
|
98
|
-
.axk-entity { background: #1e293b; border-color: #475569; }
|
|
99
|
-
.axk-row { border-top-color: #334155; }
|
|
100
|
-
.axk-col { color: #e2e8f0; }
|
|
101
|
-
.axk-uml { background: #1e293b; border-color: #64748b; }
|
|
102
|
-
.axk-uml-name { background: #312e81; color: #e0e7ff; }
|
|
103
|
-
.axk-uml-comp { border-top-color: #64748b; }
|
|
104
|
-
.axk-member { color: #e2e8f0; }
|
|
105
|
-
}
|
|
106
|
-
`;
|
|
107
|
-
/** Inject the kit stylesheet once. Safe to call repeatedly and in SSR. */
|
|
108
|
-
export function ensureDiagramKitStyles(doc = typeof document !== 'undefined' ? document : undefined) {
|
|
109
|
-
if (!doc)
|
|
110
|
-
return;
|
|
111
|
-
if (doc.getElementById(DIAGRAM_KIT_STYLE_ID))
|
|
112
|
-
return;
|
|
113
|
-
const style = doc.createElement('style');
|
|
114
|
-
style.id = DIAGRAM_KIT_STYLE_ID;
|
|
115
|
-
style.textContent = CSS;
|
|
116
|
-
doc.head.appendChild(style);
|
|
117
|
-
}
|
|
118
|
-
//# sourceMappingURL=styles.js.map
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UML class-diagram kit — typed builders for the full relationship vocabulary.
|
|
3
|
-
*
|
|
4
|
-
* The packaged form of demos/diagrams/class-uml.html + uml-relationships.html:
|
|
5
|
-
* three-compartment class cards («stereotype», name, attributes, methods) and
|
|
6
|
-
* every standard relationship with its real notation:
|
|
7
|
-
*
|
|
8
|
-
* inheritance ── solid, hollow triangle at the parent
|
|
9
|
-
* realization ┄┄ dashed, hollow triangle at the interface
|
|
10
|
-
* association ── plain line (multiplicity chips optional)
|
|
11
|
-
* directed-association ── open arrow at the target
|
|
12
|
-
* aggregation ── hollow diamond at the whole (source)
|
|
13
|
-
* composition ── FILLED diamond at the whole (source)
|
|
14
|
-
* dependency ┄┄ dashed, open arrow («uses»)
|
|
15
|
-
*
|
|
16
|
-
* ```ts
|
|
17
|
-
* const spec = umlDiagram({
|
|
18
|
-
* classes: [{ id: 'Shape', abstract: true, attributes: ['# x: float'], methods: ['+ area(): float'] }],
|
|
19
|
-
* relationships: [{ from: 'Circle', to: 'Shape', kind: 'inheritance' }],
|
|
20
|
-
* });
|
|
21
|
-
* const api = render(spec, container);
|
|
22
|
-
* spec.finalize(api); // attaches multiplicity chips (needs the live model)
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
import { ensureDiagramKitStyles } from './styles';
|
|
26
|
-
import { bindRowInteractions } from './rows';
|
|
27
|
-
import { classCardContent, classAutoHeight } from './card';
|
|
28
|
-
import { bindCardEditing } from './editing';
|
|
29
|
-
const DEFAULT_WIDTH = 200;
|
|
30
|
-
const STROKE = '#475569';
|
|
31
|
-
const DASH = '6,4';
|
|
32
|
-
/**
|
|
33
|
-
* The notation table. Every kind sets arrowHead EXPLICITLY — a plain line must
|
|
34
|
-
* carry `arrowHead: none`, or the renderer paints its default arrow (the
|
|
35
|
-
* stray-arrowhead bug the demos hit live).
|
|
36
|
-
*/
|
|
37
|
-
function edgeStyleFor(kind) {
|
|
38
|
-
const none = { type: 'none', size: 0, filled: false };
|
|
39
|
-
switch (kind) {
|
|
40
|
-
case 'inheritance':
|
|
41
|
-
return { stroke: STROKE, strokeWidth: 1.5, arrowHead: { type: 'generalization', size: 16, filled: false }, arrowTail: none };
|
|
42
|
-
case 'realization':
|
|
43
|
-
return { stroke: STROKE, strokeWidth: 1.5, strokeDasharray: DASH, arrowHead: { type: 'generalization', size: 16, filled: false }, arrowTail: none };
|
|
44
|
-
case 'association':
|
|
45
|
-
return { stroke: STROKE, strokeWidth: 1.5, arrowHead: none, arrowTail: none };
|
|
46
|
-
case 'directed-association':
|
|
47
|
-
return { stroke: STROKE, strokeWidth: 1.5, arrowHead: { type: 'open-arrow', size: 12, filled: false }, arrowTail: none };
|
|
48
|
-
case 'aggregation':
|
|
49
|
-
return { stroke: STROKE, strokeWidth: 1.5, arrowHead: none, arrowTail: { type: 'hollow-diamond', size: 14, filled: false } };
|
|
50
|
-
case 'composition':
|
|
51
|
-
return { stroke: STROKE, strokeWidth: 1.5, arrowHead: none, arrowTail: { type: 'filled-diamond', size: 14, filled: true } };
|
|
52
|
-
case 'dependency':
|
|
53
|
-
return { stroke: STROKE, strokeWidth: 1.5, strokeDasharray: DASH, arrowHead: { type: 'open-arrow', size: 12, filled: false }, arrowTail: none };
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
/** Multiplicity chip, positioned near an edge end. */
|
|
57
|
-
const chip = (text, slot) => ({
|
|
58
|
-
text,
|
|
59
|
-
slot,
|
|
60
|
-
offset: { x: 0, y: -7 },
|
|
61
|
-
style: { fontSize: 11, fontWeight: '600', color: '#0f172a', background: '#ffffffdd', padding: 1, borderRadius: 2 },
|
|
62
|
-
});
|
|
63
|
-
/**
|
|
64
|
-
* Build a render() spec for a UML class diagram. Call `spec.finalize(api)`
|
|
65
|
-
* after render() — multiplicity chips are positioned labels, which only the
|
|
66
|
-
* live model's `link.addLabel` can express.
|
|
67
|
-
*/
|
|
68
|
-
export function umlDiagram(options) {
|
|
69
|
-
var _a;
|
|
70
|
-
ensureDiagramKitStyles();
|
|
71
|
-
const editable = options.editable === true;
|
|
72
|
-
const nodes = options.classes.map((cls, i) => {
|
|
73
|
-
var _a, _b;
|
|
74
|
-
return {
|
|
75
|
-
id: cls.id,
|
|
76
|
-
position: (_a = cls.position) !== null && _a !== void 0 ? _a : { x: 80 + (i % 3) * 320, y: 60 + Math.floor(i / 3) * 260 },
|
|
77
|
-
size: { width: (_b = cls.width) !== null && _b !== void 0 ? _b : DEFAULT_WIDTH, height: classAutoHeight(cls, editable) },
|
|
78
|
-
// interactive: members are real DOM targets (hover, row selection, inline
|
|
79
|
-
// editing); node drag/select stay geometric in the binder.
|
|
80
|
-
metadata: Object.assign({ html: { content: classCardContent(cls, editable), interactive: true }, kitClass: cls, kitEditable: editable }, (options.rowSelection === false ? { kitRowSelection: false } : {})),
|
|
81
|
-
shape: { type: 'rect', fill: 'none', stroke: 'none' },
|
|
82
|
-
style: { fill: 'transparent', stroke: 'transparent', strokeWidth: 0 },
|
|
83
|
-
};
|
|
84
|
-
});
|
|
85
|
-
const rels = (_a = options.relationships) !== null && _a !== void 0 ? _a : [];
|
|
86
|
-
const edges = rels.map((rel, i) => {
|
|
87
|
-
var _a, _b;
|
|
88
|
-
return (Object.assign(Object.assign(Object.assign({ id: (_a = rel.id) !== null && _a !== void 0 ? _a : `uml-rel-${i + 1}`, source: rel.from, target: rel.to, label: rel.label, type: 'orthogonal' }, (rel.fromSide ? { sourceHandle: rel.fromSide } : {})), (rel.toSide ? { targetHandle: rel.toSide } : {})), { style: edgeStyleFor((_b = rel.kind) !== null && _b !== void 0 ? _b : 'association') }));
|
|
89
|
-
});
|
|
90
|
-
// finalize is idempotent per api: render() auto-runs it, and a demo may also
|
|
91
|
-
// call it — chips must not be added twice.
|
|
92
|
-
const finalized = new WeakSet();
|
|
93
|
-
const finalize = (api) => {
|
|
94
|
-
var _a, _b, _c, _d, _e, _f;
|
|
95
|
-
const a0 = api;
|
|
96
|
-
// Own card ring only — suppress the node resize handles on the live model
|
|
97
|
-
// (the render-input path does not honour a spec-level `behavior`).
|
|
98
|
-
const m0 = (_a = a0 === null || a0 === void 0 ? void 0 : a0.getModel) === null || _a === void 0 ? void 0 : _a.call(a0);
|
|
99
|
-
if (m0)
|
|
100
|
-
for (const cls of options.classes)
|
|
101
|
-
(_d = (_c = (_b = m0.getNode) === null || _b === void 0 ? void 0 : _b.call(m0, cls.id)) === null || _c === void 0 ? void 0 : _c.setBehavior) === null || _d === void 0 ? void 0 : _d.call(_c, { resizable: false });
|
|
102
|
-
if (options.rowSelection !== false) {
|
|
103
|
-
const a = api;
|
|
104
|
-
// bindRowInteractions disposes any prior binding for the container, so it
|
|
105
|
-
// is safe to run twice.
|
|
106
|
-
if (a === null || a === void 0 ? void 0 : a.container)
|
|
107
|
-
bindRowInteractions(a);
|
|
108
|
-
}
|
|
109
|
-
if (editable && (a0 === null || a0 === void 0 ? void 0 : a0.container))
|
|
110
|
-
bindCardEditing(a0);
|
|
111
|
-
if (api && typeof api === 'object') {
|
|
112
|
-
if (finalized.has(api))
|
|
113
|
-
return;
|
|
114
|
-
finalized.add(api);
|
|
115
|
-
}
|
|
116
|
-
const model = (_e = api === null || api === void 0 ? void 0 : api.getModel) === null || _e === void 0 ? void 0 : _e.call(api);
|
|
117
|
-
if (!model)
|
|
118
|
-
return;
|
|
119
|
-
let added = false;
|
|
120
|
-
rels.forEach((rel, i) => {
|
|
121
|
-
if (!rel.multiplicity)
|
|
122
|
-
return;
|
|
123
|
-
const link = model.getLink(edges[i].id);
|
|
124
|
-
if (!link)
|
|
125
|
-
return;
|
|
126
|
-
link.addLabel(chip(rel.multiplicity[0], 'start'));
|
|
127
|
-
link.addLabel(chip(rel.multiplicity[1], 'end'));
|
|
128
|
-
added = true;
|
|
129
|
-
});
|
|
130
|
-
if (added)
|
|
131
|
-
(_f = api === null || api === void 0 ? void 0 : api.renderNow) === null || _f === void 0 ? void 0 : _f.call(api);
|
|
132
|
-
};
|
|
133
|
-
return { nodes, edges, finalize };
|
|
134
|
-
}
|
|
135
|
-
//# sourceMappingURL=uml.js.map
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Live editing — `updateEntity` / `updateClass` mutate a rendered kit card in
|
|
3
|
-
* place (P3, the foundation the in-canvas editing chrome is built on).
|
|
4
|
-
*
|
|
5
|
-
* A delta changes the DATA (a table's name, its columns; a class's name,
|
|
6
|
-
* attributes, methods, width/height) and this module:
|
|
7
|
-
* 1. reads the stored spec (`kitEntity` / `kitClass`) — the source of truth;
|
|
8
|
-
* 2. applies the delta to a NEW spec (the caller's objects are never mutated,
|
|
9
|
-
* so undo can restore the old one cleanly);
|
|
10
|
-
* 3. regenerates the card html from the SAME builder er.ts/uml.ts use
|
|
11
|
-
* (`card.ts`), so an edited card is identical to a freshly-built one;
|
|
12
|
-
* 4. recomputes the node size;
|
|
13
|
-
* 5. RECONCILES the field ports — every port pinned to a surviving column
|
|
14
|
-
* moves to that column's new row (`erRowCenterY`), ports on a removed
|
|
15
|
-
* column are dropped along with their edges. Port ids never change, so an
|
|
16
|
-
* edge stays glued to its row across inserts/removes/reorders (the exact
|
|
17
|
-
* failure this solves: a port frozen at the old row while the rows shifted
|
|
18
|
-
* under it);
|
|
19
|
-
* 6. repaints — as ONE undoable step.
|
|
20
|
-
*
|
|
21
|
-
* ONE UNDO STEP. The change is applied through `api.getEngine().commandManager`
|
|
22
|
-
* — the same public seam `renderer/ext/public-api.ts` uses — wrapped in a
|
|
23
|
-
* single kit-local {@link Command}. There is no `SetNodeMetadataCommand` in the
|
|
24
|
-
* engine (the html/kit-spec mutation has no built-in command), so rather than
|
|
25
|
-
* reach into engine internals or compose a half-undoable macro, the whole edit
|
|
26
|
-
* lives in one Command subclass here (subclassing `Command` is the engine's
|
|
27
|
-
* intended extension point — every basic command does it). When no engine is
|
|
28
|
-
* present the edit still applies, just non-undoably.
|
|
29
|
-
*/
|
|
30
|
-
import { __awaiter } from "tslib";
|
|
31
|
-
import { Command, PortModel, LinkModel } from '@grafloria/engine';
|
|
32
|
-
import { entityCardContent, entityAutoHeight, classCardContent, classAutoHeight, erRowCenterY, rowIndexFromY, matchColumns, } from './card';
|
|
33
|
-
/**
|
|
34
|
-
* The single undoable edit. Captures the card's whole before-state on first
|
|
35
|
-
* execute and restores it on undo, so an edit — however many rows and edges it
|
|
36
|
-
* touched — is one Ctrl+Z.
|
|
37
|
-
*/
|
|
38
|
-
class UpdateCardCommand extends Command {
|
|
39
|
-
constructor(nodeId, kind, build) {
|
|
40
|
-
super(kind === 'er' ? 'Edit table' : 'Edit class');
|
|
41
|
-
this.nodeId = nodeId;
|
|
42
|
-
this.kind = kind;
|
|
43
|
-
this.build = build;
|
|
44
|
-
this.captured = false;
|
|
45
|
-
}
|
|
46
|
-
execute(context) {
|
|
47
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
48
|
-
const model = context.diagram;
|
|
49
|
-
const node = model.getNode(this.nodeId);
|
|
50
|
-
if (!node)
|
|
51
|
-
return;
|
|
52
|
-
const kitKey = this.kind === 'er' ? 'kitEntity' : 'kitClass';
|
|
53
|
-
const oldKit = ((_a = node.getMetadata(kitKey)) !== null && _a !== void 0 ? _a : {});
|
|
54
|
-
if (!this.captured) {
|
|
55
|
-
this.captured = true;
|
|
56
|
-
this.before = {
|
|
57
|
-
html: node.getMetadata('html'),
|
|
58
|
-
kit: oldKit,
|
|
59
|
-
size: Object.assign({}, node.size),
|
|
60
|
-
ports: node.getPorts().map((p) => p.serialize()),
|
|
61
|
-
links: [],
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
const result = this.build(oldKit);
|
|
65
|
-
const newWidth = (_b = result.width) !== null && _b !== void 0 ? _b : node.size.width;
|
|
66
|
-
const removedLinks = [];
|
|
67
|
-
if (this.kind === 'er') {
|
|
68
|
-
const oldCols = ((_c = oldKit['columns']) !== null && _c !== void 0 ? _c : []);
|
|
69
|
-
const newCols = ((_d = result.newKit['columns']) !== null && _d !== void 0 ? _d : []);
|
|
70
|
-
const map = matchColumns(oldCols, newCols);
|
|
71
|
-
for (const port of [...node.getPorts()]) {
|
|
72
|
-
const args = (_e = port.layout) === null || _e === void 0 ? void 0 : _e.args;
|
|
73
|
-
if (((_f = port.layout) === null || _f === void 0 ? void 0 : _f.strategy) !== 'absolute' || !args || args.units !== 'px' || args.y == null)
|
|
74
|
-
continue;
|
|
75
|
-
const oldIdx = rowIndexFromY(args.y);
|
|
76
|
-
if (oldIdx < 0 || oldIdx >= oldCols.length)
|
|
77
|
-
continue; // not a row-pinned field port
|
|
78
|
-
const newIdx = map.get(oldIdx);
|
|
79
|
-
if (newIdx === undefined) {
|
|
80
|
-
// The column is gone — drop the port and every edge riding it.
|
|
81
|
-
for (const link of model.getLinks()) {
|
|
82
|
-
if (link.sourcePortId === port.id || link.targetPortId === port.id)
|
|
83
|
-
removedLinks.push(link.serialize());
|
|
84
|
-
}
|
|
85
|
-
for (const link of model.getLinks().filter((l) => l.sourcePortId === port.id || l.targetPortId === port.id)) {
|
|
86
|
-
model.removeLink(link.id);
|
|
87
|
-
}
|
|
88
|
-
node.removePort(port.id);
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
// Move the port to its column's NEW row; keep the ±dy spread. x tracks
|
|
92
|
-
// the (possibly changed) width by side, so a widened table stays pinned.
|
|
93
|
-
args.y = erRowCenterY(newIdx);
|
|
94
|
-
const side = (_g = port.alignment) === null || _g === void 0 ? void 0 : _g.side;
|
|
95
|
-
args.x = side === 'left' ? 0 : side === 'right' ? newWidth : newWidth / 2;
|
|
96
|
-
// A nested-arg mutation is not tracked — nudge the port so the model
|
|
97
|
-
// marks it dirty and the renderer repositions it this frame.
|
|
98
|
-
port.setOffset(Object.assign({}, ((_h = port.offset) !== null && _h !== void 0 ? _h : { x: 0, y: 0 })));
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
node.setMetadata('html', { content: result.content, interactive: true });
|
|
103
|
-
node.setMetadata(kitKey, result.newKit);
|
|
104
|
-
node.setSize(newWidth, result.height);
|
|
105
|
-
if (this.before)
|
|
106
|
-
this.before.links = removedLinks;
|
|
107
|
-
}
|
|
108
|
-
undo(context) {
|
|
109
|
-
var _a;
|
|
110
|
-
const model = context.diagram;
|
|
111
|
-
const node = model.getNode(this.nodeId);
|
|
112
|
-
if (!node || !this.before)
|
|
113
|
-
return;
|
|
114
|
-
node.setMetadata('html', this.before.html);
|
|
115
|
-
node.setMetadata(this.kind === 'er' ? 'kitEntity' : 'kitClass', this.before.kit);
|
|
116
|
-
node.setSize(this.before.size.width, this.before.size.height);
|
|
117
|
-
const beforeIds = new Set(this.before.ports.map((p) => p['id']));
|
|
118
|
-
for (const p of [...node.getPorts()])
|
|
119
|
-
if (!beforeIds.has(p.id))
|
|
120
|
-
node.removePort(p.id);
|
|
121
|
-
for (const sp of this.before.ports) {
|
|
122
|
-
const live = node.getPort(sp['id']);
|
|
123
|
-
if (live) {
|
|
124
|
-
live.layout = sp['layout'];
|
|
125
|
-
live.setOffset(Object.assign({}, ((_a = sp['offset']) !== null && _a !== void 0 ? _a : { x: 0, y: 0 })));
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
node.addPort(PortModel.fromJSON(sp));
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
for (const sl of this.before.links) {
|
|
132
|
-
if (!model.getLink(sl['id']))
|
|
133
|
-
model.addLink(LinkModel.fromJSON(sl));
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
canExecute(context) {
|
|
137
|
-
var _a;
|
|
138
|
-
return !!((_a = context.diagram) === null || _a === void 0 ? void 0 : _a.getNode(this.nodeId));
|
|
139
|
-
}
|
|
140
|
-
serialize() {
|
|
141
|
-
return { id: this.id, name: this.name, timestamp: this.timestamp, data: { nodeId: this.nodeId, kind: this.kind } };
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
/** Route a build through the engine's command stack (one undo step) or apply it directly. */
|
|
145
|
-
function runUpdate(api, nodeId, kind, build) {
|
|
146
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
147
|
-
var _a, _b, _c, _d, _e;
|
|
148
|
-
const model = (_a = api.getModel) === null || _a === void 0 ? void 0 : _a.call(api);
|
|
149
|
-
const node = (_b = model === null || model === void 0 ? void 0 : model.getNode) === null || _b === void 0 ? void 0 : _b.call(model, nodeId);
|
|
150
|
-
if (!model || !node)
|
|
151
|
-
return false;
|
|
152
|
-
const command = new UpdateCardCommand(nodeId, kind, build);
|
|
153
|
-
const cm = (_d = (_c = api.getEngine) === null || _c === void 0 ? void 0 : _c.call(api)) === null || _d === void 0 ? void 0 : _d.commandManager;
|
|
154
|
-
if (cm === null || cm === void 0 ? void 0 : cm.execute) {
|
|
155
|
-
yield cm.execute(command); // ONE undoable step (Command enters history once)
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
command.execute({ diagram: model }); // no engine — apply, non-undoably
|
|
159
|
-
}
|
|
160
|
-
(_e = api.renderNow) === null || _e === void 0 ? void 0 : _e.call(api);
|
|
161
|
-
return true;
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
const isEditable = (node) => (node === null || node === void 0 ? void 0 : node.getMetadata('kitEditable')) === true;
|
|
165
|
-
/**
|
|
166
|
-
* Edit a rendered ER table in place. `delta` may change the name, the column
|
|
167
|
-
* list (add / remove / reorder / rename / retype), and the width/height. Field
|
|
168
|
-
* ports and their edges are reconciled so the diagram stays correct, as ONE
|
|
169
|
-
* undoable step.
|
|
170
|
-
*
|
|
171
|
-
* @returns whether the node existed and the edit was applied.
|
|
172
|
-
*/
|
|
173
|
-
export function updateEntity(api, entityId, delta) {
|
|
174
|
-
var _a, _b, _c;
|
|
175
|
-
const editable = isEditable((_c = (_b = (_a = api.getModel) === null || _a === void 0 ? void 0 : _a.call(api)) === null || _b === void 0 ? void 0 : _b.getNode) === null || _c === void 0 ? void 0 : _c.call(_b, entityId));
|
|
176
|
-
const build = (oldKit) => {
|
|
177
|
-
const newEntity = Object.assign({}, oldKit);
|
|
178
|
-
if (delta.name !== undefined)
|
|
179
|
-
newEntity.name = delta.name;
|
|
180
|
-
if (delta.width !== undefined)
|
|
181
|
-
newEntity.width = delta.width;
|
|
182
|
-
if (delta.height !== undefined)
|
|
183
|
-
newEntity.height = delta.height;
|
|
184
|
-
if (delta.columns !== undefined)
|
|
185
|
-
newEntity.columns = delta.columns;
|
|
186
|
-
return {
|
|
187
|
-
newKit: newEntity,
|
|
188
|
-
content: entityCardContent(newEntity, editable),
|
|
189
|
-
height: entityAutoHeight(newEntity, editable),
|
|
190
|
-
width: newEntity.width,
|
|
191
|
-
};
|
|
192
|
-
};
|
|
193
|
-
return runUpdate(api, entityId, 'er', build);
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Edit a rendered UML class in place. `delta` may change the name, stereotype,
|
|
197
|
-
* abstract flag, attributes, methods, and width/height. One undoable step.
|
|
198
|
-
*/
|
|
199
|
-
export function updateClass(api, classId, delta) {
|
|
200
|
-
var _a, _b, _c;
|
|
201
|
-
const editable = isEditable((_c = (_b = (_a = api.getModel) === null || _a === void 0 ? void 0 : _a.call(api)) === null || _b === void 0 ? void 0 : _b.getNode) === null || _c === void 0 ? void 0 : _c.call(_b, classId));
|
|
202
|
-
const build = (oldKit) => {
|
|
203
|
-
const newClass = Object.assign({}, oldKit);
|
|
204
|
-
if (delta.name !== undefined)
|
|
205
|
-
newClass.name = delta.name;
|
|
206
|
-
if (delta.stereotype !== undefined)
|
|
207
|
-
newClass.stereotype = delta.stereotype;
|
|
208
|
-
if (delta.abstract !== undefined)
|
|
209
|
-
newClass.abstract = delta.abstract;
|
|
210
|
-
if (delta.width !== undefined)
|
|
211
|
-
newClass.width = delta.width;
|
|
212
|
-
if (delta.height !== undefined)
|
|
213
|
-
newClass.height = delta.height;
|
|
214
|
-
if (delta.attributes !== undefined)
|
|
215
|
-
newClass.attributes = delta.attributes;
|
|
216
|
-
if (delta.methods !== undefined)
|
|
217
|
-
newClass.methods = delta.methods;
|
|
218
|
-
return {
|
|
219
|
-
newKit: newClass,
|
|
220
|
-
content: classCardContent(newClass, editable),
|
|
221
|
-
height: classAutoHeight(newClass, editable),
|
|
222
|
-
width: newClass.width,
|
|
223
|
-
};
|
|
224
|
-
};
|
|
225
|
-
return runUpdate(api, classId, 'uml', build);
|
|
226
|
-
}
|
|
227
|
-
// -- small column helpers, for the editing chrome and embedders --------------
|
|
228
|
-
/** Append a column (immutably) — returns the new column array. */
|
|
229
|
-
export function addColumnAt(columns, column, at = columns.length) {
|
|
230
|
-
const next = columns.slice();
|
|
231
|
-
next.splice(Math.max(0, Math.min(at, next.length)), 0, column);
|
|
232
|
-
return next;
|
|
233
|
-
}
|
|
234
|
-
/** Remove the column at `index` — returns the new column array. */
|
|
235
|
-
export function removeColumnAt(columns, index) {
|
|
236
|
-
const next = columns.slice();
|
|
237
|
-
next.splice(index, 1);
|
|
238
|
-
return next;
|
|
239
|
-
}
|
|
240
|
-
/** Rename the column at `index` — returns a new array with a NEW object there. */
|
|
241
|
-
export function renameColumnAt(columns, index, name) {
|
|
242
|
-
return columns.map((c, i) => (i === index ? Object.assign(Object.assign({}, c), { name }) : c));
|
|
243
|
-
}
|
|
244
|
-
//# sourceMappingURL=update.js.map
|