@dxos/app-graph 0.4.7-main.e015b9e → 0.4.7-main.ea67fec
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/dist/lib/browser/index.mjs +289 -229
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +282 -239
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/graph-builder.d.ts +8 -16
- package/dist/types/src/graph-builder.d.ts.map +1 -1
- package/dist/types/src/graph.d.ts +71 -14
- package/dist/types/src/graph.d.ts.map +1 -1
- package/dist/types/src/helpers.d.ts +14 -0
- package/dist/types/src/helpers.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/node.d.ts +57 -47
- package/dist/types/src/node.d.ts.map +1 -1
- package/dist/types/src/stories/EchoGraph.stories.d.ts.map +1 -1
- package/package.json +10 -29
- package/src/graph-builder.ts +18 -206
- package/src/graph.test.ts +242 -146
- package/src/graph.ts +241 -48
- package/src/helpers.ts +27 -0
- package/src/index.ts +1 -1
- package/src/node.ts +78 -66
- package/src/stories/EchoGraph.stories.tsx +59 -27
- package/dist/lib/browser/testing.mjs +0 -98
- package/dist/lib/browser/testing.mjs.map +0 -7
- package/dist/lib/node/testing.cjs +0 -122
- package/dist/lib/node/testing.cjs.map +0 -7
- package/dist/types/src/action.d.ts +0 -68
- package/dist/types/src/action.d.ts.map +0 -1
- package/dist/types/src/testing.d.ts +0 -52
- package/dist/types/src/testing.d.ts.map +0 -1
- package/src/action.ts +0 -92
- package/src/testing.ts +0 -152
|
@@ -1,292 +1,352 @@
|
|
|
1
1
|
// packages/sdk/app-graph/src/graph.ts
|
|
2
|
+
import { untracked } from "@preact/signals-core";
|
|
2
3
|
import { deepSignal } from "deepsignal/react";
|
|
3
|
-
import get from "lodash.get";
|
|
4
4
|
import { invariant } from "@dxos/invariant";
|
|
5
|
+
import { nonNullable } from "@dxos/util";
|
|
6
|
+
|
|
7
|
+
// packages/sdk/app-graph/src/node.ts
|
|
8
|
+
var isGraphNode = (data) => data && typeof data === "object" && "id" in data && "properties" in data && data.properties ? typeof data.properties === "object" && "data" in data : false;
|
|
9
|
+
var isAction = (data) => isGraphNode(data) ? typeof data.data === "function" : false;
|
|
10
|
+
var actionGroupSymbol = Symbol("ActionGroup");
|
|
11
|
+
var isActionGroup = (data) => isGraphNode(data) ? data.data === actionGroupSymbol : false;
|
|
12
|
+
var isActionLike = (data) => isAction(data) || isActionGroup(data);
|
|
13
|
+
|
|
14
|
+
// packages/sdk/app-graph/src/graph.ts
|
|
5
15
|
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/sdk/app-graph/src/graph.ts";
|
|
16
|
+
var ROOT_ID = "root";
|
|
6
17
|
var Graph = class {
|
|
7
|
-
constructor(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
constructor() {
|
|
19
|
+
/**
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
this._nodes = deepSignal({
|
|
23
|
+
[ROOT_ID]: {
|
|
24
|
+
id: ROOT_ID,
|
|
25
|
+
properties: {},
|
|
26
|
+
data: null
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
// Key is the `${node.id}-${direction}` and value is an ordered list of node ids.
|
|
33
|
+
// Explicit type required because TS says this is not portable.
|
|
34
|
+
this._edges = deepSignal({});
|
|
35
|
+
this._constructNode = (nodeBase) => {
|
|
36
|
+
const node = {
|
|
37
|
+
...nodeBase,
|
|
38
|
+
edges: ({ direction = "outbound" } = {}) => {
|
|
39
|
+
return this._edges[this.getEdgeKey(node.id, direction)];
|
|
40
|
+
},
|
|
41
|
+
nodes: ({ direction, filter } = {}) => {
|
|
42
|
+
const nodes = this._getNodes({
|
|
43
|
+
id: node.id,
|
|
44
|
+
direction
|
|
45
|
+
}).filter((n) => !isActionLike(n));
|
|
46
|
+
return filter ? nodes.filter((n) => filter(n, node)) : nodes;
|
|
47
|
+
},
|
|
48
|
+
node: (id) => {
|
|
49
|
+
return this._getNodes({
|
|
50
|
+
id
|
|
51
|
+
}).find((node2) => node2.id === id);
|
|
52
|
+
},
|
|
53
|
+
actions: () => {
|
|
54
|
+
return this._getNodes({
|
|
55
|
+
id: node.id
|
|
56
|
+
}).filter(isActionLike);
|
|
57
|
+
}
|
|
22
58
|
};
|
|
59
|
+
return node;
|
|
23
60
|
};
|
|
24
|
-
return toJSON(this._root);
|
|
25
61
|
}
|
|
26
62
|
/**
|
|
27
|
-
*
|
|
63
|
+
* Alias for `findNode('root')`.
|
|
28
64
|
*/
|
|
29
65
|
get root() {
|
|
30
|
-
return this.
|
|
66
|
+
return this.findNode(ROOT_ID);
|
|
31
67
|
}
|
|
32
68
|
/**
|
|
33
|
-
*
|
|
69
|
+
* Convert the graph to a JSON object.
|
|
34
70
|
*/
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
71
|
+
toJSON({ id = ROOT_ID, maxLength = 32 } = {}) {
|
|
72
|
+
const toJSON = (node) => {
|
|
73
|
+
const nodes = node.nodes();
|
|
74
|
+
const obj = {
|
|
75
|
+
id: node.id.length > maxLength ? `${node.id.slice(0, maxLength - 3)}...` : node.id
|
|
76
|
+
};
|
|
77
|
+
if (node.properties.label) {
|
|
78
|
+
obj.label = node.properties.label;
|
|
79
|
+
}
|
|
80
|
+
if (nodes.length) {
|
|
81
|
+
obj.nodes = nodes.map((node2) => toJSON(node2));
|
|
82
|
+
}
|
|
83
|
+
return obj;
|
|
84
|
+
};
|
|
85
|
+
const root = this.findNode(id);
|
|
86
|
+
invariant(root, `Node not found: ${id}`, {
|
|
43
87
|
F: __dxlog_file,
|
|
44
|
-
L:
|
|
88
|
+
L: 85,
|
|
45
89
|
S: this,
|
|
46
90
|
A: [
|
|
47
|
-
"
|
|
48
|
-
"
|
|
91
|
+
"root",
|
|
92
|
+
"`Node not found: ${id}`"
|
|
49
93
|
]
|
|
50
94
|
});
|
|
51
|
-
|
|
95
|
+
return toJSON(root);
|
|
52
96
|
}
|
|
53
97
|
/**
|
|
54
98
|
* Find the node with the given id in the graph.
|
|
55
99
|
*/
|
|
56
100
|
findNode(id) {
|
|
57
|
-
const
|
|
58
|
-
if (!
|
|
101
|
+
const nodeBase = this._nodes[id];
|
|
102
|
+
if (!nodeBase) {
|
|
59
103
|
return void 0;
|
|
60
104
|
}
|
|
61
|
-
return
|
|
105
|
+
return this._constructNode(nodeBase);
|
|
106
|
+
}
|
|
107
|
+
_getNodes({ id, direction = "outbound" }) {
|
|
108
|
+
const edges = this._edges[this.getEdgeKey(id, direction)];
|
|
109
|
+
if (!edges) {
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
return edges.map((id2) => this.findNode(id2)).filter(nonNullable);
|
|
113
|
+
}
|
|
114
|
+
getEdgeKey(id, direction) {
|
|
115
|
+
return `${id}-${direction}`;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Add nodes to the graph.
|
|
119
|
+
*/
|
|
120
|
+
addNodes(...nodes) {
|
|
121
|
+
return nodes.map((node) => this._addNode(node));
|
|
122
|
+
}
|
|
123
|
+
_addNode({ nodes, edges, ..._node }) {
|
|
124
|
+
return untracked(() => {
|
|
125
|
+
const node = {
|
|
126
|
+
data: null,
|
|
127
|
+
properties: {},
|
|
128
|
+
..._node
|
|
129
|
+
};
|
|
130
|
+
this._nodes[node.id] = node;
|
|
131
|
+
if (nodes) {
|
|
132
|
+
nodes.forEach((subNode) => {
|
|
133
|
+
this._addNode(subNode);
|
|
134
|
+
this.addEdge({
|
|
135
|
+
source: node.id,
|
|
136
|
+
target: subNode.id
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (edges) {
|
|
141
|
+
edges.forEach(([id, direction]) => direction === "outbound" ? this.addEdge({
|
|
142
|
+
source: node.id,
|
|
143
|
+
target: id
|
|
144
|
+
}) : this.addEdge({
|
|
145
|
+
source: id,
|
|
146
|
+
target: node.id
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
return this._constructNode(node);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Remove nodes from the graph.
|
|
154
|
+
*
|
|
155
|
+
* @param id The id of the node to remove.
|
|
156
|
+
* @param edges Whether to remove edges connected to the node from the graph as well.
|
|
157
|
+
*/
|
|
158
|
+
removeNode(id, edges = false) {
|
|
159
|
+
untracked(() => {
|
|
160
|
+
const node = this.findNode(id);
|
|
161
|
+
if (!node) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (edges) {
|
|
165
|
+
delete this._edges[this.getEdgeKey(id, "outbound")];
|
|
166
|
+
delete this._edges[this.getEdgeKey(id, "inbound")];
|
|
167
|
+
this._getNodes({
|
|
168
|
+
id
|
|
169
|
+
}).forEach((node2) => this.removeEdge({
|
|
170
|
+
source: id,
|
|
171
|
+
target: node2.id
|
|
172
|
+
}));
|
|
173
|
+
this._getNodes({
|
|
174
|
+
id,
|
|
175
|
+
direction: "inbound"
|
|
176
|
+
}).forEach((node2) => this.removeEdge({
|
|
177
|
+
source: node2.id,
|
|
178
|
+
target: id
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
delete this._nodes[id];
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Add an edge to the graph.
|
|
186
|
+
*/
|
|
187
|
+
addEdge({ source, target }) {
|
|
188
|
+
untracked(() => {
|
|
189
|
+
const outbound = this._edges[this.getEdgeKey(source, "outbound")];
|
|
190
|
+
if (!outbound) {
|
|
191
|
+
this._edges[this.getEdgeKey(source, "outbound")] = [
|
|
192
|
+
target
|
|
193
|
+
];
|
|
194
|
+
} else if (!outbound.includes(target)) {
|
|
195
|
+
outbound.push(target);
|
|
196
|
+
}
|
|
197
|
+
const inbound = this._edges[this.getEdgeKey(target, "inbound")];
|
|
198
|
+
if (!inbound) {
|
|
199
|
+
this._edges[this.getEdgeKey(target, "inbound")] = [
|
|
200
|
+
source
|
|
201
|
+
];
|
|
202
|
+
} else if (!inbound.includes(source)) {
|
|
203
|
+
inbound.push(source);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
62
206
|
}
|
|
63
207
|
/**
|
|
64
|
-
*
|
|
208
|
+
* Sort edges for a node.
|
|
209
|
+
*
|
|
210
|
+
* Edges not included in the sorted list are appended to the end of the list.
|
|
211
|
+
*
|
|
212
|
+
* @param nodeId The id of the node to sort edges for.
|
|
213
|
+
* @param direction The direction of the edges from the node to sort.
|
|
214
|
+
* @param edges The ordered list of edges.
|
|
65
215
|
*/
|
|
66
|
-
|
|
216
|
+
sortEdges(nodeId, direction, edges) {
|
|
217
|
+
untracked(() => {
|
|
218
|
+
const current = this._edges[this.getEdgeKey(nodeId, direction)];
|
|
219
|
+
if (current) {
|
|
220
|
+
const unsorted = current.filter((id) => !edges.includes(id)) ?? [];
|
|
221
|
+
const sorted = edges.filter((id) => current.includes(id)) ?? [];
|
|
222
|
+
current.splice(0, current.length, ...[
|
|
223
|
+
...sorted,
|
|
224
|
+
...unsorted
|
|
225
|
+
]);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Remove an edge from the graph.
|
|
231
|
+
*/
|
|
232
|
+
removeEdge({ source, target }) {
|
|
233
|
+
untracked(() => {
|
|
234
|
+
const outboundIndex = this._edges[this.getEdgeKey(source, "outbound")]?.findIndex((id) => id === target);
|
|
235
|
+
if (outboundIndex !== -1) {
|
|
236
|
+
this._edges[this.getEdgeKey(source, "outbound")].splice(outboundIndex, 1);
|
|
237
|
+
}
|
|
238
|
+
const inboundIndex = this._edges[this.getEdgeKey(target, "inbound")]?.findIndex((id) => id === source);
|
|
239
|
+
if (inboundIndex !== -1) {
|
|
240
|
+
this._edges[this.getEdgeKey(target, "inbound")].splice(inboundIndex, 1);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Recursive depth-first traversal.
|
|
246
|
+
*
|
|
247
|
+
* @param options.node The node to start traversing from.
|
|
248
|
+
* @param options.direction The direction to traverse graph edges.
|
|
249
|
+
* @param options.filter A predicate to filter nodes which are passed to the `visitor` callback.
|
|
250
|
+
* @param options.visitor A callback which is called for each node visited during traversal.
|
|
251
|
+
*/
|
|
252
|
+
traverse({ node = this.root, direction = "outbound", filter, visitor }, path = []) {
|
|
253
|
+
if (path.includes(node.id)) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
67
256
|
if (!filter || filter(node)) {
|
|
68
|
-
visitor?.(node,
|
|
257
|
+
visitor?.(node, [
|
|
258
|
+
...path,
|
|
259
|
+
node.id
|
|
260
|
+
]);
|
|
69
261
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
262
|
+
Object.values(this._getNodes({
|
|
263
|
+
id: node.id,
|
|
264
|
+
direction
|
|
265
|
+
})).forEach((child) => this.traverse({
|
|
266
|
+
node: child,
|
|
267
|
+
direction,
|
|
268
|
+
filter,
|
|
269
|
+
visitor
|
|
270
|
+
}, [
|
|
271
|
+
...path,
|
|
272
|
+
node.id
|
|
273
|
+
]));
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Get the path between two nodes in the graph.
|
|
277
|
+
*/
|
|
278
|
+
getPath({ source = "root", target }) {
|
|
279
|
+
const start = this.findNode(source);
|
|
280
|
+
if (!start) {
|
|
281
|
+
return void 0;
|
|
83
282
|
}
|
|
283
|
+
let found;
|
|
284
|
+
this.traverse({
|
|
285
|
+
node: start,
|
|
286
|
+
filter: () => !found,
|
|
287
|
+
visitor: (node, path) => {
|
|
288
|
+
if (node.id === target) {
|
|
289
|
+
found = path;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
return found;
|
|
84
294
|
}
|
|
85
295
|
};
|
|
86
296
|
|
|
87
297
|
// packages/sdk/app-graph/src/graph-builder.ts
|
|
88
|
-
import { untracked } from "@preact/signals-core";
|
|
89
|
-
import { deepSignal as deepSignal2 } from "deepsignal/react";
|
|
90
298
|
import { EventSubscriptions } from "@dxos/async";
|
|
91
|
-
import { Keyboard } from "@dxos/keyboard";
|
|
92
|
-
import { getHostPlatform } from "@dxos/util";
|
|
93
|
-
var KEY_BINDING = "KeyBinding";
|
|
94
299
|
var GraphBuilder = class {
|
|
95
300
|
constructor() {
|
|
96
|
-
this.
|
|
97
|
-
this._unsubscribe =
|
|
301
|
+
this._extensions = /* @__PURE__ */ new Map();
|
|
302
|
+
this._unsubscribe = new EventSubscriptions();
|
|
98
303
|
}
|
|
99
304
|
/**
|
|
100
305
|
* Register a node builder which will be called in order to construct the graph.
|
|
101
306
|
*/
|
|
102
|
-
|
|
103
|
-
this.
|
|
307
|
+
addExtension(id, extension) {
|
|
308
|
+
this._extensions.set(id, extension);
|
|
104
309
|
return this;
|
|
105
310
|
}
|
|
106
311
|
/**
|
|
107
312
|
* Remove a node builder from the graph builder.
|
|
108
313
|
*/
|
|
109
|
-
|
|
110
|
-
this.
|
|
314
|
+
removeExtension(id) {
|
|
315
|
+
this._extensions.delete(id);
|
|
111
316
|
return this;
|
|
112
317
|
}
|
|
113
318
|
/**
|
|
114
|
-
* Construct the graph, starting by calling all registered
|
|
115
|
-
* Node builders will be filtered out as they are used such that they are only used once on any given path.
|
|
319
|
+
* Construct the graph, starting by calling all registered extensions.
|
|
116
320
|
* @param previousGraph If provided, the graph will be updated in place.
|
|
117
|
-
* @param startingPath If provided, the graph will be updated starting at the given path.
|
|
118
|
-
*/
|
|
119
|
-
build(previousGraph, startingPath = []) {
|
|
120
|
-
const graph = previousGraph ?? new Graph(this._createNode(() => graph, {
|
|
121
|
-
id: "root",
|
|
122
|
-
label: "Root"
|
|
123
|
-
}));
|
|
124
|
-
return this._build(graph, graph.root, startingPath);
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Called recursively.
|
|
128
321
|
*/
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
unsubscribe && subscriptions.add(unsubscribe);
|
|
322
|
+
build(previousGraph) {
|
|
323
|
+
this._unsubscribe.clear();
|
|
324
|
+
const graph = previousGraph ?? new Graph();
|
|
325
|
+
Array.from(this._extensions.values()).forEach((builder) => {
|
|
326
|
+
const unsubscribe = builder(graph);
|
|
327
|
+
unsubscribe && this._unsubscribe.add(unsubscribe);
|
|
136
328
|
});
|
|
137
|
-
this._unsubscribe.set(node.id, subscriptions);
|
|
138
329
|
return graph;
|
|
139
330
|
}
|
|
140
|
-
_createNode(getGraph, partial, path = [], ignoreBuilders = []) {
|
|
141
|
-
const node = deepSignal2({
|
|
142
|
-
parent: null,
|
|
143
|
-
data: null,
|
|
144
|
-
properties: {},
|
|
145
|
-
childrenMap: {},
|
|
146
|
-
actionsMap: {},
|
|
147
|
-
// TODO(burdon): Document.
|
|
148
|
-
...partial,
|
|
149
|
-
get children() {
|
|
150
|
-
return Object.values(node.childrenMap);
|
|
151
|
-
},
|
|
152
|
-
get actions() {
|
|
153
|
-
return Object.values(node.actionsMap);
|
|
154
|
-
},
|
|
155
|
-
//
|
|
156
|
-
// Properties
|
|
157
|
-
//
|
|
158
|
-
addProperty: (key, value) => {
|
|
159
|
-
untracked(() => {
|
|
160
|
-
node.properties[key] = value;
|
|
161
|
-
});
|
|
162
|
-
},
|
|
163
|
-
removeProperty: (key) => {
|
|
164
|
-
untracked(() => {
|
|
165
|
-
delete node.properties[key];
|
|
166
|
-
});
|
|
167
|
-
},
|
|
168
|
-
//
|
|
169
|
-
// Nodes
|
|
170
|
-
//
|
|
171
|
-
addNode: (builder, ...partials) => {
|
|
172
|
-
return untracked(() => {
|
|
173
|
-
return partials.map((partial2) => {
|
|
174
|
-
const builders = [
|
|
175
|
-
...ignoreBuilders,
|
|
176
|
-
builder
|
|
177
|
-
];
|
|
178
|
-
const childPath = [
|
|
179
|
-
...path,
|
|
180
|
-
"childrenMap",
|
|
181
|
-
partial2.id
|
|
182
|
-
];
|
|
183
|
-
const child = this._createNode(getGraph, {
|
|
184
|
-
...partial2,
|
|
185
|
-
parent: node
|
|
186
|
-
}, childPath, builders);
|
|
187
|
-
node.childrenMap[child.id] = child;
|
|
188
|
-
this._build(getGraph(), child, childPath, builders);
|
|
189
|
-
return child;
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
},
|
|
193
|
-
removeNode: (id) => {
|
|
194
|
-
return untracked(() => {
|
|
195
|
-
const child = node.childrenMap[id];
|
|
196
|
-
delete node.childrenMap[id];
|
|
197
|
-
return child;
|
|
198
|
-
});
|
|
199
|
-
},
|
|
200
|
-
//
|
|
201
|
-
// Actions
|
|
202
|
-
//
|
|
203
|
-
addAction: (...partials) => {
|
|
204
|
-
return untracked(() => {
|
|
205
|
-
return partials.map((partial2) => {
|
|
206
|
-
const action = this._createAction(partial2);
|
|
207
|
-
let shortcut;
|
|
208
|
-
if (typeof action.keyBinding === "object") {
|
|
209
|
-
const availablePlatforms = Object.keys(action.keyBinding);
|
|
210
|
-
const platform = getHostPlatform();
|
|
211
|
-
shortcut = availablePlatforms.includes(platform) ? action.keyBinding[platform] : platform === "ios" ? action.keyBinding.macos : platform === "linux" || platform === "unknown" ? action.keyBinding.windows : void 0;
|
|
212
|
-
} else {
|
|
213
|
-
shortcut = action.keyBinding;
|
|
214
|
-
}
|
|
215
|
-
if (shortcut) {
|
|
216
|
-
Keyboard.singleton.getContext(path.join("/")).bind({
|
|
217
|
-
shortcut,
|
|
218
|
-
handler: () => {
|
|
219
|
-
action.invoke({
|
|
220
|
-
caller: KEY_BINDING
|
|
221
|
-
});
|
|
222
|
-
},
|
|
223
|
-
data: action.label
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
node.actionsMap[action.id] = action;
|
|
227
|
-
return action;
|
|
228
|
-
});
|
|
229
|
-
});
|
|
230
|
-
},
|
|
231
|
-
removeAction: (id) => {
|
|
232
|
-
return untracked(() => {
|
|
233
|
-
const action = node.actionsMap[id];
|
|
234
|
-
if (action.keyBinding) {
|
|
235
|
-
}
|
|
236
|
-
delete node.actionsMap[id];
|
|
237
|
-
return action;
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
partial.actions && partial.actions.forEach((action) => node.addAction(action));
|
|
242
|
-
return node;
|
|
243
|
-
}
|
|
244
|
-
_createAction(partial) {
|
|
245
|
-
const action = deepSignal2({
|
|
246
|
-
properties: {},
|
|
247
|
-
...partial,
|
|
248
|
-
actionsMap: {},
|
|
249
|
-
get actions() {
|
|
250
|
-
return Object.values(action.actionsMap);
|
|
251
|
-
},
|
|
252
|
-
addAction: (...partials) => {
|
|
253
|
-
return untracked(() => {
|
|
254
|
-
return partials.map((partial2) => {
|
|
255
|
-
const subAction = this._createAction(partial2);
|
|
256
|
-
action.actionsMap[subAction.id] = subAction;
|
|
257
|
-
return subAction;
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
},
|
|
261
|
-
removeAction: (id) => {
|
|
262
|
-
return untracked(() => {
|
|
263
|
-
const subAction = action.actionsMap[id];
|
|
264
|
-
delete action.actionsMap[id];
|
|
265
|
-
return subAction;
|
|
266
|
-
});
|
|
267
|
-
},
|
|
268
|
-
addProperty: (key, value) => {
|
|
269
|
-
return untracked(() => {
|
|
270
|
-
action.properties[key] = value;
|
|
271
|
-
});
|
|
272
|
-
},
|
|
273
|
-
removeProperty: (key) => {
|
|
274
|
-
return untracked(() => {
|
|
275
|
-
delete action.properties[key];
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
partial.actions && partial.actions.forEach((subAction) => action.addAction(subAction));
|
|
280
|
-
return action;
|
|
281
|
-
}
|
|
282
331
|
};
|
|
283
332
|
|
|
284
|
-
// packages/sdk/app-graph/src/
|
|
285
|
-
var
|
|
333
|
+
// packages/sdk/app-graph/src/helpers.ts
|
|
334
|
+
var manageNodes = ({ graph, condition, nodes, removeEdges }) => {
|
|
335
|
+
if (condition) {
|
|
336
|
+
return graph.addNodes(...nodes);
|
|
337
|
+
} else {
|
|
338
|
+
nodes.forEach(({ id }) => graph.removeNode(id, removeEdges));
|
|
339
|
+
}
|
|
340
|
+
};
|
|
286
341
|
export {
|
|
287
342
|
Graph,
|
|
288
343
|
GraphBuilder,
|
|
289
|
-
|
|
290
|
-
|
|
344
|
+
ROOT_ID,
|
|
345
|
+
actionGroupSymbol,
|
|
346
|
+
isAction,
|
|
347
|
+
isActionGroup,
|
|
348
|
+
isActionLike,
|
|
349
|
+
isGraphNode,
|
|
350
|
+
manageNodes
|
|
291
351
|
};
|
|
292
352
|
//# sourceMappingURL=index.mjs.map
|