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`
})
const files: Record<string, typeof imports[keyof typeof imports]> = {}
const files: Record<string, (typeof imports)[keyof typeof imports]> = {}
const imports = exampleImports[props.example]
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
* Changes should always be reflected on the graph reactively, without the need to overwrite the elements
*/
const updatePos = () =>
elements.value.forEach((el) => {
function updatePos() {
return elements.value.forEach((el) => {
if (isNode(el)) {
el.position = {
x: Math.random() * 400,
@@ -49,18 +49,25 @@ const updatePos = () =>
}
}
})
}
/**
* 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)
*/
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>
<template>
@@ -1,5 +1,5 @@
<script setup>
const props = defineProps({
defineProps({
sourceX: {
type: Number,
required: true,
+10 -6
View File
@@ -18,23 +18,27 @@ const bgName = ref('AYAME')
const connectionLineStyle = { stroke: '#fff' }
// minimap stroke color functions
const nodeStroke = (n) => {
function nodeStroke(n) {
if (n.type === 'input') return '#0041d0'
if (n.type === 'custom') return presets.sumi
if (n.type === 'output') return '#ff0072'
return '#eee'
}
const nodeColor = (n) => {
function nodeColor(n) {
if (n.type === 'custom') return bgColor.value
return '#fff'
}
// output labels
const outputColorLabel = () => h('div', {}, bgColor.value)
const outputNameLabel = () => h('div', {}, bgName.value)
function outputColorLabel() {
return h('div', {}, bgColor.value)
}
function outputNameLabel() {
return h('div', {}, bgName.value)
}
const onChange = (color) => {
function onChange(color) {
gradient.value = false
bgColor.value = color.value
bgName.value = color.name
@@ -42,7 +46,7 @@ const onChange = (color) => {
findNode('3').hidden = false
}
const onGradient = () => {
function onGradient() {
gradient.value = true
bgColor.value = null
bgName.value = 'gradient'
@@ -12,11 +12,11 @@ const props = defineProps({
const emit = defineEmits(['change', 'gradient'])
const onSelect = (color) => {
function onSelect(color) {
emit('change', color)
}
const onGradient = () => {
function onGradient() {
emit('gradient')
}
+6 -4
View File
@@ -4,9 +4,11 @@ import { nextTick, watch } from 'vue'
import Sidebar from './Sidebar.vue'
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: [
{
id: '1',
@@ -17,7 +19,7 @@ const { findNode, onConnect, nodes, edges, addEdges, addNodes, viewport, project
],
})
const onDragOver = (event) => {
function onDragOver(event) {
event.preventDefault()
if (event.dataTransfer) {
@@ -27,7 +29,7 @@ const onDragOver = (event) => {
onConnect((params) => addEdges([params]))
const onDrop = (event) => {
function onDrop(event) {
const type = event.dataTransfer?.getData('application/vueflow')
const { left, top } = vueFlowRef.value.getBoundingClientRect()
+1 -1
View File
@@ -1,5 +1,5 @@
<script setup>
const onDragStart = (event, nodeType) => {
function onDragStart(event, nodeType) {
if (event.dataTransfer) {
event.dataTransfer.setData('application/vueflow', nodeType)
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 { 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]))
const addRandomNode = () => {
function addRandomNode() {
const nodeId = (nodes.value.length + 1).toString()
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
* 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 elements = ref(initialElements)
+6 -3
View File
@@ -12,10 +12,12 @@ const elements = ref([
{ 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 = () =>
elements.value.forEach((el) => {
function updatePos() {
return elements.value.forEach((el) => {
if (isNode(el)) {
el.position = {
x: Math.random() * 400,
@@ -23,6 +25,7 @@ const updatePos = () =>
}
}
})
}
</script>
<template>
+1 -1
View File
@@ -5,7 +5,7 @@ import { Controls } from '@vue-flow/controls'
import { MiniMap } from '@vue-flow/minimap'
import { onMounted } from 'vue'
const { onConnect, nodes, edges, addEdges, addNodes } = useVueFlow({
const { onConnect, addEdges, addNodes } = useVueFlow({
fitViewOnInit: true,
// set this to true so edges get elevated when selected, defaults to false
elevateEdgesOnSelect: true,
@@ -5,11 +5,11 @@ const flowKey = 'example-flow'
const { nodes, addNodes, setNodes, setEdges, dimensions, setTransform, toObject } = useVueFlow()
const onSave = () => {
function onSave() {
localStorage.setItem(flowKey, JSON.stringify(toObject()))
}
const onRestore = () => {
function onRestore() {
const flow = JSON.parse(localStorage.getItem(flowKey))
if (flow) {
@@ -20,7 +20,7 @@ const onRestore = () => {
}
}
const onAdd = () => {
function onAdd() {
const id = nodes.value.length + 1
const newNode = {
+9 -8
View File
@@ -6,21 +6,22 @@ import { nextTick, ref } from 'vue'
import { getElements } from './utils.js'
const { nodes, edges } = getElements(15, 15)
const elements = ref([...nodes, ...edges])
const { onPaneReady, dimensions, onNodeClick, getEdges, fitView } = useVueFlow()
const { onPaneReady, dimensions, fitView } = useVueFlow()
onPaneReady((i) => {
i.fitView({
padding: 0.2,
})
onPaneReady(({ fitView, getElements }) => {
fitView({ 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) => {
if (isNode(el)) {
el.position = {
@@ -11,7 +11,7 @@ const props = defineProps({
const { animation, transition, teleport, onClick } = useTeleport(props.id)
const changeAnimation = () => {
function changeAnimation() {
animation.value = animation.value === 'fade' ? 'shrink' : 'fade'
}
</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
* Otherwise edges do not connect properly
*/
export const useTeleport = (id) => {
export function useTeleport(id) {
const animation = ref('fade')
const transition = ref(false)
const teleport = ref(null)
+12 -4
View File
@@ -26,13 +26,21 @@ const elements = ref([
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>
<template>
+1 -1
View File
@@ -17,7 +17,7 @@ const opts = reactive({
hidden: false,
})
const updateNode = () => {
function updateNode() {
const node = getNode.value('1')
node.label = opts.label.trim() !== '' ? opts.label : defaultLabel
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' },
])
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)
addEdge(params, elements.value)
}
+2 -2
View File
@@ -8,12 +8,12 @@ import Additional from './flows/Additional.vue'
const el = ref<HTMLDivElement>()
const instances: VueFlowStore[] = []
const onLoad = (instance: VueFlowStore) => {
function onLoad(instance: VueFlowStore) {
instances.push(instance)
instance.fitView()
}
const fitViews = () => {
function fitViews() {
instances.forEach((i) => i.fitView())
}
+3 -3
View File
@@ -226,7 +226,7 @@ function setElements() {
const { stop } = useResizeObserver(el, useDebounceFn(setElements, 5))
onBeforeUnmount(stop)
const scrollTo = () => {
function scrollTo() {
const el = document.getElementById('acknowledgement')
if (el) {
el.scrollIntoView({ behavior: 'smooth' })
@@ -235,7 +235,7 @@ const scrollTo = () => {
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--) {
const j = Math.floor(Math.random() * (i + 1))
;[a[i], a[j]] = [a[j], a[i]]
@@ -243,7 +243,7 @@ const shuffle = (a: any[]) => {
return a
}
const createAnimationDurations = () => {
function createAnimationDurations() {
return animationClassNames.map((className) => {
const duration = 5 + Math.random() * 5
+3 -1
View File
@@ -59,7 +59,9 @@ watch(
{ 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) => {
switch (node.id) {
+2 -2
View File
@@ -1,6 +1,6 @@
import confetti from 'canvas-confetti'
export const fireworks = (colors?: string[]) => {
export function fireworks(colors?: string[]) {
return new Promise((resolve) => {
const duration = 15 * 1000
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) => {
const end = Date.now() + 2 * 1000
+30 -15
View File
@@ -12,35 +12,50 @@ interface RGBNodeProps extends NodeProps {
blue: number
}
}
const props = defineProps<RGBNodeProps>()
const emit = defineEmits(['change'])
let color = 'red'
switch (props.data?.color) {
case 'r':
color = 'red'
break
case 'g':
color = 'green'
break
case 'b':
color = 'blue'
break
const currentColor = computed(() => {
let color
switch (props.data?.color) {
case 'r':
color = 'red'
break
case 'g':
color = 'green'
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>
<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="text-md" :style="{ color }">{{ `${color} Amount`.toUpperCase() }}</div>
<div class="text-md" :style="{ color: currentColor }">{{ `${currentColor} Amount`.toUpperCase() }}</div>
<input
v-model="props.amount[color]"
:model-value="amount[currentColor]"
class="slider nodrag"
:style="{ '--color': color }"
:style="{ '--color': currentColor }"
type="range"
min="0"
max="255"
@input="onChange"
/>
<Handle type="source" :position="Position.Right" :style="{ backgroundColor: color }" />
</div>
</template>
+2 -2
View File
@@ -17,7 +17,7 @@ function capitalize(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
const typedocSidebarEntries = (): DefaultTheme.SidebarGroup[] => {
function typedocSidebarEntries(): DefaultTheme.SidebarGroup[] {
const filePath = resolve(__dirname, '../typedocs')
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 [
{
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
* Changes should always be reflected on the graph reactively, without the need to overwrite the elements
*/
const updatePos = () =>
elements.value.forEach((el) => {
function updatePos() {
return elements.value.forEach((el) => {
console.log(el, elements.value)
if (isNode(el)) {
el.position = {
@@ -47,18 +47,23 @@ const updatePos = () =>
}
}
})
}
/**
* 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)
*/
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
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
* Changes should always be reflected on the graph reactively, without the need to overwrite the elements
*/
const updatePos = () =>
elements.value.forEach((el) => {
function updatePos() {
return elements.value.forEach((el) => {
console.log(el, elements.value)
if (isNode(el)) {
el.position = {
@@ -47,18 +47,23 @@ const updatePos = () =>
}
}
})
}
/**
* 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)
*/
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
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 onChange = (event: Event) => {
function onChange(event: Event) {
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)
onConnect((params) => addEdges([params]))
const updatePos = () =>
elements.value.forEach((el) => {
function updatePos() {
return elements.value.forEach((el) => {
if (isNode(el)) {
el.position = {
x: Math.random() * 400,
@@ -32,10 +32,17 @@ const updatePos = () =>
}
}
})
}
const logToObject = () => console.log(toObject())
const resetTransform = () => setTransform({ x: 0, y: 0, zoom: 1 })
const toggleclass = () => elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light'))
function logToObject() {
return console.log(toObject())
}
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>
<template>
+5 -3
View File
@@ -4,7 +4,9 @@ import { VueFlow, useVueFlow } from '@vue-flow/core'
import Sidebar from './Sidebar.vue'
let id = 0
const getId = () => `dndnode_${id++}`
function getId() {
return `dndnode_${id++}`
}
const { onConnect, addEdges, addNodes, project } = useVueFlow({
nodes: [
@@ -16,7 +18,7 @@ const { onConnect, addEdges, addNodes, project } = useVueFlow({
},
],
})
const onDragOver = (event: DragEvent) => {
function onDragOver(event: DragEvent) {
event.preventDefault()
if (event.dataTransfer) {
event.dataTransfer.dropEffect = 'move'
@@ -27,7 +29,7 @@ const wrapper = ref()
onConnect((params) => addEdges([params]))
const onDrop = (event: DragEvent) => {
function onDrop(event: DragEvent) {
const type = event.dataTransfer?.getData('application/vueflow')
const flowbounds = wrapper.value.$el.getBoundingClientRect()
+1 -1
View File
@@ -1,5 +1,5 @@
<script lang="ts" setup>
const onDragStart = (event: DragEvent, nodeType: string) => {
function onDragStart(event: DragEvent, nodeType: string) {
if (event.dataTransfer) {
event.dataTransfer.setData('application/vueflow', nodeType)
event.dataTransfer.effectAllowed = 'move'
+3 -1
View File
@@ -50,7 +50,9 @@ const offsets = [
]
let id = 0
const getNodeId = () => (id++).toString()
function getNodeId() {
return (id++).toString()
}
export function getElements(): Elements {
const initialElements = []
+1 -1
View File
@@ -12,7 +12,7 @@ onConnect((params) => addEdges([params]))
onPaneReady((flowInstance) => console.log('flow loaded:', flowInstance))
onNodeDragStop((node) => console.log('drag stop', node))
const addRandomNode = () => {
function addRandomNode() {
const nodeId = (nodes.value.length + 1).toString()
const newNode: Node = {
id: nodeId,
@@ -18,7 +18,7 @@ const nodeExtent: CoordinateExtent = [
const elements = ref<Elements>(initialElements)
const onLayout = (direction: string) => {
function onLayout(direction: string) {
const isHorizontal = direction === 'LR'
dagreGraph.setGraph({ rankdir: direction })
@@ -29,7 +29,7 @@ onConnect((params) => addEdges([params]))
onPaneReady((instance) => instance.fitView())
const changeType = () => {
function changeType() {
elements.value.forEach((el) => {
if (isEdge(el) || el.type === 'input') return
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 { MiniMap } from '@vue-flow/minimap'
const onNodeDragStart = (e: FlowEvents['nodeDragStart']) => console.log('drag start', e)
const onNodeDrag = (e: FlowEvents['nodeDrag']) => console.log('drag', e)
const onNodeDragStop = (e: FlowEvents['nodeDragStop']) => console.log('drag stop', e)
const onNodeDoubleClick = (e: FlowEvents['nodeDoubleClick']) => console.log('node double click', e)
const onPaneClick = (e: FlowEvents['paneClick']) => console.log('pane click', e)
const onPaneScroll = (e: FlowEvents['paneScroll']) => console.log('pane scroll', e)
const onPaneContextMenu = (e: FlowEvents['paneContextMenu']) => console.log('pane context menu', e)
const onSelectionDrag = (e: FlowEvents['selectionDrag']) => console.log('selection drag', e)
const onSelectionDragStart = (e: FlowEvents['selectionDragStart']) => console.log('selection drag start', e)
const onSelectionDragStop = (e: FlowEvents['selectionDragStop']) => console.log('selection drag stop', e)
const onSelectionContextMenu = (e: FlowEvents['selectionContextMenu']) => console.log('selection context menu', e)
const onLoad = (flowInstance: VueFlowStore) => {
function onNodeDragStart(e: FlowEvents['nodeDragStart']) {
return console.log('drag start', e)
}
function onNodeDrag(e: FlowEvents['nodeDrag']) {
return console.log('drag', e)
}
function onNodeDragStop(e: FlowEvents['nodeDragStop']) {
return console.log('drag stop', e)
}
function onNodeDoubleClick(e: FlowEvents['nodeDoubleClick']) {
return console.log('node double click', e)
}
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)
flowInstance.fitView()
}
const onMoveEnd = (e: FlowEvents['moveEnd']) => console.log('zoom/move end', e.flowTransform)
const onEdgeContextMenu = (e: FlowEvents['edgeContextMenu']) => console.log('edge context menu', e)
const onEdgeMouseEnter = (e: FlowEvents['edgeMouseEnter']) => console.log('edge mouse enter', e)
const onEdgeMouseMove = (e: FlowEvents['edgeMouseMove']) => console.log('edge mouse move', e)
const onEdgeMouseLeave = (e: FlowEvents['edgeMouseLeave']) => console.log('edge mouse leave', e)
const onEdgeDoubleClick = (e: FlowEvents['edgeDoubleClick']) => console.log('edge double click', e)
function onMoveEnd(e: FlowEvents['moveEnd']) {
return console.log('zoom/move end', e.flowTransform)
}
function onEdgeContextMenu(e: FlowEvents['edgeContextMenu']) {
return console.log('edge context menu', 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 = [
{
@@ -85,7 +119,7 @@ const initialElements: Elements = [
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.type === 'input') return '#0041d0'
if (n.type === 'output') return '#ff0072'
@@ -94,7 +128,7 @@ const nodeStrokeColor = (n: Node): string => {
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
return '#fff'
@@ -7,7 +7,9 @@ import '@vue-flow/controls/dist/style.css'
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 = [
{ 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'
const { nodesSelectionActive, addSelectedNodes, getNodes, viewport } = useVueFlow()
const selectAll = () => {
function selectAll() {
addSelectedNodes(getNodes.value)
nodesSelectionActive.value = true
}
+8 -6
View File
@@ -1,5 +1,4 @@
<script lang="ts" setup>
import { templateRef } from '@vueuse/core'
import type { Elements, VueFlowStore } from '@vue-flow/core'
import { VueFlow } from '@vue-flow/core'
import RGBNode from './RGBNode.vue'
@@ -10,6 +9,7 @@ interface Colors {
green: number
blue: number
}
const elements = ref<Elements>([
{ id: '1', type: 'rgb', data: { color: 'r' }, position: { x: -25, y: 50 } },
{ 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 },
])
const el = templateRef<HTMLDivElement>('page', null)
const onLoad = (flowInstance: VueFlowStore) => {
function onLoad(flowInstance: VueFlowStore) {
flowInstance.fitView({ padding: 1 })
}
const color = ref<Colors>({
red: 100,
green: 150,
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>
<template>
<div ref="page" class="demo-flow">
<div class="demo-flow">
<VueFlow v-model="elements" @pane-ready="onLoad">
<template #node-rgb="props">
<RGBNode v-bind="props" :amount="color" @change="onChange" />
+6 -4
View File
@@ -10,15 +10,17 @@ const state = useStorage<FlowExportObject>(flowKey, {
zoom: 1,
})
const getNodeId = () => `randomnode_${+new Date()}`
function getNodeId() {
return `randomnode_${+new Date()}`
}
const { addNodes, setNodes, setEdges, toObject, dimensions, setTransform } = useVueFlow()
const onSave = () => {
function onSave() {
state.value = toObject()
}
const onRestore = () => {
function onRestore() {
const flow: FlowExportObject | null = state.value
if (flow) {
@@ -32,7 +34,7 @@ const onRestore = () => {
}
}
const onAdd = () => {
function onAdd() {
const newNode = {
id: `random_node-${getNodeId()}`,
label: 'Added node',
+4 -2
View File
@@ -17,9 +17,11 @@ onPaneReady((i) => {
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) => {
if (isNode(el)) {
el.position = {
@@ -30,13 +30,21 @@ const { updateEdge } = useVueFlow()
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>
<template>
@@ -15,7 +15,7 @@ const opts = reactive({
hidden: false,
})
const updateNode = () => {
function updateNode() {
elements.value.forEach((el) => {
if (el.id === '1') {
// 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' },
],
})
const onLoad = (flowInstance: VueFlowStore) => flowInstance.fitView()
const onConnectStart = ({ nodeId, handleType }: OnConnectStartParams) => console.log('on connect start', { nodeId, handleType })
const onConnectEnd = (event: MouseEvent) => console.log('on connect end', event)
function onLoad(flowInstance: VueFlowStore) {
return flowInstance.fitView()
}
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)
addEdges([params])
}
+4 -4
View File
@@ -28,22 +28,22 @@ const { nodesDraggable, nodesConnectable, elementsSelectable, setInteractive, zo
const isInteractive = computed(() => nodesDraggable && nodesConnectable && elementsSelectable)
const onZoomInHandler = () => {
function onZoomInHandler() {
zoomIn()
emit('zoomIn')
}
const onZoomOutHandler = () => {
function onZoomOutHandler() {
zoomOut()
emit('zoomOut')
}
const onFitViewHandler = () => {
function onFitViewHandler() {
fitView(fitViewParams)
emit('fitView')
}
const onInteractiveChangeHandler = () => {
function onInteractiveChangeHandler() {
setInteractive(!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
}`
const patchSlots = async () => {
async function patchSlots() {
const fileContents = await content(filePath)
const patchedFileContents = fileContents.replace(typeImportsString, patchedTypeImports).replace(unpatchedSlots, patchedSlots)
@@ -8,13 +8,13 @@ interface Props extends HTMLAttributes {
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.Right) return x + shift
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.Bottom) return y + shift
return y
@@ -22,7 +22,7 @@ const handleDirections = {
[Position.Bottom]: { x: 0, y: 1 },
}
const getDirection = ({
function getDirection({
source,
sourcePosition = Position.Bottom,
target,
@@ -30,14 +30,16 @@ const getDirection = ({
source: XYPosition
sourcePosition: Position
target: XYPosition
}): XYPosition => {
}): XYPosition {
if (sourcePosition === Position.Left || sourcePosition === Position.Right) {
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 }
}
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
// 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'
const createEdgeHooks = () => ({
doubleClick: createExtendedEventHook(),
click: createExtendedEventHook(),
mouseEnter: createExtendedEventHook(),
mouseMove: createExtendedEventHook(),
mouseLeave: createExtendedEventHook(),
contextMenu: createExtendedEventHook(),
updateStart: createExtendedEventHook(),
update: createExtendedEventHook(),
updateEnd: createExtendedEventHook(),
})
function createEdgeHooks() {
return {
doubleClick: createExtendedEventHook(),
click: createExtendedEventHook(),
mouseEnter: createExtendedEventHook(),
mouseMove: createExtendedEventHook(),
mouseLeave: createExtendedEventHook(),
contextMenu: createExtendedEventHook(),
updateStart: createExtendedEventHook(),
update: createExtendedEventHook(),
updateEnd: createExtendedEventHook(),
}
}
export default function useEdgeHooks(edge: GraphEdge, emits: VueFlowStore['emits']): { emit: EdgeEventsEmit; on: EdgeEventsOn } {
const edgeHooks = createEdgeHooks()
+3 -1
View File
@@ -11,7 +11,9 @@ interface UseHandleProps {
onEdgeUpdateEnd?: (event: MouseTouchEvent) => void
}
const alwaysValid = () => true
function alwaysValid() {
return true
}
export default function useHandle({
handleId: _handleId,
+13 -11
View File
@@ -1,16 +1,18 @@
import type { GraphNode, NodeEventsEmit, NodeEventsOn, VueFlowStore } from '~/types'
const createNodeHooks = () => ({
doubleClick: createExtendedEventHook(),
click: createExtendedEventHook(),
mouseEnter: createExtendedEventHook(),
mouseMove: createExtendedEventHook(),
mouseLeave: createExtendedEventHook(),
contextMenu: createExtendedEventHook(),
dragStart: createExtendedEventHook(),
drag: createExtendedEventHook(),
dragStop: createExtendedEventHook(),
})
function createNodeHooks() {
return {
doubleClick: createExtendedEventHook(),
click: createExtendedEventHook(),
mouseEnter: createExtendedEventHook(),
mouseMove: createExtendedEventHook(),
mouseLeave: createExtendedEventHook(),
contextMenu: createExtendedEventHook(),
dragStart: createExtendedEventHook(),
drag: createExtendedEventHook(),
dragStop: createExtendedEventHook(),
}
}
export default function useNodeHooks(node: GraphNode, emits: VueFlowStore['emits']): { emit: NodeEventsEmit; on: NodeEventsOn } {
const nodeHooks = createNodeHooks()
+1 -1
View File
@@ -7,7 +7,7 @@ interface ExtendedViewport extends ViewportFunctions {
const DEFAULT_PADDING = 0.1
const noop = () => {}
function noop() {}
const initialViewportHelper: ExtendedViewport = {
zoomIn: noop,
@@ -51,9 +51,15 @@ const groups = controlledComputed(
() => groupEdgesByZLevel(getEdges, findNode, elevateEdgesOnSelect),
)
const selectable = (edgeSelectable?: boolean) => (typeof edgeSelectable === 'undefined' ? elementsSelectable : edgeSelectable)
const updatable = (edgeUpdatable?: EdgeUpdatable) => (typeof edgeUpdatable === 'undefined' ? edgesUpdatable : edgeUpdatable)
const focusable = (edgeFocusable?: boolean) => (typeof edgeFocusable === 'undefined' ? edgesFocusable : edgeFocusable)
function selectable(edgeSelectable?: boolean) {
return typeof edgeSelectable === 'undefined' ? elementsSelectable : edgeSelectable
}
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']) {
const name = type || 'default'
@@ -44,11 +44,18 @@ onMounted(() => {
onBeforeUnmount(() => resizeObserver?.disconnect())
const draggable = (nodeDraggable?: boolean) => (typeof nodeDraggable === 'undefined' ? nodesDraggable : nodeDraggable)
const selectable = (nodeSelectable?: boolean) => (typeof nodeSelectable === 'undefined' ? elementsSelectable : nodeSelectable)
const connectable = (nodeConnectable?: HandleConnectable) =>
typeof nodeConnectable === 'undefined' ? nodesConnectable : nodeConnectable
const focusable = (nodeFocusable?: boolean) => (typeof nodeFocusable === 'undefined' ? nodesFocusable : nodeFocusable)
function draggable(nodeDraggable?: boolean) {
return typeof nodeDraggable === 'undefined' ? nodesDraggable : nodeDraggable
}
function selectable(nodeSelectable?: boolean) {
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']) {
const name = type || 'default'
+54 -52
View File
@@ -2,58 +2,60 @@ import type { Ref } from 'vue'
import type { FlowHooks } from '~/types'
// flow event hooks
export const createHooks = (): FlowHooks => ({
edgesChange: createExtendedEventHook(),
nodesChange: createExtendedEventHook(),
nodeDoubleClick: createExtendedEventHook(),
nodeClick: createExtendedEventHook(),
nodeMouseEnter: createExtendedEventHook(),
nodeMouseMove: createExtendedEventHook(),
nodeMouseLeave: createExtendedEventHook(),
nodeContextMenu: createExtendedEventHook(),
nodeDragStart: createExtendedEventHook(),
nodeDrag: createExtendedEventHook(),
nodeDragStop: createExtendedEventHook(),
nodesInitialized: createExtendedEventHook(),
miniMapNodeClick: createExtendedEventHook(),
miniMapNodeDoubleClick: createExtendedEventHook(),
miniMapNodeMouseEnter: createExtendedEventHook(),
miniMapNodeMouseMove: createExtendedEventHook(),
miniMapNodeMouseLeave: createExtendedEventHook(),
connect: createExtendedEventHook(),
connectStart: createExtendedEventHook(),
connectEnd: createExtendedEventHook(),
paneReady: createExtendedEventHook(),
move: createExtendedEventHook(),
moveStart: createExtendedEventHook(),
moveEnd: createExtendedEventHook(),
selectionDragStart: createExtendedEventHook(),
selectionDrag: createExtendedEventHook(),
selectionDragStop: createExtendedEventHook(),
selectionContextMenu: createExtendedEventHook(),
selectionStart: createExtendedEventHook(),
selectionEnd: createExtendedEventHook(),
viewportChangeStart: createExtendedEventHook(),
viewportChange: createExtendedEventHook(),
viewportChangeEnd: createExtendedEventHook(),
paneScroll: createExtendedEventHook(),
paneClick: createExtendedEventHook(),
paneContextMenu: createExtendedEventHook(),
paneMouseEnter: createExtendedEventHook(),
paneMouseMove: createExtendedEventHook(),
paneMouseLeave: createExtendedEventHook(),
edgeContextMenu: createExtendedEventHook(),
edgeMouseEnter: createExtendedEventHook(),
edgeMouseMove: createExtendedEventHook(),
edgeMouseLeave: createExtendedEventHook(),
edgeDoubleClick: createExtendedEventHook(),
edgeClick: createExtendedEventHook(),
edgeUpdateStart: createExtendedEventHook(),
edgeUpdate: createExtendedEventHook(),
edgeUpdateEnd: createExtendedEventHook(),
updateNodeInternals: createExtendedEventHook(),
error: createExtendedEventHook((err) => warn(err.message)),
})
export function createHooks(): FlowHooks {
return {
edgesChange: createExtendedEventHook(),
nodesChange: createExtendedEventHook(),
nodeDoubleClick: createExtendedEventHook(),
nodeClick: createExtendedEventHook(),
nodeMouseEnter: createExtendedEventHook(),
nodeMouseMove: createExtendedEventHook(),
nodeMouseLeave: createExtendedEventHook(),
nodeContextMenu: createExtendedEventHook(),
nodeDragStart: createExtendedEventHook(),
nodeDrag: createExtendedEventHook(),
nodeDragStop: createExtendedEventHook(),
nodesInitialized: createExtendedEventHook(),
miniMapNodeClick: createExtendedEventHook(),
miniMapNodeDoubleClick: createExtendedEventHook(),
miniMapNodeMouseEnter: createExtendedEventHook(),
miniMapNodeMouseMove: createExtendedEventHook(),
miniMapNodeMouseLeave: createExtendedEventHook(),
connect: createExtendedEventHook(),
connectStart: createExtendedEventHook(),
connectEnd: createExtendedEventHook(),
paneReady: createExtendedEventHook(),
move: createExtendedEventHook(),
moveStart: createExtendedEventHook(),
moveEnd: createExtendedEventHook(),
selectionDragStart: createExtendedEventHook(),
selectionDrag: createExtendedEventHook(),
selectionDragStop: createExtendedEventHook(),
selectionContextMenu: createExtendedEventHook(),
selectionStart: createExtendedEventHook(),
selectionEnd: createExtendedEventHook(),
viewportChangeStart: createExtendedEventHook(),
viewportChange: createExtendedEventHook(),
viewportChangeEnd: createExtendedEventHook(),
paneScroll: createExtendedEventHook(),
paneClick: createExtendedEventHook(),
paneContextMenu: createExtendedEventHook(),
paneMouseEnter: createExtendedEventHook(),
paneMouseMove: createExtendedEventHook(),
paneMouseLeave: createExtendedEventHook(),
edgeContextMenu: createExtendedEventHook(),
edgeMouseEnter: createExtendedEventHook(),
edgeMouseMove: createExtendedEventHook(),
edgeMouseLeave: createExtendedEventHook(),
edgeDoubleClick: createExtendedEventHook(),
edgeClick: createExtendedEventHook(),
edgeUpdateStart: createExtendedEventHook(),
edgeUpdate: createExtendedEventHook(),
edgeUpdateEnd: createExtendedEventHook(),
updateNodeInternals: createExtendedEventHook(),
error: createExtendedEventHook((err) => warn(err.message)),
}
}
export function useHooks(emit: (...args: any[]) => void, hooks: Ref<FlowHooks>) {
onBeforeMount(() => {
+93 -91
View File
@@ -25,114 +25,116 @@ export const defaultEdgeTypes: DefaultEdgeTypes = {
simplebezier: SimpleBezierEdge,
}
const defaultState = (): State => ({
vueFlowRef: null,
viewportRef: null,
nodes: [],
edges: [],
nodeTypes: {},
edgeTypes: {},
function defaultState(): State {
return {
vueFlowRef: null,
viewportRef: null,
nodes: [],
edges: [],
nodeTypes: {},
edgeTypes: {},
initialized: false,
initialized: false,
dimensions: {
width: 0,
height: 0,
},
viewport: { x: 0, y: 0, zoom: 1 },
dimensions: {
width: 0,
height: 0,
},
viewport: { x: 0, y: 0, zoom: 1 },
d3Zoom: null,
d3Selection: null,
d3ZoomHandler: null,
minZoom: 0.5,
maxZoom: 2,
d3Zoom: null,
d3Selection: null,
d3ZoomHandler: null,
minZoom: 0.5,
maxZoom: 2,
translateExtent: [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
],
nodeExtent: [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
],
translateExtent: [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
],
nodeExtent: [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
],
selectionMode: SelectionMode.Full,
paneDragging: false,
preventScrolling: true,
zoomOnScroll: true,
zoomOnPinch: true,
zoomOnDoubleClick: true,
panOnScroll: false,
panOnScrollSpeed: 0.5,
panOnScrollMode: PanOnScrollMode.Free,
panOnDrag: true,
edgeUpdaterRadius: 10,
onlyRenderVisibleElements: false,
defaultViewport: { x: 0, y: 0, zoom: 1 },
selectionMode: SelectionMode.Full,
paneDragging: false,
preventScrolling: true,
zoomOnScroll: true,
zoomOnPinch: true,
zoomOnDoubleClick: true,
panOnScroll: false,
panOnScrollSpeed: 0.5,
panOnScrollMode: PanOnScrollMode.Free,
panOnDrag: true,
edgeUpdaterRadius: 10,
onlyRenderVisibleElements: false,
defaultViewport: { x: 0, y: 0, zoom: 1 },
nodesSelectionActive: false,
userSelectionActive: false,
nodesSelectionActive: false,
userSelectionActive: false,
userSelectionRect: null,
userSelectionRect: null,
defaultMarkerColor: '#b1b1b7',
connectionLineStyle: {},
connectionLineType: null,
connectionLineOptions: {
type: ConnectionLineType.Bezier,
style: {},
},
connectionMode: ConnectionMode.Loose,
connectionStartHandle: null,
connectionClickStartHandle: null,
connectionPosition: { x: NaN, y: NaN },
connectionRadius: 20,
connectOnClick: true,
connectionStatus: null,
isValidConnection: null,
defaultMarkerColor: '#b1b1b7',
connectionLineStyle: {},
connectionLineType: null,
connectionLineOptions: {
type: ConnectionLineType.Bezier,
style: {},
},
connectionMode: ConnectionMode.Loose,
connectionStartHandle: null,
connectionClickStartHandle: null,
connectionPosition: { x: NaN, y: NaN },
connectionRadius: 20,
connectOnClick: true,
connectionStatus: null,
isValidConnection: null,
snapGrid: [15, 15],
snapToGrid: false,
snapGrid: [15, 15],
snapToGrid: false,
edgesUpdatable: false,
edgesFocusable: true,
nodesFocusable: true,
nodesConnectable: true,
nodesDraggable: true,
elementsSelectable: true,
selectNodesOnDrag: true,
multiSelectionActive: false,
selectionKeyCode: 'Shift',
multiSelectionKeyCode: 'Meta',
zoomActivationKeyCode: 'Meta',
deleteKeyCode: 'Backspace',
panActivationKeyCode: 'Space',
edgesUpdatable: false,
edgesFocusable: true,
nodesFocusable: true,
nodesConnectable: true,
nodesDraggable: true,
elementsSelectable: true,
selectNodesOnDrag: true,
multiSelectionActive: false,
selectionKeyCode: 'Shift',
multiSelectionKeyCode: 'Meta',
zoomActivationKeyCode: 'Meta',
deleteKeyCode: 'Backspace',
panActivationKeyCode: 'Space',
hooks: createHooks(),
hooks: createHooks(),
applyDefault: true,
autoConnect: false,
applyDefault: true,
autoConnect: false,
fitViewOnInit: false,
noDragClassName: 'nodrag',
noWheelClassName: 'nowheel',
noPanClassName: 'nopan',
defaultEdgeOptions: undefined,
elevateEdgesOnSelect: false,
elevateNodesOnSelect: true,
fitViewOnInit: false,
noDragClassName: 'nodrag',
noWheelClassName: 'nowheel',
noPanClassName: 'nopan',
defaultEdgeOptions: undefined,
elevateEdgesOnSelect: false,
elevateNodesOnSelect: true,
autoPanOnNodeDrag: true,
autoPanOnConnect: true,
autoPanOnNodeDrag: true,
autoPanOnConnect: true,
disableKeyboardA11y: false,
ariaLiveMessage: '',
disableKeyboardA11y: false,
ariaLiveMessage: '',
__experimentalFeatures: {
nestedFlow: false,
},
__experimentalFeatures: {
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 {
const state = defaultState()
+23 -16
View File
@@ -185,30 +185,37 @@ export function applyChanges<
return elements
}
export const applyEdgeChanges = (changes: EdgeChange[], edges: GraphEdge[]) => applyChanges(changes, edges)
export const applyNodeChanges = (changes: NodeChange[], nodes: GraphNode[]) => applyChanges(changes, nodes)
export function applyEdgeChanges(changes: EdgeChange[], edges: GraphEdge[]) {
return applyChanges(changes, edges)
}
export function applyNodeChanges(changes: NodeChange[], nodes: GraphNode[]) {
return applyChanges(changes, nodes)
}
export const createSelectionChange = (id: string, selected: boolean): NodeSelectionChange | EdgeSelectionChange => ({
id,
type: 'select',
selected,
})
export function createSelectionChange(id: string, selected: boolean): NodeSelectionChange | EdgeSelectionChange {
return {
id,
type: 'select',
selected,
}
}
export const createAdditionChange = <
export function createAdditionChange<
T extends GraphNode | GraphEdge = GraphNode,
C extends NodeAddChange | EdgeAddChange = T extends GraphNode ? NodeAddChange : EdgeAddChange,
>(
item: T,
): C =>
<C>{
>(item: T): C {
return <C>{
item,
type: 'add',
}
}
export const createRemoveChange = (id: string): NodeRemoveChange | EdgeRemoveChange => ({
id,
type: 'remove',
})
export function createRemoveChange(id: string): NodeRemoveChange | EdgeRemoveChange {
return {
id,
type: 'remove',
}
}
export function getSelectionChanges(elements: FlowElements, selectedIds: string[]) {
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) {
const isMouseTriggered = isMouseEvent(event)
+84 -56
View File
@@ -21,11 +21,13 @@ import type {
XYZPosition,
} from '~/types'
export const nodeToRect = (node: GraphNode): Rect => ({
...(node.computedPosition || { x: 0, y: 0 }),
width: node.dimensions.width || 0,
height: node.dimensions.height || 0,
})
export function nodeToRect(node: GraphNode): Rect {
return {
...(node.computedPosition || { x: 0, y: 0 }),
width: node.dimensions.width || 0,
height: node.dimensions.height || 0,
}
}
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))
@@ -34,17 +36,23 @@ export function getOverlappingArea(rectA: Rect, rectB: Rect) {
return Math.ceil(xOverlap * yOverlap)
}
export const getDimensions = (node: HTMLElement): Dimensions => ({
width: node.offsetWidth,
height: node.offsetHeight,
})
export function getDimensions(node: HTMLElement): Dimensions {
return {
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 => ({
x: clamp(position.x, extent[0][0], extent[1][0]),
y: clamp(position.y, extent[0][1], extent[1][1]),
})
export function clampPosition(position: XYPosition, extent: CoordinateExtent): XYPosition {
return {
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 {
const doc = element.getRootNode() as Document
@@ -54,19 +62,25 @@ export function getHostForElement(element: HTMLElement): Document {
else return window.document
}
export const isEdge = <Data = ElementData>(element: MaybeElement): element is Edge<Data> =>
element && 'id' in element && 'source' in element && 'target' in element
export function isEdge<Data = ElementData>(element: MaybeElement): element is Edge<Data> {
return element && 'id' in element && 'source' in element && 'target' in element
}
export const isGraphEdge = <Data = ElementData>(element: MaybeElement): element is GraphEdge<Data> =>
isEdge(element) && 'sourceNode' in element && 'targetNode' in element
export function isGraphEdge<Data = ElementData>(element: MaybeElement): element is GraphEdge<Data> {
return isEdge(element) && 'sourceNode' in element && 'targetNode' in element
}
export const isNode = <Data = ElementData>(element: MaybeElement): element is Node<Data> =>
element && 'id' in element && !isEdge(element)
export function isNode<Data = ElementData>(element: MaybeElement): element is Node<Data> {
return element && 'id' in element && !isEdge(element)
}
export const isGraphNode = <Data = ElementData>(element: MaybeElement): element is GraphNode<Data> =>
isNode(element) && 'computedPosition' in element
export function isGraphNode<Data = ElementData>(element: MaybeElement): element is GraphNode<Data> {
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 {
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
}
const getConnectedElements = <T extends Elements = FlowElements>(
function getConnectedElements<T extends Elements = FlowElements>(
node: Node,
elements: T,
dir: 'source' | 'target',
): T extends FlowElements ? GraphNode[] : Node[] => {
): T extends FlowElements ? GraphNode[] : Node[] {
if (!isNode(node)) return []
const origin = dir === 'source' ? 'target' : 'source'
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[]
}
export const getOutgoers = <T extends Elements = FlowElements>(node: Node, elements: T) =>
getConnectedElements(node, elements, 'target')
export function getOutgoers<T extends Elements = FlowElements>(node: Node, elements: T) {
return getConnectedElements(node, elements, 'target')
}
export const getIncomers = <T extends Elements = FlowElements>(node: Node, elements: T) =>
getConnectedElements(node, elements, 'source')
export function getIncomers<T extends Elements = FlowElements>(node: Node, elements: T) {
return getConnectedElements(node, elements, 'source')
}
export const getEdgeId = ({ source, sourceHandle, target, targetHandle }: Connection) =>
`vueflow__edge-${source}${sourceHandle ?? ''}-${target}${targetHandle ?? ''}`
export function getEdgeId({ source, sourceHandle, target, targetHandle }: Connection) {
return `vueflow__edge-${source}${sourceHandle ?? ''}-${target}${targetHandle ?? ''}`
}
export const connectionExists = (edge: Edge | Connection, elements: Elements) =>
elements.some(
export function connectionExists(edge: Edge | Connection, elements: Elements) {
return elements.some(
(el) =>
isEdge(el) &&
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.targetHandle === edge.targetHandle || (!el.targetHandle && !edge.targetHandle)),
)
}
/**
* @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
}
const getBoundsOfBoxes = (box1: Box, box2: Box): Box => ({
x: Math.min(box1.x, box2.x),
y: Math.min(box1.y, box2.y),
x2: Math.max(box1.x2, box2.x2),
y2: Math.max(box1.y2, box2.y2),
})
function getBoundsOfBoxes(box1: Box, box2: Box): Box {
return {
x: Math.min(box1.x, box2.x),
y: Math.min(box1.y, box2.y),
x2: Math.max(box1.x2, box2.x2),
y2: Math.max(box1.y2, box2.y2),
}
}
export const rectToBox = ({ x, y, width, height }: Rect): Box => ({
x,
y,
x2: x + width,
y2: y + height,
})
export function rectToBox({ x, y, width, height }: Rect): Box {
return {
x,
y,
x2: x + width,
y2: y + height,
}
}
export const boxToRect = ({ x, y, x2, y2 }: Box): Rect => ({
x,
y,
width: x2 - x,
height: y2 - y,
})
export function boxToRect({ x, y, x2, y2 }: Box): Rect {
return {
x,
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[]) {
const box = nodes.reduce(
@@ -288,10 +314,12 @@ export function getRectOfNodes(nodes: GraphNode[]) {
return boxToRect(box)
}
export const graphPosToZoomedPos = ({ x, y }: XYPosition, { x: tx, y: ty, zoom: tScale }: ViewportTransform): XYPosition => ({
x: x * tScale + tx,
y: y * tScale + ty,
})
export function graphPosToZoomedPos({ x, y }: XYPosition, { x: tx, y: ty, zoom: tScale }: ViewportTransform): XYPosition {
return {
x: x * tScale + tx,
y: y * tScale + ty,
}
}
export function getNodesInside(
nodes: GraphNode[],
+3 -1
View File
@@ -1,6 +1,8 @@
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']) {
if (!edgeParams.source || !edgeParams.target) {
+6 -6
View File
@@ -152,36 +152,36 @@ watchEffect(
{ flush: 'post' },
)
const onSvgClick = (event: MouseEvent) => {
function onSvgClick(event: MouseEvent) {
const [x, y] = pointer(event)
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) }
emits.miniMapNodeClick(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) }
emits.miniMapNodeDoubleClick(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) }
emits.miniMapNodeMouseEnter(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) }
emits.miniMapNodeMouseMove(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) }
emits.miniMapNodeMouseLeave(param)
emit('nodeMouseleave', param)
@@ -13,7 +13,7 @@ export interface PointInfo {
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
// 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.
*/
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 Zy = (Ay - By) / 2 + By
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} `
path.forEach((point) => {
@@ -23,7 +23,7 @@ export const drawStraightLinePath = (source: XYPosition, target: XYPosition, pat
return svgPathString
}
const quadraticBezierCurve = (points: number[][]) => {
function quadraticBezierCurve(points: number[][]) {
const X = 0
const Y = 1
let point = points[0]
@@ -49,7 +49,7 @@ const quadraticBezierCurve = (points: number[][]) => {
/**
* 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]]
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({
diagonalMovement: DiagonalMovement.Always,
allowDiagonal: true,
@@ -34,7 +34,7 @@ export interface GraphBoundingBox {
* @param roundTo If the coordinates should be rounded to this nearest integer
* @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
nodePadding = Math.max(Math.round(nodePadding), 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'
export const getNextPointFromPosition = (point: XYPosition, position: Direction): XYPosition => {
export function getNextPointFromPosition(point: XYPosition, position: Direction): XYPosition {
switch (position) {
case 'top':
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
* 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)
while (!node.walkable) {
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
* 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 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
* 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 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 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, {
props: {
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) => {
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) => {
const sourceHandle = cy.get(`[data-nodeid="${from}"].source`)
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 targetHandle = cy.get(`[data-nodeid="${to}"].target`)
+1
View File
@@ -4,6 +4,7 @@ module.exports = {
rules: {
'vue/no-setup-props-destructure': 0,
'no-console': 0,
'unused-imports/no-unused-vars': 0,
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
'prettier/prettier': [
'error',