chore: lint files

Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
braks
2023-03-31 21:30:23 +02:00
committed by Braks
parent 9d597ff454
commit f61e5beb02
69 changed files with 623 additions and 424 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ watchEffect(() => {
vh.value = `${window.innerHeight}px` vh.value = `${window.innerHeight}px`
}) })
const files: Record<string, typeof imports[keyof typeof imports]> = {} const files: Record<string, (typeof imports)[keyof typeof imports]> = {}
const imports = exampleImports[props.example] const imports = exampleImports[props.example]
const additionalImports = 'additionalImports' in imports ? imports.additionalImports : {} const additionalImports = 'additionalImports' in imports ? imports.additionalImports : {}
+12 -5
View File
@@ -40,8 +40,8 @@ const dark = ref(false)
* To update node properties you can simply use your elements v-model and mutate the elements directly * To update node properties you can simply use your elements v-model and mutate the elements directly
* Changes should always be reflected on the graph reactively, without the need to overwrite the elements * Changes should always be reflected on the graph reactively, without the need to overwrite the elements
*/ */
const updatePos = () => function updatePos() {
elements.value.forEach((el) => { return elements.value.forEach((el) => {
if (isNode(el)) { if (isNode(el)) {
el.position = { el.position = {
x: Math.random() * 400, x: Math.random() * 400,
@@ -49,18 +49,25 @@ const updatePos = () =>
} }
} }
}) })
}
/** /**
* toObject transforms your current graph data to an easily persist-able object * toObject transforms your current graph data to an easily persist-able object
*/ */
const logToObject = () => console.log(toObject()) function logToObject() {
return console.log(toObject())
}
/** /**
* Resets the current viewpane transformation (zoom & pan) * Resets the current viewpane transformation (zoom & pan)
*/ */
const resetTransform = () => setTransform({ x: 0, y: 0, zoom: 1 }) function resetTransform() {
return setTransform({ x: 0, y: 0, zoom: 1 })
}
const toggleClass = () => (dark.value = !dark.value) function toggleClass() {
return (dark.value = !dark.value)
}
</script> </script>
<template> <template>
@@ -1,5 +1,5 @@
<script setup> <script setup>
const props = defineProps({ defineProps({
sourceX: { sourceX: {
type: Number, type: Number,
required: true, required: true,
+10 -6
View File
@@ -18,23 +18,27 @@ const bgName = ref('AYAME')
const connectionLineStyle = { stroke: '#fff' } const connectionLineStyle = { stroke: '#fff' }
// minimap stroke color functions // minimap stroke color functions
const nodeStroke = (n) => { function nodeStroke(n) {
if (n.type === 'input') return '#0041d0' if (n.type === 'input') return '#0041d0'
if (n.type === 'custom') return presets.sumi if (n.type === 'custom') return presets.sumi
if (n.type === 'output') return '#ff0072' if (n.type === 'output') return '#ff0072'
return '#eee' return '#eee'
} }
const nodeColor = (n) => { function nodeColor(n) {
if (n.type === 'custom') return bgColor.value if (n.type === 'custom') return bgColor.value
return '#fff' return '#fff'
} }
// output labels // output labels
const outputColorLabel = () => h('div', {}, bgColor.value) function outputColorLabel() {
const outputNameLabel = () => h('div', {}, bgName.value) return h('div', {}, bgColor.value)
}
function outputNameLabel() {
return h('div', {}, bgName.value)
}
const onChange = (color) => { function onChange(color) {
gradient.value = false gradient.value = false
bgColor.value = color.value bgColor.value = color.value
bgName.value = color.name bgName.value = color.name
@@ -42,7 +46,7 @@ const onChange = (color) => {
findNode('3').hidden = false findNode('3').hidden = false
} }
const onGradient = () => { function onGradient() {
gradient.value = true gradient.value = true
bgColor.value = null bgColor.value = null
bgName.value = 'gradient' bgName.value = 'gradient'
@@ -12,11 +12,11 @@ const props = defineProps({
const emit = defineEmits(['change', 'gradient']) const emit = defineEmits(['change', 'gradient'])
const onSelect = (color) => { function onSelect(color) {
emit('change', color) emit('change', color)
} }
const onGradient = () => { function onGradient() {
emit('gradient') emit('gradient')
} }
+6 -4
View File
@@ -4,9 +4,11 @@ import { nextTick, watch } from 'vue'
import Sidebar from './Sidebar.vue' import Sidebar from './Sidebar.vue'
let id = 0 let id = 0
const getId = () => `dndnode_${id++}` function getId() {
return `dndnode_${id++}`
}
const { findNode, onConnect, nodes, edges, addEdges, addNodes, viewport, project, vueFlowRef } = useVueFlow({ const { findNode, onConnect, addEdges, addNodes, project, vueFlowRef } = useVueFlow({
nodes: [ nodes: [
{ {
id: '1', id: '1',
@@ -17,7 +19,7 @@ const { findNode, onConnect, nodes, edges, addEdges, addNodes, viewport, project
], ],
}) })
const onDragOver = (event) => { function onDragOver(event) {
event.preventDefault() event.preventDefault()
if (event.dataTransfer) { if (event.dataTransfer) {
@@ -27,7 +29,7 @@ const onDragOver = (event) => {
onConnect((params) => addEdges([params])) onConnect((params) => addEdges([params]))
const onDrop = (event) => { function onDrop(event) {
const type = event.dataTransfer?.getData('application/vueflow') const type = event.dataTransfer?.getData('application/vueflow')
const { left, top } = vueFlowRef.value.getBoundingClientRect() const { left, top } = vueFlowRef.value.getBoundingClientRect()
+1 -1
View File
@@ -1,5 +1,5 @@
<script setup> <script setup>
const onDragStart = (event, nodeType) => { function onDragStart(event, nodeType) {
if (event.dataTransfer) { if (event.dataTransfer) {
event.dataTransfer.setData('application/vueflow', nodeType) event.dataTransfer.setData('application/vueflow', nodeType)
event.dataTransfer.effectAllowed = 'move' event.dataTransfer.effectAllowed = 'move'
+2 -2
View File
@@ -3,11 +3,11 @@ import { Panel, PanelPosition, VueFlow, useVueFlow } from '@vue-flow/core'
import { Background, BackgroundVariant } from '@vue-flow/background' import { Background, BackgroundVariant } from '@vue-flow/background'
import { MiniMap } from '@vue-flow/minimap' import { MiniMap } from '@vue-flow/minimap'
const { nodes, addNodes, edges, addEdges, onConnect, onPaneReady, onNodeDragStop, dimensions } = useVueFlow() const { nodes, addNodes, addEdges, onConnect, dimensions } = useVueFlow()
onConnect((params) => addEdges([params])) onConnect((params) => addEdges([params]))
const addRandomNode = () => { function addRandomNode() {
const nodeId = (nodes.value.length + 1).toString() const nodeId = (nodes.value.length + 1).toString()
const newNode = { const newNode = {
@@ -7,6 +7,7 @@ import { initialElements } from './initial-elements.js'
* You can either use `getIntersectingNodes` to check if a given node intersects with others * You can either use `getIntersectingNodes` to check if a given node intersects with others
* or `isNodeIntersecting` to check if a node is intersecting with a given area * or `isNodeIntersecting` to check if a node is intersecting with a given area
*/ */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { onNodeDrag, getIntersectingNodes, isNodeIntersecting, getNodes } = useVueFlow() const { onNodeDrag, getIntersectingNodes, isNodeIntersecting, getNodes } = useVueFlow()
const elements = ref(initialElements) const elements = ref(initialElements)
+6 -3
View File
@@ -12,10 +12,12 @@ const elements = ref([
{ id: 'e1-3', source: '1', target: '3' }, { id: 'e1-3', source: '1', target: '3' },
]) ])
const toggleClass = () => elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light')) function toggleClass() {
return elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light'))
}
const updatePos = () => function updatePos() {
elements.value.forEach((el) => { return elements.value.forEach((el) => {
if (isNode(el)) { if (isNode(el)) {
el.position = { el.position = {
x: Math.random() * 400, x: Math.random() * 400,
@@ -23,6 +25,7 @@ const updatePos = () =>
} }
} }
}) })
}
</script> </script>
<template> <template>
+1 -1
View File
@@ -5,7 +5,7 @@ import { Controls } from '@vue-flow/controls'
import { MiniMap } from '@vue-flow/minimap' import { MiniMap } from '@vue-flow/minimap'
import { onMounted } from 'vue' import { onMounted } from 'vue'
const { onConnect, nodes, edges, addEdges, addNodes } = useVueFlow({ const { onConnect, addEdges, addNodes } = useVueFlow({
fitViewOnInit: true, fitViewOnInit: true,
// set this to true so edges get elevated when selected, defaults to false // set this to true so edges get elevated when selected, defaults to false
elevateEdgesOnSelect: true, elevateEdgesOnSelect: true,
@@ -5,11 +5,11 @@ const flowKey = 'example-flow'
const { nodes, addNodes, setNodes, setEdges, dimensions, setTransform, toObject } = useVueFlow() const { nodes, addNodes, setNodes, setEdges, dimensions, setTransform, toObject } = useVueFlow()
const onSave = () => { function onSave() {
localStorage.setItem(flowKey, JSON.stringify(toObject())) localStorage.setItem(flowKey, JSON.stringify(toObject()))
} }
const onRestore = () => { function onRestore() {
const flow = JSON.parse(localStorage.getItem(flowKey)) const flow = JSON.parse(localStorage.getItem(flowKey))
if (flow) { if (flow) {
@@ -20,7 +20,7 @@ const onRestore = () => {
} }
} }
const onAdd = () => { function onAdd() {
const id = nodes.value.length + 1 const id = nodes.value.length + 1
const newNode = { const newNode = {
+9 -8
View File
@@ -6,21 +6,22 @@ import { nextTick, ref } from 'vue'
import { getElements } from './utils.js' import { getElements } from './utils.js'
const { nodes, edges } = getElements(15, 15) const { nodes, edges } = getElements(15, 15)
const elements = ref([...nodes, ...edges]) const elements = ref([...nodes, ...edges])
const { onPaneReady, dimensions, onNodeClick, getEdges, fitView } = useVueFlow() const { onPaneReady, dimensions, fitView } = useVueFlow()
onPaneReady((i) => { onPaneReady(({ fitView, getElements }) => {
i.fitView({ fitView({ padding: 0.2 })
padding: 0.2,
})
console.log(i.getElements.value) console.log(getElements.value)
}) })
const toggleClass = () => elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light')) function toggleClass() {
return elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light'))
}
const updatePos = () => { function updatePos() {
elements.value.forEach((el) => { elements.value.forEach((el) => {
if (isNode(el)) { if (isNode(el)) {
el.position = { el.position = {
@@ -11,7 +11,7 @@ const props = defineProps({
const { animation, transition, teleport, onClick } = useTeleport(props.id) const { animation, transition, teleport, onClick } = useTeleport(props.id)
const changeAnimation = () => { function changeAnimation() {
animation.value = animation.value === 'fade' ? 'shrink' : 'fade' animation.value = animation.value === 'fade' ? 'shrink' : 'fade'
} }
</script> </script>
@@ -7,7 +7,7 @@ import { nextTick, ref } from 'vue'
* Animations that resize a node need to call the `updateNodeDimensions` function from store to update node handle positions * Animations that resize a node need to call the `updateNodeDimensions` function from store to update node handle positions
* Otherwise edges do not connect properly * Otherwise edges do not connect properly
*/ */
export const useTeleport = (id) => { export function useTeleport(id) {
const animation = ref('fade') const animation = ref('fade')
const transition = ref(false) const transition = ref(false)
const teleport = ref(null) const teleport = ref(null)
+12 -4
View File
@@ -26,13 +26,21 @@ const elements = ref([
const { updateEdge, addEdges } = useVueFlow() const { updateEdge, addEdges } = useVueFlow()
const onEdgeUpdateStart = (edge) => console.log('start update', edge) function onEdgeUpdateStart(edge) {
return console.log('start update', edge)
}
const onEdgeUpdateEnd = (edge) => console.log('end update', edge) function onEdgeUpdateEnd(edge) {
return console.log('end update', edge)
}
const onEdgeUpdate = ({ edge, connection }) => updateEdge(edge, connection) function onEdgeUpdate({ edge, connection }) {
return updateEdge(edge, connection)
}
const onConnect = (params) => addEdges([params]) function onConnect(params) {
return addEdges([params])
}
</script> </script>
<template> <template>
+1 -1
View File
@@ -17,7 +17,7 @@ const opts = reactive({
hidden: false, hidden: false,
}) })
const updateNode = () => { function updateNode() {
const node = getNode.value('1') const node = getNode.value('1')
node.label = opts.label.trim() !== '' ? opts.label : defaultLabel node.label = opts.label.trim() !== '' ? opts.label : defaultLabel
node.style = { backgroundColor: opts.bg } node.style = { backgroundColor: opts.bg }
+7 -3
View File
@@ -16,11 +16,15 @@ const elements = ref([
{ id: 'C', type: 'custom', position: { x: 250, y: 300 }, isValidSourcePos: (connection) => connection.target === 'B' }, { id: 'C', type: 'custom', position: { x: 250, y: 300 }, isValidSourcePos: (connection) => connection.target === 'B' },
]) ])
const onConnectStart = ({ nodeId, handleType }) => console.log('on connect start', { nodeId, handleType }) function onConnectStart({ nodeId, handleType }) {
return console.log('on connect start', { nodeId, handleType })
}
const onConnectEnd = (event) => console.log('on connect end', event) function onConnectEnd(event) {
return console.log('on connect end', event)
}
const onConnect = (params) => { function onConnect(params) {
console.log('on connect', params) console.log('on connect', params)
addEdge(params, elements.value) addEdge(params, elements.value)
} }
+2 -2
View File
@@ -8,12 +8,12 @@ import Additional from './flows/Additional.vue'
const el = ref<HTMLDivElement>() const el = ref<HTMLDivElement>()
const instances: VueFlowStore[] = [] const instances: VueFlowStore[] = []
const onLoad = (instance: VueFlowStore) => { function onLoad(instance: VueFlowStore) {
instances.push(instance) instances.push(instance)
instance.fitView() instance.fitView()
} }
const fitViews = () => { function fitViews() {
instances.forEach((i) => i.fitView()) instances.forEach((i) => i.fitView())
} }
+3 -3
View File
@@ -226,7 +226,7 @@ function setElements() {
const { stop } = useResizeObserver(el, useDebounceFn(setElements, 5)) const { stop } = useResizeObserver(el, useDebounceFn(setElements, 5))
onBeforeUnmount(stop) onBeforeUnmount(stop)
const scrollTo = () => { function scrollTo() {
const el = document.getElementById('acknowledgement') const el = document.getElementById('acknowledgement')
if (el) { if (el) {
el.scrollIntoView({ behavior: 'smooth' }) el.scrollIntoView({ behavior: 'smooth' })
@@ -235,7 +235,7 @@ const scrollTo = () => {
const animationClassNames = ['checker-gb', 'checker-op', 'checker-yg', 'checker-ss'] const animationClassNames = ['checker-gb', 'checker-op', 'checker-yg', 'checker-ss']
const shuffle = (a: any[]) => { function shuffle(a: any[]) {
for (let i = a.length - 1; i > 0; i--) { for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1)) const j = Math.floor(Math.random() * (i + 1))
;[a[i], a[j]] = [a[j], a[i]] ;[a[i], a[j]] = [a[j], a[i]]
@@ -243,7 +243,7 @@ const shuffle = (a: any[]) => {
return a return a
} }
const createAnimationDurations = () => { function createAnimationDurations() {
return animationClassNames.map((className) => { return animationClassNames.map((className) => {
const duration = 5 + Math.random() * 5 const duration = 5 + Math.random() * 5
+3 -1
View File
@@ -59,7 +59,9 @@ watch(
{ immediate: true }, { immediate: true },
) )
const onChange = ({ color: c, val }: { color: keyof Colors; val: number }) => (color.value[c] = Number(val)) function onChange({ color: c, val }: { color: keyof Colors; val: number }) {
return (color.value[c] = Number(val))
}
const nodeColor: MiniMapNodeFunc = (node) => { const nodeColor: MiniMapNodeFunc = (node) => {
switch (node.id) { switch (node.id) {
+2 -2
View File
@@ -1,6 +1,6 @@
import confetti from 'canvas-confetti' import confetti from 'canvas-confetti'
export const fireworks = (colors?: string[]) => { export function fireworks(colors?: string[]) {
return new Promise((resolve) => { return new Promise((resolve) => {
const duration = 15 * 1000 const duration = 15 * 1000
const animationEnd = Date.now() + duration const animationEnd = Date.now() + duration
@@ -38,7 +38,7 @@ export const fireworks = (colors?: string[]) => {
}) })
} }
export const cheer = (colors: string[]) => { export function cheer(colors: string[]) {
return new Promise((resolve) => { return new Promise((resolve) => {
const end = Date.now() + 2 * 1000 const end = Date.now() + 2 * 1000
+30 -15
View File
@@ -12,35 +12,50 @@ interface RGBNodeProps extends NodeProps {
blue: number blue: number
} }
} }
const props = defineProps<RGBNodeProps>() const props = defineProps<RGBNodeProps>()
const emit = defineEmits(['change']) const emit = defineEmits(['change'])
let color = 'red'
switch (props.data?.color) { const currentColor = computed(() => {
case 'r': let color
color = 'red'
break switch (props.data?.color) {
case 'g': case 'r':
color = 'green' color = 'red'
break break
case 'b': case 'g':
color = 'blue' color = 'green'
break break
case 'b':
color = 'blue'
break
default:
color = 'red'
}
return color
})
function onChange(e: any) {
return emit('change', { color: currentColor.value, val: e.target.value })
} }
const onChange = (e: any) => emit('change', { color, val: e.target.value })
</script> </script>
<template> <template>
<div class="px-4 py-2 bg-white rounded-md border-2 border-solid border-black text-left transform scale-75 lg:scale-100"> <div class="px-4 py-2 bg-white rounded-md border-2 border-solid border-black text-left transform scale-75 lg:scale-100">
<div class="text-md" :style="{ color }">{{ `${color} Amount`.toUpperCase() }}</div> <div class="text-md" :style="{ color: currentColor }">{{ `${currentColor} Amount`.toUpperCase() }}</div>
<input <input
v-model="props.amount[color]" :model-value="amount[currentColor]"
class="slider nodrag" class="slider nodrag"
:style="{ '--color': color }" :style="{ '--color': currentColor }"
type="range" type="range"
min="0" min="0"
max="255" max="255"
@input="onChange" @input="onChange"
/> />
<Handle type="source" :position="Position.Right" :style="{ backgroundColor: color }" /> <Handle type="source" :position="Position.Right" :style="{ backgroundColor: color }" />
</div> </div>
</template> </template>
+2 -2
View File
@@ -17,7 +17,7 @@ function capitalize(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1) return str.charAt(0).toUpperCase() + str.slice(1)
} }
const typedocSidebarEntries = (): DefaultTheme.SidebarGroup[] => { function typedocSidebarEntries(): DefaultTheme.SidebarGroup[] {
const filePath = resolve(__dirname, '../typedocs') const filePath = resolve(__dirname, '../typedocs')
const docsModules = readdirSync(filePath).filter((name) => statSync(`${filePath}/${name}`).isDirectory()) const docsModules = readdirSync(filePath).filter((name) => statSync(`${filePath}/${name}`).isDirectory())
@@ -38,7 +38,7 @@ const typedocSidebarEntries = (): DefaultTheme.SidebarGroup[] => {
}) })
} }
const changelogSidebarEntries = (): DefaultTheme.SidebarGroup[] => { function changelogSidebarEntries(): DefaultTheme.SidebarGroup[] {
return [ return [
{ {
text: 'CHANGELOG', text: 'CHANGELOG',
+10 -5
View File
@@ -37,8 +37,8 @@ const dark = ref(false)
* To update node properties you can simply use your elements v-model and mutate the elements directly * To update node properties you can simply use your elements v-model and mutate the elements directly
* Changes should always be reflected on the graph reactively, without the need to overwrite the elements * Changes should always be reflected on the graph reactively, without the need to overwrite the elements
*/ */
const updatePos = () => function updatePos() {
elements.value.forEach((el) => { return elements.value.forEach((el) => {
console.log(el, elements.value) console.log(el, elements.value)
if (isNode(el)) { if (isNode(el)) {
el.position = { el.position = {
@@ -47,18 +47,23 @@ const updatePos = () =>
} }
} }
}) })
}
/** /**
* toObject transforms your current graph data to an easily persist-able object * toObject transforms your current graph data to an easily persist-able object
*/ */
const logToObject = () => console.log(instance.value?.toObject()) function logToObject() {
return console.log(instance.value?.toObject())
}
/** /**
* Resets the current viewpane transformation (zoom & pan) * Resets the current viewpane transformation (zoom & pan)
*/ */
const resetTransform = () => instance.value?.setTransform({ x: 0, y: 0, zoom: 1 }) function resetTransform() {
return instance.value?.setTransform({ x: 0, y: 0, zoom: 1 })
}
const toggleClass = () => { function toggleClass() {
dark.value = !dark.value dark.value = !dark.value
elements.value.forEach((el) => (el.class = dark.value ? 'dark' : 'light')) elements.value.forEach((el) => (el.class = dark.value ? 'dark' : 'light'))
} }
@@ -37,8 +37,8 @@ const dark = ref(false)
* To update node properties you can simply use your elements v-model and mutate the elements directly * To update node properties you can simply use your elements v-model and mutate the elements directly
* Changes should always be reflected on the graph reactively, without the need to overwrite the elements * Changes should always be reflected on the graph reactively, without the need to overwrite the elements
*/ */
const updatePos = () => function updatePos() {
elements.value.forEach((el) => { return elements.value.forEach((el) => {
console.log(el, elements.value) console.log(el, elements.value)
if (isNode(el)) { if (isNode(el)) {
el.position = { el.position = {
@@ -47,18 +47,23 @@ const updatePos = () =>
} }
} }
}) })
}
/** /**
* toObject transforms your current graph data to an easily persist-able object * toObject transforms your current graph data to an easily persist-able object
*/ */
const logToObject = () => console.log(instance.value?.toObject()) function logToObject() {
return console.log(instance.value?.toObject())
}
/** /**
* Resets the current viewpane transformation (zoom & pan) * Resets the current viewpane transformation (zoom & pan)
*/ */
const resetTransform = () => instance.value?.setTransform({ x: 0, y: 0, zoom: 1 }) function resetTransform() {
return instance.value?.setTransform({ x: 0, y: 0, zoom: 1 })
}
const toggleClass = () => { function toggleClass() {
dark.value = !dark.value dark.value = !dark.value
elements.value.forEach((el) => (el.class = dark.value ? 'dark' : 'light')) elements.value.forEach((el) => (el.class = dark.value ? 'dark' : 'light'))
} }
+1 -1
View File
@@ -6,7 +6,7 @@ const router = useRouter()
const route = useRoute() const route = useRoute()
const onChange = (event: Event) => { function onChange(event: Event) {
router.push((event.target as HTMLSelectElement).value) router.push((event.target as HTMLSelectElement).value)
} }
+12 -5
View File
@@ -23,8 +23,8 @@ onNodeDragStop((e) => console.log('drag stop', e.event))
onEdgeClick(console.log) onEdgeClick(console.log)
onConnect((params) => addEdges([params])) onConnect((params) => addEdges([params]))
const updatePos = () => function updatePos() {
elements.value.forEach((el) => { return elements.value.forEach((el) => {
if (isNode(el)) { if (isNode(el)) {
el.position = { el.position = {
x: Math.random() * 400, x: Math.random() * 400,
@@ -32,10 +32,17 @@ const updatePos = () =>
} }
} }
}) })
}
const logToObject = () => console.log(toObject()) function logToObject() {
const resetTransform = () => setTransform({ x: 0, y: 0, zoom: 1 }) return console.log(toObject())
const toggleclass = () => elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light')) }
function resetTransform() {
return setTransform({ x: 0, y: 0, zoom: 1 })
}
function toggleclass() {
return elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light'))
}
</script> </script>
<template> <template>
+5 -3
View File
@@ -4,7 +4,9 @@ import { VueFlow, useVueFlow } from '@vue-flow/core'
import Sidebar from './Sidebar.vue' import Sidebar from './Sidebar.vue'
let id = 0 let id = 0
const getId = () => `dndnode_${id++}` function getId() {
return `dndnode_${id++}`
}
const { onConnect, addEdges, addNodes, project } = useVueFlow({ const { onConnect, addEdges, addNodes, project } = useVueFlow({
nodes: [ nodes: [
@@ -16,7 +18,7 @@ const { onConnect, addEdges, addNodes, project } = useVueFlow({
}, },
], ],
}) })
const onDragOver = (event: DragEvent) => { function onDragOver(event: DragEvent) {
event.preventDefault() event.preventDefault()
if (event.dataTransfer) { if (event.dataTransfer) {
event.dataTransfer.dropEffect = 'move' event.dataTransfer.dropEffect = 'move'
@@ -27,7 +29,7 @@ const wrapper = ref()
onConnect((params) => addEdges([params])) onConnect((params) => addEdges([params]))
const onDrop = (event: DragEvent) => { function onDrop(event: DragEvent) {
const type = event.dataTransfer?.getData('application/vueflow') const type = event.dataTransfer?.getData('application/vueflow')
const flowbounds = wrapper.value.$el.getBoundingClientRect() const flowbounds = wrapper.value.$el.getBoundingClientRect()
+1 -1
View File
@@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
const onDragStart = (event: DragEvent, nodeType: string) => { function onDragStart(event: DragEvent, nodeType: string) {
if (event.dataTransfer) { if (event.dataTransfer) {
event.dataTransfer.setData('application/vueflow', nodeType) event.dataTransfer.setData('application/vueflow', nodeType)
event.dataTransfer.effectAllowed = 'move' event.dataTransfer.effectAllowed = 'move'
+3 -1
View File
@@ -50,7 +50,9 @@ const offsets = [
] ]
let id = 0 let id = 0
const getNodeId = () => (id++).toString() function getNodeId() {
return (id++).toString()
}
export function getElements(): Elements { export function getElements(): Elements {
const initialElements = [] const initialElements = []
+1 -1
View File
@@ -12,7 +12,7 @@ onConnect((params) => addEdges([params]))
onPaneReady((flowInstance) => console.log('flow loaded:', flowInstance)) onPaneReady((flowInstance) => console.log('flow loaded:', flowInstance))
onNodeDragStop((node) => console.log('drag stop', node)) onNodeDragStop((node) => console.log('drag stop', node))
const addRandomNode = () => { function addRandomNode() {
const nodeId = (nodes.value.length + 1).toString() const nodeId = (nodes.value.length + 1).toString()
const newNode: Node = { const newNode: Node = {
id: nodeId, id: nodeId,
@@ -18,7 +18,7 @@ const nodeExtent: CoordinateExtent = [
const elements = ref<Elements>(initialElements) const elements = ref<Elements>(initialElements)
const onLayout = (direction: string) => { function onLayout(direction: string) {
const isHorizontal = direction === 'LR' const isHorizontal = direction === 'LR'
dagreGraph.setGraph({ rankdir: direction }) dagreGraph.setGraph({ rankdir: direction })
@@ -29,7 +29,7 @@ onConnect((params) => addEdges([params]))
onPaneReady((instance) => instance.fitView()) onPaneReady((instance) => instance.fitView())
const changeType = () => { function changeType() {
elements.value.forEach((el) => { elements.value.forEach((el) => {
if (isEdge(el) || el.type === 'input') return if (isEdge(el) || el.type === 'input') return
el.type = el.type === 'default' ? 'output' : 'default' el.type = el.type === 'default' ? 'output' : 'default'
+54 -20
View File
@@ -5,28 +5,62 @@ import { Background } from '@vue-flow/background'
import { Controls } from '@vue-flow/controls' import { Controls } from '@vue-flow/controls'
import { MiniMap } from '@vue-flow/minimap' import { MiniMap } from '@vue-flow/minimap'
const onNodeDragStart = (e: FlowEvents['nodeDragStart']) => console.log('drag start', e) function onNodeDragStart(e: FlowEvents['nodeDragStart']) {
const onNodeDrag = (e: FlowEvents['nodeDrag']) => console.log('drag', e) return console.log('drag start', e)
const onNodeDragStop = (e: FlowEvents['nodeDragStop']) => console.log('drag stop', e) }
const onNodeDoubleClick = (e: FlowEvents['nodeDoubleClick']) => console.log('node double click', e) function onNodeDrag(e: FlowEvents['nodeDrag']) {
const onPaneClick = (e: FlowEvents['paneClick']) => console.log('pane click', e) return console.log('drag', e)
const onPaneScroll = (e: FlowEvents['paneScroll']) => console.log('pane scroll', e) }
const onPaneContextMenu = (e: FlowEvents['paneContextMenu']) => console.log('pane context menu', e) function onNodeDragStop(e: FlowEvents['nodeDragStop']) {
const onSelectionDrag = (e: FlowEvents['selectionDrag']) => console.log('selection drag', e) return console.log('drag stop', e)
const onSelectionDragStart = (e: FlowEvents['selectionDragStart']) => console.log('selection drag start', e) }
const onSelectionDragStop = (e: FlowEvents['selectionDragStop']) => console.log('selection drag stop', e) function onNodeDoubleClick(e: FlowEvents['nodeDoubleClick']) {
const onSelectionContextMenu = (e: FlowEvents['selectionContextMenu']) => console.log('selection context menu', e) return console.log('node double click', e)
const onLoad = (flowInstance: VueFlowStore) => { }
function onPaneClick(e: FlowEvents['paneClick']) {
return console.log('pane click', e)
}
function onPaneScroll(e: FlowEvents['paneScroll']) {
return console.log('pane scroll', e)
}
function onPaneContextMenu(e: FlowEvents['paneContextMenu']) {
return console.log('pane context menu', e)
}
function onSelectionDrag(e: FlowEvents['selectionDrag']) {
return console.log('selection drag', e)
}
function onSelectionDragStart(e: FlowEvents['selectionDragStart']) {
return console.log('selection drag start', e)
}
function onSelectionDragStop(e: FlowEvents['selectionDragStop']) {
return console.log('selection drag stop', e)
}
function onSelectionContextMenu(e: FlowEvents['selectionContextMenu']) {
return console.log('selection context menu', e)
}
function onLoad(flowInstance: VueFlowStore) {
console.log('flow loaded:', flowInstance) console.log('flow loaded:', flowInstance)
flowInstance.fitView() flowInstance.fitView()
} }
const onMoveEnd = (e: FlowEvents['moveEnd']) => console.log('zoom/move end', e.flowTransform) function onMoveEnd(e: FlowEvents['moveEnd']) {
const onEdgeContextMenu = (e: FlowEvents['edgeContextMenu']) => console.log('edge context menu', e) return console.log('zoom/move end', e.flowTransform)
const onEdgeMouseEnter = (e: FlowEvents['edgeMouseEnter']) => console.log('edge mouse enter', e) }
const onEdgeMouseMove = (e: FlowEvents['edgeMouseMove']) => console.log('edge mouse move', e) function onEdgeContextMenu(e: FlowEvents['edgeContextMenu']) {
const onEdgeMouseLeave = (e: FlowEvents['edgeMouseLeave']) => console.log('edge mouse leave', e) return console.log('edge context menu', e)
const onEdgeDoubleClick = (e: FlowEvents['edgeDoubleClick']) => console.log('edge double click', e) }
function onEdgeMouseEnter(e: FlowEvents['edgeMouseEnter']) {
return console.log('edge mouse enter', e)
}
function onEdgeMouseMove(e: FlowEvents['edgeMouseMove']) {
return console.log('edge mouse move', e)
}
function onEdgeMouseLeave(e: FlowEvents['edgeMouseLeave']) {
return console.log('edge mouse leave', e)
}
function onEdgeDoubleClick(e: FlowEvents['edgeDoubleClick']) {
return console.log('edge double click', e)
}
const initialElements: Elements = [ const initialElements: Elements = [
{ {
@@ -85,7 +119,7 @@ const initialElements: Elements = [
const snapGrid: SnapGrid = [16, 16] const snapGrid: SnapGrid = [16, 16]
const nodeStrokeColor = (n: Node): string => { function nodeStrokeColor(n: Node): string {
if ((n.style as Styles)?.background) return (n.style as Styles).background as string if ((n.style as Styles)?.background) return (n.style as Styles).background as string
if (n.type === 'input') return '#0041d0' if (n.type === 'input') return '#0041d0'
if (n.type === 'output') return '#ff0072' if (n.type === 'output') return '#ff0072'
@@ -94,7 +128,7 @@ const nodeStrokeColor = (n: Node): string => {
return '#eee' return '#eee'
} }
const nodeColor = (n: Node): string => { function nodeColor(n: Node): string {
if ((n.style as Styles)?.background) return (n.style as Styles).background as string if ((n.style as Styles)?.background) return (n.style as Styles).background as string
return '#fff' return '#fff'
@@ -7,7 +7,9 @@ import '@vue-flow/controls/dist/style.css'
import Sidebar from './Sidebar.vue' import Sidebar from './Sidebar.vue'
const onLoad = (flowInstance: VueFlowStore) => console.log('flow loaded:', flowInstance) function onLoad(flowInstance: VueFlowStore) {
return console.log('flow loaded:', flowInstance)
}
const initialElements: Elements = [ const initialElements: Elements = [
{ id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 } }, { id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 } },
+1 -1
View File
@@ -2,7 +2,7 @@
import { useVueFlow } from '@vue-flow/core' import { useVueFlow } from '@vue-flow/core'
const { nodesSelectionActive, addSelectedNodes, getNodes, viewport } = useVueFlow() const { nodesSelectionActive, addSelectedNodes, getNodes, viewport } = useVueFlow()
const selectAll = () => { function selectAll() {
addSelectedNodes(getNodes.value) addSelectedNodes(getNodes.value)
nodesSelectionActive.value = true nodesSelectionActive.value = true
} }
+8 -6
View File
@@ -1,5 +1,4 @@
<script lang="ts" setup> <script lang="ts" setup>
import { templateRef } from '@vueuse/core'
import type { Elements, VueFlowStore } from '@vue-flow/core' import type { Elements, VueFlowStore } from '@vue-flow/core'
import { VueFlow } from '@vue-flow/core' import { VueFlow } from '@vue-flow/core'
import RGBNode from './RGBNode.vue' import RGBNode from './RGBNode.vue'
@@ -10,6 +9,7 @@ interface Colors {
green: number green: number
blue: number blue: number
} }
const elements = ref<Elements>([ const elements = ref<Elements>([
{ id: '1', type: 'rgb', data: { color: 'r' }, position: { x: -25, y: 50 } }, { id: '1', type: 'rgb', data: { color: 'r' }, position: { x: -25, y: 50 } },
{ id: '2', type: 'rgb', data: { color: 'g' }, position: { x: 50, y: -100 } }, { id: '2', type: 'rgb', data: { color: 'g' }, position: { x: 50, y: -100 } },
@@ -20,21 +20,23 @@ const elements = ref<Elements>([
{ id: 'e3-4', data: { color: 'blue' }, source: '3', target: '4', animated: true }, { id: 'e3-4', data: { color: 'blue' }, source: '3', target: '4', animated: true },
]) ])
const el = templateRef<HTMLDivElement>('page', null) function onLoad(flowInstance: VueFlowStore) {
const onLoad = (flowInstance: VueFlowStore) => {
flowInstance.fitView({ padding: 1 }) flowInstance.fitView({ padding: 1 })
} }
const color = ref<Colors>({ const color = ref<Colors>({
red: 100, red: 100,
green: 150, green: 150,
blue: 100, blue: 100,
}) })
const onChange = ({ color: c, val }: { color: keyof Colors; val: number }) => (color.value[c] = Number(val))
function onChange({ color: c, val }: { color: keyof Colors; val: number }) {
return (color.value[c] = Number(val))
}
</script> </script>
<template> <template>
<div ref="page" class="demo-flow"> <div class="demo-flow">
<VueFlow v-model="elements" @pane-ready="onLoad"> <VueFlow v-model="elements" @pane-ready="onLoad">
<template #node-rgb="props"> <template #node-rgb="props">
<RGBNode v-bind="props" :amount="color" @change="onChange" /> <RGBNode v-bind="props" :amount="color" @change="onChange" />
+6 -4
View File
@@ -10,15 +10,17 @@ const state = useStorage<FlowExportObject>(flowKey, {
zoom: 1, zoom: 1,
}) })
const getNodeId = () => `randomnode_${+new Date()}` function getNodeId() {
return `randomnode_${+new Date()}`
}
const { addNodes, setNodes, setEdges, toObject, dimensions, setTransform } = useVueFlow() const { addNodes, setNodes, setEdges, toObject, dimensions, setTransform } = useVueFlow()
const onSave = () => { function onSave() {
state.value = toObject() state.value = toObject()
} }
const onRestore = () => { function onRestore() {
const flow: FlowExportObject | null = state.value const flow: FlowExportObject | null = state.value
if (flow) { if (flow) {
@@ -32,7 +34,7 @@ const onRestore = () => {
} }
} }
const onAdd = () => { function onAdd() {
const newNode = { const newNode = {
id: `random_node-${getNodeId()}`, id: `random_node-${getNodeId()}`,
label: 'Added node', label: 'Added node',
+4 -2
View File
@@ -17,9 +17,11 @@ onPaneReady((i) => {
console.log(i.getElements.value) console.log(i.getElements.value)
}) })
const toggleClass = () => elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light')) function toggleClass() {
return elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light'))
}
const updatePos = () => { function updatePos() {
elements.value.forEach((el) => { elements.value.forEach((el) => {
if (isNode(el)) { if (isNode(el)) {
el.position = { el.position = {
@@ -30,13 +30,21 @@ const { updateEdge } = useVueFlow()
const elements = ref(initialElements) const elements = ref(initialElements)
const onLoad = (flowInstance: VueFlowStore) => flowInstance.fitView() function onLoad(flowInstance: VueFlowStore) {
return flowInstance.fitView()
}
const onEdgeUpdateStart = ({ edge }: FlowEvents['edgeUpdateStart']) => console.log('start update', edge) function onEdgeUpdateStart({ edge }: FlowEvents['edgeUpdateStart']) {
return console.log('start update', edge)
}
const onEdgeUpdateEnd = ({ edge }: FlowEvents['edgeUpdateEnd']) => console.log('end update', edge) function onEdgeUpdateEnd({ edge }: FlowEvents['edgeUpdateEnd']) {
return console.log('end update', edge)
}
const onEdgeUpdate = ({ edge, connection }: FlowEvents['edgeUpdate']) => updateEdge(edge, connection) function onEdgeUpdate({ edge, connection }: FlowEvents['edgeUpdate']) {
return updateEdge(edge, connection)
}
</script> </script>
<template> <template>
@@ -15,7 +15,7 @@ const opts = reactive({
hidden: false, hidden: false,
}) })
const updateNode = () => { function updateNode() {
elements.value.forEach((el) => { elements.value.forEach((el) => {
if (el.id === '1') { if (el.id === '1') {
// it's important that you create a new object here in order to notify react flow about the change // it's important that you create a new object here in order to notify react flow about the change
@@ -17,11 +17,17 @@ const { addEdges } = useVueFlow({
{ id: 'C', type: 'customnode', position: { x: 250, y: 300 }, isValidSourcePos: (connection) => connection.target === 'B' }, { id: 'C', type: 'customnode', position: { x: 250, y: 300 }, isValidSourcePos: (connection) => connection.target === 'B' },
], ],
}) })
const onLoad = (flowInstance: VueFlowStore) => flowInstance.fitView() function onLoad(flowInstance: VueFlowStore) {
const onConnectStart = ({ nodeId, handleType }: OnConnectStartParams) => console.log('on connect start', { nodeId, handleType }) return flowInstance.fitView()
const onConnectEnd = (event: MouseEvent) => console.log('on connect end', event) }
function onConnectStart({ nodeId, handleType }: OnConnectStartParams) {
return console.log('on connect start', { nodeId, handleType })
}
function onConnectEnd(event: MouseEvent) {
return console.log('on connect end', event)
}
const onConnect = (params: Connection) => { function onConnect(params: Connection) {
console.log('on connect', params) console.log('on connect', params)
addEdges([params]) addEdges([params])
} }
+4 -4
View File
@@ -28,22 +28,22 @@ const { nodesDraggable, nodesConnectable, elementsSelectable, setInteractive, zo
const isInteractive = computed(() => nodesDraggable && nodesConnectable && elementsSelectable) const isInteractive = computed(() => nodesDraggable && nodesConnectable && elementsSelectable)
const onZoomInHandler = () => { function onZoomInHandler() {
zoomIn() zoomIn()
emit('zoomIn') emit('zoomIn')
} }
const onZoomOutHandler = () => { function onZoomOutHandler() {
zoomOut() zoomOut()
emit('zoomOut') emit('zoomOut')
} }
const onFitViewHandler = () => { function onFitViewHandler() {
fitView(fitViewParams) fitView(fitViewParams)
emit('fitView') emit('fitView')
} }
const onInteractiveChangeHandler = () => { function onInteractiveChangeHandler() {
setInteractive(!isInteractive.value) setInteractive(!isInteractive.value)
emit('interactionChange', !isInteractive.value) emit('interactionChange', !isInteractive.value)
} }
+1 -1
View File
@@ -49,7 +49,7 @@ const patchedSlots = `Record<string, (_: any) => any> & {
[key: \`edge-\${string}\`]: (edgeProps: EdgeProps) => any [key: \`edge-\${string}\`]: (edgeProps: EdgeProps) => any
}` }`
const patchSlots = async () => { async function patchSlots() {
const fileContents = await content(filePath) const fileContents = await content(filePath)
const patchedFileContents = fileContents.replace(typeImportsString, patchedTypeImports).replace(unpatchedSlots, patchedSlots) const patchedFileContents = fileContents.replace(typeImportsString, patchedTypeImports).replace(unpatchedSlots, patchedSlots)
@@ -8,13 +8,13 @@ interface Props extends HTMLAttributes {
radius?: number radius?: number
} }
const shiftX = (x: number, shift: number, position: Position): number => { function shiftX(x: number, shift: number, position: Position): number {
if (position === Position.Left) return x - shift if (position === Position.Left) return x - shift
if (position === Position.Right) return x + shift if (position === Position.Right) return x + shift
return x return x
} }
const shiftY = (y: number, shift: number, position: Position): number => { function shiftY(y: number, shift: number, position: Position): number {
if (position === Position.Top) return y - shift if (position === Position.Top) return y - shift
if (position === Position.Bottom) return y + shift if (position === Position.Bottom) return y + shift
return y return y
@@ -22,7 +22,7 @@ const handleDirections = {
[Position.Bottom]: { x: 0, y: 1 }, [Position.Bottom]: { x: 0, y: 1 },
} }
const getDirection = ({ function getDirection({
source, source,
sourcePosition = Position.Bottom, sourcePosition = Position.Bottom,
target, target,
@@ -30,14 +30,16 @@ const getDirection = ({
source: XYPosition source: XYPosition
sourcePosition: Position sourcePosition: Position
target: XYPosition target: XYPosition
}): XYPosition => { }): XYPosition {
if (sourcePosition === Position.Left || sourcePosition === Position.Right) { if (sourcePosition === Position.Left || sourcePosition === Position.Right) {
return source.x < target.x ? { x: 1, y: 0 } : { x: -1, y: 0 } return source.x < target.x ? { x: 1, y: 0 } : { x: -1, y: 0 }
} }
return source.y < target.y ? { x: 0, y: 1 } : { x: 0, y: -1 } return source.y < target.y ? { x: 0, y: 1 } : { x: 0, y: -1 }
} }
const distance = (a: XYPosition, b: XYPosition) => Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2) function distance(a: XYPosition, b: XYPosition) {
return Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2)
}
// With this function we try to mimic an orthogonal edge routing behaviour // With this function we try to mimic an orthogonal edge routing behaviour
// It's not as good as a real orthogonal edge routing, but it's faster and good enough as a default for step and smooth step edges // It's not as good as a real orthogonal edge routing, but it's faster and good enough as a default for step and smooth step edges
+13 -11
View File
@@ -1,16 +1,18 @@
import type { EdgeEventsEmit, EdgeEventsOn, GraphEdge, VueFlowStore } from '~/types' import type { EdgeEventsEmit, EdgeEventsOn, GraphEdge, VueFlowStore } from '~/types'
const createEdgeHooks = () => ({ function createEdgeHooks() {
doubleClick: createExtendedEventHook(), return {
click: createExtendedEventHook(), doubleClick: createExtendedEventHook(),
mouseEnter: createExtendedEventHook(), click: createExtendedEventHook(),
mouseMove: createExtendedEventHook(), mouseEnter: createExtendedEventHook(),
mouseLeave: createExtendedEventHook(), mouseMove: createExtendedEventHook(),
contextMenu: createExtendedEventHook(), mouseLeave: createExtendedEventHook(),
updateStart: createExtendedEventHook(), contextMenu: createExtendedEventHook(),
update: createExtendedEventHook(), updateStart: createExtendedEventHook(),
updateEnd: createExtendedEventHook(), update: createExtendedEventHook(),
}) updateEnd: createExtendedEventHook(),
}
}
export default function useEdgeHooks(edge: GraphEdge, emits: VueFlowStore['emits']): { emit: EdgeEventsEmit; on: EdgeEventsOn } { export default function useEdgeHooks(edge: GraphEdge, emits: VueFlowStore['emits']): { emit: EdgeEventsEmit; on: EdgeEventsOn } {
const edgeHooks = createEdgeHooks() const edgeHooks = createEdgeHooks()
+3 -1
View File
@@ -11,7 +11,9 @@ interface UseHandleProps {
onEdgeUpdateEnd?: (event: MouseTouchEvent) => void onEdgeUpdateEnd?: (event: MouseTouchEvent) => void
} }
const alwaysValid = () => true function alwaysValid() {
return true
}
export default function useHandle({ export default function useHandle({
handleId: _handleId, handleId: _handleId,
+13 -11
View File
@@ -1,16 +1,18 @@
import type { GraphNode, NodeEventsEmit, NodeEventsOn, VueFlowStore } from '~/types' import type { GraphNode, NodeEventsEmit, NodeEventsOn, VueFlowStore } from '~/types'
const createNodeHooks = () => ({ function createNodeHooks() {
doubleClick: createExtendedEventHook(), return {
click: createExtendedEventHook(), doubleClick: createExtendedEventHook(),
mouseEnter: createExtendedEventHook(), click: createExtendedEventHook(),
mouseMove: createExtendedEventHook(), mouseEnter: createExtendedEventHook(),
mouseLeave: createExtendedEventHook(), mouseMove: createExtendedEventHook(),
contextMenu: createExtendedEventHook(), mouseLeave: createExtendedEventHook(),
dragStart: createExtendedEventHook(), contextMenu: createExtendedEventHook(),
drag: createExtendedEventHook(), dragStart: createExtendedEventHook(),
dragStop: createExtendedEventHook(), drag: createExtendedEventHook(),
}) dragStop: createExtendedEventHook(),
}
}
export default function useNodeHooks(node: GraphNode, emits: VueFlowStore['emits']): { emit: NodeEventsEmit; on: NodeEventsOn } { export default function useNodeHooks(node: GraphNode, emits: VueFlowStore['emits']): { emit: NodeEventsEmit; on: NodeEventsOn } {
const nodeHooks = createNodeHooks() const nodeHooks = createNodeHooks()
+1 -1
View File
@@ -7,7 +7,7 @@ interface ExtendedViewport extends ViewportFunctions {
const DEFAULT_PADDING = 0.1 const DEFAULT_PADDING = 0.1
const noop = () => {} function noop() {}
const initialViewportHelper: ExtendedViewport = { const initialViewportHelper: ExtendedViewport = {
zoomIn: noop, zoomIn: noop,
@@ -51,9 +51,15 @@ const groups = controlledComputed(
() => groupEdgesByZLevel(getEdges, findNode, elevateEdgesOnSelect), () => groupEdgesByZLevel(getEdges, findNode, elevateEdgesOnSelect),
) )
const selectable = (edgeSelectable?: boolean) => (typeof edgeSelectable === 'undefined' ? elementsSelectable : edgeSelectable) function selectable(edgeSelectable?: boolean) {
const updatable = (edgeUpdatable?: EdgeUpdatable) => (typeof edgeUpdatable === 'undefined' ? edgesUpdatable : edgeUpdatable) return typeof edgeSelectable === 'undefined' ? elementsSelectable : edgeSelectable
const focusable = (edgeFocusable?: boolean) => (typeof edgeFocusable === 'undefined' ? edgesFocusable : edgeFocusable) }
function updatable(edgeUpdatable?: EdgeUpdatable) {
return typeof edgeUpdatable === 'undefined' ? edgesUpdatable : edgeUpdatable
}
function focusable(edgeFocusable?: boolean) {
return typeof edgeFocusable === 'undefined' ? edgesFocusable : edgeFocusable
}
function getType(type?: string, template?: GraphEdge['template']) { function getType(type?: string, template?: GraphEdge['template']) {
const name = type || 'default' const name = type || 'default'
@@ -44,11 +44,18 @@ onMounted(() => {
onBeforeUnmount(() => resizeObserver?.disconnect()) onBeforeUnmount(() => resizeObserver?.disconnect())
const draggable = (nodeDraggable?: boolean) => (typeof nodeDraggable === 'undefined' ? nodesDraggable : nodeDraggable) function draggable(nodeDraggable?: boolean) {
const selectable = (nodeSelectable?: boolean) => (typeof nodeSelectable === 'undefined' ? elementsSelectable : nodeSelectable) return typeof nodeDraggable === 'undefined' ? nodesDraggable : nodeDraggable
const connectable = (nodeConnectable?: HandleConnectable) => }
typeof nodeConnectable === 'undefined' ? nodesConnectable : nodeConnectable function selectable(nodeSelectable?: boolean) {
const focusable = (nodeFocusable?: boolean) => (typeof nodeFocusable === 'undefined' ? nodesFocusable : nodeFocusable) return typeof nodeSelectable === 'undefined' ? elementsSelectable : nodeSelectable
}
function connectable(nodeConnectable?: HandleConnectable) {
return typeof nodeConnectable === 'undefined' ? nodesConnectable : nodeConnectable
}
function focusable(nodeFocusable?: boolean) {
return typeof nodeFocusable === 'undefined' ? nodesFocusable : nodeFocusable
}
function getType(type?: string, template?: GraphNode['template']) { function getType(type?: string, template?: GraphNode['template']) {
const name = type || 'default' const name = type || 'default'
+54 -52
View File
@@ -2,58 +2,60 @@ import type { Ref } from 'vue'
import type { FlowHooks } from '~/types' import type { FlowHooks } from '~/types'
// flow event hooks // flow event hooks
export const createHooks = (): FlowHooks => ({ export function createHooks(): FlowHooks {
edgesChange: createExtendedEventHook(), return {
nodesChange: createExtendedEventHook(), edgesChange: createExtendedEventHook(),
nodeDoubleClick: createExtendedEventHook(), nodesChange: createExtendedEventHook(),
nodeClick: createExtendedEventHook(), nodeDoubleClick: createExtendedEventHook(),
nodeMouseEnter: createExtendedEventHook(), nodeClick: createExtendedEventHook(),
nodeMouseMove: createExtendedEventHook(), nodeMouseEnter: createExtendedEventHook(),
nodeMouseLeave: createExtendedEventHook(), nodeMouseMove: createExtendedEventHook(),
nodeContextMenu: createExtendedEventHook(), nodeMouseLeave: createExtendedEventHook(),
nodeDragStart: createExtendedEventHook(), nodeContextMenu: createExtendedEventHook(),
nodeDrag: createExtendedEventHook(), nodeDragStart: createExtendedEventHook(),
nodeDragStop: createExtendedEventHook(), nodeDrag: createExtendedEventHook(),
nodesInitialized: createExtendedEventHook(), nodeDragStop: createExtendedEventHook(),
miniMapNodeClick: createExtendedEventHook(), nodesInitialized: createExtendedEventHook(),
miniMapNodeDoubleClick: createExtendedEventHook(), miniMapNodeClick: createExtendedEventHook(),
miniMapNodeMouseEnter: createExtendedEventHook(), miniMapNodeDoubleClick: createExtendedEventHook(),
miniMapNodeMouseMove: createExtendedEventHook(), miniMapNodeMouseEnter: createExtendedEventHook(),
miniMapNodeMouseLeave: createExtendedEventHook(), miniMapNodeMouseMove: createExtendedEventHook(),
connect: createExtendedEventHook(), miniMapNodeMouseLeave: createExtendedEventHook(),
connectStart: createExtendedEventHook(), connect: createExtendedEventHook(),
connectEnd: createExtendedEventHook(), connectStart: createExtendedEventHook(),
paneReady: createExtendedEventHook(), connectEnd: createExtendedEventHook(),
move: createExtendedEventHook(), paneReady: createExtendedEventHook(),
moveStart: createExtendedEventHook(), move: createExtendedEventHook(),
moveEnd: createExtendedEventHook(), moveStart: createExtendedEventHook(),
selectionDragStart: createExtendedEventHook(), moveEnd: createExtendedEventHook(),
selectionDrag: createExtendedEventHook(), selectionDragStart: createExtendedEventHook(),
selectionDragStop: createExtendedEventHook(), selectionDrag: createExtendedEventHook(),
selectionContextMenu: createExtendedEventHook(), selectionDragStop: createExtendedEventHook(),
selectionStart: createExtendedEventHook(), selectionContextMenu: createExtendedEventHook(),
selectionEnd: createExtendedEventHook(), selectionStart: createExtendedEventHook(),
viewportChangeStart: createExtendedEventHook(), selectionEnd: createExtendedEventHook(),
viewportChange: createExtendedEventHook(), viewportChangeStart: createExtendedEventHook(),
viewportChangeEnd: createExtendedEventHook(), viewportChange: createExtendedEventHook(),
paneScroll: createExtendedEventHook(), viewportChangeEnd: createExtendedEventHook(),
paneClick: createExtendedEventHook(), paneScroll: createExtendedEventHook(),
paneContextMenu: createExtendedEventHook(), paneClick: createExtendedEventHook(),
paneMouseEnter: createExtendedEventHook(), paneContextMenu: createExtendedEventHook(),
paneMouseMove: createExtendedEventHook(), paneMouseEnter: createExtendedEventHook(),
paneMouseLeave: createExtendedEventHook(), paneMouseMove: createExtendedEventHook(),
edgeContextMenu: createExtendedEventHook(), paneMouseLeave: createExtendedEventHook(),
edgeMouseEnter: createExtendedEventHook(), edgeContextMenu: createExtendedEventHook(),
edgeMouseMove: createExtendedEventHook(), edgeMouseEnter: createExtendedEventHook(),
edgeMouseLeave: createExtendedEventHook(), edgeMouseMove: createExtendedEventHook(),
edgeDoubleClick: createExtendedEventHook(), edgeMouseLeave: createExtendedEventHook(),
edgeClick: createExtendedEventHook(), edgeDoubleClick: createExtendedEventHook(),
edgeUpdateStart: createExtendedEventHook(), edgeClick: createExtendedEventHook(),
edgeUpdate: createExtendedEventHook(), edgeUpdateStart: createExtendedEventHook(),
edgeUpdateEnd: createExtendedEventHook(), edgeUpdate: createExtendedEventHook(),
updateNodeInternals: createExtendedEventHook(), edgeUpdateEnd: createExtendedEventHook(),
error: createExtendedEventHook((err) => warn(err.message)), updateNodeInternals: createExtendedEventHook(),
}) error: createExtendedEventHook((err) => warn(err.message)),
}
}
export function useHooks(emit: (...args: any[]) => void, hooks: Ref<FlowHooks>) { export function useHooks(emit: (...args: any[]) => void, hooks: Ref<FlowHooks>) {
onBeforeMount(() => { onBeforeMount(() => {
+93 -91
View File
@@ -25,114 +25,116 @@ export const defaultEdgeTypes: DefaultEdgeTypes = {
simplebezier: SimpleBezierEdge, simplebezier: SimpleBezierEdge,
} }
const defaultState = (): State => ({ function defaultState(): State {
vueFlowRef: null, return {
viewportRef: null, vueFlowRef: null,
nodes: [], viewportRef: null,
edges: [], nodes: [],
nodeTypes: {}, edges: [],
edgeTypes: {}, nodeTypes: {},
edgeTypes: {},
initialized: false, initialized: false,
dimensions: { dimensions: {
width: 0, width: 0,
height: 0, height: 0,
}, },
viewport: { x: 0, y: 0, zoom: 1 }, viewport: { x: 0, y: 0, zoom: 1 },
d3Zoom: null, d3Zoom: null,
d3Selection: null, d3Selection: null,
d3ZoomHandler: null, d3ZoomHandler: null,
minZoom: 0.5, minZoom: 0.5,
maxZoom: 2, maxZoom: 2,
translateExtent: [ translateExtent: [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY], [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY], [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
], ],
nodeExtent: [ nodeExtent: [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY], [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY], [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
], ],
selectionMode: SelectionMode.Full, selectionMode: SelectionMode.Full,
paneDragging: false, paneDragging: false,
preventScrolling: true, preventScrolling: true,
zoomOnScroll: true, zoomOnScroll: true,
zoomOnPinch: true, zoomOnPinch: true,
zoomOnDoubleClick: true, zoomOnDoubleClick: true,
panOnScroll: false, panOnScroll: false,
panOnScrollSpeed: 0.5, panOnScrollSpeed: 0.5,
panOnScrollMode: PanOnScrollMode.Free, panOnScrollMode: PanOnScrollMode.Free,
panOnDrag: true, panOnDrag: true,
edgeUpdaterRadius: 10, edgeUpdaterRadius: 10,
onlyRenderVisibleElements: false, onlyRenderVisibleElements: false,
defaultViewport: { x: 0, y: 0, zoom: 1 }, defaultViewport: { x: 0, y: 0, zoom: 1 },
nodesSelectionActive: false, nodesSelectionActive: false,
userSelectionActive: false, userSelectionActive: false,
userSelectionRect: null, userSelectionRect: null,
defaultMarkerColor: '#b1b1b7', defaultMarkerColor: '#b1b1b7',
connectionLineStyle: {}, connectionLineStyle: {},
connectionLineType: null, connectionLineType: null,
connectionLineOptions: { connectionLineOptions: {
type: ConnectionLineType.Bezier, type: ConnectionLineType.Bezier,
style: {}, style: {},
}, },
connectionMode: ConnectionMode.Loose, connectionMode: ConnectionMode.Loose,
connectionStartHandle: null, connectionStartHandle: null,
connectionClickStartHandle: null, connectionClickStartHandle: null,
connectionPosition: { x: NaN, y: NaN }, connectionPosition: { x: NaN, y: NaN },
connectionRadius: 20, connectionRadius: 20,
connectOnClick: true, connectOnClick: true,
connectionStatus: null, connectionStatus: null,
isValidConnection: null, isValidConnection: null,
snapGrid: [15, 15], snapGrid: [15, 15],
snapToGrid: false, snapToGrid: false,
edgesUpdatable: false, edgesUpdatable: false,
edgesFocusable: true, edgesFocusable: true,
nodesFocusable: true, nodesFocusable: true,
nodesConnectable: true, nodesConnectable: true,
nodesDraggable: true, nodesDraggable: true,
elementsSelectable: true, elementsSelectable: true,
selectNodesOnDrag: true, selectNodesOnDrag: true,
multiSelectionActive: false, multiSelectionActive: false,
selectionKeyCode: 'Shift', selectionKeyCode: 'Shift',
multiSelectionKeyCode: 'Meta', multiSelectionKeyCode: 'Meta',
zoomActivationKeyCode: 'Meta', zoomActivationKeyCode: 'Meta',
deleteKeyCode: 'Backspace', deleteKeyCode: 'Backspace',
panActivationKeyCode: 'Space', panActivationKeyCode: 'Space',
hooks: createHooks(), hooks: createHooks(),
applyDefault: true, applyDefault: true,
autoConnect: false, autoConnect: false,
fitViewOnInit: false, fitViewOnInit: false,
noDragClassName: 'nodrag', noDragClassName: 'nodrag',
noWheelClassName: 'nowheel', noWheelClassName: 'nowheel',
noPanClassName: 'nopan', noPanClassName: 'nopan',
defaultEdgeOptions: undefined, defaultEdgeOptions: undefined,
elevateEdgesOnSelect: false, elevateEdgesOnSelect: false,
elevateNodesOnSelect: true, elevateNodesOnSelect: true,
autoPanOnNodeDrag: true, autoPanOnNodeDrag: true,
autoPanOnConnect: true, autoPanOnConnect: true,
disableKeyboardA11y: false, disableKeyboardA11y: false,
ariaLiveMessage: '', ariaLiveMessage: '',
__experimentalFeatures: { __experimentalFeatures: {
nestedFlow: false, nestedFlow: false,
}, },
vueFlowVersion: typeof __VUE_FLOW_VERSION__ !== 'undefined' ? __VUE_FLOW_VERSION__ : '-', vueFlowVersion: typeof __VUE_FLOW_VERSION__ !== 'undefined' ? __VUE_FLOW_VERSION__ : '-',
}) }
}
export function useState(opts?: FlowOptions): State { export function useState(opts?: FlowOptions): State {
const state = defaultState() const state = defaultState()
+23 -16
View File
@@ -185,30 +185,37 @@ export function applyChanges<
return elements return elements
} }
export const applyEdgeChanges = (changes: EdgeChange[], edges: GraphEdge[]) => applyChanges(changes, edges) export function applyEdgeChanges(changes: EdgeChange[], edges: GraphEdge[]) {
export const applyNodeChanges = (changes: NodeChange[], nodes: GraphNode[]) => applyChanges(changes, nodes) return applyChanges(changes, edges)
}
export function applyNodeChanges(changes: NodeChange[], nodes: GraphNode[]) {
return applyChanges(changes, nodes)
}
export const createSelectionChange = (id: string, selected: boolean): NodeSelectionChange | EdgeSelectionChange => ({ export function createSelectionChange(id: string, selected: boolean): NodeSelectionChange | EdgeSelectionChange {
id, return {
type: 'select', id,
selected, type: 'select',
}) selected,
}
}
export const createAdditionChange = < export function createAdditionChange<
T extends GraphNode | GraphEdge = GraphNode, T extends GraphNode | GraphEdge = GraphNode,
C extends NodeAddChange | EdgeAddChange = T extends GraphNode ? NodeAddChange : EdgeAddChange, C extends NodeAddChange | EdgeAddChange = T extends GraphNode ? NodeAddChange : EdgeAddChange,
>( >(item: T): C {
item: T, return <C>{
): C =>
<C>{
item, item,
type: 'add', type: 'add',
} }
}
export const createRemoveChange = (id: string): NodeRemoveChange | EdgeRemoveChange => ({ export function createRemoveChange(id: string): NodeRemoveChange | EdgeRemoveChange {
id, return {
type: 'remove', id,
}) type: 'remove',
}
}
export function getSelectionChanges(elements: FlowElements, selectedIds: string[]) { export function getSelectionChanges(elements: FlowElements, selectedIds: string[]) {
return elements.reduce( return elements.reduce(
+3 -1
View File
@@ -1,4 +1,6 @@
export const isMouseEvent = (event: MouseEvent | TouchEvent): event is MouseEvent => 'clientX' in event export function isMouseEvent(event: MouseEvent | TouchEvent): event is MouseEvent {
return 'clientX' in event
}
export function getEventPosition(event: MouseEvent | TouchEvent, bounds?: DOMRect) { export function getEventPosition(event: MouseEvent | TouchEvent, bounds?: DOMRect) {
const isMouseTriggered = isMouseEvent(event) const isMouseTriggered = isMouseEvent(event)
+84 -56
View File
@@ -21,11 +21,13 @@ import type {
XYZPosition, XYZPosition,
} from '~/types' } from '~/types'
export const nodeToRect = (node: GraphNode): Rect => ({ export function nodeToRect(node: GraphNode): Rect {
...(node.computedPosition || { x: 0, y: 0 }), return {
width: node.dimensions.width || 0, ...(node.computedPosition || { x: 0, y: 0 }),
height: node.dimensions.height || 0, width: node.dimensions.width || 0,
}) height: node.dimensions.height || 0,
}
}
export function getOverlappingArea(rectA: Rect, rectB: Rect) { export function getOverlappingArea(rectA: Rect, rectB: Rect) {
const xOverlap = Math.max(0, Math.min(rectA.x + rectA.width, rectB.x + rectB.width) - Math.max(rectA.x, rectB.x)) const xOverlap = Math.max(0, Math.min(rectA.x + rectA.width, rectB.x + rectB.width) - Math.max(rectA.x, rectB.x))
@@ -34,17 +36,23 @@ export function getOverlappingArea(rectA: Rect, rectB: Rect) {
return Math.ceil(xOverlap * yOverlap) return Math.ceil(xOverlap * yOverlap)
} }
export const getDimensions = (node: HTMLElement): Dimensions => ({ export function getDimensions(node: HTMLElement): Dimensions {
width: node.offsetWidth, return {
height: node.offsetHeight, width: node.offsetWidth,
}) height: node.offsetHeight,
}
}
export const clamp = (val: number, min = 0, max = 1) => Math.min(Math.max(val, min), max) export function clamp(val: number, min = 0, max = 1) {
return Math.min(Math.max(val, min), max)
}
export const clampPosition = (position: XYPosition, extent: CoordinateExtent): XYPosition => ({ export function clampPosition(position: XYPosition, extent: CoordinateExtent): XYPosition {
x: clamp(position.x, extent[0][0], extent[1][0]), return {
y: clamp(position.y, extent[0][1], extent[1][1]), x: clamp(position.x, extent[0][0], extent[1][0]),
}) y: clamp(position.y, extent[0][1], extent[1][1]),
}
}
export function getHostForElement(element: HTMLElement): Document { export function getHostForElement(element: HTMLElement): Document {
const doc = element.getRootNode() as Document const doc = element.getRootNode() as Document
@@ -54,19 +62,25 @@ export function getHostForElement(element: HTMLElement): Document {
else return window.document else return window.document
} }
export const isEdge = <Data = ElementData>(element: MaybeElement): element is Edge<Data> => export function isEdge<Data = ElementData>(element: MaybeElement): element is Edge<Data> {
element && 'id' in element && 'source' in element && 'target' in element return element && 'id' in element && 'source' in element && 'target' in element
}
export const isGraphEdge = <Data = ElementData>(element: MaybeElement): element is GraphEdge<Data> => export function isGraphEdge<Data = ElementData>(element: MaybeElement): element is GraphEdge<Data> {
isEdge(element) && 'sourceNode' in element && 'targetNode' in element return isEdge(element) && 'sourceNode' in element && 'targetNode' in element
}
export const isNode = <Data = ElementData>(element: MaybeElement): element is Node<Data> => export function isNode<Data = ElementData>(element: MaybeElement): element is Node<Data> {
element && 'id' in element && !isEdge(element) return element && 'id' in element && !isEdge(element)
}
export const isGraphNode = <Data = ElementData>(element: MaybeElement): element is GraphNode<Data> => export function isGraphNode<Data = ElementData>(element: MaybeElement): element is GraphNode<Data> {
isNode(element) && 'computedPosition' in element return isNode(element) && 'computedPosition' in element
}
export const isRect = (obj: any): obj is Rect => !!obj.width && !!obj.height && !!obj.x && !!obj.y export function isRect(obj: any): obj is Rect {
return !!obj.width && !!obj.height && !!obj.x && !!obj.y
}
export function parseNode(node: Node, defaults: Partial<GraphNode> = {}): GraphNode { export function parseNode(node: Node, defaults: Partial<GraphNode> = {}): GraphNode {
let initialState = defaults let initialState = defaults
@@ -128,27 +142,30 @@ export function parseEdge(edge: Edge, defaults: Partial<GraphEdge> = {}): GraphE
return Object.assign({}, defaults, edge, { id: edge.id.toString() }) as GraphEdge return Object.assign({}, defaults, edge, { id: edge.id.toString() }) as GraphEdge
} }
const getConnectedElements = <T extends Elements = FlowElements>( function getConnectedElements<T extends Elements = FlowElements>(
node: Node, node: Node,
elements: T, elements: T,
dir: 'source' | 'target', dir: 'source' | 'target',
): T extends FlowElements ? GraphNode[] : Node[] => { ): T extends FlowElements ? GraphNode[] : Node[] {
if (!isNode(node)) return [] if (!isNode(node)) return []
const origin = dir === 'source' ? 'target' : 'source' const origin = dir === 'source' ? 'target' : 'source'
const ids = elements.filter((e) => isEdge(e) && e[origin] === node.id).map((e) => isEdge(e) && e[dir]) const ids = elements.filter((e) => isEdge(e) && e[origin] === node.id).map((e) => isEdge(e) && e[dir])
return elements.filter((e) => ids.includes(e.id)) as T extends FlowElements ? GraphNode[] : Node[] return elements.filter((e) => ids.includes(e.id)) as T extends FlowElements ? GraphNode[] : Node[]
} }
export const getOutgoers = <T extends Elements = FlowElements>(node: Node, elements: T) => export function getOutgoers<T extends Elements = FlowElements>(node: Node, elements: T) {
getConnectedElements(node, elements, 'target') return getConnectedElements(node, elements, 'target')
}
export const getIncomers = <T extends Elements = FlowElements>(node: Node, elements: T) => export function getIncomers<T extends Elements = FlowElements>(node: Node, elements: T) {
getConnectedElements(node, elements, 'source') return getConnectedElements(node, elements, 'source')
}
export const getEdgeId = ({ source, sourceHandle, target, targetHandle }: Connection) => export function getEdgeId({ source, sourceHandle, target, targetHandle }: Connection) {
`vueflow__edge-${source}${sourceHandle ?? ''}-${target}${targetHandle ?? ''}` return `vueflow__edge-${source}${sourceHandle ?? ''}-${target}${targetHandle ?? ''}`
}
export const connectionExists = (edge: Edge | Connection, elements: Elements) => export function connectionExists(edge: Edge | Connection, elements: Elements) {
elements.some( return elements.some(
(el) => (el) =>
isEdge(el) && isEdge(el) &&
el.source === edge.source && el.source === edge.source &&
@@ -156,6 +173,7 @@ export const connectionExists = (edge: Edge | Connection, elements: Elements) =>
(el.sourceHandle === edge.sourceHandle || (!el.sourceHandle && !edge.sourceHandle)) && (el.sourceHandle === edge.sourceHandle || (!el.sourceHandle && !edge.sourceHandle)) &&
(el.targetHandle === edge.targetHandle || (!el.targetHandle && !edge.targetHandle)), (el.targetHandle === edge.targetHandle || (!el.targetHandle && !edge.targetHandle)),
) )
}
/** /**
* @deprecated Use store instance and call `addEdges` with template-ref or the one received by `onPaneReady` instead * @deprecated Use store instance and call `addEdges` with template-ref or the one received by `onPaneReady` instead
@@ -249,28 +267,36 @@ export function pointToRendererPoint(
return position return position
} }
const getBoundsOfBoxes = (box1: Box, box2: Box): Box => ({ function getBoundsOfBoxes(box1: Box, box2: Box): Box {
x: Math.min(box1.x, box2.x), return {
y: Math.min(box1.y, box2.y), x: Math.min(box1.x, box2.x),
x2: Math.max(box1.x2, box2.x2), y: Math.min(box1.y, box2.y),
y2: Math.max(box1.y2, box2.y2), x2: Math.max(box1.x2, box2.x2),
}) y2: Math.max(box1.y2, box2.y2),
}
}
export const rectToBox = ({ x, y, width, height }: Rect): Box => ({ export function rectToBox({ x, y, width, height }: Rect): Box {
x, return {
y, x,
x2: x + width, y,
y2: y + height, x2: x + width,
}) y2: y + height,
}
}
export const boxToRect = ({ x, y, x2, y2 }: Box): Rect => ({ export function boxToRect({ x, y, x2, y2 }: Box): Rect {
x, return {
y, x,
width: x2 - x, y,
height: y2 - y, width: x2 - x,
}) height: y2 - y,
}
}
export const getBoundsofRects = (rect1: Rect, rect2: Rect) => boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2))) export function getBoundsofRects(rect1: Rect, rect2: Rect) {
return boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2)))
}
export function getRectOfNodes(nodes: GraphNode[]) { export function getRectOfNodes(nodes: GraphNode[]) {
const box = nodes.reduce( const box = nodes.reduce(
@@ -288,10 +314,12 @@ export function getRectOfNodes(nodes: GraphNode[]) {
return boxToRect(box) return boxToRect(box)
} }
export const graphPosToZoomedPos = ({ x, y }: XYPosition, { x: tx, y: ty, zoom: tScale }: ViewportTransform): XYPosition => ({ export function graphPosToZoomedPos({ x, y }: XYPosition, { x: tx, y: ty, zoom: tScale }: ViewportTransform): XYPosition {
x: x * tScale + tx, return {
y: y * tScale + ty, x: x * tScale + tx,
}) y: y * tScale + ty,
}
}
export function getNodesInside( export function getNodesInside(
nodes: GraphNode[], nodes: GraphNode[],
+3 -1
View File
@@ -1,6 +1,8 @@
import type { Actions, Connection, Edge, GraphEdge, GraphNode, Node, State } from '~/types' import type { Actions, Connection, Edge, GraphEdge, GraphNode, Node, State } from '~/types'
export const isDef = <T>(val: T): val is NonNullable<T> => typeof unref(val) !== 'undefined' export function isDef<T>(val: T): val is NonNullable<T> {
return typeof unref(val) !== 'undefined'
}
export function addEdgeToStore(edgeParams: Edge | Connection, edges: Edge[], onError: State['hooks']['error']['trigger']) { export function addEdgeToStore(edgeParams: Edge | Connection, edges: Edge[], onError: State['hooks']['error']['trigger']) {
if (!edgeParams.source || !edgeParams.target) { if (!edgeParams.source || !edgeParams.target) {
+6 -6
View File
@@ -152,36 +152,36 @@ watchEffect(
{ flush: 'post' }, { flush: 'post' },
) )
const onSvgClick = (event: MouseEvent) => { function onSvgClick(event: MouseEvent) {
const [x, y] = pointer(event) const [x, y] = pointer(event)
emit('click', { event, position: { x, y } }) emit('click', { event, position: { x, y } })
} }
const onNodeClick = (event: MouseEvent, node: GraphNode) => { function onNodeClick(event: MouseEvent, node: GraphNode) {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) } const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) }
emits.miniMapNodeClick(param) emits.miniMapNodeClick(param)
emit('nodeClick', param) emit('nodeClick', param)
} }
const onNodeDblClick = (event: MouseEvent, node: GraphNode) => { function onNodeDblClick(event: MouseEvent, node: GraphNode) {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) } const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) }
emits.miniMapNodeDoubleClick(param) emits.miniMapNodeDoubleClick(param)
emit('nodeDblclick', param) emit('nodeDblclick', param)
} }
const onNodeMouseEnter = (event: MouseEvent, node: GraphNode) => { function onNodeMouseEnter(event: MouseEvent, node: GraphNode) {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) } const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) }
emits.miniMapNodeMouseEnter(param) emits.miniMapNodeMouseEnter(param)
emit('nodeMouseenter', param) emit('nodeMouseenter', param)
} }
const onNodeMouseMove = (event: MouseEvent, node: GraphNode) => { function onNodeMouseMove(event: MouseEvent, node: GraphNode) {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) } const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) }
emits.miniMapNodeMouseMove(param) emits.miniMapNodeMouseMove(param)
emit('nodeMousemove', param) emit('nodeMousemove', param)
} }
const onNodeMouseLeave = (event: MouseEvent, node: GraphNode) => { function onNodeMouseLeave(event: MouseEvent, node: GraphNode) {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) } const param = { event, node, connectedEdges: getConnectedEdges([node], edges.value) }
emits.miniMapNodeMouseLeave(param) emits.miniMapNodeMouseLeave(param)
emit('nodeMouseleave', param) emit('nodeMouseleave', param)
@@ -13,7 +13,7 @@ export interface PointInfo {
position: Position position: Position
} }
export const createGrid = (graph: GraphBoundingBox, nodes: NodeBoundingBox[], source: PointInfo, target: PointInfo) => { export function createGrid(graph: GraphBoundingBox, nodes: NodeBoundingBox[], source: PointInfo, target: PointInfo) {
const { xMin, yMin, width, height } = graph const { xMin, yMin, width, height } = graph
// Create a grid representation of the graph box, where each cell is // Create a grid representation of the graph box, where each cell is
@@ -4,13 +4,13 @@ import type { XYPosition } from '@vue-flow/core'
* Draws an SVG path from a list of points, using straight lines. * Draws an SVG path from a list of points, using straight lines.
*/ */
const getMidPoint = (Ax: number, Ay: number, Bx: number, By: number) => { function getMidPoint(Ax: number, Ay: number, Bx: number, By: number) {
const Zx = (Ax - Bx) / 2 + Bx const Zx = (Ax - Bx) / 2 + Bx
const Zy = (Ay - By) / 2 + By const Zy = (Ay - By) / 2 + By
return [Zx, Zy] return [Zx, Zy]
} }
export const drawStraightLinePath = (source: XYPosition, target: XYPosition, path: number[][]) => { export function drawStraightLinePath(source: XYPosition, target: XYPosition, path: number[][]) {
let svgPathString = `M ${source.x}, ${source.y} ` let svgPathString = `M ${source.x}, ${source.y} `
path.forEach((point) => { path.forEach((point) => {
@@ -23,7 +23,7 @@ export const drawStraightLinePath = (source: XYPosition, target: XYPosition, pat
return svgPathString return svgPathString
} }
const quadraticBezierCurve = (points: number[][]) => { function quadraticBezierCurve(points: number[][]) {
const X = 0 const X = 0
const Y = 1 const Y = 1
let point = points[0] let point = points[0]
@@ -49,7 +49,7 @@ const quadraticBezierCurve = (points: number[][]) => {
/** /**
* Draws a SVG path from a list of points, using rounded lines. * Draws a SVG path from a list of points, using rounded lines.
*/ */
export const drawSmoothLinePath = (source: XYPosition, target: XYPosition, path: number[][]) => { export function drawSmoothLinePath(source: XYPosition, target: XYPosition, path: number[][]) {
const points = [[source.x, source.y], ...path, [target.x, target.y]] const points = [[source.x, source.y], ...path, [target.x, target.y]]
return quadraticBezierCurve(points) return quadraticBezierCurve(points)
} }
@@ -12,7 +12,7 @@ declare module 'pathfinding' {
} }
} }
export const generatePath = (grid: Grid, start: XYPosition, end: XYPosition): number[][] => { export function generatePath(grid: Grid, start: XYPosition, end: XYPosition): number[][] {
const finder = new AStarFinder({ const finder = new AStarFinder({
diagonalMovement: DiagonalMovement.Always, diagonalMovement: DiagonalMovement.Always,
allowDiagonal: true, allowDiagonal: true,
@@ -34,7 +34,7 @@ export interface GraphBoundingBox {
* @param roundTo If the coordinates should be rounded to this nearest integer * @param roundTo If the coordinates should be rounded to this nearest integer
* @returns Graph and nodes bounding boxes. * @returns Graph and nodes bounding boxes.
*/ */
export const getBoundingBoxes = (storeNodes: GraphNode[], nodePadding = 0, graphPadding = 0, roundTo = 0) => { export function getBoundingBoxes(storeNodes: GraphNode[], nodePadding = 0, graphPadding = 0, roundTo = 0) {
// Guarantee that the given parameters are positive integers // Guarantee that the given parameters are positive integers
nodePadding = Math.max(Math.round(nodePadding), 0) nodePadding = Math.max(Math.round(nodePadding), 0)
graphPadding = Math.max(Math.round(graphPadding), 0) graphPadding = Math.max(Math.round(graphPadding), 0)
@@ -3,7 +3,7 @@ import type { Position, XYPosition } from '@vue-flow/core'
type Direction = 'top' | 'bottom' | 'left' | 'right' type Direction = 'top' | 'bottom' | 'left' | 'right'
export const getNextPointFromPosition = (point: XYPosition, position: Direction): XYPosition => { export function getNextPointFromPosition(point: XYPosition, position: Direction): XYPosition {
switch (position) { switch (position) {
case 'top': case 'top':
return { x: point.x, y: point.y - 1 } return { x: point.x, y: point.y - 1 }
@@ -21,7 +21,7 @@ export const getNextPointFromPosition = (point: XYPosition, position: Direction)
* walkable area, by adding a walkable path in the direction of the point's * walkable area, by adding a walkable path in the direction of the point's
* Position. * Position.
*/ */
export const guaranteeWalkablePath = (grid: Grid, point: XYPosition, position: Position) => { export function guaranteeWalkablePath(grid: Grid, point: XYPosition, position: Position) {
let node = grid.getNodeAt(point.x, point.y) let node = grid.getNodeAt(point.x, point.y)
while (!node.walkable) { while (!node.walkable) {
grid.setWalkableAt(node.x, node.y, true) grid.setWalkableAt(node.x, node.y, true)
@@ -22,7 +22,7 @@ const gridRatio = 10
* We avoid setting nodes in the border of the grid (x=0 or y=0), so there's * We avoid setting nodes in the border of the grid (x=0 or y=0), so there's
* always a "walkable" area around the grid. * always a "walkable" area around the grid.
*/ */
export const graphToGridPoint = (graphPoint: XYPosition, smallestX: number, smallestY: number): XYPosition => { export function graphToGridPoint(graphPoint: XYPosition, smallestX: number, smallestY: number): XYPosition {
let x = graphPoint.x / gridRatio let x = graphPoint.x / gridRatio
let y = graphPoint.y / gridRatio let y = graphPoint.y / gridRatio
@@ -60,7 +60,7 @@ export const graphToGridPoint = (graphPoint: XYPosition, smallestX: number, smal
* Converts a grid point back to a graph point, using the reverse logic of * Converts a grid point back to a graph point, using the reverse logic of
* graphToGridPoint. * graphToGridPoint.
*/ */
export const gridToGraphPoint = (gridPoint: XYPosition, smallestX: number, smallestY: number): XYPosition => { export function gridToGraphPoint(gridPoint: XYPosition, smallestX: number, smallestY: number): XYPosition {
let x = gridPoint.x * gridRatio let x = gridPoint.x * gridRatio
let y = gridPoint.y * gridRatio let y = gridPoint.y * gridRatio
+9 -3
View File
@@ -1,5 +1,11 @@
export const round = (x: number, multiple = 10) => Math.round(x / multiple) * multiple export function round(x: number, multiple = 10) {
return Math.round(x / multiple) * multiple
}
export const roundDown = (x: number, multiple = 10) => Math.floor(x / multiple) * multiple export function roundDown(x: number, multiple = 10) {
return Math.floor(x / multiple) * multiple
}
export const roundUp = (x: number, multiple = 10) => Math.ceil(x / multiple) * multiple export function roundUp(x: number, multiple = 10) {
return Math.ceil(x / multiple) * multiple
}
+10 -6
View File
@@ -7,7 +7,7 @@ import { mount } from 'cypress/vue'
import { VueFlow } from '@vue-flow/core' import { VueFlow } from '@vue-flow/core'
import type { FlowProps } from '@vue-flow/core' import type { FlowProps } from '@vue-flow/core'
const mountVueFlow = (props?: FlowProps, attrs?: Record<string, any>, slots?: Record<string, any>) => { function mountVueFlow(props?: FlowProps, attrs?: Record<string, any>, slots?: Record<string, any>) {
cy.mount(VueFlow as any, { cy.mount(VueFlow as any, {
props: { props: {
id: 'test', id: 'test',
@@ -26,11 +26,15 @@ const mountVueFlow = (props?: FlowProps, attrs?: Record<string, any>, slots?: Re
}) })
} }
const useViewPort = () => cy.get('.vue-flow__viewport') function useViewPort() {
return cy.get('.vue-flow__viewport')
}
const useTransformationPane = () => cy.get('.vue-flow__transformationpane') function useTransformationPane() {
return cy.get('.vue-flow__transformationpane')
}
const retry = (assertion: Function, { interval = 20, timeout = 1000 } = {}) => { function retry(assertion: Function, { interval = 20, timeout = 1000 } = {}) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const startTime = Date.now() const startTime = Date.now()
@@ -48,7 +52,7 @@ const retry = (assertion: Function, { interval = 20, timeout = 1000 } = {}) => {
}) })
} }
const dragConnection = (from: string, to: string) => { function dragConnection(from: string, to: string) {
cy.window().then((win) => { cy.window().then((win) => {
const sourceHandle = cy.get(`[data-nodeid="${from}"].source`) const sourceHandle = cy.get(`[data-nodeid="${from}"].source`)
const targetHandle = cy.get(`[data-nodeid="${to}"].target`) const targetHandle = cy.get(`[data-nodeid="${to}"].target`)
@@ -78,7 +82,7 @@ const dragConnection = (from: string, to: string) => {
}) })
} }
const connect = (from: string, to: string) => { function connect(from: string, to: string) {
const sourceHandle = cy.get(`[data-nodeid="${from}"].source`) const sourceHandle = cy.get(`[data-nodeid="${from}"].source`)
const targetHandle = cy.get(`[data-nodeid="${to}"].target`) const targetHandle = cy.get(`[data-nodeid="${to}"].target`)
+1
View File
@@ -4,6 +4,7 @@ module.exports = {
rules: { rules: {
'vue/no-setup-props-destructure': 0, 'vue/no-setup-props-destructure': 0,
'no-console': 0, 'no-console': 0,
'unused-imports/no-unused-vars': 0,
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
'prettier/prettier': [ 'prettier/prettier': [
'error', 'error',