diff --git a/.changeset/thirty-owls-float.md b/.changeset/thirty-owls-float.md new file mode 100644 index 00000000..bc2ef74e --- /dev/null +++ b/.changeset/thirty-owls-float.md @@ -0,0 +1,7 @@ +--- +'@xyflow/react': patch +'@xyflow/svelte': patch +'@xyflow/system': patch +--- + +Make arrow heads markers fallback to --xy-edge-stroke CSS variable when passing null as marker color diff --git a/examples/react/src/examples/Edges/index.tsx b/examples/react/src/examples/Edges/index.tsx index 6e18d24a..c4f9fb69 100644 --- a/examples/react/src/examples/Edges/index.tsx +++ b/examples/react/src/examples/Edges/index.tsx @@ -70,6 +70,30 @@ const initialNodes: Node[] = [ data: { label: 'Output 10' }, position: { x: 50, y: 400 }, }, + { + id: '11', + type: 'output', + data: { label: 'Output 11' }, + position: { x: 825, y: 400 }, + }, + { + id: '12', + type: 'output', + data: { label: 'Output 12' }, + position: { x: 825, y: 300 }, + }, + { + id: '13', + type: 'output', + data: { label: 'Output 13' }, + position: { x: 900, y: 200 }, + }, + { + id: '14', + type: 'output', + data: { label: 'Output 14' }, + position: { x: 825, y: 100 }, + }, ]; const initialEdges: Edge[] = [ @@ -182,6 +206,57 @@ const initialEdges: Edge[] = [ height: 20, }, }, + { + id: 'e4-11', + source: '4', + target: '11', + label: 'Explicit Blue Prop Color (should override CSS)', + className: 'css-variable-edge', + markerEnd: { + type: MarkerType.ArrowClosed, + color: '#0000ff', + width: 40, + height: 40, + }, + }, + { + id: 'e4-12', + source: '4', + target: '12', + label: 'Marker explicitly undefined Color (defaults to none)', + className: 'css-variable-edge', + markerEnd: { + type: MarkerType.ArrowClosed, + color: undefined, + width: 40, + height: 40, + }, + }, + { + id: 'e4-13', + source: '4', + target: '13', + label: 'Marker null Color (should use `--xy-edge-stroke` CSS variable)', + className: 'css-variable-edge', + markerEnd: { + type: MarkerType.ArrowClosed, + color: null, + width: 40, + height: 40, + }, + }, + { + id: 'e4-14', + source: '4', + target: '14', + label: 'Marker implicitly undefined Color (defaults to defaultMarkerColor)', + className: 'css-variable-edge', + markerEnd: { + type: MarkerType.ArrowClosed, + width: 40, + height: 40, + }, + }, ]; const edgeTypes: EdgeTypes = { @@ -205,28 +280,41 @@ const EdgesFlow = () => { const onConnect = useCallback((params: Connection | Edge) => setEdges((eds) => addEdge(params, eds)), [setEdges]); return ( - - - - - + <> + + + + + + + ); }; diff --git a/examples/svelte/src/routes/examples/edges/+page.svelte b/examples/svelte/src/routes/examples/edges/+page.svelte index 18c21a14..17d46823 100644 --- a/examples/svelte/src/routes/examples/edges/+page.svelte +++ b/examples/svelte/src/routes/examples/edges/+page.svelte @@ -51,6 +51,30 @@ type: 'output', data: { label: 'Output 9' }, position: { x: 675, y: 500 } + }, + { + id: '10', + type: 'output', + data: { label: 'Output 10' }, + position: { x: 825, y: 400 } + }, + { + id: '11', + type: 'output', + data: { label: 'Output 11' }, + position: { x: 825, y: 300 } + }, + { + id: '12', + type: 'output', + data: { label: 'Output 12' }, + position: { x: 900, y: 200 } + }, + { + id: '13', + type: 'output', + data: { label: 'Output 13' }, + position: { x: 825, y: 100 } } ]); @@ -129,6 +153,55 @@ label: 'hi', labelStyle: 'background: red; font-weight: 700; padding: 5px;', style: 'stroke: #ffcc0' + }, + { + id: 'e4-10', + source: '4', + target: '10', + label: 'Explicit Prop Blue Color (should override CSS)', + markerEnd: { + type: MarkerType.ArrowClosed, + color: '#0000ff', + width: 40, + height: 40 + } + }, + { + id: 'e4-11', + source: '4', + target: '11', + label: 'Marker explicitly undefined Color (defaults to none)', + className: 'css-variable-edge', + markerEnd: { + type: MarkerType.ArrowClosed, + color: undefined, + width: 40, + height: 40 + } + }, + { + id: 'e4-12', + source: '4', + target: '12', + label: 'Marker null Color (should use `--xy-edge-stroke` CSS variable)', + markerEnd: { + type: MarkerType.ArrowClosed, + color: null, + width: 40, + height: 40 + } + }, + { + id: 'e4-13', + source: '4', + target: '13', + label: 'Marker implicitly undefined Color (defaults to defaultMarkerColor)', + className: 'css-variable-edge', + markerEnd: { + type: MarkerType.ArrowClosed, + width: 40, + height: 40 + } } ]); @@ -141,6 +214,15 @@ return `edge-${connection.source}-${connection.target}}`; } + const defaultEdgeOptions = { + markerEnd: { + type: MarkerType.ArrowClosed, + color: 'red', + width: 20, + height: 20 + } + }; + $inspect(edges); @@ -149,6 +231,7 @@ bind:edges {edgeTypes} fitView + {defaultEdgeOptions} nodeDragThreshold={2} onbeforeconnect={(connection) => { console.log('on edge create', connection); @@ -158,8 +241,17 @@ id: getEdgeId(connection) }; }} + defaultMarkerColor={'purple'} > + + diff --git a/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx b/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx index 1c12775d..3cc39267 100644 --- a/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx +++ b/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx @@ -5,7 +5,7 @@ import { useStore } from '../../hooks/useStore'; import { useMarkerSymbol } from './MarkerSymbols'; type MarkerDefinitionsProps = { - defaultColor: string; + defaultColor: string | null; rfId?: string; }; diff --git a/packages/react/src/container/EdgeRenderer/MarkerSymbols.tsx b/packages/react/src/container/EdgeRenderer/MarkerSymbols.tsx index d4244d83..089cda47 100644 --- a/packages/react/src/container/EdgeRenderer/MarkerSymbols.tsx +++ b/packages/react/src/container/EdgeRenderer/MarkerSymbols.tsx @@ -6,33 +6,21 @@ import { useStoreApi } from '../../hooks/useStore'; type SymbolProps = Omit; const ArrowSymbol = ({ color = 'none', strokeWidth = 1 }: SymbolProps) => { - return ( - - ); + const style = { + strokeWidth, + ...(color && { stroke: color }), + }; + + return ; }; const ArrowClosedSymbol = ({ color = 'none', strokeWidth = 1 }: SymbolProps) => { - return ( - - ); + const style = { + strokeWidth, + ...(color && { stroke: color, fill: color }), + }; + + return ; }; export const MarkerSymbols = { diff --git a/packages/react/src/types/component-props.ts b/packages/react/src/types/component-props.ts index 16d4aa58..e0948739 100644 --- a/packages/react/src/types/component-props.ts +++ b/packages/react/src/types/component-props.ts @@ -139,7 +139,12 @@ export interface ReactFlowProps void; + onReconnectEnd?: ( + event: MouseEvent | TouchEvent, + edge: EdgeType, + handleType: HandleType, + connectionState: FinalConnectionState + ) => void; /** * Use this event handler to add interactivity to a controlled flow. * It is called on node drag, select, and move. @@ -494,9 +499,10 @@ export interface ReactFlowProps {#if type === MarkerType.Arrow} {:else if type === MarkerType.ArrowClosed} {/if} diff --git a/packages/svelte/src/lib/container/SvelteFlow/types.ts b/packages/svelte/src/lib/container/SvelteFlow/types.ts index ae8cd79f..5cd4b740 100644 --- a/packages/svelte/src/lib/container/SvelteFlow/types.ts +++ b/packages/svelte/src/lib/container/SvelteFlow/types.ts @@ -230,9 +230,10 @@ export type SvelteFlowProps< */ snapGrid?: SnapGrid; /** Color of edge markers + * You can pass `null` to use the CSS variable `--xy-edge-stroke` for the marker color. * @example "#b1b1b7" */ - defaultMarkerColor?: string; + defaultMarkerColor?: string | null; /** * Controls if all nodes should be draggable * @default true diff --git a/packages/svelte/src/lib/store/initial-store.svelte.ts b/packages/svelte/src/lib/store/initial-store.svelte.ts index a2d1ea68..702e155e 100644 --- a/packages/svelte/src/lib/store/initial-store.svelte.ts +++ b/packages/svelte/src/lib/store/initial-store.svelte.ts @@ -365,7 +365,9 @@ export function getInitialStore { return createMarkerIds(signals.edges, { defaultColor: this.defaultMarkerColor, diff --git a/packages/system/src/styles/init.css b/packages/system/src/styles/init.css index 2d342000..b1a7d14b 100644 --- a/packages/system/src/styles/init.css +++ b/packages/system/src/styles/init.css @@ -165,6 +165,13 @@ user-select: none; } } + +/* Arrowhead marker styles - use CSS custom properties as default */ +.xy-flow__arrowhead polyline { + fill: var(--xy-edge-stroke, var(--xy-edge-stroke-default)); + stroke: var(--xy-edge-stroke, var(--xy-edge-stroke-default)); +} + .xy-flow__connection { pointer-events: none; diff --git a/packages/system/src/types/edges.ts b/packages/system/src/types/edges.ts index 03001d75..42678f8c 100644 --- a/packages/system/src/types/edges.ts +++ b/packages/system/src/types/edges.ts @@ -91,7 +91,7 @@ export enum ConnectionLineType { */ export type EdgeMarker = { type: MarkerType | `${MarkerType}`; - color?: string; + color?: string | null; width?: number; height?: number; markerUnits?: string; diff --git a/packages/system/src/utils/marker.ts b/packages/system/src/utils/marker.ts index 834f17ef..9c150192 100644 --- a/packages/system/src/utils/marker.ts +++ b/packages/system/src/utils/marker.ts @@ -26,7 +26,7 @@ export function createMarkerIds( defaultMarkerEnd, }: { id?: string | null; - defaultColor?: string; + defaultColor?: string | null; defaultMarkerStart?: EdgeMarkerType; defaultMarkerEnd?: EdgeMarkerType; }