Skip to content

Commit

Permalink
feat: implement mouse proximity
Browse files Browse the repository at this point in the history
  • Loading branch information
nathan-vm committed Oct 9, 2023
1 parent 5930460 commit 35b7138
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 15 deletions.
21 changes: 6 additions & 15 deletions frontend/src/components/WorkflowPanel/DefaultNode/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Paper, Typography } from "@mui/material";
import theme from "providers/theme.config";
import React, { type CSSProperties, memo, useMemo, useState } from "react";
import React, { type CSSProperties, memo, useMemo } from "react";
import { Handle, Position } from "reactflow";
import { getUuidSlice } from "utils";
import { getUuidSlice, useMouseProximity } from "utils";

import { type DefaultNodeProps } from "../types";

export const CustomNode = memo<DefaultNodeProps>(({ id, data, selected }) => {
const [hovered, setHovered] = useState(false);
const [isNear, ElementRef] = useMouseProximity(150);

const handleStyle = useMemo<CSSProperties>(
() =>
hovered
isNear
? {
border: 0,
borderRadius: "16px",
Expand All @@ -28,7 +28,7 @@ export const CustomNode = memo<DefaultNodeProps>(({ id, data, selected }) => {
transition: "ease 100",
zIndex: 2,
},
[hovered],
[isNear],
);

const extendedClassExt = useMemo<"input" | "default" | "output">(() => {
Expand Down Expand Up @@ -121,16 +121,7 @@ export const CustomNode = memo<DefaultNodeProps>(({ id, data, selected }) => {
style={handleStyle}
/>
)}
<Paper
elevation={selected ? 12 : 3}
onMouseEnter={() => {
setHovered(true);
}}
onMouseLeave={() => {
setHovered(false);
}}
sx={nodeStyle}
>
<Paper elevation={selected ? 12 : 3} sx={nodeStyle} ref={ElementRef}>
<div
style={{
display: "flex",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export { generateTaskName } from "./generateTaskName";
export { getDefinition } from "./getDefinition";
export { lazyImport } from "./lazyImports";
export { useInterval } from "./useInterval";
export { useMouseProximity } from "./useMouseProximity";
64 changes: 64 additions & 0 deletions frontend/src/utils/useMouseProximity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { useState, useEffect, useRef } from "react";

/**
* A custom React hook to determine if the mouse pointer is within a specified
* percentage of an element's size from its center.
*
* @param {number} initialDistancePercentage - The distance in percentage from the
* element's center within which the mouse is considered "near." Default is 80.
* @returns {Array} A tuple containing a boolean value indicating whether the mouse
* is near the element's center and a ref object to attach to the target element.
*/
export function useMouseProximity(
initialDistancePercentage: number = 80,
): [boolean, React.MutableRefObject<any>] {
const [isNear, setIsNear] = useState<boolean>(false);
const elementRef = useRef<any>(null);

useEffect(() => {
function handleMouseMove(event: MouseEvent) {
const element = elementRef.current;
if (!element) return;

// Get the coordinates of the mouse pointer
const mouseX = event.clientX;
const mouseY = event.clientY;

// Get the position and dimensions of the element
const elementRect = element.getBoundingClientRect();
const elementWidth = elementRect.width;
const elementHeight = elementRect.height;
const elementX = elementRect.left;
const elementY = elementRect.top;

// Calculate the distance between the mouse and the center of the element
const centerX = elementX + elementWidth / 2;
const centerY = elementY + elementHeight / 2;
const distanceX = Math.abs(mouseX - centerX);
const distanceY = Math.abs(mouseY - centerY);

// Calculate the threshold distance based on the specified percentage
const thresholdX =
((initialDistancePercentage / 100) * elementWidth + elementWidth) / 2;
const thresholdY =
((initialDistancePercentage / 100) * +elementHeight) / 2;

// Check if the mouse is within the threshold distance on both X and Y axes
if (distanceX <= thresholdX && distanceY <= thresholdY) {
setIsNear(true);
} else {
setIsNear(false);
}
}

// Add mousemove event listener to track mouse position
document.addEventListener("mousemove", handleMouseMove);

return () => {
// Clean up the event listener when the component unmounts
document.removeEventListener("mousemove", handleMouseMove);
};
}, [initialDistancePercentage]);

return [isNear, elementRef];
}

0 comments on commit 35b7138

Please sign in to comment.