@bian-womp/spark-workbench 0.1.30 → 0.2.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/lib/cjs/index.cjs CHANGED
@@ -5,7 +5,7 @@ var sparkRemote = require('@bian-womp/spark-remote');
5
5
  var React = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var react = require('@phosphor-icons/react');
8
- var ReactFlow = require('reactflow');
8
+ var react$1 = require('@xyflow/react');
9
9
  var cx = require('classnames');
10
10
 
11
11
  class DefaultUIExtensionRegistry {
@@ -1814,10 +1814,8 @@ const DefaultNode = React.memo(function DefaultNode({ id, data, selected, isConn
1814
1814
  const vIssues = validation.inputs.filter((v) => v.handle === entry.id);
1815
1815
  const hasAny = vIssues.length > 0;
1816
1816
  const hasErr = vIssues.some((v) => v.level === "error");
1817
- const title = vIssues
1818
- .map((v) => `${v.code}: ${v.message}`)
1819
- .join("; ");
1820
- return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx(ReactFlow.Handle, { id: entry.id, type: "target", position: ReactFlow.Position.Left, isConnectable: isConnectable, className: cx("!w-3 !h-3 !bg-white !dark:bg-stone-900 !border-gray-500 dark:!border-gray-400", hasAny && (hasErr ? "!border-red-500" : "!border-amber-500")), style: { left: -5, top: topFor(i) } }), jsxRuntime.jsxs("div", { className: "absolute left-2 text-[11px] text-gray-700 dark:text-gray-300 pointer-events-none", style: {
1817
+ const title = vIssues.map((v) => `${v.code}: ${v.message}`).join("; ");
1818
+ return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx(react$1.Handle, { id: entry.id, type: "target", position: react$1.Position.Left, isConnectable: isConnectable, className: cx("!w-3 !h-3 !bg-white !dark:bg-stone-900 !border-gray-500 dark:!border-gray-400", hasAny && (hasErr ? "!border-red-500" : "!border-amber-500")), style: { left: -5, top: topFor(i) } }), jsxRuntime.jsxs("div", { className: "absolute left-2 text-[11px] text-gray-700 dark:text-gray-300 pointer-events-none", style: {
1821
1819
  top: topFor(i) - 8,
1822
1820
  right: "50%",
1823
1821
  whiteSpace: "nowrap",
@@ -1828,11 +1826,9 @@ const DefaultNode = React.memo(function DefaultNode({ id, data, selected, isConn
1828
1826
  const vIssues = validation.outputs.filter((v) => v.handle === entry.id);
1829
1827
  const hasAny = vIssues.length > 0;
1830
1828
  const hasErr = vIssues.some((v) => v.level === "error");
1831
- const title = vIssues
1832
- .map((v) => `${v.code}: ${v.message}`)
1833
- .join("; ");
1829
+ const title = vIssues.map((v) => `${v.code}: ${v.message}`).join("; ");
1834
1830
  const resolved = resolveOutputDisplay(outputValues?.[entry.id], entry.typeId);
1835
- return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx(ReactFlow.Handle, { id: entry.id, type: "source", position: ReactFlow.Position.Right, isConnectable: isConnectable, className: cx("!w-3 !h-3 !bg-white !dark:bg-stone-900 !border-gray-500 dark:!border-gray-400 !rounded-none", hasAny && (hasErr ? "!border-red-500" : "!border-amber-500")), style: { right: -5, top: topFor(i) } }), jsxRuntime.jsxs("div", { className: "absolute right-2 text-[11px] text-gray-700 dark:text-gray-300 pointer-events-none", style: {
1831
+ return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx(react$1.Handle, { id: entry.id, type: "source", position: react$1.Position.Right, isConnectable: isConnectable, className: cx("!w-3 !h-3 !bg-white !dark:bg-stone-900 !border-gray-500 dark:!border-gray-400 !rounded-none", hasAny && (hasErr ? "!border-red-500" : "!border-amber-500")), style: { right: -5, top: topFor(i) } }), jsxRuntime.jsxs("div", { className: "absolute right-2 text-[11px] text-gray-700 dark:text-gray-300 pointer-events-none", style: {
1836
1832
  top: topFor(i) - 8,
1837
1833
  textAlign: "right",
1838
1834
  left: "50%",
@@ -1846,7 +1842,7 @@ DefaultNode.displayName = "DefaultNode";
1846
1842
 
1847
1843
  function DefaultContextMenu({ open, clientPos, onAdd, onClose, }) {
1848
1844
  const { registry } = useWorkbenchContext();
1849
- const rf = ReactFlow.useReactFlow();
1845
+ const rf = react$1.useReactFlow();
1850
1846
  const ids = Array.from(registry.nodes.keys());
1851
1847
  const [query, setQuery] = React.useState("");
1852
1848
  const q = query.trim().toLowerCase();
@@ -2053,7 +2049,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement }, r
2053
2049
  selectedNodeIds: new Set(sel.nodes),
2054
2050
  selectedEdgeIds: new Set(sel.edges),
2055
2051
  });
2056
- console.info(nodeTypes, out);
2052
+ // console.info(nodeTypes, out);
2057
2053
  return out;
2058
2054
  }, [
2059
2055
  showValues,
@@ -2095,7 +2091,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement }, r
2095
2091
  const addNodeAt = (typeId, pos) => {
2096
2092
  wb.addNode({ typeId, position: pos });
2097
2093
  };
2098
- 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) })] }) }));
2094
+ return (jsxRuntime.jsx("div", { className: "w-full h-full", onContextMenu: onContextMenu, children: jsxRuntime.jsxs(react$1.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(react$1.Background, {}), jsxRuntime.jsx(react$1.MiniMap, {}), jsxRuntime.jsx(react$1.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) })] }) }));
2099
2095
  });
2100
2096
 
2101
2097
  function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, example, onExampleChange, engine, onEngineChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, overrides, onInit, onChange, }) {
@@ -2172,7 +2168,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
2172
2168
  runAutoLayout();
2173
2169
  };
2174
2170
  onInit({ wb, runner, setInitialGraph });
2175
- }, [onInit, wb, runner, runAutoLayout]);
2171
+ }, [onInit, wb, runner, runAutoLayout, registry, setRegistry]);
2176
2172
  // Expose change callback on graph/value changes
2177
2173
  React.useEffect(() => {
2178
2174
  if (!onChange)
@@ -2327,6 +2323,9 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
2327
2323
  return;
2328
2324
  if (runner.isRunning())
2329
2325
  return;
2326
+ // Only auto-launch for local backend; require explicit Start for remote
2327
+ if (backendKind !== "local")
2328
+ return;
2330
2329
  const d = wb.export();
2331
2330
  if (!d.nodes || d.nodes.length === 0)
2332
2331
  return;
@@ -2339,14 +2338,14 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
2339
2338
  catch {
2340
2339
  // ignore
2341
2340
  }
2342
- }, [engine, runner, wb]);
2341
+ }, [engine, runner, wb, backendKind]);
2343
2342
  // When switching to remote backend, auto-hydrate registry from backend
2344
2343
  React.useEffect(() => {
2345
2344
  if (backendKind === "remote-http" && httpBaseUrl) {
2346
- void hydrateFromBackend("remote-http", httpBaseUrl);
2345
+ hydrateFromBackend("remote-http", httpBaseUrl);
2347
2346
  }
2348
2347
  else if (backendKind === "remote-ws" && wsUrl) {
2349
- void hydrateFromBackend("remote-ws", wsUrl);
2348
+ hydrateFromBackend("remote-ws", wsUrl);
2350
2349
  }
2351
2350
  }, [backendKind, httpBaseUrl, wsUrl, hydrateFromBackend]);
2352
2351
  React.useEffect(() => {
@@ -2535,7 +2534,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
2535
2534
  }
2536
2535
  }, 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, contextPanel: overrides?.contextPanel })] })] }));
2537
2536
  }
2538
- function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, autoScroll, onAutoScrollChange, overrides, onInit, onChange, contextPanel, }) {
2537
+ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, autoScroll, onAutoScrollChange, overrides, onInit, onChange, }) {
2539
2538
  const [registry, setRegistry] = React.useState(sparkGraph.createSimpleGraphRegistry());
2540
2539
  const [wb] = React.useState(() => new InMemoryWorkbench({ ui: new DefaultUIExtensionRegistry() }));
2541
2540
  const runner = React.useMemo(() => {