feat(svelte): add BaseEdge and EdgeLabelRenderer
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
export default function (node: Element, target = 'body') {
|
||||
const targetEl = document.querySelector(target);
|
||||
|
||||
if (targetEl) {
|
||||
targetEl.appendChild(node);
|
||||
}
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
if (node.parentNode) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<script lang="ts">
|
||||
import portal from '$lib/actions/portal';
|
||||
|
||||
type $$Props = {}
|
||||
</script>
|
||||
|
||||
<div use:portal={'.react-flow__edgelabel-renderer'}>
|
||||
<slot />
|
||||
</div>
|
||||
@@ -1,44 +1,46 @@
|
||||
<script lang="ts">
|
||||
import type { SvelteComponentTyped } from 'svelte';
|
||||
import { Position } from '@reactflow/system';
|
||||
import type { BaseEdgeProps } from '$lib/types';
|
||||
import EdgeLabelRenderer from '$lib/components/EdgeLabelRenderer/index.svelte';
|
||||
|
||||
import { useStore } from '$lib/store';
|
||||
import BezierEdge from '$lib/components/edges/StraightEdge.svelte';
|
||||
import type { EdgeProps } from '$lib/types';
|
||||
type $$Props = BaseEdgeProps;
|
||||
|
||||
export let id: string;
|
||||
export let type: string = 'default';
|
||||
export let sourceX: number = 0;
|
||||
export let sourceY: number = 0;
|
||||
export let targetX: number = 0;
|
||||
export let targetY: number = 0;
|
||||
export let sourcePosition: Position = Position.Bottom;
|
||||
export let targetPosition: Position = Position.Top;
|
||||
|
||||
const { edgeTypesStore } = useStore();
|
||||
const edgeComponent: typeof SvelteComponentTyped<EdgeProps> = $edgeTypesStore[type] || BezierEdge;
|
||||
export let path: $$Props['path'];
|
||||
export let label: $$Props['label'];
|
||||
export let labelX: $$Props['labelX'];
|
||||
export let labelY: $$Props['labelY'];
|
||||
export let interactionWidth: $$Props['interactionWidth'] = 20;
|
||||
</script>
|
||||
|
||||
<g
|
||||
class="react-flow__edge"
|
||||
data-id={id}
|
||||
>
|
||||
<svelte:component
|
||||
this={edgeComponent}
|
||||
{id}
|
||||
{sourceX}
|
||||
{sourceY}
|
||||
{targetX}
|
||||
{targetY}
|
||||
{sourcePosition}
|
||||
{targetPosition}
|
||||
<path
|
||||
d={path}
|
||||
fill="none"
|
||||
class="react-flow__edge-path"
|
||||
/>
|
||||
|
||||
{#if interactionWidth}
|
||||
<path
|
||||
d={path}
|
||||
fill="none"
|
||||
stroke-opacity={0}
|
||||
stroke-width={interactionWidth}
|
||||
class="react-flow__edge-interaction"
|
||||
/>
|
||||
</g>
|
||||
{/if}
|
||||
|
||||
{#if label}
|
||||
<EdgeLabelRenderer>
|
||||
<div
|
||||
class="react-flow__edge-label"
|
||||
style:transform={`translate(-50%, -50%) translate(${labelX}px,${labelY}px)`}
|
||||
>
|
||||
{label}
|
||||
</div>
|
||||
</EdgeLabelRenderer>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.react-flow__edge :global(path) {
|
||||
stroke: #ccc;
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
.react-flow__edge-label {
|
||||
position: absolute;
|
||||
background: white;
|
||||
}
|
||||
</style>
|
||||
@@ -1,21 +1,24 @@
|
||||
<script lang="ts">
|
||||
import { getBezierPath } from '@reactflow/edge-utils';
|
||||
|
||||
import type { EdgeProps } from '$lib/types';
|
||||
|
||||
interface $$Props extends EdgeProps {}
|
||||
import BaseEdge from './BaseEdge.svelte';
|
||||
|
||||
export let id: $$Props['id'];
|
||||
export let sourceX: $$Props['sourceX'] = 0;
|
||||
export let sourceY: $$Props['sourceY'] = 0;
|
||||
export let targetX: $$Props['targetX'] = 0;
|
||||
export let targetY: $$Props['targetY'] = 0;
|
||||
export let sourcePosition: $$Props['sourcePosition'] = undefined;
|
||||
export let targetPosition: $$Props['targetPosition'] = undefined;
|
||||
type $$Props = EdgeProps;
|
||||
|
||||
$: [path] = getBezierPath({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition });
|
||||
$: [path, labelX, labelY] = getBezierPath({
|
||||
sourceX: $$props.sourceX,
|
||||
sourceY: $$props.sourceY,
|
||||
targetX: $$props.targetX,
|
||||
targetY: $$props.targetY,
|
||||
sourcePosition: $$props.sourcePosition,
|
||||
targetPosition: $$props.targetPosition,
|
||||
});
|
||||
</script>
|
||||
|
||||
<path
|
||||
d={path}
|
||||
class="react-flow__edge-path"
|
||||
/>
|
||||
<BaseEdge
|
||||
{path}
|
||||
{labelX}
|
||||
{labelY}
|
||||
{...$$props}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<script lang="ts">
|
||||
import type { SvelteComponentTyped } from 'svelte';
|
||||
import { Position } from '@reactflow/system';
|
||||
|
||||
import { useStore } from '$lib/store';
|
||||
import BezierEdge from '$lib/components/edges/StraightEdge.svelte';
|
||||
import type { EdgeProps, WrapEdgeProps } from '$lib/types';
|
||||
|
||||
type $$Props = WrapEdgeProps;
|
||||
|
||||
export let id: $$Props['id'];
|
||||
export let type: $$Props['type'] = 'default';
|
||||
export let source: $$Props['source'] = '';
|
||||
export let target: $$Props['target'] = '';
|
||||
export let sourceX: $$Props['sourceX'] = 0;
|
||||
export let sourceY: $$Props['sourceY'] = 0;
|
||||
export let targetX: $$Props['targetX'] = 0;
|
||||
export let targetY: $$Props['targetY'] = 0;
|
||||
export let sourcePosition: $$Props['sourcePosition'] = Position.Bottom;
|
||||
export let targetPosition: $$Props['targetPosition'] = Position.Top;
|
||||
export let animated: $$Props['animated'] = false;
|
||||
export let selected: $$Props['selected'] = false;
|
||||
export let label: $$Props['label'] = undefined;
|
||||
|
||||
const { edgeTypesStore } = useStore();
|
||||
const edgeComponent: typeof SvelteComponentTyped<EdgeProps> = $edgeTypesStore[type!] || BezierEdge;
|
||||
</script>
|
||||
|
||||
<g
|
||||
class="react-flow__edge"
|
||||
class:animated
|
||||
data-id={id}
|
||||
>
|
||||
<svelte:component
|
||||
this={edgeComponent}
|
||||
{id}
|
||||
{source}
|
||||
{target}
|
||||
{sourceX}
|
||||
{sourceY}
|
||||
{targetX}
|
||||
{targetY}
|
||||
{sourcePosition}
|
||||
{targetPosition}
|
||||
{animated}
|
||||
{selected}
|
||||
{label}
|
||||
/>
|
||||
</g>
|
||||
|
||||
<style>
|
||||
.react-flow__edge {
|
||||
pointer-events: visibleStroke;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.react-flow__edge :global(path) {
|
||||
stroke: #ccc;
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.animated :global(path) {
|
||||
stroke-dasharray: 5;
|
||||
animation: dashdraw 0.5s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes dashdraw {
|
||||
from {
|
||||
stroke-dashoffset: 10;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,21 +1,24 @@
|
||||
<script lang="ts">
|
||||
import { getSmoothStepPath } from '@reactflow/edge-utils';
|
||||
|
||||
import type { EdgeProps } from '$lib/types';
|
||||
|
||||
interface $$Props extends EdgeProps {}
|
||||
import BaseEdge from './BaseEdge.svelte';
|
||||
|
||||
export let id: $$Props['id'];
|
||||
export let sourceX: $$Props['sourceX'] = 0;
|
||||
export let sourceY: $$Props['sourceY'] = 0;
|
||||
export let targetX: $$Props['targetX'] = 0;
|
||||
export let targetY: $$Props['targetY'] = 0;
|
||||
export let sourcePosition: $$Props['sourcePosition'] = undefined;
|
||||
export let targetPosition: $$Props['targetPosition'] = undefined;
|
||||
type $$Props = EdgeProps;
|
||||
|
||||
$: [path] = getSmoothStepPath({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition });
|
||||
$: [path, labelX, labelY] = getSmoothStepPath({
|
||||
sourceX: $$props.sourceX,
|
||||
sourceY: $$props.sourceY,
|
||||
targetX: $$props.targetX,
|
||||
targetY: $$props.targetY,
|
||||
sourcePosition: $$props.sourcePosition,
|
||||
targetPosition: $$props.targetPosition,
|
||||
});
|
||||
</script>
|
||||
|
||||
<path
|
||||
d={path}
|
||||
class="react-flow__edge-path"
|
||||
<BaseEdge
|
||||
{path}
|
||||
{labelX}
|
||||
{labelY}
|
||||
{...$$props}
|
||||
/>
|
||||
@@ -1,19 +1,22 @@
|
||||
<script lang="ts">
|
||||
import { getStraightPath } from '@reactflow/edge-utils';
|
||||
|
||||
import type { EdgeProps } from '$lib/types';
|
||||
import BaseEdge from './BaseEdge.svelte';
|
||||
|
||||
interface $$Props extends EdgeProps {}
|
||||
type $$Props = EdgeProps;
|
||||
|
||||
export let id: $$Props['id'];
|
||||
export let sourceX: $$Props['sourceX'] = 0;
|
||||
export let sourceY: $$Props['sourceY'] = 0;
|
||||
export let targetX: $$Props['targetX'] = 0;
|
||||
export let targetY: $$Props['targetY'] = 0;
|
||||
|
||||
$: [path] = getStraightPath({ sourceX, sourceY, targetX, targetY });
|
||||
$: [path, labelX, labelY] = getStraightPath({
|
||||
sourceX: $$props.sourceX,
|
||||
sourceY: $$props.sourceY,
|
||||
targetX: $$props.targetX,
|
||||
targetY: $$props.targetY,
|
||||
});
|
||||
</script>
|
||||
|
||||
<path
|
||||
d={path}
|
||||
class="react-flow__edge-path"
|
||||
<BaseEdge
|
||||
{path}
|
||||
{labelX}
|
||||
{labelY}
|
||||
{...$$props}
|
||||
/>
|
||||
-1
@@ -85,7 +85,6 @@
|
||||
<style>
|
||||
.react-flow__node {
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
color: #222;
|
||||
text-align: center;
|
||||
border-width: 1px;
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import Edge from '$lib/components/edges/BaseEdge.svelte';
|
||||
import EdgeWrapper from '$lib/components/edges/EdgeWrapper.svelte';
|
||||
import { useStore } from '$lib/store';
|
||||
|
||||
const { edgesWithDataStore, widthStore, heightStore } = useStore();
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
<svg
|
||||
width={$widthStore}
|
||||
height={$heightStore}
|
||||
height={$heightStore}
|
||||
class="react-flow__edges"
|
||||
>
|
||||
{#each $edgesWithDataStore as edge (edge.id)}
|
||||
{#each $edgesWithDataStore as edge (edge.id)}
|
||||
<EdgeWrapper {...edge} />
|
||||
{/each}
|
||||
</svg>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { onDestroy } from 'svelte';
|
||||
|
||||
import BaseNode from '$lib/components/nodes/BaseNode.svelte';
|
||||
import NodeWrapper from '$lib/components/nodes/NodeWrapper.svelte';
|
||||
import { useStore } from '$lib/store';
|
||||
|
||||
const { nodesStore, updateNodeDimensions } = useStore();
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<div class="react-flow__nodes">
|
||||
{#each $nodesStore as node (node.id)}
|
||||
<BaseNode {...node} {resizeObserver} />
|
||||
<NodeWrapper {...node} {resizeObserver} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -68,9 +68,10 @@
|
||||
<Zoom>
|
||||
<Pane>
|
||||
<Viewport>
|
||||
<NodeSelection />
|
||||
<NodeRenderer />
|
||||
<EdgeRenderer />
|
||||
<div class="react-flow__edgelabel-renderer" />
|
||||
<NodeRenderer />
|
||||
<NodeSelection />
|
||||
</Viewport>
|
||||
<UserSelection />
|
||||
</Pane>
|
||||
@@ -92,4 +93,12 @@
|
||||
.react-flow :global(.react-flow__node-output) {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.react-flow__edgelabel-renderer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
</style>
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
type NodeDimensionUpdate,
|
||||
Position,
|
||||
internalsSymbol,
|
||||
SelectionMode,
|
||||
type NodeOrigin,
|
||||
type D3ZoomInstance,
|
||||
type D3SelectionInstance,
|
||||
@@ -16,17 +17,11 @@ import {
|
||||
import { fitView, getConnectedEdges, getD3Transition, getDimensions } from '@reactflow/utils';
|
||||
|
||||
import { getHandleBounds } from '../../utils';
|
||||
import {
|
||||
getEdgePositions,
|
||||
getHandle,
|
||||
getNodeData,
|
||||
type EdgePosition
|
||||
} from '$lib/container/EdgeRenderer/utils';
|
||||
import { SelectionMode } from 'reactflow';
|
||||
import { getEdgePositions, getHandle, getNodeData } from '$lib/container/EdgeRenderer/utils';
|
||||
import DefaultNode from '$lib/components/nodes/DefaultNode.svelte';
|
||||
import InputNode from '$lib/components/nodes/InputNode.svelte';
|
||||
import OutputNode from '$lib/components/nodes/OutputNode.svelte';
|
||||
import type { EdgeTypes, NodeTypes, Node, Edge } from '$lib/types';
|
||||
import type { EdgeTypes, NodeTypes, Node, Edge, WrapEdgeProps } from '$lib/types';
|
||||
import BezierEdge from '$lib/components/edges/BezierEdge.svelte';
|
||||
import StraightEdge from '$lib/components/edges/StraightEdge.svelte';
|
||||
import SmoothStepEdge from '$lib/components/edges/SmoothStepEdge.svelte';
|
||||
@@ -42,11 +37,6 @@ type CreateStoreProps = {
|
||||
id?: string;
|
||||
};
|
||||
|
||||
export type EdgeWithData = EdgePosition & {
|
||||
id: string;
|
||||
type: string;
|
||||
};
|
||||
|
||||
type SvelteFlowStore = {
|
||||
nodesStore: Writable<Node[]>;
|
||||
edgesStore: Writable<Edge[]>;
|
||||
@@ -57,7 +47,7 @@ type SvelteFlowStore = {
|
||||
selection: D3SelectionInstance | null;
|
||||
}>;
|
||||
transformStore: Writable<Transform>;
|
||||
edgesWithDataStore: Readable<EdgeWithData[]>;
|
||||
edgesWithDataStore: Readable<WrapEdgeProps[]>;
|
||||
idStore: Writable<string>;
|
||||
nodeOriginStore: Writable<NodeOrigin>;
|
||||
draggingStore: Writable<boolean>;
|
||||
@@ -162,16 +152,24 @@ export function createStore({
|
||||
targetPosition
|
||||
);
|
||||
|
||||
// we nee to do this to match the types
|
||||
const sourceHandleId = edge.sourceHandle;
|
||||
const targetHandleId = edge.targetHandle;
|
||||
|
||||
return {
|
||||
id: edge.id,
|
||||
...edge,
|
||||
type: edgeType,
|
||||
sourceX,
|
||||
sourceY,
|
||||
targetX,
|
||||
targetY
|
||||
targetY,
|
||||
sourcePosition,
|
||||
targetPosition,
|
||||
sourceHandleId,
|
||||
targetHandleId
|
||||
};
|
||||
})
|
||||
.filter((e) => e !== null) as EdgeWithData[];
|
||||
.filter((e) => e !== null) as WrapEdgeProps[];
|
||||
});
|
||||
|
||||
function setEdges(edges: Edge[]) {
|
||||
@@ -359,6 +357,7 @@ export function createStore({
|
||||
|
||||
function addSelectedNodes(ids: string[]) {
|
||||
selectionRectStore.set(null);
|
||||
selectionRectModeStore.set(null);
|
||||
|
||||
if (get(multiselectionKeyPressedStore)) {
|
||||
// @todo handle multiselection key
|
||||
|
||||
@@ -1,25 +1,4 @@
|
||||
import type { SvelteComponentTyped } from 'svelte';
|
||||
import type { Position } from '@reactflow/system';
|
||||
|
||||
export type Edge = {
|
||||
id: string;
|
||||
type: string;
|
||||
source: string;
|
||||
target: string;
|
||||
sourceHandle?: string;
|
||||
targetHandle?: string;
|
||||
selected?: boolean;
|
||||
deletable?: boolean;
|
||||
};
|
||||
|
||||
export type EdgeProps = {
|
||||
id: string;
|
||||
sourceX: number;
|
||||
sourceY: number;
|
||||
targetX: number;
|
||||
targetY: number;
|
||||
sourcePosition?: Position;
|
||||
targetPosition?: Position;
|
||||
};
|
||||
import type { EdgeProps } from '$lib/types';
|
||||
|
||||
export type EdgeTypes = Record<string, typeof SvelteComponentTyped<EdgeProps>>;
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
export type { Position, XYPosition } from '@reactflow/system';
|
||||
export type {
|
||||
Position,
|
||||
XYPosition,
|
||||
Edge,
|
||||
BaseEdgeProps,
|
||||
WrapEdgeProps,
|
||||
EdgeProps
|
||||
} from '@reactflow/system';
|
||||
|
||||
export * from './nodes';
|
||||
export * from './edges';
|
||||
|
||||
@@ -83,7 +83,8 @@
|
||||
id: '1-2',
|
||||
type: 'default',
|
||||
source: '1',
|
||||
target: '2'
|
||||
target: '2',
|
||||
label: 'Edge Text'
|
||||
}, {
|
||||
id: '1-3',
|
||||
type: 'smoothstep',
|
||||
@@ -93,7 +94,8 @@
|
||||
id: '2-4',
|
||||
type: 'default',
|
||||
source: '2',
|
||||
target: '4'
|
||||
target: '4',
|
||||
animated: true
|
||||
}];
|
||||
|
||||
function updateNode() {
|
||||
|
||||
Reference in New Issue
Block a user