docs: replace vuepress docs dir with vitepress docs dir
@@ -36,9 +36,11 @@ const store = new ReplStore({
|
|||||||
outputMode: 'preview',
|
outputMode: 'preview',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const vh = useCssVar('--vh')
|
||||||
|
|
||||||
watchEffect(
|
watchEffect(
|
||||||
() => {
|
() => {
|
||||||
document.documentElement.style.setProperty('--vh', `${window.innerHeight}px`)
|
vh.value = `${window.innerHeight}px`
|
||||||
},
|
},
|
||||||
{ flush: 'post' },
|
{ flush: 'post' },
|
||||||
)
|
)
|
||||||
@@ -99,12 +101,14 @@ const sfcOptions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.vue-repl {
|
.vue-repl {
|
||||||
|
--vh: 100vh;
|
||||||
|
|
||||||
@apply rounded-lg border-1 border-solid dark:border-gray-200/10 border-gray-200;
|
@apply rounded-lg border-1 border-solid dark:border-gray-200/10 border-gray-200;
|
||||||
|
|
||||||
height: calc(var(--vh) - var(--navbar-height));
|
height: calc(var(--vh) - 72px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.msg.err {
|
.msg.err {
|
||||||
display: none;
|
@apply hidden;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
gap: 5px;
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.buttons .button {
|
||||||
background-color: whitesmoke;
|
background-color: whitesmoke;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button:hover {
|
.buttons .button:hover {
|
||||||
background: black;
|
background: black;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import Heart from '~icons/mdi/heart'
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="acknowledgement" class="w-full dark:(bg-black text-white) border-y-1 border-white">
|
<div id="acknowledgement" class="w-full">
|
||||||
<div class="max-w-11/12 md:max-w-6/12 m-auto py-4 md:(pb-12 pt-6) text-center">
|
<div class="max-w-[1024px] md:max-w-3/4 m-auto py-4 md:(pb-12 pt-6) text-center">
|
||||||
<div>
|
<div>
|
||||||
<h1 class="md:mb-8 flex justify-center items-center"><Heart class="text-red-500" /> Acknowledgement</h1>
|
<h1 class="md:mb-8 flex justify-center items-center"><Heart class="text-red-500" /> Acknowledgement</h1>
|
||||||
<strong>First off</strong>: A big thank you to the developers of
|
<strong>First off</strong>: A big thank you to the developers of
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const npmData = await $fetch('https://api.npmjs.org/downloads/point/last-month/@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="w-full dark:(bg-black text-white border-white) border-black border-y-1">
|
<div class="w-full dark:(border-white) border-black border-y-1">
|
||||||
<div class="max-w-full md:max-w-11/12 m-auto py-4 md:py-12 <md:(dark:border-t-1 border-white)">
|
<div class="max-w-full md:max-w-11/12 m-auto py-4 md:py-12 <md:(dark:border-t-1 border-white)">
|
||||||
<div class="grid md:grid-cols-3 gap-3 text-center <md:divide-y md:divide-x dark:divide-white divide-black">
|
<div class="grid md:grid-cols-3 gap-3 text-center <md:divide-y md:divide-x dark:divide-white divide-black">
|
||||||
<div class="grid grid-rows-auto gap-2 py-4 md:py-0">
|
<div class="grid grid-rows-auto gap-2 py-4 md:py-0">
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ onBeforeUnmount(stop)
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div ref="el" class="w-full dark:(bg-black text-white)">
|
<div ref="el" class="w-full">
|
||||||
<div
|
<div
|
||||||
class="flex flex-col divide-y divide-gray-500 md:divide-y-0 gap-12 md:gap-24 lg:gap-36 max-w-9/12 md:max-w-11/12 lg:max-w-9/12 m-auto py-12 md:py-24 text-center md:text-left"
|
class="flex flex-col divide-y divide-gray-500 md:divide-y-0 gap-12 md:gap-24 lg:gap-36 max-w-9/12 md:max-w-11/12 lg:max-w-9/12 m-auto py-12 md:py-24 text-center md:text-left"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ const animations = ref<{ className: string; duration: number }[]>(shuffle(create
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VueFlow ref="el" class="dark:bg-black bg-white transition-colors duration-200 ease-in-out">
|
<VueFlow ref="el">
|
||||||
<XyzTransition xyz="fade down ease-out-back duration-10" mode="out-in">
|
<XyzTransition xyz="fade down ease-out-back duration-10" mode="out-in">
|
||||||
<Background v-if="animatedBackground">
|
<Background v-if="animatedBackground">
|
||||||
<template #pattern-container="{ id }">
|
<template #pattern-container="{ id }">
|
||||||
@@ -306,21 +306,21 @@ const animations = ref<{ className: string; duration: number }[]>(shuffle(create
|
|||||||
</template>
|
</template>
|
||||||
<template v-else-if="props.id === 'documentation'">
|
<template v-else-if="props.id === 'documentation'">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<router-link class="link group bg-[#f15a16]" to="/guide/"> Read The Documentation </router-link>
|
<router-link class="intro-link group bg-[#f15a16]" to="/guide/"> Read The Documentation </router-link>
|
||||||
</div>
|
</div>
|
||||||
<Handle type="target" :position="Position.Top" />
|
<Handle type="target" :position="Position.Top" />
|
||||||
<Handle class="block md:hidden" type="source" :position="Position.Bottom" />
|
<Handle class="block md:hidden" type="source" :position="Position.Bottom" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="props.id === 'examples'">
|
<template v-else-if="props.id === 'examples'">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<router-link class="link group bg-[#ef467e]" to="/examples/"> Check The Examples </router-link>
|
<router-link class="intro-link group bg-[#ef467e]" to="/examples/"> Check The Examples </router-link>
|
||||||
</div>
|
</div>
|
||||||
<Handle type="target" :position="Position.Top" />
|
<Handle type="target" :position="Position.Top" />
|
||||||
<Handle class="block md:hidden" type="source" :position="Position.Bottom" />
|
<Handle class="block md:hidden" type="source" :position="Position.Bottom" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="props.id === 'acknowledgement'">
|
<template v-else-if="props.id === 'acknowledgement'">
|
||||||
<div class="flex" @click="scrollTo">
|
<div class="flex" @click="scrollTo">
|
||||||
<button class="link group bg-sky-500"><Heart class="text-red-500" /> Acknowledgement</button>
|
<button class="intro-link group bg-sky-500"><Heart class="text-red-500" /> Acknowledgement</button>
|
||||||
</div>
|
</div>
|
||||||
<Handle type="target" :position="Position.Top" />
|
<Handle type="target" :position="Position.Top" />
|
||||||
</template>
|
</template>
|
||||||
@@ -431,7 +431,7 @@ const animations = ref<{ className: string; duration: number }[]>(shuffle(create
|
|||||||
hover:(ring ring-white);
|
hover:(ring ring-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
.link {
|
.intro-link {
|
||||||
@apply flex
|
@apply flex
|
||||||
gap-3
|
gap-3
|
||||||
items-center
|
items-center
|
||||||
|
|||||||
@@ -1,41 +1,39 @@
|
|||||||
{
|
{
|
||||||
"name": "docs",
|
"name": "docs2",
|
||||||
"version": "0.0.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "pnpm run typedoc && vuepress dev src",
|
"dev": "pnpm run typedoc && vitepress dev src",
|
||||||
"build": "pnpm run typedoc && vuepress build src",
|
"build": "pnpm run typedoc && vitepress build src",
|
||||||
|
"serve": "vitepress serve src",
|
||||||
"lint": "eslint --ext \".js,.jsx,.ts,.tsx\" --fix --ignore-path .gitignore .",
|
"lint": "eslint --ext \".js,.jsx,.ts,.tsx\" --fix --ignore-path .gitignore .",
|
||||||
"typedoc": "typedoc --options ./typedoc.json"
|
"typedoc": "typedoc --options ./typedoc.json",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@algolia/client-search": "^4.14.2",
|
||||||
"@animxyz/core": "^0.6.6",
|
"@animxyz/core": "^0.6.6",
|
||||||
"@animxyz/vue3": "^0.6.7",
|
"@animxyz/vue3": "^0.6.7",
|
||||||
"@braks/vue-flow": "workspace:*",
|
"@braks/vue-flow": "workspace:*",
|
||||||
"@stackblitz/sdk": "^1.8.0",
|
"@stackblitz/sdk": "^1.8.0",
|
||||||
"@vue/repl": "1.1.2",
|
"@vue/repl": "1.1.2",
|
||||||
"blobity": "^0.1.7",
|
"blobity": "^0.2.1",
|
||||||
"canvas-confetti": "^1.5.1"
|
"canvas-confetti": "^1.5.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify/json": "^2.1.81",
|
"@iconify/json": "^2.1.85",
|
||||||
"@types/canvas-confetti": "^1.4.3",
|
"@types/canvas-confetti": "^1.4.3",
|
||||||
"@types/node": "^18.0.6",
|
"@types/node": "^18.6.2",
|
||||||
"@vuepress/bundler-vite": "^2.0.0-beta.49",
|
|
||||||
"@vuepress/plugin-docsearch": "^2.0.0-beta.49",
|
|
||||||
"@vuepress/plugin-pwa": "^2.0.0-beta.49",
|
|
||||||
"@windicss/plugin-scrollbar": "^1.2.3",
|
"@windicss/plugin-scrollbar": "^1.2.3",
|
||||||
"dotenv": "^16.0.1",
|
"dotenv": "^16.0.1",
|
||||||
"ohmyfetch": "^0.4.18",
|
"ohmyfetch": "^0.4.18",
|
||||||
"typedoc": "^0.22.18",
|
"typedoc": "^0.22.18",
|
||||||
"typedoc-plugin-markdown": "^3.13.4",
|
"typedoc-plugin-markdown": "^3.13.4",
|
||||||
"unplugin-auto-import": "^0.9.5",
|
"unplugin-auto-import": "^0.10.3",
|
||||||
"unplugin-icons": "^0.14.7",
|
"unplugin-icons": "^0.14.8",
|
||||||
"unplugin-vue-components": "^0.19.9",
|
"unplugin-vue-components": "^0.21.2",
|
||||||
"vite-plugin-windicss": "^1.8.7",
|
"vite-plugin-windicss": "^1.8.7",
|
||||||
"vuepress": "^2.0.0-beta.49",
|
"vitepress": "^1.0.0-alpha.4",
|
||||||
"vuepress-plugin-seo2": "^2.0.0-beta.84",
|
|
||||||
"vuepress-plugin-sitemap2": "^2.0.0-beta.84",
|
|
||||||
"windicss": "^3.5.6"
|
"windicss": "^3.5.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,111 +0,0 @@
|
|||||||
:root {
|
|
||||||
--primary: #BB86FC;
|
|
||||||
--secondary: #03dac5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
--c-text-lighter: white !important;
|
|
||||||
--c-text: white !important;
|
|
||||||
--c-bg: black !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark .tip {
|
|
||||||
--c-bg-light: gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tip {
|
|
||||||
--c-bg-light: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
html, body {
|
|
||||||
@apply scrollbar scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-green-500 scrollbar-track-black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.home {
|
|
||||||
--content-width: 100%;
|
|
||||||
max-width: 100% !important;
|
|
||||||
@apply !px-0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page a {
|
|
||||||
@apply text-green-500 font-semibold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.examples .page, .examples .page-meta, .footer, .sidebar {
|
|
||||||
@apply dark:(!bg-black text-white);
|
|
||||||
}
|
|
||||||
|
|
||||||
.examples .page {
|
|
||||||
--content-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-default-content {
|
|
||||||
@apply overflow-scroll md:overflow-hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar {
|
|
||||||
@apply dark:bg-gray-900;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
@apply text-xl lg:text-4xl mb-4 font-bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
@apply text-lg lg:text-2xl mb-4 font-semibold;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
line-height: inherit;
|
|
||||||
margin: revert;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul li {
|
|
||||||
@apply mt-2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-button {
|
|
||||||
@apply z-1 shadow-lg transition-colors duration-200 text-white font-semibold text-lg mt-4 px-5 py-3 rounded-lg bg-green-500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-flow__node.dark {
|
|
||||||
@apply bg-gray-800 text-white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-flow__node-selector {
|
|
||||||
font-size: 14px;
|
|
||||||
background: #f0f2f3;
|
|
||||||
border: 1px solid #555;
|
|
||||||
border-radius: 5px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-flow__node-selector .vue-flow__handle {
|
|
||||||
border-color: #f0f2f3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider {
|
|
||||||
--color: red;
|
|
||||||
@apply bg-gray-200 w-full h-[10px] outline-none rounded-full;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
|
|
||||||
&::-moz-range-thumb {
|
|
||||||
@apply w-[15px] h-[15px] cursor-pointer border-1 border-solid border-white rounded-full;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
background: var(--color);
|
|
||||||
}
|
|
||||||
&::-webkit-slider-thumb {
|
|
||||||
@apply w-[15px] h-[15px] cursor-pointer border-1 border-solid border-white rounded-full;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
background: var(--color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-container.examples .theme-default-content .vue-repl pre, .theme-default-content .vue-repl pre[class*=language-] {
|
|
||||||
padding: unset;
|
|
||||||
margin: unset;
|
|
||||||
border-radius: unset;
|
|
||||||
line-height: unset;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<svg id="visual" viewBox="0 0 960 540" width="960" height="540" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><rect width="960" height="540" fill="#31475e"></rect><g><g transform="translate(57 45)"><path d="M0 -106.9L83.6 -66.7L104.2 23.8L46.4 96.3L-46.4 96.3L-104.2 23.8L-83.6 -66.7Z" fill="#3fb984"></path></g><g transform="translate(708 88)"><path d="M0 -66L51.6 -41.2L64.3 14.7L28.6 59.5L-28.6 59.5L-64.3 14.7L-51.6 -41.2Z" fill="#3fb984"></path></g><g transform="translate(823 510)"><path d="M0 -77L60.2 -48L75.1 17.1L33.4 69.4L-33.4 69.4L-75.1 17.1L-60.2 -48Z" fill="#3fb984"></path></g><g transform="translate(896 280)"><path d="M0 -45L35.2 -28.1L43.9 10L19.5 40.5L-19.5 40.5L-43.9 10L-35.2 -28.1Z" fill="#3fb984"></path></g><g transform="translate(287 458)"><path d="M0 -58L45.3 -36.2L56.5 12.9L25.2 52.3L-25.2 52.3L-56.5 12.9L-45.3 -36.2Z" fill="#3fb984"></path></g><g transform="translate(12 380)"><path d="M0 -101L79 -63L98.5 22.5L43.8 91L-43.8 91L-98.5 22.5L-79 -63Z" fill="#3fb984"></path></g><g transform="translate(609 440)"><path d="M0 -60L46.9 -37.4L58.5 13.4L26 54.1L-26 54.1L-58.5 13.4L-46.9 -37.4Z" fill="#3fb984"></path></g><g transform="translate(457 42)"><path d="M0 -81L63.3 -50.5L79 18L35.1 73L-35.1 73L-79 18L-63.3 -50.5Z" fill="#3fb984"></path></g></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,39 +0,0 @@
|
|||||||
// generated by unplugin-vue-components
|
|
||||||
// We suggest you to commit this file into source control
|
|
||||||
// Read more: https://github.com/vuejs/core/pull/3399
|
|
||||||
import '@vue/runtime-core'
|
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
|
||||||
export interface GlobalComponents {
|
|
||||||
Acknowledgement: typeof import('./../../components/home/Acknowledgement.vue')['default']
|
|
||||||
Additional: typeof import('./../../components/home/flows/Additional.vue')['default']
|
|
||||||
App: typeof import('./../../components/examples/basic/App.vue')['default']
|
|
||||||
Banner: typeof import('./../../components/home/Banner.vue')['default']
|
|
||||||
Basic: typeof import('./../../components/home/flows/Basic.vue')['default']
|
|
||||||
Controls: typeof import('./../../components/examples/save-restore/Controls.vue')['default']
|
|
||||||
Custom: typeof import('./../../components/home/edges/Custom.vue')['default']
|
|
||||||
CustomConnectionLine: typeof import('./../../components/examples/connectionline/CustomConnectionLine.vue')['default']
|
|
||||||
CustomEdge: typeof import('./../../components/examples/edges/CustomEdge.vue')['default']
|
|
||||||
CustomEdge2: typeof import('./../../components/examples/edges/CustomEdge2.vue')['default']
|
|
||||||
CustomEdgeLabel: typeof import('./../../components/examples/edges/CustomEdgeLabel.vue')['default']
|
|
||||||
CustomInput: typeof import('./../../components/examples/validation/CustomInput.vue')['default']
|
|
||||||
CustomNode: typeof import('./../../components/examples/custom-node/CustomNode.vue')['default']
|
|
||||||
Features: typeof import('./../../components/home/Features.vue')['default']
|
|
||||||
Flow: typeof import('./../../components/examples/multi/Flow.vue')['default']
|
|
||||||
Home: typeof import('./../../components/home/Home.vue')['default']
|
|
||||||
Input: typeof import('./../../components/home/nodes/Input.vue')['default']
|
|
||||||
InteractionControls: typeof import('./../../components/examples/interaction/InteractionControls.vue')['default']
|
|
||||||
Intro: typeof import('./../../components/home/flows/Intro.vue')['default']
|
|
||||||
Nested: typeof import('./../../components/home/flows/Nested.vue')['default']
|
|
||||||
Output: typeof import('./../../components/home/nodes/Output.vue')['default']
|
|
||||||
PiniaExample: typeof import('./../../components/examples/pinia/PiniaExample.vue')['default']
|
|
||||||
Repl: typeof import('./../../components/Repl.vue')['default']
|
|
||||||
RGB: typeof import('./../../components/home/flows/RGB.vue')['default']
|
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
|
||||||
Sidebar: typeof import('./../../components/examples/dnd/Sidebar.vue')['default']
|
|
||||||
TeleportableNode: typeof import('./../../components/examples/teleport/TeleportableNode.vue')['default']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export {}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
import { resolve } from 'path'
|
|
||||||
import { config } from 'dotenv'
|
|
||||||
import { defineUserConfig } from 'vuepress'
|
|
||||||
import type { HeadConfig } from 'vuepress'
|
|
||||||
import { docsearchPlugin } from '@vuepress/plugin-docsearch'
|
|
||||||
import { viteBundler } from '@vuepress/bundler-vite'
|
|
||||||
import WindiCSS from 'vite-plugin-windicss'
|
|
||||||
import Icons from 'unplugin-icons/vite'
|
|
||||||
import IconsResolver from 'unplugin-icons/resolver'
|
|
||||||
import Components from 'unplugin-vue-components/vite'
|
|
||||||
import AutoImport from 'unplugin-auto-import/vite'
|
|
||||||
import seoPlugin from 'vuepress-plugin-seo2'
|
|
||||||
import sitemapPlugin from 'vuepress-plugin-sitemap2'
|
|
||||||
import { copyVueFlowPlugin } from './copy-plugin'
|
|
||||||
import head, { meta } from './head'
|
|
||||||
import Theme from './theme'
|
|
||||||
|
|
||||||
config({ path: resolve(__dirname, '.env') })
|
|
||||||
|
|
||||||
export default defineUserConfig({
|
|
||||||
title: 'Vue Flow',
|
|
||||||
description: 'Visualize your ideas with Vue Flow, a highly customizable Vue3 Flowchart library.',
|
|
||||||
head: head as HeadConfig[],
|
|
||||||
|
|
||||||
dest: resolve(__dirname, '../../dist'),
|
|
||||||
|
|
||||||
bundler: viteBundler({
|
|
||||||
viteOptions: {
|
|
||||||
optimizeDeps: {
|
|
||||||
exclude: ['@animxyz/vue3'],
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
copyVueFlowPlugin(),
|
|
||||||
AutoImport({
|
|
||||||
imports: ['vue', '@vueuse/core'],
|
|
||||||
dts: resolve(__dirname, './auto-imports.d.ts'),
|
|
||||||
}),
|
|
||||||
WindiCSS({
|
|
||||||
transformCSS: 'pre',
|
|
||||||
config: resolve(__dirname, './windi.config.ts'),
|
|
||||||
}),
|
|
||||||
Components({
|
|
||||||
dirs: [resolve(__dirname, '../../components')],
|
|
||||||
deep: true,
|
|
||||||
// allow auto load markdown components under `./src/components/`
|
|
||||||
extensions: ['vue', 'md'],
|
|
||||||
// allow auto import and register components used in markdown
|
|
||||||
include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
|
|
||||||
dts: resolve(__dirname, './components.d.ts'),
|
|
||||||
resolvers: [IconsResolver()],
|
|
||||||
}),
|
|
||||||
Icons({
|
|
||||||
compiler: 'vue3',
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
plugins: [
|
|
||||||
[
|
|
||||||
docsearchPlugin({
|
|
||||||
appId: 'F7BJNSM4M5',
|
|
||||||
apiKey: process.env.ALGOLIA_API_KEY!,
|
|
||||||
indexName: 'vueflow',
|
|
||||||
}),
|
|
||||||
seoPlugin({
|
|
||||||
hostname: meta.url,
|
|
||||||
author: 'Burak Cakmakoglu',
|
|
||||||
}),
|
|
||||||
sitemapPlugin({
|
|
||||||
hostname: meta.url,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
|
|
||||||
theme: Theme,
|
|
||||||
})
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import { defineClientConfig } from '@vuepress/client'
|
|
||||||
import VueAnimXyz from '@animxyz/vue3'
|
|
||||||
|
|
||||||
export default defineClientConfig({
|
|
||||||
enhance({ app, router, siteData }){
|
|
||||||
app.use(VueAnimXyz)
|
|
||||||
},
|
|
||||||
setup(){},
|
|
||||||
rootComponents: [],
|
|
||||||
})
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
import { resolve } from 'path'
|
|
||||||
import { readdirSync, statSync } from 'fs'
|
|
||||||
import type { SidebarConfigArray, Theme } from 'vuepress'
|
|
||||||
import { defaultTheme } from 'vuepress'
|
|
||||||
import { path } from '@vuepress/utils'
|
|
||||||
import { useVueFlow } from '@braks/vue-flow'
|
|
||||||
|
|
||||||
const { vueFlowVersion } = useVueFlow()
|
|
||||||
|
|
||||||
function capitalize(str: string) {
|
|
||||||
return str.charAt(0).toUpperCase() + str.slice(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const typedocSidebarEntries = (): SidebarConfigArray => {
|
|
||||||
const filePath = resolve(__dirname, '../../typedocs')
|
|
||||||
|
|
||||||
const docsModules = readdirSync(filePath).filter((name) => statSync(`${filePath}/${name}`).isDirectory())
|
|
||||||
|
|
||||||
const sidebarItems = docsModules.map((module) => {
|
|
||||||
let children = readdirSync(`${filePath}/${module}/`).map((entry) => `/typedocs/${module}/${entry}`)
|
|
||||||
|
|
||||||
if (module === 'variables') {
|
|
||||||
children = children.filter((child) => {
|
|
||||||
return child.includes('default')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return { text: capitalize(module), children }
|
|
||||||
})
|
|
||||||
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
text: 'Modules',
|
|
||||||
link: '/typedocs/',
|
|
||||||
children: [...sidebarItems],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'vuepress-theme-local',
|
|
||||||
extends: defaultTheme({
|
|
||||||
docsDir: 'docs/src/',
|
|
||||||
docsBranch: 'master',
|
|
||||||
lastUpdated: true,
|
|
||||||
contributors: true,
|
|
||||||
colorMode: 'auto',
|
|
||||||
colorModeSwitch: true,
|
|
||||||
logo: '/favicons/android-chrome-512x512.png',
|
|
||||||
sidebar: {
|
|
||||||
'/guide/': [
|
|
||||||
{
|
|
||||||
text: 'Guide',
|
|
||||||
children: [
|
|
||||||
'/guide/',
|
|
||||||
'/guide/getting-started',
|
|
||||||
'/guide/theming',
|
|
||||||
{
|
|
||||||
text: 'Vue Flow',
|
|
||||||
children: [
|
|
||||||
'/guide/vue-flow/config',
|
|
||||||
'/guide/vue-flow/state',
|
|
||||||
{
|
|
||||||
text: 'Actions',
|
|
||||||
link: '/typedocs/interfaces/Actions.html',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Getters',
|
|
||||||
link: '/typedocs/interfaces/Getters.html',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Events',
|
|
||||||
link: '/typedocs/interfaces/FlowEvents.html',
|
|
||||||
},
|
|
||||||
'/guide/vue-flow/slots',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'/guide/node',
|
|
||||||
'/guide/edge',
|
|
||||||
'/guide/composables',
|
|
||||||
{
|
|
||||||
text: 'Utilities',
|
|
||||||
children: ['/guide/utils/graph', '/guide/utils/instance', '/guide/utils/edge'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Components',
|
|
||||||
children: [
|
|
||||||
'/guide/components/background',
|
|
||||||
'/guide/components/minimap',
|
|
||||||
'/guide/components/minimap-node',
|
|
||||||
'/guide/components/controls',
|
|
||||||
'/guide/components/control-button',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'/examples/': [
|
|
||||||
{
|
|
||||||
text: 'Examples',
|
|
||||||
children: [
|
|
||||||
'/examples/',
|
|
||||||
{
|
|
||||||
text: 'Nodes',
|
|
||||||
children: ['/examples/nodes/', '/examples/nodes/update-node', '/examples/nodes/nesting'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Edges',
|
|
||||||
children: [
|
|
||||||
'/examples/edges/',
|
|
||||||
'/examples/edges/updatable-edge',
|
|
||||||
'/examples/edges/connection-line',
|
|
||||||
'/examples/edges/validation',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'/examples/save',
|
|
||||||
'/examples/dnd',
|
|
||||||
'/examples/empty',
|
|
||||||
'/examples/hidden',
|
|
||||||
'/examples/horizontal',
|
|
||||||
'/examples/interaction',
|
|
||||||
'/examples/teleport',
|
|
||||||
'/examples/multi',
|
|
||||||
'/examples/pinia',
|
|
||||||
'/examples/stress',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'/typedocs/': typedocSidebarEntries(),
|
|
||||||
},
|
|
||||||
navbar: [
|
|
||||||
{ text: `v${vueFlowVersion.value}`, link: '/' },
|
|
||||||
{ text: 'Guide', link: '/guide/', activeMatch: '^/guide/' },
|
|
||||||
{
|
|
||||||
text: 'Examples',
|
|
||||||
link: '/examples/',
|
|
||||||
activeMatch: '^/examples/',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'TypeDocs',
|
|
||||||
link: '/typedocs/',
|
|
||||||
activeMatch: '^/typedocs/',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
layouts: {
|
|
||||||
Layout: resolve(__dirname, 'layouts/default.vue'),
|
|
||||||
},
|
|
||||||
clientConfigFile: path.resolve(__dirname, './clientAppEnhance.ts'),
|
|
||||||
} as Theme
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
<script>
|
|
||||||
import 'virtual:windi.css'
|
|
||||||
import '@animxyz/core'
|
|
||||||
import '@braks/vue-flow/dist/style.css'
|
|
||||||
import '@braks/vue-flow/dist/theme-default.css'
|
|
||||||
import '../../assets/index.css'
|
|
||||||
</script>
|
|
||||||
<script setup>
|
|
||||||
import ParentLayout from '@vuepress/theme-default/lib/client/layouts/Layout.vue'
|
|
||||||
import ReactIcon from '~icons/logos/react'
|
|
||||||
import GithubIcon from '~icons/carbon/logo-github'
|
|
||||||
import DiscordIcon from '~icons/logos/discord-icon'
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<ParentLayout>
|
|
||||||
<template #navbar-before>
|
|
||||||
<XyzTransition appear-visible xyz="fade perspective-1 down ease-out-back duration-10">
|
|
||||||
<div class="border-1 border-gray-300 bg-white dark:bg-gray-800 dark:(shadow-gray-700 shadow-md) shadow-lg select-none flex justify-center items-center mx-2 gap-6 px-4 py-2 rounded-lg">
|
|
||||||
<a
|
|
||||||
href="https://github.com/bcakmakoglu/vue-flow"
|
|
||||||
target="_blank" rel="noopener noreferrer"
|
|
||||||
aria-label="GitHub"
|
|
||||||
class="bg-white rounded-full relative group cursor-pointer flex justify-center items-center"
|
|
||||||
>
|
|
||||||
<GithubIcon class="text-black text-xl transform group-hover:scale-125 transition transition-all ease duration-300" />
|
|
||||||
<span class="transition-opacity ease-in duration-200 opacity-0 group-hover:opacity-100 bg-black dark:bg-white text-white dark:text-black rounded-md p-2 absolute top-[25px] right-0 mt-2 mr-2 text-xs">
|
|
||||||
Contribute on GitHub!
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://discord.gg/F4v6qE4Fuq"
|
|
||||||
target="_blank" rel="noopener noreferrer"
|
|
||||||
aria-label="Discord"
|
|
||||||
class="relative group cursor-pointer flex justify-center items-center"
|
|
||||||
>
|
|
||||||
<DiscordIcon class="text-xl transform group-hover:scale-125 transition transition-all ease duration-300" />
|
|
||||||
<span class="transition-opacity ease-in duration-200 opacity-0 group-hover:opacity-100 bg-black dark:bg-white text-white dark:text-black rounded-md p-2 absolute top-[25px] right-0 mt-2 mr-2 text-xs">
|
|
||||||
Join the Discord server!
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://reactflow.dev/"
|
|
||||||
target="_blank" rel="noopener noreferrer"
|
|
||||||
aria-label="React Flow"
|
|
||||||
class="relative group cursor-pointer flex justify-center items-center"
|
|
||||||
>
|
|
||||||
<ReactIcon class="text-xl transform group-hover:scale-125 transition transition-all ease duration-300" />
|
|
||||||
<span class="transition-opacity ease-in duration-200 opacity-0 group-hover:opacity-100 bg-black dark:bg-white text-white dark:text-black rounded-md p-2 absolute top-[25px] right-0 mt-2 mr-2 text-xs">
|
|
||||||
Check out the original React Flow by Wbkd!
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</XyzTransition>
|
|
||||||
<div class="hidden md:(block w-8) lg:w-12" />
|
|
||||||
</template>
|
|
||||||
<template #page-bottom>
|
|
||||||
<div class="page-footer">MIT Licensed | Copyright © 2021-present Burak Cakmakoglu</div>
|
|
||||||
</template>
|
|
||||||
</ParentLayout>
|
|
||||||
</template>
|
|
||||||
<style>
|
|
||||||
.page-footer {
|
|
||||||
@apply dark:(text-white bg-black) pt-[2rem] text-center;
|
|
||||||
border-top: 1px solid var(--c-border);
|
|
||||||
transition: border-color var(--t-color);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
import { defineConfig } from 'windicss/helpers'
|
|
||||||
import { resolve } from 'path'
|
|
||||||
import typography from 'windicss/plugin/typography'
|
|
||||||
// @ts-ignore
|
|
||||||
import scrollbar from '@windicss/plugin-scrollbar'
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
extract: {
|
|
||||||
include: [
|
|
||||||
resolve(__dirname, './theme/**/*.{ts,md,vue}'),
|
|
||||||
resolve(__dirname, '../../components/**/*.{ts,md,vue}'),
|
|
||||||
resolve(__dirname, '../**/*.{ts,md,vue}')
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
attributify: true,
|
|
||||||
darkMode: 'class',
|
|
||||||
|
|
||||||
plugins: [
|
|
||||||
typography({
|
|
||||||
dark: true,
|
|
||||||
}),
|
|
||||||
scrollbar
|
|
||||||
],
|
|
||||||
|
|
||||||
shortcuts: {
|
|
||||||
'primary-gradient': 'bg-gradient-to-b from-accent-500 via-accent-700 to-accent-900',
|
|
||||||
},
|
|
||||||
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
colors: {
|
|
||||||
primary: {
|
|
||||||
'50': '#fcf9ff',
|
|
||||||
'100': '#f8f3ff',
|
|
||||||
'200': '#eee1fe',
|
|
||||||
'300': '#e4cffe',
|
|
||||||
'400': '#cfaafd',
|
|
||||||
'500': '#BB86FC',
|
|
||||||
'600': '#a879e3',
|
|
||||||
'700': '#8c65bd',
|
|
||||||
'800': '#705097',
|
|
||||||
'900': '#5c427b',
|
|
||||||
'DEFAULT': '#BB86FC',
|
|
||||||
},
|
|
||||||
secondary: {
|
|
||||||
'50': '#c4fef9',
|
|
||||||
'100': '#9df7ef',
|
|
||||||
'200': '#77f0e4',
|
|
||||||
'300': '#50e8da',
|
|
||||||
'400': '#2ae1cf',
|
|
||||||
'500': '#03dac5',
|
|
||||||
'600': '#03ae9d',
|
|
||||||
'700': '#028276',
|
|
||||||
'800': '#02564e',
|
|
||||||
'900': '#012a26',
|
|
||||||
'DEFAULT': '#03dac5',
|
|
||||||
},
|
|
||||||
accent: {
|
|
||||||
'50': '#e6d4ff',
|
|
||||||
'100': '#ccaafc',
|
|
||||||
'200': '#b17ff8',
|
|
||||||
'300': '#9755f5',
|
|
||||||
'400': '#7c2af1',
|
|
||||||
'500': '#6200ee',
|
|
||||||
'600': '#5000c1',
|
|
||||||
'700': '#3d0095',
|
|
||||||
'800': '#2b0068',
|
|
||||||
'900': '#18003b',
|
|
||||||
'DEFAULT': '#6200ee',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -8,7 +8,7 @@ layout: page
|
|||||||
Connections can be validated before edges are created and nodes get connected.
|
Connections can be validated before edges are created and nodes get connected.
|
||||||
|
|
||||||
## Using a handle in a custom node
|
## Using a handle in a custom node
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<div>
|
<div>
|
||||||
[ ... ]
|
[ ... ]
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ The composition API and the power of provide/inject allows us to act more flexib
|
|||||||
a component tree.
|
a component tree.
|
||||||
Thus accessing the internal state of Vue Flow becomes super easy when using composition.
|
Thus accessing the internal state of Vue Flow becomes super easy when using composition.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useVueFlow, VueFlow } from '@braks/vue-flow'
|
import { useVueFlow, VueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ using viewpane transforms.
|
|||||||
All functions can also be accessed from `useVueFlow`.
|
All functions can also be accessed from `useVueFlow`.
|
||||||
It requires a valid Vue Flow store in its context.
|
It requires a valid Vue Flow store in its context.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useZoomPanHelper } from '@braks/vue-flow'
|
import { useZoomPanHelper } from '@braks/vue-flow'
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ You can check the full options for an edge element in the TypeDocs [here](/typed
|
|||||||
|
|
||||||
Generally you create edges by adding them to the model-value or the edges prop of the Vue Flow component.
|
Generally you create edges by adding them to the model-value or the edges prop of the Vue Flow component.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script>
|
<script>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ For more advanced graphs that require more state access you will want to use the
|
|||||||
you with an [`addEdges`](/typedocs/interfaces/Actions.html#addedges/) utility function, which you can use to add edges
|
you with an [`addEdges`](/typedocs/interfaces/Actions.html#addedges/) utility function, which you can use to add edges
|
||||||
directly to the state.
|
directly to the state.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow, useVueFlow } from '@braks/vue-flow'
|
import { VueFlow, useVueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ These edge types include `default` (bezier), `step`, `smoothstep` and `straight`
|
|||||||
|
|
||||||
A bezier edge has a curved path.
|
A bezier edge has a curved path.
|
||||||
|
|
||||||
```js:no-line-numbers
|
```js
|
||||||
const edges = [
|
const edges = [
|
||||||
{
|
{
|
||||||
id: 'e1-2',
|
id: 'e1-2',
|
||||||
@@ -125,7 +125,7 @@ const edges = [
|
|||||||
|
|
||||||
A step edge has a straight path with a step towards the target.
|
A step edge has a straight path with a step towards the target.
|
||||||
|
|
||||||
```js:no-line-numbers{4}
|
```js{4}
|
||||||
const edges = [
|
const edges = [
|
||||||
{
|
{
|
||||||
id: 'e1-2',
|
id: 'e1-2',
|
||||||
@@ -140,7 +140,7 @@ const edges = [
|
|||||||
|
|
||||||
The same as the step edge though with a border radius on the step (rounded step).
|
The same as the step edge though with a border radius on the step (rounded step).
|
||||||
|
|
||||||
```js:no-line-numbers{4}
|
```js{4}
|
||||||
const edges = [
|
const edges = [
|
||||||
{
|
{
|
||||||
id: 'e1-2',
|
id: 'e1-2',
|
||||||
@@ -155,7 +155,7 @@ const edges = [
|
|||||||
|
|
||||||
A simple straight path.
|
A simple straight path.
|
||||||
|
|
||||||
```js:no-line-numbers{4}
|
```js{4}
|
||||||
const edges = [
|
const edges = [
|
||||||
{
|
{
|
||||||
id: 'e1-2',
|
id: 'e1-2',
|
||||||
@@ -171,7 +171,7 @@ const edges = [
|
|||||||
In addition to the default edge types from the previous chapter, you can define any amount of custom edge-types.
|
In addition to the default edge types from the previous chapter, you can define any amount of custom edge-types.
|
||||||
Edge-types are inferred from your edge's definition.
|
Edge-types are inferred from your edge's definition.
|
||||||
|
|
||||||
```js:no-line-numbers{5,11}
|
```js{5,11}
|
||||||
const edges = [
|
const edges = [
|
||||||
{
|
{
|
||||||
id: 'e1-2',
|
id: 'e1-2',
|
||||||
@@ -195,7 +195,7 @@ The easiest way to define custom edges is, by passing them as template slots.
|
|||||||
Your custom edge-types are dynamically resolved to slot-names, meaning an edge with the type `custom`
|
Your custom edge-types are dynamically resolved to slot-names, meaning an edge with the type `custom`
|
||||||
will expect a slot to have the name `edge-custom`.
|
will expect a slot to have the name `edge-custom`.
|
||||||
|
|
||||||
```vue:no-line-numbers{18,26}
|
```vue{18,26}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
import CustomEdge from './CustomEdge.vue'
|
import CustomEdge from './CustomEdge.vue'
|
||||||
@@ -239,7 +239,7 @@ turned into reactive objects.
|
|||||||
Otherwise, vue will throw a warning in the console.
|
Otherwise, vue will throw a warning in the console.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
```vue:no-line-numbers{5-7,28}
|
```vue{5-7,28}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { markRaw } from 'vue'
|
import { markRaw } from 'vue'
|
||||||
import CustomEdge from './CustomEdge.vue'
|
import CustomEdge from './CustomEdge.vue'
|
||||||
@@ -277,7 +277,7 @@ const elements = ref([
|
|||||||
You can also set a template per edge, which will overwrite the edge-type component but will retain
|
You can also set a template per edge, which will overwrite the edge-type component but will retain
|
||||||
the type otherwise.
|
the type otherwise.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { markRaw } from 'vue'
|
import { markRaw } from 'vue'
|
||||||
import CustomEdge from './CustomEdge.vue'
|
import CustomEdge from './CustomEdge.vue'
|
||||||
@@ -358,7 +358,7 @@ In addition to the event handlers that you can access through [`useVueFlow`](/gu
|
|||||||
you can also pass in event handlers in your initial node definition, or you can access the node events through the `events` prop passed
|
you can also pass in event handlers in your initial node definition, or you can access the node events through the `events` prop passed
|
||||||
to your node components.
|
to your node components.
|
||||||
|
|
||||||
```vue:no-line-numbers{19-26}
|
```vue{19-26}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -395,7 +395,7 @@ to forward callback functions to your custom components.
|
|||||||
The `click` handler is part of the [`EdgeEventsHandler`](/typedocs/types/EdgeEventsHandler.html) type, meaning it will be
|
The `click` handler is part of the [`EdgeEventsHandler`](/typedocs/types/EdgeEventsHandler.html) type, meaning it will be
|
||||||
triggered when the edge is clicked.
|
triggered when the edge is clicked.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { EdgeProps, EdgeEventsOn } from '@braks/vue-flow'
|
import type { EdgeProps, EdgeEventsOn } from '@braks/vue-flow'
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<CodeGroup>
|
<CodeGroup>
|
||||||
<CodeGroupItem title="YARN" active>
|
<CodeGroupItem title="YARN" active>
|
||||||
|
|
||||||
```bash:no-line-numbers
|
```bash
|
||||||
yarn add @braks/vue-flow
|
yarn add @braks/vue-flow
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ yarn add @braks/vue-flow
|
|||||||
|
|
||||||
<CodeGroupItem title="NPM">
|
<CodeGroupItem title="NPM">
|
||||||
|
|
||||||
```bash:no-line-numbers
|
```bash
|
||||||
npm i --save @braks/vue-flow
|
npm i --save @braks/vue-flow
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ Together we call them
|
|||||||
A node also needs a [xy-position](/typedocs/interfaces/XYPosition.html/). An edge needs at least a
|
A node also needs a [xy-position](/typedocs/interfaces/XYPosition.html/). An edge needs at least a
|
||||||
source (node id) and a target (node id).
|
source (node id) and a target (node id).
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -79,14 +79,14 @@ A basic setup would look like this:
|
|||||||
<CodeGroup>
|
<CodeGroup>
|
||||||
<CodeGroupItem title="Composition API" active>
|
<CodeGroupItem title="Composition API" active>
|
||||||
|
|
||||||
@[code vue:no-line-numbers](../../../examples/vite/src/Basic/Basic.vue)
|
@[code vue](../../../examples/vite/src/Basic/Basic.vue)
|
||||||
|
|
||||||
</CodeGroupItem>
|
</CodeGroupItem>
|
||||||
|
|
||||||
|
|
||||||
<CodeGroupItem title="Options API">
|
<CodeGroupItem title="Options API">
|
||||||
|
|
||||||
@[code vue:no-line-numbers](../../../examples/vite/src/Basic/BasicOptionsAPI.vue)
|
@[code vue](../../../examples/vite/src/Basic/BasicOptionsAPI.vue)
|
||||||
|
|
||||||
</CodeGroupItem>
|
</CodeGroupItem>
|
||||||
</CodeGroup>
|
</CodeGroup>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ You can check the full options for a node element [here](/typedocs/interfaces/No
|
|||||||
|
|
||||||
Generally you create nodes by adding them to the model-value or the nodes prop of the Vue Flow component.
|
Generally you create nodes by adding them to the model-value or the nodes prop of the Vue Flow component.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script>
|
<script>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ For more advanced graphs that require more state access you will want to use the
|
|||||||
you with an [`addNodes`](/typedocs/interfaces/Actions.html#addnodes/) utility function, which you can use to add nodes
|
you with an [`addNodes`](/typedocs/interfaces/Actions.html#addnodes/) utility function, which you can use to add nodes
|
||||||
directly to the state.
|
directly to the state.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow, useVueFlow } from '@braks/vue-flow'
|
import { VueFlow, useVueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ You can also apply changes using the [`applyNodeChanges`](/typedocs/interfaces/A
|
|||||||
function,
|
function,
|
||||||
which expects an array of [changes](/typedocs/types/NodeChange.html/) to be applied to the currently stored nodes.
|
which expects an array of [changes](/typedocs/types/NodeChange.html/) to be applied to the currently stored nodes.
|
||||||
|
|
||||||
```vue:no-line-numbers{11,17-22}
|
```vue{11,17-22}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow, useVueFlow } from '@braks/vue-flow'
|
import { VueFlow, useVueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ It represents a branching point in your map.
|
|||||||
|
|
||||||
You can specify the position of handles in the node definition.
|
You can specify the position of handles in the node definition.
|
||||||
|
|
||||||
```js:no-line-numbers{5-6}
|
```js{5-6}
|
||||||
const nodes = [
|
const nodes = [
|
||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
@@ -168,7 +168,7 @@ It represents an ending point of your map.
|
|||||||
In addition to the default node types from the previous chapter, you can define any amount of custom node-types.
|
In addition to the default node types from the previous chapter, you can define any amount of custom node-types.
|
||||||
Node-types are inferred from your node's definition.
|
Node-types are inferred from your node's definition.
|
||||||
|
|
||||||
```js:no-line-numbers{5,11}
|
```js{5,11}
|
||||||
const nodes = [
|
const nodes = [
|
||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
@@ -198,7 +198,7 @@ The easiest way to define custom nodes is, by passing them as template slots.
|
|||||||
Your custom node-types are dynamically resolved to slot-names, meaning a node with the type `custom`
|
Your custom node-types are dynamically resolved to slot-names, meaning a node with the type `custom`
|
||||||
will expect a slot to have the name `node-custom`.
|
will expect a slot to have the name `node-custom`.
|
||||||
|
|
||||||
```vue:no-line-numbers{9,16}
|
```vue{9,16}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
import CustomNode from './CustomNode.vue'
|
import CustomNode from './CustomNode.vue'
|
||||||
@@ -232,7 +232,7 @@ turned into reactive objects.
|
|||||||
Otherwise, vue will throw a warning in the console.
|
Otherwise, vue will throw a warning in the console.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
```vue:no-line-numbers{6-9,26}
|
```vue{6-9,26}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { markRaw } from 'vue'
|
import { markRaw } from 'vue'
|
||||||
import CustomNode from './CustomNode.vue'
|
import CustomNode from './CustomNode.vue'
|
||||||
@@ -272,7 +272,7 @@ You can find a more advanced example [here](/examples/custom-node.html/).
|
|||||||
You can also set a template per node, which will overwrite the node-type component but will retain
|
You can also set a template per node, which will overwrite the node-type component but will retain
|
||||||
the type otherwise.
|
the type otherwise.
|
||||||
|
|
||||||
```vue:no-line-numbers{17}
|
```vue{17}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { markRaw } from 'vue'
|
import { markRaw } from 'vue'
|
||||||
import CustomNode from './CustomNode.vue'
|
import CustomNode from './CustomNode.vue'
|
||||||
@@ -339,7 +339,7 @@ you can also pass in event handlers in your initial node definition, or you can
|
|||||||
the `events` prop passed
|
the `events` prop passed
|
||||||
to your node components.
|
to your node components.
|
||||||
|
|
||||||
```vue:no-line-numbers{9-13}
|
```vue{9-13}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -368,7 +368,7 @@ The `click` handler is part of the [`NodeEventsHandler`](/typedocs/types/NodeEve
|
|||||||
will be
|
will be
|
||||||
triggered when the node is clicked.
|
triggered when the node is clicked.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { NodeProps, NodeEventsOn } from '@braks/vue-flow'
|
import type { NodeProps, NodeEventsOn } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -405,7 +405,7 @@ To overwrite default theme styles check the [Theming section](/guide/theming.htm
|
|||||||
|
|
||||||
When you create a new node type you also need to implement some styling. Your custom node has no default styles.
|
When you create a new node type you also need to implement some styling. Your custom node has no default styles.
|
||||||
|
|
||||||
```css:no-line-numbers
|
```css
|
||||||
.vue-flow__node-custom {
|
.vue-flow__node-custom {
|
||||||
background: #9CA8B3;
|
background: #9CA8B3;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@@ -435,7 +435,7 @@ or you can emit the `updateNodeInternals` event from your custom node component
|
|||||||
|
|
||||||
- Using store action
|
- Using store action
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useVueFlow } from '@braks/vue-flow'
|
import { useVueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -449,7 +449,7 @@ const onSomeEvent = () => {
|
|||||||
|
|
||||||
- Emitting event from custom component
|
- Emitting event from custom component
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
const emits = defineEmits(['updateNodeInternals'])
|
const emits = defineEmits(['updateNodeInternals'])
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
VueFlow comes without any pre-injected stylings. Some necessary stylings have to be imported, though optional styles (i.e.
|
VueFlow comes without any pre-injected stylings. Some necessary stylings have to be imported, though optional styles (i.e.
|
||||||
the default theme) can be skipped.
|
the default theme) can be skipped.
|
||||||
|
|
||||||
```css:no-line-numbers
|
```css
|
||||||
/* these are necessary styles for vue flow */
|
/* these are necessary styles for vue flow */
|
||||||
@import '@braks/vue-flow/dist/style.css';
|
@import '@braks/vue-flow/dist/style.css';
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ your own CSS rules, pass style/class properties to the components or use the ava
|
|||||||
|
|
||||||
You can customize the default theme by simply overwriting the class definitions with your own custom ones.
|
You can customize the default theme by simply overwriting the class definitions with your own custom ones.
|
||||||
|
|
||||||
```css:no-line-numbers
|
```css
|
||||||
.vue-flow {
|
.vue-flow {
|
||||||
background: red;
|
background: red;
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ You can customize the default theme by simply overwriting the class definitions
|
|||||||
|
|
||||||
You can also pass a style or class attribute directly to the Vue Flow component.
|
You can also pass a style or class attribute directly to the Vue Flow component.
|
||||||
|
|
||||||
```vue:no-line-numbers{4}
|
```vue{4}
|
||||||
<div style="height: 300px">
|
<div style="height: 300px">
|
||||||
<VueFlow
|
<VueFlow
|
||||||
v-model="elements"
|
v-model="elements"
|
||||||
@@ -41,7 +41,7 @@ You can also pass a style or class attribute directly to the Vue Flow component.
|
|||||||
|
|
||||||
Nodes/Edges can also be styled with a style or class attribute.
|
Nodes/Edges can also be styled with a style or class attribute.
|
||||||
|
|
||||||
```ts:no-line-numbers{8-12,20-27}
|
```ts{7-11,19-26}
|
||||||
const nodes = ref<Node[]>([
|
const nodes = ref<Node[]>([
|
||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
@@ -87,7 +87,7 @@ These variables can either be applied globally or you can define them on an elem
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```ts:no-line-numbers{4-5}
|
```ts{4-5}
|
||||||
const elements = ref<Elements>([
|
const elements = ref<Elements>([
|
||||||
{ id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 } },
|
{ id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 } },
|
||||||
|
|
||||||
@@ -112,8 +112,6 @@ const elements = ref<Elements>([
|
|||||||
| --vf-handle | Node handle color |
|
| --vf-handle | Node handle color |
|
||||||
| --vf-connection-path | Connectionline color |
|
| --vf-connection-path | Connectionline color |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Classes
|
## Classes
|
||||||
|
|
||||||
| Name | Container |
|
| Name | Container |
|
||||||
@@ -126,7 +124,7 @@ const elements = ref<Elements>([
|
|||||||
| .vue-flow__selection | User selection |
|
| .vue-flow__selection | User selection |
|
||||||
| .vue-flow__edges | Edges renderer wrapper |
|
| .vue-flow__edges | Edges renderer wrapper |
|
||||||
| .vue-flow__edge | Edge element wrapper |
|
| .vue-flow__edge | Edge element wrapper |
|
||||||
| .vue-flow__edge-{$type} | Edge type, either a custom or default type |
|
| .vue-flow__edge-{type} | Edge type, either a custom or default type |
|
||||||
| .vue-flow__edge .selected | Selected Edge |
|
| .vue-flow__edge .selected | Selected Edge |
|
||||||
| .vue-flow__edge .animated | Animated edge |
|
| .vue-flow__edge .animated | Animated edge |
|
||||||
| .vue-flow__edge-path | Edge element svg path |
|
| .vue-flow__edge-path | Edge element svg path |
|
||||||
@@ -138,7 +136,7 @@ const elements = ref<Elements>([
|
|||||||
| .vue-flow__nodes | Nodes renderer wrapper |
|
| .vue-flow__nodes | Nodes renderer wrapper |
|
||||||
| .vue-flow__node | Node element wrapper |
|
| .vue-flow__node | Node element wrapper |
|
||||||
| .vue-flow__node .selected | Selected Node |
|
| .vue-flow__node .selected | Selected Node |
|
||||||
| .vue-flow__node-{$type} | Node type, either a custom or default type |
|
| .vue-flow__node-{type} | Node type, either a custom or default type |
|
||||||
| .vue-flow__nodesselection | Nodes selection rect |
|
| .vue-flow__nodesselection | Nodes selection rect |
|
||||||
| .vue-flow__handle | Node handle element wrapper |
|
| .vue-flow__handle | Node handle element wrapper |
|
||||||
| .vue-flow__handle-bottom | Handle position bottom |
|
| .vue-flow__handle-bottom | Handle position bottom |
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
All default edge components are exported and can be used or extended if necessary.
|
All default edge components are exported and can be used or extended if necessary.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
// CustomEdge.vue
|
// CustomEdge.vue
|
||||||
import { EdgeProps, BezierEdge } from '@braks/vue-flow'
|
import { EdgeProps, BezierEdge } from '@braks/vue-flow'
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers{13}
|
```vue{13}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow, isEdge } from '@braks/vue-flow'
|
import { VueFlow, isEdge } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ const toggleClass = () => {
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers{13}
|
```vue{13}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow, isNode } from '@braks/vue-flow'
|
import { VueFlow, isNode } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ of [`useVueFlow`](/guide/composables.html#usevueflow/)
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers{12}
|
```vue{12}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow, addEdge } from '@braks/vue-flow'
|
import { VueFlow, addEdge } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ of [`useVueFlow`](/guide/composables.html#usevueflow/)
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers{12}
|
```vue{12}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow, updateEdge } from '@braks/vue-flow'
|
import { VueFlow, updateEdge } from '@braks/vue-flow'
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ instance provided by [`onPaneReady`](/typedocs/interfaces/FlowEvents.html#panere
|
|||||||
<CodeGroup>
|
<CodeGroup>
|
||||||
<CodeGroupItem title="Composition API" active>
|
<CodeGroupItem title="Composition API" active>
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow, useVueFlow } from '@braks/vue-flow'
|
import { VueFlow, useVueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ onPaneReady((instance) => instance.fitView())
|
|||||||
|
|
||||||
<CodeGroupItem title="Options API">
|
<CodeGroupItem title="Options API">
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script>
|
<script>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```ts:no-line-numbers
|
```ts
|
||||||
vueFlowInstance.project({ x: 100, y: 100 })
|
vueFlowInstance.project({ x: 100, y: 100 })
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ vueFlowInstance.project({ x: 100, y: 100 })
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```ts:no-line-numbers
|
```ts
|
||||||
vueFlowInstance.fitView({ padding: 0.25, includeHiddenNodes: true })
|
vueFlowInstance.fitView({ padding: 0.25, includeHiddenNodes: true })
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ vueFlowInstance.fitView({ padding: 0.25, includeHiddenNodes: true })
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```ts:no-line-numbers
|
```ts
|
||||||
vueFlowInstance.fitBounds(getRectOfNodes(nodes.value))
|
vueFlowInstance.fitBounds(getRectOfNodes(nodes.value))
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ vueFlowInstance.fitBounds(getRectOfNodes(nodes.value))
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```ts:no-line-numbers
|
```ts
|
||||||
vueFlowInstance.setTransform({ x: 100, y: 100, zoom: 1.5 })
|
vueFlowInstance.setTransform({ x: 100, y: 100, zoom: 1.5 })
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ vueFlowInstance.setTransform({ x: 100, y: 100, zoom: 1.5 })
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```ts:no-line-numbers
|
```ts
|
||||||
toObject = (): {
|
toObject = (): {
|
||||||
elements: FlowElements,
|
elements: FlowElements,
|
||||||
position: [x, y],
|
position: [x, y],
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ as options to the [`useVueFlow`](/guide/composables.html#usevueflow/) composable
|
|||||||
<CodeGroup>
|
<CodeGroup>
|
||||||
<CodeGroupItem title="Props" active>
|
<CodeGroupItem title="Props" active>
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<!-- Pass configuration as props -->
|
<!-- Pass configuration as props -->
|
||||||
<template>
|
<template>
|
||||||
<VueFlow :default-zoom="0.5" :max-zoom="4" :min-zoom="0.1" />
|
<VueFlow :default-zoom="0.5" :max-zoom="4" :min-zoom="0.1" />
|
||||||
@@ -19,7 +19,7 @@ as options to the [`useVueFlow`](/guide/composables.html#usevueflow/) composable
|
|||||||
|
|
||||||
<CodeGroupItem title="Composable">
|
<CodeGroupItem title="Composable">
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useVueFlow } from '@braks/vue-flow'
|
import { useVueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ by `useVueFlow`.
|
|||||||
<CodeGroup>
|
<CodeGroup>
|
||||||
<CodeGroupItem title="Props" active>
|
<CodeGroupItem title="Props" active>
|
||||||
|
|
||||||
```vue:no-line-numbers{2,5-6,10}
|
```vue{2,5-6,10}
|
||||||
<script setup>
|
<script setup>
|
||||||
const defaultZoom = ref(1)
|
const defaultZoom = ref(1)
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
<CodeGroupItem title="Composable">
|
<CodeGroupItem title="Composable">
|
||||||
|
|
||||||
```vue:no-line-numbers{2,7-8}
|
```vue{2,7-8}
|
||||||
<script setup>
|
<script setup>
|
||||||
const { defaultZoom } = useVueFlow({
|
const { defaultZoom } = useVueFlow({
|
||||||
defaultZoom: 0.5,
|
defaultZoom: 0.5,
|
||||||
@@ -101,7 +101,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ const elements = ref([
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ const nodes = ref([
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -198,7 +198,7 @@ const edges = ref([
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
import CustomNode from './CustomNode.vue'
|
import CustomNode from './CustomNode.vue'
|
||||||
@@ -235,7 +235,7 @@ const edges = ref([
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
import CustomEdge from './CustomEdge.vue'
|
import CustomEdge from './CustomEdge.vue'
|
||||||
@@ -275,7 +275,7 @@ const edges = ref([
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
import { VueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -496,7 +496,7 @@ const edges = ref([
|
|||||||
|
|
||||||
- Default:
|
- Default:
|
||||||
|
|
||||||
```ts:no-line-numbers
|
```ts
|
||||||
[
|
[
|
||||||
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
|
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
|
||||||
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
|
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
|
||||||
@@ -557,7 +557,7 @@ const edges = ref([
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers{5-6,10}
|
```vue{5-6,10}
|
||||||
<script setup>
|
<script setup>
|
||||||
const elements = ref([
|
const elements = ref([
|
||||||
{ id: '1', label: 'Node 1', position: { x: 250, y: 5 } },
|
{ id: '1', label: 'Node 1', position: { x: 250, y: 5 } },
|
||||||
@@ -585,7 +585,7 @@ const elements = ref([
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers{5-6,10}
|
```vue{5-6,10}
|
||||||
<script setup>
|
<script setup>
|
||||||
const elements = ref([
|
const elements = ref([
|
||||||
{ id: '1', label: 'Node 1', position: { x: 250, y: 5 } },
|
{ id: '1', label: 'Node 1', position: { x: 250, y: 5 } },
|
||||||
@@ -605,7 +605,7 @@ const elements = ref([
|
|||||||
|
|
||||||
- Default:
|
- Default:
|
||||||
|
|
||||||
```ts:no-line-numbers
|
```ts
|
||||||
[
|
[
|
||||||
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
|
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
|
||||||
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
|
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
|
||||||
@@ -620,7 +620,7 @@ const elements = ref([
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers{5-6}
|
```vue{5-6}
|
||||||
<script setup>
|
<script setup>
|
||||||
const elements = ref([
|
const elements = ref([
|
||||||
{ id: '1', label: 'Node 1', position: { x: 250, y: 5 } },
|
{ id: '1', label: 'Node 1', position: { x: 250, y: 5 } },
|
||||||
@@ -676,7 +676,7 @@ const elements = ref([
|
|||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
```vue:no-line-numbers{7-8,12}
|
```vue{7-8,12}
|
||||||
<script setup>
|
<script setup>
|
||||||
const elements = ref([
|
const elements = ref([
|
||||||
{ id: '1', label: 'Node 1', position: { x: 250, y: 5 } },
|
{ id: '1', label: 'Node 1', position: { x: 250, y: 5 } },
|
||||||
@@ -753,7 +753,7 @@ const elements = ref([
|
|||||||
|
|
||||||
##### Boolean value
|
##### Boolean value
|
||||||
|
|
||||||
```vue:no-line-numbers{2}
|
```vue{2}
|
||||||
<template>
|
<template>
|
||||||
<VueFlow v-model="elements" auto-connect />
|
<VueFlow v-model="elements" auto-connect />
|
||||||
</template>
|
</template>
|
||||||
@@ -761,7 +761,7 @@ const elements = ref([
|
|||||||
|
|
||||||
#### [Connector](/typedocs/types/Connector.html/)
|
#### [Connector](/typedocs/types/Connector.html/)
|
||||||
|
|
||||||
```vue:no-line-numbers{6-18,22}
|
```vue{6-18,22}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ You can use the default slot to add a sidebar or floating toolbar etc. to your g
|
|||||||
The connection line slot allows you to pass down a custom connection line component, which will be used, when a connection
|
The connection line slot allows you to pass down a custom connection line component, which will be used, when a connection
|
||||||
is triggered.
|
is triggered.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<template>
|
<template>
|
||||||
<VueFlow>
|
<VueFlow>
|
||||||
<template #connection-line="connectionLineProps">
|
<template #connection-line="connectionLineProps">
|
||||||
@@ -31,7 +31,7 @@ The full description of connection line props can be found [here](/typedocs/inte
|
|||||||
|
|
||||||
The zoom pane slot is placed inside the viewport transformation, so that it scales and moves with the current viewport zoom and position.
|
The zoom pane slot is placed inside the viewport transformation, so that it scales and moves with the current viewport zoom and position.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<template>
|
<template>
|
||||||
<VueFlow>
|
<VueFlow>
|
||||||
<template #zoom-pane>
|
<template #zoom-pane>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ an already existing store from the current context.
|
|||||||
Internal state can be manipulated, for example by adding new elements to the state. The
|
Internal state can be manipulated, for example by adding new elements to the state. The
|
||||||
state is reactive and changes will be reflected on the graph.
|
state is reactive and changes will be reflected on the graph.
|
||||||
|
|
||||||
```vue:no-line-numbers{4-6}
|
```vue{4-6}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useVueFlow } from '@braks/vue-flow'
|
import { useVueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ to reading, writing and updating the state.
|
|||||||
|
|
||||||
Consider this example, where we want to create a Sidebar that allows us to select all nodes.
|
Consider this example, where we want to create a Sidebar that allows us to select all nodes.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<!-- Container.vue -->
|
<!-- Container.vue -->
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
@@ -54,7 +54,7 @@ the flow of information.
|
|||||||
Instead, we can initialize a Vue Flow store instance __before__ the Sidebar is initialized, thus the instance becomes
|
Instead, we can initialize a Vue Flow store instance __before__ the Sidebar is initialized, thus the instance becomes
|
||||||
available as an injection in the component tree.
|
available as an injection in the component tree.
|
||||||
|
|
||||||
```vue:no-line-numbers{5-6}
|
```vue{5-6}
|
||||||
<script>
|
<script>
|
||||||
// Container.vue
|
// Container.vue
|
||||||
import { useVueFlow } from '@braks/vue-flow'
|
import { useVueFlow } from '@braks/vue-flow'
|
||||||
@@ -66,7 +66,7 @@ useVueFlow()
|
|||||||
|
|
||||||
Now we can easily access our current state instance from our Sidebar without passing them as props.
|
Now we can easily access our current state instance from our Sidebar without passing them as props.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useVueFlow } from '@braks/vue-flow'
|
import { useVueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ State updates like removing elements or updating positions are applied by defaul
|
|||||||
If you want to strictly control state changes you can disable this behavior by setting the `applyDefault` option/prop
|
If you want to strictly control state changes you can disable this behavior by setting the `applyDefault` option/prop
|
||||||
to `false`.
|
to `false`.
|
||||||
|
|
||||||
```vue:no-line-numbers
|
```vue
|
||||||
<div style="height: 300px">
|
<div style="height: 300px">
|
||||||
<VueFlow v-model="elements" :apply-default="false" />
|
<VueFlow v-model="elements" :apply-default="false" />
|
||||||
</div>
|
</div>
|
||||||
@@ -120,7 +120,7 @@ Though it is necessary to pass a unique id for your Vue Flow state instance, oth
|
|||||||
will create a new state instance
|
will create a new state instance
|
||||||
when mounted.
|
when mounted.
|
||||||
|
|
||||||
```vue:no-line-numbers{4,32}
|
```vue{4,32}
|
||||||
<script>
|
<script>
|
||||||
import { VueFlow, useVueFlow } from '@braks/vue-flow'
|
import { VueFlow, useVueFlow } from '@braks/vue-flow'
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
---
|
---
|
||||||
home: true
|
layout: home
|
||||||
heroText: null
|
heroText: null
|
||||||
tagline: null
|
tagline: null
|
||||||
footer: MIT Licensed | Copyright © 2021-present Burak Cakmakoglu
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<Home />
|
<Home />
|
||||||
@@ -11,10 +10,12 @@ footer: MIT Licensed | Copyright © 2021-present Burak Cakmakoglu
|
|||||||
<Banner />
|
<Banner />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
||||||
<client-only>
|
<Features />
|
||||||
<Features />
|
|
||||||
|
|
||||||
<XyzTransition appear-visible xyz="fade down ease-out-back">
|
<XyzTransition appear-visible xyz="fade down ease-out-back">
|
||||||
<Acknowledgement />
|
<Acknowledgement />
|
||||||
</XyzTransition>
|
</XyzTransition>
|
||||||
</client-only>
|
|
||||||
|
<XyzTransition appear-visible xyz="fade down ease-out-back">
|
||||||
|
<Team />
|
||||||
|
</XyzTransition>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 375 B After Width: | Height: | Size: 375 B |
|
Before Width: | Height: | Size: 744 B After Width: | Height: | Size: 744 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -17,7 +17,5 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"types": ["vite/client", "@types/node", "unplugin-icons/types/vue"]
|
"types": ["vite/client", "@types/node", "unplugin-icons/types/vue"]
|
||||||
},
|
},
|
||||||
"include": ["components", "src", "src/.vuepress"],
|
"exclude": ["node_modules", "dist"]
|
||||||
"exclude": ["node_modules", "dist"],
|
|
||||||
"references": [{ "path": "./tsconfig.node.json" }]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"composite": true,
|
|
||||||
"module": "esnext",
|
|
||||||
"moduleResolution": "node"
|
|
||||||
},
|
|
||||||
"include": ["vite.config.ts"]
|
|
||||||
}
|
|
||||||
@@ -9,5 +9,6 @@
|
|||||||
"lightHighlightTheme": "vitesse-light",
|
"lightHighlightTheme": "vitesse-light",
|
||||||
"disableSources": true,
|
"disableSources": true,
|
||||||
"out": "src/typedocs",
|
"out": "src/typedocs",
|
||||||
"tsconfig": "../packages/vue-flow/tsconfig.docs.json"
|
"tsconfig": "../packages/vue-flow/tsconfig.docs.json",
|
||||||
|
"entryDocument": "index.md"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
.data.json
|
|
||||||
.temp
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { Repl, ReplStore } from '@vue/repl'
|
|
||||||
import { useVueFlow } from '@braks/vue-flow'
|
|
||||||
import '@vue/repl/style.css'
|
|
||||||
import { exampleImports } from './examples'
|
|
||||||
|
|
||||||
const props = defineProps<{ example: keyof typeof exampleImports; mainFile?: string; dependencies?: Record<string, string> }>()
|
|
||||||
const { vueFlowVersion } = useVueFlow()
|
|
||||||
let css = `@import 'https://cdn.jsdelivr.net/npm/@braks/vue-flow@${vueFlowVersion.value}/dist/style.css';
|
|
||||||
@import 'https://cdn.jsdelivr.net/npm/@braks/vue-flow@${vueFlowVersion.value}/dist/theme-default.css';
|
|
||||||
|
|
||||||
html,
|
|
||||||
body,
|
|
||||||
#app {
|
|
||||||
margin: 0;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#app {
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-family: 'JetBrains Mono', monospace;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
text-align: center;
|
|
||||||
color: #2c3e50;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-flow__minimap {
|
|
||||||
transform: scale(75%);
|
|
||||||
transform-origin: bottom right;
|
|
||||||
}
|
|
||||||
\n`
|
|
||||||
|
|
||||||
const store = new ReplStore({
|
|
||||||
showOutput: true,
|
|
||||||
outputMode: 'preview',
|
|
||||||
})
|
|
||||||
|
|
||||||
const vh = useCssVar('--vh')
|
|
||||||
|
|
||||||
watchEffect(
|
|
||||||
() => {
|
|
||||||
vh.value = `${window.innerHeight}px`
|
|
||||||
},
|
|
||||||
{ flush: 'post' },
|
|
||||||
)
|
|
||||||
|
|
||||||
const files: any = {}
|
|
||||||
const imports = exampleImports[props.example]
|
|
||||||
|
|
||||||
for (const example of Object.keys(imports)) {
|
|
||||||
if (example.includes('css')) {
|
|
||||||
css += `${imports[example as keyof typeof imports]}`
|
|
||||||
} else {
|
|
||||||
files[example] = imports[example as keyof typeof imports]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
await store.setVueVersion('3.2.25')
|
|
||||||
|
|
||||||
await store.setFiles(
|
|
||||||
{
|
|
||||||
...files,
|
|
||||||
'main.css': css,
|
|
||||||
},
|
|
||||||
props.mainFile ?? 'App.vue',
|
|
||||||
)
|
|
||||||
|
|
||||||
// pre-set import map
|
|
||||||
store.setImportMap({
|
|
||||||
imports: {
|
|
||||||
'@braks/vue-flow': `${location.origin}/vue-flow.es.js`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const sfcOptions = {
|
|
||||||
script: {
|
|
||||||
reactivityTransform: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Repl
|
|
||||||
:clear-console="true"
|
|
||||||
:auto-resize="true"
|
|
||||||
:store="store"
|
|
||||||
:show-compile-output="false"
|
|
||||||
:show-import-map="false"
|
|
||||||
:sfc-options="sfcOptions"
|
|
||||||
@keydown.ctrl.s.prevent
|
|
||||||
@keydown.meta.s.prevent
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.file-selector {
|
|
||||||
@apply scrollbar scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-green-500 scrollbar-track-black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vue-repl {
|
|
||||||
--vh: 100vh;
|
|
||||||
|
|
||||||
@apply rounded-lg border-1 border-solid dark:border-gray-200/10 border-gray-200;
|
|
||||||
|
|
||||||
height: calc(var(--vh) - 72px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.msg.err {
|
|
||||||
@apply hidden;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { Background, Controls, MiniMap, VueFlow, isNode, useVueFlow } from '@braks/vue-flow'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import { initialElements } from './initial-elements.js'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* useVueFlow provides all event handlers and store properties
|
|
||||||
* You can pass the composable an object that has the same properties as the VueFlow component props
|
|
||||||
*/
|
|
||||||
const { onPaneReady, onNodeDragStop, onConnect, addEdges, setTransform, toObject } = useVueFlow()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Our elements
|
|
||||||
*/
|
|
||||||
const elements = ref(initialElements)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a Vue Flow event-hook which can be listened to from anywhere you call the composable, instead of only on the main component
|
|
||||||
*
|
|
||||||
* onPaneReady is called when viewpane & nodes have visible dimensions
|
|
||||||
*/
|
|
||||||
onPaneReady(({ fitView }) => {
|
|
||||||
fitView()
|
|
||||||
})
|
|
||||||
|
|
||||||
onNodeDragStop((e) => console.log('drag stop', e))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* onConnect is called when a new connection is created.
|
|
||||||
* You can add additional properties to your new edge (like a type or label) or block the creation altogether
|
|
||||||
*/
|
|
||||||
onConnect((params) => addEdges([params]))
|
|
||||||
|
|
||||||
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) => {
|
|
||||||
if (isNode(el)) {
|
|
||||||
el.position = {
|
|
||||||
x: Math.random() * 400,
|
|
||||||
y: Math.random() * 400,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* toObject transforms your current graph data to an easily persist-able object
|
|
||||||
*/
|
|
||||||
const logToObject = () => console.log(toObject())
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the current viewpane transformation (zoom & pan)
|
|
||||||
*/
|
|
||||||
const resetTransform = () => setTransform({ x: 0, y: 0, zoom: 1 })
|
|
||||||
|
|
||||||
const toggleClass = () => {
|
|
||||||
dark.value = !dark.value
|
|
||||||
elements.value.forEach((el) => (el.class = dark.value ? 'dark' : 'light'))
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VueFlow v-model="elements" class="basicflow" :default-zoom="1.5" :min-zoom="0.2" :max-zoom="4">
|
|
||||||
<Background pattern-color="#aaa" gap="8" />
|
|
||||||
<MiniMap />
|
|
||||||
<Controls />
|
|
||||||
|
|
||||||
<div class="controls">
|
|
||||||
<button style="background-color: #113285; color: white" @click="resetTransform">reset transform</button>
|
|
||||||
<button style="background-color: #6f3381; color: white" @click="updatePos">update positions</button>
|
|
||||||
<button
|
|
||||||
:style="{ backgroundColor: dark ? '#FFFFFB' : '#1C1C1C', color: dark ? '#1C1C1C' : '#FFFFFB' }"
|
|
||||||
@click="toggleClass"
|
|
||||||
>
|
|
||||||
toggle {{ dark ? 'light' : 'dark' }}
|
|
||||||
</button>
|
|
||||||
<button @click="logToObject">log toObject</button>
|
|
||||||
</div>
|
|
||||||
</VueFlow>
|
|
||||||
</template>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export { default as BasicApp } from './App.vue?raw'
|
|
||||||
export { default as BasicElements } from './initial-elements.js?raw'
|
|
||||||
export { default as BasicCSS } from './style.css'
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import { MarkerType } from '@braks/vue-flow'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* You can pass elements together as a v-model value
|
|
||||||
* or split them up into nodes and edges and pass them to the `nodes` and `edges` props of Vue Flow (or useVueFlow composable)
|
|
||||||
*/
|
|
||||||
export const initialElements = [
|
|
||||||
{ id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 }, class: 'light' },
|
|
||||||
{ id: '2', type: 'output', label: 'Node 2', position: { x: 100, y: 100 }, class: 'light' },
|
|
||||||
{ id: '3', label: 'Node 3', position: { x: 400, y: 100 }, class: 'light' },
|
|
||||||
{ id: '4', label: 'Node 4', position: { x: 150, y: 200 }, class: 'light' },
|
|
||||||
{ id: '5', type: 'output', label: 'Node 5', position: { x: 300, y: 300 }, class: 'light' },
|
|
||||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
|
||||||
{ id: 'e1-3', label: 'edge with arrowhead', source: '1', target: '3', markerEnd: MarkerType.Arrow },
|
|
||||||
{
|
|
||||||
id: 'e4-5',
|
|
||||||
type: 'step',
|
|
||||||
label: 'step-edge',
|
|
||||||
source: '4',
|
|
||||||
target: '5',
|
|
||||||
style: { stroke: 'orange' },
|
|
||||||
labelBgStyle: { fill: 'orange' },
|
|
||||||
},
|
|
||||||
{ id: 'e3-4', type: 'smoothstep', label: 'smoothstep-edge', source: '3', target: '4' },
|
|
||||||
]
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
.basicflow .vue-flow__node.dark {
|
|
||||||
background: #1C1C1C;
|
|
||||||
color: #FFFFFB;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basicflow .controls {
|
|
||||||
position: absolute;
|
|
||||||
left: 10px;
|
|
||||||
top: 10px;
|
|
||||||
z-index: 4;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basicflow .controls button {
|
|
||||||
padding: 5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
font-weight: 500;
|
|
||||||
-webkit-box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3);
|
|
||||||
box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basicflow .controls button:hover {
|
|
||||||
opacity: 0.8;
|
|
||||||
transform: scale(105%);
|
|
||||||
transition: 250ms all ease;
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { Background, BackgroundVariant, VueFlow } from '@braks/vue-flow'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import CustomConnectionLine from './CustomConnectionLine.vue'
|
|
||||||
|
|
||||||
const elements = ref([
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
type: 'input',
|
|
||||||
label: 'Node 1',
|
|
||||||
position: { x: 250, y: 5 },
|
|
||||||
},
|
|
||||||
])
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VueFlow v-model="elements">
|
|
||||||
<template #connection-line="props">
|
|
||||||
<CustomConnectionLine v-bind="props" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<Background :variant="BackgroundVariant.Lines" />
|
|
||||||
</VueFlow>
|
|
||||||
</template>
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
const props = defineProps({
|
|
||||||
sourceX: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
sourceY: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
targetX: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
targetY: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<g>
|
|
||||||
<path
|
|
||||||
class="animated"
|
|
||||||
fill="none"
|
|
||||||
stroke="#6F3381"
|
|
||||||
:stroke-width="2.5"
|
|
||||||
:d="`M${sourceX},${sourceY} C ${sourceX} ${targetY} ${sourceX} ${targetY} ${targetX},${targetY}`"
|
|
||||||
/>
|
|
||||||
<circle :cx="targetX" :cy="targetY" fill="#fff" :r="5" stroke="#6F3381" :stroke-width="1.5" />
|
|
||||||
</g>
|
|
||||||
</template>
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export { default as CustomConnectionLineApp } from './App.vue?raw'
|
|
||||||
export { default as CustomConnectionLine } from './CustomConnectionLine.vue?raw'
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { ConnectionMode, MiniMap, Position, VueFlow, useVueFlow } from '@braks/vue-flow'
|
|
||||||
import { computed, h, onMounted, ref } from 'vue'
|
|
||||||
import ColorSelectorNode from './CustomNode.vue'
|
|
||||||
import { presets } from './presets.js'
|
|
||||||
|
|
||||||
const { getNode } = useVueFlow()
|
|
||||||
|
|
||||||
const outputColorNode = computed(() => getNode.value('3'))
|
|
||||||
|
|
||||||
const elements = ref([])
|
|
||||||
|
|
||||||
const gradient = ref(false)
|
|
||||||
const bgColor = ref(presets.ayame)
|
|
||||||
const bgName = ref('AYAME')
|
|
||||||
|
|
||||||
const connectionLineStyle = { stroke: '#fff' }
|
|
||||||
|
|
||||||
// minimap stroke color functions
|
|
||||||
const 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) => {
|
|
||||||
if (n.type === 'custom') return bgColor.value
|
|
||||||
return '#fff'
|
|
||||||
}
|
|
||||||
|
|
||||||
// output labels
|
|
||||||
const outputColorLabel = () => h('div', {}, bgColor.value)
|
|
||||||
const outputNameLabel = () => h('div', {}, bgName.value)
|
|
||||||
|
|
||||||
const onChange = (color) => {
|
|
||||||
gradient.value = false
|
|
||||||
bgColor.value = color.value
|
|
||||||
bgName.value = color.name
|
|
||||||
|
|
||||||
outputColorNode.value.hidden = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const onGradient = () => {
|
|
||||||
gradient.value = true
|
|
||||||
bgColor.value = null
|
|
||||||
bgName.value = 'gradient'
|
|
||||||
|
|
||||||
outputColorNode.value.hidden = true
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
elements.value = [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
type: 'custom',
|
|
||||||
data: { color: bgColor },
|
|
||||||
position: { x: 0, y: 50 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
type: 'output',
|
|
||||||
label: outputNameLabel,
|
|
||||||
position: { x: 350, y: 25 },
|
|
||||||
targetPosition: Position.Left,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '3',
|
|
||||||
type: 'output',
|
|
||||||
label: outputColorLabel,
|
|
||||||
position: { x: 350, y: 200 },
|
|
||||||
targetPosition: Position.Left,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'e1a-2',
|
|
||||||
source: '1',
|
|
||||||
sourceHandle: 'a',
|
|
||||||
target: '2',
|
|
||||||
animated: true,
|
|
||||||
style: () => ({
|
|
||||||
stroke: bgColor.value,
|
|
||||||
filter: 'invert(100%)',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'e1b-3',
|
|
||||||
source: '1',
|
|
||||||
sourceHandle: 'b',
|
|
||||||
target: '3',
|
|
||||||
animated: true,
|
|
||||||
style: () => ({
|
|
||||||
stroke: bgColor.value,
|
|
||||||
filter: 'invert(100%)',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VueFlow
|
|
||||||
v-model="elements"
|
|
||||||
class="customnodeflow"
|
|
||||||
:class="[gradient ? 'animated-bg-gradient' : '']"
|
|
||||||
:style="{ backgroundColor: bgColor }"
|
|
||||||
:connection-mode="ConnectionMode.Loose"
|
|
||||||
:connection-line-style="connectionLineStyle"
|
|
||||||
:default-zoom="1.5"
|
|
||||||
:fit-view-on-init="true"
|
|
||||||
>
|
|
||||||
<template #node-custom="props">
|
|
||||||
<ColorSelectorNode :data="props.data" @change="onChange" @gradient="onGradient" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<MiniMap :node-stroke-color="nodeStroke" :node-color="nodeColor" />
|
|
||||||
</VueFlow>
|
|
||||||
</template>
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { Handle, Position } from '@braks/vue-flow'
|
|
||||||
import { computed } from 'vue'
|
|
||||||
import { presets } from './presets.js'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['change', 'gradient'])
|
|
||||||
|
|
||||||
const onConnect = (params) => console.log('handle onConnect', params)
|
|
||||||
|
|
||||||
const onSelect = (color) => {
|
|
||||||
emit('change', color)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onGradient = () => {
|
|
||||||
emit('gradient')
|
|
||||||
}
|
|
||||||
|
|
||||||
const colors = computed(() => {
|
|
||||||
return Object.keys(presets).map((color) => {
|
|
||||||
return {
|
|
||||||
name: color,
|
|
||||||
value: presets[color],
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const selectedColor = computed(() => {
|
|
||||||
return colors.value.find((color) => color.value === props.data.color)
|
|
||||||
})
|
|
||||||
|
|
||||||
const sourceHandleStyleA = computed(() => ({ backgroundColor: props.data.color, filter: 'invert(100%)', top: '10px' }))
|
|
||||||
const sourceHandleStyleB = computed(() => ({
|
|
||||||
backgroundColor: props.data.color,
|
|
||||||
filter: 'invert(100%)',
|
|
||||||
bottom: '10px',
|
|
||||||
top: 'auto',
|
|
||||||
}))
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>Select a color</div>
|
|
||||||
<div
|
|
||||||
style="display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center; max-width: 90%; margin: auto; gap: 3px"
|
|
||||||
>
|
|
||||||
<template v-for="color of colors" :key="color.name">
|
|
||||||
<button :title="color.name" :style="{ backgroundColor: color.value }" type="button" @click="onSelect(color)"></button>
|
|
||||||
</template>
|
|
||||||
<button class="animated-bg-gradient" title="gradient" type="button" @click="onGradient"></button>
|
|
||||||
</div>
|
|
||||||
<Handle id="a" type="source" :position="Position.Right" :style="sourceHandleStyleA" />
|
|
||||||
<Handle id="b" type="source" :position="Position.Right" :style="sourceHandleStyleB" />
|
|
||||||
</template>
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export { default as CustomNodeApp } from './App.vue?raw'
|
|
||||||
export { default as CustomNode } from './CustomNode.vue?raw'
|
|
||||||
export { default as CustomNodeCSS } from './style.css'
|
|
||||||
export { default as ColorPresets } from './presets.js?raw'
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
export const presets = {
|
|
||||||
sumi: '#1C1C1C',
|
|
||||||
gofun: '#FFFFFB',
|
|
||||||
byakuroku: '#A8D8B9',
|
|
||||||
mizu: '#81C7D4',
|
|
||||||
asagi: '#33A6B8',
|
|
||||||
ukon: '#EFBB24',
|
|
||||||
mushikuri: '#D9CD90',
|
|
||||||
hiwa: '#BEC23F',
|
|
||||||
ichigo: '#B5495B',
|
|
||||||
kurenai: '#CB1B45',
|
|
||||||
syojyohi: '#E83015',
|
|
||||||
konjyo: '#113285',
|
|
||||||
fuji: '#8B81C3',
|
|
||||||
ayame: '#6F3381',
|
|
||||||
torinoko: '#DAC9A6',
|
|
||||||
kurotsurubami: '#0B1013',
|
|
||||||
ohni: '#F05E1C',
|
|
||||||
kokikuchinashi: '#FB9966',
|
|
||||||
beniukon: '#E98B2A',
|
|
||||||
sakura: '#FEDFE1',
|
|
||||||
toki: '#EEA9A9',
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
.customnodeflow .vue-flow__node-custom {
|
|
||||||
border: 1px solid #777;
|
|
||||||
padding: 10px;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: whitesmoke;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
max-width: 250px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.customnodeflow button {
|
|
||||||
padding: 5px;
|
|
||||||
width: 25px;
|
|
||||||
height: 25px;
|
|
||||||
border-radius: 25px;
|
|
||||||
-webkit-box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3);
|
|
||||||
box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.customnodeflow button:hover {
|
|
||||||
opacity: 0.9;
|
|
||||||
transform: scale(105%);
|
|
||||||
transition: 250ms all ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.animated-bg-gradient {
|
|
||||||
background: linear-gradient(122deg, #6f3381, #81c7d4, #fedfe1, #fffffb);
|
|
||||||
background-size: 800% 800%;
|
|
||||||
|
|
||||||
-webkit-animation: gradient 4s ease infinite;
|
|
||||||
-moz-animation: gradient 4s ease infinite;
|
|
||||||
animation: gradient 4s ease infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes gradient {
|
|
||||||
0% {
|
|
||||||
background-position: 0% 22%
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
background-position: 100% 79%
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
background-position: 0% 22%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@-moz-keyframes gradient {
|
|
||||||
0% {
|
|
||||||
background-position: 0% 22%
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
background-position: 100% 79%
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
background-position: 0% 22%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes gradient {
|
|
||||||
0% {
|
|
||||||
background-position: 0% 22%
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
background-position: 100% 79%
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
background-position: 0% 22%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { VueFlow, useVueFlow } from '@braks/vue-flow'
|
|
||||||
import Sidebar from './Sidebar.vue'
|
|
||||||
|
|
||||||
let id = 0
|
|
||||||
const getId = () => `dndnode_${id++}`
|
|
||||||
|
|
||||||
const { onConnect, nodes, edges, addEdges, addNodes, viewport, project } = useVueFlow({
|
|
||||||
nodes: [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
type: 'input',
|
|
||||||
label: 'input node',
|
|
||||||
position: { x: 250, y: 25 },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
const onDragOver = (event) => {
|
|
||||||
event.preventDefault()
|
|
||||||
if (event.dataTransfer) {
|
|
||||||
event.dataTransfer.dropEffect = 'move'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onConnect((params) => addEdges([params]))
|
|
||||||
|
|
||||||
const onDrop = (event) => {
|
|
||||||
const type = event.dataTransfer?.getData('application/vueflow')
|
|
||||||
const position = project({ x: event.clientX - 40, y: event.clientY - 18 })
|
|
||||||
const newNode = {
|
|
||||||
id: getId(),
|
|
||||||
type,
|
|
||||||
position,
|
|
||||||
label: `${type} node`,
|
|
||||||
}
|
|
||||||
addNodes([newNode])
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="dndflow" @drop="onDrop">
|
|
||||||
<VueFlow @dragover="onDragOver" />
|
|
||||||
<Sidebar />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
const onDragStart = (event, nodeType) => {
|
|
||||||
if (event.dataTransfer) {
|
|
||||||
event.dataTransfer.setData('application/vueflow', nodeType)
|
|
||||||
event.dataTransfer.effectAllowed = 'move'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<aside>
|
|
||||||
<div class="description">You can drag these nodes to the pane.</div>
|
|
||||||
<div class="nodes">
|
|
||||||
<div class="vue-flow__node-input" :draggable="true" @dragstart="onDragStart($event, 'input')">Input Node</div>
|
|
||||||
<div class="vue-flow__node-default" :draggable="true" @dragstart="onDragStart($event, 'default')">Default Node</div>
|
|
||||||
<div class="vue-flow__node-output" :draggable="true" @dragstart="onDragStart($event, 'output')">Output Node</div>
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
</template>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export { default as DndApp } from './App.vue?raw'
|
|
||||||
export { default as DndSidebar } from './Sidebar.vue?raw'
|
|
||||||
export { default as DndCSS } from './style.css'
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
.dndflow {
|
|
||||||
flex-direction: column;
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dndflow aside {
|
|
||||||
color: white;
|
|
||||||
font-weight: 700;
|
|
||||||
border-right: 1px solid #eee;
|
|
||||||
padding: 15px 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
background: rgba(16, 185, 129, 0.75);
|
|
||||||
-webkit-box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.3);
|
|
||||||
box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dndflow aside .nodes > * {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
cursor: grab;
|
|
||||||
font-weight: 500;
|
|
||||||
-webkit-box-shadow: 5px 5px 10px 2px rgba(0,0,0,0.25);
|
|
||||||
box-shadow: 5px 5px 10px 2px rgba(0,0,0,0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dndflow aside .description {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dndflow .vue-flow-wrapper {
|
|
||||||
flex-grow: 1;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 640px) {
|
|
||||||
.dndflow {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dndflow aside {
|
|
||||||
min-width: 25%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 639px) {
|
|
||||||
.dndflow aside .nodes {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { Background, Controls, MarkerType, MiniMap, VueFlow } from '@braks/vue-flow'
|
|
||||||
import { h, ref } from 'vue'
|
|
||||||
import CustomEdge from './CustomEdge.vue'
|
|
||||||
import CustomEdge2 from './CustomEdge2.vue'
|
|
||||||
import CustomEdgeLabel from './CustomEdgeLabel.vue'
|
|
||||||
|
|
||||||
const elements = ref([
|
|
||||||
{ id: '1', type: 'input', label: 'Start', position: { x: 50, y: 0 }, style: { borderColor: '#10b981' } },
|
|
||||||
{ id: '2', label: 'Node 2', position: { x: 150, y: 100 } },
|
|
||||||
{ id: '2a', label: 'Node 2a', position: { x: 0, y: 180 } },
|
|
||||||
{ id: '3', label: 'Node 3', position: { x: 250, y: 200 } },
|
|
||||||
{ id: '4', label: 'Node 4', position: { x: 400, y: 300 } },
|
|
||||||
{ id: '3a', label: 'Node 3a', position: { x: 175, y: 300 } },
|
|
||||||
{ id: '5', label: 'Node 5', position: { x: 200, y: 400 } },
|
|
||||||
{ id: '6', type: 'output', label: 'Output 6', position: { x: 0, y: 350 } },
|
|
||||||
{ id: '7', type: 'output', label: 'Output 7', position: { x: 50, y: 600 } },
|
|
||||||
{ id: '8', type: 'output', label: 'Output 8', position: { x: 350, y: 600 } },
|
|
||||||
{ id: '9', type: 'output', label: 'Output 9', position: { x: 550, y: 400 } },
|
|
||||||
{ id: 'e1-2', source: '1', target: '2', label: 'bezier edge (default)', class: 'normal-edge' },
|
|
||||||
{ id: 'e2-2a', source: '2', target: '2a', type: 'smoothstep', label: 'smoothstep edge' },
|
|
||||||
{ id: 'e2-3', source: '2', target: '3', type: 'step', label: 'step edge' },
|
|
||||||
{ id: 'e3-4', source: '3', target: '4', type: 'straight', label: 'straight edge' },
|
|
||||||
{ id: 'e3-3a', source: '3', target: '3a', type: 'straight', label: 'label only edge', style: { stroke: 'none' } },
|
|
||||||
{ id: 'e3-5', source: '4', target: '5', animated: true, label: 'animated styled edge', style: { stroke: '#10b981' } },
|
|
||||||
{
|
|
||||||
id: 'e2a-6',
|
|
||||||
source: '2a',
|
|
||||||
target: '6',
|
|
||||||
label: () => h(CustomEdgeLabel, { label: 'custom label text' }),
|
|
||||||
labelStyle: { fill: '#10b981', fontWeight: 700 },
|
|
||||||
markerEnd: MarkerType.Arrow,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'e5-7',
|
|
||||||
source: '5',
|
|
||||||
target: '7',
|
|
||||||
label: 'label with bg',
|
|
||||||
labelBgPadding: [8, 4],
|
|
||||||
labelBgBorderRadius: 4,
|
|
||||||
labelBgStyle: { fill: '#FFCC00', color: '#fff', fillOpacity: 0.7 },
|
|
||||||
markerEnd: MarkerType.ArrowClosed,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'e5-8',
|
|
||||||
source: '5',
|
|
||||||
target: '8',
|
|
||||||
type: 'custom',
|
|
||||||
data: { text: 'custom edge' },
|
|
||||||
markerEnd: MarkerType.ArrowClosed,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'e4-9',
|
|
||||||
source: '4',
|
|
||||||
target: '9',
|
|
||||||
type: 'custom2',
|
|
||||||
data: { text: 'styled custom edge label' },
|
|
||||||
},
|
|
||||||
])
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VueFlow v-model="elements" :fit-view-on-init="true" :snap-to-grid="true">
|
|
||||||
<template #edge-custom="props">
|
|
||||||
<CustomEdge v-bind="props" />
|
|
||||||
</template>
|
|
||||||
<template #edge-custom2="props">
|
|
||||||
<CustomEdge2 v-bind="props" />
|
|
||||||
</template>
|
|
||||||
<MiniMap />
|
|
||||||
<Controls />
|
|
||||||
<Background />
|
|
||||||
</VueFlow>
|
|
||||||
</template>
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { getBezierPath, getEdgeCenter, useVueFlow } from '@braks/vue-flow'
|
|
||||||
import { computed } from 'vue'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
sourceX: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
sourceY: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
targetX: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
targetY: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
sourcePosition: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
targetPosition: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
markerEnd: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const { applyEdgeChanges } = useVueFlow()
|
|
||||||
|
|
||||||
const foreignObjectSize = 40
|
|
||||||
|
|
||||||
const onClick = (evt, id) => {
|
|
||||||
applyEdgeChanges([{ type: 'remove', id }])
|
|
||||||
evt.stopPropagation()
|
|
||||||
}
|
|
||||||
|
|
||||||
const edgePath = computed(() =>
|
|
||||||
getBezierPath({
|
|
||||||
sourceX: props.sourceX,
|
|
||||||
sourceY: props.sourceY,
|
|
||||||
sourcePosition: props.sourcePosition,
|
|
||||||
targetX: props.targetX,
|
|
||||||
targetY: props.targetY,
|
|
||||||
targetPosition: props.targetPosition,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
const center = computed(() =>
|
|
||||||
getEdgeCenter({
|
|
||||||
sourceX: props.sourceX,
|
|
||||||
sourceY: props.sourceY,
|
|
||||||
targetX: props.targetX,
|
|
||||||
targetY: props.targetY,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
inheritAttrs: false,
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<path :id="id" :style="style" class="vue-flow__edge-path" :d="edgePath" :marker-end="markerEnd" />
|
|
||||||
<foreignObject
|
|
||||||
:width="foreignObjectSize"
|
|
||||||
:height="foreignObjectSize"
|
|
||||||
:x="center[0] - foreignObjectSize / 2"
|
|
||||||
:y="center[1] - foreignObjectSize / 2"
|
|
||||||
class="edgebutton-foreignobject"
|
|
||||||
requiredExtensions="http://www.w3.org/1999/xhtml"
|
|
||||||
>
|
|
||||||
<body style="display: flex; align-items: center; justify-content: center">
|
|
||||||
<div>
|
|
||||||
<button ref="btn" class="edgebutton" @click="(event) => onClick(event, id)">×</button>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</foreignObject>
|
|
||||||
</template>
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { EdgeText, getBezierPath, getEdgeCenter } from '@braks/vue-flow'
|
|
||||||
import { computed } from 'vue'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
sourceX: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
sourceY: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
targetX: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
targetY: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
sourcePosition: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
targetPosition: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
markerEnd: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
sourceHandleId: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
targetHandleId: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const edgePath = computed(() =>
|
|
||||||
getBezierPath({
|
|
||||||
sourceX: props.sourceX,
|
|
||||||
sourceY: props.sourceY,
|
|
||||||
sourcePosition: props.sourcePosition,
|
|
||||||
targetX: props.targetX,
|
|
||||||
targetY: props.targetY,
|
|
||||||
targetPosition: props.targetPosition,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
const center = computed(() =>
|
|
||||||
getEdgeCenter({
|
|
||||||
sourceX: props.sourceX,
|
|
||||||
sourceY: props.sourceY,
|
|
||||||
targetX: props.targetX,
|
|
||||||
targetY: props.targetY,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
const onClick = () => console.log(props.data)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
inheritAttrs: false,
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<path :id="props.id" class="vue-flow__edge-path" :d="edgePath" :marker-end="props.markerEnd" />
|
|
||||||
<EdgeText
|
|
||||||
:x="center[0]"
|
|
||||||
:y="center[1]"
|
|
||||||
:label="props.data?.text"
|
|
||||||
:label-style="{ fill: 'white' }"
|
|
||||||
:label-show-bg="true"
|
|
||||||
:label-bg-style="{ fill: '#10b981' }"
|
|
||||||
:label-bg-padding="[2, 4]"
|
|
||||||
:label-bg-border-radius="2"
|
|
||||||
@click="onClick"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
const props = defineProps({
|
|
||||||
label: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<tspan dy="10" x="0">{{ props.label }}</tspan>
|
|
||||||
</template>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export { default as EdgesApp } from './App.vue?raw'
|
|
||||||
export { default as CustomEdge } from './CustomEdge.vue?raw'
|
|
||||||
export { default as CustomEdge2 } from './CustomEdge2.vue?raw'
|
|
||||||
export { default as CustomEdgeLabel } from './CustomEdgeLabel.vue?raw'
|
|
||||||
export { default as EdgeCSS } from './style.css'
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
.edgebutton {
|
|
||||||
border-radius: 999px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.edgebutton:hover {
|
|
||||||
transform: scale(110%);
|
|
||||||
transition: all ease 500ms;
|
|
||||||
box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.5), 0 0 0 4px #10b981;
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { Background, BackgroundVariant, Controls, MiniMap, VueFlow, useVueFlow } from '@braks/vue-flow'
|
|
||||||
|
|
||||||
const { nodes, addNodes, edges, addEdges, onConnect, onPaneReady, onNodeDragStop, dimensions } = useVueFlow()
|
|
||||||
|
|
||||||
onConnect((params) => addEdges([params]))
|
|
||||||
onPaneReady((flowInstance) => console.log('flow loaded:', flowInstance))
|
|
||||||
onNodeDragStop((node) => console.log('drag stop', node))
|
|
||||||
|
|
||||||
const addRandomNode = () => {
|
|
||||||
const nodeId = (nodes.value.length + 1).toString()
|
|
||||||
const newNode = {
|
|
||||||
id: nodeId,
|
|
||||||
label: `Node: ${nodeId}`,
|
|
||||||
position: { x: Math.random() * dimensions.value.width, y: Math.random() * dimensions.value.height },
|
|
||||||
}
|
|
||||||
addNodes([newNode])
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VueFlow>
|
|
||||||
<MiniMap />
|
|
||||||
<Controls />
|
|
||||||
<Background :variant="BackgroundVariant.Lines" />
|
|
||||||
|
|
||||||
<button type="button" :style="{ position: 'absolute', left: '10px', top: '10px', zIndex: 4 }" @click="addRandomNode">
|
|
||||||
add node
|
|
||||||
</button>
|
|
||||||
</VueFlow>
|
|
||||||
</template>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { default as EmptyApp } from './App.vue?raw'
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { Controls, MiniMap, VueFlow, useVueFlow } from '@braks/vue-flow'
|
|
||||||
import { ref, watchEffect } from 'vue'
|
|
||||||
|
|
||||||
const isHidden = ref(false)
|
|
||||||
|
|
||||||
const { nodes, edges } = useVueFlow({
|
|
||||||
nodes: [
|
|
||||||
{ id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 } },
|
|
||||||
{ id: '2', label: 'Node 2', position: { x: 100, y: 100 } },
|
|
||||||
{ id: '3', label: 'Node 3', position: { x: 400, y: 100 } },
|
|
||||||
{ id: '4', label: 'Node 4', position: { x: 400, y: 200 } },
|
|
||||||
],
|
|
||||||
edges: [
|
|
||||||
{ id: 'e1-2', source: '1', target: '2' },
|
|
||||||
{ id: 'e1-3', source: '1', target: '3' },
|
|
||||||
{ id: 'e3-4', source: '3', target: '4' },
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
nodes.value.forEach((n) => (n.hidden = isHidden.value))
|
|
||||||
edges.value.forEach((e) => (e.hidden = isHidden.value))
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VueFlow>
|
|
||||||
<MiniMap />
|
|
||||||
<Controls />
|
|
||||||
|
|
||||||
<div :style="{ position: 'absolute', left: '10px', top: '10px', zIndex: 4 }">
|
|
||||||
<div>
|
|
||||||
<label for="ishidden">
|
|
||||||
hidden
|
|
||||||
<input id="ishidden" v-model="isHidden" type="checkbox" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</VueFlow>
|
|
||||||
</template>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { default as HiddenApp } from './App.vue?raw'
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { Background, Controls, MiniMap, VueFlow, useVueFlow } from '@braks/vue-flow'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import { initialElements } from './initial-elements.js'
|
|
||||||
|
|
||||||
const { onConnect, addEdges } = useVueFlow()
|
|
||||||
|
|
||||||
const elements = ref(initialElements)
|
|
||||||
|
|
||||||
onConnect((params) => addEdges([params]))
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VueFlow
|
|
||||||
v-model="elements"
|
|
||||||
class="basicflow"
|
|
||||||
:default-edge-options="{ type: 'smoothstep' }"
|
|
||||||
:default-zoom="1.5"
|
|
||||||
:min-zoom="0.2"
|
|
||||||
:max-zoom="4"
|
|
||||||
:fit-view-on-init="true"
|
|
||||||
>
|
|
||||||
<Background pattern-color="#aaa" gap="8" />
|
|
||||||
<MiniMap />
|
|
||||||
<Controls />
|
|
||||||
</VueFlow>
|
|
||||||
</template>
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export { default as HorizontalApp } from './App.vue?raw'
|
|
||||||
export { default as HorizontalElements } from './initial-elements.js?raw'
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
import { MarkerType, Position } from '@braks/vue-flow'
|
|
||||||
|
|
||||||
export const initialElements = [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
type: 'input',
|
|
||||||
label: 'Node 1',
|
|
||||||
position: { x: 0, y: 50 },
|
|
||||||
sourcePosition: Position.Right,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
type: 'output',
|
|
||||||
label: 'Node 2',
|
|
||||||
position: { x: 250, y: 0 },
|
|
||||||
targetPosition: Position.Left,
|
|
||||||
},
|
|
||||||
{ id: '3', label: 'Node 3', position: { x: 250, y: 100 }, sourcePosition: Position.Right, targetPosition: Position.Left },
|
|
||||||
{ id: '4', label: 'Node 4', position: { x: 500, y: 150 }, sourcePosition: Position.Right, targetPosition: Position.Left },
|
|
||||||
{
|
|
||||||
id: '5',
|
|
||||||
type: 'output',
|
|
||||||
label: 'Node 5',
|
|
||||||
position: { x: 750, y: 50 },
|
|
||||||
sourcePosition: Position.Right,
|
|
||||||
targetPosition: Position.Left,
|
|
||||||
},
|
|
||||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
|
||||||
{ id: 'e1-3', source: '1', target: '3', markerEnd: MarkerType.Arrow },
|
|
||||||
{
|
|
||||||
id: 'e4-5',
|
|
||||||
source: '4',
|
|
||||||
target: '5',
|
|
||||||
style: { stroke: 'orange' },
|
|
||||||
labelBgStyle: { fill: 'orange' },
|
|
||||||
},
|
|
||||||
{ id: 'e3-4', source: '3', target: '4' },
|
|
||||||
]
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
import { BasicApp, BasicCSS, BasicElements } from './basic'
|
|
||||||
import { ColorPresets, CustomNode, CustomNodeApp, CustomNodeCSS } from './custom-node'
|
|
||||||
import { CustomConnectionLine, CustomConnectionLineApp } from './connectionline'
|
|
||||||
import { CustomEdge, CustomEdge2, CustomEdgeLabel, EdgeCSS, EdgesApp } from './edges'
|
|
||||||
import { NestedApp } from './nested'
|
|
||||||
import { StressApp, StressCSS, StressUtils } from './stress'
|
|
||||||
import { UpdateEdgeApp } from './update-edge'
|
|
||||||
import { UpdateNodeApp, UpdateNodeCSS } from './update-node'
|
|
||||||
import { ValidationApp, ValidationCSS, ValidationCustomInput, ValidationCustomNode } from './validation'
|
|
||||||
import { SaveRestoreApp, SaveRestoreCSS, SaveRestoreControls } from './save-restore'
|
|
||||||
import { DndApp, DndCSS, DndSidebar } from './dnd'
|
|
||||||
import { EmptyApp } from './empty'
|
|
||||||
import { HiddenApp } from './hidden'
|
|
||||||
import { InteractionApp, InteractionCSS, InteractionControls } from './interaction'
|
|
||||||
import { MultiApp, MultiCSS, MultiFlow } from './multi'
|
|
||||||
import { HorizontalApp, HorizontalElements } from './horizontal'
|
|
||||||
import { TeleportApp, TeleportCSS, TeleportSidebar, TeleportableNode, TeleportableUseTransition } from './teleport'
|
|
||||||
|
|
||||||
export const exampleImports = {
|
|
||||||
basic: {
|
|
||||||
'App.vue': BasicApp,
|
|
||||||
'initial-elements.js': BasicElements,
|
|
||||||
'style.css': BasicCSS,
|
|
||||||
},
|
|
||||||
customNode: {
|
|
||||||
'App.vue': CustomNodeApp,
|
|
||||||
'CustomNode.vue': CustomNode,
|
|
||||||
'style.css': CustomNodeCSS,
|
|
||||||
'presets.js': ColorPresets,
|
|
||||||
},
|
|
||||||
connectionline: {
|
|
||||||
'App.vue': CustomConnectionLineApp,
|
|
||||||
'CustomConnectionLine.vue': CustomConnectionLine,
|
|
||||||
},
|
|
||||||
edges: {
|
|
||||||
'App.vue': EdgesApp,
|
|
||||||
'CustomEdge.vue': CustomEdge,
|
|
||||||
'CustomEdge2.vue': CustomEdge2,
|
|
||||||
'CustomEdgeLabel.vue': CustomEdgeLabel,
|
|
||||||
'style.css': EdgeCSS,
|
|
||||||
},
|
|
||||||
nested: {
|
|
||||||
'App.vue': NestedApp,
|
|
||||||
},
|
|
||||||
stress: {
|
|
||||||
'App.vue': StressApp,
|
|
||||||
'utils.js': StressUtils,
|
|
||||||
'style.css': StressCSS,
|
|
||||||
},
|
|
||||||
updateEdge: {
|
|
||||||
'App.vue': UpdateEdgeApp,
|
|
||||||
},
|
|
||||||
updateNode: {
|
|
||||||
'App.vue': UpdateNodeApp,
|
|
||||||
'style.css': UpdateNodeCSS,
|
|
||||||
},
|
|
||||||
validation: {
|
|
||||||
'App.vue': ValidationApp,
|
|
||||||
'CustomInput.vue': ValidationCustomInput,
|
|
||||||
'CustomNode.vue': ValidationCustomNode,
|
|
||||||
'style.css': ValidationCSS,
|
|
||||||
},
|
|
||||||
saveRestore: {
|
|
||||||
'App.vue': SaveRestoreApp,
|
|
||||||
'Controls.vue': SaveRestoreControls,
|
|
||||||
'style.css': SaveRestoreCSS,
|
|
||||||
},
|
|
||||||
dnd: {
|
|
||||||
'App.vue': DndApp,
|
|
||||||
'Sidebar.vue': DndSidebar,
|
|
||||||
'style.css': DndCSS,
|
|
||||||
},
|
|
||||||
empty: {
|
|
||||||
'App.vue': EmptyApp,
|
|
||||||
},
|
|
||||||
hidden: {
|
|
||||||
'App.vue': HiddenApp,
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
'App.vue': InteractionApp,
|
|
||||||
'InteractionControls.vue': InteractionControls,
|
|
||||||
'style.css': InteractionCSS,
|
|
||||||
},
|
|
||||||
multi: {
|
|
||||||
'App.vue': MultiApp,
|
|
||||||
'Flow.vue': MultiFlow,
|
|
||||||
'style.css': MultiCSS,
|
|
||||||
},
|
|
||||||
horizontal: {
|
|
||||||
'App.vue': HorizontalApp,
|
|
||||||
'initial-elements.js': HorizontalElements,
|
|
||||||
},
|
|
||||||
teleport: {
|
|
||||||
'App.vue': TeleportApp,
|
|
||||||
'Sidebar.vue': TeleportSidebar,
|
|
||||||
'TeleportableNode.vue': TeleportableNode,
|
|
||||||
'useTransition.js': TeleportableUseTransition,
|
|
||||||
'style.css': TeleportCSS,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import InteractionControls from './InteractionControls.vue'
|
|
||||||
|
|
||||||
const elements = ref([
|
|
||||||
{ id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 } },
|
|
||||||
{ id: '2', label: 'Node 2', position: { x: 100, y: 100 } },
|
|
||||||
{ id: '3', label: 'Node 3', position: { x: 400, y: 100 } },
|
|
||||||
{ id: '4', label: 'Node 4', position: { x: 400, y: 200 } },
|
|
||||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
|
||||||
{ id: 'e1-3', source: '1', target: '3' },
|
|
||||||
])
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VueFlow class="interactionflow" v-model="elements" :fit-view-on-init="true">
|
|
||||||
<InteractionControls />
|
|
||||||
</VueFlow>
|
|
||||||
</template>
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { useVueFlow } from '@braks/vue-flow'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
const {
|
|
||||||
nodesDraggable,
|
|
||||||
nodesConnectable,
|
|
||||||
elementsSelectable,
|
|
||||||
zoomOnScroll,
|
|
||||||
zoomOnDoubleClick,
|
|
||||||
zoomOnPinch,
|
|
||||||
panOnScroll,
|
|
||||||
panOnScrollMode,
|
|
||||||
panOnDrag,
|
|
||||||
onConnect,
|
|
||||||
onNodeDragStop,
|
|
||||||
onPaneClick,
|
|
||||||
onPaneScroll,
|
|
||||||
onPaneContextMenu,
|
|
||||||
onNodeDragStart,
|
|
||||||
onMoveEnd,
|
|
||||||
addEdges,
|
|
||||||
} = useVueFlow()
|
|
||||||
|
|
||||||
const captureZoomClick = ref(false)
|
|
||||||
const captureZoomScroll = ref(false)
|
|
||||||
|
|
||||||
onConnect((params) => addEdges([params]))
|
|
||||||
onNodeDragStart((e) => console.log('drag start', e))
|
|
||||||
onNodeDragStop((e) => console.log('drag stop', e))
|
|
||||||
onPaneClick((event) => captureZoomClick.value && console.log('pane click', event))
|
|
||||||
onPaneScroll((event) => captureZoomScroll.value && console.log('pane scroll', event))
|
|
||||||
onPaneContextMenu((event) => captureZoomClick.value && console.log('pane ctx menu', event))
|
|
||||||
onMoveEnd((flowTransform) => console.log('move end', flowTransform))
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="controls">
|
|
||||||
<div>
|
|
||||||
<label class="label" for="draggable">
|
|
||||||
nodesDraggable
|
|
||||||
<input id="draggable" v-model="nodesDraggable" type="checkbox" class="vue-flow__draggable" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label" for="connectable">
|
|
||||||
nodesConnectable
|
|
||||||
<input id="connectable" v-model="nodesConnectable" type="checkbox" class="vue-flow__connectable" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label" for="selectable">
|
|
||||||
elementsSelectable
|
|
||||||
<input id="selectable" v-model="elementsSelectable" type="checkbox" class="vue-flow__selectable" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label" for="zoomonscroll">
|
|
||||||
zoomOnScroll
|
|
||||||
<input id="zoomonscroll" v-model="zoomOnScroll" type="checkbox" class="vue-flow__zoomonscroll" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label" for="zoomonpinch">
|
|
||||||
zoomOnPinch
|
|
||||||
<input id="zoomonpinch" v-model="zoomOnPinch" type="checkbox" class="vue-flow__zoomonpinch" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label" for="panonscroll">
|
|
||||||
panOnScroll
|
|
||||||
<input id="panonscroll" v-model="panOnScroll" type="checkbox" class="vue-flow__panonscroll" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
panOnScrollMode
|
|
||||||
<select id="panonscrollmode" v-model="panOnScrollMode" class="vue-flow__panonscrollmode">
|
|
||||||
<option value="free">free</option>
|
|
||||||
<option value="horizontal">horizontal</option>
|
|
||||||
<option value="vertical">vertical</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label" for="zoomondbl">
|
|
||||||
zoomOnDoubleClick
|
|
||||||
<input id="zoomondbl" v-model="zoomOnDoubleClick" type="checkbox" class="vue-flow__zoomondbl" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label" for="panemoveable">
|
|
||||||
paneMovable
|
|
||||||
<input id="panemoveable" v-model="panOnDrag" type="checkbox" class="vue-flow__panemoveable" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label" for="capturezoompaneclick">
|
|
||||||
capture onPaneClick
|
|
||||||
<input id="capturezoompaneclick" v-model="captureZoomClick" type="checkbox" class="vue-flow__capturezoompaneclick" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label" for="capturezoompanescroll">
|
|
||||||
capture onPaneScroll
|
|
||||||
<input id="capturezoompanescroll" v-model="captureZoomScroll" type="checkbox" class="vue-flow__capturezoompanescroll" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export { default as InteractionApp } from './App.vue?raw'
|
|
||||||
export { default as InteractionControls } from './InteractionControls.vue?raw'
|
|
||||||
export { default as InteractionCSS } from './style.css'
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
.interactionflow .controls {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
z-index: 4;
|
|
||||||
font-size: 11px;
|
|
||||||
background-color: lightgray;
|
|
||||||
border-bottom-right-radius: 10px;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.interactionflow .controls .label {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
gap: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.interactionflow .controls .label input {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import Flow from './Flow.vue'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="multiflows">
|
|
||||||
<Flow />
|
|
||||||
<Flow />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { Background, VueFlow, isNode } from '@braks/vue-flow'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
const elements = ref([
|
|
||||||
{ id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 }, class: 'light' },
|
|
||||||
{ id: '2', label: 'Node 2', position: { x: 100, y: 100 }, class: 'light' },
|
|
||||||
{ id: '3', label: 'Node 3', position: { x: 400, y: 100 }, class: 'light' },
|
|
||||||
{ id: '4', label: 'Node 4', position: { x: 400, y: 200 }, class: 'light' },
|
|
||||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
|
||||||
{ id: 'e1-3', source: '1', target: '3' },
|
|
||||||
])
|
|
||||||
|
|
||||||
const toggleClass = () => elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light'))
|
|
||||||
|
|
||||||
const updatePos = () =>
|
|
||||||
elements.value.forEach((el) => {
|
|
||||||
if (isNode(el)) {
|
|
||||||
el.position = {
|
|
||||||
x: Math.random() * 400,
|
|
||||||
y: Math.random() * 400,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VueFlow v-model="elements" :fit-view-on-init="true">
|
|
||||||
<Background />
|
|
||||||
|
|
||||||
<div style="position: absolute; right: 10px; top: 10px; z-index: 4">
|
|
||||||
<button style="margin-right: 5px" @click="updatePos">update positions</button>
|
|
||||||
<button style="margin-right: 5px" @click="toggleClass">toggle class</button>
|
|
||||||
</div>
|
|
||||||
</VueFlow>
|
|
||||||
</template>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export { default as MultiApp } from './App.vue?raw'
|
|
||||||
export { default as MultiFlow } from './Flow.vue?raw'
|
|
||||||
export { default as MultiCSS } from './style.css'
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
.vue-flow__node.dark {
|
|
||||||
background: #000000;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.multiflows {
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.multiflows .vue-flow {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.multiflows .vue-flow:first-child {
|
|
||||||
border-right: 2px solid #333;
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { Background, ConnectionMode, Controls, MiniMap, VueFlow, useVueFlow } from '@braks/vue-flow'
|
|
||||||
import { onMounted } from 'vue'
|
|
||||||
|
|
||||||
const { onConnect, nodes, edges, addEdges, addNodes } = useVueFlow({
|
|
||||||
fitViewOnInit: true,
|
|
||||||
connectionMode: ConnectionMode.Loose,
|
|
||||||
// set this to true so edges get elevated when selected, defaults to false
|
|
||||||
elevateEdgesOnSelect: true,
|
|
||||||
nodes: [
|
|
||||||
{ id: '1', type: 'input', label: 'node', position: { x: 250, y: 0 } },
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
label: 'parent node',
|
|
||||||
position: { x: 100, y: 100 },
|
|
||||||
style: { backgroundColor: 'rgba(16, 185, 129, 0.5)', width: '200px', height: '200px' },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2a',
|
|
||||||
label: 'child node',
|
|
||||||
position: { x: 10, y: 50 },
|
|
||||||
parentNode: '2',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '4',
|
|
||||||
label: 'parent node',
|
|
||||||
position: { x: 320, y: 175 },
|
|
||||||
style: { backgroundColor: 'rgba(16, 185, 129, 0.5)', width: '400px', height: '300px' },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '4a',
|
|
||||||
label: 'child node',
|
|
||||||
position: { x: 15, y: 65 },
|
|
||||||
extent: 'parent',
|
|
||||||
parentNode: '4',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '4b',
|
|
||||||
label: 'nested parent node',
|
|
||||||
position: { x: 15, y: 120 },
|
|
||||||
style: { backgroundColor: 'rgba(139, 92, 246, 0.5)', height: '150px', width: '270px' },
|
|
||||||
parentNode: '4',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '4b1',
|
|
||||||
label: 'nested child node',
|
|
||||||
position: { x: 20, y: 40 },
|
|
||||||
parentNode: '4b',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '4b2',
|
|
||||||
label: 'nested child node',
|
|
||||||
position: { x: 100, y: 100 },
|
|
||||||
parentNode: '4b',
|
|
||||||
},
|
|
||||||
{ id: '4c', label: 'child node', position: { x: 200, y: 65 }, parentNode: '4' },
|
|
||||||
],
|
|
||||||
edges: [
|
|
||||||
{ id: 'e1-2', source: '1', target: '2' },
|
|
||||||
{ id: 'e1-4', source: '1', target: '4' },
|
|
||||||
{ id: 'e1-4c', source: '1', target: '4c' },
|
|
||||||
{ id: 'e2a-4a', source: '2a', target: '4a' },
|
|
||||||
{ id: 'e4a-4b1', source: '4a', target: '4b1' },
|
|
||||||
{ id: 'e4a-4b2', source: '4a', target: '4b2' },
|
|
||||||
{ id: 'e4b1-4b2', source: '4b1', target: '4b2' },
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
onConnect((params) => addEdges([params]))
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// add nodes to parent
|
|
||||||
addNodes([
|
|
||||||
{
|
|
||||||
id: '999',
|
|
||||||
type: 'input',
|
|
||||||
label: 'Drag me to extend area!',
|
|
||||||
position: { x: 20, y: 100 },
|
|
||||||
class: 'light',
|
|
||||||
expandParent: true,
|
|
||||||
parentNode: '2',
|
|
||||||
},
|
|
||||||
])
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VueFlow>
|
|
||||||
<MiniMap />
|
|
||||||
<Controls />
|
|
||||||
<Background />
|
|
||||||
</VueFlow>
|
|
||||||
</template>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { default as NestedApp } from './App.vue?raw'
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import sdk from '@stackblitz/sdk'
|
|
||||||
|
|
||||||
const el = ref()
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
sdk.embedProjectId(el.value, 'vitejs-vite-wyfpsj', {
|
|
||||||
height: 750,
|
|
||||||
forceEmbedLayout: true,
|
|
||||||
openFile: 'src/App.vue',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div ref="el" class="outline-none"></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.application {
|
|
||||||
@apply h-[75vh];
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import Controls from './Controls.vue'
|
|
||||||
|
|
||||||
const elements = ref([{ id: '1', label: 'Node 1', position: { x: 100, y: 100 } }])
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VueFlow v-model="elements">
|
|
||||||
<Controls />
|
|
||||||
</VueFlow>
|
|
||||||
</template>
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { useVueFlow } from '@braks/vue-flow'
|
|
||||||
|
|
||||||
const flowKey = 'example-flow'
|
|
||||||
|
|
||||||
const { nodes, addNodes, setNodes, setEdges, dimensions, setTransform, toObject } = useVueFlow()
|
|
||||||
|
|
||||||
const onSave = () => {
|
|
||||||
localStorage.setItem(flowKey, JSON.stringify(toObject()))
|
|
||||||
}
|
|
||||||
|
|
||||||
const onRestore = () => {
|
|
||||||
const flow = JSON.parse(localStorage.getItem(flowKey))
|
|
||||||
|
|
||||||
if (flow) {
|
|
||||||
const [x = 0, y = 0] = flow.position
|
|
||||||
setNodes(flow.nodes)
|
|
||||||
setEdges(flow.edges)
|
|
||||||
setTransform({ x, y, zoom: flow.zoom || 0 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onAdd = () => {
|
|
||||||
const id = nodes.value.length + 1
|
|
||||||
const newNode = {
|
|
||||||
id: `random_node-${id}`,
|
|
||||||
label: `Node ${id}`,
|
|
||||||
position: { x: Math.random() * dimensions.value.width, y: Math.random() * dimensions.value.height },
|
|
||||||
}
|
|
||||||
addNodes([newNode])
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="save__controls">
|
|
||||||
<button style="background-color: #33a6b8" @click="onSave">save</button>
|
|
||||||
<button style="background-color: #113285" @click="onRestore">restore</button>
|
|
||||||
<button style="background-color: #6f3381" @click="onAdd">add node</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export { default as SaveRestoreApp } from './App.vue?raw'
|
|
||||||
export { default as SaveRestoreControls } from './Controls.vue?raw'
|
|
||||||
export { default as SaveRestoreCSS } from './style.css'
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
.save__controls {
|
|
||||||
position: absolute;
|
|
||||||
left: 10px;
|
|
||||||
top: 10px;
|
|
||||||
z-index: 4;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.save__controls button {
|
|
||||||
margin-left: 5px;
|
|
||||||
padding: 5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
font-weight: 700;
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: white;
|
|
||||||
-webkit-box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.3);
|
|
||||||
box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.3);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.save__controls button:hover {
|
|
||||||
opacity: 0.8;
|
|
||||||
transform: scale(105%);
|
|
||||||
transition: 250ms all ease-in-out;
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { VueFlow, isNode, useVueFlow } from '@braks/vue-flow'
|
|
||||||
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()
|
|
||||||
|
|
||||||
onPaneReady((i) => {
|
|
||||||
i.fitView({
|
|
||||||
padding: 0.2,
|
|
||||||
})
|
|
||||||
console.log(i.getElements.value)
|
|
||||||
})
|
|
||||||
|
|
||||||
const toggleClass = () => elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light'))
|
|
||||||
|
|
||||||
const updatePos = () => {
|
|
||||||
elements.value.forEach((el) => {
|
|
||||||
if (isNode(el)) {
|
|
||||||
el.position = {
|
|
||||||
x: Math.random() * 10 * dimensions.value.width,
|
|
||||||
y: Math.random() * 10 * dimensions.value.height,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
nextTick(() => {
|
|
||||||
fitView({ duration: 1000, padding: 0.5 })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VueFlow v-model="elements" :min-zoom="0.1">
|
|
||||||
<div style="position: absolute; right: 10px; top: 10px; z-index: 4">
|
|
||||||
<button style="margin-right: 5px" @click="updatePos">update positions</button>
|
|
||||||
<button style="margin-right: 5px" @click="toggleClass">toggle class</button>
|
|
||||||
</div>
|
|
||||||
</VueFlow>
|
|
||||||
</template>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export { default as StressApp } from './App.vue?raw'
|
|
||||||
export { default as StressUtils } from './utils.js?raw'
|
|
||||||
export { default as StressCSS } from './style.css'
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
.vue-flow__node.dark {
|
|
||||||
background: #000000;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
export function getElements(xElements = 10, yElements = 10) {
|
|
||||||
const initialNodes = []
|
|
||||||
const initialEdges = []
|
|
||||||
let nodeId = 1
|
|
||||||
let recentNodeId = null
|
|
||||||
|
|
||||||
for (let y = 0; y < yElements; y++) {
|
|
||||||
for (let x = 0; x < xElements; x++) {
|
|
||||||
const position = { x: x * 75, y: y * 75 }
|
|
||||||
const node = {
|
|
||||||
id: nodeId.toString(),
|
|
||||||
style: { width: `50px`, fontSize: `11px`, zIndex: 1 },
|
|
||||||
label: `Node ${nodeId}`,
|
|
||||||
class: 'light',
|
|
||||||
position,
|
|
||||||
}
|
|
||||||
initialNodes.push(node)
|
|
||||||
|
|
||||||
if (recentNodeId && nodeId <= xElements * yElements) {
|
|
||||||
initialEdges.push({
|
|
||||||
id: `${x}-${y}`,
|
|
||||||
source: recentNodeId.toString(),
|
|
||||||
target: nodeId.toString(),
|
|
||||||
style: (edge) => {
|
|
||||||
if (!edge.sourceNode.selected && !edge.targetNode.selected) return
|
|
||||||
return { stroke: '#10b981', strokeWidth: 3 }
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
recentNodeId = nodeId
|
|
||||||
nodeId++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
nodes: initialNodes,
|
|
||||||
edges: initialEdges,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { VueFlow } from '@braks/vue-flow'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import Sidebar from './Sidebar.vue'
|
|
||||||
import TeleportableNode from './TeleportableNode.vue'
|
|
||||||
|
|
||||||
const elements = ref([
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
label: 'Click to teleport',
|
|
||||||
type: 'teleportable',
|
|
||||||
position: { x: 125, y: 0 },
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
label: 'Click to teleport',
|
|
||||||
type: 'teleportable',
|
|
||||||
position: { x: 350, y: 200 },
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '3',
|
|
||||||
label: 'Click to teleport',
|
|
||||||
type: 'teleportable',
|
|
||||||
position: { x: 0, y: 200 },
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'e1-2',
|
|
||||||
source: '1',
|
|
||||||
target: '2',
|
|
||||||
},
|
|
||||||
])
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="teleportflow">
|
|
||||||
<VueFlow v-model="elements" :fit-view-on-init="true">
|
|
||||||
<template #node-teleportable="props">
|
|
||||||
<TeleportableNode v-bind="props" />
|
|
||||||
</template>
|
|
||||||
</VueFlow>
|
|
||||||
<Sidebar />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||