update: Flow instance provides update node internals func

* Rename onLoadParams to FlowInstance
* Pass update node internals to instance
This commit is contained in:
Braks
2021-10-22 12:39:55 +02:00
parent cd32f14a5a
commit babcbd0e1f
23 changed files with 149 additions and 46 deletions
+3 -3
View File
@@ -7,7 +7,7 @@ import Flow, {
Edge,
Elements,
FlowElement,
OnLoadParams,
FlowInstance,
addEdge,
isNode,
removeElements,
@@ -24,11 +24,11 @@ const elements = ref<Elements>([
{ id: 'e1-2', source: '1', target: '2', animated: true },
{ id: 'e1-3', source: '1', target: '3' },
] as Elements)
const rfInstance = ref<OnLoadParams | null>(null)
const rfInstance = ref<FlowInstance | null>(null)
const onElementsRemove = (elementsToRemove: Elements) =>
(elements.value = removeElements(elementsToRemove, elements.value as Elements))
const onConnect = (params: Edge | Connection) => (elements.value = addEdge(params, elements.value as Elements))
const onLoad = (flowInstance: OnLoadParams) => {
const onLoad = (flowInstance: FlowInstance) => {
flowInstance.fitView({ padding: 0.1 })
rfInstance.value = flowInstance
}
+2 -2
View File
@@ -8,7 +8,7 @@ import Flow, {
Controls,
Node,
FlowElement,
OnLoadParams,
FlowInstance,
Elements,
Position,
SnapGrid,
@@ -25,7 +25,7 @@ const nodeTypes = {
selectorNode: ColorSelectorNode,
}
const onLoad = (flowInstance: OnLoadParams) => {
const onLoad = (flowInstance: FlowInstance) => {
flowInstance.fitView()
console.log('flow loaded:', flowInstance)
}
+3 -3
View File
@@ -1,9 +1,9 @@
<script lang="ts" setup>
import Sidebar from './Sidebar.vue'
import Flow, { addEdge, removeElements, Controls, OnLoadParams, Elements, Connection, Edge, ElementId, Node } from '~/index'
import Flow, { addEdge, removeElements, Controls, FlowInstance, Elements, Connection, Edge, ElementId, Node } from '~/index'
import './dnd.css'
const flowInstance = ref<OnLoadParams>()
const flowInstance = ref<FlowInstance>()
const elements = ref<Elements>([
{
id: '1',
@@ -26,7 +26,7 @@ const onDragOver = (event: DragEvent) => {
const onConnect = (params: Connection | Edge) => (elements.value = addEdge(params, elements.value as Elements))
const onElementsRemove = (elementsToRemove: Elements) =>
(elements.value = removeElements(elementsToRemove, elements.value as Elements))
const onLoad = (instance: OnLoadParams) => (flowInstance.value = instance)
const onLoad = (instance: FlowInstance) => (flowInstance.value = instance)
const onDrop = (event: DragEvent) => {
event.preventDefault()
+2 -2
View File
@@ -3,9 +3,9 @@
* Example for checking the different edge types and source and target positions
*/
import { getElements } from './utils'
import Flow, { removeElements, addEdge, MiniMap, Controls, Background, OnLoadParams, Connection, Edge, Elements } from '~/index'
import Flow, { removeElements, addEdge, MiniMap, Controls, Background, FlowInstance, Connection, Edge, Elements } from '~/index'
const onLoad = (flowInstance: OnLoadParams) => {
const onLoad = (flowInstance: FlowInstance) => {
flowInstance.fitView()
console.log(flowInstance.getElements())
}
+2 -2
View File
@@ -9,7 +9,7 @@ import Flow, {
EdgeType,
Elements,
MiniMap,
OnLoadParams,
FlowInstance,
removeElements,
} from '~/index'
const edgeTypes = {
@@ -32,7 +32,7 @@ const elements = ref<Elements>([
},
] as Elements)
const onLoad = (flowInstance: OnLoadParams) => flowInstance.fitView()
const onLoad = (flowInstance: FlowInstance) => flowInstance.fitView()
const onElementsRemove = (elementsToRemove: Elements) =>
(elements.value = removeElements(elementsToRemove, elements.value as Elements))
const onConnect = (params: Connection | Edge) =>
+2 -2
View File
@@ -7,7 +7,7 @@ import Flow, {
Controls,
Background,
Elements,
OnLoadParams,
FlowInstance,
FlowElement,
removeElements,
Connection,
@@ -81,7 +81,7 @@ const edgeTypes: Record<string, any> = {
const elements = ref<Elements>(initialElements as Elements)
const onLoad = (flowInstance: OnLoadParams) => flowInstance.fitView()
const onLoad = (flowInstance: FlowInstance) => flowInstance.fitView()
const onNodeDragStop = (node: Node) => console.log('drag stop', node)
const onElementClick = (element: FlowElement) => console.log('click', element)
const onElementsRemove = (elementsToRemove: Elements) => (elements.value = removeElements(elementsToRemove, elements.value))
+2 -2
View File
@@ -11,7 +11,7 @@ import Flow, {
Elements,
FlowElement,
Node,
OnLoadParams,
FlowInstance,
addEdge,
removeElements,
} from '~/index'
@@ -20,7 +20,7 @@ const elements = ref<Elements>([])
const onElementsRemove = (elementsToRemove: Elements) => (elements.value = removeElements(elementsToRemove, elements.value))
const onConnect = (params: Connection | Edge) => (elements.value = addEdge(params, elements.value))
const onLoad = (flowInstance: OnLoadParams) => console.log('flow loaded:', flowInstance)
const onLoad = (flowInstance: FlowInstance) => console.log('flow loaded:', flowInstance)
const onElementClick = (element: FlowElement) => console.log('click', element)
const onNodeDragStop = (node: Node) => console.log('drag stop', node)
@@ -1,6 +1,6 @@
<script lang="ts" setup>
import { CSSProperties } from 'vue'
import Flow, { addEdge, Connection, Edge, Elements, isEdge, OnLoadParams, Position } from '~/index'
import Flow, { addEdge, Connection, Edge, Elements, isEdge, FlowInstance, Position } from '~/index'
const initialElements: Elements = [
{
@@ -27,7 +27,7 @@ const elements = ref<Elements>(initialElements)
const onConnect = (params: Connection | Edge) => (elements.value = addEdge(params, elements.value))
const onLoad = (flowInstance: OnLoadParams) => flowInstance.fitView()
const onLoad = (flowInstance: FlowInstance) => flowInstance.fitView()
const changeType = () => {
elements.value = elements.value.map((el) => {
+2 -2
View File
@@ -10,7 +10,7 @@ import Flow, {
Node,
Elements,
FlowElement,
OnLoadParams,
FlowInstance,
FlowTransform,
SnapGrid,
ArrowHeadType,
@@ -35,7 +35,7 @@ const onSelectionContextMenu = (event: MouseEvent, nodes: Node[]) => {
const onElementClick = (_: MouseEvent, element: FlowElement) =>
console.log(`${isNode(element) ? 'node' : 'edge'} click:`, element)
const onSelectionChange = (elements: Elements | null) => console.log('selection change', elements)
const onLoad = (flowInstance: OnLoadParams) => {
const onLoad = (flowInstance: FlowInstance) => {
console.log('flow loaded:', flowInstance)
flowInstance.fitView()
}
+2 -2
View File
@@ -4,7 +4,7 @@ import Flow, {
addEdge,
removeElements,
Controls,
OnLoadParams,
FlowInstance,
FlowElement,
Connection,
Edge,
@@ -16,7 +16,7 @@ import Flow, {
import './provider.css'
const onElementClick = (element: FlowElement) => console.log('click', element)
const onLoad = (flowInstance: OnLoadParams) => console.log('flow loaded:', flowInstance)
const onLoad = (flowInstance: FlowInstance) => console.log('flow loaded:', flowInstance)
const initialElements: Elements = [
{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } },
+2 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts" setup>
import localforage from 'localforage'
import { useZoomPanHelper, OnLoadParams, FlowExportObject, Node } from '~/index'
import { useZoomPanHelper, FlowInstance, FlowExportObject, Node } from '~/index'
localforage.config({
name: 'vue-flow',
@@ -14,7 +14,7 @@ const getNodeId = () => `randomnode_${+new Date()}`
const { transform } = useZoomPanHelper()
type ControlsProps = {
flowInstance?: OnLoadParams
flowInstance?: FlowInstance
}
const props = defineProps<ControlsProps>()
+2 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts" setup>
import Controls from './Controls.vue'
import Flow, { addEdge, Connection, Node, Edge, Elements, OnLoadParams, removeElements } from '~/index'
import Flow, { addEdge, Connection, Node, Edge, Elements, FlowInstance, removeElements } from '~/index'
import './save.css'
@@ -15,7 +15,7 @@ const flowInstance = ref()
const onConnect = (params: Connection | Edge) => (elements.value = addEdge(params, elements.value))
const onElementsRemove = (elementsToRemove: Elements) => (elements.value = removeElements(elementsToRemove, elements.value))
const onLoad = (instance: OnLoadParams) => (flowInstance.value = instance)
const onLoad = (instance: FlowInstance) => (flowInstance.value = instance)
const onRestore = (els: Elements) => (elements.value = els)
const onAdd = (el: Node) => (elements.value = elements.value.concat(el))
</script>
+2 -2
View File
@@ -8,7 +8,7 @@ import Flow, {
isNode,
Controls,
Background,
OnLoadParams,
FlowInstance,
Elements,
Connection,
Edge,
@@ -16,7 +16,7 @@ import Flow, {
const buttonWrapperStyles: CSSProperties = { position: 'absolute', right: 10, top: 10, zIndex: 4 }
const onLoad = (flowInstance: OnLoadParams) => {
const onLoad = (flowInstance: FlowInstance) => {
flowInstance.fitView()
console.log(flowInstance.getElements())
}
@@ -4,7 +4,7 @@ import Flow, {
updateEdge,
addEdge,
Elements,
OnLoadParams,
FlowInstance,
Connection,
Edge,
removeElements,
@@ -40,7 +40,7 @@ const initialElements: Elements = [
] as Elements
const elements = ref(initialElements)
const onLoad = (flowInstance: OnLoadParams) => flowInstance.fitView()
const onLoad = (flowInstance: FlowInstance) => flowInstance.fitView()
const onEdgeUpdateStart = (edge: Edge) => console.log('start update', edge)
const onEdgeUpdateEnd = (edge: Edge) => console.log('end update', edge)
const onEdgeUpdate = ({ edge, connection }: FlowEvents['edgeUpdate']) =>
@@ -0,0 +1,25 @@
<script lang="ts" setup>
import { CSSProperties } from 'vue'
import { Handle, Position, NodeProps } from '~/index'
interface CustomNodeProps extends NodeProps {
data: any
}
const nodeStyles: CSSProperties = { padding: 10, border: '1px solid #ddd' }
const props = defineProps<CustomNodeProps>()
</script>
<template>
<div :style="nodeStyles">
<Handle type="target" :position="Position.Left" />
<div>output handle count: {{ props.data.handleCount }}</div>
<Handle
v-for="i of props.data.handleCount"
:id="`handle-${i}`"
:key="`handle-${i}`"
type="source"
:position="Position.Right"
:style="{ top: 10 * i + props.data.handlePosition * 10 }"
/>
</div>
</template>
@@ -0,0 +1,77 @@
<script lang="ts" setup>
import { CSSProperties } from 'vue'
import CustomNode from './CustomNode.vue'
import Flow, {
NodeType,
addEdge,
useZoomPanHelper,
Node,
Elements,
Connection,
Edge,
ElementId,
Position,
isEdge,
FlowInstance,
} from '~/index'
const initialHandleCount = 1
const initialElements: Elements = [
{
id: '1',
type: 'custom',
data: { label: 'Node 1', handleCount: initialHandleCount, handlePosition: 0 },
position: { x: 250, y: 5 },
},
] as Elements
const buttonWrapperStyles: CSSProperties = { position: 'absolute', right: 10, top: 10, zIndex: 10 }
const nodeTypes: Record<string, NodeType> = {
custom: CustomNode as NodeType,
}
let id = 5
const getId = (): ElementId => `${id++}`
const elements = ref<Elements>(initialElements)
const flowInstance = ref<FlowInstance>()
const onConnect = (params: Connection | Edge) => (elements.value = addEdge(params, elements.value))
const { project } = useZoomPanHelper()
const onPaneClick = (evt: MouseEvent) =>
(elements.value = elements.value.concat({
id: getId(),
position: project({ x: evt.clientX, y: evt.clientY - 40 }),
data: { label: 'new node' },
targetPosition: Position.Left,
sourcePosition: Position.Right,
} as Node))
const toggleHandleCount = () =>
(elements.value = elements.value.map((el) => {
if (isEdge(el)) {
return el
}
return { ...el, data: { ...el.data, handleCount: el.data?.handleCount === 1 ? 2 : 1 } }
}))
const toggleHandlePosition = () =>
(elements.value = elements.value.map((el) => {
if (isEdge(el)) return el
return { ...el, data: { ...el.data, handlePosition: el.data?.handlePosition === 0 ? 1 : 0 } }
}))
const onLoad = (instance: FlowInstance) => (flowInstance.value = instance)
</script>
<template>
<Flow :elements="elements" :node-types="nodeTypes" @connect="onConnect" @pane-click="onPaneClick" @load="onLoad">
<div :style="buttonWrapperStyles">
<button @click="toggleHandleCount">toggle handle count</button>
<button @click="toggleHandlePosition">toggle handle position</button>
<button @click="() => flowInstance.updateNodeInternals('1')">update node internals</button>
</div>
</Flow>
</template>
+4
View File
@@ -93,6 +93,10 @@ export const routes: RouterOptions['routes'] = [
path: '/update-node',
component: () => import('./UpdateNode/UpdateNodeExample.vue'),
},
{
path: '/update-node-internals',
component: () => import('./UpdateNodeInternals/UpdateNodeInternalsExample.vue'),
},
]
export const router = createRouter({
+2 -2
View File
@@ -1,4 +1,4 @@
import { Connection, Edge, Elements, EmitFunc, FlowHooks, FlowTransform, Node, OnConnectStartParams, OnLoadParams } from '~/types'
import { Connection, Edge, Elements, EmitFunc, FlowHooks, FlowTransform, Node, OnConnectStartParams, FlowInstance } from '~/types'
import { Hooks } from '~/context'
// flow event hooks
@@ -22,7 +22,7 @@ const hooks = (): FlowHooks => {
}>(),
connectStop: createEventHook<MouseEvent>(),
connectEnd: createEventHook<MouseEvent>(),
load: createEventHook<OnLoadParams>(),
load: createEventHook<FlowInstance>(),
move: createEventHook<FlowTransform | undefined>(),
moveStart: createEventHook<FlowTransform | undefined>(),
moveEnd: createEventHook<FlowTransform | undefined>(),
+4 -8
View File
@@ -1,14 +1,10 @@
import { ElementId, UpdateNodeInternals } from '~/types'
import useStore from '~/composables/useStore'
import { ElementId, FlowStore, UpdateNodeInternals } from '~/types'
export default (): UpdateNodeInternals => {
const store = useStore()
return (id: ElementId) => {
export default (store: FlowStore): UpdateNodeInternals =>
(id: ElementId) => {
const nodeElement: HTMLDivElement | null = document.querySelector(`.vue-flow__node[data-id="${id}"]`)
if (nodeElement) {
store.updateNodeDimensions([{ id, nodeElement, forceUpdate: true }])
store.updateNodeDimensions({ id, nodeElement, forceUpdate: true })
}
}
}
+2 -1
View File
@@ -4,7 +4,7 @@ import { D3ZoomEvent, zoom, zoomIdentity, ZoomTransform } from 'd3-zoom'
import { get } from '@vueuse/core'
import { pointer, select } from 'd3-selection'
import { FlowTransform, KeyCode, PanOnScrollMode } from '~/types'
import { useHooks, useKeyPress, useStore, useZoomPanHelper } from '~/composables'
import { useHooks, useKeyPress, useStore, useUpdateNodeInternals, useZoomPanHelper } from '~/composables'
import { clamp, onLoadGetElements, onLoadProject, onLoadToObject } from '~/utils/graph'
interface ZoomPaneProps {
@@ -208,6 +208,7 @@ onMounted(() => {
zoomOut,
zoomTo,
setTransform,
updateNodeInternals: useUpdateNodeInternals(store),
project: onLoadProject(store),
getElements: onLoadGetElements(store),
toObject: onLoadToObject(store),
-1
View File
@@ -17,7 +17,6 @@ export {
isInputDOMNode,
} from './utils/graph'
export { default as useZoomPanHelper } from './composables/useZoomPanHelper'
export { default as useUpdateNodeInternals } from './composables/useUpdateNodeInternals'
export { default as useStore } from './composables/useStore'
export { default as useHooks } from './composables/useHooks'
export { default as useHandle } from './composables/useHandle'
+2 -2
View File
@@ -1,5 +1,5 @@
import { EventHook } from '@vueuse/core'
import { Connection, Edge, Elements, FlowTransform, Node, OnConnectStartParams, OnLoadParams } from '../types'
import { Connection, Edge, Elements, FlowTransform, Node, OnConnectStartParams, FlowInstance } from '../types'
export type FlowHook<T = any> = EventHook<T>
@@ -22,7 +22,7 @@ export interface FlowEvents {
}
connectStop: MouseEvent
connectEnd: MouseEvent
load: OnLoadParams
load: FlowInstance
move: FlowTransform | undefined
moveStart: FlowTransform | undefined
moveEnd: FlowTransform | undefined
+3 -2
View File
@@ -77,7 +77,7 @@ export type FitViewFunc = (fitViewOptions?: FitViewParams) => void
export type ProjectFunc = (position: XYPosition) => XYPosition
export type ToObjectFunc<T = any> = () => FlowExportObject<T>
export type OnLoadParams<T = any> = {
export type FlowInstance<T = any> = {
zoomIn: () => void
zoomOut: () => void
zoomTo: (zoomLevel: number) => void
@@ -86,9 +86,10 @@ export type OnLoadParams<T = any> = {
getElements: () => Elements<T>
setTransform: (transform: FlowTransform) => void
toObject: ToObjectFunc<T>
updateNodeInternals: (id: ElementId) => void
}
export type OnLoadFunc<T = any> = (params: OnLoadParams<T>) => void
export type OnLoadFunc<T = any> = (params: FlowInstance<T>) => void
export interface FlowOptions extends Omit<HTMLAttributes, 'onLoad'> {
elements: Elements