docs: replace vuepress docs dir with vitepress docs dir

This commit is contained in:
braks
2022-07-30 15:50:06 +02:00
committed by Braks
parent 21702daf1e
commit f2b169145c
179 changed files with 122 additions and 8131 deletions

View File

@@ -36,9 +36,11 @@ const store = new ReplStore({
outputMode: 'preview',
})
const vh = useCssVar('--vh')
watchEffect(
() => {
document.documentElement.style.setProperty('--vh', `${window.innerHeight}px`)
vh.value = `${window.innerHeight}px`
},
{ flush: 'post' },
)
@@ -99,12 +101,14 @@ const sfcOptions = {
}
.vue-repl {
--vh: 100vh;
@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 {
display: none;
@apply hidden;
}
</style>

View File

@@ -71,7 +71,7 @@
gap: 5px;
}
.button {
.buttons .button {
background-color: whitesmoke;
cursor: pointer;
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);
}
.button:hover {
.buttons .button:hover {
background: black;
color: white;
}

View File

@@ -3,8 +3,8 @@ import Heart from '~icons/mdi/heart'
</script>
<template>
<div id="acknowledgement" class="w-full dark:(bg-black text-white) border-y-1 border-white">
<div class="max-w-11/12 md:max-w-6/12 m-auto py-4 md:(pb-12 pt-6) text-center">
<div id="acknowledgement" class="w-full">
<div class="max-w-[1024px] md:max-w-3/4 m-auto py-4 md:(pb-12 pt-6) text-center">
<div>
<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

View File

@@ -8,7 +8,7 @@ const npmData = await $fetch('https://api.npmjs.org/downloads/point/last-month/@
</script>
<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="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">

View File

@@ -24,7 +24,7 @@ onBeforeUnmount(stop)
</script>
<template>
<div ref="el" class="w-full dark:(bg-black text-white)">
<div ref="el" class="w-full">
<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"
>

View File

@@ -239,7 +239,7 @@ const animations = ref<{ className: string; duration: number }[]>(shuffle(create
</script>
<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">
<Background v-if="animatedBackground">
<template #pattern-container="{ id }">
@@ -306,21 +306,21 @@ const animations = ref<{ className: string; duration: number }[]>(shuffle(create
</template>
<template v-else-if="props.id === 'documentation'">
<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>
<Handle type="target" :position="Position.Top" />
<Handle class="block md:hidden" type="source" :position="Position.Bottom" />
</template>
<template v-else-if="props.id === 'examples'">
<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>
<Handle type="target" :position="Position.Top" />
<Handle class="block md:hidden" type="source" :position="Position.Bottom" />
</template>
<template v-else-if="props.id === 'acknowledgement'">
<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>
<Handle type="target" :position="Position.Top" />
</template>
@@ -431,7 +431,7 @@ const animations = ref<{ className: string; duration: number }[]>(shuffle(create
hover:(ring ring-white);
}
.link {
.intro-link {
@apply flex
gap-3
items-center

View File

@@ -1,41 +1,39 @@
{
"name": "docs",
"version": "0.0.0",
"name": "docs2",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "pnpm run typedoc && vuepress dev src",
"build": "pnpm run typedoc && vuepress build src",
"dev": "pnpm run typedoc && vitepress dev src",
"build": "pnpm run typedoc && vitepress build src",
"serve": "vitepress serve src",
"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": {
"@algolia/client-search": "^4.14.2",
"@animxyz/core": "^0.6.6",
"@animxyz/vue3": "^0.6.7",
"@braks/vue-flow": "workspace:*",
"@stackblitz/sdk": "^1.8.0",
"@vue/repl": "1.1.2",
"blobity": "^0.1.7",
"blobity": "^0.2.1",
"canvas-confetti": "^1.5.1"
},
"devDependencies": {
"@iconify/json": "^2.1.81",
"@iconify/json": "^2.1.85",
"@types/canvas-confetti": "^1.4.3",
"@types/node": "^18.0.6",
"@vuepress/bundler-vite": "^2.0.0-beta.49",
"@vuepress/plugin-docsearch": "^2.0.0-beta.49",
"@vuepress/plugin-pwa": "^2.0.0-beta.49",
"@types/node": "^18.6.2",
"@windicss/plugin-scrollbar": "^1.2.3",
"dotenv": "^16.0.1",
"ohmyfetch": "^0.4.18",
"typedoc": "^0.22.18",
"typedoc-plugin-markdown": "^3.13.4",
"unplugin-auto-import": "^0.9.5",
"unplugin-icons": "^0.14.7",
"unplugin-vue-components": "^0.19.9",
"unplugin-auto-import": "^0.10.3",
"unplugin-icons": "^0.14.8",
"unplugin-vue-components": "^0.21.2",
"vite-plugin-windicss": "^1.8.7",
"vuepress": "^2.0.0-beta.49",
"vuepress-plugin-seo2": "^2.0.0-beta.84",
"vuepress-plugin-sitemap2": "^2.0.0-beta.84",
"vitepress": "^1.0.0-alpha.4",
"windicss": "^3.5.6"
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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 {}

View File

@@ -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,
})

View File

@@ -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: [],
})

View File

@@ -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

View File

@@ -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>

View File

@@ -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',
},
},
},
},
})

View File

@@ -8,7 +8,7 @@ layout: page
Connections can be validated before edges are created and nodes get connected.
## Using a handle in a custom node
```vue:no-line-numbers
```vue
<div>
[ ... ]

View File

@@ -10,7 +10,7 @@ The composition API and the power of provide/inject allows us to act more flexib
a component tree.
Thus accessing the internal state of Vue Flow becomes super easy when using composition.
```vue:no-line-numbers
```vue
<script setup>
import { useVueFlow, VueFlow } from '@braks/vue-flow'
@@ -49,7 +49,7 @@ using viewpane transforms.
All functions can also be accessed from `useVueFlow`.
It requires a valid Vue Flow store in its context.
```vue:no-line-numbers
```vue
<script setup>
import { useZoomPanHelper } from '@braks/vue-flow'

View File

@@ -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.
```vue:no-line-numbers
```vue
<script>
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
directly to the state.
```vue:no-line-numbers
```vue
<script setup>
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.
```js:no-line-numbers
```js
const edges = [
{
id: 'e1-2',
@@ -125,7 +125,7 @@ const edges = [
A step edge has a straight path with a step towards the target.
```js:no-line-numbers{4}
```js{4}
const edges = [
{
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).
```js:no-line-numbers{4}
```js{4}
const edges = [
{
id: 'e1-2',
@@ -155,7 +155,7 @@ const edges = [
A simple straight path.
```js:no-line-numbers{4}
```js{4}
const edges = [
{
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.
Edge-types are inferred from your edge's definition.
```js:no-line-numbers{5,11}
```js{5,11}
const edges = [
{
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`
will expect a slot to have the name `edge-custom`.
```vue:no-line-numbers{18,26}
```vue{18,26}
<script setup>
import { VueFlow } from '@braks/vue-flow'
import CustomEdge from './CustomEdge.vue'
@@ -239,7 +239,7 @@ turned into reactive objects.
Otherwise, vue will throw a warning in the console.
:::
```vue:no-line-numbers{5-7,28}
```vue{5-7,28}
<script setup>
import { markRaw } from '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
the type otherwise.
```vue:no-line-numbers
```vue
<script setup>
import { markRaw } from '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
to your node components.
```vue:no-line-numbers{19-26}
```vue{19-26}
<script setup>
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
triggered when the edge is clicked.
```vue:no-line-numbers
```vue
<script lang="ts" setup>
import type { EdgeProps, EdgeEventsOn } from '@braks/vue-flow'

View File

@@ -10,7 +10,7 @@
<CodeGroup>
<CodeGroupItem title="YARN" active>
```bash:no-line-numbers
```bash
yarn add @braks/vue-flow
```
@@ -19,7 +19,7 @@ yarn add @braks/vue-flow
<CodeGroupItem title="NPM">
```bash:no-line-numbers
```bash
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
source (node id) and a target (node id).
```vue:no-line-numbers
```vue
<script setup>
import { VueFlow } from '@braks/vue-flow'
@@ -79,14 +79,14 @@ A basic setup would look like this:
<CodeGroup>
<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 title="Options API">
@[code vue:no-line-numbers](../../../examples/vite/src/Basic/BasicOptionsAPI.vue)
@[code vue](../../../examples/vite/src/Basic/BasicOptionsAPI.vue)
</CodeGroupItem>
</CodeGroup>

View File

@@ -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.
```vue:no-line-numbers
```vue
<script>
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
directly to the state.
```vue:no-line-numbers
```vue
<script setup>
import { VueFlow, useVueFlow } from '@braks/vue-flow'
@@ -92,7 +92,7 @@ You can also apply changes using the [`applyNodeChanges`](/typedocs/interfaces/A
function,
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>
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.
```js:no-line-numbers{5-6}
```js{5-6}
const nodes = [
{
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.
Node-types are inferred from your node's definition.
```js:no-line-numbers{5,11}
```js{5,11}
const nodes = [
{
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`
will expect a slot to have the name `node-custom`.
```vue:no-line-numbers{9,16}
```vue{9,16}
<script setup>
import { VueFlow } from '@braks/vue-flow'
import CustomNode from './CustomNode.vue'
@@ -232,7 +232,7 @@ turned into reactive objects.
Otherwise, vue will throw a warning in the console.
:::
```vue:no-line-numbers{6-9,26}
```vue{6-9,26}
<script setup>
import { markRaw } from '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
the type otherwise.
```vue:no-line-numbers{17}
```vue{17}
<script setup>
import { markRaw } from '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
to your node components.
```vue:no-line-numbers{9-13}
```vue{9-13}
<script setup>
import { VueFlow } from '@braks/vue-flow'
@@ -368,7 +368,7 @@ The `click` handler is part of the [`NodeEventsHandler`](/typedocs/types/NodeEve
will be
triggered when the node is clicked.
```vue:no-line-numbers
```vue
<script lang="ts" setup>
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.
```css:no-line-numbers
```css
.vue-flow__node-custom {
background: #9CA8B3;
color: #fff;
@@ -435,7 +435,7 @@ or you can emit the `updateNodeInternals` event from your custom node component
- Using store action
```vue:no-line-numbers
```vue
<script setup>
import { useVueFlow } from '@braks/vue-flow'
@@ -449,7 +449,7 @@ const onSomeEvent = () => {
- Emitting event from custom component
```vue:no-line-numbers
```vue
<script setup>
const emits = defineEmits(['updateNodeInternals'])

View File

@@ -3,7 +3,7 @@
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.
```css:no-line-numbers
```css
/* these are necessary styles for vue flow */
@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.
```css:no-line-numbers
```css
.vue-flow {
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.
```vue:no-line-numbers{4}
```vue{4}
<div style="height: 300px">
<VueFlow
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.
```ts:no-line-numbers{8-12,20-27}
```ts{7-11,19-26}
const nodes = ref<Node[]>([
{
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>([
{ 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-connection-path | Connectionline color |
## Classes
| Name | Container |
@@ -126,7 +124,7 @@ const elements = ref<Elements>([
| .vue-flow__selection | User selection |
| .vue-flow__edges | Edges renderer 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 .animated | Animated edge |
| .vue-flow__edge-path | Edge element svg path |
@@ -138,7 +136,7 @@ const elements = ref<Elements>([
| .vue-flow__nodes | Nodes renderer wrapper |
| .vue-flow__node | Node element wrapper |
| .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__handle | Node handle element wrapper |
| .vue-flow__handle-bottom | Handle position bottom |

View File

@@ -2,7 +2,7 @@
All default edge components are exported and can be used or extended if necessary.
```vue:no-line-numbers
```vue
<script setup>
// CustomEdge.vue
import { EdgeProps, BezierEdge } from '@braks/vue-flow'

View File

@@ -8,7 +8,7 @@
- Example:
```vue:no-line-numbers{13}
```vue{13}
<script setup>
import { VueFlow, isEdge } from '@braks/vue-flow'
@@ -42,7 +42,7 @@ const toggleClass = () => {
- Example:
```vue:no-line-numbers{13}
```vue{13}
<script setup>
import { VueFlow, isNode } from '@braks/vue-flow'
@@ -81,7 +81,7 @@ of [`useVueFlow`](/guide/composables.html#usevueflow/)
- Example:
```vue:no-line-numbers{12}
```vue{12}
<script setup>
import { VueFlow, addEdge } from '@braks/vue-flow'
@@ -114,7 +114,7 @@ of [`useVueFlow`](/guide/composables.html#usevueflow/)
- Example:
```vue:no-line-numbers{12}
```vue{12}
<script setup>
import { VueFlow, updateEdge } from '@braks/vue-flow'

View File

@@ -11,7 +11,7 @@ instance provided by [`onPaneReady`](/typedocs/interfaces/FlowEvents.html#panere
<CodeGroup>
<CodeGroupItem title="Composition API" active>
```vue:no-line-numbers
```vue
<script setup>
import { VueFlow, useVueFlow } from '@braks/vue-flow'
@@ -27,7 +27,7 @@ onPaneReady((instance) => instance.fitView())
<CodeGroupItem title="Options API">
```vue:no-line-numbers
```vue
<script>
import { VueFlow } from '@braks/vue-flow'
@@ -64,7 +64,7 @@ export default defineComponent({
- Example:
```ts:no-line-numbers
```ts
vueFlowInstance.project({ x: 100, y: 100 })
```
@@ -78,7 +78,7 @@ vueFlowInstance.project({ x: 100, y: 100 })
- Example:
```ts:no-line-numbers
```ts
vueFlowInstance.fitView({ padding: 0.25, includeHiddenNodes: true })
```
@@ -90,7 +90,7 @@ vueFlowInstance.fitView({ padding: 0.25, includeHiddenNodes: true })
- Example:
```ts:no-line-numbers
```ts
vueFlowInstance.fitBounds(getRectOfNodes(nodes.value))
```
@@ -102,7 +102,7 @@ vueFlowInstance.fitBounds(getRectOfNodes(nodes.value))
- Example:
```ts:no-line-numbers
```ts
vueFlowInstance.setTransform({ x: 100, y: 100, zoom: 1.5 })
```
@@ -156,7 +156,7 @@ vueFlowInstance.setTransform({ x: 100, y: 100, zoom: 1.5 })
- Example:
```ts:no-line-numbers
```ts
toObject = (): {
elements: FlowElements,
position: [x, y],

View File

@@ -7,7 +7,7 @@ as options to the [`useVueFlow`](/guide/composables.html#usevueflow/) composable
<CodeGroup>
<CodeGroupItem title="Props" active>
```vue:no-line-numbers
```vue
<!-- Pass configuration as props -->
<template>
<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">
```vue:no-line-numbers
```vue
<script setup>
import { useVueFlow } from '@braks/vue-flow'
@@ -42,7 +42,7 @@ by `useVueFlow`.
<CodeGroup>
<CodeGroupItem title="Props" active>
```vue:no-line-numbers{2,5-6,10}
```vue{2,5-6,10}
<script setup>
const defaultZoom = ref(1)
@@ -61,7 +61,7 @@ onMounted(() => {
<CodeGroupItem title="Composable">
```vue:no-line-numbers{2,7-8}
```vue{2,7-8}
<script setup>
const { defaultZoom } = useVueFlow({
defaultZoom: 0.5,
@@ -101,7 +101,7 @@ onMounted(() => {
- Example:
```vue:no-line-numbers
```vue
<script setup>
import { VueFlow } from '@braks/vue-flow'
@@ -133,7 +133,7 @@ const elements = ref([
- Example:
```vue:no-line-numbers
```vue
<script setup>
import { VueFlow } from '@braks/vue-flow'
@@ -163,7 +163,7 @@ const nodes = ref([
- Example:
```vue:no-line-numbers
```vue
<script setup>
import { VueFlow } from '@braks/vue-flow'
@@ -198,7 +198,7 @@ const edges = ref([
- Example:
```vue:no-line-numbers
```vue
<script setup>
import { VueFlow } from '@braks/vue-flow'
import CustomNode from './CustomNode.vue'
@@ -235,7 +235,7 @@ const edges = ref([
- Example:
```vue:no-line-numbers
```vue
<script setup>
import { VueFlow } from '@braks/vue-flow'
import CustomEdge from './CustomEdge.vue'
@@ -275,7 +275,7 @@ const edges = ref([
- Example:
```vue:no-line-numbers
```vue
<script setup>
import { VueFlow } from '@braks/vue-flow'
@@ -496,7 +496,7 @@ const edges = ref([
- Default:
```ts:no-line-numbers
```ts
[
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
@@ -557,7 +557,7 @@ const edges = ref([
- Example:
```vue:no-line-numbers{5-6,10}
```vue{5-6,10}
<script setup>
const elements = ref([
{ id: '1', label: 'Node 1', position: { x: 250, y: 5 } },
@@ -585,7 +585,7 @@ const elements = ref([
- Example:
```vue:no-line-numbers{5-6,10}
```vue{5-6,10}
<script setup>
const elements = ref([
{ id: '1', label: 'Node 1', position: { x: 250, y: 5 } },
@@ -605,7 +605,7 @@ const elements = ref([
- Default:
```ts:no-line-numbers
```ts
[
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
@@ -620,7 +620,7 @@ const elements = ref([
- Example:
```vue:no-line-numbers{5-6}
```vue{5-6}
<script setup>
const elements = ref([
{ id: '1', label: 'Node 1', position: { x: 250, y: 5 } },
@@ -676,7 +676,7 @@ const elements = ref([
- Example:
```vue:no-line-numbers{7-8,12}
```vue{7-8,12}
<script setup>
const elements = ref([
{ id: '1', label: 'Node 1', position: { x: 250, y: 5 } },
@@ -753,7 +753,7 @@ const elements = ref([
##### Boolean value
```vue:no-line-numbers{2}
```vue{2}
<template>
<VueFlow v-model="elements" auto-connect />
</template>
@@ -761,7 +761,7 @@ const elements = ref([
#### [Connector](/typedocs/types/Connector.html/)
```vue:no-line-numbers{6-18,22}
```vue{6-18,22}
<script setup>
import { ref } from 'vue'

View File

@@ -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
is triggered.
```vue:no-line-numbers
```vue
<template>
<VueFlow>
<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.
```vue:no-line-numbers
```vue
<template>
<VueFlow>
<template #zoom-pane>

View File

@@ -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
state is reactive and changes will be reflected on the graph.
```vue:no-line-numbers{4-6}
```vue{4-6}
<script setup>
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.
```vue:no-line-numbers
```vue
<!-- Container.vue -->
<template>
<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
available as an injection in the component tree.
```vue:no-line-numbers{5-6}
```vue{5-6}
<script>
// Container.vue
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.
```vue:no-line-numbers
```vue
<script setup>
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
to `false`.
```vue:no-line-numbers
```vue
<div style="height: 300px">
<VueFlow v-model="elements" :apply-default="false" />
</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
when mounted.
```vue:no-line-numbers{4,32}
```vue{4,32}
<script>
import { VueFlow, useVueFlow } from '@braks/vue-flow'

View File

@@ -1,8 +1,7 @@
---
home: true
layout: home
heroText: null
tagline: null
footer: MIT Licensed | Copyright © 2021-present Burak Cakmakoglu
---
<Home />
@@ -11,10 +10,12 @@ footer: MIT Licensed | Copyright © 2021-present Burak Cakmakoglu
<Banner />
</Suspense>
<client-only>
<Features />
<Features />
<XyzTransition appear-visible xyz="fade down ease-out-back">
<XyzTransition appear-visible xyz="fade down ease-out-back">
<Acknowledgement />
</XyzTransition>
</client-only>
</XyzTransition>
<XyzTransition appear-visible xyz="fade down ease-out-back">
<Team />
</XyzTransition>

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 375 B

After

Width:  |  Height:  |  Size: 375 B

View File

Before

Width:  |  Height:  |  Size: 744 B

After

Width:  |  Height:  |  Size: 744 B

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -17,7 +17,5 @@
"forceConsistentCasingInFileNames": true,
"types": ["vite/client", "@types/node", "unplugin-icons/types/vue"]
},
"include": ["components", "src", "src/.vuepress"],
"exclude": ["node_modules", "dist"],
"references": [{ "path": "./tsconfig.node.json" }]
"exclude": ["node_modules", "dist"]
}

View File

@@ -1,8 +0,0 @@
{
"compilerOptions": {
"composite": true,
"module": "esnext",
"moduleResolution": "node"
},
"include": ["vite.config.ts"]
}

View File

@@ -9,5 +9,6 @@
"lightHighlightTheme": "vitesse-light",
"disableSources": true,
"out": "src/typedocs",
"tsconfig": "../packages/vue-flow/tsconfig.docs.json"
"tsconfig": "../packages/vue-flow/tsconfig.docs.json",
"entryDocument": "index.md"
}

2
docs2/.gitignore vendored
View File

@@ -1,2 +0,0 @@
.data.json
.temp

View File

@@ -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>

View File

@@ -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>

View File

@@ -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'

View File

@@ -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' },
]

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -1,2 +0,0 @@
export { default as CustomConnectionLineApp } from './App.vue?raw'
export { default as CustomConnectionLine } from './CustomConnectionLine.vue?raw'

View File

@@ -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>

View File

@@ -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>

View File

@@ -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'

View File

@@ -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',
}

View File

@@ -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%
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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'

View File

@@ -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;
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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'

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -1 +0,0 @@
export { default as EmptyApp } from './App.vue?raw'

View File

@@ -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>

View File

@@ -1 +0,0 @@
export { default as HiddenApp } from './App.vue?raw'

View File

@@ -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>

View File

@@ -1,2 +0,0 @@
export { default as HorizontalApp } from './App.vue?raw'
export { default as HorizontalElements } from './initial-elements.js?raw'

View File

@@ -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' },
]

View File

@@ -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,
},
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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'

View File

@@ -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;
}

View File

@@ -1,10 +0,0 @@
<script setup>
import Flow from './Flow.vue'
</script>
<template>
<div class="multiflows">
<Flow />
<Flow />
</div>
</template>

View File

@@ -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>

View File

@@ -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'

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -1 +0,0 @@
export { default as NestedApp } from './App.vue?raw'

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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'

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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'

View File

@@ -1,4 +0,0 @@
.vue-flow__node.dark {
background: #000000;
color: #ffffff;
}

View File

@@ -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,
}
}

View File

@@ -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>

Some files were not shown because too many files have changed in this diff Show More