diff --git a/examples/svelte/src/generic-tests/nodes/general.ts b/examples/svelte/src/generic-tests/nodes/general.ts index 4e5abc91..60757953 100644 --- a/examples/svelte/src/generic-tests/nodes/general.ts +++ b/examples/svelte/src/generic-tests/nodes/general.ts @@ -3,6 +3,7 @@ import DragHandleNode from './components/DragHandleNode.svelte'; export default { flowProps: { fitView: true, + nodeDragThreshold: 0, nodeTypes: { DragHandleNode }, diff --git a/examples/svelte/src/routes/examples/custom-connection-line/CustomNode.svelte b/examples/svelte/src/routes/examples/custom-connection-line/CustomNode.svelte index 0f4cc6bd..6507ce51 100644 --- a/examples/svelte/src/routes/examples/custom-connection-line/CustomNode.svelte +++ b/examples/svelte/src/routes/examples/custom-connection-line/CustomNode.svelte @@ -1,34 +1,35 @@
-
Node
- - - +
Node
+ + +
diff --git a/examples/svelte/src/routes/examples/customnode/CustomNode.svelte b/examples/svelte/src/routes/examples/customnode/CustomNode.svelte index e22701e3..47a33534 100644 --- a/examples/svelte/src/routes/examples/customnode/CustomNode.svelte +++ b/examples/svelte/src/routes/examples/customnode/CustomNode.svelte @@ -6,6 +6,8 @@ export let data: $$Props['data']; + $$restProps; + const { colorStore } = data; diff --git a/examples/svelte/src/routes/examples/edges/ButtonEdge.svelte b/examples/svelte/src/routes/examples/edges/ButtonEdge.svelte index 235aab98..ee582226 100644 --- a/examples/svelte/src/routes/examples/edges/ButtonEdge.svelte +++ b/examples/svelte/src/routes/examples/edges/ButtonEdge.svelte @@ -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; diff --git a/examples/svelte/src/routes/examples/edges/CustomBezierEdge.svelte b/examples/svelte/src/routes/examples/edges/CustomBezierEdge.svelte index 48d86c3d..960d3e6e 100644 --- a/examples/svelte/src/routes/examples/edges/CustomBezierEdge.svelte +++ b/examples/svelte/src/routes/examples/edges/CustomBezierEdge.svelte @@ -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;
diff --git a/examples/svelte/src/routes/examples/handle-connect/SingleHandleNode.svelte b/examples/svelte/src/routes/examples/handle-connect/SingleHandleNode.svelte index 7c1e026d..d2958969 100644 --- a/examples/svelte/src/routes/examples/handle-connect/SingleHandleNode.svelte +++ b/examples/svelte/src/routes/examples/handle-connect/SingleHandleNode.svelte @@ -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;
diff --git a/examples/svelte/src/routes/examples/node-resizer/+page.svelte b/examples/svelte/src/routes/examples/node-resizer/+page.svelte index 8e08174a..e03acf34 100644 --- a/examples/svelte/src/routes/examples/node-resizer/+page.svelte +++ b/examples/svelte/src/routes/examples/node-resizer/+page.svelte @@ -1,13 +1,14 @@ import { Handle, NodeResizer, Position, type NodeProps } from '@xyflow/svelte'; + import type { ResizeNode } from './types'; - type $$Props = NodeProps; + type $$Props = NodeProps; - export let data: $$Props['data'] = undefined; + export let data: $$Props['data']; export let selected: $$Props['selected'] = undefined; diff --git a/examples/svelte/src/routes/examples/node-resizer/HorizontalResizer.svelte b/examples/svelte/src/routes/examples/node-resizer/HorizontalResizer.svelte index 4942e511..5caea508 100644 --- a/examples/svelte/src/routes/examples/node-resizer/HorizontalResizer.svelte +++ b/examples/svelte/src/routes/examples/node-resizer/HorizontalResizer.svelte @@ -1,9 +1,10 @@ - - - - - - - ); -} - -export default ResizeIcon; diff --git a/examples/svelte/src/routes/examples/node-resizer/VerticalResizer.svelte b/examples/svelte/src/routes/examples/node-resizer/VerticalResizer.svelte index 65ccae15..5e173508 100644 --- a/examples/svelte/src/routes/examples/node-resizer/VerticalResizer.svelte +++ b/examples/svelte/src/routes/examples/node-resizer/VerticalResizer.svelte @@ -1,9 +1,10 @@ ; diff --git a/examples/svelte/src/routes/examples/node-toolbar/CustomNode.svelte b/examples/svelte/src/routes/examples/node-toolbar/CustomNode.svelte index af2dabaa..99b00f7c 100644 --- a/examples/svelte/src/routes/examples/node-toolbar/CustomNode.svelte +++ b/examples/svelte/src/routes/examples/node-toolbar/CustomNode.svelte @@ -2,6 +2,7 @@ import { NodeToolbar, type NodeProps, Handle, Position } from '@xyflow/svelte'; type $$Props = NodeProps; + $$restProps; export let data: $$Props['data']; diff --git a/examples/svelte/src/routes/examples/overview/+page.svelte b/examples/svelte/src/routes/examples/overview/+page.svelte index 301730f6..92a353bb 100644 --- a/examples/svelte/src/routes/examples/overview/+page.svelte +++ b/examples/svelte/src/routes/examples/overview/+page.svelte @@ -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([ { id: '1', @@ -191,7 +196,7 @@ attributionPosition={'top-center'} deleteKey={['Backspace', 'd']} > - + xy console.log('control button')} >log - import { Handle, Position, type NodeProps } from '@xyflow/svelte'; + import { Handle, Position, type BuiltInNode, type NodeProps } from '@xyflow/svelte'; - type $$Props = NodeProps; + type $$Props = NodeProps; + $$restProps; export let data: { label: string } = { label: 'Node' }; export let positionAbsoluteX: number = 0; diff --git a/examples/svelte/src/routes/examples/overview/CustomNodeDragHandle.svelte b/examples/svelte/src/routes/examples/overview/CustomNodeDragHandle.svelte index dcdddfc8..c087f7de 100644 --- a/examples/svelte/src/routes/examples/overview/CustomNodeDragHandle.svelte +++ b/examples/svelte/src/routes/examples/overview/CustomNodeDragHandle.svelte @@ -1,7 +1,8 @@ diff --git a/examples/svelte/src/routes/examples/subflows/DebugNode.svelte b/examples/svelte/src/routes/examples/subflows/DebugNode.svelte index 9676957e..ecacb06b 100644 --- a/examples/svelte/src/routes/examples/subflows/DebugNode.svelte +++ b/examples/svelte/src/routes/examples/subflows/DebugNode.svelte @@ -1,16 +1,19 @@
{id}
- x:{Math.round(positionAbsolute.x)} y:{Math.round(positionAbsolute.y)} z:{zIndex} + x:{Math.round(positionAbsoluteX)} y:{Math.round(positionAbsoluteY)} z:{zIndex}
diff --git a/examples/svelte/src/routes/examples/useupdatenodeinternals/CustomNode.svelte b/examples/svelte/src/routes/examples/useupdatenodeinternals/CustomNode.svelte index fbe9c8d7..89a73e1c 100644 --- a/examples/svelte/src/routes/examples/useupdatenodeinternals/CustomNode.svelte +++ b/examples/svelte/src/routes/examples/useupdatenodeinternals/CustomNode.svelte @@ -4,6 +4,7 @@ type $$Props = NodeProps; export let id: $$Props['id']; + $$restProps; const updateNodeInternals = useUpdateNodeInternals(); diff --git a/packages/svelte/src/lib/components/EdgeWrapper/EdgeWrapper.svelte b/packages/svelte/src/lib/components/EdgeWrapper/EdgeWrapper.svelte index f2166cee..54fdf91f 100644 --- a/packages/svelte/src/lib/components/EdgeWrapper/EdgeWrapper.svelte +++ b/packages/svelte/src/lib/components/EdgeWrapper/EdgeWrapper.svelte @@ -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(); diff --git a/packages/svelte/src/lib/components/Handle/Handle.svelte b/packages/svelte/src/lib/components/Handle/Handle.svelte index f93688fc..a7b5493c 100644 --- a/packages/svelte/src/lib/components/Handle/Handle.svelte +++ b/packages/svelte/src/lib/components/Handle/Handle.svelte @@ -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('svelteflow__node_id'); const connectable = getContext>('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, diff --git a/packages/svelte/src/lib/components/NodeSelection/NodeSelection.svelte b/packages/svelte/src/lib/components/NodeSelection/NodeSelection.svelte index e648604a..08a1cd6e 100644 --- a/packages/svelte/src/lib/components/NodeSelection/NodeSelection.svelte +++ b/packages/svelte/src/lib/components/NodeSelection/NodeSelection.svelte @@ -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} diff --git a/packages/svelte/src/lib/components/NodeWrapper/NodeWrapper.svelte b/packages/svelte/src/lib/components/NodeWrapper/NodeWrapper.svelte index 74a30a3b..7ba52792 100644 --- a/packages/svelte/src/lib/components/NodeWrapper/NodeWrapper.svelte +++ b/packages/svelte/src/lib/components/NodeWrapper/NodeWrapper.svelte @@ -1,7 +1,7 @@ diff --git a/packages/svelte/src/lib/components/NodeWrapper/types.ts b/packages/svelte/src/lib/components/NodeWrapper/types.ts index 7277be5f..842eb70b 100644 --- a/packages/svelte/src/lib/components/NodeWrapper/types.ts +++ b/packages/svelte/src/lib/components/NodeWrapper/types.ts @@ -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; }; diff --git a/packages/svelte/src/lib/container/NodeRenderer/NodeRenderer.svelte b/packages/svelte/src/lib/container/NodeRenderer/NodeRenderer.svelte index dc08aee0..9aeb308d 100644 --- a/packages/svelte/src/lib/container/NodeRenderer/NodeRenderer.svelte +++ b/packages/svelte/src/lib/container/NodeRenderer/NodeRenderer.svelte @@ -26,7 +26,7 @@ updates.set(id, { id, nodeElement: entry.target as HTMLDivElement, - forceUpdate: true + force: true }); }); diff --git a/packages/svelte/src/lib/container/Pane/Pane.svelte b/packages/svelte/src/lib/container/Pane/Pane.svelte index 05cbdb41..e616a1b4 100644 --- a/packages/svelte/src/lib/container/Pane/Pane.svelte +++ b/packages/svelte/src/lib/container/Pane/Pane.svelte @@ -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 = diff --git a/packages/svelte/src/lib/hooks/useInternalNode.ts b/packages/svelte/src/lib/hooks/useInternalNode.ts new file mode 100644 index 00000000..16c83960 --- /dev/null +++ b/packages/svelte/src/lib/hooks/useInternalNode.ts @@ -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 { + const { nodeLookup, nodes } = useStore(); + + return derived([nodeLookup, nodes], ([nodeLookup]) => nodeLookup.get(id)); +} diff --git a/packages/svelte/src/lib/hooks/useSvelteFlow.ts b/packages/svelte/src/lib/hooks/useSvelteFlow.ts index 6c83418f..be40af64 100644 --- a/packages/svelte/src/lib/hooks/useSvelteFlow.ts +++ b/packages/svelte/src/lib/hooks/useSvelteFlow.ts @@ -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(lookup: Map, ids: string[]) { +function getElements(lookup: Map, ids: string[]): Node[]; +function getElements(lookup: Map, ids: string[]): Edge[]; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function getElements(lookup: Map, 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); } } diff --git a/packages/svelte/src/lib/hooks/useUpdateNodeInternals.ts b/packages/svelte/src/lib/hooks/useUpdateNodeInternals.ts index cbb240ab..489dec0b 100644 --- a/packages/svelte/src/lib/hooks/useUpdateNodeInternals.ts +++ b/packages/svelte/src/lib/hooks/useUpdateNodeInternals.ts @@ -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 }); } }); diff --git a/packages/svelte/src/lib/plugins/Controls/Controls.svelte b/packages/svelte/src/lib/plugins/Controls/Controls.svelte index aedcc182..2984ad2c 100644 --- a/packages/svelte/src/lib/plugins/Controls/Controls.svelte +++ b/packages/svelte/src/lib/plugins/Controls/Controls.svelte @@ -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 = () => { diff --git a/packages/svelte/src/lib/plugins/Controls/types.ts b/packages/svelte/src/lib/plugins/Controls/types.ts index 1de8dee9..a4e5f9d7 100644 --- a/packages/svelte/src/lib/plugins/Controls/types.ts +++ b/packages/svelte/src/lib/plugins/Controls/types.ts @@ -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 & { diff --git a/packages/svelte/src/lib/store/index.ts b/packages/svelte/src/lib/store/index.ts index 39c9cad4..e02573ad 100644 --- a/packages/svelte/src/lib/store/index.ts +++ b/packages/svelte/src/lib/store/index.ts @@ -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(); diff --git a/packages/svelte/src/lib/types/general.ts b/packages/svelte/src/lib/types/general.ts index fe728fae..8aaa9a0a 100644 --- a/packages/svelte/src/lib/types/general.ts +++ b/packages/svelte/src/lib/types/general.ts @@ -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; +export type FitViewOptions = FitViewOptionsBase; export type OnDelete = (params: { nodes: Node[]; edges: Edge[] }) => void; export type OnEdgeCreate = (connection: Connection) => Edge | Connection | void; diff --git a/packages/svelte/src/lib/types/nodes.ts b/packages/svelte/src/lib/types/nodes.ts index 488b306f..0e741c00 100644 --- a/packages/svelte/src/lib/types/nodes.ts +++ b/packages/svelte/src/lib/types/nodes.ts @@ -45,3 +45,14 @@ export type NodeTypes = Record< export type DefaultNodeOptions = Partial>; 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 }; +}; diff --git a/packages/svelte/src/lib/utils/index.ts b/packages/svelte/src/lib/utils/index.ts index 8c9acdf3..10f205ca 100644 --- a/packages/svelte/src/lib/utils/index.ts +++ b/packages/svelte/src/lib/utils/index.ts @@ -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 = (element: unknown): element */ export const isEdge = (element: unknown): element is EdgeType => isEdgeBase(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 }; - }>(); diff --git a/packages/system/src/types/general.ts b/packages/system/src/types/general.ts index 0ab0fa03..6ff1dd45 100644 --- a/packages/system/src/types/general.ts +++ b/packages/system/src/types/general.ts @@ -61,13 +61,13 @@ export type FitViewParamsBase = { nodeOrigin?: NodeOrigin; }; -export type FitViewOptionsBase = { +export type FitViewOptionsBase = { padding?: number; includeHiddenNodes?: boolean; minZoom?: number; maxZoom?: number; duration?: number; - nodes?: (NodeType | { id: NodeType['id'] })[]; + nodes?: (NodeType | { id: string })[]; }; export type Viewport = {