chore(svelte-examples): pull out of lib package (#3363)

* chore(svelte-examples): pull out of lib package

* chore(svelte-examples): cleanup

* chore(examples): add readme files
This commit is contained in:
Moritz Klack
2023-08-31 16:44:27 +02:00
committed by GitHub
parent 3da34c739e
commit dcc38794a6
197 changed files with 2003 additions and 1575 deletions
+12
View File
@@ -0,0 +1,12 @@
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface Platform {}
}
}
export {};
+20
View File
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
html,
body,
#root {
height: 100%;
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}
</style>
%sveltekit.head%
</head>
<body>
<div id="root">%sveltekit.body%</div>
</body>
</html>
@@ -0,0 +1,46 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { page } from '$app/stores';
const routes = [
'customnode',
'drag-n-drop',
'edges',
'figma',
'interaction',
'overview',
'stress',
'subflows',
'usesvelteflow',
'validation'
];
const onChange = (event: Event) => {
const route = (event.target as HTMLSelectElement).value;
goto(route);
};
</script>
<header>
<div class="logo">Svelte Flow</div>
<select on:change={onChange} value={$page.route.id}>
{#each routes as route}
<option value={`/${route}`}>{route}</option>
{/each}
</select>
</header>
<style>
header {
padding: 10px;
border-bottom: 1px solid #eee;
display: flex;
font-weight: 700;
align-items: center;
color: #111;
}
.logo {
margin-right: 1rem;
}
</style>
@@ -0,0 +1 @@
export { default as Header } from './Header.svelte';
@@ -0,0 +1,8 @@
import { redirect } from '@sveltejs/kit';
/** @type {import('./$types').LayoutServerLoad} */
export function load({ route }) {
if (route.id === '/') {
throw redirect(307, '/overview');
}
}
+22
View File
@@ -0,0 +1,22 @@
<script lang="ts">
import { Header } from '../components/Header';
</script>
<div class="app">
<Header />
<div class="flow">
<slot />
</div>
</div>
<style>
.app {
display: flex;
flex-direction: column;
height: 100%;
}
.flow {
flex: 1;
}
</style>
+1
View File
@@ -0,0 +1 @@
<div>this redirects to /overview</div>
@@ -0,0 +1,131 @@
<script lang="ts">
import type { ChangeEventHandler } from 'svelte/elements';
import { writable } from 'svelte/store';
import {
SvelteFlow,
Controls,
Background,
BackgroundVariant,
MiniMap,
Position,
type Node,
type NodeTypes,
type Edge,
type Connection
} from '@xyflow/svelte';
import CustomNode from './CustomNode.svelte';
import '@xyflow/svelte/dist/style.css';
const nodeTypes: NodeTypes = {
colorNode: CustomNode
};
const bgColor = writable('#1A192B');
const onChange: ChangeEventHandler<HTMLInputElement> = (event) => {
nodes.update((nds) =>
nds.map((node) => {
if (node.type !== 'colorNode') {
return node;
}
const color = (event.target as HTMLInputElement)?.value;
bgColor.set(color);
return {
...node,
data: {
...node.data,
color
}
};
})
);
};
const nodes = writable<Node[]>([
{
id: '1',
type: 'input',
data: { label: 'An input node' },
position: { x: 0, y: 50 },
sourcePosition: Position.Right
},
{
id: '2',
type: 'colorNode',
data: { onChange: onChange, color: $bgColor },
style: 'border: 1px solid #777; padding: 10px',
position: { x: 250, y: 50 }
},
{
id: '2a',
type: 'colorNode',
data: { onChange: onChange, color: $bgColor },
style: 'border: 1px solid #777; padding: 10px',
position: { x: 250, y: 520 }
},
{
id: '3',
type: 'output',
data: { label: 'Output A' },
position: { x: 650, y: 25 },
targetPosition: Position.Left
},
{
id: '4',
type: 'output',
data: { label: 'Output B' },
position: { x: 650, y: 120 },
targetPosition: Position.Left
}
]);
const edges = writable<Edge[]>([
{
id: 'e1-2',
source: '1',
target: '2',
animated: true
},
{
id: 'e2a-3',
source: '2',
sourceHandle: 'a',
target: '3',
animated: true
},
{
id: 'e2b-4',
source: '2',
sourceHandle: 'b',
target: '4',
animated: true
}
]);
const onConnect = (connection: Connection) => {
console.log('on connect', connection);
};
</script>
<SvelteFlow
{nodes}
{edges}
{nodeTypes}
style="--bgcolor: {$bgColor}"
fitView
on:connect={onConnect}
>
<Controls />
<Background variant={BackgroundVariant.Dots} />
<MiniMap />
</SvelteFlow>
<style>
:global(.svelte-flow) {
background: var(--bgcolor);
}
</style>
@@ -0,0 +1,21 @@
<script lang="ts">
import { Handle, Position, type NodeProps } from '@xyflow/svelte';
type $$Props = NodeProps;
export let data: { color: string; onChange: () => void } = { color: '#111', onChange: () => {} };
</script>
<Handle type="target" position={Position.Left} on:connect />
<div>
Custom Color Picker Node: <strong>{data.color}</strong>
</div>
<input class="nodrag" type="color" on:input={data.onChange} value={data.color} />
<Handle type="source" position={Position.Right} id="a" style="top: 10px;" on:connect />
<Handle
type="source"
position={Position.Right}
id="b"
style="top: auto; bottom: 10px;"
on:connect
/>
@@ -0,0 +1,9 @@
<script lang="ts">
import { SvelteFlowProvider } from '@xyflow/svelte';
import Flow from './Flow.svelte';
</script>
<SvelteFlowProvider>
<Flow />
</SvelteFlowProvider>
@@ -0,0 +1,106 @@
<script lang="ts">
import { writable } from 'svelte/store';
import {
SvelteFlow,
Controls,
Background,
BackgroundVariant,
MiniMap,
useSvelteFlow,
type Node
} from '@xyflow/svelte';
import Sidebar from './Sidebar.svelte';
import '@xyflow/svelte/dist/style.css';
const nodes = writable([
{
id: '1',
type: 'input',
data: { label: 'Input Node' },
position: { x: 150, y: 5 }
},
{
id: '2',
type: 'default',
data: { label: 'Node' },
position: { x: 0, y: 150 }
},
{
id: '3',
type: 'output',
data: { label: 'Output Node' },
position: { x: 300, y: 150 }
}
]);
const edges = writable([
{
id: '1-2',
type: 'default',
source: '1',
target: '2',
label: 'Edge Text'
},
{
id: '1-3',
type: 'smoothstep',
source: '1',
target: '3'
}
]);
const svelteFlow = useSvelteFlow();
const onDragOver = (event: DragEvent) => {
event.preventDefault();
console.log(event);
if (event.dataTransfer) {
event.dataTransfer.dropEffect = 'move';
}
};
const onDrop = (event: DragEvent) => {
event.preventDefault();
if (!event.dataTransfer) {
return null;
}
const type = event.dataTransfer.getData('application/svelteflow');
const position = svelteFlow.project({
x: event.clientX,
y: event.clientY - 40
});
const newNode: Node = {
id: `${Math.random()}`,
type,
position,
data: { label: `${type} node` }
};
svelteFlow.nodes.update((nds) => nds.concat(newNode));
};
$: {
console.log($nodes);
}
</script>
<main>
<SvelteFlow {nodes} {edges} fitView on:dragover={onDragOver} on:drop={onDrop}>
<Controls />
<Background variant={BackgroundVariant.Dots} />
<MiniMap />
</SvelteFlow>
<Sidebar />
</main>
<style>
main {
height: 100%;
display: flex;
}
</style>
@@ -0,0 +1,61 @@
<script lang="ts">
import { useSvelteFlow } from '@xyflow/svelte';
const onDragStart = (event: DragEvent, nodeType: string) => {
if (!event.dataTransfer) {
return null;
}
event.dataTransfer.setData('application/svelteflow', nodeType);
event.dataTransfer.effectAllowed = 'move';
};
const { zoomIn, zoomOut, fitView, viewport, nodes } = useSvelteFlow();
</script>
<aside>
<div class="label">You can drag these nodes to the pane on the left.</div>
<div
class="input-node node"
on:dragstart={(event) => onDragStart(event, 'input')}
draggable={true}
>
Input Node
</div>
<div
class="default-node node"
on:dragstart={(event) => onDragStart(event, 'default')}
draggable={true}
>
Default Node
</div>
<div
class="output-node node"
on:dragstart={(event) => onDragStart(event, 'output')}
draggable={true}
>
Output Node
</div>
</aside>
<style>
.label {
margin: 0.5rem 0 0.25rem 0;
}
aside {
width: 20vw;
background: #f4f4f4;
padding: 0.4rem 0.8rem;
font-size: 12px;
}
.node {
margin-bottom: 0.5rem;
border: 1px solid #111;
padding: 0.5rem 1rem;
font-weight: 700;
border-radius: 3px;
cursor: grab;
}
</style>
@@ -0,0 +1,152 @@
<script lang="ts">
import { writable } from 'svelte/store';
import {
SvelteFlow,
Controls,
Background,
BackgroundVariant,
MiniMap,
MarkerType
} from '@xyflow/svelte';
import '@xyflow/svelte/dist/style.css';
const nodes = writable([
{
id: '1',
type: 'input',
data: { label: 'Input 1' },
position: { x: 250, y: 0 }
},
{ id: '2', data: { label: 'Node 2' }, position: { x: 150, y: 100 } },
{ id: '2a', data: { label: 'Node 2a' }, position: { x: 0, y: 180 } },
{ id: '2b', data: { label: 'Node 2b' }, position: { x: -40, y: 300 } },
{ id: '3', data: { label: 'Node 3' }, position: { x: 250, y: 200 } },
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 300 } },
{ id: '3a', data: { label: 'Node 3a' }, position: { x: 150, y: 300 } },
{ id: '5', data: { label: 'Node 5' }, position: { x: 250, y: 400 } },
{
id: '6',
type: 'output',
data: { label: 'Output 6' },
position: { x: 50, y: 550 }
},
{
id: '7',
type: 'output',
data: { label: 'Output 7' },
position: { x: 250, y: 550 }
},
{
id: '8',
type: 'output',
data: { label: 'Output 8' },
position: { x: 525, y: 600 }
},
{
id: '9',
type: 'output',
data: { label: 'Output 9' },
position: { x: 675, y: 500 }
}
]);
const edges = writable([
{
id: 'e1-2',
source: '1',
target: '2',
label: 'bezier edge (default)'
},
{
id: 'e2-2a',
source: '2',
target: '2a',
type: 'smoothstep',
label: 'smoothstep edge'
},
{
id: 'e2a-2b',
source: '2a',
target: '2b',
type: 'simplebezier',
label: 'simple bezier edge'
},
{ id: 'e2-3', source: '2', target: '3', type: 'step', label: 'step edge' },
{
id: 'e3-4',
source: '3',
target: '4',
type: 'straight',
label: 'straight edge'
},
{
id: 'e3-3a',
source: '3',
target: '3a',
type: 'straight',
label: 'label only edge',
style: 'stroke: none'
},
{
id: 'e3-5',
source: '4',
target: '5',
animated: true,
label: 'animated styled edge',
style: 'stroke: red'
},
{
id: 'e5-7',
source: '5',
target: '7',
label: 'label with styled bg',
labelStyle: 'background: #FFCC00; color: #fff; opacity: 0.7',
markerEnd: {
type: MarkerType.ArrowClosed
}
},
{
id: 'e5-8',
source: '5',
target: '8',
data: { text: 'custom edge' }
},
{
id: 'e5-9',
source: '5',
target: '9',
data: { text: 'custom edge 2' }
},
{
id: 'e5-6',
source: '5',
target: '6',
label: 'hi',
labelStyle: 'background: red; font-weight: 700; padding: 5px;',
style: 'stroke: #ffcc0',
markerEnd: {
type: MarkerType.Arrow,
color: '#FFCC00',
markerUnits: 'userSpaceOnUse',
width: 20,
height: 20,
strokeWidth: 2
},
markerStart: {
type: MarkerType.ArrowClosed,
color: '#FFCC00',
orient: 'auto-start-reverse',
markerUnits: 'userSpaceOnUse',
width: 20,
height: 20
}
}
]);
</script>
<SvelteFlow {nodes} {edges} fitView>
<Controls />
<Background variant={BackgroundVariant.Dots} />
<MiniMap />
</SvelteFlow>
@@ -0,0 +1,56 @@
<script lang="ts">
import { writable } from 'svelte/store';
import {
SvelteFlow,
Controls,
Background,
BackgroundVariant,
SelectionMode
} from '@xyflow/svelte';
import '@xyflow/svelte/dist/style.css';
const onPaneContextMenu = (e: any) => {
e.preventDefault();
console.log('context menu');
};
const panOnDrag = [1, 2];
const onMoveStart = (e: any) => console.log('move start', e);
const onMove = (e: any) => console.log('move', e);
const onMoveEnd = (e: any) => console.log('move end', e);
const nodes = writable([
{
id: '1',
type: 'input',
data: { label: 'Node 1' },
position: { x: 250, y: 5 },
className: 'light'
},
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 }, className: 'light' },
{ id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 }, className: 'light' },
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 }, className: 'light' }
]);
const edges = writable([
{ id: 'e1-2', source: '1', target: '2', animated: true },
{ id: 'e1-3', source: '1', target: '3' }
]);
</script>
<SvelteFlow
{nodes}
{edges}
fitView
selectionMode={SelectionMode.Partial}
panOnScroll
{panOnDrag}
{onMoveStart}
{onMove}
{onMoveEnd}
>
<Controls />
<Background variant={BackgroundVariant.Dots} />
</SvelteFlow>
@@ -0,0 +1,213 @@
<script lang="ts">
import { writable } from 'svelte/store';
import {
SvelteFlow,
Controls,
Panel,
PanOnScrollMode,
MiniMap,
type OnMoveEnd,
type Node,
type Edge
} from '@xyflow/svelte';
import '@xyflow/svelte/dist/style.css';
const nodes = writable([
{
id: '1',
type: 'input',
data: { label: 'Node 1' },
position: { x: 250, y: 5 }
},
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 } },
{ id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 } },
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 } }
]);
const edges = writable([
{ id: 'e1-2', source: '1', target: '2', animated: true },
{ id: 'e1-3', source: '1', target: '3' }
]);
const onNodeDragStart = (_: MouseEvent, node: Node) => console.log('drag start', node);
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
const onEdgeClick = (_: MouseEvent, edge: Edge) => console.log('click', edge);
const onPaneClick = (event: MouseEvent) => console.log('onPaneClick', event);
const onPaneScroll = (event?: WheelEvent) => console.log('onPaneScroll', event);
const onPaneContextMenu = (event: MouseEvent) => console.log('onPaneContextMenu', event);
const onMoveEnd: OnMoveEnd = (_, viewport) => console.log('onMoveEnd', viewport);
let isSelectable = false;
let isDraggable = false;
let isConnectable = false;
let zoomOnScroll = false;
let zoomOnPinch = false;
let panOnScroll = false;
let panOnScrollMode = PanOnScrollMode.Free;
let zoomOnDoubleClick = false;
let panOnDrag = true;
let captureZoomClick = false;
let captureZoomScroll = false;
let captureElementClick = false;
</script>
<SvelteFlow
{nodes}
{edges}
elementsSelectable={isSelectable}
nodesConnectable={isConnectable}
nodesDraggable={isDraggable}
{zoomOnScroll}
{zoomOnPinch}
{panOnScroll}
{panOnScrollMode}
{zoomOnDoubleClick}
{panOnDrag}
{onMoveEnd}
>
<MiniMap />
<Controls />
<Panel position="top-right">
<div>
<label for="draggable">
nodesDraggable
<input
id="draggable"
type="checkbox"
bind:checked={isDraggable}
class="svelte-flow__draggable"
/>
</label>
</div>
<div>
<label for="connectable">
nodesConnectable
<input
id="connectable"
type="checkbox"
bind:checked={isConnectable}
class="svelte-flow__connectable"
/>
</label>
</div>
<div>
<label for="selectable">
elementsSelectable
<input
id="selectable"
type="checkbox"
bind:checked={isSelectable}
class="svelte-flow__selectable"
/>
</label>
</div>
<div>
<label for="zoomonscroll">
zoomOnScroll
<input
id="zoomonscroll"
type="checkbox"
bind:checked={zoomOnScroll}
class="svelte-flow__zoomonscroll"
/>
</label>
</div>
<div>
<label for="zoomonpinch">
zoomOnPinch
<input
id="zoomonpinch"
type="checkbox"
bind:checked={zoomOnPinch}
class="svelte-flow__zoomonpinch"
/>
</label>
</div>
<div>
<label for="panonscroll">
panOnScroll
<input
id="panonscroll"
type="checkbox"
bind:checked={panOnScroll}
class="svelte-flow__panonscroll"
/>
</label>
</div>
<div>
<label for="panonscrollmode">
panOnScrollMode
<select
id="panonscrollmode"
bind:value={panOnScrollMode}
on:change={(event) => {
panOnScrollMode = PanOnScrollMode.Free;
}}
class="svelte-flow__panonscrollmode"
>
<option value="free">free</option>
<option value="horizontal">horizontal</option>
<option value="vertical">vertical</option>
</select>
</label>
</div>
<div>
<label for="zoomondbl">
zoomOnDoubleClick
<input
id="zoomondbl"
type="checkbox"
bind:checked={zoomOnDoubleClick}
class="svelte-flow__zoomondbl"
/>
</label>
</div>
<div>
<label for="panondrag">
panOnDrag
<input
id="panondrag"
type="checkbox"
bind:checked={panOnDrag}
class="svelte-flow__panondrag"
/>
</label>
</div>
<div>
<label for="capturezoompaneclick">
capture onPaneClick
<input
id="capturezoompaneclick"
type="checkbox"
bind:checked={captureZoomClick}
class="svelte-flow__capturezoompaneclick"
/>
</label>
</div>
<div>
<label for="capturezoompanescroll">
capture onPaneScroll
<input
id="capturezoompanescroll"
type="checkbox"
bind:checked={captureZoomScroll}
class="svelte-flow__capturezoompanescroll"
/>
</label>
</div>
<div>
<label for="captureelementclick">
capture onElementClick
<input
id="captureelementclick"
type="checkbox"
bind:checked={captureElementClick}
class="svelte-flow__captureelementclick"
/>
</label>
</div>
</Panel>
</SvelteFlow>
@@ -0,0 +1,169 @@
<script lang="ts">
import { writable } from 'svelte/store';
import {
SvelteFlow,
Controls,
Background,
BackgroundVariant,
MiniMap,
Panel,
SelectionMode,
type NodeTypes,
type EdgeTypes
} from '@xyflow/svelte';
import CustomNode from './CustomNode.svelte';
import CustomEdge from './CustomEdge.svelte';
import '@xyflow/svelte/dist/style.css';
const nodeTypes: NodeTypes = {
custom: CustomNode
};
const edgeTypes: EdgeTypes = {
custom: CustomEdge
};
const nodes = writable([
{
id: '1',
type: 'input',
data: { label: 'Input Node' },
position: { x: 150, y: 5 }
},
{
id: '2',
type: 'default',
data: { label: 'Node' },
position: { x: 0, y: 150 },
selectable: false
},
{
id: 'A',
type: 'default',
data: { label: 'Styled with class' },
class: 'custom-style',
position: { x: 150, y: 150 }
},
{
id: 'D',
type: 'default',
data: { label: 'Not draggable' },
position: { x: 150, y: 200 },
draggable: false
},
{
id: '3',
type: 'output',
data: { label: 'Output Node' },
position: { x: 300, y: 150 }
},
{
id: 'B',
type: 'default',
data: { label: 'Styled with style' },
style: 'border: 2px solid #ff5050;',
position: { x: 450, y: 150 }
},
{
id: '4',
type: 'custom',
data: { label: 'Custom Node' },
position: { x: 150, y: 300 }
}
]);
const edges = writable([
{
id: '1-2',
type: 'default',
source: '1',
target: '2',
label: 'Edge Text'
},
{
id: '1-3',
type: 'smoothstep',
source: '1',
target: '3',
selectable: false
},
{
id: '2-4',
type: 'custom',
source: '2',
target: '4',
animated: true
}
]);
function updateNode() {
nodes.update((nds) =>
nds.map((n) => {
if (n.id === '1') {
return {
...n,
position: { x: n.position.x + 20, y: n.position.y }
};
}
return n;
})
);
}
$: {
console.log('nodes changed', $nodes);
}
</script>
<SvelteFlow
{nodes}
{edges}
{nodeTypes}
{edgeTypes}
fitView
minZoom={0.1}
maxZoom={2.5}
selectionMode={SelectionMode.Full}
initialViewport={{ x: 100, y: 100, zoom: 2 }}
snapGrid={[25, 25]}
on:nodeclick={(event) => console.log('on node click', event)}
on:nodemouseenter={(event) => console.log('on node enter', event)}
on:nodemouseleave={(event) => console.log('on node leave', event)}
on:edgeclick={(event) => console.log('edge click', event)}
on:connectstart={(event) => console.log('on connect start', event)}
on:connect={(event) => console.log('on connect', event)}
on:connectend={(event) => console.log('on connect end', event)}
on:paneclick={(event) => console.log('on pane click', event)}
on:panecontextmenu={(event) => {
event.preventDefault();
console.log('on pane contextmenu', event);
}}
>
<Controls />
<Background variant={BackgroundVariant.Dots} />
<MiniMap />
<Panel position="top-right">
<button on:click={updateNode}>update node pos</button>
</Panel>
</SvelteFlow>
<style>
:global(.svelte-flow .custom-style) {
background: #ff5050;
color: white;
}
:root {
--background-color: #ffffdd;
--background-pattern-color: #5050ff;
--minimap-background-color: #f5f6f7;
--minimap-mask-color: rgb(255, 255, 240, 0.6);
--controls-button-background-color: #ddd;
--controls-button-background-color-hover: #ccc;
}
</style>
@@ -0,0 +1,59 @@
<script lang="ts">
import {
BaseEdge,
EdgeLabelRenderer,
useSvelteFlow,
type EdgeProps,
getBezierPath
} from '@xyflow/svelte';
type $$Props = EdgeProps;
$: [path, labelX, labelY] = getBezierPath({
sourceX: $$props.sourceX,
sourceY: $$props.sourceY,
targetX: $$props.targetX,
targetY: $$props.targetY,
sourcePosition: $$props.sourcePosition,
targetPosition: $$props.targetPosition
});
const svelteFlow = useSvelteFlow();
function onClick() {
svelteFlow.edges.update((eds) => eds.filter((e) => e.id !== $$props.id));
}
</script>
<BaseEdge {path} {labelX} {labelY} {...$$props} />
<EdgeLabelRenderer>
<button
style:transform={`translate(-50%,-50%) translate(${labelX}px,${labelY}px)`}
class="edge-button"
on:click={onClick}
>
</button>
</EdgeLabelRenderer>
<style>
.edge-button {
border-radius: 50%;
position: absolute;
border: none;
width: 1rem;
height: 1rem;
display: flex;
justify-content: center;
align-items: center;
font-size: 8px;
pointer-events: all;
cursor: pointer;
background-color: #eee;
}
.edge-button:hover {
box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.12);
}
</style>
@@ -0,0 +1,27 @@
<script lang="ts">
import { Handle, Position, type NodeProps } from '@xyflow/svelte';
type $$Props = NodeProps;
export let data: { label: string } = { label: 'Node' };
export let xPos: number = 0;
export let yPos: number = 0;
</script>
<div class="custom">
<div>{data.label}</div>
<div>{~~xPos}, {~~yPos}</div>
<Handle type="target" position={Position.Top} />
<Handle type="source" position={Position.Bottom} style="left: 10%;" id="a" />
<Handle type="source" position={Position.Bottom} id="b" />
<Handle type="source" position={Position.Bottom} style="left: 90%;" id="c" />
</div>
<style>
.custom {
background: #ffcc00;
padding: 10px;
}
</style>
@@ -0,0 +1,57 @@
<script lang="ts">
import { writable } from 'svelte/store';
import {
SvelteFlow,
Controls,
Background,
BackgroundVariant,
MiniMap,
type Node,
type Edge
} from '@xyflow/svelte';
import '@xyflow/svelte/dist/style.css';
const yNodes = 25;
const xNodes = 25;
const nodeItems: Node[] = [];
const edgeItems: Edge[] = [];
let source = null;
for (let y = 0; y < yNodes; y++) {
for (let x = 0; x < xNodes; x++) {
const position = { x: x * 100, y: y * 50 };
const id = `${x}-${y}`;
const data = { label: `Node ${id}` };
const node = {
id,
data,
position,
type: 'default'
};
nodeItems.push(node);
if (source) {
const edge = {
id: `${source.id}-${id}`,
source: source.id,
target: id
};
edgeItems.push(edge);
}
source = node;
}
}
const nodes = writable(nodeItems);
const edges = writable(edgeItems);
</script>
<SvelteFlow {nodes} {edges} fitView minZoom={0.2}>
<Controls />
<Background variant={BackgroundVariant.Dots} />
<MiniMap />
</SvelteFlow>
@@ -0,0 +1,134 @@
<script lang="ts">
import { writable } from 'svelte/store';
import {
SvelteFlow,
Controls,
Background,
BackgroundVariant,
MiniMap,
type NodeTypes,
type Node
} from '@xyflow/svelte';
import '@xyflow/svelte/dist/style.css';
import DebugNode from './DebugNode.svelte';
const nodeTypes: NodeTypes = {
default: DebugNode
};
const nodes = writable<Node[]>([
{
id: '1',
type: 'input',
data: { label: 'Node 1' },
position: { x: 250, y: 5 },
origin: [0.5, 0.5]
},
{
id: '4',
data: { label: 'Node 4' },
position: { x: 100, y: 200 },
style: 'width:500px; height:300px;'
},
{
id: '4a',
data: { label: 'Node 4a' },
position: { x: 15, y: 15 },
parentNode: '4',
extent: [
[0, 0],
[100, 100]
]
},
{
id: '4b',
data: { label: 'Node 4b' },
position: { x: 100, y: 60 },
style: 'width: 300px; height: 200px;',
parentNode: '4'
},
{
id: '4b1',
data: { label: 'Node 4b1' },
position: { x: 40, y: 20 },
parentNode: '4b'
},
{
id: '4b2',
data: { label: 'Node 4b2' },
position: { x: 20, y: 100 },
parentNode: '4b'
},
{
id: '5',
type: 'group',
data: { label: 'Node 5' },
position: { x: 650, y: 250 },
style: 'width: 400px; height: 150px',
zIndex: 1000
},
{
id: '5a',
data: { label: 'Node 5a' },
position: { x: 0, y: 0 },
parentNode: '5',
extent: 'parent'
},
{
id: '5b',
data: { label: 'Node 5b' },
position: { x: 225, y: 50 },
parentNode: '5',
expandParent: true
},
{
id: '2',
data: { label: 'Node 2' },
position: { x: 100, y: 100 }
},
{
id: '3',
data: { label: 'Node 3' },
position: { x: 400, y: 100 }
}
]);
const edges = writable([
{
id: 'e1-2',
source: '1',
target: '2'
// markerEnd: {
// type: MarkerType.Arrow,
// strokeWidth: 2,
// width: 15,
// height: 15,
// color: '#f00',
// },
},
{ id: 'e1-3', source: '1', target: '3' },
{ id: 'e3-4', source: '3', target: '4' },
{ id: 'e3-4b', source: '3', target: '4b', zIndex: 100 },
{ id: 'e4a-4b1', source: '4a', target: '4b1' },
{ id: 'e4a-4b2', source: '4a', target: '4b2', zIndex: 100 },
{ id: 'e4b1-4b2', source: '4b1', target: '4b2' }
]);
$: {
console.log($nodes);
}
</script>
<SvelteFlow {nodes} {edges} {nodeTypes} fitView minZoom={0.1} maxZoom={2.5}>
<Controls />
<Background variant={BackgroundVariant.Dots} />
<MiniMap />
</SvelteFlow>
<style>
:global(.svelte-flow .svelte-flow__node.parent) {
background-color: rgba(220, 220, 255, 0.4);
}
</style>
@@ -0,0 +1,24 @@
<script lang="ts">
import { Handle, Position, type NodeProps } from '@xyflow/svelte';
type $$Props = NodeProps;
export let id: string;
export let xPos: number = 0;
export let yPos: number = 0;
export let zIndex: number = 0;
</script>
<Handle type="target" position={Position.Top} />
<div>{id}</div>
<div>
x:{Math.round(xPos || 0)} y:{Math.round(yPos || 0)} z:{zIndex}
</div>
<Handle type="source" position={Position.Bottom} />
<style>
.custom {
background: #ffcc00;
padding: 10px;
}
</style>
@@ -0,0 +1,9 @@
<script lang="ts">
import { SvelteFlowProvider } from '@xyflow/svelte';
import Flow from './Flow.svelte';
</script>
<SvelteFlowProvider>
<Flow />
</SvelteFlowProvider>
@@ -0,0 +1,61 @@
<script lang="ts">
import { writable } from 'svelte/store';
import { SvelteFlow, Controls, Background, BackgroundVariant, MiniMap } from '@xyflow/svelte';
import Sidebar from './Sidebar.svelte';
import '@xyflow/svelte/dist/style.css';
const nodes = writable([
{
id: '1',
type: 'input',
data: { label: 'Input Node' },
position: { x: 150, y: 5 }
},
{
id: '2',
type: 'default',
data: { label: 'Node' },
position: { x: 0, y: 150 }
},
{
id: '3',
type: 'output',
data: { label: 'Output Node' },
position: { x: 300, y: 150 }
}
]);
const edges = writable([
{
id: '1-2',
type: 'default',
source: '1',
target: '2',
label: 'Edge Text'
},
{
id: '1-3',
type: 'smoothstep',
source: '1',
target: '3'
}
]);
</script>
<main>
<SvelteFlow {nodes} {edges} fitView>
<Controls />
<Background variant={BackgroundVariant.Dots} />
<MiniMap />
</SvelteFlow>
<Sidebar />
</main>
<style>
main {
height: 100%;
display: flex;
}
</style>
@@ -0,0 +1,56 @@
<script lang="ts">
import { useSvelteFlow } from '@xyflow/svelte';
const {
zoomIn,
zoomOut,
setZoom,
fitView,
setCenter,
setViewport,
getViewport,
viewport,
nodes
} = useSvelteFlow();
</script>
<aside>
<div class="label">Functions:</div>
<button on:click={() => zoomIn()}>zoom in</button>
<button on:click={() => zoomOut({ duration: 1000 })}>zoom out transition</button>
<button on:click={() => setZoom(2)}>set zoom</button>
<button on:click={() => fitView()}>fitView</button>
<button on:click={() => setCenter(0, 0)}>setCenter 0, 0</button>
<button on:click={() => setViewport({ x: 100, y: 100, zoom: 2 })}>setViewport</button>
<button on:click={() => console.log(getViewport())}>getViewport</button>
<div class="label">Nodes:</div>
{#each $nodes as node (node.id)}
<div>id: {node.id} | x: {node.position.x.toFixed(1)} y: {node.position.y.toFixed(1)}</div>
{/each}
<div class="label">Viewport:</div>
<div>
x: {$viewport.x.toFixed(1)} y: {$viewport.y.toFixed(1)} zoom: {$viewport.zoom.toFixed(1)}
</div>
</aside>
<style>
.label {
font-weight: 700;
margin: 0.5rem 0 0.25rem 0;
}
aside {
width: 20vw;
background: #f4f4f4;
padding: 0.4rem 0.8rem;
font-size: 12px;
}
button {
display: block;
margin-bottom: 0.5rem;
font-size: 12px;
}
</style>
@@ -0,0 +1,40 @@
<script lang="ts">
import { writable } from 'svelte/store';
import {
SvelteFlow,
Controls,
Background,
BackgroundVariant,
type IsValidConnection,
Position
} from '@xyflow/svelte';
import '@xyflow/svelte/dist/style.css';
import './style.css';
const nodeDefaults = {
sourcePosition: Position.Right,
targetPosition: Position.Left
};
const nodes = writable([
{
id: '0',
position: { x: 0, y: 150 },
data: { label: 'only connectable with B' },
...nodeDefaults
},
{ id: 'A', position: { x: 250, y: 0 }, data: { label: 'A' }, ...nodeDefaults },
{ id: 'B', position: { x: 250, y: 150 }, data: { label: 'B' }, ...nodeDefaults },
{ id: 'C', position: { x: 250, y: 300 }, data: { label: 'C' }, ...nodeDefaults }
]);
const edges = writable([]);
const isValidConnection: IsValidConnection = (connection) => connection.target === 'B';
</script>
<SvelteFlow {nodes} {edges} fitView minZoom={0.1} maxZoom={2.5} {isValidConnection}>
<Controls />
<Background variant={BackgroundVariant.Dots} />
</SvelteFlow>
@@ -0,0 +1,7 @@
.svelte-flow__handle.connecting {
background: #ff6060;
}
.svelte-flow__handle.valid {
background: #55dd99;
}
+8
View File
@@ -0,0 +1,8 @@
/* 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;
}
+8
View File
@@ -0,0 +1,8 @@
/* 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;
}