{/* Loading spinner - always mounted, animation paused when hidden to avoid overhead */}
{
connectionLineType={ConnectionLineType.SmoothStep}
onPaneClick={onPaneClick}
onEdgeClick={onEdgeClick}
- onPaneContextMenu={(e) => e.preventDefault()}
- onNodeContextMenu={(e) => e.preventDefault()}
+ onPaneContextMenu={handlePaneContextMenu}
+ onNodeContextMenu={handleNodeContextMenu}
+ onSelectionContextMenu={handleSelectionContextMenu}
onPointerMove={handleCanvasPointerMove}
onPointerLeave={handleCanvasPointerLeave}
elementsSelectable={true}
@@ -2640,7 +2829,7 @@ const WorkflowContent = React.memo(() => {
noWheelClassName='allow-scroll'
edgesFocusable={true}
edgesUpdatable={effectivePermissions.canEdit}
- className={`workflow-container h-full bg-[var(--bg)] transition-opacity duration-150 ${reactFlowStyles} ${isCanvasReady ? 'opacity-100' : 'opacity-0'}`}
+ className={`workflow-container h-full transition-opacity duration-150 ${reactFlowStyles} ${isCanvasReady ? 'opacity-100' : 'opacity-0'}`}
onNodeDrag={effectivePermissions.canEdit ? onNodeDrag : undefined}
onNodeDragStop={effectivePermissions.canEdit ? onNodeDragStop : undefined}
onSelectionDragStop={effectivePermissions.canEdit ? onSelectionDragStop : undefined}
@@ -2662,6 +2851,48 @@ const WorkflowContent = React.memo(() => {
+
+ {/* Context Menus */}
+
b.parentId && (b.parentType === 'loop' || b.parentType === 'parallel')
+ )}
+ disableEdit={!effectivePermissions.canEdit}
+ />
+
+
>
)}
diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/workspace-header.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/workspace-header.tsx
index b42cf9649a..598804496f 100644
--- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/workspace-header.tsx
+++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/workspace-header.tsx
@@ -151,6 +151,13 @@ export function WorkspaceHeader({
setIsMounted(true)
}, [])
+ // Listen for open-invite-modal event from context menu
+ useEffect(() => {
+ const handleOpenInvite = () => setIsInviteModalOpen(true)
+ window.addEventListener('open-invite-modal', handleOpenInvite)
+ return () => window.removeEventListener('open-invite-modal', handleOpenInvite)
+ }, [])
+
/**
* Focus the inline list rename input when it becomes active
*/
diff --git a/apps/sim/stores/panel/editor/store.ts b/apps/sim/stores/panel/editor/store.ts
index 0e3ff198a6..c716f61662 100644
--- a/apps/sim/stores/panel/editor/store.ts
+++ b/apps/sim/stores/panel/editor/store.ts
@@ -22,6 +22,10 @@ interface PanelEditorState {
setConnectionsHeight: (height: number) => void
/** Toggle connections between collapsed (min height) and expanded (default height) */
toggleConnectionsCollapsed: () => void
+ /** Flag to signal the editor to focus the rename input */
+ shouldFocusRename: boolean
+ /** Sets the shouldFocusRename flag */
+ setShouldFocusRename: (value: boolean) => void
}
/**
@@ -33,6 +37,8 @@ export const usePanelEditorStore = create()(
(set, get) => ({
currentBlockId: null,
connectionsHeight: EDITOR_CONNECTIONS_HEIGHT.DEFAULT,
+ shouldFocusRename: false,
+ setShouldFocusRename: (value) => set({ shouldFocusRename: value }),
setCurrentBlockId: (blockId) => {
set({ currentBlockId: blockId })
@@ -79,6 +85,10 @@ export const usePanelEditorStore = create()(
}),
{
name: 'panel-editor-state',
+ partialize: (state) => ({
+ currentBlockId: state.currentBlockId,
+ connectionsHeight: state.connectionsHeight,
+ }),
onRehydrateStorage: () => (state) => {
// Sync CSS variables with stored state after rehydration
if (state && typeof window !== 'undefined') {