feat: improve mouse events
This commit is contained in:
@@ -188,6 +188,8 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
|
|||||||
const flowActionsRef = useRef<{ pasteAtViewportCenter: () => void; fitView: () => void } | null>(null)
|
const flowActionsRef = useRef<{ pasteAtViewportCenter: () => void; fitView: () => void } | null>(null)
|
||||||
const [contextTarget, setContextTarget] = React.useState<null | { type: 'canvas'; clientX: number; clientY: number }>(null)
|
const [contextTarget, setContextTarget] = React.useState<null | { type: 'canvas'; clientX: number; clientY: number }>(null)
|
||||||
const [lastCreatedNodeId, setLastCreatedNodeId] = React.useState<string | null>(null)
|
const [lastCreatedNodeId, setLastCreatedNodeId] = React.useState<string | null>(null)
|
||||||
|
const [isPanning, setIsPanning] = React.useState(false)
|
||||||
|
const [isSelecting, setIsSelecting] = React.useState(false)
|
||||||
const [ariaAnnouncement, setAriaAnnouncement] = React.useState<string | null>(null)
|
const [ariaAnnouncement, setAriaAnnouncement] = React.useState<string | null>(null)
|
||||||
const nodesRef = useRef(nodes)
|
const nodesRef = useRef(nodes)
|
||||||
nodesRef.current = nodes
|
nodesRef.current = nodes
|
||||||
@@ -286,6 +288,11 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
|
|||||||
|
|
||||||
const onInit = useCallback((instance: unknown) => setRfInstance(instance), [])
|
const onInit = useCallback((instance: unknown) => setRfInstance(instance), [])
|
||||||
|
|
||||||
|
const onMoveStart = useCallback(() => setIsPanning(true), [])
|
||||||
|
const onMoveEnd = useCallback(() => setIsPanning(false), [])
|
||||||
|
const onSelectionDragStart = useCallback(() => setIsSelecting(true), [])
|
||||||
|
const onSelectionDragStop = useCallback(() => setIsSelecting(false), [])
|
||||||
|
|
||||||
const onNodeDragStart = useCallback(() => saveForDragEnd(), [saveForDragEnd])
|
const onNodeDragStart = useCallback(() => saveForDragEnd(), [saveForDragEnd])
|
||||||
const onNodeDragStop = useCallback(() => commitDragEnd(), [commitDragEnd])
|
const onNodeDragStop = useCallback(() => commitDragEnd(), [commitDragEnd])
|
||||||
|
|
||||||
@@ -612,6 +619,7 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
|
|||||||
<FlowFitViewOnLoad />
|
<FlowFitViewOnLoad />
|
||||||
<FlowKeyboardShortcuts />
|
<FlowKeyboardShortcuts />
|
||||||
<ReactFlow
|
<ReactFlow
|
||||||
|
className={isPanning ? 'react-flow--panning' : isSelecting ? 'react-flow--selecting' : undefined}
|
||||||
nodes={nodes.map((n) => ({
|
nodes={nodes.map((n) => ({
|
||||||
...n,
|
...n,
|
||||||
className: [n.className, 'nowheel'].filter(Boolean).join(' '),
|
className: [n.className, 'nowheel'].filter(Boolean).join(' '),
|
||||||
@@ -624,6 +632,10 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
|
|||||||
onConnectEnd={onConnectEnd}
|
onConnectEnd={onConnectEnd}
|
||||||
onNodeDragStart={onNodeDragStart}
|
onNodeDragStart={onNodeDragStart}
|
||||||
onNodeDragStop={onNodeDragStop}
|
onNodeDragStop={onNodeDragStop}
|
||||||
|
onMoveStart={onMoveStart}
|
||||||
|
onMoveEnd={onMoveEnd}
|
||||||
|
onSelectionDragStart={onSelectionDragStart}
|
||||||
|
onSelectionDragStop={onSelectionDragStop}
|
||||||
isValidConnection={isValidConnection}
|
isValidConnection={isValidConnection}
|
||||||
nodeTypes={nodeTypes}
|
nodeTypes={nodeTypes}
|
||||||
edgeTypes={edgeTypes}
|
edgeTypes={edgeTypes}
|
||||||
@@ -639,6 +651,11 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
|
|||||||
nodesDraggable
|
nodesDraggable
|
||||||
nodesConnectable
|
nodesConnectable
|
||||||
elementsSelectable
|
elementsSelectable
|
||||||
|
panOnScroll
|
||||||
|
zoomOnScroll
|
||||||
|
zoomActivationKeyCode="Meta"
|
||||||
|
panOnDrag={[1]}
|
||||||
|
selectionOnDrag
|
||||||
>
|
>
|
||||||
{/* BackgroundVariant from @xyflow/system expects enum; 'dots' is valid at runtime */}
|
{/* BackgroundVariant from @xyflow/system expects enum; 'dots' is valid at runtime */}
|
||||||
<Background variant={'dots' as React.ComponentProps<typeof Background>['variant']} gap={20} />
|
<Background variant={'dots' as React.ComponentProps<typeof Background>['variant']} gap={20} />
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { cn } from '@/lib/utils'
|
|||||||
const MIN_ZOOM = 0.1
|
const MIN_ZOOM = 0.1
|
||||||
const MAX_ZOOM = 2
|
const MAX_ZOOM = 2
|
||||||
/** When zoom <= this value, show compact icon view (bottom ~30% of zoom range). */
|
/** When zoom <= this value, show compact icon view (bottom ~30% of zoom range). */
|
||||||
export const CONTEXTUAL_ZOOM_THRESHOLD = MIN_ZOOM + 0.3 * (MAX_ZOOM - MIN_ZOOM)
|
export const CONTEXTUAL_ZOOM_THRESHOLD = MIN_ZOOM + 0.1 * (MAX_ZOOM - MIN_ZOOM)
|
||||||
|
|
||||||
/** Handle id per type for compact view (input, output). */
|
/** Handle id per type for compact view (input, output). */
|
||||||
const COMPACT_HANDLES: Record<string, { input?: string; output?: string }> = {
|
const COMPACT_HANDLES: Record<string, { input?: string; output?: string }> = {
|
||||||
|
|||||||
@@ -20,6 +20,17 @@ body {
|
|||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Canvas pane cursors: crosshair for selection box, grab/grabbing for middle-click pan */
|
||||||
|
.react-flow__pane {
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
.react-flow.react-flow--panning .react-flow__pane {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
.react-flow.react-flow--selecting .react-flow__pane {
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
|
||||||
/* Node specific overrides */
|
/* Node specific overrides */
|
||||||
.react-flow__node {
|
.react-flow__node {
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
Reference in New Issue
Block a user