Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f31f819
Add easing option to setZoom function
lgrkvst Mar 1, 2026
37f3a47
Add github action to codespell main on push and PRs
yarikoptic Mar 2, 2026
acda5ad
Add rudimentary codespell config
yarikoptic Mar 2, 2026
e4f4f31
Update codespell config: skip .npm/.cache, add ignore-words-list
yarikoptic Mar 2, 2026
ecfaac8
Fix ambiguous typos requiring context review
yarikoptic Mar 2, 2026
4f36cdc
Add .npm to .gitignore
yarikoptic Mar 2, 2026
b26df27
[DATALAD RUNCMD] Fix non-ambiguous typos with codespell
yarikoptic Mar 2, 2026
54d1e14
Fix grammar typo: "if is fails" → "if it fails"
yarikoptic Mar 3, 2026
b29e9a8
Do not wild exclude .git*, so we could codespell .github/ workflows
yarikoptic Mar 3, 2026
5c5cf6d
refactor(useReactFlow): pass options
moklick Mar 6, 2026
017218a
Merge branch 'patch-2' of github.com:lgrkvst/xyflow into lgrkvst-patch-2
moklick Mar 6, 2026
c9d48d5
fix: screenToFlowPosition add snapGrid types
dfblhmm Mar 9, 2026
8224951
chore(changesets): add
moklick Mar 9, 2026
4a278db
Fix missing border radius on smooth step edge bends
justn-hyeok Mar 19, 2026
dc5a005
chore(useSvelteFlow): pass options inside setZoom correctly
moklick Mar 19, 2026
77cb125
Fix options passing in viewport helper functions
moklick Mar 19, 2026
fe9ec9a
Merge pull request #5723 from xyflow/lgrkvst-patch-2
moklick Mar 19, 2026
8c9b7e7
chore(changesets): add
moklick Mar 19, 2026
38f4fef
Merge pull request #5722 from dfblhmm/fix/type-definition
moklick Mar 19, 2026
f91ef16
refactor(step-edge): cleanup
moklick Mar 19, 2026
e7b78d1
Merge pull request #5720 from yarikoptic/enh-codespell
moklick Mar 19, 2026
916c557
Merge pull request #5730 from justn-hyeok/fix/smoothstep-edge-rounding
moklick Mar 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/brown-shrimps-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@xyflow/react': patch
---

Add `snapGrid` to `screenToFlowPosition` options
6 changes: 6 additions & 0 deletions .changeset/dull-cows-sneeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@xyflow/react': patch
'@xyflow/svelte': patch
---

Pass options to useReactFlow/useSvelteFlow viewport helper functions correctly
5 changes: 5 additions & 0 deletions .changeset/fix-smoothstep-edge-rounding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@xyflow/system": patch
---

Fix missing border radius on `getSmoothStepPath` edge bends when using `stepPosition`
8 changes: 8 additions & 0 deletions .codespellrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[codespell]
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
skip = .git,.gitattributes,.gitignore,package-lock.json,*-lock.yaml,*.css,.codespellrc,.npm,.cache
check-hidden = true
# ned - person name "Ned Batchelder" in .coderabbit.yaml
# mistic - GitHub username @mistic in CHANGELOGs
# inout - legitimate "inout field" (input/output) term
ignore-words-list = ned,mistic,inout
23 changes: 23 additions & 0 deletions .github/workflows/codespell.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Codespell configuration is within .codespellrc
---
name: Codespell

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

jobs:
codespell:
name: Check for spelling errors
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
- name: Codespell
uses: codespell-project/actions-codespell@v2
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.DS_Store
.cache
.npm
node_modules
examples/build
cypress/videos
Expand Down
2 changes: 1 addition & 1 deletion CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ Additionally, we ask that all community members uphold the standards laid out in

## Attribution

This Code of Conduct is a direct decendant of the [Gleam Code of Conduct](https://github.com/gleam-lang/gleam/blob/f793b5d28a3102276a8b861c7e16a19c5231426e/CODE_OF_CONDUCT.md), which is itself a decendant of the [Contributor Covenant (v1.4)](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html).
This Code of Conduct is a direct descendant of the [Gleam Code of Conduct](https://github.com/gleam-lang/gleam/blob/f793b5d28a3102276a8b861c7e16a19c5231426e/CODE_OF_CONDUCT.md), which is itself a descendant of the [Contributor Covenant (v1.4)](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html).
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ Astro App used for SSR testing at [`examples/astro-xyflow`](./astro-xyflow)

## E2E

For furhter documentation of E2E tests have a look at [`/tests/playwright`](/tests/playwright).
For further documentation of E2E tests have a look at [`/tests/playwright`](/tests/playwright).
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
fitView
fitViewOptions={{ padding: 2 }}
onconnectstart={(_, { nodeId }) => {
// Memorize the nodeId you start draggin a connection line from a node
// Memorize the nodeId you start dragging a connection line from a node
connectingNodeId = nodeId;
}}
onconnectend={handleConnectEnd}
Expand Down
4 changes: 2 additions & 2 deletions packages/react/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ There is more! Besides the new main features, we added some minor things that we

## 12.0.0-next.22

- ⚠️ rename `updateEdge` to `reconnectEdge` and realted APIs [#4373](https://github.com/xyflow/xyflow/pull/4373)
- ⚠️ rename `updateEdge` to `reconnectEdge` and related APIs [#4373](https://github.com/xyflow/xyflow/pull/4373)
- revise selection usability (capture while dragging out of the flow)
- use correct end handle position when drawing a connection lines
- determine correct end positions for connection lines
Expand Down Expand Up @@ -1021,7 +1021,7 @@ There is more! Besides the new main features, we added some minor things that we

- **`useConnection` hook:** This hook makes it possible to handle an ongoing connection. For example, you can use it for colorizing handles.
- **`onDelete` handler**: We added a combined handler for `onDeleteNodes` and `onDeleteEdges` to make it easier to react to deletions.
- **`isValidConnection` prop:** This makes it possible to implement one validation function for all connections. It also gets called for programatically added edges.
- **`isValidConnection` prop:** This makes it possible to implement one validation function for all connections. It also gets called for programmatically added edges.
- **Controlled `viewport`:** This is definitely an advanced feature. Possible use cases are to animate the viewport or round the transform for lower res screens for example. This features brings two new props: `viewport` and `onViewportChange`.
- **`ViewportPortal` component:** This makes it possible to render elements in the viewport without the need to implement a custom node.
- **Background component**: add `patternClassName` to be able to style the background pattern by using a class name. This is useful if you want to style the background pattern with Tailwind for example.
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/hooks/useHandleConnections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export function useHandleConnections({
);

useEffect(() => {
// @todo dicuss if onConnect/onDisconnect should be called when the component mounts/unmounts
// @todo discuss if onConnect/onDisconnect should be called when the component mounts/unmounts
if (prevConnections.current && prevConnections.current !== connections) {
const _connections = connections ?? new Map();
handleConnectionChange(prevConnections.current, _connections, onDisconnect);
Expand Down
6 changes: 3 additions & 3 deletions packages/react/src/hooks/useViewportHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ const useViewportHelper = (): ViewportHelperFunctions => {
zoomIn: (options) => {
const { panZoom } = store.getState();

return panZoom ? panZoom.scaleBy(1.2, { duration: options?.duration }) : Promise.resolve(false);
return panZoom ? panZoom.scaleBy(1.2, options) : Promise.resolve(false);
},
zoomOut: (options) => {
const { panZoom } = store.getState();

return panZoom ? panZoom.scaleBy(1 / 1.2, { duration: options?.duration }) : Promise.resolve(false);
return panZoom ? panZoom.scaleBy(1 / 1.2, options) : Promise.resolve(false);
},
zoomTo: (zoomLevel, options) => {
const { panZoom } = store.getState();

return panZoom ? panZoom.scaleTo(zoomLevel, { duration: options?.duration }) : Promise.resolve(false);
return panZoom ? panZoom.scaleTo(zoomLevel, options) : Promise.resolve(false);
},
getZoom: () => store.getState().transform[2],
setViewport: async (viewport, options) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ const createStore = ({
}
},
/*
* Every node gets registerd at a ResizeObserver. Whenever a node
* Every node gets registered at a ResizeObserver. Whenever a node
* changes its dimensions, this function is called to measure the
* new dimensions and update the nodes.
*/
Expand Down
6 changes: 5 additions & 1 deletion packages/react/src/types/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
Connection,
NodeChange,
EdgeChange,
SnapGrid,
} from '@xyflow/system';

import type { Node, Edge, ReactFlowInstance, EdgeProps, NodeProps } from '.';
Expand Down Expand Up @@ -203,7 +204,10 @@ export type ViewportHelperFunctions = {
* @example
* const flowPosition = screenToFlowPosition({ x: event.clientX, y: event.clientY })
*/
screenToFlowPosition: (clientPosition: XYPosition, options?: { snapToGrid: boolean }) => XYPosition;
screenToFlowPosition: (
clientPosition: XYPosition,
options?: { snapToGrid?: boolean; snapGrid?: SnapGrid }
) => XYPosition;
/**
* Translate a position inside the flow's canvas to a screen pixel position.
*
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/types/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export type NodeWrapperProps<NodeType extends Node> = {

/**
* The `BuiltInNode` type represents the built-in node types that are available in React Flow.
* You can use this type to extend your custom node type if you still want ot use the built-in ones.
* You can use this type to extend your custom node type if you still want to use the built-in ones.
*
* @public
* @example
Expand Down
2 changes: 1 addition & 1 deletion packages/svelte/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@ Another huge update for Svelte Flow 🙏 Handling data flows will be way easier

This is a huge update! We added a new `<NodeToolbar />` component and a new `colorMode` ('light' | 'dark' | 'system') prop for toggling dark/light mode.

There are also some breaking changes again (sorry!) but we are very close to the final API for Svelte Flow 1.0.0. The biggest change is that we group node attriubutes (`width`, `height`, `positionAbsolute`) that are added by the library under `node.computed`. This makes it easier to understand, that this stuff comes from the library itself. `node.width` and `node.height` is still an optional node option and can be used to set certain dimensions for SSR or on the client.
There are also some breaking changes again (sorry!) but we are very close to the final API for Svelte Flow 1.0.0. The biggest change is that we group node attributes (`width`, `height`, `positionAbsolute`) that are added by the library under `node.computed`. This makes it easier to understand, that this stuff comes from the library itself. `node.width` and `node.height` is still an optional node option and can be used to set certain dimensions for SSR or on the client.

- add `<NodeToolbar />` component
- add `on:selectionclick` and `on:selectioncontextmenu` event handlers
Expand Down
6 changes: 3 additions & 3 deletions packages/svelte/src/lib/container/SvelteFlow/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export type SvelteFlowProps<
* @default 'strict'
*/
connectionMode?: ConnectionMode;
/** Provide a custom snippet to be used insted of the default connection line */
/** Provide a custom snippet to be used instead of the default connection line */
connectionLineComponent?: Component;
/** Styles to be applied to the connection line */
connectionLineStyle?: string;
Expand Down Expand Up @@ -325,7 +325,7 @@ export type SvelteFlowProps<
*/
panOnScrollMode?: PanOnScrollMode;
/**
* Enableing this prop allows users to pan the viewport by clicking and dragging.
* Enabling this prop allows users to pan the viewport by clicking and dragging.
* You can also set this prop to an array of numbers to limit which mouse buttons can activate panning.
* @default true
* @example [0, 2] // allows panning with the left and right mouse buttons
Expand Down Expand Up @@ -447,7 +447,7 @@ export type SvelteFlowProps<
/** This event handler is called when the user stops panning or zooming the viewport */
onmoveend?: OnMoveEnd;
/**
* Ocassionally something may happen that causes Svelte Flow to throw an error.
* Occasionally something may happen that causes Svelte Flow to throw an error.
* Instead of exploding your application, we log a message to the console and then call this event handler.
* You might use it for additional logging or to show a message to the user.
*/
Expand Down
4 changes: 1 addition & 3 deletions packages/svelte/src/lib/hooks/useSvelteFlow.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,7 @@ export function useSvelteFlow<NodeType extends Node = Node, EdgeType extends Edg
getEdges: (ids) => (ids === undefined ? store.edges : getElements(store.edgeLookup, ids)),
setZoom: (zoomLevel, options) => {
const panZoom = store.panZoom;
return panZoom
? panZoom.scaleTo(zoomLevel, { duration: options?.duration })
: Promise.resolve(false);
return panZoom ? panZoom.scaleTo(zoomLevel, options) : Promise.resolve(false);
},
getZoom: () => store.viewport.zoom,
setViewport: async (nextViewport, options) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/svelte/src/lib/store/initial-store.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ export function getInitialStore<NodeType extends Node = Node, EdgeType extends E
}

// Only way to check if an object is a proxy
// is to see if is failes to perform a structured clone
// is to see if it fails to perform a structured clone
function warnIfDeeplyReactive(array: unknown[] | undefined, name: string) {
try {
if (array && array.length > 0) {
Expand Down
2 changes: 1 addition & 1 deletion packages/system/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@

- [#4464](https://github.com/xyflow/xyflow/pull/4464) [`89cd677b`](https://github.com/xyflow/xyflow/commit/89cd677b5668b78434e02e7b025c6ac58db91e58) Thanks [@moklick](https://github.com/moklick)! - fix(handles): reconnect for connectionMode=loose

- [#4467](https://github.com/xyflow/xyflow/pull/4467) [`c253c7c5`](https://github.com/xyflow/xyflow/commit/c253c7c59a2ccd2cb91ad44ce4acbe481d9d7fe1) Thanks [@moklick](https://github.com/moklick)! - chore(subflows): log warning instead of throwing an error when parent node cant be found
- [#4467](https://github.com/xyflow/xyflow/pull/4467) [`c253c7c5`](https://github.com/xyflow/xyflow/commit/c253c7c59a2ccd2cb91ad44ce4acbe481d9d7fe1) Thanks [@moklick](https://github.com/moklick)! - chore(subflows): log warning instead of throwing an error when parent node can't be found

## 0.0.36

Expand Down
32 changes: 16 additions & 16 deletions packages/system/src/utils/edges/smoothstep-edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,12 @@ function getPoints({
if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {
if (dirAccessor === 'x') {
// Primary direction is horizontal, so stepPosition affects X coordinate
centerX = center.x ?? (sourceGapped.x + (targetGapped.x - sourceGapped.x) * stepPosition);
centerX = center.x ?? sourceGapped.x + (targetGapped.x - sourceGapped.x) * stepPosition;
centerY = center.y ?? (sourceGapped.y + targetGapped.y) / 2;
} else {
// Primary direction is vertical, so stepPosition affects Y coordinate
// Primary direction is vertical, so stepPosition affects Y coordinate
centerX = center.x ?? (sourceGapped.x + targetGapped.x) / 2;
centerY = center.y ?? (sourceGapped.y + (targetGapped.y - sourceGapped.y) * stepPosition);
centerY = center.y ?? sourceGapped.y + (targetGapped.y - sourceGapped.y) * stepPosition;
}

/*
Expand Down Expand Up @@ -194,11 +194,17 @@ function getPoints({
}
}

const gappedSource = { x: sourceGapped.x + sourceGapOffset.x, y: sourceGapped.y + sourceGapOffset.y };
const gappedTarget = { x: targetGapped.x + targetGapOffset.x, y: targetGapped.y + targetGapOffset.y };

const pathPoints = [
source,
{ x: sourceGapped.x + sourceGapOffset.x, y: sourceGapped.y + sourceGapOffset.y },
// we only want to add the gapped source/target if they are different from the first/last point to avoid duplicates which can cause issues with the bends
...(gappedSource.x !== points[0].x || gappedSource.y !== points[0].y ? [gappedSource] : []),
...points,
{ x: targetGapped.x + targetGapOffset.x, y: targetGapped.y + targetGapOffset.y },
...(gappedTarget.x !== points[points.length - 1].x || gappedTarget.y !== points[points.length - 1].y
? [gappedTarget]
: []),
target,
];

Expand Down Expand Up @@ -280,19 +286,13 @@ export function getSmoothStepPath({
stepPosition,
});

const path = points.reduce<string>((res, p, i) => {
let segment = '';
let path = `M${points[0].x} ${points[0].y}`;

if (i > 0 && i < points.length - 1) {
segment = getBend(points[i - 1], p, points[i + 1], borderRadius);
} else {
segment = `${i === 0 ? 'M' : 'L'}${p.x} ${p.y}`;
}

res += segment;
for (let i = 1; i < points.length - 1; i++) {
path += getBend(points[i - 1], points[i], points[i + 1], borderRadius);
}

return res;
}, '');
path += `L${points[points.length - 1].x} ${points[points.length - 1].y}`;

return [path, labelX, labelY, offsetX, offsetY];
}
2 changes: 1 addition & 1 deletion packages/system/src/utils/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ export function nodeHasDimensions<NodeType extends NodeBase = NodeBase>(node: No
}

/**
* Convert child position to aboslute position
* Convert child position to absolute position
*
* @internal
* @param position
Expand Down
2 changes: 1 addition & 1 deletion packages/system/src/utils/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ export async function panBy({
* @param connectionKey at which key the connection should be added
* @param connectionLookup reference to the connection lookup
* @param nodeId nodeId of the connection
* @param handleId handleId of the conneciton
* @param handleId handleId of the connection
*/
function addConnectionToLookup(
type: 'source' | 'target',
Expand Down
2 changes: 1 addition & 1 deletion packages/system/src/xyhandle/XYHandle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ function onPointerDown(
doc.addEventListener('touchend', onPointerUp as EventListener);
}

// checks if and returns connection in fom of an object { source: 123, target: 312 }
// checks if and returns connection in form of an object { source: 123, target: 312 }
function isValidHandle(
event: MouseEvent | TouchEvent,
{
Expand Down
2 changes: 1 addition & 1 deletion packages/system/src/xypanzoom/eventhandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ export function createPanZoomEndHandler({
() => {
onPanZoomEnd?.(event.sourceEvent as MouseEvent | TouchEvent, viewport);
},
// we need a setTimeout for panOnScroll to supress multiple end events fired during scroll
// we need a setTimeout for panOnScroll to suppress multiple end events fired during scroll
panOnScroll ? 150 : 0
);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/playwright/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# End-to-End with Playwright
Here you can find our framework independant E2E tests written with [playwright](https://playwright.dev/).
Here you can find our framework independent E2E tests written with [playwright](https://playwright.dev/).

## Installation
```bash
Expand Down
2 changes: 1 addition & 1 deletion tests/playwright/e2e/edges.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ test.describe('Edges', () => {
// Go to the starting url before each test.
await page.goto('/tests/generic/edges/general');

// Timeout get's ignored and tests timeout after 200ms ???
// Timeout gets ignored and tests timeout after 200ms ???
// page.waitForSelector('[data-id="edge-with-class"]', { timeout: 5000 });
});

Expand Down
Loading