Merge pull request #5496 from xyflow/5481-nodecomponent-prop-missing-from-svelte-flow-minimap

feat(Minimap): add `nodeComponent` prop to Svelteflow
This commit is contained in:
Peter Kogo
2025-09-04 12:08:01 +02:00
committed by GitHub
7 changed files with 137 additions and 15 deletions

View File

@@ -0,0 +1,5 @@
---
"@xyflow/svelte": minor
---
Pass a custom `nodeComponent` to Svelteflow's Minimap

View File

@@ -7,6 +7,7 @@
'add-node-on-drop', 'add-node-on-drop',
'color-mode', 'color-mode',
'custom-connection-line', 'custom-connection-line',
'custom-minimap',
'customnode', 'customnode',
'dagre', 'dagre',
'detached-handle', 'detached-handle',

View File

@@ -0,0 +1,48 @@
<script lang="ts">
import {
SvelteFlow,
Background,
Controls,
MiniMap,
type Node,
type Edge,
} from '@xyflow/svelte';
import '@xyflow/svelte/dist/style.css';
import CustomMiniMapNode from './CustomMiniMapNode.svelte';
let nodes = $state.raw<Node[]>([]);
let edges = $state.raw<Edge[]>([]);
function addRandomNode() {
const nodeId = (nodes.length + 1).toString();
const newNode: Node = {
id: nodeId,
data: { label: `Node: ${nodeId}` },
position: {
x: Math.random() * (typeof window !== 'undefined' ? window.innerWidth : 800),
y: Math.random() * (typeof window !== 'undefined' ? window.innerHeight : 600),
},
type: 'default'
};
nodes = [...nodes, newNode];
}
</script>
<SvelteFlow
bind:nodes
bind:edges
onlyRenderVisibleElements={true}
>
<Controls />
<Background />
<MiniMap nodeComponent={CustomMiniMapNode} />
<button
type="button"
onclick={addRandomNode}
style="position: absolute; left: 10px; top: 10px; z-index: 4;"
>
add node
</button>
</SvelteFlow>

View File

@@ -0,0 +1,22 @@
<script lang="ts">
let {
x,
y,
width,
height,
selected,
}: {
x: number;
y: number;
width: number;
height: number;
selected?: boolean;
} = $props();
</script>
<circle
cx={x + width / 2}
cy={y + height / 2}
r={Math.min(width, height) - 2}
fill={selected ? "#ff6b6b" : "#ffcc00"}
/>

View File

@@ -27,6 +27,7 @@
nodeClass = '', nodeClass = '',
nodeBorderRadius = 5, nodeBorderRadius = 5,
nodeStrokeWidth = 2, nodeStrokeWidth = 2,
nodeComponent,
bgColor, bgColor,
maskColor, maskColor,
maskStrokeColor, maskStrokeColor,
@@ -127,6 +128,7 @@
y={node.internals.positionAbsolute.y} y={node.internals.positionAbsolute.y}
{...nodeDimesions} {...nodeDimesions}
selected={node.selected} selected={node.selected}
nodeComponent={nodeComponent}
color={nodeColorFunc?.(node)} color={nodeColorFunc?.(node)}
borderRadius={nodeBorderRadius} borderRadius={nodeBorderRadius}
strokeColor={nodeStrokeColorFunc(node)} strokeColor={nodeStrokeColorFunc(node)}

View File

@@ -1,5 +1,7 @@
<script lang="ts"> <script lang="ts">
import type { ClassValue } from 'svelte/elements'; import type { ClassValue } from 'svelte/elements';
import type { Component } from 'svelte';
import type { MiniMapNodeProps } from './types';
let { let {
x, x,
@@ -12,7 +14,8 @@
strokeColor, strokeColor,
strokeWidth = 2, strokeWidth = 2,
selected, selected,
class: className class: className,
nodeComponent
}: { }: {
x: number; x: number;
y: number; y: number;
@@ -25,20 +28,39 @@
strokeWidth?: number; strokeWidth?: number;
selected?: boolean; selected?: boolean;
class?: ClassValue; class?: ClassValue;
nodeComponent?: Component<MiniMapNodeProps>;
} = $props(); } = $props();
</script> </script>
<rect {#if nodeComponent}
class={['svelte-flow__minimap-node', className]} {@const CustomComponent = nodeComponent}
class:selected
{x} <CustomComponent
{y} {x}
rx={borderRadius} {y}
ry={borderRadius} {width}
{width} {height}
{height} {borderRadius}
style:fill={color} class={className}
style:stroke={strokeColor} {color}
style:stroke-width={strokeWidth} {shapeRendering}
shape-rendering={shapeRendering} {strokeColor}
/> {strokeWidth}
{selected}
/>
{:else}
<rect
class={['svelte-flow__minimap-node', className]}
class:selected
{x}
{y}
rx={borderRadius}
ry={borderRadius}
{width}
{height}
style:fill={color}
style:stroke={strokeColor}
style:stroke-width={strokeWidth}
shape-rendering={shapeRendering}
/>
{/if}

View File

@@ -1,9 +1,29 @@
import type { PanelPosition } from '@xyflow/system'; import type { PanelPosition } from '@xyflow/system';
import type { ClassValue, HTMLAttributes } from 'svelte/elements'; import type { ClassValue, HTMLAttributes } from 'svelte/elements';
import type { Component } from 'svelte';
import type { Node } from '$lib/types'; import type { Node } from '$lib/types';
export type GetMiniMapNodeAttribute = (node: Node) => string; export type GetMiniMapNodeAttribute = (node: Node) => string;
/**
* The props that are passed to the MiniMapNode component
*
* @public
*/
export type MiniMapNodeProps = {
x: number;
y: number;
width: number;
height: number;
borderRadius?: number;
class?: ClassValue;
color?: string;
shapeRendering?: string;
strokeColor?: string;
strokeWidth?: number;
selected?: boolean;
};
export type MiniMapProps = { export type MiniMapProps = {
/** Background color of minimap */ /** Background color of minimap */
bgColor?: string; bgColor?: string;
@@ -17,6 +37,8 @@ export type MiniMapProps = {
nodeBorderRadius?: number; nodeBorderRadius?: number;
/** Stroke width of nodes on the minimap */ /** Stroke width of nodes on the minimap */
nodeStrokeWidth?: number; nodeStrokeWidth?: number;
/** A custom component to render the nodes in the minimap. This component must render an SVG element! */
nodeComponent?: Component<MiniMapNodeProps>;
/** Color of the mask representing viewport */ /** Color of the mask representing viewport */
maskColor?: string; maskColor?: string;
/** Stroke color of the mask representing viewport */ /** Stroke color of the mask representing viewport */