docs: update examples
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { Background, Controls, MiniMap } from '@vue-flow/additional-components'
|
||||
import { Background, Controls, MiniMap, Panel, PanelPosition } from '@vue-flow/additional-components'
|
||||
import { VueFlow, isNode, useVueFlow } from '@vue-flow/core'
|
||||
import { ref } from 'vue'
|
||||
import { initialElements } from './initial-elements.js'
|
||||
@@ -58,28 +58,62 @@ const logToObject = () => console.log(toObject())
|
||||
*/
|
||||
const resetTransform = () => setTransform({ x: 0, y: 0, zoom: 1 })
|
||||
|
||||
const toggleClass = () => {
|
||||
dark.value = !dark.value
|
||||
elements.value.forEach((el) => (el.class = dark.value ? 'dark' : 'light'))
|
||||
}
|
||||
const toggleClass = () => (dark.value = !dark.value)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VueFlow v-model="elements" class="basicflow" :default-zoom="1.5" :min-zoom="0.2" :max-zoom="4">
|
||||
<Background pattern-color="#aaa" gap="8" />
|
||||
<VueFlow v-model="elements" :class="{ dark }" class="basicflow" :default-zoom="1.5" :min-zoom="0.2" :max-zoom="4">
|
||||
<Background :pattern-color="dark ? '#FFFFFB' : '#aaa'" gap="8" />
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
|
||||
<div class="controls">
|
||||
<button style="background-color: #113285; color: white" @click="resetTransform">reset transform</button>
|
||||
<button style="background-color: #6f3381; color: white" @click="updatePos">update positions</button>
|
||||
<Panel :position="PanelPosition.TopRight" class="controls">
|
||||
<button style="background-color: #113285; color: white" title="Reset Transform" @click="resetTransform">
|
||||
<svg width="16" height="16" viewBox="0 0 32 32">
|
||||
<path fill="#FFFFFB" d="M18 28A12 12 0 1 0 6 16v6.2l-3.6-3.6L1 20l6 6l6-6l-1.4-1.4L8 22.2V16a10 10 0 1 1 10 10Z" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button style="background-color: #6f3381" title="Shuffle Node Positions" @click="updatePos">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="#FFFFFB"
|
||||
d="M14 20v-2h2.6l-3.2-3.2l1.425-1.425L18 16.55V14h2v6Zm-8.6 0L4 18.6L16.6 6H14V4h6v6h-2V7.4Zm3.775-9.425L4 5.4L5.4 4l5.175 5.175Z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button
|
||||
:style="{ backgroundColor: dark ? '#FFFFFB' : '#1C1C1C', color: dark ? '#1C1C1C' : '#FFFFFB' }"
|
||||
:style="{ backgroundColor: dark ? '#FFFFFB' : '#292524', color: dark ? '#292524' : '#FFFFFB' }"
|
||||
@click="toggleClass"
|
||||
>
|
||||
toggle {{ dark ? 'light' : 'dark' }}
|
||||
<template v-if="dark">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="#292524"
|
||||
d="M12 17q-2.075 0-3.537-1.463Q7 14.075 7 12t1.463-3.538Q9.925 7 12 7t3.538 1.462Q17 9.925 17 12q0 2.075-1.462 3.537Q14.075 17 12 17ZM2 13q-.425 0-.712-.288Q1 12.425 1 12t.288-.713Q1.575 11 2 11h2q.425 0 .713.287Q5 11.575 5 12t-.287.712Q4.425 13 4 13Zm18 0q-.425 0-.712-.288Q19 12.425 19 12t.288-.713Q19.575 11 20 11h2q.425 0 .712.287q.288.288.288.713t-.288.712Q22.425 13 22 13Zm-8-8q-.425 0-.712-.288Q11 4.425 11 4V2q0-.425.288-.713Q11.575 1 12 1t.713.287Q13 1.575 13 2v2q0 .425-.287.712Q12.425 5 12 5Zm0 18q-.425 0-.712-.288Q11 22.425 11 22v-2q0-.425.288-.712Q11.575 19 12 19t.713.288Q13 19.575 13 20v2q0 .425-.287.712Q12.425 23 12 23ZM5.65 7.05L4.575 6q-.3-.275-.288-.7q.013-.425.288-.725q.3-.3.725-.3t.7.3L7.05 5.65q.275.3.275.7q0 .4-.275.7q-.275.3-.687.287q-.413-.012-.713-.287ZM18 19.425l-1.05-1.075q-.275-.3-.275-.712q0-.413.275-.688q.275-.3.688-.287q.412.012.712.287L19.425 18q.3.275.288.7q-.013.425-.288.725q-.3.3-.725.3t-.7-.3ZM16.95 7.05q-.3-.275-.287-.688q.012-.412.287-.712L18 4.575q.275-.3.7-.288q.425.013.725.288q.3.3.3.725t-.3.7L18.35 7.05q-.3.275-.7.275q-.4 0-.7-.275ZM4.575 19.425q-.3-.3-.3-.725t.3-.7l1.075-1.05q.3-.275.713-.275q.412 0 .687.275q.3.275.288.688q-.013.412-.288.712L6 19.425q-.275.3-.7.287q-.425-.012-.725-.287Z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="#FFFFFB"
|
||||
d="M12 21q-3.75 0-6.375-2.625T3 12q0-3.75 2.625-6.375T12 3q.35 0 .688.025q.337.025.662.075q-1.025.725-1.637 1.887Q11.1 6.15 11.1 7.5q0 2.25 1.575 3.825Q14.25 12.9 16.5 12.9q1.375 0 2.525-.613q1.15-.612 1.875-1.637q.05.325.075.662Q21 11.65 21 12q0 3.75-2.625 6.375T12 21Z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
</button>
|
||||
<button @click="logToObject">log toObject</button>
|
||||
</div>
|
||||
|
||||
<button title="Log `toObject`" @click="logToObject">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="#292524"
|
||||
d="M20 19V7H4v12h16m0-16a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16m-7 14v-2h5v2h-5m-3.42-4L5.57 9H8.4l3.3 3.3c.39.39.39 1.03 0 1.42L8.42 17H5.59l3.99-4Z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</Panel>
|
||||
</VueFlow>
|
||||
</template>
|
||||
|
||||
@@ -5,13 +5,13 @@ import { MarkerType } from '@vue-flow/core'
|
||||
* or split them up into nodes and edges and pass them to the `nodes` and `edges` props of Vue Flow (or useVueFlow composable)
|
||||
*/
|
||||
export const initialElements = [
|
||||
{ id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 }, class: 'light' },
|
||||
{ id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 0 }, class: 'light' },
|
||||
{ id: '2', type: 'output', label: 'Node 2', position: { x: 100, y: 100 }, class: 'light' },
|
||||
{ id: '3', label: 'Node 3', position: { x: 400, y: 100 }, class: 'light' },
|
||||
{ id: '4', label: 'Node 4', position: { x: 150, y: 200 }, class: 'light' },
|
||||
{ id: '5', type: 'output', label: 'Node 5', position: { x: 300, y: 300 }, class: 'light' },
|
||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
||||
{ id: 'e1-3', label: 'edge with arrowhead', source: '1', target: '3', markerEnd: MarkerType.Arrow },
|
||||
{ id: 'e1-3', label: 'edge with arrowhead', source: '1', target: '3', markerEnd: MarkerType.ArrowClosed },
|
||||
{
|
||||
id: 'e4-5',
|
||||
type: 'step',
|
||||
@@ -19,7 +19,6 @@ export const initialElements = [
|
||||
source: '4',
|
||||
target: '5',
|
||||
style: { stroke: 'orange' },
|
||||
labelStyle: { stroke: 'black' },
|
||||
labelBgStyle: { fill: 'orange' },
|
||||
},
|
||||
{ id: 'e3-4', type: 'smoothstep', label: 'smoothstep-edge', source: '3', target: '4' },
|
||||
|
||||
@@ -1,13 +1,28 @@
|
||||
.basicflow .vue-flow__node.dark {
|
||||
background: #1C1C1C;
|
||||
.basicflow.dark {
|
||||
background: #57534e;
|
||||
color: #FFFFFB;
|
||||
}
|
||||
|
||||
.basicflow.dark .vue-flow__node {
|
||||
background: #292524;
|
||||
color: #FFFFFB;
|
||||
}
|
||||
|
||||
.basicflow.dark .vue-flow__controls .vue-flow__controls-button {
|
||||
background: #292524;
|
||||
fill: #FFFFFB;
|
||||
border-color: #FFFFFB;
|
||||
}
|
||||
|
||||
.basicflow.dark .vue-flow__edge-textbg {
|
||||
fill: #292524;
|
||||
}
|
||||
|
||||
.basicflow.dark .vue-flow__edge-text {
|
||||
fill: #FFFFFB;
|
||||
}
|
||||
|
||||
.basicflow .controls {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
z-index: 4;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
@@ -15,16 +30,18 @@
|
||||
}
|
||||
|
||||
.basicflow .controls button {
|
||||
padding: 5px;
|
||||
padding: 4px;
|
||||
border-radius: 5px;
|
||||
font-weight: 500;
|
||||
font-weight: 600;
|
||||
-webkit-box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.basicflow .controls button:hover {
|
||||
opacity: 0.8;
|
||||
transform: scale(105%);
|
||||
transform: scale(102%);
|
||||
transition: 250ms all ease;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script setup>
|
||||
import { Background, BackgroundVariant, Controls, MiniMap } from '@vue-flow/additional-components'
|
||||
import { VueFlow } from '@vue-flow/core'
|
||||
import { ref } from 'vue'
|
||||
import CustomConnectionLine from './CustomConnectionLine.vue'
|
||||
@@ -16,10 +15,8 @@ const elements = ref([
|
||||
|
||||
<template>
|
||||
<VueFlow v-model="elements">
|
||||
<template #connection-line="props">
|
||||
<CustomConnectionLine v-bind="props" />
|
||||
<template #connection-line="{ sourceX, sourceY, targetX, targetY }">
|
||||
<CustomConnectionLine :source-x="sourceX" :source-y="sourceY" :target-x="targetX" :target-y="targetY" />
|
||||
</template>
|
||||
|
||||
<Background :variant="BackgroundVariant.Lines" />
|
||||
</VueFlow>
|
||||
</template>
|
||||
|
||||
@@ -22,12 +22,13 @@ const props = defineProps({
|
||||
<template>
|
||||
<g>
|
||||
<path
|
||||
class="animated"
|
||||
class="vue-flow__connection animated"
|
||||
fill="none"
|
||||
stroke="#6F3381"
|
||||
:stroke-width="2.5"
|
||||
:d="`M${sourceX},${sourceY} C ${sourceX} ${targetY} ${sourceX} ${targetY} ${targetX},${targetY}`"
|
||||
/>
|
||||
<circle :cx="targetX" :cy="targetY" fill="#fff" :r="5" stroke="#6F3381" :stroke-width="1.5" />
|
||||
|
||||
<circle :cx="targetX" :cy="targetY" fill="#fff" :r="4" stroke="#6F3381" :stroke-width="1.5" />
|
||||
</g>
|
||||
</template>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<script setup>
|
||||
import { MiniMap } from '@vue-flow/additional-components'
|
||||
import { ConnectionMode, Position, VueFlow, useVueFlow } from '@vue-flow/core'
|
||||
import { computed, h, onMounted, ref } from 'vue'
|
||||
import { Position, VueFlow, useVueFlow } from '@vue-flow/core'
|
||||
import { h, onMounted, ref } from 'vue'
|
||||
import ColorSelectorNode from './CustomNode.vue'
|
||||
import { presets } from './presets.js'
|
||||
|
||||
const { getNode } = useVueFlow()
|
||||
|
||||
const outputColorNode = computed(() => getNode.value('3'))
|
||||
const { findNode } = useVueFlow()
|
||||
|
||||
const elements = ref([])
|
||||
|
||||
const gradient = ref(false)
|
||||
|
||||
const bgColor = ref(presets.ayame)
|
||||
|
||||
const bgName = ref('AYAME')
|
||||
|
||||
const connectionLineStyle = { stroke: '#fff' }
|
||||
@@ -39,7 +39,7 @@ const onChange = (color) => {
|
||||
bgColor.value = color.value
|
||||
bgName.value = color.name
|
||||
|
||||
outputColorNode.value.hidden = false
|
||||
findNode('3').hidden = false
|
||||
}
|
||||
|
||||
const onGradient = () => {
|
||||
@@ -47,7 +47,7 @@ const onGradient = () => {
|
||||
bgColor.value = null
|
||||
bgName.value = 'gradient'
|
||||
|
||||
outputColorNode.value.hidden = true
|
||||
findNode('3').hidden = true
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@@ -104,13 +104,12 @@ onMounted(() => {
|
||||
class="customnodeflow"
|
||||
:class="[gradient ? 'animated-bg-gradient' : '']"
|
||||
:style="{ backgroundColor: bgColor }"
|
||||
:connection-mode="ConnectionMode.Loose"
|
||||
:connection-line-style="connectionLineStyle"
|
||||
:default-zoom="1.5"
|
||||
:fit-view-on-init="true"
|
||||
fit-view-on-init
|
||||
>
|
||||
<template #node-custom="props">
|
||||
<ColorSelectorNode :data="props.data" @change="onChange" @gradient="onGradient" />
|
||||
<template #node-custom="{ data }">
|
||||
<ColorSelectorNode :data="data" @change="onChange" @gradient="onGradient" />
|
||||
</template>
|
||||
|
||||
<MiniMap :node-stroke-color="nodeStroke" :node-color="nodeColor" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
import { Handle, Position } from '@vue-flow/core'
|
||||
import { computed } from 'vue'
|
||||
import { presets } from './presets.js'
|
||||
import { colors } from './presets.js'
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
@@ -12,8 +12,6 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['change', 'gradient'])
|
||||
|
||||
const onConnect = (params) => console.log('handle onConnect', params)
|
||||
|
||||
const onSelect = (color) => {
|
||||
emit('change', color)
|
||||
}
|
||||
@@ -22,20 +20,8 @@ const onGradient = () => {
|
||||
emit('gradient')
|
||||
}
|
||||
|
||||
const colors = computed(() => {
|
||||
return Object.keys(presets).map((color) => {
|
||||
return {
|
||||
name: color,
|
||||
value: presets[color],
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const selectedColor = computed(() => {
|
||||
return colors.value.find((color) => color.value === props.data.color)
|
||||
})
|
||||
|
||||
const sourceHandleStyleA = computed(() => ({ backgroundColor: props.data.color, filter: 'invert(100%)', top: '10px' }))
|
||||
|
||||
const sourceHandleStyleB = computed(() => ({
|
||||
backgroundColor: props.data.color,
|
||||
filter: 'invert(100%)',
|
||||
@@ -46,14 +32,18 @@ const sourceHandleStyleB = computed(() => ({
|
||||
|
||||
<template>
|
||||
<div>Select a color</div>
|
||||
|
||||
<div
|
||||
style="display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center; max-width: 90%; margin: auto; gap: 3px"
|
||||
>
|
||||
<template v-for="color of colors" :key="color.name">
|
||||
<button :title="color.name" :style="{ backgroundColor: color.value }" type="button" @click="onSelect(color)"></button>
|
||||
</template>
|
||||
|
||||
<button class="animated-bg-gradient" title="gradient" type="button" @click="onGradient"></button>
|
||||
</div>
|
||||
|
||||
<Handle id="a" type="source" :position="Position.Right" :style="sourceHandleStyleA" />
|
||||
|
||||
<Handle id="b" type="source" :position="Position.Right" :style="sourceHandleStyleB" />
|
||||
</template>
|
||||
|
||||
@@ -21,3 +21,10 @@ export const presets = {
|
||||
sakura: '#FEDFE1',
|
||||
toki: '#EEA9A9',
|
||||
}
|
||||
|
||||
export const colors = Object.keys(presets).map((color) => {
|
||||
return {
|
||||
name: color,
|
||||
value: presets[color],
|
||||
}
|
||||
})
|
||||
|
||||
@@ -15,8 +15,10 @@ const { onConnect, nodes, edges, addEdges, addNodes, viewport, project } = useVu
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const onDragOver = (event) => {
|
||||
event.preventDefault()
|
||||
|
||||
if (event.dataTransfer) {
|
||||
event.dataTransfer.dropEffect = 'move'
|
||||
}
|
||||
@@ -26,13 +28,16 @@ onConnect((params) => addEdges([params]))
|
||||
|
||||
const onDrop = (event) => {
|
||||
const type = event.dataTransfer?.getData('application/vueflow')
|
||||
|
||||
const position = project({ x: event.clientX - 40, y: event.clientY - 18 })
|
||||
|
||||
const newNode = {
|
||||
id: getId(),
|
||||
type,
|
||||
position,
|
||||
label: `${type} node`,
|
||||
}
|
||||
|
||||
addNodes([newNode])
|
||||
}
|
||||
</script>
|
||||
@@ -40,6 +45,7 @@ const onDrop = (event) => {
|
||||
<template>
|
||||
<div class="dndflow" @drop="onDrop">
|
||||
<VueFlow @dragover="onDragOver" />
|
||||
|
||||
<Sidebar />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -10,9 +10,12 @@ const onDragStart = (event, nodeType) => {
|
||||
<template>
|
||||
<aside>
|
||||
<div class="description">You can drag these nodes to the pane.</div>
|
||||
|
||||
<div class="nodes">
|
||||
<div class="vue-flow__node-input" :draggable="true" @dragstart="onDragStart($event, 'input')">Input Node</div>
|
||||
|
||||
<div class="vue-flow__node-default" :draggable="true" @dragstart="onDragStart($event, 'default')">Default Node</div>
|
||||
|
||||
<div class="vue-flow__node-output" :draggable="true" @dragstart="onDragStart($event, 'output')">Output Node</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { Background, Controls, MiniMap } from '@vue-flow/additional-components'
|
||||
import { Background } from '@vue-flow/additional-components'
|
||||
import { MarkerType, VueFlow } from '@vue-flow/core'
|
||||
import { h, ref } from 'vue'
|
||||
import CustomEdge from './CustomEdge.vue'
|
||||
@@ -65,11 +65,11 @@ const elements = ref([
|
||||
<template #edge-custom="props">
|
||||
<CustomEdge v-bind="props" />
|
||||
</template>
|
||||
|
||||
<template #edge-custom2="props">
|
||||
<CustomEdge2 v-bind="props" />
|
||||
</template>
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
|
||||
<Background />
|
||||
</VueFlow>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { EdgeLabelRenderer, getBezierPath, useVueFlow } from '@vue-flow/core'
|
||||
import { BaseEdge, EdgeLabelRenderer, getBezierPath, useVueFlow } from '@vue-flow/core'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -57,7 +57,8 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<path :id="id" :style="style" class="vue-flow__edge-path" :d="path[0]" :marker-end="markerEnd" />
|
||||
<!-- You can use the `BaseEdge` component to create your own custom edge more easily -->
|
||||
<BaseEdge :id="id" :style="style" :path="path[0]" :marker-end="markerEnd" />
|
||||
|
||||
<!-- Use the `EdgeLabelRenderer` to escape the SVG world of edges and render your own custom label in a `<div>` ctx -->
|
||||
<EdgeLabelRenderer>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { EdgeText, getBezierPath } from '@vue-flow/core'
|
||||
import { BaseEdge, getBezierPath } from '@vue-flow/core'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -63,12 +63,14 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<path :id="id" class="vue-flow__edge-path" :d="path[0]" :marker-end="markerEnd" />
|
||||
|
||||
<EdgeText
|
||||
:x="path[1]"
|
||||
:y="path[2]"
|
||||
<BaseEdge
|
||||
:id="id"
|
||||
:style="style"
|
||||
:path="path[0]"
|
||||
:marker-end="markerEnd"
|
||||
:label="data.text"
|
||||
:label-x="path[1]"
|
||||
:label-y="path[2]"
|
||||
:label-style="{ fill: 'white' }"
|
||||
:label-show-bg="true"
|
||||
:label-bg-style="{ fill: 'red' }"
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
<script setup>
|
||||
import { Background, BackgroundVariant, Controls, MiniMap } from '@vue-flow/additional-components'
|
||||
import { Background, BackgroundVariant, MiniMap, Panel, PanelPosition } from '@vue-flow/additional-components'
|
||||
import { VueFlow, useVueFlow } from '@vue-flow/core'
|
||||
|
||||
const { nodes, addNodes, edges, addEdges, onConnect, onPaneReady, onNodeDragStop, dimensions } = useVueFlow()
|
||||
|
||||
onConnect((params) => addEdges([params]))
|
||||
onPaneReady((flowInstance) => console.log('flow loaded:', flowInstance))
|
||||
onNodeDragStop((node) => console.log('drag stop', node))
|
||||
|
||||
const addRandomNode = () => {
|
||||
const nodeId = (nodes.value.length + 1).toString()
|
||||
|
||||
const newNode = {
|
||||
id: nodeId,
|
||||
label: `Node: ${nodeId}`,
|
||||
position: { x: Math.random() * dimensions.value.width, y: Math.random() * dimensions.value.height },
|
||||
}
|
||||
|
||||
addNodes([newNode])
|
||||
}
|
||||
</script>
|
||||
@@ -22,11 +22,11 @@ const addRandomNode = () => {
|
||||
<template>
|
||||
<VueFlow>
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
|
||||
<Background :variant="BackgroundVariant.Lines" />
|
||||
|
||||
<button type="button" :style="{ position: 'absolute', left: '10px', top: '10px', zIndex: 4 }" @click="addRandomNode">
|
||||
add node
|
||||
</button>
|
||||
<Panel :position="PanelPosition.TopRight">
|
||||
<button type="button" @click="addRandomNode">add node</button>
|
||||
</Panel>
|
||||
</VueFlow>
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
import { Controls, MiniMap } from '@vue-flow/additional-components'
|
||||
import { Background, Panel, PanelPosition } from '@vue-flow/additional-components'
|
||||
import { VueFlow, useVueFlow } from '@vue-flow/core'
|
||||
import { ref, watchEffect } from 'vue'
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
const isHidden = ref(false)
|
||||
|
||||
@@ -19,24 +19,23 @@ const { nodes, edges } = useVueFlow({
|
||||
],
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
watch(isHidden, () => {
|
||||
nodes.value.forEach((n) => (n.hidden = isHidden.value))
|
||||
edges.value.forEach((e) => (e.hidden = isHidden.value))
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VueFlow>
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
<VueFlow fit-view-on-init>
|
||||
<Background />
|
||||
|
||||
<div :style="{ position: 'absolute', left: '10px', top: '10px', zIndex: 4 }">
|
||||
<Panel :position="PanelPosition.TopRight">
|
||||
<div>
|
||||
<label for="ishidden">
|
||||
hidden
|
||||
<input id="ishidden" v-model="isHidden" type="checkbox" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
</VueFlow>
|
||||
</template>
|
||||
|
||||
@@ -19,10 +19,12 @@ onConnect((params) => addEdges([params]))
|
||||
:default-zoom="1.5"
|
||||
:min-zoom="0.2"
|
||||
:max-zoom="4"
|
||||
:fit-view-on-init="true"
|
||||
fit-view-on-init
|
||||
>
|
||||
<Background pattern-color="#aaa" gap="8" />
|
||||
|
||||
<MiniMap />
|
||||
|
||||
<Controls />
|
||||
</VueFlow>
|
||||
</template>
|
||||
|
||||
@@ -96,7 +96,7 @@ export const exampleImports = {
|
||||
'App.vue': TeleportApp,
|
||||
'Sidebar.vue': TeleportSidebar,
|
||||
'TeleportableNode.vue': TeleportableNode,
|
||||
'useTransition.js': TeleportableUseTransition,
|
||||
'useTeleport.js': TeleportableUseTransition,
|
||||
'style.css': TeleportCSS,
|
||||
},
|
||||
transition: {
|
||||
|
||||
@@ -14,7 +14,7 @@ const elements = ref([
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VueFlow v-model="elements" class="interactionflow" :fit-view-on-init="true">
|
||||
<VueFlow v-model="elements" class="interactionflow" fit-view-on-init>
|
||||
<InteractionControls />
|
||||
</VueFlow>
|
||||
</template>
|
||||
|
||||
@@ -23,14 +23,21 @@ const {
|
||||
} = useVueFlow()
|
||||
|
||||
const captureZoomClick = ref(false)
|
||||
|
||||
const captureZoomScroll = ref(false)
|
||||
|
||||
onConnect((params) => addEdges([params]))
|
||||
|
||||
onNodeDragStart((e) => console.log('drag start', e))
|
||||
|
||||
onNodeDragStop((e) => console.log('drag stop', e))
|
||||
|
||||
onPaneClick((event) => captureZoomClick.value && console.log('pane click', event))
|
||||
|
||||
onPaneScroll((event) => captureZoomScroll.value && console.log('pane scroll', event))
|
||||
|
||||
onPaneContextMenu((event) => captureZoomClick.value && console.log('pane ctx menu', event))
|
||||
|
||||
onMoveEnd((flowTransform) => console.log('move end', flowTransform))
|
||||
</script>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
font-size: 11px;
|
||||
background-color: lightgray;
|
||||
border-bottom-right-radius: 10px;
|
||||
padding: 12px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.interactionflow .controls .label {
|
||||
|
||||
@@ -5,6 +5,7 @@ import Flow from './Flow.vue'
|
||||
<template>
|
||||
<div class="multiflows">
|
||||
<Flow />
|
||||
|
||||
<Flow />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { Background, Panel, PanelPosition } from '@vue-flow/additional-components'
|
||||
import { VueFlow, isNode } from '@vue-flow/core'
|
||||
import { Background } from '@vue-flow/additional-components'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const elements = ref([
|
||||
@@ -26,12 +26,12 @@ const updatePos = () =>
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VueFlow v-model="elements" :fit-view-on-init="true">
|
||||
<VueFlow v-model="elements" fit-view-on-init>
|
||||
<Background />
|
||||
|
||||
<div style="position: absolute; right: 10px; top: 10px; z-index: 4">
|
||||
<Panel :position="PanelPosition.TopRight">
|
||||
<button style="margin-right: 5px" @click="updatePos">update positions</button>
|
||||
<button style="margin-right: 5px" @click="toggleClass">toggle class</button>
|
||||
</div>
|
||||
<button @click="toggleClass">toggle class</button>
|
||||
</Panel>
|
||||
</VueFlow>
|
||||
</template>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<script setup>
|
||||
import { Background, Controls, MiniMap } from '@vue-flow/additional-components'
|
||||
import { ConnectionMode, VueFlow, useVueFlow } from '@vue-flow/core'
|
||||
import { VueFlow, useVueFlow } from '@vue-flow/core'
|
||||
import { onMounted } from 'vue'
|
||||
|
||||
const { onConnect, nodes, edges, addEdges, addNodes } = useVueFlow({
|
||||
fitViewOnInit: true,
|
||||
connectionMode: ConnectionMode.Loose,
|
||||
// set this to true so edges get elevated when selected, defaults to false
|
||||
elevateEdgesOnSelect: true,
|
||||
nodes: [
|
||||
@@ -88,7 +87,9 @@ onMounted(() => {
|
||||
<template>
|
||||
<VueFlow>
|
||||
<MiniMap />
|
||||
|
||||
<Controls />
|
||||
|
||||
<Background />
|
||||
</VueFlow>
|
||||
</template>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script lang="ts" setup>
|
||||
import { VueFlow } from '@vue-flow/core'
|
||||
import { ref } from 'vue'
|
||||
import Controls from './Controls.vue'
|
||||
import SaveRestoreControls from './Controls.vue'
|
||||
|
||||
const elements = ref([{ id: '1', label: 'Node 1', position: { x: 100, y: 100 } }])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VueFlow v-model="elements">
|
||||
<Controls />
|
||||
<SaveRestoreControls />
|
||||
</VueFlow>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup>
|
||||
import { Panel, PanelPosition } from '@vue-flow/additional-components'
|
||||
import { useVueFlow } from '@vue-flow/core'
|
||||
|
||||
const flowKey = 'example-flow'
|
||||
@@ -22,19 +23,21 @@ const onRestore = () => {
|
||||
|
||||
const onAdd = () => {
|
||||
const id = nodes.value.length + 1
|
||||
|
||||
const newNode = {
|
||||
id: `random_node-${id}`,
|
||||
label: `Node ${id}`,
|
||||
position: { x: Math.random() * dimensions.value.width, y: Math.random() * dimensions.value.height },
|
||||
}
|
||||
|
||||
addNodes([newNode])
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="save__controls">
|
||||
<Panel :position="PanelPosition.TopRight" class="save-restore-controls">
|
||||
<button style="background-color: #33a6b8" @click="onSave">save</button>
|
||||
<button style="background-color: #113285" @click="onRestore">restore</button>
|
||||
<button style="background-color: #6f3381" @click="onAdd">add node</button>
|
||||
</div>
|
||||
</Panel>
|
||||
</template>
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
.save__controls {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
z-index: 4;
|
||||
.save-restore-controls {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.save__controls button {
|
||||
.save-restore-controls button {
|
||||
margin-left: 5px;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
@@ -18,8 +14,7 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.save__controls button:hover {
|
||||
opacity: 0.8;
|
||||
.save-restore-controls button:hover {
|
||||
transform: scale(105%);
|
||||
transition: 250ms all ease-in-out;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup>
|
||||
import { Background, MiniMap, Panel, PanelPosition } from '@vue-flow/additional-components'
|
||||
import { VueFlow, isNode, useVueFlow } from '@vue-flow/core'
|
||||
import { nextTick, ref } from 'vue'
|
||||
import { getElements } from './utils.js'
|
||||
@@ -12,6 +13,7 @@ onPaneReady((i) => {
|
||||
i.fitView({
|
||||
padding: 0.2,
|
||||
})
|
||||
|
||||
console.log(i.getElements.value)
|
||||
})
|
||||
|
||||
@@ -26,6 +28,7 @@ const updatePos = () => {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
nextTick(() => {
|
||||
fitView({ duration: 1000, padding: 0.5 })
|
||||
})
|
||||
@@ -34,9 +37,13 @@ const updatePos = () => {
|
||||
|
||||
<template>
|
||||
<VueFlow v-model="elements" :min-zoom="0.1">
|
||||
<div style="position: absolute; right: 10px; top: 10px; z-index: 4">
|
||||
<MiniMap />
|
||||
|
||||
<Background />
|
||||
|
||||
<Panel :position="PanelPosition.TopRight">
|
||||
<button style="margin-right: 5px" @click="updatePos">update positions</button>
|
||||
<button style="margin-right: 5px" @click="toggleClass">toggle class</button>
|
||||
</div>
|
||||
<button @click="toggleClass">toggle class</button>
|
||||
</Panel>
|
||||
</VueFlow>
|
||||
</template>
|
||||
|
||||
@@ -36,11 +36,12 @@ const elements = ref([
|
||||
|
||||
<template>
|
||||
<div class="teleportflow">
|
||||
<VueFlow v-model="elements" :fit-view-on-init="true">
|
||||
<template #node-teleportable="props">
|
||||
<TeleportableNode v-bind="props" />
|
||||
<VueFlow v-model="elements" fit-view-on-init>
|
||||
<template #node-teleportable="{ id }">
|
||||
<TeleportableNode :id="id" />
|
||||
</template>
|
||||
</VueFlow>
|
||||
|
||||
<Sidebar />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script setup>
|
||||
//
|
||||
// ...
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<aside>
|
||||
<div class="description">Teleport destination</div>
|
||||
|
||||
<div id="port" class="port"></div>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { Handle, Position } from '@vue-flow/core'
|
||||
import { useTeleport } from './useTransition.js'
|
||||
import { useTeleport } from './useTeleport.js'
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
@@ -27,12 +27,17 @@ export default {
|
||||
<transition :name="animation">
|
||||
<div v-if="!transition" class="teleportable">
|
||||
<Handle type="target" :position="Position.Top" />
|
||||
|
||||
[Node {{ id }}]
|
||||
|
||||
<div class="buttons">
|
||||
<div v-if="teleport !== '#port'" class="button" @click.prevent="onClick('#port')">Teleport To Sidebar</div>
|
||||
|
||||
<div v-if="teleport !== null" class="button" @click.prevent="onClick(null)">Teleport To Main Graph</div>
|
||||
|
||||
<div class="button" @click.prevent="changeAnimation">Animation: {{ animation }}</div>
|
||||
</div>
|
||||
|
||||
<Handle type="source" :position="Position.Bottom" />
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
@@ -12,7 +12,7 @@ export const useTeleport = (id) => {
|
||||
const transition = ref(false)
|
||||
const teleport = ref(null)
|
||||
|
||||
const { updateNodeInternals, getNode, edges } = useVueFlow()
|
||||
const { updateNodeInternals, findNode, edges } = useVueFlow()
|
||||
|
||||
/**
|
||||
* specify a selector to teleport to
|
||||
@@ -65,7 +65,7 @@ export const useTeleport = (id) => {
|
||||
* i.e. if they emit events, they will still emit them up their regular tree
|
||||
*/
|
||||
const onClick = (destination) => {
|
||||
const node = getNode.value(id)
|
||||
const node = findNode(id)
|
||||
|
||||
transition.value = true
|
||||
|
||||
@@ -79,13 +79,13 @@ export const useTeleport = (id) => {
|
||||
// check if nodes connected to edge are teleported and hide edge if one of them is
|
||||
if (destination) {
|
||||
connectedEdges.forEach(
|
||||
(edge) => (edge.hidden = !!getNode.value(edge.source).data.destination || !!getNode.value(edge.target).data.destination),
|
||||
(edge) => (edge.hidden = !!findNode(edge.source).data.destination || !!findNode(edge.target).data.destination),
|
||||
)
|
||||
}
|
||||
|
||||
const onFinish = () => {
|
||||
connectedEdges.forEach(
|
||||
(edge) => (edge.hidden = !!getNode.value(edge.source).data.destination || !!getNode.value(edge.target).data.destination),
|
||||
(edge) => (edge.hidden = !!findNode(edge.source).data.destination || !!findNode(edge.target).data.destination),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ConnectionMode, Position, VueFlow, useVueFlow } from '@vue-flow/core'
|
||||
import { Position, VueFlow, useVueFlow } from '@vue-flow/core'
|
||||
import TransitionEdge from './TransitionEdge.vue'
|
||||
|
||||
const elements = ref([
|
||||
@@ -21,28 +21,18 @@ const elements = ref([
|
||||
|
||||
{ id: 'e1-2', type: 'custom', source: '1', target: '2', animated: true, style: { stroke: '#fff' } },
|
||||
])
|
||||
const bgColor = ref('#1A192B')
|
||||
const connectionLineStyle = { stroke: '#fff' }
|
||||
const snapGrid = [16, 16]
|
||||
|
||||
const { onPaneReady } = useVueFlow({
|
||||
connectionMode: ConnectionMode.Loose,
|
||||
connectionLineStyle,
|
||||
snapToGrid: true,
|
||||
snapGrid,
|
||||
defaultZoom: 1.5,
|
||||
})
|
||||
const { onPaneReady } = useVueFlow()
|
||||
|
||||
onPaneReady((i) => {
|
||||
i.fitView({
|
||||
nodes: ['1'],
|
||||
})
|
||||
console.log('flow loaded:', i)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VueFlow v-model="elements" :style="{ backgroundColor: bgColor }">
|
||||
<VueFlow v-model="elements" :style="{ backgroundColor: '#1A192B' }">
|
||||
<template #edge-custom="props">
|
||||
<TransitionEdge v-bind="props" />
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
import { TransitionPresets, useDebounceFn, useTransition, watchDebounced } from '@vueuse/core'
|
||||
import { getBezierPath, useVueFlow } from '@vue-flow/core'
|
||||
import { computed, ref } from 'vue'
|
||||
import { BezierEdge, useVueFlow } from '@vue-flow/core'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
@@ -64,21 +64,11 @@ const showDot = ref(false)
|
||||
|
||||
const { onNodeDoubleClick, fitBounds, fitView } = useVueFlow()
|
||||
|
||||
const edgePath = computed(() =>
|
||||
getBezierPath({
|
||||
sourceX: props.sourceX,
|
||||
sourceY: props.sourceY,
|
||||
sourcePosition: props.sourcePosition,
|
||||
targetX: props.targetX,
|
||||
targetY: props.targetY,
|
||||
targetPosition: props.targetPosition,
|
||||
}),
|
||||
)
|
||||
|
||||
const debouncedFitBounds = useDebounceFn(fitBounds, 1, { maxWait: 1 })
|
||||
|
||||
onNodeDoubleClick(({ node }) => {
|
||||
const isSource = props.source === node.id
|
||||
|
||||
const isTarget = props.target === node.id
|
||||
|
||||
if (!showDot.value && (isSource || isTarget)) {
|
||||
@@ -150,7 +140,8 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<path :id="id" ref="curve" :style="style" class="vue-flow__edge-path" :d="edgePath" :marker-end="markerEnd" />
|
||||
<BezierEdge v-bind="props" />
|
||||
|
||||
<Transition name="fade">
|
||||
<circle
|
||||
v-if="showDot"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { Controls } from '@vue-flow/additional-components'
|
||||
import { ConnectionMode, VueFlow, addEdge, updateEdge } from '@vue-flow/core'
|
||||
import { Background } from '@vue-flow/additional-components'
|
||||
import { VueFlow, useVueFlow } from '@vue-flow/core'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const elements = ref([
|
||||
@@ -24,25 +24,26 @@ const elements = ref([
|
||||
{ id: 'e1-2', source: '1', target: '2', label: 'Updateable edge', updatable: true },
|
||||
])
|
||||
|
||||
const onLoad = (flowInstance) => flowInstance.fitView()
|
||||
const { updateEdge, addEdges } = useVueFlow()
|
||||
|
||||
const onEdgeUpdateStart = (edge) => console.log('start update', edge)
|
||||
|
||||
const onEdgeUpdateEnd = (edge) => console.log('end update', edge)
|
||||
const onEdgeUpdate = ({ edge, connection }) => {
|
||||
elements.value = updateEdge(edge, connection, elements.value)
|
||||
}
|
||||
const onConnect = (params) => (elements.value = addEdge(params, elements.value))
|
||||
|
||||
const onEdgeUpdate = ({ edge, connection }) => updateEdge(edge, connection)
|
||||
|
||||
const onConnect = (params) => addEdges([params])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VueFlow
|
||||
v-model="elements"
|
||||
:connection-mode="ConnectionMode.Loose"
|
||||
@pane-ready="onLoad"
|
||||
fit-view-on-init
|
||||
@edge-update="onEdgeUpdate"
|
||||
@connect="onConnect"
|
||||
@edge-update-start="onEdgeUpdateStart"
|
||||
@edge-update-end="onEdgeUpdateEnd"
|
||||
>
|
||||
<Controls />
|
||||
<Background />
|
||||
</VueFlow>
|
||||
</template>
|
||||
|
||||
@@ -16,8 +16,8 @@ const elements = ref([
|
||||
{ id: 'C', type: 'custom', position: { x: 250, y: 300 }, isValidSourcePos: (connection) => connection.target === 'B' },
|
||||
])
|
||||
|
||||
const onLoad = (flowInstance) => flowInstance.fitView()
|
||||
const onConnectStart = ({ nodeId, handleType }) => console.log('on connect start', { nodeId, handleType })
|
||||
|
||||
const onConnectEnd = (event) => console.log('on connect end', event)
|
||||
|
||||
const onConnect = (params) => {
|
||||
@@ -29,15 +29,16 @@ const onConnect = (params) => {
|
||||
<template>
|
||||
<VueFlow
|
||||
v-model="elements"
|
||||
fit-view-on-init
|
||||
class="validationflow"
|
||||
@connect="onConnect"
|
||||
@pane-ready="onLoad"
|
||||
@connect-start="onConnectStart"
|
||||
@connect-end="onConnectEnd"
|
||||
>
|
||||
<template #node-custominput="props">
|
||||
<CustomInput v-bind="props" />
|
||||
</template>
|
||||
|
||||
<template #node-custom="props">
|
||||
<CustomNode v-bind="props" />
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user