Skip to content

Commit 450be60

Browse files
committed
Merge branch 'refs/heads/master' into release/2.0.0
2 parents 5f8ea6e + 4588471 commit 450be60

File tree

19 files changed

+258
-209
lines changed

19 files changed

+258
-209
lines changed

CHANGELOG.md

+46
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,52 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [1.40.0] - 2024-08-19
6+
7+
[809a9a4](809a9a4e16ba4b8cae4159c259ec6a9da0f42954)...[538b03e](538b03ef6b94d252410cca563428eb8288eba711)
8+
9+
### Bug Fixes
10+
11+
- Correct controlled flow docs and replace `applyChanges` with `applyDefault` (#1574) ([876c198](876c19868f6b21f600c33b16192a5d2c1fb9256f))
12+
- Simplify event emit definitions to avoid hitting complexity limit of TS (#1585) ([ebc604d](ebc604d9803d53b8eb78ae68b727aa7b216ad6b3))
13+
- Only display grab cursor when panOnDrag is on left mouse button (#1586) ([e90f4cc](e90f4cca57415ad068eec777fa1bbe2f8b70bd75))
14+
15+
### Documentation
16+
17+
- Update layouting example (#1576) ([2976b11](2976b1102528a88f7b367d9c660130f2b9d078b9))
18+
19+
### Refactor
20+
21+
- Remove null as return type of data in `useNodesData` (#1575) ([1d772af](1d772af4a4c6424af570672372025617bebbc686))
22+
23+
## [1.39.3] - 2024-08-06
24+
25+
[faeed3d](faeed3d6be9fe29c30a71ae09dbd056cc9445ad2)...[809a9a4](809a9a4e16ba4b8cae4159c259ec6a9da0f42954)
26+
27+
### Bug Fixes
28+
29+
- Push into changes arr instead of using index (#1569) ([afa8861](afa88610edcf573d339c13f06d20c1a94d4572b1))
30+
31+
## [1.39.2] - 2024-08-05
32+
33+
[90a289e](90a289ebbd29812657a64f9268ef23ce851d8462)...[faeed3d](faeed3d6be9fe29c30a71ae09dbd056cc9445ad2)
34+
35+
### Bug Fixes
36+
37+
- Only capture pointer if valid selection has started (#1565) ([a8d837b](a8d837bf93fb201b1805a2a8be79ed1084f7aad1))
38+
39+
## [1.39.1] - 2024-07-27
40+
41+
[d9a133b](d9a133bd0169be8c4d5fb4ea5807d83b24df291e)...[90a289e](90a289ebbd29812657a64f9268ef23ce851d8462)
42+
43+
### Bug Fixes
44+
45+
- Check if injected state matches options and scope id (#1562) ([fff558f](fff558fbc313d422716d8e5c9ec7255360cbb102))
46+
47+
### Miscellaneous Tasks
48+
49+
- Enable sitemaps (#1554) ([6d9535a](6d9535a1a938382aafb9ad94db7a1bb9e2e51aba))
50+
551
## [1.39.0] - 2024-07-15
652

753
[f2ecf29](f2ecf29cf8fe0f308768e5db6e28020ea3decd82)...[d9a133b](d9a133bd0169be8c4d5fb4ea5807d83b24df291e)

docs/examples/index.ts

-3
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,6 @@ export const exampleImports = {
137137
'useLayout.js': useLayout,
138138
'Icon.vue': LayoutIcon,
139139
'additionalImports': {
140-
'@vueuse/core': 'https://cdn.jsdelivr.net/npm/@vueuse/core@latest/index.mjs',
141-
'@vueuse/shared': 'https://cdn.jsdelivr.net/npm/@vueuse/shared@latest/index.mjs',
142-
'vue-demi': 'https://cdn.jsdelivr.net/npm/vue-demi@latest/lib/index.mjs',
143140
'@dagrejs/dagre': 'https://cdn.jsdelivr.net/npm/@dagrejs/[email protected]/+esm',
144141
},
145142
},

docs/examples/layout/AnimationEdge.vue

+38-73
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<script setup>
2-
import { computed, nextTick, ref, toRef, watch } from 'vue'
2+
import { computed, ref, toRef, watch } from 'vue'
33
import { BaseEdge, EdgeLabelRenderer, Position, getSmoothStepPath, useNodesData, useVueFlow } from '@vue-flow/core'
4-
import { TransitionPresets, executeTransition } from '@vueuse/core'
54
65
const props = defineProps({
76
id: {
@@ -42,29 +41,29 @@ const props = defineProps({
4241
},
4342
})
4443
45-
const { findEdge } = useVueFlow()
44+
const { updateEdgeData } = useVueFlow()
4645
4746
const nodesData = useNodesData([props.target, props.source])
4847
49-
const edgePoint = ref(0)
48+
const labelRef = ref()
5049
5150
const edgeRef = ref()
5251
53-
const labelPosition = ref({ x: 0, y: 0 })
52+
const targetNodeData = computed(() => nodesData.value[0].data)
5453
55-
const currentLength = ref(0)
56-
57-
const targetNodeData = toRef(() => nodesData.value[0].data)
58-
59-
const sourceNodeData = toRef(() => nodesData.value[1].data)
54+
const sourceNodeData = computed(() => nodesData.value[1].data)
6055
6156
const isFinished = toRef(() => sourceNodeData.value.isFinished)
6257
6358
const isCancelled = toRef(() => targetNodeData.value.isCancelled)
6459
6560
const isAnimating = ref(false)
6661
67-
const edgeColor = toRef(() => {
62+
let animation = null
63+
64+
const path = computed(() => getSmoothStepPath(props))
65+
66+
const edgeColor = computed(() => {
6867
if (targetNodeData.value.hasError) {
6968
return '#f87171'
7069
}
@@ -84,42 +83,14 @@ const edgeColor = toRef(() => {
8483
return '#6b7280'
8584
})
8685
87-
const path = computed(() => getSmoothStepPath(props))
88-
8986
watch(isCancelled, (isCancelled) => {
9087
if (isCancelled) {
91-
reset()
88+
animation?.cancel()
9289
}
9390
})
9491
9592
watch(isAnimating, (isAnimating) => {
96-
const edge = findEdge(props.id)
97-
98-
if (edge) {
99-
// we set the `isAnimating` flag, so we can wait until the next node gets executed
100-
edge.data = {
101-
...edge.data,
102-
isAnimating,
103-
}
104-
}
105-
})
106-
107-
watch(edgePoint, (point) => {
108-
const pathEl = edgeRef.value?.pathEl
109-
110-
if (!pathEl || point === 0 || !isAnimating.value) {
111-
return
112-
}
113-
114-
const nextLength = pathEl.getTotalLength()
115-
116-
// if length changed, restart animation
117-
if (currentLength.value !== nextLength) {
118-
runAnimation()
119-
return
120-
}
121-
122-
labelPosition.value = pathEl.getPointAtLength(point)
93+
updateEdgeData(props.id, { isAnimating })
12394
})
12495
12596
watch(isFinished, (isFinished) => {
@@ -128,7 +99,7 @@ watch(isFinished, (isFinished) => {
12899
}
129100
})
130101
131-
async function runAnimation() {
102+
function runAnimation() {
132103
const pathEl = edgeRef.value?.pathEl
133104
134105
if (!pathEl) {
@@ -137,35 +108,26 @@ async function runAnimation() {
137108
138109
const totalLength = pathEl.getTotalLength()
139110
140-
// if animation restarted, use last edgePoint value to continue from
141-
const from = edgePoint.value || 0
142-
143-
// update initial label position
144-
labelPosition.value = pathEl.getPointAtLength(from)
145-
146111
isAnimating.value = true
147112
148-
// update currentLength value, so we can check if the path length changed during animation
149-
if (currentLength.value !== totalLength) {
150-
currentLength.value = totalLength
151-
}
113+
const keyframes = [{ offsetDistance: '0%' }, { offsetDistance: '100%' }]
152114
153-
await executeTransition(edgePoint, from, totalLength, {
154-
transition: TransitionPresets.easeInOutCubic,
155-
duration: Math.max(1500, totalLength / 2),
156-
abort: () => !isAnimating.value,
115+
// use path length as a possible measure for the animation duration
116+
const pathLengthDuration = totalLength * 10
117+
118+
animation = labelRef.value.animate(keyframes, {
119+
duration: Math.min(Math.max(pathLengthDuration, 1500), 3000), // clamp duration between 1.5s and 3s
120+
direction: 'normal',
121+
easing: 'ease-in-out',
122+
iterations: 1,
157123
})
158124
159-
reset()
125+
animation.onfinish = handleAnimationEnd
126+
animation.oncancel = handleAnimationEnd
160127
}
161128
162-
function reset() {
163-
nextTick(() => {
164-
edgePoint.value = 0
165-
currentLength.value = 0
166-
labelPosition.value = { x: 0, y: 0 }
167-
isAnimating.value = false
168-
})
129+
function handleAnimationEnd() {
130+
isAnimating.value = false
169131
}
170132
</script>
171133
@@ -179,10 +141,18 @@ export default {
179141
<template>
180142
<BaseEdge :id="id" ref="edgeRef" :path="path[0]" :style="{ stroke: edgeColor }" />
181143
182-
<EdgeLabelRenderer v-if="isAnimating">
144+
<EdgeLabelRenderer>
183145
<div
184-
:style="{ transform: `translate(-50%, -50%) translate(${labelPosition.x}px,${labelPosition.y}px)` }"
185-
class="nodrag nopan animated-edge-label"
146+
ref="labelRef"
147+
:style="{
148+
visibility: isAnimating ? 'visible' : 'hidden',
149+
position: 'absolute',
150+
zIndex: 1,
151+
offsetPath: `path('${path[0]}')`,
152+
offsetRotate: '0deg',
153+
offsetAnchor: 'center',
154+
}"
155+
class="animated-edge-label"
186156
>
187157
<span class="truck">
188158
<span class="box">📦</span>
@@ -192,12 +162,7 @@ export default {
192162
</EdgeLabelRenderer>
193163
</template>
194164
195-
<style>
196-
.animated-edge-label {
197-
position: absolute;
198-
z-index: 100;
199-
}
200-
165+
<style scoped>
201166
.truck {
202167
position: relative;
203168
display: inline-block;

docs/examples/layout/ProcessNode.vue

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup>
2-
import { toRef } from 'vue'
2+
import { computed, toRef } from 'vue'
33
import { Handle, useHandleConnections } from '@vue-flow/core'
44
55
const props = defineProps({
@@ -27,7 +27,7 @@ const isSender = toRef(() => sourceConnections.value.length <= 0)
2727
2828
const isReceiver = toRef(() => targetConnections.value.length <= 0)
2929
30-
const bgColor = toRef(() => {
30+
const bgColor = computed(() => {
3131
if (isSender.value) {
3232
return '#2563eb'
3333
}
@@ -47,7 +47,7 @@ const bgColor = toRef(() => {
4747
return '#4b5563'
4848
})
4949
50-
const processLabel = toRef(() => {
50+
const processLabel = computed(() => {
5151
if (props.data.hasError) {
5252
return ''
5353
}
@@ -77,6 +77,7 @@ const processLabel = toRef(() => {
7777
<Handle v-if="!isSender" type="target" :position="targetPosition">
7878
<span v-if="!data.isRunning && !data.isFinished && !data.isCancelled && !data.isSkipped && !data.hasError">📥 </span>
7979
</Handle>
80+
8081
<Handle v-if="!isReceiver" type="source" :position="sourcePosition" />
8182

8283
<div v-if="!isSender && data.isRunning" class="spinner" />

docs/src/.vitepress/config.mts

+4
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ export default defineConfigWithTheme<DefaultTheme.Config>({
9999
],
100100
},
101101

102+
sitemap: {
103+
hostname: 'https://vueflow.dev'
104+
},
105+
102106
themeConfig: {
103107
logo: '/favicons/android-chrome-512x512.png',
104108
footer: {

docs/src/guide/controlled-flow.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -82,23 +82,23 @@ removeNodes('1')
8282
</script>
8383
```
8484

85-
## The `applyChanges` option
85+
## The `applyDefault` option
8686

87-
The `applyChanges` option is a prop that can be passed to the `<VueFlow>` component to enable or disable automatic change handling.
87+
The `applyDefault` option is a prop that can be passed to the `<VueFlow>` component to enable or disable automatic change handling.
8888

8989
By setting this option to `false`, we tell Vue Flow to not apply changes automatically anymore,
9090
that way we can take control of changes and apply them manually.
9191

9292
```vue
9393
<template>
94-
<VueFlow :nodes="nodes" :edges="edges" :apply-changes="false" />
94+
<VueFlow :nodes="nodes" :edges="edges" :apply-default="false" />
9595
</template>
9696
```
9797

9898
## `onNodesChange` / `onEdgesChange` events
9999

100100
Vue Flow provides two events that can be used to listen to changes on nodes and edges.
101-
These events are emitted regardless of the `applyChanges` option, so you can use them to listen to changes even if you have automatic changes enabled.
101+
These events are emitted regardless of the `applyDefault` option, so you can use them to listen to changes even if you have automatic changes enabled.
102102

103103
```vue
104104
<script setup>
@@ -150,7 +150,7 @@ const onChange = (changes) => {
150150

151151
Using what we just learned, we can now take control of changes and apply them manually.
152152

153-
In this example, we will first disable automatic change handlers with `applyChanges`,
153+
In this example, we will first disable automatic change handlers with `applyDefault`,
154154
then use the `onNodesChange` event to listen to changes and validate delete changes and,
155155
if they are valid, use `applyNodeChanges` to apply them.
156156

examples/vite/src/Basic/Basic.vue

+4-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const elements = ref<Elements>([
1515
{ id: 'e1-3', source: '1', target: '3' },
1616
])
1717
18-
const { onConnect, addEdges, setTransform, toObject } = useVueFlow({
18+
const { onConnect, addEdges, setViewport, toObject } = useVueFlow({
1919
minZoom: 0.2,
2020
maxZoom: 4,
2121
})
@@ -36,8 +36,8 @@ function updatePos() {
3636
function logToObject() {
3737
return console.log(toObject())
3838
}
39-
function resetTransform() {
40-
return setTransform({ x: 0, y: 0, zoom: 1 })
39+
function resetViewport() {
40+
return setViewport({ x: 0, y: 0, zoom: 1 })
4141
}
4242
function toggleclass() {
4343
return elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light'))
@@ -50,7 +50,7 @@ function toggleclass() {
5050
<MiniMap />
5151
<Controls />
5252
<Panel position="top-right" style="display: flex; gap: 5px">
53-
<button @click="resetTransform">reset transform</button>
53+
<button @click="resetViewport">reset viewport</button>
5454
<button @click="updatePos">change pos</button>
5555
<button @click="toggleclass">toggle class</button>
5656
<button @click="logToObject">toObject</button>

0 commit comments

Comments
 (0)