-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.ts
95 lines (80 loc) · 2.77 KB
/
utils.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
// Copyright © 2023 Tomoki Miyauchi. All rights reserved. MIT license.
// This module is browser compatible.
import { compositeKey, isBoolean, isFunction, isObject } from "./deps.ts";
import type {
ComparableEventListenerLike,
EventListenerLike,
} from "./types.ts";
/** To flatten {@linkcode options}.
* @see https://dom.spec.whatwg.org/#concept-flatten-options
*/
export function flatOptions(options?: boolean | EventListenerOptions): boolean {
if (isBoolean(options)) return options;
return Boolean(options?.capture);
}
export type NormalizedOptions = Pick<
EventListenerLike,
keyof AddEventListenerOptions
>;
/** To flatten {@linkcode options} more.
* @see https://dom.spec.whatwg.org/#event-flatten-more
*/
export function flatOptionsMore(
options?: boolean | AddEventListenerOptions,
): NormalizedOptions {
const capture = flatOptions(options);
const { once = false, passive = null, signal = null } = isObject(options)
? options
: {};
return { capture, once, passive, signal };
}
/** Return default passive value.
* @see https://dom.spec.whatwg.org/#default-passive-value
*/
export function defaultPassiveValue(
type: string,
target: EventTarget,
): boolean {
if (!touchOrUiEvents.has(type)) return false;
if (isWindow(target)) return true;
if (!isNodeLike(target)) return false;
// target is Document
if (!target.ownerDocument) {
return target === Reflect.get(globalThis, "document");
}
return ("documentElement" in target.ownerDocument &&
target.ownerDocument.documentElement === target || // target is HTML document
"body" in target.ownerDocument &&
target.ownerDocument.body === target); // target is body
}
const touchOrUiEvents = /*@__PURE__*/ new Set<string>([
"touchstart",
"touchmove",
"wheel",
"mousewheel",
]);
interface NodeLike {
readonly ownerDocument: object | null;
}
/** Whether the {@linkcode input} is {@linkcode NodeLike} or not. */
export function isNodeLike(input: object): input is NodeLike {
return "ownerDocument" in input && typeof input.ownerDocument === "object";
}
/** Whether the {@linkcode input} is {@linkcode Window} or not.
* This works universally.
*/
export function isWindow(input: unknown): input is Window {
return globalThis.Window && input instanceof globalThis.Window;
}
/** {@linkcode listener} to Function.
* if {@linkcode listener} is function, return it; otherwise return bound `handleEvent`.
*/
export function toHandler(
listener: EventListenerOrEventListenerObject,
): EventListener {
return isFunction(listener) ? listener : listener.handleEvent.bind(listener);
}
/** Return {@linkcode listener} representation key. */
export function toKey(listener: ComparableEventListenerLike): object {
return compositeKey(listener.callback, listener.type, listener.capture);
}