update: change name to vue flow
* Add gif to readme Signed-off-by: Braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
@@ -1,17 +1,17 @@
|
|||||||
# React Flow in Vue3 = Revue Flow
|
# Vue Flow
|
||||||
[](https://reactflow.dev/)
|
[](https://reactflow.dev/)
|
||||||

|

|
||||||
[](https://david-dm.org/bcakmakoglu/revue-flow)
|
[](https://david-dm.org/bcakmakoglu/vue-flow)
|
||||||
[](https://david-dm.org/bcakmakoglu/revue-flow?type=dev)
|
[](https://david-dm.org/bcakmakoglu/vue-flow?type=dev)
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
This repo is still a big construction site with nothing really finished.
|
This repo is still a big construction site with nothing really finished.
|
||||||
You can check the examples to see what's working and what's not.
|
You can check the examples to see what's working and what's not.
|
||||||
Please visit [React Flow](https://reactflow.dev/) and support them if you like the idea.
|
Please visit [React Flow](https://reactflow.dev/) and support them if you like the idea.
|
||||||
They did most of the heavy lifting by writing the library in the first place.
|
They did most of the heavy lifting by writing the library in the first place.
|
||||||
All I did is bring it to Vue3.
|
All I did is bring it to Vue.
|
||||||
|
|
||||||
### Motivation
|
### Motivation
|
||||||
Seeing as many libraries exist in the React ecosystem and Vue sadly does not get the same
|
Seeing as many libraries exist in the React ecosystem and Vue sadly does not get the same
|
||||||
@@ -20,31 +20,29 @@ love and attention, I decided to port the React Flow library to Vue.js.
|
|||||||
## Usage
|
## Usage
|
||||||
Check the React Flow docs for usage. It's really the same.
|
Check the React Flow docs for usage. It's really the same.
|
||||||
|
|
||||||
### Vue3
|
### Vue 3
|
||||||
```bash
|
```bash
|
||||||
# install revue flow
|
# install vue flow
|
||||||
$ yarn add @braks/revue-flow
|
$ pnpm add @braks/vue-flow
|
||||||
|
|
||||||
# or
|
# or
|
||||||
$ npm i --save @braks/revue-flow
|
$ npm i --save @braks/vue-flow
|
||||||
```
|
```
|
||||||
|
|
||||||
### Vue2
|
### Vue 2
|
||||||
This doesn't work with Vue2, sorry.
|
Vue Flow doesn't work with Vue 2, sorry.
|
||||||
|
|
||||||
## Development
|
|
||||||
This project uses Vite for development and Rollup to create a distribution.
|
|
||||||
|
|
||||||
|
## 🧪 Development
|
||||||
```bash
|
```bash
|
||||||
# start (dev)
|
# start (dev)
|
||||||
$ yarn dev
|
$ pnpm dev
|
||||||
|
|
||||||
# build app
|
# build app
|
||||||
$ yarn build
|
$ pnpm build
|
||||||
|
|
||||||
# serve app from build
|
# serve app from build
|
||||||
$ yarn serve
|
$ pnpm serve
|
||||||
|
|
||||||
# build dist
|
# build dist
|
||||||
$ yarn build:dist
|
$ pnpm build:dist
|
||||||
```
|
```
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.6 MiB |
@@ -54,7 +54,7 @@ const toggleClassnames = () => {
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Flow
|
<Flow
|
||||||
class="revue-flow-basic-example"
|
class="vue-flow-basic-example"
|
||||||
:elements="elements"
|
:elements="elements"
|
||||||
:default-zoom="1.5"
|
:default-zoom="1.5"
|
||||||
:min-zoom="0.2"
|
:min-zoom="0.2"
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const sourceHandleStyleB: CSSProperties = { ...targetHandleStyle, bottom: '10px'
|
|||||||
const onConnect = (params: Connection | Edge) => console.log('handle onConnect', params)
|
const onConnect = (params: Connection | Edge) => console.log('handle onConnect', params)
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="revue-flow__node-color-selector">
|
<div class="vue-flow__node-color-selector">
|
||||||
<Handle type="target" :position="Position.Left" :style="targetHandleStyle" :on-connect="onConnect" />
|
<Handle type="target" :position="Position.Left" :style="targetHandleStyle" :on-connect="onConnect" />
|
||||||
<div>
|
<div>
|
||||||
Custom Color Picker Node: <strong>{{ data.color }}</strong>
|
Custom Color Picker Node: <strong>{{ data.color }}</strong>
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ const onDragStart = (event: DragEvent, nodeType: string) => {
|
|||||||
<template>
|
<template>
|
||||||
<aside>
|
<aside>
|
||||||
<div class="description">You can drag these nodes to the pane on the left.</div>
|
<div class="description">You can drag these nodes to the pane on the left.</div>
|
||||||
<div class="revue-flow__node-input" :draggable="true" @dragstart="(event: DragEvent) => onDragStart(event, 'input')">
|
<div class="vue-flow__node-input" :draggable="true" @dragstart="(event: DragEvent) => onDragStart(event, 'input')">
|
||||||
Input Node
|
Input Node
|
||||||
</div>
|
</div>
|
||||||
<div class="revue-flow__node-default" :draggable="true" @dragstart="(event: DragEvent) => onDragStart(event, 'default')">
|
<div class="vue-flow__node-default" :draggable="true" @dragstart="(event: DragEvent) => onDragStart(event, 'default')">
|
||||||
Default Node
|
Default Node
|
||||||
</div>
|
</div>
|
||||||
<div class="revue-flow__node-output" :draggable="true" @dragstart="(event: DragEvent) => onDragStart(event, 'output')">
|
<div class="vue-flow__node-output" :draggable="true" @dragstart="(event: DragEvent) => onDragStart(event, 'output')">
|
||||||
Output Node
|
Output Node
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ const center = computed(() =>
|
|||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<path :id="props.id" :style="props.style" class="revue-flow__edge-path" :d="edgePath" :marker-end="markerEnd" />
|
<path :id="props.id" :style="props.style" class="vue-flow__edge-path" :d="edgePath" :marker-end="markerEnd" />
|
||||||
<foreignObject
|
<foreignObject
|
||||||
:width="foreignObjectSize"
|
:width="foreignObjectSize"
|
||||||
:height="foreignObjectSize"
|
:height="foreignObjectSize"
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const edgePath = computed(() =>
|
|||||||
const markerEnd = computed(() => getMarkerEnd(props.arrowHeadType, props.markerEndId))
|
const markerEnd = computed(() => getMarkerEnd(props.arrowHeadType, props.markerEndId))
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<path :id="props.id" class="revue-flow__edge-path" :d="edgePath" :marker-end="markerEnd" />
|
<path :id="props.id" class="vue-flow__edge-path" :d="edgePath" :marker-end="markerEnd" />
|
||||||
<text>
|
<text>
|
||||||
<textPath :href="`#${props.id}`" :style="{ fontSize: '12px' }" startOffset="50%" text-anchor="middle">
|
<textPath :href="`#${props.id}`" :style="{ fontSize: '12px' }" startOffset="50%" text-anchor="middle">
|
||||||
{{ props.data.text }}
|
{{ props.data.text }}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ const center = computed(() =>
|
|||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<path :id="props.id" class="revue-flow__edge-path" :d="edgePath" :marker-end="markerEnd" />
|
<path :id="props.id" class="vue-flow__edge-path" :d="edgePath" :marker-end="markerEnd" />
|
||||||
<EdgeText
|
<EdgeText
|
||||||
:x="center[0]"
|
:x="center[0]"
|
||||||
:y="center[1]"
|
:y="center[1]"
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ const onChange = (event: any) => {
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<header>
|
<header>
|
||||||
<a class="logo" href="https://github.com/bcakmakoglu/revue-flow"> Revue Flow Dev </a>
|
<a class="logo" href="https://github.com/bcakmakoglu/vue-flow"> Vue Flow Dev </a>
|
||||||
<select v-model="route.path" @change="onChange">
|
<select v-model="route.path" @change="onChange">
|
||||||
<template v-for="r of routes" :key="r.path">
|
<template v-for="r of routes" :key="r.path">
|
||||||
<option v-if="r.path !== '/'" :value="r.path">
|
<option v-if="r.path !== '/'" :value="r.path">
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ watchEffect(() => {
|
|||||||
<div>
|
<div>
|
||||||
<label for="ishidden">
|
<label for="ishidden">
|
||||||
isHidden
|
isHidden
|
||||||
<input id="ishidden" v-model="isHidden" type="checkbox" class="revue-flow__ishidden" />
|
<input id="ishidden" v-model="isHidden" type="checkbox" class="vue-flow__ishidden" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -73,43 +73,43 @@ const captureElementClick = ref(false)
|
|||||||
<div>
|
<div>
|
||||||
<label for="draggable">
|
<label for="draggable">
|
||||||
nodesDraggable
|
nodesDraggable
|
||||||
<input id="draggable" v-model="isDraggable" type="checkbox" class="revue-flow__draggable" />
|
<input id="draggable" v-model="isDraggable" type="checkbox" class="vue-flow__draggable" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="connectable">
|
<label for="connectable">
|
||||||
nodesConnectable
|
nodesConnectable
|
||||||
<input id="connectable" v-model="isConnectable" type="checkbox" class="revue-flow__connectable" />
|
<input id="connectable" v-model="isConnectable" type="checkbox" class="vue-flow__connectable" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="selectable">
|
<label for="selectable">
|
||||||
elementsSelectable
|
elementsSelectable
|
||||||
<input id="selectable" v-model="isSelectable" type="checkbox" class="revue-flow__selectable" />
|
<input id="selectable" v-model="isSelectable" type="checkbox" class="vue-flow__selectable" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="zoomonscroll">
|
<label for="zoomonscroll">
|
||||||
zoomOnScroll
|
zoomOnScroll
|
||||||
<input id="zoomonscroll" v-model="zoomOnScroll" type="checkbox" class="revue-flow__zoomonscroll" />
|
<input id="zoomonscroll" v-model="zoomOnScroll" type="checkbox" class="vue-flow__zoomonscroll" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="zoomonpinch">
|
<label for="zoomonpinch">
|
||||||
zoomOnPinch
|
zoomOnPinch
|
||||||
<input id="zoomonpinch" v-model="zoomOnPinch" type="checkbox" class="revue-flow__zoomonpinch" />
|
<input id="zoomonpinch" v-model="zoomOnPinch" type="checkbox" class="vue-flow__zoomonpinch" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="panonscroll">
|
<label for="panonscroll">
|
||||||
panOnScroll
|
panOnScroll
|
||||||
<input id="panonscroll" v-model="panOnScroll" type="checkbox" class="revue-flow__panonscroll" />
|
<input id="panonscroll" v-model="panOnScroll" type="checkbox" class="vue-flow__panonscroll" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>
|
<label>
|
||||||
panOnScrollMode
|
panOnScrollMode
|
||||||
<select id="panonscrollmode" v-model="panOnScrollMode" class="revue-flow__panonscrollmode">
|
<select id="panonscrollmode" v-model="panOnScrollMode" class="vue-flow__panonscrollmode">
|
||||||
<option value="free">free</option>
|
<option value="free">free</option>
|
||||||
<option value="horizontal">horizontal</option>
|
<option value="horizontal">horizontal</option>
|
||||||
<option value="vertical">vertical</option>
|
<option value="vertical">vertical</option>
|
||||||
@@ -119,36 +119,31 @@ const captureElementClick = ref(false)
|
|||||||
<div>
|
<div>
|
||||||
<label for="zoomondbl">
|
<label for="zoomondbl">
|
||||||
zoomOnDoubleClick
|
zoomOnDoubleClick
|
||||||
<input id="zoomondbl" v-model="zoomOnDoubleClick" type="checkbox" class="revue-flow__zoomondbl" />
|
<input id="zoomondbl" v-model="zoomOnDoubleClick" type="checkbox" class="vue-flow__zoomondbl" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="panemoveable">
|
<label for="panemoveable">
|
||||||
paneMoveable
|
paneMoveable
|
||||||
<input id="panemoveable" v-model="paneMoveable" type="checkbox" class="revue-flow__panemoveable" />
|
<input id="panemoveable" v-model="paneMoveable" type="checkbox" class="vue-flow__panemoveable" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="capturezoompaneclick">
|
<label for="capturezoompaneclick">
|
||||||
capture onPaneClick
|
capture onPaneClick
|
||||||
<input id="capturezoompaneclick" v-model="captureZoomClick" type="checkbox" class="revue-flow__capturezoompaneclick" />
|
<input id="capturezoompaneclick" v-model="captureZoomClick" type="checkbox" class="vue-flow__capturezoompaneclick" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="capturezoompanescroll">
|
<label for="capturezoompanescroll">
|
||||||
capture onPaneScroll
|
capture onPaneScroll
|
||||||
<input
|
<input id="capturezoompanescroll" v-model="captureZoomScroll" type="checkbox" class="vue-flow__capturezoompanescroll" />
|
||||||
id="capturezoompanescroll"
|
|
||||||
v-model="captureZoomScroll"
|
|
||||||
type="checkbox"
|
|
||||||
class="revue-flow__capturezoompanescroll"
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="captureelementclick">
|
<label for="captureelementclick">
|
||||||
capture onElementClick
|
capture onElementClick
|
||||||
<input id="captureelementclick" v-model="captureElementClick" type="checkbox" class="revue-flow__captureelementclick" />
|
<input id="captureelementclick" v-model="captureElementClick" type="checkbox" class="vue-flow__captureelementclick" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+5
-5
@@ -58,22 +58,22 @@ header select {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__node a {
|
.vue-flow__node a {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #111;
|
color: #111;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__node.dark-node {
|
.vue-flow__node.dark-node {
|
||||||
background: #0041d0;
|
background: #0041d0;
|
||||||
color: #f8f8f8;
|
color: #f8f8f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__node.dark {
|
.vue-flow__node.dark {
|
||||||
background: #557;
|
background: #557;
|
||||||
color: #f8f8f8;
|
color: #f8f8f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__node-selectorNode {
|
.vue-flow__node-selectorNode {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
background: #f0f2f3;
|
background: #f0f2f3;
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
@@ -81,7 +81,7 @@ header select {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__node-selectorNode .revue-flow__handle {
|
.vue-flow__node-selectorNode .vue-flow__handle {
|
||||||
border-color: #f0f2f3;
|
border-color: #f0f2f3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Revue Flow Examples</title>
|
<title>Vue Flow Examples</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
+9
-9
@@ -1,25 +1,25 @@
|
|||||||
{
|
{
|
||||||
"name": "@braks/revue-flow",
|
"name": "@braks/vue-flow",
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"private": false,
|
"private": false,
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/bcakmakoglu/revue-flow"
|
"url": "https://github.com/bcakmakoglu/vue-flow"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "Burak Cakmakoglu",
|
"author": "Burak Cakmakoglu",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"import": "./dist/revue-flow.esm.js",
|
"import": "./dist/vue-flow.esm.js",
|
||||||
"require": "./dist/revue-flow.cjs.js"
|
"require": "./dist/vue-flow.cjs.js"
|
||||||
},
|
},
|
||||||
"./*": "./*"
|
"./*": "./*"
|
||||||
},
|
},
|
||||||
"main": "./dist/revue-flow.cjs.js",
|
"main": "./dist/vue-flow.cjs.js",
|
||||||
"types": "./dist/revue-flow.d.ts",
|
"types": "./dist/vue-flow.d.ts",
|
||||||
"module": "./dist/revue-flow.esm.js",
|
"module": "./dist/vue-flow.esm.js",
|
||||||
"unpkg": "./dist/revue-flow.iife.min.js",
|
"unpkg": "./dist/vue-flow.iife.min.js",
|
||||||
"jsdelivr": "./dist/revue-flow.iife.min.js",
|
"jsdelivr": "./dist/vue-flow.iife.min.js",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
@@ -14,20 +14,20 @@ const configs: any[] = []
|
|||||||
|
|
||||||
const activePackages = [
|
const activePackages = [
|
||||||
{
|
{
|
||||||
display: 'Revue-Flow',
|
display: 'vue-flow',
|
||||||
external: ['@vueuse/core']
|
external: ['@vueuse/core'],
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
for (const { external, iife } of activePackages) {
|
for (const { external, iife } of activePackages) {
|
||||||
const iifeGlobals = {
|
const iifeGlobals = {
|
||||||
vue: 'Vue',
|
'vue': 'Vue',
|
||||||
'@vueuse/core': 'VueUse'
|
'@vueuse/core': 'VueUse',
|
||||||
}
|
}
|
||||||
|
|
||||||
const iifeName = 'RevueFlow'
|
const iifeName = 'RevueFlow'
|
||||||
const functionNames = ['revue-flow']
|
const functionNames = ['vue-flow']
|
||||||
|
|
||||||
for (const fn of functionNames) {
|
for (const fn of functionNames) {
|
||||||
const input = 'src/index.ts'
|
const input = 'src/index.ts'
|
||||||
@@ -35,12 +35,12 @@ for (const { external, iife } of activePackages) {
|
|||||||
const output: any[] = [
|
const output: any[] = [
|
||||||
{
|
{
|
||||||
file: `dist/${fn}.cjs.js`,
|
file: `dist/${fn}.cjs.js`,
|
||||||
format: 'cjs'
|
format: 'cjs',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: `dist/${fn}.esm.js`,
|
file: `dist/${fn}.esm.js`,
|
||||||
format: 'es'
|
format: 'es',
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
if (iife !== false) {
|
if (iife !== false) {
|
||||||
@@ -50,7 +50,7 @@ for (const { external, iife } of activePackages) {
|
|||||||
format: 'iife',
|
format: 'iife',
|
||||||
name: iifeName,
|
name: iifeName,
|
||||||
extend: true,
|
extend: true,
|
||||||
globals: iifeGlobals
|
globals: iifeGlobals,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: `dist/${fn}.iife.min.js`,
|
file: `dist/${fn}.iife.min.js`,
|
||||||
@@ -61,11 +61,11 @@ for (const { external, iife } of activePackages) {
|
|||||||
plugins: [
|
plugins: [
|
||||||
terser({
|
terser({
|
||||||
format: {
|
format: {
|
||||||
comments: false
|
comments: false,
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,34 +76,34 @@ for (const { external, iife } of activePackages) {
|
|||||||
typescript({
|
typescript({
|
||||||
tsconfigOverride: {
|
tsconfigOverride: {
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
declaration: false
|
declaration: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
svg(),
|
svg(),
|
||||||
resolve(),
|
resolve(),
|
||||||
postcss({
|
postcss({
|
||||||
inject: true,
|
inject: true,
|
||||||
minimize: true
|
minimize: true,
|
||||||
}),
|
}),
|
||||||
commonjs({ include: 'node_modules/**' }),
|
commonjs({ include: 'node_modules/**' }),
|
||||||
babel({
|
babel({
|
||||||
extensions: [...DEFAULT_BABEL_EXTENSIONS, '.ts', '.tsx'],
|
extensions: [...DEFAULT_BABEL_EXTENSIONS, '.ts', '.tsx'],
|
||||||
exclude: 'node_modules/**',
|
exclude: 'node_modules/**',
|
||||||
babelHelpers: 'bundled'
|
babelHelpers: 'bundled',
|
||||||
})
|
}),
|
||||||
],
|
],
|
||||||
external: ['vue', ...(external || [])]
|
external: ['vue', ...(external || [])],
|
||||||
})
|
})
|
||||||
|
|
||||||
configs.push({
|
configs.push({
|
||||||
input,
|
input,
|
||||||
output: {
|
output: {
|
||||||
file: `dist/${fn}.d.ts`,
|
file: `dist/${fn}.d.ts`,
|
||||||
format: 'es'
|
format: 'es',
|
||||||
},
|
},
|
||||||
plugins: [dts()],
|
plugins: [dts()],
|
||||||
external: ['vue', ...(external || []), /\.css$/]
|
external: ['vue', ...(external || []), /\.css$/],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const defaultColors: Record<BackgroundVariant, string> = {
|
|||||||
const store = useStore()
|
const store = useStore()
|
||||||
// when there are multiple flows on a page we need to make sure that every background gets its own pattern.
|
// when there are multiple flows on a page we need to make sure that every background gets its own pattern.
|
||||||
|
|
||||||
const bgClasses = ['revue-flow__background']
|
const bgClasses = ['vue-flow__background']
|
||||||
const background = computed(() => {
|
const background = computed(() => {
|
||||||
const scaledGap = props.gap && props.gap * store.transform[2]
|
const scaledGap = props.gap && props.gap * store.transform[2]
|
||||||
const xOffset = scaledGap && store.transform[0] % scaledGap
|
const xOffset = scaledGap && store.transform[0] % scaledGap
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export interface ControlButtonProps extends ButtonHTMLAttributes {}
|
|||||||
const props: any = defineProps<ControlButtonProps>()
|
const props: any = defineProps<ControlButtonProps>()
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<button :class="['revue-flow__controls-button']" v-bind="props">
|
<button :class="['vue-flow__controls-button']" v-bind="props">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const store = useStore()
|
|||||||
const { zoomIn, zoomOut, fitView } = useZoomPanHelper()
|
const { zoomIn, zoomOut, fitView } = useZoomPanHelper()
|
||||||
|
|
||||||
const isInteractive = store.nodesDraggable && store.nodesConnectable && store.elementsSelectable
|
const isInteractive = store.nodesDraggable && store.nodesConnectable && store.elementsSelectable
|
||||||
const mapClasses = ['revue-flow__controls']
|
const mapClasses = ['vue-flow__controls']
|
||||||
|
|
||||||
const onZoomInHandler = () => {
|
const onZoomInHandler = () => {
|
||||||
zoomIn?.()
|
zoomIn?.()
|
||||||
@@ -56,14 +56,14 @@ const onInteractiveChangeHandler = () => {
|
|||||||
<div :class="mapClasses">
|
<div :class="mapClasses">
|
||||||
<template v-if="props.showZoom">
|
<template v-if="props.showZoom">
|
||||||
<slot name="control-zoom-in">
|
<slot name="control-zoom-in">
|
||||||
<ControlButton class="revue-flow__controls-zoomin" @click="onZoomInHandler">
|
<ControlButton class="vue-flow__controls-zoomin" @click="onZoomInHandler">
|
||||||
<slot name="icon-zoom-in">
|
<slot name="icon-zoom-in">
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
</slot>
|
</slot>
|
||||||
</ControlButton>
|
</ControlButton>
|
||||||
</slot>
|
</slot>
|
||||||
<slot name="control-zoom-out">
|
<slot name="control-zoom-out">
|
||||||
<ControlButton class="revue-flow__controls-zoomout" @click="onZoomOutHandler">
|
<ControlButton class="vue-flow__controls-zoomout" @click="onZoomOutHandler">
|
||||||
<slot name="icon-zoom-out">
|
<slot name="icon-zoom-out">
|
||||||
<MinusIcon />
|
<MinusIcon />
|
||||||
</slot>
|
</slot>
|
||||||
@@ -71,14 +71,14 @@ const onInteractiveChangeHandler = () => {
|
|||||||
</slot>
|
</slot>
|
||||||
</template>
|
</template>
|
||||||
<slot name="control-fitview">
|
<slot name="control-fitview">
|
||||||
<ControlButton v-if="props.showFitView" class="revue-flow__controls-fitview" @click="onFitViewHandler">
|
<ControlButton v-if="props.showFitView" class="vue-flow__controls-fitview" @click="onFitViewHandler">
|
||||||
<slot name="icon-fitview">
|
<slot name="icon-fitview">
|
||||||
<Fitview />
|
<Fitview />
|
||||||
</slot>
|
</slot>
|
||||||
</ControlButton>
|
</ControlButton>
|
||||||
</slot>
|
</slot>
|
||||||
<slot name="control-interactive">
|
<slot name="control-interactive">
|
||||||
<ControlButton v-if="props.showInteractive" class="revue-flow__controls-interactive" @click="onInteractiveChangeHandler">
|
<ControlButton v-if="props.showInteractive" class="vue-flow__controls-interactive" @click="onInteractiveChangeHandler">
|
||||||
<slot name="icon-unlock">
|
<slot name="icon-unlock">
|
||||||
<Unlock v-if="isInteractive" />
|
<Unlock v-if="isInteractive" />
|
||||||
</slot>
|
</slot>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ const viewBox = computed(() => {
|
|||||||
:width="elementWidth"
|
:width="elementWidth"
|
||||||
:height="elementHeight"
|
:height="elementHeight"
|
||||||
:viewBox="`${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`"
|
:viewBox="`${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`"
|
||||||
class="revue-flow__minimap"
|
class="vue-flow__minimap"
|
||||||
>
|
>
|
||||||
<slot name="mini-map-nodes" :nodes="store.nodes" :view-box="viewBox">
|
<slot name="mini-map-nodes" :nodes="store.nodes" :view-box="viewBox">
|
||||||
<template v-for="(node, i) of store.nodes" :key="`mini-map-node-${i}`">
|
<template v-for="(node, i) of store.nodes" :key="`mini-map-node-${i}`">
|
||||||
@@ -94,7 +94,7 @@ const viewBox = computed(() => {
|
|||||||
</template>
|
</template>
|
||||||
</slot>
|
</slot>
|
||||||
<path
|
<path
|
||||||
class="revue-flow__minimap-mask"
|
class="vue-flow__minimap-mask"
|
||||||
:d="`
|
:d="`
|
||||||
M${viewBox.x - viewBox.offset},${viewBox.y - viewBox.offset}h${viewBox.width + viewBox.offset * 2}
|
M${viewBox.x - viewBox.offset},${viewBox.y - viewBox.offset}h${viewBox.width + viewBox.offset * 2}
|
||||||
v${viewBox.height + viewBox.offset * 2}
|
v${viewBox.height + viewBox.offset * 2}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const fill = computed(() => (props.color || styles.background || styles.backgrou
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<rect
|
<rect
|
||||||
class="revue-flow__minimap-node"
|
class="vue-flow__minimap-node"
|
||||||
:x="props.x"
|
:x="props.x"
|
||||||
:y="props.y"
|
:y="props.y"
|
||||||
:rx="props.borderRadius"
|
:rx="props.borderRadius"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// These components are not used by revue Flow directly
|
// These components are not used by vue flow directly
|
||||||
// but the user can add them as children of a revue Flow component
|
// but the user can add them as children of a vue flow component
|
||||||
|
|
||||||
export { default as MiniMap } from './MiniMap/MiniMap.vue'
|
export { default as MiniMap } from './MiniMap/MiniMap.vue'
|
||||||
export { default as Controls } from './Controls/Controls.vue'
|
export { default as Controls } from './Controls/Controls.vue'
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ const dAttr = computed(() => {
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<g class="revue-flow__connection">
|
<g class="vue-flow__connection">
|
||||||
<slot
|
<slot
|
||||||
v-bind="{
|
v-bind="{
|
||||||
sourceX,
|
sourceX,
|
||||||
@@ -84,7 +84,7 @@ const dAttr = computed(() => {
|
|||||||
connectionLineStyle: props.connectionLineStyle,
|
connectionLineStyle: props.connectionLineStyle,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<path :d="dAttr" class="revue-flow__connection-path" :style="props.connectionLineStyle" />
|
<path :d="dAttr" class="vue-flow__connection-path" :style="props.connectionLineStyle" />
|
||||||
</slot>
|
</slot>
|
||||||
</g>
|
</g>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ const path = computed(() =>
|
|||||||
const markerEnd = computed(() => getMarkerEnd(props.arrowHeadType, props.markerEndId))
|
const markerEnd = computed(() => getMarkerEnd(props.arrowHeadType, props.markerEndId))
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<path class="revue-flow__edge-path" :style="props.style" :d="path" :marker-end="markerEnd" />
|
<path class="vue-flow__edge-path" :style="props.style" :d="path" :marker-end="markerEnd" />
|
||||||
<EdgeText
|
<EdgeText
|
||||||
v-if="props.label"
|
v-if="props.label"
|
||||||
:x="centered[0]"
|
:x="centered[0]"
|
||||||
|
|||||||
@@ -122,8 +122,8 @@ const edgePos = computed(() =>
|
|||||||
<g
|
<g
|
||||||
v-if="!props.edge.isHidden && isVisible(edgePos)"
|
v-if="!props.edge.isHidden && isVisible(edgePos)"
|
||||||
:class="[
|
:class="[
|
||||||
'revue-flow__edge',
|
'vue-flow__edge',
|
||||||
`revue-flow__edge-${props.edge.type || 'default'}`,
|
`vue-flow__edge-${props.edge.type || 'default'}`,
|
||||||
{
|
{
|
||||||
selected: isSelected,
|
selected: isSelected,
|
||||||
animated: props.edge.animated,
|
animated: props.edge.animated,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const props = withDefaults(defineProps<EdgeAnchorProps>(), {
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<circle
|
<circle
|
||||||
class="revue-flow__edgeupdater"
|
class="vue-flow__edgeupdater"
|
||||||
:cx="shiftX(props.centerX, props.radius, props.position)"
|
:cx="shiftX(props.centerX, props.radius, props.position)"
|
||||||
:cy="shiftY(props.centerY, props.radius, props.position)"
|
:cy="shiftY(props.centerY, props.radius, props.position)"
|
||||||
:r="props.radius"
|
:r="props.radius"
|
||||||
|
|||||||
@@ -30,19 +30,19 @@ const edgeRef = templateRef<SVGTextElement>('edge-text', null)
|
|||||||
const { width = 0, height = 0, x = 0, y = 0 } = useElementBounding(edgeRef)
|
const { width = 0, height = 0, x = 0, y = 0 } = useElementBounding(edgeRef)
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<g :transform="`translate(${props.x - width / 2} ${props.y - height / 2})`" class="revue-flow__edge-textwrapper">
|
<g :transform="`translate(${props.x - width / 2} ${props.y - height / 2})`" class="vue-flow__edge-textwrapper">
|
||||||
<rect
|
<rect
|
||||||
v-if="props.labelShowBg"
|
v-if="props.labelShowBg"
|
||||||
:width="width + 2 * props.labelBgPadding[0] + 'px'"
|
:width="width + 2 * props.labelBgPadding[0] + 'px'"
|
||||||
:height="height + 2 * props.labelBgPadding[1] + 'px'"
|
:height="height + 2 * props.labelBgPadding[1] + 'px'"
|
||||||
:x="-props.labelBgPadding[0]"
|
:x="-props.labelBgPadding[0]"
|
||||||
:y="-props.labelBgPadding[1]"
|
:y="-props.labelBgPadding[1]"
|
||||||
class="revue-flow__edge-textbg"
|
class="vue-flow__edge-textbg"
|
||||||
:style="props.labelBgStyle"
|
:style="props.labelBgStyle"
|
||||||
:rx="props.labelBgBorderRadius"
|
:rx="props.labelBgBorderRadius"
|
||||||
:ry="props.labelBgBorderRadius"
|
:ry="props.labelBgBorderRadius"
|
||||||
/>
|
/>
|
||||||
<text ref="edge-text" class="revue-flow__edge-text" :y="height / 2" dy="0.3em" :style="props.labelStyle">
|
<text ref="edge-text" class="vue-flow__edge-text" :y="height / 2" dy="0.3em" :style="props.labelStyle">
|
||||||
<component
|
<component
|
||||||
:is="props.label.component"
|
:is="props.label.component"
|
||||||
v-if="typeof props.label.component !== 'undefined'"
|
v-if="typeof props.label.component !== 'undefined'"
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ const path = computed(() =>
|
|||||||
const markerEnd = computed(() => getMarkerEnd(props.arrowHeadType, props.markerEndId))
|
const markerEnd = computed(() => getMarkerEnd(props.arrowHeadType, props.markerEndId))
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<path class="revue-flow__edge-path" :style="props.style" :d="path" :marker-end="markerEnd" />
|
<path class="vue-flow__edge-path" :style="props.style" :d="path" :marker-end="markerEnd" />
|
||||||
<EdgeText
|
<EdgeText
|
||||||
v-if="props.label"
|
v-if="props.label"
|
||||||
:x="centered[0]"
|
:x="centered[0]"
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ const markerEnd = computed(() => getMarkerEnd(props.arrowHeadType, props.markerE
|
|||||||
<template>
|
<template>
|
||||||
<path
|
<path
|
||||||
:style="props.style"
|
:style="props.style"
|
||||||
class="revue-flow__edge-path"
|
class="vue-flow__edge-path"
|
||||||
:d="`M ${props.sourceX},${props.sourceY}L ${props.targetX},${props.targetY}`"
|
:d="`M ${props.sourceX},${props.sourceY}L ${props.targetX},${props.targetY}`"
|
||||||
:marker-end="markerEnd"
|
:marker-end="markerEnd"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export const getMarkerEnd = (arrowHeadType?: ArrowHeadType, markerEndId?: string
|
|||||||
return `url(#${markerEndId})`
|
return `url(#${markerEndId})`
|
||||||
}
|
}
|
||||||
|
|
||||||
return typeof arrowHeadType !== 'undefined' ? `url(#revue-flow__${arrowHeadType})` : 'none'
|
return typeof arrowHeadType !== 'undefined' ? `url(#vue-flow__${arrowHeadType})` : 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetCenterParams {
|
export interface GetCenterParams {
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ const onMouseDownHandler = (event: MouseEvent) =>
|
|||||||
:data-nodeid="nodeId"
|
:data-nodeid="nodeId"
|
||||||
:data-handlepos="props.position"
|
:data-handlepos="props.position"
|
||||||
:class="[
|
:class="[
|
||||||
'revue-flow__handle',
|
'vue-flow__handle',
|
||||||
`revue-flow__handle-${props.position}`,
|
`vue-flow__handle-${props.position}`,
|
||||||
'nodrag',
|
'nodrag',
|
||||||
{
|
{
|
||||||
source: props.type !== 'target',
|
source: props.type !== 'target',
|
||||||
|
|||||||
@@ -142,8 +142,8 @@ onMounted(() => {
|
|||||||
<div
|
<div
|
||||||
ref="node-element"
|
ref="node-element"
|
||||||
:class="[
|
:class="[
|
||||||
'revue-flow__node',
|
'vue-flow__node',
|
||||||
`revue-flow__node-${props.node.type}`,
|
`vue-flow__node-${props.node.type}`,
|
||||||
{
|
{
|
||||||
selected: props.selected,
|
selected: props.selected,
|
||||||
selectable: props.selectable,
|
selectable: props.selectable,
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ const onContextMenu = (event: MouseEvent) => {
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="revue-flow__nodesselection"
|
class="vue-flow__nodesselection"
|
||||||
:style="{
|
:style="{
|
||||||
transform: `translate(${store.transform[0]}px,${store.transform[1]}px) scale(${store.transform[2]})`,
|
transform: `translate(${store.transform[0]}px,${store.transform[1]}px) scale(${store.transform[2]})`,
|
||||||
}"
|
}"
|
||||||
@@ -83,7 +83,7 @@ const onContextMenu = (event: MouseEvent) => {
|
|||||||
@move="onDrag"
|
@move="onDrag"
|
||||||
@stop="onStop"
|
@stop="onStop"
|
||||||
>
|
>
|
||||||
<div class="revue-flow__nodesselection-rect" :style="innerStyle" @contextmenu="onContextMenu" />
|
<div class="vue-flow__nodesselection-rect" :style="innerStyle" @contextmenu="onContextMenu" />
|
||||||
</Draggable>
|
</Draggable>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const props = defineProps<SelectionRectProps>()
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="revue-flow__selection"
|
class="vue-flow__selection"
|
||||||
:style="{
|
:style="{
|
||||||
width: `${props.width}px`,
|
width: `${props.width}px`,
|
||||||
height: `${props.height}px`,
|
height: `${props.height}px`,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ useEventListener(el, 'mouseup', onMouseUp)
|
|||||||
useEventListener(el, 'mouseleave', onMouseLeave)
|
useEventListener(el, 'mouseleave', onMouseLeave)
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div ref="user-selection" class="revue-flow__selectionpane">
|
<div ref="user-selection" class="vue-flow__selectionpane">
|
||||||
<SelectionRect
|
<SelectionRect
|
||||||
v-if="store.userSelectionRect.draw"
|
v-if="store.userSelectionRect.draw"
|
||||||
:width="store.userSelectionRect.width"
|
:width="store.userSelectionRect.width"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { XYPosition } from '~/types'
|
import { XYPosition } from '~/types'
|
||||||
|
|
||||||
export function getMousePosition(event: MouseEvent): XYPosition | void {
|
export function getMousePosition(event: MouseEvent): XYPosition | void {
|
||||||
const revueFlowNode = (event.target as Element).closest('.revue-flow')
|
const revueFlowNode = (event.target as Element).closest('.vue-flow')
|
||||||
if (!revueFlowNode) {
|
if (!revueFlowNode) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ export const checkElementBelowIsValid = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const resetRecentHandle = (hoveredHandle: Element): void => {
|
const resetRecentHandle = (hoveredHandle: Element): void => {
|
||||||
hoveredHandle?.classList.remove('revue-flow__handle-valid')
|
hoveredHandle?.classList.remove('vue-flow__handle-valid')
|
||||||
hoveredHandle?.classList.remove('revue-flow__handle-connecting')
|
hoveredHandle?.classList.remove('vue-flow__handle-connecting')
|
||||||
}
|
}
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
@@ -82,8 +82,8 @@ export default () => {
|
|||||||
},
|
},
|
||||||
elementEdgeUpdaterType?: HandleType,
|
elementEdgeUpdaterType?: HandleType,
|
||||||
) => {
|
) => {
|
||||||
const revueFlowNode = (event.target as Element).closest('.revue-flow')
|
const revueFlowNode = (event.target as Element).closest('.vue-flow')
|
||||||
// when revue-flow is used inside a shadow root we can't use document
|
// when vue-flow is used inside a shadow root we can't use document
|
||||||
const doc = getHostForElement(event.target as HTMLElement)
|
const doc = getHostForElement(event.target as HTMLElement)
|
||||||
|
|
||||||
if (!doc) return
|
if (!doc) return
|
||||||
@@ -130,8 +130,8 @@ export default () => {
|
|||||||
|
|
||||||
if (!isOwnHandle && elementBelow) {
|
if (!isOwnHandle && elementBelow) {
|
||||||
recentHoveredHandle = elementBelow
|
recentHoveredHandle = elementBelow
|
||||||
elementBelow.classList.add('revue-flow__handle-connecting')
|
elementBelow.classList.add('vue-flow__handle-connecting')
|
||||||
elementBelow.classList.toggle('revue-flow__handle-valid', isValid)
|
elementBelow.classList.toggle('vue-flow__handle-valid', isValid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export default (): UpdateNodeInternals => {
|
|||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
return (id: ElementId) => {
|
return (id: ElementId) => {
|
||||||
const nodeElement: HTMLDivElement | null = document.querySelector(`.revue-flow__node[data-id="${id}"]`)
|
const nodeElement: HTMLDivElement | null = document.querySelector(`.vue-flow__node[data-id="${id}"]`)
|
||||||
|
|
||||||
if (nodeElement) {
|
if (nodeElement) {
|
||||||
store.updateNodeDimensions([{ id, nodeElement, forceUpdate: true }])
|
store.updateNodeDimensions([{ id, nodeElement, forceUpdate: true }])
|
||||||
|
|||||||
@@ -149,13 +149,13 @@ export default (el: Ref<HTMLDivElement>, options: UseZoomOptions): UseZoom => {
|
|||||||
|
|
||||||
// when the target element is a node, we still allow zooming
|
// when the target element is a node, we still allow zooming
|
||||||
if (
|
if (
|
||||||
((event.target as Element).closest('.revue-flow__node') || (event.target as Element).closest('.revue-flow__edge')) &&
|
((event.target as Element).closest('.vue-flow__node') || (event.target as Element).closest('.vue-flow__edge')) &&
|
||||||
event.type !== 'wheel'
|
event.type !== 'wheel'
|
||||||
)
|
)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
// when the target element is a node selection, we still allow zooming
|
// when the target element is a node selection, we still allow zooming
|
||||||
if ((event.target as Element).closest('.revue-flow__nodesselection') && event.type !== 'wheel') return false
|
if ((event.target as Element).closest('.vue-flow__nodesselection') && event.type !== 'wheel') return false
|
||||||
|
|
||||||
if (!zoomOnPinch && event.ctrlKey && event.type === 'wheel') return false
|
if (!zoomOnPinch && event.ctrlKey && event.type === 'wheel') return false
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const connectionLineVisible = computed(
|
|||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<svg :width="store.dimensions.width" :height="store.dimensions.height" class="revue-flow__edges">
|
<svg :width="store.dimensions.width" :height="store.dimensions.height" class="vue-flow__edges">
|
||||||
<MarkerDefinitions :color="props.arrowHeadColor" />
|
<MarkerDefinitions :color="props.arrowHeadColor" />
|
||||||
<g
|
<g
|
||||||
:transform="store.transform.length && `translate(${store.transform[0]},${store.transform[1]}) scale(${store.transform[2]})`"
|
:transform="store.transform.length && `translate(${store.transform[0]},${store.transform[1]}) scale(${store.transform[2]})`"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const props = defineProps<MarkerProps>()
|
|||||||
<template>
|
<template>
|
||||||
<marker
|
<marker
|
||||||
:id="props.id"
|
:id="props.id"
|
||||||
class="revue-flow__arrowhead"
|
class="vue-flow__arrowhead"
|
||||||
markerWidth="12.5"
|
markerWidth="12.5"
|
||||||
markerHeight="12.5"
|
markerHeight="12.5"
|
||||||
viewBox="-10 -10 20 20"
|
viewBox="-10 -10 20 20"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const props = withDefaults(defineProps<MarkerDefinitionsProps>(), {
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<defs>
|
<defs>
|
||||||
<Marker id="revue-flow__arrowclosed">
|
<Marker id="vue-flow__arrowclosed">
|
||||||
<polyline
|
<polyline
|
||||||
:stroke="props.color"
|
:stroke="props.color"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
@@ -21,7 +21,7 @@ const props = withDefaults(defineProps<MarkerDefinitionsProps>(), {
|
|||||||
points="-5,-4 0,0 -5,4 -5,-4"
|
points="-5,-4 0,0 -5,4 -5,-4"
|
||||||
/>
|
/>
|
||||||
</Marker>
|
</Marker>
|
||||||
<Marker id="revue-flow__arrow">
|
<Marker id="vue-flow__arrow">
|
||||||
<polyline
|
<polyline
|
||||||
:stroke="props.color"
|
:stroke="props.color"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ const nodeTypes = createNodeTypes({ ...defaultNodeTypes, ...props.nodeTypes })
|
|||||||
const edgeTypes = createEdgeTypes({ ...defaultEdgeTypes, ...props.edgeTypes })
|
const edgeTypes = createEdgeTypes({ ...defaultEdgeTypes, ...props.edgeTypes })
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="revue-flow">
|
<div class="vue-flow">
|
||||||
<ZoomPane
|
<ZoomPane
|
||||||
:selection-key-code="props.selectionKeyCode"
|
:selection-key-code="props.selectionKeyCode"
|
||||||
:zoom-activation-key-code="props.zoomActivationKeyCode"
|
:zoom-activation-key-code="props.zoomActivationKeyCode"
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ const type = (node: TNode) => {
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="revue-flow__nodes"
|
class="vue-flow__nodes"
|
||||||
:style="{ transform: `translate(${store.transform[0]}px,${store.transform[1]}px) scale(${store.transform[2]})` }"
|
:style="{ transform: `translate(${store.transform[0]}px,${store.transform[1]}px) scale(${store.transform[2]})` }"
|
||||||
>
|
>
|
||||||
<template v-for="node of getNodes" :key="node.id">
|
<template v-for="node of getNodes" :key="node.id">
|
||||||
|
|||||||
@@ -52,5 +52,5 @@ useKeyPress(props.multiSelectionKeyCode, (keyPressed) => (store.multiSelectionAc
|
|||||||
<slot></slot>
|
<slot></slot>
|
||||||
<UserSelection v-if="selectionKeyPresed && (store.selectionActive || store.elementsSelectable)" id="user-selection" />
|
<UserSelection v-if="selectionKeyPresed && (store.selectionActive || store.elementsSelectable)" id="user-selection" />
|
||||||
<NodesSelection v-if="store.nodesSelectionActive" id="nodes-selection" />
|
<NodesSelection v-if="store.nodesSelectionActive" id="nodes-selection" />
|
||||||
<div class="revue-flow__pane" @click="onClick" @contextmenu="onContextMenu" @wheel="onWheel" />
|
<div class="vue-flow__pane" @click="onClick" @contextmenu="onContextMenu" @wheel="onWheel" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ hooks.load.trigger({
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div ref="zoom-pane" class="revue-flow__renderer revue-flow__zoompane">
|
<div ref="zoom-pane" class="vue-flow__renderer vue-flow__zoompane">
|
||||||
<slot v-bind="{ transform, dimensions: { width, height } }"></slot>
|
<slot v-bind="{ transform, dimensions: { width, height } }"></slot>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export default function useFlowStore(preloadedState: FlowState): StoreDefinition
|
|||||||
setActivePinia(pinia)
|
setActivePinia(pinia)
|
||||||
|
|
||||||
return defineStore({
|
return defineStore({
|
||||||
id: `revue-flow-${Math.floor(Math.random() * 100)}`,
|
id: `vue-flow-${Math.floor(Math.random() * 100)}`,
|
||||||
state: () => ({
|
state: () => ({
|
||||||
...preloadedState,
|
...preloadedState,
|
||||||
}),
|
}),
|
||||||
|
|||||||
+27
-27
@@ -1,13 +1,13 @@
|
|||||||
.revue-flow {
|
.vue-flow {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__renderer,
|
.vue-flow__renderer,
|
||||||
.revue-flow__pane,
|
.vue-flow__pane,
|
||||||
.revue-flow__selectionpane {
|
.vue-flow__selectionpane {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -15,25 +15,25 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__pane {
|
.vue-flow__pane {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__renderer {
|
.vue-flow__renderer {
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__selectionpane {
|
.vue-flow__selectionpane {
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__selection {
|
.vue-flow__selection {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__edges {
|
.vue-flow__edges {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__edge {
|
.vue-flow__edge {
|
||||||
pointer-events: visibleStroke;
|
pointer-events: visibleStroke;
|
||||||
|
|
||||||
&.inactive {
|
&.inactive {
|
||||||
@@ -55,20 +55,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__edge-path {
|
.vue-flow__edge-path {
|
||||||
fill: none;
|
fill: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__edge-textwrapper {
|
.vue-flow__edge-textwrapper {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__edge-text {
|
.vue-flow__edge-text {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__connection {
|
.vue-flow__connection {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
.animated {
|
.animated {
|
||||||
@@ -77,11 +77,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__connection-path {
|
.vue-flow__connection-path {
|
||||||
fill: none;
|
fill: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__nodes {
|
.vue-flow__nodes {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -90,14 +90,14 @@
|
|||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__node {
|
.vue-flow__node {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
transform-origin: 0 0;
|
transform-origin: 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__nodesselection {
|
.vue-flow__nodesselection {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -114,7 +114,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__handle {
|
.vue-flow__handle {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
&.connectable {
|
&.connectable {
|
||||||
@@ -122,39 +122,39 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__handle-bottom {
|
.vue-flow__handle-bottom {
|
||||||
top: auto;
|
top: auto;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
bottom: -4px;
|
bottom: -4px;
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__handle-top {
|
.vue-flow__handle-top {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: -4px;
|
top: -4px;
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__handle-left {
|
.vue-flow__handle-left {
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: -4px;
|
left: -4px;
|
||||||
transform: translate(0, -50%);
|
transform: translate(0, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__handle-right {
|
.vue-flow__handle-right {
|
||||||
right: -4px;
|
right: -4px;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translate(0, -50%);
|
transform: translate(0, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__edgeupdater {
|
.vue-flow__edgeupdater {
|
||||||
cursor: move;
|
cursor: move;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* additional components */
|
/* additional components */
|
||||||
|
|
||||||
.revue-flow__background {
|
.vue-flow__background {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -162,7 +162,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__controls {
|
.vue-flow__controls {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
@@ -179,7 +179,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__minimap {
|
.vue-flow__minimap {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
|
|||||||
+25
-25
@@ -1,11 +1,11 @@
|
|||||||
.revue-flow__selection {
|
.vue-flow__selection {
|
||||||
background: rgba(0, 89, 220, 0.08);
|
background: rgba(0, 89, 220, 0.08);
|
||||||
border: 1px dotted rgba(0, 89, 220, 0.8);
|
border: 1px dotted rgba(0, 89, 220, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__edge {
|
.vue-flow__edge {
|
||||||
&.selected {
|
&.selected {
|
||||||
.revue-flow__edge-path {
|
.vue-flow__edge-path {
|
||||||
stroke: #555;
|
stroke: #555;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,37 +16,37 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.updating {
|
&.updating {
|
||||||
.revue-flow__edge-path {
|
.vue-flow__edge-path {
|
||||||
stroke: #777;
|
stroke: #777;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__edge-path {
|
.vue-flow__edge-path {
|
||||||
stroke: #b1b1b7;
|
stroke: #b1b1b7;
|
||||||
stroke-width: 1;
|
stroke-width: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__edge-text {
|
.vue-flow__edge-text {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__edge-textbg {
|
.vue-flow__edge-textbg {
|
||||||
fill: white;
|
fill: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__connection-path {
|
.vue-flow__connection-path {
|
||||||
stroke: #b1b1b7;
|
stroke: #b1b1b7;
|
||||||
stroke-width: 1;
|
stroke-width: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__node {
|
.vue-flow__node {
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__node-default,
|
.vue-flow__node-default,
|
||||||
.revue-flow__node-input,
|
.vue-flow__node-input,
|
||||||
.revue-flow__node-output {
|
.vue-flow__node-output {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
width: 150px;
|
width: 150px;
|
||||||
@@ -57,15 +57,15 @@
|
|||||||
border-style: solid;
|
border-style: solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__node-default.selectable,
|
.vue-flow__node-default.selectable,
|
||||||
.revue-flow__node-input.selectable,
|
.vue-flow__node-input.selectable,
|
||||||
.revue-flow__node-output.selectable {
|
.vue-flow__node-output.selectable {
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: 0 1px 4px 1px rgba(0, 0, 0, 0.08);
|
box-shadow: 0 1px 4px 1px rgba(0, 0, 0, 0.08);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__node-input {
|
.vue-flow__node-input {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-color: #0041d0;
|
border-color: #0041d0;
|
||||||
|
|
||||||
@@ -74,12 +74,12 @@
|
|||||||
box-shadow: 0 0 0 0.5px #0041d0;
|
box-shadow: 0 0 0 0.5px #0041d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__handle {
|
.vue-flow__handle {
|
||||||
background: #0041d0;
|
background: #0041d0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__node-default {
|
.vue-flow__node-default {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-color: #1a192b;
|
border-color: #1a192b;
|
||||||
|
|
||||||
@@ -88,12 +88,12 @@
|
|||||||
box-shadow: 0 0 0 0.5px #1a192b;
|
box-shadow: 0 0 0 0.5px #1a192b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__handle {
|
.vue-flow__handle {
|
||||||
background: #1a192b;
|
background: #1a192b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__node-output {
|
.vue-flow__node-output {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-color: #ff0072;
|
border-color: #ff0072;
|
||||||
|
|
||||||
@@ -102,17 +102,17 @@
|
|||||||
box-shadow: 0 0 0 0.5px #ff0072;
|
box-shadow: 0 0 0 0.5px #ff0072;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__handle {
|
.vue-flow__handle {
|
||||||
background: #ff0072;
|
background: #ff0072;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__nodesselection-rect {
|
.vue-flow__nodesselection-rect {
|
||||||
background: rgba(0, 89, 220, 0.08);
|
background: rgba(0, 89, 220, 0.08);
|
||||||
border: 1px dotted rgba(0, 89, 220, 0.8);
|
border: 1px dotted rgba(0, 89, 220, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__handle {
|
.vue-flow__handle {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 6px;
|
width: 6px;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
@@ -125,11 +125,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__minimap {
|
.vue-flow__minimap {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revue-flow__controls {
|
.vue-flow__controls {
|
||||||
box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.08);
|
box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
&-button {
|
&-button {
|
||||||
|
|||||||
Reference in New Issue
Block a user