diff --git a/src/components/editor/EditorContainer.tsx b/src/components/editor/EditorContainer.tsx index 629e41f..95c89b5 100644 --- a/src/components/editor/EditorContainer.tsx +++ b/src/components/editor/EditorContainer.tsx @@ -65,10 +65,10 @@ const EditorContainer: React.FunctionComponent = (props): JSX.Element | n onDistanceChange: (distance: number | null) => { console.info('Distance Changed', distance); - if (distance && distance < 40 && !isDraggedNodeClose) { + if (distance && distance < settings.dnd.closeDistanceThreshold && !isDraggedNodeClose) { console.info('setIsDraggedNodeClose', true); setIsDraggedNodeClose(true); - } else if ((!distance || distance > 40) && isDraggedNodeClose) { + } else if ((!distance || distance > settings.dnd.closeDistanceThreshold) && isDraggedNodeClose) { console.info('setIsDraggedNodeClose', false); setIsDraggedNodeClose(false); } diff --git a/src/components/nodes/NodeRouter.tsx b/src/components/nodes/NodeRouter.tsx index 8733b24..4f0f67f 100644 --- a/src/components/nodes/NodeRouter.tsx +++ b/src/components/nodes/NodeRouter.tsx @@ -3,6 +3,7 @@ import React from 'react'; import { NodeProps } from 'reaflow'; import { NodeData } from 'reaflow/dist/types'; import { useRecoilState } from 'recoil'; +import settings from '../../settings'; import { isDraggedNodeCloseState } from '../../states/isDraggedNodeCloseState'; import { isDraggedNodeDroppableState } from '../../states/isDraggedNodeDroppableState'; import { lastFocusedNodeState } from '../../states/lastFocusedNodeState'; @@ -45,33 +46,70 @@ const NodeRouter: React.FunctionComponent = (props) => { } const defaultStrokeWidth = 0; - const strokeWidth = lastFocusedNode?.id === nodeProps.id && isDroppable && isDraggedNodeClose ? 10 : defaultStrokeWidth; + const strokeWidth = lastFocusedNode?.id === nodeProps.id && isDroppable && isDraggedNodeClose ? settings.dnd.closeDistanceThreshold : defaultStrokeWidth; - const commonBlockProps: Partial = { + /** + * When clicking on a node. + * + * @param event + * @param node + */ + const onNodeClick = (event: React.MouseEvent, node: NodeData) => { + console.log(`node clicked (${nodeProps?.properties?.text || nodeProps?.id})`, nodeProps); + console.log(`node selected`, node); + setSelectedNodes([node]); + }; + + /** + * When the mouse enters a node (on hover). + * + * XXX Does not work because `foreignObject` is displayed on top of the Node. See https://github.com/reaviz/reaflow/issues/45 + * + * @param event + * @param node + */ + const onNodeEnter = (event: React.MouseEvent, node: BaseNodeData) => { + if (node?.id !== lastFocusedNode?.id) { + setLastFocusedNode(node); + console.log('setLastFocusedNode', node); + } + }; + + /** + * When the mouse leaves a node (leaves hover area). + * + * XXX Does not work because `foreignObject` is displayed on top of the Node. See https://github.com/reaviz/reaflow/issues/45 + * + * @param event + * @param node + */ + const onNodeLeave = (event: React.MouseEvent, node: BaseNodeData) => { + if (lastFocusedNode?.id === node?.id) { + setLastFocusedNode(undefined); + console.log('setLastFocusedNode', undefined); + } + }; + + /** + * Node props applied to all nodes, no matter what type they are. + */ + const commonNodeProps: Partial = { ...nodeProps, updateCurrentNode, - className: classnames({ 'dnd-closest': lastFocusedNode?.id === nodeProps.id }, `node node-${type}`), + className: classnames( + `node node-${type}`, + { + 'dnd-closest': lastFocusedNode?.id === nodeProps.id + }, + ), style: { strokeWidth: strokeWidth, fill: 'white', color: 'black', }, - onClick: (event: React.MouseEvent, node: NodeData) => { - console.log(`node clicked (${nodeProps?.properties?.text || nodeProps?.id})`, nodeProps) - setSelectedNodes([node]); - }, - onEnter: (event: React.MouseEvent, node: BaseNodeData) => { - if (node?.id !== lastFocusedNode?.id) { - setLastFocusedNode(node); - console.log('setLastFocusedNode', node); - } - }, - onLeave: (event: React.MouseEvent, node: BaseNodeData) => { - if (lastFocusedNode?.id === node?.id) { - setLastFocusedNode(undefined); - console.log('setLastFocusedNode', undefined); - } - }, + onClick: onNodeClick, + onEnter: onNodeEnter, + onLeave: onNodeLeave, }; // console.log('rendering node of type: ', type, commonBlockProps) @@ -80,13 +118,13 @@ const NodeRouter: React.FunctionComponent = (props) => { case 'information': return ( ); case 'question': return ( ); } diff --git a/src/settings.ts b/src/settings.ts index 023fd1f..88db744 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -5,6 +5,9 @@ * @readonly */ export const settings = { + /** + * Left container of blocks. + */ blocksContainer: { width: '150px', }, @@ -13,7 +16,15 @@ export const settings = { * Drag & Drop */ dnd: { + /** + * Color applied to the "closest" element when dragging a block close to a node. + */ colorClosest: '#002aff', + + /** + * Minimum distance threshold to consider a dragged block to be close to a node. + */ + closeDistanceThreshold: 10, }, };