feat: Create examples directory and add some examples
* Add svg plugins for vite & rollup update: more bundle stuff
This commit is contained in:
20
examples/App.tsx
Normal file
20
examples/App.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import Header from './Header';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'App',
|
||||
components: {
|
||||
Header
|
||||
},
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const key = computed(() => route.fullPath);
|
||||
return () => (
|
||||
<>
|
||||
<Header />
|
||||
<router-view ref="view" key={key.value} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
});
|
||||
97
examples/Basic/index.tsx
Normal file
97
examples/Basic/index.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
import RevueFlow, {
|
||||
MiniMap,
|
||||
Controls,
|
||||
Background,
|
||||
Connection,
|
||||
Edge,
|
||||
Elements,
|
||||
FlowElement,
|
||||
Node,
|
||||
OnLoadParams,
|
||||
addEdge,
|
||||
isNode,
|
||||
removeElements
|
||||
} from '../../src';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||
const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
|
||||
|
||||
const initialElements: Elements = [
|
||||
{ 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 } },
|
||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
||||
{ id: 'e1-3', source: '1', target: '3' }
|
||||
];
|
||||
|
||||
const BasicFlow = defineComponent({
|
||||
components: { RevueFlow, MiniMap, Controls, Background },
|
||||
setup() {
|
||||
const elements = ref<Elements>(initialElements);
|
||||
const rfInstance = ref<OnLoadParams | null>(null);
|
||||
const onElementsRemove = (elementsToRemove: Elements) => (elements.value = removeElements(elementsToRemove, elements.value));
|
||||
const onConnect = (params: Edge | Connection) => (elements.value = addEdge(params, elements.value));
|
||||
const onLoad = (revueFlowInstance: OnLoadParams) => (rfInstance.value = revueFlowInstance);
|
||||
|
||||
const updatePos = () => {
|
||||
elements.value = elements.value.map((el) => {
|
||||
if (isNode(el)) {
|
||||
el.position = {
|
||||
x: Math.random() * 400,
|
||||
y: Math.random() * 400
|
||||
};
|
||||
}
|
||||
|
||||
return el;
|
||||
});
|
||||
};
|
||||
|
||||
const logToObject = () => console.log(rfInstance.value?.toObject());
|
||||
const resetTransform = () => rfInstance.value?.setTransform({ x: 0, y: 0, zoom: 1 });
|
||||
|
||||
const toggleClassnames = () => {
|
||||
elements.value = elements.value.map((el) => {
|
||||
if (isNode(el)) {
|
||||
el.className = el.className === 'light' ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
return el;
|
||||
});
|
||||
};
|
||||
|
||||
return () => (
|
||||
<RevueFlow
|
||||
elements={elements.value}
|
||||
onLoad={onLoad}
|
||||
onElementClick={onElementClick}
|
||||
onElementsRemove={onElementsRemove}
|
||||
onConnect={onConnect}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
class="revue-flow-basic-example"
|
||||
defaultZoom={1.5}
|
||||
minZoom={0.2}
|
||||
maxZoom={4}
|
||||
>
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
<Background color="#aaa" gap={16} />
|
||||
<div style={{ position: 'absolute', right: '10px', top: '10px', zIndex: 4 }}>
|
||||
<button onClick={resetTransform} style={{ marginRight: '5px' }}>
|
||||
reset transform
|
||||
</button>
|
||||
<button onClick={updatePos} style={{ marginRight: '5px' }}>
|
||||
change pos
|
||||
</button>
|
||||
<button onClick={toggleClassnames} style={{ marginRight: '5px' }}>
|
||||
toggle classnames
|
||||
</button>
|
||||
<button onClick={logToObject}>toObject</button>
|
||||
</div>
|
||||
</RevueFlow>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default BasicFlow;
|
||||
39
examples/CustomConnectionLine/ConnectionLine.tsx
Normal file
39
examples/CustomConnectionLine/ConnectionLine.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
import { ConnectionLineComponentProps } from '../../src';
|
||||
|
||||
const ConnectionLine = defineComponent({
|
||||
props: {
|
||||
sourceX: {
|
||||
type: Number as PropType<ConnectionLineComponentProps['sourceX']>,
|
||||
required: true
|
||||
},
|
||||
sourceY: {
|
||||
type: Number as PropType<ConnectionLineComponentProps['sourceY']>,
|
||||
required: true
|
||||
},
|
||||
targetX: {
|
||||
type: Number as PropType<ConnectionLineComponentProps['targetX']>,
|
||||
required: true
|
||||
},
|
||||
targetY: {
|
||||
type: Number as PropType<ConnectionLineComponentProps['targetY']>,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
return () => (
|
||||
<g>
|
||||
<path
|
||||
fill="none"
|
||||
stroke="#222"
|
||||
stroke-width={1.5}
|
||||
class="animated"
|
||||
d={`M${props.sourceX},${props.sourceY} C ${props.sourceX} ${props.targetY} ${props.sourceX} ${props.targetY} ${props.targetX},${props.targetY}`}
|
||||
/>
|
||||
<circle cx={props.targetX} cy={props.targetY} fill="#fff" r={3} stroke="#222" stroke-width={1.5} />
|
||||
</g>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default ConnectionLine;
|
||||
28
examples/CustomConnectionLine/index.tsx
Normal file
28
examples/CustomConnectionLine/index.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import RevueFlow, { removeElements, addEdge, Background, BackgroundVariant, Elements, Connection, Edge } from '../../src';
|
||||
|
||||
import ConnectionLine from './ConnectionLine';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
|
||||
const initialElements: Elements = [{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } }];
|
||||
|
||||
const ConnectionLineFlow = defineComponent({
|
||||
components: { Background },
|
||||
setup() {
|
||||
const elements = ref(initialElements);
|
||||
const onElementsRemove = (elementsToRemove: Elements) => (elements.value = removeElements(elementsToRemove, elements.value));
|
||||
const onConnect = (params: Connection | Edge) => (elements.value = addEdge(params, elements.value));
|
||||
|
||||
return () => (
|
||||
<RevueFlow
|
||||
elements={elements.value}
|
||||
connectionLineComponent={ConnectionLine as any}
|
||||
onElementsRemove={onElementsRemove}
|
||||
onConnect={onConnect}
|
||||
>
|
||||
<Background variant={BackgroundVariant.Lines} />
|
||||
</RevueFlow>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default ConnectionLineFlow;
|
||||
33
examples/CustomNode/ColorSelectorNode.tsx
Normal file
33
examples/CustomNode/ColorSelectorNode.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import { CSSProperties, defineComponent } from 'vue';
|
||||
import { Handle, Position, Connection, Edge } from '../../src';
|
||||
|
||||
const targetHandleStyle: CSSProperties = { background: '#555' };
|
||||
const sourceHandleStyleA: CSSProperties = { ...targetHandleStyle, top: 10 };
|
||||
const sourceHandleStyleB: CSSProperties = { ...targetHandleStyle, bottom: 10, top: 'auto' };
|
||||
|
||||
const onConnect = (params: Connection | Edge) => console.log('handle onConnect', params);
|
||||
|
||||
const ColorSelectorNode = defineComponent({
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
return () => (
|
||||
<>
|
||||
<Handle type="target" position={Position.Left} style={targetHandleStyle} onConnect={onConnect} />
|
||||
<div>
|
||||
Custom Color Picker Node: <strong>{props.data.color}</strong>
|
||||
</div>
|
||||
<input class="nodrag" type="color" onInput={props.data.onChange} v-model={props.data.color} />
|
||||
<Handle type="source" position={Position.Right} id="a" style={sourceHandleStyleA} />
|
||||
<Handle type="source" position={Position.Right} id="b" style={sourceHandleStyleB} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default ColorSelectorNode;
|
||||
133
examples/CustomNode/index.tsx
Normal file
133
examples/CustomNode/index.tsx
Normal file
@@ -0,0 +1,133 @@
|
||||
import { defineComponent, onMounted, ref } from 'vue';
|
||||
import RevueFlow, {
|
||||
isEdge,
|
||||
removeElements,
|
||||
addEdge,
|
||||
MiniMap,
|
||||
Controls,
|
||||
Node,
|
||||
FlowElement,
|
||||
OnLoadParams,
|
||||
Elements,
|
||||
Position,
|
||||
SnapGrid,
|
||||
Connection,
|
||||
Edge
|
||||
} from '../../src';
|
||||
import ColorSelectorNode from './ColorSelectorNode';
|
||||
|
||||
const onLoad = (reactFlowInstance: OnLoadParams) => console.log('flow loaded:', reactFlowInstance);
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||
const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
|
||||
|
||||
const initBgColor = '#1A192B';
|
||||
|
||||
const connectionLineStyle = { stroke: '#fff' };
|
||||
const snapGrid: SnapGrid = [16, 16];
|
||||
const nodeTypes = {
|
||||
selectorNode: ColorSelectorNode
|
||||
};
|
||||
|
||||
const CustomNodeFlow = defineComponent({
|
||||
components: { RevueFlow, MiniMap, Controls },
|
||||
setup() {
|
||||
const elements = ref<Elements>([]);
|
||||
const bgColor = ref(initBgColor);
|
||||
|
||||
onMounted(() => {
|
||||
const onChange = (event: Event) => {
|
||||
elements.value = elements.value.map((e) => {
|
||||
if (isEdge(e) || e.id !== '2') {
|
||||
return e;
|
||||
}
|
||||
|
||||
const color = (event.target as HTMLInputElement).value;
|
||||
|
||||
bgColor.value = color;
|
||||
|
||||
return {
|
||||
...e,
|
||||
data: {
|
||||
...e.data,
|
||||
color
|
||||
}
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
elements.value = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'input',
|
||||
data: { label: 'An input node' },
|
||||
position: { x: 0, y: 50 },
|
||||
sourcePosition: Position.Right
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
type: 'selectorNode',
|
||||
data: { onChange: onChange, color: initBgColor },
|
||||
style: { border: '1px solid #777', padding: 10 },
|
||||
position: { x: 250, y: 50 }
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
type: 'output',
|
||||
data: { label: 'Output A' },
|
||||
position: { x: 550, y: 25 },
|
||||
targetPosition: Position.Left
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
type: 'output',
|
||||
data: { label: 'Output B' },
|
||||
position: { x: 550, y: 100 },
|
||||
targetPosition: Position.Left
|
||||
},
|
||||
|
||||
{ id: 'e1-2', source: '1', target: '2', animated: true, style: { stroke: '#fff' } },
|
||||
{ id: 'e2a-3', source: '2', sourceHandle: 'a', target: '3', animated: true, style: { stroke: '#fff' } },
|
||||
{ id: 'e2b-4', source: '2', sourceHandle: 'b', target: '4', animated: true, style: { stroke: '#fff' } }
|
||||
];
|
||||
});
|
||||
|
||||
const onElementsRemove = (elementsToRemove: Elements) => (elements.value = removeElements(elementsToRemove, elements.value));
|
||||
const onConnect = (params: Connection | Edge) =>
|
||||
(elements.value = addEdge({ ...params, animated: true, style: { stroke: '#fff' } }, elements.value));
|
||||
|
||||
return () => (
|
||||
<RevueFlow
|
||||
elements={elements.value}
|
||||
onElementClick={onElementClick}
|
||||
onElementsRemove={onElementsRemove}
|
||||
onConnect={onConnect}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
style={{ background: bgColor.value }}
|
||||
onLoad={onLoad}
|
||||
nodeTypes={nodeTypes}
|
||||
connectionLineStyle={connectionLineStyle}
|
||||
snapToGrid={true}
|
||||
snapGrid={snapGrid}
|
||||
defaultZoom={1.5}
|
||||
>
|
||||
<MiniMap
|
||||
nodeStrokeColor={(n: Node): string => {
|
||||
if (n.type === 'input') return '#0041d0';
|
||||
if (n.type === 'selectorNode') return bgColor.value;
|
||||
if (n.type === 'output') return '#ff0072';
|
||||
|
||||
return '#eee';
|
||||
}}
|
||||
nodeColor={(n: Node): string => {
|
||||
if (n.type === 'selectorNode') return bgColor.value;
|
||||
|
||||
return '#fff';
|
||||
}}
|
||||
/>
|
||||
<Controls />
|
||||
</RevueFlow>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default CustomNodeFlow;
|
||||
30
examples/Header.tsx
Normal file
30
examples/Header.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { routes } from './router';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
const Header = defineComponent({
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const onChange = async (event: any) => {
|
||||
await router.push(event.target.value);
|
||||
};
|
||||
|
||||
return () => (
|
||||
<header>
|
||||
<a class="logo" href="https://github.com/wbkd/react-flow">
|
||||
Revue Flow Dev
|
||||
</a>
|
||||
<select v-model={route.path} onChange={onChange}>
|
||||
{routes.map((route) => (
|
||||
<option value={route.path} key={route.path}>
|
||||
{route.path === '/' ? 'overview' : route.path.substr(1, route.path.length)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default Header;
|
||||
91
examples/index.css
Normal file
91
examples/index.css
Normal file
@@ -0,0 +1,91 @@
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
#root {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#root {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#root {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
header {
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #eee;
|
||||
display: flex;
|
||||
font-weight: 700;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
header a,
|
||||
header a:focus,
|
||||
header a:active,
|
||||
header a:visited {
|
||||
color: #111;
|
||||
}
|
||||
|
||||
header a:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
header select {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.overview-example__add {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.revue-flow__node a {
|
||||
font-weight: 700;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.revue-flow__node.dark-node {
|
||||
background: #0041d0;
|
||||
color: #f8f8f8;
|
||||
}
|
||||
|
||||
.revue-flow__node.dark {
|
||||
background: #557;
|
||||
color: #f8f8f8;
|
||||
}
|
||||
|
||||
.revue-flow__node-selectorNode {
|
||||
font-size: 12px;
|
||||
background: #f0f2f3;
|
||||
border: 1px solid #555;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.revue-flow__node-selectorNode .revue-flow__handle {
|
||||
border-color: #f0f2f3;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.overview-example__add {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
9
examples/main.ts
Normal file
9
examples/main.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { createApp } from 'vue';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import { router } from './router';
|
||||
const app = createApp(App);
|
||||
|
||||
app.config.performance = true;
|
||||
app.use(router);
|
||||
app.mount('#root');
|
||||
21
examples/router.ts
Normal file
21
examples/router.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { createRouter, createWebHashHistory } from 'vue-router';
|
||||
|
||||
export const routes = [
|
||||
{
|
||||
path: '/basic',
|
||||
component: () => import('./Basic')
|
||||
},
|
||||
{
|
||||
path: '/custom-connectionline',
|
||||
component: () => import('./CustomConnectionLine')
|
||||
},
|
||||
{
|
||||
path: '/custom-node',
|
||||
component: () => import('./CustomNode')
|
||||
}
|
||||
];
|
||||
|
||||
export const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes
|
||||
});
|
||||
Reference in New Issue
Block a user