@bian-womp/spark-workbench 0.3.30 → 0.3.32

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.
Files changed (35) hide show
  1. package/lib/cjs/index.cjs +42 -40
  2. package/lib/cjs/index.cjs.map +1 -1
  3. package/lib/cjs/src/misc/Inspector.d.ts.map +1 -1
  4. package/lib/cjs/src/misc/WorkbenchCanvas.d.ts.map +1 -1
  5. package/lib/cjs/src/misc/context/WorkbenchContext.d.ts +20 -9
  6. package/lib/cjs/src/misc/context/WorkbenchContext.d.ts.map +1 -1
  7. package/lib/cjs/src/misc/context-menu/ContextMenuButton.d.ts +1 -2
  8. package/lib/cjs/src/misc/context-menu/ContextMenuButton.d.ts.map +1 -1
  9. package/lib/cjs/src/misc/context-menu/ContextMenuHandlers.d.ts +0 -5
  10. package/lib/cjs/src/misc/context-menu/ContextMenuHandlers.d.ts.map +1 -1
  11. package/lib/cjs/src/misc/context-menu/ContextMenuHelpers.d.ts.map +1 -1
  12. package/lib/cjs/src/misc/context-menu/DefaultContextMenu.d.ts +1 -1
  13. package/lib/cjs/src/misc/context-menu/DefaultContextMenu.d.ts.map +1 -1
  14. package/lib/cjs/src/misc/context-menu/NodeContextMenu.d.ts +1 -1
  15. package/lib/cjs/src/misc/context-menu/NodeContextMenu.d.ts.map +1 -1
  16. package/lib/cjs/src/misc/context-menu/SelectionContextMenu.d.ts +1 -1
  17. package/lib/cjs/src/misc/context-menu/SelectionContextMenu.d.ts.map +1 -1
  18. package/lib/esm/index.js +43 -41
  19. package/lib/esm/index.js.map +1 -1
  20. package/lib/esm/src/misc/Inspector.d.ts.map +1 -1
  21. package/lib/esm/src/misc/WorkbenchCanvas.d.ts.map +1 -1
  22. package/lib/esm/src/misc/context/WorkbenchContext.d.ts +20 -9
  23. package/lib/esm/src/misc/context/WorkbenchContext.d.ts.map +1 -1
  24. package/lib/esm/src/misc/context-menu/ContextMenuButton.d.ts +1 -2
  25. package/lib/esm/src/misc/context-menu/ContextMenuButton.d.ts.map +1 -1
  26. package/lib/esm/src/misc/context-menu/ContextMenuHandlers.d.ts +0 -5
  27. package/lib/esm/src/misc/context-menu/ContextMenuHandlers.d.ts.map +1 -1
  28. package/lib/esm/src/misc/context-menu/ContextMenuHelpers.d.ts.map +1 -1
  29. package/lib/esm/src/misc/context-menu/DefaultContextMenu.d.ts +1 -1
  30. package/lib/esm/src/misc/context-menu/DefaultContextMenu.d.ts.map +1 -1
  31. package/lib/esm/src/misc/context-menu/NodeContextMenu.d.ts +1 -1
  32. package/lib/esm/src/misc/context-menu/NodeContextMenu.d.ts.map +1 -1
  33. package/lib/esm/src/misc/context-menu/SelectionContextMenu.d.ts +1 -1
  34. package/lib/esm/src/misc/context-menu/SelectionContextMenu.d.ts.map +1 -1
  35. package/package.json +4 -4
package/lib/cjs/index.cjs CHANGED
@@ -5067,13 +5067,6 @@ function createNodeContextMenuHandlers(nodeId, wb, runner, registry, outputsMap,
5067
5067
  onClose();
5068
5068
  },
5069
5069
  onDuplicate: async () => {
5070
- wb.duplicateNode(nodeId, runner, {
5071
- commit: true,
5072
- reason: "duplicate-node",
5073
- });
5074
- onClose();
5075
- },
5076
- onDuplicateWithEdges: async () => {
5077
5070
  wb.duplicateNodeWithEdges(nodeId, runner, {
5078
5071
  commit: true,
5079
5072
  reason: "duplicate-node-with-edges",
@@ -5485,6 +5478,10 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
5485
5478
  selectedNodeStatus.activeRunIds.length > 0 ? (jsxRuntime.jsxs("div", { className: "mt-1", children: [jsxRuntime.jsx("div", { className: "text-[10px] text-blue-600", children: "RunIds:" }), jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1 mt-1", children: selectedNodeStatus.activeRunIds.map((runId, idx) => (jsxRuntime.jsx("span", { className: "text-[10px] px-1.5 py-0.5 bg-blue-100 border border-blue-300 rounded font-mono", children: runId }, idx))) })] })) : (jsxRuntime.jsx("div", { className: "text-[10px] text-blue-600 mt-1", children: "RunIds not available (some runs may have started without runId)" }))] })), !!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 ??
5486
5479
  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) => {
5487
5480
  const typeId = sparkGraph.getInputTypeId(effectiveHandles.inputs, h);
5481
+ const declaredTypes = sparkGraph.getInputDeclaredTypes(effectiveHandles.inputs, h);
5482
+ const typeLabel = Array.isArray(declaredTypes)
5483
+ ? declaredTypes.join(" | ")
5484
+ : typeId ?? "";
5488
5485
  const isLinked = wb.def.edges.some((e) => e.target.nodeId === selectedNodeId &&
5489
5486
  e.target.handle === h);
5490
5487
  const inbound = new Set(wb.def.edges
@@ -5535,7 +5532,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
5535
5532
  const title = inIssues
5536
5533
  .map((v) => `${v.code}: ${v.message}`)
5537
5534
  .join("; ");
5538
- 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: prettyHandle(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("div", { className: "flex items-center gap-1 flex-1", children: [jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500 flex-1 select-text", value: current !== undefined && current !== null
5535
+ 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: prettyHandle(h) }), jsxRuntime.jsx("span", { className: "text-gray-500 text-[11px]", children: typeLabel })] }), hasValidation && (jsxRuntime.jsx(IssueBadge, { level: hasErr ? "error" : "warning", size: 24, className: "ml-1 w-6 h-6", title: title })), isEnum ? (jsxRuntime.jsxs("div", { className: "flex items-center gap-1 flex-1", children: [jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500 flex-1 select-text", value: current !== undefined && current !== null
5539
5536
  ? String(current)
5540
5537
  : "", onChange: (e) => {
5541
5538
  const val = e.target.value;
@@ -5569,11 +5566,11 @@ function formatShortcut(shortcut) {
5569
5566
  navigator.userAgent.toLowerCase().includes("mac");
5570
5567
  return shortcut.replace(/⌘\/Ctrl/g, isMac ? "⌘" : "Ctrl");
5571
5568
  }
5572
- function ContextMenuButton({ label, onClick, disabled = false, shortcut, enableKeyboardShortcuts = true, }) {
5573
- return (jsxRuntime.jsxs("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-between", onClick: onClick, disabled: disabled, children: [jsxRuntime.jsx("span", { children: label }), enableKeyboardShortcuts && shortcut && (jsxRuntime.jsx("span", { className: "text-gray-400 text-xs ml-4", children: formatShortcut(shortcut) }))] }));
5569
+ function ContextMenuButton({ label, onClick, disabled = false, shortcut, }) {
5570
+ return (jsxRuntime.jsxs("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-between", onClick: onClick, disabled: disabled, children: [jsxRuntime.jsx("span", { children: label }), shortcut && (jsxRuntime.jsx("span", { className: "text-gray-400 text-xs ml-4", children: formatShortcut(shortcut) }))] }));
5574
5571
  }
5575
5572
 
5576
- function DefaultContextMenu({ open, clientPos, handlers, registry, nodeIds, enableKeyboardShortcuts = true, keyboardShortcuts = {
5573
+ function DefaultContextMenu({ open, clientPos, handlers, registry, nodeIds, keyboardShortcuts = {
5577
5574
  undo: "⌘/Ctrl + Z",
5578
5575
  redo: "⌘/Ctrl + Shift + Z",
5579
5576
  paste: "⌘/Ctrl + V",
@@ -5680,16 +5677,15 @@ function DefaultContextMenu({ open, clientPos, handlers, registry, nodeIds, enab
5680
5677
  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) => {
5681
5678
  e.preventDefault();
5682
5679
  e.stopPropagation();
5683
- }, 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 &&
5680
+ }, children: [hasPasteData && handlers.onPaste && (jsxRuntime.jsx(ContextMenuButton, { label: "Paste", onClick: handlePaste, shortcut: keyboardShortcuts.paste })), (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 })), 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 })), handlers.onRedo && (jsxRuntime.jsx(ContextMenuButton, { label: "Redo", onClick: handlers.onRedo, disabled: !canRedo, shortcut: keyboardShortcuts.redo })), (handlers.onUndo || handlers.onRedo) && (jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" }))] })), hasPasteData &&
5684
5681
  handlers.onPaste &&
5685
5682
  !handlers.onUndo &&
5686
5683
  !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" })) })] }));
5687
5684
  }
5688
5685
 
5689
- function NodeContextMenu({ open, clientPos, nodeId, handlers, bakeableOutputs, runMode, wb, enableKeyboardShortcuts = true, keyboardShortcuts = {
5686
+ function NodeContextMenu({ open, clientPos, nodeId, handlers, bakeableOutputs, runMode, wb, keyboardShortcuts = {
5690
5687
  copy: "⌘/Ctrl + C",
5691
5688
  duplicate: "⌘/Ctrl + E",
5692
- duplicateWithEdges: "⌘/Ctrl + Shift + E",
5693
5689
  delete: "Delete",
5694
5690
  }, }) {
5695
5691
  const ref = React.useRef(null);
@@ -5737,10 +5733,10 @@ function NodeContextMenu({ open, clientPos, nodeId, handlers, bakeableOutputs, r
5737
5733
  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) => {
5738
5734
  e.preventDefault();
5739
5735
  e.stopPropagation();
5740
- }, 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 }), handlers.onRunNode && (jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handlers.onRunNode, children: "Run node" })), runMode === "manual" && handlers.onRunFromHere && hasOutboundEdges && (jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handlers.onRunFromHere, children: isStartNode ? "Run workflow" : "Run from here" })), 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)))] }))] }));
5736
+ }, 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 }), jsxRuntime.jsx(ContextMenuButton, { label: "Duplicate", onClick: handlers.onDuplicate, shortcut: keyboardShortcuts.duplicate }), handlers.onRunNode && (jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handlers.onRunNode, children: "Run node" })), runMode === "manual" && handlers.onRunFromHere && hasOutboundEdges && (jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handlers.onRunFromHere, children: isStartNode ? "Run workflow" : "Run from here" })), jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" }), jsxRuntime.jsx(ContextMenuButton, { label: "Copy", onClick: handlers.onCopy, shortcut: keyboardShortcuts.copy }), 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)))] }))] }));
5741
5737
  }
5742
5738
 
5743
- function SelectionContextMenu({ open, clientPos, handlers, enableKeyboardShortcuts = true, keyboardShortcuts = {
5739
+ function SelectionContextMenu({ open, clientPos, handlers, keyboardShortcuts = {
5744
5740
  copy: "⌘/Ctrl + C",
5745
5741
  duplicate: "⌘/Ctrl + E",
5746
5742
  delete: "Delete",
@@ -5782,7 +5778,7 @@ function SelectionContextMenu({ open, clientPos, handlers, enableKeyboardShortcu
5782
5778
  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) => {
5783
5779
  e.preventDefault();
5784
5780
  e.stopPropagation();
5785
- }, 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 })] }));
5781
+ }, 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 }), handlers.onDuplicate && (jsxRuntime.jsx(ContextMenuButton, { label: "Duplicate", onClick: handlers.onDuplicate, shortcut: keyboardShortcuts.duplicate })), jsxRuntime.jsx(ContextMenuButton, { label: "Delete", onClick: handlers.onDelete, shortcut: keyboardShortcuts.delete })] }));
5786
5782
  }
5787
5783
 
5788
5784
  function KeyboardShortcutToast({ message, duration = 1000, onClose, }) {
@@ -6354,14 +6350,23 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6354
6350
  return getBakeableOutputs(menuState.nodeId, wb, wb.registry, outputTypesMap);
6355
6351
  }, [menuState, wb, wb.registry, registryVersion, outputTypesMap]);
6356
6352
  // Keyboard shortcuts configuration
6357
- const enableKeyboardShortcuts = overrides?.enableKeyboardShortcuts !== false; // Default to true
6353
+ const keyboardShortcutEnables = React.useMemo(() => ({
6354
+ undo: true,
6355
+ redo: true,
6356
+ copy: true,
6357
+ paste: true,
6358
+ duplicate: true,
6359
+ selectAll: true,
6360
+ ...(overrides?.enableKeyboardShortcuts ?? {}),
6361
+ }), [overrides?.enableKeyboardShortcuts]);
6362
+ const isShortcutEnabled = React.useCallback((action) => keyboardShortcutEnables[action] !== false, [keyboardShortcutEnables]);
6363
+ const hasEnabledKeyboardShortcuts = React.useMemo(() => Object.values(keyboardShortcutEnables).some(Boolean), [keyboardShortcutEnables]);
6358
6364
  const keyboardShortcuts = React.useMemo(() => overrides?.keyboardShortcuts || {
6359
6365
  undo: "⌘/Ctrl + Z",
6360
6366
  redo: "⌘/Ctrl + Shift + Z",
6361
6367
  copy: "⌘/Ctrl + C",
6362
6368
  paste: "⌘/Ctrl + V",
6363
6369
  duplicate: "⌘/Ctrl + E",
6364
- duplicateWithEdges: "⌘/Ctrl + Shift + E",
6365
6370
  selectAll: "⌘/Ctrl + A",
6366
6371
  delete: "Delete",
6367
6372
  }, [overrides?.keyboardShortcuts]);
@@ -6369,7 +6374,7 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6369
6374
  const { toast, showToast, hideToast } = useKeyboardShortcutToast();
6370
6375
  // Keyboard shortcut handler
6371
6376
  React.useEffect(() => {
6372
- if (!enableKeyboardShortcuts)
6377
+ if (!hasEnabledKeyboardShortcuts)
6373
6378
  return;
6374
6379
  const handleKeyDown = async (e) => {
6375
6380
  // Check if target is inside WorkbenchCanvas container
@@ -6392,6 +6397,8 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6392
6397
  const key = e.key.toLowerCase();
6393
6398
  // Undo: Cmd/Ctrl + Z
6394
6399
  if (modKey && key === "z" && !e.shiftKey && !e.altKey) {
6400
+ if (!isShortcutEnabled("undo"))
6401
+ return;
6395
6402
  e.preventDefault();
6396
6403
  if (runner &&
6397
6404
  "onUndo" in defaultContextMenuHandlers &&
@@ -6407,6 +6414,8 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6407
6414
  }
6408
6415
  // Redo: Cmd/Ctrl + Shift + Z
6409
6416
  if (modKey && e.shiftKey && key === "z" && !e.altKey) {
6417
+ if (!isShortcutEnabled("redo"))
6418
+ return;
6410
6419
  e.preventDefault();
6411
6420
  if (runner &&
6412
6421
  "onRedo" in defaultContextMenuHandlers &&
@@ -6422,6 +6431,8 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6422
6431
  }
6423
6432
  // Copy: Cmd/Ctrl + C
6424
6433
  if (modKey && key === "c" && !e.shiftKey && !e.altKey) {
6434
+ if (!isShortcutEnabled("copy"))
6435
+ return;
6425
6436
  const selection = wb.getSelection();
6426
6437
  if (selection.nodes.length > 0 || selection.edges.length > 0) {
6427
6438
  e.preventDefault();
@@ -6439,6 +6450,8 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6439
6450
  }
6440
6451
  // Duplicate: Cmd/Ctrl + E
6441
6452
  if (modKey && key === "e" && !e.shiftKey && !e.altKey) {
6453
+ if (!isShortcutEnabled("duplicate"))
6454
+ return;
6442
6455
  const selection = wb.getSelection();
6443
6456
  if (selection.nodes.length === 1 &&
6444
6457
  nodeContextMenuHandlers?.onDuplicate) {
@@ -6458,20 +6471,10 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6458
6471
  }
6459
6472
  return;
6460
6473
  }
6461
- // Duplicate with edges: Cmd/Ctrl + Shift + E
6462
- if (modKey && key === "e" && e.shiftKey && !e.altKey) {
6463
- const selection = wb.getSelection();
6464
- if (selection.nodes.length === 1 &&
6465
- nodeContextMenuHandlers?.onDuplicateWithEdges) {
6466
- e.preventDefault();
6467
- const modKeyLabel = isMac ? "⌘" : "Ctrl";
6468
- showToast(`Duplicate with edges (${modKeyLabel} + Shift + E)`);
6469
- nodeContextMenuHandlers.onDuplicateWithEdges();
6470
- }
6471
- return;
6472
- }
6473
6474
  // Paste: Cmd/Ctrl + V
6474
6475
  if (modKey && key === "v" && !e.shiftKey && !e.altKey) {
6476
+ if (!isShortcutEnabled("paste"))
6477
+ return;
6475
6478
  e.preventDefault();
6476
6479
  if ("hasPasteData" in defaultContextMenuHandlers &&
6477
6480
  defaultContextMenuHandlers.hasPasteData &&
@@ -6490,6 +6493,8 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6490
6493
  }
6491
6494
  // Select All: Cmd/Ctrl + A
6492
6495
  if (modKey && key === "a" && !e.shiftKey && !e.altKey) {
6496
+ if (!isShortcutEnabled("selectAll"))
6497
+ return;
6493
6498
  e.preventDefault();
6494
6499
  if (defaultContextMenuHandlers.onSelectAll) {
6495
6500
  const modKeyLabel = isMac ? "⌘" : "Ctrl";
@@ -6506,7 +6511,7 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6506
6511
  window.removeEventListener("keydown", handleKeyDown);
6507
6512
  };
6508
6513
  }, [
6509
- enableKeyboardShortcuts,
6514
+ hasEnabledKeyboardShortcuts,
6510
6515
  wb,
6511
6516
  runner,
6512
6517
  defaultContextMenuHandlers,
@@ -6514,6 +6519,7 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6514
6519
  nodeContextMenuHandlers,
6515
6520
  rfInstanceRef,
6516
6521
  showToast,
6522
+ isShortcutEnabled,
6517
6523
  ]);
6518
6524
  // Get custom renderers from UI extension registry (reactive to uiVersion changes)
6519
6525
  const { BackgroundRenderer, MinimapRenderer, ControlsRenderer, DefaultContextMenuRenderer, NodeContextMenuRenderer, SelectionContextMenuRenderer, connectionLineRenderer, } = React.useMemo(() => {
@@ -6563,14 +6569,10 @@ const WorkbenchCanvasComponent = React.forwardRef((props, ref) => {
6563
6569
  userOnInit(inst);
6564
6570
  }
6565
6571
  }, 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" &&
6566
- (DefaultContextMenuRenderer ? (jsxRuntime.jsx(DefaultContextMenuRenderer, { open: true, clientPos: menuState.menuPos, handlers: defaultContextMenuHandlers, registry: wb.registry, nodeIds: nodeIds, ...(enableKeyboardShortcuts !== false
6567
- ? { enableKeyboardShortcuts, keyboardShortcuts }
6568
- : {}) })) : (jsxRuntime.jsx(DefaultContextMenu, { open: true, clientPos: menuState.menuPos, handlers: defaultContextMenuHandlers, registry: wb.registry, nodeIds: nodeIds, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts }))), menuState?.type === "node" &&
6572
+ (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" &&
6569
6573
  nodeContextMenuHandlers &&
6570
- (NodeContextMenuRenderer ? (jsxRuntime.jsx(NodeContextMenuRenderer, { open: true, clientPos: menuState.menuPos, nodeId: menuState.nodeId, handlers: nodeContextMenuHandlers, bakeableOutputs: bakeableOutputs, runMode: runMode, wb: wb, ...(enableKeyboardShortcuts !== false
6571
- ? { enableKeyboardShortcuts, keyboardShortcuts }
6572
- : {}) })) : (jsxRuntime.jsx(NodeContextMenu, { open: true, clientPos: menuState.menuPos, nodeId: menuState.nodeId, handlers: nodeContextMenuHandlers, bakeableOutputs: bakeableOutputs, runMode: runMode }))), menuState?.type === "selection" &&
6573
- (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))] }));
6574
+ (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" &&
6575
+ (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(SelectionBoundOverlay, { selection: selection, rfInstance: rfInstanceRef.current, viewportTick: selectionOverlayTick })] }), toast && (jsxRuntime.jsx(KeyboardShortcutToast, { message: toast.message, onClose: hideToast }, toast.id))] }));
6574
6576
  });
6575
6577
  const WorkbenchCanvas = WorkbenchCanvasComponent;
6576
6578