refactor(react/svelte): cleanup types
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { get, type Writable } from 'svelte/store';
|
||||
import { drag as d3Drag, type D3DragEvent, type SubjectPosition } from 'd3-drag';
|
||||
import { select } from 'd3-selection';
|
||||
import type { XYPosition, CoordinateExtent, Transform, Node as RFNode } from '@reactflow/system';
|
||||
import type { XYPosition, CoordinateExtent, Transform } from '@reactflow/system';
|
||||
|
||||
import { getDragItems, hasSelector, calcNextPosition } from './utils';
|
||||
import type { Node } from '$lib/types';
|
||||
@@ -62,7 +62,7 @@ export default function drag(
|
||||
|
||||
dragItems = dragItems.map((n) => {
|
||||
const nextPosition = { x: x - n.distance.x, y: y - n.distance.y };
|
||||
const updatedPos = calcNextPosition(n, nextPosition, get(nodes) as RFNode[]);
|
||||
const updatedPos = calcNextPosition(n, nextPosition, get(nodes));
|
||||
|
||||
// we want to make sure that we only fire a change event when there is a changes
|
||||
hasChange =
|
||||
@@ -89,7 +89,7 @@ export default function drag(
|
||||
const pointerPos = getPointerPosition(event);
|
||||
console.log(pointerPos);
|
||||
lastPos = pointerPos;
|
||||
dragItems = getDragItems(get(nodes) as RFNode[], pointerPos, nodeId);
|
||||
dragItems = getDragItems(get(nodes), pointerPos, nodeId);
|
||||
})
|
||||
.on('drag', (event: UseDragEvent) => {
|
||||
const pointerPos = getPointerPosition(event);
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import type {
|
||||
CoordinateExtent,
|
||||
Node,
|
||||
NodeDragItem,
|
||||
NodeInternals,
|
||||
NodeOrigin,
|
||||
XYPosition
|
||||
} from '@reactflow/system';
|
||||
import type { CoordinateExtent, NodeDragItem, NodeOrigin, XYPosition } from '@reactflow/system';
|
||||
import { clampPosition, isNumeric } from '@reactflow/utils';
|
||||
|
||||
import { clampPosition, isNumeric } from '../../../utils';
|
||||
import type { Node } from '$lib/types';
|
||||
|
||||
export function isParentSelected(node: Node, nodes: Node[]): boolean {
|
||||
if (!node.parentNode) {
|
||||
@@ -122,31 +116,3 @@ export function calcNextPosition(
|
||||
positionAbsolute
|
||||
};
|
||||
}
|
||||
|
||||
// returns two params:
|
||||
// 1. the dragged node (or the first of the list, if we are dragging a node selection)
|
||||
// 2. array of selected nodes (for multi selections)
|
||||
export function getEventHandlerParams({
|
||||
nodeId,
|
||||
dragItems,
|
||||
nodeInternals
|
||||
}: {
|
||||
nodeId?: string;
|
||||
dragItems: NodeDragItem[];
|
||||
nodeInternals: NodeInternals;
|
||||
}): [Node, Node[]] {
|
||||
const extentedDragItems: Node[] = dragItems.map((n) => {
|
||||
const node = nodeInternals.get(n.id)!;
|
||||
|
||||
return {
|
||||
...node,
|
||||
position: n.position,
|
||||
positionAbsolute: n.positionAbsolute
|
||||
};
|
||||
});
|
||||
|
||||
return [
|
||||
nodeId ? extentedDragItems.find((n) => n.id === nodeId)! : extentedDragItems[0],
|
||||
extentedDragItems
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import type { Writable } from 'svelte/store';
|
||||
import { select } from 'd3-selection';
|
||||
import { zoom as d3Zoom, zoomIdentity } from 'd3-zoom';
|
||||
import type { D3ZoomEvent } from 'd3-zoom';
|
||||
import { zoom as d3Zoom, zoomIdentity, type D3ZoomEvent } from 'd3-zoom';
|
||||
import type { D3SelectionInstance, D3ZoomInstance, Transform } from '@reactflow/system';
|
||||
|
||||
const isWrappedWithClass = (event: any, className: string | undefined) =>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { get, type Writable } from 'svelte/store';
|
||||
import {
|
||||
getHostForElement,
|
||||
calcAutoPan,
|
||||
@@ -10,7 +11,6 @@ import type {
|
||||
HandleType,
|
||||
Connection,
|
||||
ConnectionMode,
|
||||
Node,
|
||||
XYPosition,
|
||||
Transform
|
||||
} from '@reactflow/system';
|
||||
@@ -25,8 +25,7 @@ import {
|
||||
type ConnectionHandle,
|
||||
type ValidConnectionFunc
|
||||
} from './utils';
|
||||
import { get, type Writable } from 'svelte/store';
|
||||
import type { ConnectionData } from '$lib/types';
|
||||
import type { ConnectionData, Node } from '$lib/types';
|
||||
|
||||
export function handlePointerDown({
|
||||
event,
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
type $$Props = HandleProps;
|
||||
|
||||
export let id: $$Props['id'] = undefined;
|
||||
export let type: $$Props['type'] = 'source';
|
||||
export let position: $$Props['position'] = Position.Top;
|
||||
export let id: $$Props['id'] = undefined;
|
||||
export let isConnectable: $$Props['isConnectable'] = true;
|
||||
export let isValidConnection: $$Props['isValidConnection'] = (_: Connection) => true;
|
||||
let className: string | null = null;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { internalsSymbol, ConnectionMode, type ConnectionStatus } from '@reactflow/system';
|
||||
import type { Connection, HandleType, XYPosition, Node, NodeHandleBounds } from '@reactflow/system';
|
||||
import type { Connection, HandleType, XYPosition, NodeHandleBounds } from '@reactflow/system';
|
||||
import { getEventPosition } from '@reactflow/utils';
|
||||
|
||||
import type { Node } from '$lib/types';
|
||||
|
||||
export type ConnectionHandle = {
|
||||
id: string | null;
|
||||
type: HandleType;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { BaseEdgeProps } from '$lib/types';
|
||||
import EdgeLabelRenderer from '$lib/components/EdgeLabelRenderer/index.svelte';
|
||||
import type { BaseEdgeProps } from '$lib/types';
|
||||
|
||||
type $$Props = BaseEdgeProps;
|
||||
|
||||
export let path: $$Props['path'];
|
||||
export let label: $$Props['label'];
|
||||
export let labelX: $$Props['labelX'];
|
||||
export let labelY: $$Props['labelY'];
|
||||
export let path: $$Props['path'] = '';
|
||||
export let label: $$Props['label'] = undefined;
|
||||
export let labelX: $$Props['labelX'] = undefined;
|
||||
export let labelY: $$Props['labelY'] = undefined;
|
||||
export let interactionWidth: $$Props['interactionWidth'] = 20;
|
||||
</script>
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
import { useStore } from '$lib/store';
|
||||
import BezierEdge from '$lib/components/edges/StraightEdge.svelte';
|
||||
import type { EdgeProps, WrapEdgeProps } from '$lib/types';
|
||||
import type { EdgeProps, EdgeLayouted } from '$lib/types';
|
||||
|
||||
type $$Props = WrapEdgeProps;
|
||||
type $$Props = EdgeLayouted;
|
||||
|
||||
export let id: $$Props['id'];
|
||||
export let type: $$Props['type'] = 'default';
|
||||
@@ -16,6 +16,8 @@
|
||||
export let sourceY: $$Props['sourceY'] = 0;
|
||||
export let targetX: $$Props['targetX'] = 0;
|
||||
export let targetY: $$Props['targetY'] = 0;
|
||||
export let sourceHandleId: $$Props['sourceHandleId'] = undefined;
|
||||
export let targetHandleId: $$Props['targetHandleId'] = undefined;
|
||||
export let sourcePosition: $$Props['sourcePosition'] = Position.Bottom;
|
||||
export let targetPosition: $$Props['targetPosition'] = Position.Top;
|
||||
export let animated: $$Props['animated'] = false;
|
||||
|
||||
@@ -30,8 +30,11 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { useStore } from '$lib/store';
|
||||
import { SelectionMode, type Node, type Edge } from '@reactflow/system';
|
||||
import { getConnectedEdges, getEventPosition, getNodesInside } from '@reactflow/utils';
|
||||
import { SelectionMode } from '@reactflow/system';
|
||||
import { getEventPosition, getNodesInside } from '@reactflow/utils';
|
||||
|
||||
import { getConnectedEdges} from '$lib/utils';
|
||||
import type { Node, Edge } from '$lib/types';
|
||||
|
||||
const {
|
||||
nodes,
|
||||
@@ -107,8 +110,8 @@
|
||||
height: Math.abs(mousePos.y - startY)
|
||||
};
|
||||
|
||||
selectedNodes = getNodesInside(
|
||||
new Map($nodes.map((node) => [node.id, node])),
|
||||
selectedNodes = getNodesInside<Node>(
|
||||
$nodes,
|
||||
nextUserSelectRect,
|
||||
$transform,
|
||||
selectionMode === SelectionMode.Partial,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { setContext, onMount } from 'svelte';
|
||||
import { ConnectionLineType } from '@reactflow/system';
|
||||
import cc from 'classcat';
|
||||
|
||||
import { key, createStore } from '$lib/store';
|
||||
@@ -23,7 +24,7 @@
|
||||
export let nodeTypes: $$Props['nodeTypes'] = undefined;
|
||||
export let selectionKey: $$Props['selectionKey'] = undefined;
|
||||
export let deleteKey: $$Props['deleteKey'] = undefined;
|
||||
export let connectionLineType: $$Props['connectionLineType'] = undefined;
|
||||
export let connectionLineType: $$Props['connectionLineType'] = ConnectionLineType.Bezier;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
@@ -51,27 +52,6 @@
|
||||
});
|
||||
});
|
||||
|
||||
// $: {
|
||||
// const updatableProps = {
|
||||
// defaultEdgeOptions,
|
||||
// connectionMode,
|
||||
// snapToGrid,
|
||||
// snapGrid,
|
||||
// nodesDraggable,
|
||||
// connectOnClick,
|
||||
// fitViewOnInit: fitView,
|
||||
// fitViewOnInitOptions: fitViewOptions,
|
||||
// };
|
||||
|
||||
// Object.keys(updatableProps).forEach((key) => {
|
||||
// store.update((state) => ({
|
||||
// ...state,
|
||||
// [key]: valuesToUpdate[key],
|
||||
// }));
|
||||
|
||||
// });
|
||||
// }
|
||||
|
||||
$: {
|
||||
store.setNodes(nodes);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ export { Controls, ControlButton } from '$lib/plugins/Controls';
|
||||
export { Background, BackgroundVariant } from '$lib/plugins/Background';
|
||||
export { Minimap } from '$lib/plugins/Minimap';
|
||||
export { default as Panel } from '$lib/container/Panel/index.svelte';
|
||||
|
||||
export * from '$lib/types';
|
||||
export * from '$lib/utils';
|
||||
|
||||
export default SvelteFlow;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { derived } from 'svelte/store';
|
||||
import { getBezierPath, getSmoothStepPath, getStraightPath } from '@reactflow/edge-utils';
|
||||
import { ConnectionLineType, ConnectionMode, Position } from '@reactflow/system';
|
||||
import { ConnectionLineType, ConnectionMode, Position, internalsSymbol } from '@reactflow/system';
|
||||
|
||||
import type { SvelteFlowStoreState } from './types';
|
||||
import { derived } from 'svelte/store';
|
||||
|
||||
const oppositePosition = {
|
||||
[Position.Left]: Position.Right,
|
||||
@@ -20,21 +20,21 @@ export function getConnectionPath(store: SvelteFlowStoreState) {
|
||||
store.nodes,
|
||||
store.transform
|
||||
],
|
||||
([$connection, $connectionLineType, $connectionMode, $nodes, $transform]) => {
|
||||
if (!$connection.nodeId) {
|
||||
([connection, connectionLineType, connectionMode, nodes, transform]) => {
|
||||
if (!connection.nodeId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fromNode = $nodes.find((n) => n.id === $connection.nodeId);
|
||||
const fromNode = nodes.find((n) => n.id === connection.nodeId);
|
||||
const fromHandleBounds = fromNode?.[internalsSymbol]?.handleBounds;
|
||||
const handleBoundsStrict = fromHandleBounds?.[$connection.handleType || 'source'] || [];
|
||||
const handleBoundsStrict = fromHandleBounds?.[connection.handleType || 'source'] || [];
|
||||
const handleBoundsLoose = handleBoundsStrict
|
||||
? handleBoundsStrict
|
||||
: fromHandleBounds?.[$connection.handleType === 'source' ? 'target' : 'source']!;
|
||||
: fromHandleBounds?.[connection.handleType === 'source' ? 'target' : 'source']!;
|
||||
const handleBounds =
|
||||
$connectionMode === ConnectionMode.Strict ? handleBoundsStrict : handleBoundsLoose;
|
||||
const fromHandle = $connection.handleId
|
||||
? handleBounds.find((d) => d.id === $connection.handleId)
|
||||
connectionMode === ConnectionMode.Strict ? handleBoundsStrict : handleBoundsLoose;
|
||||
const fromHandle = connection.handleId
|
||||
? handleBounds.find((d) => d.id === connection.handleId)
|
||||
: handleBounds[0];
|
||||
const fromHandleX = fromHandle
|
||||
? fromHandle.x + fromHandle.width / 2
|
||||
@@ -49,22 +49,22 @@ export function getConnectionPath(store: SvelteFlowStoreState) {
|
||||
sourceX: fromX,
|
||||
sourceY: fromY,
|
||||
sourcePosition: fromPosition,
|
||||
targetX: (($connection.position?.x ?? 0) - $transform[0]) / $transform[2],
|
||||
targetY: (($connection.position?.y ?? 0) - $transform[1]) / $transform[2],
|
||||
targetX: ((connection.position?.x ?? 0) - transform[0]) / transform[2],
|
||||
targetY: ((connection.position?.y ?? 0) - transform[1]) / transform[2],
|
||||
targetPosition: toPosition
|
||||
};
|
||||
|
||||
let path = '';
|
||||
|
||||
if ($connectionLineType === ConnectionLineType.Bezier) {
|
||||
if (connectionLineType === ConnectionLineType.Bezier) {
|
||||
// we assume the destination position is opposite to the source position
|
||||
[path] = getBezierPath(pathParams);
|
||||
} else if ($connectionLineType === ConnectionLineType.Step) {
|
||||
} else if (connectionLineType === ConnectionLineType.Step) {
|
||||
[path] = getSmoothStepPath({
|
||||
...pathParams,
|
||||
borderRadius: 0
|
||||
});
|
||||
} else if ($connectionLineType === ConnectionLineType.SmoothStep) {
|
||||
} else if (connectionLineType === ConnectionLineType.SmoothStep) {
|
||||
[path] = getSmoothStepPath(pathParams);
|
||||
} else {
|
||||
[path] = getStraightPath(pathParams);
|
||||
|
||||
@@ -2,7 +2,7 @@ import { derived } from 'svelte/store';
|
||||
import { Position } from '@reactflow/system';
|
||||
|
||||
import { getEdgePositions, getHandle, getNodeData } from '$lib/container/EdgeRenderer/utils';
|
||||
import type { WrapEdgeProps } from '$lib/types';
|
||||
import type { EdgeLayouted } from '$lib/types';
|
||||
import type { SvelteFlowStoreState } from './types';
|
||||
|
||||
export function getEdgesLayouted(store: SvelteFlowStoreState) {
|
||||
@@ -56,6 +56,6 @@ export function getEdgesLayouted(store: SvelteFlowStoreState) {
|
||||
targetHandleId
|
||||
};
|
||||
})
|
||||
.filter((e) => e !== null) as WrapEdgeProps[];
|
||||
.filter((e) => e !== null) as EdgeLayouted[];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getContext } from 'svelte';
|
||||
import { get } from 'svelte/store';
|
||||
import { zoomIdentity } from 'd3-zoom';
|
||||
import {
|
||||
type Transform,
|
||||
type NodeDragItem,
|
||||
@@ -7,23 +8,14 @@ import {
|
||||
internalsSymbol,
|
||||
type NodeOrigin,
|
||||
type ViewportHelperFunctionOptions,
|
||||
type Node as RFNode,
|
||||
type Connection,
|
||||
type XYPosition,
|
||||
type CoordinateExtent
|
||||
} from '@reactflow/system';
|
||||
import {
|
||||
fitView as fitViewUtil,
|
||||
getConnectedEdges,
|
||||
getD3Transition,
|
||||
getDimensions,
|
||||
addEdge as addEdgeUtil
|
||||
} from '@reactflow/utils';
|
||||
import { zoomIdentity } from 'd3-zoom';
|
||||
import { fitView as fitViewUtil, getD3Transition, getDimensions } from '@reactflow/utils';
|
||||
|
||||
import { getHandleBounds } from '../../utils';
|
||||
import { getHandleBounds, getConnectedEdges, addEdge as addEdgeUtil } from '$lib/utils';
|
||||
import type { EdgeTypes, NodeTypes, Node, Edge, ConnectionData } from '$lib/types';
|
||||
|
||||
import { getEdgesLayouted } from './edges-layouted';
|
||||
import { getConnectionPath } from './connection-path';
|
||||
import { initConnectionData, initialStoreState } from './initial-store';
|
||||
@@ -170,7 +162,7 @@ export function createStore({
|
||||
|
||||
return fitViewUtil(
|
||||
{
|
||||
nodes: get(store.nodes) as RFNode[],
|
||||
nodes: get(store.nodes),
|
||||
width: get(store.width),
|
||||
height: get(store.height),
|
||||
minZoom: 0.2,
|
||||
@@ -227,7 +219,7 @@ export function createStore({
|
||||
const initialHitEdges = deletableEdges.filter((e) => edgeIds.includes(e.id));
|
||||
|
||||
if (nodesToRemove || initialHitEdges) {
|
||||
const connectedEdges = getConnectedEdges(nodesToRemove as RFNode[], deletableEdges);
|
||||
const connectedEdges = getConnectedEdges(nodesToRemove, deletableEdges);
|
||||
const edgesToRemove = [...initialHitEdges, ...connectedEdges];
|
||||
const edgeIdsToRemove = edgesToRemove.reduce<string[]>((res, edge) => {
|
||||
if (!res.includes(edge.id)) {
|
||||
|
||||
@@ -5,15 +5,15 @@ import {
|
||||
type D3SelectionInstance,
|
||||
ConnectionMode,
|
||||
ConnectionLineType,
|
||||
type SelectionRect,
|
||||
type Transform,
|
||||
type NodeOrigin,
|
||||
type Rect
|
||||
type NodeOrigin
|
||||
} from '@reactflow/system';
|
||||
|
||||
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 { Node, Edge, ConnectionData, NodeTypes, EdgeTypes } from '$lib/types';
|
||||
import type { Node, Edge, ConnectionData, NodeTypes, EdgeTypes, EdgeLayouted } 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';
|
||||
@@ -29,7 +29,7 @@ export const initConnectionData = {
|
||||
export const initialStoreState = {
|
||||
nodes: writable<Node[]>([]),
|
||||
edges: writable<Edge[]>([]),
|
||||
edgesLayouted: readable<Edge[]>([]),
|
||||
edgesLayouted: readable<EdgeLayouted[]>([]),
|
||||
height: writable<number>(500),
|
||||
width: writable<number>(500),
|
||||
nodeOrigin: writable<NodeOrigin>([0.5, 0.5]),
|
||||
@@ -39,7 +39,7 @@ export const initialStoreState = {
|
||||
}),
|
||||
id: writable<string | null>(null),
|
||||
dragging: writable<boolean>(false),
|
||||
selectionRect: writable<(Rect & { startX: number; startY: number }) | null>(null),
|
||||
selectionRect: writable<SelectionRect | null>(null),
|
||||
selectionKeyPressed: writable<boolean>(false),
|
||||
multiselectionKeyPressed: writable<boolean>(false),
|
||||
deleteKeyPressed: writable<boolean>(false),
|
||||
|
||||
@@ -6,7 +6,7 @@ import type {
|
||||
NodeDragItem
|
||||
} from '@reactflow/system';
|
||||
|
||||
import { initialStoreState } from './initial-store';
|
||||
import type { initialStoreState } from './initial-store';
|
||||
import type { Node, Edge, ConnectionData } from '$lib/types';
|
||||
|
||||
export type SvelteFlowStoreActions = {
|
||||
@@ -1,4 +1,66 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import type { SvelteComponentTyped } from 'svelte';
|
||||
import type { EdgeProps } from '$lib/types';
|
||||
import type {
|
||||
BaseEdge,
|
||||
BezierPathOptions,
|
||||
Position,
|
||||
SmoothStepPathOptions
|
||||
} from '@reactflow/system';
|
||||
|
||||
import type { Node } from '$lib/types';
|
||||
|
||||
export type DefaultEdge<EdgeData = any> = BaseEdge<EdgeData> & {
|
||||
label?: string;
|
||||
style?: string;
|
||||
class?: string;
|
||||
sourceNode?: Node;
|
||||
targetNode?: Node;
|
||||
};
|
||||
|
||||
type SmoothStepEdgeType<T> = DefaultEdge<T> & {
|
||||
type: 'smoothstep';
|
||||
pathOptions?: SmoothStepPathOptions;
|
||||
};
|
||||
|
||||
type BezierEdgeType<T> = DefaultEdge<T> & {
|
||||
type: 'default';
|
||||
pathOptions?: BezierPathOptions;
|
||||
};
|
||||
|
||||
export type Edge<T = any> = DefaultEdge<T> | SmoothStepEdgeType<T> | BezierEdgeType<T>;
|
||||
|
||||
export type EdgeLayouted = Omit<Edge, 'sourceHandle' | 'targetHandle'> & {
|
||||
sourceX: number;
|
||||
sourceY: number;
|
||||
targetX: number;
|
||||
targetY: number;
|
||||
sourcePosition: Position;
|
||||
targetPosition: Position;
|
||||
sourceHandleId?: string;
|
||||
targetHandleId?: string;
|
||||
};
|
||||
|
||||
export type EdgeProps = Pick<
|
||||
EdgeLayouted,
|
||||
| 'id'
|
||||
| 'source'
|
||||
| 'target'
|
||||
| 'sourceX'
|
||||
| 'sourceY'
|
||||
| 'targetX'
|
||||
| 'targetY'
|
||||
| 'sourcePosition'
|
||||
| 'targetPosition'
|
||||
| 'animated'
|
||||
| 'selected'
|
||||
| 'label'
|
||||
| 'interactionWidth'
|
||||
>;
|
||||
|
||||
export type BaseEdgeProps = Pick<EdgeProps, 'interactionWidth' | 'label'> & {
|
||||
path: string;
|
||||
labelX?: number;
|
||||
labelY?: number;
|
||||
};
|
||||
|
||||
export type EdgeTypes = Record<string, typeof SvelteComponentTyped<EdgeProps>>;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Node, NodeTypes } from './nodes';
|
||||
import type { ShortcutModifierDefinition } from '@svelte-put/shortcut';
|
||||
import type { ConnectionLineType, Edge, HandleType, XYPosition } from '@reactflow/system';
|
||||
import type { ConnectionLineType, HandleType, XYPosition } from '@reactflow/system';
|
||||
|
||||
import type { Node, NodeTypes, Edge } from '.';
|
||||
|
||||
export type KeyModifier = ShortcutModifierDefinition;
|
||||
export type KeyDefinitionObject = { key: string; modifier?: KeyModifier };
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
export type {
|
||||
Position,
|
||||
XYPosition,
|
||||
Edge,
|
||||
BaseEdgeProps,
|
||||
WrapEdgeProps,
|
||||
EdgeProps
|
||||
} from '@reactflow/system';
|
||||
|
||||
export * from './nodes';
|
||||
export * from './edges';
|
||||
export * from './general';
|
||||
|
||||
@@ -1,33 +1,17 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import type { SvelteComponentTyped } from 'svelte';
|
||||
import type { internalsSymbol, NodeHandleBounds, Position, XYPosition } from '@reactflow/system';
|
||||
import type { BaseNode } from '@reactflow/system';
|
||||
|
||||
// @todo: currently the helper function only like Node from '@reactflow/core'
|
||||
// we need a base node type or helpes that accept Node like types
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type Node<NodeData = any> = {
|
||||
id: string;
|
||||
type: string;
|
||||
data: NodeData;
|
||||
position: XYPosition;
|
||||
sourcePosition?: Position;
|
||||
targetPosition?: Position;
|
||||
positionAbsolute?: XYPosition;
|
||||
|
||||
width?: number;
|
||||
height?: number;
|
||||
selected?: boolean;
|
||||
export type Node<
|
||||
NodeData = any,
|
||||
NodeType extends string | undefined = string | undefined
|
||||
> = BaseNode<NodeData, NodeType> & {
|
||||
class?: string;
|
||||
style?: string;
|
||||
deletable?: boolean;
|
||||
// not supported yet
|
||||
parentNode?: string;
|
||||
|
||||
// only used internally
|
||||
[internalsSymbol]?: {
|
||||
z?: number;
|
||||
handleBounds?: NodeHandleBounds;
|
||||
isParent?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import type { HandleElement, Position } from '@reactflow/system';
|
||||
import {
|
||||
isNodeBase,
|
||||
isEdgeBase,
|
||||
addEdgeBase,
|
||||
getOutgoersBase,
|
||||
getIncomersBase,
|
||||
updateEdgeBase,
|
||||
getConnectedEdgesBase,
|
||||
getDimensions
|
||||
} from '@reactflow/utils';
|
||||
import type { Edge, Node } from '$lib/types';
|
||||
|
||||
export const isNode = isNodeBase<Node, Edge>;
|
||||
export const isEdge = isEdgeBase<Node, Edge>;
|
||||
export const getOutgoers = getOutgoersBase<Node, Edge>;
|
||||
export const getIncomers = getIncomersBase<Node, Edge>;
|
||||
export const addEdge = addEdgeBase<Edge>;
|
||||
export const updateEdge = updateEdgeBase<Edge>;
|
||||
export const getConnectedEdges = getConnectedEdgesBase<Node, Edge>;
|
||||
|
||||
export const getHandleBounds = (
|
||||
selector: string,
|
||||
nodeElement: HTMLDivElement,
|
||||
zoom: number
|
||||
): HandleElement[] | null => {
|
||||
const handles = nodeElement.querySelectorAll(selector);
|
||||
|
||||
if (!handles || !handles.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const handlesArray = Array.from(handles) as HTMLDivElement[];
|
||||
const nodeBounds = nodeElement.getBoundingClientRect();
|
||||
|
||||
return handlesArray.map((handle): HandleElement => {
|
||||
const handleBounds = handle.getBoundingClientRect();
|
||||
|
||||
return {
|
||||
id: handle.getAttribute('data-handleid'),
|
||||
position: handle.getAttribute('data-handlepos') as unknown as Position,
|
||||
x: (handleBounds.left - nodeBounds.left) / zoom,
|
||||
y: (handleBounds.top - nodeBounds.top) / zoom,
|
||||
...getDimensions(handle)
|
||||
};
|
||||
});
|
||||
};
|
||||
@@ -1,97 +0,0 @@
|
||||
import {
|
||||
type CoordinateExtent,
|
||||
type Dimensions,
|
||||
type XYPosition,
|
||||
type Node,
|
||||
type XYZPosition,
|
||||
type HandleElement,
|
||||
internalsSymbol,
|
||||
Position
|
||||
} from '@reactflow/system';
|
||||
|
||||
export const clamp = (val: number, min = 0, max = 1): number => Math.min(Math.max(val, min), max);
|
||||
|
||||
export const clampPosition = (position: XYPosition = { x: 0, y: 0 }, extent: CoordinateExtent) => ({
|
||||
x: clamp(position.x, extent[0][0], extent[1][0]),
|
||||
y: clamp(position.y, extent[0][1], extent[1][1])
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const isNumeric = (n: any): n is number => !isNaN(n) && isFinite(n);
|
||||
|
||||
export const getDimensions = (node: HTMLDivElement): Dimensions => ({
|
||||
width: node.offsetWidth,
|
||||
height: node.offsetHeight
|
||||
});
|
||||
|
||||
type ParentNodes = Record<string, boolean>;
|
||||
|
||||
function calculateXYZPosition(node: Node, nodes: Node[], result: XYZPosition): XYZPosition {
|
||||
if (!node.parentNode) {
|
||||
return result;
|
||||
}
|
||||
const parentNode = nodes.find((n) => n.id === node.parentNode)!;
|
||||
const parentNodePosition = parentNode.positionAbsolute!;
|
||||
|
||||
return calculateXYZPosition(parentNode, nodes, {
|
||||
x: (result.x ?? 0) + parentNodePosition.x,
|
||||
y: (result.y ?? 0) + parentNodePosition.y,
|
||||
z:
|
||||
(parentNode[internalsSymbol]?.z ?? 0) > (result.z ?? 0)
|
||||
? parentNode[internalsSymbol]?.z ?? 0
|
||||
: result.z ?? 0
|
||||
});
|
||||
}
|
||||
|
||||
export function updateAbsoluteNodePositions(nodes: Node[], parentNodes?: ParentNodes) {
|
||||
nodes.forEach((node) => {
|
||||
if (node.parentNode) {
|
||||
throw new Error(`Parent node ${node.parentNode} not found`);
|
||||
}
|
||||
|
||||
if (node.parentNode || parentNodes?.[node.id]) {
|
||||
const { x, y, z } = calculateXYZPosition(node, nodes, {
|
||||
...node.position,
|
||||
z: node[internalsSymbol]?.z ?? 0
|
||||
});
|
||||
|
||||
node.positionAbsolute = {
|
||||
x,
|
||||
y
|
||||
};
|
||||
|
||||
node[internalsSymbol]!.z = z;
|
||||
|
||||
if (parentNodes?.[node.id]) {
|
||||
node[internalsSymbol]!.isParent = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const getHandleBounds = (
|
||||
selector: string,
|
||||
nodeElement: HTMLDivElement,
|
||||
zoom: number
|
||||
): HandleElement[] | null => {
|
||||
const handles = nodeElement.querySelectorAll(selector);
|
||||
|
||||
if (!handles || !handles.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const handlesArray = Array.from(handles) as HTMLDivElement[];
|
||||
const nodeBounds = nodeElement.getBoundingClientRect();
|
||||
|
||||
return handlesArray.map((handle): HandleElement => {
|
||||
const handleBounds = handle.getBoundingClientRect();
|
||||
|
||||
return {
|
||||
id: handle.getAttribute('data-handleid'),
|
||||
position: handle.getAttribute('data-handlepos') as unknown as Position,
|
||||
x: (handleBounds.left - nodeBounds.left) / zoom,
|
||||
y: (handleBounds.top - nodeBounds.top) / zoom,
|
||||
...getDimensions(handle)
|
||||
};
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user