@babsey/code-graph 0.0.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/LICENSE +21 -0
- package/README.md +39 -0
- package/dist/code-graph.css +37 -0
- package/dist/code-graph.js +1799 -0
- package/dist/code-graph.umd.cjs +1820 -0
- package/package.json +65 -0
|
@@ -0,0 +1,1799 @@
|
|
|
1
|
+
import { AbstractNode, NodeInterfaceType, NodeInterface, ButtonInterfaceComponent, CheckboxInterfaceComponent, IntegerInterfaceComponent, NumberInterfaceComponent, SelectInterfaceComponent, SliderInterfaceComponent, TextInputInterfaceComponent, TextareaInputInterfaceComponent, setType, allowMultipleConnections, IntegerInterface as IntegerInterface$1, TextInputInterface as TextInputInterface$1, displayInSidebar, sortTopologically, useViewModel, useTemporaryConnection, Components, useGraph, GRAPH_NODE_TYPE_PREFIX, useTransform, useNodeCategories, BaklavaEditor, DEFAULT_TOOLBAR_COMMANDS, useBaklava, DependencyEngine, applyResult } from "baklavajs";
|
|
2
|
+
import { ButtonInterfaceComponent as ButtonInterfaceComponent2, CheckboxInterfaceComponent as CheckboxInterfaceComponent2, IntegerInterfaceComponent as IntegerInterfaceComponent2, NumberInterfaceComponent as NumberInterfaceComponent2, SelectInterfaceComponent as SelectInterfaceComponent2, SliderInterfaceComponent as SliderInterfaceComponent2, TextInputInterfaceComponent as TextInputInterfaceComponent2, TextareaInputInterfaceComponent as TextareaInputInterfaceComponent2 } from "baklavajs";
|
|
3
|
+
import mustache from "mustache";
|
|
4
|
+
import { reactive, defineComponent, createElementBlock, openBlock, toDisplayString, markRaw, ref, computed, onMounted, onUpdated, normalizeClass, createCommentVNode, createElementVNode, unref, renderSlot, createStaticVNode, onBeforeUnmount, normalizeStyle, withModifiers, createBlock, withDirectives, Fragment, createTextVNode, createVNode, withKeys, vModelText, renderList, nextTick, toRef, resolveDynamicComponent, inject, Transition, withCtx, onUnmounted, normalizeProps, guardReactiveProps, mergeProps } from "vue";
|
|
5
|
+
import toposort from "toposort";
|
|
6
|
+
import { v4 } from "uuid";
|
|
7
|
+
import { usePointer } from "@vueuse/core";
|
|
8
|
+
class AbstractCodeNode extends AbstractNode {
|
|
9
|
+
state;
|
|
10
|
+
code;
|
|
11
|
+
isCodeNode = true;
|
|
12
|
+
inputs = {};
|
|
13
|
+
outputs = {};
|
|
14
|
+
constructor() {
|
|
15
|
+
super();
|
|
16
|
+
this.initializeIo();
|
|
17
|
+
this.width = 400;
|
|
18
|
+
this.twoColumn = true;
|
|
19
|
+
this.state = reactive({
|
|
20
|
+
codeTemplate: "{{ &outputs.code }}",
|
|
21
|
+
hidden: false,
|
|
22
|
+
integrated: false,
|
|
23
|
+
modules: [],
|
|
24
|
+
script: "",
|
|
25
|
+
variableName: ""
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
get codeTemplate() {
|
|
29
|
+
return this.state.codeTemplate;
|
|
30
|
+
}
|
|
31
|
+
get idx() {
|
|
32
|
+
return this.code?.codeNodes.filter((node) => !node.state.integrated).indexOf(this) ?? -1;
|
|
33
|
+
}
|
|
34
|
+
get idxByVariableNames() {
|
|
35
|
+
return this.code?.getNodesBySameVariableNames(this.state.variableName).indexOf(this) ?? -1;
|
|
36
|
+
}
|
|
37
|
+
get script() {
|
|
38
|
+
return this.state.script;
|
|
39
|
+
}
|
|
40
|
+
get shortId() {
|
|
41
|
+
return this.id.slice(0, 6);
|
|
42
|
+
}
|
|
43
|
+
get variableName() {
|
|
44
|
+
return this.state.variableName ? this.state.variableName + (this.idxByVariableNames + 1) : "";
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get connected nodes to the node.
|
|
48
|
+
* @param type inputs or outputs
|
|
49
|
+
* @returns code node instances
|
|
50
|
+
*/
|
|
51
|
+
getConnectedNodes(type) {
|
|
52
|
+
let nodeIds = [];
|
|
53
|
+
if (type !== "inputs") {
|
|
54
|
+
const targets = this.graph?.connections.filter((c) => c.from.name !== "_node").filter((c) => c.from.nodeId === this.id).map((c) => c.to.nodeId);
|
|
55
|
+
if (targets) nodeIds = nodeIds.concat(targets);
|
|
56
|
+
}
|
|
57
|
+
if (type !== "outputs") {
|
|
58
|
+
const sources = this.graph?.connections.filter((c) => c.from.name !== "_node").filter((c) => c.to.nodeId === this.id).map((c) => c.from.nodeId);
|
|
59
|
+
if (sources) nodeIds = nodeIds.concat(sources);
|
|
60
|
+
}
|
|
61
|
+
if (!nodeIds || nodeIds.length == 0) return [];
|
|
62
|
+
return nodeIds.map((nodeId) => this.graph?.findNodeById(nodeId));
|
|
63
|
+
}
|
|
64
|
+
registerCode(code) {
|
|
65
|
+
this.code = code;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Render code of this node.
|
|
69
|
+
*/
|
|
70
|
+
renderCode() {
|
|
71
|
+
const inputs = {};
|
|
72
|
+
Object.keys(this.inputs).forEach((intfKey) => {
|
|
73
|
+
if (intfKey === "_node") return;
|
|
74
|
+
const intf = this.inputs[intfKey];
|
|
75
|
+
const value = intf.isString ? `'${intf.value}'` : intf.value;
|
|
76
|
+
if (intf && intf.state) inputs[intfKey] = intf.state.script.length > 0 ? intf.state.script : value;
|
|
77
|
+
});
|
|
78
|
+
const outputs = {};
|
|
79
|
+
Object.keys(this.outputs).forEach((intfKey) => {
|
|
80
|
+
if (intfKey === "_node") return;
|
|
81
|
+
const intf = this.outputs[intfKey];
|
|
82
|
+
const value = intf.isString ? `'${intf.value}'` : intf.value;
|
|
83
|
+
if (intf && intf.state) outputs[intfKey] = value;
|
|
84
|
+
});
|
|
85
|
+
this.state.script = mustache.render(this.state.codeTemplate, { inputs, outputs });
|
|
86
|
+
if (this.outputs.code) this.outputs.code.state.script = this.state.script;
|
|
87
|
+
}
|
|
88
|
+
updateOutputVariableName() {
|
|
89
|
+
if (this.outputs.code) this.outputs.code.name = this.variableName;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
class CodeNode extends AbstractCodeNode {
|
|
93
|
+
/**
|
|
94
|
+
* The default implementation does nothing.
|
|
95
|
+
* Overwrite this method to do calculation.
|
|
96
|
+
* @param inputs Values of all input interfaces
|
|
97
|
+
* @param globalValues Set of values passed to every node by the engine plugin
|
|
98
|
+
* @return Values for output interfaces
|
|
99
|
+
*/
|
|
100
|
+
calculate;
|
|
101
|
+
load(state) {
|
|
102
|
+
super.load(state);
|
|
103
|
+
loadNodeState(this.graph, state);
|
|
104
|
+
}
|
|
105
|
+
save() {
|
|
106
|
+
const state = super.save();
|
|
107
|
+
saveNodeState(this.graph, state);
|
|
108
|
+
return state;
|
|
109
|
+
}
|
|
110
|
+
updateModules(modules) {
|
|
111
|
+
if (modules) {
|
|
112
|
+
this.state.modules = modules;
|
|
113
|
+
} else if (this.type.includes(".")) {
|
|
114
|
+
const modules2 = this.type.split(".");
|
|
115
|
+
this.state.modules.push(modules2.slice(0, modules2.length - 1).join("."));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const loadNodeState = (graph, nodeState) => {
|
|
120
|
+
if (!graph) return;
|
|
121
|
+
const node = graph.findNodeById(nodeState.id);
|
|
122
|
+
if (!node || node.subgraph) return;
|
|
123
|
+
const codeNode = node;
|
|
124
|
+
if (codeNode.state) {
|
|
125
|
+
codeNode.state.integrated = nodeState.integrated;
|
|
126
|
+
codeNode.state.modules = nodeState.modules;
|
|
127
|
+
codeNode.state.props = nodeState.props;
|
|
128
|
+
}
|
|
129
|
+
Object.entries(nodeState.inputs).forEach(([inputKey, inputItem]) => {
|
|
130
|
+
if (inputKey === "_node") return;
|
|
131
|
+
if (codeNode.inputs[inputKey]) codeNode.inputs[inputKey].hidden = inputItem.hidden;
|
|
132
|
+
});
|
|
133
|
+
Object.entries(nodeState.outputs).forEach(([outputKey, outputItem]) => {
|
|
134
|
+
if (outputKey === "_node") return;
|
|
135
|
+
if (codeNode.outputs[outputKey]) codeNode.outputs[outputKey].hidden = outputItem.hidden;
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
const saveNodeState = (graph, nodeState) => {
|
|
139
|
+
if (!graph) return;
|
|
140
|
+
const node = graph.findNodeById(nodeState.id);
|
|
141
|
+
if (!node || node.subgraph) return;
|
|
142
|
+
const codeNode = node;
|
|
143
|
+
if (codeNode.state) {
|
|
144
|
+
nodeState.integrated = codeNode.state.integrated;
|
|
145
|
+
nodeState.modules = codeNode.state.modules;
|
|
146
|
+
}
|
|
147
|
+
Object.entries(nodeState.inputs).forEach(([inputKey, inputItem]) => {
|
|
148
|
+
if (inputKey === "_node") return;
|
|
149
|
+
if (codeNode.inputs[inputKey]) inputItem.hidden = codeNode.inputs[inputKey].hidden;
|
|
150
|
+
});
|
|
151
|
+
Object.entries(nodeState.outputs).forEach(([outputKey, outputItem]) => {
|
|
152
|
+
if (outputKey === "_node") return;
|
|
153
|
+
if (codeNode.outputs[outputKey]) outputItem.hidden = codeNode.outputs[outputKey].hidden;
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
new NodeInterfaceType("boolean");
|
|
157
|
+
new NodeInterfaceType("dict");
|
|
158
|
+
new NodeInterfaceType("list");
|
|
159
|
+
const nodeType = new NodeInterfaceType("node");
|
|
160
|
+
const numberType = new NodeInterfaceType("number");
|
|
161
|
+
const stringType = new NodeInterfaceType("string");
|
|
162
|
+
const _hoisted_1$f = ["title"];
|
|
163
|
+
const _sfc_main$g = /* @__PURE__ */ defineComponent({
|
|
164
|
+
__name: "CodeNodeInterface",
|
|
165
|
+
props: {
|
|
166
|
+
intf: {}
|
|
167
|
+
},
|
|
168
|
+
setup(__props) {
|
|
169
|
+
return (_ctx, _cache) => {
|
|
170
|
+
return openBlock(), createElementBlock("div", {
|
|
171
|
+
title: _ctx.intf.state?.script
|
|
172
|
+
}, toDisplayString(_ctx.intf.name), 9, _hoisted_1$f);
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
class CodeNodeInterface extends NodeInterface {
|
|
177
|
+
optional = false;
|
|
178
|
+
code;
|
|
179
|
+
state;
|
|
180
|
+
constructor(name, value) {
|
|
181
|
+
super(name, value);
|
|
182
|
+
this.setComponent(markRaw(_sfc_main$g));
|
|
183
|
+
this.state = reactive({
|
|
184
|
+
script: ""
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
get shortId() {
|
|
188
|
+
return this.id.slice(0, 6);
|
|
189
|
+
}
|
|
190
|
+
// override get value(): T {
|
|
191
|
+
// return super.value
|
|
192
|
+
// }
|
|
193
|
+
// override set value(value: T) {
|
|
194
|
+
// super.value = value;
|
|
195
|
+
// if (this.name !== '_node') this.setHidden(false);
|
|
196
|
+
// }
|
|
197
|
+
}
|
|
198
|
+
class ButtonInterface extends CodeNodeInterface {
|
|
199
|
+
component = markRaw(ButtonInterfaceComponent);
|
|
200
|
+
callback;
|
|
201
|
+
constructor(name, callback) {
|
|
202
|
+
super(name, void 0);
|
|
203
|
+
this.callback = callback;
|
|
204
|
+
this.setPort(false);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
class CheckboxInterface extends CodeNodeInterface {
|
|
208
|
+
component = markRaw(CheckboxInterfaceComponent);
|
|
209
|
+
}
|
|
210
|
+
class BaseNumericInterface extends CodeNodeInterface {
|
|
211
|
+
min;
|
|
212
|
+
max;
|
|
213
|
+
constructor(name, value, min, max) {
|
|
214
|
+
super(name, value);
|
|
215
|
+
this.min = min;
|
|
216
|
+
this.max = max;
|
|
217
|
+
}
|
|
218
|
+
validate(v) {
|
|
219
|
+
return (this.min === void 0 || v >= this.min) && (this.max === void 0 || v <= this.max);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
class IntegerInterface extends BaseNumericInterface {
|
|
223
|
+
component = markRaw(IntegerInterfaceComponent);
|
|
224
|
+
validate(v) {
|
|
225
|
+
return Number.isInteger(v) && super.validate(v);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
class CodeInputInterface extends CodeNodeInterface {
|
|
229
|
+
isCodeInput = true;
|
|
230
|
+
constructor(name = "", value) {
|
|
231
|
+
super(name, value);
|
|
232
|
+
this.setComponent(markRaw(_sfc_main$g));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
class CodeOutputInterface extends CodeNodeInterface {
|
|
236
|
+
isCodeOutput = true;
|
|
237
|
+
constructor(name = "", value = "") {
|
|
238
|
+
super(name, value);
|
|
239
|
+
this.setComponent(markRaw(_sfc_main$g));
|
|
240
|
+
}
|
|
241
|
+
get script() {
|
|
242
|
+
return this.state.script;
|
|
243
|
+
}
|
|
244
|
+
get value() {
|
|
245
|
+
return super.value;
|
|
246
|
+
}
|
|
247
|
+
set value(value) {
|
|
248
|
+
super.value = value;
|
|
249
|
+
this.state.script = this.name.length > 0 ? this.name : this.value;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
class NumberInterface extends BaseNumericInterface {
|
|
253
|
+
component = markRaw(NumberInterfaceComponent);
|
|
254
|
+
}
|
|
255
|
+
class SelectInterface extends CodeNodeInterface {
|
|
256
|
+
component = markRaw(SelectInterfaceComponent);
|
|
257
|
+
items;
|
|
258
|
+
constructor(name, value, items) {
|
|
259
|
+
super(name, value);
|
|
260
|
+
this.items = items;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
class SliderInterface extends BaseNumericInterface {
|
|
264
|
+
component = markRaw(SliderInterfaceComponent);
|
|
265
|
+
min;
|
|
266
|
+
max;
|
|
267
|
+
constructor(name, value, min, max) {
|
|
268
|
+
super(name, value, min, max);
|
|
269
|
+
this.min = min;
|
|
270
|
+
this.max = max;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
class TextInterface extends CodeNodeInterface {
|
|
274
|
+
component = markRaw(TextInputInterfaceComponent);
|
|
275
|
+
constructor(name, value) {
|
|
276
|
+
super(name, value);
|
|
277
|
+
this.setPort(false);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
class TextInputInterface extends CodeNodeInterface {
|
|
281
|
+
isString = true;
|
|
282
|
+
component = markRaw(TextInputInterfaceComponent);
|
|
283
|
+
}
|
|
284
|
+
class TextareaInputInterface extends CodeNodeInterface {
|
|
285
|
+
component = markRaw(TextareaInputInterfaceComponent);
|
|
286
|
+
}
|
|
287
|
+
function defineCodeNode(definition) {
|
|
288
|
+
return class extends CodeNode {
|
|
289
|
+
type = definition.type;
|
|
290
|
+
inputs = {};
|
|
291
|
+
outputs = {};
|
|
292
|
+
constructor() {
|
|
293
|
+
super();
|
|
294
|
+
this._title = definition.title ?? definition.type;
|
|
295
|
+
this.updateModules(definition.modules);
|
|
296
|
+
if (definition.codeTemplate) this.state.codeTemplate = definition.codeTemplate(this);
|
|
297
|
+
if (definition.variableName) this.state.variableName = definition.variableName;
|
|
298
|
+
this.addInput(
|
|
299
|
+
"_node",
|
|
300
|
+
new CodeNodeInterface("", []).use(setType, nodeType).use(allowMultipleConnections).setHidden(true)
|
|
301
|
+
);
|
|
302
|
+
this.addOutput(
|
|
303
|
+
"_node",
|
|
304
|
+
new CodeNodeInterface("", []).use(setType, nodeType).use(allowMultipleConnections).setHidden(true)
|
|
305
|
+
);
|
|
306
|
+
this.executeFactory("input", definition.inputs);
|
|
307
|
+
this.executeFactory("output", definition.outputs);
|
|
308
|
+
definition.onCreate?.call(this);
|
|
309
|
+
}
|
|
310
|
+
calculate = definition.calculate ? (inputs, globalValues) => ({
|
|
311
|
+
...definition.calculate.call(this, inputs, globalValues),
|
|
312
|
+
_node: null
|
|
313
|
+
}) : void 0;
|
|
314
|
+
onPlaced() {
|
|
315
|
+
definition.onPlaced?.call(this);
|
|
316
|
+
}
|
|
317
|
+
onDestroy() {
|
|
318
|
+
definition.onDestroy?.call(this);
|
|
319
|
+
}
|
|
320
|
+
onCodeUpdate() {
|
|
321
|
+
definition.onCodeUpdate?.call(this);
|
|
322
|
+
}
|
|
323
|
+
executeFactory(type, factory) {
|
|
324
|
+
Object.keys(factory || {}).forEach((k) => {
|
|
325
|
+
const intf = factory[k]();
|
|
326
|
+
if (type === "input") {
|
|
327
|
+
this.addInput(k, intf);
|
|
328
|
+
} else {
|
|
329
|
+
this.addOutput(k, intf);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
class DynamicCodeNode extends CodeNode {
|
|
336
|
+
/**
|
|
337
|
+
* The default implementation does nothing.
|
|
338
|
+
* Overwrite this method to do calculation.
|
|
339
|
+
* @param inputs Values of all input interfaces
|
|
340
|
+
* @param globalValues Set of values passed to every node by the engine plugin
|
|
341
|
+
* @return Values for output interfaces
|
|
342
|
+
*/
|
|
343
|
+
calculate;
|
|
344
|
+
}
|
|
345
|
+
function defineDynamicCodeNode(definition) {
|
|
346
|
+
return class extends DynamicCodeNode {
|
|
347
|
+
type = definition.type;
|
|
348
|
+
inputs = {};
|
|
349
|
+
outputs = {};
|
|
350
|
+
calculate;
|
|
351
|
+
preventUpdate = false;
|
|
352
|
+
staticInputKeys = Object.keys(definition.inputs ?? {});
|
|
353
|
+
staticOutputKeys = Object.keys(definition.outputs ?? {});
|
|
354
|
+
constructor() {
|
|
355
|
+
super();
|
|
356
|
+
this._title = definition.title ?? definition.type;
|
|
357
|
+
this.updateModules(definition.modules);
|
|
358
|
+
if (definition.codeTemplate) this.state.codeTemplate = definition.codeTemplate(this);
|
|
359
|
+
if (definition.variableName) this.state.variableName = definition.variableName;
|
|
360
|
+
this.addInput(
|
|
361
|
+
"_node",
|
|
362
|
+
new CodeNodeInterface("", []).use(setType, nodeType).use(allowMultipleConnections).setHidden(true)
|
|
363
|
+
);
|
|
364
|
+
this.addOutput(
|
|
365
|
+
"_node",
|
|
366
|
+
new CodeNodeInterface("", []).use(setType, nodeType).use(allowMultipleConnections).setHidden(true)
|
|
367
|
+
);
|
|
368
|
+
this.staticInputKeys.push("_node");
|
|
369
|
+
this.staticOutputKeys.push("_node");
|
|
370
|
+
this.executeFactory("input", definition.inputs);
|
|
371
|
+
this.executeFactory("output", definition.outputs);
|
|
372
|
+
if (definition.calculate) {
|
|
373
|
+
this.calculate = (inputs, globalValues) => ({
|
|
374
|
+
...definition.calculate?.call(this, inputs, globalValues),
|
|
375
|
+
_node: null
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
definition.onCreate?.call(this);
|
|
379
|
+
}
|
|
380
|
+
onPlaced() {
|
|
381
|
+
this.events.update.subscribe(this, (data) => {
|
|
382
|
+
if (!data) return;
|
|
383
|
+
if (data.type === "input" && this.staticInputKeys.includes(data.name) || data.type === "output" && this.staticOutputKeys.includes(data.name)) {
|
|
384
|
+
this.onUpdate();
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
this.onUpdate();
|
|
388
|
+
definition.onPlaced?.call(this);
|
|
389
|
+
}
|
|
390
|
+
onDestroy() {
|
|
391
|
+
definition.onDestroy?.call(this);
|
|
392
|
+
}
|
|
393
|
+
onCodeUpdate() {
|
|
394
|
+
definition.onCodeUpdate?.call(this);
|
|
395
|
+
}
|
|
396
|
+
load(state) {
|
|
397
|
+
this.preventUpdate = true;
|
|
398
|
+
this.hooks.beforeLoad.execute(state);
|
|
399
|
+
this.id = state.id;
|
|
400
|
+
this.title = state.title;
|
|
401
|
+
for (const k of this.staticInputKeys) {
|
|
402
|
+
this.inputs[k].load(state.inputs[k]);
|
|
403
|
+
this.inputs[k].nodeId = this.id;
|
|
404
|
+
if (k === "_node") continue;
|
|
405
|
+
this.inputs[k].hidden = state.inputs[k].hidden;
|
|
406
|
+
}
|
|
407
|
+
for (const k of this.staticOutputKeys) {
|
|
408
|
+
this.outputs[k].load(state.outputs[k]);
|
|
409
|
+
this.outputs[k].nodeId = this.id;
|
|
410
|
+
if (k === "_node") continue;
|
|
411
|
+
this.outputs[k].hidden = state.outputs[k].hidden;
|
|
412
|
+
}
|
|
413
|
+
this.preventUpdate = false;
|
|
414
|
+
this.onUpdate();
|
|
415
|
+
this.preventUpdate = true;
|
|
416
|
+
for (const k of Object.keys(state.inputs)) {
|
|
417
|
+
if (this.staticInputKeys.includes(k)) continue;
|
|
418
|
+
if (!this.inputs[k]) {
|
|
419
|
+
const value = state.inputs[k].value;
|
|
420
|
+
let inputInterface;
|
|
421
|
+
if (typeof value == "number") {
|
|
422
|
+
inputInterface = new IntegerInterface$1(k, value).use(setType, numberType);
|
|
423
|
+
} else {
|
|
424
|
+
inputInterface = new TextInputInterface$1(k, JSON.stringify(value)).use(setType, stringType);
|
|
425
|
+
}
|
|
426
|
+
inputInterface.use(displayInSidebar, true);
|
|
427
|
+
this.addInput(k, inputInterface);
|
|
428
|
+
}
|
|
429
|
+
if (this.inputs[k]) {
|
|
430
|
+
this.inputs[k].load(state.inputs[k]);
|
|
431
|
+
this.inputs[k].nodeId = this.id;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
for (const k of Object.keys(state.outputs)) {
|
|
435
|
+
if (this.staticOutputKeys.includes(k)) continue;
|
|
436
|
+
if (!this.outputs[k]) {
|
|
437
|
+
const outputInterface = new CodeOutputInterface(k);
|
|
438
|
+
this.addOutput(k, outputInterface);
|
|
439
|
+
}
|
|
440
|
+
if (this.outputs[k]) {
|
|
441
|
+
this.outputs[k].load(state.outputs[k]);
|
|
442
|
+
this.outputs[k].nodeId = this.id;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
loadNodeState(this.graph, state);
|
|
446
|
+
this.preventUpdate = false;
|
|
447
|
+
this.events.loaded.emit(this);
|
|
448
|
+
}
|
|
449
|
+
onUpdate() {
|
|
450
|
+
if (this.preventUpdate) return;
|
|
451
|
+
if (this.graph) this.graph.activeTransactions++;
|
|
452
|
+
const inputValues = this.getStaticValues(this.staticInputKeys, this.inputs);
|
|
453
|
+
const outputValues = this.getStaticValues(this.staticOutputKeys, this.outputs);
|
|
454
|
+
const result = definition.onUpdate.call(this, inputValues, outputValues);
|
|
455
|
+
this.updateInterfaces("input", result.inputs ?? {}, result.forceUpdateInputs ?? []);
|
|
456
|
+
this.updateInterfaces("output", result.outputs ?? {}, result.forceUpdateOutputs ?? []);
|
|
457
|
+
if (this.graph) this.graph.activeTransactions--;
|
|
458
|
+
}
|
|
459
|
+
getStaticValues(keys, interfaces) {
|
|
460
|
+
const values = {};
|
|
461
|
+
for (const k of keys) {
|
|
462
|
+
values[k] = interfaces[k].value;
|
|
463
|
+
}
|
|
464
|
+
return values;
|
|
465
|
+
}
|
|
466
|
+
updateInterfaces(type, newInterfaces, forceUpdates) {
|
|
467
|
+
const staticKeys = type === "input" ? this.staticInputKeys : this.staticOutputKeys;
|
|
468
|
+
const currentInterfaces = type === "input" ? this.inputs : this.outputs;
|
|
469
|
+
for (const k of Object.keys(currentInterfaces)) {
|
|
470
|
+
if (staticKeys.includes(k) || newInterfaces[k] && !forceUpdates.includes(k)) continue;
|
|
471
|
+
if (type === "input") {
|
|
472
|
+
this.removeInput(k);
|
|
473
|
+
} else {
|
|
474
|
+
this.removeOutput(k);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
for (const k of Object.keys(newInterfaces)) {
|
|
478
|
+
if (currentInterfaces[k]) continue;
|
|
479
|
+
const intf = newInterfaces[k]();
|
|
480
|
+
if (type === "input") {
|
|
481
|
+
this.addInput(k, intf);
|
|
482
|
+
} else {
|
|
483
|
+
this.addOutput(k, intf);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
executeFactory(type, factory) {
|
|
488
|
+
Object.keys(factory || {}).forEach((k) => {
|
|
489
|
+
const intf = factory[k]();
|
|
490
|
+
if (type === "input") {
|
|
491
|
+
this.addInput(k, intf);
|
|
492
|
+
} else {
|
|
493
|
+
this.addOutput(k, intf);
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
class Code {
|
|
500
|
+
_id;
|
|
501
|
+
_viewModel;
|
|
502
|
+
_state;
|
|
503
|
+
constructor(viewModel) {
|
|
504
|
+
this._id = v4();
|
|
505
|
+
this._viewModel = viewModel;
|
|
506
|
+
this._state = reactive({
|
|
507
|
+
autosort: false,
|
|
508
|
+
modules: {},
|
|
509
|
+
script: "",
|
|
510
|
+
token: null,
|
|
511
|
+
template: ""
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
get codeNodes() {
|
|
515
|
+
return getCodeNodes(this.graph);
|
|
516
|
+
}
|
|
517
|
+
get connections() {
|
|
518
|
+
return this.graph.connections;
|
|
519
|
+
}
|
|
520
|
+
get graph() {
|
|
521
|
+
return this.viewModel.displayedGraph;
|
|
522
|
+
}
|
|
523
|
+
get id() {
|
|
524
|
+
return this._id;
|
|
525
|
+
}
|
|
526
|
+
get modules() {
|
|
527
|
+
let categories = [];
|
|
528
|
+
this.codeNodes.filter((node) => node.state.modules?.length > 0).forEach((node) => {
|
|
529
|
+
categories = categories.concat(node.state.modules);
|
|
530
|
+
});
|
|
531
|
+
if (!categories) return [];
|
|
532
|
+
categories.sort();
|
|
533
|
+
return Array.from(new Set(categories.map((category) => this.viewModel.state.modules[category])));
|
|
534
|
+
}
|
|
535
|
+
get nodeIds() {
|
|
536
|
+
return this.codeNodes.map((node) => node.id);
|
|
537
|
+
}
|
|
538
|
+
get nodes() {
|
|
539
|
+
return this.graph.nodes;
|
|
540
|
+
}
|
|
541
|
+
get scriptedCodeNodes() {
|
|
542
|
+
return getCodeNodes(this.graph).filter(
|
|
543
|
+
(codeNode) => codeNode.state?.script.length > 0
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
get shortId() {
|
|
547
|
+
return this.id.slice(0);
|
|
548
|
+
}
|
|
549
|
+
get state() {
|
|
550
|
+
return this._state;
|
|
551
|
+
}
|
|
552
|
+
get viewModel() {
|
|
553
|
+
return this._viewModel;
|
|
554
|
+
}
|
|
555
|
+
get visibleNodes() {
|
|
556
|
+
return this.codeNodes.filter((node) => !node.state?.hidden);
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Add code node to graph.
|
|
560
|
+
* @param node code node
|
|
561
|
+
* @param props optional
|
|
562
|
+
*/
|
|
563
|
+
addNode(node, props) {
|
|
564
|
+
if (props) node.state.props = props;
|
|
565
|
+
return this.graph.addNode(node);
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Add code node at coordinates.
|
|
569
|
+
* @param node code node
|
|
570
|
+
* @param position position
|
|
571
|
+
* @param props optional
|
|
572
|
+
* @returns code node
|
|
573
|
+
*/
|
|
574
|
+
addNodeAtCoordinates = (node, position = { x: 0, y: 0 }, props) => {
|
|
575
|
+
this.addNode(node, props);
|
|
576
|
+
if (node.position) node.position = position;
|
|
577
|
+
return node;
|
|
578
|
+
};
|
|
579
|
+
/**
|
|
580
|
+
* Add connection of code nodes
|
|
581
|
+
* @param from code node interface
|
|
582
|
+
* @param to code node interface
|
|
583
|
+
*/
|
|
584
|
+
addConnection(from, to) {
|
|
585
|
+
if (from.name !== "_node") from.hidden = false;
|
|
586
|
+
if (to.name !== "_node") to.hidden = false;
|
|
587
|
+
this.graph.addConnection(from, to);
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Clear code graph.
|
|
591
|
+
*/
|
|
592
|
+
clear() {
|
|
593
|
+
this.graph._nodes = [];
|
|
594
|
+
this.graph._connections = [];
|
|
595
|
+
}
|
|
596
|
+
findNodeById(id) {
|
|
597
|
+
return this.graph.findNodeById(id);
|
|
598
|
+
}
|
|
599
|
+
findNodeByType(nodeType2) {
|
|
600
|
+
return this.codeNodes.find((codeNode) => codeNode.type === nodeType2);
|
|
601
|
+
}
|
|
602
|
+
getNodesBySameType(type) {
|
|
603
|
+
return this.codeNodes.filter((codeNode) => codeNode.type === type);
|
|
604
|
+
}
|
|
605
|
+
getNodesBySameVariableNames(variableName) {
|
|
606
|
+
return this.codeNodes.filter(
|
|
607
|
+
(codeNode) => codeNode.state.variableName === variableName
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Check whether the graph has this connection.
|
|
612
|
+
* @param from node interface
|
|
613
|
+
* @param to node interface
|
|
614
|
+
* @returns boolean
|
|
615
|
+
*/
|
|
616
|
+
hasConnection(from, to) {
|
|
617
|
+
return this.connections.some(
|
|
618
|
+
(connection) => connection.from.id === from.id && connection.to.id === to.id
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Load template from the file.
|
|
623
|
+
*/
|
|
624
|
+
loadTemplate(resolve) {
|
|
625
|
+
resolve.then((template) => {
|
|
626
|
+
this._state.template = template.default ?? "";
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
onCodeUpdate() {
|
|
630
|
+
this.codeNodes.forEach((codeNode) => codeNode.onCodeUpdate());
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Remove connection from the graph
|
|
634
|
+
* @param connection connection between code nodes
|
|
635
|
+
*/
|
|
636
|
+
removeConnection(connection) {
|
|
637
|
+
this.graph.removeConnection(connection);
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Remove node from the graph.
|
|
641
|
+
* @param codeNode code node
|
|
642
|
+
*/
|
|
643
|
+
removeNode(codeNode) {
|
|
644
|
+
this.graph.removeNode(codeNode);
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Render node codes.
|
|
648
|
+
*/
|
|
649
|
+
renderNodeCodes() {
|
|
650
|
+
if (this.codeNodes.length === 0) return;
|
|
651
|
+
this.codeNodes.forEach((node) => node.renderCode());
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Render code.
|
|
655
|
+
*/
|
|
656
|
+
renderCode() {
|
|
657
|
+
this.state.script = mustache.render(this.state.template || "", this);
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Save code graph.
|
|
661
|
+
* @returns graph state
|
|
662
|
+
*/
|
|
663
|
+
save() {
|
|
664
|
+
if (this.state.autosort) this.sortNodes();
|
|
665
|
+
const editorState = this.viewModel.editor.save();
|
|
666
|
+
editorState.graph.id = this.id;
|
|
667
|
+
this.saveNodeStates(editorState.graph.nodes);
|
|
668
|
+
return JSON.parse(JSON.stringify(editorState));
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Save node states.
|
|
672
|
+
* @param nodeStates a list of node state.
|
|
673
|
+
*/
|
|
674
|
+
saveNodeStates(nodeStates) {
|
|
675
|
+
nodeStates.forEach((nodeState, nodeIdx) => {
|
|
676
|
+
const node = this.nodes[nodeIdx];
|
|
677
|
+
Object.entries(nodeState.inputs).forEach(([inputKey]) => {
|
|
678
|
+
if (node.inputs[inputKey]) nodeState.inputs[inputKey].hidden = node.inputs[inputKey].hidden;
|
|
679
|
+
});
|
|
680
|
+
Object.entries(nodeState.outputs).forEach(([outputKey]) => {
|
|
681
|
+
if (node.inputs[outputKey]) nodeState.outputs[outputKey].hidden = node.outputs[outputKey].hidden;
|
|
682
|
+
});
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Sort code nodes.
|
|
687
|
+
*/
|
|
688
|
+
sortNodes() {
|
|
689
|
+
if (this.nodes.length === 0 || this.connections.length === 0) return;
|
|
690
|
+
try {
|
|
691
|
+
const edges = this.connections.map((connection) => [
|
|
692
|
+
connection.to.nodeId,
|
|
693
|
+
connection.from.nodeId
|
|
694
|
+
]);
|
|
695
|
+
let nodeIds = [...this.nodeIds];
|
|
696
|
+
nodeIds.reverse();
|
|
697
|
+
nodeIds = toposort.array(nodeIds, edges);
|
|
698
|
+
nodeIds.reverse();
|
|
699
|
+
const unconnected = this.graph.nodes.map((node) => node.id).filter((nodeId) => !nodeIds.includes(nodeId));
|
|
700
|
+
nodeIds = nodeIds.concat(unconnected);
|
|
701
|
+
this.graph._nodes = nodeIds.map((nodeId) => this.findNodeById(nodeId));
|
|
702
|
+
} catch {
|
|
703
|
+
console.warn("Failed to sort nodes.");
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
updateOutputVariableNames() {
|
|
707
|
+
this.codeNodes.forEach((codeNode) => codeNode.updateOutputVariableName());
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
const getCodeNodes = (graph) => {
|
|
711
|
+
let nodes = [];
|
|
712
|
+
graph.nodes.forEach((node) => {
|
|
713
|
+
if (node.subgraph) {
|
|
714
|
+
nodes = nodes.concat(getCodeNodes(node.subgraph));
|
|
715
|
+
} else if (node.isCodeNode) {
|
|
716
|
+
nodes.push(node);
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
return nodes;
|
|
720
|
+
};
|
|
721
|
+
const getPositionAtColumn = (col = 0, offset = 100) => {
|
|
722
|
+
const width = 350;
|
|
723
|
+
const padding = 70;
|
|
724
|
+
return {
|
|
725
|
+
x: col * (width + padding),
|
|
726
|
+
y: offset
|
|
727
|
+
};
|
|
728
|
+
};
|
|
729
|
+
const getPositionBeforeNode = (node) => {
|
|
730
|
+
const position = { ...node.position };
|
|
731
|
+
position.x -= 400;
|
|
732
|
+
position.y += 50;
|
|
733
|
+
return position;
|
|
734
|
+
};
|
|
735
|
+
const transferCodeScript = (graph) => {
|
|
736
|
+
const { calculationOrder, connectionsFromNode } = sortTopologically(graph);
|
|
737
|
+
calculationOrder.forEach((node) => {
|
|
738
|
+
if (!node.isCodeNode) return;
|
|
739
|
+
const codeNode = node;
|
|
740
|
+
if (connectionsFromNode.has(codeNode)) {
|
|
741
|
+
connectionsFromNode.get(codeNode).forEach((c) => {
|
|
742
|
+
if (c.to.state && c.from.script) c.to.state.script = c.from.script;
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
});
|
|
746
|
+
};
|
|
747
|
+
const _hoisted_1$e = ["id"];
|
|
748
|
+
const _hoisted_2$5 = { class: "align-middle" };
|
|
749
|
+
const _sfc_main$f = /* @__PURE__ */ defineComponent({
|
|
750
|
+
__name: "CodeGraphNodeInterface",
|
|
751
|
+
props: {
|
|
752
|
+
node: {},
|
|
753
|
+
intf: {}
|
|
754
|
+
},
|
|
755
|
+
setup(__props) {
|
|
756
|
+
const props = __props;
|
|
757
|
+
const { viewModel } = useViewModel();
|
|
758
|
+
const { hoveredOver, temporaryConnection } = useTemporaryConnection();
|
|
759
|
+
const el = ref(null);
|
|
760
|
+
const isConnected = computed(() => props.intf.connectionCount > 0);
|
|
761
|
+
const classes = computed(() => ({
|
|
762
|
+
"--connected": isConnected.value
|
|
763
|
+
}));
|
|
764
|
+
const startHover = () => {
|
|
765
|
+
hoveredOver(props.intf);
|
|
766
|
+
};
|
|
767
|
+
const endHover = () => {
|
|
768
|
+
hoveredOver(void 0);
|
|
769
|
+
};
|
|
770
|
+
const onRender = () => {
|
|
771
|
+
if (el.value) {
|
|
772
|
+
viewModel.value.hooks.renderInterface.execute({ intf: props.intf, el: el.value });
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
onMounted(onRender);
|
|
776
|
+
onUpdated(onRender);
|
|
777
|
+
return (_ctx, _cache) => {
|
|
778
|
+
return openBlock(), createElementBlock("div", {
|
|
779
|
+
id: _ctx.intf.id,
|
|
780
|
+
ref_key: "el",
|
|
781
|
+
ref: el,
|
|
782
|
+
class: normalizeClass(["baklava-node-interface", classes.value])
|
|
783
|
+
}, [
|
|
784
|
+
_ctx.intf.port ? (openBlock(), createElementBlock("div", {
|
|
785
|
+
key: 0,
|
|
786
|
+
class: normalizeClass(["__port", { "--selected": unref(temporaryConnection)?.from === _ctx.intf }]),
|
|
787
|
+
onPointerover: startHover,
|
|
788
|
+
onPointerout: endHover
|
|
789
|
+
}, null, 34)) : createCommentVNode("", true),
|
|
790
|
+
createElementVNode("span", _hoisted_2$5, [
|
|
791
|
+
renderSlot(_ctx.$slots, "default")
|
|
792
|
+
])
|
|
793
|
+
], 10, _hoisted_1$e);
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
});
|
|
797
|
+
const _export_sfc = (sfc, props) => {
|
|
798
|
+
const target = sfc.__vccOpts || sfc;
|
|
799
|
+
for (const [key, val] of props) {
|
|
800
|
+
target[key] = val;
|
|
801
|
+
}
|
|
802
|
+
return target;
|
|
803
|
+
};
|
|
804
|
+
const _sfc_main$e = {};
|
|
805
|
+
const _hoisted_1$d = {
|
|
806
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
807
|
+
width: "24",
|
|
808
|
+
height: "24",
|
|
809
|
+
viewBox: "0 0 24 24",
|
|
810
|
+
fill: "currentColor",
|
|
811
|
+
class: "baklava-icon icon icon-tabler icons-tabler-filled icon-tabler-layout-sidebar-left-collapse"
|
|
812
|
+
};
|
|
813
|
+
function _sfc_render$9(_ctx, _cache) {
|
|
814
|
+
return openBlock(), createElementBlock("svg", _hoisted_1$d, [..._cache[0] || (_cache[0] = [
|
|
815
|
+
createElementVNode("path", {
|
|
816
|
+
stroke: "none",
|
|
817
|
+
d: "M0 0h24v24H0z",
|
|
818
|
+
fill: "none"
|
|
819
|
+
}, null, -1),
|
|
820
|
+
createElementVNode("path", { d: "M18 3a3 3 0 0 1 2.995 2.824l.005 .176v12a3 3 0 0 1 -2.824 2.995l-.176 .005h-12a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-12a3 3 0 0 1 2.824 -2.995l.176 -.005h12zm0 2h-9v14h9a1 1 0 0 0 .993 -.883l.007 -.117v-12a1 1 0 0 0 -.883 -.993l-.117 -.007zm-2.293 4.293a1 1 0 0 1 .083 1.32l-.083 .094l-1.292 1.293l1.292 1.293a1 1 0 0 1 .083 1.32l-.083 .094a1 1 0 0 1 -1.32 .083l-.094 -.083l-2 -2a1 1 0 0 1 -.083 -1.32l.083 -.094l2 -2a1 1 0 0 1 1.414 0z" }, null, -1)
|
|
821
|
+
])]);
|
|
822
|
+
}
|
|
823
|
+
const LayoutSidebarLeftCollapse = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["render", _sfc_render$9]]);
|
|
824
|
+
const _sfc_main$d = {};
|
|
825
|
+
const _hoisted_1$c = {
|
|
826
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
827
|
+
width: "24",
|
|
828
|
+
height: "24",
|
|
829
|
+
viewBox: "0 0 24 24",
|
|
830
|
+
fill: "currentColor",
|
|
831
|
+
class: "baklava-icon icon icon-tabler icons-tabler-filled icon-tabler-layout-sidebar-left-expand"
|
|
832
|
+
};
|
|
833
|
+
function _sfc_render$8(_ctx, _cache) {
|
|
834
|
+
return openBlock(), createElementBlock("svg", _hoisted_1$c, [..._cache[0] || (_cache[0] = [
|
|
835
|
+
createElementVNode("path", {
|
|
836
|
+
stroke: "none",
|
|
837
|
+
d: "M0 0h24v24H0z",
|
|
838
|
+
fill: "none"
|
|
839
|
+
}, null, -1),
|
|
840
|
+
createElementVNode("path", { d: "M18 3a3 3 0 0 1 2.995 2.824l.005 .176v12a3 3 0 0 1 -2.824 2.995l-.176 .005h-12a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-12a3 3 0 0 1 2.824 -2.995l.176 -.005h12zm0 2h-9v14h9a1 1 0 0 0 .993 -.883l.007 -.117v-12a1 1 0 0 0 -.883 -.993l-.117 -.007zm-4.387 4.21l.094 .083l2 2a1 1 0 0 1 .083 1.32l-.083 .094l-2 2a1 1 0 0 1 -1.497 -1.32l.083 -.094l1.292 -1.293l-1.292 -1.293a1 1 0 0 1 -.083 -1.32l.083 -.094a1 1 0 0 1 1.32 -.083z" }, null, -1)
|
|
841
|
+
])]);
|
|
842
|
+
}
|
|
843
|
+
const LayoutSidebarLeftExpand = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["render", _sfc_render$8]]);
|
|
844
|
+
const _sfc_main$c = {};
|
|
845
|
+
const _hoisted_1$b = {
|
|
846
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
847
|
+
width: "24",
|
|
848
|
+
height: "24",
|
|
849
|
+
viewBox: "0 0 24 24",
|
|
850
|
+
fill: "currentColor",
|
|
851
|
+
class: "balkava-icon icon icon-tabler icons-tabler-filled icon-tabler-layout-sidebar-right"
|
|
852
|
+
};
|
|
853
|
+
function _sfc_render$7(_ctx, _cache) {
|
|
854
|
+
return openBlock(), createElementBlock("svg", _hoisted_1$b, [..._cache[0] || (_cache[0] = [
|
|
855
|
+
createElementVNode("path", {
|
|
856
|
+
stroke: "none",
|
|
857
|
+
d: "M0 0h24v24H0z",
|
|
858
|
+
fill: "none"
|
|
859
|
+
}, null, -1),
|
|
860
|
+
createElementVNode("path", { d: "M6 21a3 3 0 0 1 -3 -3v-12a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3zm8 -16h-8a1 1 0 0 0 -1 1v12a1 1 0 0 0 1 1h8z" }, null, -1)
|
|
861
|
+
])]);
|
|
862
|
+
}
|
|
863
|
+
const LayoutSidebarRight = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["render", _sfc_render$7]]);
|
|
864
|
+
const _sfc_main$b = {};
|
|
865
|
+
const _hoisted_1$a = {
|
|
866
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
867
|
+
width: "24",
|
|
868
|
+
height: "24",
|
|
869
|
+
viewBox: "0 0 24 24",
|
|
870
|
+
fill: "currentColor",
|
|
871
|
+
class: "baklava-icon icon icon-tabler icons-tabler-filled icon-tabler-layout-sidebar-right-collapse"
|
|
872
|
+
};
|
|
873
|
+
function _sfc_render$6(_ctx, _cache) {
|
|
874
|
+
return openBlock(), createElementBlock("svg", _hoisted_1$a, [..._cache[0] || (_cache[0] = [
|
|
875
|
+
createElementVNode("path", {
|
|
876
|
+
stroke: "none",
|
|
877
|
+
d: "M0 0h24v24H0z",
|
|
878
|
+
fill: "none"
|
|
879
|
+
}, null, -1),
|
|
880
|
+
createElementVNode("path", { d: "M18 3a3 3 0 0 1 2.995 2.824l.005 .176v12a3 3 0 0 1 -2.824 2.995l-.176 .005h-12a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-12a3 3 0 0 1 2.824 -2.995l.176 -.005h12zm-3 2h-9a1 1 0 0 0 -.993 .883l-.007 .117v12a1 1 0 0 0 .883 .993l.117 .007h9v-14zm-5.387 4.21l.094 .083l2 2a1 1 0 0 1 .083 1.32l-.083 .094l-2 2a1 1 0 0 1 -1.497 -1.32l.083 -.094l1.292 -1.293l-1.292 -1.293a1 1 0 0 1 -.083 -1.32l.083 -.094a1 1 0 0 1 1.32 -.083z" }, null, -1)
|
|
881
|
+
])]);
|
|
882
|
+
}
|
|
883
|
+
const LayoutSidebarRightCollapse = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["render", _sfc_render$6]]);
|
|
884
|
+
const _sfc_main$a = {};
|
|
885
|
+
const _hoisted_1$9 = {
|
|
886
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
887
|
+
width: "24",
|
|
888
|
+
height: "24",
|
|
889
|
+
viewBox: "0 0 24 24",
|
|
890
|
+
fill: "currentColor",
|
|
891
|
+
class: "baklava-icon icon icon-tabler icons-tabler-filled icon-tabler-layout-sidebar-right-expand"
|
|
892
|
+
};
|
|
893
|
+
function _sfc_render$5(_ctx, _cache) {
|
|
894
|
+
return openBlock(), createElementBlock("svg", _hoisted_1$9, [..._cache[0] || (_cache[0] = [
|
|
895
|
+
createElementVNode("path", {
|
|
896
|
+
stroke: "none",
|
|
897
|
+
d: "M0 0h24v24H0z",
|
|
898
|
+
fill: "none"
|
|
899
|
+
}, null, -1),
|
|
900
|
+
createElementVNode("path", { d: "M18 3a3 3 0 0 1 2.995 2.824l.005 .176v12a3 3 0 0 1 -2.824 2.995l-.176 .005h-12a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-12a3 3 0 0 1 2.824 -2.995l.176 -.005h12zm-3 2h-9a1 1 0 0 0 -.993 .883l-.007 .117v12a1 1 0 0 0 .883 .993l.117 .007h9v-14zm-3.293 4.293a1 1 0 0 1 .083 1.32l-.083 .094l-1.292 1.293l1.292 1.293a1 1 0 0 1 .083 1.32l-.083 .094a1 1 0 0 1 -1.32 .083l-.094 -.083l-2 -2a1 1 0 0 1 -.083 -1.32l.083 -.094l2 -2a1 1 0 0 1 1.414 0z" }, null, -1)
|
|
901
|
+
])]);
|
|
902
|
+
}
|
|
903
|
+
const LayoutSidebarRightExpand = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["render", _sfc_render$5]]);
|
|
904
|
+
const _sfc_main$9 = {};
|
|
905
|
+
const _hoisted_1$8 = {
|
|
906
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
907
|
+
class: "baklava-icon",
|
|
908
|
+
width: "24",
|
|
909
|
+
height: "24",
|
|
910
|
+
viewBox: "0 0 24 24",
|
|
911
|
+
fill: "none",
|
|
912
|
+
stroke: "currentColor",
|
|
913
|
+
"stroke-width": "2",
|
|
914
|
+
"stroke-linecap": "round",
|
|
915
|
+
"stroke-linejoin": "round"
|
|
916
|
+
};
|
|
917
|
+
function _sfc_render$4(_ctx, _cache) {
|
|
918
|
+
return openBlock(), createElementBlock("svg", _hoisted_1$8, [..._cache[0] || (_cache[0] = [
|
|
919
|
+
createStaticVNode('<path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M5 2h5v4h-5z"></path><path d="M15 10h5v4h-5z"></path><path d="M5 18h5v4h-5z"></path><path d="M5 10h5v4h-5z"></path><path d="M10 12h5"></path><path d="M7.5 6v4"></path><path d="M7.5 14v4"></path>', 8)
|
|
920
|
+
])]);
|
|
921
|
+
}
|
|
922
|
+
const Schema = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["render", _sfc_render$4]]);
|
|
923
|
+
const _sfc_main$8 = {};
|
|
924
|
+
const _hoisted_1$7 = {
|
|
925
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
926
|
+
class: "baklava-icon",
|
|
927
|
+
width: "24",
|
|
928
|
+
height: "24",
|
|
929
|
+
viewBox: "0 0 24 24",
|
|
930
|
+
fill: "none",
|
|
931
|
+
stroke: "currentColor",
|
|
932
|
+
"stroke-width": "2",
|
|
933
|
+
"stroke-linecap": "round",
|
|
934
|
+
"stroke-linejoin": "round"
|
|
935
|
+
};
|
|
936
|
+
function _sfc_render$3(_ctx, _cache) {
|
|
937
|
+
return openBlock(), createElementBlock("svg", _hoisted_1$7, [..._cache[0] || (_cache[0] = [
|
|
938
|
+
createStaticVNode('<path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M6 2h4v4m-4 0h-1v-1"></path><path d="M15 11v-1h5v4h-2"></path><path d="M5 18h5v4h-5z"></path><path d="M5 10h5v4h-5z"></path><path d="M10 12h2"></path><path d="M7.5 7.5v2.5"></path><path d="M7.5 14v4"></path><path d="M3 3l18 18"></path>', 9)
|
|
939
|
+
])]);
|
|
940
|
+
}
|
|
941
|
+
const SchemaOff = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["render", _sfc_render$3]]);
|
|
942
|
+
const _sfc_main$7 = {};
|
|
943
|
+
const _hoisted_1$6 = {
|
|
944
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
945
|
+
class: "baklava-icon",
|
|
946
|
+
width: "24",
|
|
947
|
+
height: "24",
|
|
948
|
+
viewBox: "0 0 24 24",
|
|
949
|
+
fill: "none",
|
|
950
|
+
stroke: "currentColor",
|
|
951
|
+
"stroke-width": "2",
|
|
952
|
+
"stroke-linecap": "round",
|
|
953
|
+
"stroke-linejoin": "round"
|
|
954
|
+
};
|
|
955
|
+
function _sfc_render$2(_ctx, _cache) {
|
|
956
|
+
return openBlock(), createElementBlock("svg", _hoisted_1$6, [..._cache[0] || (_cache[0] = [
|
|
957
|
+
createStaticVNode('<path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M3 3l18 18"></path><path d="M4 7h3m4 0h9"></path><path d="M10 11l0 6"></path><path d="M14 14l0 3"></path><path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l.077 -.923"></path><path d="M18.384 14.373l.616 -7.373"></path><path d="M9 5v-1a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3"></path>', 8)
|
|
958
|
+
])]);
|
|
959
|
+
}
|
|
960
|
+
const TrashOff = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["render", _sfc_render$2]]);
|
|
961
|
+
const _sfc_main$6 = {};
|
|
962
|
+
const _hoisted_1$5 = {
|
|
963
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
964
|
+
class: "baklava-icon",
|
|
965
|
+
width: "16",
|
|
966
|
+
height: "16",
|
|
967
|
+
viewBox: "0 0 24 24",
|
|
968
|
+
"stroke-width": "2",
|
|
969
|
+
stroke: "currentColor",
|
|
970
|
+
fill: "none",
|
|
971
|
+
"stroke-linecap": "round",
|
|
972
|
+
"stroke-linejoin": "round"
|
|
973
|
+
};
|
|
974
|
+
function _sfc_render$1(_ctx, _cache) {
|
|
975
|
+
return openBlock(), createElementBlock("svg", _hoisted_1$5, [..._cache[0] || (_cache[0] = [
|
|
976
|
+
createElementVNode("path", {
|
|
977
|
+
stroke: "none",
|
|
978
|
+
d: "M0 0h24v24H0z",
|
|
979
|
+
fill: "none"
|
|
980
|
+
}, null, -1),
|
|
981
|
+
createElementVNode("circle", {
|
|
982
|
+
cx: "12",
|
|
983
|
+
cy: "12",
|
|
984
|
+
r: "1"
|
|
985
|
+
}, null, -1),
|
|
986
|
+
createElementVNode("circle", {
|
|
987
|
+
cx: "12",
|
|
988
|
+
cy: "19",
|
|
989
|
+
r: "1"
|
|
990
|
+
}, null, -1),
|
|
991
|
+
createElementVNode("circle", {
|
|
992
|
+
cx: "12",
|
|
993
|
+
cy: "5",
|
|
994
|
+
r: "1"
|
|
995
|
+
}, null, -1)
|
|
996
|
+
])]);
|
|
997
|
+
}
|
|
998
|
+
const VerticalDots = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$1]]);
|
|
999
|
+
const _hoisted_1$4 = ["id", "data-node-type"];
|
|
1000
|
+
const _hoisted_2$4 = {
|
|
1001
|
+
class: "__title-label",
|
|
1002
|
+
style: { "flex-grow": "1" }
|
|
1003
|
+
};
|
|
1004
|
+
const _hoisted_3$2 = { key: 0 };
|
|
1005
|
+
const _hoisted_4$1 = {
|
|
1006
|
+
class: "__menu",
|
|
1007
|
+
style: { "display": "flex" }
|
|
1008
|
+
};
|
|
1009
|
+
const _hoisted_5 = { class: "__outputs" };
|
|
1010
|
+
const _hoisted_6 = { key: 0 };
|
|
1011
|
+
const _hoisted_7 = ["id", "title"];
|
|
1012
|
+
const _hoisted_8 = { class: "__inputs" };
|
|
1013
|
+
const _hoisted_9 = { key: 0 };
|
|
1014
|
+
const _hoisted_10 = ["id", "title"];
|
|
1015
|
+
const _sfc_main$5 = /* @__PURE__ */ defineComponent({
|
|
1016
|
+
__name: "CodeGraphNode",
|
|
1017
|
+
props: {
|
|
1018
|
+
node: {},
|
|
1019
|
+
selected: { type: Boolean, default: false },
|
|
1020
|
+
dragging: { type: Boolean }
|
|
1021
|
+
},
|
|
1022
|
+
emits: ["select", "start-drag", "update"],
|
|
1023
|
+
setup(__props, { emit: __emit }) {
|
|
1024
|
+
const ContextMenu = Components.ContextMenu;
|
|
1025
|
+
const NodeInterface2 = Components.NodeInterface;
|
|
1026
|
+
const props = __props;
|
|
1027
|
+
const node = computed(() => props.node);
|
|
1028
|
+
const emit = __emit;
|
|
1029
|
+
const { viewModel } = useViewModel();
|
|
1030
|
+
const { graph, switchGraph } = useGraph();
|
|
1031
|
+
const el = ref(null);
|
|
1032
|
+
const renaming = ref(false);
|
|
1033
|
+
const tempName = ref("");
|
|
1034
|
+
const renameInputEl = ref(null);
|
|
1035
|
+
const isResizing = ref(false);
|
|
1036
|
+
let resizeStartWidth = 0;
|
|
1037
|
+
let resizeStartMouseX = 0;
|
|
1038
|
+
const showContextMenu = ref(false);
|
|
1039
|
+
const contextMenuItems = computed(() => {
|
|
1040
|
+
const items = [
|
|
1041
|
+
{ value: "edit", label: "Edit" },
|
|
1042
|
+
{ value: "rename", label: "Rename" },
|
|
1043
|
+
{ value: "delete", label: "Delete" }
|
|
1044
|
+
];
|
|
1045
|
+
if (props.node.type.startsWith(GRAPH_NODE_TYPE_PREFIX)) {
|
|
1046
|
+
items.push({ value: "editSubgraph", label: "Edit Subgraph" });
|
|
1047
|
+
}
|
|
1048
|
+
return items;
|
|
1049
|
+
});
|
|
1050
|
+
const classes = computed(() => ({
|
|
1051
|
+
"--selected": props.selected,
|
|
1052
|
+
"--dragging": props.dragging,
|
|
1053
|
+
"--two-column": !!props.node.twoColumn,
|
|
1054
|
+
"--hidden": node.value.state?.hidden
|
|
1055
|
+
}));
|
|
1056
|
+
const classesContent = computed(() => ({
|
|
1057
|
+
"--reverse-y": props.node.reverseY ?? viewModel.value.settings.nodes.reverseY
|
|
1058
|
+
}));
|
|
1059
|
+
const styles = computed(() => ({
|
|
1060
|
+
"top": `${props.node.position?.y ?? 0}px`,
|
|
1061
|
+
"left": `${props.node.position?.x ?? 0}px`,
|
|
1062
|
+
"--width": `${props.node.width ?? viewModel.value.settings.nodes.defaultWidth}px`
|
|
1063
|
+
}));
|
|
1064
|
+
const displayedInputs = computed(() => Object.values(props.node.inputs).filter((ni) => !ni.hidden));
|
|
1065
|
+
const displayedOutputs = computed(() => Object.values(props.node.outputs).filter((ni) => !ni.hidden));
|
|
1066
|
+
const select = () => {
|
|
1067
|
+
emit("select");
|
|
1068
|
+
};
|
|
1069
|
+
const startDrag = (ev) => {
|
|
1070
|
+
if (!props.selected) {
|
|
1071
|
+
select();
|
|
1072
|
+
}
|
|
1073
|
+
emit("start-drag", ev);
|
|
1074
|
+
};
|
|
1075
|
+
const openContextMenu = () => {
|
|
1076
|
+
showContextMenu.value = true;
|
|
1077
|
+
};
|
|
1078
|
+
const closeSidebar = () => {
|
|
1079
|
+
const sidebar = viewModel.value.displayedGraph.sidebar;
|
|
1080
|
+
sidebar.nodeId = "";
|
|
1081
|
+
sidebar.visible = false;
|
|
1082
|
+
};
|
|
1083
|
+
const openSidebar = () => {
|
|
1084
|
+
const sidebar = viewModel.value.displayedGraph.sidebar;
|
|
1085
|
+
sidebar.nodeId = props.node.id;
|
|
1086
|
+
sidebar.visible = true;
|
|
1087
|
+
};
|
|
1088
|
+
const updateSidebar = () => {
|
|
1089
|
+
const sidebar = viewModel.value.displayedGraph.sidebar;
|
|
1090
|
+
sidebar.nodeId = props.node.id;
|
|
1091
|
+
};
|
|
1092
|
+
const onContextMenuClick = async (action) => {
|
|
1093
|
+
switch (action) {
|
|
1094
|
+
case "edit":
|
|
1095
|
+
openSidebar();
|
|
1096
|
+
break;
|
|
1097
|
+
case "delete":
|
|
1098
|
+
graph.value.removeNode(props.node);
|
|
1099
|
+
break;
|
|
1100
|
+
case "rename":
|
|
1101
|
+
tempName.value = props.node.title;
|
|
1102
|
+
renaming.value = true;
|
|
1103
|
+
await nextTick();
|
|
1104
|
+
renameInputEl.value?.focus();
|
|
1105
|
+
break;
|
|
1106
|
+
case "editSubgraph":
|
|
1107
|
+
switchGraph(props.node.template);
|
|
1108
|
+
break;
|
|
1109
|
+
}
|
|
1110
|
+
};
|
|
1111
|
+
const doneRenaming = () => {
|
|
1112
|
+
props.node.title = tempName.value;
|
|
1113
|
+
renaming.value = false;
|
|
1114
|
+
};
|
|
1115
|
+
const onRender = () => {
|
|
1116
|
+
if (el.value) {
|
|
1117
|
+
viewModel.value.hooks.renderNode.execute({ node: props.node, el: el.value });
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
const startResize = (ev) => {
|
|
1121
|
+
isResizing.value = true;
|
|
1122
|
+
resizeStartWidth = props.node.width;
|
|
1123
|
+
resizeStartMouseX = ev.clientX;
|
|
1124
|
+
ev.preventDefault();
|
|
1125
|
+
};
|
|
1126
|
+
const doResize = (ev) => {
|
|
1127
|
+
if (!isResizing.value) return;
|
|
1128
|
+
const deltaX = ev.clientX - resizeStartMouseX;
|
|
1129
|
+
const newWidth = resizeStartWidth + deltaX / graph.value.scaling;
|
|
1130
|
+
const minWidth = viewModel.value.settings.nodes.minWidth;
|
|
1131
|
+
const maxWidth = viewModel.value.settings.nodes.maxWidth;
|
|
1132
|
+
props.node.width = Math.max(minWidth, Math.min(maxWidth, newWidth));
|
|
1133
|
+
};
|
|
1134
|
+
const stopResize = () => {
|
|
1135
|
+
isResizing.value = false;
|
|
1136
|
+
};
|
|
1137
|
+
onMounted(() => {
|
|
1138
|
+
onRender();
|
|
1139
|
+
window.addEventListener("mousemove", doResize);
|
|
1140
|
+
window.addEventListener("mouseup", stopResize);
|
|
1141
|
+
});
|
|
1142
|
+
onUpdated(onRender);
|
|
1143
|
+
onBeforeUnmount(() => {
|
|
1144
|
+
window.removeEventListener("mousemove", doResize);
|
|
1145
|
+
window.removeEventListener("mouseup", stopResize);
|
|
1146
|
+
});
|
|
1147
|
+
return (_ctx, _cache) => {
|
|
1148
|
+
return openBlock(), createElementBlock("div", {
|
|
1149
|
+
id: node.value.id,
|
|
1150
|
+
ref_key: "el",
|
|
1151
|
+
ref: el,
|
|
1152
|
+
class: normalizeClass([classes.value, "baklava-node"]),
|
|
1153
|
+
"data-node-type": node.value.type,
|
|
1154
|
+
style: normalizeStyle(styles.value),
|
|
1155
|
+
onPointerdown: select
|
|
1156
|
+
}, [
|
|
1157
|
+
unref(viewModel).settings.nodes.resizable ? (openBlock(), createElementBlock("div", {
|
|
1158
|
+
key: 0,
|
|
1159
|
+
class: "__resize-handle",
|
|
1160
|
+
onMousedown: startResize
|
|
1161
|
+
}, null, 32)) : createCommentVNode("", true),
|
|
1162
|
+
createElementVNode("div", {
|
|
1163
|
+
class: "__title",
|
|
1164
|
+
onPointerdown: withModifiers(startDrag, ["self", "stop"]),
|
|
1165
|
+
onContextmenu: withModifiers(openContextMenu, ["prevent"])
|
|
1166
|
+
}, [
|
|
1167
|
+
node.value.inputs._node ? (openBlock(), createBlock(_sfc_main$f, {
|
|
1168
|
+
key: 0,
|
|
1169
|
+
node: node.value,
|
|
1170
|
+
intf: node.value.inputs._node,
|
|
1171
|
+
class: "--input",
|
|
1172
|
+
"data-interface-type": "node",
|
|
1173
|
+
style: { "flex-grow": "0" }
|
|
1174
|
+
}, null, 8, ["node", "intf"])) : createCommentVNode("", true),
|
|
1175
|
+
!renaming.value ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
1176
|
+
createElementVNode("div", _hoisted_2$4, [
|
|
1177
|
+
node.value.idx > -1 ? (openBlock(), createElementBlock("span", _hoisted_3$2, toDisplayString(node.value.idx + 1) + " - ", 1)) : createCommentVNode("", true),
|
|
1178
|
+
createTextVNode(toDisplayString(node.value.title) + " (" + toDisplayString(node.value.shortId) + ") ", 1)
|
|
1179
|
+
]),
|
|
1180
|
+
createElementVNode("div", _hoisted_4$1, [
|
|
1181
|
+
!node.value.subgraph ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
|
|
1182
|
+
!unref(viewModel).displayedGraph.sidebar.visible && unref(viewModel).displayedGraph.sidebar.nodeId !== node.value.id ? (openBlock(), createBlock(unref(LayoutSidebarRightExpand), {
|
|
1183
|
+
key: 0,
|
|
1184
|
+
class: "--clickable mx-1",
|
|
1185
|
+
onClick: openSidebar
|
|
1186
|
+
})) : unref(viewModel).displayedGraph.sidebar.visible && unref(viewModel).displayedGraph.sidebar.nodeId !== node.value.id ? (openBlock(), createBlock(unref(LayoutSidebarRight), {
|
|
1187
|
+
key: 1,
|
|
1188
|
+
class: "--clickable mx-1",
|
|
1189
|
+
onClick: updateSidebar
|
|
1190
|
+
})) : (openBlock(), createBlock(unref(LayoutSidebarRightCollapse), {
|
|
1191
|
+
key: 2,
|
|
1192
|
+
class: "--clickable mx-1",
|
|
1193
|
+
onClick: closeSidebar
|
|
1194
|
+
}))
|
|
1195
|
+
], 64)) : createCommentVNode("", true),
|
|
1196
|
+
createVNode(unref(VerticalDots), {
|
|
1197
|
+
class: "--clickable mx-1",
|
|
1198
|
+
onClick: openContextMenu
|
|
1199
|
+
}),
|
|
1200
|
+
createVNode(unref(ContextMenu), {
|
|
1201
|
+
modelValue: showContextMenu.value,
|
|
1202
|
+
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => showContextMenu.value = $event),
|
|
1203
|
+
x: 0,
|
|
1204
|
+
y: 0,
|
|
1205
|
+
items: contextMenuItems.value,
|
|
1206
|
+
onClick: onContextMenuClick
|
|
1207
|
+
}, null, 8, ["modelValue", "items"])
|
|
1208
|
+
])
|
|
1209
|
+
], 64)) : withDirectives((openBlock(), createElementBlock("input", {
|
|
1210
|
+
key: 2,
|
|
1211
|
+
ref_key: "renameInputEl",
|
|
1212
|
+
ref: renameInputEl,
|
|
1213
|
+
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => tempName.value = $event),
|
|
1214
|
+
class: "baklava-input",
|
|
1215
|
+
placeholder: "Node Name",
|
|
1216
|
+
style: { "flex-grow": "1" },
|
|
1217
|
+
type: "text",
|
|
1218
|
+
onBlur: doneRenaming,
|
|
1219
|
+
onKeydown: withKeys(doneRenaming, ["enter"])
|
|
1220
|
+
}, null, 544)), [
|
|
1221
|
+
[vModelText, tempName.value]
|
|
1222
|
+
]),
|
|
1223
|
+
node.value.outputs._node ? (openBlock(), createBlock(_sfc_main$f, {
|
|
1224
|
+
key: 3,
|
|
1225
|
+
node: node.value,
|
|
1226
|
+
intf: node.value.outputs._node,
|
|
1227
|
+
class: "--output",
|
|
1228
|
+
"data-interface-type": "node"
|
|
1229
|
+
}, null, 8, ["node", "intf"])) : createCommentVNode("", true)
|
|
1230
|
+
], 32),
|
|
1231
|
+
createElementVNode("div", {
|
|
1232
|
+
class: normalizeClass(["__content", classesContent.value]),
|
|
1233
|
+
onKeydown: _cache[2] || (_cache[2] = withKeys(withModifiers(() => {
|
|
1234
|
+
}, ["stop"]), ["delete"])),
|
|
1235
|
+
onContextmenu: _cache[3] || (_cache[3] = withModifiers(() => {
|
|
1236
|
+
}, ["prevent"]))
|
|
1237
|
+
}, [
|
|
1238
|
+
createElementVNode("div", _hoisted_5, [
|
|
1239
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(displayedOutputs.value, (output) => {
|
|
1240
|
+
return openBlock(), createElementBlock(Fragment, {
|
|
1241
|
+
key: output.id
|
|
1242
|
+
}, [
|
|
1243
|
+
node.value.state?.hidden ? (openBlock(), createElementBlock("div", _hoisted_6, [
|
|
1244
|
+
output.port ? (openBlock(), createElementBlock("div", {
|
|
1245
|
+
key: 0,
|
|
1246
|
+
id: output.id,
|
|
1247
|
+
title: output.name,
|
|
1248
|
+
class: "baklava-node-interface --output --connected"
|
|
1249
|
+
}, [..._cache[4] || (_cache[4] = [
|
|
1250
|
+
createElementVNode("div", { class: "__port" }, null, -1)
|
|
1251
|
+
])], 8, _hoisted_7)) : createCommentVNode("", true)
|
|
1252
|
+
])) : renderSlot(_ctx.$slots, "nodeInterface", {
|
|
1253
|
+
key: 1,
|
|
1254
|
+
type: "output",
|
|
1255
|
+
node: node.value,
|
|
1256
|
+
intf: output
|
|
1257
|
+
}, () => [
|
|
1258
|
+
createVNode(unref(NodeInterface2), {
|
|
1259
|
+
node: node.value,
|
|
1260
|
+
intf: output
|
|
1261
|
+
}, null, 8, ["node", "intf"])
|
|
1262
|
+
])
|
|
1263
|
+
], 64);
|
|
1264
|
+
}), 128))
|
|
1265
|
+
]),
|
|
1266
|
+
createElementVNode("div", _hoisted_8, [
|
|
1267
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(displayedInputs.value, (input) => {
|
|
1268
|
+
return openBlock(), createElementBlock(Fragment, {
|
|
1269
|
+
key: input.id
|
|
1270
|
+
}, [
|
|
1271
|
+
node.value.state?.hidden ? (openBlock(), createElementBlock("div", _hoisted_9, [
|
|
1272
|
+
input.port ? (openBlock(), createElementBlock("div", {
|
|
1273
|
+
key: 0,
|
|
1274
|
+
id: input.id,
|
|
1275
|
+
title: input.name,
|
|
1276
|
+
class: "baklava-node-interface --input --connected"
|
|
1277
|
+
}, [..._cache[5] || (_cache[5] = [
|
|
1278
|
+
createElementVNode("div", { class: "__port" }, null, -1)
|
|
1279
|
+
])], 8, _hoisted_10)) : createCommentVNode("", true)
|
|
1280
|
+
])) : renderSlot(_ctx.$slots, "nodeInterface", {
|
|
1281
|
+
key: 1,
|
|
1282
|
+
node: node.value,
|
|
1283
|
+
intf: input,
|
|
1284
|
+
type: "input"
|
|
1285
|
+
}, () => [
|
|
1286
|
+
createVNode(unref(NodeInterface2), {
|
|
1287
|
+
node: node.value,
|
|
1288
|
+
intf: input,
|
|
1289
|
+
title: input.name
|
|
1290
|
+
}, null, 8, ["node", "intf", "title"])
|
|
1291
|
+
])
|
|
1292
|
+
], 64);
|
|
1293
|
+
}), 128))
|
|
1294
|
+
])
|
|
1295
|
+
], 34)
|
|
1296
|
+
], 46, _hoisted_1$4);
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
});
|
|
1300
|
+
const _hoisted_1$3 = ["title"];
|
|
1301
|
+
const _hoisted_2$3 = {
|
|
1302
|
+
key: 0,
|
|
1303
|
+
class: "__label"
|
|
1304
|
+
};
|
|
1305
|
+
const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|
1306
|
+
__name: "Checkbox",
|
|
1307
|
+
props: {
|
|
1308
|
+
modelValue: { type: Boolean },
|
|
1309
|
+
inversed: { type: Boolean },
|
|
1310
|
+
name: {}
|
|
1311
|
+
},
|
|
1312
|
+
emits: ["update:modelValue"],
|
|
1313
|
+
setup(__props, { emit: __emit }) {
|
|
1314
|
+
const emit = __emit;
|
|
1315
|
+
return (_ctx, _cache) => {
|
|
1316
|
+
return openBlock(), createElementBlock("div", {
|
|
1317
|
+
class: normalizeClass(["baklava-checkbox", { "--checked": _ctx.inversed ? !_ctx.modelValue : _ctx.modelValue }]),
|
|
1318
|
+
title: _ctx.name,
|
|
1319
|
+
onClick: _cache[0] || (_cache[0] = ($event) => emit("update:modelValue", !_ctx.modelValue))
|
|
1320
|
+
}, [
|
|
1321
|
+
_cache[1] || (_cache[1] = createElementVNode("div", { class: "__checkmark-container" }, [
|
|
1322
|
+
createElementVNode("svg", {
|
|
1323
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1324
|
+
width: "18",
|
|
1325
|
+
height: "18",
|
|
1326
|
+
viewBox: "0 0 18 18"
|
|
1327
|
+
}, [
|
|
1328
|
+
createElementVNode("path", {
|
|
1329
|
+
class: "__checkmark",
|
|
1330
|
+
d: "M 6 5 L 6 10 L 16 10",
|
|
1331
|
+
transform: "rotate(-45 10 10)"
|
|
1332
|
+
})
|
|
1333
|
+
])
|
|
1334
|
+
], -1)),
|
|
1335
|
+
_ctx.name ? (openBlock(), createElementBlock("div", _hoisted_2$3, toDisplayString(_ctx.name), 1)) : createCommentVNode("", true)
|
|
1336
|
+
], 10, _hoisted_1$3);
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
});
|
|
1340
|
+
const _hoisted_1$2 = { class: "__header" };
|
|
1341
|
+
const _hoisted_2$2 = { class: "__node-name" };
|
|
1342
|
+
const _hoisted_3$1 = { style: { "display": "flex" } };
|
|
1343
|
+
const _hoisted_4 = {
|
|
1344
|
+
key: 1,
|
|
1345
|
+
class: "__interface"
|
|
1346
|
+
};
|
|
1347
|
+
const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|
1348
|
+
__name: "CodeGraphSidebar",
|
|
1349
|
+
setup(__props) {
|
|
1350
|
+
const { viewModel } = useViewModel();
|
|
1351
|
+
const { graph } = useGraph();
|
|
1352
|
+
const el = ref(null);
|
|
1353
|
+
const width = toRef(viewModel.value.settings.sidebar, "width");
|
|
1354
|
+
const resizable = computed(() => viewModel.value.settings.sidebar.resizable);
|
|
1355
|
+
let resizeStartWidth = 0;
|
|
1356
|
+
let resizeStartMouseX = 0;
|
|
1357
|
+
const node = computed(() => {
|
|
1358
|
+
const id = graph.value.sidebar.nodeId;
|
|
1359
|
+
return graph.value.nodes.find((x) => x.id === id);
|
|
1360
|
+
});
|
|
1361
|
+
const codeNode = computed(() => node.value);
|
|
1362
|
+
const styles = computed(() => ({
|
|
1363
|
+
width: `${width.value}px`
|
|
1364
|
+
}));
|
|
1365
|
+
const displayedInterfaces = computed(() => {
|
|
1366
|
+
if (!node.value) return [];
|
|
1367
|
+
const allIntfs = [...Object.values(node.value.inputs), ...Object.values(node.value.outputs)];
|
|
1368
|
+
return allIntfs.filter((intf) => intf.displayInSidebar && intf.component);
|
|
1369
|
+
});
|
|
1370
|
+
const close = () => {
|
|
1371
|
+
graph.value.sidebar.visible = false;
|
|
1372
|
+
};
|
|
1373
|
+
const doneRenaming = () => {
|
|
1374
|
+
node.value?.events.update.emit(null);
|
|
1375
|
+
};
|
|
1376
|
+
const startResize = (event) => {
|
|
1377
|
+
resizeStartWidth = width.value;
|
|
1378
|
+
resizeStartMouseX = event.clientX;
|
|
1379
|
+
window.addEventListener("mousemove", onMouseMove);
|
|
1380
|
+
window.addEventListener(
|
|
1381
|
+
"mouseup",
|
|
1382
|
+
() => {
|
|
1383
|
+
window.removeEventListener("mousemove", onMouseMove);
|
|
1384
|
+
},
|
|
1385
|
+
{ once: true }
|
|
1386
|
+
);
|
|
1387
|
+
};
|
|
1388
|
+
const onMouseMove = (event) => {
|
|
1389
|
+
const maxwidth = el.value?.parentElement?.getBoundingClientRect().width ?? 500;
|
|
1390
|
+
const deltaX = event.clientX - resizeStartMouseX;
|
|
1391
|
+
let newWidth = resizeStartWidth - deltaX;
|
|
1392
|
+
if (newWidth < 300) {
|
|
1393
|
+
newWidth = 300;
|
|
1394
|
+
} else if (newWidth > 0.9 * maxwidth) {
|
|
1395
|
+
newWidth = 0.9 * maxwidth;
|
|
1396
|
+
}
|
|
1397
|
+
width.value = newWidth;
|
|
1398
|
+
};
|
|
1399
|
+
return (_ctx, _cache) => {
|
|
1400
|
+
return openBlock(), createElementBlock("div", {
|
|
1401
|
+
ref_key: "el",
|
|
1402
|
+
ref: el,
|
|
1403
|
+
class: normalizeClass(["baklava-sidebar", { "--open": unref(graph).sidebar.visible }]),
|
|
1404
|
+
style: normalizeStyle(styles.value)
|
|
1405
|
+
}, [
|
|
1406
|
+
resizable.value ? (openBlock(), createElementBlock("div", {
|
|
1407
|
+
key: 0,
|
|
1408
|
+
class: "__resizer",
|
|
1409
|
+
onMousedown: startResize
|
|
1410
|
+
}, null, 32)) : createCommentVNode("", true),
|
|
1411
|
+
createElementVNode("div", _hoisted_1$2, [
|
|
1412
|
+
createElementVNode("button", {
|
|
1413
|
+
tabindex: "-1",
|
|
1414
|
+
class: "__close",
|
|
1415
|
+
onClick: close
|
|
1416
|
+
}, "×"),
|
|
1417
|
+
createElementVNode("div", _hoisted_2$2, [
|
|
1418
|
+
createElementVNode("b", null, toDisplayString(node.value ? node.value.title : ""), 1)
|
|
1419
|
+
])
|
|
1420
|
+
]),
|
|
1421
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(displayedInterfaces.value, (intf) => {
|
|
1422
|
+
return openBlock(), createElementBlock("div", {
|
|
1423
|
+
key: intf.id,
|
|
1424
|
+
class: "__interface"
|
|
1425
|
+
}, [
|
|
1426
|
+
createElementVNode("div", _hoisted_3$1, [
|
|
1427
|
+
createVNode(_sfc_main$4, {
|
|
1428
|
+
modelValue: intf.hidden,
|
|
1429
|
+
"onUpdate:modelValue": [
|
|
1430
|
+
($event) => intf.hidden = $event,
|
|
1431
|
+
_cache[0] || (_cache[0] = () => node.value?.events.update.emit(null))
|
|
1432
|
+
],
|
|
1433
|
+
inversed: "",
|
|
1434
|
+
style: { "margin-right": "8px" }
|
|
1435
|
+
}, null, 8, ["modelValue", "onUpdate:modelValue"]),
|
|
1436
|
+
(openBlock(), createBlock(resolveDynamicComponent(intf.component), {
|
|
1437
|
+
modelValue: intf.value,
|
|
1438
|
+
"onUpdate:modelValue": ($event) => intf.value = $event,
|
|
1439
|
+
node: node.value,
|
|
1440
|
+
intf,
|
|
1441
|
+
style: { "width": "100%" }
|
|
1442
|
+
}, null, 8, ["modelValue", "onUpdate:modelValue", "node", "intf"]))
|
|
1443
|
+
])
|
|
1444
|
+
]);
|
|
1445
|
+
}), 128)),
|
|
1446
|
+
codeNode.value && codeNode.value.state ? (openBlock(), createElementBlock("div", _hoisted_4, [
|
|
1447
|
+
_cache[2] || (_cache[2] = createElementVNode("label", null, "Variable name", -1)),
|
|
1448
|
+
withDirectives(createElementVNode("input", {
|
|
1449
|
+
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => codeNode.value.state.variableName = $event),
|
|
1450
|
+
type: "text",
|
|
1451
|
+
class: "baklava-input",
|
|
1452
|
+
title: "Variable name",
|
|
1453
|
+
onBlur: doneRenaming,
|
|
1454
|
+
onKeydown: withKeys(doneRenaming, ["enter"])
|
|
1455
|
+
}, null, 544), [
|
|
1456
|
+
[vModelText, codeNode.value.state.variableName]
|
|
1457
|
+
])
|
|
1458
|
+
])) : createCommentVNode("", true)
|
|
1459
|
+
], 6);
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
});
|
|
1463
|
+
const _sfc_main$2 = defineComponent({
|
|
1464
|
+
props: {
|
|
1465
|
+
type: {
|
|
1466
|
+
type: String,
|
|
1467
|
+
required: true
|
|
1468
|
+
},
|
|
1469
|
+
title: {
|
|
1470
|
+
type: String,
|
|
1471
|
+
required: true
|
|
1472
|
+
}
|
|
1473
|
+
},
|
|
1474
|
+
setup(props) {
|
|
1475
|
+
const { viewModel } = useViewModel();
|
|
1476
|
+
const { switchGraph } = useGraph();
|
|
1477
|
+
const showContextMenu = ref(false);
|
|
1478
|
+
const hasContextMenu = computed(() => props.type.startsWith(GRAPH_NODE_TYPE_PREFIX));
|
|
1479
|
+
const contextMenuItems = [
|
|
1480
|
+
{ label: "Edit Subgraph", value: "editSubgraph" },
|
|
1481
|
+
{ label: "Delete Subgraph", value: "deleteSubgraph" }
|
|
1482
|
+
];
|
|
1483
|
+
const openContextMenu = () => {
|
|
1484
|
+
showContextMenu.value = true;
|
|
1485
|
+
};
|
|
1486
|
+
const onContextMenuClick = (action) => {
|
|
1487
|
+
const graphTemplateId = props.type.substring(GRAPH_NODE_TYPE_PREFIX.length);
|
|
1488
|
+
const graphTemplate = viewModel.value.editor.graphTemplates.find((gt) => gt.id === graphTemplateId);
|
|
1489
|
+
if (!graphTemplate) {
|
|
1490
|
+
return;
|
|
1491
|
+
}
|
|
1492
|
+
switch (action) {
|
|
1493
|
+
case "editSubgraph":
|
|
1494
|
+
switchGraph(graphTemplate);
|
|
1495
|
+
break;
|
|
1496
|
+
case "deleteSubgraph":
|
|
1497
|
+
viewModel.value.editor.removeGraphTemplate(graphTemplate);
|
|
1498
|
+
break;
|
|
1499
|
+
}
|
|
1500
|
+
};
|
|
1501
|
+
return { showContextMenu, hasContextMenu, contextMenuItems, openContextMenu, onContextMenuClick };
|
|
1502
|
+
}
|
|
1503
|
+
});
|
|
1504
|
+
const _hoisted_1$1 = ["data-node-type"];
|
|
1505
|
+
const _hoisted_2$1 = { class: "__title" };
|
|
1506
|
+
const _hoisted_3 = { class: "__title-label" };
|
|
1507
|
+
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
1508
|
+
return openBlock(), createElementBlock("div", {
|
|
1509
|
+
class: "baklava-node --palette",
|
|
1510
|
+
"data-node-type": _ctx.type
|
|
1511
|
+
}, [
|
|
1512
|
+
createElementVNode("div", _hoisted_2$1, [
|
|
1513
|
+
createElementVNode("div", _hoisted_3, toDisplayString(_ctx.title), 1)
|
|
1514
|
+
])
|
|
1515
|
+
], 8, _hoisted_1$1);
|
|
1516
|
+
}
|
|
1517
|
+
const PaletteEntry = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render]]);
|
|
1518
|
+
const _hoisted_1 = {
|
|
1519
|
+
class: "baklava-node --palette",
|
|
1520
|
+
style: { "margin-top": "-20px", "margin-bottom": "30px" }
|
|
1521
|
+
};
|
|
1522
|
+
const _hoisted_2 = { key: 0 };
|
|
1523
|
+
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
1524
|
+
__name: "CodeNodePalette",
|
|
1525
|
+
setup(__props) {
|
|
1526
|
+
const { viewModel } = useViewModel();
|
|
1527
|
+
const { x: mouseX, y: mouseY } = usePointer();
|
|
1528
|
+
const { transform } = useTransform();
|
|
1529
|
+
const categories = useNodeCategories(viewModel);
|
|
1530
|
+
const editorEl = inject("editorEl");
|
|
1531
|
+
const searchQuery = ref("");
|
|
1532
|
+
const draggedNode = ref(null);
|
|
1533
|
+
const filterCategoryBySearch = (categories2) => {
|
|
1534
|
+
if (searchQuery.value) {
|
|
1535
|
+
return categories2.filter(
|
|
1536
|
+
(c) => Object.values(c.nodeTypes).some(
|
|
1537
|
+
(nodeType2) => nodeType2.title.toLowerCase().includes(searchQuery.value?.toLowerCase())
|
|
1538
|
+
)
|
|
1539
|
+
);
|
|
1540
|
+
}
|
|
1541
|
+
return categories2;
|
|
1542
|
+
};
|
|
1543
|
+
const filterNodesBySearch = (nodeTypes) => {
|
|
1544
|
+
if (searchQuery.value) {
|
|
1545
|
+
return Object.values(nodeTypes).filter(
|
|
1546
|
+
(nt) => nt.title.toLowerCase().includes(searchQuery.value?.toLowerCase())
|
|
1547
|
+
);
|
|
1548
|
+
}
|
|
1549
|
+
return Object.values(nodeTypes);
|
|
1550
|
+
};
|
|
1551
|
+
const draggedNodeStyles = computed(() => {
|
|
1552
|
+
if (!draggedNode.value || !editorEl?.value) return {};
|
|
1553
|
+
const { left, top } = editorEl.value.getBoundingClientRect();
|
|
1554
|
+
return {
|
|
1555
|
+
top: `${mouseY.value - top}px`,
|
|
1556
|
+
left: `${mouseX.value - left}px`
|
|
1557
|
+
};
|
|
1558
|
+
});
|
|
1559
|
+
const onDragStart = (type, nodeInformation) => {
|
|
1560
|
+
draggedNode.value = {
|
|
1561
|
+
type,
|
|
1562
|
+
nodeInformation
|
|
1563
|
+
};
|
|
1564
|
+
const onDragEnd = () => {
|
|
1565
|
+
const instance = reactive(new nodeInformation.type());
|
|
1566
|
+
viewModel.value.displayedGraph.addNode(instance);
|
|
1567
|
+
const rect = editorEl.value.getBoundingClientRect();
|
|
1568
|
+
const [x, y] = transform(mouseX.value - rect.left, mouseY.value - rect.top);
|
|
1569
|
+
instance.position.x = x;
|
|
1570
|
+
instance.position.y = y;
|
|
1571
|
+
draggedNode.value = null;
|
|
1572
|
+
document.removeEventListener("pointerup", onDragEnd);
|
|
1573
|
+
};
|
|
1574
|
+
document.addEventListener("pointerup", onDragEnd);
|
|
1575
|
+
};
|
|
1576
|
+
return (_ctx, _cache) => {
|
|
1577
|
+
return openBlock(), createElementBlock(Fragment, null, [
|
|
1578
|
+
createElementVNode("div", {
|
|
1579
|
+
class: normalizeClass(["baklava-node-palette", { "--open": unref(viewModel).settings.palette.enabled }]),
|
|
1580
|
+
onContextmenu: _cache[1] || (_cache[1] = withModifiers(() => {
|
|
1581
|
+
}, ["stop", "prevent"]))
|
|
1582
|
+
}, [
|
|
1583
|
+
createElementVNode("div", _hoisted_1, [
|
|
1584
|
+
withDirectives(createElementVNode("input", {
|
|
1585
|
+
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchQuery.value = $event),
|
|
1586
|
+
type: "text",
|
|
1587
|
+
class: "baklava-input",
|
|
1588
|
+
title: "Filter node types"
|
|
1589
|
+
}, null, 512), [
|
|
1590
|
+
[vModelText, searchQuery.value]
|
|
1591
|
+
])
|
|
1592
|
+
]),
|
|
1593
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(filterCategoryBySearch(unref(categories)), (c) => {
|
|
1594
|
+
return openBlock(), createElementBlock("section", {
|
|
1595
|
+
key: c.name
|
|
1596
|
+
}, [
|
|
1597
|
+
c.name !== "default" ? (openBlock(), createElementBlock("h3", _hoisted_2, toDisplayString(c.name), 1)) : createCommentVNode("", true),
|
|
1598
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(filterNodesBySearch(c.nodeTypes), (ni, nt) => {
|
|
1599
|
+
return openBlock(), createBlock(PaletteEntry, {
|
|
1600
|
+
key: nt,
|
|
1601
|
+
type: nt,
|
|
1602
|
+
title: ni.title,
|
|
1603
|
+
onPointerdown: ($event) => onDragStart(nt, ni)
|
|
1604
|
+
}, null, 8, ["type", "title", "onPointerdown"]);
|
|
1605
|
+
}), 128))
|
|
1606
|
+
]);
|
|
1607
|
+
}), 128))
|
|
1608
|
+
], 34),
|
|
1609
|
+
createVNode(Transition, { name: "fade" }, {
|
|
1610
|
+
default: withCtx(() => [
|
|
1611
|
+
draggedNode.value ? (openBlock(), createElementBlock("div", {
|
|
1612
|
+
key: 0,
|
|
1613
|
+
class: "baklava-dragged-node",
|
|
1614
|
+
style: normalizeStyle(draggedNodeStyles.value)
|
|
1615
|
+
}, [
|
|
1616
|
+
createVNode(PaletteEntry, {
|
|
1617
|
+
type: draggedNode.value.type,
|
|
1618
|
+
title: draggedNode.value.nodeInformation.title
|
|
1619
|
+
}, null, 8, ["type", "title"])
|
|
1620
|
+
], 4)) : createCommentVNode("", true)
|
|
1621
|
+
]),
|
|
1622
|
+
_: 1
|
|
1623
|
+
})
|
|
1624
|
+
], 64);
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
});
|
|
1628
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
1629
|
+
__name: "CodeGraphEditor",
|
|
1630
|
+
props: {
|
|
1631
|
+
viewModel: {}
|
|
1632
|
+
},
|
|
1633
|
+
setup(__props) {
|
|
1634
|
+
const props = __props;
|
|
1635
|
+
const viewModel = toRef(props, "viewModel");
|
|
1636
|
+
const onUpdate = (node) => node.events.update.emit(null);
|
|
1637
|
+
onMounted(() => {
|
|
1638
|
+
viewModel.value.subscribe();
|
|
1639
|
+
viewModel.value.engine.start();
|
|
1640
|
+
});
|
|
1641
|
+
onUnmounted(() => {
|
|
1642
|
+
viewModel.value.unsubscribe();
|
|
1643
|
+
viewModel.value.engine.stop();
|
|
1644
|
+
});
|
|
1645
|
+
return (_ctx, _cache) => {
|
|
1646
|
+
return openBlock(), createBlock(unref(BaklavaEditor), { "view-model": viewModel.value }, {
|
|
1647
|
+
palette: withCtx(() => [
|
|
1648
|
+
createVNode(_sfc_main$1)
|
|
1649
|
+
]),
|
|
1650
|
+
node: withCtx((nodeProps) => [
|
|
1651
|
+
createVNode(_sfc_main$5, mergeProps(nodeProps, {
|
|
1652
|
+
onUpdate: ($event) => onUpdate(nodeProps.node)
|
|
1653
|
+
}), null, 16, ["onUpdate"])
|
|
1654
|
+
]),
|
|
1655
|
+
sidebar: withCtx((nodeProps) => [
|
|
1656
|
+
createVNode(_sfc_main$3, normalizeProps(guardReactiveProps(nodeProps)), null, 16)
|
|
1657
|
+
]),
|
|
1658
|
+
_: 1
|
|
1659
|
+
}, 8, ["view-model"]);
|
|
1660
|
+
};
|
|
1661
|
+
}
|
|
1662
|
+
});
|
|
1663
|
+
const addToolbarCommands = (viewModel) => {
|
|
1664
|
+
const TOGGLE_PALETTE_COMMAND = "TOGGLE_PALETTE";
|
|
1665
|
+
viewModel.commandHandler.registerCommand(TOGGLE_PALETTE_COMMAND, {
|
|
1666
|
+
execute: () => viewModel.settings.palette.enabled = !viewModel.settings.palette.enabled,
|
|
1667
|
+
canExecute: () => true
|
|
1668
|
+
});
|
|
1669
|
+
const CLEAR_ALL_COMMAND = "CLEAR_ALL";
|
|
1670
|
+
viewModel.commandHandler.registerCommand(CLEAR_ALL_COMMAND, {
|
|
1671
|
+
execute: () => viewModel.displayedGraph.nodes.forEach((node) => viewModel.displayedGraph.removeNode(node)),
|
|
1672
|
+
canExecute: () => viewModel.displayedGraph.nodes.length > 0
|
|
1673
|
+
});
|
|
1674
|
+
const TOGGLE_MINIMAP_COMMAND = "TOGGLE_MINIMAP";
|
|
1675
|
+
viewModel.commandHandler.registerCommand(TOGGLE_MINIMAP_COMMAND, {
|
|
1676
|
+
execute: () => viewModel.settings.enableMinimap = !viewModel.settings.enableMinimap,
|
|
1677
|
+
canExecute: () => viewModel.displayedGraph.nodes.length > 1
|
|
1678
|
+
});
|
|
1679
|
+
viewModel.settings.toolbar.commands = [
|
|
1680
|
+
{
|
|
1681
|
+
command: TOGGLE_PALETTE_COMMAND,
|
|
1682
|
+
title: "Toggle palette",
|
|
1683
|
+
// Tooltip text
|
|
1684
|
+
icon: computed(() => viewModel.settings.palette.enabled ? LayoutSidebarLeftCollapse : LayoutSidebarLeftExpand)
|
|
1685
|
+
},
|
|
1686
|
+
...DEFAULT_TOOLBAR_COMMANDS,
|
|
1687
|
+
{
|
|
1688
|
+
command: CLEAR_ALL_COMMAND,
|
|
1689
|
+
title: "Clear all",
|
|
1690
|
+
// Tooltip text
|
|
1691
|
+
icon: TrashOff
|
|
1692
|
+
},
|
|
1693
|
+
{
|
|
1694
|
+
command: TOGGLE_MINIMAP_COMMAND,
|
|
1695
|
+
title: "Toggle minimap",
|
|
1696
|
+
// Tooltip text
|
|
1697
|
+
icon: computed(() => viewModel.settings.enableMinimap ? SchemaOff : Schema)
|
|
1698
|
+
}
|
|
1699
|
+
];
|
|
1700
|
+
};
|
|
1701
|
+
const DEFAULT_SETTINGS = {
|
|
1702
|
+
enableMinimap: false,
|
|
1703
|
+
toolbar: {
|
|
1704
|
+
enabled: true
|
|
1705
|
+
},
|
|
1706
|
+
palette: {
|
|
1707
|
+
enabled: true
|
|
1708
|
+
},
|
|
1709
|
+
sidebar: {
|
|
1710
|
+
enabled: true,
|
|
1711
|
+
resizable: true,
|
|
1712
|
+
width: 350
|
|
1713
|
+
},
|
|
1714
|
+
displayValueOnHover: false
|
|
1715
|
+
};
|
|
1716
|
+
function useCodeGraph(existingEditor) {
|
|
1717
|
+
const viewModel = useBaklava(existingEditor);
|
|
1718
|
+
addToolbarCommands(viewModel);
|
|
1719
|
+
viewModel.code = new Code(viewModel);
|
|
1720
|
+
const settings = {};
|
|
1721
|
+
Object.keys(DEFAULT_SETTINGS).forEach((K) => {
|
|
1722
|
+
settings[K] = typeof DEFAULT_SETTINGS[K] === "object" ? { ...viewModel.settings[K], ...DEFAULT_SETTINGS[K] } : DEFAULT_SETTINGS[K];
|
|
1723
|
+
});
|
|
1724
|
+
viewModel.settings = reactive({ ...viewModel.settings, ...settings });
|
|
1725
|
+
viewModel.settings.nodes.defaultWidth = 350;
|
|
1726
|
+
viewModel.state = reactive({
|
|
1727
|
+
modules: {},
|
|
1728
|
+
token: null
|
|
1729
|
+
});
|
|
1730
|
+
viewModel.engine = new DependencyEngine(viewModel.editor);
|
|
1731
|
+
viewModel.subscribe = () => {
|
|
1732
|
+
if (viewModel.state.token) viewModel.unsubscribe();
|
|
1733
|
+
const token = Symbol();
|
|
1734
|
+
viewModel.displayedGraph.events.addNode.subscribe(token, (node) => node.code = viewModel.code);
|
|
1735
|
+
viewModel.engine.events.beforeRun.subscribe(token, () => {
|
|
1736
|
+
viewModel.engine.pause();
|
|
1737
|
+
viewModel.code.onCodeUpdate();
|
|
1738
|
+
viewModel.code.sortNodes();
|
|
1739
|
+
viewModel.code.updateOutputVariableNames();
|
|
1740
|
+
viewModel.engine.resume();
|
|
1741
|
+
});
|
|
1742
|
+
viewModel.engine.events.afterRun.subscribe(token, (result) => {
|
|
1743
|
+
viewModel.engine.pause();
|
|
1744
|
+
applyResult(result, viewModel.editor);
|
|
1745
|
+
transferCodeScript(viewModel.displayedGraph);
|
|
1746
|
+
viewModel.code.renderNodeCodes();
|
|
1747
|
+
viewModel.code.renderCode();
|
|
1748
|
+
viewModel.engine.resume();
|
|
1749
|
+
});
|
|
1750
|
+
viewModel.state.token = token;
|
|
1751
|
+
};
|
|
1752
|
+
viewModel.unsubscribe = () => {
|
|
1753
|
+
if (!viewModel.state.token) return;
|
|
1754
|
+
const token = viewModel.state.token;
|
|
1755
|
+
viewModel.displayedGraph.events.addNode.unsubscribe(token);
|
|
1756
|
+
viewModel.engine.events.beforeRun.unsubscribe(token);
|
|
1757
|
+
viewModel.engine.events.afterRun.unsubscribe(token);
|
|
1758
|
+
viewModel.state.token = null;
|
|
1759
|
+
};
|
|
1760
|
+
return viewModel;
|
|
1761
|
+
}
|
|
1762
|
+
export {
|
|
1763
|
+
AbstractCodeNode,
|
|
1764
|
+
ButtonInterface,
|
|
1765
|
+
ButtonInterfaceComponent2 as ButtonInterfaceComponent,
|
|
1766
|
+
CheckboxInterface,
|
|
1767
|
+
CheckboxInterfaceComponent2 as CheckboxInterfaceComponent,
|
|
1768
|
+
Code,
|
|
1769
|
+
_sfc_main as CodeGraphEditor,
|
|
1770
|
+
CodeInputInterface,
|
|
1771
|
+
CodeNode,
|
|
1772
|
+
CodeNodeInterface,
|
|
1773
|
+
CodeOutputInterface,
|
|
1774
|
+
DEFAULT_SETTINGS,
|
|
1775
|
+
DynamicCodeNode,
|
|
1776
|
+
IntegerInterface,
|
|
1777
|
+
IntegerInterfaceComponent2 as IntegerInterfaceComponent,
|
|
1778
|
+
NumberInterface,
|
|
1779
|
+
NumberInterfaceComponent2 as NumberInterfaceComponent,
|
|
1780
|
+
SelectInterface,
|
|
1781
|
+
SelectInterfaceComponent2 as SelectInterfaceComponent,
|
|
1782
|
+
SliderInterface,
|
|
1783
|
+
SliderInterfaceComponent2 as SliderInterfaceComponent,
|
|
1784
|
+
TextInputInterface,
|
|
1785
|
+
TextInputInterfaceComponent2 as TextInputInterfaceComponent,
|
|
1786
|
+
TextInterface,
|
|
1787
|
+
TextareaInputInterface,
|
|
1788
|
+
TextareaInputInterfaceComponent2 as TextareaInputInterfaceComponent,
|
|
1789
|
+
addToolbarCommands,
|
|
1790
|
+
defineCodeNode,
|
|
1791
|
+
defineDynamicCodeNode,
|
|
1792
|
+
getCodeNodes,
|
|
1793
|
+
getPositionAtColumn,
|
|
1794
|
+
getPositionBeforeNode,
|
|
1795
|
+
loadNodeState,
|
|
1796
|
+
saveNodeState,
|
|
1797
|
+
transferCodeScript,
|
|
1798
|
+
useCodeGraph
|
|
1799
|
+
};
|