Skip to content

Commit

Permalink
Allow delay and distance constraints to be combined
Browse files Browse the repository at this point in the history
  • Loading branch information
clauderic committed Nov 6, 2023
1 parent 62b3446 commit 422a04d
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 26 deletions.
5 changes: 5 additions & 0 deletions .changeset/delay-or-distance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@dnd-kit/core': minor
---

Allow `delay` and `distance` activation constraints to be used concurrently for `MouseSensor`, `TouchSensor` and `PointerSensor`.
37 changes: 20 additions & 17 deletions packages/core/src/sensors/pointer/AbstractPointerSensor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@ export interface PointerEventHandlers {
end: EventDescriptor;
}

export type PointerActivationConstraint = DistanceConstraint | DelayConstraint;
export type PointerActivationConstraint =
| DelayConstraint
| DistanceConstraint
| (DelayConstraint & DistanceConstraint);

function isDistanceConstraint(
constraint: PointerActivationConstraint
): constraint is DistanceConstraint {
): constraint is PointerActivationConstraint & DistanceConstraint {
return Boolean(constraint && 'distance' in constraint);
}

Expand All @@ -55,7 +58,8 @@ export interface AbstractPointerSensorOptions extends SensorOptions {
onActivation?({event}: {event: Event}): void;
}

export type AbstractPointerSensorProps = SensorProps<AbstractPointerSensorOptions>;
export type AbstractPointerSensorProps =
SensorProps<AbstractPointerSensorOptions>;

export class AbstractPointerSensor implements SensorInstance {
public autoScrollEnabled = true;
Expand Down Expand Up @@ -109,17 +113,17 @@ export class AbstractPointerSensor implements SensorInstance {
this.documentListeners.add(EventName.Keydown, this.handleKeydown);

if (activationConstraint) {
if (isDistanceConstraint(activationConstraint)) {
return;
}

if (isDelayConstraint(activationConstraint)) {
this.timeoutId = setTimeout(
this.handleStart,
activationConstraint.delay
);
return;
}

if (isDistanceConstraint(activationConstraint)) {
return;
}
}

this.handleStart();
Expand Down Expand Up @@ -178,29 +182,28 @@ export class AbstractPointerSensor implements SensorInstance {
const coordinates = getEventCoordinates(event) ?? defaultCoordinates;
const delta = getCoordinatesDelta(initialCoordinates, coordinates);

// Constraint validation
if (!activated && activationConstraint) {
// Constraint validation
if (isDelayConstraint(activationConstraint)) {
if (hasExceededDistance(delta, activationConstraint.tolerance)) {
return this.handleCancel();
}

return;
}

if (isDistanceConstraint(activationConstraint)) {
if (
activationConstraint.tolerance != null &&
hasExceededDistance(delta, activationConstraint.tolerance)
) {
return this.handleCancel();
}

if (hasExceededDistance(delta, activationConstraint.distance)) {
return this.handleStart();
}
}

return;
if (isDelayConstraint(activationConstraint)) {
if (hasExceededDistance(delta, activationConstraint.tolerance)) {
return this.handleCancel();
}
}

return;
}

if (event.cancelable) {
Expand Down
28 changes: 19 additions & 9 deletions stories/1 - Core/Draggable/1-Draggable.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,10 @@ function DraggableItem({
handle,
buttonStyle,
}: DraggableItemProps) {
const {
attributes,
isDragging,
listeners,
setNodeRef,
transform,
} = useDraggable({
id: 'draggable',
});
const {attributes, isDragging, listeners, setNodeRef, transform} =
useDraggable({
id: 'draggable',
});

return (
<Draggable
Expand Down Expand Up @@ -154,6 +149,21 @@ export const PressDelay = () => (
/>
);

PressDelay.storyName = 'Press delay';

export const PressDelayOrDistance = () => (
<DraggableStory
label="Activated dragging 3px or holding 250ms"
activationConstraint={{
delay: 250,
distance: 3,
tolerance: 10,
}}
/>
);

PressDelayOrDistance.storyName = 'Press delay or minimum distance';

export const MinimumDistance = () => (
<DraggableStory
label="I'm activated after dragging 15px"
Expand Down

0 comments on commit 422a04d

Please sign in to comment.