@bian-womp/spark-workbench 0.3.61 → 0.3.63
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 +15 -217
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/misc/SelectionActiveSync.d.ts +10 -0
- package/lib/cjs/src/misc/SelectionActiveSync.d.ts.map +1 -0
- package/lib/cjs/src/misc/WorkbenchCanvas.d.ts.map +1 -1
- package/lib/esm/index.js +16 -218
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/misc/SelectionActiveSync.d.ts +10 -0
- package/lib/esm/src/misc/SelectionActiveSync.d.ts.map +1 -0
- package/lib/esm/src/misc/WorkbenchCanvas.d.ts.map +1 -1
- package/package.json +4 -4
- package/lib/cjs/src/misc/SelectionBoundOverlay.d.ts +0 -11
- package/lib/cjs/src/misc/SelectionBoundOverlay.d.ts.map +0 -1
- package/lib/esm/src/misc/SelectionBoundOverlay.d.ts +0 -11
- package/lib/esm/src/misc/SelectionBoundOverlay.d.ts.map +0 -1
package/lib/cjs/index.cjs
CHANGED
|
@@ -5890,220 +5890,22 @@ function useKeyboardShortcutToast() {
|
|
|
5890
5890
|
return { toast, showToast, hideToast };
|
|
5891
5891
|
}
|
|
5892
5892
|
|
|
5893
|
-
const
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
const
|
|
5897
|
-
const
|
|
5898
|
-
const
|
|
5899
|
-
const
|
|
5900
|
-
const upListenerRef = React.useRef(null);
|
|
5901
|
-
React.useRef(null);
|
|
5902
|
-
const { wb } = useWorkbenchContext();
|
|
5893
|
+
const selectionActiveSelector = (state) => state.nodesSelectionActive;
|
|
5894
|
+
const selectionDragActiveSelector = (state) => state.userSelectionActive;
|
|
5895
|
+
const SelectionActiveSync = ({ selection }) => {
|
|
5896
|
+
const store = react.useStoreApi();
|
|
5897
|
+
const currentActive = react.useStore(selectionActiveSelector);
|
|
5898
|
+
const draggingSelection = react.useStore(selectionDragActiveSelector);
|
|
5899
|
+
const active = selection.nodes.length > 1;
|
|
5903
5900
|
React.useEffect(() => {
|
|
5904
|
-
if (
|
|
5905
|
-
return;
|
|
5906
|
-
const parent = overlayRef.current.parentElement;
|
|
5907
|
-
if (!parent)
|
|
5908
|
-
return;
|
|
5909
|
-
const updateRect = () => {
|
|
5910
|
-
setParentRect(parent.getBoundingClientRect());
|
|
5911
|
-
};
|
|
5912
|
-
updateRect();
|
|
5913
|
-
const resizeObserver = new ResizeObserver(updateRect);
|
|
5914
|
-
resizeObserver.observe(parent);
|
|
5915
|
-
const scrollHandler = () => updateRect();
|
|
5916
|
-
window.addEventListener("scroll", scrollHandler, true);
|
|
5917
|
-
return () => {
|
|
5918
|
-
resizeObserver.disconnect();
|
|
5919
|
-
window.removeEventListener("scroll", scrollHandler, true);
|
|
5920
|
-
};
|
|
5921
|
-
}, [viewportTick]);
|
|
5922
|
-
const cleanupDragListeners = React.useCallback(() => {
|
|
5923
|
-
if (moveListenerRef.current) {
|
|
5924
|
-
window.removeEventListener("mousemove", moveListenerRef.current);
|
|
5925
|
-
moveListenerRef.current = null;
|
|
5926
|
-
}
|
|
5927
|
-
if (upListenerRef.current) {
|
|
5928
|
-
window.removeEventListener("mouseup", upListenerRef.current);
|
|
5929
|
-
upListenerRef.current = null;
|
|
5930
|
-
}
|
|
5931
|
-
dragStateRef.current = null;
|
|
5932
|
-
setIsDragging(false);
|
|
5933
|
-
}, []);
|
|
5934
|
-
React.useEffect(() => cleanupDragListeners, [cleanupDragListeners]);
|
|
5935
|
-
const handleMouseMove = React.useCallback((e) => {
|
|
5936
|
-
if (!rfInstance || !wb || !parentRect)
|
|
5937
|
-
return;
|
|
5938
|
-
const dragState = dragStateRef.current;
|
|
5939
|
-
if (!dragState)
|
|
5940
|
-
return;
|
|
5941
|
-
e.preventDefault();
|
|
5942
|
-
e.stopPropagation();
|
|
5943
|
-
const current = rfInstance.screenToFlowPosition({
|
|
5944
|
-
x: e.clientX,
|
|
5945
|
-
y: e.clientY,
|
|
5946
|
-
});
|
|
5947
|
-
const dx = current.x - dragState.startFlow.x;
|
|
5948
|
-
const dy = current.y - dragState.startFlow.y;
|
|
5949
|
-
// Update nodes directly via React Flow for immediate visual feedback
|
|
5950
|
-
const nodes = rfInstance.getNodes();
|
|
5951
|
-
const updatedNodes = nodes.map((node) => {
|
|
5952
|
-
if (dragState.initialPositions[node.id]) {
|
|
5953
|
-
const initialPos = dragState.initialPositions[node.id];
|
|
5954
|
-
return {
|
|
5955
|
-
...node,
|
|
5956
|
-
position: {
|
|
5957
|
-
x: initialPos.x + dx,
|
|
5958
|
-
y: initialPos.y + dy,
|
|
5959
|
-
},
|
|
5960
|
-
};
|
|
5961
|
-
}
|
|
5962
|
-
return node;
|
|
5963
|
-
});
|
|
5964
|
-
rfInstance.setNodes(updatedNodes);
|
|
5965
|
-
// Also update workbench state
|
|
5966
|
-
const nextPositions = {};
|
|
5967
|
-
for (const [nodeId, pos] of Object.entries(dragState.initialPositions)) {
|
|
5968
|
-
nextPositions[nodeId] = { x: pos.x + dx, y: pos.y + dy };
|
|
5969
|
-
}
|
|
5970
|
-
if (Object.keys(nextPositions).length) {
|
|
5971
|
-
wb.setPositions(nextPositions, { commit: false });
|
|
5972
|
-
}
|
|
5973
|
-
}, [rfInstance, wb, parentRect]);
|
|
5974
|
-
const handleMouseUp = React.useCallback((e) => {
|
|
5975
|
-
if (!rfInstance || !wb) {
|
|
5976
|
-
cleanupDragListeners();
|
|
5901
|
+
if (draggingSelection)
|
|
5977
5902
|
return;
|
|
5903
|
+
if (currentActive !== active) {
|
|
5904
|
+
console.log("[SelectionActiveSync] setting active selection to", active);
|
|
5905
|
+
store.setState({ nodesSelectionActive: active });
|
|
5978
5906
|
}
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
cleanupDragListeners();
|
|
5982
|
-
return;
|
|
5983
|
-
}
|
|
5984
|
-
e.preventDefault();
|
|
5985
|
-
e.stopPropagation();
|
|
5986
|
-
const current = rfInstance.screenToFlowPosition({
|
|
5987
|
-
x: e.clientX,
|
|
5988
|
-
y: e.clientY,
|
|
5989
|
-
});
|
|
5990
|
-
const dx = current.x - dragState.startFlow.x;
|
|
5991
|
-
const dy = current.y - dragState.startFlow.y;
|
|
5992
|
-
const nextPositions = {};
|
|
5993
|
-
for (const [nodeId, pos] of Object.entries(dragState.initialPositions)) {
|
|
5994
|
-
nextPositions[nodeId] = { x: pos.x + dx, y: pos.y + dy };
|
|
5995
|
-
}
|
|
5996
|
-
if (Object.keys(nextPositions).length) {
|
|
5997
|
-
wb.setPositions(nextPositions, { commit: true });
|
|
5998
|
-
}
|
|
5999
|
-
cleanupDragListeners();
|
|
6000
|
-
}, [cleanupDragListeners, rfInstance, wb]);
|
|
6001
|
-
const handleMouseDown = React.useCallback((e) => {
|
|
6002
|
-
if (e.button !== 0)
|
|
6003
|
-
return;
|
|
6004
|
-
if (!rfInstance || !wb)
|
|
6005
|
-
return;
|
|
6006
|
-
if (selection.nodes.length < 2)
|
|
6007
|
-
return;
|
|
6008
|
-
e.preventDefault();
|
|
6009
|
-
e.stopPropagation();
|
|
6010
|
-
const startFlow = rfInstance.screenToFlowPosition({
|
|
6011
|
-
x: e.clientX,
|
|
6012
|
-
y: e.clientY,
|
|
6013
|
-
});
|
|
6014
|
-
const positions = wb.getPositions();
|
|
6015
|
-
const initialPositions = {};
|
|
6016
|
-
for (const nodeId of selection.nodes) {
|
|
6017
|
-
const pos = positions[nodeId];
|
|
6018
|
-
if (pos) {
|
|
6019
|
-
initialPositions[nodeId] = pos;
|
|
6020
|
-
}
|
|
6021
|
-
}
|
|
6022
|
-
if (!Object.keys(initialPositions).length)
|
|
6023
|
-
return;
|
|
6024
|
-
dragStateRef.current = { startFlow, initialPositions };
|
|
6025
|
-
setIsDragging(true);
|
|
6026
|
-
moveListenerRef.current = handleMouseMove;
|
|
6027
|
-
upListenerRef.current = handleMouseUp;
|
|
6028
|
-
window.addEventListener("mousemove", handleMouseMove, { passive: false });
|
|
6029
|
-
window.addEventListener("mouseup", handleMouseUp, { passive: false });
|
|
6030
|
-
}, [handleMouseMove, handleMouseUp, rfInstance, selection.nodes, wb]);
|
|
6031
|
-
// Continuous bounds update loop
|
|
6032
|
-
React.useEffect(() => {
|
|
6033
|
-
if (typeof document === "undefined" ||
|
|
6034
|
-
!rfInstance ||
|
|
6035
|
-
!parentRect ||
|
|
6036
|
-
selection.nodes.length < 2) {
|
|
6037
|
-
setBounds(null);
|
|
6038
|
-
return;
|
|
6039
|
-
}
|
|
6040
|
-
let animationFrameId = null;
|
|
6041
|
-
let isActive = true;
|
|
6042
|
-
const updateBounds = () => {
|
|
6043
|
-
if (!isActive)
|
|
6044
|
-
return;
|
|
6045
|
-
let calculatedBounds = null;
|
|
6046
|
-
for (const nodeId of selection.nodes) {
|
|
6047
|
-
const el = document.querySelector(`.react-flow__node[data-id="${nodeId}"]`);
|
|
6048
|
-
if (!el)
|
|
6049
|
-
continue;
|
|
6050
|
-
const rect = el.getBoundingClientRect();
|
|
6051
|
-
const relativeLeft = rect.left - parentRect.left;
|
|
6052
|
-
const relativeTop = rect.top - parentRect.top;
|
|
6053
|
-
const relativeRight = rect.right - parentRect.left;
|
|
6054
|
-
const relativeBottom = rect.bottom - parentRect.top;
|
|
6055
|
-
if (!calculatedBounds) {
|
|
6056
|
-
calculatedBounds = {
|
|
6057
|
-
left: relativeLeft,
|
|
6058
|
-
top: relativeTop,
|
|
6059
|
-
right: relativeRight,
|
|
6060
|
-
bottom: relativeBottom,
|
|
6061
|
-
};
|
|
6062
|
-
}
|
|
6063
|
-
else {
|
|
6064
|
-
calculatedBounds.left = Math.min(calculatedBounds.left, relativeLeft);
|
|
6065
|
-
calculatedBounds.top = Math.min(calculatedBounds.top, relativeTop);
|
|
6066
|
-
calculatedBounds.right = Math.max(calculatedBounds.right, relativeRight);
|
|
6067
|
-
calculatedBounds.bottom = Math.max(calculatedBounds.bottom, relativeBottom);
|
|
6068
|
-
}
|
|
6069
|
-
}
|
|
6070
|
-
setBounds(calculatedBounds);
|
|
6071
|
-
// Continue the animation loop
|
|
6072
|
-
if (isActive) {
|
|
6073
|
-
animationFrameId = requestAnimationFrame(updateBounds);
|
|
6074
|
-
}
|
|
6075
|
-
};
|
|
6076
|
-
// Start the animation loop
|
|
6077
|
-
animationFrameId = requestAnimationFrame(updateBounds);
|
|
6078
|
-
return () => {
|
|
6079
|
-
isActive = false;
|
|
6080
|
-
if (animationFrameId !== null) {
|
|
6081
|
-
cancelAnimationFrame(animationFrameId);
|
|
6082
|
-
}
|
|
6083
|
-
};
|
|
6084
|
-
}, [selection.nodes, rfInstance, viewportTick, parentRect]);
|
|
6085
|
-
if (!bounds || selection.nodes.length < 2) {
|
|
6086
|
-
return jsxRuntime.jsx("div", { ref: overlayRef, style: { display: "none" } });
|
|
6087
|
-
}
|
|
6088
|
-
const { left, top, right, bottom } = bounds;
|
|
6089
|
-
const width = right - left;
|
|
6090
|
-
const height = bottom - top;
|
|
6091
|
-
return (jsxRuntime.jsx("div", { ref: overlayRef, onMouseDown: handleMouseDown, style: {
|
|
6092
|
-
position: "absolute",
|
|
6093
|
-
left: `${left}px`,
|
|
6094
|
-
top: `${top}px`,
|
|
6095
|
-
width: `${width}px`,
|
|
6096
|
-
height: `${height}px`,
|
|
6097
|
-
border: isDragging ? "2px solid #0ea5e9" : "1px dashed #0ea5e9",
|
|
6098
|
-
backgroundColor: isDragging
|
|
6099
|
-
? "rgba(14, 165, 233, 0.05)"
|
|
6100
|
-
: "transparent",
|
|
6101
|
-
pointerEvents: "auto",
|
|
6102
|
-
cursor: isDragging ? "grabbing" : "move",
|
|
6103
|
-
zIndex: 4,
|
|
6104
|
-
boxSizing: "border-box",
|
|
6105
|
-
transition: isDragging ? "none" : "border 0.1s ease",
|
|
6106
|
-
} }));
|
|
5907
|
+
}, [active, currentActive, draggingSelection, store]);
|
|
5908
|
+
return null;
|
|
6107
5909
|
};
|
|
6108
5910
|
|
|
6109
5911
|
const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
|
|
@@ -6746,10 +6548,6 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
|
|
|
6746
6548
|
connectionLineRenderer: ui.getConnectionLineRenderer(),
|
|
6747
6549
|
};
|
|
6748
6550
|
}, [ui, uiVersion]);
|
|
6749
|
-
const [selectionOverlayTick, setSelectionOverlayTick] = React.useState(0);
|
|
6750
|
-
const onMove = React.useCallback(() => {
|
|
6751
|
-
setSelectionOverlayTick((t) => t + 1);
|
|
6752
|
-
}, []);
|
|
6753
6551
|
const onMoveEnd = React.useCallback(() => {
|
|
6754
6552
|
if (rfInstanceRef.current) {
|
|
6755
6553
|
const viewport = rfInstanceRef.current.getViewport();
|
|
@@ -6781,11 +6579,11 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
|
|
|
6781
6579
|
if (userOnInit) {
|
|
6782
6580
|
userOnInit(inst);
|
|
6783
6581
|
}
|
|
6784
|
-
}, onConnect: onConnect, onEdgesChange: onEdgesChange, onEdgesDelete: onEdgesDelete, onNodesDelete: onNodesDelete, onNodesChange: onNodesChange,
|
|
6582
|
+
}, 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: [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" &&
|
|
6785
6583
|
(DefaultContextMenuRenderer ? (jsxRuntime.jsx(DefaultContextMenuRenderer, { open: true, clientPos: menuState.menuPos, handlers: defaultContextMenuHandlers, registry: wb.registry, nodeIds: nodeIds, keyboardShortcuts: keyboardShortcuts })) : (jsxRuntime.jsx(DefaultContextMenu, { open: true, clientPos: menuState.menuPos, handlers: defaultContextMenuHandlers, registry: wb.registry, nodeIds: nodeIds, keyboardShortcuts: keyboardShortcuts }))), menuState?.type === "node" &&
|
|
6786
6584
|
nodeContextMenuHandlers &&
|
|
6787
6585
|
(NodeContextMenuRenderer ? (jsxRuntime.jsx(NodeContextMenuRenderer, { open: true, clientPos: menuState.menuPos, nodeId: menuState.nodeId, handlers: nodeContextMenuHandlers, bakeableOutputs: bakeableOutputs, runMode: runMode, wb: wb, keyboardShortcuts: keyboardShortcuts })) : (jsxRuntime.jsx(NodeContextMenu, { open: true, clientPos: menuState.menuPos, nodeId: menuState.nodeId, handlers: nodeContextMenuHandlers, bakeableOutputs: bakeableOutputs, runMode: runMode }))), menuState?.type === "selection" &&
|
|
6788
|
-
(SelectionContextMenuRenderer ? (jsxRuntime.jsx(SelectionContextMenuRenderer, { open: true, clientPos: menuState.menuPos, handlers: selectionContextMenuHandlers, keyboardShortcuts: keyboardShortcuts })) : (jsxRuntime.jsx(SelectionContextMenu, { open: true, clientPos: menuState.menuPos, handlers: selectionContextMenuHandlers, keyboardShortcuts: keyboardShortcuts })))] }), jsxRuntime.jsx(
|
|
6586
|
+
(SelectionContextMenuRenderer ? (jsxRuntime.jsx(SelectionContextMenuRenderer, { open: true, clientPos: menuState.menuPos, handlers: selectionContextMenuHandlers, keyboardShortcuts: keyboardShortcuts })) : (jsxRuntime.jsx(SelectionContextMenu, { open: true, clientPos: menuState.menuPos, handlers: selectionContextMenuHandlers, keyboardShortcuts: keyboardShortcuts })))] }), jsxRuntime.jsx(SelectionActiveSync, { selection: selection })] }), toast && (jsxRuntime.jsx(KeyboardShortcutToast, { message: toast.message, onClose: hideToast }, toast.id))] }));
|
|
6789
6587
|
});
|
|
6790
6588
|
const WorkbenchCanvas = WorkbenchCanvasComponent;
|
|
6791
6589
|
|