From 5e41e975eb7de336f1c63048b48986dfb8f4fc5f Mon Sep 17 00:00:00 2001 From: braks <78412429+bcakmakoglu@users.noreply.github.com> Date: Fri, 24 Mar 2023 22:03:19 +0100 Subject: [PATCH 1/7] feat(core): add `updatable` prop to `Edge` types --- packages/core/src/types/edges.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/core/src/types/edges.ts b/packages/core/src/types/edges.ts index 143c7fa6..01f73a86 100644 --- a/packages/core/src/types/edges.ts +++ b/packages/core/src/types/edges.ts @@ -36,8 +36,11 @@ type DefaultEdge = { ariaLabel?: string; interactionWidth?: number; focusable?: boolean; + updatable?: EdgeUpdatable; } & EdgeLabelOptions; +export type EdgeUpdatable = boolean | 'target' | 'source'; + export type SmoothStepPathOptions = { offset?: number; borderRadius?: number; From 82ee1415ef329bc127e3ed3dc36a5e61cf3eb9b7 Mon Sep 17 00:00:00 2001 From: braks <78412429+bcakmakoglu@users.noreply.github.com> Date: Fri, 24 Mar 2023 22:03:48 +0100 Subject: [PATCH 2/7] feat(core): add global `edgesUpdatable` prop --- packages/core/src/store/initialState.ts | 1 + packages/core/src/types/general.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/core/src/store/initialState.ts b/packages/core/src/store/initialState.ts index 2722038d..92192e9e 100644 --- a/packages/core/src/store/initialState.ts +++ b/packages/core/src/store/initialState.ts @@ -48,6 +48,7 @@ const initialState: ReactFlowStore = { nodesConnectable: true, nodesFocusable: true, edgesFocusable: true, + edgesUpdatable: false, elementsSelectable: true, elevateNodesOnSelect: true, fitViewOnInit: false, diff --git a/packages/core/src/types/general.ts b/packages/core/src/types/general.ts index fab391d0..fec29371 100644 --- a/packages/core/src/types/general.ts +++ b/packages/core/src/types/general.ts @@ -183,6 +183,7 @@ export type ReactFlowStore = { nodesConnectable: boolean; nodesFocusable: boolean; edgesFocusable: boolean; + edgesUpdatable: boolean; elementsSelectable: boolean; elevateNodesOnSelect: boolean; From b06629e75e6c3cd0ad30b69bd0a5ae23b28e116b Mon Sep 17 00:00:00 2001 From: braks <78412429+bcakmakoglu@users.noreply.github.com> Date: Fri, 24 Mar 2023 22:04:21 +0100 Subject: [PATCH 3/7] feat(core): allow setting edges updatable to bool, `source` or `target` --- .../core/src/components/Edges/wrapEdge.tsx | 44 +++++++++---------- .../core/src/container/EdgeRenderer/index.tsx | 5 ++- packages/core/src/types/edges.ts | 1 + 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/packages/core/src/components/Edges/wrapEdge.tsx b/packages/core/src/components/Edges/wrapEdge.tsx index 607f2c5a..a5014af9 100644 --- a/packages/core/src/components/Edges/wrapEdge.tsx +++ b/packages/core/src/components/Edges/wrapEdge.tsx @@ -55,6 +55,7 @@ export default (EdgeComponent: ComponentType) => { rfId, ariaLabel, isFocusable, + isUpdatable, pathOptions, interactionWidth, }: WrapEdgeProps): JSX.Element | null => { @@ -138,7 +139,6 @@ export default (EdgeComponent: ComponentType) => { const onEdgeUpdaterMouseOut = () => setUpdateHover(false); const inactive = !elementsSelectable && !onClick; - const handleEdgeUpdate = typeof onEdgeUpdate !== 'undefined'; const onKeyDown = (event: KeyboardEvent) => { if (elementSelectionKeys.includes(event.key) && elementsSelectable) { @@ -205,28 +205,28 @@ export default (EdgeComponent: ComponentType) => { interactionWidth={interactionWidth} /> )} - {handleEdgeUpdate && ( + {isUpdatable && ( <> - - + {isUpdatable === 'source' && } + {isUpdatable === 'target' && } )} diff --git a/packages/core/src/container/EdgeRenderer/index.tsx b/packages/core/src/container/EdgeRenderer/index.tsx index 09b8f0c6..26a12c1c 100644 --- a/packages/core/src/container/EdgeRenderer/index.tsx +++ b/packages/core/src/container/EdgeRenderer/index.tsx @@ -39,6 +39,7 @@ type EdgeRendererProps = Pick< const selector = (s: ReactFlowState) => ({ nodesConnectable: s.nodesConnectable, edgesFocusable: s.edgesFocusable, + edgesUpdatable: s.edgesUpdatable, elementsSelectable: s.elementsSelectable, width: s.width, height: s.height, @@ -66,7 +67,7 @@ const EdgeRenderer = ({ onEdgeUpdateEnd, children, }: EdgeRendererProps) => { - const { edgesFocusable, elementsSelectable, width, height, connectionMode, nodeInternals, onError } = useStore( + const { edgesFocusable, edgesUpdatable, elementsSelectable, width, height, connectionMode, nodeInternals, onError } = useStore( selector, shallow ); @@ -114,6 +115,7 @@ const EdgeRenderer = ({ const sourcePosition = sourceHandle?.position || Position.Bottom; const targetPosition = targetHandle?.position || Position.Top; const isFocusable = !!(edge.focusable || (edgesFocusable && typeof edge.focusable === 'undefined')); + const isUpdatable = edge.updatable || (edgesUpdatable && typeof edge.updatable === 'undefined'); if (!sourceHandle || !targetHandle) { onError?.('008', errorMessages['error008'](sourceHandle, edge)); @@ -173,6 +175,7 @@ const EdgeRenderer = ({ rfId={rfId} ariaLabel={edge.ariaLabel} isFocusable={isFocusable} + isUpdatable={isUpdatable} pathOptions={'pathOptions' in edge ? edge.pathOptions : undefined} interactionWidth={edge.interactionWidth} /> diff --git a/packages/core/src/types/edges.ts b/packages/core/src/types/edges.ts index 01f73a86..1a21b377 100644 --- a/packages/core/src/types/edges.ts +++ b/packages/core/src/types/edges.ts @@ -91,6 +91,7 @@ export type WrapEdgeProps = Omit, 'sourceHandle' | 'targetHandl onEdgeUpdateEnd?: (event: MouseEvent | TouchEvent, edge: Edge, handleType: HandleType) => void; rfId?: string; isFocusable: boolean; + isUpdatable: EdgeUpdatable; pathOptions?: BezierPathOptions | SmoothStepPathOptions; }; From 449c3055e0e7e8d56ef845029070ff522049dec5 Mon Sep 17 00:00:00 2001 From: braks <78412429+bcakmakoglu@users.noreply.github.com> Date: Fri, 24 Mar 2023 22:08:05 +0100 Subject: [PATCH 4/7] chore(core): cleanup --- packages/core/src/components/Edges/wrapEdge.tsx | 12 ++++++++---- packages/core/src/container/EdgeRenderer/index.tsx | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/core/src/components/Edges/wrapEdge.tsx b/packages/core/src/components/Edges/wrapEdge.tsx index a5014af9..cb7d987f 100644 --- a/packages/core/src/components/Edges/wrapEdge.tsx +++ b/packages/core/src/components/Edges/wrapEdge.tsx @@ -207,7 +207,8 @@ export default (EdgeComponent: ComponentType) => { )} {isUpdatable && ( <> - {isUpdatable === 'source' && ) => { onMouseEnter={onEdgeUpdaterMouseEnter} onMouseOut={onEdgeUpdaterMouseOut} type="source" - />} - {isUpdatable === 'target' && + )} + {(isUpdatable === 'target' || isUpdatable === true) && ( + ) => { onMouseEnter={onEdgeUpdaterMouseEnter} onMouseOut={onEdgeUpdaterMouseOut} type="target" - />} + /> + )} )} diff --git a/packages/core/src/container/EdgeRenderer/index.tsx b/packages/core/src/container/EdgeRenderer/index.tsx index 26a12c1c..ed32e62b 100644 --- a/packages/core/src/container/EdgeRenderer/index.tsx +++ b/packages/core/src/container/EdgeRenderer/index.tsx @@ -115,7 +115,7 @@ const EdgeRenderer = ({ const sourcePosition = sourceHandle?.position || Position.Bottom; const targetPosition = targetHandle?.position || Position.Top; const isFocusable = !!(edge.focusable || (edgesFocusable && typeof edge.focusable === 'undefined')); - const isUpdatable = edge.updatable || (edgesUpdatable && typeof edge.updatable === 'undefined'); + const isUpdatable = edge.updatable || typeof onEdgeUpdate !== 'undefined' || (edgesUpdatable && typeof edge.updatable === 'undefined'); if (!sourceHandle || !targetHandle) { onError?.('008', errorMessages['error008'](sourceHandle, edge)); From 5f2f5db5199d09cd2a04273957a85fd6b76025ea Mon Sep 17 00:00:00 2001 From: braks <78412429+bcakmakoglu@users.noreply.github.com> Date: Fri, 24 Mar 2023 22:23:28 +0100 Subject: [PATCH 5/7] chore(examples): update updatable edge example --- .../src/examples/UpdatableEdge/index.tsx | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/examples/vite-app/src/examples/UpdatableEdge/index.tsx b/examples/vite-app/src/examples/UpdatableEdge/index.tsx index 51760701..f9a109d1 100644 --- a/examples/vite-app/src/examples/UpdatableEdge/index.tsx +++ b/examples/vite-app/src/examples/UpdatableEdge/index.tsx @@ -36,7 +36,7 @@ const initialNodes: Node[] = [ ), }, - position: { x: 100, y: 100 }, + position: { x: 75, y: 0 }, }, { id: '3', @@ -55,9 +55,46 @@ const initialNodes: Node[] = [ width: 180, }, }, + { + id: '4', + data: { + label: ( + <> + Node D + + ), + }, + position: { x: -75, y: 100 }, + }, + { + id: '5', + data: { + label: ( + <> + Node E + + ), + }, + position: { x: 150, y: 100 }, + }, + { + id: '6', + data: { + label: ( + <> + Node F + + ), + }, + position: { x: 150, y: 250 }, + }, ]; -const initialEdges = [{ id: 'e1-2', source: '1', target: '2', label: 'This is a draggable edge' }]; +const initialEdges: Edge[] = [ + { id: 'e1-3', source: '1', target: '3', label: 'This edge can only be updated from source', updatable: 'source' }, + { id: 'e2-4', source: '2', target: '4', label: 'This edge can only be updated from target', updatable: 'target' }, + { id: 'e5-6', source: '5', target: '6', label: 'This edge can be updated from both sides' }, +]; const onInit = (reactFlowInstance: ReactFlowInstance) => reactFlowInstance.fitView(); const onEdgeUpdateStart = (_: ReactMouseEvent, edge: Edge, handleType: HandleType) => From 65b2d9ccefadc23763720369733170d56827c36b Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 27 Mar 2023 16:53:55 +0200 Subject: [PATCH 6/7] refactor(edgesUpdatable): pass to store --- packages/core/src/components/StoreUpdater/index.tsx | 3 +++ packages/core/src/container/EdgeRenderer/index.tsx | 10 +++++----- packages/core/src/container/ReactFlow/index.tsx | 2 ++ packages/core/src/store/initialState.ts | 2 +- packages/core/src/types/component-props.ts | 1 + packages/core/src/types/edges.ts | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/core/src/components/StoreUpdater/index.tsx b/packages/core/src/components/StoreUpdater/index.tsx index 4491bb94..e31fba17 100644 --- a/packages/core/src/components/StoreUpdater/index.tsx +++ b/packages/core/src/components/StoreUpdater/index.tsx @@ -20,6 +20,7 @@ type StoreUpdaterProps = Pick< | 'nodesConnectable' | 'nodesFocusable' | 'edgesFocusable' + | 'edgesUpdatable' | 'minZoom' | 'maxZoom' | 'nodeExtent' @@ -98,6 +99,7 @@ const StoreUpdater = ({ nodesConnectable, nodesFocusable, edgesFocusable, + edgesUpdatable, elevateNodesOnSelect, minZoom, maxZoom, @@ -162,6 +164,7 @@ const StoreUpdater = ({ useDirectStoreUpdater('nodesConnectable', nodesConnectable, store.setState); useDirectStoreUpdater('nodesFocusable', nodesFocusable, store.setState); useDirectStoreUpdater('edgesFocusable', edgesFocusable, store.setState); + useDirectStoreUpdater('edgesUpdatable', edgesUpdatable, store.setState); useDirectStoreUpdater('elementsSelectable', elementsSelectable, store.setState); useDirectStoreUpdater('elevateNodesOnSelect', elevateNodesOnSelect, store.setState); useDirectStoreUpdater('snapToGrid', snapToGrid, store.setState); diff --git a/packages/core/src/container/EdgeRenderer/index.tsx b/packages/core/src/container/EdgeRenderer/index.tsx index ed32e62b..9f7a2f1b 100644 --- a/packages/core/src/container/EdgeRenderer/index.tsx +++ b/packages/core/src/container/EdgeRenderer/index.tsx @@ -67,10 +67,8 @@ const EdgeRenderer = ({ onEdgeUpdateEnd, children, }: EdgeRendererProps) => { - const { edgesFocusable, edgesUpdatable, elementsSelectable, width, height, connectionMode, nodeInternals, onError } = useStore( - selector, - shallow - ); + const { edgesFocusable, edgesUpdatable, elementsSelectable, width, height, connectionMode, nodeInternals, onError } = + useStore(selector, shallow); const edgeTree = useVisibleEdges(onlyRenderVisibleElements, nodeInternals, elevateEdgesOnSelect); if (!width) { @@ -115,7 +113,9 @@ const EdgeRenderer = ({ const sourcePosition = sourceHandle?.position || Position.Bottom; const targetPosition = targetHandle?.position || Position.Top; const isFocusable = !!(edge.focusable || (edgesFocusable && typeof edge.focusable === 'undefined')); - const isUpdatable = edge.updatable || typeof onEdgeUpdate !== 'undefined' || (edgesUpdatable && typeof edge.updatable === 'undefined'); + const isUpdatable = + typeof onEdgeUpdate !== 'undefined' && + (edge.updatable || (edgesUpdatable && typeof edge.updatable === 'undefined')); if (!sourceHandle || !targetHandle) { onError?.('008', errorMessages['error008'](sourceHandle, edge)); diff --git a/packages/core/src/container/ReactFlow/index.tsx b/packages/core/src/container/ReactFlow/index.tsx index 9fa23f9c..1d36123d 100644 --- a/packages/core/src/container/ReactFlow/index.tsx +++ b/packages/core/src/container/ReactFlow/index.tsx @@ -115,6 +115,7 @@ const ReactFlow = forwardRef( nodesFocusable, nodeOrigin = initNodeOrigin, edgesFocusable, + edgesUpdatable, elementsSelectable, defaultViewport = initDefaultViewport, minZoom = 0.5, @@ -266,6 +267,7 @@ const ReactFlow = forwardRef( nodesConnectable={nodesConnectable} nodesFocusable={nodesFocusable} edgesFocusable={edgesFocusable} + edgesUpdatable={edgesUpdatable} elementsSelectable={elementsSelectable} elevateNodesOnSelect={elevateNodesOnSelect} minZoom={minZoom} diff --git a/packages/core/src/store/initialState.ts b/packages/core/src/store/initialState.ts index 92192e9e..0223df7c 100644 --- a/packages/core/src/store/initialState.ts +++ b/packages/core/src/store/initialState.ts @@ -48,7 +48,7 @@ const initialState: ReactFlowStore = { nodesConnectable: true, nodesFocusable: true, edgesFocusable: true, - edgesUpdatable: false, + edgesUpdatable: true, elementsSelectable: true, elevateNodesOnSelect: true, fitViewOnInit: false, diff --git a/packages/core/src/types/component-props.ts b/packages/core/src/types/component-props.ts index cae9da3b..46364257 100644 --- a/packages/core/src/types/component-props.ts +++ b/packages/core/src/types/component-props.ts @@ -112,6 +112,7 @@ export type ReactFlowProps = HTMLAttributes & { nodesFocusable?: boolean; nodeOrigin?: NodeOrigin; edgesFocusable?: boolean; + edgesUpdatable?: boolean; initNodeOrigin?: NodeOrigin; elementsSelectable?: boolean; selectNodesOnDrag?: boolean; diff --git a/packages/core/src/types/edges.ts b/packages/core/src/types/edges.ts index 1a21b377..7358b0e8 100644 --- a/packages/core/src/types/edges.ts +++ b/packages/core/src/types/edges.ts @@ -39,7 +39,7 @@ type DefaultEdge = { updatable?: EdgeUpdatable; } & EdgeLabelOptions; -export type EdgeUpdatable = boolean | 'target' | 'source'; +export type EdgeUpdatable = boolean | HandleType; export type SmoothStepPathOptions = { offset?: number; From c22e1c28c5555a638c2a8e82c3bfc986b3965d36 Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 27 Mar 2023 16:55:24 +0200 Subject: [PATCH 7/7] chore(changeset): add --- .changeset/violet-houses-argue.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/violet-houses-argue.md diff --git a/.changeset/violet-houses-argue.md b/.changeset/violet-houses-argue.md new file mode 100644 index 00000000..0ae30058 --- /dev/null +++ b/.changeset/violet-houses-argue.md @@ -0,0 +1,7 @@ +--- +'@reactflow/background': minor +'@reactflow/core': minor +'@reactflow/minimap': minor +--- + +edges: add updatable option