DragRecognizer
The pointer's drags and pans. drag is a Stream of Drag.Samples as a pointer drags target, kept
to its axis, and refused when another element holds that axis; pan gives the same samples with a
session's start at each down, moves nothing, and stops no drag. watchDrag and watchPan call you
with each sample inside its pointer event's dispatch while a Scope is open, with no fiber of their own:
a binding's drags run on these. They're apart from Recognizer's gestures, so an app that never drags
ships none of this.
import * as DragRecognizer from "@wardic/core/DragRecognizer"
yield* DragRecognizer.watchDrag(card, { axis: "x" }, {
on: (sample) => {
if (sample.phase === "end") fling(sample.velocity.x)
else moveTo(sample.offset.x)
},
})Interfaces
AdoptableDrag
An adoptable drag's watch, a target given drag controls: it can end its gesture from outside its
pointer, as Motion's drag controls' stop and cancel do. Each tells its "end" inside the call, and
does nothing when no gesture has started.
Extends
Properties
cancel
readonly cancel: () => void;Ends the gesture where it is: an "end" with no velocity, marked cancelled.
Returns
void
stop
readonly stop: () => void;Ends the gesture as its pointer's release would: an "end" at its last point, with its moves' velocity.
Returns
void
DragOptions
drag's and watchDrag's options.
Properties
adoptable?
readonly adoptable?: boolean;true: the target was given drag controls, so the drag reads the pointer feed that also delivers the
downs they hand it (InputSource.adoptablePointerOf), and its WatchedDrag ends a gesture from
outside. Default false: the plain feed, and a stop and cancel that do nothing.
axis?
readonly axis?: Axis | LazyArg<Axis>;The axes the drag moves on, and claims: "xy" by default. A one-axis drag's samples have their other
axis's offset, delta and velocity at 0; point and phase are left as they are. A function is
read at each gesture's start and holds to its end, as a Reorder item's axis is decided per gesture.
claim?
readonly claim?: boolean;false: the drag claims no axis and is never refused, as Motion's dragPropagation. It still counts
as an active drag, so no hover or press starts while it's on. Default true.
listen?
readonly listen?: boolean;false: a press on the target starts no gesture, only a down handed to it does, as Motion's
dragListener={false} with drag controls. Default true: both do.
lock?
readonly lock?: boolean;A direction lock, as Motion's dragDirectionLock: the gesture starts only once it's moved 10 px on one
axis, y first, as Motion's, and moves on that axis alone, so a parent that drags the other axis keeps
its gesture. A lock on an axis the drag doesn't move on, axis: "y" swiped sideways, refuses it.
Default false.
mapPoint?
readonly mapPoint?: LazyArg<Option<PointMap>>;Where each pointer point is for the gesture, as Motion's transformPagePoint: read at each down, and
applied to all that gesture's points, its down's and each move's. None, or no function given, leaves
them as they are. It's handed the point on the screen and gives one; the scroll a hold counts in is
added back after. A caller gives back the same Some while its mapping is the same, so a down
allocates nothing.
threshold?
readonly threshold?: (down) => Option<number>;How far, in px, a gesture from down moves before it starts, read at the down, as Motion's
distanceThreshold: none, or no function given, is 3. A direction lock still waits for its 10 px
on one axis.
Parameters
down
Returns
Option<number>
PanOptions
watchPan's options.
Properties
mapPoint?
readonly mapPoint?: LazyArg<Option<PointMap>>;Where each pointer point is for the gesture, as DragOptions' mapPoint.
PanSample
A pan's sample: a drag's, or its session's start, "session", as Motion's onPanSessionStart: at the
primary pointer's down on the target, at its point, with no offset, delta or velocity.
Extends
Omit<Sample,"phase">
Properties
axis
readonly axis: Axis;The axes it moves on, read at its start: its drag's axis, or a direction-locked drag's lock. A pan's are both.
Inherited from
cancelled?
readonly cancelled?: boolean;true on an "end" its watch's cancel gave: the drag ended where it is, which a binding
releases with no fling and tells no app. Absent on every other sample.
Inherited from
delta
readonly delta: Point;How far it's moved since the sample before.
Inherited from
offset
readonly offset: Point;How far it's moved since the down that started the drag: point less the down's.
Inherited from
phase
readonly phase: "start" | "end" | "move" | "session";"session" at the down, then a drag's: "start" past the threshold, "move", "end".
point
readonly point: Point;Where the pointer is, in the Environment's coordinates.
Inherited from
raw?
readonly raw?: unknown;The platform's own event behind it, which core never reads: a binding hands it to an app's callback.
Inherited from
scroll
readonly scroll: Point;The scroll counted into point since the down: point less scroll is where the pointer is on the screen.
Inherited from
timeStamp
readonly timeStamp: number;The time, in ms, of the event behind it: for a move a scroll made, the scroll's.
Inherited from
velocity
readonly velocity: Point;The pointer's velocity on each axis, in units a second, over the drag's last 100 ms, as Motion's.
The "end" sample counts the release point, so a pause before letting go slows it, down to none.
Inherited from
WatchedDrag
A drag's watch, as one with no drag controls gives it back: its Scope ends it, and nothing else does.
Extended by
Type Aliases
PointMap
type PointMap = (point) => Point;A point mapped, as Motion's transformPagePoint: the Environment's coordinates in, the gesture's out.
Parameters
point
Returns
Variables
watchDrag
const watchDrag: {
(target, options, handlers): Effect<AdoptableDrag, never, Scope | InputSource>;
(target, options, handlers): Effect<WatchedDrag, never, Scope | InputSource>;
(target, options, handlers): Effect<AdoptableDrag, never, Scope | InputSource>;
};Watches drags on target while the Scope is open: handlers.on hears each of a gesture's samples, kept
to its axis, inside its pointer event's dispatch.
- It starts once the pointer has moved
thresholdpx, 3 by default, from its down. - Its axis is claimed at its
"start", beforeonhears it, and counts as an active drag, so no hover or press starts elsewhere while it's on. Every watch on one target shares the claim. When another element holds an axis it needs, the gesture is refused: it tells nothing until its end, as a tap tells nothing, and doesn't retry. Of nested drags, the innermost claims first. Withclaim: falseit only counts. - Its claim is given back at its
"end", beforeonhears it, or when the Scope closes mid-drag, so a throw fromoncan't keep it. - Velocity is the pointer's on each axis over the last 100 ms, read from the events' times.
A down handed to the target starts a gesture as its own press does; with listen: false, only those
do. An adoptable watch gives back an AdoptableDrag, which ends a gesture from outside; a plain
one, a WatchedDrag. With adoptable known only when it runs, an AdoptableDrag whose ends do
nothing unless it is.
Call Signature
(
target,
options,
handlers
): Effect<AdoptableDrag, never, Scope | InputSource>;Parameters
target
unknown
options
DragOptions & object
handlers
Returns
Effect<AdoptableDrag, never, Scope | InputSource>
Call Signature
(
target,
options,
handlers
): Effect<WatchedDrag, never, Scope | InputSource>;Parameters
target
unknown
options
DragOptions & object
handlers
Returns
Effect<WatchedDrag, never, Scope | InputSource>
Call Signature
(
target,
options,
handlers
): Effect<AdoptableDrag, never, Scope | InputSource>;Parameters
target
unknown
options
handlers
Returns
Effect<AdoptableDrag, never, Scope | InputSource>
Example
const watched = yield* DragRecognizer.watchDrag(slider, { axis: "x", adoptable: true }, { on: move })
watched.cancel() // ends the gesture where it iswatchPan
const watchPan: (target, handlers, options?) => Effect.Effect<void, never, Scope.Scope | InputSource>;Parameters
target
unknown
handlers
options?
Returns
Effect.Effect<void, never, Scope.Scope | InputSource>
Functions
drag()
function drag(target, options?): Stream<Sample, never, InputSource>;A drag on target, as a Stream of samples kept to its axis, with watchDrag's rules: each sample
arrives inside its pointer event's dispatch, and the Stream ends when the input does, as a test's
script does.
Parameters
target
unknown
options?
DragOptions = {}
Returns
Stream<Sample, never, InputSource>
Example
DragRecognizer.drag(card, { axis: "x" }).pipe(Drag.withinBounds({ x: { min: 0, max: 200 } }))pan()
function pan(target): Stream<PanSample, never, InputSource>;A pan on target, as Motion's pan gesture: its session's start at the primary pointer's down, then a
drag's "start" past its threshold, a "move" at each move, and an "end" at the release, a cancel
or a lost release. It moves nothing.
A pan claims no axis, so it never stops a drag, nested or not, and no drag stops it. Once started it counts as an active drag until its end, so a press it took over ends as neither a tap nor a cancel, and no hover starts meanwhile: that's Wardic's, not Motion's, whose swipe let go over a tappable element taps it too.
Parameters
target
unknown
Returns
Stream<PanSample, never, InputSource>