feat(handle): Add onClick handler

* for touch enabled connections
This commit is contained in:
Braks
2022-04-04 21:42:48 +02:00
parent 728046505c
commit b42c1b02de
7 changed files with 64 additions and 17 deletions
+9 -3
View File
@@ -4,7 +4,7 @@ import { Position } from '../../types'
import { NodeId } from '../../context'
import type { HandleProps } from '../../types/handle'
const { id, hooks } = useVueFlow()
const { id, hooks, connectionStartHandle } = useVueFlow()
const props = withDefaults(defineProps<HandleProps>(), {
type: 'source',
position: 'top' as Position,
@@ -13,11 +13,12 @@ const props = withDefaults(defineProps<HandleProps>(), {
const nodeId = inject(NodeId, '')
const handler = useHandle()
const { onMouseDown, onClick } = useHandle()
const onMouseDownHandler = (event: MouseEvent) =>
handler(event, props.id, nodeId, props.type === 'target', props.isValidConnection, undefined, (connection) =>
onMouseDown(event, props.id ?? null, nodeId, props.type === 'target', props.isValidConnection, undefined, (connection) =>
hooks.value.connect.trigger(connection),
)
const onClickHandler = (event: MouseEvent) => onClick(event, props.id ?? null, nodeId, props.type, props.isValidConnection)
</script>
<script lang="ts">
export default {
@@ -38,9 +39,14 @@ export default {
source: props.type !== 'target',
target: props.type === 'target',
connectable: props.connectable,
connecting:
connectionStartHandle?.nodeId === nodeId &&
connectionStartHandle?.handleId === props.id &&
connectionStartHandle?.type === props.type,
},
]"
@mousedown="onMouseDownHandler"
@click="onClickHandler"
>
<slot :node-id="nodeId" v-bind="props"></slot>
</div>
+50 -4
View File
@@ -15,7 +15,7 @@ export const checkElementBelowIsValid = (
connectionMode: ConnectionMode,
isTarget: boolean,
nodeId: string,
handleId: string,
handleId: string | null,
isValidConnection: ValidConnectionFunc,
doc: Document,
) => {
@@ -67,10 +67,10 @@ const resetRecentHandle = (hoveredHandle: Element): void => {
hoveredHandle?.classList.remove('vue-flow__handle-connecting')
}
export default (store: FlowStore = useVueFlow().store) =>
(
export default (store: FlowStore = useVueFlow().store) => {
const onMouseDown = (
event: MouseEvent,
handleId: string,
handleId: string | null,
nodeId: string,
isTarget: boolean,
isValidConnection?: ValidConnectionFunc,
@@ -173,3 +173,49 @@ export default (store: FlowStore = useVueFlow().store) =>
doc.addEventListener('mousemove', onMouseMove as EventListenerOrEventListenerObject)
doc.addEventListener('mouseup', onMouseUp as EventListenerOrEventListenerObject)
}
const onClick = (
event: MouseEvent,
handleId: string | null,
nodeId: string,
handleType: HandleType,
isValidConnection?: ValidConnectionFunc,
) => {
if (!store.connectOnClick) return
if (!store.connectionStartHandle) {
store.hooks.connectStart.trigger({ event, nodeId, handleId, handleType })
store.setState({ connectionStartHandle: { nodeId, type: handleType, handleId } })
} else {
let validConnectFunc: ValidConnectionFunc = isValidConnection ?? (() => true)
const node = store.getNode(nodeId)
if (node && (typeof node.connectable === 'undefined' ? store.nodesConnectable : node.connectable) === false) return
if (!isValidConnection) {
if (node) validConnectFunc = (handleType !== 'target' ? node.isValidTargetPos : node.isValidSourcePos) ?? (() => true)
}
const doc = getHostForElement(event.target as HTMLElement)
const { connection, isValid } = checkElementBelowIsValid(
event as MouseEvent,
store.connectionMode,
store.connectionStartHandle.type === 'target',
store.connectionStartHandle.nodeId,
store.connectionStartHandle.handleId || null,
validConnectFunc,
doc,
)
store.hooks.connectStop.trigger(event)
if (isValid) store.hooks.connect.trigger(connection)
store.hooks.connectEnd.trigger(event)
store.setState({ connectionStartHandle: null })
}
}
return {
onMouseDown,
onClick,
}
}
+1 -1
View File
@@ -28,7 +28,7 @@ export type OnConnectStartParams = {
/** Source node id */
nodeId?: string
/** Source handle id */
handleId?: string
handleId: string | null
/** Source handle type */
handleType?: HandleType
}
+1 -1
View File
@@ -1,5 +1,5 @@
import { CSSProperties, ToRefs } from 'vue'
import { GraphEdge, Edge, DefaultEdgeOptions } from "./edge";
import { GraphEdge, Edge, DefaultEdgeOptions } from './edge'
import { GraphNode, CoordinateExtent, Node } from './node'
import { ConnectionLineType, ConnectionMode } from './connection'
import { KeyCode, PanOnScrollMode, UseZoomPanHelper } from './zoom'
+1 -1
View File
@@ -21,7 +21,7 @@ export interface HandleProps {
/** Unique id of handle element */
id?: string
/** Handle type (source / target) {@link HandleType} */
type?: string
type?: HandleType
/** Handle position (top, bottom, left, right) {@link Position} */
position?: Position
/** A valid connection func {@link ValidConnectionFunc} */
-5
View File
@@ -72,8 +72,3 @@ export interface NodeProps<T = any> {
children?: Node<T>[]
dragHandle?: string
}
export type NodeBounds = XYPosition & {
width: number | null
height: number | null
}
+2 -2
View File
@@ -31,8 +31,8 @@ export const getHandlePosition = (position: Position, rect: Rect, handle?: Handl
}
}
export const getHandle = (bounds?: HandleElement[], handleId?: string): HandleElement | undefined => {
if (!bounds) return undefined
export const getHandle = (bounds: HandleElement[] = [], handleId: string | null): HandleElement | undefined => {
if (!bounds.length) return undefined
// there is no handleId when there are no multiple handles/ handles with ids
// so we just pick the first one