@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
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ER_HEAD_H = exports.ER_ROW_H = exports.erRowCenterY = void 0;
|
|
4
|
+
exports.erDiagram = erDiagram;
|
|
5
|
+
/**
|
|
6
|
+
* ER diagram kit — typed builders for database entity-relationship diagrams.
|
|
7
|
+
*
|
|
8
|
+
* The packaged form of what demos/diagrams/table-er.html and er-advanced.html
|
|
9
|
+
* hand-composed: HTML "table" cards (header, typed columns, PK/FK badges),
|
|
10
|
+
* crow's-foot cardinality edges, and field-level FK→PK connections via
|
|
11
|
+
* absolute-layout ports. An embedder writes data:
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* const spec = erDiagram({
|
|
15
|
+
* entities: [
|
|
16
|
+
* { id: 'CUSTOMER', columns: [{ name: 'id', type: 'int', pk: true }, …] },
|
|
17
|
+
* { id: 'ORDER', columns: [{ name: 'customer_id', type: 'int', fk: true }, …] },
|
|
18
|
+
* ],
|
|
19
|
+
* relationships: [
|
|
20
|
+
* { from: 'CUSTOMER', to: 'ORDER', label: 'places' }, // table-level
|
|
21
|
+
* { from: 'ORDER.customer_id', to: 'CUSTOMER.id' }, // field-level
|
|
22
|
+
* ],
|
|
23
|
+
* });
|
|
24
|
+
* render(spec, container);
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
const styles_1 = require("./styles");
|
|
28
|
+
const rows_1 = require("./rows");
|
|
29
|
+
const card_1 = require("./card");
|
|
30
|
+
Object.defineProperty(exports, "erRowCenterY", { enumerable: true, get: function () { return card_1.erRowCenterY; } });
|
|
31
|
+
Object.defineProperty(exports, "ER_ROW_H", { enumerable: true, get: function () { return card_1.ER_ROW_H; } });
|
|
32
|
+
Object.defineProperty(exports, "ER_HEAD_H", { enumerable: true, get: function () { return card_1.ER_HEAD_H; } });
|
|
33
|
+
const editing_1 = require("./editing");
|
|
34
|
+
const DEFAULT_WIDTH = 190;
|
|
35
|
+
const CARDINALITY = {
|
|
36
|
+
'one-to-many': { tail: 'one', head: 'crow-foot' },
|
|
37
|
+
'one-to-one': { tail: 'one', head: 'one' },
|
|
38
|
+
'many-to-many': { tail: 'crow-foot', head: 'crow-foot' },
|
|
39
|
+
'one-to-zero-or-many': { tail: 'one', head: 'zero-or-many' },
|
|
40
|
+
'one-to-one-or-many': { tail: 'one', head: 'one-or-many' },
|
|
41
|
+
};
|
|
42
|
+
function parseEnd(ref, byId) {
|
|
43
|
+
const dot = ref.indexOf('.');
|
|
44
|
+
const entityId = dot === -1 ? ref : ref.slice(0, dot);
|
|
45
|
+
const entity = byId.get(entityId);
|
|
46
|
+
if (!entity)
|
|
47
|
+
throw new Error(`erDiagram: unknown entity "${entityId}" in relationship end "${ref}"`);
|
|
48
|
+
if (dot === -1)
|
|
49
|
+
return { entity };
|
|
50
|
+
const column = ref.slice(dot + 1);
|
|
51
|
+
const rowIndex = entity.columns.findIndex((c) => c.name === column);
|
|
52
|
+
if (rowIndex === -1) {
|
|
53
|
+
throw new Error(`erDiagram: entity "${entityId}" has no column "${column}" (relationship end "${ref}")`);
|
|
54
|
+
}
|
|
55
|
+
return { entity, column, rowIndex };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Build a render() spec for an ER diagram.
|
|
59
|
+
*
|
|
60
|
+
* Entities become HTML table cards; relationships become orthogonal edges with
|
|
61
|
+
* crow's-foot cardinality. A `TABLE.column` end pins the edge to that row via
|
|
62
|
+
* an absolute-layout port (the FK→PK look). Two edges landing on the same
|
|
63
|
+
* column are automatically spread apart.
|
|
64
|
+
*/
|
|
65
|
+
function erDiagram(options) {
|
|
66
|
+
var _a;
|
|
67
|
+
(0, styles_1.ensureDiagramKitStyles)();
|
|
68
|
+
const byId = new Map(options.entities.map((e) => [e.id, e]));
|
|
69
|
+
// Field-level ports are accumulated per entity while walking relationships.
|
|
70
|
+
const portsByEntity = new Map();
|
|
71
|
+
// How many edges already landed on a given entity row+side — drives the
|
|
72
|
+
// spread (dy) so shared columns (a PK referenced twice) don't stack.
|
|
73
|
+
const rowLandings = new Map();
|
|
74
|
+
const width = (e) => { var _a; return (_a = e.width) !== null && _a !== void 0 ? _a : DEFAULT_WIDTH; };
|
|
75
|
+
const fieldPort = (end, side) => {
|
|
76
|
+
var _a, _b;
|
|
77
|
+
const entity = end.entity;
|
|
78
|
+
const key = `${entity.id}#${end.rowIndex}#${side}`;
|
|
79
|
+
const landing = (_a = rowLandings.get(key)) !== null && _a !== void 0 ? _a : 0;
|
|
80
|
+
rowLandings.set(key, landing + 1);
|
|
81
|
+
// Spread repeat landings ±5px around the row centre: 0, -5, +5, -10, …
|
|
82
|
+
const dy = landing === 0 ? 0 : (landing % 2 === 1 ? -1 : 1) * Math.ceil(landing / 2) * 5;
|
|
83
|
+
const id = `${entity.id}__${end.column}__${side}__${landing}`;
|
|
84
|
+
const w = width(entity);
|
|
85
|
+
const port = {
|
|
86
|
+
id,
|
|
87
|
+
side,
|
|
88
|
+
visible: false,
|
|
89
|
+
layout: {
|
|
90
|
+
strategy: 'absolute',
|
|
91
|
+
args: {
|
|
92
|
+
units: 'px',
|
|
93
|
+
x: side === 'right' ? w : side === 'left' ? 0 : w / 2,
|
|
94
|
+
y: (0, card_1.erRowCenterY)(end.rowIndex),
|
|
95
|
+
dy,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
const bucket = (_b = portsByEntity.get(entity.id)) !== null && _b !== void 0 ? _b : [];
|
|
100
|
+
bucket.push(port);
|
|
101
|
+
portsByEntity.set(entity.id, bucket);
|
|
102
|
+
return id;
|
|
103
|
+
};
|
|
104
|
+
const edges = ((_a = options.relationships) !== null && _a !== void 0 ? _a : []).map((rel, i) => {
|
|
105
|
+
var _a, _b, _c, _d, _e;
|
|
106
|
+
const from = parseEnd(rel.from, byId);
|
|
107
|
+
const to = parseEnd(rel.to, byId);
|
|
108
|
+
const fromSide = (_a = rel.fromSide) !== null && _a !== void 0 ? _a : 'right';
|
|
109
|
+
const toSide = (_b = rel.toSide) !== null && _b !== void 0 ? _b : 'left';
|
|
110
|
+
const markers = typeof rel.cardinality === 'object'
|
|
111
|
+
? rel.cardinality
|
|
112
|
+
: CARDINALITY[(_c = rel.cardinality) !== null && _c !== void 0 ? _c : 'one-to-many'];
|
|
113
|
+
return {
|
|
114
|
+
id: (_d = rel.id) !== null && _d !== void 0 ? _d : `er-rel-${i + 1}`,
|
|
115
|
+
source: from.entity.id,
|
|
116
|
+
target: to.entity.id,
|
|
117
|
+
label: rel.label,
|
|
118
|
+
type: 'orthogonal',
|
|
119
|
+
sourceHandle: from.column !== undefined ? fieldPort(from, fromSide) : fromSide,
|
|
120
|
+
targetHandle: to.column !== undefined ? fieldPort(to, toSide) : toSide,
|
|
121
|
+
style: {
|
|
122
|
+
stroke: (_e = rel.color) !== null && _e !== void 0 ? _e : '#64748b',
|
|
123
|
+
strokeWidth: 1.5,
|
|
124
|
+
arrowTail: { type: markers.tail, size: 8, filled: false },
|
|
125
|
+
arrowHead: { type: markers.head, size: 9, filled: false },
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
const editable = options.editable === true;
|
|
130
|
+
const nodes = options.entities.map((entity, i) => {
|
|
131
|
+
var _a;
|
|
132
|
+
return (Object.assign({ id: entity.id, position: (_a = entity.position) !== null && _a !== void 0 ? _a : { x: 60 + (i % 3) * 340, y: 60 + Math.floor(i / 3) * 280 }, size: { width: width(entity), height: (0, card_1.entityAutoHeight)(entity, editable) },
|
|
133
|
+
// interactive: rows are real DOM targets (hover, row selection, inline
|
|
134
|
+
// editing) — node drag/select stay geometric in the binder.
|
|
135
|
+
metadata: Object.assign({ html: { content: (0, card_1.entityCardContent)(entity, editable), interactive: true }, kitEntity: entity, kitEditable: editable }, (options.rowSelection === false ? { kitRowSelection: false } : {})),
|
|
136
|
+
// The card draws its own border — the node's default rectangle is hidden
|
|
137
|
+
// (and re-suppressed on selection by the kit stylesheet).
|
|
138
|
+
shape: { type: 'rect', fill: 'none', stroke: 'none' }, style: { fill: 'transparent', stroke: 'transparent', strokeWidth: 0 } }, (portsByEntity.has(entity.id) ? { ports: portsByEntity.get(entity.id) } : {})));
|
|
139
|
+
});
|
|
140
|
+
return {
|
|
141
|
+
nodes,
|
|
142
|
+
edges,
|
|
143
|
+
finalize: (api) => {
|
|
144
|
+
var _a, _b, _c, _d;
|
|
145
|
+
const a = api;
|
|
146
|
+
// The card draws its OWN selection ring — suppress the node resize handles
|
|
147
|
+
// on the live model (they'd frame the card in a SECOND rectangle). Set here
|
|
148
|
+
// because the render-input path does not honour a spec-level `behavior`.
|
|
149
|
+
const model = (_a = a === null || a === void 0 ? void 0 : a.getModel) === null || _a === void 0 ? void 0 : _a.call(a);
|
|
150
|
+
if (model)
|
|
151
|
+
for (const e of options.entities)
|
|
152
|
+
(_d = (_c = (_b = model.getNode) === null || _b === void 0 ? void 0 : _b.call(model, e.id)) === null || _c === void 0 ? void 0 : _c.setBehavior) === null || _d === void 0 ? void 0 : _d.call(_c, { resizable: false });
|
|
153
|
+
if (options.rowSelection !== false && (a === null || a === void 0 ? void 0 : a.container))
|
|
154
|
+
(0, rows_1.bindRowInteractions)(a);
|
|
155
|
+
// Editing chrome (dbl-click rename, add/delete column) — opt-in, and safe
|
|
156
|
+
// to run alongside row selection (it claims control clicks in the capture
|
|
157
|
+
// phase before the selection handler sees them).
|
|
158
|
+
if (editable && (a === null || a === void 0 ? void 0 : a.container))
|
|
159
|
+
(0, editing_1.bindCardEditing)(a);
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=er.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"er.js","sourceRoot":"","sources":["../../../../../../libs/element/src/lib/diagram-kit/er.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed façade handles — Option B of the domain-API decision (2026-07-19):
|
|
3
|
+
* the clean OO surface over the data-first kit, with NO engine changes.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* const t = erTable(api, 'ORDERS');
|
|
7
|
+
* await t.rename('Sales Orders');
|
|
8
|
+
* await t.columns.add({ name: 'status', type: 'varchar' }, { at: 2 });
|
|
9
|
+
* await t.columns.get('customer_id')!.rename('cust_id'); // ports stay glued
|
|
10
|
+
* t.onRowSelect(({ field }) => panel.show(field));
|
|
11
|
+
* await t.undo();
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* THE DESIGN INVARIANT: a handle is STATELESS — nothing but `(api, id)`. Every
|
|
15
|
+
* getter re-reads the live model (`metadata.kitEntity` / `kitClass`), so a
|
|
16
|
+
* handle can never go stale across re-renders, undo, collab, or edits made
|
|
17
|
+
* behind its back. Every mutation funnels through `updateEntity`/`updateClass`,
|
|
18
|
+
* so one-step undo and field-port reconciliation are inherited, not
|
|
19
|
+
* re-implemented. Inheritance lives HERE — `CardHandle → ErTable / UmlClass` —
|
|
20
|
+
* where it is safe, never on the stored NodeModel (which the engine
|
|
21
|
+
* reconstructs from data on undo/paste/collab; see the decision doc).
|
|
22
|
+
*/
|
|
23
|
+
import type { ErColumn, ErEntitySpec } from './er';
|
|
24
|
+
import type { UmlClassSpec } from './uml';
|
|
25
|
+
import { updateEntity, updateClass } from './update';
|
|
26
|
+
import type { RowRef } from './rows';
|
|
27
|
+
/** The slice of DiagramInstance the handles need (same shape update.ts uses). */
|
|
28
|
+
export interface HandleApi {
|
|
29
|
+
container: HTMLElement;
|
|
30
|
+
getModel(): {
|
|
31
|
+
getNode(id: string): {
|
|
32
|
+
getMetadata?(key: string): unknown;
|
|
33
|
+
size: {
|
|
34
|
+
width: number;
|
|
35
|
+
height: number;
|
|
36
|
+
};
|
|
37
|
+
state?: {
|
|
38
|
+
selected?: boolean;
|
|
39
|
+
};
|
|
40
|
+
} | undefined;
|
|
41
|
+
selectNode?(node: unknown): void;
|
|
42
|
+
};
|
|
43
|
+
getEngine?(): {
|
|
44
|
+
undo(): Promise<void> | void;
|
|
45
|
+
redo(): Promise<void> | void;
|
|
46
|
+
} | undefined;
|
|
47
|
+
renderNow?(): void;
|
|
48
|
+
}
|
|
49
|
+
export declare abstract class CardHandle {
|
|
50
|
+
protected readonly api: HandleApi;
|
|
51
|
+
readonly id: string;
|
|
52
|
+
constructor(api: HandleApi, id: string);
|
|
53
|
+
/** The live node, or undefined once deleted. Handles never cache it. */
|
|
54
|
+
protected liveNode(): {
|
|
55
|
+
getMetadata?(key: string): unknown;
|
|
56
|
+
size: {
|
|
57
|
+
width: number;
|
|
58
|
+
height: number;
|
|
59
|
+
};
|
|
60
|
+
state?: {
|
|
61
|
+
selected?: boolean;
|
|
62
|
+
};
|
|
63
|
+
} | undefined;
|
|
64
|
+
get exists(): boolean;
|
|
65
|
+
/** Escape hatch to the underlying NodeModel (typed loosely on purpose). */
|
|
66
|
+
get node(): unknown;
|
|
67
|
+
get width(): number;
|
|
68
|
+
get height(): number;
|
|
69
|
+
abstract get name(): string;
|
|
70
|
+
/** Rename the card title — one undoable step. */
|
|
71
|
+
abstract rename(name: string): Promise<boolean>;
|
|
72
|
+
/** Resize the card — one undoable step (kit body scrolls when capped). */
|
|
73
|
+
abstract resize(size: {
|
|
74
|
+
width?: number;
|
|
75
|
+
height?: number;
|
|
76
|
+
}): Promise<boolean>;
|
|
77
|
+
select(): void;
|
|
78
|
+
undo(): Promise<void>;
|
|
79
|
+
redo(): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Row-selection events for THIS card only (the kit's `axk:row-select`,
|
|
82
|
+
* filtered). ER cards resolve the selection to a typed {@link ErField} when
|
|
83
|
+
* possible. Returns an unbind function.
|
|
84
|
+
*/
|
|
85
|
+
onRowSelect(cb: (e: {
|
|
86
|
+
field: ErField | null;
|
|
87
|
+
selected: RowRef | null;
|
|
88
|
+
}) => void): () => void;
|
|
89
|
+
}
|
|
90
|
+
/** A column of an {@link ErTable} — itself just (table, name): stateless. */
|
|
91
|
+
export declare class ErField {
|
|
92
|
+
readonly table: ErTable;
|
|
93
|
+
private readonly columnName;
|
|
94
|
+
constructor(table: ErTable, columnName: string);
|
|
95
|
+
private col;
|
|
96
|
+
get exists(): boolean;
|
|
97
|
+
get name(): string;
|
|
98
|
+
get index(): number;
|
|
99
|
+
get type(): string | undefined;
|
|
100
|
+
get pk(): boolean;
|
|
101
|
+
get fk(): boolean;
|
|
102
|
+
/** Rename — the field port keeps its id, so attached edges stay glued. */
|
|
103
|
+
rename(name: string): Promise<boolean>;
|
|
104
|
+
setType(type: string): Promise<boolean>;
|
|
105
|
+
setKeys(keys: {
|
|
106
|
+
pk?: boolean;
|
|
107
|
+
fk?: boolean;
|
|
108
|
+
}): Promise<boolean>;
|
|
109
|
+
/** Remove this column (its ports and attached edges are dropped). */
|
|
110
|
+
remove(): Promise<boolean>;
|
|
111
|
+
}
|
|
112
|
+
/** The columns collection of an {@link ErTable}. Iterable of {@link ErField}. */
|
|
113
|
+
export declare class ErColumnList implements Iterable<ErField> {
|
|
114
|
+
private readonly table;
|
|
115
|
+
constructor(table: ErTable);
|
|
116
|
+
private cols;
|
|
117
|
+
get length(): number;
|
|
118
|
+
names(): string[];
|
|
119
|
+
at(index: number): ErField | undefined;
|
|
120
|
+
get(name: string): ErField | undefined;
|
|
121
|
+
[Symbol.iterator](): Iterator<ErField>;
|
|
122
|
+
add(column: ErColumn, opts?: {
|
|
123
|
+
at?: number;
|
|
124
|
+
}): Promise<boolean>;
|
|
125
|
+
removeAt(index: number): Promise<boolean>;
|
|
126
|
+
renameAt(index: number, name: string): Promise<boolean>;
|
|
127
|
+
patchAt(index: number, patch: Partial<ErColumn>): Promise<boolean>;
|
|
128
|
+
move(from: number, to: number): Promise<boolean>;
|
|
129
|
+
}
|
|
130
|
+
export declare class ErTable extends CardHandle {
|
|
131
|
+
readonly columns: ErColumnList;
|
|
132
|
+
/** A deep COPY of the stored entity spec — never a live reference. */
|
|
133
|
+
get spec(): ErEntitySpec;
|
|
134
|
+
get name(): string;
|
|
135
|
+
rename(name: string): Promise<boolean>;
|
|
136
|
+
resize(size: {
|
|
137
|
+
width?: number;
|
|
138
|
+
height?: number;
|
|
139
|
+
}): Promise<boolean>;
|
|
140
|
+
/** The raw delta path — everything above funnels through here. */
|
|
141
|
+
update(delta: Parameters<typeof updateEntity>[2]): Promise<boolean>;
|
|
142
|
+
}
|
|
143
|
+
/** attributes / methods of a {@link UmlClass} (members are plain strings). */
|
|
144
|
+
export declare class UmlMemberList {
|
|
145
|
+
private readonly cls;
|
|
146
|
+
private readonly kind;
|
|
147
|
+
constructor(cls: UmlClass, kind: 'attributes' | 'methods');
|
|
148
|
+
list(): string[];
|
|
149
|
+
get length(): number;
|
|
150
|
+
at(index: number): string | undefined;
|
|
151
|
+
add(member: string, opts?: {
|
|
152
|
+
at?: number;
|
|
153
|
+
}): Promise<boolean>;
|
|
154
|
+
removeAt(index: number): Promise<boolean>;
|
|
155
|
+
renameAt(index: number, member: string): Promise<boolean>;
|
|
156
|
+
}
|
|
157
|
+
export declare class UmlClass extends CardHandle {
|
|
158
|
+
readonly attributes: UmlMemberList;
|
|
159
|
+
readonly methods: UmlMemberList;
|
|
160
|
+
/** A deep COPY of the stored class spec — never a live reference. */
|
|
161
|
+
get spec(): UmlClassSpec;
|
|
162
|
+
get name(): string;
|
|
163
|
+
get abstract(): boolean;
|
|
164
|
+
get stereotype(): string | undefined;
|
|
165
|
+
rename(name: string): Promise<boolean>;
|
|
166
|
+
resize(size: {
|
|
167
|
+
width?: number;
|
|
168
|
+
height?: number;
|
|
169
|
+
}): Promise<boolean>;
|
|
170
|
+
setAbstract(abstract: boolean): Promise<boolean>;
|
|
171
|
+
setStereotype(stereotype: string | undefined): Promise<boolean>;
|
|
172
|
+
update(delta: Parameters<typeof updateClass>[2]): Promise<boolean>;
|
|
173
|
+
}
|
|
174
|
+
/** Typed handle for a kit ER table. Throws for unknown ids / non-kit nodes. */
|
|
175
|
+
export declare function erTable(api: HandleApi, id: string): ErTable;
|
|
176
|
+
/** Typed handle for a kit UML class. Throws for unknown ids / non-kit nodes. */
|
|
177
|
+
export declare function umlClass(api: HandleApi, id: string): UmlClass;
|
|
178
|
+
/** Every kit ER table in the diagram, as handles. */
|
|
179
|
+
export declare function erTables(api: HandleApi): ErTable[];
|
|
180
|
+
/** Every kit UML class in the diagram, as handles. */
|
|
181
|
+
export declare function umlClasses(api: HandleApi): UmlClass[];
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UmlClass = exports.UmlMemberList = exports.ErTable = exports.ErColumnList = exports.ErField = exports.CardHandle = void 0;
|
|
4
|
+
exports.erTable = erTable;
|
|
5
|
+
exports.umlClass = umlClass;
|
|
6
|
+
exports.erTables = erTables;
|
|
7
|
+
exports.umlClasses = umlClasses;
|
|
8
|
+
const tslib_1 = require("tslib");
|
|
9
|
+
const update_1 = require("./update");
|
|
10
|
+
const deep = (v) => JSON.parse(JSON.stringify(v));
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Base
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
class CardHandle {
|
|
15
|
+
constructor(api, id) {
|
|
16
|
+
this.api = api;
|
|
17
|
+
this.id = id;
|
|
18
|
+
}
|
|
19
|
+
/** The live node, or undefined once deleted. Handles never cache it. */
|
|
20
|
+
liveNode() {
|
|
21
|
+
return this.api.getModel().getNode(this.id);
|
|
22
|
+
}
|
|
23
|
+
get exists() {
|
|
24
|
+
return this.liveNode() !== undefined;
|
|
25
|
+
}
|
|
26
|
+
/** Escape hatch to the underlying NodeModel (typed loosely on purpose). */
|
|
27
|
+
get node() {
|
|
28
|
+
return this.liveNode();
|
|
29
|
+
}
|
|
30
|
+
get width() {
|
|
31
|
+
var _a, _b;
|
|
32
|
+
return (_b = (_a = this.liveNode()) === null || _a === void 0 ? void 0 : _a.size.width) !== null && _b !== void 0 ? _b : 0;
|
|
33
|
+
}
|
|
34
|
+
get height() {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
return (_b = (_a = this.liveNode()) === null || _a === void 0 ? void 0 : _a.size.height) !== null && _b !== void 0 ? _b : 0;
|
|
37
|
+
}
|
|
38
|
+
select() {
|
|
39
|
+
var _a, _b, _c;
|
|
40
|
+
const model = this.api.getModel();
|
|
41
|
+
const node = model.getNode(this.id);
|
|
42
|
+
if (node)
|
|
43
|
+
(_a = model.selectNode) === null || _a === void 0 ? void 0 : _a.call(model, node);
|
|
44
|
+
(_c = (_b = this.api).renderNow) === null || _c === void 0 ? void 0 : _c.call(_b);
|
|
45
|
+
}
|
|
46
|
+
undo() {
|
|
47
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
var _a, _b, _c, _d, _e;
|
|
49
|
+
yield ((_c = (_b = (_a = this.api).getEngine) === null || _b === void 0 ? void 0 : _b.call(_a)) === null || _c === void 0 ? void 0 : _c.undo());
|
|
50
|
+
(_e = (_d = this.api).renderNow) === null || _e === void 0 ? void 0 : _e.call(_d);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
redo() {
|
|
54
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
var _a, _b, _c, _d, _e;
|
|
56
|
+
yield ((_c = (_b = (_a = this.api).getEngine) === null || _b === void 0 ? void 0 : _b.call(_a)) === null || _c === void 0 ? void 0 : _c.redo());
|
|
57
|
+
(_e = (_d = this.api).renderNow) === null || _e === void 0 ? void 0 : _e.call(_d);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Row-selection events for THIS card only (the kit's `axk:row-select`,
|
|
62
|
+
* filtered). ER cards resolve the selection to a typed {@link ErField} when
|
|
63
|
+
* possible. Returns an unbind function.
|
|
64
|
+
*/
|
|
65
|
+
onRowSelect(cb) {
|
|
66
|
+
const handler = (event) => {
|
|
67
|
+
var _a, _b, _c;
|
|
68
|
+
const selected = (_b = (_a = event.detail) === null || _a === void 0 ? void 0 : _a.selected) !== null && _b !== void 0 ? _b : null;
|
|
69
|
+
if (selected && selected.nodeId !== this.id)
|
|
70
|
+
return; // another card
|
|
71
|
+
if (!selected) {
|
|
72
|
+
cb({ field: null, selected: null });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const field = this instanceof ErTable && selected.name !== undefined
|
|
76
|
+
? ((_c = this.columns.get(selected.name)) !== null && _c !== void 0 ? _c : null)
|
|
77
|
+
: null;
|
|
78
|
+
cb({ field, selected });
|
|
79
|
+
};
|
|
80
|
+
this.api.container.addEventListener('axk:row-select', handler);
|
|
81
|
+
return () => this.api.container.removeEventListener('axk:row-select', handler);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.CardHandle = CardHandle;
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// ER
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
/** A column of an {@link ErTable} — itself just (table, name): stateless. */
|
|
89
|
+
class ErField {
|
|
90
|
+
constructor(table, columnName) {
|
|
91
|
+
this.table = table;
|
|
92
|
+
this.columnName = columnName;
|
|
93
|
+
}
|
|
94
|
+
col() {
|
|
95
|
+
return this.table.spec.columns.find((c) => c.name === this.columnName);
|
|
96
|
+
}
|
|
97
|
+
get exists() {
|
|
98
|
+
return this.col() !== undefined;
|
|
99
|
+
}
|
|
100
|
+
get name() {
|
|
101
|
+
return this.columnName;
|
|
102
|
+
}
|
|
103
|
+
get index() {
|
|
104
|
+
return this.table.spec.columns.findIndex((c) => c.name === this.columnName);
|
|
105
|
+
}
|
|
106
|
+
get type() {
|
|
107
|
+
var _a;
|
|
108
|
+
return (_a = this.col()) === null || _a === void 0 ? void 0 : _a.type;
|
|
109
|
+
}
|
|
110
|
+
get pk() {
|
|
111
|
+
var _a;
|
|
112
|
+
return ((_a = this.col()) === null || _a === void 0 ? void 0 : _a.pk) === true;
|
|
113
|
+
}
|
|
114
|
+
get fk() {
|
|
115
|
+
var _a;
|
|
116
|
+
return ((_a = this.col()) === null || _a === void 0 ? void 0 : _a.fk) === true;
|
|
117
|
+
}
|
|
118
|
+
/** Rename — the field port keeps its id, so attached edges stay glued. */
|
|
119
|
+
rename(name) {
|
|
120
|
+
return this.table.columns.renameAt(this.index, name);
|
|
121
|
+
}
|
|
122
|
+
setType(type) {
|
|
123
|
+
return this.table.columns.patchAt(this.index, { type });
|
|
124
|
+
}
|
|
125
|
+
setKeys(keys) {
|
|
126
|
+
return this.table.columns.patchAt(this.index, keys);
|
|
127
|
+
}
|
|
128
|
+
/** Remove this column (its ports and attached edges are dropped). */
|
|
129
|
+
remove() {
|
|
130
|
+
return this.table.columns.removeAt(this.index);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
exports.ErField = ErField;
|
|
134
|
+
/** The columns collection of an {@link ErTable}. Iterable of {@link ErField}. */
|
|
135
|
+
class ErColumnList {
|
|
136
|
+
constructor(table) {
|
|
137
|
+
this.table = table;
|
|
138
|
+
}
|
|
139
|
+
cols() {
|
|
140
|
+
return this.table.spec.columns;
|
|
141
|
+
}
|
|
142
|
+
get length() {
|
|
143
|
+
return this.cols().length;
|
|
144
|
+
}
|
|
145
|
+
names() {
|
|
146
|
+
return this.cols().map((c) => c.name);
|
|
147
|
+
}
|
|
148
|
+
at(index) {
|
|
149
|
+
const c = this.cols()[index];
|
|
150
|
+
return c ? new ErField(this.table, c.name) : undefined;
|
|
151
|
+
}
|
|
152
|
+
get(name) {
|
|
153
|
+
return this.cols().some((c) => c.name === name) ? new ErField(this.table, name) : undefined;
|
|
154
|
+
}
|
|
155
|
+
[Symbol.iterator]() {
|
|
156
|
+
return this.cols()
|
|
157
|
+
.map((c) => new ErField(this.table, c.name))[Symbol.iterator]();
|
|
158
|
+
}
|
|
159
|
+
add(column, opts = {}) {
|
|
160
|
+
var _a;
|
|
161
|
+
const next = [...this.cols()];
|
|
162
|
+
next.splice((_a = opts.at) !== null && _a !== void 0 ? _a : next.length, 0, Object.assign({}, column));
|
|
163
|
+
return this.table.update({ columns: next });
|
|
164
|
+
}
|
|
165
|
+
removeAt(index) {
|
|
166
|
+
const next = this.cols().filter((_, i) => i !== index);
|
|
167
|
+
return this.table.update({ columns: next });
|
|
168
|
+
}
|
|
169
|
+
renameAt(index, name) {
|
|
170
|
+
return this.patchAt(index, { name });
|
|
171
|
+
}
|
|
172
|
+
patchAt(index, patch) {
|
|
173
|
+
const next = this.cols().map((c, i) => (i === index ? Object.assign(Object.assign({}, c), patch) : c));
|
|
174
|
+
return this.table.update({ columns: next });
|
|
175
|
+
}
|
|
176
|
+
move(from, to) {
|
|
177
|
+
const next = [...this.cols()];
|
|
178
|
+
const [c] = next.splice(from, 1);
|
|
179
|
+
next.splice(to, 0, c);
|
|
180
|
+
return this.table.update({ columns: next });
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.ErColumnList = ErColumnList;
|
|
184
|
+
class ErTable extends CardHandle {
|
|
185
|
+
constructor() {
|
|
186
|
+
super(...arguments);
|
|
187
|
+
this.columns = new ErColumnList(this);
|
|
188
|
+
}
|
|
189
|
+
/** A deep COPY of the stored entity spec — never a live reference. */
|
|
190
|
+
get spec() {
|
|
191
|
+
var _a, _b;
|
|
192
|
+
const raw = (_b = (_a = this.liveNode()) === null || _a === void 0 ? void 0 : _a.getMetadata) === null || _b === void 0 ? void 0 : _b.call(_a, 'kitEntity');
|
|
193
|
+
if (!raw)
|
|
194
|
+
throw new Error(`erTable('${this.id}'): the node is gone`);
|
|
195
|
+
return deep(raw);
|
|
196
|
+
}
|
|
197
|
+
get name() {
|
|
198
|
+
var _a;
|
|
199
|
+
return (_a = this.spec.name) !== null && _a !== void 0 ? _a : this.id;
|
|
200
|
+
}
|
|
201
|
+
rename(name) {
|
|
202
|
+
return this.update({ name });
|
|
203
|
+
}
|
|
204
|
+
resize(size) {
|
|
205
|
+
return this.update(size);
|
|
206
|
+
}
|
|
207
|
+
/** The raw delta path — everything above funnels through here. */
|
|
208
|
+
update(delta) {
|
|
209
|
+
return (0, update_1.updateEntity)(this.api, this.id, delta);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
exports.ErTable = ErTable;
|
|
213
|
+
// ---------------------------------------------------------------------------
|
|
214
|
+
// UML
|
|
215
|
+
// ---------------------------------------------------------------------------
|
|
216
|
+
/** attributes / methods of a {@link UmlClass} (members are plain strings). */
|
|
217
|
+
class UmlMemberList {
|
|
218
|
+
constructor(cls, kind) {
|
|
219
|
+
this.cls = cls;
|
|
220
|
+
this.kind = kind;
|
|
221
|
+
}
|
|
222
|
+
list() {
|
|
223
|
+
var _a;
|
|
224
|
+
return (_a = this.cls.spec[this.kind]) !== null && _a !== void 0 ? _a : [];
|
|
225
|
+
}
|
|
226
|
+
get length() {
|
|
227
|
+
return this.list().length;
|
|
228
|
+
}
|
|
229
|
+
at(index) {
|
|
230
|
+
return this.list()[index];
|
|
231
|
+
}
|
|
232
|
+
add(member, opts = {}) {
|
|
233
|
+
var _a;
|
|
234
|
+
const next = [...this.list()];
|
|
235
|
+
next.splice((_a = opts.at) !== null && _a !== void 0 ? _a : next.length, 0, member);
|
|
236
|
+
return this.cls.update({ [this.kind]: next });
|
|
237
|
+
}
|
|
238
|
+
removeAt(index) {
|
|
239
|
+
return this.cls.update({ [this.kind]: this.list().filter((_, i) => i !== index) });
|
|
240
|
+
}
|
|
241
|
+
renameAt(index, member) {
|
|
242
|
+
return this.cls.update({ [this.kind]: this.list().map((m, i) => (i === index ? member : m)) });
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
exports.UmlMemberList = UmlMemberList;
|
|
246
|
+
class UmlClass extends CardHandle {
|
|
247
|
+
constructor() {
|
|
248
|
+
super(...arguments);
|
|
249
|
+
this.attributes = new UmlMemberList(this, 'attributes');
|
|
250
|
+
this.methods = new UmlMemberList(this, 'methods');
|
|
251
|
+
}
|
|
252
|
+
/** A deep COPY of the stored class spec — never a live reference. */
|
|
253
|
+
get spec() {
|
|
254
|
+
var _a, _b;
|
|
255
|
+
const raw = (_b = (_a = this.liveNode()) === null || _a === void 0 ? void 0 : _a.getMetadata) === null || _b === void 0 ? void 0 : _b.call(_a, 'kitClass');
|
|
256
|
+
if (!raw)
|
|
257
|
+
throw new Error(`umlClass('${this.id}'): the node is gone`);
|
|
258
|
+
return deep(raw);
|
|
259
|
+
}
|
|
260
|
+
get name() {
|
|
261
|
+
var _a;
|
|
262
|
+
return (_a = this.spec.name) !== null && _a !== void 0 ? _a : this.id;
|
|
263
|
+
}
|
|
264
|
+
get abstract() {
|
|
265
|
+
return this.spec.abstract === true;
|
|
266
|
+
}
|
|
267
|
+
get stereotype() {
|
|
268
|
+
return this.spec.stereotype;
|
|
269
|
+
}
|
|
270
|
+
rename(name) {
|
|
271
|
+
return this.update({ name });
|
|
272
|
+
}
|
|
273
|
+
resize(size) {
|
|
274
|
+
return this.update(size);
|
|
275
|
+
}
|
|
276
|
+
setAbstract(abstract) {
|
|
277
|
+
return this.update({ abstract });
|
|
278
|
+
}
|
|
279
|
+
setStereotype(stereotype) {
|
|
280
|
+
return this.update({ stereotype });
|
|
281
|
+
}
|
|
282
|
+
update(delta) {
|
|
283
|
+
return (0, update_1.updateClass)(this.api, this.id, delta);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
exports.UmlClass = UmlClass;
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
// Factories
|
|
289
|
+
// ---------------------------------------------------------------------------
|
|
290
|
+
function requireKit(api, id, key, what) {
|
|
291
|
+
var _a;
|
|
292
|
+
const node = api.getModel().getNode(id);
|
|
293
|
+
if (!node)
|
|
294
|
+
throw new Error(`${what}('${id}'): no node with that id`);
|
|
295
|
+
if (!((_a = node.getMetadata) === null || _a === void 0 ? void 0 : _a.call(node, key))) {
|
|
296
|
+
throw new Error(`${what}('${id}'): that node is not an ${what === 'erTable' ? 'ER table' : 'UML class'} (missing metadata.${key})`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/** Typed handle for a kit ER table. Throws for unknown ids / non-kit nodes. */
|
|
300
|
+
function erTable(api, id) {
|
|
301
|
+
requireKit(api, id, 'kitEntity', 'erTable');
|
|
302
|
+
return new ErTable(api, id);
|
|
303
|
+
}
|
|
304
|
+
/** Typed handle for a kit UML class. Throws for unknown ids / non-kit nodes. */
|
|
305
|
+
function umlClass(api, id) {
|
|
306
|
+
requireKit(api, id, 'kitClass', 'umlClass');
|
|
307
|
+
return new UmlClass(api, id);
|
|
308
|
+
}
|
|
309
|
+
/** Every kit ER table in the diagram, as handles. */
|
|
310
|
+
function erTables(api) {
|
|
311
|
+
var _a, _b;
|
|
312
|
+
const model = api.getModel();
|
|
313
|
+
return ((_b = (_a = model.getNodes) === null || _a === void 0 ? void 0 : _a.call(model)) !== null && _b !== void 0 ? _b : [])
|
|
314
|
+
.filter((n) => { var _a; return (_a = n.getMetadata) === null || _a === void 0 ? void 0 : _a.call(n, 'kitEntity'); })
|
|
315
|
+
.map((n) => new ErTable(api, n.id));
|
|
316
|
+
}
|
|
317
|
+
/** Every kit UML class in the diagram, as handles. */
|
|
318
|
+
function umlClasses(api) {
|
|
319
|
+
var _a, _b;
|
|
320
|
+
const model = api.getModel();
|
|
321
|
+
return ((_b = (_a = model.getNodes) === null || _a === void 0 ? void 0 : _a.call(model)) !== null && _b !== void 0 ? _b : [])
|
|
322
|
+
.filter((n) => { var _a; return (_a = n.getMetadata) === null || _a === void 0 ? void 0 : _a.call(n, 'kitClass'); })
|
|
323
|
+
.map((n) => new UmlClass(api, n.id));
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=handles.js.map
|