Make an endpoint follow the pointer, and recede further at rest
Two things from using it. The label only jumped to its new place on release: its position comes from a memo of ours rather than React Flow's own store, so nothing moved it until the drag had already finished. It is now updated on every drag frame, with the write to storage still happening once at the end rather than once per pixel. The edges deliberately do not depend on that position — an endpoint's edges follow from which messages it touches, never from where it sits — so dragging one no longer rebuilds the edge array on every frame. And they sit further back at rest, so the nodes read first. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011LF61rxW1FG5YCD2J9YqjY
This commit is contained in:
@@ -433,10 +433,13 @@ function FlowEditorInner({
|
||||
)
|
||||
|
||||
// Edges follow from the name bindings, so they are derived, never stored.
|
||||
// Kept off `external` deliberately: an endpoint's edges depend on which
|
||||
// messages it touches, never on where it sits, so dragging one must not
|
||||
// rebuild the edge array on every frame.
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: the key is the dependency; the array identity changes on every drag frame.
|
||||
const edges = useMemo(
|
||||
() => [...deriveEdges(definitions, flowName), ...external.edges],
|
||||
[key, flowName, external],
|
||||
[key, flowName, detail.endpoints],
|
||||
)
|
||||
|
||||
const shownNodes = useMemo(
|
||||
@@ -740,13 +743,21 @@ function FlowEditorInner({
|
||||
nodes={shownNodes}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChange}
|
||||
onNodeDrag={(_event, _node, dragged) => {
|
||||
// An endpoint's position is ours, not React Flow's, so it only
|
||||
// follows the pointer if we move it every frame.
|
||||
const endpoints = dragged.filter(isEndpointNode)
|
||||
if (!endpoints.length) return
|
||||
setMoved((current) => {
|
||||
const next = { ...current }
|
||||
for (const node of endpoints) next[node.id] = node.position
|
||||
return next
|
||||
})
|
||||
}}
|
||||
onNodeDragStop={(_event, _node, dragged) => {
|
||||
for (const node of dragged.filter(isEndpointNode)) {
|
||||
// Written once at the end; every frame would be a write per pixel.
|
||||
rememberPlacement(flowName, node.id, node.position)
|
||||
setMoved((current) => ({
|
||||
...current,
|
||||
[node.id]: node.position,
|
||||
}))
|
||||
}
|
||||
const own = dragged.filter(isDocumentNode)
|
||||
if (own.length) commit(definitions, mergeDragged(canvasNodes, own))
|
||||
|
||||
Reference in New Issue
Block a user