UNPKG

@mui/x-internal-gestures

Version:

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

237 lines (218 loc) 7.79 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.TurnWheelGesture = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _Gesture = require("../Gesture"); var _utils = require("../utils"); /** * TurnWheelGesture - Detects wheel events on an element * * This gesture tracks mouse wheel or touchpad scroll events on elements, firing events when: * - The user scrolls/wheels on the element (ongoing) * * Unlike other gestures which may have start/ongoing/end states, * wheel gestures are always considered "ongoing" since they are discrete events. */ /** * Configuration options for the TurnWheelGesture * Uses the base gesture options with additional wheel-specific options */ /** * Event data specific to wheel gesture events * Contains information about scroll delta amounts and mode */ /** * Type definition for the CustomEvent created by TurnWheelGesture */ /** * State tracking for the TurnWheelGesture */ /** * TurnWheelGesture class for handling wheel/scroll interactions * * This gesture detects when users scroll or use the mouse wheel on elements, * and dispatches corresponding scroll events with delta information. * Unlike most gestures, it extends directly from Gesture rather than PointerGesture. */ class TurnWheelGesture extends _Gesture.Gesture { constructor(options) { super(options); this.state = { totalDeltaX: 0, totalDeltaY: 0, totalDeltaZ: 0 }; this.isSinglePhase = void 0; this.eventType = void 0; this.optionsType = void 0; this.mutableOptionsType = void 0; this.mutableStateType = void 0; /** * Scaling factor for delta values * Values > 1 increase sensitivity, values < 1 decrease sensitivity */ this.sensitivity = void 0; /** * Maximum value for totalDelta values * Limits how large the accumulated wheel deltas can be */ this.max = void 0; /** * Minimum value for totalDelta values * Sets a lower bound for accumulated wheel deltas */ this.min = void 0; /** * Initial value for totalDelta values * Sets the starting value for delta trackers */ this.initialDelta = void 0; /** * Whether to invert the direction of delta changes * When true, reverses the sign of deltaX, deltaY, and deltaZ values */ this.invert = void 0; // Store bound event handlers to properly remove them this.handleWheelEventBound = void 0; this.sensitivity = options.sensitivity ?? 1; this.max = options.max ?? Number.MAX_SAFE_INTEGER; this.min = options.min ?? Number.MIN_SAFE_INTEGER; this.initialDelta = options.initialDelta ?? 0; this.invert = options.invert ?? false; this.state.totalDeltaX = this.initialDelta; this.state.totalDeltaY = this.initialDelta; this.state.totalDeltaZ = this.initialDelta; this.handleWheelEventBound = this.handleWheelEvent.bind(this); } clone(overrides) { return new TurnWheelGesture((0, _extends2.default)({ name: this.name, preventDefault: this.preventDefault, stopPropagation: this.stopPropagation, sensitivity: this.sensitivity, max: this.max, min: this.min, initialDelta: this.initialDelta, invert: this.invert, requiredKeys: [...this.requiredKeys], pointerMode: [...this.pointerMode], preventIf: [...this.preventIf] }, overrides)); } init(element, pointerManager, gestureRegistry, keyboardManager) { super.init(element, pointerManager, gestureRegistry, keyboardManager); // Add event listener directly to the element // @ts-expect-error, WheelEvent is correct. this.element.addEventListener('wheel', this.handleWheelEventBound); } destroy() { // Remove the element-specific event listener // @ts-expect-error, WheelEvent is correct. this.element.removeEventListener('wheel', this.handleWheelEventBound); this.resetState(); super.destroy(); } resetState() { this.isActive = false; this.state = { totalDeltaX: 0, totalDeltaY: 0, totalDeltaZ: 0 }; } updateOptions(options) { super.updateOptions(options); this.sensitivity = options.sensitivity ?? this.sensitivity; this.max = options.max ?? this.max; this.min = options.min ?? this.min; this.initialDelta = options.initialDelta ?? this.initialDelta; this.invert = options.invert ?? this.invert; } /** * Handle wheel events for a specific element * @param element The element that received the wheel event * @param event The original wheel event */ handleWheelEvent(event) { // Check if this gesture should be prevented by active gestures if (this.shouldPreventGesture(this.element)) { return; } // Get pointers from the PointerManager to use for centroid calculation const pointers = this.pointerManager.getPointers() || new Map(); const pointersArray = Array.from(pointers.values()); // Update total deltas with scaled values this.state.totalDeltaX += event.deltaX * this.sensitivity * (this.invert ? -1 : 1); this.state.totalDeltaY += event.deltaY * this.sensitivity * (this.invert ? -1 : 1); this.state.totalDeltaZ += event.deltaZ * this.sensitivity * (this.invert ? -1 : 1); // Apply proper min/max clamping for each axis // Ensure values stay between min and max bounds ['totalDeltaX', 'totalDeltaY', 'totalDeltaZ'].forEach(axis => { // First clamp at the minimum bound if (this.state[axis] < this.min) { this.state[axis] = this.min; } // Then clamp at the maximum bound if (this.state[axis] > this.max) { this.state[axis] = this.max; } }); // Emit the wheel event this.emitWheelEvent(pointersArray, event); } /** * Emit wheel-specific events * @param pointers The current pointers on the element * @param event The original wheel event */ emitWheelEvent(pointers, event) { // Calculate centroid - either from existing pointers or from the wheel event position const centroid = pointers.length > 0 ? (0, _utils.calculateCentroid)(pointers) : { x: event.clientX, y: event.clientY }; // Get list of active gestures const activeGestures = this.gesturesRegistry.getActiveGestures(this.element); // Create custom event data const customEventData = { gestureName: this.name, centroid, target: event.target, srcEvent: event, phase: 'ongoing', // Wheel events are always in "ongoing" state pointers, timeStamp: event.timeStamp, deltaX: event.deltaX * this.sensitivity * (this.invert ? -1 : 1), deltaY: event.deltaY * this.sensitivity * (this.invert ? -1 : 1), deltaZ: event.deltaZ * this.sensitivity * (this.invert ? -1 : 1), deltaMode: event.deltaMode, totalDeltaX: this.state.totalDeltaX, totalDeltaY: this.state.totalDeltaY, totalDeltaZ: this.state.totalDeltaZ, activeGestures, customData: this.customData }; // Apply default event behavior if configured if (this.preventDefault) { event.preventDefault(); } if (this.stopPropagation) { event.stopPropagation(); } // Event names to trigger const eventName = (0, _utils.createEventName)(this.name, 'ongoing'); // Dispatch custom events on the element const domEvent = new CustomEvent(eventName, { bubbles: true, cancelable: true, composed: true, detail: customEventData }); this.element.dispatchEvent(domEvent); } } exports.TurnWheelGesture = TurnWheelGesture;