-
-
Notifications
You must be signed in to change notification settings - Fork 112
/
gestureRecognizerConfiguration.ts
117 lines (101 loc) · 5.15 KB
/
gestureRecognizerConfiguration.ts
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
107
108
109
110
111
112
113
114
115
116
117
// Note: we may add properties in the future that aren't explicitly readonly;
// it's just that the ELEMENTS and zone definitions involved shouldn't be shifting
// after configuration.
import { InputSample } from "../headless/inputSample.js";
import { Mutable } from "../mutable.js";
import { Nonoptional } from "../nonoptional.js";
import { PaddedZoneSource } from "./paddedZoneSource.js";
import { RecognitionZoneSource } from "./recognitionZoneSource.js";
// For example, customization of a longpress timer's length need not be readonly.
export interface GestureRecognizerConfiguration<HoveredItemType> {
/**
* Specifies the element that mouse input listeners should be attached to. If
* not specified, `eventRoot` will be set equal to `targetRoot`.
*/
readonly mouseEventRoot?: HTMLElement;
/**
* Specifies the element that touch input listeners should be attached to. If
* not specified, `eventRoot` will be set equal to `targetRoot`.
*/
readonly touchEventRoot?: HTMLElement;
/**
* Specifies the most specific common ancestor element of any event target
* that the `InputEventEngine` should consider.
*/
readonly targetRoot: HTMLElement;
/**
* A boundary constraining the legal coordinates for supported touchstart and mousedown
* events. If not specified, this will be set to `targetRoot`.
*/
readonly inputStartBounds?: RecognitionZoneSource;
/**
* A boundary constraining the maximum range that an ongoing input may travel before it
* is forceably canceled. If not specified, this will be set to `targetRoot`.
*/
readonly maxRoamingBounds?: RecognitionZoneSource;
/**
* A boundary constraining the "safe range" for ongoing touch events. Events that leave a
* safe boundary that did not start outside its respective "padded" bound will be canceled.
*
* If not specified, this will be based on the active viewport, padded internally by 2px on
* all sides.
*/
readonly safeBounds?: RecognitionZoneSource;
/**
* Used to define a "boundary" slightly more constrained than `safeBounds`. Events that
* start within this pixel range from a safe bound will disable that bound for the duration
* of its corresponding input sequence. May be a number or an array of 1, 2, or 4 numbers,
* as with CSS styling.
*
* If not specified, this will default to a padding of 3px inside the standard safeBounds
* unless `paddedSafeBounds` is defined.
*
* If `paddedSafeBounds` was specified initially, this will be set to `undefined`.
*/
readonly safeBoundPadding?: number | number[];
/**
* Used to define when an input coordinate is "close" to `safeBounds` borders via exclusion.
* If this is not defined while `safeBoundPadding` is, this will be built automatically to
* match the spec set by `safeBoundPadding`.
*
* Defining this directly will cause `safeBoundPadding` to be ignored in favor of the bounds
* set here.
*/
readonly paddedSafeBounds?: RecognitionZoneSource;
/**
* Allows the gesture-recognizer client to specify the most relevant, identifying UI "item"
* (as perceived by users / relevant for gesture discrimination) underneath the touchpoint's
* current location based when processing input events.
*
* For applications in the DOM, simply returning `target` itself may be sufficient.
* @param coord The current touchpath coordinate; its .targetX and .targetY values should be
* interpreted as offsets from `targetRoot`.
* @param target The `EventTarget` (`Node` or `Element`) provided by the corresponding input event.
* @returns
*/
readonly itemIdentifier?: (coord: Omit<InputSample<any>, 'item'>, target: EventTarget) => HoveredItemType;
}
export function preprocessRecognizerConfig<HoveredItemType>(
config: GestureRecognizerConfiguration<HoveredItemType>
): Nonoptional<GestureRecognizerConfiguration<HoveredItemType>> {
// Allows configuration pre-processing during this method.
let processingConfig: Mutable<Nonoptional<GestureRecognizerConfiguration<HoveredItemType>>> = {...config} as Nonoptional<GestureRecognizerConfiguration<HoveredItemType>>;
processingConfig.mouseEventRoot = processingConfig.mouseEventRoot ?? processingConfig.targetRoot;
processingConfig.touchEventRoot = processingConfig.touchEventRoot ?? processingConfig.targetRoot;
processingConfig.inputStartBounds = processingConfig.inputStartBounds ?? processingConfig.targetRoot;
processingConfig.maxRoamingBounds = processingConfig.maxRoamingBounds ?? processingConfig.targetRoot;
processingConfig.safeBounds = processingConfig.safeBounds ?? new PaddedZoneSource([2]);
processingConfig.itemIdentifier = processingConfig.itemIdentifier ?? (() => null);
if(!config.paddedSafeBounds) {
let paddingArray = config.safeBoundPadding;
if(typeof paddingArray == 'number') {
paddingArray = [ paddingArray ];
}
paddingArray = paddingArray ?? [3];
processingConfig.paddedSafeBounds = new PaddedZoneSource(processingConfig.safeBounds, paddingArray);
} else {
// processingConfig.paddedSafeBounds is already set via the spread operator above.
delete processingConfig.safeBoundPadding;
}
return processingConfig;
}