@bian-womp/spark-workbench 0.1.18 → 0.1.20
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 +81 -19
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/misc/Inspector.d.ts.map +1 -1
- package/lib/cjs/src/misc/WorkbenchStudio.d.ts +13 -2
- package/lib/cjs/src/misc/WorkbenchStudio.d.ts.map +1 -1
- package/lib/cjs/src/misc/hooks.d.ts.map +1 -1
- package/lib/cjs/src/misc/mapping.d.ts +1 -1
- package/lib/cjs/src/misc/mapping.d.ts.map +1 -1
- package/lib/esm/index.js +82 -20
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/misc/Inspector.d.ts.map +1 -1
- package/lib/esm/src/misc/WorkbenchStudio.d.ts +13 -2
- package/lib/esm/src/misc/WorkbenchStudio.d.ts.map +1 -1
- package/lib/esm/src/misc/hooks.d.ts.map +1 -1
- package/lib/esm/src/misc/mapping.d.ts +1 -1
- package/lib/esm/src/misc/mapping.d.ts.map +1 -1
- package/package.json +4 -4
package/lib/cjs/index.cjs
CHANGED
|
@@ -659,6 +659,14 @@ function useWorkbenchBridge(wb) {
|
|
|
659
659
|
return;
|
|
660
660
|
if (!params.sourceHandle || !params.targetHandle)
|
|
661
661
|
return;
|
|
662
|
+
// Prevent duplicate edges between the same endpoints
|
|
663
|
+
const def = wb.export();
|
|
664
|
+
const exists = def.edges.some((e) => e.source.nodeId === params.source &&
|
|
665
|
+
e.source.handle === params.sourceHandle &&
|
|
666
|
+
e.target.nodeId === params.target &&
|
|
667
|
+
e.target.handle === params.targetHandle);
|
|
668
|
+
if (exists)
|
|
669
|
+
return;
|
|
662
670
|
wb.connect({
|
|
663
671
|
source: { nodeId: params.source, handle: params.sourceHandle },
|
|
664
672
|
target: { nodeId: params.target, handle: params.targetHandle },
|
|
@@ -916,7 +924,9 @@ function toReactFlow(def, positions, registry, opts) {
|
|
|
916
924
|
const nodeHandleMap = {};
|
|
917
925
|
const nodes = def.nodes.map((n) => {
|
|
918
926
|
const desc = registry.nodes.get(n.typeId);
|
|
919
|
-
const inputHandles = Object.entries(desc?.inputs ?? {})
|
|
927
|
+
const inputHandles = Object.entries(desc?.inputs ?? {})
|
|
928
|
+
.filter(([id]) => !sparkGraph.isInputPrivate(desc?.inputs, id))
|
|
929
|
+
.map(([id, v]) => ({ id, typeId: sparkGraph.getInputTypeId(desc?.inputs, id) }));
|
|
920
930
|
const outputHandles = Object.entries(desc?.outputs ?? {}).map(([id, typeId]) => ({ id, typeId: formatDeclaredTypeSignature(typeId) }));
|
|
921
931
|
nodeHandleMap[n.nodeId] = {
|
|
922
932
|
inputs: new Set(inputHandles.map((h) => h.id)),
|
|
@@ -1110,8 +1120,8 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, children, }) {
|
|
|
1110
1120
|
layers.push(layer);
|
|
1111
1121
|
q.splice(0, q.length, ...next);
|
|
1112
1122
|
}
|
|
1113
|
-
const X =
|
|
1114
|
-
const Y =
|
|
1123
|
+
const X = 960;
|
|
1124
|
+
const Y = 480;
|
|
1115
1125
|
const pos = {};
|
|
1116
1126
|
layers.forEach((layer, layerIndex) => {
|
|
1117
1127
|
layer.forEach((id, itemIndex) => {
|
|
@@ -1521,7 +1531,9 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
1521
1531
|
const selectedDesc = selectedNode
|
|
1522
1532
|
? registry.nodes.get(selectedNode.typeId)
|
|
1523
1533
|
: undefined;
|
|
1524
|
-
const inputHandles = Object.
|
|
1534
|
+
const inputHandles = Object.entries(selectedDesc?.inputs ?? {})
|
|
1535
|
+
.filter(([k]) => !sparkGraph.isInputPrivate(selectedDesc?.inputs, k))
|
|
1536
|
+
.map(([k]) => k);
|
|
1525
1537
|
const outputHandles = Object.keys(selectedDesc?.outputs ?? {});
|
|
1526
1538
|
const nodeInputs = selectedNodeId ? inputsMap[selectedNodeId] ?? {} : {};
|
|
1527
1539
|
const nodeOutputs = selectedNodeId ? outputsMap[selectedNodeId] ?? {} : {};
|
|
@@ -1568,7 +1580,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
1568
1580
|
const nextDrafts = { ...drafts };
|
|
1569
1581
|
const nextOriginals = { ...originals };
|
|
1570
1582
|
for (const h of handles) {
|
|
1571
|
-
const typeId = desc?.inputs
|
|
1583
|
+
const typeId = sparkGraph.getInputTypeId(desc?.inputs, h);
|
|
1572
1584
|
const current = nodeInputs[h];
|
|
1573
1585
|
const display = safeToString(typeId, current);
|
|
1574
1586
|
const wasOriginal = originals[h];
|
|
@@ -1588,7 +1600,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
1588
1600
|
const widthClass = debug ? "w-[480px]" : "w-[320px]";
|
|
1589
1601
|
return (jsxRuntime.jsxs("div", { className: `${widthClass} border-l border-gray-300 p-3 flex flex-col h-full min-h-0 overflow-hidden`, children: [jsxRuntime.jsx("div", { className: "font-semibold mb-2", children: "Inspector" }), jsxRuntime.jsx("div", { className: "flex-1 overflow-auto", children: !selectedNode && !selectedEdge ? (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("div", { className: "text-gray-500", children: "Select a node or edge." }), globalValidationIssues && globalValidationIssues.length > 0 && (jsxRuntime.jsxs("div", { className: "mt-2 text-xs bg-red-50 border border-red-200 rounded px-2 py-1", children: [jsxRuntime.jsx("div", { className: "font-semibold mb-1", children: "Validation" }), jsxRuntime.jsx("ul", { className: "list-disc ml-4", children: globalValidationIssues.map((m, i) => (jsxRuntime.jsxs("li", { className: "flex items-center gap-1", children: [jsxRuntime.jsx(IssueBadge, { level: m.level, size: 24, className: "w-6 h-6" }), jsxRuntime.jsx("span", { children: `${m.code}: ${m.message}` })] }, i))) })] }))] })) : selectedEdge ? (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { className: "mb-2", children: [jsxRuntime.jsxs("div", { children: ["Edge: ", selectedEdge.id] }), jsxRuntime.jsxs("div", { children: [selectedEdge.source.nodeId, ".", selectedEdge.source.handle, " \u2192", " ", selectedEdge.target.nodeId, ".", selectedEdge.target.handle] }), jsxRuntime.jsxs("div", { children: ["Type: ", selectedEdge.typeId] })] }), selectedEdgeValidation.length > 0 && (jsxRuntime.jsxs("div", { className: "mt-2 text-xs bg-red-50 border border-red-200 rounded px-2 py-1", children: [jsxRuntime.jsx("div", { className: "font-semibold mb-1", children: "Validation" }), jsxRuntime.jsx("ul", { className: "list-disc ml-4", children: selectedEdgeValidation.map((m, i) => (jsxRuntime.jsxs("li", { className: "flex items-center gap-1", children: [jsxRuntime.jsx(IssueBadge, { level: m.level, size: 24, className: "w-6 h-6" }), jsxRuntime.jsx("span", { children: `${m.code}: ${m.message}` })] }, i))) })] }))] })) : (jsxRuntime.jsxs("div", { children: [selectedNode && (jsxRuntime.jsxs("div", { className: "mb-2", children: [jsxRuntime.jsxs("div", { children: ["Node: ", selectedNode.nodeId] }), jsxRuntime.jsxs("div", { children: ["Type: ", selectedNode.typeId] }), !!selectedNodeStatus?.lastError && (jsxRuntime.jsx("div", { className: "mt-2 text-sm text-red-700 bg-red-50 border border-red-200 rounded px-2 py-1 break-words", children: String(selectedNodeStatus.lastError?.message ??
|
|
1590
1602
|
selectedNodeStatus.lastError) }))] })), jsxRuntime.jsxs("div", { className: "mb-2", children: [jsxRuntime.jsx("div", { className: "font-semibold mb-1", children: "Inputs" }), inputHandles.length === 0 ? (jsxRuntime.jsx("div", { className: "text-gray-500", children: "No inputs" })) : (inputHandles.map((h) => {
|
|
1591
|
-
const typeId = (selectedDesc?.inputs
|
|
1603
|
+
const typeId = sparkGraph.getInputTypeId(selectedDesc?.inputs, h);
|
|
1592
1604
|
const isLinked = def.edges.some((e) => e.target.nodeId === selectedNodeId &&
|
|
1593
1605
|
e.target.handle === h);
|
|
1594
1606
|
const commonProps = {
|
|
@@ -1616,7 +1628,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
1616
1628
|
const title = inIssues
|
|
1617
1629
|
.map((v) => `${v.code}: ${v.message}`)
|
|
1618
1630
|
.join("; ");
|
|
1619
|
-
return (jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [jsxRuntime.jsxs("label", { className: "w-32", children: [h, jsxRuntime.jsx("span", { className: "text-gray-500
|
|
1631
|
+
return (jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [jsxRuntime.jsxs("label", { className: "w-32 flex flex-col", children: [jsxRuntime.jsx("span", { children: h }), jsxRuntime.jsx("span", { className: "text-gray-500 text-[11px]", children: typeId })] }), hasValidation && (jsxRuntime.jsx(IssueBadge, { level: hasErr ? "error" : "warning", size: 24, className: "ml-1 w-6 h-6", title: title })), isEnum ? (jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500 w-full", value: current !== undefined && current !== null
|
|
1620
1632
|
? String(current)
|
|
1621
1633
|
: "", onChange: (e) => {
|
|
1622
1634
|
const val = e.target.value;
|
|
@@ -1948,13 +1960,13 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement }, r
|
|
|
1948
1960
|
return (jsxRuntime.jsx("div", { className: "w-full h-full", onContextMenu: onContextMenu, children: jsxRuntime.jsxs(ReactFlow, { nodes: nodes, edges: edges, nodeTypes: nodeTypes, selectionOnDrag: true, onConnect: onConnect, onEdgesChange: onEdgesChange, onEdgesDelete: onEdgesDelete, onNodesDelete: onNodesDelete, onNodesChange: onNodesChange, onSelectionChange: onSelectionChange, deleteKeyCode: ["Backspace", "Delete"], fitView: true, onInit: (inst) => (rfInstanceRef.current = inst), children: [jsxRuntime.jsx(ReactFlow.Background, {}), jsxRuntime.jsx(ReactFlow.MiniMap, {}), jsxRuntime.jsx(ReactFlow.Controls, {}), jsxRuntime.jsx(DefaultContextMenu, { open: menuOpen, clientPos: menuPos, onAdd: addNodeAt, onClose: () => setMenuOpen(false) }), jsxRuntime.jsx(NodeContextMenu, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, onClose: () => setNodeMenuOpen(false) })] }) }));
|
|
1949
1961
|
});
|
|
1950
1962
|
|
|
1951
|
-
function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, example, onExampleChange, engine, onEngineChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, overrides, }) {
|
|
1963
|
+
function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, example, onExampleChange, engine, onEngineChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, overrides, onInit, onChange, }) {
|
|
1952
1964
|
const { wb, runner, registry, def, selectedNodeId, runAutoLayout } = useWorkbenchContext();
|
|
1953
1965
|
const selectedNode = def.nodes.find((n) => n.nodeId === selectedNodeId);
|
|
1954
1966
|
const selectedDesc = selectedNode
|
|
1955
1967
|
? registry.nodes.get(selectedNode.typeId)
|
|
1956
1968
|
: undefined;
|
|
1957
|
-
const [exampleState, setExampleState] = React.useState(example ?? "
|
|
1969
|
+
const [exampleState, setExampleState] = React.useState(example ?? "");
|
|
1958
1970
|
const defaultExamples = React.useMemo(() => [
|
|
1959
1971
|
{
|
|
1960
1972
|
id: "simple",
|
|
@@ -1997,6 +2009,54 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
1997
2009
|
const lastAutoLaunched = React.useRef(undefined);
|
|
1998
2010
|
const autoLayoutRan = React.useRef(false);
|
|
1999
2011
|
const canvasRef = React.useRef(null);
|
|
2012
|
+
// Expose init callback with setInitialGraph helper
|
|
2013
|
+
const initCalled = React.useRef(false);
|
|
2014
|
+
React.useEffect(() => {
|
|
2015
|
+
if (initCalled.current)
|
|
2016
|
+
return;
|
|
2017
|
+
initCalled.current = true;
|
|
2018
|
+
if (!onInit)
|
|
2019
|
+
return;
|
|
2020
|
+
const setInitialGraph = async (d, inputs) => {
|
|
2021
|
+
await wb.load(d);
|
|
2022
|
+
try {
|
|
2023
|
+
runner.build(wb.export());
|
|
2024
|
+
}
|
|
2025
|
+
catch { }
|
|
2026
|
+
if (inputs) {
|
|
2027
|
+
for (const [nodeId, map] of Object.entries(inputs)) {
|
|
2028
|
+
runner.setInputs(nodeId, map);
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
runAutoLayout();
|
|
2032
|
+
};
|
|
2033
|
+
onInit({ wb, runner, setInitialGraph });
|
|
2034
|
+
}, [onInit, wb, runner, runAutoLayout]);
|
|
2035
|
+
// Expose change callback on graph/value changes
|
|
2036
|
+
React.useEffect(() => {
|
|
2037
|
+
if (!onChange)
|
|
2038
|
+
return;
|
|
2039
|
+
const off1 = wb.on("graphChanged", () => {
|
|
2040
|
+
try {
|
|
2041
|
+
const cur = wb.export();
|
|
2042
|
+
const inputs = runner.getInputs(cur);
|
|
2043
|
+
onChange({ def: cur, inputs });
|
|
2044
|
+
}
|
|
2045
|
+
catch { }
|
|
2046
|
+
});
|
|
2047
|
+
const off2 = runner.on("value", () => {
|
|
2048
|
+
try {
|
|
2049
|
+
const cur = wb.export();
|
|
2050
|
+
const inputs = runner.getInputs(cur);
|
|
2051
|
+
onChange({ def: cur, inputs });
|
|
2052
|
+
}
|
|
2053
|
+
catch { }
|
|
2054
|
+
});
|
|
2055
|
+
return () => {
|
|
2056
|
+
off1();
|
|
2057
|
+
off2();
|
|
2058
|
+
};
|
|
2059
|
+
}, [wb, runner, onChange]);
|
|
2000
2060
|
const applyExample = React.useCallback(async (key) => {
|
|
2001
2061
|
if (runner.isRunning()) {
|
|
2002
2062
|
alert(`Stop engine before switching example.`);
|
|
@@ -2111,7 +2171,9 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
2111
2171
|
}, [setRegistry, wb]);
|
|
2112
2172
|
// Ensure initial example is loaded (and sync when example prop changes)
|
|
2113
2173
|
React.useEffect(() => {
|
|
2114
|
-
|
|
2174
|
+
if (!example)
|
|
2175
|
+
return;
|
|
2176
|
+
applyExample(example);
|
|
2115
2177
|
}, [example, wb]);
|
|
2116
2178
|
React.useEffect(() => {
|
|
2117
2179
|
if (!engine)
|
|
@@ -2182,7 +2244,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
2182
2244
|
break;
|
|
2183
2245
|
}
|
|
2184
2246
|
case "base.bool": {
|
|
2185
|
-
value =
|
|
2247
|
+
value = raw === "true" || raw === "1" ? true : false;
|
|
2186
2248
|
break;
|
|
2187
2249
|
}
|
|
2188
2250
|
case "base.string": {
|
|
@@ -2319,14 +2381,14 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
2319
2381
|
return overrides.toElement(baseToElement, { registry });
|
|
2320
2382
|
return baseToElement;
|
|
2321
2383
|
}, [overrides, baseToElement, registry]);
|
|
2322
|
-
return (jsxRuntime.jsxs("div", { className: "w-full h-screen flex flex-col", children: [jsxRuntime.jsxs("div", { className: "p-2 border-b border-gray-300 flex gap-2 items-center", children: [runner.isRunning() ? (jsxRuntime.jsxs("span", { className: "ml-2 text-sm text-green-700", children: ["Running: ", runner.getRunningEngine()] })) : (jsxRuntime.jsx("span", { className: "ml-2 text-sm text-gray-500", children: "Stopped" })), jsxRuntime.jsx("label", { className: "ml-2 text-sm", children: "Example:" }), jsxRuntime.
|
|
2384
|
+
return (jsxRuntime.jsxs("div", { className: "w-full h-screen flex flex-col", children: [jsxRuntime.jsxs("div", { className: "p-2 border-b border-gray-300 flex gap-2 items-center", children: [runner.isRunning() ? (jsxRuntime.jsxs("span", { className: "ml-2 text-sm text-green-700", children: ["Running: ", runner.getRunningEngine()] })) : (jsxRuntime.jsx("span", { className: "ml-2 text-sm text-gray-500", children: "Stopped" })), jsxRuntime.jsx("label", { className: "ml-2 text-sm", children: "Example:" }), jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: exampleState, onChange: (e) => applyExample(e.target.value), disabled: runner.isRunning(), title: runner.isRunning()
|
|
2323
2385
|
? "Stop engine before switching example"
|
|
2324
|
-
: undefined, children: examples.map((ex) => (jsxRuntime.jsx("option", { value: ex.id, children: ex.label }, ex.id))) }), jsxRuntime.jsx("label", { className: "ml-2 text-sm", children: "Backend:" }), jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: backendKind, onChange: (e) => onBackendKindChange(e.target.value), disabled: runner.isRunning(), title: runner.isRunning()
|
|
2386
|
+
: undefined, children: [jsxRuntime.jsx("option", { value: "", children: "Select Example\u2026" }), examples.map((ex) => (jsxRuntime.jsx("option", { value: ex.id, children: ex.label }, ex.id)))] }), jsxRuntime.jsx("label", { className: "ml-2 text-sm", children: "Backend:" }), jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: backendKind, onChange: (e) => onBackendKindChange(e.target.value), disabled: runner.isRunning(), title: runner.isRunning()
|
|
2325
2387
|
? "Stop engine before switching backend"
|
|
2326
2388
|
: undefined, children: [jsxRuntime.jsx("option", { value: "local", children: "Local" }), jsxRuntime.jsx("option", { value: "remote-http", children: "Remote (HTTP)" }), jsxRuntime.jsx("option", { value: "remote-ws", children: "Remote (WebSocket)" })] }), backendKind === "remote-http" && (jsxRuntime.jsx("input", { className: "ml-2 border border-gray-300 rounded px-2 py-1 w-72", placeholder: "http://127.0.0.1:18080", value: httpBaseUrl, onChange: (e) => onHttpBaseUrlChange(e.target.value) })), backendKind === "remote-ws" && (jsxRuntime.jsx("input", { className: "ml-2 border border-gray-300 rounded px-2 py-1 w-72", placeholder: "ws://127.0.0.1:18081", value: wsUrl, onChange: (e) => onWsUrlChange(e.target.value) })), jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: runner.getRunningEngine() ?? engine ?? "", onChange: (e) => {
|
|
2327
2389
|
const kind = e.target.value || undefined;
|
|
2328
2390
|
onEngineChange?.(kind);
|
|
2329
|
-
}, children: [jsxRuntime.jsx("option", { value: "", children: "Select Engine\u2026" }), jsxRuntime.jsx("option", { value: "push", children: "Push" }), jsxRuntime.jsx("option", { value: "batched", children: "Batched" }), jsxRuntime.jsx("option", { value: "pull", children: "Pull" }), jsxRuntime.jsx("option", { value: "hybrid", children: "Hybrid" }), jsxRuntime.jsx("option", { value: "step", children: "Step" })] }), runner.getRunningEngine() === "step" && (jsxRuntime.jsx("button", { className: "ml-2", onClick: () => runner.step(), disabled: !runner.isRunning(), children: "Step" })), runner.getRunningEngine() === "batched" && (jsxRuntime.jsx("button", { className: "ml-2", onClick: () => runner.flush(), disabled: !runner.isRunning(), children: "Flush" })), runner.isRunning() ? (jsxRuntime.jsx("button", { onClick: () => runner.dispose(), disabled: !runner.isRunning(), children: "Stop" })) : (jsxRuntime.jsx("button", { onClick: () => {
|
|
2391
|
+
}, children: [jsxRuntime.jsx("option", { value: "", children: "Select Engine\u2026" }), jsxRuntime.jsx("option", { value: "push", children: "Push" }), jsxRuntime.jsx("option", { value: "batched", children: "Batched" }), jsxRuntime.jsx("option", { value: "pull", children: "Pull" }), jsxRuntime.jsx("option", { value: "hybrid", children: "Hybrid" }), jsxRuntime.jsx("option", { value: "step", children: "Step" })] }), runner.getRunningEngine() === "step" && (jsxRuntime.jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: () => runner.step(), disabled: !runner.isRunning(), children: "Step" })), runner.getRunningEngine() === "batched" && (jsxRuntime.jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: () => runner.flush(), disabled: !runner.isRunning(), children: "Flush" })), runner.isRunning() ? (jsxRuntime.jsx("button", { className: "border border-gray-300 rounded px-2 py-1.5", onClick: () => runner.dispose(), disabled: !runner.isRunning(), children: "Stop" })) : (jsxRuntime.jsx("button", { className: "border border-gray-300 rounded px-2 py-1.5", onClick: () => {
|
|
2330
2392
|
const kind = engine;
|
|
2331
2393
|
if (!kind)
|
|
2332
2394
|
return alert("Select an engine first.");
|
|
@@ -2336,9 +2398,9 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
2336
2398
|
catch (err) {
|
|
2337
2399
|
alert(String(err?.message ?? err));
|
|
2338
2400
|
}
|
|
2339
|
-
}, disabled: !engine, children: "Start" })), jsxRuntime.jsx("button", { onClick: runAutoLayout, children: "Auto Layout" }), jsxRuntime.jsx("button", { className: "ml-2", onClick: () => canvasRef.current?.fitView?.(), title: "Fit View", children: "Fit View" }), jsxRuntime.jsx("button", { className: "ml-2", onClick: downloadGraph, children: "Download Graph" }), jsxRuntime.jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: debug, onChange: (e) => onDebugChange(e.target.checked) }), jsxRuntime.jsx("span", { children: "Debug events" })] }), jsxRuntime.jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: showValues, onChange: (e) => onShowValuesChange(e.target.checked) }), jsxRuntime.jsx("span", { children: "Show values in nodes" })] })] }), jsxRuntime.jsxs("div", { className: "flex flex-1 min-h-0", children: [jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: jsxRuntime.jsx(WorkbenchCanvas, { ref: canvasRef, showValues: showValues, toString: toString, toElement: toElement }) }), jsxRuntime.jsx(Inspector, { setInput: setInput, debug: debug, autoScroll: autoScroll, hideWorkbench: hideWorkbench, onAutoScrollChange: onAutoScrollChange, onHideWorkbenchChange: onHideWorkbenchChange, toString: toString, toElement: toElement })] })] }));
|
|
2401
|
+
}, disabled: !engine, children: "Start" })), jsxRuntime.jsx("button", { className: "border border-gray-300 rounded px-2 py-1.5", onClick: runAutoLayout, children: "Auto Layout" }), jsxRuntime.jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: () => canvasRef.current?.fitView?.(), title: "Fit View", children: "Fit View" }), jsxRuntime.jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: downloadGraph, children: "Download Graph" }), jsxRuntime.jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: debug, onChange: (e) => onDebugChange(e.target.checked) }), jsxRuntime.jsx("span", { children: "Debug events" })] }), jsxRuntime.jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: showValues, onChange: (e) => onShowValuesChange(e.target.checked) }), jsxRuntime.jsx("span", { children: "Show values in nodes" })] })] }), jsxRuntime.jsxs("div", { className: "flex flex-1 min-h-0", children: [jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: jsxRuntime.jsx(WorkbenchCanvas, { ref: canvasRef, showValues: showValues, toString: toString, toElement: toElement }) }), jsxRuntime.jsx(Inspector, { setInput: setInput, debug: debug, autoScroll: autoScroll, hideWorkbench: hideWorkbench, onAutoScrollChange: onAutoScrollChange, onHideWorkbenchChange: onHideWorkbenchChange, toString: toString, toElement: toElement })] })] }));
|
|
2340
2402
|
}
|
|
2341
|
-
function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, autoScroll, onAutoScrollChange, overrides, }) {
|
|
2403
|
+
function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, autoScroll, onAutoScrollChange, overrides, onInit, onChange, }) {
|
|
2342
2404
|
const [registry, setRegistry] = React.useState(sparkGraph.createSimpleGraphRegistry());
|
|
2343
2405
|
const [wb] = React.useState(() => new InMemoryWorkbench({ ui: new DefaultUIExtensionRegistry() }));
|
|
2344
2406
|
const runner = React.useMemo(() => {
|
|
@@ -2352,14 +2414,14 @@ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, bac
|
|
|
2352
2414
|
// Allow external UI registration (e.g., node renderers) with access to wb
|
|
2353
2415
|
React.useEffect(() => {
|
|
2354
2416
|
const baseRegisterUI = (_wb) => { };
|
|
2355
|
-
overrides?.registerUI?.(baseRegisterUI, { wb });
|
|
2417
|
+
overrides?.registerUI?.(baseRegisterUI, { wb, wbRunner: runner });
|
|
2356
2418
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2357
|
-
}, [wb, overrides]);
|
|
2419
|
+
}, [wb, runner, overrides]);
|
|
2358
2420
|
return (jsxRuntime.jsx(WorkbenchProvider, { wb: wb, runner: runner, registry: registry, setRegistry: setRegistry, children: jsxRuntime.jsx(WorkbenchStudioCanvas, { setRegistry: setRegistry, autoScroll: autoScroll, onAutoScrollChange: onAutoScrollChange, example: example, onExampleChange: onExampleChange, engine: engine, onEngineChange: onEngineChange, backendKind: backendKind, onBackendKindChange: (v) => {
|
|
2359
2421
|
if (runner.isRunning())
|
|
2360
2422
|
runner.dispose();
|
|
2361
2423
|
onBackendKindChange(v);
|
|
2362
|
-
}, httpBaseUrl: httpBaseUrl, onHttpBaseUrlChange: onHttpBaseUrlChange, wsUrl: wsUrl, onWsUrlChange: onWsUrlChange, debug: debug, onDebugChange: onDebugChange, showValues: showValues, onShowValuesChange: onShowValuesChange, hideWorkbench: hideWorkbench, onHideWorkbenchChange: onHideWorkbenchChange, overrides: overrides }) }));
|
|
2424
|
+
}, httpBaseUrl: httpBaseUrl, onHttpBaseUrlChange: onHttpBaseUrlChange, wsUrl: wsUrl, onWsUrlChange: onWsUrlChange, debug: debug, onDebugChange: onDebugChange, showValues: showValues, onShowValuesChange: onShowValuesChange, hideWorkbench: hideWorkbench, onHideWorkbenchChange: onHideWorkbenchChange, overrides: overrides, onInit: onInit, onChange: onChange }) }));
|
|
2363
2425
|
}
|
|
2364
2426
|
|
|
2365
2427
|
exports.AbstractWorkbench = AbstractWorkbench;
|