use generics across the library

This commit is contained in:
peterkogo
2025-04-17 15:36:39 +02:00
parent cf1e0bee81
commit 353c661dd8
27 changed files with 198 additions and 152 deletions
@@ -1,4 +1,4 @@
<script lang="ts">
<script lang="ts" generics="NodeType extends Node = Node, EdgeType extends Edge = Edge">
import type { Component } from 'svelte';
import {
ConnectionLineType,
@@ -9,6 +9,7 @@
} from '@xyflow/system';
import type { SvelteFlowStore } from '$lib/store/types';
import type { Node, Edge } from '$lib/types';
let {
store = $bindable(),
@@ -17,7 +18,7 @@
style,
LineComponent
}: {
store: SvelteFlowStore;
store: SvelteFlowStore<NodeType, EdgeType>;
type: ConnectionLineType;
containerStyle?: string;
style?: string;
@@ -1,11 +1,11 @@
<script lang="ts">
<script lang="ts" generics="NodeType extends Node = Node, EdgeType extends Edge = Edge">
import { setContext } from 'svelte';
import { elementSelectionKeys, getMarkerId } from '@xyflow/system';
import { BezierEdgeInternal } from '$lib/components/edges';
import type { EdgeLayouted, Edge, EdgeEvents } from '$lib/types';
import type { Node, EdgeLayouted, Edge, EdgeEvents } from '$lib/types';
import type { SvelteFlowStore } from '$lib/store/types';
const {
@@ -15,7 +15,10 @@
onedgecontextmenu,
onedgepointerenter,
onedgepointerleave
}: { store: SvelteFlowStore; edge: EdgeLayouted } & EdgeEvents = $props();
}: {
store: SvelteFlowStore<NodeType, EdgeType>;
edge: EdgeLayouted<EdgeType>;
} & EdgeEvents<EdgeType> = $props();
let {
source,
@@ -76,7 +79,7 @@
function onmouseevent<T = MouseEvent>(
event: T,
callback: ({ edge, event }: { edge: Edge; event: T }) => void
callback: ({ edge, event }: { edge: EdgeType; event: T }) => void
) {
const edge = store.edgeLookup.get(id);
@@ -1,4 +1,4 @@
<script lang="ts">
<script lang="ts" generics="NodeType extends Node = Node, EdgeType extends Edge = Edge">
import {
shortcut,
type ShortcutEventDetail,
@@ -7,7 +7,7 @@
import { isInputDOMNode, isMacOs } from '@xyflow/system';
import type { KeyHandlerProps } from './types';
import type { KeyDefinition, KeyDefinitionObject } from '$lib/types';
import type { Node, Edge, KeyDefinition, KeyDefinitionObject } from '$lib/types';
import { useSvelteFlow } from '$lib/hooks/useSvelteFlow.svelte';
let {
@@ -17,9 +17,9 @@
deleteKey = 'Backspace',
panActivationKey = ' ',
zoomActivationKey = isMacOs() ? 'Meta' : 'Control'
}: KeyHandlerProps = $props();
}: KeyHandlerProps<NodeType, EdgeType> = $props();
let { deleteElements } = useSvelteFlow();
let { deleteElements } = useSvelteFlow<NodeType, EdgeType>();
function isKeyObject(key?: KeyDefinition | null): key is KeyDefinitionObject {
return key !== null && typeof key === 'object';
@@ -1,8 +1,8 @@
import type { SvelteFlowStore } from '$lib/store/types';
import type { KeyDefinition } from '$lib/types';
import type { Node, Edge, KeyDefinition } from '$lib/types';
export type KeyHandlerProps = {
store: SvelteFlowStore;
export type KeyHandlerProps<NodeType extends Node = Node, EdgeType extends Edge = Edge> = {
store: SvelteFlowStore<NodeType, EdgeType>;
selectionKey?: KeyDefinition | KeyDefinition[] | null;
multiSelectionKey?: KeyDefinition | KeyDefinition[] | null;
deleteKey?: KeyDefinition | KeyDefinition[] | null;
@@ -1,4 +1,4 @@
<script lang="ts">
<script lang="ts" generics="NodeType extends Node = Node, EdgeType extends Edge = Edge">
import { arrowKeyDiffs, getInternalNodesBounds, isNumeric, type Rect } from '@xyflow/system';
import { Selection } from '$lib/components/Selection';
@@ -6,6 +6,7 @@
import type { NodeSelectionProps } from './types';
import { toPxString } from '$lib/utils';
import type { Node, Edge } from '$lib/types';
let {
store = $bindable(),
@@ -14,7 +15,7 @@
onnodedragstop,
onselectionclick,
onselectioncontextmenu
}: NodeSelectionProps = $props();
}: NodeSelectionProps<NodeType, EdgeType> = $props();
let ref = $state<HTMLDivElement>();
@@ -63,13 +64,13 @@
disabled: false,
store,
onDrag: (event, _, __, nodes) => {
onnodedrag?.({ event, targetNode: null, nodes });
onnodedrag?.({ event, targetNode: null, nodes: nodes as NodeType[] });
},
onDragStart: (event, _, __, nodes) => {
onnodedragstart?.({ event, targetNode: null, nodes });
onnodedragstart?.({ event, targetNode: null, nodes: nodes as NodeType[] });
},
onDragStop: (event, _, __, nodes) => {
onnodedragstop?.({ event, targetNode: null, nodes });
onnodedragstop?.({ event, targetNode: null, nodes: nodes as NodeType[] });
}
}}
{oncontextmenu}
@@ -1,5 +1,7 @@
import type { SvelteFlowStore } from '$lib/store/types';
import type { NodeEvents, NodeSelectionEvents } from '$lib/types';
import type { Node, Edge, NodeEvents, NodeSelectionEvents } from '$lib/types';
export type NodeSelectionProps = { store: SvelteFlowStore } & NodeSelectionEvents &
Pick<NodeEvents, 'onnodedrag' | 'onnodedragstart' | 'onnodedragstop'>;
export type NodeSelectionProps<NodeType extends Node = Node, EdgeType extends Edge = Edge> = {
store: SvelteFlowStore<NodeType, EdgeType>;
} & NodeSelectionEvents<NodeType> &
Pick<NodeEvents<NodeType>, 'onnodedrag' | 'onnodedragstart' | 'onnodedragstop'>;
@@ -1,4 +1,4 @@
<script lang="ts">
<script lang="ts" generics="NodeType extends Node = Node, EdgeType extends Edge = Edge">
import { setContext, onDestroy } from 'svelte';
import {
arrowKeyDiffs,
@@ -13,7 +13,7 @@
import DefaultNode from '$lib/components/nodes/DefaultNode.svelte';
import type { ConnectableContext, NodeWrapperProps } from './types';
import type { NodeEvents } from '$lib/types';
import type { Node, Edge, NodeEvents } from '$lib/types';
import { toPxString } from '$lib/utils';
let {
@@ -29,7 +29,7 @@
onnodepointerleave,
onnodepointermove,
onnodecontextmenu
}: NodeWrapperProps & NodeEvents = $props();
}: NodeWrapperProps<NodeType, EdgeType> & NodeEvents<NodeType> = $props();
let {
data = {},
@@ -55,7 +55,8 @@
dragHandle,
internals: {
z: zIndex = 0,
positionAbsolute: { x: positionX, y: positionY }
positionAbsolute: { x: positionX, y: positionY },
userNode
}
} = $derived(node);
@@ -162,7 +163,7 @@
store.handleNodeSelection(id);
}
onnodeclick?.({ node, event });
onnodeclick?.({ node: userNode, event });
}
function onKeyDown(event: KeyboardEvent) {
@@ -205,13 +206,17 @@
nodeClickDistance,
onNodeMouseDown: store.handleNodeSelection,
onDrag: (event, _, targetNode, nodes) => {
onnodedrag?.({ event, targetNode, nodes });
onnodedrag?.({ event, targetNode: targetNode as NodeType, nodes: nodes as NodeType[] });
},
onDragStart: (event, _, targetNode, nodes) => {
onnodedragstart?.({ event, targetNode, nodes });
onnodedragstart?.({
event,
targetNode: targetNode as NodeType,
nodes: nodes as NodeType[]
});
},
onDragStop: (event, _, targetNode, nodes) => {
onnodedragstop?.({ event, targetNode, nodes });
onnodedragstop?.({ event, targetNode: targetNode as NodeType, nodes: nodes as NodeType[] });
},
store
}}
@@ -230,10 +235,18 @@
style:visibility={initialized ? 'visible' : 'hidden'}
style="{style};width:{inlineDimensions.width};height:{inlineDimensions.height}"
onclick={onSelectNodeHandler}
onpointerenter={onnodepointerenter ? (event) => onnodepointerenter({ node, event }) : undefined}
onpointerleave={onnodepointerleave ? (event) => onnodepointerleave({ node, event }) : undefined}
onpointermove={onnodepointermove ? (event) => onnodepointermove({ node, event }) : undefined}
oncontextmenu={onnodecontextmenu ? (event) => onnodecontextmenu({ node, event }) : undefined}
onpointerenter={onnodepointerenter
? (event) => onnodepointerenter({ node: userNode, event })
: undefined}
onpointerleave={onnodepointerleave
? (event) => onnodepointerleave({ node: userNode, event })
: undefined}
onpointermove={onnodepointermove
? (event) => onnodepointermove({ node: userNode, event })
: undefined}
oncontextmenu={onnodecontextmenu
? (event) => onnodecontextmenu({ node: userNode, event })
: undefined}
onkeydown={focusable ? onKeyDown : undefined}
tabIndex={focusable ? 0 : undefined}
role={focusable ? 'button' : undefined}
@@ -1,13 +1,13 @@
import type { SvelteFlowStore } from '$lib/store/types';
import type { InternalNode } from '$lib/types';
import type { Node, Edge, InternalNode } from '$lib/types';
export type ConnectableContext = {
value: boolean;
};
export type NodeWrapperProps = {
node: InternalNode;
store: SvelteFlowStore;
export type NodeWrapperProps<NodeType extends Node = Node, EdgeType extends Edge = Edge> = {
node: InternalNode<NodeType>;
store: SvelteFlowStore<NodeType, EdgeType>;
nodeClickDistance?: number;
resizeObserver?: ResizeObserver | null;
};
@@ -1,14 +1,15 @@
<script lang="ts">
<script lang="ts" generics="NodeType extends Node = Node, EdgeType extends Edge = Edge">
import { onDestroy, setContext } from 'svelte';
import { createStore, key } from '$lib/store';
import type { SvelteFlowProviderProps } from './types';
import type { ProviderContext, SvelteFlowStore } from '$lib/store/types';
import type { Node, Edge } from '$lib/types';
let { children }: SvelteFlowProviderProps = $props();
let store = $state.raw(
createStore({
createStore<NodeType, EdgeType>({
props: {},
nodes: [],
edges: []
@@ -20,10 +21,10 @@
getStore() {
return store;
},
setStore: (newStore: SvelteFlowStore) => {
setStore: (newStore: SvelteFlowStore<NodeType, EdgeType>) => {
store = newStore;
}
} satisfies ProviderContext);
} satisfies ProviderContext<NodeType, EdgeType>);
onDestroy(() => {
store.reset();
@@ -1,13 +1,5 @@
import type { Snippet } from 'svelte';
import type { NodeOrigin } from '@xyflow/system';
import type { Edge, Node } from '$lib/types';
export type SvelteFlowProviderProps = {
initialNodes?: Node[];
initialEdges?: Edge[];
initialWidth?: number;
initialHeight?: number;
fitView?: boolean;
nodeOrigin?: NodeOrigin;
children?: Snippet;
};