From 5293fd74bed6c6035f0f762fbd5498b548181c89 Mon Sep 17 00:00:00 2001 From: Daniel Leal Date: Tue, 28 Feb 2023 16:37:21 +0000 Subject: [PATCH 1/2] fix(core): track modifier keys on useKey press --- .../vite-app/src/examples/Figma/index.tsx | 3 +++ .../examples/UseOnSelectionChange/index.tsx | 19 ++++++++++++++++++- packages/core/src/hooks/useKeyPress.ts | 11 +++++++++-- packages/core/src/utils/index.ts | 5 ++--- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/examples/vite-app/src/examples/Figma/index.tsx b/examples/vite-app/src/examples/Figma/index.tsx index 22f0dcce..64cfb4bb 100644 --- a/examples/vite-app/src/examples/Figma/index.tsx +++ b/examples/vite-app/src/examples/Figma/index.tsx @@ -38,6 +38,9 @@ const BasicFlow = () => { onSelectionContextMenu={onPaneContextMenu} > +
+ +
); }; diff --git a/examples/vite-app/src/examples/UseOnSelectionChange/index.tsx b/examples/vite-app/src/examples/UseOnSelectionChange/index.tsx index 160ca769..b6f5531f 100644 --- a/examples/vite-app/src/examples/UseOnSelectionChange/index.tsx +++ b/examples/vite-app/src/examples/UseOnSelectionChange/index.tsx @@ -18,6 +18,20 @@ const initialNodes: Node[] = [ data: { label: 'Node 1' }, position: { x: 250, y: 5 }, }, + { + id: '2', + type: 'default', + data: { label: 'Node 2' }, + position: { x: 250, y: 100 }, + }, +]; + +const initialEdges: Edge[] = [ + { + id: 'e1-2', + source: '1', + target: '2', + }, ]; const SelectionLogger = () => { @@ -34,7 +48,7 @@ const SelectionLogger = () => { const Flow = () => { const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); - const [edges, setEdges, onEdgesChange] = useEdgesState([]); + const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); const onConnect = useCallback((params: Edge | Connection) => setEdges((els) => addEdge(params, els)), [setEdges]); return ( @@ -52,6 +66,9 @@ const WrappedFlow = () => ( +
+ +
); diff --git a/packages/core/src/hooks/useKeyPress.ts b/packages/core/src/hooks/useKeyPress.ts index 20dcf37e..3301fc8f 100644 --- a/packages/core/src/hooks/useKeyPress.ts +++ b/packages/core/src/hooks/useKeyPress.ts @@ -19,6 +19,9 @@ const doc = typeof document !== 'undefined' ? document : null; export default (keyCode: KeyCode | null = null, options: UseKeyPressOptions = { target: doc }): boolean => { const [keyPressed, setKeyPressed] = useState(false); + // we need to remember if a modifier key is pressed in order to track it + const modifierPressed = useRef(false); + // we need to remember the pressed keys in order to support combinations const pressedKeys = useRef(new Set([])); @@ -43,7 +46,10 @@ export default (keyCode: KeyCode | null = null, options: UseKeyPressOptions = { useEffect(() => { if (keyCode !== null) { const downHandler = (event: KeyboardEvent) => { - if (isInputDOMNode(event)) { + + modifierPressed.current = event.ctrlKey || event.metaKey || event.shiftKey; + + if (!modifierPressed.current && isInputDOMNode(event)) { return false; } const keyOrCode = useKeyOrCode(event.code, keysToWatch); @@ -56,7 +62,7 @@ export default (keyCode: KeyCode | null = null, options: UseKeyPressOptions = { }; const upHandler = (event: KeyboardEvent) => { - if (isInputDOMNode(event)) { + if (!modifierPressed.current && isInputDOMNode(event)) { return false; } const keyOrCode = useKeyOrCode(event.code, keysToWatch); @@ -67,6 +73,7 @@ export default (keyCode: KeyCode | null = null, options: UseKeyPressOptions = { } else { pressedKeys.current.delete(event[keyOrCode]); } + modifierPressed.current = false; }; const resetHandler = () => { diff --git a/packages/core/src/utils/index.ts b/packages/core/src/utils/index.ts index 2d801d05..b4f0ca3f 100644 --- a/packages/core/src/utils/index.ts +++ b/packages/core/src/utils/index.ts @@ -104,11 +104,10 @@ export function isInputDOMNode(event: KeyboardEvent | ReactKeyboardEvent): boole const target = (kbEvent.composedPath?.()?.[0] || event.target) as HTMLElement; const isInput = ['INPUT', 'SELECT', 'TEXTAREA'].includes(target?.nodeName) || target?.hasAttribute('contenteditable'); - // we want to be able to do a multi selection event if we are in an input field - const isModifierKey = event.ctrlKey || event.metaKey || event.shiftKey; + // when an input field is focused we don't want to trigger deletion or movement of nodes - return (isInput && !isModifierKey) || !!target?.closest('.nokey'); + return isInput || !!target?.closest('.nokey'); } export const isMouseEvent = ( From 5fabd2720f6367f75f79a45822d8f675a3b8e1cf Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 6 Mar 2023 15:24:17 +0100 Subject: [PATCH 2/2] chore(changeset): add --- .changeset/rare-points-change.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/rare-points-change.md diff --git a/.changeset/rare-points-change.md b/.changeset/rare-points-change.md new file mode 100644 index 00000000..9ce10e25 --- /dev/null +++ b/.changeset/rare-points-change.md @@ -0,0 +1,5 @@ +--- +'@reactflow/core': major +--- + +track modifier keys on useKeypress