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:
@@ -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>
|
||||||
|
|||||||
@@ -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} />
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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[];
|
||||||
|
|||||||
@@ -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>;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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>;
|
||||||
|
|
||||||
|
|||||||
@@ -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'>>;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user