@dxos/graph 0.8.4-main.fd6878d → 0.8.4-staging.60fe92afc8
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 +299 -216
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +299 -217
- 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 +16 -25
- package/src/Graph.ts +83 -0
- package/src/GraphModel.test.ts +265 -0
- package/src/GraphModel.ts +453 -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,34 +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 {
|
|
60
167
|
_graph;
|
|
61
168
|
/**
|
|
169
|
+
* Optional function to wrap mutations.
|
|
170
|
+
* When set, all graph mutations are wrapped in this function.
|
|
171
|
+
*/
|
|
172
|
+
_change;
|
|
173
|
+
/**
|
|
62
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).
|
|
63
177
|
*/
|
|
64
|
-
constructor(graph) {
|
|
178
|
+
constructor(graph, change) {
|
|
65
179
|
this._graph = graph ?? {
|
|
66
180
|
nodes: [],
|
|
67
181
|
edges: []
|
|
68
182
|
};
|
|
183
|
+
this._change = change;
|
|
69
184
|
}
|
|
70
185
|
[inspectCustom]() {
|
|
71
186
|
return this.toJSON();
|
|
@@ -125,7 +240,7 @@ var ReadonlyGraphModel = class {
|
|
|
125
240
|
visited.add(root.id);
|
|
126
241
|
const targets = this.filterEdges({
|
|
127
242
|
source: root.id
|
|
128
|
-
}).map((edge) => this.getNode(edge.target)).filter(
|
|
243
|
+
}).map((edge) => this.getNode(edge.target)).filter(isTruthy);
|
|
129
244
|
return [
|
|
130
245
|
root,
|
|
131
246
|
...targets.flatMap((target) => this._traverse(target, visited))
|
|
@@ -133,9 +248,22 @@ var ReadonlyGraphModel = class {
|
|
|
133
248
|
}
|
|
134
249
|
};
|
|
135
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
|
+
}
|
|
136
262
|
clear() {
|
|
137
|
-
this.
|
|
138
|
-
|
|
263
|
+
this._mutate((graph) => {
|
|
264
|
+
graph.nodes.length = 0;
|
|
265
|
+
graph.edges.length = 0;
|
|
266
|
+
});
|
|
139
267
|
return this;
|
|
140
268
|
}
|
|
141
269
|
addGraph(graph) {
|
|
@@ -151,76 +279,44 @@ var AbstractGraphModel = class extends ReadonlyGraphModel {
|
|
|
151
279
|
return this;
|
|
152
280
|
}
|
|
153
281
|
addNode(node) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
A: [
|
|
159
|
-
"node.id",
|
|
160
|
-
"'ID is required'"
|
|
161
|
-
]
|
|
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);
|
|
162
286
|
});
|
|
163
|
-
invariant2(!this.findNode(node.id), `node already exists: ${node.id}`, {
|
|
164
|
-
F: __dxlog_file2,
|
|
165
|
-
L: 158,
|
|
166
|
-
S: this,
|
|
167
|
-
A: [
|
|
168
|
-
"!this.findNode(node.id)",
|
|
169
|
-
"`node already exists: ${node.id}`"
|
|
170
|
-
]
|
|
171
|
-
});
|
|
172
|
-
this._graph.nodes.push(node);
|
|
173
287
|
return node;
|
|
174
288
|
}
|
|
175
289
|
addNodes(nodes) {
|
|
176
290
|
return nodes.map((node) => this.addNode(node));
|
|
177
291
|
}
|
|
178
292
|
addEdge(edge) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
L: 168,
|
|
182
|
-
S: this,
|
|
183
|
-
A: [
|
|
184
|
-
"edge.source",
|
|
185
|
-
""
|
|
186
|
-
]
|
|
187
|
-
});
|
|
188
|
-
invariant2(edge.target, void 0, {
|
|
189
|
-
F: __dxlog_file2,
|
|
190
|
-
L: 169,
|
|
191
|
-
S: this,
|
|
192
|
-
A: [
|
|
193
|
-
"edge.target",
|
|
194
|
-
""
|
|
195
|
-
]
|
|
196
|
-
});
|
|
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", ""] });
|
|
197
295
|
if (!edge.id) {
|
|
198
296
|
edge = {
|
|
199
297
|
id: createEdgeId(edge),
|
|
200
298
|
...edge
|
|
201
299
|
};
|
|
202
300
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
S: this,
|
|
207
|
-
A: [
|
|
208
|
-
"!this.findNode(edge.id!)",
|
|
209
|
-
""
|
|
210
|
-
]
|
|
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);
|
|
211
304
|
});
|
|
212
|
-
this._graph.edges.push(edge);
|
|
213
305
|
return edge;
|
|
214
306
|
}
|
|
215
307
|
addEdges(edges) {
|
|
216
308
|
return edges.map((edge) => this.addEdge(edge));
|
|
217
309
|
}
|
|
218
310
|
removeNode(id) {
|
|
219
|
-
|
|
220
|
-
|
|
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
|
+
});
|
|
221
317
|
return this.copy({
|
|
222
|
-
nodes,
|
|
223
|
-
edges
|
|
318
|
+
nodes: removedNodes,
|
|
319
|
+
edges: removedEdges
|
|
224
320
|
});
|
|
225
321
|
}
|
|
226
322
|
removeNodes(ids) {
|
|
@@ -228,10 +324,13 @@ var AbstractGraphModel = class extends ReadonlyGraphModel {
|
|
|
228
324
|
return this.copy().addGraphs(graphs);
|
|
229
325
|
}
|
|
230
326
|
removeEdge(id) {
|
|
231
|
-
|
|
327
|
+
let removedEdges = [];
|
|
328
|
+
this._mutate((graph) => {
|
|
329
|
+
removedEdges = removeBy(graph.edges, (edge) => edge.id === id);
|
|
330
|
+
});
|
|
232
331
|
return this.copy({
|
|
233
332
|
nodes: [],
|
|
234
|
-
edges
|
|
333
|
+
edges: removedEdges
|
|
235
334
|
});
|
|
236
335
|
}
|
|
237
336
|
removeEdges(ids) {
|
|
@@ -239,7 +338,7 @@ var AbstractGraphModel = class extends ReadonlyGraphModel {
|
|
|
239
338
|
return this.copy().addGraphs(graphs);
|
|
240
339
|
}
|
|
241
340
|
};
|
|
242
|
-
var
|
|
341
|
+
var AbstractBuilder = class {
|
|
243
342
|
_model;
|
|
244
343
|
constructor(_model) {
|
|
245
344
|
this._model = _model;
|
|
@@ -273,155 +372,138 @@ var AbstractGraphBuilder = class {
|
|
|
273
372
|
};
|
|
274
373
|
var GraphModel = class _GraphModel extends AbstractGraphModel {
|
|
275
374
|
get builder() {
|
|
276
|
-
return new
|
|
375
|
+
return new Builder(this);
|
|
277
376
|
}
|
|
278
377
|
copy(graph) {
|
|
279
|
-
return new _GraphModel(
|
|
280
|
-
nodes: graph?.nodes ?? [],
|
|
281
|
-
edges: graph?.edges ?? []
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
};
|
|
285
|
-
var subscribe = (model, cb, fire = false) => {
|
|
286
|
-
if (fire) {
|
|
287
|
-
cb(model, model.graph);
|
|
378
|
+
return new _GraphModel(graph);
|
|
288
379
|
}
|
|
289
|
-
return effect(() => {
|
|
290
|
-
cb(model, model.graph);
|
|
291
|
-
});
|
|
292
380
|
};
|
|
293
381
|
var ReactiveGraphModel = class _ReactiveGraphModel extends GraphModel {
|
|
294
|
-
|
|
295
|
-
|
|
382
|
+
_registry;
|
|
383
|
+
_graphAtom;
|
|
384
|
+
constructor(_registry, graph) {
|
|
385
|
+
const initialGraph = {
|
|
296
386
|
nodes: graph?.nodes ?? [],
|
|
297
387
|
edges: graph?.edges ?? []
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
return new _ReactiveGraphModel(graph);
|
|
388
|
+
};
|
|
389
|
+
super(initialGraph), this._registry = _registry;
|
|
390
|
+
this._graphAtom = Atom2.make(initialGraph);
|
|
302
391
|
}
|
|
303
|
-
|
|
304
|
-
return
|
|
392
|
+
get registry() {
|
|
393
|
+
return this._registry;
|
|
305
394
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
return this;
|
|
311
|
-
}
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
// src/selection.ts
|
|
315
|
-
import { computed, signal } from "@preact/signals-core";
|
|
316
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
317
|
-
var __dxlog_file3 = "/__w/dxos/dxos/packages/common/graph/src/selection.ts";
|
|
318
|
-
var SelectionModel = class {
|
|
319
|
-
_singleSelect;
|
|
320
|
-
_selected;
|
|
321
|
-
_selectedIds;
|
|
322
|
-
constructor(_singleSelect = false) {
|
|
323
|
-
this._singleSelect = _singleSelect;
|
|
324
|
-
this._selected = signal(/* @__PURE__ */ new Set());
|
|
325
|
-
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;
|
|
326
400
|
}
|
|
327
|
-
|
|
328
|
-
return
|
|
329
|
-
selected: Array.from(this._selected.value.values())
|
|
330
|
-
};
|
|
401
|
+
get graph() {
|
|
402
|
+
return this._registry.get(this._graphAtom);
|
|
331
403
|
}
|
|
332
|
-
get
|
|
333
|
-
return this.
|
|
404
|
+
get nodes() {
|
|
405
|
+
return this.graph.nodes;
|
|
334
406
|
}
|
|
335
|
-
get
|
|
336
|
-
return this.
|
|
407
|
+
get edges() {
|
|
408
|
+
return this.graph.edges;
|
|
337
409
|
}
|
|
338
|
-
|
|
339
|
-
return this.
|
|
410
|
+
copy(graph) {
|
|
411
|
+
return new _ReactiveGraphModel(this._registry, graph);
|
|
340
412
|
}
|
|
341
413
|
clear() {
|
|
342
|
-
this.
|
|
414
|
+
this._registry.set(this._graphAtom, {
|
|
415
|
+
nodes: [],
|
|
416
|
+
edges: []
|
|
417
|
+
});
|
|
418
|
+
return this;
|
|
343
419
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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
|
|
352
436
|
]
|
|
353
437
|
});
|
|
354
|
-
|
|
355
|
-
id
|
|
356
|
-
] : [
|
|
357
|
-
...Array.from(this._selected.value.values()),
|
|
358
|
-
id
|
|
359
|
-
]);
|
|
438
|
+
return node;
|
|
360
439
|
}
|
|
361
|
-
|
|
362
|
-
invariant3(
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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
|
|
369
456
|
]
|
|
370
457
|
});
|
|
371
|
-
|
|
458
|
+
return edge;
|
|
372
459
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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
|
+
});
|
|
379
472
|
}
|
|
380
|
-
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
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);
|
|
388
495
|
});
|
|
389
|
-
this._selected.value = set;
|
|
390
496
|
}
|
|
391
497
|
};
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
data: Schema.optional(Schema.Any)
|
|
399
|
-
});
|
|
400
|
-
var BaseGraphEdge = Schema.Struct({
|
|
401
|
-
id: Schema.String,
|
|
402
|
-
type: Schema.optional(Schema.String),
|
|
403
|
-
source: Schema.String,
|
|
404
|
-
target: Schema.String,
|
|
405
|
-
data: Schema.optional(Schema.Any)
|
|
406
|
-
});
|
|
407
|
-
var Graph = Schema.Struct({
|
|
408
|
-
id: Schema.optional(Schema.String),
|
|
409
|
-
nodes: Schema.mutable(Schema.Array(BaseGraphNode)),
|
|
410
|
-
edges: Schema.mutable(Schema.Array(BaseGraphEdge))
|
|
411
|
-
});
|
|
498
|
+
var Builder = class extends AbstractBuilder {
|
|
499
|
+
call(cb) {
|
|
500
|
+
cb(this);
|
|
501
|
+
return this;
|
|
502
|
+
}
|
|
503
|
+
};
|
|
412
504
|
export {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
BaseGraphNode,
|
|
417
|
-
Graph,
|
|
418
|
-
GraphBuilder,
|
|
419
|
-
GraphModel,
|
|
420
|
-
ReactiveGraphModel,
|
|
421
|
-
ReadonlyGraphModel,
|
|
422
|
-
SelectionModel,
|
|
423
|
-
createEdgeId,
|
|
424
|
-
parseEdgeId,
|
|
425
|
-
subscribe
|
|
505
|
+
Graph_exports as Graph,
|
|
506
|
+
GraphModel_exports as GraphModel,
|
|
507
|
+
SelectionModel
|
|
426
508
|
};
|
|
427
509
|
//# sourceMappingURL=index.mjs.map
|