chore: lint files
Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
@@ -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 : {}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
|
||||
@@ -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,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'
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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'))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,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'
|
||||
|
||||
@@ -50,7 +50,9 @@ const offsets = [
|
||||
]
|
||||
|
||||
let id = 0
|
||||
const getNodeId = () => (id++).toString()
|
||||
function getNodeId() {
|
||||
return (id++).toString()
|
||||
}
|
||||
|
||||
export function getElements(): Elements {
|
||||
const initialElements = []
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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 } },
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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])
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -11,7 +11,9 @@ interface UseHandleProps {
|
||||
onEdgeUpdateEnd?: (event: MouseTouchEvent) => void
|
||||
}
|
||||
|
||||
const alwaysValid = () => true
|
||||
function alwaysValid() {
|
||||
return true
|
||||
}
|
||||
|
||||
export default function useHandle({
|
||||
handleId: _handleId,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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[],
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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`)
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user