46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
import type { PointerEvent as ReactPointerEvent } from 'react';
|
|
|
|
type PointerLikeEvent = MouseEvent & { pageX?: number; pageY?: number };
|
|
type PreventableEvent = Event | ReactPointerEvent | { preventDefault?: () => void; stopPropagation?: () => void };
|
|
|
|
export const preventAll = (event?: PreventableEvent | null): void => {
|
|
if (!event) {
|
|
return;
|
|
}
|
|
try {
|
|
event.preventDefault();
|
|
} catch (error) {
|
|
console.warn('[events] preventDefault failed', error);
|
|
}
|
|
try {
|
|
event.stopPropagation();
|
|
} catch (error) {
|
|
console.warn('[events] stopPropagation failed', error);
|
|
}
|
|
};
|
|
|
|
type AnyFn = (...args: unknown[]) => unknown;
|
|
|
|
export const safeInvoke = <Fn extends AnyFn>(
|
|
fn: Fn | null,
|
|
...args: Parameters<Fn>
|
|
): ReturnType<Fn> | undefined =>
|
|
(fn ? (fn(...args) as ReturnType<Fn>) : undefined);
|
|
|
|
export const getPointerPosition = (
|
|
event?: PointerLikeEvent | null,
|
|
{ fallbackToPage = true }: { fallbackToPage?: boolean } = {},
|
|
): { x: number; y: number } => {
|
|
if (!event) {
|
|
return { x: 0, y: 0 };
|
|
}
|
|
const clientX = Number.isFinite(event.clientX) ? event.clientX : null;
|
|
const clientY = Number.isFinite(event.clientY) ? event.clientY : null;
|
|
const pageX = fallbackToPage && Number.isFinite(event.pageX) ? event.pageX : null;
|
|
const pageY = fallbackToPage && Number.isFinite(event.pageY) ? event.pageY : null;
|
|
return {
|
|
x: clientX ?? pageX ?? 0,
|
|
y: clientY ?? pageY ?? 0,
|
|
};
|
|
};
|