feat: performance 1
This commit is contained in:
@@ -1,18 +1,17 @@
|
||||
import React, { useContext, useMemo } from 'react'
|
||||
import React, { useContext, useMemo, memo } from 'react'
|
||||
import {
|
||||
BaseEdge,
|
||||
getBezierPath,
|
||||
type EdgeProps,
|
||||
} from '@xyflow/react'
|
||||
import FlowContext from '@/lib/graph/flowContext'
|
||||
import { ConnectionPathContext } from '@/lib/graph/flowContext'
|
||||
import { getConnectionStatus, CONNECTION_STATUS_CLASS } from '@/lib/graph/connectionStatus'
|
||||
import { getConnectionLabelForTarget } from '@/lib/graph/nodeRegistry'
|
||||
|
||||
const EDGE_STROKE_WIDTH = 2
|
||||
const DOT_MARKER_R = 1.5
|
||||
const EMPTY_PATH_NODE_IDS = new Set<string>()
|
||||
|
||||
export function AnimatedEdge({
|
||||
function AnimatedEdgeInner({
|
||||
id,
|
||||
source,
|
||||
sourceX,
|
||||
@@ -25,9 +24,9 @@ export function AnimatedEdge({
|
||||
label: labelProp,
|
||||
interactionWidth,
|
||||
target,
|
||||
data,
|
||||
}: EdgeProps) {
|
||||
const ctx = useContext(FlowContext)
|
||||
const nodes = ctx?.nodes ?? []
|
||||
const ctx = useContext(ConnectionPathContext)
|
||||
const pathNodeIds = ctx?.connectionPathNodeIds ?? EMPTY_PATH_NODE_IDS
|
||||
const pausedSegmentNodeIds = ctx?.connectionPathPausedSegmentNodeIds ?? EMPTY_PATH_NODE_IDS
|
||||
const activeSegmentNodeIds = ctx?.connectionPathActiveSegmentNodeIds ?? EMPTY_PATH_NODE_IDS
|
||||
@@ -35,12 +34,8 @@ export function AnimatedEdge({
|
||||
() => new Set(ctx?.connectionPathErrorNodeIds ?? []),
|
||||
[ctx?.connectionPathErrorNodeIds]
|
||||
)
|
||||
const targetNode = useMemo(() => nodes.find((n: any) => n.id === target), [nodes, target])
|
||||
const derivedLabel = useMemo(
|
||||
() => (targetNode?.type != null ? getConnectionLabelForTarget(targetNode.type) : undefined),
|
||||
[targetNode?.type]
|
||||
)
|
||||
const label = labelProp ?? derivedLabel
|
||||
|
||||
const label = labelProp ?? (data as { connectionLabel?: string } | undefined)?.connectionLabel
|
||||
|
||||
const connectionStatus = useMemo(
|
||||
() =>
|
||||
@@ -146,3 +141,23 @@ export function AnimatedEdge({
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function edgePropsAreEqual(prev: EdgeProps, next: EdgeProps): boolean {
|
||||
return (
|
||||
prev.id === next.id &&
|
||||
prev.source === next.source &&
|
||||
prev.target === next.target &&
|
||||
prev.sourceX === next.sourceX &&
|
||||
prev.sourceY === next.sourceY &&
|
||||
prev.targetX === next.targetX &&
|
||||
prev.targetY === next.targetY &&
|
||||
prev.sourcePosition === next.sourcePosition &&
|
||||
prev.targetPosition === next.targetPosition &&
|
||||
prev.style === next.style &&
|
||||
prev.label === next.label &&
|
||||
(prev.data as { connectionLabel?: string } | undefined)?.connectionLabel ===
|
||||
(next.data as { connectionLabel?: string } | undefined)?.connectionLabel
|
||||
)
|
||||
}
|
||||
|
||||
export const AnimatedEdge = memo(AnimatedEdgeInner, edgePropsAreEqual)
|
||||
|
||||
@@ -2,8 +2,7 @@ import type { ComponentProps, ReactNode } from "react";
|
||||
import { NodeResizer } from "@xyflow/react";
|
||||
import { useContext } from "react";
|
||||
|
||||
import FlowContext from "@/lib/graph/flowContext";
|
||||
import { useConnectionPathRole } from "@/lib/graph/flowContext";
|
||||
import { FlowUIContext, useConnectionPathRole } from "@/lib/graph/flowContext";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
/** Default min size for resizable nodes (used by NodeResizer). */
|
||||
@@ -37,8 +36,8 @@ export function BaseNode({
|
||||
resizeConstraints,
|
||||
...props
|
||||
}: BaseNodeProps) {
|
||||
const flowContext = useContext(FlowContext);
|
||||
const isFullscreenInstance = Boolean(nodeId && flowContext?.fullscreenNodeId === nodeId);
|
||||
const flowUIContext = useContext(FlowUIContext);
|
||||
const isFullscreenInstance = Boolean(nodeId && flowUIContext?.fullscreenNodeId === nodeId);
|
||||
const connectionPathRole = useConnectionPathRole(nodeId);
|
||||
const hasSize =
|
||||
dimensions &&
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useContext, useEffect } from 'react'
|
||||
import { useReactFlow } from '@xyflow/react'
|
||||
import type { Node } from '@xyflow/react'
|
||||
import FlowContext from '@/lib/graph/flowContext'
|
||||
import { GraphContext, FlowUIContext } from '@/lib/graph/flowContext'
|
||||
import { getNextNodeId, getDefaultDataForType } from '@/lib/graph/flowUtils'
|
||||
import { getDefaultStyle, getRegisteredNodeTypeIds } from '@/lib/graph/nodeRegistry'
|
||||
|
||||
@@ -14,11 +14,12 @@ function isMod(ev: KeyboardEvent) {
|
||||
/** Must be rendered inside ReactFlowProvider and FlowContext. Handles Escape, ⌘C, ⌘V, ⌘D, ⌘0. */
|
||||
export function FlowKeyboardShortcuts() {
|
||||
const { fitView, screenToFlowPosition } = useReactFlow()
|
||||
const ctx = useContext(FlowContext)
|
||||
const nodes = ctx?.nodes ?? []
|
||||
const setNodes = ctx?.setNodes
|
||||
const setConnectionFrom = ctx?.setConnectionFrom
|
||||
const flowActionsRef = ctx?.flowActionsRef
|
||||
const graphCtx = useContext(GraphContext)
|
||||
const uiCtx = useContext(FlowUIContext)
|
||||
const nodes = graphCtx?.nodes ?? []
|
||||
const setNodes = graphCtx?.setNodes
|
||||
const setConnectionFrom = uiCtx?.setConnectionFrom
|
||||
const flowActionsRef = uiCtx?.flowActionsRef
|
||||
|
||||
const pasteAtViewportCenter = useCallback(async () => {
|
||||
if (!setNodes || !screenToFlowPosition) return
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useContext, useMemo } from 'react'
|
||||
import FlowContext from '@/lib/graph/flowContext'
|
||||
import { GraphContext } from '@/lib/graph/flowContext'
|
||||
import { ArrowDownLeft, ArrowUpRight } from 'lucide-react'
|
||||
import { NodeHelpPopover } from '@/components/graph/NodeHelpPopover'
|
||||
import { getNodeType, getNodeClassificationLabel } from '@/lib/graph/nodeRegistry'
|
||||
@@ -11,7 +11,7 @@ type Props = {
|
||||
}
|
||||
|
||||
export function NodeFooterEdgeIndicators({ nodeId, nodeType, children }: Props) {
|
||||
const ctx = useContext(FlowContext)
|
||||
const ctx = useContext(GraphContext)
|
||||
const edges = ctx?.edges ?? []
|
||||
|
||||
const { inputs, outputs } = useMemo(() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useContext } from 'react'
|
||||
import { Handle, Position } from '@xyflow/react'
|
||||
import { ArrowDownLeft, ArrowUpRight } from 'lucide-react'
|
||||
import FlowContext from '@/lib/graph/flowContext'
|
||||
import { FlowUIContext } from '@/lib/graph/flowContext'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
type NodeHandleProps = {
|
||||
@@ -11,7 +11,7 @@ type NodeHandleProps = {
|
||||
}
|
||||
|
||||
export function InputHandle({ id, nodeId }: NodeHandleProps) {
|
||||
const ctx = useContext(FlowContext)
|
||||
const ctx = useContext(FlowUIContext)
|
||||
const connectionFrom = ctx?.connectionFrom ?? null
|
||||
const isValidConnection = ctx?.isValidConnection
|
||||
const isConnecting = Boolean(nodeId && connectionFrom && connectionFrom.nodeId !== nodeId)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react'
|
||||
import FlowContext from '@/lib/graph/flowContext'
|
||||
import { GraphContext, FlowUIContext } from '@/lib/graph/flowContext'
|
||||
import type { AppNode } from '@/lib/graph/nodeTypes'
|
||||
import { replaceNodeIdInGraph } from '@/lib/graph/flowUtils'
|
||||
|
||||
@@ -9,13 +9,14 @@ type Props = {
|
||||
}
|
||||
|
||||
export function NodeHeaderTitle({ nodeId, displayTitle }: Props) {
|
||||
const ctx = useContext(FlowContext)
|
||||
const nodes = ctx?.nodes ?? []
|
||||
const setNodes = ctx?.setNodes
|
||||
const edges = ctx?.edges ?? []
|
||||
const setEdges = ctx?.setEdges
|
||||
const renamingNodeId = ctx?.renamingNodeId ?? null
|
||||
const setRenamingNodeId = ctx?.setRenamingNodeId
|
||||
const graphCtx = useContext(GraphContext)
|
||||
const uiCtx = useContext(FlowUIContext)
|
||||
const nodes = graphCtx?.nodes ?? []
|
||||
const setNodes = graphCtx?.setNodes
|
||||
const edges = graphCtx?.edges ?? []
|
||||
const setEdges = graphCtx?.setEdges
|
||||
const renamingNodeId = uiCtx?.renamingNodeId ?? null
|
||||
const setRenamingNodeId = uiCtx?.setRenamingNodeId
|
||||
|
||||
const [inputValue, setInputValue] = useState(nodeId)
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* it is taken from getNodeType(nodeType)?.getNodeMenuExtraContent?.(nodeId, data).
|
||||
*/
|
||||
import React, { useCallback, useContext, useMemo } from 'react'
|
||||
import FlowContext from '@/lib/graph/flowContext'
|
||||
import { GraphContext, FlowUIContext } from '@/lib/graph/flowContext'
|
||||
import { getNodeType } from '@/lib/graph/nodeRegistry'
|
||||
import {
|
||||
Menubar,
|
||||
@@ -43,12 +43,13 @@ type Props = {
|
||||
}
|
||||
|
||||
export function NodeMenubar({ nodeId, nodeType, editInputsContent, inputsMenuContent, insertTagsContent, insertMenuLabel = 'Insert', insertContentDirect, insertTagsLabel = 'Tags', nodeMenuExtraContent: nodeMenuExtraContentProp, outputMenuContent, dataMenuContent }: Props) {
|
||||
const ctx = useContext(FlowContext)
|
||||
const nodes = ctx?.nodes ?? []
|
||||
const setNodes = ctx?.setNodes
|
||||
const setEdges = ctx?.setEdges
|
||||
const graphCtx = useContext(GraphContext)
|
||||
const uiCtx = useContext(FlowUIContext)
|
||||
const nodes = graphCtx?.nodes ?? []
|
||||
const setNodes = graphCtx?.setNodes
|
||||
const setEdges = graphCtx?.setEdges
|
||||
|
||||
const edges = ctx?.edges ?? []
|
||||
const edges = graphCtx?.edges ?? []
|
||||
const node = nodes.find((n: any) => n.id === nodeId)
|
||||
const nodeMenuExtraContent = useMemo(
|
||||
() => nodeMenuExtraContentProp ?? getNodeType(nodeType)?.getNodeMenuExtraContent?.(nodeId, node?.data ?? {}),
|
||||
@@ -64,8 +65,8 @@ export function NodeMenubar({ nodeId, nodeType, editInputsContent, inputsMenuCon
|
||||
}, [nodeId, setNodes, setEdges])
|
||||
|
||||
const onRename = useCallback(() => {
|
||||
ctx?.setRenamingNodeId?.(nodeId)
|
||||
}, [nodeId, ctx])
|
||||
uiCtx?.setRenamingNodeId?.(nodeId)
|
||||
}, [nodeId, uiCtx])
|
||||
|
||||
return (
|
||||
<Menubar className="h-auto min-h-0 flex items-center bg-none p-1 border-t-0 border-l-0 border-r-0 border-b border-b-secondary shadow-none rounded-none text-muted-foreground">
|
||||
|
||||
Reference in New Issue
Block a user