From 7a1617d71d85586ca417862826cfd936ce924c73 Mon Sep 17 00:00:00 2001 From: moklick Date: Thu, 25 Jan 2024 12:24:00 +0100 Subject: [PATCH] fix(react): apply defaultEdgeOptions marker closes #3826 --- examples/react/src/examples/Edges/index.tsx | 10 +++++++ packages/react/CHANGELOG.md | 3 +- .../EdgeRenderer/MarkerDefinitions.tsx | 29 +++++++++---------- packages/svelte/CHANGELOG.md | 3 +- packages/system/src/utils/marker.ts | 21 ++++++++++---- 5 files changed, 44 insertions(+), 22 deletions(-) diff --git a/examples/react/src/examples/Edges/index.tsx b/examples/react/src/examples/Edges/index.tsx index d6870621..bbba30fb 100644 --- a/examples/react/src/examples/Edges/index.tsx +++ b/examples/react/src/examples/Edges/index.tsx @@ -175,6 +175,15 @@ const edgeTypes: EdgeTypes = { custom2: CustomEdge2, }; +const defaultEdgeOptions = { + markerEnd: { + type: MarkerType.ArrowClosed, + color: 'red', + width: 20, + height: 20, + }, +}; + const EdgesFlow = () => { const [nodes, , onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); @@ -197,6 +206,7 @@ const EdgesFlow = () => { onEdgeMouseMove={onEdgeMouseMove} onEdgeMouseLeave={onEdgeMouseLeave} onDelete={console.log} + defaultEdgeOptions={defaultEdgeOptions} > diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index f47f7ef4..9b83293c 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -6,7 +6,8 @@ - selection box is not interrupted by selectionKey being let go - fix `OnNodeDrag` type -- refactor(handles): do not use fallback handle if an id is being used #3409 +- do not use fallback handle if a specific id is being used +- fix `defaultEdgeOptions` markers not being applied ## 12.0.0-next.7 diff --git a/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx b/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx index a4696e5b..5b6194c5 100644 --- a/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx +++ b/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx @@ -1,9 +1,8 @@ -import { memo, useCallback } from 'react'; +import { memo, useMemo } from 'react'; import { type MarkerProps, createMarkerIds } from '@xyflow/system'; import { useStore } from '../../hooks/useStore'; import { useMarkerSymbol } from './MarkerSymbols'; -import type { ReactFlowState } from '../../types'; type MarkerDefinitionsProps = { defaultColor: string; @@ -43,23 +42,23 @@ const Marker = ({ ); }; -const markerSelector = - ({ defaultColor, rfId }: { defaultColor: string; rfId?: string }) => - (s: ReactFlowState) => { - const markers = createMarkerIds(s.edges, { id: rfId, defaultColor }); - - return markers; - }; - -const markersEqual = (a: MarkerProps[], b: MarkerProps[]) => - // the id includes all marker options, so we just need to look at that part of the marker - !(a.length !== b.length || a.some((m, i) => m.id !== b[i].id)); - // when you have multiple flows on a page and you hide the first one, the other ones have no markers anymore // when they do have markers with the same ids. To prevent this the user can pass a unique id to the react flow wrapper // that we can then use for creating our unique marker ids const MarkerDefinitions = ({ defaultColor, rfId }: MarkerDefinitionsProps) => { - const markers = useStore(useCallback(markerSelector({ defaultColor, rfId }), [defaultColor, rfId]), markersEqual); + const edges = useStore((s) => s.edges); + const defaultEdgeOptions = useStore((s) => s.defaultEdgeOptions); + + const markers = useMemo(() => { + const markers = createMarkerIds(edges, { + id: rfId, + defaultColor, + defaultMarkerStart: defaultEdgeOptions?.markerStart, + defaultMarkerEnd: defaultEdgeOptions?.markerEnd, + }); + + return markers; + }, [edges, defaultEdgeOptions, rfId, defaultColor]); if (!markers.length) { return null; diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 6ca5483e..4bdc8461 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -11,7 +11,8 @@ - selection box is not interrupted by selectionKey being let go - Edge label has a default background and is clickable -- refactor(handles): do not use fallback handle if an id is being used #3409 +- do not use fallback handle if a specific id is being used +- use correct id for `` data-id attribute ## 0.0.34 diff --git a/packages/system/src/utils/marker.ts b/packages/system/src/utils/marker.ts index 0a191276..834f17ef 100644 --- a/packages/system/src/utils/marker.ts +++ b/packages/system/src/utils/marker.ts @@ -19,21 +19,32 @@ export function getMarkerId(marker: EdgeMarkerType | undefined, id?: string | nu export function createMarkerIds( edges: EdgeBase[], - { id, defaultColor }: { id?: string | null; defaultColor?: string } + { + id, + defaultColor, + defaultMarkerStart, + defaultMarkerEnd, + }: { + id?: string | null; + defaultColor?: string; + defaultMarkerStart?: EdgeMarkerType; + defaultMarkerEnd?: EdgeMarkerType; + } ) { - const ids: string[] = []; + const ids = new Set(); return edges .reduce((markers, edge) => { - [edge.markerStart, edge.markerEnd].forEach((marker) => { + [edge.markerStart || defaultMarkerStart, edge.markerEnd || defaultMarkerEnd].forEach((marker) => { if (marker && typeof marker === 'object') { const markerId = getMarkerId(marker, id); - if (!ids.includes(markerId)) { + if (!ids.has(markerId)) { markers.push({ id: markerId, color: marker.color || defaultColor, ...marker }); - ids.push(markerId); + ids.add(markerId); } } }); + return markers; }, []) .sort((a, b) => a.id.localeCompare(b.id));