Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | 94x 94x 94x 94x 94x 87x 87x 87x 87x 87x 87x 183x 183x 183x 145x 145x 38x 87x 87x 36x 51x 5x 46x 46x 46x 1x 45x 45x 45x 45x | /**
* @module Utils
*/
import * as MC from "@lisn/globals/minification-constants";
import * as MH from "@lisn/globals/minification-helpers";
import { getVectorDirection } from "@lisn/utils/directions";
import { getBrowserSupport } from "@lisn/utils/event";
import { GestureFragment } from "@lisn/utils/gesture";
/**
* Returns a {@link GestureFragment} for the given events. If the browser
* supports Pointer events, then only "pointermove" events will be considered.
* Otherwise, only "mousemove" events will be considered.
*
* If there are less than 2 such events in the given list of events, returns
* `false`.
*
* If the gesture is to be considered terminated, e.g. because there is
* "pointercancel" in the list or buttons other than the primary are pressed,
* returns `null`.
*
* Pointer gestures always require the primary button to be pressed and the
* resulting intent is always "drag", and `deltaZ` is always 1.
*
* @param [options.angleDiffThreshold] See {@link getVectorDirection}
*
* @returns `false` if there are less than 2 "pointermove"/"mousemove" events
* in the list, `null` if the gesture is terminated, otherwise a
* {@link GestureFragment}.
*
* @category Gestures
*/
export const getPointerGestureFragment = (
events: Event | readonly Event[],
options?: {
angleDiffThreshold?: number;
},
): GestureFragment | null | false => {
Iif (!MH.isIterableObject(events)) {
events = [events];
}
let isCancelled = false;
const supports = getBrowserSupport();
// If the browser supports pointer events, then only take those; otherwise
// take the mouse events
const pointerEventClass = supports._pointer ? PointerEvent : MouseEvent;
const pointerUpType = supports._pointer ? MC.S_POINTERUP : MC.S_MOUSEUP;
const filteredEvents: MouseEvent[] = MH.filter(
events,
(event): event is MouseEvent => {
const eType = event.type;
isCancelled = isCancelled || eType === MC.S_POINTERCANCEL;
if (eType !== MC.S_CLICK && MH.isInstanceOf(event, pointerEventClass)) {
// Only events where the primary button is pressed (unless it's a
// pointerup event, in which case no buttons should be pressed) are
// considered, otherwise consider it terminated
isCancelled =
isCancelled ||
(eType === pointerUpType && event.buttons !== 0) ||
(eType !== pointerUpType && event.buttons !== 1);
// we don't handle touch pointer events
return !MH.isTouchPointerEvent(event);
}
return false;
},
);
const numEvents = MH.lengthOf(filteredEvents);
if (numEvents < 2) {
return false; // no enough events
}
if (isCancelled) {
return null; // terminated
}
const firstEvent = filteredEvents[0];
const lastEvent = filteredEvents[numEvents - 1];
if (MH.getPointerType(firstEvent) !== MH.getPointerType(lastEvent)) {
return null; // different devices, consider it terminated
}
const deltaX = lastEvent.clientX - firstEvent.clientX;
const deltaY = lastEvent.clientY - firstEvent.clientY;
const direction = getVectorDirection(
[deltaX, deltaY],
options?.angleDiffThreshold,
);
return direction === MC.S_NONE
? false
: {
device: MC.S_POINTER,
direction,
intent: MC.S_DRAG,
deltaX,
deltaY,
deltaZ: 1,
};
};
|