Refactor(types): unify node and edge handling (#3978)

* refactor(types): unify node and edge type behaviour

* chore(changelogs): update

* chore(examples): cleanup
This commit is contained in:
Moritz Klack
2024-03-05 13:15:28 +01:00
committed by GitHub
parent 3122a3ac21
commit 4a12a9f781
29 changed files with 174 additions and 104 deletions
@@ -1,4 +1,4 @@
import React, { memo, FC, CSSProperties, useCallback } from 'react'; import React, { memo, CSSProperties, useCallback } from 'react';
import { Handle, Position, NodeProps, Connection, Edge, useOnViewportChange, Viewport } from '@xyflow/react'; import { Handle, Position, NodeProps, Connection, Edge, useOnViewportChange, Viewport } from '@xyflow/react';
import type { ColorSelectorNode } from '.'; import type { ColorSelectorNode } from '.';
@@ -13,7 +13,7 @@ const sourceHandleStyleB: CSSProperties = {
const onConnect = (params: Connection | Edge) => console.log('handle onConnect', params); const onConnect = (params: Connection | Edge) => console.log('handle onConnect', params);
const ColorSelectorNode: FC<NodeProps<ColorSelectorNode['data']>> = ({ data, isConnectable }) => { function ColorSelectorNode({ data, isConnectable }: NodeProps<ColorSelectorNode>) {
const onStart = useCallback((viewport: Viewport) => console.log('onStart', viewport), []); const onStart = useCallback((viewport: Viewport) => console.log('onStart', viewport), []);
const onChange = useCallback((viewport: Viewport) => console.log('onChange', viewport), []); const onChange = useCallback((viewport: Viewport) => console.log('onChange', viewport), []);
const onEnd = useCallback((viewport: Viewport) => console.log('onEnd', viewport), []); const onEnd = useCallback((viewport: Viewport) => console.log('onEnd', viewport), []);
@@ -44,6 +44,6 @@ const ColorSelectorNode: FC<NodeProps<ColorSelectorNode['data']>> = ({ data, isC
<Handle type="source" position={Position.Right} id="b" style={sourceHandleStyleB} isConnectable={isConnectable} /> <Handle type="source" position={Position.Right} id="b" style={sourceHandleStyleB} isConnectable={isConnectable} />
</> </>
); );
}; }
export default memo(ColorSelectorNode); export default memo(ColorSelectorNode);
@@ -17,6 +17,8 @@ import {
OnBeforeDelete, OnBeforeDelete,
BuiltInNode, BuiltInNode,
BuiltInEdge, BuiltInEdge,
NodeTypes,
ReactFlowProvider,
} from '@xyflow/react'; } from '@xyflow/react';
import ColorSelectorNode from './ColorSelectorNode'; import ColorSelectorNode from './ColorSelectorNode';
@@ -40,7 +42,7 @@ const initBgColor = '#1A192B';
const connectionLineStyle = { stroke: '#fff' }; const connectionLineStyle = { stroke: '#fff' };
const snapGrid: SnapGrid = [16, 16]; const snapGrid: SnapGrid = [16, 16];
const nodeTypes = { const nodeTypes: NodeTypes = {
selectorNode: ColorSelectorNode, selectorNode: ColorSelectorNode,
}; };
@@ -188,4 +190,8 @@ const CustomNodeFlow = () => {
); );
}; };
export default CustomNodeFlow; export default () => (
<ReactFlowProvider>
<CustomNodeFlow />
</ReactFlowProvider>
);
@@ -27,18 +27,21 @@ const initialNodes: Node[] = [
data: { label: 'Node 2' }, data: { label: 'Node 2' },
position: { x: 100, y: 100 }, position: { x: 100, y: 100 },
className: 'light', className: 'light',
type: 'default',
}, },
{ {
id: '3', id: '3',
data: { label: 'Node 3' }, data: { label: 'Node 3' },
position: { x: 400, y: 100 }, position: { x: 400, y: 100 },
className: 'light', className: 'light',
type: 'default',
}, },
{ {
id: '4', id: '4',
data: { label: 'Node 4' }, data: { label: 'Node 4' },
position: { x: 400, y: 200 }, position: { x: 400, y: 200 },
className: 'light', className: 'light',
type: 'default',
}, },
]; ];
@@ -85,6 +88,7 @@ const UseZoomPanHelperFlow = () => {
data: { data: {
label: `${projectedPosition.x}-${projectedPosition.y}`, label: `${projectedPosition.x}-${projectedPosition.y}`,
}, },
type: 'default',
}) })
); );
}, },
@@ -106,6 +110,7 @@ const UseZoomPanHelperFlow = () => {
data: { data: {
label: 'New Node', label: 'New Node',
}, },
type: 'default',
}; };
addNodes(newNode); addNodes(newNode);
@@ -139,8 +144,8 @@ const UseZoomPanHelperFlow = () => {
const onSetNodes = () => { const onSetNodes = () => {
setNodes([ setNodes([
{ id: 'a', position: { x: 0, y: 0 }, data: { label: 'Node a' } }, { id: 'a', type: 'default', position: { x: 0, y: 0 }, data: { label: 'Node a' } },
{ id: 'b', position: { x: 0, y: 150 }, data: { label: 'Node b' } }, { id: 'b', type: 'default', position: { x: 0, y: 150 }, data: { label: 'Node b' } },
]); ]);
setEdges([{ id: 'a-b', source: 'a', target: 'b' }]); setEdges([{ id: 'a-b', source: 'a', target: 'b' }]);
@@ -1,5 +1,4 @@
<script lang="ts"> <script lang="ts">
import type { ChangeEventHandler } from 'svelte/elements';
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
import { import {
SvelteFlow, SvelteFlow,
@@ -1,10 +1,10 @@
<script lang="ts"> <script lang="ts">
import type { Writable } from 'svelte/store'; import type { Writable } from 'svelte/store';
import { Handle, Position, type NodeProps } from '@xyflow/svelte'; import { Handle, Position, type NodeProps, type Node } from '@xyflow/svelte';
type $$Props = NodeProps; type $$Props = NodeProps<Node<{ colorStore: Writable<string> }>>;
export let data: { colorStore: Writable<string> }; export let data: $$Props['data'];
const { colorStore } = data; const { colorStore } = data;
</script> </script>
+1
View File
@@ -5,6 +5,7 @@
## Patch changes ## Patch changes
- fix `ref` prop for `ReactFlow` and `Handle` component - fix `ref` prop for `ReactFlow` and `Handle` component
- unify `Edge` and `Node` type handling
## 12.0.0-next.10 ## 12.0.0-next.10
@@ -212,6 +212,7 @@ export function EdgeWrapper<EdgeType extends Edge = Edge>({
id={id} id={id}
source={edge.source} source={edge.source}
target={edge.target} target={edge.target}
type={edge.type}
selected={edge.selected} selected={edge.selected}
animated={edge.animated} animated={edge.animated}
label={edge.label} label={edge.label}
@@ -1,5 +1,4 @@
import type { ComponentType } from 'react'; import type { EdgeTypes } from '../../types';
import type { EdgeProps, EdgeTypes } from '../../types';
import { import {
BezierEdgeInternal, BezierEdgeInternal,
StraightEdgeInternal, StraightEdgeInternal,
@@ -9,11 +8,11 @@ import {
} from '../Edges'; } from '../Edges';
export const builtinEdgeTypes: EdgeTypes = { export const builtinEdgeTypes: EdgeTypes = {
default: BezierEdgeInternal as ComponentType<EdgeProps>, default: BezierEdgeInternal,
straight: StraightEdgeInternal as ComponentType<EdgeProps>, straight: StraightEdgeInternal,
step: StepEdgeInternal as ComponentType<EdgeProps>, step: StepEdgeInternal,
smoothstep: SmoothStepEdgeInternal as ComponentType<EdgeProps>, smoothstep: SmoothStepEdgeInternal,
simplebezier: SimpleBezierEdgeInternal as ComponentType<EdgeProps>, simplebezier: SimpleBezierEdgeInternal,
}; };
export const nullPosition = { export const nullPosition = {
@@ -1,10 +1,10 @@
import { import {
memo,
forwardRef,
type HTMLAttributes, type HTMLAttributes,
type MouseEvent as ReactMouseEvent, type MouseEvent as ReactMouseEvent,
type TouchEvent as ReactTouchEvent, type TouchEvent as ReactTouchEvent,
type ForwardedRef, type ForwardedRef,
memo,
forwardRef,
} from 'react'; } from 'react';
import cc from 'classcat'; import cc from 'classcat';
import { shallow } from 'zustand/shallow'; import { shallow } from 'zustand/shallow';
@@ -1,5 +1,4 @@
import type { ComponentType } from 'react'; import type { XYPosition } from '@xyflow/system';
import type { NodeProps, XYPosition } from '@xyflow/system';
import { InputNode } from '../Nodes/InputNode'; import { InputNode } from '../Nodes/InputNode';
import { DefaultNode } from '../Nodes/DefaultNode'; import { DefaultNode } from '../Nodes/DefaultNode';
@@ -15,10 +14,10 @@ export const arrowKeyDiffs: Record<string, XYPosition> = {
}; };
export const builtinNodeTypes: NodeTypes = { export const builtinNodeTypes: NodeTypes = {
input: InputNode as ComponentType<NodeProps>, input: InputNode,
default: DefaultNode as ComponentType<NodeProps>, default: DefaultNode,
output: OutputNode as ComponentType<NodeProps>, output: OutputNode,
group: GroupNode as ComponentType<NodeProps>, group: GroupNode,
}; };
export function getNodeInlineStyleDimensions<NodeType extends Node = Node>( export function getNodeInlineStyleDimensions<NodeType extends Node = Node>(
@@ -1,13 +1,14 @@
import { Position, type NodeProps } from '@xyflow/system'; import { Position } from '@xyflow/system';
import { Handle } from '../../components/Handle'; import { Handle } from '../../components/Handle';
import type { BuiltInNode, NodeProps } from '../../types/nodes';
export function DefaultNode({ export function DefaultNode({
data, data,
isConnectable, isConnectable,
targetPosition = Position.Top, targetPosition = Position.Top,
sourcePosition = Position.Bottom, sourcePosition = Position.Bottom,
}: NodeProps) { }: NodeProps<BuiltInNode>) {
return ( return (
<> <>
<Handle type="target" position={targetPosition} isConnectable={isConnectable} /> <Handle type="target" position={targetPosition} isConnectable={isConnectable} />
@@ -1,8 +1,9 @@
import { Position, type NodeProps } from '@xyflow/system'; import { Position } from '@xyflow/system';
import { Handle } from '../../components/Handle'; import { Handle } from '../../components/Handle';
import type { BuiltInNode, NodeProps } from '../../types/nodes';
export function InputNode({ data, isConnectable, sourcePosition = Position.Bottom }: NodeProps) { export function InputNode({ data, isConnectable, sourcePosition = Position.Bottom }: NodeProps<BuiltInNode>) {
return ( return (
<> <>
{data?.label} {data?.label}
@@ -1,8 +1,9 @@
import { Position, type NodeProps } from '@xyflow/system'; import { Position } from '@xyflow/system';
import { Handle } from '../../components/Handle'; import { Handle } from '../../components/Handle';
import type { BuiltInNode, NodeProps } from '../../types/nodes';
export function OutputNode({ data, isConnectable, targetPosition = Position.Top }: NodeProps) { export function OutputNode({ data, isConnectable, targetPosition = Position.Top }: NodeProps<BuiltInNode>) {
return ( return (
<> <>
<Handle type="target" position={targetPosition} isConnectable={isConnectable} /> <Handle type="target" position={targetPosition} isConnectable={isConnectable} />
-1
View File
@@ -64,7 +64,6 @@ export {
SelectionMode, SelectionMode,
type SelectionRect, type SelectionRect,
type OnError, type OnError,
type NodeProps,
type NodeOrigin, type NodeOrigin,
type OnSelectionDrag, type OnSelectionDrag,
Position, Position,
+4 -4
View File
@@ -98,10 +98,10 @@ export type EdgeTextProps = HTMLAttributes<SVGElement> &
* Custom edge component props * Custom edge component props
* @public * @public
*/ */
export type EdgeProps< export type EdgeProps<EdgeType extends Edge = Edge> = Pick<
EdgeData extends Record<string, unknown> = Record<string, unknown>, EdgeType,
EdgeType extends string | undefined = string | undefined 'id' | 'animated' | 'data' | 'style' | 'selected' | 'source' | 'target'
> = Pick<Edge<EdgeData, EdgeType>, 'id' | 'animated' | 'data' | 'style' | 'selected' | 'source' | 'target'> & > &
EdgePosition & EdgePosition &
EdgeLabelOptions & { EdgeLabelOptions & {
sourceHandleId?: string | null; sourceHandleId?: string | null;
+27 -7
View File
@@ -10,18 +10,18 @@ import {
SetCenter, SetCenter,
FitBounds, FitBounds,
XYPosition, XYPosition,
NodeProps,
OnBeforeDeleteBase, OnBeforeDeleteBase,
Connection, Connection,
} from '@xyflow/system'; } from '@xyflow/system';
import type { NodeChange, EdgeChange, Node, Edge, ReactFlowInstance, EdgeProps } from '.'; import type { NodeChange, EdgeChange, Node, Edge, ReactFlowInstance, EdgeProps, NodeProps } from '.';
// this is needed, to use generics + forwardRef // this is needed, to use generics + forwardRef
declare module 'react' { declare module 'react' {
function forwardRef<T, P>( // eslint-disable-next-line @typescript-eslint/ban-types
render: (props: P, ref: React.Ref<T>) => React.ReactNode | null function forwardRef<T, P = {}>(
): (props: P & React.RefAttributes<T>) => React.ReactNode | null; render: (props: P, ref: React.Ref<T>) => React.ReactElement | null
): (props: P & React.RefAttributes<T>) => React.ReactElement | null;
} }
export type OnNodesChange<NodeType extends Node = Node> = (changes: NodeChange<NodeType>[]) => void; export type OnNodesChange<NodeType extends Node = Node> = (changes: NodeChange<NodeType>[]) => void;
@@ -34,8 +34,28 @@ export type OnDelete<NodeType extends Node = Node, EdgeType extends Edge = Edge>
edges: EdgeType[]; edges: EdgeType[];
}) => void; }) => void;
export type NodeTypes = { [key: string]: ComponentType<NodeProps> }; export type NodeTypes = Record<
export type EdgeTypes = { [key: string]: ComponentType<EdgeProps> }; string,
ComponentType<
NodeProps & {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type: any;
}
>
>;
export type EdgeTypes = Record<
string,
ComponentType<
EdgeProps & {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type: any;
}
>
>;
export type UnselectNodesAndEdgesParams = { export type UnselectNodesAndEdgesParams = {
nodes?: Node[]; nodes?: Node[];
+4 -2
View File
@@ -1,5 +1,5 @@
import type { CSSProperties, MouseEvent as ReactMouseEvent } from 'react'; import type { CSSProperties, MouseEvent as ReactMouseEvent } from 'react';
import type { CoordinateExtent, NodeBase, NodeOrigin, OnError } from '@xyflow/system'; import type { CoordinateExtent, NodeBase, NodeOrigin, OnError, NodeProps as NodePropsBase } from '@xyflow/system';
import { NodeTypes } from './general'; import { NodeTypes } from './general';
@@ -9,7 +9,7 @@ import { NodeTypes } from './general';
*/ */
export type Node< export type Node<
NodeData extends Record<string, unknown> = Record<string, unknown>, NodeData extends Record<string, unknown> = Record<string, unknown>,
NodeType extends string | undefined = string | undefined NodeType extends string = string
> = NodeBase<NodeData, NodeType> & { > = NodeBase<NodeData, NodeType> & {
style?: CSSProperties; style?: CSSProperties;
className?: string; className?: string;
@@ -49,3 +49,5 @@ export type NodeWrapperProps<NodeType extends Node> = {
}; };
export type BuiltInNode = Node<{ label: string }, 'input' | 'output' | 'default'>; export type BuiltInNode = Node<{ label: string }, 'input' | 'output' | 'default'>;
export type NodeProps<NodeType extends Node = Node> = NodePropsBase<NodeType>;
+10
View File
@@ -1,5 +1,15 @@
# @xyflow/svelte # @xyflow/svelte
## 0.0.38
## ⚠️ Breaking changes
- `NodeProps` generic is a node and not only node data. `type $$Props = NodeProps<AppNode>`
## Patch changes
- unify `Edge` and `Node` type handling
## 0.0.37 ## 0.0.37
## ⚠️ Breaking changes ## ⚠️ Breaking changes
@@ -51,7 +51,8 @@
edgecontextmenu: { edge: Edge; event: MouseEvent }; edgecontextmenu: { edge: Edge; event: MouseEvent };
}>(); }>();
$: edgeComponent = $edgeTypes[type!] || BezierEdgeInternal; const edgeType = type || 'default';
$: edgeComponent = $edgeTypes[edgeType] || BezierEdgeInternal;
$: markerStartUrl = markerStart ? `url(#${getMarkerId(markerStart, $flowId)})` : undefined; $: markerStartUrl = markerStart ? `url(#${getMarkerId(markerStart, $flowId)})` : undefined;
$: markerEndUrl = markerEnd ? `url(#${getMarkerId(markerEnd, $flowId)})` : undefined; $: markerEndUrl = markerEnd ? `url(#${getMarkerId(markerEnd, $flowId)})` : undefined;
$: isSelectable = selectable || ($elementsSelectable && typeof selectable === 'undefined'); $: isSelectable = selectable || ($elementsSelectable && typeof selectable === 'undefined');
@@ -113,6 +114,7 @@
{data} {data}
{style} {style}
{interactionWidth} {interactionWidth}
type={edgeType}
sourceHandleId={sourceHandle} sourceHandleId={sourceHandle}
targetHandleId={targetHandle} targetHandleId={targetHandle}
markerStart={markerStartUrl} markerStart={markerStartUrl}
@@ -1,16 +1,10 @@
<svelte:options immutable /> <svelte:options immutable />
<script lang="ts"> <script lang="ts">
import { import { createEventDispatcher, setContext, onDestroy } from 'svelte';
createEventDispatcher,
setContext,
SvelteComponent,
type ComponentType,
onDestroy
} from 'svelte';
import { get, writable } from 'svelte/store'; import { get, writable } from 'svelte/store';
import cc from 'classcat'; import cc from 'classcat';
import { errorMessages, Position, type NodeProps } from '@xyflow/system'; import { errorMessages, Position } from '@xyflow/system';
import drag from '$lib/actions/drag'; import drag from '$lib/actions/drag';
import { useStore } from '$lib/store'; import { useStore } from '$lib/store';
@@ -71,8 +65,7 @@
console.warn('003', errorMessages['error003'](type!)); console.warn('003', errorMessages['error003'](type!));
} }
const nodeComponent: ComponentType<SvelteComponent<NodeProps>> = const nodeComponent = $nodeTypes[nodeType] || DefaultNode;
$nodeTypes[nodeType] || DefaultNode;
const dispatch = createEventDispatcher<{ const dispatch = createEventDispatcher<{
nodeclick: { node: Node; event: MouseEvent | TouchEvent }; nodeclick: { node: Node; event: MouseEvent | TouchEvent };
nodecontextmenu: { node: Node; event: MouseEvent | TouchEvent }; nodecontextmenu: { node: Node; event: MouseEvent | TouchEvent };
@@ -211,11 +204,11 @@
{selected} {selected}
{sourcePosition} {sourcePosition}
{targetPosition} {targetPosition}
{type}
{zIndex} {zIndex}
{dragging} {dragging}
{dragHandle} {dragHandle}
isConnectable={connectable} type={nodeType}
isConnectable={$connectableStore}
positionAbsoluteX={positionX} positionAbsoluteX={positionX}
positionAbsoluteY={positionY} positionAbsoluteY={positionY}
{width} {width}
@@ -11,6 +11,7 @@
export let source: $$Props['source'] = ''; export let source: $$Props['source'] = '';
export let target: $$Props['target'] = ''; export let target: $$Props['target'] = '';
export let type: $$Props['type'] = 'straight';
export let animated: $$Props['animated'] = undefined; export let animated: $$Props['animated'] = undefined;
export let selected: $$Props['selected'] = undefined; export let selected: $$Props['selected'] = undefined;
export let label: $$Props['label'] = undefined; export let label: $$Props['label'] = undefined;
@@ -1,9 +1,10 @@
<script lang="ts"> <script lang="ts">
import { Position, type NodeProps } from '@xyflow/system'; import { Position } from '@xyflow/system';
import { Handle } from '$lib/components/Handle'; import { Handle } from '$lib/components/Handle';
import type { NodeProps } from '$lib/types';
interface $$Props extends NodeProps<{ label: string }> {} interface $$Props extends NodeProps {}
export let data: $$Props['data'] = { label: 'Node' }; export let data: $$Props['data'] = { label: 'Node' };
export let targetPosition: $$Props['targetPosition'] = Position.Top; export let targetPosition: $$Props['targetPosition'] = Position.Top;
@@ -15,12 +16,12 @@
export let height: $$Props['height'] = undefined; export let height: $$Props['height'] = undefined;
export let selected: $$Props['selected'] = undefined; export let selected: $$Props['selected'] = undefined;
export let type: $$Props['type'] = undefined; export let type: $$Props['type'] = undefined;
export let zIndex: $$Props['zIndex'] = undefined;
export let dragging: $$Props['dragging'] = false; export let dragging: $$Props['dragging'] = false;
export let dragHandle: $$Props['dragHandle'] = undefined; export let dragHandle: $$Props['dragHandle'] = undefined;
export let positionAbsoluteX: $$Props['positionAbsoluteX'] = 0; export let positionAbsoluteX: $$Props['positionAbsoluteX'] = 0;
export let positionAbsoluteY: $$Props['positionAbsoluteY'] = 0; export let positionAbsoluteY: $$Props['positionAbsoluteY'] = 0;
export let isConnectable: $$Props['isConnectable'] = undefined; export let isConnectable: $$Props['isConnectable'];
export let zIndex: $$Props['zIndex'];
// @todo: there must be a better way to do this // @todo: there must be a better way to do this
id; id;
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import type { NodeProps } from '@xyflow/system'; import type { NodeProps } from '$lib/types';
interface $$Props extends NodeProps<{}> {} interface $$Props extends NodeProps {}
// unused props - we need to list them here in order to prevent warnings // unused props - we need to list them here in order to prevent warnings
export let id: $$Props['id'] = ''; export let id: $$Props['id'] = '';
@@ -12,12 +12,12 @@
export let sourcePosition: $$Props['sourcePosition'] = undefined; export let sourcePosition: $$Props['sourcePosition'] = undefined;
export let targetPosition: $$Props['targetPosition'] = undefined; export let targetPosition: $$Props['targetPosition'] = undefined;
export let type: $$Props['type'] = undefined; export let type: $$Props['type'] = undefined;
export let zIndex: $$Props['zIndex'] = undefined;
export let dragging: $$Props['dragging'] = false; export let dragging: $$Props['dragging'] = false;
export let dragHandle: $$Props['dragHandle'] = undefined; export let dragHandle: $$Props['dragHandle'] = undefined;
export let positionAbsoluteX: $$Props['positionAbsoluteX'] = 0; export let positionAbsoluteX: $$Props['positionAbsoluteX'] = 0;
export let positionAbsoluteY: $$Props['positionAbsoluteY'] = 0; export let positionAbsoluteY: $$Props['positionAbsoluteY'] = 0;
export let isConnectable: $$Props['isConnectable'] = undefined; export let isConnectable: $$Props['isConnectable'];
export let zIndex: $$Props['zIndex'];
// @todo: there must be a better way to do this // @todo: there must be a better way to do this
id; id;
@@ -1,9 +1,10 @@
<script lang="ts"> <script lang="ts">
import { Position, type NodeProps } from '@xyflow/system'; import { Position } from '@xyflow/system';
import type { NodeProps } from '$lib/types';
import { Handle } from '$lib/components/Handle'; import { Handle } from '$lib/components/Handle';
interface $$Props extends NodeProps<{ label: string }> {} interface $$Props extends NodeProps {}
export let data: $$Props['data'] = { label: 'Node' }; export let data: $$Props['data'] = { label: 'Node' };
export let sourcePosition: $$Props['sourcePosition'] = Position.Bottom; export let sourcePosition: $$Props['sourcePosition'] = Position.Bottom;
@@ -15,12 +16,12 @@
export let selected: $$Props['selected'] = undefined; export let selected: $$Props['selected'] = undefined;
export let targetPosition: $$Props['targetPosition'] = undefined; export let targetPosition: $$Props['targetPosition'] = undefined;
export let type: $$Props['type'] = undefined; export let type: $$Props['type'] = undefined;
export let zIndex: $$Props['zIndex'] = undefined;
export let dragging: $$Props['dragging'] = false; export let dragging: $$Props['dragging'] = false;
export let dragHandle: $$Props['dragHandle'] = undefined; export let dragHandle: $$Props['dragHandle'] = undefined;
export let positionAbsoluteX: $$Props['positionAbsoluteX'] = 0; export let positionAbsoluteX: $$Props['positionAbsoluteX'] = 0;
export let positionAbsoluteY: $$Props['positionAbsoluteY'] = 0; export let positionAbsoluteY: $$Props['positionAbsoluteY'] = 0;
export let isConnectable: $$Props['isConnectable'] = undefined; export let isConnectable: $$Props['isConnectable'];
export let zIndex: $$Props['zIndex'];
// @todo: there must be a better way to do this // @todo: there must be a better way to do this
id; id;
@@ -1,9 +1,10 @@
<script lang="ts"> <script lang="ts">
import { Position, type NodeProps } from '@xyflow/system'; import { Position } from '@xyflow/system';
import type { NodeProps } from '$lib/types';
import { Handle } from '$lib/components/Handle'; import { Handle } from '$lib/components/Handle';
interface $$Props extends NodeProps<{ label: string }> {} interface $$Props extends NodeProps {}
export let data: $$Props['data'] = { label: 'Node' }; export let data: $$Props['data'] = { label: 'Node' };
export let targetPosition: $$Props['targetPosition'] = Position.Top; export let targetPosition: $$Props['targetPosition'] = Position.Top;
@@ -15,12 +16,12 @@
export let selected: $$Props['selected'] = undefined; export let selected: $$Props['selected'] = undefined;
export let sourcePosition: $$Props['sourcePosition'] = undefined; export let sourcePosition: $$Props['sourcePosition'] = undefined;
export let type: $$Props['type'] = undefined; export let type: $$Props['type'] = undefined;
export let zIndex: $$Props['zIndex'] = undefined;
export let dragging: $$Props['dragging'] = false; export let dragging: $$Props['dragging'] = false;
export let dragHandle: $$Props['dragHandle'] = undefined; export let dragHandle: $$Props['dragHandle'] = undefined;
export let positionAbsoluteX: $$Props['positionAbsoluteX'] = 0; export let positionAbsoluteX: $$Props['positionAbsoluteX'] = 0;
export let positionAbsoluteY: $$Props['positionAbsoluteY'] = 0; export let positionAbsoluteY: $$Props['positionAbsoluteY'] = 0;
export let isConnectable: $$Props['isConnectable'] = undefined; export let isConnectable: $$Props['isConnectable'];
export let zIndex: $$Props['zIndex'];
// @todo: there must be a better way to do this // @todo: there must be a better way to do this
id; id;
+1 -2
View File
@@ -45,7 +45,7 @@ export type {
DefaultEdgeOptions DefaultEdgeOptions
} from '$lib/types/edges'; } from '$lib/types/edges';
export type { HandleComponentProps, FitViewOptions } from '$lib/types/general'; export type { HandleComponentProps, FitViewOptions } from '$lib/types/general';
export type { Node, NodeTypes, DefaultNodeOptions, BuiltInNode } from '$lib/types/nodes'; export type { Node, NodeTypes, DefaultNodeOptions, BuiltInNode, NodeProps } from '$lib/types/nodes';
export type { SvelteFlowStore } from '$lib/store/types'; export type { SvelteFlowStore } from '$lib/store/types';
// system types // system types
@@ -77,7 +77,6 @@ export {
SelectionMode, SelectionMode,
type SelectionRect, type SelectionRect,
type OnError, type OnError,
type NodeProps,
type NodeOrigin, type NodeOrigin,
type OnSelectionDrag, type OnSelectionDrag,
Position, Position,
+20 -5
View File
@@ -49,11 +49,14 @@ export type BuiltInEdge = SmoothStepEdge | BezierEdge | StepEdge;
/** /**
* Custom edge component props. * Custom edge component props.
*/ */
export type EdgeProps< export type EdgeProps<EdgeType extends Edge = Edge> = Omit<
EdgeData extends Record<string, unknown> = Record<string, unknown>, EdgeType,
EdgeType extends string | undefined = string | undefined 'sourceHandle' | 'targetHandle'
> = Omit<Edge<EdgeData, EdgeType>, 'sourceHandle' | 'targetHandle' | 'type'> & > &
EdgePosition & { EdgePosition & {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data?: any;
type: string;
markerStart?: string; markerStart?: string;
markerEnd?: string; markerEnd?: string;
sourceHandleId?: string | null; sourceHandleId?: string | null;
@@ -103,7 +106,19 @@ export type StepEdgeProps = EdgeComponentWithPathOptions<StepPathOptions>;
*/ */
export type StraightEdgeProps = Omit<EdgeComponentProps, 'sourcePosition' | 'targetPosition'>; export type StraightEdgeProps = Omit<EdgeComponentProps, 'sourcePosition' | 'targetPosition'>;
export type EdgeTypes = Record<string, ComponentType<SvelteComponent<EdgeProps>>>; export type EdgeTypes = Record<
string,
ComponentType<
SvelteComponent<
EdgeProps & {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data?: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type: any;
}
>
>
>;
export type DefaultEdgeOptions = DefaultEdgeOptionsBase<Edge>; export type DefaultEdgeOptions = DefaultEdgeOptionsBase<Edge>;
+22 -3
View File
@@ -1,5 +1,5 @@
import type { ComponentType, SvelteComponent } from 'svelte'; import type { ComponentType, SvelteComponent } from 'svelte';
import type { NodeBase, NodeProps } from '@xyflow/system'; import type { NodeBase, NodeProps as NodePropsBase } from '@xyflow/system';
/** /**
* The node data structure that gets used for the nodes prop. * The node data structure that gets used for the nodes prop.
@@ -7,13 +7,32 @@ import type { NodeBase, NodeProps } from '@xyflow/system';
*/ */
export type Node< export type Node<
NodeData extends Record<string, unknown> = Record<string, unknown>, NodeData extends Record<string, unknown> = Record<string, unknown>,
NodeType extends string | undefined = string | undefined NodeType extends string = string
> = NodeBase<NodeData, NodeType> & { > = NodeBase<NodeData, NodeType> & {
class?: string; class?: string;
style?: string; style?: string;
}; };
export type NodeTypes = Record<string, ComponentType<SvelteComponent<NodeProps>>>; // @todo: currently generics for nodes are not really supported
// let's fix `type: any` when we migrate to Svelte 5
export type NodeProps<NodeType extends Node = Node> = NodePropsBase<NodeType> & {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type: any;
};
export type NodeTypes = Record<
string,
ComponentType<
SvelteComponent<
NodeProps & {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type: any;
}
>
>
>;
export type DefaultNodeOptions = Partial<Omit<Node, 'id'>>; export type DefaultNodeOptions = Partial<Omit<Node, 'id'>>;
+13 -19
View File
@@ -10,7 +10,7 @@ import { Optional } from '../utils/types';
*/ */
export type NodeBase< export type NodeBase<
NodeData extends Record<string, unknown> = Record<string, unknown>, NodeData extends Record<string, unknown> = Record<string, unknown>,
NodeType extends string | undefined = string | undefined NodeType extends string = string
> = { > = {
/** Unique id of a node */ /** Unique id of a node */
id: string; id: string;
@@ -82,25 +82,19 @@ export type NodeBase<
* The node data structure that gets used for the nodes prop. * The node data structure that gets used for the nodes prop.
* *
* @public * @public
* @param id - The id of the node.
*/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any export type NodeProps<NodeType extends NodeBase> = Pick<
export type NodeProps<NodeData = any> = { NodeType,
id: NodeBase['id']; 'id' | 'data' | 'width' | 'height' | 'sourcePosition' | 'targetPosition' | 'selected' | 'dragHandle'
data: NodeData; > &
dragHandle: NodeBase['dragHandle']; Required<Pick<NodeType, 'type' | 'dragging' | 'zIndex'>> & {
type: NodeBase['type']; /** whether a node is connectable or not */
selected: NodeBase['selected']; isConnectable: boolean;
isConnectable: NodeBase['connectable']; /** position absolute x value */
zIndex: NodeBase['zIndex']; positionAbsoluteX: number;
positionAbsoluteX: number; /** position absolute x value */
positionAbsoluteY: number; positionAbsoluteY: number;
width?: number; };
height?: number;
dragging: NodeBase['dragging'];
sourcePosition?: NodeBase['sourcePosition'];
targetPosition?: NodeBase['targetPosition'];
};
export type NodeHandleBounds = { export type NodeHandleBounds = {
source: HandleElement[] | null; source: HandleElement[] | null;