diff --git a/frontend/src/lib/components/graph/FlowGraphV2.svelte b/frontend/src/lib/components/graph/FlowGraphV2.svelte index 052df58d63..08cd4e80ca 100644 --- a/frontend/src/lib/components/graph/FlowGraphV2.svelte +++ b/frontend/src/lib/components/graph/FlowGraphV2.svelte @@ -13,7 +13,8 @@ Controls, ControlButton, SvelteFlowProvider, - type Viewport + type Viewport, + SelectionMode } from '@xyflow/svelte' import { graphBuilder, @@ -388,10 +389,11 @@ insert: (detail) => { onInsert?.(detail) }, - select: (modId) => { + select: (mod: string | FlowModule) => { if (!notSelectable) { // TODO: Handle Ctrl/Cmd and Shift modifiers when node-level click events are available // For now, normal click behavior + const modId = typeof mod === 'string' ? mod : mod.id selectionManager.selectId(modId) onSelect?.(modId) } @@ -423,7 +425,7 @@ delete expandedSubflows[id] expandedSubflows = expandedSubflows }, - updateMock: (detail) => { + updateMock: (detail: any) => { onUpdateMock?.(detail) }, testUpTo: (id: string) => { @@ -472,8 +474,8 @@ selectionManager.handleKeyDown(event, nodes) } - function handleKeyUp(event: KeyboardEvent) { - selectionManager.handleKeyUp(event) + function handleKeyUp(_event: KeyboardEvent) { + // Keep for potential future use } async function updateStores() { @@ -767,8 +769,12 @@ connectionLineType={ConnectionLineType.SmoothStep} defaultEdgeOptions={{ type: 'smoothstep' }} preventScrolling={scroll} + selectionOnDrag={selectionManager.mode === 'rect-select'} + elementsSelectable={true} + selectionMode={SelectionMode.Partial} + selectionKey={selectionManager.mode === 'rect-select' ? null : 'Shift'} + panActivationKey={selectionManager.mode === 'rect-select' ? 'Shift' : null} zoomOnDoubleClick={false} - elementsSelectable={false} elevateNodesOnSelect={false} {proOptions} nodesDraggable={false} @@ -791,15 +797,11 @@ selectedNodes={nodes.filter((node) => selectionManager.selectedIds.includes(node.id))} /> - - - selectionManager.selectNodes(nodeIds, addToExisting, modules, nodes)} - {nodes} - /> {/if} + + + {#if leftHeader}
{@render leftHeader()} @@ -882,4 +884,8 @@ :global(.svelte-flow__edgelabel-renderer) { @apply z-50; } + + :global(.svelte-flow__selection) { + display: none; + } diff --git a/frontend/src/lib/components/graph/SelectionTool.svelte b/frontend/src/lib/components/graph/SelectionTool.svelte index 143baea07f..b69e995aef 100644 --- a/frontend/src/lib/components/graph/SelectionTool.svelte +++ b/frontend/src/lib/components/graph/SelectionTool.svelte @@ -1,208 +1,61 @@ -{#if selectionMode === 'rect-select'} + +{#if selectionBoxBounds()} + {@const bounds = selectionBoxBounds()!}
- - {#if previewNote && isDrawing} -
- {/if}
{/if} - - diff --git a/frontend/src/lib/components/graph/noteManager.svelte.ts b/frontend/src/lib/components/graph/noteManager.svelte.ts index f6964abe3b..fb46a44317 100644 --- a/frontend/src/lib/components/graph/noteManager.svelte.ts +++ b/frontend/src/lib/components/graph/noteManager.svelte.ts @@ -215,7 +215,7 @@ export class NoteManager { height: size.height, zIndex: zIndex ?? -2000, // Use provided zIndex or fallback draggable: isGroupNote ? false : editMode && !note.locked, - selectable: true + selectable: false } } diff --git a/frontend/src/lib/components/graph/renderers/nodes/NoteNode.svelte b/frontend/src/lib/components/graph/renderers/nodes/NoteNode.svelte index a2dfbdaf7f..612de13f70 100644 --- a/frontend/src/lib/components/graph/renderers/nodes/NoteNode.svelte +++ b/frontend/src/lib/components/graph/renderers/nodes/NoteNode.svelte @@ -20,11 +20,11 @@ // Callback for layout calculations (needed in both edit and view modes) onTextHeightChange?: (height: number) => void } - selected?: boolean dragging?: boolean } - let { data, selected = false, dragging = false }: Props = $props() + let { data, dragging = false }: Props = $props() + let selected = $state(false) // Get NoteEditor context for edit mode const noteEditorContext = getNoteEditorContext() diff --git a/frontend/src/lib/components/graph/selectionUtils.svelte.ts b/frontend/src/lib/components/graph/selectionUtils.svelte.ts index 3b408f1385..dd5f8c1420 100644 --- a/frontend/src/lib/components/graph/selectionUtils.svelte.ts +++ b/frontend/src/lib/components/graph/selectionUtils.svelte.ts @@ -10,9 +10,6 @@ export interface SelectionState { export class SelectionManager { public selectedIds = $state([]) #selectionMode = $state<'normal' | 'rect-select'>('normal') - #modeSource = $state<'button' | 'keyboard' | 'temporary'>('button') - #previousMode = $state<'normal' | 'rect-select'>('normal') - #cmdKeyPressed = $state(false) constructor() {} @@ -29,39 +26,10 @@ export class SelectionManager { } set mode(mode: 'normal' | 'rect-select') { - this.#previousMode = this.#selectionMode this.#selectionMode = mode - // Default to button source when mode is set directly (for backward compatibility) - if (this.#modeSource !== 'temporary') { - this.#modeSource = 'button' - } // Note: No automatic selection clearing when changing modes - preserve current selection } - // Toggle mode temporarily (for cmd key hold behavior) - toggleModeTemporary() { - this.#previousMode = this.#selectionMode - this.#modeSource = 'temporary' - this.#selectionMode = this.#selectionMode === 'normal' ? 'rect-select' : 'normal' - } - - // Toggle mode persistently (for cmd key tap behavior) - toggleModePersistent() { - this.#previousMode = this.#selectionMode - this.#modeSource = 'keyboard' - this.#selectionMode = this.#selectionMode === 'normal' ? 'rect-select' : 'normal' - // Note: Preserve current selection when toggling modes - } - - // Revert temporary mode change - revertTemporaryMode() { - if (this.#modeSource === 'temporary') { - this.#selectionMode = this.#previousMode - this.#modeSource = 'button' // Reset to default button source - // Note: Preserve current selection when reverting temporary mode changes - } - } - // Get hierarchical children of a node getNodeChildrenIds(nodeId: string, modules: FlowModule[] | undefined, nodes: Node[]): string[] { const module = modules?.find((m) => m.id === nodeId) @@ -203,13 +171,6 @@ export class SelectionManager { if (event.key === 'Escape') { // Escape key clears selection regardless of mode this.clearSelection() - } else if (event.key === 'Meta' || event.key === 'Cmd') { - // Cmd/Meta key pressed - temporarily toggle mode - if (!this.#cmdKeyPressed) { - this.#cmdKeyPressed = true - event.preventDefault() - this.toggleModeTemporary() - } } else if ((event.ctrlKey || event.metaKey) && event.key === 'a') { event.preventDefault() // Select all visible nodes (exclude note nodes) @@ -219,13 +180,4 @@ export class SelectionManager { } } } - - // Handle keyboard releases - handleKeyUp(event: KeyboardEvent) { - if (event.key === 'Meta' || event.key === 'Cmd') { - // Cmd/Meta key released - revert temporary mode change - this.#cmdKeyPressed = false - this.revertTemporaryMode() - } - } }