Merge branch 'xyflow' into svelte-flow-fix-hidden

This commit is contained in:
moklick
2023-11-08 18:19:13 +01:00
89 changed files with 4323 additions and 1254 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ import { defineConfig } from 'cypress';
export default defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
baseUrl: 'http://localhost:3000/examples',
viewportWidth: 1280,
viewportHeight: 720,
video: false,
+1 -1
View File
@@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React Flow Examples</title>
</head>
+13 -13
View File
@@ -1,5 +1,5 @@
{
"name": "@xyflow/react-examples",
"name": "react-examples",
"private": true,
"version": "0.0.0",
"type": "module",
@@ -15,25 +15,25 @@
},
"dependencies": {
"@xyflow/react": "workspace:*",
"classcat": "^5.0.3",
"classcat": "^5.0.4",
"dagre": "^0.8.5",
"localforage": "^1.10.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.3.0",
"zustand": "^4.4.1"
"react-router-dom": "^6.18.0",
"zustand": "^4.4.6"
},
"devDependencies": {
"@cypress/skip-test": "^2.6.1",
"@types/dagre": "^0.7.48",
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "4.0.4",
"@vitejs/plugin-react-swc": "^3.3.2",
"@types/dagre": "^0.7.52",
"@types/react": "^18.2.36",
"@types/react-dom": "^18.2.14",
"@vitejs/plugin-react": "4.1.1",
"@vitejs/plugin-react-swc": "^3.4.1",
"cypress": "12.17.3",
"cypress-real-events": "1.10.0",
"start-server-and-test": "^1.14.0",
"typescript": "5.1.3",
"vite": "4.4.9"
"cypress-real-events": "1.11.0",
"start-server-and-test": "^2.0.2",
"typescript": "5.2.2",
"vite": "4.5.0"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

+34
View File
@@ -0,0 +1,34 @@
import { useEffect, useState } from 'react';
import { Outlet, useLocation, useNavigate } from 'react-router-dom';
import routes from './routes';
export default function Header() {
const location = useLocation();
const navigate = useNavigate();
const [currentPath, setCurrentPath] = useState(location.pathname);
useEffect(() => {
const name = routes.find((route) => route.path === currentPath)?.name;
document.title = `React Flow Examples${name ? ' - ' + name : ''}`;
navigate(currentPath);
}, [currentPath]);
return (
<>
<header>
<a className="logo" href="https://github.com/xyflow/xyflow">
React Flow Dev
</a>
<select value={currentPath} onChange={(event) => setCurrentPath(event.target.value)}>
{routes.map((route) => (
<option value={route.path} key={route.path}>
{route.name}
</option>
))}
</select>
</header>
<Outlet />
</>
);
}
+12 -317
View File
@@ -1,326 +1,21 @@
import { useEffect, useState } from 'react';
import { BrowserRouter, Route, Routes, useLocation, useNavigate } from 'react-router-dom';
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
import routes from './routes';
import GenericTestRoutes from '../generic-tests';
import Basic from '../examples/Basic';
import Backgrounds from '../examples/Backgrounds';
import ControlledUncontrolled from '../examples/ControlledUncontrolled';
import ControlledViewport from '../examples/ControlledViewport';
import CustomConnectionLine from '../examples/CustomConnectionLine';
import CustomMiniMapNode from '../examples/CustomMiniMapNode';
import CustomNode from '../examples/CustomNode';
import DefaultNodes from '../examples/DefaultNodes';
import DragHandle from '../examples/DragHandle';
import DragNDrop from '../examples/DragNDrop';
import EasyConnect from '../examples/EasyConnect';
import Edges from '../examples/Edges';
import EdgeRenderer from '../examples/EdgeRenderer';
import EdgeTypes from '../examples/EdgeTypes';
import Empty from '../examples/Empty';
import Figma from '../examples/Figma';
import FloatingEdges from '../examples/FloatingEdges';
import Hidden from '../examples/Hidden';
import Interaction from '../examples/Interaction';
import Intersection from '../examples/Intersection';
import Layouting from '../examples/Layouting';
import MultiFlows from '../examples/MultiFlows';
import NestedNodes from '../examples/NestedNodes';
import NodeResizer from '../examples/NodeResizer';
import NodeTypeChange from '../examples/NodeTypeChange';
import NodeTypesObjectChange from '../examples/NodeTypesObjectChange';
import Overview from '../examples/Overview';
import Provider from '../examples/Provider';
import SaveRestore from '../examples/SaveRestore';
import Stress from '../examples/Stress';
import Subflow from '../examples/Subflow';
import SwitchFlow from '../examples/Switch';
import TouchDevice from '../examples/TouchDevice';
import Undirectional from '../examples/Undirectional';
import UpdatableEdge from '../examples/UpdatableEdge';
import UpdateNode from '../examples/UpdateNode';
import UseUpdateNodeInternals from '../examples/UseUpdateNodeInternals';
import UseReactFlow from '../examples/UseReactFlow';
import Validation from '../examples/Validation';
import UseKeyPress from '../examples/UseKeyPress';
import EdgeRouting from '../examples/EdgeRouting';
import CancelConnection from '../examples/CancelConnection';
import InteractiveMinimap from '../examples/InteractiveMinimap';
import UseOnSelectionChange from '../examples/UseOnSelectionChange';
import NodeToolbar from '../examples/NodeToolbar';
import useNodesInitialized from '../examples/UseNodesInit';
interface IRoute {
name: string;
path: string;
component: React.ComponentType;
}
const routes: IRoute[] = [
{
name: 'Basic',
path: '/',
component: Basic,
},
{
name: 'Backgrounds',
path: '/backgrounds',
component: Backgrounds,
},
{
name: 'Cancel Connection',
path: '/cancel-connection',
component: CancelConnection,
},
{
name: 'Controlled/Uncontrolled',
path: '/controlled-uncontrolled',
component: ControlledUncontrolled,
},
{
name: 'Controlled Viewport',
path: '/controlled-viewport',
component: ControlledViewport,
},
{
name: 'Custom Connection Line',
path: '/custom-connectionline',
component: CustomConnectionLine,
},
{
name: 'Custom Minimap Node',
path: '/custom-minimap-node',
component: CustomMiniMapNode,
},
{
name: 'Custom Node',
path: '/custom-node',
component: CustomNode,
},
{
name: 'Default Nodes',
path: '/default-nodes',
component: DefaultNodes,
},
{
name: 'Drag Handle',
path: '/draghandle',
component: DragHandle,
},
{
name: 'Drag and Drop',
path: '/dragndrop',
component: DragNDrop,
},
{
name: 'EasyConnect',
path: '/easy-connect',
component: EasyConnect,
},
{
name: 'Edges',
path: '/edges',
component: Edges,
},
{
name: 'Edge Renderer',
path: '/edge-renderer',
component: EdgeRenderer,
},
{
name: 'Edge Types',
path: '/edge-types',
component: EdgeTypes,
},
{
name: 'Edge Routing',
path: '/edge-routing',
component: EdgeRouting,
},
{
name: 'Empty',
path: '/empty',
component: Empty,
},
{
name: 'Figma',
path: '/figma',
component: Figma,
},
{
name: 'Floating Edges',
path: '/floating-edges',
component: FloatingEdges,
},
{
name: 'Hidden',
path: '/hidden',
component: Hidden,
},
{
name: 'Interaction',
path: '/interaction',
component: Interaction,
},
{
name: 'Intersection',
path: '/intersection',
component: Intersection,
},
{
name: 'Interactive Minimap',
path: '/interactive-minimap',
component: InteractiveMinimap,
},
{
name: 'Layouting',
path: '/layouting',
component: Layouting,
},
{
name: 'Multi Flows',
path: '/multiflows',
component: MultiFlows,
},
{
name: 'Nested Nodes',
path: '/nested-nodes',
component: NestedNodes,
},
{
name: 'Node Type Change',
path: '/nodetype-change',
component: NodeTypeChange,
},
{
name: 'nodeTypes Object Change',
path: '/nodetypesobject-change',
component: NodeTypesObjectChange,
},
{
name: 'NodeToolbar',
path: '/node-toolbar',
component: NodeToolbar,
},
{
name: 'NodeResizer',
path: '/node-resizer',
component: NodeResizer,
},
{
name: 'Overview',
path: '/overview',
component: Overview,
},
{
name: 'Provider',
path: '/provider',
component: Provider,
},
{
name: 'Save/Restore',
path: '/save-restore',
component: SaveRestore,
},
{
name: 'Stress',
path: '/stress',
component: Stress,
},
{
name: 'Subflow',
path: '/subflow',
component: Subflow,
},
{
name: 'Switch Flow',
path: '/switch',
component: SwitchFlow,
},
{
name: 'Touch Device',
path: '/touch-device',
component: TouchDevice,
},
{
name: 'Undirectional',
path: '/undirectional',
component: Undirectional,
},
{
name: 'Updatable Edge',
path: '/updatable-edge',
component: UpdatableEdge,
},
{
name: 'Update Node',
path: '/update-node',
component: UpdateNode,
},
{
name: 'useNodesInitialized',
path: '/use-nodes-initialized',
component: useNodesInitialized,
},
{
name: 'useOnSelectionChange',
path: '/use-on-selection-change',
component: UseOnSelectionChange,
},
{
name: 'useReactFlow',
path: '/usereactflow',
component: UseReactFlow,
},
{
name: 'useUpdateNodeInternals',
path: '/useupdatenodeinternals',
component: UseUpdateNodeInternals,
},
{
name: 'Validation',
path: '/validation',
component: Validation,
},
{
name: 'useKeyPress',
path: '/use-key-press',
component: UseKeyPress,
},
];
const Header = () => {
const location = useLocation();
const navigate = useNavigate();
const [currentPath, setCurrentPath] = useState(location.pathname);
useEffect(() => {
const name = routes.find((route) => route.path === currentPath)?.name;
document.title = `React Flow Examples${name ? ' - ' + name : ''}`;
navigate(currentPath);
}, [currentPath]);
return (
<header>
<a className="logo" href="https://github.com/wbkd/react-flow">
React Flow Dev
</a>
<select value={currentPath} onChange={(event) => setCurrentPath(event.target.value)}>
{routes.map((route) => (
<option value={route.path} key={route.path}>
{route.name}
</option>
))}
</select>
</header>
);
};
import Header from './header';
export default () => (
<BrowserRouter>
<Header />
<Routes>
{routes.map((route) => (
<Route path={route.path} key={route.path} element={<route.component />} />
))}
<Route path="/" element={<Navigate to="/examples" />} />
<Route path="examples" element={<Header />}>
<Route index element={<Basic />} />
{routes.map((route) => (
<Route path={route.path} key={route.path} element={<route.component />} />
))}
</Route>
<Route path="tests/generic/*" element={<GenericTestRoutes />} />
</Routes>
</BrowserRouter>
);
+287
View File
@@ -0,0 +1,287 @@
import Basic from '../examples/Basic';
import Backgrounds from '../examples/Backgrounds';
import ControlledUncontrolled from '../examples/ControlledUncontrolled';
import ControlledViewport from '../examples/ControlledViewport';
import CustomConnectionLine from '../examples/CustomConnectionLine';
import CustomMiniMapNode from '../examples/CustomMiniMapNode';
import CustomNode from '../examples/CustomNode';
import DefaultNodes from '../examples/DefaultNodes';
import DragHandle from '../examples/DragHandle';
import DragNDrop from '../examples/DragNDrop';
import EasyConnect from '../examples/EasyConnect';
import Edges from '../examples/Edges';
import EdgeRenderer from '../examples/EdgeRenderer';
import EdgeTypes from '../examples/EdgeTypes';
import Empty from '../examples/Empty';
import Figma from '../examples/Figma';
import FloatingEdges from '../examples/FloatingEdges';
import Hidden from '../examples/Hidden';
import Interaction from '../examples/Interaction';
import Intersection from '../examples/Intersection';
import Layouting from '../examples/Layouting';
import MultiFlows from '../examples/MultiFlows';
import NestedNodes from '../examples/NestedNodes';
import NodeResizer from '../examples/NodeResizer';
import NodeTypeChange from '../examples/NodeTypeChange';
import NodeTypesObjectChange from '../examples/NodeTypesObjectChange';
import Overview from '../examples/Overview';
import Provider from '../examples/Provider';
import SaveRestore from '../examples/SaveRestore';
import Stress from '../examples/Stress';
import Subflow from '../examples/Subflow';
import SwitchFlow from '../examples/Switch';
import TouchDevice from '../examples/TouchDevice';
import Undirectional from '../examples/Undirectional';
import UpdatableEdge from '../examples/UpdatableEdge';
import UpdateNode from '../examples/UpdateNode';
import UseUpdateNodeInternals from '../examples/UseUpdateNodeInternals';
import UseReactFlow from '../examples/UseReactFlow';
import Validation from '../examples/Validation';
import UseKeyPress from '../examples/UseKeyPress';
import EdgeRouting from '../examples/EdgeRouting';
import CancelConnection from '../examples/CancelConnection';
import InteractiveMinimap from '../examples/InteractiveMinimap';
import UseOnSelectionChange from '../examples/UseOnSelectionChange';
import NodeToolbar from '../examples/NodeToolbar';
import useNodesInitialized from '../examples/UseNodesInit';
export interface IRoute {
name: string;
path: string;
component: React.ComponentType;
}
const routes: IRoute[] = [
{
name: 'Basic',
path: 'basic',
component: Basic,
},
{
name: 'Backgrounds',
path: 'backgrounds',
component: Backgrounds,
},
{
name: 'Cancel Connection',
path: 'cancel-connection',
component: CancelConnection,
},
{
name: 'Controlled/Uncontrolled',
path: 'controlled-uncontrolled',
component: ControlledUncontrolled,
},
{
name: 'Controlled Viewport',
path: 'controlled-viewport',
component: ControlledViewport,
},
{
name: 'Custom Connection Line',
path: 'custom-connectionline',
component: CustomConnectionLine,
},
{
name: 'Custom Minimap Node',
path: 'custom-minimap-node',
component: CustomMiniMapNode,
},
{
name: 'Custom Node',
path: 'custom-node',
component: CustomNode,
},
{
name: 'Default Nodes',
path: 'default-nodes',
component: DefaultNodes,
},
{
name: 'Drag Handle',
path: 'draghandle',
component: DragHandle,
},
{
name: 'Drag and Drop',
path: 'dragndrop',
component: DragNDrop,
},
{
name: 'EasyConnect',
path: 'easy-connect',
component: EasyConnect,
},
{
name: 'Edges',
path: 'edges',
component: Edges,
},
{
name: 'Edge Renderer',
path: 'edge-renderer',
component: EdgeRenderer,
},
{
name: 'Edge Types',
path: 'edge-types',
component: EdgeTypes,
},
{
name: 'Edge Routing',
path: 'edge-routing',
component: EdgeRouting,
},
{
name: 'Empty',
path: 'empty',
component: Empty,
},
{
name: 'Figma',
path: 'figma',
component: Figma,
},
{
name: 'Floating Edges',
path: 'floating-edges',
component: FloatingEdges,
},
{
name: 'Hidden',
path: 'hidden',
component: Hidden,
},
{
name: 'Interaction',
path: 'interaction',
component: Interaction,
},
{
name: 'Intersection',
path: 'intersection',
component: Intersection,
},
{
name: 'Interactive Minimap',
path: 'interactive-minimap',
component: InteractiveMinimap,
},
{
name: 'Layouting',
path: 'layouting',
component: Layouting,
},
{
name: 'Multi Flows',
path: 'multiflows',
component: MultiFlows,
},
{
name: 'Nested Nodes',
path: 'nested-nodes',
component: NestedNodes,
},
{
name: 'Node Type Change',
path: 'nodetype-change',
component: NodeTypeChange,
},
{
name: 'nodeTypes Object Change',
path: 'nodetypesobject-change',
component: NodeTypesObjectChange,
},
{
name: 'NodeToolbar',
path: 'node-toolbar',
component: NodeToolbar,
},
{
name: 'NodeResizer',
path: 'node-resizer',
component: NodeResizer,
},
{
name: 'Overview',
path: 'overview',
component: Overview,
},
{
name: 'Provider',
path: 'provider',
component: Provider,
},
{
name: 'Save/Restore',
path: 'save-restore',
component: SaveRestore,
},
{
name: 'Stress',
path: 'stress',
component: Stress,
},
{
name: 'Subflow',
path: 'subflow',
component: Subflow,
},
{
name: 'Switch Flow',
path: 'switch',
component: SwitchFlow,
},
{
name: 'Touch Device',
path: 'touch-device',
component: TouchDevice,
},
{
name: 'Undirectional',
path: 'undirectional',
component: Undirectional,
},
{
name: 'Updatable Edge',
path: 'updatable-edge',
component: UpdatableEdge,
},
{
name: 'Update Node',
path: 'update-node',
component: UpdateNode,
},
{
name: 'useNodesInitialized',
path: 'use-nodes-initialized',
component: useNodesInitialized,
},
{
name: 'useOnSelectionChange',
path: 'use-on-selection-change',
component: UseOnSelectionChange,
},
{
name: 'useReactFlow',
path: 'usereactflow',
component: UseReactFlow,
},
{
name: 'useUpdateNodeInternals',
path: 'useupdatenodeinternals',
component: UseUpdateNodeInternals,
},
{
name: 'Validation',
path: 'validation',
component: Validation,
},
{
name: 'useKeyPress',
path: 'use-key-press',
component: UseKeyPress,
},
];
export default routes;
+7
View File
@@ -0,0 +1,7 @@
import { Edge, Node, ReactFlowProps } from '@xyflow/react';
declare global {
interface FlowConfig {
flowProps: Omit<ReactFlowProps, 'nodes' | 'edges'> & { nodes: Node[]; edges: Edge[] };
}
}
@@ -41,6 +41,7 @@ const initialNodes: Node[] = [
data: { label: 'Node 4' },
position: { x: 400, y: 200 },
className: 'light',
connectable: false,
},
];
+30
View File
@@ -0,0 +1,30 @@
import { useState, useCallback } from 'react';
import {
ReactFlow,
applyNodeChanges,
applyEdgeChanges,
addEdge,
OnNodesChange,
OnEdgesChange,
OnConnect,
} from '@xyflow/react';
type FlowProps = {
flowConfig: FlowConfig;
};
export default ({ flowConfig }: FlowProps) => {
const [nodes, setNodes] = useState(flowConfig.flowProps.nodes);
const [edges, setEdges] = useState(flowConfig.flowProps.edges);
const props = { ...flowConfig.flowProps, nodes, edges };
const onNodesChange: OnNodesChange = useCallback((changes) => setNodes((nds) => applyNodeChanges(changes, nds)), []);
const onEdgesChange: OnEdgesChange = useCallback((changes) => setEdges((eds) => applyEdgeChanges(changes, eds)), []);
const onConnect: OnConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)), []);
return (
<div style={{ height: '100%' }}>
<ReactFlow {...props} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} />
</div>
);
};
@@ -0,0 +1,163 @@
import { MarkerType } from '@xyflow/react';
export default {
flowProps: {
fitView: true,
nodes: [
{
id: '1',
data: { label: '1' },
position: { x: 0, y: 0 },
type: 'input',
},
{
id: '2',
data: { label: '2' },
position: { x: -100, y: 100 },
},
{
id: '3',
data: { label: '3' },
position: { x: 100, y: 100 },
},
{
id: '4',
data: { label: '4' },
position: { x: -100, y: 200 },
},
{
id: '5',
data: { label: '5' },
position: { x: 100, y: 200 },
},
{
id: '6',
data: { label: '6' },
position: { x: -100, y: 300 },
},
{
id: '7',
data: { label: '7' },
position: { x: 100, y: 300 },
},
{
id: '8',
data: { label: '8' },
position: { x: -100, y: 400 },
},
{
id: '9',
data: { label: '9' },
position: { x: 100, y: 400 },
},
{
id: '10',
data: { label: '10' },
position: { x: -100, y: 500 },
},
{
id: '11',
data: { label: '11' },
position: { x: 100, y: 500 },
},
// {
// id: '12',
// data: { label: '12' },
// position: { x: -100, y: 600 }
// },
// {
// id: '13',
// data: { label: '13' },
// position: { x: 100, y: 600 }
// }
],
edges: [
{
id: 'edge-with-class',
source: '1',
target: '2',
className: 'edge-class-test',
},
{
id: 'edge-with-style',
source: '1',
target: '3',
style: {
stroke: 'red',
},
},
{
id: 'hidden-edge',
source: '2',
target: '4',
label: 'hidden',
hidden: true,
},
{
id: 'animated-edge',
source: '3',
target: '5',
label: 'animated',
animated: true,
},
{
id: 'not-selectable-edge',
source: '4',
target: '6',
label: 'not-selectable',
selectable: false,
},
{
id: 'not-deletable',
source: '5',
target: '7',
label: 'not-deletable',
deletable: false,
},
{
id: 'z-index',
source: '6',
target: '8',
label: 'z-index',
zIndex: 3141592,
},
{
id: 'aria-label',
source: '7',
target: '9',
label: 'aria-label',
ariaLabel: 'aria-label-test',
},
{
id: 'interaction-width',
source: '8',
target: '10',
label: 'interaction-width',
interactionWidth: 42,
},
{
id: 'markers',
source: '9',
target: '11',
label: 'markers',
markerEnd: { type: MarkerType.Arrow },
markerStart: { type: MarkerType.ArrowClosed },
},
// {
// id: 'updatable',
// source: '9',
// target: '11',
// label: 'focusable',
// updatable: true
// },
// {
// id: 'not-focusable',
//
// source: '5',
// target: '7',
// label: 'not-focusable',
// focusable: false
// },
],
},
} satisfies FlowConfig;
@@ -0,0 +1,17 @@
import { useLocation } from 'react-router-dom';
import Flow from './Flow';
const flowConfigs = import.meta.glob<FlowConfig>('./**/*.ts', { eager: true, import: 'default' });
export default () => {
const location = useLocation();
const path = `.${location.pathname.replace('/tests/generic', '')}.ts`;
const flowConfig = flowConfigs[path];
if (!flowConfig) {
return `404: This route doesn't exists.`;
}
return <Flow flowConfig={flowConfig} />;
};
@@ -0,0 +1,25 @@
export default () => {
return (
<div
className="container"
style={{
width: '100px',
height: '50px',
background: 'red',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<div
className="drag-handle custom-drag-handle"
style={{
display: 'inline-block',
width: '25px',
height: '25px',
backgroundColor: 'green',
}}
/>
</div>
);
};
@@ -0,0 +1,91 @@
import DragHandleNode from './components/DragHandleNode';
export default {
flowProps: {
fitView: true,
nodeTypes: {
DragHandleNode,
},
nodes: [
{
id: 'Node-1',
data: { label: 'Node-1' },
position: { x: 0, y: 0 },
type: 'input',
className: 'playwright-test-class-123',
style: { backgroundColor: 'red' },
},
{
id: 'Node-2',
type: 'output',
data: { label: 'Node-2' },
position: { x: -100, y: 100 },
},
{
id: 'Node-3',
data: { label: 'Node-3' },
position: { x: 100, y: 100 },
},
{
id: 'Node-4',
data: { label: 'Node-4' },
position: { x: 0, y: 200 },
type: 'output',
},
{
id: 'drag-handle',
data: { label: 'Drag Handle' },
position: { x: 200, y: 0 },
type: 'DragHandleNode',
dragHandle: '.custom-drag-handle',
},
{
id: 'notConnectable',
type: 'output',
data: { label: 'notConnectable' },
position: { x: 0, y: 300 },
connectable: false,
},
{
id: 'notDraggable',
data: { label: 'notDraggable' },
position: { x: 0, y: 400 },
draggable: false,
},
{
id: 'notSelectable',
data: { label: 'notSelectable' },
position: { x: 0, y: 500 },
selectable: false,
},
{
id: 'notDeletable',
data: { label: 'notDeletable' },
position: { x: 0, y: 600 },
deletable: false,
},
{
id: 'hidden',
data: { label: 'hidden' },
position: { x: 0, y: 700 },
hidden: true,
},
],
edges: [
{
id: '1-2',
type: 'default',
source: 'Node-1',
target: 'Node-2',
label: 'edge',
},
{
id: '1-3',
type: 'default',
source: 'Node-1',
target: 'Node-3',
label: 'edge',
},
],
},
} satisfies FlowConfig;
@@ -0,0 +1,37 @@
export default {
flowProps: {
minZoom: 0.25,
maxZoom: 4,
fitView: true,
nodes: [
{
id: '1',
data: { label: '1' },
position: { x: 0, y: 0 },
type: 'input',
},
{
id: '2',
data: { label: '2' },
position: { x: -100, y: 100 },
},
{
id: '3',
data: { label: '3' },
position: { x: 100, y: 100 },
},
],
edges: [
{
id: 'first-edge',
source: '1',
target: '2',
},
{
id: 'second-edge',
source: '1',
target: '3',
},
],
},
} satisfies FlowConfig;
@@ -0,0 +1,38 @@
export default {
flowProps: {
panOnScroll: true,
defaultViewport: { x: 1.23, y: 9.87, zoom: 1.234 },
autoPanOnConnect: false,
autoPanOnNodeDrag: false,
nodes: [
{
id: '1',
data: { label: '1' },
position: { x: 0, y: 0 },
type: 'input',
},
{
id: '2',
data: { label: '2' },
position: { x: -100, y: 100 },
},
{
id: '3',
data: { label: '3' },
position: { x: 100, y: 100 },
},
],
edges: [
{
id: 'first-edge',
source: '1',
target: '2',
},
{
id: 'second-edge',
source: '1',
target: '3',
},
],
},
} satisfies FlowConfig;
+2 -1
View File
@@ -1,9 +1,10 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import './index.css';
import '@xyflow/react/dist/style.css';
import './index.css';
createRoot(document.getElementById('root') as HTMLElement).render(
<StrictMode>
+15 -15
View File
@@ -1,5 +1,5 @@
{
"name": "svelte",
"name": "svelte-examples",
"version": "0.0.1",
"private": true,
"scripts": {
@@ -12,20 +12,20 @@
"format": "prettier --plugin-search-dir . --write ."
},
"devDependencies": {
"@sveltejs/adapter-auto": "^2.0.0",
"@sveltejs/kit": "^1.20.4",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte": "^2.30.0",
"prettier": "^2.8.0",
"prettier-plugin-svelte": "^2.10.1",
"svelte": "^4.0.5",
"svelte-check": "^3.4.3",
"tslib": "^2.4.1",
"typescript": "^5.0.0",
"vite": "^4.4.2"
"@sveltejs/adapter-auto": "^2.1.1",
"@sveltejs/kit": "^1.27.3",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0",
"eslint": "^8.53.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-svelte": "^2.35.0",
"prettier": "^3.0.3",
"prettier-plugin-svelte": "^3.0.3",
"svelte": "^4.2.2",
"svelte-check": "^3.5.2",
"tslib": "^2.6.2",
"typescript": "^5.2.2",
"vite": "^4.5.0"
},
"type": "module",
"dependencies": {
+7
View File
@@ -1,4 +1,7 @@
// See https://kit.svelte.dev/docs/types#app
import type { Edge, Node, SvelteFlowProps } from '@xyflow/svelte';
// for information about these interfaces
declare global {
namespace App {
@@ -7,6 +10,10 @@ declare global {
// interface PageData {}
// interface Platform {}
}
interface FlowConfig {
flowProps: Omit<SvelteFlowProps, 'nodes' | 'edges'> & { nodes: Node[]; edges: Edge[] };
}
}
export {};
+2 -1
View File
@@ -1,8 +1,9 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
<style>
html,
body,
@@ -31,7 +31,7 @@
<div class="logo">Svelte Flow</div>
<select on:change={onChange} value={$page.route.id}>
{#each routes as route}
<option value={`/${route}`}>{route}</option>
<option value={`/examples/${route}`}>{route}</option>
{/each}
</select>
</header>
@@ -0,0 +1,161 @@
import { MarkerType } from '@xyflow/svelte';
export default {
flowProps: {
fitView: true,
nodes: [
{
id: '1',
data: { label: '1' },
position: { x: 0, y: 0 },
type: 'input'
},
{
id: '2',
data: { label: '2' },
position: { x: -100, y: 100 }
},
{
id: '3',
data: { label: '3' },
position: { x: 100, y: 100 }
},
{
id: '4',
data: { label: '4' },
position: { x: -100, y: 200 }
},
{
id: '5',
data: { label: '5' },
position: { x: 100, y: 200 }
},
{
id: '6',
data: { label: '6' },
position: { x: -100, y: 300 }
},
{
id: '7',
data: { label: '7' },
position: { x: 100, y: 300 }
},
{
id: '8',
data: { label: '8' },
position: { x: -100, y: 400 }
},
{
id: '9',
data: { label: '9' },
position: { x: 100, y: 400 }
},
{
id: '10',
data: { label: '10' },
position: { x: -100, y: 500 }
},
{
id: '11',
data: { label: '11' },
position: { x: 100, y: 500 }
}
// {
// id: '12',
// data: { label: '12' },
// position: { x: -100, y: 600 }
// },
// {
// id: '13',
// data: { label: '13' },
// position: { x: 100, y: 600 }
// }
],
edges: [
{
id: 'edge-with-class',
source: '1',
target: '2',
class: 'edge-class-test'
},
{
id: 'edge-with-style',
source: '1',
target: '3',
style: 'stroke: red;'
},
{
id: 'hidden-edge',
source: '2',
target: '4',
label: 'hidden',
hidden: true
},
{
id: 'animated-edge',
source: '3',
target: '5',
label: 'animated',
animated: true
},
{
id: 'not-selectable-edge',
source: '4',
target: '6',
label: 'not-selectable',
selectable: false
},
{
id: 'not-deletable',
source: '5',
target: '7',
label: 'not-deletable',
deletable: false
},
{
id: 'z-index',
source: '6',
target: '8',
label: 'z-index',
zIndex: 3141592
},
{
id: 'aria-label',
source: '7',
target: '9',
label: 'aria-label',
ariaLabel: 'aria-label-test'
},
{
id: 'interaction-width',
source: '8',
target: '10',
label: 'interaction-width',
interactionWidth: 42
},
{
id: 'markers',
source: '9',
target: '11',
label: 'markers',
markerEnd: { type: MarkerType.Arrow },
markerStart: { type: MarkerType.ArrowClosed }
}
// {
// id: 'updatable',
// source: '9',
// target: '11',
// label: 'focusable',
// updatable: true
// },
// {
// id: 'not-focusable',
//
// source: '5',
// target: '7',
// label: 'not-focusable',
// focusable: false
// },
]
}
} satisfies FlowConfig;
@@ -0,0 +1,26 @@
<script lang="ts">
import type { NodeProps } from '@xyflow/svelte';
type $$Props = NodeProps;
</script>
<div class="container">
<div class="drag-handle custom-drag-handle" />
</div>
<style>
.container {
width: 100px;
height: 50px;
background: red;
display: flex;
align-items: center;
justify-content: center;
}
.drag-handle {
display: inline-block;
width: 25px;
height: 25px;
background-color: green;
}
</style>
@@ -0,0 +1,91 @@
import DragHandleNode from './components/DragHandleNode.svelte';
export default {
flowProps: {
fitView: true,
nodeTypes: {
DragHandleNode
},
nodes: [
{
id: 'Node-1',
data: { label: 'Node-1' },
position: { x: 0, y: 0 },
type: 'input',
class: 'playwright-test-class-123',
style: 'background-color: red;'
},
{
id: 'Node-2',
type: 'output',
data: { label: 'Node-2' },
position: { x: -100, y: 100 }
},
{
id: 'Node-3',
data: { label: 'Node-3' },
position: { x: 100, y: 100 }
},
{
id: 'Node-4',
data: { label: 'Node-4' },
position: { x: 0, y: 200 },
type: 'output'
},
{
id: 'drag-handle',
data: { label: 'Drag Handle' },
position: { x: 200, y: 0 },
type: 'DragHandleNode',
dragHandle: '.custom-drag-handle'
},
{
id: 'notConnectable',
type: 'output',
data: { label: 'notConnectable' },
position: { x: 0, y: 300 },
connectable: false
},
{
id: 'notDraggable',
data: { label: 'notDraggable' },
position: { x: 0, y: 400 },
draggable: false
},
{
id: 'notSelectable',
data: { label: 'notSelectable' },
position: { x: 0, y: 500 },
selectable: false
},
{
id: 'notDeletable',
data: { label: 'notDeletable' },
position: { x: 0, y: 600 },
deletable: false
},
{
id: 'hidden',
data: { label: 'hidden' },
position: { x: 0, y: 700 },
hidden: true
}
],
edges: [
{
id: '1-2',
type: 'default',
source: 'Node-1',
target: 'Node-2',
label: 'edge'
},
{
id: '1-3',
type: 'default',
source: 'Node-1',
target: 'Node-3',
label: 'edge'
}
]
}
} satisfies FlowConfig;
@@ -0,0 +1,40 @@
export default {
flowProps: {
zoomOnScroll: false,
// zoomActivationKey: 'Space',
// panOnDrag: false,
// panOnScroll: false,
panActivationKey: 'Space',
fitView: true,
nodes: [
{
id: '1',
data: { label: '1' },
position: { x: 0, y: 0 },
type: 'input'
},
{
id: '2',
data: { label: '2' },
position: { x: -100, y: 100 }
},
{
id: '3',
data: { label: '3' },
position: { x: 100, y: 100 }
}
],
edges: [
{
id: 'first-edge',
source: '1',
target: '2'
},
{
id: 'second-edge',
source: '1',
target: '3'
}
]
}
} satisfies FlowConfig;
@@ -0,0 +1,37 @@
export default {
flowProps: {
minZoom: 0.25,
maxZoom: 4,
fitView: true,
nodes: [
{
id: '1',
data: { label: '1' },
position: { x: 0, y: 0 },
type: 'input'
},
{
id: '2',
data: { label: '2' },
position: { x: -100, y: 100 }
},
{
id: '3',
data: { label: '3' },
position: { x: 100, y: 100 }
}
],
edges: [
{
id: 'first-edge',
source: '1',
target: '2'
},
{
id: 'second-edge',
source: '1',
target: '3'
}
]
}
} satisfies FlowConfig;
@@ -0,0 +1,38 @@
export default {
flowProps: {
panOnScroll: true,
initialViewport: { x: 1.23, y: 9.87, zoom: 1.234 },
autoPanOnConnect: false,
autoPanOnNodeDrag: false,
nodes: [
{
id: '1',
data: { label: '1' },
position: { x: 0, y: 0 },
type: 'input'
},
{
id: '2',
data: { label: '2' },
position: { x: -100, y: 100 }
},
{
id: '3',
data: { label: '3' },
position: { x: 100, y: 100 }
}
],
edges: [
{
id: 'first-edge',
source: '1',
target: '2'
},
{
id: 'second-edge',
source: '1',
target: '3'
}
]
}
} satisfies FlowConfig;
+3 -3
View File
@@ -2,7 +2,7 @@ import { redirect } from '@sveltejs/kit';
/** @type {import('./$types').LayoutServerLoad} */
export function load({ route }) {
if (route.id === '/') {
throw redirect(307, '/overview');
}
if (route.id === '/') {
throw redirect(307, '/examples/overview');
}
}
@@ -1,5 +1,5 @@
<script lang="ts">
import { Header } from '../components/Header';
import { Header } from '$components/Header';
</script>
<div class="app">
@@ -0,0 +1 @@
<div>this redirects to /overview</div>
@@ -0,0 +1,11 @@
<script lang="ts">
import { SvelteFlowProvider } from '@xyflow/svelte';
import Flow from './Flow.svelte';
export let data: { flowConfig: FlowConfig };
</script>
<SvelteFlowProvider>
<Flow flowConfig={data.flowConfig} />
</SvelteFlowProvider>
@@ -0,0 +1,19 @@
import { error } from '@sveltejs/kit';
const flowConfigs = import.meta.glob<FlowConfig>('/src/generic-tests/**/*.ts', {
eager: true,
import: 'default'
});
/** @type {import('./$types').PageLoad} */
export function load({ params }) {
const flowConfig = flowConfigs[`/src/generic-tests/${params.topic}/${params.example}.ts`];
if (!flowConfig) {
throw error(404, 'Not found');
}
return {
flowConfig
};
}
@@ -0,0 +1,16 @@
<script lang="ts">
import { writable } from 'svelte/store';
import { SvelteFlow } from '@xyflow/svelte';
import '@xyflow/svelte/dist/style.css';
export let flowConfig: FlowConfig;
// Create writables here so it is easier to create test cases
const nodes = writable(flowConfig.flowProps.nodes);
const edges = writable(flowConfig.flowProps.edges);
const props = { ...flowConfig.flowProps, nodes, edges };
</script>
<SvelteFlow {...props} />
Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

+4 -1
View File
@@ -11,7 +11,10 @@ const config = {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
adapter: adapter()
adapter: adapter(),
alias: {
$components: './src/components'
}
}
};