@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
TypeScript
/**
* 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 {};