feat(store): add store as refs to useVueFlow

Signed-off-by: Braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
Braks
2021-12-20 19:29:52 +01:00
parent be725c6d2d
commit 91009e1dca
8 changed files with 46 additions and 29 deletions
@@ -5,6 +5,8 @@ import { getBoundsofRects, getRectOfNodes } from '../../utils'
import type { MiniMapProps } from '../../types/components' import type { MiniMapProps } from '../../types/components'
import MiniMapNode from './MiniMapNode.vue' import MiniMapNode from './MiniMapNode.vue'
type StringFunc = (node: GraphNode) => string
const props = withDefaults(defineProps<MiniMapProps>(), { const props = withDefaults(defineProps<MiniMapProps>(), {
nodeStrokeColor: '#555', nodeStrokeColor: '#555',
nodeColor: '#fff', nodeColor: '#fff',
+6 -3
View File
@@ -8,16 +8,19 @@ import { useStore } from '~/store'
const applyNodeChanges = (changes: NodeChange[], nodes: GraphNode[]) => applyChanges(changes, nodes) const applyNodeChanges = (changes: NodeChange[], nodes: GraphNode[]) => applyChanges(changes, nodes)
const applyEdgeChanges = (changes: EdgeChange[], edges: GraphEdge[]) => applyChanges(changes, edges) const applyEdgeChanges = (changes: EdgeChange[], edges: GraphEdge[]) => applyChanges(changes, edges)
let id = 0
export default (options?: FlowOptions): UseVueFlow => { export default (options?: FlowOptions): UseVueFlow => {
const currentInstance = getCurrentInstance() const currentInstance = getCurrentInstance()
let vueFlow: UseVueFlow | false | undefined = currentInstance ? inject(VueFlow, undefined) : false let vueFlow: UseVueFlow | false | undefined = currentInstance ? inject(VueFlow, undefined) : false
if (!vueFlow || (vueFlow && options?.id && options.id !== vueFlow.store.id)) { if (!vueFlow || (vueFlow && options?.id && options.id !== vueFlow.id)) {
const store = reactive(useStore(options)) const name = options?.id ?? `vue-flow-${id++}`
const store = reactive(useStore(name, options))
const applyNodes = (changes: NodeChange[]) => applyNodeChanges(changes, store.nodes) const applyNodes = (changes: NodeChange[]) => applyNodeChanges(changes, store.nodes)
const applyEdges = (changes: EdgeChange[]) => applyEdgeChanges(changes, store.edges) const applyEdges = (changes: EdgeChange[]) => applyEdgeChanges(changes, store.edges)
vueFlow = { vueFlow = {
id: store.id, id: name,
store, store,
...toRefs(store),
useNodesState: (nodes, applyDefault = true) => useNodesState(store, applyNodes)({ nodes, applyDefault }), useNodesState: (nodes, applyDefault = true) => useNodesState(store, applyNodes)({ nodes, applyDefault }),
useEdgesState: (edges, applyDefault = true) => useEdgesState(store, applyEdges)({ edges, applyDefault }), useEdgesState: (edges, applyDefault = true) => useEdgesState(store, applyEdges)({ edges, applyDefault }),
applyNodeChanges: applyNodes, applyNodeChanges: applyNodes,
+6 -8
View File
@@ -23,7 +23,7 @@ const emit = defineEmits([...Object.keys(createHooks()), 'update:modelValue', 'u
const { modelValue, nodes, edges } = useVModels(props, emit) const { modelValue, nodes, edges } = useVModels(props, emit)
const { store } = useVueFlow(props) const { store } = useVueFlow(props)
useHooks(store, emit) useHooks(store.hooks, emit)
nextTick(() => { nextTick(() => {
modelValue && (modelValue.value = [...store.nodes, ...store.edges]) modelValue && (modelValue.value = [...store.nodes, ...store.edges])
@@ -33,13 +33,11 @@ nextTick(() => {
modelValue && (modelValue.value = [...store.nodes, ...store.edges]) modelValue && (modelValue.value = [...store.nodes, ...store.edges])
edges && (edges.value = store.edges) edges && (edges.value = store.edges)
}) })
onMounted(() => { watch(
watch( () => props,
() => props, (v) => nextTick(() => store.setState(v)),
(v) => nextTick(() => store.setState(v)), { flush: 'sync', deep: true, immediate: true },
{ flush: 'sync' }, )
)
})
</script> </script>
<script lang="ts"> <script lang="ts">
export default { export default {
+1 -1
View File
@@ -47,4 +47,4 @@ const bind = (emit: EmitFunc, hooks: FlowHooks) => {
} }
} }
export default (store: FlowStore, emit: EmitFunc) => bind(emit, store.hooks) export default (hooks: FlowHooks, emit: EmitFunc) => bind(emit, hooks)
+2 -1
View File
@@ -15,7 +15,7 @@ export const defaultEdgeTypes: DefaultEdgeTypes = {
smoothstep: SmoothStepEdge, smoothstep: SmoothStepEdge,
} }
export default (): FlowState => ({ export default (preloadedState?: Partial<FlowState>): FlowState => ({
nodes: [], nodes: [],
edges: [], edges: [],
@@ -87,4 +87,5 @@ export default (): FlowState => ({
storageKey: undefined, storageKey: undefined,
vueFlowVersion: typeof __VUE_FLOW_VERSION__ !== 'undefined' ? __VUE_FLOW_VERSION__ : '-', vueFlowVersion: typeof __VUE_FLOW_VERSION__ !== 'undefined' ? __VUE_FLOW_VERSION__ : '-',
...preloadedState,
}) })
+25 -13
View File
@@ -2,10 +2,10 @@ import useState from './state'
import useActions from './actions' import useActions from './actions'
import useGetters from './getters' import useGetters from './getters'
import { FlowExportObject, FlowHooksOn, FlowOptions, FlowState, GraphEdge, GraphNode, Store } from '~/types' import { FlowExportObject, FlowHooksOn, FlowOptions, FlowState, GraphEdge, GraphNode, Store } from '~/types'
import { onLoadToObject } from '~/utils' import { isEdge, isNode, onLoadToObject } from '~/utils'
const useFlowStore = (id: string, preloadedState: FlowState): Store => { const useFlowStore = (preloadedState: FlowState): Store => {
const state = reactive(useState()) const state = reactive(useState(preloadedState))
const getters = useGetters(state) const getters = useGetters(state)
const actions = useActions(state, getters) const actions = useActions(state, getters)
const hooksOn: FlowHooksOn = <any>{} const hooksOn: FlowHooksOn = <any>{}
@@ -15,7 +15,6 @@ const useFlowStore = (id: string, preloadedState: FlowState): Store => {
}) })
actions.setState(preloadedState) actions.setState(preloadedState)
return { return {
id,
state, state,
hooksOn, hooksOn,
...toRefs(state), ...toRefs(state),
@@ -24,27 +23,40 @@ const useFlowStore = (id: string, preloadedState: FlowState): Store => {
} }
} }
let id = 0 export default (id: string, options?: FlowOptions) => {
export default (options?: FlowOptions) => {
const withStorage = options?.storageKey ?? false const withStorage = options?.storageKey ?? false
let storedState = ref<FlowExportObject>() let storedState = ref<FlowExportObject>()
const initial = useState() const storageKey = id ?? options?.id
const storageKey = options?.id ?? `vue-flow-${id++}`
const preloadedState = { const preloadedState = {
...initial,
...(options as FlowState), ...(options as FlowState),
} }
if (withStorage) { if (withStorage) {
storedState = useStorage<FlowExportObject>(storageKey, { edges: [], nodes: [], position: [0, 0], zoom: 0 }) storedState = useStorage<FlowExportObject>(storageKey, { edges: [], nodes: [], position: [0, 0], zoom: 0 })
if (storedState.value) { if (storedState.value) {
preloadedState.nodes = (storedState.value.nodes ? storedState.value.nodes : options?.nodes ?? []) as GraphNode[] preloadedState.nodes = (
preloadedState.edges = (storedState.value.edges ? storedState.value.edges : options?.edges ?? []) as GraphEdge[] storedState.value.nodes
? storedState.value.nodes
: options?.nodes
? options.nodes
: options?.elements
? options?.elements.filter((el) => isNode(el))
: []
) as GraphNode[]
preloadedState.edges = (
storedState.value.edges
? storedState.value.edges
: options?.edges
? options.edges
: options?.elements
? options?.elements.filter((el) => isEdge(el))
: []
) as GraphEdge[]
if (storedState.value.position && storedState.value.zoom) if (storedState.value.position && storedState.value.zoom)
preloadedState.transform = [storedState.value.position[0], storedState.value.position[1], storedState.value.zoom] preloadedState.transform = [storedState.value.position[0], storedState.value.position[1], storedState.value.zoom]
} }
} }
const store = useFlowStore(storageKey, preloadedState) const store = useFlowStore(preloadedState)
if (withStorage && storageKey === store.id) { if (withStorage && storageKey === id) {
const toObject = onLoadToObject(store.state) const toObject = onLoadToObject(store.state)
watch( watch(
store.state, store.state,
+3 -2
View File
@@ -1,4 +1,4 @@
import { CSSProperties } from 'vue' import { CSSProperties, ToRefs } from 'vue'
import { GraphEdge, Edge } from './edge' import { GraphEdge, Edge } from './edge'
import { GraphNode, CoordinateExtent, Node } from './node' import { GraphNode, CoordinateExtent, Node } from './node'
import { Connection, ConnectionLineType, ConnectionMode } from './connection' import { Connection, ConnectionLineType, ConnectionMode } from './connection'
@@ -153,4 +153,5 @@ export type UseVueFlow = {
useEdgesState: (edges?: Edge[], applyDefault?: boolean) => UseEdgeState useEdgesState: (edges?: Edge[], applyDefault?: boolean) => UseEdgeState
applyNodeChanges: (changes: NodeChange[]) => void applyNodeChanges: (changes: NodeChange[]) => void
applyEdgeChanges: (changes: EdgeChange[]) => void applyEdgeChanges: (changes: EdgeChange[]) => void
} & FlowHooksOn } & FlowHooksOn &
ToRefs<FlowStore>
+1 -1
View File
@@ -97,7 +97,7 @@ export interface FlowGetters<N = any, E = N> {
getSelectedEdges: ComputedRef<GraphEdge<E>[]> getSelectedEdges: ComputedRef<GraphEdge<E>[]>
} }
export type Store<N = any, E = N> = { id: string; state: FlowState<N, E>; hooksOn: FlowHooksOn } & ToRefs<FlowState<N, E>> & export type Store<N = any, E = N> = { state: FlowState<N, E>; hooksOn: FlowHooksOn } & ToRefs<FlowState<N, E>> &
FlowActions<N, E> & FlowActions<N, E> &
FlowGetters<N, E> FlowGetters<N, E>
export type FlowStore<N = any, E = N> = UnwrapNestedRefs<Store<N, E>> export type FlowStore<N = any, E = N> = UnwrapNestedRefs<Store<N, E>>