diff --git a/examples/svelte/package.json b/examples/svelte/package.json index 4efc4adf..8cd6a14e 100644 --- a/examples/svelte/package.json +++ b/examples/svelte/package.json @@ -29,6 +29,7 @@ }, "type": "module", "dependencies": { + "@dagrejs/dagre": "^1.0.4", "@xyflow/svelte": "workspace:^" } } diff --git a/examples/svelte/src/components/Header/Header.svelte b/examples/svelte/src/components/Header/Header.svelte index e842824e..202e513b 100644 --- a/examples/svelte/src/components/Header/Header.svelte +++ b/examples/svelte/src/components/Header/Header.svelte @@ -3,21 +3,22 @@ import { page } from '$app/stores'; const routes = [ + 'add-node-on-drop', 'custom-connection-line', 'customnode', + 'dagre', 'drag-n-drop', 'edges', 'figma', 'interaction', + 'intersections', 'overview', 'stress', 'subflows', 'two-way-viewport', 'usesvelteflow', 'useupdatenodeinternals', - 'validation', - 'intersections', - 'add-node-on-drop' + 'validation' ]; const onChange = (event: Event) => { diff --git a/examples/svelte/src/routes/dagre/+page.svelte b/examples/svelte/src/routes/dagre/+page.svelte new file mode 100644 index 00000000..02b417a9 --- /dev/null +++ b/examples/svelte/src/routes/dagre/+page.svelte @@ -0,0 +1,79 @@ + + +
+ + + + + + + +
diff --git a/examples/svelte/src/routes/dagre/nodes-and-edges.ts b/examples/svelte/src/routes/dagre/nodes-and-edges.ts new file mode 100644 index 00000000..7be0a33f --- /dev/null +++ b/examples/svelte/src/routes/dagre/nodes-and-edges.ts @@ -0,0 +1,72 @@ +import type { Node, Edge } from '@xyflow/svelte'; + +const position = { x: 0, y: 0 }; +const edgeType = 'smoothstep'; + +export const initialNodes: Node[] = [ + { + id: '1', + type: 'input', + data: { label: 'input' }, + position + }, + { + id: '2', + data: { label: 'node 2' }, + position + }, + { + id: '2a', + data: { label: 'node 2a' }, + position + }, + { + id: '2b', + data: { label: 'node 2b' }, + position + }, + { + id: '2c', + data: { label: 'node 2c' }, + position + }, + { + id: '2d', + data: { label: 'node 2d' }, + position + }, + { + id: '3', + data: { label: 'node 3' }, + position + }, + { + id: '4', + data: { label: 'node 4' }, + position + }, + { + id: '5', + data: { label: 'node 5' }, + position + }, + { + id: '6', + type: 'output', + data: { label: 'output' }, + position + }, + { id: '7', type: 'output', data: { label: 'output' }, position } +]; + +export const initialEdges: Edge[] = [ + { id: 'e12', source: '1', target: '2', type: edgeType, animated: true }, + { id: 'e13', source: '1', target: '3', type: edgeType, animated: true }, + { id: 'e22a', source: '2', target: '2a', type: edgeType, animated: true }, + { id: 'e22b', source: '2', target: '2b', type: edgeType, animated: true }, + { id: 'e22c', source: '2', target: '2c', type: edgeType, animated: true }, + { id: 'e2c2d', source: '2c', target: '2d', type: edgeType, animated: true }, + { id: 'e45', source: '4', target: '5', type: edgeType, animated: true }, + { id: 'e56', source: '5', target: '6', type: edgeType, animated: true }, + { id: 'e57', source: '5', target: '7', type: edgeType, animated: true } +]; diff --git a/examples/svelte/src/routes/overview/CustomEdge.svelte b/examples/svelte/src/routes/overview/CustomEdge.svelte index 9f0992bb..5f22a826 100644 --- a/examples/svelte/src/routes/overview/CustomEdge.svelte +++ b/examples/svelte/src/routes/overview/CustomEdge.svelte @@ -2,7 +2,7 @@ import { BaseEdge, EdgeLabelRenderer, - useSvelteFlow, + useEdges, type EdgeProps, getBezierPath } from '@xyflow/svelte'; @@ -18,10 +18,10 @@ targetPosition: $$props.targetPosition }); - const svelteFlow = useSvelteFlow(); + const edges = useEdges(); function onClick() { - svelteFlow.edges.update((eds) => eds.filter((e) => e.id !== $$props.id)); + edges.update((eds) => eds.filter((e) => e.id !== $$props.id)); } diff --git a/examples/svelte/src/styles/base.css b/examples/svelte/src/styles/base.css deleted file mode 100644 index 80bc953d..00000000 --- a/examples/svelte/src/styles/base.css +++ /dev/null @@ -1,8 +0,0 @@ -/* this gets exported as style.css and can be used for the default theming */ -@import '../../../system/src/styles/init.css'; -@import '../../../system/src/styles/base.css'; - -.svelte-flow__edge-label { - text-align: center; - position: absolute; -} diff --git a/examples/svelte/src/styles/style.css b/examples/svelte/src/styles/style.css deleted file mode 100644 index b3f57e6f..00000000 --- a/examples/svelte/src/styles/style.css +++ /dev/null @@ -1,8 +0,0 @@ -/* this gets exported as style.css and can be used for the default theming */ -@import '../../../system/src/styles/init.css'; -@import '../../../system/src/styles/style.css'; - -.svelte-flow__edge-label { - text-align: center; - position: absolute; -} diff --git a/packages/react/src/additional-components/Background/Background.tsx b/packages/react/src/additional-components/Background/Background.tsx index 73664f9f..843daf19 100644 --- a/packages/react/src/additional-components/Background/Background.tsx +++ b/packages/react/src/additional-components/Background/Background.tsx @@ -46,6 +46,8 @@ function Background({ ? [scaledSize / offset, scaledSize / offset] : [patternDimensions[0] / offset, patternDimensions[1] / offset]; + const _patternId = `${patternId}${id ? id : ''}`; + return ( )} - + ); } diff --git a/packages/react/src/components/Nodes/wrapNode.tsx b/packages/react/src/components/Nodes/wrapNode.tsx index bff0ac24..4ebead71 100644 --- a/packages/react/src/components/Nodes/wrapNode.tsx +++ b/packages/react/src/components/Nodes/wrapNode.tsx @@ -69,8 +69,9 @@ export default (NodeComponent: ComponentType) => { const onContextMenuHandler = getMouseHandler(id, store.getState, onContextMenu); const onDoubleClickHandler = getMouseHandler(id, store.getState, onDoubleClick); const onSelectNodeHandler = (event: MouseEvent) => { - const { selectNodesOnDrag } = store.getState(); - if (isSelectable && (!selectNodesOnDrag || !isDraggable)) { + const { selectNodesOnDrag, nodeDragThreshold } = store.getState(); + + if (isSelectable && (!selectNodesOnDrag || !isDraggable || nodeDragThreshold > 0)) { // this handler gets called within the drag start event when selectNodesOnDrag=true handleNodeClick({ id, diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index bfd9be66..3f3fbf59 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,3 +1,29 @@ +## 0.0.24 + +- update node automatically when `type`, `sourcePosition` or `targetPosition` option changes +- prevent dev tool warnings when using built-in node types +- updates `useSvelteFlow` hook: +- add node type "group" +- add `class` prop for BaseEdge +- add `id` prop for Background +- add `selected` prop for MiniMap Node +- rename Controls prop `showInteractive` to `showLock` + +## 0.0.23 + +- updates `useSvelteFlow` hook: + - add `screenToFlowCoordinate` and `flowToScreenCoordinate` + - add `getConnectedEdges`, `getIncomers` and `getOutgoers` + - add `deleteElements` + - add `fitBounds` + - add `getIntersectingNodes` and `isNodeIntersecting` +- add `useConnection` hook +- add `useNodes` hook +- add `useEdges` hook +- add `viewport` prop (writable viewport) +- fix selection style +- fix Background component with lines variant + ## 0.0.22 - add `connectionLine` slot for rendering a custom connection line diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 1de47e73..d30631e3 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@xyflow/svelte", - "version": "0.0.22", + "version": "0.0.24", "description": "Svelte Flow - A highly customizable Svelte library for building node-based editors, workflow systems, diagrams and more.", "keywords": [ "svelte", @@ -36,6 +36,7 @@ "sideEffects": [ "*.css" ], + "license": "MIT", "publishConfig": { "access": "public" }, diff --git a/packages/svelte/src/lib/components/BaseEdge/BaseEdge.svelte b/packages/svelte/src/lib/components/BaseEdge/BaseEdge.svelte index 5676d135..fe0e7d94 100644 --- a/packages/svelte/src/lib/components/BaseEdge/BaseEdge.svelte +++ b/packages/svelte/src/lib/components/BaseEdge/BaseEdge.svelte @@ -14,6 +14,8 @@ export let markerEnd: $$Props['markerEnd'] = undefined; export let style: $$Props['style'] = undefined; export let interactionWidth: $$Props['interactionWidth'] = 20; + let className: $$Props['class'] = undefined; + export { className as class }; (); $: edgeComponent = $edgeTypes[type!] || BezierEdge; $: markerStartUrl = markerStart ? `url(#${getMarkerId(markerStart, $flowId)})` : undefined; @@ -51,12 +54,18 @@ } const edge = $edges.find((e) => e.id === id); - dispatch('edgeclick', { event, edge }); + + if (edge) { + dispatch('edgeclick', { event, edge }); + } } function onContextMenu(event: MouseEvent) { const edge = $edges.find((e) => e.id === id); - dispatch('edgecontextmenu', { event, edge }); + + if (edge) { + dispatch('edgecontextmenu', { event, edge }); + } } diff --git a/packages/svelte/src/lib/components/Handle/Handle.svelte b/packages/svelte/src/lib/components/Handle/Handle.svelte index 58d5ad02..655bcc6b 100644 --- a/packages/svelte/src/lib/components/Handle/Handle.svelte +++ b/packages/svelte/src/lib/components/Handle/Handle.svelte @@ -1,7 +1,13 @@ {#if isVisible}
{/if} diff --git a/packages/svelte/src/lib/components/nodes/DefaultNode.svelte b/packages/svelte/src/lib/components/nodes/DefaultNode.svelte index 6d8e06db..c802de0c 100644 --- a/packages/svelte/src/lib/components/nodes/DefaultNode.svelte +++ b/packages/svelte/src/lib/components/nodes/DefaultNode.svelte @@ -8,6 +8,28 @@ export let data: $$Props['data'] = { label: 'Node' }; export let targetPosition: $$Props['targetPosition'] = Position.Top; export let sourcePosition: $$Props['sourcePosition'] = Position.Bottom; + + // unused props - we need to list them here in order to prevent warnings + export let id: $$Props['id'] = ''; + 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 xPos: $$Props['xPos'] = 0; + export let yPos: $$Props['yPos'] = 0; + export let isConnectable: $$Props['isConnectable'] = undefined; + + // @todo: there must be a better way to do this + id; + selected; + type; + zIndex; + dragging; + dragHandle; + xPos; + yPos; + isConnectable; diff --git a/packages/svelte/src/lib/components/nodes/GroupNode.svelte b/packages/svelte/src/lib/components/nodes/GroupNode.svelte new file mode 100644 index 00000000..cd11b299 --- /dev/null +++ b/packages/svelte/src/lib/components/nodes/GroupNode.svelte @@ -0,0 +1,33 @@ + diff --git a/packages/svelte/src/lib/components/nodes/InputNode.svelte b/packages/svelte/src/lib/components/nodes/InputNode.svelte index 4eb41ddd..71e40096 100644 --- a/packages/svelte/src/lib/components/nodes/InputNode.svelte +++ b/packages/svelte/src/lib/components/nodes/InputNode.svelte @@ -7,6 +7,30 @@ export let data: $$Props['data'] = { label: 'Node' }; export let sourcePosition: $$Props['sourcePosition'] = Position.Bottom; + + // unused props - we need to list them here in order to prevent warnings + export let id: $$Props['id'] = ''; + export let selected: $$Props['selected'] = undefined; + export let targetPosition: $$Props['targetPosition'] = 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 xPos: $$Props['xPos'] = 0; + export let yPos: $$Props['yPos'] = 0; + export let isConnectable: $$Props['isConnectable'] = undefined; + + // @todo: there must be a better way to do this + id; + selected; + targetPosition; + type; + zIndex; + dragging; + dragHandle; + xPos; + yPos; + isConnectable; {data?.label} diff --git a/packages/svelte/src/lib/components/nodes/OutputNode.svelte b/packages/svelte/src/lib/components/nodes/OutputNode.svelte index 83b3745c..a9bde54b 100644 --- a/packages/svelte/src/lib/components/nodes/OutputNode.svelte +++ b/packages/svelte/src/lib/components/nodes/OutputNode.svelte @@ -7,6 +7,30 @@ export let data: $$Props['data'] = { label: 'Node' }; export let targetPosition: $$Props['targetPosition'] = Position.Top; + + // unused props - we need to list them here in order to prevent warnings + export let id: $$Props['id'] = ''; + export let selected: $$Props['selected'] = undefined; + export let sourcePosition: $$Props['sourcePosition'] = 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 xPos: $$Props['xPos'] = 0; + export let yPos: $$Props['yPos'] = 0; + export let isConnectable: $$Props['isConnectable'] = undefined; + + // @todo: there must be a better way to do this + id; + selected; + sourcePosition; + type; + zIndex; + dragging; + dragHandle; + xPos; + yPos; + isConnectable; {data?.label} diff --git a/packages/svelte/src/lib/container/EdgeRenderer/EdgeRenderer.svelte b/packages/svelte/src/lib/container/EdgeRenderer/EdgeRenderer.svelte index 77848c02..396c7119 100644 --- a/packages/svelte/src/lib/container/EdgeRenderer/EdgeRenderer.svelte +++ b/packages/svelte/src/lib/container/EdgeRenderer/EdgeRenderer.svelte @@ -29,7 +29,34 @@ ($elementsSelectable && typeof edge.selectable === 'undefined') )} - +