@dxos/graph 0.8.4-main.b97322e → 0.8.4-main.bc2380dfbc
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/LICENSE +102 -5
- package/dist/lib/browser/index.mjs +301 -213
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +301 -214
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/Graph.d.ts +64 -0
- package/dist/types/src/Graph.d.ts.map +1 -0
- package/dist/types/src/GraphModel.d.ts +135 -0
- package/dist/types/src/GraphModel.d.ts.map +1 -0
- package/dist/types/src/GraphModel.test.d.ts +2 -0
- package/dist/types/src/GraphModel.test.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +2 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/selection.d.ts +30 -8
- package/dist/types/src/selection.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +19 -25
- package/src/Graph.ts +83 -0
- package/src/GraphModel.test.ts +265 -0
- package/src/GraphModel.ts +454 -0
- package/src/index.ts +3 -3
- package/src/selection.ts +71 -22
- package/dist/types/src/model.d.ts +0 -105
- package/dist/types/src/model.d.ts.map +0 -1
- package/dist/types/src/model.test.d.ts +0 -2
- package/dist/types/src/model.test.d.ts.map +0 -1
- package/dist/types/src/types.d.ts +0 -58
- package/dist/types/src/types.d.ts.map +0 -1
- package/dist/types/src/util.d.ts +0 -9
- package/dist/types/src/util.d.ts.map +0 -1
- package/src/model.test.ts +0 -188
- package/src/model.ts +0 -317
- package/src/types.ts +0 -72
- package/src/util.ts +0 -22
|
@@ -1,35 +1,132 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
|
+
};
|
|
2
7
|
|
|
3
|
-
// src/
|
|
4
|
-
import {
|
|
5
|
-
import { inspectCustom } from "@dxos/debug";
|
|
6
|
-
import { failedInvariant, invariant as invariant2 } from "@dxos/invariant";
|
|
7
|
-
import { live } from "@dxos/live-object";
|
|
8
|
-
import { isNotFalsy, removeBy } from "@dxos/util";
|
|
9
|
-
|
|
10
|
-
// src/util.ts
|
|
8
|
+
// src/selection.ts
|
|
9
|
+
import { Atom, Registry } from "@effect-atom/atom-react";
|
|
11
10
|
import { invariant } from "@dxos/invariant";
|
|
12
|
-
var __dxlog_file = "/__w/dxos/dxos/packages/common/graph/src/
|
|
11
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/common/graph/src/selection.ts";
|
|
12
|
+
var SelectionModel = class {
|
|
13
|
+
_registry;
|
|
14
|
+
_selected;
|
|
15
|
+
_mode;
|
|
16
|
+
constructor({ mode = "multi" } = {}) {
|
|
17
|
+
this._registry = Registry.make();
|
|
18
|
+
this._selected = Atom.make(/* @__PURE__ */ new Set());
|
|
19
|
+
this._mode = mode;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Returns the selected IDs atom for subscription.
|
|
23
|
+
*/
|
|
24
|
+
get selected() {
|
|
25
|
+
return this._selected;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Gets the current selected IDs as a Set.
|
|
29
|
+
*/
|
|
30
|
+
getSelected() {
|
|
31
|
+
return this._registry.get(this._selected);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Gets the current selected IDs as an array.
|
|
35
|
+
*/
|
|
36
|
+
getSelectedIds() {
|
|
37
|
+
return Array.from(this._registry.get(this._selected).values());
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Subscribe to selection changes.
|
|
41
|
+
*/
|
|
42
|
+
subscribe(cb) {
|
|
43
|
+
this._registry.get(this._selected);
|
|
44
|
+
return this._registry.subscribe(this._selected, () => {
|
|
45
|
+
cb(this._registry.get(this._selected));
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
toJSON() {
|
|
49
|
+
return {
|
|
50
|
+
selected: this.getSelectedIds()
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Gets the current selection size.
|
|
55
|
+
*/
|
|
56
|
+
getSize() {
|
|
57
|
+
return this._registry.get(this._selected).size;
|
|
58
|
+
}
|
|
59
|
+
contains(id) {
|
|
60
|
+
return this._registry.get(this._selected).has(id);
|
|
61
|
+
}
|
|
62
|
+
clear() {
|
|
63
|
+
this._registry.set(this._selected, /* @__PURE__ */ new Set());
|
|
64
|
+
}
|
|
65
|
+
add(id) {
|
|
66
|
+
invariant(id, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 59, S: this, A: ["id", ""] });
|
|
67
|
+
const current = this._registry.get(this._selected);
|
|
68
|
+
this._registry.set(this._selected, new Set(this._mode === "single" ? [
|
|
69
|
+
id
|
|
70
|
+
] : [
|
|
71
|
+
...Array.from(current.values()),
|
|
72
|
+
id
|
|
73
|
+
]));
|
|
74
|
+
}
|
|
75
|
+
remove(id) {
|
|
76
|
+
invariant(id, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 69, S: this, A: ["id", ""] });
|
|
77
|
+
const current = this._registry.get(this._selected);
|
|
78
|
+
this._registry.set(this._selected, new Set(Array.from(current.values()).filter((_id) => _id !== id)));
|
|
79
|
+
}
|
|
80
|
+
// TODO(burdon): Handle single select.
|
|
81
|
+
setSelected(ids, subtract = false) {
|
|
82
|
+
const current = this._registry.get(this._selected);
|
|
83
|
+
this._registry.set(this._selected, /* @__PURE__ */ new Set([
|
|
84
|
+
...subtract ? Array.from(current.values()) : [],
|
|
85
|
+
...ids
|
|
86
|
+
]));
|
|
87
|
+
}
|
|
88
|
+
toggleSelected(ids, subtract = false) {
|
|
89
|
+
const current = this._registry.get(this._selected);
|
|
90
|
+
const set = new Set(subtract ? Array.from(current.values()) : void 0);
|
|
91
|
+
ids.forEach((id) => {
|
|
92
|
+
if (current.has(id)) {
|
|
93
|
+
set.delete(id);
|
|
94
|
+
} else {
|
|
95
|
+
set.add(id);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
this._registry.set(this._selected, set);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// src/Graph.ts
|
|
103
|
+
var Graph_exports = {};
|
|
104
|
+
__export(Graph_exports, {
|
|
105
|
+
Edge: () => Edge,
|
|
106
|
+
Graph: () => Graph,
|
|
107
|
+
Node: () => Node,
|
|
108
|
+
createEdgeId: () => createEdgeId,
|
|
109
|
+
parseEdgeId: () => parseEdgeId
|
|
110
|
+
});
|
|
111
|
+
import * as Schema from "effect/Schema";
|
|
112
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
113
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/common/graph/src/Graph.ts";
|
|
114
|
+
var Node = Schema.Struct({
|
|
115
|
+
id: Schema.String,
|
|
116
|
+
type: Schema.optional(Schema.String),
|
|
117
|
+
data: Schema.optional(Schema.Any)
|
|
118
|
+
});
|
|
119
|
+
var Edge = Schema.Struct({
|
|
120
|
+
id: Schema.String,
|
|
121
|
+
type: Schema.optional(Schema.String),
|
|
122
|
+
source: Schema.String,
|
|
123
|
+
target: Schema.String,
|
|
124
|
+
data: Schema.optional(Schema.Any)
|
|
125
|
+
});
|
|
13
126
|
var KEY_REGEX = /\w+/;
|
|
14
127
|
var createEdgeId = ({ source, target, relation }) => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
L: 13,
|
|
18
|
-
S: void 0,
|
|
19
|
-
A: [
|
|
20
|
-
"source.match(KEY_REGEX)",
|
|
21
|
-
"`invalid source: ${source}`"
|
|
22
|
-
]
|
|
23
|
-
});
|
|
24
|
-
invariant(target.match(KEY_REGEX), `invalid target: ${target}`, {
|
|
25
|
-
F: __dxlog_file,
|
|
26
|
-
L: 14,
|
|
27
|
-
S: void 0,
|
|
28
|
-
A: [
|
|
29
|
-
"target.match(KEY_REGEX)",
|
|
30
|
-
"`invalid target: ${target}`"
|
|
31
|
-
]
|
|
32
|
-
});
|
|
128
|
+
invariant2(source.match(KEY_REGEX), `invalid source: ${source}`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 27, S: void 0, A: ["source.match(KEY_REGEX)", "`invalid source: ${source}`"] });
|
|
129
|
+
invariant2(target.match(KEY_REGEX), `invalid target: ${target}`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 28, S: void 0, A: ["target.match(KEY_REGEX)", "`invalid target: ${target}`"] });
|
|
33
130
|
return [
|
|
34
131
|
source,
|
|
35
132
|
relation,
|
|
@@ -38,33 +135,52 @@ var createEdgeId = ({ source, target, relation }) => {
|
|
|
38
135
|
};
|
|
39
136
|
var parseEdgeId = (id) => {
|
|
40
137
|
const [source, relation, target] = id.split("_");
|
|
41
|
-
|
|
42
|
-
F: __dxlog_file,
|
|
43
|
-
L: 20,
|
|
44
|
-
S: void 0,
|
|
45
|
-
A: [
|
|
46
|
-
"source.length && target.length",
|
|
47
|
-
""
|
|
48
|
-
]
|
|
49
|
-
});
|
|
138
|
+
invariant2(source.length && target.length, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 37, S: void 0, A: ["source.length && target.length", ""] });
|
|
50
139
|
return {
|
|
51
140
|
source,
|
|
52
141
|
relation: relation.length ? relation : void 0,
|
|
53
142
|
target
|
|
54
143
|
};
|
|
55
144
|
};
|
|
145
|
+
var Graph = Schema.Struct({
|
|
146
|
+
id: Schema.optional(Schema.String),
|
|
147
|
+
nodes: Schema.mutable(Schema.Array(Node)),
|
|
148
|
+
edges: Schema.mutable(Schema.Array(Edge))
|
|
149
|
+
});
|
|
56
150
|
|
|
57
|
-
// src/
|
|
58
|
-
var
|
|
151
|
+
// src/GraphModel.ts
|
|
152
|
+
var GraphModel_exports = {};
|
|
153
|
+
__export(GraphModel_exports, {
|
|
154
|
+
AbstractBuilder: () => AbstractBuilder,
|
|
155
|
+
AbstractGraphModel: () => AbstractGraphModel,
|
|
156
|
+
Builder: () => Builder,
|
|
157
|
+
GraphModel: () => GraphModel,
|
|
158
|
+
ReactiveGraphModel: () => ReactiveGraphModel,
|
|
159
|
+
ReadonlyGraphModel: () => ReadonlyGraphModel
|
|
160
|
+
});
|
|
161
|
+
import { Atom as Atom2 } from "@effect-atom/atom-react";
|
|
162
|
+
import { inspectCustom } from "@dxos/debug";
|
|
163
|
+
import { failedInvariant, invariant as invariant3 } from "@dxos/invariant";
|
|
164
|
+
import { isTruthy, removeBy } from "@dxos/util";
|
|
165
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/common/graph/src/GraphModel.ts";
|
|
59
166
|
var ReadonlyGraphModel = class {
|
|
167
|
+
_graph;
|
|
168
|
+
/**
|
|
169
|
+
* Optional function to wrap mutations.
|
|
170
|
+
* When set, all graph mutations are wrapped in this function.
|
|
171
|
+
*/
|
|
172
|
+
_change;
|
|
60
173
|
/**
|
|
61
174
|
* NOTE: Pass in simple Graph or Live.
|
|
175
|
+
* @param graph - The graph data.
|
|
176
|
+
* @param change - Optional function to wrap mutations (e.g., Obj.update for ECHO objects).
|
|
62
177
|
*/
|
|
63
|
-
constructor(graph) {
|
|
178
|
+
constructor(graph, change) {
|
|
64
179
|
this._graph = graph ?? {
|
|
65
180
|
nodes: [],
|
|
66
181
|
edges: []
|
|
67
182
|
};
|
|
183
|
+
this._change = change;
|
|
68
184
|
}
|
|
69
185
|
[inspectCustom]() {
|
|
70
186
|
return this.toJSON();
|
|
@@ -124,7 +240,7 @@ var ReadonlyGraphModel = class {
|
|
|
124
240
|
visited.add(root.id);
|
|
125
241
|
const targets = this.filterEdges({
|
|
126
242
|
source: root.id
|
|
127
|
-
}).map((edge) => this.getNode(edge.target)).filter(
|
|
243
|
+
}).map((edge) => this.getNode(edge.target)).filter(isTruthy);
|
|
128
244
|
return [
|
|
129
245
|
root,
|
|
130
246
|
...targets.flatMap((target) => this._traverse(target, visited))
|
|
@@ -132,9 +248,22 @@ var ReadonlyGraphModel = class {
|
|
|
132
248
|
}
|
|
133
249
|
};
|
|
134
250
|
var AbstractGraphModel = class extends ReadonlyGraphModel {
|
|
251
|
+
/**
|
|
252
|
+
* Execute a mutation on the graph.
|
|
253
|
+
* If a change function is set, wraps the mutation in it.
|
|
254
|
+
*/
|
|
255
|
+
_mutate(fn) {
|
|
256
|
+
if (this._change != null) {
|
|
257
|
+
this._change(() => fn(this._graph));
|
|
258
|
+
} else {
|
|
259
|
+
fn(this._graph);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
135
262
|
clear() {
|
|
136
|
-
this.
|
|
137
|
-
|
|
263
|
+
this._mutate((graph) => {
|
|
264
|
+
graph.nodes.length = 0;
|
|
265
|
+
graph.edges.length = 0;
|
|
266
|
+
});
|
|
138
267
|
return this;
|
|
139
268
|
}
|
|
140
269
|
addGraph(graph) {
|
|
@@ -150,76 +279,44 @@ var AbstractGraphModel = class extends ReadonlyGraphModel {
|
|
|
150
279
|
return this;
|
|
151
280
|
}
|
|
152
281
|
addNode(node) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
A: [
|
|
158
|
-
"node.id",
|
|
159
|
-
"'ID is required'"
|
|
160
|
-
]
|
|
282
|
+
invariant3(node.id, "ID is required", { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 126, S: this, A: ["node.id", "'ID is required'"] });
|
|
283
|
+
invariant3(!this.findNode(node.id), `node already exists: ${node.id}`, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 127, S: this, A: ["!this.findNode(node.id)", "`node already exists: ${node.id}`"] });
|
|
284
|
+
this._mutate((graph) => {
|
|
285
|
+
graph.nodes.push(node);
|
|
161
286
|
});
|
|
162
|
-
invariant2(!this.findNode(node.id), `node already exists: ${node.id}`, {
|
|
163
|
-
F: __dxlog_file2,
|
|
164
|
-
L: 158,
|
|
165
|
-
S: this,
|
|
166
|
-
A: [
|
|
167
|
-
"!this.findNode(node.id)",
|
|
168
|
-
"`node already exists: ${node.id}`"
|
|
169
|
-
]
|
|
170
|
-
});
|
|
171
|
-
this._graph.nodes.push(node);
|
|
172
287
|
return node;
|
|
173
288
|
}
|
|
174
289
|
addNodes(nodes) {
|
|
175
290
|
return nodes.map((node) => this.addNode(node));
|
|
176
291
|
}
|
|
177
292
|
addEdge(edge) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
L: 168,
|
|
181
|
-
S: this,
|
|
182
|
-
A: [
|
|
183
|
-
"edge.source",
|
|
184
|
-
""
|
|
185
|
-
]
|
|
186
|
-
});
|
|
187
|
-
invariant2(edge.target, void 0, {
|
|
188
|
-
F: __dxlog_file2,
|
|
189
|
-
L: 169,
|
|
190
|
-
S: this,
|
|
191
|
-
A: [
|
|
192
|
-
"edge.target",
|
|
193
|
-
""
|
|
194
|
-
]
|
|
195
|
-
});
|
|
293
|
+
invariant3(edge.source, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 137, S: this, A: ["edge.source", ""] });
|
|
294
|
+
invariant3(edge.target, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 138, S: this, A: ["edge.target", ""] });
|
|
196
295
|
if (!edge.id) {
|
|
197
296
|
edge = {
|
|
198
297
|
id: createEdgeId(edge),
|
|
199
298
|
...edge
|
|
200
299
|
};
|
|
201
300
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
S: this,
|
|
206
|
-
A: [
|
|
207
|
-
"!this.findNode(edge.id!)",
|
|
208
|
-
""
|
|
209
|
-
]
|
|
301
|
+
invariant3(!this.findNode(edge.id), void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 146, S: this, A: ["!this.findNode(edge.id)", ""] });
|
|
302
|
+
this._mutate((graph) => {
|
|
303
|
+
graph.edges.push(edge);
|
|
210
304
|
});
|
|
211
|
-
this._graph.edges.push(edge);
|
|
212
305
|
return edge;
|
|
213
306
|
}
|
|
214
307
|
addEdges(edges) {
|
|
215
308
|
return edges.map((edge) => this.addEdge(edge));
|
|
216
309
|
}
|
|
217
310
|
removeNode(id) {
|
|
218
|
-
|
|
219
|
-
|
|
311
|
+
let removedEdges = [];
|
|
312
|
+
let removedNodes = [];
|
|
313
|
+
this._mutate((graph) => {
|
|
314
|
+
removedEdges = removeBy(graph.edges, (edge) => edge.source === id || edge.target === id);
|
|
315
|
+
removedNodes = removeBy(graph.nodes, (node) => node.id === id);
|
|
316
|
+
});
|
|
220
317
|
return this.copy({
|
|
221
|
-
nodes,
|
|
222
|
-
edges
|
|
318
|
+
nodes: removedNodes,
|
|
319
|
+
edges: removedEdges
|
|
223
320
|
});
|
|
224
321
|
}
|
|
225
322
|
removeNodes(ids) {
|
|
@@ -227,10 +324,13 @@ var AbstractGraphModel = class extends ReadonlyGraphModel {
|
|
|
227
324
|
return this.copy().addGraphs(graphs);
|
|
228
325
|
}
|
|
229
326
|
removeEdge(id) {
|
|
230
|
-
|
|
327
|
+
let removedEdges = [];
|
|
328
|
+
this._mutate((graph) => {
|
|
329
|
+
removedEdges = removeBy(graph.edges, (edge) => edge.id === id);
|
|
330
|
+
});
|
|
231
331
|
return this.copy({
|
|
232
332
|
nodes: [],
|
|
233
|
-
edges
|
|
333
|
+
edges: removedEdges
|
|
234
334
|
});
|
|
235
335
|
}
|
|
236
336
|
removeEdges(ids) {
|
|
@@ -238,7 +338,8 @@ var AbstractGraphModel = class extends ReadonlyGraphModel {
|
|
|
238
338
|
return this.copy().addGraphs(graphs);
|
|
239
339
|
}
|
|
240
340
|
};
|
|
241
|
-
var
|
|
341
|
+
var AbstractBuilder = class {
|
|
342
|
+
_model;
|
|
242
343
|
constructor(_model) {
|
|
243
344
|
this._model = _model;
|
|
244
345
|
}
|
|
@@ -271,152 +372,138 @@ var AbstractGraphBuilder = class {
|
|
|
271
372
|
};
|
|
272
373
|
var GraphModel = class _GraphModel extends AbstractGraphModel {
|
|
273
374
|
get builder() {
|
|
274
|
-
return new
|
|
375
|
+
return new Builder(this);
|
|
275
376
|
}
|
|
276
377
|
copy(graph) {
|
|
277
|
-
return new _GraphModel(
|
|
278
|
-
nodes: graph?.nodes ?? [],
|
|
279
|
-
edges: graph?.edges ?? []
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
var subscribe = (model, cb, fire = false) => {
|
|
284
|
-
if (fire) {
|
|
285
|
-
cb(model, model.graph);
|
|
378
|
+
return new _GraphModel(graph);
|
|
286
379
|
}
|
|
287
|
-
return effect(() => {
|
|
288
|
-
cb(model, model.graph);
|
|
289
|
-
});
|
|
290
380
|
};
|
|
291
381
|
var ReactiveGraphModel = class _ReactiveGraphModel extends GraphModel {
|
|
292
|
-
|
|
293
|
-
|
|
382
|
+
_registry;
|
|
383
|
+
_graphAtom;
|
|
384
|
+
constructor(_registry, graph) {
|
|
385
|
+
const initialGraph = {
|
|
294
386
|
nodes: graph?.nodes ?? [],
|
|
295
387
|
edges: graph?.edges ?? []
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
return new _ReactiveGraphModel(graph);
|
|
388
|
+
};
|
|
389
|
+
super(initialGraph), this._registry = _registry;
|
|
390
|
+
this._graphAtom = Atom2.make(initialGraph);
|
|
300
391
|
}
|
|
301
|
-
|
|
302
|
-
return
|
|
392
|
+
get registry() {
|
|
393
|
+
return this._registry;
|
|
303
394
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
return this;
|
|
309
|
-
}
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
// src/selection.ts
|
|
313
|
-
import { computed, signal } from "@preact/signals-core";
|
|
314
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
315
|
-
var __dxlog_file3 = "/__w/dxos/dxos/packages/common/graph/src/selection.ts";
|
|
316
|
-
var SelectionModel = class {
|
|
317
|
-
constructor(_singleSelect = false) {
|
|
318
|
-
this._singleSelect = _singleSelect;
|
|
319
|
-
this._selected = signal(/* @__PURE__ */ new Set());
|
|
320
|
-
this._selectedIds = computed(() => Array.from(this._selected.value.values()));
|
|
395
|
+
/**
|
|
396
|
+
* Get the graph atom for reactive subscriptions.
|
|
397
|
+
*/
|
|
398
|
+
get graphAtom() {
|
|
399
|
+
return this._graphAtom;
|
|
321
400
|
}
|
|
322
|
-
|
|
323
|
-
return
|
|
324
|
-
selected: Array.from(this._selected.value.values())
|
|
325
|
-
};
|
|
401
|
+
get graph() {
|
|
402
|
+
return this._registry.get(this._graphAtom);
|
|
326
403
|
}
|
|
327
|
-
get
|
|
328
|
-
return this.
|
|
404
|
+
get nodes() {
|
|
405
|
+
return this.graph.nodes;
|
|
329
406
|
}
|
|
330
|
-
get
|
|
331
|
-
return this.
|
|
407
|
+
get edges() {
|
|
408
|
+
return this.graph.edges;
|
|
332
409
|
}
|
|
333
|
-
|
|
334
|
-
return this.
|
|
410
|
+
copy(graph) {
|
|
411
|
+
return new _ReactiveGraphModel(this._registry, graph);
|
|
335
412
|
}
|
|
336
413
|
clear() {
|
|
337
|
-
this.
|
|
414
|
+
this._registry.set(this._graphAtom, {
|
|
415
|
+
nodes: [],
|
|
416
|
+
edges: []
|
|
417
|
+
});
|
|
418
|
+
return this;
|
|
338
419
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
420
|
+
/**
|
|
421
|
+
* Set the entire graph at once, triggering a single notification.
|
|
422
|
+
*/
|
|
423
|
+
setGraph(graph) {
|
|
424
|
+
this._registry.set(this._graphAtom, graph);
|
|
425
|
+
return this;
|
|
426
|
+
}
|
|
427
|
+
addNode(node) {
|
|
428
|
+
invariant3(node.id, "ID is required", { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 280, S: this, A: ["node.id", "'ID is required'"] });
|
|
429
|
+
invariant3(!this.findNode(node.id), `node already exists: ${node.id}`, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 281, S: this, A: ["!this.findNode(node.id)", "`node already exists: ${node.id}`"] });
|
|
430
|
+
const current = this._registry.get(this._graphAtom);
|
|
431
|
+
this._registry.set(this._graphAtom, {
|
|
432
|
+
...current,
|
|
433
|
+
nodes: [
|
|
434
|
+
...current.nodes,
|
|
435
|
+
node
|
|
347
436
|
]
|
|
348
437
|
});
|
|
349
|
-
|
|
350
|
-
id
|
|
351
|
-
] : [
|
|
352
|
-
...Array.from(this._selected.value.values()),
|
|
353
|
-
id
|
|
354
|
-
]);
|
|
438
|
+
return node;
|
|
355
439
|
}
|
|
356
|
-
|
|
357
|
-
invariant3(
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
440
|
+
addEdge(edge) {
|
|
441
|
+
invariant3(edge.source, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 293, S: this, A: ["edge.source", ""] });
|
|
442
|
+
invariant3(edge.target, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 294, S: this, A: ["edge.target", ""] });
|
|
443
|
+
if (!edge.id) {
|
|
444
|
+
edge = {
|
|
445
|
+
id: createEdgeId(edge),
|
|
446
|
+
...edge
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
invariant3(!this.findNode(edge.id), void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 301, S: this, A: ["!this.findNode(edge.id)", ""] });
|
|
450
|
+
const current = this._registry.get(this._graphAtom);
|
|
451
|
+
this._registry.set(this._graphAtom, {
|
|
452
|
+
...current,
|
|
453
|
+
edges: [
|
|
454
|
+
...current.edges,
|
|
455
|
+
edge
|
|
364
456
|
]
|
|
365
457
|
});
|
|
366
|
-
|
|
458
|
+
return edge;
|
|
367
459
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
460
|
+
removeNode(id) {
|
|
461
|
+
const current = this._registry.get(this._graphAtom);
|
|
462
|
+
const removedEdges = current.edges.filter((edge) => edge.source === id || edge.target === id);
|
|
463
|
+
const removedNodes = current.nodes.filter((node) => node.id === id);
|
|
464
|
+
this._registry.set(this._graphAtom, {
|
|
465
|
+
nodes: current.nodes.filter((node) => node.id !== id),
|
|
466
|
+
edges: current.edges.filter((edge) => edge.source !== id && edge.target !== id)
|
|
467
|
+
});
|
|
468
|
+
return this.copy({
|
|
469
|
+
nodes: removedNodes,
|
|
470
|
+
edges: removedEdges
|
|
471
|
+
});
|
|
374
472
|
}
|
|
375
|
-
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
473
|
+
removeEdge(id) {
|
|
474
|
+
const current = this._registry.get(this._graphAtom);
|
|
475
|
+
const removedEdges = current.edges.filter((edge) => edge.id === id);
|
|
476
|
+
this._registry.set(this._graphAtom, {
|
|
477
|
+
...current,
|
|
478
|
+
edges: current.edges.filter((edge) => edge.id !== id)
|
|
479
|
+
});
|
|
480
|
+
return this.copy({
|
|
481
|
+
nodes: [],
|
|
482
|
+
edges: removedEdges
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Subscribe to graph changes.
|
|
487
|
+
*/
|
|
488
|
+
subscribe(cb, fire = false) {
|
|
489
|
+
if (fire) {
|
|
490
|
+
cb(this, this.graph);
|
|
491
|
+
}
|
|
492
|
+
this._registry.get(this._graphAtom);
|
|
493
|
+
return this._registry.subscribe(this._graphAtom, () => {
|
|
494
|
+
cb(this, this.graph);
|
|
383
495
|
});
|
|
384
|
-
this._selected.value = set;
|
|
385
496
|
}
|
|
386
497
|
};
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
data: Schema.optional(Schema.Any)
|
|
394
|
-
});
|
|
395
|
-
var BaseGraphEdge = Schema.Struct({
|
|
396
|
-
id: Schema.String,
|
|
397
|
-
type: Schema.optional(Schema.String),
|
|
398
|
-
source: Schema.String,
|
|
399
|
-
target: Schema.String,
|
|
400
|
-
data: Schema.optional(Schema.Any)
|
|
401
|
-
});
|
|
402
|
-
var Graph = Schema.Struct({
|
|
403
|
-
id: Schema.optional(Schema.String),
|
|
404
|
-
nodes: Schema.mutable(Schema.Array(BaseGraphNode)),
|
|
405
|
-
edges: Schema.mutable(Schema.Array(BaseGraphEdge))
|
|
406
|
-
});
|
|
498
|
+
var Builder = class extends AbstractBuilder {
|
|
499
|
+
call(cb) {
|
|
500
|
+
cb(this);
|
|
501
|
+
return this;
|
|
502
|
+
}
|
|
503
|
+
};
|
|
407
504
|
export {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
BaseGraphNode,
|
|
412
|
-
Graph,
|
|
413
|
-
GraphBuilder,
|
|
414
|
-
GraphModel,
|
|
415
|
-
ReactiveGraphModel,
|
|
416
|
-
ReadonlyGraphModel,
|
|
417
|
-
SelectionModel,
|
|
418
|
-
createEdgeId,
|
|
419
|
-
parseEdgeId,
|
|
420
|
-
subscribe
|
|
505
|
+
Graph_exports as Graph,
|
|
506
|
+
GraphModel_exports as GraphModel,
|
|
507
|
+
SelectionModel
|
|
421
508
|
};
|
|
422
509
|
//# sourceMappingURL=index.mjs.map
|