refactor(core): add overloads to useVueFlow (#1481)

* refactor(core): add overloads to `useVueFlow`

* chore(changeset): add

* chore(core): cleanup
This commit is contained in:
Braks
2024-06-18 12:29:29 +02:00
parent 9b4e3b2656
commit 4fe1a7b541
5 changed files with 37 additions and 26 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@vue-flow/core": minor
---
Add overloads to `useVueFlow`. Allows calling `useVueFlow` with an `id` string only while emitting a deprecation warning for using the options obj.
+19 -8
View File
@@ -1,8 +1,8 @@
import { tryOnScopeDispose } from '@vueuse/core' import { tryOnScopeDispose } from '@vueuse/core'
import type { EffectScope } from 'vue' import type { EffectScope } from 'vue'
import { effectScope, getCurrentScope, inject, provide, watch } from 'vue' import { effectScope, getCurrentInstance, getCurrentScope, inject, provide, watch } from 'vue'
import type { EdgeChange, FlowOptions, NodeChange, VueFlowStore } from '../types' import type { EdgeChange, FlowOptions, NodeChange, VueFlowStore } from '../types'
import { warn } from '../utils' import { ErrorCode, VueFlowError, warn } from '../utils'
import { VueFlow } from '../context' import { VueFlow } from '../context'
import { Storage } from '../utils/storage' import { Storage } from '../utils/storage'
@@ -18,15 +18,21 @@ type Scope = (EffectScope & { vueFlowId: string }) | undefined
* If no store instance is found in context, a new store instance is created and registered in storage * If no store instance is found in context, a new store instance is created and registered in storage
* *
* @public * @public
* @param options - optional options to initialize the store instance
* @returns a vue flow store instance * @returns a vue flow store instance
* @param idOrOpts - id of the store instance or options to create a new store instance
*/ */
export function useVueFlow(options?: FlowOptions): VueFlowStore { export function useVueFlow(id?: string): VueFlowStore
export function useVueFlow(options?: FlowOptions): VueFlowStore
export function useVueFlow(idOrOpts?: any): VueFlowStore {
const storage = Storage.getInstance() const storage = Storage.getInstance()
const scope = getCurrentScope() as Scope const scope = getCurrentScope() as Scope
const id = options?.id const isOptsObj = typeof idOrOpts === 'object'
const options = isOptsObj ? idOrOpts : undefined
const id = options?.id ?? idOrOpts
const vueFlowId = scope?.vueFlowId || id const vueFlowId = scope?.vueFlowId || id
let vueFlow: Injection let vueFlow: Injection
@@ -114,7 +120,7 @@ export function useVueFlow(options?: FlowOptions): VueFlowStore {
}) })
} else { } else {
// If options were passed, overwrite state with the options' values // If options were passed, overwrite state with the options' values
if (options) { if (isOptsObj) {
vueFlow.setState(options) vueFlow.setState(options)
} }
} }
@@ -126,8 +132,13 @@ export function useVueFlow(options?: FlowOptions): VueFlowStore {
scope.vueFlowId = vueFlow.id scope.vueFlowId = vueFlow.id
} }
if (options) { if (isOptsObj) {
warn('options are deprecated and will be removed in the next major version. Use props on the `<VueFlow>` component instead.') const instance = getCurrentInstance()
// ignore the warning if we are in a VueFlow component
if (instance?.type.name !== 'VueFlow') {
vueFlow.emits.error(new VueFlowError(ErrorCode.USEVUEFLOW_OPTIONS))
}
} }
return vueFlow return vueFlow
@@ -309,7 +309,7 @@ export function useWatchProps(
;(storeRef.value as any) = nextValue ;(storeRef.value as any) = nextValue
} }
}, },
{ immediate: true, flush: 'pre' }, { immediate: true },
) )
}) })
} }
@@ -56,18 +56,12 @@ const modelValue = useVModel(props, 'modelValue', emit)
const modelNodes = useVModel(props, 'nodes', emit) const modelNodes = useVModel(props, 'nodes', emit)
const modelEdges = useVModel(props, 'edges', emit) const modelEdges = useVModel(props, 'edges', emit)
const { vueFlowRef, hooks, getNodeTypes, getEdgeTypes, ...rest } = useVueFlow(props) const instance = useVueFlow(props)
// watch props and update store state // watch props and update store state
const dispose = useWatchProps({ modelValue, nodes: modelNodes, edges: modelEdges }, props, { const dispose = useWatchProps({ modelValue, nodes: modelNodes, edges: modelEdges }, props, instance)
vueFlowRef,
hooks,
getNodeTypes,
getEdgeTypes,
...rest,
})
useHooks(emit, hooks) useHooks(emit, instance.hooks)
useOnInitHandler() useOnInitHandler()
@@ -83,13 +77,7 @@ onUnmounted(() => {
dispose() dispose()
}) })
defineExpose<VueFlowStore>({ defineExpose<VueFlowStore>(instance)
vueFlowRef,
hooks,
getNodeTypes,
getEdgeTypes,
...rest,
})
</script> </script>
<script lang="ts"> <script lang="ts">
@@ -100,7 +88,7 @@ export default {
</script> </script>
<template> <template>
<div ref="vueFlowRef" class="vue-flow"> <div :ref="instance.vueFlowRef" class="vue-flow">
<Viewport> <Viewport>
<EdgeRenderer /> <EdgeRenderer />
+7
View File
@@ -14,6 +14,9 @@ export enum ErrorCode {
EDGE_SOURCE_TARGET_SAME = 'EDGE_SOURCE_TARGET_SAME', EDGE_SOURCE_TARGET_SAME = 'EDGE_SOURCE_TARGET_SAME',
EDGE_SOURCE_TARGET_MISSING = 'EDGE_SOURCE_TARGET_MISSING', EDGE_SOURCE_TARGET_MISSING = 'EDGE_SOURCE_TARGET_MISSING',
EDGE_ORPHANED = 'EDGE_ORPHANED', EDGE_ORPHANED = 'EDGE_ORPHANED',
// deprecation errors
USEVUEFLOW_OPTIONS = 'USEVUEFLOW_OPTIONS',
} }
const messages = { const messages = {
@@ -36,6 +39,10 @@ const messages = {
[ErrorCode.EDGE_ORPHANED]: (id: string) => [ErrorCode.EDGE_ORPHANED]: (id: string) =>
`Edge was orphaned (suddenly missing source or target) and has been removed\nEdge: ${id}`, `Edge was orphaned (suddenly missing source or target) and has been removed\nEdge: ${id}`,
[ErrorCode.EDGE_NOT_FOUND]: (id: string) => `Edge not found\nEdge: ${id}`, [ErrorCode.EDGE_NOT_FOUND]: (id: string) => `Edge not found\nEdge: ${id}`,
// deprecation errors
[ErrorCode.USEVUEFLOW_OPTIONS]: () =>
`The options parameter is deprecated and will be removed in the next major version. Please use the id parameter instead`,
} as const } as const
type ErrorArgs<T extends ErrorCode> = (typeof messages)[T] extends (...args: any[]) => string type ErrorArgs<T extends ErrorCode> = (typeof messages)[T] extends (...args: any[]) => string