allow paneClick events to happen more leniantly
This commit is contained in:
@@ -34,7 +34,7 @@ const BasicFlow = () => {
|
||||
selectionMode={SelectionMode.Partial}
|
||||
panOnDrag={panOnDrag}
|
||||
panOnScroll
|
||||
paneClickDistance={2}
|
||||
paneClickDistance={100}
|
||||
zoomActivationKeyCode="Meta"
|
||||
multiSelectionKeyCode={MULTI_SELECT_KEY}
|
||||
onPaneContextMenu={onPaneContextMenu}
|
||||
@@ -44,6 +44,7 @@ const BasicFlow = () => {
|
||||
onMoveStart={onMoveStart}
|
||||
onMove={onMove}
|
||||
onMoveEnd={onMoveEnd}
|
||||
onPaneClick={(e) => console.log('pane click', e)}
|
||||
>
|
||||
<Background variant={BackgroundVariant.Cross} />
|
||||
<Controls />
|
||||
|
||||
@@ -9,11 +9,6 @@
|
||||
|
||||
import '@xyflow/svelte/dist/style.css';
|
||||
|
||||
const onPaneContextMenu = (e: any) => {
|
||||
e.preventDefault();
|
||||
console.log('context menu');
|
||||
};
|
||||
|
||||
const panOnDrag = [1, 2];
|
||||
|
||||
const onmovestart = (e: any) => console.log('move start', e);
|
||||
@@ -46,10 +41,12 @@
|
||||
selectionMode={SelectionMode.Partial}
|
||||
selectionOnDrag
|
||||
panOnScroll
|
||||
paneClickDistance={100}
|
||||
{panOnDrag}
|
||||
{onmovestart}
|
||||
{onmove}
|
||||
{onmoveend}
|
||||
onpaneclick={(e) => console.log('on pane click', e)}
|
||||
>
|
||||
<Controls />
|
||||
<Background variant={BackgroundVariant.Dots} />
|
||||
|
||||
@@ -67,6 +67,7 @@ export function Pane({
|
||||
selectionKeyPressed,
|
||||
selectionMode = SelectionMode.Full,
|
||||
panOnDrag,
|
||||
paneClickDistance = 0,
|
||||
selectionOnDrag,
|
||||
onSelectionStart,
|
||||
onSelectionEnd,
|
||||
@@ -117,14 +118,9 @@ export function Pane({
|
||||
const onWheel = onPaneScroll ? (event: React.WheelEvent) => onPaneScroll(event) : undefined;
|
||||
|
||||
const onClickCapture = (event: ReactMouseEvent) => {
|
||||
const isSelectionOnDragActive =
|
||||
(selectionOnDrag && container.current === event.target) || !selectionOnDrag || selectionKeyPressed;
|
||||
|
||||
if (!isSelectionOnDragActive) {
|
||||
return;
|
||||
if (selectionInProgress.current) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
// We are using capture here in order to prevent other pointer events
|
||||
@@ -149,9 +145,6 @@ export function Pane({
|
||||
return;
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
(event.target as Partial<Element>)?.setPointerCapture?.(event.pointerId);
|
||||
|
||||
selectionStarted.current = true;
|
||||
@@ -159,8 +152,6 @@ export function Pane({
|
||||
|
||||
const { x, y } = getEventPosition(event.nativeEvent, containerBounds.current);
|
||||
|
||||
resetSelectedElements();
|
||||
|
||||
store.setState({
|
||||
userSelectionRect: {
|
||||
width: 0,
|
||||
@@ -172,7 +163,14 @@ export function Pane({
|
||||
},
|
||||
});
|
||||
|
||||
onSelectionStart?.(event);
|
||||
if (event.target !== container.current || paneClickDistance === 0) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
resetSelectedElements();
|
||||
|
||||
onSelectionStart?.(event);
|
||||
}
|
||||
};
|
||||
|
||||
const onPointerMove = (event: ReactPointerEvent): void => {
|
||||
@@ -191,11 +189,23 @@ export function Pane({
|
||||
return;
|
||||
}
|
||||
|
||||
selectionInProgress.current = true;
|
||||
|
||||
const { x: mouseX, y: mouseY } = getEventPosition(event.nativeEvent, containerBounds.current);
|
||||
const { startX, startY } = userSelectionRect;
|
||||
|
||||
if (
|
||||
!selectionInProgress.current &&
|
||||
event.target === container.current &&
|
||||
!selectionKeyPressed &&
|
||||
paneClickDistance > 0
|
||||
) {
|
||||
const distance = Math.hypot(mouseX - startX, mouseY - startY);
|
||||
if (distance <= paneClickDistance) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
selectionInProgress.current = true;
|
||||
|
||||
const nextUserSelectRect = {
|
||||
startX,
|
||||
startY,
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
let {
|
||||
store = $bindable(),
|
||||
panOnDrag = true,
|
||||
paneClickDistance = 1,
|
||||
selectionOnDrag,
|
||||
onpaneclick,
|
||||
onpanecontextmenu,
|
||||
@@ -67,7 +68,7 @@
|
||||
let panOnDragActive = $derived(store.panActivationKeyPressed || panOnDrag);
|
||||
let isSelecting = $derived(
|
||||
store.selectionKeyPressed ||
|
||||
store.selectionRect ||
|
||||
!!store.selectionRect ||
|
||||
(selectionOnDrag && panOnDragActive !== true)
|
||||
);
|
||||
let hasActiveSelection = $derived(
|
||||
@@ -76,19 +77,7 @@
|
||||
|
||||
// Used to prevent click events when the user lets go of the selectionKey during a selection
|
||||
let selectionInProgress = false;
|
||||
|
||||
function onClick(event: MouseEvent) {
|
||||
// We prevent click events when the user let go of the selectionKey during a selection
|
||||
// We also prevent click events when a connection is in progress
|
||||
if (selectionInProgress || store.connection.inProgress) {
|
||||
selectionInProgress = false;
|
||||
return;
|
||||
}
|
||||
|
||||
onpaneclick?.({ event });
|
||||
store.unselectNodesAndEdges();
|
||||
store.selectionRectMode = null;
|
||||
}
|
||||
let selectionStarted = false;
|
||||
|
||||
// We start the selection process when the user clicks down on the pane
|
||||
function onPointerDownCapture(event: PointerEvent) {
|
||||
@@ -114,14 +103,12 @@
|
||||
return;
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
(event.target as Partial<Element>)?.setPointerCapture?.(event.pointerId);
|
||||
|
||||
const { x, y } = getEventPosition(event, containerBounds);
|
||||
selectionStarted = true;
|
||||
selectionInProgress = false;
|
||||
|
||||
store.unselectNodesAndEdges();
|
||||
const { x, y } = getEventPosition(event, containerBounds);
|
||||
|
||||
store.selectionRect = {
|
||||
width: 0,
|
||||
@@ -132,7 +119,14 @@
|
||||
y
|
||||
};
|
||||
|
||||
onselectionstart?.(event);
|
||||
if (event.target !== container || paneClickDistance === 0) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
store.unselectNodesAndEdges();
|
||||
|
||||
onselectionstart?.(event);
|
||||
}
|
||||
}
|
||||
|
||||
function onPointerMove(event: PointerEvent) {
|
||||
@@ -140,11 +134,23 @@
|
||||
return;
|
||||
}
|
||||
|
||||
selectionInProgress = true;
|
||||
|
||||
const mousePos = getEventPosition(event, containerBounds);
|
||||
const { startX = 0, startY = 0 } = store.selectionRect;
|
||||
|
||||
if (
|
||||
!selectionInProgress &&
|
||||
event.target === container &&
|
||||
!store.selectionKeyPressed &&
|
||||
paneClickDistance > 0
|
||||
) {
|
||||
const distance = Math.hypot(mousePos.x - startX, mousePos.y - startY);
|
||||
if (distance <= paneClickDistance) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
selectionInProgress = true;
|
||||
|
||||
const nextUserSelectRect = {
|
||||
...store.selectionRect,
|
||||
x: mousePos.x < startX ? mousePos.x : startX,
|
||||
@@ -195,7 +201,7 @@
|
||||
}
|
||||
|
||||
function onPointerUp(event: PointerEvent) {
|
||||
if (event.button !== 0) {
|
||||
if (event.button !== 0 || !selectionStarted) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -203,22 +209,20 @@
|
||||
|
||||
// We only want to trigger click functions when in selection mode if
|
||||
// the user did not move the mouse.
|
||||
if (!isSelecting && store.selectionRectMode === 'user' && event.target === container) {
|
||||
|
||||
if (!selectionInProgress && event.target === container) {
|
||||
onClick?.(event);
|
||||
}
|
||||
|
||||
store.selectionRect = null;
|
||||
|
||||
if (selectedNodeIds.size > 0) {
|
||||
if (selectionInProgress && selectedNodeIds.size > 0) {
|
||||
store.selectionRectMode = 'nodes';
|
||||
}
|
||||
|
||||
// If the user kept holding the selectionKey during the selection,
|
||||
// we need to reset the selectionInProgress, so the next click event is not prevented
|
||||
if (store.selectionKeyPressed) {
|
||||
selectionInProgress = false;
|
||||
}
|
||||
|
||||
onselectionend?.(event);
|
||||
|
||||
selectionStarted = false;
|
||||
}
|
||||
|
||||
const onContextMenu = (event: MouseEvent) => {
|
||||
@@ -231,17 +235,25 @@
|
||||
};
|
||||
|
||||
const onClickCapture = (event: MouseEvent) => {
|
||||
const isSelectionActive =
|
||||
(selectionOnDrag && container === event.target) ||
|
||||
!selectionOnDrag ||
|
||||
store.selectionKeyPressed;
|
||||
if (selectionInProgress) {
|
||||
event.stopPropagation();
|
||||
selectionInProgress = false;
|
||||
}
|
||||
};
|
||||
|
||||
if (!isSelectionActive) {
|
||||
function onClick(event: MouseEvent) {
|
||||
// We prevent click events when the user let go of the selectionKey during a selection
|
||||
// We also prevent click events when a connection is in progress
|
||||
if (selectionInProgress || store.connection.inProgress) {
|
||||
selectionInProgress = false;
|
||||
return;
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
};
|
||||
onpaneclick?.({ event });
|
||||
store.unselectNodesAndEdges();
|
||||
store.selectionRectMode = null;
|
||||
store.selectionRect = null;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
|
||||
Reference in New Issue
Block a user