refactor(store): use null instead of undefined for optional state properties

* remove setConnectionNodeId action
This commit is contained in:
Braks
2022-04-04 21:42:48 +02:00
parent 188156dd0b
commit 728046505c
13 changed files with 119 additions and 99 deletions
+1 -2
View File
@@ -2,11 +2,10 @@
import { useHandle, useVueFlow } from '../../composables' import { useHandle, useVueFlow } from '../../composables'
import { Position } from '../../types' import { Position } from '../../types'
import { NodeId } from '../../context' import { NodeId } from '../../context'
import type { HandleProps } from '../../types/components' import type { HandleProps } from '../../types/handle'
const { id, hooks } = useVueFlow() const { id, hooks } = useVueFlow()
const props = withDefaults(defineProps<HandleProps>(), { const props = withDefaults(defineProps<HandleProps>(), {
id: '',
type: 'source', type: 'source',
position: 'top' as Position, position: 'top' as Position,
connectable: true, connectable: true,
+13 -7
View File
@@ -26,7 +26,7 @@ export const checkElementBelowIsValid = (
const result: Result = { const result: Result = {
elementBelow, elementBelow,
isValid: false, isValid: false,
connection: { source: '', target: '', sourceHandle: '', targetHandle: '' }, connection: { source: null, target: null, sourceHandle: null, targetHandle: null },
isHoveringHandle: false, isHoveringHandle: false,
} }
@@ -99,14 +99,16 @@ export default (store: FlowStore = useVueFlow().store) =>
const containerBounds = flowNode.getBoundingClientRect() const containerBounds = flowNode.getBoundingClientRect()
let recentHoveredHandle: Element let recentHoveredHandle: Element
store.connectionPosition.x = event.clientX - containerBounds.left store.setState({
store.connectionPosition.y = event.clientY - containerBounds.top connectionPosition: {
x: event.clientX - containerBounds.left,
store.setConnectionNodeId({ y: event.clientY - containerBounds.top,
},
connectionNodeId: nodeId, connectionNodeId: nodeId,
connectionHandleId: handleId, connectionHandleId: handleId,
connectionHandleType: handleType, connectionHandleType: handleType,
}) })
store.hooks.connectStart.trigger({ event, nodeId, handleId, handleType }) store.hooks.connectStart.trigger({ event, nodeId, handleId, handleType })
function onMouseMove(event: MouseEvent) { function onMouseMove(event: MouseEvent) {
@@ -157,8 +159,12 @@ export default (store: FlowStore = useVueFlow().store) =>
if (elementEdgeUpdaterType) onEdgeUpdateEnd?.() if (elementEdgeUpdaterType) onEdgeUpdateEnd?.()
resetRecentHandle(recentHoveredHandle) resetRecentHandle(recentHoveredHandle)
store.setConnectionNodeId({ connectionNodeId: undefined, connectionHandleId: undefined, connectionHandleType: undefined }) store.setState({
store.connectionPosition = { x: NaN, y: NaN } connectionNodeId: null,
connectionHandleId: null,
connectionHandleType: null,
connectionPosition: { x: NaN, y: NaN },
})
doc.removeEventListener('mousemove', onMouseMove as EventListenerOrEventListenerObject) doc.removeEventListener('mousemove', onMouseMove as EventListenerOrEventListenerObject)
doc.removeEventListener('mouseup', onMouseUp as EventListenerOrEventListenerObject) doc.removeEventListener('mouseup', onMouseUp as EventListenerOrEventListenerObject)
+2
View File
@@ -21,6 +21,8 @@ const props = withDefaults(defineProps<FlowProps>(), {
paneMovable: undefined, paneMovable: undefined,
applyDefault: undefined, applyDefault: undefined,
fitViewOnInit: undefined, fitViewOnInit: undefined,
zoomActivationKeyCode: () => null,
connectionLineStyle: () => null,
}) })
const emit = defineEmits([...Object.keys(createHooks()), 'update:modelValue', 'update:edges', 'update:nodes']) const emit = defineEmits([...Object.keys(createHooks()), 'update:modelValue', 'update:edges', 'update:nodes'])
-10
View File
@@ -199,15 +199,6 @@ export default (state: State, getters: ComputedGetters): Actions => {
addSelectedNodes([]) addSelectedNodes([])
addSelectedEdges([]) addSelectedEdges([])
} }
const setConnectionNodeId: Actions['setConnectionNodeId'] = ({
connectionHandleId,
connectionHandleType,
connectionNodeId,
}) => {
state.connectionNodeId = connectionNodeId
state.connectionHandleId = connectionHandleId
state.connectionHandleType = connectionHandleType
}
const setInteractive: Actions['setInteractive'] = (isInteractive) => { const setInteractive: Actions['setInteractive'] = (isInteractive) => {
state.nodesDraggable = isInteractive state.nodesDraggable = isInteractive
state.nodesConnectable = isInteractive state.nodesConnectable = isInteractive
@@ -327,7 +318,6 @@ export default (state: State, getters: ComputedGetters): Actions => {
setMaxZoom, setMaxZoom,
setTranslateExtent, setTranslateExtent,
resetSelectedElements, resetSelectedElements,
setConnectionNodeId,
setInteractive, setInteractive,
setState, setState,
$reset: () => { $reset: () => {
+10 -8
View File
@@ -31,7 +31,7 @@ export default (opts?: FlowOptions): State => {
paneReady: false, paneReady: false,
initialized: false, initialized: false,
instance: undefined, instance: null,
dimensions: { dimensions: {
width: 0, width: 0,
@@ -39,9 +39,9 @@ export default (opts?: FlowOptions): State => {
}, },
transform: [0, 0, 1], transform: [0, 0, 1],
d3Zoom: undefined, d3Zoom: null,
d3Selection: undefined, d3Selection: null,
d3ZoomHandler: undefined, d3ZoomHandler: null,
minZoom: 0.5, minZoom: 0.5,
maxZoom: 2, maxZoom: 2,
translateExtent: [ translateExtent: [
@@ -73,11 +73,13 @@ export default (opts?: FlowOptions): State => {
defaultMarkerColor: '#b1b1b7', defaultMarkerColor: '#b1b1b7',
connectionLineStyle: {}, connectionLineStyle: {},
connectionLineType: ConnectionLineType.Bezier, connectionLineType: ConnectionLineType.Bezier,
connectionNodeId: undefined, connectionNodeId: null,
connectionHandleId: undefined, connectionHandleId: null,
connectionHandleType: 'source', connectionHandleType: null,
connectionPosition: { x: NaN, y: NaN }, connectionPosition: { x: NaN, y: NaN },
connectionMode: ConnectionMode.Loose, connectionMode: ConnectionMode.Loose,
connectionStartHandle: null,
connectOnClick: true,
snapGrid: [15, 15], snapGrid: [15, 15],
snapToGrid: false, snapToGrid: false,
@@ -90,7 +92,7 @@ export default (opts?: FlowOptions): State => {
multiSelectionActive: false, multiSelectionActive: false,
selectionKeyCode: 'Shift', selectionKeyCode: 'Shift',
multiSelectionKeyCode: 'Meta', multiSelectionKeyCode: 'Meta',
zoomActivationKeyCode: undefined, zoomActivationKeyCode: null,
deleteKeyCode: 'Backspace', deleteKeyCode: 'Backspace',
hooks: createHooks(), hooks: createHooks(),
+1 -48
View File
@@ -1,6 +1,5 @@
import { Component, CSSProperties, DefineComponent } from 'vue' import { Component, CSSProperties, DefineComponent } from 'vue'
import { BackgroundVariant, Dimensions, Position, XYPosition } from './flow' import { BackgroundVariant, Dimensions, XYPosition } from './flow'
import { Connection, ConnectionLineType } from './connection'
import { GraphNode, Node, NodeProps } from './node' import { GraphNode, Node, NodeProps } from './node'
import { EdgeProps } from './edge' import { EdgeProps } from './edge'
import { FitViewParams } from './zoom' import { FitViewParams } from './zoom'
@@ -23,29 +22,6 @@ export type EdgeComponent<E = any> =
export type DefaultEdgeTypes = { [key in 'default' | 'straight' | 'smoothstep' | 'step']: EdgeComponent } export type DefaultEdgeTypes = { [key in 'default' | 'straight' | 'smoothstep' | 'step']: EdgeComponent }
export type DefaultNodeTypes = { [key in 'input' | 'output' | 'default']: NodeComponent } export type DefaultNodeTypes = { [key in 'input' | 'output' | 'default']: NodeComponent }
export type HandleType = 'source' | 'target'
export interface HandleElement extends XYPosition, Dimensions {
id?: string
position: Position
}
/** A valid connection function can determine if an attempted connection is valid or not, i.e. abort creating a new edge */
export type ValidConnectionFunc = (connection: Connection) => boolean
export interface HandleProps {
/** Unique id of handle element */
id?: string
/** Handle type (source / target) {@link HandleType} */
type?: string
/** Handle position (top, bottom, left, right) {@link Position} */
position?: Position
/** A valid connection func {@link ValidConnectionFunc} */
isValidConnection?: ValidConnectionFunc
/** Enable/disable connecting to handle */
connectable?: boolean
}
export interface BackgroundProps { export interface BackgroundProps {
/** The background pattern */ /** The background pattern */
variant?: BackgroundVariant variant?: BackgroundVariant
@@ -128,26 +104,3 @@ export interface EdgeTextProps {
labelBgPadding?: [number, number] labelBgPadding?: [number, number]
labelBgBorderRadius?: number labelBgBorderRadius?: number
} }
export interface ConnectionLineProps<N = any> {
/** Source X position of the connection line */
sourceX: number
/** Source Y position of the connection line */
sourceY: number
/** Source position of the connection line */
sourcePosition: Position
/** Target X position of the connection line */
targetX: number
/** Target Y position of the connection line */
targetY: number
/** Target position of the connection line */
targetPosition: Position
connectionLineType: ConnectionLineType
connectionLineStyle: CSSProperties
/** All currently stored nodes */
nodes: GraphNode<N>[]
/** The source node of the connection line */
sourceNode: GraphNode<N>
/** The source handle element of the connection line */
sourceHandle: HandleElement
}
+31 -5
View File
@@ -1,4 +1,7 @@
import { HandleType } from './components' import { CSSProperties } from 'vue'
import { Position } from './flow'
import { GraphNode } from './node'
import { HandleElement, HandleType } from './handle'
/** Connection line types (same as default edge types */ /** Connection line types (same as default edge types */
export enum ConnectionLineType { export enum ConnectionLineType {
@@ -11,13 +14,13 @@ export enum ConnectionLineType {
/** Connection params that are passed when onConnect is called */ /** Connection params that are passed when onConnect is called */
export interface Connection { export interface Connection {
/** Source node id */ /** Source node id */
source: string source: string | null
/** Target node id */ /** Target node id */
target: string target: string | null
/** Source handle id */ /** Source handle id */
sourceHandle?: string sourceHandle: string | null
/** Target handle id */ /** Target handle id */
targetHandle?: string targetHandle: string | null
} }
/** The source nodes params when connection is initiated */ /** The source nodes params when connection is initiated */
@@ -41,3 +44,26 @@ export type SetConnectionId = {
connectionHandleId: string | undefined connectionHandleId: string | undefined
connectionHandleType: HandleType | undefined connectionHandleType: HandleType | undefined
} }
export interface ConnectionLineProps<N = any> {
/** Source X position of the connection line */
sourceX: number
/** Source Y position of the connection line */
sourceY: number
/** Source position of the connection line */
sourcePosition: Position
/** Target X position of the connection line */
targetX: number
/** Target Y position of the connection line */
targetY: number
/** Target position of the connection line */
targetPosition: Position
connectionLineType: ConnectionLineType
connectionLineStyle: CSSProperties
/** All currently stored nodes */
nodes: GraphNode<N>[]
/** The source node of the connection line */
sourceNode: GraphNode<N>
/** The source handle element of the connection line */
sourceHandle: HandleElement
}
+2 -2
View File
@@ -47,9 +47,9 @@ export interface Edge<T = any> extends Element<T> {
/** Target node id */ /** Target node id */
target: string target: string
/** Source handle id */ /** Source handle id */
sourceHandle?: string sourceHandle: string | null
/** Target handle id */ /** Target handle id */
targetHandle?: string targetHandle: string | null
/** Source position */ /** Source position */
sourcePosition?: Position sourcePosition?: Position
/** Target position */ /** Target position */
+10 -3
View File
@@ -1,5 +1,5 @@
import { CSSProperties, ToRefs } from 'vue' import { CSSProperties, ToRefs } from 'vue'
import { GraphEdge, Edge } from './edge' import { GraphEdge, Edge, DefaultEdgeOptions } from "./edge";
import { GraphNode, CoordinateExtent, Node } from './node' import { GraphNode, CoordinateExtent, Node } from './node'
import { ConnectionLineType, ConnectionMode } from './connection' import { ConnectionLineType, ConnectionMode } from './connection'
import { KeyCode, PanOnScrollMode, UseZoomPanHelper } from './zoom' import { KeyCode, PanOnScrollMode, UseZoomPanHelper } from './zoom'
@@ -93,11 +93,11 @@ export interface FlowProps<N = any, E = N> {
nodeTypes?: { [key in keyof DefaultNodeTypes]?: NodeComponent } & { [key: string]: NodeComponent } nodeTypes?: { [key in keyof DefaultNodeTypes]?: NodeComponent } & { [key: string]: NodeComponent }
connectionMode?: ConnectionMode connectionMode?: ConnectionMode
connectionLineType?: ConnectionLineType connectionLineType?: ConnectionLineType
connectionLineStyle?: CSSProperties connectionLineStyle?: CSSProperties | null
deleteKeyCode?: KeyCode deleteKeyCode?: KeyCode
selectionKeyCode?: KeyCode selectionKeyCode?: KeyCode
multiSelectionKeyCode?: KeyCode multiSelectionKeyCode?: KeyCode
zoomActivationKeyCode?: KeyCode zoomActivationKeyCode?: KeyCode | null
snapToGrid?: boolean snapToGrid?: boolean
snapGrid?: SnapGrid snapGrid?: SnapGrid
onlyRenderVisibleElements?: boolean onlyRenderVisibleElements?: boolean
@@ -116,6 +116,7 @@ export interface FlowProps<N = any, E = N> {
defaultMarkerColor?: string defaultMarkerColor?: string
zoomOnScroll?: boolean zoomOnScroll?: boolean
zoomOnPinch?: boolean zoomOnPinch?: boolean
panOnDrag?: boolean
panOnScroll?: boolean panOnScroll?: boolean
panOnScrollSpeed?: number panOnScrollSpeed?: number
panOnScrollMode?: PanOnScrollMode panOnScrollMode?: PanOnScrollMode
@@ -123,7 +124,13 @@ export interface FlowProps<N = any, E = N> {
preventScrolling?: boolean preventScrolling?: boolean
edgeUpdaterRadius?: number edgeUpdaterRadius?: number
fitViewOnInit?: boolean fitViewOnInit?: boolean
connectOnClick?: boolean
/** apply default change handlers for position, dimensions, adding/removing nodes. set this to false if you want to apply the changes manually */
applyDefault?: boolean applyDefault?: boolean
noDragClassName?: string
noWheelClassName?: string
noPanClassName?: string
defaultEdgeOptions?: DefaultEdgeOptions
} }
export type FlowOptions<N = any, E = N> = FlowProps<N, E> export type FlowOptions<N = any, E = N> = FlowProps<N, E>
+31
View File
@@ -0,0 +1,31 @@
import { Dimensions, Position, XYPosition } from './flow'
import { Connection } from './connection'
export type HandleType = 'source' | 'target'
export interface HandleElement extends XYPosition, Dimensions {
id?: string | null
position: Position
}
export interface StartHandle {
nodeId: string
type: HandleType
handleId?: string | null
}
/** A valid connection function can determine if an attempted connection is valid or not, i.e. abort creating a new edge */
export type ValidConnectionFunc = (connection: Connection) => boolean
export interface HandleProps {
/** Unique id of handle element */
id?: string
/** Handle type (source / target) {@link HandleType} */
type?: string
/** Handle position (top, bottom, left, right) {@link Position} */
position?: Position
/** A valid connection func {@link ValidConnectionFunc} */
isValidConnection?: ValidConnectionFunc
/** Enable/disable connecting to handle */
connectable?: boolean
}
+1
View File
@@ -7,3 +7,4 @@ export * from './zoom'
export * from './store' export * from './store'
export * from './hooks' export * from './hooks'
export * from './changes' export * from './changes'
export * from './handle'
+2 -1
View File
@@ -1,6 +1,7 @@
import { CSSProperties } from 'vue' import { CSSProperties } from 'vue'
import { XYPosition, Position, SnapGrid, Element, XYZPosition, Dimensions } from './flow' import { XYPosition, Position, SnapGrid, Element, XYZPosition, Dimensions } from './flow'
import { DefaultNodeTypes, HandleElement, ValidConnectionFunc } from './components' import { DefaultNodeTypes } from './components'
import { HandleElement, ValidConnectionFunc } from './handle'
export type CoordinateExtent = [[number, number], [number, number]] export type CoordinateExtent = [[number, number], [number, number]]
+15 -13
View File
@@ -1,23 +1,24 @@
import { ComputedRef, CSSProperties, ToRefs } from 'vue' import { ComputedRef, CSSProperties, ToRefs } from 'vue'
import { Dimensions, Elements, FlowElements, FlowInstance, FlowOptions, Rect, SnapGrid, Transform, XYPosition } from './flow' import { Dimensions, Elements, FlowElements, FlowInstance, FlowOptions, Rect, SnapGrid, Transform, XYPosition } from './flow'
import { HandleType, EdgeComponent, NodeComponent, DefaultNodeTypes, DefaultEdgeTypes } from './components' import { EdgeComponent, NodeComponent, DefaultNodeTypes, DefaultEdgeTypes } from './components'
import { Connection, ConnectionLineType, ConnectionMode, SetConnectionId } from './connection' import { Connection, ConnectionLineType, ConnectionMode } from './connection'
import { Edge, GraphEdge } from './edge' import { Edge, GraphEdge } from './edge'
import { GraphNode, CoordinateExtent, Node } from './node' import { GraphNode, CoordinateExtent, Node } from './node'
import { D3Selection, D3Zoom, D3ZoomHandler, KeyCode, PanOnScrollMode } from './zoom' import { D3Selection, D3Zoom, D3ZoomHandler, KeyCode, PanOnScrollMode } from './zoom'
import { FlowHooks, FlowHooksOn } from './hooks' import { FlowHooks, FlowHooksOn } from './hooks'
import { NodeChange, EdgeChange } from './changes' import { NodeChange, EdgeChange } from './changes'
import { StartHandle, HandleType } from './handle'
export interface State<N = any, E = N> extends Omit<FlowOptions<N, E>, 'id' | 'modelValue'> { export interface State<N = any, E = N> extends Omit<FlowOptions<N, E>, 'id' | 'modelValue'> {
hooks: FlowHooks<N, E> hooks: FlowHooks<N, E>
instance: FlowInstance<N, E> | undefined instance: FlowInstance<N, E> | null
nodes: GraphNode<N>[] nodes: GraphNode<N>[]
edges: GraphEdge<E>[] edges: GraphEdge<E>[]
d3Zoom: D3Zoom | undefined d3Zoom: D3Zoom | null
d3Selection: D3Selection | undefined d3Selection: D3Selection | null
d3ZoomHandler: D3ZoomHandler | undefined d3ZoomHandler: D3ZoomHandler | null
minZoom: number minZoom: number
maxZoom: number maxZoom: number
defaultZoom: number defaultZoom: number
@@ -35,15 +36,17 @@ export interface State<N = any, E = N> extends Omit<FlowOptions<N, E>, 'id' | 'm
deleteKeyCode: KeyCode deleteKeyCode: KeyCode
selectionKeyCode: KeyCode selectionKeyCode: KeyCode
multiSelectionKeyCode: KeyCode multiSelectionKeyCode: KeyCode
zoomActivationKeyCode: KeyCode | undefined zoomActivationKeyCode: KeyCode | null
connectionNodeId: string | undefined connectionNodeId: string | null
connectionHandleId: string | undefined connectionHandleId: string | null
connectionHandleType: HandleType | undefined connectionHandleType: HandleType | null
connectionPosition: XYPosition connectionPosition: XYPosition
connectionMode: ConnectionMode connectionMode: ConnectionMode
connectionLineType: ConnectionLineType connectionLineType: ConnectionLineType
connectionLineStyle: CSSProperties | undefined connectionLineStyle: CSSProperties | null
connectionStartHandle: StartHandle | null
connectOnClick: boolean
edgeUpdaterRadius: number edgeUpdaterRadius: number
snapToGrid: boolean snapToGrid: boolean
@@ -88,9 +91,8 @@ export interface Actions<N = any, E = N> {
setMaxZoom: (zoom: number) => void setMaxZoom: (zoom: number) => void
setTranslateExtent: (translateExtent: CoordinateExtent) => void setTranslateExtent: (translateExtent: CoordinateExtent) => void
resetSelectedElements: () => void resetSelectedElements: () => void
setConnectionNodeId: (payload: SetConnectionId) => void
setInteractive: (isInteractive: boolean) => void setInteractive: (isInteractive: boolean) => void
setState: (state: Partial<FlowOptions<N, E>>) => void setState: (state: Partial<FlowOptions<N, E> & Omit<State, 'nodes' | 'edges' | 'modelValue'>>) => void
updateNodePosition: ({ id, diff, dragging }: { id?: string; diff?: XYPosition; dragging?: boolean }) => void updateNodePosition: ({ id, diff, dragging }: { id?: string; diff?: XYPosition; dragging?: boolean }) => void
updateNodeDimensions: ( updateNodeDimensions: (
update: { update: {