UNPKG

@mui/x-internal-gestures

Version:

The core engine of GestureEvents, a modern and robust multi-pointer gesture detection library for JavaScript.

291 lines 11.1 kB
/** * Base Gesture module that provides common functionality for all gesture implementations */ import { ActiveGesturesRegistry } from "./ActiveGesturesRegistry.js"; import { KeyboardKey, KeyboardManager } from "./KeyboardManager.js"; import { PointerData, PointerManager } from "./PointerManager.js"; import { TargetElement } from "./types/TargetElement.js"; /** * The possible phases of a gesture during its lifecycle. * * - 'start': The gesture has been recognized and is beginning * - 'ongoing': The gesture is in progress (e.g., a finger is moving) * - 'end': The gesture has completed successfully * - 'cancel': The gesture was interrupted or terminated abnormally */ export type GesturePhase = 'start' | 'ongoing' | 'end' | 'cancel'; /** * Core data structure passed to gesture event handlers. * Contains all relevant information about a gesture event. */ export type GestureEventData<CustomData extends Record<string, unknown> = Record<string, unknown>> = { /** The name of the gesture */ gestureName: string; /** The centroid of all active pointers involved in the gesture */ centroid: { x: number; y: number; }; /** The target element of the original event */ target: EventTarget | null; /** The original event that triggered this gesture */ srcEvent: Event; /** The current phase of the gesture */ phase: GesturePhase; /** Array of all active pointers involved in the gesture */ pointers: PointerData[]; /** The time at which the gesture event occurred */ timeStamp: number; /** List of all currently active gestures */ activeGestures: Record<string, boolean>; /** User-mutable data object for sharing state between gesture events */ customData: CustomData; }; /** * Defines the types of pointers that can trigger a gesture. */ export type PointerMode = 'mouse' | 'touch' | 'pen'; /** * Base configuration options that can be overridden per pointer mode. */ export type BaseGestureOptions = { /** * Array of keyboard keys that must be pressed for the gesture to be recognized. * If not provided or empty, no keyboard key requirement is applied. * * A special identifier `ControlOrMeta` can be used to match either Control or Meta keys, * which is useful for cross-platform compatibility. * * @example ['Shift', 'Alt'] * @default [] (no key requirement) */ requiredKeys?: KeyboardKey[]; }; /** * Configuration options for creating a gesture instance. */ export type GestureOptions<GestureName extends string, FineGrainedGestureOptions extends BaseGestureOptions = BaseGestureOptions> = { /** Unique name identifying this gesture type */ name: GestureName; /** Whether to prevent default browser action for gesture events */ preventDefault?: boolean; /** Whether to stop propagation of gesture events */ stopPropagation?: boolean; /** * List of gesture names that should prevent this gesture from activating when they are active. * If any of these gestures are active, this gesture will not be recognized. * * This only works when the gestures in the array have phases. Because `TurnWheel` and `Tap` * gestures are single-phase, they will not be able to prevent other gestures. * * Phased events are those that have multiple phases, usually denoted by `<event>Start` * and `<event>End`, like `pan` and `pinch` events. * * @example ['pan', 'pinch'] * @default [] (no prevented gestures) */ preventIf?: string[]; /** * List of pointer types that can trigger this gesture. * If provided, only the specified pointer types will be able to activate the gesture. * * @example ['mouse', 'touch'] * @default [] (all pointer types allowed) */ pointerMode?: PointerMode[]; } & FineGrainedGestureOptions & { /** * Pointer mode-specific configuration overrides. * Options defined here will override any option defined in the base root options. * * @example * ```typescript * { * pointerOptions: { * mouse: { requiredKeys: ['ControlOrMeta'] }, * touch: { requiredKeys: [] }, * }, * } * ``` */ pointerOptions?: Partial<Record<PointerMode, FineGrainedGestureOptions>>; }; declare const _privateKey: unique symbol; /** * Type for the state of a gesture recognizer. */ export type GestureState = { [_privateKey]?: undefined; }; /** * Base abstract class for all gestures. This class provides the fundamental structure * and functionality for handling gestures, including registering and unregistering * gesture handlers, creating emitters, and managing gesture state. * * Gesture is designed as an extensible base for implementing specific gesture recognizers. * Concrete gesture implementations should extend this class or one of its subclasses. * * To implement: * - Non-pointer gestures (like wheel events): extend this Gesture class directly * - Pointer-based gestures: extend the PointerGesture class instead * * @example * ```ts * import { Gesture } from './Gesture'; * * class CustomGesture extends Gesture { * constructor(options) { * super(options); * } * * clone(overrides) { * return new CustomGesture({ * name: this.name, * // ... other options * ...overrides, * }); * } * } * ``` */ export declare abstract class Gesture<GestureName extends string> { /** Unique name identifying this gesture type */ readonly name: GestureName; /** Whether to prevent default browser action for gesture events */ protected preventDefault: boolean; /** Whether to stop propagation of gesture events */ protected stopPropagation: boolean; /** * List of gesture names that should prevent this gesture from activating when they are active. */ protected preventIf: string[]; /** * Array of keyboard keys that must be pressed for the gesture to be recognized. */ protected requiredKeys: KeyboardKey[]; /** * KeyboardManager instance for tracking key presses */ protected keyboardManager: KeyboardManager; /** * List of pointer types that can trigger this gesture. * If undefined, all pointer types are allowed. */ protected pointerMode: PointerMode[]; /** * Pointer mode-specific configuration overrides. */ protected pointerOptions: Partial<Record<PointerMode, BaseGestureOptions>>; /** * User-mutable data object for sharing state between gesture events * This object is included in all events emitted by this gesture */ protected customData: Record<string, unknown>; /** Reference to the singleton PointerManager instance */ protected pointerManager: PointerManager; /** Reference to the singleton ActiveGesturesRegistry instance */ protected gesturesRegistry: ActiveGesturesRegistry<GestureName>; /** The DOM element this gesture is attached to */ protected element: TargetElement; /** Stores the active gesture state */ protected abstract state: GestureState; /** @internal For types. If false enables phases (xStart, x, xEnd) */ protected abstract readonly isSinglePhase: boolean; /** @internal For types. The event type this gesture is associated with */ protected abstract readonly eventType: CustomEvent; /** @internal For types. The options type for this gesture */ protected abstract readonly optionsType: GestureOptions<GestureName>; /** @internal For types. The options that can be changed at runtime */ protected abstract readonly mutableOptionsType: Omit<typeof this.optionsType, 'name'>; /** @internal For types. The state that can be changed at runtime */ protected abstract readonly mutableStateType: Partial<typeof this.state>; /** * Create a new gesture instance with the specified options * * @param options - Configuration options for this gesture */ constructor(options: GestureOptions<GestureName>); /** * Initialize the gesture by acquiring the pointer manager and gestures registry * Must be called before the gesture can be used */ init(element: TargetElement, pointerManager: PointerManager, gestureRegistry: ActiveGesturesRegistry<GestureName>, keyboardManager: KeyboardManager): void; /** * Handle option change events * @param event Custom event with new options in the detail property */ private handleOptionsChange; /** * Update the gesture options with new values * @param options Object containing properties to update */ protected updateOptions(options: typeof this.mutableOptionsType): void; /** * Get the default configuration for the pointer specific options. * Change this function in child classes to provide different defaults. */ protected getBaseConfig(): { requiredKeys: KeyboardKey[]; }; /** * Get the effective configuration for a specific pointer mode. * This merges the base configuration with pointer mode-specific overrides. * * @param pointerType - The pointer type to get configuration for * @returns The effective configuration object */ protected getEffectiveConfig<T>(pointerType: PointerMode, baseConfig: T): T; /** * Handle state change events * @param event Custom event with new state values in the detail property */ private handleStateChange; /** * Update the gesture state with new values * @param stateChanges Object containing state properties to update */ protected updateState(stateChanges: typeof this.mutableStateType): void; /** * Create a deep clone of this gesture for a new element * * @param overrides - Optional configuration options that override the defaults * @returns A new instance of this gesture with the same configuration and any overrides applied */ abstract clone(overrides?: Record<string, unknown>): Gesture<GestureName>; /** * Check if the event's target is or is contained within any of our registered elements * * @param event - The browser event to check * @returns The matching element or null if no match is found */ protected getTargetElement(event: Event): TargetElement | null; /** Whether the gesture is currently active */ set isActive(isActive: boolean); /** Whether the gesture is currently active */ get isActive(): boolean; /** * Checks if this gesture should be prevented from activating. * * @param element - The DOM element to check against * @param pointerType - The type of pointer triggering the gesture * @returns true if the gesture should be prevented, false otherwise */ protected shouldPreventGesture(element: TargetElement, pointerType: string): boolean; /** * Checks if the given pointer type is allowed for this gesture based on the pointerMode setting. * * @param pointerType - The type of pointer to check. * @returns true if the pointer type is allowed, false otherwise. */ protected isPointerTypeAllowed(pointerType: string): boolean; /** * Clean up the gesture and unregister any listeners * Call this method when the gesture is no longer needed to prevent memory leaks */ destroy(): void; /** * Reset the gesture state to its initial values */ protected abstract resetState(): void; } export {};