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