@bian-womp/spark-workbench 0.2.73 → 0.2.75
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/lib/cjs/index.cjs +257 -47
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/core/InMemoryWorkbench.d.ts +0 -3
- package/lib/cjs/src/core/InMemoryWorkbench.d.ts.map +1 -1
- package/lib/cjs/src/index.d.ts +1 -0
- package/lib/cjs/src/index.d.ts.map +1 -1
- package/lib/cjs/src/misc/KeyboardShortcutToast.d.ts +16 -0
- package/lib/cjs/src/misc/KeyboardShortcutToast.d.ts.map +1 -0
- package/lib/cjs/src/misc/WorkbenchCanvas.d.ts.map +1 -1
- package/lib/cjs/src/misc/context/WorkbenchContext.d.ts +3 -11
- package/lib/cjs/src/misc/context/WorkbenchContext.d.ts.map +1 -1
- package/lib/cjs/src/misc/context/WorkbenchContext.provider.d.ts.map +1 -1
- package/lib/cjs/src/misc/context-menu/ContextMenuHandlers.d.ts +5 -0
- package/lib/cjs/src/misc/context-menu/ContextMenuHandlers.d.ts.map +1 -1
- package/lib/cjs/src/misc/context-menu/ContextMenuHelpers.d.ts +1 -1
- package/lib/cjs/src/misc/context-menu/ContextMenuHelpers.d.ts.map +1 -1
- package/lib/cjs/src/misc/context-menu/DefaultContextMenu.d.ts.map +1 -1
- package/lib/cjs/src/misc/context-menu/NodeContextMenu.d.ts.map +1 -1
- package/lib/cjs/src/misc/context-menu/SelectionContextMenu.d.ts.map +1 -1
- package/lib/cjs/src/misc/load.d.ts.map +1 -1
- package/lib/cjs/src/misc/viewport-utils.d.ts +9 -0
- package/lib/cjs/src/misc/viewport-utils.d.ts.map +1 -0
- package/lib/cjs/src/runtime/IGraphRunner.d.ts +13 -1
- package/lib/cjs/src/runtime/IGraphRunner.d.ts.map +1 -1
- package/lib/cjs/src/runtime/RemoteGraphRunner.d.ts +5 -0
- package/lib/cjs/src/runtime/RemoteGraphRunner.d.ts.map +1 -1
- package/lib/esm/index.js +256 -48
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/core/InMemoryWorkbench.d.ts +0 -3
- package/lib/esm/src/core/InMemoryWorkbench.d.ts.map +1 -1
- package/lib/esm/src/index.d.ts +1 -0
- package/lib/esm/src/index.d.ts.map +1 -1
- package/lib/esm/src/misc/KeyboardShortcutToast.d.ts +16 -0
- package/lib/esm/src/misc/KeyboardShortcutToast.d.ts.map +1 -0
- package/lib/esm/src/misc/WorkbenchCanvas.d.ts.map +1 -1
- package/lib/esm/src/misc/context/WorkbenchContext.d.ts +3 -11
- package/lib/esm/src/misc/context/WorkbenchContext.d.ts.map +1 -1
- package/lib/esm/src/misc/context/WorkbenchContext.provider.d.ts.map +1 -1
- package/lib/esm/src/misc/context-menu/ContextMenuHandlers.d.ts +5 -0
- package/lib/esm/src/misc/context-menu/ContextMenuHandlers.d.ts.map +1 -1
- package/lib/esm/src/misc/context-menu/ContextMenuHelpers.d.ts +1 -1
- package/lib/esm/src/misc/context-menu/ContextMenuHelpers.d.ts.map +1 -1
- package/lib/esm/src/misc/context-menu/DefaultContextMenu.d.ts.map +1 -1
- package/lib/esm/src/misc/context-menu/NodeContextMenu.d.ts.map +1 -1
- package/lib/esm/src/misc/context-menu/SelectionContextMenu.d.ts.map +1 -1
- package/lib/esm/src/misc/load.d.ts.map +1 -1
- package/lib/esm/src/misc/viewport-utils.d.ts +9 -0
- package/lib/esm/src/misc/viewport-utils.d.ts.map +1 -0
- package/lib/esm/src/runtime/IGraphRunner.d.ts +13 -1
- package/lib/esm/src/runtime/IGraphRunner.d.ts.map +1 -1
- package/lib/esm/src/runtime/RemoteGraphRunner.d.ts +5 -0
- package/lib/esm/src/runtime/RemoteGraphRunner.d.ts.map +1 -1
- package/package.json +4 -4
package/lib/cjs/index.cjs
CHANGED
|
@@ -8,7 +8,6 @@ var React = require('react');
|
|
|
8
8
|
var cx = require('classnames');
|
|
9
9
|
var jsxRuntime = require('react/jsx-runtime');
|
|
10
10
|
var react$1 = require('@phosphor-icons/react');
|
|
11
|
-
var isEqual = require('lodash/isEqual');
|
|
12
11
|
|
|
13
12
|
class DefaultUIExtensionRegistry {
|
|
14
13
|
constructor() {
|
|
@@ -280,7 +279,7 @@ class InMemoryWorkbench extends AbstractWorkbench {
|
|
|
280
279
|
}
|
|
281
280
|
// Position and selection APIs for React Flow bridge
|
|
282
281
|
setPositions(map, options) {
|
|
283
|
-
this.positions = { ...map };
|
|
282
|
+
this.positions = { ...this.positions, ...map };
|
|
284
283
|
this.emit("graphUiChanged", {
|
|
285
284
|
def: this.def,
|
|
286
285
|
change: { type: "moveNodes" },
|
|
@@ -323,12 +322,13 @@ class InMemoryWorkbench extends AbstractWorkbench {
|
|
|
323
322
|
// Clear selection
|
|
324
323
|
this.setSelection({ nodes: [], edges: [] }, options);
|
|
325
324
|
}
|
|
326
|
-
setViewport(viewport
|
|
325
|
+
setViewport(viewport) {
|
|
326
|
+
if (lod.isEqual(this.viewport, viewport))
|
|
327
|
+
return;
|
|
327
328
|
this.viewport = { ...viewport };
|
|
328
329
|
this.emit("graphUiChanged", {
|
|
329
330
|
def: this.def,
|
|
330
331
|
change: { type: "viewport" },
|
|
331
|
-
...options,
|
|
332
332
|
});
|
|
333
333
|
}
|
|
334
334
|
getViewport() {
|
|
@@ -971,6 +971,24 @@ class LocalGraphRunner extends AbstractGraphRunner {
|
|
|
971
971
|
}
|
|
972
972
|
}
|
|
973
973
|
|
|
974
|
+
function isValidViewport(viewport) {
|
|
975
|
+
return (viewport !== null &&
|
|
976
|
+
typeof viewport === "object" &&
|
|
977
|
+
"x" in viewport &&
|
|
978
|
+
"y" in viewport &&
|
|
979
|
+
"zoom" in viewport &&
|
|
980
|
+
typeof viewport.x === "number" &&
|
|
981
|
+
typeof viewport.y === "number" &&
|
|
982
|
+
typeof viewport.zoom === "number");
|
|
983
|
+
}
|
|
984
|
+
function excludeViewportFromUIState(uiState) {
|
|
985
|
+
if (!uiState) {
|
|
986
|
+
return {};
|
|
987
|
+
}
|
|
988
|
+
const { viewport: _ignoredViewport, ...rest } = uiState;
|
|
989
|
+
return rest;
|
|
990
|
+
}
|
|
991
|
+
|
|
974
992
|
// Counter for generating readable runner IDs
|
|
975
993
|
let remoteRunnerCounter = 0;
|
|
976
994
|
class RemoteGraphRunner extends AbstractGraphRunner {
|
|
@@ -1142,9 +1160,26 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1142
1160
|
this.clientPromise = (async () => {
|
|
1143
1161
|
// Build client config from backend config
|
|
1144
1162
|
const clientConfig = this.buildClientConfig(backend);
|
|
1145
|
-
//
|
|
1163
|
+
// Wrap custom event handler to intercept flow-viewport events and emit viewport event
|
|
1164
|
+
const wrappedOnCustomEvent = (event) => {
|
|
1165
|
+
const msg = event?.message;
|
|
1166
|
+
if (msg &&
|
|
1167
|
+
typeof msg === "object" &&
|
|
1168
|
+
"type" in msg &&
|
|
1169
|
+
msg.type === "flow-viewport") {
|
|
1170
|
+
const viewport = msg.payload?.viewport;
|
|
1171
|
+
if (isValidViewport(viewport)) {
|
|
1172
|
+
this.emit("viewport", { viewport });
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
// Call original handler if provided
|
|
1176
|
+
if (backend.onCustomEvent) {
|
|
1177
|
+
backend.onCustomEvent(event);
|
|
1178
|
+
}
|
|
1179
|
+
};
|
|
1180
|
+
// Create client with wrapped custom event handler
|
|
1146
1181
|
const client = new sparkRemote.RuntimeApiClient(clientConfig, {
|
|
1147
|
-
onCustomEvent:
|
|
1182
|
+
onCustomEvent: wrappedOnCustomEvent,
|
|
1148
1183
|
runnerId: this.runnerId,
|
|
1149
1184
|
});
|
|
1150
1185
|
// Setup event subscriptions
|
|
@@ -1419,6 +1454,20 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1419
1454
|
const client = await this.ensureClient();
|
|
1420
1455
|
await client.copyOutputs(fromNodeId, toNodeId, options);
|
|
1421
1456
|
}
|
|
1457
|
+
async setViewport(viewport) {
|
|
1458
|
+
const client = await this.ensureClient();
|
|
1459
|
+
const transport = client.transport;
|
|
1460
|
+
if (transport && transport.send) {
|
|
1461
|
+
transport.send({
|
|
1462
|
+
seq: Date.now(),
|
|
1463
|
+
ts: Date.now(),
|
|
1464
|
+
message: {
|
|
1465
|
+
type: "SetViewport",
|
|
1466
|
+
payload: { viewport },
|
|
1467
|
+
},
|
|
1468
|
+
});
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1422
1471
|
triggerExternal(nodeId, event, options) {
|
|
1423
1472
|
// If engine exists, call directly; otherwise ensure client (fire-and-forget)
|
|
1424
1473
|
if (this.engine) {
|
|
@@ -2436,7 +2485,8 @@ function isSnapshotPayload(parsed) {
|
|
|
2436
2485
|
async function download(wb, runner) {
|
|
2437
2486
|
try {
|
|
2438
2487
|
const def = wb.export();
|
|
2439
|
-
const
|
|
2488
|
+
const fullUiState = wb.getUIState();
|
|
2489
|
+
const uiState = excludeViewportFromUIState(fullUiState);
|
|
2440
2490
|
const runtimeState = wb.getRuntimeState();
|
|
2441
2491
|
let snapshot;
|
|
2442
2492
|
if (runner.isRunning()) {
|
|
@@ -2446,7 +2496,7 @@ async function download(wb, runner) {
|
|
|
2446
2496
|
def,
|
|
2447
2497
|
extData: {
|
|
2448
2498
|
...(fullSnapshot.extData || {}),
|
|
2449
|
-
ui: uiState,
|
|
2499
|
+
ui: Object.keys(uiState || {}).length > 0 ? uiState : undefined,
|
|
2450
2500
|
runtime: runtimeState || undefined,
|
|
2451
2501
|
},
|
|
2452
2502
|
};
|
|
@@ -2458,7 +2508,10 @@ async function download(wb, runner) {
|
|
|
2458
2508
|
inputs,
|
|
2459
2509
|
outputs: {},
|
|
2460
2510
|
environment: {},
|
|
2461
|
-
extData: {
|
|
2511
|
+
extData: {
|
|
2512
|
+
ui: Object.keys(uiState || {}).length > 0 ? uiState : undefined,
|
|
2513
|
+
runtime: runtimeState || undefined,
|
|
2514
|
+
},
|
|
2462
2515
|
};
|
|
2463
2516
|
}
|
|
2464
2517
|
downloadJSON(snapshot, `spark-snapshot-${generateTimestamp()}.json`);
|
|
@@ -2482,7 +2535,8 @@ async function upload(parsed, wb, runner) {
|
|
|
2482
2535
|
}
|
|
2483
2536
|
await wb.load(def);
|
|
2484
2537
|
if (extData.ui && typeof extData.ui === "object") {
|
|
2485
|
-
|
|
2538
|
+
const uiWithoutViewport = excludeViewportFromUIState(extData.ui);
|
|
2539
|
+
wb.setUIState(uiWithoutViewport);
|
|
2486
2540
|
}
|
|
2487
2541
|
if (extData.runtime && typeof extData.runtime === "object") {
|
|
2488
2542
|
wb.setRuntimeState(extData.runtime);
|
|
@@ -2729,11 +2783,12 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
2729
2783
|
}
|
|
2730
2784
|
// Save cleaned metadata to workbench state
|
|
2731
2785
|
wb.setRuntimeState(metadata);
|
|
2732
|
-
|
|
2733
|
-
const
|
|
2734
|
-
// Save both runtime and UI state to extData (merge to preserve both)
|
|
2786
|
+
const fullUiState = wb.getUIState();
|
|
2787
|
+
const uiWithoutViewport = excludeViewportFromUIState(fullUiState);
|
|
2735
2788
|
await runner.setExtData?.({
|
|
2736
|
-
...(
|
|
2789
|
+
...(Object.keys(uiWithoutViewport || {}).length > 0
|
|
2790
|
+
? { ui: uiWithoutViewport }
|
|
2791
|
+
: {}),
|
|
2737
2792
|
runtime: metadata,
|
|
2738
2793
|
});
|
|
2739
2794
|
}
|
|
@@ -3167,6 +3222,16 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
3167
3222
|
}
|
|
3168
3223
|
});
|
|
3169
3224
|
const offWbGraphUiChanged = wb.on("graphUiChanged", async (event) => {
|
|
3225
|
+
// Handle viewport changes separately (send via SetViewport command, not commit)
|
|
3226
|
+
if (event.change?.type === "viewport") {
|
|
3227
|
+
const viewport = wb.getViewport();
|
|
3228
|
+
if (viewport && runner.setViewport) {
|
|
3229
|
+
runner.setViewport(viewport).catch((err) => {
|
|
3230
|
+
console.warn("[WorkbenchContext] Failed to send viewport update:", err);
|
|
3231
|
+
});
|
|
3232
|
+
}
|
|
3233
|
+
return;
|
|
3234
|
+
}
|
|
3170
3235
|
// Only commit if commit flag is true (e.g., drag end, not during dragging)
|
|
3171
3236
|
if (event.commit) {
|
|
3172
3237
|
// Build detailed reason from change type
|
|
@@ -3182,9 +3247,6 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
3182
3247
|
else if (changeType === "selection") {
|
|
3183
3248
|
reason = "selection";
|
|
3184
3249
|
}
|
|
3185
|
-
else if (changeType === "viewport") {
|
|
3186
|
-
reason = "viewport";
|
|
3187
|
-
}
|
|
3188
3250
|
}
|
|
3189
3251
|
await saveUiRuntimeMetadata();
|
|
3190
3252
|
const history = await runner
|
|
@@ -3216,7 +3278,12 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
3216
3278
|
console.error("Failed to handle registry changed event");
|
|
3217
3279
|
}
|
|
3218
3280
|
});
|
|
3219
|
-
|
|
3281
|
+
const offFlowViewport = runner.on("viewport", (event) => {
|
|
3282
|
+
const viewport = event.viewport;
|
|
3283
|
+
if (isValidViewport(viewport)) {
|
|
3284
|
+
wb.setViewport(viewport);
|
|
3285
|
+
}
|
|
3286
|
+
});
|
|
3220
3287
|
const offRunnerTransport = runner.on("transport", (t) => {
|
|
3221
3288
|
if (t.state === "disconnected") {
|
|
3222
3289
|
console.info("[WorkbenchContext] Transport disconnected, resetting node status");
|
|
@@ -3256,6 +3323,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
3256
3323
|
offWbSelectionChanged();
|
|
3257
3324
|
offRunnerRegistry();
|
|
3258
3325
|
offRunnerTransport();
|
|
3326
|
+
offFlowViewport();
|
|
3259
3327
|
};
|
|
3260
3328
|
}, [runner, wb, setRegistry]);
|
|
3261
3329
|
const isRunning = React.useCallback(() => runner.isRunning(), [runner]);
|
|
@@ -3614,6 +3682,47 @@ function createNodeCopyHandler(wb, runner, nodeId, getDefaultNodeSize, onCopyRes
|
|
|
3614
3682
|
* Creates base selection context menu handlers.
|
|
3615
3683
|
*/
|
|
3616
3684
|
function createSelectionContextMenuHandlers(wb, onClose, getDefaultNodeSize, onCopyResult, runner) {
|
|
3685
|
+
const onDuplicate = runner
|
|
3686
|
+
? () => {
|
|
3687
|
+
const selection = wb.getSelection();
|
|
3688
|
+
if (selection.nodes.length === 0) {
|
|
3689
|
+
onClose();
|
|
3690
|
+
return;
|
|
3691
|
+
}
|
|
3692
|
+
const def = wb.export();
|
|
3693
|
+
const positions = wb.getPositions();
|
|
3694
|
+
const newNodes = [];
|
|
3695
|
+
// Duplicate each selected node
|
|
3696
|
+
for (const nodeId of selection.nodes) {
|
|
3697
|
+
const n = def.nodes.find((n) => n.nodeId === nodeId);
|
|
3698
|
+
if (!n)
|
|
3699
|
+
continue;
|
|
3700
|
+
const pos = positions[nodeId] || { x: 0, y: 0 };
|
|
3701
|
+
// Get inputs without bindings (literal values only)
|
|
3702
|
+
const allInputs = runner.getInputs(def)[nodeId] || {};
|
|
3703
|
+
const inboundHandles = new Set(def.edges
|
|
3704
|
+
.filter((e) => e.target.nodeId === nodeId)
|
|
3705
|
+
.map((e) => e.target.handle));
|
|
3706
|
+
const inputsWithoutBindings = Object.fromEntries(Object.entries(allInputs).filter(([handle]) => !inboundHandles.has(handle)));
|
|
3707
|
+
const newNodeId = wb.addNode({
|
|
3708
|
+
typeId: n.typeId,
|
|
3709
|
+
params: n.params,
|
|
3710
|
+
position: { x: pos.x + 24, y: pos.y + 24 },
|
|
3711
|
+
resolvedHandles: n.resolvedHandles,
|
|
3712
|
+
}, {
|
|
3713
|
+
inputs: inputsWithoutBindings,
|
|
3714
|
+
copyOutputsFrom: nodeId,
|
|
3715
|
+
dry: true,
|
|
3716
|
+
});
|
|
3717
|
+
newNodes.push(newNodeId);
|
|
3718
|
+
}
|
|
3719
|
+
// Select all newly duplicated nodes
|
|
3720
|
+
if (newNodes.length > 0) {
|
|
3721
|
+
wb.setSelection({ nodes: newNodes, edges: [] }, { commit: true, reason: "duplicate-selection" });
|
|
3722
|
+
}
|
|
3723
|
+
onClose();
|
|
3724
|
+
}
|
|
3725
|
+
: undefined;
|
|
3617
3726
|
return {
|
|
3618
3727
|
onCopy: runner
|
|
3619
3728
|
? createCopyHandler(wb, runner, getDefaultNodeSize, onCopyResult)
|
|
@@ -3625,13 +3734,14 @@ function createSelectionContextMenuHandlers(wb, onClose, getDefaultNodeSize, onC
|
|
|
3625
3734
|
wb.deleteSelection({ commit: true, reason: "delete-selection" });
|
|
3626
3735
|
onClose();
|
|
3627
3736
|
},
|
|
3737
|
+
onDuplicate,
|
|
3628
3738
|
onClose,
|
|
3629
3739
|
};
|
|
3630
3740
|
}
|
|
3631
3741
|
/**
|
|
3632
3742
|
* Creates base default context menu handlers.
|
|
3633
3743
|
*/
|
|
3634
|
-
function createDefaultContextMenuHandlers(onAddNode, onClose, onPaste, runner, getCopiedData, clearCopiedData, history) {
|
|
3744
|
+
function createDefaultContextMenuHandlers(onAddNode, onClose, onPaste, runner, getCopiedData, clearCopiedData, history, wb) {
|
|
3635
3745
|
// Wrap paste handler to clear storage after paste
|
|
3636
3746
|
const wrappedOnPaste = onPaste && getCopiedData && clearCopiedData
|
|
3637
3747
|
? (position) => {
|
|
@@ -3642,12 +3752,22 @@ function createDefaultContextMenuHandlers(onAddNode, onClose, onPaste, runner, g
|
|
|
3642
3752
|
const hasPasteData = getCopiedData ? () => !!getCopiedData() : undefined;
|
|
3643
3753
|
const canUndo = history ? history.undoCount > 0 : undefined;
|
|
3644
3754
|
const canRedo = history ? history.redoCount > 0 : undefined;
|
|
3755
|
+
const onSelectAll = wb
|
|
3756
|
+
? () => {
|
|
3757
|
+
const def = wb.export();
|
|
3758
|
+
const allNodeIds = def.nodes.map((n) => n.nodeId);
|
|
3759
|
+
const allEdgeIds = def.edges.map((e) => e.id);
|
|
3760
|
+
wb.setSelection({ nodes: allNodeIds, edges: allEdgeIds }, { commit: true, reason: "select-all" });
|
|
3761
|
+
onClose();
|
|
3762
|
+
}
|
|
3763
|
+
: undefined;
|
|
3645
3764
|
return {
|
|
3646
3765
|
onAddNode,
|
|
3647
3766
|
onPaste: wrappedOnPaste,
|
|
3648
3767
|
hasPasteData,
|
|
3649
3768
|
onUndo: runner ? () => runner.undo().then(() => onClose()) : undefined,
|
|
3650
3769
|
onRedo: runner ? () => runner.redo().then(() => onClose()) : undefined,
|
|
3770
|
+
onSelectAll,
|
|
3651
3771
|
canUndo,
|
|
3652
3772
|
canRedo,
|
|
3653
3773
|
onClose,
|
|
@@ -4187,6 +4307,7 @@ function DefaultContextMenu({ open, clientPos, handlers, registry, nodeIds, enab
|
|
|
4187
4307
|
undo: "⌘/Ctrl + Z",
|
|
4188
4308
|
redo: "⌘/Ctrl + Shift + Z",
|
|
4189
4309
|
paste: "⌘/Ctrl + V",
|
|
4310
|
+
selectAll: "⌘/Ctrl + A",
|
|
4190
4311
|
}, }) {
|
|
4191
4312
|
const rf = react.useReactFlow();
|
|
4192
4313
|
const [query, setQuery] = React.useState("");
|
|
@@ -4289,7 +4410,7 @@ function DefaultContextMenu({ open, clientPos, handlers, registry, nodeIds, enab
|
|
|
4289
4410
|
return (jsxRuntime.jsxs("div", { ref: ref, tabIndex: -1, className: "fixed z-[1000] bg-white border border-gray-300 rounded-lg shadow-lg p-1 min-w-[180px] text-sm text-gray-700 select-none", style: { left: x, top: y }, onClick: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), onWheel: (e) => e.stopPropagation(), onContextMenu: (e) => {
|
|
4290
4411
|
e.preventDefault();
|
|
4291
4412
|
e.stopPropagation();
|
|
4292
|
-
}, children: [hasPasteData && handlers.onPaste && (jsxRuntime.jsx(ContextMenuButton, { label: "Paste", onClick: handlePaste, shortcut: keyboardShortcuts.paste, enableKeyboardShortcuts: enableKeyboardShortcuts })), (handlers.onUndo || handlers.onRedo) && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [hasPasteData && handlers.onPaste && (jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" })), handlers.onUndo && (jsxRuntime.jsx(ContextMenuButton, { label: "Undo", onClick: handlers.onUndo, disabled: !canUndo, shortcut: keyboardShortcuts.undo, enableKeyboardShortcuts: enableKeyboardShortcuts })), handlers.onRedo && (jsxRuntime.jsx(ContextMenuButton, { label: "Redo", onClick: handlers.onRedo, disabled: !canRedo, shortcut: keyboardShortcuts.redo, enableKeyboardShortcuts: enableKeyboardShortcuts }))] })), hasPasteData &&
|
|
4413
|
+
}, children: [hasPasteData && handlers.onPaste && (jsxRuntime.jsx(ContextMenuButton, { label: "Paste", onClick: handlePaste, shortcut: keyboardShortcuts.paste, enableKeyboardShortcuts: enableKeyboardShortcuts })), (handlers.onUndo || handlers.onRedo || handlers.onSelectAll) && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [hasPasteData && handlers.onPaste && (jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" })), handlers.onSelectAll && (jsxRuntime.jsx(ContextMenuButton, { label: "Select All", onClick: handlers.onSelectAll, shortcut: keyboardShortcuts.selectAll, enableKeyboardShortcuts: enableKeyboardShortcuts })), handlers.onSelectAll && (handlers.onUndo || handlers.onRedo) && (jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" })), handlers.onUndo && (jsxRuntime.jsx(ContextMenuButton, { label: "Undo", onClick: handlers.onUndo, disabled: !canUndo, shortcut: keyboardShortcuts.undo, enableKeyboardShortcuts: enableKeyboardShortcuts })), handlers.onRedo && (jsxRuntime.jsx(ContextMenuButton, { label: "Redo", onClick: handlers.onRedo, disabled: !canRedo, shortcut: keyboardShortcuts.redo, enableKeyboardShortcuts: enableKeyboardShortcuts })), (handlers.onUndo || handlers.onRedo) && (jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" }))] })), hasPasteData &&
|
|
4293
4414
|
handlers.onPaste &&
|
|
4294
4415
|
!handlers.onUndo &&
|
|
4295
4416
|
!handlers.onRedo && jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" }), jsxRuntime.jsxs("div", { className: "px-2 py-1 font-semibold text-gray-700", children: ["Add Node", " ", jsxRuntime.jsxs("span", { className: "text-gray-500 font-normal", children: ["(", totalCount, ")"] })] }), jsxRuntime.jsx("div", { className: "px-2 pb-1", children: jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: query, onChange: (e) => setQuery(e.target.value), placeholder: "Filter nodes...", className: "w-full border border-gray-300 rounded px-2 py-1 text-sm outline-none focus:border-gray-400 select-text", onClick: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), onWheel: (e) => e.stopPropagation() }) }), jsxRuntime.jsx("div", { className: "max-h-60 overflow-auto", children: totalCount > 0 ? (renderTree(root)) : (jsxRuntime.jsx("div", { className: "px-3 py-2 text-gray-400", children: "No matches" })) })] }));
|
|
@@ -4297,7 +4418,8 @@ function DefaultContextMenu({ open, clientPos, handlers, registry, nodeIds, enab
|
|
|
4297
4418
|
|
|
4298
4419
|
function NodeContextMenu({ open, clientPos, nodeId, handlers, canRunPull, bakeableOutputs, enableKeyboardShortcuts = true, keyboardShortcuts = {
|
|
4299
4420
|
copy: "⌘/Ctrl + C",
|
|
4300
|
-
duplicate: "⌘/Ctrl +
|
|
4421
|
+
duplicate: "⌘/Ctrl + E",
|
|
4422
|
+
duplicateWithEdges: "⌘/Ctrl + Shift + E",
|
|
4301
4423
|
delete: "Delete",
|
|
4302
4424
|
}, }) {
|
|
4303
4425
|
const ref = React.useRef(null);
|
|
@@ -4337,11 +4459,12 @@ function NodeContextMenu({ open, clientPos, nodeId, handlers, canRunPull, bakeab
|
|
|
4337
4459
|
return (jsxRuntime.jsxs("div", { ref: ref, tabIndex: -1, className: "fixed z-[1000] bg-white border border-gray-300 rounded-lg shadow-lg p-1 min-w-[180px] text-sm text-gray-700 select-none", style: { left: x, top: y }, onClick: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), onWheel: (e) => e.stopPropagation(), onContextMenu: (e) => {
|
|
4338
4460
|
e.preventDefault();
|
|
4339
4461
|
e.stopPropagation();
|
|
4340
|
-
}, children: [jsxRuntime.jsxs("div", { className: "px-2 py-1 font-semibold text-gray-700", children: ["Node (", nodeId, ")"] }), jsxRuntime.jsx(ContextMenuButton, { label: "Delete", onClick: handlers.onDelete, shortcut: keyboardShortcuts.delete, enableKeyboardShortcuts: enableKeyboardShortcuts }), jsxRuntime.jsx(ContextMenuButton, { label: "Duplicate", onClick: handlers.onDuplicate, shortcut: keyboardShortcuts.duplicate, enableKeyboardShortcuts: enableKeyboardShortcuts }), jsxRuntime.jsx(
|
|
4462
|
+
}, children: [jsxRuntime.jsxs("div", { className: "px-2 py-1 font-semibold text-gray-700", children: ["Node (", nodeId, ")"] }), jsxRuntime.jsx(ContextMenuButton, { label: "Delete", onClick: handlers.onDelete, shortcut: keyboardShortcuts.delete, enableKeyboardShortcuts: enableKeyboardShortcuts }), jsxRuntime.jsx(ContextMenuButton, { label: "Duplicate", onClick: handlers.onDuplicate, shortcut: keyboardShortcuts.duplicate, enableKeyboardShortcuts: enableKeyboardShortcuts }), jsxRuntime.jsx(ContextMenuButton, { label: "Duplicate with edges", onClick: handlers.onDuplicateWithEdges, shortcut: keyboardShortcuts.duplicateWithEdges, enableKeyboardShortcuts: enableKeyboardShortcuts }), canRunPull && (jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handlers.onRunPull, children: "Run (pull)" })), jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" }), jsxRuntime.jsx(ContextMenuButton, { label: "Copy", onClick: handlers.onCopy, shortcut: keyboardShortcuts.copy, enableKeyboardShortcuts: enableKeyboardShortcuts }), jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handlers.onCopyId, children: "Copy Node ID" }), bakeableOutputs.length > 0 && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" }), jsxRuntime.jsx("div", { className: "px-2 py-1 font-semibold text-gray-700", children: "Bake" }), bakeableOutputs.map((h) => (jsxRuntime.jsxs("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: () => handlers.onBake(h), children: ["Bake: ", h] }, h)))] }))] }));
|
|
4341
4463
|
}
|
|
4342
4464
|
|
|
4343
4465
|
function SelectionContextMenu({ open, clientPos, handlers, enableKeyboardShortcuts = true, keyboardShortcuts = {
|
|
4344
4466
|
copy: "⌘/Ctrl + C",
|
|
4467
|
+
duplicate: "⌘/Ctrl + E",
|
|
4345
4468
|
delete: "Delete",
|
|
4346
4469
|
}, }) {
|
|
4347
4470
|
const ref = React.useRef(null);
|
|
@@ -4381,7 +4504,45 @@ function SelectionContextMenu({ open, clientPos, handlers, enableKeyboardShortcu
|
|
|
4381
4504
|
return (jsxRuntime.jsxs("div", { ref: ref, tabIndex: -1, className: "fixed z-[1000] bg-white border border-gray-300 rounded-lg shadow-lg p-1 min-w-[180px] text-sm text-gray-700 select-none", style: { left: x, top: y }, onClick: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), onWheel: (e) => e.stopPropagation(), onContextMenu: (e) => {
|
|
4382
4505
|
e.preventDefault();
|
|
4383
4506
|
e.stopPropagation();
|
|
4384
|
-
}, children: [jsxRuntime.jsx("div", { className: "px-2 py-1 font-semibold text-gray-700", children: "Selection" }), jsxRuntime.jsx(ContextMenuButton, { label: "Copy", onClick: handlers.onCopy, shortcut: keyboardShortcuts.copy, enableKeyboardShortcuts: enableKeyboardShortcuts }), jsxRuntime.jsx(ContextMenuButton, { label: "Delete", onClick: handlers.onDelete, shortcut: keyboardShortcuts.delete, enableKeyboardShortcuts: enableKeyboardShortcuts })] }));
|
|
4507
|
+
}, children: [jsxRuntime.jsx("div", { className: "px-2 py-1 font-semibold text-gray-700", children: "Selection" }), jsxRuntime.jsx(ContextMenuButton, { label: "Copy", onClick: handlers.onCopy, shortcut: keyboardShortcuts.copy, enableKeyboardShortcuts: enableKeyboardShortcuts }), handlers.onDuplicate && (jsxRuntime.jsx(ContextMenuButton, { label: "Duplicate", onClick: handlers.onDuplicate, shortcut: keyboardShortcuts.duplicate, enableKeyboardShortcuts: enableKeyboardShortcuts })), jsxRuntime.jsx(ContextMenuButton, { label: "Delete", onClick: handlers.onDelete, shortcut: keyboardShortcuts.delete, enableKeyboardShortcuts: enableKeyboardShortcuts })] }));
|
|
4508
|
+
}
|
|
4509
|
+
|
|
4510
|
+
function KeyboardShortcutToast({ message, duration = 1000, onClose, }) {
|
|
4511
|
+
const [isVisible, setIsVisible] = React.useState(true);
|
|
4512
|
+
const onCloseRef = React.useRef(onClose);
|
|
4513
|
+
const fadeOutTimerRef = React.useRef(null);
|
|
4514
|
+
// Keep onClose ref up to date
|
|
4515
|
+
React.useEffect(() => {
|
|
4516
|
+
onCloseRef.current = onClose;
|
|
4517
|
+
}, [onClose]);
|
|
4518
|
+
React.useEffect(() => {
|
|
4519
|
+
const timer = setTimeout(() => {
|
|
4520
|
+
setIsVisible(false);
|
|
4521
|
+
// Wait for fade-out animation before calling onClose
|
|
4522
|
+
fadeOutTimerRef.current = setTimeout(() => {
|
|
4523
|
+
onCloseRef.current();
|
|
4524
|
+
}, 300);
|
|
4525
|
+
}, duration);
|
|
4526
|
+
return () => {
|
|
4527
|
+
clearTimeout(timer);
|
|
4528
|
+
if (fadeOutTimerRef.current) {
|
|
4529
|
+
clearTimeout(fadeOutTimerRef.current);
|
|
4530
|
+
}
|
|
4531
|
+
};
|
|
4532
|
+
}, [duration]);
|
|
4533
|
+
return (jsxRuntime.jsx("div", { className: `fixed top-4 left-1/2 -translate-x-1/2 z-[2000] pointer-events-none transition-opacity duration-300 ${isVisible ? "opacity-100" : "opacity-0"}`, children: jsxRuntime.jsx("div", { className: "bg-white border border-gray-300 rounded-lg shadow-lg px-2 py-1 text-sm text-gray-700 font-medium whitespace-nowrap", children: message }) }));
|
|
4534
|
+
}
|
|
4535
|
+
// Hook to manage toast state
|
|
4536
|
+
function useKeyboardShortcutToast() {
|
|
4537
|
+
const [toast, setToast] = React.useState(null);
|
|
4538
|
+
const showToast = (message) => {
|
|
4539
|
+
const id = Date.now();
|
|
4540
|
+
setToast({ message, id });
|
|
4541
|
+
};
|
|
4542
|
+
const hideToast = () => {
|
|
4543
|
+
setToast(null);
|
|
4544
|
+
};
|
|
4545
|
+
return { toast, showToast, hideToast };
|
|
4385
4546
|
}
|
|
4386
4547
|
|
|
4387
4548
|
const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, getDefaultNodeSize }, ref) => {
|
|
@@ -4426,7 +4587,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4426
4587
|
inputConnected: n.data.inputConnected,
|
|
4427
4588
|
},
|
|
4428
4589
|
});
|
|
4429
|
-
return isEqual(pick(a), pick(b));
|
|
4590
|
+
return lod.isEqual(pick(a), pick(b));
|
|
4430
4591
|
};
|
|
4431
4592
|
const isSameEdge = (a, b) => {
|
|
4432
4593
|
const pick = (e) => ({
|
|
@@ -4440,7 +4601,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4440
4601
|
label: e.label,
|
|
4441
4602
|
type: e.type,
|
|
4442
4603
|
});
|
|
4443
|
-
return isEqual(pick(a), pick(b));
|
|
4604
|
+
return lod.isEqual(pick(a), pick(b));
|
|
4444
4605
|
};
|
|
4445
4606
|
// Expose imperative API
|
|
4446
4607
|
const rfInstanceRef = React.useRef(null);
|
|
@@ -4756,7 +4917,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4756
4917
|
return;
|
|
4757
4918
|
wb.pasteCopiedData(data, position, { commit: true, reason: "paste" });
|
|
4758
4919
|
onCloseMenu();
|
|
4759
|
-
}, runner, () => storage.get(), () => storage.set(null), historyState);
|
|
4920
|
+
}, runner, () => storage.get(), () => storage.set(null), historyState, wb);
|
|
4760
4921
|
if (overrides?.getDefaultContextMenuHandlers) {
|
|
4761
4922
|
return overrides.getDefaultContextMenuHandlers(wb, baseHandlers);
|
|
4762
4923
|
}
|
|
@@ -4821,9 +4982,13 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4821
4982
|
redo: "⌘/Ctrl + Shift + Z",
|
|
4822
4983
|
copy: "⌘/Ctrl + C",
|
|
4823
4984
|
paste: "⌘/Ctrl + V",
|
|
4824
|
-
duplicate: "⌘/Ctrl +
|
|
4985
|
+
duplicate: "⌘/Ctrl + E",
|
|
4986
|
+
duplicateWithEdges: "⌘/Ctrl + Shift + E",
|
|
4987
|
+
selectAll: "⌘/Ctrl + A",
|
|
4825
4988
|
delete: "Delete",
|
|
4826
4989
|
};
|
|
4990
|
+
// Toast notification for keyboard shortcuts
|
|
4991
|
+
const { toast, showToast, hideToast } = useKeyboardShortcutToast();
|
|
4827
4992
|
// Keyboard shortcut handler
|
|
4828
4993
|
React.useEffect(() => {
|
|
4829
4994
|
if (!enableKeyboardShortcuts)
|
|
@@ -4849,6 +5014,8 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4849
5014
|
defaultContextMenuHandlers.onUndo &&
|
|
4850
5015
|
defaultContextMenuHandlers.canUndo) {
|
|
4851
5016
|
if (defaultContextMenuHandlers.canUndo) {
|
|
5017
|
+
const modKeyLabel = isMac ? "⌘" : "Ctrl";
|
|
5018
|
+
showToast(`Undo (${modKeyLabel} + Z)`);
|
|
4852
5019
|
defaultContextMenuHandlers.onUndo();
|
|
4853
5020
|
}
|
|
4854
5021
|
}
|
|
@@ -4862,6 +5029,8 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4862
5029
|
defaultContextMenuHandlers.onRedo &&
|
|
4863
5030
|
defaultContextMenuHandlers.canRedo) {
|
|
4864
5031
|
if (defaultContextMenuHandlers.canRedo) {
|
|
5032
|
+
const modKeyLabel = isMac ? "⌘" : "Ctrl";
|
|
5033
|
+
showToast(`Redo (${modKeyLabel} + Shift + Z)`);
|
|
4865
5034
|
defaultContextMenuHandlers.onRedo();
|
|
4866
5035
|
}
|
|
4867
5036
|
}
|
|
@@ -4872,6 +5041,8 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4872
5041
|
const selection = wb.getSelection();
|
|
4873
5042
|
if (selection.nodes.length > 0 || selection.edges.length > 0) {
|
|
4874
5043
|
e.preventDefault();
|
|
5044
|
+
const modKeyLabel = isMac ? "⌘" : "Ctrl";
|
|
5045
|
+
showToast(`Copy (${modKeyLabel} + C)`);
|
|
4875
5046
|
// If single node selected, use node context menu handler; otherwise use selection handler
|
|
4876
5047
|
if (selection.nodes.length === 1 && nodeContextMenuHandlers?.onCopy) {
|
|
4877
5048
|
nodeContextMenuHandlers.onCopy();
|
|
@@ -4882,14 +5053,37 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4882
5053
|
}
|
|
4883
5054
|
return;
|
|
4884
5055
|
}
|
|
4885
|
-
// Duplicate: Cmd/Ctrl +
|
|
4886
|
-
if (modKey && key === "
|
|
5056
|
+
// Duplicate: Cmd/Ctrl + E
|
|
5057
|
+
if (modKey && key === "e" && !e.shiftKey && !e.altKey) {
|
|
4887
5058
|
const selection = wb.getSelection();
|
|
4888
5059
|
if (selection.nodes.length === 1 &&
|
|
4889
5060
|
nodeContextMenuHandlers?.onDuplicate) {
|
|
5061
|
+
// Single node selected - use node context menu handler
|
|
4890
5062
|
e.preventDefault();
|
|
5063
|
+
const modKeyLabel = isMac ? "⌘" : "Ctrl";
|
|
5064
|
+
showToast(`Duplicate (${modKeyLabel} + E)`);
|
|
4891
5065
|
nodeContextMenuHandlers.onDuplicate();
|
|
4892
5066
|
}
|
|
5067
|
+
else if (selection.nodes.length > 1 &&
|
|
5068
|
+
selectionContextMenuHandlers.onDuplicate) {
|
|
5069
|
+
// Multiple nodes selected - use selection context menu handler
|
|
5070
|
+
e.preventDefault();
|
|
5071
|
+
const modKeyLabel = isMac ? "⌘" : "Ctrl";
|
|
5072
|
+
showToast(`Duplicate (${modKeyLabel} + E)`);
|
|
5073
|
+
selectionContextMenuHandlers.onDuplicate();
|
|
5074
|
+
}
|
|
5075
|
+
return;
|
|
5076
|
+
}
|
|
5077
|
+
// Duplicate with edges: Cmd/Ctrl + Shift + E
|
|
5078
|
+
if (modKey && key === "e" && e.shiftKey && !e.altKey) {
|
|
5079
|
+
const selection = wb.getSelection();
|
|
5080
|
+
if (selection.nodes.length === 1 &&
|
|
5081
|
+
nodeContextMenuHandlers?.onDuplicateWithEdges) {
|
|
5082
|
+
e.preventDefault();
|
|
5083
|
+
const modKeyLabel = isMac ? "⌘" : "Ctrl";
|
|
5084
|
+
showToast(`Duplicate with edges (${modKeyLabel} + Shift + E)`);
|
|
5085
|
+
nodeContextMenuHandlers.onDuplicateWithEdges();
|
|
5086
|
+
}
|
|
4893
5087
|
return;
|
|
4894
5088
|
}
|
|
4895
5089
|
// Paste: Cmd/Ctrl + V
|
|
@@ -4900,6 +5094,8 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4900
5094
|
defaultContextMenuHandlers.hasPasteData() &&
|
|
4901
5095
|
"onPaste" in defaultContextMenuHandlers &&
|
|
4902
5096
|
defaultContextMenuHandlers.onPaste) {
|
|
5097
|
+
const modKeyLabel = isMac ? "⌘" : "Ctrl";
|
|
5098
|
+
showToast(`Paste (${modKeyLabel} + V)`);
|
|
4903
5099
|
const center = rfInstanceRef.current?.screenToFlowPosition({
|
|
4904
5100
|
x: window.innerWidth / 2,
|
|
4905
5101
|
y: window.innerHeight / 2,
|
|
@@ -4908,6 +5104,16 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4908
5104
|
}
|
|
4909
5105
|
return;
|
|
4910
5106
|
}
|
|
5107
|
+
// Select All: Cmd/Ctrl + A
|
|
5108
|
+
if (modKey && key === "a" && !e.shiftKey && !e.altKey) {
|
|
5109
|
+
e.preventDefault();
|
|
5110
|
+
if (defaultContextMenuHandlers.onSelectAll) {
|
|
5111
|
+
const modKeyLabel = isMac ? "⌘" : "Ctrl";
|
|
5112
|
+
showToast(`Select All (${modKeyLabel} + A)`);
|
|
5113
|
+
defaultContextMenuHandlers.onSelectAll();
|
|
5114
|
+
}
|
|
5115
|
+
return;
|
|
5116
|
+
}
|
|
4911
5117
|
// Note: Delete/Backspace is handled by ReactFlow's deleteKeyCode prop
|
|
4912
5118
|
// which triggers onNodesDelete/onEdgesDelete, so we don't need to handle it here
|
|
4913
5119
|
};
|
|
@@ -4923,6 +5129,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4923
5129
|
selectionContextMenuHandlers,
|
|
4924
5130
|
nodeContextMenuHandlers,
|
|
4925
5131
|
rfInstanceRef,
|
|
5132
|
+
showToast,
|
|
4926
5133
|
]);
|
|
4927
5134
|
// Get custom renderers from UI extension registry (reactive to uiVersion changes)
|
|
4928
5135
|
const { BackgroundRenderer, MinimapRenderer, ControlsRenderer, DefaultContextMenuRenderer, NodeContextMenuRenderer, connectionLineRenderer, } = React.useMemo(() => {
|
|
@@ -4938,7 +5145,8 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4938
5145
|
const onMoveEnd = React.useCallback(() => {
|
|
4939
5146
|
if (rfInstanceRef.current) {
|
|
4940
5147
|
const viewport = rfInstanceRef.current.getViewport();
|
|
4941
|
-
|
|
5148
|
+
const viewportData = lod.pick(viewport, ["x", "y", "zoom"]);
|
|
5149
|
+
wb.setViewport(viewportData);
|
|
4942
5150
|
}
|
|
4943
5151
|
}, [wb]);
|
|
4944
5152
|
const viewportRef = React.useRef(null);
|
|
@@ -4959,24 +5167,24 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
4959
5167
|
});
|
|
4960
5168
|
}
|
|
4961
5169
|
});
|
|
4962
|
-
return (jsxRuntime.
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
? { enableKeyboardShortcuts, keyboardShortcuts }
|
|
4975
|
-
: {}) })) : (jsxRuntime.jsx(DefaultContextMenu, { open: menuOpen, clientPos: menuPos, handlers: defaultContextMenuHandlers, registry: registry, nodeIds: nodeIds, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })), !!nodeAtMenu &&
|
|
4976
|
-
nodeContextMenuHandlers &&
|
|
4977
|
-
(NodeContextMenuRenderer ? (jsxRuntime.jsx(NodeContextMenuRenderer, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, handlers: nodeContextMenuHandlers, canRunPull: canRunPull, bakeableOutputs: bakeableOutputs, ...(enableKeyboardShortcuts !== false
|
|
5170
|
+
return (jsxRuntime.jsxs("div", { className: "w-full h-full", onContextMenu: onContextMenu, children: [jsxRuntime.jsx(react.ReactFlowProvider, { children: jsxRuntime.jsxs(react.ReactFlow, { nodes: throttled.nodes, edges: throttled.edges, nodeTypes: nodeTypes, connectionLineComponent: connectionLineRenderer, selectionOnDrag: true, onInit: (inst) => {
|
|
5171
|
+
rfInstanceRef.current = inst;
|
|
5172
|
+
const savedViewport = wb.getViewport();
|
|
5173
|
+
if (savedViewport) {
|
|
5174
|
+
viewportRef.current = savedViewport;
|
|
5175
|
+
inst.setViewport({
|
|
5176
|
+
x: savedViewport.x,
|
|
5177
|
+
y: savedViewport.y,
|
|
5178
|
+
zoom: savedViewport.zoom,
|
|
5179
|
+
});
|
|
5180
|
+
}
|
|
5181
|
+
}, onConnect: onConnect, onEdgesChange: onEdgesChange, onEdgesDelete: onEdgesDelete, onNodesDelete: onNodesDelete, onNodesChange: onNodesChange, onMoveEnd: onMoveEnd, deleteKeyCode: ["Backspace", "Delete"], proOptions: { hideAttribution: true }, noDragClassName: "wb-nodrag", noWheelClassName: "wb-nowheel", noPanClassName: "wb-nopan", fitView: true, children: [BackgroundRenderer ? (jsxRuntime.jsx(BackgroundRenderer, {})) : (jsxRuntime.jsx(react.Background, { id: "workbench-canvas-background", variant: react.BackgroundVariant.Dots, gap: 12, size: 1 })), MinimapRenderer ? jsxRuntime.jsx(MinimapRenderer, {}) : jsxRuntime.jsx(react.MiniMap, {}), ControlsRenderer ? jsxRuntime.jsx(ControlsRenderer, {}) : jsxRuntime.jsx(react.Controls, {}), DefaultContextMenuRenderer ? (jsxRuntime.jsx(DefaultContextMenuRenderer, { open: menuOpen, clientPos: menuPos, handlers: defaultContextMenuHandlers, registry: registry, nodeIds: nodeIds, ...(enableKeyboardShortcuts !== false
|
|
4978
5182
|
? { enableKeyboardShortcuts, keyboardShortcuts }
|
|
4979
|
-
: {}) })) : (jsxRuntime.jsx(
|
|
5183
|
+
: {}) })) : (jsxRuntime.jsx(DefaultContextMenu, { open: menuOpen, clientPos: menuPos, handlers: defaultContextMenuHandlers, registry: registry, nodeIds: nodeIds, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })), !!nodeAtMenu &&
|
|
5184
|
+
nodeContextMenuHandlers &&
|
|
5185
|
+
(NodeContextMenuRenderer ? (jsxRuntime.jsx(NodeContextMenuRenderer, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, handlers: nodeContextMenuHandlers, canRunPull: canRunPull, bakeableOutputs: bakeableOutputs, ...(enableKeyboardShortcuts !== false
|
|
5186
|
+
? { enableKeyboardShortcuts, keyboardShortcuts }
|
|
5187
|
+
: {}) })) : (jsxRuntime.jsx(NodeContextMenu, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, handlers: nodeContextMenuHandlers, canRunPull: canRunPull, bakeableOutputs: bakeableOutputs, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts }))), selectionMenuOpen && selectionMenuPos && (jsxRuntime.jsx(SelectionContextMenu, { open: selectionMenuOpen, clientPos: selectionMenuPos, handlers: selectionContextMenuHandlers, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts }))] }) }), toast && (jsxRuntime.jsx(KeyboardShortcutToast, { message: toast.message, onClose: hideToast }, toast.id))] }));
|
|
4980
5188
|
});
|
|
4981
5189
|
|
|
4982
5190
|
function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, example, onExampleChange, engine, onEngineChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, overrides, onInit, onChange, }) {
|
|
@@ -5539,6 +5747,7 @@ exports.createNodeCopyHandler = createNodeCopyHandler;
|
|
|
5539
5747
|
exports.createSelectionContextMenuHandlers = createSelectionContextMenuHandlers;
|
|
5540
5748
|
exports.download = download;
|
|
5541
5749
|
exports.estimateNodeSize = estimateNodeSize;
|
|
5750
|
+
exports.excludeViewportFromUIState = excludeViewportFromUIState;
|
|
5542
5751
|
exports.formatDataUrlAsLabel = formatDataUrlAsLabel;
|
|
5543
5752
|
exports.formatDeclaredTypeSignature = formatDeclaredTypeSignature;
|
|
5544
5753
|
exports.getBakeableOutputs = getBakeableOutputs;
|
|
@@ -5547,6 +5756,7 @@ exports.getHandleBoundsY = getHandleBoundsY;
|
|
|
5547
5756
|
exports.getHandleClassName = getHandleClassName;
|
|
5548
5757
|
exports.getHandleLayoutY = getHandleLayoutY;
|
|
5549
5758
|
exports.getNodeBorderClassNames = getNodeBorderClassNames;
|
|
5759
|
+
exports.isValidViewport = isValidViewport;
|
|
5550
5760
|
exports.layoutNode = layoutNode;
|
|
5551
5761
|
exports.preformatValueForDisplay = preformatValueForDisplay;
|
|
5552
5762
|
exports.prettyHandle = prettyHandle;
|