Merge pull request #4238 from xyflow/svelte4next

Svelte Flow 0.1.0
This commit is contained in:
Moritz Klack
2024-05-02 17:30:25 +02:00
committed by GitHub
37 changed files with 189 additions and 223 deletions
@@ -3,6 +3,7 @@ import DragHandleNode from './components/DragHandleNode.svelte';
export default {
flowProps: {
fitView: true,
nodeDragThreshold: 0,
nodeTypes: {
DragHandleNode
},
@@ -1,34 +1,35 @@
<script lang="ts">
import { Handle, Position, type NodeProps } from '@xyflow/svelte';
import { Handle, Position, type NodeProps } from '@xyflow/svelte';
type $$Props = NodeProps;
type $$Props = NodeProps;
export let isConnectable: $$Props['isConnectable'];
export let isConnectable: $$Props['isConnectable'];
$$restProps;
const DEFAULT_HANDLE_STYLE = 'width: 10px; height: 10px; bottom: -5px;';
const handleStyle = 'width: 10px; height: 10px; bottom: -5px;';
</script>
<div style="background: #DDD; padding: 25px">
<div>Node</div>
<Handle
type="source"
id="red"
position={Position.Bottom}
style={DEFAULT_HANDLE_STYLE + 'left: 15%; background: red;'}
{isConnectable}
/>
<Handle
type="source"
position={Position.Bottom}
id="blue"
style={DEFAULT_HANDLE_STYLE + 'left: 50%; background: blue;'}
{isConnectable}
/>
<Handle
type="source"
position={Position.Bottom}
id="orange"
style={DEFAULT_HANDLE_STYLE + 'left: 85%; background: orange;'}
{isConnectable}
/>
<div>Node</div>
<Handle
type="source"
id="red"
position={Position.Bottom}
style={handleStyle + 'left: 15%; background: red;'}
{isConnectable}
/>
<Handle
type="source"
position={Position.Bottom}
id="blue"
style={handleStyle + 'left: 50%; background: blue;'}
{isConnectable}
/>
<Handle
type="source"
position={Position.Bottom}
id="orange"
style={handleStyle + 'left: 85%; background: orange;'}
{isConnectable}
/>
</div>
@@ -6,6 +6,8 @@
export let data: $$Props['data'];
$$restProps;
const { colorStore } = data;
</script>
@@ -4,27 +4,18 @@
type $$Props = EdgeProps;
export let id: $$Props['id'] = '';
export let source: $$Props['source'] = '';
export let target: $$Props['target'] = '';
export let animated: $$Props['animated'] = undefined;
export let selected: $$Props['selected'] = undefined;
export let label: $$Props['label'] = undefined;
export let labelStyle: $$Props['labelStyle'] = undefined;
export let data: $$Props['data'] = undefined;
export let style: $$Props['style'] = undefined;
export let markerStart: $$Props['markerStart'] = undefined;
export let markerEnd: $$Props['markerEnd'] = undefined;
export let interactionWidth: $$Props['interactionWidth'] = undefined;
export let sourceX: $$Props['sourceX'];
export let sourceY: $$Props['sourceY'];
export let sourcePosition: $$Props['sourcePosition'];
export let sourceHandleId: $$Props['sourceHandleId'] = undefined;
export let targetX: $$Props['targetX'];
export let targetY: $$Props['targetY'];
export let targetPosition: $$Props['targetPosition'];
export let targetHandleId: $$Props['targetHandleId'] = undefined;
$$restProps;
$: [edgePath, labelX, labelY] = getBezierPath({
sourceX,
@@ -34,18 +25,6 @@
targetY,
targetPosition
});
source;
target;
animated;
selected;
data;
label;
labelStyle;
markerStart;
interactionWidth;
sourceHandleId;
targetHandleId;
</script>
<BaseEdge path={edgePath} {markerEnd} {style} />
@@ -3,14 +3,8 @@
type $$Props = EdgeProps;
export let id: $$Props['id'] = '';
export let source: $$Props['source'] = '';
export let target: $$Props['target'] = '';
export let animated: $$Props['animated'] = undefined;
export let selected: $$Props['selected'] = undefined;
export let label: $$Props['label'] = undefined;
export let labelStyle: $$Props['labelStyle'] = undefined;
export let data: $$Props['data'] = undefined;
export let style: $$Props['style'] = undefined;
export let markerStart: $$Props['markerStart'] = undefined;
export let markerEnd: $$Props['markerEnd'] = undefined;
@@ -19,23 +13,12 @@
export let sourceX: $$Props['sourceX'];
export let sourceY: $$Props['sourceY'];
export let sourcePosition: $$Props['sourcePosition'];
export let sourceHandleId: $$Props['sourceHandleId'] = undefined;
export let targetX: $$Props['targetX'];
export let targetY: $$Props['targetY'];
export let targetPosition: $$Props['targetPosition'];
export let targetHandleId: $$Props['targetHandleId'] = undefined;
id;
source;
target;
animated;
selected;
data;
sourcePosition;
targetPosition;
sourceHandleId;
targetHandleId;
$$restProps;
</script>
<BezierEdge
@@ -33,33 +33,7 @@
console.log('connections', id, $connections);
}
export let data: $$Props['data'];
export let targetPosition: $$Props['targetPosition'] = Position.Top;
export let sourcePosition: $$Props['sourcePosition'] = Position.Bottom;
export let width: $$Props['width'] = undefined;
export let height: $$Props['height'] = undefined;
export let selected: $$Props['selected'] = undefined;
export let type: $$Props['type'] = undefined;
export let zIndex: $$Props['zIndex'] = undefined;
export let dragging: $$Props['dragging'] = false;
export let dragHandle: $$Props['dragHandle'] = undefined;
export let positionAbsoluteX: $$Props['positionAbsoluteX'] = 0;
export let positionAbsoluteY: $$Props['positionAbsoluteY'] = 0;
export let isConnectable: $$Props['isConnectable'] = undefined;
data;
targetPosition;
sourcePosition;
width;
height;
selected;
type;
zIndex;
dragging;
dragHandle;
positionAbsoluteX;
positionAbsoluteY;
isConnectable;
$$restProps;
</script>
<div class="custom">
@@ -21,34 +21,7 @@
console.log('disconnect source', connection);
}
export let data: $$Props['data'];
export let targetPosition: $$Props['targetPosition'] = Position.Top;
export let sourcePosition: $$Props['sourcePosition'] = Position.Bottom;
export let width: $$Props['width'] = undefined;
export let height: $$Props['height'] = undefined;
export let selected: $$Props['selected'] = undefined;
export let type: $$Props['type'] = undefined;
export let zIndex: $$Props['zIndex'] = undefined;
export let dragging: $$Props['dragging'] = false;
export let dragHandle: $$Props['dragHandle'] = undefined;
export let positionAbsolute: $$Props['positionAbsolute'] = {
x: 0,
y: 0
};
export let isConnectable: $$Props['isConnectable'] = undefined;
data;
targetPosition;
sourcePosition;
width;
height;
selected;
type;
zIndex;
dragging;
dragHandle;
positionAbsolute;
isConnectable;
$$restProps;
</script>
<div class="custom">
@@ -1,13 +1,14 @@
<script lang="ts">
import { SvelteFlow, Controls, Panel, type Node, type Edge } from '@xyflow/svelte';
import { writable } from 'svelte/store';
import { SvelteFlow, Controls, Panel, type Edge } from '@xyflow/svelte';
import DefaultResizer from './DefaultResizer.svelte';
import CustomResizer from './CustomResizer.svelte';
import VerticalResizer from './VerticalResizer.svelte';
import HorizontalResizer from './HorizontalResizer.svelte';
import { writable } from 'svelte/store';
import '@xyflow/svelte/dist/style.css';
import type { ResizeNode } from './types';
const nodeTypes = {
defaultResizer: DefaultResizer,
@@ -20,7 +21,7 @@
const edges = writable<Edge[]>([]);
const nodes = writable<Node[]>([
const nodes = writable<ResizeNode[]>([
{
id: '1',
type: 'defaultResizer',
@@ -1,9 +1,10 @@
<script lang="ts">
import { Handle, Position, type NodeProps, NodeResizeControl } from '@xyflow/svelte';
import type { ResizeNode } from './types';
type $$Props = NodeProps;
type $$Props = NodeProps<ResizeNode>;
export let data: $$Props['data'] = undefined;
export let data: $$Props['data'];
</script>
<NodeResizeControl
@@ -1,9 +1,10 @@
<script lang="ts">
import { Handle, NodeResizer, Position, type NodeProps } from '@xyflow/svelte';
import type { ResizeNode } from './types';
type $$Props = NodeProps;
type $$Props = NodeProps<ResizeNode>;
export let data: $$Props['data'] = undefined;
export let data: $$Props['data'];
export let selected: $$Props['selected'] = undefined;
</script>
@@ -1,9 +1,10 @@
<script lang="ts">
import { Handle, NodeResizeControl, Position, type NodeProps } from '@xyflow/svelte';
import type { ResizeNode } from './types';
type $$Props = NodeProps;
type $$Props = NodeProps<ResizeNode>;
export let data: $$Props['data'] = undefined;
export let data: $$Props['data'];
</script>
<NodeResizeControl
@@ -1,24 +0,0 @@
function ResizeIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="8"
height="8"
viewBox="0 0 24 24"
strokeWidth="2"
stroke="currentColor"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
style={{ position: 'absolute', right: 2, bottom: 2 }}
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<polyline points="16 20 20 20 20 16" />
<line x1="14" y1="14" x2="20" y2="20" />
<polyline points="8 4 4 4 4 8" />
<line x1="4" y1="4" x2="10" y2="10" />
</svg>
);
}
export default ResizeIcon;
@@ -1,9 +1,10 @@
<script lang="ts">
import { Handle, NodeResizeControl, Position, type NodeProps } from '@xyflow/svelte';
import type { ResizeNode } from './types';
type $$Props = NodeProps;
type $$Props = NodeProps<ResizeNode>;
export let data: $$Props['data'] = undefined;
export let data: $$Props['data'];
</script>
<NodeResizeControl
@@ -0,0 +1,21 @@
import {
type Node,
type ShouldResize,
type OnResizeStart,
type OnResize,
type OnResizeEnd
} from '@xyflow/svelte';
export type ResizeNode = Node<{
minWidth?: number;
maxWidth?: number;
minHeight?: number;
maxHeight?: number;
shouldResize?: ShouldResize;
onResizeStart?: OnResizeStart;
onResize?: OnResize;
onResizeEnd?: OnResizeEnd;
keepAspectRatio?: boolean;
label?: string;
isVisible?: boolean;
}>;
@@ -2,6 +2,7 @@
import { NodeToolbar, type NodeProps, Handle, Position } from '@xyflow/svelte';
type $$Props = NodeProps;
$$restProps;
export let data: $$Props['data'];
</script>
@@ -13,8 +13,8 @@
type Node,
type Edge,
ConnectionMode,
useSvelteFlow,
ControlButton
ControlButton,
type FitViewOptions
} from '@xyflow/svelte';
import CustomNode from './CustomNode.svelte';
@@ -33,6 +33,11 @@
custom: CustomEdge
};
const fitViewOptions: FitViewOptions = {
padding: 0.2,
nodes: [{ id: '1' }, { id: '2' }]
};
const nodes = writable<Node[]>([
{
id: '1',
@@ -191,7 +196,7 @@
attributionPosition={'top-center'}
deleteKey={['Backspace', 'd']}
>
<Controls orientation="horizontal">
<Controls orientation="horizontal" {fitViewOptions}>
<ControlButton slot="before">xy</ControlButton>
<ControlButton aria-label="log" on:click={() => console.log('control button')}
>log</ControlButton
@@ -1,7 +1,8 @@
<script lang="ts">
import { Handle, Position, type NodeProps } from '@xyflow/svelte';
import { Handle, Position, type BuiltInNode, type NodeProps } from '@xyflow/svelte';
type $$Props = NodeProps;
type $$Props = NodeProps<BuiltInNode>;
$$restProps;
export let data: { label: string } = { label: 'Node' };
export let positionAbsoluteX: number = 0;
@@ -1,7 +1,8 @@
<script lang="ts">
import type { NodeProps } from '@xyflow/svelte';
import type { BuiltInNode, NodeProps } from '@xyflow/svelte';
type $$Props = NodeProps;
type $$Props = NodeProps<BuiltInNode>;
$$restProps;
export let data: { label: string } = { label: 'Node' };
</script>
@@ -1,16 +1,19 @@
<script lang="ts">
import { Handle, Position, type NodeProps, type XYPosition } from '@xyflow/svelte';
import { Handle, Position, type NodeProps } from '@xyflow/svelte';
type $$Props = NodeProps;
export let id: string;
export let positionAbsolute: XYPosition = { x: 0, y: 0 };
export let positionAbsoluteX: number = 0;
export let positionAbsoluteY: number = 0;
export let zIndex: number = 0;
$$restProps;
</script>
<Handle type="target" position={Position.Top} />
<div>{id}</div>
<div>
x:{Math.round(positionAbsolute.x)} y:{Math.round(positionAbsolute.y)} z:{zIndex}
x:{Math.round(positionAbsoluteX)} y:{Math.round(positionAbsoluteY)} z:{zIndex}
</div>
<Handle type="source" position={Position.Bottom} />
@@ -4,6 +4,7 @@
type $$Props = NodeProps;
export let id: $$Props['id'];
$$restProps;
const updateNodeInternals = useUpdateNodeInternals();
@@ -53,8 +53,8 @@
$: edgeType = type || 'default';
$: edgeComponent = $edgeTypes[edgeType] || BezierEdgeInternal;
$: markerStartUrl = markerStart ? `url(#${getMarkerId(markerStart, $flowId)})` : undefined;
$: markerEndUrl = markerEnd ? `url(#${getMarkerId(markerEnd, $flowId)})` : undefined;
$: markerStartUrl = markerStart ? `url('#${getMarkerId(markerStart, $flowId)}')` : undefined;
$: markerEndUrl = markerEnd ? `url('#${getMarkerId(markerEnd, $flowId)}')` : undefined;
$: isSelectable = selectable || ($elementsSelectable && typeof selectable === 'undefined');
const handleEdgeSelect = useHandleEdgeSelect();
@@ -22,6 +22,7 @@
export let position: $$Props['position'] = Position.Top;
export let style: $$Props['style'] = undefined;
export let isConnectable: $$Props['isConnectable'] = undefined;
export let isValidConnection: $$Props['isValidConnection'] = undefined;
export let onconnect: $$Props['onconnect'] = undefined;
export let ondisconnect: $$Props['ondisconnect'] = undefined;
// @todo implement connectablestart, connectableend
@@ -31,12 +32,12 @@
let className: $$Props['class'] = undefined;
export { className as class };
const isTarget = type === 'target';
$: isTarget = type === 'target';
const nodeId = getContext<string>('svelteflow__node_id');
const connectable = getContext<Writable<boolean>>('svelteflow__node_connectable');
$: isConnectable = isConnectable !== undefined ? isConnectable : $connectable;
const handleId = id || null;
$: handleId = id || null;
const store = useStore();
const {
@@ -45,7 +46,7 @@
nodeLookup,
connectionRadius,
viewport,
isValidConnection,
isValidConnection: isValidConnectionStore,
lib,
addEdge,
onedgecreate,
@@ -77,7 +78,7 @@
lib: $lib,
autoPanOnConnect: $autoPanOnConnect,
flowId: $flowId,
isValidConnection: $isValidConnection,
isValidConnection: isValidConnection ?? $isValidConnectionStore,
updateConnection,
cancelConnection,
panBy,
@@ -5,17 +5,17 @@
import { useStore } from '$lib/store';
import { Selection } from '$lib/components/Selection';
import drag from '$lib/actions/drag';
import type { Node } from '$lib/types';
import { createNodeEventDispatcher } from '$lib';
import type { Node, NodeEventMap } from '$lib/types';
const store = useStore();
const { selectionRectMode, nodes } = store;
const dispatch = createEventDispatcher<{
selectioncontextmenu: { nodes: Node[]; event: MouseEvent | TouchEvent };
selectionclick: { nodes: Node[]; event: MouseEvent | TouchEvent };
}>();
const dispatchNodeEvent = createNodeEventDispatcher();
const dispatch = createEventDispatcher<
NodeEventMap & {
selectioncontextmenu: { nodes: Node[]; event: MouseEvent | TouchEvent };
selectionclick: { nodes: Node[]; event: MouseEvent | TouchEvent };
}
>();
$: selectedNodes = $nodes.filter((n) => n.selected);
$: bounds = getNodesBounds(selectedNodes);
@@ -37,13 +37,13 @@
disabled: false,
store,
onDrag: (event, _, __, nodes) => {
dispatchNodeEvent('nodedrag', { event, targetNode: null, nodes });
dispatch('nodedrag', { event, targetNode: null, nodes });
},
onDragStart: (event, _, __, nodes) => {
dispatchNodeEvent('nodedragstart', { event, targetNode: null, nodes });
dispatch('nodedragstart', { event, targetNode: null, nodes });
},
onDragStop: (event, _, __, nodes) => {
dispatchNodeEvent('nodedragstop', { event, targetNode: null, nodes });
dispatch('nodedragstop', { event, targetNode: null, nodes });
}
}}
on:contextmenu={onContextMenu}
@@ -1,7 +1,7 @@
<svelte:options immutable />
<script lang="ts">
import { setContext, onDestroy } from 'svelte';
import { setContext, onDestroy, createEventDispatcher } from 'svelte';
import { get, writable } from 'svelte/store';
import cc from 'classcat';
import { errorMessages, Position } from '@xyflow/system';
@@ -11,7 +11,7 @@
import DefaultNode from '$lib/components/nodes/DefaultNode.svelte';
import type { NodeWrapperProps } from './types';
import { getNodeInlineStyleDimensions } from './utils';
import { createNodeEventDispatcher } from '$lib';
import type { NodeEventMap } from '$lib/types';
interface $$Props extends NodeWrapperProps {}
@@ -58,7 +58,7 @@
let nodeRef: HTMLDivElement;
let prevNodeRef: HTMLDivElement | null = null;
const dispatchNodeEvent = createNodeEventDispatcher();
const dispatchNodeEvent = createEventDispatcher<NodeEventMap>();
const connectableStore = writable(connectable);
let prevType: string | undefined = undefined;
let prevSourcePosition: Position | undefined = undefined;
@@ -104,7 +104,7 @@
{
id,
nodeElement: nodeRef,
forceUpdate: true
force: true
}
]
])
@@ -141,7 +141,7 @@
handleNodeSelection(id);
}
dispatchNodeEvent('nodeclick', { node, event });
dispatchNodeEvent('nodeclick', { node: node.internals.userNode, event });
}
</script>
@@ -1,4 +1,4 @@
import type { Node } from '$lib/types';
import type { InternalNode, Node } from '$lib/types';
export type NodeWrapperProps = Pick<
Node,
@@ -32,6 +32,6 @@ export type NodeWrapperProps = Pick<
resizeObserver?: ResizeObserver | null;
isParent?: boolean;
zIndex: number;
node: Node;
node: InternalNode;
initialized: boolean;
};
@@ -26,7 +26,7 @@
updates.set(id, {
id,
nodeElement: entry.target as HTMLDivElement,
forceUpdate: true
force: true
});
});
@@ -35,7 +35,7 @@
} from '@xyflow/system';
import { useStore } from '$lib/store';
import type { Node, Edge } from '$lib/types';
import type { Node, Edge, InternalNode } from '$lib/types';
import type { PaneProps } from './types';
type $$Props = PaneProps;
@@ -68,7 +68,7 @@
let container: HTMLDivElement;
let containerBounds: DOMRect | null = null;
let selectedNodes: Node[] = [];
let selectedNodes: InternalNode[] = [];
$: _panOnDrag = $panActivationKeyPressed || panOnDrag;
$: isSelecting =
@@ -0,0 +1,17 @@
import { derived, type Readable } from 'svelte/store';
import { useStore } from '$lib/store';
import type { InternalNode } from '$lib/types';
/**
* Hook to get an internal node by id.
*
* @public
* @param id - the node id
* @returns a readable with an internal node or undefined
*/
export function useInternalNode(id: string): Readable<InternalNode | undefined> {
const { nodeLookup, nodes } = useStore();
return derived([nodeLookup, nodes], ([nodeLookup]) => nodeLookup.get(id));
}
+19 -6
View File
@@ -18,7 +18,7 @@ import {
} from '@xyflow/system';
import { useStore } from '$lib/store';
import type { Edge, FitViewOptions, Node } from '$lib/types';
import type { Edge, FitViewOptions, InternalNode, Node } from '$lib/types';
import { isNode } from '$lib/utils';
/**
@@ -41,6 +41,13 @@ export function useSvelteFlow(): {
* @param options.duration - optional duration. If set, a transition will be applied
*/
zoomOut: ZoomInOut;
/**
* Returns an internal node by id.
*
* @param id - the node id
* @returns the node or undefined if no node was found
*/
getInternalNode: (id: string) => InternalNode | undefined;
/**
* Returns a node by id.
*
@@ -280,10 +287,13 @@ export function useSvelteFlow(): {
}
};
const getInternalNode = (id: string) => get(nodeLookup).get(id);
return {
zoomIn,
zoomOut,
getNode: (id) => get(nodeLookup).get(id),
getInternalNode,
getNode: (id) => getInternalNode(id)?.internals.userNode,
getNodes: (ids) => (ids === undefined ? get(nodes) : getElements(get(nodeLookup), ids)),
getEdge: (id) => get(edgeLookup).get(id),
getEdges: (ids) => (ids === undefined ? get(edges) : getElements(get(edgeLookup), ids)),
@@ -474,14 +484,17 @@ export function useSvelteFlow(): {
viewport
};
}
function getElements<EdgeOrNode>(lookup: Map<string, EdgeOrNode>, ids: string[]) {
function getElements(lookup: Map<string, InternalNode>, ids: string[]): Node[];
function getElements(lookup: Map<string, Edge>, ids: string[]): Edge[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function getElements(lookup: Map<string, any>, ids: string[]): any[] {
const result = [];
for (const id of ids) {
const element = lookup.get(id);
const item = lookup.get(id);
if (element) {
if (item) {
const element = 'internals' in item ? item.internals?.userNode : item;
result.push(element);
}
}
@@ -23,7 +23,7 @@ export function useUpdateNodeInternals(): UpdateNodeInternals {
) as HTMLDivElement;
if (nodeElement) {
updates.set(updateId, { id: updateId, nodeElement, forceUpdate: true });
updates.set(updateId, { id: updateId, nodeElement, force: true });
}
});
@@ -26,6 +26,7 @@
export let ariaLabel: $$Props['aria-label'] = undefined;
export let style: $$Props['style'] = undefined;
export let orientation: $$Props['orientation'] = 'vertical';
export let fitViewOptions: $$Props['fitViewOptions'] = undefined;
let className: $$Props['class'] = '';
export { className as class };
@@ -63,7 +64,7 @@
};
const onFitViewHandler = () => {
fitView();
fitView(fitViewOptions);
};
const onToggleInteractivity = () => {
@@ -1,6 +1,8 @@
import type { HTMLButtonAttributes } from 'svelte/elements';
import type { PanelPosition } from '@xyflow/system';
import type { FitViewOptions } from '$lib/types';
export type ControlsProps = {
/** Position of the controls on the pane
* @example PanelPosition.TopLeft, PanelPosition.TopRight,
@@ -21,6 +23,7 @@ export type ControlsProps = {
style?: string;
class?: string;
orientation?: 'horizontal' | 'vertical';
fitViewOptions?: FitViewOptions;
};
export type ControlButtonProps = HTMLButtonAttributes & {
+8 -6
View File
@@ -2,7 +2,7 @@ import { getContext, setContext } from 'svelte';
import { derived, get, writable } from 'svelte/store';
import {
createMarkerIds,
fitView as fitViewUtil,
fitView as fitViewSystem,
getElementsToRemove,
panBy as panBySystem,
updateNodeInternals as updateNodeInternalsSystem,
@@ -111,8 +111,12 @@ export function createStore({
switch (change.type) {
case 'dimensions': {
const measured = { ...node.measured, ...change.dimensions };
node.width = change.dimensions?.width ?? node.width;
node.height = change.dimensions?.height ?? node.height;
if (change.setAttributes) {
node.width = change.dimensions?.width ?? node.width;
node.height = change.dimensions?.height ?? node.height;
}
node.measured = measured;
break;
}
@@ -136,7 +140,7 @@ export function createStore({
return false;
}
return fitViewUtil(
return fitViewSystem(
{
nodeLookup: get(store.nodeLookup),
width: get(store.width),
@@ -350,8 +354,6 @@ export function createStore({
store.selectionRectMode.set(null);
store.snapGrid.set(null);
store.isValidConnection.set(() => true);
store.nodes.set([]);
store.edges.set([]);
unselectNodesAndEdges();
cancelConnection();
+5 -1
View File
@@ -45,11 +45,15 @@ export type HandleComponentProps = {
isConnectableStart?: boolean;
/** Should you be able to connect to this handle */
isConnectableEnd?: boolean;
/** Function that is called when checking if connection is valid.
* Overrides the isValidConnection on the Flow component.
*/
isValidConnection?: IsValidConnection;
onconnect?: (connections: Connection[]) => void;
ondisconnect?: (connections: Connection[]) => void;
};
export type FitViewOptions = FitViewOptionsBase<Node>;
export type FitViewOptions<NodeType extends Node = Node> = FitViewOptionsBase<NodeType>;
export type OnDelete = (params: { nodes: Node[]; edges: Edge[] }) => void;
export type OnEdgeCreate = (connection: Connection) => Edge | Connection | void;
+11
View File
@@ -45,3 +45,14 @@ export type NodeTypes = Record<
export type DefaultNodeOptions = Partial<Omit<Node, 'id'>>;
export type BuiltInNode = Node<{ label: string }, 'input' | 'output' | 'default'>;
export type NodeEventMap = {
nodeclick: { node: Node; event: MouseEvent | TouchEvent };
nodecontextmenu: { node: Node; event: MouseEvent | TouchEvent };
nodedrag: { targetNode: Node | null; nodes: Node[]; event: MouseEvent | TouchEvent };
nodedragstart: { targetNode: Node | null; nodes: Node[]; event: MouseEvent | TouchEvent };
nodedragstop: { targetNode: Node | null; nodes: Node[]; event: MouseEvent | TouchEvent };
nodemouseenter: { node: Node; event: MouseEvent | TouchEvent };
nodemouseleave: { node: Node; event: MouseEvent | TouchEvent };
nodemousemove: { node: Node; event: MouseEvent | TouchEvent };
};
-13
View File
@@ -1,4 +1,3 @@
import { createEventDispatcher } from 'svelte';
import { isNodeBase, isEdgeBase } from '@xyflow/system';
import type { Edge, Node } from '$lib/types';
@@ -22,15 +21,3 @@ export const isNode = <NodeType extends Node = Node>(element: unknown): element
*/
export const isEdge = <EdgeType extends Edge = Edge>(element: unknown): element is EdgeType =>
isEdgeBase<EdgeType>(element);
export const createNodeEventDispatcher = () =>
createEventDispatcher<{
nodeclick: { node: Node; event: MouseEvent | TouchEvent };
nodecontextmenu: { node: Node; event: MouseEvent | TouchEvent };
nodedrag: { targetNode: Node | null; nodes: Node[]; event: MouseEvent | TouchEvent };
nodedragstart: { targetNode: Node | null; nodes: Node[]; event: MouseEvent | TouchEvent };
nodedragstop: { targetNode: Node | null; nodes: Node[]; event: MouseEvent | TouchEvent };
nodemouseenter: { node: Node; event: MouseEvent | TouchEvent };
nodemouseleave: { node: Node; event: MouseEvent | TouchEvent };
nodemousemove: { node: Node; event: MouseEvent | TouchEvent };
}>();
+2 -2
View File
@@ -61,13 +61,13 @@ export type FitViewParamsBase<NodeType extends NodeBase> = {
nodeOrigin?: NodeOrigin;
};
export type FitViewOptionsBase<NodeType extends NodeBase> = {
export type FitViewOptionsBase<NodeType extends NodeBase = NodeBase> = {
padding?: number;
includeHiddenNodes?: boolean;
minZoom?: number;
maxZoom?: number;
duration?: number;
nodes?: (NodeType | { id: NodeType['id'] })[];
nodes?: (NodeType | { id: string })[];
};
export type Viewport = {