feat(core): add connectableStart & connectableEnd props
Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
@@ -3,7 +3,21 @@ import { isFunction, isString } from '@vueuse/core'
|
|||||||
import { Position } from '../../types'
|
import { Position } from '../../types'
|
||||||
import type { HandleProps } from '../../types/handle'
|
import type { HandleProps } from '../../types/handle'
|
||||||
|
|
||||||
const { position = Position.Top, connectable, id, isValidConnection, ...props } = defineProps<HandleProps>()
|
const {
|
||||||
|
position = Position.Top,
|
||||||
|
connectable,
|
||||||
|
connectableStart = true,
|
||||||
|
connectableEnd = true,
|
||||||
|
id,
|
||||||
|
isValidConnection,
|
||||||
|
...props
|
||||||
|
} = defineProps<HandleProps>()
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(event: 'mousedown', e: MouseEvent): void
|
||||||
|
(event: 'touchstart', e: TouchEvent): void
|
||||||
|
(event: 'click', e: MouseEvent): void
|
||||||
|
}>()
|
||||||
|
|
||||||
const type = toRef(props, 'type', 'source')
|
const type = toRef(props, 'type', 'source')
|
||||||
|
|
||||||
@@ -42,6 +56,14 @@ const isConnectable = computed(() => {
|
|||||||
return isDef(connectable) ? connectable : nodesConnectable.value
|
return isDef(connectable) ? connectable : nodesConnectable.value
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const isConnecting = computed(
|
||||||
|
() =>
|
||||||
|
connectionStartHandle &&
|
||||||
|
connectionStartHandle.nodeId === nodeId &&
|
||||||
|
connectionStartHandle.handleId === handleId &&
|
||||||
|
connectionStartHandle.type === type.value,
|
||||||
|
)
|
||||||
|
|
||||||
// set up handle bounds if they don't exist yet and the node has been initialized (i.e. the handle was added after the node has already been mounted)
|
// set up handle bounds if they don't exist yet and the node has been initialized (i.e. the handle was added after the node has already been mounted)
|
||||||
until(() => node.initialized)
|
until(() => node.initialized)
|
||||||
.toBe(true, { flush: 'post' })
|
.toBe(true, { flush: 'post' })
|
||||||
@@ -71,6 +93,30 @@ until(() => node.initialized)
|
|||||||
|
|
||||||
node.handleBounds[type.value] = [...(node.handleBounds[type.value] ?? []), nextBounds]
|
node.handleBounds[type.value] = [...(node.handleBounds[type.value] ?? []), nextBounds]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function onPointerDown(event: MouseEvent | TouchEvent) {
|
||||||
|
const isMouseTriggered = isMouseEvent(event)
|
||||||
|
|
||||||
|
if (isConnectable.value && connectableStart && ((isMouseTriggered && event.button === 0) || !isMouseTriggered)) {
|
||||||
|
handlePointerDown(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMouseTriggered) {
|
||||||
|
emits('mousedown', event)
|
||||||
|
} else {
|
||||||
|
emits('touchstart', event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClick(event: MouseEvent) {
|
||||||
|
if (!connectionStartHandle && !connectableStart) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isConnectable.value) {
|
||||||
|
handleClick(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -95,16 +141,15 @@ export default {
|
|||||||
type,
|
type,
|
||||||
{
|
{
|
||||||
connectable: isConnectable,
|
connectable: isConnectable,
|
||||||
connecting:
|
connecting: isConnecting,
|
||||||
connectionStartHandle &&
|
connectablestart: connectableStart,
|
||||||
connectionStartHandle.nodeId === nodeId &&
|
connectableend: connectableEnd,
|
||||||
connectionStartHandle.handleId === handleId &&
|
connectionindicator: (isConnectable && connectableStart && !isConnecting) || (connectableEnd && isConnecting),
|
||||||
connectionStartHandle.type === type,
|
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
@mousedown="handlePointerDown"
|
@mousedown="onPointerDown"
|
||||||
@touchstart.passive="handlePointerDown"
|
@touchstart.passive="onPointerDown"
|
||||||
@click="handleClick"
|
@click="onClick"
|
||||||
>
|
>
|
||||||
<slot :id="id" />
|
<slot :id="id" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -58,6 +58,10 @@ export interface HandleProps {
|
|||||||
position?: Position
|
position?: Position
|
||||||
/** A valid connection func {@link ValidConnectionFunc} */
|
/** A valid connection func {@link ValidConnectionFunc} */
|
||||||
isValidConnection?: ValidConnectionFunc
|
isValidConnection?: ValidConnectionFunc
|
||||||
/** Enable/disable connecting to handle */
|
/** Enable/disable connecting to handle altogether */
|
||||||
connectable?: HandleConnectable
|
connectable?: HandleConnectable
|
||||||
|
/** Can this handle be used to *start* a connection */
|
||||||
|
connectableStart?: boolean
|
||||||
|
/** Can this handle be used to *end* a connection */
|
||||||
|
connectableEnd?: boolean
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,25 +98,30 @@ export function isValidHandle(
|
|||||||
connection: { source: '', target: '', sourceHandle: null, targetHandle: null },
|
connection: { source: '', target: '', sourceHandle: null, targetHandle: null },
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handleToCheck && handleDomNode && handle) {
|
if (handleToCheck) {
|
||||||
const handleNodeId = handleDomNode.getAttribute('data-nodeid')
|
const handleType = getHandleType(undefined, handleToCheck)
|
||||||
const handleId = handleDomNode.getAttribute('data-handleid')
|
const handleNodeId = handleToCheck.getAttribute('data-nodeid')!
|
||||||
|
const handleId = handleToCheck.getAttribute('data-handleid')
|
||||||
|
const connectable = handleToCheck.classList.contains('connectable')
|
||||||
|
const connectableEnd = handleToCheck.classList.contains('connectableend')
|
||||||
|
|
||||||
const connection: Connection = {
|
const connection: Connection = {
|
||||||
source: isTarget ? handle.nodeId : fromNodeId,
|
source: isTarget ? handleNodeId : fromNodeId,
|
||||||
sourceHandle: isTarget ? handleId : fromHandleId,
|
sourceHandle: isTarget ? handleId : fromHandleId,
|
||||||
target: isTarget ? fromNodeId : handle.nodeId,
|
target: isTarget ? fromNodeId : handleNodeId,
|
||||||
targetHandle: isTarget ? fromHandleId : handleId,
|
targetHandle: isTarget ? fromHandleId : handleId,
|
||||||
}
|
}
|
||||||
|
|
||||||
result.connection = connection
|
result.connection = connection
|
||||||
result.handleId = handleId
|
result.handleId = handleId
|
||||||
|
|
||||||
|
const isConnectable = connectable && connectableEnd
|
||||||
|
|
||||||
// in strict mode we don't allow target to target or source to source connections
|
// in strict mode we don't allow target to target or source to source connections
|
||||||
const isValid =
|
const isValid =
|
||||||
handleToCheck.classList.contains('connectable') &&
|
isConnectable &&
|
||||||
(connectionMode === ConnectionMode.Strict
|
(connectionMode === ConnectionMode.Strict
|
||||||
? (isTarget && handle.type === 'source') || (!isTarget && handle.type === 'target')
|
? (isTarget && handleType === 'source') || (!isTarget && handleType === 'target')
|
||||||
: handleNodeId !== fromNodeId || handleId !== fromHandleId)
|
: handleNodeId !== fromNodeId || handleId !== fromHandleId)
|
||||||
|
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
|
|||||||
Reference in New Issue
Block a user