@bian-womp/spark-workbench 0.3.20 → 0.3.22

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
@@ -1215,7 +1215,7 @@ class LocalGraphRunner extends AbstractGraphRunner {
1215
1215
  this.engine.on("error", (e) => this.emit("error", e));
1216
1216
  this.engine.on("invalidate", (e) => this.emit("invalidate", e));
1217
1217
  this.engine.on("stats", (e) => this.emit("stats", e));
1218
- this.engine.launch(opts?.invalidate);
1218
+ this.engine.launch(opts?.invalidate, opts?.runMode, opts?.startPaused);
1219
1219
  const runMode = opts?.runMode ?? "manual";
1220
1220
  this.emit("status", { running: true, runMode });
1221
1221
  for (const [nodeId, map] of Object.entries(this.stagedInputs)) {
@@ -1363,6 +1363,26 @@ class LocalGraphRunner extends AbstractGraphRunner {
1363
1363
  await this.setExtData(payload.extData);
1364
1364
  }
1365
1365
  }
1366
+ async convertSnapshot(converterConfig, options) {
1367
+ const snapshot = await this.snapshotFull();
1368
+ const converter = sparkGraph.buildValueConverter(converterConfig);
1369
+ const converted = sparkGraph.convertSnapshot(snapshot, converter);
1370
+ await this.applySnapshotFull(converted, {
1371
+ skipBuild: true,
1372
+ dry: options?.dry,
1373
+ });
1374
+ return converted;
1375
+ }
1376
+ async pause() {
1377
+ if (!this.runtime)
1378
+ return;
1379
+ this.runtime.pause();
1380
+ }
1381
+ async resume() {
1382
+ if (!this.runtime)
1383
+ return;
1384
+ this.runtime.resume();
1385
+ }
1366
1386
  hydrate(snapshot, opts) {
1367
1387
  // Hydrate via runtime for exact restore (this emits events on runtime emitter)
1368
1388
  this.runtime?.hydrate({
@@ -1961,6 +1981,23 @@ class RemoteGraphRunner extends AbstractGraphRunner {
1961
1981
  skipBuild: options?.skipBuild,
1962
1982
  });
1963
1983
  }
1984
+ async convertSnapshot(converterConfig, options) {
1985
+ const client = await this.ensureClient();
1986
+ const converted = await client.api.convertSnapshot(converterConfig, {
1987
+ dry: options?.dry,
1988
+ });
1989
+ // Hydrate local cache with converted values
1990
+ this.hydrateValueCache(converted, { dry: options?.dry });
1991
+ return converted;
1992
+ }
1993
+ async pause() {
1994
+ const client = await this.ensureClient();
1995
+ await client.api.pause();
1996
+ }
1997
+ async resume() {
1998
+ const client = await this.ensureClient();
1999
+ await client.api.resume();
2000
+ }
1964
2001
  /**
1965
2002
  * Hydrates the local valueCache from a snapshot and emits value events.
1966
2003
  * This ensures the UI can display inputs/outputs immediately without waiting
@@ -5758,10 +5795,32 @@ function useKeyboardShortcutToast() {
5758
5795
  return { toast, showToast, hideToast };
5759
5796
  }
5760
5797
 
5761
- const SelectionBoundOverlay = ({ selection, rfInstance }) => {
5798
+ const SelectionBoundOverlay = ({ selection, rfInstance, viewportTick }) => {
5799
+ const overlayRef = React.useRef(null);
5800
+ const [parentRect, setParentRect] = React.useState(null);
5801
+ React.useEffect(() => {
5802
+ if (!overlayRef.current)
5803
+ return;
5804
+ const parent = overlayRef.current.parentElement;
5805
+ if (!parent)
5806
+ return;
5807
+ const updateRect = () => {
5808
+ setParentRect(parent.getBoundingClientRect());
5809
+ };
5810
+ updateRect();
5811
+ const resizeObserver = new ResizeObserver(updateRect);
5812
+ resizeObserver.observe(parent);
5813
+ const scrollHandler = () => updateRect();
5814
+ window.addEventListener("scroll", scrollHandler, true);
5815
+ return () => {
5816
+ resizeObserver.disconnect();
5817
+ window.removeEventListener("scroll", scrollHandler, true);
5818
+ };
5819
+ }, [viewportTick]);
5762
5820
  const selectionBounds = React.useMemo(() => {
5763
5821
  if (typeof document === "undefined" ||
5764
5822
  !rfInstance ||
5823
+ !parentRect ||
5765
5824
  selection.nodes.length < 2) {
5766
5825
  return null;
5767
5826
  }
@@ -5771,31 +5830,35 @@ const SelectionBoundOverlay = ({ selection, rfInstance }) => {
5771
5830
  if (!el)
5772
5831
  continue;
5773
5832
  const rect = el.getBoundingClientRect();
5833
+ const relativeLeft = rect.left - parentRect.left;
5834
+ const relativeTop = rect.top - parentRect.top;
5835
+ const relativeRight = rect.right - parentRect.left;
5836
+ const relativeBottom = rect.bottom - parentRect.top;
5774
5837
  if (!bounds) {
5775
5838
  bounds = {
5776
- left: rect.left,
5777
- top: rect.top,
5778
- right: rect.right,
5779
- bottom: rect.bottom,
5839
+ left: relativeLeft,
5840
+ top: relativeTop,
5841
+ right: relativeRight,
5842
+ bottom: relativeBottom,
5780
5843
  };
5781
5844
  }
5782
5845
  else {
5783
- bounds.left = Math.min(bounds.left, rect.left);
5784
- bounds.top = Math.min(bounds.top, rect.top);
5785
- bounds.right = Math.max(bounds.right, rect.right);
5786
- bounds.bottom = Math.max(bounds.bottom, rect.bottom);
5846
+ bounds.left = Math.min(bounds.left, relativeLeft);
5847
+ bounds.top = Math.min(bounds.top, relativeTop);
5848
+ bounds.right = Math.max(bounds.right, relativeRight);
5849
+ bounds.bottom = Math.max(bounds.bottom, relativeBottom);
5787
5850
  }
5788
5851
  }
5789
5852
  return bounds;
5790
- }, [selection.nodes, rfInstance]);
5853
+ }, [selection.nodes, rfInstance, viewportTick, parentRect]);
5791
5854
  if (!selectionBounds || selection.nodes.length < 2) {
5792
- return null;
5855
+ return jsxRuntime.jsx("div", { ref: overlayRef, style: { display: "none" } });
5793
5856
  }
5794
5857
  const { left, top, right, bottom } = selectionBounds;
5795
5858
  const width = right - left;
5796
5859
  const height = bottom - top;
5797
- return (jsxRuntime.jsx("div", { style: {
5798
- position: "fixed",
5860
+ return (jsxRuntime.jsx("div", { ref: overlayRef, style: {
5861
+ position: "absolute",
5799
5862
  left: `${left}px`,
5800
5863
  top: `${top}px`,
5801
5864
  width: `${width}px`,
@@ -6432,6 +6495,10 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6432
6495
  connectionLineRenderer: ui.getConnectionLineRenderer(),
6433
6496
  };
6434
6497
  }, [ui, uiVersion]);
6498
+ const [selectionOverlayTick, setSelectionOverlayTick] = React.useState(0);
6499
+ const onMove = React.useCallback(() => {
6500
+ setSelectionOverlayTick((t) => t + 1);
6501
+ }, []);
6435
6502
  const onMoveEnd = React.useCallback(() => {
6436
6503
  if (rfInstanceRef.current) {
6437
6504
  const viewport = rfInstanceRef.current.getViewport();
@@ -6454,7 +6521,7 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6454
6521
  return () => off();
6455
6522
  }, [wb]);
6456
6523
  const { onInit: userOnInit, ...restReactFlowProps } = reactFlowProps || {};
6457
- return (jsxRuntime.jsxs("div", { className: "w-full h-full", onContextMenu: onContextMenu, children: [jsxRuntime.jsxs(react.ReactFlowProvider, { children: [jsxRuntime.jsxs(react.ReactFlow, { ...restReactFlowProps, nodes: throttled.nodes, edges: throttled.edges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, connectionLineComponent: connectionLineRenderer, selectionOnDrag: true, onInit: (inst) => {
6524
+ return (jsxRuntime.jsxs("div", { className: "w-full h-full relative overflow-hidden", onContextMenu: onContextMenu, children: [jsxRuntime.jsxs(react.ReactFlowProvider, { children: [jsxRuntime.jsxs(react.ReactFlow, { ...restReactFlowProps, nodes: throttled.nodes, edges: throttled.edges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, connectionLineComponent: connectionLineRenderer, selectionOnDrag: true, onInit: (inst) => {
6458
6525
  rfInstanceRef.current = inst;
6459
6526
  const savedViewport = wb.getViewport();
6460
6527
  if (savedViewport) {
@@ -6463,7 +6530,7 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6463
6530
  if (userOnInit) {
6464
6531
  userOnInit(inst);
6465
6532
  }
6466
- }, 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", 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, {}), menuState?.type === "default" &&
6533
+ }, onConnect: onConnect, onEdgesChange: onEdgesChange, onEdgesDelete: onEdgesDelete, onNodesDelete: onNodesDelete, onNodesChange: onNodesChange, onMove: onMove, onMoveEnd: onMoveEnd, deleteKeyCode: ["Backspace", "Delete"], proOptions: { hideAttribution: true }, noDragClassName: "wb-nodrag", noWheelClassName: "wb-nowheel", noPanClassName: "wb-nopan", 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, {}), menuState?.type === "default" &&
6467
6534
  (DefaultContextMenuRenderer ? (jsxRuntime.jsx(DefaultContextMenuRenderer, { open: true, clientPos: menuState.menuPos, handlers: defaultContextMenuHandlers, registry: wb.registry, nodeIds: nodeIds, ...(enableKeyboardShortcuts !== false
6468
6535
  ? { enableKeyboardShortcuts, keyboardShortcuts }
6469
6536
  : {}) })) : (jsxRuntime.jsx(DefaultContextMenu, { open: true, clientPos: menuState.menuPos, handlers: defaultContextMenuHandlers, registry: wb.registry, nodeIds: nodeIds, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts }))), menuState?.type === "node" &&
@@ -6471,7 +6538,7 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6471
6538
  (NodeContextMenuRenderer ? (jsxRuntime.jsx(NodeContextMenuRenderer, { open: true, clientPos: menuState.menuPos, nodeId: menuState.nodeId, handlers: nodeContextMenuHandlers, bakeableOutputs: bakeableOutputs, runMode: runMode, wb: wb, ...(enableKeyboardShortcuts !== false
6472
6539
  ? { enableKeyboardShortcuts, keyboardShortcuts }
6473
6540
  : {}) })) : (jsxRuntime.jsx(NodeContextMenu, { open: true, clientPos: menuState.menuPos, nodeId: menuState.nodeId, handlers: nodeContextMenuHandlers, bakeableOutputs: bakeableOutputs, runMode: runMode }))), menuState?.type === "selection" &&
6474
- (SelectionContextMenuRenderer ? (jsxRuntime.jsx(SelectionContextMenuRenderer, { open: true, clientPos: menuState.menuPos, handlers: selectionContextMenuHandlers, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })) : (jsxRuntime.jsx(SelectionContextMenu, { open: true, clientPos: menuState.menuPos, handlers: selectionContextMenuHandlers, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })))] }), jsxRuntime.jsx(SelectionBoundOverlay, { selection: selection, rfInstance: rfInstanceRef.current })] }), toast && (jsxRuntime.jsx(KeyboardShortcutToast, { message: toast.message, onClose: hideToast }, toast.id))] }));
6541
+ (SelectionContextMenuRenderer ? (jsxRuntime.jsx(SelectionContextMenuRenderer, { open: true, clientPos: menuState.menuPos, handlers: selectionContextMenuHandlers, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })) : (jsxRuntime.jsx(SelectionContextMenu, { open: true, clientPos: menuState.menuPos, handlers: selectionContextMenuHandlers, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })))] }), jsxRuntime.jsx(SelectionBoundOverlay, { selection: selection, rfInstance: rfInstanceRef.current, viewportTick: selectionOverlayTick })] }), toast && (jsxRuntime.jsx(KeyboardShortcutToast, { message: toast.message, onClose: hideToast }, toast.id))] }));
6475
6542
  });
6476
6543
  const WorkbenchCanvas = WorkbenchCanvasComponent;
6477
6544