├── .eslintrc.cjs
├── .gitattributes
├── .gitignore
├── .npmrc
├── .prettierrc
├── .storybook
├── main.cjs
└── preview.js
├── LICENSE
├── README.md
├── package.json
├── src
├── app.d.ts
├── app.html
├── lib
│ ├── components
│ │ ├── attribution
│ │ │ ├── attribution.svelte
│ │ │ └── index.ts
│ │ ├── edges
│ │ │ ├── base-edge.svelte
│ │ │ ├── bezier-edge.svelte
│ │ │ ├── edge-text.svelte
│ │ │ └── index.ts
│ │ ├── handles
│ │ │ ├── handle.svelte
│ │ │ ├── handler.ts
│ │ │ └── index.ts
│ │ └── nodes
│ │ │ ├── default-node.svelte
│ │ │ ├── index.ts
│ │ │ ├── input-node.svelte
│ │ │ ├── node-content.svelte
│ │ │ ├── node-wrapper.svelte
│ │ │ └── output-node.svelte
│ ├── container
│ │ ├── edge-renderer
│ │ │ ├── edge-renderer.svelte
│ │ │ └── index.ts
│ │ ├── flow-renderer
│ │ │ ├── flow-renderer.svelte
│ │ │ └── index.ts
│ │ ├── graph-view
│ │ │ ├── graph-view.svelte
│ │ │ └── index.ts
│ │ ├── node-renderer
│ │ │ ├── index.ts
│ │ │ └── node-renderer.svelte
│ │ └── svelte-flow
│ │ │ ├── index.ts
│ │ │ └── svelte-flow.svelte
│ ├── contexts
│ │ ├── flow-contexts.ts
│ │ └── index.ts
│ ├── index.ts
│ └── types
│ │ ├── edges.ts
│ │ ├── general.ts
│ │ ├── handles.ts
│ │ ├── index.ts
│ │ ├── nodes.ts
│ │ └── utils.ts
├── routes
│ └── index.svelte
└── stories
│ ├── container
│ ├── container.svelte
│ └── index.ts
│ └── examples
│ ├── custom-node
│ ├── color-picker-node.svelte
│ ├── custom-node.stories.ts
│ ├── custom-node.svelte
│ └── data.ts
│ └── overview
│ ├── custom-label.svelte
│ ├── data.ts
│ ├── overview.stories.ts
│ └── overview.svelte
├── static
└── favicon.png
├── svelte.config.js
├── tsconfig.json
└── yarn.lock
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: '@typescript-eslint/parser',
4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier', 'plugin:storybook/recommended'],
5 | plugins: ['svelte3', '@typescript-eslint'],
6 | ignorePatterns: ['*.cjs'],
7 | overrides: [{
8 | files: ['*.svelte'],
9 | processor: 'svelte3/svelte3'
10 | }],
11 | settings: {
12 | 'svelte3/typescript': () => require('typescript')
13 | },
14 | parserOptions: {
15 | sourceType: 'module',
16 | ecmaVersion: 2020
17 | },
18 | env: {
19 | browser: true,
20 | es2017: true,
21 | node: true
22 | }
23 | };
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 | .vscode
10 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "singleQuote": true,
4 | "trailingComma": "all"
5 | }
6 |
--------------------------------------------------------------------------------
/.storybook/main.cjs:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const preprocess = require('svelte-preprocess');
3 |
4 | const replaceFileExtension = (filePath, newExtension) => {
5 | const { name, root, dir } = path.parse(filePath);
6 | return path.format({
7 | name,
8 | root,
9 | dir,
10 | ext: newExtension,
11 | });
12 | };
13 |
14 | const fixCjsGeneratedStories = (config) => {
15 | // Find the plugin instance that needs to be mutated
16 | const virtualModulesPlugin = config.plugins.find(
17 | (plugin) => plugin.constructor.name === 'VirtualModulesPlugin',
18 | );
19 | // Change the file extension to .cjs for all files that end with "generated-stories-entry.js"
20 | virtualModulesPlugin._staticModules = Object.fromEntries(
21 | Object.entries(virtualModulesPlugin._staticModules).map(([key, value]) => {
22 | if (key.endsWith('generated-stories-entry.js')) {
23 | return [replaceFileExtension(key, '.cjs'), value];
24 | }
25 | return [key, value];
26 | }),
27 | );
28 | // Change the entry points to point to the appropriate .cjs files
29 | config.entry = config.entry.map((entry) => {
30 | if (entry.endsWith('generated-stories-entry.js')) {
31 | return replaceFileExtension(entry, '.cjs');
32 | }
33 | return entry;
34 | });
35 | return config;
36 | };
37 |
38 | const babelPluginOptions = {
39 | loose: true,
40 | modules: 'commonjs',
41 | targets: {
42 | esmodules: true,
43 | },
44 | };
45 |
46 | const babelLoaderEsModules = (config) => {
47 | // Configure babel-loader to use esmodules.
48 | config.module.rules.forEach((rule) => {
49 | if (!rule?.test?.source.includes('js')) return;
50 | if (!Array.isArray(rule.use) || rule.use.length <= 0) return;
51 | const use = rule.use[0];
52 | if (!use.loader.includes('babel-loader')) return;
53 | if (!Array.isArray(use.options.plugins)) return;
54 | const { plugins } = use.options;
55 | plugins.forEach((plugin, i) => {
56 | if (Array.isArray(plugin)) {
57 | plugin[1] = { ...plugin[1], ...babelPluginOptions };
58 | } else {
59 | /* ref to plugin */
60 | plugins[i] = [plugin, babelPluginOptions];
61 | }
62 | });
63 | });
64 | return config;
65 | };
66 |
67 | const noFullySpecified = (config) => {
68 | // Remove fully-specified file-extension requirement.
69 | config.module.rules = [
70 | ...config.module.rules,
71 | {
72 | test: /\.m?js/,
73 | resolve: {
74 | fullySpecified: false,
75 | },
76 | },
77 | ];
78 | return config;
79 | };
80 |
81 | const sveltekitAlias = (config) => {
82 | // Set SvelteKit aliases.
83 | config.resolve.alias = {
84 | ...config.resolve.alias,
85 | svelte: `${__dirname}/../node_modules/svelte`,
86 | $lib: `${__dirname}/../src/lib`,
87 | };
88 | return config;
89 | };
90 |
91 | module.exports = {
92 | stories: [
93 | '../src/**/*.stories.mdx',
94 | '../src/**/*.stories.@(js|jsx|ts|tsx|svelte)',
95 | ],
96 | addons: [
97 | '@storybook/addon-links',
98 | '@storybook/addon-essentials',
99 | '@storybook/addon-svelte-csf',
100 | 'storybook-dark-mode',
101 | ],
102 | framework: '@storybook/svelte',
103 | core: {
104 | builder: 'webpack5',
105 | },
106 | svelteOptions: {
107 | preprocess: preprocess({
108 | typescript: {
109 | compilerOptions: {
110 | target: 'es2018',
111 | },
112 | },
113 | babel: {
114 | plugins: [
115 | '@babel/plugin-proposal-optional-chaining',
116 | '@babel/plugin-proposal-nullish-coalescing-operator',
117 | ],
118 | },
119 | }),
120 | },
121 | webpackFinal: async (config) => {
122 | config = fixCjsGeneratedStories(config);
123 | config = babelLoaderEsModules(config);
124 | config = noFullySpecified(config);
125 | config = sveltekitAlias(config);
126 | return config;
127 | },
128 | };
129 |
--------------------------------------------------------------------------------
/.storybook/preview.js:
--------------------------------------------------------------------------------
1 | export const parameters = {
2 | actions: { argTypesRegex: "^on[A-Z].*" },
3 | controls: {
4 | matchers: {
5 | color: /(background|color)$/i,
6 | date: /Date$/,
7 | },
8 | },
9 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Lucas Fernandes
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > [!IMPORTANT]
2 | > This project is deprecated in favor of [Svelte Flow](https://svelteflow.dev/), an official implementation of xyflow (formerly React Flow) — the now framework-agnostic library that inspired this project.
3 |
4 | # Svelte Flow
5 |
6 | Cool node graphs and diagrams, inspired by [React Flow](https://github.com/wbkd/react-flow).
7 |
8 |
9 |
10 |
11 |
12 | 🚨 **This is in the earliest development stage possible!** I'm still sorting out everything yet.
13 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svelte-flow",
3 | "version": "0.0.1",
4 | "scripts": {
5 | "dev": "svelte-kit dev",
6 | "build": "svelte-kit build",
7 | "package": "svelte-kit package",
8 | "preview": "svelte-kit preview",
9 | "prepare": "svelte-kit sync",
10 | "check": "svelte-check --tsconfig ./tsconfig.json",
11 | "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
12 | "lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
13 | "format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. .",
14 | "storybook": "start-storybook -p 6006",
15 | "build-storybook": "build-storybook"
16 | },
17 | "devDependencies": {
18 | "@babel/core": "^7.17.9",
19 | "@storybook/addon-actions": "^6.5.0-alpha.61",
20 | "@storybook/addon-essentials": "^6.5.0-alpha.61",
21 | "@storybook/addon-links": "^6.5.0-alpha.61",
22 | "@storybook/builder-webpack5": "^6.5.0-alpha.61",
23 | "@storybook/manager-webpack5": "^6.5.0-alpha.61",
24 | "@storybook/svelte": "^6.5.0-alpha.61",
25 | "@sveltejs/adapter-auto": "next",
26 | "@sveltejs/kit": "next",
27 | "@types/d3-selection": "^3.0.3",
28 | "@types/d3-zoom": "^3.0.1",
29 | "@typescript-eslint/eslint-plugin": "^5.10.1",
30 | "@typescript-eslint/parser": "^5.10.1",
31 | "babel-loader": "^8.2.4",
32 | "eslint": "^7.32.0",
33 | "eslint-config-prettier": "^8.3.0",
34 | "eslint-plugin-storybook": "^0.5.8",
35 | "eslint-plugin-svelte3": "^3.2.1",
36 | "prettier": "^2.5.1",
37 | "prettier-plugin-svelte": "^2.5.0",
38 | "sass": "^1.50.0",
39 | "svelte": "^3.46.6",
40 | "svelte-check": "^2.2.6",
41 | "svelte-loader": "^3.1.2",
42 | "svelte-preprocess": "^4.10.1",
43 | "tslib": "^2.3.1",
44 | "typescript": "~4.6.2",
45 | "webpack": "5"
46 | },
47 | "type": "module",
48 | "dependencies": {
49 | "d3-selection": "^3.0.0",
50 | "d3-zoom": "^3.0.0",
51 | "interactjs": "^1.10.11"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/app.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | // See https://kit.svelte.dev/docs/types#the-app-namespace
4 | // for information about these interfaces
5 | declare namespace App {
6 | // interface Locals {}
7 | // interface Platform {}
8 | // interface Session {}
9 | // interface Stuff {}
10 | }
11 |
--------------------------------------------------------------------------------
/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | %svelte.head%
9 |
10 |
11 | %svelte.body%
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/lib/components/attribution/attribution.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 | {#if !hide}
6 | Svelte Flow
7 | {/if}
8 |
9 |
20 |
--------------------------------------------------------------------------------
/src/lib/components/attribution/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Attribution } from './attribution.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/components/edges/base-edge.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 | {#if label}
15 |
23 | {/if}
24 |
25 |
30 |
--------------------------------------------------------------------------------
/src/lib/components/edges/bezier-edge.svelte:
--------------------------------------------------------------------------------
1 |
170 |
171 |
180 |
--------------------------------------------------------------------------------
/src/lib/components/edges/edge-text.svelte:
--------------------------------------------------------------------------------
1 |
18 |
19 |
23 | {#if labelShowBg}
24 |
32 | {/if}
33 |
34 |
40 | {label}
41 |
42 |
43 |
44 |
45 |
49 |
--------------------------------------------------------------------------------
/src/lib/components/edges/index.ts:
--------------------------------------------------------------------------------
1 | export { default as BaseEdge } from './base-edge.svelte';
2 | export { default as BezierEdge } from './bezier-edge.svelte';
3 | export { default as EdgeText } from './edge-text.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/handles/handle.svelte:
--------------------------------------------------------------------------------
1 |
114 |
115 |
131 |
132 |
161 |
--------------------------------------------------------------------------------
/src/lib/components/handles/handler.ts:
--------------------------------------------------------------------------------
1 | import interact from 'interactjs';
2 | import { get } from 'svelte/store';
3 | import { getFlowContexts } from '$lib/contexts';
4 |
5 | export const getDraggableHandle = (
6 | target: HTMLElement,
7 | start: () => void,
8 | move: (event: Event) => void,
9 | end: () => void,
10 | ) => {
11 | return interact(target, {
12 | styleCursor: false,
13 | }).draggable({
14 | autoScroll: true,
15 | listeners: {
16 | start,
17 | move,
18 | end,
19 | },
20 | });
21 | };
22 |
23 | export const getDropzoneHandle = (
24 | target: HTMLElement,
25 | nodeId: string,
26 | handleId: string,
27 | createEdge: (
28 | source: string,
29 | sourceHandle: string,
30 | target: string,
31 | targetHandle: string,
32 | ) => void,
33 | ) => {
34 | const accept = '.svelte-flow-handle-draggable';
35 | let isDraggedIn = false;
36 |
37 | return interact(target, {
38 | styleCursor: false,
39 | }).dropzone({
40 | accept,
41 | overlap: 0.25,
42 | ondragenter: () => (isDraggedIn = true),
43 | ondragleave: () => (isDraggedIn = false),
44 | ondropdeactivate: (event) => {
45 | if (isDraggedIn) {
46 | const sourceNodeId = event.relatedTarget?.dataset?.nodeid;
47 | const sourceHandleId = event.relatedTarget?.dataset?.handleid;
48 | createEdge(sourceNodeId, sourceHandleId, nodeId, handleId);
49 | }
50 | },
51 | });
52 | };
53 |
--------------------------------------------------------------------------------
/src/lib/components/handles/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Handle } from './handle.svelte';
2 | export * from './handler';
3 |
--------------------------------------------------------------------------------
/src/lib/components/nodes/default-node.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/lib/components/nodes/index.ts:
--------------------------------------------------------------------------------
1 | export { default as DefaultNode } from './default-node.svelte';
2 | export { default as InputNode } from './input-node.svelte';
3 | export { default as NodeContent } from './node-content.svelte';
4 | export { default as NodeWrapper } from './node-wrapper.svelte';
5 | export { default as OutputNode } from './output-node.svelte';
6 |
--------------------------------------------------------------------------------
/src/lib/components/nodes/input-node.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/lib/components/nodes/node-content.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 | {#if typeof label === 'string'}
11 | {label}
12 | {:else if label != null}
13 |
14 | {/if}
15 |
16 |
17 |
18 |
19 |
27 |
--------------------------------------------------------------------------------
/src/lib/components/nodes/node-wrapper.svelte:
--------------------------------------------------------------------------------
1 |
29 |
30 |
35 |
36 |
37 |
38 |
45 |
--------------------------------------------------------------------------------
/src/lib/components/nodes/output-node.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/lib/container/edge-renderer/edge-renderer.svelte:
--------------------------------------------------------------------------------
1 |
39 |
40 |
55 |
56 |
61 |
--------------------------------------------------------------------------------
/src/lib/container/edge-renderer/index.ts:
--------------------------------------------------------------------------------
1 | export { default as EdgeRenderer } from './edge-renderer.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/container/flow-renderer/flow-renderer.svelte:
--------------------------------------------------------------------------------
1 |
34 |
35 |
44 |
45 |
62 |
--------------------------------------------------------------------------------
/src/lib/container/flow-renderer/index.ts:
--------------------------------------------------------------------------------
1 | export { default as FlowRenderer } from './flow-renderer.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/container/graph-view/graph-view.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 | {#if isMounted}
14 |
15 | {/if}
16 |
17 |
--------------------------------------------------------------------------------
/src/lib/container/graph-view/index.ts:
--------------------------------------------------------------------------------
1 | export { default as GraphView } from './graph-view.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/container/node-renderer/index.ts:
--------------------------------------------------------------------------------
1 | export { default as NodeRenderer } from './node-renderer.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/container/node-renderer/node-renderer.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 | {#each $nodes as node}
9 |
15 |
21 |
22 | {/each}
23 |
--------------------------------------------------------------------------------
/src/lib/container/svelte-flow/index.ts:
--------------------------------------------------------------------------------
1 | export { default as SvelteFlow } from './svelte-flow.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/container/svelte-flow/svelte-flow.svelte:
--------------------------------------------------------------------------------
1 |
31 |
32 |
36 |
37 |
44 |
--------------------------------------------------------------------------------
/src/lib/contexts/flow-contexts.ts:
--------------------------------------------------------------------------------
1 | import { writable } from 'svelte/store';
2 | import { getContext, setContext } from 'svelte';
3 | import type { Writable } from 'svelte/store';
4 | import type { ComponentsList, Edge, Node } from '$lib/types';
5 |
6 | const nodesKey = Symbol('nodes');
7 | const edgesKey = Symbol('edges');
8 | const nodeTypesKey = Symbol('nodeTypes');
9 | const edgeTypesKey = Symbol('edgeTypes');
10 |
11 | export const setFlowContexts = (
12 | nodes: Node[],
13 | edges: Edge[],
14 | nodeTypes: ComponentsList,
15 | edgeTypes: ComponentsList,
16 | ) => {
17 | setContext(nodesKey, writable(nodes));
18 | setContext(edgesKey, writable(edges));
19 | setContext(nodeTypesKey, writable(nodeTypes));
20 | setContext(edgeTypesKey, writable(edgeTypes));
21 | };
22 |
23 | export const getFlowContexts = () => ({
24 | nodes: getContext(nodesKey) as Writable,
25 | edges: getContext(edgesKey) as Writable,
26 | nodeTypes: getContext(nodeTypesKey) as Writable,
27 | edgeTypes: getContext(edgeTypesKey) as Writable,
28 | });
29 |
--------------------------------------------------------------------------------
/src/lib/contexts/index.ts:
--------------------------------------------------------------------------------
1 | export * from './flow-contexts';
2 |
--------------------------------------------------------------------------------
/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | export { SvelteFlow } from './container/svelte-flow';
2 |
--------------------------------------------------------------------------------
/src/lib/types/edges.ts:
--------------------------------------------------------------------------------
1 | import type { Position } from './utils';
2 |
3 | export type Edge = {
4 | id: string;
5 | type?: string;
6 | source: string;
7 | sourceHandle?: string;
8 | target: string;
9 | targetHandle?: string;
10 | label?: string;
11 | zIndex?: number;
12 |
13 | // only used internally
14 | draft?: boolean;
15 | position?: EdgePosition;
16 | };
17 |
18 | export type EdgePosition = {
19 | sourcePos?: Position;
20 | sourceX: number;
21 | sourceY: number;
22 | targetPos?: Position;
23 | targetX: number;
24 | targetY: number;
25 | };
26 |
--------------------------------------------------------------------------------
/src/lib/types/general.ts:
--------------------------------------------------------------------------------
1 | export type Connection = {
2 | source?: string;
3 | target?: string;
4 | sourceHandle?: string;
5 | targetHandle?: string;
6 | };
7 |
8 | export type OnConnect = (connection: Connection) => void;
9 |
--------------------------------------------------------------------------------
/src/lib/types/handles.ts:
--------------------------------------------------------------------------------
1 | import type { Position } from './utils';
2 |
3 | export type HandleType = 'source' | 'target';
4 |
5 | export type HandleElement = {
6 | id: string;
7 | type: HandleType;
8 | position: Position;
9 | element: HTMLElement;
10 | };
11 |
--------------------------------------------------------------------------------
/src/lib/types/index.ts:
--------------------------------------------------------------------------------
1 | export * from './edges';
2 | export * from './general';
3 | export * from './handles';
4 | export * from './nodes';
5 | export * from './utils';
6 |
--------------------------------------------------------------------------------
/src/lib/types/nodes.ts:
--------------------------------------------------------------------------------
1 | import type { SvelteComponent } from 'svelte';
2 | import type { Position, XYPosition } from './utils';
3 | import type { HandleElement } from './handles';
4 |
5 | export type NodeData = {
6 | label: string | typeof SvelteComponent;
7 | [key: string]: any;
8 | };
9 |
10 | export type Node = {
11 | id: string;
12 | position: XYPosition;
13 | type?: string;
14 | targetPosition?: Position;
15 | sourcePosition?: Position;
16 | data?: NodeData;
17 | className?: string;
18 | // width?: number;
19 | // height?: number;
20 |
21 | // only used internally
22 | element?: HTMLElement;
23 | handles?: HandleElement[];
24 | // positionAbsolute?: XYPosition;
25 | };
26 |
--------------------------------------------------------------------------------
/src/lib/types/utils.ts:
--------------------------------------------------------------------------------
1 | import type { SvelteComponent } from 'svelte';
2 |
3 | export type Position = 'top' | 'right' | 'bottom' | 'left';
4 |
5 | export type XYPosition = {
6 | x: number;
7 | y: number;
8 | };
9 |
10 | export type ComponentsList = {
11 | [key: string]: typeof SvelteComponent;
12 | };
13 |
--------------------------------------------------------------------------------
/src/routes/index.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/stories/container/container.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
--------------------------------------------------------------------------------
/src/stories/container/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Container } from './container.svelte';
2 |
--------------------------------------------------------------------------------
/src/stories/examples/custom-node/color-picker-node.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 | Color: {value}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
31 |
--------------------------------------------------------------------------------
/src/stories/examples/custom-node/custom-node.stories.ts:
--------------------------------------------------------------------------------
1 | import ExampleCustomNode from './custom-node.svelte';
2 |
3 | export default {
4 | title: 'Examples',
5 | component: ExampleCustomNode,
6 | };
7 |
8 | const Template = () => ({
9 | Component: ExampleCustomNode,
10 | });
11 |
12 | export const CustomNode = Template.bind({});
13 |
--------------------------------------------------------------------------------
/src/stories/examples/custom-node/custom-node.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/stories/examples/custom-node/data.ts:
--------------------------------------------------------------------------------
1 | import type { Edge, Node } from '$lib/types';
2 |
3 | export const nodes: Node[] = [
4 | {
5 | id: '1',
6 | type: 'input',
7 | data: { label: 'An input node' },
8 | position: { x: -250, y: 0 },
9 | sourcePosition: 'right',
10 | },
11 | {
12 | id: '2',
13 | type: 'colorPickerNode',
14 | position: { x: 0, y: 0 },
15 | },
16 | {
17 | id: '3',
18 | type: 'output',
19 | data: { label: 'Output A' },
20 | position: { x: 250, y: -50 },
21 | targetPosition: 'left',
22 | },
23 | {
24 | id: '4',
25 | type: 'output',
26 | data: { label: 'Output B' },
27 | position: { x: 250, y: 50 },
28 | targetPosition: 'left',
29 | },
30 | ];
31 |
32 | export const edges: Edge[] = [
33 | {
34 | id: 'e1-2',
35 | source: '1',
36 | target: '2',
37 | },
38 | {
39 | id: 'e2a-3',
40 | source: '2',
41 | target: '3',
42 | sourceHandle: 'a',
43 | },
44 | {
45 | id: 'e2b-4',
46 | source: '2',
47 | target: '4',
48 | sourceHandle: 'b',
49 | },
50 | ];
51 |
--------------------------------------------------------------------------------
/src/stories/examples/overview/custom-label.svelte:
--------------------------------------------------------------------------------
1 | This is a default node
2 |
--------------------------------------------------------------------------------
/src/stories/examples/overview/data.ts:
--------------------------------------------------------------------------------
1 | import CustomLabel from './custom-label.svelte';
2 | import type { Edge, Node } from '$lib/types';
3 |
4 | export const nodes: Node[] = [
5 | {
6 | id: '1',
7 | type: 'input',
8 | data: {
9 | label: 'Welcome to Svelte Flow!',
10 | },
11 | position: { x: 0, y: -175 },
12 | },
13 | {
14 | id: '2',
15 | data: {
16 | label: CustomLabel,
17 | },
18 | position: { x: -150, y: -50 },
19 | },
20 | {
21 | id: '3',
22 | data: {
23 | label: 'This one has a custom style',
24 | },
25 | position: { x: 150, y: -50 },
26 | className: 'my-custom-style',
27 | },
28 | {
29 | id: '4',
30 | position: { x: 0, y: 75 },
31 | data: {
32 | label: 'Another default node',
33 | },
34 | },
35 | {
36 | id: '5',
37 | data: {
38 | label: 'Node id: 5',
39 | },
40 | position: { x: 0, y: 175 },
41 | },
42 | ];
43 |
44 | export const edges: Edge[] = [
45 | { id: 'e1-2', source: '1', target: '2', label: 'this is an edge label' },
46 | { id: 'e1-3', source: '1', target: '3' },
47 | {
48 | id: 'e3-4',
49 | source: '3',
50 | target: '4',
51 | label: 'animated edge',
52 | },
53 | {
54 | id: 'e4-5',
55 | source: '4',
56 | target: '5',
57 | label: 'edge with arrow head',
58 | },
59 | ];
60 |
--------------------------------------------------------------------------------
/src/stories/examples/overview/overview.stories.ts:
--------------------------------------------------------------------------------
1 | import ExampleOverview from './overview.svelte';
2 |
3 | export default {
4 | title: 'Examples',
5 | component: ExampleOverview,
6 | };
7 |
8 | const Template = () => ({
9 | Component: ExampleOverview,
10 | });
11 |
12 | export const Overview = Template.bind({});
13 |
--------------------------------------------------------------------------------
/src/stories/examples/overview/overview.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doceazedo/svelte-flow/29537b5dad56af18108bee6aa90a3a52d183890e/static/favicon.png
--------------------------------------------------------------------------------
/svelte.config.js:
--------------------------------------------------------------------------------
1 | import adapter from '@sveltejs/adapter-auto';
2 | import preprocess from 'svelte-preprocess';
3 |
4 | /** @type {import('@sveltejs/kit').Config} */
5 | const config = {
6 | // Consult https://github.com/sveltejs/svelte-preprocess
7 | // for more information about preprocessors
8 | preprocess: preprocess(),
9 |
10 | kit: {
11 | adapter: adapter()
12 | }
13 | };
14 |
15 | export default config;
16 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.svelte-kit/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------