added Edge Reconnection
This commit is contained in:
@@ -5,38 +5,21 @@
|
||||
type EdgeProps,
|
||||
EdgeLabelRenderer,
|
||||
useSvelteFlow,
|
||||
MarkerType
|
||||
MarkerType,
|
||||
EdgeReconnectAnchor
|
||||
} from '@xyflow/svelte';
|
||||
|
||||
type $$Props = EdgeProps;
|
||||
|
||||
interface Props {
|
||||
id?: $$Props['id'];
|
||||
style?: $$Props['style'];
|
||||
markerEnd?: $$Props['markerEnd'];
|
||||
sourceX: $$Props['sourceX'];
|
||||
sourceY: $$Props['sourceY'];
|
||||
sourcePosition: $$Props['sourcePosition'];
|
||||
targetX: $$Props['targetX'];
|
||||
targetY: $$Props['targetY'];
|
||||
targetPosition: $$Props['targetPosition'];
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
let {
|
||||
id = '',
|
||||
style = undefined,
|
||||
markerEnd = undefined,
|
||||
style,
|
||||
markerEnd,
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourcePosition,
|
||||
targetX,
|
||||
targetY,
|
||||
targetPosition,
|
||||
...rest
|
||||
}: Props = $props();
|
||||
|
||||
rest;
|
||||
selected
|
||||
}: EdgeProps = $props();
|
||||
|
||||
let [edgePath, labelX, labelY] = $derived(
|
||||
getBezierPath({
|
||||
@@ -50,42 +33,61 @@
|
||||
);
|
||||
|
||||
const { updateEdge } = useSvelteFlow();
|
||||
|
||||
let reconnecting = $state(false);
|
||||
</script>
|
||||
|
||||
<BaseEdge path={edgePath} {markerEnd} {style} />
|
||||
<EdgeLabelRenderer>
|
||||
<div
|
||||
class="edgeButtonContainer nodrag nopan"
|
||||
style:transform="translate(-50%, -50%) translate({labelX}px,{labelY}px)"
|
||||
>
|
||||
<button
|
||||
class="edgeButton"
|
||||
onclick={(event) => {
|
||||
event.stopPropagation();
|
||||
updateEdge('e5-6', {
|
||||
markerEnd: {
|
||||
type: MarkerType.Arrow,
|
||||
color: '#FFCC00',
|
||||
markerUnits: 'userSpaceOnUse',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
},
|
||||
markerStart: {
|
||||
type: MarkerType.ArrowClosed,
|
||||
color: '#FFCC00',
|
||||
orient: 'auto-start-reverse',
|
||||
markerUnits: 'userSpaceOnUse',
|
||||
width: 20,
|
||||
height: 20
|
||||
}
|
||||
});
|
||||
}}
|
||||
{#if !reconnecting}
|
||||
<BaseEdge path={edgePath} {markerEnd} {style} />
|
||||
<EdgeLabelRenderer>
|
||||
<div
|
||||
class="edgeButtonContainer nodrag nopan"
|
||||
style:transform="translate(-50%, -50%) translate({labelX}px,{labelY}px)"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
</EdgeLabelRenderer>
|
||||
<button
|
||||
class="edgeButton"
|
||||
onclick={(event) => {
|
||||
event.stopPropagation();
|
||||
updateEdge('e5-6', {
|
||||
markerEnd: {
|
||||
type: MarkerType.Arrow,
|
||||
color: '#FFCC00',
|
||||
markerUnits: 'userSpaceOnUse',
|
||||
width: 20,
|
||||
height: 20,
|
||||
strokeWidth: 2
|
||||
},
|
||||
markerStart: {
|
||||
type: MarkerType.ArrowClosed,
|
||||
color: '#FFCC00',
|
||||
orient: 'auto-start-reverse',
|
||||
markerUnits: 'userSpaceOnUse',
|
||||
width: 20,
|
||||
height: 20
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
</EdgeLabelRenderer>
|
||||
{/if}
|
||||
|
||||
{#if selected}
|
||||
<EdgeReconnectAnchor
|
||||
bind:reconnecting
|
||||
type="source"
|
||||
position={{ x: sourceX, y: sourceY }}
|
||||
asDomNode
|
||||
/>
|
||||
<EdgeReconnectAnchor
|
||||
bind:reconnecting
|
||||
type="target"
|
||||
position={{ x: targetX, y: targetY }}
|
||||
asDomNode
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.edgeButtonContainer {
|
||||
|
||||
@@ -1,57 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { BezierEdge, type EdgeProps } from '@xyflow/svelte';
|
||||
|
||||
type $$Props = EdgeProps;
|
||||
|
||||
|
||||
|
||||
interface Props {
|
||||
label?: $$Props['label'];
|
||||
labelStyle?: $$Props['labelStyle'];
|
||||
style?: $$Props['style'];
|
||||
markerStart?: $$Props['markerStart'];
|
||||
markerEnd?: $$Props['markerEnd'];
|
||||
interactionWidth?: $$Props['interactionWidth'];
|
||||
sourceX: $$Props['sourceX'];
|
||||
sourceY: $$Props['sourceY'];
|
||||
sourcePosition: $$Props['sourcePosition'];
|
||||
targetX: $$Props['targetX'];
|
||||
targetY: $$Props['targetY'];
|
||||
targetPosition: $$Props['targetPosition'];
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
let {
|
||||
label = undefined,
|
||||
labelStyle = undefined,
|
||||
style = undefined,
|
||||
markerStart = undefined,
|
||||
markerEnd = undefined,
|
||||
interactionWidth = undefined,
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourcePosition,
|
||||
targetX,
|
||||
targetY,
|
||||
targetPosition,
|
||||
...rest
|
||||
}: Props = $props();
|
||||
|
||||
rest;
|
||||
let { ...props }: EdgeProps = $props();
|
||||
</script>
|
||||
|
||||
<BezierEdge
|
||||
{sourceX}
|
||||
{sourceY}
|
||||
{sourcePosition}
|
||||
{targetX}
|
||||
{targetY}
|
||||
{targetPosition}
|
||||
{label}
|
||||
{labelStyle}
|
||||
{markerStart}
|
||||
{markerEnd}
|
||||
{style}
|
||||
{interactionWidth}
|
||||
pathOptions={{ curvature: 1 }}
|
||||
/>
|
||||
<BezierEdge {...props} pathOptions={{ curvature: 1 }} />
|
||||
|
||||
@@ -1,31 +1 @@
|
||||
type PortalOptions = {
|
||||
target?: string;
|
||||
domNode: Element | null;
|
||||
};
|
||||
|
||||
function tryToMount(node: Element, domNode: Element | null, target: string | undefined) {
|
||||
if (!domNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetEl = target ? domNode.querySelector(target) : domNode;
|
||||
|
||||
if (targetEl) {
|
||||
targetEl.appendChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
export default function (node: Element, { target, domNode }: PortalOptions) {
|
||||
tryToMount(node, domNode, target);
|
||||
|
||||
return {
|
||||
async update({ target, domNode }: PortalOptions) {
|
||||
tryToMount(node, domNode, target);
|
||||
},
|
||||
destroy() {
|
||||
if (node.parentNode) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
export { default as portal } from './portal.svelte';
|
||||
|
||||
42
packages/svelte/src/lib/actions/portal/portal.svelte.ts
Normal file
42
packages/svelte/src/lib/actions/portal/portal.svelte.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { useStore } from '$lib/store';
|
||||
|
||||
type Portal = 'viewport' | 'edgelabel' | 'root';
|
||||
|
||||
const selector: Record<Exclude<Portal, 'root'>, string> = {
|
||||
viewport: '.svelte-flow__viewport-portal',
|
||||
edgelabel: '.svelte-flow__edgelabel-renderer'
|
||||
};
|
||||
|
||||
function tryToMount(node: Element, domNode: Element | null, target: Portal | undefined) {
|
||||
if (!target || !domNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetEl = target === 'root' ? domNode : domNode.querySelector(selector[target]);
|
||||
|
||||
if (targetEl) {
|
||||
targetEl.appendChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
export default function (node: Element, target: Portal | undefined) {
|
||||
const { domNode } = $derived(useStore());
|
||||
|
||||
let previousTarget: Portal | undefined = target;
|
||||
|
||||
tryToMount(node, domNode, target);
|
||||
|
||||
return {
|
||||
async update(target: Portal) {
|
||||
if (target !== previousTarget) {
|
||||
node.parentNode?.removeChild(node);
|
||||
}
|
||||
tryToMount(node, domNode, target);
|
||||
},
|
||||
destroy() {
|
||||
if (node.parentNode) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,13 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
import portal from '$lib/actions/portal';
|
||||
import { useStore } from '$lib/store';
|
||||
|
||||
const store = useStore();
|
||||
import { portal } from '$lib/actions/portal';
|
||||
|
||||
let { children }: { children?: Snippet } = $props();
|
||||
</script>
|
||||
|
||||
<div use:portal={{ target: '.svelte-flow__edgelabel-renderer', domNode: store.domNode }}>
|
||||
<div use:portal={'edgelabel'}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
<script lang="ts">
|
||||
import { useStore } from '$lib/store';
|
||||
import type { Edge } from '$lib/types';
|
||||
import { XYHandle, type HandleType, type XYPosition } from '@xyflow/system';
|
||||
import { getContext, type Snippet } from 'svelte';
|
||||
import type { ClassValue } from 'svelte/elements';
|
||||
import { portal } from '$lib/actions/portal';
|
||||
|
||||
let {
|
||||
type,
|
||||
reconnecting = $bindable(false),
|
||||
position,
|
||||
class: className,
|
||||
size = 25,
|
||||
style,
|
||||
children,
|
||||
asDomNode = false
|
||||
}: {
|
||||
type: HandleType;
|
||||
reconnecting?: boolean;
|
||||
style?: string;
|
||||
class?: ClassValue;
|
||||
position?: XYPosition;
|
||||
asDomNode?: boolean;
|
||||
size?: number;
|
||||
children?: Snippet;
|
||||
} = $props();
|
||||
|
||||
const store = useStore();
|
||||
|
||||
let edgeId: string | undefined = getContext('svelteflow__edge_id');
|
||||
|
||||
if (!edgeId) {
|
||||
throw new Error('EdgeReconnectAnchor must be used within an Edge component');
|
||||
}
|
||||
|
||||
const onPointerDown = (event: PointerEvent) => {
|
||||
if (event.button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
autoPanOnConnect,
|
||||
domNode,
|
||||
isValidConnection,
|
||||
connectionMode,
|
||||
connectionRadius,
|
||||
onconnectstart,
|
||||
onconnectend,
|
||||
onreconnect,
|
||||
onreconnectstart,
|
||||
onreconnectend,
|
||||
onbeforereconnect,
|
||||
cancelConnection,
|
||||
nodeLookup,
|
||||
flowId,
|
||||
panBy,
|
||||
updateConnection,
|
||||
edgeLookup
|
||||
} = store;
|
||||
|
||||
let newEdge: Edge | undefined;
|
||||
let edge = edgeLookup.get(edgeId)!;
|
||||
|
||||
reconnecting = true;
|
||||
onreconnectstart?.(event, edge, type);
|
||||
|
||||
const opposite =
|
||||
type === 'target'
|
||||
? { nodeId: edge.source, handleId: edge.sourceHandle ?? null, type: 'source' as HandleType }
|
||||
: {
|
||||
nodeId: edge.target,
|
||||
handleId: edge.targetHandle ?? null,
|
||||
type: 'target' as HandleType
|
||||
};
|
||||
|
||||
XYHandle.onPointerDown(event, {
|
||||
autoPanOnConnect,
|
||||
connectionMode,
|
||||
connectionRadius,
|
||||
domNode,
|
||||
handleId: opposite.handleId,
|
||||
nodeId: opposite.nodeId,
|
||||
nodeLookup,
|
||||
isTarget: opposite.type === 'target',
|
||||
edgeUpdaterType: opposite.type,
|
||||
lib: 'svelte',
|
||||
flowId,
|
||||
cancelConnection,
|
||||
panBy,
|
||||
isValidConnection,
|
||||
onConnectStart: onconnectstart,
|
||||
onConnectEnd: onconnectend,
|
||||
onConnect: (connection) => {
|
||||
newEdge = { ...edge, ...connection };
|
||||
newEdge = onbeforereconnect ? (onbeforereconnect(newEdge, edge) ?? undefined) : newEdge;
|
||||
|
||||
if (newEdge) {
|
||||
store.edges = store.edges.map((e) => (e.id === edge.id ? (newEdge as Edge) : e));
|
||||
}
|
||||
|
||||
onreconnect?.(edge, connection);
|
||||
},
|
||||
onReconnectEnd: (event, connectionState) => {
|
||||
reconnecting = false;
|
||||
onreconnectend?.(event, edge, opposite.type, connectionState);
|
||||
},
|
||||
updateConnection,
|
||||
getTransform: () => [store.viewport.x, store.viewport.y, store.viewport.zoom],
|
||||
getFromHandle: () => store.connection.fromHandle
|
||||
});
|
||||
};
|
||||
|
||||
let offset = $derived(asDomNode ? '-50%' : `-${size * 0.5}px`);
|
||||
</script>
|
||||
|
||||
<svelte:element
|
||||
this={asDomNode ? 'div' : 'g'}
|
||||
use:portal={asDomNode ? 'edgelabel' : undefined}
|
||||
xmlns={asDomNode ? undefined : 'http://www.w3.org/2000/svg'}
|
||||
class={['svelte-flow__edgeupdater nopan', `svelte-flow__edgeupdater-${type}`, className]}
|
||||
style:position="absolute"
|
||||
style:width={`${size}px`}
|
||||
style:height={`${size}px`}
|
||||
style:transform={position
|
||||
? `translate(calc(${offset} + ${position.x}px), calc(${offset} + ${position.y}px))`
|
||||
: `translate(${offset}, ${offset})`}
|
||||
{style}
|
||||
onpointerdown={onPointerDown}
|
||||
>
|
||||
{#if !reconnecting}
|
||||
{#if children}
|
||||
{@render children()}
|
||||
{:else if !asDomNode}
|
||||
<rect
|
||||
width={size}
|
||||
height={size}
|
||||
x={0}
|
||||
fill="transparent"
|
||||
stroke="transparent"
|
||||
pointer-events="all"
|
||||
/>
|
||||
{/if}
|
||||
{/if}
|
||||
</svelte:element>
|
||||
@@ -0,0 +1 @@
|
||||
export { default as EdgeReconnectAnchor } from './EdgeReconnectAnchor.svelte';
|
||||
@@ -196,10 +196,10 @@
|
||||
The Handle component is the part of a node that can be used to connect nodes.
|
||||
-->
|
||||
<div
|
||||
data-handleid={handleId}
|
||||
data-handleid={handleId ?? 'null'}
|
||||
data-nodeid={nodeId}
|
||||
data-handlepos={position}
|
||||
data-id="{store.flowId}-{nodeId}-{handleId}-{type}"
|
||||
data-id="{store.flowId}-{nodeId}-{handleId ?? 'null'}-{type}"
|
||||
class={[
|
||||
'svelte-flow__handle',
|
||||
`svelte-flow__handle-${position}`,
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
import portal from '$lib/actions/portal';
|
||||
import { useStore } from '$lib/store';
|
||||
import { portal } from '$lib/actions/portal';
|
||||
|
||||
let { children }: { children?: Snippet } = $props();
|
||||
|
||||
const store = useStore();
|
||||
</script>
|
||||
|
||||
<div use:portal={{ target: '.svelte-flow__viewport-portal', domNode: store.domNode }}>
|
||||
<div use:portal={'viewport'}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -66,9 +66,6 @@
|
||||
nodes = $bindable([]),
|
||||
edges = $bindable([]),
|
||||
viewport = $bindable(undefined),
|
||||
nodesDraggable = $bindable(true),
|
||||
nodesConnectable = $bindable(true),
|
||||
elementsSelectable = $bindable(true),
|
||||
...props
|
||||
}: SvelteFlowProps & HTMLAttributes<HTMLDivElement> = $props();
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
edgeTypes,
|
||||
colorMode: _colorMode,
|
||||
isValidConnection,
|
||||
onmove,
|
||||
onmovestart,
|
||||
onmoveend,
|
||||
onerror,
|
||||
ondelete,
|
||||
onbeforedelete,
|
||||
@@ -39,6 +42,10 @@
|
||||
onconnect,
|
||||
onconnectstart,
|
||||
onconnectend,
|
||||
onbeforereconnect,
|
||||
onreconnect,
|
||||
onreconnectstart,
|
||||
onreconnectend,
|
||||
onclickconnectstart,
|
||||
onclickconnectend,
|
||||
clickConnect,
|
||||
|
||||
@@ -18,7 +18,10 @@ import type {
|
||||
OnConnect,
|
||||
OnConnectStart,
|
||||
OnConnectEnd,
|
||||
ColorModeClass
|
||||
ColorModeClass,
|
||||
OnReconnect,
|
||||
OnRecoonnectStart,
|
||||
OnReconnectEnd
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type {
|
||||
@@ -32,7 +35,8 @@ import type {
|
||||
OnDelete,
|
||||
OnBeforeConnect,
|
||||
OnBeforeDelete,
|
||||
IsValidConnection
|
||||
IsValidConnection,
|
||||
OnBeforeReconnect
|
||||
} from '$lib/types';
|
||||
|
||||
import type { Component } from 'svelte';
|
||||
@@ -356,16 +360,22 @@ export type SvelteFlowProps = NodeEvents &
|
||||
ondelete?: OnDelete;
|
||||
/** This handler gets called before the user deletes nodes or edges and provides a way to abort the deletion by returning false. */
|
||||
onbeforedelete?: OnBeforeDelete;
|
||||
|
||||
/** This handler gets called when a new edge is created. You can use it to modify the newly created edge. */
|
||||
onbeforeconnect?: OnBeforeConnect;
|
||||
|
||||
/** This event gets fired when a connection successfully completes and an edge is created. */
|
||||
onconnect?: OnConnect;
|
||||
/** When a user starts to drag a connection line, this event gets fired. */
|
||||
onconnectstart?: OnConnectStart;
|
||||
/** When a user stops dragging a connection line, this event gets fired. */
|
||||
onconnectend?: OnConnectEnd;
|
||||
/** This event gets fired when after an edge was reconnected*/
|
||||
onreconnect?: OnReconnect;
|
||||
/** This event gets fired when a user starts to reconnect an edge */
|
||||
onreconnectstart?: OnRecoonnectStart;
|
||||
/** This event gets fired when a user stops reconnecting an edge */
|
||||
onreconnectend?: OnReconnectEnd;
|
||||
/** This handler gets called when an edge is reconnected. You can use it to modify the edge before the update is applied. */
|
||||
onbeforereconnect?: OnBeforeReconnect;
|
||||
/** A connection is started by clicking on a handle */
|
||||
onclickconnectstart?: OnConnectStart;
|
||||
/** A connection is finished by clicking on a handle */
|
||||
|
||||
@@ -16,6 +16,7 @@ export {
|
||||
} from '$lib/components/edges';
|
||||
export * from '$lib/components/Handle';
|
||||
export * from '$lib/components/EdgeLabel';
|
||||
export * from '$lib/components/EdgeReconnectAnchor';
|
||||
|
||||
// plugins
|
||||
export * from '$lib/plugins/Controls';
|
||||
@@ -40,6 +41,9 @@ export * from '$lib/hooks/useNodesData.svelte';
|
||||
export * from '$lib/hooks/useInternalNode.svelte';
|
||||
export * from '$lib/hooks/useInitialized.svelte';
|
||||
|
||||
//actions
|
||||
export * from '$lib/actions/portal';
|
||||
|
||||
// types
|
||||
export type {
|
||||
Edge,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { getContext } from 'svelte';
|
||||
import { Position, getNodeToolbarTransform } from '@xyflow/system';
|
||||
|
||||
import portal from '$lib/actions/portal';
|
||||
import { portal } from '$lib/actions/portal';
|
||||
import { useStore } from '$lib/store';
|
||||
import { useSvelteFlow } from '$lib/hooks/useSvelteFlow.svelte';
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
<div
|
||||
data-id={toolbarNodes.reduce((acc, node) => `${acc}${node.id} `, '').trim()}
|
||||
class="svelte-flow__node-toolbar"
|
||||
use:portal={{ domNode: store.domNode }}
|
||||
use:portal={'root'}
|
||||
style:position="absolute"
|
||||
style:transform
|
||||
style:z-index={zIndex}
|
||||
|
||||
@@ -29,7 +29,10 @@ import {
|
||||
type ColorModeClass,
|
||||
type Transform,
|
||||
fitViewport,
|
||||
type Handle
|
||||
type Handle,
|
||||
type OnReconnect,
|
||||
type OnRecoonnectStart,
|
||||
type OnReconnectEnd
|
||||
} from '@xyflow/system';
|
||||
|
||||
import DefaultNode from '$lib/components/nodes/DefaultNode.svelte';
|
||||
@@ -54,7 +57,8 @@ import type {
|
||||
IsValidConnection,
|
||||
Edge,
|
||||
EdgeLayouted,
|
||||
InternalNode
|
||||
InternalNode,
|
||||
OnBeforeReconnect
|
||||
} from '$lib/types';
|
||||
|
||||
import type { StoreSignals } from './types';
|
||||
@@ -270,16 +274,22 @@ export const getInitialStore = (signals: StoreSignals) => {
|
||||
onlyRenderVisibleElements: boolean = $derived(signals.props.onlyRenderVisibleElements ?? false);
|
||||
onerror: OnError = $derived(signals.props.onerror ?? devWarn);
|
||||
|
||||
ondelete?: OnDelete = $derived(signals.props.ondelete ?? undefined);
|
||||
ondelete?: OnDelete = $derived(signals.props.ondelete);
|
||||
onbeforedelete?: OnBeforeDelete = $derived(signals.props.onbeforedelete);
|
||||
|
||||
onbeforeconnect?: OnBeforeConnect = $derived(signals.props.onbeforeconnect);
|
||||
onconnect?: OnConnect = $derived(signals.props.onconnect);
|
||||
onconnectstart?: OnConnectStart = $derived(signals.props.onconnectstart);
|
||||
onconnectend?: OnConnectEnd = $derived(signals.props.onconnectend);
|
||||
|
||||
onbeforereconnect?: OnBeforeReconnect = $derived(signals.props.onbeforereconnect);
|
||||
onreconnect?: OnReconnect = $derived(signals.props.onreconnect);
|
||||
onreconnectstart?: OnRecoonnectStart = $derived(signals.props.onreconnectstart);
|
||||
onreconnectend?: OnReconnectEnd = $derived(signals.props.onreconnectend);
|
||||
|
||||
clickConnect?: boolean = $derived(signals.props.clickConnect ?? true);
|
||||
onclickconnectstart?: OnConnectStart = $derived(signals.props.onclickconnectstart ?? undefined);
|
||||
onclickconnectend?: OnConnectEnd = $derived(signals.props.onclickconnectend ?? undefined);
|
||||
onclickconnectstart?: OnConnectStart = $derived(signals.props.onclickconnectstart);
|
||||
onclickconnectend?: OnConnectEnd = $derived(signals.props.onclickconnectend);
|
||||
clickConnectStartHandle: Pick<Handle, 'id' | 'nodeId' | 'type'> | null = $state(null);
|
||||
|
||||
resolveFitView = async () => {
|
||||
|
||||
@@ -36,6 +36,10 @@ export type FitViewOptions<NodeType extends Node = Node> = FitViewOptionsBase<No
|
||||
|
||||
export type OnDelete = (params: { nodes: Node[]; edges: Edge[] }) => void;
|
||||
export type OnBeforeConnect = (connection: Connection) => Edge | Connection | void;
|
||||
export type OnBeforeReconnect<EdgeType extends Edge = Edge> = (
|
||||
newEdge: EdgeType,
|
||||
oldEdge: EdgeType
|
||||
) => EdgeType | void;
|
||||
export type OnBeforeDelete<
|
||||
NodeType extends Node = Node,
|
||||
EdgeType extends Edge = Edge
|
||||
|
||||
@@ -80,6 +80,19 @@ export type OnConnectStart = (event: MouseEvent | TouchEvent, params: OnConnectS
|
||||
export type OnConnect = (connection: Connection) => void;
|
||||
export type OnConnectEnd = (event: MouseEvent | TouchEvent, connectionState: FinalConnectionState) => void;
|
||||
|
||||
export type OnReconnect<EdgeType extends EdgeBase = EdgeBase> = (oldEdge: EdgeType, newConnection: Connection) => void;
|
||||
export type OnRecoonnectStart<EdgeType extends EdgeBase = EdgeBase> = (
|
||||
event: MouseEvent | TouchEvent,
|
||||
edge: EdgeType,
|
||||
handleType: HandleType
|
||||
) => void;
|
||||
export type OnReconnectEnd<EdgeType extends EdgeBase = EdgeBase> = (
|
||||
event: MouseEvent | TouchEvent,
|
||||
edge: EdgeType,
|
||||
handleType: HandleType,
|
||||
connectionState: FinalConnectionState
|
||||
) => void;
|
||||
|
||||
export type IsValidConnection = (edge: EdgeBase | Connection) => boolean;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user