-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathgesture_handler.js
More file actions
58 lines (52 loc) · 1.89 KB
/
Copy pathgesture_handler.js
File metadata and controls
58 lines (52 loc) · 1.89 KB
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
// Detects tap/hold/double-tap gestures from pointer events and dispatches the resolved gesture
// via the given callback. HA's own internal <action-handler> element isn't exposed for
// third-party use, so this reimplements that detection directly.
//
// Kept framework-free (no DOM/Lit dependency) so gesture timing can be unit tested with fake
// timers, independent of rendering.
export const HOLD_TIME_MS = 500;
export const DOUBLE_TAP_WINDOW_MS = 250;
// dispatch(hold, dblClick) is called once per resolved gesture. hasHold/hasDoubleTap should be
// true only when the corresponding action is actually configured - like HA's native rows, a
// long-press without a hold_action resolves as a plain tap, and without a double_tap_action a
// tap dispatches immediately instead of waiting out the double-tap window for a second tap that
// will never come.
export const createGestureHandlers = (dispatch, { hasHold, hasDoubleTap }) => {
let holdTimer;
let held = false;
let pendingTapTimer;
const onDown = () => {
held = false;
if (hasHold) {
holdTimer = setTimeout(() => {
held = true;
}, HOLD_TIME_MS);
}
};
const onCancel = () => {
clearTimeout(holdTimer);
};
const onUp = () => {
clearTimeout(holdTimer);
if (held) {
held = false;
dispatch(true, false);
return;
}
if (!hasDoubleTap) {
dispatch(false, false);
return;
}
if (pendingTapTimer) {
clearTimeout(pendingTapTimer);
pendingTapTimer = undefined;
dispatch(false, true);
} else {
pendingTapTimer = setTimeout(() => {
pendingTapTimer = undefined;
dispatch(false, false);
}, DOUBLE_TAP_WINDOW_MS);
}
};
return { onDown, onUp, onCancel };
};